shithub: qk1

Download patch

ref: be559d26383e23407fe568d178cef7273c411dbf
author: Travis Bradshaw <travis.bradshaw@idsoftware.com>
date: Tue Jan 31 09:32:09 EST 2012

The Quake sources as originally release under the GPL license on December 21, 1999

diff: cannot open b/QW/client//null: 'b/QW/client//null' does not exist diff: cannot open b/QW/docs//null: 'b/QW/docs//null' does not exist diff: cannot open b/QW/dxsdk/sdk/inc//null: 'b/QW/dxsdk/sdk/inc//null' does not exist diff: cannot open b/QW/dxsdk/sdk/lib//null: 'b/QW/dxsdk/sdk/lib//null' does not exist diff: cannot open b/QW/dxsdk/sdk//null: 'b/QW/dxsdk/sdk//null' does not exist diff: cannot open b/QW/dxsdk//null: 'b/QW/dxsdk//null' does not exist diff: cannot open b/QW/gas2masm//null: 'b/QW/gas2masm//null' does not exist diff: cannot open b/QW/progs//null: 'b/QW/progs//null' does not exist diff: cannot open b/QW/qwfwd//null: 'b/QW/qwfwd//null' does not exist diff: cannot open b/QW/scitech/include//null: 'b/QW/scitech/include//null' does not exist diff: cannot open b/QW/scitech/lib/win32/vc//null: 'b/QW/scitech/lib/win32/vc//null' does not exist diff: cannot open b/QW/scitech/lib/win32//null: 'b/QW/scitech/lib/win32//null' does not exist diff: cannot open b/QW/scitech/lib//null: 'b/QW/scitech/lib//null' does not exist diff: cannot open b/QW/scitech//null: 'b/QW/scitech//null' does not exist diff: cannot open b/QW/server//null: 'b/QW/server//null' does not exist diff: cannot open b/QW//null: 'b/QW//null' does not exist diff: cannot open b/WinQuake/data//null: 'b/WinQuake/data//null' does not exist diff: cannot open b/WinQuake/docs//null: 'b/WinQuake/docs//null' does not exist diff: cannot open b/WinQuake/dxsdk/SDK/INC//null: 'b/WinQuake/dxsdk/SDK/INC//null' does not exist diff: cannot open b/WinQuake/dxsdk/SDK/LIB//null: 'b/WinQuake/dxsdk/SDK/LIB//null' does not exist diff: cannot open b/WinQuake/dxsdk/SDK//null: 'b/WinQuake/dxsdk/SDK//null' does not exist diff: cannot open b/WinQuake/dxsdk//null: 'b/WinQuake/dxsdk//null' does not exist diff: cannot open b/WinQuake/gas2masm//null: 'b/WinQuake/gas2masm//null' does not exist diff: cannot open b/WinQuake/kit//null: 'b/WinQuake/kit//null' does not exist diff: cannot open b/WinQuake//null: 'b/WinQuake//null' does not exist
--- /dev/null
+++ b/QW/Makefile.Linux
@@ -1,0 +1,930 @@
+#
+# QuakeWorld Makefile for Linux 2.0
+#
+# Apr '98 by Zoid <zoid@idsoftware.com>
+#
+# GNU Make required
+#
+# ELF only
+#
+
+# RPM release number
+RPM_RELEASE=1
+
+VERSION=2.30$(GLIBC)
+
+ifneq (,$(findstring libc6,$(shell if [ -e /lib/libc.so.6* ];then echo libc6;fi)))
+GLIBC=-glibc
+else
+GLIBC=
+endif
+
+ifneq (,$(findstring alpha,$(shell uname -m)))
+ARCH=axp
+RPMARCH=alpha
+else
+ARCH=i386
+RPMARCH=i386
+endif
+
+MAINDIR=/grog/Projects/QW
+
+BUILD_DEBUG_DIR=debug$(ARCH)$(GLIBC)
+BUILD_RELEASE_DIR=release$(ARCH)$(GLIBC)
+CLIENT_DIR=$(MAINDIR)/client
+SERVER_DIR=$(MAINDIR)/server
+
+MESA_DIR=/usr/local/src/Mesa-3.0
+
+CC=gcc
+BASE_CFLAGS=-Wall -Dstricmp=strcasecmp -I$(CLIENT_DIR) -I$(SERVER_DIR)
+DEBUG_CFLAGS=$(BASE_CFLAGS) -g
+ifeq ($(ARCH),axp)
+RELEASE_CFLAGS=$(BASE_CFLAGS) -ffast-math -funroll-loops \
+	-fomit-frame-pointer -fexpensive-optimizations
+else
+RELEASE_CFLAGS=$(BASE_CFLAGS) -m486 -O6 -ffast-math -funroll-loops \
+	-fomit-frame-pointer -fexpensive-optimizations -malign-loops=2 \
+	-malign-jumps=2 -malign-functions=2
+endif
+GLCFLAGS=-DGLQUAKE -I/usr/local/src/Mesa-3.0/include -I/usr/include/glide
+
+LDFLAGS=-lm
+SVGALDFLAGS=-lvga
+XLDFLAGS=-L/usr/X11R6/lib -lX11 -lXext
+GL_SVGA_LDFLAGS=-L/usr/X11/lib -L/usr/local/src/Mesa-3.0/lib -lm -lMesaGL -lglide2x -lX11 -lXext -lvga
+GL_X11_LDFLAGS=-L/usr/X11/lib -L/usr/local/src/Mesa-3.0/lib -lm -lGL -lX11 -lXext
+
+DO_CC=$(CC) $(CFLAGS) -o $@ -c $<
+DO_O_CC=$(CC) -O $(CFLAGS) -o $@ -c $<
+DO_GL_CC=$(CC) $(CFLAGS) $(GLCFLAGS) -o $@ -c $<
+DO_SERVER_CC=$(CC) -DSERVERONLY $(CFLAGS) -o $@ -c $<
+
+DO_AS=$(CC) $(CFLAGS) -DELF -x assembler-with-cpp -o $@ -c $<
+DO_GL_AS=$(CC) $(CFLAGS) $(GLCFLAGS) -DELF -x assembler-with-cpp -o $@ -c $<
+
+#############################################################################
+# SETUP AND BUILD
+#############################################################################
+
+ifeq ($(ARCH),axp)
+TARGETS=$(BUILDDIR)/qwsv 
+#$(BUILDDIR)/qwcl.x11
+else
+TARGETS=$(BUILDDIR)/qwsv $(BUILDDIR)/qwcl $(BUILDDIR)/qwcl.x11 $(BUILDDIR)/glqwcl $(BUILDDIR)/glqwcl.glx
+endif
+
+build_debug:
+	@-mkdir $(BUILD_DEBUG_DIR) \
+		$(BUILD_DEBUG_DIR)/client \
+		$(BUILD_DEBUG_DIR)/glclient \
+		$(BUILD_DEBUG_DIR)/server 
+	$(MAKE) targets BUILDDIR=$(BUILD_DEBUG_DIR) CFLAGS="$(DEBUG_CFLAGS)"
+
+build_release:
+	@-mkdir $(BUILD_RELEASE_DIR) \
+		$(BUILD_RELEASE_DIR)/client \
+		$(BUILD_RELEASE_DIR)/glclient \
+		$(BUILD_RELEASE_DIR)/server
+	$(MAKE) targets BUILDDIR=$(BUILD_RELEASE_DIR) CFLAGS="$(RELEASE_CFLAGS)"
+
+all: build_debug build_release
+
+targets: $(TARGETS)
+
+#############################################################################
+# SERVER
+#############################################################################
+
+QWSV_OBJS = \
+	 $(BUILDDIR)/server/pr_cmds.o \
+	 $(BUILDDIR)/server/pr_edict.o \
+	 $(BUILDDIR)/server/pr_exec.o \
+	 $(BUILDDIR)/server/sv_init.o \
+	 $(BUILDDIR)/server/sv_main.o \
+	 $(BUILDDIR)/server/sv_nchan.o \
+	 $(BUILDDIR)/server/sv_ents.o \
+	 $(BUILDDIR)/server/sv_send.o \
+	 $(BUILDDIR)/server/sv_move.o \
+	 $(BUILDDIR)/server/sv_phys.o \
+	 $(BUILDDIR)/server/sv_user.o \
+	 $(BUILDDIR)/server/sv_ccmds.o \
+	 $(BUILDDIR)/server/world.o \
+	 $(BUILDDIR)/server/sys_unix.o \
+	 $(BUILDDIR)/server/model.o \
+	 $(BUILDDIR)/server/cmd.o \
+	 $(BUILDDIR)/server/common.o \
+	 $(BUILDDIR)/server/crc.o \
+	 $(BUILDDIR)/server/cvar.o \
+	 $(BUILDDIR)/server/mathlib.o \
+	 $(BUILDDIR)/server/md4.o \
+	 $(BUILDDIR)/server/zone.o \
+	 $(BUILDDIR)/server/pmove.o \
+	 $(BUILDDIR)/server/pmovetst.o \
+	 $(BUILDDIR)/server/net_chan.o \
+	 $(BUILDDIR)/server/net_udp.o 
+
+$(BUILDDIR)/qwsv : $(QWSV_OBJS)
+	$(CC) $(CFLAGS) -o $@ $(QWSV_OBJS) $(LDFLAGS)
+
+$(BUILDDIR)/server/pr_cmds.o :   $(SERVER_DIR)/pr_cmds.c 
+	$(DO_SERVER_CC)
+
+$(BUILDDIR)/server/pr_edict.o :  $(SERVER_DIR)/pr_edict.c
+	$(DO_SERVER_CC)
+
+$(BUILDDIR)/server/pr_exec.o :   $(SERVER_DIR)/pr_exec.c
+	$(DO_SERVER_CC)
+
+$(BUILDDIR)/server/sv_init.o :   $(SERVER_DIR)/sv_init.c
+	$(DO_SERVER_CC)
+
+$(BUILDDIR)/server/sv_main.o :   $(SERVER_DIR)/sv_main.c
+	$(DO_SERVER_CC)
+
+$(BUILDDIR)/server/sv_nchan.o :  $(SERVER_DIR)/sv_nchan.c
+	$(DO_SERVER_CC)
+
+$(BUILDDIR)/server/sv_ents.o :   $(SERVER_DIR)/sv_ents.c
+	$(DO_SERVER_CC)
+
+$(BUILDDIR)/server/sv_send.o :   $(SERVER_DIR)/sv_send.c
+	$(DO_SERVER_CC)
+
+$(BUILDDIR)/server/sv_move.o :   $(SERVER_DIR)/sv_move.c
+	$(DO_SERVER_CC)
+
+$(BUILDDIR)/server/sv_phys.o :   $(SERVER_DIR)/sv_phys.c
+	$(DO_SERVER_CC)
+
+$(BUILDDIR)/server/sv_user.o :   $(SERVER_DIR)/sv_user.c
+	$(DO_SERVER_CC)
+
+$(BUILDDIR)/server/sv_ccmds.o :  $(SERVER_DIR)/sv_ccmds.c
+	$(DO_SERVER_CC)
+
+$(BUILDDIR)/server/world.o :     $(SERVER_DIR)/world.c
+	$(DO_SERVER_CC)
+
+$(BUILDDIR)/server/sys_unix.o :  $(SERVER_DIR)/sys_unix.c
+	$(DO_SERVER_CC)
+
+$(BUILDDIR)/server/model.o :     $(SERVER_DIR)/model.c
+	$(DO_SERVER_CC)
+
+$(BUILDDIR)/server/cmd.o :       $(CLIENT_DIR)/cmd.c
+	$(DO_SERVER_CC)
+
+$(BUILDDIR)/server/common.o :    $(CLIENT_DIR)/common.c
+	$(DO_SERVER_CC)
+
+$(BUILDDIR)/server/crc.o :       $(CLIENT_DIR)/crc.c
+	$(DO_SERVER_CC)
+
+$(BUILDDIR)/server/cvar.o :      $(CLIENT_DIR)/cvar.c
+	$(DO_SERVER_CC)
+
+$(BUILDDIR)/server/mathlib.o :   $(CLIENT_DIR)/mathlib.c
+	$(DO_SERVER_CC)
+
+$(BUILDDIR)/server/md4.o :       $(CLIENT_DIR)/md4.c
+	$(DO_SERVER_CC)
+
+$(BUILDDIR)/server/zone.o :      $(CLIENT_DIR)/zone.c
+	$(DO_SERVER_CC)
+
+$(BUILDDIR)/server/pmove.o :     $(CLIENT_DIR)/pmove.c
+	$(DO_SERVER_CC)
+
+$(BUILDDIR)/server/pmovetst.o :  $(CLIENT_DIR)/pmovetst.c
+	$(DO_SERVER_CC)
+
+$(BUILDDIR)/server/net_chan.o :  $(CLIENT_DIR)/net_chan.c
+	$(DO_SERVER_CC)
+
+$(BUILDDIR)/server/net_udp.o :   $(CLIENT_DIR)/net_udp.c
+	$(DO_SERVER_CC)
+
+#############################################################################
+# CLIENT
+#############################################################################
+
+QWCL_OBJS = \
+	$(BUILDDIR)/client/cl_demo.o \
+	$(BUILDDIR)/client/cl_ents.o \
+	$(BUILDDIR)/client/cl_input.o \
+	$(BUILDDIR)/client/cl_main.o \
+	$(BUILDDIR)/client/cl_parse.o \
+	$(BUILDDIR)/client/cl_pred.o \
+	$(BUILDDIR)/client/cl_tent.o \
+	$(BUILDDIR)/client/cl_cam.o \
+	$(BUILDDIR)/client/cmd.o \
+	$(BUILDDIR)/client/common.o \
+	$(BUILDDIR)/client/console.o \
+	$(BUILDDIR)/client/crc.o \
+	$(BUILDDIR)/client/cvar.o \
+	$(BUILDDIR)/client/d_edge.o \
+	$(BUILDDIR)/client/d_fill.o \
+	$(BUILDDIR)/client/d_init.o \
+	$(BUILDDIR)/client/d_modech.o \
+	$(BUILDDIR)/client/d_part.o \
+	$(BUILDDIR)/client/d_polyse.o \
+	$(BUILDDIR)/client/d_scan.o \
+	$(BUILDDIR)/client/d_sky.o \
+	$(BUILDDIR)/client/d_sprite.o \
+	$(BUILDDIR)/client/d_surf.o \
+	$(BUILDDIR)/client/d_vars.o \
+	$(BUILDDIR)/client/d_zpoint.o \
+	$(BUILDDIR)/client/draw.o \
+	$(BUILDDIR)/client/keys.o \
+	$(BUILDDIR)/client/mathlib.o \
+	$(BUILDDIR)/client/md4.o \
+	$(BUILDDIR)/client/menu.o \
+	$(BUILDDIR)/client/model.o \
+	$(BUILDDIR)/client/net_chan.o \
+	$(BUILDDIR)/client/net_udp.o \
+	$(BUILDDIR)/client/nonintel.o \
+	$(BUILDDIR)/client/pmove.o \
+	$(BUILDDIR)/client/pmovetst.o \
+	$(BUILDDIR)/client/r_aclip.o \
+	$(BUILDDIR)/client/r_alias.o \
+	$(BUILDDIR)/client/r_bsp.o \
+	$(BUILDDIR)/client/r_draw.o \
+	$(BUILDDIR)/client/r_edge.o \
+	$(BUILDDIR)/client/r_efrag.o \
+	$(BUILDDIR)/client/r_light.o \
+	$(BUILDDIR)/client/r_main.o \
+	$(BUILDDIR)/client/r_misc.o \
+	$(BUILDDIR)/client/r_part.o \
+	$(BUILDDIR)/client/r_sky.o \
+	$(BUILDDIR)/client/r_sprite.o \
+	$(BUILDDIR)/client/r_surf.o \
+	$(BUILDDIR)/client/r_vars.o \
+	$(BUILDDIR)/client/sbar.o \
+	$(BUILDDIR)/client/screen.o \
+	$(BUILDDIR)/client/skin.o \
+	$(BUILDDIR)/client/snd_dma.o \
+	$(BUILDDIR)/client/snd_mem.o \
+	$(BUILDDIR)/client/snd_mix.o \
+	$(BUILDDIR)/client/view.o \
+	$(BUILDDIR)/client/wad.o \
+	$(BUILDDIR)/client/zone.o \
+	$(BUILDDIR)/client/cd_linux.o \
+	$(BUILDDIR)/client/sys_linux.o \
+	$(BUILDDIR)/client/snd_linux.o \
+
+ifeq ($(ARCH),i386)
+	QWCL_AS_OBJS = \
+	$(BUILDDIR)/client/d_copy.o \
+	$(BUILDDIR)/client/d_draw.o \
+	$(BUILDDIR)/client/d_draw16.o \
+	$(BUILDDIR)/client/d_parta.o \
+	$(BUILDDIR)/client/d_polysa.o \
+	$(BUILDDIR)/client/d_scana.o \
+	$(BUILDDIR)/client/d_spr8.o \
+	$(BUILDDIR)/client/d_varsa.o \
+	$(BUILDDIR)/client/math.o \
+	$(BUILDDIR)/client/r_aclipa.o \
+	$(BUILDDIR)/client/r_aliasa.o \
+	$(BUILDDIR)/client/r_drawa.o \
+	$(BUILDDIR)/client/r_edgea.o \
+	$(BUILDDIR)/client/r_varsa.o \
+	$(BUILDDIR)/client/snd_mixa.o \
+	$(BUILDDIR)/client/surf16.o \
+	$(BUILDDIR)/client/surf8.o \
+	$(BUILDDIR)/client/sys_dosa.o
+else
+	QWCL_AS_OBJS=
+endif
+
+QWCL_SVGA_OBJS = $(BUILDDIR)/client/vid_svgalib.o
+QWCL_X11_OBJS = $(BUILDDIR)/client/vid_x.o
+
+$(BUILDDIR)/qwcl : $(QWCL_OBJS) $(QWCL_AS_OBJS) $(QWCL_SVGA_OBJS)
+	$(CC) $(CFLAGS) -o $@ $(QWCL_OBJS) $(QWCL_AS_OBJS) $(QWCL_SVGA_OBJS) \
+		$(LDFLAGS) $(SVGALDFLAGS)
+
+$(BUILDDIR)/qwcl.x11 : $(QWCL_OBJS) $(QWCL_AS_OBJS) $(QWCL_X11_OBJS)
+	$(CC) $(CFLAGS) -o $@ $(QWCL_OBJS) $(QWCL_AS_OBJS) $(QWCL_X11_OBJS) \
+		$(LDFLAGS) $(XLDFLAGS)
+
+$(BUILDDIR)/client/cl_demo.o :        $(CLIENT_DIR)/cl_demo.c
+	$(DO_CC)
+                                                                      
+$(BUILDDIR)/client/cl_ents.o :        $(CLIENT_DIR)/cl_ents.c
+	$(DO_CC)
+                                                                      
+$(BUILDDIR)/client/cl_input.o :       $(CLIENT_DIR)/cl_input.c
+	$(DO_CC)
+                                                                      
+$(BUILDDIR)/client/cl_main.o :        $(CLIENT_DIR)/cl_main.c
+	$(DO_CC)
+                                                                      
+$(BUILDDIR)/client/cl_parse.o :       $(CLIENT_DIR)/cl_parse.c
+	$(DO_CC)
+                                                                      
+$(BUILDDIR)/client/cl_pred.o :        $(CLIENT_DIR)/cl_pred.c
+	$(DO_CC)
+                                                                      
+$(BUILDDIR)/client/cl_tent.o :        $(CLIENT_DIR)/cl_tent.c
+	$(DO_CC)
+                                                                      
+$(BUILDDIR)/client/cl_cam.o :         $(CLIENT_DIR)/cl_cam.c
+	$(DO_CC)
+                                                                      
+$(BUILDDIR)/client/cmd.o :            $(CLIENT_DIR)/cmd.c
+	$(DO_CC)
+                                                                      
+$(BUILDDIR)/client/common.o :         $(CLIENT_DIR)/common.c
+	$(DO_CC)
+                                                                      
+$(BUILDDIR)/client/console.o :        $(CLIENT_DIR)/console.c
+	$(DO_CC)
+                                                                      
+$(BUILDDIR)/client/crc.o :            $(CLIENT_DIR)/crc.c
+	$(DO_CC)
+                                                                      
+$(BUILDDIR)/client/cvar.o :           $(CLIENT_DIR)/cvar.c
+	$(DO_CC)
+                                                                      
+$(BUILDDIR)/client/d_edge.o :         $(CLIENT_DIR)/d_edge.c
+	$(DO_CC)
+                                                                      
+$(BUILDDIR)/client/d_fill.o :         $(CLIENT_DIR)/d_fill.c
+	$(DO_CC)
+                                                                      
+$(BUILDDIR)/client/d_init.o :         $(CLIENT_DIR)/d_init.c
+	$(DO_CC)
+                                                                      
+$(BUILDDIR)/client/d_modech.o :       $(CLIENT_DIR)/d_modech.c
+	$(DO_CC)
+                                                                      
+$(BUILDDIR)/client/d_part.o :         $(CLIENT_DIR)/d_part.c
+	$(DO_CC)
+                                                                      
+$(BUILDDIR)/client/d_polyse.o :       $(CLIENT_DIR)/d_polyse.c
+	$(DO_CC)
+                                                                      
+$(BUILDDIR)/client/d_scan.o :         $(CLIENT_DIR)/d_scan.c
+	$(DO_CC)
+                                                                      
+$(BUILDDIR)/client/d_sky.o :          $(CLIENT_DIR)/d_sky.c
+	$(DO_CC)
+                                                                      
+$(BUILDDIR)/client/d_sprite.o :       $(CLIENT_DIR)/d_sprite.c
+	$(DO_CC)
+                                                                      
+$(BUILDDIR)/client/d_surf.o :         $(CLIENT_DIR)/d_surf.c
+	$(DO_CC)
+                                                                      
+$(BUILDDIR)/client/d_vars.o :         $(CLIENT_DIR)/d_vars.c
+	$(DO_CC)
+                                                                      
+$(BUILDDIR)/client/d_zpoint.o :       $(CLIENT_DIR)/d_zpoint.c
+	$(DO_CC)
+                                                                      
+$(BUILDDIR)/client/draw.o :           $(CLIENT_DIR)/draw.c
+	$(DO_CC)
+                                                                      
+$(BUILDDIR)/client/keys.o :           $(CLIENT_DIR)/keys.c
+	$(DO_CC)
+                                                                      
+$(BUILDDIR)/client/mathlib.o :        $(CLIENT_DIR)/mathlib.c
+	$(DO_CC)
+                                                                      
+$(BUILDDIR)/client/md4.o :            $(CLIENT_DIR)/md4.c
+	$(DO_CC)
+                                                                      
+$(BUILDDIR)/client/menu.o :           $(CLIENT_DIR)/menu.c
+	$(DO_CC)
+                                                                      
+$(BUILDDIR)/client/model.o :          $(CLIENT_DIR)/model.c
+	$(DO_CC)
+                                                                      
+$(BUILDDIR)/client/net_chan.o :       $(CLIENT_DIR)/net_chan.c
+	$(DO_CC)
+                                                                      
+$(BUILDDIR)/client/net_udp.o :        $(CLIENT_DIR)/net_udp.c
+	$(DO_CC)
+                                                                      
+$(BUILDDIR)/client/nonintel.o :       $(CLIENT_DIR)/nonintel.c
+	$(DO_CC)
+                                                                      
+$(BUILDDIR)/client/pmove.o :          $(CLIENT_DIR)/pmove.c
+	$(DO_CC)
+                                                                      
+$(BUILDDIR)/client/pmovetst.o :       $(CLIENT_DIR)/pmovetst.c
+	$(DO_CC)
+                                                                      
+$(BUILDDIR)/client/r_aclip.o :        $(CLIENT_DIR)/r_aclip.c
+	$(DO_CC)
+                                                                      
+$(BUILDDIR)/client/r_alias.o :        $(CLIENT_DIR)/r_alias.c
+	$(DO_CC)
+                                                                      
+$(BUILDDIR)/client/r_bsp.o :          $(CLIENT_DIR)/r_bsp.c
+	$(DO_CC)
+                                                                      
+$(BUILDDIR)/client/r_draw.o :         $(CLIENT_DIR)/r_draw.c
+	$(DO_CC)
+                                                                      
+$(BUILDDIR)/client/r_edge.o :         $(CLIENT_DIR)/r_edge.c
+	$(DO_CC)
+                                                                      
+$(BUILDDIR)/client/r_efrag.o :        $(CLIENT_DIR)/r_efrag.c
+	$(DO_CC)
+                                                                      
+$(BUILDDIR)/client/r_light.o :        $(CLIENT_DIR)/r_light.c
+	$(DO_CC)
+                                                                      
+$(BUILDDIR)/client/r_main.o :         $(CLIENT_DIR)/r_main.c
+	$(DO_CC)
+                                                                      
+$(BUILDDIR)/client/r_misc.o :         $(CLIENT_DIR)/r_misc.c
+	$(DO_CC)
+                                                                      
+$(BUILDDIR)/client/r_part.o :         $(CLIENT_DIR)/r_part.c
+	$(DO_CC)
+                                                                      
+$(BUILDDIR)/client/r_sky.o :          $(CLIENT_DIR)/r_sky.c
+	$(DO_CC)
+                                                                      
+$(BUILDDIR)/client/r_sprite.o :       $(CLIENT_DIR)/r_sprite.c
+	$(DO_CC)
+                                                                      
+$(BUILDDIR)/client/r_surf.o :         $(CLIENT_DIR)/r_surf.c
+	$(DO_CC)
+                                                                      
+$(BUILDDIR)/client/r_vars.o :         $(CLIENT_DIR)/r_vars.c
+	$(DO_CC)
+                                                                      
+$(BUILDDIR)/client/sbar.o :           $(CLIENT_DIR)/sbar.c
+	$(DO_CC)
+                                                                      
+$(BUILDDIR)/client/screen.o :         $(CLIENT_DIR)/screen.c
+	$(DO_CC)
+                                                                      
+$(BUILDDIR)/client/skin.o :           $(CLIENT_DIR)/skin.c
+	$(DO_CC)
+                                                                      
+$(BUILDDIR)/client/snd_dma.o :        $(CLIENT_DIR)/snd_dma.c
+	$(DO_CC)
+                                                                      
+$(BUILDDIR)/client/snd_mem.o :        $(CLIENT_DIR)/snd_mem.c
+	$(DO_CC)
+                                                                      
+$(BUILDDIR)/client/snd_mix.o :        $(CLIENT_DIR)/snd_mix.c
+	$(DO_CC)
+                                                                      
+$(BUILDDIR)/client/view.o :           $(CLIENT_DIR)/view.c
+	$(DO_CC)
+                                                                      
+$(BUILDDIR)/client/wad.o :            $(CLIENT_DIR)/wad.c
+	$(DO_CC)
+                                                                      
+$(BUILDDIR)/client/zone.o :           $(CLIENT_DIR)/zone.c
+	$(DO_CC)
+                                                                      
+$(BUILDDIR)/client/cd_linux.o :       $(CLIENT_DIR)/cd_linux.c
+	$(DO_CC)
+                                                                      
+$(BUILDDIR)/client/sys_linux.o :      $(CLIENT_DIR)/sys_linux.c
+	$(DO_CC)
+                                                                      
+$(BUILDDIR)/client/snd_linux.o :      $(CLIENT_DIR)/snd_linux.c
+	$(DO_CC)
+                                                                      
+$(BUILDDIR)/client/d_copy.o :         $(CLIENT_DIR)/d_copy.s
+	$(DO_AS)
+
+$(BUILDDIR)/client/d_draw.o :         $(CLIENT_DIR)/d_draw.s
+	$(DO_AS)
+
+$(BUILDDIR)/client/d_draw16.o :       $(CLIENT_DIR)/d_draw16.s
+	$(DO_AS)
+
+$(BUILDDIR)/client/d_parta.o :        $(CLIENT_DIR)/d_parta.s
+	$(DO_AS)
+
+$(BUILDDIR)/client/d_polysa.o :       $(CLIENT_DIR)/d_polysa.s
+	$(DO_AS)
+
+$(BUILDDIR)/client/d_scana.o :        $(CLIENT_DIR)/d_scana.s
+	$(DO_AS)
+
+$(BUILDDIR)/client/d_spr8.o :         $(CLIENT_DIR)/d_spr8.s
+	$(DO_AS)
+
+$(BUILDDIR)/client/d_varsa.o :        $(CLIENT_DIR)/d_varsa.s
+	$(DO_AS)
+
+$(BUILDDIR)/client/math.o :           $(CLIENT_DIR)/math.s
+	$(DO_AS)
+
+$(BUILDDIR)/client/r_aclipa.o :       $(CLIENT_DIR)/r_aclipa.s
+	$(DO_AS)
+
+$(BUILDDIR)/client/r_aliasa.o :       $(CLIENT_DIR)/r_aliasa.s
+	$(DO_AS)
+
+$(BUILDDIR)/client/r_drawa.o :        $(CLIENT_DIR)/r_drawa.s
+	$(DO_AS)
+
+$(BUILDDIR)/client/r_edgea.o :        $(CLIENT_DIR)/r_edgea.s
+	$(DO_AS)
+
+$(BUILDDIR)/client/r_varsa.o :        $(CLIENT_DIR)/r_varsa.s
+	$(DO_AS)
+
+$(BUILDDIR)/client/snd_mixa.o :       $(CLIENT_DIR)/snd_mixa.s
+	$(DO_AS)
+
+$(BUILDDIR)/client/surf16.o :         $(CLIENT_DIR)/surf16.s
+	$(DO_AS)
+
+$(BUILDDIR)/client/surf8.o :          $(CLIENT_DIR)/surf8.s
+	$(DO_AS)
+
+$(BUILDDIR)/client/sys_dosa.o :       $(CLIENT_DIR)/sys_dosa.s
+	$(DO_AS)
+
+$(BUILDDIR)/client/vid_svgalib.o : $(CLIENT_DIR)/vid_svgalib.c
+	$(DO_O_CC)
+
+$(BUILDDIR)/client/vid_x.o : $(CLIENT_DIR)/vid_x.c
+	$(DO_CC)
+
+#############################################################################
+# GL CLIENT
+#############################################################################
+
+GLQWCL_OBJS = \
+	$(BUILDDIR)/glclient/cl_demo.o \
+	$(BUILDDIR)/glclient/cl_ents.o \
+	$(BUILDDIR)/glclient/cl_input.o \
+	$(BUILDDIR)/glclient/cl_main.o \
+	$(BUILDDIR)/glclient/cl_parse.o \
+	$(BUILDDIR)/glclient/cl_pred.o \
+	$(BUILDDIR)/glclient/cl_tent.o \
+	$(BUILDDIR)/glclient/cl_cam.o \
+	$(BUILDDIR)/glclient/cmd.o \
+	$(BUILDDIR)/glclient/common.o \
+	$(BUILDDIR)/glclient/console.o \
+	$(BUILDDIR)/glclient/crc.o \
+	$(BUILDDIR)/glclient/cvar.o \
+	$(BUILDDIR)/glclient/keys.o \
+	$(BUILDDIR)/glclient/mathlib.o \
+	$(BUILDDIR)/glclient/md4.o \
+	$(BUILDDIR)/glclient/menu.o \
+	$(BUILDDIR)/glclient/net_chan.o \
+	$(BUILDDIR)/glclient/net_udp.o \
+	$(BUILDDIR)/glclient/nonintel.o \
+	$(BUILDDIR)/glclient/pmove.o \
+	$(BUILDDIR)/glclient/pmovetst.o \
+	$(BUILDDIR)/glclient/r_part.o \
+	$(BUILDDIR)/glclient/sbar.o \
+	$(BUILDDIR)/glclient/skin.o \
+	$(BUILDDIR)/glclient/snd_dma.o \
+	$(BUILDDIR)/glclient/snd_mem.o \
+	$(BUILDDIR)/glclient/snd_mix.o \
+	$(BUILDDIR)/glclient/view.o \
+	$(BUILDDIR)/glclient/wad.o \
+	$(BUILDDIR)/glclient/zone.o \
+	$(BUILDDIR)/glclient/cd_linux.o \
+	$(BUILDDIR)/glclient/sys_linux.o \
+	$(BUILDDIR)/glclient/snd_linux.o \
+	\
+	$(BUILDDIR)/glclient/gl_draw.o \
+	$(BUILDDIR)/glclient/gl_mesh.o \
+	$(BUILDDIR)/glclient/gl_model.o \
+	$(BUILDDIR)/glclient/gl_ngraph.o \
+	$(BUILDDIR)/glclient/gl_refrag.o \
+	$(BUILDDIR)/glclient/gl_rlight.o \
+	$(BUILDDIR)/glclient/gl_rmain.o \
+	$(BUILDDIR)/glclient/gl_rmisc.o \
+	$(BUILDDIR)/glclient/gl_rsurf.o \
+	$(BUILDDIR)/glclient/gl_screen.o \
+	$(BUILDDIR)/glclient/gl_warp.o \
+	\
+	$(BUILDDIR)/glclient/math.o \
+	$(BUILDDIR)/glclient/snd_mixa.o \
+	$(BUILDDIR)/glclient/sys_dosa.o
+	
+GLQWCL_SVGA_OBJS = $(BUILDDIR)/glclient/gl_vidlinux.o
+GLQWCL_X11_OBJS = $(BUILDDIR)/glclient/gl_vidlinuxglx.o
+
+$(BUILDDIR)/glqwcl : $(GLQWCL_OBJS) $(GLQWCL_SVGA_OBJS)
+	$(CC) $(CFLAGS) -o $@ $(GLQWCL_OBJS) $(GLQWCL_SVGA_OBJS) $(LDFLAGS) $(GL_SVGA_LDFLAGS)
+
+$(BUILDDIR)/glqwcl.glx : $(GLQWCL_OBJS) $(GLQWCL_X11_OBJS)
+	$(CC) $(CFLAGS) -o $@ $(GLQWCL_OBJS) $(GLQWCL_X11_OBJS) $(LDFLAGS) $(GL_X11_LDFLAGS)
+
+$(BUILDDIR)/glclient/cl_demo.o :       $(CLIENT_DIR)/cl_demo.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glclient/cl_ents.o :       $(CLIENT_DIR)/cl_ents.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glclient/cl_input.o :      $(CLIENT_DIR)/cl_input.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glclient/cl_main.o :       $(CLIENT_DIR)/cl_main.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glclient/cl_parse.o :      $(CLIENT_DIR)/cl_parse.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glclient/cl_pred.o :       $(CLIENT_DIR)/cl_pred.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glclient/cl_tent.o :       $(CLIENT_DIR)/cl_tent.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glclient/cl_cam.o :        $(CLIENT_DIR)/cl_cam.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glclient/cmd.o :           $(CLIENT_DIR)/cmd.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glclient/common.o :        $(CLIENT_DIR)/common.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glclient/console.o :       $(CLIENT_DIR)/console.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glclient/crc.o :           $(CLIENT_DIR)/crc.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glclient/cvar.o :          $(CLIENT_DIR)/cvar.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glclient/keys.o :          $(CLIENT_DIR)/keys.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glclient/mathlib.o :       $(CLIENT_DIR)/mathlib.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glclient/md4.o :           $(CLIENT_DIR)/md4.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glclient/menu.o :          $(CLIENT_DIR)/menu.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glclient/net_chan.o :      $(CLIENT_DIR)/net_chan.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glclient/net_udp.o :       $(CLIENT_DIR)/net_udp.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glclient/nonintel.o :      $(CLIENT_DIR)/nonintel.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glclient/pmove.o :         $(CLIENT_DIR)/pmove.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glclient/pmovetst.o :      $(CLIENT_DIR)/pmovetst.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glclient/r_part.o :        $(CLIENT_DIR)/r_part.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glclient/sbar.o :          $(CLIENT_DIR)/sbar.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glclient/screen.o :        $(CLIENT_DIR)/screen.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glclient/skin.o :          $(CLIENT_DIR)/skin.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glclient/snd_dma.o :       $(CLIENT_DIR)/snd_dma.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glclient/snd_mem.o :       $(CLIENT_DIR)/snd_mem.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glclient/snd_mix.o :       $(CLIENT_DIR)/snd_mix.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glclient/view.o :          $(CLIENT_DIR)/view.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glclient/wad.o :           $(CLIENT_DIR)/wad.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glclient/zone.o :          $(CLIENT_DIR)/zone.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glclient/cd_linux.o :      $(CLIENT_DIR)/cd_linux.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glclient/sys_linux.o :     $(CLIENT_DIR)/sys_linux.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glclient/snd_linux.o :     $(CLIENT_DIR)/snd_linux.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glclient/gl_draw.o :       $(CLIENT_DIR)/gl_draw.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glclient/gl_mesh.o :       $(CLIENT_DIR)/gl_mesh.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glclient/gl_model.o :      $(CLIENT_DIR)/gl_model.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glclient/gl_ngraph.o :     $(CLIENT_DIR)/gl_ngraph.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glclient/gl_refrag.o :     $(CLIENT_DIR)/gl_refrag.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glclient/gl_rlight.o :     $(CLIENT_DIR)/gl_rlight.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glclient/gl_rmain.o :      $(CLIENT_DIR)/gl_rmain.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glclient/gl_rmisc.o :      $(CLIENT_DIR)/gl_rmisc.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glclient/gl_rsurf.o :      $(CLIENT_DIR)/gl_rsurf.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glclient/gl_screen.o :     $(CLIENT_DIR)/gl_screen.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glclient/gl_vidlinux.o :   $(CLIENT_DIR)/gl_vidlinux.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glclient/gl_vidlinuxglx.o :   $(CLIENT_DIR)/gl_vidlinuxglx.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glclient/gl_warp.o :       $(CLIENT_DIR)/gl_warp.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glclient/math.o :          $(CLIENT_DIR)/math.s
+	$(DO_GL_AS)
+
+$(BUILDDIR)/glclient/snd_mixa.o :      $(CLIENT_DIR)/snd_mixa.s
+	$(DO_GL_AS)
+
+$(BUILDDIR)/glclient/sys_dosa.o :      $(CLIENT_DIR)/sys_dosa.s
+	$(DO_GL_AS)
+
+#############################################################################
+# RPM
+#############################################################################
+
+# Make RPMs.  You need to be root to make this work
+RPMROOT=/usr/src/redhat
+RPM = rpm
+RPMFLAGS = -bb
+INSTALLDIR = /usr/local/games/quake
+
+ifeq ($(ARCH),axp)
+rpm: rpm-qwsv
+tar: tar-qwsv
+else
+rpm: rpm-qwcl rpm-qwsv
+tar: tar-qwcl tar-qwsv
+endif
+
+QWCL_RPMDIR=/var/tmp/qwcl-$(VERSION)
+TDFXGL_DIR=/home/zoid/3dfxgl
+
+QWPROGS = \
+	$(MAINDIR)/progs/buttons.qc \
+	$(MAINDIR)/progs/client.qc \
+	$(MAINDIR)/progs/combat.qc \
+	$(MAINDIR)/progs/defs.qc \
+	$(MAINDIR)/progs/doors.qc \
+	$(MAINDIR)/progs/items.qc \
+	$(MAINDIR)/progs/misc.qc \
+	$(MAINDIR)/progs/models.qc \
+	$(MAINDIR)/progs/plats.qc \
+	$(MAINDIR)/progs/player.qc \
+	$(MAINDIR)/progs/progdefs.h \
+	$(MAINDIR)/progs/progs.src \
+	$(MAINDIR)/progs/qwprogs.dat \
+	$(MAINDIR)/progs/server.qc \
+	$(MAINDIR)/progs/spectate.qc \
+	$(MAINDIR)/progs/sprites.qc \
+	$(MAINDIR)/progs/subs.qc \
+	$(MAINDIR)/progs/triggers.qc \
+	$(MAINDIR)/progs/weapons.qc \
+	$(MAINDIR)/progs/world.qc
+
+rpm-qwcl: qwcl.spec \
+		$(BUILD_RELEASE_DIR)/qwcl \
+		$(BUILD_RELEASE_DIR)/glqwcl \
+		$(BUILD_RELEASE_DIR)/glqwcl.glx \
+		$(BUILD_RELEASE_DIR)/qwcl.x11
+	touch $(RPMROOT)/SOURCES/qwcl-$(VERSION).tar.gz
+	if [ ! -d archives ];then mkdir archives;fi
+	$(MAKE) copyfiles-qwcl DESTDIR=$(QWCL_RPMDIR)/$(INSTALLDIR)
+	cp qwcl.spec $(RPMROOT)/SPECS/qwcl.spec
+	cp $(MAINDIR)/quake.gif $(RPMROOT)/SOURCES/quake.gif
+	cd $(RPMROOT)/SPECS; $(RPM) $(RPMFLAGS) qwcl.spec
+	cp $(RPMROOT)/RPMS/$(RPMARCH)/qwcl-$(VERSION)-$(RPM_RELEASE).$(RPMARCH).rpm archives/.
+	rm -rf $(QWCL_RPMDIR)
+
+tar-qwcl: $(BUILD_RELEASE_DIR)/qwcl \
+		$(BUILD_RELEASE_DIR)/glqwcl \
+		$(BUILD_RELEASE_DIR)/glqwcl.glx \
+		$(BUILD_RELEASE_DIR)/qwcl.x11
+	if [ ! -d archives ];then mkdir archives;fi
+	$(MAKE) copyfiles-qwcl DESTDIR=$(QWCL_RPMDIR)/$(INSTALLDIR)
+	cd $(QWCL_RPMDIR)/$(INSTALLDIR); tar czvf qwcl-$(VERSION)-$(RPMARCH)-unknown-linux2.0.tar.gz *
+	mv $(QWCL_RPMDIR)/$(INSTALLDIR)/*.tar.gz archives/.
+	rm -rf $(QWCL_RPMDIR)
+
+copyfiles-qwcl:
+	-mkdirhier $(DESTDIR)
+	-mkdirhier $(DESTDIR)/qw
+	-mkdirhier $(DESTDIR)/qw/skins
+	cp $(BUILD_RELEASE_DIR)/qwcl $(DESTDIR)/.
+	strip $(DESTDIR)/qwcl
+	chmod 4755 $(DESTDIR)/qwcl
+	cp $(BUILD_RELEASE_DIR)/qwcl.x11 $(DESTDIR)/.
+	strip $(DESTDIR)/qwcl.x11
+	chmod 755 $(DESTDIR)/qwcl.x11
+	cp $(BUILD_RELEASE_DIR)/glqwcl $(DESTDIR)/.
+	strip $(DESTDIR)/glqwcl
+	chmod 4755 $(DESTDIR)/glqwcl
+	cp $(BUILD_RELEASE_DIR)/glqwcl.glx $(DESTDIR)/.
+	strip $(DESTDIR)/glqwcl.glx
+	chmod 4755 $(DESTDIR)/glqwcl.glx
+	cp $(TDFXGL_DIR)/release$(ARCH)/lib3dfxgl.so $(DESTDIR)/.
+	chmod 755 $(DESTDIR)/lib3dfxgl.so
+	cp $(MAINDIR)/glqwcl.3dfxgl $(DESTDIR)/.
+	chmod 755 $(DESTDIR)/glqwcl.3dfxgl
+	cp $(MAINDIR)/docs/README.qwcl $(DESTDIR)/.
+	chmod 644 $(DESTDIR)/README.qwcl
+	cp $(MAINDIR)/fixskins.sh $(DESTDIR)/qw/skins/.
+	chmod 755 $(DESTDIR)/qw/skins/fixskins.sh
+	cp $(MESA_DIR)/lib/libMesaGL.so.2.6 $(DESTDIR)
+	chmod 755 $(DESTDIR)/libMesaGL.so.2.6
+	cd $(DESTDIR); ln -sf libMesaGL.so.2.6 libMesaGL.so.2
+	cd $(DESTDIR); ln -sf libMesaGL.so.2 libMesaGL.so
+	cd $(DESTDIR); ln -sf libMesaGL.so libGL.so
+
+qwcl.spec : $(MAINDIR)/qwcl.spec.sh $(BUILD_RELEASE_DIR)/qwcl
+	sh $< $(VERSION) $(RPM_RELEASE) $(INSTALLDIR) > $@
+
+QWSV_RPMDIR=/var/tmp/qwsv-$(VERSION)
+rpm-qwsv: qwsv.spec $(BUILD_RELEASE_DIR)/qwsv $(QWPROGS)
+	touch $(RPMROOT)/SOURCES/qwsv-$(VERSION).tar.gz
+	if [ ! -d archives ];then mkdir archives;fi
+	$(MAKE) copyfiles-qwsv DESTDIR=$(QWSV_RPMDIR)/$(INSTALLDIR)
+	cp qwsv.spec $(RPMROOT)/SPECS/qwsv.spec
+	cp $(MAINDIR)/quake.gif $(RPMROOT)/SOURCES/quake.gif
+	cd $(RPMROOT)/SPECS; $(RPM) $(RPMFLAGS) qwsv.spec
+	cp $(RPMROOT)/RPMS/$(RPMARCH)/qwsv-$(VERSION)-$(RPM_RELEASE).$(RPMARCH).rpm archives/.
+	rm -rf $(QWSV_RPMDIR)
+
+tar-qwsv: $(BUILD_RELEASE_DIR)/qwsv $(QWPROGS)
+	if [ ! -d archives ];then mkdir archives;fi
+	$(MAKE) copyfiles-qwsv DESTDIR=$(QWSV_RPMDIR)/$(INSTALLDIR)
+	cd $(QWSV_RPMDIR)/$(INSTALLDIR); tar czvf qwsv-$(VERSION)-$(RPMARCH)-unknown-linux2.0.tar.gz *
+	mv $(QWSV_RPMDIR)/$(INSTALLDIR)/*.tar.gz archives/.
+	rm -rf $(QWSV_RPMDIR)
+
+copyfiles-qwsv:
+	-mkdirhier $(DESTDIR)
+	-mkdirhier $(DESTDIR)/qw
+	-mkdirhier $(DESTDIR)/qw/skins
+	cp $(BUILD_RELEASE_DIR)/qwsv $(DESTDIR)/.
+	strip $(DESTDIR)/qwsv
+	chmod 755 $(DESTDIR)/qwsv
+	cp $(MAINDIR)/docs/README.qwsv $(DESTDIR)/.
+	chmod 644 $(DESTDIR)/README.qwsv
+	cp $(QWPROGS) $(DESTDIR)/qw/.
+	cd $(DESTDIR)/qw; chmod 644 *
+	chmod 755 $(DESTDIR)/qw/skins
+	cp $(MAINDIR)/fixskins.sh $(DESTDIR)/qw/skins/.
+	chmod 755 $(DESTDIR)/qw/skins/fixskins.sh
+
+qwsv.spec : $(MAINDIR)/qwsv.spec.sh $(BUILD_RELEASE_DIR)/qwsv
+	sh $< $(VERSION) $(RPM_RELEASE) $(INSTALLDIR) > $@
+
+#############################################################################
+# MISC
+#############################################################################
+
+clean: clean-debug clean-release
+
+clean-debug:
+	$(MAKE) clean2 BUILDDIR=$(BUILD_DEBUG_DIR) CFLAGS="$(DEBUG_CFLAGS)"
+
+clean-release:
+	$(MAKE) clean2 BUILDDIR=$(BUILD_RELEASE_DIR) CFLAGS="$(DEBUG_CFLAGS)"
+
+clean2:
+	-rm -f $(QWSV_OBJS) \
+		$(QWCL_OBJS) \
+		$(QWCL_AS_OBJS) \
+		$(QWCL_SVGA_OBJS) \
+		$(QWCL_X11_OBJS) \
+		$(GLQWCL_OBJS) \
+
--- /dev/null
+++ b/QW/Makefile.Solaris
@@ -1,0 +1,185 @@
+#
+# QuakeWorld Makefile for Linux 2.0
+#
+# Apr '98 by Zoid <zoid@idsoftware.com>
+#
+# GNU Make required
+#
+
+ifneq (,$(findstring i86pc,$(shell uname -m)))
+ARCH=i386
+else
+ARCH=sparc
+endif
+
+MAINDIR=/grog/Projects/QW
+
+BUILD_DEBUG_DIR=debug$(ARCH)
+BUILD_RELEASE_DIR=release$(ARCH)
+CLIENT_DIR=$(MAINDIR)/client
+SERVER_DIR=$(MAINDIR)/server
+
+CC=gcc
+BASE_CFLAGS=-Wall -Dstricmp=strcasecmp -I$(CLIENT_DIR) -I$(SERVER_DIR)
+RELEASE_CFLAGS=$(BASE_CFLAGS) -O2 -ffast-math
+	# -funroll-loops -fomit-frame-pointer -fexpensive-optimizations
+DEBUG_CFLAGS=$(BASE_CFLAGS) -g
+
+LDFLAGS=-lm -lsocket -lnsl
+
+DO_CC=$(CC) $(CFLAGS) -o $@ -c $<
+DO_SERVER_CC=$(CC) -DSERVERONLY $(CFLAGS) -o $@ -c $<
+
+#############################################################################
+# SETUP AND BUILD
+#############################################################################
+
+TARGETS=$(BUILDDIR)/qwsv 
+
+build_debug:
+	@-mkdir $(BUILD_DEBUG_DIR) \
+		$(BUILD_DEBUG_DIR)/server 
+	$(MAKE) targets BUILDDIR=$(BUILD_DEBUG_DIR) CFLAGS="$(DEBUG_CFLAGS)"
+
+build_release:
+	@-mkdir $(BUILD_RELEASE_DIR) \
+		$(BUILD_RELEASE_DIR)/server
+	$(MAKE) targets BUILDDIR=$(BUILD_RELEASE_DIR) CFLAGS="$(RELEASE_CFLAGS)"
+
+all: build_debug build_release
+
+targets: $(TARGETS)
+
+#############################################################################
+# SERVER
+#############################################################################
+
+QWSV_OBJS = \
+	 $(BUILDDIR)/server/pr_cmds.o \
+	 $(BUILDDIR)/server/pr_edict.o \
+	 $(BUILDDIR)/server/pr_exec.o \
+	 $(BUILDDIR)/server/sv_init.o \
+	 $(BUILDDIR)/server/sv_main.o \
+	 $(BUILDDIR)/server/sv_nchan.o \
+	 $(BUILDDIR)/server/sv_ents.o \
+	 $(BUILDDIR)/server/sv_send.o \
+	 $(BUILDDIR)/server/sv_move.o \
+	 $(BUILDDIR)/server/sv_phys.o \
+	 $(BUILDDIR)/server/sv_user.o \
+	 $(BUILDDIR)/server/sv_ccmds.o \
+	 $(BUILDDIR)/server/world.o \
+	 $(BUILDDIR)/server/sys_unix.o \
+	 $(BUILDDIR)/server/model.o \
+	 $(BUILDDIR)/server/cmd.o \
+	 $(BUILDDIR)/server/common.o \
+	 $(BUILDDIR)/server/crc.o \
+	 $(BUILDDIR)/server/cvar.o \
+	 $(BUILDDIR)/server/mathlib.o \
+	 $(BUILDDIR)/server/md4.o \
+	 $(BUILDDIR)/server/zone.o \
+	 $(BUILDDIR)/server/pmove.o \
+	 $(BUILDDIR)/server/pmovetst.o \
+	 $(BUILDDIR)/server/net_chan.o \
+	 $(BUILDDIR)/server/net_udp.o 
+
+$(BUILDDIR)/qwsv : $(QWSV_OBJS)
+	$(CC) $(CFLAGS) -o $@ $(QWSV_OBJS) $(LDFLAGS)
+
+$(BUILDDIR)/server/pr_cmds.o :   $(SERVER_DIR)/pr_cmds.c 
+	$(DO_SERVER_CC)
+
+$(BUILDDIR)/server/pr_edict.o :  $(SERVER_DIR)/pr_edict.c
+	$(DO_SERVER_CC)
+
+$(BUILDDIR)/server/pr_exec.o :   $(SERVER_DIR)/pr_exec.c
+	$(DO_SERVER_CC)
+
+$(BUILDDIR)/server/sv_init.o :   $(SERVER_DIR)/sv_init.c
+	$(DO_SERVER_CC)
+
+$(BUILDDIR)/server/sv_main.o :   $(SERVER_DIR)/sv_main.c
+	$(DO_SERVER_CC)
+
+$(BUILDDIR)/server/sv_nchan.o :   $(SERVER_DIR)/sv_nchan.c
+	$(DO_SERVER_CC)
+
+$(BUILDDIR)/server/sv_ents.o :   $(SERVER_DIR)/sv_ents.c
+	$(DO_SERVER_CC)
+
+$(BUILDDIR)/server/sv_send.o :   $(SERVER_DIR)/sv_send.c
+	$(DO_SERVER_CC)
+
+$(BUILDDIR)/server/sv_move.o :   $(SERVER_DIR)/sv_move.c
+	$(DO_SERVER_CC)
+
+$(BUILDDIR)/server/sv_phys.o :   $(SERVER_DIR)/sv_phys.c
+	$(DO_SERVER_CC)
+
+$(BUILDDIR)/server/sv_user.o :   $(SERVER_DIR)/sv_user.c
+	$(DO_SERVER_CC)
+
+$(BUILDDIR)/server/sv_ccmds.o :  $(SERVER_DIR)/sv_ccmds.c
+	$(DO_SERVER_CC)
+
+$(BUILDDIR)/server/world.o :     $(SERVER_DIR)/world.c
+	$(DO_SERVER_CC)
+
+$(BUILDDIR)/server/sys_unix.o :  $(SERVER_DIR)/sys_unix.c
+	$(DO_SERVER_CC)
+
+$(BUILDDIR)/server/model.o :     $(SERVER_DIR)/model.c
+	$(DO_SERVER_CC)
+
+$(BUILDDIR)/server/cmd.o :       $(CLIENT_DIR)/cmd.c
+	$(DO_SERVER_CC)
+
+$(BUILDDIR)/server/common.o :    $(CLIENT_DIR)/common.c
+	$(DO_SERVER_CC)
+
+$(BUILDDIR)/server/crc.o :       $(CLIENT_DIR)/crc.c
+	$(DO_SERVER_CC)
+
+$(BUILDDIR)/server/cvar.o :      $(CLIENT_DIR)/cvar.c
+	$(DO_SERVER_CC)
+
+$(BUILDDIR)/server/mathlib.o :   $(CLIENT_DIR)/mathlib.c
+	$(DO_SERVER_CC)
+
+$(BUILDDIR)/server/md4.o :       $(CLIENT_DIR)/md4.c
+	$(DO_SERVER_CC)
+
+$(BUILDDIR)/server/zone.o :      $(CLIENT_DIR)/zone.c
+	$(DO_SERVER_CC)
+
+$(BUILDDIR)/server/pmove.o :     $(CLIENT_DIR)/pmove.c
+	$(DO_SERVER_CC)
+
+$(BUILDDIR)/server/pmovetst.o :  $(CLIENT_DIR)/pmovetst.c
+	$(DO_SERVER_CC)
+
+$(BUILDDIR)/server/net_chan.o :  $(CLIENT_DIR)/net_chan.c
+	$(DO_SERVER_CC)
+
+$(BUILDDIR)/server/net_udp.o :   $(CLIENT_DIR)/net_udp.c
+	$(DO_SERVER_CC)
+
+#############################################################################
+# MISC
+#############################################################################
+
+clean: clean-debug clean-release
+
+clean-debug:
+	$(MAKE) clean2 BUILDDIR=$(BUILD_DEBUG_DIR) CFLAGS="$(DEBUG_CFLAGS)"
+
+clean-release:
+	$(MAKE) clean2 BUILDDIR=$(BUILD_RELEASE_DIR) CFLAGS="$(DEBUG_CFLAGS)"
+
+clean2:
+	-rm -f $(QWSV_OBJS) \
+		$(QWCL_OBJS) \
+		$(QWCL_AS_OBJS) \
+		$(QWCL_SVGA_OBJS) \
+		$(QWCL_X11_OBJS) \
+		$(GLQWCL_OBJS) \
+
--- /dev/null
+++ b/QW/clean.bat
@@ -1,0 +1,40 @@
+rm -rf client\debug
+rm -rf client\release
+rm -rf client\gldebug
+rm -rf client\glrelease
+
+rm -f client\qwcl.ncb
+rm -f client\qwcl.opt
+rm -f client\qwcl.plg
+rm -f client\qwcl.stt
+
+rm -rf server\debug
+rm -rf server\release
+
+rm -f server\qwsv.ncb
+rm -f server\qwsv.opt
+rm -f server\qwsv.plg
+rm -f server\qwsv.stt
+
+rm -rf gas2masm\debug
+rm -rf gas2masm\release
+
+rm -f gas2masm\gas2masm.ncb
+rm -f gas2masm\gas2masm.opt
+rm -f gas2masm\gas2masm.plg
+rm -f gas2masm\gas2masm.stt
+
+rm -rf qwfwd\debug
+rm -rf qwfwd\release
+
+rm -f qwfwd\qwfwd.ncb
+rm -f qwfwd\qwfwd.opt
+rm -f qwfwd\qwfwd.plg
+rm -f qwfwd\qwfwd.stt
+
+rm -f qw.ncb
+rm -f qw.opt
+rm -f qw.plg
+rm -f qw.stt
+
+
--- /dev/null
+++ b/QW/client/adivtab.h
@@ -1,0 +1,1074 @@
+/*
+Copyright (C) 1999, 2000  Id Software Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+*/
+
+// table of quotients and remainders for [-15...16] / [-15...16]
+
+// numerator = -15
+{1, 0},
+{1, -1},
+{1, -2},
+{1, -3},
+{1, -4},
+{1, -5},
+{1, -6},
+{1, -7},
+{2, -1},
+{2, -3},
+{3, 0},
+{3, -3},
+{5, 0},
+{7, -1},
+{15, 0},
+{0, 0},
+{-15, 0},
+{-8, 1},
+{-5, 0},
+{-4, 1},
+{-3, 0},
+{-3, 3},
+{-3, 6},
+{-2, 1},
+{-2, 3},
+{-2, 5},
+{-2, 7},
+{-2, 9},
+{-2, 11},
+{-2, 13},
+{-1, 0},
+{-1, 1},
+// numerator = -14
+{0, -14},
+{1, 0},
+{1, -1},
+{1, -2},
+{1, -3},
+{1, -4},
+{1, -5},
+{1, -6},
+{2, 0},
+{2, -2},
+{2, -4},
+{3, -2},
+{4, -2},
+{7, 0},
+{14, 0},
+{0, 0},
+{-14, 0},
+{-7, 0},
+{-5, 1},
+{-4, 2},
+{-3, 1},
+{-3, 4},
+{-2, 0},
+{-2, 2},
+{-2, 4},
+{-2, 6},
+{-2, 8},
+{-2, 10},
+{-2, 12},
+{-1, 0},
+{-1, 1},
+{-1, 2},
+// numerator = -13
+{0, -13},
+{0, -13},
+{1, 0},
+{1, -1},
+{1, -2},
+{1, -3},
+{1, -4},
+{1, -5},
+{1, -6},
+{2, -1},
+{2, -3},
+{3, -1},
+{4, -1},
+{6, -1},
+{13, 0},
+{0, 0},
+{-13, 0},
+{-7, 1},
+{-5, 2},
+{-4, 3},
+{-3, 2},
+{-3, 5},
+{-2, 1},
+{-2, 3},
+{-2, 5},
+{-2, 7},
+{-2, 9},
+{-2, 11},
+{-1, 0},
+{-1, 1},
+{-1, 2},
+{-1, 3},
+// numerator = -12
+{0, -12},
+{0, -12},
+{0, -12},
+{1, 0},
+{1, -1},
+{1, -2},
+{1, -3},
+{1, -4},
+{1, -5},
+{2, 0},
+{2, -2},
+{3, 0},
+{4, 0},
+{6, 0},
+{12, 0},
+{0, 0},
+{-12, 0},
+{-6, 0},
+{-4, 0},
+{-3, 0},
+{-3, 3},
+{-2, 0},
+{-2, 2},
+{-2, 4},
+{-2, 6},
+{-2, 8},
+{-2, 10},
+{-1, 0},
+{-1, 1},
+{-1, 2},
+{-1, 3},
+{-1, 4},
+// numerator = -11
+{0, -11},
+{0, -11},
+{0, -11},
+{0, -11},
+{1, 0},
+{1, -1},
+{1, -2},
+{1, -3},
+{1, -4},
+{1, -5},
+{2, -1},
+{2, -3},
+{3, -2},
+{5, -1},
+{11, 0},
+{0, 0},
+{-11, 0},
+{-6, 1},
+{-4, 1},
+{-3, 1},
+{-3, 4},
+{-2, 1},
+{-2, 3},
+{-2, 5},
+{-2, 7},
+{-2, 9},
+{-1, 0},
+{-1, 1},
+{-1, 2},
+{-1, 3},
+{-1, 4},
+{-1, 5},
+// numerator = -10
+{0, -10},
+{0, -10},
+{0, -10},
+{0, -10},
+{0, -10},
+{1, 0},
+{1, -1},
+{1, -2},
+{1, -3},
+{1, -4},
+{2, 0},
+{2, -2},
+{3, -1},
+{5, 0},
+{10, 0},
+{0, 0},
+{-10, 0},
+{-5, 0},
+{-4, 2},
+{-3, 2},
+{-2, 0},
+{-2, 2},
+{-2, 4},
+{-2, 6},
+{-2, 8},
+{-1, 0},
+{-1, 1},
+{-1, 2},
+{-1, 3},
+{-1, 4},
+{-1, 5},
+{-1, 6},
+// numerator = -9
+{0, -9},
+{0, -9},
+{0, -9},
+{0, -9},
+{0, -9},
+{0, -9},
+{1, 0},
+{1, -1},
+{1, -2},
+{1, -3},
+{1, -4},
+{2, -1},
+{3, 0},
+{4, -1},
+{9, 0},
+{0, 0},
+{-9, 0},
+{-5, 1},
+{-3, 0},
+{-3, 3},
+{-2, 1},
+{-2, 3},
+{-2, 5},
+{-2, 7},
+{-1, 0},
+{-1, 1},
+{-1, 2},
+{-1, 3},
+{-1, 4},
+{-1, 5},
+{-1, 6},
+{-1, 7},
+// numerator = -8
+{0, -8},
+{0, -8},
+{0, -8},
+{0, -8},
+{0, -8},
+{0, -8},
+{0, -8},
+{1, 0},
+{1, -1},
+{1, -2},
+{1, -3},
+{2, 0},
+{2, -2},
+{4, 0},
+{8, 0},
+{0, 0},
+{-8, 0},
+{-4, 0},
+{-3, 1},
+{-2, 0},
+{-2, 2},
+{-2, 4},
+{-2, 6},
+{-1, 0},
+{-1, 1},
+{-1, 2},
+{-1, 3},
+{-1, 4},
+{-1, 5},
+{-1, 6},
+{-1, 7},
+{-1, 8},
+// numerator = -7
+{0, -7},
+{0, -7},
+{0, -7},
+{0, -7},
+{0, -7},
+{0, -7},
+{0, -7},
+{0, -7},
+{1, 0},
+{1, -1},
+{1, -2},
+{1, -3},
+{2, -1},
+{3, -1},
+{7, 0},
+{0, 0},
+{-7, 0},
+{-4, 1},
+{-3, 2},
+{-2, 1},
+{-2, 3},
+{-2, 5},
+{-1, 0},
+{-1, 1},
+{-1, 2},
+{-1, 3},
+{-1, 4},
+{-1, 5},
+{-1, 6},
+{-1, 7},
+{-1, 8},
+{-1, 9},
+// numerator = -6
+{0, -6},
+{0, -6},
+{0, -6},
+{0, -6},
+{0, -6},
+{0, -6},
+{0, -6},
+{0, -6},
+{0, -6},
+{1, 0},
+{1, -1},
+{1, -2},
+{2, 0},
+{3, 0},
+{6, 0},
+{0, 0},
+{-6, 0},
+{-3, 0},
+{-2, 0},
+{-2, 2},
+{-2, 4},
+{-1, 0},
+{-1, 1},
+{-1, 2},
+{-1, 3},
+{-1, 4},
+{-1, 5},
+{-1, 6},
+{-1, 7},
+{-1, 8},
+{-1, 9},
+{-1, 10},
+// numerator = -5
+{0, -5},
+{0, -5},
+{0, -5},
+{0, -5},
+{0, -5},
+{0, -5},
+{0, -5},
+{0, -5},
+{0, -5},
+{0, -5},
+{1, 0},
+{1, -1},
+{1, -2},
+{2, -1},
+{5, 0},
+{0, 0},
+{-5, 0},
+{-3, 1},
+{-2, 1},
+{-2, 3},
+{-1, 0},
+{-1, 1},
+{-1, 2},
+{-1, 3},
+{-1, 4},
+{-1, 5},
+{-1, 6},
+{-1, 7},
+{-1, 8},
+{-1, 9},
+{-1, 10},
+{-1, 11},
+// numerator = -4
+{0, -4},
+{0, -4},
+{0, -4},
+{0, -4},
+{0, -4},
+{0, -4},
+{0, -4},
+{0, -4},
+{0, -4},
+{0, -4},
+{0, -4},
+{1, 0},
+{1, -1},
+{2, 0},
+{4, 0},
+{0, 0},
+{-4, 0},
+{-2, 0},
+{-2, 2},
+{-1, 0},
+{-1, 1},
+{-1, 2},
+{-1, 3},
+{-1, 4},
+{-1, 5},
+{-1, 6},
+{-1, 7},
+{-1, 8},
+{-1, 9},
+{-1, 10},
+{-1, 11},
+{-1, 12},
+// numerator = -3
+{0, -3},
+{0, -3},
+{0, -3},
+{0, -3},
+{0, -3},
+{0, -3},
+{0, -3},
+{0, -3},
+{0, -3},
+{0, -3},
+{0, -3},
+{0, -3},
+{1, 0},
+{1, -1},
+{3, 0},
+{0, 0},
+{-3, 0},
+{-2, 1},
+{-1, 0},
+{-1, 1},
+{-1, 2},
+{-1, 3},
+{-1, 4},
+{-1, 5},
+{-1, 6},
+{-1, 7},
+{-1, 8},
+{-1, 9},
+{-1, 10},
+{-1, 11},
+{-1, 12},
+{-1, 13},
+// numerator = -2
+{0, -2},
+{0, -2},
+{0, -2},
+{0, -2},
+{0, -2},
+{0, -2},
+{0, -2},
+{0, -2},
+{0, -2},
+{0, -2},
+{0, -2},
+{0, -2},
+{0, -2},
+{1, 0},
+{2, 0},
+{0, 0},
+{-2, 0},
+{-1, 0},
+{-1, 1},
+{-1, 2},
+{-1, 3},
+{-1, 4},
+{-1, 5},
+{-1, 6},
+{-1, 7},
+{-1, 8},
+{-1, 9},
+{-1, 10},
+{-1, 11},
+{-1, 12},
+{-1, 13},
+{-1, 14},
+// numerator = -1
+{0, -1},
+{0, -1},
+{0, -1},
+{0, -1},
+{0, -1},
+{0, -1},
+{0, -1},
+{0, -1},
+{0, -1},
+{0, -1},
+{0, -1},
+{0, -1},
+{0, -1},
+{0, -1},
+{1, 0},
+{0, 0},
+{-1, 0},
+{-1, 1},
+{-1, 2},
+{-1, 3},
+{-1, 4},
+{-1, 5},
+{-1, 6},
+{-1, 7},
+{-1, 8},
+{-1, 9},
+{-1, 10},
+{-1, 11},
+{-1, 12},
+{-1, 13},
+{-1, 14},
+{-1, 15},
+// numerator = 0
+{0, 0},
+{0, 0},
+{0, 0},
+{0, 0},
+{0, 0},
+{0, 0},
+{0, 0},
+{0, 0},
+{0, 0},
+{0, 0},
+{0, 0},
+{0, 0},
+{0, 0},
+{0, 0},
+{0, 0},
+{0, 0},
+{0, 0},
+{0, 0},
+{0, 0},
+{0, 0},
+{0, 0},
+{0, 0},
+{0, 0},
+{0, 0},
+{0, 0},
+{0, 0},
+{0, 0},
+{0, 0},
+{0, 0},
+{0, 0},
+{0, 0},
+{0, 0},
+// numerator = 1
+{-1, -14},
+{-1, -13},
+{-1, -12},
+{-1, -11},
+{-1, -10},
+{-1, -9},
+{-1, -8},
+{-1, -7},
+{-1, -6},
+{-1, -5},
+{-1, -4},
+{-1, -3},
+{-1, -2},
+{-1, -1},
+{-1, 0},
+{0, 0},
+{1, 0},
+{0, 1},
+{0, 1},
+{0, 1},
+{0, 1},
+{0, 1},
+{0, 1},
+{0, 1},
+{0, 1},
+{0, 1},
+{0, 1},
+{0, 1},
+{0, 1},
+{0, 1},
+{0, 1},
+{0, 1},
+// numerator = 2
+{-1, -13},
+{-1, -12},
+{-1, -11},
+{-1, -10},
+{-1, -9},
+{-1, -8},
+{-1, -7},
+{-1, -6},
+{-1, -5},
+{-1, -4},
+{-1, -3},
+{-1, -2},
+{-1, -1},
+{-1, 0},
+{-2, 0},
+{0, 0},
+{2, 0},
+{1, 0},
+{0, 2},
+{0, 2},
+{0, 2},
+{0, 2},
+{0, 2},
+{0, 2},
+{0, 2},
+{0, 2},
+{0, 2},
+{0, 2},
+{0, 2},
+{0, 2},
+{0, 2},
+{0, 2},
+// numerator = 3
+{-1, -12},
+{-1, -11},
+{-1, -10},
+{-1, -9},
+{-1, -8},
+{-1, -7},
+{-1, -6},
+{-1, -5},
+{-1, -4},
+{-1, -3},
+{-1, -2},
+{-1, -1},
+{-1, 0},
+{-2, -1},
+{-3, 0},
+{0, 0},
+{3, 0},
+{1, 1},
+{1, 0},
+{0, 3},
+{0, 3},
+{0, 3},
+{0, 3},
+{0, 3},
+{0, 3},
+{0, 3},
+{0, 3},
+{0, 3},
+{0, 3},
+{0, 3},
+{0, 3},
+{0, 3},
+// numerator = 4
+{-1, -11},
+{-1, -10},
+{-1, -9},
+{-1, -8},
+{-1, -7},
+{-1, -6},
+{-1, -5},
+{-1, -4},
+{-1, -3},
+{-1, -2},
+{-1, -1},
+{-1, 0},
+{-2, -2},
+{-2, 0},
+{-4, 0},
+{0, 0},
+{4, 0},
+{2, 0},
+{1, 1},
+{1, 0},
+{0, 4},
+{0, 4},
+{0, 4},
+{0, 4},
+{0, 4},
+{0, 4},
+{0, 4},
+{0, 4},
+{0, 4},
+{0, 4},
+{0, 4},
+{0, 4},
+// numerator = 5
+{-1, -10},
+{-1, -9},
+{-1, -8},
+{-1, -7},
+{-1, -6},
+{-1, -5},
+{-1, -4},
+{-1, -3},
+{-1, -2},
+{-1, -1},
+{-1, 0},
+{-2, -3},
+{-2, -1},
+{-3, -1},
+{-5, 0},
+{0, 0},
+{5, 0},
+{2, 1},
+{1, 2},
+{1, 1},
+{1, 0},
+{0, 5},
+{0, 5},
+{0, 5},
+{0, 5},
+{0, 5},
+{0, 5},
+{0, 5},
+{0, 5},
+{0, 5},
+{0, 5},
+{0, 5},
+// numerator = 6
+{-1, -9},
+{-1, -8},
+{-1, -7},
+{-1, -6},
+{-1, -5},
+{-1, -4},
+{-1, -3},
+{-1, -2},
+{-1, -1},
+{-1, 0},
+{-2, -4},
+{-2, -2},
+{-2, 0},
+{-3, 0},
+{-6, 0},
+{0, 0},
+{6, 0},
+{3, 0},
+{2, 0},
+{1, 2},
+{1, 1},
+{1, 0},
+{0, 6},
+{0, 6},
+{0, 6},
+{0, 6},
+{0, 6},
+{0, 6},
+{0, 6},
+{0, 6},
+{0, 6},
+{0, 6},
+// numerator = 7
+{-1, -8},
+{-1, -7},
+{-1, -6},
+{-1, -5},
+{-1, -4},
+{-1, -3},
+{-1, -2},
+{-1, -1},
+{-1, 0},
+{-2, -5},
+{-2, -3},
+{-2, -1},
+{-3, -2},
+{-4, -1},
+{-7, 0},
+{0, 0},
+{7, 0},
+{3, 1},
+{2, 1},
+{1, 3},
+{1, 2},
+{1, 1},
+{1, 0},
+{0, 7},
+{0, 7},
+{0, 7},
+{0, 7},
+{0, 7},
+{0, 7},
+{0, 7},
+{0, 7},
+{0, 7},
+// numerator = 8
+{-1, -7},
+{-1, -6},
+{-1, -5},
+{-1, -4},
+{-1, -3},
+{-1, -2},
+{-1, -1},
+{-1, 0},
+{-2, -6},
+{-2, -4},
+{-2, -2},
+{-2, 0},
+{-3, -1},
+{-4, 0},
+{-8, 0},
+{0, 0},
+{8, 0},
+{4, 0},
+{2, 2},
+{2, 0},
+{1, 3},
+{1, 2},
+{1, 1},
+{1, 0},
+{0, 8},
+{0, 8},
+{0, 8},
+{0, 8},
+{0, 8},
+{0, 8},
+{0, 8},
+{0, 8},
+// numerator = 9
+{-1, -6},
+{-1, -5},
+{-1, -4},
+{-1, -3},
+{-1, -2},
+{-1, -1},
+{-1, 0},
+{-2, -7},
+{-2, -5},
+{-2, -3},
+{-2, -1},
+{-3, -3},
+{-3, 0},
+{-5, -1},
+{-9, 0},
+{0, 0},
+{9, 0},
+{4, 1},
+{3, 0},
+{2, 1},
+{1, 4},
+{1, 3},
+{1, 2},
+{1, 1},
+{1, 0},
+{0, 9},
+{0, 9},
+{0, 9},
+{0, 9},
+{0, 9},
+{0, 9},
+{0, 9},
+// numerator = 10
+{-1, -5},
+{-1, -4},
+{-1, -3},
+{-1, -2},
+{-1, -1},
+{-1, 0},
+{-2, -8},
+{-2, -6},
+{-2, -4},
+{-2, -2},
+{-2, 0},
+{-3, -2},
+{-4, -2},
+{-5, 0},
+{-10, 0},
+{0, 0},
+{10, 0},
+{5, 0},
+{3, 1},
+{2, 2},
+{2, 0},
+{1, 4},
+{1, 3},
+{1, 2},
+{1, 1},
+{1, 0},
+{0, 10},
+{0, 10},
+{0, 10},
+{0, 10},
+{0, 10},
+{0, 10},
+// numerator = 11
+{-1, -4},
+{-1, -3},
+{-1, -2},
+{-1, -1},
+{-1, 0},
+{-2, -9},
+{-2, -7},
+{-2, -5},
+{-2, -3},
+{-2, -1},
+{-3, -4},
+{-3, -1},
+{-4, -1},
+{-6, -1},
+{-11, 0},
+{0, 0},
+{11, 0},
+{5, 1},
+{3, 2},
+{2, 3},
+{2, 1},
+{1, 5},
+{1, 4},
+{1, 3},
+{1, 2},
+{1, 1},
+{1, 0},
+{0, 11},
+{0, 11},
+{0, 11},
+{0, 11},
+{0, 11},
+// numerator = 12
+{-1, -3},
+{-1, -2},
+{-1, -1},
+{-1, 0},
+{-2, -10},
+{-2, -8},
+{-2, -6},
+{-2, -4},
+{-2, -2},
+{-2, 0},
+{-3, -3},
+{-3, 0},
+{-4, 0},
+{-6, 0},
+{-12, 0},
+{0, 0},
+{12, 0},
+{6, 0},
+{4, 0},
+{3, 0},
+{2, 2},
+{2, 0},
+{1, 5},
+{1, 4},
+{1, 3},
+{1, 2},
+{1, 1},
+{1, 0},
+{0, 12},
+{0, 12},
+{0, 12},
+{0, 12},
+// numerator = 13
+{-1, -2},
+{-1, -1},
+{-1, 0},
+{-2, -11},
+{-2, -9},
+{-2, -7},
+{-2, -5},
+{-2, -3},
+{-2, -1},
+{-3, -5},
+{-3, -2},
+{-4, -3},
+{-5, -2},
+{-7, -1},
+{-13, 0},
+{0, 0},
+{13, 0},
+{6, 1},
+{4, 1},
+{3, 1},
+{2, 3},
+{2, 1},
+{1, 6},
+{1, 5},
+{1, 4},
+{1, 3},
+{1, 2},
+{1, 1},
+{1, 0},
+{0, 13},
+{0, 13},
+{0, 13},
+// numerator = 14
+{-1, -1},
+{-1, 0},
+{-2, -12},
+{-2, -10},
+{-2, -8},
+{-2, -6},
+{-2, -4},
+{-2, -2},
+{-2, 0},
+{-3, -4},
+{-3, -1},
+{-4, -2},
+{-5, -1},
+{-7, 0},
+{-14, 0},
+{0, 0},
+{14, 0},
+{7, 0},
+{4, 2},
+{3, 2},
+{2, 4},
+{2, 2},
+{2, 0},
+{1, 6},
+{1, 5},
+{1, 4},
+{1, 3},
+{1, 2},
+{1, 1},
+{1, 0},
+{0, 14},
+{0, 14},
+// numerator = 15
+{-1, 0},
+{-2, -13},
+{-2, -11},
+{-2, -9},
+{-2, -7},
+{-2, -5},
+{-2, -3},
+{-2, -1},
+{-3, -6},
+{-3, -3},
+{-3, 0},
+{-4, -1},
+{-5, 0},
+{-8, -1},
+{-15, 0},
+{0, 0},
+{15, 0},
+{7, 1},
+{5, 0},
+{3, 3},
+{3, 0},
+{2, 3},
+{2, 1},
+{1, 7},
+{1, 6},
+{1, 5},
+{1, 4},
+{1, 3},
+{1, 2},
+{1, 1},
+{1, 0},
+{0, 15},
+// numerator = 16
+{-2, -14},
+{-2, -12},
+{-2, -10},
+{-2, -8},
+{-2, -6},
+{-2, -4},
+{-2, -2},
+{-2, 0},
+{-3, -5},
+{-3, -2},
+{-4, -4},
+{-4, 0},
+{-6, -2},
+{-8, 0},
+{-16, 0},
+{0, 0},
+{16, 0},
+{8, 0},
+{5, 1},
+{4, 0},
+{3, 1},
+{2, 4},
+{2, 2},
+{2, 0},
+{1, 7},
+{1, 6},
+{1, 5},
+{1, 4},
+{1, 3},
+{1, 2},
+{1, 1},
+{1, 0},
--- /dev/null
+++ b/QW/client/anorm_dots.h
@@ -1,0 +1,37 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+{
+{1.23,1.30,1.47,1.35,1.56,1.71,1.37,1.38,1.59,1.60,1.79,1.97,1.88,1.92,1.79,1.02,0.93,1.07,0.82,0.87,0.88,0.94,0.96,1.14,1.11,0.82,0.83,0.89,0.89,0.86,0.94,0.91,1.00,1.21,0.98,1.48,1.30,1.57,0.96,1.07,1.14,1.60,1.61,1.40,1.37,1.72,1.78,1.79,1.93,1.99,1.90,1.68,1.71,1.86,1.60,1.68,1.78,1.86,1.93,1.99,1.97,1.44,1.22,1.49,0.93,0.99,0.99,1.23,1.22,1.44,1.49,0.89,0.89,0.97,0.91,0.98,1.19,0.82,0.76,0.82,0.71,0.72,0.73,0.76,0.79,0.86,0.83,0.72,0.76,0.76,0.89,0.82,0.89,0.82,0.89,0.91,0.83,0.96,1.14,0.97,1.40,1.19,0.98,0.94,1.00,1.07,1.37,1.21,1.48,1.30,1.57,1.61,1.37,0.86,0.83,0.91,0.82,0.82,0.88,0.89,0.96,1.14,0.98,0.87,0.93,0.94,1.02,1.30,1.07,1.35,1.38,1.11,1.56,1.92,1.79,1.79,1.59,1.60,1.72,1.90,1.79,0.80,0.85,0.79,0.93,0.80,0.85,0.77,0.74,0.72,0.77,0.74,0.72,0.70,0.70,0.71,0.76,0.73,0.79,0.79,0.73,0.76,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00},
+{1.26,1.26,1.48,1.23,1.50,1.71,1.14,1.19,1.38,1.46,1.64,1.94,1.87,1.84,1.71,1.02,0.92,1.00,0.79,0.85,0.84,0.91,0.90,0.98,0.99,0.77,0.77,0.83,0.82,0.79,0.86,0.84,0.92,0.99,0.91,1.24,1.03,1.33,0.88,0.94,0.97,1.41,1.39,1.18,1.11,1.51,1.61,1.59,1.80,1.91,1.76,1.54,1.65,1.76,1.70,1.70,1.85,1.85,1.97,1.99,1.93,1.28,1.09,1.39,0.92,0.97,0.99,1.18,1.26,1.52,1.48,0.83,0.85,0.90,0.88,0.93,1.00,0.77,0.73,0.78,0.72,0.71,0.74,0.75,0.79,0.86,0.81,0.75,0.81,0.79,0.96,0.88,0.94,0.86,0.93,0.92,0.85,1.08,1.33,1.05,1.55,1.31,1.01,1.05,1.27,1.31,1.60,1.47,1.70,1.54,1.76,1.76,1.57,0.93,0.90,0.99,0.88,0.88,0.95,0.97,1.11,1.39,1.20,0.92,0.97,1.01,1.10,1.39,1.22,1.51,1.58,1.32,1.64,1.97,1.85,1.91,1.77,1.74,1.88,1.99,1.91,0.79,0.86,0.80,0.94,0.84,0.88,0.74,0.74,0.71,0.82,0.77,0.76,0.70,0.73,0.72,0.73,0.70,0.74,0.85,0.77,0.82,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00},
+{1.34,1.27,1.53,1.17,1.46,1.71,0.98,1.05,1.20,1.34,1.48,1.86,1.82,1.71,1.62,1.09,0.94,0.99,0.79,0.85,0.82,0.90,0.87,0.93,0.96,0.76,0.74,0.79,0.76,0.74,0.79,0.78,0.85,0.92,0.85,1.00,0.93,1.06,0.81,0.86,0.89,1.16,1.12,0.97,0.95,1.28,1.38,1.35,1.60,1.77,1.57,1.33,1.50,1.58,1.69,1.63,1.82,1.74,1.91,1.92,1.80,1.04,0.97,1.21,0.90,0.93,0.97,1.05,1.21,1.48,1.37,0.77,0.80,0.84,0.85,0.88,0.92,0.73,0.71,0.74,0.74,0.71,0.75,0.73,0.79,0.84,0.78,0.79,0.86,0.81,1.05,0.94,0.99,0.90,0.95,0.92,0.86,1.24,1.44,1.14,1.59,1.34,1.02,1.27,1.50,1.49,1.80,1.69,1.86,1.72,1.87,1.80,1.69,1.00,0.98,1.23,0.95,0.96,1.09,1.16,1.37,1.63,1.46,0.99,1.10,1.25,1.24,1.51,1.41,1.67,1.77,1.55,1.72,1.95,1.89,1.98,1.91,1.86,1.97,1.99,1.94,0.81,0.89,0.85,0.98,0.90,0.94,0.75,0.78,0.73,0.89,0.83,0.82,0.72,0.77,0.76,0.72,0.70,0.71,0.91,0.83,0.89,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00},
+{1.46,1.34,1.60,1.16,1.46,1.71,0.94,0.99,1.05,1.26,1.33,1.74,1.76,1.57,1.54,1.23,0.98,1.05,0.83,0.89,0.84,0.92,0.87,0.91,0.96,0.78,0.74,0.79,0.72,0.72,0.75,0.76,0.80,0.88,0.83,0.94,0.87,0.95,0.76,0.80,0.82,0.97,0.96,0.89,0.88,1.08,1.11,1.10,1.37,1.59,1.37,1.07,1.27,1.34,1.57,1.45,1.69,1.55,1.77,1.79,1.60,0.93,0.90,0.99,0.86,0.87,0.93,0.96,1.07,1.35,1.18,0.73,0.76,0.77,0.81,0.82,0.85,0.70,0.71,0.72,0.78,0.73,0.77,0.73,0.79,0.82,0.76,0.83,0.90,0.84,1.18,0.98,1.03,0.92,0.95,0.90,0.86,1.32,1.45,1.15,1.53,1.27,0.99,1.42,1.65,1.58,1.93,1.83,1.94,1.81,1.88,1.74,1.70,1.19,1.17,1.44,1.11,1.15,1.36,1.41,1.61,1.81,1.67,1.22,1.34,1.50,1.42,1.65,1.61,1.82,1.91,1.75,1.80,1.89,1.89,1.98,1.99,1.94,1.98,1.92,1.87,0.86,0.95,0.92,1.14,0.98,1.03,0.79,0.84,0.77,0.97,0.90,0.89,0.76,0.82,0.82,0.74,0.72,0.71,0.98,0.89,0.97,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00},
+{1.60,1.44,1.68,1.22,1.49,1.71,0.93,0.99,0.99,1.23,1.22,1.60,1.68,1.44,1.49,1.40,1.14,1.19,0.89,0.96,0.89,0.97,0.89,0.91,0.98,0.82,0.76,0.82,0.71,0.72,0.73,0.76,0.79,0.86,0.83,0.91,0.83,0.89,0.72,0.76,0.76,0.89,0.89,0.82,0.82,0.98,0.96,0.97,1.14,1.40,1.19,0.94,1.00,1.07,1.37,1.21,1.48,1.30,1.57,1.61,1.37,0.86,0.83,0.91,0.82,0.82,0.88,0.89,0.96,1.14,0.98,0.70,0.72,0.73,0.77,0.76,0.79,0.70,0.72,0.71,0.82,0.77,0.80,0.74,0.79,0.80,0.74,0.87,0.93,0.85,1.23,1.02,1.02,0.93,0.93,0.87,0.85,1.30,1.35,1.07,1.38,1.11,0.94,1.47,1.71,1.56,1.97,1.88,1.92,1.79,1.79,1.59,1.60,1.30,1.35,1.56,1.37,1.38,1.59,1.60,1.79,1.92,1.79,1.48,1.57,1.72,1.61,1.78,1.79,1.93,1.99,1.90,1.86,1.78,1.86,1.93,1.99,1.97,1.90,1.79,1.72,0.94,1.07,1.00,1.37,1.21,1.30,0.86,0.91,0.83,1.14,0.98,0.96,0.82,0.88,0.89,0.79,0.76,0.73,1.07,0.94,1.11,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00},
+{1.74,1.57,1.76,1.33,1.54,1.71,0.94,1.05,0.99,1.26,1.16,1.46,1.60,1.34,1.46,1.59,1.37,1.37,0.97,1.11,0.96,1.10,0.95,0.94,1.08,0.89,0.82,0.88,0.72,0.76,0.75,0.80,0.80,0.88,0.87,0.91,0.83,0.87,0.72,0.76,0.74,0.83,0.84,0.78,0.79,0.96,0.89,0.92,0.98,1.23,1.05,0.86,0.92,0.95,1.11,0.98,1.22,1.03,1.34,1.42,1.14,0.79,0.77,0.84,0.78,0.76,0.82,0.82,0.89,0.97,0.90,0.70,0.71,0.71,0.73,0.72,0.74,0.73,0.76,0.72,0.86,0.81,0.82,0.76,0.79,0.77,0.73,0.90,0.95,0.86,1.18,1.03,0.98,0.92,0.90,0.83,0.84,1.19,1.17,0.98,1.15,0.97,0.89,1.42,1.65,1.44,1.93,1.83,1.81,1.67,1.61,1.36,1.41,1.32,1.45,1.58,1.57,1.53,1.74,1.70,1.88,1.94,1.81,1.69,1.77,1.87,1.79,1.89,1.92,1.98,1.99,1.98,1.89,1.65,1.80,1.82,1.91,1.94,1.75,1.61,1.50,1.07,1.34,1.27,1.60,1.45,1.55,0.93,0.99,0.90,1.35,1.18,1.07,0.87,0.93,0.96,0.85,0.82,0.77,1.15,0.99,1.27,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00},
+{1.86,1.71,1.82,1.48,1.62,1.71,0.98,1.20,1.05,1.34,1.17,1.34,1.53,1.27,1.46,1.77,1.60,1.57,1.16,1.38,1.12,1.35,1.06,1.00,1.28,0.97,0.89,0.95,0.76,0.81,0.79,0.86,0.85,0.92,0.93,0.93,0.85,0.87,0.74,0.78,0.74,0.79,0.82,0.76,0.79,0.96,0.85,0.90,0.94,1.09,0.99,0.81,0.85,0.89,0.95,0.90,0.99,0.94,1.10,1.24,0.98,0.75,0.73,0.78,0.74,0.72,0.77,0.76,0.82,0.89,0.83,0.73,0.71,0.71,0.71,0.70,0.72,0.77,0.80,0.74,0.90,0.85,0.84,0.78,0.79,0.75,0.73,0.92,0.95,0.86,1.05,0.99,0.94,0.90,0.86,0.79,0.81,1.00,0.98,0.91,0.96,0.89,0.83,1.27,1.50,1.23,1.80,1.69,1.63,1.46,1.37,1.09,1.16,1.24,1.44,1.49,1.69,1.59,1.80,1.69,1.87,1.86,1.72,1.82,1.91,1.94,1.92,1.95,1.99,1.98,1.91,1.97,1.89,1.51,1.72,1.67,1.77,1.86,1.55,1.41,1.25,1.33,1.58,1.50,1.80,1.63,1.74,1.04,1.21,0.97,1.48,1.37,1.21,0.93,0.97,1.05,0.92,0.88,0.84,1.14,1.02,1.34,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00},
+{1.94,1.84,1.87,1.64,1.71,1.71,1.14,1.38,1.19,1.46,1.23,1.26,1.48,1.26,1.50,1.91,1.80,1.76,1.41,1.61,1.39,1.59,1.33,1.24,1.51,1.18,0.97,1.11,0.82,0.88,0.86,0.94,0.92,0.99,1.03,0.98,0.91,0.90,0.79,0.84,0.77,0.79,0.84,0.77,0.83,0.99,0.85,0.91,0.92,1.02,1.00,0.79,0.80,0.86,0.88,0.84,0.92,0.88,0.97,1.10,0.94,0.74,0.71,0.74,0.72,0.70,0.73,0.72,0.76,0.82,0.77,0.77,0.73,0.74,0.71,0.70,0.73,0.83,0.85,0.78,0.92,0.88,0.86,0.81,0.79,0.74,0.75,0.92,0.93,0.85,0.96,0.94,0.88,0.86,0.81,0.75,0.79,0.93,0.90,0.85,0.88,0.82,0.77,1.05,1.27,0.99,1.60,1.47,1.39,1.20,1.11,0.95,0.97,1.08,1.33,1.31,1.70,1.55,1.76,1.57,1.76,1.70,1.54,1.85,1.97,1.91,1.99,1.97,1.99,1.91,1.77,1.88,1.85,1.39,1.64,1.51,1.58,1.74,1.32,1.22,1.01,1.54,1.76,1.65,1.93,1.70,1.85,1.28,1.39,1.09,1.52,1.48,1.26,0.97,0.99,1.18,1.00,0.93,0.90,1.05,1.01,1.31,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00},
+{1.97,1.92,1.88,1.79,1.79,1.71,1.37,1.59,1.38,1.60,1.35,1.23,1.47,1.30,1.56,1.99,1.93,1.90,1.60,1.78,1.61,1.79,1.57,1.48,1.72,1.40,1.14,1.37,0.89,0.96,0.94,1.07,1.00,1.21,1.30,1.14,0.98,0.96,0.86,0.91,0.83,0.82,0.88,0.82,0.89,1.11,0.87,0.94,0.93,1.02,1.07,0.80,0.79,0.85,0.82,0.80,0.87,0.85,0.93,1.02,0.93,0.77,0.72,0.74,0.71,0.70,0.70,0.71,0.72,0.77,0.74,0.82,0.76,0.79,0.72,0.73,0.76,0.89,0.89,0.82,0.93,0.91,0.86,0.83,0.79,0.73,0.76,0.91,0.89,0.83,0.89,0.89,0.82,0.82,0.76,0.72,0.76,0.86,0.83,0.79,0.82,0.76,0.73,0.94,1.00,0.91,1.37,1.21,1.14,0.98,0.96,0.88,0.89,0.96,1.14,1.07,1.60,1.40,1.61,1.37,1.57,1.48,1.30,1.78,1.93,1.79,1.99,1.92,1.90,1.79,1.59,1.72,1.79,1.30,1.56,1.35,1.38,1.60,1.11,1.07,0.94,1.68,1.86,1.71,1.97,1.68,1.86,1.44,1.49,1.22,1.44,1.49,1.22,0.99,0.99,1.23,1.19,0.98,0.97,0.97,0.98,1.19,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00},
+{1.94,1.97,1.87,1.91,1.85,1.71,1.60,1.77,1.58,1.74,1.51,1.26,1.48,1.39,1.64,1.99,1.97,1.99,1.70,1.85,1.76,1.91,1.76,1.70,1.88,1.55,1.33,1.57,0.96,1.08,1.05,1.31,1.27,1.47,1.54,1.39,1.20,1.11,0.93,0.99,0.90,0.88,0.95,0.88,0.97,1.32,0.92,1.01,0.97,1.10,1.22,0.84,0.80,0.88,0.79,0.79,0.85,0.86,0.92,1.02,0.94,0.82,0.76,0.77,0.72,0.73,0.70,0.72,0.71,0.74,0.74,0.88,0.81,0.85,0.75,0.77,0.82,0.94,0.93,0.86,0.92,0.92,0.86,0.85,0.79,0.74,0.79,0.88,0.85,0.81,0.82,0.83,0.77,0.78,0.73,0.71,0.75,0.79,0.77,0.74,0.77,0.73,0.70,0.86,0.92,0.84,1.14,0.99,0.98,0.91,0.90,0.84,0.83,0.88,0.97,0.94,1.41,1.18,1.39,1.11,1.33,1.24,1.03,1.61,1.80,1.59,1.91,1.84,1.76,1.64,1.38,1.51,1.71,1.26,1.50,1.23,1.19,1.46,0.99,1.00,0.91,1.70,1.85,1.65,1.93,1.54,1.76,1.52,1.48,1.26,1.28,1.39,1.09,0.99,0.97,1.18,1.31,1.01,1.05,0.90,0.93,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00},
+{1.86,1.95,1.82,1.98,1.89,1.71,1.80,1.91,1.77,1.86,1.67,1.34,1.53,1.51,1.72,1.92,1.91,1.99,1.69,1.82,1.80,1.94,1.87,1.86,1.97,1.59,1.44,1.69,1.05,1.24,1.27,1.49,1.50,1.69,1.72,1.63,1.46,1.37,1.00,1.23,0.98,0.95,1.09,0.96,1.16,1.55,0.99,1.25,1.10,1.24,1.41,0.90,0.85,0.94,0.79,0.81,0.85,0.89,0.94,1.09,0.98,0.89,0.82,0.83,0.74,0.77,0.72,0.76,0.73,0.75,0.78,0.94,0.86,0.91,0.79,0.83,0.89,0.99,0.95,0.90,0.90,0.92,0.84,0.86,0.79,0.75,0.81,0.85,0.80,0.78,0.76,0.77,0.73,0.74,0.71,0.71,0.73,0.74,0.74,0.71,0.76,0.72,0.70,0.79,0.85,0.78,0.98,0.92,0.93,0.85,0.87,0.82,0.79,0.81,0.89,0.86,1.16,0.97,1.12,0.95,1.06,1.00,0.93,1.38,1.60,1.35,1.77,1.71,1.57,1.48,1.20,1.28,1.62,1.27,1.46,1.17,1.05,1.34,0.96,0.99,0.90,1.63,1.74,1.50,1.80,1.33,1.58,1.48,1.37,1.21,1.04,1.21,0.97,0.97,0.93,1.05,1.34,1.02,1.14,0.84,0.88,0.92,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00},
+{1.74,1.89,1.76,1.98,1.89,1.71,1.93,1.99,1.91,1.94,1.82,1.46,1.60,1.65,1.80,1.79,1.77,1.92,1.57,1.69,1.74,1.87,1.88,1.94,1.98,1.53,1.45,1.70,1.18,1.32,1.42,1.58,1.65,1.83,1.81,1.81,1.67,1.61,1.19,1.44,1.17,1.11,1.36,1.15,1.41,1.75,1.22,1.50,1.34,1.42,1.61,0.98,0.92,1.03,0.83,0.86,0.89,0.95,0.98,1.23,1.14,0.97,0.89,0.90,0.78,0.82,0.76,0.82,0.77,0.79,0.84,0.98,0.90,0.98,0.83,0.89,0.97,1.03,0.95,0.92,0.86,0.90,0.82,0.86,0.79,0.77,0.84,0.81,0.76,0.76,0.72,0.73,0.70,0.72,0.71,0.73,0.73,0.72,0.74,0.71,0.78,0.74,0.72,0.75,0.80,0.76,0.94,0.88,0.91,0.83,0.87,0.84,0.79,0.76,0.82,0.80,0.97,0.89,0.96,0.88,0.95,0.94,0.87,1.11,1.37,1.10,1.59,1.57,1.37,1.33,1.05,1.08,1.54,1.34,1.46,1.16,0.99,1.26,0.96,1.05,0.92,1.45,1.55,1.27,1.60,1.07,1.34,1.35,1.18,1.07,0.93,0.99,0.90,0.93,0.87,0.96,1.27,0.99,1.15,0.77,0.82,0.85,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00},
+{1.60,1.78,1.68,1.93,1.86,1.71,1.97,1.99,1.99,1.97,1.93,1.60,1.68,1.78,1.86,1.61,1.57,1.79,1.37,1.48,1.59,1.72,1.79,1.92,1.90,1.38,1.35,1.60,1.23,1.30,1.47,1.56,1.71,1.88,1.79,1.92,1.79,1.79,1.30,1.56,1.35,1.37,1.59,1.38,1.60,1.90,1.48,1.72,1.57,1.61,1.79,1.21,1.00,1.30,0.89,0.94,0.96,1.07,1.14,1.40,1.37,1.14,0.96,0.98,0.82,0.88,0.82,0.89,0.83,0.86,0.91,1.02,0.93,1.07,0.87,0.94,1.11,1.02,0.93,0.93,0.82,0.87,0.80,0.85,0.79,0.80,0.85,0.77,0.72,0.74,0.71,0.70,0.70,0.71,0.72,0.77,0.74,0.72,0.76,0.73,0.82,0.79,0.76,0.73,0.79,0.76,0.93,0.86,0.91,0.83,0.89,0.89,0.82,0.72,0.76,0.76,0.89,0.82,0.89,0.82,0.89,0.91,0.83,0.96,1.14,0.97,1.40,1.44,1.19,1.22,0.99,0.98,1.49,1.44,1.49,1.22,0.99,1.23,0.98,1.19,0.97,1.21,1.30,1.00,1.37,0.94,1.07,1.14,0.98,0.96,0.86,0.91,0.83,0.88,0.82,0.89,1.11,0.94,1.07,0.73,0.76,0.79,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00},
+{1.46,1.65,1.60,1.82,1.80,1.71,1.93,1.91,1.99,1.94,1.98,1.74,1.76,1.89,1.89,1.42,1.34,1.61,1.11,1.22,1.36,1.50,1.61,1.81,1.75,1.15,1.17,1.41,1.18,1.19,1.42,1.44,1.65,1.83,1.67,1.94,1.81,1.88,1.32,1.58,1.45,1.57,1.74,1.53,1.70,1.98,1.69,1.87,1.77,1.79,1.92,1.45,1.27,1.55,0.97,1.07,1.11,1.34,1.37,1.59,1.60,1.35,1.07,1.18,0.86,0.93,0.87,0.96,0.90,0.93,0.99,1.03,0.95,1.15,0.90,0.99,1.27,0.98,0.90,0.92,0.78,0.83,0.77,0.84,0.79,0.82,0.86,0.73,0.71,0.73,0.72,0.70,0.73,0.72,0.76,0.81,0.76,0.76,0.82,0.77,0.89,0.85,0.82,0.75,0.80,0.80,0.94,0.88,0.94,0.87,0.95,0.96,0.88,0.72,0.74,0.76,0.83,0.78,0.84,0.79,0.87,0.91,0.83,0.89,0.98,0.92,1.23,1.34,1.05,1.16,0.99,0.96,1.46,1.57,1.54,1.33,1.05,1.26,1.08,1.37,1.10,0.98,1.03,0.92,1.14,0.86,0.95,0.97,0.90,0.89,0.79,0.84,0.77,0.82,0.76,0.82,0.97,0.89,0.98,0.71,0.72,0.74,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00},
+{1.34,1.51,1.53,1.67,1.72,1.71,1.80,1.77,1.91,1.86,1.98,1.86,1.82,1.95,1.89,1.24,1.10,1.41,0.95,0.99,1.09,1.25,1.37,1.63,1.55,0.96,0.98,1.16,1.05,1.00,1.27,1.23,1.50,1.69,1.46,1.86,1.72,1.87,1.24,1.49,1.44,1.69,1.80,1.59,1.69,1.97,1.82,1.94,1.91,1.92,1.99,1.63,1.50,1.74,1.16,1.33,1.38,1.58,1.60,1.77,1.80,1.48,1.21,1.37,0.90,0.97,0.93,1.05,0.97,1.04,1.21,0.99,0.95,1.14,0.92,1.02,1.34,0.94,0.86,0.90,0.74,0.79,0.75,0.81,0.79,0.84,0.86,0.71,0.71,0.73,0.76,0.73,0.77,0.74,0.80,0.85,0.78,0.81,0.89,0.84,0.97,0.92,0.88,0.79,0.85,0.86,0.98,0.92,1.00,0.93,1.06,1.12,0.95,0.74,0.74,0.78,0.79,0.76,0.82,0.79,0.87,0.93,0.85,0.85,0.94,0.90,1.09,1.27,0.99,1.17,1.05,0.96,1.46,1.71,1.62,1.48,1.20,1.34,1.28,1.57,1.35,0.90,0.94,0.85,0.98,0.81,0.89,0.89,0.83,0.82,0.75,0.78,0.73,0.77,0.72,0.76,0.89,0.83,0.91,0.71,0.70,0.72,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00},
+{1.26,1.39,1.48,1.51,1.64,1.71,1.60,1.58,1.77,1.74,1.91,1.94,1.87,1.97,1.85,1.10,0.97,1.22,0.88,0.92,0.95,1.01,1.11,1.39,1.32,0.88,0.90,0.97,0.96,0.93,1.05,0.99,1.27,1.47,1.20,1.70,1.54,1.76,1.08,1.31,1.33,1.70,1.76,1.55,1.57,1.88,1.85,1.91,1.97,1.99,1.99,1.70,1.65,1.85,1.41,1.54,1.61,1.76,1.80,1.91,1.93,1.52,1.26,1.48,0.92,0.99,0.97,1.18,1.09,1.28,1.39,0.94,0.93,1.05,0.92,1.01,1.31,0.88,0.81,0.86,0.72,0.75,0.74,0.79,0.79,0.86,0.85,0.71,0.73,0.75,0.82,0.77,0.83,0.78,0.85,0.88,0.81,0.88,0.97,0.90,1.18,1.00,0.93,0.86,0.92,0.94,1.14,0.99,1.24,1.03,1.33,1.39,1.11,0.79,0.77,0.84,0.79,0.77,0.84,0.83,0.90,0.98,0.91,0.85,0.92,0.91,1.02,1.26,1.00,1.23,1.19,0.99,1.50,1.84,1.71,1.64,1.38,1.46,1.51,1.76,1.59,0.84,0.88,0.80,0.94,0.79,0.86,0.82,0.77,0.76,0.74,0.74,0.71,0.73,0.70,0.72,0.82,0.77,0.85,0.74,0.70,0.73,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00}
+}
--- /dev/null
+++ b/QW/client/anorms.h
@@ -1,0 +1,181 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+{-0.525731, 0.000000, 0.850651}, 
+{-0.442863, 0.238856, 0.864188}, 
+{-0.295242, 0.000000, 0.955423}, 
+{-0.309017, 0.500000, 0.809017}, 
+{-0.162460, 0.262866, 0.951056}, 
+{0.000000, 0.000000, 1.000000}, 
+{0.000000, 0.850651, 0.525731}, 
+{-0.147621, 0.716567, 0.681718}, 
+{0.147621, 0.716567, 0.681718}, 
+{0.000000, 0.525731, 0.850651}, 
+{0.309017, 0.500000, 0.809017}, 
+{0.525731, 0.000000, 0.850651}, 
+{0.295242, 0.000000, 0.955423}, 
+{0.442863, 0.238856, 0.864188}, 
+{0.162460, 0.262866, 0.951056}, 
+{-0.681718, 0.147621, 0.716567}, 
+{-0.809017, 0.309017, 0.500000}, 
+{-0.587785, 0.425325, 0.688191}, 
+{-0.850651, 0.525731, 0.000000}, 
+{-0.864188, 0.442863, 0.238856}, 
+{-0.716567, 0.681718, 0.147621}, 
+{-0.688191, 0.587785, 0.425325}, 
+{-0.500000, 0.809017, 0.309017}, 
+{-0.238856, 0.864188, 0.442863}, 
+{-0.425325, 0.688191, 0.587785}, 
+{-0.716567, 0.681718, -0.147621}, 
+{-0.500000, 0.809017, -0.309017}, 
+{-0.525731, 0.850651, 0.000000}, 
+{0.000000, 0.850651, -0.525731}, 
+{-0.238856, 0.864188, -0.442863}, 
+{0.000000, 0.955423, -0.295242}, 
+{-0.262866, 0.951056, -0.162460}, 
+{0.000000, 1.000000, 0.000000}, 
+{0.000000, 0.955423, 0.295242}, 
+{-0.262866, 0.951056, 0.162460}, 
+{0.238856, 0.864188, 0.442863}, 
+{0.262866, 0.951056, 0.162460}, 
+{0.500000, 0.809017, 0.309017}, 
+{0.238856, 0.864188, -0.442863}, 
+{0.262866, 0.951056, -0.162460}, 
+{0.500000, 0.809017, -0.309017}, 
+{0.850651, 0.525731, 0.000000}, 
+{0.716567, 0.681718, 0.147621}, 
+{0.716567, 0.681718, -0.147621}, 
+{0.525731, 0.850651, 0.000000}, 
+{0.425325, 0.688191, 0.587785}, 
+{0.864188, 0.442863, 0.238856}, 
+{0.688191, 0.587785, 0.425325}, 
+{0.809017, 0.309017, 0.500000}, 
+{0.681718, 0.147621, 0.716567}, 
+{0.587785, 0.425325, 0.688191}, 
+{0.955423, 0.295242, 0.000000}, 
+{1.000000, 0.000000, 0.000000}, 
+{0.951056, 0.162460, 0.262866}, 
+{0.850651, -0.525731, 0.000000}, 
+{0.955423, -0.295242, 0.000000}, 
+{0.864188, -0.442863, 0.238856}, 
+{0.951056, -0.162460, 0.262866}, 
+{0.809017, -0.309017, 0.500000}, 
+{0.681718, -0.147621, 0.716567}, 
+{0.850651, 0.000000, 0.525731}, 
+{0.864188, 0.442863, -0.238856}, 
+{0.809017, 0.309017, -0.500000}, 
+{0.951056, 0.162460, -0.262866}, 
+{0.525731, 0.000000, -0.850651}, 
+{0.681718, 0.147621, -0.716567}, 
+{0.681718, -0.147621, -0.716567}, 
+{0.850651, 0.000000, -0.525731}, 
+{0.809017, -0.309017, -0.500000}, 
+{0.864188, -0.442863, -0.238856}, 
+{0.951056, -0.162460, -0.262866}, 
+{0.147621, 0.716567, -0.681718}, 
+{0.309017, 0.500000, -0.809017}, 
+{0.425325, 0.688191, -0.587785}, 
+{0.442863, 0.238856, -0.864188}, 
+{0.587785, 0.425325, -0.688191}, 
+{0.688191, 0.587785, -0.425325}, 
+{-0.147621, 0.716567, -0.681718}, 
+{-0.309017, 0.500000, -0.809017}, 
+{0.000000, 0.525731, -0.850651}, 
+{-0.525731, 0.000000, -0.850651}, 
+{-0.442863, 0.238856, -0.864188}, 
+{-0.295242, 0.000000, -0.955423}, 
+{-0.162460, 0.262866, -0.951056}, 
+{0.000000, 0.000000, -1.000000}, 
+{0.295242, 0.000000, -0.955423}, 
+{0.162460, 0.262866, -0.951056}, 
+{-0.442863, -0.238856, -0.864188}, 
+{-0.309017, -0.500000, -0.809017}, 
+{-0.162460, -0.262866, -0.951056}, 
+{0.000000, -0.850651, -0.525731}, 
+{-0.147621, -0.716567, -0.681718}, 
+{0.147621, -0.716567, -0.681718}, 
+{0.000000, -0.525731, -0.850651}, 
+{0.309017, -0.500000, -0.809017}, 
+{0.442863, -0.238856, -0.864188}, 
+{0.162460, -0.262866, -0.951056}, 
+{0.238856, -0.864188, -0.442863}, 
+{0.500000, -0.809017, -0.309017}, 
+{0.425325, -0.688191, -0.587785}, 
+{0.716567, -0.681718, -0.147621}, 
+{0.688191, -0.587785, -0.425325}, 
+{0.587785, -0.425325, -0.688191}, 
+{0.000000, -0.955423, -0.295242}, 
+{0.000000, -1.000000, 0.000000}, 
+{0.262866, -0.951056, -0.162460}, 
+{0.000000, -0.850651, 0.525731}, 
+{0.000000, -0.955423, 0.295242}, 
+{0.238856, -0.864188, 0.442863}, 
+{0.262866, -0.951056, 0.162460}, 
+{0.500000, -0.809017, 0.309017}, 
+{0.716567, -0.681718, 0.147621}, 
+{0.525731, -0.850651, 0.000000}, 
+{-0.238856, -0.864188, -0.442863}, 
+{-0.500000, -0.809017, -0.309017}, 
+{-0.262866, -0.951056, -0.162460}, 
+{-0.850651, -0.525731, 0.000000}, 
+{-0.716567, -0.681718, -0.147621}, 
+{-0.716567, -0.681718, 0.147621}, 
+{-0.525731, -0.850651, 0.000000}, 
+{-0.500000, -0.809017, 0.309017}, 
+{-0.238856, -0.864188, 0.442863}, 
+{-0.262866, -0.951056, 0.162460}, 
+{-0.864188, -0.442863, 0.238856}, 
+{-0.809017, -0.309017, 0.500000}, 
+{-0.688191, -0.587785, 0.425325}, 
+{-0.681718, -0.147621, 0.716567}, 
+{-0.442863, -0.238856, 0.864188}, 
+{-0.587785, -0.425325, 0.688191}, 
+{-0.309017, -0.500000, 0.809017}, 
+{-0.147621, -0.716567, 0.681718}, 
+{-0.425325, -0.688191, 0.587785}, 
+{-0.162460, -0.262866, 0.951056}, 
+{0.442863, -0.238856, 0.864188}, 
+{0.162460, -0.262866, 0.951056}, 
+{0.309017, -0.500000, 0.809017}, 
+{0.147621, -0.716567, 0.681718}, 
+{0.000000, -0.525731, 0.850651}, 
+{0.425325, -0.688191, 0.587785}, 
+{0.587785, -0.425325, 0.688191}, 
+{0.688191, -0.587785, 0.425325}, 
+{-0.955423, 0.295242, 0.000000}, 
+{-0.951056, 0.162460, 0.262866}, 
+{-1.000000, 0.000000, 0.000000}, 
+{-0.850651, 0.000000, 0.525731}, 
+{-0.955423, -0.295242, 0.000000}, 
+{-0.951056, -0.162460, 0.262866}, 
+{-0.864188, 0.442863, -0.238856}, 
+{-0.951056, 0.162460, -0.262866}, 
+{-0.809017, 0.309017, -0.500000}, 
+{-0.864188, -0.442863, -0.238856}, 
+{-0.951056, -0.162460, -0.262866}, 
+{-0.809017, -0.309017, -0.500000}, 
+{-0.681718, 0.147621, -0.716567}, 
+{-0.681718, -0.147621, -0.716567}, 
+{-0.850651, 0.000000, -0.525731}, 
+{-0.688191, 0.587785, -0.425325}, 
+{-0.587785, 0.425325, -0.688191}, 
+{-0.425325, 0.688191, -0.587785}, 
+{-0.425325, -0.688191, -0.587785}, 
+{-0.587785, -0.425325, -0.688191}, 
+{-0.688191, -0.587785, -0.425325}, 
--- /dev/null
+++ b/QW/client/asm_draw.h
@@ -1,0 +1,151 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+//
+// asm_draw.h
+//
+// Include file for asm drawing routines.
+//
+
+//
+// !!! note that this file must match the corresponding C structures at all
+// times !!!
+//
+
+// !!! if this is changed, it must be changed in r_local.h too !!!
+#define	NEAR_CLIP	0.01
+
+// !!! if this is changed, it must be changed in r_local.h too !!!
+#define	CYCLE	128
+
+// espan_t structure
+// !!! if this is changed, it must be changed in r_shared.h too !!!
+#define espan_t_u    	0
+#define espan_t_v	    4
+#define espan_t_count   8
+#define espan_t_pnext	12
+#define espan_t_size    16
+
+// sspan_t structure
+// !!! if this is changed, it must be changed in d_local.h too !!!
+#define sspan_t_u    	0
+#define sspan_t_v	    4
+#define sspan_t_count   8
+#define sspan_t_size    12
+
+// spanpackage_t structure
+// !!! if this is changed, it must be changed in d_polyset.c too !!!
+#define spanpackage_t_pdest				0
+#define spanpackage_t_pz				4
+#define spanpackage_t_count				8
+#define spanpackage_t_ptex				12
+#define spanpackage_t_sfrac				16
+#define spanpackage_t_tfrac				20
+#define spanpackage_t_light				24
+#define spanpackage_t_zi				28
+#define spanpackage_t_size				32 
+
+// edge_t structure
+// !!! if this is changed, it must be changed in r_shared.h too !!!
+#define et_u			0
+#define et_u_step		4
+#define et_prev			8
+#define et_next			12
+#define et_surfs		16
+#define et_nextremove	20
+#define et_nearzi		24
+#define et_owner		28
+#define et_size			32
+
+// surf_t structure
+// !!! if this is changed, it must be changed in r_shared.h too !!!
+#define SURF_T_SHIFT	6
+#define st_next			0
+#define st_prev			4
+#define st_spans		8
+#define st_key			12
+#define st_last_u		16
+#define st_spanstate	20
+#define st_flags		24
+#define st_data			28
+#define st_entity		32
+#define st_nearzi		36
+#define st_insubmodel	40
+#define st_d_ziorigin	44
+#define st_d_zistepu	48
+#define st_d_zistepv	52
+#define st_pad			56
+#define st_size			64
+
+// clipplane_t structure
+// !!! if this is changed, it must be changed in r_local.h too !!!
+#define cp_normal		0
+#define cp_dist			12
+#define cp_next			16
+#define cp_leftedge		20
+#define cp_rightedge	21
+#define cp_reserved		22
+#define cp_size			24
+
+// medge_t structure
+// !!! if this is changed, it must be changed in model.h too !!!
+#define me_v				0
+#define me_cachededgeoffset	4
+#define me_size				8
+
+// mvertex_t structure
+// !!! if this is changed, it must be changed in model.h too !!!
+#define mv_position		0
+#define mv_size			12
+
+// refdef_t structure
+// !!! if this is changed, it must be changed in render.h too !!!
+#define rd_vrect					0
+#define rd_aliasvrect				20
+#define rd_vrectright				40
+#define rd_vrectbottom				44
+#define rd_aliasvrectright			48
+#define rd_aliasvrectbottom			52
+#define rd_vrectrightedge			56
+#define rd_fvrectx					60
+#define rd_fvrecty					64
+#define rd_fvrectx_adj				68
+#define rd_fvrecty_adj				72
+#define rd_vrect_x_adj_shift20		76
+#define rd_vrectright_adj_shift20	80
+#define rd_fvrectright_adj			84
+#define rd_fvrectbottom_adj			88
+#define rd_fvrectright				92
+#define rd_fvrectbottom				96
+#define rd_horizontalFieldOfView	100
+#define rd_xOrigin					104
+#define rd_yOrigin					108
+#define rd_vieworg					112
+#define rd_viewangles				124
+#define rd_ambientlight				136
+#define rd_size						140
+
+// mtriangle_t structure
+// !!! if this is changed, it must be changed in model.h too !!!
+#define mtri_facesfront		0
+#define mtri_vertindex		4
+#define mtri_size			16	// !!! if this changes, array indexing in !!!
+								// !!! d_polysa.s must be changed to match !!!
+#define mtri_shift			4
+
--- /dev/null
+++ b/QW/client/asm_i386.h
@@ -1,0 +1,97 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+
+#ifndef __ASM_I386__
+#define __ASM_I386__
+
+#ifdef ELF
+#define C(label) label
+#else
+#define C(label) _##label
+#endif
+
+//
+// !!! note that this file must match the corresponding C structures at all
+// times !!!
+//
+
+// plane_t structure
+// !!! if this is changed, it must be changed in model.h too !!!
+// !!! if the size of this is changed, the array lookup in SV_HullPointContents
+//     must be changed too !!!
+#define pl_normal	0
+#define pl_dist		12
+#define pl_type		16
+#define pl_signbits	17
+#define pl_pad		18
+#define pl_size		20
+
+// hull_t structure
+// !!! if this is changed, it must be changed in model.h too !!!
+#define	hu_clipnodes		0
+#define	hu_planes			4
+#define	hu_firstclipnode	8
+#define	hu_lastclipnode		12
+#define	hu_clip_mins		16
+#define	hu_clip_maxs		28
+#define hu_size  			40
+
+// dnode_t structure
+// !!! if this is changed, it must be changed in bspfile.h too !!!
+#define	nd_planenum		0
+#define	nd_children		4
+#define	nd_mins			8
+#define	nd_maxs			20
+#define	nd_firstface	32
+#define	nd_numfaces		36
+#define nd_size			40
+
+// sfxcache_t structure
+// !!! if this is changed, it much be changed in sound.h too !!!
+#define sfxc_length		0
+#define sfxc_loopstart	4
+#define sfxc_speed		8
+#define sfxc_width		12
+#define sfxc_stereo		16
+#define sfxc_data		20
+
+// channel_t structure
+// !!! if this is changed, it much be changed in sound.h too !!!
+#define ch_sfx			0
+#define ch_leftvol		4
+#define ch_rightvol		8
+#define ch_end			12
+#define ch_pos			16
+#define ch_looping		20
+#define ch_entnum		24
+#define ch_entchannel	28
+#define ch_origin		32
+#define ch_dist_mult	44
+#define ch_master_vol	48
+#define ch_size			52
+
+// portable_samplepair_t structure
+// !!! if this is changed, it much be changed in sound.h too !!!
+#define psp_left		0
+#define psp_right		4
+#define psp_size		8
+
+#endif
+
--- /dev/null
+++ b/QW/client/block16.h
@@ -1,0 +1,123 @@
+LEnter16_16:
+	movb	(%esi),%al
+	movb	(%esi,%ebx,),%cl
+	movb	%dh,%ah
+	addl	%ebp,%edx
+	movb	%dh,%ch
+	leal	(%esi,%ebx,2),%esi
+	movw	0x12345678(,%eax,2),%ax
+LBPatch0:
+	addl	%ebp,%edx
+	movw	%ax,(%edi)
+	movw	0x12345678(,%ecx,2),%cx
+LBPatch1:
+	movw	%cx,2(%edi)
+	addl	$0x4,%edi
+
+	movb	(%esi),%al
+	movb	(%esi,%ebx,),%cl
+	movb	%dh,%ah
+	addl	%ebp,%edx
+	movb	%dh,%ch
+	leal	(%esi,%ebx,2),%esi
+	movw	0x12345678(,%eax,2),%ax
+LBPatch2:
+	addl	%ebp,%edx
+	movw	%ax,(%edi)
+	movw	0x12345678(,%ecx,2),%cx
+LBPatch3:
+	movw	%cx,2(%edi)
+	addl	$0x4,%edi
+
+	movb	(%esi),%al
+	movb	(%esi,%ebx,),%cl
+	movb	%dh,%ah
+	addl	%ebp,%edx
+	movb	%dh,%ch
+	leal	(%esi,%ebx,2),%esi
+	movw	0x12345678(,%eax,2),%ax
+LBPatch4:
+	addl	%ebp,%edx
+	movw	%ax,(%edi)
+	movw	0x12345678(,%ecx,2),%cx
+LBPatch5:
+	movw	%cx,2(%edi)
+	addl	$0x4,%edi
+
+	movb	(%esi),%al
+	movb	(%esi,%ebx,),%cl
+	movb	%dh,%ah
+	addl	%ebp,%edx
+	movb	%dh,%ch
+	leal	(%esi,%ebx,2),%esi
+	movw	0x12345678(,%eax,2),%ax
+LBPatch6:
+	addl	%ebp,%edx
+	movw	%ax,(%edi)
+	movw	0x12345678(,%ecx,2),%cx
+LBPatch7:
+	movw	%cx,2(%edi)
+	addl	$0x4,%edi
+
+LEnter8_16:
+	movb	(%esi),%al
+	movb	(%esi,%ebx,),%cl
+	movb	%dh,%ah
+	addl	%ebp,%edx
+	movb	%dh,%ch
+	leal	(%esi,%ebx,2),%esi
+	movw	0x12345678(,%eax,2),%ax
+LBPatch8:
+	addl	%ebp,%edx
+	movw	%ax,(%edi)
+	movw	0x12345678(,%ecx,2),%cx
+LBPatch9:
+	movw	%cx,2(%edi)
+	addl	$0x4,%edi
+
+	movb	(%esi),%al
+	movb	(%esi,%ebx,),%cl
+	movb	%dh,%ah
+	addl	%ebp,%edx
+	movb	%dh,%ch
+	leal	(%esi,%ebx,2),%esi
+	movw	0x12345678(,%eax,2),%ax
+LBPatch10:
+	addl	%ebp,%edx
+	movw	%ax,(%edi)
+	movw	0x12345678(,%ecx,2),%cx
+LBPatch11:
+	movw	%cx,2(%edi)
+	addl	$0x4,%edi
+
+LEnter4_16:
+	movb	(%esi),%al
+	movb	(%esi,%ebx,),%cl
+	movb	%dh,%ah
+	addl	%ebp,%edx
+	movb	%dh,%ch
+	leal	(%esi,%ebx,2),%esi
+	movw	0x12345678(,%eax,2),%ax
+LBPatch12:
+	addl	%ebp,%edx
+	movw	%ax,(%edi)
+	movw	0x12345678(,%ecx,2),%cx
+LBPatch13:
+	movw	%cx,2(%edi)
+	addl	$0x4,%edi
+
+LEnter2_16:
+	movb	(%esi),%al
+	movb	(%esi,%ebx,),%cl
+	movb	%dh,%ah
+	addl	%ebp,%edx
+	movb	%dh,%ch
+	leal	(%esi,%ebx,2),%esi
+	movw	0x12345678(,%eax,2),%ax
+LBPatch14:
+	addl	%ebp,%edx
+	movw	%ax,(%edi)
+	movw	0x12345678(,%ecx,2),%cx
+LBPatch15:
+	movw	%cx,2(%edi)
+	addl	$0x4,%edi
--- /dev/null
+++ b/QW/client/block8.h
@@ -1,0 +1,124 @@
+LEnter16_8:
+	movb	(%esi),%al
+	movb	(%esi,%ebx,),%cl
+	movb	%dh,%ah
+	addl	%ebp,%edx
+	movb	%dh,%ch
+	leal	(%esi,%ebx,2),%esi
+	movb	0x12345678(%eax),%al
+LBPatch0:
+	addl	%ebp,%edx
+	movb	%al,(%edi)
+	movb	0x12345678(%ecx),%cl
+LBPatch1:
+	movb	%cl,1(%edi)
+	addl	$0x2,%edi
+
+	movb	(%esi),%al
+	movb	(%esi,%ebx,),%cl
+	movb	%dh,%ah
+	addl	%ebp,%edx
+	movb	%dh,%ch
+	leal	(%esi,%ebx,2),%esi
+	movb	0x12345678(%eax),%al
+LBPatch2:
+	addl	%ebp,%edx
+	movb	%al,(%edi)
+	movb	0x12345678(%ecx),%cl
+LBPatch3:
+	movb	%cl,1(%edi)
+	addl	$0x2,%edi
+
+	movb	(%esi),%al
+	movb	(%esi,%ebx,),%cl
+	movb	%dh,%ah
+	addl	%ebp,%edx
+	movb	%dh,%ch
+	leal	(%esi,%ebx,2),%esi
+	movb	0x12345678(%eax),%al
+LBPatch4:
+	addl	%ebp,%edx
+	movb	%al,(%edi)
+	movb	0x12345678(%ecx),%cl
+LBPatch5:
+	movb	%cl,1(%edi)
+	addl	$0x2,%edi
+
+	movb	(%esi),%al
+	movb	(%esi,%ebx,),%cl
+	movb	%dh,%ah
+	addl	%ebp,%edx
+	movb	%dh,%ch
+	leal	(%esi,%ebx,2),%esi
+	movb	0x12345678(%eax),%al
+LBPatch6:
+	addl	%ebp,%edx
+	movb	%al,(%edi)
+	movb	0x12345678(%ecx),%cl
+LBPatch7:
+	movb	%cl,1(%edi)
+	addl	$0x2,%edi
+
+LEnter8_8:
+	movb	(%esi),%al
+	movb	(%esi,%ebx,),%cl
+	movb	%dh,%ah
+	addl	%ebp,%edx
+	movb	%dh,%ch
+	leal	(%esi,%ebx,2),%esi
+	movb	0x12345678(%eax),%al
+LBPatch8:
+	addl	%ebp,%edx
+	movb	%al,(%edi)
+	movb	0x12345678(%ecx),%cl
+LBPatch9:
+	movb	%cl,1(%edi)
+	addl	$0x2,%edi
+
+	movb	(%esi),%al
+	movb	(%esi,%ebx,),%cl
+	movb	%dh,%ah
+	addl	%ebp,%edx
+	movb	%dh,%ch
+	leal	(%esi,%ebx,2),%esi
+	movb	0x12345678(%eax),%al
+LBPatch10:
+	addl	%ebp,%edx
+	movb	%al,(%edi)
+	movb	0x12345678(%ecx),%cl
+LBPatch11:
+	movb	%cl,1(%edi)
+	addl	$0x2,%edi
+
+LEnter4_8:
+	movb	(%esi),%al
+	movb	(%esi,%ebx,),%cl
+	movb	%dh,%ah
+	addl	%ebp,%edx
+	movb	%dh,%ch
+	leal	(%esi,%ebx,2),%esi
+	movb	0x12345678(%eax),%al
+LBPatch12:
+	addl	%ebp,%edx
+	movb	%al,(%edi)
+	movb	0x12345678(%ecx),%cl
+LBPatch13:
+	movb	%cl,1(%edi)
+	addl	$0x2,%edi
+
+LEnter2_8:
+	movb	(%esi),%al
+	movb	(%esi,%ebx,),%cl
+	movb	%dh,%ah
+	addl	%ebp,%edx
+	movb	%dh,%ch
+	leal	(%esi,%ebx,2),%esi
+	movb	0x12345678(%eax),%al
+LBPatch14:
+	addl	%ebp,%edx
+	movb	%al,(%edi)
+	movb	0x12345678(%ecx),%cl
+LBPatch15:
+	movb	%cl,1(%edi)
+	addl	$0x2,%edi
+
--- /dev/null
+++ b/QW/client/bothdefs.h
@@ -1,0 +1,157 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+
+// defs common to client and server
+
+#define GLQUAKE_VERSION 1.00
+#define	VERSION		2.40
+#define LINUX_VERSION 0.98
+
+
+#if (defined(_M_IX86) || defined(__i386__)) && !defined(id386)
+#define id386	1
+#else
+#define id386	0
+#endif
+
+#ifdef SERVERONLY		// no asm in dedicated server
+#undef id386
+#endif
+
+#if id386
+#define UNALIGNED_OK	1	// set to 0 if unaligned accesses are not supported
+#else
+#define UNALIGNED_OK	0
+#endif
+
+// !!! if this is changed, it must be changed in d_ifacea.h too !!!
+#define CACHE_SIZE	32		// used to align key data structures
+
+#define UNUSED(x)	(x = x)	// for pesky compiler / lint warnings
+
+#define	MINIMUM_MEMORY	0x550000
+
+// up / down
+#define	PITCH	0
+
+// left / right
+#define	YAW		1
+
+// fall over
+#define	ROLL	2
+
+
+#define	MAX_SCOREBOARD		16		// max numbers of players
+
+#define	SOUND_CHANNELS		8
+
+
+#define	MAX_QPATH		64			// max length of a quake game pathname
+#define	MAX_OSPATH		128			// max length of a filesystem pathname
+
+#define	ON_EPSILON		0.1			// point on plane side epsilon
+
+#define	MAX_MSGLEN		1450		// max length of a reliable message
+#define	MAX_DATAGRAM	1450		// max length of unreliable message
+
+//
+// per-level limits
+//
+#define	MAX_EDICTS		768			// FIXME: ouch! ouch! ouch!
+#define	MAX_LIGHTSTYLES	64
+#define	MAX_MODELS		256			// these are sent over the net as bytes
+#define	MAX_SOUNDS		256			// so they cannot be blindly increased
+
+#define	SAVEGAME_COMMENT_LENGTH	39
+
+#define	MAX_STYLESTRING	64
+
+//
+// stats are integers communicated to the client by the server
+//
+#define	MAX_CL_STATS		32
+#define	STAT_HEALTH			0
+//define	STAT_FRAGS			1
+#define	STAT_WEAPON			2
+#define	STAT_AMMO			3
+#define	STAT_ARMOR			4
+//define	STAT_WEAPONFRAME	5
+#define	STAT_SHELLS			6
+#define	STAT_NAILS			7
+#define	STAT_ROCKETS		8
+#define	STAT_CELLS			9
+#define	STAT_ACTIVEWEAPON	10
+#define	STAT_TOTALSECRETS	11
+#define	STAT_TOTALMONSTERS	12
+#define	STAT_SECRETS		13		// bumped on client side by svc_foundsecret
+#define	STAT_MONSTERS		14		// bumped by svc_killedmonster
+#define	STAT_ITEMS			15
+//define	STAT_VIEWHEIGHT		16
+
+
+//
+// item flags
+//
+#define	IT_SHOTGUN				1
+#define	IT_SUPER_SHOTGUN		2
+#define	IT_NAILGUN				4
+#define	IT_SUPER_NAILGUN		8
+
+#define	IT_GRENADE_LAUNCHER		16
+#define	IT_ROCKET_LAUNCHER		32
+#define	IT_LIGHTNING			64
+#define	IT_SUPER_LIGHTNING		128
+
+#define	IT_SHELLS				256
+#define	IT_NAILS				512
+#define	IT_ROCKETS				1024
+#define	IT_CELLS				2048
+
+#define	IT_AXE					4096
+
+#define	IT_ARMOR1				8192
+#define	IT_ARMOR2				16384
+#define	IT_ARMOR3				32768
+
+#define	IT_SUPERHEALTH			65536
+
+#define	IT_KEY1					131072
+#define	IT_KEY2					262144
+
+#define	IT_INVISIBILITY			524288
+
+#define	IT_INVULNERABILITY		1048576
+#define	IT_SUIT					2097152
+#define	IT_QUAD					4194304
+
+#define	IT_SIGIL1				(1<<28)
+
+#define	IT_SIGIL2				(1<<29)
+#define	IT_SIGIL3				(1<<30)
+#define	IT_SIGIL4				(1<<31)
+
+//
+// print flags
+//
+#define	PRINT_LOW			0		// pickup messages
+#define	PRINT_MEDIUM		1		// death messages
+#define	PRINT_HIGH			2		// critical messages
+#define	PRINT_CHAT			3		// chat messages
+
--- /dev/null
+++ b/QW/client/bspfile.h
@@ -1,0 +1,271 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+
+
+// upper design bounds
+
+#define	MAX_MAP_HULLS		4
+
+#define	MAX_MAP_MODELS		256
+#define	MAX_MAP_BRUSHES		4096
+#define	MAX_MAP_ENTITIES	1024
+#define	MAX_MAP_ENTSTRING	65536
+
+#define	MAX_MAP_PLANES		8192
+#define	MAX_MAP_NODES		32767		// because negative shorts are contents
+#define	MAX_MAP_CLIPNODES	32767		//
+#define	MAX_MAP_LEAFS		32767		// 
+#define	MAX_MAP_VERTS		65535
+#define	MAX_MAP_FACES		65535
+#define	MAX_MAP_MARKSURFACES 65535
+#define	MAX_MAP_TEXINFO		4096
+#define	MAX_MAP_EDGES		256000
+#define	MAX_MAP_SURFEDGES	512000
+#define	MAX_MAP_MIPTEX		0x200000
+#define	MAX_MAP_LIGHTING	0x100000
+#define	MAX_MAP_VISIBILITY	0x100000
+
+// key / value pair sizes
+
+#define	MAX_KEY		32
+#define	MAX_VALUE	1024
+
+
+//=============================================================================
+
+
+#define BSPVERSION	29
+
+typedef struct
+{
+	int		fileofs, filelen;
+} lump_t;
+
+#define	LUMP_ENTITIES	0
+#define	LUMP_PLANES		1
+#define	LUMP_TEXTURES	2
+#define	LUMP_VERTEXES	3
+#define	LUMP_VISIBILITY	4
+#define	LUMP_NODES		5
+#define	LUMP_TEXINFO	6
+#define	LUMP_FACES		7
+#define	LUMP_LIGHTING	8
+#define	LUMP_CLIPNODES	9
+#define	LUMP_LEAFS		10
+#define	LUMP_MARKSURFACES 11
+#define	LUMP_EDGES		12
+#define	LUMP_SURFEDGES	13
+#define	LUMP_MODELS		14
+
+#define	HEADER_LUMPS	15
+
+typedef struct
+{
+	float		mins[3], maxs[3];
+	float		origin[3];
+	int			headnode[MAX_MAP_HULLS];
+	int			visleafs;		// not including the solid leaf 0
+	int			firstface, numfaces;
+} dmodel_t;
+
+typedef struct
+{
+	int			version;	
+	lump_t		lumps[HEADER_LUMPS];
+} dheader_t;
+
+typedef struct
+{
+	int			nummiptex;
+	int			dataofs[4];		// [nummiptex]
+} dmiptexlump_t;
+
+#define	MIPLEVELS	4
+typedef struct miptex_s
+{
+	char		name[16];
+	unsigned	width, height;
+	unsigned	offsets[MIPLEVELS];		// four mip maps stored
+} miptex_t;
+
+
+typedef struct
+{
+	float	point[3];
+} dvertex_t;
+
+
+// 0-2 are axial planes
+#define	PLANE_X			0
+#define	PLANE_Y			1
+#define	PLANE_Z			2
+
+// 3-5 are non-axial planes snapped to the nearest
+#define	PLANE_ANYX		3
+#define	PLANE_ANYY		4
+#define	PLANE_ANYZ		5
+
+typedef struct
+{
+	float	normal[3];
+	float	dist;
+	int		type;		// PLANE_X - PLANE_ANYZ ?remove? trivial to regenerate
+} dplane_t;
+
+
+
+#define	CONTENTS_EMPTY		-1
+#define	CONTENTS_SOLID		-2
+#define	CONTENTS_WATER		-3
+#define	CONTENTS_SLIME		-4
+#define	CONTENTS_LAVA		-5
+#define	CONTENTS_SKY		-6
+
+// !!! if this is changed, it must be changed in asm_i386.h too !!!
+typedef struct
+{
+	int			planenum;
+	short		children[2];	// negative numbers are -(leafs+1), not nodes
+	short		mins[3];		// for sphere culling
+	short		maxs[3];
+	unsigned short	firstface;
+	unsigned short	numfaces;	// counting both sides
+} dnode_t;
+
+typedef struct
+{
+	int			planenum;
+	short		children[2];	// negative numbers are contents
+} dclipnode_t;
+
+
+typedef struct texinfo_s
+{
+	float		vecs[2][4];		// [s/t][xyz offset]
+	int			miptex;
+	int			flags;
+} texinfo_t;
+#define	TEX_SPECIAL		1		// sky or slime, no lightmap or 256 subdivision
+
+// note that edge 0 is never used, because negative edge nums are used for
+// counterclockwise use of the edge in a face
+typedef struct
+{
+	unsigned short	v[2];		// vertex numbers
+} dedge_t;
+
+#define	MAXLIGHTMAPS	4
+typedef struct
+{
+	short		planenum;
+	short		side;
+
+	int			firstedge;		// we must support > 64k edges
+	short		numedges;	
+	short		texinfo;
+
+// lighting info
+	byte		styles[MAXLIGHTMAPS];
+	int			lightofs;		// start of [numstyles*surfsize] samples
+} dface_t;
+
+
+
+#define	AMBIENT_WATER	0
+#define	AMBIENT_SKY		1
+#define	AMBIENT_SLIME	2
+#define	AMBIENT_LAVA	3
+
+#define	NUM_AMBIENTS			4		// automatic ambient sounds
+
+// leaf 0 is the generic CONTENTS_SOLID leaf, used for all solid areas
+// all other leafs need visibility info
+typedef struct
+{
+	int			contents;
+	int			visofs;				// -1 = no visibility info
+
+	short		mins[3];			// for frustum culling
+	short		maxs[3];
+
+	unsigned short		firstmarksurface;
+	unsigned short		nummarksurfaces;
+
+	byte		ambient_level[NUM_AMBIENTS];
+} dleaf_t;
+
+//============================================================================
+
+#ifndef QUAKE_GAME
+
+// the utilities get to be lazy and just use large static arrays
+
+extern	int			nummodels;
+extern	dmodel_t	dmodels[MAX_MAP_MODELS];
+
+extern	int			visdatasize;
+extern	byte		dvisdata[MAX_MAP_VISIBILITY];
+
+extern	int			lightdatasize;
+extern	byte		dlightdata[MAX_MAP_LIGHTING];
+
+extern	int			texdatasize;
+extern	byte		dtexdata[MAX_MAP_MIPTEX]; // (dmiptexlump_t)
+
+extern	int			entdatasize;
+extern	char		dentdata[MAX_MAP_ENTSTRING];
+
+extern	int			numleafs;
+extern	dleaf_t		dleafs[MAX_MAP_LEAFS];
+
+extern	int			numplanes;
+extern	dplane_t	dplanes[MAX_MAP_PLANES];
+
+extern	int			numvertexes;
+extern	dvertex_t	dvertexes[MAX_MAP_VERTS];
+
+extern	int			numnodes;
+extern	dnode_t		dnodes[MAX_MAP_NODES];
+
+extern	int			numtexinfo;
+extern	texinfo_t	texinfo[MAX_MAP_TEXINFO];
+
+extern	int			numfaces;
+extern	dface_t		dfaces[MAX_MAP_FACES];
+
+extern	int			numclipnodes;
+extern	dclipnode_t	dclipnodes[MAX_MAP_CLIPNODES];
+
+extern	int			numedges;
+extern	dedge_t		dedges[MAX_MAP_EDGES];
+
+extern	int			nummarksurfaces;
+extern	unsigned short	dmarksurfaces[MAX_MAP_MARKSURFACES];
+
+extern	int			numsurfedges;
+extern	int			dsurfedges[MAX_MAP_SURFEDGES];
+
+
+
+void	LoadBSPFile (char *filename);
+void	WriteBSPFile (char *filename);
+void	PrintBSPFileSizes (void);
+
+#endif
--- /dev/null
+++ b/QW/client/buildnum.c
@@ -1,0 +1,76 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the included (GNU.txt) GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+#include <stdlib.h>
+#include <string.h>
+
+#include <quakedef.h>
+
+// char *date = "Oct 24 1996";
+// char *time = "13:22:52";
+char *date = __DATE__ ;
+char *time = __TIME__ ;
+
+char *mon[12] = 
+{ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
+char mond[12] = 
+{ 31,    28,    31,    30,    31,    30,    31,    31,    30,    31,    30,    31 };
+
+// returns days since Oct 24 1996
+int build_number( void )
+{
+	int m = 0; 
+	int d = 0;
+	int y = 0;
+	int hr, min;
+	static int b = 0;
+
+	if (b != 0)
+		return b;
+
+	for (m = 0; m < 11; m++)
+	{
+		if (_strnicmp( &date[0], mon[m], 3 ) == 0)
+			break;
+		d += mond[m];
+	}
+
+	d += atoi( &date[4] ) - 1;
+
+	y = atoi( &date[7] ) - 1900;
+
+	b = d + (int)((y - 1) * 365.25);
+
+	if (((y % 4) == 0) && m > 1)
+	{
+		b += 1;
+	}
+
+	b -= 34995; // Oct 24 1996
+
+	hr = (time[0] - '0') * 10 + (time[1] - '0');
+	min = (time[3] - '0') * 10 + (time[4] - '0');
+//	sec = (time[6] - '0') * 10 + (time[7] - '0');
+
+	b *= 60*24;
+	b += hr * 60 + min;
+
+	return b;
+}
+
--- /dev/null
+++ b/QW/client/cd_audio.c
@@ -1,0 +1,847 @@
+#include <dpmi.h>
+#include "quakedef.h"
+#include "dosisms.h"
+
+extern	cvar_t	bgmvolume;
+
+#define ADDRESS_MODE_HSG		0
+#define ADDRESS_MODE_RED_BOOK	1
+
+#define STATUS_ERROR_BIT	0x8000
+#define STATUS_BUSY_BIT		0x0200
+#define STATUS_DONE_BIT		0x0100
+#define STATUS_ERROR_MASK	0x00ff
+
+#define ERROR_WRITE_PROTECT		0
+#define ERROR_UNKNOWN_UNIT		1
+#define ERROR_DRIVE_NOT_READY	2
+#define ERROR_UNKNOWN_COMMAND	3
+#define ERROR_CRC_ERROR			4
+#define ERROR_BAD_REQUEST_LEN	5
+#define ERROR_SEEK_ERROR		6
+#define ERROR_UNKNOWN_MEDIA		7
+#define ERROR_SECTOR_NOT_FOUND	8
+#define ERROR_OUT_OF_PAPER		9
+#define ERROR_WRITE_FAULT		10
+#define ERROR_READ_FAULT		11
+#define ERROR_GENERAL_FAILURE	12
+#define ERROR_RESERVED_13		13
+#define ERROR_RESERVED_14		14
+#define ERROR_BAD_DISK_CHANGE	15
+
+#define COMMAND_READ			3
+#define COMMAND_WRITE			12
+#define COMMAND_PLAY_AUDIO		132
+#define COMMAND_STOP_AUDIO		133
+#define COMMAND_RESUME_AUDIO	136
+
+#define READ_REQUEST_AUDIO_CHANNEL_INFO		4
+#define READ_REQUEST_DEVICE_STATUS			6
+#define READ_REQUEST_MEDIA_CHANGE			9
+#define READ_REQUEST_AUDIO_DISK_INFO		10
+#define READ_REQUEST_AUDIO_TRACK_INFO		11
+#define READ_REQUEST_AUDIO_STATUS			15
+
+#define WRITE_REQUEST_EJECT					0
+#define WRITE_REQUEST_RESET					2
+#define WRITE_REQUEST_AUDIO_CHANNEL_INFO	3
+
+#define STATUS_DOOR_OPEN					0x00000001
+#define STATUS_DOOR_UNLOCKED				0x00000002
+#define STATUS_RAW_SUPPORT					0x00000004
+#define STATUS_READ_WRITE					0x00000008
+#define STATUS_AUDIO_SUPPORT				0x00000010
+#define STATUS_INTERLEAVE_SUPPORT			0x00000020
+#define STATUS_BIT_6_RESERVED				0x00000040
+#define STATUS_PREFETCH_SUPPORT				0x00000080
+#define STATUS_AUDIO_MANIPLUATION_SUPPORT	0x00000100
+#define STATUS_RED_BOOK_ADDRESS_SUPPORT		0x00000200
+
+#define MEDIA_NOT_CHANGED		1
+#define MEDIA_STATUS_UNKNOWN	0
+#define MEDIA_CHANGED			-1
+
+#define AUDIO_CONTROL_MASK				0xd0
+#define AUDIO_CONTROL_DATA_TRACK		0x40
+#define AUDIO_CONTROL_AUDIO_2_TRACK		0x00
+#define AUDIO_CONTROL_AUDIO_2P_TRACK	0x10
+#define AUDIO_CONTROL_AUDIO_4_TRACK		0x80
+#define AUDIO_CONTROL_AUDIO_4P_TRACK	0x90
+
+#define AUDIO_STATUS_PAUSED				0x0001
+
+#pragma pack(1)
+
+struct playAudioRequest
+{
+	char	addressingMode;
+	int		startLocation;
+	int		sectors;
+};
+
+struct readRequest
+{
+	char	mediaDescriptor;
+	short	bufferOffset;
+	short	bufferSegment;
+	short	length;
+	short	startSector;
+	int		volumeID;
+};
+
+struct writeRequest
+{
+	char	mediaDescriptor;
+	short	bufferOffset;
+	short	bufferSegment;
+	short	length;
+	short	startSector;
+	int		volumeID;
+};
+
+struct cd_request
+{
+	char	headerLength;
+	char	unit;
+	char	command;
+	short	status;
+	char	reserved[8];
+	union
+	{
+		struct	playAudioRequest	playAudio;
+		struct	readRequest			read;
+		struct	writeRequest		write;
+	} x;
+};
+
+
+struct audioChannelInfo_s
+{
+	char	code;
+	char	channel0input;
+	char	channel0volume;
+	char	channel1input;
+	char	channel1volume;
+	char	channel2input;
+	char	channel2volume;
+	char	channel3input;
+	char	channel3volume;
+};
+
+struct deviceStatus_s
+{
+	char	code;
+	int		status;
+};
+
+struct mediaChange_s
+{
+	char	code;
+	char	status;
+};
+
+struct audioDiskInfo_s
+{
+	char	code;
+	char	lowTrack;
+	char	highTrack;
+	int		leadOutStart;
+};
+
+struct audioTrackInfo_s
+{
+	char	code;
+	char	track;
+	int		start;
+	char	control;
+};
+
+struct audioStatus_s
+{
+	char	code;
+	short	status;
+	int		PRstartLocation;
+	int		PRendLocation;
+};
+
+struct reset_s
+{
+	char	code;
+};
+
+union readInfo_u
+{
+	struct audioChannelInfo_s	audioChannelInfo;
+	struct deviceStatus_s		deviceStatus;
+	struct mediaChange_s		mediaChange;
+	struct audioDiskInfo_s		audioDiskInfo;
+	struct audioTrackInfo_s		audioTrackInfo;
+	struct audioStatus_s		audioStatus;
+	struct reset_s				reset;
+};
+
+#pragma pack()
+
+#define MAXIMUM_TRACKS			32
+
+typedef struct
+{
+	int			start;
+	int			length;
+	qboolean	isData;
+} track_info;
+
+typedef struct
+{
+	qboolean	valid;
+	int			leadOutAddress;
+	track_info	track[MAXIMUM_TRACKS];
+	byte		lowTrack;
+	byte		highTrack;
+} cd_info;
+
+static struct cd_request	*cdRequest;
+static union readInfo_u		*readInfo;
+static cd_info				cd;
+
+static qboolean	playing = false;
+static qboolean	wasPlaying = false;
+static qboolean	mediaCheck = false;
+static qboolean	initialized = false;
+static qboolean	enabled = true;
+static qboolean playLooping = false;
+static short	cdRequestSegment;
+static short	cdRequestOffset;
+static short	readInfoSegment;
+static short	readInfoOffset;
+static byte 	remap[256];
+static byte		cdrom;
+static byte		playTrack;
+static byte		cdvolume;
+
+
+static int RedBookToSector(int rb)
+{
+	byte	minute;
+	byte	second;
+	byte	frame;
+
+	minute = (rb >> 16) & 0xff;
+	second = (rb >> 8) & 0xff;
+	frame = rb & 0xff;
+	return minute * 60 * 75 + second * 75 + frame;
+}
+
+
+static void CDAudio_Reset(void)
+{
+	cdRequest->headerLength = 13;
+	cdRequest->unit = 0;
+	cdRequest->command = COMMAND_WRITE;
+	cdRequest->status = 0;
+
+	cdRequest->x.write.mediaDescriptor = 0;
+	cdRequest->x.write.bufferOffset = readInfoOffset;
+	cdRequest->x.write.bufferSegment = readInfoSegment;
+	cdRequest->x.write.length = sizeof(struct reset_s);
+	cdRequest->x.write.startSector = 0;
+	cdRequest->x.write.volumeID = 0;
+
+	readInfo->reset.code = WRITE_REQUEST_RESET;
+
+	regs.x.ax = 0x1510;
+	regs.x.cx = cdrom;
+	regs.x.es = cdRequestSegment;
+	regs.x.bx = cdRequestOffset;
+	dos_int86 (0x2f);
+}
+
+
+static void CDAudio_Eject(void)
+{
+	cdRequest->headerLength = 13;
+	cdRequest->unit = 0;
+	cdRequest->command = COMMAND_WRITE;
+	cdRequest->status = 0;
+
+	cdRequest->x.write.mediaDescriptor = 0;
+	cdRequest->x.write.bufferOffset = readInfoOffset;
+	cdRequest->x.write.bufferSegment = readInfoSegment;
+	cdRequest->x.write.length = sizeof(struct reset_s);
+	cdRequest->x.write.startSector = 0;
+	cdRequest->x.write.volumeID = 0;
+
+	readInfo->reset.code = WRITE_REQUEST_EJECT;
+
+	regs.x.ax = 0x1510;
+	regs.x.cx = cdrom;
+	regs.x.es = cdRequestSegment;
+	regs.x.bx = cdRequestOffset;
+	dos_int86 (0x2f);
+}
+
+
+static int CDAudio_GetAudioTrackInfo(byte track, int *start)
+{
+	byte	control;
+
+	cdRequest->headerLength = 13;
+	cdRequest->unit = 0;
+	cdRequest->command = COMMAND_READ;
+	cdRequest->status = 0;
+
+	cdRequest->x.read.mediaDescriptor = 0;
+	cdRequest->x.read.bufferOffset = readInfoOffset;
+	cdRequest->x.read.bufferSegment = readInfoSegment;
+	cdRequest->x.read.length = sizeof(struct audioTrackInfo_s);
+	cdRequest->x.read.startSector = 0;
+	cdRequest->x.read.volumeID = 0;
+
+	readInfo->audioTrackInfo.code = READ_REQUEST_AUDIO_TRACK_INFO;
+	readInfo->audioTrackInfo.track = track;
+
+	regs.x.ax = 0x1510;
+	regs.x.cx = cdrom;
+	regs.x.es = cdRequestSegment;
+	regs.x.bx = cdRequestOffset;
+	dos_int86 (0x2f);
+
+	if (cdRequest->status & STATUS_ERROR_BIT)
+	{
+		Con_DPrintf("CDAudio_GetAudioTrackInfo %04x\n", cdRequest->status & 	0xffff);
+		return -1;
+	}
+
+	*start = readInfo->audioTrackInfo.start;
+	control = readInfo->audioTrackInfo.control & AUDIO_CONTROL_MASK;
+	return (control & AUDIO_CONTROL_DATA_TRACK);
+}
+
+
+static int CDAudio_GetAudioDiskInfo(void)
+{
+	int n;
+
+	cdRequest->headerLength = 13;
+	cdRequest->unit = 0;
+	cdRequest->command = COMMAND_READ;
+	cdRequest->status = 0;
+
+	cdRequest->x.read.mediaDescriptor = 0;
+	cdRequest->x.read.bufferOffset = readInfoOffset;
+	cdRequest->x.read.bufferSegment = readInfoSegment;
+	cdRequest->x.read.length = sizeof(struct audioDiskInfo_s);
+	cdRequest->x.read.startSector = 0;
+	cdRequest->x.read.volumeID = 0;
+
+	readInfo->audioDiskInfo.code = READ_REQUEST_AUDIO_DISK_INFO;
+
+	regs.x.ax = 0x1510;
+	regs.x.cx = cdrom;
+	regs.x.es = cdRequestSegment;
+	regs.x.bx = cdRequestOffset;
+	dos_int86 (0x2f);
+
+	if (cdRequest->status & STATUS_ERROR_BIT)
+	{
+		Con_DPrintf("CDAudio_GetAudioDiskInfo %04x\n", cdRequest->status & 	0xffff);
+		return -1;
+	}
+
+	cd.valid = true;
+	cd.lowTrack = readInfo->audioDiskInfo.lowTrack;
+	cd.highTrack = readInfo->audioDiskInfo.highTrack;
+	cd.leadOutAddress = readInfo->audioDiskInfo.leadOutStart;
+
+	for (n = cd.lowTrack; n <= cd.highTrack; n++)
+	{
+		cd.track[n].isData = CDAudio_GetAudioTrackInfo (n, &cd.track[n].start);
+		if (n > cd.lowTrack)
+		{
+			cd.track[n-1].length = RedBookToSector(cd.track[n].start) - RedBookToSector(cd.track[n-1].start);
+			if (n == cd.highTrack)
+				cd.track[n].length = RedBookToSector(cd.leadOutAddress) - RedBookToSector(cd.track[n].start);
+		}
+	}
+
+	return 0;
+}
+
+
+static int CDAudio_GetAudioStatus(void)
+{
+	cdRequest->headerLength = 13;
+	cdRequest->unit = 0;
+	cdRequest->command = COMMAND_READ;
+	cdRequest->status = 0;
+
+	cdRequest->x.read.mediaDescriptor = 0;
+	cdRequest->x.read.bufferOffset = readInfoOffset;
+	cdRequest->x.read.bufferSegment = readInfoSegment;
+	cdRequest->x.read.length = sizeof(struct audioStatus_s);
+	cdRequest->x.read.startSector = 0;
+	cdRequest->x.read.volumeID = 0;
+
+	readInfo->audioDiskInfo.code = READ_REQUEST_AUDIO_STATUS;
+
+	regs.x.ax = 0x1510;
+	regs.x.cx = cdrom;
+	regs.x.es = cdRequestSegment;
+	regs.x.bx = cdRequestOffset;
+	dos_int86 (0x2f);
+
+	if (cdRequest->status & STATUS_ERROR_BIT)
+		return -1;
+	return 0;
+}
+
+
+static int CDAudio_MediaChange(void)
+{
+	cdRequest->headerLength = 13;
+	cdRequest->unit = 0;
+	cdRequest->command = COMMAND_READ;
+	cdRequest->status = 0;
+
+	cdRequest->x.read.mediaDescriptor = 0;
+	cdRequest->x.read.bufferOffset = readInfoOffset;
+	cdRequest->x.read.bufferSegment = readInfoSegment;
+	cdRequest->x.read.length = sizeof(struct mediaChange_s);
+	cdRequest->x.read.startSector = 0;
+	cdRequest->x.read.volumeID = 0;
+
+	readInfo->mediaChange.code = READ_REQUEST_MEDIA_CHANGE;
+
+	regs.x.ax = 0x1510;
+	regs.x.cx = cdrom;
+	regs.x.es = cdRequestSegment;
+	regs.x.bx = cdRequestOffset;
+	dos_int86 (0x2f);
+
+	return readInfo->mediaChange.status;
+}
+
+
+byte CDAudio_GetVolume (void)
+{
+	return cdvolume;
+}
+
+
+// we set the volume to 0 first and then to the desired volume
+// some cd-rom drivers seem to need it done this way
+void CDAudio_SetVolume (byte volume)
+{
+	if (!initialized || !enabled)
+		return;
+
+	cdRequest->headerLength = 13;
+	cdRequest->unit = 0;
+	cdRequest->command = COMMAND_WRITE;
+	cdRequest->status = 0;
+
+	cdRequest->x.read.mediaDescriptor = 0;
+	cdRequest->x.read.bufferOffset = readInfoOffset;
+	cdRequest->x.read.bufferSegment = readInfoSegment;
+	cdRequest->x.read.length = sizeof(struct audioChannelInfo_s);
+	cdRequest->x.read.startSector = 0;
+	cdRequest->x.read.volumeID = 0;
+
+	readInfo->audioChannelInfo.code = WRITE_REQUEST_AUDIO_CHANNEL_INFO;
+	readInfo->audioChannelInfo.channel0input = 0;
+	readInfo->audioChannelInfo.channel0volume = 0;
+	readInfo->audioChannelInfo.channel1input = 1;
+	readInfo->audioChannelInfo.channel1volume = 0;
+	readInfo->audioChannelInfo.channel2input = 2;
+	readInfo->audioChannelInfo.channel2volume = 0;
+	readInfo->audioChannelInfo.channel3input = 3;
+	readInfo->audioChannelInfo.channel3volume = 0;
+
+	regs.x.ax = 0x1510;
+	regs.x.cx = cdrom;
+	regs.x.es = cdRequestSegment;
+	regs.x.bx = cdRequestOffset;
+	dos_int86 (0x2f);
+
+	readInfo->audioChannelInfo.channel0volume = volume;
+	readInfo->audioChannelInfo.channel1volume = volume;
+
+	regs.x.ax = 0x1510;
+	regs.x.cx = cdrom;
+	regs.x.es = cdRequestSegment;
+	regs.x.bx = cdRequestOffset;
+	dos_int86 (0x2f);
+
+	cdvolume = volume;
+}
+
+
+void CDAudio_Play(byte track, qboolean looping)
+{
+	if (!initialized || !enabled)
+		return;
+	
+	if (!cd.valid)
+		return;
+
+	track = remap[track];
+
+	if (playing)
+	{
+		if (playTrack == track)
+			return;
+		CDAudio_Stop();
+	}
+
+	playLooping = looping;
+
+	if (track < cd.lowTrack || track > cd.highTrack)
+	{
+		Con_DPrintf("CDAudio_Play: Bad track number %u.\n", track);
+		return;
+	}
+
+	playTrack = track;
+
+	if (cd.track[track].isData)
+	{
+		Con_DPrintf("CDAudio_Play: Can not play data.\n");
+		return;
+	}
+
+	cdRequest->headerLength = 13;
+	cdRequest->unit = 0;
+	cdRequest->command = COMMAND_PLAY_AUDIO;
+	cdRequest->status = 0;
+
+	cdRequest->x.playAudio.addressingMode = ADDRESS_MODE_RED_BOOK;
+	cdRequest->x.playAudio.startLocation = cd.track[track].start;
+	cdRequest->x.playAudio.sectors = cd.track[track].length;
+
+	regs.x.ax = 0x1510;
+	regs.x.cx = cdrom;
+	regs.x.es = cdRequestSegment;
+	regs.x.bx = cdRequestOffset;
+	dos_int86 (0x2f);
+
+	if (cdRequest->status & STATUS_ERROR_BIT)
+	{
+		Con_DPrintf("CDAudio_Play: track %u failed\n", track);
+		cd.valid = false;
+		playing = false;
+		return;
+	}
+
+	playing = true;
+}
+
+
+void CDAudio_Stop(void)
+{
+	if (!initialized || !enabled)
+		return;
+	
+	cdRequest->headerLength = 13;
+	cdRequest->unit = 0;
+	cdRequest->command = COMMAND_STOP_AUDIO;
+	cdRequest->status = 0;
+
+	regs.x.ax = 0x1510;
+	regs.x.cx = cdrom;
+	regs.x.es = cdRequestSegment;
+	regs.x.bx = cdRequestOffset;
+	dos_int86 (0x2f);
+
+	wasPlaying = playing;
+	playing = false;
+}
+
+
+void CDAudio_Resume(void)
+{
+	if (!initialized || !enabled)
+		return;
+	
+	if (!cd.valid)
+		return;
+
+	if (!wasPlaying)
+		return;
+	
+	cdRequest->headerLength = 13;
+	cdRequest->unit = 0;
+	cdRequest->command = COMMAND_RESUME_AUDIO;
+	cdRequest->status = 0;
+
+	regs.x.ax = 0x1510;
+	regs.x.cx = cdrom;
+	regs.x.es = cdRequestSegment;
+	regs.x.bx = cdRequestOffset;
+	dos_int86 (0x2f);
+
+	playing = true;
+}
+
+
+static void CD_f (void)
+{
+	char	*command;
+	int		ret;
+	int		n;
+	int		startAddress;
+
+	if (Cmd_Argc() < 2)
+		return;
+
+	command = Cmd_Argv (1);
+
+	if (Q_strcasecmp(command, "on") == 0)
+	{
+		enabled = true;
+		return;
+	}
+
+	if (Q_strcasecmp(command, "off") == 0)
+	{
+		if (playing)
+			CDAudio_Stop();
+		enabled = false;
+		return;
+	}
+
+	if (Q_strcasecmp(command, "reset") == 0)
+	{
+		enabled = true;
+		if (playing)
+			CDAudio_Stop();
+		for (n = 0; n < 256; n++)
+			remap[n] = n;
+		CDAudio_Reset();
+		CDAudio_GetAudioDiskInfo();
+		return;
+	}
+
+	if (Q_strcasecmp(command, "remap") == 0)
+	{
+		ret = Cmd_Argc() - 2;
+		if (ret <= 0)
+		{
+			for (n = 1; n < 256; n++)
+				if (remap[n] != n)
+					Con_Printf("  %u -> %u\n", n, remap[n]);
+			return;
+		}
+		for (n = 1; n <= ret; n++)
+			remap[n] = Q_atoi(Cmd_Argv (n+1));
+		return;
+	}
+
+	if (!cd.valid)
+	{
+		Con_Printf("No CD in player.\n");
+		return;
+	}
+
+	if (Q_strcasecmp(command, "play") == 0)
+	{
+		CDAudio_Play(Q_atoi(Cmd_Argv (2)), false);
+		return;
+	}
+
+	if (Q_strcasecmp(command, "loop") == 0)
+	{
+		CDAudio_Play(Q_atoi(Cmd_Argv (2)), true);
+		return;
+	}
+
+	if (Q_strcasecmp(command, "stop") == 0)
+	{
+		CDAudio_Stop();
+		return;
+	}
+
+	if (Q_strcasecmp(command, "resume") == 0)
+	{
+		CDAudio_Resume();
+		return;
+	}
+
+	if (Q_strcasecmp(command, "eject") == 0)
+	{
+		if (playing)
+			CDAudio_Stop();
+		CDAudio_Eject();
+		cd.valid = false;
+		return;
+	}
+
+	if (Q_strcasecmp(command, "info") == 0)
+	{
+		Con_Printf("%u tracks\n", cd.highTrack - cd.lowTrack + 1);
+		for (n = cd.lowTrack; n <= cd.highTrack; n++)
+		{
+			ret = CDAudio_GetAudioTrackInfo (n, &startAddress);
+			Con_Printf("Track %2u: %s at %2u:%02u\n", n, ret ? "data " : "music", (startAddress >> 16) & 0xff, (startAddress >> 8) & 0xff);
+		}
+		if (playing)
+			Con_Printf("Currently %s track %u\n", playLooping ? "looping" : "playing", playTrack);
+		Con_Printf("Volume is %u\n", cdvolume);
+		CDAudio_MediaChange();
+		Con_Printf("Status %04x\n", cdRequest->status & 0xffff);
+		return;
+	}
+}
+
+
+void CDAudio_Update(void)
+{
+	int		ret;
+	int		newVolume;
+	static	double lastUpdate;
+
+	if (!initialized || !enabled)
+		return;
+
+	if ((realtime - lastUpdate) < 0.25)
+		return;
+	lastUpdate = realtime;
+
+	if (mediaCheck)
+	{
+		static	double lastCheck;
+
+		if ((realtime - lastCheck) < 5.0)
+			return;
+		lastCheck = realtime;
+
+		ret = CDAudio_MediaChange();
+		if (ret == MEDIA_CHANGED)
+		{
+			Con_DPrintf("CDAudio: media changed\n");
+			playing = false;
+			wasPlaying = false;
+			cd.valid = false;
+			CDAudio_GetAudioDiskInfo();
+			return;
+		}
+	}
+
+	newVolume = (int)(bgmvolume.value * 255.0);
+	if (newVolume < 0)
+	{
+		Cvar_SetValue ("bgmvolume", 0.0);
+		newVolume = 0;
+	}
+	else if (newVolume > 255)
+	{
+		Cvar_SetValue ("bgmvolume", 1.0);
+		newVolume = 255;
+	}
+	if (cdvolume != newVolume)
+		CDAudio_SetVolume (newVolume);
+
+	if (playing)
+	{
+		CDAudio_GetAudioStatus();
+		if ((cdRequest->status & STATUS_BUSY_BIT) == 0)
+		{
+			playing = false;
+			if (playLooping)
+				CDAudio_Play(playTrack, true);
+		}
+	}
+}
+
+
+qboolean CDAudio_Playing(void)
+{
+	return playing;
+}
+
+
+int CDAudio_Init(void)
+{
+	char	*memory;
+	int		n;
+
+	if (cls.state == ca_dedicated)
+		return -1;
+
+	if (COM_CheckParm("-nocdaudio"))
+		return -1;
+
+	if (COM_CheckParm("-cdmediacheck"))
+		mediaCheck = true;
+
+	regs.x.ax = 0x1500;
+	regs.x.bx = 0;
+	dos_int86 (0x2f);
+	if (regs.x.bx == 0)
+	{
+		Con_NotifyBox (
+			"MSCDEX not loaded, music is\n"
+			"disabled.  Use \"-nocdaudio\" if you\n"
+			"wish to avoid this message in the\n"
+			"future.  See README.TXT for help.\n"
+			);			
+		return -1;
+	}
+	if (regs.x.bx > 1)
+		Con_DPrintf("CDAudio_Init: First CD-ROM drive will be used\n");
+	cdrom = regs.x.cx;
+
+	regs.x.ax = 0x150c;
+	regs.x.bx = 0;
+	dos_int86 (0x2f);
+	if (regs.x.bx == 0)
+	{
+		Con_NotifyBox (
+			"MSCDEX version 2.00 or later\n"
+			"required for music. See README.TXT\n"
+			"for help.\n"
+			);			
+		Con_DPrintf("CDAudio_Init: MSCDEX version 2.00 or later required.\n");
+		return -1;
+	}
+
+	memory = dos_getmemory(sizeof(struct cd_request
+) + sizeof(union readInfo_u));
+	if (memory == NULL)
+	{
+		Con_DPrintf("CDAudio_Init: Unable to allocate low memory.\n");
+		return -1;
+	}
+
+	cdRequest = (struct cd_request *)memory;
+	cdRequestSegment = ptr2real(cdRequest) >> 4;
+	cdRequestOffset = ptr2real(cdRequest) & 0xf;
+
+	readInfo = (union readInfo_u *)(memory + sizeof(struct cd_request));
+	readInfoSegment = ptr2real(readInfo) >> 4;
+	readInfoOffset = ptr2real(readInfo) & 0xf;
+
+	for (n = 0; n < 256; n++)
+		remap[n] = n;
+	initialized = true;
+
+	CDAudio_SetVolume (255);
+	if (CDAudio_GetAudioDiskInfo())
+	{
+		Con_Printf("CDAudio_Init: No CD in player.\n");
+		enabled = false;
+	}
+
+	Cmd_AddCommand ("cd", CD_f);
+
+	Con_Printf("CD Audio Initialized\n");
+
+	return 0;
+}
+
+
+void CDAudio_Shutdown(void)
+{
+	if (!initialized)
+		return;
+	CDAudio_Stop();
+}
--- /dev/null
+++ b/QW/client/cd_linux.c
@@ -1,0 +1,418 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the included (GNU.txt) GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// Quake is a trademark of Id Software, Inc., (c) 1996 Id Software, Inc. All
+// rights reserved.
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/ioctl.h>
+#include <sys/file.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <string.h>
+#include <time.h>
+#include <errno.h>
+
+#include <linux/cdrom.h>
+
+#include "quakedef.h"
+
+static qboolean cdValid = false;
+static qboolean	playing = false;
+static qboolean	wasPlaying = false;
+static qboolean	initialized = false;
+static qboolean	enabled = true;
+static qboolean playLooping = false;
+static float	cdvolume;
+static byte 	remap[100];
+static byte		playTrack;
+static byte		maxTrack;
+
+static int cdfile = -1;
+static char cd_dev[64] = "/dev/cdrom";
+
+static void CDAudio_Eject(void)
+{
+	if (cdfile == -1 || !enabled)
+		return; // no cd init'd
+
+	if ( ioctl(cdfile, CDROMEJECT) == -1 ) 
+		Con_DPrintf("ioctl cdromeject failed\n");
+}
+
+
+static void CDAudio_CloseDoor(void)
+{
+	if (cdfile == -1 || !enabled)
+		return; // no cd init'd
+
+	if ( ioctl(cdfile, CDROMCLOSETRAY) == -1 ) 
+		Con_DPrintf("ioctl cdromclosetray failed\n");
+}
+
+static int CDAudio_GetAudioDiskInfo(void)
+{
+	struct cdrom_tochdr tochdr;
+
+	cdValid = false;
+
+	if ( ioctl(cdfile, CDROMREADTOCHDR, &tochdr) == -1 ) 
+    {
+      Con_DPrintf("ioctl cdromreadtochdr failed\n");
+	  return -1;
+    }
+
+	if (tochdr.cdth_trk0 < 1)
+	{
+		Con_DPrintf("CDAudio: no music tracks\n");
+		return -1;
+	}
+
+	cdValid = true;
+	maxTrack = tochdr.cdth_trk1;
+
+	return 0;
+}
+
+
+void CDAudio_Play(byte track, qboolean looping)
+{
+	struct cdrom_tocentry entry;
+	struct cdrom_ti ti;
+
+	if (cdfile == -1 || !enabled)
+		return;
+	
+	if (!cdValid)
+	{
+		CDAudio_GetAudioDiskInfo();
+		if (!cdValid)
+			return;
+	}
+
+	track = remap[track];
+
+	if (track < 1 || track > maxTrack)
+	{
+		Con_DPrintf("CDAudio: Bad track number %u.\n", track);
+		return;
+	}
+
+	// don't try to play a non-audio track
+	entry.cdte_track = track;
+	entry.cdte_format = CDROM_MSF;
+    if ( ioctl(cdfile, CDROMREADTOCENTRY, &entry) == -1 )
+	{
+		Con_DPrintf("ioctl cdromreadtocentry failed\n");
+		return;
+	}
+	if (entry.cdte_ctrl == CDROM_DATA_TRACK)
+	{
+		Con_Printf("CDAudio: track %i is not audio\n", track);
+		return;
+	}
+
+	if (playing)
+	{
+		if (playTrack == track)
+			return;
+		CDAudio_Stop();
+	}
+
+	ti.cdti_trk0 = track;
+	ti.cdti_trk1 = track;
+	ti.cdti_ind0 = 1;
+	ti.cdti_ind1 = 99;
+
+	if ( ioctl(cdfile, CDROMPLAYTRKIND, &ti) == -1 ) 
+    {
+		Con_DPrintf("ioctl cdromplaytrkind failed\n");
+		return;
+    }
+
+	if ( ioctl(cdfile, CDROMRESUME) == -1 ) 
+		Con_DPrintf("ioctl cdromresume failed\n");
+
+	playLooping = looping;
+	playTrack = track;
+	playing = true;
+
+	if (cdvolume == 0.0)
+		CDAudio_Pause ();
+}
+
+
+void CDAudio_Stop(void)
+{
+	if (cdfile == -1 || !enabled)
+		return;
+	
+	if (!playing)
+		return;
+
+	if ( ioctl(cdfile, CDROMSTOP) == -1 )
+		Con_DPrintf("ioctl cdromstop failed (%d)\n", errno);
+
+	wasPlaying = false;
+	playing = false;
+}
+
+void CDAudio_Pause(void)
+{
+	if (cdfile == -1 || !enabled)
+		return;
+
+	if (!playing)
+		return;
+
+	if ( ioctl(cdfile, CDROMPAUSE) == -1 ) 
+		Con_DPrintf("ioctl cdrompause failed\n");
+
+	wasPlaying = playing;
+	playing = false;
+}
+
+
+void CDAudio_Resume(void)
+{
+	if (cdfile == -1 || !enabled)
+		return;
+	
+	if (!cdValid)
+		return;
+
+	if (!wasPlaying)
+		return;
+	
+	if ( ioctl(cdfile, CDROMRESUME) == -1 ) 
+		Con_DPrintf("ioctl cdromresume failed\n");
+	playing = true;
+}
+
+static void CD_f (void)
+{
+	char	*command;
+	int		ret;
+	int		n;
+
+	if (Cmd_Argc() < 2)
+		return;
+
+	command = Cmd_Argv (1);
+
+	if (Q_strcasecmp(command, "on") == 0)
+	{
+		enabled = true;
+		return;
+	}
+
+	if (Q_strcasecmp(command, "off") == 0)
+	{
+		if (playing)
+			CDAudio_Stop();
+		enabled = false;
+		return;
+	}
+
+	if (Q_strcasecmp(command, "reset") == 0)
+	{
+		enabled = true;
+		if (playing)
+			CDAudio_Stop();
+		for (n = 0; n < 100; n++)
+			remap[n] = n;
+		CDAudio_GetAudioDiskInfo();
+		return;
+	}
+
+	if (Q_strcasecmp(command, "remap") == 0)
+	{
+		ret = Cmd_Argc() - 2;
+		if (ret <= 0)
+		{
+			for (n = 1; n < 100; n++)
+				if (remap[n] != n)
+					Con_Printf("  %u -> %u\n", n, remap[n]);
+			return;
+		}
+		for (n = 1; n <= ret; n++)
+			remap[n] = Q_atoi(Cmd_Argv (n+1));
+		return;
+	}
+
+	if (Q_strcasecmp(command, "close") == 0)
+	{
+		CDAudio_CloseDoor();
+		return;
+	}
+
+	if (!cdValid)
+	{
+		CDAudio_GetAudioDiskInfo();
+		if (!cdValid)
+		{
+			Con_Printf("No CD in player.\n");
+			return;
+		}
+	}
+
+	if (Q_strcasecmp(command, "play") == 0)
+	{
+		CDAudio_Play((byte)Q_atoi(Cmd_Argv (2)), false);
+		return;
+	}
+
+	if (Q_strcasecmp(command, "loop") == 0)
+	{
+		CDAudio_Play((byte)Q_atoi(Cmd_Argv (2)), true);
+		return;
+	}
+
+	if (Q_strcasecmp(command, "stop") == 0)
+	{
+		CDAudio_Stop();
+		return;
+	}
+
+	if (Q_strcasecmp(command, "pause") == 0)
+	{
+		CDAudio_Pause();
+		return;
+	}
+
+	if (Q_strcasecmp(command, "resume") == 0)
+	{
+		CDAudio_Resume();
+		return;
+	}
+
+	if (Q_strcasecmp(command, "eject") == 0)
+	{
+		if (playing)
+			CDAudio_Stop();
+		CDAudio_Eject();
+		cdValid = false;
+		return;
+	}
+
+	if (Q_strcasecmp(command, "info") == 0)
+	{
+		Con_Printf("%u tracks\n", maxTrack);
+		if (playing)
+			Con_Printf("Currently %s track %u\n", playLooping ? "looping" : "playing", playTrack);
+		else if (wasPlaying)
+			Con_Printf("Paused %s track %u\n", playLooping ? "looping" : "playing", playTrack);
+		Con_Printf("Volume is %f\n", cdvolume);
+		return;
+	}
+}
+
+void CDAudio_Update(void)
+{
+	struct cdrom_subchnl subchnl;
+	static time_t lastchk;
+
+	if (!enabled)
+		return;
+
+	if (bgmvolume.value != cdvolume)
+	{
+		if (cdvolume)
+		{
+			Cvar_SetValue ("bgmvolume", 0.0);
+			cdvolume = bgmvolume.value;
+			CDAudio_Pause ();
+		}
+		else
+		{
+			Cvar_SetValue ("bgmvolume", 1.0);
+			cdvolume = bgmvolume.value;
+			CDAudio_Resume ();
+		}
+	}
+
+	if (playing && lastchk < time(NULL)) {
+		lastchk = time(NULL) + 2; //two seconds between chks
+		subchnl.cdsc_format = CDROM_MSF;
+		if (ioctl(cdfile, CDROMSUBCHNL, &subchnl) == -1 ) {
+			Con_DPrintf("ioctl cdromsubchnl failed\n");
+			playing = false;
+			return;
+		}
+		if (subchnl.cdsc_audiostatus != CDROM_AUDIO_PLAY &&
+			subchnl.cdsc_audiostatus != CDROM_AUDIO_PAUSED) {
+			playing = false;
+			if (playLooping)
+				CDAudio_Play(playTrack, true);
+		}
+	}
+}
+
+int CDAudio_Init(void)
+{
+	int i;
+
+#if 0
+	if (cls.state == ca_dedicated)
+		return -1;
+#endif
+
+	if (COM_CheckParm("-nocdaudio"))
+		return -1;
+
+	if ((i = COM_CheckParm("-cddev")) != 0 && i < com_argc - 1) {
+		strncpy(cd_dev, com_argv[i + 1], sizeof(cd_dev));
+		cd_dev[sizeof(cd_dev) - 1] = 0;
+	}
+
+	if ((cdfile = open(cd_dev, O_RDONLY)) == -1) {
+		Con_Printf("CDAudio_Init: open of \"%s\" failed (%i)\n", cd_dev, errno);
+		cdfile = -1;
+		return -1;
+	}
+
+	for (i = 0; i < 100; i++)
+		remap[i] = i;
+	initialized = true;
+	enabled = true;
+
+	if (CDAudio_GetAudioDiskInfo())
+	{
+		Con_Printf("CDAudio_Init: No CD in player.\n");
+		cdValid = false;
+	}
+
+	Cmd_AddCommand ("cd", CD_f);
+
+	Con_Printf("CD Audio Initialized\n");
+
+	return 0;
+}
+
+
+void CDAudio_Shutdown(void)
+{
+	if (!initialized)
+		return;
+	CDAudio_Stop();
+	close(cdfile);
+	cdfile = -1;
+}
--- /dev/null
+++ b/QW/client/cd_null.c
@@ -1,0 +1,31 @@
+#include "quakedef.h"
+
+void CDAudio_Play(byte track, qboolean looping)
+{
+}
+
+
+void CDAudio_Stop(void)
+{
+}
+
+
+void CDAudio_Resume(void)
+{
+}
+
+
+void CDAudio_Update(void)
+{
+}
+
+
+int CDAudio_Init(void)
+{
+	return 0;
+}
+
+
+void CDAudio_Shutdown(void)
+{
+}
\ No newline at end of file
--- /dev/null
+++ b/QW/client/cd_win.c
@@ -1,0 +1,479 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the included (GNU.txt) GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// Quake is a trademark of Id Software, Inc., (c) 1996 Id Software, Inc. All
+// rights reserved.
+
+#include <windows.h>
+#include "quakedef.h"
+
+extern	HWND	mainwindow;
+extern	cvar_t	bgmvolume;
+
+static qboolean cdValid = false;
+static qboolean	playing = false;
+static qboolean	wasPlaying = false;
+static qboolean	initialized = false;
+static qboolean	enabled = false;
+static qboolean playLooping = false;
+static float	cdvolume;
+static byte 	remap[100];
+static byte		cdrom;
+static byte		playTrack;
+static byte		maxTrack;
+
+UINT	wDeviceID;
+
+
+static void CDAudio_Eject(void)
+{
+	DWORD	dwReturn;
+
+    if (dwReturn = mciSendCommand(wDeviceID, MCI_SET, MCI_SET_DOOR_OPEN, (DWORD)NULL))
+		Con_DPrintf("MCI_SET_DOOR_OPEN failed (%i)\n", dwReturn);
+}
+
+
+static void CDAudio_CloseDoor(void)
+{
+	DWORD	dwReturn;
+
+    if (dwReturn = mciSendCommand(wDeviceID, MCI_SET, MCI_SET_DOOR_CLOSED, (DWORD)NULL))
+		Con_DPrintf("MCI_SET_DOOR_CLOSED failed (%i)\n", dwReturn);
+}
+
+
+static int CDAudio_GetAudioDiskInfo(void)
+{
+	DWORD				dwReturn;
+	MCI_STATUS_PARMS	mciStatusParms;
+
+
+	cdValid = false;
+
+	mciStatusParms.dwItem = MCI_STATUS_READY;
+    dwReturn = mciSendCommand(wDeviceID, MCI_STATUS, MCI_STATUS_ITEM | MCI_WAIT, (DWORD) (LPVOID) &mciStatusParms);
+	if (dwReturn)
+	{
+		Con_DPrintf("CDAudio: drive ready test - get status failed\n");
+		return -1;
+	}
+	if (!mciStatusParms.dwReturn)
+	{
+		Con_DPrintf("CDAudio: drive not ready\n");
+		return -1;
+	}
+
+	mciStatusParms.dwItem = MCI_STATUS_NUMBER_OF_TRACKS;
+    dwReturn = mciSendCommand(wDeviceID, MCI_STATUS, MCI_STATUS_ITEM | MCI_WAIT, (DWORD) (LPVOID) &mciStatusParms);
+	if (dwReturn)
+	{
+		Con_DPrintf("CDAudio: get tracks - status failed\n");
+		return -1;
+	}
+	if (mciStatusParms.dwReturn < 1)
+	{
+		Con_DPrintf("CDAudio: no music tracks\n");
+		return -1;
+	}
+
+	cdValid = true;
+	maxTrack = mciStatusParms.dwReturn;
+
+	return 0;
+}
+
+
+void CDAudio_Play(byte track, qboolean looping)
+{
+	DWORD				dwReturn;
+    MCI_PLAY_PARMS		mciPlayParms;
+	MCI_STATUS_PARMS	mciStatusParms;
+
+	if (!enabled)
+		return;
+	
+	if (!cdValid)
+	{
+		CDAudio_GetAudioDiskInfo();
+		if (!cdValid)
+			return;
+	}
+
+	track = remap[track];
+
+	if (track < 1 || track > maxTrack)
+	{
+		Con_DPrintf("CDAudio: Bad track number %u.\n", track);
+		return;
+	}
+
+	// don't try to play a non-audio track
+	mciStatusParms.dwItem = MCI_CDA_STATUS_TYPE_TRACK;
+	mciStatusParms.dwTrack = track;
+    dwReturn = mciSendCommand(wDeviceID, MCI_STATUS, MCI_STATUS_ITEM | MCI_TRACK | MCI_WAIT, (DWORD) (LPVOID) &mciStatusParms);
+	if (dwReturn)
+	{
+		Con_DPrintf("MCI_STATUS failed (%i)\n", dwReturn);
+		return;
+	}
+	if (mciStatusParms.dwReturn != MCI_CDA_TRACK_AUDIO)
+	{
+		Con_Printf("CDAudio: track %i is not audio\n", track);
+		return;
+	}
+
+	// get the length of the track to be played
+	mciStatusParms.dwItem = MCI_STATUS_LENGTH;
+	mciStatusParms.dwTrack = track;
+    dwReturn = mciSendCommand(wDeviceID, MCI_STATUS, MCI_STATUS_ITEM | MCI_TRACK | MCI_WAIT, (DWORD) (LPVOID) &mciStatusParms);
+	if (dwReturn)
+	{
+		Con_DPrintf("MCI_STATUS failed (%i)\n", dwReturn);
+		return;
+	}
+
+	if (playing)
+	{
+		if (playTrack == track)
+			return;
+		CDAudio_Stop();
+	}
+
+    mciPlayParms.dwFrom = MCI_MAKE_TMSF(track, 0, 0, 0);
+	mciPlayParms.dwTo = (mciStatusParms.dwReturn << 8) | track;
+    mciPlayParms.dwCallback = (DWORD)mainwindow;
+    dwReturn = mciSendCommand(wDeviceID, MCI_PLAY, MCI_NOTIFY | MCI_FROM | MCI_TO, (DWORD)(LPVOID) &mciPlayParms);
+	if (dwReturn)
+	{
+		Con_DPrintf("CDAudio: MCI_PLAY failed (%i)\n", dwReturn);
+		return;
+	}
+
+	playLooping = looping;
+	playTrack = track;
+	playing = true;
+
+	if (cdvolume == 0.0)
+		CDAudio_Pause ();
+}
+
+
+void CDAudio_Stop(void)
+{
+	DWORD	dwReturn;
+
+	if (!enabled)
+		return;
+	
+	if (!playing)
+		return;
+
+    if (dwReturn = mciSendCommand(wDeviceID, MCI_STOP, 0, (DWORD)NULL))
+		Con_DPrintf("MCI_STOP failed (%i)", dwReturn);
+
+	wasPlaying = false;
+	playing = false;
+}
+
+
+void CDAudio_Pause(void)
+{
+	DWORD				dwReturn;
+	MCI_GENERIC_PARMS	mciGenericParms;
+
+	if (!enabled)
+		return;
+
+	if (!playing)
+		return;
+
+	mciGenericParms.dwCallback = (DWORD)mainwindow;
+    if (dwReturn = mciSendCommand(wDeviceID, MCI_PAUSE, 0, (DWORD)(LPVOID) &mciGenericParms))
+		Con_DPrintf("MCI_PAUSE failed (%i)", dwReturn);
+
+	wasPlaying = playing;
+	playing = false;
+}
+
+
+void CDAudio_Resume(void)
+{
+	DWORD			dwReturn;
+    MCI_PLAY_PARMS	mciPlayParms;
+
+	if (!enabled)
+		return;
+	
+	if (!cdValid)
+		return;
+
+	if (!wasPlaying)
+		return;
+	
+    mciPlayParms.dwFrom = MCI_MAKE_TMSF(playTrack, 0, 0, 0);
+    mciPlayParms.dwTo = MCI_MAKE_TMSF(playTrack + 1, 0, 0, 0);
+    mciPlayParms.dwCallback = (DWORD)mainwindow;
+    dwReturn = mciSendCommand(wDeviceID, MCI_PLAY, MCI_TO | MCI_NOTIFY, (DWORD)(LPVOID) &mciPlayParms);
+	if (dwReturn)
+	{
+		Con_DPrintf("CDAudio: MCI_PLAY failed (%i)\n", dwReturn);
+		return;
+	}
+	playing = true;
+}
+
+
+static void CD_f (void)
+{
+	char	*command;
+	int		ret;
+	int		n;
+	int		startAddress;
+
+	if (Cmd_Argc() < 2)
+		return;
+
+	command = Cmd_Argv (1);
+
+	if (Q_strcasecmp(command, "on") == 0)
+	{
+		enabled = true;
+		return;
+	}
+
+	if (Q_strcasecmp(command, "off") == 0)
+	{
+		if (playing)
+			CDAudio_Stop();
+		enabled = false;
+		return;
+	}
+
+	if (Q_strcasecmp(command, "reset") == 0)
+	{
+		enabled = true;
+		if (playing)
+			CDAudio_Stop();
+		for (n = 0; n < 100; n++)
+			remap[n] = n;
+		CDAudio_GetAudioDiskInfo();
+		return;
+	}
+
+	if (Q_strcasecmp(command, "remap") == 0)
+	{
+		ret = Cmd_Argc() - 2;
+		if (ret <= 0)
+		{
+			for (n = 1; n < 100; n++)
+				if (remap[n] != n)
+					Con_Printf("  %u -> %u\n", n, remap[n]);
+			return;
+		}
+		for (n = 1; n <= ret; n++)
+			remap[n] = Q_atoi(Cmd_Argv (n+1));
+		return;
+	}
+
+	if (Q_strcasecmp(command, "close") == 0)
+	{
+		CDAudio_CloseDoor();
+		return;
+	}
+
+	if (!cdValid)
+	{
+		CDAudio_GetAudioDiskInfo();
+		if (!cdValid)
+		{
+			Con_Printf("No CD in player.\n");
+			return;
+		}
+	}
+
+	if (Q_strcasecmp(command, "play") == 0)
+	{
+		CDAudio_Play((byte)Q_atoi(Cmd_Argv (2)), false);
+		return;
+	}
+
+	if (Q_strcasecmp(command, "loop") == 0)
+	{
+		CDAudio_Play((byte)Q_atoi(Cmd_Argv (2)), true);
+		return;
+	}
+
+	if (Q_strcasecmp(command, "stop") == 0)
+	{
+		CDAudio_Stop();
+		return;
+	}
+
+	if (Q_strcasecmp(command, "pause") == 0)
+	{
+		CDAudio_Pause();
+		return;
+	}
+
+	if (Q_strcasecmp(command, "resume") == 0)
+	{
+		CDAudio_Resume();
+		return;
+	}
+
+	if (Q_strcasecmp(command, "eject") == 0)
+	{
+		if (playing)
+			CDAudio_Stop();
+		CDAudio_Eject();
+		cdValid = false;
+		return;
+	}
+
+	if (Q_strcasecmp(command, "info") == 0)
+	{
+		Con_Printf("%u tracks\n", maxTrack);
+		if (playing)
+			Con_Printf("Currently %s track %u\n", playLooping ? "looping" : "playing", playTrack);
+		else if (wasPlaying)
+			Con_Printf("Paused %s track %u\n", playLooping ? "looping" : "playing", playTrack);
+		Con_Printf("Volume is %f\n", cdvolume);
+		return;
+	}
+}
+
+
+LONG CDAudio_MessageHandler(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+	if (lParam != wDeviceID)
+		return 1;
+
+	switch (wParam)
+	{
+		case MCI_NOTIFY_SUCCESSFUL:
+			if (playing)
+			{
+				playing = false;
+				if (playLooping)
+					CDAudio_Play(playTrack, true);
+			}
+			break;
+
+		case MCI_NOTIFY_ABORTED:
+		case MCI_NOTIFY_SUPERSEDED:
+			break;
+
+		case MCI_NOTIFY_FAILURE:
+			Con_DPrintf("MCI_NOTIFY_FAILURE\n");
+			CDAudio_Stop ();
+			cdValid = false;
+			break;
+
+		default:
+			Con_DPrintf("Unexpected MM_MCINOTIFY type (%i)\n", wParam);
+			return 1;
+	}
+
+	return 0;
+}
+
+
+void CDAudio_Update(void)
+{
+	if (!enabled)
+		return;
+
+	if (bgmvolume.value != cdvolume)
+	{
+		if (cdvolume)
+		{
+			Cvar_SetValue ("bgmvolume", 0.0);
+			cdvolume = bgmvolume.value;
+			CDAudio_Pause ();
+		}
+		else
+		{
+			Cvar_SetValue ("bgmvolume", 1.0);
+			cdvolume = bgmvolume.value;
+			CDAudio_Resume ();
+		}
+	}
+}
+
+
+int CDAudio_Init(void)
+{
+	DWORD	dwReturn;
+	MCI_OPEN_PARMS	mciOpenParms;
+    MCI_SET_PARMS	mciSetParms;
+	int				n;
+
+#if		0	// QW
+	if (cls.state == ca_dedicated)
+		return -1;
+#endif
+	if (COM_CheckParm("-nocdaudio"))
+		return -1;
+
+	mciOpenParms.lpstrDeviceType = "cdaudio";
+	if (dwReturn = mciSendCommand(0, MCI_OPEN, MCI_OPEN_TYPE | MCI_OPEN_SHAREABLE, (DWORD) (LPVOID) &mciOpenParms))
+	{
+		Con_Printf("CDAudio_Init: MCI_OPEN failed (%i)\n", dwReturn);
+		return -1;
+	}
+	wDeviceID = mciOpenParms.wDeviceID;
+
+    // Set the time format to track/minute/second/frame (TMSF).
+    mciSetParms.dwTimeFormat = MCI_FORMAT_TMSF;
+    if (dwReturn = mciSendCommand(wDeviceID, MCI_SET, MCI_SET_TIME_FORMAT, (DWORD)(LPVOID) &mciSetParms))
+    {
+		Con_Printf("MCI_SET_TIME_FORMAT failed (%i)\n", dwReturn);
+        mciSendCommand(wDeviceID, MCI_CLOSE, 0, (DWORD)NULL);
+		return -1;
+    }
+
+	for (n = 0; n < 100; n++)
+		remap[n] = n;
+	initialized = true;
+	enabled = true;
+
+	if (CDAudio_GetAudioDiskInfo())
+	{
+		Con_Printf("CDAudio_Init: No CD in player.\n");
+		cdValid = false;
+		enabled = false;
+	}
+
+	Cmd_AddCommand ("cd", CD_f);
+
+//	Con_Printf("CD Audio Initialized\n");
+
+	return 0;
+}
+
+
+void CDAudio_Shutdown(void)
+{
+	if (!initialized)
+		return;
+	CDAudio_Stop();
+	if (mciSendCommand(wDeviceID, MCI_CLOSE, MCI_WAIT, (DWORD)NULL))
+		Con_DPrintf("CDAudio_Shutdown: MCI_CLOSE failed\n");
+}
--- /dev/null
+++ b/QW/client/cdaudio.h
@@ -1,0 +1,27 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+
+int CDAudio_Init(void);
+void CDAudio_Play(byte track, qboolean looping);
+void CDAudio_Stop(void);
+void CDAudio_Pause(void);
+void CDAudio_Resume(void);
+void CDAudio_Shutdown(void);
+void CDAudio_Update(void);
--- /dev/null
+++ b/QW/client/cl_cam.c
@@ -1,0 +1,574 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the included (GNU.txt) GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+/* ZOID
+ *
+ * Player camera tracking in Spectator mode
+ *
+ * This takes over player controls for spectator automatic camera.
+ * Player moves as a spectator, but the camera tracks and enemy player
+ */
+
+#include "quakedef.h"
+#include "winquake.h"
+
+#define	PM_SPECTATORMAXSPEED	500
+#define	PM_STOPSPEED	100
+#define	PM_MAXSPEED			320
+#define BUTTON_JUMP 2
+#define BUTTON_ATTACK 1
+#define MAX_ANGLE_TURN 10
+
+static vec3_t desired_position; // where the camera wants to be
+static qboolean locked = false;
+static int oldbuttons;
+
+// track high fragger
+cvar_t cl_hightrack = {"cl_hightrack", "0" };
+
+cvar_t cl_chasecam = {"cl_chasecam", "0"};
+
+//cvar_t cl_camera_maxpitch = {"cl_camera_maxpitch", "10" };
+//cvar_t cl_camera_maxyaw = {"cl_camera_maxyaw", "30" };
+
+qboolean cam_forceview;
+vec3_t cam_viewangles;
+double cam_lastviewtime;
+
+int spec_track = 0; // player# of who we are tracking
+int autocam = CAM_NONE;
+
+static void vectoangles(vec3_t vec, vec3_t ang)
+{
+	float	forward;
+	float	yaw, pitch;
+	
+	if (vec[1] == 0 && vec[0] == 0)
+	{
+		yaw = 0;
+		if (vec[2] > 0)
+			pitch = 90;
+		else
+			pitch = 270;
+	}
+	else
+	{
+		yaw = (int) (atan2(vec[1], vec[0]) * 180 / M_PI);
+		if (yaw < 0)
+			yaw += 360;
+
+		forward = sqrt (vec[0]*vec[0] + vec[1]*vec[1]);
+		pitch = (int) (atan2(vec[2], forward) * 180 / M_PI);
+		if (pitch < 0)
+			pitch += 360;
+	}
+
+	ang[0] = pitch;
+	ang[1] = yaw;
+	ang[2] = 0;
+}
+
+static float vlen(vec3_t v)
+{
+	return sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
+}
+
+// returns true if weapon model should be drawn in camera mode
+qboolean Cam_DrawViewModel(void)
+{
+	if (!cl.spectator)
+		return true;
+
+	if (autocam && locked && cl_chasecam.value)
+		return true;
+	return false;
+}
+
+// returns true if we should draw this player, we don't if we are chase camming
+qboolean Cam_DrawPlayer(int playernum)
+{
+	if (cl.spectator && autocam && locked && cl_chasecam.value && 
+		spec_track == playernum)
+		return false;
+	return true;
+}
+
+void Cam_Unlock(void)
+{
+	if (autocam) {
+		MSG_WriteByte (&cls.netchan.message, clc_stringcmd);
+		MSG_WriteString (&cls.netchan.message, "ptrack");
+		autocam = CAM_NONE;
+		locked = false;
+		Sbar_Changed();
+	}
+}
+
+void Cam_Lock(int playernum)
+{
+	char st[40];
+
+	sprintf(st, "ptrack %i", playernum);
+	MSG_WriteByte (&cls.netchan.message, clc_stringcmd);
+	MSG_WriteString (&cls.netchan.message, st);
+	spec_track = playernum;
+	cam_forceview = true;
+	locked = false;
+	Sbar_Changed();
+}
+
+pmtrace_t Cam_DoTrace(vec3_t vec1, vec3_t vec2)
+{
+#if 0
+	memset(&pmove, 0, sizeof(pmove));
+
+	pmove.numphysent = 1;
+	VectorCopy (vec3_origin, pmove.physents[0].origin);
+	pmove.physents[0].model = cl.worldmodel;
+#endif
+
+	VectorCopy (vec1, pmove.origin);
+	return PM_PlayerMove(pmove.origin, vec2);
+}
+	
+// Returns distance or 9999 if invalid for some reason
+static float Cam_TryFlyby(player_state_t *self, player_state_t *player, vec3_t vec, qboolean checkvis)
+{
+	vec3_t v;
+	pmtrace_t trace;
+	float len;
+
+	vectoangles(vec, v);
+//	v[0] = -v[0];
+	VectorCopy (v, pmove.angles);
+	VectorNormalize(vec);
+	VectorMA(player->origin, 800, vec, v);
+	// v is endpos
+	// fake a player move
+	trace = Cam_DoTrace(player->origin, v);
+	if (/*trace.inopen ||*/ trace.inwater)
+		return 9999;
+	VectorCopy(trace.endpos, vec);
+	VectorSubtract(trace.endpos, player->origin, v);
+	len = sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
+	if (len < 32 || len > 800)
+		return 9999;
+	if (checkvis) {
+		VectorSubtract(trace.endpos, self->origin, v);
+		len = sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
+
+		trace = Cam_DoTrace(self->origin, vec);
+		if (trace.fraction != 1 || trace.inwater)
+			return 9999;
+	}
+	return len;
+}
+
+// Is player visible?
+static qboolean Cam_IsVisible(player_state_t *player, vec3_t vec)
+{
+	pmtrace_t trace;
+	vec3_t v;
+	float d;
+
+	trace = Cam_DoTrace(player->origin, vec);
+	if (trace.fraction != 1 || /*trace.inopen ||*/ trace.inwater)
+		return false;
+	// check distance, don't let the player get too far away or too close
+	VectorSubtract(player->origin, vec, v);
+	d = vlen(v);
+	if (d < 16)
+		return false;
+	return true;
+}
+
+static qboolean InitFlyby(player_state_t *self, player_state_t *player, int checkvis) 
+{
+    float f, max;
+    vec3_t vec, vec2;
+	vec3_t forward, right, up;
+
+	VectorCopy(player->viewangles, vec);
+    vec[0] = 0;
+	AngleVectors (vec, forward, right, up);
+//	for (i = 0; i < 3; i++)
+//		forward[i] *= 3;
+
+    max = 1000;
+	VectorAdd(forward, up, vec2);
+	VectorAdd(vec2, right, vec2);
+    if ((f = Cam_TryFlyby(self, player, vec2, checkvis)) < max) {
+        max = f;
+		VectorCopy(vec2, vec);
+    }
+	VectorAdd(forward, up, vec2);
+	VectorSubtract(vec2, right, vec2);
+    if ((f = Cam_TryFlyby(self, player, vec2, checkvis)) < max) {
+        max = f;
+		VectorCopy(vec2, vec);
+    }
+	VectorAdd(forward, right, vec2);
+    if ((f = Cam_TryFlyby(self, player, vec2, checkvis)) < max) {
+        max = f;
+		VectorCopy(vec2, vec);
+    }
+	VectorSubtract(forward, right, vec2);
+    if ((f = Cam_TryFlyby(self, player, vec2, checkvis)) < max) {
+        max = f;
+		VectorCopy(vec2, vec);
+    }
+	VectorAdd(forward, up, vec2);
+    if ((f = Cam_TryFlyby(self, player, vec2, checkvis)) < max) {
+        max = f;
+		VectorCopy(vec2, vec);
+    }
+	VectorSubtract(forward, up, vec2);
+    if ((f = Cam_TryFlyby(self, player, vec2, checkvis)) < max) {
+        max = f;
+		VectorCopy(vec2, vec);
+    }
+	VectorAdd(up, right, vec2);
+	VectorSubtract(vec2, forward, vec2);
+    if ((f = Cam_TryFlyby(self, player, vec2, checkvis)) < max) {
+        max = f;
+		VectorCopy(vec2, vec);
+    }
+	VectorSubtract(up, right, vec2);
+	VectorSubtract(vec2, forward, vec2);
+    if ((f = Cam_TryFlyby(self, player, vec2, checkvis)) < max) {
+        max = f;
+		VectorCopy(vec2, vec);
+    }
+	// invert
+	VectorSubtract(vec3_origin, forward, vec2);
+    if ((f = Cam_TryFlyby(self, player, vec2, checkvis)) < max) {
+        max = f;
+		VectorCopy(vec2, vec);
+    }
+	VectorCopy(forward, vec2);
+    if ((f = Cam_TryFlyby(self, player, vec2, checkvis)) < max) {
+        max = f;
+		VectorCopy(vec2, vec);
+    }
+	// invert
+	VectorSubtract(vec3_origin, right, vec2);
+    if ((f = Cam_TryFlyby(self, player, vec2, checkvis)) < max) {
+        max = f;
+		VectorCopy(vec2, vec);
+    }
+	VectorCopy(right, vec2);
+    if ((f = Cam_TryFlyby(self, player, vec2, checkvis)) < max) {
+        max = f;
+		VectorCopy(vec2, vec);
+    }
+
+	// ack, can't find him
+    if (max >= 1000) {
+//		Cam_Unlock();
+		return false;
+	}
+	locked = true;
+	VectorCopy(vec, desired_position); 
+	return true;
+}
+
+static void Cam_CheckHighTarget(void)
+{
+	int i, j, max;
+	player_info_t	*s;
+
+	j = -1;
+	for (i = 0, max = -9999; i < MAX_CLIENTS; i++) {
+		s = &cl.players[i];
+		if (s->name[0] && !s->spectator && s->frags > max) {
+			max = s->frags;
+			j = i;
+		}
+	}
+	if (j >= 0) {
+		if (!locked || cl.players[j].frags > cl.players[spec_track].frags)
+			Cam_Lock(j);
+	} else
+		Cam_Unlock();
+}
+	
+// ZOID
+//
+// Take over the user controls and track a player.
+// We find a nice position to watch the player and move there
+void Cam_Track(usercmd_t *cmd)
+{
+	player_state_t *player, *self;
+	frame_t *frame;
+	vec3_t vec;
+	float len;
+
+	if (!cl.spectator)
+		return;
+	
+	if (cl_hightrack.value && !locked)
+		Cam_CheckHighTarget();
+
+	if (!autocam || cls.state != ca_active)
+		return;
+
+	if (locked && (!cl.players[spec_track].name[0] || cl.players[spec_track].spectator)) {
+		locked = false;
+		if (cl_hightrack.value)
+			Cam_CheckHighTarget();
+		else
+			Cam_Unlock();
+		return;
+	}
+
+	frame = &cl.frames[cls.netchan.incoming_sequence & UPDATE_MASK];
+	player = frame->playerstate + spec_track;
+	self = frame->playerstate + cl.playernum;
+
+	if (!locked || !Cam_IsVisible(player, desired_position)) {
+		if (!locked || realtime - cam_lastviewtime > 0.1) {
+			if (!InitFlyby(self, player, true))
+				InitFlyby(self, player, false);
+			cam_lastviewtime = realtime;
+		}
+	} else
+		cam_lastviewtime = realtime;
+	
+	// couldn't track for some reason
+	if (!locked || !autocam)
+		return;
+
+	if (cl_chasecam.value) {
+		cmd->forwardmove = cmd->sidemove = cmd->upmove = 0;
+
+		VectorCopy(player->viewangles, cl.viewangles);
+		VectorCopy(player->origin, desired_position);
+		if (memcmp(&desired_position, &self->origin, sizeof(desired_position)) != 0) {
+			MSG_WriteByte (&cls.netchan.message, clc_tmove);
+			MSG_WriteCoord (&cls.netchan.message, desired_position[0]);
+			MSG_WriteCoord (&cls.netchan.message, desired_position[1]);
+			MSG_WriteCoord (&cls.netchan.message, desired_position[2]);
+			// move there locally immediately
+			VectorCopy(desired_position, self->origin);
+		}
+		self->weaponframe = player->weaponframe;
+
+	} else {
+		// Ok, move to our desired position and set our angles to view
+		// the player
+		VectorSubtract(desired_position, self->origin, vec);
+		len = vlen(vec);
+		cmd->forwardmove = cmd->sidemove = cmd->upmove = 0;
+		if (len > 16) { // close enough?
+			MSG_WriteByte (&cls.netchan.message, clc_tmove);
+			MSG_WriteCoord (&cls.netchan.message, desired_position[0]);
+			MSG_WriteCoord (&cls.netchan.message, desired_position[1]);
+			MSG_WriteCoord (&cls.netchan.message, desired_position[2]);
+		}
+
+		// move there locally immediately
+		VectorCopy(desired_position, self->origin);
+										 
+		VectorSubtract(player->origin, desired_position, vec);
+		vectoangles(vec, cl.viewangles);
+		cl.viewangles[0] = -cl.viewangles[0];
+	}
+}
+
+#if 0
+static float adjustang(float current, float ideal, float speed)
+{
+	float move;
+
+	current = anglemod(current);
+	ideal = anglemod(ideal);
+
+	if (current == ideal)
+		return current;
+
+	move = ideal - current;
+	if (ideal > current)
+	{
+		if (move >= 180)
+			move = move - 360;
+	}
+	else
+	{
+		if (move <= -180)
+			move = move + 360;
+	}
+	if (move > 0)
+	{
+		if (move > speed)
+			move = speed;
+	}
+	else
+	{
+		if (move < -speed)
+			move = -speed;
+	}
+
+//Con_Printf("c/i: %4.2f/%4.2f move: %4.2f\n", current, ideal, move);
+	return anglemod (current + move);
+}
+#endif
+
+#if 0
+void Cam_SetView(void)
+{
+	return;
+	player_state_t *player, *self;
+	frame_t *frame;
+	vec3_t vec, vec2;
+
+	if (cls.state != ca_active || !cl.spectator || 
+		!autocam || !locked)
+		return;
+
+	frame = &cl.frames[cls.netchan.incoming_sequence & UPDATE_MASK];
+	player = frame->playerstate + spec_track;
+	self = frame->playerstate + cl.playernum;
+
+	VectorSubtract(player->origin, cl.simorg, vec);
+	if (cam_forceview) {
+		cam_forceview = false;
+		vectoangles(vec, cam_viewangles);
+		cam_viewangles[0] = -cam_viewangles[0];
+	} else {
+		vectoangles(vec, vec2);
+		vec2[PITCH] = -vec2[PITCH];
+
+		cam_viewangles[PITCH] = adjustang(cam_viewangles[PITCH], vec2[PITCH], cl_camera_maxpitch.value);
+		cam_viewangles[YAW] = adjustang(cam_viewangles[YAW], vec2[YAW], cl_camera_maxyaw.value);
+	}
+	VectorCopy(cam_viewangles, cl.viewangles);
+	VectorCopy(cl.viewangles, cl.simangles);
+}
+#endif
+
+void Cam_FinishMove(usercmd_t *cmd)
+{
+	int i;
+	player_info_t	*s;
+	int end;
+
+	if (cls.state != ca_active)
+		return;
+
+	if (!cl.spectator) // only in spectator mode
+		return;
+
+#if 0
+	if (autocam && locked) {
+		frame = &cl.frames[cls.netchan.incoming_sequence & UPDATE_MASK];
+		player = frame->playerstate + spec_track;
+		self = frame->playerstate + cl.playernum;
+
+		VectorSubtract(player->origin, self->origin, vec);
+		if (cam_forceview) {
+			cam_forceview = false;
+			vectoangles(vec, cam_viewangles);
+			cam_viewangles[0] = -cam_viewangles[0];
+		} else {
+			vectoangles(vec, vec2);
+			vec2[PITCH] = -vec2[PITCH];
+
+			cam_viewangles[PITCH] = adjustang(cam_viewangles[PITCH], vec2[PITCH], cl_camera_maxpitch.value);
+			cam_viewangles[YAW] = adjustang(cam_viewangles[YAW], vec2[YAW], cl_camera_maxyaw.value);
+		}
+		VectorCopy(cam_viewangles, cl.viewangles);
+	}
+#endif
+
+	if (cmd->buttons & BUTTON_ATTACK) {
+		if (!(oldbuttons & BUTTON_ATTACK)) {
+
+			oldbuttons |= BUTTON_ATTACK;
+			autocam++;
+
+			if (autocam > CAM_TRACK) {
+				Cam_Unlock();
+				VectorCopy(cl.viewangles, cmd->angles);
+				return;
+			}
+		} else
+			return;
+	} else {
+		oldbuttons &= ~BUTTON_ATTACK;
+		if (!autocam)
+			return;
+	}
+
+	if (autocam && cl_hightrack.value) {
+		Cam_CheckHighTarget();
+		return;
+	}
+
+	if (locked) {
+		if ((cmd->buttons & BUTTON_JUMP) && (oldbuttons & BUTTON_JUMP))
+			return;		// don't pogo stick
+
+		if (!(cmd->buttons & BUTTON_JUMP)) {
+			oldbuttons &= ~BUTTON_JUMP;
+			return;
+		}
+		oldbuttons |= BUTTON_JUMP;	// don't jump again until released
+	}
+
+//	Con_Printf("Selecting track target...\n");
+
+	if (locked && autocam)
+		end = (spec_track + 1) % MAX_CLIENTS;
+	else
+		end = spec_track;
+	i = end;
+	do {
+		s = &cl.players[i];
+		if (s->name[0] && !s->spectator) {
+			Cam_Lock(i);
+			return;
+		}
+		i = (i + 1) % MAX_CLIENTS;
+	} while (i != end);
+	// stay on same guy?
+	i = spec_track;
+	s = &cl.players[i];
+	if (s->name[0] && !s->spectator) {
+		Cam_Lock(i);
+		return;
+	}
+	Con_Printf("No target found ...\n");
+	autocam = locked = false;
+}
+
+void Cam_Reset(void)
+{
+	autocam = CAM_NONE;
+	spec_track = 0;
+}
+
+void CL_InitCam(void)
+{
+	Cvar_RegisterVariable (&cl_hightrack);
+	Cvar_RegisterVariable (&cl_chasecam);
+//	Cvar_RegisterVariable (&cl_camera_maxpitch);
+//	Cvar_RegisterVariable (&cl_camera_maxyaw);
+}
+
+
--- /dev/null
+++ b/QW/client/cl_demo.c
@@ -1,0 +1,805 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the included (GNU.txt) GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+
+#include "quakedef.h"
+
+void CL_FinishTimeDemo (void);
+
+/*
+==============================================================================
+
+DEMO CODE
+
+When a demo is playing back, all NET_SendMessages are skipped, and
+NET_GetMessages are read from the demo file.
+
+Whenever cl.time gets past the last received message, another message is
+read from the demo file.
+==============================================================================
+*/
+
+/*
+==============
+CL_StopPlayback
+
+Called when a demo file runs out, or the user starts a game
+==============
+*/
+void CL_StopPlayback (void)
+{
+	if (!cls.demoplayback)
+		return;
+
+	fclose (cls.demofile);
+	cls.demofile = NULL;
+	cls.state = ca_disconnected;
+	cls.demoplayback = 0;
+
+	if (cls.timedemo)
+		CL_FinishTimeDemo ();
+}
+
+#define dem_cmd		0
+#define dem_read	1
+#define dem_set		2
+
+/*
+====================
+CL_WriteDemoCmd
+
+Writes the current user cmd
+====================
+*/
+void CL_WriteDemoCmd (usercmd_t *pcmd)
+{
+	int		i;
+	float	fl;
+	byte	c;
+	usercmd_t cmd;
+
+//Con_Printf("write: %ld bytes, %4.4f\n", msg->cursize, realtime);
+
+	fl = LittleFloat((float)realtime);
+	fwrite (&fl, sizeof(fl), 1, cls.demofile);
+
+	c = dem_cmd;
+	fwrite (&c, sizeof(c), 1, cls.demofile);
+
+	// correct for byte order, bytes don't matter
+	cmd = *pcmd;
+
+	for (i = 0; i < 3; i++)
+		cmd.angles[i] = LittleFloat(cmd.angles[i]);
+	cmd.forwardmove = LittleShort(cmd.forwardmove);
+	cmd.sidemove    = LittleShort(cmd.sidemove);
+	cmd.upmove      = LittleShort(cmd.upmove);
+
+	fwrite(&cmd, sizeof(cmd), 1, cls.demofile);
+
+	for (i=0 ; i<3 ; i++)
+	{
+		fl = LittleFloat (cl.viewangles[i]);
+		fwrite (&fl, 4, 1, cls.demofile);
+	}
+
+	fflush (cls.demofile);
+}
+
+/*
+====================
+CL_WriteDemoMessage
+
+Dumps the current net message, prefixed by the length and view angles
+====================
+*/
+void CL_WriteDemoMessage (sizebuf_t *msg)
+{
+	int		len;
+	float	fl;
+	byte	c;
+
+//Con_Printf("write: %ld bytes, %4.4f\n", msg->cursize, realtime);
+
+	if (!cls.demorecording)
+		return;
+
+	fl = LittleFloat((float)realtime);
+	fwrite (&fl, sizeof(fl), 1, cls.demofile);
+
+	c = dem_read;
+	fwrite (&c, sizeof(c), 1, cls.demofile);
+
+	len = LittleLong (msg->cursize);
+	fwrite (&len, 4, 1, cls.demofile);
+	fwrite (msg->data, msg->cursize, 1, cls.demofile);
+
+	fflush (cls.demofile);
+}
+
+/*
+====================
+CL_GetDemoMessage
+
+  FIXME...
+====================
+*/
+qboolean CL_GetDemoMessage (void)
+{
+	int		r, i, j;
+	float	f;
+	float	demotime;
+	byte	c;
+	usercmd_t *pcmd;
+
+	// read the time from the packet
+	fread(&demotime, sizeof(demotime), 1, cls.demofile);
+	demotime = LittleFloat(demotime);
+
+// decide if it is time to grab the next message		
+	if (cls.timedemo) {
+		if (cls.td_lastframe < 0)
+			cls.td_lastframe = demotime;
+		else if (demotime > cls.td_lastframe) {
+			cls.td_lastframe = demotime;
+			// rewind back to time
+			fseek(cls.demofile, ftell(cls.demofile) - sizeof(demotime),
+					SEEK_SET);
+			return 0;		// allready read this frame's message
+		}
+		if (!cls.td_starttime && cls.state == ca_active) {
+			cls.td_starttime = Sys_DoubleTime();
+			cls.td_startframe = host_framecount;
+		}
+		realtime = demotime; // warp
+	} else if (!cl.paused && cls.state >= ca_onserver) {	// allways grab until fully connected
+		if (realtime + 1.0 < demotime) {
+			// too far back
+			realtime = demotime - 1.0;
+			// rewind back to time
+			fseek(cls.demofile, ftell(cls.demofile) - sizeof(demotime),
+					SEEK_SET);
+			return 0;
+		} else if (realtime < demotime) {
+			// rewind back to time
+			fseek(cls.demofile, ftell(cls.demofile) - sizeof(demotime),
+					SEEK_SET);
+			return 0;		// don't need another message yet
+		}
+	} else
+		realtime = demotime; // we're warping
+
+	if (cls.state < ca_demostart)
+		Host_Error ("CL_GetDemoMessage: cls.state != ca_active");
+	
+	// get the msg type
+	fread (&c, sizeof(c), 1, cls.demofile);
+	
+	switch (c) {
+	case dem_cmd :
+		// user sent input
+		i = cls.netchan.outgoing_sequence & UPDATE_MASK;
+		pcmd = &cl.frames[i].cmd;
+		r = fread (pcmd, sizeof(*pcmd), 1, cls.demofile);
+		if (r != 1)
+		{
+			CL_StopPlayback ();
+			return 0;
+		}
+		// byte order stuff
+		for (j = 0; j < 3; j++)
+			pcmd->angles[j] = LittleFloat(pcmd->angles[j]);
+		pcmd->forwardmove = LittleShort(pcmd->forwardmove);
+		pcmd->sidemove    = LittleShort(pcmd->sidemove);
+		pcmd->upmove      = LittleShort(pcmd->upmove);
+		cl.frames[i].senttime = demotime;
+		cl.frames[i].receivedtime = -1;		// we haven't gotten a reply yet
+		cls.netchan.outgoing_sequence++;
+		for (i=0 ; i<3 ; i++)
+		{
+			r = fread (&f, 4, 1, cls.demofile);
+			cl.viewangles[i] = LittleFloat (f);
+		}
+		break;
+
+	case dem_read:
+		// get the next message
+		fread (&net_message.cursize, 4, 1, cls.demofile);
+		net_message.cursize = LittleLong (net_message.cursize);
+	//Con_Printf("read: %ld bytes\n", net_message.cursize);
+		if (net_message.cursize > MAX_MSGLEN)
+			Sys_Error ("Demo message > MAX_MSGLEN");
+		r = fread (net_message.data, net_message.cursize, 1, cls.demofile);
+		if (r != 1)
+		{
+			CL_StopPlayback ();
+			return 0;
+		}
+		break;
+
+	case dem_set :
+		fread (&i, 4, 1, cls.demofile);
+		cls.netchan.outgoing_sequence = LittleLong(i);
+		fread (&i, 4, 1, cls.demofile);
+		cls.netchan.incoming_sequence = LittleLong(i);
+		break;
+
+	default :
+		Con_Printf("Corrupted demo.\n");
+		CL_StopPlayback ();
+		return 0;
+	}
+
+	return 1;
+}
+
+/*
+====================
+CL_GetMessage
+
+Handles recording and playback of demos, on top of NET_ code
+====================
+*/
+qboolean CL_GetMessage (void)
+{
+	if	(cls.demoplayback)
+		return CL_GetDemoMessage ();
+
+	if (!NET_GetPacket ())
+		return false;
+
+	CL_WriteDemoMessage (&net_message);
+	
+	return true;
+}
+
+
+/*
+====================
+CL_Stop_f
+
+stop recording a demo
+====================
+*/
+void CL_Stop_f (void)
+{
+	if (!cls.demorecording)
+	{
+		Con_Printf ("Not recording a demo.\n");
+		return;
+	}
+
+// write a disconnect message to the demo file
+	SZ_Clear (&net_message);
+	MSG_WriteLong (&net_message, -1);	// -1 sequence means out of band
+	MSG_WriteByte (&net_message, svc_disconnect);
+	MSG_WriteString (&net_message, "EndOfDemo");
+	CL_WriteDemoMessage (&net_message);
+
+// finish up
+	fclose (cls.demofile);
+	cls.demofile = NULL;
+	cls.demorecording = false;
+	Con_Printf ("Completed demo\n");
+}
+
+
+/*
+====================
+CL_WriteDemoMessage
+
+Dumps the current net message, prefixed by the length and view angles
+====================
+*/
+void CL_WriteRecordDemoMessage (sizebuf_t *msg, int seq)
+{
+	int		len;
+	int		i;
+	float	fl;
+	byte	c;
+
+//Con_Printf("write: %ld bytes, %4.4f\n", msg->cursize, realtime);
+
+	if (!cls.demorecording)
+		return;
+
+	fl = LittleFloat((float)realtime);
+	fwrite (&fl, sizeof(fl), 1, cls.demofile);
+
+	c = dem_read;
+	fwrite (&c, sizeof(c), 1, cls.demofile);
+
+	len = LittleLong (msg->cursize + 8);
+	fwrite (&len, 4, 1, cls.demofile);
+
+	i = LittleLong(seq);
+	fwrite (&i, 4, 1, cls.demofile);
+	fwrite (&i, 4, 1, cls.demofile);
+
+	fwrite (msg->data, msg->cursize, 1, cls.demofile);
+
+	fflush (cls.demofile);
+}
+
+
+void CL_WriteSetDemoMessage (void)
+{
+	int		len;
+	float	fl;
+	byte	c;
+
+//Con_Printf("write: %ld bytes, %4.4f\n", msg->cursize, realtime);
+
+	if (!cls.demorecording)
+		return;
+
+	fl = LittleFloat((float)realtime);
+	fwrite (&fl, sizeof(fl), 1, cls.demofile);
+
+	c = dem_set;
+	fwrite (&c, sizeof(c), 1, cls.demofile);
+
+	len = LittleLong(cls.netchan.outgoing_sequence);
+	fwrite (&len, 4, 1, cls.demofile);
+	len = LittleLong(cls.netchan.incoming_sequence);
+	fwrite (&len, 4, 1, cls.demofile);
+
+	fflush (cls.demofile);
+}
+
+
+
+
+/*
+====================
+CL_Record_f
+
+record <demoname> <server>
+====================
+*/
+void CL_Record_f (void)
+{
+	int		c;
+	char	name[MAX_OSPATH];
+	sizebuf_t	buf;
+	char	buf_data[MAX_MSGLEN];
+	int n, i, j;
+	char *s;
+	entity_t *ent;
+	entity_state_t *es, blankes;
+	player_info_t *player;
+	extern	char gamedirfile[];
+	int seq = 1;
+
+	c = Cmd_Argc();
+	if (c != 2)
+	{
+		Con_Printf ("record <demoname>\n");
+		return;
+	}
+
+	if (cls.state != ca_active) {
+		Con_Printf ("You must be connected to record.\n");
+		return;
+	}
+
+	if (cls.demorecording)
+		CL_Stop_f();
+  
+	sprintf (name, "%s/%s", com_gamedir, Cmd_Argv(1));
+
+//
+// open the demo file
+//
+	COM_DefaultExtension (name, ".qwd");
+
+	cls.demofile = fopen (name, "wb");
+	if (!cls.demofile)
+	{
+		Con_Printf ("ERROR: couldn't open.\n");
+		return;
+	}
+
+	Con_Printf ("recording to %s.\n", name);
+	cls.demorecording = true;
+
+/*-------------------------------------------------*/
+
+// serverdata
+	// send the info about the new client to all connected clients
+	memset(&buf, 0, sizeof(buf));
+	buf.data = buf_data;
+	buf.maxsize = sizeof(buf_data);
+
+// send the serverdata
+	MSG_WriteByte (&buf, svc_serverdata);
+	MSG_WriteLong (&buf, PROTOCOL_VERSION);
+	MSG_WriteLong (&buf, cl.servercount);
+	MSG_WriteString (&buf, gamedirfile);
+
+	if (cl.spectator)
+		MSG_WriteByte (&buf, cl.playernum | 128);
+	else
+		MSG_WriteByte (&buf, cl.playernum);
+
+	// send full levelname
+	MSG_WriteString (&buf, cl.levelname);
+
+	// send the movevars
+	MSG_WriteFloat(&buf, movevars.gravity);
+	MSG_WriteFloat(&buf, movevars.stopspeed);
+	MSG_WriteFloat(&buf, movevars.maxspeed);
+	MSG_WriteFloat(&buf, movevars.spectatormaxspeed);
+	MSG_WriteFloat(&buf, movevars.accelerate);
+	MSG_WriteFloat(&buf, movevars.airaccelerate);
+	MSG_WriteFloat(&buf, movevars.wateraccelerate);
+	MSG_WriteFloat(&buf, movevars.friction);
+	MSG_WriteFloat(&buf, movevars.waterfriction);
+	MSG_WriteFloat(&buf, movevars.entgravity);
+
+	// send music
+	MSG_WriteByte (&buf, svc_cdtrack);
+	MSG_WriteByte (&buf, 0); // none in demos
+
+	// send server info string
+	MSG_WriteByte (&buf, svc_stufftext);
+	MSG_WriteString (&buf, va("fullserverinfo \"%s\"\n", cl.serverinfo) );
+
+	// flush packet
+	CL_WriteRecordDemoMessage (&buf, seq++);
+	SZ_Clear (&buf); 
+
+// soundlist
+	MSG_WriteByte (&buf, svc_soundlist);
+	MSG_WriteByte (&buf, 0);
+
+	n = 0;
+	s = cl.sound_name[n+1];
+	while (*s) {
+		MSG_WriteString (&buf, s);
+		if (buf.cursize > MAX_MSGLEN/2) {
+			MSG_WriteByte (&buf, 0);
+			MSG_WriteByte (&buf, n);
+			CL_WriteRecordDemoMessage (&buf, seq++);
+			SZ_Clear (&buf); 
+			MSG_WriteByte (&buf, svc_soundlist);
+			MSG_WriteByte (&buf, n + 1);
+		}
+		n++;
+		s = cl.sound_name[n+1];
+	}
+	if (buf.cursize) {
+		MSG_WriteByte (&buf, 0);
+		MSG_WriteByte (&buf, 0);
+		CL_WriteRecordDemoMessage (&buf, seq++);
+		SZ_Clear (&buf); 
+	}
+
+// modellist
+	MSG_WriteByte (&buf, svc_modellist);
+	MSG_WriteByte (&buf, 0);
+
+	n = 0;
+	s = cl.model_name[n+1];
+	while (*s) {
+		MSG_WriteString (&buf, s);
+		if (buf.cursize > MAX_MSGLEN/2) {
+			MSG_WriteByte (&buf, 0);
+			MSG_WriteByte (&buf, n);
+			CL_WriteRecordDemoMessage (&buf, seq++);
+			SZ_Clear (&buf); 
+			MSG_WriteByte (&buf, svc_modellist);
+			MSG_WriteByte (&buf, n + 1);
+		}
+		n++;
+		s = cl.model_name[n+1];
+	}
+	if (buf.cursize) {
+		MSG_WriteByte (&buf, 0);
+		MSG_WriteByte (&buf, 0);
+		CL_WriteRecordDemoMessage (&buf, seq++);
+		SZ_Clear (&buf); 
+	}
+
+// spawnstatic
+
+	for (i = 0; i < cl.num_statics; i++) {
+		ent = cl_static_entities + i;
+
+		MSG_WriteByte (&buf, svc_spawnstatic);
+
+		for (j = 1; j < MAX_MODELS; j++)
+			if (ent->model == cl.model_precache[j])
+				break;
+		if (j == MAX_MODELS)
+			MSG_WriteByte (&buf, 0);
+		else
+			MSG_WriteByte (&buf, j);
+
+		MSG_WriteByte (&buf, ent->frame);
+		MSG_WriteByte (&buf, 0);
+		MSG_WriteByte (&buf, ent->skinnum);
+		for (j=0 ; j<3 ; j++)
+		{
+			MSG_WriteCoord (&buf, ent->origin[j]);
+			MSG_WriteAngle (&buf, ent->angles[j]);
+		}
+
+		if (buf.cursize > MAX_MSGLEN/2) {
+			CL_WriteRecordDemoMessage (&buf, seq++);
+			SZ_Clear (&buf); 
+		}
+	}
+
+// spawnstaticsound
+	// static sounds are skipped in demos, life is hard
+
+// baselines
+
+	memset(&blankes, 0, sizeof(blankes));
+	for (i = 0; i < MAX_EDICTS; i++) {
+		es = cl_baselines + i;
+
+		if (memcmp(es, &blankes, sizeof(blankes))) {
+			MSG_WriteByte (&buf,svc_spawnbaseline);		
+			MSG_WriteShort (&buf, i);
+
+			MSG_WriteByte (&buf, es->modelindex);
+			MSG_WriteByte (&buf, es->frame);
+			MSG_WriteByte (&buf, es->colormap);
+			MSG_WriteByte (&buf, es->skinnum);
+			for (j=0 ; j<3 ; j++)
+			{
+				MSG_WriteCoord(&buf, es->origin[j]);
+				MSG_WriteAngle(&buf, es->angles[j]);
+			}
+
+			if (buf.cursize > MAX_MSGLEN/2) {
+				CL_WriteRecordDemoMessage (&buf, seq++);
+				SZ_Clear (&buf); 
+			}
+		}
+	}
+
+	MSG_WriteByte (&buf, svc_stufftext);
+	MSG_WriteString (&buf, va("cmd spawn %i 0\n", cl.servercount) );
+
+	if (buf.cursize) {
+		CL_WriteRecordDemoMessage (&buf, seq++);
+		SZ_Clear (&buf); 
+	}
+
+// send current status of all other players
+
+	for (i = 0; i < MAX_CLIENTS; i++) {
+		player = cl.players + i;
+
+		MSG_WriteByte (&buf, svc_updatefrags);
+		MSG_WriteByte (&buf, i);
+		MSG_WriteShort (&buf, player->frags);
+		
+		MSG_WriteByte (&buf, svc_updateping);
+		MSG_WriteByte (&buf, i);
+		MSG_WriteShort (&buf, player->ping);
+		
+		MSG_WriteByte (&buf, svc_updatepl);
+		MSG_WriteByte (&buf, i);
+		MSG_WriteByte (&buf, player->pl);
+		
+		MSG_WriteByte (&buf, svc_updateentertime);
+		MSG_WriteByte (&buf, i);
+		MSG_WriteFloat (&buf, player->entertime);
+
+		MSG_WriteByte (&buf, svc_updateuserinfo);
+		MSG_WriteByte (&buf, i);
+		MSG_WriteLong (&buf, player->userid);
+		MSG_WriteString (&buf, player->userinfo);
+
+		if (buf.cursize > MAX_MSGLEN/2) {
+			CL_WriteRecordDemoMessage (&buf, seq++);
+			SZ_Clear (&buf); 
+		}
+	}
+	
+// send all current light styles
+	for (i=0 ; i<MAX_LIGHTSTYLES ; i++)
+	{
+		MSG_WriteByte (&buf, svc_lightstyle);
+		MSG_WriteByte (&buf, (char)i);
+		MSG_WriteString (&buf, cl_lightstyle[i].map);
+	}
+
+	for (i = 0; i < MAX_CL_STATS; i++) {
+		MSG_WriteByte (&buf, svc_updatestatlong);
+		MSG_WriteByte (&buf, i);
+		MSG_WriteLong (&buf, cl.stats[i]);
+		if (buf.cursize > MAX_MSGLEN/2) {
+			CL_WriteRecordDemoMessage (&buf, seq++);
+			SZ_Clear (&buf); 
+		}
+	}
+
+#if 0
+	MSG_WriteByte (&buf, svc_updatestatlong);
+	MSG_WriteByte (&buf, STAT_TOTALMONSTERS);
+	MSG_WriteLong (&buf, cl.stats[STAT_TOTALMONSTERS]);
+
+	MSG_WriteByte (&buf, svc_updatestatlong);
+	MSG_WriteByte (&buf, STAT_SECRETS);
+	MSG_WriteLong (&buf, cl.stats[STAT_SECRETS]);
+
+	MSG_WriteByte (&buf, svc_updatestatlong);
+	MSG_WriteByte (&buf, STAT_MONSTERS);
+	MSG_WriteLong (&buf, cl.stats[STAT_MONSTERS]);
+#endif
+
+	// get the client to check and download skins
+	// when that is completed, a begin command will be issued
+	MSG_WriteByte (&buf, svc_stufftext);
+	MSG_WriteString (&buf, va("skins\n") );
+
+	CL_WriteRecordDemoMessage (&buf, seq++);
+
+	CL_WriteSetDemoMessage();
+
+	// done
+}
+
+/*
+====================
+CL_ReRecord_f
+
+record <demoname>
+====================
+*/
+void CL_ReRecord_f (void)
+{
+	int		c;
+	char	name[MAX_OSPATH];
+
+	c = Cmd_Argc();
+	if (c != 2)
+	{
+		Con_Printf ("rerecord <demoname>\n");
+		return;
+	}
+
+	if (!*cls.servername) {
+		Con_Printf("No server to reconnect to...\n");
+		return;
+	}
+
+	if (cls.demorecording)
+		CL_Stop_f();
+  
+	sprintf (name, "%s/%s", com_gamedir, Cmd_Argv(1));
+
+//
+// open the demo file
+//
+	COM_DefaultExtension (name, ".qwd");
+
+	cls.demofile = fopen (name, "wb");
+	if (!cls.demofile)
+	{
+		Con_Printf ("ERROR: couldn't open.\n");
+		return;
+	}
+
+	Con_Printf ("recording to %s.\n", name);
+	cls.demorecording = true;
+
+	CL_Disconnect();
+	CL_BeginServerConnect();
+}
+
+
+/*
+====================
+CL_PlayDemo_f
+
+play [demoname]
+====================
+*/
+void CL_PlayDemo_f (void)
+{
+	char	name[256];
+
+	if (Cmd_Argc() != 2)
+	{
+		Con_Printf ("play <demoname> : plays a demo\n");
+		return;
+	}
+
+//
+// disconnect from server
+//
+	CL_Disconnect ();
+	
+//
+// open the demo file
+//
+	strcpy (name, Cmd_Argv(1));
+	COM_DefaultExtension (name, ".qwd");
+
+	Con_Printf ("Playing demo from %s.\n", name);
+	COM_FOpenFile (name, &cls.demofile);
+	if (!cls.demofile)
+	{
+		Con_Printf ("ERROR: couldn't open.\n");
+		cls.demonum = -1;		// stop demo loop
+		return;
+	}
+
+	cls.demoplayback = true;
+	cls.state = ca_demostart;
+	Netchan_Setup (&cls.netchan, net_from, 0);
+	realtime = 0;
+}
+
+/*
+====================
+CL_FinishTimeDemo
+
+====================
+*/
+void CL_FinishTimeDemo (void)
+{
+	int		frames;
+	float	time;
+	
+	cls.timedemo = false;
+	
+// the first frame didn't count
+	frames = (host_framecount - cls.td_startframe) - 1;
+	time = Sys_DoubleTime() - cls.td_starttime;
+	if (!time)
+		time = 1;
+	Con_Printf ("%i frames %5.1f seconds %5.1f fps\n", frames, time, frames/time);
+}
+
+/*
+====================
+CL_TimeDemo_f
+
+timedemo [demoname]
+====================
+*/
+void CL_TimeDemo_f (void)
+{
+	if (Cmd_Argc() != 2)
+	{
+		Con_Printf ("timedemo <demoname> : gets demo speeds\n");
+		return;
+	}
+
+	CL_PlayDemo_f ();
+	
+	if (cls.state != ca_demostart)
+		return;
+
+// cls.td_starttime will be grabbed at the second frame of the demo, so
+// all the loading time doesn't get counted
+	
+	cls.timedemo = true;
+	cls.td_starttime = 0;
+	cls.td_startframe = host_framecount;
+	cls.td_lastframe = -1;		// get a new message this frame
+}
+
--- /dev/null
+++ b/QW/client/cl_ents.c
@@ -1,0 +1,1083 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// cl_ents.c -- entity parsing and management
+
+#include "quakedef.h"
+
+extern	cvar_t	cl_predict_players;
+extern	cvar_t	cl_predict_players2;
+extern	cvar_t	cl_solid_players;
+
+static struct predicted_player {
+	int flags;
+	qboolean active;
+	vec3_t origin;	// predicted origin
+} predicted_players[MAX_CLIENTS];
+
+//============================================================
+
+/*
+===============
+CL_AllocDlight
+
+===============
+*/
+dlight_t *CL_AllocDlight (int key)
+{
+	int		i;
+	dlight_t	*dl;
+
+// first look for an exact key match
+	if (key)
+	{
+		dl = cl_dlights;
+		for (i=0 ; i<MAX_DLIGHTS ; i++, dl++)
+		{
+			if (dl->key == key)
+			{
+				memset (dl, 0, sizeof(*dl));
+				dl->key = key;
+				return dl;
+			}
+		}
+	}
+
+// then look for anything else
+	dl = cl_dlights;
+	for (i=0 ; i<MAX_DLIGHTS ; i++, dl++)
+	{
+		if (dl->die < cl.time)
+		{
+			memset (dl, 0, sizeof(*dl));
+			dl->key = key;
+			return dl;
+		}
+	}
+
+	dl = &cl_dlights[0];
+	memset (dl, 0, sizeof(*dl));
+	dl->key = key;
+	return dl;
+}
+
+/*
+===============
+CL_NewDlight
+===============
+*/
+void CL_NewDlight (int key, float x, float y, float z, float radius, float time,
+				   int type)
+{
+	dlight_t	*dl;
+
+	dl = CL_AllocDlight (key);
+	dl->origin[0] = x;
+	dl->origin[1] = y;
+	dl->origin[2] = z;
+	dl->radius = radius;
+	dl->die = cl.time + time;
+	if (type == 0) {
+		dl->color[0] = 0.2;
+		dl->color[1] = 0.1;
+		dl->color[2] = 0.05;
+		dl->color[3] = 0.7;
+	} else if (type == 1) {
+		dl->color[0] = 0.05;
+		dl->color[1] = 0.05;
+		dl->color[2] = 0.3;
+		dl->color[3] = 0.7;
+	} else if (type == 2) {
+		dl->color[0] = 0.5;
+		dl->color[1] = 0.05;
+		dl->color[2] = 0.05;
+		dl->color[3] = 0.7;
+	} else if (type == 3) {
+		dl->color[0]=0.5;
+		dl->color[1] = 0.05;
+		dl->color[2] = 0.4;
+		dl->color[3] = 0.7;
+	}
+}
+
+
+/*
+===============
+CL_DecayLights
+
+===============
+*/
+void CL_DecayLights (void)
+{
+	int			i;
+	dlight_t	*dl;
+
+	dl = cl_dlights;
+	for (i=0 ; i<MAX_DLIGHTS ; i++, dl++)
+	{
+		if (dl->die < cl.time || !dl->radius)
+			continue;
+		
+		dl->radius -= host_frametime*dl->decay;
+		if (dl->radius < 0)
+			dl->radius = 0;
+	}
+}
+
+
+/*
+=========================================================================
+
+PACKET ENTITY PARSING / LINKING
+
+=========================================================================
+*/
+
+/*
+==================
+CL_ParseDelta
+
+Can go from either a baseline or a previous packet_entity
+==================
+*/
+int	bitcounts[32];	/// just for protocol profiling
+void CL_ParseDelta (entity_state_t *from, entity_state_t *to, int bits)
+{
+	int			i;
+
+	// set everything to the state we are delta'ing from
+	*to = *from;
+
+	to->number = bits & 511;
+	bits &= ~511;
+
+	if (bits & U_MOREBITS)
+	{	// read in the low order bits
+		i = MSG_ReadByte ();
+		bits |= i;
+	}
+
+	// count the bits for net profiling
+	for (i=0 ; i<16 ; i++)
+		if (bits&(1<<i))
+			bitcounts[i]++;
+
+	to->flags = bits;
+	
+	if (bits & U_MODEL)
+		to->modelindex = MSG_ReadByte ();
+		
+	if (bits & U_FRAME)
+		to->frame = MSG_ReadByte ();
+
+	if (bits & U_COLORMAP)
+		to->colormap = MSG_ReadByte();
+
+	if (bits & U_SKIN)
+		to->skinnum = MSG_ReadByte();
+
+	if (bits & U_EFFECTS)
+		to->effects = MSG_ReadByte();
+
+	if (bits & U_ORIGIN1)
+		to->origin[0] = MSG_ReadCoord ();
+		
+	if (bits & U_ANGLE1)
+		to->angles[0] = MSG_ReadAngle();
+
+	if (bits & U_ORIGIN2)
+		to->origin[1] = MSG_ReadCoord ();
+		
+	if (bits & U_ANGLE2)
+		to->angles[1] = MSG_ReadAngle();
+
+	if (bits & U_ORIGIN3)
+		to->origin[2] = MSG_ReadCoord ();
+		
+	if (bits & U_ANGLE3)
+		to->angles[2] = MSG_ReadAngle();
+
+	if (bits & U_SOLID)
+	{
+		// FIXME
+	}
+}
+
+
+/*
+=================
+FlushEntityPacket
+=================
+*/
+void FlushEntityPacket (void)
+{
+	int			word;
+	entity_state_t	olde, newe;
+
+	Con_DPrintf ("FlushEntityPacket\n");
+
+	memset (&olde, 0, sizeof(olde));
+
+	cl.validsequence = 0;		// can't render a frame
+	cl.frames[cls.netchan.incoming_sequence&UPDATE_MASK].invalid = true;
+
+	// read it all, but ignore it
+	while (1)
+	{
+		word = (unsigned short)MSG_ReadShort ();
+		if (msg_badread)
+		{	// something didn't parse right...
+			Host_EndGame ("msg_badread in packetentities");
+			return;
+		}
+
+		if (!word)
+			break;	// done
+
+		CL_ParseDelta (&olde, &newe, word);
+	}
+}
+
+/*
+==================
+CL_ParsePacketEntities
+
+An svc_packetentities has just been parsed, deal with the
+rest of the data stream.
+==================
+*/
+void CL_ParsePacketEntities (qboolean delta)
+{
+	int			oldpacket, newpacket;
+	packet_entities_t	*oldp, *newp, dummy;
+	int			oldindex, newindex;
+	int			word, newnum, oldnum;
+	qboolean	full;
+	byte		from;
+
+	newpacket = cls.netchan.incoming_sequence&UPDATE_MASK;
+	newp = &cl.frames[newpacket].packet_entities;
+	cl.frames[newpacket].invalid = false;
+
+	if (delta)
+	{
+		from = MSG_ReadByte ();
+
+		oldpacket = cl.frames[newpacket].delta_sequence;
+
+		if ( (from&UPDATE_MASK) != (oldpacket&UPDATE_MASK) )
+			Con_DPrintf ("WARNING: from mismatch\n");
+	}
+	else
+		oldpacket = -1;
+
+	full = false;
+	if (oldpacket != -1)
+	{
+		if (cls.netchan.outgoing_sequence - oldpacket >= UPDATE_BACKUP-1)
+		{	// we can't use this, it is too old
+			FlushEntityPacket ();
+			return;
+		}
+		cl.validsequence = cls.netchan.incoming_sequence;
+		oldp = &cl.frames[oldpacket&UPDATE_MASK].packet_entities;
+	}
+	else
+	{	// this is a full update that we can start delta compressing from now
+		oldp = &dummy;
+		dummy.num_entities = 0;
+		cl.validsequence = cls.netchan.incoming_sequence;
+		full = true;
+	}
+
+	oldindex = 0;
+	newindex = 0;
+	newp->num_entities = 0;
+
+	while (1)
+	{
+		word = (unsigned short)MSG_ReadShort ();
+		if (msg_badread)
+		{	// something didn't parse right...
+			Host_EndGame ("msg_badread in packetentities");
+			return;
+		}
+
+		if (!word)
+		{
+			while (oldindex < oldp->num_entities)
+			{	// copy all the rest of the entities from the old packet
+//Con_Printf ("copy %i\n", oldp->entities[oldindex].number);
+				if (newindex >= MAX_PACKET_ENTITIES)
+					Host_EndGame ("CL_ParsePacketEntities: newindex == MAX_PACKET_ENTITIES");
+				newp->entities[newindex] = oldp->entities[oldindex];
+				newindex++;
+				oldindex++;
+			}
+			break;
+		}
+		newnum = word&511;
+		oldnum = oldindex >= oldp->num_entities ? 9999 : oldp->entities[oldindex].number;
+
+		while (newnum > oldnum)
+		{
+			if (full)
+			{
+				Con_Printf ("WARNING: oldcopy on full update");
+				FlushEntityPacket ();
+				return;
+			}
+
+//Con_Printf ("copy %i\n", oldnum);
+			// copy one of the old entities over to the new packet unchanged
+			if (newindex >= MAX_PACKET_ENTITIES)
+				Host_EndGame ("CL_ParsePacketEntities: newindex == MAX_PACKET_ENTITIES");
+			newp->entities[newindex] = oldp->entities[oldindex];
+			newindex++;
+			oldindex++;
+			oldnum = oldindex >= oldp->num_entities ? 9999 : oldp->entities[oldindex].number;
+		}
+
+		if (newnum < oldnum)
+		{	// new from baseline
+//Con_Printf ("baseline %i\n", newnum);
+			if (word & U_REMOVE)
+			{
+				if (full)
+				{
+					cl.validsequence = 0;
+					Con_Printf ("WARNING: U_REMOVE on full update\n");
+					FlushEntityPacket ();
+					return;
+				}
+				continue;
+			}
+			if (newindex >= MAX_PACKET_ENTITIES)
+				Host_EndGame ("CL_ParsePacketEntities: newindex == MAX_PACKET_ENTITIES");
+			CL_ParseDelta (&cl_baselines[newnum], &newp->entities[newindex], word);
+			newindex++;
+			continue;
+		}
+
+		if (newnum == oldnum)
+		{	// delta from previous
+			if (full)
+			{
+				cl.validsequence = 0;
+				Con_Printf ("WARNING: delta on full update");
+			}
+			if (word & U_REMOVE)
+			{
+				oldindex++;
+				continue;
+			}
+//Con_Printf ("delta %i\n",newnum);
+			CL_ParseDelta (&oldp->entities[oldindex], &newp->entities[newindex], word);
+			newindex++;
+			oldindex++;
+		}
+
+	}
+
+	newp->num_entities = newindex;
+}
+
+
+/*
+===============
+CL_LinkPacketEntities
+
+===============
+*/
+void CL_LinkPacketEntities (void)
+{
+	entity_t			*ent;
+	packet_entities_t	*pack;
+	entity_state_t		*s1, *s2;
+	float				f;
+	model_t				*model;
+	vec3_t				old_origin;
+	float				autorotate;
+	int					i;
+	int					pnum;
+	dlight_t			*dl;
+
+	pack = &cl.frames[cls.netchan.incoming_sequence&UPDATE_MASK].packet_entities;
+
+	autorotate = anglemod(100*cl.time);
+
+	f = 0;		// FIXME: no interpolation right now
+
+	for (pnum=0 ; pnum<pack->num_entities ; pnum++)
+	{
+		s1 = &pack->entities[pnum];
+		s2 = s1;	// FIXME: no interpolation right now
+
+		// spawn light flashes, even ones coming from invisible objects
+		if ((s1->effects & (EF_BLUE | EF_RED)) == (EF_BLUE | EF_RED))
+			CL_NewDlight (s1->number, s1->origin[0], s1->origin[1], s1->origin[2], 200 + (rand()&31), 0.1, 3);
+		else if (s1->effects & EF_BLUE)
+			CL_NewDlight (s1->number, s1->origin[0], s1->origin[1], s1->origin[2], 200 + (rand()&31), 0.1, 1);
+		else if (s1->effects & EF_RED)
+			CL_NewDlight (s1->number, s1->origin[0], s1->origin[1], s1->origin[2], 200 + (rand()&31), 0.1, 2);
+		else if (s1->effects & EF_BRIGHTLIGHT)
+			CL_NewDlight (s1->number, s1->origin[0], s1->origin[1], s1->origin[2] + 16, 400 + (rand()&31), 0.1, 0);
+		else if (s1->effects & EF_DIMLIGHT)
+			CL_NewDlight (s1->number, s1->origin[0], s1->origin[1], s1->origin[2], 200 + (rand()&31), 0.1, 0);
+
+		// if set to invisible, skip
+		if (!s1->modelindex)
+			continue;
+
+		// create a new entity
+		if (cl_numvisedicts == MAX_VISEDICTS)
+			break;		// object list is full
+
+		ent = &cl_visedicts[cl_numvisedicts];
+		cl_numvisedicts++;
+
+		ent->keynum = s1->number;
+		ent->model = model = cl.model_precache[s1->modelindex];
+	
+		// set colormap
+		if (s1->colormap && (s1->colormap < MAX_CLIENTS) 
+			&& !strcmp(ent->model->name,"progs/player.mdl") )
+		{
+			ent->colormap = cl.players[s1->colormap-1].translations;
+			ent->scoreboard = &cl.players[s1->colormap-1];
+		}
+		else
+		{
+			ent->colormap = vid.colormap;
+			ent->scoreboard = NULL;
+		}
+
+		// set skin
+		ent->skinnum = s1->skinnum;
+		
+		// set frame
+		ent->frame = s1->frame;
+
+		// rotate binary objects locally
+		if (model->flags & EF_ROTATE)
+		{
+			ent->angles[0] = 0;
+			ent->angles[1] = autorotate;
+			ent->angles[2] = 0;
+		}
+		else
+		{
+			float	a1, a2;
+
+			for (i=0 ; i<3 ; i++)
+			{
+				a1 = s1->angles[i];
+				a2 = s2->angles[i];
+				if (a1 - a2 > 180)
+					a1 -= 360;
+				if (a1 - a2 < -180)
+					a1 += 360;
+				ent->angles[i] = a2 + f * (a1 - a2);
+			}
+		}
+
+		// calculate origin
+		for (i=0 ; i<3 ; i++)
+			ent->origin[i] = s2->origin[i] + 
+			f * (s1->origin[i] - s2->origin[i]);
+
+		// add automatic particle trails
+		if (!model->flags)
+			continue;
+
+		// scan the old entity display list for a matching
+		for (i=0 ; i<cl_oldnumvisedicts ; i++)
+		{
+			if (cl_oldvisedicts[i].keynum == ent->keynum)
+			{
+				VectorCopy (cl_oldvisedicts[i].origin, old_origin);
+				break;
+			}
+		}
+		if (i == cl_oldnumvisedicts)
+			continue;		// not in last message
+
+		for (i=0 ; i<3 ; i++)
+			if ( abs(old_origin[i] - ent->origin[i]) > 128)
+			{	// no trail if too far
+				VectorCopy (ent->origin, old_origin);
+				break;
+			}
+		if (model->flags & EF_ROCKET)
+		{
+			R_RocketTrail (old_origin, ent->origin, 0);
+			dl = CL_AllocDlight (s1->number);
+			VectorCopy (ent->origin, dl->origin);
+			dl->radius = 200;
+			dl->die = cl.time + 0.1;
+		}
+		else if (model->flags & EF_GRENADE)
+			R_RocketTrail (old_origin, ent->origin, 1);
+		else if (model->flags & EF_GIB)
+			R_RocketTrail (old_origin, ent->origin, 2);
+		else if (model->flags & EF_ZOMGIB)
+			R_RocketTrail (old_origin, ent->origin, 4);
+		else if (model->flags & EF_TRACER)
+			R_RocketTrail (old_origin, ent->origin, 3);
+		else if (model->flags & EF_TRACER2)
+			R_RocketTrail (old_origin, ent->origin, 5);
+		else if (model->flags & EF_TRACER3)
+			R_RocketTrail (old_origin, ent->origin, 6);
+	}
+}
+
+
+/*
+=========================================================================
+
+PROJECTILE PARSING / LINKING
+
+=========================================================================
+*/
+
+typedef struct
+{
+	int		modelindex;
+	vec3_t	origin;
+	vec3_t	angles;
+} projectile_t;
+
+#define	MAX_PROJECTILES	32
+projectile_t	cl_projectiles[MAX_PROJECTILES];
+int				cl_num_projectiles;
+
+extern int cl_spikeindex;
+
+void CL_ClearProjectiles (void)
+{
+	cl_num_projectiles = 0;
+}
+
+/*
+=====================
+CL_ParseProjectiles
+
+Nails are passed as efficient temporary entities
+=====================
+*/
+void CL_ParseProjectiles (void)
+{
+	int		i, c, j;
+	byte	bits[6];
+	projectile_t	*pr;
+
+	c = MSG_ReadByte ();
+	for (i=0 ; i<c ; i++)
+	{
+		for (j=0 ; j<6 ; j++)
+			bits[j] = MSG_ReadByte ();
+
+		if (cl_num_projectiles == MAX_PROJECTILES)
+			continue;
+
+		pr = &cl_projectiles[cl_num_projectiles];
+		cl_num_projectiles++;
+
+		pr->modelindex = cl_spikeindex;
+		pr->origin[0] = ( ( bits[0] + ((bits[1]&15)<<8) ) <<1) - 4096;
+		pr->origin[1] = ( ( (bits[1]>>4) + (bits[2]<<4) ) <<1) - 4096;
+		pr->origin[2] = ( ( bits[3] + ((bits[4]&15)<<8) ) <<1) - 4096;
+		pr->angles[0] = 360*(bits[4]>>4)/16;
+		pr->angles[1] = 360*bits[5]/256;
+	}
+}
+
+/*
+=============
+CL_LinkProjectiles
+
+=============
+*/
+void CL_LinkProjectiles (void)
+{
+	int		i;
+	projectile_t	*pr;
+	entity_t		*ent;
+
+	for (i=0, pr=cl_projectiles ; i<cl_num_projectiles ; i++, pr++)
+	{
+		// grab an entity to fill in
+		if (cl_numvisedicts == MAX_VISEDICTS)
+			break;		// object list is full
+		ent = &cl_visedicts[cl_numvisedicts];
+		cl_numvisedicts++;
+		ent->keynum = 0;
+
+		if (pr->modelindex < 1)
+			continue;
+		ent->model = cl.model_precache[pr->modelindex];
+		ent->skinnum = 0;
+		ent->frame = 0;
+		ent->colormap = vid.colormap;
+		ent->scoreboard = NULL;
+		VectorCopy (pr->origin, ent->origin);
+		VectorCopy (pr->angles, ent->angles);
+	}
+}
+
+//========================================
+
+extern	int		cl_spikeindex, cl_playerindex, cl_flagindex;
+
+entity_t *CL_NewTempEntity (void);
+
+/*
+===================
+CL_ParsePlayerinfo
+===================
+*/
+extern int parsecountmod;
+extern double parsecounttime;
+void CL_ParsePlayerinfo (void)
+{
+	int			msec;
+	int			flags;
+	player_info_t	*info;
+	player_state_t	*state;
+	int			num;
+	int			i;
+
+	num = MSG_ReadByte ();
+	if (num > MAX_CLIENTS)
+		Sys_Error ("CL_ParsePlayerinfo: bad num");
+
+	info = &cl.players[num];
+
+	state = &cl.frames[parsecountmod].playerstate[num];
+
+	flags = state->flags = MSG_ReadShort ();
+
+	state->messagenum = cl.parsecount;
+	state->origin[0] = MSG_ReadCoord ();
+	state->origin[1] = MSG_ReadCoord ();
+	state->origin[2] = MSG_ReadCoord ();
+
+	state->frame = MSG_ReadByte ();
+
+	// the other player's last move was likely some time
+	// before the packet was sent out, so accurately track
+	// the exact time it was valid at
+	if (flags & PF_MSEC)
+	{
+		msec = MSG_ReadByte ();
+		state->state_time = parsecounttime - msec*0.001;
+	}
+	else
+		state->state_time = parsecounttime;
+
+	if (flags & PF_COMMAND)
+		MSG_ReadDeltaUsercmd (&nullcmd, &state->command);
+
+	for (i=0 ; i<3 ; i++)
+	{
+		if (flags & (PF_VELOCITY1<<i) )
+			state->velocity[i] = MSG_ReadShort();
+		else
+			state->velocity[i] = 0;
+	}
+	if (flags & PF_MODEL)
+		state->modelindex = MSG_ReadByte ();
+	else
+		state->modelindex = cl_playerindex;
+
+	if (flags & PF_SKINNUM)
+		state->skinnum = MSG_ReadByte ();
+	else
+		state->skinnum = 0;
+
+	if (flags & PF_EFFECTS)
+		state->effects = MSG_ReadByte ();
+	else
+		state->effects = 0;
+
+	if (flags & PF_WEAPONFRAME)
+		state->weaponframe = MSG_ReadByte ();
+	else
+		state->weaponframe = 0;
+
+	VectorCopy (state->command.angles, state->viewangles);
+}
+
+
+/*
+================
+CL_AddFlagModels
+
+Called when the CTF flags are set
+================
+*/
+void CL_AddFlagModels (entity_t *ent, int team)
+{
+	int		i;
+	float	f;
+	vec3_t	v_forward, v_right, v_up;
+	entity_t	*newent;
+
+	if (cl_flagindex == -1)
+		return;
+
+	f = 14;
+	if (ent->frame >= 29 && ent->frame <= 40) {
+		if (ent->frame >= 29 && ent->frame <= 34) { //axpain
+			if      (ent->frame == 29) f = f + 2; 
+			else if (ent->frame == 30) f = f + 8;
+			else if (ent->frame == 31) f = f + 12;
+			else if (ent->frame == 32) f = f + 11;
+			else if (ent->frame == 33) f = f + 10;
+			else if (ent->frame == 34) f = f + 4;
+		} else if (ent->frame >= 35 && ent->frame <= 40) { // pain
+			if      (ent->frame == 35) f = f + 2; 
+			else if (ent->frame == 36) f = f + 10;
+			else if (ent->frame == 37) f = f + 10;
+			else if (ent->frame == 38) f = f + 8;
+			else if (ent->frame == 39) f = f + 4;
+			else if (ent->frame == 40) f = f + 2;
+		}
+	} else if (ent->frame >= 103 && ent->frame <= 118) {
+		if      (ent->frame >= 103 && ent->frame <= 104) f = f + 6;  //nailattack
+		else if (ent->frame >= 105 && ent->frame <= 106) f = f + 6;  //light 
+		else if (ent->frame >= 107 && ent->frame <= 112) f = f + 7;  //rocketattack
+		else if (ent->frame >= 112 && ent->frame <= 118) f = f + 7;  //shotattack
+	}
+
+	newent = CL_NewTempEntity ();
+	newent->model = cl.model_precache[cl_flagindex];
+	newent->skinnum = team;
+
+	AngleVectors (ent->angles, v_forward, v_right, v_up);
+	v_forward[2] = -v_forward[2]; // reverse z component
+	for (i=0 ; i<3 ; i++)
+		newent->origin[i] = ent->origin[i] - f*v_forward[i] + 22*v_right[i];
+	newent->origin[2] -= 16;
+
+	VectorCopy (ent->angles, newent->angles)
+	newent->angles[2] -= 45;
+}
+
+/*
+=============
+CL_LinkPlayers
+
+Create visible entities in the correct position
+for all current players
+=============
+*/
+void CL_LinkPlayers (void)
+{
+	int				j;
+	player_info_t	*info;
+	player_state_t	*state;
+	player_state_t	exact;
+	double			playertime;
+	entity_t		*ent;
+	int				msec;
+	frame_t			*frame;
+	int				oldphysent;
+
+	playertime = realtime - cls.latency + 0.02;
+	if (playertime > realtime)
+		playertime = realtime;
+
+	frame = &cl.frames[cl.parsecount&UPDATE_MASK];
+
+	for (j=0, info=cl.players, state=frame->playerstate ; j < MAX_CLIENTS 
+		; j++, info++, state++)
+	{
+		if (state->messagenum != cl.parsecount)
+			continue;	// not present this frame
+
+		// spawn light flashes, even ones coming from invisible objects
+#ifdef GLQUAKE
+		if (!gl_flashblend.value || j != cl.playernum) {
+#endif
+			if ((state->effects & (EF_BLUE | EF_RED)) == (EF_BLUE | EF_RED))
+				CL_NewDlight (j, state->origin[0], state->origin[1], state->origin[2], 200 + (rand()&31), 0.1, 3);
+			else if (state->effects & EF_BLUE)
+				CL_NewDlight (j, state->origin[0], state->origin[1], state->origin[2], 200 + (rand()&31), 0.1, 1);
+			else if (state->effects & EF_RED)
+				CL_NewDlight (j, state->origin[0], state->origin[1], state->origin[2], 200 + (rand()&31), 0.1, 2);
+			else if (state->effects & EF_BRIGHTLIGHT)
+				CL_NewDlight (j, state->origin[0], state->origin[1], state->origin[2] + 16, 400 + (rand()&31), 0.1, 0);
+			else if (state->effects & EF_DIMLIGHT)
+				CL_NewDlight (j, state->origin[0], state->origin[1], state->origin[2], 200 + (rand()&31), 0.1, 0);
+#ifdef GLQUAKE
+		}
+#endif
+
+		// the player object never gets added
+		if (j == cl.playernum)
+			continue;
+
+		if (!state->modelindex)
+			continue;
+
+		if (!Cam_DrawPlayer(j))
+			continue;
+
+		// grab an entity to fill in
+		if (cl_numvisedicts == MAX_VISEDICTS)
+			break;		// object list is full
+		ent = &cl_visedicts[cl_numvisedicts];
+		cl_numvisedicts++;
+		ent->keynum = 0;
+
+		ent->model = cl.model_precache[state->modelindex];
+		ent->skinnum = state->skinnum;
+		ent->frame = state->frame;
+		ent->colormap = info->translations;
+		if (state->modelindex == cl_playerindex)
+			ent->scoreboard = info;		// use custom skin
+		else
+			ent->scoreboard = NULL;
+
+		//
+		// angles
+		//
+		ent->angles[PITCH] = -state->viewangles[PITCH]/3;
+		ent->angles[YAW] = state->viewangles[YAW];
+		ent->angles[ROLL] = 0;
+		ent->angles[ROLL] = V_CalcRoll (ent->angles, state->velocity)*4;
+
+		// only predict half the move to minimize overruns
+		msec = 500*(playertime - state->state_time);
+		if (msec <= 0 || (!cl_predict_players.value && !cl_predict_players2.value))
+		{
+			VectorCopy (state->origin, ent->origin);
+//Con_DPrintf ("nopredict\n");
+		}
+		else
+		{
+			// predict players movement
+			if (msec > 255)
+				msec = 255;
+			state->command.msec = msec;
+//Con_DPrintf ("predict: %i\n", msec);
+
+			oldphysent = pmove.numphysent;
+			CL_SetSolidPlayers (j);
+			CL_PredictUsercmd (state, &exact, &state->command, false);
+			pmove.numphysent = oldphysent;
+			VectorCopy (exact.origin, ent->origin);
+		}
+
+		if (state->effects & EF_FLAG1)
+			CL_AddFlagModels (ent, 0);
+		else if (state->effects & EF_FLAG2)
+			CL_AddFlagModels (ent, 1);
+
+	}
+}
+
+//======================================================================
+
+/*
+===============
+CL_SetSolid
+
+Builds all the pmove physents for the current frame
+===============
+*/
+void CL_SetSolidEntities (void)
+{
+	int		i;
+	frame_t	*frame;
+	packet_entities_t	*pak;
+	entity_state_t		*state;
+
+	pmove.physents[0].model = cl.worldmodel;
+	VectorCopy (vec3_origin, pmove.physents[0].origin);
+	pmove.physents[0].info = 0;
+	pmove.numphysent = 1;
+
+	frame = &cl.frames[parsecountmod];
+	pak = &frame->packet_entities;
+
+	for (i=0 ; i<pak->num_entities ; i++)
+	{
+		state = &pak->entities[i];
+
+		if (!state->modelindex)
+			continue;
+		if (!cl.model_precache[state->modelindex])
+			continue;
+		if ( cl.model_precache[state->modelindex]->hulls[1].firstclipnode 
+			|| cl.model_precache[state->modelindex]->clipbox )
+		{
+			pmove.physents[pmove.numphysent].model = cl.model_precache[state->modelindex];
+			VectorCopy (state->origin, pmove.physents[pmove.numphysent].origin);
+			pmove.numphysent++;
+		}
+	}
+
+}
+
+/*
+===
+Calculate the new position of players, without other player clipping
+
+We do this to set up real player prediction.
+Players are predicted twice, first without clipping other players,
+then with clipping against them.
+This sets up the first phase.
+===
+*/
+void CL_SetUpPlayerPrediction(qboolean dopred)
+{
+	int				j;
+	player_state_t	*state;
+	player_state_t	exact;
+	double			playertime;
+	int				msec;
+	frame_t			*frame;
+	struct predicted_player *pplayer;
+
+	playertime = realtime - cls.latency + 0.02;
+	if (playertime > realtime)
+		playertime = realtime;
+
+	frame = &cl.frames[cl.parsecount&UPDATE_MASK];
+
+	for (j=0, pplayer = predicted_players, state=frame->playerstate; 
+		j < MAX_CLIENTS;
+		j++, pplayer++, state++) {
+
+		pplayer->active = false;
+
+		if (state->messagenum != cl.parsecount)
+			continue;	// not present this frame
+
+		if (!state->modelindex)
+			continue;
+
+		pplayer->active = true;
+		pplayer->flags = state->flags;
+
+		// note that the local player is special, since he moves locally
+		// we use his last predicted postition
+		if (j == cl.playernum) {
+			VectorCopy(cl.frames[cls.netchan.outgoing_sequence&UPDATE_MASK].playerstate[cl.playernum].origin,
+				pplayer->origin);
+		} else {
+			// only predict half the move to minimize overruns
+			msec = 500*(playertime - state->state_time);
+			if (msec <= 0 ||
+				(!cl_predict_players.value && !cl_predict_players2.value) ||
+				!dopred)
+			{
+				VectorCopy (state->origin, pplayer->origin);
+	//Con_DPrintf ("nopredict\n");
+			}
+			else
+			{
+				// predict players movement
+				if (msec > 255)
+					msec = 255;
+				state->command.msec = msec;
+	//Con_DPrintf ("predict: %i\n", msec);
+
+				CL_PredictUsercmd (state, &exact, &state->command, false);
+				VectorCopy (exact.origin, pplayer->origin);
+			}
+		}
+	}
+}
+
+/*
+===============
+CL_SetSolid
+
+Builds all the pmove physents for the current frame
+Note that CL_SetUpPlayerPrediction() must be called first!
+pmove must be setup with world and solid entity hulls before calling
+(via CL_PredictMove)
+===============
+*/
+void CL_SetSolidPlayers (int playernum)
+{
+	int		j;
+	extern	vec3_t	player_mins;
+	extern	vec3_t	player_maxs;
+	struct predicted_player *pplayer;
+	physent_t *pent;
+
+	if (!cl_solid_players.value)
+		return;
+
+	pent = pmove.physents + pmove.numphysent;
+
+	for (j=0, pplayer = predicted_players; j < MAX_CLIENTS;	j++, pplayer++) {
+
+		if (!pplayer->active)
+			continue;	// not present this frame
+
+		// the player object never gets added
+		if (j == playernum)
+			continue;
+
+		if (pplayer->flags & PF_DEAD)
+			continue; // dead players aren't solid
+
+		pent->model = 0;
+		VectorCopy(pplayer->origin, pent->origin);
+		VectorCopy(player_mins, pent->mins);
+		VectorCopy(player_maxs, pent->maxs);
+		pmove.numphysent++;
+		pent++;
+	}
+}
+
+
+/*
+===============
+CL_EmitEntities
+
+Builds the visedicts array for cl.time
+
+Made up of: clients, packet_entities, nails, and tents
+===============
+*/
+void CL_EmitEntities (void)
+{
+	if (cls.state != ca_active)
+		return;
+	if (!cl.validsequence)
+		return;
+
+	cl_oldnumvisedicts = cl_numvisedicts;
+	cl_oldvisedicts = cl_visedicts_list[(cls.netchan.incoming_sequence-1)&1];
+	cl_visedicts = cl_visedicts_list[cls.netchan.incoming_sequence&1];
+
+	cl_numvisedicts = 0;
+
+	CL_LinkPlayers ();
+	CL_LinkPacketEntities ();
+	CL_LinkProjectiles ();
+	CL_UpdateTEnts ();
+}
+
--- /dev/null
+++ b/QW/client/cl_input.c
@@ -1,0 +1,533 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// cl.input.c  -- builds an intended movement command to send to the server
+
+#include "quakedef.h"
+
+cvar_t	cl_nodelta = {"cl_nodelta","0"};
+
+/*
+===============================================================================
+
+KEY BUTTONS
+
+Continuous button event tracking is complicated by the fact that two different
+input sources (say, mouse button 1 and the control key) can both press the
+same button, but the button should only be released when both of the
+pressing key have been released.
+
+When a key event issues a button command (+forward, +attack, etc), it appends
+its key number as a parameter to the command so it can be matched up with
+the release.
+
+state bit 0 is the current state of the key
+state bit 1 is edge triggered on the up to down transition
+state bit 2 is edge triggered on the down to up transition
+
+===============================================================================
+*/
+
+
+kbutton_t	in_mlook, in_klook;
+kbutton_t	in_left, in_right, in_forward, in_back;
+kbutton_t	in_lookup, in_lookdown, in_moveleft, in_moveright;
+kbutton_t	in_strafe, in_speed, in_use, in_jump, in_attack;
+kbutton_t	in_up, in_down;
+
+int			in_impulse;
+
+
+void KeyDown (kbutton_t *b)
+{
+	int		k;
+	char	*c;
+	
+	c = Cmd_Argv(1);
+	if (c[0])
+		k = atoi(c);
+	else
+		k = -1;		// typed manually at the console for continuous down
+
+	if (k == b->down[0] || k == b->down[1])
+		return;		// repeating key
+	
+	if (!b->down[0])
+		b->down[0] = k;
+	else if (!b->down[1])
+		b->down[1] = k;
+	else
+	{
+		Con_Printf ("Three keys down for a button!\n");
+		return;
+	}
+	
+	if (b->state & 1)
+		return;		// still down
+	b->state |= 1 + 2;	// down + impulse down
+}
+
+void KeyUp (kbutton_t *b)
+{
+	int		k;
+	char	*c;
+	
+	c = Cmd_Argv(1);
+	if (c[0])
+		k = atoi(c);
+	else
+	{ // typed manually at the console, assume for unsticking, so clear all
+		b->down[0] = b->down[1] = 0;
+		b->state = 4;	// impulse up
+		return;
+	}
+
+	if (b->down[0] == k)
+		b->down[0] = 0;
+	else if (b->down[1] == k)
+		b->down[1] = 0;
+	else
+		return;		// key up without coresponding down (menu pass through)
+	if (b->down[0] || b->down[1])
+		return;		// some other key is still holding it down
+
+	if (!(b->state & 1))
+		return;		// still up (this should not happen)
+	b->state &= ~1;		// now up
+	b->state |= 4; 		// impulse up
+}
+
+void IN_KLookDown (void) {KeyDown(&in_klook);}
+void IN_KLookUp (void) {KeyUp(&in_klook);}
+void IN_MLookDown (void) {KeyDown(&in_mlook);}
+void IN_MLookUp (void) {
+KeyUp(&in_mlook);
+if ( !(in_mlook.state&1) &&  lookspring.value)
+	V_StartPitchDrift();
+}
+void IN_UpDown(void) {KeyDown(&in_up);}
+void IN_UpUp(void) {KeyUp(&in_up);}
+void IN_DownDown(void) {KeyDown(&in_down);}
+void IN_DownUp(void) {KeyUp(&in_down);}
+void IN_LeftDown(void) {KeyDown(&in_left);}
+void IN_LeftUp(void) {KeyUp(&in_left);}
+void IN_RightDown(void) {KeyDown(&in_right);}
+void IN_RightUp(void) {KeyUp(&in_right);}
+void IN_ForwardDown(void) {KeyDown(&in_forward);}
+void IN_ForwardUp(void) {KeyUp(&in_forward);}
+void IN_BackDown(void) {KeyDown(&in_back);}
+void IN_BackUp(void) {KeyUp(&in_back);}
+void IN_LookupDown(void) {KeyDown(&in_lookup);}
+void IN_LookupUp(void) {KeyUp(&in_lookup);}
+void IN_LookdownDown(void) {KeyDown(&in_lookdown);}
+void IN_LookdownUp(void) {KeyUp(&in_lookdown);}
+void IN_MoveleftDown(void) {KeyDown(&in_moveleft);}
+void IN_MoveleftUp(void) {KeyUp(&in_moveleft);}
+void IN_MoverightDown(void) {KeyDown(&in_moveright);}
+void IN_MoverightUp(void) {KeyUp(&in_moveright);}
+
+void IN_SpeedDown(void) {KeyDown(&in_speed);}
+void IN_SpeedUp(void) {KeyUp(&in_speed);}
+void IN_StrafeDown(void) {KeyDown(&in_strafe);}
+void IN_StrafeUp(void) {KeyUp(&in_strafe);}
+
+void IN_AttackDown(void) {KeyDown(&in_attack);}
+void IN_AttackUp(void) {KeyUp(&in_attack);}
+
+void IN_UseDown (void) {KeyDown(&in_use);}
+void IN_UseUp (void) {KeyUp(&in_use);}
+void IN_JumpDown (void) {KeyDown(&in_jump);}
+void IN_JumpUp (void) {KeyUp(&in_jump);}
+
+void IN_Impulse (void) {in_impulse=Q_atoi(Cmd_Argv(1));}
+
+/*
+===============
+CL_KeyState
+
+Returns 0.25 if a key was pressed and released during the frame,
+0.5 if it was pressed and held
+0 if held then released, and
+1.0 if held for the entire time
+===============
+*/
+float CL_KeyState (kbutton_t *key)
+{
+	float		val;
+	qboolean	impulsedown, impulseup, down;
+	
+	impulsedown = key->state & 2;
+	impulseup = key->state & 4;
+	down = key->state & 1;
+	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
+
+	key->state &= 1;		// clear impulses
+	
+	return val;
+}
+
+
+
+
+//==========================================================================
+
+cvar_t	cl_upspeed = {"cl_upspeed","200"};
+cvar_t	cl_forwardspeed = {"cl_forwardspeed","200", true};
+cvar_t	cl_backspeed = {"cl_backspeed","200", true};
+cvar_t	cl_sidespeed = {"cl_sidespeed","350"};
+
+cvar_t	cl_movespeedkey = {"cl_movespeedkey","2.0"};
+
+cvar_t	cl_yawspeed = {"cl_yawspeed","140"};
+cvar_t	cl_pitchspeed = {"cl_pitchspeed","150"};
+
+cvar_t	cl_anglespeedkey = {"cl_anglespeedkey","1.5"};
+
+
+/*
+================
+CL_AdjustAngles
+
+Moves the local angle positions
+================
+*/
+void CL_AdjustAngles (void)
+{
+	float	speed;
+	float	up, down;
+	
+	if (in_speed.state & 1)
+		speed = host_frametime * cl_anglespeedkey.value;
+	else
+		speed = host_frametime;
+
+	if (!(in_strafe.state & 1))
+	{
+		cl.viewangles[YAW] -= speed*cl_yawspeed.value*CL_KeyState (&in_right);
+		cl.viewangles[YAW] += speed*cl_yawspeed.value*CL_KeyState (&in_left);
+		cl.viewangles[YAW] = anglemod(cl.viewangles[YAW]);
+	}
+	if (in_klook.state & 1)
+	{
+		V_StopPitchDrift ();
+		cl.viewangles[PITCH] -= speed*cl_pitchspeed.value * CL_KeyState (&in_forward);
+		cl.viewangles[PITCH] += speed*cl_pitchspeed.value * CL_KeyState (&in_back);
+	}
+	
+	up = CL_KeyState (&in_lookup);
+	down = CL_KeyState(&in_lookdown);
+	
+	cl.viewangles[PITCH] -= speed*cl_pitchspeed.value * up;
+	cl.viewangles[PITCH] += speed*cl_pitchspeed.value * down;
+
+	if (up || down)
+		V_StopPitchDrift ();
+		
+	if (cl.viewangles[PITCH] > 80)
+		cl.viewangles[PITCH] = 80;
+	if (cl.viewangles[PITCH] < -70)
+		cl.viewangles[PITCH] = -70;
+
+	if (cl.viewangles[ROLL] > 50)
+		cl.viewangles[ROLL] = 50;
+	if (cl.viewangles[ROLL] < -50)
+		cl.viewangles[ROLL] = -50;
+		
+}
+
+/*
+================
+CL_BaseMove
+
+Send the intended movement message to the server
+================
+*/
+void CL_BaseMove (usercmd_t *cmd)
+{	
+	CL_AdjustAngles ();
+	
+	memset (cmd, 0, sizeof(*cmd));
+	
+	VectorCopy (cl.viewangles, cmd->angles);
+	if (in_strafe.state & 1)
+	{
+		cmd->sidemove += cl_sidespeed.value * CL_KeyState (&in_right);
+		cmd->sidemove -= cl_sidespeed.value * CL_KeyState (&in_left);
+	}
+
+	cmd->sidemove += cl_sidespeed.value * CL_KeyState (&in_moveright);
+	cmd->sidemove -= cl_sidespeed.value * CL_KeyState (&in_moveleft);
+
+	cmd->upmove += cl_upspeed.value * CL_KeyState (&in_up);
+	cmd->upmove -= cl_upspeed.value * CL_KeyState (&in_down);
+
+	if (! (in_klook.state & 1) )
+	{	
+		cmd->forwardmove += cl_forwardspeed.value * CL_KeyState (&in_forward);
+		cmd->forwardmove -= cl_backspeed.value * CL_KeyState (&in_back);
+	}	
+
+//
+// adjust for speed key
+//
+	if (in_speed.state & 1)
+	{
+		cmd->forwardmove *= cl_movespeedkey.value;
+		cmd->sidemove *= cl_movespeedkey.value;
+		cmd->upmove *= cl_movespeedkey.value;
+	}	
+}
+
+int MakeChar (int i)
+{
+	i &= ~3;
+	if (i < -127*4)
+		i = -127*4;
+	if (i > 127*4)
+		i = 127*4;
+	return i;
+}
+
+/*
+==============
+CL_FinishMove
+==============
+*/
+void CL_FinishMove (usercmd_t *cmd)
+{
+	int		i;
+	int		ms;
+
+//
+// allways dump the first two message, because it may contain leftover inputs
+// from the last level
+//
+	if (++cl.movemessages <= 2)
+		return;
+//
+// figure button bits
+//	
+	if ( in_attack.state & 3 )
+		cmd->buttons |= 1;
+	in_attack.state &= ~2;
+	
+	if (in_jump.state & 3)
+		cmd->buttons |= 2;
+	in_jump.state &= ~2;
+
+	// send milliseconds of time to apply the move
+	ms = host_frametime * 1000;
+	if (ms > 250)
+		ms = 100;		// time was unreasonable
+	cmd->msec = ms;
+
+	VectorCopy (cl.viewangles, cmd->angles);
+
+	cmd->impulse = in_impulse;
+	in_impulse = 0;
+
+
+//
+// chop down so no extra bits are kept that the server wouldn't get
+//
+	cmd->forwardmove = MakeChar (cmd->forwardmove);
+	cmd->sidemove = MakeChar (cmd->sidemove);
+	cmd->upmove = MakeChar (cmd->upmove);
+
+	for (i=0 ; i<3 ; i++)
+		cmd->angles[i] = ((int)(cmd->angles[i]*65536.0/360)&65535) * (360.0/65536.0);
+}
+
+/*
+=================
+CL_SendCmd
+=================
+*/
+void CL_SendCmd (void)
+{
+	sizebuf_t	buf;
+	byte		data[128];
+	int			i;
+	usercmd_t	*cmd, *oldcmd;
+	int			checksumIndex;
+	int			lost;
+	int			seq_hash;
+
+	if (cls.demoplayback)
+		return; // sendcmds come from the demo
+
+	// save this command off for prediction
+	i = cls.netchan.outgoing_sequence & UPDATE_MASK;
+	cmd = &cl.frames[i].cmd;
+	cl.frames[i].senttime = realtime;
+	cl.frames[i].receivedtime = -1;		// we haven't gotten a reply yet
+
+//	seq_hash = (cls.netchan.outgoing_sequence & 0xffff) ; // ^ QW_CHECK_HASH;
+	seq_hash = cls.netchan.outgoing_sequence;
+
+	// get basic movement from keyboard
+	CL_BaseMove (cmd);
+
+	// allow mice or other external controllers to add to the move
+	IN_Move (cmd);
+
+	// if we are spectator, try autocam
+	if (cl.spectator)
+		Cam_Track(cmd);
+
+	CL_FinishMove(cmd);
+
+	Cam_FinishMove(cmd);
+
+// send this and the previous cmds in the message, so
+// if the last packet was dropped, it can be recovered
+	buf.maxsize = 128;
+	buf.cursize = 0;
+	buf.data = data;
+
+	MSG_WriteByte (&buf, clc_move);
+
+	// save the position for a checksum byte
+	checksumIndex = buf.cursize;
+	MSG_WriteByte (&buf, 0);
+
+	// write our lossage percentage
+	lost = CL_CalcNet();
+	MSG_WriteByte (&buf, (byte)lost);
+
+	i = (cls.netchan.outgoing_sequence-2) & UPDATE_MASK;
+	cmd = &cl.frames[i].cmd;
+	MSG_WriteDeltaUsercmd (&buf, &nullcmd, cmd);
+	oldcmd = cmd;
+
+	i = (cls.netchan.outgoing_sequence-1) & UPDATE_MASK;
+	cmd = &cl.frames[i].cmd;
+	MSG_WriteDeltaUsercmd (&buf, oldcmd, cmd);
+	oldcmd = cmd;
+
+	i = (cls.netchan.outgoing_sequence) & UPDATE_MASK;
+	cmd = &cl.frames[i].cmd;
+	MSG_WriteDeltaUsercmd (&buf, oldcmd, cmd);
+
+	// calculate a checksum over the move commands
+	buf.data[checksumIndex] = COM_BlockSequenceCRCByte(
+		buf.data + checksumIndex + 1, buf.cursize - checksumIndex - 1,
+		seq_hash);
+
+	// request delta compression of entities
+	if (cls.netchan.outgoing_sequence - cl.validsequence >= UPDATE_BACKUP-1)
+		cl.validsequence = 0;
+
+	if (cl.validsequence && !cl_nodelta.value && cls.state == ca_active &&
+		!cls.demorecording)
+	{
+		cl.frames[cls.netchan.outgoing_sequence&UPDATE_MASK].delta_sequence = cl.validsequence;
+		MSG_WriteByte (&buf, clc_delta);
+		MSG_WriteByte (&buf, cl.validsequence&255);
+	}
+	else
+		cl.frames[cls.netchan.outgoing_sequence&UPDATE_MASK].delta_sequence = -1;
+
+	if (cls.demorecording)
+		CL_WriteDemoCmd(cmd);
+
+//
+// deliver the message
+//
+	Netchan_Transmit (&cls.netchan, buf.cursize, buf.data);	
+}
+
+
+
+/*
+============
+CL_InitInput
+============
+*/
+void CL_InitInput (void)
+{
+	Cmd_AddCommand ("+moveup",IN_UpDown);
+	Cmd_AddCommand ("-moveup",IN_UpUp);
+	Cmd_AddCommand ("+movedown",IN_DownDown);
+	Cmd_AddCommand ("-movedown",IN_DownUp);
+	Cmd_AddCommand ("+left",IN_LeftDown);
+	Cmd_AddCommand ("-left",IN_LeftUp);
+	Cmd_AddCommand ("+right",IN_RightDown);
+	Cmd_AddCommand ("-right",IN_RightUp);
+	Cmd_AddCommand ("+forward",IN_ForwardDown);
+	Cmd_AddCommand ("-forward",IN_ForwardUp);
+	Cmd_AddCommand ("+back",IN_BackDown);
+	Cmd_AddCommand ("-back",IN_BackUp);
+	Cmd_AddCommand ("+lookup", IN_LookupDown);
+	Cmd_AddCommand ("-lookup", IN_LookupUp);
+	Cmd_AddCommand ("+lookdown", IN_LookdownDown);
+	Cmd_AddCommand ("-lookdown", IN_LookdownUp);
+	Cmd_AddCommand ("+strafe", IN_StrafeDown);
+	Cmd_AddCommand ("-strafe", IN_StrafeUp);
+	Cmd_AddCommand ("+moveleft", IN_MoveleftDown);
+	Cmd_AddCommand ("-moveleft", IN_MoveleftUp);
+	Cmd_AddCommand ("+moveright", IN_MoverightDown);
+	Cmd_AddCommand ("-moveright", IN_MoverightUp);
+	Cmd_AddCommand ("+speed", IN_SpeedDown);
+	Cmd_AddCommand ("-speed", IN_SpeedUp);
+	Cmd_AddCommand ("+attack", IN_AttackDown);
+	Cmd_AddCommand ("-attack", IN_AttackUp);
+	Cmd_AddCommand ("+use", IN_UseDown);
+	Cmd_AddCommand ("-use", IN_UseUp);
+	Cmd_AddCommand ("+jump", IN_JumpDown);
+	Cmd_AddCommand ("-jump", IN_JumpUp);
+	Cmd_AddCommand ("impulse", IN_Impulse);
+	Cmd_AddCommand ("+klook", IN_KLookDown);
+	Cmd_AddCommand ("-klook", IN_KLookUp);
+	Cmd_AddCommand ("+mlook", IN_MLookDown);
+	Cmd_AddCommand ("-mlook", IN_MLookUp);
+
+	Cvar_RegisterVariable (&cl_nodelta);
+}
+
+/*
+============
+CL_ClearStates
+============
+*/
+void CL_ClearStates (void)
+{
+}
+
--- /dev/null
+++ b/QW/client/cl_main.c
@@ -1,0 +1,1535 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// cl_main.c  -- client main loop
+
+#include "quakedef.h"
+#include "winquake.h"
+#ifdef _WIN32
+#include "winsock.h"
+#else
+#include <netinet/in.h>
+#endif
+
+
+// we need to declare some mouse variables here, because the menu system
+// references them even when on a unix system.
+
+qboolean	noclip_anglehack;		// remnant from old quake
+
+
+cvar_t	rcon_password = {"rcon_password", "", false};
+
+cvar_t	rcon_address = {"rcon_address", ""};
+
+cvar_t	cl_timeout = {"cl_timeout", "60"};
+
+cvar_t	cl_shownet = {"cl_shownet","0"};	// can be 0, 1, or 2
+
+cvar_t	cl_sbar		= {"cl_sbar", "0", true};
+cvar_t	cl_hudswap	= {"cl_hudswap", "0", true};
+cvar_t	cl_maxfps	= {"cl_maxfps", "0", true};
+
+cvar_t	lookspring = {"lookspring","0", true};
+cvar_t	lookstrafe = {"lookstrafe","0", true};
+cvar_t	sensitivity = {"sensitivity","3", true};
+
+cvar_t	m_pitch = {"m_pitch","0.022", true};
+cvar_t	m_yaw = {"m_yaw","0.022"};
+cvar_t	m_forward = {"m_forward","1"};
+cvar_t	m_side = {"m_side","0.8"};
+
+cvar_t	entlatency = {"entlatency", "20"};
+cvar_t	cl_predict_players = {"cl_predict_players", "1"};
+cvar_t	cl_predict_players2 = {"cl_predict_players2", "1"};
+cvar_t	cl_solid_players = {"cl_solid_players", "1"};
+
+cvar_t  localid = {"localid", ""};
+
+static qboolean allowremotecmd = true;
+
+//
+// info mirrors
+//
+cvar_t	password = {"password", "", false, true};
+cvar_t	spectator = {"spectator", "", false, true};
+cvar_t	name = {"name","unnamed", true, true};
+cvar_t	team = {"team","", true, true};
+cvar_t	skin = {"skin","", true, true};
+cvar_t	topcolor = {"topcolor","0", true, true};
+cvar_t	bottomcolor = {"bottomcolor","0", true, true};
+cvar_t	rate = {"rate","2500", true, true};
+cvar_t	noaim = {"noaim","0", true, true};
+cvar_t	msg = {"msg","1", true, true};
+
+extern cvar_t cl_hightrack;
+
+
+client_static_t	cls;
+client_state_t	cl;
+
+entity_state_t	cl_baselines[MAX_EDICTS];
+efrag_t			cl_efrags[MAX_EFRAGS];
+entity_t		cl_static_entities[MAX_STATIC_ENTITIES];
+lightstyle_t	cl_lightstyle[MAX_LIGHTSTYLES];
+dlight_t		cl_dlights[MAX_DLIGHTS];
+
+// refresh list
+// this is double buffered so the last frame
+// can be scanned for oldorigins of trailing objects
+int				cl_numvisedicts, cl_oldnumvisedicts;
+entity_t		*cl_visedicts, *cl_oldvisedicts;
+entity_t		cl_visedicts_list[2][MAX_VISEDICTS];
+
+double			connect_time = -1;		// for connection retransmits
+
+quakeparms_t host_parms;
+
+qboolean	host_initialized;		// true if into command execution
+qboolean	nomaster;
+
+double		host_frametime;
+double		realtime;				// without any filtering or bounding
+double		oldrealtime;			// last frame run
+int			host_framecount;
+
+int			host_hunklevel;
+
+byte		*host_basepal;
+byte		*host_colormap;
+
+netadr_t	master_adr;				// address of the master server
+
+cvar_t	host_speeds = {"host_speeds","0"};			// set for running times
+cvar_t	show_fps = {"show_fps","0"};			// set for running times
+cvar_t	developer = {"developer","0"};
+
+int			fps_count;
+
+jmp_buf 	host_abort;
+
+void Master_Connect_f (void);
+
+float	server_version = 0;	// version of server we connected to
+
+char emodel_name[] = 
+	{ 'e' ^ 0xff, 'm' ^ 0xff, 'o' ^ 0xff, 'd' ^ 0xff, 'e' ^ 0xff, 'l' ^ 0xff, 0 };
+char pmodel_name[] = 
+	{ 'p' ^ 0xff, 'm' ^ 0xff, 'o' ^ 0xff, 'd' ^ 0xff, 'e' ^ 0xff, 'l' ^ 0xff, 0 };
+char prespawn_name[] = 
+	{ 'p'^0xff, 'r'^0xff, 'e'^0xff, 's'^0xff, 'p'^0xff, 'a'^0xff, 'w'^0xff, 'n'^0xff,
+		' '^0xff, '%'^0xff, 'i'^0xff, ' '^0xff, '0'^0xff, ' '^0xff, '%'^0xff, 'i'^0xff, 0 };
+char modellist_name[] = 
+	{ 'm'^0xff, 'o'^0xff, 'd'^0xff, 'e'^0xff, 'l'^0xff, 'l'^0xff, 'i'^0xff, 's'^0xff, 't'^0xff, 
+		' '^0xff, '%'^0xff, 'i'^0xff, ' '^0xff, '%'^0xff, 'i'^0xff, 0 };
+char soundlist_name[] = 
+	{ 's'^0xff, 'o'^0xff, 'u'^0xff, 'n'^0xff, 'd'^0xff, 'l'^0xff, 'i'^0xff, 's'^0xff, 't'^0xff, 
+		' '^0xff, '%'^0xff, 'i'^0xff, ' '^0xff, '%'^0xff, 'i'^0xff, 0 };
+
+/*
+==================
+CL_Quit_f
+==================
+*/
+void CL_Quit_f (void)
+{
+	if (1 /* key_dest != key_console */ /* && cls.state != ca_dedicated */)
+	{
+		M_Menu_Quit_f ();
+		return;
+	}
+	CL_Disconnect ();
+	Sys_Quit ();
+}
+
+/*
+=======================
+CL_Version_f
+======================
+*/
+void CL_Version_f (void)
+{
+	Con_Printf ("Version %4.2f\n", VERSION);
+	Con_Printf ("Exe: "__TIME__" "__DATE__"\n");
+}
+
+
+/*
+=======================
+CL_SendConnectPacket
+
+called by CL_Connect_f and CL_CheckResend
+======================
+*/
+void CL_SendConnectPacket (void)
+{
+	netadr_t	adr;
+	char	data[2048];
+	double t1, t2;
+// JACK: Fixed bug where DNS lookups would cause two connects real fast
+//       Now, adds lookup time to the connect time.
+//		 Should I add it to realtime instead?!?!
+
+	if (cls.state != ca_disconnected)
+		return;
+
+	t1 = Sys_DoubleTime ();
+
+	if (!NET_StringToAdr (cls.servername, &adr))
+	{
+		Con_Printf ("Bad server address\n");
+		connect_time = -1;
+		return;
+	}
+
+	if (!NET_IsClientLegal(&adr))
+	{
+		Con_Printf ("Illegal server address\n");
+		connect_time = -1;
+		return;
+	}
+
+	if (adr.port == 0)
+		adr.port = BigShort (27500);
+	t2 = Sys_DoubleTime ();
+
+	connect_time = realtime+t2-t1;	// for retransmit requests
+
+	cls.qport = Cvar_VariableValue("qport");
+
+	Info_SetValueForStarKey (cls.userinfo, "*ip", NET_AdrToString(adr), MAX_INFO_STRING);
+
+//	Con_Printf ("Connecting to %s...\n", cls.servername);
+	sprintf (data, "%c%c%c%cconnect %i %i %i \"%s\"\n",
+		255, 255, 255, 255,	PROTOCOL_VERSION, cls.qport, cls.challenge, cls.userinfo);
+	NET_SendPacket (strlen(data), data, adr);
+}
+
+/*
+=================
+CL_CheckForResend
+
+Resend a connect message if the last one has timed out
+
+=================
+*/
+void CL_CheckForResend (void)
+{
+	netadr_t	adr;
+	char	data[2048];
+	double t1, t2;
+
+	if (connect_time == -1)
+		return;
+	if (cls.state != ca_disconnected)
+		return;
+	if (connect_time && realtime - connect_time < 5.0)
+		return;
+
+	t1 = Sys_DoubleTime ();
+	if (!NET_StringToAdr (cls.servername, &adr))
+	{
+		Con_Printf ("Bad server address\n");
+		connect_time = -1;
+		return;
+	}
+	if (!NET_IsClientLegal(&adr))
+	{
+		Con_Printf ("Illegal server address\n");
+		connect_time = -1;
+		return;
+	}
+
+	if (adr.port == 0)
+		adr.port = BigShort (27500);
+	t2 = Sys_DoubleTime ();
+
+	connect_time = realtime+t2-t1;	// for retransmit requests
+
+	Con_Printf ("Connecting to %s...\n", cls.servername);
+	sprintf (data, "%c%c%c%cgetchallenge\n", 255, 255, 255, 255);
+	NET_SendPacket (strlen(data), data, adr);
+}
+
+void CL_BeginServerConnect(void)
+{
+	connect_time = 0;
+	CL_CheckForResend();
+}
+
+/*
+================
+CL_Connect_f
+
+================
+*/
+void CL_Connect_f (void)
+{
+	char	*server;
+
+	if (Cmd_Argc() != 2)
+	{
+		Con_Printf ("usage: connect <server>\n");
+		return;	
+	}
+	
+	server = Cmd_Argv (1);
+
+	CL_Disconnect ();
+
+	strncpy (cls.servername, server, sizeof(cls.servername)-1);
+	CL_BeginServerConnect();
+}
+
+
+/*
+=====================
+CL_Rcon_f
+
+  Send the rest of the command line over as
+  an unconnected command.
+=====================
+*/
+void CL_Rcon_f (void)
+{
+	char	message[1024];
+	int		i;
+	netadr_t	to;
+
+	if (!rcon_password.string)
+	{
+		Con_Printf ("You must set 'rcon_password' before\n"
+					"issuing an rcon command.\n");
+		return;
+	}
+
+	message[0] = 255;
+	message[1] = 255;
+	message[2] = 255;
+	message[3] = 255;
+	message[4] = 0;
+
+	strcat (message, "rcon ");
+
+	strcat (message, rcon_password.string);
+	strcat (message, " ");
+
+	for (i=1 ; i<Cmd_Argc() ; i++)
+	{
+		strcat (message, Cmd_Argv(i));
+		strcat (message, " ");
+	}
+
+	if (cls.state >= ca_connected)
+		to = cls.netchan.remote_address;
+	else
+	{
+		if (!strlen(rcon_address.string))
+		{
+			Con_Printf ("You must either be connected,\n"
+						"or set the 'rcon_address' cvar\n"
+						"to issue rcon commands\n");
+
+			return;
+		}
+		NET_StringToAdr (rcon_address.string, &to);
+	}
+	
+	NET_SendPacket (strlen(message)+1, message
+		, to);
+}
+
+
+/*
+=====================
+CL_ClearState
+
+=====================
+*/
+void CL_ClearState (void)
+{
+	int			i;
+
+	S_StopAllSounds (true);
+
+	Con_DPrintf ("Clearing memory\n");
+	D_FlushCaches ();
+	Mod_ClearAll ();
+	if (host_hunklevel)	// FIXME: check this...
+		Hunk_FreeToLowMark (host_hunklevel);
+
+	CL_ClearTEnts ();
+
+// wipe the entire cl structure
+	memset (&cl, 0, sizeof(cl));
+
+	SZ_Clear (&cls.netchan.message);
+
+// clear other arrays	
+	memset (cl_efrags, 0, sizeof(cl_efrags));
+	memset (cl_dlights, 0, sizeof(cl_dlights));
+	memset (cl_lightstyle, 0, sizeof(cl_lightstyle));
+
+//
+// allocate the efrags and chain together into a free list
+//
+	cl.free_efrags = cl_efrags;
+	for (i=0 ; i<MAX_EFRAGS-1 ; i++)
+		cl.free_efrags[i].entnext = &cl.free_efrags[i+1];
+	cl.free_efrags[i].entnext = NULL;
+}
+
+/*
+=====================
+CL_Disconnect
+
+Sends a disconnect message to the server
+This is also called on Host_Error, so it shouldn't cause any errors
+=====================
+*/
+void CL_Disconnect (void)
+{
+	byte	final[10];
+
+	connect_time = -1;
+
+#ifdef _WIN32
+	SetWindowText (mainwindow, "QuakeWorld: disconnected");
+#endif
+
+// stop sounds (especially looping!)
+	S_StopAllSounds (true);
+	
+// if running a local server, shut it down
+	if (cls.demoplayback)
+		CL_StopPlayback ();
+	else if (cls.state != ca_disconnected)
+	{
+		if (cls.demorecording)
+			CL_Stop_f ();
+
+		final[0] = clc_stringcmd;
+		strcpy (final+1, "drop");
+		Netchan_Transmit (&cls.netchan, 6, final);
+		Netchan_Transmit (&cls.netchan, 6, final);
+		Netchan_Transmit (&cls.netchan, 6, final);
+
+		cls.state = ca_disconnected;
+
+		cls.demoplayback = cls.demorecording = cls.timedemo = false;
+	}
+	Cam_Reset();
+
+	if (cls.download) {
+		fclose(cls.download);
+		cls.download = NULL;
+	}
+
+	CL_StopUpload();
+
+}
+
+void CL_Disconnect_f (void)
+{
+	CL_Disconnect ();
+}
+
+/*
+====================
+CL_User_f
+
+user <name or userid>
+
+Dump userdata / masterdata for a user
+====================
+*/
+void CL_User_f (void)
+{
+	int		uid;
+	int		i;
+
+	if (Cmd_Argc() != 2)
+	{
+		Con_Printf ("Usage: user <username / userid>\n");
+		return;
+	}
+
+	uid = atoi(Cmd_Argv(1));
+
+	for (i=0 ; i<MAX_CLIENTS ; i++)
+	{
+		if (!cl.players[i].name[0])
+			continue;
+		if (cl.players[i].userid == uid
+		|| !strcmp(cl.players[i].name, Cmd_Argv(1)) )
+		{
+			Info_Print (cl.players[i].userinfo);
+			return;
+		}
+	}
+	Con_Printf ("User not in server.\n");
+}
+
+/*
+====================
+CL_Users_f
+
+Dump userids for all current players
+====================
+*/
+void CL_Users_f (void)
+{
+	int		i;
+	int		c;
+
+	c = 0;
+	Con_Printf ("userid frags name\n");
+	Con_Printf ("------ ----- ----\n");
+	for (i=0 ; i<MAX_CLIENTS ; i++)
+	{
+		if (cl.players[i].name[0])
+		{
+			Con_Printf ("%6i %4i %s\n", cl.players[i].userid, cl.players[i].frags, cl.players[i].name);
+			c++;
+		}
+	}
+
+	Con_Printf ("%i total users\n", c);
+}
+
+void CL_Color_f (void)
+{
+	// just for quake compatability...
+	int		top, bottom;
+	char	num[16];
+
+	if (Cmd_Argc() == 1)
+	{
+		Con_Printf ("\"color\" is \"%s %s\"\n",
+			Info_ValueForKey (cls.userinfo, "topcolor"),
+			Info_ValueForKey (cls.userinfo, "bottomcolor") );
+		Con_Printf ("color <0-13> [0-13]\n");
+		return;
+	}
+
+	if (Cmd_Argc() == 2)
+		top = bottom = atoi(Cmd_Argv(1));
+	else
+	{
+		top = atoi(Cmd_Argv(1));
+		bottom = atoi(Cmd_Argv(2));
+	}
+	
+	top &= 15;
+	if (top > 13)
+		top = 13;
+	bottom &= 15;
+	if (bottom > 13)
+		bottom = 13;
+	
+	sprintf (num, "%i", top);
+	Cvar_Set ("topcolor", num);
+	sprintf (num, "%i", bottom);
+	Cvar_Set ("bottomcolor", num);
+}
+
+/*
+==================
+CL_FullServerinfo_f
+
+Sent by server when serverinfo changes
+==================
+*/
+void CL_FullServerinfo_f (void)
+{
+	char *p;
+	float v;
+
+	if (Cmd_Argc() != 2)
+	{
+		Con_Printf ("usage: fullserverinfo <complete info string>\n");
+		return;
+	}
+
+	strcpy (cl.serverinfo, Cmd_Argv(1));
+
+	if ((p = Info_ValueForKey(cl.serverinfo, "*vesion")) && *p) {
+		v = Q_atof(p);
+		if (v) {
+			if (!server_version)
+				Con_Printf("Version %1.2f Server\n", v);
+			server_version = v;
+		}
+	}
+}
+
+/*
+==================
+CL_FullInfo_f
+
+Allow clients to change userinfo
+==================
+Casey was here :)
+*/
+void CL_FullInfo_f (void)
+{
+	char	key[512];
+	char	value[512];
+	char	*o;
+	char	*s;
+
+	if (Cmd_Argc() != 2)
+	{
+		Con_Printf ("fullinfo <complete info string>\n");
+		return;
+	}
+
+	s = Cmd_Argv(1);
+	if (*s == '\\')
+		s++;
+	while (*s)
+	{
+		o = key;
+		while (*s && *s != '\\')
+			*o++ = *s++;
+		*o = 0;
+
+		if (!*s)
+		{
+			Con_Printf ("MISSING VALUE\n");
+			return;
+		}
+
+		o = value;
+		s++;
+		while (*s && *s != '\\')
+			*o++ = *s++;
+		*o = 0;
+
+		if (*s)
+			s++;
+
+		if (!stricmp(key, pmodel_name) || !stricmp(key, emodel_name))
+			continue;
+
+		Info_SetValueForKey (cls.userinfo, key, value, MAX_INFO_STRING);
+	}
+}
+
+/*
+==================
+CL_SetInfo_f
+
+Allow clients to change userinfo
+==================
+*/
+void CL_SetInfo_f (void)
+{
+	if (Cmd_Argc() == 1)
+	{
+		Info_Print (cls.userinfo);
+		return;
+	}
+	if (Cmd_Argc() != 3)
+	{
+		Con_Printf ("usage: setinfo [ <key> <value> ]\n");
+		return;
+	}
+	if (!stricmp(Cmd_Argv(1), pmodel_name) || !strcmp(Cmd_Argv(1), emodel_name))
+		return;
+
+	Info_SetValueForKey (cls.userinfo, Cmd_Argv(1), Cmd_Argv(2), MAX_INFO_STRING);
+	if (cls.state >= ca_connected)
+		Cmd_ForwardToServer ();
+}
+
+/*
+====================
+CL_Packet_f
+
+packet <destination> <contents>
+
+Contents allows \n escape character
+====================
+*/
+void CL_Packet_f (void)
+{
+	char	send[2048];
+	int		i, l;
+	char	*in, *out;
+	netadr_t	adr;
+
+	if (Cmd_Argc() != 3)
+	{
+		Con_Printf ("packet <destination> <contents>\n");
+		return;
+	}
+
+	if (!NET_StringToAdr (Cmd_Argv(1), &adr))
+	{
+		Con_Printf ("Bad address\n");
+		return;
+	}
+
+	in = Cmd_Argv(2);
+	out = send+4;
+	send[0] = send[1] = send[2] = send[3] = 0xff;
+
+	l = strlen (in);
+	for (i=0 ; i<l ; i++)
+	{
+		if (in[i] == '\\' && in[i+1] == 'n')
+		{
+			*out++ = '\n';
+			i++;
+		}
+		else
+			*out++ = in[i];
+	}
+	*out = 0;
+
+	NET_SendPacket (out-send, send, adr);
+}
+
+
+/*
+=====================
+CL_NextDemo
+
+Called to play the next demo in the demo loop
+=====================
+*/
+void CL_NextDemo (void)
+{
+	char	str[1024];
+
+	if (cls.demonum == -1)
+		return;		// don't play demos
+
+	if (!cls.demos[cls.demonum][0] || cls.demonum == MAX_DEMOS)
+	{
+		cls.demonum = 0;
+		if (!cls.demos[cls.demonum][0])
+		{
+//			Con_Printf ("No demos listed with startdemos\n");
+			cls.demonum = -1;
+			return;
+		}
+	}
+
+	sprintf (str,"playdemo %s\n", cls.demos[cls.demonum]);
+	Cbuf_InsertText (str);
+	cls.demonum++;
+}
+
+
+/*
+=================
+CL_Changing_f
+
+Just sent as a hint to the client that they should
+drop to full console
+=================
+*/
+void CL_Changing_f (void)
+{
+	if (cls.download)  // don't change when downloading
+		return;
+
+	S_StopAllSounds (true);
+	cl.intermission = 0;
+	cls.state = ca_connected;	// not active anymore, but not disconnected
+	Con_Printf ("\nChanging map...\n");
+}
+
+
+/*
+=================
+CL_Reconnect_f
+
+The server is changing levels
+=================
+*/
+void CL_Reconnect_f (void)
+{
+	if (cls.download)  // don't change when downloading
+		return;
+
+	S_StopAllSounds (true);
+
+	if (cls.state == ca_connected) {
+		Con_Printf ("reconnecting...\n");
+		MSG_WriteChar (&cls.netchan.message, clc_stringcmd);
+		MSG_WriteString (&cls.netchan.message, "new");
+		return;
+	}
+
+	if (!*cls.servername) {
+		Con_Printf("No server to reconnect to...\n");
+		return;
+	}
+
+	CL_Disconnect();
+	CL_BeginServerConnect();
+}
+
+/*
+=================
+CL_ConnectionlessPacket
+
+Responses to broadcasts, etc
+=================
+*/
+void CL_ConnectionlessPacket (void)
+{
+	char	*s;
+	int		c;
+
+    MSG_BeginReading ();
+    MSG_ReadLong ();        // skip the -1
+
+	c = MSG_ReadByte ();
+	if (!cls.demoplayback)
+		Con_Printf ("%s: ", NET_AdrToString (net_from));
+//	Con_DPrintf ("%s", net_message.data + 5);
+	if (c == S2C_CONNECTION)
+	{
+		Con_Printf ("connection\n");
+		if (cls.state >= ca_connected)
+		{
+			if (!cls.demoplayback)
+				Con_Printf ("Dup connect received.  Ignored.\n");
+			return;
+		}
+		Netchan_Setup (&cls.netchan, net_from, cls.qport);
+		MSG_WriteChar (&cls.netchan.message, clc_stringcmd);
+		MSG_WriteString (&cls.netchan.message, "new");	
+		cls.state = ca_connected;
+		Con_Printf ("Connected.\n");
+		allowremotecmd = false; // localid required now for remote cmds
+		return;
+	}
+	// remote command from gui front end
+	if (c == A2C_CLIENT_COMMAND)
+	{
+		char	cmdtext[2048];
+
+		Con_Printf ("client command\n");
+
+		if ((*(unsigned *)net_from.ip != *(unsigned *)net_local_adr.ip
+			&& *(unsigned *)net_from.ip != htonl(INADDR_LOOPBACK)) )
+		{
+			Con_Printf ("Command packet from remote host.  Ignored.\n");
+			return;
+		}
+#ifdef _WIN32
+		ShowWindow (mainwindow, SW_RESTORE);
+		SetForegroundWindow (mainwindow);
+#endif
+		s = MSG_ReadString ();
+
+		strncpy(cmdtext, s, sizeof(cmdtext) - 1);
+		cmdtext[sizeof(cmdtext) - 1] = 0;
+
+		s = MSG_ReadString ();
+
+		while (*s && isspace(*s))
+			s++;
+		while (*s && isspace(s[strlen(s) - 1]))
+			s[strlen(s) - 1] = 0;
+
+		if (!allowremotecmd && (!*localid.string || strcmp(localid.string, s))) {
+			if (!*localid.string) {
+				Con_Printf("===========================\n");
+				Con_Printf("Command packet received from local host, but no "
+					"localid has been set.  You may need to upgrade your server "
+					"browser.\n");
+				Con_Printf("===========================\n");
+				return;
+			}
+			Con_Printf("===========================\n");
+			Con_Printf("Invalid localid on command packet received from local host. "
+				"\n|%s| != |%s|\n"
+				"You may need to reload your server browser and QuakeWorld.\n",
+				s, localid.string);
+			Con_Printf("===========================\n");
+			Cvar_Set("localid", "");
+			return;
+		}
+
+		Cbuf_AddText (cmdtext);
+		allowremotecmd = false;
+		return;
+	}
+	// print command from somewhere
+	if (c == A2C_PRINT)
+	{
+		Con_Printf ("print\n");
+
+		s = MSG_ReadString ();
+		Con_Print (s);
+		return;
+	}
+
+	// ping from somewhere
+	if (c == A2A_PING)
+	{
+		char	data[6];
+
+		Con_Printf ("ping\n");
+
+		data[0] = 0xff;
+		data[1] = 0xff;
+		data[2] = 0xff;
+		data[3] = 0xff;
+		data[4] = A2A_ACK;
+		data[5] = 0;
+		
+		NET_SendPacket (6, &data, net_from);
+		return;
+	}
+
+	if (c == S2C_CHALLENGE) {
+		Con_Printf ("challenge\n");
+
+		s = MSG_ReadString ();
+		cls.challenge = atoi(s);
+		CL_SendConnectPacket ();
+		return;
+	}
+
+#if 0
+	if (c == svc_disconnect) {
+		Con_Printf ("disconnect\n");
+
+		Host_EndGame ("Server disconnected");
+		return;
+	}
+#endif
+
+	Con_Printf ("unknown:  %c\n", c);
+}
+
+
+/*
+=================
+CL_ReadPackets
+=================
+*/
+void CL_ReadPackets (void)
+{
+//	while (NET_GetPacket ())
+	while (CL_GetMessage())
+	{
+		//
+		// remote command packet
+		//
+		if (*(int *)net_message.data == -1)
+		{
+			CL_ConnectionlessPacket ();
+			continue;
+		}
+
+		if (net_message.cursize < 8)
+		{
+			Con_Printf ("%s: Runt packet\n",NET_AdrToString(net_from));
+			continue;
+		}
+
+		//
+		// packet from server
+		//
+		if (!cls.demoplayback && 
+			!NET_CompareAdr (net_from, cls.netchan.remote_address))
+		{
+			Con_DPrintf ("%s:sequenced packet without connection\n"
+				,NET_AdrToString(net_from));
+			continue;
+		}
+		if (!Netchan_Process(&cls.netchan))
+			continue;		// wasn't accepted for some reason
+		CL_ParseServerMessage ();
+
+//		if (cls.demoplayback && cls.state >= ca_active && !CL_DemoBehind())
+//			return;
+	}
+
+	//
+	// check timeout
+	//
+	if (cls.state >= ca_connected
+	 && realtime - cls.netchan.last_received > cl_timeout.value)
+	{
+		Con_Printf ("\nServer connection timed out.\n");
+		CL_Disconnect ();
+		return;
+	}
+	
+}
+
+//=============================================================================
+
+/*
+=====================
+CL_Download_f
+=====================
+*/
+void CL_Download_f (void)
+{
+	char *p, *q;
+
+	if (cls.state == ca_disconnected)
+	{
+		Con_Printf ("Must be connected.\n");
+		return;
+	}
+
+	if (Cmd_Argc() != 2)
+	{
+		Con_Printf ("Usage: download <datafile>\n");
+		return;
+	}
+
+	sprintf (cls.downloadname, "%s/%s", com_gamedir, Cmd_Argv(1));
+
+	p = cls.downloadname;
+	for (;;) {
+		if ((q = strchr(p, '/')) != NULL) {
+			*q = 0;
+			Sys_mkdir(cls.downloadname);
+			*q = '/';
+			p = q + 1;
+		} else
+			break;
+	}
+
+	strcpy(cls.downloadtempname, cls.downloadname);
+	cls.download = fopen (cls.downloadname, "wb");
+	cls.downloadtype = dl_single;
+
+	MSG_WriteByte (&cls.netchan.message, clc_stringcmd);
+	SZ_Print (&cls.netchan.message, va("download %s\n",Cmd_Argv(1)));
+}
+
+#ifdef _WINDOWS
+#include <windows.h>
+/*
+=================
+CL_Minimize_f
+=================
+*/
+void CL_Windows_f (void) {
+//	if (modestate == MS_WINDOWED)
+//		ShowWindow(mainwindow, SW_MINIMIZE);
+//	else
+		SendMessage(mainwindow, WM_SYSKEYUP, VK_TAB, 1 | (0x0F << 16) | (1<<29));
+}
+#endif
+
+/*
+=================
+CL_Init
+=================
+*/
+void CL_Init (void)
+{
+	extern	cvar_t		baseskin;
+	extern	cvar_t		noskins;
+	char st[80];
+
+	cls.state = ca_disconnected;
+
+	Info_SetValueForKey (cls.userinfo, "name", "unnamed", MAX_INFO_STRING);
+	Info_SetValueForKey (cls.userinfo, "topcolor", "0", MAX_INFO_STRING);
+	Info_SetValueForKey (cls.userinfo, "bottomcolor", "0", MAX_INFO_STRING);
+	Info_SetValueForKey (cls.userinfo, "rate", "2500", MAX_INFO_STRING);
+	Info_SetValueForKey (cls.userinfo, "msg", "1", MAX_INFO_STRING);
+	sprintf (st, "%4.2f-%04d", VERSION, build_number());
+	Info_SetValueForStarKey (cls.userinfo, "*ver", st, MAX_INFO_STRING);
+
+	CL_InitInput ();
+	CL_InitTEnts ();
+	CL_InitPrediction ();
+	CL_InitCam ();
+	Pmove_Init ();
+	
+//
+// register our commands
+//
+	Cvar_RegisterVariable (&show_fps);
+	Cvar_RegisterVariable (&host_speeds);
+	Cvar_RegisterVariable (&developer);
+
+	Cvar_RegisterVariable (&cl_warncmd);
+	Cvar_RegisterVariable (&cl_upspeed);
+	Cvar_RegisterVariable (&cl_forwardspeed);
+	Cvar_RegisterVariable (&cl_backspeed);
+	Cvar_RegisterVariable (&cl_sidespeed);
+	Cvar_RegisterVariable (&cl_movespeedkey);
+	Cvar_RegisterVariable (&cl_yawspeed);
+	Cvar_RegisterVariable (&cl_pitchspeed);
+	Cvar_RegisterVariable (&cl_anglespeedkey);
+	Cvar_RegisterVariable (&cl_shownet);
+	Cvar_RegisterVariable (&cl_sbar);
+	Cvar_RegisterVariable (&cl_hudswap);
+	Cvar_RegisterVariable (&cl_maxfps);
+	Cvar_RegisterVariable (&cl_timeout);
+	Cvar_RegisterVariable (&lookspring);
+	Cvar_RegisterVariable (&lookstrafe);
+	Cvar_RegisterVariable (&sensitivity);
+
+	Cvar_RegisterVariable (&m_pitch);
+	Cvar_RegisterVariable (&m_yaw);
+	Cvar_RegisterVariable (&m_forward);
+	Cvar_RegisterVariable (&m_side);
+
+	Cvar_RegisterVariable (&rcon_password);
+	Cvar_RegisterVariable (&rcon_address);
+
+	Cvar_RegisterVariable (&entlatency);
+	Cvar_RegisterVariable (&cl_predict_players2);
+	Cvar_RegisterVariable (&cl_predict_players);
+	Cvar_RegisterVariable (&cl_solid_players);
+
+	Cvar_RegisterVariable (&localid);
+
+	Cvar_RegisterVariable (&baseskin);
+	Cvar_RegisterVariable (&noskins);
+
+	//
+	// info mirrors
+	//
+	Cvar_RegisterVariable (&name);
+	Cvar_RegisterVariable (&password);
+	Cvar_RegisterVariable (&spectator);
+	Cvar_RegisterVariable (&skin);
+	Cvar_RegisterVariable (&team);
+	Cvar_RegisterVariable (&topcolor);
+	Cvar_RegisterVariable (&bottomcolor);
+	Cvar_RegisterVariable (&rate);
+	Cvar_RegisterVariable (&msg);
+	Cvar_RegisterVariable (&noaim);
+
+
+	Cmd_AddCommand ("version", CL_Version_f);
+
+	Cmd_AddCommand ("changing", CL_Changing_f);
+	Cmd_AddCommand ("disconnect", CL_Disconnect_f);
+	Cmd_AddCommand ("record", CL_Record_f);
+	Cmd_AddCommand ("rerecord", CL_ReRecord_f);
+	Cmd_AddCommand ("stop", CL_Stop_f);
+	Cmd_AddCommand ("playdemo", CL_PlayDemo_f);
+	Cmd_AddCommand ("timedemo", CL_TimeDemo_f);
+
+	Cmd_AddCommand ("skins", Skin_Skins_f);
+	Cmd_AddCommand ("allskins", Skin_AllSkins_f);
+
+	Cmd_AddCommand ("quit", CL_Quit_f);
+
+	Cmd_AddCommand ("connect", CL_Connect_f);
+	Cmd_AddCommand ("reconnect", CL_Reconnect_f);
+
+	Cmd_AddCommand ("rcon", CL_Rcon_f);
+	Cmd_AddCommand ("packet", CL_Packet_f);
+	Cmd_AddCommand ("user", CL_User_f);
+	Cmd_AddCommand ("users", CL_Users_f);
+
+	Cmd_AddCommand ("setinfo", CL_SetInfo_f);
+	Cmd_AddCommand ("fullinfo", CL_FullInfo_f);
+	Cmd_AddCommand ("fullserverinfo", CL_FullServerinfo_f);
+
+	Cmd_AddCommand ("color", CL_Color_f);
+	Cmd_AddCommand ("download", CL_Download_f);
+
+	Cmd_AddCommand ("nextul", CL_NextUpload);
+	Cmd_AddCommand ("stopul", CL_StopUpload);
+
+//
+// forward to server commands
+//
+	Cmd_AddCommand ("kill", NULL);
+	Cmd_AddCommand ("pause", NULL);
+	Cmd_AddCommand ("say", NULL);
+	Cmd_AddCommand ("say_team", NULL);
+	Cmd_AddCommand ("serverinfo", NULL);
+
+//
+//  Windows commands
+//
+#ifdef _WINDOWS
+	Cmd_AddCommand ("windows", CL_Windows_f);
+#endif
+}
+
+
+/*
+================
+Host_EndGame
+
+Call this to drop to a console without exiting the qwcl
+================
+*/
+void Host_EndGame (char *message, ...)
+{
+	va_list		argptr;
+	char		string[1024];
+	
+	va_start (argptr,message);
+	vsprintf (string,message,argptr);
+	va_end (argptr);
+	Con_Printf ("\n===========================\n");
+	Con_Printf ("Host_EndGame: %s\n",string);
+	Con_Printf ("===========================\n\n");
+	
+	CL_Disconnect ();
+
+	longjmp (host_abort, 1);
+}
+
+/*
+================
+Host_Error
+
+This shuts down the client and exits qwcl
+================
+*/
+void Host_Error (char *error, ...)
+{
+	va_list		argptr;
+	char		string[1024];
+	static	qboolean inerror = false;
+	
+	if (inerror)
+		Sys_Error ("Host_Error: recursively entered");
+	inerror = true;
+	
+	va_start (argptr,error);
+	vsprintf (string,error,argptr);
+	va_end (argptr);
+	Con_Printf ("Host_Error: %s\n",string);
+	
+	CL_Disconnect ();
+	cls.demonum = -1;
+
+	inerror = false;
+
+// FIXME
+	Sys_Error ("Host_Error: %s\n",string);
+}
+
+
+/*
+===============
+Host_WriteConfiguration
+
+Writes key bindings and archived cvars to config.cfg
+===============
+*/
+void Host_WriteConfiguration (void)
+{
+	FILE	*f;
+
+	if (host_initialized)
+	{
+		f = fopen (va("%s/config.cfg",com_gamedir), "w");
+		if (!f)
+		{
+			Con_Printf ("Couldn't write config.cfg.\n");
+			return;
+		}
+		
+		Key_WriteBindings (f);
+		Cvar_WriteVariables (f);
+
+		fclose (f);
+	}
+}
+
+
+//============================================================================
+
+#if 0
+/*
+==================
+Host_SimulationTime
+
+This determines if enough time has passed to run a simulation frame
+==================
+*/
+qboolean Host_SimulationTime(float time)
+{
+	float fps;
+
+	if (oldrealtime > realtime)
+		oldrealtime = 0;
+
+	if (cl_maxfps.value)
+		fps = max(30.0, min(cl_maxfps.value, 72.0));
+	else
+		fps = max(30.0, min(rate.value/80.0, 72.0));
+
+	if (!cls.timedemo && (realtime + time) - oldrealtime < 1.0/fps)
+		return false;			// framerate is too high
+	return true;
+}
+#endif
+
+
+/*
+==================
+Host_Frame
+
+Runs all active servers
+==================
+*/
+int		nopacketcount;
+void Host_Frame (float time)
+{
+	static double		time1 = 0;
+	static double		time2 = 0;
+	static double		time3 = 0;
+	int			pass1, pass2, pass3;
+	float fps;
+	if (setjmp (host_abort) )
+		return;			// something bad happened, or the server disconnected
+
+	// decide the simulation time
+	realtime += time;
+	if (oldrealtime > realtime)
+		oldrealtime = 0;
+
+	if (cl_maxfps.value)
+		fps = max(30.0, min(cl_maxfps.value, 72.0));
+	else
+		fps = max(30.0, min(rate.value/80.0, 72.0));
+
+	if (!cls.timedemo && realtime - oldrealtime < 1.0/fps)
+		return;			// framerate is too high
+
+	host_frametime = realtime - oldrealtime;
+	oldrealtime = realtime;
+	if (host_frametime > 0.2)
+		host_frametime = 0.2;
+		
+	// get new key events
+	Sys_SendKeyEvents ();
+
+	// allow mice or other external controllers to add commands
+	IN_Commands ();
+
+	// process console commands
+	Cbuf_Execute ();
+
+	// fetch results from server
+	CL_ReadPackets ();
+
+	// send intentions now
+	// resend a connection request if necessary
+	if (cls.state == ca_disconnected) {
+		CL_CheckForResend ();
+	} else
+		CL_SendCmd ();
+
+	// Set up prediction for other players
+	CL_SetUpPlayerPrediction(false);
+
+	// do client side motion prediction
+	CL_PredictMove ();
+
+	// Set up prediction for other players
+	CL_SetUpPlayerPrediction(true);
+
+	// build a refresh entity list
+	CL_EmitEntities ();
+
+	// update video
+	if (host_speeds.value)
+		time1 = Sys_DoubleTime ();
+
+	SCR_UpdateScreen ();
+
+	if (host_speeds.value)
+		time2 = Sys_DoubleTime ();
+		
+	// update audio
+	if (cls.state == ca_active)
+	{
+		S_Update (r_origin, vpn, vright, vup);
+		CL_DecayLights ();
+	}
+	else
+		S_Update (vec3_origin, vec3_origin, vec3_origin, vec3_origin);
+	
+	CDAudio_Update();
+
+	if (host_speeds.value)
+	{
+		pass1 = (time1 - time3)*1000;
+		time3 = Sys_DoubleTime ();
+		pass2 = (time2 - time1)*1000;
+		pass3 = (time3 - time2)*1000;
+		Con_Printf ("%3i tot %3i server %3i gfx %3i snd\n",
+					pass1+pass2+pass3, pass1, pass2, pass3);
+	}
+
+	host_framecount++;
+	fps_count++;
+}
+
+static void simple_crypt(char *buf, int len)
+{
+	while (len--)
+		*buf++ ^= 0xff;
+}
+
+void Host_FixupModelNames(void)
+{
+	simple_crypt(emodel_name, sizeof(emodel_name) - 1);
+	simple_crypt(pmodel_name, sizeof(pmodel_name) - 1);
+	simple_crypt(prespawn_name,  sizeof(prespawn_name)  - 1);
+	simple_crypt(modellist_name, sizeof(modellist_name) - 1);
+	simple_crypt(soundlist_name, sizeof(soundlist_name) - 1);
+}
+
+//============================================================================
+
+/*
+====================
+Host_Init
+====================
+*/
+void Host_Init (quakeparms_t *parms)
+{
+	COM_InitArgv (parms->argc, parms->argv);
+	COM_AddParm ("-game");
+	COM_AddParm ("qw");
+
+	Sys_mkdir("qw");
+
+	if (COM_CheckParm ("-minmemory"))
+		parms->memsize = MINIMUM_MEMORY;
+
+	host_parms = *parms;
+
+	if (parms->memsize < MINIMUM_MEMORY)
+		Sys_Error ("Only %4.1f megs of memory reported, can't execute game", parms->memsize / (float)0x100000);
+
+	Memory_Init (parms->membase, parms->memsize);
+	Cbuf_Init ();
+	Cmd_Init ();
+	V_Init ();
+
+	COM_Init ();
+
+	Host_FixupModelNames();
+	
+	NET_Init (PORT_CLIENT);
+	Netchan_Init ();
+
+	W_LoadWadFile ("gfx.wad");
+	Key_Init ();
+	Con_Init ();	
+	M_Init ();	
+	Mod_Init ();
+	
+//	Con_Printf ("Exe: "__TIME__" "__DATE__"\n");
+	Con_Printf ("%4.1f megs RAM used.\n",parms->memsize/ (1024*1024.0));
+	
+	R_InitTextures ();
+ 
+	host_basepal = (byte *)COM_LoadHunkFile ("gfx/palette.lmp");
+	if (!host_basepal)
+		Sys_Error ("Couldn't load gfx/palette.lmp");
+	host_colormap = (byte *)COM_LoadHunkFile ("gfx/colormap.lmp");
+	if (!host_colormap)
+		Sys_Error ("Couldn't load gfx/colormap.lmp");
+#ifdef __linux__
+	IN_Init ();
+	CDAudio_Init ();
+	VID_Init (host_basepal);
+	Draw_Init ();
+	SCR_Init ();
+	R_Init ();
+
+//	S_Init ();		// S_Init is now done as part of VID. Sigh.
+	
+	cls.state = ca_disconnected;
+	Sbar_Init ();
+	CL_Init ();
+#else
+	VID_Init (host_basepal);
+	Draw_Init ();
+	SCR_Init ();
+	R_Init ();
+//	S_Init ();		// S_Init is now done as part of VID. Sigh.
+#ifdef GLQUAKE
+	S_Init();
+#endif
+
+	cls.state = ca_disconnected;
+	CDAudio_Init ();
+	Sbar_Init ();
+	CL_Init ();
+	IN_Init ();
+#endif
+
+	Cbuf_InsertText ("exec quake.rc\n");
+	Cbuf_AddText ("echo Type connect <internet address> or use GameSpy to connect to a game.\n");
+	Cbuf_AddText ("cl_warncmd 1\n");
+
+	Hunk_AllocName (0, "-HOST_HUNKLEVEL-");
+	host_hunklevel = Hunk_LowMark ();
+
+	host_initialized = true;
+
+	Con_Printf ("\nClient Version %4.2f (Build %04d)\n\n", VERSION, build_number());
+
+	Con_Printf ("������� QuakeWorld Initialized �������\n");	
+}
+
+
+/*
+===============
+Host_Shutdown
+
+FIXME: this is a callback from Sys_Quit and Sys_Error.  It would be better
+to run quit through here before the final handoff to the sys code.
+===============
+*/
+void Host_Shutdown(void)
+{
+	static qboolean isdown = false;
+	
+	if (isdown)
+	{
+		printf ("recursive shutdown\n");
+		return;
+	}
+	isdown = true;
+
+	Host_WriteConfiguration (); 
+		
+	CDAudio_Shutdown ();
+	NET_Shutdown ();
+	S_Shutdown();
+	IN_Shutdown ();
+	if (host_basepal)
+		VID_Shutdown();
+}
+
--- /dev/null
+++ b/QW/client/cl_parse.c
@@ -1,0 +1,1383 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// cl_parse.c  -- parse a message received from the server
+
+#include "quakedef.h"
+
+char *svc_strings[] =
+{
+	"svc_bad",
+	"svc_nop",
+	"svc_disconnect",
+	"svc_updatestat",
+	"svc_version",		// [long] server version
+	"svc_setview",		// [short] entity number
+	"svc_sound",			// <see code>
+	"svc_time",			// [float] server time
+	"svc_print",			// [string] null terminated string
+	"svc_stufftext",		// [string] stuffed into client's console buffer
+						// the string should be \n terminated
+	"svc_setangle",		// [vec3] set the view angle to this absolute value
+	
+	"svc_serverdata",		// [long] version ...
+	"svc_lightstyle",		// [byte] [string]
+	"svc_updatename",		// [byte] [string]
+	"svc_updatefrags",	// [byte] [short]
+	"svc_clientdata",		// <shortbits + data>
+	"svc_stopsound",		// <see code>
+	"svc_updatecolors",	// [byte] [byte]
+	"svc_particle",		// [vec3] <variable>
+	"svc_damage",			// [byte] impact [byte] blood [vec3] from
+	
+	"svc_spawnstatic",
+	"OBSOLETE svc_spawnbinary",
+	"svc_spawnbaseline",
+	
+	"svc_temp_entity",		// <variable>
+	"svc_setpause",
+	"svc_signonnum",
+	"svc_centerprint",
+	"svc_killedmonster",
+	"svc_foundsecret",
+	"svc_spawnstaticsound",
+	"svc_intermission",
+	"svc_finale",
+
+	"svc_cdtrack",
+	"svc_sellscreen",
+
+	"svc_smallkick",
+	"svc_bigkick",
+
+	"svc_updateping",
+	"svc_updateentertime",
+
+	"svc_updatestatlong",
+	"svc_muzzleflash",
+	"svc_updateuserinfo",
+	"svc_download",
+	"svc_playerinfo",
+	"svc_nails",
+	"svc_choke",
+	"svc_modellist",
+	"svc_soundlist",
+	"svc_packetentities",
+ 	"svc_deltapacketentities",
+	"svc_maxspeed",
+	"svc_entgravity",
+
+	"svc_setinfo",
+	"svc_serverinfo",
+	"svc_updatepl",
+	"NEW PROTOCOL",
+	"NEW PROTOCOL",
+	"NEW PROTOCOL",
+	"NEW PROTOCOL",
+	"NEW PROTOCOL",
+	"NEW PROTOCOL",
+	"NEW PROTOCOL",
+	"NEW PROTOCOL",
+	"NEW PROTOCOL",
+	"NEW PROTOCOL",
+	"NEW PROTOCOL",
+	"NEW PROTOCOL",
+	"NEW PROTOCOL"
+};
+
+int	oldparsecountmod;
+int	parsecountmod;
+double	parsecounttime;
+
+int		cl_spikeindex, cl_playerindex, cl_flagindex;
+
+//=============================================================================
+
+int packet_latency[NET_TIMINGS];
+
+int CL_CalcNet (void)
+{
+	int		a, i;
+	frame_t	*frame;
+	int lost;
+	char st[80];
+
+	for (i=cls.netchan.outgoing_sequence-UPDATE_BACKUP+1
+		; i <= cls.netchan.outgoing_sequence
+		; i++)
+	{
+		frame = &cl.frames[i&UPDATE_MASK];
+		if (frame->receivedtime == -1)
+			packet_latency[i&NET_TIMINGSMASK] = 9999;	// dropped
+		else if (frame->receivedtime == -2)
+			packet_latency[i&NET_TIMINGSMASK] = 10000;	// choked
+		else if (frame->invalid)
+			packet_latency[i&NET_TIMINGSMASK] = 9998;	// invalid delta
+		else
+			packet_latency[i&NET_TIMINGSMASK] = (frame->receivedtime - frame->senttime)*20;
+	}
+
+	lost = 0;
+	for (a=0 ; a<NET_TIMINGS ; a++)
+	{
+		i = (cls.netchan.outgoing_sequence-a) & NET_TIMINGSMASK;
+		if (packet_latency[i] == 9999)
+			lost++;
+	}
+	return lost * 100 / NET_TIMINGS;
+}
+
+//=============================================================================
+
+/*
+===============
+CL_CheckOrDownloadFile
+
+Returns true if the file exists, otherwise it attempts
+to start a download from the server.
+===============
+*/
+qboolean	CL_CheckOrDownloadFile (char *filename)
+{
+	FILE	*f;
+
+	if (strstr (filename, ".."))
+	{
+		Con_Printf ("Refusing to download a path with ..\n");
+		return true;
+	}
+
+	COM_FOpenFile (filename, &f);
+	if (f)
+	{	// it exists, no need to download
+		fclose (f);
+		return true;
+	}
+
+	//ZOID - can't download when recording
+	if (cls.demorecording) {
+		Con_Printf("Unable to download %s in record mode.\n", cls.downloadname);
+		return true;
+	}
+	//ZOID - can't download when playback
+	if (cls.demoplayback)
+		return true;
+
+	strcpy (cls.downloadname, filename);
+	Con_Printf ("Downloading %s...\n", cls.downloadname);
+
+	// download to a temp name, and only rename
+	// to the real name when done, so if interrupted
+	// a runt file wont be left
+	COM_StripExtension (cls.downloadname, cls.downloadtempname);
+	strcat (cls.downloadtempname, ".tmp");
+
+	MSG_WriteByte (&cls.netchan.message, clc_stringcmd);
+	MSG_WriteString (&cls.netchan.message, va("download %s", cls.downloadname));
+
+	cls.downloadnumber++;
+
+	return false;
+}
+
+/*
+=================
+Model_NextDownload
+=================
+*/
+void Model_NextDownload (void)
+{
+	char	*s;
+	int		i;
+	extern	char gamedirfile[];
+
+	if (cls.downloadnumber == 0)
+	{
+		Con_Printf ("Checking models...\n");
+		cls.downloadnumber = 1;
+	}
+
+	cls.downloadtype = dl_model;
+	for ( 
+		; cl.model_name[cls.downloadnumber][0]
+		; cls.downloadnumber++)
+	{
+		s = cl.model_name[cls.downloadnumber];
+		if (s[0] == '*')
+			continue;	// inline brush model
+		if (!CL_CheckOrDownloadFile(s))
+			return;		// started a download
+	}
+
+	for (i=1 ; i<MAX_MODELS ; i++)
+	{
+		if (!cl.model_name[i][0])
+			break;
+
+		cl.model_precache[i] = Mod_ForName (cl.model_name[i], false);
+
+		if (!cl.model_precache[i])
+		{
+			Con_Printf ("\nThe required model file '%s' could not be found or downloaded.\n\n"
+				, cl.model_name[i]);
+			Con_Printf ("You may need to download or purchase a %s client "
+				"pack in order to play on this server.\n\n", gamedirfile);
+			CL_Disconnect ();
+			return;
+		}
+	}
+
+	// all done
+	cl.worldmodel = cl.model_precache[1];	
+	R_NewMap ();
+	Hunk_Check ();		// make sure nothing is hurt
+
+	// done with modellist, request first of static signon messages
+	MSG_WriteByte (&cls.netchan.message, clc_stringcmd);
+//	MSG_WriteString (&cls.netchan.message, va("prespawn %i 0 %i", cl.servercount, cl.worldmodel->checksum2));
+	MSG_WriteString (&cls.netchan.message, va(prespawn_name, cl.servercount, cl.worldmodel->checksum2));
+}
+
+/*
+=================
+Sound_NextDownload
+=================
+*/
+void Sound_NextDownload (void)
+{
+	char	*s;
+	int		i;
+
+	if (cls.downloadnumber == 0)
+	{
+		Con_Printf ("Checking sounds...\n");
+		cls.downloadnumber = 1;
+	}
+
+	cls.downloadtype = dl_sound;
+	for ( 
+		; cl.sound_name[cls.downloadnumber][0]
+		; cls.downloadnumber++)
+	{
+		s = cl.sound_name[cls.downloadnumber];
+		if (!CL_CheckOrDownloadFile(va("sound/%s",s)))
+			return;		// started a download
+	}
+
+	for (i=1 ; i<MAX_SOUNDS ; i++)
+	{
+		if (!cl.sound_name[i][0])
+			break;
+		cl.sound_precache[i] = S_PrecacheSound (cl.sound_name[i]);
+	}
+
+	// done with sounds, request models now
+	memset (cl.model_precache, 0, sizeof(cl.model_precache));
+	cl_playerindex = -1;
+	cl_spikeindex = -1;
+	cl_flagindex = -1;
+	MSG_WriteByte (&cls.netchan.message, clc_stringcmd);
+//	MSG_WriteString (&cls.netchan.message, va("modellist %i 0", cl.servercount));
+	MSG_WriteString (&cls.netchan.message, va(modellist_name, cl.servercount, 0));
+}
+
+
+/*
+======================
+CL_RequestNextDownload
+======================
+*/
+void CL_RequestNextDownload (void)
+{
+	switch (cls.downloadtype)
+	{
+	case dl_single:
+		break;
+	case dl_skin:
+		Skin_NextDownload ();
+		break;
+	case dl_model:
+		Model_NextDownload ();
+		break;
+	case dl_sound:
+		Sound_NextDownload ();
+		break;
+	case dl_none:
+	default:
+		Con_DPrintf("Unknown download type.\n");
+	}
+}
+
+/*
+=====================
+CL_ParseDownload
+
+A download message has been received from the server
+=====================
+*/
+void CL_ParseDownload (void)
+{
+	int		size, percent;
+	byte	name[1024];
+	int		r;
+
+
+	// read the data
+	size = MSG_ReadShort ();
+	percent = MSG_ReadByte ();
+
+	if (cls.demoplayback) {
+		if (size > 0)
+			msg_readcount += size;
+		return; // not in demo playback
+	}
+
+	if (size == -1)
+	{
+		Con_Printf ("File not found.\n");
+		if (cls.download)
+		{
+			Con_Printf ("cls.download shouldn't have been set\n");
+			fclose (cls.download);
+			cls.download = NULL;
+		}
+		CL_RequestNextDownload ();
+		return;
+	}
+
+	// open the file if not opened yet
+	if (!cls.download)
+	{
+		if (strncmp(cls.downloadtempname,"skins/",6))
+			sprintf (name, "%s/%s", com_gamedir, cls.downloadtempname);
+		else
+			sprintf (name, "qw/%s", cls.downloadtempname);
+
+		COM_CreatePath (name);
+
+		cls.download = fopen (name, "wb");
+		if (!cls.download)
+		{
+			msg_readcount += size;
+			Con_Printf ("Failed to open %s\n", cls.downloadtempname);
+			CL_RequestNextDownload ();
+			return;
+		}
+	}
+
+	fwrite (net_message.data + msg_readcount, 1, size, cls.download);
+	msg_readcount += size;
+
+	if (percent != 100)
+	{
+// change display routines by zoid
+		// request next block
+#if 0
+		Con_Printf (".");
+		if (10*(percent/10) != cls.downloadpercent)
+		{
+			cls.downloadpercent = 10*(percent/10);
+			Con_Printf ("%i%%", cls.downloadpercent);
+		}
+#endif
+		cls.downloadpercent = percent;
+
+		MSG_WriteByte (&cls.netchan.message, clc_stringcmd);
+		SZ_Print (&cls.netchan.message, "nextdl");
+	}
+	else
+	{
+		char	oldn[MAX_OSPATH];
+		char	newn[MAX_OSPATH];
+
+#if 0
+		Con_Printf ("100%%\n");
+#endif
+
+		fclose (cls.download);
+
+		// rename the temp file to it's final name
+		if (strcmp(cls.downloadtempname, cls.downloadname)) {
+			if (strncmp(cls.downloadtempname,"skins/",6)) {
+				sprintf (oldn, "%s/%s", com_gamedir, cls.downloadtempname);
+				sprintf (newn, "%s/%s", com_gamedir, cls.downloadname);
+			} else {
+				sprintf (oldn, "qw/%s", cls.downloadtempname);
+				sprintf (newn, "qw/%s", cls.downloadname);
+			}
+			r = rename (oldn, newn);
+			if (r)
+				Con_Printf ("failed to rename.\n");
+		}
+
+		cls.download = NULL;
+		cls.downloadpercent = 0;
+
+		// get another file if needed
+
+		CL_RequestNextDownload ();
+	}
+}
+
+static byte *upload_data;
+static int upload_pos;
+static int upload_size;
+
+void CL_NextUpload(void)
+{
+	byte	buffer[1024];
+	int		r;
+	int		percent;
+	int		size;
+
+	if (!upload_data)
+		return;
+
+	r = upload_size - upload_pos;
+	if (r > 768)
+		r = 768;
+	memcpy(buffer, upload_data + upload_pos, r);
+	MSG_WriteByte (&cls.netchan.message, clc_upload);
+	MSG_WriteShort (&cls.netchan.message, r);
+
+	upload_pos += r;
+	size = upload_size;
+	if (!size)
+		size = 1;
+	percent = upload_pos*100/size;
+	MSG_WriteByte (&cls.netchan.message, percent);
+	SZ_Write (&cls.netchan.message, buffer, r);
+
+Con_DPrintf ("UPLOAD: %6d: %d written\n", upload_pos - r, r);
+
+	if (upload_pos != upload_size)
+		return;
+
+	Con_Printf ("Upload completed\n");
+
+	free(upload_data);
+	upload_data = 0;
+	upload_pos = upload_size = 0;
+}
+
+void CL_StartUpload (byte *data, int size)
+{
+	if (cls.state < ca_onserver)
+		return; // gotta be connected
+
+	// override
+	if (upload_data)
+		free(upload_data);
+
+Con_DPrintf("Upload starting of %d...\n", size);
+
+	upload_data = malloc(size);
+	memcpy(upload_data, data, size);
+	upload_size = size;
+	upload_pos = 0;
+
+	CL_NextUpload();
+} 
+
+qboolean CL_IsUploading(void)
+{
+	if (upload_data)
+		return true;
+	return false;
+}
+
+void CL_StopUpload(void)
+{
+	if (upload_data)
+		free(upload_data);
+	upload_data = NULL;
+}
+
+/*
+=====================================================================
+
+  SERVER CONNECTING MESSAGES
+
+=====================================================================
+*/
+
+/*
+==================
+CL_ParseServerData
+==================
+*/
+void CL_ParseServerData (void)
+{
+	char	*str;
+	FILE	*f;
+	char	fn[MAX_OSPATH];
+	qboolean	cflag = false;
+	extern	char	gamedirfile[MAX_OSPATH];
+	int protover;
+	
+	Con_DPrintf ("Serverdata packet received.\n");
+//
+// wipe the client_state_t struct
+//
+	CL_ClearState ();
+
+// parse protocol version number
+// allow 2.2 and 2.29 demos to play
+	protover = MSG_ReadLong ();
+	if (protover != PROTOCOL_VERSION && 
+		!(cls.demoplayback && (protover == 26 || protover == 27 || protover == 28)))
+		Host_EndGame ("Server returned version %i, not %i\nYou probably need to upgrade.\nCheck http://www.quakeworld.net/", protover, PROTOCOL_VERSION);
+
+	cl.servercount = MSG_ReadLong ();
+
+	// game directory
+	str = MSG_ReadString ();
+
+	if (stricmp(gamedirfile, str)) {
+		// save current config
+		Host_WriteConfiguration (); 
+		cflag = true;
+	}
+
+	COM_Gamedir(str);
+
+	//ZOID--run the autoexec.cfg in the gamedir
+	//if it exists
+	if (cflag) {
+		sprintf(fn, "%s/%s", com_gamedir, "config.cfg");
+		if ((f = fopen(fn, "r")) != NULL) {
+			fclose(f);
+			Cbuf_AddText ("cl_warncmd 0\n");
+			Cbuf_AddText("exec config.cfg\n");
+			Cbuf_AddText("exec frontend.cfg\n");
+			Cbuf_AddText ("cl_warncmd 1\n");
+		}
+	}
+
+	// parse player slot, high bit means spectator
+	cl.playernum = MSG_ReadByte ();
+	if (cl.playernum & 128)
+	{
+		cl.spectator = true;
+		cl.playernum &= ~128;
+	}
+
+	// get the full level name
+	str = MSG_ReadString ();
+	strncpy (cl.levelname, str, sizeof(cl.levelname)-1);
+
+	// get the movevars
+	movevars.gravity			= MSG_ReadFloat();
+	movevars.stopspeed          = MSG_ReadFloat();
+	movevars.maxspeed           = MSG_ReadFloat();
+	movevars.spectatormaxspeed  = MSG_ReadFloat();
+	movevars.accelerate         = MSG_ReadFloat();
+	movevars.airaccelerate      = MSG_ReadFloat();
+	movevars.wateraccelerate    = MSG_ReadFloat();
+	movevars.friction           = MSG_ReadFloat();
+	movevars.waterfriction      = MSG_ReadFloat();
+	movevars.entgravity         = MSG_ReadFloat();
+
+	// seperate the printfs so the server message can have a color
+	Con_Printf("\n\n\35\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\37\n\n");
+	Con_Printf ("%c%s\n", 2, str);
+
+	// ask for the sound list next
+	memset(cl.sound_name, 0, sizeof(cl.sound_name));
+	MSG_WriteByte (&cls.netchan.message, clc_stringcmd);
+//	MSG_WriteString (&cls.netchan.message, va("soundlist %i 0", cl.servercount));
+	MSG_WriteString (&cls.netchan.message, va(soundlist_name, cl.servercount, 0));
+
+	// now waiting for downloads, etc
+	cls.state = ca_onserver;
+}
+
+/*
+==================
+CL_ParseSoundlist
+==================
+*/
+void CL_ParseSoundlist (void)
+{
+	int	numsounds;
+	char	*str;
+	int n;
+
+// precache sounds
+//	memset (cl.sound_precache, 0, sizeof(cl.sound_precache));
+
+	numsounds = MSG_ReadByte();
+
+	for (;;) {
+		str = MSG_ReadString ();
+		if (!str[0])
+			break;
+		numsounds++;
+		if (numsounds == MAX_SOUNDS)
+			Host_EndGame ("Server sent too many sound_precache");
+		strcpy (cl.sound_name[numsounds], str);
+	}
+
+	n = MSG_ReadByte();
+
+	if (n) {
+		MSG_WriteByte (&cls.netchan.message, clc_stringcmd);
+//		MSG_WriteString (&cls.netchan.message, va("soundlist %i %i", cl.servercount, n));
+		MSG_WriteString (&cls.netchan.message, va(soundlist_name, cl.servercount, n));
+		return;
+	}
+
+	cls.downloadnumber = 0;
+	cls.downloadtype = dl_sound;
+	Sound_NextDownload ();
+}
+
+/*
+==================
+CL_ParseModellist
+==================
+*/
+void CL_ParseModellist (void)
+{
+	int	nummodels;
+	char	*str;
+	int n;
+
+// precache models and note certain default indexes
+	nummodels = MSG_ReadByte();
+
+	for (;;)
+	{
+		str = MSG_ReadString ();
+		if (!str[0])
+			break;
+		nummodels++;
+		if (nummodels==MAX_MODELS)
+			Host_EndGame ("Server sent too many model_precache");
+		strcpy (cl.model_name[nummodels], str);
+
+		if (!strcmp(cl.model_name[nummodels],"progs/spike.mdl"))
+			cl_spikeindex = nummodels;
+		if (!strcmp(cl.model_name[nummodels],"progs/player.mdl"))
+			cl_playerindex = nummodels;
+		if (!strcmp(cl.model_name[nummodels],"progs/flag.mdl"))
+			cl_flagindex = nummodels;
+	}
+
+	n = MSG_ReadByte();
+
+	if (n) {
+		MSG_WriteByte (&cls.netchan.message, clc_stringcmd);
+//		MSG_WriteString (&cls.netchan.message, va("modellist %i %i", cl.servercount, n));
+		MSG_WriteString (&cls.netchan.message, va(modellist_name, cl.servercount, n));
+		return;
+	}
+
+	cls.downloadnumber = 0;
+	cls.downloadtype = dl_model;
+	Model_NextDownload ();
+}
+
+/*
+==================
+CL_ParseBaseline
+==================
+*/
+void CL_ParseBaseline (entity_state_t *es)
+{
+	int			i;
+	
+	es->modelindex = MSG_ReadByte ();
+	es->frame = MSG_ReadByte ();
+	es->colormap = MSG_ReadByte();
+	es->skinnum = MSG_ReadByte();
+	for (i=0 ; i<3 ; i++)
+	{
+		es->origin[i] = MSG_ReadCoord ();
+		es->angles[i] = MSG_ReadAngle ();
+	}
+}
+
+
+
+/*
+=====================
+CL_ParseStatic
+
+Static entities are non-interactive world objects
+like torches
+=====================
+*/
+void CL_ParseStatic (void)
+{
+	entity_t *ent;
+	int		i;
+	entity_state_t	es;
+
+	CL_ParseBaseline (&es);
+		
+	i = cl.num_statics;
+	if (i >= MAX_STATIC_ENTITIES)
+		Host_EndGame ("Too many static entities");
+	ent = &cl_static_entities[i];
+	cl.num_statics++;
+
+// copy it to the current state
+	ent->model = cl.model_precache[es.modelindex];
+	ent->frame = es.frame;
+	ent->colormap = vid.colormap;
+	ent->skinnum = es.skinnum;
+
+	VectorCopy (es.origin, ent->origin);
+	VectorCopy (es.angles, ent->angles);
+	
+	R_AddEfrags (ent);
+}
+
+/*
+===================
+CL_ParseStaticSound
+===================
+*/
+void CL_ParseStaticSound (void)
+{
+	vec3_t		org;
+	int			sound_num, vol, atten;
+	int			i;
+	
+	for (i=0 ; i<3 ; i++)
+		org[i] = MSG_ReadCoord ();
+	sound_num = MSG_ReadByte ();
+	vol = MSG_ReadByte ();
+	atten = MSG_ReadByte ();
+	
+	S_StaticSound (cl.sound_precache[sound_num], org, vol, atten);
+}
+
+
+
+/*
+=====================================================================
+
+ACTION MESSAGES
+
+=====================================================================
+*/
+
+/*
+==================
+CL_ParseStartSoundPacket
+==================
+*/
+void CL_ParseStartSoundPacket(void)
+{
+    vec3_t  pos;
+    int 	channel, ent;
+    int 	sound_num;
+    int 	volume;
+    float 	attenuation;  
+ 	int		i;
+	           
+    channel = MSG_ReadShort(); 
+
+    if (channel & SND_VOLUME)
+		volume = MSG_ReadByte ();
+	else
+		volume = DEFAULT_SOUND_PACKET_VOLUME;
+	
+    if (channel & SND_ATTENUATION)
+		attenuation = MSG_ReadByte () / 64.0;
+	else
+		attenuation = DEFAULT_SOUND_PACKET_ATTENUATION;
+	
+	sound_num = MSG_ReadByte ();
+
+	for (i=0 ; i<3 ; i++)
+		pos[i] = MSG_ReadCoord ();
+ 
+	ent = (channel>>3)&1023;
+	channel &= 7;
+
+	if (ent > MAX_EDICTS)
+		Host_EndGame ("CL_ParseStartSoundPacket: ent = %i", ent);
+	
+    S_StartSound (ent, channel, cl.sound_precache[sound_num], pos, volume/255.0, attenuation);
+}       
+
+
+/*
+==================
+CL_ParseClientdata
+
+Server information pertaining to this client only, sent every frame
+==================
+*/
+void CL_ParseClientdata (void)
+{
+	int				i;
+	float		latency;
+	frame_t		*frame;
+
+// calculate simulated time of message
+	oldparsecountmod = parsecountmod;
+
+	i = cls.netchan.incoming_acknowledged;
+	cl.parsecount = i;
+	i &= UPDATE_MASK;
+	parsecountmod = i;
+	frame = &cl.frames[i];
+	parsecounttime = cl.frames[i].senttime;
+
+	frame->receivedtime = realtime;
+
+// calculate latency
+	latency = frame->receivedtime - frame->senttime;
+
+	if (latency < 0 || latency > 1.0)
+	{
+//		Con_Printf ("Odd latency: %5.2f\n", latency);
+	}
+	else
+	{
+	// drift the average latency towards the observed latency
+		if (latency < cls.latency)
+			cls.latency = latency;
+		else
+			cls.latency += 0.001;	// drift up, so correction are needed
+	}	
+}
+
+/*
+=====================
+CL_NewTranslation
+=====================
+*/
+void CL_NewTranslation (int slot)
+{
+#ifdef GLQUAKE
+	if (slot > MAX_CLIENTS)
+		Sys_Error ("CL_NewTranslation: slot > MAX_CLIENTS");
+
+	R_TranslatePlayerSkin(slot);
+#else
+
+	int		i, j;
+	int		top, bottom;
+	byte	*dest, *source;
+	player_info_t	*player;
+	char s[512];
+
+	if (slot > MAX_CLIENTS)
+		Sys_Error ("CL_NewTranslation: slot > MAX_CLIENTS");
+
+	player = &cl.players[slot];
+
+	strcpy(s, Info_ValueForKey(player->userinfo, "skin"));
+	COM_StripExtension(s, s);
+	if (player->skin && !stricmp(s, player->skin->name))
+		player->skin = NULL;
+
+	if (player->_topcolor != player->topcolor ||
+		player->_bottomcolor != player->bottomcolor || !player->skin) {
+		player->_topcolor = player->topcolor;
+		player->_bottomcolor = player->bottomcolor;
+
+		dest = player->translations;
+		source = vid.colormap;
+		memcpy (dest, vid.colormap, sizeof(player->translations));
+		top = player->topcolor;
+		if (top > 13 || top < 0)
+			top = 13;
+		top *= 16;
+		bottom = player->bottomcolor;
+		if (bottom > 13 || bottom < 0)
+			bottom = 13;
+		bottom *= 16;
+
+		for (i=0 ; i<VID_GRADES ; i++, dest += 256, source+=256)
+		{
+			if (top < 128)	// the artists made some backwards ranges.  sigh.
+				memcpy (dest + TOP_RANGE, source + top, 16);
+			else
+				for (j=0 ; j<16 ; j++)
+					dest[TOP_RANGE+j] = source[top+15-j];
+					
+			if (bottom < 128)
+				memcpy (dest + BOTTOM_RANGE, source + bottom, 16);
+			else
+				for (j=0 ; j<16 ; j++)
+					dest[BOTTOM_RANGE+j] = source[bottom+15-j];		
+		}
+	}
+#endif
+}
+
+/*
+==============
+CL_UpdateUserinfo
+==============
+*/
+void CL_ProcessUserInfo (int slot, player_info_t *player)
+{
+	strncpy (player->name, Info_ValueForKey (player->userinfo, "name"), sizeof(player->name)-1);
+	player->topcolor = atoi(Info_ValueForKey (player->userinfo, "topcolor"));
+	player->bottomcolor = atoi(Info_ValueForKey (player->userinfo, "bottomcolor"));
+	if (Info_ValueForKey (player->userinfo, "*spectator")[0])
+		player->spectator = true;
+	else
+		player->spectator = false;
+
+	if (cls.state == ca_active)
+		Skin_Find (player);
+
+	Sbar_Changed ();
+	CL_NewTranslation (slot);
+}
+
+/*
+==============
+CL_UpdateUserinfo
+==============
+*/
+void CL_UpdateUserinfo (void)
+{
+	int		slot;
+	player_info_t	*player;
+
+	slot = MSG_ReadByte ();
+	if (slot >= MAX_CLIENTS)
+		Host_EndGame ("CL_ParseServerMessage: svc_updateuserinfo > MAX_SCOREBOARD");
+
+	player = &cl.players[slot];
+	player->userid = MSG_ReadLong ();
+	strncpy (player->userinfo, MSG_ReadString(), sizeof(player->userinfo)-1);
+
+	CL_ProcessUserInfo (slot, player);
+}
+
+/*
+==============
+CL_SetInfo
+==============
+*/
+void CL_SetInfo (void)
+{
+	int		slot;
+	player_info_t	*player;
+	char key[MAX_MSGLEN];
+	char value[MAX_MSGLEN];
+
+	slot = MSG_ReadByte ();
+	if (slot >= MAX_CLIENTS)
+		Host_EndGame ("CL_ParseServerMessage: svc_setinfo > MAX_SCOREBOARD");
+
+	player = &cl.players[slot];
+
+	strncpy (key, MSG_ReadString(), sizeof(key) - 1);
+	key[sizeof(key) - 1] = 0;
+	strncpy (value, MSG_ReadString(), sizeof(value) - 1);
+	key[sizeof(value) - 1] = 0;
+
+	Con_DPrintf("SETINFO %s: %s=%s\n", player->name, key, value);
+
+	Info_SetValueForKey (player->userinfo, key, value, MAX_INFO_STRING);
+
+	CL_ProcessUserInfo (slot, player);
+}
+
+/*
+==============
+CL_ServerInfo
+==============
+*/
+void CL_ServerInfo (void)
+{
+	int		slot;
+	player_info_t	*player;
+	char key[MAX_MSGLEN];
+	char value[MAX_MSGLEN];
+
+	strncpy (key, MSG_ReadString(), sizeof(key) - 1);
+	key[sizeof(key) - 1] = 0;
+	strncpy (value, MSG_ReadString(), sizeof(value) - 1);
+	key[sizeof(value) - 1] = 0;
+
+	Con_DPrintf("SERVERINFO: %s=%s\n", key, value);
+
+	Info_SetValueForKey (cl.serverinfo, key, value, MAX_SERVERINFO_STRING);
+}
+
+/*
+=====================
+CL_SetStat
+=====================
+*/
+void CL_SetStat (int stat, int value)
+{
+	int	j;
+	if (stat < 0 || stat >= MAX_CL_STATS)
+		Sys_Error ("CL_SetStat: %i is invalid", stat);
+
+	Sbar_Changed ();
+	
+	if (stat == STAT_ITEMS)
+	{	// set flash times
+		Sbar_Changed ();
+		for (j=0 ; j<32 ; j++)
+			if ( (value & (1<<j)) && !(cl.stats[stat] & (1<<j)))
+				cl.item_gettime[j] = cl.time;
+	}
+
+	cl.stats[stat] = value;
+}
+
+/*
+==============
+CL_MuzzleFlash
+==============
+*/
+void CL_MuzzleFlash (void)
+{
+	vec3_t		fv, rv, uv;
+	dlight_t	*dl;
+	int			i;
+	player_state_t	*pl;
+
+	i = MSG_ReadShort ();
+
+	if ((unsigned)(i-1) >= MAX_CLIENTS)
+		return;
+
+#ifdef GLQUAKE
+	// don't draw our own muzzle flash in gl if flashblending
+	if (i-1 == cl.playernum && gl_flashblend.value)
+		return;
+#endif
+
+	pl = &cl.frames[parsecountmod].playerstate[i-1];
+
+	dl = CL_AllocDlight (i);
+	VectorCopy (pl->origin,  dl->origin);
+	AngleVectors (pl->viewangles, fv, rv, uv);
+		
+	VectorMA (dl->origin, 18, fv, dl->origin);
+	dl->radius = 200 + (rand()&31);
+	dl->minlight = 32;
+	dl->die = cl.time + 0.1;
+	dl->color[0] = 0.2;
+	dl->color[1] = 0.1;
+	dl->color[2] = 0.05;
+	dl->color[3] = 0.7;
+}
+
+
+#define SHOWNET(x) if(cl_shownet.value==2)Con_Printf ("%3i:%s\n", msg_readcount-1, x);
+/*
+=====================
+CL_ParseServerMessage
+=====================
+*/
+int	received_framecount;
+void CL_ParseServerMessage (void)
+{
+	int			cmd;
+	char		*s;
+	int			i, j;
+
+	received_framecount = host_framecount;
+	cl.last_servermessage = realtime;
+	CL_ClearProjectiles ();
+
+//
+// if recording demos, copy the message out
+//
+	if (cl_shownet.value == 1)
+		Con_Printf ("%i ",net_message.cursize);
+	else if (cl_shownet.value == 2)
+		Con_Printf ("------------------\n");
+
+
+	CL_ParseClientdata ();
+
+//
+// parse the message
+//
+	while (1)
+	{
+		if (msg_badread)
+		{
+			Host_EndGame ("CL_ParseServerMessage: Bad server message");
+			break;
+		}
+
+		cmd = MSG_ReadByte ();
+
+		if (cmd == -1)
+		{
+			msg_readcount++;	// so the EOM showner has the right value
+			SHOWNET("END OF MESSAGE");
+			break;
+		}
+
+		SHOWNET(svc_strings[cmd]);
+	
+	// other commands
+		switch (cmd)
+		{
+		default:
+			Host_EndGame ("CL_ParseServerMessage: Illegible server message");
+			break;
+			
+		case svc_nop:
+//			Con_Printf ("svc_nop\n");
+			break;
+			
+		case svc_disconnect:
+			if (cls.state == ca_connected)
+				Host_EndGame ("Server disconnected\n"
+					"Server version may not be compatible");
+			else
+				Host_EndGame ("Server disconnected");
+			break;
+
+		case svc_print:
+			i = MSG_ReadByte ();
+			if (i == PRINT_CHAT)
+			{
+				S_LocalSound ("misc/talk.wav");
+				con_ormask = 128;
+			}
+			Con_Printf ("%s", MSG_ReadString ());
+			con_ormask = 0;
+			break;
+			
+		case svc_centerprint:
+			SCR_CenterPrint (MSG_ReadString ());
+			break;
+			
+		case svc_stufftext:
+			s = MSG_ReadString ();
+			Con_DPrintf ("stufftext: %s\n", s);
+			Cbuf_AddText (s);
+			break;
+			
+		case svc_damage:
+			V_ParseDamage ();
+			break;
+			
+		case svc_serverdata:
+			Cbuf_Execute ();		// make sure any stuffed commands are done
+			CL_ParseServerData ();
+			vid.recalc_refdef = true;	// leave full screen intermission
+			break;
+			
+		case svc_setangle:
+			for (i=0 ; i<3 ; i++)
+				cl.viewangles[i] = MSG_ReadAngle ();
+//			cl.viewangles[PITCH] = cl.viewangles[ROLL] = 0;
+			break;
+			
+		case svc_lightstyle:
+			i = MSG_ReadByte ();
+			if (i >= MAX_LIGHTSTYLES)
+				Sys_Error ("svc_lightstyle > MAX_LIGHTSTYLES");
+			Q_strcpy (cl_lightstyle[i].map,  MSG_ReadString());
+			cl_lightstyle[i].length = Q_strlen(cl_lightstyle[i].map);
+			break;
+			
+		case svc_sound:
+			CL_ParseStartSoundPacket();
+			break;
+			
+		case svc_stopsound:
+			i = MSG_ReadShort();
+			S_StopSound(i>>3, i&7);
+			break;
+		
+		case svc_updatefrags:
+			Sbar_Changed ();
+			i = MSG_ReadByte ();
+			if (i >= MAX_CLIENTS)
+				Host_EndGame ("CL_ParseServerMessage: svc_updatefrags > MAX_SCOREBOARD");
+			cl.players[i].frags = MSG_ReadShort ();
+			break;			
+
+		case svc_updateping:
+			i = MSG_ReadByte ();
+			if (i >= MAX_CLIENTS)
+				Host_EndGame ("CL_ParseServerMessage: svc_updateping > MAX_SCOREBOARD");
+			cl.players[i].ping = MSG_ReadShort ();
+			break;
+			
+		case svc_updatepl:
+			i = MSG_ReadByte ();
+			if (i >= MAX_CLIENTS)
+				Host_EndGame ("CL_ParseServerMessage: svc_updatepl > MAX_SCOREBOARD");
+			cl.players[i].pl = MSG_ReadByte ();
+			break;
+			
+		case svc_updateentertime:
+		// time is sent over as seconds ago
+			i = MSG_ReadByte ();
+			if (i >= MAX_CLIENTS)
+				Host_EndGame ("CL_ParseServerMessage: svc_updateentertime > MAX_SCOREBOARD");
+			cl.players[i].entertime = realtime - MSG_ReadFloat ();
+			break;
+			
+		case svc_spawnbaseline:
+			i = MSG_ReadShort ();
+			CL_ParseBaseline (&cl_baselines[i]);
+			break;
+		case svc_spawnstatic:
+			CL_ParseStatic ();
+			break;			
+		case svc_temp_entity:
+			CL_ParseTEnt ();
+			break;
+
+		case svc_killedmonster:
+			cl.stats[STAT_MONSTERS]++;
+			break;
+
+		case svc_foundsecret:
+			cl.stats[STAT_SECRETS]++;
+			break;
+
+		case svc_updatestat:
+			i = MSG_ReadByte ();
+			j = MSG_ReadByte ();
+			CL_SetStat (i, j);
+			break;
+		case svc_updatestatlong:
+			i = MSG_ReadByte ();
+			j = MSG_ReadLong ();
+			CL_SetStat (i, j);
+			break;
+			
+		case svc_spawnstaticsound:
+			CL_ParseStaticSound ();
+			break;
+
+		case svc_cdtrack:
+			cl.cdtrack = MSG_ReadByte ();
+			CDAudio_Play ((byte)cl.cdtrack, true);
+			break;
+
+		case svc_intermission:
+			cl.intermission = 1;
+			cl.completed_time = realtime;
+			vid.recalc_refdef = true;	// go to full screen
+			for (i=0 ; i<3 ; i++)
+				cl.simorg[i] = MSG_ReadCoord ();			
+			for (i=0 ; i<3 ; i++)
+				cl.simangles[i] = MSG_ReadAngle ();
+			VectorCopy (vec3_origin, cl.simvel);
+			break;
+
+		case svc_finale:
+			cl.intermission = 2;
+			cl.completed_time = realtime;
+			vid.recalc_refdef = true;	// go to full screen
+			SCR_CenterPrint (MSG_ReadString ());			
+			break;
+			
+		case svc_sellscreen:
+			Cmd_ExecuteString ("help");
+			break;
+
+		case svc_smallkick:
+			cl.punchangle = -2;
+			break;
+		case svc_bigkick:
+			cl.punchangle = -4;
+			break;
+
+		case svc_muzzleflash:
+			CL_MuzzleFlash ();
+			break;
+
+		case svc_updateuserinfo:
+			CL_UpdateUserinfo ();
+			break;
+
+		case svc_setinfo:
+			CL_SetInfo ();
+			break;
+
+		case svc_serverinfo:
+			CL_ServerInfo ();
+			break;
+
+		case svc_download:
+			CL_ParseDownload ();
+			break;
+
+		case svc_playerinfo:
+			CL_ParsePlayerinfo ();
+			break;
+
+		case svc_nails:
+			CL_ParseProjectiles ();
+			break;
+
+		case svc_chokecount:		// some preceding packets were choked
+			i = MSG_ReadByte ();
+			for (j=0 ; j<i ; j++)
+				cl.frames[ (cls.netchan.incoming_acknowledged-1-j)&UPDATE_MASK ].receivedtime = -2;
+			break;
+
+		case svc_modellist:
+			CL_ParseModellist ();
+			break;
+
+		case svc_soundlist:
+			CL_ParseSoundlist ();
+			break;
+
+		case svc_packetentities:
+			CL_ParsePacketEntities (false);
+			break;
+
+		case svc_deltapacketentities:
+			CL_ParsePacketEntities (true);
+			break;
+
+		case svc_maxspeed :
+			movevars.maxspeed = MSG_ReadFloat();
+			break;
+
+		case svc_entgravity :
+			movevars.entgravity = MSG_ReadFloat();
+			break;
+
+		case svc_setpause:
+			cl.paused = MSG_ReadByte ();
+			if (cl.paused)
+				CDAudio_Pause ();
+			else
+				CDAudio_Resume ();
+			break;
+
+		}
+	}
+
+	CL_SetSolidEntities ();
+}
+
+
--- /dev/null
+++ b/QW/client/cl_pred.c
@@ -1,0 +1,225 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+#include "quakedef.h"
+#include "winquake.h"
+
+cvar_t	cl_nopred = {"cl_nopred","0"};
+cvar_t	cl_pushlatency = {"pushlatency","-999"};
+
+extern	frame_t		*view_frame;
+
+/*
+=================
+CL_NudgePosition
+
+If pmove.origin is in a solid position,
+try nudging slightly on all axis to
+allow for the cut precision of the net coordinates
+=================
+*/
+void CL_NudgePosition (void)
+{
+	vec3_t	base;
+	int		x, y;
+
+	if (PM_HullPointContents (&cl.model_precache[1]->hulls[1], 0, pmove.origin) == CONTENTS_EMPTY)
+		return;
+
+	VectorCopy (pmove.origin, base);
+	for (x=-1 ; x<=1 ; x++)
+	{
+		for (y=-1 ; y<=1 ; y++)
+		{
+			pmove.origin[0] = base[0] + x * 1.0/8;
+			pmove.origin[1] = base[1] + y * 1.0/8;
+			if (PM_HullPointContents (&cl.model_precache[1]->hulls[1], 0, pmove.origin) == CONTENTS_EMPTY)
+				return;
+		}
+	}
+	Con_DPrintf ("CL_NudgePosition: stuck\n");
+}
+
+/*
+==============
+CL_PredictUsercmd
+==============
+*/
+void CL_PredictUsercmd (player_state_t *from, player_state_t *to, usercmd_t *u, qboolean spectator)
+{
+	// split up very long moves
+	if (u->msec > 50)
+	{
+		player_state_t	temp;
+		usercmd_t	split;
+
+		split = *u;
+		split.msec /= 2;
+
+		CL_PredictUsercmd (from, &temp, &split, spectator);
+		CL_PredictUsercmd (&temp, to, &split, spectator);
+		return;
+	}
+
+	VectorCopy (from->origin, pmove.origin);
+//	VectorCopy (from->viewangles, pmove.angles);
+	VectorCopy (u->angles, pmove.angles);
+	VectorCopy (from->velocity, pmove.velocity);
+
+	pmove.oldbuttons = from->oldbuttons;
+	pmove.waterjumptime = from->waterjumptime;
+	pmove.dead = cl.stats[STAT_HEALTH] <= 0;
+	pmove.spectator = spectator;
+
+	pmove.cmd = *u;
+
+	PlayerMove ();
+//for (i=0 ; i<3 ; i++)
+//pmove.origin[i] = ((int)(pmove.origin[i]*8))*0.125;
+	to->waterjumptime = pmove.waterjumptime;
+	to->oldbuttons = pmove.cmd.buttons;
+	VectorCopy (pmove.origin, to->origin);
+	VectorCopy (pmove.angles, to->viewangles);
+	VectorCopy (pmove.velocity, to->velocity);
+	to->onground = onground;
+
+	to->weaponframe = from->weaponframe;
+}
+
+
+
+/*
+==============
+CL_PredictMove
+==============
+*/
+void CL_PredictMove (void)
+{
+	int			i;
+	float		f;
+	frame_t		*from, *to = NULL;
+	int			oldphysent;
+
+	if (cl_pushlatency.value > 0)
+		Cvar_Set ("pushlatency", "0");
+
+	if (cl.paused)
+		return;
+
+	cl.time = realtime - cls.latency - cl_pushlatency.value*0.001;
+	if (cl.time > realtime)
+		cl.time = realtime;
+
+	if (cl.intermission)
+		return;
+
+	if (!cl.validsequence)
+		return;
+
+	if (cls.netchan.outgoing_sequence - cls.netchan.incoming_sequence >= UPDATE_BACKUP-1)
+		return;
+
+	VectorCopy (cl.viewangles, cl.simangles);
+
+	// this is the last frame received from the server
+	from = &cl.frames[cls.netchan.incoming_sequence & UPDATE_MASK];
+
+	// we can now render a frame
+	if (cls.state == ca_onserver)
+	{	// first update is the final signon stage
+		char		text[1024];
+
+		cls.state = ca_active;
+		sprintf (text, "QuakeWorld: %s", cls.servername);
+#ifdef _WIN32
+		SetWindowText (mainwindow, text);
+#endif
+	}
+
+	if (cl_nopred.value)
+	{
+		VectorCopy (from->playerstate[cl.playernum].velocity, cl.simvel);
+		VectorCopy (from->playerstate[cl.playernum].origin, cl.simorg);
+		return;
+	}
+
+	// predict forward until cl.time <= to->senttime
+	oldphysent = pmove.numphysent;
+	CL_SetSolidPlayers (cl.playernum);
+
+//	to = &cl.frames[cls.netchan.incoming_sequence & UPDATE_MASK];
+
+	for (i=1 ; i<UPDATE_BACKUP-1 && cls.netchan.incoming_sequence+i <
+			cls.netchan.outgoing_sequence; i++)
+	{
+		to = &cl.frames[(cls.netchan.incoming_sequence+i) & UPDATE_MASK];
+		CL_PredictUsercmd (&from->playerstate[cl.playernum]
+			, &to->playerstate[cl.playernum], &to->cmd, cl.spectator);
+		if (to->senttime >= cl.time)
+			break;
+		from = to;
+	}
+
+	pmove.numphysent = oldphysent;
+
+	if (i == UPDATE_BACKUP-1 || !to)
+		return;		// net hasn't deliver packets in a long time...
+
+	// now interpolate some fraction of the final frame
+	if (to->senttime == from->senttime)
+		f = 0;
+	else
+	{
+		f = (cl.time - from->senttime) / (to->senttime - from->senttime);
+
+		if (f < 0)
+			f = 0;
+		if (f > 1)
+			f = 1;
+	}
+
+	for (i=0 ; i<3 ; i++)
+		if ( fabs(from->playerstate[cl.playernum].origin[i] - to->playerstate[cl.playernum].origin[i]) > 128)
+		{	// teleported, so don't lerp
+			VectorCopy (to->playerstate[cl.playernum].velocity, cl.simvel);
+			VectorCopy (to->playerstate[cl.playernum].origin, cl.simorg);
+			return;
+		}
+		
+	for (i=0 ; i<3 ; i++)
+	{
+		cl.simorg[i] = from->playerstate[cl.playernum].origin[i] 
+			+ f*(to->playerstate[cl.playernum].origin[i] - from->playerstate[cl.playernum].origin[i]);
+		cl.simvel[i] = from->playerstate[cl.playernum].velocity[i] 
+			+ f*(to->playerstate[cl.playernum].velocity[i] - from->playerstate[cl.playernum].velocity[i]);
+	}		
+}
+
+
+/*
+==============
+CL_InitPrediction
+==============
+*/
+void CL_InitPrediction (void)
+{
+	Cvar_RegisterVariable (&cl_pushlatency);
+	Cvar_RegisterVariable (&cl_nopred);
+}
+
--- /dev/null
+++ b/QW/client/cl_tent.c
@@ -1,0 +1,459 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// cl_tent.c -- client side temporary entities
+
+#include "quakedef.h"
+
+
+#define	MAX_BEAMS	8
+typedef struct
+{
+	int		entity;
+	struct model_s	*model;
+	float	endtime;
+	vec3_t	start, end;
+} beam_t;
+
+beam_t		cl_beams[MAX_BEAMS];
+
+#define	MAX_EXPLOSIONS	8
+typedef struct
+{
+	vec3_t	origin;
+	float	start;
+	model_t	*model;
+} explosion_t;
+
+explosion_t	cl_explosions[MAX_EXPLOSIONS];
+
+
+sfx_t			*cl_sfx_wizhit;
+sfx_t			*cl_sfx_knighthit;
+sfx_t			*cl_sfx_tink1;
+sfx_t			*cl_sfx_ric1;
+sfx_t			*cl_sfx_ric2;
+sfx_t			*cl_sfx_ric3;
+sfx_t			*cl_sfx_r_exp3;
+
+/*
+=================
+CL_ParseTEnts
+=================
+*/
+void CL_InitTEnts (void)
+{
+	cl_sfx_wizhit = S_PrecacheSound ("wizard/hit.wav");
+	cl_sfx_knighthit = S_PrecacheSound ("hknight/hit.wav");
+	cl_sfx_tink1 = S_PrecacheSound ("weapons/tink1.wav");
+	cl_sfx_ric1 = S_PrecacheSound ("weapons/ric1.wav");
+	cl_sfx_ric2 = S_PrecacheSound ("weapons/ric2.wav");
+	cl_sfx_ric3 = S_PrecacheSound ("weapons/ric3.wav");
+	cl_sfx_r_exp3 = S_PrecacheSound ("weapons/r_exp3.wav");
+}
+
+/*
+=================
+CL_ClearTEnts
+=================
+*/
+void CL_ClearTEnts (void)
+{
+	memset (&cl_beams, 0, sizeof(cl_beams));
+	memset (&cl_explosions, 0, sizeof(cl_explosions));
+}
+
+/*
+=================
+CL_AllocExplosion
+=================
+*/
+explosion_t *CL_AllocExplosion (void)
+{
+	int		i;
+	float	time;
+	int		index;
+	
+	for (i=0 ; i<MAX_EXPLOSIONS ; i++)
+		if (!cl_explosions[i].model)
+			return &cl_explosions[i];
+// find the oldest explosion
+	time = cl.time;
+	index = 0;
+
+	for (i=0 ; i<MAX_EXPLOSIONS ; i++)
+		if (cl_explosions[i].start < time)
+		{
+			time = cl_explosions[i].start;
+			index = i;
+		}
+	return &cl_explosions[index];
+}
+
+/*
+=================
+CL_ParseBeam
+=================
+*/
+void CL_ParseBeam (model_t *m)
+{
+	int		ent;
+	vec3_t	start, end;
+	beam_t	*b;
+	int		i;
+	
+	ent = MSG_ReadShort ();
+	
+	start[0] = MSG_ReadCoord ();
+	start[1] = MSG_ReadCoord ();
+	start[2] = MSG_ReadCoord ();
+	
+	end[0] = MSG_ReadCoord ();
+	end[1] = MSG_ReadCoord ();
+	end[2] = MSG_ReadCoord ();
+
+// override any beam with the same entity
+	for (i=0, b=cl_beams ; i< MAX_BEAMS ; i++, b++)
+		if (b->entity == ent)
+		{
+			b->entity = ent;
+			b->model = m;
+			b->endtime = cl.time + 0.2;
+			VectorCopy (start, b->start);
+			VectorCopy (end, b->end);
+			return;
+		}
+
+// find a free beam
+	for (i=0, b=cl_beams ; i< MAX_BEAMS ; i++, b++)
+	{
+		if (!b->model || b->endtime < cl.time)
+		{
+			b->entity = ent;
+			b->model = m;
+			b->endtime = cl.time + 0.2;
+			VectorCopy (start, b->start);
+			VectorCopy (end, b->end);
+			return;
+		}
+	}
+	Con_Printf ("beam list overflow!\n");	
+}
+
+/*
+=================
+CL_ParseTEnt
+=================
+*/
+void CL_ParseTEnt (void)
+{
+	int		type;
+	vec3_t	pos;
+	dlight_t	*dl;
+	int		rnd;
+	explosion_t	*ex;
+	int		cnt;
+
+	type = MSG_ReadByte ();
+	switch (type)
+	{
+	case TE_WIZSPIKE:			// spike hitting wall
+		pos[0] = MSG_ReadCoord ();
+		pos[1] = MSG_ReadCoord ();
+		pos[2] = MSG_ReadCoord ();
+		R_RunParticleEffect (pos, vec3_origin, 20, 30);
+		S_StartSound (-1, 0, cl_sfx_wizhit, pos, 1, 1);
+		break;
+		
+	case TE_KNIGHTSPIKE:			// spike hitting wall
+		pos[0] = MSG_ReadCoord ();
+		pos[1] = MSG_ReadCoord ();
+		pos[2] = MSG_ReadCoord ();
+		R_RunParticleEffect (pos, vec3_origin, 226, 20);
+		S_StartSound (-1, 0, cl_sfx_knighthit, pos, 1, 1);
+		break;
+		
+	case TE_SPIKE:			// spike hitting wall
+		pos[0] = MSG_ReadCoord ();
+		pos[1] = MSG_ReadCoord ();
+		pos[2] = MSG_ReadCoord ();
+		R_RunParticleEffect (pos, vec3_origin, 0, 10);
+
+		if ( rand() % 5 )
+			S_StartSound (-1, 0, cl_sfx_tink1, pos, 1, 1);
+		else
+		{
+			rnd = rand() & 3;
+			if (rnd == 1)
+				S_StartSound (-1, 0, cl_sfx_ric1, pos, 1, 1);
+			else if (rnd == 2)
+				S_StartSound (-1, 0, cl_sfx_ric2, pos, 1, 1);
+			else
+				S_StartSound (-1, 0, cl_sfx_ric3, pos, 1, 1);
+		}
+		break;
+	case TE_SUPERSPIKE:			// super spike hitting wall
+		pos[0] = MSG_ReadCoord ();
+		pos[1] = MSG_ReadCoord ();
+		pos[2] = MSG_ReadCoord ();
+		R_RunParticleEffect (pos, vec3_origin, 0, 20);
+
+		if ( rand() % 5 )
+			S_StartSound (-1, 0, cl_sfx_tink1, pos, 1, 1);
+		else
+		{
+			rnd = rand() & 3;
+			if (rnd == 1)
+				S_StartSound (-1, 0, cl_sfx_ric1, pos, 1, 1);
+			else if (rnd == 2)
+				S_StartSound (-1, 0, cl_sfx_ric2, pos, 1, 1);
+			else
+				S_StartSound (-1, 0, cl_sfx_ric3, pos, 1, 1);
+		}
+		break;
+		
+	case TE_EXPLOSION:			// rocket explosion
+	// particles
+		pos[0] = MSG_ReadCoord ();
+		pos[1] = MSG_ReadCoord ();
+		pos[2] = MSG_ReadCoord ();
+		R_ParticleExplosion (pos);
+		
+	// light
+		dl = CL_AllocDlight (0);
+		VectorCopy (pos, dl->origin);
+		dl->radius = 350;
+		dl->die = cl.time + 0.5;
+		dl->decay = 300;
+		dl->color[0] = 0.2;
+		dl->color[1] = 0.1;
+		dl->color[2] = 0.05;
+		dl->color[3] = 0.7;
+	
+	// sound
+		S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
+	
+	// sprite
+		ex = CL_AllocExplosion ();
+		VectorCopy (pos, ex->origin);
+		ex->start = cl.time;
+		ex->model = Mod_ForName ("progs/s_explod.spr", true);
+		break;
+		
+	case TE_TAREXPLOSION:			// tarbaby explosion
+		pos[0] = MSG_ReadCoord ();
+		pos[1] = MSG_ReadCoord ();
+		pos[2] = MSG_ReadCoord ();
+		R_BlobExplosion (pos);
+
+		S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
+		break;
+
+	case TE_LIGHTNING1:				// lightning bolts
+		CL_ParseBeam (Mod_ForName("progs/bolt.mdl", true));
+		break;
+	
+	case TE_LIGHTNING2:				// lightning bolts
+		CL_ParseBeam (Mod_ForName("progs/bolt2.mdl", true));
+		break;
+	
+	case TE_LIGHTNING3:				// lightning bolts
+		CL_ParseBeam (Mod_ForName("progs/bolt3.mdl", true));
+		break;
+	
+	case TE_LAVASPLASH:	
+		pos[0] = MSG_ReadCoord ();
+		pos[1] = MSG_ReadCoord ();
+		pos[2] = MSG_ReadCoord ();
+		R_LavaSplash (pos);
+		break;
+	
+	case TE_TELEPORT:
+		pos[0] = MSG_ReadCoord ();
+		pos[1] = MSG_ReadCoord ();
+		pos[2] = MSG_ReadCoord ();
+		R_TeleportSplash (pos);
+		break;
+
+	case TE_GUNSHOT:			// bullet hitting wall
+		cnt = MSG_ReadByte ();
+		pos[0] = MSG_ReadCoord ();
+		pos[1] = MSG_ReadCoord ();
+		pos[2] = MSG_ReadCoord ();
+		R_RunParticleEffect (pos, vec3_origin, 0, 20*cnt);
+		break;
+		
+	case TE_BLOOD:				// bullets hitting body
+		cnt = MSG_ReadByte ();
+		pos[0] = MSG_ReadCoord ();
+		pos[1] = MSG_ReadCoord ();
+		pos[2] = MSG_ReadCoord ();
+		R_RunParticleEffect (pos, vec3_origin, 73, 20*cnt);
+		break;
+
+	case TE_LIGHTNINGBLOOD:		// lightning hitting body
+		pos[0] = MSG_ReadCoord ();
+		pos[1] = MSG_ReadCoord ();
+		pos[2] = MSG_ReadCoord ();
+		R_RunParticleEffect (pos, vec3_origin, 225, 50);
+		break;
+
+	default:
+		Sys_Error ("CL_ParseTEnt: bad type");
+	}
+}
+
+
+/*
+=================
+CL_NewTempEntity
+=================
+*/
+entity_t *CL_NewTempEntity (void)
+{
+	entity_t	*ent;
+
+	if (cl_numvisedicts == MAX_VISEDICTS)
+		return NULL;
+	ent = &cl_visedicts[cl_numvisedicts];
+	cl_numvisedicts++;
+	ent->keynum = 0;
+	
+	memset (ent, 0, sizeof(*ent));
+
+	ent->colormap = vid.colormap;
+	return ent;
+}
+
+
+/*
+=================
+CL_UpdateBeams
+=================
+*/
+void CL_UpdateBeams (void)
+{
+	int			i;
+	beam_t		*b;
+	vec3_t		dist, org;
+	float		d;
+	entity_t	*ent;
+	float		yaw, pitch;
+	float		forward;
+
+// update lightning
+	for (i=0, b=cl_beams ; i< MAX_BEAMS ; i++, b++)
+	{
+		if (!b->model || b->endtime < cl.time)
+			continue;
+
+	// if coming from the player, update the start position
+		if (b->entity == cl.playernum+1)	// entity 0 is the world
+		{
+			VectorCopy (cl.simorg, b->start);
+//			b->start[2] -= 22;	// adjust for view height
+		}
+
+	// calculate pitch and yaw
+		VectorSubtract (b->end, b->start, dist);
+
+		if (dist[1] == 0 && dist[0] == 0)
+		{
+			yaw = 0;
+			if (dist[2] > 0)
+				pitch = 90;
+			else
+				pitch = 270;
+		}
+		else
+		{
+			yaw = (int) (atan2(dist[1], dist[0]) * 180 / M_PI);
+			if (yaw < 0)
+				yaw += 360;
+	
+			forward = sqrt (dist[0]*dist[0] + dist[1]*dist[1]);
+			pitch = (int) (atan2(dist[2], forward) * 180 / M_PI);
+			if (pitch < 0)
+				pitch += 360;
+		}
+
+	// add new entities for the lightning
+		VectorCopy (b->start, org);
+		d = VectorNormalize(dist);
+		while (d > 0)
+		{
+			ent = CL_NewTempEntity ();
+			if (!ent)
+				return;
+			VectorCopy (org, ent->origin);
+			ent->model = b->model;
+			ent->angles[0] = pitch;
+			ent->angles[1] = yaw;
+			ent->angles[2] = rand()%360;
+
+			for (i=0 ; i<3 ; i++)
+				org[i] += dist[i]*30;
+			d -= 30;
+		}
+	}
+	
+}
+
+/*
+=================
+CL_UpdateExplosions
+=================
+*/
+void CL_UpdateExplosions (void)
+{
+	int			i;
+	int			f;
+	explosion_t	*ex;
+	entity_t	*ent;
+
+	for (i=0, ex=cl_explosions ; i< MAX_EXPLOSIONS ; i++, ex++)
+	{
+		if (!ex->model)
+			continue;
+		f = 10*(cl.time - ex->start);
+		if (f >= ex->model->numframes)
+		{
+			ex->model = NULL;
+			continue;
+		}
+
+		ent = CL_NewTempEntity ();
+		if (!ent)
+			return;
+		VectorCopy (ex->origin, ent->origin);
+		ent->model = ex->model;
+		ent->frame = f;
+	}
+}
+
+/*
+=================
+CL_UpdateTEnts
+=================
+*/
+void CL_UpdateTEnts (void)
+{
+	CL_UpdateBeams ();
+	CL_UpdateExplosions ();
+}
--- /dev/null
+++ b/QW/client/client.h
@@ -1,0 +1,515 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// client.h
+
+
+typedef struct
+{
+	char		name[16];
+	qboolean	failedload;		// the name isn't a valid skin
+	cache_user_t	cache;
+} skin_t;
+
+// player_state_t is the information needed by a player entity
+// to do move prediction and to generate a drawable entity
+typedef struct
+{
+	int			messagenum;		// all player's won't be updated each frame
+
+	double		state_time;		// not the same as the packet time,
+								// because player commands come asyncronously
+	usercmd_t	command;		// last command for prediction
+
+	vec3_t		origin;
+	vec3_t		viewangles;		// only for demos, not from server
+	vec3_t		velocity;
+	int			weaponframe;
+
+	int			modelindex;
+	int			frame;
+	int			skinnum;
+	int			effects;
+
+	int			flags;			// dead, gib, etc
+
+	float		waterjumptime;
+	int			onground;		// -1 = in air, else pmove entity number
+	int			oldbuttons;
+} player_state_t;
+
+
+#define	MAX_SCOREBOARDNAME	16
+typedef struct player_info_s
+{
+	int		userid;
+	char	userinfo[MAX_INFO_STRING];
+
+	// scoreboard information
+	char	name[MAX_SCOREBOARDNAME];
+	float	entertime;
+	int		frags;
+	int		ping;
+	byte	pl;
+
+	// skin information
+	int		topcolor;
+	int		bottomcolor;
+
+	int		_topcolor;
+	int		_bottomcolor;
+
+	int		spectator;
+	byte	translations[VID_GRADES*256];
+	skin_t	*skin;
+} player_info_t;
+
+
+typedef struct
+{
+	// generated on client side
+	usercmd_t	cmd;		// cmd that generated the frame
+	double		senttime;	// time cmd was sent off
+	int			delta_sequence;		// sequence number to delta from, -1 = full update
+
+	// received from server
+	double		receivedtime;	// time message was received, or -1
+	player_state_t	playerstate[MAX_CLIENTS];	// message received that reflects performing
+							// the usercmd
+	packet_entities_t	packet_entities;
+	qboolean	invalid;		// true if the packet_entities delta was invalid
+} frame_t;
+
+
+typedef struct
+{
+	int		destcolor[3];
+	int		percent;		// 0-256
+} cshift_t;
+
+#define	CSHIFT_CONTENTS	0
+#define	CSHIFT_DAMAGE	1
+#define	CSHIFT_BONUS	2
+#define	CSHIFT_POWERUP	3
+#define	NUM_CSHIFTS		4
+
+
+//
+// client_state_t should hold all pieces of the client state
+//
+#define	MAX_DLIGHTS		32
+typedef struct
+{
+	int		key;				// so entities can reuse same entry
+	vec3_t	origin;
+	float	radius;
+	float	die;				// stop lighting after this time
+	float	decay;				// drop this each second
+	float	minlight;			// don't add when contributing less
+	float   color[4];
+} dlight_t;
+
+typedef struct
+{
+	int		length;
+	char	map[MAX_STYLESTRING];
+} lightstyle_t;
+
+
+
+#define	MAX_EFRAGS		512
+
+#define	MAX_DEMOS		8
+#define	MAX_DEMONAME	16
+
+typedef enum {
+ca_disconnected, 	// full screen console with no connection
+ca_demostart,		// starting up a demo
+ca_connected,		// netchan_t established, waiting for svc_serverdata
+ca_onserver,		// processing data lists, donwloading, etc
+ca_active			// everything is in, so frames can be rendered
+} cactive_t;
+
+typedef enum {
+	dl_none,
+	dl_model,
+	dl_sound,
+	dl_skin,
+	dl_single
+} dltype_t;		// download type
+
+//
+// the client_static_t structure is persistant through an arbitrary number
+// of server connections
+//
+typedef struct
+{
+// connection information
+	cactive_t	state;
+	
+// network stuff
+	netchan_t	netchan;
+
+// private userinfo for sending to masterless servers
+	char		userinfo[MAX_INFO_STRING];
+
+	char		servername[MAX_OSPATH];	// name of server from original connect
+
+	int			qport;
+
+	FILE		*download;		// file transfer from server
+	char		downloadtempname[MAX_OSPATH];
+	char		downloadname[MAX_OSPATH];
+	int			downloadnumber;
+	dltype_t	downloadtype;
+	int			downloadpercent;
+
+// demo loop control
+	int			demonum;		// -1 = don't play demos
+	char		demos[MAX_DEMOS][MAX_DEMONAME];		// when not playing
+
+// demo recording info must be here, because record is started before
+// entering a map (and clearing client_state_t)
+	qboolean	demorecording;
+	qboolean	demoplayback;
+	qboolean	timedemo;
+	FILE		*demofile;
+	float		td_lastframe;		// to meter out one message a frame
+	int			td_startframe;		// host_framecount at start
+	float		td_starttime;		// realtime at second frame of timedemo
+
+	int			challenge;
+
+	float		latency;		// rolling average
+} client_static_t;
+
+extern client_static_t	cls;
+
+//
+// the client_state_t structure is wiped completely at every
+// server signon
+//
+typedef struct
+{
+	int			servercount;	// server identification for prespawns
+
+	char		serverinfo[MAX_SERVERINFO_STRING];
+
+	int			parsecount;		// server message counter
+	int			validsequence;	// this is the sequence number of the last good
+								// packetentity_t we got.  If this is 0, we can't
+								// render a frame yet
+	int			movemessages;	// since connecting to this server
+								// throw out the first couple, so the player
+								// doesn't accidentally do something the 
+								// first frame
+
+	int			spectator;
+
+	double		last_ping_request;	// while showing scoreboard
+	double		last_servermessage;
+
+// sentcmds[cl.netchan.outgoing_sequence & UPDATE_MASK] = cmd
+	frame_t		frames[UPDATE_BACKUP];
+
+// information for local display
+	int			stats[MAX_CL_STATS];	// health, etc
+	float		item_gettime[32];	// cl.time of aquiring item, for blinking
+	float		faceanimtime;		// use anim frame if cl.time < this
+
+	cshift_t	cshifts[NUM_CSHIFTS];	// color shifts for damage, powerups
+	cshift_t	prev_cshifts[NUM_CSHIFTS];	// and content types
+
+// the client maintains its own idea of view angles, which are
+// sent to the server each frame.  And only reset at level change
+// and teleport times
+	vec3_t		viewangles;
+
+// the client simulates or interpolates movement to get these values
+	double		time;			// this is the time value that the client
+								// is rendering at.  allways <= realtime
+	vec3_t		simorg;
+	vec3_t		simvel;
+	vec3_t		simangles;
+
+// pitch drifting vars
+	float		pitchvel;
+	qboolean	nodrift;
+	float		driftmove;
+	double		laststop;
+
+
+	float		crouch;			// local amount for smoothing stepups
+
+	qboolean	paused;			// send over by server
+
+	float		punchangle;		// temporar yview kick from weapon firing
+	
+	int			intermission;	// don't change view angle, full screen, etc
+	int			completed_time;	// latched ffrom time at intermission start
+	
+//
+// information that is static for the entire time connected to a server
+//
+	char		model_name[MAX_MODELS][MAX_QPATH];
+	char		sound_name[MAX_SOUNDS][MAX_QPATH];
+
+	struct model_s		*model_precache[MAX_MODELS];
+	struct sfx_s		*sound_precache[MAX_SOUNDS];
+
+	char		levelname[40];	// for display on solo scoreboard
+	int			playernum;
+
+// refresh related state
+	struct model_s	*worldmodel;	// cl_entitites[0].model
+	struct efrag_s	*free_efrags;
+	int			num_entities;	// stored bottom up in cl_entities array
+	int			num_statics;	// stored top down in cl_entitiers
+
+	int			cdtrack;		// cd audio
+
+	entity_t	viewent;		// weapon model
+
+// all player information
+	player_info_t	players[MAX_CLIENTS];
+} client_state_t;
+
+
+//
+// cvars
+//
+extern  cvar_t	cl_warncmd;
+extern	cvar_t	cl_upspeed;
+extern	cvar_t	cl_forwardspeed;
+extern	cvar_t	cl_backspeed;
+extern	cvar_t	cl_sidespeed;
+
+extern	cvar_t	cl_movespeedkey;
+
+extern	cvar_t	cl_yawspeed;
+extern	cvar_t	cl_pitchspeed;
+
+extern	cvar_t	cl_anglespeedkey;
+
+extern	cvar_t	cl_shownet;
+extern	cvar_t	cl_sbar;
+extern	cvar_t	cl_hudswap;
+
+extern	cvar_t	cl_pitchdriftspeed;
+extern	cvar_t	lookspring;
+extern	cvar_t	lookstrafe;
+extern	cvar_t	sensitivity;
+
+extern	cvar_t	m_pitch;
+extern	cvar_t	m_yaw;
+extern	cvar_t	m_forward;
+extern	cvar_t	m_side;
+
+extern cvar_t		_windowed_mouse;
+
+extern	cvar_t	name;
+
+
+#define	MAX_STATIC_ENTITIES	128			// torches, etc
+
+extern	client_state_t	cl;
+
+// FIXME, allocate dynamically
+extern	entity_state_t	cl_baselines[MAX_EDICTS];
+extern	efrag_t			cl_efrags[MAX_EFRAGS];
+extern	entity_t		cl_static_entities[MAX_STATIC_ENTITIES];
+extern	lightstyle_t	cl_lightstyle[MAX_LIGHTSTYLES];
+extern	dlight_t		cl_dlights[MAX_DLIGHTS];
+
+extern	qboolean	nomaster;
+extern float	server_version;	// version of server we connected to
+
+//=============================================================================
+
+
+//
+// cl_main
+//
+dlight_t *CL_AllocDlight (int key);
+void	CL_DecayLights (void);
+
+void CL_Init (void);
+void Host_WriteConfiguration (void);
+
+void CL_EstablishConnection (char *host);
+
+void CL_Disconnect (void);
+void CL_Disconnect_f (void);
+void CL_NextDemo (void);
+qboolean CL_DemoBehind(void);
+
+void CL_BeginServerConnect(void);
+
+#define			MAX_VISEDICTS	256
+extern	int				cl_numvisedicts, cl_oldnumvisedicts;
+extern	entity_t		*cl_visedicts, *cl_oldvisedicts;
+extern	entity_t		cl_visedicts_list[2][MAX_VISEDICTS];
+
+extern char emodel_name[], pmodel_name[], prespawn_name[], modellist_name[], soundlist_name[];
+
+//
+// cl_input
+//
+typedef struct
+{
+	int		down[2];		// key nums holding it down
+	int		state;			// low bit is down state
+} kbutton_t;
+
+extern	kbutton_t	in_mlook, in_klook;
+extern 	kbutton_t 	in_strafe;
+extern 	kbutton_t 	in_speed;
+
+void CL_InitInput (void);
+void CL_SendCmd (void);
+void CL_SendMove (usercmd_t *cmd);
+
+void CL_ParseTEnt (void);
+void CL_UpdateTEnts (void);
+
+void CL_ClearState (void);
+
+void CL_ReadPackets (void);
+
+int  CL_ReadFromServer (void);
+void CL_WriteToServer (usercmd_t *cmd);
+void CL_BaseMove (usercmd_t *cmd);
+
+
+float CL_KeyState (kbutton_t *key);
+char *Key_KeynumToString (int keynum);
+
+//
+// cl_demo.c
+//
+void CL_StopPlayback (void);
+qboolean CL_GetMessage (void);
+void CL_WriteDemoCmd (usercmd_t *pcmd);
+
+void CL_Stop_f (void);
+void CL_Record_f (void);
+void CL_ReRecord_f (void);
+void CL_PlayDemo_f (void);
+void CL_TimeDemo_f (void);
+
+//
+// cl_parse.c
+//
+#define NET_TIMINGS 256
+#define NET_TIMINGSMASK 255
+extern int	packet_latency[NET_TIMINGS];
+int CL_CalcNet (void);
+void CL_ParseServerMessage (void);
+void CL_NewTranslation (int slot);
+qboolean	CL_CheckOrDownloadFile (char *filename);
+qboolean CL_IsUploading(void);
+void CL_NextUpload(void);
+void CL_StartUpload (byte *data, int size);
+void CL_StopUpload(void);
+
+//
+// view.c
+//
+void V_StartPitchDrift (void);
+void V_StopPitchDrift (void);
+
+void V_RenderView (void);
+void V_UpdatePalette (void);
+void V_Register (void);
+void V_ParseDamage (void);
+void V_SetContentsColor (int contents);
+void V_CalcBlend (void);
+
+
+//
+// cl_tent
+//
+void CL_InitTEnts (void);
+void CL_ClearTEnts (void);
+
+//
+// cl_ents.c
+//
+void CL_SetSolidPlayers (int playernum);
+void CL_SetUpPlayerPrediction(qboolean dopred);
+void CL_EmitEntities (void);
+void CL_ClearProjectiles (void);
+void CL_ParseProjectiles (void);
+void CL_ParsePacketEntities (qboolean delta);
+void CL_SetSolidEntities (void);
+void CL_ParsePlayerinfo (void);
+
+//
+// cl_pred.c
+//
+void CL_InitPrediction (void);
+void CL_PredictMove (void);
+void CL_PredictUsercmd (player_state_t *from, player_state_t *to, usercmd_t *u, qboolean spectator);
+
+//
+// cl_cam.c
+//
+#define CAM_NONE	0
+#define CAM_TRACK	1
+
+extern	int		autocam;
+extern int spec_track; // player# of who we are tracking
+
+qboolean Cam_DrawViewModel(void);
+qboolean Cam_DrawPlayer(int playernum);
+void Cam_Track(usercmd_t *cmd);
+void Cam_FinishMove(usercmd_t *cmd);
+void Cam_Reset(void);
+void CL_InitCam(void);
+
+//
+// skin.c
+//
+
+typedef struct
+{
+    char	manufacturer;
+    char	version;
+    char	encoding;
+    char	bits_per_pixel;
+    unsigned short	xmin,ymin,xmax,ymax;
+    unsigned short	hres,vres;
+    unsigned char	palette[48];
+    char	reserved;
+    char	color_planes;
+    unsigned short	bytes_per_line;
+    unsigned short	palette_type;
+    char	filler[58];
+    unsigned char	data;			// unbounded
+} pcx_t;
+
+
+void	Skin_Find (player_info_t *sc);
+byte	*Skin_Cache (skin_t *skin);
+void	Skin_Skins_f (void);
+void	Skin_AllSkins_f (void);
+void	Skin_NextDownload (void);
+
+#define RSSHOT_WIDTH 320
+#define RSSHOT_HEIGHT 200
--- /dev/null
+++ b/QW/client/cmd.c
@@ -1,0 +1,748 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// cmd.c -- Quake script command processing module
+
+#include "quakedef.h"
+
+void Cmd_ForwardToServer (void);
+
+#define	MAX_ALIAS_NAME	32
+
+typedef struct cmdalias_s
+{
+	struct cmdalias_s	*next;
+	char	name[MAX_ALIAS_NAME];
+	char	*value;
+} cmdalias_t;
+
+cmdalias_t	*cmd_alias;
+
+qboolean	cmd_wait;
+
+cvar_t cl_warncmd = {"cl_warncmd", "0"};
+
+//=============================================================================
+
+/*
+============
+Cmd_Wait_f
+
+Causes execution of the remainder of the command buffer to be delayed until
+next frame.  This allows commands like:
+bind g "impulse 5 ; +attack ; wait ; -attack ; impulse 2"
+============
+*/
+void Cmd_Wait_f (void)
+{
+	cmd_wait = true;
+}
+
+/*
+=============================================================================
+
+						COMMAND BUFFER
+
+=============================================================================
+*/
+
+sizebuf_t	cmd_text;
+byte		cmd_text_buf[8192];
+
+/*
+============
+Cbuf_Init
+============
+*/
+void Cbuf_Init (void)
+{
+	cmd_text.data = cmd_text_buf;
+	cmd_text.maxsize = sizeof(cmd_text_buf);
+}
+
+/*
+============
+Cbuf_AddText
+
+Adds command text at the end of the buffer
+============
+*/
+void Cbuf_AddText (char *text)
+{
+	int		l;
+	
+	l = Q_strlen (text);
+
+	if (cmd_text.cursize + l >= cmd_text.maxsize)
+	{
+		Con_Printf ("Cbuf_AddText: overflow\n");
+		return;
+	}
+	SZ_Write (&cmd_text, text, Q_strlen (text));
+}
+
+
+/*
+============
+Cbuf_InsertText
+
+Adds command text immediately after the current command
+Adds a \n to the text
+FIXME: actually change the command buffer to do less copying
+============
+*/
+void Cbuf_InsertText (char *text)
+{
+	char	*temp;
+	int		templen;
+
+// copy off any commands still remaining in the exec buffer
+	templen = cmd_text.cursize;
+	if (templen)
+	{
+		temp = Z_Malloc (templen);
+		Q_memcpy (temp, cmd_text.data, templen);
+		SZ_Clear (&cmd_text);
+	}
+	else
+		temp = NULL;	// shut up compiler
+		
+// add the entire text of the file
+	Cbuf_AddText (text);
+	SZ_Write (&cmd_text, "\n", 1);
+// add the copied off data
+	if (templen)
+	{
+		SZ_Write (&cmd_text, temp, templen);
+		Z_Free (temp);
+	}
+}
+
+/*
+============
+Cbuf_Execute
+============
+*/
+void Cbuf_Execute (void)
+{
+	int		i;
+	char	*text;
+	char	line[1024];
+	int		quotes;
+	
+	while (cmd_text.cursize)
+	{
+// find a \n or ; line break
+		text = (char *)cmd_text.data;
+
+		quotes = 0;
+		for (i=0 ; i< cmd_text.cursize ; i++)
+		{
+			if (text[i] == '"')
+				quotes++;
+			if ( !(quotes&1) &&  text[i] == ';')
+				break;	// don't break if inside a quoted string
+			if (text[i] == '\n')
+				break;
+		}
+			
+				
+		memcpy (line, text, i);
+		line[i] = 0;
+		
+// delete the text from the command buffer and move remaining commands down
+// this is necessary because commands (exec, alias) can insert data at the
+// beginning of the text buffer
+
+		if (i == cmd_text.cursize)
+			cmd_text.cursize = 0;
+		else
+		{
+			i++;
+			cmd_text.cursize -= i;
+			Q_memcpy (text, text+i, cmd_text.cursize);
+		}
+
+// execute the command line
+		Cmd_ExecuteString (line);
+		
+		if (cmd_wait)
+		{	// skip out while text still remains in buffer, leaving it
+			// for next frame
+			cmd_wait = false;
+			break;
+		}
+	}
+}
+
+/*
+==============================================================================
+
+						SCRIPT COMMANDS
+
+==============================================================================
+*/
+
+/*
+===============
+Cmd_StuffCmds_f
+
+Adds command line parameters as script statements
+Commands lead with a +, and continue until a - or another +
+quake +prog jctest.qp +cmd amlev1
+quake -nosound +cmd amlev1
+===============
+*/
+void Cmd_StuffCmds_f (void)
+{
+	int		i, j;
+	int		s;
+	char	*text, *build, c;
+		
+// build the combined string to parse from
+	s = 0;
+	for (i=1 ; i<com_argc ; i++)
+	{
+		if (!com_argv[i])
+			continue;		// NEXTSTEP nulls out -NXHost
+		s += Q_strlen (com_argv[i]) + 1;
+	}
+	if (!s)
+		return;
+		
+	text = Z_Malloc (s+1);
+	text[0] = 0;
+	for (i=1 ; i<com_argc ; i++)
+	{
+		if (!com_argv[i])
+			continue;		// NEXTSTEP nulls out -NXHost
+		Q_strcat (text,com_argv[i]);
+		if (i != com_argc-1)
+			Q_strcat (text, " ");
+	}
+	
+// pull out the commands
+	build = Z_Malloc (s+1);
+	build[0] = 0;
+	
+	for (i=0 ; i<s-1 ; i++)
+	{
+		if (text[i] == '+')
+		{
+			i++;
+
+			for (j=i ; (text[j] != '+') && (text[j] != '-') && (text[j] != 0) ; j++)
+				;
+
+			c = text[j];
+			text[j] = 0;
+			
+			Q_strcat (build, text+i);
+			Q_strcat (build, "\n");
+			text[j] = c;
+			i = j-1;
+		}
+	}
+	
+	if (build[0])
+		Cbuf_InsertText (build);
+	
+	Z_Free (text);
+	Z_Free (build);
+}
+
+
+/*
+===============
+Cmd_Exec_f
+===============
+*/
+void Cmd_Exec_f (void)
+{
+	char	*f;
+	int		mark;
+
+	if (Cmd_Argc () != 2)
+	{
+		Con_Printf ("exec <filename> : execute a script file\n");
+		return;
+	}
+
+	// FIXME: is this safe freeing the hunk here???
+	mark = Hunk_LowMark ();
+	f = (char *)COM_LoadHunkFile (Cmd_Argv(1));
+	if (!f)
+	{
+		Con_Printf ("couldn't exec %s\n",Cmd_Argv(1));
+		return;
+	}
+	if (!Cvar_Command () && (cl_warncmd.value || developer.value))
+		Con_Printf ("execing %s\n",Cmd_Argv(1));
+	
+	Cbuf_InsertText (f);
+	Hunk_FreeToLowMark (mark);
+}
+
+
+/*
+===============
+Cmd_Echo_f
+
+Just prints the rest of the line to the console
+===============
+*/
+void Cmd_Echo_f (void)
+{
+	int		i;
+	
+	for (i=1 ; i<Cmd_Argc() ; i++)
+		Con_Printf ("%s ",Cmd_Argv(i));
+	Con_Printf ("\n");
+}
+
+/*
+===============
+Cmd_Alias_f
+
+Creates a new command that executes a command string (possibly ; seperated)
+===============
+*/
+
+char *CopyString (char *in)
+{
+	char	*out;
+	
+	out = Z_Malloc (strlen(in)+1);
+	strcpy (out, in);
+	return out;
+}
+
+void Cmd_Alias_f (void)
+{
+	cmdalias_t	*a;
+	char		cmd[1024];
+	int			i, c;
+	char		*s;
+
+	if (Cmd_Argc() == 1)
+	{
+		Con_Printf ("Current alias commands:\n");
+		for (a = cmd_alias ; a ; a=a->next)
+			Con_Printf ("%s : %s\n", a->name, a->value);
+		return;
+	}
+
+	s = Cmd_Argv(1);
+	if (strlen(s) >= MAX_ALIAS_NAME)
+	{
+		Con_Printf ("Alias name is too long\n");
+		return;
+	}
+
+	// if the alias allready exists, reuse it
+	for (a = cmd_alias ; a ; a=a->next)
+	{
+		if (!strcmp(s, a->name))
+		{
+			Z_Free (a->value);
+			break;
+		}
+	}
+
+	if (!a)
+	{
+		a = Z_Malloc (sizeof(cmdalias_t));
+		a->next = cmd_alias;
+		cmd_alias = a;
+	}
+	strcpy (a->name, s);	
+
+// copy the rest of the command line
+	cmd[0] = 0;		// start out with a null string
+	c = Cmd_Argc();
+	for (i=2 ; i< c ; i++)
+	{
+		strcat (cmd, Cmd_Argv(i));
+		if (i != c)
+			strcat (cmd, " ");
+	}
+	strcat (cmd, "\n");
+	
+	a->value = CopyString (cmd);
+}
+
+/*
+=============================================================================
+
+					COMMAND EXECUTION
+
+=============================================================================
+*/
+
+typedef struct cmd_function_s
+{
+	struct cmd_function_s	*next;
+	char					*name;
+	xcommand_t				function;
+} cmd_function_t;
+
+
+#define	MAX_ARGS		80
+
+static	int			cmd_argc;
+static	char		*cmd_argv[MAX_ARGS];
+static	char		*cmd_null_string = "";
+static	char		*cmd_args = NULL;
+
+
+
+static	cmd_function_t	*cmd_functions;		// possible commands to execute
+
+/*
+============
+Cmd_Argc
+============
+*/
+int		Cmd_Argc (void)
+{
+	return cmd_argc;
+}
+
+/*
+============
+Cmd_Argv
+============
+*/
+char	*Cmd_Argv (int arg)
+{
+	if ( arg >= cmd_argc )
+		return cmd_null_string;
+	return cmd_argv[arg];	
+}
+
+/*
+============
+Cmd_Args
+
+Returns a single string containing argv(1) to argv(argc()-1)
+============
+*/
+char		*Cmd_Args (void)
+{
+	if (!cmd_args)
+		return "";
+	return cmd_args;
+}
+
+
+/*
+============
+Cmd_TokenizeString
+
+Parses the given string into command line tokens.
+============
+*/
+void Cmd_TokenizeString (char *text)
+{
+	int		i;
+	
+// clear the args from the last string
+	for (i=0 ; i<cmd_argc ; i++)
+		Z_Free (cmd_argv[i]);
+		
+	cmd_argc = 0;
+	cmd_args = NULL;
+	
+	while (1)
+	{
+// skip whitespace up to a /n
+		while (*text && *text <= ' ' && *text != '\n')
+		{
+			text++;
+		}
+		
+		if (*text == '\n')
+		{	// a newline seperates commands in the buffer
+			text++;
+			break;
+		}
+
+		if (!*text)
+			return;
+	
+		if (cmd_argc == 1)
+			 cmd_args = text;
+			
+		text = COM_Parse (text);
+		if (!text)
+			return;
+
+		if (cmd_argc < MAX_ARGS)
+		{
+			cmd_argv[cmd_argc] = Z_Malloc (Q_strlen(com_token)+1);
+			Q_strcpy (cmd_argv[cmd_argc], com_token);
+			cmd_argc++;
+		}
+	}
+	
+}
+
+
+/*
+============
+Cmd_AddCommand
+============
+*/
+void	Cmd_AddCommand (char *cmd_name, xcommand_t function)
+{
+	cmd_function_t	*cmd;
+	
+	if (host_initialized)	// because hunk allocation would get stomped
+		Sys_Error ("Cmd_AddCommand after host_initialized");
+		
+// fail if the command is a variable name
+	if (Cvar_VariableString(cmd_name)[0])
+	{
+		Con_Printf ("Cmd_AddCommand: %s already defined as a var\n", cmd_name);
+		return;
+	}
+	
+// fail if the command already exists
+	for (cmd=cmd_functions ; cmd ; cmd=cmd->next)
+	{
+		if (!Q_strcmp (cmd_name, cmd->name))
+		{
+			Con_Printf ("Cmd_AddCommand: %s already defined\n", cmd_name);
+			return;
+		}
+	}
+
+	cmd = Hunk_Alloc (sizeof(cmd_function_t));
+	cmd->name = cmd_name;
+	cmd->function = function;
+	cmd->next = cmd_functions;
+	cmd_functions = cmd;
+}
+
+/*
+============
+Cmd_Exists
+============
+*/
+qboolean	Cmd_Exists (char *cmd_name)
+{
+	cmd_function_t	*cmd;
+
+	for (cmd=cmd_functions ; cmd ; cmd=cmd->next)
+	{
+		if (!Q_strcmp (cmd_name,cmd->name))
+			return true;
+	}
+
+	return false;
+}
+
+
+
+/*
+============
+Cmd_CompleteCommand
+============
+*/
+char *Cmd_CompleteCommand (char *partial)
+{
+	cmd_function_t	*cmd;
+	int				len;
+	cmdalias_t		*a;
+	
+	len = Q_strlen(partial);
+	
+	if (!len)
+		return NULL;
+		
+// check for exact match
+	for (cmd=cmd_functions ; cmd ; cmd=cmd->next)
+		if (!strcmp (partial,cmd->name))
+			return cmd->name;
+	for (a=cmd_alias ; a ; a=a->next)
+		if (!strcmp (partial, a->name))
+			return a->name;
+
+// check for partial match
+	for (cmd=cmd_functions ; cmd ; cmd=cmd->next)
+		if (!strncmp (partial,cmd->name, len))
+			return cmd->name;
+	for (a=cmd_alias ; a ; a=a->next)
+		if (!strncmp (partial, a->name, len))
+			return a->name;
+
+	return NULL;
+}
+
+#ifndef SERVERONLY		// FIXME
+/*
+===================
+Cmd_ForwardToServer
+
+adds the current command line as a clc_stringcmd to the client message.
+things like godmode, noclip, etc, are commands directed to the server,
+so when they are typed in at the console, they will need to be forwarded.
+===================
+*/
+void Cmd_ForwardToServer (void)
+{
+	if (cls.state == ca_disconnected)
+	{
+		Con_Printf ("Can't \"%s\", not connected\n", Cmd_Argv(0));
+		return;
+	}
+	
+	if (cls.demoplayback)
+		return;		// not really connected
+
+	MSG_WriteByte (&cls.netchan.message, clc_stringcmd);
+	SZ_Print (&cls.netchan.message, Cmd_Argv(0));
+	if (Cmd_Argc() > 1)
+	{
+		SZ_Print (&cls.netchan.message, " ");
+		SZ_Print (&cls.netchan.message, Cmd_Args());
+	}
+}
+
+// don't forward the first argument
+void Cmd_ForwardToServer_f (void)
+{
+	if (cls.state == ca_disconnected)
+	{
+		Con_Printf ("Can't \"%s\", not connected\n", Cmd_Argv(0));
+		return;
+	}
+
+	if (Q_strcasecmp(Cmd_Argv(1), "snap") == 0) {
+		Cbuf_InsertText ("snap\n");
+		return;
+	}
+	
+	if (cls.demoplayback)
+		return;		// not really connected
+
+	if (Cmd_Argc() > 1)
+	{
+		MSG_WriteByte (&cls.netchan.message, clc_stringcmd);
+		SZ_Print (&cls.netchan.message, Cmd_Args());
+	}
+}
+#else
+void Cmd_ForwardToServer (void)
+{
+}
+#endif
+
+/*
+============
+Cmd_ExecuteString
+
+A complete command line has been parsed, so try to execute it
+FIXME: lookupnoadd the token to speed search?
+============
+*/
+void	Cmd_ExecuteString (char *text)
+{	
+	cmd_function_t	*cmd;
+	cmdalias_t		*a;
+
+	Cmd_TokenizeString (text);
+			
+// execute the command line
+	if (!Cmd_Argc())
+		return;		// no tokens
+
+// check functions
+	for (cmd=cmd_functions ; cmd ; cmd=cmd->next)
+	{
+		if (!Q_strcasecmp (cmd_argv[0],cmd->name))
+		{
+			if (!cmd->function)
+				Cmd_ForwardToServer ();
+			else
+				cmd->function ();
+			return;
+		}
+	}
+
+// check alias
+	for (a=cmd_alias ; a ; a=a->next)
+	{
+		if (!Q_strcasecmp (cmd_argv[0], a->name))
+		{
+			Cbuf_InsertText (a->value);
+			return;
+		}
+	}
+	
+// check cvars
+	if (!Cvar_Command () && (cl_warncmd.value || developer.value))
+		Con_Printf ("Unknown command \"%s\"\n", Cmd_Argv(0));
+	
+}
+
+
+
+/*
+================
+Cmd_CheckParm
+
+Returns the position (1 to argc-1) in the command's argument list
+where the given parameter apears, or 0 if not present
+================
+*/
+int Cmd_CheckParm (char *parm)
+{
+	int i;
+	
+	if (!parm)
+		Sys_Error ("Cmd_CheckParm: NULL");
+
+	for (i = 1; i < Cmd_Argc (); i++)
+		if (! Q_strcasecmp (parm, Cmd_Argv (i)))
+			return i;
+			
+	return 0;
+}
+
+/*
+============
+Cmd_Init
+============
+*/
+void Cmd_Init (void)
+{
+//
+// register our commands
+//
+	Cmd_AddCommand ("stuffcmds",Cmd_StuffCmds_f);
+	Cmd_AddCommand ("exec",Cmd_Exec_f);
+	Cmd_AddCommand ("echo",Cmd_Echo_f);
+	Cmd_AddCommand ("alias",Cmd_Alias_f);
+	Cmd_AddCommand ("wait", Cmd_Wait_f);
+#ifndef SERVERONLY
+	Cmd_AddCommand ("cmd", Cmd_ForwardToServer_f);
+#endif
+}
+
--- /dev/null
+++ b/QW/client/cmd.h
@@ -1,0 +1,107 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+
+// cmd.h -- Command buffer and command execution
+
+//===========================================================================
+
+/*
+
+Any number of commands can be added in a frame, from several different sources.
+Most commands come from either keybindings or console line input, but remote
+servers can also send across commands and entire text files can be execed.
+
+The + command line options are also added to the command buffer.
+
+The game starts with a Cbuf_AddText ("exec quake.rc\n"); Cbuf_Execute ();
+
+*/
+
+
+void Cbuf_Init (void);
+// allocates an initial text buffer that will grow as needed
+
+void Cbuf_AddText (char *text);
+// as new commands are generated from the console or keybindings,
+// the text is added to the end of the command buffer.
+
+void Cbuf_InsertText (char *text);
+// when a command wants to issue other commands immediately, the text is
+// inserted at the beginning of the buffer, before any remaining unexecuted
+// commands.
+
+void Cbuf_Execute (void);
+// Pulls off \n terminated lines of text from the command buffer and sends
+// them through Cmd_ExecuteString.  Stops when the buffer is empty.
+// Normally called once per frame, but may be explicitly invoked.
+// Do not call inside a command function!
+
+//===========================================================================
+
+/*
+
+Command execution takes a null terminated string, breaks it into tokens,
+then searches for a command or variable that matches the first token.
+
+*/
+
+typedef void (*xcommand_t) (void);
+
+void	Cmd_Init (void);
+
+void	Cmd_AddCommand (char *cmd_name, xcommand_t function);
+// called by the init functions of other parts of the program to
+// register commands and functions to call for them.
+// The cmd_name is referenced later, so it should not be in temp memory
+// if function is NULL, the command will be forwarded to the server
+// as a clc_stringcmd instead of executed locally
+
+qboolean Cmd_Exists (char *cmd_name);
+// used by the cvar code to check for cvar / command name overlap
+
+char 	*Cmd_CompleteCommand (char *partial);
+// attempts to match a partial command for automatic command line completion
+// returns NULL if nothing fits
+
+int		Cmd_Argc (void);
+char	*Cmd_Argv (int arg);
+char	*Cmd_Args (void);
+// The functions that execute commands get their parameters with these
+// functions. Cmd_Argv () will return an empty string, not a NULL
+// if arg > argc, so string operations are allways safe.
+
+int Cmd_CheckParm (char *parm);
+// Returns the position (1 to argc-1) in the command's argument list
+// where the given parameter apears, or 0 if not present
+
+void Cmd_TokenizeString (char *text);
+// Takes a null terminated string.  Does not need to be /n terminated.
+// breaks the string up into arg tokens.
+
+void	Cmd_ExecuteString (char *text);
+// Parses a single line of text into arguments and tries to execute it
+// as if it was typed at the console
+
+void	Cmd_ForwardToServer (void);
+// adds the current command line as a clc_stringcmd to the client message.
+// things like godmode, noclip, etc, are commands directed to the server,
+// so when they are typed in at the console, they will need to be forwarded.
+
+void Cmd_StuffCmds_f (void);
--- /dev/null
+++ b/QW/client/common.c
@@ -1,0 +1,2299 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// common.c -- misc functions used in client and server
+
+#include <ctype.h>
+
+#ifdef SERVERONLY 
+#include "qwsvdef.h"
+#else
+#include "quakedef.h"
+#endif
+
+#define MAX_NUM_ARGVS	50
+#define NUM_SAFE_ARGVS	6
+
+usercmd_t nullcmd; // guarenteed to be zero
+
+static char	*largv[MAX_NUM_ARGVS + NUM_SAFE_ARGVS + 1];
+static char	*argvdummy = " ";
+
+static char	*safeargvs[NUM_SAFE_ARGVS] =
+	{"-stdvid", "-nolan", "-nosound", "-nocdaudio", "-nojoy", "-nomouse"};
+
+cvar_t	registered = {"registered","0"};
+
+qboolean	com_modified;	// set true if using non-id files
+
+int		static_registered = 1;	// only for startup check, then set
+
+qboolean		msg_suppress_1 = 0;
+
+void COM_InitFilesystem (void);
+void COM_Path_f (void);
+
+
+// if a packfile directory differs from this, it is assumed to be hacked
+#define	PAK0_COUNT		339
+#define	PAK0_CRC		52883
+
+qboolean		standard_quake = true, rogue, hipnotic;
+
+char	gamedirfile[MAX_OSPATH];
+
+// this graphic needs to be in the pak file to use registered features
+unsigned short 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
+};
+
+/*
+
+
+All of Quake's data access is through a hierchal file system, but the contents of the file system can be transparently merged from several sources.
+
+The "base directory" is the path to the directory holding the quake.exe and all game directories.  The sys_* files pass this to host_init in quakeparms_t->basedir.  This can be overridden with the "-basedir" command line parm to allow code debugging in a different directory.  The base directory is
+only used during filesystem initialization.
+
+The "game directory" is the first tree on the search path and directory that all generated files (savegames, screenshots, demos, config files) will be saved to.  This can be overridden with the "-game" command line parameter.  The game directory can never be changed while quake is executing.  This is a precacution against having a malicious server instruct clients to write files over areas they shouldn't.
+
+The "cache directory" is only used during development to save network bandwidth, especially over ISDN / T1 lines.  If there is a cache directory
+specified, when a file is found by the normal search path, it will be mirrored
+into the cache directory, then opened there.
+	
+*/
+
+//============================================================================
+
+
+// ClearLink is used for new headnodes
+void ClearLink (link_t *l)
+{
+	l->prev = l->next = l;
+}
+
+void RemoveLink (link_t *l)
+{
+	l->next->prev = l->prev;
+	l->prev->next = l->next;
+}
+
+void InsertLinkBefore (link_t *l, link_t *before)
+{
+	l->next = before;
+	l->prev = before->prev;
+	l->prev->next = l;
+	l->next->prev = l;
+}
+void InsertLinkAfter (link_t *l, link_t *after)
+{
+	l->next = after->next;
+	l->prev = after;
+	l->prev->next = l;
+	l->next->prev = l;
+}
+
+/*
+============================================================================
+
+					LIBRARY REPLACEMENT FUNCTIONS
+
+============================================================================
+*/
+
+#if 0
+void Q_memset (void *dest, int fill, int count)
+{
+	int		i;
+	
+	if ( (((long)dest | count) & 3) == 0)
+	{
+		count >>= 2;
+		fill = fill | (fill<<8) | (fill<<16) | (fill<<24);
+		for (i=0 ; i<count ; i++)
+			((int *)dest)[i] = fill;
+	}
+	else
+		for (i=0 ; i<count ; i++)
+			((byte *)dest)[i] = fill;
+}
+
+void Q_memcpy (void *dest, void *src, int count)
+{
+	int		i;
+	
+	if (( ( (long)dest | (long)src | count) & 3) == 0 )
+	{
+		count>>=2;
+		for (i=0 ; i<count ; i++)
+			((int *)dest)[i] = ((int *)src)[i];
+	}
+	else
+		for (i=0 ; i<count ; i++)
+			((byte *)dest)[i] = ((byte *)src)[i];
+}
+
+int Q_memcmp (void *m1, void *m2, int count)
+{
+	while(count)
+	{
+		count--;
+		if (((byte *)m1)[count] != ((byte *)m2)[count])
+			return -1;
+	}
+	return 0;
+}
+
+void Q_strcpy (char *dest, char *src)
+{
+	while (*src)
+	{
+		*dest++ = *src++;
+	}
+	*dest++ = 0;
+}
+
+void Q_strncpy (char *dest, char *src, int count)
+{
+	while (*src && count--)
+	{
+		*dest++ = *src++;
+	}
+	if (count)
+		*dest++ = 0;
+}
+
+int Q_strlen (char *str)
+{
+	int		count;
+	
+	count = 0;
+	while (str[count])
+		count++;
+
+	return count;
+}
+
+char *Q_strrchr(char *s, char c)
+{
+    int len = Q_strlen(s);
+    s += len;
+    while (len--)
+        if (*--s == c) return s;
+    return 0;
+}
+
+void Q_strcat (char *dest, char *src)
+{
+	dest += Q_strlen(dest);
+	Q_strcpy (dest, src);
+}
+
+int Q_strcmp (char *s1, char *s2)
+{
+	while (1)
+	{
+		if (*s1 != *s2)
+			return -1;		// strings not equal	
+		if (!*s1)
+			return 0;		// strings are equal
+		s1++;
+		s2++;
+	}
+	
+	return -1;
+}
+
+int Q_strncmp (char *s1, char *s2, int count)
+{
+	while (1)
+	{
+		if (!count--)
+			return 0;
+		if (*s1 != *s2)
+			return -1;		// strings not equal	
+		if (!*s1)
+			return 0;		// strings are equal
+		s1++;
+		s2++;
+	}
+	
+	return -1;
+}
+
+int Q_strncasecmp (char *s1, char *s2, int n)
+{
+	int		c1, c2;
+	
+	while (1)
+	{
+		c1 = *s1++;
+		c2 = *s2++;
+
+		if (!n--)
+			return 0;		// strings are equal until end point
+		
+		if (c1 != c2)
+		{
+			if (c1 >= 'a' && c1 <= 'z')
+				c1 -= ('a' - 'A');
+			if (c2 >= 'a' && c2 <= 'z')
+				c2 -= ('a' - 'A');
+			if (c1 != c2)
+				return -1;		// strings not equal
+		}
+		if (!c1)
+			return 0;		// strings are equal
+//		s1++;
+//		s2++;
+	}
+	
+	return -1;
+}
+
+int Q_strcasecmp (char *s1, char *s2)
+{
+	return Q_strncasecmp (s1, s2, 99999);
+}
+
+#endif
+
+int Q_atoi (char *str)
+{
+	int		val;
+	int		sign;
+	int		c;
+	
+	if (*str == '-')
+	{
+		sign = -1;
+		str++;
+	}
+	else
+		sign = 1;
+		
+	val = 0;
+
+//
+// check for hex
+//
+	if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X') )
+	{
+		str += 2;
+		while (1)
+		{
+			c = *str++;
+			if (c >= '0' && c <= '9')
+				val = (val<<4) + c - '0';
+			else if (c >= 'a' && c <= 'f')
+				val = (val<<4) + c - 'a' + 10;
+			else if (c >= 'A' && c <= 'F')
+				val = (val<<4) + c - 'A' + 10;
+			else
+				return val*sign;
+		}
+	}
+	
+//
+// check for character
+//
+	if (str[0] == '\'')
+	{
+		return sign * str[1];
+	}
+	
+//
+// assume decimal
+//
+	while (1)
+	{
+		c = *str++;
+		if (c <'0' || c > '9')
+			return val*sign;
+		val = val*10 + c - '0';
+	}
+	
+	return 0;
+}
+
+
+float Q_atof (char *str)
+{
+	double	val;
+	int		sign;
+	int		c;
+	int		decimal, total;
+	
+	if (*str == '-')
+	{
+		sign = -1;
+		str++;
+	}
+	else
+		sign = 1;
+		
+	val = 0;
+
+//
+// check for hex
+//
+	if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X') )
+	{
+		str += 2;
+		while (1)
+		{
+			c = *str++;
+			if (c >= '0' && c <= '9')
+				val = (val*16) + c - '0';
+			else if (c >= 'a' && c <= 'f')
+				val = (val*16) + c - 'a' + 10;
+			else if (c >= 'A' && c <= 'F')
+				val = (val*16) + c - 'A' + 10;
+			else
+				return val*sign;
+		}
+	}
+	
+//
+// check for character
+//
+	if (str[0] == '\'')
+	{
+		return sign * str[1];
+	}
+	
+//
+// assume decimal
+//
+	decimal = -1;
+	total = 0;
+	while (1)
+	{
+		c = *str++;
+		if (c == '.')
+		{
+			decimal = total;
+			continue;
+		}
+		if (c <'0' || c > '9')
+			break;
+		val = val*10 + c - '0';
+		total++;
+	}
+
+	if (decimal == -1)
+		return val*sign;
+	while (total > decimal)
+	{
+		val /= 10;
+		total--;
+	}
+	
+	return val*sign;
+}
+
+/*
+============================================================================
+
+					BYTE ORDER FUNCTIONS
+
+============================================================================
+*/
+
+qboolean	bigendien;
+
+short	(*BigShort) (short l);
+short	(*LittleShort) (short l);
+int	(*BigLong) (int l);
+int	(*LittleLong) (int l);
+float	(*BigFloat) (float l);
+float	(*LittleFloat) (float l);
+
+short   ShortSwap (short l)
+{
+	byte    b1,b2;
+
+	b1 = l&255;
+	b2 = (l>>8)&255;
+
+	return (b1<<8) + b2;
+}
+
+short	ShortNoSwap (short l)
+{
+	return l;
+}
+
+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;
+}
+
+int	LongNoSwap (int l)
+{
+	return l;
+}
+
+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;
+}
+
+float FloatNoSwap (float f)
+{
+	return f;
+}
+
+/*
+==============================================================================
+
+			MESSAGE IO FUNCTIONS
+
+Handles byte ordering and avoids alignment errors
+==============================================================================
+*/
+
+//
+// writing functions
+//
+
+void MSG_WriteChar (sizebuf_t *sb, int c)
+{
+	byte	*buf;
+	
+#ifdef PARANOID
+	if (c < -128 || c > 127)
+		Sys_Error ("MSG_WriteChar: range error");
+#endif
+
+	buf = SZ_GetSpace (sb, 1);
+	buf[0] = c;
+}
+
+void MSG_WriteByte (sizebuf_t *sb, int c)
+{
+	byte	*buf;
+	
+#ifdef PARANOID
+	if (c < 0 || c > 255)
+		Sys_Error ("MSG_WriteByte: range error");
+#endif
+
+	buf = SZ_GetSpace (sb, 1);
+	buf[0] = c;
+}
+
+void MSG_WriteShort (sizebuf_t *sb, int c)
+{
+	byte	*buf;
+	
+#ifdef PARANOID
+	if (c < ((short)0x8000) || c > (short)0x7fff)
+		Sys_Error ("MSG_WriteShort: range error");
+#endif
+
+	buf = SZ_GetSpace (sb, 2);
+	buf[0] = c&0xff;
+	buf[1] = c>>8;
+}
+
+void MSG_WriteLong (sizebuf_t *sb, int c)
+{
+	byte	*buf;
+	
+	buf = SZ_GetSpace (sb, 4);
+	buf[0] = c&0xff;
+	buf[1] = (c>>8)&0xff;
+	buf[2] = (c>>16)&0xff;
+	buf[3] = c>>24;
+}
+
+void MSG_WriteFloat (sizebuf_t *sb, float f)
+{
+	union
+	{
+		float	f;
+		int	l;
+	} dat;
+	
+	
+	dat.f = f;
+	dat.l = LittleLong (dat.l);
+	
+	SZ_Write (sb, &dat.l, 4);
+}
+
+void MSG_WriteString (sizebuf_t *sb, char *s)
+{
+	if (!s)
+		SZ_Write (sb, "", 1);
+	else
+		SZ_Write (sb, s, Q_strlen(s)+1);
+}
+
+void MSG_WriteCoord (sizebuf_t *sb, float f)
+{
+	MSG_WriteShort (sb, (int)(f*8));
+}
+
+void MSG_WriteAngle (sizebuf_t *sb, float f)
+{
+	MSG_WriteByte (sb, (int)(f*256/360) & 255);
+}
+
+void MSG_WriteAngle16 (sizebuf_t *sb, float f)
+{
+	MSG_WriteShort (sb, (int)(f*65536/360) & 65535);
+}
+
+void MSG_WriteDeltaUsercmd (sizebuf_t *buf, usercmd_t *from, usercmd_t *cmd)
+{
+	int		bits;
+
+//
+// send the movement message
+//
+	bits = 0;
+	if (cmd->angles[0] != from->angles[0])
+		bits |= CM_ANGLE1;
+	if (cmd->angles[1] != from->angles[1])
+		bits |= CM_ANGLE2;
+	if (cmd->angles[2] != from->angles[2])
+		bits |= CM_ANGLE3;
+	if (cmd->forwardmove != from->forwardmove)
+		bits |= CM_FORWARD;
+	if (cmd->sidemove != from->sidemove)
+		bits |= CM_SIDE;
+	if (cmd->upmove != from->upmove)
+		bits |= CM_UP;
+	if (cmd->buttons != from->buttons)
+		bits |= CM_BUTTONS;
+	if (cmd->impulse != from->impulse)
+		bits |= CM_IMPULSE;
+
+    MSG_WriteByte (buf, bits);
+
+	if (bits & CM_ANGLE1)
+		MSG_WriteAngle16 (buf, cmd->angles[0]);
+	if (bits & CM_ANGLE2)
+		MSG_WriteAngle16 (buf, cmd->angles[1]);
+	if (bits & CM_ANGLE3)
+		MSG_WriteAngle16 (buf, cmd->angles[2]);
+	
+	if (bits & CM_FORWARD)
+		MSG_WriteShort (buf, cmd->forwardmove);
+	if (bits & CM_SIDE)
+	  	MSG_WriteShort (buf, cmd->sidemove);
+	if (bits & CM_UP)
+		MSG_WriteShort (buf, cmd->upmove);
+
+ 	if (bits & CM_BUTTONS)
+	  	MSG_WriteByte (buf, cmd->buttons);
+ 	if (bits & CM_IMPULSE)
+	    MSG_WriteByte (buf, cmd->impulse);
+	MSG_WriteByte (buf, cmd->msec);
+}
+
+
+//
+// reading functions
+//
+int			msg_readcount;
+qboolean	msg_badread;
+
+void MSG_BeginReading (void)
+{
+	msg_readcount = 0;
+	msg_badread = false;
+}
+
+int MSG_GetReadCount(void)
+{
+	return msg_readcount;
+}
+
+// returns -1 and sets msg_badread if no more characters are available
+int MSG_ReadChar (void)
+{
+	int	c;
+	
+	if (msg_readcount+1 > net_message.cursize)
+	{
+		msg_badread = true;
+		return -1;
+	}
+		
+	c = (signed char)net_message.data[msg_readcount];
+	msg_readcount++;
+	
+	return c;
+}
+
+int MSG_ReadByte (void)
+{
+	int	c;
+	
+	if (msg_readcount+1 > net_message.cursize)
+	{
+		msg_badread = true;
+		return -1;
+	}
+		
+	c = (unsigned char)net_message.data[msg_readcount];
+	msg_readcount++;
+	
+	return c;
+}
+
+int MSG_ReadShort (void)
+{
+	int	c;
+	
+	if (msg_readcount+2 > net_message.cursize)
+	{
+		msg_badread = true;
+		return -1;
+	}
+		
+	c = (short)(net_message.data[msg_readcount]
+	+ (net_message.data[msg_readcount+1]<<8));
+	
+	msg_readcount += 2;
+	
+	return c;
+}
+
+int MSG_ReadLong (void)
+{
+	int	c;
+	
+	if (msg_readcount+4 > net_message.cursize)
+	{
+		msg_badread = true;
+		return -1;
+	}
+		
+	c = net_message.data[msg_readcount]
+	+ (net_message.data[msg_readcount+1]<<8)
+	+ (net_message.data[msg_readcount+2]<<16)
+	+ (net_message.data[msg_readcount+3]<<24);
+	
+	msg_readcount += 4;
+	
+	return c;
+}
+
+float MSG_ReadFloat (void)
+{
+	union
+	{
+		byte	b[4];
+		float	f;
+		int	l;
+	} dat;
+	
+	dat.b[0] =	net_message.data[msg_readcount];
+	dat.b[1] =	net_message.data[msg_readcount+1];
+	dat.b[2] =	net_message.data[msg_readcount+2];
+	dat.b[3] =	net_message.data[msg_readcount+3];
+	msg_readcount += 4;
+	
+	dat.l = LittleLong (dat.l);
+
+	return dat.f;	
+}
+
+char *MSG_ReadString (void)
+{
+	static char	string[2048];
+	int		l,c;
+	
+	l = 0;
+	do
+	{
+		c = MSG_ReadChar ();
+		if (c == -1 || c == 0)
+			break;
+		string[l] = c;
+		l++;
+	} while (l < sizeof(string)-1);
+	
+	string[l] = 0;
+	
+	return string;
+}
+
+char *MSG_ReadStringLine (void)
+{
+	static char	string[2048];
+	int		l,c;
+	
+	l = 0;
+	do
+	{
+		c = MSG_ReadChar ();
+		if (c == -1 || c == 0 || c == '\n')
+			break;
+		string[l] = c;
+		l++;
+	} while (l < sizeof(string)-1);
+	
+	string[l] = 0;
+	
+	return string;
+}
+
+float MSG_ReadCoord (void)
+{
+	return MSG_ReadShort() * (1.0/8);
+}
+
+float MSG_ReadAngle (void)
+{
+	return MSG_ReadChar() * (360.0/256);
+}
+
+float MSG_ReadAngle16 (void)
+{
+	return MSG_ReadShort() * (360.0/65536);
+}
+
+void MSG_ReadDeltaUsercmd (usercmd_t *from, usercmd_t *move)
+{
+	int bits;
+
+	memcpy (move, from, sizeof(*move));
+
+	bits = MSG_ReadByte ();
+		
+// read current angles
+	if (bits & CM_ANGLE1)
+		move->angles[0] = MSG_ReadAngle16 ();
+	if (bits & CM_ANGLE2)
+		move->angles[1] = MSG_ReadAngle16 ();
+	if (bits & CM_ANGLE3)
+		move->angles[2] = MSG_ReadAngle16 ();
+		
+// read movement
+	if (bits & CM_FORWARD)
+		move->forwardmove = MSG_ReadShort ();
+	if (bits & CM_SIDE)
+		move->sidemove = MSG_ReadShort ();
+	if (bits & CM_UP)
+		move->upmove = MSG_ReadShort ();
+	
+// read buttons
+	if (bits & CM_BUTTONS)
+		move->buttons = MSG_ReadByte ();
+
+	if (bits & CM_IMPULSE)
+		move->impulse = MSG_ReadByte ();
+
+// read time to run command
+	move->msec = MSG_ReadByte ();
+}
+
+
+//===========================================================================
+
+void SZ_Clear (sizebuf_t *buf)
+{
+	buf->cursize = 0;
+	buf->overflowed = false;
+}
+
+void *SZ_GetSpace (sizebuf_t *buf, int length)
+{
+	void	*data;
+	
+	if (buf->cursize + length > buf->maxsize)
+	{
+		if (!buf->allowoverflow)
+			Sys_Error ("SZ_GetSpace: overflow without allowoverflow set (%d)", buf->maxsize);
+		
+		if (length > buf->maxsize)
+			Sys_Error ("SZ_GetSpace: %i is > full buffer size", length);
+			
+		Sys_Printf ("SZ_GetSpace: overflow\n");	// because Con_Printf may be redirected
+		SZ_Clear (buf); 
+		buf->overflowed = true;
+	}
+
+	data = buf->data + buf->cursize;
+	buf->cursize += length;
+	
+	return data;
+}
+
+void SZ_Write (sizebuf_t *buf, void *data, int length)
+{
+	Q_memcpy (SZ_GetSpace(buf,length),data,length);		
+}
+
+void SZ_Print (sizebuf_t *buf, char *data)
+{
+	int		len;
+	
+	len = Q_strlen(data)+1;
+
+	if (!buf->cursize || buf->data[buf->cursize-1])
+		Q_memcpy ((byte *)SZ_GetSpace(buf, len),data,len); // no trailing 0
+	else
+		Q_memcpy ((byte *)SZ_GetSpace(buf, len-1)-1,data,len); // write over trailing 0
+}
+
+
+//============================================================================
+
+
+/*
+============
+COM_SkipPath
+============
+*/
+char *COM_SkipPath (char *pathname)
+{
+	char	*last;
+	
+	last = pathname;
+	while (*pathname)
+	{
+		if (*pathname=='/')
+			last = pathname+1;
+		pathname++;
+	}
+	return last;
+}
+
+/*
+============
+COM_StripExtension
+============
+*/
+void COM_StripExtension (char *in, char *out)
+{
+	while (*in && *in != '.')
+		*out++ = *in++;
+	*out = 0;
+}
+
+/*
+============
+COM_FileExtension
+============
+*/
+char *COM_FileExtension (char *in)
+{
+	static char exten[8];
+	int		i;
+
+	while (*in && *in != '.')
+		in++;
+	if (!*in)
+		return "";
+	in++;
+	for (i=0 ; i<7 && *in ; i++,in++)
+		exten[i] = *in;
+	exten[i] = 0;
+	return exten;
+}
+
+/*
+============
+COM_FileBase
+============
+*/
+void COM_FileBase (char *in, char *out)
+{
+	char *s, *s2;
+	
+	s = in + strlen(in) - 1;
+	
+	while (s != in && *s != '.')
+		s--;
+	
+	for (s2 = s ; *s2 && *s2 != '/' ; s2--)
+	;
+	
+	if (s-s2 < 2)
+		strcpy (out,"?model?");
+	else
+	{
+		s--;
+		strncpy (out,s2+1, s-s2);
+		out[s-s2] = 0;
+	}
+}
+
+
+/*
+==================
+COM_DefaultExtension
+==================
+*/
+void COM_DefaultExtension (char *path, char *extension)
+{
+	char    *src;
+//
+// if path doesn't have a .EXT, append extension
+// (extension should include the .)
+//
+	src = path + strlen(path) - 1;
+
+	while (*src != '/' && src != path)
+	{
+		if (*src == '.')
+			return;                 // it has an extension
+		src--;
+	}
+
+	strcat (path, extension);
+}
+
+//============================================================================
+
+char		com_token[1024];
+int		com_argc;
+char	**com_argv;
+
+
+/*
+==============
+COM_Parse
+
+Parse a token out of a string
+==============
+*/
+char *COM_Parse (char *data)
+{
+	int		c;
+	int		len;
+	
+	len = 0;
+	com_token[0] = 0;
+	
+	if (!data)
+		return NULL;
+		
+// skip whitespace
+skipwhite:
+	while ( (c = *data) <= ' ')
+	{
+		if (c == 0)
+			return NULL;			// end of file;
+		data++;
+	}
+	
+// skip // comments
+	if (c=='/' && data[1] == '/')
+	{
+		while (*data && *data != '\n')
+			data++;
+		goto skipwhite;
+	}
+	
+
+// handle quoted strings specially
+	if (c == '\"')
+	{
+		data++;
+		while (1)
+		{
+			c = *data++;
+			if (c=='\"' || !c)
+			{
+				com_token[len] = 0;
+				return data;
+			}
+			com_token[len] = c;
+			len++;
+		}
+	}
+
+// parse a regular word
+	do
+	{
+		com_token[len] = c;
+		data++;
+		len++;
+		c = *data;
+	} while (c>32);
+	
+	com_token[len] = 0;
+	return data;
+}
+
+
+/*
+================
+COM_CheckParm
+
+Returns the position (1 to argc-1) in the program's argument list
+where the given parameter apears, or 0 if not present
+================
+*/
+int COM_CheckParm (char *parm)
+{
+	int		i;
+	
+	for (i=1 ; i<com_argc ; i++)
+	{
+		if (!com_argv[i])
+			continue;		// NEXTSTEP sometimes clears appkit vars.
+		if (!Q_strcmp (parm,com_argv[i]))
+			return i;
+	}
+		
+	return 0;
+}
+
+/*
+================
+COM_CheckRegistered
+
+Looks for the pop.txt file and verifies it.
+Sets the "registered" cvar.
+Immediately exits out if an alternate game was attempted to be started without
+being registered.
+================
+*/
+void COM_CheckRegistered (void)
+{
+	FILE		*h;
+	unsigned short	check[128];
+	int			i;
+
+	COM_FOpenFile("gfx/pop.lmp", &h);
+	static_registered = 0;
+
+	if (!h)
+	{
+		Con_Printf ("Playing shareware version.\n");
+#ifndef SERVERONLY
+// FIXME DEBUG -- only temporary
+		if (com_modified)
+			Sys_Error ("You must have the registered version to play QuakeWorld");
+#endif
+		return;
+	}
+
+	fread (check, 1, sizeof(check), h);
+	fclose (h);
+	
+	for (i=0 ; i<128 ; i++)
+		if (pop[i] != (unsigned short)BigShort (check[i]))
+			Sys_Error ("Corrupted data file.");
+	
+	Cvar_Set ("registered", "1");
+	static_registered = 1;
+	Con_Printf ("Playing registered version.\n");
+}
+
+
+
+/*
+================
+COM_InitArgv
+================
+*/
+void COM_InitArgv (int argc, char **argv)
+{
+	qboolean	safe;
+	int			i;
+
+	safe = false;
+
+	for (com_argc=0 ; (com_argc<MAX_NUM_ARGVS) && (com_argc < argc) ;
+		 com_argc++)
+	{
+		largv[com_argc] = argv[com_argc];
+		if (!Q_strcmp ("-safe", argv[com_argc]))
+			safe = true;
+	}
+
+	if (safe)
+	{
+	// force all the safe-mode switches. Note that we reserved extra space in
+	// case we need to add these, so we don't need an overflow check
+		for (i=0 ; i<NUM_SAFE_ARGVS ; i++)
+		{
+			largv[com_argc] = safeargvs[i];
+			com_argc++;
+		}
+	}
+
+	largv[com_argc] = argvdummy;
+	com_argv = largv;
+}
+
+/*
+================
+COM_AddParm
+
+Adds the given string at the end of the current argument list
+================
+*/
+void COM_AddParm (char *parm)
+{
+	largv[com_argc++] = parm;
+}
+
+
+/*
+================
+COM_Init
+================
+*/
+void COM_Init (void)
+{
+	byte	swaptest[2] = {1,0};
+
+// set the byte swapping variables in a portable manner	
+	if ( *(short *)swaptest == 1)
+	{
+		bigendien = false;
+		BigShort = ShortSwap;
+		LittleShort = ShortNoSwap;
+		BigLong = LongSwap;
+		LittleLong = LongNoSwap;
+		BigFloat = FloatSwap;
+		LittleFloat = FloatNoSwap;
+	}
+	else
+	{
+		bigendien = true;
+		BigShort = ShortNoSwap;
+		LittleShort = ShortSwap;
+		BigLong = LongNoSwap;
+		LittleLong = LongSwap;
+		BigFloat = FloatNoSwap;
+		LittleFloat = FloatSwap;
+	}
+
+	Cvar_RegisterVariable (&registered);
+	Cmd_AddCommand ("path", COM_Path_f);
+
+	COM_InitFilesystem ();
+	COM_CheckRegistered ();
+}
+
+
+/*
+============
+va
+
+does a varargs printf into a temp buffer, so I don't need to have
+varargs versions of all text functions.
+FIXME: make this buffer size safe someday
+============
+*/
+char	*va(char *format, ...)
+{
+	va_list		argptr;
+	static char		string[1024];
+	
+	va_start (argptr, format);
+	vsprintf (string, format,argptr);
+	va_end (argptr);
+
+	return string;	
+}
+
+
+/// just for debugging
+int	memsearch (byte *start, int count, int search)
+{
+	int		i;
+	
+	for (i=0 ; i<count ; i++)
+		if (start[i] == search)
+			return i;
+	return -1;
+}
+
+/*
+=============================================================================
+
+QUAKE FILESYSTEM
+
+=============================================================================
+*/
+
+int	com_filesize;
+
+
+//
+// in memory
+//
+
+typedef struct
+{
+	char	name[MAX_QPATH];
+	int		filepos, filelen;
+} packfile_t;
+
+typedef struct pack_s
+{
+	char	filename[MAX_OSPATH];
+	FILE	*handle;
+	int		numfiles;
+	packfile_t	*files;
+} pack_t;
+
+//
+// on disk
+//
+typedef struct
+{
+	char	name[56];
+	int		filepos, filelen;
+} dpackfile_t;
+
+typedef struct
+{
+	char	id[4];
+	int		dirofs;
+	int		dirlen;
+} dpackheader_t;
+
+#define	MAX_FILES_IN_PACK	2048
+
+char	com_gamedir[MAX_OSPATH];
+char	com_basedir[MAX_OSPATH];
+
+typedef struct searchpath_s
+{
+	char	filename[MAX_OSPATH];
+	pack_t	*pack;		// only one of filename / pack will be used
+	struct searchpath_s *next;
+} searchpath_t;
+
+searchpath_t	*com_searchpaths;
+searchpath_t	*com_base_searchpaths;	// without gamedirs
+
+/*
+================
+COM_filelength
+================
+*/
+int COM_filelength (FILE *f)
+{
+	int		pos;
+	int		end;
+
+	pos = ftell (f);
+	fseek (f, 0, SEEK_END);
+	end = ftell (f);
+	fseek (f, pos, SEEK_SET);
+
+	return end;
+}
+
+int COM_FileOpenRead (char *path, FILE **hndl)
+{
+	FILE	*f;
+
+	f = fopen(path, "rb");
+	if (!f)
+	{
+		*hndl = NULL;
+		return -1;
+	}
+	*hndl = f;
+	
+	return COM_filelength(f);
+}
+
+/*
+============
+COM_Path_f
+
+============
+*/
+void COM_Path_f (void)
+{
+	searchpath_t	*s;
+	
+	Con_Printf ("Current search path:\n");
+	for (s=com_searchpaths ; s ; s=s->next)
+	{
+		if (s == com_base_searchpaths)
+			Con_Printf ("----------\n");
+		if (s->pack)
+			Con_Printf ("%s (%i files)\n", s->pack->filename, s->pack->numfiles);
+		else
+			Con_Printf ("%s\n", s->filename);
+	}
+}
+
+/*
+============
+COM_WriteFile
+
+The filename will be prefixed by the current game directory
+============
+*/
+void COM_WriteFile (char *filename, void *data, int len)
+{
+	FILE	*f;
+	char	name[MAX_OSPATH];
+	
+	sprintf (name, "%s/%s", com_gamedir, filename);
+	
+	f = fopen (name, "wb");
+	if (!f) {
+		Sys_mkdir(com_gamedir);
+		f = fopen (name, "wb");
+		if (!f)
+			Sys_Error ("Error opening %s", filename);
+	}
+	
+	Sys_Printf ("COM_WriteFile: %s\n", name);
+	fwrite (data, 1, len, f);
+	fclose (f);
+}
+
+
+/*
+============
+COM_CreatePath
+
+Only used for CopyFile and download
+============
+*/
+void	COM_CreatePath (char *path)
+{
+	char	*ofs;
+	
+	for (ofs = path+1 ; *ofs ; ofs++)
+	{
+		if (*ofs == '/')
+		{	// create the directory
+			*ofs = 0;
+			Sys_mkdir (path);
+			*ofs = '/';
+		}
+	}
+}
+
+
+/*
+===========
+COM_CopyFile
+
+Copies a file over from the net to the local cache, creating any directories
+needed.  This is for the convenience of developers using ISDN from home.
+===========
+*/
+void COM_CopyFile (char *netpath, char *cachepath)
+{
+	FILE	*in, *out;
+	int		remaining, count;
+	char	buf[4096];
+	
+	remaining = COM_FileOpenRead (netpath, &in);		
+	COM_CreatePath (cachepath);	// create directories up to the cache file
+	out = fopen(cachepath, "wb");
+	if (!out)
+		Sys_Error ("Error opening %s", cachepath);
+	
+	while (remaining)
+	{
+		if (remaining < sizeof(buf))
+			count = remaining;
+		else
+			count = sizeof(buf);
+		fread (buf, 1, count, in);
+		fwrite (buf, 1, count, out);
+		remaining -= count;
+	}
+
+	fclose (in);
+	fclose (out);
+}
+
+/*
+===========
+COM_FindFile
+
+Finds the file in the search path.
+Sets com_filesize and one of handle or file
+===========
+*/
+int file_from_pak; // global indicating file came from pack file ZOID
+
+int COM_FOpenFile (char *filename, FILE **file)
+{
+	searchpath_t	*search;
+	char		netpath[MAX_OSPATH];
+	pack_t		*pak;
+	int			i;
+	int			findtime;
+
+	file_from_pak = 0;
+		
+//
+// search through the path, one element at a time
+//
+	for (search = com_searchpaths ; search ; search = search->next)
+	{
+	// is the element a pak file?
+		if (search->pack)
+		{
+		// look through all the pak file elements
+			pak = search->pack;
+			for (i=0 ; i<pak->numfiles ; i++)
+				if (!strcmp (pak->files[i].name, filename))
+				{	// found it!
+					Sys_Printf ("PackFile: %s : %s\n",pak->filename, filename);
+				// open a new file on the pakfile
+					*file = fopen (pak->filename, "rb");
+					if (!*file)
+						Sys_Error ("Couldn't reopen %s", pak->filename);	
+					fseek (*file, pak->files[i].filepos, SEEK_SET);
+					com_filesize = pak->files[i].filelen;
+					file_from_pak = 1;
+					return com_filesize;
+				}
+		}
+		else
+		{		
+	// check a file in the directory tree
+			if (!static_registered)
+			{	// if not a registered version, don't ever go beyond base
+				if ( strchr (filename, '/') || strchr (filename,'\\'))
+					continue;
+			}
+			
+			sprintf (netpath, "%s/%s",search->filename, filename);
+			
+			findtime = Sys_FileTime (netpath);
+			if (findtime == -1)
+				continue;
+				
+			Sys_Printf ("FindFile: %s\n",netpath);
+
+			*file = fopen (netpath, "rb");
+			return COM_filelength (*file);
+		}
+		
+	}
+	
+	Sys_Printf ("FindFile: can't find %s\n", filename);
+	
+	*file = NULL;
+	com_filesize = -1;
+	return -1;
+}
+
+/*
+============
+COM_LoadFile
+
+Filename are reletive to the quake directory.
+Allways appends a 0 byte to the loaded data.
+============
+*/
+cache_user_t *loadcache;
+byte	*loadbuf;
+int		loadsize;
+byte *COM_LoadFile (char *path, int usehunk)
+{
+	FILE	*h;
+	byte	*buf;
+	char	base[32];
+	int		len;
+
+	buf = NULL;	// quiet compiler warning
+
+// look for it in the filesystem or pack files
+	len = com_filesize = COM_FOpenFile (path, &h);
+	if (!h)
+		return NULL;
+	
+// extract the filename base name for hunk tag
+	COM_FileBase (path, base);
+	
+	if (usehunk == 1)
+		buf = Hunk_AllocName (len+1, base);
+	else if (usehunk == 2)
+		buf = Hunk_TempAlloc (len+1);
+	else if (usehunk == 0)
+		buf = Z_Malloc (len+1);
+	else if (usehunk == 3)
+		buf = Cache_Alloc (loadcache, len+1, base);
+	else if (usehunk == 4)
+	{
+		if (len+1 > loadsize)
+			buf = Hunk_TempAlloc (len+1);
+		else
+			buf = loadbuf;
+	}
+	else
+		Sys_Error ("COM_LoadFile: bad usehunk");
+
+	if (!buf)
+		Sys_Error ("COM_LoadFile: not enough space for %s", path);
+		
+	((byte *)buf)[len] = 0;
+#ifndef SERVERONLY
+	Draw_BeginDisc ();
+#endif
+	fread (buf, 1, len, h);
+	fclose (h);
+#ifndef SERVERONLY
+	Draw_EndDisc ();
+#endif
+
+	return buf;
+}
+
+byte *COM_LoadHunkFile (char *path)
+{
+	return COM_LoadFile (path, 1);
+}
+
+byte *COM_LoadTempFile (char *path)
+{
+	return COM_LoadFile (path, 2);
+}
+
+void COM_LoadCacheFile (char *path, struct cache_user_s *cu)
+{
+	loadcache = cu;
+	COM_LoadFile (path, 3);
+}
+
+// uses temp hunk if larger than bufsize
+byte *COM_LoadStackFile (char *path, void *buffer, int bufsize)
+{
+	byte	*buf;
+	
+	loadbuf = (byte *)buffer;
+	loadsize = bufsize;
+	buf = COM_LoadFile (path, 4);
+	
+	return buf;
+}
+
+/*
+=================
+COM_LoadPackFile
+
+Takes an explicit (not game tree related) path to a pak file.
+
+Loads the header and directory, adding the files at the beginning
+of the list so they override previous pack files.
+=================
+*/
+pack_t *COM_LoadPackFile (char *packfile)
+{
+	dpackheader_t	header;
+	int				i;
+	packfile_t		*newfiles;
+	int				numpackfiles;
+	pack_t			*pack;
+	FILE			*packhandle;
+	dpackfile_t		info[MAX_FILES_IN_PACK];
+	unsigned short		crc;
+
+	if (COM_FileOpenRead (packfile, &packhandle) == -1)
+		return NULL;
+
+	fread (&header, 1, sizeof(header), packhandle);
+	if (header.id[0] != 'P' || header.id[1] != 'A'
+	|| header.id[2] != 'C' || header.id[3] != 'K')
+		Sys_Error ("%s is not a packfile", packfile);
+	header.dirofs = LittleLong (header.dirofs);
+	header.dirlen = LittleLong (header.dirlen);
+
+	numpackfiles = header.dirlen / sizeof(dpackfile_t);
+
+	if (numpackfiles > MAX_FILES_IN_PACK)
+		Sys_Error ("%s has %i files", packfile, numpackfiles);
+
+	if (numpackfiles != PAK0_COUNT)
+		com_modified = true;	// not the original file
+
+	newfiles = Z_Malloc (numpackfiles * sizeof(packfile_t));
+
+	fseek (packhandle, header.dirofs, SEEK_SET);
+	fread (&info, 1, header.dirlen, packhandle);
+
+// crc the directory to check for modifications
+	crc = CRC_Block((byte *)info, header.dirlen);
+
+//	CRC_Init (&crc);
+//	for (i=0 ; i<header.dirlen ; i++)
+//		CRC_ProcessByte (&crc, ((byte *)info)[i]);
+	if (crc != PAK0_CRC)
+		com_modified = true;
+
+// parse the directory
+	for (i=0 ; i<numpackfiles ; i++)
+	{
+		strcpy (newfiles[i].name, info[i].name);
+		newfiles[i].filepos = LittleLong(info[i].filepos);
+		newfiles[i].filelen = LittleLong(info[i].filelen);
+	}
+
+	pack = Z_Malloc (sizeof (pack_t));
+	strcpy (pack->filename, packfile);
+	pack->handle = packhandle;
+	pack->numfiles = numpackfiles;
+	pack->files = newfiles;
+	
+	Con_Printf ("Added packfile %s (%i files)\n", packfile, numpackfiles);
+	return pack;
+}
+
+
+/*
+================
+COM_AddGameDirectory
+
+Sets com_gamedir, adds the directory to the head of the path,
+then loads and adds pak1.pak pak2.pak ... 
+================
+*/
+void COM_AddGameDirectory (char *dir)
+{
+	int				i;
+	searchpath_t	*search;
+	pack_t			*pak;
+	char			pakfile[MAX_OSPATH];
+	char			*p;
+
+	if ((p = strrchr(dir, '/')) != NULL)
+		strcpy(gamedirfile, ++p);
+	else
+		strcpy(gamedirfile, p);
+	strcpy (com_gamedir, dir);
+
+//
+// add the directory to the search path
+//
+	search = Hunk_Alloc (sizeof(searchpath_t));
+	strcpy (search->filename, dir);
+	search->next = com_searchpaths;
+	com_searchpaths = search;
+
+//
+// add any pak files in the format pak0.pak pak1.pak, ...
+//
+	for (i=0 ; ; i++)
+	{
+		sprintf (pakfile, "%s/pak%i.pak", dir, i);
+		pak = COM_LoadPackFile (pakfile);
+		if (!pak)
+			break;
+		search = Hunk_Alloc (sizeof(searchpath_t));
+		search->pack = pak;
+		search->next = com_searchpaths;
+		com_searchpaths = search;		
+	}
+
+}
+
+/*
+================
+COM_Gamedir
+
+Sets the gamedir and path to a different directory.
+================
+*/
+void COM_Gamedir (char *dir)
+{
+	searchpath_t	*search, *next;
+	int				i;
+	pack_t			*pak;
+	char			pakfile[MAX_OSPATH];
+
+	if (strstr(dir, "..") || strstr(dir, "/")
+		|| strstr(dir, "\\") || strstr(dir, ":") )
+	{
+		Con_Printf ("Gamedir should be a single filename, not a path\n");
+		return;
+	}
+
+	if (!strcmp(gamedirfile, dir))
+		return;		// still the same
+	strcpy (gamedirfile, dir);
+
+	//
+	// free up any current game dir info
+	//
+	while (com_searchpaths != com_base_searchpaths)
+	{
+		if (com_searchpaths->pack)
+		{
+			fclose (com_searchpaths->pack->handle);
+			Z_Free (com_searchpaths->pack->files);
+			Z_Free (com_searchpaths->pack);
+		}
+		next = com_searchpaths->next;
+		Z_Free (com_searchpaths);
+		com_searchpaths = next;
+	}
+
+	//
+	// flush all data, so it will be forced to reload
+	//
+	Cache_Flush ();
+
+	if (!strcmp(dir,"id1") || !strcmp(dir, "qw"))
+		return;
+
+	sprintf (com_gamedir, "%s/%s", com_basedir, dir);
+
+	//
+	// add the directory to the search path
+	//
+	search = Z_Malloc (sizeof(searchpath_t));
+	strcpy (search->filename, com_gamedir);
+	search->next = com_searchpaths;
+	com_searchpaths = search;
+
+	//
+	// add any pak files in the format pak0.pak pak1.pak, ...
+	//
+	for (i=0 ; ; i++)
+	{
+		sprintf (pakfile, "%s/pak%i.pak", com_gamedir, i);
+		pak = COM_LoadPackFile (pakfile);
+		if (!pak)
+			break;
+		search = Z_Malloc (sizeof(searchpath_t));
+		search->pack = pak;
+		search->next = com_searchpaths;
+		com_searchpaths = search;		
+	}
+}
+
+/*
+================
+COM_InitFilesystem
+================
+*/
+void COM_InitFilesystem (void)
+{
+	int		i;
+
+//
+// -basedir <path>
+// Overrides the system supplied base directory (under id1)
+//
+	i = COM_CheckParm ("-basedir");
+	if (i && i < com_argc-1)
+		strcpy (com_basedir, com_argv[i+1]);
+	else
+		strcpy (com_basedir, host_parms.basedir);
+
+//
+// start up with id1 by default
+//
+	COM_AddGameDirectory (va("%s/id1", com_basedir) );
+	COM_AddGameDirectory (va("%s/qw", com_basedir) );
+
+	// any set gamedirs will be freed up to here
+	com_base_searchpaths = com_searchpaths;
+}
+
+
+
+/*
+=====================================================================
+
+  INFO STRINGS
+
+=====================================================================
+*/
+
+/*
+===============
+Info_ValueForKey
+
+Searches the string for the given
+key and returns the associated value, or an empty string.
+===============
+*/
+char *Info_ValueForKey (char *s, char *key)
+{
+	char	pkey[512];
+	static	char value[4][512];	// use two buffers so compares
+								// work without stomping on each other
+	static	int	valueindex;
+	char	*o;
+	
+	valueindex = (valueindex + 1) % 4;
+	if (*s == '\\')
+		s++;
+	while (1)
+	{
+		o = pkey;
+		while (*s != '\\')
+		{
+			if (!*s)
+				return "";
+			*o++ = *s++;
+		}
+		*o = 0;
+		s++;
+
+		o = value[valueindex];
+
+		while (*s != '\\' && *s)
+		{
+			if (!*s)
+				return "";
+			*o++ = *s++;
+		}
+		*o = 0;
+
+		if (!strcmp (key, pkey) )
+			return value[valueindex];
+
+		if (!*s)
+			return "";
+		s++;
+	}
+}
+
+void Info_RemoveKey (char *s, char *key)
+{
+	char	*start;
+	char	pkey[512];
+	char	value[512];
+	char	*o;
+
+	if (strstr (key, "\\"))
+	{
+		Con_Printf ("Can't use a key with a \\\n");
+		return;
+	}
+
+	while (1)
+	{
+		start = s;
+		if (*s == '\\')
+			s++;
+		o = pkey;
+		while (*s != '\\')
+		{
+			if (!*s)
+				return;
+			*o++ = *s++;
+		}
+		*o = 0;
+		s++;
+
+		o = value;
+		while (*s != '\\' && *s)
+		{
+			if (!*s)
+				return;
+			*o++ = *s++;
+		}
+		*o = 0;
+
+		if (!strcmp (key, pkey) )
+		{
+			strcpy (start, s);	// remove this part
+			return;
+		}
+
+		if (!*s)
+			return;
+	}
+
+}
+
+void Info_RemovePrefixedKeys (char *start, char prefix)
+{
+	char	*s;
+	char	pkey[512];
+	char	value[512];
+	char	*o;
+
+	s = start;
+
+	while (1)
+	{
+		if (*s == '\\')
+			s++;
+		o = pkey;
+		while (*s != '\\')
+		{
+			if (!*s)
+				return;
+			*o++ = *s++;
+		}
+		*o = 0;
+		s++;
+
+		o = value;
+		while (*s != '\\' && *s)
+		{
+			if (!*s)
+				return;
+			*o++ = *s++;
+		}
+		*o = 0;
+
+		if (pkey[0] == prefix)
+		{
+			Info_RemoveKey (start, pkey);
+			s = start;
+		}
+
+		if (!*s)
+			return;
+	}
+
+}
+
+
+void Info_SetValueForStarKey (char *s, char *key, char *value, int maxsize)
+{
+	char	new[1024], *v;
+	int		c;
+#ifdef SERVERONLY
+	extern cvar_t sv_highchars;
+#endif
+
+	if (strstr (key, "\\") || strstr (value, "\\") )
+	{
+		Con_Printf ("Can't use keys or values with a \\\n");
+		return;
+	}
+
+	if (strstr (key, "\"") || strstr (value, "\"") )
+	{
+		Con_Printf ("Can't use keys or values with a \"\n");
+		return;
+	}
+
+	if (strlen(key) > 63 || strlen(value) > 63)
+	{
+		Con_Printf ("Keys and values must be < 64 characters.\n");
+		return;
+	}
+
+	// this next line is kinda trippy
+	if (*(v = Info_ValueForKey(s, key))) {
+		// key exists, make sure we have enough room for new value, if we don't,
+		// don't change it!
+		if (strlen(value) - strlen(v) + strlen(s) > maxsize) {
+			Con_Printf ("Info string length exceeded\n");
+			return;
+		}
+	}
+	Info_RemoveKey (s, key);
+	if (!value || !strlen(value))
+		return;
+
+	sprintf (new, "\\%s\\%s", key, value);
+
+	if ((int)(strlen(new) + strlen(s)) > maxsize)
+	{
+		Con_Printf ("Info string length exceeded\n");
+		return;
+	}
+
+	// only copy ascii values
+	s += strlen(s);
+	v = new;
+	while (*v)
+	{
+		c = (unsigned char)*v++;
+#ifndef SERVERONLY
+		// client only allows highbits on name
+		if (stricmp(key, "name") != 0) {
+			c &= 127;
+			if (c < 32 || c > 127)
+				continue;
+			// auto lowercase team
+			if (stricmp(key, "team") == 0)
+				c = tolower(c);
+		}
+#else
+		if (!sv_highchars.value) {
+			c &= 127;
+			if (c < 32 || c > 127)
+				continue;
+		}
+#endif
+//		c &= 127;		// strip high bits
+		if (c > 13) // && c < 127)
+			*s++ = c;
+	}
+	*s = 0;
+}
+
+void Info_SetValueForKey (char *s, char *key, char *value, int maxsize)
+{
+	if (key[0] == '*')
+	{
+		Con_Printf ("Can't set * keys\n");
+		return;
+	}
+
+	Info_SetValueForStarKey (s, key, value, maxsize);
+}
+
+void Info_Print (char *s)
+{
+	char	key[512];
+	char	value[512];
+	char	*o;
+	int		l;
+
+	if (*s == '\\')
+		s++;
+	while (*s)
+	{
+		o = key;
+		while (*s && *s != '\\')
+			*o++ = *s++;
+
+		l = o - key;
+		if (l < 20)
+		{
+			memset (o, ' ', 20-l);
+			key[20] = 0;
+		}
+		else
+			*o = 0;
+		Con_Printf ("%s", key);
+
+		if (!*s)
+		{
+			Con_Printf ("MISSING VALUE\n");
+			return;
+		}
+
+		o = value;
+		s++;
+		while (*s && *s != '\\')
+			*o++ = *s++;
+		*o = 0;
+
+		if (*s)
+			s++;
+		Con_Printf ("%s\n", value);
+	}
+}
+
+static byte chktbl[1024 + 4] = {
+0x78,0xd2,0x94,0xe3,0x41,0xec,0xd6,0xd5,0xcb,0xfc,0xdb,0x8a,0x4b,0xcc,0x85,0x01,
+0x23,0xd2,0xe5,0xf2,0x29,0xa7,0x45,0x94,0x4a,0x62,0xe3,0xa5,0x6f,0x3f,0xe1,0x7a,
+0x64,0xed,0x5c,0x99,0x29,0x87,0xa8,0x78,0x59,0x0d,0xaa,0x0f,0x25,0x0a,0x5c,0x58,
+0xfb,0x00,0xa7,0xa8,0x8a,0x1d,0x86,0x80,0xc5,0x1f,0xd2,0x28,0x69,0x71,0x58,0xc3,
+0x51,0x90,0xe1,0xf8,0x6a,0xf3,0x8f,0xb0,0x68,0xdf,0x95,0x40,0x5c,0xe4,0x24,0x6b,
+0x29,0x19,0x71,0x3f,0x42,0x63,0x6c,0x48,0xe7,0xad,0xa8,0x4b,0x91,0x8f,0x42,0x36,
+0x34,0xe7,0x32,0x55,0x59,0x2d,0x36,0x38,0x38,0x59,0x9b,0x08,0x16,0x4d,0x8d,0xf8,
+0x0a,0xa4,0x52,0x01,0xbb,0x52,0xa9,0xfd,0x40,0x18,0x97,0x37,0xff,0xc9,0x82,0x27,
+0xb2,0x64,0x60,0xce,0x00,0xd9,0x04,0xf0,0x9e,0x99,0xbd,0xce,0x8f,0x90,0x4a,0xdd,
+0xe1,0xec,0x19,0x14,0xb1,0xfb,0xca,0x1e,0x98,0x0f,0xd4,0xcb,0x80,0xd6,0x05,0x63,
+0xfd,0xa0,0x74,0xa6,0x86,0xf6,0x19,0x98,0x76,0x27,0x68,0xf7,0xe9,0x09,0x9a,0xf2,
+0x2e,0x42,0xe1,0xbe,0x64,0x48,0x2a,0x74,0x30,0xbb,0x07,0xcc,0x1f,0xd4,0x91,0x9d,
+0xac,0x55,0x53,0x25,0xb9,0x64,0xf7,0x58,0x4c,0x34,0x16,0xbc,0xf6,0x12,0x2b,0x65,
+0x68,0x25,0x2e,0x29,0x1f,0xbb,0xb9,0xee,0x6d,0x0c,0x8e,0xbb,0xd2,0x5f,0x1d,0x8f,
+0xc1,0x39,0xf9,0x8d,0xc0,0x39,0x75,0xcf,0x25,0x17,0xbe,0x96,0xaf,0x98,0x9f,0x5f,
+0x65,0x15,0xc4,0x62,0xf8,0x55,0xfc,0xab,0x54,0xcf,0xdc,0x14,0x06,0xc8,0xfc,0x42,
+0xd3,0xf0,0xad,0x10,0x08,0xcd,0xd4,0x11,0xbb,0xca,0x67,0xc6,0x48,0x5f,0x9d,0x59,
+0xe3,0xe8,0x53,0x67,0x27,0x2d,0x34,0x9e,0x9e,0x24,0x29,0xdb,0x69,0x99,0x86,0xf9,
+0x20,0xb5,0xbb,0x5b,0xb0,0xf9,0xc3,0x67,0xad,0x1c,0x9c,0xf7,0xcc,0xef,0xce,0x69,
+0xe0,0x26,0x8f,0x79,0xbd,0xca,0x10,0x17,0xda,0xa9,0x88,0x57,0x9b,0x15,0x24,0xba,
+0x84,0xd0,0xeb,0x4d,0x14,0xf5,0xfc,0xe6,0x51,0x6c,0x6f,0x64,0x6b,0x73,0xec,0x85,
+0xf1,0x6f,0xe1,0x67,0x25,0x10,0x77,0x32,0x9e,0x85,0x6e,0x69,0xb1,0x83,0x00,0xe4,
+0x13,0xa4,0x45,0x34,0x3b,0x40,0xff,0x41,0x82,0x89,0x79,0x57,0xfd,0xd2,0x8e,0xe8,
+0xfc,0x1d,0x19,0x21,0x12,0x00,0xd7,0x66,0xe5,0xc7,0x10,0x1d,0xcb,0x75,0xe8,0xfa,
+0xb6,0xee,0x7b,0x2f,0x1a,0x25,0x24,0xb9,0x9f,0x1d,0x78,0xfb,0x84,0xd0,0x17,0x05,
+0x71,0xb3,0xc8,0x18,0xff,0x62,0xee,0xed,0x53,0xab,0x78,0xd3,0x65,0x2d,0xbb,0xc7,
+0xc1,0xe7,0x70,0xa2,0x43,0x2c,0x7c,0xc7,0x16,0x04,0xd2,0x45,0xd5,0x6b,0x6c,0x7a,
+0x5e,0xa1,0x50,0x2e,0x31,0x5b,0xcc,0xe8,0x65,0x8b,0x16,0x85,0xbf,0x82,0x83,0xfb,
+0xde,0x9f,0x36,0x48,0x32,0x79,0xd6,0x9b,0xfb,0x52,0x45,0xbf,0x43,0xf7,0x0b,0x0b,
+0x19,0x19,0x31,0xc3,0x85,0xec,0x1d,0x8c,0x20,0xf0,0x3a,0xfa,0x80,0x4d,0x2c,0x7d,
+0xac,0x60,0x09,0xc0,0x40,0xee,0xb9,0xeb,0x13,0x5b,0xe8,0x2b,0xb1,0x20,0xf0,0xce,
+0x4c,0xbd,0xc6,0x04,0x86,0x70,0xc6,0x33,0xc3,0x15,0x0f,0x65,0x19,0xfd,0xc2,0xd3,
+
+// map checksum goes here
+0x00,0x00,0x00,0x00
+};
+
+static byte chkbuf[16 + 60 + 4];
+
+static unsigned last_mapchecksum = 0;
+
+#if 0
+/*
+====================
+COM_BlockSequenceCheckByte
+
+For proxy protecting
+====================
+*/
+byte	COM_BlockSequenceCheckByte (byte *base, int length, int sequence, unsigned mapchecksum)
+{
+	int		checksum;
+	byte	*p;
+
+	if (last_mapchecksum != mapchecksum) {
+		last_mapchecksum = mapchecksum;
+		chktbl[1024] = (mapchecksum & 0xff000000) >> 24;
+		chktbl[1025] = (mapchecksum & 0x00ff0000) >> 16;
+		chktbl[1026] = (mapchecksum & 0x0000ff00) >> 8;
+		chktbl[1027] = (mapchecksum & 0x000000ff);
+
+		Com_BlockFullChecksum (chktbl, sizeof(chktbl), chkbuf);
+	}
+
+	p = chktbl + (sequence % (sizeof(chktbl) - 8));
+
+	if (length > 60)
+		length = 60;
+	memcpy (chkbuf + 16, base, length);
+
+	length += 16;
+
+	chkbuf[length] = (sequence & 0xff) ^ p[0];
+	chkbuf[length+1] = p[1];
+	chkbuf[length+2] = ((sequence>>8) & 0xff) ^ p[2];
+	chkbuf[length+3] = p[3];
+
+	length += 4;
+
+	checksum = LittleLong(Com_BlockChecksum (chkbuf, length));
+
+	checksum &= 0xff;
+
+	return checksum;
+}
+#endif
+
+/*
+====================
+COM_BlockSequenceCRCByte
+
+For proxy protecting
+====================
+*/
+byte	COM_BlockSequenceCRCByte (byte *base, int length, int sequence)
+{
+	unsigned short crc;
+	byte	*p;
+	byte chkb[60 + 4];
+
+	p = chktbl + (sequence % (sizeof(chktbl) - 8));
+
+	if (length > 60)
+		length = 60;
+	memcpy (chkb, base, length);
+
+	chkb[length] = (sequence & 0xff) ^ p[0];
+	chkb[length+1] = p[1];
+	chkb[length+2] = ((sequence>>8) & 0xff) ^ p[2];
+	chkb[length+3] = p[3];
+
+	length += 4;
+
+	crc = CRC_Block(chkb, length);
+
+	crc &= 0xff;
+
+	return crc;
+}
+
+// char *date = "Oct 24 1996";
+static char *date = __DATE__ ;
+static char *mon[12] = 
+{ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
+static char mond[12] = 
+{ 31,    28,    31,    30,    31,    30,    31,    31,    30,    31,    30,    31 };
+
+// returns days since Oct 24 1996
+int build_number( void )
+{
+	int m = 0; 
+	int d = 0;
+	int y = 0;
+	static int b = 0;
+
+	if (b != 0)
+		return b;
+
+	for (m = 0; m < 11; m++)
+	{
+		if (Q_strncasecmp( &date[0], mon[m], 3 ) == 0)
+			break;
+		d += mond[m];
+	}
+
+	d += atoi( &date[4] ) - 1;
+
+	y = atoi( &date[7] ) - 1900;
+
+	b = d + (int)((y - 1) * 365.25);
+
+	if (((y % 4) == 0) && m > 1)
+	{
+		b += 1;
+	}
+
+	b -= 35778; // Dec 16 1998
+
+	return b;
+}
+
--- /dev/null
+++ b/QW/client/common.h
@@ -1,0 +1,222 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// comndef.h  -- general definitions
+
+typedef unsigned char 		byte;
+#define _DEF_BYTE_
+
+// KJB Undefined true and false defined in SciTech's DEBUG.H header
+#undef true
+#undef false
+
+typedef enum {false, true}	qboolean;
+
+#define	MAX_INFO_STRING	196
+#define	MAX_SERVERINFO_STRING	512
+#define	MAX_LOCALINFO_STRING	32768
+
+//============================================================================
+
+typedef struct sizebuf_s
+{
+	qboolean	allowoverflow;	// if false, do a Sys_Error
+	qboolean	overflowed;		// set to true if the buffer size failed
+	byte	*data;
+	int		maxsize;
+	int		cursize;
+} sizebuf_t;
+
+void SZ_Clear (sizebuf_t *buf);
+void *SZ_GetSpace (sizebuf_t *buf, int length);
+void SZ_Write (sizebuf_t *buf, void *data, int length);
+void SZ_Print (sizebuf_t *buf, char *data);	// strcats onto the sizebuf
+
+//============================================================================
+
+typedef struct link_s
+{
+	struct link_s	*prev, *next;
+} link_t;
+
+
+void ClearLink (link_t *l);
+void RemoveLink (link_t *l);
+void InsertLinkBefore (link_t *l, link_t *before);
+void InsertLinkAfter (link_t *l, link_t *after);
+
+// (type *)STRUCT_FROM_LINK(link_t *link, type, member)
+// ent = STRUCT_FROM_LINK(link,entity_t,order)
+// FIXME: remove this mess!
+#define	STRUCT_FROM_LINK(l,t,m) ((t *)((byte *)l - (int)&(((t *)0)->m)))
+
+//============================================================================
+
+#ifndef NULL
+#define NULL ((void *)0)
+#endif
+
+#define Q_MAXCHAR ((char)0x7f)
+#define Q_MAXSHORT ((short)0x7fff)
+#define Q_MAXINT	((int)0x7fffffff)
+#define Q_MAXLONG ((int)0x7fffffff)
+#define Q_MAXFLOAT ((int)0x7fffffff)
+
+#define Q_MINCHAR ((char)0x80)
+#define Q_MINSHORT ((short)0x8000)
+#define Q_MININT 	((int)0x80000000)
+#define Q_MINLONG ((int)0x80000000)
+#define Q_MINFLOAT ((int)0x7fffffff)
+
+//============================================================================
+
+extern	qboolean		bigendien;
+
+extern	short	(*BigShort) (short l);
+extern	short	(*LittleShort) (short l);
+extern	int	(*BigLong) (int l);
+extern	int	(*LittleLong) (int l);
+extern	float	(*BigFloat) (float l);
+extern	float	(*LittleFloat) (float l);
+
+//============================================================================
+
+struct usercmd_s;
+
+extern struct usercmd_s nullcmd;
+
+void MSG_WriteChar (sizebuf_t *sb, int c);
+void MSG_WriteByte (sizebuf_t *sb, int c);
+void MSG_WriteShort (sizebuf_t *sb, int c);
+void MSG_WriteLong (sizebuf_t *sb, int c);
+void MSG_WriteFloat (sizebuf_t *sb, float f);
+void MSG_WriteString (sizebuf_t *sb, char *s);
+void MSG_WriteCoord (sizebuf_t *sb, float f);
+void MSG_WriteAngle (sizebuf_t *sb, float f);
+void MSG_WriteAngle16 (sizebuf_t *sb, float f);
+void MSG_WriteDeltaUsercmd (sizebuf_t *sb, struct usercmd_s *from, struct usercmd_s *cmd);
+
+extern	int			msg_readcount;
+extern	qboolean	msg_badread;		// set if a read goes beyond end of message
+
+void MSG_BeginReading (void);
+int MSG_GetReadCount(void);
+int MSG_ReadChar (void);
+int MSG_ReadByte (void);
+int MSG_ReadShort (void);
+int MSG_ReadLong (void);
+float MSG_ReadFloat (void);
+char *MSG_ReadString (void);
+char *MSG_ReadStringLine (void);
+
+float MSG_ReadCoord (void);
+float MSG_ReadAngle (void);
+float MSG_ReadAngle16 (void);
+void MSG_ReadDeltaUsercmd (struct usercmd_s *from, struct usercmd_s *cmd);
+
+//============================================================================
+
+#define Q_memset(d, f, c) memset((d), (f), (c))
+#define Q_memcpy(d, s, c) memcpy((d), (s), (c))
+#define Q_memcmp(m1, m2, c) memcmp((m1), (m2), (c))
+#define Q_strcpy(d, s) strcpy((d), (s))
+#define Q_strncpy(d, s, n) strncpy((d), (s), (n))
+#define Q_strlen(s) ((int)strlen(s))
+#define Q_strrchr(s, c) strrchr((s), (c))
+#define Q_strcat(d, s) strcat((d), (s))
+#define Q_strcmp(s1, s2) strcmp((s1), (s2))
+#define Q_strncmp(s1, s2, n) strncmp((s1), (s2), (n))
+
+#ifdef _WIN32
+
+#define Q_strcasecmp(s1, s2) _stricmp((s1), (s2))
+#define Q_strncasecmp(s1, s2, n) _strnicmp((s1), (s2), (n))
+
+#else
+
+#define Q_strcasecmp(s1, s2) strcasecmp((s1), (s2))
+#define Q_strncasecmp(s1, s2, n) strncasecmp((s1), (s2), (n))
+
+#endif
+
+int	Q_atoi (char *str);
+float Q_atof (char *str);
+
+
+
+//============================================================================
+
+extern	char		com_token[1024];
+extern	qboolean	com_eof;
+
+char *COM_Parse (char *data);
+
+
+extern	int		com_argc;
+extern	char	**com_argv;
+
+int COM_CheckParm (char *parm);
+void COM_AddParm (char *parm);
+
+void COM_Init (void);
+void COM_InitArgv (int argc, char **argv);
+
+char *COM_SkipPath (char *pathname);
+void COM_StripExtension (char *in, char *out);
+void COM_FileBase (char *in, char *out);
+void COM_DefaultExtension (char *path, char *extension);
+
+char	*va(char *format, ...);
+// does a varargs printf into a temp buffer
+
+
+//============================================================================
+
+extern int com_filesize;
+struct cache_user_s;
+
+extern	char	com_gamedir[MAX_OSPATH];
+
+void COM_WriteFile (char *filename, void *data, int len);
+int COM_FOpenFile (char *filename, FILE **file);
+void COM_CloseFile (FILE *h);
+
+byte *COM_LoadStackFile (char *path, void *buffer, int bufsize);
+byte *COM_LoadTempFile (char *path);
+byte *COM_LoadHunkFile (char *path);
+void COM_LoadCacheFile (char *path, struct cache_user_s *cu);
+void COM_CreatePath (char *path);
+void COM_Gamedir (char *dir);
+
+extern	struct cvar_s	registered;
+extern qboolean		standard_quake, rogue, hipnotic;
+
+char *Info_ValueForKey (char *s, char *key);
+void Info_RemoveKey (char *s, char *key);
+void Info_RemovePrefixedKeys (char *start, char prefix);
+void Info_SetValueForKey (char *s, char *key, char *value, int maxsize);
+void Info_SetValueForStarKey (char *s, char *key, char *value, int maxsize);
+void Info_Print (char *s);
+
+unsigned Com_BlockChecksum (void *buffer, int length);
+void Com_BlockFullChecksum (void *buffer, int len, unsigned char *outbuf);
+byte	COM_BlockSequenceCheckByte (byte *base, int length, int sequence, unsigned mapchecksum);
+byte	COM_BlockSequenceCRCByte (byte *base, int length, int sequence);
+
+int build_number( void );
--- /dev/null
+++ b/QW/client/console.c
@@ -1,0 +1,693 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// console.c
+
+#include "quakedef.h"
+
+int			con_ormask;
+console_t	con_main;
+console_t	con_chat;
+console_t	*con;			// point to either con_main or con_chat
+
+int 		con_linewidth;	// characters across screen
+int			con_totallines;		// total lines in console scrollback
+
+float		con_cursorspeed = 4;
+
+
+cvar_t		con_notifytime = {"con_notifytime","3"};		//seconds
+
+#define	NUM_CON_TIMES 4
+float		con_times[NUM_CON_TIMES];	// realtime time the line was generated
+								// for transparent notify lines
+
+int			con_vislines;
+int			con_notifylines;		// scan lines to clear for notify lines
+
+qboolean	con_debuglog;
+
+#define		MAXCMDLINE	256
+extern	char	key_lines[32][MAXCMDLINE];
+extern	int		edit_line;
+extern	int		key_linepos;
+		
+
+qboolean	con_initialized;
+
+
+void Key_ClearTyping (void)
+{
+	key_lines[edit_line][1] = 0;	// clear any typing
+	key_linepos = 1;
+}
+
+/*
+================
+Con_ToggleConsole_f
+================
+*/
+void Con_ToggleConsole_f (void)
+{
+	Key_ClearTyping ();
+
+	if (key_dest == key_console)
+	{
+		if (cls.state == ca_active)
+			key_dest = key_game;
+	}
+	else
+		key_dest = key_console;
+	
+	Con_ClearNotify ();
+}
+
+/*
+================
+Con_ToggleChat_f
+================
+*/
+void Con_ToggleChat_f (void)
+{
+	Key_ClearTyping ();
+
+	if (key_dest == key_console)
+	{
+		if (cls.state == ca_active)
+			key_dest = key_game;
+	}
+	else
+		key_dest = key_console;
+	
+	Con_ClearNotify ();
+}
+
+/*
+================
+Con_Clear_f
+================
+*/
+void Con_Clear_f (void)
+{
+	Q_memset (con_main.text, ' ', CON_TEXTSIZE);
+	Q_memset (con_chat.text, ' ', CON_TEXTSIZE);
+}
+
+						
+/*
+================
+Con_ClearNotify
+================
+*/
+void Con_ClearNotify (void)
+{
+	int		i;
+	
+	for (i=0 ; i<NUM_CON_TIMES ; i++)
+		con_times[i] = 0;
+}
+
+						
+/*
+================
+Con_MessageMode_f
+================
+*/
+void Con_MessageMode_f (void)
+{
+	chat_team = false;
+	key_dest = key_message;
+}
+
+/*
+================
+Con_MessageMode2_f
+================
+*/
+void Con_MessageMode2_f (void)
+{
+	chat_team = true;
+	key_dest = key_message;
+}
+
+/*
+================
+Con_Resize
+
+================
+*/
+void Con_Resize (console_t *con)
+{
+	int		i, j, width, oldwidth, oldtotallines, numlines, numchars;
+	char	tbuf[CON_TEXTSIZE];
+
+	width = (vid.width >> 3) - 2;
+
+	if (width == con_linewidth)
+		return;
+
+	if (width < 1)			// video hasn't been initialized yet
+	{
+		width = 38;
+		con_linewidth = width;
+		con_totallines = CON_TEXTSIZE / con_linewidth;
+		Q_memset (con->text, ' ', CON_TEXTSIZE);
+	}
+	else
+	{
+		oldwidth = con_linewidth;
+		con_linewidth = width;
+		oldtotallines = con_totallines;
+		con_totallines = CON_TEXTSIZE / con_linewidth;
+		numlines = oldtotallines;
+
+		if (con_totallines < numlines)
+			numlines = con_totallines;
+
+		numchars = oldwidth;
+	
+		if (con_linewidth < numchars)
+			numchars = con_linewidth;
+
+		Q_memcpy (tbuf, con->text, CON_TEXTSIZE);
+		Q_memset (con->text, ' ', CON_TEXTSIZE);
+
+		for (i=0 ; i<numlines ; i++)
+		{
+			for (j=0 ; j<numchars ; j++)
+			{
+				con->text[(con_totallines - 1 - i) * con_linewidth + j] =
+						tbuf[((con->current - i + oldtotallines) %
+							  oldtotallines) * oldwidth + j];
+			}
+		}
+
+		Con_ClearNotify ();
+	}
+
+	con->current = con_totallines - 1;
+	con->display = con->current;
+}
+
+					
+/*
+================
+Con_CheckResize
+
+If the line width has changed, reformat the buffer.
+================
+*/
+void Con_CheckResize (void)
+{
+	Con_Resize (&con_main);
+	Con_Resize (&con_chat);
+}
+
+
+/*
+================
+Con_Init
+================
+*/
+void Con_Init (void)
+{
+	con_debuglog = COM_CheckParm("-condebug");
+
+	con = &con_main;
+	con_linewidth = -1;
+	Con_CheckResize ();
+	
+	Con_Printf ("Console initialized.\n");
+
+//
+// register our commands
+//
+	Cvar_RegisterVariable (&con_notifytime);
+
+	Cmd_AddCommand ("toggleconsole", Con_ToggleConsole_f);
+	Cmd_AddCommand ("togglechat", Con_ToggleChat_f);
+	Cmd_AddCommand ("messagemode", Con_MessageMode_f);
+	Cmd_AddCommand ("messagemode2", Con_MessageMode2_f);
+	Cmd_AddCommand ("clear", Con_Clear_f);
+	con_initialized = true;
+}
+
+
+/*
+===============
+Con_Linefeed
+===============
+*/
+void Con_Linefeed (void)
+{
+	con->x = 0;
+	if (con->display == con->current)
+		con->display++;
+	con->current++;
+	Q_memset (&con->text[(con->current%con_totallines)*con_linewidth]
+	, ' ', con_linewidth);
+}
+
+/*
+================
+Con_Print
+
+Handles cursor positioning, line wrapping, etc
+All console printing must go through this in order to be logged to disk
+If no console is visible, the notify window will pop up.
+================
+*/
+void Con_Print (char *txt)
+{
+	int		y;
+	int		c, l;
+	static int	cr;
+	int		mask;
+
+	if (txt[0] == 1 || txt[0] == 2)
+	{
+		mask = 128;		// go to colored text
+		txt++;
+	}
+	else
+		mask = 0;
+
+
+	while ( (c = *txt) )
+	{
+	// count word length
+		for (l=0 ; l< con_linewidth ; l++)
+			if ( txt[l] <= ' ')
+				break;
+
+	// word wrap
+		if (l != con_linewidth && (con->x + l > con_linewidth) )
+			con->x = 0;
+
+		txt++;
+
+		if (cr)
+		{
+			con->current--;
+			cr = false;
+		}
+
+		
+		if (!con->x)
+		{
+			Con_Linefeed ();
+		// mark time for transparent overlay
+			if (con->current >= 0)
+				con_times[con->current % NUM_CON_TIMES] = realtime;
+		}
+
+		switch (c)
+		{
+		case '\n':
+			con->x = 0;
+			break;
+
+		case '\r':
+			con->x = 0;
+			cr = 1;
+			break;
+
+		default:	// display character and advance
+			y = con->current % con_totallines;
+			con->text[y*con_linewidth+con->x] = c | mask | con_ormask;
+			con->x++;
+			if (con->x >= con_linewidth)
+				con->x = 0;
+			break;
+		}
+		
+	}
+}
+
+
+/*
+================
+Con_Printf
+
+Handles cursor positioning, line wrapping, etc
+================
+*/
+#define	MAXPRINTMSG	4096
+// FIXME: make a buffer size safe vsprintf?
+void Con_Printf (char *fmt, ...)
+{
+	va_list		argptr;
+	char		msg[MAXPRINTMSG];
+	static qboolean	inupdate;
+	
+	va_start (argptr,fmt);
+	vsprintf (msg,fmt,argptr);
+	va_end (argptr);
+	
+// also echo to debugging console
+	Sys_Printf ("%s", msg);	// also echo to debugging console
+
+// log all messages to file
+	if (con_debuglog)
+		Sys_DebugLog(va("%s/qconsole.log",com_gamedir), "%s", msg);
+		
+	if (!con_initialized)
+		return;
+		
+// write it to the scrollable buffer
+	Con_Print (msg);
+	
+// update the screen immediately if the console is displayed
+	if (cls.state != ca_active)
+	{
+	// protect against infinite loop if something in SCR_UpdateScreen calls
+	// Con_Printd
+		if (!inupdate)
+		{
+			inupdate = true;
+			SCR_UpdateScreen ();
+			inupdate = false;
+		}
+	}
+}
+
+/*
+================
+Con_DPrintf
+
+A Con_Printf that only shows up if the "developer" cvar is set
+================
+*/
+void Con_DPrintf (char *fmt, ...)
+{
+	va_list		argptr;
+	char		msg[MAXPRINTMSG];
+		
+	if (!developer.value)
+		return;			// don't confuse non-developers with techie stuff...
+
+	va_start (argptr,fmt);
+	vsprintf (msg,fmt,argptr);
+	va_end (argptr);
+	
+	Con_Printf ("%s", msg);
+}
+
+/*
+==============================================================================
+
+DRAWING
+
+==============================================================================
+*/
+
+
+/*
+================
+Con_DrawInput
+
+The input line scrolls horizontally if typing goes beyond the right edge
+================
+*/
+void Con_DrawInput (void)
+{
+	int		y;
+	int		i;
+	char	*text;
+
+	if (key_dest != key_console && cls.state == ca_active)
+		return;		// don't draw anything (allways draw if not active)
+
+	text = key_lines[edit_line];
+	
+// add the cursor frame
+	text[key_linepos] = 10+((int)(realtime*con_cursorspeed)&1);
+	
+// fill out remainder with spaces
+	for (i=key_linepos+1 ; i< con_linewidth ; i++)
+		text[i] = ' ';
+		
+//	prestep if horizontally scrolling
+	if (key_linepos >= con_linewidth)
+		text += 1 + key_linepos - con_linewidth;
+		
+// draw it
+	y = con_vislines-22;
+
+	for (i=0 ; i<con_linewidth ; i++)
+		Draw_Character ( (i+1)<<3, con_vislines - 22, text[i]);
+
+// remove cursor
+	key_lines[edit_line][key_linepos] = 0;
+}
+
+
+/*
+================
+Con_DrawNotify
+
+Draws the last few lines of output transparently over the game top
+================
+*/
+void Con_DrawNotify (void)
+{
+	int		x, v;
+	char	*text;
+	int		i;
+	float	time;
+	char	*s;
+	int		skip;
+
+	v = 0;
+	for (i= con->current-NUM_CON_TIMES+1 ; i<=con->current ; i++)
+	{
+		if (i < 0)
+			continue;
+		time = con_times[i % NUM_CON_TIMES];
+		if (time == 0)
+			continue;
+		time = realtime - time;
+		if (time > con_notifytime.value)
+			continue;
+		text = con->text + (i % con_totallines)*con_linewidth;
+		
+		clearnotify = 0;
+		scr_copytop = 1;
+
+		for (x = 0 ; x < con_linewidth ; x++)
+			Draw_Character ( (x+1)<<3, v, text[x]);
+
+		v += 8;
+	}
+
+
+	if (key_dest == key_message)
+	{
+		clearnotify = 0;
+		scr_copytop = 1;
+	
+		if (chat_team)
+		{
+			Draw_String (8, v, "say_team:");
+			skip = 11;
+		}
+		else
+		{
+			Draw_String (8, v, "say:");
+			skip = 5;
+		}
+
+		s = chat_buffer;
+		if (chat_bufferlen > (vid.width>>3)-(skip+1))
+			s += chat_bufferlen - ((vid.width>>3)-(skip+1));
+		x = 0;
+		while(s[x])
+		{
+			Draw_Character ( (x+skip)<<3, v, s[x]);
+			x++;
+		}
+		Draw_Character ( (x+skip)<<3, v, 10+((int)(realtime*con_cursorspeed)&1));
+		v += 8;
+	}
+	
+	if (v > con_notifylines)
+		con_notifylines = v;
+}
+
+/*
+================
+Con_DrawConsole
+
+Draws the console with the solid background
+================
+*/
+void Con_DrawConsole (int lines)
+{
+	int				i, j, x, y, n;
+	int				rows;
+	char			*text;
+	int				row;
+	char			dlbar[1024];
+	
+	if (lines <= 0)
+		return;
+
+// draw the background
+	Draw_ConsoleBackground (lines);
+
+// draw the text
+	con_vislines = lines;
+	
+// changed to line things up better
+	rows = (lines-22)>>3;		// rows of text to draw
+
+	y = lines - 30;
+
+// draw from the bottom up
+	if (con->display != con->current)
+	{
+	// draw arrows to show the buffer is backscrolled
+		for (x=0 ; x<con_linewidth ; x+=4)
+			Draw_Character ( (x+1)<<3, y, '^');
+	
+		y -= 8;
+		rows--;
+	}
+	
+	row = con->display;
+	for (i=0 ; i<rows ; i++, y-=8, row--)
+	{
+		if (row < 0)
+			break;
+		if (con->current - row >= con_totallines)
+			break;		// past scrollback wrap point
+			
+		text = con->text + (row % con_totallines)*con_linewidth;
+
+		for (x=0 ; x<con_linewidth ; x++)
+			Draw_Character ( (x+1)<<3, y, text[x]);
+	}
+
+	// draw the download bar
+	// figure out width
+	if (cls.download) {
+		if ((text = strrchr(cls.downloadname, '/')) != NULL)
+			text++;
+		else
+			text = cls.downloadname;
+
+		x = con_linewidth - ((con_linewidth * 7) / 40);
+		y = x - strlen(text) - 8;
+		i = con_linewidth/3;
+		if (strlen(text) > i) {
+			y = x - i - 11;
+			strncpy(dlbar, text, i);
+			dlbar[i] = 0;
+			strcat(dlbar, "...");
+		} else
+			strcpy(dlbar, text);
+		strcat(dlbar, ": ");
+		i = strlen(dlbar);
+		dlbar[i++] = '\x80';
+		// where's the dot go?
+		if (cls.downloadpercent == 0)
+			n = 0;
+		else
+			n = y * cls.downloadpercent / 100;
+			
+		for (j = 0; j < y; j++)
+			if (j == n)
+				dlbar[i++] = '\x83';
+			else
+				dlbar[i++] = '\x81';
+		dlbar[i++] = '\x82';
+		dlbar[i] = 0;
+
+		sprintf(dlbar + strlen(dlbar), " %02d%%", cls.downloadpercent);
+
+		// draw it
+		y = con_vislines-22 + 8;
+		for (i = 0; i < strlen(dlbar); i++)
+			Draw_Character ( (i+1)<<3, y, dlbar[i]);
+	}
+
+
+// draw the input prompt, user text, and cursor if desired
+	Con_DrawInput ();
+}
+
+
+/*
+==================
+Con_NotifyBox
+==================
+*/
+void Con_NotifyBox (char *text)
+{
+	double		t1, t2;
+
+// during startup for sound / cd warnings
+	Con_Printf("\n\n\35\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\37\n");
+
+	Con_Printf (text);
+
+	Con_Printf ("Press a key.\n");
+	Con_Printf("\35\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\37\n");
+
+	key_count = -2;		// wait for a key down and up
+	key_dest = key_console;
+
+	do
+	{
+		t1 = Sys_DoubleTime ();
+		SCR_UpdateScreen ();
+		Sys_SendKeyEvents ();
+		t2 = Sys_DoubleTime ();
+		realtime += t2-t1;		// make the cursor blink
+	} while (key_count < 0);
+
+	Con_Printf ("\n");
+	key_dest = key_game;
+	realtime = 0;				// put the cursor back to invisible
+}
+
+
+/*
+==================
+Con_SafePrintf
+
+Okay to call even when the screen can't be updated
+==================
+*/
+void Con_SafePrintf (char *fmt, ...)
+{
+	va_list		argptr;
+	char		msg[1024];
+	int			temp;
+		
+	va_start (argptr,fmt);
+	vsprintf (msg,fmt,argptr);
+	va_end (argptr);
+	
+	temp = scr_disabled_for_loading;
+	scr_disabled_for_loading = true;
+	Con_Printf ("%s", msg);
+	scr_disabled_for_loading = temp;
+}
+
--- /dev/null
+++ b/QW/client/console.h
@@ -1,0 +1,60 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+
+//
+// console
+//
+
+#define		CON_TEXTSIZE	16384
+typedef struct
+{
+	char	text[CON_TEXTSIZE];
+	int		current;		// line where next message will be printed
+	int		x;				// offset in current line for next print
+	int		display;		// bottom of console displays this line
+} console_t;
+
+extern	console_t	con_main;
+extern	console_t	con_chat;
+extern	console_t	*con;			// point to either con_main or con_chat
+
+extern	int			con_ormask;
+
+extern int con_totallines;
+extern qboolean con_initialized;
+extern byte *con_chars;
+extern	int	con_notifylines;		// scan lines to clear for notify lines
+
+void Con_DrawCharacter (int cx, int line, int num);
+
+void Con_CheckResize (void);
+void Con_Init (void);
+void Con_DrawConsole (int lines);
+void Con_Print (char *txt);
+void Con_Printf (char *fmt, ...);
+void Con_DPrintf (char *fmt, ...);
+void Con_SafePrintf (char *fmt, ...);
+void Con_Clear_f (void);
+void Con_DrawNotify (void);
+void Con_ClearNotify (void);
+void Con_ToggleConsole_f (void);
+
+void Con_NotifyBox (char *text);	// during startup for sound / cd warnings
+
--- /dev/null
+++ b/QW/client/crc.c
@@ -1,0 +1,93 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+/* crc.c */
+
+#include "quakedef.h"
+#include "crc.h"
+
+// 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
+
+#define CRC_INIT_VALUE	0xffff
+#define CRC_XOR_VALUE	0x0000
+
+static unsigned short crctable[256] =
+{
+	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
+};
+
+void CRC_Init(unsigned short *crcvalue)
+{
+	*crcvalue = CRC_INIT_VALUE;
+}
+
+void CRC_ProcessByte(unsigned short *crcvalue, byte data)
+{
+	*crcvalue = (*crcvalue << 8) ^ crctable[(*crcvalue >> 8) ^ data];
+}
+
+unsigned short CRC_Value(unsigned short crcvalue)
+{
+	return crcvalue ^ CRC_XOR_VALUE;
+}
+
+unsigned short CRC_Block (byte *start, int count)
+{
+	unsigned short	crc;
+
+	CRC_Init (&crc);
+	while (count--)
+		crc = (crc << 8) ^ crctable[(crc >> 8) ^ *start++];
+
+	return crc;
+}
+
--- /dev/null
+++ b/QW/client/crc.h
@@ -1,0 +1,25 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+/* crc.h */
+
+void CRC_Init(unsigned short *crcvalue);
+void CRC_ProcessByte(unsigned short *crcvalue, byte data);
+unsigned short CRC_Value(unsigned short crcvalue);
+unsigned short CRC_Block (byte *start, int count);
--- /dev/null
+++ b/QW/client/cvar.c
@@ -1,0 +1,249 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// cvar.c -- dynamic variable tracking
+
+#ifdef SERVERONLY 
+#include "qwsvdef.h"
+#else
+#include "quakedef.h"
+#endif
+
+cvar_t	*cvar_vars;
+char	*cvar_null_string = "";
+
+/*
+============
+Cvar_FindVar
+============
+*/
+cvar_t *Cvar_FindVar (char *var_name)
+{
+	cvar_t	*var;
+	
+	for (var=cvar_vars ; var ; var=var->next)
+		if (!Q_strcmp (var_name, var->name))
+			return var;
+
+	return NULL;
+}
+
+/*
+============
+Cvar_VariableValue
+============
+*/
+float	Cvar_VariableValue (char *var_name)
+{
+	cvar_t	*var;
+	
+	var = Cvar_FindVar (var_name);
+	if (!var)
+		return 0;
+	return Q_atof (var->string);
+}
+
+
+/*
+============
+Cvar_VariableString
+============
+*/
+char *Cvar_VariableString (char *var_name)
+{
+	cvar_t *var;
+	
+	var = Cvar_FindVar (var_name);
+	if (!var)
+		return cvar_null_string;
+	return var->string;
+}
+
+
+/*
+============
+Cvar_CompleteVariable
+============
+*/
+char *Cvar_CompleteVariable (char *partial)
+{
+	cvar_t		*cvar;
+	int			len;
+	
+	len = Q_strlen(partial);
+	
+	if (!len)
+		return NULL;
+		
+	// check exact match
+	for (cvar=cvar_vars ; cvar ; cvar=cvar->next)
+		if (!strcmp (partial,cvar->name))
+			return cvar->name;
+
+	// check partial match
+	for (cvar=cvar_vars ; cvar ; cvar=cvar->next)
+		if (!Q_strncmp (partial,cvar->name, len))
+			return cvar->name;
+
+	return NULL;
+}
+
+
+#ifdef SERVERONLY
+void SV_SendServerInfoChange(char *key, char *value);
+#endif
+
+/*
+============
+Cvar_Set
+============
+*/
+void Cvar_Set (char *var_name, char *value)
+{
+	cvar_t	*var;
+	
+	var = Cvar_FindVar (var_name);
+	if (!var)
+	{	// there is an error in C code if this happens
+		Con_Printf ("Cvar_Set: variable %s not found\n", var_name);
+		return;
+	}
+
+#ifdef SERVERONLY
+	if (var->info)
+	{
+		Info_SetValueForKey (svs.info, var_name, value, MAX_SERVERINFO_STRING);
+		SV_SendServerInfoChange(var_name, value);
+//		SV_BroadcastCommand ("fullserverinfo \"%s\"\n", svs.info);
+	}
+#else
+	if (var->info)
+	{
+		Info_SetValueForKey (cls.userinfo, var_name, value, MAX_INFO_STRING);
+		if (cls.state >= ca_connected)
+		{
+			MSG_WriteByte (&cls.netchan.message, clc_stringcmd);
+			SZ_Print (&cls.netchan.message, va("setinfo \"%s\" \"%s\"\n", var_name, value));
+		}
+	}
+#endif
+	
+	Z_Free (var->string);	// free the old value string
+	
+	var->string = Z_Malloc (Q_strlen(value)+1);
+	Q_strcpy (var->string, value);
+	var->value = Q_atof (var->string);
+}
+
+/*
+============
+Cvar_SetValue
+============
+*/
+void Cvar_SetValue (char *var_name, float value)
+{
+	char	val[32];
+	
+	sprintf (val, "%f",value);
+	Cvar_Set (var_name, val);
+}
+
+
+/*
+============
+Cvar_RegisterVariable
+
+Adds a freestanding variable to the variable list.
+============
+*/
+void Cvar_RegisterVariable (cvar_t *variable)
+{
+	char	value[512];
+
+// first check to see if it has allready been defined
+	if (Cvar_FindVar (variable->name))
+	{
+		Con_Printf ("Can't register variable %s, allready defined\n", variable->name);
+		return;
+	}
+	
+// check for overlap with a command
+	if (Cmd_Exists (variable->name))
+	{
+		Con_Printf ("Cvar_RegisterVariable: %s is a command\n", variable->name);
+		return;
+	}
+		
+// link the variable in
+	variable->next = cvar_vars;
+	cvar_vars = variable;
+
+// copy the value off, because future sets will Z_Free it
+	strcpy (value, variable->string);
+	variable->string = Z_Malloc (1);	
+	
+// set it through the function to be consistant
+	Cvar_Set (variable->name, value);
+}
+
+/*
+============
+Cvar_Command
+
+Handles variable inspection and changing from the console
+============
+*/
+qboolean	Cvar_Command (void)
+{
+	cvar_t			*v;
+
+// check variables
+	v = Cvar_FindVar (Cmd_Argv(0));
+	if (!v)
+		return false;
+		
+// perform a variable print or set
+	if (Cmd_Argc() == 1)
+	{
+		Con_Printf ("\"%s\" is \"%s\"\n", v->name, v->string);
+		return true;
+	}
+
+	Cvar_Set (v->name, Cmd_Argv(1));
+	return true;
+}
+
+
+/*
+============
+Cvar_WriteVariables
+
+Writes lines containing "set variable value" for all variables
+with the archive flag set to true.
+============
+*/
+void Cvar_WriteVariables (FILE *f)
+{
+	cvar_t	*var;
+	
+	for (var = cvar_vars ; var ; var = var->next)
+		if (var->archive)
+			fprintf (f, "%s \"%s\"\n", var->name, var->string);
+}
+
--- /dev/null
+++ b/QW/client/cvar.h
@@ -1,0 +1,97 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// cvar.h
+
+/*
+
+cvar_t variables are used to hold scalar or string variables that can be changed or displayed at the console or prog code as well as accessed directly
+in C code.
+
+it is sufficient to initialize a cvar_t with just the first two fields, or
+you can add a ,true flag for variables that you want saved to the configuration
+file when the game is quit:
+
+cvar_t	r_draworder = {"r_draworder","1"};
+cvar_t	scr_screensize = {"screensize","1",true};
+
+Cvars must be registered before use, or they will have a 0 value instead of the float interpretation of the string.  Generally, all cvar_t declarations should be registered in the apropriate init function before any console commands are executed:
+Cvar_RegisterVariable (&host_framerate);
+
+
+C code usually just references a cvar in place:
+if ( r_draworder.value )
+
+It could optionally ask for the value to be looked up for a string name:
+if (Cvar_VariableValue ("r_draworder"))
+
+Interpreted prog code can access cvars with the cvar(name) or
+cvar_set (name, value) internal functions:
+teamplay = cvar("teamplay");
+cvar_set ("registered", "1");
+
+The user can access cvars from the console in two ways:
+r_draworder			prints the current value
+r_draworder 0		sets the current value to 0
+Cvars are restricted from having the same names as commands to keep this
+interface from being ambiguous.
+*/
+
+typedef struct cvar_s
+{
+	char	*name;
+	char	*string;
+	qboolean archive;		// set to true to cause it to be saved to vars.rc
+	qboolean info;			// added to serverinfo or userinfo when changed
+	float	value;
+	struct cvar_s *next;
+} cvar_t;
+
+void 	Cvar_RegisterVariable (cvar_t *variable);
+// registers a cvar that allready has the name, string, and optionally the
+// archive elements set.
+
+void 	Cvar_Set (char *var_name, char *value);
+// equivelant to "<name> <variable>" typed at the console
+
+void	Cvar_SetValue (char *var_name, float value);
+// expands value to a string and calls Cvar_Set
+
+float	Cvar_VariableValue (char *var_name);
+// returns 0 if not defined or non numeric
+
+char	*Cvar_VariableString (char *var_name);
+// returns an empty string if not defined
+
+char 	*Cvar_CompleteVariable (char *partial);
+// attempts to match a partial variable name for command line completion
+// returns NULL if nothing fits
+
+qboolean Cvar_Command (void);
+// called by Cmd_ExecuteString when Cmd_Argv(0) doesn't match a known
+// command.  Returns true if the command was a variable reference that
+// was handled. (print or change)
+
+void 	Cvar_WriteVariables (FILE *f);
+// Writes lines containing "set variable value" for all variables
+// with the archive flag set to true.
+
+cvar_t *Cvar_FindVar (char *var_name);
+
+extern cvar_t	*cvar_vars;
--- /dev/null
+++ b/QW/client/d_copy.s
@@ -1,0 +1,149 @@
+//
+// d_copy.s
+// x86 assembly-language screen copying code.
+//
+
+#include "asm_i386.h"
+#include "quakeasm.h"
+#include "asm_draw.h"
+
+	.data
+
+LCopyWidth:		.long	0
+LBlockSrcStep:	.long	0
+LBlockDestStep:	.long	0
+LSrcDelta:		.long	0
+LDestDelta:		.long	0
+
+#define bufptr	4+16
+
+// copies 16 rows per plane at a pop; idea is that 16*512 = 8k, and since
+// no Mode X mode is wider than 360, all the data should fit in the cache for
+// the passes for the next 3 planes
+
+	.text
+
+.globl C(VGA_UpdatePlanarScreen)
+C(VGA_UpdatePlanarScreen):
+	pushl	%ebp				// preserve caller's stack frame
+	pushl	%edi
+	pushl	%esi				// preserve register variables
+	pushl	%ebx
+
+	movl	C(VGA_bufferrowbytes),%eax
+	shll	$1,%eax
+	movl	%eax,LBlockSrcStep
+	movl	C(VGA_rowbytes),%eax
+	shll	$1,%eax
+	movl	%eax,LBlockDestStep
+
+	movl	$0x3C4,%edx
+	movb	$2,%al
+	outb	%al,%dx		// point the SC to the Map Mask
+	incl	%edx
+
+	movl	bufptr(%esp),%esi
+	movl	C(VGA_pagebase),%edi
+	movl	C(VGA_height),%ebp
+	shrl	$1,%ebp
+
+	movl	C(VGA_width),%ecx
+	movl	C(VGA_bufferrowbytes),%eax
+	subl	%ecx,%eax
+	movl	%eax,LSrcDelta
+	movl	C(VGA_rowbytes),%eax
+	shll	$2,%eax
+	subl	%ecx,%eax
+	movl	%eax,LDestDelta
+	shrl	$4,%ecx
+	movl	%ecx,LCopyWidth
+
+LRowLoop:
+	movb	$1,%al
+
+LPlaneLoop:
+	outb	%al,%dx
+	movb	$2,%ah
+
+	pushl	%esi
+	pushl	%edi
+LRowSetLoop:
+	movl	LCopyWidth,%ecx
+LColumnLoop:
+	movb	12(%esi),%bh
+	movb	8(%esi),%bl
+	shll	$16,%ebx
+	movb	4(%esi),%bh
+	movb	(%esi),%bl
+	movl	%ebx,(%edi)
+	addl	$16,%esi
+	addl	$4,%edi
+	decl	%ecx
+	jnz		LColumnLoop
+
+	addl	LDestDelta,%edi
+	addl	LSrcDelta,%esi
+	decb	%ah
+	jnz		LRowSetLoop
+
+	popl	%edi
+	popl	%esi
+	incl	%esi
+
+	shlb	$1,%al
+	cmpb	$16,%al
+	jnz		LPlaneLoop
+
+	subl	$4,%esi
+	addl	LBlockSrcStep,%esi
+	addl	LBlockDestStep,%edi
+	decl	%ebp
+	jnz		LRowLoop
+
+	popl	%ebx				// restore register variables
+	popl	%esi
+	popl	%edi
+	popl	%ebp				// restore the caller's stack frame
+
+	ret
+
+
+#define srcptr			4+16
+#define destptr			8+16
+#define width			12+16
+#define height			16+16
+#define srcrowbytes		20+16
+#define destrowbytes	24+16
+
+.globl C(VGA_UpdateLinearScreen)
+C(VGA_UpdateLinearScreen):
+	pushl	%ebp				// preserve caller's stack frame
+	pushl	%edi
+	pushl	%esi				// preserve register variables
+	pushl	%ebx
+
+	cld
+	movl	srcptr(%esp),%esi
+	movl	destptr(%esp),%edi
+	movl	width(%esp),%ebx
+	movl	srcrowbytes(%esp),%eax
+	subl	%ebx,%eax
+	movl	destrowbytes(%esp),%edx
+	subl	%ebx,%edx
+	shrl	$2,%ebx
+	movl	height(%esp),%ebp
+LLRowLoop:
+	movl	%ebx,%ecx
+	rep/movsl	(%esi),(%edi)
+	addl	%eax,%esi
+	addl	%edx,%edi
+	decl	%ebp
+	jnz		LLRowLoop
+
+	popl	%ebx				// restore register variables
+	popl	%esi
+	popl	%edi
+	popl	%ebp				// restore the caller's stack frame
+
+	ret
+
--- /dev/null
+++ b/QW/client/d_draw.asm
@@ -1,0 +1,949 @@
+ .386P
+ .model FLAT
+ externdef _d_zistepu:dword
+ externdef _d_pzbuffer:dword
+ externdef _d_zistepv:dword
+ externdef _d_zrowbytes:dword
+ externdef _d_ziorigin:dword
+ externdef _r_turb_s:dword
+ externdef _r_turb_t:dword
+ externdef _r_turb_pdest:dword
+ externdef _r_turb_spancount:dword
+ externdef _r_turb_turb:dword
+ externdef _r_turb_pbase:dword
+ externdef _r_turb_sstep:dword
+ externdef _r_turb_tstep:dword
+ externdef _r_bmodelactive:dword
+ externdef _d_sdivzstepu:dword
+ externdef _d_tdivzstepu:dword
+ externdef _d_sdivzstepv:dword
+ externdef _d_tdivzstepv:dword
+ externdef _d_sdivzorigin:dword
+ externdef _d_tdivzorigin:dword
+ externdef _sadjust:dword
+ externdef _tadjust:dword
+ externdef _bbextents:dword
+ externdef _bbextentt:dword
+ externdef _cacheblock:dword
+ externdef _d_viewbuffer:dword
+ externdef _cachewidth:dword
+ externdef _d_pzbuffer:dword
+ externdef _d_zrowbytes:dword
+ externdef _d_zwidth:dword
+ externdef _d_scantable:dword
+ externdef _r_lightptr:dword
+ externdef _r_numvblocks:dword
+ externdef _prowdestbase:dword
+ externdef _pbasesource:dword
+ externdef _r_lightwidth:dword
+ externdef _lightright:dword
+ externdef _lightrightstep:dword
+ externdef _lightdeltastep:dword
+ externdef _lightdelta:dword
+ externdef _lightright:dword
+ externdef _lightdelta:dword
+ externdef _sourcetstep:dword
+ externdef _surfrowbytes:dword
+ externdef _lightrightstep:dword
+ externdef _lightdeltastep:dword
+ externdef _r_sourcemax:dword
+ externdef _r_stepback:dword
+ externdef _colormap:dword
+ externdef _blocksize:dword
+ externdef _sourcesstep:dword
+ externdef _lightleft:dword
+ externdef _blockdivshift:dword
+ externdef _blockdivmask:dword
+ externdef _lightleftstep:dword
+ externdef _r_origin:dword
+ externdef _r_ppn:dword
+ externdef _r_pup:dword
+ externdef _r_pright:dword
+ externdef _ycenter:dword
+ externdef _xcenter:dword
+ externdef _d_vrectbottom_particle:dword
+ externdef _d_vrectright_particle:dword
+ externdef _d_vrecty:dword
+ externdef _d_vrectx:dword
+ externdef _d_pix_shift:dword
+ externdef _d_pix_min:dword
+ externdef _d_pix_max:dword
+ externdef _d_y_aspect_shift:dword
+ externdef _screenwidth:dword
+ externdef _vright:dword
+ externdef _vup:dword
+ externdef _vpn:dword
+ externdef _BOPS_Error:dword
+ externdef _snd_scaletable:dword
+ externdef _paintbuffer:dword
+ externdef _snd_linear_count:dword
+ externdef _snd_p:dword
+ externdef _snd_vol:dword
+ externdef _snd_out:dword
+ externdef _r_leftclipped:dword
+ externdef _r_leftenter:dword
+ externdef _r_rightclipped:dword
+ externdef _r_rightenter:dword
+ externdef _modelorg:dword
+ externdef _xscale:dword
+ externdef _r_refdef:dword
+ externdef _yscale:dword
+ externdef _r_leftexit:dword
+ externdef _r_rightexit:dword
+ externdef _r_lastvertvalid:dword
+ externdef _cacheoffset:dword
+ externdef _newedges:dword
+ externdef _removeedges:dword
+ externdef _r_pedge:dword
+ externdef _r_framecount:dword
+ externdef _r_u1:dword
+ externdef _r_emitted:dword
+ externdef _edge_p:dword
+ externdef _surface_p:dword
+ externdef _surfaces:dword
+ externdef _r_lzi1:dword
+ externdef _r_v1:dword
+ externdef _r_ceilv1:dword
+ externdef _r_nearzi:dword
+ externdef _r_nearzionly:dword
+ externdef _edge_aftertail:dword
+ externdef _edge_tail:dword
+ externdef _current_iv:dword
+ externdef _edge_head_u_shift20:dword
+ externdef _span_p:dword
+ externdef _edge_head:dword
+ externdef _fv:dword
+ externdef _edge_tail_u_shift20:dword
+ externdef _r_apverts:dword
+ externdef _r_anumverts:dword
+ externdef _aliastransform:dword
+ externdef _r_avertexnormals:dword
+ externdef _r_plightvec:dword
+ externdef _r_ambientlight:dword
+ externdef _r_shadelight:dword
+ externdef _aliasxcenter:dword
+ externdef _aliasycenter:dword
+ externdef _a_sstepxfrac:dword
+ externdef _r_affinetridesc:dword
+ externdef _acolormap:dword
+ externdef _d_pcolormap:dword
+ externdef _r_affinetridesc:dword
+ externdef _d_sfrac:dword
+ externdef _d_ptex:dword
+ externdef _d_pedgespanpackage:dword
+ externdef _d_tfrac:dword
+ externdef _d_light:dword
+ externdef _d_zi:dword
+ externdef _d_pdest:dword
+ externdef _d_pz:dword
+ externdef _d_aspancount:dword
+ externdef _erroradjustup:dword
+ externdef _errorterm:dword
+ externdef _d_xdenom:dword
+ externdef _r_p0:dword
+ externdef _r_p1:dword
+ externdef _r_p2:dword
+ externdef _a_tstepxfrac:dword
+ externdef _r_sstepx:dword
+ externdef _r_tstepx:dword
+ externdef _a_ststepxwhole:dword
+ externdef _zspantable:dword
+ externdef _skintable:dword
+ externdef _r_zistepx:dword
+ externdef _erroradjustdown:dword
+ externdef _d_countextrastep:dword
+ externdef _ubasestep:dword
+ externdef _a_ststepxwhole:dword
+ externdef _a_tstepxfrac:dword
+ externdef _r_lstepx:dword
+ externdef _a_spans:dword
+ externdef _erroradjustdown:dword
+ externdef _d_pdestextrastep:dword
+ externdef _d_pzextrastep:dword
+ externdef _d_sfracextrastep:dword
+ externdef _d_ptexextrastep:dword
+ externdef _d_countextrastep:dword
+ externdef _d_tfracextrastep:dword
+ externdef _d_lightextrastep:dword
+ externdef _d_ziextrastep:dword
+ externdef _d_pdestbasestep:dword
+ externdef _d_pzbasestep:dword
+ externdef _d_sfracbasestep:dword
+ externdef _d_ptexbasestep:dword
+ externdef _ubasestep:dword
+ externdef _d_tfracbasestep:dword
+ externdef _d_lightbasestep:dword
+ externdef _d_zibasestep:dword
+ externdef _zspantable:dword
+ externdef _r_lstepy:dword
+ externdef _r_sstepy:dword
+ externdef _r_tstepy:dword
+ externdef _r_zistepy:dword
+ externdef _D_PolysetSetEdgeTable:dword
+ externdef _D_RasterizeAliasPolySmooth:dword
+ externdef float_point5:dword
+ externdef Float2ToThe31nd:dword
+ externdef izistep:dword
+ externdef izi:dword
+ externdef FloatMinus2ToThe31nd:dword
+ externdef float_1:dword
+ externdef float_particle_z_clip:dword
+ externdef float_minus_1:dword
+ externdef float_0:dword
+ externdef fp_16:dword
+ externdef fp_64k:dword
+ externdef fp_1m:dword
+ externdef fp_1m_minus_1:dword
+ externdef fp_8:dword
+ externdef entryvec_table:dword
+ externdef advancetable:dword
+ externdef sstep:dword
+ externdef tstep:dword
+ externdef pspantemp:dword
+ externdef counttemp:dword
+ externdef jumptemp:dword
+ externdef reciprocal_table:dword
+ externdef DP_Count:dword
+ externdef DP_u:dword
+ externdef DP_v:dword
+ externdef DP_32768:dword
+ externdef DP_Color:dword
+ externdef DP_Pix:dword
+ externdef DP_EntryTable:dword
+ externdef pbase:dword
+ externdef s:dword
+ externdef t:dword
+ externdef sfracf:dword
+ externdef tfracf:dword
+ externdef snext:dword
+ externdef tnext:dword
+ externdef spancountminus1:dword
+ externdef zi16stepu:dword
+ externdef sdivz16stepu:dword
+ externdef tdivz16stepu:dword
+ externdef zi8stepu:dword
+ externdef sdivz8stepu:dword
+ externdef tdivz8stepu:dword
+ externdef reciprocal_table_16:dword
+ externdef entryvec_table_16:dword
+ externdef ceil_cw:dword
+ externdef single_cw:dword
+ externdef fp_64kx64k:dword
+ externdef pz:dword
+ externdef spr8entryvec_table:dword
+_TEXT SEGMENT
+LClampHigh0:
+ mov esi,ds:dword ptr[_bbextents]
+ jmp LClampReentry0
+LClampHighOrLow0:
+ jg LClampHigh0
+ xor esi,esi
+ jmp LClampReentry0
+LClampHigh1:
+ mov edx,ds:dword ptr[_bbextentt]
+ jmp LClampReentry1
+LClampHighOrLow1:
+ jg LClampHigh1
+ xor edx,edx
+ jmp LClampReentry1
+LClampLow2:
+ mov ebp,2048
+ jmp LClampReentry2
+LClampHigh2:
+ mov ebp,ds:dword ptr[_bbextents]
+ jmp LClampReentry2
+LClampLow3:
+ mov ecx,2048
+ jmp LClampReentry3
+LClampHigh3:
+ mov ecx,ds:dword ptr[_bbextentt]
+ jmp LClampReentry3
+LClampLow4:
+ mov eax,2048
+ jmp LClampReentry4
+LClampHigh4:
+ mov eax,ds:dword ptr[_bbextents]
+ jmp LClampReentry4
+LClampLow5:
+ mov ebx,2048
+ jmp LClampReentry5
+LClampHigh5:
+ mov ebx,ds:dword ptr[_bbextentt]
+ jmp LClampReentry5
+ align 4
+ public _D_DrawSpans8
+_D_DrawSpans8:
+ push ebp
+ push edi
+ push esi
+ push ebx
+ fld ds:dword ptr[_d_sdivzstepu]
+ fmul ds:dword ptr[fp_8]
+ mov edx,ds:dword ptr[_cacheblock]
+ fld ds:dword ptr[_d_tdivzstepu]
+ fmul ds:dword ptr[fp_8]
+ mov ebx,ds:dword ptr[4+16+esp]
+ fld ds:dword ptr[_d_zistepu]
+ fmul ds:dword ptr[fp_8]
+ mov ds:dword ptr[pbase],edx
+ fstp ds:dword ptr[zi8stepu]
+ fstp ds:dword ptr[tdivz8stepu]
+ fstp ds:dword ptr[sdivz8stepu]
+LSpanLoop:
+ fild ds:dword ptr[4+ebx]
+ fild ds:dword ptr[0+ebx]
+ fld st(1)
+ fmul ds:dword ptr[_d_sdivzstepv]
+ fld st(1)
+ fmul ds:dword ptr[_d_sdivzstepu]
+ fld st(2)
+ fmul ds:dword ptr[_d_tdivzstepu]
+ fxch st(1)
+ faddp st(2),st(0)
+ fxch st(1)
+ fld st(3)
+ fmul ds:dword ptr[_d_tdivzstepv]
+ fxch st(1)
+ fadd ds:dword ptr[_d_sdivzorigin]
+ fxch st(4)
+ fmul ds:dword ptr[_d_zistepv]
+ fxch st(1)
+ faddp st(2),st(0)
+ fxch st(2)
+ fmul ds:dword ptr[_d_zistepu]
+ fxch st(1)
+ fadd ds:dword ptr[_d_tdivzorigin]
+ fxch st(2)
+ faddp st(1),st(0)
+ fld ds:dword ptr[fp_64k]
+ fxch st(1)
+ fadd ds:dword ptr[_d_ziorigin]
+ fdiv st(1),st(0)
+ mov ecx,ds:dword ptr[_d_viewbuffer]
+ mov eax,ds:dword ptr[4+ebx]
+ mov ds:dword ptr[pspantemp],ebx
+ mov edx,ds:dword ptr[_tadjust]
+ mov esi,ds:dword ptr[_sadjust]
+ mov edi,ds:dword ptr[_d_scantable+eax*4]
+ add edi,ecx
+ mov ecx,ds:dword ptr[0+ebx]
+ add edi,ecx
+ mov ecx,ds:dword ptr[8+ebx]
+ cmp ecx,8
+ ja LSetupNotLast1
+ dec ecx
+ jz LCleanup1
+ mov ds:dword ptr[spancountminus1],ecx
+ fxch st(1)
+ fld st(0)
+ fmul st(0),st(4)
+ fxch st(1)
+ fmul st(0),st(3)
+ fxch st(1)
+ fistp ds:dword ptr[s]
+ fistp ds:dword ptr[t]
+ fild ds:dword ptr[spancountminus1]
+ fld ds:dword ptr[_d_tdivzstepu]
+ fld ds:dword ptr[_d_zistepu]
+ fmul st(0),st(2)
+ fxch st(1)
+ fmul st(0),st(2)
+ fxch st(2)
+ fmul ds:dword ptr[_d_sdivzstepu]
+ fxch st(1)
+ faddp st(3),st(0)
+ fxch st(1)
+ faddp st(3),st(0)
+ faddp st(3),st(0)
+ fld ds:dword ptr[fp_64k]
+ fdiv st(0),st(1)
+ jmp LFDIVInFlight1
+LCleanup1:
+ fxch st(1)
+ fld st(0)
+ fmul st(0),st(4)
+ fxch st(1)
+ fmul st(0),st(3)
+ fxch st(1)
+ fistp ds:dword ptr[s]
+ fistp ds:dword ptr[t]
+ jmp LFDIVInFlight1
+ align 4
+LSetupNotLast1:
+ fxch st(1)
+ fld st(0)
+ fmul st(0),st(4)
+ fxch st(1)
+ fmul st(0),st(3)
+ fxch st(1)
+ fistp ds:dword ptr[s]
+ fistp ds:dword ptr[t]
+ fadd ds:dword ptr[zi8stepu]
+ fxch st(2)
+ fadd ds:dword ptr[sdivz8stepu]
+ fxch st(2)
+ fld ds:dword ptr[tdivz8stepu]
+ faddp st(2),st(0)
+ fld ds:dword ptr[fp_64k]
+ fdiv st(0),st(1)
+LFDIVInFlight1:
+ add esi,ds:dword ptr[s]
+ add edx,ds:dword ptr[t]
+ mov ebx,ds:dword ptr[_bbextents]
+ mov ebp,ds:dword ptr[_bbextentt]
+ cmp esi,ebx
+ ja LClampHighOrLow0
+LClampReentry0:
+ mov ds:dword ptr[s],esi
+ mov ebx,ds:dword ptr[pbase]
+ shl esi,16
+ cmp edx,ebp
+ mov ds:dword ptr[sfracf],esi
+ ja LClampHighOrLow1
+LClampReentry1:
+ mov ds:dword ptr[t],edx
+ mov esi,ds:dword ptr[s]
+ shl edx,16
+ mov eax,ds:dword ptr[t]
+ sar esi,16
+ mov ds:dword ptr[tfracf],edx
+ sar eax,16
+ mov edx,ds:dword ptr[_cachewidth]
+ imul eax,edx
+ add esi,ebx
+ add esi,eax
+ cmp ecx,8
+ jna LLastSegment
+LNotLastSegment:
+ fld st(0)
+ fmul st(0),st(4)
+ fxch st(1)
+ fmul st(0),st(3)
+ fxch st(1)
+ fistp ds:dword ptr[snext]
+ fistp ds:dword ptr[tnext]
+ mov eax,ds:dword ptr[snext]
+ mov edx,ds:dword ptr[tnext]
+ mov bl,ds:byte ptr[esi]
+ sub ecx,8
+ mov ebp,ds:dword ptr[_sadjust]
+ mov ds:dword ptr[counttemp],ecx
+ mov ecx,ds:dword ptr[_tadjust]
+ mov ds:byte ptr[edi],bl
+ add ebp,eax
+ add ecx,edx
+ mov eax,ds:dword ptr[_bbextents]
+ mov edx,ds:dword ptr[_bbextentt]
+ cmp ebp,2048
+ jl LClampLow2
+ cmp ebp,eax
+ ja LClampHigh2
+LClampReentry2:
+ cmp ecx,2048
+ jl LClampLow3
+ cmp ecx,edx
+ ja LClampHigh3
+LClampReentry3:
+ mov ds:dword ptr[snext],ebp
+ mov ds:dword ptr[tnext],ecx
+ sub ebp,ds:dword ptr[s]
+ sub ecx,ds:dword ptr[t]
+ mov eax,ecx
+ mov edx,ebp
+ sar eax,19
+ jz LZero
+ sar edx,19
+ mov ebx,ds:dword ptr[_cachewidth]
+ imul eax,ebx
+ jmp LSetUp1
+LZero:
+ sar edx,19
+ mov ebx,ds:dword ptr[_cachewidth]
+LSetUp1:
+ add eax,edx
+ mov edx,ds:dword ptr[tfracf]
+ mov ds:dword ptr[advancetable+4],eax
+ add eax,ebx
+ shl ebp,13
+ mov ebx,ds:dword ptr[sfracf]
+ shl ecx,13
+ mov ds:dword ptr[advancetable],eax
+ mov ds:dword ptr[tstep],ecx
+ add edx,ecx
+ sbb ecx,ecx
+ add ebx,ebp
+ adc esi,ds:dword ptr[advancetable+4+ecx*4]
+ add edx,ds:dword ptr[tstep]
+ sbb ecx,ecx
+ mov al,ds:byte ptr[esi]
+ add ebx,ebp
+ mov ds:byte ptr[1+edi],al
+ adc esi,ds:dword ptr[advancetable+4+ecx*4]
+ add edx,ds:dword ptr[tstep]
+ sbb ecx,ecx
+ add ebx,ebp
+ mov al,ds:byte ptr[esi]
+ adc esi,ds:dword ptr[advancetable+4+ecx*4]
+ add edx,ds:dword ptr[tstep]
+ sbb ecx,ecx
+ mov ds:byte ptr[2+edi],al
+ add ebx,ebp
+ mov al,ds:byte ptr[esi]
+ adc esi,ds:dword ptr[advancetable+4+ecx*4]
+ add edx,ds:dword ptr[tstep]
+ sbb ecx,ecx
+ mov ds:byte ptr[3+edi],al
+ add ebx,ebp
+ mov al,ds:byte ptr[esi]
+ adc esi,ds:dword ptr[advancetable+4+ecx*4]
+ mov ecx,ds:dword ptr[counttemp]
+ cmp ecx,8
+ ja LSetupNotLast2
+ dec ecx
+ jz LFDIVInFlight2
+ mov ds:dword ptr[spancountminus1],ecx
+ fild ds:dword ptr[spancountminus1]
+ fld ds:dword ptr[_d_zistepu]
+ fmul st(0),st(1)
+ fld ds:dword ptr[_d_tdivzstepu]
+ fmul st(0),st(2)
+ fxch st(1)
+ faddp st(3),st(0)
+ fxch st(1)
+ fmul ds:dword ptr[_d_sdivzstepu]
+ fxch st(1)
+ faddp st(3),st(0)
+ fld ds:dword ptr[fp_64k]
+ fxch st(1)
+ faddp st(4),st(0)
+ fdiv st(0),st(1)
+ jmp LFDIVInFlight2
+ align 4
+LSetupNotLast2:
+ fadd ds:dword ptr[zi8stepu]
+ fxch st(2)
+ fadd ds:dword ptr[sdivz8stepu]
+ fxch st(2)
+ fld ds:dword ptr[tdivz8stepu]
+ faddp st(2),st(0)
+ fld ds:dword ptr[fp_64k]
+ fdiv st(0),st(1)
+LFDIVInFlight2:
+ mov ds:dword ptr[counttemp],ecx
+ add edx,ds:dword ptr[tstep]
+ sbb ecx,ecx
+ mov ds:byte ptr[4+edi],al
+ add ebx,ebp
+ mov al,ds:byte ptr[esi]
+ adc esi,ds:dword ptr[advancetable+4+ecx*4]
+ add edx,ds:dword ptr[tstep]
+ sbb ecx,ecx
+ mov ds:byte ptr[5+edi],al
+ add ebx,ebp
+ mov al,ds:byte ptr[esi]
+ adc esi,ds:dword ptr[advancetable+4+ecx*4]
+ add edx,ds:dword ptr[tstep]
+ sbb ecx,ecx
+ mov ds:byte ptr[6+edi],al
+ add ebx,ebp
+ mov al,ds:byte ptr[esi]
+ adc esi,ds:dword ptr[advancetable+4+ecx*4]
+ add edi,8
+ mov ds:dword ptr[tfracf],edx
+ mov edx,ds:dword ptr[snext]
+ mov ds:dword ptr[sfracf],ebx
+ mov ebx,ds:dword ptr[tnext]
+ mov ds:dword ptr[s],edx
+ mov ds:dword ptr[t],ebx
+ mov ecx,ds:dword ptr[counttemp]
+ cmp ecx,8
+ mov ds:byte ptr[-1+edi],al
+ ja LNotLastSegment
+LLastSegment:
+ test ecx,ecx
+ jz LNoSteps
+ fld st(0)
+ fmul st(0),st(4)
+ fxch st(1)
+ fmul st(0),st(3)
+ fxch st(1)
+ fistp ds:dword ptr[snext]
+ fistp ds:dword ptr[tnext]
+ mov al,ds:byte ptr[esi]
+ mov ebx,ds:dword ptr[_tadjust]
+ mov ds:byte ptr[edi],al
+ mov eax,ds:dword ptr[_sadjust]
+ add eax,ds:dword ptr[snext]
+ add ebx,ds:dword ptr[tnext]
+ mov ebp,ds:dword ptr[_bbextents]
+ mov edx,ds:dword ptr[_bbextentt]
+ cmp eax,2048
+ jl LClampLow4
+ cmp eax,ebp
+ ja LClampHigh4
+LClampReentry4:
+ mov ds:dword ptr[snext],eax
+ cmp ebx,2048
+ jl LClampLow5
+ cmp ebx,edx
+ ja LClampHigh5
+LClampReentry5:
+ cmp ecx,1
+ je LOnlyOneStep
+ sub eax,ds:dword ptr[s]
+ sub ebx,ds:dword ptr[t]
+ add eax,eax
+ add ebx,ebx
+ imul ds:dword ptr[reciprocal_table-8+ecx*4]
+ mov ebp,edx
+ mov eax,ebx
+ imul ds:dword ptr[reciprocal_table-8+ecx*4]
+LSetEntryvec:
+ mov ebx,ds:dword ptr[entryvec_table+ecx*4]
+ mov eax,edx
+ mov ds:dword ptr[jumptemp],ebx
+ mov ecx,ebp
+ sar edx,16
+ mov ebx,ds:dword ptr[_cachewidth]
+ sar ecx,16
+ imul edx,ebx
+ add edx,ecx
+ mov ecx,ds:dword ptr[tfracf]
+ mov ds:dword ptr[advancetable+4],edx
+ add edx,ebx
+ shl ebp,16
+ mov ebx,ds:dword ptr[sfracf]
+ shl eax,16
+ mov ds:dword ptr[advancetable],edx
+ mov ds:dword ptr[tstep],eax
+ mov edx,ecx
+ add edx,eax
+ sbb ecx,ecx
+ add ebx,ebp
+ adc esi,ds:dword ptr[advancetable+4+ecx*4]
+ jmp dword ptr[jumptemp]
+LNoSteps:
+ mov al,ds:byte ptr[esi]
+ sub edi,7
+ jmp LEndSpan
+LOnlyOneStep:
+ sub eax,ds:dword ptr[s]
+ sub ebx,ds:dword ptr[t]
+ mov ebp,eax
+ mov edx,ebx
+ jmp LSetEntryvec
+ public Entry2_8
+Entry2_8:
+ sub edi,6
+ mov al,ds:byte ptr[esi]
+ jmp LLEntry2_8
+ public Entry3_8
+Entry3_8:
+ sub edi,5
+ add edx,eax
+ mov al,ds:byte ptr[esi]
+ sbb ecx,ecx
+ add ebx,ebp
+ adc esi,ds:dword ptr[advancetable+4+ecx*4]
+ jmp LLEntry3_8
+ public Entry4_8
+Entry4_8:
+ sub edi,4
+ add edx,eax
+ mov al,ds:byte ptr[esi]
+ sbb ecx,ecx
+ add ebx,ebp
+ adc esi,ds:dword ptr[advancetable+4+ecx*4]
+ add edx,ds:dword ptr[tstep]
+ jmp LLEntry4_8
+ public Entry5_8
+Entry5_8:
+ sub edi,3
+ add edx,eax
+ mov al,ds:byte ptr[esi]
+ sbb ecx,ecx
+ add ebx,ebp
+ adc esi,ds:dword ptr[advancetable+4+ecx*4]
+ add edx,ds:dword ptr[tstep]
+ jmp LLEntry5_8
+ public Entry6_8
+Entry6_8:
+ sub edi,2
+ add edx,eax
+ mov al,ds:byte ptr[esi]
+ sbb ecx,ecx
+ add ebx,ebp
+ adc esi,ds:dword ptr[advancetable+4+ecx*4]
+ add edx,ds:dword ptr[tstep]
+ jmp LLEntry6_8
+ public Entry7_8
+Entry7_8:
+ dec edi
+ add edx,eax
+ mov al,ds:byte ptr[esi]
+ sbb ecx,ecx
+ add ebx,ebp
+ adc esi,ds:dword ptr[advancetable+4+ecx*4]
+ add edx,ds:dword ptr[tstep]
+ jmp LLEntry7_8
+ public Entry8_8
+Entry8_8:
+ add edx,eax
+ mov al,ds:byte ptr[esi]
+ sbb ecx,ecx
+ add ebx,ebp
+ adc esi,ds:dword ptr[advancetable+4+ecx*4]
+ add edx,ds:dword ptr[tstep]
+ sbb ecx,ecx
+ mov ds:byte ptr[1+edi],al
+ add ebx,ebp
+ mov al,ds:byte ptr[esi]
+ adc esi,ds:dword ptr[advancetable+4+ecx*4]
+ add edx,ds:dword ptr[tstep]
+LLEntry7_8:
+ sbb ecx,ecx
+ mov ds:byte ptr[2+edi],al
+ add ebx,ebp
+ mov al,ds:byte ptr[esi]
+ adc esi,ds:dword ptr[advancetable+4+ecx*4]
+ add edx,ds:dword ptr[tstep]
+LLEntry6_8:
+ sbb ecx,ecx
+ mov ds:byte ptr[3+edi],al
+ add ebx,ebp
+ mov al,ds:byte ptr[esi]
+ adc esi,ds:dword ptr[advancetable+4+ecx*4]
+ add edx,ds:dword ptr[tstep]
+LLEntry5_8:
+ sbb ecx,ecx
+ mov ds:byte ptr[4+edi],al
+ add ebx,ebp
+ mov al,ds:byte ptr[esi]
+ adc esi,ds:dword ptr[advancetable+4+ecx*4]
+ add edx,ds:dword ptr[tstep]
+LLEntry4_8:
+ sbb ecx,ecx
+ mov ds:byte ptr[5+edi],al
+ add ebx,ebp
+ mov al,ds:byte ptr[esi]
+ adc esi,ds:dword ptr[advancetable+4+ecx*4]
+LLEntry3_8:
+ mov ds:byte ptr[6+edi],al
+ mov al,ds:byte ptr[esi]
+LLEntry2_8:
+LEndSpan:
+ fstp st(0)
+ fstp st(0)
+ fstp st(0)
+ mov ebx,ds:dword ptr[pspantemp]
+ mov ebx,ds:dword ptr[12+ebx]
+ test ebx,ebx
+ mov ds:byte ptr[7+edi],al
+ jnz LSpanLoop
+ pop ebx
+ pop esi
+ pop edi
+ pop ebp
+ ret
+
+LClamp:
+ mov edx,040000000h
+ xor ebx,ebx
+ fstp st(0)
+ jmp LZDraw
+LClampNeg:
+ mov edx,040000000h
+ xor ebx,ebx
+ fstp st(0)
+ jmp LZDrawNeg
+ public _D_DrawZSpans
+_D_DrawZSpans:
+ push ebp
+ push edi
+ push esi
+ push ebx
+ fld ds:dword ptr[_d_zistepu]
+ mov eax,ds:dword ptr[_d_zistepu]
+ mov esi,ds:dword ptr[4+16+esp]
+ test eax,eax
+ jz LFNegSpan
+ fmul ds:dword ptr[Float2ToThe31nd]
+ fistp ds:dword ptr[izistep]
+ mov ebx,ds:dword ptr[izistep]
+LFSpanLoop:
+ fild ds:dword ptr[4+esi]
+ fild ds:dword ptr[0+esi]
+ mov ecx,ds:dword ptr[4+esi]
+ mov edi,ds:dword ptr[_d_pzbuffer]
+ fmul ds:dword ptr[_d_zistepu]
+ fxch st(1)
+ fmul ds:dword ptr[_d_zistepv]
+ fxch st(1)
+ fadd ds:dword ptr[_d_ziorigin]
+ imul ecx,ds:dword ptr[_d_zrowbytes]
+ faddp st(1),st(0)
+ fcom ds:dword ptr[float_point5]
+ add edi,ecx
+ mov edx,ds:dword ptr[0+esi]
+ add edx,edx
+ mov ecx,ds:dword ptr[8+esi]
+ add edi,edx
+ push esi
+ fnstsw ax
+ test ah,045h
+ jz LClamp
+ fmul ds:dword ptr[Float2ToThe31nd]
+ fistp ds:dword ptr[izi]
+ mov edx,ds:dword ptr[izi]
+LZDraw:
+ test edi,2
+ jz LFMiddle
+ mov eax,edx
+ add edx,ebx
+ shr eax,16
+ dec ecx
+ mov ds:word ptr[edi],ax
+ add edi,2
+LFMiddle:
+ push ecx
+ shr ecx,1
+ jz LFLast
+ shr ecx,1
+ jnc LFMiddleLoop
+ mov eax,edx
+ add edx,ebx
+ shr eax,16
+ mov esi,edx
+ add edx,ebx
+ and esi,0FFFF0000h
+ or eax,esi
+ mov ds:dword ptr[edi],eax
+ add edi,4
+ and ecx,ecx
+ jz LFLast
+LFMiddleLoop:
+ mov eax,edx
+ add edx,ebx
+ shr eax,16
+ mov esi,edx
+ add edx,ebx
+ and esi,0FFFF0000h
+ or eax,esi
+ mov ebp,edx
+ mov ds:dword ptr[edi],eax
+ add edx,ebx
+ shr ebp,16
+ mov esi,edx
+ add edx,ebx
+ and esi,0FFFF0000h
+ or ebp,esi
+ mov ds:dword ptr[4+edi],ebp
+ add edi,8
+ dec ecx
+ jnz LFMiddleLoop
+LFLast:
+ pop ecx
+ pop esi
+ and ecx,1
+ jz LFSpanDone
+ shr edx,16
+ mov ds:word ptr[edi],dx
+LFSpanDone:
+ mov esi,ds:dword ptr[12+esi]
+ test esi,esi
+ jnz LFSpanLoop
+ jmp LFDone
+LFNegSpan:
+ fmul ds:dword ptr[FloatMinus2ToThe31nd]
+ fistp ds:dword ptr[izistep]
+ mov ebx,ds:dword ptr[izistep]
+LFNegSpanLoop:
+ fild ds:dword ptr[4+esi]
+ fild ds:dword ptr[0+esi]
+ mov ecx,ds:dword ptr[4+esi]
+ mov edi,ds:dword ptr[_d_pzbuffer]
+ fmul ds:dword ptr[_d_zistepu]
+ fxch st(1)
+ fmul ds:dword ptr[_d_zistepv]
+ fxch st(1)
+ fadd ds:dword ptr[_d_ziorigin]
+ imul ecx,ds:dword ptr[_d_zrowbytes]
+ faddp st(1),st(0)
+ fcom ds:dword ptr[float_point5]
+ add edi,ecx
+ mov edx,ds:dword ptr[0+esi]
+ add edx,edx
+ mov ecx,ds:dword ptr[8+esi]
+ add edi,edx
+ push esi
+ fnstsw ax
+ test ah,045h
+ jz LClampNeg
+ fmul ds:dword ptr[Float2ToThe31nd]
+ fistp ds:dword ptr[izi]
+ mov edx,ds:dword ptr[izi]
+LZDrawNeg:
+ test edi,2
+ jz LFNegMiddle
+ mov eax,edx
+ sub edx,ebx
+ shr eax,16
+ dec ecx
+ mov ds:word ptr[edi],ax
+ add edi,2
+LFNegMiddle:
+ push ecx
+ shr ecx,1
+ jz LFNegLast
+ shr ecx,1
+ jnc LFNegMiddleLoop
+ mov eax,edx
+ sub edx,ebx
+ shr eax,16
+ mov esi,edx
+ sub edx,ebx
+ and esi,0FFFF0000h
+ or eax,esi
+ mov ds:dword ptr[edi],eax
+ add edi,4
+ and ecx,ecx
+ jz LFNegLast
+LFNegMiddleLoop:
+ mov eax,edx
+ sub edx,ebx
+ shr eax,16
+ mov esi,edx
+ sub edx,ebx
+ and esi,0FFFF0000h
+ or eax,esi
+ mov ebp,edx
+ mov ds:dword ptr[edi],eax
+ sub edx,ebx
+ shr ebp,16
+ mov esi,edx
+ sub edx,ebx
+ and esi,0FFFF0000h
+ or ebp,esi
+ mov ds:dword ptr[4+edi],ebp
+ add edi,8
+ dec ecx
+ jnz LFNegMiddleLoop
+LFNegLast:
+ pop ecx
+ pop esi
+ and ecx,1
+ jz LFNegSpanDone
+ shr edx,16
+ mov ds:word ptr[edi],dx
+LFNegSpanDone:
+ mov esi,ds:dword ptr[12+esi]
+ test esi,esi
+ jnz LFNegSpanLoop
+LFDone:
+ pop ebx
+ pop esi
+ pop edi
+ pop ebp
+ ret
+_TEXT ENDS
+ END
--- /dev/null
+++ b/QW/client/d_draw.s
@@ -1,0 +1,1037 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+//
+// d_draw.s
+// x86 assembly-language horizontal 8-bpp span-drawing code.
+//
+
+#include "asm_i386.h"
+#include "quakeasm.h"
+#include "asm_draw.h"
+#include "d_ifacea.h"
+
+#if	id386
+
+//----------------------------------------------------------------------
+// 8-bpp horizontal span drawing code for polygons, with no transparency.
+//
+// Assumes there is at least one span in pspans, and that every span
+// contains at least one pixel
+//----------------------------------------------------------------------
+
+	.text
+
+// out-of-line, rarely-needed clamping code
+
+LClampHigh0:
+	movl	C(bbextents),%esi
+	jmp		LClampReentry0
+LClampHighOrLow0:
+	jg		LClampHigh0
+	xorl	%esi,%esi
+	jmp		LClampReentry0
+
+LClampHigh1:
+	movl	C(bbextentt),%edx
+	jmp		LClampReentry1
+LClampHighOrLow1:
+	jg		LClampHigh1
+	xorl	%edx,%edx
+	jmp		LClampReentry1
+
+LClampLow2:
+	movl	$2048,%ebp
+	jmp		LClampReentry2
+LClampHigh2:
+	movl	C(bbextents),%ebp
+	jmp		LClampReentry2
+
+LClampLow3:
+	movl	$2048,%ecx
+	jmp		LClampReentry3
+LClampHigh3:
+	movl	C(bbextentt),%ecx
+	jmp		LClampReentry3
+
+LClampLow4:
+	movl	$2048,%eax
+	jmp		LClampReentry4
+LClampHigh4:
+	movl	C(bbextents),%eax
+	jmp		LClampReentry4
+
+LClampLow5:
+	movl	$2048,%ebx
+	jmp		LClampReentry5
+LClampHigh5:
+	movl	C(bbextentt),%ebx
+	jmp		LClampReentry5
+
+
+#define pspans	4+16
+
+	.align 4
+.globl C(D_DrawSpans8)
+C(D_DrawSpans8):
+	pushl	%ebp				// preserve caller's stack frame
+	pushl	%edi
+	pushl	%esi				// preserve register variables
+	pushl	%ebx
+
+//
+// set up scaled-by-8 steps, for 8-long segments; also set up cacheblock
+// and span list pointers
+//
+// TODO: any overlap from rearranging?
+	flds	C(d_sdivzstepu)
+	fmuls	fp_8
+	movl	C(cacheblock),%edx
+	flds	C(d_tdivzstepu)
+	fmuls	fp_8
+	movl	pspans(%esp),%ebx	// point to the first span descriptor
+	flds	C(d_zistepu)
+	fmuls	fp_8
+	movl	%edx,pbase			// pbase = cacheblock
+	fstps	zi8stepu
+	fstps	tdivz8stepu
+	fstps	sdivz8stepu
+
+LSpanLoop:
+//
+// set up the initial s/z, t/z, and 1/z on the FP stack, and generate the
+// initial s and t values
+//
+// FIXME: pipeline FILD?
+	fildl	espan_t_v(%ebx)
+	fildl	espan_t_u(%ebx)
+
+	fld		%st(1)			// dv | du | dv
+	fmuls	C(d_sdivzstepv)	// dv*d_sdivzstepv | du | dv
+	fld		%st(1)			// du | dv*d_sdivzstepv | du | dv
+	fmuls	C(d_sdivzstepu)	// du*d_sdivzstepu | dv*d_sdivzstepv | du | dv
+	fld		%st(2)			// du | du*d_sdivzstepu | dv*d_sdivzstepv | du | dv
+	fmuls	C(d_tdivzstepu)	// du*d_tdivzstepu | du*d_sdivzstepu |
+							//  dv*d_sdivzstepv | du | dv
+	fxch	%st(1)			// du*d_sdivzstepu | du*d_tdivzstepu |
+							//  dv*d_sdivzstepv | du | dv
+	faddp	%st(0),%st(2)	// du*d_tdivzstepu |
+							//  du*d_sdivzstepu + dv*d_sdivzstepv | du | dv
+	fxch	%st(1)			// du*d_sdivzstepu + dv*d_sdivzstepv |
+							//  du*d_tdivzstepu | du | dv
+	fld		%st(3)			// dv | du*d_sdivzstepu + dv*d_sdivzstepv |
+							//  du*d_tdivzstepu | du | dv
+	fmuls	C(d_tdivzstepv)	// dv*d_tdivzstepv |
+							//  du*d_sdivzstepu + dv*d_sdivzstepv |
+							//  du*d_tdivzstepu | du | dv
+	fxch	%st(1)			// du*d_sdivzstepu + dv*d_sdivzstepv |
+							//  dv*d_tdivzstepv | du*d_tdivzstepu | du | dv
+	fadds	C(d_sdivzorigin)	// sdivz = d_sdivzorigin + dv*d_sdivzstepv +
+							//  du*d_sdivzstepu; stays in %st(2) at end
+	fxch	%st(4)			// dv | dv*d_tdivzstepv | du*d_tdivzstepu | du |
+							//  s/z
+	fmuls	C(d_zistepv)		// dv*d_zistepv | dv*d_tdivzstepv |
+							//  du*d_tdivzstepu | du | s/z
+	fxch	%st(1)			// dv*d_tdivzstepv |  dv*d_zistepv |
+							//  du*d_tdivzstepu | du | s/z
+	faddp	%st(0),%st(2)	// dv*d_zistepv |
+							//  dv*d_tdivzstepv + du*d_tdivzstepu | du | s/z
+	fxch	%st(2)			// du | dv*d_tdivzstepv + du*d_tdivzstepu |
+							//  dv*d_zistepv | s/z
+	fmuls	C(d_zistepu)		// du*d_zistepu |
+							//  dv*d_tdivzstepv + du*d_tdivzstepu |
+							//  dv*d_zistepv | s/z
+	fxch	%st(1)			// dv*d_tdivzstepv + du*d_tdivzstepu |
+							//  du*d_zistepu | dv*d_zistepv | s/z
+	fadds	C(d_tdivzorigin)	// tdivz = d_tdivzorigin + dv*d_tdivzstepv +
+							//  du*d_tdivzstepu; stays in %st(1) at end
+	fxch	%st(2)			// dv*d_zistepv | du*d_zistepu | t/z | s/z
+	faddp	%st(0),%st(1)	// dv*d_zistepv + du*d_zistepu | t/z | s/z
+
+	flds	fp_64k			// fp_64k | dv*d_zistepv + du*d_zistepu | t/z | s/z
+	fxch	%st(1)			// dv*d_zistepv + du*d_zistepu | fp_64k | t/z | s/z
+	fadds	C(d_ziorigin)		// zi = d_ziorigin + dv*d_zistepv +
+							//  du*d_zistepu; stays in %st(0) at end
+							// 1/z | fp_64k | t/z | s/z
+//
+// calculate and clamp s & t
+//
+	fdivr	%st(0),%st(1)	// 1/z | z*64k | t/z | s/z
+
+//
+// point %edi to the first pixel in the span
+//
+	movl	C(d_viewbuffer),%ecx
+	movl	espan_t_v(%ebx),%eax
+	movl	%ebx,pspantemp	// preserve spans pointer
+
+	movl	C(tadjust),%edx
+	movl	C(sadjust),%esi
+	movl	C(d_scantable)(,%eax,4),%edi	// v * screenwidth
+	addl	%ecx,%edi
+	movl	espan_t_u(%ebx),%ecx
+	addl	%ecx,%edi				// pdest = &pdestspan[scans->u];
+	movl	espan_t_count(%ebx),%ecx
+
+//
+// now start the FDIV for the end of the span
+//
+	cmpl	$8,%ecx
+	ja		LSetupNotLast1
+
+	decl	%ecx
+	jz		LCleanup1		// if only one pixel, no need to start an FDIV
+	movl	%ecx,spancountminus1
+
+// finish up the s and t calcs
+	fxch	%st(1)			// z*64k | 1/z | t/z | s/z
+
+	fld		%st(0)			// z*64k | z*64k | 1/z | t/z | s/z
+	fmul	%st(4),%st(0)	// s | z*64k | 1/z | t/z | s/z
+	fxch	%st(1)			// z*64k | s | 1/z | t/z | s/z
+	fmul	%st(3),%st(0)	// t | s | 1/z | t/z | s/z
+	fxch	%st(1)			// s | t | 1/z | t/z | s/z
+	fistpl	s				// 1/z | t | t/z | s/z
+	fistpl	t				// 1/z | t/z | s/z
+
+	fildl	spancountminus1
+
+	flds	C(d_tdivzstepu)	// C(d_tdivzstepu) | spancountminus1
+	flds	C(d_zistepu)		// C(d_zistepu) | C(d_tdivzstepu) | spancountminus1
+	fmul	%st(2),%st(0)	// C(d_zistepu)*scm1 | C(d_tdivzstepu) | scm1
+	fxch	%st(1)			// C(d_tdivzstepu) | C(d_zistepu)*scm1 | scm1
+	fmul	%st(2),%st(0)	// C(d_tdivzstepu)*scm1 | C(d_zistepu)*scm1 | scm1
+	fxch	%st(2)			// scm1 | C(d_zistepu)*scm1 | C(d_tdivzstepu)*scm1
+	fmuls	C(d_sdivzstepu)	// C(d_sdivzstepu)*scm1 | C(d_zistepu)*scm1 |
+							//  C(d_tdivzstepu)*scm1
+	fxch	%st(1)			// C(d_zistepu)*scm1 | C(d_sdivzstepu)*scm1 |
+							//  C(d_tdivzstepu)*scm1
+	faddp	%st(0),%st(3)	// C(d_sdivzstepu)*scm1 | C(d_tdivzstepu)*scm1
+	fxch	%st(1)			// C(d_tdivzstepu)*scm1 | C(d_sdivzstepu)*scm1
+	faddp	%st(0),%st(3)	// C(d_sdivzstepu)*scm1
+	faddp	%st(0),%st(3)
+
+	flds	fp_64k
+	fdiv	%st(1),%st(0)	// this is what we've gone to all this trouble to
+							//  overlap
+	jmp		LFDIVInFlight1
+
+LCleanup1:
+// finish up the s and t calcs
+	fxch	%st(1)			// z*64k | 1/z | t/z | s/z
+
+	fld		%st(0)			// z*64k | z*64k | 1/z | t/z | s/z
+	fmul	%st(4),%st(0)	// s | z*64k | 1/z | t/z | s/z
+	fxch	%st(1)			// z*64k | s | 1/z | t/z | s/z
+	fmul	%st(3),%st(0)	// t | s | 1/z | t/z | s/z
+	fxch	%st(1)			// s | t | 1/z | t/z | s/z
+	fistpl	s				// 1/z | t | t/z | s/z
+	fistpl	t				// 1/z | t/z | s/z
+	jmp		LFDIVInFlight1
+
+	.align	4
+LSetupNotLast1:
+// finish up the s and t calcs
+	fxch	%st(1)			// z*64k | 1/z | t/z | s/z
+
+	fld		%st(0)			// z*64k | z*64k | 1/z | t/z | s/z
+	fmul	%st(4),%st(0)	// s | z*64k | 1/z | t/z | s/z
+	fxch	%st(1)			// z*64k | s | 1/z | t/z | s/z
+	fmul	%st(3),%st(0)	// t | s | 1/z | t/z | s/z
+	fxch	%st(1)			// s | t | 1/z | t/z | s/z
+	fistpl	s				// 1/z | t | t/z | s/z
+	fistpl	t				// 1/z | t/z | s/z
+
+	fadds	zi8stepu
+	fxch	%st(2)
+	fadds	sdivz8stepu
+	fxch	%st(2)
+	flds	tdivz8stepu
+	faddp	%st(0),%st(2)
+	flds	fp_64k
+	fdiv	%st(1),%st(0)	// z = 1/1/z
+							// this is what we've gone to all this trouble to
+							//  overlap
+LFDIVInFlight1:
+
+	addl	s,%esi
+	addl	t,%edx
+	movl	C(bbextents),%ebx
+	movl	C(bbextentt),%ebp
+	cmpl	%ebx,%esi
+	ja		LClampHighOrLow0
+LClampReentry0:
+	movl	%esi,s
+	movl	pbase,%ebx
+	shll	$16,%esi
+	cmpl	%ebp,%edx
+	movl	%esi,sfracf
+	ja		LClampHighOrLow1
+LClampReentry1:
+	movl	%edx,t
+	movl	s,%esi					// sfrac = scans->sfrac;
+	shll	$16,%edx
+	movl	t,%eax					// tfrac = scans->tfrac;
+	sarl	$16,%esi
+	movl	%edx,tfracf
+
+//
+// calculate the texture starting address
+//
+	sarl	$16,%eax
+	movl	C(cachewidth),%edx
+	imull	%edx,%eax				// (tfrac >> 16) * cachewidth
+	addl	%ebx,%esi
+	addl	%eax,%esi				// psource = pbase + (sfrac >> 16) +
+									//           ((tfrac >> 16) * cachewidth);
+
+//
+// determine whether last span or not
+//
+	cmpl	$8,%ecx
+	jna		LLastSegment
+
+//
+// not the last segment; do full 8-wide segment
+//
+LNotLastSegment:
+
+//
+// advance s/z, t/z, and 1/z, and calculate s & t at end of span and steps to
+// get there
+//
+
+// pick up after the FDIV that was left in flight previously
+
+	fld		%st(0)			// duplicate it
+	fmul	%st(4),%st(0)	// s = s/z * z
+	fxch	%st(1)
+	fmul	%st(3),%st(0)	// t = t/z * z
+	fxch	%st(1)
+	fistpl	snext
+	fistpl	tnext
+	movl	snext,%eax
+	movl	tnext,%edx
+
+	movb	(%esi),%bl	// get first source texel
+	subl	$8,%ecx		// count off this segments' pixels
+	movl	C(sadjust),%ebp
+	movl	%ecx,counttemp	// remember count of remaining pixels
+
+	movl	C(tadjust),%ecx
+	movb	%bl,(%edi)	// store first dest pixel
+
+	addl	%eax,%ebp
+	addl	%edx,%ecx
+
+	movl	C(bbextents),%eax
+	movl	C(bbextentt),%edx
+
+	cmpl	$2048,%ebp
+	jl		LClampLow2
+	cmpl	%eax,%ebp
+	ja		LClampHigh2
+LClampReentry2:
+
+	cmpl	$2048,%ecx
+	jl		LClampLow3
+	cmpl	%edx,%ecx
+	ja		LClampHigh3
+LClampReentry3:
+
+	movl	%ebp,snext
+	movl	%ecx,tnext
+
+	subl	s,%ebp
+	subl	t,%ecx
+	
+//
+// set up advancetable
+//
+	movl	%ecx,%eax
+	movl	%ebp,%edx
+	sarl	$19,%eax			// tstep >>= 16;
+	jz		LZero
+	sarl	$19,%edx			// sstep >>= 16;
+	movl	C(cachewidth),%ebx
+	imull	%ebx,%eax
+	jmp		LSetUp1
+
+LZero:
+	sarl	$19,%edx			// sstep >>= 16;
+	movl	C(cachewidth),%ebx
+
+LSetUp1:
+
+	addl	%edx,%eax			// add in sstep
+								// (tstep >> 16) * cachewidth + (sstep >> 16);
+	movl	tfracf,%edx
+	movl	%eax,advancetable+4	// advance base in t
+	addl	%ebx,%eax			// ((tstep >> 16) + 1) * cachewidth +
+								//  (sstep >> 16);
+	shll	$13,%ebp			// left-justify sstep fractional part
+	movl	sfracf,%ebx
+	shll	$13,%ecx			// left-justify tstep fractional part
+	movl	%eax,advancetable	// advance extra in t
+
+	movl	%ecx,tstep
+	addl	%ecx,%edx			// advance tfrac fractional part by tstep frac
+
+	sbbl	%ecx,%ecx			// turn tstep carry into -1 (0 if none)
+	addl	%ebp,%ebx			// advance sfrac fractional part by sstep frac
+	adcl	advancetable+4(,%ecx,4),%esi	// point to next source texel
+
+	addl	tstep,%edx
+	sbbl	%ecx,%ecx
+	movb	(%esi),%al
+	addl	%ebp,%ebx
+	movb	%al,1(%edi)
+	adcl	advancetable+4(,%ecx,4),%esi
+
+	addl	tstep,%edx
+	sbbl	%ecx,%ecx
+	addl	%ebp,%ebx
+	movb	(%esi),%al
+	adcl	advancetable+4(,%ecx,4),%esi
+
+	addl	tstep,%edx
+	sbbl	%ecx,%ecx
+	movb	%al,2(%edi)
+	addl	%ebp,%ebx
+	movb	(%esi),%al
+	adcl	advancetable+4(,%ecx,4),%esi
+
+	addl	tstep,%edx
+	sbbl	%ecx,%ecx
+	movb	%al,3(%edi)
+	addl	%ebp,%ebx
+	movb	(%esi),%al
+	adcl	advancetable+4(,%ecx,4),%esi
+
+
+//
+// start FDIV for end of next segment in flight, so it can overlap
+//
+	movl	counttemp,%ecx
+	cmpl	$8,%ecx			// more than one segment after this?
+	ja		LSetupNotLast2	// yes
+
+	decl	%ecx
+	jz		LFDIVInFlight2	// if only one pixel, no need to start an FDIV
+	movl	%ecx,spancountminus1
+	fildl	spancountminus1
+
+	flds	C(d_zistepu)		// C(d_zistepu) | spancountminus1
+	fmul	%st(1),%st(0)	// C(d_zistepu)*scm1 | scm1
+	flds	C(d_tdivzstepu)	// C(d_tdivzstepu) | C(d_zistepu)*scm1 | scm1
+	fmul	%st(2),%st(0)	// C(d_tdivzstepu)*scm1 | C(d_zistepu)*scm1 | scm1
+	fxch	%st(1)			// C(d_zistepu)*scm1 | C(d_tdivzstepu)*scm1 | scm1
+	faddp	%st(0),%st(3)	// C(d_tdivzstepu)*scm1 | scm1
+	fxch	%st(1)			// scm1 | C(d_tdivzstepu)*scm1
+	fmuls	C(d_sdivzstepu)	// C(d_sdivzstepu)*scm1 | C(d_tdivzstepu)*scm1
+	fxch	%st(1)			// C(d_tdivzstepu)*scm1 | C(d_sdivzstepu)*scm1
+	faddp	%st(0),%st(3)	// C(d_sdivzstepu)*scm1
+	flds	fp_64k			// 64k | C(d_sdivzstepu)*scm1
+	fxch	%st(1)			// C(d_sdivzstepu)*scm1 | 64k
+	faddp	%st(0),%st(4)	// 64k
+
+	fdiv	%st(1),%st(0)	// this is what we've gone to all this trouble to
+							//  overlap
+	jmp		LFDIVInFlight2
+
+	.align	4
+LSetupNotLast2:
+	fadds	zi8stepu
+	fxch	%st(2)
+	fadds	sdivz8stepu
+	fxch	%st(2)
+	flds	tdivz8stepu
+	faddp	%st(0),%st(2)
+	flds	fp_64k
+	fdiv	%st(1),%st(0)	// z = 1/1/z
+							// this is what we've gone to all this trouble to
+							//  overlap
+LFDIVInFlight2:
+	movl	%ecx,counttemp
+
+	addl	tstep,%edx
+	sbbl	%ecx,%ecx
+	movb	%al,4(%edi)
+	addl	%ebp,%ebx
+	movb	(%esi),%al
+	adcl	advancetable+4(,%ecx,4),%esi
+
+	addl	tstep,%edx
+	sbbl	%ecx,%ecx
+	movb	%al,5(%edi)
+	addl	%ebp,%ebx
+	movb	(%esi),%al
+	adcl	advancetable+4(,%ecx,4),%esi
+
+	addl	tstep,%edx
+	sbbl	%ecx,%ecx
+	movb	%al,6(%edi)
+	addl	%ebp,%ebx
+	movb	(%esi),%al
+	adcl	advancetable+4(,%ecx,4),%esi
+
+	addl	$8,%edi
+	movl	%edx,tfracf
+	movl	snext,%edx
+	movl	%ebx,sfracf
+	movl	tnext,%ebx
+	movl	%edx,s
+	movl	%ebx,t
+
+	movl	counttemp,%ecx		// retrieve count
+
+//
+// determine whether last span or not
+//
+	cmpl	$8,%ecx				// are there multiple segments remaining?
+	movb	%al,-1(%edi)
+	ja		LNotLastSegment		// yes
+
+//
+// last segment of scan
+//
+LLastSegment:
+
+//
+// advance s/z, t/z, and 1/z, and calculate s & t at end of span and steps to
+// get there. The number of pixels left is variable, and we want to land on the
+// last pixel, not step one past it, so we can't run into arithmetic problems
+//
+	testl	%ecx,%ecx
+	jz		LNoSteps		// just draw the last pixel and we're done
+
+// pick up after the FDIV that was left in flight previously
+
+
+	fld		%st(0)			// duplicate it
+	fmul	%st(4),%st(0)	// s = s/z * z
+	fxch	%st(1)
+	fmul	%st(3),%st(0)	// t = t/z * z
+	fxch	%st(1)
+	fistpl	snext
+	fistpl	tnext
+
+	movb	(%esi),%al		// load first texel in segment
+	movl	C(tadjust),%ebx
+	movb	%al,(%edi)		// store first pixel in segment
+	movl	C(sadjust),%eax
+
+	addl	snext,%eax
+	addl	tnext,%ebx
+
+	movl	C(bbextents),%ebp
+	movl	C(bbextentt),%edx
+
+	cmpl	$2048,%eax
+	jl		LClampLow4
+	cmpl	%ebp,%eax
+	ja		LClampHigh4
+LClampReentry4:
+	movl	%eax,snext
+
+	cmpl	$2048,%ebx
+	jl		LClampLow5
+	cmpl	%edx,%ebx
+	ja		LClampHigh5
+LClampReentry5:
+
+	cmpl	$1,%ecx			// don't bother 
+	je		LOnlyOneStep	// if two pixels in segment, there's only one step,
+							//  of the segment length
+	subl	s,%eax
+	subl	t,%ebx
+
+	addl	%eax,%eax		// convert to 15.17 format so multiply by 1.31
+	addl	%ebx,%ebx		//  reciprocal yields 16.48
+
+	imull	reciprocal_table-8(,%ecx,4) // sstep = (snext - s) / (spancount-1)
+	movl	%edx,%ebp
+
+	movl	%ebx,%eax
+	imull	reciprocal_table-8(,%ecx,4) // tstep = (tnext - t) / (spancount-1)
+
+LSetEntryvec:
+//
+// set up advancetable
+//
+	movl	entryvec_table(,%ecx,4),%ebx
+	movl	%edx,%eax
+	movl	%ebx,jumptemp		// entry point into code for RET later
+	movl	%ebp,%ecx
+	sarl	$16,%edx			// tstep >>= 16;
+	movl	C(cachewidth),%ebx
+	sarl	$16,%ecx			// sstep >>= 16;
+	imull	%ebx,%edx
+
+	addl	%ecx,%edx			// add in sstep
+								// (tstep >> 16) * cachewidth + (sstep >> 16);
+	movl	tfracf,%ecx
+	movl	%edx,advancetable+4	// advance base in t
+	addl	%ebx,%edx			// ((tstep >> 16) + 1) * cachewidth +
+								//  (sstep >> 16);
+	shll	$16,%ebp			// left-justify sstep fractional part
+	movl	sfracf,%ebx
+	shll	$16,%eax			// left-justify tstep fractional part
+	movl	%edx,advancetable	// advance extra in t
+
+	movl	%eax,tstep
+	movl	%ecx,%edx
+	addl	%eax,%edx
+	sbbl	%ecx,%ecx
+	addl	%ebp,%ebx
+	adcl	advancetable+4(,%ecx,4),%esi
+
+	jmp		*jumptemp			// jump to the number-of-pixels handler
+
+//----------------------------------------
+
+LNoSteps:
+	movb	(%esi),%al		// load first texel in segment
+	subl	$7,%edi			// adjust for hardwired offset
+	jmp		LEndSpan
+
+
+LOnlyOneStep:
+	subl	s,%eax
+	subl	t,%ebx
+	movl	%eax,%ebp
+	movl	%ebx,%edx
+	jmp		LSetEntryvec
+
+//----------------------------------------
+
+.globl	Entry2_8
+Entry2_8:
+	subl	$6,%edi		// adjust for hardwired offsets
+	movb	(%esi),%al
+	jmp		LLEntry2_8
+
+//----------------------------------------
+
+.globl	Entry3_8
+Entry3_8:
+	subl	$5,%edi		// adjust for hardwired offsets
+	addl	%eax,%edx
+	movb	(%esi),%al
+	sbbl	%ecx,%ecx
+	addl	%ebp,%ebx
+	adcl	advancetable+4(,%ecx,4),%esi
+	jmp		LLEntry3_8
+
+//----------------------------------------
+
+.globl	Entry4_8
+Entry4_8:
+	subl	$4,%edi		// adjust for hardwired offsets
+	addl	%eax,%edx
+	movb	(%esi),%al
+	sbbl	%ecx,%ecx
+	addl	%ebp,%ebx
+	adcl	advancetable+4(,%ecx,4),%esi
+	addl	tstep,%edx
+	jmp		LLEntry4_8
+
+//----------------------------------------
+
+.globl	Entry5_8
+Entry5_8:
+	subl	$3,%edi		// adjust for hardwired offsets
+	addl	%eax,%edx
+	movb	(%esi),%al
+	sbbl	%ecx,%ecx
+	addl	%ebp,%ebx
+	adcl	advancetable+4(,%ecx,4),%esi
+	addl	tstep,%edx
+	jmp		LLEntry5_8
+
+//----------------------------------------
+
+.globl	Entry6_8
+Entry6_8:
+	subl	$2,%edi		// adjust for hardwired offsets
+	addl	%eax,%edx
+	movb	(%esi),%al
+	sbbl	%ecx,%ecx
+	addl	%ebp,%ebx
+	adcl	advancetable+4(,%ecx,4),%esi
+	addl	tstep,%edx
+	jmp		LLEntry6_8
+
+//----------------------------------------
+
+.globl	Entry7_8
+Entry7_8:
+	decl	%edi		// adjust for hardwired offsets
+	addl	%eax,%edx
+	movb	(%esi),%al
+	sbbl	%ecx,%ecx
+	addl	%ebp,%ebx
+	adcl	advancetable+4(,%ecx,4),%esi
+	addl	tstep,%edx
+	jmp		LLEntry7_8
+
+//----------------------------------------
+
+.globl	Entry8_8
+Entry8_8:
+	addl	%eax,%edx
+	movb	(%esi),%al
+	sbbl	%ecx,%ecx
+	addl	%ebp,%ebx
+	adcl	advancetable+4(,%ecx,4),%esi
+
+	addl	tstep,%edx
+	sbbl	%ecx,%ecx
+	movb	%al,1(%edi)
+	addl	%ebp,%ebx
+	movb	(%esi),%al
+	adcl	advancetable+4(,%ecx,4),%esi
+	addl	tstep,%edx
+LLEntry7_8:
+	sbbl	%ecx,%ecx
+	movb	%al,2(%edi)
+	addl	%ebp,%ebx
+	movb	(%esi),%al
+	adcl	advancetable+4(,%ecx,4),%esi
+	addl	tstep,%edx
+LLEntry6_8:
+	sbbl	%ecx,%ecx
+	movb	%al,3(%edi)
+	addl	%ebp,%ebx
+	movb	(%esi),%al
+	adcl	advancetable+4(,%ecx,4),%esi
+	addl	tstep,%edx
+LLEntry5_8:
+	sbbl	%ecx,%ecx
+	movb	%al,4(%edi)
+	addl	%ebp,%ebx
+	movb	(%esi),%al
+	adcl	advancetable+4(,%ecx,4),%esi
+	addl	tstep,%edx
+LLEntry4_8:
+	sbbl	%ecx,%ecx
+	movb	%al,5(%edi)
+	addl	%ebp,%ebx
+	movb	(%esi),%al
+	adcl	advancetable+4(,%ecx,4),%esi
+LLEntry3_8:
+	movb	%al,6(%edi)
+	movb	(%esi),%al
+LLEntry2_8:
+
+LEndSpan:
+
+//
+// clear s/z, t/z, 1/z from FP stack
+//
+	fstp %st(0)
+	fstp %st(0)
+	fstp %st(0)
+
+	movl	pspantemp,%ebx				// restore spans pointer
+	movl	espan_t_pnext(%ebx),%ebx	// point to next span
+	testl	%ebx,%ebx			// any more spans?
+	movb	%al,7(%edi)
+	jnz		LSpanLoop			// more spans
+
+	popl	%ebx				// restore register variables
+	popl	%esi
+	popl	%edi
+	popl	%ebp				// restore the caller's stack frame
+	ret
+
+//----------------------------------------------------------------------
+// 8-bpp horizontal span z drawing codefor polygons, with no transparency.
+//
+// Assumes there is at least one span in pzspans, and that every span
+// contains at least one pixel
+//----------------------------------------------------------------------
+
+	.text
+
+// z-clamp on a non-negative gradient span
+LClamp:
+	movl	$0x40000000,%edx
+	xorl	%ebx,%ebx
+	fstp	%st(0)
+	jmp		LZDraw
+
+// z-clamp on a negative gradient span
+LClampNeg:
+	movl	$0x40000000,%edx
+	xorl	%ebx,%ebx
+	fstp	%st(0)
+	jmp		LZDrawNeg
+
+
+#define pzspans	4+16
+
+.globl C(D_DrawZSpans)
+C(D_DrawZSpans):
+	pushl	%ebp				// preserve caller's stack frame
+	pushl	%edi
+	pushl	%esi				// preserve register variables
+	pushl	%ebx
+
+	flds	C(d_zistepu)
+	movl	C(d_zistepu),%eax
+	movl	pzspans(%esp),%esi
+	testl	%eax,%eax
+	jz		LFNegSpan
+
+	fmuls	Float2ToThe31nd
+	fistpl	izistep		// note: we are relying on FP exceptions being turned
+						// off here to avoid range problems
+	movl	izistep,%ebx	// remains loaded for all spans
+
+LFSpanLoop:
+// set up the initial 1/z value
+	fildl	espan_t_v(%esi)
+	fildl	espan_t_u(%esi)
+	movl	espan_t_v(%esi),%ecx
+	movl	C(d_pzbuffer),%edi
+	fmuls	C(d_zistepu)
+	fxch	%st(1)
+	fmuls	C(d_zistepv)
+	fxch	%st(1)
+	fadds	C(d_ziorigin)
+	imull	C(d_zrowbytes),%ecx
+	faddp	%st(0),%st(1)
+
+// clamp if z is nearer than 2 (1/z > 0.5)
+	fcoms	float_point5
+	addl	%ecx,%edi
+	movl	espan_t_u(%esi),%edx
+	addl	%edx,%edx				// word count
+	movl	espan_t_count(%esi),%ecx
+	addl	%edx,%edi				// pdest = &pdestspan[scans->u];
+	pushl	%esi		// preserve spans pointer
+	fnstsw	%ax
+	testb	$0x45,%ah
+	jz		LClamp
+
+	fmuls	Float2ToThe31nd
+	fistpl	izi			// note: we are relying on FP exceptions being turned
+						// off here to avoid problems when the span is closer
+						// than 1/(2**31)
+	movl	izi,%edx
+
+// at this point:
+// %ebx = izistep
+// %ecx = count
+// %edx = izi
+// %edi = pdest
+
+LZDraw:
+
+// do a single pixel up front, if necessary to dword align the destination
+	testl	$2,%edi
+	jz		LFMiddle
+	movl	%edx,%eax
+	addl	%ebx,%edx
+	shrl	$16,%eax
+	decl	%ecx
+	movw	%ax,(%edi)
+	addl	$2,%edi
+
+// do middle a pair of aligned dwords at a time
+LFMiddle:
+	pushl	%ecx
+	shrl	$1,%ecx				// count / 2
+	jz		LFLast				// no aligned dwords to do
+	shrl	$1,%ecx				// (count / 2) / 2
+	jnc		LFMiddleLoop		// even number of aligned dwords to do
+
+	movl	%edx,%eax
+	addl	%ebx,%edx
+	shrl	$16,%eax
+	movl	%edx,%esi
+	addl	%ebx,%edx
+	andl	$0xFFFF0000,%esi
+	orl		%esi,%eax
+	movl	%eax,(%edi)
+	addl	$4,%edi
+	andl	%ecx,%ecx
+	jz		LFLast
+
+LFMiddleLoop:
+	movl	%edx,%eax
+	addl	%ebx,%edx
+	shrl	$16,%eax
+	movl	%edx,%esi
+	addl	%ebx,%edx
+	andl	$0xFFFF0000,%esi
+	orl		%esi,%eax
+	movl	%edx,%ebp
+	movl	%eax,(%edi)
+	addl	%ebx,%edx
+	shrl	$16,%ebp
+	movl	%edx,%esi
+	addl	%ebx,%edx
+	andl	$0xFFFF0000,%esi
+	orl		%esi,%ebp
+	movl	%ebp,4(%edi)	// FIXME: eliminate register contention
+	addl	$8,%edi
+
+	decl	%ecx
+	jnz		LFMiddleLoop
+
+LFLast:
+	popl	%ecx			// retrieve count
+	popl	%esi			// retrieve span pointer
+
+// do the last, unaligned pixel, if there is one
+	andl	$1,%ecx			// is there an odd pixel left to do?
+	jz		LFSpanDone		// no
+	shrl	$16,%edx
+	movw	%dx,(%edi)		// do the final pixel's z
+
+LFSpanDone:
+	movl	espan_t_pnext(%esi),%esi
+	testl	%esi,%esi
+	jnz		LFSpanLoop
+
+	jmp		LFDone
+
+LFNegSpan:
+	fmuls	FloatMinus2ToThe31nd
+	fistpl	izistep		// note: we are relying on FP exceptions being turned
+						// off here to avoid range problems
+	movl	izistep,%ebx	// remains loaded for all spans
+
+LFNegSpanLoop:
+// set up the initial 1/z value
+	fildl	espan_t_v(%esi)
+	fildl	espan_t_u(%esi)
+	movl	espan_t_v(%esi),%ecx
+	movl	C(d_pzbuffer),%edi
+	fmuls	C(d_zistepu)
+	fxch	%st(1)
+	fmuls	C(d_zistepv)
+	fxch	%st(1)
+	fadds	C(d_ziorigin)
+	imull	C(d_zrowbytes),%ecx
+	faddp	%st(0),%st(1)
+
+// clamp if z is nearer than 2 (1/z > 0.5)
+	fcoms	float_point5
+	addl	%ecx,%edi
+	movl	espan_t_u(%esi),%edx
+	addl	%edx,%edx				// word count
+	movl	espan_t_count(%esi),%ecx
+	addl	%edx,%edi				// pdest = &pdestspan[scans->u];
+	pushl	%esi		// preserve spans pointer
+	fnstsw	%ax
+	testb	$0x45,%ah
+	jz		LClampNeg
+
+	fmuls	Float2ToThe31nd
+	fistpl	izi			// note: we are relying on FP exceptions being turned
+						// off here to avoid problems when the span is closer
+						// than 1/(2**31)
+	movl	izi,%edx
+
+// at this point:
+// %ebx = izistep
+// %ecx = count
+// %edx = izi
+// %edi = pdest
+
+LZDrawNeg:
+
+// do a single pixel up front, if necessary to dword align the destination
+	testl	$2,%edi
+	jz		LFNegMiddle
+	movl	%edx,%eax
+	subl	%ebx,%edx
+	shrl	$16,%eax
+	decl	%ecx
+	movw	%ax,(%edi)
+	addl	$2,%edi
+
+// do middle a pair of aligned dwords at a time
+LFNegMiddle:
+	pushl	%ecx
+	shrl	$1,%ecx				// count / 2
+	jz		LFNegLast			// no aligned dwords to do
+	shrl	$1,%ecx				// (count / 2) / 2
+	jnc		LFNegMiddleLoop		// even number of aligned dwords to do
+
+	movl	%edx,%eax
+	subl	%ebx,%edx
+	shrl	$16,%eax
+	movl	%edx,%esi
+	subl	%ebx,%edx
+	andl	$0xFFFF0000,%esi
+	orl		%esi,%eax
+	movl	%eax,(%edi)
+	addl	$4,%edi
+	andl	%ecx,%ecx
+	jz		LFNegLast
+
+LFNegMiddleLoop:
+	movl	%edx,%eax
+	subl	%ebx,%edx
+	shrl	$16,%eax
+	movl	%edx,%esi
+	subl	%ebx,%edx
+	andl	$0xFFFF0000,%esi
+	orl		%esi,%eax
+	movl	%edx,%ebp
+	movl	%eax,(%edi)
+	subl	%ebx,%edx
+	shrl	$16,%ebp
+	movl	%edx,%esi
+	subl	%ebx,%edx
+	andl	$0xFFFF0000,%esi
+	orl		%esi,%ebp
+	movl	%ebp,4(%edi)	// FIXME: eliminate register contention
+	addl	$8,%edi
+
+	decl	%ecx
+	jnz		LFNegMiddleLoop
+
+LFNegLast:
+	popl	%ecx			// retrieve count
+	popl	%esi			// retrieve span pointer
+
+// do the last, unaligned pixel, if there is one
+	andl	$1,%ecx			// is there an odd pixel left to do?
+	jz		LFNegSpanDone	// no
+	shrl	$16,%edx
+	movw	%dx,(%edi)		// do the final pixel's z
+
+LFNegSpanDone:
+	movl	espan_t_pnext(%esi),%esi
+	testl	%esi,%esi
+	jnz		LFNegSpanLoop
+
+LFDone:
+	popl	%ebx				// restore register variables
+	popl	%esi
+	popl	%edi
+	popl	%ebp				// restore the caller's stack frame
+	ret
+
+#endif	// id386
--- /dev/null
+++ b/QW/client/d_draw16.asm
@@ -1,0 +1,924 @@
+ .386P
+ .model FLAT
+ externdef _d_zistepu:dword
+ externdef _d_pzbuffer:dword
+ externdef _d_zistepv:dword
+ externdef _d_zrowbytes:dword
+ externdef _d_ziorigin:dword
+ externdef _r_turb_s:dword
+ externdef _r_turb_t:dword
+ externdef _r_turb_pdest:dword
+ externdef _r_turb_spancount:dword
+ externdef _r_turb_turb:dword
+ externdef _r_turb_pbase:dword
+ externdef _r_turb_sstep:dword
+ externdef _r_turb_tstep:dword
+ externdef _r_bmodelactive:dword
+ externdef _d_sdivzstepu:dword
+ externdef _d_tdivzstepu:dword
+ externdef _d_sdivzstepv:dword
+ externdef _d_tdivzstepv:dword
+ externdef _d_sdivzorigin:dword
+ externdef _d_tdivzorigin:dword
+ externdef _sadjust:dword
+ externdef _tadjust:dword
+ externdef _bbextents:dword
+ externdef _bbextentt:dword
+ externdef _cacheblock:dword
+ externdef _d_viewbuffer:dword
+ externdef _cachewidth:dword
+ externdef _d_pzbuffer:dword
+ externdef _d_zrowbytes:dword
+ externdef _d_zwidth:dword
+ externdef _d_scantable:dword
+ externdef _r_lightptr:dword
+ externdef _r_numvblocks:dword
+ externdef _prowdestbase:dword
+ externdef _pbasesource:dword
+ externdef _r_lightwidth:dword
+ externdef _lightright:dword
+ externdef _lightrightstep:dword
+ externdef _lightdeltastep:dword
+ externdef _lightdelta:dword
+ externdef _lightright:dword
+ externdef _lightdelta:dword
+ externdef _sourcetstep:dword
+ externdef _surfrowbytes:dword
+ externdef _lightrightstep:dword
+ externdef _lightdeltastep:dword
+ externdef _r_sourcemax:dword
+ externdef _r_stepback:dword
+ externdef _colormap:dword
+ externdef _blocksize:dword
+ externdef _sourcesstep:dword
+ externdef _lightleft:dword
+ externdef _blockdivshift:dword
+ externdef _blockdivmask:dword
+ externdef _lightleftstep:dword
+ externdef _r_origin:dword
+ externdef _r_ppn:dword
+ externdef _r_pup:dword
+ externdef _r_pright:dword
+ externdef _ycenter:dword
+ externdef _xcenter:dword
+ externdef _d_vrectbottom_particle:dword
+ externdef _d_vrectright_particle:dword
+ externdef _d_vrecty:dword
+ externdef _d_vrectx:dword
+ externdef _d_pix_shift:dword
+ externdef _d_pix_min:dword
+ externdef _d_pix_max:dword
+ externdef _d_y_aspect_shift:dword
+ externdef _screenwidth:dword
+ externdef _vright:dword
+ externdef _vup:dword
+ externdef _vpn:dword
+ externdef _BOPS_Error:dword
+ externdef _snd_scaletable:dword
+ externdef _paintbuffer:dword
+ externdef _snd_linear_count:dword
+ externdef _snd_p:dword
+ externdef _snd_vol:dword
+ externdef _snd_out:dword
+ externdef _r_leftclipped:dword
+ externdef _r_leftenter:dword
+ externdef _r_rightclipped:dword
+ externdef _r_rightenter:dword
+ externdef _modelorg:dword
+ externdef _xscale:dword
+ externdef _r_refdef:dword
+ externdef _yscale:dword
+ externdef _r_leftexit:dword
+ externdef _r_rightexit:dword
+ externdef _r_lastvertvalid:dword
+ externdef _cacheoffset:dword
+ externdef _newedges:dword
+ externdef _removeedges:dword
+ externdef _r_pedge:dword
+ externdef _r_framecount:dword
+ externdef _r_u1:dword
+ externdef _r_emitted:dword
+ externdef _edge_p:dword
+ externdef _surface_p:dword
+ externdef _surfaces:dword
+ externdef _r_lzi1:dword
+ externdef _r_v1:dword
+ externdef _r_ceilv1:dword
+ externdef _r_nearzi:dword
+ externdef _r_nearzionly:dword
+ externdef _edge_aftertail:dword
+ externdef _edge_tail:dword
+ externdef _current_iv:dword
+ externdef _edge_head_u_shift20:dword
+ externdef _span_p:dword
+ externdef _edge_head:dword
+ externdef _fv:dword
+ externdef _edge_tail_u_shift20:dword
+ externdef _r_apverts:dword
+ externdef _r_anumverts:dword
+ externdef _aliastransform:dword
+ externdef _r_avertexnormals:dword
+ externdef _r_plightvec:dword
+ externdef _r_ambientlight:dword
+ externdef _r_shadelight:dword
+ externdef _aliasxcenter:dword
+ externdef _aliasycenter:dword
+ externdef _a_sstepxfrac:dword
+ externdef _r_affinetridesc:dword
+ externdef _acolormap:dword
+ externdef _d_pcolormap:dword
+ externdef _r_affinetridesc:dword
+ externdef _d_sfrac:dword
+ externdef _d_ptex:dword
+ externdef _d_pedgespanpackage:dword
+ externdef _d_tfrac:dword
+ externdef _d_light:dword
+ externdef _d_zi:dword
+ externdef _d_pdest:dword
+ externdef _d_pz:dword
+ externdef _d_aspancount:dword
+ externdef _erroradjustup:dword
+ externdef _errorterm:dword
+ externdef _d_xdenom:dword
+ externdef _r_p0:dword
+ externdef _r_p1:dword
+ externdef _r_p2:dword
+ externdef _a_tstepxfrac:dword
+ externdef _r_sstepx:dword
+ externdef _r_tstepx:dword
+ externdef _a_ststepxwhole:dword
+ externdef _zspantable:dword
+ externdef _skintable:dword
+ externdef _r_zistepx:dword
+ externdef _erroradjustdown:dword
+ externdef _d_countextrastep:dword
+ externdef _ubasestep:dword
+ externdef _a_ststepxwhole:dword
+ externdef _a_tstepxfrac:dword
+ externdef _r_lstepx:dword
+ externdef _a_spans:dword
+ externdef _erroradjustdown:dword
+ externdef _d_pdestextrastep:dword
+ externdef _d_pzextrastep:dword
+ externdef _d_sfracextrastep:dword
+ externdef _d_ptexextrastep:dword
+ externdef _d_countextrastep:dword
+ externdef _d_tfracextrastep:dword
+ externdef _d_lightextrastep:dword
+ externdef _d_ziextrastep:dword
+ externdef _d_pdestbasestep:dword
+ externdef _d_pzbasestep:dword
+ externdef _d_sfracbasestep:dword
+ externdef _d_ptexbasestep:dword
+ externdef _ubasestep:dword
+ externdef _d_tfracbasestep:dword
+ externdef _d_lightbasestep:dword
+ externdef _d_zibasestep:dword
+ externdef _zspantable:dword
+ externdef _r_lstepy:dword
+ externdef _r_sstepy:dword
+ externdef _r_tstepy:dword
+ externdef _r_zistepy:dword
+ externdef _D_PolysetSetEdgeTable:dword
+ externdef _D_RasterizeAliasPolySmooth:dword
+ externdef float_point5:dword
+ externdef Float2ToThe31nd:dword
+ externdef izistep:dword
+ externdef izi:dword
+ externdef FloatMinus2ToThe31nd:dword
+ externdef float_1:dword
+ externdef float_particle_z_clip:dword
+ externdef float_minus_1:dword
+ externdef float_0:dword
+ externdef fp_16:dword
+ externdef fp_64k:dword
+ externdef fp_1m:dword
+ externdef fp_1m_minus_1:dword
+ externdef fp_8:dword
+ externdef entryvec_table:dword
+ externdef advancetable:dword
+ externdef sstep:dword
+ externdef tstep:dword
+ externdef pspantemp:dword
+ externdef counttemp:dword
+ externdef jumptemp:dword
+ externdef reciprocal_table:dword
+ externdef DP_Count:dword
+ externdef DP_u:dword
+ externdef DP_v:dword
+ externdef DP_32768:dword
+ externdef DP_Color:dword
+ externdef DP_Pix:dword
+ externdef DP_EntryTable:dword
+ externdef pbase:dword
+ externdef s:dword
+ externdef t:dword
+ externdef sfracf:dword
+ externdef tfracf:dword
+ externdef snext:dword
+ externdef tnext:dword
+ externdef spancountminus1:dword
+ externdef zi16stepu:dword
+ externdef sdivz16stepu:dword
+ externdef tdivz16stepu:dword
+ externdef zi8stepu:dword
+ externdef sdivz8stepu:dword
+ externdef tdivz8stepu:dword
+ externdef reciprocal_table_16:dword
+ externdef entryvec_table_16:dword
+ externdef ceil_cw:dword
+ externdef single_cw:dword
+ externdef fp_64kx64k:dword
+ externdef pz:dword
+ externdef spr8entryvec_table:dword
+_DATA SEGMENT
+_DATA ENDS
+_TEXT SEGMENT
+LClampHigh0:
+ mov esi,ds:dword ptr[_bbextents]
+ jmp LClampReentry0
+LClampHighOrLow0:
+ jg LClampHigh0
+ xor esi,esi
+ jmp LClampReentry0
+LClampHigh1:
+ mov edx,ds:dword ptr[_bbextentt]
+ jmp LClampReentry1
+LClampHighOrLow1:
+ jg LClampHigh1
+ xor edx,edx
+ jmp LClampReentry1
+LClampLow2:
+ mov ebp,4096
+ jmp LClampReentry2
+LClampHigh2:
+ mov ebp,ds:dword ptr[_bbextents]
+ jmp LClampReentry2
+LClampLow3:
+ mov ecx,4096
+ jmp LClampReentry3
+LClampHigh3:
+ mov ecx,ds:dword ptr[_bbextentt]
+ jmp LClampReentry3
+LClampLow4:
+ mov eax,4096
+ jmp LClampReentry4
+LClampHigh4:
+ mov eax,ds:dword ptr[_bbextents]
+ jmp LClampReentry4
+LClampLow5:
+ mov ebx,4096
+ jmp LClampReentry5
+LClampHigh5:
+ mov ebx,ds:dword ptr[_bbextentt]
+ jmp LClampReentry5
+ align 4
+ public _D_DrawSpans16
+_D_DrawSpans16:
+ push ebp
+ push edi
+ push esi
+ push ebx
+ fld ds:dword ptr[_d_sdivzstepu]
+ fmul ds:dword ptr[fp_16]
+ mov edx,ds:dword ptr[_cacheblock]
+ fld ds:dword ptr[_d_tdivzstepu]
+ fmul ds:dword ptr[fp_16]
+ mov ebx,ds:dword ptr[4+16+esp]
+ fld ds:dword ptr[_d_zistepu]
+ fmul ds:dword ptr[fp_16]
+ mov ds:dword ptr[pbase],edx
+ fstp ds:dword ptr[zi16stepu]
+ fstp ds:dword ptr[tdivz16stepu]
+ fstp ds:dword ptr[sdivz16stepu]
+LSpanLoop:
+ fild ds:dword ptr[4+ebx]
+ fild ds:dword ptr[0+ebx]
+ fld st(1)
+ fmul ds:dword ptr[_d_sdivzstepv]
+ fld st(1)
+ fmul ds:dword ptr[_d_sdivzstepu]
+ fld st(2)
+ fmul ds:dword ptr[_d_tdivzstepu]
+ fxch st(1)
+ faddp st(2),st(0)
+ fxch st(1)
+ fld st(3)
+ fmul ds:dword ptr[_d_tdivzstepv]
+ fxch st(1)
+ fadd ds:dword ptr[_d_sdivzorigin]
+ fxch st(4)
+ fmul ds:dword ptr[_d_zistepv]
+ fxch st(1)
+ faddp st(2),st(0)
+ fxch st(2)
+ fmul ds:dword ptr[_d_zistepu]
+ fxch st(1)
+ fadd ds:dword ptr[_d_tdivzorigin]
+ fxch st(2)
+ faddp st(1),st(0)
+ fld ds:dword ptr[fp_64k]
+ fxch st(1)
+ fadd ds:dword ptr[_d_ziorigin]
+ fdiv st(1),st(0)
+ mov ecx,ds:dword ptr[_d_viewbuffer]
+ mov eax,ds:dword ptr[4+ebx]
+ mov ds:dword ptr[pspantemp],ebx
+ mov edx,ds:dword ptr[_tadjust]
+ mov esi,ds:dword ptr[_sadjust]
+ mov edi,ds:dword ptr[_d_scantable+eax*4]
+ add edi,ecx
+ mov ecx,ds:dword ptr[0+ebx]
+ add edi,ecx
+ mov ecx,ds:dword ptr[8+ebx]
+ cmp ecx,16
+ ja LSetupNotLast1
+ dec ecx
+ jz LCleanup1
+ mov ds:dword ptr[spancountminus1],ecx
+ fxch st(1)
+ fld st(0)
+ fmul st(0),st(4)
+ fxch st(1)
+ fmul st(0),st(3)
+ fxch st(1)
+ fistp ds:dword ptr[s]
+ fistp ds:dword ptr[t]
+ fild ds:dword ptr[spancountminus1]
+ fld ds:dword ptr[_d_tdivzstepu]
+ fld ds:dword ptr[_d_zistepu]
+ fmul st(0),st(2)
+ fxch st(1)
+ fmul st(0),st(2)
+ fxch st(2)
+ fmul ds:dword ptr[_d_sdivzstepu]
+ fxch st(1)
+ faddp st(3),st(0)
+ fxch st(1)
+ faddp st(3),st(0)
+ faddp st(3),st(0)
+ fld ds:dword ptr[fp_64k]
+ fdiv st(0),st(1)
+ jmp LFDIVInFlight1
+LCleanup1:
+ fxch st(1)
+ fld st(0)
+ fmul st(0),st(4)
+ fxch st(1)
+ fmul st(0),st(3)
+ fxch st(1)
+ fistp ds:dword ptr[s]
+ fistp ds:dword ptr[t]
+ jmp LFDIVInFlight1
+ align 4
+LSetupNotLast1:
+ fxch st(1)
+ fld st(0)
+ fmul st(0),st(4)
+ fxch st(1)
+ fmul st(0),st(3)
+ fxch st(1)
+ fistp ds:dword ptr[s]
+ fistp ds:dword ptr[t]
+ fadd ds:dword ptr[zi16stepu]
+ fxch st(2)
+ fadd ds:dword ptr[sdivz16stepu]
+ fxch st(2)
+ fld ds:dword ptr[tdivz16stepu]
+ faddp st(2),st(0)
+ fld ds:dword ptr[fp_64k]
+ fdiv st(0),st(1)
+LFDIVInFlight1:
+ add esi,ds:dword ptr[s]
+ add edx,ds:dword ptr[t]
+ mov ebx,ds:dword ptr[_bbextents]
+ mov ebp,ds:dword ptr[_bbextentt]
+ cmp esi,ebx
+ ja LClampHighOrLow0
+LClampReentry0:
+ mov ds:dword ptr[s],esi
+ mov ebx,ds:dword ptr[pbase]
+ shl esi,16
+ cmp edx,ebp
+ mov ds:dword ptr[sfracf],esi
+ ja LClampHighOrLow1
+LClampReentry1:
+ mov ds:dword ptr[t],edx
+ mov esi,ds:dword ptr[s]
+ shl edx,16
+ mov eax,ds:dword ptr[t]
+ sar esi,16
+ mov ds:dword ptr[tfracf],edx
+ sar eax,16
+ mov edx,ds:dword ptr[_cachewidth]
+ imul eax,edx
+ add esi,ebx
+ add esi,eax
+ cmp ecx,16
+ jna LLastSegment
+LNotLastSegment:
+ fld st(0)
+ fmul st(0),st(4)
+ fxch st(1)
+ fmul st(0),st(3)
+ fxch st(1)
+ fistp ds:dword ptr[snext]
+ fistp ds:dword ptr[tnext]
+ mov eax,ds:dword ptr[snext]
+ mov edx,ds:dword ptr[tnext]
+ mov bl,ds:byte ptr[esi]
+ sub ecx,16
+ mov ebp,ds:dword ptr[_sadjust]
+ mov ds:dword ptr[counttemp],ecx
+ mov ecx,ds:dword ptr[_tadjust]
+ mov ds:byte ptr[edi],bl
+ add ebp,eax
+ add ecx,edx
+ mov eax,ds:dword ptr[_bbextents]
+ mov edx,ds:dword ptr[_bbextentt]
+ cmp ebp,4096
+ jl LClampLow2
+ cmp ebp,eax
+ ja LClampHigh2
+LClampReentry2:
+ cmp ecx,4096
+ jl LClampLow3
+ cmp ecx,edx
+ ja LClampHigh3
+LClampReentry3:
+ mov ds:dword ptr[snext],ebp
+ mov ds:dword ptr[tnext],ecx
+ sub ebp,ds:dword ptr[s]
+ sub ecx,ds:dword ptr[t]
+ mov eax,ecx
+ mov edx,ebp
+ sar eax,20
+ jz LZero
+ sar edx,20
+ mov ebx,ds:dword ptr[_cachewidth]
+ imul eax,ebx
+ jmp LSetUp1
+LZero:
+ sar edx,20
+ mov ebx,ds:dword ptr[_cachewidth]
+LSetUp1:
+ add eax,edx
+ mov edx,ds:dword ptr[tfracf]
+ mov ds:dword ptr[advancetable+4],eax
+ add eax,ebx
+ shl ebp,12
+ mov ebx,ds:dword ptr[sfracf]
+ shl ecx,12
+ mov ds:dword ptr[advancetable],eax
+ mov ds:dword ptr[tstep],ecx
+ add edx,ecx
+ sbb ecx,ecx
+ add ebx,ebp
+ adc esi,ds:dword ptr[advancetable+4+ecx*4]
+ add edx,ds:dword ptr[tstep]
+ sbb ecx,ecx
+ mov al,ds:byte ptr[esi]
+ add ebx,ebp
+ mov ds:byte ptr[1+edi],al
+ adc esi,ds:dword ptr[advancetable+4+ecx*4]
+ add edx,ds:dword ptr[tstep]
+ sbb ecx,ecx
+ add ebx,ebp
+ mov al,ds:byte ptr[esi]
+ adc esi,ds:dword ptr[advancetable+4+ecx*4]
+ add edx,ds:dword ptr[tstep]
+ sbb ecx,ecx
+ mov ds:byte ptr[2+edi],al
+ add ebx,ebp
+ mov al,ds:byte ptr[esi]
+ adc esi,ds:dword ptr[advancetable+4+ecx*4]
+ add edx,ds:dword ptr[tstep]
+ sbb ecx,ecx
+ mov ds:byte ptr[3+edi],al
+ add ebx,ebp
+ mov al,ds:byte ptr[esi]
+ adc esi,ds:dword ptr[advancetable+4+ecx*4]
+ add edx,ds:dword ptr[tstep]
+ sbb ecx,ecx
+ mov ds:byte ptr[4+edi],al
+ add ebx,ebp
+ mov al,ds:byte ptr[esi]
+ adc esi,ds:dword ptr[advancetable+4+ecx*4]
+ add edx,ds:dword ptr[tstep]
+ sbb ecx,ecx
+ mov ds:byte ptr[5+edi],al
+ add ebx,ebp
+ mov al,ds:byte ptr[esi]
+ adc esi,ds:dword ptr[advancetable+4+ecx*4]
+ add edx,ds:dword ptr[tstep]
+ sbb ecx,ecx
+ mov ds:byte ptr[6+edi],al
+ add ebx,ebp
+ mov al,ds:byte ptr[esi]
+ adc esi,ds:dword ptr[advancetable+4+ecx*4]
+ add edx,ds:dword ptr[tstep]
+ sbb ecx,ecx
+ mov ds:byte ptr[7+edi],al
+ add ebx,ebp
+ mov al,ds:byte ptr[esi]
+ adc esi,ds:dword ptr[advancetable+4+ecx*4]
+ mov ecx,ds:dword ptr[counttemp]
+ cmp ecx,16
+ ja LSetupNotLast2
+ dec ecx
+ jz LFDIVInFlight2
+ mov ds:dword ptr[spancountminus1],ecx
+ fild ds:dword ptr[spancountminus1]
+ fld ds:dword ptr[_d_zistepu]
+ fmul st(0),st(1)
+ fld ds:dword ptr[_d_tdivzstepu]
+ fmul st(0),st(2)
+ fxch st(1)
+ faddp st(3),st(0)
+ fxch st(1)
+ fmul ds:dword ptr[_d_sdivzstepu]
+ fxch st(1)
+ faddp st(3),st(0)
+ fld ds:dword ptr[fp_64k]
+ fxch st(1)
+ faddp st(4),st(0)
+ fdiv st(0),st(1)
+ jmp LFDIVInFlight2
+ align 4
+LSetupNotLast2:
+ fadd ds:dword ptr[zi16stepu]
+ fxch st(2)
+ fadd ds:dword ptr[sdivz16stepu]
+ fxch st(2)
+ fld ds:dword ptr[tdivz16stepu]
+ faddp st(2),st(0)
+ fld ds:dword ptr[fp_64k]
+ fdiv st(0),st(1)
+LFDIVInFlight2:
+ mov ds:dword ptr[counttemp],ecx
+ add edx,ds:dword ptr[tstep]
+ sbb ecx,ecx
+ mov ds:byte ptr[8+edi],al
+ add ebx,ebp
+ mov al,ds:byte ptr[esi]
+ adc esi,ds:dword ptr[advancetable+4+ecx*4]
+ add edx,ds:dword ptr[tstep]
+ sbb ecx,ecx
+ mov ds:byte ptr[9+edi],al
+ add ebx,ebp
+ mov al,ds:byte ptr[esi]
+ adc esi,ds:dword ptr[advancetable+4+ecx*4]
+ add edx,ds:dword ptr[tstep]
+ sbb ecx,ecx
+ mov ds:byte ptr[10+edi],al
+ add ebx,ebp
+ mov al,ds:byte ptr[esi]
+ adc esi,ds:dword ptr[advancetable+4+ecx*4]
+ add edx,ds:dword ptr[tstep]
+ sbb ecx,ecx
+ mov ds:byte ptr[11+edi],al
+ add ebx,ebp
+ mov al,ds:byte ptr[esi]
+ adc esi,ds:dword ptr[advancetable+4+ecx*4]
+ add edx,ds:dword ptr[tstep]
+ sbb ecx,ecx
+ mov ds:byte ptr[12+edi],al
+ add ebx,ebp
+ mov al,ds:byte ptr[esi]
+ adc esi,ds:dword ptr[advancetable+4+ecx*4]
+ add edx,ds:dword ptr[tstep]
+ sbb ecx,ecx
+ mov ds:byte ptr[13+edi],al
+ add ebx,ebp
+ mov al,ds:byte ptr[esi]
+ adc esi,ds:dword ptr[advancetable+4+ecx*4]
+ add edx,ds:dword ptr[tstep]
+ sbb ecx,ecx
+ mov ds:byte ptr[14+edi],al
+ add ebx,ebp
+ mov al,ds:byte ptr[esi]
+ adc esi,ds:dword ptr[advancetable+4+ecx*4]
+ add edi,16
+ mov ds:dword ptr[tfracf],edx
+ mov edx,ds:dword ptr[snext]
+ mov ds:dword ptr[sfracf],ebx
+ mov ebx,ds:dword ptr[tnext]
+ mov ds:dword ptr[s],edx
+ mov ds:dword ptr[t],ebx
+ mov ecx,ds:dword ptr[counttemp]
+ cmp ecx,16
+ mov ds:byte ptr[-1+edi],al
+ ja LNotLastSegment
+LLastSegment:
+ test ecx,ecx
+ jz LNoSteps
+ fld st(0)
+ fmul st(0),st(4)
+ fxch st(1)
+ fmul st(0),st(3)
+ fxch st(1)
+ fistp ds:dword ptr[snext]
+ fistp ds:dword ptr[tnext]
+ mov al,ds:byte ptr[esi]
+ mov ebx,ds:dword ptr[_tadjust]
+ mov ds:byte ptr[edi],al
+ mov eax,ds:dword ptr[_sadjust]
+ add eax,ds:dword ptr[snext]
+ add ebx,ds:dword ptr[tnext]
+ mov ebp,ds:dword ptr[_bbextents]
+ mov edx,ds:dword ptr[_bbextentt]
+ cmp eax,4096
+ jl LClampLow4
+ cmp eax,ebp
+ ja LClampHigh4
+LClampReentry4:
+ mov ds:dword ptr[snext],eax
+ cmp ebx,4096
+ jl LClampLow5
+ cmp ebx,edx
+ ja LClampHigh5
+LClampReentry5:
+ cmp ecx,1
+ je LOnlyOneStep
+ sub eax,ds:dword ptr[s]
+ sub ebx,ds:dword ptr[t]
+ add eax,eax
+ add ebx,ebx
+ imul ds:dword ptr[reciprocal_table_16-8+ecx*4]
+ mov ebp,edx
+ mov eax,ebx
+ imul ds:dword ptr[reciprocal_table_16-8+ecx*4]
+LSetEntryvec:
+ mov ebx,ds:dword ptr[entryvec_table_16+ecx*4]
+ mov eax,edx
+ mov ds:dword ptr[jumptemp],ebx
+ mov ecx,ebp
+ sar edx,16
+ mov ebx,ds:dword ptr[_cachewidth]
+ sar ecx,16
+ imul edx,ebx
+ add edx,ecx
+ mov ecx,ds:dword ptr[tfracf]
+ mov ds:dword ptr[advancetable+4],edx
+ add edx,ebx
+ shl ebp,16
+ mov ebx,ds:dword ptr[sfracf]
+ shl eax,16
+ mov ds:dword ptr[advancetable],edx
+ mov ds:dword ptr[tstep],eax
+ mov edx,ecx
+ add edx,eax
+ sbb ecx,ecx
+ add ebx,ebp
+ adc esi,ds:dword ptr[advancetable+4+ecx*4]
+ jmp dword ptr[jumptemp]
+LNoSteps:
+ mov al,ds:byte ptr[esi]
+ sub edi,15
+ jmp LEndSpan
+LOnlyOneStep:
+ sub eax,ds:dword ptr[s]
+ sub ebx,ds:dword ptr[t]
+ mov ebp,eax
+ mov edx,ebx
+ jmp LSetEntryvec
+ public Entry2_16, Entry3_16, Entry4_16, Entry5_16
+ public Entry6_16, Entry7_16, Entry8_16, Entry9_16
+ public Entry10_16, Entry11_16, Entry12_16, Entry13_16
+ public Entry14_16, Entry15_16, Entry16_16
+Entry2_16:
+ sub edi,14
+ mov al,ds:byte ptr[esi]
+ jmp LEntry2_16
+Entry3_16:
+ sub edi,13
+ add edx,eax
+ mov al,ds:byte ptr[esi]
+ sbb ecx,ecx
+ add ebx,ebp
+ adc esi,ds:dword ptr[advancetable+4+ecx*4]
+ jmp LEntry3_16
+Entry4_16:
+ sub edi,12
+ add edx,eax
+ mov al,ds:byte ptr[esi]
+ sbb ecx,ecx
+ add ebx,ebp
+ adc esi,ds:dword ptr[advancetable+4+ecx*4]
+ add edx,ds:dword ptr[tstep]
+ jmp LEntry4_16
+Entry5_16:
+ sub edi,11
+ add edx,eax
+ mov al,ds:byte ptr[esi]
+ sbb ecx,ecx
+ add ebx,ebp
+ adc esi,ds:dword ptr[advancetable+4+ecx*4]
+ add edx,ds:dword ptr[tstep]
+ jmp LEntry5_16
+Entry6_16:
+ sub edi,10
+ add edx,eax
+ mov al,ds:byte ptr[esi]
+ sbb ecx,ecx
+ add ebx,ebp
+ adc esi,ds:dword ptr[advancetable+4+ecx*4]
+ add edx,ds:dword ptr[tstep]
+ jmp LEntry6_16
+Entry7_16:
+ sub edi,9
+ add edx,eax
+ mov al,ds:byte ptr[esi]
+ sbb ecx,ecx
+ add ebx,ebp
+ adc esi,ds:dword ptr[advancetable+4+ecx*4]
+ add edx,ds:dword ptr[tstep]
+ jmp LEntry7_16
+Entry8_16:
+ sub edi,8
+ add edx,eax
+ mov al,ds:byte ptr[esi]
+ sbb ecx,ecx
+ add ebx,ebp
+ adc esi,ds:dword ptr[advancetable+4+ecx*4]
+ add edx,ds:dword ptr[tstep]
+ jmp LEntry8_16
+Entry9_16:
+ sub edi,7
+ add edx,eax
+ mov al,ds:byte ptr[esi]
+ sbb ecx,ecx
+ add ebx,ebp
+ adc esi,ds:dword ptr[advancetable+4+ecx*4]
+ add edx,ds:dword ptr[tstep]
+ jmp LEntry9_16
+Entry10_16:
+ sub edi,6
+ add edx,eax
+ mov al,ds:byte ptr[esi]
+ sbb ecx,ecx
+ add ebx,ebp
+ adc esi,ds:dword ptr[advancetable+4+ecx*4]
+ add edx,ds:dword ptr[tstep]
+ jmp LEntry10_16
+Entry11_16:
+ sub edi,5
+ add edx,eax
+ mov al,ds:byte ptr[esi]
+ sbb ecx,ecx
+ add ebx,ebp
+ adc esi,ds:dword ptr[advancetable+4+ecx*4]
+ add edx,ds:dword ptr[tstep]
+ jmp LEntry11_16
+Entry12_16:
+ sub edi,4
+ add edx,eax
+ mov al,ds:byte ptr[esi]
+ sbb ecx,ecx
+ add ebx,ebp
+ adc esi,ds:dword ptr[advancetable+4+ecx*4]
+ add edx,ds:dword ptr[tstep]
+ jmp LEntry12_16
+Entry13_16:
+ sub edi,3
+ add edx,eax
+ mov al,ds:byte ptr[esi]
+ sbb ecx,ecx
+ add ebx,ebp
+ adc esi,ds:dword ptr[advancetable+4+ecx*4]
+ add edx,ds:dword ptr[tstep]
+ jmp LEntry13_16
+Entry14_16:
+ sub edi,2
+ add edx,eax
+ mov al,ds:byte ptr[esi]
+ sbb ecx,ecx
+ add ebx,ebp
+ adc esi,ds:dword ptr[advancetable+4+ecx*4]
+ add edx,ds:dword ptr[tstep]
+ jmp LEntry14_16
+Entry15_16:
+ dec edi
+ add edx,eax
+ mov al,ds:byte ptr[esi]
+ sbb ecx,ecx
+ add ebx,ebp
+ adc esi,ds:dword ptr[advancetable+4+ecx*4]
+ add edx,ds:dword ptr[tstep]
+ jmp LEntry15_16
+Entry16_16:
+ add edx,eax
+ mov al,ds:byte ptr[esi]
+ sbb ecx,ecx
+ add ebx,ebp
+ adc esi,ds:dword ptr[advancetable+4+ecx*4]
+ add edx,ds:dword ptr[tstep]
+ sbb ecx,ecx
+ mov ds:byte ptr[1+edi],al
+ add ebx,ebp
+ mov al,ds:byte ptr[esi]
+ adc esi,ds:dword ptr[advancetable+4+ecx*4]
+ add edx,ds:dword ptr[tstep]
+LEntry15_16:
+ sbb ecx,ecx
+ mov ds:byte ptr[2+edi],al
+ add ebx,ebp
+ mov al,ds:byte ptr[esi]
+ adc esi,ds:dword ptr[advancetable+4+ecx*4]
+ add edx,ds:dword ptr[tstep]
+LEntry14_16:
+ sbb ecx,ecx
+ mov ds:byte ptr[3+edi],al
+ add ebx,ebp
+ mov al,ds:byte ptr[esi]
+ adc esi,ds:dword ptr[advancetable+4+ecx*4]
+ add edx,ds:dword ptr[tstep]
+LEntry13_16:
+ sbb ecx,ecx
+ mov ds:byte ptr[4+edi],al
+ add ebx,ebp
+ mov al,ds:byte ptr[esi]
+ adc esi,ds:dword ptr[advancetable+4+ecx*4]
+ add edx,ds:dword ptr[tstep]
+LEntry12_16:
+ sbb ecx,ecx
+ mov ds:byte ptr[5+edi],al
+ add ebx,ebp
+ mov al,ds:byte ptr[esi]
+ adc esi,ds:dword ptr[advancetable+4+ecx*4]
+ add edx,ds:dword ptr[tstep]
+LEntry11_16:
+ sbb ecx,ecx
+ mov ds:byte ptr[6+edi],al
+ add ebx,ebp
+ mov al,ds:byte ptr[esi]
+ adc esi,ds:dword ptr[advancetable+4+ecx*4]
+ add edx,ds:dword ptr[tstep]
+LEntry10_16:
+ sbb ecx,ecx
+ mov ds:byte ptr[7+edi],al
+ add ebx,ebp
+ mov al,ds:byte ptr[esi]
+ adc esi,ds:dword ptr[advancetable+4+ecx*4]
+ add edx,ds:dword ptr[tstep]
+LEntry9_16:
+ sbb ecx,ecx
+ mov ds:byte ptr[8+edi],al
+ add ebx,ebp
+ mov al,ds:byte ptr[esi]
+ adc esi,ds:dword ptr[advancetable+4+ecx*4]
+ add edx,ds:dword ptr[tstep]
+LEntry8_16:
+ sbb ecx,ecx
+ mov ds:byte ptr[9+edi],al
+ add ebx,ebp
+ mov al,ds:byte ptr[esi]
+ adc esi,ds:dword ptr[advancetable+4+ecx*4]
+ add edx,ds:dword ptr[tstep]
+LEntry7_16:
+ sbb ecx,ecx
+ mov ds:byte ptr[10+edi],al
+ add ebx,ebp
+ mov al,ds:byte ptr[esi]
+ adc esi,ds:dword ptr[advancetable+4+ecx*4]
+ add edx,ds:dword ptr[tstep]
+LEntry6_16:
+ sbb ecx,ecx
+ mov ds:byte ptr[11+edi],al
+ add ebx,ebp
+ mov al,ds:byte ptr[esi]
+ adc esi,ds:dword ptr[advancetable+4+ecx*4]
+ add edx,ds:dword ptr[tstep]
+LEntry5_16:
+ sbb ecx,ecx
+ mov ds:byte ptr[12+edi],al
+ add ebx,ebp
+ mov al,ds:byte ptr[esi]
+ adc esi,ds:dword ptr[advancetable+4+ecx*4]
+ add edx,ds:dword ptr[tstep]
+LEntry4_16:
+ sbb ecx,ecx
+ mov ds:byte ptr[13+edi],al
+ add ebx,ebp
+ mov al,ds:byte ptr[esi]
+ adc esi,ds:dword ptr[advancetable+4+ecx*4]
+LEntry3_16:
+ mov ds:byte ptr[14+edi],al
+ mov al,ds:byte ptr[esi]
+LEntry2_16:
+LEndSpan:
+ fstp st(0)
+ fstp st(0)
+ fstp st(0)
+ mov ebx,ds:dword ptr[pspantemp]
+ mov ebx,ds:dword ptr[12+ebx]
+ test ebx,ebx
+ mov ds:byte ptr[15+edi],al
+ jnz LSpanLoop
+ pop ebx
+ pop esi
+ pop edi
+ pop ebp
+ ret
+_TEXT ENDS
+ END
--- /dev/null
+++ b/QW/client/d_draw16.s
@@ -1,0 +1,974 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+//
+// d_draw16.s
+// x86 assembly-language horizontal 8-bpp span-drawing code, with 16-pixel
+// subdivision.
+//
+
+#include "asm_i386.h"
+#include "quakeasm.h"
+#include "asm_draw.h"
+#include "d_ifacea.h"
+
+#if	id386
+
+//----------------------------------------------------------------------
+// 8-bpp horizontal span drawing code for polygons, with no transparency and
+// 16-pixel subdivision.
+//
+// Assumes there is at least one span in pspans, and that every span
+// contains at least one pixel
+//----------------------------------------------------------------------
+
+	.data
+
+	.text
+
+// out-of-line, rarely-needed clamping code
+
+LClampHigh0:
+	movl	C(bbextents),%esi
+	jmp		LClampReentry0
+LClampHighOrLow0:
+	jg		LClampHigh0
+	xorl	%esi,%esi
+	jmp		LClampReentry0
+
+LClampHigh1:
+	movl	C(bbextentt),%edx
+	jmp		LClampReentry1
+LClampHighOrLow1:
+	jg		LClampHigh1
+	xorl	%edx,%edx
+	jmp		LClampReentry1
+
+LClampLow2:
+	movl	$4096,%ebp
+	jmp		LClampReentry2
+LClampHigh2:
+	movl	C(bbextents),%ebp
+	jmp		LClampReentry2
+
+LClampLow3:
+	movl	$4096,%ecx
+	jmp		LClampReentry3
+LClampHigh3:
+	movl	C(bbextentt),%ecx
+	jmp		LClampReentry3
+
+LClampLow4:
+	movl	$4096,%eax
+	jmp		LClampReentry4
+LClampHigh4:
+	movl	C(bbextents),%eax
+	jmp		LClampReentry4
+
+LClampLow5:
+	movl	$4096,%ebx
+	jmp		LClampReentry5
+LClampHigh5:
+	movl	C(bbextentt),%ebx
+	jmp		LClampReentry5
+
+
+#define pspans	4+16
+
+	.align 4
+.globl C(D_DrawSpans16)
+C(D_DrawSpans16):
+	pushl	%ebp				// preserve caller's stack frame
+	pushl	%edi
+	pushl	%esi				// preserve register variables
+	pushl	%ebx
+
+//
+// set up scaled-by-16 steps, for 16-long segments; also set up cacheblock
+// and span list pointers
+//
+// TODO: any overlap from rearranging?
+	flds	C(d_sdivzstepu)
+	fmuls	fp_16
+	movl	C(cacheblock),%edx
+	flds	C(d_tdivzstepu)
+	fmuls	fp_16
+	movl	pspans(%esp),%ebx	// point to the first span descriptor
+	flds	C(d_zistepu)
+	fmuls	fp_16
+	movl	%edx,pbase			// pbase = cacheblock
+	fstps	zi16stepu
+	fstps	tdivz16stepu
+	fstps	sdivz16stepu
+
+LSpanLoop:
+//
+// set up the initial s/z, t/z, and 1/z on the FP stack, and generate the
+// initial s and t values
+//
+// FIXME: pipeline FILD?
+	fildl	espan_t_v(%ebx)
+	fildl	espan_t_u(%ebx)
+
+	fld		%st(1)			// dv | du | dv
+	fmuls	C(d_sdivzstepv)	// dv*d_sdivzstepv | du | dv
+	fld		%st(1)			// du | dv*d_sdivzstepv | du | dv
+	fmuls	C(d_sdivzstepu)	// du*d_sdivzstepu | dv*d_sdivzstepv | du | dv
+	fld		%st(2)			// du | du*d_sdivzstepu | dv*d_sdivzstepv | du | dv
+	fmuls	C(d_tdivzstepu)	// du*d_tdivzstepu | du*d_sdivzstepu |
+							//  dv*d_sdivzstepv | du | dv
+	fxch	%st(1)			// du*d_sdivzstepu | du*d_tdivzstepu |
+							//  dv*d_sdivzstepv | du | dv
+	faddp	%st(0),%st(2)	// du*d_tdivzstepu |
+							//  du*d_sdivzstepu + dv*d_sdivzstepv | du | dv
+	fxch	%st(1)			// du*d_sdivzstepu + dv*d_sdivzstepv |
+							//  du*d_tdivzstepu | du | dv
+	fld		%st(3)			// dv | du*d_sdivzstepu + dv*d_sdivzstepv |
+							//  du*d_tdivzstepu | du | dv
+	fmuls	C(d_tdivzstepv)	// dv*d_tdivzstepv |
+							//  du*d_sdivzstepu + dv*d_sdivzstepv |
+							//  du*d_tdivzstepu | du | dv
+	fxch	%st(1)			// du*d_sdivzstepu + dv*d_sdivzstepv |
+							//  dv*d_tdivzstepv | du*d_tdivzstepu | du | dv
+	fadds	C(d_sdivzorigin)	// sdivz = d_sdivzorigin + dv*d_sdivzstepv +
+							//  du*d_sdivzstepu; stays in %st(2) at end
+	fxch	%st(4)			// dv | dv*d_tdivzstepv | du*d_tdivzstepu | du |
+							//  s/z
+	fmuls	C(d_zistepv)		// dv*d_zistepv | dv*d_tdivzstepv |
+							//  du*d_tdivzstepu | du | s/z
+	fxch	%st(1)			// dv*d_tdivzstepv |  dv*d_zistepv |
+							//  du*d_tdivzstepu | du | s/z
+	faddp	%st(0),%st(2)	// dv*d_zistepv |
+							//  dv*d_tdivzstepv + du*d_tdivzstepu | du | s/z
+	fxch	%st(2)			// du | dv*d_tdivzstepv + du*d_tdivzstepu |
+							//  dv*d_zistepv | s/z
+	fmuls	C(d_zistepu)		// du*d_zistepu |
+							//  dv*d_tdivzstepv + du*d_tdivzstepu |
+							//  dv*d_zistepv | s/z
+	fxch	%st(1)			// dv*d_tdivzstepv + du*d_tdivzstepu |
+							//  du*d_zistepu | dv*d_zistepv | s/z
+	fadds	C(d_tdivzorigin)	// tdivz = d_tdivzorigin + dv*d_tdivzstepv +
+							//  du*d_tdivzstepu; stays in %st(1) at end
+	fxch	%st(2)			// dv*d_zistepv | du*d_zistepu | t/z | s/z
+	faddp	%st(0),%st(1)	// dv*d_zistepv + du*d_zistepu | t/z | s/z
+
+	flds	fp_64k			// fp_64k | dv*d_zistepv + du*d_zistepu | t/z | s/z
+	fxch	%st(1)			// dv*d_zistepv + du*d_zistepu | fp_64k | t/z | s/z
+	fadds	C(d_ziorigin)		// zi = d_ziorigin + dv*d_zistepv +
+							//  du*d_zistepu; stays in %st(0) at end
+							// 1/z | fp_64k | t/z | s/z
+//
+// calculate and clamp s & t
+//
+	fdivr	%st(0),%st(1)	// 1/z | z*64k | t/z | s/z
+
+//
+// point %edi to the first pixel in the span
+//
+	movl	C(d_viewbuffer),%ecx
+	movl	espan_t_v(%ebx),%eax
+	movl	%ebx,pspantemp	// preserve spans pointer
+
+	movl	C(tadjust),%edx
+	movl	C(sadjust),%esi
+	movl	C(d_scantable)(,%eax,4),%edi	// v * screenwidth
+	addl	%ecx,%edi
+	movl	espan_t_u(%ebx),%ecx
+	addl	%ecx,%edi				// pdest = &pdestspan[scans->u];
+	movl	espan_t_count(%ebx),%ecx
+
+//
+// now start the FDIV for the end of the span
+//
+	cmpl	$16,%ecx
+	ja		LSetupNotLast1
+
+	decl	%ecx
+	jz		LCleanup1		// if only one pixel, no need to start an FDIV
+	movl	%ecx,spancountminus1
+
+// finish up the s and t calcs
+	fxch	%st(1)			// z*64k | 1/z | t/z | s/z
+
+	fld		%st(0)			// z*64k | z*64k | 1/z | t/z | s/z
+	fmul	%st(4),%st(0)	// s | z*64k | 1/z | t/z | s/z
+	fxch	%st(1)			// z*64k | s | 1/z | t/z | s/z
+	fmul	%st(3),%st(0)	// t | s | 1/z | t/z | s/z
+	fxch	%st(1)			// s | t | 1/z | t/z | s/z
+	fistpl	s				// 1/z | t | t/z | s/z
+	fistpl	t				// 1/z | t/z | s/z
+
+	fildl	spancountminus1
+
+	flds	C(d_tdivzstepu)	// C(d_tdivzstepu) | spancountminus1
+	flds	C(d_zistepu)		// C(d_zistepu) | C(d_tdivzstepu) | spancountminus1
+	fmul	%st(2),%st(0)	// C(d_zistepu)*scm1 | C(d_tdivzstepu) | scm1
+	fxch	%st(1)			// C(d_tdivzstepu) | C(d_zistepu)*scm1 | scm1
+	fmul	%st(2),%st(0)	// C(d_tdivzstepu)*scm1 | C(d_zistepu)*scm1 | scm1
+	fxch	%st(2)			// scm1 | C(d_zistepu)*scm1 | C(d_tdivzstepu)*scm1
+	fmuls	C(d_sdivzstepu)	// C(d_sdivzstepu)*scm1 | C(d_zistepu)*scm1 |
+							//  C(d_tdivzstepu)*scm1
+	fxch	%st(1)			// C(d_zistepu)*scm1 | C(d_sdivzstepu)*scm1 |
+							//  C(d_tdivzstepu)*scm1
+	faddp	%st(0),%st(3)	// C(d_sdivzstepu)*scm1 | C(d_tdivzstepu)*scm1
+	fxch	%st(1)			// C(d_tdivzstepu)*scm1 | C(d_sdivzstepu)*scm1
+	faddp	%st(0),%st(3)	// C(d_sdivzstepu)*scm1
+	faddp	%st(0),%st(3)
+
+	flds	fp_64k
+	fdiv	%st(1),%st(0)	// this is what we've gone to all this trouble to
+							//  overlap
+	jmp		LFDIVInFlight1
+
+LCleanup1:
+// finish up the s and t calcs
+	fxch	%st(1)			// z*64k | 1/z | t/z | s/z
+
+	fld		%st(0)			// z*64k | z*64k | 1/z | t/z | s/z
+	fmul	%st(4),%st(0)	// s | z*64k | 1/z | t/z | s/z
+	fxch	%st(1)			// z*64k | s | 1/z | t/z | s/z
+	fmul	%st(3),%st(0)	// t | s | 1/z | t/z | s/z
+	fxch	%st(1)			// s | t | 1/z | t/z | s/z
+	fistpl	s				// 1/z | t | t/z | s/z
+	fistpl	t				// 1/z | t/z | s/z
+	jmp		LFDIVInFlight1
+
+	.align	4
+LSetupNotLast1:
+// finish up the s and t calcs
+	fxch	%st(1)			// z*64k | 1/z | t/z | s/z
+
+	fld		%st(0)			// z*64k | z*64k | 1/z | t/z | s/z
+	fmul	%st(4),%st(0)	// s | z*64k | 1/z | t/z | s/z
+	fxch	%st(1)			// z*64k | s | 1/z | t/z | s/z
+	fmul	%st(3),%st(0)	// t | s | 1/z | t/z | s/z
+	fxch	%st(1)			// s | t | 1/z | t/z | s/z
+	fistpl	s				// 1/z | t | t/z | s/z
+	fistpl	t				// 1/z | t/z | s/z
+
+	fadds	zi16stepu
+	fxch	%st(2)
+	fadds	sdivz16stepu
+	fxch	%st(2)
+	flds	tdivz16stepu
+	faddp	%st(0),%st(2)
+	flds	fp_64k
+	fdiv	%st(1),%st(0)	// z = 1/1/z
+							// this is what we've gone to all this trouble to
+							//  overlap
+LFDIVInFlight1:
+
+	addl	s,%esi
+	addl	t,%edx
+	movl	C(bbextents),%ebx
+	movl	C(bbextentt),%ebp
+	cmpl	%ebx,%esi
+	ja		LClampHighOrLow0
+LClampReentry0:
+	movl	%esi,s
+	movl	pbase,%ebx
+	shll	$16,%esi
+	cmpl	%ebp,%edx
+	movl	%esi,sfracf
+	ja		LClampHighOrLow1
+LClampReentry1:
+	movl	%edx,t
+	movl	s,%esi					// sfrac = scans->sfrac;
+	shll	$16,%edx
+	movl	t,%eax					// tfrac = scans->tfrac;
+	sarl	$16,%esi
+	movl	%edx,tfracf
+
+//
+// calculate the texture starting address
+//
+	sarl	$16,%eax
+	movl	C(cachewidth),%edx
+	imull	%edx,%eax				// (tfrac >> 16) * cachewidth
+	addl	%ebx,%esi
+	addl	%eax,%esi				// psource = pbase + (sfrac >> 16) +
+									//           ((tfrac >> 16) * cachewidth);
+//
+// determine whether last span or not
+//
+	cmpl	$16,%ecx
+	jna		LLastSegment
+
+//
+// not the last segment; do full 16-wide segment
+//
+LNotLastSegment:
+
+//
+// advance s/z, t/z, and 1/z, and calculate s & t at end of span and steps to
+// get there
+//
+
+// pick up after the FDIV that was left in flight previously
+
+	fld		%st(0)			// duplicate it
+	fmul	%st(4),%st(0)	// s = s/z * z
+	fxch	%st(1)
+	fmul	%st(3),%st(0)	// t = t/z * z
+	fxch	%st(1)
+	fistpl	snext
+	fistpl	tnext
+	movl	snext,%eax
+	movl	tnext,%edx
+
+	movb	(%esi),%bl	// get first source texel
+	subl	$16,%ecx		// count off this segments' pixels
+	movl	C(sadjust),%ebp
+	movl	%ecx,counttemp	// remember count of remaining pixels
+
+	movl	C(tadjust),%ecx
+	movb	%bl,(%edi)	// store first dest pixel
+
+	addl	%eax,%ebp
+	addl	%edx,%ecx
+
+	movl	C(bbextents),%eax
+	movl	C(bbextentt),%edx
+
+	cmpl	$4096,%ebp
+	jl		LClampLow2
+	cmpl	%eax,%ebp
+	ja		LClampHigh2
+LClampReentry2:
+
+	cmpl	$4096,%ecx
+	jl		LClampLow3
+	cmpl	%edx,%ecx
+	ja		LClampHigh3
+LClampReentry3:
+
+	movl	%ebp,snext
+	movl	%ecx,tnext
+
+	subl	s,%ebp
+	subl	t,%ecx
+	
+//
+// set up advancetable
+//
+	movl	%ecx,%eax
+	movl	%ebp,%edx
+	sarl	$20,%eax			// tstep >>= 16;
+	jz		LZero
+	sarl	$20,%edx			// sstep >>= 16;
+	movl	C(cachewidth),%ebx
+	imull	%ebx,%eax
+	jmp		LSetUp1
+
+LZero:
+	sarl	$20,%edx			// sstep >>= 16;
+	movl	C(cachewidth),%ebx
+
+LSetUp1:
+
+	addl	%edx,%eax			// add in sstep
+								// (tstep >> 16) * cachewidth + (sstep >> 16);
+	movl	tfracf,%edx
+	movl	%eax,advancetable+4	// advance base in t
+	addl	%ebx,%eax			// ((tstep >> 16) + 1) * cachewidth +
+								//  (sstep >> 16);
+	shll	$12,%ebp			// left-justify sstep fractional part
+	movl	sfracf,%ebx
+	shll	$12,%ecx			// left-justify tstep fractional part
+	movl	%eax,advancetable	// advance extra in t
+
+	movl	%ecx,tstep
+	addl	%ecx,%edx			// advance tfrac fractional part by tstep frac
+
+	sbbl	%ecx,%ecx			// turn tstep carry into -1 (0 if none)
+	addl	%ebp,%ebx			// advance sfrac fractional part by sstep frac
+	adcl	advancetable+4(,%ecx,4),%esi	// point to next source texel
+
+	addl	tstep,%edx
+	sbbl	%ecx,%ecx
+	movb	(%esi),%al
+	addl	%ebp,%ebx
+	movb	%al,1(%edi)
+	adcl	advancetable+4(,%ecx,4),%esi
+
+	addl	tstep,%edx
+	sbbl	%ecx,%ecx
+	addl	%ebp,%ebx
+	movb	(%esi),%al
+	adcl	advancetable+4(,%ecx,4),%esi
+
+	addl	tstep,%edx
+	sbbl	%ecx,%ecx
+	movb	%al,2(%edi)
+	addl	%ebp,%ebx
+	movb	(%esi),%al
+	adcl	advancetable+4(,%ecx,4),%esi
+
+	addl	tstep,%edx
+	sbbl	%ecx,%ecx
+	movb	%al,3(%edi)
+	addl	%ebp,%ebx
+	movb	(%esi),%al
+	adcl	advancetable+4(,%ecx,4),%esi
+
+	addl	tstep,%edx
+	sbbl	%ecx,%ecx
+	movb	%al,4(%edi)
+	addl	%ebp,%ebx
+	movb	(%esi),%al
+	adcl	advancetable+4(,%ecx,4),%esi
+
+	addl	tstep,%edx
+	sbbl	%ecx,%ecx
+	movb	%al,5(%edi)
+	addl	%ebp,%ebx
+	movb	(%esi),%al
+	adcl	advancetable+4(,%ecx,4),%esi
+
+	addl	tstep,%edx
+	sbbl	%ecx,%ecx
+	movb	%al,6(%edi)
+	addl	%ebp,%ebx
+	movb	(%esi),%al
+	adcl	advancetable+4(,%ecx,4),%esi
+
+	addl	tstep,%edx
+	sbbl	%ecx,%ecx
+	movb	%al,7(%edi)
+	addl	%ebp,%ebx
+	movb	(%esi),%al
+	adcl	advancetable+4(,%ecx,4),%esi
+
+
+//
+// start FDIV for end of next segment in flight, so it can overlap
+//
+	movl	counttemp,%ecx
+	cmpl	$16,%ecx			// more than one segment after this?
+	ja		LSetupNotLast2	// yes
+
+	decl	%ecx
+	jz		LFDIVInFlight2	// if only one pixel, no need to start an FDIV
+	movl	%ecx,spancountminus1
+	fildl	spancountminus1
+
+	flds	C(d_zistepu)		// C(d_zistepu) | spancountminus1
+	fmul	%st(1),%st(0)	// C(d_zistepu)*scm1 | scm1
+	flds	C(d_tdivzstepu)	// C(d_tdivzstepu) | C(d_zistepu)*scm1 | scm1
+	fmul	%st(2),%st(0)	// C(d_tdivzstepu)*scm1 | C(d_zistepu)*scm1 | scm1
+	fxch	%st(1)			// C(d_zistepu)*scm1 | C(d_tdivzstepu)*scm1 | scm1
+	faddp	%st(0),%st(3)	// C(d_tdivzstepu)*scm1 | scm1
+	fxch	%st(1)			// scm1 | C(d_tdivzstepu)*scm1
+	fmuls	C(d_sdivzstepu)	// C(d_sdivzstepu)*scm1 | C(d_tdivzstepu)*scm1
+	fxch	%st(1)			// C(d_tdivzstepu)*scm1 | C(d_sdivzstepu)*scm1
+	faddp	%st(0),%st(3)	// C(d_sdivzstepu)*scm1
+	flds	fp_64k			// 64k | C(d_sdivzstepu)*scm1
+	fxch	%st(1)			// C(d_sdivzstepu)*scm1 | 64k
+	faddp	%st(0),%st(4)	// 64k
+
+	fdiv	%st(1),%st(0)	// this is what we've gone to all this trouble to
+							//  overlap
+	jmp		LFDIVInFlight2
+
+	.align	4
+LSetupNotLast2:
+	fadds	zi16stepu
+	fxch	%st(2)
+	fadds	sdivz16stepu
+	fxch	%st(2)
+	flds	tdivz16stepu
+	faddp	%st(0),%st(2)
+	flds	fp_64k
+	fdiv	%st(1),%st(0)	// z = 1/1/z
+							// this is what we've gone to all this trouble to
+							//  overlap
+LFDIVInFlight2:
+	movl	%ecx,counttemp
+
+	addl	tstep,%edx
+	sbbl	%ecx,%ecx
+	movb	%al,8(%edi)
+	addl	%ebp,%ebx
+	movb	(%esi),%al
+	adcl	advancetable+4(,%ecx,4),%esi
+
+	addl	tstep,%edx
+	sbbl	%ecx,%ecx
+	movb	%al,9(%edi)
+	addl	%ebp,%ebx
+	movb	(%esi),%al
+	adcl	advancetable+4(,%ecx,4),%esi
+
+	addl	tstep,%edx
+	sbbl	%ecx,%ecx
+	movb	%al,10(%edi)
+	addl	%ebp,%ebx
+	movb	(%esi),%al
+	adcl	advancetable+4(,%ecx,4),%esi
+
+	addl	tstep,%edx
+	sbbl	%ecx,%ecx
+	movb	%al,11(%edi)
+	addl	%ebp,%ebx
+	movb	(%esi),%al
+	adcl	advancetable+4(,%ecx,4),%esi
+
+	addl	tstep,%edx
+	sbbl	%ecx,%ecx
+	movb	%al,12(%edi)
+	addl	%ebp,%ebx
+	movb	(%esi),%al
+	adcl	advancetable+4(,%ecx,4),%esi
+
+	addl	tstep,%edx
+	sbbl	%ecx,%ecx
+	movb	%al,13(%edi)
+	addl	%ebp,%ebx
+	movb	(%esi),%al
+	adcl	advancetable+4(,%ecx,4),%esi
+
+	addl	tstep,%edx
+	sbbl	%ecx,%ecx
+	movb	%al,14(%edi)
+	addl	%ebp,%ebx
+	movb	(%esi),%al
+	adcl	advancetable+4(,%ecx,4),%esi
+
+	addl	$16,%edi
+	movl	%edx,tfracf
+	movl	snext,%edx
+	movl	%ebx,sfracf
+	movl	tnext,%ebx
+	movl	%edx,s
+	movl	%ebx,t
+
+	movl	counttemp,%ecx		// retrieve count
+
+//
+// determine whether last span or not
+//
+	cmpl	$16,%ecx				// are there multiple segments remaining?
+	movb	%al,-1(%edi)
+	ja		LNotLastSegment		// yes
+
+//
+// last segment of scan
+//
+LLastSegment:
+
+//
+// advance s/z, t/z, and 1/z, and calculate s & t at end of span and steps to
+// get there. The number of pixels left is variable, and we want to land on the
+// last pixel, not step one past it, so we can't run into arithmetic problems
+//
+	testl	%ecx,%ecx
+	jz		LNoSteps		// just draw the last pixel and we're done
+
+// pick up after the FDIV that was left in flight previously
+
+
+	fld		%st(0)			// duplicate it
+	fmul	%st(4),%st(0)	// s = s/z * z
+	fxch	%st(1)
+	fmul	%st(3),%st(0)	// t = t/z * z
+	fxch	%st(1)
+	fistpl	snext
+	fistpl	tnext
+
+	movb	(%esi),%al		// load first texel in segment
+	movl	C(tadjust),%ebx
+	movb	%al,(%edi)		// store first pixel in segment
+	movl	C(sadjust),%eax
+
+	addl	snext,%eax
+	addl	tnext,%ebx
+
+	movl	C(bbextents),%ebp
+	movl	C(bbextentt),%edx
+
+	cmpl	$4096,%eax
+	jl		LClampLow4
+	cmpl	%ebp,%eax
+	ja		LClampHigh4
+LClampReentry4:
+	movl	%eax,snext
+
+	cmpl	$4096,%ebx
+	jl		LClampLow5
+	cmpl	%edx,%ebx
+	ja		LClampHigh5
+LClampReentry5:
+
+	cmpl	$1,%ecx			// don't bother 
+	je		LOnlyOneStep	// if two pixels in segment, there's only one step,
+							//  of the segment length
+	subl	s,%eax
+	subl	t,%ebx
+
+	addl	%eax,%eax		// convert to 15.17 format so multiply by 1.31
+	addl	%ebx,%ebx		//  reciprocal yields 16.48
+
+	imull	reciprocal_table_16-8(,%ecx,4)	// sstep = (snext - s) /
+											//  (spancount-1)
+	movl	%edx,%ebp
+
+	movl	%ebx,%eax
+	imull	reciprocal_table_16-8(,%ecx,4)	// tstep = (tnext - t) /
+											//  (spancount-1)
+LSetEntryvec:
+//
+// set up advancetable
+//
+	movl	entryvec_table_16(,%ecx,4),%ebx
+	movl	%edx,%eax
+	movl	%ebx,jumptemp		// entry point into code for RET later
+	movl	%ebp,%ecx
+	sarl	$16,%edx			// tstep >>= 16;
+	movl	C(cachewidth),%ebx
+	sarl	$16,%ecx			// sstep >>= 16;
+	imull	%ebx,%edx
+
+	addl	%ecx,%edx			// add in sstep
+								// (tstep >> 16) * cachewidth + (sstep >> 16);
+	movl	tfracf,%ecx
+	movl	%edx,advancetable+4	// advance base in t
+	addl	%ebx,%edx			// ((tstep >> 16) + 1) * cachewidth +
+								//  (sstep >> 16);
+	shll	$16,%ebp			// left-justify sstep fractional part
+	movl	sfracf,%ebx
+	shll	$16,%eax			// left-justify tstep fractional part
+	movl	%edx,advancetable	// advance extra in t
+
+	movl	%eax,tstep
+	movl	%ecx,%edx
+	addl	%eax,%edx
+	sbbl	%ecx,%ecx
+	addl	%ebp,%ebx
+	adcl	advancetable+4(,%ecx,4),%esi
+
+	jmp		*jumptemp			// jump to the number-of-pixels handler
+
+//----------------------------------------
+
+LNoSteps:
+	movb	(%esi),%al		// load first texel in segment
+	subl	$15,%edi			// adjust for hardwired offset
+	jmp		LEndSpan
+
+
+LOnlyOneStep:
+	subl	s,%eax
+	subl	t,%ebx
+	movl	%eax,%ebp
+	movl	%ebx,%edx
+	jmp		LSetEntryvec
+
+//----------------------------------------
+
+.globl	Entry2_16, Entry3_16, Entry4_16, Entry5_16
+.globl	Entry6_16, Entry7_16, Entry8_16, Entry9_16
+.globl	Entry10_16, Entry11_16, Entry12_16, Entry13_16
+.globl	Entry14_16, Entry15_16, Entry16_16
+
+Entry2_16:
+	subl	$14,%edi		// adjust for hardwired offsets
+	movb	(%esi),%al
+	jmp		LEntry2_16
+
+//----------------------------------------
+
+Entry3_16:
+	subl	$13,%edi		// adjust for hardwired offsets
+	addl	%eax,%edx
+	movb	(%esi),%al
+	sbbl	%ecx,%ecx
+	addl	%ebp,%ebx
+	adcl	advancetable+4(,%ecx,4),%esi
+	jmp		LEntry3_16
+
+//----------------------------------------
+
+Entry4_16:
+	subl	$12,%edi		// adjust for hardwired offsets
+	addl	%eax,%edx
+	movb	(%esi),%al
+	sbbl	%ecx,%ecx
+	addl	%ebp,%ebx
+	adcl	advancetable+4(,%ecx,4),%esi
+	addl	tstep,%edx
+	jmp		LEntry4_16
+
+//----------------------------------------
+
+Entry5_16:
+	subl	$11,%edi		// adjust for hardwired offsets
+	addl	%eax,%edx
+	movb	(%esi),%al
+	sbbl	%ecx,%ecx
+	addl	%ebp,%ebx
+	adcl	advancetable+4(,%ecx,4),%esi
+	addl	tstep,%edx
+	jmp		LEntry5_16
+
+//----------------------------------------
+
+Entry6_16:
+	subl	$10,%edi		// adjust for hardwired offsets
+	addl	%eax,%edx
+	movb	(%esi),%al
+	sbbl	%ecx,%ecx
+	addl	%ebp,%ebx
+	adcl	advancetable+4(,%ecx,4),%esi
+	addl	tstep,%edx
+	jmp		LEntry6_16
+
+//----------------------------------------
+
+Entry7_16:
+	subl	$9,%edi		// adjust for hardwired offsets
+	addl	%eax,%edx
+	movb	(%esi),%al
+	sbbl	%ecx,%ecx
+	addl	%ebp,%ebx
+	adcl	advancetable+4(,%ecx,4),%esi
+	addl	tstep,%edx
+	jmp		LEntry7_16
+
+//----------------------------------------
+
+Entry8_16:
+	subl	$8,%edi		// adjust for hardwired offsets
+	addl	%eax,%edx
+	movb	(%esi),%al
+	sbbl	%ecx,%ecx
+	addl	%ebp,%ebx
+	adcl	advancetable+4(,%ecx,4),%esi
+	addl	tstep,%edx
+	jmp		LEntry8_16
+
+//----------------------------------------
+
+Entry9_16:
+	subl	$7,%edi		// adjust for hardwired offsets
+	addl	%eax,%edx
+	movb	(%esi),%al
+	sbbl	%ecx,%ecx
+	addl	%ebp,%ebx
+	adcl	advancetable+4(,%ecx,4),%esi
+	addl	tstep,%edx
+	jmp		LEntry9_16
+
+//----------------------------------------
+
+Entry10_16:
+	subl	$6,%edi		// adjust for hardwired offsets
+	addl	%eax,%edx
+	movb	(%esi),%al
+	sbbl	%ecx,%ecx
+	addl	%ebp,%ebx
+	adcl	advancetable+4(,%ecx,4),%esi
+	addl	tstep,%edx
+	jmp		LEntry10_16
+
+//----------------------------------------
+
+Entry11_16:
+	subl	$5,%edi		// adjust for hardwired offsets
+	addl	%eax,%edx
+	movb	(%esi),%al
+	sbbl	%ecx,%ecx
+	addl	%ebp,%ebx
+	adcl	advancetable+4(,%ecx,4),%esi
+	addl	tstep,%edx
+	jmp		LEntry11_16
+
+//----------------------------------------
+
+Entry12_16:
+	subl	$4,%edi		// adjust for hardwired offsets
+	addl	%eax,%edx
+	movb	(%esi),%al
+	sbbl	%ecx,%ecx
+	addl	%ebp,%ebx
+	adcl	advancetable+4(,%ecx,4),%esi
+	addl	tstep,%edx
+	jmp		LEntry12_16
+
+//----------------------------------------
+
+Entry13_16:
+	subl	$3,%edi		// adjust for hardwired offsets
+	addl	%eax,%edx
+	movb	(%esi),%al
+	sbbl	%ecx,%ecx
+	addl	%ebp,%ebx
+	adcl	advancetable+4(,%ecx,4),%esi
+	addl	tstep,%edx
+	jmp		LEntry13_16
+
+//----------------------------------------
+
+Entry14_16:
+	subl	$2,%edi		// adjust for hardwired offsets
+	addl	%eax,%edx
+	movb	(%esi),%al
+	sbbl	%ecx,%ecx
+	addl	%ebp,%ebx
+	adcl	advancetable+4(,%ecx,4),%esi
+	addl	tstep,%edx
+	jmp		LEntry14_16
+
+//----------------------------------------
+
+Entry15_16:
+	decl	%edi		// adjust for hardwired offsets
+	addl	%eax,%edx
+	movb	(%esi),%al
+	sbbl	%ecx,%ecx
+	addl	%ebp,%ebx
+	adcl	advancetable+4(,%ecx,4),%esi
+	addl	tstep,%edx
+	jmp		LEntry15_16
+
+//----------------------------------------
+
+Entry16_16:
+	addl	%eax,%edx
+	movb	(%esi),%al
+	sbbl	%ecx,%ecx
+	addl	%ebp,%ebx
+	adcl	advancetable+4(,%ecx,4),%esi
+
+	addl	tstep,%edx
+	sbbl	%ecx,%ecx
+	movb	%al,1(%edi)
+	addl	%ebp,%ebx
+	movb	(%esi),%al
+	adcl	advancetable+4(,%ecx,4),%esi
+	addl	tstep,%edx
+LEntry15_16:
+	sbbl	%ecx,%ecx
+	movb	%al,2(%edi)
+	addl	%ebp,%ebx
+	movb	(%esi),%al
+	adcl	advancetable+4(,%ecx,4),%esi
+	addl	tstep,%edx
+LEntry14_16:
+	sbbl	%ecx,%ecx
+	movb	%al,3(%edi)
+	addl	%ebp,%ebx
+	movb	(%esi),%al
+	adcl	advancetable+4(,%ecx,4),%esi
+	addl	tstep,%edx
+LEntry13_16:
+	sbbl	%ecx,%ecx
+	movb	%al,4(%edi)
+	addl	%ebp,%ebx
+	movb	(%esi),%al
+	adcl	advancetable+4(,%ecx,4),%esi
+	addl	tstep,%edx
+LEntry12_16:
+	sbbl	%ecx,%ecx
+	movb	%al,5(%edi)
+	addl	%ebp,%ebx
+	movb	(%esi),%al
+	adcl	advancetable+4(,%ecx,4),%esi
+	addl	tstep,%edx
+LEntry11_16:
+	sbbl	%ecx,%ecx
+	movb	%al,6(%edi)
+	addl	%ebp,%ebx
+	movb	(%esi),%al
+	adcl	advancetable+4(,%ecx,4),%esi
+	addl	tstep,%edx
+LEntry10_16:
+	sbbl	%ecx,%ecx
+	movb	%al,7(%edi)
+	addl	%ebp,%ebx
+	movb	(%esi),%al
+	adcl	advancetable+4(,%ecx,4),%esi
+	addl	tstep,%edx
+LEntry9_16:
+	sbbl	%ecx,%ecx
+	movb	%al,8(%edi)
+	addl	%ebp,%ebx
+	movb	(%esi),%al
+	adcl	advancetable+4(,%ecx,4),%esi
+	addl	tstep,%edx
+LEntry8_16:
+	sbbl	%ecx,%ecx
+	movb	%al,9(%edi)
+	addl	%ebp,%ebx
+	movb	(%esi),%al
+	adcl	advancetable+4(,%ecx,4),%esi
+	addl	tstep,%edx
+LEntry7_16:
+	sbbl	%ecx,%ecx
+	movb	%al,10(%edi)
+	addl	%ebp,%ebx
+	movb	(%esi),%al
+	adcl	advancetable+4(,%ecx,4),%esi
+	addl	tstep,%edx
+LEntry6_16:
+	sbbl	%ecx,%ecx
+	movb	%al,11(%edi)
+	addl	%ebp,%ebx
+	movb	(%esi),%al
+	adcl	advancetable+4(,%ecx,4),%esi
+	addl	tstep,%edx
+LEntry5_16:
+	sbbl	%ecx,%ecx
+	movb	%al,12(%edi)
+	addl	%ebp,%ebx
+	movb	(%esi),%al
+	adcl	advancetable+4(,%ecx,4),%esi
+	addl	tstep,%edx
+LEntry4_16:
+	sbbl	%ecx,%ecx
+	movb	%al,13(%edi)
+	addl	%ebp,%ebx
+	movb	(%esi),%al
+	adcl	advancetable+4(,%ecx,4),%esi
+LEntry3_16:
+	movb	%al,14(%edi)
+	movb	(%esi),%al
+LEntry2_16:
+
+LEndSpan:
+
+//
+// clear s/z, t/z, 1/z from FP stack
+//
+	fstp %st(0)
+	fstp %st(0)
+	fstp %st(0)
+
+	movl	pspantemp,%ebx				// restore spans pointer
+	movl	espan_t_pnext(%ebx),%ebx	// point to next span
+	testl	%ebx,%ebx			// any more spans?
+	movb	%al,15(%edi)
+	jnz		LSpanLoop			// more spans
+
+	popl	%ebx				// restore register variables
+	popl	%esi
+	popl	%edi
+	popl	%ebp				// restore the caller's stack frame
+	ret
+
+#endif	// id386
--- /dev/null
+++ b/QW/client/d_edge.c
@@ -1,0 +1,336 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// d_edge.c
+
+#include "quakedef.h"
+#include "d_local.h"
+
+static int	miplevel;
+
+float		scale_for_mip;
+int			screenwidth;
+int			ubasestep, errorterm, erroradjustup, erroradjustdown;
+int			vstartscan;
+
+// FIXME: should go away
+extern void			R_RotateBmodel (void);
+extern void			R_TransformFrustum (void);
+
+vec3_t		transformed_modelorg;
+
+/*
+==============
+D_DrawPoly
+
+==============
+*/
+void D_DrawPoly (void)
+{
+// this driver takes spans, not polygons
+}
+
+
+/*
+=============
+D_MipLevelForScale
+=============
+*/
+int D_MipLevelForScale (float scale)
+{
+	int		lmiplevel;
+
+	if (scale >= d_scalemip[0] )
+		lmiplevel = 0;
+	else if (scale >= d_scalemip[1] )
+		lmiplevel = 1;
+	else if (scale >= d_scalemip[2] )
+		lmiplevel = 2;
+	else
+		lmiplevel = 3;
+
+	if (lmiplevel < d_minmip)
+		lmiplevel = d_minmip;
+
+	return lmiplevel;
+}
+
+
+/*
+==============
+D_DrawSolidSurface
+==============
+*/
+
+// FIXME: clean this up
+
+void D_DrawSolidSurface (surf_t *surf, int color)
+{
+	espan_t	*span;
+	byte	*pdest;
+	int		u, u2, pix;
+	
+	pix = (color<<24) | (color<<16) | (color<<8) | color;
+	for (span=surf->spans ; span ; span=span->pnext)
+	{
+		pdest = (byte *)d_viewbuffer + screenwidth*span->v;
+		u = span->u;
+		u2 = span->u + span->count - 1;
+		((byte *)pdest)[u] = pix;
+
+		if (u2 - u < 8)
+		{
+			for (u++ ; u <= u2 ; u++)
+				((byte *)pdest)[u] = pix;
+		}
+		else
+		{
+			for (u++ ; u & 3 ; u++)
+				((byte *)pdest)[u] = pix;
+
+			u2 -= 4;
+			for ( ; u <= u2 ; u+=4)
+				*(int *)((byte *)pdest + u) = pix;
+			u2 += 4;
+			for ( ; u <= u2 ; u++)
+				((byte *)pdest)[u] = pix;
+		}
+	}
+}
+
+
+/*
+==============
+D_CalcGradients
+==============
+*/
+void D_CalcGradients (msurface_t *pface)
+{
+	mplane_t	*pplane;
+	float		mipscale;
+	vec3_t		p_temp1;
+	vec3_t		p_saxis, p_taxis;
+	float		t;
+
+	pplane = pface->plane;
+
+	mipscale = 1.0 / (float)(1 << miplevel);
+
+	TransformVector (pface->texinfo->vecs[0], p_saxis);
+	TransformVector (pface->texinfo->vecs[1], p_taxis);
+
+	t = xscaleinv * mipscale;
+	d_sdivzstepu = p_saxis[0] * t;
+	d_tdivzstepu = p_taxis[0] * t;
+
+	t = yscaleinv * mipscale;
+	d_sdivzstepv = -p_saxis[1] * t;
+	d_tdivzstepv = -p_taxis[1] * t;
+
+	d_sdivzorigin = p_saxis[2] * mipscale - xcenter * d_sdivzstepu -
+			ycenter * d_sdivzstepv;
+	d_tdivzorigin = p_taxis[2] * mipscale - xcenter * d_tdivzstepu -
+			ycenter * d_tdivzstepv;
+
+	VectorScale (transformed_modelorg, mipscale, p_temp1);
+
+	t = 0x10000*mipscale;
+	sadjust = ((fixed16_t)(DotProduct (p_temp1, p_saxis) * 0x10000 + 0.5)) -
+			((pface->texturemins[0] << 16) >> miplevel)
+			+ pface->texinfo->vecs[0][3]*t;
+	tadjust = ((fixed16_t)(DotProduct (p_temp1, p_taxis) * 0x10000 + 0.5)) -
+			((pface->texturemins[1] << 16) >> miplevel)
+			+ pface->texinfo->vecs[1][3]*t;
+
+//
+// -1 (-epsilon) so we never wander off the edge of the texture
+//
+	bbextents = ((pface->extents[0] << 16) >> miplevel) - 1;
+	bbextentt = ((pface->extents[1] << 16) >> miplevel) - 1;
+}
+
+
+/*
+==============
+D_DrawSurfaces
+==============
+*/
+void D_DrawSurfaces (void)
+{
+	surf_t			*s;
+	msurface_t		*pface;
+	surfcache_t		*pcurrentcache;
+	vec3_t			world_transformed_modelorg;
+	vec3_t			local_modelorg;
+
+	currententity = &r_worldentity;
+	TransformVector (modelorg, transformed_modelorg);
+	VectorCopy (transformed_modelorg, world_transformed_modelorg);
+
+// TODO: could preset a lot of this at mode set time
+	if (r_drawflat.value)
+	{
+		for (s = &surfaces[1] ; s<surface_p ; s++)
+		{
+			if (!s->spans)
+				continue;
+
+			d_zistepu = s->d_zistepu;
+			d_zistepv = s->d_zistepv;
+			d_ziorigin = s->d_ziorigin;
+
+#ifdef __alpha__
+			D_DrawSolidSurface (s, (int)((long)s->data & 0xFF));
+#else
+			D_DrawSolidSurface (s, (int)s->data & 0xFF);
+#endif
+			D_DrawZSpans (s->spans);
+		}
+	}
+	else
+	{
+		for (s = &surfaces[1] ; s<surface_p ; s++)
+		{
+			if (!s->spans)
+				continue;
+
+			r_drawnpolycount++;
+
+			d_zistepu = s->d_zistepu;
+			d_zistepv = s->d_zistepv;
+			d_ziorigin = s->d_ziorigin;
+
+			if (s->flags & SURF_DRAWSKY)
+			{
+				if (!r_skymade)
+				{
+					R_MakeSky ();
+				}
+
+				D_DrawSkyScans8 (s->spans);
+				D_DrawZSpans (s->spans);
+			}
+			else if (s->flags & SURF_DRAWBACKGROUND)
+			{
+			// set up a gradient for the background surface that places it
+			// effectively at infinity distance from the viewpoint
+				d_zistepu = 0;
+				d_zistepv = 0;
+				d_ziorigin = -0.9;
+
+				D_DrawSolidSurface (s, (int)r_clearcolor.value & 0xFF);
+				D_DrawZSpans (s->spans);
+			}
+			else if (s->flags & SURF_DRAWTURB)
+			{
+				pface = s->data;
+				miplevel = 0;
+				cacheblock = (pixel_t *)
+						((byte *)pface->texinfo->texture +
+						pface->texinfo->texture->offsets[0]);
+				cachewidth = 64;
+
+				if (s->insubmodel)
+				{
+				// FIXME: we don't want to do all this for every polygon!
+				// TODO: store once at start of frame
+					currententity = s->entity;	//FIXME: make this passed in to
+												// R_RotateBmodel ()
+					VectorSubtract (r_origin, currententity->origin,
+							local_modelorg);
+					TransformVector (local_modelorg, transformed_modelorg);
+
+					R_RotateBmodel ();	// FIXME: don't mess with the frustum,
+										// make entity passed in
+				}
+
+				D_CalcGradients (pface);
+
+				Turbulent8 (s->spans);
+				D_DrawZSpans (s->spans);
+
+				if (s->insubmodel)
+				{
+				//
+				// restore the old drawing state
+				// FIXME: we don't want to do this every time!
+				// TODO: speed up
+				//
+					currententity = &r_worldentity;
+					VectorCopy (world_transformed_modelorg,
+								transformed_modelorg);
+					VectorCopy (base_vpn, vpn);
+					VectorCopy (base_vup, vup);
+					VectorCopy (base_vright, vright);
+					VectorCopy (base_modelorg, modelorg);
+					R_TransformFrustum ();
+				}
+			}
+			else
+			{
+				if (s->insubmodel)
+				{
+				// FIXME: we don't want to do all this for every polygon!
+				// TODO: store once at start of frame
+					currententity = s->entity;	//FIXME: make this passed in to
+												// R_RotateBmodel ()
+					VectorSubtract (r_origin, currententity->origin, local_modelorg);
+					TransformVector (local_modelorg, transformed_modelorg);
+
+					R_RotateBmodel ();	// FIXME: don't mess with the frustum,
+										// make entity passed in
+				}
+
+				pface = s->data;
+				miplevel = D_MipLevelForScale (s->nearzi * scale_for_mip
+				* pface->texinfo->mipadjust);
+
+			// FIXME: make this passed in to D_CacheSurface
+				pcurrentcache = D_CacheSurface (pface, miplevel);
+
+				cacheblock = (pixel_t *)pcurrentcache->data;
+				cachewidth = pcurrentcache->width;
+
+				D_CalcGradients (pface);
+
+				(*d_drawspans) (s->spans);
+
+				D_DrawZSpans (s->spans);
+
+				if (s->insubmodel)
+				{
+				//
+				// restore the old drawing state
+				// FIXME: we don't want to do this every time!
+				// TODO: speed up
+				//
+					VectorCopy (world_transformed_modelorg,
+								transformed_modelorg);
+					VectorCopy (base_vpn, vpn);
+					VectorCopy (base_vup, vup);
+					VectorCopy (base_vright, vright);
+					VectorCopy (base_modelorg, modelorg);
+					R_TransformFrustum ();
+					currententity = &r_worldentity;
+				}
+			}
+		}
+	}
+}
+
--- /dev/null
+++ b/QW/client/d_fill.c
@@ -1,0 +1,88 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// d_clear: clears a specified rectangle to the specified color
+
+#include "quakedef.h"
+
+
+/*
+================
+D_FillRect
+================
+*/
+void D_FillRect (vrect_t *rect, int color)
+{
+	int				rx, ry, rwidth, rheight;
+	unsigned char	*dest;
+	unsigned		*ldest;
+
+	rx = rect->x;
+	ry = rect->y;
+	rwidth = rect->width;
+	rheight = rect->height;
+
+	if (rx < 0)
+	{
+		rwidth += rx;
+		rx = 0;
+	}
+	if (ry < 0)
+	{
+		rheight += ry;
+		ry = 0;
+	}
+	if (rx+rwidth > vid.width)
+		rwidth = vid.width - rx;
+	if (ry+rheight > vid.height)
+		rheight = vid.height - rx;
+		
+	if (rwidth < 1 || rheight < 1)
+		return;
+
+	dest = ((byte *)vid.buffer + ry*vid.rowbytes + rx);
+
+	if (((rwidth & 0x03) == 0) && (((long)dest & 0x03) == 0))
+	{
+	// faster aligned dword clear
+		ldest = (unsigned *)dest;
+		color += color << 16;
+
+		rwidth >>= 2;
+		color += color << 8;
+
+		for (ry=0 ; ry<rheight ; ry++)
+		{
+			for (rx=0 ; rx<rwidth ; rx++)
+				ldest[rx] = color;
+			ldest = (unsigned *)((byte*)ldest + vid.rowbytes);
+		}
+	}
+	else
+	{
+	// slower byte-by-byte clear for unaligned cases
+		for (ry=0 ; ry<rheight ; ry++)
+		{
+			for (rx=0 ; rx<rwidth ; rx++)
+				dest[rx] = color;
+			dest += vid.rowbytes;
+		}
+	}
+}
+
--- /dev/null
+++ b/QW/client/d_iface.h
@@ -1,0 +1,229 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// d_iface.h: interface header file for rasterization driver modules
+
+#define WARP_WIDTH		320
+#define WARP_HEIGHT		200
+
+#define MAX_LBM_HEIGHT	200
+
+typedef struct
+{
+	float	u, v;
+	float	s, t;
+	float	zi;
+} emitpoint_t;
+
+typedef enum {
+	pt_static, pt_grav, pt_slowgrav, pt_fire, pt_explode, pt_explode2, pt_blob, pt_blob2
+} ptype_t;
+
+// !!! if this is changed, it must be changed in d_ifacea.h too !!!
+typedef struct particle_s
+{
+// driver-usable fields
+	vec3_t		org;
+	float		color;
+// drivers never touch the following fields
+	struct particle_s	*next;
+	vec3_t		vel;
+	float		ramp;
+	float		die;
+	ptype_t		type;
+} particle_t;
+
+#define PARTICLE_Z_CLIP	8.0
+
+typedef struct polyvert_s {
+	float	u, v, zi, s, t;
+} polyvert_t;
+
+typedef struct polydesc_s {
+	int			numverts;
+	float		nearzi;
+	msurface_t	*pcurrentface;
+	polyvert_t	*pverts;
+} polydesc_t;
+
+// !!! if this is changed, it must be changed in d_ifacea.h too !!!
+typedef struct finalvert_s {
+	int		v[6];		// u, v, s, t, l, 1/z
+	int		flags;
+	float	reserved;
+} finalvert_t;
+
+// !!! if this is changed, it must be changed in d_ifacea.h too !!!
+typedef struct
+{
+	void				*pskin;
+	maliasskindesc_t	*pskindesc;
+	int					skinwidth;
+	int					skinheight;
+	mtriangle_t			*ptriangles;
+	finalvert_t			*pfinalverts;
+	int					numtriangles;
+	int					drawtype;
+	int					seamfixupX16;
+} affinetridesc_t;
+
+// !!! if this is changed, it must be changed in d_ifacea.h too !!!
+typedef struct {
+	float	u, v, zi, color;
+} screenpart_t;
+
+typedef struct
+{
+	int			nump;
+	emitpoint_t	*pverts;	// there's room for an extra element at [nump], 
+							//  if the driver wants to duplicate element [0] at
+							//  element [nump] to avoid dealing with wrapping
+	mspriteframe_t	*pspriteframe;
+	vec3_t			vup, vright, vpn;	// in worldspace
+	float			nearzi;
+} spritedesc_t;
+
+typedef struct
+{
+	int		u, v;
+	float	zi;
+	int		color;
+} zpointdesc_t;
+
+extern cvar_t	r_drawflat;
+extern int		d_spanpixcount;
+extern int		r_framecount;		// sequence # of current frame since Quake
+									//  started
+extern qboolean	r_drawpolys;		// 1 if driver wants clipped polygons
+									//  rather than a span list
+extern qboolean	r_drawculledpolys;	// 1 if driver wants clipped polygons that
+									//  have been culled by the edge list
+extern qboolean	r_worldpolysbacktofront;	// 1 if driver wants polygons
+											//  delivered back to front rather
+											//  than front to back
+extern qboolean	r_recursiveaffinetriangles;	// true if a driver wants to use
+											//  recursive triangular subdivison
+											//  and vertex drawing via
+											//  D_PolysetDrawFinalVerts() past
+											//  a certain distance (normally 
+											//  only used by the software
+											//  driver)
+extern float	r_aliasuvscale;		// scale-up factor for screen u and v
+									//  on Alias vertices passed to driver
+extern int		r_pixbytes;
+extern qboolean	r_dowarp;
+
+extern affinetridesc_t	r_affinetridesc;
+extern spritedesc_t		r_spritedesc;
+extern zpointdesc_t		r_zpointdesc;
+extern polydesc_t		r_polydesc;
+
+extern int		d_con_indirect;	// if 0, Quake will draw console directly
+								//  to vid.buffer; if 1, Quake will
+								//  draw console via D_DrawRect. Must be
+								//  defined by driver
+
+extern vec3_t	r_pright, r_pup, r_ppn;
+
+
+void D_Aff8Patch (void *pcolormap);
+void D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height);
+void D_DisableBackBufferAccess (void);
+void D_EndDirectRect (int x, int y, int width, int height);
+void D_PolysetDraw (void);
+void D_PolysetDrawFinalVerts (finalvert_t *fv, int numverts);
+void D_DrawParticle (particle_t *pparticle);
+void D_DrawPoly (void);
+void D_DrawSprite (void);
+void D_DrawSurfaces (void);
+void D_DrawZPoint (void);
+void D_EnableBackBufferAccess (void);
+void D_EndParticles (void);
+void D_Init (void);
+void D_ViewChanged (void);
+void D_SetupFrame (void);
+void D_StartParticles (void);
+void D_TurnZOn (void);
+void D_WarpScreen (void);
+
+void D_FillRect (vrect_t *vrect, int color);
+void D_DrawRect (void);
+void D_UpdateRects (vrect_t *prect);
+
+// currently for internal use only, and should be a do-nothing function in
+// hardware drivers
+// FIXME: this should go away
+void D_PolysetUpdateTables (void);
+
+// these are currently for internal use only, and should not be used by drivers
+extern int				r_skydirect;
+extern byte				*r_skysource;
+
+// transparency types for D_DrawRect ()
+#define DR_SOLID		0
+#define DR_TRANSPARENT	1
+
+// !!! must be kept the same as in quakeasm.h !!!
+#define TRANSPARENT_COLOR	0xFF
+
+extern void *acolormap;	// FIXME: should go away
+
+//=======================================================================//
+
+// callbacks to Quake
+
+typedef struct
+{
+	pixel_t		*surfdat;	// destination for generated surface
+	int			rowbytes;	// destination logical width in bytes
+	msurface_t	*surf;		// description for surface to generate
+	fixed8_t	lightadj[MAXLIGHTMAPS];
+							// adjust for lightmap levels for dynamic lighting
+	texture_t	*texture;	// corrected for animating textures
+	int			surfmip;	// mipmapped ratio of surface texels / world pixels
+	int			surfwidth;	// in mipmapped texels
+	int			surfheight;	// in mipmapped texels
+} drawsurf_t;
+
+extern drawsurf_t	r_drawsurf;
+
+void R_DrawSurface (void);
+void R_GenTile (msurface_t *psurf, void *pdest);
+
+
+// !!! if this is changed, it must be changed in d_ifacea.h too !!!
+#define TURB_TEX_SIZE	64		// base turbulent texture size
+
+// !!! if this is changed, it must be changed in d_ifacea.h too !!!
+#define	CYCLE			128		// turbulent cycle size
+
+#define TILE_SIZE		128		// size of textures generated by R_GenTiledSurf
+
+#define SKYSHIFT		7
+#define	SKYSIZE			(1 << SKYSHIFT)
+#define SKYMASK			(SKYSIZE - 1)
+
+extern float	skyspeed, skyspeed2;
+extern float	skytime;
+
+extern int		c_surf;
+extern vrect_t	scr_vrect;
+
+extern byte		*r_warpbuffer;
+
--- /dev/null
+++ b/QW/client/d_ifacea.h
@@ -1,0 +1,98 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+//
+// d_ifacea.h
+//
+// Include file for asm driver interface.
+//
+
+//
+// !!! note that this file must match the corresponding C structures in
+// d_iface.h at all times !!!
+//
+
+// !!! if this is changed, it must be changed in r_shared.h too !!!
+#define ALIAS_ONSEAM				0x0020
+
+// !!! if this is changed, it must be changed in d_iface.h too !!!
+#define TURB_TEX_SIZE	64		// base turbulent texture size
+
+// !!! if this is changed, it must be changed in d_iface.h too !!!
+#define	CYCLE	128
+
+// !!! if this is changed, it must be changed in r_shared.h too !!!
+#define	MAXHEIGHT	1024
+
+// !!! if this is changed, it must be changed in quakedef.h too !!!
+#define CACHE_SIZE	32		// used to align key data structures
+
+// particle_t structure
+// !!! if this is changed, it must be changed in d_iface.h too !!!
+// driver-usable fields
+#define pt_org				0
+#define pt_color			12
+// drivers never touch the following fields
+#define pt_next				16
+#define pt_vel				20
+#define pt_ramp				32
+#define pt_die				36
+#define pt_type				40
+#define pt_size				44
+
+#define PARTICLE_Z_CLIP	8.0
+
+// finalvert_t structure
+// !!! if this is changed, it must be changed in d_iface.h too !!!
+#define fv_v				0	// !!! if this is moved, cases where the !!!
+								// !!! address of this field is pushed in !!!
+								// !!! d_polysa.s must be changed !!!
+#define fv_flags			24
+#define fv_reserved			28
+#define fv_size				32
+#define fv_shift			5
+
+
+// stvert_t structure
+// !!! if this is changed, it must be changed in modelgen.h too !!!
+#define stv_onseam	0
+#define stv_s		4
+#define stv_t		8
+#define stv_size	12
+
+
+// trivertx_t structure
+// !!! if this is changed, it must be changed in modelgen.h too !!!
+#define tv_v				0
+#define tv_lightnormalindex	3
+#define tv_size				4
+
+// affinetridesc_t structure
+// !!! if this is changed, it must be changed in d_iface.h too !!!
+#define atd_pskin			0
+#define atd_pskindesc		4
+#define atd_skinwidth		8
+#define atd_skinheight		12
+#define atd_ptriangles		16
+#define atd_pfinalverts		20
+#define atd_numtriangles	24
+#define atd_drawtype		28
+#define atd_seamfixupX16	32
+#define atd_size			36
+
--- /dev/null
+++ b/QW/client/d_init.c
@@ -1,0 +1,174 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// d_init.c: rasterization driver initialization
+
+#include "quakedef.h"
+#include "d_local.h"
+
+#define NUM_MIPS	4
+
+cvar_t	d_subdiv16 = {"d_subdiv16", "1"};
+cvar_t	d_mipcap = {"d_mipcap", "0"};
+cvar_t	d_mipscale = {"d_mipscale", "1"};
+
+surfcache_t		*d_initial_rover;
+qboolean		d_roverwrapped;
+int				d_minmip;
+float			d_scalemip[NUM_MIPS-1];
+
+static float	basemip[NUM_MIPS-1] = {1.0, 0.5*0.8, 0.25*0.8};
+
+extern int			d_aflatcolor;
+
+void (*d_drawspans) (espan_t *pspan);
+
+
+/*
+===============
+D_Init
+===============
+*/
+void D_Init (void)
+{
+
+	r_skydirect = 1;
+
+	Cvar_RegisterVariable (&d_subdiv16);
+	Cvar_RegisterVariable (&d_mipcap);
+	Cvar_RegisterVariable (&d_mipscale);
+
+	r_drawpolys = false;
+	r_worldpolysbacktofront = false;
+	r_recursiveaffinetriangles = true;
+	r_pixbytes = 1;
+	r_aliasuvscale = 1.0;
+}
+
+
+/*
+===============
+D_CopyRects
+===============
+*/
+void D_CopyRects (vrect_t *prects, int transparent)
+{
+
+// this function is only required if the CPU doesn't have direct access to the
+// back buffer, and there's some driver interface function that the driver
+// doesn't support and requires Quake to do in software (such as drawing the
+// console); Quake will then draw into wherever the driver points vid.buffer
+// and will call this function before swapping buffers
+
+	UNUSED(prects);
+	UNUSED(transparent);
+}
+
+
+/*
+===============
+D_EnableBackBufferAccess
+===============
+*/
+void D_EnableBackBufferAccess (void)
+{
+
+	VID_LockBuffer ();
+}
+
+
+/*
+===============
+D_TurnZOn
+===============
+*/
+void D_TurnZOn (void)
+{
+// not needed for software version
+}
+
+
+/*
+===============
+D_DisableBackBufferAccess
+===============
+*/
+void D_DisableBackBufferAccess (void)
+{
+	VID_UnlockBuffer ();
+}
+
+
+/*
+===============
+D_SetupFrame
+===============
+*/
+void D_SetupFrame (void)
+{
+	int		i;
+
+	if (r_dowarp)
+		d_viewbuffer = r_warpbuffer;
+	else
+		d_viewbuffer = (void *)(byte *)vid.buffer;
+
+	if (r_dowarp)
+		screenwidth = WARP_WIDTH;
+	else
+		screenwidth = vid.rowbytes;
+
+	d_roverwrapped = false;
+	d_initial_rover = sc_rover;
+
+	d_minmip = d_mipcap.value;
+	if (d_minmip > 3)
+		d_minmip = 3;
+	else if (d_minmip < 0)
+		d_minmip = 0;
+
+	for (i=0 ; i<(NUM_MIPS-1) ; i++)
+		d_scalemip[i] = basemip[i] * d_mipscale.value;
+
+#if	id386
+				if (d_subdiv16.value)
+					d_drawspans = D_DrawSpans16;
+				else
+					d_drawspans = D_DrawSpans8;
+#else
+				d_drawspans = D_DrawSpans8;
+#endif
+
+	d_aflatcolor = 0;
+}
+
+
+/*
+===============
+D_UpdateRects
+===============
+*/
+void D_UpdateRects (vrect_t *prect)
+{
+
+// the software driver draws these directly to the vid buffer
+
+	UNUSED(prect);
+}
+
--- /dev/null
+++ b/QW/client/d_local.h
@@ -1,0 +1,111 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// d_local.h:  private rasterization driver defs
+
+#include "r_shared.h"
+
+//
+// TODO: fine-tune this; it's based on providing some overage even if there
+// is a 2k-wide scan, with subdivision every 8, for 256 spans of 12 bytes each
+//
+#define SCANBUFFERPAD		0x1000
+
+#define R_SKY_SMASK	0x007F0000
+#define R_SKY_TMASK	0x007F0000
+
+#define DS_SPAN_LIST_END	-128
+
+#define SURFCACHE_SIZE_AT_320X200	600*1024
+
+typedef struct surfcache_s
+{
+	struct surfcache_s	*next;
+	struct surfcache_s 	**owner;		// NULL is an empty chunk of memory
+	int					lightadj[MAXLIGHTMAPS]; // checked for strobe flush
+	int					dlight;
+	int					size;		// including header
+	unsigned			width;
+	unsigned			height;		// DEBUG only needed for debug
+	float				mipscale;
+	struct texture_s	*texture;	// checked for animating textures
+	byte				data[4];	// width*height elements
+} surfcache_t;
+
+// !!! if this is changed, it must be changed in asm_draw.h too !!!
+typedef struct sspan_s
+{
+	int				u, v, count;
+} sspan_t;
+
+extern cvar_t	d_subdiv16;
+
+extern float	scale_for_mip;
+
+extern qboolean		d_roverwrapped;
+extern surfcache_t	*sc_rover;
+extern surfcache_t	*d_initial_rover;
+
+extern float	d_sdivzstepu, d_tdivzstepu, d_zistepu;
+extern float	d_sdivzstepv, d_tdivzstepv, d_zistepv;
+extern float	d_sdivzorigin, d_tdivzorigin, d_ziorigin;
+
+fixed16_t	sadjust, tadjust;
+fixed16_t	bbextents, bbextentt;
+
+
+void D_DrawSpans8 (espan_t *pspans);
+void D_DrawSpans16 (espan_t *pspans);
+void D_DrawZSpans (espan_t *pspans);
+void Turbulent8 (espan_t *pspan);
+void D_SpriteDrawSpans (sspan_t *pspan);
+
+void D_DrawSkyScans8 (espan_t *pspan);
+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);
+
+#if id386
+extern void D_PolysetAff8Start (void);
+extern void D_PolysetAff8End (void);
+#endif
+
+extern short *d_pzbuffer;
+extern unsigned int d_zrowbytes, d_zwidth;
+
+extern int	*d_pscantable;
+extern int	d_scantable[MAXHEIGHT];
+
+extern int	d_vrectx, d_vrecty, d_vrectright_particle, d_vrectbottom_particle;
+
+extern int	d_y_aspect_shift, d_pix_min, d_pix_max, d_pix_shift;
+
+extern pixel_t	*d_viewbuffer;
+
+extern short	*zspantable[MAXHEIGHT];
+
+extern int		d_minmip;
+extern float	d_scalemip[3];
+
+extern void (*d_drawspans) (espan_t *pspan);
+
--- /dev/null
+++ b/QW/client/d_modech.c
@@ -1,0 +1,107 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// d_modech.c: called when mode has just changed
+
+#include "quakedef.h"
+#include "d_local.h"
+
+int	d_vrectx, d_vrecty, d_vrectright_particle, d_vrectbottom_particle;
+
+int	d_y_aspect_shift, d_pix_min, d_pix_max, d_pix_shift;
+
+int		d_scantable[MAXHEIGHT];
+short	*zspantable[MAXHEIGHT]; 
+
+/*
+================
+D_Patch
+================
+*/
+void D_Patch (void)
+{
+#if id386
+
+	static qboolean protectset8 = false;
+
+	if (!protectset8)
+	{
+		Sys_MakeCodeWriteable ((int)D_PolysetAff8Start,
+						     (int)D_PolysetAff8End - (int)D_PolysetAff8Start);
+		protectset8 = true;
+	}
+
+#endif	// id386
+}
+
+
+/*
+================
+D_ViewChanged
+================
+*/
+void D_ViewChanged (void)
+{
+	int rowbytes;
+
+	if (r_dowarp)
+		rowbytes = WARP_WIDTH;
+	else
+		rowbytes = vid.rowbytes;
+
+	scale_for_mip = xscale;
+	if (yscale > xscale)
+		scale_for_mip = yscale;
+
+	d_zrowbytes = vid.width * 2;
+	d_zwidth = vid.width;
+
+	d_pix_min = r_refdef.vrect.width / 320;
+	if (d_pix_min < 1)
+		d_pix_min = 1;
+
+	d_pix_max = (int)((float)r_refdef.vrect.width / (320.0 / 4.0) + 0.5);
+	d_pix_shift = 8 - (int)((float)r_refdef.vrect.width / 320.0 + 0.5);
+	if (d_pix_max < 1)
+		d_pix_max = 1;
+
+	if (pixelAspect > 1.4)
+		d_y_aspect_shift = 1;
+	else
+		d_y_aspect_shift = 0;
+
+	d_vrectx = r_refdef.vrect.x;
+	d_vrecty = r_refdef.vrect.y;
+	d_vrectright_particle = r_refdef.vrectright - d_pix_max;
+	d_vrectbottom_particle =
+			r_refdef.vrectbottom - (d_pix_max << d_y_aspect_shift);
+
+	{
+		int		i;
+
+		for (i=0 ; i<vid.height; i++)
+		{
+			d_scantable[i] = i*rowbytes;
+			zspantable[i] = d_pzbuffer + i*d_zwidth;
+		}
+	}
+
+	D_Patch ();
+}
+
--- /dev/null
+++ b/QW/client/d_part.c
@@ -1,0 +1,207 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// d_part.c: software driver module for drawing particles
+
+#include "quakedef.h"
+#include "d_local.h"
+
+
+/*
+==============
+D_EndParticles
+==============
+*/
+void D_EndParticles (void)
+{
+// not used by software driver
+}
+
+
+/*
+==============
+D_StartParticles
+==============
+*/
+void D_StartParticles (void)
+{
+// not used by software driver
+}
+
+
+#if	!id386
+
+/*
+==============
+D_DrawParticle
+==============
+*/
+void D_DrawParticle (particle_t *pparticle)
+{
+	vec3_t	local, transformed;
+	float	zi;
+	byte	*pdest;
+	short	*pz;
+	int		i, izi, pix, count, u, v;
+
+// transform point
+	VectorSubtract (pparticle->org, r_origin, local);
+
+	transformed[0] = DotProduct(local, r_pright);
+	transformed[1] = DotProduct(local, r_pup);
+	transformed[2] = DotProduct(local, r_ppn);		
+
+	if (transformed[2] < PARTICLE_Z_CLIP)
+		return;
+
+// project the point
+// FIXME: preadjust xcenter and ycenter
+	zi = 1.0 / transformed[2];
+	u = (int)(xcenter + zi * transformed[0] + 0.5);
+	v = (int)(ycenter - zi * transformed[1] + 0.5);
+
+	if ((v > d_vrectbottom_particle) || 
+		(u > d_vrectright_particle) ||
+		(v < d_vrecty) ||
+		(u < d_vrectx))
+	{
+		return;
+	}
+
+	pz = d_pzbuffer + (d_zwidth * v) + u;
+	pdest = d_viewbuffer + d_scantable[v] + u;
+	izi = (int)(zi * 0x8000);
+
+	pix = izi >> d_pix_shift;
+
+	if (pix < d_pix_min)
+		pix = d_pix_min;
+	else if (pix > d_pix_max)
+		pix = d_pix_max;
+
+	switch (pix)
+	{
+	case 1:
+		count = 1 << d_y_aspect_shift;
+
+		for ( ; count ; count--, pz += d_zwidth, pdest += screenwidth)
+		{
+			if (pz[0] <= izi)
+			{
+				pz[0] = izi;
+				pdest[0] = pparticle->color;
+			}
+		}
+		break;
+
+	case 2:
+		count = 2 << d_y_aspect_shift;
+
+		for ( ; count ; count--, pz += d_zwidth, pdest += screenwidth)
+		{
+			if (pz[0] <= izi)
+			{
+				pz[0] = izi;
+				pdest[0] = pparticle->color;
+			}
+
+			if (pz[1] <= izi)
+			{
+				pz[1] = izi;
+				pdest[1] = pparticle->color;
+			}
+		}
+		break;
+
+	case 3:
+		count = 3 << d_y_aspect_shift;
+
+		for ( ; count ; count--, pz += d_zwidth, pdest += screenwidth)
+		{
+			if (pz[0] <= izi)
+			{
+				pz[0] = izi;
+				pdest[0] = pparticle->color;
+			}
+
+			if (pz[1] <= izi)
+			{
+				pz[1] = izi;
+				pdest[1] = pparticle->color;
+			}
+
+			if (pz[2] <= izi)
+			{
+				pz[2] = izi;
+				pdest[2] = pparticle->color;
+			}
+		}
+		break;
+
+	case 4:
+		count = 4 << d_y_aspect_shift;
+
+		for ( ; count ; count--, pz += d_zwidth, pdest += screenwidth)
+		{
+			if (pz[0] <= izi)
+			{
+				pz[0] = izi;
+				pdest[0] = pparticle->color;
+			}
+
+			if (pz[1] <= izi)
+			{
+				pz[1] = izi;
+				pdest[1] = pparticle->color;
+			}
+
+			if (pz[2] <= izi)
+			{
+				pz[2] = izi;
+				pdest[2] = pparticle->color;
+			}
+
+			if (pz[3] <= izi)
+			{
+				pz[3] = izi;
+				pdest[3] = pparticle->color;
+			}
+		}
+		break;
+
+	default:
+		count = pix << d_y_aspect_shift;
+
+		for ( ; count ; count--, pz += d_zwidth, pdest += screenwidth)
+		{
+			for (i=0 ; i<pix ; i++)
+			{
+				if (pz[i] <= izi)
+				{
+					pz[i] = izi;
+					pdest[i] = pparticle->color;
+				}
+			}
+		}
+		break;
+	}
+}
+
+#endif	// !id386
+
--- /dev/null
+++ b/QW/client/d_parta.asm
@@ -1,0 +1,557 @@
+ .386P
+ .model FLAT
+ externdef _d_zistepu:dword
+ externdef _d_pzbuffer:dword
+ externdef _d_zistepv:dword
+ externdef _d_zrowbytes:dword
+ externdef _d_ziorigin:dword
+ externdef _r_turb_s:dword
+ externdef _r_turb_t:dword
+ externdef _r_turb_pdest:dword
+ externdef _r_turb_spancount:dword
+ externdef _r_turb_turb:dword
+ externdef _r_turb_pbase:dword
+ externdef _r_turb_sstep:dword
+ externdef _r_turb_tstep:dword
+ externdef _r_bmodelactive:dword
+ externdef _d_sdivzstepu:dword
+ externdef _d_tdivzstepu:dword
+ externdef _d_sdivzstepv:dword
+ externdef _d_tdivzstepv:dword
+ externdef _d_sdivzorigin:dword
+ externdef _d_tdivzorigin:dword
+ externdef _sadjust:dword
+ externdef _tadjust:dword
+ externdef _bbextents:dword
+ externdef _bbextentt:dword
+ externdef _cacheblock:dword
+ externdef _d_viewbuffer:dword
+ externdef _cachewidth:dword
+ externdef _d_pzbuffer:dword
+ externdef _d_zrowbytes:dword
+ externdef _d_zwidth:dword
+ externdef _d_scantable:dword
+ externdef _r_lightptr:dword
+ externdef _r_numvblocks:dword
+ externdef _prowdestbase:dword
+ externdef _pbasesource:dword
+ externdef _r_lightwidth:dword
+ externdef _lightright:dword
+ externdef _lightrightstep:dword
+ externdef _lightdeltastep:dword
+ externdef _lightdelta:dword
+ externdef _lightright:dword
+ externdef _lightdelta:dword
+ externdef _sourcetstep:dword
+ externdef _surfrowbytes:dword
+ externdef _lightrightstep:dword
+ externdef _lightdeltastep:dword
+ externdef _r_sourcemax:dword
+ externdef _r_stepback:dword
+ externdef _colormap:dword
+ externdef _blocksize:dword
+ externdef _sourcesstep:dword
+ externdef _lightleft:dword
+ externdef _blockdivshift:dword
+ externdef _blockdivmask:dword
+ externdef _lightleftstep:dword
+ externdef _r_origin:dword
+ externdef _r_ppn:dword
+ externdef _r_pup:dword
+ externdef _r_pright:dword
+ externdef _ycenter:dword
+ externdef _xcenter:dword
+ externdef _d_vrectbottom_particle:dword
+ externdef _d_vrectright_particle:dword
+ externdef _d_vrecty:dword
+ externdef _d_vrectx:dword
+ externdef _d_pix_shift:dword
+ externdef _d_pix_min:dword
+ externdef _d_pix_max:dword
+ externdef _d_y_aspect_shift:dword
+ externdef _screenwidth:dword
+ externdef _vright:dword
+ externdef _vup:dword
+ externdef _vpn:dword
+ externdef _BOPS_Error:dword
+ externdef _snd_scaletable:dword
+ externdef _paintbuffer:dword
+ externdef _snd_linear_count:dword
+ externdef _snd_p:dword
+ externdef _snd_vol:dword
+ externdef _snd_out:dword
+ externdef _r_leftclipped:dword
+ externdef _r_leftenter:dword
+ externdef _r_rightclipped:dword
+ externdef _r_rightenter:dword
+ externdef _modelorg:dword
+ externdef _xscale:dword
+ externdef _r_refdef:dword
+ externdef _yscale:dword
+ externdef _r_leftexit:dword
+ externdef _r_rightexit:dword
+ externdef _r_lastvertvalid:dword
+ externdef _cacheoffset:dword
+ externdef _newedges:dword
+ externdef _removeedges:dword
+ externdef _r_pedge:dword
+ externdef _r_framecount:dword
+ externdef _r_u1:dword
+ externdef _r_emitted:dword
+ externdef _edge_p:dword
+ externdef _surface_p:dword
+ externdef _surfaces:dword
+ externdef _r_lzi1:dword
+ externdef _r_v1:dword
+ externdef _r_ceilv1:dword
+ externdef _r_nearzi:dword
+ externdef _r_nearzionly:dword
+ externdef _edge_aftertail:dword
+ externdef _edge_tail:dword
+ externdef _current_iv:dword
+ externdef _edge_head_u_shift20:dword
+ externdef _span_p:dword
+ externdef _edge_head:dword
+ externdef _fv:dword
+ externdef _edge_tail_u_shift20:dword
+ externdef _r_apverts:dword
+ externdef _r_anumverts:dword
+ externdef _aliastransform:dword
+ externdef _r_avertexnormals:dword
+ externdef _r_plightvec:dword
+ externdef _r_ambientlight:dword
+ externdef _r_shadelight:dword
+ externdef _aliasxcenter:dword
+ externdef _aliasycenter:dword
+ externdef _a_sstepxfrac:dword
+ externdef _r_affinetridesc:dword
+ externdef _acolormap:dword
+ externdef _d_pcolormap:dword
+ externdef _r_affinetridesc:dword
+ externdef _d_sfrac:dword
+ externdef _d_ptex:dword
+ externdef _d_pedgespanpackage:dword
+ externdef _d_tfrac:dword
+ externdef _d_light:dword
+ externdef _d_zi:dword
+ externdef _d_pdest:dword
+ externdef _d_pz:dword
+ externdef _d_aspancount:dword
+ externdef _erroradjustup:dword
+ externdef _errorterm:dword
+ externdef _d_xdenom:dword
+ externdef _r_p0:dword
+ externdef _r_p1:dword
+ externdef _r_p2:dword
+ externdef _a_tstepxfrac:dword
+ externdef _r_sstepx:dword
+ externdef _r_tstepx:dword
+ externdef _a_ststepxwhole:dword
+ externdef _zspantable:dword
+ externdef _skintable:dword
+ externdef _r_zistepx:dword
+ externdef _erroradjustdown:dword
+ externdef _d_countextrastep:dword
+ externdef _ubasestep:dword
+ externdef _a_ststepxwhole:dword
+ externdef _a_tstepxfrac:dword
+ externdef _r_lstepx:dword
+ externdef _a_spans:dword
+ externdef _erroradjustdown:dword
+ externdef _d_pdestextrastep:dword
+ externdef _d_pzextrastep:dword
+ externdef _d_sfracextrastep:dword
+ externdef _d_ptexextrastep:dword
+ externdef _d_countextrastep:dword
+ externdef _d_tfracextrastep:dword
+ externdef _d_lightextrastep:dword
+ externdef _d_ziextrastep:dword
+ externdef _d_pdestbasestep:dword
+ externdef _d_pzbasestep:dword
+ externdef _d_sfracbasestep:dword
+ externdef _d_ptexbasestep:dword
+ externdef _ubasestep:dword
+ externdef _d_tfracbasestep:dword
+ externdef _d_lightbasestep:dword
+ externdef _d_zibasestep:dword
+ externdef _zspantable:dword
+ externdef _r_lstepy:dword
+ externdef _r_sstepy:dword
+ externdef _r_tstepy:dword
+ externdef _r_zistepy:dword
+ externdef _D_PolysetSetEdgeTable:dword
+ externdef _D_RasterizeAliasPolySmooth:dword
+ externdef float_point5:dword
+ externdef Float2ToThe31nd:dword
+ externdef izistep:dword
+ externdef izi:dword
+ externdef FloatMinus2ToThe31nd:dword
+ externdef float_1:dword
+ externdef float_particle_z_clip:dword
+ externdef float_minus_1:dword
+ externdef float_0:dword
+ externdef fp_16:dword
+ externdef fp_64k:dword
+ externdef fp_1m:dword
+ externdef fp_1m_minus_1:dword
+ externdef fp_8:dword
+ externdef entryvec_table:dword
+ externdef advancetable:dword
+ externdef sstep:dword
+ externdef tstep:dword
+ externdef pspantemp:dword
+ externdef counttemp:dword
+ externdef jumptemp:dword
+ externdef reciprocal_table:dword
+ externdef DP_Count:dword
+ externdef DP_u:dword
+ externdef DP_v:dword
+ externdef DP_32768:dword
+ externdef DP_Color:dword
+ externdef DP_Pix:dword
+ externdef DP_EntryTable:dword
+ externdef pbase:dword
+ externdef s:dword
+ externdef t:dword
+ externdef sfracf:dword
+ externdef tfracf:dword
+ externdef snext:dword
+ externdef tnext:dword
+ externdef spancountminus1:dword
+ externdef zi16stepu:dword
+ externdef sdivz16stepu:dword
+ externdef tdivz16stepu:dword
+ externdef zi8stepu:dword
+ externdef sdivz8stepu:dword
+ externdef tdivz8stepu:dword
+ externdef reciprocal_table_16:dword
+ externdef entryvec_table_16:dword
+ externdef ceil_cw:dword
+ externdef single_cw:dword
+ externdef fp_64kx64k:dword
+ externdef pz:dword
+ externdef spr8entryvec_table:dword
+_TEXT SEGMENT
+ align 4
+ public _D_DrawParticle
+_D_DrawParticle:
+ push ebp
+ push edi
+ push ebx
+ mov edi,ds:dword ptr[12+4+esp]
+ fld ds:dword ptr[_r_origin]
+ fsubr ds:dword ptr[0+edi]
+ fld ds:dword ptr[0+4+edi]
+ fsub ds:dword ptr[_r_origin+4]
+ fld ds:dword ptr[0+8+edi]
+ fsub ds:dword ptr[_r_origin+8]
+ fxch st(2)
+ fld ds:dword ptr[_r_ppn]
+ fmul st(0),st(1)
+ fld ds:dword ptr[_r_ppn+4]
+ fmul st(0),st(3)
+ fld ds:dword ptr[_r_ppn+8]
+ fmul st(0),st(5)
+ fxch st(2)
+ faddp st(1),st(0)
+ faddp st(1),st(0)
+ fld st(0)
+ fdivr ds:dword ptr[float_1]
+ fxch st(1)
+ fcomp ds:dword ptr[float_particle_z_clip]
+ fxch st(3)
+ fld ds:dword ptr[_r_pup]
+ fmul st(0),st(2)
+ fld ds:dword ptr[_r_pup+4]
+ fnstsw ax
+ test ah,1
+ jnz LPop6AndDone
+ fmul st(0),st(4)
+ fld ds:dword ptr[_r_pup+8]
+ fmul st(0),st(3)
+ fxch st(2)
+ faddp st(1),st(0)
+ faddp st(1),st(0)
+ fxch st(3)
+ fmul ds:dword ptr[_r_pright+4]
+ fxch st(2)
+ fmul ds:dword ptr[_r_pright]
+ fxch st(1)
+ fmul ds:dword ptr[_r_pright+8]
+ fxch st(2)
+ faddp st(1),st(0)
+ faddp st(1),st(0)
+ fxch st(1)
+ fmul st(0),st(2)
+ fxch st(1)
+ fmul st(0),st(2)
+ fxch st(1)
+ fsubr ds:dword ptr[_ycenter]
+ fxch st(1)
+ fadd ds:dword ptr[_xcenter]
+ fxch st(1)
+ fadd ds:dword ptr[float_point5]
+ fxch st(1)
+ fadd ds:dword ptr[float_point5]
+ fxch st(2)
+ fmul ds:dword ptr[DP_32768]
+ fxch st(2)
+ fistp ds:dword ptr[DP_u]
+ fistp ds:dword ptr[DP_v]
+ mov eax,ds:dword ptr[DP_u]
+ mov edx,ds:dword ptr[DP_v]
+ mov ebx,ds:dword ptr[_d_vrectbottom_particle]
+ mov ecx,ds:dword ptr[_d_vrectright_particle]
+ cmp edx,ebx
+ jg LPop1AndDone
+ cmp eax,ecx
+ jg LPop1AndDone
+ mov ebx,ds:dword ptr[_d_vrecty]
+ mov ecx,ds:dword ptr[_d_vrectx]
+ cmp edx,ebx
+ jl LPop1AndDone
+ cmp eax,ecx
+ jl LPop1AndDone
+ fld ds:dword ptr[12+edi]
+ fistp ds:dword ptr[DP_Color]
+ mov ebx,ds:dword ptr[_d_viewbuffer]
+ add ebx,eax
+ mov edi,ds:dword ptr[_d_scantable+edx*4]
+ imul edx,ds:dword ptr[_d_zrowbytes]
+ lea edx,ds:dword ptr[edx+eax*2]
+ mov eax,ds:dword ptr[_d_pzbuffer]
+ fistp ds:dword ptr[izi]
+ add edi,ebx
+ add edx,eax
+ mov eax,ds:dword ptr[izi]
+ mov ecx,ds:dword ptr[_d_pix_shift]
+ shr eax,cl
+ mov ebp,ds:dword ptr[izi]
+ mov ebx,ds:dword ptr[_d_pix_min]
+ mov ecx,ds:dword ptr[_d_pix_max]
+ cmp eax,ebx
+ jnl LTestPixMax
+ mov eax,ebx
+ jmp LTestDone
+LTestPixMax:
+ cmp eax,ecx
+ jng LTestDone
+ mov eax,ecx
+LTestDone:
+ mov ch,ds:byte ptr[DP_Color]
+ mov ebx,ds:dword ptr[_d_y_aspect_shift]
+ test ebx,ebx
+ jnz LDefault
+ cmp eax,4
+ ja LDefault
+ jmp dword ptr[DP_EntryTable-4+eax*4]
+ public DP_1x1
+DP_1x1:
+ cmp ds:word ptr[edx],bp
+ jg LDone
+ mov ds:word ptr[edx],bp
+ mov ds:byte ptr[edi],ch
+ jmp LDone
+ public DP_2x2
+DP_2x2:
+ push esi
+ mov ebx,ds:dword ptr[_screenwidth]
+ mov esi,ds:dword ptr[_d_zrowbytes]
+ cmp ds:word ptr[edx],bp
+ jg L2x2_1
+ mov ds:word ptr[edx],bp
+ mov ds:byte ptr[edi],ch
+L2x2_1:
+ cmp ds:word ptr[2+edx],bp
+ jg L2x2_2
+ mov ds:word ptr[2+edx],bp
+ mov ds:byte ptr[1+edi],ch
+L2x2_2:
+ cmp ds:word ptr[edx+esi*1],bp
+ jg L2x2_3
+ mov ds:word ptr[edx+esi*1],bp
+ mov ds:byte ptr[edi+ebx*1],ch
+L2x2_3:
+ cmp ds:word ptr[2+edx+esi*1],bp
+ jg L2x2_4
+ mov ds:word ptr[2+edx+esi*1],bp
+ mov ds:byte ptr[1+edi+ebx*1],ch
+L2x2_4:
+ pop esi
+ jmp LDone
+ public DP_3x3
+DP_3x3:
+ push esi
+ mov ebx,ds:dword ptr[_screenwidth]
+ mov esi,ds:dword ptr[_d_zrowbytes]
+ cmp ds:word ptr[edx],bp
+ jg L3x3_1
+ mov ds:word ptr[edx],bp
+ mov ds:byte ptr[edi],ch
+L3x3_1:
+ cmp ds:word ptr[2+edx],bp
+ jg L3x3_2
+ mov ds:word ptr[2+edx],bp
+ mov ds:byte ptr[1+edi],ch
+L3x3_2:
+ cmp ds:word ptr[4+edx],bp
+ jg L3x3_3
+ mov ds:word ptr[4+edx],bp
+ mov ds:byte ptr[2+edi],ch
+L3x3_3:
+ cmp ds:word ptr[edx+esi*1],bp
+ jg L3x3_4
+ mov ds:word ptr[edx+esi*1],bp
+ mov ds:byte ptr[edi+ebx*1],ch
+L3x3_4:
+ cmp ds:word ptr[2+edx+esi*1],bp
+ jg L3x3_5
+ mov ds:word ptr[2+edx+esi*1],bp
+ mov ds:byte ptr[1+edi+ebx*1],ch
+L3x3_5:
+ cmp ds:word ptr[4+edx+esi*1],bp
+ jg L3x3_6
+ mov ds:word ptr[4+edx+esi*1],bp
+ mov ds:byte ptr[2+edi+ebx*1],ch
+L3x3_6:
+ cmp ds:word ptr[edx+esi*2],bp
+ jg L3x3_7
+ mov ds:word ptr[edx+esi*2],bp
+ mov ds:byte ptr[edi+ebx*2],ch
+L3x3_7:
+ cmp ds:word ptr[2+edx+esi*2],bp
+ jg L3x3_8
+ mov ds:word ptr[2+edx+esi*2],bp
+ mov ds:byte ptr[1+edi+ebx*2],ch
+L3x3_8:
+ cmp ds:word ptr[4+edx+esi*2],bp
+ jg L3x3_9
+ mov ds:word ptr[4+edx+esi*2],bp
+ mov ds:byte ptr[2+edi+ebx*2],ch
+L3x3_9:
+ pop esi
+ jmp LDone
+ public DP_4x4
+DP_4x4:
+ push esi
+ mov ebx,ds:dword ptr[_screenwidth]
+ mov esi,ds:dword ptr[_d_zrowbytes]
+ cmp ds:word ptr[edx],bp
+ jg L4x4_1
+ mov ds:word ptr[edx],bp
+ mov ds:byte ptr[edi],ch
+L4x4_1:
+ cmp ds:word ptr[2+edx],bp
+ jg L4x4_2
+ mov ds:word ptr[2+edx],bp
+ mov ds:byte ptr[1+edi],ch
+L4x4_2:
+ cmp ds:word ptr[4+edx],bp
+ jg L4x4_3
+ mov ds:word ptr[4+edx],bp
+ mov ds:byte ptr[2+edi],ch
+L4x4_3:
+ cmp ds:word ptr[6+edx],bp
+ jg L4x4_4
+ mov ds:word ptr[6+edx],bp
+ mov ds:byte ptr[3+edi],ch
+L4x4_4:
+ cmp ds:word ptr[edx+esi*1],bp
+ jg L4x4_5
+ mov ds:word ptr[edx+esi*1],bp
+ mov ds:byte ptr[edi+ebx*1],ch
+L4x4_5:
+ cmp ds:word ptr[2+edx+esi*1],bp
+ jg L4x4_6
+ mov ds:word ptr[2+edx+esi*1],bp
+ mov ds:byte ptr[1+edi+ebx*1],ch
+L4x4_6:
+ cmp ds:word ptr[4+edx+esi*1],bp
+ jg L4x4_7
+ mov ds:word ptr[4+edx+esi*1],bp
+ mov ds:byte ptr[2+edi+ebx*1],ch
+L4x4_7:
+ cmp ds:word ptr[6+edx+esi*1],bp
+ jg L4x4_8
+ mov ds:word ptr[6+edx+esi*1],bp
+ mov ds:byte ptr[3+edi+ebx*1],ch
+L4x4_8:
+ lea edx,ds:dword ptr[edx+esi*2]
+ lea edi,ds:dword ptr[edi+ebx*2]
+ cmp ds:word ptr[edx],bp
+ jg L4x4_9
+ mov ds:word ptr[edx],bp
+ mov ds:byte ptr[edi],ch
+L4x4_9:
+ cmp ds:word ptr[2+edx],bp
+ jg L4x4_10
+ mov ds:word ptr[2+edx],bp
+ mov ds:byte ptr[1+edi],ch
+L4x4_10:
+ cmp ds:word ptr[4+edx],bp
+ jg L4x4_11
+ mov ds:word ptr[4+edx],bp
+ mov ds:byte ptr[2+edi],ch
+L4x4_11:
+ cmp ds:word ptr[6+edx],bp
+ jg L4x4_12
+ mov ds:word ptr[6+edx],bp
+ mov ds:byte ptr[3+edi],ch
+L4x4_12:
+ cmp ds:word ptr[edx+esi*1],bp
+ jg L4x4_13
+ mov ds:word ptr[edx+esi*1],bp
+ mov ds:byte ptr[edi+ebx*1],ch
+L4x4_13:
+ cmp ds:word ptr[2+edx+esi*1],bp
+ jg L4x4_14
+ mov ds:word ptr[2+edx+esi*1],bp
+ mov ds:byte ptr[1+edi+ebx*1],ch
+L4x4_14:
+ cmp ds:word ptr[4+edx+esi*1],bp
+ jg L4x4_15
+ mov ds:word ptr[4+edx+esi*1],bp
+ mov ds:byte ptr[2+edi+ebx*1],ch
+L4x4_15:
+ cmp ds:word ptr[6+edx+esi*1],bp
+ jg L4x4_16
+ mov ds:word ptr[6+edx+esi*1],bp
+ mov ds:byte ptr[3+edi+ebx*1],ch
+L4x4_16:
+ pop esi
+ jmp LDone
+LDefault:
+ mov ebx,eax
+ mov ds:dword ptr[DP_Pix],eax
+ mov cl,ds:byte ptr[_d_y_aspect_shift]
+ shl ebx,cl
+LGenRowLoop:
+ mov eax,ds:dword ptr[DP_Pix]
+LGenColLoop:
+ cmp ds:word ptr[-2+edx+eax*2],bp
+ jg LGSkip
+ mov ds:word ptr[-2+edx+eax*2],bp
+ mov ds:byte ptr[-1+edi+eax*1],ch
+LGSkip:
+ dec eax
+ jnz LGenColLoop
+ add edx,ds:dword ptr[_d_zrowbytes]
+ add edi,ds:dword ptr[_screenwidth]
+ dec ebx
+ jnz LGenRowLoop
+LDone:
+ pop ebx
+ pop edi
+ pop ebp
+ ret
+LPop6AndDone:
+ fstp st(0)
+ fstp st(0)
+ fstp st(0)
+ fstp st(0)
+ fstp st(0)
+LPop1AndDone:
+ fstp st(0)
+ jmp LDone
+_TEXT ENDS
+ END
--- /dev/null
+++ b/QW/client/d_parta.s
@@ -1,0 +1,477 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+//
+// d_parta.s
+// x86 assembly-language 8-bpp particle-drawing code.
+//
+
+#include "asm_i386.h"
+#include "quakeasm.h"
+#include "d_ifacea.h"
+#include "asm_draw.h"
+
+#if	id386
+
+//----------------------------------------------------------------------
+// 8-bpp particle drawing code.
+//----------------------------------------------------------------------
+
+//FIXME: comments, full optimization
+
+//----------------------------------------------------------------------
+// 8-bpp particle queueing code.
+//----------------------------------------------------------------------
+
+	.text
+
+#define P	12+4
+
+	.align 4
+.globl C(D_DrawParticle)
+C(D_DrawParticle):
+	pushl	%ebp				// preserve caller's stack frame
+	pushl	%edi				// preserve register variables
+	pushl	%ebx
+
+	movl	P(%esp),%edi
+
+// FIXME: better FP overlap in general here
+
+// transform point
+//	VectorSubtract (p->org, r_origin, local);
+	flds	C(r_origin)
+	fsubrs	pt_org(%edi)
+	flds	pt_org+4(%edi)
+	fsubs	C(r_origin)+4
+	flds	pt_org+8(%edi)
+	fsubs	C(r_origin)+8
+	fxch	%st(2)			// local[0] | local[1] | local[2]
+
+//	transformed[2] = DotProduct(local, r_ppn);		
+	flds	C(r_ppn)		// r_ppn[0] | local[0] | local[1] | local[2]
+	fmul	%st(1),%st(0)	// dot0 | local[0] | local[1] | local[2]
+	flds	C(r_ppn)+4	// r_ppn[1] | dot0 | local[0] | local[1] | local[2]
+	fmul	%st(3),%st(0)	// dot1 | dot0 | local[0] | local[1] | local[2]
+	flds	C(r_ppn)+8	// r_ppn[2] | dot1 | dot0 | local[0] |
+						//  local[1] | local[2]
+	fmul	%st(5),%st(0)	// dot2 | dot1 | dot0 | local[0] | local[1] | local[2]
+	fxch	%st(2)		// dot0 | dot1 | dot2 | local[0] | local[1] | local[2]
+	faddp	%st(0),%st(1) // dot0 + dot1 | dot2 | local[0] | local[1] |
+						  //  local[2]
+	faddp	%st(0),%st(1) // z | local[0] | local[1] | local[2]
+	fld		%st(0)		// z | z | local[0] | local[1] |
+						//  local[2]
+	fdivrs	float_1		// 1/z | z | local[0] | local[1] | local[2]
+	fxch	%st(1)		// z | 1/z | local[0] | local[1] | local[2]
+
+//	if (transformed[2] < PARTICLE_Z_CLIP)
+//		return;
+	fcomps	float_particle_z_clip	// 1/z | local[0] | local[1] | local[2]
+	fxch	%st(3)					// local[2] | local[0] | local[1] | 1/z
+
+	flds	C(r_pup)	// r_pup[0] | local[2] | local[0] | local[1] | 1/z
+	fmul	%st(2),%st(0)	// dot0 | local[2] | local[0] | local[1] | 1/z 
+	flds	C(r_pup)+4	// r_pup[1] | dot0 | local[2] | local[0] |
+						//  local[1] | 1/z 
+
+	fnstsw	%ax
+	testb	$1,%ah
+	jnz		LPop6AndDone
+
+//	transformed[1] = DotProduct(local, r_pup);
+	fmul	%st(4),%st(0)	// dot1 | dot0 | local[2] | local[0] | local[1] | 1/z 
+	flds	C(r_pup)+8	// r_pup[2] | dot1 | dot0 | local[2] |
+						//  local[0] | local[1] | 1/z 
+	fmul	%st(3),%st(0)	// dot2 | dot1 | dot0 | local[2] | local[0] |
+						//  local[1] | 1/z 
+	fxch	%st(2)		// dot0 | dot1 | dot2 | local[2] | local[0] |
+						//  local[1] | 1/z 
+	faddp	%st(0),%st(1) // dot0 + dot1 | dot2 | local[2] | local[0] |
+						//  local[1] | 1/z 
+	faddp	%st(0),%st(1) // y | local[2] | local[0] | local[1] | 1/z 
+	fxch	%st(3)		// local[1] | local[2] | local[0] | y | 1/z 
+
+//	transformed[0] = DotProduct(local, r_pright);
+	fmuls	C(r_pright)+4	// dot1 | local[2] | local[0] | y | 1/z
+	fxch	%st(2)		// local[0] | local[2] | dot1 | y | 1/z
+	fmuls	C(r_pright)	// dot0 | local[2] | dot1 | y | 1/z
+	fxch	%st(1)		// local[2] | dot0 | dot1 | y | 1/z
+	fmuls	C(r_pright)+8	// dot2 | dot0 | dot1 | y | 1/z
+	fxch	%st(2)		// dot1 | dot0 | dot2 | y | 1/z
+	faddp	%st(0),%st(1) // dot1 + dot0 | dot2 | y | 1/z
+
+	faddp	%st(0),%st(1)	// x | y | 1/z
+	fxch	%st(1)			// y | x | 1/z
+
+// project the point
+	fmul	%st(2),%st(0)	// y/z | x | 1/z
+	fxch	%st(1)			// x | y/z | 1/z
+	fmul	%st(2),%st(0)	// x/z | y/z | 1/z
+	fxch	%st(1)			// y/z | x/z | 1/z
+	fsubrs	C(ycenter)		// v | x/z | 1/z
+	fxch	%st(1)			// x/z | v | 1/z
+	fadds	C(xcenter)		// u | v | 1/z
+// FIXME: preadjust xcenter and ycenter
+	fxch	%st(1)			// v | u | 1/z
+	fadds	float_point5	// v | u | 1/z
+	fxch	%st(1)			// u | v | 1/z
+	fadds	float_point5	// u | v | 1/z
+	fxch	%st(2)			// 1/z | v | u
+	fmuls	DP_32768		// 1/z * 0x8000 | v | u
+	fxch	%st(2)			// u | v | 1/z * 0x8000
+
+// FIXME: use Terje's fp->int trick here?
+// FIXME: check we're getting proper rounding here
+	fistpl	DP_u			// v | 1/z * 0x8000
+	fistpl	DP_v			// 1/z * 0x8000
+
+	movl	DP_u,%eax
+	movl	DP_v,%edx
+
+// if ((v > d_vrectbottom_particle) || 
+// 	(u > d_vrectright_particle) ||
+// 	(v < d_vrecty) ||
+// 	(u < d_vrectx))
+// {
+// 	continue;
+// }
+
+	movl	C(d_vrectbottom_particle),%ebx
+	movl	C(d_vrectright_particle),%ecx
+	cmpl	%ebx,%edx
+	jg		LPop1AndDone
+	cmpl	%ecx,%eax
+	jg		LPop1AndDone
+	movl	C(d_vrecty),%ebx
+	movl	C(d_vrectx),%ecx
+	cmpl	%ebx,%edx
+	jl		LPop1AndDone
+
+	cmpl	%ecx,%eax
+	jl		LPop1AndDone
+
+	flds	pt_color(%edi)	// color | 1/z * 0x8000
+// FIXME: use Terje's fast fp->int trick?
+	fistpl	DP_Color		// 1/z * 0x8000
+
+	movl	C(d_viewbuffer),%ebx
+
+	addl	%eax,%ebx
+	movl	C(d_scantable)(,%edx,4),%edi		// point to the pixel
+
+	imull	C(d_zrowbytes),%edx		// point to the z pixel
+
+	leal	(%edx,%eax,2),%edx
+	movl	C(d_pzbuffer),%eax
+
+	fistpl	izi
+
+	addl	%ebx,%edi
+	addl	%eax,%edx
+
+// pix = izi >> d_pix_shift;
+
+	movl	izi,%eax
+	movl	C(d_pix_shift),%ecx
+	shrl	%cl,%eax
+	movl	izi,%ebp
+
+// if (pix < d_pix_min)
+// 		pix = d_pix_min;
+// else if (pix > d_pix_max)
+//  	pix = d_pix_max;
+
+	movl	C(d_pix_min),%ebx
+	movl	C(d_pix_max),%ecx
+	cmpl	%ebx,%eax
+	jnl		LTestPixMax
+	movl	%ebx,%eax
+	jmp		LTestDone
+
+LTestPixMax:
+	cmpl	%ecx,%eax
+	jng		LTestDone
+	movl	%ecx,%eax
+LTestDone:
+
+	movb	DP_Color,%ch
+
+	movl	C(d_y_aspect_shift),%ebx
+	testl	%ebx,%ebx
+	jnz		LDefault
+
+	cmpl	$4,%eax
+	ja		LDefault
+
+	jmp		DP_EntryTable-4(,%eax,4)
+
+// 1x1
+.globl	DP_1x1
+DP_1x1:
+	cmpw	%bp,(%edx)		// just one pixel to do
+	jg		LDone
+	movw	%bp,(%edx)
+	movb	%ch,(%edi)
+	jmp		LDone
+
+// 2x2
+.globl	DP_2x2
+DP_2x2:
+	pushl	%esi
+	movl	C(screenwidth),%ebx
+	movl	C(d_zrowbytes),%esi
+
+	cmpw	%bp,(%edx)
+	jg		L2x2_1
+	movw	%bp,(%edx)
+	movb	%ch,(%edi)
+L2x2_1:
+	cmpw	%bp,2(%edx)
+	jg		L2x2_2
+	movw	%bp,2(%edx)
+	movb	%ch,1(%edi)
+L2x2_2:
+	cmpw	%bp,(%edx,%esi,1)
+	jg		L2x2_3
+	movw	%bp,(%edx,%esi,1)
+	movb	%ch,(%edi,%ebx,1)
+L2x2_3:
+	cmpw	%bp,2(%edx,%esi,1)
+	jg		L2x2_4
+	movw	%bp,2(%edx,%esi,1)
+	movb	%ch,1(%edi,%ebx,1)
+L2x2_4:
+
+	popl	%esi
+	jmp		LDone
+
+// 3x3
+.globl	DP_3x3
+DP_3x3:
+	pushl	%esi
+	movl	C(screenwidth),%ebx
+	movl	C(d_zrowbytes),%esi
+
+	cmpw	%bp,(%edx)
+	jg		L3x3_1
+	movw	%bp,(%edx)
+	movb	%ch,(%edi)
+L3x3_1:
+	cmpw	%bp,2(%edx)
+	jg		L3x3_2
+	movw	%bp,2(%edx)
+	movb	%ch,1(%edi)
+L3x3_2:
+	cmpw	%bp,4(%edx)
+	jg		L3x3_3
+	movw	%bp,4(%edx)
+	movb	%ch,2(%edi)
+L3x3_3:
+
+	cmpw	%bp,(%edx,%esi,1)
+	jg		L3x3_4
+	movw	%bp,(%edx,%esi,1)
+	movb	%ch,(%edi,%ebx,1)
+L3x3_4:
+	cmpw	%bp,2(%edx,%esi,1)
+	jg		L3x3_5
+	movw	%bp,2(%edx,%esi,1)
+	movb	%ch,1(%edi,%ebx,1)
+L3x3_5:
+	cmpw	%bp,4(%edx,%esi,1)
+	jg		L3x3_6
+	movw	%bp,4(%edx,%esi,1)
+	movb	%ch,2(%edi,%ebx,1)
+L3x3_6:
+
+	cmpw	%bp,(%edx,%esi,2)
+	jg		L3x3_7
+	movw	%bp,(%edx,%esi,2)
+	movb	%ch,(%edi,%ebx,2)
+L3x3_7:
+	cmpw	%bp,2(%edx,%esi,2)
+	jg		L3x3_8
+	movw	%bp,2(%edx,%esi,2)
+	movb	%ch,1(%edi,%ebx,2)
+L3x3_8:
+	cmpw	%bp,4(%edx,%esi,2)
+	jg		L3x3_9
+	movw	%bp,4(%edx,%esi,2)
+	movb	%ch,2(%edi,%ebx,2)
+L3x3_9:
+
+	popl	%esi
+	jmp		LDone
+
+
+// 4x4
+.globl	DP_4x4
+DP_4x4:
+	pushl	%esi
+	movl	C(screenwidth),%ebx
+	movl	C(d_zrowbytes),%esi
+
+	cmpw	%bp,(%edx)
+	jg		L4x4_1
+	movw	%bp,(%edx)
+	movb	%ch,(%edi)
+L4x4_1:
+	cmpw	%bp,2(%edx)
+	jg		L4x4_2
+	movw	%bp,2(%edx)
+	movb	%ch,1(%edi)
+L4x4_2:
+	cmpw	%bp,4(%edx)
+	jg		L4x4_3
+	movw	%bp,4(%edx)
+	movb	%ch,2(%edi)
+L4x4_3:
+	cmpw	%bp,6(%edx)
+	jg		L4x4_4
+	movw	%bp,6(%edx)
+	movb	%ch,3(%edi)
+L4x4_4:
+
+	cmpw	%bp,(%edx,%esi,1)
+	jg		L4x4_5
+	movw	%bp,(%edx,%esi,1)
+	movb	%ch,(%edi,%ebx,1)
+L4x4_5:
+	cmpw	%bp,2(%edx,%esi,1)
+	jg		L4x4_6
+	movw	%bp,2(%edx,%esi,1)
+	movb	%ch,1(%edi,%ebx,1)
+L4x4_6:
+	cmpw	%bp,4(%edx,%esi,1)
+	jg		L4x4_7
+	movw	%bp,4(%edx,%esi,1)
+	movb	%ch,2(%edi,%ebx,1)
+L4x4_7:
+	cmpw	%bp,6(%edx,%esi,1)
+	jg		L4x4_8
+	movw	%bp,6(%edx,%esi,1)
+	movb	%ch,3(%edi,%ebx,1)
+L4x4_8:
+
+	leal	(%edx,%esi,2),%edx
+	leal	(%edi,%ebx,2),%edi
+
+	cmpw	%bp,(%edx)
+	jg		L4x4_9
+	movw	%bp,(%edx)
+	movb	%ch,(%edi)
+L4x4_9:
+	cmpw	%bp,2(%edx)
+	jg		L4x4_10
+	movw	%bp,2(%edx)
+	movb	%ch,1(%edi)
+L4x4_10:
+	cmpw	%bp,4(%edx)
+	jg		L4x4_11
+	movw	%bp,4(%edx)
+	movb	%ch,2(%edi)
+L4x4_11:
+	cmpw	%bp,6(%edx)
+	jg		L4x4_12
+	movw	%bp,6(%edx)
+	movb	%ch,3(%edi)
+L4x4_12:
+
+	cmpw	%bp,(%edx,%esi,1)
+	jg		L4x4_13
+	movw	%bp,(%edx,%esi,1)
+	movb	%ch,(%edi,%ebx,1)
+L4x4_13:
+	cmpw	%bp,2(%edx,%esi,1)
+	jg		L4x4_14
+	movw	%bp,2(%edx,%esi,1)
+	movb	%ch,1(%edi,%ebx,1)
+L4x4_14:
+	cmpw	%bp,4(%edx,%esi,1)
+	jg		L4x4_15
+	movw	%bp,4(%edx,%esi,1)
+	movb	%ch,2(%edi,%ebx,1)
+L4x4_15:
+	cmpw	%bp,6(%edx,%esi,1)
+	jg		L4x4_16
+	movw	%bp,6(%edx,%esi,1)
+	movb	%ch,3(%edi,%ebx,1)
+L4x4_16:
+
+	popl	%esi
+	jmp		LDone
+
+// default case, handling any size particle
+LDefault:
+
+// count = pix << d_y_aspect_shift;
+
+	movl	%eax,%ebx
+	movl	%eax,DP_Pix
+	movb	C(d_y_aspect_shift),%cl
+	shll	%cl,%ebx
+
+// for ( ; count ; count--, pz += d_zwidth, pdest += screenwidth)
+// {
+// 	for (i=0 ; i<pix ; i++)
+// 	{
+// 		if (pz[i] <= izi)
+// 		{
+// 			pz[i] = izi;
+// 			pdest[i] = color;
+// 		}
+// 	}
+// }
+
+LGenRowLoop:
+	movl	DP_Pix,%eax
+
+LGenColLoop:
+	cmpw	%bp,-2(%edx,%eax,2)
+	jg		LGSkip
+	movw	%bp,-2(%edx,%eax,2)
+	movb	%ch,-1(%edi,%eax,1)
+LGSkip:
+	decl	%eax			// --pix
+	jnz		LGenColLoop
+
+	addl	C(d_zrowbytes),%edx
+	addl	C(screenwidth),%edi
+
+	decl	%ebx			// --count
+	jnz		LGenRowLoop
+
+LDone:
+	popl	%ebx				// restore register variables
+	popl	%edi
+	popl	%ebp				// restore the caller's stack frame
+	ret
+
+LPop6AndDone:
+	fstp	%st(0)
+	fstp	%st(0)
+	fstp	%st(0)
+	fstp	%st(0)
+	fstp	%st(0)
+LPop1AndDone:
+	fstp	%st(0)
+	jmp		LDone
+
+#endif	// id386
--- /dev/null
+++ b/QW/client/d_polysa.asm
@@ -1,0 +1,1120 @@
+ .386P
+ .model FLAT
+ externdef _d_zistepu:dword
+ externdef _d_pzbuffer:dword
+ externdef _d_zistepv:dword
+ externdef _d_zrowbytes:dword
+ externdef _d_ziorigin:dword
+ externdef _r_turb_s:dword
+ externdef _r_turb_t:dword
+ externdef _r_turb_pdest:dword
+ externdef _r_turb_spancount:dword
+ externdef _r_turb_turb:dword
+ externdef _r_turb_pbase:dword
+ externdef _r_turb_sstep:dword
+ externdef _r_turb_tstep:dword
+ externdef _r_bmodelactive:dword
+ externdef _d_sdivzstepu:dword
+ externdef _d_tdivzstepu:dword
+ externdef _d_sdivzstepv:dword
+ externdef _d_tdivzstepv:dword
+ externdef _d_sdivzorigin:dword
+ externdef _d_tdivzorigin:dword
+ externdef _sadjust:dword
+ externdef _tadjust:dword
+ externdef _bbextents:dword
+ externdef _bbextentt:dword
+ externdef _cacheblock:dword
+ externdef _d_viewbuffer:dword
+ externdef _cachewidth:dword
+ externdef _d_pzbuffer:dword
+ externdef _d_zrowbytes:dword
+ externdef _d_zwidth:dword
+ externdef _d_scantable:dword
+ externdef _r_lightptr:dword
+ externdef _r_numvblocks:dword
+ externdef _prowdestbase:dword
+ externdef _pbasesource:dword
+ externdef _r_lightwidth:dword
+ externdef _lightright:dword
+ externdef _lightrightstep:dword
+ externdef _lightdeltastep:dword
+ externdef _lightdelta:dword
+ externdef _lightright:dword
+ externdef _lightdelta:dword
+ externdef _sourcetstep:dword
+ externdef _surfrowbytes:dword
+ externdef _lightrightstep:dword
+ externdef _lightdeltastep:dword
+ externdef _r_sourcemax:dword
+ externdef _r_stepback:dword
+ externdef _colormap:dword
+ externdef _blocksize:dword
+ externdef _sourcesstep:dword
+ externdef _lightleft:dword
+ externdef _blockdivshift:dword
+ externdef _blockdivmask:dword
+ externdef _lightleftstep:dword
+ externdef _r_origin:dword
+ externdef _r_ppn:dword
+ externdef _r_pup:dword
+ externdef _r_pright:dword
+ externdef _ycenter:dword
+ externdef _xcenter:dword
+ externdef _d_vrectbottom_particle:dword
+ externdef _d_vrectright_particle:dword
+ externdef _d_vrecty:dword
+ externdef _d_vrectx:dword
+ externdef _d_pix_shift:dword
+ externdef _d_pix_min:dword
+ externdef _d_pix_max:dword
+ externdef _d_y_aspect_shift:dword
+ externdef _screenwidth:dword
+ externdef _vright:dword
+ externdef _vup:dword
+ externdef _vpn:dword
+ externdef _BOPS_Error:dword
+ externdef _snd_scaletable:dword
+ externdef _paintbuffer:dword
+ externdef _snd_linear_count:dword
+ externdef _snd_p:dword
+ externdef _snd_vol:dword
+ externdef _snd_out:dword
+ externdef _r_leftclipped:dword
+ externdef _r_leftenter:dword
+ externdef _r_rightclipped:dword
+ externdef _r_rightenter:dword
+ externdef _modelorg:dword
+ externdef _xscale:dword
+ externdef _r_refdef:dword
+ externdef _yscale:dword
+ externdef _r_leftexit:dword
+ externdef _r_rightexit:dword
+ externdef _r_lastvertvalid:dword
+ externdef _cacheoffset:dword
+ externdef _newedges:dword
+ externdef _removeedges:dword
+ externdef _r_pedge:dword
+ externdef _r_framecount:dword
+ externdef _r_u1:dword
+ externdef _r_emitted:dword
+ externdef _edge_p:dword
+ externdef _surface_p:dword
+ externdef _surfaces:dword
+ externdef _r_lzi1:dword
+ externdef _r_v1:dword
+ externdef _r_ceilv1:dword
+ externdef _r_nearzi:dword
+ externdef _r_nearzionly:dword
+ externdef _edge_aftertail:dword
+ externdef _edge_tail:dword
+ externdef _current_iv:dword
+ externdef _edge_head_u_shift20:dword
+ externdef _span_p:dword
+ externdef _edge_head:dword
+ externdef _fv:dword
+ externdef _edge_tail_u_shift20:dword
+ externdef _r_apverts:dword
+ externdef _r_anumverts:dword
+ externdef _aliastransform:dword
+ externdef _r_avertexnormals:dword
+ externdef _r_plightvec:dword
+ externdef _r_ambientlight:dword
+ externdef _r_shadelight:dword
+ externdef _aliasxcenter:dword
+ externdef _aliasycenter:dword
+ externdef _a_sstepxfrac:dword
+ externdef _r_affinetridesc:dword
+ externdef _acolormap:dword
+ externdef _d_pcolormap:dword
+ externdef _r_affinetridesc:dword
+ externdef _d_sfrac:dword
+ externdef _d_ptex:dword
+ externdef _d_pedgespanpackage:dword
+ externdef _d_tfrac:dword
+ externdef _d_light:dword
+ externdef _d_zi:dword
+ externdef _d_pdest:dword
+ externdef _d_pz:dword
+ externdef _d_aspancount:dword
+ externdef _erroradjustup:dword
+ externdef _errorterm:dword
+ externdef _d_xdenom:dword
+ externdef _r_p0:dword
+ externdef _r_p1:dword
+ externdef _r_p2:dword
+ externdef _a_tstepxfrac:dword
+ externdef _r_sstepx:dword
+ externdef _r_tstepx:dword
+ externdef _a_ststepxwhole:dword
+ externdef _zspantable:dword
+ externdef _skintable:dword
+ externdef _r_zistepx:dword
+ externdef _erroradjustdown:dword
+ externdef _d_countextrastep:dword
+ externdef _ubasestep:dword
+ externdef _a_ststepxwhole:dword
+ externdef _a_tstepxfrac:dword
+ externdef _r_lstepx:dword
+ externdef _a_spans:dword
+ externdef _erroradjustdown:dword
+ externdef _d_pdestextrastep:dword
+ externdef _d_pzextrastep:dword
+ externdef _d_sfracextrastep:dword
+ externdef _d_ptexextrastep:dword
+ externdef _d_countextrastep:dword
+ externdef _d_tfracextrastep:dword
+ externdef _d_lightextrastep:dword
+ externdef _d_ziextrastep:dword
+ externdef _d_pdestbasestep:dword
+ externdef _d_pzbasestep:dword
+ externdef _d_sfracbasestep:dword
+ externdef _d_ptexbasestep:dword
+ externdef _ubasestep:dword
+ externdef _d_tfracbasestep:dword
+ externdef _d_lightbasestep:dword
+ externdef _d_zibasestep:dword
+ externdef _zspantable:dword
+ externdef _r_lstepy:dword
+ externdef _r_sstepy:dword
+ externdef _r_tstepy:dword
+ externdef _r_zistepy:dword
+ externdef _D_PolysetSetEdgeTable:dword
+ externdef _D_RasterizeAliasPolySmooth:dword
+ externdef float_point5:dword
+ externdef Float2ToThe31nd:dword
+ externdef izistep:dword
+ externdef izi:dword
+ externdef FloatMinus2ToThe31nd:dword
+ externdef float_1:dword
+ externdef float_particle_z_clip:dword
+ externdef float_minus_1:dword
+ externdef float_0:dword
+ externdef fp_16:dword
+ externdef fp_64k:dword
+ externdef fp_1m:dword
+ externdef fp_1m_minus_1:dword
+ externdef fp_8:dword
+ externdef entryvec_table:dword
+ externdef advancetable:dword
+ externdef sstep:dword
+ externdef tstep:dword
+ externdef pspantemp:dword
+ externdef counttemp:dword
+ externdef jumptemp:dword
+ externdef reciprocal_table:dword
+ externdef DP_Count:dword
+ externdef DP_u:dword
+ externdef DP_v:dword
+ externdef DP_32768:dword
+ externdef DP_Color:dword
+ externdef DP_Pix:dword
+ externdef DP_EntryTable:dword
+ externdef pbase:dword
+ externdef s:dword
+ externdef t:dword
+ externdef sfracf:dword
+ externdef tfracf:dword
+ externdef snext:dword
+ externdef tnext:dword
+ externdef spancountminus1:dword
+ externdef zi16stepu:dword
+ externdef sdivz16stepu:dword
+ externdef tdivz16stepu:dword
+ externdef zi8stepu:dword
+ externdef sdivz8stepu:dword
+ externdef tdivz8stepu:dword
+ externdef reciprocal_table_16:dword
+ externdef entryvec_table_16:dword
+ externdef ceil_cw:dword
+ externdef single_cw:dword
+ externdef fp_64kx64k:dword
+ externdef pz:dword
+ externdef spr8entryvec_table:dword
+_DATA SEGMENT
+ align 4
+p10_minus_p20 dd 0
+p01_minus_p21 dd 0
+temp0 dd 0
+temp1 dd 0
+Ltemp dd 0
+aff8entryvec_table dd LDraw8, LDraw7, LDraw6, LDraw5
+ dd LDraw4, LDraw3, LDraw2, LDraw1
+lzistepx dd 0
+_DATA ENDS
+_TEXT SEGMENT
+ externdef _D_PolysetSetEdgeTable:dword
+ externdef _D_RasterizeAliasPolySmooth:dword
+ public _D_PolysetCalcGradients
+_D_PolysetCalcGradients:
+ fild ds:dword ptr[_r_p0+0]
+ fild ds:dword ptr[_r_p2+0]
+ fild ds:dword ptr[_r_p0+4]
+ fild ds:dword ptr[_r_p2+4]
+ fild ds:dword ptr[_r_p1+0]
+ fild ds:dword ptr[_r_p1+4]
+ fxch st(3)
+ fsub st(0),st(2)
+ fxch st(1)
+ fsub st(0),st(4)
+ fxch st(5)
+ fsubrp st(4),st(0)
+ fxch st(2)
+ fsubrp st(1),st(0)
+ fxch st(1)
+ fld ds:dword ptr[_d_xdenom]
+ fxch st(4)
+ fstp ds:dword ptr[p10_minus_p20]
+ fstp ds:dword ptr[p01_minus_p21]
+ fxch st(2)
+ fild ds:dword ptr[_r_p2+16]
+ fild ds:dword ptr[_r_p0+16]
+ fild ds:dword ptr[_r_p1+16]
+ fxch st(2)
+ fld st(0)
+ fsubp st(2),st(0)
+ fsubp st(2),st(0)
+ fld st(0)
+ fmul st(0),st(5)
+ fxch st(2)
+ fld st(0)
+ fmul ds:dword ptr[p01_minus_p21]
+ fxch st(2)
+ fmul ds:dword ptr[p10_minus_p20]
+ fxch st(1)
+ fmul st(0),st(5)
+ fxch st(2)
+ fsubrp st(3),st(0)
+ fsubp st(1),st(0)
+ fld st(2)
+ fmul ds:dword ptr[float_minus_1]
+ fxch st(2)
+ fmul st(0),st(3)
+ fxch st(1)
+ fmul st(0),st(2)
+ fldcw ds:word ptr[ceil_cw]
+ fistp ds:dword ptr[_r_lstepy]
+ fistp ds:dword ptr[_r_lstepx]
+ fldcw ds:word ptr[single_cw]
+ fild ds:dword ptr[_r_p2+8]
+ fild ds:dword ptr[_r_p0+8]
+ fild ds:dword ptr[_r_p1+8]
+ fxch st(2)
+ fld st(0)
+ fsubp st(2),st(0)
+ fsubp st(2),st(0)
+ fld st(0)
+ fmul st(0),st(6)
+ fxch st(2)
+ fld st(0)
+ fmul ds:dword ptr[p01_minus_p21]
+ fxch st(2)
+ fmul ds:dword ptr[p10_minus_p20]
+ fxch st(1)
+ fmul st(0),st(6)
+ fxch st(2)
+ fsubrp st(3),st(0)
+ fsubp st(1),st(0)
+ fmul st(0),st(2)
+ fxch st(1)
+ fmul st(0),st(3)
+ fxch st(1)
+ fistp ds:dword ptr[_r_sstepy]
+ fistp ds:dword ptr[_r_sstepx]
+ fild ds:dword ptr[_r_p2+12]
+ fild ds:dword ptr[_r_p0+12]
+ fild ds:dword ptr[_r_p1+12]
+ fxch st(2)
+ fld st(0)
+ fsubp st(2),st(0)
+ fsubp st(2),st(0)
+ fld st(0)
+ fmul st(0),st(6)
+ fxch st(2)
+ fld st(0)
+ fmul ds:dword ptr[p01_minus_p21]
+ fxch st(2)
+ fmul ds:dword ptr[p10_minus_p20]
+ fxch st(1)
+ fmul st(0),st(6)
+ fxch st(2)
+ fsubrp st(3),st(0)
+ fsubp st(1),st(0)
+ fmul st(0),st(2)
+ fxch st(1)
+ fmul st(0),st(3)
+ fxch st(1)
+ fistp ds:dword ptr[_r_tstepy]
+ fistp ds:dword ptr[_r_tstepx]
+ fild ds:dword ptr[_r_p2+20]
+ fild ds:dword ptr[_r_p0+20]
+ fild ds:dword ptr[_r_p1+20]
+ fxch st(2)
+ fld st(0)
+ fsubp st(2),st(0)
+ fsubp st(2),st(0)
+ fld st(0)
+ fmulp st(6),st(0)
+ fxch st(1)
+ fld st(0)
+ fmul ds:dword ptr[p01_minus_p21]
+ fxch st(2)
+ fmul ds:dword ptr[p10_minus_p20]
+ fxch st(1)
+ fmulp st(5),st(0)
+ fxch st(5)
+ fsubp st(1),st(0)
+ fxch st(3)
+ fsubrp st(4),st(0)
+ fxch st(1)
+ fmulp st(2),st(0)
+ fmulp st(2),st(0)
+ fistp ds:dword ptr[_r_zistepx]
+ fistp ds:dword ptr[_r_zistepy]
+ mov eax,ds:dword ptr[_r_sstepx]
+ mov edx,ds:dword ptr[_r_tstepx]
+ shl eax,16
+ shl edx,16
+ mov ds:dword ptr[_a_sstepxfrac],eax
+ mov ds:dword ptr[_a_tstepxfrac],edx
+ mov ecx,ds:dword ptr[_r_sstepx]
+ mov eax,ds:dword ptr[_r_tstepx]
+ sar ecx,16
+ sar eax,16
+ imul ds:dword ptr[4+0+esp]
+ add eax,ecx
+ mov ds:dword ptr[_a_ststepxwhole],eax
+ ret
+ public _D_PolysetRecursiveTriangle
+_D_PolysetRecursiveTriangle:
+ push ebp
+ push esi
+ push edi
+ push ebx
+ mov esi,ds:dword ptr[8+16+esp]
+ mov ebx,ds:dword ptr[4+16+esp]
+ mov edi,ds:dword ptr[12+16+esp]
+ mov eax,ds:dword ptr[0+esi]
+ mov edx,ds:dword ptr[0+ebx]
+ mov ebp,ds:dword ptr[4+esi]
+ sub eax,edx
+ mov ecx,ds:dword ptr[4+ebx]
+ sub ebp,ecx
+ inc eax
+ cmp eax,2
+ ja LSplit
+ mov eax,ds:dword ptr[0+edi]
+ inc ebp
+ cmp ebp,2
+ ja LSplit
+ mov edx,ds:dword ptr[0+esi]
+ mov ebp,ds:dword ptr[4+edi]
+ sub eax,edx
+ mov ecx,ds:dword ptr[4+esi]
+ sub ebp,ecx
+ inc eax
+ cmp eax,2
+ ja LSplit2
+ mov eax,ds:dword ptr[0+ebx]
+ inc ebp
+ cmp ebp,2
+ ja LSplit2
+ mov edx,ds:dword ptr[0+edi]
+ mov ebp,ds:dword ptr[4+ebx]
+ sub eax,edx
+ mov ecx,ds:dword ptr[4+edi]
+ sub ebp,ecx
+ inc eax
+ inc ebp
+ mov edx,ebx
+ cmp eax,2
+ ja LSplit3
+ cmp ebp,2
+ jna LDone
+LSplit3:
+ mov ebx,edi
+ mov edi,esi
+ mov esi,edx
+ jmp LSplit
+LSplit2:
+ mov eax,ebx
+ mov ebx,esi
+ mov esi,edi
+ mov edi,eax
+LSplit:
+ sub esp,24
+ mov eax,ds:dword ptr[8+ebx]
+ mov edx,ds:dword ptr[8+esi]
+ mov ecx,ds:dword ptr[12+ebx]
+ add eax,edx
+ mov edx,ds:dword ptr[12+esi]
+ sar eax,1
+ add ecx,edx
+ mov ds:dword ptr[8+esp],eax
+ mov eax,ds:dword ptr[20+ebx]
+ sar ecx,1
+ mov edx,ds:dword ptr[20+esi]
+ mov ds:dword ptr[12+esp],ecx
+ add eax,edx
+ mov ecx,ds:dword ptr[0+ebx]
+ mov edx,ds:dword ptr[0+esi]
+ sar eax,1
+ add edx,ecx
+ mov ds:dword ptr[20+esp],eax
+ mov eax,ds:dword ptr[4+ebx]
+ sar edx,1
+ mov ebp,ds:dword ptr[4+esi]
+ mov ds:dword ptr[0+esp],edx
+ add ebp,eax
+ sar ebp,1
+ mov ds:dword ptr[4+esp],ebp
+ cmp ds:dword ptr[4+esi],eax
+ jg LNoDraw
+ mov edx,ds:dword ptr[0+esi]
+ jnz LDraw
+ cmp edx,ecx
+ jl LNoDraw
+LDraw:
+ mov edx,ds:dword ptr[20+esp]
+ mov ecx,ds:dword ptr[4+esp]
+ sar edx,16
+ mov ebp,ds:dword ptr[0+esp]
+ mov eax,ds:dword ptr[_zspantable+ecx*4]
+ cmp dx,ds:word ptr[eax+ebp*2]
+ jnge LNoDraw
+ mov ds:word ptr[eax+ebp*2],dx
+ mov eax,ds:dword ptr[12+esp]
+ sar eax,16
+ mov edx,ds:dword ptr[8+esp]
+ sar edx,16
+ sub ecx,ecx
+ mov eax,ds:dword ptr[_skintable+eax*4]
+ mov ebp,ds:dword ptr[4+esp]
+ mov cl,ds:byte ptr[eax+edx]
+ mov edx,ds:dword ptr[_d_pcolormap]
+ mov dl,ds:byte ptr[edx+ecx]
+ mov ecx,ds:dword ptr[0+esp]
+ mov eax,ds:dword ptr[_d_scantable+ebp*4]
+ add ecx,eax
+ mov eax,ds:dword ptr[_d_viewbuffer]
+ mov ds:byte ptr[eax+ecx*1],dl
+LNoDraw:
+ push esp
+ push ebx
+ push edi
+ call near ptr _D_PolysetRecursiveTriangle
+ mov ebx,esp
+ push esi
+ push ebx
+ push edi
+ call near ptr _D_PolysetRecursiveTriangle
+ add esp,24
+LDone:
+ pop ebx
+ pop edi
+ pop esi
+ pop ebp
+ ret 12
+ public _D_PolysetAff8Start
+_D_PolysetAff8Start:
+ public _D_PolysetDrawSpans8
+_D_PolysetDrawSpans8:
+ push esi
+ push ebx
+ mov esi,ds:dword ptr[4+8+esp]
+ mov ecx,ds:dword ptr[_r_zistepx]
+ push ebp
+ push edi
+ ror ecx,16
+ mov edx,ds:dword ptr[8+esi]
+ mov ds:dword ptr[lzistepx],ecx
+LSpanLoop:
+ mov eax,ds:dword ptr[_d_aspancount]
+ sub eax,edx
+ mov edx,ds:dword ptr[_erroradjustup]
+ mov ebx,ds:dword ptr[_errorterm]
+ add ebx,edx
+ js LNoTurnover
+ mov edx,ds:dword ptr[_erroradjustdown]
+ mov edi,ds:dword ptr[_d_countextrastep]
+ sub ebx,edx
+ mov ebp,ds:dword ptr[_d_aspancount]
+ mov ds:dword ptr[_errorterm],ebx
+ add ebp,edi
+ mov ds:dword ptr[_d_aspancount],ebp
+ jmp LRightEdgeStepped
+LNoTurnover:
+ mov edi,ds:dword ptr[_d_aspancount]
+ mov edx,ds:dword ptr[_ubasestep]
+ mov ds:dword ptr[_errorterm],ebx
+ add edi,edx
+ mov ds:dword ptr[_d_aspancount],edi
+LRightEdgeStepped:
+ cmp eax,1
+ jl LNextSpan
+ jz LExactlyOneLong
+ mov ecx,ds:dword ptr[_a_ststepxwhole]
+ mov edx,ds:dword ptr[_r_affinetridesc+8]
+ mov ds:dword ptr[advancetable+4],ecx
+ add ecx,edx
+ mov ds:dword ptr[advancetable],ecx
+ mov ecx,ds:dword ptr[_a_tstepxfrac]
+ mov cx,ds:word ptr[_r_lstepx]
+ mov edx,eax
+ mov ds:dword ptr[tstep],ecx
+ add edx,7
+ shr edx,3
+ mov ebx,ds:dword ptr[16+esi]
+ mov bx,dx
+ mov ecx,ds:dword ptr[4+esi]
+ neg eax
+ mov edi,ds:dword ptr[0+esi]
+ and eax,7
+ sub edi,eax
+ sub ecx,eax
+ sub ecx,eax
+ mov edx,ds:dword ptr[20+esi]
+ mov dx,ds:word ptr[24+esi]
+ mov ebp,ds:dword ptr[28+esi]
+ ror ebp,16
+ push esi
+ mov esi,ds:dword ptr[12+esi]
+ jmp dword ptr[aff8entryvec_table+eax*4]
+LDrawLoop:
+LDraw8:
+ cmp bp,ds:word ptr[ecx]
+ jl Lp1
+ xor eax,eax
+ mov ah,dh
+ mov al,ds:byte ptr[esi]
+ mov ds:word ptr[ecx],bp
+ mov al,ds:byte ptr[12345678h+eax]
+LPatch8:
+ mov ds:byte ptr[edi],al
+Lp1:
+ add edx,ds:dword ptr[tstep]
+ sbb eax,eax
+ add ebp,ds:dword ptr[lzistepx]
+ adc ebp,0
+ add ebx,ds:dword ptr[_a_sstepxfrac]
+ adc esi,ds:dword ptr[advancetable+4+eax*4]
+LDraw7:
+ cmp bp,ds:word ptr[2+ecx]
+ jl Lp2
+ xor eax,eax
+ mov ah,dh
+ mov al,ds:byte ptr[esi]
+ mov ds:word ptr[2+ecx],bp
+ mov al,ds:byte ptr[12345678h+eax]
+LPatch7:
+ mov ds:byte ptr[1+edi],al
+Lp2:
+ add edx,ds:dword ptr[tstep]
+ sbb eax,eax
+ add ebp,ds:dword ptr[lzistepx]
+ adc ebp,0
+ add ebx,ds:dword ptr[_a_sstepxfrac]
+ adc esi,ds:dword ptr[advancetable+4+eax*4]
+LDraw6:
+ cmp bp,ds:word ptr[4+ecx]
+ jl Lp3
+ xor eax,eax
+ mov ah,dh
+ mov al,ds:byte ptr[esi]
+ mov ds:word ptr[4+ecx],bp
+ mov al,ds:byte ptr[12345678h+eax]
+LPatch6:
+ mov ds:byte ptr[2+edi],al
+Lp3:
+ add edx,ds:dword ptr[tstep]
+ sbb eax,eax
+ add ebp,ds:dword ptr[lzistepx]
+ adc ebp,0
+ add ebx,ds:dword ptr[_a_sstepxfrac]
+ adc esi,ds:dword ptr[advancetable+4+eax*4]
+LDraw5:
+ cmp bp,ds:word ptr[6+ecx]
+ jl Lp4
+ xor eax,eax
+ mov ah,dh
+ mov al,ds:byte ptr[esi]
+ mov ds:word ptr[6+ecx],bp
+ mov al,ds:byte ptr[12345678h+eax]
+LPatch5:
+ mov ds:byte ptr[3+edi],al
+Lp4:
+ add edx,ds:dword ptr[tstep]
+ sbb eax,eax
+ add ebp,ds:dword ptr[lzistepx]
+ adc ebp,0
+ add ebx,ds:dword ptr[_a_sstepxfrac]
+ adc esi,ds:dword ptr[advancetable+4+eax*4]
+LDraw4:
+ cmp bp,ds:word ptr[8+ecx]
+ jl Lp5
+ xor eax,eax
+ mov ah,dh
+ mov al,ds:byte ptr[esi]
+ mov ds:word ptr[8+ecx],bp
+ mov al,ds:byte ptr[12345678h+eax]
+LPatch4:
+ mov ds:byte ptr[4+edi],al
+Lp5:
+ add edx,ds:dword ptr[tstep]
+ sbb eax,eax
+ add ebp,ds:dword ptr[lzistepx]
+ adc ebp,0
+ add ebx,ds:dword ptr[_a_sstepxfrac]
+ adc esi,ds:dword ptr[advancetable+4+eax*4]
+LDraw3:
+ cmp bp,ds:word ptr[10+ecx]
+ jl Lp6
+ xor eax,eax
+ mov ah,dh
+ mov al,ds:byte ptr[esi]
+ mov ds:word ptr[10+ecx],bp
+ mov al,ds:byte ptr[12345678h+eax]
+LPatch3:
+ mov ds:byte ptr[5+edi],al
+Lp6:
+ add edx,ds:dword ptr[tstep]
+ sbb eax,eax
+ add ebp,ds:dword ptr[lzistepx]
+ adc ebp,0
+ add ebx,ds:dword ptr[_a_sstepxfrac]
+ adc esi,ds:dword ptr[advancetable+4+eax*4]
+LDraw2:
+ cmp bp,ds:word ptr[12+ecx]
+ jl Lp7
+ xor eax,eax
+ mov ah,dh
+ mov al,ds:byte ptr[esi]
+ mov ds:word ptr[12+ecx],bp
+ mov al,ds:byte ptr[12345678h+eax]
+LPatch2:
+ mov ds:byte ptr[6+edi],al
+Lp7:
+ add edx,ds:dword ptr[tstep]
+ sbb eax,eax
+ add ebp,ds:dword ptr[lzistepx]
+ adc ebp,0
+ add ebx,ds:dword ptr[_a_sstepxfrac]
+ adc esi,ds:dword ptr[advancetable+4+eax*4]
+LDraw1:
+ cmp bp,ds:word ptr[14+ecx]
+ jl Lp8
+ xor eax,eax
+ mov ah,dh
+ mov al,ds:byte ptr[esi]
+ mov ds:word ptr[14+ecx],bp
+ mov al,ds:byte ptr[12345678h+eax]
+LPatch1:
+ mov ds:byte ptr[7+edi],al
+Lp8:
+ add edx,ds:dword ptr[tstep]
+ sbb eax,eax
+ add ebp,ds:dword ptr[lzistepx]
+ adc ebp,0
+ add ebx,ds:dword ptr[_a_sstepxfrac]
+ adc esi,ds:dword ptr[advancetable+4+eax*4]
+ add edi,8
+ add ecx,16
+ dec bx
+ jnz LDrawLoop
+ pop esi
+LNextSpan:
+ add esi,32
+LNextSpanESISet:
+ mov edx,ds:dword ptr[8+esi]
+ cmp edx,offset -999999
+ jnz LSpanLoop
+ pop edi
+ pop ebp
+ pop ebx
+ pop esi
+ ret
+LExactlyOneLong:
+ mov ecx,ds:dword ptr[4+esi]
+ mov ebp,ds:dword ptr[28+esi]
+ ror ebp,16
+ mov ebx,ds:dword ptr[12+esi]
+ cmp bp,ds:word ptr[ecx]
+ jl LNextSpan
+ xor eax,eax
+ mov edi,ds:dword ptr[0+esi]
+ mov ah,ds:byte ptr[24+1+esi]
+ add esi,32
+ mov al,ds:byte ptr[ebx]
+ mov ds:word ptr[ecx],bp
+ mov al,ds:byte ptr[12345678h+eax]
+LPatch9:
+ mov ds:byte ptr[edi],al
+ jmp LNextSpanESISet
+ public _D_PolysetAff8End
+_D_PolysetAff8End:
+ public _D_Aff8Patch
+_D_Aff8Patch:
+ mov eax,ds:dword ptr[4+esp]
+ mov ds:dword ptr[LPatch1-4],eax
+ mov ds:dword ptr[LPatch2-4],eax
+ mov ds:dword ptr[LPatch3-4],eax
+ mov ds:dword ptr[LPatch4-4],eax
+ mov ds:dword ptr[LPatch5-4],eax
+ mov ds:dword ptr[LPatch6-4],eax
+ mov ds:dword ptr[LPatch7-4],eax
+ mov ds:dword ptr[LPatch8-4],eax
+ mov ds:dword ptr[LPatch9-4],eax
+ ret
+ public _D_PolysetDraw
+_D_PolysetDraw:
+ sub esp,offset (((1024+1 + 1 + ((32 - 1) / 32)) + 1) * 32)
+ mov eax,esp
+ add eax,32 - 1
+ and eax,offset not (32 - 1)
+ mov ds:dword ptr[_a_spans],eax
+ mov eax,ds:dword ptr[_r_affinetridesc+28]
+ test eax,eax
+ jz _D_DrawNonSubdiv
+ push ebp
+ mov ebp,ds:dword ptr[_r_affinetridesc+24]
+ push esi
+ shl ebp,4
+ push ebx
+ mov ebx,ds:dword ptr[_r_affinetridesc+16]
+ push edi
+ mov edi,ds:dword ptr[_r_affinetridesc+20]
+Llooptop:
+ mov ecx,ds:dword ptr[4-16+0+ebx+ebp]
+ mov esi,ds:dword ptr[4-16+4+ebx+ebp]
+ shl ecx,5
+ mov edx,ds:dword ptr[4-16+8+ebx+ebp]
+ shl esi,5
+ add ecx,edi
+ shl edx,5
+ add esi,edi
+ add edx,edi
+ fild ds:dword ptr[0+4+ecx]
+ fild ds:dword ptr[0+4+esi]
+ fild ds:dword ptr[0+0+ecx]
+ fild ds:dword ptr[0+0+edx]
+ fxch st(2)
+ fsubr st(0),st(3)
+ fild ds:dword ptr[0+0+esi]
+ fxch st(2)
+ fsubr st(3),st(0)
+ fild ds:dword ptr[0+4+edx]
+ fxch st(1)
+ fsubrp st(3),st(0)
+ fxch st(1)
+ fmulp st(3),st(0)
+ fsubp st(3),st(0)
+ mov eax,ds:dword ptr[0+16+ecx]
+ and eax,0FF00h
+ fmulp st(2),st(0)
+ add eax,ds:dword ptr[_acolormap]
+ fsubrp st(1),st(0)
+ mov ds:dword ptr[_d_pcolormap],eax
+ fstp ds:dword ptr[Ltemp]
+ mov eax,ds:dword ptr[Ltemp]
+ sub eax,080000001h
+ jc Lskip
+ mov eax,ds:dword ptr[0-16+ebx+ebp]
+ test eax,eax
+ jz Lfacesback
+ push edx
+ push esi
+ push ecx
+ call near ptr _D_PolysetRecursiveTriangle
+ sub ebp,16
+ jnz Llooptop
+ jmp Ldone2
+Lfacesback:
+ mov eax,ds:dword ptr[0+8+ecx]
+ push eax
+ mov eax,ds:dword ptr[0+8+esi]
+ push eax
+ mov eax,ds:dword ptr[0+8+edx]
+ push eax
+ push ecx
+ push edx
+ mov eax,ds:dword ptr[_r_affinetridesc+32]
+ test ds:dword ptr[24+ecx],00020h
+ jz Lp11
+ add ds:dword ptr[0+8+ecx],eax
+Lp11:
+ test ds:dword ptr[24+esi],00020h
+ jz Lp12
+ add ds:dword ptr[0+8+esi],eax
+Lp12:
+ test ds:dword ptr[24+edx],00020h
+ jz Lp13
+ add ds:dword ptr[0+8+edx],eax
+Lp13:
+ push edx
+ push esi
+ push ecx
+ call near ptr _D_PolysetRecursiveTriangle
+ pop edx
+ pop ecx
+ pop eax
+ mov ds:dword ptr[0+8+edx],eax
+ pop eax
+ mov ds:dword ptr[0+8+esi],eax
+ pop eax
+ mov ds:dword ptr[0+8+ecx],eax
+Lskip:
+ sub ebp,16
+ jnz Llooptop
+Ldone2:
+ pop edi
+ pop ebx
+ pop esi
+ pop ebp
+ add esp,offset (((1024+1 + 1 + ((32 - 1) / 32)) + 1) * 32)
+ ret
+ public _D_PolysetScanLeftEdge
+_D_PolysetScanLeftEdge:
+ push ebp
+ push esi
+ push edi
+ push ebx
+ mov eax,ds:dword ptr[4+16+esp]
+ mov ecx,ds:dword ptr[_d_sfrac]
+ and eax,0FFFFh
+ mov ebx,ds:dword ptr[_d_ptex]
+ or ecx,eax
+ mov esi,ds:dword ptr[_d_pedgespanpackage]
+ mov edx,ds:dword ptr[_d_tfrac]
+ mov edi,ds:dword ptr[_d_light]
+ mov ebp,ds:dword ptr[_d_zi]
+LScanLoop:
+ mov ds:dword ptr[12+esi],ebx
+ mov eax,ds:dword ptr[_d_pdest]
+ mov ds:dword ptr[0+esi],eax
+ mov eax,ds:dword ptr[_d_pz]
+ mov ds:dword ptr[4+esi],eax
+ mov eax,ds:dword ptr[_d_aspancount]
+ mov ds:dword ptr[8+esi],eax
+ mov ds:dword ptr[24+esi],edi
+ mov ds:dword ptr[28+esi],ebp
+ mov ds:dword ptr[16+esi],ecx
+ mov ds:dword ptr[20+esi],edx
+ mov al,ds:byte ptr[32+esi]
+ add esi,32
+ mov eax,ds:dword ptr[_erroradjustup]
+ mov ds:dword ptr[_d_pedgespanpackage],esi
+ mov esi,ds:dword ptr[_errorterm]
+ add esi,eax
+ mov eax,ds:dword ptr[_d_pdest]
+ js LNoLeftEdgeTurnover
+ sub esi,ds:dword ptr[_erroradjustdown]
+ add eax,ds:dword ptr[_d_pdestextrastep]
+ mov ds:dword ptr[_errorterm],esi
+ mov ds:dword ptr[_d_pdest],eax
+ mov eax,ds:dword ptr[_d_pz]
+ mov esi,ds:dword ptr[_d_aspancount]
+ add eax,ds:dword ptr[_d_pzextrastep]
+ add ecx,ds:dword ptr[_d_sfracextrastep]
+ adc ebx,ds:dword ptr[_d_ptexextrastep]
+ add esi,ds:dword ptr[_d_countextrastep]
+ mov ds:dword ptr[_d_pz],eax
+ mov eax,ds:dword ptr[_d_tfracextrastep]
+ mov ds:dword ptr[_d_aspancount],esi
+ add edx,eax
+ jnc LSkip1
+ add ebx,ds:dword ptr[_r_affinetridesc+8]
+LSkip1:
+ add edi,ds:dword ptr[_d_lightextrastep]
+ add ebp,ds:dword ptr[_d_ziextrastep]
+ mov esi,ds:dword ptr[_d_pedgespanpackage]
+ dec ecx
+ test ecx,0FFFFh
+ jnz LScanLoop
+ pop ebx
+ pop edi
+ pop esi
+ pop ebp
+ ret
+LNoLeftEdgeTurnover:
+ mov ds:dword ptr[_errorterm],esi
+ add eax,ds:dword ptr[_d_pdestbasestep]
+ mov ds:dword ptr[_d_pdest],eax
+ mov eax,ds:dword ptr[_d_pz]
+ mov esi,ds:dword ptr[_d_aspancount]
+ add eax,ds:dword ptr[_d_pzbasestep]
+ add ecx,ds:dword ptr[_d_sfracbasestep]
+ adc ebx,ds:dword ptr[_d_ptexbasestep]
+ add esi,ds:dword ptr[_ubasestep]
+ mov ds:dword ptr[_d_pz],eax
+ mov ds:dword ptr[_d_aspancount],esi
+ mov esi,ds:dword ptr[_d_tfracbasestep]
+ add edx,esi
+ jnc LSkip2
+ add ebx,ds:dword ptr[_r_affinetridesc+8]
+LSkip2:
+ add edi,ds:dword ptr[_d_lightbasestep]
+ add ebp,ds:dword ptr[_d_zibasestep]
+ mov esi,ds:dword ptr[_d_pedgespanpackage]
+ dec ecx
+ test ecx,0FFFFh
+ jnz LScanLoop
+ pop ebx
+ pop edi
+ pop esi
+ pop ebp
+ ret
+ public _D_PolysetDrawFinalVerts
+_D_PolysetDrawFinalVerts:
+ push ebp
+ push ebx
+ mov ecx,ds:dword ptr[8+8+esp]
+ mov ebx,ds:dword ptr[4+8+esp]
+ push esi
+ push edi
+LFVLoop:
+ mov eax,ds:dword ptr[0+0+ebx]
+ mov edx,ds:dword ptr[_r_refdef+40]
+ cmp eax,edx
+ jge LNextVert
+ mov esi,ds:dword ptr[0+4+ebx]
+ mov edx,ds:dword ptr[_r_refdef+44]
+ cmp esi,edx
+ jge LNextVert
+ mov edi,ds:dword ptr[_zspantable+esi*4]
+ mov edx,ds:dword ptr[0+20+ebx]
+ shr edx,16
+ cmp dx,ds:word ptr[edi+eax*2]
+ jl LNextVert
+ mov ds:word ptr[edi+eax*2],dx
+ mov edi,ds:dword ptr[0+12+ebx]
+ shr edi,16
+ mov edi,ds:dword ptr[_skintable+edi*4]
+ mov edx,ds:dword ptr[0+8+ebx]
+ shr edx,16
+ mov dl,ds:byte ptr[edi+edx]
+ mov edi,ds:dword ptr[0+16+ebx]
+ and edi,0FF00h
+ and edx,000FFh
+ add edi,edx
+ mov edx,ds:dword ptr[_acolormap]
+ mov dl,ds:byte ptr[edx+edi*1]
+ mov edi,ds:dword ptr[_d_scantable+esi*4]
+ mov esi,ds:dword ptr[_d_viewbuffer]
+ add edi,eax
+ mov ds:byte ptr[esi+edi],dl
+LNextVert:
+ add ebx,32
+ dec ecx
+ jnz LFVLoop
+ pop edi
+ pop esi
+ pop ebx
+ pop ebp
+ ret
+ public _D_DrawNonSubdiv
+_D_DrawNonSubdiv:
+ push ebp
+ mov ebp,ds:dword ptr[_r_affinetridesc+24]
+ push ebx
+ shl ebp,4
+ push esi
+ mov esi,ds:dword ptr[_r_affinetridesc+16]
+ push edi
+LNDLoop:
+ mov edi,ds:dword ptr[_r_affinetridesc+20]
+ mov ecx,ds:dword ptr[4+0-16+esi+ebp*1]
+ shl ecx,5
+ mov edx,ds:dword ptr[4+4-16+esi+ebp*1]
+ shl edx,5
+ mov ebx,ds:dword ptr[4+8-16+esi+ebp*1]
+ shl ebx,5
+ add ecx,edi
+ add edx,edi
+ add ebx,edi
+ mov eax,ds:dword ptr[0+4+ecx]
+ mov esi,ds:dword ptr[0+0+ecx]
+ sub eax,ds:dword ptr[0+4+edx]
+ sub esi,ds:dword ptr[0+0+ebx]
+ imul eax,esi
+ mov esi,ds:dword ptr[0+0+ecx]
+ mov edi,ds:dword ptr[0+4+ecx]
+ sub esi,ds:dword ptr[0+0+edx]
+ sub edi,ds:dword ptr[0+4+ebx]
+ imul edi,esi
+ sub eax,edi
+ jns LNextTri
+ mov ds:dword ptr[_d_xdenom],eax
+ fild ds:dword ptr[_d_xdenom]
+ mov eax,ds:dword ptr[0+0+ecx]
+ mov esi,ds:dword ptr[0+4+ecx]
+ mov ds:dword ptr[_r_p0+0],eax
+ mov ds:dword ptr[_r_p0+4],esi
+ mov eax,ds:dword ptr[0+8+ecx]
+ mov esi,ds:dword ptr[0+12+ecx]
+ mov ds:dword ptr[_r_p0+8],eax
+ mov ds:dword ptr[_r_p0+12],esi
+ mov eax,ds:dword ptr[0+16+ecx]
+ mov esi,ds:dword ptr[0+20+ecx]
+ mov ds:dword ptr[_r_p0+16],eax
+ mov ds:dword ptr[_r_p0+20],esi
+ fdivr ds:dword ptr[float_1]
+ mov eax,ds:dword ptr[0+0+edx]
+ mov esi,ds:dword ptr[0+4+edx]
+ mov ds:dword ptr[_r_p1+0],eax
+ mov ds:dword ptr[_r_p1+4],esi
+ mov eax,ds:dword ptr[0+8+edx]
+ mov esi,ds:dword ptr[0+12+edx]
+ mov ds:dword ptr[_r_p1+8],eax
+ mov ds:dword ptr[_r_p1+12],esi
+ mov eax,ds:dword ptr[0+16+edx]
+ mov esi,ds:dword ptr[0+20+edx]
+ mov ds:dword ptr[_r_p1+16],eax
+ mov ds:dword ptr[_r_p1+20],esi
+ mov eax,ds:dword ptr[0+0+ebx]
+ mov esi,ds:dword ptr[0+4+ebx]
+ mov ds:dword ptr[_r_p2+0],eax
+ mov ds:dword ptr[_r_p2+4],esi
+ mov eax,ds:dword ptr[0+8+ebx]
+ mov esi,ds:dword ptr[0+12+ebx]
+ mov ds:dword ptr[_r_p2+8],eax
+ mov ds:dword ptr[_r_p2+12],esi
+ mov eax,ds:dword ptr[0+16+ebx]
+ mov esi,ds:dword ptr[0+20+ebx]
+ mov ds:dword ptr[_r_p2+16],eax
+ mov edi,ds:dword ptr[_r_affinetridesc+16]
+ mov ds:dword ptr[_r_p2+20],esi
+ mov eax,ds:dword ptr[0-16+edi+ebp*1]
+ test eax,eax
+ jnz LFacesFront
+ mov eax,ds:dword ptr[24+ecx]
+ mov esi,ds:dword ptr[24+edx]
+ mov edi,ds:dword ptr[24+ebx]
+ test eax,00020h
+ mov eax,ds:dword ptr[_r_affinetridesc+32]
+ jz LOnseamDone0
+ add ds:dword ptr[_r_p0+8],eax
+LOnseamDone0:
+ test esi,00020h
+ jz LOnseamDone1
+ add ds:dword ptr[_r_p1+8],eax
+LOnseamDone1:
+ test edi,00020h
+ jz LOnseamDone2
+ add ds:dword ptr[_r_p2+8],eax
+LOnseamDone2:
+LFacesFront:
+ fstp ds:dword ptr[_d_xdenom]
+ call near ptr _D_PolysetSetEdgeTable
+ call near ptr _D_RasterizeAliasPolySmooth
+LNextTri:
+ mov esi,ds:dword ptr[_r_affinetridesc+16]
+ sub ebp,16
+ jnz LNDLoop
+ pop edi
+ pop esi
+ pop ebx
+ pop ebp
+ add esp,offset (((1024+1 + 1 + ((32 - 1) / 32)) + 1) * 32)
+ ret
+_TEXT ENDS
+ END
--- /dev/null
+++ b/QW/client/d_polysa.s
@@ -1,0 +1,1744 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+//
+// d_polysa.s
+// x86 assembly-language polygon model drawing code
+//
+
+#include "asm_i386.h"
+#include "quakeasm.h"
+#include "asm_draw.h"
+#include "d_ifacea.h"
+
+#if	id386
+
+// !!! if this is changed, it must be changed in d_polyse.c too !!!
+#define DPS_MAXSPANS			MAXHEIGHT+1	
+									// 1 extra for spanpackage that marks end
+
+//#define	SPAN_SIZE	(((DPS_MAXSPANS + 1 + ((CACHE_SIZE - 1) / spanpackage_t_size)) + 1) * spanpackage_t_size)
+#define SPAN_SIZE (1024+1+1+1)*32 
+
+
+	.data
+
+	.align	4
+p10_minus_p20:	.single		0
+p01_minus_p21:	.single		0
+temp0:			.single		0
+temp1:			.single		0
+Ltemp:			.single		0
+
+aff8entryvec_table:	.long	LDraw8, LDraw7, LDraw6, LDraw5
+				.long	LDraw4, LDraw3, LDraw2, LDraw1
+
+lzistepx:		.long	0
+
+
+	.text
+
+#ifndef NeXT
+	.extern C(D_PolysetSetEdgeTable)
+	.extern C(D_RasterizeAliasPolySmooth)
+#endif
+
+//----------------------------------------------------------------------
+// affine triangle gradient calculation code
+//----------------------------------------------------------------------
+
+#define skinwidth	4+0
+
+.globl C(D_PolysetCalcGradients)
+C(D_PolysetCalcGradients):
+
+//	p00_minus_p20 = r_p0[0] - r_p2[0];
+//	p01_minus_p21 = r_p0[1] - r_p2[1];
+//	p10_minus_p20 = r_p1[0] - r_p2[0];
+//	p11_minus_p21 = r_p1[1] - r_p2[1];
+//
+//	xstepdenominv = 1.0 / (p10_minus_p20 * p01_minus_p21 -
+//			     p00_minus_p20 * p11_minus_p21);
+//
+//	ystepdenominv = -xstepdenominv;
+
+	fildl	C(r_p0)+0		// r_p0[0]
+	fildl	C(r_p2)+0		// r_p2[0] | r_p0[0]
+	fildl	C(r_p0)+4		// r_p0[1] | r_p2[0] | r_p0[0]
+	fildl	C(r_p2)+4		// r_p2[1] | r_p0[1] | r_p2[0] | r_p0[0]
+	fildl	C(r_p1)+0		// r_p1[0] | r_p2[1] | r_p0[1] | r_p2[0] | r_p0[0]
+	fildl	C(r_p1)+4		// r_p1[1] | r_p1[0] | r_p2[1] | r_p0[1] |
+							//  r_p2[0] | r_p0[0]
+	fxch	%st(3)			// r_p0[1] | r_p1[0] | r_p2[1] | r_p1[1] |
+							//  r_p2[0] | r_p0[0]
+	fsub	%st(2),%st(0)	// p01_minus_p21 | r_p1[0] | r_p2[1] | r_p1[1] |
+							//  r_p2[0] | r_p0[0]
+	fxch	%st(1)			// r_p1[0] | p01_minus_p21 | r_p2[1] | r_p1[1] |
+							//  r_p2[0] | r_p0[0]
+	fsub	%st(4),%st(0)	// p10_minus_p20 | p01_minus_p21 | r_p2[1] |
+							//  r_p1[1] | r_p2[0] | r_p0[0]
+	fxch	%st(5)			// r_p0[0] | p01_minus_p21 | r_p2[1] |
+							//  r_p1[1] | r_p2[0] | p10_minus_p20
+	fsubp	%st(0),%st(4)	// p01_minus_p21 | r_p2[1] | r_p1[1] |
+							//  p00_minus_p20 | p10_minus_p20
+	fxch	%st(2)			// r_p1[1] | r_p2[1] | p01_minus_p21 |
+							//  p00_minus_p20 | p10_minus_p20
+	fsubp	%st(0),%st(1)	// p11_minus_p21 | p01_minus_p21 |
+							//  p00_minus_p20 | p10_minus_p20
+	fxch	%st(1)			// p01_minus_p21 | p11_minus_p21 |
+							//  p00_minus_p20 | p10_minus_p20
+	flds	C(d_xdenom)		// d_xdenom | p01_minus_p21 | p11_minus_p21 |
+							//  p00_minus_p20 | p10_minus_p20
+	fxch	%st(4)			// p10_minus_p20 | p01_minus_p21 | p11_minus_p21 |
+							//  p00_minus_p20 | d_xdenom
+	fstps	p10_minus_p20	// p01_minus_p21 | p11_minus_p21 |
+							//  p00_minus_p20 | d_xdenom
+	fstps	p01_minus_p21	// p11_minus_p21 | p00_minus_p20 | xstepdenominv
+	fxch	%st(2)			// xstepdenominv | p00_minus_p20 | p11_minus_p21
+
+//// ceil () for light so positive steps are exaggerated, negative steps
+//// diminished,  pushing us away from underflow toward overflow. Underflow is
+//// very visible, overflow is very unlikely, because of ambient lighting
+//	t0 = r_p0[4] - r_p2[4];
+//	t1 = r_p1[4] - r_p2[4];
+
+	fildl	C(r_p2)+16		// r_p2[4] | xstepdenominv | p00_minus_p20 |
+							//  p11_minus_p21
+	fildl	C(r_p0)+16		// r_p0[4] | r_p2[4] | xstepdenominv |
+							//  p00_minus_p20 | p11_minus_p21
+	fildl	C(r_p1)+16		// r_p1[4] | r_p0[4] | r_p2[4] | xstepdenominv |
+							//  p00_minus_p20 | p11_minus_p21
+	fxch	%st(2)			// r_p2[4] | r_p0[4] | r_p1[4] | xstepdenominv |
+							//  p00_minus_p20 | p11_minus_p21
+	fld		%st(0)			// r_p2[4] | r_p2[4] | r_p0[4] | r_p1[4] |
+							//  xstepdenominv | p00_minus_p20 | p11_minus_p21
+	fsubrp	%st(0),%st(2)	// r_p2[4] | t0 | r_p1[4] | xstepdenominv |
+							//  p00_minus_p20 | p11_minus_p21
+	fsubrp	%st(0),%st(2)	// t0 | t1 | xstepdenominv | p00_minus_p20 |
+							//  p11_minus_p21
+
+//	r_lstepx = (int)
+//			ceil((t1 * p01_minus_p21 - t0 * p11_minus_p21) * xstepdenominv);
+//	r_lstepy = (int)
+//			ceil((t1 * p00_minus_p20 - t0 * p10_minus_p20) * ystepdenominv);
+
+	fld		%st(0)			// t0 | t0 | t1 | xstepdenominv | p00_minus_p20 |
+							//  p11_minus_p21
+	fmul	%st(5),%st(0)	// t0*p11_minus_p21 | t0 | t1 | xstepdenominv |
+							//  p00_minus_p20 | p11_minus_p21
+	fxch	%st(2)			// t1 | t0 | t0*p11_minus_p21 | xstepdenominv |
+							//  p00_minus_p20 | p11_minus_p21
+	fld		%st(0)			// t1 | t1 | t0 | t0*p11_minus_p21 |
+							//  xstepdenominv | p00_minus_p20 | p11_minus_p21
+	fmuls	p01_minus_p21	// t1*p01_minus_p21 | t1 | t0 | t0*p11_minus_p21 |
+							//  xstepdenominv | p00_minus_p20 | p11_minus_p21
+	fxch	%st(2)			// t0 | t1 | t1*p01_minus_p21 | t0*p11_minus_p21 |
+							//  xstepdenominv | p00_minus_p20 | p11_minus_p21
+	fmuls	p10_minus_p20	// t0*p10_minus_p20 | t1 | t1*p01_minus_p21 |
+							//  t0*p11_minus_p21 | xstepdenominv |
+							//  p00_minus_p20 | p11_minus_p21
+	fxch	%st(1)			// t1 | t0*p10_minus_p20 | t1*p01_minus_p21 |
+							//  t0*p11_minus_p21 | xstepdenominv |
+							//  p00_minus_p20 | p11_minus_p21
+	fmul	%st(5),%st(0)	// t1*p00_minus_p20 | t0*p10_minus_p20 |
+							//  t1*p01_minus_p21 | t0*p11_minus_p21 |
+							//  xstepdenominv | p00_minus_p20 | p11_minus_p21
+	fxch	%st(2)			// t1*p01_minus_p21 | t0*p10_minus_p20 |
+							//  t1*p00_minus_p20 | t0*p11_minus_p21 |
+							//  xstepdenominv | p00_minus_p20 | p11_minus_p21
+	fsubp	%st(0),%st(3)	// t0*p10_minus_p20 | t1*p00_minus_p20 |
+							//  t1*p01_minus_p21 - t0*p11_minus_p21 |
+							//  xstepdenominv | p00_minus_p20 | p11_minus_p21
+	fsubrp	%st(0),%st(1)	// t1*p00_minus_p20 - t0*p10_minus_p20 |
+							//  t1*p01_minus_p21 - t0*p11_minus_p21 |
+							//  xstepdenominv | p00_minus_p20 | p11_minus_p21
+	fld		%st(2)			// xstepdenominv |
+							//  t1*p00_minus_p20 - t0*p10_minus_p20 |
+							//  t1*p01_minus_p21 - t0*p11_minus_p21 |
+							//  xstepdenominv | p00_minus_p20 | p11_minus_p21
+	fmuls	float_minus_1	// ystepdenominv |
+							//  t1*p00_minus_p20 - t0*p10_minus_p20 |
+							//  t1*p01_minus_p21 - t0*p11_minus_p21 |
+							//  xstepdenominv | p00_minus_p20 | p11_minus_p21
+	fxch	%st(2)			// t1*p01_minus_p21 - t0*p11_minus_p21 |
+							//  t1*p00_minus_p20 - t0*p10_minus_p20 |
+							//  ystepdenominv | xstepdenominv | p00_minus_p20 |
+							//  p11_minus_p21
+	fmul	%st(3),%st(0)	// (t1*p01_minus_p21 - t0*p11_minus_p21)*
+							//   xstepdenominv |
+							//  t1*p00_minus_p20 - t0*p10_minus_p20 |
+							//   | ystepdenominv | xstepdenominv |
+							//   p00_minus_p20 | p11_minus_p21
+	fxch	%st(1)			// t1*p00_minus_p20 - t0*p10_minus_p20 |
+							//  (t1*p01_minus_p21 - t0*p11_minus_p21)*
+							//   xstepdenominv | ystepdenominv |
+							//   xstepdenominv | p00_minus_p20 | p11_minus_p21
+	fmul	%st(2),%st(0)	// (t1*p00_minus_p20 - t0*p10_minus_p20)*
+							//  ystepdenominv |
+							//  (t1*p01_minus_p21 - t0*p11_minus_p21)*
+							//  xstepdenominv | ystepdenominv |
+							//  xstepdenominv | p00_minus_p20 | p11_minus_p21
+	fldcw	ceil_cw
+	fistpl	C(r_lstepy)		// r_lstepx | ystepdenominv | xstepdenominv |
+							//  p00_minus_p20 | p11_minus_p21
+	fistpl	C(r_lstepx)		// ystepdenominv | xstepdenominv | p00_minus_p20 |
+							//  p11_minus_p21
+	fldcw	single_cw
+
+//	t0 = r_p0[2] - r_p2[2];
+//	t1 = r_p1[2] - r_p2[2];
+
+	fildl	C(r_p2)+8		// r_p2[2] | ystepdenominv | xstepdenominv |
+							//  p00_minus_p20 | p11_minus_p21
+	fildl	C(r_p0)+8		// r_p0[2] | r_p2[2] | ystepdenominv |
+							//   xstepdenominv | p00_minus_p20 | p11_minus_p21
+	fildl	C(r_p1)+8		// r_p1[2] | r_p0[2] | r_p2[2] | ystepdenominv |
+							//  xstepdenominv | p00_minus_p20 | p11_minus_p21
+	fxch	%st(2)			// r_p2[2] | r_p0[2] | r_p1[2] | ystepdenominv |
+							//  xstepdenominv | p00_minus_p20 | p11_minus_p21
+	fld		%st(0)			// r_p2[2] | r_p2[2] | r_p0[2] | r_p1[2] |
+							//  ystepdenominv | xstepdenominv | p00_minus_p20 |
+							//  p11_minus_p21
+	fsubrp	%st(0),%st(2)	// r_p2[2] | t0 | r_p1[2] | ystepdenominv |
+							//  xstepdenominv | p00_minus_p20 | p11_minus_p21
+	fsubrp	%st(0),%st(2)	// t0 | t1 | ystepdenominv | xstepdenominv |
+							//  p00_minus_p20 | p11_minus_p21
+
+//	r_sstepx = (int)((t1 * p01_minus_p21 - t0 * p11_minus_p21) *
+//			xstepdenominv);
+//	r_sstepy = (int)((t1 * p00_minus_p20 - t0 * p10_minus_p20) *
+//			ystepdenominv);
+
+	fld		%st(0)			// t0 | t0 | t1 | ystepdenominv | xstepdenominv
+	fmul	%st(6),%st(0)	// t0*p11_minus_p21 | t0 | t1 | ystepdenominv |
+							//  xstepdenominv | p00_minus_p20 | p11_minus_p21
+	fxch	%st(2)			// t1 | t0 | t0*p11_minus_p21 | ystepdenominv |
+							//  xstepdenominv | p00_minus_p20 | p11_minus_p21
+	fld		%st(0)			// t1 | t1 | t0 | t0*p11_minus_p21 |
+							//  ystepdenominv | xstepdenominv | p00_minus_p20 |
+							//  p11_minus_p21
+	fmuls	p01_minus_p21	// t1*p01_minus_p21 | t1 | t0 | t0*p11_minus_p21 |
+							//  ystepdenominv | xstepdenominv | p00_minus_p20 |
+							//  p11_minus_p21
+	fxch	%st(2)			// t0 | t1 | t1*p01_minus_p21 | t0*p11_minus_p21 |
+							//  ystepdenominv | xstepdenominv | p00_minus_p20 |
+							//  p11_minus_p21
+	fmuls	p10_minus_p20	// t0*p10_minus_p20 | t1 | t1*p01_minus_p21 |
+							//  t0*p11_minus_p21 | ystepdenominv |
+							//  xstepdenominv | p00_minus_p20 | p11_minus_p21
+	fxch	%st(1)			// t1 | t0*p10_minus_p20 | t1*p01_minus_p21 |
+							//  t0*p11_minus_p21 | ystepdenominv |
+							//  xstepdenominv | p00_minus_p20 | p11_minus_p21
+	fmul	%st(6),%st(0)	// t1*p00_minus_p20 | t0*p10_minus_p20 |
+							//  t1*p01_minus_p21 | t0*p11_minus_p21 |
+							//  ystepdenominv | xstepdenominv | p00_minus_p20 |
+							//  p11_minus_p21
+	fxch	%st(2)			// t1*p01_minus_p21 | t0*p10_minus_p20 |
+							//  t1*p00_minus_p20 | t0*p11_minus_p21 |
+							//  ystepdenominv | xstepdenominv | p00_minus_p20 |
+							//  p11_minus_p21
+	fsubp	%st(0),%st(3)	// t0*p10_minus_p20 | t1*p00_minus_p20 |
+							//  t1*p01_minus_p21 - t0*p11_minus_p21 |
+							//  ystepdenominv | xstepdenominv | p00_minus_p20 |
+							//  p11_minus_p21
+	fsubrp	%st(0),%st(1)	// t1*p00_minus_p20 - t0*p10_minus_p20 |
+							//  t1*p01_minus_p21 - t0*p11_minus_p21 |
+							//  ystepdenominv | xstepdenominv | p00_minus_p20 |
+							//  p11_minus_p21
+	fmul	%st(2),%st(0)	// (t1*p00_minus_p20 - t0*p10_minus_p20)*
+							//   ystepdenominv |
+							//  t1*p01_minus_p21 - t0*p11_minus_p21 |
+							//  ystepdenominv | xstepdenominv | p00_minus_p20 |
+							//  p11_minus_p21
+	fxch	%st(1)			// t1*p01_minus_p21 - t0*p11_minus_p21 |
+							//  (t1*p00_minus_p20 - t0*p10_minus_p20)*
+							//   ystepdenominv | ystepdenominv |
+							//  xstepdenominv | p00_minus_p20 | p11_minus_p21
+	fmul	%st(3),%st(0)	// (t1*p01_minus_p21 - t0*p11_minus_p21)*
+							//  xstepdenominv |
+							//  (t1*p00_minus_p20 - t0*p10_minus_p20)*
+							//  ystepdenominv | ystepdenominv |
+							//  xstepdenominv | p00_minus_p20 | p11_minus_p21
+	fxch	%st(1)			// (t1*p00_minus_p20 - t0*p10_minus_p20)*
+							//  ystepdenominv |
+							//  (t1*p01_minus_p21 - t0*p11_minus_p21)*
+							//  xstepdenominv | ystepdenominv |
+							//  xstepdenominv | p00_minus_p20 | p11_minus_p21
+	fistpl	C(r_sstepy)		// r_sstepx | ystepdenominv | xstepdenominv |
+							//  p00_minus_p20 | p11_minus_p21
+	fistpl	C(r_sstepx)		// ystepdenominv | xstepdenominv | p00_minus_p20 |
+							//  p11_minus_p21
+
+//	t0 = r_p0[3] - r_p2[3];
+//	t1 = r_p1[3] - r_p2[3];
+
+	fildl	C(r_p2)+12		// r_p2[3] | ystepdenominv | xstepdenominv |
+							//  p00_minus_p20 | p11_minus_p21
+	fildl	C(r_p0)+12		// r_p0[3] | r_p2[3] | ystepdenominv |
+							//  xstepdenominv | p00_minus_p20 | p11_minus_p21
+	fildl	C(r_p1)+12		// r_p1[3] | r_p0[3] | r_p2[3] | ystepdenominv |
+							//  xstepdenominv | p00_minus_p20 | p11_minus_p21
+	fxch	%st(2)			// r_p2[3] | r_p0[3] | r_p1[3] | ystepdenominv |
+							//  xstepdenominv | p00_minus_p20 | p11_minus_p21
+	fld		%st(0)			// r_p2[3] | r_p2[3] | r_p0[3] | r_p1[3] |
+							//  ystepdenominv | xstepdenominv | p00_minus_p20 |
+							//  p11_minus_p21
+	fsubrp	%st(0),%st(2)	// r_p2[3] | t0 | r_p1[3] | ystepdenominv |
+							//  xstepdenominv | p00_minus_p20 | p11_minus_p21
+	fsubrp	%st(0),%st(2)	// t0 | t1 | ystepdenominv | xstepdenominv |
+							//  p00_minus_p20 | p11_minus_p21
+
+//	r_tstepx = (int)((t1 * p01_minus_p21 - t0 * p11_minus_p21) *
+//			xstepdenominv);
+//	r_tstepy = (int)((t1 * p00_minus_p20 - t0 * p10_minus_p20) *
+//			ystepdenominv);
+
+	fld		%st(0)			// t0 | t0 | t1 | ystepdenominv | xstepdenominv |
+							//  p00_minus_p20 | p11_minus_p21
+	fmul	%st(6),%st(0)	// t0*p11_minus_p21 | t0 | t1 | ystepdenominv |
+							//  xstepdenominv | p00_minus_p20 | p11_minus_p21
+	fxch	%st(2)			// t1 | t0 | t0*p11_minus_p21 | ystepdenominv |
+							//  xstepdenominv | p00_minus_p20 | p11_minus_p21
+	fld		%st(0)			// t1 | t1 | t0 | t0*p11_minus_p21 |
+							//  ystepdenominv | xstepdenominv | p00_minus_p20 |
+							//  p11_minus_p21
+	fmuls	p01_minus_p21	// t1*p01_minus_p21 | t1 | t0 | t0*p11_minus_p21 |
+							//  ystepdenominv | xstepdenominv | p00_minus_p20 |
+							//  p11_minus_p21
+	fxch	%st(2)			// t0 | t1 | t1*p01_minus_p21 | t0*p11_minus_p21 |
+							//  ystepdenominv | xstepdenominv | p00_minus_p20 |
+							//  p11_minus_p21
+	fmuls	p10_minus_p20	// t0*p10_minus_p20 | t1 | t1*p01_minus_p21 |
+							//  t0*p11_minus_p21 | ystepdenominv |
+							//  xstepdenominv | p00_minus_p20 | p11_minus_p21
+	fxch	%st(1)			// t1 | t0*p10_minus_p20 | t1*p01_minus_p21 |
+							//  t0*p11_minus_p21 | ystepdenominv |
+							//  xstepdenominv | p00_minus_p20 | p11_minus_p21
+	fmul	%st(6),%st(0)	// t1*p00_minus_p20 | t0*p10_minus_p20 |
+							//  t1*p01_minus_p21 | t0*p11_minus_p21 |
+							//  ystepdenominv | xstepdenominv | p00_minus_p20 |
+							//  p11_minus_p21
+	fxch	%st(2)			// t1*p01_minus_p21 | t0*p10_minus_p20 |
+							//  t1*p00_minus_p20 | t0*p11_minus_p21 |
+							//  ystepdenominv | xstepdenominv | p00_minus_p20 |
+							//  p11_minus_p21
+	fsubp	%st(0),%st(3)	// t0*p10_minus_p20 | t1*p00_minus_p20 |
+							//  t1*p01_minus_p21 - t0*p11_minus_p21 |
+							//  ystepdenominv | xstepdenominv | p00_minus_p20 |
+							//  p11_minus_p21
+	fsubrp	%st(0),%st(1)	// t1*p00_minus_p20 - t0*p10_minus_p20 |
+							//  t1*p01_minus_p21 - t0*p11_minus_p21 |
+							//  ystepdenominv | xstepdenominv | p00_minus_p20 |
+							//  p11_minus_p21
+	fmul	%st(2),%st(0)	// (t1*p00_minus_p20 - t0*p10_minus_p20)*
+							//   ystepdenominv |
+							//  t1*p01_minus_p21 - t0*p11_minus_p21 |
+							//  ystepdenominv | xstepdenominv | p00_minus_p20 |
+							//  p11_minus_p21
+	fxch	%st(1)			// t1*p01_minus_p21 - t0*p11_minus_p21 |
+							//  (t1*p00_minus_p20 - t0*p10_minus_p20)*
+							//  ystepdenominv | ystepdenominv |
+							//  xstepdenominv | p00_minus_p20 | p11_minus_p21
+	fmul	%st(3),%st(0)	// (t1*p01_minus_p21 - t0*p11_minus_p21)*
+							//  xstepdenominv |
+							//  (t1*p00_minus_p20 - t0*p10_minus_p20)*
+							//  ystepdenominv | ystepdenominv |
+							//  xstepdenominv | p00_minus_p20 | p11_minus_p21
+	fxch	%st(1)			// (t1*p00_minus_p20 - t0*p10_minus_p20)*
+							//  ystepdenominv |
+							//  (t1*p01_minus_p21 - t0*p11_minus_p21)*
+							//  xstepdenominv | ystepdenominv |
+							//  xstepdenominv | p00_minus_p20 | p11_minus_p21
+	fistpl	C(r_tstepy)		// r_tstepx | ystepdenominv | xstepdenominv |
+							//  p00_minus_p20 | p11_minus_p21
+	fistpl	C(r_tstepx)		// ystepdenominv | xstepdenominv | p00_minus_p20 |
+							//  p11_minus_p21
+
+//	t0 = r_p0[5] - r_p2[5];
+//	t1 = r_p1[5] - r_p2[5];
+
+	fildl	C(r_p2)+20		// r_p2[5] | ystepdenominv | xstepdenominv |
+							//  p00_minus_p20 | p11_minus_p21
+	fildl	C(r_p0)+20		// r_p0[5] | r_p2[5] | ystepdenominv |
+							//  xstepdenominv | p00_minus_p20 | p11_minus_p21
+	fildl	C(r_p1)+20		// r_p1[5] | r_p0[5] | r_p2[5] | ystepdenominv |
+							//  xstepdenominv | p00_minus_p20 | p11_minus_p21
+	fxch	%st(2)			// r_p2[5] | r_p0[5] | r_p1[5] | ystepdenominv |
+							//  xstepdenominv | p00_minus_p20 | p11_minus_p21
+	fld		%st(0)			// r_p2[5] | r_p2[5] | r_p0[5] | r_p1[5] |
+							//  ystepdenominv | xstepdenominv | p00_minus_p20 |
+							//  p11_minus_p21
+	fsubrp	%st(0),%st(2)	// r_p2[5] | t0 | r_p1[5] | ystepdenominv |
+							//  xstepdenominv | p00_minus_p20 | p11_minus_p21
+	fsubrp	%st(0),%st(2)	// t0 | t1 | ystepdenominv | xstepdenominv |
+							//  p00_minus_p20 | p11_minus_p21
+
+//	r_zistepx = (int)((t1 * p01_minus_p21 - t0 * p11_minus_p21) *
+//			xstepdenominv);
+//	r_zistepy = (int)((t1 * p00_minus_p20 - t0 * p10_minus_p20) *
+//			ystepdenominv);
+
+	fld		%st(0)			// t0 | t0 | t1 | ystepdenominv | xstepdenominv |
+							//  p00_minus_p20 | p11_minus_p21
+	fmulp	%st(0),%st(6)	// t0 | t1 | ystepdenominv | xstepdenominv |
+							//  p00_minus_p20 | t0*p11_minus_p21
+	fxch	%st(1)			// t1 | t0 | ystepdenominv | xstepdenominv |
+							//  p00_minus_p20 | t0*p11_minus_p21
+	fld		%st(0)			// t1 | t1 | t0 | ystepdenominv | xstepdenominv |
+							//  p00_minus_p20 | t0*p11_minus_p21
+	fmuls	p01_minus_p21	// t1*p01_minus_p21 | t1 | t0 | ystepdenominv |
+							//  xstepdenominv | p00_minus_p20 |
+							//  t0*p11_minus_p21
+	fxch	%st(2)			// t0 | t1 | t1*p01_minus_p21 | ystepdenominv |
+							//  xstepdenominv | p00_minus_p20 |
+							//  t0*p11_minus_p21
+	fmuls	p10_minus_p20	// t0*p10_minus_p20 | t1 | t1*p01_minus_p21 |
+							//  ystepdenominv | xstepdenominv | p00_minus_p20 |
+							//  t0*p11_minus_p21
+	fxch	%st(1)			// t1 | t0*p10_minus_p20 | t1*p01_minus_p21 |
+							//  ystepdenominv | xstepdenominv | p00_minus_p20 |
+							//  t0*p11_minus_p21
+	fmulp	%st(0),%st(5)	// t0*p10_minus_p20 | t1*p01_minus_p21 |
+							//  ystepdenominv | xstepdenominv |
+							//  t1*p00_minus_p20 | t0*p11_minus_p21
+	fxch	%st(5)			// t0*p11_minus_p21 | t1*p01_minus_p21 |
+							//  ystepdenominv | xstepdenominv |
+							//  t1*p00_minus_p20 | t0*p10_minus_p20
+	fsubrp	%st(0),%st(1)	// t1*p01_minus_p21 - t0*p11_minus_p21 |
+							//  ystepdenominv | xstepdenominv |
+							//  t1*p00_minus_p20 | t0*p10_minus_p20
+	fxch	%st(3)			// t1*p00_minus_p20 | ystepdenominv |
+							//  xstepdenominv |
+							//  t1*p01_minus_p21 - t0*p11_minus_p21 |
+							//  t0*p10_minus_p20
+	fsubp	%st(0),%st(4)	// ystepdenominv | xstepdenominv |
+							//  t1*p01_minus_p21 - t0*p11_minus_p21 |
+							//  t1*p00_minus_p20 - t0*p10_minus_p20
+	fxch	%st(1)			// xstepdenominv | ystepdenominv |
+							//  t1*p01_minus_p21 - t0*p11_minus_p21 |
+							//  t1*p00_minus_p20 - t0*p10_minus_p20
+	fmulp	%st(0),%st(2)	// ystepdenominv |
+							//  (t1*p01_minus_p21 - t0*p11_minus_p21) *
+							//  xstepdenominv |
+							//  t1*p00_minus_p20 - t0*p10_minus_p20
+	fmulp	%st(0),%st(2)	// (t1*p01_minus_p21 - t0*p11_minus_p21) *
+							//  xstepdenominv |
+							//  (t1*p00_minus_p20 - t0*p10_minus_p20) *
+							//  ystepdenominv
+	fistpl	C(r_zistepx)	// (t1*p00_minus_p20 - t0*p10_minus_p20) *
+							//  ystepdenominv
+	fistpl	C(r_zistepy)
+
+//	a_sstepxfrac = r_sstepx << 16;
+//	a_tstepxfrac = r_tstepx << 16;
+//
+//	a_ststepxwhole = r_affinetridesc.skinwidth * (r_tstepx >> 16) +
+//			(r_sstepx >> 16);
+
+	movl	C(r_sstepx),%eax
+	movl	C(r_tstepx),%edx
+	shll	$16,%eax
+	shll	$16,%edx
+	movl	%eax,C(a_sstepxfrac)
+	movl	%edx,C(a_tstepxfrac)
+
+	movl	C(r_sstepx),%ecx
+	movl	C(r_tstepx),%eax
+	sarl	$16,%ecx
+	sarl	$16,%eax
+	imull	skinwidth(%esp)
+	addl	%ecx,%eax
+	movl	%eax,C(a_ststepxwhole)
+
+	ret
+
+
+//----------------------------------------------------------------------
+// recursive subdivision affine triangle drawing code
+//
+// not C-callable because of stdcall return
+//----------------------------------------------------------------------
+
+#define lp1	4+16
+#define lp2	8+16
+#define lp3	12+16
+
+.globl C(D_PolysetRecursiveTriangle)
+C(D_PolysetRecursiveTriangle):
+	pushl	%ebp				// preserve caller stack frame pointer
+	pushl	%esi				// preserve register variables
+	pushl	%edi
+	pushl	%ebx
+
+//	int		*temp;
+//	int		d;
+//	int		new[6];
+//	int		i;
+//	int		z;
+//	short	*zbuf;
+	movl	lp2(%esp),%esi
+	movl	lp1(%esp),%ebx
+	movl	lp3(%esp),%edi
+
+//	d = lp2[0] - lp1[0];
+//	if (d < -1 || d > 1)
+//		goto split;
+	movl	0(%esi),%eax
+
+	movl	0(%ebx),%edx
+	movl	4(%esi),%ebp
+
+	subl	%edx,%eax
+	movl	4(%ebx),%ecx
+
+	subl	%ecx,%ebp
+	incl	%eax
+
+	cmpl	$2,%eax
+	ja		LSplit
+
+//	d = lp2[1] - lp1[1];
+//	if (d < -1 || d > 1)
+//		goto split;
+	movl	0(%edi),%eax
+	incl	%ebp
+
+	cmpl	$2,%ebp
+	ja		LSplit
+
+//	d = lp3[0] - lp2[0];
+//	if (d < -1 || d > 1)
+//		goto split2;
+	movl	0(%esi),%edx
+	movl	4(%edi),%ebp
+
+	subl	%edx,%eax
+	movl	4(%esi),%ecx
+
+	subl	%ecx,%ebp
+	incl	%eax
+
+	cmpl	$2,%eax
+	ja		LSplit2
+
+//	d = lp3[1] - lp2[1];
+//	if (d < -1 || d > 1)
+//		goto split2;
+	movl	0(%ebx),%eax
+	incl	%ebp
+
+	cmpl	$2,%ebp
+	ja		LSplit2
+
+//	d = lp1[0] - lp3[0];
+//	if (d < -1 || d > 1)
+//		goto split3;
+	movl	0(%edi),%edx
+	movl	4(%ebx),%ebp
+
+	subl	%edx,%eax
+	movl	4(%edi),%ecx
+
+	subl	%ecx,%ebp
+	incl	%eax
+
+	incl	%ebp
+	movl	%ebx,%edx
+
+	cmpl	$2,%eax
+	ja		LSplit3
+
+//	d = lp1[1] - lp3[1];
+//	if (d < -1 || d > 1)
+//	{
+//split3:
+//		temp = lp1;
+//		lp3 = lp2;
+//		lp1 = lp3;
+//		lp2 = temp;
+//		goto split;
+//	}
+//
+//	return;			// entire tri is filled
+//
+	cmpl	$2,%ebp
+	jna		LDone
+
+LSplit3:
+	movl	%edi,%ebx
+	movl	%esi,%edi
+	movl	%edx,%esi
+	jmp		LSplit
+
+//split2:
+LSplit2:
+
+//	temp = lp1;
+//	lp1 = lp2;
+//	lp2 = lp3;
+//	lp3 = temp;
+	movl	%ebx,%eax
+	movl	%esi,%ebx
+	movl	%edi,%esi
+	movl	%eax,%edi
+
+//split:
+LSplit:
+
+	subl	$24,%esp		// allocate space for a new vertex
+
+//// split this edge
+//	new[0] = (lp1[0] + lp2[0]) >> 1;
+//	new[1] = (lp1[1] + lp2[1]) >> 1;
+//	new[2] = (lp1[2] + lp2[2]) >> 1;
+//	new[3] = (lp1[3] + lp2[3]) >> 1;
+//	new[5] = (lp1[5] + lp2[5]) >> 1;
+	movl	8(%ebx),%eax
+
+	movl	8(%esi),%edx
+	movl	12(%ebx),%ecx
+
+	addl	%edx,%eax
+	movl	12(%esi),%edx
+
+	sarl	$1,%eax
+	addl	%edx,%ecx
+
+	movl	%eax,8(%esp)
+	movl	20(%ebx),%eax
+
+	sarl	$1,%ecx
+	movl	20(%esi),%edx
+
+	movl	%ecx,12(%esp)
+	addl	%edx,%eax
+
+	movl	0(%ebx),%ecx
+	movl	0(%esi),%edx
+
+	sarl	$1,%eax
+	addl	%ecx,%edx
+
+	movl	%eax,20(%esp)
+	movl	4(%ebx),%eax
+
+	sarl	$1,%edx
+	movl	4(%esi),%ebp
+
+	movl	%edx,0(%esp)
+	addl	%eax,%ebp
+
+	sarl	$1,%ebp
+	movl	%ebp,4(%esp)
+
+//// draw the point if splitting a leading edge
+//	if (lp2[1] > lp1[1])
+//		goto nodraw;
+	cmpl	%eax,4(%esi)
+	jg		LNoDraw
+
+//	if ((lp2[1] == lp1[1]) && (lp2[0] < lp1[0]))
+//		goto nodraw;
+	movl	0(%esi),%edx
+	jnz		LDraw
+
+	cmpl	%ecx,%edx
+	jl		LNoDraw
+
+LDraw:
+
+// z = new[5] >> 16;
+	movl	20(%esp),%edx
+	movl	4(%esp),%ecx
+
+	sarl	$16,%edx
+	movl	0(%esp),%ebp
+
+//	zbuf = zspantable[new[1]] + new[0];
+	movl	C(zspantable)(,%ecx,4),%eax
+
+//	if (z >= *zbuf)
+//	{
+	cmpw	(%eax,%ebp,2),%dx
+	jnge	LNoDraw
+
+//		int		pix;
+//		
+//		*zbuf = z;
+	movw	%dx,(%eax,%ebp,2)
+
+//		pix = d_pcolormap[skintable[new[3]>>16][new[2]>>16]];
+	movl	12(%esp),%eax
+
+	sarl	$16,%eax
+	movl	8(%esp),%edx
+
+	sarl	$16,%edx
+	subl	%ecx,%ecx
+
+	movl	C(skintable)(,%eax,4),%eax
+	movl	4(%esp),%ebp
+
+	movb	(%eax,%edx,),%cl
+	movl	C(d_pcolormap),%edx
+
+	movb	(%edx,%ecx,),%dl
+	movl	0(%esp),%ecx
+
+//		d_viewbuffer[d_scantable[new[1]] + new[0]] = pix;
+	movl	C(d_scantable)(,%ebp,4),%eax
+	addl	%eax,%ecx
+	movl	C(d_viewbuffer),%eax
+	movb	%dl,(%eax,%ecx,1)
+
+//	}
+//
+//nodraw:
+LNoDraw:
+
+//// recursively continue
+//	D_PolysetRecursiveTriangle (lp3, lp1, new);
+	pushl	%esp
+	pushl	%ebx
+	pushl	%edi
+	call	C(D_PolysetRecursiveTriangle)
+
+//	D_PolysetRecursiveTriangle (lp3, new, lp2);
+	movl	%esp,%ebx
+	pushl	%esi
+	pushl	%ebx
+	pushl	%edi
+	call	C(D_PolysetRecursiveTriangle)
+	addl	$24,%esp
+
+LDone:
+	popl	%ebx				// restore register variables
+	popl	%edi
+	popl	%esi
+	popl	%ebp				// restore caller stack frame pointer
+	ret		$12
+
+
+//----------------------------------------------------------------------
+// 8-bpp horizontal span drawing code for affine polygons, with smooth
+// shading and no transparency
+//----------------------------------------------------------------------
+
+#define pspans	4+8
+
+.globl C(D_PolysetAff8Start)
+C(D_PolysetAff8Start):
+
+.globl C(D_PolysetDrawSpans8)
+C(D_PolysetDrawSpans8):
+	pushl	%esi				// preserve register variables
+	pushl	%ebx
+
+	movl	pspans(%esp),%esi	// point to the first span descriptor
+	movl	C(r_zistepx),%ecx
+
+	pushl	%ebp				// preserve caller's stack frame
+	pushl	%edi
+
+	rorl	$16,%ecx			// put high 16 bits of 1/z step in low word
+	movl	spanpackage_t_count(%esi),%edx
+
+	movl	%ecx,lzistepx
+
+LSpanLoop:
+
+//		lcount = d_aspancount - pspanpackage->count;
+//
+//		errorterm += erroradjustup;
+//		if (errorterm >= 0)
+//		{
+//			d_aspancount += d_countextrastep;
+//			errorterm -= erroradjustdown;
+//		}
+//		else
+//		{
+//			d_aspancount += ubasestep;
+//		}
+	movl	C(d_aspancount),%eax
+	subl	%edx,%eax
+
+	movl	C(erroradjustup),%edx
+	movl	C(errorterm),%ebx
+	addl	%edx,%ebx
+	js		LNoTurnover
+
+	movl	C(erroradjustdown),%edx
+	movl	C(d_countextrastep),%edi
+	subl	%edx,%ebx
+	movl	C(d_aspancount),%ebp
+	movl	%ebx,C(errorterm)
+	addl	%edi,%ebp
+	movl	%ebp,C(d_aspancount)
+	jmp		LRightEdgeStepped
+
+LNoTurnover:
+	movl	C(d_aspancount),%edi
+	movl	C(ubasestep),%edx
+	movl	%ebx,C(errorterm)
+	addl	%edx,%edi
+	movl	%edi,C(d_aspancount)
+
+LRightEdgeStepped:
+	cmpl	$1,%eax
+
+	jl		LNextSpan
+	jz		LExactlyOneLong
+
+//
+// set up advancetable
+//
+	movl	C(a_ststepxwhole),%ecx
+	movl	C(r_affinetridesc)+atd_skinwidth,%edx
+
+	movl	%ecx,advancetable+4	// advance base in t
+	addl	%edx,%ecx
+
+	movl	%ecx,advancetable	// advance extra in t
+	movl	C(a_tstepxfrac),%ecx
+
+	movw	C(r_lstepx),%cx
+	movl	%eax,%edx			// count
+
+	movl	%ecx,tstep
+	addl	$7,%edx
+
+	shrl	$3,%edx				// count of full and partial loops
+	movl	spanpackage_t_sfrac(%esi),%ebx
+
+	movw	%dx,%bx
+	movl	spanpackage_t_pz(%esi),%ecx
+
+	negl	%eax
+
+	movl	spanpackage_t_pdest(%esi),%edi
+	andl	$7,%eax		// 0->0, 1->7, 2->6, ... , 7->1
+
+	subl	%eax,%edi	// compensate for hardwired offsets
+	subl	%eax,%ecx
+
+	subl	%eax,%ecx
+	movl	spanpackage_t_tfrac(%esi),%edx
+
+	movw	spanpackage_t_light(%esi),%dx
+	movl	spanpackage_t_zi(%esi),%ebp
+
+	rorl	$16,%ebp	// put high 16 bits of 1/z in low word
+	pushl	%esi
+
+	movl	spanpackage_t_ptex(%esi),%esi
+	jmp		aff8entryvec_table(,%eax,4)
+
+// %bx = count of full and partial loops
+// %ebx high word = sfrac
+// %ecx = pz
+// %dx = light
+// %edx high word = tfrac
+// %esi = ptex
+// %edi = pdest
+// %ebp = 1/z
+// tstep low word = C(r_lstepx)
+// tstep high word = C(a_tstepxfrac)
+// C(a_sstepxfrac) low word = 0
+// C(a_sstepxfrac) high word = C(a_sstepxfrac)
+
+LDrawLoop:
+
+// FIXME: do we need to clamp light? We may need at least a buffer bit to
+// keep it from poking into tfrac and causing problems
+
+LDraw8:
+	cmpw	(%ecx),%bp
+	jl		Lp1
+	xorl	%eax,%eax
+	movb	%dh,%ah
+	movb	(%esi),%al
+	movw	%bp,(%ecx)
+	movb	0x12345678(%eax),%al
+LPatch8:
+	movb	%al,(%edi)
+Lp1:
+	addl	tstep,%edx
+	sbbl	%eax,%eax
+	addl	lzistepx,%ebp
+	adcl	$0,%ebp
+	addl	C(a_sstepxfrac),%ebx
+	adcl	advancetable+4(,%eax,4),%esi
+
+LDraw7:
+	cmpw	2(%ecx),%bp
+	jl		Lp2
+	xorl	%eax,%eax
+	movb	%dh,%ah
+	movb	(%esi),%al
+	movw	%bp,2(%ecx)
+	movb	0x12345678(%eax),%al
+LPatch7:
+	movb	%al,1(%edi)
+Lp2:
+	addl	tstep,%edx
+	sbbl	%eax,%eax
+	addl	lzistepx,%ebp
+	adcl	$0,%ebp
+	addl	C(a_sstepxfrac),%ebx
+	adcl	advancetable+4(,%eax,4),%esi
+
+LDraw6:
+	cmpw	4(%ecx),%bp
+	jl		Lp3
+	xorl	%eax,%eax
+	movb	%dh,%ah
+	movb	(%esi),%al
+	movw	%bp,4(%ecx)
+	movb	0x12345678(%eax),%al
+LPatch6:
+	movb	%al,2(%edi)
+Lp3:
+	addl	tstep,%edx
+	sbbl	%eax,%eax
+	addl	lzistepx,%ebp
+	adcl	$0,%ebp
+	addl	C(a_sstepxfrac),%ebx
+	adcl	advancetable+4(,%eax,4),%esi
+
+LDraw5:
+	cmpw	6(%ecx),%bp
+	jl		Lp4
+	xorl	%eax,%eax
+	movb	%dh,%ah
+	movb	(%esi),%al
+	movw	%bp,6(%ecx)
+	movb	0x12345678(%eax),%al
+LPatch5:
+	movb	%al,3(%edi)
+Lp4:
+	addl	tstep,%edx
+	sbbl	%eax,%eax
+	addl	lzistepx,%ebp
+	adcl	$0,%ebp
+	addl	C(a_sstepxfrac),%ebx
+	adcl	advancetable+4(,%eax,4),%esi
+
+LDraw4:
+	cmpw	8(%ecx),%bp
+	jl		Lp5
+	xorl	%eax,%eax
+	movb	%dh,%ah
+	movb	(%esi),%al
+	movw	%bp,8(%ecx)
+	movb	0x12345678(%eax),%al
+LPatch4:
+	movb	%al,4(%edi)
+Lp5:
+	addl	tstep,%edx
+	sbbl	%eax,%eax
+	addl	lzistepx,%ebp
+	adcl	$0,%ebp
+	addl	C(a_sstepxfrac),%ebx
+	adcl	advancetable+4(,%eax,4),%esi
+
+LDraw3:
+	cmpw	10(%ecx),%bp
+	jl		Lp6
+	xorl	%eax,%eax
+	movb	%dh,%ah
+	movb	(%esi),%al
+	movw	%bp,10(%ecx)
+	movb	0x12345678(%eax),%al
+LPatch3:
+	movb	%al,5(%edi)
+Lp6:
+	addl	tstep,%edx
+	sbbl	%eax,%eax
+	addl	lzistepx,%ebp
+	adcl	$0,%ebp
+	addl	C(a_sstepxfrac),%ebx
+	adcl	advancetable+4(,%eax,4),%esi
+
+LDraw2:
+	cmpw	12(%ecx),%bp
+	jl		Lp7
+	xorl	%eax,%eax
+	movb	%dh,%ah
+	movb	(%esi),%al
+	movw	%bp,12(%ecx)
+	movb	0x12345678(%eax),%al
+LPatch2:
+	movb	%al,6(%edi)
+Lp7:
+	addl	tstep,%edx
+	sbbl	%eax,%eax
+	addl	lzistepx,%ebp
+	adcl	$0,%ebp
+	addl	C(a_sstepxfrac),%ebx
+	adcl	advancetable+4(,%eax,4),%esi
+
+LDraw1:
+	cmpw	14(%ecx),%bp
+	jl		Lp8
+	xorl	%eax,%eax
+	movb	%dh,%ah
+	movb	(%esi),%al
+	movw	%bp,14(%ecx)
+	movb	0x12345678(%eax),%al
+LPatch1:
+	movb	%al,7(%edi)
+Lp8:
+	addl	tstep,%edx
+	sbbl	%eax,%eax
+	addl	lzistepx,%ebp
+	adcl	$0,%ebp
+	addl	C(a_sstepxfrac),%ebx
+	adcl	advancetable+4(,%eax,4),%esi
+
+	addl	$8,%edi
+	addl	$16,%ecx
+
+	decw	%bx
+	jnz		LDrawLoop
+
+	popl	%esi				// restore spans pointer
+LNextSpan:
+	addl	$(spanpackage_t_size),%esi	// point to next span
+LNextSpanESISet:
+	movl	spanpackage_t_count(%esi),%edx
+	cmpl	$-999999,%edx		// any more spans?
+	jnz		LSpanLoop			// yes
+
+	popl	%edi
+	popl	%ebp				// restore the caller's stack frame
+	popl	%ebx				// restore register variables
+	popl	%esi
+	ret
+
+
+// draw a one-long span
+
+LExactlyOneLong:
+
+	movl	spanpackage_t_pz(%esi),%ecx
+	movl	spanpackage_t_zi(%esi),%ebp
+
+	rorl	$16,%ebp	// put high 16 bits of 1/z in low word
+	movl	spanpackage_t_ptex(%esi),%ebx
+
+	cmpw	(%ecx),%bp
+	jl		LNextSpan
+	xorl	%eax,%eax
+	movl	spanpackage_t_pdest(%esi),%edi
+	movb	spanpackage_t_light+1(%esi),%ah
+	addl	$(spanpackage_t_size),%esi	// point to next span
+	movb	(%ebx),%al
+	movw	%bp,(%ecx)
+	movb	0x12345678(%eax),%al
+LPatch9:
+	movb	%al,(%edi)
+
+	jmp		LNextSpanESISet
+
+.globl C(D_PolysetAff8End)
+C(D_PolysetAff8End):
+
+
+#define pcolormap		4
+
+.globl C(D_Aff8Patch)
+C(D_Aff8Patch):
+	movl	pcolormap(%esp),%eax
+	movl	%eax,LPatch1-4
+	movl	%eax,LPatch2-4
+	movl	%eax,LPatch3-4
+	movl	%eax,LPatch4-4
+	movl	%eax,LPatch5-4
+	movl	%eax,LPatch6-4
+	movl	%eax,LPatch7-4
+	movl	%eax,LPatch8-4
+	movl	%eax,LPatch9-4
+
+	ret
+
+
+//----------------------------------------------------------------------
+// Alias model polygon dispatching code, combined with subdivided affine
+// triangle drawing code
+//----------------------------------------------------------------------
+
+.globl C(D_PolysetDraw)
+C(D_PolysetDraw):
+
+//	spanpackage_t	spans[DPS_MAXSPANS + 1 +
+//			((CACHE_SIZE - 1) / sizeof(spanpackage_t)) + 1];
+//						// one extra because of cache line pretouching
+//
+//	a_spans = (spanpackage_t *)
+//			(((long)&spans[0] + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1));
+	subl	$(SPAN_SIZE),%esp
+	movl	%esp,%eax
+	addl	$(CACHE_SIZE - 1),%eax
+	andl	$(~(CACHE_SIZE - 1)),%eax
+	movl	%eax,C(a_spans)
+
+//	if (r_affinetridesc.drawtype)
+//		D_DrawSubdiv ();
+//	else
+//		D_DrawNonSubdiv ();
+	movl	C(r_affinetridesc)+atd_drawtype,%eax
+	testl	%eax,%eax
+	jz		C(D_DrawNonSubdiv)
+
+	pushl	%ebp				// preserve caller stack frame pointer
+
+//	lnumtriangles = r_affinetridesc.numtriangles;
+	movl	C(r_affinetridesc)+atd_numtriangles,%ebp
+
+	pushl	%esi				// preserve register variables
+	shll	$4,%ebp
+
+	pushl	%ebx
+//	ptri = r_affinetridesc.ptriangles;
+	movl	C(r_affinetridesc)+atd_ptriangles,%ebx
+
+	pushl	%edi
+
+//	mtriangle_t		*ptri;
+//	finalvert_t		*pfv, *index0, *index1, *index2;
+//	int				i;
+//	int				lnumtriangles;
+//	int				s0, s1, s2;
+
+//	pfv = r_affinetridesc.pfinalverts;
+	movl	C(r_affinetridesc)+atd_pfinalverts,%edi
+
+//	for (i=0 ; i<lnumtriangles ; i++)
+//	{
+
+Llooptop:
+
+//		index0 = pfv + ptri[i].vertindex[0];
+//		index1 = pfv + ptri[i].vertindex[1];
+//		index2 = pfv + ptri[i].vertindex[2];
+	movl	mtri_vertindex-16+0(%ebx,%ebp,),%ecx
+	movl	mtri_vertindex-16+4(%ebx,%ebp,),%esi
+
+	shll	$(fv_shift),%ecx
+	movl	mtri_vertindex-16+8(%ebx,%ebp,),%edx
+
+	shll	$(fv_shift),%esi
+	addl	%edi,%ecx
+
+	shll	$(fv_shift),%edx
+	addl	%edi,%esi
+
+	addl	%edi,%edx
+
+//		if (((index0->v[1]-index1->v[1]) *
+//				(index0->v[0]-index2->v[0]) -
+//				(index0->v[0]-index1->v[0])*(index0->v[1]-index2->v[1])) >= 0)
+//		{
+//			continue;
+//		}
+//
+//		d_pcolormap = &((byte *)acolormap)[index0->v[4] & 0xFF00];
+	fildl	fv_v+4(%ecx)	// i0v1
+	fildl	fv_v+4(%esi)	// i1v1 | i0v1
+	fildl	fv_v+0(%ecx)	// i0v0 | i1v1 | i0v1
+	fildl	fv_v+0(%edx)	// i2v0 | i0v0 | i1v1 | i0v1
+	fxch	%st(2)			// i1v1 | i0v0 | i2v0 | i0v1
+	fsubr	%st(3),%st(0)	// i0v1-i1v1 | i0v0 | i2v0 | i0v1
+	fildl	fv_v+0(%esi)	// i1v0 | i0v1-i1v1 | i0v0 | i2v0 | i0v1
+	fxch	%st(2)			// i0v0 | i0v1-i1v1 | i1v0 | i2v0 | i0v1
+	fsub	%st(0),%st(3)	// i0v0 | i0v1-i1v1 | i1v0 | i0v0-i2v0 | i0v1
+	fildl	fv_v+4(%edx)	// i2v1 | i0v0 | i0v1-i1v1 | i1v0 | i0v0-i2v0| i0v1
+	fxch	%st(1)			// i0v0 | i2v1 | i0v1-i1v1 | i1v0 | i0v0-i2v0| i0v1
+	fsubp	%st(0),%st(3)	// i2v1 | i0v1-i1v1 | i0v0-i1v0 | i0v0-i2v0 | i0v1
+	fxch	%st(1)			// i0v1-i1v1 | i2v1 | i0v0-i1v0 | i0v0-i2v0 | i0v1
+	fmulp	%st(0),%st(3)	// i2v1 | i0v0-i1v0 | i0v1-i1v1*i0v0-i2v0 | i0v1
+	fsubrp	%st(0),%st(3)	// i0v0-i1v0 | i0v1-i1v1*i0v0-i2v0 | i0v1-i2v1
+	movl	fv_v+16(%ecx),%eax
+	andl	$0xFF00,%eax
+	fmulp	%st(0),%st(2)	// i0v1-i1v1*i0v0-i2v0 | i0v0-i1v0*i0v1-i2v1
+	addl	C(acolormap),%eax
+	fsubp	%st(0),%st(1)	// (i0v1-i1v1)*(i0v0-i2v0)-(i0v0-i1v0)*(i0v1-i2v1)
+	movl	%eax,C(d_pcolormap)
+	fstps	Ltemp
+	movl	Ltemp,%eax
+	subl	$0x80000001,%eax
+	jc		Lskip
+
+//		if (ptri[i].facesfront)
+//		{
+//			D_PolysetRecursiveTriangle(index0->v, index1->v, index2->v);
+	movl	mtri_facesfront-16(%ebx,%ebp,),%eax
+	testl	%eax,%eax
+	jz		Lfacesback
+
+	pushl	%edx
+	pushl	%esi
+	pushl	%ecx
+	call	C(D_PolysetRecursiveTriangle)
+
+	subl	$16,%ebp
+	jnz		Llooptop
+	jmp		Ldone2
+
+//		}
+//		else
+//		{
+Lfacesback:
+
+//			s0 = index0->v[2];
+//			s1 = index1->v[2];
+//			s2 = index2->v[2];
+	movl	fv_v+8(%ecx),%eax
+	pushl	%eax
+	movl	fv_v+8(%esi),%eax
+	pushl	%eax
+	movl	fv_v+8(%edx),%eax
+	pushl	%eax
+	pushl	%ecx
+	pushl	%edx
+
+//			if (index0->flags & ALIAS_ONSEAM)
+//				index0->v[2] += r_affinetridesc.seamfixupX16;
+	movl	C(r_affinetridesc)+atd_seamfixupX16,%eax
+	testl	$(ALIAS_ONSEAM),fv_flags(%ecx)
+	jz		Lp11
+	addl	%eax,fv_v+8(%ecx)
+Lp11:
+
+//			if (index1->flags & ALIAS_ONSEAM)
+//				index1->v[2] += r_affinetridesc.seamfixupX16;
+	testl	$(ALIAS_ONSEAM),fv_flags(%esi)
+	jz		Lp12
+	addl	%eax,fv_v+8(%esi)
+Lp12:
+
+//			if (index2->flags & ALIAS_ONSEAM)
+//				index2->v[2] += r_affinetridesc.seamfixupX16;
+	testl	$(ALIAS_ONSEAM),fv_flags(%edx)
+	jz		Lp13
+	addl	%eax,fv_v+8(%edx)
+Lp13:
+
+//			D_PolysetRecursiveTriangle(index0->v, index1->v, index2->v);
+	pushl	%edx
+	pushl	%esi
+	pushl	%ecx
+	call	C(D_PolysetRecursiveTriangle)
+
+//			index0->v[2] = s0;
+//			index1->v[2] = s1;
+//			index2->v[2] = s2;
+	popl	%edx
+	popl	%ecx
+	popl	%eax
+	movl	%eax,fv_v+8(%edx)
+	popl	%eax
+	movl	%eax,fv_v+8(%esi)
+	popl	%eax
+	movl	%eax,fv_v+8(%ecx)
+
+//		}
+//	}
+Lskip:
+	subl	$16,%ebp
+	jnz		Llooptop
+
+Ldone2:
+	popl	%edi				// restore the caller's stack frame
+	popl	%ebx
+	popl	%esi				// restore register variables
+	popl	%ebp
+
+	addl	$(SPAN_SIZE),%esp
+
+	ret
+
+
+//----------------------------------------------------------------------
+// Alias model triangle left-edge scanning code
+//----------------------------------------------------------------------
+
+#define height	4+16
+
+.globl C(D_PolysetScanLeftEdge)
+C(D_PolysetScanLeftEdge):
+	pushl	%ebp				// preserve caller stack frame pointer
+	pushl	%esi				// preserve register variables
+	pushl	%edi
+	pushl	%ebx
+
+	movl	height(%esp),%eax
+	movl	C(d_sfrac),%ecx
+	andl	$0xFFFF,%eax
+	movl	C(d_ptex),%ebx
+	orl		%eax,%ecx
+	movl	C(d_pedgespanpackage),%esi
+	movl	C(d_tfrac),%edx
+	movl	C(d_light),%edi
+	movl	C(d_zi),%ebp
+
+// %eax: scratch
+// %ebx: d_ptex
+// %ecx: d_sfrac in high word, count in low word
+// %edx: d_tfrac
+// %esi: d_pedgespanpackage, errorterm, scratch alternately
+// %edi: d_light
+// %ebp: d_zi
+
+//	do
+//	{
+
+LScanLoop:
+
+//		d_pedgespanpackage->ptex = ptex;
+//		d_pedgespanpackage->pdest = d_pdest;
+//		d_pedgespanpackage->pz = d_pz;
+//		d_pedgespanpackage->count = d_aspancount;
+//		d_pedgespanpackage->light = d_light;
+//		d_pedgespanpackage->zi = d_zi;
+//		d_pedgespanpackage->sfrac = d_sfrac << 16;
+//		d_pedgespanpackage->tfrac = d_tfrac << 16;
+	movl	%ebx,spanpackage_t_ptex(%esi)
+	movl	C(d_pdest),%eax
+	movl	%eax,spanpackage_t_pdest(%esi)
+	movl	C(d_pz),%eax
+	movl	%eax,spanpackage_t_pz(%esi)
+	movl	C(d_aspancount),%eax
+	movl	%eax,spanpackage_t_count(%esi)
+	movl	%edi,spanpackage_t_light(%esi)
+	movl	%ebp,spanpackage_t_zi(%esi)
+	movl	%ecx,spanpackage_t_sfrac(%esi)
+	movl	%edx,spanpackage_t_tfrac(%esi)
+
+// pretouch the next cache line
+	movb	spanpackage_t_size(%esi),%al
+
+//		d_pedgespanpackage++;
+	addl	$(spanpackage_t_size),%esi
+	movl	C(erroradjustup),%eax
+	movl	%esi,C(d_pedgespanpackage)
+
+//		errorterm += erroradjustup;
+	movl	C(errorterm),%esi
+	addl	%eax,%esi
+	movl	C(d_pdest),%eax
+
+//		if (errorterm >= 0)
+//		{
+	js		LNoLeftEdgeTurnover
+
+//			errorterm -= erroradjustdown;
+//			d_pdest += d_pdestextrastep;
+	subl	C(erroradjustdown),%esi
+	addl	C(d_pdestextrastep),%eax
+	movl	%esi,C(errorterm)
+	movl	%eax,C(d_pdest)
+
+//			d_pz += d_pzextrastep;
+//			d_aspancount += d_countextrastep;
+//			d_ptex += d_ptexextrastep;
+//			d_sfrac += d_sfracextrastep;
+//			d_ptex += d_sfrac >> 16;
+//			d_sfrac &= 0xFFFF;
+//			d_tfrac += d_tfracextrastep;
+	movl	C(d_pz),%eax
+	movl	C(d_aspancount),%esi
+	addl	C(d_pzextrastep),%eax
+	addl	C(d_sfracextrastep),%ecx
+	adcl	C(d_ptexextrastep),%ebx
+	addl	C(d_countextrastep),%esi
+	movl	%eax,C(d_pz)
+	movl	C(d_tfracextrastep),%eax
+	movl	%esi,C(d_aspancount)
+	addl	%eax,%edx
+
+//			if (d_tfrac & 0x10000)
+//			{
+	jnc		LSkip1
+
+//				d_ptex += r_affinetridesc.skinwidth;
+//				d_tfrac &= 0xFFFF;
+	addl	C(r_affinetridesc)+atd_skinwidth,%ebx
+
+//			}
+
+LSkip1:
+
+//			d_light += d_lightextrastep;
+//			d_zi += d_ziextrastep;
+	addl	C(d_lightextrastep),%edi
+	addl	C(d_ziextrastep),%ebp
+
+//		}
+	movl	C(d_pedgespanpackage),%esi
+	decl	%ecx
+	testl	$0xFFFF,%ecx
+	jnz		LScanLoop
+
+	popl	%ebx
+	popl	%edi
+	popl	%esi
+	popl	%ebp
+	ret
+
+//		else
+//		{
+
+LNoLeftEdgeTurnover:
+	movl	%esi,C(errorterm)
+
+//			d_pdest += d_pdestbasestep;
+	addl	C(d_pdestbasestep),%eax
+	movl	%eax,C(d_pdest)
+
+//			d_pz += d_pzbasestep;
+//			d_aspancount += ubasestep;
+//			d_ptex += d_ptexbasestep;
+//			d_sfrac += d_sfracbasestep;
+//			d_ptex += d_sfrac >> 16;
+//			d_sfrac &= 0xFFFF;
+	movl	C(d_pz),%eax
+	movl	C(d_aspancount),%esi
+	addl	C(d_pzbasestep),%eax
+	addl	C(d_sfracbasestep),%ecx
+	adcl	C(d_ptexbasestep),%ebx
+	addl	C(ubasestep),%esi
+	movl	%eax,C(d_pz)
+	movl	%esi,C(d_aspancount)
+
+//			d_tfrac += d_tfracbasestep;
+	movl	C(d_tfracbasestep),%esi
+	addl	%esi,%edx
+
+//			if (d_tfrac & 0x10000)
+//			{
+	jnc		LSkip2
+
+//				d_ptex += r_affinetridesc.skinwidth;
+//				d_tfrac &= 0xFFFF;
+	addl	C(r_affinetridesc)+atd_skinwidth,%ebx
+
+//			}
+
+LSkip2:
+
+//			d_light += d_lightbasestep;
+//			d_zi += d_zibasestep;
+	addl	C(d_lightbasestep),%edi
+	addl	C(d_zibasestep),%ebp
+
+//		}
+//	} while (--height);
+	movl	C(d_pedgespanpackage),%esi
+	decl	%ecx
+	testl	$0xFFFF,%ecx
+	jnz		LScanLoop
+
+	popl	%ebx
+	popl	%edi
+	popl	%esi
+	popl	%ebp
+	ret
+
+
+//----------------------------------------------------------------------
+// Alias model vertex drawing code
+//----------------------------------------------------------------------
+
+#define fv			4+8
+#define	numverts	8+8
+
+.globl C(D_PolysetDrawFinalVerts)
+C(D_PolysetDrawFinalVerts):
+	pushl	%ebp				// preserve caller stack frame pointer
+	pushl	%ebx
+
+//	int		i, z;
+//	short	*zbuf;
+
+	movl	numverts(%esp),%ecx
+	movl	fv(%esp),%ebx
+
+	pushl	%esi				// preserve register variables
+	pushl	%edi
+
+LFVLoop:
+
+//	for (i=0 ; i<numverts ; i++, fv++)
+//	{
+//	// valid triangle coordinates for filling can include the bottom and
+//	// right clip edges, due to the fill rule; these shouldn't be drawn
+//		if ((fv->v[0] < r_refdef.vrectright) &&
+//			(fv->v[1] < r_refdef.vrectbottom))
+//		{
+	movl	fv_v+0(%ebx),%eax
+	movl	C(r_refdef)+rd_vrectright,%edx
+	cmpl	%edx,%eax
+	jge		LNextVert
+	movl	fv_v+4(%ebx),%esi
+	movl	C(r_refdef)+rd_vrectbottom,%edx
+	cmpl	%edx,%esi
+	jge		LNextVert
+
+//			zbuf = zspantable[fv->v[1]] + fv->v[0];
+	movl	C(zspantable)(,%esi,4),%edi
+
+//			z = fv->v[5]>>16;
+	movl	fv_v+20(%ebx),%edx
+	shrl	$16,%edx
+
+//			if (z >= *zbuf)
+//			{
+//				int		pix;
+	cmpw	(%edi,%eax,2),%dx
+	jl		LNextVert
+
+//				*zbuf = z;
+	movw	%dx,(%edi,%eax,2)
+
+//				pix = skintable[fv->v[3]>>16][fv->v[2]>>16];
+	movl	fv_v+12(%ebx),%edi
+	shrl	$16,%edi
+	movl	C(skintable)(,%edi,4),%edi
+	movl	fv_v+8(%ebx),%edx
+	shrl	$16,%edx
+	movb	(%edi,%edx),%dl
+
+//				pix = ((byte *)acolormap)[pix + (fv->v[4] & 0xFF00)];
+	movl	fv_v+16(%ebx),%edi
+	andl	$0xFF00,%edi
+	andl	$0x00FF,%edx
+	addl	%edx,%edi
+	movl	C(acolormap),%edx
+	movb	(%edx,%edi,1),%dl
+
+//				d_viewbuffer[d_scantable[fv->v[1]] + fv->v[0]] = pix;
+	movl	C(d_scantable)(,%esi,4),%edi
+	movl	C(d_viewbuffer),%esi
+	addl	%eax,%edi
+	movb	%dl,(%esi,%edi)
+
+//			}
+//		}
+//	}
+LNextVert:
+	addl	$(fv_size),%ebx
+	decl	%ecx
+	jnz		LFVLoop
+
+	popl	%edi
+	popl	%esi
+	popl	%ebx
+	popl	%ebp
+	ret
+
+
+//----------------------------------------------------------------------
+// Alias model non-subdivided polygon dispatching code
+//
+// not C-callable because of stack buffer cleanup
+//----------------------------------------------------------------------
+
+.globl C(D_DrawNonSubdiv)
+C(D_DrawNonSubdiv):
+	pushl	%ebp				// preserve caller stack frame pointer
+	movl	C(r_affinetridesc)+atd_numtriangles,%ebp
+	pushl	%ebx
+	shll	$(mtri_shift),%ebp
+	pushl	%esi				// preserve register variables
+	movl	C(r_affinetridesc)+atd_ptriangles,%esi
+	pushl	%edi
+
+//	mtriangle_t		*ptri;
+//	finalvert_t		*pfv, *index0, *index1, *index2;
+//	int				i;
+//	int				lnumtriangles;
+
+//	pfv = r_affinetridesc.pfinalverts;
+//	ptri = r_affinetridesc.ptriangles;
+//	lnumtriangles = r_affinetridesc.numtriangles;
+
+LNDLoop:
+
+//	for (i=0 ; i<lnumtriangles ; i++, ptri++)
+//	{
+//		index0 = pfv + ptri->vertindex[0];
+//		index1 = pfv + ptri->vertindex[1];
+//		index2 = pfv + ptri->vertindex[2];
+	movl	C(r_affinetridesc)+atd_pfinalverts,%edi
+	movl	mtri_vertindex+0-mtri_size(%esi,%ebp,1),%ecx
+	shll	$(fv_shift),%ecx
+	movl	mtri_vertindex+4-mtri_size(%esi,%ebp,1),%edx
+	shll	$(fv_shift),%edx
+	movl	mtri_vertindex+8-mtri_size(%esi,%ebp,1),%ebx
+	shll	$(fv_shift),%ebx
+	addl	%edi,%ecx
+	addl	%edi,%edx
+	addl	%edi,%ebx
+
+//		d_xdenom = (index0->v[1]-index1->v[1]) *
+//				(index0->v[0]-index2->v[0]) -
+//				(index0->v[0]-index1->v[0])*(index0->v[1]-index2->v[1]);
+	movl	fv_v+4(%ecx),%eax
+	movl	fv_v+0(%ecx),%esi
+	subl	fv_v+4(%edx),%eax
+	subl	fv_v+0(%ebx),%esi
+	imull	%esi,%eax
+	movl	fv_v+0(%ecx),%esi
+	movl	fv_v+4(%ecx),%edi
+	subl	fv_v+0(%edx),%esi
+	subl	fv_v+4(%ebx),%edi
+	imull	%esi,%edi
+	subl	%edi,%eax
+
+//		if (d_xdenom >= 0)
+//		{
+//			continue;
+	jns		LNextTri
+
+//		}
+
+	movl	%eax,C(d_xdenom)
+	fildl	C(d_xdenom)
+
+//		r_p0[0] = index0->v[0];		// u
+//		r_p0[1] = index0->v[1];		// v
+//		r_p0[2] = index0->v[2];		// s
+//		r_p0[3] = index0->v[3];		// t
+//		r_p0[4] = index0->v[4];		// light
+//		r_p0[5] = index0->v[5];		// iz
+	movl	fv_v+0(%ecx),%eax
+	movl	fv_v+4(%ecx),%esi
+	movl	%eax,C(r_p0)+0
+	movl	%esi,C(r_p0)+4
+	movl	fv_v+8(%ecx),%eax
+	movl	fv_v+12(%ecx),%esi
+	movl	%eax,C(r_p0)+8
+	movl	%esi,C(r_p0)+12
+	movl	fv_v+16(%ecx),%eax
+	movl	fv_v+20(%ecx),%esi
+	movl	%eax,C(r_p0)+16
+	movl	%esi,C(r_p0)+20
+
+	fdivrs	float_1
+
+//		r_p1[0] = index1->v[0];
+//		r_p1[1] = index1->v[1];
+//		r_p1[2] = index1->v[2];
+//		r_p1[3] = index1->v[3];
+//		r_p1[4] = index1->v[4];
+//		r_p1[5] = index1->v[5];
+	movl	fv_v+0(%edx),%eax
+	movl	fv_v+4(%edx),%esi
+	movl	%eax,C(r_p1)+0
+	movl	%esi,C(r_p1)+4
+	movl	fv_v+8(%edx),%eax
+	movl	fv_v+12(%edx),%esi
+	movl	%eax,C(r_p1)+8
+	movl	%esi,C(r_p1)+12
+	movl	fv_v+16(%edx),%eax
+	movl	fv_v+20(%edx),%esi
+	movl	%eax,C(r_p1)+16
+	movl	%esi,C(r_p1)+20
+
+//		r_p2[0] = index2->v[0];
+//		r_p2[1] = index2->v[1];
+//		r_p2[2] = index2->v[2];
+//		r_p2[3] = index2->v[3];
+//		r_p2[4] = index2->v[4];
+//		r_p2[5] = index2->v[5];
+	movl	fv_v+0(%ebx),%eax
+	movl	fv_v+4(%ebx),%esi
+	movl	%eax,C(r_p2)+0
+	movl	%esi,C(r_p2)+4
+	movl	fv_v+8(%ebx),%eax
+	movl	fv_v+12(%ebx),%esi
+	movl	%eax,C(r_p2)+8
+	movl	%esi,C(r_p2)+12
+	movl	fv_v+16(%ebx),%eax
+	movl	fv_v+20(%ebx),%esi
+	movl	%eax,C(r_p2)+16
+	movl	C(r_affinetridesc)+atd_ptriangles,%edi
+	movl	%esi,C(r_p2)+20
+	movl	mtri_facesfront-mtri_size(%edi,%ebp,1),%eax
+
+//		if (!ptri->facesfront)
+//		{
+	testl	%eax,%eax
+	jnz		LFacesFront
+
+//			if (index0->flags & ALIAS_ONSEAM)
+//				r_p0[2] += r_affinetridesc.seamfixupX16;
+	movl	fv_flags(%ecx),%eax
+	movl	fv_flags(%edx),%esi
+	movl	fv_flags(%ebx),%edi
+	testl	$(ALIAS_ONSEAM),%eax
+	movl	C(r_affinetridesc)+atd_seamfixupX16,%eax
+	jz		LOnseamDone0
+	addl	%eax,C(r_p0)+8
+LOnseamDone0:
+
+//			if (index1->flags & ALIAS_ONSEAM)
+// 				r_p1[2] += r_affinetridesc.seamfixupX16;
+	testl	$(ALIAS_ONSEAM),%esi
+	jz		LOnseamDone1
+	addl	%eax,C(r_p1)+8
+LOnseamDone1:
+
+//			if (index2->flags & ALIAS_ONSEAM)
+//				r_p2[2] += r_affinetridesc.seamfixupX16;
+	testl	$(ALIAS_ONSEAM),%edi
+	jz		LOnseamDone2
+	addl	%eax,C(r_p2)+8
+LOnseamDone2:
+
+//		}
+
+LFacesFront:
+
+	fstps	C(d_xdenom)
+
+//		D_PolysetSetEdgeTable ();
+//		D_RasterizeAliasPolySmooth ();
+		call	C(D_PolysetSetEdgeTable)
+		call	C(D_RasterizeAliasPolySmooth)
+
+LNextTri:
+		movl	C(r_affinetridesc)+atd_ptriangles,%esi
+		subl	$16,%ebp
+		jnz		LNDLoop
+//	}
+
+	popl	%edi
+	popl	%esi
+	popl	%ebx
+	popl	%ebp
+
+	addl	$(SPAN_SIZE),%esp
+
+	ret
+
+
+#endif	// id386
+
--- /dev/null
+++ b/QW/client/d_polyse.c
@@ -1,0 +1,1064 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// d_polyset.c: routines for drawing sets of polygons sharing the same
+// texture (used for Alias models)
+
+#include "quakedef.h"
+#include "r_local.h"
+#include "d_local.h"
+
+// TODO: put in span spilling to shrink list size
+// !!! if this is changed, it must be changed in d_polysa.s too !!!
+#define DPS_MAXSPANS			MAXHEIGHT+1	
+									// 1 extra for spanpackage that marks end
+
+// !!! if this is changed, it must be changed in asm_draw.h too !!!
+typedef struct {
+	void			*pdest;
+	short			*pz;
+	int				count;
+	byte			*ptex;
+	int				sfrac, tfrac, light, zi;
+} spanpackage_t;
+
+typedef struct {
+	int		isflattop;
+	int		numleftedges;
+	int		*pleftedgevert0;
+	int		*pleftedgevert1;
+	int		*pleftedgevert2;
+	int		numrightedges;
+	int		*prightedgevert0;
+	int		*prightedgevert1;
+	int		*prightedgevert2;
+} edgetable;
+
+int	r_p0[6], r_p1[6], r_p2[6];
+
+byte		*d_pcolormap;
+
+int			d_aflatcolor;
+int			d_xdenom;
+
+edgetable	*pedgetable;
+
+edgetable	edgetables[12] = {
+	{0, 1, r_p0, r_p2, NULL, 2, r_p0, r_p1, r_p2 },
+	{0, 2, r_p1, r_p0, r_p2,   1, r_p1, r_p2, NULL},
+	{1, 1, r_p0, r_p2, NULL, 1, r_p1, r_p2, NULL},
+	{0, 1, r_p1, r_p0, NULL, 2, r_p1, r_p2, r_p0 },
+	{0, 2, r_p0, r_p2, r_p1,   1, r_p0, r_p1, NULL},
+	{0, 1, r_p2, r_p1, NULL, 1, r_p2, r_p0, NULL},
+	{0, 1, r_p2, r_p1, NULL, 2, r_p2, r_p0, r_p1 },
+	{0, 2, r_p2, r_p1, r_p0,   1, r_p2, r_p0, NULL},
+	{0, 1, r_p1, r_p0, NULL, 1, r_p1, r_p2, NULL},
+	{1, 1, r_p2, r_p1, NULL, 1, r_p0, r_p1, NULL},
+	{1, 1, r_p1, r_p0, NULL, 1, r_p2, r_p0, NULL},
+	{0, 1, r_p0, r_p2, NULL, 1, r_p0, r_p1, NULL},
+};
+
+// FIXME: some of these can become statics
+int				a_sstepxfrac, a_tstepxfrac, r_lstepx, a_ststepxwhole;
+int				r_sstepx, r_tstepx, r_lstepy, r_sstepy, r_tstepy;
+int				r_zistepx, r_zistepy;
+int				d_aspancount, d_countextrastep;
+
+spanpackage_t			*a_spans;
+spanpackage_t			*d_pedgespanpackage;
+static int				ystart;
+byte					*d_pdest, *d_ptex;
+short					*d_pz;
+int						d_sfrac, d_tfrac, d_light, d_zi;
+int						d_ptexextrastep, d_sfracextrastep;
+int						d_tfracextrastep, d_lightextrastep, d_pdestextrastep;
+int						d_lightbasestep, d_pdestbasestep, d_ptexbasestep;
+int						d_sfracbasestep, d_tfracbasestep;
+int						d_ziextrastep, d_zibasestep;
+int						d_pzextrastep, d_pzbasestep;
+
+typedef struct {
+	int		quotient;
+	int		remainder;
+} adivtab_t;
+
+static adivtab_t	adivtab[32*32] = {
+#include "adivtab.h"
+};
+
+byte	*skintable[MAX_LBM_HEIGHT];
+int		skinwidth;
+byte	*skinstart;
+
+void D_PolysetDrawSpans8 (spanpackage_t *pspanpackage);
+void D_PolysetCalcGradients (int skinwidth);
+void D_DrawSubdiv (void);
+void D_DrawNonSubdiv (void);
+void D_PolysetRecursiveTriangle (int *p1, int *p2, int *p3);
+void D_PolysetSetEdgeTable (void);
+void D_RasterizeAliasPolySmooth (void);
+void D_PolysetScanLeftEdge (int height);
+
+#if	!id386
+
+/*
+================
+D_PolysetDraw
+================
+*/
+void D_PolysetDraw (void)
+{
+	spanpackage_t	spans[DPS_MAXSPANS + 1 +
+			((CACHE_SIZE - 1) / sizeof(spanpackage_t)) + 1];
+						// one extra because of cache line pretouching
+
+	a_spans = (spanpackage_t *)
+			(((long)&spans[0] + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1));
+
+	if (r_affinetridesc.drawtype)
+	{
+		D_DrawSubdiv ();
+	}
+	else
+	{
+		D_DrawNonSubdiv ();
+	}
+}
+
+
+/*
+================
+D_PolysetDrawFinalVerts
+================
+*/
+void D_PolysetDrawFinalVerts (finalvert_t *fv, int numverts)
+{
+	int		i, z;
+	short	*zbuf;
+
+	for (i=0 ; i<numverts ; i++, fv++)
+	{
+	// valid triangle coordinates for filling can include the bottom and
+	// right clip edges, due to the fill rule; these shouldn't be drawn
+		if ((fv->v[0] < r_refdef.vrectright) &&
+			(fv->v[1] < r_refdef.vrectbottom))
+		{
+			z = fv->v[5]>>16;
+			zbuf = zspantable[fv->v[1]] + fv->v[0];
+			if (z >= *zbuf)
+			{
+				int		pix;
+				
+				*zbuf = z;
+				pix = skintable[fv->v[3]>>16][fv->v[2]>>16];
+				pix = ((byte *)acolormap)[pix + (fv->v[4] & 0xFF00) ];
+				d_viewbuffer[d_scantable[fv->v[1]] + fv->v[0]] = pix;
+			}
+		}
+	}
+}
+
+
+/*
+================
+D_DrawSubdiv
+================
+*/
+void D_DrawSubdiv (void)
+{
+	mtriangle_t		*ptri;
+	finalvert_t		*pfv, *index0, *index1, *index2;
+	int				i;
+	int				lnumtriangles;
+
+	pfv = r_affinetridesc.pfinalverts;
+	ptri = r_affinetridesc.ptriangles;
+	lnumtriangles = r_affinetridesc.numtriangles;
+
+	for (i=0 ; i<lnumtriangles ; i++)
+	{
+		index0 = pfv + ptri[i].vertindex[0];
+		index1 = pfv + ptri[i].vertindex[1];
+		index2 = pfv + ptri[i].vertindex[2];
+
+		if (((index0->v[1]-index1->v[1]) *
+			 (index0->v[0]-index2->v[0]) -
+			 (index0->v[0]-index1->v[0]) * 
+			 (index0->v[1]-index2->v[1])) >= 0)
+		{
+			continue;
+		}
+
+		d_pcolormap = &((byte *)acolormap)[index0->v[4] & 0xFF00];
+
+		if (ptri[i].facesfront)
+		{
+			D_PolysetRecursiveTriangle(index0->v, index1->v, index2->v);
+		}
+		else
+		{
+			int		s0, s1, s2;
+
+			s0 = index0->v[2];
+			s1 = index1->v[2];
+			s2 = index2->v[2];
+
+			if (index0->flags & ALIAS_ONSEAM)
+				index0->v[2] += r_affinetridesc.seamfixupX16;
+			if (index1->flags & ALIAS_ONSEAM)
+				index1->v[2] += r_affinetridesc.seamfixupX16;
+			if (index2->flags & ALIAS_ONSEAM)
+				index2->v[2] += r_affinetridesc.seamfixupX16;
+
+			D_PolysetRecursiveTriangle(index0->v, index1->v, index2->v);
+
+			index0->v[2] = s0;
+			index1->v[2] = s1;
+			index2->v[2] = s2;
+		}
+	}
+}
+
+
+/*
+================
+D_DrawNonSubdiv
+================
+*/
+void D_DrawNonSubdiv (void)
+{
+	mtriangle_t		*ptri;
+	finalvert_t		*pfv, *index0, *index1, *index2;
+	int				i;
+	int				lnumtriangles;
+
+	pfv = r_affinetridesc.pfinalverts;
+	ptri = r_affinetridesc.ptriangles;
+	lnumtriangles = r_affinetridesc.numtriangles;
+
+	for (i=0 ; i<lnumtriangles ; i++, ptri++)
+	{
+		index0 = pfv + ptri->vertindex[0];
+		index1 = pfv + ptri->vertindex[1];
+		index2 = pfv + ptri->vertindex[2];
+
+		d_xdenom = (index0->v[1]-index1->v[1]) *
+				(index0->v[0]-index2->v[0]) -
+				(index0->v[0]-index1->v[0])*(index0->v[1]-index2->v[1]);
+
+		if (d_xdenom >= 0)
+		{
+			continue;
+		}
+
+		r_p0[0] = index0->v[0];		// u
+		r_p0[1] = index0->v[1];		// v
+		r_p0[2] = index0->v[2];		// s
+		r_p0[3] = index0->v[3];		// t
+		r_p0[4] = index0->v[4];		// light
+		r_p0[5] = index0->v[5];		// iz
+
+		r_p1[0] = index1->v[0];
+		r_p1[1] = index1->v[1];
+		r_p1[2] = index1->v[2];
+		r_p1[3] = index1->v[3];
+		r_p1[4] = index1->v[4];
+		r_p1[5] = index1->v[5];
+
+		r_p2[0] = index2->v[0];
+		r_p2[1] = index2->v[1];
+		r_p2[2] = index2->v[2];
+		r_p2[3] = index2->v[3];
+		r_p2[4] = index2->v[4];
+		r_p2[5] = index2->v[5];
+
+		if (!ptri->facesfront)
+		{
+			if (index0->flags & ALIAS_ONSEAM)
+				r_p0[2] += r_affinetridesc.seamfixupX16;
+			if (index1->flags & ALIAS_ONSEAM)
+				r_p1[2] += r_affinetridesc.seamfixupX16;
+			if (index2->flags & ALIAS_ONSEAM)
+				r_p2[2] += r_affinetridesc.seamfixupX16;
+		}
+
+		D_PolysetSetEdgeTable ();
+		D_RasterizeAliasPolySmooth ();
+	}
+}
+
+
+/*
+================
+D_PolysetRecursiveTriangle
+================
+*/
+void D_PolysetRecursiveTriangle (int *lp1, int *lp2, int *lp3)
+{
+	int		*temp;
+	int		d;
+	int		new[6];
+	int		z;
+	short	*zbuf;
+
+	d = lp2[0] - lp1[0];
+	if (d < -1 || d > 1)
+		goto split;
+	d = lp2[1] - lp1[1];
+	if (d < -1 || d > 1)
+		goto split;
+
+	d = lp3[0] - lp2[0];
+	if (d < -1 || d > 1)
+		goto split2;
+	d = lp3[1] - lp2[1];
+	if (d < -1 || d > 1)
+		goto split2;
+
+	d = lp1[0] - lp3[0];
+	if (d < -1 || d > 1)
+		goto split3;
+	d = lp1[1] - lp3[1];
+	if (d < -1 || d > 1)
+	{
+split3:
+		temp = lp1;
+		lp1 = lp3;
+		lp3 = lp2;
+		lp2 = temp;
+
+		goto split;
+	}
+
+	return;			// entire tri is filled
+
+split2:
+	temp = lp1;
+	lp1 = lp2;
+	lp2 = lp3;
+	lp3 = temp;
+
+split:
+// split this edge
+	new[0] = (lp1[0] + lp2[0]) >> 1;
+	new[1] = (lp1[1] + lp2[1]) >> 1;
+	new[2] = (lp1[2] + lp2[2]) >> 1;
+	new[3] = (lp1[3] + lp2[3]) >> 1;
+	new[5] = (lp1[5] + lp2[5]) >> 1;
+
+// draw the point if splitting a leading edge
+	if (lp2[1] > lp1[1])
+		goto nodraw;
+	if ((lp2[1] == lp1[1]) && (lp2[0] < lp1[0]))
+		goto nodraw;
+
+
+	z = new[5]>>16;
+	zbuf = zspantable[new[1]] + new[0];
+	if (z >= *zbuf)
+	{
+		int		pix;
+		
+		*zbuf = z;
+		pix = d_pcolormap[skintable[new[3]>>16][new[2]>>16]];
+		d_viewbuffer[d_scantable[new[1]] + new[0]] = pix;
+	}
+
+nodraw:
+// recursively continue
+	D_PolysetRecursiveTriangle (lp3, lp1, new);
+	D_PolysetRecursiveTriangle (lp3, new, lp2);
+}
+
+#endif	// !id386
+
+
+/*
+================
+D_PolysetUpdateTables
+================
+*/
+void D_PolysetUpdateTables (void)
+{
+	int		i;
+	byte	*s;
+	
+	if (r_affinetridesc.skinwidth != skinwidth ||
+		r_affinetridesc.pskin != skinstart)
+	{
+		skinwidth = r_affinetridesc.skinwidth;
+		skinstart = r_affinetridesc.pskin;
+		s = skinstart;
+		for (i=0 ; i<MAX_LBM_HEIGHT ; i++, s+=skinwidth)
+			skintable[i] = s;
+	}
+}
+
+
+#if	!id386
+
+/*
+===================
+D_PolysetScanLeftEdge
+====================
+*/
+void D_PolysetScanLeftEdge (int height)
+{
+
+	do
+	{
+		d_pedgespanpackage->pdest = d_pdest;
+		d_pedgespanpackage->pz = d_pz;
+		d_pedgespanpackage->count = d_aspancount;
+		d_pedgespanpackage->ptex = d_ptex;
+
+		d_pedgespanpackage->sfrac = d_sfrac;
+		d_pedgespanpackage->tfrac = d_tfrac;
+
+	// FIXME: need to clamp l, s, t, at both ends?
+		d_pedgespanpackage->light = d_light;
+		d_pedgespanpackage->zi = d_zi;
+
+		d_pedgespanpackage++;
+
+		errorterm += erroradjustup;
+		if (errorterm >= 0)
+		{
+			d_pdest += d_pdestextrastep;
+			d_pz += d_pzextrastep;
+			d_aspancount += d_countextrastep;
+			d_ptex += d_ptexextrastep;
+			d_sfrac += d_sfracextrastep;
+			d_ptex += d_sfrac >> 16;
+
+			d_sfrac &= 0xFFFF;
+			d_tfrac += d_tfracextrastep;
+			if (d_tfrac & 0x10000)
+			{
+				d_ptex += r_affinetridesc.skinwidth;
+				d_tfrac &= 0xFFFF;
+			}
+			d_light += d_lightextrastep;
+			d_zi += d_ziextrastep;
+			errorterm -= erroradjustdown;
+		}
+		else
+		{
+			d_pdest += d_pdestbasestep;
+			d_pz += d_pzbasestep;
+			d_aspancount += ubasestep;
+			d_ptex += d_ptexbasestep;
+			d_sfrac += d_sfracbasestep;
+			d_ptex += d_sfrac >> 16;
+			d_sfrac &= 0xFFFF;
+			d_tfrac += d_tfracbasestep;
+			if (d_tfrac & 0x10000)
+			{
+				d_ptex += r_affinetridesc.skinwidth;
+				d_tfrac &= 0xFFFF;
+			}
+			d_light += d_lightbasestep;
+			d_zi += d_zibasestep;
+		}
+	} while (--height);
+}
+
+#endif	// !id386
+
+
+/*
+===================
+D_PolysetSetUpForLineScan
+====================
+*/
+void D_PolysetSetUpForLineScan(fixed8_t startvertu, fixed8_t startvertv,
+		fixed8_t endvertu, fixed8_t endvertv)
+{
+	double		dm, dn;
+	int			tm, tn;
+	adivtab_t	*ptemp;
+
+// TODO: implement x86 version
+
+	errorterm = -1;
+
+	tm = endvertu - startvertu;
+	tn = endvertv - startvertv;
+
+	if (((tm <= 16) && (tm >= -15)) &&
+		((tn <= 16) && (tn >= -15)))
+	{
+		ptemp = &adivtab[((tm+15) << 5) + (tn+15)];
+		ubasestep = ptemp->quotient;
+		erroradjustup = ptemp->remainder;
+		erroradjustdown = tn;
+	}
+	else
+	{
+		dm = (double)tm;
+		dn = (double)tn;
+
+		FloorDivMod (dm, dn, &ubasestep, &erroradjustup);
+
+		erroradjustdown = dn;
+	}
+}
+
+
+#if	!id386
+
+/*
+================
+D_PolysetCalcGradients
+================
+*/
+void D_PolysetCalcGradients (int skinwidth)
+{
+	float	xstepdenominv, ystepdenominv, t0, t1;
+	float	p01_minus_p21, p11_minus_p21, p00_minus_p20, p10_minus_p20;
+
+	p00_minus_p20 = r_p0[0] - r_p2[0];
+	p01_minus_p21 = r_p0[1] - r_p2[1];
+	p10_minus_p20 = r_p1[0] - r_p2[0];
+	p11_minus_p21 = r_p1[1] - r_p2[1];
+
+	xstepdenominv = 1.0 / (float)d_xdenom;
+
+	ystepdenominv = -xstepdenominv;
+
+// ceil () for light so positive steps are exaggerated, negative steps
+// diminished,  pushing us away from underflow toward overflow. Underflow is
+// very visible, overflow is very unlikely, because of ambient lighting
+	t0 = r_p0[4] - r_p2[4];
+	t1 = r_p1[4] - r_p2[4];
+	r_lstepx = (int)
+			ceil((t1 * p01_minus_p21 - t0 * p11_minus_p21) * xstepdenominv);
+	r_lstepy = (int)
+			ceil((t1 * p00_minus_p20 - t0 * p10_minus_p20) * ystepdenominv);
+
+	t0 = r_p0[2] - r_p2[2];
+	t1 = r_p1[2] - r_p2[2];
+	r_sstepx = (int)((t1 * p01_minus_p21 - t0 * p11_minus_p21) *
+			xstepdenominv);
+	r_sstepy = (int)((t1 * p00_minus_p20 - t0* p10_minus_p20) *
+			ystepdenominv);
+
+	t0 = r_p0[3] - r_p2[3];
+	t1 = r_p1[3] - r_p2[3];
+	r_tstepx = (int)((t1 * p01_minus_p21 - t0 * p11_minus_p21) *
+			xstepdenominv);
+	r_tstepy = (int)((t1 * p00_minus_p20 - t0 * p10_minus_p20) *
+			ystepdenominv);
+
+	t0 = r_p0[5] - r_p2[5];
+	t1 = r_p1[5] - r_p2[5];
+	r_zistepx = (int)((t1 * p01_minus_p21 - t0 * p11_minus_p21) *
+			xstepdenominv);
+	r_zistepy = (int)((t1 * p00_minus_p20 - t0 * p10_minus_p20) *
+			ystepdenominv);
+
+#if	id386
+	a_sstepxfrac = r_sstepx << 16;
+	a_tstepxfrac = r_tstepx << 16;
+#else
+	a_sstepxfrac = r_sstepx & 0xFFFF;
+	a_tstepxfrac = r_tstepx & 0xFFFF;
+#endif
+
+	a_ststepxwhole = skinwidth * (r_tstepx >> 16) + (r_sstepx >> 16);
+}
+
+#endif	// !id386
+
+
+byte gelmap[256];
+void InitGel (byte *palette)
+{
+	int		i;
+	int		r;
+
+	for (i=0 ; i<256 ; i++)
+	{
+//		r = (palette[i*3]>>4);
+		r = (palette[i*3] + palette[i*3+1] + palette[i*3+2])/(16*3);
+		gelmap[i] = /* 64 */ 0 + r;
+	}
+}
+
+
+#if	!id386
+
+/*
+================
+D_PolysetDrawSpans8
+================
+*/
+void D_PolysetDrawSpans8 (spanpackage_t *pspanpackage)
+{
+	int		lcount;
+	byte	*lpdest;
+	byte	*lptex;
+	int		lsfrac, ltfrac;
+	int		llight;
+	int		lzi;
+	short	*lpz;
+
+	do
+	{
+		lcount = d_aspancount - pspanpackage->count;
+
+		errorterm += erroradjustup;
+		if (errorterm >= 0)
+		{
+			d_aspancount += d_countextrastep;
+			errorterm -= erroradjustdown;
+		}
+		else
+		{
+			d_aspancount += ubasestep;
+		}
+
+		if (lcount)
+		{
+			lpdest = pspanpackage->pdest;
+			lptex = pspanpackage->ptex;
+			lpz = pspanpackage->pz;
+			lsfrac = pspanpackage->sfrac;
+			ltfrac = pspanpackage->tfrac;
+			llight = pspanpackage->light;
+			lzi = pspanpackage->zi;
+
+			do
+			{
+				if ((lzi >> 16) >= *lpz)
+				{
+					*lpdest = ((byte *)acolormap)[*lptex + (llight & 0xFF00)];
+// gel mapping					*lpdest = gelmap[*lpdest];
+					*lpz = lzi >> 16;
+				}
+				lpdest++;
+				lzi += r_zistepx;
+				lpz++;
+				llight += r_lstepx;
+				lptex += a_ststepxwhole;
+				lsfrac += a_sstepxfrac;
+				lptex += lsfrac >> 16;
+				lsfrac &= 0xFFFF;
+				ltfrac += a_tstepxfrac;
+				if (ltfrac & 0x10000)
+				{
+					lptex += r_affinetridesc.skinwidth;
+					ltfrac &= 0xFFFF;
+				}
+			} while (--lcount);
+		}
+
+		pspanpackage++;
+	} while (pspanpackage->count != -999999);
+}
+#endif	// !id386
+
+
+/*
+================
+D_PolysetFillSpans8
+================
+*/
+void D_PolysetFillSpans8 (spanpackage_t *pspanpackage)
+{
+	int				color;
+
+// FIXME: do z buffering
+
+	color = d_aflatcolor++;
+
+	while (1)
+	{
+		int		lcount;
+		byte	*lpdest;
+
+		lcount = pspanpackage->count;
+
+		if (lcount == -1)
+			return;
+
+		if (lcount)
+		{
+			lpdest = pspanpackage->pdest;
+
+			do
+			{
+				*lpdest++ = color;
+			} while (--lcount);
+		}
+
+		pspanpackage++;
+	}
+}
+
+/*
+================
+D_RasterizeAliasPolySmooth
+================
+*/
+void D_RasterizeAliasPolySmooth (void)
+{
+	int				initialleftheight, initialrightheight;
+	int				*plefttop, *prighttop, *pleftbottom, *prightbottom;
+	int				working_lstepx, originalcount;
+
+	plefttop = pedgetable->pleftedgevert0;
+	prighttop = pedgetable->prightedgevert0;
+
+	pleftbottom = pedgetable->pleftedgevert1;
+	prightbottom = pedgetable->prightedgevert1;
+
+	initialleftheight = pleftbottom[1] - plefttop[1];
+	initialrightheight = prightbottom[1] - prighttop[1];
+
+//
+// set the s, t, and light gradients, which are consistent across the triangle
+// because being a triangle, things are affine
+//
+	D_PolysetCalcGradients (r_affinetridesc.skinwidth);
+
+//
+// rasterize the polygon
+//
+
+//
+// scan out the top (and possibly only) part of the left edge
+//
+	D_PolysetSetUpForLineScan(plefttop[0], plefttop[1],
+						  pleftbottom[0], pleftbottom[1]);
+
+	d_pedgespanpackage = a_spans;
+
+	ystart = plefttop[1];
+	d_aspancount = plefttop[0] - prighttop[0];
+
+	d_ptex = (byte *)r_affinetridesc.pskin + (plefttop[2] >> 16) +
+			(plefttop[3] >> 16) * r_affinetridesc.skinwidth;
+#if	id386
+	d_sfrac = (plefttop[2] & 0xFFFF) << 16;
+	d_tfrac = (plefttop[3] & 0xFFFF) << 16;
+	d_pzbasestep = (d_zwidth + ubasestep) << 1;
+	d_pzextrastep = d_pzbasestep + 2;
+#else
+	d_sfrac = plefttop[2] & 0xFFFF;
+	d_tfrac = plefttop[3] & 0xFFFF;
+	d_pzbasestep = d_zwidth + ubasestep;
+	d_pzextrastep = d_pzbasestep + 1;
+#endif
+	d_light = plefttop[4];
+	d_zi = plefttop[5];
+
+	d_pdestbasestep = screenwidth + ubasestep;
+	d_pdestextrastep = d_pdestbasestep + 1;
+	d_pdest = (byte *)d_viewbuffer +
+			ystart * screenwidth + plefttop[0];
+	d_pz = d_pzbuffer + ystart * d_zwidth + plefttop[0];
+
+// TODO: can reuse partial expressions here
+
+// for negative steps in x along left edge, bias toward overflow rather than
+// underflow (sort of turning the floor () we did in the gradient calcs into
+// ceil (), but plus a little bit)
+	if (ubasestep < 0)
+		working_lstepx = r_lstepx - 1;
+	else
+		working_lstepx = r_lstepx;
+
+	d_countextrastep = ubasestep + 1;
+	d_ptexbasestep = ((r_sstepy + r_sstepx * ubasestep) >> 16) +
+			((r_tstepy + r_tstepx * ubasestep) >> 16) *
+			r_affinetridesc.skinwidth;
+#if	id386
+	d_sfracbasestep = (r_sstepy + r_sstepx * ubasestep) << 16;
+	d_tfracbasestep = (r_tstepy + r_tstepx * ubasestep) << 16;
+#else
+	d_sfracbasestep = (r_sstepy + r_sstepx * ubasestep) & 0xFFFF;
+	d_tfracbasestep = (r_tstepy + r_tstepx * ubasestep) & 0xFFFF;
+#endif
+	d_lightbasestep = r_lstepy + working_lstepx * ubasestep;
+	d_zibasestep = r_zistepy + r_zistepx * ubasestep;
+
+	d_ptexextrastep = ((r_sstepy + r_sstepx * d_countextrastep) >> 16) +
+			((r_tstepy + r_tstepx * d_countextrastep) >> 16) *
+			r_affinetridesc.skinwidth;
+#if	id386
+	d_sfracextrastep = (r_sstepy + r_sstepx*d_countextrastep) << 16;
+	d_tfracextrastep = (r_tstepy + r_tstepx*d_countextrastep) << 16;
+#else
+	d_sfracextrastep = (r_sstepy + r_sstepx*d_countextrastep) & 0xFFFF;
+	d_tfracextrastep = (r_tstepy + r_tstepx*d_countextrastep) & 0xFFFF;
+#endif
+	d_lightextrastep = d_lightbasestep + working_lstepx;
+	d_ziextrastep = d_zibasestep + r_zistepx;
+
+	D_PolysetScanLeftEdge (initialleftheight);
+
+//
+// scan out the bottom part of the left edge, if it exists
+//
+	if (pedgetable->numleftedges == 2)
+	{
+		int		height;
+
+		plefttop = pleftbottom;
+		pleftbottom = pedgetable->pleftedgevert2;
+
+		D_PolysetSetUpForLineScan(plefttop[0], plefttop[1],
+							  pleftbottom[0], pleftbottom[1]);
+
+		height = pleftbottom[1] - plefttop[1];
+
+// TODO: make this a function; modularize this function in general
+
+		ystart = plefttop[1];
+		d_aspancount = plefttop[0] - prighttop[0];
+		d_ptex = (byte *)r_affinetridesc.pskin + (plefttop[2] >> 16) +
+				(plefttop[3] >> 16) * r_affinetridesc.skinwidth;
+		d_sfrac = 0;
+		d_tfrac = 0;
+		d_light = plefttop[4];
+		d_zi = plefttop[5];
+
+		d_pdestbasestep = screenwidth + ubasestep;
+		d_pdestextrastep = d_pdestbasestep + 1;
+		d_pdest = (byte *)d_viewbuffer + ystart * screenwidth + plefttop[0];
+#if	id386
+		d_pzbasestep = (d_zwidth + ubasestep) << 1;
+		d_pzextrastep = d_pzbasestep + 2;
+#else
+		d_pzbasestep = d_zwidth + ubasestep;
+		d_pzextrastep = d_pzbasestep + 1;
+#endif
+		d_pz = d_pzbuffer + ystart * d_zwidth + plefttop[0];
+
+		if (ubasestep < 0)
+			working_lstepx = r_lstepx - 1;
+		else
+			working_lstepx = r_lstepx;
+
+		d_countextrastep = ubasestep + 1;
+		d_ptexbasestep = ((r_sstepy + r_sstepx * ubasestep) >> 16) +
+				((r_tstepy + r_tstepx * ubasestep) >> 16) *
+				r_affinetridesc.skinwidth;
+#if	id386
+		d_sfracbasestep = (r_sstepy + r_sstepx * ubasestep) << 16;
+		d_tfracbasestep = (r_tstepy + r_tstepx * ubasestep) << 16;
+#else
+		d_sfracbasestep = (r_sstepy + r_sstepx * ubasestep) & 0xFFFF;
+		d_tfracbasestep = (r_tstepy + r_tstepx * ubasestep) & 0xFFFF;
+#endif
+		d_lightbasestep = r_lstepy + working_lstepx * ubasestep;
+		d_zibasestep = r_zistepy + r_zistepx * ubasestep;
+
+		d_ptexextrastep = ((r_sstepy + r_sstepx * d_countextrastep) >> 16) +
+				((r_tstepy + r_tstepx * d_countextrastep) >> 16) *
+				r_affinetridesc.skinwidth;
+#if	id386
+		d_sfracextrastep = ((r_sstepy+r_sstepx*d_countextrastep) & 0xFFFF)<<16;
+		d_tfracextrastep = ((r_tstepy+r_tstepx*d_countextrastep) & 0xFFFF)<<16;
+#else
+		d_sfracextrastep = (r_sstepy+r_sstepx*d_countextrastep) & 0xFFFF;
+		d_tfracextrastep = (r_tstepy+r_tstepx*d_countextrastep) & 0xFFFF;
+#endif
+		d_lightextrastep = d_lightbasestep + working_lstepx;
+		d_ziextrastep = d_zibasestep + r_zistepx;
+
+		D_PolysetScanLeftEdge (height);
+	}
+
+// scan out the top (and possibly only) part of the right edge, updating the
+// count field
+	d_pedgespanpackage = a_spans;
+
+	D_PolysetSetUpForLineScan(prighttop[0], prighttop[1],
+						  prightbottom[0], prightbottom[1]);
+	d_aspancount = 0;
+	d_countextrastep = ubasestep + 1;
+	originalcount = a_spans[initialrightheight].count;
+	a_spans[initialrightheight].count = -999999; // mark end of the spanpackages
+	D_PolysetDrawSpans8 (a_spans);
+
+// scan out the bottom part of the right edge, if it exists
+	if (pedgetable->numrightedges == 2)
+	{
+		int				height;
+		spanpackage_t	*pstart;
+
+		pstart = a_spans + initialrightheight;
+		pstart->count = originalcount;
+
+		d_aspancount = prightbottom[0] - prighttop[0];
+
+		prighttop = prightbottom;
+		prightbottom = pedgetable->prightedgevert2;
+
+		height = prightbottom[1] - prighttop[1];
+
+		D_PolysetSetUpForLineScan(prighttop[0], prighttop[1],
+							  prightbottom[0], prightbottom[1]);
+
+		d_countextrastep = ubasestep + 1;
+		a_spans[initialrightheight + height].count = -999999;
+											// mark end of the spanpackages
+		D_PolysetDrawSpans8 (pstart);
+	}
+}
+
+
+/*
+================
+D_PolysetSetEdgeTable
+================
+*/
+void D_PolysetSetEdgeTable (void)
+{
+	int			edgetableindex;
+
+	edgetableindex = 0;	// assume the vertices are already in
+						//  top to bottom order
+
+//
+// determine which edges are right & left, and the order in which
+// to rasterize them
+//
+	if (r_p0[1] >= r_p1[1])
+	{
+		if (r_p0[1] == r_p1[1])
+		{
+			if (r_p0[1] < r_p2[1])
+				pedgetable = &edgetables[2];
+			else
+				pedgetable = &edgetables[5];
+
+			return;
+		}
+		else
+		{
+			edgetableindex = 1;
+		}
+	}
+
+	if (r_p0[1] == r_p2[1])
+	{
+		if (edgetableindex)
+			pedgetable = &edgetables[8];
+		else
+			pedgetable = &edgetables[9];
+
+		return;
+	}
+	else if (r_p1[1] == r_p2[1])
+	{
+		if (edgetableindex)
+			pedgetable = &edgetables[10];
+		else
+			pedgetable = &edgetables[11];
+
+		return;
+	}
+
+	if (r_p0[1] > r_p2[1])
+		edgetableindex += 2;
+
+	if (r_p1[1] > r_p2[1])
+		edgetableindex += 4;
+
+	pedgetable = &edgetables[edgetableindex];
+}
+
+
+#if 0
+
+void D_PolysetRecursiveDrawLine (int *lp1, int *lp2)
+{
+	int		d;
+	int		new[6];
+	int 	ofs;
+	
+	d = lp2[0] - lp1[0];
+	if (d < -1 || d > 1)
+		goto split;
+	d = lp2[1] - lp1[1];
+	if (d < -1 || d > 1)
+		goto split;
+
+	return;	// line is completed
+
+split:
+// split this edge
+	new[0] = (lp1[0] + lp2[0]) >> 1;
+	new[1] = (lp1[1] + lp2[1]) >> 1;
+	new[5] = (lp1[5] + lp2[5]) >> 1;
+	new[2] = (lp1[2] + lp2[2]) >> 1;
+	new[3] = (lp1[3] + lp2[3]) >> 1;
+	new[4] = (lp1[4] + lp2[4]) >> 1;
+
+// draw the point
+	ofs = d_scantable[new[1]] + new[0];
+	if (new[5] > d_pzbuffer[ofs])
+	{
+		int		pix;
+		
+		d_pzbuffer[ofs] = new[5];
+		pix = skintable[new[3]>>16][new[2]>>16];
+//		pix = ((byte *)acolormap)[pix + (new[4] & 0xFF00)];
+		d_viewbuffer[ofs] = pix;
+	}
+
+// recursively continue
+	D_PolysetRecursiveDrawLine (lp1, new);
+	D_PolysetRecursiveDrawLine (new, lp2);
+}
+
+void D_PolysetRecursiveTriangle2 (int *lp1, int *lp2, int *lp3)
+{
+	int		d;
+	int		new[4];
+	
+	d = lp2[0] - lp1[0];
+	if (d < -1 || d > 1)
+		goto split;
+	d = lp2[1] - lp1[1];
+	if (d < -1 || d > 1)
+		goto split;
+	return;
+
+split:
+// split this edge
+	new[0] = (lp1[0] + lp2[0]) >> 1;
+	new[1] = (lp1[1] + lp2[1]) >> 1;
+	new[5] = (lp1[5] + lp2[5]) >> 1;
+	new[2] = (lp1[2] + lp2[2]) >> 1;
+	new[3] = (lp1[3] + lp2[3]) >> 1;
+	new[4] = (lp1[4] + lp2[4]) >> 1;
+
+	D_PolysetRecursiveDrawLine (new, lp3);
+
+// recursively continue
+	D_PolysetRecursiveTriangle (lp1, new, lp3);
+	D_PolysetRecursiveTriangle (new, lp2, lp3);
+}
+
+#endif
+
--- /dev/null
+++ b/QW/client/d_scan.c
@@ -1,0 +1,446 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// d_scan.c
+//
+// Portable C scan-level rasterization code, all pixel depths.
+
+#include "quakedef.h"
+#include "r_local.h"
+#include "d_local.h"
+
+unsigned char	*r_turb_pbase, *r_turb_pdest;
+fixed16_t		r_turb_s, r_turb_t, r_turb_sstep, r_turb_tstep;
+int				*r_turb_turb;
+int				r_turb_spancount;
+
+void D_DrawTurbulent8Span (void);
+
+
+/*
+=============
+D_WarpScreen
+
+// this performs a slight compression of the screen at the same time as
+// the sine warp, to keep the edges from wrapping
+=============
+*/
+void D_WarpScreen (void)
+{
+	int		w, h;
+	int		u,v;
+	byte	*dest;
+	int		*turb;
+	int		*col;
+	byte	**row;
+	byte	*rowptr[1024];
+	int		column[1280];
+	float	wratio, hratio;
+
+	w = r_refdef.vrect.width;
+	h = r_refdef.vrect.height;
+
+	wratio = w / (float)scr_vrect.width;
+	hratio = h / (float)scr_vrect.height;
+
+	for (v=0 ; v<scr_vrect.height+AMP2*2 ; v++)
+	{
+		rowptr[v] = d_viewbuffer + (r_refdef.vrect.y * screenwidth) +
+				 (screenwidth * (int)((float)v * hratio * h / (h + AMP2 * 2)));
+	}
+
+	for (u=0 ; u<scr_vrect.width+AMP2*2 ; u++)
+	{
+		column[u] = r_refdef.vrect.x +
+				(int)((float)u * wratio * w / (w + AMP2 * 2));
+	}
+
+	turb = intsintable + ((int)(cl.time*SPEED)&(CYCLE-1));
+	dest = vid.buffer + scr_vrect.y * vid.rowbytes + scr_vrect.x;
+
+	for (v=0 ; v<scr_vrect.height ; v++, dest += vid.rowbytes)
+	{
+		col = &column[turb[v]];
+		row = &rowptr[v];
+		for (u=0 ; u<scr_vrect.width ; u+=4)
+		{
+			dest[u+0] = row[turb[u+0]][col[u+0]];
+			dest[u+1] = row[turb[u+1]][col[u+1]];
+			dest[u+2] = row[turb[u+2]][col[u+2]];
+			dest[u+3] = row[turb[u+3]][col[u+3]];
+		}
+	}
+}
+
+
+#if	!id386
+
+/*
+=============
+D_DrawTurbulent8Span
+=============
+*/
+void D_DrawTurbulent8Span (void)
+{
+	int		sturb, tturb;
+
+	do
+	{
+		sturb = ((r_turb_s + r_turb_turb[(r_turb_t>>16)&(CYCLE-1)])>>16)&63;
+		tturb = ((r_turb_t + r_turb_turb[(r_turb_s>>16)&(CYCLE-1)])>>16)&63;
+		*r_turb_pdest++ = *(r_turb_pbase + (tturb<<6) + sturb);
+		r_turb_s += r_turb_sstep;
+		r_turb_t += r_turb_tstep;
+	} while (--r_turb_spancount > 0);
+}
+
+#endif	// !id386
+
+/*
+=============
+Turbulent8
+=============
+*/
+void Turbulent8 (espan_t *pspan)
+{
+	int				count;
+	fixed16_t		snext, tnext;
+	float			sdivz, tdivz, zi, z, du, dv, spancountminus1;
+	float			sdivz16stepu, tdivz16stepu, zi16stepu;
+	
+	r_turb_turb = sintable + ((int)(cl.time*SPEED)&(CYCLE-1));
+
+	r_turb_sstep = 0;	// keep compiler happy
+	r_turb_tstep = 0;	// ditto
+
+	r_turb_pbase = (unsigned char *)cacheblock;
+
+	sdivz16stepu = d_sdivzstepu * 16;
+	tdivz16stepu = d_tdivzstepu * 16;
+	zi16stepu = d_zistepu * 16;
+
+	do
+	{
+		r_turb_pdest = (unsigned char *)((byte *)d_viewbuffer +
+				(screenwidth * pspan->v) + pspan->u);
+
+		count = pspan->count;
+
+	// calculate the initial s/z, t/z, 1/z, s, and t and clamp
+		du = (float)pspan->u;
+		dv = (float)pspan->v;
+
+		sdivz = d_sdivzorigin + dv*d_sdivzstepv + du*d_sdivzstepu;
+		tdivz = d_tdivzorigin + dv*d_tdivzstepv + du*d_tdivzstepu;
+		zi = d_ziorigin + dv*d_zistepv + du*d_zistepu;
+		z = (float)0x10000 / zi;	// prescale to 16.16 fixed-point
+
+		r_turb_s = (int)(sdivz * z) + sadjust;
+		if (r_turb_s > bbextents)
+			r_turb_s = bbextents;
+		else if (r_turb_s < 0)
+			r_turb_s = 0;
+
+		r_turb_t = (int)(tdivz * z) + tadjust;
+		if (r_turb_t > bbextentt)
+			r_turb_t = bbextentt;
+		else if (r_turb_t < 0)
+			r_turb_t = 0;
+
+		do
+		{
+		// calculate s and t at the far end of the span
+			if (count >= 16)
+				r_turb_spancount = 16;
+			else
+				r_turb_spancount = count;
+
+			count -= r_turb_spancount;
+
+			if (count)
+			{
+			// calculate s/z, t/z, zi->fixed s and t at far end of span,
+			// calculate s and t steps across span by shifting
+				sdivz += sdivz16stepu;
+				tdivz += tdivz16stepu;
+				zi += zi16stepu;
+				z = (float)0x10000 / zi;	// prescale to 16.16 fixed-point
+
+				snext = (int)(sdivz * z) + sadjust;
+				if (snext > bbextents)
+					snext = bbextents;
+				else if (snext < 16)
+					snext = 16;	// prevent round-off error on <0 steps from
+								//  from causing overstepping & running off the
+								//  edge of the texture
+
+				tnext = (int)(tdivz * z) + tadjust;
+				if (tnext > bbextentt)
+					tnext = bbextentt;
+				else if (tnext < 16)
+					tnext = 16;	// guard against round-off error on <0 steps
+
+				r_turb_sstep = (snext - r_turb_s) >> 4;
+				r_turb_tstep = (tnext - r_turb_t) >> 4;
+			}
+			else
+			{
+			// calculate s/z, t/z, zi->fixed s and t at last pixel in span (so
+			// can't step off polygon), clamp, calculate s and t steps across
+			// span by division, biasing steps low so we don't run off the
+			// texture
+				spancountminus1 = (float)(r_turb_spancount - 1);
+				sdivz += d_sdivzstepu * spancountminus1;
+				tdivz += d_tdivzstepu * spancountminus1;
+				zi += d_zistepu * spancountminus1;
+				z = (float)0x10000 / zi;	// prescale to 16.16 fixed-point
+				snext = (int)(sdivz * z) + sadjust;
+				if (snext > bbextents)
+					snext = bbextents;
+				else if (snext < 16)
+					snext = 16;	// prevent round-off error on <0 steps from
+								//  from causing overstepping & running off the
+								//  edge of the texture
+
+				tnext = (int)(tdivz * z) + tadjust;
+				if (tnext > bbextentt)
+					tnext = bbextentt;
+				else if (tnext < 16)
+					tnext = 16;	// guard against round-off error on <0 steps
+
+				if (r_turb_spancount > 1)
+				{
+					r_turb_sstep = (snext - r_turb_s) / (r_turb_spancount - 1);
+					r_turb_tstep = (tnext - r_turb_t) / (r_turb_spancount - 1);
+				}
+			}
+
+			r_turb_s = r_turb_s & ((CYCLE<<16)-1);
+			r_turb_t = r_turb_t & ((CYCLE<<16)-1);
+
+			D_DrawTurbulent8Span ();
+
+			r_turb_s = snext;
+			r_turb_t = tnext;
+
+		} while (count > 0);
+
+	} while ((pspan = pspan->pnext) != NULL);
+}
+
+
+#if	!id386
+
+/*
+=============
+D_DrawSpans8
+=============
+*/
+void D_DrawSpans8 (espan_t *pspan)
+{
+	int				count, spancount;
+	unsigned char	*pbase, *pdest;
+	fixed16_t		s, t, snext, tnext, sstep, tstep;
+	float			sdivz, tdivz, zi, z, du, dv, spancountminus1;
+	float			sdivz8stepu, tdivz8stepu, zi8stepu;
+
+	sstep = 0;	// keep compiler happy
+	tstep = 0;	// ditto
+
+	pbase = (unsigned char *)cacheblock;
+
+	sdivz8stepu = d_sdivzstepu * 8;
+	tdivz8stepu = d_tdivzstepu * 8;
+	zi8stepu = d_zistepu * 8;
+
+	do
+	{
+		pdest = (unsigned char *)((byte *)d_viewbuffer +
+				(screenwidth * pspan->v) + pspan->u);
+
+		count = pspan->count;
+
+	// calculate the initial s/z, t/z, 1/z, s, and t and clamp
+		du = (float)pspan->u;
+		dv = (float)pspan->v;
+
+		sdivz = d_sdivzorigin + dv*d_sdivzstepv + du*d_sdivzstepu;
+		tdivz = d_tdivzorigin + dv*d_tdivzstepv + du*d_tdivzstepu;
+		zi = d_ziorigin + dv*d_zistepv + du*d_zistepu;
+		z = (float)0x10000 / zi;	// prescale to 16.16 fixed-point
+
+		s = (int)(sdivz * z) + sadjust;
+		if (s > bbextents)
+			s = bbextents;
+		else if (s < 0)
+			s = 0;
+
+		t = (int)(tdivz * z) + tadjust;
+		if (t > bbextentt)
+			t = bbextentt;
+		else if (t < 0)
+			t = 0;
+
+		do
+		{
+		// calculate s and t at the far end of the span
+			if (count >= 8)
+				spancount = 8;
+			else
+				spancount = count;
+
+			count -= spancount;
+
+			if (count)
+			{
+			// calculate s/z, t/z, zi->fixed s and t at far end of span,
+			// calculate s and t steps across span by shifting
+				sdivz += sdivz8stepu;
+				tdivz += tdivz8stepu;
+				zi += zi8stepu;
+				z = (float)0x10000 / zi;	// prescale to 16.16 fixed-point
+
+				snext = (int)(sdivz * z) + sadjust;
+				if (snext > bbextents)
+					snext = bbextents;
+				else if (snext < 8)
+					snext = 8;	// prevent round-off error on <0 steps from
+								//  from causing overstepping & running off the
+								//  edge of the texture
+
+				tnext = (int)(tdivz * z) + tadjust;
+				if (tnext > bbextentt)
+					tnext = bbextentt;
+				else if (tnext < 8)
+					tnext = 8;	// guard against round-off error on <0 steps
+
+				sstep = (snext - s) >> 3;
+				tstep = (tnext - t) >> 3;
+			}
+			else
+			{
+			// calculate s/z, t/z, zi->fixed s and t at last pixel in span (so
+			// can't step off polygon), clamp, calculate s and t steps across
+			// span by division, biasing steps low so we don't run off the
+			// texture
+				spancountminus1 = (float)(spancount - 1);
+				sdivz += d_sdivzstepu * spancountminus1;
+				tdivz += d_tdivzstepu * spancountminus1;
+				zi += d_zistepu * spancountminus1;
+				z = (float)0x10000 / zi;	// prescale to 16.16 fixed-point
+				snext = (int)(sdivz * z) + sadjust;
+				if (snext > bbextents)
+					snext = bbextents;
+				else if (snext < 8)
+					snext = 8;	// prevent round-off error on <0 steps from
+								//  from causing overstepping & running off the
+								//  edge of the texture
+
+				tnext = (int)(tdivz * z) + tadjust;
+				if (tnext > bbextentt)
+					tnext = bbextentt;
+				else if (tnext < 8)
+					tnext = 8;	// guard against round-off error on <0 steps
+
+				if (spancount > 1)
+				{
+					sstep = (snext - s) / (spancount - 1);
+					tstep = (tnext - t) / (spancount - 1);
+				}
+			}
+
+			do
+			{
+				*pdest++ = *(pbase + (s >> 16) + (t >> 16) * cachewidth);
+				s += sstep;
+				t += tstep;
+			} while (--spancount > 0);
+
+			s = snext;
+			t = tnext;
+
+		} while (count > 0);
+
+	} while ((pspan = pspan->pnext) != NULL);
+}
+
+#endif
+
+
+#if	!id386
+
+/*
+=============
+D_DrawZSpans
+=============
+*/
+void D_DrawZSpans (espan_t *pspan)
+{
+	int				count, doublecount, izistep;
+	int				izi;
+	short			*pdest;
+	unsigned		ltemp;
+	double			zi;
+	float			du, dv;
+
+// FIXME: check for clamping/range problems
+// we count on FP exceptions being turned off to avoid range problems
+	izistep = (int)(d_zistepu * 0x8000 * 0x10000);
+
+	do
+	{
+		pdest = d_pzbuffer + (d_zwidth * pspan->v) + pspan->u;
+
+		count = pspan->count;
+
+	// calculate the initial 1/z
+		du = (float)pspan->u;
+		dv = (float)pspan->v;
+
+		zi = d_ziorigin + dv*d_zistepv + du*d_zistepu;
+	// we count on FP exceptions being turned off to avoid range problems
+		izi = (int)(zi * 0x8000 * 0x10000);
+
+		if ((long)pdest & 0x02)
+		{
+			*pdest++ = (short)(izi >> 16);
+			izi += izistep;
+			count--;
+		}
+
+		if ((doublecount = count >> 1) > 0)
+		{
+			do
+			{
+				ltemp = izi >> 16;
+				izi += izistep;
+				ltemp |= izi & 0xFFFF0000;
+				izi += izistep;
+				*(int *)pdest = ltemp;
+				pdest += 2;
+			} while (--doublecount > 0);
+		}
+
+		if (count & 1)
+			*pdest = (short)(izi >> 16);
+
+	} while ((pspan = pspan->pnext) != NULL);
+}
+
+#endif
--- /dev/null
+++ b/QW/client/d_scana.asm
@@ -1,0 +1,281 @@
+ .386P
+ .model FLAT
+ externdef _d_zistepu:dword
+ externdef _d_pzbuffer:dword
+ externdef _d_zistepv:dword
+ externdef _d_zrowbytes:dword
+ externdef _d_ziorigin:dword
+ externdef _r_turb_s:dword
+ externdef _r_turb_t:dword
+ externdef _r_turb_pdest:dword
+ externdef _r_turb_spancount:dword
+ externdef _r_turb_turb:dword
+ externdef _r_turb_pbase:dword
+ externdef _r_turb_sstep:dword
+ externdef _r_turb_tstep:dword
+ externdef _r_bmodelactive:dword
+ externdef _d_sdivzstepu:dword
+ externdef _d_tdivzstepu:dword
+ externdef _d_sdivzstepv:dword
+ externdef _d_tdivzstepv:dword
+ externdef _d_sdivzorigin:dword
+ externdef _d_tdivzorigin:dword
+ externdef _sadjust:dword
+ externdef _tadjust:dword
+ externdef _bbextents:dword
+ externdef _bbextentt:dword
+ externdef _cacheblock:dword
+ externdef _d_viewbuffer:dword
+ externdef _cachewidth:dword
+ externdef _d_pzbuffer:dword
+ externdef _d_zrowbytes:dword
+ externdef _d_zwidth:dword
+ externdef _d_scantable:dword
+ externdef _r_lightptr:dword
+ externdef _r_numvblocks:dword
+ externdef _prowdestbase:dword
+ externdef _pbasesource:dword
+ externdef _r_lightwidth:dword
+ externdef _lightright:dword
+ externdef _lightrightstep:dword
+ externdef _lightdeltastep:dword
+ externdef _lightdelta:dword
+ externdef _lightright:dword
+ externdef _lightdelta:dword
+ externdef _sourcetstep:dword
+ externdef _surfrowbytes:dword
+ externdef _lightrightstep:dword
+ externdef _lightdeltastep:dword
+ externdef _r_sourcemax:dword
+ externdef _r_stepback:dword
+ externdef _colormap:dword
+ externdef _blocksize:dword
+ externdef _sourcesstep:dword
+ externdef _lightleft:dword
+ externdef _blockdivshift:dword
+ externdef _blockdivmask:dword
+ externdef _lightleftstep:dword
+ externdef _r_origin:dword
+ externdef _r_ppn:dword
+ externdef _r_pup:dword
+ externdef _r_pright:dword
+ externdef _ycenter:dword
+ externdef _xcenter:dword
+ externdef _d_vrectbottom_particle:dword
+ externdef _d_vrectright_particle:dword
+ externdef _d_vrecty:dword
+ externdef _d_vrectx:dword
+ externdef _d_pix_shift:dword
+ externdef _d_pix_min:dword
+ externdef _d_pix_max:dword
+ externdef _d_y_aspect_shift:dword
+ externdef _screenwidth:dword
+ externdef _vright:dword
+ externdef _vup:dword
+ externdef _vpn:dword
+ externdef _BOPS_Error:dword
+ externdef _snd_scaletable:dword
+ externdef _paintbuffer:dword
+ externdef _snd_linear_count:dword
+ externdef _snd_p:dword
+ externdef _snd_vol:dword
+ externdef _snd_out:dword
+ externdef _r_leftclipped:dword
+ externdef _r_leftenter:dword
+ externdef _r_rightclipped:dword
+ externdef _r_rightenter:dword
+ externdef _modelorg:dword
+ externdef _xscale:dword
+ externdef _r_refdef:dword
+ externdef _yscale:dword
+ externdef _r_leftexit:dword
+ externdef _r_rightexit:dword
+ externdef _r_lastvertvalid:dword
+ externdef _cacheoffset:dword
+ externdef _newedges:dword
+ externdef _removeedges:dword
+ externdef _r_pedge:dword
+ externdef _r_framecount:dword
+ externdef _r_u1:dword
+ externdef _r_emitted:dword
+ externdef _edge_p:dword
+ externdef _surface_p:dword
+ externdef _surfaces:dword
+ externdef _r_lzi1:dword
+ externdef _r_v1:dword
+ externdef _r_ceilv1:dword
+ externdef _r_nearzi:dword
+ externdef _r_nearzionly:dword
+ externdef _edge_aftertail:dword
+ externdef _edge_tail:dword
+ externdef _current_iv:dword
+ externdef _edge_head_u_shift20:dword
+ externdef _span_p:dword
+ externdef _edge_head:dword
+ externdef _fv:dword
+ externdef _edge_tail_u_shift20:dword
+ externdef _r_apverts:dword
+ externdef _r_anumverts:dword
+ externdef _aliastransform:dword
+ externdef _r_avertexnormals:dword
+ externdef _r_plightvec:dword
+ externdef _r_ambientlight:dword
+ externdef _r_shadelight:dword
+ externdef _aliasxcenter:dword
+ externdef _aliasycenter:dword
+ externdef _a_sstepxfrac:dword
+ externdef _r_affinetridesc:dword
+ externdef _acolormap:dword
+ externdef _d_pcolormap:dword
+ externdef _r_affinetridesc:dword
+ externdef _d_sfrac:dword
+ externdef _d_ptex:dword
+ externdef _d_pedgespanpackage:dword
+ externdef _d_tfrac:dword
+ externdef _d_light:dword
+ externdef _d_zi:dword
+ externdef _d_pdest:dword
+ externdef _d_pz:dword
+ externdef _d_aspancount:dword
+ externdef _erroradjustup:dword
+ externdef _errorterm:dword
+ externdef _d_xdenom:dword
+ externdef _r_p0:dword
+ externdef _r_p1:dword
+ externdef _r_p2:dword
+ externdef _a_tstepxfrac:dword
+ externdef _r_sstepx:dword
+ externdef _r_tstepx:dword
+ externdef _a_ststepxwhole:dword
+ externdef _zspantable:dword
+ externdef _skintable:dword
+ externdef _r_zistepx:dword
+ externdef _erroradjustdown:dword
+ externdef _d_countextrastep:dword
+ externdef _ubasestep:dword
+ externdef _a_ststepxwhole:dword
+ externdef _a_tstepxfrac:dword
+ externdef _r_lstepx:dword
+ externdef _a_spans:dword
+ externdef _erroradjustdown:dword
+ externdef _d_pdestextrastep:dword
+ externdef _d_pzextrastep:dword
+ externdef _d_sfracextrastep:dword
+ externdef _d_ptexextrastep:dword
+ externdef _d_countextrastep:dword
+ externdef _d_tfracextrastep:dword
+ externdef _d_lightextrastep:dword
+ externdef _d_ziextrastep:dword
+ externdef _d_pdestbasestep:dword
+ externdef _d_pzbasestep:dword
+ externdef _d_sfracbasestep:dword
+ externdef _d_ptexbasestep:dword
+ externdef _ubasestep:dword
+ externdef _d_tfracbasestep:dword
+ externdef _d_lightbasestep:dword
+ externdef _d_zibasestep:dword
+ externdef _zspantable:dword
+ externdef _r_lstepy:dword
+ externdef _r_sstepy:dword
+ externdef _r_tstepy:dword
+ externdef _r_zistepy:dword
+ externdef _D_PolysetSetEdgeTable:dword
+ externdef _D_RasterizeAliasPolySmooth:dword
+ externdef float_point5:dword
+ externdef Float2ToThe31nd:dword
+ externdef izistep:dword
+ externdef izi:dword
+ externdef FloatMinus2ToThe31nd:dword
+ externdef float_1:dword
+ externdef float_particle_z_clip:dword
+ externdef float_minus_1:dword
+ externdef float_0:dword
+ externdef fp_16:dword
+ externdef fp_64k:dword
+ externdef fp_1m:dword
+ externdef fp_1m_minus_1:dword
+ externdef fp_8:dword
+ externdef entryvec_table:dword
+ externdef advancetable:dword
+ externdef sstep:dword
+ externdef tstep:dword
+ externdef pspantemp:dword
+ externdef counttemp:dword
+ externdef jumptemp:dword
+ externdef reciprocal_table:dword
+ externdef DP_Count:dword
+ externdef DP_u:dword
+ externdef DP_v:dword
+ externdef DP_32768:dword
+ externdef DP_Color:dword
+ externdef DP_Pix:dword
+ externdef DP_EntryTable:dword
+ externdef pbase:dword
+ externdef s:dword
+ externdef t:dword
+ externdef sfracf:dword
+ externdef tfracf:dword
+ externdef snext:dword
+ externdef tnext:dword
+ externdef spancountminus1:dword
+ externdef zi16stepu:dword
+ externdef sdivz16stepu:dword
+ externdef tdivz16stepu:dword
+ externdef zi8stepu:dword
+ externdef sdivz8stepu:dword
+ externdef tdivz8stepu:dword
+ externdef reciprocal_table_16:dword
+ externdef entryvec_table_16:dword
+ externdef ceil_cw:dword
+ externdef single_cw:dword
+ externdef fp_64kx64k:dword
+ externdef pz:dword
+ externdef spr8entryvec_table:dword
+_DATA SEGMENT
+_DATA ENDS
+_TEXT SEGMENT
+ align 4
+ public _D_DrawTurbulent8Span
+_D_DrawTurbulent8Span:
+ push ebp
+ push esi
+ push edi
+ push ebx
+ mov esi,ds:dword ptr[_r_turb_s]
+ mov ecx,ds:dword ptr[_r_turb_t]
+ mov edi,ds:dword ptr[_r_turb_pdest]
+ mov ebx,ds:dword ptr[_r_turb_spancount]
+Llp:
+ mov eax,ecx
+ mov edx,esi
+ sar eax,16
+ mov ebp,ds:dword ptr[_r_turb_turb]
+ sar edx,16
+ and eax,128-1
+ and edx,128-1
+ mov eax,ds:dword ptr[ebp+eax*4]
+ mov edx,ds:dword ptr[ebp+edx*4]
+ add eax,esi
+ sar eax,16
+ add edx,ecx
+ sar edx,16
+ and eax,64-1
+ and edx,64-1
+ shl edx,6
+ mov ebp,ds:dword ptr[_r_turb_pbase]
+ add edx,eax
+ inc edi
+ add esi,ds:dword ptr[_r_turb_sstep]
+ add ecx,ds:dword ptr[_r_turb_tstep]
+ mov dl,ds:byte ptr[ebp+edx*1]
+ dec ebx
+ mov ds:byte ptr[-1+edi],dl
+ jnz Llp
+ mov ds:dword ptr[_r_turb_pdest],edi
+ pop ebx
+ pop edi
+ pop esi
+ pop ebp
+ ret
+_TEXT ENDS
+ END
--- /dev/null
+++ b/QW/client/d_scana.s
@@ -1,0 +1,89 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+//
+// d_scana.s
+// x86 assembly-language turbulent texture mapping code
+//
+
+#include "asm_i386.h"
+#include "quakeasm.h"
+#include "asm_draw.h"
+#include "d_ifacea.h"
+
+#if id386
+
+	.data
+
+	.text
+
+//----------------------------------------------------------------------
+// turbulent texture mapping code
+//----------------------------------------------------------------------
+
+	.align 4
+.globl C(D_DrawTurbulent8Span)
+C(D_DrawTurbulent8Span):
+	pushl	%ebp				// preserve caller's stack frame pointer
+	pushl	%esi				// preserve register variables
+	pushl	%edi
+	pushl	%ebx
+
+	movl	C(r_turb_s),%esi
+	movl	C(r_turb_t),%ecx
+	movl	C(r_turb_pdest),%edi
+	movl	C(r_turb_spancount),%ebx
+
+Llp:
+	movl	%ecx,%eax
+	movl	%esi,%edx
+	sarl	$16,%eax
+	movl	C(r_turb_turb),%ebp
+	sarl	$16,%edx
+	andl	$(CYCLE-1),%eax
+	andl	$(CYCLE-1),%edx
+	movl	(%ebp,%eax,4),%eax
+	movl	(%ebp,%edx,4),%edx
+	addl	%esi,%eax
+	sarl	$16,%eax
+	addl	%ecx,%edx
+	sarl	$16,%edx
+	andl	$(TURB_TEX_SIZE-1),%eax
+	andl	$(TURB_TEX_SIZE-1),%edx
+	shll	$6,%edx
+	movl	C(r_turb_pbase),%ebp
+	addl	%eax,%edx
+	incl	%edi
+	addl	C(r_turb_sstep),%esi
+	addl	C(r_turb_tstep),%ecx
+	movb	(%ebp,%edx,1),%dl
+	decl	%ebx
+	movb	%dl,-1(%edi)
+	jnz		Llp
+
+	movl	%edi,C(r_turb_pdest)
+
+	popl	%ebx				// restore register variables
+	popl	%edi
+	popl	%esi
+	popl	%ebp				// restore caller's stack frame pointer
+	ret
+
+#endif	// id386
+
--- /dev/null
+++ b/QW/client/d_sky.c
@@ -1,0 +1,138 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// d_sky.c
+
+#include "quakedef.h"
+#include "r_local.h"
+#include "d_local.h"
+
+#define SKY_SPAN_SHIFT	5
+#define SKY_SPAN_MAX	(1 << SKY_SPAN_SHIFT)
+
+
+/*
+=================
+D_Sky_uv_To_st
+=================
+*/
+void D_Sky_uv_To_st (int u, int v, fixed16_t *s, fixed16_t *t)
+{
+	float	wu, wv, temp;
+	vec3_t	end;
+
+	if (r_refdef.vrect.width >= r_refdef.vrect.height)
+		temp = (float)r_refdef.vrect.width;
+	else
+		temp = (float)r_refdef.vrect.height;
+
+	wu = 8192.0 * (float)(u-((int)vid.width>>1)) / temp;
+	wv = 8192.0 * (float)(((int)vid.height>>1)-v) / temp;
+
+	end[0] = 4096*vpn[0] + wu*vright[0] + wv*vup[0];
+	end[1] = 4096*vpn[1] + wu*vright[1] + wv*vup[1];
+	end[2] = 4096*vpn[2] + wu*vright[2] + wv*vup[2];
+	end[2] *= 3;
+	VectorNormalize (end);
+
+	temp = skytime*skyspeed;	// TODO: add D_SetupFrame & set this there
+	*s = (int)((temp + 6*(SKYSIZE/2-1)*end[0]) * 0x10000);
+	*t = (int)((temp + 6*(SKYSIZE/2-1)*end[1]) * 0x10000);
+}
+
+
+/*
+=================
+D_DrawSkyScans8
+=================
+*/
+void D_DrawSkyScans8 (espan_t *pspan)
+{
+	int				count, spancount, u, v;
+	unsigned char	*pdest;
+	fixed16_t		s, t, snext, tnext, sstep, tstep;
+	int				spancountminus1;
+
+	sstep = 0;	// keep compiler happy
+	tstep = 0;	// ditto
+
+	do
+	{
+		pdest = (unsigned char *)((byte *)d_viewbuffer +
+				(screenwidth * pspan->v) + pspan->u);
+
+		count = pspan->count;
+
+	// calculate the initial s & t
+		u = pspan->u;
+		v = pspan->v;
+		D_Sky_uv_To_st (u, v, &s, &t);
+
+		do
+		{
+			if (count >= SKY_SPAN_MAX)
+				spancount = SKY_SPAN_MAX;
+			else
+				spancount = count;
+
+			count -= spancount;
+
+			if (count)
+			{
+				u += spancount;
+
+			// calculate s and t at far end of span,
+			// calculate s and t steps across span by shifting
+				D_Sky_uv_To_st (u, v, &snext, &tnext);
+
+				sstep = (snext - s) >> SKY_SPAN_SHIFT;
+				tstep = (tnext - t) >> SKY_SPAN_SHIFT;
+			}
+			else
+			{
+			// calculate s and t at last pixel in span,
+			// calculate s and t steps across span by division
+				spancountminus1 = (float)(spancount - 1);
+
+				if (spancountminus1 > 0)
+				{
+					u += spancountminus1;
+					D_Sky_uv_To_st (u, v, &snext, &tnext);
+
+					sstep = (snext - s) / spancountminus1;
+					tstep = (tnext - t) / spancountminus1;
+				}
+			}
+
+			do
+			{
+				*pdest++ = r_skysource[((t & R_SKY_TMASK) >> 8) +
+						((s & R_SKY_SMASK) >> 16)];
+				s += sstep;
+				t += tstep;
+			} while (--spancount > 0);
+
+			s = snext;
+			t = tnext;
+
+		} while (count > 0);
+
+	} while ((pspan = pspan->pnext) != NULL);
+}
+
--- /dev/null
+++ b/QW/client/d_spr8.asm
@@ -1,0 +1,886 @@
+ .386P
+ .model FLAT
+ externdef _d_zistepu:dword
+ externdef _d_pzbuffer:dword
+ externdef _d_zistepv:dword
+ externdef _d_zrowbytes:dword
+ externdef _d_ziorigin:dword
+ externdef _r_turb_s:dword
+ externdef _r_turb_t:dword
+ externdef _r_turb_pdest:dword
+ externdef _r_turb_spancount:dword
+ externdef _r_turb_turb:dword
+ externdef _r_turb_pbase:dword
+ externdef _r_turb_sstep:dword
+ externdef _r_turb_tstep:dword
+ externdef _r_bmodelactive:dword
+ externdef _d_sdivzstepu:dword
+ externdef _d_tdivzstepu:dword
+ externdef _d_sdivzstepv:dword
+ externdef _d_tdivzstepv:dword
+ externdef _d_sdivzorigin:dword
+ externdef _d_tdivzorigin:dword
+ externdef _sadjust:dword
+ externdef _tadjust:dword
+ externdef _bbextents:dword
+ externdef _bbextentt:dword
+ externdef _cacheblock:dword
+ externdef _d_viewbuffer:dword
+ externdef _cachewidth:dword
+ externdef _d_pzbuffer:dword
+ externdef _d_zrowbytes:dword
+ externdef _d_zwidth:dword
+ externdef _d_scantable:dword
+ externdef _r_lightptr:dword
+ externdef _r_numvblocks:dword
+ externdef _prowdestbase:dword
+ externdef _pbasesource:dword
+ externdef _r_lightwidth:dword
+ externdef _lightright:dword
+ externdef _lightrightstep:dword
+ externdef _lightdeltastep:dword
+ externdef _lightdelta:dword
+ externdef _lightright:dword
+ externdef _lightdelta:dword
+ externdef _sourcetstep:dword
+ externdef _surfrowbytes:dword
+ externdef _lightrightstep:dword
+ externdef _lightdeltastep:dword
+ externdef _r_sourcemax:dword
+ externdef _r_stepback:dword
+ externdef _colormap:dword
+ externdef _blocksize:dword
+ externdef _sourcesstep:dword
+ externdef _lightleft:dword
+ externdef _blockdivshift:dword
+ externdef _blockdivmask:dword
+ externdef _lightleftstep:dword
+ externdef _r_origin:dword
+ externdef _r_ppn:dword
+ externdef _r_pup:dword
+ externdef _r_pright:dword
+ externdef _ycenter:dword
+ externdef _xcenter:dword
+ externdef _d_vrectbottom_particle:dword
+ externdef _d_vrectright_particle:dword
+ externdef _d_vrecty:dword
+ externdef _d_vrectx:dword
+ externdef _d_pix_shift:dword
+ externdef _d_pix_min:dword
+ externdef _d_pix_max:dword
+ externdef _d_y_aspect_shift:dword
+ externdef _screenwidth:dword
+ externdef _vright:dword
+ externdef _vup:dword
+ externdef _vpn:dword
+ externdef _BOPS_Error:dword
+ externdef _snd_scaletable:dword
+ externdef _paintbuffer:dword
+ externdef _snd_linear_count:dword
+ externdef _snd_p:dword
+ externdef _snd_vol:dword
+ externdef _snd_out:dword
+ externdef _r_leftclipped:dword
+ externdef _r_leftenter:dword
+ externdef _r_rightclipped:dword
+ externdef _r_rightenter:dword
+ externdef _modelorg:dword
+ externdef _xscale:dword
+ externdef _r_refdef:dword
+ externdef _yscale:dword
+ externdef _r_leftexit:dword
+ externdef _r_rightexit:dword
+ externdef _r_lastvertvalid:dword
+ externdef _cacheoffset:dword
+ externdef _newedges:dword
+ externdef _removeedges:dword
+ externdef _r_pedge:dword
+ externdef _r_framecount:dword
+ externdef _r_u1:dword
+ externdef _r_emitted:dword
+ externdef _edge_p:dword
+ externdef _surface_p:dword
+ externdef _surfaces:dword
+ externdef _r_lzi1:dword
+ externdef _r_v1:dword
+ externdef _r_ceilv1:dword
+ externdef _r_nearzi:dword
+ externdef _r_nearzionly:dword
+ externdef _edge_aftertail:dword
+ externdef _edge_tail:dword
+ externdef _current_iv:dword
+ externdef _edge_head_u_shift20:dword
+ externdef _span_p:dword
+ externdef _edge_head:dword
+ externdef _fv:dword
+ externdef _edge_tail_u_shift20:dword
+ externdef _r_apverts:dword
+ externdef _r_anumverts:dword
+ externdef _aliastransform:dword
+ externdef _r_avertexnormals:dword
+ externdef _r_plightvec:dword
+ externdef _r_ambientlight:dword
+ externdef _r_shadelight:dword
+ externdef _aliasxcenter:dword
+ externdef _aliasycenter:dword
+ externdef _a_sstepxfrac:dword
+ externdef _r_affinetridesc:dword
+ externdef _acolormap:dword
+ externdef _d_pcolormap:dword
+ externdef _r_affinetridesc:dword
+ externdef _d_sfrac:dword
+ externdef _d_ptex:dword
+ externdef _d_pedgespanpackage:dword
+ externdef _d_tfrac:dword
+ externdef _d_light:dword
+ externdef _d_zi:dword
+ externdef _d_pdest:dword
+ externdef _d_pz:dword
+ externdef _d_aspancount:dword
+ externdef _erroradjustup:dword
+ externdef _errorterm:dword
+ externdef _d_xdenom:dword
+ externdef _r_p0:dword
+ externdef _r_p1:dword
+ externdef _r_p2:dword
+ externdef _a_tstepxfrac:dword
+ externdef _r_sstepx:dword
+ externdef _r_tstepx:dword
+ externdef _a_ststepxwhole:dword
+ externdef _zspantable:dword
+ externdef _skintable:dword
+ externdef _r_zistepx:dword
+ externdef _erroradjustdown:dword
+ externdef _d_countextrastep:dword
+ externdef _ubasestep:dword
+ externdef _a_ststepxwhole:dword
+ externdef _a_tstepxfrac:dword
+ externdef _r_lstepx:dword
+ externdef _a_spans:dword
+ externdef _erroradjustdown:dword
+ externdef _d_pdestextrastep:dword
+ externdef _d_pzextrastep:dword
+ externdef _d_sfracextrastep:dword
+ externdef _d_ptexextrastep:dword
+ externdef _d_countextrastep:dword
+ externdef _d_tfracextrastep:dword
+ externdef _d_lightextrastep:dword
+ externdef _d_ziextrastep:dword
+ externdef _d_pdestbasestep:dword
+ externdef _d_pzbasestep:dword
+ externdef _d_sfracbasestep:dword
+ externdef _d_ptexbasestep:dword
+ externdef _ubasestep:dword
+ externdef _d_tfracbasestep:dword
+ externdef _d_lightbasestep:dword
+ externdef _d_zibasestep:dword
+ externdef _zspantable:dword
+ externdef _r_lstepy:dword
+ externdef _r_sstepy:dword
+ externdef _r_tstepy:dword
+ externdef _r_zistepy:dword
+ externdef _D_PolysetSetEdgeTable:dword
+ externdef _D_RasterizeAliasPolySmooth:dword
+ externdef float_point5:dword
+ externdef Float2ToThe31nd:dword
+ externdef izistep:dword
+ externdef izi:dword
+ externdef FloatMinus2ToThe31nd:dword
+ externdef float_1:dword
+ externdef float_particle_z_clip:dword
+ externdef float_minus_1:dword
+ externdef float_0:dword
+ externdef fp_16:dword
+ externdef fp_64k:dword
+ externdef fp_1m:dword
+ externdef fp_1m_minus_1:dword
+ externdef fp_8:dword
+ externdef entryvec_table:dword
+ externdef advancetable:dword
+ externdef sstep:dword
+ externdef tstep:dword
+ externdef pspantemp:dword
+ externdef counttemp:dword
+ externdef jumptemp:dword
+ externdef reciprocal_table:dword
+ externdef DP_Count:dword
+ externdef DP_u:dword
+ externdef DP_v:dword
+ externdef DP_32768:dword
+ externdef DP_Color:dword
+ externdef DP_Pix:dword
+ externdef DP_EntryTable:dword
+ externdef pbase:dword
+ externdef s:dword
+ externdef t:dword
+ externdef sfracf:dword
+ externdef tfracf:dword
+ externdef snext:dword
+ externdef tnext:dword
+ externdef spancountminus1:dword
+ externdef zi16stepu:dword
+ externdef sdivz16stepu:dword
+ externdef tdivz16stepu:dword
+ externdef zi8stepu:dword
+ externdef sdivz8stepu:dword
+ externdef tdivz8stepu:dword
+ externdef reciprocal_table_16:dword
+ externdef entryvec_table_16:dword
+ externdef ceil_cw:dword
+ externdef single_cw:dword
+ externdef fp_64kx64k:dword
+ externdef pz:dword
+ externdef spr8entryvec_table:dword
+_TEXT SEGMENT
+LClampHigh0:
+ mov esi,ds:dword ptr[_bbextents]
+ jmp LClampReentry0
+LClampHighOrLow0:
+ jg LClampHigh0
+ xor esi,esi
+ jmp LClampReentry0
+LClampHigh1:
+ mov edx,ds:dword ptr[_bbextentt]
+ jmp LClampReentry1
+LClampHighOrLow1:
+ jg LClampHigh1
+ xor edx,edx
+ jmp LClampReentry1
+LClampLow2:
+ mov ebp,2048
+ jmp LClampReentry2
+LClampHigh2:
+ mov ebp,ds:dword ptr[_bbextents]
+ jmp LClampReentry2
+LClampLow3:
+ mov ecx,2048
+ jmp LClampReentry3
+LClampHigh3:
+ mov ecx,ds:dword ptr[_bbextentt]
+ jmp LClampReentry3
+LClampLow4:
+ mov eax,2048
+ jmp LClampReentry4
+LClampHigh4:
+ mov eax,ds:dword ptr[_bbextents]
+ jmp LClampReentry4
+LClampLow5:
+ mov ebx,2048
+ jmp LClampReentry5
+LClampHigh5:
+ mov ebx,ds:dword ptr[_bbextentt]
+ jmp LClampReentry5
+ align 4
+ public _D_SpriteDrawSpans
+_D_SpriteDrawSpans:
+ push ebp
+ push edi
+ push esi
+ push ebx
+ fld ds:dword ptr[_d_sdivzstepu]
+ fmul ds:dword ptr[fp_8]
+ mov edx,ds:dword ptr[_cacheblock]
+ fld ds:dword ptr[_d_tdivzstepu]
+ fmul ds:dword ptr[fp_8]
+ mov ebx,ds:dword ptr[4+16+esp]
+ fld ds:dword ptr[_d_zistepu]
+ fmul ds:dword ptr[fp_8]
+ mov ds:dword ptr[pbase],edx
+ fld ds:dword ptr[_d_zistepu]
+ fmul ds:dword ptr[fp_64kx64k]
+ fxch st(3)
+ fstp ds:dword ptr[sdivz8stepu]
+ fstp ds:dword ptr[zi8stepu]
+ fstp ds:dword ptr[tdivz8stepu]
+ fistp ds:dword ptr[izistep]
+ mov eax,ds:dword ptr[izistep]
+ ror eax,16
+ mov ecx,ds:dword ptr[8+ebx]
+ mov ds:dword ptr[izistep],eax
+ cmp ecx,0
+ jle LNextSpan
+LSpanLoop:
+ fild ds:dword ptr[4+ebx]
+ fild ds:dword ptr[0+ebx]
+ fld st(1)
+ fmul ds:dword ptr[_d_sdivzstepv]
+ fld st(1)
+ fmul ds:dword ptr[_d_sdivzstepu]
+ fld st(2)
+ fmul ds:dword ptr[_d_tdivzstepu]
+ fxch st(1)
+ faddp st(2),st(0)
+ fxch st(1)
+ fld st(3)
+ fmul ds:dword ptr[_d_tdivzstepv]
+ fxch st(1)
+ fadd ds:dword ptr[_d_sdivzorigin]
+ fxch st(4)
+ fmul ds:dword ptr[_d_zistepv]
+ fxch st(1)
+ faddp st(2),st(0)
+ fxch st(2)
+ fmul ds:dword ptr[_d_zistepu]
+ fxch st(1)
+ fadd ds:dword ptr[_d_tdivzorigin]
+ fxch st(2)
+ faddp st(1),st(0)
+ fld ds:dword ptr[fp_64k]
+ fxch st(1)
+ fadd ds:dword ptr[_d_ziorigin]
+ fld st(0)
+ fmul ds:dword ptr[fp_64kx64k]
+ fxch st(1)
+ fdiv st(2),st(0)
+ fxch st(1)
+ fistp ds:dword ptr[izi]
+ mov ebp,ds:dword ptr[izi]
+ ror ebp,16
+ mov eax,ds:dword ptr[4+ebx]
+ mov ds:dword ptr[izi],ebp
+ mov ebp,ds:dword ptr[0+ebx]
+ imul ds:dword ptr[_d_zrowbytes]
+ shl ebp,1
+ add eax,ds:dword ptr[_d_pzbuffer]
+ add eax,ebp
+ mov ds:dword ptr[pz],eax
+ mov ebp,ds:dword ptr[_d_viewbuffer]
+ mov eax,ds:dword ptr[4+ebx]
+ push ebx
+ mov edx,ds:dword ptr[_tadjust]
+ mov esi,ds:dword ptr[_sadjust]
+ mov edi,ds:dword ptr[_d_scantable+eax*4]
+ add edi,ebp
+ mov ebp,ds:dword ptr[0+ebx]
+ add edi,ebp
+ cmp ecx,8
+ ja LSetupNotLast1
+ dec ecx
+ jz LCleanup1
+ mov ds:dword ptr[spancountminus1],ecx
+ fxch st(1)
+ fld st(0)
+ fmul st(0),st(4)
+ fxch st(1)
+ fmul st(0),st(3)
+ fxch st(1)
+ fistp ds:dword ptr[s]
+ fistp ds:dword ptr[t]
+ fild ds:dword ptr[spancountminus1]
+ fld ds:dword ptr[_d_tdivzstepu]
+ fld ds:dword ptr[_d_zistepu]
+ fmul st(0),st(2)
+ fxch st(1)
+ fmul st(0),st(2)
+ fxch st(2)
+ fmul ds:dword ptr[_d_sdivzstepu]
+ fxch st(1)
+ faddp st(3),st(0)
+ fxch st(1)
+ faddp st(3),st(0)
+ faddp st(3),st(0)
+ fld ds:dword ptr[fp_64k]
+ fdiv st(0),st(1)
+ jmp LFDIVInFlight1
+LCleanup1:
+ fxch st(1)
+ fld st(0)
+ fmul st(0),st(4)
+ fxch st(1)
+ fmul st(0),st(3)
+ fxch st(1)
+ fistp ds:dword ptr[s]
+ fistp ds:dword ptr[t]
+ jmp LFDIVInFlight1
+ align 4
+LSetupNotLast1:
+ fxch st(1)
+ fld st(0)
+ fmul st(0),st(4)
+ fxch st(1)
+ fmul st(0),st(3)
+ fxch st(1)
+ fistp ds:dword ptr[s]
+ fistp ds:dword ptr[t]
+ fadd ds:dword ptr[zi8stepu]
+ fxch st(2)
+ fadd ds:dword ptr[sdivz8stepu]
+ fxch st(2)
+ fld ds:dword ptr[tdivz8stepu]
+ faddp st(2),st(0)
+ fld ds:dword ptr[fp_64k]
+ fdiv st(0),st(1)
+LFDIVInFlight1:
+ add esi,ds:dword ptr[s]
+ add edx,ds:dword ptr[t]
+ mov ebx,ds:dword ptr[_bbextents]
+ mov ebp,ds:dword ptr[_bbextentt]
+ cmp esi,ebx
+ ja LClampHighOrLow0
+LClampReentry0:
+ mov ds:dword ptr[s],esi
+ mov ebx,ds:dword ptr[pbase]
+ shl esi,16
+ cmp edx,ebp
+ mov ds:dword ptr[sfracf],esi
+ ja LClampHighOrLow1
+LClampReentry1:
+ mov ds:dword ptr[t],edx
+ mov esi,ds:dword ptr[s]
+ shl edx,16
+ mov eax,ds:dword ptr[t]
+ sar esi,16
+ mov ds:dword ptr[tfracf],edx
+ sar eax,16
+ add esi,ebx
+ imul eax,ds:dword ptr[_cachewidth]
+ add esi,eax
+ cmp ecx,8
+ jna LLastSegment
+LNotLastSegment:
+ fld st(0)
+ fmul st(0),st(4)
+ fxch st(1)
+ fmul st(0),st(3)
+ fxch st(1)
+ fistp ds:dword ptr[snext]
+ fistp ds:dword ptr[tnext]
+ mov eax,ds:dword ptr[snext]
+ mov edx,ds:dword ptr[tnext]
+ sub ecx,8
+ mov ebp,ds:dword ptr[_sadjust]
+ push ecx
+ mov ecx,ds:dword ptr[_tadjust]
+ add ebp,eax
+ add ecx,edx
+ mov eax,ds:dword ptr[_bbextents]
+ mov edx,ds:dword ptr[_bbextentt]
+ cmp ebp,2048
+ jl LClampLow2
+ cmp ebp,eax
+ ja LClampHigh2
+LClampReentry2:
+ cmp ecx,2048
+ jl LClampLow3
+ cmp ecx,edx
+ ja LClampHigh3
+LClampReentry3:
+ mov ds:dword ptr[snext],ebp
+ mov ds:dword ptr[tnext],ecx
+ sub ebp,ds:dword ptr[s]
+ sub ecx,ds:dword ptr[t]
+ mov eax,ecx
+ mov edx,ebp
+ sar edx,19
+ mov ebx,ds:dword ptr[_cachewidth]
+ sar eax,19
+ jz LIsZero
+ imul eax,ebx
+LIsZero:
+ add eax,edx
+ mov edx,ds:dword ptr[tfracf]
+ mov ds:dword ptr[advancetable+4],eax
+ add eax,ebx
+ shl ebp,13
+ mov ds:dword ptr[sstep],ebp
+ mov ebx,ds:dword ptr[sfracf]
+ shl ecx,13
+ mov ds:dword ptr[advancetable],eax
+ mov ds:dword ptr[tstep],ecx
+ mov ecx,ds:dword ptr[pz]
+ mov ebp,ds:dword ptr[izi]
+ cmp bp,ds:word ptr[ecx]
+ jl Lp1
+ mov al,ds:byte ptr[esi]
+ cmp al,255
+ jz Lp1
+ mov ds:word ptr[ecx],bp
+ mov ds:byte ptr[edi],al
+Lp1:
+ add ebp,ds:dword ptr[izistep]
+ adc ebp,0
+ add edx,ds:dword ptr[tstep]
+ sbb eax,eax
+ add ebx,ds:dword ptr[sstep]
+ adc esi,ds:dword ptr[advancetable+4+eax*4]
+ cmp bp,ds:word ptr[2+ecx]
+ jl Lp2
+ mov al,ds:byte ptr[esi]
+ cmp al,255
+ jz Lp2
+ mov ds:word ptr[2+ecx],bp
+ mov ds:byte ptr[1+edi],al
+Lp2:
+ add ebp,ds:dword ptr[izistep]
+ adc ebp,0
+ add edx,ds:dword ptr[tstep]
+ sbb eax,eax
+ add ebx,ds:dword ptr[sstep]
+ adc esi,ds:dword ptr[advancetable+4+eax*4]
+ cmp bp,ds:word ptr[4+ecx]
+ jl Lp3
+ mov al,ds:byte ptr[esi]
+ cmp al,255
+ jz Lp3
+ mov ds:word ptr[4+ecx],bp
+ mov ds:byte ptr[2+edi],al
+Lp3:
+ add ebp,ds:dword ptr[izistep]
+ adc ebp,0
+ add edx,ds:dword ptr[tstep]
+ sbb eax,eax
+ add ebx,ds:dword ptr[sstep]
+ adc esi,ds:dword ptr[advancetable+4+eax*4]
+ cmp bp,ds:word ptr[6+ecx]
+ jl Lp4
+ mov al,ds:byte ptr[esi]
+ cmp al,255
+ jz Lp4
+ mov ds:word ptr[6+ecx],bp
+ mov ds:byte ptr[3+edi],al
+Lp4:
+ add ebp,ds:dword ptr[izistep]
+ adc ebp,0
+ add edx,ds:dword ptr[tstep]
+ sbb eax,eax
+ add ebx,ds:dword ptr[sstep]
+ adc esi,ds:dword ptr[advancetable+4+eax*4]
+ cmp bp,ds:word ptr[8+ecx]
+ jl Lp5
+ mov al,ds:byte ptr[esi]
+ cmp al,255
+ jz Lp5
+ mov ds:word ptr[8+ecx],bp
+ mov ds:byte ptr[4+edi],al
+Lp5:
+ add ebp,ds:dword ptr[izistep]
+ adc ebp,0
+ add edx,ds:dword ptr[tstep]
+ sbb eax,eax
+ add ebx,ds:dword ptr[sstep]
+ adc esi,ds:dword ptr[advancetable+4+eax*4]
+ pop eax
+ cmp eax,8
+ ja LSetupNotLast2
+ dec eax
+ jz LFDIVInFlight2
+ mov ds:dword ptr[spancountminus1],eax
+ fild ds:dword ptr[spancountminus1]
+ fld ds:dword ptr[_d_zistepu]
+ fmul st(0),st(1)
+ fld ds:dword ptr[_d_tdivzstepu]
+ fmul st(0),st(2)
+ fxch st(1)
+ faddp st(3),st(0)
+ fxch st(1)
+ fmul ds:dword ptr[_d_sdivzstepu]
+ fxch st(1)
+ faddp st(3),st(0)
+ fld ds:dword ptr[fp_64k]
+ fxch st(1)
+ faddp st(4),st(0)
+ fdiv st(0),st(1)
+ jmp LFDIVInFlight2
+ align 4
+LSetupNotLast2:
+ fadd ds:dword ptr[zi8stepu]
+ fxch st(2)
+ fadd ds:dword ptr[sdivz8stepu]
+ fxch st(2)
+ fld ds:dword ptr[tdivz8stepu]
+ faddp st(2),st(0)
+ fld ds:dword ptr[fp_64k]
+ fdiv st(0),st(1)
+LFDIVInFlight2:
+ push eax
+ cmp bp,ds:word ptr[10+ecx]
+ jl Lp6
+ mov al,ds:byte ptr[esi]
+ cmp al,255
+ jz Lp6
+ mov ds:word ptr[10+ecx],bp
+ mov ds:byte ptr[5+edi],al
+Lp6:
+ add ebp,ds:dword ptr[izistep]
+ adc ebp,0
+ add edx,ds:dword ptr[tstep]
+ sbb eax,eax
+ add ebx,ds:dword ptr[sstep]
+ adc esi,ds:dword ptr[advancetable+4+eax*4]
+ cmp bp,ds:word ptr[12+ecx]
+ jl Lp7
+ mov al,ds:byte ptr[esi]
+ cmp al,255
+ jz Lp7
+ mov ds:word ptr[12+ecx],bp
+ mov ds:byte ptr[6+edi],al
+Lp7:
+ add ebp,ds:dword ptr[izistep]
+ adc ebp,0
+ add edx,ds:dword ptr[tstep]
+ sbb eax,eax
+ add ebx,ds:dword ptr[sstep]
+ adc esi,ds:dword ptr[advancetable+4+eax*4]
+ cmp bp,ds:word ptr[14+ecx]
+ jl Lp8
+ mov al,ds:byte ptr[esi]
+ cmp al,255
+ jz Lp8
+ mov ds:word ptr[14+ecx],bp
+ mov ds:byte ptr[7+edi],al
+Lp8:
+ add ebp,ds:dword ptr[izistep]
+ adc ebp,0
+ add edx,ds:dword ptr[tstep]
+ sbb eax,eax
+ add ebx,ds:dword ptr[sstep]
+ adc esi,ds:dword ptr[advancetable+4+eax*4]
+ add edi,8
+ add ecx,16
+ mov ds:dword ptr[tfracf],edx
+ mov edx,ds:dword ptr[snext]
+ mov ds:dword ptr[sfracf],ebx
+ mov ebx,ds:dword ptr[tnext]
+ mov ds:dword ptr[s],edx
+ mov ds:dword ptr[t],ebx
+ mov ds:dword ptr[pz],ecx
+ mov ds:dword ptr[izi],ebp
+ pop ecx
+ cmp ecx,8
+ ja LNotLastSegment
+LLastSegment:
+ test ecx,ecx
+ jz LNoSteps
+ fld st(0)
+ fmul st(0),st(4)
+ fxch st(1)
+ fmul st(0),st(3)
+ fxch st(1)
+ fistp ds:dword ptr[snext]
+ fistp ds:dword ptr[tnext]
+ mov ebx,ds:dword ptr[_tadjust]
+ mov eax,ds:dword ptr[_sadjust]
+ add eax,ds:dword ptr[snext]
+ add ebx,ds:dword ptr[tnext]
+ mov ebp,ds:dword ptr[_bbextents]
+ mov edx,ds:dword ptr[_bbextentt]
+ cmp eax,2048
+ jl LClampLow4
+ cmp eax,ebp
+ ja LClampHigh4
+LClampReentry4:
+ mov ds:dword ptr[snext],eax
+ cmp ebx,2048
+ jl LClampLow5
+ cmp ebx,edx
+ ja LClampHigh5
+LClampReentry5:
+ cmp ecx,1
+ je LOnlyOneStep
+ sub eax,ds:dword ptr[s]
+ sub ebx,ds:dword ptr[t]
+ add eax,eax
+ add ebx,ebx
+ imul ds:dword ptr[reciprocal_table-8+ecx*4]
+ mov ebp,edx
+ mov eax,ebx
+ imul ds:dword ptr[reciprocal_table-8+ecx*4]
+LSetEntryvec:
+ mov ebx,ds:dword ptr[spr8entryvec_table+ecx*4]
+ mov eax,edx
+ push ebx
+ mov ecx,ebp
+ sar ecx,16
+ mov ebx,ds:dword ptr[_cachewidth]
+ sar edx,16
+ jz LIsZeroLast
+ imul edx,ebx
+LIsZeroLast:
+ add edx,ecx
+ mov ecx,ds:dword ptr[tfracf]
+ mov ds:dword ptr[advancetable+4],edx
+ add edx,ebx
+ shl ebp,16
+ mov ebx,ds:dword ptr[sfracf]
+ shl eax,16
+ mov ds:dword ptr[advancetable],edx
+ mov ds:dword ptr[tstep],eax
+ mov ds:dword ptr[sstep],ebp
+ mov edx,ecx
+ mov ecx,ds:dword ptr[pz]
+ mov ebp,ds:dword ptr[izi]
+ ret
+LNoSteps:
+ mov ecx,ds:dword ptr[pz]
+ sub edi,7
+ sub ecx,14
+ jmp LEndSpan
+LOnlyOneStep:
+ sub eax,ds:dword ptr[s]
+ sub ebx,ds:dword ptr[t]
+ mov ebp,eax
+ mov edx,ebx
+ jmp LSetEntryvec
+ public Spr8Entry2_8
+Spr8Entry2_8:
+ sub edi,6
+ sub ecx,12
+ mov al,ds:byte ptr[esi]
+ jmp LLEntry2_8
+ public Spr8Entry3_8
+Spr8Entry3_8:
+ sub edi,5
+ sub ecx,10
+ jmp LLEntry3_8
+ public Spr8Entry4_8
+Spr8Entry4_8:
+ sub edi,4
+ sub ecx,8
+ jmp LLEntry4_8
+ public Spr8Entry5_8
+Spr8Entry5_8:
+ sub edi,3
+ sub ecx,6
+ jmp LLEntry5_8
+ public Spr8Entry6_8
+Spr8Entry6_8:
+ sub edi,2
+ sub ecx,4
+ jmp LLEntry6_8
+ public Spr8Entry7_8
+Spr8Entry7_8:
+ dec edi
+ sub ecx,2
+ jmp LLEntry7_8
+ public Spr8Entry8_8
+Spr8Entry8_8:
+ cmp bp,ds:word ptr[ecx]
+ jl Lp9
+ mov al,ds:byte ptr[esi]
+ cmp al,255
+ jz Lp9
+ mov ds:word ptr[ecx],bp
+ mov ds:byte ptr[edi],al
+Lp9:
+ add ebp,ds:dword ptr[izistep]
+ adc ebp,0
+ add edx,ds:dword ptr[tstep]
+ sbb eax,eax
+ add ebx,ds:dword ptr[sstep]
+ adc esi,ds:dword ptr[advancetable+4+eax*4]
+LLEntry7_8:
+ cmp bp,ds:word ptr[2+ecx]
+ jl Lp10
+ mov al,ds:byte ptr[esi]
+ cmp al,255
+ jz Lp10
+ mov ds:word ptr[2+ecx],bp
+ mov ds:byte ptr[1+edi],al
+Lp10:
+ add ebp,ds:dword ptr[izistep]
+ adc ebp,0
+ add edx,ds:dword ptr[tstep]
+ sbb eax,eax
+ add ebx,ds:dword ptr[sstep]
+ adc esi,ds:dword ptr[advancetable+4+eax*4]
+LLEntry6_8:
+ cmp bp,ds:word ptr[4+ecx]
+ jl Lp11
+ mov al,ds:byte ptr[esi]
+ cmp al,255
+ jz Lp11
+ mov ds:word ptr[4+ecx],bp
+ mov ds:byte ptr[2+edi],al
+Lp11:
+ add ebp,ds:dword ptr[izistep]
+ adc ebp,0
+ add edx,ds:dword ptr[tstep]
+ sbb eax,eax
+ add ebx,ds:dword ptr[sstep]
+ adc esi,ds:dword ptr[advancetable+4+eax*4]
+LLEntry5_8:
+ cmp bp,ds:word ptr[6+ecx]
+ jl Lp12
+ mov al,ds:byte ptr[esi]
+ cmp al,255
+ jz Lp12
+ mov ds:word ptr[6+ecx],bp
+ mov ds:byte ptr[3+edi],al
+Lp12:
+ add ebp,ds:dword ptr[izistep]
+ adc ebp,0
+ add edx,ds:dword ptr[tstep]
+ sbb eax,eax
+ add ebx,ds:dword ptr[sstep]
+ adc esi,ds:dword ptr[advancetable+4+eax*4]
+LLEntry4_8:
+ cmp bp,ds:word ptr[8+ecx]
+ jl Lp13
+ mov al,ds:byte ptr[esi]
+ cmp al,255
+ jz Lp13
+ mov ds:word ptr[8+ecx],bp
+ mov ds:byte ptr[4+edi],al
+Lp13:
+ add ebp,ds:dword ptr[izistep]
+ adc ebp,0
+ add edx,ds:dword ptr[tstep]
+ sbb eax,eax
+ add ebx,ds:dword ptr[sstep]
+ adc esi,ds:dword ptr[advancetable+4+eax*4]
+LLEntry3_8:
+ cmp bp,ds:word ptr[10+ecx]
+ jl Lp14
+ mov al,ds:byte ptr[esi]
+ cmp al,255
+ jz Lp14
+ mov ds:word ptr[10+ecx],bp
+ mov ds:byte ptr[5+edi],al
+Lp14:
+ add ebp,ds:dword ptr[izistep]
+ adc ebp,0
+ add edx,ds:dword ptr[tstep]
+ sbb eax,eax
+ add ebx,ds:dword ptr[sstep]
+ adc esi,ds:dword ptr[advancetable+4+eax*4]
+LLEntry2_8:
+ cmp bp,ds:word ptr[12+ecx]
+ jl Lp15
+ mov al,ds:byte ptr[esi]
+ cmp al,255
+ jz Lp15
+ mov ds:word ptr[12+ecx],bp
+ mov ds:byte ptr[6+edi],al
+Lp15:
+ add ebp,ds:dword ptr[izistep]
+ adc ebp,0
+ add edx,ds:dword ptr[tstep]
+ sbb eax,eax
+ add ebx,ds:dword ptr[sstep]
+ adc esi,ds:dword ptr[advancetable+4+eax*4]
+LEndSpan:
+ cmp bp,ds:word ptr[14+ecx]
+ jl Lp16
+ mov al,ds:byte ptr[esi]
+ cmp al,255
+ jz Lp16
+ mov ds:word ptr[14+ecx],bp
+ mov ds:byte ptr[7+edi],al
+Lp16:
+ fstp st(0)
+ fstp st(0)
+ fstp st(0)
+ pop ebx
+LNextSpan:
+ add ebx,12
+ mov ecx,ds:dword ptr[8+ebx]
+ cmp ecx,0
+ jg LSpanLoop
+ jz LNextSpan
+ pop ebx
+ pop esi
+ pop edi
+ pop ebp
+ ret
+_TEXT ENDS
+ END
--- /dev/null
+++ b/QW/client/d_spr8.s
@@ -1,0 +1,900 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+//
+// d_spr8.s
+// x86 assembly-language horizontal 8-bpp transparent span-drawing code.
+//
+
+#include "asm_i386.h"
+#include "quakeasm.h"
+#include "asm_draw.h"
+
+#if id386
+
+//----------------------------------------------------------------------
+// 8-bpp horizontal span drawing code for polygons, with transparency.
+//----------------------------------------------------------------------
+
+	.text
+
+// out-of-line, rarely-needed clamping code
+
+LClampHigh0:
+	movl	C(bbextents),%esi
+	jmp		LClampReentry0
+LClampHighOrLow0:
+	jg		LClampHigh0
+	xorl	%esi,%esi
+	jmp		LClampReentry0
+
+LClampHigh1:
+	movl	C(bbextentt),%edx
+	jmp		LClampReentry1
+LClampHighOrLow1:
+	jg		LClampHigh1
+	xorl	%edx,%edx
+	jmp		LClampReentry1
+
+LClampLow2:
+	movl	$2048,%ebp
+	jmp		LClampReentry2
+LClampHigh2:
+	movl	C(bbextents),%ebp
+	jmp		LClampReentry2
+
+LClampLow3:
+	movl	$2048,%ecx
+	jmp		LClampReentry3
+LClampHigh3:
+	movl	C(bbextentt),%ecx
+	jmp		LClampReentry3
+
+LClampLow4:
+	movl	$2048,%eax
+	jmp		LClampReentry4
+LClampHigh4:
+	movl	C(bbextents),%eax
+	jmp		LClampReentry4
+
+LClampLow5:
+	movl	$2048,%ebx
+	jmp		LClampReentry5
+LClampHigh5:
+	movl	C(bbextentt),%ebx
+	jmp		LClampReentry5
+
+
+#define pspans	4+16
+
+	.align 4
+.globl C(D_SpriteDrawSpans)
+C(D_SpriteDrawSpans):
+	pushl	%ebp				// preserve caller's stack frame
+	pushl	%edi
+	pushl	%esi				// preserve register variables
+	pushl	%ebx
+
+//
+// set up scaled-by-8 steps, for 8-long segments; also set up cacheblock
+// and span list pointers, and 1/z step in 0.32 fixed-point
+//
+// FIXME: any overlap from rearranging?
+	flds	C(d_sdivzstepu)
+	fmuls	fp_8
+	movl	C(cacheblock),%edx
+	flds	C(d_tdivzstepu)
+	fmuls	fp_8
+	movl	pspans(%esp),%ebx	// point to the first span descriptor
+	flds	C(d_zistepu)
+	fmuls	fp_8
+	movl	%edx,pbase			// pbase = cacheblock
+	flds	C(d_zistepu)
+	fmuls	fp_64kx64k
+	fxch	%st(3)
+	fstps	sdivz8stepu
+	fstps	zi8stepu
+	fstps	tdivz8stepu
+	fistpl	izistep
+	movl	izistep,%eax
+	rorl	$16,%eax		// put upper 16 bits in low word
+	movl	sspan_t_count(%ebx),%ecx
+	movl	%eax,izistep
+
+	cmpl	$0,%ecx
+	jle		LNextSpan
+
+LSpanLoop:
+
+//
+// set up the initial s/z, t/z, and 1/z on the FP stack, and generate the
+// initial s and t values
+//
+// FIXME: pipeline FILD?
+	fildl	sspan_t_v(%ebx)
+	fildl	sspan_t_u(%ebx)
+
+	fld		%st(1)			// dv | du | dv
+	fmuls	C(d_sdivzstepv)	// dv*d_sdivzstepv | du | dv
+	fld		%st(1)			// du | dv*d_sdivzstepv | du | dv
+	fmuls	C(d_sdivzstepu)	// du*d_sdivzstepu | dv*d_sdivzstepv | du | dv
+	fld		%st(2)			// du | du*d_sdivzstepu | dv*d_sdivzstepv | du | dv
+	fmuls	C(d_tdivzstepu)	// du*d_tdivzstepu | du*d_sdivzstepu |
+							//  dv*d_sdivzstepv | du | dv
+	fxch	%st(1)			// du*d_sdivzstepu | du*d_tdivzstepu |
+							//  dv*d_sdivzstepv | du | dv
+	faddp	%st(0),%st(2)	// du*d_tdivzstepu |
+							//  du*d_sdivzstepu + dv*d_sdivzstepv | du | dv
+	fxch	%st(1)			// du*d_sdivzstepu + dv*d_sdivzstepv |
+							//  du*d_tdivzstepu | du | dv
+	fld		%st(3)			// dv | du*d_sdivzstepu + dv*d_sdivzstepv |
+							//  du*d_tdivzstepu | du | dv
+	fmuls	C(d_tdivzstepv)	// dv*d_tdivzstepv |
+							//  du*d_sdivzstepu + dv*d_sdivzstepv |
+							//  du*d_tdivzstepu | du | dv
+	fxch	%st(1)			// du*d_sdivzstepu + dv*d_sdivzstepv |
+							//  dv*d_tdivzstepv | du*d_tdivzstepu | du | dv
+	fadds	C(d_sdivzorigin) // sdivz = d_sdivzorigin + dv*d_sdivzstepv +
+							//  du*d_sdivzstepu; stays in %st(2) at end
+	fxch	%st(4)			// dv | dv*d_tdivzstepv | du*d_tdivzstepu | du |
+							//  s/z
+	fmuls	C(d_zistepv)		// dv*d_zistepv | dv*d_tdivzstepv |
+							//  du*d_tdivzstepu | du | s/z
+	fxch	%st(1)			// dv*d_tdivzstepv |  dv*d_zistepv |
+							//  du*d_tdivzstepu | du | s/z
+	faddp	%st(0),%st(2)	// dv*d_zistepv |
+							//  dv*d_tdivzstepv + du*d_tdivzstepu | du | s/z
+	fxch	%st(2)			// du | dv*d_tdivzstepv + du*d_tdivzstepu |
+							//  dv*d_zistepv | s/z
+	fmuls	C(d_zistepu)		// du*d_zistepu |
+							//  dv*d_tdivzstepv + du*d_tdivzstepu |
+							//  dv*d_zistepv | s/z
+	fxch	%st(1)			// dv*d_tdivzstepv + du*d_tdivzstepu |
+							//  du*d_zistepu | dv*d_zistepv | s/z
+	fadds	C(d_tdivzorigin)	// tdivz = d_tdivzorigin + dv*d_tdivzstepv +
+							//  du*d_tdivzstepu; stays in %st(1) at end
+	fxch	%st(2)			// dv*d_zistepv | du*d_zistepu | t/z | s/z
+	faddp	%st(0),%st(1)	// dv*d_zistepv + du*d_zistepu | t/z | s/z
+
+	flds	fp_64k			// fp_64k | dv*d_zistepv + du*d_zistepu | t/z | s/z
+	fxch	%st(1)			// dv*d_zistepv + du*d_zistepu | fp_64k | t/z | s/z
+	fadds	C(d_ziorigin)		// zi = d_ziorigin + dv*d_zistepv +
+							//  du*d_zistepu; stays in %st(0) at end
+							// 1/z | fp_64k | t/z | s/z
+
+	fld		%st(0)			// FIXME: get rid of stall on FMUL?
+	fmuls	fp_64kx64k
+	fxch	%st(1)
+
+//
+// calculate and clamp s & t
+//
+	fdivr	%st(0),%st(2)	// 1/z | z*64k | t/z | s/z
+	fxch	%st(1)
+
+	fistpl	izi				// 0.32 fixed-point 1/z
+	movl	izi,%ebp
+
+//
+// set pz to point to the first z-buffer pixel in the span
+//
+	rorl	$16,%ebp		// put upper 16 bits in low word
+	movl	sspan_t_v(%ebx),%eax
+	movl	%ebp,izi
+	movl	sspan_t_u(%ebx),%ebp
+	imull	C(d_zrowbytes)
+	shll	$1,%ebp					// a word per pixel
+	addl	C(d_pzbuffer),%eax
+	addl	%ebp,%eax
+	movl	%eax,pz
+
+//
+// point %edi to the first pixel in the span
+//
+	movl	C(d_viewbuffer),%ebp
+	movl	sspan_t_v(%ebx),%eax
+	pushl	%ebx		// preserve spans pointer
+	movl	C(tadjust),%edx
+	movl	C(sadjust),%esi
+	movl	C(d_scantable)(,%eax,4),%edi	// v * screenwidth
+	addl	%ebp,%edi
+	movl	sspan_t_u(%ebx),%ebp
+	addl	%ebp,%edi				// pdest = &pdestspan[scans->u];
+
+//
+// now start the FDIV for the end of the span
+//
+	cmpl	$8,%ecx
+	ja		LSetupNotLast1
+
+	decl	%ecx
+	jz		LCleanup1		// if only one pixel, no need to start an FDIV
+	movl	%ecx,spancountminus1
+
+// finish up the s and t calcs
+	fxch	%st(1)			// z*64k | 1/z | t/z | s/z
+
+	fld		%st(0)			// z*64k | z*64k | 1/z | t/z | s/z
+	fmul	%st(4),%st(0)	// s | z*64k | 1/z | t/z | s/z
+	fxch	%st(1)			// z*64k | s | 1/z | t/z | s/z
+	fmul	%st(3),%st(0)	// t | s | 1/z | t/z | s/z
+	fxch	%st(1)			// s | t | 1/z | t/z | s/z
+	fistpl	s				// 1/z | t | t/z | s/z
+	fistpl	t				// 1/z | t/z | s/z
+
+	fildl	spancountminus1
+
+	flds	C(d_tdivzstepu)	// _d_tdivzstepu | spancountminus1
+	flds	C(d_zistepu)	// _d_zistepu | _d_tdivzstepu | spancountminus1
+	fmul	%st(2),%st(0)	// _d_zistepu*scm1 | _d_tdivzstepu | scm1
+	fxch	%st(1)			// _d_tdivzstepu | _d_zistepu*scm1 | scm1
+	fmul	%st(2),%st(0)	// _d_tdivzstepu*scm1 | _d_zistepu*scm1 | scm1
+	fxch	%st(2)			// scm1 | _d_zistepu*scm1 | _d_tdivzstepu*scm1
+	fmuls	C(d_sdivzstepu)	// _d_sdivzstepu*scm1 | _d_zistepu*scm1 |
+							//  _d_tdivzstepu*scm1
+	fxch	%st(1)			// _d_zistepu*scm1 | _d_sdivzstepu*scm1 |
+							//  _d_tdivzstepu*scm1
+	faddp	%st(0),%st(3)	// _d_sdivzstepu*scm1 | _d_tdivzstepu*scm1
+	fxch	%st(1)			// _d_tdivzstepu*scm1 | _d_sdivzstepu*scm1
+	faddp	%st(0),%st(3)	// _d_sdivzstepu*scm1
+	faddp	%st(0),%st(3)
+
+	flds	fp_64k
+	fdiv	%st(1),%st(0)	// this is what we've gone to all this trouble to
+							//  overlap
+	jmp		LFDIVInFlight1
+
+LCleanup1:
+// finish up the s and t calcs
+	fxch	%st(1)			// z*64k | 1/z | t/z | s/z
+
+	fld		%st(0)			// z*64k | z*64k | 1/z | t/z | s/z
+	fmul	%st(4),%st(0)	// s | z*64k | 1/z | t/z | s/z
+	fxch	%st(1)			// z*64k | s | 1/z | t/z | s/z
+	fmul	%st(3),%st(0)	// t | s | 1/z | t/z | s/z
+	fxch	%st(1)			// s | t | 1/z | t/z | s/z
+	fistpl	s				// 1/z | t | t/z | s/z
+	fistpl	t				// 1/z | t/z | s/z
+	jmp		LFDIVInFlight1
+
+	.align	4
+LSetupNotLast1:
+// finish up the s and t calcs
+	fxch	%st(1)			// z*64k | 1/z | t/z | s/z
+
+	fld		%st(0)			// z*64k | z*64k | 1/z | t/z | s/z
+	fmul	%st(4),%st(0)	// s | z*64k | 1/z | t/z | s/z
+	fxch	%st(1)			// z*64k | s | 1/z | t/z | s/z
+	fmul	%st(3),%st(0)	// t | s | 1/z | t/z | s/z
+	fxch	%st(1)			// s | t | 1/z | t/z | s/z
+	fistpl	s				// 1/z | t | t/z | s/z
+	fistpl	t				// 1/z | t/z | s/z
+
+	fadds	zi8stepu
+	fxch	%st(2)
+	fadds	sdivz8stepu
+	fxch	%st(2)
+	flds	tdivz8stepu
+	faddp	%st(0),%st(2)
+	flds	fp_64k
+	fdiv	%st(1),%st(0)	// z = 1/1/z
+							// this is what we've gone to all this trouble to
+							//  overlap
+LFDIVInFlight1:
+
+	addl	s,%esi
+	addl	t,%edx
+	movl	C(bbextents),%ebx
+	movl	C(bbextentt),%ebp
+	cmpl	%ebx,%esi
+	ja		LClampHighOrLow0
+LClampReentry0:
+	movl	%esi,s
+	movl	pbase,%ebx
+	shll	$16,%esi
+	cmpl	%ebp,%edx
+	movl	%esi,sfracf
+	ja		LClampHighOrLow1
+LClampReentry1:
+	movl	%edx,t
+	movl	s,%esi					// sfrac = scans->sfrac;
+	shll	$16,%edx
+	movl	t,%eax					// tfrac = scans->tfrac;
+	sarl	$16,%esi
+	movl	%edx,tfracf
+
+//
+// calculate the texture starting address
+//
+	sarl	$16,%eax
+	addl	%ebx,%esi
+	imull	C(cachewidth),%eax		// (tfrac >> 16) * cachewidth
+	addl	%eax,%esi				// psource = pbase + (sfrac >> 16) +
+									//           ((tfrac >> 16) * cachewidth);
+
+//
+// determine whether last span or not
+//
+	cmpl	$8,%ecx
+	jna		LLastSegment
+
+//
+// not the last segment; do full 8-wide segment
+//
+LNotLastSegment:
+
+//
+// advance s/z, t/z, and 1/z, and calculate s & t at end of span and steps to
+// get there
+//
+
+// pick up after the FDIV that was left in flight previously
+
+	fld		%st(0)			// duplicate it
+	fmul	%st(4),%st(0)	// s = s/z * z
+	fxch	%st(1)
+	fmul	%st(3),%st(0)	// t = t/z * z
+	fxch	%st(1)
+	fistpl	snext
+	fistpl	tnext
+	movl	snext,%eax
+	movl	tnext,%edx
+
+	subl	$8,%ecx		// count off this segments' pixels
+	movl	C(sadjust),%ebp
+	pushl	%ecx		// remember count of remaining pixels
+	movl	C(tadjust),%ecx
+
+	addl	%eax,%ebp
+	addl	%edx,%ecx
+
+	movl	C(bbextents),%eax
+	movl	C(bbextentt),%edx
+
+	cmpl	$2048,%ebp
+	jl		LClampLow2
+	cmpl	%eax,%ebp
+	ja		LClampHigh2
+LClampReentry2:
+
+	cmpl	$2048,%ecx
+	jl		LClampLow3
+	cmpl	%edx,%ecx
+	ja		LClampHigh3
+LClampReentry3:
+
+	movl	%ebp,snext
+	movl	%ecx,tnext
+
+	subl	s,%ebp
+	subl	t,%ecx
+	
+//
+// set up advancetable
+//
+	movl	%ecx,%eax
+	movl	%ebp,%edx
+	sarl	$19,%edx			// sstep >>= 16;
+	movl	C(cachewidth),%ebx
+	sarl	$19,%eax			// tstep >>= 16;
+	jz		LIsZero
+	imull	%ebx,%eax			// (tstep >> 16) * cachewidth;
+LIsZero:
+	addl	%edx,%eax			// add in sstep
+								// (tstep >> 16) * cachewidth + (sstep >> 16);
+	movl	tfracf,%edx
+	movl	%eax,advancetable+4	// advance base in t
+	addl	%ebx,%eax			// ((tstep >> 16) + 1) * cachewidth +
+								//  (sstep >> 16);
+	shll	$13,%ebp			// left-justify sstep fractional part
+	movl	%ebp,sstep
+	movl	sfracf,%ebx
+	shll	$13,%ecx			// left-justify tstep fractional part
+	movl	%eax,advancetable	// advance extra in t
+	movl	%ecx,tstep
+
+	movl	pz,%ecx
+	movl	izi,%ebp
+
+	cmpw	(%ecx),%bp
+	jl		Lp1
+	movb	(%esi),%al			// get first source texel
+	cmpb	$(TRANSPARENT_COLOR),%al
+	jz		Lp1
+	movw	%bp,(%ecx)
+	movb	%al,(%edi)			// store first dest pixel
+Lp1:
+	addl	izistep,%ebp
+	adcl	$0,%ebp
+	addl	tstep,%edx			// advance tfrac fractional part by tstep frac
+
+	sbbl	%eax,%eax			// turn tstep carry into -1 (0 if none)
+	addl	sstep,%ebx			// advance sfrac fractional part by sstep frac
+	adcl	advancetable+4(,%eax,4),%esi	// point to next source texel
+
+	cmpw	2(%ecx),%bp
+	jl		Lp2
+	movb	(%esi),%al
+	cmpb	$(TRANSPARENT_COLOR),%al
+	jz		Lp2
+	movw	%bp,2(%ecx)
+	movb	%al,1(%edi)
+Lp2:
+	addl	izistep,%ebp
+	adcl	$0,%ebp
+	addl	tstep,%edx
+	sbbl	%eax,%eax
+	addl	sstep,%ebx
+	adcl	advancetable+4(,%eax,4),%esi
+
+	cmpw	4(%ecx),%bp
+	jl		Lp3
+	movb	(%esi),%al
+	cmpb	$(TRANSPARENT_COLOR),%al
+	jz		Lp3
+	movw	%bp,4(%ecx)
+	movb	%al,2(%edi)
+Lp3:
+	addl	izistep,%ebp
+	adcl	$0,%ebp
+	addl	tstep,%edx
+	sbbl	%eax,%eax
+	addl	sstep,%ebx
+	adcl	advancetable+4(,%eax,4),%esi
+
+	cmpw	6(%ecx),%bp
+	jl		Lp4
+	movb	(%esi),%al
+	cmpb	$(TRANSPARENT_COLOR),%al
+	jz		Lp4
+	movw	%bp,6(%ecx)
+	movb	%al,3(%edi)
+Lp4:
+	addl	izistep,%ebp
+	adcl	$0,%ebp
+	addl	tstep,%edx
+	sbbl	%eax,%eax
+	addl	sstep,%ebx
+	adcl	advancetable+4(,%eax,4),%esi
+
+	cmpw	8(%ecx),%bp
+	jl		Lp5
+	movb	(%esi),%al
+	cmpb	$(TRANSPARENT_COLOR),%al
+	jz		Lp5
+	movw	%bp,8(%ecx)
+	movb	%al,4(%edi)
+Lp5:
+	addl	izistep,%ebp
+	adcl	$0,%ebp
+	addl	tstep,%edx
+	sbbl	%eax,%eax
+	addl	sstep,%ebx
+	adcl	advancetable+4(,%eax,4),%esi
+
+//
+// start FDIV for end of next segment in flight, so it can overlap
+//
+	popl	%eax
+	cmpl	$8,%eax			// more than one segment after this?
+	ja		LSetupNotLast2	// yes
+
+	decl	%eax
+	jz		LFDIVInFlight2	// if only one pixel, no need to start an FDIV
+	movl	%eax,spancountminus1
+	fildl	spancountminus1
+
+	flds	C(d_zistepu)		// _d_zistepu | spancountminus1
+	fmul	%st(1),%st(0)	// _d_zistepu*scm1 | scm1
+	flds	C(d_tdivzstepu)	// _d_tdivzstepu | _d_zistepu*scm1 | scm1
+	fmul	%st(2),%st(0)	// _d_tdivzstepu*scm1 | _d_zistepu*scm1 | scm1
+	fxch	%st(1)			// _d_zistepu*scm1 | _d_tdivzstepu*scm1 | scm1
+	faddp	%st(0),%st(3)	// _d_tdivzstepu*scm1 | scm1
+	fxch	%st(1)			// scm1 | _d_tdivzstepu*scm1
+	fmuls	C(d_sdivzstepu)	// _d_sdivzstepu*scm1 | _d_tdivzstepu*scm1
+	fxch	%st(1)			// _d_tdivzstepu*scm1 | _d_sdivzstepu*scm1
+	faddp	%st(0),%st(3)	// _d_sdivzstepu*scm1
+	flds	fp_64k			// 64k | _d_sdivzstepu*scm1
+	fxch	%st(1)			// _d_sdivzstepu*scm1 | 64k
+	faddp	%st(0),%st(4)	// 64k
+
+	fdiv	%st(1),%st(0)	// this is what we've gone to all this trouble to
+							//  overlap
+	jmp		LFDIVInFlight2
+
+	.align	4
+LSetupNotLast2:
+	fadds	zi8stepu
+	fxch	%st(2)
+	fadds	sdivz8stepu
+	fxch	%st(2)
+	flds	tdivz8stepu
+	faddp	%st(0),%st(2)
+	flds	fp_64k
+	fdiv	%st(1),%st(0)	// z = 1/1/z
+							// this is what we've gone to all this trouble to
+							//  overlap
+LFDIVInFlight2:
+	pushl	%eax
+
+	cmpw	10(%ecx),%bp
+	jl		Lp6
+	movb	(%esi),%al
+	cmpb	$(TRANSPARENT_COLOR),%al
+	jz		Lp6
+	movw	%bp,10(%ecx)
+	movb	%al,5(%edi)
+Lp6:
+	addl	izistep,%ebp
+	adcl	$0,%ebp
+	addl	tstep,%edx
+	sbbl	%eax,%eax
+	addl	sstep,%ebx
+	adcl	advancetable+4(,%eax,4),%esi
+
+	cmpw	12(%ecx),%bp
+	jl		Lp7
+	movb	(%esi),%al
+	cmpb	$(TRANSPARENT_COLOR),%al
+	jz		Lp7
+	movw	%bp,12(%ecx)
+	movb	%al,6(%edi)
+Lp7:
+	addl	izistep,%ebp
+	adcl	$0,%ebp
+	addl	tstep,%edx
+	sbbl	%eax,%eax
+	addl	sstep,%ebx
+	adcl	advancetable+4(,%eax,4),%esi
+
+	cmpw	14(%ecx),%bp
+	jl		Lp8
+	movb	(%esi),%al
+	cmpb	$(TRANSPARENT_COLOR),%al
+	jz		Lp8
+	movw	%bp,14(%ecx)
+	movb	%al,7(%edi)
+Lp8:
+	addl	izistep,%ebp
+	adcl	$0,%ebp
+	addl	tstep,%edx
+	sbbl	%eax,%eax
+	addl	sstep,%ebx
+	adcl	advancetable+4(,%eax,4),%esi
+
+	addl	$8,%edi
+	addl	$16,%ecx
+	movl	%edx,tfracf
+	movl	snext,%edx
+	movl	%ebx,sfracf
+	movl	tnext,%ebx
+	movl	%edx,s
+	movl	%ebx,t
+
+	movl	%ecx,pz
+	movl	%ebp,izi
+
+	popl	%ecx				// retrieve count
+
+//
+// determine whether last span or not
+//
+	cmpl	$8,%ecx				// are there multiple segments remaining?
+	ja		LNotLastSegment		// yes
+
+//
+// last segment of scan
+//
+LLastSegment:
+
+//
+// advance s/z, t/z, and 1/z, and calculate s & t at end of span and steps to
+// get there. The number of pixels left is variable, and we want to land on the
+// last pixel, not step one past it, so we can't run into arithmetic problems
+//
+	testl	%ecx,%ecx
+	jz		LNoSteps		// just draw the last pixel and we're done
+
+// pick up after the FDIV that was left in flight previously
+
+
+	fld		%st(0)			// duplicate it
+	fmul	%st(4),%st(0)	// s = s/z * z
+	fxch	%st(1)
+	fmul	%st(3),%st(0)	// t = t/z * z
+	fxch	%st(1)
+	fistpl	snext
+	fistpl	tnext
+
+	movl	C(tadjust),%ebx
+	movl	C(sadjust),%eax
+
+	addl	snext,%eax
+	addl	tnext,%ebx
+
+	movl	C(bbextents),%ebp
+	movl	C(bbextentt),%edx
+
+	cmpl	$2048,%eax
+	jl		LClampLow4
+	cmpl	%ebp,%eax
+	ja		LClampHigh4
+LClampReentry4:
+	movl	%eax,snext
+
+	cmpl	$2048,%ebx
+	jl		LClampLow5
+	cmpl	%edx,%ebx
+	ja		LClampHigh5
+LClampReentry5:
+
+	cmpl	$1,%ecx			// don't bother 
+	je		LOnlyOneStep	// if two pixels in segment, there's only one step,
+							//  of the segment length
+	subl	s,%eax
+	subl	t,%ebx
+
+	addl	%eax,%eax		// convert to 15.17 format so multiply by 1.31
+	addl	%ebx,%ebx		//  reciprocal yields 16.48
+	imull	reciprocal_table-8(,%ecx,4) // sstep = (snext - s) / (spancount-1)
+	movl	%edx,%ebp
+
+	movl	%ebx,%eax
+	imull	reciprocal_table-8(,%ecx,4) // tstep = (tnext - t) / (spancount-1)
+
+LSetEntryvec:
+//
+// set up advancetable
+//
+	movl	spr8entryvec_table(,%ecx,4),%ebx
+	movl	%edx,%eax
+	pushl	%ebx				// entry point into code for RET later
+	movl	%ebp,%ecx
+	sarl	$16,%ecx			// sstep >>= 16;
+	movl	C(cachewidth),%ebx
+	sarl	$16,%edx			// tstep >>= 16;
+	jz		LIsZeroLast
+	imull	%ebx,%edx			// (tstep >> 16) * cachewidth;
+LIsZeroLast:
+	addl	%ecx,%edx			// add in sstep
+								// (tstep >> 16) * cachewidth + (sstep >> 16);
+	movl	tfracf,%ecx
+	movl	%edx,advancetable+4	// advance base in t
+	addl	%ebx,%edx			// ((tstep >> 16) + 1) * cachewidth +
+								//  (sstep >> 16);
+	shll	$16,%ebp			// left-justify sstep fractional part
+	movl	sfracf,%ebx
+	shll	$16,%eax			// left-justify tstep fractional part
+	movl	%edx,advancetable	// advance extra in t
+
+	movl	%eax,tstep
+	movl	%ebp,sstep
+	movl	%ecx,%edx
+
+	movl	pz,%ecx
+	movl	izi,%ebp
+
+	ret							// jump to the number-of-pixels handler
+
+//----------------------------------------
+
+LNoSteps:
+	movl	pz,%ecx
+	subl	$7,%edi			// adjust for hardwired offset
+	subl	$14,%ecx
+	jmp		LEndSpan
+
+
+LOnlyOneStep:
+	subl	s,%eax
+	subl	t,%ebx
+	movl	%eax,%ebp
+	movl	%ebx,%edx
+	jmp		LSetEntryvec
+
+//----------------------------------------
+
+.globl	Spr8Entry2_8
+Spr8Entry2_8:
+	subl	$6,%edi		// adjust for hardwired offsets
+	subl	$12,%ecx
+	movb	(%esi),%al
+	jmp		LLEntry2_8
+
+//----------------------------------------
+
+.globl	Spr8Entry3_8
+Spr8Entry3_8:
+	subl	$5,%edi		// adjust for hardwired offsets
+	subl	$10,%ecx
+	jmp		LLEntry3_8
+
+//----------------------------------------
+
+.globl	Spr8Entry4_8
+Spr8Entry4_8:
+	subl	$4,%edi		// adjust for hardwired offsets
+	subl	$8,%ecx
+	jmp		LLEntry4_8
+
+//----------------------------------------
+
+.globl	Spr8Entry5_8
+Spr8Entry5_8:
+	subl	$3,%edi		// adjust for hardwired offsets
+	subl	$6,%ecx
+	jmp		LLEntry5_8
+
+//----------------------------------------
+
+.globl	Spr8Entry6_8
+Spr8Entry6_8:
+	subl	$2,%edi		// adjust for hardwired offsets
+	subl	$4,%ecx
+	jmp		LLEntry6_8
+
+//----------------------------------------
+
+.globl	Spr8Entry7_8
+Spr8Entry7_8:
+	decl	%edi		// adjust for hardwired offsets
+	subl	$2,%ecx
+	jmp		LLEntry7_8
+
+//----------------------------------------
+
+.globl	Spr8Entry8_8
+Spr8Entry8_8:
+	cmpw	(%ecx),%bp
+	jl		Lp9
+	movb	(%esi),%al
+	cmpb	$(TRANSPARENT_COLOR),%al
+	jz		Lp9
+	movw	%bp,(%ecx)
+	movb	%al,(%edi)
+Lp9:
+	addl	izistep,%ebp
+	adcl	$0,%ebp
+	addl	tstep,%edx
+	sbbl	%eax,%eax
+	addl	sstep,%ebx
+	adcl	advancetable+4(,%eax,4),%esi
+LLEntry7_8:
+	cmpw	2(%ecx),%bp
+	jl		Lp10
+	movb	(%esi),%al
+	cmpb	$(TRANSPARENT_COLOR),%al
+	jz		Lp10
+	movw	%bp,2(%ecx)
+	movb	%al,1(%edi)
+Lp10:
+	addl	izistep,%ebp
+	adcl	$0,%ebp
+	addl	tstep,%edx
+	sbbl	%eax,%eax
+	addl	sstep,%ebx
+	adcl	advancetable+4(,%eax,4),%esi
+LLEntry6_8:
+	cmpw	4(%ecx),%bp
+	jl		Lp11
+	movb	(%esi),%al
+	cmpb	$(TRANSPARENT_COLOR),%al
+	jz		Lp11
+	movw	%bp,4(%ecx)
+	movb	%al,2(%edi)
+Lp11:
+	addl	izistep,%ebp
+	adcl	$0,%ebp
+	addl	tstep,%edx
+	sbbl	%eax,%eax
+	addl	sstep,%ebx
+	adcl	advancetable+4(,%eax,4),%esi
+LLEntry5_8:
+	cmpw	6(%ecx),%bp
+	jl		Lp12
+	movb	(%esi),%al
+	cmpb	$(TRANSPARENT_COLOR),%al
+	jz		Lp12
+	movw	%bp,6(%ecx)
+	movb	%al,3(%edi)
+Lp12:
+	addl	izistep,%ebp
+	adcl	$0,%ebp
+	addl	tstep,%edx
+	sbbl	%eax,%eax
+	addl	sstep,%ebx
+	adcl	advancetable+4(,%eax,4),%esi
+LLEntry4_8:
+	cmpw	8(%ecx),%bp
+	jl		Lp13
+	movb	(%esi),%al
+	cmpb	$(TRANSPARENT_COLOR),%al
+	jz		Lp13
+	movw	%bp,8(%ecx)
+	movb	%al,4(%edi)
+Lp13:
+	addl	izistep,%ebp
+	adcl	$0,%ebp
+	addl	tstep,%edx
+	sbbl	%eax,%eax
+	addl	sstep,%ebx
+	adcl	advancetable+4(,%eax,4),%esi
+LLEntry3_8:
+	cmpw	10(%ecx),%bp
+	jl		Lp14
+	movb	(%esi),%al
+	cmpb	$(TRANSPARENT_COLOR),%al
+	jz		Lp14
+	movw	%bp,10(%ecx)
+	movb	%al,5(%edi)
+Lp14:
+	addl	izistep,%ebp
+	adcl	$0,%ebp
+	addl	tstep,%edx
+	sbbl	%eax,%eax
+	addl	sstep,%ebx
+	adcl	advancetable+4(,%eax,4),%esi
+LLEntry2_8:
+	cmpw	12(%ecx),%bp
+	jl		Lp15
+	movb	(%esi),%al
+	cmpb	$(TRANSPARENT_COLOR),%al
+	jz		Lp15
+	movw	%bp,12(%ecx)
+	movb	%al,6(%edi)
+Lp15:
+	addl	izistep,%ebp
+	adcl	$0,%ebp
+	addl	tstep,%edx
+	sbbl	%eax,%eax
+	addl	sstep,%ebx
+	adcl	advancetable+4(,%eax,4),%esi
+
+LEndSpan:
+	cmpw	14(%ecx),%bp
+	jl		Lp16
+	movb	(%esi),%al		// load first texel in segment
+	cmpb	$(TRANSPARENT_COLOR),%al
+	jz		Lp16
+	movw	%bp,14(%ecx)
+	movb	%al,7(%edi)
+Lp16:
+
+//
+// clear s/z, t/z, 1/z from FP stack
+//
+	fstp %st(0)
+	fstp %st(0)
+	fstp %st(0)
+
+	popl	%ebx				// restore spans pointer
+LNextSpan:
+	addl	$(sspan_t_size),%ebx // point to next span
+	movl	sspan_t_count(%ebx),%ecx
+	cmpl	$0,%ecx				// any more spans?
+	jg		LSpanLoop			// yes
+	jz		LNextSpan			// yes, but this one's empty
+
+	popl	%ebx				// restore register variables
+	popl	%esi
+	popl	%edi
+	popl	%ebp				// restore the caller's stack frame
+	ret
+
+#endif	// id386
--- /dev/null
+++ b/QW/client/d_sprite.c
@@ -1,0 +1,442 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// d_sprite.c: software top-level rasterization driver module for drawing
+// sprites
+
+#include "quakedef.h"
+#include "d_local.h"
+
+static int		sprite_height;
+static int		minindex, maxindex;
+static sspan_t	*sprite_spans;
+
+#if	!id386
+
+/*
+=====================
+D_SpriteDrawSpans
+=====================
+*/
+void D_SpriteDrawSpans (sspan_t *pspan)
+{
+	int			count, spancount, izistep;
+	int			izi;
+	byte		*pbase, *pdest;
+	fixed16_t	s, t, snext, tnext, sstep, tstep;
+	float		sdivz, tdivz, zi, z, du, dv, spancountminus1;
+	float		sdivz8stepu, tdivz8stepu, zi8stepu;
+	byte		btemp;
+	short		*pz;
+
+	sstep = 0;	// keep compiler happy
+	tstep = 0;	// ditto
+
+	pbase = cacheblock;
+
+	sdivz8stepu = d_sdivzstepu * 8;
+	tdivz8stepu = d_tdivzstepu * 8;
+	zi8stepu = d_zistepu * 8;
+
+// we count on FP exceptions being turned off to avoid range problems
+	izistep = (int)(d_zistepu * 0x8000 * 0x10000);
+
+	do
+	{
+		pdest = (byte *)d_viewbuffer + (screenwidth * pspan->v) + pspan->u;
+		pz = d_pzbuffer + (d_zwidth * pspan->v) + pspan->u;
+
+		count = pspan->count;
+
+		if (count <= 0)
+			goto NextSpan;
+
+	// calculate the initial s/z, t/z, 1/z, s, and t and clamp
+		du = (float)pspan->u;
+		dv = (float)pspan->v;
+
+		sdivz = d_sdivzorigin + dv*d_sdivzstepv + du*d_sdivzstepu;
+		tdivz = d_tdivzorigin + dv*d_tdivzstepv + du*d_tdivzstepu;
+		zi = d_ziorigin + dv*d_zistepv + du*d_zistepu;
+		z = (float)0x10000 / zi;	// prescale to 16.16 fixed-point
+	// we count on FP exceptions being turned off to avoid range problems
+		izi = (int)(zi * 0x8000 * 0x10000);
+
+		s = (int)(sdivz * z) + sadjust;
+		if (s > bbextents)
+			s = bbextents;
+		else if (s < 0)
+			s = 0;
+
+		t = (int)(tdivz * z) + tadjust;
+		if (t > bbextentt)
+			t = bbextentt;
+		else if (t < 0)
+			t = 0;
+
+		do
+		{
+		// calculate s and t at the far end of the span
+			if (count >= 8)
+				spancount = 8;
+			else
+				spancount = count;
+
+			count -= spancount;
+
+			if (count)
+			{
+			// calculate s/z, t/z, zi->fixed s and t at far end of span,
+			// calculate s and t steps across span by shifting
+				sdivz += sdivz8stepu;
+				tdivz += tdivz8stepu;
+				zi += zi8stepu;
+				z = (float)0x10000 / zi;	// prescale to 16.16 fixed-point
+
+				snext = (int)(sdivz * z) + sadjust;
+				if (snext > bbextents)
+					snext = bbextents;
+				else if (snext < 8)
+					snext = 8;	// prevent round-off error on <0 steps from
+								//  from causing overstepping & running off the
+								//  edge of the texture
+
+				tnext = (int)(tdivz * z) + tadjust;
+				if (tnext > bbextentt)
+					tnext = bbextentt;
+				else if (tnext < 8)
+					tnext = 8;	// guard against round-off error on <0 steps
+
+				sstep = (snext - s) >> 3;
+				tstep = (tnext - t) >> 3;
+			}
+			else
+			{
+			// calculate s/z, t/z, zi->fixed s and t at last pixel in span (so
+			// can't step off polygon), clamp, calculate s and t steps across
+			// span by division, biasing steps low so we don't run off the
+			// texture
+				spancountminus1 = (float)(spancount - 1);
+				sdivz += d_sdivzstepu * spancountminus1;
+				tdivz += d_tdivzstepu * spancountminus1;
+				zi += d_zistepu * spancountminus1;
+				z = (float)0x10000 / zi;	// prescale to 16.16 fixed-point
+				snext = (int)(sdivz * z) + sadjust;
+				if (snext > bbextents)
+					snext = bbextents;
+				else if (snext < 8)
+					snext = 8;	// prevent round-off error on <0 steps from
+								//  from causing overstepping & running off the
+								//  edge of the texture
+
+				tnext = (int)(tdivz * z) + tadjust;
+				if (tnext > bbextentt)
+					tnext = bbextentt;
+				else if (tnext < 8)
+					tnext = 8;	// guard against round-off error on <0 steps
+
+				if (spancount > 1)
+				{
+					sstep = (snext - s) / (spancount - 1);
+					tstep = (tnext - t) / (spancount - 1);
+				}
+			}
+
+			do
+			{
+				btemp = *(pbase + (s >> 16) + (t >> 16) * cachewidth);
+				if (btemp != 255)
+				{
+					if (*pz <= (izi >> 16))
+					{
+						*pz = izi >> 16;
+						*pdest = btemp;
+					}
+				}
+
+				izi += izistep;
+				pdest++;
+				pz++;
+				s += sstep;
+				t += tstep;
+			} while (--spancount > 0);
+
+			s = snext;
+			t = tnext;
+
+		} while (count > 0);
+
+NextSpan:
+		pspan++;
+
+	} while (pspan->count != DS_SPAN_LIST_END);
+}
+
+#endif
+
+
+/*
+=====================
+D_SpriteScanLeftEdge
+=====================
+*/
+void D_SpriteScanLeftEdge (void)
+{
+	int			i, v, itop, ibottom, lmaxindex;
+	emitpoint_t	*pvert, *pnext;
+	sspan_t		*pspan;
+	float		du, dv, vtop, vbottom, slope;
+	fixed16_t	u, u_step;
+
+	pspan = sprite_spans;
+	i = minindex;
+	if (i == 0)
+		i = r_spritedesc.nump;
+
+	lmaxindex = maxindex;
+	if (lmaxindex == 0)
+		lmaxindex = r_spritedesc.nump;
+
+	vtop = ceil (r_spritedesc.pverts[i].v);
+
+	do
+	{
+		pvert = &r_spritedesc.pverts[i];
+		pnext = pvert - 1;
+
+		vbottom = ceil (pnext->v);
+
+		if (vtop < vbottom)
+		{
+			du = pnext->u - pvert->u;
+			dv = pnext->v - pvert->v;
+			slope = du / dv;
+			u_step = (int)(slope * 0x10000);
+		// adjust u to ceil the integer portion
+			u = (int)((pvert->u + (slope * (vtop - pvert->v))) * 0x10000) +
+					(0x10000 - 1);
+			itop = (int)vtop;
+			ibottom = (int)vbottom;
+
+			for (v=itop ; v<ibottom ; v++)
+			{
+				pspan->u = u >> 16;
+				pspan->v = v;
+				u += u_step;
+				pspan++;
+			}
+		}
+
+		vtop = vbottom;
+
+		i--;
+		if (i == 0)
+			i = r_spritedesc.nump;
+
+	} while (i != lmaxindex);
+}
+
+
+/*
+=====================
+D_SpriteScanRightEdge
+=====================
+*/
+void D_SpriteScanRightEdge (void)
+{
+	int			i, v, itop, ibottom;
+	emitpoint_t	*pvert, *pnext;
+	sspan_t		*pspan;
+	float		du, dv, vtop, vbottom, slope, uvert, unext, vvert, vnext;
+	fixed16_t	u, u_step;
+
+	pspan = sprite_spans;
+	i = minindex;
+
+	vvert = r_spritedesc.pverts[i].v;
+	if (vvert < r_refdef.fvrecty_adj)
+		vvert = r_refdef.fvrecty_adj;
+	if (vvert > r_refdef.fvrectbottom_adj)
+		vvert = r_refdef.fvrectbottom_adj;
+
+	vtop = ceil (vvert);
+
+	do
+	{
+		pvert = &r_spritedesc.pverts[i];
+		pnext = pvert + 1;
+
+		vnext = pnext->v;
+		if (vnext < r_refdef.fvrecty_adj)
+			vnext = r_refdef.fvrecty_adj;
+		if (vnext > r_refdef.fvrectbottom_adj)
+			vnext = r_refdef.fvrectbottom_adj;
+
+		vbottom = ceil (vnext);
+
+		if (vtop < vbottom)
+		{
+			uvert = pvert->u;
+			if (uvert < r_refdef.fvrectx_adj)
+				uvert = r_refdef.fvrectx_adj;
+			if (uvert > r_refdef.fvrectright_adj)
+				uvert = r_refdef.fvrectright_adj;
+
+			unext = pnext->u;
+			if (unext < r_refdef.fvrectx_adj)
+				unext = r_refdef.fvrectx_adj;
+			if (unext > r_refdef.fvrectright_adj)
+				unext = r_refdef.fvrectright_adj;
+
+			du = unext - uvert;
+			dv = vnext - vvert;
+			slope = du / dv;
+			u_step = (int)(slope * 0x10000);
+		// adjust u to ceil the integer portion
+			u = (int)((uvert + (slope * (vtop - vvert))) * 0x10000) +
+					(0x10000 - 1);
+			itop = (int)vtop;
+			ibottom = (int)vbottom;
+
+			for (v=itop ; v<ibottom ; v++)
+			{
+				pspan->count = (u >> 16) - pspan->u;
+				u += u_step;
+				pspan++;
+			}
+		}
+
+		vtop = vbottom;
+		vvert = vnext;
+
+		i++;
+		if (i == r_spritedesc.nump)
+			i = 0;
+
+	} while (i != maxindex);
+
+	pspan->count = DS_SPAN_LIST_END;	// mark the end of the span list 
+}
+
+
+/*
+=====================
+D_SpriteCalculateGradients
+=====================
+*/
+void D_SpriteCalculateGradients (void)
+{
+	vec3_t		p_normal, p_saxis, p_taxis, p_temp1;
+	float		distinv;
+
+	TransformVector (r_spritedesc.vpn, p_normal);
+	TransformVector (r_spritedesc.vright, p_saxis);
+	TransformVector (r_spritedesc.vup, p_taxis);
+	VectorInverse (p_taxis);
+
+	distinv = 1.0 / (-DotProduct (modelorg, r_spritedesc.vpn));
+
+	d_sdivzstepu = p_saxis[0] * xscaleinv;
+	d_tdivzstepu = p_taxis[0] * xscaleinv;
+
+	d_sdivzstepv = -p_saxis[1] * yscaleinv;
+	d_tdivzstepv = -p_taxis[1] * yscaleinv;
+
+	d_zistepu = p_normal[0] * xscaleinv * distinv;
+	d_zistepv = -p_normal[1] * yscaleinv * distinv;
+
+	d_sdivzorigin = p_saxis[2] - xcenter * d_sdivzstepu -
+			ycenter * d_sdivzstepv;
+	d_tdivzorigin = p_taxis[2] - xcenter * d_tdivzstepu -
+			ycenter * d_tdivzstepv;
+	d_ziorigin = p_normal[2] * distinv - xcenter * d_zistepu -
+			ycenter * d_zistepv;
+
+	TransformVector (modelorg, p_temp1);
+
+	sadjust = ((fixed16_t)(DotProduct (p_temp1, p_saxis) * 0x10000 + 0.5)) -
+			(-(cachewidth >> 1) << 16);
+	tadjust = ((fixed16_t)(DotProduct (p_temp1, p_taxis) * 0x10000 + 0.5)) -
+			(-(sprite_height >> 1) << 16);
+
+// -1 (-epsilon) so we never wander off the edge of the texture
+	bbextents = (cachewidth << 16) - 1;
+	bbextentt = (sprite_height << 16) - 1;
+}
+
+
+/*
+=====================
+D_DrawSprite
+=====================
+*/
+void D_DrawSprite (void)
+{
+	int			i, nump;
+	float		ymin, ymax;
+	emitpoint_t	*pverts;
+	sspan_t		spans[MAXHEIGHT+1];
+
+	sprite_spans = spans;
+
+// find the top and bottom vertices, and make sure there's at least one scan to
+// draw
+	ymin = 999999.9;
+	ymax = -999999.9;
+	pverts = r_spritedesc.pverts;
+
+	for (i=0 ; i<r_spritedesc.nump ; i++)
+	{
+		if (pverts->v < ymin)
+		{
+			ymin = pverts->v;
+			minindex = i;
+		}
+
+		if (pverts->v > ymax)
+		{
+			ymax = pverts->v;
+			maxindex = i;
+		}
+
+		pverts++;
+	}
+
+	ymin = ceil (ymin);
+	ymax = ceil (ymax);
+
+	if (ymin >= ymax)
+		return;		// doesn't cross any scans at all
+
+	cachewidth = r_spritedesc.pspriteframe->width;
+	sprite_height = r_spritedesc.pspriteframe->height;
+	cacheblock = (byte *)&r_spritedesc.pspriteframe->pixels[0];
+
+// copy the first vertex to the last vertex, so we don't have to deal with
+// wrapping
+	nump = r_spritedesc.nump;
+	pverts = r_spritedesc.pverts;
+	pverts[nump] = pverts[0];
+
+	D_SpriteCalculateGradients ();
+	D_SpriteScanLeftEdge ();
+	D_SpriteScanRightEdge ();
+	D_SpriteDrawSpans (sprite_spans);
+}
+
--- /dev/null
+++ b/QW/client/d_surf.c
@@ -1,0 +1,338 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// d_surf.c: rasterization driver surface heap manager
+
+#include "quakedef.h"
+#include "d_local.h"
+#include "r_local.h"
+
+float           surfscale;
+qboolean        r_cache_thrash;         // set if surface cache is thrashing
+
+int                                     sc_size;
+surfcache_t                     *sc_rover, *sc_base;
+
+#define GUARDSIZE       4
+
+
+int     D_SurfaceCacheForRes (int width, int height)
+{
+	int             size, pix;
+
+	if (COM_CheckParm ("-surfcachesize"))
+	{
+		size = Q_atoi(com_argv[COM_CheckParm("-surfcachesize")+1]) * 1024;
+		return size;
+	}
+	
+	size = SURFCACHE_SIZE_AT_320X200;
+
+	pix = width*height;
+	if (pix > 64000)
+		size += (pix-64000)*3;
+		
+
+	return size;
+}
+
+void D_CheckCacheGuard (void)
+{
+	byte    *s;
+	int             i;
+
+	s = (byte *)sc_base + sc_size;
+	for (i=0 ; i<GUARDSIZE ; i++)
+		if (s[i] != (byte)i)
+			Sys_Error ("D_CheckCacheGuard: failed");
+}
+
+void D_ClearCacheGuard (void)
+{
+	byte    *s;
+	int             i;
+	
+	s = (byte *)sc_base + sc_size;
+	for (i=0 ; i<GUARDSIZE ; i++)
+		s[i] = (byte)i;
+}
+
+
+/*
+================
+D_InitCaches
+
+================
+*/
+void D_InitCaches (void *buffer, int size)
+{
+//	if (!msg_suppress_1)
+//		Con_Printf ("%ik surface cache\n", size/1024);
+
+	sc_size = size - GUARDSIZE;
+	sc_base = (surfcache_t *)buffer;
+	sc_rover = sc_base;
+	
+	sc_base->next = NULL;
+	sc_base->owner = NULL;
+	sc_base->size = sc_size;
+	
+	D_ClearCacheGuard ();
+}
+
+
+/*
+==================
+D_FlushCaches
+==================
+*/
+void D_FlushCaches (void)
+{
+	surfcache_t     *c;
+	
+	if (!sc_base)
+		return;
+
+	for (c = sc_base ; c ; c = c->next)
+	{
+		if (c->owner)
+			*c->owner = NULL;
+	}
+	
+	sc_rover = sc_base;
+	sc_base->next = NULL;
+	sc_base->owner = NULL;
+	sc_base->size = sc_size;
+}
+
+/*
+=================
+D_SCAlloc
+=================
+*/
+surfcache_t     *D_SCAlloc (int width, int size)
+{
+	surfcache_t             *new;
+	qboolean                wrapped_this_time;
+
+	if ((width < 0) || (width > 256))
+		Sys_Error ("D_SCAlloc: bad cache width %d\n", width);
+
+	if ((size <= 0) || (size > 0x10000))
+		Sys_Error ("D_SCAlloc: bad cache size %d\n", size);
+	
+#ifdef __alpha__
+	size = (int)((long)&((surfcache_t *)0)->data[size]);
+#else
+	size = (int)&((surfcache_t *)0)->data[size];
+#endif
+	size = (size + 3) & ~3;
+	if (size > sc_size)
+		Sys_Error ("D_SCAlloc: %i > cache size",size);
+
+// if there is not size bytes after the rover, reset to the start
+	wrapped_this_time = false;
+
+	if ( !sc_rover || (byte *)sc_rover - (byte *)sc_base > sc_size - size)
+	{
+		if (sc_rover)
+		{
+			wrapped_this_time = true;
+		}
+		sc_rover = sc_base;
+	}
+		
+// colect and free surfcache_t blocks until the rover block is large enough
+	new = sc_rover;
+	if (sc_rover->owner)
+		*sc_rover->owner = NULL;
+	
+	while (new->size < size)
+	{
+	// free another
+		sc_rover = sc_rover->next;
+		if (!sc_rover)
+			Sys_Error ("D_SCAlloc: hit the end of memory");
+		if (sc_rover->owner)
+			*sc_rover->owner = NULL;
+			
+		new->size += sc_rover->size;
+		new->next = sc_rover->next;
+	}
+
+// create a fragment out of any leftovers
+	if (new->size - size > 256)
+	{
+		sc_rover = (surfcache_t *)( (byte *)new + size);
+		sc_rover->size = new->size - size;
+		sc_rover->next = new->next;
+		sc_rover->width = 0;
+		sc_rover->owner = NULL;
+		new->next = sc_rover;
+		new->size = size;
+	}
+	else
+		sc_rover = new->next;
+	
+	new->width = width;
+// DEBUG
+	if (width > 0)
+		new->height = (size - sizeof(*new) + sizeof(new->data)) / width;
+
+	new->owner = NULL;              // should be set properly after return
+
+	if (d_roverwrapped)
+	{
+		if (wrapped_this_time || (sc_rover >= d_initial_rover))
+			r_cache_thrash = true;
+	}
+	else if (wrapped_this_time)
+	{       
+		d_roverwrapped = true;
+	}
+
+D_CheckCacheGuard ();   // DEBUG
+	return new;
+}
+
+
+/*
+=================
+D_SCDump
+=================
+*/
+void D_SCDump (void)
+{
+	surfcache_t             *test;
+
+	for (test = sc_base ; test ; test = test->next)
+	{
+		if (test == sc_rover)
+			Sys_Printf ("ROVER:\n");
+		printf ("%p : %i bytes     %i width\n",test, test->size, test->width);
+	}
+}
+
+//=============================================================================
+
+// if the num is not a power of 2, assume it will not repeat
+
+int     MaskForNum (int num)
+{
+	if (num==128)
+		return 127;
+	if (num==64)
+		return 63;
+	if (num==32)
+		return 31;
+	if (num==16)
+		return 15;
+	return 255;
+}
+
+int D_log2 (int num)
+{
+	int     c;
+	
+	c = 0;
+	
+	while (num>>=1)
+		c++;
+	return c;
+}
+
+//=============================================================================
+
+/*
+================
+D_CacheSurface
+================
+*/
+surfcache_t *D_CacheSurface (msurface_t *surface, int miplevel)
+{
+	surfcache_t     *cache;
+
+//
+// if the surface is animating or flashing, flush the cache
+//
+	r_drawsurf.texture = R_TextureAnimation (surface->texinfo->texture);
+	r_drawsurf.lightadj[0] = d_lightstylevalue[surface->styles[0]];
+	r_drawsurf.lightadj[1] = d_lightstylevalue[surface->styles[1]];
+	r_drawsurf.lightadj[2] = d_lightstylevalue[surface->styles[2]];
+	r_drawsurf.lightadj[3] = d_lightstylevalue[surface->styles[3]];
+	
+//
+// see if the cache holds apropriate data
+//
+	cache = surface->cachespots[miplevel];
+
+	if (cache && !cache->dlight && surface->dlightframe != r_framecount
+			&& cache->texture == r_drawsurf.texture
+			&& cache->lightadj[0] == r_drawsurf.lightadj[0]
+			&& cache->lightadj[1] == r_drawsurf.lightadj[1]
+			&& cache->lightadj[2] == r_drawsurf.lightadj[2]
+			&& cache->lightadj[3] == r_drawsurf.lightadj[3] )
+		return cache;
+
+//
+// determine shape of surface
+//
+	surfscale = 1.0 / (1<<miplevel);
+	r_drawsurf.surfmip = miplevel;
+	r_drawsurf.surfwidth = surface->extents[0] >> miplevel;
+	r_drawsurf.rowbytes = r_drawsurf.surfwidth;
+	r_drawsurf.surfheight = surface->extents[1] >> miplevel;
+	
+//
+// allocate memory if needed
+//
+	if (!cache)     // if a texture just animated, don't reallocate it
+	{
+		cache = D_SCAlloc (r_drawsurf.surfwidth,
+						   r_drawsurf.surfwidth * r_drawsurf.surfheight);
+		surface->cachespots[miplevel] = cache;
+		cache->owner = &surface->cachespots[miplevel];
+		cache->mipscale = surfscale;
+	}
+	
+	if (surface->dlightframe == r_framecount)
+		cache->dlight = 1;
+	else
+		cache->dlight = 0;
+
+	r_drawsurf.surfdat = (pixel_t *)cache->data;
+	
+	cache->texture = r_drawsurf.texture;
+	cache->lightadj[0] = r_drawsurf.lightadj[0];
+	cache->lightadj[1] = r_drawsurf.lightadj[1];
+	cache->lightadj[2] = r_drawsurf.lightadj[2];
+	cache->lightadj[3] = r_drawsurf.lightadj[3];
+
+//
+// draw and light the surface texture
+//
+	r_drawsurf.surf = surface;
+
+	c_surf++;
+	R_DrawSurface ();
+
+	return surface->cachespots[miplevel];
+}
+
+
--- /dev/null
+++ b/QW/client/d_vars.c
@@ -1,0 +1,50 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// r_vars.c: global refresh variables
+
+#if	!id386
+
+#include	"quakedef.h"
+
+// all global and static refresh variables are collected in a contiguous block
+// to avoid cache conflicts.
+
+//-------------------------------------------------------
+// global refresh variables
+//-------------------------------------------------------
+
+// FIXME: make into one big structure, like cl or sv
+// FIXME: do separately for refresh engine and driver
+
+float	d_sdivzstepu, d_tdivzstepu, d_zistepu;
+float	d_sdivzstepv, d_tdivzstepv, d_zistepv;
+float	d_sdivzorigin, d_tdivzorigin, d_ziorigin;
+
+fixed16_t	sadjust, tadjust, bbextents, bbextentt;
+
+pixel_t			*cacheblock;
+int				cachewidth;
+pixel_t			*d_viewbuffer;
+short			*d_pzbuffer;
+unsigned int	d_zrowbytes;
+unsigned int	d_zwidth;
+
+#endif	// !id386
+
--- /dev/null
+++ b/QW/client/d_varsa.asm
@@ -1,0 +1,362 @@
+ .386P
+ .model FLAT
+ externdef _d_zistepu:dword
+ externdef _d_pzbuffer:dword
+ externdef _d_zistepv:dword
+ externdef _d_zrowbytes:dword
+ externdef _d_ziorigin:dword
+ externdef _r_turb_s:dword
+ externdef _r_turb_t:dword
+ externdef _r_turb_pdest:dword
+ externdef _r_turb_spancount:dword
+ externdef _r_turb_turb:dword
+ externdef _r_turb_pbase:dword
+ externdef _r_turb_sstep:dword
+ externdef _r_turb_tstep:dword
+ externdef _r_bmodelactive:dword
+ externdef _d_sdivzstepu:dword
+ externdef _d_tdivzstepu:dword
+ externdef _d_sdivzstepv:dword
+ externdef _d_tdivzstepv:dword
+ externdef _d_sdivzorigin:dword
+ externdef _d_tdivzorigin:dword
+ externdef _sadjust:dword
+ externdef _tadjust:dword
+ externdef _bbextents:dword
+ externdef _bbextentt:dword
+ externdef _cacheblock:dword
+ externdef _d_viewbuffer:dword
+ externdef _cachewidth:dword
+ externdef _d_pzbuffer:dword
+ externdef _d_zrowbytes:dword
+ externdef _d_zwidth:dword
+ externdef _d_scantable:dword
+ externdef _r_lightptr:dword
+ externdef _r_numvblocks:dword
+ externdef _prowdestbase:dword
+ externdef _pbasesource:dword
+ externdef _r_lightwidth:dword
+ externdef _lightright:dword
+ externdef _lightrightstep:dword
+ externdef _lightdeltastep:dword
+ externdef _lightdelta:dword
+ externdef _lightright:dword
+ externdef _lightdelta:dword
+ externdef _sourcetstep:dword
+ externdef _surfrowbytes:dword
+ externdef _lightrightstep:dword
+ externdef _lightdeltastep:dword
+ externdef _r_sourcemax:dword
+ externdef _r_stepback:dword
+ externdef _colormap:dword
+ externdef _blocksize:dword
+ externdef _sourcesstep:dword
+ externdef _lightleft:dword
+ externdef _blockdivshift:dword
+ externdef _blockdivmask:dword
+ externdef _lightleftstep:dword
+ externdef _r_origin:dword
+ externdef _r_ppn:dword
+ externdef _r_pup:dword
+ externdef _r_pright:dword
+ externdef _ycenter:dword
+ externdef _xcenter:dword
+ externdef _d_vrectbottom_particle:dword
+ externdef _d_vrectright_particle:dword
+ externdef _d_vrecty:dword
+ externdef _d_vrectx:dword
+ externdef _d_pix_shift:dword
+ externdef _d_pix_min:dword
+ externdef _d_pix_max:dword
+ externdef _d_y_aspect_shift:dword
+ externdef _screenwidth:dword
+ externdef _vright:dword
+ externdef _vup:dword
+ externdef _vpn:dword
+ externdef _BOPS_Error:dword
+ externdef _snd_scaletable:dword
+ externdef _paintbuffer:dword
+ externdef _snd_linear_count:dword
+ externdef _snd_p:dword
+ externdef _snd_vol:dword
+ externdef _snd_out:dword
+ externdef _r_leftclipped:dword
+ externdef _r_leftenter:dword
+ externdef _r_rightclipped:dword
+ externdef _r_rightenter:dword
+ externdef _modelorg:dword
+ externdef _xscale:dword
+ externdef _r_refdef:dword
+ externdef _yscale:dword
+ externdef _r_leftexit:dword
+ externdef _r_rightexit:dword
+ externdef _r_lastvertvalid:dword
+ externdef _cacheoffset:dword
+ externdef _newedges:dword
+ externdef _removeedges:dword
+ externdef _r_pedge:dword
+ externdef _r_framecount:dword
+ externdef _r_u1:dword
+ externdef _r_emitted:dword
+ externdef _edge_p:dword
+ externdef _surface_p:dword
+ externdef _surfaces:dword
+ externdef _r_lzi1:dword
+ externdef _r_v1:dword
+ externdef _r_ceilv1:dword
+ externdef _r_nearzi:dword
+ externdef _r_nearzionly:dword
+ externdef _edge_aftertail:dword
+ externdef _edge_tail:dword
+ externdef _current_iv:dword
+ externdef _edge_head_u_shift20:dword
+ externdef _span_p:dword
+ externdef _edge_head:dword
+ externdef _fv:dword
+ externdef _edge_tail_u_shift20:dword
+ externdef _r_apverts:dword
+ externdef _r_anumverts:dword
+ externdef _aliastransform:dword
+ externdef _r_avertexnormals:dword
+ externdef _r_plightvec:dword
+ externdef _r_ambientlight:dword
+ externdef _r_shadelight:dword
+ externdef _aliasxcenter:dword
+ externdef _aliasycenter:dword
+ externdef _a_sstepxfrac:dword
+ externdef _r_affinetridesc:dword
+ externdef _acolormap:dword
+ externdef _d_pcolormap:dword
+ externdef _r_affinetridesc:dword
+ externdef _d_sfrac:dword
+ externdef _d_ptex:dword
+ externdef _d_pedgespanpackage:dword
+ externdef _d_tfrac:dword
+ externdef _d_light:dword
+ externdef _d_zi:dword
+ externdef _d_pdest:dword
+ externdef _d_pz:dword
+ externdef _d_aspancount:dword
+ externdef _erroradjustup:dword
+ externdef _errorterm:dword
+ externdef _d_xdenom:dword
+ externdef _r_p0:dword
+ externdef _r_p1:dword
+ externdef _r_p2:dword
+ externdef _a_tstepxfrac:dword
+ externdef _r_sstepx:dword
+ externdef _r_tstepx:dword
+ externdef _a_ststepxwhole:dword
+ externdef _zspantable:dword
+ externdef _skintable:dword
+ externdef _r_zistepx:dword
+ externdef _erroradjustdown:dword
+ externdef _d_countextrastep:dword
+ externdef _ubasestep:dword
+ externdef _a_ststepxwhole:dword
+ externdef _a_tstepxfrac:dword
+ externdef _r_lstepx:dword
+ externdef _a_spans:dword
+ externdef _erroradjustdown:dword
+ externdef _d_pdestextrastep:dword
+ externdef _d_pzextrastep:dword
+ externdef _d_sfracextrastep:dword
+ externdef _d_ptexextrastep:dword
+ externdef _d_countextrastep:dword
+ externdef _d_tfracextrastep:dword
+ externdef _d_lightextrastep:dword
+ externdef _d_ziextrastep:dword
+ externdef _d_pdestbasestep:dword
+ externdef _d_pzbasestep:dword
+ externdef _d_sfracbasestep:dword
+ externdef _d_ptexbasestep:dword
+ externdef _ubasestep:dword
+ externdef _d_tfracbasestep:dword
+ externdef _d_lightbasestep:dword
+ externdef _d_zibasestep:dword
+ externdef _zspantable:dword
+ externdef _r_lstepy:dword
+ externdef _r_sstepy:dword
+ externdef _r_tstepy:dword
+ externdef _r_zistepy:dword
+ externdef _D_PolysetSetEdgeTable:dword
+ externdef _D_RasterizeAliasPolySmooth:dword
+ externdef float_point5:dword
+ externdef Float2ToThe31nd:dword
+ externdef izistep:dword
+ externdef izi:dword
+ externdef FloatMinus2ToThe31nd:dword
+ externdef float_1:dword
+ externdef float_particle_z_clip:dword
+ externdef float_minus_1:dword
+ externdef float_0:dword
+ externdef fp_16:dword
+ externdef fp_64k:dword
+ externdef fp_1m:dword
+ externdef fp_1m_minus_1:dword
+ externdef fp_8:dword
+ externdef entryvec_table:dword
+ externdef advancetable:dword
+ externdef sstep:dword
+ externdef tstep:dword
+ externdef pspantemp:dword
+ externdef counttemp:dword
+ externdef jumptemp:dword
+ externdef reciprocal_table:dword
+ externdef DP_Count:dword
+ externdef DP_u:dword
+ externdef DP_v:dword
+ externdef DP_32768:dword
+ externdef DP_Color:dword
+ externdef DP_Pix:dword
+ externdef DP_EntryTable:dword
+ externdef pbase:dword
+ externdef s:dword
+ externdef t:dword
+ externdef sfracf:dword
+ externdef tfracf:dword
+ externdef snext:dword
+ externdef tnext:dword
+ externdef spancountminus1:dword
+ externdef zi16stepu:dword
+ externdef sdivz16stepu:dword
+ externdef tdivz16stepu:dword
+ externdef zi8stepu:dword
+ externdef sdivz8stepu:dword
+ externdef tdivz8stepu:dword
+ externdef reciprocal_table_16:dword
+ externdef entryvec_table_16:dword
+ externdef ceil_cw:dword
+ externdef single_cw:dword
+ externdef fp_64kx64k:dword
+ externdef pz:dword
+ externdef spr8entryvec_table:dword
+_DATA SEGMENT
+ align 4
+ public _d_sdivzstepu
+ public _d_tdivzstepu
+ public _d_zistepu
+ public _d_sdivzstepv
+ public _d_tdivzstepv
+ public _d_zistepv
+ public _d_sdivzorigin
+ public _d_tdivzorigin
+ public _d_ziorigin
+_d_sdivzstepu dd 0
+_d_tdivzstepu dd 0
+_d_zistepu dd 0
+_d_sdivzstepv dd 0
+_d_tdivzstepv dd 0
+_d_zistepv dd 0
+_d_sdivzorigin dd 0
+_d_tdivzorigin dd 0
+_d_ziorigin dd 0
+ public _sadjust
+ public _tadjust
+ public _bbextents
+ public _bbextentt
+_sadjust dd 0
+_tadjust dd 0
+_bbextents dd 0
+_bbextentt dd 0
+ public _cacheblock
+ public _d_viewbuffer
+ public _cachewidth
+ public _d_pzbuffer
+ public _d_zrowbytes
+ public _d_zwidth
+_cacheblock dd 0
+_cachewidth dd 0
+_d_viewbuffer dd 0
+_d_pzbuffer dd 0
+_d_zrowbytes dd 0
+_d_zwidth dd 0
+ public izi
+izi dd 0
+ public pbase, s, t, sfracf, tfracf, snext, tnext
+ public spancountminus1, zi16stepu, sdivz16stepu, tdivz16stepu
+ public zi8stepu, sdivz8stepu, tdivz8stepu, pz
+s dd 0
+t dd 0
+snext dd 0
+tnext dd 0
+sfracf dd 0
+tfracf dd 0
+pbase dd 0
+zi8stepu dd 0
+sdivz8stepu dd 0
+tdivz8stepu dd 0
+zi16stepu dd 0
+sdivz16stepu dd 0
+tdivz16stepu dd 0
+spancountminus1 dd 0
+pz dd 0
+ public izistep
+izistep dd 0
+ public reciprocal_table_16, entryvec_table_16
+reciprocal_table_16 dd 040000000h, 02aaaaaaah, 020000000h
+ dd 019999999h, 015555555h, 012492492h
+ dd 010000000h, 0e38e38eh, 0ccccccch, 0ba2e8bah
+ dd 0aaaaaaah, 09d89d89h, 09249249h, 08888888h
+ externdef Entry2_16:dword
+ externdef Entry3_16:dword
+ externdef Entry4_16:dword
+ externdef Entry5_16:dword
+ externdef Entry6_16:dword
+ externdef Entry7_16:dword
+ externdef Entry8_16:dword
+ externdef Entry9_16:dword
+ externdef Entry10_16:dword
+ externdef Entry11_16:dword
+ externdef Entry12_16:dword
+ externdef Entry13_16:dword
+ externdef Entry14_16:dword
+ externdef Entry15_16:dword
+ externdef Entry16_16:dword
+entryvec_table_16 dd 0, Entry2_16, Entry3_16, Entry4_16
+ dd Entry5_16, Entry6_16, Entry7_16, Entry8_16
+ dd Entry9_16, Entry10_16, Entry11_16, Entry12_16
+ dd Entry13_16, Entry14_16, Entry15_16, Entry16_16
+ public DP_Count, DP_u, DP_v, DP_32768, DP_Color, DP_Pix, DP_EntryTable
+DP_Count dd 0
+DP_u dd 0
+DP_v dd 0
+DP_32768 dd 32768.0
+DP_Color dd 0
+DP_Pix dd 0
+ externdef DP_1x1:dword
+ externdef DP_2x2:dword
+ externdef DP_3x3:dword
+ externdef DP_4x4:dword
+DP_EntryTable dd DP_1x1, DP_2x2, DP_3x3, DP_4x4
+ public advancetable, sstep, tstep, pspantemp, counttemp, jumptemp
+advancetable dd 0, 0
+sstep dd 0
+tstep dd 0
+pspantemp dd 0
+counttemp dd 0
+jumptemp dd 0
+ public reciprocal_table, entryvec_table
+reciprocal_table dd 040000000h, 02aaaaaaah, 020000000h
+ dd 019999999h, 015555555h, 012492492h
+ externdef Entry2_8:dword
+ externdef Entry3_8:dword
+ externdef Entry4_8:dword
+ externdef Entry5_8:dword
+ externdef Entry6_8:dword
+ externdef Entry7_8:dword
+ externdef Entry8_8:dword
+entryvec_table dd 0, Entry2_8, Entry3_8, Entry4_8
+ dd Entry5_8, Entry6_8, Entry7_8, Entry8_8
+ externdef Spr8Entry2_8:dword
+ externdef Spr8Entry3_8:dword
+ externdef Spr8Entry4_8:dword
+ externdef Spr8Entry5_8:dword
+ externdef Spr8Entry6_8:dword
+ externdef Spr8Entry7_8:dword
+ externdef Spr8Entry8_8:dword
+ public spr8entryvec_table
+spr8entryvec_table dd 0, Spr8Entry2_8, Spr8Entry3_8, Spr8Entry4_8
+ dd Spr8Entry5_8, Spr8Entry6_8, Spr8Entry7_8, Spr8Entry8_8
+_DATA ENDS
+ END
--- /dev/null
+++ b/QW/client/d_varsa.s
@@ -1,0 +1,213 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+//
+// d_varsa.s
+//
+
+#include "asm_i386.h"
+#include "quakeasm.h"
+#include "asm_draw.h"
+#include "d_ifacea.h"
+
+#if	id386
+
+	.data
+
+//-------------------------------------------------------
+// global refresh variables
+//-------------------------------------------------------
+
+// FIXME: put all refresh variables into one contiguous block. Make into one
+// big structure, like cl or sv?
+
+	.align	4
+.globl	C(d_sdivzstepu)
+.globl	C(d_tdivzstepu)
+.globl	C(d_zistepu)
+.globl	C(d_sdivzstepv)
+.globl	C(d_tdivzstepv)
+.globl	C(d_zistepv)
+.globl	C(d_sdivzorigin)
+.globl	C(d_tdivzorigin)
+.globl	C(d_ziorigin)
+C(d_sdivzstepu):	.single	0
+C(d_tdivzstepu):	.single	0
+C(d_zistepu):		.single	0
+C(d_sdivzstepv):	.single	0
+C(d_tdivzstepv):	.single	0
+C(d_zistepv):		.single	0
+C(d_sdivzorigin):	.single	0
+C(d_tdivzorigin):	.single	0
+C(d_ziorigin):		.single	0
+
+.globl	C(sadjust)
+.globl	C(tadjust)
+.globl	C(bbextents)
+.globl	C(bbextentt)
+C(sadjust):			.long	0
+C(tadjust):			.long	0
+C(bbextents):		.long	0
+C(bbextentt):		.long	0
+
+.globl	C(cacheblock)
+.globl	C(d_viewbuffer)
+.globl	C(cachewidth)
+.globl	C(d_pzbuffer)
+.globl	C(d_zrowbytes)
+.globl	C(d_zwidth)
+C(cacheblock):		.long	0
+C(cachewidth):		.long	0
+C(d_viewbuffer):	.long	0
+C(d_pzbuffer):		.long	0
+C(d_zrowbytes):		.long	0
+C(d_zwidth):		.long	0
+
+
+//-------------------------------------------------------
+// ASM-only variables
+//-------------------------------------------------------
+.globl	izi
+izi:			.long	0
+
+.globl	pbase, s, t, sfracf, tfracf, snext, tnext
+.globl	spancountminus1, zi16stepu, sdivz16stepu, tdivz16stepu
+.globl	zi8stepu, sdivz8stepu, tdivz8stepu, pz
+s:				.long	0
+t:				.long	0
+snext:			.long	0
+tnext:			.long	0
+sfracf:			.long	0
+tfracf:			.long	0
+pbase:			.long	0
+zi8stepu:		.long	0
+sdivz8stepu:	.long	0
+tdivz8stepu:	.long	0
+zi16stepu:		.long	0
+sdivz16stepu:	.long	0
+tdivz16stepu:	.long	0
+spancountminus1: .long	0
+pz:				.long	0
+
+.globl	izistep
+izistep:				.long	0
+
+//-------------------------------------------------------
+// local variables for d_draw16.s
+//-------------------------------------------------------
+
+.globl	reciprocal_table_16, entryvec_table_16
+// 1/2, 1/3, 1/4, 1/5, 1/6, 1/7, 1/8, 1/9, 1/10, 1/11, 1/12, 1/13,
+// 1/14, and 1/15 in 0.32 form
+reciprocal_table_16:	.long	0x40000000, 0x2aaaaaaa, 0x20000000
+						.long	0x19999999, 0x15555555, 0x12492492
+						.long	0x10000000, 0xe38e38e, 0xccccccc, 0xba2e8ba
+						.long	0xaaaaaaa, 0x9d89d89, 0x9249249, 0x8888888
+
+#ifndef NeXT
+	.extern Entry2_16
+	.extern Entry3_16
+	.extern Entry4_16
+	.extern Entry5_16
+	.extern Entry6_16
+	.extern Entry7_16
+	.extern Entry8_16
+	.extern Entry9_16
+	.extern Entry10_16
+	.extern Entry11_16
+	.extern Entry12_16
+	.extern Entry13_16
+	.extern Entry14_16
+	.extern Entry15_16
+	.extern Entry16_16
+#endif
+
+entryvec_table_16:	.long	0, Entry2_16, Entry3_16, Entry4_16
+					.long	Entry5_16, Entry6_16, Entry7_16, Entry8_16
+					.long	Entry9_16, Entry10_16, Entry11_16, Entry12_16
+					.long	Entry13_16, Entry14_16, Entry15_16, Entry16_16
+
+//-------------------------------------------------------
+// local variables for d_parta.s
+//-------------------------------------------------------
+.globl	DP_Count, DP_u, DP_v, DP_32768, DP_Color, DP_Pix, DP_EntryTable
+DP_Count:		.long	0
+DP_u:			.long	0
+DP_v:			.long	0
+DP_32768:		.single	32768.0
+DP_Color:		.long	0
+DP_Pix:			.long	0
+
+
+#ifndef NeXT
+	.extern DP_1x1
+	.extern DP_2x2
+	.extern DP_3x3
+	.extern DP_4x4
+#endif
+
+DP_EntryTable:	.long	DP_1x1, DP_2x2, DP_3x3, DP_4x4
+
+//
+// advancetable is 8 bytes, but points to the middle of that range so negative
+// offsets will work
+//
+.globl	advancetable, sstep, tstep, pspantemp, counttemp, jumptemp
+advancetable:	.long	0, 0
+sstep:			.long	0
+tstep:			.long	0
+
+pspantemp:		.long	0
+counttemp:		.long	0
+jumptemp:		.long	0
+
+// 1/2, 1/3, 1/4, 1/5, 1/6, and 1/7 in 0.32 form
+.globl	reciprocal_table, entryvec_table
+reciprocal_table:	.long	0x40000000, 0x2aaaaaaa, 0x20000000
+					.long	0x19999999, 0x15555555, 0x12492492
+
+#ifndef NeXT
+	.extern Entry2_8
+	.extern Entry3_8
+	.extern Entry4_8
+	.extern Entry5_8
+	.extern Entry6_8
+	.extern Entry7_8
+	.extern Entry8_8
+#endif
+
+entryvec_table:	.long	0, Entry2_8, Entry3_8, Entry4_8
+				.long	Entry5_8, Entry6_8, Entry7_8, Entry8_8
+
+#ifndef NeXT
+	.extern Spr8Entry2_8
+	.extern Spr8Entry3_8
+	.extern Spr8Entry4_8
+	.extern Spr8Entry5_8
+	.extern Spr8Entry6_8
+	.extern Spr8Entry7_8
+	.extern Spr8Entry8_8
+#endif
+	
+.globl spr8entryvec_table
+spr8entryvec_table:	.long	0, Spr8Entry2_8, Spr8Entry3_8, Spr8Entry4_8
+					.long	Spr8Entry5_8, Spr8Entry6_8, Spr8Entry7_8, Spr8Entry8_8
+
+#endif	// id386
+
--- /dev/null
+++ b/QW/client/d_zpoint.c
@@ -1,0 +1,47 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// d_zpoint.c: software driver module for drawing z-buffered points
+
+#include "quakedef.h"
+#include "d_local.h"
+
+
+/*
+=====================
+D_DrawZPoint
+=====================
+*/
+void D_DrawZPoint (void)
+{
+	byte	*pdest;
+	short	*pz;
+	int		izi;
+	
+	pz = d_pzbuffer + (d_zwidth * r_zpointdesc.v) + r_zpointdesc.u;
+	pdest = d_viewbuffer + d_scantable[r_zpointdesc.v] + r_zpointdesc.u;
+	izi = (int)(r_zpointdesc.zi * 0x8000);
+
+	if (*pz <= izi)
+	{
+		*pz = izi;
+		*pdest = r_zpointdesc.color;
+	}
+}
+
--- /dev/null
+++ b/QW/client/docs.txt
@@ -1,0 +1,118 @@
+
+The QuakeWorld connection process:
+---------------------------------
+
+servercount
+Each time a server changes maps, it will bump the servercount variable.  The signon
+messages sent from the client to the server will include a servercount, and if the
+server detects that it has changed levels while the client is in the process of
+connecting, the client connection process will be restarted.
+
+svc_skinlist
+
+MAX_SIGNON_BUFFERS...
+
++attack;wait  : this both does the attack and prints a chat?
+
+put frag counts in userinfo as *frags?
+
+no forward to server commands unless active?
+
+changelevel / reconnect confusion
+
+syncing the fixangle over the reliable channel with the first update
+	option to put the update in the reliable message?
+
+
+--------------
+A "connect <server>" command is executed on the client.
+
+CL_Connect_f() disconnects from the current server if connected, 
+sets the current server to the new value, and sends the first connection packet.
+
+The connection packet will be resent by CL_CheckForResend() every two seconds until the server connects.
+
+A connection packet is an out of band packet containing "connect <userinfo>" with userinfo quoted.
+
+--------------
+
+The server receives the OOB message in SVC_DirectConnect()
+
+It can respond with an OOB client print of "banned" or "server is full" if the client
+cannot enter the game.
+
+If the client can get in, the server will initialize a new client_t structure with a
+netchan_t, and respond with an OOB message containing S2C_CONNECTION.  Further
+communication will be through sequenced netchan_t messages instead of OOB messages.
+
+The client_t->state is set to cs_connected
+
+--------------
+
+if S2C_CONNECTION packet is dropped, the connect message will be resent after two
+seconds and the server will recognize the address and reuse the allocated client_t FIXME:bug?)			
+
+When the client receives the S2C_CONNECTION, it initializes cls.netchan and sends
+a "new" string command over the netchan to the server.
+
+cls.state is set to ca_connected	FIXME: change to cs_connected?
+
+--------------
+
+The "new" usercommand on the server is issued by the client every time they enter a level,
+which is why none of the information is sent in the initial S2C_CONNECTION message. 
+
+"new" sends over 
+
+Before the client can begin playing in the server, the following information must be sent:
+
+gamedir
+svc_serverinfo
+	PROTOCOL_VERSION
+	servercount		// for detecting when the server
+	gamedir			// for deciding the add-on directory (qw, ctf, etc)
+	playernumber	// the client will allways be in this slot
+	the qc string of world.message	// usually the level's full verbose name
+cdtrack
+fullserverinfo
+
+when received, the client changes state to ca_onserver.  When the client receives
+all the information needed to render a frame, the state will be changed to ca_active
+
+.....
+
+svc_soundlist
+
+.....
+
+svc_modellist
+
+.....
+
+prespawn passes the contents of the sv.signon_buffers, which hold
+static entity spawning, static sound spawning, and all the entity baselines
+FIXME: don't need to pass all baselines, uninitialized probs?
+
+.....
+
+"spawn" sends all dynamically changing state (fullclient updates, lightmaps, frags)
+and ma
+
+FIXME: 32 clients could be up to 16k in updates, which overflows the 8k packet size
+
+FIXME: there is an updating hole between the sending of spawn data and the client
+being notified 
+
+
+"begin"
+
+Actually spawns the client into the world as a visible entity.
+
+The client_t->state is set to cs_spawned, so normal datagram updates begin
+
+-----------------------
+
+When the first valid packetentities_t arrives at the client, cls.state is set
+to ca_active, and rendering can begin.
+
+FIXME: make sure player and packets are both valid
--- /dev/null
+++ b/QW/client/draw.c
@@ -1,0 +1,1020 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+
+// draw.c -- this is the only file outside the refresh that touches the
+// vid buffer
+
+#include "quakedef.h"
+
+typedef struct {
+	vrect_t	rect;
+	int		width;
+	int		height;
+	byte	*ptexbytes;
+	int		rowbytes;
+} rectdesc_t;
+
+static rectdesc_t	r_rectdesc;
+
+byte		*draw_chars;				// 8*8 graphic characters
+qpic_t		*draw_disc;
+qpic_t		*draw_backtile;
+
+//=============================================================================
+/* Support Routines */
+
+typedef struct cachepic_s
+{
+	char		name[MAX_QPATH];
+	cache_user_t	cache;
+} cachepic_t;
+
+#define	MAX_CACHED_PICS		128
+cachepic_t	menu_cachepics[MAX_CACHED_PICS];
+int			menu_numcachepics;
+
+
+qpic_t	*Draw_PicFromWad (char *name)
+{
+	return W_GetLumpName (name);
+}
+
+/*
+================
+Draw_CachePic
+================
+*/
+qpic_t	*Draw_CachePic (char *path)
+{
+	cachepic_t	*pic;
+	int			i;
+	qpic_t		*dat;
+	
+	for (pic=menu_cachepics, i=0 ; i<menu_numcachepics ; pic++, i++)
+		if (!strcmp (path, pic->name))
+			break;
+
+	if (i == menu_numcachepics)
+	{
+		if (menu_numcachepics == MAX_CACHED_PICS)
+			Sys_Error ("menu_numcachepics == MAX_CACHED_PICS");
+		menu_numcachepics++;
+		strcpy (pic->name, path);
+	}
+
+	dat = Cache_Check (&pic->cache);
+
+	if (dat)
+		return dat;
+
+//
+// load the pic from disk
+//
+	COM_LoadCacheFile (path, &pic->cache);
+	
+	dat = (qpic_t *)pic->cache.data;
+	if (!dat)
+	{
+		Sys_Error ("Draw_CachePic: failed to load %s", path);
+	}
+
+	SwapPic (dat);
+
+	return dat;
+}
+
+
+
+/*
+===============
+Draw_Init
+===============
+*/
+void Draw_Init (void)
+{
+	draw_chars = W_GetLumpName ("conchars");
+	draw_disc = W_GetLumpName ("disc");
+	draw_backtile = W_GetLumpName ("backtile");
+
+	r_rectdesc.width = draw_backtile->width;
+	r_rectdesc.height = draw_backtile->height;
+	r_rectdesc.ptexbytes = draw_backtile->data;
+	r_rectdesc.rowbytes = draw_backtile->width;
+}
+
+
+
+/*
+================
+Draw_Character
+
+Draws one 8*8 graphics character with 0 being transparent.
+It can be clipped to the top of the screen to allow the console to be
+smoothly scrolled off.
+================
+*/
+void Draw_Character (int x, int y, int num)
+{
+	byte			*dest;
+	byte			*source;
+	unsigned short	*pusdest;
+	int				drawline;	
+	int				row, col;
+
+	num &= 255;
+	
+	if (y <= -8)
+		return;			// totally off screen
+
+	if (y > vid.height - 8 || x < 0 || x > vid.width - 8)
+		return;
+	if (num < 0 || num > 255)
+		return;
+
+	row = num>>4;
+	col = num&15;
+	source = draw_chars + (row<<10) + (col<<3);
+
+	if (y < 0)
+	{	// clipped
+		drawline = 8 + y;
+		source -= 128*y;
+		y = 0;
+	}
+	else
+		drawline = 8;
+
+
+	if (r_pixbytes == 1)
+	{
+		dest = vid.conbuffer + y*vid.conrowbytes + x;
+	
+		while (drawline--)
+		{
+			if (source[0])
+				dest[0] = source[0];
+			if (source[1])
+				dest[1] = source[1];
+			if (source[2])
+				dest[2] = source[2];
+			if (source[3])
+				dest[3] = source[3];
+			if (source[4])
+				dest[4] = source[4];
+			if (source[5])
+				dest[5] = source[5];
+			if (source[6])
+				dest[6] = source[6];
+			if (source[7])
+				dest[7] = source[7];
+			source += 128;
+			dest += vid.conrowbytes;
+		}
+	}
+	else
+	{
+	// FIXME: pre-expand to native format?
+		pusdest = (unsigned short *)
+				((byte *)vid.conbuffer + y*vid.conrowbytes + (x<<1));
+
+		while (drawline--)
+		{
+			if (source[0])
+				pusdest[0] = d_8to16table[source[0]];
+			if (source[1])
+				pusdest[1] = d_8to16table[source[1]];
+			if (source[2])
+				pusdest[2] = d_8to16table[source[2]];
+			if (source[3])
+				pusdest[3] = d_8to16table[source[3]];
+			if (source[4])
+				pusdest[4] = d_8to16table[source[4]];
+			if (source[5])
+				pusdest[5] = d_8to16table[source[5]];
+			if (source[6])
+				pusdest[6] = d_8to16table[source[6]];
+			if (source[7])
+				pusdest[7] = d_8to16table[source[7]];
+
+			source += 128;
+			pusdest += (vid.conrowbytes >> 1);
+		}
+	}
+}
+
+/*
+================
+Draw_String
+================
+*/
+void Draw_String (int x, int y, char *str)
+{
+	while (*str)
+	{
+		Draw_Character (x, y, *str);
+		str++;
+		x += 8;
+	}
+}
+
+/*
+================
+Draw_Alt_String
+================
+*/
+void Draw_Alt_String (int x, int y, char *str)
+{
+	while (*str)
+	{
+		Draw_Character (x, y, (*str) | 0x80);
+		str++;
+		x += 8;
+	}
+}
+
+void Draw_Pixel(int x, int y, byte color)
+{
+	byte			*dest;
+	unsigned short	*pusdest;
+
+	if (r_pixbytes == 1)
+	{
+		dest = vid.conbuffer + y*vid.conrowbytes + x;
+		*dest = color;
+	}
+	else
+	{
+	// FIXME: pre-expand to native format?
+		pusdest = (unsigned short *)
+				((byte *)vid.conbuffer + y*vid.conrowbytes + (x<<1));
+		*pusdest = d_8to16table[color];
+	}
+}
+
+void Draw_Crosshair(void)
+{
+	int x, y;
+	extern cvar_t crosshair, cl_crossx, cl_crossy, crosshaircolor;
+	extern vrect_t		scr_vrect;
+	byte c = (byte)crosshaircolor.value;
+
+	if (crosshair.value == 2) {
+		x = scr_vrect.x + scr_vrect.width/2 + cl_crossx.value; 
+		y = scr_vrect.y + scr_vrect.height/2 + cl_crossy.value;
+		Draw_Pixel(x - 1, y, c);
+		Draw_Pixel(x - 3, y, c);
+		Draw_Pixel(x + 1, y, c);
+		Draw_Pixel(x + 3, y, c);
+		Draw_Pixel(x, y - 1, c);
+		Draw_Pixel(x, y - 3, c);
+		Draw_Pixel(x, y + 1, c);
+		Draw_Pixel(x, y + 3, c);
+	} else if (crosshair.value)
+		Draw_Character (
+			scr_vrect.x + scr_vrect.width/2-4 + cl_crossx.value, 
+			scr_vrect.y + scr_vrect.height/2-4 + cl_crossy.value, 
+			'+');
+}
+
+/*
+================
+Draw_DebugChar
+
+Draws a single character directly to the upper right corner of the screen.
+This is for debugging lockups by drawing different chars in different parts
+of the code.
+================
+*/
+void Draw_DebugChar (char num)
+{
+	byte			*dest;
+	byte			*source;
+	int				drawline;	
+	extern byte		*draw_chars;
+	int				row, col;
+
+	if (!vid.direct)
+		return;		// don't have direct FB access, so no debugchars...
+
+	drawline = 8;
+
+	row = num>>4;
+	col = num&15;
+	source = draw_chars + (row<<10) + (col<<3);
+
+	dest = vid.direct + 312;
+
+	while (drawline--)
+	{
+		dest[0] = source[0];
+		dest[1] = source[1];
+		dest[2] = source[2];
+		dest[3] = source[3];
+		dest[4] = source[4];
+		dest[5] = source[5];
+		dest[6] = source[6];
+		dest[7] = source[7];
+		source += 128;
+		dest += 320;
+	}
+}
+
+/*
+=============
+Draw_Pic
+=============
+*/
+void Draw_Pic (int x, int y, qpic_t *pic)
+{
+	byte			*dest, *source;
+	unsigned short	*pusdest;
+	int				v, u;
+
+	if ((x < 0) ||
+		(x + pic->width > vid.width) ||
+		(y < 0) ||
+		(y + pic->height > vid.height))
+	{
+		Sys_Error ("Draw_Pic: bad coordinates");
+	}
+
+	source = pic->data;
+
+	if (r_pixbytes == 1)
+	{
+		dest = vid.buffer + y * vid.rowbytes + x;
+
+		for (v=0 ; v<pic->height ; v++)
+		{
+			Q_memcpy (dest, source, pic->width);
+			dest += vid.rowbytes;
+			source += pic->width;
+		}
+	}
+	else
+	{
+	// FIXME: pretranslate at load time?
+		pusdest = (unsigned short *)vid.buffer + y * (vid.rowbytes >> 1) + x;
+
+		for (v=0 ; v<pic->height ; v++)
+		{
+			for (u=0 ; u<pic->width ; u++)
+			{
+				pusdest[u] = d_8to16table[source[u]];
+			}
+
+			pusdest += vid.rowbytes >> 1;
+			source += pic->width;
+		}
+	}
+}
+
+
+/*
+=============
+Draw_SubPic
+=============
+*/
+void Draw_SubPic(int x, int y, qpic_t *pic, int srcx, int srcy, int width, int height)
+{
+	byte			*dest, *source;
+	unsigned short	*pusdest;
+	int				v, u;
+
+	if ((x < 0) ||
+		(x + width > vid.width) ||
+		(y < 0) ||
+		(y + height > vid.height))
+	{
+		Sys_Error ("Draw_Pic: bad coordinates");
+	}
+
+	source = pic->data + srcy * pic->width + srcx;
+
+	if (r_pixbytes == 1)
+	{
+		dest = vid.buffer + y * vid.rowbytes + x;
+
+		for (v=0 ; v<height ; v++)
+		{
+			Q_memcpy (dest, source, width);
+			dest += vid.rowbytes;
+			source += pic->width;
+		}
+	}
+	else
+	{
+	// FIXME: pretranslate at load time?
+		pusdest = (unsigned short *)vid.buffer + y * (vid.rowbytes >> 1) + x;
+
+		for (v=0 ; v<height ; v++)
+		{
+			for (u=srcx ; u<(srcx+width) ; u++)
+			{
+				pusdest[u] = d_8to16table[source[u]];
+			}
+
+			pusdest += vid.rowbytes >> 1;
+			source += pic->width;
+		}
+	}
+}
+
+
+/*
+=============
+Draw_TransPic
+=============
+*/
+void Draw_TransPic (int x, int y, qpic_t *pic)
+{
+	byte	*dest, *source, tbyte;
+	unsigned short	*pusdest;
+	int				v, u;
+
+	if (x < 0 || (unsigned)(x + pic->width) > vid.width || y < 0 ||
+		 (unsigned)(y + pic->height) > vid.height)
+	{
+		Sys_Error ("Draw_TransPic: bad coordinates");
+	}
+		
+	source = pic->data;
+
+	if (r_pixbytes == 1)
+	{
+		dest = vid.buffer + y * vid.rowbytes + x;
+
+		if (pic->width & 7)
+		{	// general
+			for (v=0 ; v<pic->height ; v++)
+			{
+				for (u=0 ; u<pic->width ; u++)
+					if ( (tbyte=source[u]) != TRANSPARENT_COLOR)
+						dest[u] = tbyte;
+	
+				dest += vid.rowbytes;
+				source += pic->width;
+			}
+		}
+		else
+		{	// unwound
+			for (v=0 ; v<pic->height ; v++)
+			{
+				for (u=0 ; u<pic->width ; u+=8)
+				{
+					if ( (tbyte=source[u]) != TRANSPARENT_COLOR)
+						dest[u] = tbyte;
+					if ( (tbyte=source[u+1]) != TRANSPARENT_COLOR)
+						dest[u+1] = tbyte;
+					if ( (tbyte=source[u+2]) != TRANSPARENT_COLOR)
+						dest[u+2] = tbyte;
+					if ( (tbyte=source[u+3]) != TRANSPARENT_COLOR)
+						dest[u+3] = tbyte;
+					if ( (tbyte=source[u+4]) != TRANSPARENT_COLOR)
+						dest[u+4] = tbyte;
+					if ( (tbyte=source[u+5]) != TRANSPARENT_COLOR)
+						dest[u+5] = tbyte;
+					if ( (tbyte=source[u+6]) != TRANSPARENT_COLOR)
+						dest[u+6] = tbyte;
+					if ( (tbyte=source[u+7]) != TRANSPARENT_COLOR)
+						dest[u+7] = tbyte;
+				}
+				dest += vid.rowbytes;
+				source += pic->width;
+			}
+		}
+	}
+	else
+	{
+	// FIXME: pretranslate at load time?
+		pusdest = (unsigned short *)vid.buffer + y * (vid.rowbytes >> 1) + x;
+
+		for (v=0 ; v<pic->height ; v++)
+		{
+			for (u=0 ; u<pic->width ; u++)
+			{
+				tbyte = source[u];
+
+				if (tbyte != TRANSPARENT_COLOR)
+				{
+					pusdest[u] = d_8to16table[tbyte];
+				}
+			}
+
+			pusdest += vid.rowbytes >> 1;
+			source += pic->width;
+		}
+	}
+}
+
+
+/*
+=============
+Draw_TransPicTranslate
+=============
+*/
+void Draw_TransPicTranslate (int x, int y, qpic_t *pic, byte *translation)
+{
+	byte	*dest, *source, tbyte;
+	unsigned short	*pusdest;
+	int				v, u;
+
+	if (x < 0 || (unsigned)(x + pic->width) > vid.width || y < 0 ||
+		 (unsigned)(y + pic->height) > vid.height)
+	{
+		Sys_Error ("Draw_TransPic: bad coordinates");
+	}
+		
+	source = pic->data;
+
+	if (r_pixbytes == 1)
+	{
+		dest = vid.buffer + y * vid.rowbytes + x;
+
+		if (pic->width & 7)
+		{	// general
+			for (v=0 ; v<pic->height ; v++)
+			{
+				for (u=0 ; u<pic->width ; u++)
+					if ( (tbyte=source[u]) != TRANSPARENT_COLOR)
+						dest[u] = translation[tbyte];
+
+				dest += vid.rowbytes;
+				source += pic->width;
+			}
+		}
+		else
+		{	// unwound
+			for (v=0 ; v<pic->height ; v++)
+			{
+				for (u=0 ; u<pic->width ; u+=8)
+				{
+					if ( (tbyte=source[u]) != TRANSPARENT_COLOR)
+						dest[u] = translation[tbyte];
+					if ( (tbyte=source[u+1]) != TRANSPARENT_COLOR)
+						dest[u+1] = translation[tbyte];
+					if ( (tbyte=source[u+2]) != TRANSPARENT_COLOR)
+						dest[u+2] = translation[tbyte];
+					if ( (tbyte=source[u+3]) != TRANSPARENT_COLOR)
+						dest[u+3] = translation[tbyte];
+					if ( (tbyte=source[u+4]) != TRANSPARENT_COLOR)
+						dest[u+4] = translation[tbyte];
+					if ( (tbyte=source[u+5]) != TRANSPARENT_COLOR)
+						dest[u+5] = translation[tbyte];
+					if ( (tbyte=source[u+6]) != TRANSPARENT_COLOR)
+						dest[u+6] = translation[tbyte];
+					if ( (tbyte=source[u+7]) != TRANSPARENT_COLOR)
+						dest[u+7] = translation[tbyte];
+				}
+				dest += vid.rowbytes;
+				source += pic->width;
+			}
+		}
+	}
+	else
+	{
+	// FIXME: pretranslate at load time?
+		pusdest = (unsigned short *)vid.buffer + y * (vid.rowbytes >> 1) + x;
+
+		for (v=0 ; v<pic->height ; v++)
+		{
+			for (u=0 ; u<pic->width ; u++)
+			{
+				tbyte = source[u];
+
+				if (tbyte != TRANSPARENT_COLOR)
+				{
+					pusdest[u] = d_8to16table[tbyte];
+				}
+			}
+
+			pusdest += vid.rowbytes >> 1;
+			source += pic->width;
+		}
+	}
+}
+
+
+void Draw_CharToConback (int num, byte *dest)
+{
+	int		row, col;
+	byte	*source;
+	int		drawline;
+	int		x;
+
+	row = num>>4;
+	col = num&15;
+	source = draw_chars + (row<<10) + (col<<3);
+
+	drawline = 8;
+
+	while (drawline--)
+	{
+		for (x=0 ; x<8 ; x++)
+			if (source[x])
+				dest[x] = 0x60 + source[x];
+		source += 128;
+		dest += 320;
+	}
+
+}
+
+/*
+================
+Draw_ConsoleBackground
+
+================
+*/
+void Draw_ConsoleBackground (int lines)
+{
+	int				x, y, v;
+	byte			*src, *dest;
+	unsigned short	*pusdest;
+	int				f, fstep;
+	qpic_t			*conback;
+	char			ver[100];
+	static			char saveback[320*8];
+
+	conback = Draw_CachePic ("gfx/conback.lmp");
+
+// hack the version number directly into the pic
+
+	//sprintf (ver, "start commands with a \\ character %4.2f", VERSION);
+
+	if (cls.download) {
+		sprintf (ver, "%4.2f", VERSION);
+		dest = conback->data + 320 + 320*186 - 11 - 8*strlen(ver);
+	} else {
+#if defined(__linux__)
+		sprintf (ver, "Linux (%4.2f) QuakeWorld %4.2f", LINUX_VERSION, VERSION);
+#else
+		sprintf (ver, "QuakeWorld %4.2f", VERSION);
+#endif
+		dest = conback->data + 320 - (strlen(ver)*8 + 11) + 320*186;
+	}
+
+	memcpy(saveback, conback->data + 320*186, 320*8);
+	for (x=0 ; x<strlen(ver) ; x++)
+		Draw_CharToConback (ver[x], dest+(x<<3));
+	
+// draw the pic
+	if (r_pixbytes == 1)
+	{
+		dest = vid.conbuffer;
+
+		for (y=0 ; y<lines ; y++, dest += vid.conrowbytes)
+		{
+			v = (vid.conheight - lines + y)*200/vid.conheight;
+			src = conback->data + v*320;
+			if (vid.conwidth == 320)
+				memcpy (dest, src, vid.conwidth);
+			else
+			{
+				f = 0;
+				fstep = 320*0x10000/vid.conwidth;
+				for (x=0 ; x<vid.conwidth ; x+=4)
+				{
+					dest[x] = src[f>>16];
+					f += fstep;
+					dest[x+1] = src[f>>16];
+					f += fstep;
+					dest[x+2] = src[f>>16];
+					f += fstep;
+					dest[x+3] = src[f>>16];
+					f += fstep;
+				}
+			}
+		}
+	}
+	else
+	{
+		pusdest = (unsigned short *)vid.conbuffer;
+
+		for (y=0 ; y<lines ; y++, pusdest += (vid.conrowbytes >> 1))
+		{
+		// FIXME: pre-expand to native format?
+		// FIXME: does the endian switching go away in production?
+			v = (vid.conheight - lines + y)*200/vid.conheight;
+			src = conback->data + v*320;
+			f = 0;
+			fstep = 320*0x10000/vid.conwidth;
+			for (x=0 ; x<vid.conwidth ; x+=4)
+			{
+				pusdest[x] = d_8to16table[src[f>>16]];
+				f += fstep;
+				pusdest[x+1] = d_8to16table[src[f>>16]];
+				f += fstep;
+				pusdest[x+2] = d_8to16table[src[f>>16]];
+				f += fstep;
+				pusdest[x+3] = d_8to16table[src[f>>16]];
+				f += fstep;
+			}
+		}
+	}
+	// put it back
+	memcpy(conback->data + 320*186, saveback, 320*8);
+}
+
+
+/*
+==============
+R_DrawRect8
+==============
+*/
+void R_DrawRect8 (vrect_t *prect, int rowbytes, byte *psrc,
+	int transparent)
+{
+	byte	t;
+	int		i, j, srcdelta, destdelta;
+	byte	*pdest;
+
+	pdest = vid.buffer + (prect->y * vid.rowbytes) + prect->x;
+
+	srcdelta = rowbytes - prect->width;
+	destdelta = vid.rowbytes - prect->width;
+
+	if (transparent)
+	{
+		for (i=0 ; i<prect->height ; i++)
+		{
+			for (j=0 ; j<prect->width ; j++)
+			{
+				t = *psrc;
+				if (t != TRANSPARENT_COLOR)
+				{
+					*pdest = t;
+				}
+
+				psrc++;
+				pdest++;
+			}
+
+			psrc += srcdelta;
+			pdest += destdelta;
+		}
+	}
+	else
+	{
+		for (i=0 ; i<prect->height ; i++)
+		{
+			memcpy (pdest, psrc, prect->width);
+			psrc += rowbytes;
+			pdest += vid.rowbytes;
+		}
+	}
+}
+
+
+/*
+==============
+R_DrawRect16
+==============
+*/
+void R_DrawRect16 (vrect_t *prect, int rowbytes, byte *psrc,
+	int transparent)
+{
+	byte			t;
+	int				i, j, srcdelta, destdelta;
+	unsigned short	*pdest;
+
+// FIXME: would it be better to pre-expand native-format versions?
+
+	pdest = (unsigned short *)vid.buffer +
+			(prect->y * (vid.rowbytes >> 1)) + prect->x;
+
+	srcdelta = rowbytes - prect->width;
+	destdelta = (vid.rowbytes >> 1) - prect->width;
+
+	if (transparent)
+	{
+		for (i=0 ; i<prect->height ; i++)
+		{
+			for (j=0 ; j<prect->width ; j++)
+			{
+				t = *psrc;
+				if (t != TRANSPARENT_COLOR)
+				{
+					*pdest = d_8to16table[t];
+				}
+
+				psrc++;
+				pdest++;
+			}
+
+			psrc += srcdelta;
+			pdest += destdelta;
+		}
+	}
+	else
+	{
+		for (i=0 ; i<prect->height ; i++)
+		{
+			for (j=0 ; j<prect->width ; j++)
+			{
+				*pdest = d_8to16table[*psrc];
+				psrc++;
+				pdest++;
+			}
+
+			psrc += srcdelta;
+			pdest += destdelta;
+		}
+	}
+}
+
+
+/*
+=============
+Draw_TileClear
+
+This repeats a 64*64 tile graphic to fill the screen around a sized down
+refresh window.
+=============
+*/
+void Draw_TileClear (int x, int y, int w, int h)
+{
+	int				width, height, tileoffsetx, tileoffsety;
+	byte			*psrc;
+	vrect_t			vr;
+
+	r_rectdesc.rect.x = x;
+	r_rectdesc.rect.y = y;
+	r_rectdesc.rect.width = w;
+	r_rectdesc.rect.height = h;
+
+	vr.y = r_rectdesc.rect.y;
+	height = r_rectdesc.rect.height;
+
+	tileoffsety = vr.y % r_rectdesc.height;
+
+	while (height > 0)
+	{
+		vr.x = r_rectdesc.rect.x;
+		width = r_rectdesc.rect.width;
+
+		if (tileoffsety != 0)
+			vr.height = r_rectdesc.height - tileoffsety;
+		else
+			vr.height = r_rectdesc.height;
+
+		if (vr.height > height)
+			vr.height = height;
+
+		tileoffsetx = vr.x % r_rectdesc.width;
+
+		while (width > 0)
+		{
+			if (tileoffsetx != 0)
+				vr.width = r_rectdesc.width - tileoffsetx;
+			else
+				vr.width = r_rectdesc.width;
+
+			if (vr.width > width)
+				vr.width = width;
+
+			psrc = r_rectdesc.ptexbytes +
+					(tileoffsety * r_rectdesc.rowbytes) + tileoffsetx;
+
+			if (r_pixbytes == 1)
+			{
+				R_DrawRect8 (&vr, r_rectdesc.rowbytes, psrc, 0);
+			}
+			else
+			{
+				R_DrawRect16 (&vr, r_rectdesc.rowbytes, psrc, 0);
+			}
+
+			vr.x += vr.width;
+			width -= vr.width;
+			tileoffsetx = 0;	// only the left tile can be left-clipped
+		}
+
+		vr.y += vr.height;
+		height -= vr.height;
+		tileoffsety = 0;		// only the top tile can be top-clipped
+	}
+}
+
+
+/*
+=============
+Draw_Fill
+
+Fills a box of pixels with a single color
+=============
+*/
+void Draw_Fill (int x, int y, int w, int h, int c)
+{
+	byte			*dest;
+	unsigned short	*pusdest;
+	unsigned		uc;
+	int				u, v;
+
+	if (x < 0 || x + w > vid.width ||
+		y < 0 || y + h > vid.height) {
+		Con_Printf("Bad Draw_Fill(%d, %d, %d, %d, %c)\n",
+			x, y, w, h, c);
+		return;
+	}
+
+	if (r_pixbytes == 1)
+	{
+		dest = vid.buffer + y*vid.rowbytes + x;
+		for (v=0 ; v<h ; v++, dest += vid.rowbytes)
+			for (u=0 ; u<w ; u++)
+				dest[u] = c;
+	}
+	else
+	{
+		uc = d_8to16table[c];
+
+		pusdest = (unsigned short *)vid.buffer + y * (vid.rowbytes >> 1) + x;
+		for (v=0 ; v<h ; v++, pusdest += (vid.rowbytes >> 1))
+			for (u=0 ; u<w ; u++)
+				pusdest[u] = uc;
+	}
+}
+//=============================================================================
+
+/*
+================
+Draw_FadeScreen
+
+================
+*/
+void Draw_FadeScreen (void)
+{
+	int			x,y;
+	byte		*pbuf;
+
+	VID_UnlockBuffer ();
+	S_ExtraUpdate ();
+	VID_LockBuffer ();
+
+	for (y=0 ; y<vid.height ; y++)
+	{
+		int	t;
+
+		pbuf = (byte *)(vid.buffer + vid.rowbytes*y);
+		t = (y & 1) << 1;
+
+		for (x=0 ; x<vid.width ; x++)
+		{
+			if ((x & 3) != t)
+				pbuf[x] = 0;
+		}
+	}
+
+	VID_UnlockBuffer ();
+	S_ExtraUpdate ();
+	VID_LockBuffer ();
+}
+
+//=============================================================================
+
+/*
+================
+Draw_BeginDisc
+
+Draws the little blue disc in the corner of the screen.
+Call before beginning any disc IO.
+================
+*/
+void Draw_BeginDisc (void)
+{
+
+	D_BeginDirectRect (vid.width - 24, 0, draw_disc->data, 24, 24);
+}
+
+
+/*
+================
+Draw_EndDisc
+
+Erases the disc icon.
+Call after completing any disc IO
+================
+*/
+void Draw_EndDisc (void)
+{
+
+	D_EndDirectRect (vid.width - 24, 0, 24, 24);
+}
+
--- /dev/null
+++ b/QW/client/draw.h
@@ -1,0 +1,43 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+
+// draw.h -- these are the only functions outside the refresh allowed
+// to touch the vid buffer
+
+extern	qpic_t		*draw_disc;	// also used on sbar
+
+void Draw_Init (void);
+void Draw_Character (int x, int y, int num);
+void Draw_DebugChar (char num);
+void Draw_SubPic(int x, int y, qpic_t *pic, int srcx, int srcy, int width, int height);
+void Draw_Pic (int x, int y, qpic_t *pic);
+void Draw_TransPic (int x, int y, qpic_t *pic);
+void Draw_TransPicTranslate (int x, int y, qpic_t *pic, byte *translation);
+void Draw_ConsoleBackground (int lines);
+void Draw_BeginDisc (void);
+void Draw_EndDisc (void);
+void Draw_TileClear (int x, int y, int w, int h);
+void Draw_Fill (int x, int y, int w, int h, int c);
+void Draw_FadeScreen (void);
+void Draw_String (int x, int y, char *str);
+void Draw_Alt_String (int x, int y, char *str);
+qpic_t *Draw_PicFromWad (char *name);
+qpic_t *Draw_CachePic (char *path);
+void Draw_Crosshair(void);
--- /dev/null
+++ b/QW/client/exitscrn.txt
@@ -1,0 +1,22 @@
+            QuakeWorld
+    version 1.64 by id Software
+
+Programming
+ John Carmack    Michael Abrash
+ John Cash       Christian Antkow
+
+Additional Programming
+ Dave 'Zoid' Kirsch
+   Courtesy of ThreeWave Software
+ Jack 'morbid' Mathews
+   Courtesy of the QuakeSpy Team
+
+QuakeWorld is an unsupported
+product of id Software.
+
+Quake is a trademark of Id Software,
+inc., (c)1996, 1997 Id Software, inc.
+All rights reserved. NIN logo is a
+registered trademark licensed to
+Nothing Interactive, Inc. All rights
+reserved. Press y to exit
--- /dev/null
+++ b/QW/client/gl_draw.c
@@ -1,0 +1,1378 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+
+// draw.c -- this is the only file outside the refresh that touches the
+// vid buffer
+
+#include "quakedef.h"
+
+extern unsigned char d_15to8table[65536];
+extern cvar_t crosshair, cl_crossx, cl_crossy, crosshaircolor;
+
+cvar_t		gl_nobind = {"gl_nobind", "0"};
+cvar_t		gl_max_size = {"gl_max_size", "1024"};
+cvar_t		gl_picmip = {"gl_picmip", "0"};
+
+byte		*draw_chars;				// 8*8 graphic characters
+qpic_t		*draw_disc;
+qpic_t		*draw_backtile;
+
+int			translate_texture;
+int			char_texture;
+int			cs_texture; // crosshair texture
+
+static byte cs_data[64] = {
+	0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff,
+	0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xff,
+	0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
+};
+
+
+typedef struct
+{
+	int		texnum;
+	float	sl, tl, sh, th;
+} glpic_t;
+
+byte		conback_buffer[sizeof(qpic_t) + sizeof(glpic_t)];
+qpic_t		*conback = (qpic_t *)&conback_buffer;
+
+int		gl_lightmap_format = 4;
+int		gl_solid_format = 3;
+int		gl_alpha_format = 4;
+
+int		gl_filter_min = GL_LINEAR_MIPMAP_NEAREST;
+int		gl_filter_max = GL_LINEAR;
+
+
+int		texels;
+
+typedef struct
+{
+	int		texnum;
+	char	identifier[64];
+	int		width, height;
+	qboolean	mipmap;
+} gltexture_t;
+
+#define	MAX_GLTEXTURES	1024
+gltexture_t	gltextures[MAX_GLTEXTURES];
+int			numgltextures;
+
+void GL_Bind (int texnum)
+{
+	if (gl_nobind.value)
+		texnum = char_texture;
+	if (currenttexture == texnum)
+		return;
+	currenttexture = texnum;
+#ifdef _WIN32
+	bindTexFunc (GL_TEXTURE_2D, texnum);
+#else
+	glBindTexture (GL_TEXTURE_2D, texnum);
+#endif
+}
+
+
+/*
+=============================================================================
+
+  scrap allocation
+
+  Allocate all the little status bar obejcts into a single texture
+  to crutch up stupid hardware / drivers
+
+=============================================================================
+*/
+
+#define	MAX_SCRAPS		1
+#define	BLOCK_WIDTH		256
+#define	BLOCK_HEIGHT	256
+
+int			scrap_allocated[MAX_SCRAPS][BLOCK_WIDTH];
+byte		scrap_texels[MAX_SCRAPS][BLOCK_WIDTH*BLOCK_HEIGHT*4];
+qboolean	scrap_dirty;
+int			scrap_texnum;
+
+// returns a texture number and the position inside it
+int Scrap_AllocBlock (int w, int h, int *x, int *y)
+{
+	int		i, j;
+	int		best, best2;
+	int		texnum;
+
+	for (texnum=0 ; texnum<MAX_SCRAPS ; texnum++)
+	{
+		best = BLOCK_HEIGHT;
+
+		for (i=0 ; i<BLOCK_WIDTH-w ; i++)
+		{
+			best2 = 0;
+
+			for (j=0 ; j<w ; j++)
+			{
+				if (scrap_allocated[texnum][i+j] >= best)
+					break;
+				if (scrap_allocated[texnum][i+j] > best2)
+					best2 = scrap_allocated[texnum][i+j];
+			}
+			if (j == w)
+			{	// this is a valid spot
+				*x = i;
+				*y = best = best2;
+			}
+		}
+
+		if (best + h > BLOCK_HEIGHT)
+			continue;
+
+		for (i=0 ; i<w ; i++)
+			scrap_allocated[texnum][*x + i] = best + h;
+
+		return texnum;
+	}
+
+	Sys_Error ("Scrap_AllocBlock: full");
+	return 0;
+}
+
+int	scrap_uploads;
+
+void Scrap_Upload (void)
+{
+	scrap_uploads++;
+	GL_Bind(scrap_texnum);
+	GL_Upload8 (scrap_texels[0], BLOCK_WIDTH, BLOCK_HEIGHT, false, true);
+	scrap_dirty = false;
+}
+
+//=============================================================================
+/* Support Routines */
+
+typedef struct cachepic_s
+{
+	char		name[MAX_QPATH];
+	qpic_t		pic;
+	byte		padding[32];	// for appended glpic
+} cachepic_t;
+
+#define	MAX_CACHED_PICS		128
+cachepic_t	menu_cachepics[MAX_CACHED_PICS];
+int			menu_numcachepics;
+
+byte		menuplyr_pixels[4096];
+
+int		pic_texels;
+int		pic_count;
+
+qpic_t *Draw_PicFromWad (char *name)
+{
+	qpic_t	*p;
+	glpic_t	*gl;
+
+	p = W_GetLumpName (name);
+	gl = (glpic_t *)p->data;
+
+	// load little ones into the scrap
+	if (p->width < 64 && p->height < 64)
+	{
+		int		x, y;
+		int		i, j, k;
+		int		texnum;
+
+		texnum = Scrap_AllocBlock (p->width, p->height, &x, &y);
+		scrap_dirty = true;
+		k = 0;
+		for (i=0 ; i<p->height ; i++)
+			for (j=0 ; j<p->width ; j++, k++)
+				scrap_texels[texnum][(y+i)*BLOCK_WIDTH + x + j] = p->data[k];
+		texnum += scrap_texnum;
+		gl->texnum = texnum;
+		gl->sl = (x+0.01)/(float)BLOCK_WIDTH;
+		gl->sh = (x+p->width-0.01)/(float)BLOCK_WIDTH;
+		gl->tl = (y+0.01)/(float)BLOCK_WIDTH;
+		gl->th = (y+p->height-0.01)/(float)BLOCK_WIDTH;
+
+		pic_count++;
+		pic_texels += p->width*p->height;
+	}
+	else
+	{
+		gl->texnum = GL_LoadPicTexture (p);
+		gl->sl = 0;
+		gl->sh = 1;
+		gl->tl = 0;
+		gl->th = 1;
+	}
+	return p;
+}
+
+
+/*
+================
+Draw_CachePic
+================
+*/
+qpic_t	*Draw_CachePic (char *path)
+{
+	cachepic_t	*pic;
+	int			i;
+	qpic_t		*dat;
+	glpic_t		*gl;
+
+	for (pic=menu_cachepics, i=0 ; i<menu_numcachepics ; pic++, i++)
+		if (!strcmp (path, pic->name))
+			return &pic->pic;
+
+	if (menu_numcachepics == MAX_CACHED_PICS)
+		Sys_Error ("menu_numcachepics == MAX_CACHED_PICS");
+	menu_numcachepics++;
+	strcpy (pic->name, path);
+
+//
+// load the pic from disk
+//
+	dat = (qpic_t *)COM_LoadTempFile (path);	
+	if (!dat)
+		Sys_Error ("Draw_CachePic: failed to load %s", path);
+	SwapPic (dat);
+
+	// HACK HACK HACK --- we need to keep the bytes for
+	// the translatable player picture just for the menu
+	// configuration dialog
+	if (!strcmp (path, "gfx/menuplyr.lmp"))
+		memcpy (menuplyr_pixels, dat->data, dat->width*dat->height);
+
+	pic->pic.width = dat->width;
+	pic->pic.height = dat->height;
+
+	gl = (glpic_t *)pic->pic.data;
+	gl->texnum = GL_LoadPicTexture (dat);
+	gl->sl = 0;
+	gl->sh = 1;
+	gl->tl = 0;
+	gl->th = 1;
+
+	return &pic->pic;
+}
+
+
+void Draw_CharToConback (int num, byte *dest)
+{
+	int		row, col;
+	byte	*source;
+	int		drawline;
+	int		x;
+
+	row = num>>4;
+	col = num&15;
+	source = draw_chars + (row<<10) + (col<<3);
+
+	drawline = 8;
+
+	while (drawline--)
+	{
+		for (x=0 ; x<8 ; x++)
+			if (source[x] != 255)
+				dest[x] = 0x60 + source[x];
+		source += 128;
+		dest += 320;
+	}
+
+}
+
+typedef struct
+{
+	char *name;
+	int	minimize, maximize;
+} glmode_t;
+
+glmode_t modes[] = {
+	{"GL_NEAREST", GL_NEAREST, GL_NEAREST},
+	{"GL_LINEAR", GL_LINEAR, GL_LINEAR},
+	{"GL_NEAREST_MIPMAP_NEAREST", GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST},
+	{"GL_LINEAR_MIPMAP_NEAREST", GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR},
+	{"GL_NEAREST_MIPMAP_LINEAR", GL_NEAREST_MIPMAP_LINEAR, GL_NEAREST},
+	{"GL_LINEAR_MIPMAP_LINEAR", GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR}
+};
+
+/*
+===============
+Draw_TextureMode_f
+===============
+*/
+void Draw_TextureMode_f (void)
+{
+	int		i;
+	gltexture_t	*glt;
+
+	if (Cmd_Argc() == 1)
+	{
+		for (i=0 ; i< 6 ; i++)
+			if (gl_filter_min == modes[i].minimize)
+			{
+				Con_Printf ("%s\n", modes[i].name);
+				return;
+			}
+		Con_Printf ("current filter is unknown???\n");
+		return;
+	}
+
+	for (i=0 ; i< 6 ; i++)
+	{
+		if (!Q_strcasecmp (modes[i].name, Cmd_Argv(1) ) )
+			break;
+	}
+	if (i == 6)
+	{
+		Con_Printf ("bad filter name\n");
+		return;
+	}
+
+	gl_filter_min = modes[i].minimize;
+	gl_filter_max = modes[i].maximize;
+
+	// change all the existing mipmap texture objects
+	for (i=0, glt=gltextures ; i<numgltextures ; i++, glt++)
+	{
+		if (glt->mipmap)
+		{
+			GL_Bind (glt->texnum);
+			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
+			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
+		}
+	}
+}
+
+/*
+===============
+Draw_Init
+===============
+*/
+void Draw_Init (void)
+{
+	int		i;
+	qpic_t	*cb;
+	byte	*dest;
+	int		x;
+	char	ver[40];
+	glpic_t	*gl;
+	int start;
+	byte    *ncdata;
+
+	Cvar_RegisterVariable (&gl_nobind);
+	Cvar_RegisterVariable (&gl_max_size);
+	Cvar_RegisterVariable (&gl_picmip);
+
+	// 3dfx can only handle 256 wide textures
+	if (!Q_strncasecmp ((char *)gl_renderer, "3dfx",4) ||
+		!Q_strncasecmp ((char *)gl_renderer, "Mesa",4))
+		Cvar_Set ("gl_max_size", "256");
+
+	Cmd_AddCommand ("gl_texturemode", &Draw_TextureMode_f);
+
+	// load the console background and the charset
+	// by hand, because we need to write the version
+	// string into the background before turning
+	// it into a texture
+	draw_chars = W_GetLumpName ("conchars");
+	for (i=0 ; i<256*64 ; i++)
+		if (draw_chars[i] == 0)
+			draw_chars[i] = 255;	// proper transparent color
+
+	// now turn them into textures
+	char_texture = GL_LoadTexture ("charset", 128, 128, draw_chars, false, true);
+//	Draw_CrosshairAdjust();
+	cs_texture = GL_LoadTexture ("crosshair", 8, 8, cs_data, false, true);
+
+	start = Hunk_LowMark ();
+
+	cb = (qpic_t *)COM_LoadHunkFile ("gfx/conback.lmp");	
+	if (!cb)
+		Sys_Error ("Couldn't load gfx/conback.lmp");
+	SwapPic (cb);
+
+	sprintf (ver, "%4.2f", VERSION);
+	dest = cb->data + 320 + 320*186 - 11 - 8*strlen(ver);
+	for (x=0 ; x<strlen(ver) ; x++)
+		Draw_CharToConback (ver[x], dest+(x<<3));
+
+#if 0
+	conback->width = vid.conwidth;
+	conback->height = vid.conheight;
+
+	// scale console to vid size
+	dest = ncdata = Hunk_AllocName(vid.conwidth * vid.conheight, "conback");
+
+	for (y=0 ; y<vid.conheight ; y++, dest += vid.conwidth)
+	{
+		src = cb->data + cb->width * (y*cb->height/vid.conheight);
+		if (vid.conwidth == cb->width)
+			memcpy (dest, src, vid.conwidth);
+		else
+		{
+			f = 0;
+			fstep = cb->width*0x10000/vid.conwidth;
+			for (x=0 ; x<vid.conwidth ; x+=4)
+			{
+				dest[x] = src[f>>16];
+				f += fstep;
+				dest[x+1] = src[f>>16];
+				f += fstep;
+				dest[x+2] = src[f>>16];
+				f += fstep;
+				dest[x+3] = src[f>>16];
+				f += fstep;
+			}
+		}
+	}
+#else
+	conback->width = cb->width;
+	conback->height = cb->height;
+	ncdata = cb->data;
+#endif
+	
+	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
+	gl = (glpic_t *)conback->data;
+	gl->texnum = GL_LoadTexture ("conback", conback->width, conback->height, ncdata, false, false);
+	gl->sl = 0;
+	gl->sh = 1;
+	gl->tl = 0;
+	gl->th = 1;
+	conback->width = vid.conwidth;
+	conback->height = vid.conheight;
+
+	// free loaded console
+	Hunk_FreeToLowMark (start);
+
+	// save a texture slot for translated picture
+	translate_texture = texture_extension_number++;
+
+	// save slots for scraps
+	scrap_texnum = texture_extension_number;
+	texture_extension_number += MAX_SCRAPS;
+
+	//
+	// get the other pics we need
+	//
+	draw_disc = Draw_PicFromWad ("disc");
+	draw_backtile = Draw_PicFromWad ("backtile");
+}
+
+
+
+/*
+================
+Draw_Character
+
+Draws one 8*8 graphics character with 0 being transparent.
+It can be clipped to the top of the screen to allow the console to be
+smoothly scrolled off.
+================
+*/
+void Draw_Character (int x, int y, int num)
+{
+	int				row, col;
+	float			frow, fcol, size;
+
+	if (num == 32)
+		return;		// space
+
+	num &= 255;
+	
+	if (y <= -8)
+		return;			// totally off screen
+
+	row = num>>4;
+	col = num&15;
+
+	frow = row*0.0625;
+	fcol = col*0.0625;
+	size = 0.0625;
+
+	GL_Bind (char_texture);
+
+	glBegin (GL_QUADS);
+	glTexCoord2f (fcol, frow);
+	glVertex2f (x, y);
+	glTexCoord2f (fcol + size, frow);
+	glVertex2f (x+8, y);
+	glTexCoord2f (fcol + size, frow + size);
+	glVertex2f (x+8, y+8);
+	glTexCoord2f (fcol, frow + size);
+	glVertex2f (x, y+8);
+	glEnd ();
+}
+
+/*
+================
+Draw_String
+================
+*/
+void Draw_String (int x, int y, char *str)
+{
+	while (*str)
+	{
+		Draw_Character (x, y, *str);
+		str++;
+		x += 8;
+	}
+}
+
+/*
+================
+Draw_Alt_String
+================
+*/
+void Draw_Alt_String (int x, int y, char *str)
+{
+	while (*str)
+	{
+		Draw_Character (x, y, (*str) | 0x80);
+		str++;
+		x += 8;
+	}
+}
+
+void Draw_Crosshair(void)
+{
+	int x, y;
+	extern vrect_t		scr_vrect;
+	unsigned char *pColor;
+
+	if (crosshair.value == 2) {
+		x = scr_vrect.x + scr_vrect.width/2 - 3 + cl_crossx.value; 
+		y = scr_vrect.y + scr_vrect.height/2 - 3 + cl_crossy.value;
+
+		glTexEnvf ( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
+		pColor = (unsigned char *) &d_8to24table[(byte) crosshaircolor.value];
+		glColor4ubv ( pColor );
+		GL_Bind (cs_texture);
+
+		glBegin (GL_QUADS);
+		glTexCoord2f (0, 0);
+		glVertex2f (x - 4, y - 4);
+		glTexCoord2f (1, 0);
+		glVertex2f (x+12, y-4);
+		glTexCoord2f (1, 1);
+		glVertex2f (x+12, y+12);
+		glTexCoord2f (0, 1);
+		glVertex2f (x - 4, y+12);
+		glEnd ();
+		
+		glTexEnvf ( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
+	} else if (crosshair.value)
+		Draw_Character (scr_vrect.x + scr_vrect.width/2-4 + cl_crossx.value, 
+			scr_vrect.y + scr_vrect.height/2-4 + cl_crossy.value, 
+			'+');
+}
+
+
+/*
+================
+Draw_DebugChar
+
+Draws a single character directly to the upper right corner of the screen.
+This is for debugging lockups by drawing different chars in different parts
+of the code.
+================
+*/
+void Draw_DebugChar (char num)
+{
+}
+
+/*
+=============
+Draw_Pic
+=============
+*/
+void Draw_Pic (int x, int y, qpic_t *pic)
+{
+	glpic_t			*gl;
+
+	if (scrap_dirty)
+		Scrap_Upload ();
+	gl = (glpic_t *)pic->data;
+	glColor4f (1,1,1,1);
+	GL_Bind (gl->texnum);
+	glBegin (GL_QUADS);
+	glTexCoord2f (gl->sl, gl->tl);
+	glVertex2f (x, y);
+	glTexCoord2f (gl->sh, gl->tl);
+	glVertex2f (x+pic->width, y);
+	glTexCoord2f (gl->sh, gl->th);
+	glVertex2f (x+pic->width, y+pic->height);
+	glTexCoord2f (gl->sl, gl->th);
+	glVertex2f (x, y+pic->height);
+	glEnd ();
+}
+
+/*
+=============
+Draw_AlphaPic
+=============
+*/
+void Draw_AlphaPic (int x, int y, qpic_t *pic, float alpha)
+{
+	glpic_t			*gl;
+
+	if (scrap_dirty)
+		Scrap_Upload ();
+	gl = (glpic_t *)pic->data;
+	glDisable(GL_ALPHA_TEST);
+	glEnable (GL_BLEND);
+//	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+	glCullFace(GL_FRONT);
+	glColor4f (1,1,1,alpha);
+	GL_Bind (gl->texnum);
+	glBegin (GL_QUADS);
+	glTexCoord2f (gl->sl, gl->tl);
+	glVertex2f (x, y);
+	glTexCoord2f (gl->sh, gl->tl);
+	glVertex2f (x+pic->width, y);
+	glTexCoord2f (gl->sh, gl->th);
+	glVertex2f (x+pic->width, y+pic->height);
+	glTexCoord2f (gl->sl, gl->th);
+	glVertex2f (x, y+pic->height);
+	glEnd ();
+	glColor4f (1,1,1,1);
+	glEnable(GL_ALPHA_TEST);
+	glDisable (GL_BLEND);
+}
+
+void Draw_SubPic(int x, int y, qpic_t *pic, int srcx, int srcy, int width, int height)
+{
+	glpic_t			*gl;
+	float newsl, newtl, newsh, newth;
+	float oldglwidth, oldglheight;
+
+	if (scrap_dirty)
+		Scrap_Upload ();
+	gl = (glpic_t *)pic->data;
+	
+	oldglwidth = gl->sh - gl->sl;
+	oldglheight = gl->th - gl->tl;
+
+	newsl = gl->sl + (srcx*oldglwidth)/pic->width;
+	newsh = newsl + (width*oldglwidth)/pic->width;
+
+	newtl = gl->tl + (srcy*oldglheight)/pic->height;
+	newth = newtl + (height*oldglheight)/pic->height;
+	
+	glColor4f (1,1,1,1);
+	GL_Bind (gl->texnum);
+	glBegin (GL_QUADS);
+	glTexCoord2f (newsl, newtl);
+	glVertex2f (x, y);
+	glTexCoord2f (newsh, newtl);
+	glVertex2f (x+width, y);
+	glTexCoord2f (newsh, newth);
+	glVertex2f (x+width, y+height);
+	glTexCoord2f (newsl, newth);
+	glVertex2f (x, y+height);
+	glEnd ();
+}
+
+/*
+=============
+Draw_TransPic
+=============
+*/
+void Draw_TransPic (int x, int y, qpic_t *pic)
+{
+
+	if (x < 0 || (unsigned)(x + pic->width) > vid.width || y < 0 ||
+		 (unsigned)(y + pic->height) > vid.height)
+	{
+		Sys_Error ("Draw_TransPic: bad coordinates");
+	}
+		
+	Draw_Pic (x, y, pic);
+}
+
+
+/*
+=============
+Draw_TransPicTranslate
+
+Only used for the player color selection menu
+=============
+*/
+void Draw_TransPicTranslate (int x, int y, qpic_t *pic, byte *translation)
+{
+	int				v, u, c;
+	unsigned		trans[64*64], *dest;
+	byte			*src;
+	int				p;
+
+	GL_Bind (translate_texture);
+
+	c = pic->width * pic->height;
+
+	dest = trans;
+	for (v=0 ; v<64 ; v++, dest += 64)
+	{
+		src = &menuplyr_pixels[ ((v*pic->height)>>6) *pic->width];
+		for (u=0 ; u<64 ; u++)
+		{
+			p = src[(u*pic->width)>>6];
+			if (p == 255)
+				dest[u] = p;
+			else
+				dest[u] =  d_8to24table[translation[p]];
+		}
+	}
+
+	glTexImage2D (GL_TEXTURE_2D, 0, gl_alpha_format, 64, 64, 0, GL_RGBA, GL_UNSIGNED_BYTE, trans);
+
+	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+	glColor3f (1,1,1);
+	glBegin (GL_QUADS);
+	glTexCoord2f (0, 0);
+	glVertex2f (x, y);
+	glTexCoord2f (1, 0);
+	glVertex2f (x+pic->width, y);
+	glTexCoord2f (1, 1);
+	glVertex2f (x+pic->width, y+pic->height);
+	glTexCoord2f (0, 1);
+	glVertex2f (x, y+pic->height);
+	glEnd ();
+}
+
+
+/*
+================
+Draw_ConsoleBackground
+
+================
+*/
+void Draw_ConsoleBackground (int lines)
+{
+	char ver[80];
+	int x, i;
+	int y;
+
+	y = (vid.height * 3) >> 2;
+	if (lines > y)
+		Draw_Pic(0, lines-vid.height, conback);
+	else
+		Draw_AlphaPic (0, lines - vid.height, conback, (float)(1.2 * lines)/y);
+
+	// hack the version number directly into the pic
+//	y = lines-186;
+	y = lines-14;
+	if (!cls.download) {
+#ifdef __linux__
+		sprintf (ver, "LinuxGL (%4.2f) QuakeWorld", LINUX_VERSION);
+#else
+		sprintf (ver, "GL (%4.2f) QuakeWorld", GLQUAKE_VERSION);
+#endif
+		x = vid.conwidth - (strlen(ver)*8 + 11) - (vid.conwidth*8/320)*7;
+		for (i=0 ; i<strlen(ver) ; i++)
+			Draw_Character (x + i * 8, y, ver[i] | 0x80);
+	}
+}
+
+
+/*
+=============
+Draw_TileClear
+
+This repeats a 64*64 tile graphic to fill the screen around a sized down
+refresh window.
+=============
+*/
+void Draw_TileClear (int x, int y, int w, int h)
+{
+	glColor3f (1,1,1);
+	GL_Bind (*(int *)draw_backtile->data);
+	glBegin (GL_QUADS);
+	glTexCoord2f (x/64.0, y/64.0);
+	glVertex2f (x, y);
+	glTexCoord2f ( (x+w)/64.0, y/64.0);
+	glVertex2f (x+w, y);
+	glTexCoord2f ( (x+w)/64.0, (y+h)/64.0);
+	glVertex2f (x+w, y+h);
+	glTexCoord2f ( x/64.0, (y+h)/64.0 );
+	glVertex2f (x, y+h);
+	glEnd ();
+}
+
+
+/*
+=============
+Draw_Fill
+
+Fills a box of pixels with a single color
+=============
+*/
+void Draw_Fill (int x, int y, int w, int h, int c)
+{
+	glDisable (GL_TEXTURE_2D);
+	glColor3f (host_basepal[c*3]/255.0,
+		host_basepal[c*3+1]/255.0,
+		host_basepal[c*3+2]/255.0);
+
+	glBegin (GL_QUADS);
+
+	glVertex2f (x,y);
+	glVertex2f (x+w, y);
+	glVertex2f (x+w, y+h);
+	glVertex2f (x, y+h);
+
+	glEnd ();
+	glColor3f (1,1,1);
+	glEnable (GL_TEXTURE_2D);
+}
+//=============================================================================
+
+/*
+================
+Draw_FadeScreen
+
+================
+*/
+void Draw_FadeScreen (void)
+{
+	glEnable (GL_BLEND);
+	glDisable (GL_TEXTURE_2D);
+	glColor4f (0, 0, 0, 0.8);
+	glBegin (GL_QUADS);
+
+	glVertex2f (0,0);
+	glVertex2f (vid.width, 0);
+	glVertex2f (vid.width, vid.height);
+	glVertex2f (0, vid.height);
+
+	glEnd ();
+	glColor4f (1,1,1,1);
+	glEnable (GL_TEXTURE_2D);
+	glDisable (GL_BLEND);
+
+	Sbar_Changed();
+}
+
+//=============================================================================
+
+/*
+================
+Draw_BeginDisc
+
+Draws the little blue disc in the corner of the screen.
+Call before beginning any disc IO.
+================
+*/
+void Draw_BeginDisc (void)
+{
+	if (!draw_disc)
+		return;
+	glDrawBuffer  (GL_FRONT);
+	Draw_Pic (vid.width - 24, 0, draw_disc);
+	glDrawBuffer  (GL_BACK);
+}
+
+
+/*
+================
+Draw_EndDisc
+
+Erases the disc icon.
+Call after completing any disc IO
+================
+*/
+void Draw_EndDisc (void)
+{
+}
+
+/*
+================
+GL_Set2D
+
+Setup as if the screen was 320*200
+================
+*/
+void GL_Set2D (void)
+{
+	glViewport (glx, gly, glwidth, glheight);
+
+	glMatrixMode(GL_PROJECTION);
+    glLoadIdentity ();
+	glOrtho  (0, vid.width, vid.height, 0, -99999, 99999);
+
+	glMatrixMode(GL_MODELVIEW);
+    glLoadIdentity ();
+
+	glDisable (GL_DEPTH_TEST);
+	glDisable (GL_CULL_FACE);
+	glDisable (GL_BLEND);
+	glEnable (GL_ALPHA_TEST);
+//	glDisable (GL_ALPHA_TEST);
+
+	glColor4f (1,1,1,1);
+}
+
+//====================================================================
+
+/*
+================
+GL_FindTexture
+================
+*/
+int GL_FindTexture (char *identifier)
+{
+	int		i;
+	gltexture_t	*glt;
+
+	for (i=0, glt=gltextures ; i<numgltextures ; i++, glt++)
+	{
+		if (!strcmp (identifier, glt->identifier))
+			return gltextures[i].texnum;
+	}
+
+	return -1;
+}
+
+/*
+================
+GL_ResampleTexture
+================
+*/
+void GL_ResampleTexture (unsigned *in, int inwidth, int inheight, unsigned *out,  int outwidth, int outheight)
+{
+	int		i, j;
+	unsigned	*inrow;
+	unsigned	frac, fracstep;
+
+	fracstep = inwidth*0x10000/outwidth;
+	for (i=0 ; i<outheight ; i++, out += outwidth)
+	{
+		inrow = in + inwidth*(i*inheight/outheight);
+		frac = fracstep >> 1;
+		for (j=0 ; j<outwidth ; j+=4)
+		{
+			out[j] = inrow[frac>>16];
+			frac += fracstep;
+			out[j+1] = inrow[frac>>16];
+			frac += fracstep;
+			out[j+2] = inrow[frac>>16];
+			frac += fracstep;
+			out[j+3] = inrow[frac>>16];
+			frac += fracstep;
+		}
+	}
+}
+
+/*
+================
+GL_Resample8BitTexture -- JACK
+================
+*/
+void GL_Resample8BitTexture (unsigned char *in, int inwidth, int inheight, unsigned char *out,  int outwidth, int outheight)
+{
+	int		i, j;
+	unsigned	char *inrow;
+	unsigned	frac, fracstep;
+
+	fracstep = inwidth*0x10000/outwidth;
+	for (i=0 ; i<outheight ; i++, out += outwidth)
+	{
+		inrow = in + inwidth*(i*inheight/outheight);
+		frac = fracstep >> 1;
+		for (j=0 ; j<outwidth ; j+=4)
+		{
+			out[j] = inrow[frac>>16];
+			frac += fracstep;
+			out[j+1] = inrow[frac>>16];
+			frac += fracstep;
+			out[j+2] = inrow[frac>>16];
+			frac += fracstep;
+			out[j+3] = inrow[frac>>16];
+			frac += fracstep;
+		}
+	}
+}
+
+/*
+================
+GL_MipMap
+
+Operates in place, quartering the size of the texture
+================
+*/
+void GL_MipMap (byte *in, int width, int height)
+{
+	int		i, j;
+	byte	*out;
+
+	width <<=2;
+	height >>= 1;
+	out = in;
+	for (i=0 ; i<height ; i++, in+=width)
+	{
+		for (j=0 ; j<width ; j+=8, out+=4, in+=8)
+		{
+			out[0] = (in[0] + in[4] + in[width+0] + in[width+4])>>2;
+			out[1] = (in[1] + in[5] + in[width+1] + in[width+5])>>2;
+			out[2] = (in[2] + in[6] + in[width+2] + in[width+6])>>2;
+			out[3] = (in[3] + in[7] + in[width+3] + in[width+7])>>2;
+		}
+	}
+}
+
+/*
+================
+GL_MipMap8Bit
+
+Mipping for 8 bit textures
+================
+*/
+void GL_MipMap8Bit (byte *in, int width, int height)
+{
+	int		i, j;
+	byte	*out;
+	unsigned short     r,g,b;
+	byte	*at1, *at2, *at3, *at4;
+
+	height >>= 1;
+	out = in;
+	for (i=0 ; i<height ; i++, in+=width)
+		for (j=0 ; j<width ; j+=2, out+=1, in+=2)
+		{
+			at1 = (byte *) &d_8to24table[in[0]];
+			at2 = (byte *) &d_8to24table[in[1]];
+			at3 = (byte *) &d_8to24table[in[width+0]];
+			at4 = (byte *) &d_8to24table[in[width+1]];
+
+ 			r = (at1[0]+at2[0]+at3[0]+at4[0]); r>>=5;
+ 			g = (at1[1]+at2[1]+at3[1]+at4[1]); g>>=5;
+ 			b = (at1[2]+at2[2]+at3[2]+at4[2]); b>>=5;
+
+			out[0] = d_15to8table[(r<<0) + (g<<5) + (b<<10)];
+		}
+}
+
+/*
+===============
+GL_Upload32
+===============
+*/
+void GL_Upload32 (unsigned *data, int width, int height,  qboolean mipmap, qboolean alpha)
+{
+	int			samples;
+static	unsigned	scaled[1024*512];	// [512*256];
+	int			scaled_width, scaled_height;
+
+	for (scaled_width = 1 ; scaled_width < width ; scaled_width<<=1)
+		;
+	for (scaled_height = 1 ; scaled_height < height ; scaled_height<<=1)
+		;
+
+	scaled_width >>= (int)gl_picmip.value;
+	scaled_height >>= (int)gl_picmip.value;
+
+	if (scaled_width > gl_max_size.value)
+		scaled_width = gl_max_size.value;
+	if (scaled_height > gl_max_size.value)
+		scaled_height = gl_max_size.value;
+
+	if (scaled_width * scaled_height > sizeof(scaled)/4)
+		Sys_Error ("GL_LoadTexture: too big");
+
+	samples = alpha ? gl_alpha_format : gl_solid_format;
+
+#if 0
+	if (mipmap)
+		gluBuild2DMipmaps (GL_TEXTURE_2D, samples, width, height, GL_RGBA, GL_UNSIGNED_BYTE, trans);
+	else if (scaled_width == width && scaled_height == height)
+		glTexImage2D (GL_TEXTURE_2D, 0, samples, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, trans);
+	else
+	{
+		gluScaleImage (GL_RGBA, width, height, GL_UNSIGNED_BYTE, trans,
+			scaled_width, scaled_height, GL_UNSIGNED_BYTE, scaled);
+		glTexImage2D (GL_TEXTURE_2D, 0, samples, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaled);
+	}
+#else
+texels += scaled_width * scaled_height;
+
+	if (scaled_width == width && scaled_height == height)
+	{
+		if (!mipmap)
+		{
+			glTexImage2D (GL_TEXTURE_2D, 0, samples, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
+			goto done;
+		}
+		memcpy (scaled, data, width*height*4);
+	}
+	else
+		GL_ResampleTexture (data, width, height, scaled, scaled_width, scaled_height);
+
+	glTexImage2D (GL_TEXTURE_2D, 0, samples, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaled);
+	if (mipmap)
+	{
+		int		miplevel;
+
+		miplevel = 0;
+		while (scaled_width > 1 || scaled_height > 1)
+		{
+			GL_MipMap ((byte *)scaled, scaled_width, scaled_height);
+			scaled_width >>= 1;
+			scaled_height >>= 1;
+			if (scaled_width < 1)
+				scaled_width = 1;
+			if (scaled_height < 1)
+				scaled_height = 1;
+			miplevel++;
+			glTexImage2D (GL_TEXTURE_2D, miplevel, samples, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaled);
+		}
+	}
+done: ;
+#endif
+
+
+	if (mipmap)
+	{
+		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
+		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
+	}
+	else
+	{
+		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_max);
+		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
+	}
+}
+
+void GL_Upload8_EXT (byte *data, int width, int height,  qboolean mipmap, qboolean alpha) 
+{
+	int			i, s;
+	qboolean	noalpha;
+	int			samples;
+    static	unsigned char scaled[1024*512];	// [512*256];
+	int			scaled_width, scaled_height;
+
+	s = width*height;
+	// if there are no transparent pixels, make it a 3 component
+	// texture even if it was specified as otherwise
+	if (alpha)
+	{
+		noalpha = true;
+		for (i=0 ; i<s ; i++)
+		{
+			if (data[i] == 255)
+				noalpha = false;
+		}
+
+		if (alpha && noalpha)
+			alpha = false;
+	}
+	for (scaled_width = 1 ; scaled_width < width ; scaled_width<<=1)
+		;
+	for (scaled_height = 1 ; scaled_height < height ; scaled_height<<=1)
+		;
+
+	scaled_width >>= (int)gl_picmip.value;
+	scaled_height >>= (int)gl_picmip.value;
+
+	if (scaled_width > gl_max_size.value)
+		scaled_width = gl_max_size.value;
+	if (scaled_height > gl_max_size.value)
+		scaled_height = gl_max_size.value;
+
+	if (scaled_width * scaled_height > sizeof(scaled))
+		Sys_Error ("GL_LoadTexture: too big");
+
+	samples = 1; // alpha ? gl_alpha_format : gl_solid_format;
+
+	texels += scaled_width * scaled_height;
+
+	if (scaled_width == width && scaled_height == height)
+	{
+		if (!mipmap)
+		{
+			glTexImage2D (GL_TEXTURE_2D, 0, GL_COLOR_INDEX8_EXT, scaled_width, scaled_height, 0, GL_COLOR_INDEX , GL_UNSIGNED_BYTE, data);
+			goto done;
+		}
+		memcpy (scaled, data, width*height);
+	}
+	else
+		GL_Resample8BitTexture (data, width, height, scaled, scaled_width, scaled_height);
+
+	glTexImage2D (GL_TEXTURE_2D, 0, GL_COLOR_INDEX8_EXT, scaled_width, scaled_height, 0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, scaled);
+	if (mipmap)
+	{
+		int		miplevel;
+
+		miplevel = 0;
+		while (scaled_width > 1 || scaled_height > 1)
+		{
+			GL_MipMap8Bit ((byte *)scaled, scaled_width, scaled_height);
+			scaled_width >>= 1;
+			scaled_height >>= 1;
+			if (scaled_width < 1)
+				scaled_width = 1;
+			if (scaled_height < 1)
+				scaled_height = 1;
+			miplevel++;
+			glTexImage2D (GL_TEXTURE_2D, miplevel, GL_COLOR_INDEX8_EXT, scaled_width, scaled_height, 0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, scaled);
+		}
+	}
+done: ;
+
+	if (mipmap)
+	{
+		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
+		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
+	}
+	else
+	{
+		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_max);
+		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
+	}
+}
+
+extern qboolean VID_Is8bit();
+
+/*
+===============
+GL_Upload8
+===============
+*/
+void GL_Upload8 (byte *data, int width, int height,  qboolean mipmap, qboolean alpha)
+{
+static	unsigned	trans[640*480];		// FIXME, temporary
+	int			i, s;
+	qboolean	noalpha;
+	int			p;
+
+	s = width*height;
+	// if there are no transparent pixels, make it a 3 component
+	// texture even if it was specified as otherwise
+	if (alpha)
+	{
+		noalpha = true;
+		for (i=0 ; i<s ; i++)
+		{
+			p = data[i];
+			if (p == 255)
+				noalpha = false;
+			trans[i] = d_8to24table[p];
+		}
+
+		if (alpha && noalpha)
+			alpha = false;
+	}
+	else
+	{
+		if (s&3)
+			Sys_Error ("GL_Upload8: s&3");
+		for (i=0 ; i<s ; i+=4)
+		{
+			trans[i] = d_8to24table[data[i]];
+			trans[i+1] = d_8to24table[data[i+1]];
+			trans[i+2] = d_8to24table[data[i+2]];
+			trans[i+3] = d_8to24table[data[i+3]];
+		}
+	}
+
+	if (VID_Is8bit() && !alpha && (data!=scrap_texels[0])) {
+		GL_Upload8_EXT (data, width, height, mipmap, alpha);
+		return;
+	}
+
+	GL_Upload32 (trans, width, height, mipmap, alpha);
+}
+
+/*
+================
+GL_LoadTexture
+================
+*/
+int GL_LoadTexture (char *identifier, int width, int height, byte *data, qboolean mipmap, qboolean alpha)
+{
+	int			i;
+	gltexture_t	*glt;
+
+	// see if the texture is allready present
+	if (identifier[0])
+	{
+		for (i=0, glt=gltextures ; i<numgltextures ; i++, glt++)
+		{
+			if (!strcmp (identifier, glt->identifier))
+			{
+				if (width != glt->width || height != glt->height)
+					Sys_Error ("GL_LoadTexture: cache mismatch");
+				return gltextures[i].texnum;
+			}
+		}
+	}
+	else
+		glt = &gltextures[numgltextures];
+	numgltextures++;
+
+	strcpy (glt->identifier, identifier);
+	glt->texnum = texture_extension_number;
+	glt->width = width;
+	glt->height = height;
+	glt->mipmap = mipmap;
+
+	GL_Bind(texture_extension_number );
+
+	GL_Upload8 (data, width, height, mipmap, alpha);
+
+	texture_extension_number++;
+
+	return texture_extension_number-1;
+}
+
+/*
+================
+GL_LoadPicTexture
+================
+*/
+int GL_LoadPicTexture (qpic_t *pic)
+{
+	return GL_LoadTexture ("", pic->width, pic->height, pic->data, false, true);
+}
+
+/****************************************/
+
+static GLenum oldtarget = TEXTURE0_SGIS;
+
+void GL_SelectTexture (GLenum target) 
+{
+	if (!gl_mtexable)
+		return;
+#ifndef __linux__ // no multitexture under Linux yet
+	qglSelectTextureSGIS(target);
+#endif
+	if (target == oldtarget) 
+		return;
+	cnttextures[oldtarget-TEXTURE0_SGIS] = currenttexture;
+	currenttexture = cnttextures[target-TEXTURE0_SGIS];
+	oldtarget = target;
+}
--- /dev/null
+++ b/QW/client/gl_mesh.c
@@ -1,0 +1,359 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// gl_mesh.c: triangle model functions
+
+#include "quakedef.h"
+
+/*
+=================================================================
+
+ALIAS MODEL DISPLAY LIST GENERATION
+
+=================================================================
+*/
+
+model_t		*aliasmodel;
+aliashdr_t	*paliashdr;
+
+qboolean	used[8192];
+
+// the command list holds counts and s/t values that are valid for
+// every frame
+int		commands[8192];
+int		numcommands;
+
+// all frames will have their vertexes rearranged and expanded
+// so they are in the order expected by the command list
+int		vertexorder[8192];
+int		numorder;
+
+int		allverts, alltris;
+
+int		stripverts[128];
+int		striptris[128];
+int		stripcount;
+
+/*
+================
+StripLength
+================
+*/
+int	StripLength (int starttri, int startv)
+{
+	int			m1, m2;
+	int			j;
+	mtriangle_t	*last, *check;
+	int			k;
+
+	used[starttri] = 2;
+
+	last = &triangles[starttri];
+
+	stripverts[0] = last->vertindex[(startv)%3];
+	stripverts[1] = last->vertindex[(startv+1)%3];
+	stripverts[2] = last->vertindex[(startv+2)%3];
+
+	striptris[0] = starttri;
+	stripcount = 1;
+
+	m1 = last->vertindex[(startv+2)%3];
+	m2 = last->vertindex[(startv+1)%3];
+
+	// look for a matching triangle
+nexttri:
+	for (j=starttri+1, check=&triangles[starttri+1] ; j<pheader->numtris ; j++, check++)
+	{
+		if (check->facesfront != last->facesfront)
+			continue;
+		for (k=0 ; k<3 ; k++)
+		{
+			if (check->vertindex[k] != m1)
+				continue;
+			if (check->vertindex[ (k+1)%3 ] != m2)
+				continue;
+
+			// this is the next part of the fan
+
+			// if we can't use this triangle, this tristrip is done
+			if (used[j])
+				goto done;
+
+			// the new edge
+			if (stripcount & 1)
+				m2 = check->vertindex[ (k+2)%3 ];
+			else
+				m1 = check->vertindex[ (k+2)%3 ];
+
+			stripverts[stripcount+2] = check->vertindex[ (k+2)%3 ];
+			striptris[stripcount] = j;
+			stripcount++;
+
+			used[j] = 2;
+			goto nexttri;
+		}
+	}
+done:
+
+	// clear the temp used flags
+	for (j=starttri+1 ; j<pheader->numtris ; j++)
+		if (used[j] == 2)
+			used[j] = 0;
+
+	return stripcount;
+}
+
+/*
+===========
+FanLength
+===========
+*/
+int	FanLength (int starttri, int startv)
+{
+	int		m1, m2;
+	int		j;
+	mtriangle_t	*last, *check;
+	int		k;
+
+	used[starttri] = 2;
+
+	last = &triangles[starttri];
+
+	stripverts[0] = last->vertindex[(startv)%3];
+	stripverts[1] = last->vertindex[(startv+1)%3];
+	stripverts[2] = last->vertindex[(startv+2)%3];
+
+	striptris[0] = starttri;
+	stripcount = 1;
+
+	m1 = last->vertindex[(startv+0)%3];
+	m2 = last->vertindex[(startv+2)%3];
+
+
+	// look for a matching triangle
+nexttri:
+	for (j=starttri+1, check=&triangles[starttri+1] ; j<pheader->numtris ; j++, check++)
+	{
+		if (check->facesfront != last->facesfront)
+			continue;
+		for (k=0 ; k<3 ; k++)
+		{
+			if (check->vertindex[k] != m1)
+				continue;
+			if (check->vertindex[ (k+1)%3 ] != m2)
+				continue;
+
+			// this is the next part of the fan
+
+			// if we can't use this triangle, this tristrip is done
+			if (used[j])
+				goto done;
+
+			// the new edge
+			m2 = check->vertindex[ (k+2)%3 ];
+
+			stripverts[stripcount+2] = m2;
+			striptris[stripcount] = j;
+			stripcount++;
+
+			used[j] = 2;
+			goto nexttri;
+		}
+	}
+done:
+
+	// clear the temp used flags
+	for (j=starttri+1 ; j<pheader->numtris ; j++)
+		if (used[j] == 2)
+			used[j] = 0;
+
+	return stripcount;
+}
+
+
+/*
+================
+BuildTris
+
+Generate a list of trifans or strips
+for the model, which holds for all frames
+================
+*/
+void BuildTris (void)
+{
+	int		i, j, k;
+	int		startv;
+	float	s, t;
+	int		len, bestlen, besttype;
+	int		bestverts[1024];
+	int		besttris[1024];
+	int		type;
+
+	//
+	// build tristrips
+	//
+	numorder = 0;
+	numcommands = 0;
+	memset (used, 0, sizeof(used));
+	for (i=0 ; i<pheader->numtris ; i++)
+	{
+		// pick an unused triangle and start the trifan
+		if (used[i])
+			continue;
+
+		bestlen = 0;
+		for (type = 0 ; type < 2 ; type++)
+//	type = 1;
+		{
+			for (startv =0 ; startv < 3 ; startv++)
+			{
+				if (type == 1)
+					len = StripLength (i, startv);
+				else
+					len = FanLength (i, startv);
+				if (len > bestlen)
+				{
+					besttype = type;
+					bestlen = len;
+					for (j=0 ; j<bestlen+2 ; j++)
+						bestverts[j] = stripverts[j];
+					for (j=0 ; j<bestlen ; j++)
+						besttris[j] = striptris[j];
+				}
+			}
+		}
+
+		// mark the tris on the best strip as used
+		for (j=0 ; j<bestlen ; j++)
+			used[besttris[j]] = 1;
+
+		if (besttype == 1)
+			commands[numcommands++] = (bestlen+2);
+		else
+			commands[numcommands++] = -(bestlen+2);
+
+		for (j=0 ; j<bestlen+2 ; j++)
+		{
+			// emit a vertex into the reorder buffer
+			k = bestverts[j];
+			vertexorder[numorder++] = k;
+
+			// emit s/t coords into the commands stream
+			s = stverts[k].s;
+			t = stverts[k].t;
+			if (!triangles[besttris[0]].facesfront && stverts[k].onseam)
+				s += pheader->skinwidth / 2;	// on back side
+			s = (s + 0.5) / pheader->skinwidth;
+			t = (t + 0.5) / pheader->skinheight;
+
+			*(float *)&commands[numcommands++] = s;
+			*(float *)&commands[numcommands++] = t;
+		}
+	}
+
+	commands[numcommands++] = 0;		// end of list marker
+
+	Con_DPrintf ("%3i tri %3i vert %3i cmd\n", pheader->numtris, numorder, numcommands);
+
+	allverts += numorder;
+	alltris += pheader->numtris;
+}
+
+
+/*
+================
+GL_MakeAliasModelDisplayLists
+================
+*/
+void GL_MakeAliasModelDisplayLists (model_t *m, aliashdr_t *hdr)
+{
+	int		i, j;
+	int			*cmds;
+	trivertx_t	*verts;
+	char	cache[MAX_QPATH], fullpath[MAX_OSPATH];
+	FILE	*f;
+
+	aliasmodel = m;
+	paliashdr = hdr;	// (aliashdr_t *)Mod_Extradata (m);
+
+	//
+	// look for a cached version
+	//
+	strcpy (cache, "glquake/");
+	COM_StripExtension (m->name+strlen("progs/"), cache+strlen("glquake/"));
+	strcat (cache, ".ms2");
+
+	COM_FOpenFile (cache, &f);	
+	if (f)
+	{
+		fread (&numcommands, 4, 1, f);
+		fread (&numorder, 4, 1, f);
+		fread (&commands, numcommands * sizeof(commands[0]), 1, f);
+		fread (&vertexorder, numorder * sizeof(vertexorder[0]), 1, f);
+		fclose (f);
+	}
+	else
+	{
+		//
+		// build it from scratch
+		//
+		Con_Printf ("meshing %s...\n",m->name);
+
+		BuildTris ();		// trifans or lists
+
+		//
+		// save out the cached version
+		//
+		sprintf (fullpath, "%s/%s", com_gamedir, cache);
+		f = fopen (fullpath, "wb");
+		if (!f) {
+			char gldir[MAX_OSPATH];
+
+			sprintf (gldir, "%s/glquake", com_gamedir);
+			Sys_mkdir (gldir);
+			f = fopen (fullpath, "wb");
+		}
+
+		if (f)
+		{
+			fwrite (&numcommands, 4, 1, f);
+			fwrite (&numorder, 4, 1, f);
+			fwrite (&commands, numcommands * sizeof(commands[0]), 1, f);
+			fwrite (&vertexorder, numorder * sizeof(vertexorder[0]), 1, f);
+			fclose (f);
+		}
+	}
+
+
+	// save the data out
+
+	paliashdr->poseverts = numorder;
+
+	cmds = Hunk_Alloc (numcommands * 4);
+	paliashdr->commands = (byte *)cmds - (byte *)paliashdr;
+	memcpy (cmds, commands, numcommands * 4);
+
+	verts = Hunk_Alloc (paliashdr->numposes * paliashdr->poseverts 
+		* sizeof(trivertx_t) );
+	paliashdr->posedata = (byte *)verts - (byte *)paliashdr;
+	for (i=0 ; i<paliashdr->numposes ; i++)
+		for (j=0 ; j<numorder ; j++)
+			*verts++ = poseverts[i][vertexorder[j]];
+}
+
--- /dev/null
+++ b/QW/client/gl_model.c
@@ -1,0 +1,1884 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// models.c -- model loading and caching
+
+// models are the only shared resource between a client and server running
+// on the same machine.
+
+#include "quakedef.h"
+
+model_t	*loadmodel;
+char	loadname[32];	// for hunk tags
+
+void Mod_LoadSpriteModel (model_t *mod, void *buffer);
+void Mod_LoadBrushModel (model_t *mod, void *buffer);
+void Mod_LoadAliasModel (model_t *mod, void *buffer);
+model_t *Mod_LoadModel (model_t *mod, qboolean crash);
+
+byte	mod_novis[MAX_MAP_LEAFS/8];
+
+#define	MAX_MOD_KNOWN	512
+model_t	mod_known[MAX_MOD_KNOWN];
+int		mod_numknown;
+
+cvar_t gl_subdivide_size = {"gl_subdivide_size", "128", true};
+
+/*
+===============
+Mod_Init
+===============
+*/
+void Mod_Init (void)
+{
+	Cvar_RegisterVariable (&gl_subdivide_size);
+	memset (mod_novis, 0xff, sizeof(mod_novis));
+}
+
+/*
+===============
+Mod_Init
+
+Caches the data if needed
+===============
+*/
+void *Mod_Extradata (model_t *mod)
+{
+	void	*r;
+	
+	r = Cache_Check (&mod->cache);
+	if (r)
+		return r;
+
+	Mod_LoadModel (mod, true);
+	
+	if (!mod->cache.data)
+		Sys_Error ("Mod_Extradata: caching failed");
+	return mod->cache.data;
+}
+
+/*
+===============
+Mod_PointInLeaf
+===============
+*/
+mleaf_t *Mod_PointInLeaf (vec3_t p, model_t *model)
+{
+	mnode_t		*node;
+	float		d;
+	mplane_t	*plane;
+	
+	if (!model || !model->nodes)
+		Sys_Error ("Mod_PointInLeaf: bad model");
+
+	node = model->nodes;
+	while (1)
+	{
+		if (node->contents < 0)
+			return (mleaf_t *)node;
+		plane = node->plane;
+		d = DotProduct (p,plane->normal) - plane->dist;
+		if (d > 0)
+			node = node->children[0];
+		else
+			node = node->children[1];
+	}
+	
+	return NULL;	// never reached
+}
+
+
+/*
+===================
+Mod_DecompressVis
+===================
+*/
+byte *Mod_DecompressVis (byte *in, model_t *model)
+{
+	static byte	decompressed[MAX_MAP_LEAFS/8];
+	int		c;
+	byte	*out;
+	int		row;
+
+	row = (model->numleafs+7)>>3;	
+	out = decompressed;
+
+#if 0
+	memcpy (out, in, row);
+#else
+	if (!in)
+	{	// no vis info, so make all visible
+		while (row)
+		{
+			*out++ = 0xff;
+			row--;
+		}
+		return decompressed;		
+	}
+
+	do
+	{
+		if (*in)
+		{
+			*out++ = *in++;
+			continue;
+		}
+	
+		c = in[1];
+		in += 2;
+		while (c)
+		{
+			*out++ = 0;
+			c--;
+		}
+	} while (out - decompressed < row);
+#endif
+	
+	return decompressed;
+}
+
+byte *Mod_LeafPVS (mleaf_t *leaf, model_t *model)
+{
+	if (leaf == model->leafs)
+		return mod_novis;
+	return Mod_DecompressVis (leaf->compressed_vis, model);
+}
+
+/*
+===================
+Mod_ClearAll
+===================
+*/
+void Mod_ClearAll (void)
+{
+	int		i;
+	model_t	*mod;
+	
+	for (i=0 , mod=mod_known ; i<mod_numknown ; i++, mod++)
+		if (mod->type != mod_alias)
+			mod->needload = true;
+}
+
+/*
+==================
+Mod_FindName
+
+==================
+*/
+model_t *Mod_FindName (char *name)
+{
+	int		i;
+	model_t	*mod;
+	
+	if (!name[0])
+		Sys_Error ("Mod_ForName: NULL name");
+		
+//
+// search the currently loaded models
+//
+	for (i=0 , mod=mod_known ; i<mod_numknown ; i++, mod++)
+		if (!strcmp (mod->name, name) )
+			break;
+			
+	if (i == mod_numknown)
+	{
+		if (mod_numknown == MAX_MOD_KNOWN)
+			Sys_Error ("mod_numknown == MAX_MOD_KNOWN");
+		strcpy (mod->name, name);
+		mod->needload = true;
+		mod_numknown++;
+	}
+
+	return mod;
+}
+
+/*
+==================
+Mod_TouchModel
+
+==================
+*/
+void Mod_TouchModel (char *name)
+{
+	model_t	*mod;
+	
+	mod = Mod_FindName (name);
+	
+	if (!mod->needload)
+	{
+		if (mod->type == mod_alias)
+			Cache_Check (&mod->cache);
+	}
+}
+
+/*
+==================
+Mod_LoadModel
+
+Loads a model into the cache
+==================
+*/
+model_t *Mod_LoadModel (model_t *mod, qboolean crash)
+{
+	void	*d;
+	unsigned *buf;
+	byte	stackbuf[1024];		// avoid dirtying the cache heap
+
+	if (!mod->needload)
+	{
+		if (mod->type == mod_alias)
+		{
+			d = Cache_Check (&mod->cache);
+			if (d)
+				return mod;
+		}
+		else
+			return mod;		// not cached at all
+	}
+
+//
+// because the world is so huge, load it one piece at a time
+//
+	if (!crash)
+	{
+	
+	}
+	
+//
+// load the file
+//
+	buf = (unsigned *)COM_LoadStackFile (mod->name, stackbuf, sizeof(stackbuf));
+	if (!buf)
+	{
+		if (crash)
+			Sys_Error ("Mod_NumForName: %s not found", mod->name);
+		return NULL;
+	}
+	
+//
+// allocate a new model
+//
+	COM_FileBase (mod->name, loadname);
+	
+	loadmodel = mod;
+
+//
+// fill it in
+//
+
+// call the apropriate loader
+	mod->needload = false;
+	
+	switch (LittleLong(*(unsigned *)buf))
+	{
+	case IDPOLYHEADER:
+		Mod_LoadAliasModel (mod, buf);
+		break;
+		
+	case IDSPRITEHEADER:
+		Mod_LoadSpriteModel (mod, buf);
+		break;
+	
+	default:
+		Mod_LoadBrushModel (mod, buf);
+		break;
+	}
+
+	return mod;
+}
+
+/*
+==================
+Mod_ForName
+
+Loads in a model for the given name
+==================
+*/
+model_t *Mod_ForName (char *name, qboolean crash)
+{
+	model_t	*mod;
+	
+	mod = Mod_FindName (name);
+	
+	return Mod_LoadModel (mod, crash);
+}
+
+
+/*
+===============================================================================
+
+					BRUSHMODEL LOADING
+
+===============================================================================
+*/
+
+byte	*mod_base;
+
+
+/*
+=================
+Mod_LoadTextures
+=================
+*/
+void Mod_LoadTextures (lump_t *l)
+{
+	int		i, j, pixels, num, max, altmax;
+	miptex_t	*mt;
+	texture_t	*tx, *tx2;
+	texture_t	*anims[10];
+	texture_t	*altanims[10];
+	dmiptexlump_t *m;
+
+	if (!l->filelen)
+	{
+		loadmodel->textures = NULL;
+		return;
+	}
+	m = (dmiptexlump_t *)(mod_base + l->fileofs);
+	
+	m->nummiptex = LittleLong (m->nummiptex);
+	
+	loadmodel->numtextures = m->nummiptex;
+	loadmodel->textures = Hunk_AllocName (m->nummiptex * sizeof(*loadmodel->textures) , loadname);
+
+	for (i=0 ; i<m->nummiptex ; i++)
+	{
+		m->dataofs[i] = LittleLong(m->dataofs[i]);
+		if (m->dataofs[i] == -1)
+			continue;
+		mt = (miptex_t *)((byte *)m + m->dataofs[i]);
+		mt->width = LittleLong (mt->width);
+		mt->height = LittleLong (mt->height);
+		for (j=0 ; j<MIPLEVELS ; j++)
+			mt->offsets[j] = LittleLong (mt->offsets[j]);
+		
+		if ( (mt->width & 15) || (mt->height & 15) )
+			Sys_Error ("Texture %s is not 16 aligned", mt->name);
+		pixels = mt->width*mt->height/64*85;
+		tx = Hunk_AllocName (sizeof(texture_t) +pixels, loadname );
+		loadmodel->textures[i] = tx;
+
+		memcpy (tx->name, mt->name, sizeof(tx->name));
+		tx->width = mt->width;
+		tx->height = mt->height;
+		for (j=0 ; j<MIPLEVELS ; j++)
+			tx->offsets[j] = mt->offsets[j] + sizeof(texture_t) - sizeof(miptex_t);
+		// the pixels immediately follow the structures
+		memcpy ( tx+1, mt+1, pixels);
+		
+
+		if (!Q_strncmp(mt->name,"sky",3))	
+			R_InitSky (tx);
+		else
+		{
+			texture_mode = GL_LINEAR_MIPMAP_NEAREST; //_LINEAR;
+			tx->gl_texturenum = GL_LoadTexture (mt->name, tx->width, tx->height, (byte *)(tx+1), true, false);
+			texture_mode = GL_LINEAR;
+		}
+	}
+
+//
+// sequence the animations
+//
+	for (i=0 ; i<m->nummiptex ; i++)
+	{
+		tx = loadmodel->textures[i];
+		if (!tx || tx->name[0] != '+')
+			continue;
+		if (tx->anim_next)
+			continue;	// allready sequenced
+
+	// find the number of frames in the animation
+		memset (anims, 0, sizeof(anims));
+		memset (altanims, 0, sizeof(altanims));
+
+		max = tx->name[1];
+		altmax = 0;
+		if (max >= 'a' && max <= 'z')
+			max -= 'a' - 'A';
+		if (max >= '0' && max <= '9')
+		{
+			max -= '0';
+			altmax = 0;
+			anims[max] = tx;
+			max++;
+		}
+		else if (max >= 'A' && max <= 'J')
+		{
+			altmax = max - 'A';
+			max = 0;
+			altanims[altmax] = tx;
+			altmax++;
+		}
+		else
+			Sys_Error ("Bad animating texture %s", tx->name);
+
+		for (j=i+1 ; j<m->nummiptex ; j++)
+		{
+			tx2 = loadmodel->textures[j];
+			if (!tx2 || tx2->name[0] != '+')
+				continue;
+			if (strcmp (tx2->name+2, tx->name+2))
+				continue;
+
+			num = tx2->name[1];
+			if (num >= 'a' && num <= 'z')
+				num -= 'a' - 'A';
+			if (num >= '0' && num <= '9')
+			{
+				num -= '0';
+				anims[num] = tx2;
+				if (num+1 > max)
+					max = num + 1;
+			}
+			else if (num >= 'A' && num <= 'J')
+			{
+				num = num - 'A';
+				altanims[num] = tx2;
+				if (num+1 > altmax)
+					altmax = num+1;
+			}
+			else
+				Sys_Error ("Bad animating texture %s", tx->name);
+		}
+		
+#define	ANIM_CYCLE	2
+	// link them all together
+		for (j=0 ; j<max ; j++)
+		{
+			tx2 = anims[j];
+			if (!tx2)
+				Sys_Error ("Missing frame %i of %s",j, tx->name);
+			tx2->anim_total = max * ANIM_CYCLE;
+			tx2->anim_min = j * ANIM_CYCLE;
+			tx2->anim_max = (j+1) * ANIM_CYCLE;
+			tx2->anim_next = anims[ (j+1)%max ];
+			if (altmax)
+				tx2->alternate_anims = altanims[0];
+		}
+		for (j=0 ; j<altmax ; j++)
+		{
+			tx2 = altanims[j];
+			if (!tx2)
+				Sys_Error ("Missing frame %i of %s",j, tx->name);
+			tx2->anim_total = altmax * ANIM_CYCLE;
+			tx2->anim_min = j * ANIM_CYCLE;
+			tx2->anim_max = (j+1) * ANIM_CYCLE;
+			tx2->anim_next = altanims[ (j+1)%altmax ];
+			if (max)
+				tx2->alternate_anims = anims[0];
+		}
+	}
+}
+
+/*
+=================
+Mod_LoadLighting
+=================
+*/
+void Mod_LoadLighting (lump_t *l)
+{
+	if (!l->filelen)
+	{
+		loadmodel->lightdata = NULL;
+		return;
+	}
+	loadmodel->lightdata = Hunk_AllocName ( l->filelen, loadname);	
+	memcpy (loadmodel->lightdata, mod_base + l->fileofs, l->filelen);
+}
+
+
+/*
+=================
+Mod_LoadVisibility
+=================
+*/
+void Mod_LoadVisibility (lump_t *l)
+{
+	if (!l->filelen)
+	{
+		loadmodel->visdata = NULL;
+		return;
+	}
+	loadmodel->visdata = Hunk_AllocName ( l->filelen, loadname);	
+	memcpy (loadmodel->visdata, mod_base + l->fileofs, l->filelen);
+}
+
+
+/*
+=================
+Mod_LoadEntities
+=================
+*/
+void Mod_LoadEntities (lump_t *l)
+{
+	if (!l->filelen)
+	{
+		loadmodel->entities = NULL;
+		return;
+	}
+	loadmodel->entities = Hunk_AllocName ( l->filelen, loadname);	
+	memcpy (loadmodel->entities, mod_base + l->fileofs, l->filelen);
+}
+
+
+/*
+=================
+Mod_LoadVertexes
+=================
+*/
+void Mod_LoadVertexes (lump_t *l)
+{
+	dvertex_t	*in;
+	mvertex_t	*out;
+	int			i, count;
+
+	in = (void *)(mod_base + l->fileofs);
+	if (l->filelen % sizeof(*in))
+		Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
+	count = l->filelen / sizeof(*in);
+	out = Hunk_AllocName ( count*sizeof(*out), loadname);	
+
+	loadmodel->vertexes = out;
+	loadmodel->numvertexes = count;
+
+	for ( i=0 ; i<count ; i++, in++, out++)
+	{
+		out->position[0] = LittleFloat (in->point[0]);
+		out->position[1] = LittleFloat (in->point[1]);
+		out->position[2] = LittleFloat (in->point[2]);
+	}
+}
+
+/*
+=================
+Mod_LoadSubmodels
+=================
+*/
+void Mod_LoadSubmodels (lump_t *l)
+{
+	dmodel_t	*in;
+	dmodel_t	*out;
+	int			i, j, count;
+
+	in = (void *)(mod_base + l->fileofs);
+	if (l->filelen % sizeof(*in))
+		Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
+	count = l->filelen / sizeof(*in);
+	out = Hunk_AllocName ( count*sizeof(*out), loadname);	
+
+	loadmodel->submodels = out;
+	loadmodel->numsubmodels = count;
+
+	for ( i=0 ; i<count ; i++, in++, out++)
+	{
+		for (j=0 ; j<3 ; j++)
+		{	// spread the mins / maxs by a pixel
+			out->mins[j] = LittleFloat (in->mins[j]) - 1;
+			out->maxs[j] = LittleFloat (in->maxs[j]) + 1;
+			out->origin[j] = LittleFloat (in->origin[j]);
+		}
+		for (j=0 ; j<MAX_MAP_HULLS ; j++)
+			out->headnode[j] = LittleLong (in->headnode[j]);
+		out->visleafs = LittleLong (in->visleafs);
+		out->firstface = LittleLong (in->firstface);
+		out->numfaces = LittleLong (in->numfaces);
+	}
+}
+
+/*
+=================
+Mod_LoadEdges
+=================
+*/
+void Mod_LoadEdges (lump_t *l)
+{
+	dedge_t *in;
+	medge_t *out;
+	int 	i, count;
+
+	in = (void *)(mod_base + l->fileofs);
+	if (l->filelen % sizeof(*in))
+		Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
+	count = l->filelen / sizeof(*in);
+	out = Hunk_AllocName ( (count + 1) * sizeof(*out), loadname);	
+
+	loadmodel->edges = out;
+	loadmodel->numedges = count;
+
+	for ( i=0 ; i<count ; i++, in++, out++)
+	{
+		out->v[0] = (unsigned short)LittleShort(in->v[0]);
+		out->v[1] = (unsigned short)LittleShort(in->v[1]);
+	}
+}
+
+/*
+=================
+Mod_LoadTexinfo
+=================
+*/
+void Mod_LoadTexinfo (lump_t *l)
+{
+	texinfo_t *in;
+	mtexinfo_t *out;
+	int 	i, j, count;
+	int		miptex;
+	float	len1, len2;
+
+	in = (void *)(mod_base + l->fileofs);
+	if (l->filelen % sizeof(*in))
+		Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
+	count = l->filelen / sizeof(*in);
+	out = Hunk_AllocName ( count*sizeof(*out), loadname);	
+
+	loadmodel->texinfo = out;
+	loadmodel->numtexinfo = count;
+
+	for ( i=0 ; i<count ; i++, in++, out++)
+	{
+		for (j=0 ; j<8 ; j++)
+			out->vecs[0][j] = LittleFloat (in->vecs[0][j]);
+		len1 = Length (out->vecs[0]);
+		len2 = Length (out->vecs[1]);
+		len1 = (len1 + len2)/2;
+		if (len1 < 0.32)
+			out->mipadjust = 4;
+		else if (len1 < 0.49)
+			out->mipadjust = 3;
+		else if (len1 < 0.99)
+			out->mipadjust = 2;
+		else
+			out->mipadjust = 1;
+#if 0
+		if (len1 + len2 < 0.001)
+			out->mipadjust = 1;		// don't crash
+		else
+			out->mipadjust = 1 / floor( (len1+len2)/2 + 0.1 );
+#endif
+
+		miptex = LittleLong (in->miptex);
+		out->flags = LittleLong (in->flags);
+	
+		if (!loadmodel->textures)
+		{
+			out->texture = r_notexture_mip;	// checkerboard texture
+			out->flags = 0;
+		}
+		else
+		{
+			if (miptex >= loadmodel->numtextures)
+				Sys_Error ("miptex >= loadmodel->numtextures");
+			out->texture = loadmodel->textures[miptex];
+			if (!out->texture)
+			{
+				out->texture = r_notexture_mip; // texture not found
+				out->flags = 0;
+			}
+		}
+	}
+}
+
+/*
+================
+CalcSurfaceExtents
+
+Fills in s->texturemins[] and s->extents[]
+================
+*/
+void CalcSurfaceExtents (msurface_t *s)
+{
+	float	mins[2], maxs[2], val;
+	int		i,j, e;
+	mvertex_t	*v;
+	mtexinfo_t	*tex;
+	int		bmins[2], bmaxs[2];
+
+	mins[0] = mins[1] = 999999;
+	maxs[0] = maxs[1] = -99999;
+
+	tex = s->texinfo;
+	
+	for (i=0 ; i<s->numedges ; i++)
+	{
+		e = loadmodel->surfedges[s->firstedge+i];
+		if (e >= 0)
+			v = &loadmodel->vertexes[loadmodel->edges[e].v[0]];
+		else
+			v = &loadmodel->vertexes[loadmodel->edges[-e].v[1]];
+		
+		for (j=0 ; j<2 ; j++)
+		{
+			val = v->position[0] * tex->vecs[j][0] + 
+				v->position[1] * tex->vecs[j][1] +
+				v->position[2] * tex->vecs[j][2] +
+				tex->vecs[j][3];
+			if (val < mins[j])
+				mins[j] = val;
+			if (val > maxs[j])
+				maxs[j] = val;
+		}
+	}
+
+	for (i=0 ; i<2 ; i++)
+	{	
+		bmins[i] = floor(mins[i]/16);
+		bmaxs[i] = ceil(maxs[i]/16);
+
+		s->texturemins[i] = bmins[i] * 16;
+		s->extents[i] = (bmaxs[i] - bmins[i]) * 16;
+		if ( !(tex->flags & TEX_SPECIAL) && s->extents[i] > 512 /* 256 */ )
+			Sys_Error ("Bad surface extents");
+	}
+}
+
+
+/*
+=================
+Mod_LoadFaces
+=================
+*/
+void Mod_LoadFaces (lump_t *l)
+{
+	dface_t		*in;
+	msurface_t 	*out;
+	int			i, count, surfnum;
+	int			planenum, side;
+
+	in = (void *)(mod_base + l->fileofs);
+	if (l->filelen % sizeof(*in))
+		Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
+	count = l->filelen / sizeof(*in);
+	out = Hunk_AllocName ( count*sizeof(*out), loadname);	
+
+	loadmodel->surfaces = out;
+	loadmodel->numsurfaces = count;
+
+	for ( surfnum=0 ; surfnum<count ; surfnum++, in++, out++)
+	{
+		out->firstedge = LittleLong(in->firstedge);
+		out->numedges = LittleShort(in->numedges);		
+		out->flags = 0;
+
+		planenum = LittleShort(in->planenum);
+		side = LittleShort(in->side);
+		if (side)
+			out->flags |= SURF_PLANEBACK;			
+
+		out->plane = loadmodel->planes + planenum;
+
+		out->texinfo = loadmodel->texinfo + LittleShort (in->texinfo);
+
+		CalcSurfaceExtents (out);
+				
+	// lighting info
+
+		for (i=0 ; i<MAXLIGHTMAPS ; i++)
+			out->styles[i] = in->styles[i];
+		i = LittleLong(in->lightofs);
+		if (i == -1)
+			out->samples = NULL;
+		else
+			out->samples = loadmodel->lightdata + i;
+		
+	// set the drawing flags flag
+		
+		if (!Q_strncmp(out->texinfo->texture->name,"sky",3))	// sky
+		{
+			out->flags |= (SURF_DRAWSKY | SURF_DRAWTILED);
+#ifndef QUAKE2
+			GL_SubdivideSurface (out);	// cut up polygon for warps
+#endif
+			continue;
+		}
+		
+		if (!Q_strncmp(out->texinfo->texture->name,"*",1))		// turbulent
+		{
+			out->flags |= (SURF_DRAWTURB | SURF_DRAWTILED);
+			for (i=0 ; i<2 ; i++)
+			{
+				out->extents[i] = 16384;
+				out->texturemins[i] = -8192;
+			}
+			GL_SubdivideSurface (out);	// cut up polygon for warps
+			continue;
+		}
+
+	}
+}
+
+
+/*
+=================
+Mod_SetParent
+=================
+*/
+void Mod_SetParent (mnode_t *node, mnode_t *parent)
+{
+	node->parent = parent;
+	if (node->contents < 0)
+		return;
+	Mod_SetParent (node->children[0], node);
+	Mod_SetParent (node->children[1], node);
+}
+
+/*
+=================
+Mod_LoadNodes
+=================
+*/
+void Mod_LoadNodes (lump_t *l)
+{
+	int			i, j, count, p;
+	dnode_t		*in;
+	mnode_t 	*out;
+
+	in = (void *)(mod_base + l->fileofs);
+	if (l->filelen % sizeof(*in))
+		Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
+	count = l->filelen / sizeof(*in);
+	out = Hunk_AllocName ( count*sizeof(*out), loadname);	
+
+	loadmodel->nodes = out;
+	loadmodel->numnodes = count;
+
+	for ( i=0 ; i<count ; i++, in++, out++)
+	{
+		for (j=0 ; j<3 ; j++)
+		{
+			out->minmaxs[j] = LittleShort (in->mins[j]);
+			out->minmaxs[3+j] = LittleShort (in->maxs[j]);
+		}
+	
+		p = LittleLong(in->planenum);
+		out->plane = loadmodel->planes + p;
+
+		out->firstsurface = LittleShort (in->firstface);
+		out->numsurfaces = LittleShort (in->numfaces);
+		
+		for (j=0 ; j<2 ; j++)
+		{
+			p = LittleShort (in->children[j]);
+			if (p >= 0)
+				out->children[j] = loadmodel->nodes + p;
+			else
+				out->children[j] = (mnode_t *)(loadmodel->leafs + (-1 - p));
+		}
+	}
+	
+	Mod_SetParent (loadmodel->nodes, NULL);	// sets nodes and leafs
+}
+
+/*
+=================
+Mod_LoadLeafs
+=================
+*/
+void Mod_LoadLeafs (lump_t *l)
+{
+	dleaf_t 	*in;
+	mleaf_t 	*out;
+	int			i, j, count, p;
+	char s[80];
+	qboolean isnotmap = true;
+
+	in = (void *)(mod_base + l->fileofs);
+	if (l->filelen % sizeof(*in))
+		Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
+	count = l->filelen / sizeof(*in);
+	out = Hunk_AllocName ( count*sizeof(*out), loadname);	
+
+	loadmodel->leafs = out;
+	loadmodel->numleafs = count;
+	sprintf(s, "maps/%s.bsp", Info_ValueForKey(cl.serverinfo,"map"));
+	if (!strcmp(s, loadmodel->name))
+		isnotmap = false;
+	for ( i=0 ; i<count ; i++, in++, out++)
+	{
+		for (j=0 ; j<3 ; j++)
+		{
+			out->minmaxs[j] = LittleShort (in->mins[j]);
+			out->minmaxs[3+j] = LittleShort (in->maxs[j]);
+		}
+
+		p = LittleLong(in->contents);
+		out->contents = p;
+
+		out->firstmarksurface = loadmodel->marksurfaces +
+			LittleShort(in->firstmarksurface);
+		out->nummarksurfaces = LittleShort(in->nummarksurfaces);
+		
+		p = LittleLong(in->visofs);
+		if (p == -1)
+			out->compressed_vis = NULL;
+		else
+			out->compressed_vis = loadmodel->visdata + p;
+		out->efrags = NULL;
+		
+		for (j=0 ; j<4 ; j++)
+			out->ambient_sound_level[j] = in->ambient_level[j];
+
+		// gl underwater warp
+		if (out->contents != CONTENTS_EMPTY)
+		{
+			for (j=0 ; j<out->nummarksurfaces ; j++)
+				out->firstmarksurface[j]->flags |= SURF_UNDERWATER;
+		}
+		if (isnotmap)
+		{
+			for (j=0 ; j<out->nummarksurfaces ; j++)
+				out->firstmarksurface[j]->flags |= SURF_DONTWARP;
+		}
+	}	
+}
+
+/*
+=================
+Mod_LoadClipnodes
+=================
+*/
+void Mod_LoadClipnodes (lump_t *l)
+{
+	dclipnode_t *in, *out;
+	int			i, count;
+	hull_t		*hull;
+
+	in = (void *)(mod_base + l->fileofs);
+	if (l->filelen % sizeof(*in))
+		Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
+	count = l->filelen / sizeof(*in);
+	out = Hunk_AllocName ( count*sizeof(*out), loadname);	
+
+	loadmodel->clipnodes = out;
+	loadmodel->numclipnodes = count;
+
+	hull = &loadmodel->hulls[1];
+	hull->clipnodes = out;
+	hull->firstclipnode = 0;
+	hull->lastclipnode = count-1;
+	hull->planes = loadmodel->planes;
+	hull->clip_mins[0] = -16;
+	hull->clip_mins[1] = -16;
+	hull->clip_mins[2] = -24;
+	hull->clip_maxs[0] = 16;
+	hull->clip_maxs[1] = 16;
+	hull->clip_maxs[2] = 32;
+
+	hull = &loadmodel->hulls[2];
+	hull->clipnodes = out;
+	hull->firstclipnode = 0;
+	hull->lastclipnode = count-1;
+	hull->planes = loadmodel->planes;
+	hull->clip_mins[0] = -32;
+	hull->clip_mins[1] = -32;
+	hull->clip_mins[2] = -24;
+	hull->clip_maxs[0] = 32;
+	hull->clip_maxs[1] = 32;
+	hull->clip_maxs[2] = 64;
+
+	for (i=0 ; i<count ; i++, out++, in++)
+	{
+		out->planenum = LittleLong(in->planenum);
+		out->children[0] = LittleShort(in->children[0]);
+		out->children[1] = LittleShort(in->children[1]);
+	}
+}
+
+/*
+=================
+Mod_MakeHull0
+
+Deplicate the drawing hull structure as a clipping hull
+=================
+*/
+void Mod_MakeHull0 (void)
+{
+	mnode_t		*in, *child;
+	dclipnode_t *out;
+	int			i, j, count;
+	hull_t		*hull;
+	
+	hull = &loadmodel->hulls[0];	
+	
+	in = loadmodel->nodes;
+	count = loadmodel->numnodes;
+	out = Hunk_AllocName ( count*sizeof(*out), loadname);	
+
+	hull->clipnodes = out;
+	hull->firstclipnode = 0;
+	hull->lastclipnode = count-1;
+	hull->planes = loadmodel->planes;
+
+	for (i=0 ; i<count ; i++, out++, in++)
+	{
+		out->planenum = in->plane - loadmodel->planes;
+		for (j=0 ; j<2 ; j++)
+		{
+			child = in->children[j];
+			if (child->contents < 0)
+				out->children[j] = child->contents;
+			else
+				out->children[j] = child - loadmodel->nodes;
+		}
+	}
+}
+
+/*
+=================
+Mod_LoadMarksurfaces
+=================
+*/
+void Mod_LoadMarksurfaces (lump_t *l)
+{	
+	int		i, j, count;
+	short		*in;
+	msurface_t **out;
+	
+	in = (void *)(mod_base + l->fileofs);
+	if (l->filelen % sizeof(*in))
+		Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
+	count = l->filelen / sizeof(*in);
+	out = Hunk_AllocName ( count*sizeof(*out), loadname);	
+
+	loadmodel->marksurfaces = out;
+	loadmodel->nummarksurfaces = count;
+
+	for ( i=0 ; i<count ; i++)
+	{
+		j = LittleShort(in[i]);
+		if (j >= loadmodel->numsurfaces)
+			Sys_Error ("Mod_ParseMarksurfaces: bad surface number");
+		out[i] = loadmodel->surfaces + j;
+	}
+}
+
+/*
+=================
+Mod_LoadSurfedges
+=================
+*/
+void Mod_LoadSurfedges (lump_t *l)
+{	
+	int		i, count;
+	int		*in, *out;
+	
+	in = (void *)(mod_base + l->fileofs);
+	if (l->filelen % sizeof(*in))
+		Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
+	count = l->filelen / sizeof(*in);
+	out = Hunk_AllocName ( count*sizeof(*out), loadname);	
+
+	loadmodel->surfedges = out;
+	loadmodel->numsurfedges = count;
+
+	for ( i=0 ; i<count ; i++)
+		out[i] = LittleLong (in[i]);
+}
+
+
+/*
+=================
+Mod_LoadPlanes
+=================
+*/
+void Mod_LoadPlanes (lump_t *l)
+{
+	int			i, j;
+	mplane_t	*out;
+	dplane_t 	*in;
+	int			count;
+	int			bits;
+	
+	in = (void *)(mod_base + l->fileofs);
+	if (l->filelen % sizeof(*in))
+		Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
+	count = l->filelen / sizeof(*in);
+	out = Hunk_AllocName ( count*2*sizeof(*out), loadname);	
+	
+	loadmodel->planes = out;
+	loadmodel->numplanes = count;
+
+	for ( i=0 ; i<count ; i++, in++, out++)
+	{
+		bits = 0;
+		for (j=0 ; j<3 ; j++)
+		{
+			out->normal[j] = LittleFloat (in->normal[j]);
+			if (out->normal[j] < 0)
+				bits |= 1<<j;
+		}
+
+		out->dist = LittleFloat (in->dist);
+		out->type = LittleLong (in->type);
+		out->signbits = bits;
+	}
+}
+
+/*
+=================
+RadiusFromBounds
+=================
+*/
+float RadiusFromBounds (vec3_t mins, vec3_t maxs)
+{
+	int		i;
+	vec3_t	corner;
+
+	for (i=0 ; i<3 ; i++)
+	{
+		corner[i] = fabs(mins[i]) > fabs(maxs[i]) ? fabs(mins[i]) : fabs(maxs[i]);
+	}
+
+	return Length (corner);
+}
+
+/*
+=================
+Mod_LoadBrushModel
+=================
+*/
+void Mod_LoadBrushModel (model_t *mod, void *buffer)
+{
+	int			i, j;
+	dheader_t	*header;
+	dmodel_t 	*bm;
+	
+	loadmodel->type = mod_brush;
+	
+	header = (dheader_t *)buffer;
+
+	i = LittleLong (header->version);
+	if (i != BSPVERSION)
+		Sys_Error ("Mod_LoadBrushModel: %s has wrong version number (%i should be %i)", mod->name, i, BSPVERSION);
+
+// swap all the lumps
+	mod_base = (byte *)header;
+
+	for (i=0 ; i<sizeof(dheader_t)/4 ; i++)
+		((int *)header)[i] = LittleLong ( ((int *)header)[i]);
+
+// checksum all of the map, except for entities
+	mod->checksum = 0;
+	mod->checksum2 = 0;
+
+	for (i = 0; i < HEADER_LUMPS; i++) {
+		if (i == LUMP_ENTITIES)
+			continue;
+		mod->checksum ^= Com_BlockChecksum(mod_base + header->lumps[i].fileofs, 
+			header->lumps[i].filelen);
+
+		if (i == LUMP_VISIBILITY || i == LUMP_LEAFS || i == LUMP_NODES)
+			continue;
+		mod->checksum2 ^= Com_BlockChecksum(mod_base + header->lumps[i].fileofs, 
+			header->lumps[i].filelen);
+	}
+	
+
+// load into heap
+	
+	Mod_LoadVertexes (&header->lumps[LUMP_VERTEXES]);
+	Mod_LoadEdges (&header->lumps[LUMP_EDGES]);
+	Mod_LoadSurfedges (&header->lumps[LUMP_SURFEDGES]);
+	Mod_LoadTextures (&header->lumps[LUMP_TEXTURES]);
+	Mod_LoadLighting (&header->lumps[LUMP_LIGHTING]);
+	Mod_LoadPlanes (&header->lumps[LUMP_PLANES]);
+	Mod_LoadTexinfo (&header->lumps[LUMP_TEXINFO]);
+	Mod_LoadFaces (&header->lumps[LUMP_FACES]);
+	Mod_LoadMarksurfaces (&header->lumps[LUMP_MARKSURFACES]);
+	Mod_LoadVisibility (&header->lumps[LUMP_VISIBILITY]);
+	Mod_LoadLeafs (&header->lumps[LUMP_LEAFS]);
+	Mod_LoadNodes (&header->lumps[LUMP_NODES]);
+	Mod_LoadClipnodes (&header->lumps[LUMP_CLIPNODES]);
+	Mod_LoadEntities (&header->lumps[LUMP_ENTITIES]);
+	Mod_LoadSubmodels (&header->lumps[LUMP_MODELS]);
+
+	Mod_MakeHull0 ();
+	
+	mod->numframes = 2;		// regular and alternate animation
+	
+//
+// set up the submodels (FIXME: this is confusing)
+//
+	for (i=0 ; i<mod->numsubmodels ; i++)
+	{
+		bm = &mod->submodels[i];
+
+		mod->hulls[0].firstclipnode = bm->headnode[0];
+		for (j=1 ; j<MAX_MAP_HULLS ; j++)
+		{
+			mod->hulls[j].firstclipnode = bm->headnode[j];
+			mod->hulls[j].lastclipnode = mod->numclipnodes-1;
+		}
+		
+		mod->firstmodelsurface = bm->firstface;
+		mod->nummodelsurfaces = bm->numfaces;
+		
+		VectorCopy (bm->maxs, mod->maxs);
+		VectorCopy (bm->mins, mod->mins);
+
+		mod->radius = RadiusFromBounds (mod->mins, mod->maxs);
+
+		mod->numleafs = bm->visleafs;
+
+		if (i < mod->numsubmodels-1)
+		{	// duplicate the basic information
+			char	name[10];
+
+			sprintf (name, "*%i", i+1);
+			loadmodel = Mod_FindName (name);
+			*loadmodel = *mod;
+			strcpy (loadmodel->name, name);
+			mod = loadmodel;
+		}
+	}
+}
+
+/*
+==============================================================================
+
+ALIAS MODELS
+
+==============================================================================
+*/
+
+aliashdr_t	*pheader;
+
+stvert_t	stverts[MAXALIASVERTS];
+mtriangle_t	triangles[MAXALIASTRIS];
+
+// a pose is a single set of vertexes.  a frame may be
+// an animating sequence of poses
+trivertx_t	*poseverts[MAXALIASFRAMES];
+int			posenum;
+
+byte		player_8bit_texels[320*200];
+
+/*
+=================
+Mod_LoadAliasFrame
+=================
+*/
+void * Mod_LoadAliasFrame (void * pin, maliasframedesc_t *frame)
+{
+	trivertx_t		*pinframe;
+	int				i;
+	daliasframe_t	*pdaliasframe;
+	
+	pdaliasframe = (daliasframe_t *)pin;
+
+	strcpy (frame->name, pdaliasframe->name);
+	frame->firstpose = posenum;
+	frame->numposes = 1;
+
+	for (i=0 ; i<3 ; i++)
+	{
+	// these are byte values, so we don't have to worry about
+	// endianness
+		frame->bboxmin.v[i] = pdaliasframe->bboxmin.v[i];
+		frame->bboxmin.v[i] = pdaliasframe->bboxmax.v[i];
+	}
+
+	pinframe = (trivertx_t *)(pdaliasframe + 1);
+
+	poseverts[posenum] = pinframe;
+	posenum++;
+
+	pinframe += pheader->numverts;
+
+	return (void *)pinframe;
+}
+
+
+/*
+=================
+Mod_LoadAliasGroup
+=================
+*/
+void *Mod_LoadAliasGroup (void * pin,  maliasframedesc_t *frame)
+{
+	daliasgroup_t		*pingroup;
+	int					i, numframes;
+	daliasinterval_t	*pin_intervals;
+	void				*ptemp;
+	
+	pingroup = (daliasgroup_t *)pin;
+
+	numframes = LittleLong (pingroup->numframes);
+
+	frame->firstpose = posenum;
+	frame->numposes = numframes;
+
+	for (i=0 ; i<3 ; i++)
+	{
+	// these are byte values, so we don't have to worry about endianness
+		frame->bboxmin.v[i] = pingroup->bboxmin.v[i];
+		frame->bboxmin.v[i] = pingroup->bboxmax.v[i];
+	}
+
+	pin_intervals = (daliasinterval_t *)(pingroup + 1);
+
+	frame->interval = LittleFloat (pin_intervals->interval);
+
+	pin_intervals += numframes;
+
+	ptemp = (void *)pin_intervals;
+
+	for (i=0 ; i<numframes ; i++)
+	{
+		poseverts[posenum] = (trivertx_t *)((daliasframe_t *)ptemp + 1);
+		posenum++;
+
+		ptemp = (trivertx_t *)((daliasframe_t *)ptemp + 1) + pheader->numverts;
+	}
+
+	return ptemp;
+}
+
+//=========================================================
+
+/*
+=================
+Mod_FloodFillSkin
+
+Fill background pixels so mipmapping doesn't have haloes - Ed
+=================
+*/
+
+typedef struct
+{
+	short		x, y;
+} floodfill_t;
+
+extern unsigned d_8to24table[];
+
+// must be a power of 2
+#define FLOODFILL_FIFO_SIZE 0x1000
+#define FLOODFILL_FIFO_MASK (FLOODFILL_FIFO_SIZE - 1)
+
+#define FLOODFILL_STEP( off, dx, dy ) \
+{ \
+	if (pos[off] == fillcolor) \
+	{ \
+		pos[off] = 255; \
+		fifo[inpt].x = x + (dx), fifo[inpt].y = y + (dy); \
+		inpt = (inpt + 1) & FLOODFILL_FIFO_MASK; \
+	} \
+	else if (pos[off] != 255) fdc = pos[off]; \
+}
+
+void Mod_FloodFillSkin( byte *skin, int skinwidth, int skinheight )
+{
+	byte				fillcolor = *skin; // assume this is the pixel to fill
+	floodfill_t			fifo[FLOODFILL_FIFO_SIZE];
+	int					inpt = 0, outpt = 0;
+	int					filledcolor = -1;
+	int					i;
+
+	if (filledcolor == -1)
+	{
+		filledcolor = 0;
+		// attempt to find opaque black
+		for (i = 0; i < 256; ++i)
+			if (d_8to24table[i] == (255 << 0)) // alpha 1.0
+			{
+				filledcolor = i;
+				break;
+			}
+	}
+
+	// can't fill to filled color or to transparent color (used as visited marker)
+	if ((fillcolor == filledcolor) || (fillcolor == 255))
+	{
+		//printf( "not filling skin from %d to %d\n", fillcolor, filledcolor );
+		return;
+	}
+
+	fifo[inpt].x = 0, fifo[inpt].y = 0;
+	inpt = (inpt + 1) & FLOODFILL_FIFO_MASK;
+
+	while (outpt != inpt)
+	{
+		int			x = fifo[outpt].x, y = fifo[outpt].y;
+		int			fdc = filledcolor;
+		byte		*pos = &skin[x + skinwidth * y];
+
+		outpt = (outpt + 1) & FLOODFILL_FIFO_MASK;
+
+		if (x > 0)				FLOODFILL_STEP( -1, -1, 0 );
+		if (x < skinwidth - 1)	FLOODFILL_STEP( 1, 1, 0 );
+		if (y > 0)				FLOODFILL_STEP( -skinwidth, 0, -1 );
+		if (y < skinheight - 1)	FLOODFILL_STEP( skinwidth, 0, 1 );
+		skin[x + skinwidth * y] = fdc;
+	}
+}
+
+/*
+===============
+Mod_LoadAllSkins
+===============
+*/
+void *Mod_LoadAllSkins (int numskins, daliasskintype_t *pskintype)
+{
+	int		i, j, k;
+	char	name[32];
+	int		s;
+	byte	*skin;
+	daliasskingroup_t		*pinskingroup;
+	int		groupskins;
+	daliasskininterval_t	*pinskinintervals;
+	
+	skin = (byte *)(pskintype + 1);
+
+	if (numskins < 1 || numskins > MAX_SKINS)
+		Sys_Error ("Mod_LoadAliasModel: Invalid # of skins: %d\n", numskins);
+
+	s = pheader->skinwidth * pheader->skinheight;
+
+	for (i=0 ; i<numskins ; i++)
+	{
+		if (pskintype->type == ALIAS_SKIN_SINGLE) {
+			Mod_FloodFillSkin( skin, pheader->skinwidth, pheader->skinheight );
+
+			// save 8 bit texels for the player model to remap
+			// save 8 bit texels for the player model to remap
+			if (!strcmp(loadmodel->name,"progs/player.mdl"))
+			{
+				if (s > sizeof(player_8bit_texels))
+					Sys_Error ("Player skin too large");
+				memcpy (player_8bit_texels, (byte *)(pskintype + 1), s);
+			}
+			sprintf (name, "%s_%i", loadmodel->name, i);
+			pheader->gl_texturenum[i][0] =
+			pheader->gl_texturenum[i][1] =
+			pheader->gl_texturenum[i][2] =
+			pheader->gl_texturenum[i][3] =
+				GL_LoadTexture (name, pheader->skinwidth, 
+				pheader->skinheight, (byte *)(pskintype + 1), true, false);
+			pskintype = (daliasskintype_t *)((byte *)(pskintype+1) + s);
+		} else {
+			// animating skin group.  yuck.
+			pskintype++;
+			pinskingroup = (daliasskingroup_t *)pskintype;
+			groupskins = LittleLong (pinskingroup->numskins);
+			pinskinintervals = (daliasskininterval_t *)(pinskingroup + 1);
+
+			pskintype = (void *)(pinskinintervals + groupskins);
+
+			for (j=0 ; j<groupskins ; j++)
+			{
+					Mod_FloodFillSkin( skin, pheader->skinwidth, pheader->skinheight );
+					sprintf (name, "%s_%i_%i", loadmodel->name, i,j);
+					pheader->gl_texturenum[i][j&3] = 
+						GL_LoadTexture (name, pheader->skinwidth, 
+						pheader->skinheight, (byte *)(pskintype), true, false);
+					pskintype = (daliasskintype_t *)((byte *)(pskintype) + s);
+			}
+			k = j;
+			for (/* */; j < 4; j++)
+				pheader->gl_texturenum[i][j&3] = 
+				pheader->gl_texturenum[i][j - k]; 
+		}
+	}
+
+	return (void *)pskintype;
+}
+
+
+//=========================================================================
+
+/*
+=================
+Mod_LoadAliasModel
+=================
+*/
+void Mod_LoadAliasModel (model_t *mod, void *buffer)
+{
+	int					i, j;
+	mdl_t				*pinmodel;
+	stvert_t			*pinstverts;
+	dtriangle_t			*pintriangles;
+	int					version, numframes;
+	int					size;
+	daliasframetype_t	*pframetype;
+	daliasskintype_t	*pskintype;
+	int					start, end, total;
+
+	if (!strcmp(loadmodel->name, "progs/player.mdl") ||
+		!strcmp(loadmodel->name, "progs/eyes.mdl")) {
+		unsigned short crc;
+		byte *p;
+		int len;
+		char st[40];
+
+		CRC_Init(&crc);
+		for (len = com_filesize, p = buffer; len; len--, p++)
+			CRC_ProcessByte(&crc, *p);
+	
+		sprintf(st, "%d", (int) crc);
+		Info_SetValueForKey (cls.userinfo, 
+			!strcmp(loadmodel->name, "progs/player.mdl") ? pmodel_name : emodel_name,
+			st, MAX_INFO_STRING);
+
+		if (cls.state >= ca_connected) {
+			MSG_WriteByte (&cls.netchan.message, clc_stringcmd);
+			sprintf(st, "setinfo %s %d", 
+				!strcmp(loadmodel->name, "progs/player.mdl") ? pmodel_name : emodel_name,
+				(int)crc);
+			SZ_Print (&cls.netchan.message, st);
+		}
+	}
+	
+	start = Hunk_LowMark ();
+
+	pinmodel = (mdl_t *)buffer;
+
+	version = LittleLong (pinmodel->version);
+	if (version != ALIAS_VERSION)
+		Sys_Error ("%s has wrong version number (%i should be %i)",
+				 mod->name, version, ALIAS_VERSION);
+
+//
+// allocate space for a working header, plus all the data except the frames,
+// skin and group info
+//
+	size = 	sizeof (aliashdr_t) 
+			+ (LittleLong (pinmodel->numframes) - 1) *
+			sizeof (pheader->frames[0]);
+	pheader = Hunk_AllocName (size, loadname);
+	
+	mod->flags = LittleLong (pinmodel->flags);
+
+//
+// endian-adjust and copy the data, starting with the alias model header
+//
+	pheader->boundingradius = LittleFloat (pinmodel->boundingradius);
+	pheader->numskins = LittleLong (pinmodel->numskins);
+	pheader->skinwidth = LittleLong (pinmodel->skinwidth);
+	pheader->skinheight = LittleLong (pinmodel->skinheight);
+
+	if (pheader->skinheight > MAX_LBM_HEIGHT)
+		Sys_Error ("model %s has a skin taller than %d", mod->name,
+				   MAX_LBM_HEIGHT);
+
+	pheader->numverts = LittleLong (pinmodel->numverts);
+
+	if (pheader->numverts <= 0)
+		Sys_Error ("model %s has no vertices", mod->name);
+
+	if (pheader->numverts > MAXALIASVERTS)
+		Sys_Error ("model %s has too many vertices", mod->name);
+
+	pheader->numtris = LittleLong (pinmodel->numtris);
+
+	if (pheader->numtris <= 0)
+		Sys_Error ("model %s has no triangles", mod->name);
+
+	pheader->numframes = LittleLong (pinmodel->numframes);
+	numframes = pheader->numframes;
+	if (numframes < 1)
+		Sys_Error ("Mod_LoadAliasModel: Invalid # of frames: %d\n", numframes);
+
+	pheader->size = LittleFloat (pinmodel->size) * ALIAS_BASE_SIZE_RATIO;
+	mod->synctype = LittleLong (pinmodel->synctype);
+	mod->numframes = pheader->numframes;
+
+	for (i=0 ; i<3 ; i++)
+	{
+		pheader->scale[i] = LittleFloat (pinmodel->scale[i]);
+		pheader->scale_origin[i] = LittleFloat (pinmodel->scale_origin[i]);
+		pheader->eyeposition[i] = LittleFloat (pinmodel->eyeposition[i]);
+	}
+
+
+//
+// load the skins
+//
+	pskintype = (daliasskintype_t *)&pinmodel[1];
+	pskintype = Mod_LoadAllSkins (pheader->numskins, pskintype);
+
+//
+// load base s and t vertices
+//
+	pinstverts = (stvert_t *)pskintype;
+
+	for (i=0 ; i<pheader->numverts ; i++)
+	{
+		stverts[i].onseam = LittleLong (pinstverts[i].onseam);
+		stverts[i].s = LittleLong (pinstverts[i].s);
+		stverts[i].t = LittleLong (pinstverts[i].t);
+	}
+
+//
+// load triangle lists
+//
+	pintriangles = (dtriangle_t *)&pinstverts[pheader->numverts];
+
+	for (i=0 ; i<pheader->numtris ; i++)
+	{
+		triangles[i].facesfront = LittleLong (pintriangles[i].facesfront);
+
+		for (j=0 ; j<3 ; j++)
+		{
+			triangles[i].vertindex[j] =
+					LittleLong (pintriangles[i].vertindex[j]);
+		}
+	}
+
+//
+// load the frames
+//
+	posenum = 0;
+	pframetype = (daliasframetype_t *)&pintriangles[pheader->numtris];
+
+	for (i=0 ; i<numframes ; i++)
+	{
+		aliasframetype_t	frametype;
+
+		frametype = LittleLong (pframetype->type);
+
+		if (frametype == ALIAS_SINGLE)
+		{
+			pframetype = (daliasframetype_t *)
+					Mod_LoadAliasFrame (pframetype + 1, &pheader->frames[i]);
+		}
+		else
+		{
+			pframetype = (daliasframetype_t *)
+					Mod_LoadAliasGroup (pframetype + 1, &pheader->frames[i]);
+		}
+	}
+
+	pheader->numposes = posenum;
+
+	mod->type = mod_alias;
+
+// FIXME: do this right
+	mod->mins[0] = mod->mins[1] = mod->mins[2] = -16;
+	mod->maxs[0] = mod->maxs[1] = mod->maxs[2] = 16;
+
+	//
+	// build the draw lists
+	//
+	GL_MakeAliasModelDisplayLists (mod, pheader);
+
+//
+// move the complete, relocatable alias model to the cache
+//	
+	end = Hunk_LowMark ();
+	total = end - start;
+	
+	Cache_Alloc (&mod->cache, total, loadname);
+	if (!mod->cache.data)
+		return;
+	memcpy (mod->cache.data, pheader, total);
+
+	Hunk_FreeToLowMark (start);
+}
+
+//=============================================================================
+
+/*
+=================
+Mod_LoadSpriteFrame
+=================
+*/
+void * Mod_LoadSpriteFrame (void * pin, mspriteframe_t **ppframe, int framenum)
+{
+	dspriteframe_t		*pinframe;
+	mspriteframe_t		*pspriteframe;
+	int					width, height, size, origin[2];
+	char				name[64];
+
+	pinframe = (dspriteframe_t *)pin;
+
+	width = LittleLong (pinframe->width);
+	height = LittleLong (pinframe->height);
+	size = width * height;
+
+	pspriteframe = Hunk_AllocName (sizeof (mspriteframe_t),loadname);
+
+	Q_memset (pspriteframe, 0, sizeof (mspriteframe_t));
+
+	*ppframe = pspriteframe;
+
+	pspriteframe->width = width;
+	pspriteframe->height = height;
+	origin[0] = LittleLong (pinframe->origin[0]);
+	origin[1] = LittleLong (pinframe->origin[1]);
+
+	pspriteframe->up = origin[1];
+	pspriteframe->down = origin[1] - height;
+	pspriteframe->left = origin[0];
+	pspriteframe->right = width + origin[0];
+
+	sprintf (name, "%s_%i", loadmodel->name, framenum);
+	pspriteframe->gl_texturenum = GL_LoadTexture (name, width, height, (byte *)(pinframe + 1), true, true);
+
+	return (void *)((byte *)pinframe + sizeof (dspriteframe_t) + size);
+}
+
+
+/*
+=================
+Mod_LoadSpriteGroup
+=================
+*/
+void * Mod_LoadSpriteGroup (void * pin, mspriteframe_t **ppframe, int framenum)
+{
+	dspritegroup_t		*pingroup;
+	mspritegroup_t		*pspritegroup;
+	int					i, numframes;
+	dspriteinterval_t	*pin_intervals;
+	float				*poutintervals;
+	void				*ptemp;
+
+	pingroup = (dspritegroup_t *)pin;
+
+	numframes = LittleLong (pingroup->numframes);
+
+	pspritegroup = Hunk_AllocName (sizeof (mspritegroup_t) +
+				(numframes - 1) * sizeof (pspritegroup->frames[0]), loadname);
+
+	pspritegroup->numframes = numframes;
+
+	*ppframe = (mspriteframe_t *)pspritegroup;
+
+	pin_intervals = (dspriteinterval_t *)(pingroup + 1);
+
+	poutintervals = Hunk_AllocName (numframes * sizeof (float), loadname);
+
+	pspritegroup->intervals = poutintervals;
+
+	for (i=0 ; i<numframes ; i++)
+	{
+		*poutintervals = LittleFloat (pin_intervals->interval);
+		if (*poutintervals <= 0.0)
+			Sys_Error ("Mod_LoadSpriteGroup: interval<=0");
+
+		poutintervals++;
+		pin_intervals++;
+	}
+
+	ptemp = (void *)pin_intervals;
+
+	for (i=0 ; i<numframes ; i++)
+	{
+		ptemp = Mod_LoadSpriteFrame (ptemp, &pspritegroup->frames[i], framenum * 100 + i);
+	}
+
+	return ptemp;
+}
+
+
+/*
+=================
+Mod_LoadSpriteModel
+=================
+*/
+void Mod_LoadSpriteModel (model_t *mod, void *buffer)
+{
+	int					i;
+	int					version;
+	dsprite_t			*pin;
+	msprite_t			*psprite;
+	int					numframes;
+	int					size;
+	dspriteframetype_t	*pframetype;
+	
+	pin = (dsprite_t *)buffer;
+
+	version = LittleLong (pin->version);
+	if (version != SPRITE_VERSION)
+		Sys_Error ("%s has wrong version number "
+				 "(%i should be %i)", mod->name, version, SPRITE_VERSION);
+
+	numframes = LittleLong (pin->numframes);
+
+	size = sizeof (msprite_t) +	(numframes - 1) * sizeof (psprite->frames);
+
+	psprite = Hunk_AllocName (size, loadname);
+
+	mod->cache.data = psprite;
+
+	psprite->type = LittleLong (pin->type);
+	psprite->maxwidth = LittleLong (pin->width);
+	psprite->maxheight = LittleLong (pin->height);
+	psprite->beamlength = LittleFloat (pin->beamlength);
+	mod->synctype = LittleLong (pin->synctype);
+	psprite->numframes = numframes;
+
+	mod->mins[0] = mod->mins[1] = -psprite->maxwidth/2;
+	mod->maxs[0] = mod->maxs[1] = psprite->maxwidth/2;
+	mod->mins[2] = -psprite->maxheight/2;
+	mod->maxs[2] = psprite->maxheight/2;
+	
+//
+// load the frames
+//
+	if (numframes < 1)
+		Sys_Error ("Mod_LoadSpriteModel: Invalid # of frames: %d\n", numframes);
+
+	mod->numframes = numframes;
+
+	pframetype = (dspriteframetype_t *)(pin + 1);
+
+	for (i=0 ; i<numframes ; i++)
+	{
+		spriteframetype_t	frametype;
+
+		frametype = LittleLong (pframetype->type);
+		psprite->frames[i].type = frametype;
+
+		if (frametype == SPR_SINGLE)
+		{
+			pframetype = (dspriteframetype_t *)
+					Mod_LoadSpriteFrame (pframetype + 1,
+										 &psprite->frames[i].frameptr, i);
+		}
+		else
+		{
+			pframetype = (dspriteframetype_t *)
+					Mod_LoadSpriteGroup (pframetype + 1,
+										 &psprite->frames[i].frameptr, i);
+		}
+	}
+
+	mod->type = mod_sprite;
+}
+
+//=============================================================================
+
+/*
+================
+Mod_Print
+================
+*/
+void Mod_Print (void)
+{
+	int		i;
+	model_t	*mod;
+
+	Con_Printf ("Cached models:\n");
+	for (i=0, mod=mod_known ; i < mod_numknown ; i++, mod++)
+	{
+		Con_Printf ("%8p : %s\n",mod->cache.data, mod->name);
+	}
+}
+
+
--- /dev/null
+++ b/QW/client/gl_model.h
@@ -1,0 +1,436 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+
+#ifndef __MODEL__
+#define __MODEL__
+
+#include "modelgen.h"
+#include "spritegn.h"
+
+/*
+
+d*_t structures are on-disk representations
+m*_t structures are in-memory
+
+*/
+
+// entity effects
+
+#define	EF_BRIGHTFIELD			1
+#define	EF_MUZZLEFLASH 			2
+#define	EF_BRIGHTLIGHT 			4
+#define	EF_DIMLIGHT 			8
+#define	EF_FLAG1	 			16
+#define	EF_FLAG2	 			32
+#define EF_BLUE					64
+#define EF_RED					128
+
+/*
+==============================================================================
+
+BRUSH MODELS
+
+==============================================================================
+*/
+
+
+//
+// in memory representation
+//
+// !!! if this is changed, it must be changed in asm_draw.h too !!!
+typedef struct
+{
+	vec3_t		position;
+} mvertex_t;
+
+#define	SIDE_FRONT	0
+#define	SIDE_BACK	1
+#define	SIDE_ON		2
+
+
+// plane_t structure
+// !!! if this is changed, it must be changed in asm_i386.h too !!!
+typedef struct mplane_s
+{
+	vec3_t	normal;
+	float	dist;
+	byte	type;			// for texture axis selection and fast side tests
+	byte	signbits;		// signx + signy<<1 + signz<<1
+	byte	pad[2];
+} mplane_t;
+
+typedef struct texture_s
+{
+	char		name[16];
+	unsigned	width, height;
+	int			gl_texturenum;
+	struct msurface_s	*texturechain;	// for gl_texsort drawing
+	int			anim_total;				// total tenths in sequence ( 0 = no)
+	int			anim_min, anim_max;		// time for this frame min <=time< max
+	struct texture_s *anim_next;		// in the animation sequence
+	struct texture_s *alternate_anims;	// bmodels in frmae 1 use these
+	unsigned	offsets[MIPLEVELS];		// four mip maps stored
+} texture_t;
+
+
+#define	SURF_PLANEBACK		2
+#define	SURF_DRAWSKY		4
+#define SURF_DRAWSPRITE		8
+#define SURF_DRAWTURB		0x10
+#define SURF_DRAWTILED		0x20
+#define SURF_DRAWBACKGROUND	0x40
+#define SURF_UNDERWATER		0x80
+#define SURF_DONTWARP		0x100
+
+// !!! if this is changed, it must be changed in asm_draw.h too !!!
+typedef struct
+{
+	unsigned short	v[2];
+	unsigned int	cachededgeoffset;
+} medge_t;
+
+typedef struct
+{
+	float		vecs[2][4];
+	float		mipadjust;
+	texture_t	*texture;
+	int			flags;
+} mtexinfo_t;
+
+#define	VERTEXSIZE	7
+
+typedef struct glpoly_s
+{
+	struct	glpoly_s	*next;
+	struct	glpoly_s	*chain;
+	int		numverts;
+	int		flags;			// for SURF_UNDERWATER
+	float	verts[4][VERTEXSIZE];	// variable sized (xyz s1t1 s2t2)
+} glpoly_t;
+
+typedef struct msurface_s
+{
+	int			visframe;		// should be drawn when node is crossed
+
+	mplane_t	*plane;
+	int			flags;
+
+	int			firstedge;	// look up in model->surfedges[], negative numbers
+	int			numedges;	// are backwards edges
+	
+	short		texturemins[2];
+	short		extents[2];
+
+	int			light_s, light_t;	// gl lightmap coordinates
+
+	glpoly_t	*polys;				// multiple if warped
+	struct	msurface_s	*texturechain;
+
+	mtexinfo_t	*texinfo;
+	
+// lighting info
+	int			dlightframe;
+	int			dlightbits;
+
+	int			lightmaptexturenum;
+	byte		styles[MAXLIGHTMAPS];
+	int			cached_light[MAXLIGHTMAPS];	// values currently used in lightmap
+	qboolean	cached_dlight;				// true if dynamic light in cache
+	byte		*samples;		// [numstyles*surfsize]
+} msurface_t;
+
+typedef struct mnode_s
+{
+// common with leaf
+	int			contents;		// 0, to differentiate from leafs
+	int			visframe;		// node needs to be traversed if current
+	
+	float		minmaxs[6];		// for bounding box culling
+
+	struct mnode_s	*parent;
+
+// node specific
+	mplane_t	*plane;
+	struct mnode_s	*children[2];	
+
+	unsigned short		firstsurface;
+	unsigned short		numsurfaces;
+} mnode_t;
+
+
+
+typedef struct mleaf_s
+{
+// common with node
+	int			contents;		// wil be a negative contents number
+	int			visframe;		// node needs to be traversed if current
+
+	float		minmaxs[6];		// for bounding box culling
+
+	struct mnode_s	*parent;
+
+// leaf specific
+	byte		*compressed_vis;
+	efrag_t		*efrags;
+
+	msurface_t	**firstmarksurface;
+	int			nummarksurfaces;
+	int			key;			// BSP sequence number for leaf's contents
+	byte		ambient_sound_level[NUM_AMBIENTS];
+} mleaf_t;
+
+// !!! if this is changed, it must be changed in asm_i386.h too !!!
+typedef struct
+{
+	dclipnode_t	*clipnodes;
+	mplane_t	*planes;
+	int			firstclipnode;
+	int			lastclipnode;
+	vec3_t		clip_mins;
+	vec3_t		clip_maxs;
+} hull_t;
+
+/*
+==============================================================================
+
+SPRITE MODELS
+
+==============================================================================
+*/
+
+
+// FIXME: shorten these?
+typedef struct mspriteframe_s
+{
+	int		width;
+	int		height;
+	float	up, down, left, right;
+	int		gl_texturenum;
+} mspriteframe_t;
+
+typedef struct
+{
+	int				numframes;
+	float			*intervals;
+	mspriteframe_t	*frames[1];
+} mspritegroup_t;
+
+typedef struct
+{
+	spriteframetype_t	type;
+	mspriteframe_t		*frameptr;
+} mspriteframedesc_t;
+
+typedef struct
+{
+	int					type;
+	int					maxwidth;
+	int					maxheight;
+	int					numframes;
+	float				beamlength;		// remove?
+	void				*cachespot;		// remove?
+	mspriteframedesc_t	frames[1];
+} msprite_t;
+
+
+/*
+==============================================================================
+
+ALIAS MODELS
+
+Alias models are position independent, so the cache manager can move them.
+==============================================================================
+*/
+
+typedef struct
+{
+	int					firstpose;
+	int					numposes;
+	float				interval;
+	trivertx_t			bboxmin;
+	trivertx_t			bboxmax;
+	int					frame;
+	char				name[16];
+} maliasframedesc_t;
+
+typedef struct
+{
+	trivertx_t			bboxmin;
+	trivertx_t			bboxmax;
+	int					frame;
+} maliasgroupframedesc_t;
+
+typedef struct
+{
+	int						numframes;
+	int						intervals;
+	maliasgroupframedesc_t	frames[1];
+} maliasgroup_t;
+
+// !!! if this is changed, it must be changed in asm_draw.h too !!!
+typedef struct mtriangle_s {
+	int					facesfront;
+	int					vertindex[3];
+} mtriangle_t;
+
+
+#define	MAX_SKINS	32
+typedef struct {
+	int			ident;
+	int			version;
+	vec3_t		scale;
+	vec3_t		scale_origin;
+	float		boundingradius;
+	vec3_t		eyeposition;
+	int			numskins;
+	int			skinwidth;
+	int			skinheight;
+	int			numverts;
+	int			numtris;
+	int			numframes;
+	synctype_t	synctype;
+	int			flags;
+	float		size;
+
+	int					numposes;
+	int					poseverts;
+	int					posedata;	// numposes*poseverts trivert_t
+	int					commands;	// gl command list with embedded s/t
+	int					gl_texturenum[MAX_SKINS][4];
+	maliasframedesc_t	frames[1];	// variable sized
+} aliashdr_t;
+
+#define	MAXALIASVERTS	1024
+#define	MAXALIASFRAMES	256
+#define	MAXALIASTRIS	2048
+extern	aliashdr_t	*pheader;
+extern	stvert_t	stverts[MAXALIASVERTS];
+extern	mtriangle_t	triangles[MAXALIASTRIS];
+extern	trivertx_t	*poseverts[MAXALIASFRAMES];
+
+//===================================================================
+
+//
+// Whole model
+//
+
+typedef enum {mod_brush, mod_sprite, mod_alias} modtype_t;
+
+#define	EF_ROCKET	1			// leave a trail
+#define	EF_GRENADE	2			// leave a trail
+#define	EF_GIB		4			// leave a trail
+#define	EF_ROTATE	8			// rotate (bonus items)
+#define	EF_TRACER	16			// green split trail
+#define	EF_ZOMGIB	32			// small blood trail
+#define	EF_TRACER2	64			// orange split trail + rotate
+#define	EF_TRACER3	128			// purple trail
+
+typedef struct model_s
+{
+	char		name[MAX_QPATH];
+	qboolean	needload;		// bmodels and sprites don't cache normally
+
+	modtype_t	type;
+	int			numframes;
+	synctype_t	synctype;
+	
+	int			flags;
+
+//
+// volume occupied by the model graphics
+//		
+	vec3_t		mins, maxs;
+	float		radius;
+
+//
+// solid volume for clipping 
+//
+	qboolean	clipbox;
+	vec3_t		clipmins, clipmaxs;
+
+//
+// brush model
+//
+	int			firstmodelsurface, nummodelsurfaces;
+
+	int			numsubmodels;
+	dmodel_t	*submodels;
+
+	int			numplanes;
+	mplane_t	*planes;
+
+	int			numleafs;		// number of visible leafs, not counting 0
+	mleaf_t		*leafs;
+
+	int			numvertexes;
+	mvertex_t	*vertexes;
+
+	int			numedges;
+	medge_t		*edges;
+
+	int			numnodes;
+	mnode_t		*nodes;
+
+	int			numtexinfo;
+	mtexinfo_t	*texinfo;
+
+	int			numsurfaces;
+	msurface_t	*surfaces;
+
+	int			numsurfedges;
+	int			*surfedges;
+
+	int			numclipnodes;
+	dclipnode_t	*clipnodes;
+
+	int			nummarksurfaces;
+	msurface_t	**marksurfaces;
+
+	hull_t		hulls[MAX_MAP_HULLS];
+
+	int			numtextures;
+	texture_t	**textures;
+
+	byte		*visdata;
+	byte		*lightdata;
+	char		*entities;
+
+	unsigned	checksum;
+	unsigned	checksum2;
+
+//
+// additional model data
+//
+	cache_user_t	cache;		// only access through Mod_Extradata
+
+} model_t;
+
+//============================================================================
+
+void	Mod_Init (void);
+void	Mod_ClearAll (void);
+model_t *Mod_ForName (char *name, qboolean crash);
+void	*Mod_Extradata (model_t *mod);	// handles caching
+void	Mod_TouchModel (char *name);
+
+mleaf_t *Mod_PointInLeaf (float *p, model_t *model);
+byte	*Mod_LeafPVS (mleaf_t *leaf, model_t *model);
+
+#endif	// __MODEL__
--- /dev/null
+++ b/QW/client/gl_ngraph.c
@@ -1,0 +1,141 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// gl_ngraph.c
+
+#include "quakedef.h"
+
+extern byte		*draw_chars;				// 8*8 graphic characters
+
+int	netgraphtexture;	// netgraph texture
+
+#define NET_GRAPHHEIGHT 32
+
+static	byte ngraph_texels[NET_GRAPHHEIGHT][NET_TIMINGS];
+
+static void R_LineGraph (int x, int h)
+{
+	int		i;
+	int		s;
+	int		color;
+
+	s = NET_GRAPHHEIGHT;
+
+	if (h == 10000)
+		color = 0x6f;	// yellow
+	else if (h == 9999)
+		color = 0x4f;	// red
+	else if (h == 9998)
+		color = 0xd0;	// blue
+	else
+		color = 0xfe;	// white
+
+	if (h>s)
+		h = s;
+	
+	for (i=0 ; i<h ; i++)
+		if (i & 1)
+			ngraph_texels[NET_GRAPHHEIGHT - i - 1][x] = 0xff;
+		else
+			ngraph_texels[NET_GRAPHHEIGHT - i - 1][x] = (byte)color;
+
+	for ( ; i<s ; i++)
+		ngraph_texels[NET_GRAPHHEIGHT - i - 1][x] = (byte)0xff;
+}
+
+void Draw_CharToNetGraph (int x, int y, int num)
+{
+	int		row, col;
+	byte	*source;
+	int		drawline;
+	int		nx;
+
+	row = num>>4;
+	col = num&15;
+	source = draw_chars + (row<<10) + (col<<3);
+
+	for (drawline = 8; drawline; drawline--, y++)
+	{
+		for (nx=0 ; nx<8 ; nx++)
+			if (source[nx] != 255)
+				ngraph_texels[y][nx+x] = 0x60 + source[nx];
+		source += 128;
+	}
+}
+
+
+/*
+==============
+R_NetGraph
+==============
+*/
+void R_NetGraph (void)
+{
+	int		a, x, i, y;
+	int lost;
+	char st[80];
+	unsigned	ngraph_pixels[NET_GRAPHHEIGHT][NET_TIMINGS];
+
+	x = 0;
+	lost = CL_CalcNet();
+	for (a=0 ; a<NET_TIMINGS ; a++)
+	{
+		i = (cls.netchan.outgoing_sequence-a) & NET_TIMINGSMASK;
+		R_LineGraph (NET_TIMINGS-1-a, packet_latency[i]);
+	}
+
+	// now load the netgraph texture into gl and draw it
+	for (y = 0; y < NET_GRAPHHEIGHT; y++)
+		for (x = 0; x < NET_TIMINGS; x++)
+			ngraph_pixels[y][x] = d_8to24table[ngraph_texels[y][x]];
+
+	x =	-((vid.width - 320)>>1);
+	y = vid.height - sb_lines - 24 - NET_GRAPHHEIGHT - 1;
+
+	M_DrawTextBox (x, y, NET_TIMINGS/8, NET_GRAPHHEIGHT/8 + 1);
+	y += 8;
+
+	sprintf(st, "%3i%% packet loss", lost);
+	Draw_String(8, y, st);
+	y += 8;
+	
+    GL_Bind(netgraphtexture);
+
+	glTexImage2D (GL_TEXTURE_2D, 0, gl_alpha_format, 
+		NET_TIMINGS, NET_GRAPHHEIGHT, 0, GL_RGBA, 
+		GL_UNSIGNED_BYTE, ngraph_pixels);
+
+	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+	x = 8;
+	glColor3f (1,1,1);
+	glBegin (GL_QUADS);
+	glTexCoord2f (0, 0);
+	glVertex2f (x, y);
+	glTexCoord2f (1, 0);
+	glVertex2f (x+NET_TIMINGS, y);
+	glTexCoord2f (1, 1);
+	glVertex2f (x+NET_TIMINGS, y+NET_GRAPHHEIGHT);
+	glTexCoord2f (0, 1);
+	glVertex2f (x, y+NET_GRAPHHEIGHT);
+	glEnd ();
+}
+
--- /dev/null
+++ b/QW/client/gl_refrag.c
@@ -1,0 +1,234 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// r_efrag.c
+
+#include "quakedef.h"
+
+mnode_t	*r_pefragtopnode;
+
+
+//===========================================================================
+
+/*
+===============================================================================
+
+					ENTITY FRAGMENT FUNCTIONS
+
+===============================================================================
+*/
+
+efrag_t		**lastlink;
+
+vec3_t		r_emins, r_emaxs;
+
+entity_t	*r_addent;
+
+
+/*
+================
+R_RemoveEfrags
+
+Call when removing an object from the world or moving it to another position
+================
+*/
+void R_RemoveEfrags (entity_t *ent)
+{
+	efrag_t		*ef, *old, *walk, **prev;
+	
+	ef = ent->efrag;
+	
+	while (ef)
+	{
+		prev = &ef->leaf->efrags;
+		while (1)
+		{
+			walk = *prev;
+			if (!walk)
+				break;
+			if (walk == ef)
+			{	// remove this fragment
+				*prev = ef->leafnext;
+				break;
+			}
+			else
+				prev = &walk->leafnext;
+		}
+				
+		old = ef;
+		ef = ef->entnext;
+		
+	// put it on the free list
+		old->entnext = cl.free_efrags;
+		cl.free_efrags = old;
+	}
+	
+	ent->efrag = NULL; 
+}
+
+/*
+===================
+R_SplitEntityOnNode
+===================
+*/
+void R_SplitEntityOnNode (mnode_t *node)
+{
+	efrag_t		*ef;
+	mplane_t	*splitplane;
+	mleaf_t		*leaf;
+	int			sides;
+	
+	if (node->contents == CONTENTS_SOLID)
+	{
+		return;
+	}
+	
+// add an efrag if the node is a leaf
+
+	if ( node->contents < 0)
+	{
+		if (!r_pefragtopnode)
+			r_pefragtopnode = node;
+
+		leaf = (mleaf_t *)node;
+
+// grab an efrag off the free list
+		ef = cl.free_efrags;
+		if (!ef)
+		{
+			Con_Printf ("Too many efrags!\n");
+			return;		// no free fragments...
+		}
+		cl.free_efrags = cl.free_efrags->entnext;
+
+		ef->entity = r_addent;
+		
+// add the entity link	
+		*lastlink = ef;
+		lastlink = &ef->entnext;
+		ef->entnext = NULL;
+		
+// set the leaf links
+		ef->leaf = leaf;
+		ef->leafnext = leaf->efrags;
+		leaf->efrags = ef;
+			
+		return;
+	}
+	
+// NODE_MIXED
+
+	splitplane = node->plane;
+	sides = BOX_ON_PLANE_SIDE(r_emins, r_emaxs, splitplane);
+	
+	if (sides == 3)
+	{
+	// split on this plane
+	// if this is the first splitter of this bmodel, remember it
+		if (!r_pefragtopnode)
+			r_pefragtopnode = node;
+	}
+	
+// recurse down the contacted sides
+	if (sides & 1)
+		R_SplitEntityOnNode (node->children[0]);
+		
+	if (sides & 2)
+		R_SplitEntityOnNode (node->children[1]);
+}
+
+
+
+/*
+===========
+R_AddEfrags
+===========
+*/
+void R_AddEfrags (entity_t *ent)
+{
+	model_t		*entmodel;
+	int			i;
+		
+	if (!ent->model)
+		return;
+
+	r_addent = ent;
+			
+	lastlink = &ent->efrag;
+	r_pefragtopnode = NULL;
+	
+	entmodel = ent->model;
+
+	for (i=0 ; i<3 ; i++)
+	{
+		r_emins[i] = ent->origin[i] + entmodel->mins[i];
+		r_emaxs[i] = ent->origin[i] + entmodel->maxs[i];
+	}
+
+	R_SplitEntityOnNode (cl.worldmodel->nodes);
+
+	ent->topnode = r_pefragtopnode;
+}
+
+
+/*
+================
+R_StoreEfrags
+
+// FIXME: a lot of this goes away with edge-based
+================
+*/
+void R_StoreEfrags (efrag_t **ppefrag)
+{
+	entity_t	*pent;
+	model_t		*clmodel;
+	efrag_t		*pefrag;
+
+
+	while ((pefrag = *ppefrag) != NULL)
+	{
+		pent = pefrag->entity;
+		clmodel = pent->model;
+
+		switch (clmodel->type)
+		{
+		case mod_alias:
+		case mod_brush:
+		case mod_sprite:
+			pent = pefrag->entity;
+
+			if ((pent->visframe != r_framecount) &&
+				(cl_numvisedicts < MAX_VISEDICTS))
+			{
+				cl_visedicts[cl_numvisedicts++] = *pent;
+
+			// mark that we've recorded this entity for this frame
+				pent->visframe = r_framecount;
+			}
+
+			ppefrag = &pefrag->leafnext;
+			break;
+
+		default:	
+			Sys_Error ("R_StoreEfrags: Bad entity type %d\n", clmodel->type);
+		}
+	}
+}
+
+
--- /dev/null
+++ b/QW/client/gl_rlight.c
@@ -1,0 +1,381 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// r_light.c
+
+#include "quakedef.h"
+
+int	r_dlightframecount;
+
+
+/*
+==================
+R_AnimateLight
+==================
+*/
+void R_AnimateLight (void)
+{
+	int			i,j,k;
+	
+//
+// light animations
+// 'm' is normal light, 'a' is no light, 'z' is double bright
+	i = (int)(cl.time*10);
+	for (j=0 ; j<MAX_LIGHTSTYLES ; j++)
+	{
+		if (!cl_lightstyle[j].length)
+		{
+			d_lightstylevalue[j] = 256;
+			continue;
+		}
+		k = i % cl_lightstyle[j].length;
+		k = cl_lightstyle[j].map[k] - 'a';
+		k = k*22;
+		d_lightstylevalue[j] = k;
+	}	
+}
+
+/*
+=============================================================================
+
+DYNAMIC LIGHTS BLEND RENDERING
+
+=============================================================================
+*/
+
+void AddLightBlend (float r, float g, float b, float a2)
+{
+	float	a;
+
+	v_blend[3] = a = v_blend[3] + a2*(1-v_blend[3]);
+
+	a2 = a2/a;
+
+	v_blend[0] = v_blend[1]*(1-a2) + r*a2;
+	v_blend[1] = v_blend[1]*(1-a2) + g*a2;
+	v_blend[2] = v_blend[2]*(1-a2) + b*a2;
+//Con_Printf("AddLightBlend(): %4.2f %4.2f %4.2f %4.6f\n", v_blend[0], v_blend[1], v_blend[2], v_blend[3]);
+}
+
+float bubble_sintable[17], bubble_costable[17];
+
+void R_InitBubble() {
+	float a;
+	int i;
+	float *bub_sin, *bub_cos;
+
+	bub_sin = bubble_sintable;
+	bub_cos = bubble_costable;
+
+	for (i=16 ; i>=0 ; i--)
+	{
+		a = i/16.0 * M_PI*2;
+		*bub_sin++ = sin(a);
+		*bub_cos++ = cos(a);
+	}
+}
+
+void R_RenderDlight (dlight_t *light)
+{
+	int		i, j;
+//	float	a;
+	vec3_t	v;
+	float	rad;
+	float	*bub_sin, *bub_cos;
+
+	bub_sin = bubble_sintable;
+	bub_cos = bubble_costable;
+	rad = light->radius * 0.35;
+
+	VectorSubtract (light->origin, r_origin, v);
+	if (Length (v) < rad)
+	{	// view is inside the dlight
+		AddLightBlend (1, 0.5, 0, light->radius * 0.0003);
+		return;
+	}
+
+	glBegin (GL_TRIANGLE_FAN);
+//	glColor3f (0.2,0.1,0.0);
+//	glColor3f (0.2,0.1,0.05); // changed dimlight effect
+	glColor4f (light->color[0], light->color[1], light->color[2],
+		light->color[3]);
+	for (i=0 ; i<3 ; i++)
+		v[i] = light->origin[i] - vpn[i]*rad;
+	glVertex3fv (v);
+	glColor3f (0,0,0);
+	for (i=16 ; i>=0 ; i--)
+	{
+//		a = i/16.0 * M_PI*2;
+		for (j=0 ; j<3 ; j++)
+			v[j] = light->origin[j] + (vright[j]*(*bub_cos) +
+				+ vup[j]*(*bub_sin)) * rad;
+		bub_sin++; 
+		bub_cos++;
+		glVertex3fv (v);
+	}
+	glEnd ();
+}
+
+/*
+=============
+R_RenderDlights
+=============
+*/
+void R_RenderDlights (void)
+{
+	int		i;
+	dlight_t	*l;
+
+	if (!gl_flashblend.value)
+		return;
+
+	r_dlightframecount = r_framecount + 1;	// because the count hasn't
+											//  advanced yet for this frame
+	glDepthMask (0);
+	glDisable (GL_TEXTURE_2D);
+	glShadeModel (GL_SMOOTH);
+	glEnable (GL_BLEND);
+	glBlendFunc (GL_ONE, GL_ONE);
+
+	l = cl_dlights;
+	for (i=0 ; i<MAX_DLIGHTS ; i++, l++)
+	{
+		if (l->die < cl.time || !l->radius)
+			continue;
+		R_RenderDlight (l);
+	}
+
+	glColor3f (1,1,1);
+	glDisable (GL_BLEND);
+	glEnable (GL_TEXTURE_2D);
+	glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+	glDepthMask (1);
+}
+
+
+/*
+=============================================================================
+
+DYNAMIC LIGHTS
+
+=============================================================================
+*/
+
+/*
+=============
+R_MarkLights
+=============
+*/
+void R_MarkLights (dlight_t *light, int bit, mnode_t *node)
+{
+	mplane_t	*splitplane;
+	float		dist;
+	msurface_t	*surf;
+	int			i;
+	
+	if (node->contents < 0)
+		return;
+
+	splitplane = node->plane;
+	dist = DotProduct (light->origin, splitplane->normal) - splitplane->dist;
+	
+	if (dist > light->radius)
+	{
+		R_MarkLights (light, bit, node->children[0]);
+		return;
+	}
+	if (dist < -light->radius)
+	{
+		R_MarkLights (light, bit, node->children[1]);
+		return;
+	}
+		
+// mark the polygons
+	surf = cl.worldmodel->surfaces + node->firstsurface;
+	for (i=0 ; i<node->numsurfaces ; i++, surf++)
+	{
+		if (surf->dlightframe != r_dlightframecount)
+		{
+			surf->dlightbits = 0;
+			surf->dlightframe = r_dlightframecount;
+		}
+		surf->dlightbits |= bit;
+	}
+
+	R_MarkLights (light, bit, node->children[0]);
+	R_MarkLights (light, bit, node->children[1]);
+}
+
+
+/*
+=============
+R_PushDlights
+=============
+*/
+void R_PushDlights (void)
+{
+	int		i;
+	dlight_t	*l;
+
+	if (gl_flashblend.value)
+		return;
+
+	r_dlightframecount = r_framecount + 1;	// because the count hasn't
+											//  advanced yet for this frame
+	l = cl_dlights;
+
+	for (i=0 ; i<MAX_DLIGHTS ; i++, l++)
+	{
+		if (l->die < cl.time || !l->radius)
+			continue;
+		R_MarkLights ( l, 1<<i, cl.worldmodel->nodes );
+	}
+}
+
+
+/*
+=============================================================================
+
+LIGHT SAMPLING
+
+=============================================================================
+*/
+
+mplane_t		*lightplane;
+vec3_t			lightspot;
+
+int RecursiveLightPoint (mnode_t *node, vec3_t start, vec3_t end)
+{
+	int			r;
+	float		front, back, frac;
+	int			side;
+	mplane_t	*plane;
+	vec3_t		mid;
+	msurface_t	*surf;
+	int			s, t, ds, dt;
+	int			i;
+	mtexinfo_t	*tex;
+	byte		*lightmap;
+	unsigned	scale;
+	int			maps;
+
+	if (node->contents < 0)
+		return -1;		// didn't hit anything
+	
+// calculate mid point
+
+// FIXME: optimize for axial
+	plane = node->plane;
+	front = DotProduct (start, plane->normal) - plane->dist;
+	back = DotProduct (end, plane->normal) - plane->dist;
+	side = front < 0;
+	
+	if ( (back < 0) == side)
+		return RecursiveLightPoint (node->children[side], start, end);
+	
+	frac = front / (front-back);
+	mid[0] = start[0] + (end[0] - start[0])*frac;
+	mid[1] = start[1] + (end[1] - start[1])*frac;
+	mid[2] = start[2] + (end[2] - start[2])*frac;
+	
+// go down front side	
+	r = RecursiveLightPoint (node->children[side], start, mid);
+	if (r >= 0)
+		return r;		// hit something
+		
+	if ( (back < 0) == side )
+		return -1;		// didn't hit anuthing
+		
+// check for impact on this node
+	VectorCopy (mid, lightspot);
+	lightplane = plane;
+
+	surf = cl.worldmodel->surfaces + node->firstsurface;
+	for (i=0 ; i<node->numsurfaces ; i++, surf++)
+	{
+		if (surf->flags & SURF_DRAWTILED)
+			continue;	// no lightmaps
+
+		tex = surf->texinfo;
+		
+		s = DotProduct (mid, tex->vecs[0]) + tex->vecs[0][3];
+		t = DotProduct (mid, tex->vecs[1]) + tex->vecs[1][3];;
+
+		if (s < surf->texturemins[0] ||
+		t < surf->texturemins[1])
+			continue;
+		
+		ds = s - surf->texturemins[0];
+		dt = t - surf->texturemins[1];
+		
+		if ( ds > surf->extents[0] || dt > surf->extents[1] )
+			continue;
+
+		if (!surf->samples)
+			return 0;
+
+		ds >>= 4;
+		dt >>= 4;
+
+		lightmap = surf->samples;
+		r = 0;
+		if (lightmap)
+		{
+
+			lightmap += dt * ((surf->extents[0]>>4)+1) + ds;
+
+			for (maps = 0 ; maps < MAXLIGHTMAPS && surf->styles[maps] != 255 ;
+					maps++)
+			{
+				scale = d_lightstylevalue[surf->styles[maps]];
+				r += *lightmap * scale;
+				lightmap += ((surf->extents[0]>>4)+1) *
+						((surf->extents[1]>>4)+1);
+			}
+			
+			r >>= 8;
+		}
+		
+		return r;
+	}
+
+// go down back side
+	return RecursiveLightPoint (node->children[!side], mid, end);
+}
+
+int R_LightPoint (vec3_t p)
+{
+	vec3_t		end;
+	int			r;
+	
+	if (!cl.worldmodel->lightdata)
+		return 255;
+	
+	end[0] = p[0];
+	end[1] = p[1];
+	end[2] = p[2] - 2048;
+	
+	r = RecursiveLightPoint (cl.worldmodel->nodes, p, end);
+	
+	if (r == -1)
+		r = 0;
+
+	return r;
+}
+
--- /dev/null
+++ b/QW/client/gl_rmain.c
@@ -1,0 +1,1144 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// r_main.c
+
+#include "quakedef.h"
+
+entity_t	r_worldentity;
+
+qboolean	r_cache_thrash;		// compatability
+
+vec3_t		modelorg, r_entorigin;
+entity_t	*currententity;
+
+int			r_visframecount;	// bumped when going to a new PVS
+int			r_framecount;		// used for dlight push checking
+
+mplane_t	frustum[4];
+
+int			c_brush_polys, c_alias_polys;
+
+qboolean	envmap;				// true during envmap command capture 
+
+int			currenttexture = -1;		// to avoid unnecessary texture sets
+
+int			cnttextures[2] = {-1, -1};     // cached
+
+int			particletexture;	// little dot for particles
+int			playertextures;		// up to 16 color translated skins
+
+int			mirrortexturenum;	// quake texturenum, not gltexturenum
+qboolean	mirror;
+mplane_t	*mirror_plane;
+
+//
+// view origin
+//
+vec3_t	vup;
+vec3_t	vpn;
+vec3_t	vright;
+vec3_t	r_origin;
+
+float	r_world_matrix[16];
+float	r_base_world_matrix[16];
+
+//
+// screen size info
+//
+refdef_t	r_refdef;
+
+mleaf_t		*r_viewleaf, *r_oldviewleaf;
+
+texture_t	*r_notexture_mip;
+
+int		d_lightstylevalue[256];	// 8.8 fraction of base light value
+
+
+void R_MarkLeaves (void);
+
+cvar_t	r_norefresh = {"r_norefresh","0"};
+cvar_t	r_drawentities = {"r_drawentities","1"};
+cvar_t	r_drawviewmodel = {"r_drawviewmodel","1"};
+cvar_t	r_speeds = {"r_speeds","0"};
+cvar_t	r_fullbright = {"r_fullbright","0"};
+cvar_t	r_lightmap = {"r_lightmap","0"};
+cvar_t	r_shadows = {"r_shadows","0"};
+cvar_t	r_mirroralpha = {"r_mirroralpha","1"};
+cvar_t	r_wateralpha = {"r_wateralpha","1"};
+cvar_t	r_dynamic = {"r_dynamic","1"};
+cvar_t	r_novis = {"r_novis","0"};
+cvar_t	r_netgraph = {"r_netgraph","0"};
+
+cvar_t	gl_clear = {"gl_clear","0"};
+cvar_t	gl_cull = {"gl_cull","1"};
+cvar_t	gl_texsort = {"gl_texsort","1"};
+cvar_t	gl_smoothmodels = {"gl_smoothmodels","1"};
+cvar_t	gl_affinemodels = {"gl_affinemodels","0"};
+cvar_t	gl_polyblend = {"gl_polyblend","1"};
+cvar_t	gl_flashblend = {"gl_flashblend","1"};
+cvar_t	gl_playermip = {"gl_playermip","0"};
+cvar_t	gl_nocolors = {"gl_nocolors","0"};
+cvar_t	gl_keeptjunctions = {"gl_keeptjunctions","1"};
+cvar_t	gl_reporttjunctions = {"gl_reporttjunctions","0"};
+cvar_t	gl_finish = {"gl_finish","0"};
+
+extern	cvar_t	gl_ztrick;
+extern	cvar_t	scr_fov;
+/*
+=================
+R_CullBox
+
+Returns true if the box is completely outside the frustom
+=================
+*/
+qboolean R_CullBox (vec3_t mins, vec3_t maxs)
+{
+	int		i;
+
+	for (i=0 ; i<4 ; i++)
+		if (BoxOnPlaneSide (mins, maxs, &frustum[i]) == 2)
+			return true;
+	return false;
+}
+
+
+void R_RotateForEntity (entity_t *e)
+{
+    glTranslatef (e->origin[0],  e->origin[1],  e->origin[2]);
+
+    glRotatef (e->angles[1],  0, 0, 1);
+    glRotatef (-e->angles[0],  0, 1, 0);
+	//ZOID: fixed z angle
+    glRotatef (e->angles[2],  1, 0, 0);
+}
+
+/*
+=============================================================
+
+  SPRITE MODELS
+
+=============================================================
+*/
+
+/*
+================
+R_GetSpriteFrame
+================
+*/
+mspriteframe_t *R_GetSpriteFrame (entity_t *currententity)
+{
+	msprite_t		*psprite;
+	mspritegroup_t	*pspritegroup;
+	mspriteframe_t	*pspriteframe;
+	int				i, numframes, frame;
+	float			*pintervals, fullinterval, targettime, time;
+
+	psprite = currententity->model->cache.data;
+	frame = currententity->frame;
+
+	if ((frame >= psprite->numframes) || (frame < 0))
+	{
+		Con_Printf ("R_DrawSprite: no such frame %d\n", frame);
+		frame = 0;
+	}
+
+	if (psprite->frames[frame].type == SPR_SINGLE)
+	{
+		pspriteframe = psprite->frames[frame].frameptr;
+	}
+	else
+	{
+		pspritegroup = (mspritegroup_t *)psprite->frames[frame].frameptr;
+		pintervals = pspritegroup->intervals;
+		numframes = pspritegroup->numframes;
+		fullinterval = pintervals[numframes-1];
+
+		time = cl.time + currententity->syncbase;
+
+	// when loading in Mod_LoadSpriteGroup, we guaranteed all interval values
+	// are positive, so we don't have to worry about division by 0
+		targettime = time - ((int)(time / fullinterval)) * fullinterval;
+
+		for (i=0 ; i<(numframes-1) ; i++)
+		{
+			if (pintervals[i] > targettime)
+				break;
+		}
+
+		pspriteframe = pspritegroup->frames[i];
+	}
+
+	return pspriteframe;
+}
+
+
+/*
+=================
+R_DrawSpriteModel
+
+=================
+*/
+void R_DrawSpriteModel (entity_t *e)
+{
+	vec3_t	point;
+	mspriteframe_t	*frame;
+	float		*up, *right;
+	vec3_t		v_forward, v_right, v_up;
+	msprite_t		*psprite;
+
+	// don't even bother culling, because it's just a single
+	// polygon without a surface cache
+	frame = R_GetSpriteFrame (e);
+	psprite = currententity->model->cache.data;
+
+	if (psprite->type == SPR_ORIENTED)
+	{	// bullet marks on walls
+		AngleVectors (currententity->angles, v_forward, v_right, v_up);
+		up = v_up;
+		right = v_right;
+	}
+	else
+	{	// normal sprite
+		up = vup;
+		right = vright;
+	}
+
+	glColor3f (1,1,1);
+
+	GL_DisableMultitexture();
+
+    GL_Bind(frame->gl_texturenum);
+
+	glEnable (GL_ALPHA_TEST);
+	glBegin (GL_QUADS);
+
+	glEnable (GL_ALPHA_TEST);
+	glBegin (GL_QUADS);
+
+	glTexCoord2f (0, 1);
+	VectorMA (e->origin, frame->down, up, point);
+	VectorMA (point, frame->left, right, point);
+	glVertex3fv (point);
+
+	glTexCoord2f (0, 0);
+	VectorMA (e->origin, frame->up, up, point);
+	VectorMA (point, frame->left, right, point);
+	glVertex3fv (point);
+
+	glTexCoord2f (1, 0);
+	VectorMA (e->origin, frame->up, up, point);
+	VectorMA (point, frame->right, right, point);
+	glVertex3fv (point);
+
+	glTexCoord2f (1, 1);
+	VectorMA (e->origin, frame->down, up, point);
+	VectorMA (point, frame->right, right, point);
+	glVertex3fv (point);
+	
+	glEnd ();
+
+	glDisable (GL_ALPHA_TEST);
+}
+
+/*
+=============================================================
+
+  ALIAS MODELS
+
+=============================================================
+*/
+
+
+#define NUMVERTEXNORMALS	162
+
+float	r_avertexnormals[NUMVERTEXNORMALS][3] = {
+#include "anorms.h"
+};
+
+vec3_t	shadevector;
+float	shadelight, ambientlight;
+
+// precalculated dot products for quantized angles
+#define SHADEDOT_QUANT 16
+float	r_avertexnormal_dots[SHADEDOT_QUANT][256] =
+#include "anorm_dots.h"
+;
+
+float	*shadedots = r_avertexnormal_dots[0];
+
+int	lastposenum;
+
+/*
+=============
+GL_DrawAliasFrame
+=============
+*/
+void GL_DrawAliasFrame (aliashdr_t *paliashdr, int posenum)
+{
+	float 	l;
+	trivertx_t	*verts;
+	int		*order;
+	int		count;
+
+lastposenum = posenum;
+
+	verts = (trivertx_t *)((byte *)paliashdr + paliashdr->posedata);
+	verts += posenum * paliashdr->poseverts;
+	order = (int *)((byte *)paliashdr + paliashdr->commands);
+
+	while (1)
+	{
+		// get the vertex count and primitive type
+		count = *order++;
+		if (!count)
+			break;		// done
+		if (count < 0)
+		{
+			count = -count;
+			glBegin (GL_TRIANGLE_FAN);
+		}
+		else
+			glBegin (GL_TRIANGLE_STRIP);
+
+		do
+		{
+			// texture coordinates come from the draw list
+			glTexCoord2f (((float *)order)[0], ((float *)order)[1]);
+			order += 2;
+
+			// normals and vertexes come from the frame list
+			l = shadedots[verts->lightnormalindex] * shadelight;
+			glColor3f (l, l, l);
+			glVertex3f (verts->v[0], verts->v[1], verts->v[2]);
+			verts++;
+		} while (--count);
+
+		glEnd ();
+	}
+}
+
+
+/*
+=============
+GL_DrawAliasShadow
+=============
+*/
+extern	vec3_t			lightspot;
+
+void GL_DrawAliasShadow (aliashdr_t *paliashdr, int posenum)
+{
+	trivertx_t	*verts;
+	int		*order;
+	vec3_t	point;
+	float	height, lheight;
+	int		count;
+
+	lheight = currententity->origin[2] - lightspot[2];
+
+	height = 0;
+	verts = (trivertx_t *)((byte *)paliashdr + paliashdr->posedata);
+	verts += posenum * paliashdr->poseverts;
+	order = (int *)((byte *)paliashdr + paliashdr->commands);
+
+	height = -lheight + 1.0;
+
+	while (1)
+	{
+		// get the vertex count and primitive type
+		count = *order++;
+		if (!count)
+			break;		// done
+		if (count < 0)
+		{
+			count = -count;
+			glBegin (GL_TRIANGLE_FAN);
+		}
+		else
+			glBegin (GL_TRIANGLE_STRIP);
+
+		do
+		{
+			// texture coordinates come from the draw list
+			// (skipped for shadows) glTexCoord2fv ((float *)order);
+			order += 2;
+
+			// normals and vertexes come from the frame list
+			point[0] = verts->v[0] * paliashdr->scale[0] + paliashdr->scale_origin[0];
+			point[1] = verts->v[1] * paliashdr->scale[1] + paliashdr->scale_origin[1];
+			point[2] = verts->v[2] * paliashdr->scale[2] + paliashdr->scale_origin[2];
+
+			point[0] -= shadevector[0]*(point[2]+lheight);
+			point[1] -= shadevector[1]*(point[2]+lheight);
+			point[2] = height;
+//			height -= 0.001;
+			glVertex3fv (point);
+
+			verts++;
+		} while (--count);
+
+		glEnd ();
+	}	
+}
+
+
+
+/*
+=================
+R_SetupAliasFrame
+
+=================
+*/
+void R_SetupAliasFrame (int frame, aliashdr_t *paliashdr)
+{
+	int				pose, numposes;
+	float			interval;
+
+	if ((frame >= paliashdr->numframes) || (frame < 0))
+	{
+		Con_DPrintf ("R_AliasSetupFrame: no such frame %d\n", frame);
+		frame = 0;
+	}
+
+	pose = paliashdr->frames[frame].firstpose;
+	numposes = paliashdr->frames[frame].numposes;
+
+	if (numposes > 1)
+	{
+		interval = paliashdr->frames[frame].interval;
+		pose += (int)(cl.time / interval) % numposes;
+	}
+
+	GL_DrawAliasFrame (paliashdr, pose);
+}
+
+
+
+/*
+=================
+R_DrawAliasModel
+
+=================
+*/
+void R_DrawAliasModel (entity_t *e)
+{
+	int			i;
+	int			lnum;
+	vec3_t		dist;
+	float		add;
+	model_t		*clmodel;
+	vec3_t		mins, maxs;
+	aliashdr_t	*paliashdr;
+	float		an;
+	int			anim;
+
+	clmodel = currententity->model;
+
+	VectorAdd (currententity->origin, clmodel->mins, mins);
+	VectorAdd (currententity->origin, clmodel->maxs, maxs);
+
+	if (R_CullBox (mins, maxs))
+		return;
+
+
+	VectorCopy (currententity->origin, r_entorigin);
+	VectorSubtract (r_origin, r_entorigin, modelorg);
+
+	//
+	// get lighting information
+	//
+
+	ambientlight = shadelight = R_LightPoint (currententity->origin);
+
+	// allways give the gun some light
+	if (e == &cl.viewent && ambientlight < 24)
+		ambientlight = shadelight = 24;
+
+	for (lnum=0 ; lnum<MAX_DLIGHTS ; lnum++)
+	{
+		if (cl_dlights[lnum].die >= cl.time)
+		{
+			VectorSubtract (currententity->origin,
+							cl_dlights[lnum].origin,
+							dist);
+			add = cl_dlights[lnum].radius - Length(dist);
+
+			if (add > 0) {
+				ambientlight += add;
+				//ZOID models should be affected by dlights as well
+				shadelight += add;
+			}
+		}
+	}
+
+	// clamp lighting so it doesn't overbright as much
+	if (ambientlight > 128)
+		ambientlight = 128;
+	if (ambientlight + shadelight > 192)
+		shadelight = 192 - ambientlight;
+
+	// ZOID: never allow players to go totally black
+	if (!strcmp(clmodel->name, "progs/player.mdl")) {
+		if (ambientlight < 8)
+			ambientlight = shadelight = 8;
+
+	} else if (!strcmp (clmodel->name, "progs/flame2.mdl")
+		|| !strcmp (clmodel->name, "progs/flame.mdl") )
+		// HACK HACK HACK -- no fullbright colors, so make torches full light
+		ambientlight = shadelight = 256;
+
+	shadedots = r_avertexnormal_dots[((int)(e->angles[1] * (SHADEDOT_QUANT / 360.0))) & (SHADEDOT_QUANT - 1)];
+	shadelight = shadelight / 200.0;
+	
+	an = e->angles[1]/180*M_PI;
+	shadevector[0] = cos(-an);
+	shadevector[1] = sin(-an);
+	shadevector[2] = 1;
+	VectorNormalize (shadevector);
+
+	//
+	// locate the proper data
+	//
+	paliashdr = (aliashdr_t *)Mod_Extradata (currententity->model);
+
+	c_alias_polys += paliashdr->numtris;
+
+	//
+	// draw all the triangles
+	//
+
+	GL_DisableMultitexture();
+
+    glPushMatrix ();
+	R_RotateForEntity (e);
+
+	if (!strcmp (clmodel->name, "progs/eyes.mdl") ) {
+		glTranslatef (paliashdr->scale_origin[0], paliashdr->scale_origin[1], paliashdr->scale_origin[2] - (22 + 8));
+	// double size of eyes, since they are really hard to see in gl
+		glScalef (paliashdr->scale[0]*2, paliashdr->scale[1]*2, paliashdr->scale[2]*2);
+	} else {
+		glTranslatef (paliashdr->scale_origin[0], paliashdr->scale_origin[1], paliashdr->scale_origin[2]);
+		glScalef (paliashdr->scale[0], paliashdr->scale[1], paliashdr->scale[2]);
+	}
+
+	anim = (int)(cl.time*10) & 3;
+    GL_Bind(paliashdr->gl_texturenum[currententity->skinnum][anim]);
+
+	// we can't dynamically colormap textures, so they are cached
+	// seperately for the players.  Heads are just uncolored.
+	if (currententity->scoreboard && !gl_nocolors.value)
+	{
+		i = currententity->scoreboard - cl.players;
+		if (!currententity->scoreboard->skin) {
+			Skin_Find(currententity->scoreboard);
+			R_TranslatePlayerSkin(i);
+		}
+		if (i >= 0 && i<MAX_CLIENTS)
+		    GL_Bind(playertextures + i);
+	}
+
+	if (gl_smoothmodels.value)
+		glShadeModel (GL_SMOOTH);
+	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+
+	if (gl_affinemodels.value)
+		glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
+
+	R_SetupAliasFrame (currententity->frame, paliashdr);
+
+	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+
+	glShadeModel (GL_FLAT);
+	if (gl_affinemodels.value)
+		glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
+
+	glPopMatrix ();
+
+	if (r_shadows.value)
+	{
+		glPushMatrix ();
+		R_RotateForEntity (e);
+		glDisable (GL_TEXTURE_2D);
+		glEnable (GL_BLEND);
+		glColor4f (0,0,0,0.5);
+		GL_DrawAliasShadow (paliashdr, lastposenum);
+		glEnable (GL_TEXTURE_2D);
+		glDisable (GL_BLEND);
+		glColor4f (1,1,1,1);
+		glPopMatrix ();
+	}
+
+}
+
+//==================================================================================
+
+/*
+=============
+R_DrawEntitiesOnList
+=============
+*/
+void R_DrawEntitiesOnList (void)
+{
+	int		i;
+
+	if (!r_drawentities.value)
+		return;
+
+	// draw sprites seperately, because of alpha blending
+	for (i=0 ; i<cl_numvisedicts ; i++)
+	{
+		currententity = &cl_visedicts[i];
+
+		switch (currententity->model->type)
+		{
+		case mod_alias:
+			R_DrawAliasModel (currententity);
+			break;
+
+		case mod_brush:
+			R_DrawBrushModel (currententity);
+			break;
+
+		default:
+			break;
+		}
+	}
+
+	for (i=0 ; i<cl_numvisedicts ; i++)
+	{
+		currententity = &cl_visedicts[i];
+
+		switch (currententity->model->type)
+		{
+		case mod_sprite:
+			R_DrawSpriteModel (currententity);
+			break;
+
+		default :
+			break;
+		}
+	}
+}
+
+/*
+=============
+R_DrawViewModel
+=============
+*/
+void R_DrawViewModel (void)
+{
+	float		ambient[4], diffuse[4];
+	int			j;
+	int			lnum;
+	vec3_t		dist;
+	float		add;
+	dlight_t	*dl;
+	int			ambientlight, shadelight;
+
+	if (!r_drawviewmodel.value || !Cam_DrawViewModel())
+		return;
+
+	if (envmap)
+		return;
+
+	if (!r_drawentities.value)
+		return;
+
+	if (cl.stats[STAT_ITEMS] & IT_INVISIBILITY)
+		return;
+
+	if (cl.stats[STAT_HEALTH] <= 0)
+		return;
+
+	currententity = &cl.viewent;
+	if (!currententity->model)
+		return;
+
+	j = R_LightPoint (currententity->origin);
+
+	if (j < 24)
+		j = 24;		// allways give some light on gun
+	ambientlight = j;
+	shadelight = j;
+
+// add dynamic lights		
+	for (lnum=0 ; lnum<MAX_DLIGHTS ; lnum++)
+	{
+		dl = &cl_dlights[lnum];
+		if (!dl->radius)
+			continue;
+		if (!dl->radius)
+			continue;
+		if (dl->die < cl.time)
+			continue;
+
+		VectorSubtract (currententity->origin, dl->origin, dist);
+		add = dl->radius - Length(dist);
+		if (add > 0)
+			ambientlight += add;
+	}
+
+	ambient[0] = ambient[1] = ambient[2] = ambient[3] = (float)ambientlight / 128;
+	diffuse[0] = diffuse[1] = diffuse[2] = diffuse[3] = (float)shadelight / 128;
+
+	// hack the depth range to prevent view model from poking into walls
+	glDepthRange (gldepthmin, gldepthmin + 0.3*(gldepthmax-gldepthmin));
+	R_DrawAliasModel (currententity);
+	glDepthRange (gldepthmin, gldepthmax);
+}
+
+
+/*
+============
+R_PolyBlend
+============
+*/
+void R_PolyBlend (void)
+{
+	if (!gl_polyblend.value)
+		return;
+	if (!v_blend[3])
+		return;
+
+//Con_Printf("R_PolyBlend(): %4.2f %4.2f %4.2f %4.2f\n",v_blend[0], v_blend[1],	v_blend[2],	v_blend[3]);
+
+ 	GL_DisableMultitexture();
+
+	glDisable (GL_ALPHA_TEST);
+	glEnable (GL_BLEND);
+	glDisable (GL_DEPTH_TEST);
+	glDisable (GL_TEXTURE_2D);
+
+    glLoadIdentity ();
+
+    glRotatef (-90,  1, 0, 0);	    // put Z going up
+    glRotatef (90,  0, 0, 1);	    // put Z going up
+
+	glColor4fv (v_blend);
+
+	glBegin (GL_QUADS);
+
+	glVertex3f (10, 100, 100);
+	glVertex3f (10, -100, 100);
+	glVertex3f (10, -100, -100);
+	glVertex3f (10, 100, -100);
+	glEnd ();
+
+	glDisable (GL_BLEND);
+	glEnable (GL_TEXTURE_2D);
+	glEnable (GL_ALPHA_TEST);
+}
+
+
+int SignbitsForPlane (mplane_t *out)
+{
+	int	bits, j;
+
+	// for fast box on planeside test
+
+	bits = 0;
+	for (j=0 ; j<3 ; j++)
+	{
+		if (out->normal[j] < 0)
+			bits |= 1<<j;
+	}
+	return bits;
+}
+
+
+void R_SetFrustum (void)
+{
+	int		i;
+
+	if (r_refdef.fov_x == 90) 
+	{
+		// front side is visible
+
+		VectorAdd (vpn, vright, frustum[0].normal);
+		VectorSubtract (vpn, vright, frustum[1].normal);
+
+		VectorAdd (vpn, vup, frustum[2].normal);
+		VectorSubtract (vpn, vup, frustum[3].normal);
+	}
+	else
+	{
+
+		// rotate VPN right by FOV_X/2 degrees
+		RotatePointAroundVector( frustum[0].normal, vup, vpn, -(90-r_refdef.fov_x / 2 ) );
+		// rotate VPN left by FOV_X/2 degrees
+		RotatePointAroundVector( frustum[1].normal, vup, vpn, 90-r_refdef.fov_x / 2 );
+		// rotate VPN up by FOV_X/2 degrees
+		RotatePointAroundVector( frustum[2].normal, vright, vpn, 90-r_refdef.fov_y / 2 );
+		// rotate VPN down by FOV_X/2 degrees
+		RotatePointAroundVector( frustum[3].normal, vright, vpn, -( 90 - r_refdef.fov_y / 2 ) );
+	}
+
+	for (i=0 ; i<4 ; i++)
+	{
+		frustum[i].type = PLANE_ANYZ;
+		frustum[i].dist = DotProduct (r_origin, frustum[i].normal);
+		frustum[i].signbits = SignbitsForPlane (&frustum[i]);
+	}
+}
+
+
+
+/*
+===============
+R_SetupFrame
+===============
+*/
+void R_SetupFrame (void)
+{
+// don't allow cheats in multiplayer
+	r_fullbright.value = 0;
+	r_lightmap.value = 0;
+	if (!atoi(Info_ValueForKey(cl.serverinfo, "watervis")))
+		r_wateralpha.value = 1;
+
+	R_AnimateLight ();
+
+	r_framecount++;
+
+// build the transformation matrix for the given view angles
+	VectorCopy (r_refdef.vieworg, r_origin);
+
+	AngleVectors (r_refdef.viewangles, vpn, vright, vup);
+
+// current viewleaf
+	r_oldviewleaf = r_viewleaf;
+	r_viewleaf = Mod_PointInLeaf (r_origin, cl.worldmodel);
+
+	V_SetContentsColor (r_viewleaf->contents);
+	V_CalcBlend ();
+
+	r_cache_thrash = false;
+
+	c_brush_polys = 0;
+	c_alias_polys = 0;
+
+}
+
+
+void MYgluPerspective( GLdouble fovy, GLdouble aspect,
+		     GLdouble zNear, GLdouble zFar )
+{
+   GLdouble xmin, xmax, ymin, ymax;
+
+   ymax = zNear * tan( fovy * M_PI / 360.0 );
+   ymin = -ymax;
+
+   xmin = ymin * aspect;
+   xmax = ymax * aspect;
+
+   glFrustum( xmin, xmax, ymin, ymax, zNear, zFar );
+}
+
+
+/*
+=============
+R_SetupGL
+=============
+*/
+void R_SetupGL (void)
+{
+	float	screenaspect;
+	extern	int glwidth, glheight;
+	int		x, x2, y2, y, w, h;
+
+	//
+	// set up viewpoint
+	//
+	glMatrixMode(GL_PROJECTION);
+    glLoadIdentity ();
+	x = r_refdef.vrect.x * glwidth/vid.width;
+	x2 = (r_refdef.vrect.x + r_refdef.vrect.width) * glwidth/vid.width;
+	y = (vid.height-r_refdef.vrect.y) * glheight/vid.height;
+	y2 = (vid.height - (r_refdef.vrect.y + r_refdef.vrect.height)) * glheight/vid.height;
+
+	// fudge around because of frac screen scale
+	if (x > 0)
+		x--;
+	if (x2 < glwidth)
+		x2++;
+	if (y2 < 0)
+		y2--;
+	if (y < glheight)
+		y++;
+
+	w = x2 - x;
+	h = y - y2;
+
+	if (envmap)
+	{
+		x = y2 = 0;
+		w = h = 256;
+	}
+
+	glViewport (glx + x, gly + y2, w, h);
+    screenaspect = (float)r_refdef.vrect.width/r_refdef.vrect.height;
+//	yfov = 2*atan((float)r_refdef.vrect.height/r_refdef.vrect.width)*180/M_PI;
+//	yfov = (2.0 * tan (scr_fov.value/360*M_PI)) / screenaspect;
+//	yfov = 2*atan((float)r_refdef.vrect.height/r_refdef.vrect.width)*(scr_fov.value*2)/M_PI;
+//    MYgluPerspective (yfov,  screenaspect,  4,  4096);
+    MYgluPerspective (r_refdef.fov_y,  screenaspect,  4,  4096);
+
+	if (mirror)
+	{
+		if (mirror_plane->normal[2])
+			glScalef (1, -1, 1);
+		else
+			glScalef (-1, 1, 1);
+		glCullFace(GL_BACK);
+	}
+	else
+		glCullFace(GL_FRONT);
+
+	glMatrixMode(GL_MODELVIEW);
+    glLoadIdentity ();
+
+    glRotatef (-90,  1, 0, 0);	    // put Z going up
+    glRotatef (90,  0, 0, 1);	    // put Z going up
+    glRotatef (-r_refdef.viewangles[2],  1, 0, 0);
+    glRotatef (-r_refdef.viewangles[0],  0, 1, 0);
+    glRotatef (-r_refdef.viewangles[1],  0, 0, 1);
+    glTranslatef (-r_refdef.vieworg[0],  -r_refdef.vieworg[1],  -r_refdef.vieworg[2]);
+
+	glGetFloatv (GL_MODELVIEW_MATRIX, r_world_matrix);
+
+	//
+	// set drawing parms
+	//
+	if (gl_cull.value)
+		glEnable(GL_CULL_FACE);
+	else
+		glDisable(GL_CULL_FACE);
+
+	glDisable(GL_BLEND);
+	glDisable(GL_ALPHA_TEST);
+	glEnable(GL_DEPTH_TEST);
+}
+
+/*
+================
+R_RenderScene
+
+r_refdef must be set before the first call
+================
+*/
+void R_RenderScene (void)
+{
+	R_SetupFrame ();
+
+	R_SetFrustum ();
+
+	R_SetupGL ();
+
+	R_MarkLeaves ();	// done here so we know if we're in water
+
+	R_DrawWorld ();		// adds static entities to the list
+
+	S_ExtraUpdate ();	// don't let sound get messed up if going slow
+
+	R_DrawEntitiesOnList ();
+
+	GL_DisableMultitexture();
+
+	R_RenderDlights ();
+
+	R_DrawParticles ();
+
+#ifdef GLTEST
+	Test_Draw ();
+#endif
+
+}
+
+
+/*
+=============
+R_Clear
+=============
+*/
+void R_Clear (void)
+{
+	if (r_mirroralpha.value != 1.0)
+	{
+		if (gl_clear.value)
+			glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+		else
+			glClear (GL_DEPTH_BUFFER_BIT);
+		gldepthmin = 0;
+		gldepthmax = 0.5;
+		glDepthFunc (GL_LEQUAL);
+	}
+	else if (gl_ztrick.value)
+	{
+		static int trickframe;
+
+		if (gl_clear.value)
+			glClear (GL_COLOR_BUFFER_BIT);
+
+		trickframe++;
+		if (trickframe & 1)
+		{
+			gldepthmin = 0;
+			gldepthmax = 0.49999;
+			glDepthFunc (GL_LEQUAL);
+		}
+		else
+		{
+			gldepthmin = 1;
+			gldepthmax = 0.5;
+			glDepthFunc (GL_GEQUAL);
+		}
+	}
+	else
+	{
+		if (gl_clear.value)
+			glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+		else
+			glClear (GL_DEPTH_BUFFER_BIT);
+		gldepthmin = 0;
+		gldepthmax = 1;
+		glDepthFunc (GL_LEQUAL);
+	}
+
+	glDepthRange (gldepthmin, gldepthmax);
+}
+
+#if 0 //!!! FIXME, Zoid, mirror is disabled for now
+/*
+=============
+R_Mirror
+=============
+*/
+void R_Mirror (void)
+{
+	float		d;
+	msurface_t	*s;
+	entity_t	*ent;
+
+	if (!mirror)
+		return;
+
+	memcpy (r_base_world_matrix, r_world_matrix, sizeof(r_base_world_matrix));
+
+	d = DotProduct (r_refdef.vieworg, mirror_plane->normal) - mirror_plane->dist;
+	VectorMA (r_refdef.vieworg, -2*d, mirror_plane->normal, r_refdef.vieworg);
+
+	d = DotProduct (vpn, mirror_plane->normal);
+	VectorMA (vpn, -2*d, mirror_plane->normal, vpn);
+
+	r_refdef.viewangles[0] = -asin (vpn[2])/M_PI*180;
+	r_refdef.viewangles[1] = atan2 (vpn[1], vpn[0])/M_PI*180;
+	r_refdef.viewangles[2] = -r_refdef.viewangles[2];
+
+	ent = &cl_entities[cl.viewentity];
+	if (cl_numvisedicts < MAX_VISEDICTS)
+	{
+		cl_visedicts[cl_numvisedicts] = ent;
+		cl_numvisedicts++;
+	}
+
+	gldepthmin = 0.5;
+	gldepthmax = 1;
+	glDepthRange (gldepthmin, gldepthmax);
+	glDepthFunc (GL_LEQUAL);
+
+	R_RenderScene ();
+	R_DrawWaterSurfaces ();
+
+
+	gldepthmin = 0;
+	gldepthmax = 0.5;
+	glDepthRange (gldepthmin, gldepthmax);
+	glDepthFunc (GL_LEQUAL);
+
+	// blend on top
+	glEnable (GL_BLEND);
+	glMatrixMode(GL_PROJECTION);
+	if (mirror_plane->normal[2])
+		glScalef (1,-1,1);
+	else
+		glScalef (-1,1,1);
+	glCullFace(GL_FRONT);
+	glMatrixMode(GL_MODELVIEW);
+
+	glLoadMatrixf (r_base_world_matrix);
+
+	glColor4f (1,1,1,r_mirroralpha.value);
+	s = cl.worldmodel->textures[mirrortexturenum]->texturechain;
+	for ( ; s ; s=s->texturechain)
+		R_RenderBrushPoly (s);
+	cl.worldmodel->textures[mirrortexturenum]->texturechain = NULL;
+	glDisable (GL_BLEND);
+	glColor4f (1,1,1,1);
+}
+#endif
+
+/*
+================
+R_RenderView
+
+r_refdef must be set before the first call
+================
+*/
+void R_RenderView (void)
+{
+	double	time1 = 0, time2;
+
+	if (r_norefresh.value)
+		return;
+
+	if (!r_worldentity.model || !cl.worldmodel)
+		Sys_Error ("R_RenderView: NULL worldmodel");
+
+	if (r_speeds.value)
+	{
+		glFinish ();
+		time1 = Sys_DoubleTime ();
+		c_brush_polys = 0;
+		c_alias_polys = 0;
+	}
+
+	mirror = false;
+
+	if (gl_finish.value)
+		glFinish ();
+
+	R_Clear ();
+
+	// render normal view
+	R_RenderScene ();
+	R_DrawViewModel ();
+	R_DrawWaterSurfaces ();
+
+	// render mirror view
+//	R_Mirror ();
+
+	R_PolyBlend ();
+
+	if (r_speeds.value)
+	{
+//		glFinish ();
+		time2 = Sys_DoubleTime ();
+		Con_Printf ("%3i ms  %4i wpoly %4i epoly\n", (int)((time2-time1)*1000), c_brush_polys, c_alias_polys); 
+	}
+}
--- /dev/null
+++ b/QW/client/gl_rmisc.c
@@ -1,0 +1,473 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// r_misc.c
+
+#include "quakedef.h"
+
+extern void R_InitBubble();
+
+/*
+==================
+R_InitTextures
+==================
+*/
+void	R_InitTextures (void)
+{
+	int		x,y, m;
+	byte	*dest;
+
+// create a simple checkerboard texture for the default
+	r_notexture_mip = Hunk_AllocName (sizeof(texture_t) + 16*16+8*8+4*4+2*2, "notexture");
+	
+	r_notexture_mip->width = r_notexture_mip->height = 16;
+	r_notexture_mip->offsets[0] = sizeof(texture_t);
+	r_notexture_mip->offsets[1] = r_notexture_mip->offsets[0] + 16*16;
+	r_notexture_mip->offsets[2] = r_notexture_mip->offsets[1] + 8*8;
+	r_notexture_mip->offsets[3] = r_notexture_mip->offsets[2] + 4*4;
+	
+	for (m=0 ; m<4 ; m++)
+	{
+		dest = (byte *)r_notexture_mip + r_notexture_mip->offsets[m];
+		for (y=0 ; y< (16>>m) ; y++)
+			for (x=0 ; x< (16>>m) ; x++)
+			{
+				if (  (y< (8>>m) ) ^ (x< (8>>m) ) )
+					*dest++ = 0;
+				else
+					*dest++ = 0xff;
+			}
+	}	
+}
+
+byte	dottexture[8][8] =
+{
+	{0,1,1,0,0,0,0,0},
+	{1,1,1,1,0,0,0,0},
+	{1,1,1,1,0,0,0,0},
+	{0,1,1,0,0,0,0,0},
+	{0,0,0,0,0,0,0,0},
+	{0,0,0,0,0,0,0,0},
+	{0,0,0,0,0,0,0,0},
+	{0,0,0,0,0,0,0,0},
+};
+void R_InitParticleTexture (void)
+{
+	int		x,y;
+	byte	data[8][8][4];
+
+	//
+	// particle texture
+	//
+	particletexture = texture_extension_number++;
+    GL_Bind(particletexture);
+
+	for (x=0 ; x<8 ; x++)
+	{
+		for (y=0 ; y<8 ; y++)
+		{
+			data[y][x][0] = 255;
+			data[y][x][1] = 255;
+			data[y][x][2] = 255;
+			data[y][x][3] = dottexture[x][y]*255;
+		}
+	}
+	glTexImage2D (GL_TEXTURE_2D, 0, gl_alpha_format, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
+
+	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+
+	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+}
+
+/*
+===============
+R_Envmap_f
+
+Grab six views for environment mapping tests
+===============
+*/
+void R_Envmap_f (void)
+{
+	byte	buffer[256*256*4];
+
+	glDrawBuffer  (GL_FRONT);
+	glReadBuffer  (GL_FRONT);
+	envmap = true;
+
+	r_refdef.vrect.x = 0;
+	r_refdef.vrect.y = 0;
+	r_refdef.vrect.width = 256;
+	r_refdef.vrect.height = 256;
+
+	r_refdef.viewangles[0] = 0;
+	r_refdef.viewangles[1] = 0;
+	r_refdef.viewangles[2] = 0;
+	GL_BeginRendering (&glx, &gly, &glwidth, &glheight);
+	R_RenderView ();
+	glReadPixels (0, 0, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
+	COM_WriteFile ("env0.rgb", buffer, sizeof(buffer));		
+
+	r_refdef.viewangles[1] = 90;
+	GL_BeginRendering (&glx, &gly, &glwidth, &glheight);
+	R_RenderView ();
+	glReadPixels (0, 0, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
+	COM_WriteFile ("env1.rgb", buffer, sizeof(buffer));		
+
+	r_refdef.viewangles[1] = 180;
+	GL_BeginRendering (&glx, &gly, &glwidth, &glheight);
+	R_RenderView ();
+	glReadPixels (0, 0, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
+	COM_WriteFile ("env2.rgb", buffer, sizeof(buffer));		
+
+	r_refdef.viewangles[1] = 270;
+	GL_BeginRendering (&glx, &gly, &glwidth, &glheight);
+	R_RenderView ();
+	glReadPixels (0, 0, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
+	COM_WriteFile ("env3.rgb", buffer, sizeof(buffer));		
+
+	r_refdef.viewangles[0] = -90;
+	r_refdef.viewangles[1] = 0;
+	GL_BeginRendering (&glx, &gly, &glwidth, &glheight);
+	R_RenderView ();
+	glReadPixels (0, 0, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
+	COM_WriteFile ("env4.rgb", buffer, sizeof(buffer));		
+
+	r_refdef.viewangles[0] = 90;
+	r_refdef.viewangles[1] = 0;
+	GL_BeginRendering (&glx, &gly, &glwidth, &glheight);
+	R_RenderView ();
+	glReadPixels (0, 0, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
+	COM_WriteFile ("env5.rgb", buffer, sizeof(buffer));		
+
+	envmap = false;
+	glDrawBuffer  (GL_BACK);
+	glReadBuffer  (GL_BACK);
+	GL_EndRendering ();
+}
+
+/*
+===============
+R_Init
+===============
+*/
+void R_Init (void)
+{	
+	Cmd_AddCommand ("timerefresh", R_TimeRefresh_f);	
+	Cmd_AddCommand ("envmap", R_Envmap_f);	
+	Cmd_AddCommand ("pointfile", R_ReadPointFile_f);	
+
+	Cvar_RegisterVariable (&r_norefresh);
+	Cvar_RegisterVariable (&r_lightmap);
+	Cvar_RegisterVariable (&r_fullbright);
+	Cvar_RegisterVariable (&r_drawentities);
+	Cvar_RegisterVariable (&r_drawviewmodel);
+	Cvar_RegisterVariable (&r_shadows);
+	Cvar_RegisterVariable (&r_mirroralpha);
+	Cvar_RegisterVariable (&r_wateralpha);
+	Cvar_RegisterVariable (&r_dynamic);
+	Cvar_RegisterVariable (&r_novis);
+	Cvar_RegisterVariable (&r_speeds);
+	Cvar_RegisterVariable (&r_netgraph);
+
+	Cvar_RegisterVariable (&gl_clear);
+	Cvar_RegisterVariable (&gl_texsort);
+ 
+ 	if (gl_mtexable)
+		Cvar_SetValue ("gl_texsort", 0.0);
+
+	Cvar_RegisterVariable (&gl_cull);
+	Cvar_RegisterVariable (&gl_smoothmodels);
+	Cvar_RegisterVariable (&gl_affinemodels);
+	Cvar_RegisterVariable (&gl_polyblend);
+	Cvar_RegisterVariable (&gl_flashblend);
+	Cvar_RegisterVariable (&gl_playermip);
+	Cvar_RegisterVariable (&gl_nocolors);
+	Cvar_RegisterVariable (&gl_finish);
+
+	Cvar_RegisterVariable (&gl_keeptjunctions);
+	Cvar_RegisterVariable (&gl_reporttjunctions);
+
+	R_InitBubble();
+	
+	R_InitParticles ();
+	R_InitParticleTexture ();
+
+#ifdef GLTEST
+	Test_Init ();
+#endif
+
+	netgraphtexture = texture_extension_number;
+	texture_extension_number++;
+
+	playertextures = texture_extension_number;
+	texture_extension_number += MAX_CLIENTS;
+}
+
+/*
+===============
+R_TranslatePlayerSkin
+
+Translates a skin texture by the per-player color lookup
+===============
+*/
+void R_TranslatePlayerSkin (int playernum)
+{
+	int		top, bottom;
+	byte	translate[256];
+	unsigned	translate32[256];
+	int		i, j;
+	byte	*original;
+	unsigned	pixels[512*256], *out;
+	unsigned	scaled_width, scaled_height;
+	int			inwidth, inheight;
+	int			tinwidth, tinheight;
+	byte		*inrow;
+	unsigned	frac, fracstep;
+	player_info_t *player;
+	extern	byte		player_8bit_texels[320*200];
+	char s[512];
+
+	GL_DisableMultitexture();
+
+	player = &cl.players[playernum];
+	if (!player->name[0])
+		return;
+
+	strcpy(s, Info_ValueForKey(player->userinfo, "skin"));
+	COM_StripExtension(s, s);
+	if (player->skin && !stricmp(s, player->skin->name))
+		player->skin = NULL;
+
+	if (player->_topcolor != player->topcolor ||
+		player->_bottomcolor != player->bottomcolor || !player->skin) {
+		player->_topcolor = player->topcolor;
+		player->_bottomcolor = player->bottomcolor;
+
+		top = player->topcolor;
+		bottom = player->bottomcolor;
+		top = (top < 0) ? 0 : ((top > 13) ? 13 : top);
+		bottom = (bottom < 0) ? 0 : ((bottom > 13) ? 13 : bottom);
+		top *= 16;
+		bottom *= 16;
+
+		for (i=0 ; i<256 ; i++)
+			translate[i] = i;
+
+		for (i=0 ; i<16 ; i++)
+		{
+			if (top < 128)	// the artists made some backwards ranges.  sigh.
+				translate[TOP_RANGE+i] = top+i;
+			else
+				translate[TOP_RANGE+i] = top+15-i;
+					
+			if (bottom < 128)
+				translate[BOTTOM_RANGE+i] = bottom+i;
+			else
+				translate[BOTTOM_RANGE+i] = bottom+15-i;
+		}
+
+		//
+		// locate the original skin pixels
+		//
+		// real model width
+		tinwidth = 296;
+		tinheight = 194;
+
+		if (!player->skin)
+			Skin_Find(player);
+		if ((original = Skin_Cache(player->skin)) != NULL) {
+			//skin data width
+			inwidth = 320;
+			inheight = 200;
+		} else {
+			original = player_8bit_texels;
+			inwidth = 296;
+			inheight = 194;
+		}
+
+
+		// because this happens during gameplay, do it fast
+		// instead of sending it through gl_upload 8
+		GL_Bind(playertextures + playernum);
+
+	#if 0
+		s = 320*200;
+		byte	translated[320*200];
+
+		for (i=0 ; i<s ; i+=4)
+		{
+			translated[i] = translate[original[i]];
+			translated[i+1] = translate[original[i+1]];
+			translated[i+2] = translate[original[i+2]];
+			translated[i+3] = translate[original[i+3]];
+		}
+
+
+		// don't mipmap these, because it takes too long
+		GL_Upload8 (translated, paliashdr->skinwidth, paliashdr->skinheight, 
+			false, false, true);
+	#endif
+
+		scaled_width = gl_max_size.value < 512 ? gl_max_size.value : 512;
+		scaled_height = gl_max_size.value < 256 ? gl_max_size.value : 256;
+		// allow users to crunch sizes down even more if they want
+		scaled_width >>= (int)gl_playermip.value;
+		scaled_height >>= (int)gl_playermip.value;
+
+		if (VID_Is8bit()) { // 8bit texture upload
+			byte *out2;
+
+			out2 = (byte *)pixels;
+			memset(pixels, 0, sizeof(pixels));
+			fracstep = tinwidth*0x10000/scaled_width;
+			for (i=0 ; i<scaled_height ; i++, out2 += scaled_width)
+			{
+				inrow = original + inwidth*(i*tinheight/scaled_height);
+				frac = fracstep >> 1;
+				for (j=0 ; j<scaled_width ; j+=4)
+				{
+					out2[j] = translate[inrow[frac>>16]];
+					frac += fracstep;
+					out2[j+1] = translate[inrow[frac>>16]];
+					frac += fracstep;
+					out2[j+2] = translate[inrow[frac>>16]];
+					frac += fracstep;
+					out2[j+3] = translate[inrow[frac>>16]];
+					frac += fracstep;
+				}
+			}
+
+			GL_Upload8_EXT ((byte *)pixels, scaled_width, scaled_height, false, false);
+			return;
+		}
+
+		for (i=0 ; i<256 ; i++)
+			translate32[i] = d_8to24table[translate[i]];
+
+		out = pixels;
+		memset(pixels, 0, sizeof(pixels));
+		fracstep = tinwidth*0x10000/scaled_width;
+		for (i=0 ; i<scaled_height ; i++, out += scaled_width)
+		{
+			inrow = original + inwidth*(i*tinheight/scaled_height);
+			frac = fracstep >> 1;
+			for (j=0 ; j<scaled_width ; j+=4)
+			{
+				out[j] = translate32[inrow[frac>>16]];
+				frac += fracstep;
+				out[j+1] = translate32[inrow[frac>>16]];
+				frac += fracstep;
+				out[j+2] = translate32[inrow[frac>>16]];
+				frac += fracstep;
+				out[j+3] = translate32[inrow[frac>>16]];
+				frac += fracstep;
+			}
+		}
+
+		glTexImage2D (GL_TEXTURE_2D, 0, gl_solid_format, 
+			scaled_width, scaled_height, 0, GL_RGBA, 
+			GL_UNSIGNED_BYTE, pixels);
+
+		glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+	}
+}
+
+/*
+===============
+R_NewMap
+===============
+*/
+void R_NewMap (void)
+{
+	int		i;
+	
+	for (i=0 ; i<256 ; i++)
+		d_lightstylevalue[i] = 264;		// normal light value
+
+	memset (&r_worldentity, 0, sizeof(r_worldentity));
+	r_worldentity.model = cl.worldmodel;
+
+// clear out efrags in case the level hasn't been reloaded
+// FIXME: is this one short?
+	for (i=0 ; i<cl.worldmodel->numleafs ; i++)
+		cl.worldmodel->leafs[i].efrags = NULL;
+		 	
+	r_viewleaf = NULL;
+	R_ClearParticles ();
+
+	GL_BuildLightmaps ();
+
+	// identify sky texture
+	skytexturenum = -1;
+	mirrortexturenum = -1;
+	for (i=0 ; i<cl.worldmodel->numtextures ; i++)
+	{
+		if (!cl.worldmodel->textures[i])
+			continue;
+		if (!Q_strncmp(cl.worldmodel->textures[i]->name,"sky",3) )
+			skytexturenum = i;
+		if (!Q_strncmp(cl.worldmodel->textures[i]->name,"window02_1",10) )
+			mirrortexturenum = i;
+ 		cl.worldmodel->textures[i]->texturechain = NULL;
+	}
+#ifdef QUAKE2
+	R_LoadSkys ();
+#endif
+}
+
+
+/*
+====================
+R_TimeRefresh_f
+
+For program optimization
+====================
+*/
+void R_TimeRefresh_f (void)
+{
+	int			i;
+	float		start, stop, time;
+
+	glDrawBuffer  (GL_FRONT);
+	glFinish ();
+
+	start = Sys_DoubleTime ();
+	for (i=0 ; i<128 ; i++)
+	{
+		r_refdef.viewangles[1] = i/128.0*360.0;
+		R_RenderView ();
+	}
+
+	glFinish ();
+	stop = Sys_DoubleTime ();
+	time = stop-start;
+	Con_Printf ("%f seconds (%f fps)\n", time, 128/time);
+
+	glDrawBuffer  (GL_BACK);
+	GL_EndRendering ();
+}
+
+void D_FlushCaches (void)
+{
+}
+
+
--- /dev/null
+++ b/QW/client/gl_rsurf.c
@@ -1,0 +1,1697 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// r_surf.c: surface-related refresh code
+
+#include "quakedef.h"
+
+int			skytexturenum;
+
+#ifndef GL_RGBA4
+#define	GL_RGBA4	0
+#endif
+
+
+int		lightmap_bytes;		// 1, 2, or 4
+
+int		lightmap_textures;
+
+unsigned		blocklights[18*18];
+
+#define	BLOCK_WIDTH		128
+#define	BLOCK_HEIGHT	128
+
+#define	MAX_LIGHTMAPS	64
+int			active_lightmaps;
+
+typedef struct glRect_s {
+	unsigned char l,t,w,h;
+} glRect_t;
+
+glpoly_t	*lightmap_polys[MAX_LIGHTMAPS];
+qboolean	lightmap_modified[MAX_LIGHTMAPS];
+glRect_t	lightmap_rectchange[MAX_LIGHTMAPS];
+
+int			allocated[MAX_LIGHTMAPS][BLOCK_WIDTH];
+
+// the lightmap texture data needs to be kept in
+// main memory so texsubimage can update properly
+byte		lightmaps[4*MAX_LIGHTMAPS*BLOCK_WIDTH*BLOCK_HEIGHT];
+
+// For gl_texsort 0
+msurface_t  *skychain = NULL;
+msurface_t  *waterchain = NULL;
+
+void R_RenderDynamicLightmaps (msurface_t *fa);
+
+/*
+===============
+R_AddDynamicLights
+===============
+*/
+void R_AddDynamicLights (msurface_t *surf)
+{
+	int			lnum;
+	int			sd, td;
+	float		dist, rad, minlight;
+	vec3_t		impact, local;
+	int			s, t;
+	int			i;
+	int			smax, tmax;
+	mtexinfo_t	*tex;
+
+	smax = (surf->extents[0]>>4)+1;
+	tmax = (surf->extents[1]>>4)+1;
+	tex = surf->texinfo;
+
+	for (lnum=0 ; lnum<MAX_DLIGHTS ; lnum++)
+	{
+		if ( !(surf->dlightbits & (1<<lnum) ) )
+			continue;		// not lit by this light
+
+		rad = cl_dlights[lnum].radius;
+		dist = DotProduct (cl_dlights[lnum].origin, surf->plane->normal) -
+				surf->plane->dist;
+		rad -= fabs(dist);
+		minlight = cl_dlights[lnum].minlight;
+		if (rad < minlight)
+			continue;
+		minlight = rad - minlight;
+
+		for (i=0 ; i<3 ; i++)
+		{
+			impact[i] = cl_dlights[lnum].origin[i] -
+					surf->plane->normal[i]*dist;
+		}
+
+		local[0] = DotProduct (impact, tex->vecs[0]) + tex->vecs[0][3];
+		local[1] = DotProduct (impact, tex->vecs[1]) + tex->vecs[1][3];
+
+		local[0] -= surf->texturemins[0];
+		local[1] -= surf->texturemins[1];
+		
+		for (t = 0 ; t<tmax ; t++)
+		{
+			td = local[1] - t*16;
+			if (td < 0)
+				td = -td;
+			for (s=0 ; s<smax ; s++)
+			{
+				sd = local[0] - s*16;
+				if (sd < 0)
+					sd = -sd;
+				if (sd > td)
+					dist = sd + (td>>1);
+				else
+					dist = td + (sd>>1);
+				if (dist < minlight)
+					blocklights[t*smax + s] += (rad - dist)*256;
+			}
+		}
+	}
+}
+
+
+/*
+===============
+R_BuildLightMap
+
+Combine and scale multiple lightmaps into the 8.8 format in blocklights
+===============
+*/
+void R_BuildLightMap (msurface_t *surf, byte *dest, int stride)
+{
+	int			smax, tmax;
+	int			t;
+	int			i, j, size;
+	byte		*lightmap;
+	unsigned	scale;
+	int			maps;
+	unsigned	*bl;
+
+	surf->cached_dlight = (surf->dlightframe == r_framecount);
+
+	smax = (surf->extents[0]>>4)+1;
+	tmax = (surf->extents[1]>>4)+1;
+	size = smax*tmax;
+	lightmap = surf->samples;
+
+// set to full bright if no light data
+	if (/* r_fullbright.value || */ !cl.worldmodel->lightdata)
+	{
+		for (i=0 ; i<size ; i++)
+			blocklights[i] = 255*256;
+		goto store;
+	}
+
+// clear to no light
+	for (i=0 ; i<size ; i++)
+		blocklights[i] = 0;
+
+// add all the lightmaps
+	if (lightmap)
+		for (maps = 0 ; maps < MAXLIGHTMAPS && surf->styles[maps] != 255 ;
+			 maps++)
+		{
+			scale = d_lightstylevalue[surf->styles[maps]];
+			surf->cached_light[maps] = scale;	// 8.8 fraction
+			for (i=0 ; i<size ; i++)
+				blocklights[i] += lightmap[i] * scale;
+			lightmap += size;	// skip to next lightmap
+		}
+
+// add all the dynamic lights
+	if (surf->dlightframe == r_framecount)
+		R_AddDynamicLights (surf);
+
+// bound, invert, and shift
+store:
+	switch (gl_lightmap_format)
+	{
+	case GL_RGBA:
+		stride -= (smax<<2);
+		bl = blocklights;
+		for (i=0 ; i<tmax ; i++, dest += stride)
+		{
+			for (j=0 ; j<smax ; j++)
+			{
+				t = *bl++;
+				t >>= 7;
+				if (t > 255)
+					t = 255;
+				dest[3] = 255-t;
+				dest += 4;
+			}
+		}
+		break;
+	case GL_ALPHA:
+	case GL_LUMINANCE:
+	case GL_INTENSITY:
+		bl = blocklights;
+		for (i=0 ; i<tmax ; i++, dest += stride)
+		{
+			for (j=0 ; j<smax ; j++)
+			{
+				t = *bl++;
+				t >>= 7;
+				if (t > 255)
+					t = 255;
+				dest[j] = 255-t;
+			}
+		}
+		break;
+	default:
+		Sys_Error ("Bad lightmap format");
+	}
+}
+
+
+/*
+===============
+R_TextureAnimation
+
+Returns the proper texture for a given time and base texture
+===============
+*/
+texture_t *R_TextureAnimation (texture_t *base)
+{
+	int		reletive;
+	int		count;
+
+	if (currententity->frame)
+	{
+		if (base->alternate_anims)
+			base = base->alternate_anims;
+	}
+	
+	if (!base->anim_total)
+		return base;
+
+	reletive = (int)(cl.time*10) % base->anim_total;
+
+	count = 0;	
+	while (base->anim_min > reletive || base->anim_max <= reletive)
+	{
+		base = base->anim_next;
+		if (!base)
+			Sys_Error ("R_TextureAnimation: broken cycle");
+		if (++count > 100)
+			Sys_Error ("R_TextureAnimation: infinite cycle");
+	}
+
+	return base;
+}
+
+
+/*
+=============================================================
+
+	BRUSH MODELS
+
+=============================================================
+*/
+
+
+extern	int		solidskytexture;
+extern	int		alphaskytexture;
+extern	float	speedscale;		// for top sky and bottom sky
+
+void DrawGLWaterPoly (glpoly_t *p);
+void DrawGLWaterPolyLightmap (glpoly_t *p);
+
+#ifdef _WIN32
+lpMTexFUNC qglMTexCoord2fSGIS = NULL;
+lpSelTexFUNC qglSelectTextureSGIS = NULL;
+#endif
+
+qboolean mtexenabled = false;
+
+void GL_SelectTexture (GLenum target);
+
+void GL_DisableMultitexture(void) 
+{
+	if (mtexenabled) {
+		glDisable(GL_TEXTURE_2D);
+		GL_SelectTexture(TEXTURE0_SGIS);
+		mtexenabled = false;
+	}
+}
+
+void GL_EnableMultitexture(void) 
+{
+	if (gl_mtexable) {
+		GL_SelectTexture(TEXTURE1_SGIS);
+		glEnable(GL_TEXTURE_2D);
+		mtexenabled = true;
+	}
+}
+
+#ifndef _WIN32
+/*
+================
+R_DrawSequentialPoly
+
+Systems that have fast state and texture changes can
+just do everything as it passes with no need to sort
+================
+*/
+void R_DrawSequentialPoly (msurface_t *s)
+{
+	glpoly_t	*p;
+	float		*v;
+	int			i;
+	texture_t	*t;
+
+	//
+	// normal lightmaped poly
+	//
+//	if ((!(s->flags & (SURF_DRAWSKY|SURF_DRAWTURB)))
+//		&& ((r_viewleaf->contents!=CONTENTS_EMPTY && (s->flags & SURF_UNDERWATER)) ||
+//		(r_viewleaf->contents==CONTENTS_EMPTY && !(s->flags & SURF_UNDERWATER))))
+	if (0)
+	{
+		p = s->polys;
+
+		t = R_TextureAnimation (s->texinfo->texture);
+		GL_Bind (t->gl_texturenum);
+		glBegin (GL_POLYGON);
+		v = p->verts[0];
+		for (i=0 ; i<p->numverts ; i++, v+= VERTEXSIZE)
+		{
+			glTexCoord2f (v[3], v[4]);
+			glVertex3fv (v);
+		}
+		glEnd ();
+
+		GL_Bind (lightmap_textures + s->lightmaptexturenum);
+		glEnable (GL_BLEND);
+		glBegin (GL_POLYGON);
+		v = p->verts[0];
+		for (i=0 ; i<p->numverts ; i++, v+= VERTEXSIZE)
+		{
+			glTexCoord2f (v[5], v[6]);
+			glVertex3fv (v);
+		}
+		glEnd ();
+
+		glDisable (GL_BLEND);
+
+		return;
+	}
+
+	//
+	// subdivided water surface warp
+	//
+	if (s->flags & SURF_DRAWTURB)
+	{
+		GL_Bind (s->texinfo->texture->gl_texturenum);
+		EmitWaterPolys (s);
+		return;
+	}
+
+	//
+	// subdivided sky warp
+	//
+	if (s->flags & SURF_DRAWSKY)
+	{
+		GL_Bind (solidskytexture);
+		speedscale = realtime*8;
+		speedscale -= (int)speedscale;
+
+		EmitSkyPolys (s);
+
+		glEnable (GL_BLEND);
+		glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+		GL_Bind (alphaskytexture);
+		speedscale = realtime*16;
+		speedscale -= (int)speedscale;
+		EmitSkyPolys (s);
+		if (gl_lightmap_format == GL_LUMINANCE)
+			glBlendFunc (GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
+
+		glDisable (GL_BLEND);
+	}
+
+	//
+	// underwater warped with lightmap
+	//
+	p = s->polys;
+
+	t = R_TextureAnimation (s->texinfo->texture);
+	GL_Bind (t->gl_texturenum);
+	DrawGLWaterPoly (p);
+
+	GL_Bind (lightmap_textures + s->lightmaptexturenum);
+	glEnable (GL_BLEND);
+	DrawGLWaterPolyLightmap (p);
+	glDisable (GL_BLEND);
+}
+#else
+/*
+================
+R_DrawSequentialPoly
+
+Systems that have fast state and texture changes can
+just do everything as it passes with no need to sort
+================
+*/
+void R_DrawSequentialPoly (msurface_t *s)
+{
+	glpoly_t	*p;
+	float		*v;
+	int			i;
+	texture_t	*t;
+	vec3_t		nv, dir;
+	float		ss, ss2, length;
+	float		s1, t1;
+	glRect_t	*theRect;
+
+	//
+	// normal lightmaped poly
+	//
+
+	if (! (s->flags & (SURF_DRAWSKY|SURF_DRAWTURB|SURF_UNDERWATER) ) )
+	{
+		R_RenderDynamicLightmaps (s);
+		if (gl_mtexable) {
+			p = s->polys;
+
+			t = R_TextureAnimation (s->texinfo->texture);
+			// Binds world to texture env 0
+			GL_SelectTexture(TEXTURE0_SGIS);
+			GL_Bind (t->gl_texturenum);
+			glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+			// Binds lightmap to texenv 1
+			GL_EnableMultitexture(); // Same as SelectTexture (TEXTURE1)
+			GL_Bind (lightmap_textures + s->lightmaptexturenum);
+			i = s->lightmaptexturenum;
+			if (lightmap_modified[i])
+			{
+				lightmap_modified[i] = false;
+				theRect = &lightmap_rectchange[i];
+				glTexSubImage2D(GL_TEXTURE_2D, 0, 0, theRect->t, 
+					BLOCK_WIDTH, theRect->h, gl_lightmap_format, GL_UNSIGNED_BYTE,
+					lightmaps+(i* BLOCK_HEIGHT + theRect->t) *BLOCK_WIDTH*lightmap_bytes);
+				theRect->l = BLOCK_WIDTH;
+				theRect->t = BLOCK_HEIGHT;
+				theRect->h = 0;
+				theRect->w = 0;
+			}
+			glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND);
+			glBegin(GL_POLYGON);
+			v = p->verts[0];
+			for (i=0 ; i<p->numverts ; i++, v+= VERTEXSIZE)
+			{
+				qglMTexCoord2fSGIS (TEXTURE0_SGIS, v[3], v[4]);
+				qglMTexCoord2fSGIS (TEXTURE1_SGIS, v[5], v[6]);
+				glVertex3fv (v);
+			}
+			glEnd ();
+			return;
+		} else {
+			p = s->polys;
+
+			t = R_TextureAnimation (s->texinfo->texture);
+			GL_Bind (t->gl_texturenum);
+			glBegin (GL_POLYGON);
+			v = p->verts[0];
+			for (i=0 ; i<p->numverts ; i++, v+= VERTEXSIZE)
+			{
+				glTexCoord2f (v[3], v[4]);
+				glVertex3fv (v);
+			}
+			glEnd ();
+
+			GL_Bind (lightmap_textures + s->lightmaptexturenum);
+			glEnable (GL_BLEND);
+			glBegin (GL_POLYGON);
+			v = p->verts[0];
+			for (i=0 ; i<p->numverts ; i++, v+= VERTEXSIZE)
+			{
+				glTexCoord2f (v[5], v[6]);
+				glVertex3fv (v);
+			}
+			glEnd ();
+
+			glDisable (GL_BLEND);
+		}
+
+		return;
+	}
+
+	//
+	// subdivided water surface warp
+	//
+
+	if (s->flags & SURF_DRAWTURB)
+	{
+		GL_DisableMultitexture();
+		GL_Bind (s->texinfo->texture->gl_texturenum);
+		EmitWaterPolys (s);
+		return;
+	}
+
+	//
+	// subdivided sky warp
+	//
+	if (s->flags & SURF_DRAWSKY)
+	{
+		GL_DisableMultitexture();
+		GL_Bind (solidskytexture);
+		speedscale = realtime*8;
+		speedscale -= (int)speedscale & ~127;
+
+		EmitSkyPolys (s);
+
+		glEnable (GL_BLEND);
+		GL_Bind (alphaskytexture);
+		speedscale = realtime*16;
+		speedscale -= (int)speedscale & ~127;
+		EmitSkyPolys (s);
+
+		glDisable (GL_BLEND);
+		return;
+	}
+
+	//
+	// underwater warped with lightmap
+	//
+	R_RenderDynamicLightmaps (s);
+	if (gl_mtexable) {
+		p = s->polys;
+
+		t = R_TextureAnimation (s->texinfo->texture);
+		GL_SelectTexture(TEXTURE0_SGIS);
+		GL_Bind (t->gl_texturenum);
+		glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+		GL_EnableMultitexture();
+		GL_Bind (lightmap_textures + s->lightmaptexturenum);
+		i = s->lightmaptexturenum;
+		if (lightmap_modified[i])
+		{
+			lightmap_modified[i] = false;
+			theRect = &lightmap_rectchange[i];
+			glTexSubImage2D(GL_TEXTURE_2D, 0, 0, theRect->t, 
+				BLOCK_WIDTH, theRect->h, gl_lightmap_format, GL_UNSIGNED_BYTE,
+				lightmaps+(i* BLOCK_HEIGHT + theRect->t) *BLOCK_WIDTH*lightmap_bytes);
+			theRect->l = BLOCK_WIDTH;
+			theRect->t = BLOCK_HEIGHT;
+			theRect->h = 0;
+			theRect->w = 0;
+		}
+		glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND);
+		glBegin (GL_TRIANGLE_FAN);
+		v = p->verts[0];
+		for (i=0 ; i<p->numverts ; i++, v+= VERTEXSIZE)
+		{
+			qglMTexCoord2fSGIS (TEXTURE0_SGIS, v[3], v[4]);
+			qglMTexCoord2fSGIS (TEXTURE1_SGIS, v[5], v[6]);
+
+			nv[0] = v[0] + 8*sin(v[1]*0.05+realtime)*sin(v[2]*0.05+realtime);
+			nv[1] = v[1] + 8*sin(v[0]*0.05+realtime)*sin(v[2]*0.05+realtime);
+			nv[2] = v[2];
+
+			glVertex3fv (nv);
+		}
+		glEnd ();
+
+	} else {
+		p = s->polys;
+
+		t = R_TextureAnimation (s->texinfo->texture);
+		GL_Bind (t->gl_texturenum);
+		DrawGLWaterPoly (p);
+
+		GL_Bind (lightmap_textures + s->lightmaptexturenum);
+		glEnable (GL_BLEND);
+		DrawGLWaterPolyLightmap (p);
+		glDisable (GL_BLEND);
+	}
+}
+#endif
+
+
+/*
+================
+DrawGLWaterPoly
+
+Warp the vertex coordinates
+================
+*/
+void DrawGLWaterPoly (glpoly_t *p)
+{
+	int		i;
+	float	*v;
+	vec3_t	nv;
+
+	GL_DisableMultitexture();
+
+	glBegin (GL_TRIANGLE_FAN);
+	v = p->verts[0];
+	for (i=0 ; i<p->numverts ; i++, v+= VERTEXSIZE)
+	{
+		glTexCoord2f (v[3], v[4]);
+
+		nv[0] = v[0] + 8*sin(v[1]*0.05+realtime)*sin(v[2]*0.05+realtime);
+		nv[1] = v[1] + 8*sin(v[0]*0.05+realtime)*sin(v[2]*0.05+realtime);
+		nv[2] = v[2];
+
+		glVertex3fv (nv);
+	}
+	glEnd ();
+}
+
+void DrawGLWaterPolyLightmap (glpoly_t *p)
+{
+	int		i;
+	float	*v;
+	vec3_t	nv;
+
+	GL_DisableMultitexture();
+
+	glBegin (GL_TRIANGLE_FAN);
+	v = p->verts[0];
+	for (i=0 ; i<p->numverts ; i++, v+= VERTEXSIZE)
+	{
+		glTexCoord2f (v[5], v[6]);
+
+		nv[0] = v[0] + 8*sin(v[1]*0.05+realtime)*sin(v[2]*0.05+realtime);
+		nv[1] = v[1] + 8*sin(v[0]*0.05+realtime)*sin(v[2]*0.05+realtime);
+		nv[2] = v[2];
+
+		glVertex3fv (nv);
+	}
+	glEnd ();
+}
+
+/*
+================
+DrawGLPoly
+================
+*/
+void DrawGLPoly (glpoly_t *p)
+{
+	int		i;
+	float	*v;
+
+	glBegin (GL_POLYGON);
+	v = p->verts[0];
+	for (i=0 ; i<p->numverts ; i++, v+= VERTEXSIZE)
+	{
+		glTexCoord2f (v[3], v[4]);
+		glVertex3fv (v);
+	}
+	glEnd ();
+}
+
+
+/*
+================
+R_BlendLightmaps
+================
+*/
+void R_BlendLightmaps (void)
+{
+	int			i, j;
+	glpoly_t	*p;
+	float		*v;
+	glRect_t	*theRect;
+
+#if 0
+	if (r_fullbright.value)
+		return;
+#endif
+	if (!gl_texsort.value)
+		return;
+
+	glDepthMask (0);		// don't bother writing Z
+
+	if (gl_lightmap_format == GL_LUMINANCE)
+		glBlendFunc (GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
+	else if (gl_lightmap_format == GL_INTENSITY)
+	{
+		glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+		glColor4f (0,0,0,1);
+		glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+	}
+
+	if (!r_lightmap.value)
+	{
+		glEnable (GL_BLEND);
+	}
+
+	for (i=0 ; i<MAX_LIGHTMAPS ; i++)
+	{
+		p = lightmap_polys[i];
+		if (!p)
+			continue;
+		GL_Bind(lightmap_textures+i);
+		if (lightmap_modified[i])
+		{
+			lightmap_modified[i] = false;
+			theRect = &lightmap_rectchange[i];
+//			theRect->l = 0;
+//			theRect->t = 0;
+//			theRect->w = BLOCK_WIDTH;
+//			theRect->h = BLOCK_HEIGHT;
+//			glTexImage2D (GL_TEXTURE_2D, 0, lightmap_bytes
+//			, BLOCK_WIDTH, BLOCK_HEIGHT, 0, 
+//			gl_lightmap_format, GL_UNSIGNED_BYTE, lightmaps+i*BLOCK_WIDTH*BLOCK_HEIGHT*lightmap_bytes);
+//			glTexImage2D (GL_TEXTURE_2D, 0, lightmap_bytes
+//				, BLOCK_WIDTH, theRect->h, 0, 
+//				gl_lightmap_format, GL_UNSIGNED_BYTE, lightmaps+(i*BLOCK_HEIGHT+theRect->t)*BLOCK_WIDTH*lightmap_bytes);
+			glTexSubImage2D(GL_TEXTURE_2D, 0, 0, theRect->t, 
+				BLOCK_WIDTH, theRect->h, gl_lightmap_format, GL_UNSIGNED_BYTE,
+				lightmaps+(i* BLOCK_HEIGHT + theRect->t) *BLOCK_WIDTH*lightmap_bytes);
+			theRect->l = BLOCK_WIDTH;
+			theRect->t = BLOCK_HEIGHT;
+			theRect->h = 0;
+			theRect->w = 0;
+		}
+		for ( ; p ; p=p->chain)
+		{
+//			if (p->flags & SURF_UNDERWATER)
+//				DrawGLWaterPolyLightmap (p);
+			if (((r_viewleaf->contents==CONTENTS_EMPTY && (p->flags & SURF_UNDERWATER)) ||
+				(r_viewleaf->contents!=CONTENTS_EMPTY && !(p->flags & SURF_UNDERWATER)))
+				&& !(p->flags & SURF_DONTWARP))
+				DrawGLWaterPolyLightmap (p);
+			else
+			{
+				glBegin (GL_POLYGON);
+				v = p->verts[0];
+				for (j=0 ; j<p->numverts ; j++, v+= VERTEXSIZE)
+				{
+					glTexCoord2f (v[5], v[6]);
+					glVertex3fv (v);
+				}
+				glEnd ();
+			}
+		}
+	}
+
+	glDisable (GL_BLEND);
+	if (gl_lightmap_format == GL_LUMINANCE)
+		glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+	else if (gl_lightmap_format == GL_INTENSITY)
+	{
+		glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+		glColor4f (1,1,1,1);
+	}
+
+	glDepthMask (1);		// back to normal Z buffering
+}
+
+/*
+================
+R_RenderBrushPoly
+================
+*/
+void R_RenderBrushPoly (msurface_t *fa)
+{
+	texture_t	*t;
+	byte		*base;
+	int			maps;
+	glRect_t    *theRect;
+	int smax, tmax;
+
+	c_brush_polys++;
+
+	if (fa->flags & SURF_DRAWSKY)
+	{	// warp texture, no lightmaps
+		EmitBothSkyLayers (fa);
+		return;
+	}
+		
+	t = R_TextureAnimation (fa->texinfo->texture);
+	GL_Bind (t->gl_texturenum);
+
+	if (fa->flags & SURF_DRAWTURB)
+	{	// warp texture, no lightmaps
+		EmitWaterPolys (fa);
+		return;
+	}
+
+	if (((r_viewleaf->contents==CONTENTS_EMPTY && (fa->flags & SURF_UNDERWATER)) ||
+		(r_viewleaf->contents!=CONTENTS_EMPTY && !(fa->flags & SURF_UNDERWATER)))
+		&& !(fa->flags & SURF_DONTWARP))
+		DrawGLWaterPoly (fa->polys);
+	else
+		DrawGLPoly (fa->polys);
+
+	// add the poly to the proper lightmap chain
+
+	fa->polys->chain = lightmap_polys[fa->lightmaptexturenum];
+	lightmap_polys[fa->lightmaptexturenum] = fa->polys;
+
+	// check for lightmap modification
+	for (maps = 0 ; maps < MAXLIGHTMAPS && fa->styles[maps] != 255 ;
+		 maps++)
+		if (d_lightstylevalue[fa->styles[maps]] != fa->cached_light[maps])
+			goto dynamic;
+
+	if (fa->dlightframe == r_framecount	// dynamic this frame
+		|| fa->cached_dlight)			// dynamic previously
+	{
+dynamic:
+		if (r_dynamic.value)
+		{
+			lightmap_modified[fa->lightmaptexturenum] = true;
+			theRect = &lightmap_rectchange[fa->lightmaptexturenum];
+			if (fa->light_t < theRect->t) {
+				if (theRect->h)
+					theRect->h += theRect->t - fa->light_t;
+				theRect->t = fa->light_t;
+			}
+			if (fa->light_s < theRect->l) {
+				if (theRect->w)
+					theRect->w += theRect->l - fa->light_s;
+				theRect->l = fa->light_s;
+			}
+			smax = (fa->extents[0]>>4)+1;
+			tmax = (fa->extents[1]>>4)+1;
+			if ((theRect->w + theRect->l) < (fa->light_s + smax))
+				theRect->w = (fa->light_s-theRect->l)+smax;
+			if ((theRect->h + theRect->t) < (fa->light_t + tmax))
+				theRect->h = (fa->light_t-theRect->t)+tmax;
+			base = lightmaps + fa->lightmaptexturenum*lightmap_bytes*BLOCK_WIDTH*BLOCK_HEIGHT;
+			base += fa->light_t * BLOCK_WIDTH * lightmap_bytes + fa->light_s * lightmap_bytes;
+			R_BuildLightMap (fa, base, BLOCK_WIDTH*lightmap_bytes);
+		}
+	}
+}
+
+/*
+================
+R_RenderDynamicLightmaps
+Multitexture
+================
+*/
+void R_RenderDynamicLightmaps (msurface_t *fa)
+{
+	byte		*base;
+	int			maps;
+	glRect_t    *theRect;
+	int smax, tmax;
+
+	c_brush_polys++;
+
+	if (fa->flags & ( SURF_DRAWSKY | SURF_DRAWTURB) )
+		return;
+		
+	fa->polys->chain = lightmap_polys[fa->lightmaptexturenum];
+	lightmap_polys[fa->lightmaptexturenum] = fa->polys;
+
+	// check for lightmap modification
+	for (maps = 0 ; maps < MAXLIGHTMAPS && fa->styles[maps] != 255 ;
+		 maps++)
+		if (d_lightstylevalue[fa->styles[maps]] != fa->cached_light[maps])
+			goto dynamic;
+
+	if (fa->dlightframe == r_framecount	// dynamic this frame
+		|| fa->cached_dlight)			// dynamic previously
+	{
+dynamic:
+		if (r_dynamic.value)
+		{
+			lightmap_modified[fa->lightmaptexturenum] = true;
+			theRect = &lightmap_rectchange[fa->lightmaptexturenum];
+			if (fa->light_t < theRect->t) {
+				if (theRect->h)
+					theRect->h += theRect->t - fa->light_t;
+				theRect->t = fa->light_t;
+			}
+			if (fa->light_s < theRect->l) {
+				if (theRect->w)
+					theRect->w += theRect->l - fa->light_s;
+				theRect->l = fa->light_s;
+			}
+			smax = (fa->extents[0]>>4)+1;
+			tmax = (fa->extents[1]>>4)+1;
+			if ((theRect->w + theRect->l) < (fa->light_s + smax))
+				theRect->w = (fa->light_s-theRect->l)+smax;
+			if ((theRect->h + theRect->t) < (fa->light_t + tmax))
+				theRect->h = (fa->light_t-theRect->t)+tmax;
+			base = lightmaps + fa->lightmaptexturenum*lightmap_bytes*BLOCK_WIDTH*BLOCK_HEIGHT;
+			base += fa->light_t * BLOCK_WIDTH * lightmap_bytes + fa->light_s * lightmap_bytes;
+			R_BuildLightMap (fa, base, BLOCK_WIDTH*lightmap_bytes);
+		}
+	}
+}
+
+/*
+================
+R_MirrorChain
+================
+*/
+void R_MirrorChain (msurface_t *s)
+{
+	if (mirror)
+		return;
+	mirror = true;
+	mirror_plane = s->plane;
+}
+
+
+#if 0
+/*
+================
+R_DrawWaterSurfaces
+================
+*/
+void R_DrawWaterSurfaces (void)
+{
+	int			i;
+	msurface_t	*s;
+	texture_t	*t;
+
+	if (r_wateralpha.value == 1.0)
+		return;
+
+	//
+	// go back to the world matrix
+	//
+    glLoadMatrixf (r_world_matrix);
+
+	glEnable (GL_BLEND);
+	glColor4f (1,1,1,r_wateralpha.value);
+	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+
+	for (i=0 ; i<cl.worldmodel->numtextures ; i++)
+	{
+		t = cl.worldmodel->textures[i];
+		if (!t)
+			continue;
+		s = t->texturechain;
+		if (!s)
+			continue;
+		if ( !(s->flags & SURF_DRAWTURB) )
+			continue;
+
+		// set modulate mode explicitly
+		GL_Bind (t->gl_texturenum);
+
+		for ( ; s ; s=s->texturechain)
+			R_RenderBrushPoly (s);
+
+		t->texturechain = NULL;
+	}
+
+	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+
+	glColor4f (1,1,1,1);
+	glDisable (GL_BLEND);
+}
+#else
+/*
+================
+R_DrawWaterSurfaces
+================
+*/
+void R_DrawWaterSurfaces (void)
+{
+	int			i;
+	msurface_t	*s;
+	texture_t	*t;
+
+	if (r_wateralpha.value == 1.0 && gl_texsort.value)
+		return;
+
+	//
+	// go back to the world matrix
+	//
+
+    glLoadMatrixf (r_world_matrix);
+
+	if (r_wateralpha.value < 1.0) {
+		glEnable (GL_BLEND);
+		glColor4f (1,1,1,r_wateralpha.value);
+		glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+	}
+
+	if (!gl_texsort.value) {
+		if (!waterchain)
+			return;
+
+		for ( s = waterchain ; s ; s=s->texturechain) {
+			GL_Bind (s->texinfo->texture->gl_texturenum);
+			EmitWaterPolys (s);
+		}
+		
+		waterchain = NULL;
+	} else {
+
+		for (i=0 ; i<cl.worldmodel->numtextures ; i++)
+		{
+			t = cl.worldmodel->textures[i];
+			if (!t)
+				continue;
+			s = t->texturechain;
+			if (!s)
+				continue;
+			if ( !(s->flags & SURF_DRAWTURB ) )
+				continue;
+
+			// set modulate mode explicitly
+			
+			GL_Bind (t->gl_texturenum);
+
+			for ( ; s ; s=s->texturechain)
+				EmitWaterPolys (s);
+			
+			t->texturechain = NULL;
+		}
+
+	}
+
+	if (r_wateralpha.value < 1.0) {
+		glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+
+		glColor4f (1,1,1,1);
+		glDisable (GL_BLEND);
+	}
+
+}
+
+#endif
+
+/*
+================
+DrawTextureChains
+================
+*/
+void DrawTextureChains (void)
+{
+	int		i;
+	msurface_t	*s;
+	texture_t	*t;
+
+	if (!gl_texsort.value) {
+		GL_DisableMultitexture();
+
+		if (skychain) {
+			R_DrawSkyChain(skychain);
+			skychain = NULL;
+		}
+
+		return;
+	} 
+
+	for (i=0 ; i<cl.worldmodel->numtextures ; i++)
+	{
+		t = cl.worldmodel->textures[i];
+		if (!t)
+			continue;
+		s = t->texturechain;
+		if (!s)
+			continue;
+		if (i == skytexturenum)
+			R_DrawSkyChain (s);
+		else if (i == mirrortexturenum && r_mirroralpha.value != 1.0)
+		{
+			R_MirrorChain (s);
+			continue;
+		}
+		else
+		{
+			if ((s->flags & SURF_DRAWTURB) && r_wateralpha.value != 1.0)
+				continue;	// draw translucent water later
+			for ( ; s ; s=s->texturechain)
+				R_RenderBrushPoly (s);
+		}
+
+		t->texturechain = NULL;
+	}
+}
+
+/*
+=================
+R_DrawBrushModel
+=================
+*/
+void R_DrawBrushModel (entity_t *e)
+{
+	int			i;
+	int			k;
+	vec3_t		mins, maxs;
+	msurface_t	*psurf;
+	float		dot;
+	mplane_t	*pplane;
+	model_t		*clmodel;
+	qboolean	rotated;
+
+	currententity = e;
+	currenttexture = -1;
+
+	clmodel = e->model;
+
+	if (e->angles[0] || e->angles[1] || e->angles[2])
+	{
+		rotated = true;
+		for (i=0 ; i<3 ; i++)
+		{
+			mins[i] = e->origin[i] - clmodel->radius;
+			maxs[i] = e->origin[i] + clmodel->radius;
+		}
+	}
+	else
+	{
+		rotated = false;
+		VectorAdd (e->origin, clmodel->mins, mins);
+		VectorAdd (e->origin, clmodel->maxs, maxs);
+	}
+
+	if (R_CullBox (mins, maxs))
+		return;
+
+	glColor3f (1,1,1);
+	memset (lightmap_polys, 0, sizeof(lightmap_polys));
+
+	VectorSubtract (r_refdef.vieworg, e->origin, modelorg);
+	if (rotated)
+	{
+		vec3_t	temp;
+		vec3_t	forward, right, up;
+
+		VectorCopy (modelorg, temp);
+		AngleVectors (e->angles, forward, right, up);
+		modelorg[0] = DotProduct (temp, forward);
+		modelorg[1] = -DotProduct (temp, right);
+		modelorg[2] = DotProduct (temp, up);
+	}
+
+	psurf = &clmodel->surfaces[clmodel->firstmodelsurface];
+
+// calculate dynamic lighting for bmodel if it's not an
+// instanced model
+	if (clmodel->firstmodelsurface != 0 && !gl_flashblend.value)
+	{
+		for (k=0 ; k<MAX_DLIGHTS ; k++)
+		{
+			if ((cl_dlights[k].die < cl.time) ||
+				(!cl_dlights[k].radius))
+				continue;
+
+			R_MarkLights (&cl_dlights[k], 1<<k,
+				clmodel->nodes + clmodel->hulls[0].firstclipnode);
+		}
+	}
+
+    glPushMatrix ();
+e->angles[0] = -e->angles[0];	// stupid quake bug
+	R_RotateForEntity (e);
+e->angles[0] = -e->angles[0];	// stupid quake bug
+
+	//
+	// draw texture
+	//
+	for (i=0 ; i<clmodel->nummodelsurfaces ; i++, psurf++)
+	{
+	// find which side of the node we are on
+		pplane = psurf->plane;
+
+		dot = DotProduct (modelorg, pplane->normal) - pplane->dist;
+
+	// draw the polygon
+		if (((psurf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) ||
+			(!(psurf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON)))
+		{
+			if (gl_texsort.value)
+				R_RenderBrushPoly (psurf);
+			else
+				R_DrawSequentialPoly (psurf);
+		}
+	}
+
+	R_BlendLightmaps ();
+
+	glPopMatrix ();
+}
+
+/*
+=============================================================
+
+	WORLD MODEL
+
+=============================================================
+*/
+
+/*
+================
+R_RecursiveWorldNode
+================
+*/
+void R_RecursiveWorldNode (mnode_t *node)
+{
+	int			c, side;
+	mplane_t	*plane;
+	msurface_t	*surf, **mark;
+	mleaf_t		*pleaf;
+	double		dot;
+
+	if (node->contents == CONTENTS_SOLID)
+		return;		// solid
+
+	if (node->visframe != r_visframecount)
+		return;
+	if (R_CullBox (node->minmaxs, node->minmaxs+3))
+		return;
+	
+// if a leaf node, draw stuff
+	if (node->contents < 0)
+	{
+		pleaf = (mleaf_t *)node;
+
+		mark = pleaf->firstmarksurface;
+		c = pleaf->nummarksurfaces;
+
+		if (c)
+		{
+			do
+			{
+				(*mark)->visframe = r_framecount;
+				mark++;
+			} while (--c);
+		}
+
+	// deal with model fragments in this leaf
+		if (pleaf->efrags)
+			R_StoreEfrags (&pleaf->efrags);
+
+		return;
+	}
+
+// node is just a decision point, so go down the apropriate sides
+
+// find which side of the node we are on
+	plane = node->plane;
+
+	switch (plane->type)
+	{
+	case PLANE_X:
+		dot = modelorg[0] - plane->dist;
+		break;
+	case PLANE_Y:
+		dot = modelorg[1] - plane->dist;
+		break;
+	case PLANE_Z:
+		dot = modelorg[2] - plane->dist;
+		break;
+	default:
+		dot = DotProduct (modelorg, plane->normal) - plane->dist;
+		break;
+	}
+
+	if (dot >= 0)
+		side = 0;
+	else
+		side = 1;
+
+// recurse down the children, front side first
+	R_RecursiveWorldNode (node->children[side]);
+
+// draw stuff
+	c = node->numsurfaces;
+
+	if (c)
+	{
+		surf = cl.worldmodel->surfaces + node->firstsurface;
+
+		if (dot < 0 -BACKFACE_EPSILON)
+			side = SURF_PLANEBACK;
+		else if (dot > BACKFACE_EPSILON)
+			side = 0;
+		{
+			for ( ; c ; c--, surf++)
+			{
+				if (surf->visframe != r_framecount)
+					continue;
+
+				// don't backface underwater surfaces, because they warp
+//				if ( !(surf->flags & SURF_UNDERWATER) && ( (dot < 0) ^ !!(surf->flags & SURF_PLANEBACK)) )
+//					continue;		// wrong side
+				if ( !(((r_viewleaf->contents==CONTENTS_EMPTY && (surf->flags & SURF_UNDERWATER)) ||
+					(r_viewleaf->contents!=CONTENTS_EMPTY && !(surf->flags & SURF_UNDERWATER)))
+					&& !(surf->flags & SURF_DONTWARP)) && ( (dot < 0) ^ !!(surf->flags & SURF_PLANEBACK)) )
+					continue;		// wrong side
+
+				// if sorting by texture, just store it out
+				if (gl_texsort.value)
+				{
+					if (!mirror
+					|| surf->texinfo->texture != cl.worldmodel->textures[mirrortexturenum])
+					{
+						surf->texturechain = surf->texinfo->texture->texturechain;
+						surf->texinfo->texture->texturechain = surf;
+					}
+				} else if (surf->flags & SURF_DRAWSKY) {
+					surf->texturechain = skychain;
+					skychain = surf;
+				} else if (surf->flags & SURF_DRAWTURB) {
+					surf->texturechain = waterchain;
+					waterchain = surf;
+				} else
+					R_DrawSequentialPoly (surf);
+
+			}
+		}
+
+	}
+
+// recurse down the back side
+	R_RecursiveWorldNode (node->children[!side]);
+}
+
+
+
+/*
+=============
+R_DrawWorld
+=============
+*/
+void R_DrawWorld (void)
+{
+	entity_t	ent;
+
+	memset (&ent, 0, sizeof(ent));
+	ent.model = cl.worldmodel;
+
+	VectorCopy (r_refdef.vieworg, modelorg);
+
+	currententity = &ent;
+	currenttexture = -1;
+
+	glColor3f (1,1,1);
+	memset (lightmap_polys, 0, sizeof(lightmap_polys));
+#ifdef QUAKE2
+	R_ClearSkyBox ();
+#endif
+
+	R_RecursiveWorldNode (cl.worldmodel->nodes);
+
+		DrawTextureChains ();
+
+	R_BlendLightmaps ();
+
+#ifdef QUAKE2
+	R_DrawSkyBox ();
+#endif
+}
+
+
+/*
+===============
+R_MarkLeaves
+===============
+*/
+void R_MarkLeaves (void)
+{
+	byte	*vis;
+	mnode_t	*node;
+	int		i;
+	byte	solid[4096];
+
+	if (r_oldviewleaf == r_viewleaf && !r_novis.value)
+		return;
+	
+	if (mirror)
+		return;
+
+	r_visframecount++;
+	r_oldviewleaf = r_viewleaf;
+
+	if (r_novis.value)
+	{
+		vis = solid;
+		memset (solid, 0xff, (cl.worldmodel->numleafs+7)>>3);
+	}
+	else
+		vis = Mod_LeafPVS (r_viewleaf, cl.worldmodel);
+		
+	for (i=0 ; i<cl.worldmodel->numleafs ; i++)
+	{
+		if (vis[i>>3] & (1<<(i&7)))
+		{
+			node = (mnode_t *)&cl.worldmodel->leafs[i+1];
+			do
+			{
+				if (node->visframe == r_visframecount)
+					break;
+				node->visframe = r_visframecount;
+				node = node->parent;
+			} while (node);
+		}
+	}
+}
+
+
+
+/*
+=============================================================================
+
+  LIGHTMAP ALLOCATION
+
+=============================================================================
+*/
+
+// returns a texture number and the position inside it
+int AllocBlock (int w, int h, int *x, int *y)
+{
+	int		i, j;
+	int		best, best2;
+	int		texnum;
+
+	for (texnum=0 ; texnum<MAX_LIGHTMAPS ; texnum++)
+	{
+		best = BLOCK_HEIGHT;
+
+		for (i=0 ; i<BLOCK_WIDTH-w ; i++)
+		{
+			best2 = 0;
+
+			for (j=0 ; j<w ; j++)
+			{
+				if (allocated[texnum][i+j] >= best)
+					break;
+				if (allocated[texnum][i+j] > best2)
+					best2 = allocated[texnum][i+j];
+			}
+			if (j == w)
+			{	// this is a valid spot
+				*x = i;
+				*y = best = best2;
+			}
+		}
+
+		if (best + h > BLOCK_HEIGHT)
+			continue;
+
+		for (i=0 ; i<w ; i++)
+			allocated[texnum][*x + i] = best + h;
+
+		return texnum;
+	}
+
+	Sys_Error ("AllocBlock: full");
+	return 0;
+}
+
+
+mvertex_t	*r_pcurrentvertbase;
+model_t		*currentmodel;
+
+int	nColinElim;
+
+/*
+================
+BuildSurfaceDisplayList
+================
+*/
+void BuildSurfaceDisplayList (msurface_t *fa)
+{
+	int			i, lindex, lnumverts;
+	medge_t		*pedges, *r_pedge;
+	int			vertpage;
+	float		*vec;
+	float		s, t;
+	glpoly_t	*poly;
+
+// reconstruct the polygon
+	pedges = currentmodel->edges;
+	lnumverts = fa->numedges;
+	vertpage = 0;
+
+	//
+	// draw texture
+	//
+	poly = Hunk_Alloc (sizeof(glpoly_t) + (lnumverts-4) * VERTEXSIZE*sizeof(float));
+	poly->next = fa->polys;
+	poly->flags = fa->flags;
+	fa->polys = poly;
+	poly->numverts = lnumverts;
+
+	for (i=0 ; i<lnumverts ; i++)
+	{
+		lindex = currentmodel->surfedges[fa->firstedge + i];
+
+		if (lindex > 0)
+		{
+			r_pedge = &pedges[lindex];
+			vec = r_pcurrentvertbase[r_pedge->v[0]].position;
+		}
+		else
+		{
+			r_pedge = &pedges[-lindex];
+			vec = r_pcurrentvertbase[r_pedge->v[1]].position;
+		}
+		s = DotProduct (vec, fa->texinfo->vecs[0]) + fa->texinfo->vecs[0][3];
+		s /= fa->texinfo->texture->width;
+
+		t = DotProduct (vec, fa->texinfo->vecs[1]) + fa->texinfo->vecs[1][3];
+		t /= fa->texinfo->texture->height;
+
+		VectorCopy (vec, poly->verts[i]);
+		poly->verts[i][3] = s;
+		poly->verts[i][4] = t;
+
+		//
+		// lightmap texture coordinates
+		//
+		s = DotProduct (vec, fa->texinfo->vecs[0]) + fa->texinfo->vecs[0][3];
+		s -= fa->texturemins[0];
+		s += fa->light_s*16;
+		s += 8;
+		s /= BLOCK_WIDTH*16; //fa->texinfo->texture->width;
+
+		t = DotProduct (vec, fa->texinfo->vecs[1]) + fa->texinfo->vecs[1][3];
+		t -= fa->texturemins[1];
+		t += fa->light_t*16;
+		t += 8;
+		t /= BLOCK_HEIGHT*16; //fa->texinfo->texture->height;
+
+		poly->verts[i][5] = s;
+		poly->verts[i][6] = t;
+	}
+
+	//
+	// remove co-linear points - Ed
+	//
+	if (!gl_keeptjunctions.value && !(fa->flags & SURF_UNDERWATER) )
+	{
+		for (i = 0 ; i < lnumverts ; ++i)
+		{
+			vec3_t v1, v2;
+			float *prev, *this, *next;
+
+			prev = poly->verts[(i + lnumverts - 1) % lnumverts];
+			this = poly->verts[i];
+			next = poly->verts[(i + 1) % lnumverts];
+
+			VectorSubtract( this, prev, v1 );
+			VectorNormalize( v1 );
+			VectorSubtract( next, prev, v2 );
+			VectorNormalize( v2 );
+
+			// skip co-linear points
+			#define COLINEAR_EPSILON 0.001
+			if ((fabs( v1[0] - v2[0] ) <= COLINEAR_EPSILON) &&
+				(fabs( v1[1] - v2[1] ) <= COLINEAR_EPSILON) && 
+				(fabs( v1[2] - v2[2] ) <= COLINEAR_EPSILON))
+			{
+				int j;
+				for (j = i + 1; j < lnumverts; ++j)
+				{
+					int k;
+					for (k = 0; k < VERTEXSIZE; ++k)
+						poly->verts[j - 1][k] = poly->verts[j][k];
+				}
+				--lnumverts;
+				++nColinElim;
+				// retry next vertex next time, which is now current vertex
+				--i;
+			}
+		}
+	}
+	poly->numverts = lnumverts;
+
+}
+
+/*
+========================
+GL_CreateSurfaceLightmap
+========================
+*/
+void GL_CreateSurfaceLightmap (msurface_t *surf)
+{
+	int		smax, tmax;
+	byte	*base;
+
+	if (surf->flags & (SURF_DRAWSKY|SURF_DRAWTURB))
+		return;
+
+	smax = (surf->extents[0]>>4)+1;
+	tmax = (surf->extents[1]>>4)+1;
+
+	surf->lightmaptexturenum = AllocBlock (smax, tmax, &surf->light_s, &surf->light_t);
+	base = lightmaps + surf->lightmaptexturenum*lightmap_bytes*BLOCK_WIDTH*BLOCK_HEIGHT;
+	base += (surf->light_t * BLOCK_WIDTH + surf->light_s) * lightmap_bytes;
+	R_BuildLightMap (surf, base, BLOCK_WIDTH*lightmap_bytes);
+}
+
+
+/*
+==================
+GL_BuildLightmaps
+
+Builds the lightmap texture
+with all the surfaces from all brush models
+==================
+*/
+void GL_BuildLightmaps (void)
+{
+	int		i, j;
+	model_t	*m;
+
+	memset (allocated, 0, sizeof(allocated));
+
+	r_framecount = 1;		// no dlightcache
+
+	if (!lightmap_textures)
+	{
+		lightmap_textures = texture_extension_number;
+		texture_extension_number += MAX_LIGHTMAPS;
+	}
+
+	gl_lightmap_format = GL_LUMINANCE;
+	if (COM_CheckParm ("-lm_1"))
+		gl_lightmap_format = GL_LUMINANCE;
+	if (COM_CheckParm ("-lm_a"))
+		gl_lightmap_format = GL_ALPHA;
+	if (COM_CheckParm ("-lm_i"))
+		gl_lightmap_format = GL_INTENSITY;
+	if (COM_CheckParm ("-lm_2"))
+		gl_lightmap_format = GL_RGBA4;
+	if (COM_CheckParm ("-lm_4"))
+		gl_lightmap_format = GL_RGBA;
+
+	switch (gl_lightmap_format)
+	{
+	case GL_RGBA:
+		lightmap_bytes = 4;
+		break;
+	case GL_RGBA4:
+		lightmap_bytes = 2;
+		break;
+	case GL_LUMINANCE:
+	case GL_INTENSITY:
+	case GL_ALPHA:
+		lightmap_bytes = 1;
+		break;
+	}
+
+	for (j=1 ; j<MAX_MODELS ; j++)
+	{
+		m = cl.model_precache[j];
+		if (!m)
+			break;
+		if (m->name[0] == '*')
+			continue;
+		r_pcurrentvertbase = m->vertexes;
+		currentmodel = m;
+		for (i=0 ; i<m->numsurfaces ; i++)
+		{
+			GL_CreateSurfaceLightmap (m->surfaces + i);
+			if ( m->surfaces[i].flags & SURF_DRAWTURB )
+				continue;
+#ifndef QUAKE2
+			if ( m->surfaces[i].flags & SURF_DRAWSKY )
+				continue;
+#endif
+			BuildSurfaceDisplayList (m->surfaces + i);
+		}
+	}
+
+ 	if (!gl_texsort.value)
+ 		GL_SelectTexture(TEXTURE1_SGIS);
+
+	//
+	// upload all lightmaps that were filled
+	//
+	for (i=0 ; i<MAX_LIGHTMAPS ; i++)
+	{
+		if (!allocated[i][0])
+			break;		// no more used
+		lightmap_modified[i] = false;
+		lightmap_rectchange[i].l = BLOCK_WIDTH;
+		lightmap_rectchange[i].t = BLOCK_HEIGHT;
+		lightmap_rectchange[i].w = 0;
+		lightmap_rectchange[i].h = 0;
+		GL_Bind(lightmap_textures + i);
+		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+		glTexImage2D (GL_TEXTURE_2D, 0, lightmap_bytes
+		, BLOCK_WIDTH, BLOCK_HEIGHT, 0, 
+		gl_lightmap_format, GL_UNSIGNED_BYTE, lightmaps+i*BLOCK_WIDTH*BLOCK_HEIGHT*lightmap_bytes);
+	}
+
+ 	if (!gl_texsort.value)
+ 		GL_SelectTexture(TEXTURE0_SGIS);
+
+}
+
--- /dev/null
+++ b/QW/client/gl_screen.c
@@ -1,0 +1,1188 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+
+// screen.c -- master for refresh, status bar, console, chat, notify, etc
+
+#include "quakedef.h"
+
+#include <time.h>
+
+/*
+
+background clear
+rendering
+turtle/net/ram icons
+sbar
+centerprint / slow centerprint
+notify lines
+intermission / finale overlay
+loading plaque
+console
+menu
+
+required background clears
+required update regions
+
+
+syncronous draw mode or async
+One off screen buffer, with updates either copied or xblited
+Need to double buffer?
+
+
+async draw will require the refresh area to be cleared, because it will be
+xblited, but sync draw can just ignore it.
+
+sync
+draw
+
+CenterPrint ()
+SlowPrint ()
+Screen_Update ();
+Con_Printf ();
+
+net 
+turn off messages option
+
+the refresh is allways rendered, unless the console is full screen
+
+
+console is:
+	notify lines
+	half
+	full
+	
+
+*/
+
+
+int                     glx, gly, glwidth, glheight;
+
+// only the refresh window will be updated unless these variables are flagged 
+int                     scr_copytop;
+int                     scr_copyeverything;
+
+float           scr_con_current;
+float           scr_conlines;           // lines of console to display
+
+float           oldscreensize, oldfov;
+cvar_t          scr_viewsize = {"viewsize","100", true};
+cvar_t          scr_fov = {"fov","90"}; // 10 - 170
+cvar_t          scr_conspeed = {"scr_conspeed","300"};
+cvar_t          scr_centertime = {"scr_centertime","2"};
+cvar_t          scr_showram = {"showram","1"};
+cvar_t          scr_showturtle = {"showturtle","0"};
+cvar_t          scr_showpause = {"showpause","1"};
+cvar_t          scr_printspeed = {"scr_printspeed","8"};
+cvar_t			scr_allowsnap = {"scr_allowsnap", "1"};
+cvar_t			gl_triplebuffer = {"gl_triplebuffer", "1", true };
+extern  		cvar_t  crosshair;
+
+qboolean        scr_initialized;                // ready to draw
+
+qpic_t          *scr_ram;
+qpic_t          *scr_net;
+qpic_t          *scr_turtle;
+
+int                     scr_fullupdate;
+
+int                     clearconsole;
+int                     clearnotify;
+
+int                     sb_lines;
+
+viddef_t        vid;                            // global video state
+
+vrect_t         scr_vrect;
+
+qboolean        scr_disabled_for_loading;
+qboolean        scr_drawloading;
+float           scr_disabled_time;
+
+qboolean        block_drawing;
+
+void SCR_ScreenShot_f (void);
+void SCR_RSShot_f (void);
+
+/*
+===============================================================================
+
+CENTER PRINTING
+
+===============================================================================
+*/
+
+char            scr_centerstring[1024];
+float           scr_centertime_start;   // for slow victory printing
+float           scr_centertime_off;
+int                     scr_center_lines;
+int                     scr_erase_lines;
+int                     scr_erase_center;
+
+/*
+==============
+SCR_CenterPrint
+
+Called for important messages that should stay in the center of the screen
+for a few moments
+==============
+*/
+void SCR_CenterPrint (char *str)
+{
+	strncpy (scr_centerstring, str, sizeof(scr_centerstring)-1);
+	scr_centertime_off = scr_centertime.value;
+	scr_centertime_start = cl.time;
+
+// count the number of lines for centering
+	scr_center_lines = 1;
+	while (*str)
+	{
+		if (*str == '\n')
+			scr_center_lines++;
+		str++;
+	}
+}
+
+
+void SCR_DrawCenterString (void)
+{
+	char    *start;
+	int             l;
+	int             j;
+	int             x, y;
+	int             remaining;
+
+// the finale prints the characters one at a time
+	if (cl.intermission)
+		remaining = scr_printspeed.value * (cl.time - scr_centertime_start);
+	else
+		remaining = 9999;
+
+	scr_erase_center = 0;
+	start = scr_centerstring;
+
+	if (scr_center_lines <= 4)
+		y = vid.height*0.35;
+	else
+		y = 48;
+
+	do      
+	{
+	// scan the width of the line
+		for (l=0 ; l<40 ; l++)
+			if (start[l] == '\n' || !start[l])
+				break;
+		x = (vid.width - l*8)/2;
+		for (j=0 ; j<l ; j++, x+=8)
+		{
+			Draw_Character (x, y, start[j]);        
+			if (!remaining--)
+				return;
+		}
+			
+		y += 8;
+
+		while (*start && *start != '\n')
+			start++;
+
+		if (!*start)
+			break;
+		start++;                // skip the \n
+	} while (1);
+}
+
+void SCR_CheckDrawCenterString (void)
+{
+	scr_copytop = 1;
+	if (scr_center_lines > scr_erase_lines)
+		scr_erase_lines = scr_center_lines;
+
+	scr_centertime_off -= host_frametime;
+	
+	if (scr_centertime_off <= 0 && !cl.intermission)
+		return;
+	if (key_dest != key_game)
+		return;
+
+	SCR_DrawCenterString ();
+}
+
+//=============================================================================
+
+/*
+====================
+CalcFov
+====================
+*/
+float CalcFov (float fov_x, float width, float height)
+{
+        float   a;
+        float   x;
+
+        if (fov_x < 1 || fov_x > 179)
+                Sys_Error ("Bad fov: %f", fov_x);
+
+        x = width/tan(fov_x/360*M_PI);
+
+        a = atan (height/x);
+
+        a = a*360/M_PI;
+
+        return a;
+}
+
+/*
+=================
+SCR_CalcRefdef
+
+Must be called whenever vid changes
+Internal use only
+=================
+*/
+static void SCR_CalcRefdef (void)
+{
+	float           size;
+	int             h;
+	qboolean		full = false;
+
+
+	scr_fullupdate = 0;             // force a background redraw
+	vid.recalc_refdef = 0;
+
+// force the status bar to redraw
+	Sbar_Changed ();
+
+//========================================
+	
+// bound viewsize
+	if (scr_viewsize.value < 30)
+		Cvar_Set ("viewsize","30");
+	if (scr_viewsize.value > 120)
+		Cvar_Set ("viewsize","120");
+
+// bound field of view
+	if (scr_fov.value < 10)
+		Cvar_Set ("fov","10");
+	if (scr_fov.value > 170)
+		Cvar_Set ("fov","170");
+
+// intermission is always full screen   
+	if (cl.intermission)
+		size = 120;
+	else
+		size = scr_viewsize.value;
+
+	if (size >= 120)
+		sb_lines = 0;           // no status bar at all
+	else if (size >= 110)
+		sb_lines = 24;          // no inventory
+	else
+		sb_lines = 24+16+8;
+
+	if (scr_viewsize.value >= 100.0) {
+		full = true;
+		size = 100.0;
+	} else
+		size = scr_viewsize.value;
+	if (cl.intermission)
+	{
+		full = true;
+		size = 100.0;
+		sb_lines = 0;
+	}
+	size /= 100.0;
+
+	if (!cl_sbar.value && full)
+		h = vid.height;
+	else
+		h = vid.height - sb_lines;
+
+	r_refdef.vrect.width = vid.width * size;
+	if (r_refdef.vrect.width < 96)
+	{
+		size = 96.0 / r_refdef.vrect.width;
+		r_refdef.vrect.width = 96;      // min for icons
+	}
+
+	r_refdef.vrect.height = vid.height * size;
+	if (cl_sbar.value || !full) {
+  		if (r_refdef.vrect.height > vid.height - sb_lines)
+  			r_refdef.vrect.height = vid.height - sb_lines;
+	} else if (r_refdef.vrect.height > vid.height)
+			r_refdef.vrect.height = vid.height;
+	r_refdef.vrect.x = (vid.width - r_refdef.vrect.width)/2;
+	if (full)
+		r_refdef.vrect.y = 0;
+	else 
+		r_refdef.vrect.y = (h - r_refdef.vrect.height)/2;
+
+	r_refdef.fov_x = scr_fov.value;
+	r_refdef.fov_y = CalcFov (r_refdef.fov_x, r_refdef.vrect.width, r_refdef.vrect.height);
+
+	scr_vrect = r_refdef.vrect;
+}
+
+
+/*
+=================
+SCR_SizeUp_f
+
+Keybinding command
+=================
+*/
+void SCR_SizeUp_f (void)
+{
+	Cvar_SetValue ("viewsize",scr_viewsize.value+10);
+	vid.recalc_refdef = 1;
+}
+
+
+/*
+=================
+SCR_SizeDown_f
+
+Keybinding command
+=================
+*/
+void SCR_SizeDown_f (void)
+{
+	Cvar_SetValue ("viewsize",scr_viewsize.value-10);
+	vid.recalc_refdef = 1;
+}
+
+//============================================================================
+
+/*
+==================
+SCR_Init
+==================
+*/
+void SCR_Init (void)
+{
+	Cvar_RegisterVariable (&scr_fov);
+	Cvar_RegisterVariable (&scr_viewsize);
+	Cvar_RegisterVariable (&scr_conspeed);
+	Cvar_RegisterVariable (&scr_showram);
+	Cvar_RegisterVariable (&scr_showturtle);
+	Cvar_RegisterVariable (&scr_showpause);
+	Cvar_RegisterVariable (&scr_centertime);
+	Cvar_RegisterVariable (&scr_printspeed);
+	Cvar_RegisterVariable (&scr_allowsnap);
+	Cvar_RegisterVariable (&gl_triplebuffer);
+
+//
+// register our commands
+//
+	Cmd_AddCommand ("screenshot",SCR_ScreenShot_f);
+	Cmd_AddCommand ("snap",SCR_RSShot_f);
+	Cmd_AddCommand ("sizeup",SCR_SizeUp_f);
+	Cmd_AddCommand ("sizedown",SCR_SizeDown_f);
+
+	scr_ram = Draw_PicFromWad ("ram");
+	scr_net = Draw_PicFromWad ("net");
+	scr_turtle = Draw_PicFromWad ("turtle");
+
+	scr_initialized = true;
+}
+
+
+
+/*
+==============
+SCR_DrawRam
+==============
+*/
+void SCR_DrawRam (void)
+{
+	if (!scr_showram.value)
+		return;
+
+	if (!r_cache_thrash)
+		return;
+
+	Draw_Pic (scr_vrect.x+32, scr_vrect.y, scr_ram);
+}
+
+/*
+==============
+SCR_DrawTurtle
+==============
+*/
+void SCR_DrawTurtle (void)
+{
+	static int      count;
+	
+	if (!scr_showturtle.value)
+		return;
+
+	if (host_frametime < 0.1)
+	{
+		count = 0;
+		return;
+	}
+
+	count++;
+	if (count < 3)
+		return;
+
+	Draw_Pic (scr_vrect.x, scr_vrect.y, scr_turtle);
+}
+
+/*
+==============
+SCR_DrawNet
+==============
+*/
+void SCR_DrawNet (void)
+{
+	if (cls.netchan.outgoing_sequence - cls.netchan.incoming_acknowledged < UPDATE_BACKUP-1)
+		return;
+	if (cls.demoplayback)
+		return;
+
+	Draw_Pic (scr_vrect.x+64, scr_vrect.y, scr_net);
+}
+
+void SCR_DrawFPS (void)
+{
+	extern cvar_t show_fps;
+	static double lastframetime;
+	double t;
+	extern int fps_count;
+	static lastfps;
+	int x, y;
+	char st[80];
+
+	if (!show_fps.value)
+		return;
+
+	t = Sys_DoubleTime();
+	if ((t - lastframetime) >= 1.0) {
+		lastfps = fps_count;
+		fps_count = 0;
+		lastframetime = t;
+	}
+
+	sprintf(st, "%3d FPS", lastfps);
+	x = vid.width - strlen(st) * 8 - 8;
+	y = vid.height - sb_lines - 8;
+//	Draw_TileClear(x, y, strlen(st) * 8, 8);
+	Draw_String(x, y, st);
+}
+
+
+/*
+==============
+DrawPause
+==============
+*/
+void SCR_DrawPause (void)
+{
+	qpic_t  *pic;
+
+	if (!scr_showpause.value)               // turn off for screenshots
+		return;
+
+	if (!cl.paused)
+		return;
+
+	pic = Draw_CachePic ("gfx/pause.lmp");
+	Draw_Pic ( (vid.width - pic->width)/2, 
+		(vid.height - 48 - pic->height)/2, pic);
+}
+
+
+
+/*
+==============
+SCR_DrawLoading
+==============
+*/
+void SCR_DrawLoading (void)
+{
+	qpic_t  *pic;
+
+	if (!scr_drawloading)
+		return;
+		
+	pic = Draw_CachePic ("gfx/loading.lmp");
+	Draw_Pic ( (vid.width - pic->width)/2, 
+		(vid.height - 48 - pic->height)/2, pic);
+}
+
+
+
+//=============================================================================
+
+
+/*
+==================
+SCR_SetUpToDrawConsole
+==================
+*/
+void SCR_SetUpToDrawConsole (void)
+{
+	Con_CheckResize ();
+	
+	if (scr_drawloading)
+		return;         // never a console with loading plaque
+		
+// decide on the height of the console
+	if (cls.state != ca_active)
+	{
+		scr_conlines = vid.height;              // full screen
+		scr_con_current = scr_conlines;
+	}
+	else if (key_dest == key_console)
+		scr_conlines = vid.height/2;    // half screen
+	else
+		scr_conlines = 0;                               // none visible
+	
+	if (scr_conlines < scr_con_current)
+	{
+		scr_con_current -= scr_conspeed.value*host_frametime;
+		if (scr_conlines > scr_con_current)
+			scr_con_current = scr_conlines;
+
+	}
+	else if (scr_conlines > scr_con_current)
+	{
+		scr_con_current += scr_conspeed.value*host_frametime;
+		if (scr_conlines < scr_con_current)
+			scr_con_current = scr_conlines;
+	}
+
+	if (clearconsole++ < vid.numpages)
+	{
+		Sbar_Changed ();
+	}
+	else if (clearnotify++ < vid.numpages)
+	{
+	}
+	else
+		con_notifylines = 0;
+}
+	
+/*
+==================
+SCR_DrawConsole
+==================
+*/
+void SCR_DrawConsole (void)
+{
+	if (scr_con_current)
+	{
+		scr_copyeverything = 1;
+		Con_DrawConsole (scr_con_current);
+		clearconsole = 0;
+	}
+	else
+	{
+		if (key_dest == key_game || key_dest == key_message)
+			Con_DrawNotify ();      // only draw notify in game
+	}
+}
+
+
+/* 
+============================================================================== 
+ 
+						SCREEN SHOTS 
+ 
+============================================================================== 
+*/ 
+
+typedef struct _TargaHeader {
+	unsigned char   id_length, colormap_type, image_type;
+	unsigned short  colormap_index, colormap_length;
+	unsigned char   colormap_size;
+	unsigned short  x_origin, y_origin, width, height;
+	unsigned char   pixel_size, attributes;
+} TargaHeader;
+
+
+/* 
+================== 
+SCR_ScreenShot_f
+================== 
+*/  
+void SCR_ScreenShot_f (void) 
+{
+	byte            *buffer;
+	char            pcxname[80]; 
+	char            checkname[MAX_OSPATH];
+	int                     i, c, temp;
+// 
+// find a file name to save it to 
+// 
+	strcpy(pcxname,"quake00.tga");
+		
+	for (i=0 ; i<=99 ; i++) 
+	{ 
+		pcxname[5] = i/10 + '0'; 
+		pcxname[6] = i%10 + '0'; 
+		sprintf (checkname, "%s/%s", com_gamedir, pcxname);
+		if (Sys_FileTime(checkname) == -1)
+			break;  // file doesn't exist
+	} 
+	if (i==100) 
+	{
+		Con_Printf ("SCR_ScreenShot_f: Couldn't create a PCX file\n"); 
+		return;
+	}
+
+
+	buffer = malloc(glwidth*glheight*3 + 18);
+	memset (buffer, 0, 18);
+	buffer[2] = 2;          // uncompressed type
+	buffer[12] = glwidth&255;
+	buffer[13] = glwidth>>8;
+	buffer[14] = glheight&255;
+	buffer[15] = glheight>>8;
+	buffer[16] = 24;        // pixel size
+
+	glReadPixels (glx, gly, glwidth, glheight, GL_RGB, GL_UNSIGNED_BYTE, buffer+18 ); 
+
+	// swap rgb to bgr
+	c = 18+glwidth*glheight*3;
+	for (i=18 ; i<c ; i+=3)
+	{
+		temp = buffer[i];
+		buffer[i] = buffer[i+2];
+		buffer[i+2] = temp;
+	}
+	COM_WriteFile (pcxname, buffer, glwidth*glheight*3 + 18 );
+
+	free (buffer);
+	Con_Printf ("Wrote %s\n", pcxname);
+} 
+
+/* 
+============== 
+WritePCXfile 
+============== 
+*/ 
+void WritePCXfile (char *filename, byte *data, int width, int height,
+	int rowbytes, byte *palette, qboolean upload) 
+{
+	int		i, j, length;
+	pcx_t	*pcx;
+	byte		*pack;
+	  
+	pcx = Hunk_TempAlloc (width*height*2+1000);
+	if (pcx == NULL)
+	{
+		Con_Printf("SCR_ScreenShot_f: not enough memory\n");
+		return;
+	} 
+ 
+	pcx->manufacturer = 0x0a;	// PCX id
+	pcx->version = 5;			// 256 color
+ 	pcx->encoding = 1;		// uncompressed
+	pcx->bits_per_pixel = 8;		// 256 color
+	pcx->xmin = 0;
+	pcx->ymin = 0;
+	pcx->xmax = LittleShort((short)(width-1));
+	pcx->ymax = LittleShort((short)(height-1));
+	pcx->hres = LittleShort((short)width);
+	pcx->vres = LittleShort((short)height);
+	Q_memset (pcx->palette,0,sizeof(pcx->palette));
+	pcx->color_planes = 1;		// chunky image
+	pcx->bytes_per_line = LittleShort((short)width);
+	pcx->palette_type = LittleShort(2);		// not a grey scale
+	Q_memset (pcx->filler,0,sizeof(pcx->filler));
+
+// pack the image
+	pack = &pcx->data;
+
+	data += rowbytes * (height - 1);
+
+	for (i=0 ; i<height ; i++)
+	{
+		for (j=0 ; j<width ; j++)
+		{
+			if ( (*data & 0xc0) != 0xc0)
+				*pack++ = *data++;
+			else
+			{
+				*pack++ = 0xc1;
+				*pack++ = *data++;
+			}
+		}
+
+		data += rowbytes - width;
+		data -= rowbytes * 2;
+	}
+			
+// write the palette
+	*pack++ = 0x0c;	// palette ID byte
+	for (i=0 ; i<768 ; i++)
+		*pack++ = *palette++;
+		
+// write output file 
+	length = pack - (byte *)pcx;
+
+	if (upload)
+		CL_StartUpload((void *)pcx, length);
+	else
+		COM_WriteFile (filename, pcx, length);
+} 
+ 
+
+
+/*
+Find closest color in the palette for named color
+*/
+int MipColor(int r, int g, int b)
+{
+	int i;
+	float dist;
+	int best;
+	float bestdist;
+	int r1, g1, b1;
+	static int lr = -1, lg = -1, lb = -1;
+	static int lastbest;
+
+	if (r == lr && g == lg && b == lb)
+		return lastbest;
+
+	bestdist = 256*256*3;
+
+	for (i = 0; i < 256; i++) {
+		r1 = host_basepal[i*3] - r;
+		g1 = host_basepal[i*3+1] - g;
+		b1 = host_basepal[i*3+2] - b;
+		dist = r1*r1 + g1*g1 + b1*b1;
+		if (dist < bestdist) {
+			bestdist = dist;
+			best = i;
+		}
+	}
+	lr = r; lg = g; lb = b;
+	lastbest = best;
+	return best;
+}
+
+// from gl_draw.c
+byte		*draw_chars;				// 8*8 graphic characters
+
+void SCR_DrawCharToSnap (int num, byte *dest, int width)
+{
+	int		row, col;
+	byte	*source;
+	int		drawline;
+	int		x;
+
+	row = num>>4;
+	col = num&15;
+	source = draw_chars + (row<<10) + (col<<3);
+
+	drawline = 8;
+
+	while (drawline--)
+	{
+		for (x=0 ; x<8 ; x++)
+			if (source[x])
+				dest[x] = source[x];
+			else
+				dest[x] = 98;
+		source += 128;
+		dest -= width;
+	}
+
+}
+
+void SCR_DrawStringToSnap (const char *s, byte *buf, int x, int y, int width)
+{
+	byte *dest;
+	const unsigned char *p;
+
+	dest = buf + ((y * width) + x);
+
+	p = (const unsigned char *)s;
+	while (*p) {
+		SCR_DrawCharToSnap(*p++, dest, width);
+		dest += 8;
+	}
+}
+
+
+/* 
+================== 
+SCR_RSShot_f
+================== 
+*/  
+void SCR_RSShot_f (void) 
+{ 
+	int     i, x, y;
+	unsigned char		*src, *dest;
+	char		pcxname[80]; 
+	char		checkname[MAX_OSPATH];
+	unsigned char		*newbuf, *srcbuf;
+	int srcrowbytes;
+	int w, h;
+	int dx, dy, dex, dey, nx;
+	int r, b, g;
+	int count;
+	float fracw, frach;
+	char st[80];
+	time_t now;
+
+	if (CL_IsUploading())
+		return; // already one pending
+
+	if (cls.state < ca_onserver)
+		return; // gotta be connected
+
+	Con_Printf("Remote screen shot requested.\n");
+
+#if 0
+// 
+// find a file name to save it to 
+// 
+	strcpy(pcxname,"mquake00.pcx");
+		
+	for (i=0 ; i<=99 ; i++) 
+	{ 
+		pcxname[6] = i/10 + '0'; 
+		pcxname[7] = i%10 + '0'; 
+		sprintf (checkname, "%s/%s", com_gamedir, pcxname);
+		if (Sys_FileTime(checkname) == -1)
+			break;	// file doesn't exist
+	} 
+	if (i==100) 
+	{
+		Con_Printf ("SCR_ScreenShot_f: Couldn't create a PCX"); 
+		return;
+	}
+#endif
+ 
+// 
+// save the pcx file 
+// 
+	newbuf = malloc(glheight * glwidth * 3);
+
+	glReadPixels (glx, gly, glwidth, glheight, GL_RGB, GL_UNSIGNED_BYTE, newbuf ); 
+
+	w = (vid.width < RSSHOT_WIDTH) ? glwidth : RSSHOT_WIDTH;
+	h = (vid.height < RSSHOT_HEIGHT) ? glheight : RSSHOT_HEIGHT;
+
+	fracw = (float)glwidth / (float)w;
+	frach = (float)glheight / (float)h;
+
+	for (y = 0; y < h; y++) {
+		dest = newbuf + (w*3 * y);
+
+		for (x = 0; x < w; x++) {
+			r = g = b = 0;
+
+			dx = x * fracw;
+			dex = (x + 1) * fracw;
+			if (dex == dx) dex++; // at least one
+			dy = y * frach;
+			dey = (y + 1) * frach;
+			if (dey == dy) dey++; // at least one
+
+			count = 0;
+			for (/* */; dy < dey; dy++) {
+				src = newbuf + (glwidth * 3 * dy) + dx * 3;
+				for (nx = dx; nx < dex; nx++) {
+					r += *src++;
+					g += *src++;
+					b += *src++;
+					count++;
+				}
+			}
+			r /= count;
+			g /= count;
+			b /= count;
+			*dest++ = r;
+			*dest++ = b;
+			*dest++ = g;
+		}
+	}
+
+	// convert to eight bit
+	for (y = 0; y < h; y++) {
+		src = newbuf + (w * 3 * y);
+		dest = newbuf + (w * y);
+
+		for (x = 0; x < w; x++) {
+			*dest++ = MipColor(src[0], src[1], src[2]);
+			src += 3;
+		}
+	}
+
+	time(&now);
+	strcpy(st, ctime(&now));
+	st[strlen(st) - 1] = 0;
+	SCR_DrawStringToSnap (st, newbuf, w - strlen(st)*8, h - 1, w);
+
+	strncpy(st, cls.servername, sizeof(st));
+	st[sizeof(st) - 1] = 0;
+	SCR_DrawStringToSnap (st, newbuf, w - strlen(st)*8, h - 11, w);
+
+	strncpy(st, name.string, sizeof(st));
+	st[sizeof(st) - 1] = 0;
+	SCR_DrawStringToSnap (st, newbuf, w - strlen(st)*8, h - 21, w);
+
+	WritePCXfile (pcxname, newbuf, w, h, w, host_basepal, true);
+
+	free(newbuf);
+
+	Con_Printf ("Wrote %s\n", pcxname);
+} 
+
+
+
+
+//=============================================================================
+
+
+//=============================================================================
+
+char    *scr_notifystring;
+qboolean        scr_drawdialog;
+
+void SCR_DrawNotifyString (void)
+{
+	char    *start;
+	int             l;
+	int             j;
+	int             x, y;
+
+	start = scr_notifystring;
+
+	y = vid.height*0.35;
+
+	do      
+	{
+	// scan the width of the line
+		for (l=0 ; l<40 ; l++)
+			if (start[l] == '\n' || !start[l])
+				break;
+		x = (vid.width - l*8)/2;
+		for (j=0 ; j<l ; j++, x+=8)
+			Draw_Character (x, y, start[j]);        
+			
+		y += 8;
+
+		while (*start && *start != '\n')
+			start++;
+
+		if (!*start)
+			break;
+		start++;                // skip the \n
+	} while (1);
+}
+
+/*
+==================
+SCR_ModalMessage
+
+Displays a text string in the center of the screen and waits for a Y or N
+keypress.  
+==================
+*/
+int SCR_ModalMessage (char *text)
+{
+	scr_notifystring = text;
+ 
+// draw a fresh screen
+	scr_fullupdate = 0;
+	scr_drawdialog = true;
+	SCR_UpdateScreen ();
+	scr_drawdialog = false;
+	
+	S_ClearBuffer ();               // so dma doesn't loop current sound
+
+	do
+	{
+		key_count = -1;         // wait for a key down and up
+		Sys_SendKeyEvents ();
+	} while (key_lastpress != 'y' && key_lastpress != 'n' && key_lastpress != K_ESCAPE);
+
+	scr_fullupdate = 0;
+	SCR_UpdateScreen ();
+
+	return key_lastpress == 'y';
+}
+
+
+//=============================================================================
+
+/*
+===============
+SCR_BringDownConsole
+
+Brings the console down and fades the palettes back to normal
+================
+*/
+void SCR_BringDownConsole (void)
+{
+	int             i;
+	
+	scr_centertime_off = 0;
+	
+	for (i=0 ; i<20 && scr_conlines != scr_con_current ; i++)
+		SCR_UpdateScreen ();
+
+	cl.cshifts[0].percent = 0;              // no area contents palette on next frame
+	VID_SetPalette (host_basepal);
+}
+
+void SCR_TileClear (void)
+{
+	if (r_refdef.vrect.x > 0) {
+		// left
+		Draw_TileClear (0, 0, r_refdef.vrect.x, vid.height - sb_lines);
+		// right
+		Draw_TileClear (r_refdef.vrect.x + r_refdef.vrect.width, 0, 
+			vid.width - r_refdef.vrect.x + r_refdef.vrect.width, 
+			vid.height - sb_lines);
+	}
+	if (r_refdef.vrect.y > 0) {
+		// top
+		Draw_TileClear (r_refdef.vrect.x, 0, 
+			r_refdef.vrect.x + r_refdef.vrect.width, 
+			r_refdef.vrect.y);
+		// bottom
+		Draw_TileClear (r_refdef.vrect.x,
+			r_refdef.vrect.y + r_refdef.vrect.height, 
+			r_refdef.vrect.width, 
+			vid.height - sb_lines - 
+			(r_refdef.vrect.height + r_refdef.vrect.y));
+	}
+}
+
+float oldsbar = 0;
+
+/*
+==================
+SCR_UpdateScreen
+
+This is called every frame, and can also be called explicitly to flush
+text to the screen.
+
+WARNING: be very careful calling this from elsewhere, because the refresh
+needs almost the entire 256k of stack space!
+==================
+*/
+void SCR_UpdateScreen (void)
+{
+	if (block_drawing)
+		return;
+
+	vid.numpages = 2 + gl_triplebuffer.value;
+
+	scr_copytop = 0;
+	scr_copyeverything = 0;
+
+	if (scr_disabled_for_loading)
+	{
+		if (realtime - scr_disabled_time > 60)
+		{
+			scr_disabled_for_loading = false;
+			Con_Printf ("load failed.\n");
+		}
+		else
+			return;
+	}
+
+	if (!scr_initialized || !con_initialized)
+		return;                         // not initialized yet
+
+
+	if (oldsbar != cl_sbar.value) {
+		oldsbar = cl_sbar.value;
+		vid.recalc_refdef = true;
+	}
+
+	GL_BeginRendering (&glx, &gly, &glwidth, &glheight);
+	
+	//
+	// determine size of refresh window
+	//
+	if (oldfov != scr_fov.value)
+	{
+		oldfov = scr_fov.value;
+		vid.recalc_refdef = true;
+	}
+
+	if (vid.recalc_refdef)
+		SCR_CalcRefdef ();
+
+//
+// do 3D refresh drawing, and then update the screen
+//
+	SCR_SetUpToDrawConsole ();
+	
+	V_RenderView ();
+
+	GL_Set2D ();
+
+	//
+	// draw any areas not covered by the refresh
+	//
+	SCR_TileClear ();
+
+	if (r_netgraph.value)
+		R_NetGraph ();
+
+	if (scr_drawdialog)
+	{
+		Sbar_Draw ();
+		Draw_FadeScreen ();
+		SCR_DrawNotifyString ();
+		scr_copyeverything = true;
+	}
+	else if (scr_drawloading)
+	{
+		SCR_DrawLoading ();
+		Sbar_Draw ();
+	}
+	else if (cl.intermission == 1 && key_dest == key_game)
+	{
+		Sbar_IntermissionOverlay ();
+	}
+	else if (cl.intermission == 2 && key_dest == key_game)
+	{
+		Sbar_FinaleOverlay ();
+		SCR_CheckDrawCenterString ();
+	}
+	else
+	{
+		if (crosshair.value)
+			Draw_Crosshair();
+		
+		SCR_DrawRam ();
+		SCR_DrawNet ();
+		SCR_DrawFPS ();
+		SCR_DrawTurtle ();
+		SCR_DrawPause ();
+		SCR_CheckDrawCenterString ();
+		Sbar_Draw ();
+		SCR_DrawConsole ();     
+		M_Draw ();
+	}
+
+	V_UpdatePalette ();
+
+	GL_EndRendering ();
+}
--- /dev/null
+++ b/QW/client/gl_test.c
@@ -1,0 +1,182 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+
+#include "quakedef.h"
+
+#ifdef GLTEST
+
+typedef struct
+{
+	plane_t	*plane;
+	vec3_t	origin;
+	vec3_t	normal;
+	vec3_t	up;
+	vec3_t	right;
+	vec3_t	reflect;
+	float	length;
+} puff_t;
+
+#define	MAX_PUFFS	64
+
+puff_t	puffs[MAX_PUFFS];
+
+
+void Test_Init (void)
+{
+}
+
+
+
+plane_t	junk;
+plane_t	*HitPlane (vec3_t start, vec3_t end)
+{
+	trace_t		trace;
+
+// fill in a default trace
+	memset (&trace, 0, sizeof(trace_t));
+	trace.fraction = 1;
+	trace.allsolid = true;
+	VectorCopy (end, trace.endpos);
+
+	SV_RecursiveHullCheck (cl.worldmodel->hulls, 0, 0, 1, start, end, &trace);
+
+	junk = trace.plane;
+	return &junk;
+}
+
+void Test_Spawn (vec3_t origin)
+{
+	int		i;
+	puff_t	*p;
+	vec3_t	temp;
+	vec3_t	normal;
+	vec3_t	incoming;
+	plane_t	*plane;
+	float	d;
+
+	for (i=0,p=puffs ; i<MAX_PUFFS ; i++,p++)
+	{
+		if (p->length <= 0)
+			break;
+	}
+	if (i == MAX_PUFFS)
+		return;
+
+	VectorSubtract (r_refdef.vieworg, origin, incoming);
+	VectorSubtract (origin, incoming, temp);
+	plane = HitPlane (r_refdef.vieworg, temp);
+
+	VectorNormalize (incoming);
+	d = DotProduct (incoming, plane->normal);
+	VectorSubtract (vec3_origin, incoming, p->reflect);
+	VectorMA (p->reflect, d*2, plane->normal, p->reflect);
+
+	VectorCopy (origin, p->origin);
+	VectorCopy (plane->normal, p->normal);
+
+	CrossProduct (incoming, p->normal, p->up);
+
+	CrossProduct (p->up, p->normal, p->right);
+
+	p->length = 8;
+}
+
+void DrawPuff (puff_t *p)
+{
+	vec3_t	pts[2][3];
+	int		i, j;
+	float	s, d;
+
+	for (i=0 ; i<2 ; i++)
+	{
+		if (i == 1)
+		{
+			s = 6;
+			d = p->length;
+		}
+		else
+		{
+			s = 2;
+			d = 0;
+		}
+
+		for (j=0 ; j<3 ; j++)
+		{
+			pts[i][0][j] = p->origin[j] + p->up[j]*s + p->reflect[j]*d;
+			pts[i][1][j] = p->origin[j] + p->right[j]*s + p->reflect[j]*d;
+			pts[i][2][j] = p->origin[j] + -p->right[j]*s + p->reflect[j]*d;
+		}
+	}
+
+	glColor3f (1, 0, 0);
+
+#if 0
+	glBegin (GL_LINES);
+	glVertex3fv (p->origin);
+	glVertex3f (p->origin[0] + p->length*p->reflect[0],
+		p->origin[1] + p->length*p->reflect[1],
+		p->origin[2] + p->length*p->reflect[2]);
+
+	glVertex3fv (pts[0][0]);
+	glVertex3fv (pts[1][0]);
+
+	glVertex3fv (pts[0][1]);
+	glVertex3fv (pts[1][1]);
+
+	glVertex3fv (pts[0][2]);
+	glVertex3fv (pts[1][2]);
+
+	glEnd ();
+#endif
+
+	glBegin (GL_QUADS);
+	for (i=0 ; i<3 ; i++)
+	{
+		j = (i+1)%3;
+		glVertex3fv (pts[0][j]);
+		glVertex3fv (pts[1][j]);
+		glVertex3fv (pts[1][i]);
+		glVertex3fv (pts[0][i]);
+	}
+	glEnd ();
+
+	glBegin (GL_TRIANGLES);
+	glVertex3fv (pts[1][0]);
+	glVertex3fv (pts[1][1]);
+	glVertex3fv (pts[1][2]);
+	glEnd ();
+
+	p->length -= host_frametime*2;
+}
+
+
+void Test_Draw (void)
+{
+	int		i;
+	puff_t	*p;
+
+	for (i=0, p=puffs ; i<MAX_PUFFS ; i++,p++)
+	{
+		if (p->length > 0)
+			DrawPuff (p);
+	}
+}
+
+#endif
--- /dev/null
+++ b/QW/client/gl_vidlinux.c
@@ -1,0 +1,816 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+#include <termios.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/vt.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <signal.h>
+
+#include <asm/io.h>
+
+#include "vga.h"
+#include "vgakeyboard.h"
+#include "vgamouse.h"
+
+#include "quakedef.h"
+#include "GL/fxmesa.h"
+
+#define WARP_WIDTH              320
+#define WARP_HEIGHT             200
+
+static fxMesaContext fc = NULL;
+#define stringify(m) { #m, m }
+
+unsigned short	d_8to16table[256];
+unsigned	d_8to24table[256];
+unsigned char d_15to8table[65536];
+
+int num_shades=32;
+
+struct
+{
+	char *name;
+	int num;
+} mice[] =
+{
+	stringify(MOUSE_MICROSOFT),
+	stringify(MOUSE_MOUSESYSTEMS),
+	stringify(MOUSE_MMSERIES),
+	stringify(MOUSE_LOGITECH),
+	stringify(MOUSE_BUSMOUSE),
+	stringify(MOUSE_PS2),
+};
+
+static unsigned char scantokey[128];
+
+int num_mice = sizeof (mice) / sizeof(mice[0]);
+
+int	d_con_indirect = 0;
+
+int		svgalib_inited=0;
+int		UseMouse = 1;
+int		UseKeyboard = 1;
+
+int		mouserate = MOUSE_DEFAULTSAMPLERATE;
+
+cvar_t	_windowed_mouse = {"_windowed_mouse","0", true};
+
+cvar_t		vid_mode = {"vid_mode","5",false};
+cvar_t		vid_redrawfull = {"vid_redrawfull","0",false};
+cvar_t		vid_waitforrefresh = {"vid_waitforrefresh","0",true};
+ 
+char	*framebuffer_ptr;
+
+cvar_t  mouse_button_commands[3] =
+{
+    {"mouse1","+attack"},
+    {"mouse2","+strafe"},
+    {"mouse3","+forward"},
+};
+
+int     mouse_buttons;
+int     mouse_buttonstate;
+int     mouse_oldbuttonstate;
+float   mouse_x, mouse_y;
+float	old_mouse_x, old_mouse_y;
+int		mx, my;
+
+cvar_t	m_filter = {"m_filter","1"};
+
+int scr_width, scr_height;
+
+/*-----------------------------------------------------------------------*/
+
+//int		texture_mode = GL_NEAREST;
+//int		texture_mode = GL_NEAREST_MIPMAP_NEAREST;
+//int		texture_mode = GL_NEAREST_MIPMAP_LINEAR;
+int		texture_mode = GL_LINEAR;
+//int		texture_mode = GL_LINEAR_MIPMAP_NEAREST;
+//int		texture_mode = GL_LINEAR_MIPMAP_LINEAR;
+
+int		texture_extension_number = 1;
+
+float		gldepthmin, gldepthmax;
+
+cvar_t	gl_ztrick = {"gl_ztrick","1"};
+
+const char *gl_vendor;
+const char *gl_renderer;
+const char *gl_version;
+const char *gl_extensions;
+
+qboolean is8bit = false;
+qboolean isPermedia = false;
+qboolean gl_mtexable = false;
+
+/*-----------------------------------------------------------------------*/
+void D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height)
+{
+}
+
+void D_EndDirectRect (int x, int y, int width, int height)
+{
+}
+
+int matchmouse(int mouse, char *name)
+{
+	int i;
+	for (i=0 ; i<num_mice ; i++)
+		if (!strcmp(mice[i].name, name))
+			return i;
+	return mouse;
+}
+
+#if 0
+
+void vtswitch(int newconsole)
+{
+
+	int fd;
+	struct vt_stat x;
+
+// switch consoles and wait until reactivated
+	fd = open("/dev/console", O_RDONLY);
+	ioctl(fd, VT_GETSTATE, &x);
+	ioctl(fd, VT_ACTIVATE, newconsole);
+	ioctl(fd, VT_WAITACTIVE, x.v_active);
+	close(fd);
+
+}
+
+#endif
+
+void keyhandler(int scancode, int state)
+{
+	
+	int sc;
+
+	sc = scancode & 0x7f;
+
+	Key_Event(scantokey[sc], state == KEY_EVENTPRESS);
+
+}
+
+void VID_Shutdown(void)
+{
+	if (!fc)
+		return;
+
+	fxMesaDestroyContext(fc);
+
+	if (UseKeyboard)
+		keyboard_close();
+}
+
+void signal_handler(int sig)
+{
+	printf("Received signal %d, exiting...\n", sig);
+	Sys_Quit();
+	exit(0);
+}
+
+void InitSig(void)
+{
+	signal(SIGHUP, signal_handler);
+	signal(SIGINT, signal_handler);
+	signal(SIGQUIT, signal_handler);
+	signal(SIGILL, signal_handler);
+	signal(SIGTRAP, signal_handler);
+	signal(SIGIOT, signal_handler);
+	signal(SIGBUS, signal_handler);
+	signal(SIGFPE, signal_handler);
+	signal(SIGSEGV, signal_handler);
+	signal(SIGTERM, signal_handler);
+}
+
+void VID_ShiftPalette(unsigned char *p)
+{
+//	VID_SetPalette(p);
+}
+
+void	VID_SetPalette (unsigned char *palette)
+{
+	byte	*pal;
+	unsigned r,g,b;
+	unsigned v;
+	int     r1,g1,b1;
+	int		k;
+	unsigned short i;
+	unsigned	*table;
+	FILE *f;
+	char s[255];
+	float dist, bestdist;
+	static qboolean palflag = false;
+
+//
+// 8 8 8 encoding
+//
+	Con_Printf("Converting 8to24\n");
+
+	pal = palette;
+	table = d_8to24table;
+	for (i=0 ; i<256 ; i++)
+	{
+		r = pal[0];
+		g = pal[1];
+		b = pal[2];
+		pal += 3;
+		
+//		v = (255<<24) + (r<<16) + (g<<8) + (b<<0);
+//		v = (255<<0) + (r<<8) + (g<<16) + (b<<24);
+		v = (255<<24) + (r<<0) + (g<<8) + (b<<16);
+		*table++ = v;
+	}
+	d_8to24table[255] &= 0xffffff;	// 255 is transparent
+
+	// JACK: 3D distance calcs - k is last closest, l is the distance.
+	// FIXME: Precalculate this and cache to disk.
+	if (palflag)
+		return;
+	palflag = true;
+
+	COM_FOpenFile("glquake/15to8.pal", &f);
+	if (f) {
+		fread(d_15to8table, 1<<15, 1, f);
+		fclose(f);
+	} else {
+		for (i=0; i < (1<<15); i++) {
+			/* Maps
+ 			000000000000000
+ 			000000000011111 = Red  = 0x1F
+ 			000001111100000 = Blue = 0x03E0
+ 			111110000000000 = Grn  = 0x7C00
+ 			*/
+ 			r = ((i & 0x1F) << 3)+4;
+ 			g = ((i & 0x03E0) >> 2)+4;
+ 			b = ((i & 0x7C00) >> 7)+4;
+			pal = (unsigned char *)d_8to24table;
+			for (v=0,k=0,bestdist=10000.0; v<256; v++,pal+=4) {
+ 				r1 = (int)r - (int)pal[0];
+ 				g1 = (int)g - (int)pal[1];
+ 				b1 = (int)b - (int)pal[2];
+				dist = sqrt(((r1*r1)+(g1*g1)+(b1*b1)));
+				if (dist < bestdist) {
+					k=v;
+					bestdist = dist;
+				}
+			}
+			d_15to8table[i]=k;
+		}
+		sprintf(s, "%s/glquake", com_gamedir);
+ 		Sys_mkdir (s);
+		sprintf(s, "%s/glquake/15to8.pal", com_gamedir);
+		if ((f = fopen(s, "wb")) != NULL) {
+			fwrite(d_15to8table, 1<<15, 1, f);
+			fclose(f);
+		}
+	}
+}
+
+/*
+===============
+GL_Init
+===============
+*/
+void GL_Init (void)
+{
+	gl_vendor = glGetString (GL_VENDOR);
+	Con_Printf ("GL_VENDOR: %s\n", gl_vendor);
+	gl_renderer = glGetString (GL_RENDERER);
+	Con_Printf ("GL_RENDERER: %s\n", gl_renderer);
+
+	gl_version = glGetString (GL_VERSION);
+	Con_Printf ("GL_VERSION: %s\n", gl_version);
+	gl_extensions = glGetString (GL_EXTENSIONS);
+	Con_Printf ("GL_EXTENSIONS: %s\n", gl_extensions);
+
+//	Con_Printf ("%s %s\n", gl_renderer, gl_version);
+
+	glClearColor (1,0,0,0);
+	glCullFace(GL_FRONT);
+	glEnable(GL_TEXTURE_2D);
+
+	glEnable(GL_ALPHA_TEST);
+	glAlphaFunc(GL_GREATER, 0.666);
+
+	glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
+	glShadeModel (GL_FLAT);
+
+	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+
+	glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+//	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+}
+
+/*
+=================
+GL_BeginRendering
+
+=================
+*/
+void GL_BeginRendering (int *x, int *y, int *width, int *height)
+{
+	extern cvar_t gl_clear;
+
+	*x = *y = 0;
+	*width = scr_width;
+	*height = scr_height;
+
+//    if (!wglMakeCurrent( maindc, baseRC ))
+//		Sys_Error ("wglMakeCurrent failed");
+
+//	glViewport (*x, *y, *width, *height);
+}
+
+
+void GL_EndRendering (void)
+{
+	glFlush();
+	fxMesaSwapBuffers();
+}
+
+void Init_KBD(void)
+{
+	int i;
+
+	if (COM_CheckParm("-nokbd")) UseKeyboard = 0;
+
+	if (UseKeyboard)
+	{
+		for (i=0 ; i<128 ; i++)
+			scantokey[i] = ' ';
+
+		scantokey[42] = K_SHIFT;
+		scantokey[54] = K_SHIFT;
+		scantokey[72] = K_UPARROW;
+		scantokey[103] = K_UPARROW;
+		scantokey[80] = K_DOWNARROW;
+		scantokey[108] = K_DOWNARROW;
+		scantokey[75] = K_LEFTARROW;
+		scantokey[105] = K_LEFTARROW;
+		scantokey[77] = K_RIGHTARROW;
+		scantokey[106] = K_RIGHTARROW;
+		scantokey[29] = K_CTRL;
+		scantokey[97] = K_CTRL;
+		scantokey[56] = K_ALT;
+		scantokey[100] = K_ALT;
+//		scantokey[58] = JK_CAPS;
+//		scantokey[69] = JK_NUM_LOCK;
+		scantokey[71] = K_HOME;
+		scantokey[73] = K_PGUP;
+		scantokey[79] = K_END;
+		scantokey[81] = K_PGDN;
+		scantokey[82] = K_INS;
+		scantokey[83] = K_DEL;
+		scantokey[1 ] = K_ESCAPE;
+		scantokey[28] = K_ENTER;
+		scantokey[15] = K_TAB;
+		scantokey[14] = K_BACKSPACE;
+		scantokey[119] = K_PAUSE;
+		scantokey[57] = ' ';
+
+		scantokey[102] = K_HOME;
+		scantokey[104] = K_PGUP;
+		scantokey[107] = K_END;
+		scantokey[109] = K_PGDN;
+		scantokey[110] = K_INS;
+		scantokey[111] = K_DEL;
+
+		scantokey[2] = '1';
+		scantokey[3] = '2';
+		scantokey[4] = '3';
+		scantokey[5] = '4';
+		scantokey[6] = '5';
+		scantokey[7] = '6';
+		scantokey[8] = '7';
+		scantokey[9] = '8';
+		scantokey[10] = '9';
+		scantokey[11] = '0';
+		scantokey[12] = '-';
+		scantokey[13] = '=';
+		scantokey[41] = '`';
+		scantokey[26] = '[';
+		scantokey[27] = ']';
+		scantokey[39] = ';';
+		scantokey[40] = '\'';
+		scantokey[51] = ',';
+		scantokey[52] = '.';
+		scantokey[53] = '/';
+		scantokey[43] = '\\';
+
+		scantokey[59] = K_F1;
+		scantokey[60] = K_F2;
+		scantokey[61] = K_F3;
+		scantokey[62] = K_F4;
+		scantokey[63] = K_F5;
+		scantokey[64] = K_F6;
+		scantokey[65] = K_F7;
+		scantokey[66] = K_F8;
+		scantokey[67] = K_F9;
+		scantokey[68] = K_F10;
+		scantokey[87] = K_F11;
+		scantokey[88] = K_F12;
+		scantokey[30] = 'a';
+		scantokey[48] = 'b';
+		scantokey[46] = 'c';
+		scantokey[32] = 'd';       
+		scantokey[18] = 'e';       
+		scantokey[33] = 'f';       
+		scantokey[34] = 'g';       
+		scantokey[35] = 'h';       
+		scantokey[23] = 'i';       
+		scantokey[36] = 'j';       
+		scantokey[37] = 'k';       
+		scantokey[38] = 'l';       
+		scantokey[50] = 'm';       
+		scantokey[49] = 'n';       
+		scantokey[24] = 'o';       
+		scantokey[25] = 'p';       
+		scantokey[16] = 'q';       
+		scantokey[19] = 'r';       
+		scantokey[31] = 's';       
+		scantokey[20] = 't';       
+		scantokey[22] = 'u';       
+		scantokey[47] = 'v';       
+		scantokey[17] = 'w';       
+		scantokey[45] = 'x';       
+		scantokey[21] = 'y';       
+		scantokey[44] = 'z';       
+
+		scantokey[78] = '+';
+		scantokey[74] = '-';
+
+		if (keyboard_init())
+			Sys_Error("keyboard_init() failed");
+		keyboard_seteventhandler(keyhandler);
+	}
+}
+
+#define NUM_RESOLUTIONS 3
+
+static resolutions[NUM_RESOLUTIONS][3]={ 
+  { 512, 384, GR_RESOLUTION_512x384 },
+  { 640, 400, GR_RESOLUTION_640x400 },
+  { 640, 480, GR_RESOLUTION_640x480 }
+};
+
+int findres(int *width, int *height)
+{
+	int i;
+
+	for(i=0;i<NUM_RESOLUTIONS;i++)
+		if((*width<=resolutions[i][0]) && (*height<=resolutions[i][1])) {
+			*width = resolutions[i][0];
+			*height = resolutions[i][1];
+			return resolutions[i][2];
+		}
+        
+	*width = 640;
+	*height = 480;
+	return GR_RESOLUTION_640x480;
+}
+
+qboolean VID_Is8bit(void)
+{
+	return is8bit;
+}
+
+#ifdef GL_EXT_SHARED
+void VID_Init8bitPalette() 
+{
+	// Check for 8bit Extensions and initialize them.
+	int i;
+	char thePalette[256*3];
+	char *oldPalette, *newPalette;
+
+	if (strstr(gl_extensions, "GL_EXT_shared_texture_palette") == NULL)
+		return;
+
+	Con_SafePrintf("8-bit GL extensions enabled.\n");
+	glEnable( GL_SHARED_TEXTURE_PALETTE_EXT );
+	oldPalette = (char *) d_8to24table; //d_8to24table3dfx;
+	newPalette = thePalette;
+	for (i=0;i<256;i++) {
+		*newPalette++ = *oldPalette++;
+		*newPalette++ = *oldPalette++;
+		*newPalette++ = *oldPalette++;
+		oldPalette++;
+	}
+	glColorTableEXT(GL_SHARED_TEXTURE_PALETTE_EXT, GL_RGB, 256, GL_RGB, GL_UNSIGNED_BYTE, (void *) thePalette);
+	is8bit = true;
+}
+
+#else
+extern void gl3DfxSetPaletteEXT(GLuint *pal);
+
+void VID_Init8bitPalette(void) 
+{
+	// Check for 8bit Extensions and initialize them.
+	int i;
+	GLubyte table[256][4];
+	char *oldpal;
+
+	if (strstr(gl_extensions, "3DFX_set_global_palette") == NULL)
+		return;
+
+	Con_SafePrintf("8-bit GL extensions enabled.\n");
+	glEnable( GL_SHARED_TEXTURE_PALETTE_EXT );
+	oldpal = (char *) d_8to24table; //d_8to24table3dfx;
+	for (i=0;i<256;i++) {
+		table[i][2] = *oldpal++;
+		table[i][1] = *oldpal++;
+		table[i][0] = *oldpal++;
+		table[i][3] = 255;
+		oldpal++;
+	}
+	gl3DfxSetPaletteEXT((GLuint *)table);
+	is8bit = true;
+}
+#endif
+
+void VID_Init(unsigned char *palette)
+{
+	int i;
+	GLint attribs[32];
+	char	gldir[MAX_OSPATH];
+	int width = 640, height = 480;
+
+	S_Init();
+
+	Init_KBD();
+
+	Cvar_RegisterVariable (&vid_mode);
+	Cvar_RegisterVariable (&vid_redrawfull);
+	Cvar_RegisterVariable (&vid_waitforrefresh);
+	Cvar_RegisterVariable (&gl_ztrick);
+	
+        vid.maxwarpwidth = WARP_WIDTH;
+        vid.maxwarpheight = WARP_HEIGHT;
+        vid.colormap = host_colormap;
+        vid.fullbright = 256 - LittleLong (*((int *)vid.colormap + 2048));
+
+// interpret command-line params
+
+// set vid parameters
+	attribs[0] = FXMESA_DOUBLEBUFFER;
+	attribs[1] = FXMESA_ALPHA_SIZE;
+	attribs[2] = 1;
+	attribs[3] = FXMESA_DEPTH_SIZE;
+	attribs[4] = 1;
+	attribs[5] = FXMESA_NONE;
+
+	if ((i = COM_CheckParm("-width")) != 0)
+		width = atoi(com_argv[i+1]);
+	if ((i = COM_CheckParm("-height")) != 0)
+		height = atoi(com_argv[i+1]);
+
+	if ((i = COM_CheckParm("-conwidth")) != 0)
+		vid.conwidth = Q_atoi(com_argv[i+1]);
+	else
+		vid.conwidth = 640;
+
+	vid.conwidth &= 0xfff8; // make it a multiple of eight
+
+	if (vid.conwidth < 320)
+		vid.conwidth = 320;
+
+	// pick a conheight that matches with correct aspect
+	vid.conheight = vid.conwidth*3 / 4;
+
+	if ((i = COM_CheckParm("-conheight")) != 0)
+		vid.conheight = Q_atoi(com_argv[i+1]);
+	if (vid.conheight < 200)
+		vid.conheight = 200;
+
+	fc = fxMesaCreateContext(0, findres(&width, &height), GR_REFRESH_75Hz, 
+		attribs);
+	if (!fc)
+		Sys_Error("Unable to create 3DFX context.\n");
+
+	scr_width = width;
+	scr_height = height;
+
+	fxMesaMakeCurrent(fc);
+
+	if (vid.conheight > height)
+		vid.conheight = height;
+	if (vid.conwidth > width)
+		vid.conwidth = width;
+	vid.width = vid.conwidth;
+	vid.height = vid.conheight;
+
+	vid.aspect = ((float)vid.height / (float)vid.width) *
+				(320.0 / 240.0);
+	vid.numpages = 2;
+
+	InitSig(); // trap evil signals
+
+	GL_Init();
+
+	sprintf (gldir, "%s/glquake", com_gamedir);
+	Sys_mkdir (gldir);
+
+	VID_SetPalette(palette);
+
+	// Check for 3DFX Extensions and initialize them.
+	VID_Init8bitPalette();
+
+	Con_SafePrintf ("Video mode %dx%d initialized.\n", width, height);
+
+	vid.recalc_refdef = 1;				// force a surface cache flush
+}
+
+void Sys_SendKeyEvents(void)
+{
+	if (UseKeyboard)
+		while (keyboard_update());
+}
+
+void Force_CenterView_f (void)
+{
+	cl.viewangles[PITCH] = 0;
+}
+
+
+void mousehandler(int buttonstate, int dx, int dy)
+{
+	mouse_buttonstate = buttonstate;
+	mx += dx;
+	my += dy;
+}
+
+void IN_Init(void)
+{
+
+	int mtype;
+	char *mousedev;
+	int mouserate;
+
+	if (UseMouse)
+	{
+
+		Cvar_RegisterVariable (&mouse_button_commands[0]);
+		Cvar_RegisterVariable (&mouse_button_commands[1]);
+		Cvar_RegisterVariable (&mouse_button_commands[2]);
+		Cmd_AddCommand ("force_centerview", Force_CenterView_f);
+
+		mouse_buttons = 3;
+
+		mtype = vga_getmousetype();
+
+		mousedev = "/dev/mouse";
+		if (getenv("MOUSEDEV")) mousedev = getenv("MOUSEDEV");
+		if (COM_CheckParm("-mdev"))
+			mousedev = com_argv[COM_CheckParm("-mdev")+1];
+
+		mouserate = 1200;
+		if (getenv("MOUSERATE")) mouserate = atoi(getenv("MOUSERATE"));
+		if (COM_CheckParm("-mrate"))
+			mouserate = atoi(com_argv[COM_CheckParm("-mrate")+1]);
+
+		if (mouse_init(mousedev, mtype, mouserate))
+		{
+			Con_Printf("No mouse found\n");
+			UseMouse = 0;
+		}
+		else
+			mouse_seteventhandler(mousehandler);
+
+	}
+
+}
+
+void IN_Shutdown(void)
+{
+	if (UseMouse)
+		mouse_close();
+}
+
+/*
+===========
+IN_Commands
+===========
+*/
+void IN_Commands (void)
+{
+	if (UseMouse)
+	{
+		// poll mouse values
+		while (mouse_update())
+			;
+
+		// perform button actions
+		if ((mouse_buttonstate & MOUSE_LEFTBUTTON) &&
+			!(mouse_oldbuttonstate & MOUSE_LEFTBUTTON))
+			Key_Event (K_MOUSE1, true);
+		else if (!(mouse_buttonstate & MOUSE_LEFTBUTTON) &&
+			(mouse_oldbuttonstate & MOUSE_LEFTBUTTON))
+			Key_Event (K_MOUSE1, false);
+
+		if ((mouse_buttonstate & MOUSE_RIGHTBUTTON) &&
+			!(mouse_oldbuttonstate & MOUSE_RIGHTBUTTON))
+			Key_Event (K_MOUSE2, true);
+		else if (!(mouse_buttonstate & MOUSE_RIGHTBUTTON) &&
+			(mouse_oldbuttonstate & MOUSE_RIGHTBUTTON))
+			Key_Event (K_MOUSE2, false);
+
+		if ((mouse_buttonstate & MOUSE_MIDDLEBUTTON) &&
+			!(mouse_oldbuttonstate & MOUSE_MIDDLEBUTTON))
+			Key_Event (K_MOUSE3, true);
+		else if (!(mouse_buttonstate & MOUSE_MIDDLEBUTTON) &&
+			(mouse_oldbuttonstate & MOUSE_MIDDLEBUTTON))
+			Key_Event (K_MOUSE3, false);
+
+		mouse_oldbuttonstate = mouse_buttonstate;
+	}
+}
+
+/*
+===========
+IN_Move
+===========
+*/
+void IN_MouseMove (usercmd_t *cmd)
+{
+	if (!UseMouse)
+		return;
+
+	// poll mouse values
+	while (mouse_update())
+		;
+
+	if (m_filter.value)
+	{
+		mouse_x = (mx + old_mouse_x) * 0.5;
+		mouse_y = (my + old_mouse_y) * 0.5;
+	}
+	else
+	{
+		mouse_x = mx;
+		mouse_y = my;
+	}
+	old_mouse_x = mx;
+	old_mouse_y = my;
+	mx = my = 0; // clear for next update
+
+	mouse_x *= sensitivity.value;
+	mouse_y *= sensitivity.value;
+
+// add mouse X/Y movement to cmd
+	if ( (in_strafe.state & 1) || (lookstrafe.value && (in_mlook.state & 1) ))
+		cmd->sidemove += m_side.value * mouse_x;
+	else
+		cl.viewangles[YAW] -= m_yaw.value * mouse_x;
+	
+	if (in_mlook.state & 1)
+		V_StopPitchDrift ();
+		
+	if ( (in_mlook.state & 1) && !(in_strafe.state & 1))
+	{
+		cl.viewangles[PITCH] += m_pitch.value * mouse_y;
+		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 * mouse_y;
+		else
+			cmd->forwardmove -= m_forward.value * mouse_y;
+	}
+}
+
+void IN_Move (usercmd_t *cmd)
+{
+	IN_MouseMove(cmd);
+}
+
+void VID_UnlockBuffer() {}
+void VID_LockBuffer() {}
+
--- /dev/null
+++ b/QW/client/gl_vidlinux_svga.c
@@ -1,0 +1,855 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+#include <termios.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/vt.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <signal.h>
+
+#include <asm/io.h>
+
+/*#include "vga.h" */
+#include "vgakeyboard.h"
+#include "vgamouse.h"
+
+#include "quakedef.h"
+#include "GL/fxmesa.h"
+
+#define WARP_WIDTH              320
+#define WARP_HEIGHT             200
+
+static fxMesaContext fc = NULL;
+#define stringify(m) { #m, m }
+
+unsigned short	d_8to16table[256];
+unsigned	d_8to24table[256];
+unsigned char d_15to8table[65536];
+
+int num_shades=32;
+
+struct
+{
+	char *name;
+	int num;
+} mice[] =
+{
+	stringify(MOUSE_MICROSOFT),
+	stringify(MOUSE_MOUSESYSTEMS),
+	stringify(MOUSE_MMSERIES),
+	stringify(MOUSE_LOGITECH),
+	stringify(MOUSE_BUSMOUSE),
+	stringify(MOUSE_PS2),
+};
+
+static unsigned char scantokey[128];
+
+int num_mice = sizeof (mice) / sizeof(mice[0]);
+
+int	d_con_indirect = 0;
+
+int		svgalib_inited=0;
+int		UseMouse = 1;
+int		UseKeyboard = 1;
+
+int		mouserate = MOUSE_DEFAULTSAMPLERATE;
+
+cvar_t		vid_mode = {"vid_mode","5",false};
+cvar_t		vid_redrawfull = {"vid_redrawfull","0",false};
+cvar_t		vid_waitforrefresh = {"vid_waitforrefresh","0",true};
+ 
+char	*framebuffer_ptr;
+
+cvar_t  mouse_button_commands[3] =
+{
+    {"mouse1","+attack"},
+    {"mouse2","+strafe"},
+    {"mouse3","+forward"},
+};
+
+int     mouse_buttons;
+int     mouse_buttonstate;
+int     mouse_oldbuttonstate;
+float   mouse_x, mouse_y;
+float	old_mouse_x, old_mouse_y;
+int		mx, my;
+
+cvar_t _windowed_mouse = {"_windowed_mouse", "1", true};
+cvar_t	m_filter = {"m_filter","0"};
+
+int scr_width, scr_height;
+
+/*-----------------------------------------------------------------------*/
+
+//int		texture_mode = GL_NEAREST;
+//int		texture_mode = GL_NEAREST_MIPMAP_NEAREST;
+//int		texture_mode = GL_NEAREST_MIPMAP_LINEAR;
+int		texture_mode = GL_LINEAR;
+//int		texture_mode = GL_LINEAR_MIPMAP_NEAREST;
+//int		texture_mode = GL_LINEAR_MIPMAP_LINEAR;
+
+int		texture_extension_number = 1;
+
+float		gldepthmin, gldepthmax;
+
+cvar_t	gl_ztrick = {"gl_ztrick","1"};
+
+const char *gl_vendor;
+const char *gl_renderer;
+const char *gl_version;
+const char *gl_extensions;
+
+qboolean is8bit = false;
+qboolean isPermedia = false;
+qboolean gl_mtexable = false;
+
+/*-----------------------------------------------------------------------*/
+void D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height)
+{
+}
+
+void D_EndDirectRect (int x, int y, int width, int height)
+{
+}
+
+/*
+=================
+VID_Gamma_f
+
+Keybinding command
+=================
+*/
+void VID_Gamma_f (void)
+{
+	float	gamma, f, inf;
+	unsigned char	palette[768];
+	int		i;
+
+	if (Cmd_Argc () == 2)
+	{
+		gamma = Q_atof (Cmd_Argv(1));
+
+		for (i=0 ; i<768 ; i++)
+		{
+			f = pow ( (host_basepal[i]+1)/256.0 , gamma );
+			inf = f*255 + 0.5;
+			if (inf < 0)
+				inf = 0;
+			if (inf > 255)
+				inf = 255;
+			palette[i] = inf;
+		}
+
+		VID_SetPalette (palette);
+
+		vid.recalc_refdef = 1;				// force a surface cache flush
+	}
+}
+
+int matchmouse(int mouse, char *name)
+{
+	int i;
+	for (i=0 ; i<num_mice ; i++)
+		if (!strcmp(mice[i].name, name))
+			return i;
+	return mouse;
+}
+
+#if 0
+
+void vtswitch(int newconsole)
+{
+
+	int fd;
+	struct vt_stat x;
+
+// switch consoles and wait until reactivated
+	fd = open("/dev/console", O_RDONLY);
+	ioctl(fd, VT_GETSTATE, &x);
+	ioctl(fd, VT_ACTIVATE, newconsole);
+	ioctl(fd, VT_WAITACTIVE, x.v_active);
+	close(fd);
+
+}
+
+#endif
+
+void keyhandler(int scancode, int state)
+{
+	
+	int sc;
+
+	sc = scancode & 0x7f;
+//	Con_Printf("scancode=%x (%d%s)\n", scancode, sc, scancode&0x80?"+128":"");
+	Key_Event(scantokey[sc], state == KEY_EVENTPRESS);
+
+}
+
+void VID_Shutdown(void)
+{
+	if (!fc)
+		return;
+
+	fxMesaDestroyContext(fc);
+
+	if (UseKeyboard)
+		keyboard_close();
+}
+
+void signal_handler(int sig)
+{
+	printf("Received signal %d, exiting...\n", sig);
+	VID_Shutdown();
+	exit(0);
+}
+
+void InitSig(void)
+{
+	signal(SIGHUP, signal_handler);
+	signal(SIGQUIT, signal_handler);
+	signal(SIGILL, signal_handler);
+	signal(SIGTRAP, signal_handler);
+	signal(SIGIOT, signal_handler);
+	signal(SIGBUS, signal_handler);
+	signal(SIGFPE, signal_handler);
+	signal(SIGSEGV, signal_handler);
+	signal(SIGTERM, signal_handler);
+}
+
+void VID_ShiftPalette(unsigned char *p)
+{
+	VID_SetPalette(p);
+}
+
+void	VID_SetPalette (unsigned char *palette)
+{
+	byte	*pal;
+	unsigned short r,g,b;
+	int     v;
+	int     r1,g1,b1;
+	int		k;
+	unsigned short i;
+	unsigned	*table;
+	FILE *f;
+	char s[255];
+	float dist, bestdist;
+	static qboolean palflag = false;
+
+//
+// 8 8 8 encoding
+//
+	pal = palette;
+	table = d_8to24table;
+	for (i=0 ; i<256 ; i++)
+	{
+		r = pal[0];
+		g = pal[1];
+		b = pal[2];
+		pal += 3;
+		
+//		v = (255<<24) + (r<<16) + (g<<8) + (b<<0);
+//		v = (255<<0) + (r<<8) + (g<<16) + (b<<24);
+		v = (255<<24) + (r<<0) + (g<<8) + (b<<16);
+		*table++ = v;
+	}
+	d_8to24table[255] &= 0xffffff;	// 255 is transparent
+
+	// JACK: 3D distance calcs - k is last closest, l is the distance.
+	// FIXME: Precalculate this and cache to disk.
+	if (palflag)
+		return;
+	palflag = true;
+
+	COM_FOpenFile("glquake/15to8.pal", &f);
+	if (f) {
+		fread(d_15to8table, 1<<15, 1, f);
+		fclose(f);
+	} else {
+		for (i=0; i < (1<<15); i++) {
+			/* Maps
+ 			000000000000000
+ 			000000000011111 = Red  = 0x1F
+ 			000001111100000 = Blue = 0x03E0
+ 			111110000000000 = Grn  = 0x7C00
+ 			*/
+ 			r = ((i & 0x1F) << 3)+4;
+ 			g = ((i & 0x03E0) >> 2)+4;
+ 			b = ((i & 0x7C00) >> 7)+4;
+			pal = (unsigned char *)d_8to24table;
+			for (v=0,k=0,bestdist=10000.0; v<256; v++,pal+=4) {
+ 				r1 = (int)r - (int)pal[0];
+ 				g1 = (int)g - (int)pal[1];
+ 				b1 = (int)b - (int)pal[2];
+				dist = sqrt(((r1*r1)+(g1*g1)+(b1*b1)));
+				if (dist < bestdist) {
+					k=v;
+					bestdist = dist;
+				}
+			}
+			d_15to8table[i]=k;
+		}
+		sprintf(s, "%s/glquake", com_gamedir);
+ 		Sys_mkdir (s);
+		sprintf(s, "%s/glquake/15to8.pal", com_gamedir);
+		if ((f = fopen(s, "wb")) != NULL) {
+			fwrite(d_15to8table, 1<<15, 1, f);
+			fclose(f);
+		}
+	}
+}
+
+/*
+===============
+GL_Init
+===============
+*/
+void GL_Init (void)
+{
+	gl_vendor = glGetString (GL_VENDOR);
+	Con_Printf ("GL_VENDOR: %s\n", gl_vendor);
+	gl_renderer = glGetString (GL_RENDERER);
+	Con_Printf ("GL_RENDERER: %s\n", gl_renderer);
+
+	gl_version = glGetString (GL_VERSION);
+	Con_Printf ("GL_VERSION: %s\n", gl_version);
+	gl_extensions = glGetString (GL_EXTENSIONS);
+	Con_Printf ("GL_EXTENSIONS: %s\n", gl_extensions);
+
+//	Con_Printf ("%s %s\n", gl_renderer, gl_version);
+
+	glClearColor (1,0,0,0);
+	glCullFace(GL_FRONT);
+	glEnable(GL_TEXTURE_2D);
+
+	glEnable(GL_ALPHA_TEST);
+	glAlphaFunc(GL_GREATER, 0.666);
+
+	glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
+	glShadeModel (GL_FLAT);
+
+	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+
+	glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+//	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+}
+
+/*
+=================
+GL_BeginRendering
+
+=================
+*/
+void GL_BeginRendering (int *x, int *y, int *width, int *height)
+{
+	extern cvar_t gl_clear;
+
+	*x = *y = 0;
+	*width = scr_width;
+	*height = scr_height;
+
+//    if (!wglMakeCurrent( maindc, baseRC ))
+//		Sys_Error ("wglMakeCurrent failed");
+
+//	glViewport (*x, *y, *width, *height);
+}
+
+
+void GL_EndRendering (void)
+{
+	glFlush();
+	fxMesaSwapBuffers();
+}
+
+void Init_KBD(void)
+{
+	int i;
+
+	if (COM_CheckParm("-nokbd")) UseKeyboard = 0;
+
+	if (UseKeyboard)
+	{
+		for (i=0 ; i<128 ; i++)
+			scantokey[i] = ' ';
+
+		scantokey[  1] = K_ESCAPE;
+		scantokey[  2] = '1';
+		scantokey[  3] = '2';
+		scantokey[  4] = '3';
+		scantokey[  5] = '4';
+		scantokey[  6] = '5';
+		scantokey[  7] = '6';
+		scantokey[  8] = '7';
+		scantokey[  9] = '8';
+		scantokey[ 10] = '9';
+		scantokey[ 11] = '0';
+		scantokey[ 12] = '-';
+		scantokey[ 13] = '=';
+		scantokey[ 14] = K_BACKSPACE;
+		scantokey[ 15] = K_TAB;
+		scantokey[ 16] = 'q';       
+		scantokey[ 17] = 'w';       
+		scantokey[ 18] = 'e';       
+		scantokey[ 19] = 'r';       
+		scantokey[ 20] = 't';       
+		scantokey[ 21] = 'y';       
+		scantokey[ 22] = 'u';       
+		scantokey[ 23] = 'i';       
+		scantokey[ 24] = 'o';       
+		scantokey[ 25] = 'p';       
+		scantokey[ 26] = '[';
+		scantokey[ 27] = ']';
+		scantokey[ 28] = K_ENTER;
+		scantokey[ 29] = K_CTRL; //left
+		scantokey[ 30] = 'a';
+		scantokey[ 31] = 's';       
+		scantokey[ 32] = 'd';       
+		scantokey[ 33] = 'f';       
+		scantokey[ 34] = 'g';       
+		scantokey[ 35] = 'h';       
+		scantokey[ 36] = 'j';       
+		scantokey[ 37] = 'k';       
+		scantokey[ 38] = 'l';       
+		scantokey[ 39] = ';';
+		scantokey[ 40] = '\'';
+		scantokey[ 41] = '`';
+		scantokey[ 42] = K_SHIFT; //left
+		scantokey[ 43] = '\\';
+		scantokey[ 44] = 'z';       
+		scantokey[ 45] = 'x';  
+		scantokey[ 46] = 'c';
+		scantokey[ 47] = 'v';       
+		scantokey[ 48] = 'b';
+		scantokey[ 49] = 'n';       
+		scantokey[ 50] = 'm';       
+		scantokey[ 51] = ',';
+		scantokey[ 52] = '.';
+		scantokey[ 53] = '/';
+		scantokey[ 54] = K_SHIFT; //right
+		scantokey[ 55] = '*'; //keypad
+		scantokey[ 56] = K_ALT; //left
+		scantokey[ 57] = ' ';
+		// 58 caps lock
+		scantokey[ 59] = K_F1;
+		scantokey[ 60] = K_F2;
+		scantokey[ 61] = K_F3;
+		scantokey[ 62] = K_F4;
+		scantokey[ 63] = K_F5;
+		scantokey[ 64] = K_F6;
+		scantokey[ 65] = K_F7;
+		scantokey[ 66] = K_F8;
+		scantokey[ 67] = K_F9;
+		scantokey[ 68] = K_F10;
+		// 69 numlock
+		// 70 scrollock
+		scantokey[ 71] = K_HOME;
+		scantokey[ 72] = K_UPARROW;
+		scantokey[ 73] = K_PGUP;
+		scantokey[ 74] = '-';
+		scantokey[ 75] = K_LEFTARROW;
+		scantokey[ 76] = '5';
+		scantokey[ 77] = K_RIGHTARROW;
+		scantokey[ 79] = K_END;
+		scantokey[ 78] = '+';
+		scantokey[ 80] = K_DOWNARROW;
+		scantokey[ 81] = K_PGDN;
+		scantokey[ 82] = K_INS;
+		scantokey[ 83] = K_DEL;
+		// 84 to 86 not used
+		scantokey[ 87] = K_F11;
+		scantokey[ 88] = K_F12;
+		// 89 to 95 not used
+		scantokey[ 96] = K_ENTER; //keypad enter
+		scantokey[ 97] = K_CTRL; //right
+		scantokey[ 98] = '/';
+		scantokey[ 99] = K_F12; // print screen, bind to screenshot by default
+		scantokey[100] = K_ALT; // right
+
+
+		scantokey[101] = K_PAUSE; // break
+		scantokey[102] = K_HOME;
+		scantokey[103] = K_UPARROW;
+		scantokey[104] = K_PGUP;
+		scantokey[105] = K_LEFTARROW;
+		scantokey[106] = K_RIGHTARROW;
+		scantokey[107] = K_END;
+		scantokey[108] = K_DOWNARROW;
+		scantokey[109] = K_PGDN;
+		scantokey[110] = K_INS;
+		scantokey[111] = K_DEL;
+
+		scantokey[119] = K_PAUSE;
+
+		if (keyboard_init())
+			Sys_Error("keyboard_init() failed");
+		keyboard_seteventhandler(keyhandler);
+	}
+}
+
+#define NUM_RESOLUTIONS 3
+
+static resolutions[NUM_RESOLUTIONS][3]={ 
+  { 512, 384, GR_RESOLUTION_512x384 },
+  { 640, 400, GR_RESOLUTION_640x400 },
+  { 640, 480, GR_RESOLUTION_640x480 }
+};
+
+int findres(int *width, int *height)
+{
+	int i;
+
+	for(i=0;i<NUM_RESOLUTIONS;i++)
+		if((*width<=resolutions[i][0]) && (*height<=resolutions[i][1])) {
+			*width = resolutions[i][0];
+			*height = resolutions[i][1];
+			return resolutions[i][2];
+		}
+        
+	*width = 640;
+	*height = 480;
+	return GR_RESOLUTION_640x480;
+}
+
+qboolean VID_Is8bit(void)
+{
+	return is8bit;
+}
+
+#ifdef GL_EXT_SHARED
+void VID_Init8bitPalette() 
+{
+	// Check for 8bit Extensions and initialize them.
+	int i;
+	char thePalette[256*3];
+	char *oldPalette, *newPalette;
+
+	if (strstr(gl_extensions, "GL_EXT_shared_texture_palette") == NULL)
+		return;
+
+	Con_SafePrintf("8-bit GL extensions enabled.\n");
+	glEnable( GL_SHARED_TEXTURE_PALETTE_EXT );
+	oldPalette = (char *) d_8to24table; //d_8to24table3dfx;
+	newPalette = thePalette;
+	for (i=0;i<256;i++) {
+		*newPalette++ = *oldPalette++;
+		*newPalette++ = *oldPalette++;
+		*newPalette++ = *oldPalette++;
+		oldPalette++;
+	}
+	glColorTableEXT(GL_SHARED_TEXTURE_PALETTE_EXT, GL_RGB, 256, GL_RGB, GL_UNSIGNED_BYTE, (void *) thePalette);
+	is8bit = true;
+}
+
+#else
+extern void gl3DfxSetPaletteEXT(GLuint *pal);
+
+void VID_Init8bitPalette(void) 
+{
+	// Check for 8bit Extensions and initialize them.
+	int i;
+	GLubyte table[256][4];
+	char *oldpal;
+
+	if (strstr(gl_extensions, "3DFX_set_global_palette") == NULL)
+		return;
+
+	Con_SafePrintf("8-bit GL extensions enabled.\n");
+	glEnable( GL_SHARED_TEXTURE_PALETTE_EXT );
+	oldpal = (char *) d_8to24table; //d_8to24table3dfx;
+	for (i=0;i<256;i++) {
+		table[i][2] = *oldpal++;
+		table[i][1] = *oldpal++;
+		table[i][0] = *oldpal++;
+		table[i][3] = 255;
+		oldpal++;
+	}
+	gl3DfxSetPaletteEXT((GLuint *)table);
+	is8bit = true;
+}
+#endif
+
+void VID_Init(unsigned char *palette)
+{
+	int i;
+	GLint attribs[32];
+	char	gldir[MAX_OSPATH];
+	int width = 640, height = 480;
+
+	S_Init();
+
+	Init_KBD();
+
+	Cvar_RegisterVariable (&vid_mode);
+	Cvar_RegisterVariable (&vid_redrawfull);
+	Cvar_RegisterVariable (&vid_waitforrefresh);
+	Cvar_RegisterVariable (&gl_ztrick);
+	
+        vid.maxwarpwidth = WARP_WIDTH;
+        vid.maxwarpheight = WARP_HEIGHT;
+        vid.colormap = host_colormap;
+        vid.fullbright = 256 - LittleLong (*((int *)vid.colormap + 2048));
+
+// interpret command-line params
+
+// set vid parameters
+	attribs[0] = FXMESA_DOUBLEBUFFER;
+	attribs[1] = FXMESA_ALPHA_SIZE;
+	attribs[2] = 1;
+	attribs[3] = FXMESA_DEPTH_SIZE;
+	attribs[4] = 1;
+	attribs[5] = FXMESA_NONE;
+
+	if ((i = COM_CheckParm("-width")) != 0)
+		width = atoi(com_argv[i+1]);
+	if ((i = COM_CheckParm("-height")) != 0)
+		height = atoi(com_argv[i+1]);
+
+	if ((i = COM_CheckParm("-conwidth")) != 0)
+		vid.conwidth = Q_atoi(com_argv[i+1]);
+	else
+		vid.conwidth = 640;
+
+	vid.conwidth &= 0xfff8; // make it a multiple of eight
+
+	if (vid.conwidth < 320)
+		vid.conwidth = 320;
+
+	// pick a conheight that matches with correct aspect
+	vid.conheight = vid.conwidth*3 / 4;
+
+	if ((i = COM_CheckParm("-conheight")) != 0)
+		vid.conheight = Q_atoi(com_argv[i+1]);
+	if (vid.conheight < 200)
+		vid.conheight = 200;
+
+	fc = fxMesaCreateContext(0, findres(&width, &height), GR_REFRESH_75Hz, 
+		attribs);
+	if (!fc)
+		Sys_Error("Unable to create 3DFX context.\n");
+
+	scr_width = width;
+	scr_height = height;
+
+	fxMesaMakeCurrent(fc);
+
+	if (vid.conheight > height)
+		vid.conheight = height;
+	if (vid.conwidth > width)
+		vid.conwidth = width;
+	vid.width = vid.conwidth;
+	vid.height = vid.conheight;
+
+	vid.aspect = ((float)vid.height / (float)vid.width) *
+				(320.0 / 240.0);
+	vid.numpages = 2;
+
+	InitSig(); // trap evil signals
+
+	GL_Init();
+
+	sprintf (gldir, "%s/glquake", com_gamedir);
+	Sys_mkdir (gldir);
+
+	VID_SetPalette(palette);
+
+	// Check for 3DFX Extensions and initialize them.
+	VID_Init8bitPalette();
+
+	Con_SafePrintf ("Video mode %dx%d initialized.\n", width, height);
+
+	vid.recalc_refdef = 1;				// force a surface cache flush
+}
+
+void Sys_SendKeyEvents(void)
+{
+	if (UseKeyboard)
+		while (keyboard_update());
+}
+
+void Force_CenterView_f (void)
+{
+	cl.viewangles[PITCH] = 0;
+}
+
+
+void mousehandler(int buttonstate, int dx, int dy)
+{
+	mouse_buttonstate = buttonstate;
+	mx += dx;
+	my += dy;
+}
+
+void IN_Init(void)
+{
+
+	int mtype;
+	char *mousedev;
+	int mouserate;
+
+	if (UseMouse)
+	{
+
+		Cvar_RegisterVariable (&mouse_button_commands[0]);
+		Cvar_RegisterVariable (&mouse_button_commands[1]);
+		Cvar_RegisterVariable (&mouse_button_commands[2]);
+		Cmd_AddCommand ("force_centerview", Force_CenterView_f);
+
+		mouse_buttons = 3;
+
+		mtype = vga_getmousetype();
+
+		mousedev = "/dev/mouse";
+		if (getenv("MOUSEDEV")) mousedev = getenv("MOUSEDEV");
+		if (COM_CheckParm("-mdev"))
+			mousedev = com_argv[COM_CheckParm("-mdev")+1];
+
+		mouserate = 1200;
+		if (getenv("MOUSERATE")) mouserate = atoi(getenv("MOUSERATE"));
+		if (COM_CheckParm("-mrate"))
+			mouserate = atoi(com_argv[COM_CheckParm("-mrate")+1]);
+
+		if (mouse_init(mousedev, mtype, mouserate))
+		{
+			Con_Printf("No mouse found\n");
+			UseMouse = 0;
+		}
+		else
+			mouse_seteventhandler(mousehandler);
+
+	}
+
+}
+
+void IN_Shutdown(void)
+{
+	if (UseMouse)
+		mouse_close();
+}
+
+/*
+===========
+IN_Commands
+===========
+*/
+void IN_Commands (void)
+{
+	if (UseMouse)
+	{
+		// poll mouse values
+		while (mouse_update())
+			;
+
+		// perform button actions
+		if ((mouse_buttonstate & MOUSE_LEFTBUTTON) &&
+			!(mouse_oldbuttonstate & MOUSE_LEFTBUTTON))
+			Key_Event (K_MOUSE1, true);
+		else if (!(mouse_buttonstate & MOUSE_LEFTBUTTON) &&
+			(mouse_oldbuttonstate & MOUSE_LEFTBUTTON))
+			Key_Event (K_MOUSE1, false);
+
+		if ((mouse_buttonstate & MOUSE_RIGHTBUTTON) &&
+			!(mouse_oldbuttonstate & MOUSE_RIGHTBUTTON))
+			Key_Event (K_MOUSE2, true);
+		else if (!(mouse_buttonstate & MOUSE_RIGHTBUTTON) &&
+			(mouse_oldbuttonstate & MOUSE_RIGHTBUTTON))
+			Key_Event (K_MOUSE2, false);
+
+		if ((mouse_buttonstate & MOUSE_MIDDLEBUTTON) &&
+			!(mouse_oldbuttonstate & MOUSE_MIDDLEBUTTON))
+			Key_Event (K_MOUSE3, true);
+		else if (!(mouse_buttonstate & MOUSE_MIDDLEBUTTON) &&
+			(mouse_oldbuttonstate & MOUSE_MIDDLEBUTTON))
+			Key_Event (K_MOUSE3, false);
+
+		mouse_oldbuttonstate = mouse_buttonstate;
+	}
+}
+
+/*
+===========
+IN_Move
+===========
+*/
+void IN_MouseMove (usercmd_t *cmd)
+{
+	if (!UseMouse)
+		return;
+
+	// poll mouse values
+	while (mouse_update())
+		;
+
+	if (m_filter.value)
+	{
+		mouse_x = (mx + old_mouse_x) * 0.5;
+		mouse_y = (my + old_mouse_y) * 0.5;
+	}
+	else
+	{
+		mouse_x = mx;
+		mouse_y = my;
+	}
+	old_mouse_x = mx;
+	old_mouse_y = my;
+	mx = my = 0; // clear for next update
+
+	mouse_x *= sensitivity.value;
+	mouse_y *= sensitivity.value;
+
+// add mouse X/Y movement to cmd
+	if ( (in_strafe.state & 1) || (lookstrafe.value && (in_mlook.state & 1) ))
+		cmd->sidemove += m_side.value * mouse_x;
+	else
+		cl.viewangles[YAW] -= m_yaw.value * mouse_x;
+	
+	if (in_mlook.state & 1)
+		V_StopPitchDrift ();
+		
+	if ( (in_mlook.state & 1) && !(in_strafe.state & 1))
+	{
+		cl.viewangles[PITCH] += m_pitch.value * mouse_y;
+		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 * mouse_y;
+		else
+			cmd->forwardmove -= m_forward.value * mouse_y;
+	}
+}
+
+void IN_Move (usercmd_t *cmd)
+{
+	IN_MouseMove(cmd);
+}
+
+
+void	VID_LockBuffer (void) {}
+void	VID_UnlockBuffer (void) {}
+
--- /dev/null
+++ b/QW/client/gl_vidlinux_x11.c
@@ -1,0 +1,870 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+#include <termios.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/vt.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <signal.h>
+#include <asm/io.h>
+
+//#include <X11/cursorfont.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/Xatom.h>
+#include <X11/keysym.h>
+
+#include "GL/gl.h"
+#include "GL/glx.h"
+
+#include "quakedef.h"
+
+#define WARP_WIDTH              320
+#define WARP_HEIGHT             200
+
+static Display *dpy = NULL;
+static Window win;
+static GLXContext ctx = NULL;
+
+unsigned short d_8to16table[256];
+unsigned int d_8to24table[256];
+unsigned char d_15to8table[65536];
+
+static qboolean usedga = false;
+
+#define stringify(m) { #m, m }
+
+cvar_t vid_mode = {"vid_mode","0",false};
+ 
+cvar_t  mouse_button_commands[3] =
+{
+    {"mouse1","+attack"},
+    {"mouse2","+strafe"},
+    {"mouse3","+forward"},
+};
+
+static int mouse_buttons=3;
+static int mouse_buttonstate;
+static int mouse_oldbuttonstate;
+static float mouse_x, mouse_y;
+static float p_mouse_x, p_mouse_y;
+static float old_mouse_x, old_mouse_y;
+
+cvar_t _windowed_mouse = {"_windowed_mouse", "1", true};
+cvar_t m_filter = {"m_filter","0"};
+static float old_windowed_mouse;
+
+static int scr_width, scr_height;
+
+#define KEY_MASK (KeyPressMask | KeyReleaseMask)
+#define MOUSE_MASK (ButtonPressMask | ButtonReleaseMask | \
+		    PointerMotionMask | ButtonMotionMask)
+
+/*-----------------------------------------------------------------------*/
+
+//int		texture_mode = GL_NEAREST;
+//int		texture_mode = GL_NEAREST_MIPMAP_NEAREST;
+//int		texture_mode = GL_NEAREST_MIPMAP_LINEAR;
+int		texture_mode = GL_LINEAR;
+//int		texture_mode = GL_LINEAR_MIPMAP_NEAREST;
+//int		texture_mode = GL_LINEAR_MIPMAP_LINEAR;
+
+int		texture_extension_number = 1;
+
+float		gldepthmin, gldepthmax;
+
+cvar_t	gl_ztrick = {"gl_ztrick","1"};
+
+const char *gl_vendor;
+const char *gl_renderer;
+const char *gl_version;
+const char *gl_extensions;
+
+qboolean is8bit = false;
+qboolean isPermedia = false;
+qboolean gl_mtexable = false;
+
+/*-----------------------------------------------------------------------*/
+void D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height)
+{
+}
+
+void D_EndDirectRect (int x, int y, int width, int height)
+{
+}
+
+/*
+=================
+VID_Gamma_f
+
+Keybinding command
+=================
+*/
+void VID_Gamma_f (void)
+{
+	float	gamma, f, inf;
+	unsigned char	palette[768];
+	int		i;
+
+	if (Cmd_Argc () == 2)
+	{
+		gamma = Q_atof (Cmd_Argv(1));
+
+		for (i=0 ; i<768 ; i++)
+		{
+			f = pow ( (host_basepal[i]+1)/256.0 , gamma );
+			inf = f*255 + 0.5;
+			if (inf < 0)
+				inf = 0;
+			if (inf > 255)
+				inf = 255;
+			palette[i] = inf;
+		}
+
+		VID_SetPalette (palette);
+
+		vid.recalc_refdef = 1;				// force a surface cache flush
+	}
+}
+
+void VID_Shutdown(void)
+{
+	if (!ctx)
+		return;
+
+	XUngrabPointer(dpy,CurrentTime);
+	XUngrabKeyboard(dpy,CurrentTime);
+
+	glXDestroyContext(dpy,ctx);
+
+#ifdef USE_DGA
+	if (usedga)
+		XF86DGADirectVideo(dpy,DefaultScreen(dpy),0);
+#endif
+}
+
+int XLateKey(XKeyEvent *ev)
+{
+
+	int key;
+	char buf[64];
+	KeySym keysym;
+
+	key = 0;
+
+	XLookupString(ev, buf, sizeof buf, &keysym, 0);
+
+	switch(keysym)
+	{
+		case XK_KP_Page_Up:
+		case XK_Page_Up:	 key = K_PGUP; break;
+
+		case XK_KP_Page_Down:
+		case XK_Page_Down:	 key = K_PGDN; break;
+
+		case XK_KP_Home:
+		case XK_Home:	 key = K_HOME; break;
+
+		case XK_KP_End:
+		case XK_End:	 key = K_END; break;
+
+		case XK_KP_Left:
+		case XK_Left:	 key = K_LEFTARROW; break;
+
+		case XK_KP_Right:
+		case XK_Right:	key = K_RIGHTARROW;		break;
+
+		case XK_KP_Down:
+		case XK_Down:	 key = K_DOWNARROW; break;
+
+		case XK_KP_Up:
+		case XK_Up:		 key = K_UPARROW;	 break;
+
+		case XK_Escape: key = K_ESCAPE;		break;
+
+		case XK_KP_Enter:
+		case XK_Return: key = K_ENTER;		 break;
+
+		case XK_Tab:		key = K_TAB;			 break;
+
+		case XK_F1:		 key = K_F1;				break;
+
+		case XK_F2:		 key = K_F2;				break;
+
+		case XK_F3:		 key = K_F3;				break;
+
+		case XK_F4:		 key = K_F4;				break;
+
+		case XK_F5:		 key = K_F5;				break;
+
+		case XK_F6:		 key = K_F6;				break;
+
+		case XK_F7:		 key = K_F7;				break;
+
+		case XK_F8:		 key = K_F8;				break;
+
+		case XK_F9:		 key = K_F9;				break;
+
+		case XK_F10:		key = K_F10;			 break;
+
+		case XK_F11:		key = K_F11;			 break;
+
+		case XK_F12:		key = K_F12;			 break;
+
+		case XK_BackSpace: key = K_BACKSPACE; break;
+
+		case XK_KP_Delete:
+		case XK_Delete: key = K_DEL; break;
+
+		case XK_Pause:	key = K_PAUSE;		 break;
+
+		case XK_Shift_L:
+		case XK_Shift_R:	key = K_SHIFT;		break;
+
+		case XK_Execute: 
+		case XK_Control_L: 
+		case XK_Control_R:	key = K_CTRL;		 break;
+
+		case XK_Alt_L:	
+		case XK_Meta_L: 
+		case XK_Alt_R:	
+		case XK_Meta_R: key = K_ALT;			break;
+
+		case XK_KP_Begin: key = K_AUX30;	break;
+
+		case XK_Insert:
+		case XK_KP_Insert: key = K_INS; break;
+
+		case XK_KP_Multiply: key = '*'; break;
+		case XK_KP_Add: key = '+'; break;
+		case XK_KP_Subtract: key = '-'; break;
+		case XK_KP_Divide: key = '/'; break;
+
+#if 0
+		case 0x021: key = '1';break;/* [!] */
+		case 0x040: key = '2';break;/* [@] */
+		case 0x023: key = '3';break;/* [#] */
+		case 0x024: key = '4';break;/* [$] */
+		case 0x025: key = '5';break;/* [%] */
+		case 0x05e: key = '6';break;/* [^] */
+		case 0x026: key = '7';break;/* [&] */
+		case 0x02a: key = '8';break;/* [*] */
+		case 0x028: key = '9';;break;/* [(] */
+		case 0x029: key = '0';break;/* [)] */
+		case 0x05f: key = '-';break;/* [_] */
+		case 0x02b: key = '=';break;/* [+] */
+		case 0x07c: key = '\'';break;/* [|] */
+		case 0x07d: key = '[';break;/* [}] */
+		case 0x07b: key = ']';break;/* [{] */
+		case 0x022: key = '\'';break;/* ["] */
+		case 0x03a: key = ';';break;/* [:] */
+		case 0x03f: key = '/';break;/* [?] */
+		case 0x03e: key = '.';break;/* [>] */
+		case 0x03c: key = ',';break;/* [<] */
+#endif
+
+		default:
+			key = *(unsigned char*)buf;
+			if (key >= 'A' && key <= 'Z')
+				key = key - 'A' + 'a';
+//			fprintf(stdout, "case 0x0%x: key = ___;break;/* [%c] */\n", keysym);
+			break;
+	} 
+
+	return key;
+}
+
+struct
+{
+	int key;
+	int down;
+} keyq[64];
+int keyq_head=0;
+int keyq_tail=0;
+
+int config_notify=0;
+int config_notify_width;
+int config_notify_height;
+						      
+qboolean Keyboard_Update(void)
+{
+	XEvent x_event;
+   
+	if(!XCheckMaskEvent(dpy,KEY_MASK,&x_event))
+		return false;
+
+	switch(x_event.type) {
+	case KeyPress:
+		keyq[keyq_head].key = XLateKey(&x_event.xkey);
+		keyq[keyq_head].down = true;
+		keyq_head = (keyq_head + 1) & 63;
+		break;
+	case KeyRelease:
+		keyq[keyq_head].key = XLateKey(&x_event.xkey);
+		keyq[keyq_head].down = false;
+		keyq_head = (keyq_head + 1) & 63;
+		break;
+	}
+
+	return true;
+}
+
+qboolean Mouse_Update(void)
+{
+	XEvent x_event;
+	int b;
+   
+	if(!XCheckMaskEvent(dpy,MOUSE_MASK,&x_event))
+		return false;
+
+	switch(x_event.type) {
+	case MotionNotify:
+		if (usedga) {
+			mouse_x += x_event.xmotion.x_root;
+			mouse_y += x_event.xmotion.y_root;
+		} else if (_windowed_mouse.value) {
+			mouse_x += (float) ((int)x_event.xmotion.x - (int)(scr_width/2));
+			mouse_y += (float) ((int)x_event.xmotion.y - (int)(scr_height/2));
+
+			/* move the mouse to the window center again */
+			XSelectInput(dpy,win, (KEY_MASK | MOUSE_MASK) & ~PointerMotionMask);
+			XWarpPointer(dpy,None,win,0,0,0,0, (scr_width/2),(scr_height/2));
+			XSelectInput(dpy,win, KEY_MASK | MOUSE_MASK);
+		} else {
+			mouse_x = (float) (x_event.xmotion.x-p_mouse_x);
+			mouse_y = (float) (x_event.xmotion.y-p_mouse_y);
+			p_mouse_x=x_event.xmotion.x;
+			p_mouse_y=x_event.xmotion.y;
+		}
+		break;
+
+	case ButtonPress:
+		b=-1;
+		if (x_event.xbutton.button == 1)
+			b = 0;
+		else if (x_event.xbutton.button == 2)
+			b = 2;
+		else if (x_event.xbutton.button == 3)
+			b = 1;
+		if (b>=0)
+			mouse_buttonstate |= 1<<b;
+		break;
+
+	case ButtonRelease:
+		b=-1;
+		if (x_event.xbutton.button == 1)
+			b = 0;
+		else if (x_event.xbutton.button == 2)
+			b = 2;
+		else if (x_event.xbutton.button == 3)
+			b = 1;
+		if (b>=0)
+			mouse_buttonstate &= ~(1<<b);
+		break;
+	}
+   
+	if (old_windowed_mouse != _windowed_mouse.value) {
+		old_windowed_mouse = _windowed_mouse.value;
+
+		if (!_windowed_mouse.value) {
+			/* ungrab the pointer */
+			Con_Printf("Releasing mouse.\n");
+
+			XUngrabPointer(dpy,CurrentTime);
+			XUngrabKeyboard(dpy,CurrentTime);
+		} else {
+			/* grab the pointer */
+			Con_Printf("Grabbing mouse.\n");
+
+			XGrabPointer(dpy,win,False,MOUSE_MASK,GrabModeAsync,
+				GrabModeAsync,win,None,CurrentTime);
+			XWarpPointer(dpy,None,win, 0,0,0,0, scr_width/2, scr_height/2);
+			XGrabKeyboard(dpy,win,
+				False,
+				GrabModeAsync,GrabModeAsync,
+				CurrentTime);
+
+			//XSync(dpy,True);
+		}
+	}
+	return true;
+}
+
+void signal_handler(int sig)
+{
+	printf("Received signal %d, exiting...\n", sig);
+	VID_Shutdown();
+	exit(0);
+}
+
+void InitSig(void)
+{
+	signal(SIGHUP, signal_handler);
+	signal(SIGQUIT, signal_handler);
+	signal(SIGILL, signal_handler);
+	signal(SIGTRAP, signal_handler);
+	signal(SIGIOT, signal_handler);
+	signal(SIGBUS, signal_handler);
+	signal(SIGFPE, signal_handler);
+	signal(SIGSEGV, signal_handler);
+	signal(SIGTERM, signal_handler);
+}
+
+void VID_ShiftPalette(unsigned char *p)
+{
+	VID_SetPalette(p);
+}
+
+void	VID_SetPalette (unsigned char *palette)
+{
+	byte	*pal;
+	unsigned short r,g,b;
+	int     v;
+	int     r1,g1,b1;
+	int		k;
+	unsigned short i;
+	unsigned	*table;
+	FILE *f;
+	char s[255];
+	float dist, bestdist;
+	static qboolean palflag = false;
+
+//
+// 8 8 8 encoding
+//
+	pal = palette;
+	table = d_8to24table;
+	for (i=0 ; i<256 ; i++)
+	{
+		r = pal[0];
+		g = pal[1];
+		b = pal[2];
+		pal += 3;
+		
+//		v = (255<<24) + (r<<16) + (g<<8) + (b<<0);
+//		v = (255<<0) + (r<<8) + (g<<16) + (b<<24);
+		v = (255<<24) + (r<<0) + (g<<8) + (b<<16);
+		*table++ = v;
+	}
+	d_8to24table[255] &= 0xffffff;	// 255 is transparent
+
+	// JACK: 3D distance calcs - k is last closest, l is the distance.
+	// FIXME: Precalculate this and cache to disk.
+	if (palflag)
+		return;
+	palflag = true;
+
+	COM_FOpenFile("glquake/15to8.pal", &f);
+	if (f) {
+		fread(d_15to8table, 1<<15, 1, f);
+		fclose(f);
+	} else {
+		for (i=0; i < (1<<15); i++) {
+			/* Maps
+ 			000000000000000
+ 			000000000011111 = Red  = 0x1F
+ 			000001111100000 = Blue = 0x03E0
+ 			111110000000000 = Grn  = 0x7C00
+ 			*/
+ 			r = ((i & 0x1F) << 3)+4;
+ 			g = ((i & 0x03E0) >> 2)+4;
+ 			b = ((i & 0x7C00) >> 7)+4;
+			pal = (unsigned char *)d_8to24table;
+			for (v=0,k=0,bestdist=10000.0; v<256; v++,pal+=4) {
+ 				r1 = (int)r - (int)pal[0];
+ 				g1 = (int)g - (int)pal[1];
+ 				b1 = (int)b - (int)pal[2];
+				dist = sqrt(((r1*r1)+(g1*g1)+(b1*b1)));
+				if (dist < bestdist) {
+					k=v;
+					bestdist = dist;
+				}
+			}
+			d_15to8table[i]=k;
+		}
+		sprintf(s, "%s/glquake", com_gamedir);
+ 		Sys_mkdir (s);
+		sprintf(s, "%s/glquake/15to8.pal", com_gamedir);
+		if ((f = fopen(s, "wb")) != NULL) {
+			fwrite(d_15to8table, 1<<15, 1, f);
+			fclose(f);
+		}
+	}
+}
+
+/*
+===============
+GL_Init
+===============
+*/
+void GL_Init (void)
+{
+	gl_vendor = glGetString (GL_VENDOR);
+	Con_Printf ("GL_VENDOR: %s\n", gl_vendor);
+	gl_renderer = glGetString (GL_RENDERER);
+	Con_Printf ("GL_RENDERER: %s\n", gl_renderer);
+
+	gl_version = glGetString (GL_VERSION);
+	Con_Printf ("GL_VERSION: %s\n", gl_version);
+	gl_extensions = glGetString (GL_EXTENSIONS);
+	Con_Printf ("GL_EXTENSIONS: %s\n", gl_extensions);
+
+//	Con_Printf ("%s %s\n", gl_renderer, gl_version);
+
+	glClearColor (1,0,0,0);
+	glCullFace(GL_FRONT);
+	glEnable(GL_TEXTURE_2D);
+
+	glEnable(GL_ALPHA_TEST);
+	glAlphaFunc(GL_GREATER, 0.666);
+
+	glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
+	glShadeModel (GL_FLAT);
+
+	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+
+	glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+//	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+}
+
+/*
+=================
+GL_BeginRendering
+
+=================
+*/
+void GL_BeginRendering (int *x, int *y, int *width, int *height)
+{
+	extern cvar_t gl_clear;
+
+	*x = *y = 0;
+	*width = scr_width;
+	*height = scr_height;
+
+//    if (!wglMakeCurrent( maindc, baseRC ))
+//		Sys_Error ("wglMakeCurrent failed");
+
+//	glViewport (*x, *y, *width, *height);
+}
+
+
+void GL_EndRendering (void)
+{
+	glFlush();
+	glXSwapBuffers(dpy,win);
+}
+
+qboolean VID_Is8bit(void)
+{
+	return is8bit;
+}
+
+#ifdef GL_EXT_SHARED
+void VID_Init8bitPalette() 
+{
+	// Check for 8bit Extensions and initialize them.
+	int i;
+	char thePalette[256*3];
+	char *oldPalette, *newPalette;
+
+	if (strstr(gl_extensions, "GL_EXT_shared_texture_palette") == NULL)
+		return;
+
+	Con_SafePrintf("8-bit GL extensions enabled.\n");
+	glEnable( GL_SHARED_TEXTURE_PALETTE_EXT );
+	oldPalette = (char *) d_8to24table; //d_8to24table3dfx;
+	newPalette = thePalette;
+	for (i=0;i<256;i++) {
+		*newPalette++ = *oldPalette++;
+		*newPalette++ = *oldPalette++;
+		*newPalette++ = *oldPalette++;
+		oldPalette++;
+	}
+	glColorTableEXT(GL_SHARED_TEXTURE_PALETTE_EXT, GL_RGB, 256, GL_RGB, GL_UNSIGNED_BYTE, (void *) thePalette);
+	is8bit = true;
+}
+
+#else
+extern void gl3DfxSetPaletteEXT(GLuint *pal);
+
+void VID_Init8bitPalette(void) 
+{
+	// Check for 8bit Extensions and initialize them.
+	int i;
+	GLubyte table[256][4];
+	char *oldpal;
+
+	if (strstr(gl_extensions, "3DFX_set_global_palette") == NULL)
+		return;
+
+	Con_SafePrintf("8-bit GL extensions enabled.\n");
+	glEnable( GL_SHARED_TEXTURE_PALETTE_EXT );
+	oldpal = (char *) d_8to24table; //d_8to24table3dfx;
+	for (i=0;i<256;i++) {
+		table[i][2] = *oldpal++;
+		table[i][1] = *oldpal++;
+		table[i][0] = *oldpal++;
+		table[i][3] = 255;
+		oldpal++;
+	}
+	gl3DfxSetPaletteEXT((GLuint *)table);
+	is8bit = true;
+}
+#endif
+
+void VID_Init(unsigned char *palette)
+{
+	int i;
+	char	gldir[MAX_OSPATH];
+	int width = 640, height = 480;
+	int attrib[] = { 
+		GLX_RGBA,
+		GLX_RED_SIZE, 1,
+		GLX_GREEN_SIZE, 1,
+		GLX_BLUE_SIZE, 1,
+		GLX_DOUBLEBUFFER,
+		GLX_DEPTH_SIZE, 1,
+		None };
+	int scrnum;
+	XSetWindowAttributes attr;
+	unsigned long mask;
+	Window root;
+	XVisualInfo *visinfo;
+
+	S_Init();
+
+	Cvar_RegisterVariable (&vid_mode);
+	Cvar_RegisterVariable (&gl_ztrick);
+	
+	vid.maxwarpwidth = WARP_WIDTH;
+	vid.maxwarpheight = WARP_HEIGHT;
+	vid.colormap = host_colormap;
+	vid.fullbright = 256 - LittleLong (*((int *)vid.colormap + 2048));
+
+// interpret command-line params
+
+// set vid parameters
+
+	if ((i = COM_CheckParm("-width")) != 0)
+		width = atoi(com_argv[i+1]);
+	if ((i = COM_CheckParm("-height")) != 0)
+		height = atoi(com_argv[i+1]);
+
+	if ((i = COM_CheckParm("-conwidth")) != 0)
+		vid.conwidth = Q_atoi(com_argv[i+1]);
+	else
+		vid.conwidth = 640;
+
+	vid.conwidth &= 0xfff8; // make it a multiple of eight
+
+	if (vid.conwidth < 320)
+		vid.conwidth = 320;
+
+	// pick a conheight that matches with correct aspect
+	vid.conheight = vid.conwidth*3 / 4;
+
+	if ((i = COM_CheckParm("-conheight")) != 0)
+		vid.conheight = Q_atoi(com_argv[i+1]);
+	if (vid.conheight < 200)
+		vid.conheight = 200;
+
+	if (!(dpy = XOpenDisplay(NULL))) {
+		fprintf(stderr, "Error couldn't open the X display\n");
+		exit(1);
+	}
+
+	scrnum = DefaultScreen(dpy);
+	root = RootWindow(dpy, scrnum);
+
+	visinfo=glXChooseVisual(dpy,scrnum,attrib);
+	if (!visinfo) {
+		fprintf(stderr, "Error couldn't get an RGB, Double-buffered, Depth visual\n");
+		exit(1);
+	}
+
+	/* window attributes */
+	attr.background_pixel=0;
+	attr.border_pixel=0;
+	attr.colormap=XCreateColormap(dpy,root,visinfo->visual,AllocNone);
+	attr.event_mask=KEY_MASK|MOUSE_MASK|VisibilityChangeMask;
+	mask=CWBackPixel|CWBorderPixel|CWColormap|CWEventMask;
+
+	win=XCreateWindow(dpy,root,0,0,width,height,
+			0,visinfo->depth,InputOutput,
+			visinfo->visual,mask,&attr);
+	XMapWindow(dpy,win);
+
+	XMoveWindow(dpy,win,0,0);
+
+	XFlush(dpy);
+
+	if (COM_CheckParm("-window"))
+		putenv("MESA_GLX_FX=window");
+	else
+		putenv("MESA_GLX_FX=fullscreen");
+
+	ctx = glXCreateContext(dpy,visinfo,NULL,True);
+
+	if (!ctx) {
+		fprintf(stderr, "Unable to create glX context.\n");
+		exit(1);
+	}
+
+	glXMakeCurrent(dpy,win,ctx);
+
+	scr_width = width;
+	scr_height = height;
+
+	if (vid.conheight > height)
+		vid.conheight = height;
+	if (vid.conwidth > width)
+		vid.conwidth = width;
+	vid.width = vid.conwidth;
+	vid.height = vid.conheight;
+
+	vid.aspect = ((float)vid.height / (float)vid.width) *
+				(320.0 / 240.0);
+	vid.numpages = 2;
+
+	InitSig(); // trap evil signals
+
+	GL_Init();
+
+	sprintf (gldir, "%s/glquake", com_gamedir);
+	Sys_mkdir (gldir);
+
+	VID_SetPalette(palette);
+
+	// Check for 3DFX Extensions and initialize them.
+	VID_Init8bitPalette();
+
+	Con_SafePrintf ("Video mode %dx%d initialized.\n", width, height);
+
+	vid.recalc_refdef = 1;				// force a surface cache flush
+}
+
+void Sys_SendKeyEvents(void)
+{
+	if (dpy)
+	{
+		while (Keyboard_Update())
+			;
+
+		while (keyq_head != keyq_tail)
+		{
+			Key_Event(keyq[keyq_tail].key, keyq[keyq_tail].down);
+			keyq_tail = (keyq_tail + 1) & 63;
+		}
+	}
+}
+
+void Force_CenterView_f (void)
+{
+	cl.viewangles[PITCH] = 0;
+}
+
+
+void IN_Init(void)
+{
+	Cvar_RegisterVariable (&_windowed_mouse);
+	Cvar_RegisterVariable (&m_filter);
+	Cvar_RegisterVariable (&mouse_button_commands[0]);
+	Cvar_RegisterVariable (&mouse_button_commands[1]);
+	Cvar_RegisterVariable (&mouse_button_commands[2]);
+	Cmd_AddCommand ("force_centerview", Force_CenterView_f);
+}
+
+void IN_Shutdown(void)
+{
+}
+
+/*
+===========
+IN_Commands
+===========
+*/
+void IN_Commands (void)
+{
+	int i;
+
+	for (i=0 ; i<mouse_buttons ; i++) {
+		if ( (mouse_buttonstate & (1<<i)) && !(mouse_oldbuttonstate & (1<<i)) )
+			Key_Event (K_MOUSE1 + i, true);
+
+		if ( !(mouse_buttonstate & (1<<i)) && (mouse_oldbuttonstate & (1<<i)) )
+			Key_Event (K_MOUSE1 + i, false);
+	}
+
+	mouse_oldbuttonstate = mouse_buttonstate;
+}
+
+/*
+===========
+IN_Move
+===========
+*/
+void IN_Move (usercmd_t *cmd)
+{
+	while (Mouse_Update())
+		;
+
+	if (m_filter.value) {
+		mouse_x = (mouse_x + old_mouse_x) * 0.5;
+		mouse_y = (mouse_y + old_mouse_y) * 0.5;
+	}
+
+	old_mouse_x = mouse_x;
+	old_mouse_y = mouse_y;
+   
+	mouse_x *= sensitivity.value;
+	mouse_y *= sensitivity.value;
+   
+	if ( (in_strafe.state & 1) || (lookstrafe.value && (in_mlook.state & 1) ))
+		cmd->sidemove += m_side.value * mouse_x;
+	else
+		cl.viewangles[YAW] -= m_yaw.value * mouse_x;
+	if (in_mlook.state & 1)
+		V_StopPitchDrift ();
+   
+	if ( (in_mlook.state & 1) && !(in_strafe.state & 1)) {
+		cl.viewangles[PITCH] += m_pitch.value * mouse_y;
+		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 * mouse_y;
+		else
+			cmd->forwardmove -= m_forward.value * mouse_y;
+	}
+	mouse_x = mouse_y = 0.0;
+}
+
+
+void	VID_LockBuffer (void) {}
+void	VID_UnlockBuffer (void) {}
+
--- /dev/null
+++ b/QW/client/gl_vidlinuxglx.c
@@ -1,0 +1,789 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+#include <termios.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/vt.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <signal.h>
+
+#include "quakedef.h"
+
+#include <GL/glx.h>
+
+#include <X11/keysym.h>
+#include <X11/cursorfont.h>
+
+#ifdef USE_DGA
+#include <X11/extensions/xf86dga.h>
+#endif
+
+
+#define WARP_WIDTH              320
+#define WARP_HEIGHT             200
+
+static Display *dpy = NULL;
+static Window win;
+static GLXContext ctx = NULL;
+
+static float old_windowed_mouse = 0;
+
+#define KEY_MASK (KeyPressMask | KeyReleaseMask)
+#define MOUSE_MASK (ButtonPressMask | ButtonReleaseMask | \
+		    PointerMotionMask)
+
+#define X_MASK (KEY_MASK | MOUSE_MASK | VisibilityChangeMask)
+
+unsigned short	d_8to16table[256];
+unsigned		d_8to24table[256];
+unsigned char	d_15to8table[65536];
+
+cvar_t	_windowed_mouse = {"_windowed_mouse","0", true};
+cvar_t	vid_mode = {"vid_mode","0",false};
+ 
+static float   mouse_x, mouse_y;
+static float	old_mouse_x, old_mouse_y;
+
+cvar_t	m_filter = {"m_filter", "0"};
+
+static int scr_width, scr_height;
+
+/*-----------------------------------------------------------------------*/
+
+//int		texture_mode = GL_NEAREST;
+//int		texture_mode = GL_NEAREST_MIPMAP_NEAREST;
+//int		texture_mode = GL_NEAREST_MIPMAP_LINEAR;
+int		texture_mode = GL_LINEAR;
+//int		texture_mode = GL_LINEAR_MIPMAP_NEAREST;
+//int		texture_mode = GL_LINEAR_MIPMAP_LINEAR;
+
+int		texture_extension_number = 1;
+
+float		gldepthmin, gldepthmax;
+
+cvar_t	gl_ztrick = {"gl_ztrick","1"};
+
+const char *gl_vendor;
+const char *gl_renderer;
+const char *gl_version;
+const char *gl_extensions;
+
+qboolean is8bit = false;
+qboolean isPermedia = false;
+qboolean gl_mtexable = false;
+
+/*-----------------------------------------------------------------------*/
+void D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height)
+{
+}
+
+void D_EndDirectRect (int x, int y, int width, int height)
+{
+}
+
+static int XLateKey(XKeyEvent *ev)
+{
+
+	int key;
+	char buf[64];
+	KeySym keysym;
+
+	key = 0;
+
+	XLookupString(ev, buf, sizeof buf, &keysym, 0);
+
+	switch(keysym)
+	{
+		case XK_KP_Page_Up:	 
+		case XK_Page_Up:	 key = K_PGUP; break;
+
+		case XK_KP_Page_Down: 
+		case XK_Page_Down:	 key = K_PGDN; break;
+
+		case XK_KP_Home: 
+		case XK_Home:	 key = K_HOME; break;
+
+		case XK_KP_End:  
+		case XK_End:	 key = K_END; break;
+
+		case XK_KP_Left: 
+		case XK_Left:	 key = K_LEFTARROW; break;
+
+		case XK_KP_Right: 
+		case XK_Right:	key = K_RIGHTARROW;		break;
+
+		case XK_KP_Down: 
+		case XK_Down:	 key = K_DOWNARROW; break;
+
+		case XK_KP_Up:   
+		case XK_Up:		 key = K_UPARROW;	 break;
+
+		case XK_Escape: key = K_ESCAPE;		break;
+
+		case XK_KP_Enter: 
+		case XK_Return: key = K_ENTER;		 break;
+
+		case XK_Tab:		key = K_TAB;			 break;
+
+		case XK_F1:		 key = K_F1;				break;
+
+		case XK_F2:		 key = K_F2;				break;
+
+		case XK_F3:		 key = K_F3;				break;
+
+		case XK_F4:		 key = K_F4;				break;
+
+		case XK_F5:		 key = K_F5;				break;
+
+		case XK_F6:		 key = K_F6;				break;
+
+		case XK_F7:		 key = K_F7;				break;
+
+		case XK_F8:		 key = K_F8;				break;
+
+		case XK_F9:		 key = K_F9;				break;
+
+		case XK_F10:		key = K_F10;			 break;
+
+		case XK_F11:		key = K_F11;			 break;
+
+		case XK_F12:		key = K_F12;			 break;
+
+		case XK_BackSpace: key = K_BACKSPACE; break;
+
+		case XK_KP_Delete: 
+		case XK_Delete: key = K_DEL; break;
+
+		case XK_Pause:	key = K_PAUSE;		 break;
+
+		case XK_Shift_L:
+		case XK_Shift_R:	key = K_SHIFT;		break;
+
+		case XK_Execute: 
+		case XK_Control_L: 
+		case XK_Control_R:	key = K_CTRL;		 break;
+
+		case XK_Alt_L:	
+		case XK_Meta_L: 
+		case XK_Alt_R:	
+		case XK_Meta_R: key = K_ALT;			break;
+
+		case XK_KP_Begin: key = '5';	break;
+
+		case XK_KP_Insert: 
+		case XK_Insert:key = K_INS; break;
+
+		case XK_KP_Multiply: key = '*'; break;
+		case XK_KP_Add:  key = '+'; break;
+		case XK_KP_Subtract: key = '-'; break;
+		case XK_KP_Divide: key = '/'; break;
+
+#if 0
+		case 0x021: key = '1';break;/* [!] */
+		case 0x040: key = '2';break;/* [@] */
+		case 0x023: key = '3';break;/* [#] */
+		case 0x024: key = '4';break;/* [$] */
+		case 0x025: key = '5';break;/* [%] */
+		case 0x05e: key = '6';break;/* [^] */
+		case 0x026: key = '7';break;/* [&] */
+		case 0x02a: key = '8';break;/* [*] */
+		case 0x028: key = '9';;break;/* [(] */
+		case 0x029: key = '0';break;/* [)] */
+		case 0x05f: key = '-';break;/* [_] */
+		case 0x02b: key = '=';break;/* [+] */
+		case 0x07c: key = '\'';break;/* [|] */
+		case 0x07d: key = '[';break;/* [}] */
+		case 0x07b: key = ']';break;/* [{] */
+		case 0x022: key = '\'';break;/* ["] */
+		case 0x03a: key = ';';break;/* [:] */
+		case 0x03f: key = '/';break;/* [?] */
+		case 0x03e: key = '.';break;/* [>] */
+		case 0x03c: key = ',';break;/* [<] */
+#endif
+
+		default:
+			key = *(unsigned char*)buf;
+			if (key >= 'A' && key <= 'Z')
+				key = key - 'A' + 'a';
+			break;
+	} 
+
+	return key;
+}
+
+static void install_grabs(void)
+{
+	XGrabPointer(dpy, win,
+				 True,
+				 0,
+				 GrabModeAsync, GrabModeAsync,
+				 win,
+				 None,
+				 CurrentTime);
+
+#ifdef USE_DGA
+	XF86DGADirectVideo(dpy, DefaultScreen(dpy), XF86DGADirectMouse);
+	dgamouse = 1;
+#else
+	XWarpPointer(dpy, None, win,
+				 0, 0, 0, 0,
+				 vid.width / 2, vid.height / 2);
+#endif
+
+	XGrabKeyboard(dpy, win,
+				  False,
+				  GrabModeAsync, GrabModeAsync,
+				  CurrentTime);
+
+//	XSync(dpy, True);
+}
+
+static void uninstall_grabs(void)
+{
+#ifdef USE_DGA
+	XF86DGADirectVideo(dpy, DefaultScreen(dpy), 0);
+	dgamouse = 0;
+#endif
+
+	XUngrabPointer(dpy, CurrentTime);
+	XUngrabKeyboard(dpy, CurrentTime);
+
+//	XSync(dpy, True);
+}
+
+static void GetEvent(void)
+{
+	XEvent event;
+	int b;
+
+	if (!dpy)
+		return;
+
+	XNextEvent(dpy, &event);
+
+	switch (event.type) {
+	case KeyPress:
+	case KeyRelease:
+		Key_Event(XLateKey(&event.xkey), event.type == KeyPress);
+		break;
+
+	case MotionNotify:
+#ifdef USE_DGA
+		if (dgamouse && _windowed_mouse.value) {
+			mouse_x = event.xmotion.x_root;
+			mouse_y = event.xmotion.y_root;
+		} else
+#endif
+		{
+			if (_windowed_mouse.value) {
+				mouse_x = (float) ((int)event.xmotion.x - (int)(vid.width/2));
+				mouse_y = (float) ((int)event.xmotion.y - (int)(vid.height/2));
+
+				/* move the mouse to the window center again */
+				XSelectInput(dpy, win, X_MASK & ~PointerMotionMask);
+				XWarpPointer(dpy, None, win, 0, 0, 0, 0, 
+					(vid.width/2), (vid.height/2));
+				XSelectInput(dpy, win, X_MASK);
+			}
+		}
+		break;
+
+	case ButtonPress:
+		b=-1;
+		if (event.xbutton.button == 1)
+			b = 0;
+		else if (event.xbutton.button == 2)
+			b = 2;
+		else if (event.xbutton.button == 3)
+			b = 1;
+		if (b>=0)
+			Key_Event(K_MOUSE1 + b, true);
+		break;
+
+	case ButtonRelease:
+		b=-1;
+		if (event.xbutton.button == 1)
+			b = 0;
+		else if (event.xbutton.button == 2)
+			b = 2;
+		else if (event.xbutton.button == 3)
+			b = 1;
+		if (b>=0)
+			Key_Event(K_MOUSE1 + b, false);
+		break;
+	}
+
+	if (old_windowed_mouse != _windowed_mouse.value) {
+		old_windowed_mouse = _windowed_mouse.value;
+
+		if (!_windowed_mouse.value) {
+			/* ungrab the pointer */
+			uninstall_grabs();
+		} else {
+			/* grab the pointer */
+			install_grabs();
+		}
+	}
+}
+
+
+void VID_Shutdown(void)
+{
+	if (!ctx)
+		return;
+
+	glXDestroyContext(dpy, ctx);
+}
+
+void signal_handler(int sig)
+{
+	printf("Received signal %d, exiting...\n", sig);
+	Sys_Quit();
+	exit(0);
+}
+
+void InitSig(void)
+{
+	signal(SIGHUP, signal_handler);
+	signal(SIGINT, signal_handler);
+	signal(SIGQUIT, signal_handler);
+	signal(SIGILL, signal_handler);
+	signal(SIGTRAP, signal_handler);
+	signal(SIGIOT, signal_handler);
+	signal(SIGBUS, signal_handler);
+	signal(SIGFPE, signal_handler);
+	signal(SIGSEGV, signal_handler);
+	signal(SIGTERM, signal_handler);
+}
+
+void VID_ShiftPalette(unsigned char *p)
+{
+//	VID_SetPalette(p);
+}
+
+void	VID_SetPalette (unsigned char *palette)
+{
+	byte	*pal;
+	unsigned r,g,b;
+	unsigned v;
+	int     r1,g1,b1;
+	int		k;
+	unsigned short i;
+	unsigned	*table;
+	FILE *f;
+	char s[255];
+	float dist, bestdist;
+	static qboolean palflag = false;
+
+//
+// 8 8 8 encoding
+//
+	Con_Printf("Converting 8to24\n");
+
+	pal = palette;
+	table = d_8to24table;
+	for (i=0 ; i<256 ; i++)
+	{
+		r = pal[0];
+		g = pal[1];
+		b = pal[2];
+		pal += 3;
+		
+//		v = (255<<24) + (r<<16) + (g<<8) + (b<<0);
+//		v = (255<<0) + (r<<8) + (g<<16) + (b<<24);
+		v = (255<<24) + (r<<0) + (g<<8) + (b<<16);
+		*table++ = v;
+	}
+	d_8to24table[255] &= 0xffffff;	// 255 is transparent
+
+	// JACK: 3D distance calcs - k is last closest, l is the distance.
+	// FIXME: Precalculate this and cache to disk.
+	if (palflag)
+		return;
+	palflag = true;
+
+	COM_FOpenFile("glquake/15to8.pal", &f);
+	if (f) {
+		fread(d_15to8table, 1<<15, 1, f);
+		fclose(f);
+	} else {
+		for (i=0; i < (1<<15); i++) {
+			/* Maps
+ 			000000000000000
+ 			000000000011111 = Red  = 0x1F
+ 			000001111100000 = Blue = 0x03E0
+ 			111110000000000 = Grn  = 0x7C00
+ 			*/
+ 			r = ((i & 0x1F) << 3)+4;
+ 			g = ((i & 0x03E0) >> 2)+4;
+ 			b = ((i & 0x7C00) >> 7)+4;
+			pal = (unsigned char *)d_8to24table;
+			for (v=0,k=0,bestdist=10000.0; v<256; v++,pal+=4) {
+ 				r1 = (int)r - (int)pal[0];
+ 				g1 = (int)g - (int)pal[1];
+ 				b1 = (int)b - (int)pal[2];
+				dist = sqrt(((r1*r1)+(g1*g1)+(b1*b1)));
+				if (dist < bestdist) {
+					k=v;
+					bestdist = dist;
+				}
+			}
+			d_15to8table[i]=k;
+		}
+		sprintf(s, "%s/glquake", com_gamedir);
+ 		Sys_mkdir (s);
+		sprintf(s, "%s/glquake/15to8.pal", com_gamedir);
+		if ((f = fopen(s, "wb")) != NULL) {
+			fwrite(d_15to8table, 1<<15, 1, f);
+			fclose(f);
+		}
+	}
+}
+
+/*
+===============
+GL_Init
+===============
+*/
+void GL_Init (void)
+{
+	gl_vendor = glGetString (GL_VENDOR);
+	Con_Printf ("GL_VENDOR: %s\n", gl_vendor);
+	gl_renderer = glGetString (GL_RENDERER);
+	Con_Printf ("GL_RENDERER: %s\n", gl_renderer);
+
+	gl_version = glGetString (GL_VERSION);
+	Con_Printf ("GL_VERSION: %s\n", gl_version);
+	gl_extensions = glGetString (GL_EXTENSIONS);
+	Con_Printf ("GL_EXTENSIONS: %s\n", gl_extensions);
+
+//	Con_Printf ("%s %s\n", gl_renderer, gl_version);
+
+	glClearColor (1,0,0,0);
+	glCullFace(GL_FRONT);
+	glEnable(GL_TEXTURE_2D);
+
+	glEnable(GL_ALPHA_TEST);
+	glAlphaFunc(GL_GREATER, 0.666);
+
+	glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
+	glShadeModel (GL_FLAT);
+
+	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+
+	glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+//	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+}
+
+/*
+=================
+GL_BeginRendering
+
+=================
+*/
+void GL_BeginRendering (int *x, int *y, int *width, int *height)
+{
+	extern cvar_t gl_clear;
+
+	*x = *y = 0;
+	*width = scr_width;
+	*height = scr_height;
+
+//    if (!wglMakeCurrent( maindc, baseRC ))
+//		Sys_Error ("wglMakeCurrent failed");
+
+//	glViewport (*x, *y, *width, *height);
+}
+
+
+void GL_EndRendering (void)
+{
+	glFlush();
+	glXSwapBuffers(dpy, win);
+}
+
+qboolean VID_Is8bit(void)
+{
+	return is8bit;
+}
+
+#ifdef GL_EXT_SHARED
+void VID_Init8bitPalette() 
+{
+	// Check for 8bit Extensions and initialize them.
+	int i;
+	char thePalette[256*3];
+	char *oldPalette, *newPalette;
+
+	if (strstr(gl_extensions, "GL_EXT_shared_texture_palette") == NULL)
+		return;
+
+	Con_SafePrintf("8-bit GL extensions enabled.\n");
+	glEnable( GL_SHARED_TEXTURE_PALETTE_EXT );
+	oldPalette = (char *) d_8to24table; //d_8to24table3dfx;
+	newPalette = thePalette;
+	for (i=0;i<256;i++) {
+		*newPalette++ = *oldPalette++;
+		*newPalette++ = *oldPalette++;
+		*newPalette++ = *oldPalette++;
+		oldPalette++;
+	}
+	glColorTableEXT(GL_SHARED_TEXTURE_PALETTE_EXT, GL_RGB, 256, GL_RGB, GL_UNSIGNED_BYTE, (void *) thePalette);
+	is8bit = true;
+}
+
+#else
+extern void gl3DfxSetPaletteEXT(GLuint *pal);
+
+void VID_Init8bitPalette(void) 
+{
+	// Check for 8bit Extensions and initialize them.
+	int i;
+	GLubyte table[256][4];
+	char *oldpal;
+
+	if (strstr(gl_extensions, "3DFX_set_global_palette") == NULL)
+		return;
+
+	Con_SafePrintf("8-bit GL extensions enabled.\n");
+	glEnable( GL_SHARED_TEXTURE_PALETTE_EXT );
+	oldpal = (char *) d_8to24table; //d_8to24table3dfx;
+	for (i=0;i<256;i++) {
+		table[i][2] = *oldpal++;
+		table[i][1] = *oldpal++;
+		table[i][0] = *oldpal++;
+		table[i][3] = 255;
+		oldpal++;
+	}
+	gl3DfxSetPaletteEXT((GLuint *)table);
+	is8bit = true;
+}
+#endif
+
+void VID_Init(unsigned char *palette)
+{
+	int i;
+	int attrib[] = {
+		GLX_RGBA,
+		GLX_RED_SIZE, 1,
+		GLX_GREEN_SIZE, 1,
+		GLX_BLUE_SIZE, 1,
+		GLX_DOUBLEBUFFER,
+		GLX_DEPTH_SIZE, 1,
+		None
+	};
+	char	gldir[MAX_OSPATH];
+	int width = 640, height = 480;
+	int scrnum;
+	XSetWindowAttributes attr;
+	unsigned long mask;
+	Window root;
+	XVisualInfo *visinfo;
+
+	S_Init();
+
+	Cvar_RegisterVariable (&vid_mode);
+	Cvar_RegisterVariable (&gl_ztrick);
+	Cvar_RegisterVariable (&_windowed_mouse);
+	
+	vid.maxwarpwidth = WARP_WIDTH;
+	vid.maxwarpheight = WARP_HEIGHT;
+	vid.colormap = host_colormap;
+	vid.fullbright = 256 - LittleLong (*((int *)vid.colormap + 2048));
+
+// interpret command-line params
+
+// set vid parameters
+	if ((i = COM_CheckParm("-width")) != 0)
+		width = atoi(com_argv[i+1]);
+	if ((i = COM_CheckParm("-height")) != 0)
+		height = atoi(com_argv[i+1]);
+
+	if ((i = COM_CheckParm("-conwidth")) != 0)
+		vid.conwidth = Q_atoi(com_argv[i+1]);
+	else
+		vid.conwidth = 640;
+
+	vid.conwidth &= 0xfff8; // make it a multiple of eight
+
+	if (vid.conwidth < 320)
+		vid.conwidth = 320;
+
+	// pick a conheight that matches with correct aspect
+	vid.conheight = vid.conwidth*3 / 4;
+
+	if ((i = COM_CheckParm("-conheight")) != 0)
+		vid.conheight = Q_atoi(com_argv[i+1]);
+	if (vid.conheight < 200)
+		vid.conheight = 200;
+
+	if (!(dpy = XOpenDisplay(NULL))) {
+		fprintf(stderr, "Error couldn't open the X display\n");
+		exit(1);
+	}
+
+	scrnum = DefaultScreen(dpy);
+	root = RootWindow(dpy, scrnum);
+
+	visinfo = glXChooseVisual(dpy, scrnum, attrib);
+	if (!visinfo) {
+		fprintf(stderr, "qkHack: Error couldn't get an RGB, Double-buffered, Depth visual\n");
+		exit(1);
+	}
+	/* window attributes */
+	attr.background_pixel = 0;
+	attr.border_pixel = 0;
+	attr.colormap = XCreateColormap(dpy, root, visinfo->visual, AllocNone);
+	attr.event_mask = X_MASK;
+	mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
+
+	win = XCreateWindow(dpy, root, 0, 0, width, height,
+						0, visinfo->depth, InputOutput,
+						visinfo->visual, mask, &attr);
+	XMapWindow(dpy, win);
+
+	XMoveWindow(dpy, win, 0, 0);
+
+	XFlush(dpy);
+
+	ctx = glXCreateContext(dpy, visinfo, NULL, True);
+
+	glXMakeCurrent(dpy, win, ctx);
+
+	scr_width = width;
+	scr_height = height;
+
+	if (vid.conheight > height)
+		vid.conheight = height;
+	if (vid.conwidth > width)
+		vid.conwidth = width;
+	vid.width = vid.conwidth;
+	vid.height = vid.conheight;
+
+	vid.aspect = ((float)vid.height / (float)vid.width) * (320.0 / 240.0);
+	vid.numpages = 2;
+
+	InitSig(); // trap evil signals
+
+	GL_Init();
+
+	sprintf (gldir, "%s/glquake", com_gamedir);
+	Sys_mkdir (gldir);
+
+	VID_SetPalette(palette);
+
+	// Check for 3DFX Extensions and initialize them.
+	VID_Init8bitPalette();
+
+	Con_SafePrintf ("Video mode %dx%d initialized.\n", width, height);
+
+	vid.recalc_refdef = 1;				// force a surface cache flush
+}
+
+void Sys_SendKeyEvents(void)
+{
+	if (dpy) {
+		while (XPending(dpy)) 
+			GetEvent();
+	}
+}
+
+void Force_CenterView_f (void)
+{
+	cl.viewangles[PITCH] = 0;
+}
+
+void IN_Init(void)
+{
+}
+
+void IN_Shutdown(void)
+{
+}
+
+/*
+===========
+IN_Commands
+===========
+*/
+void IN_Commands (void)
+{
+}
+
+/*
+===========
+IN_Move
+===========
+*/
+void IN_MouseMove (usercmd_t *cmd)
+{
+	if (m_filter.value)
+	{
+		mouse_x = (mouse_x + old_mouse_x) * 0.5;
+		mouse_y = (mouse_y + old_mouse_y) * 0.5;
+	}
+	old_mouse_x = mouse_x;
+	old_mouse_y = mouse_y;
+
+	mouse_x *= sensitivity.value;
+	mouse_y *= sensitivity.value;
+
+// add mouse X/Y movement to cmd
+	if ( (in_strafe.state & 1) || (lookstrafe.value && (in_mlook.state & 1) ))
+		cmd->sidemove += m_side.value * mouse_x;
+	else
+		cl.viewangles[YAW] -= m_yaw.value * mouse_x;
+	
+	if (in_mlook.state & 1)
+		V_StopPitchDrift ();
+		
+	if ( (in_mlook.state & 1) && !(in_strafe.state & 1))
+	{
+		cl.viewangles[PITCH] += m_pitch.value * mouse_y;
+		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 * mouse_y;
+		else
+			cmd->forwardmove -= m_forward.value * mouse_y;
+	}
+	mouse_x = mouse_y = 0.0;
+}
+
+void IN_Move (usercmd_t *cmd)
+{
+	IN_MouseMove(cmd);
+}
+
+
+void VID_UnlockBuffer() {}
+void VID_LockBuffer() {}
+
--- /dev/null
+++ b/QW/client/gl_vidnt.c
@@ -1,0 +1,1949 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// gl_vidnt.c -- NT GL vid component
+
+#include "quakedef.h"
+#include "winquake.h"
+#include "resource.h"
+#include <commctrl.h>
+
+#define MAX_MODE_LIST	30
+#define VID_ROW_SIZE	3
+#define WARP_WIDTH		320
+#define WARP_HEIGHT		200
+#define MAXWIDTH		10000
+#define MAXHEIGHT		10000
+#define BASEWIDTH		320
+#define BASEHEIGHT		200
+
+#define MODE_WINDOWED			0
+#define NO_MODE					(MODE_WINDOWED - 1)
+#define MODE_FULLSCREEN_DEFAULT	(MODE_WINDOWED + 1)
+
+typedef struct {
+	modestate_t	type;
+	int			width;
+	int			height;
+	int			modenum;
+	int			dib;
+	int			fullscreen;
+	int			bpp;
+	int			halfscreen;
+	char		modedesc[17];
+} vmode_t;
+
+typedef struct {
+	int			width;
+	int			height;
+} lmode_t;
+
+lmode_t	lowresmodes[] = {
+	{320, 200},
+	{320, 240},
+	{400, 300},
+	{512, 384},
+};
+
+const char *gl_vendor;
+const char *gl_renderer;
+const char *gl_version;
+const char *gl_extensions;
+
+qboolean		DDActive;
+qboolean		scr_skipupdate;
+
+static vmode_t	modelist[MAX_MODE_LIST];
+static int		nummodes;
+static vmode_t	*pcurrentmode;
+static vmode_t	badmode;
+
+static DEVMODE	gdevmode;
+static qboolean	vid_initialized = false;
+static qboolean	windowed, leavecurrentmode;
+static qboolean vid_canalttab = false;
+static qboolean vid_wassuspended = false;
+static int		windowed_mouse;
+extern qboolean	mouseactive;  // from in_win.c
+static HICON	hIcon;
+
+int			DIBWidth, DIBHeight;
+RECT		WindowRect;
+DWORD		WindowStyle, ExWindowStyle;
+
+HWND	mainwindow, dibwindow;
+
+int			vid_modenum = NO_MODE;
+int			vid_realmode;
+int			vid_default = MODE_WINDOWED;
+static int	windowed_default;
+unsigned char	vid_curpal[256*3];
+static qboolean fullsbardraw = false;
+
+static float vid_gamma = 1.0;
+
+HGLRC	baseRC;
+HDC		maindc;
+
+glvert_t glv;
+
+cvar_t	gl_ztrick = {"gl_ztrick","1"};
+
+HWND WINAPI InitializeWindow (HINSTANCE hInstance, int nCmdShow);
+
+viddef_t	vid;				// global video state
+
+unsigned short	d_8to16table[256];
+unsigned	d_8to24table[256];
+unsigned char d_15to8table[65536];
+
+float		gldepthmin, gldepthmax;
+
+modestate_t	modestate = MS_UNINIT;
+
+void VID_MenuDraw (void);
+void VID_MenuKey (int key);
+
+LONG WINAPI MainWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
+void AppActivate(BOOL fActive, BOOL minimize);
+char *VID_GetModeDescription (int mode);
+void ClearAllStates (void);
+void VID_UpdateWindowStatus (void);
+void GL_Init (void);
+
+PROC glArrayElementEXT;
+PROC glColorPointerEXT;
+PROC glTexCoordPointerEXT;
+PROC glVertexPointerEXT;
+
+typedef void (APIENTRY *lp3DFXFUNC) (int, int, int, int, int, const void*);
+lp3DFXFUNC glColorTableEXT;
+qboolean is8bit = false;
+qboolean isPermedia = false;
+qboolean gl_mtexable = false;
+
+//====================================
+
+cvar_t		vid_mode = {"vid_mode","0", false};
+// Note that 0 is MODE_WINDOWED
+cvar_t		_vid_default_mode = {"_vid_default_mode","0", true};
+// Note that 3 is MODE_FULLSCREEN_DEFAULT
+cvar_t		_vid_default_mode_win = {"_vid_default_mode_win","3", true};
+cvar_t		vid_wait = {"vid_wait","0"};
+cvar_t		vid_nopageflip = {"vid_nopageflip","0", true};
+cvar_t		_vid_wait_override = {"_vid_wait_override", "0", true};
+cvar_t		vid_config_x = {"vid_config_x","800", true};
+cvar_t		vid_config_y = {"vid_config_y","600", true};
+cvar_t		vid_stretch_by_2 = {"vid_stretch_by_2","1", true};
+cvar_t		_windowed_mouse = {"_windowed_mouse","1", true};
+
+int			window_center_x, window_center_y, window_x, window_y, window_width, window_height;
+RECT		window_rect;
+
+// direct draw software compatability stuff
+
+void VID_HandlePause (qboolean pause)
+{
+}
+
+void VID_ForceLockState (int lk)
+{
+}
+
+void VID_LockBuffer (void)
+{
+}
+
+void VID_UnlockBuffer (void)
+{
+}
+
+int VID_ForceUnlockedAndReturnState (void)
+{
+	return 0;
+}
+
+void D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height)
+{
+}
+
+void D_EndDirectRect (int x, int y, int width, int height)
+{
+}
+
+
+void CenterWindow(HWND hWndCenter, int width, int height, BOOL lefttopjustify)
+{
+    RECT    rect;
+    int     CenterX, CenterY;
+
+	CenterX = (GetSystemMetrics(SM_CXSCREEN) - width) / 2;
+	CenterY = (GetSystemMetrics(SM_CYSCREEN) - height) / 2;
+	if (CenterX > CenterY*2)
+		CenterX >>= 1;	// dual screens
+	CenterX = (CenterX < 0) ? 0: CenterX;
+	CenterY = (CenterY < 0) ? 0: CenterY;
+	SetWindowPos (hWndCenter, NULL, CenterX, CenterY, 0, 0,
+			SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW | SWP_DRAWFRAME);
+}
+
+qboolean VID_SetWindowedMode (int modenum)
+{
+	HDC				hdc;
+	int				lastmodestate, width, height;
+	RECT			rect;
+
+	lastmodestate = modestate;
+
+	WindowRect.top = WindowRect.left = 0;
+
+	WindowRect.right = modelist[modenum].width;
+	WindowRect.bottom = modelist[modenum].height;
+
+	DIBWidth = modelist[modenum].width;
+	DIBHeight = modelist[modenum].height;
+
+	WindowStyle = WS_OVERLAPPED | WS_BORDER | WS_CAPTION | WS_SYSMENU |
+				  WS_MINIMIZEBOX;
+	ExWindowStyle = 0;
+
+	rect = WindowRect;
+	AdjustWindowRectEx(&rect, WindowStyle, FALSE, 0);
+
+	width = rect.right - rect.left;
+	height = rect.bottom - rect.top;
+
+	// Create the DIB window
+	dibwindow = CreateWindowEx (
+		 ExWindowStyle,
+		 "WinQuake",
+		 "GLQuake",
+		 WindowStyle,
+		 rect.left, rect.top,
+		 width,
+		 height,
+		 NULL,
+		 NULL,
+		 global_hInstance,
+		 NULL);
+
+	if (!dibwindow)
+		Sys_Error ("Couldn't create DIB window");
+
+	// Center and show the DIB window
+	CenterWindow(dibwindow, WindowRect.right - WindowRect.left,
+				 WindowRect.bottom - WindowRect.top, false);
+
+	ShowWindow (dibwindow, SW_SHOWDEFAULT);
+	UpdateWindow (dibwindow);
+
+	modestate = MS_WINDOWED;
+
+// because we have set the background brush for the window to NULL
+// (to avoid flickering when re-sizing the window on the desktop),
+// we clear the window to black when created, otherwise it will be
+// empty while Quake starts up.
+	hdc = GetDC(dibwindow);
+	PatBlt(hdc,0,0,WindowRect.right,WindowRect.bottom,BLACKNESS);
+	ReleaseDC(dibwindow, hdc);
+
+	if (vid.conheight > modelist[modenum].height)
+		vid.conheight = modelist[modenum].height;
+	if (vid.conwidth > modelist[modenum].width)
+		vid.conwidth = modelist[modenum].width;
+	vid.width = vid.conwidth;
+	vid.height = vid.conheight;
+
+	vid.numpages = 2;
+
+	mainwindow = dibwindow;
+
+	SendMessage (mainwindow, WM_SETICON, (WPARAM)TRUE, (LPARAM)hIcon);
+	SendMessage (mainwindow, WM_SETICON, (WPARAM)FALSE, (LPARAM)hIcon);
+
+	return true;
+}
+
+
+qboolean VID_SetFullDIBMode (int modenum)
+{
+	HDC				hdc;
+	int				lastmodestate, width, height;
+	RECT			rect;
+
+	if (!leavecurrentmode)
+	{
+		gdevmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
+		gdevmode.dmBitsPerPel = modelist[modenum].bpp;
+		gdevmode.dmPelsWidth = modelist[modenum].width <<
+							   modelist[modenum].halfscreen;
+		gdevmode.dmPelsHeight = modelist[modenum].height;
+		gdevmode.dmSize = sizeof (gdevmode);
+
+		if (ChangeDisplaySettings (&gdevmode, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL)
+			Sys_Error ("Couldn't set fullscreen DIB mode");
+	}
+
+	lastmodestate = modestate;
+	modestate = MS_FULLDIB;
+
+	WindowRect.top = WindowRect.left = 0;
+
+	WindowRect.right = modelist[modenum].width;
+	WindowRect.bottom = modelist[modenum].height;
+
+	DIBWidth = modelist[modenum].width;
+	DIBHeight = modelist[modenum].height;
+
+	WindowStyle = WS_POPUP;
+	ExWindowStyle = 0;
+
+	rect = WindowRect;
+	AdjustWindowRectEx(&rect, WindowStyle, FALSE, 0);
+
+	width = rect.right - rect.left;
+	height = rect.bottom - rect.top;
+
+	// Create the DIB window
+	dibwindow = CreateWindowEx (
+		 ExWindowStyle,
+		 "WinQuake",
+		 "GLQuake",
+		 WindowStyle,
+		 rect.left, rect.top,
+		 width,
+		 height,
+		 NULL,
+		 NULL,
+		 global_hInstance,
+		 NULL);
+
+	if (!dibwindow)
+		Sys_Error ("Couldn't create DIB window");
+
+	ShowWindow (dibwindow, SW_SHOWDEFAULT);
+	UpdateWindow (dibwindow);
+
+	// Because we have set the background brush for the window to NULL
+	// (to avoid flickering when re-sizing the window on the desktop), we
+	// clear the window to black when created, otherwise it will be
+	// empty while Quake starts up.
+	hdc = GetDC(dibwindow);
+	PatBlt(hdc,0,0,WindowRect.right,WindowRect.bottom,BLACKNESS);
+	ReleaseDC(dibwindow, hdc);
+
+	if (vid.conheight > modelist[modenum].height)
+		vid.conheight = modelist[modenum].height;
+	if (vid.conwidth > modelist[modenum].width)
+		vid.conwidth = modelist[modenum].width;
+	vid.width = vid.conwidth;
+	vid.height = vid.conheight;
+
+	vid.numpages = 2;
+
+// needed because we're not getting WM_MOVE messages fullscreen on NT
+	window_x = 0;
+	window_y = 0;
+
+	mainwindow = dibwindow;
+
+	SendMessage (mainwindow, WM_SETICON, (WPARAM)TRUE, (LPARAM)hIcon);
+	SendMessage (mainwindow, WM_SETICON, (WPARAM)FALSE, (LPARAM)hIcon);
+
+	return true;
+}
+
+
+int VID_SetMode (int modenum, unsigned char *palette)
+{
+	int				original_mode, temp;
+	qboolean		stat;
+    MSG				msg;
+	HDC				hdc;
+
+	if ((windowed && (modenum != 0)) ||
+		(!windowed && (modenum < 1)) ||
+		(!windowed && (modenum >= nummodes)))
+	{
+		Sys_Error ("Bad video mode\n");
+	}
+
+// so Con_Printfs don't mess us up by forcing vid and snd updates
+	temp = scr_disabled_for_loading;
+	scr_disabled_for_loading = true;
+
+	CDAudio_Pause ();
+
+	if (vid_modenum == NO_MODE)
+		original_mode = windowed_default;
+	else
+		original_mode = vid_modenum;
+
+	// Set either the fullscreen or windowed mode
+	if (modelist[modenum].type == MS_WINDOWED)
+	{
+		if (_windowed_mouse.value && key_dest == key_game)
+		{
+			stat = VID_SetWindowedMode(modenum);
+			IN_ActivateMouse ();
+			IN_HideMouse ();
+		}
+		else
+		{
+			IN_DeactivateMouse ();
+			IN_ShowMouse ();
+			stat = VID_SetWindowedMode(modenum);
+		}
+	}
+	else if (modelist[modenum].type == MS_FULLDIB)
+	{
+		stat = VID_SetFullDIBMode(modenum);
+		IN_ActivateMouse ();
+		IN_HideMouse ();
+	}
+	else
+	{
+		Sys_Error ("VID_SetMode: Bad mode type in modelist");
+	}
+
+	window_width = DIBWidth;
+	window_height = DIBHeight;
+	VID_UpdateWindowStatus ();
+
+	CDAudio_Resume ();
+	scr_disabled_for_loading = temp;
+
+	if (!stat)
+	{
+		Sys_Error ("Couldn't set video mode");
+	}
+
+// now we try to make sure we get the focus on the mode switch, because
+// sometimes in some systems we don't.  We grab the foreground, then
+// finish setting up, pump all our messages, and sleep for a little while
+// to let messages finish bouncing around the system, then we put
+// ourselves at the top of the z order, then grab the foreground again,
+// Who knows if it helps, but it probably doesn't hurt
+	SetForegroundWindow (mainwindow);
+	VID_SetPalette (palette);
+	vid_modenum = modenum;
+	Cvar_SetValue ("vid_mode", (float)vid_modenum);
+
+	while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE))
+	{
+      	TranslateMessage (&msg);
+      	DispatchMessage (&msg);
+	}
+
+	Sleep (100);
+
+	SetWindowPos (mainwindow, HWND_TOP, 0, 0, 0, 0,
+				  SWP_DRAWFRAME | SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW |
+				  SWP_NOCOPYBITS);
+
+	SetForegroundWindow (mainwindow);
+
+// fix the leftover Alt from any Alt-Tab or the like that switched us away
+	ClearAllStates ();
+
+	if (!msg_suppress_1)
+		Con_SafePrintf ("Video mode %s initialized.\n", VID_GetModeDescription (vid_modenum));
+
+	VID_SetPalette (palette);
+
+	vid.recalc_refdef = 1;
+
+	return true;
+}
+
+
+/*
+================
+VID_UpdateWindowStatus
+================
+*/
+void VID_UpdateWindowStatus (void)
+{
+
+	window_rect.left = window_x;
+	window_rect.top = window_y;
+	window_rect.right = window_x + window_width;
+	window_rect.bottom = window_y + window_height;
+	window_center_x = (window_rect.left + window_rect.right) / 2;
+	window_center_y = (window_rect.top + window_rect.bottom) / 2;
+
+	IN_UpdateClipCursor ();
+}
+
+
+//====================================
+
+BINDTEXFUNCPTR bindTexFunc;
+
+#define TEXTURE_EXT_STRING "GL_EXT_texture_object"
+
+
+void CheckTextureExtensions (void)
+{
+	char		*tmp;
+	qboolean	texture_ext;
+	HINSTANCE	hInstGL;
+
+	texture_ext = FALSE;
+	/* check for texture extension */
+	tmp = (unsigned char *)glGetString(GL_EXTENSIONS);
+	while (*tmp)
+	{
+		if (strncmp((const char*)tmp, TEXTURE_EXT_STRING, strlen(TEXTURE_EXT_STRING)) == 0)
+			texture_ext = TRUE;
+		tmp++;
+	}
+
+	if (!texture_ext || COM_CheckParm ("-gl11") )
+	{
+		hInstGL = LoadLibrary("opengl32.dll");
+		
+		if (hInstGL == NULL)
+			Sys_Error ("Couldn't load opengl32.dll\n");
+
+		bindTexFunc = (void *)GetProcAddress(hInstGL,"glBindTexture");
+
+		if (!bindTexFunc)
+			Sys_Error ("No texture objects!");
+		return;
+	}
+
+/* load library and get procedure adresses for texture extension API */
+	if ((bindTexFunc = (BINDTEXFUNCPTR)
+		wglGetProcAddress((LPCSTR) "glBindTextureEXT")) == NULL)
+	{
+		Sys_Error ("GetProcAddress for BindTextureEXT failed");
+		return;
+	}
+}
+
+void CheckArrayExtensions (void)
+{
+	char		*tmp;
+
+	/* check for texture extension */
+	tmp = (unsigned char *)glGetString(GL_EXTENSIONS);
+	while (*tmp)
+	{
+		if (strncmp((const char*)tmp, "GL_EXT_vertex_array", strlen("GL_EXT_vertex_array")) == 0)
+		{
+			if (
+((glArrayElementEXT = wglGetProcAddress("glArrayElementEXT")) == NULL) ||
+((glColorPointerEXT = wglGetProcAddress("glColorPointerEXT")) == NULL) ||
+((glTexCoordPointerEXT = wglGetProcAddress("glTexCoordPointerEXT")) == NULL) ||
+((glVertexPointerEXT = wglGetProcAddress("glVertexPointerEXT")) == NULL) )
+			{
+				Sys_Error ("GetProcAddress for vertex extension failed");
+				return;
+			}
+			return;
+		}
+		tmp++;
+	}
+
+	Sys_Error ("Vertex array extension not present");
+}
+
+//int		texture_mode = GL_NEAREST;
+//int		texture_mode = GL_NEAREST_MIPMAP_NEAREST;
+//int		texture_mode = GL_NEAREST_MIPMAP_LINEAR;
+int		texture_mode = GL_LINEAR;
+//int		texture_mode = GL_LINEAR_MIPMAP_NEAREST;
+//int		texture_mode = GL_LINEAR_MIPMAP_LINEAR;
+
+int		texture_extension_number = 1;
+
+#ifdef _WIN32
+void CheckMultiTextureExtensions(void) 
+{
+	if (strstr(gl_extensions, "GL_SGIS_multitexture ") && !COM_CheckParm("-nomtex")) {
+		Con_Printf("Multitexture extensions found.\n");
+		qglMTexCoord2fSGIS = (void *) wglGetProcAddress("glMTexCoord2fSGIS");
+		qglSelectTextureSGIS = (void *) wglGetProcAddress("glSelectTextureSGIS");
+		gl_mtexable = true;
+	}
+}
+#else
+void CheckMultiTextureExtensions(void) 
+{
+		gl_mtexable = true;
+}
+#endif
+
+/*
+===============
+GL_Init
+===============
+*/
+void GL_Init (void)
+{
+	gl_vendor = glGetString (GL_VENDOR);
+	Con_Printf ("GL_VENDOR: %s\n", gl_vendor);
+	gl_renderer = glGetString (GL_RENDERER);
+	Con_Printf ("GL_RENDERER: %s\n", gl_renderer);
+
+	gl_version = glGetString (GL_VERSION);
+	Con_Printf ("GL_VERSION: %s\n", gl_version);
+	gl_extensions = glGetString (GL_EXTENSIONS);
+	Con_Printf ("GL_EXTENSIONS: %s\n", gl_extensions);
+
+//	Con_Printf ("%s %s\n", gl_renderer, gl_version);
+
+    if (strnicmp(gl_renderer,"PowerVR",7)==0)
+         fullsbardraw = true;
+
+    if (strnicmp(gl_renderer,"Permedia",8)==0)
+         isPermedia = true;
+
+	CheckTextureExtensions ();
+	CheckMultiTextureExtensions ();
+
+	glClearColor (1,0,0,0);
+	glCullFace(GL_FRONT);
+	glEnable(GL_TEXTURE_2D);
+
+	glEnable(GL_ALPHA_TEST);
+	glAlphaFunc(GL_GREATER, 0.666);
+
+	glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
+	glShadeModel (GL_FLAT);
+
+	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+
+	glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+//	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+
+#if 0
+	CheckArrayExtensions ();
+
+	glEnable (GL_VERTEX_ARRAY_EXT);
+	glEnable (GL_TEXTURE_COORD_ARRAY_EXT);
+	glVertexPointerEXT (3, GL_FLOAT, 0, 0, &glv.x);
+	glTexCoordPointerEXT (2, GL_FLOAT, 0, 0, &glv.s);
+	glColorPointerEXT (3, GL_FLOAT, 0, 0, &glv.r);
+#endif
+}
+
+/*
+=================
+GL_BeginRendering
+
+=================
+*/
+void GL_BeginRendering (int *x, int *y, int *width, int *height)
+{
+	extern cvar_t gl_clear;
+
+	*x = *y = 0;
+	*width = WindowRect.right - WindowRect.left;
+	*height = WindowRect.bottom - WindowRect.top;
+
+//    if (!wglMakeCurrent( maindc, baseRC ))
+//		Sys_Error ("wglMakeCurrent failed");
+
+//	glViewport (*x, *y, *width, *height);
+}
+
+
+void GL_EndRendering (void)
+{
+	if (!scr_skipupdate || block_drawing)
+		SwapBuffers(maindc);
+
+// handle the mouse state when windowed if that's changed
+	if (modestate == MS_WINDOWED)
+	{
+		if (!_windowed_mouse.value) {
+			if (windowed_mouse)	{
+				IN_DeactivateMouse ();
+				IN_ShowMouse ();
+				windowed_mouse = false;
+			}
+		} else {
+			windowed_mouse = true;
+			if (key_dest == key_game && !mouseactive && ActiveApp) {
+				IN_ActivateMouse ();
+				IN_HideMouse ();
+			} else if (mouseactive && key_dest != key_game) {
+				IN_DeactivateMouse ();
+				IN_ShowMouse ();
+			}
+		}
+	}
+	if (fullsbardraw)
+		Sbar_Changed();
+}
+
+void	VID_SetPalette (unsigned char *palette)
+{
+	byte	*pal;
+	unsigned r,g,b;
+	unsigned v;
+	int     r1,g1,b1;
+	int		j,k,l,m;
+	unsigned short i;
+	unsigned	*table;
+	FILE *f;
+	char s[255];
+	HWND hDlg, hProgress;
+	float gamma;
+
+//
+// 8 8 8 encoding
+//
+	pal = palette;
+	table = d_8to24table;
+	for (i=0 ; i<256 ; i++)
+	{
+		r = pal[0];
+		g = pal[1];
+		b = pal[2];
+		pal += 3;
+		
+//		v = (255<<24) + (r<<16) + (g<<8) + (b<<0);
+//		v = (255<<0) + (r<<8) + (g<<16) + (b<<24);
+		v = (255<<24) + (r<<0) + (g<<8) + (b<<16);
+		*table++ = v;
+	}
+	d_8to24table[255] &= 0xffffff;	// 255 is transparent
+
+	// JACK: 3D distance calcs - k is last closest, l is the distance.
+	// FIXME: Precalculate this and cache to disk.
+	for (i=0; i < (1<<15); i++) {
+		/* Maps
+			000000000000000
+			000000000011111 = Red  = 0x1F
+			000001111100000 = Blue = 0x03E0
+			111110000000000 = Grn  = 0x7C00
+		*/
+		r = ((i & 0x1F) << 3)+4;
+		g = ((i & 0x03E0) >> 2)+4;
+		b = ((i & 0x7C00) >> 7)+4;
+		pal = (unsigned char *)d_8to24table;
+		for (v=0,k=0,l=10000*10000; v<256; v++,pal+=4) {
+			r1 = r-pal[0];
+			g1 = g-pal[1];
+			b1 = b-pal[2];
+			j = (r1*r1)+(g1*g1)+(b1*b1);
+			if (j<l) {
+				k=v;
+				l=j;
+			}
+		}
+		d_15to8table[i]=k;
+	}
+}
+
+BOOL	gammaworks;
+
+void	VID_ShiftPalette (unsigned char *palette)
+{
+	extern	byte ramps[3][256];
+	
+//	VID_SetPalette (palette);
+
+//	gammaworks = SetDeviceGammaRamp (maindc, ramps);
+}
+
+
+void VID_SetDefaultMode (void)
+{
+	IN_DeactivateMouse ();
+}
+
+
+void	VID_Shutdown (void)
+{
+   	HGLRC hRC;
+   	HDC	  hDC;
+
+	if (vid_initialized)
+	{
+		vid_canalttab = false;
+		hRC = wglGetCurrentContext();
+    	hDC = wglGetCurrentDC();
+
+    	wglMakeCurrent(NULL, NULL);
+
+    	if (hRC)
+    	    wglDeleteContext(hRC);
+
+		if (hDC && dibwindow)
+			ReleaseDC(dibwindow, hDC);
+
+		if (modestate == MS_FULLDIB)
+			ChangeDisplaySettings (NULL, 0);
+
+		if (maindc && dibwindow)
+			ReleaseDC (dibwindow, maindc);
+
+		AppActivate(false, false);
+	}
+}
+
+
+//==========================================================================
+
+
+BOOL bSetupPixelFormat(HDC hDC)
+{
+    static PIXELFORMATDESCRIPTOR pfd = {
+	sizeof(PIXELFORMATDESCRIPTOR),	// size of this pfd
+	1,				// version number
+	PFD_DRAW_TO_WINDOW 		// support window
+	|  PFD_SUPPORT_OPENGL 	// support OpenGL
+	|  PFD_DOUBLEBUFFER ,	// double buffered
+	PFD_TYPE_RGBA,			// RGBA type
+	24,				// 24-bit color depth
+	0, 0, 0, 0, 0, 0,		// color bits ignored
+	0,				// no alpha buffer
+	0,				// shift bit ignored
+	0,				// no accumulation buffer
+	0, 0, 0, 0, 			// accum bits ignored
+	32,				// 32-bit z-buffer	
+	0,				// no stencil buffer
+	0,				// no auxiliary buffer
+	PFD_MAIN_PLANE,			// main layer
+	0,				// reserved
+	0, 0, 0				// layer masks ignored
+    };
+    int pixelformat;
+
+    if ( (pixelformat = ChoosePixelFormat(hDC, &pfd)) == 0 )
+    {
+        MessageBox(NULL, "ChoosePixelFormat failed", "Error", MB_OK);
+        return FALSE;
+    }
+
+    if (SetPixelFormat(hDC, pixelformat, &pfd) == FALSE)
+    {
+        MessageBox(NULL, "SetPixelFormat failed", "Error", MB_OK);
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
+
+
+byte        scantokey[128] = 
+					{ 
+//  0           1       2       3       4       5       6       7 
+//  8           9       A       B       C       D       E       F 
+	0  ,    27,     '1',    '2',    '3',    '4',    '5',    '6', 
+	'7',    '8',    '9',    '0',    '-',    '=',    K_BACKSPACE, 9, // 0 
+	'q',    'w',    'e',    'r',    't',    'y',    'u',    'i', 
+	'o',    'p',    '[',    ']',    13 ,    K_CTRL,'a',  's',      // 1 
+	'd',    'f',    'g',    'h',    'j',    'k',    'l',    ';', 
+	'\'' ,    '`',    K_SHIFT,'\\',  'z',    'x',    'c',    'v',      // 2 
+	'b',    'n',    'm',    ',',    '.',    '/',    K_SHIFT,'*', 
+	K_ALT,' ',   0  ,    K_F1, K_F2, K_F3, K_F4, K_F5,   // 3 
+	K_F6, K_F7, K_F8, K_F9, K_F10, K_PAUSE  ,    0  , K_HOME, 
+	K_UPARROW,K_PGUP,'-',K_LEFTARROW,'5',K_RIGHTARROW,'+',K_END, //4 
+	K_DOWNARROW,K_PGDN,K_INS,K_DEL,0,0,             0,              K_F11, 
+	K_F12,0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0,        // 5 
+	0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0, 
+	0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0,        // 6 
+	0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0, 
+	0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0         // 7 
+					}; 
+
+byte        shiftscantokey[128] = 
+					{ 
+//  0           1       2       3       4       5       6       7 
+//  8           9       A       B       C       D       E       F 
+	0  ,    27,     '!',    '@',    '#',    '$',    '%',    '^', 
+	'&',    '*',    '(',    ')',    '_',    '+',    K_BACKSPACE, 9, // 0 
+	'Q',    'W',    'E',    'R',    'T',    'Y',    'U',    'I', 
+	'O',    'P',    '{',    '}',    13 ,    K_CTRL,'A',  'S',      // 1 
+	'D',    'F',    'G',    'H',    'J',    'K',    'L',    ':', 
+	'"' ,    '~',    K_SHIFT,'|',  'Z',    'X',    'C',    'V',      // 2 
+	'B',    'N',    'M',    '<',    '>',    '?',    K_SHIFT,'*', 
+	K_ALT,' ',   0  ,    K_F1, K_F2, K_F3, K_F4, K_F5,   // 3 
+	K_F6, K_F7, K_F8, K_F9, K_F10, K_PAUSE  ,    0  , K_HOME, 
+	K_UPARROW,K_PGUP,'_',K_LEFTARROW,'%',K_RIGHTARROW,'+',K_END, //4 
+	K_DOWNARROW,K_PGDN,K_INS,K_DEL,0,0,             0,              K_F11, 
+	K_F12,0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0,        // 5 
+	0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0, 
+	0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0,        // 6 
+	0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0, 
+	0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0         // 7 
+					}; 
+
+
+/*
+=======
+MapKey
+
+Map from windows to quake keynums
+=======
+*/
+int MapKey (int key)
+{
+	key = (key>>16)&255;
+	if (key > 127)
+		return 0;
+	if (scantokey[key] == 0)
+		Con_DPrintf("key 0x%02x has no translation\n", key);
+	return scantokey[key];
+}
+
+/*
+===================================================================
+
+MAIN WINDOW
+
+===================================================================
+*/
+
+/*
+================
+ClearAllStates
+================
+*/
+void ClearAllStates (void)
+{
+	int		i;
+	
+// send an up event for each key, to make sure the server clears them all
+	for (i=0 ; i<256 ; i++)
+	{
+		Key_Event (i, false);
+	}
+
+	Key_ClearStates ();
+	IN_ClearStates ();
+}
+
+void AppActivate(BOOL fActive, BOOL minimize)
+/****************************************************************************
+*
+* Function:     AppActivate
+* Parameters:   fActive - True if app is activating
+*
+* Description:  If the application is activating, then swap the system
+*               into SYSPAL_NOSTATIC mode so that our palettes will display
+*               correctly.
+*
+****************************************************************************/
+{
+	MSG msg;
+    HDC			hdc;
+    int			i, t;
+	static BOOL	sound_active;
+
+	ActiveApp = fActive;
+	Minimized = minimize;
+
+// enable/disable sound on focus gain/loss
+	if (!ActiveApp && sound_active)
+	{
+		S_BlockSound ();
+		sound_active = false;
+	}
+	else if (ActiveApp && !sound_active)
+	{
+		S_UnblockSound ();
+		sound_active = true;
+	}
+
+	if (fActive)
+	{
+		if (modestate == MS_FULLDIB)
+		{
+			IN_ActivateMouse ();
+			IN_HideMouse ();
+			if (vid_canalttab && vid_wassuspended) {
+				vid_wassuspended = false;
+				ChangeDisplaySettings (&gdevmode, CDS_FULLSCREEN);
+				ShowWindow(mainwindow, SW_SHOWNORMAL);
+			}
+		}
+		else if ((modestate == MS_WINDOWED) && _windowed_mouse.value && key_dest == key_game)
+		{
+			IN_ActivateMouse ();
+			IN_HideMouse ();
+		}
+	}
+
+	if (!fActive)
+	{
+		if (modestate == MS_FULLDIB)
+		{
+			IN_DeactivateMouse ();
+			IN_ShowMouse ();
+			if (vid_canalttab) { 
+				ChangeDisplaySettings (NULL, 0);
+				vid_wassuspended = true;
+			}
+		}
+		else if ((modestate == MS_WINDOWED) && _windowed_mouse.value)
+		{
+			IN_DeactivateMouse ();
+			IN_ShowMouse ();
+		}
+	}
+}
+
+
+/* main window procedure */
+LONG WINAPI MainWndProc (
+    HWND    hWnd,
+    UINT    uMsg,
+    WPARAM  wParam,
+    LPARAM  lParam)
+{
+    LONG    lRet = 1;
+	int		fwKeys, xPos, yPos, fActive, fMinimized, temp;
+	extern unsigned int uiWheelMessage;
+
+	if ( uMsg == uiWheelMessage )
+		uMsg = WM_MOUSEWHEEL;
+
+    switch (uMsg)
+    {
+		case WM_KILLFOCUS:
+			if (modestate == MS_FULLDIB)
+				ShowWindow(mainwindow, SW_SHOWMINNOACTIVE);
+			break;
+
+		case WM_CREATE:
+			break;
+
+		case WM_MOVE:
+			window_x = (int) LOWORD(lParam);
+			window_y = (int) HIWORD(lParam);
+			VID_UpdateWindowStatus ();
+			break;
+
+		case WM_KEYDOWN:
+		case WM_SYSKEYDOWN:
+			Key_Event (MapKey(lParam), true);
+			break;
+			
+		case WM_KEYUP:
+		case WM_SYSKEYUP:
+			Key_Event (MapKey(lParam), false);
+			break;
+
+		case WM_SYSCHAR:
+		// keep Alt-Space from happening
+			break;
+
+	// this is complicated because Win32 seems to pack multiple mouse events into
+	// one update sometimes, so we always check all states and look for events
+		case WM_LBUTTONDOWN:
+		case WM_LBUTTONUP:
+		case WM_RBUTTONDOWN:
+		case WM_RBUTTONUP:
+		case WM_MBUTTONDOWN:
+		case WM_MBUTTONUP:
+		case WM_MOUSEMOVE:
+			temp = 0;
+
+			if (wParam & MK_LBUTTON)
+				temp |= 1;
+
+			if (wParam & MK_RBUTTON)
+				temp |= 2;
+
+			if (wParam & MK_MBUTTON)
+				temp |= 4;
+
+			IN_MouseEvent (temp);
+
+			break;
+
+		// JACK: This is the mouse wheel with the Intellimouse
+		// Its delta is either positive or neg, and we generate the proper
+		// Event.
+		case WM_MOUSEWHEEL: 
+			if ((short) HIWORD(wParam) > 0) {
+				Key_Event(K_MWHEELUP, true);
+				Key_Event(K_MWHEELUP, false);
+			} else {
+				Key_Event(K_MWHEELDOWN, true);
+				Key_Event(K_MWHEELDOWN, false);
+			}
+			break;
+
+    	case WM_SIZE:
+            break;
+
+   	    case WM_CLOSE:
+			if (MessageBox (mainwindow, "Are you sure you want to quit?", "Confirm Exit",
+						MB_YESNO | MB_SETFOREGROUND | MB_ICONQUESTION) == IDYES)
+			{
+				Sys_Quit ();
+			}
+
+	        break;
+
+		case WM_ACTIVATE:
+			fActive = LOWORD(wParam);
+			fMinimized = (BOOL) HIWORD(wParam);
+			AppActivate(!(fActive == WA_INACTIVE), fMinimized);
+
+		// fix the leftover Alt from any Alt-Tab or the like that switched us away
+			ClearAllStates ();
+
+			break;
+
+   	    case WM_DESTROY:
+        {
+			if (dibwindow)
+				DestroyWindow (dibwindow);
+
+            PostQuitMessage (0);
+        }
+        break;
+
+		case MM_MCINOTIFY:
+            lRet = CDAudio_MessageHandler (hWnd, uMsg, wParam, lParam);
+			break;
+
+    	default:
+            /* pass all unhandled messages to DefWindowProc */
+            lRet = DefWindowProc (hWnd, uMsg, wParam, lParam);
+        break;
+    }
+
+    /* return 1 if handled message, 0 if not */
+    return lRet;
+}
+
+
+/*
+=================
+VID_NumModes
+=================
+*/
+int VID_NumModes (void)
+{
+	return nummodes;
+}
+
+	
+/*
+=================
+VID_GetModePtr
+=================
+*/
+vmode_t *VID_GetModePtr (int modenum)
+{
+
+	if ((modenum >= 0) && (modenum < nummodes))
+		return &modelist[modenum];
+	else
+		return &badmode;
+}
+
+
+/*
+=================
+VID_GetModeDescription
+=================
+*/
+char *VID_GetModeDescription (int mode)
+{
+	char		*pinfo;
+	vmode_t		*pv;
+	static char	temp[100];
+
+	if ((mode < 0) || (mode >= nummodes))
+		return NULL;
+
+	if (!leavecurrentmode)
+	{
+		pv = VID_GetModePtr (mode);
+		pinfo = pv->modedesc;
+	}
+	else
+	{
+		sprintf (temp, "Desktop resolution (%dx%d)",
+				 modelist[MODE_FULLSCREEN_DEFAULT].width,
+				 modelist[MODE_FULLSCREEN_DEFAULT].height);
+		pinfo = temp;
+	}
+
+	return pinfo;
+}
+
+
+// KJB: Added this to return the mode driver name in description for console
+
+char *VID_GetExtModeDescription (int mode)
+{
+	static char	pinfo[40];
+	vmode_t		*pv;
+
+	if ((mode < 0) || (mode >= nummodes))
+		return NULL;
+
+	pv = VID_GetModePtr (mode);
+	if (modelist[mode].type == MS_FULLDIB)
+	{
+		if (!leavecurrentmode)
+		{
+			sprintf(pinfo,"%s fullscreen", pv->modedesc);
+		}
+		else
+		{
+			sprintf (pinfo, "Desktop resolution (%dx%d)",
+					 modelist[MODE_FULLSCREEN_DEFAULT].width,
+					 modelist[MODE_FULLSCREEN_DEFAULT].height);
+		}
+	}
+	else
+	{
+		if (modestate == MS_WINDOWED)
+			sprintf(pinfo, "%s windowed", pv->modedesc);
+		else
+			sprintf(pinfo, "windowed");
+	}
+
+	return pinfo;
+}
+
+
+/*
+=================
+VID_DescribeCurrentMode_f
+=================
+*/
+void VID_DescribeCurrentMode_f (void)
+{
+	Con_Printf ("%s\n", VID_GetExtModeDescription (vid_modenum));
+}
+
+
+/*
+=================
+VID_NumModes_f
+=================
+*/
+void VID_NumModes_f (void)
+{
+
+	if (nummodes == 1)
+		Con_Printf ("%d video mode is available\n", nummodes);
+	else
+		Con_Printf ("%d video modes are available\n", nummodes);
+}
+
+
+/*
+=================
+VID_DescribeMode_f
+=================
+*/
+void VID_DescribeMode_f (void)
+{
+	int		t, modenum;
+	
+	modenum = Q_atoi (Cmd_Argv(1));
+
+	t = leavecurrentmode;
+	leavecurrentmode = 0;
+
+	Con_Printf ("%s\n", VID_GetExtModeDescription (modenum));
+
+	leavecurrentmode = t;
+}
+
+
+/*
+=================
+VID_DescribeModes_f
+=================
+*/
+void VID_DescribeModes_f (void)
+{
+	int			i, lnummodes, t;
+	char		*pinfo;
+	vmode_t		*pv;
+
+	lnummodes = VID_NumModes ();
+
+	t = leavecurrentmode;
+	leavecurrentmode = 0;
+
+	for (i=1 ; i<lnummodes ; i++)
+	{
+		pv = VID_GetModePtr (i);
+		pinfo = VID_GetExtModeDescription (i);
+		Con_Printf ("%2d: %s\n", i, pinfo);
+	}
+
+	leavecurrentmode = t;
+}
+
+
+void VID_InitDIB (HINSTANCE hInstance)
+{
+	WNDCLASS		wc;
+	HDC				hdc;
+	int				i;
+
+	/* Register the frame class */
+    wc.style         = 0;
+    wc.lpfnWndProc   = (WNDPROC)MainWndProc;
+    wc.cbClsExtra    = 0;
+    wc.cbWndExtra    = 0;
+    wc.hInstance     = hInstance;
+    wc.hIcon         = 0;
+    wc.hCursor       = LoadCursor (NULL,IDC_ARROW);
+	wc.hbrBackground = NULL;
+    wc.lpszMenuName  = 0;
+    wc.lpszClassName = "WinQuake";
+
+    if (!RegisterClass (&wc) )
+		Sys_Error ("Couldn't register window class");
+
+	modelist[0].type = MS_WINDOWED;
+
+	if (COM_CheckParm("-width"))
+		modelist[0].width = Q_atoi(com_argv[COM_CheckParm("-width")+1]);
+	else
+		modelist[0].width = 640;
+
+	if (modelist[0].width < 320)
+		modelist[0].width = 320;
+
+	if (COM_CheckParm("-height"))
+		modelist[0].height= Q_atoi(com_argv[COM_CheckParm("-height")+1]);
+	else
+		modelist[0].height = modelist[0].width * 240/320;
+
+	if (modelist[0].height < 240)
+		modelist[0].height = 240;
+
+	sprintf (modelist[0].modedesc, "%dx%d",
+			 modelist[0].width, modelist[0].height);
+
+	modelist[0].modenum = MODE_WINDOWED;
+	modelist[0].dib = 1;
+	modelist[0].fullscreen = 0;
+	modelist[0].halfscreen = 0;
+	modelist[0].bpp = 0;
+
+	nummodes = 1;
+}
+
+
+/*
+=================
+VID_InitFullDIB
+=================
+*/
+void VID_InitFullDIB (HINSTANCE hInstance)
+{
+	DEVMODE	devmode;
+	int		i, modenum, cmodes, originalnummodes, existingmode, numlowresmodes;
+	int		j, bpp, done;
+	BOOL	stat;
+
+// enumerate >8 bpp modes
+	originalnummodes = nummodes;
+	modenum = 0;
+
+	do
+	{
+		stat = EnumDisplaySettings (NULL, modenum, &devmode);
+
+		if ((devmode.dmBitsPerPel >= 15) &&
+			(devmode.dmPelsWidth <= MAXWIDTH) &&
+			(devmode.dmPelsHeight <= MAXHEIGHT) &&
+			(nummodes < MAX_MODE_LIST))
+		{
+			devmode.dmFields = DM_BITSPERPEL |
+							   DM_PELSWIDTH |
+							   DM_PELSHEIGHT;
+
+			if (ChangeDisplaySettings (&devmode, CDS_TEST | CDS_FULLSCREEN) ==
+					DISP_CHANGE_SUCCESSFUL)
+			{
+				modelist[nummodes].type = MS_FULLDIB;
+				modelist[nummodes].width = devmode.dmPelsWidth;
+				modelist[nummodes].height = devmode.dmPelsHeight;
+				modelist[nummodes].modenum = 0;
+				modelist[nummodes].halfscreen = 0;
+				modelist[nummodes].dib = 1;
+				modelist[nummodes].fullscreen = 1;
+				modelist[nummodes].bpp = devmode.dmBitsPerPel;
+				sprintf (modelist[nummodes].modedesc, "%dx%dx%d",
+						 devmode.dmPelsWidth, devmode.dmPelsHeight,
+						 devmode.dmBitsPerPel);
+
+			// if the width is more than twice the height, reduce it by half because this
+			// is probably a dual-screen monitor
+				if (!COM_CheckParm("-noadjustaspect"))
+				{
+					if (modelist[nummodes].width > (modelist[nummodes].height << 1))
+					{
+						modelist[nummodes].width >>= 1;
+						modelist[nummodes].halfscreen = 1;
+						sprintf (modelist[nummodes].modedesc, "%dx%dx%d",
+								 modelist[nummodes].width,
+								 modelist[nummodes].height,
+								 modelist[nummodes].bpp);
+					}
+				}
+
+				for (i=originalnummodes, existingmode = 0 ; i<nummodes ; i++)
+				{
+					if ((modelist[nummodes].width == modelist[i].width)   &&
+						(modelist[nummodes].height == modelist[i].height) &&
+						(modelist[nummodes].bpp == modelist[i].bpp))
+					{
+						existingmode = 1;
+						break;
+					}
+				}
+
+				if (!existingmode)
+				{
+					nummodes++;
+				}
+			}
+		}
+
+		modenum++;
+	} while (stat);
+
+// see if there are any low-res modes that aren't being reported
+	numlowresmodes = sizeof(lowresmodes) / sizeof(lowresmodes[0]);
+	bpp = 16;
+	done = 0;
+
+	do
+	{
+		for (j=0 ; (j<numlowresmodes) && (nummodes < MAX_MODE_LIST) ; j++)
+		{
+			devmode.dmBitsPerPel = bpp;
+			devmode.dmPelsWidth = lowresmodes[j].width;
+			devmode.dmPelsHeight = lowresmodes[j].height;
+			devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
+
+			if (ChangeDisplaySettings (&devmode, CDS_TEST | CDS_FULLSCREEN) ==
+					DISP_CHANGE_SUCCESSFUL)
+			{
+				modelist[nummodes].type = MS_FULLDIB;
+				modelist[nummodes].width = devmode.dmPelsWidth;
+				modelist[nummodes].height = devmode.dmPelsHeight;
+				modelist[nummodes].modenum = 0;
+				modelist[nummodes].halfscreen = 0;
+				modelist[nummodes].dib = 1;
+				modelist[nummodes].fullscreen = 1;
+				modelist[nummodes].bpp = devmode.dmBitsPerPel;
+				sprintf (modelist[nummodes].modedesc, "%dx%dx%d",
+						 devmode.dmPelsWidth, devmode.dmPelsHeight,
+						 devmode.dmBitsPerPel);
+
+				for (i=originalnummodes, existingmode = 0 ; i<nummodes ; i++)
+				{
+					if ((modelist[nummodes].width == modelist[i].width)   &&
+						(modelist[nummodes].height == modelist[i].height) &&
+						(modelist[nummodes].bpp == modelist[i].bpp))
+					{
+						existingmode = 1;
+						break;
+					}
+				}
+
+				if (!existingmode)
+				{
+					nummodes++;
+				}
+			}
+		}
+		switch (bpp)
+		{
+			case 16:
+				bpp = 32;
+				break;
+
+			case 32:
+				bpp = 24;
+				break;
+
+			case 24:
+				done = 1;
+				break;
+		}
+	} while (!done);
+
+	if (nummodes == originalnummodes)
+		Con_SafePrintf ("No fullscreen DIB modes found\n");
+}
+
+qboolean VID_Is8bit() {
+	return is8bit;
+}
+
+#define GL_SHARED_TEXTURE_PALETTE_EXT 0x81FB
+
+void VID_Init8bitPalette() 
+{
+	// Check for 8bit Extensions and initialize them.
+	int i;
+	char thePalette[256*3];
+	char *oldPalette, *newPalette;
+
+	glColorTableEXT = (void *)wglGetProcAddress("glColorTableEXT");
+    if (!glColorTableEXT || strstr(gl_extensions, "GL_EXT_shared_texture_palette") ||
+		COM_CheckParm("-no8bit"))
+		return;
+
+	Con_SafePrintf("8-bit GL extensions enabled.\n");
+    glEnable( GL_SHARED_TEXTURE_PALETTE_EXT );
+	oldPalette = (char *) d_8to24table; //d_8to24table3dfx;
+	newPalette = thePalette;
+	for (i=0;i<256;i++) {
+		*newPalette++ = *oldPalette++;
+		*newPalette++ = *oldPalette++;
+		*newPalette++ = *oldPalette++;
+		oldPalette++;
+	}
+	glColorTableEXT(GL_SHARED_TEXTURE_PALETTE_EXT, GL_RGB, 256, GL_RGB, GL_UNSIGNED_BYTE,
+		(void *) thePalette);
+	is8bit = TRUE;
+}
+
+static void Check_Gamma (unsigned char *pal)
+{
+	float	f, inf;
+	unsigned char	palette[768];
+	int		i;
+
+	if ((i = COM_CheckParm("-gamma")) == 0) {
+		if ((gl_renderer && strstr(gl_renderer, "Voodoo")) ||
+			(gl_vendor && strstr(gl_vendor, "3Dfx")))
+			vid_gamma = 1;
+		else
+			vid_gamma = 0.7; // default to 0.7 on non-3dfx hardware
+	} else
+		vid_gamma = Q_atof(com_argv[i+1]);
+
+	for (i=0 ; i<768 ; i++)
+	{
+		f = pow ( (pal[i]+1)/256.0 , vid_gamma );
+		inf = f*255 + 0.5;
+		if (inf < 0)
+			inf = 0;
+		if (inf > 255)
+			inf = 255;
+		palette[i] = inf;
+	}
+
+	memcpy (pal, palette, sizeof(palette));
+}
+
+/*
+===================
+VID_Init
+===================
+*/
+void	VID_Init (unsigned char *palette)
+{
+	int		i, existingmode;
+	int		basenummodes, width, height, bpp, findbpp, done;
+	byte	*ptmp;
+	char	gldir[MAX_OSPATH];
+	HDC		hdc;
+	DEVMODE	devmode;
+
+	memset(&devmode, 0, sizeof(devmode));
+
+	Cvar_RegisterVariable (&vid_mode);
+	Cvar_RegisterVariable (&vid_wait);
+	Cvar_RegisterVariable (&vid_nopageflip);
+	Cvar_RegisterVariable (&_vid_wait_override);
+	Cvar_RegisterVariable (&_vid_default_mode);
+	Cvar_RegisterVariable (&_vid_default_mode_win);
+	Cvar_RegisterVariable (&vid_config_x);
+	Cvar_RegisterVariable (&vid_config_y);
+	Cvar_RegisterVariable (&vid_stretch_by_2);
+	Cvar_RegisterVariable (&_windowed_mouse);
+	Cvar_RegisterVariable (&gl_ztrick);
+
+	Cmd_AddCommand ("vid_nummodes", VID_NumModes_f);
+	Cmd_AddCommand ("vid_describecurrentmode", VID_DescribeCurrentMode_f);
+	Cmd_AddCommand ("vid_describemode", VID_DescribeMode_f);
+	Cmd_AddCommand ("vid_describemodes", VID_DescribeModes_f);
+
+	hIcon = LoadIcon (global_hInstance, MAKEINTRESOURCE (IDI_ICON2));
+
+	InitCommonControls();
+
+	VID_InitDIB (global_hInstance);
+	basenummodes = nummodes = 1;
+
+	VID_InitFullDIB (global_hInstance);
+
+	if (COM_CheckParm("-window"))
+	{
+		hdc = GetDC (NULL);
+
+		if (GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE)
+		{
+			Sys_Error ("Can't run in non-RGB mode");
+		}
+
+		ReleaseDC (NULL, hdc);
+
+		windowed = true;
+
+		vid_default = MODE_WINDOWED;
+	}
+	else
+	{
+		if (nummodes == 1)
+			Sys_Error ("No RGB fullscreen modes available");
+
+		windowed = false;
+
+		if (COM_CheckParm("-mode"))
+		{
+			vid_default = Q_atoi(com_argv[COM_CheckParm("-mode")+1]);
+		}
+		else
+		{
+			if (COM_CheckParm("-current"))
+			{
+				modelist[MODE_FULLSCREEN_DEFAULT].width =
+						GetSystemMetrics (SM_CXSCREEN);
+				modelist[MODE_FULLSCREEN_DEFAULT].height =
+						GetSystemMetrics (SM_CYSCREEN);
+				vid_default = MODE_FULLSCREEN_DEFAULT;
+				leavecurrentmode = 1;
+			}
+			else
+			{
+				if (COM_CheckParm("-width"))
+				{
+					width = Q_atoi(com_argv[COM_CheckParm("-width")+1]);
+				}
+				else
+				{
+					width = 640;
+				}
+
+				if (COM_CheckParm("-bpp"))
+				{
+					bpp = Q_atoi(com_argv[COM_CheckParm("-bpp")+1]);
+					findbpp = 0;
+				}
+				else
+				{
+					bpp = 15;
+					findbpp = 1;
+				}
+
+				if (COM_CheckParm("-height"))
+					height = Q_atoi(com_argv[COM_CheckParm("-height")+1]);
+
+			// if they want to force it, add the specified mode to the list
+				if (COM_CheckParm("-force") && (nummodes < MAX_MODE_LIST))
+				{
+					modelist[nummodes].type = MS_FULLDIB;
+					modelist[nummodes].width = width;
+					modelist[nummodes].height = height;
+					modelist[nummodes].modenum = 0;
+					modelist[nummodes].halfscreen = 0;
+					modelist[nummodes].dib = 1;
+					modelist[nummodes].fullscreen = 1;
+					modelist[nummodes].bpp = bpp;
+					sprintf (modelist[nummodes].modedesc, "%dx%dx%d",
+							 devmode.dmPelsWidth, devmode.dmPelsHeight,
+							 devmode.dmBitsPerPel);
+
+					for (i=nummodes, existingmode = 0 ; i<nummodes ; i++)
+					{
+						if ((modelist[nummodes].width == modelist[i].width)   &&
+							(modelist[nummodes].height == modelist[i].height) &&
+							(modelist[nummodes].bpp == modelist[i].bpp))
+						{
+							existingmode = 1;
+							break;
+						}
+					}
+
+					if (!existingmode)
+					{
+						nummodes++;
+					}
+				}
+
+				done = 0;
+
+				do
+				{
+					if (COM_CheckParm("-height"))
+					{
+						height = Q_atoi(com_argv[COM_CheckParm("-height")+1]);
+
+						for (i=1, vid_default=0 ; i<nummodes ; i++)
+						{
+							if ((modelist[i].width == width) &&
+								(modelist[i].height == height) &&
+								(modelist[i].bpp == bpp))
+							{
+								vid_default = i;
+								done = 1;
+								break;
+							}
+						}
+					}
+					else
+					{
+						for (i=1, vid_default=0 ; i<nummodes ; i++)
+						{
+							if ((modelist[i].width == width) && (modelist[i].bpp == bpp))
+							{
+								vid_default = i;
+								done = 1;
+								break;
+							}
+						}
+					}
+
+					if (!done)
+					{
+						if (findbpp)
+						{
+							switch (bpp)
+							{
+							case 15:
+								bpp = 16;
+								break;
+							case 16:
+								bpp = 32;
+								break;
+							case 32:
+								bpp = 24;
+								break;
+							case 24:
+								done = 1;
+								break;
+							}
+						}
+						else
+						{
+							done = 1;
+						}
+					}
+				} while (!done);
+
+				if (!vid_default)
+				{
+					Sys_Error ("Specified video mode not available");
+				}
+			}
+		}
+	}
+
+	vid_initialized = true;
+
+	if ((i = COM_CheckParm("-conwidth")) != 0)
+		vid.conwidth = Q_atoi(com_argv[i+1]);
+	else
+		vid.conwidth = 640;
+
+	vid.conwidth &= 0xfff8; // make it a multiple of eight
+
+	if (vid.conwidth < 320)
+		vid.conwidth = 320;
+
+	// pick a conheight that matches with correct aspect
+	vid.conheight = vid.conwidth*3 / 4;
+
+	if ((i = COM_CheckParm("-conheight")) != 0)
+		vid.conheight = Q_atoi(com_argv[i+1]);
+	if (vid.conheight < 200)
+		vid.conheight = 200;
+
+	vid.maxwarpwidth = WARP_WIDTH;
+	vid.maxwarpheight = WARP_HEIGHT;
+	vid.colormap = host_colormap;
+	vid.fullbright = 256 - LittleLong (*((int *)vid.colormap + 2048));
+
+	DestroyWindow (hwnd_dialog);
+
+	Check_Gamma(palette);
+	VID_SetPalette (palette);
+
+	VID_SetMode (vid_default, palette);
+
+    maindc = GetDC(mainwindow);
+	bSetupPixelFormat(maindc);
+
+    baseRC = wglCreateContext( maindc );
+	if (!baseRC)
+		Sys_Error ("Could not initialize GL (wglCreateContext failed).\n\nMake sure you in are 65535 color mode, and try running -window.");
+    if (!wglMakeCurrent( maindc, baseRC ))
+		Sys_Error ("wglMakeCurrent failed");
+
+	GL_Init ();
+
+	sprintf (gldir, "%s/glquake", com_gamedir);
+	Sys_mkdir (gldir);
+
+	vid_realmode = vid_modenum;
+
+	// Check for 3DFX Extensions and initialize them.
+	VID_Init8bitPalette();
+
+	vid_menudrawfn = VID_MenuDraw;
+	vid_menukeyfn = VID_MenuKey;
+
+	strcpy (badmode.modedesc, "Bad mode");
+	vid_canalttab = true;
+
+	if (COM_CheckParm("-fullsbar"))
+		fullsbardraw = true;
+}
+
+
+//========================================================
+// Video menu stuff
+//========================================================
+
+extern void M_Menu_Options_f (void);
+extern void M_Print (int cx, int cy, char *str);
+extern void M_PrintWhite (int cx, int cy, char *str);
+extern void M_DrawCharacter (int cx, int line, int num);
+extern void M_DrawTransPic (int x, int y, qpic_t *pic);
+extern void M_DrawPic (int x, int y, qpic_t *pic);
+
+static int	vid_line, vid_wmodes;
+
+typedef struct
+{
+	int		modenum;
+	char	*desc;
+	int		iscur;
+} modedesc_t;
+
+#define MAX_COLUMN_SIZE		9
+#define MODE_AREA_HEIGHT	(MAX_COLUMN_SIZE + 2)
+#define MAX_MODEDESCS		(MAX_COLUMN_SIZE*3)
+
+static modedesc_t	modedescs[MAX_MODEDESCS];
+
+/*
+================
+VID_MenuDraw
+================
+*/
+void VID_MenuDraw (void)
+{
+	qpic_t		*p;
+	char		*ptr;
+	int			lnummodes, i, j, k, column, row, dup, dupmode;
+	char		temp[100];
+	vmode_t		*pv;
+
+	p = Draw_CachePic ("gfx/vidmodes.lmp");
+	M_DrawPic ( (320-p->width)/2, 4, p);
+
+	vid_wmodes = 0;
+	lnummodes = VID_NumModes ();
+	
+	for (i=1 ; (i<lnummodes) && (vid_wmodes < MAX_MODEDESCS) ; i++)
+	{
+		ptr = VID_GetModeDescription (i);
+		pv = VID_GetModePtr (i);
+
+		k = vid_wmodes;
+
+		modedescs[k].modenum = i;
+		modedescs[k].desc = ptr;
+		modedescs[k].iscur = 0;
+
+		if (i == vid_modenum)
+			modedescs[k].iscur = 1;
+
+		vid_wmodes++;
+
+	}
+
+	if (vid_wmodes > 0)
+	{
+		M_Print (2*8, 36+0*8, "Fullscreen Modes (WIDTHxHEIGHTxBPP)");
+
+		column = 8;
+		row = 36+2*8;
+
+		for (i=0 ; i<vid_wmodes ; i++)
+		{
+			if (modedescs[i].iscur)
+				M_PrintWhite (column, row, modedescs[i].desc);
+			else
+				M_Print (column, row, modedescs[i].desc);
+
+			column += 13*8;
+
+			if ((i % VID_ROW_SIZE) == (VID_ROW_SIZE - 1))
+			{
+				column = 8;
+				row += 8;
+			}
+		}
+	}
+
+	M_Print (3*8, 36 + MODE_AREA_HEIGHT * 8 + 8*2,
+			 "Video modes must be set from the");
+	M_Print (3*8, 36 + MODE_AREA_HEIGHT * 8 + 8*3,
+			 "command line with -width <width>");
+	M_Print (3*8, 36 + MODE_AREA_HEIGHT * 8 + 8*4,
+			 "and -bpp <bits-per-pixel>");
+	M_Print (3*8, 36 + MODE_AREA_HEIGHT * 8 + 8*6,
+			 "Select windowed mode with -window");
+}
+
+
+/*
+================
+VID_MenuKey
+================
+*/
+void VID_MenuKey (int key)
+{
+	switch (key)
+	{
+	case K_ESCAPE:
+		S_LocalSound ("misc/menu1.wav");
+		M_Menu_Options_f ();
+		break;
+
+	default:
+		break;
+	}
+}
--- /dev/null
+++ b/QW/client/gl_warp.c
@@ -1,0 +1,1087 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// gl_warp.c -- sky and water polygons
+
+#include "quakedef.h"
+
+extern	model_t	*loadmodel;
+
+int		skytexturenum;
+
+int		solidskytexture;
+int		alphaskytexture;
+float	speedscale;		// for top sky and bottom sky
+
+msurface_t	*warpface;
+
+extern cvar_t gl_subdivide_size;
+
+void BoundPoly (int numverts, float *verts, vec3_t mins, vec3_t maxs)
+{
+	int		i, j;
+	float	*v;
+
+	mins[0] = mins[1] = mins[2] = 9999;
+	maxs[0] = maxs[1] = maxs[2] = -9999;
+	v = verts;
+	for (i=0 ; i<numverts ; i++)
+		for (j=0 ; j<3 ; j++, v++)
+		{
+			if (*v < mins[j])
+				mins[j] = *v;
+			if (*v > maxs[j])
+				maxs[j] = *v;
+		}
+}
+
+void SubdividePolygon (int numverts, float *verts)
+{
+	int		i, j, k;
+	vec3_t	mins, maxs;
+	float	m;
+	float	*v;
+	vec3_t	front[64], back[64];
+	int		f, b;
+	float	dist[64];
+	float	frac;
+	glpoly_t	*poly;
+	float	s, t;
+
+	if (numverts > 60)
+		Sys_Error ("numverts = %i", numverts);
+
+	BoundPoly (numverts, verts, mins, maxs);
+
+	for (i=0 ; i<3 ; i++)
+	{
+		m = (mins[i] + maxs[i]) * 0.5;
+		m = gl_subdivide_size.value * floor (m/gl_subdivide_size.value + 0.5);
+		if (maxs[i] - m < 8)
+			continue;
+		if (m - mins[i] < 8)
+			continue;
+
+		// cut it
+		v = verts + i;
+		for (j=0 ; j<numverts ; j++, v+= 3)
+			dist[j] = *v - m;
+
+		// wrap cases
+		dist[j] = dist[0];
+		v-=i;
+		VectorCopy (verts, v);
+
+		f = b = 0;
+		v = verts;
+		for (j=0 ; j<numverts ; j++, v+= 3)
+		{
+			if (dist[j] >= 0)
+			{
+				VectorCopy (v, front[f]);
+				f++;
+			}
+			if (dist[j] <= 0)
+			{
+				VectorCopy (v, back[b]);
+				b++;
+			}
+			if (dist[j] == 0 || dist[j+1] == 0)
+				continue;
+			if ( (dist[j] > 0) != (dist[j+1] > 0) )
+			{
+				// clip point
+				frac = dist[j] / (dist[j] - dist[j+1]);
+				for (k=0 ; k<3 ; k++)
+					front[f][k] = back[b][k] = v[k] + frac*(v[3+k] - v[k]);
+				f++;
+				b++;
+			}
+		}
+
+		SubdividePolygon (f, front[0]);
+		SubdividePolygon (b, back[0]);
+		return;
+	}
+
+	poly = Hunk_Alloc (sizeof(glpoly_t) + (numverts-4) * VERTEXSIZE*sizeof(float));
+	poly->next = warpface->polys;
+	warpface->polys = poly;
+	poly->numverts = numverts;
+	for (i=0 ; i<numverts ; i++, verts+= 3)
+	{
+		VectorCopy (verts, poly->verts[i]);
+		s = DotProduct (verts, warpface->texinfo->vecs[0]);
+		t = DotProduct (verts, warpface->texinfo->vecs[1]);
+		poly->verts[i][3] = s;
+		poly->verts[i][4] = t;
+	}
+}
+
+/*
+================
+GL_SubdivideSurface
+
+Breaks a polygon up along axial 64 unit
+boundaries so that turbulent and sky warps
+can be done reasonably.
+================
+*/
+void GL_SubdivideSurface (msurface_t *fa)
+{
+	vec3_t		verts[64];
+	int			numverts;
+	int			i;
+	int			lindex;
+	float		*vec;
+
+	warpface = fa;
+
+	//
+	// convert edges back to a normal polygon
+	//
+	numverts = 0;
+	for (i=0 ; i<fa->numedges ; i++)
+	{
+		lindex = loadmodel->surfedges[fa->firstedge + i];
+
+		if (lindex > 0)
+			vec = loadmodel->vertexes[loadmodel->edges[lindex].v[0]].position;
+		else
+			vec = loadmodel->vertexes[loadmodel->edges[-lindex].v[1]].position;
+		VectorCopy (vec, verts[numverts]);
+		numverts++;
+	}
+
+	SubdividePolygon (numverts, verts[0]);
+}
+
+//=========================================================
+
+
+
+// speed up sin calculations - Ed
+float	turbsin[] =
+{
+	#include "gl_warp_sin.h"
+};
+#define TURBSCALE (256.0 / (2 * M_PI))
+
+/*
+=============
+EmitWaterPolys
+
+Does a water warp on the pre-fragmented glpoly_t chain
+=============
+*/
+void EmitWaterPolys (msurface_t *fa)
+{
+	glpoly_t	*p;
+	float		*v;
+	int			i;
+	float		s, t, os, ot;
+
+
+	for (p=fa->polys ; p ; p=p->next)
+	{
+		glBegin (GL_POLYGON);
+		for (i=0,v=p->verts[0] ; i<p->numverts ; i++, v+=VERTEXSIZE)
+		{
+			os = v[3];
+			ot = v[4];
+
+			s = os + turbsin[(int)((ot*0.125+realtime) * TURBSCALE) & 255];
+			s *= (1.0/64);
+
+			t = ot + turbsin[(int)((os*0.125+realtime) * TURBSCALE) & 255];
+			t *= (1.0/64);
+
+			glTexCoord2f (s, t);
+			glVertex3fv (v);
+		}
+		glEnd ();
+	}
+}
+
+
+
+
+/*
+=============
+EmitSkyPolys
+=============
+*/
+void EmitSkyPolys (msurface_t *fa)
+{
+	glpoly_t	*p;
+	float		*v;
+	int			i;
+	float	s, t;
+	vec3_t	dir;
+	float	length;
+
+	for (p=fa->polys ; p ; p=p->next)
+	{
+		glBegin (GL_POLYGON);
+		for (i=0,v=p->verts[0] ; i<p->numverts ; i++, v+=VERTEXSIZE)
+		{
+			VectorSubtract (v, r_origin, dir);
+			dir[2] *= 3;	// flatten the sphere
+
+			length = dir[0]*dir[0] + dir[1]*dir[1] + dir[2]*dir[2];
+			length = sqrt (length);
+			length = 6*63/length;
+
+			dir[0] *= length;
+			dir[1] *= length;
+
+			s = (speedscale + dir[0]) * (1.0/128);
+			t = (speedscale + dir[1]) * (1.0/128);
+
+			glTexCoord2f (s, t);
+			glVertex3fv (v);
+		}
+		glEnd ();
+	}
+}
+
+/*
+===============
+EmitBothSkyLayers
+
+Does a sky warp on the pre-fragmented glpoly_t chain
+This will be called for brushmodels, the world
+will have them chained together.
+===============
+*/
+void EmitBothSkyLayers (msurface_t *fa)
+{
+	GL_DisableMultitexture();
+
+	GL_Bind (solidskytexture);
+	speedscale = realtime*8;
+	speedscale -= (int)speedscale & ~127 ;
+
+	EmitSkyPolys (fa);
+
+	glEnable (GL_BLEND);
+	GL_Bind (alphaskytexture);
+	speedscale = realtime*16;
+	speedscale -= (int)speedscale & ~127 ;
+
+	EmitSkyPolys (fa);
+
+	glDisable (GL_BLEND);
+}
+
+#ifndef QUAKE2
+/*
+=================
+R_DrawSkyChain
+=================
+*/
+void R_DrawSkyChain (msurface_t *s)
+{
+	msurface_t	*fa;
+
+	GL_DisableMultitexture();
+
+	// used when gl_texsort is on
+	GL_Bind(solidskytexture);
+	speedscale = realtime*8;
+	speedscale -= (int)speedscale & ~127 ;
+
+	for (fa=s ; fa ; fa=fa->texturechain)
+		EmitSkyPolys (fa);
+
+	glEnable (GL_BLEND);
+	GL_Bind (alphaskytexture);
+	speedscale = realtime*16;
+	speedscale -= (int)speedscale & ~127 ;
+
+	for (fa=s ; fa ; fa=fa->texturechain)
+		EmitSkyPolys (fa);
+
+	glDisable (GL_BLEND);
+}
+
+#endif
+
+/*
+=================================================================
+
+  Quake 2 environment sky
+
+=================================================================
+*/
+
+#ifdef QUAKE2
+
+
+#define	SKY_TEX		2000
+
+/*
+=================================================================
+
+  PCX Loading
+
+=================================================================
+*/
+
+typedef struct
+{
+    char	manufacturer;
+    char	version;
+    char	encoding;
+    char	bits_per_pixel;
+    unsigned short	xmin,ymin,xmax,ymax;
+    unsigned short	hres,vres;
+    unsigned char	palette[48];
+    char	reserved;
+    char	color_planes;
+    unsigned short	bytes_per_line;
+    unsigned short	palette_type;
+    char	filler[58];
+    unsigned 	data;			// unbounded
+} pcx_t;
+
+byte	*pcx_rgb;
+
+/*
+============
+LoadPCX
+============
+*/
+void LoadPCX (FILE *f)
+{
+	pcx_t	*pcx, pcxbuf;
+	byte	palette[768];
+	byte	*pix;
+	int		x, y;
+	int		dataByte, runLength;
+	int		count;
+
+//
+// parse the PCX file
+//
+	fread (&pcxbuf, 1, sizeof(pcxbuf), f);
+
+	pcx = &pcxbuf;
+
+	if (pcx->manufacturer != 0x0a
+		|| pcx->version != 5
+		|| pcx->encoding != 1
+		|| pcx->bits_per_pixel != 8
+		|| pcx->xmax >= 320
+		|| pcx->ymax >= 256)
+	{
+		Con_Printf ("Bad pcx file\n");
+		return;
+	}
+
+	// seek to palette
+	fseek (f, -768, SEEK_END);
+	fread (palette, 1, 768, f);
+
+	fseek (f, sizeof(pcxbuf) - 4, SEEK_SET);
+
+	count = (pcx->xmax+1) * (pcx->ymax+1);
+	pcx_rgb = malloc( count * 4);
+
+	for (y=0 ; y<=pcx->ymax ; y++)
+	{
+		pix = pcx_rgb + 4*y*(pcx->xmax+1);
+		for (x=0 ; x<=pcx->ymax ; )
+		{
+			dataByte = fgetc(f);
+
+			if((dataByte & 0xC0) == 0xC0)
+			{
+				runLength = dataByte & 0x3F;
+				dataByte = fgetc(f);
+			}
+			else
+				runLength = 1;
+
+			while(runLength-- > 0)
+			{
+				pix[0] = palette[dataByte*3];
+				pix[1] = palette[dataByte*3+1];
+				pix[2] = palette[dataByte*3+2];
+				pix[3] = 255;
+				pix += 4;
+				x++;
+			}
+		}
+	}
+}
+
+/*
+=========================================================
+
+TARGA LOADING
+
+=========================================================
+*/
+
+typedef struct _TargaHeader {
+	unsigned char 	id_length, colormap_type, image_type;
+	unsigned short	colormap_index, colormap_length;
+	unsigned char	colormap_size;
+	unsigned short	x_origin, y_origin, width, height;
+	unsigned char	pixel_size, attributes;
+} TargaHeader;
+
+
+TargaHeader		targa_header;
+byte			*targa_rgba;
+
+int fgetLittleShort (FILE *f)
+{
+	byte	b1, b2;
+
+	b1 = fgetc(f);
+	b2 = fgetc(f);
+
+	return (short)(b1 + b2*256);
+}
+
+int fgetLittleLong (FILE *f)
+{
+	byte	b1, b2, b3, b4;
+
+	b1 = fgetc(f);
+	b2 = fgetc(f);
+	b3 = fgetc(f);
+	b4 = fgetc(f);
+
+	return b1 + (b2<<8) + (b3<<16) + (b4<<24);
+}
+
+
+/*
+=============
+LoadTGA
+=============
+*/
+void LoadTGA (FILE *fin)
+{
+	int				columns, rows, numPixels;
+	byte			*pixbuf;
+	int				row, column;
+
+	targa_header.id_length = fgetc(fin);
+	targa_header.colormap_type = fgetc(fin);
+	targa_header.image_type = fgetc(fin);
+	
+	targa_header.colormap_index = fgetLittleShort(fin);
+	targa_header.colormap_length = fgetLittleShort(fin);
+	targa_header.colormap_size = fgetc(fin);
+	targa_header.x_origin = fgetLittleShort(fin);
+	targa_header.y_origin = fgetLittleShort(fin);
+	targa_header.width = fgetLittleShort(fin);
+	targa_header.height = fgetLittleShort(fin);
+	targa_header.pixel_size = fgetc(fin);
+	targa_header.attributes = fgetc(fin);
+
+	if (targa_header.image_type!=2 
+		&& targa_header.image_type!=10) 
+		Sys_Error ("LoadTGA: Only type 2 and 10 targa RGB images supported\n");
+
+	if (targa_header.colormap_type !=0 
+		|| (targa_header.pixel_size!=32 && targa_header.pixel_size!=24))
+		Sys_Error ("Texture_LoadTGA: Only 32 or 24 bit images supported (no colormaps)\n");
+
+	columns = targa_header.width;
+	rows = targa_header.height;
+	numPixels = columns * rows;
+
+	targa_rgba = malloc (numPixels*4);
+	
+	if (targa_header.id_length != 0)
+		fseek(fin, targa_header.id_length, SEEK_CUR);  // skip TARGA image comment
+	
+	if (targa_header.image_type==2) {  // Uncompressed, RGB images
+		for(row=rows-1; row>=0; row--) {
+			pixbuf = targa_rgba + row*columns*4;
+			for(column=0; column<columns; column++) {
+				unsigned char red,green,blue,alphabyte;
+				switch (targa_header.pixel_size) {
+					case 24:
+							
+							blue = getc(fin);
+							green = getc(fin);
+							red = getc(fin);
+							*pixbuf++ = red;
+							*pixbuf++ = green;
+							*pixbuf++ = blue;
+							*pixbuf++ = 255;
+							break;
+					case 32:
+							blue = getc(fin);
+							green = getc(fin);
+							red = getc(fin);
+							alphabyte = getc(fin);
+							*pixbuf++ = red;
+							*pixbuf++ = green;
+							*pixbuf++ = blue;
+							*pixbuf++ = alphabyte;
+							break;
+				}
+			}
+		}
+	}
+	else if (targa_header.image_type==10) {   // Runlength encoded RGB images
+		unsigned char red,green,blue,alphabyte,packetHeader,packetSize,j;
+		for(row=rows-1; row>=0; row--) {
+			pixbuf = targa_rgba + row*columns*4;
+			for(column=0; column<columns; ) {
+				packetHeader=getc(fin);
+				packetSize = 1 + (packetHeader & 0x7f);
+				if (packetHeader & 0x80) {        // run-length packet
+					switch (targa_header.pixel_size) {
+						case 24:
+								blue = getc(fin);
+								green = getc(fin);
+								red = getc(fin);
+								alphabyte = 255;
+								break;
+						case 32:
+								blue = getc(fin);
+								green = getc(fin);
+								red = getc(fin);
+								alphabyte = getc(fin);
+								break;
+					}
+	
+					for(j=0;j<packetSize;j++) {
+						*pixbuf++=red;
+						*pixbuf++=green;
+						*pixbuf++=blue;
+						*pixbuf++=alphabyte;
+						column++;
+						if (column==columns) { // run spans across rows
+							column=0;
+							if (row>0)
+								row--;
+							else
+								goto breakOut;
+							pixbuf = targa_rgba + row*columns*4;
+						}
+					}
+				}
+				else {                            // non run-length packet
+					for(j=0;j<packetSize;j++) {
+						switch (targa_header.pixel_size) {
+							case 24:
+									blue = getc(fin);
+									green = getc(fin);
+									red = getc(fin);
+									*pixbuf++ = red;
+									*pixbuf++ = green;
+									*pixbuf++ = blue;
+									*pixbuf++ = 255;
+									break;
+							case 32:
+									blue = getc(fin);
+									green = getc(fin);
+									red = getc(fin);
+									alphabyte = getc(fin);
+									*pixbuf++ = red;
+									*pixbuf++ = green;
+									*pixbuf++ = blue;
+									*pixbuf++ = alphabyte;
+									break;
+						}
+						column++;
+						if (column==columns) { // pixel packet run spans across rows
+							column=0;
+							if (row>0)
+								row--;
+							else
+								goto breakOut;
+							pixbuf = targa_rgba + row*columns*4;
+						}						
+					}
+				}
+			}
+			breakOut:;
+		}
+	}
+	
+	fclose(fin);
+}
+
+/*
+==================
+R_LoadSkys
+==================
+*/
+char	*suf[6] = {"rt", "bk", "lf", "ft", "up", "dn"};
+void R_LoadSkys (void)
+{
+	int		i;
+	FILE	*f;
+	char	name[64];
+
+	for (i=0 ; i<6 ; i++)
+	{
+		GL_Bind (SKY_TEX + i);
+		sprintf (name, "gfx/env/bkgtst%s.tga", suf[i]);
+		COM_FOpenFile (name, &f);
+		if (!f)
+		{
+			Con_Printf ("Couldn't load %s\n", name);
+			continue;
+		}
+		LoadTGA (f);
+//		LoadPCX (f);
+
+		glTexImage2D (GL_TEXTURE_2D, 0, gl_solid_format, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, targa_rgba);
+//		glTexImage2D (GL_TEXTURE_2D, 0, gl_solid_format, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, pcx_rgb);
+
+		free (targa_rgba);
+//		free (pcx_rgb);
+
+		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+	}
+}
+
+
+vec3_t	skyclip[6] = {
+	{1,1,0},
+	{1,-1,0},
+	{0,-1,1},
+	{0,1,1},
+	{1,0,1},
+	{-1,0,1} 
+};
+int	c_sky;
+
+// 1 = s, 2 = t, 3 = 2048
+int	st_to_vec[6][3] =
+{
+	{3,-1,2},
+	{-3,1,2},
+
+	{1,3,2},
+	{-1,-3,2},
+
+	{-2,-1,3},		// 0 degrees yaw, look straight up
+	{2,-1,-3}		// look straight down
+
+//	{-1,2,3},
+//	{1,2,-3}
+};
+
+// s = [0]/[2], t = [1]/[2]
+int	vec_to_st[6][3] =
+{
+	{-2,3,1},
+	{2,3,-1},
+
+	{1,3,2},
+	{-1,3,-2},
+
+	{-2,-1,3},
+	{-2,1,-3}
+
+//	{-1,2,3},
+//	{1,2,-3}
+};
+
+float	skymins[2][6], skymaxs[2][6];
+
+void DrawSkyPolygon (int nump, vec3_t vecs)
+{
+	int		i,j;
+	vec3_t	v, av;
+	float	s, t, dv;
+	int		axis;
+	float	*vp;
+
+	c_sky++;
+#if 0
+glBegin (GL_POLYGON);
+for (i=0 ; i<nump ; i++, vecs+=3)
+{
+	VectorAdd(vecs, r_origin, v);
+	glVertex3fv (v);
+}
+glEnd();
+return;
+#endif
+	// decide which face it maps to
+	VectorCopy (vec3_origin, v);
+	for (i=0, vp=vecs ; i<nump ; i++, vp+=3)
+	{
+		VectorAdd (vp, v, v);
+	}
+	av[0] = fabs(v[0]);
+	av[1] = fabs(v[1]);
+	av[2] = fabs(v[2]);
+	if (av[0] > av[1] && av[0] > av[2])
+	{
+		if (v[0] < 0)
+			axis = 1;
+		else
+			axis = 0;
+	}
+	else if (av[1] > av[2] && av[1] > av[0])
+	{
+		if (v[1] < 0)
+			axis = 3;
+		else
+			axis = 2;
+	}
+	else
+	{
+		if (v[2] < 0)
+			axis = 5;
+		else
+			axis = 4;
+	}
+
+	// project new texture coords
+	for (i=0 ; i<nump ; i++, vecs+=3)
+	{
+		j = vec_to_st[axis][2];
+		if (j > 0)
+			dv = vecs[j - 1];
+		else
+			dv = -vecs[-j - 1];
+
+		j = vec_to_st[axis][0];
+		if (j < 0)
+			s = -vecs[-j -1] / dv;
+		else
+			s = vecs[j-1] / dv;
+		j = vec_to_st[axis][1];
+		if (j < 0)
+			t = -vecs[-j -1] / dv;
+		else
+			t = vecs[j-1] / dv;
+
+		if (s < skymins[0][axis])
+			skymins[0][axis] = s;
+		if (t < skymins[1][axis])
+			skymins[1][axis] = t;
+		if (s > skymaxs[0][axis])
+			skymaxs[0][axis] = s;
+		if (t > skymaxs[1][axis])
+			skymaxs[1][axis] = t;
+	}
+}
+
+#define	MAX_CLIP_VERTS	64
+void ClipSkyPolygon (int nump, vec3_t vecs, int stage)
+{
+	float	*norm;
+	float	*v;
+	qboolean	front, back;
+	float	d, e;
+	float	dists[MAX_CLIP_VERTS];
+	int		sides[MAX_CLIP_VERTS];
+	vec3_t	newv[2][MAX_CLIP_VERTS];
+	int		newc[2];
+	int		i, j;
+
+	if (nump > MAX_CLIP_VERTS-2)
+		Sys_Error ("ClipSkyPolygon: MAX_CLIP_VERTS");
+	if (stage == 6)
+	{	// fully clipped, so draw it
+		DrawSkyPolygon (nump, vecs);
+		return;
+	}
+
+	front = back = false;
+	norm = skyclip[stage];
+	for (i=0, v = vecs ; i<nump ; i++, v+=3)
+	{
+		d = DotProduct (v, norm);
+		if (d > ON_EPSILON)
+		{
+			front = true;
+			sides[i] = SIDE_FRONT;
+		}
+		else if (d < ON_EPSILON)
+		{
+			back = true;
+			sides[i] = SIDE_BACK;
+		}
+		else
+			sides[i] = SIDE_ON;
+		dists[i] = d;
+	}
+
+	if (!front || !back)
+	{	// not clipped
+		ClipSkyPolygon (nump, vecs, stage+1);
+		return;
+	}
+
+	// clip it
+	sides[i] = sides[0];
+	dists[i] = dists[0];
+	VectorCopy (vecs, (vecs+(i*3)) );
+	newc[0] = newc[1] = 0;
+
+	for (i=0, v = vecs ; i<nump ; i++, v+=3)
+	{
+		switch (sides[i])
+		{
+		case SIDE_FRONT:
+			VectorCopy (v, newv[0][newc[0]]);
+			newc[0]++;
+			break;
+		case SIDE_BACK:
+			VectorCopy (v, newv[1][newc[1]]);
+			newc[1]++;
+			break;
+		case SIDE_ON:
+			VectorCopy (v, newv[0][newc[0]]);
+			newc[0]++;
+			VectorCopy (v, newv[1][newc[1]]);
+			newc[1]++;
+			break;
+		}
+
+		if (sides[i] == SIDE_ON || sides[i+1] == SIDE_ON || sides[i+1] == sides[i])
+			continue;
+
+		d = dists[i] / (dists[i] - dists[i+1]);
+		for (j=0 ; j<3 ; j++)
+		{
+			e = v[j] + d*(v[j+3] - v[j]);
+			newv[0][newc[0]][j] = e;
+			newv[1][newc[1]][j] = e;
+		}
+		newc[0]++;
+		newc[1]++;
+	}
+
+	// continue
+	ClipSkyPolygon (newc[0], newv[0][0], stage+1);
+	ClipSkyPolygon (newc[1], newv[1][0], stage+1);
+}
+
+/*
+=================
+R_DrawSkyChain
+=================
+*/
+void R_DrawSkyChain (msurface_t *s)
+{
+	msurface_t	*fa;
+
+	int		i;
+	vec3_t	verts[MAX_CLIP_VERTS];
+	glpoly_t	*p;
+
+	c_sky = 0;
+	GL_Bind(solidskytexture);
+
+	// calculate vertex values for sky box
+
+	for (fa=s ; fa ; fa=fa->texturechain)
+	{
+		for (p=fa->polys ; p ; p=p->next)
+		{
+			for (i=0 ; i<p->numverts ; i++)
+			{
+				VectorSubtract (p->verts[i], r_origin, verts[i]);
+			}
+			ClipSkyPolygon (p->numverts, verts[0], 0);
+		}
+	}
+}
+
+
+/*
+==============
+R_ClearSkyBox
+==============
+*/
+void R_ClearSkyBox (void)
+{
+	int		i;
+
+	for (i=0 ; i<6 ; i++)
+	{
+		skymins[0][i] = skymins[1][i] = 9999;
+		skymaxs[0][i] = skymaxs[1][i] = -9999;
+	}
+}
+
+
+void MakeSkyVec (float s, float t, int axis)
+{
+	vec3_t		v, b;
+	int			j, k;
+
+	b[0] = s*2048;
+	b[1] = t*2048;
+	b[2] = 2048;
+
+	for (j=0 ; j<3 ; j++)
+	{
+		k = st_to_vec[axis][j];
+		if (k < 0)
+			v[j] = -b[-k - 1];
+		else
+			v[j] = b[k - 1];
+		v[j] += r_origin[j];
+	}
+
+	// avoid bilerp seam
+	s = (s+1)*0.5;
+	t = (t+1)*0.5;
+
+	if (s < 1.0/512)
+		s = 1.0/512;
+	else if (s > 511.0/512)
+		s = 511.0/512;
+	if (t < 1.0/512)
+		t = 1.0/512;
+	else if (t > 511.0/512)
+		t = 511.0/512;
+
+	t = 1.0 - t;
+	glTexCoord2f (s, t);
+	glVertex3fv (v);
+}
+
+/*
+==============
+R_DrawSkyBox
+==============
+*/
+int	skytexorder[6] = {0,2,1,3,4,5};
+void R_DrawSkyBox (void)
+{
+	int		i, j, k;
+	vec3_t	v;
+	float	s, t;
+
+#if 0
+glEnable (GL_BLEND);
+glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+glColor4f (1,1,1,0.5);
+glDisable (GL_DEPTH_TEST);
+#endif
+	for (i=0 ; i<6 ; i++)
+	{
+		if (skymins[0][i] >= skymaxs[0][i]
+		|| skymins[1][i] >= skymaxs[1][i])
+			continue;
+
+		GL_Bind (SKY_TEX+skytexorder[i]);
+#if 0
+skymins[0][i] = -1;
+skymins[1][i] = -1;
+skymaxs[0][i] = 1;
+skymaxs[1][i] = 1;
+#endif
+		glBegin (GL_QUADS);
+		MakeSkyVec (skymins[0][i], skymins[1][i], i);
+		MakeSkyVec (skymins[0][i], skymaxs[1][i], i);
+		MakeSkyVec (skymaxs[0][i], skymaxs[1][i], i);
+		MakeSkyVec (skymaxs[0][i], skymins[1][i], i);
+		glEnd ();
+	}
+#if 0
+glDisable (GL_BLEND);
+glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+glColor4f (1,1,1,0.5);
+glEnable (GL_DEPTH_TEST);
+#endif
+}
+
+
+#endif
+
+//===============================================================
+
+/*
+=============
+R_InitSky
+
+A sky texture is 256*128, with the right side being a masked overlay
+==============
+*/
+void R_InitSky (texture_t *mt)
+{
+	int			i, j, p;
+	byte		*src;
+	unsigned	trans[128*128];
+	unsigned	transpix;
+	int			r, g, b;
+	unsigned	*rgba;
+	extern	int			skytexturenum;
+
+	src = (byte *)mt + mt->offsets[0];
+
+	// make an average value for the back to avoid
+	// a fringe on the top level
+
+	r = g = b = 0;
+	for (i=0 ; i<128 ; i++)
+		for (j=0 ; j<128 ; j++)
+		{
+			p = src[i*256 + j + 128];
+			rgba = &d_8to24table[p];
+			trans[(i*128) + j] = *rgba;
+			r += ((byte *)rgba)[0];
+			g += ((byte *)rgba)[1];
+			b += ((byte *)rgba)[2];
+		}
+
+	((byte *)&transpix)[0] = r/(128*128);
+	((byte *)&transpix)[1] = g/(128*128);
+	((byte *)&transpix)[2] = b/(128*128);
+	((byte *)&transpix)[3] = 0;
+
+
+	if (!solidskytexture)
+		solidskytexture = texture_extension_number++;
+	GL_Bind (solidskytexture );
+	glTexImage2D (GL_TEXTURE_2D, 0, gl_solid_format, 128, 128, 0, GL_RGBA, GL_UNSIGNED_BYTE, trans);
+	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+
+	for (i=0 ; i<128 ; i++)
+		for (j=0 ; j<128 ; j++)
+		{
+			p = src[i*256 + j];
+			if (p == 0)
+				trans[(i*128) + j] = transpix;
+			else
+				trans[(i*128) + j] = d_8to24table[p];
+		}
+
+	if (!alphaskytexture)
+		alphaskytexture = texture_extension_number++;
+	GL_Bind(alphaskytexture);
+	glTexImage2D (GL_TEXTURE_2D, 0, gl_alpha_format, 128, 128, 0, GL_RGBA, GL_UNSIGNED_BYTE, trans);
+	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+}
+
--- /dev/null
+++ b/QW/client/gl_warp_sin.h
@@ -1,0 +1,51 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+ 0, 0.19633, 0.392541, 0.588517, 0.784137, 0.979285, 1.17384, 1.3677,
+ 1.56072, 1.75281, 1.94384, 2.1337, 2.32228, 2.50945, 2.69512, 2.87916,
+ 3.06147, 3.24193, 3.42044, 3.59689, 3.77117, 3.94319, 4.11282, 4.27998,
+ 4.44456, 4.60647, 4.76559, 4.92185, 5.07515, 5.22538, 5.37247, 5.51632,
+ 5.65685, 5.79398, 5.92761, 6.05767, 6.18408, 6.30677, 6.42566, 6.54068,
+ 6.65176, 6.75883, 6.86183, 6.9607, 7.05537, 7.14579, 7.23191, 7.31368,
+ 7.39104, 7.46394, 7.53235, 7.59623, 7.65552, 7.71021, 7.76025, 7.80562,
+ 7.84628, 7.88222, 7.91341, 7.93984, 7.96148, 7.97832, 7.99036, 7.99759,
+ 8, 7.99759, 7.99036, 7.97832, 7.96148, 7.93984, 7.91341, 7.88222,
+ 7.84628, 7.80562, 7.76025, 7.71021, 7.65552, 7.59623, 7.53235, 7.46394,
+ 7.39104, 7.31368, 7.23191, 7.14579, 7.05537, 6.9607, 6.86183, 6.75883,
+ 6.65176, 6.54068, 6.42566, 6.30677, 6.18408, 6.05767, 5.92761, 5.79398,
+ 5.65685, 5.51632, 5.37247, 5.22538, 5.07515, 4.92185, 4.76559, 4.60647,
+ 4.44456, 4.27998, 4.11282, 3.94319, 3.77117, 3.59689, 3.42044, 3.24193,
+ 3.06147, 2.87916, 2.69512, 2.50945, 2.32228, 2.1337, 1.94384, 1.75281,
+ 1.56072, 1.3677, 1.17384, 0.979285, 0.784137, 0.588517, 0.392541, 0.19633,
+ 9.79717e-16, -0.19633, -0.392541, -0.588517, -0.784137, -0.979285, -1.17384, -1.3677,
+ -1.56072, -1.75281, -1.94384, -2.1337, -2.32228, -2.50945, -2.69512, -2.87916,
+ -3.06147, -3.24193, -3.42044, -3.59689, -3.77117, -3.94319, -4.11282, -4.27998,
+ -4.44456, -4.60647, -4.76559, -4.92185, -5.07515, -5.22538, -5.37247, -5.51632,
+ -5.65685, -5.79398, -5.92761, -6.05767, -6.18408, -6.30677, -6.42566, -6.54068,
+ -6.65176, -6.75883, -6.86183, -6.9607, -7.05537, -7.14579, -7.23191, -7.31368,
+ -7.39104, -7.46394, -7.53235, -7.59623, -7.65552, -7.71021, -7.76025, -7.80562,
+ -7.84628, -7.88222, -7.91341, -7.93984, -7.96148, -7.97832, -7.99036, -7.99759,
+ -8, -7.99759, -7.99036, -7.97832, -7.96148, -7.93984, -7.91341, -7.88222,
+ -7.84628, -7.80562, -7.76025, -7.71021, -7.65552, -7.59623, -7.53235, -7.46394,
+ -7.39104, -7.31368, -7.23191, -7.14579, -7.05537, -6.9607, -6.86183, -6.75883,
+ -6.65176, -6.54068, -6.42566, -6.30677, -6.18408, -6.05767, -5.92761, -5.79398,
+ -5.65685, -5.51632, -5.37247, -5.22538, -5.07515, -4.92185, -4.76559, -4.60647,
+ -4.44456, -4.27998, -4.11282, -3.94319, -3.77117, -3.59689, -3.42044, -3.24193,
+ -3.06147, -2.87916, -2.69512, -2.50945, -2.32228, -2.1337, -1.94384, -1.75281,
+ -1.56072, -1.3677, -1.17384, -0.979285, -0.784137, -0.588517, -0.392541, -0.19633,
--- /dev/null
+++ b/QW/client/glquake.h
@@ -1,0 +1,302 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// disable data conversion warnings
+
+#pragma warning(disable : 4244)     // MIPS
+#pragma warning(disable : 4136)     // X86
+#pragma warning(disable : 4051)     // ALPHA
+  
+#ifdef _WIN32
+#include <windows.h>
+#endif
+
+#include <GL/gl.h>
+#include <GL/glu.h>
+
+void GL_BeginRendering (int *x, int *y, int *width, int *height);
+void GL_EndRendering (void);
+
+
+// Function prototypes for the Texture Object Extension routines
+typedef GLboolean (APIENTRY *ARETEXRESFUNCPTR)(GLsizei, const GLuint *,
+                    const GLboolean *);
+typedef void (APIENTRY *BINDTEXFUNCPTR)(GLenum, GLuint);
+typedef void (APIENTRY *DELTEXFUNCPTR)(GLsizei, const GLuint *);
+typedef void (APIENTRY *GENTEXFUNCPTR)(GLsizei, GLuint *);
+typedef GLboolean (APIENTRY *ISTEXFUNCPTR)(GLuint);
+typedef void (APIENTRY *PRIORTEXFUNCPTR)(GLsizei, const GLuint *,
+                    const GLclampf *);
+typedef void (APIENTRY *TEXSUBIMAGEPTR)(int, int, int, int, int, int, int, int, void *);
+
+extern	BINDTEXFUNCPTR bindTexFunc;
+extern	DELTEXFUNCPTR delTexFunc;
+extern	TEXSUBIMAGEPTR TexSubImage2DFunc;
+
+extern	int texture_extension_number;
+extern	int		texture_mode;
+
+extern	float	gldepthmin, gldepthmax;
+
+void GL_Upload32 (unsigned *data, int width, int height,  qboolean mipmap, qboolean alpha);
+void GL_Upload8 (byte *data, int width, int height,  qboolean mipmap, qboolean alpha);
+void GL_Upload8_EXT (byte *data, int width, int height,  qboolean mipmap, qboolean alpha);
+int GL_LoadTexture (char *identifier, int width, int height, byte *data, qboolean mipmap, qboolean alpha);
+int GL_FindTexture (char *identifier);
+
+typedef struct
+{
+	float	x, y, z;
+	float	s, t;
+	float	r, g, b;
+} glvert_t;
+
+extern glvert_t glv;
+
+extern	int glx, gly, glwidth, glheight;
+
+#ifdef _WIN32
+extern	PROC glArrayElementEXT;
+extern	PROC glColorPointerEXT;
+extern	PROC glTexturePointerEXT;
+extern	PROC glVertexPointerEXT;
+#endif
+
+// r_local.h -- private refresh defs
+
+#define ALIAS_BASE_SIZE_RATIO		(1.0 / 11.0)
+					// normalizing factor so player model works out to about
+					//  1 pixel per triangle
+#define	MAX_LBM_HEIGHT		480
+
+#define TILE_SIZE		128		// size of textures generated by R_GenTiledSurf
+
+#define SKYSHIFT		7
+#define	SKYSIZE			(1 << SKYSHIFT)
+#define SKYMASK			(SKYSIZE - 1)
+
+#define BACKFACE_EPSILON	0.01
+
+
+void R_TimeRefresh_f (void);
+void R_ReadPointFile_f (void);
+texture_t *R_TextureAnimation (texture_t *base);
+
+typedef struct surfcache_s
+{
+	struct surfcache_s	*next;
+	struct surfcache_s 	**owner;		// NULL is an empty chunk of memory
+	int					lightadj[MAXLIGHTMAPS]; // checked for strobe flush
+	int					dlight;
+	int					size;		// including header
+	unsigned			width;
+	unsigned			height;		// DEBUG only needed for debug
+	float				mipscale;
+	struct texture_s	*texture;	// checked for animating textures
+	byte				data[4];	// width*height elements
+} surfcache_t;
+
+
+typedef struct
+{
+	pixel_t		*surfdat;	// destination for generated surface
+	int			rowbytes;	// destination logical width in bytes
+	msurface_t	*surf;		// description for surface to generate
+	fixed8_t	lightadj[MAXLIGHTMAPS];
+							// adjust for lightmap levels for dynamic lighting
+	texture_t	*texture;	// corrected for animating textures
+	int			surfmip;	// mipmapped ratio of surface texels / world pixels
+	int			surfwidth;	// in mipmapped texels
+	int			surfheight;	// in mipmapped texels
+} drawsurf_t;
+
+
+typedef enum {
+	pt_static, pt_grav, pt_slowgrav, pt_fire, pt_explode, pt_explode2, pt_blob, pt_blob2
+} ptype_t;
+
+// !!! if this is changed, it must be changed in d_ifacea.h too !!!
+typedef struct particle_s
+{
+// driver-usable fields
+	vec3_t		org;
+	float		color;
+// drivers never touch the following fields
+	struct particle_s	*next;
+	vec3_t		vel;
+	float		ramp;
+	float		die;
+	ptype_t		type;
+} particle_t;
+
+
+//====================================================
+
+
+extern	entity_t	r_worldentity;
+extern	qboolean	r_cache_thrash;		// compatability
+extern	vec3_t		modelorg, r_entorigin;
+extern	entity_t	*currententity;
+extern	int			r_visframecount;	// ??? what difs?
+extern	int			r_framecount;
+extern	mplane_t	frustum[4];
+extern	int		c_brush_polys, c_alias_polys;
+
+
+//
+// view origin
+//
+extern	vec3_t	vup;
+extern	vec3_t	vpn;
+extern	vec3_t	vright;
+extern	vec3_t	r_origin;
+
+//
+// screen size info
+//
+extern	refdef_t	r_refdef;
+extern	mleaf_t		*r_viewleaf, *r_oldviewleaf;
+extern	texture_t	*r_notexture_mip;
+extern	int		d_lightstylevalue[256];	// 8.8 fraction of base light value
+
+extern	qboolean	envmap;
+extern	int	currenttexture;
+extern	int	cnttextures[2];
+extern	int	particletexture;
+extern	int	netgraphtexture;	// netgraph texture
+extern	int	playertextures;
+
+extern	int	skytexturenum;		// index in cl.loadmodel, not gl texture object
+
+extern	cvar_t	r_norefresh;
+extern	cvar_t	r_drawentities;
+extern	cvar_t	r_drawworld;
+extern	cvar_t	r_drawviewmodel;
+extern	cvar_t	r_speeds;
+extern	cvar_t	r_waterwarp;
+extern	cvar_t	r_fullbright;
+extern	cvar_t	r_lightmap;
+extern	cvar_t	r_shadows;
+extern	cvar_t	r_mirroralpha;
+extern	cvar_t	r_wateralpha;
+extern	cvar_t	r_dynamic;
+extern	cvar_t	r_novis;
+extern	cvar_t	r_netgraph;
+
+extern	cvar_t	gl_clear;
+extern	cvar_t	gl_cull;
+extern	cvar_t	gl_poly;
+extern	cvar_t	gl_texsort;
+extern	cvar_t	gl_smoothmodels;
+extern	cvar_t	gl_affinemodels;
+extern	cvar_t	gl_polyblend;
+extern	cvar_t	gl_keeptjunctions;
+extern	cvar_t	gl_reporttjunctions;
+extern	cvar_t	gl_flashblend;
+extern	cvar_t	gl_nocolors;
+extern	cvar_t	gl_finish;
+
+extern	int		gl_lightmap_format;
+extern	int		gl_solid_format;
+extern	int		gl_alpha_format;
+
+extern	cvar_t	gl_max_size;
+extern	cvar_t	gl_playermip;
+
+extern	int			mirrortexturenum;	// quake texturenum, not gltexturenum
+extern	qboolean	mirror;
+extern	mplane_t	*mirror_plane;
+
+extern	float	r_world_matrix[16];
+
+extern	const char *gl_vendor;
+extern	const char *gl_renderer;
+extern	const char *gl_version;
+extern	const char *gl_extensions;
+
+void R_TranslatePlayerSkin (int playernum);
+void GL_Bind (int texnum);
+
+// Multitexture
+#define    TEXTURE0_SGIS				0x835E
+#define    TEXTURE1_SGIS				0x835F
+
+#ifdef _WIN32
+typedef void (APIENTRY *lpMTexFUNC) (GLenum, GLfloat, GLfloat);
+typedef void (APIENTRY *lpSelTexFUNC) (GLenum);
+extern lpMTexFUNC qglMTexCoord2fSGIS;
+extern lpSelTexFUNC qglSelectTextureSGIS;
+#endif
+
+extern qboolean gl_mtexable;
+
+void GL_DisableMultitexture(void);
+void GL_EnableMultitexture(void);
+
+//
+// gl_warp.c
+//
+void GL_SubdivideSurface (msurface_t *fa);
+void EmitBothSkyLayers (msurface_t *fa);
+void EmitWaterPolys (msurface_t *fa);
+void EmitSkyPolys (msurface_t *fa);
+void R_DrawSkyChain (msurface_t *s);
+
+//
+// gl_draw.c
+//
+int GL_LoadPicTexture (qpic_t *pic);
+void GL_Set2D (void);
+
+//
+// gl_rmain.c
+//
+qboolean R_CullBox (vec3_t mins, vec3_t maxs);
+void R_RotateForEntity (entity_t *e);
+
+//
+// gl_rlight.c
+//
+void R_MarkLights (dlight_t *light, int bit, mnode_t *node);
+void R_AnimateLight (void);
+void R_RenderDlights (void);
+int R_LightPoint (vec3_t p);
+
+//
+// gl_refrag.c
+//
+void R_StoreEfrags (efrag_t **ppefrag);
+
+//
+// gl_mesh.c
+//
+void GL_MakeAliasModelDisplayLists (model_t *m, aliashdr_t *hdr);
+
+//
+// gl_rsurf.c
+//
+void R_DrawBrushModel (entity_t *e);
+void R_DrawWorld (void);
+void GL_BuildLightmaps (void);
+
+//
+// gl_ngraph.c
+//
+void R_NetGraph (void);
+
--- /dev/null
+++ b/QW/client/glquake2.h
@@ -1,0 +1,190 @@
+// disable data conversion warnings
+
+#pragma warning(disable : 4244)     // MIPS
+#pragma warning(disable : 4136)     // X86
+#pragma warning(disable : 4051)     // ALPHA
+  
+#include <windows.h>
+
+#include <gl\gl.h>
+#include <gl\glu.h>
+
+void GL_BeginRendering (int *x, int *y, int *width, int *height);
+void GL_EndRendering (void);
+
+
+// Function prototypes for the Texture Object Extension routines
+typedef GLboolean (APIENTRY *ARETEXRESFUNCPTR)(GLsizei, const GLuint *,
+                    const GLboolean *);
+typedef void (APIENTRY *BINDTEXFUNCPTR)(GLenum, GLuint);
+typedef void (APIENTRY *DELTEXFUNCPTR)(GLsizei, const GLuint *);
+typedef void (APIENTRY *GENTEXFUNCPTR)(GLsizei, GLuint *);
+typedef GLboolean (APIENTRY *ISTEXFUNCPTR)(GLuint);
+typedef void (APIENTRY *PRIORTEXFUNCPTR)(GLsizei, const GLuint *,
+                    const GLclampf *);
+typedef void (APIENTRY *TEXSUBIMAGEPTR)(int, int, int, int, int, int, int, int, void *);
+
+extern	BINDTEXFUNCPTR bindTexFunc;
+extern	DELTEXFUNCPTR delTexFunc;
+extern	TEXSUBIMAGEPTR TexSubImage2DFunc;
+
+extern	int texture_extension_number;
+extern	int		texture_mode;
+
+extern	float	gldepthmin, gldepthmax;
+
+void GL_Upload32 (unsigned *data, int width, int height,  qboolean mipmap, qboolean alpha, qboolean modulate);
+void GL_Upload8 (byte *data, int width, int height,  qboolean mipmap, qboolean alpha, qboolean modulate);
+int GL_LoadTexture (char *identifier, int width, int height, byte *data, int mipmap, int alpha, int modulate);
+int GL_FindTexture (char *identifier);
+
+typedef struct
+{
+	float	x, y, z;
+	float	s, t;
+	float	r, g, b;
+} glvert_t;
+
+extern glvert_t glv;
+
+extern	int glx, gly, glwidth, glheight;
+
+extern	PROC glArrayElementEXT;
+extern	PROC glColorPointerEXT;
+extern	PROC glTexturePointerEXT;
+extern	PROC glVertexPointerEXT;
+
+
+// r_local.h -- private refresh defs
+
+#define MAXALIASVERTS		2000	// TODO: tune this
+
+#define ALIAS_BASE_SIZE_RATIO		(1.0 / 11.0)
+					// normalizing factor so player model works out to about
+					//  1 pixel per triangle
+#define	MAX_LBM_HEIGHT		480
+
+#define TILE_SIZE		128		// size of textures generated by R_GenTiledSurf
+
+#define SKYSHIFT		7
+#define	SKYSIZE			(1 << SKYSHIFT)
+#define SKYMASK			(SKYSIZE - 1)
+
+#define BACKFACE_EPSILON	0.01
+
+
+void R_TimeRefresh_f (void);
+void R_ReadPointFile_f (void);
+texture_t *R_TextureAnimation (texture_t *base);
+
+typedef struct surfcache_s
+{
+	struct surfcache_s	*next;
+	struct surfcache_s 	**owner;		// NULL is an empty chunk of memory
+	int					lightadj[MAXLIGHTMAPS]; // checked for strobe flush
+	int					dlight;
+	int					size;		// including header
+	unsigned			width;
+	unsigned			height;		// DEBUG only needed for debug
+	float				mipscale;
+	struct texture_s	*texture;	// checked for animating textures
+	byte				data[4];	// width*height elements
+} surfcache_t;
+
+
+typedef struct
+{
+	pixel_t		*surfdat;	// destination for generated surface
+	int			rowbytes;	// destination logical width in bytes
+	msurface_t	*surf;		// description for surface to generate
+	fixed8_t	lightadj[MAXLIGHTMAPS];
+							// adjust for lightmap levels for dynamic lighting
+	texture_t	*texture;	// corrected for animating textures
+	int			surfmip;	// mipmapped ratio of surface texels / world pixels
+	int			surfwidth;	// in mipmapped texels
+	int			surfheight;	// in mipmapped texels
+} drawsurf_t;
+
+
+typedef enum {
+	pt_static, pt_grav, pt_slowgrav, pt_fire, pt_explode, pt_explode2, pt_blob, pt_blob2
+} ptype_t;
+
+// !!! if this is changed, it must be changed in d_ifacea.h too !!!
+typedef struct particle_s
+{
+// driver-usable fields
+	vec3_t		org;
+	float		color;
+// drivers never touch the following fields
+	struct particle_s	*next;
+	vec3_t		vel;
+	float		ramp;
+	float		die;
+	ptype_t		type;
+} particle_t;
+
+
+//====================================================
+
+
+extern	entity_t	r_worldentity;
+extern	qboolean	r_cache_thrash;		// compatability
+extern	vec3_t		modelorg, r_entorigin;
+extern	entity_t	*currententity;
+extern	int			r_visframecount;	// ??? what difs?
+extern	int			r_framecount;
+extern	mplane_t	frustum[4];
+extern	int		c_brush_polys, c_alias_polys;
+
+
+//
+// view origin
+//
+extern	vec3_t	vup;
+extern	vec3_t	vpn;
+extern	vec3_t	vright;
+extern	vec3_t	r_origin;
+
+//
+// screen size info
+//
+extern	refdef_t	r_refdef;
+extern	mleaf_t		*r_viewleaf, *r_oldviewleaf;
+extern	texture_t	*r_notexture_mip;
+extern	int		d_lightstylevalue[256];	// 8.8 fraction of base light value
+
+extern	qboolean	envmap;
+extern	int	currenttexture;
+extern	int	particletexture;
+extern	int	playertextures;
+
+extern	int	skytexturenum;		// index in cl.loadmodel, not gl texture object
+
+extern	cvar_t	r_drawentities;
+extern	cvar_t	r_drawworld;
+extern	cvar_t	r_drawviewmodel;
+extern	cvar_t	r_speeds;
+extern	cvar_t	r_waterwarp;
+extern	cvar_t	r_fullbright;
+extern	cvar_t	r_lightmap;
+extern	cvar_t	r_shadows;
+extern	cvar_t	r_dynamic;
+
+extern	cvar_t	gl_clear;
+extern	cvar_t	gl_cull;
+extern	cvar_t	gl_poly;
+extern	cvar_t	gl_texsort;
+extern	cvar_t	gl_smoothmodels;
+extern	cvar_t	gl_affinemodels;
+extern	cvar_t	gl_fogblend;
+extern	cvar_t	gl_polyblend;
+extern	cvar_t	gl_keeptjunctions;
+extern	cvar_t	gl_reporttjunctions;
+
+extern	int		gl_lightmap_format;
+extern	int		gl_solid_format;
+extern	int		gl_alpha_format;
+
+void R_TranslatePlayerSkin (int playernum);
+void GL_Bind (int texnum);
--- /dev/null
+++ b/QW/client/in_null.c
@@ -1,0 +1,29 @@
+// in_null.c -- for systems without a mouse
+
+#include "quakedef.h"
+
+void IN_Init (void)
+{
+}
+
+void IN_Shutdown (void)
+{
+}
+
+void IN_Commands (void)
+{
+}
+
+void IN_Move (usercmd_t *cmd)
+{
+}
+
+/*
+===========
+IN_ModeChanged
+===========
+*/
+void IN_ModeChanged (void)
+{
+}
+
--- /dev/null
+++ b/QW/client/in_win.c
@@ -1,0 +1,1232 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// in_win.c -- windows 95 mouse and joystick code
+// 02/21/97 JCB Added extended DirectInput code to support external controllers.
+
+#include <dinput.h>
+#include "quakedef.h"
+#include "winquake.h"
+//#include "dosisms.h"
+
+#define DINPUT_BUFFERSIZE           16
+#define iDirectInputCreate(a,b,c,d)	pDirectInputCreate(a,b,c,d)
+
+HRESULT (WINAPI *pDirectInputCreate)(HINSTANCE hinst, DWORD dwVersion,
+	LPDIRECTINPUT * lplpDirectInput, LPUNKNOWN punkOuter);
+
+// mouse variables
+cvar_t	m_filter = {"m_filter","0"};
+
+int			mouse_buttons;
+int			mouse_oldbuttonstate;
+POINT		current_pos;
+int			mouse_x, mouse_y, old_mouse_x, old_mouse_y, mx_accum, my_accum;
+
+static qboolean	restore_spi;
+static int		originalmouseparms[3], newmouseparms[3] = {0, 0, 1};
+qboolean		mouseinitialized;
+static qboolean	mouseparmsvalid, mouseactivatetoggle;
+static qboolean	mouseshowtoggle = 1;
+static qboolean	dinput_acquired;
+static unsigned int		mstate_di;
+unsigned int uiWheelMessage;
+
+qboolean	mouseactive;
+
+// joystick defines and variables
+// where should defines be moved?
+#define JOY_ABSOLUTE_AXIS	0x00000000		// control like a joystick
+#define JOY_RELATIVE_AXIS	0x00000010		// control like a mouse, spinner, trackball
+#define	JOY_MAX_AXES		6				// X, Y, Z, R, U, V
+#define JOY_AXIS_X			0
+#define JOY_AXIS_Y			1
+#define JOY_AXIS_Z			2
+#define JOY_AXIS_R			3
+#define JOY_AXIS_U			4
+#define JOY_AXIS_V			5
+
+enum _ControlList
+{
+	AxisNada = 0, AxisForward, AxisLook, AxisSide, AxisTurn
+};
+
+DWORD	dwAxisFlags[JOY_MAX_AXES] =
+{
+	JOY_RETURNX, JOY_RETURNY, JOY_RETURNZ, JOY_RETURNR, JOY_RETURNU, JOY_RETURNV
+};
+
+DWORD	dwAxisMap[JOY_MAX_AXES];
+DWORD	dwControlMap[JOY_MAX_AXES];
+PDWORD	pdwRawValue[JOY_MAX_AXES];
+
+// none of these cvars are saved over a session
+// this means that advanced controller configuration needs to be executed
+// each time.  this avoids any problems with getting back to a default usage
+// or when changing from one controller to another.  this way at least something
+// works.
+cvar_t	in_joystick = {"joystick","0", true};
+cvar_t	joy_name = {"joyname", "joystick"};
+cvar_t	joy_advanced = {"joyadvanced", "0"};
+cvar_t	joy_advaxisx = {"joyadvaxisx", "0"};
+cvar_t	joy_advaxisy = {"joyadvaxisy", "0"};
+cvar_t	joy_advaxisz = {"joyadvaxisz", "0"};
+cvar_t	joy_advaxisr = {"joyadvaxisr", "0"};
+cvar_t	joy_advaxisu = {"joyadvaxisu", "0"};
+cvar_t	joy_advaxisv = {"joyadvaxisv", "0"};
+cvar_t	joy_forwardthreshold = {"joyforwardthreshold", "0.15"};
+cvar_t	joy_sidethreshold = {"joysidethreshold", "0.15"};
+cvar_t	joy_pitchthreshold = {"joypitchthreshold", "0.15"};
+cvar_t	joy_yawthreshold = {"joyyawthreshold", "0.15"};
+cvar_t	joy_forwardsensitivity = {"joyforwardsensitivity", "-1.0"};
+cvar_t	joy_sidesensitivity = {"joysidesensitivity", "-1.0"};
+cvar_t	joy_pitchsensitivity = {"joypitchsensitivity", "1.0"};
+cvar_t	joy_yawsensitivity = {"joyyawsensitivity", "-1.0"};
+cvar_t	joy_wwhack1 = {"joywwhack1", "0.0"};
+cvar_t	joy_wwhack2 = {"joywwhack2", "0.0"};
+
+qboolean	joy_avail, joy_advancedinit, joy_haspov;
+DWORD		joy_oldbuttonstate, joy_oldpovstate;
+
+int			joy_id;
+DWORD		joy_flags;
+DWORD		joy_numbuttons;
+
+static LPDIRECTINPUT		g_pdi;
+static LPDIRECTINPUTDEVICE	g_pMouse;
+
+static JOYINFOEX	ji;
+
+static HINSTANCE hInstDI;
+
+static qboolean	dinput;
+
+typedef struct MYDATA {
+	LONG  lX;                   // X axis goes here
+	LONG  lY;                   // Y axis goes here
+	LONG  lZ;                   // Z axis goes here
+	BYTE  bButtonA;             // One button goes here
+	BYTE  bButtonB;             // Another button goes here
+	BYTE  bButtonC;             // Another button goes here
+	BYTE  bButtonD;             // Another button goes here
+} MYDATA;
+
+static DIOBJECTDATAFORMAT rgodf[] = {
+  { &GUID_XAxis,    FIELD_OFFSET(MYDATA, lX),       DIDFT_AXIS | DIDFT_ANYINSTANCE,   0,},
+  { &GUID_YAxis,    FIELD_OFFSET(MYDATA, lY),       DIDFT_AXIS | DIDFT_ANYINSTANCE,   0,},
+  { &GUID_ZAxis,    FIELD_OFFSET(MYDATA, lZ),       0x80000000 | DIDFT_AXIS | DIDFT_ANYINSTANCE,   0,},
+  { 0,              FIELD_OFFSET(MYDATA, bButtonA), DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0,},
+  { 0,              FIELD_OFFSET(MYDATA, bButtonB), DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0,},
+  { 0,              FIELD_OFFSET(MYDATA, bButtonC), 0x80000000 | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0,},
+  { 0,              FIELD_OFFSET(MYDATA, bButtonD), 0x80000000 | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0,},
+};
+
+#define NUM_OBJECTS (sizeof(rgodf) / sizeof(rgodf[0]))
+
+static DIDATAFORMAT	df = {
+	sizeof(DIDATAFORMAT),       // this structure
+	sizeof(DIOBJECTDATAFORMAT), // size of object data format
+	DIDF_RELAXIS,               // absolute axis coordinates
+	sizeof(MYDATA),             // device data size
+	NUM_OBJECTS,                // number of objects
+	rgodf,                      // and here they are
+};
+
+// forward-referenced functions
+void IN_StartupJoystick (void);
+void Joy_AdvancedUpdate_f (void);
+void IN_JoyMove (usercmd_t *cmd);
+
+
+/*
+===========
+Force_CenterView_f
+===========
+*/
+void Force_CenterView_f (void)
+{
+	cl.viewangles[PITCH] = 0;
+}
+
+
+/*
+===========
+IN_UpdateClipCursor
+===========
+*/
+void IN_UpdateClipCursor (void)
+{
+
+	if (mouseinitialized && mouseactive && !dinput)
+	{
+		ClipCursor (&window_rect);
+	}
+}
+
+
+/*
+===========
+IN_ShowMouse
+===========
+*/
+void IN_ShowMouse (void)
+{
+
+	if (!mouseshowtoggle)
+	{
+		ShowCursor (TRUE);
+		mouseshowtoggle = 1;
+	}
+}
+
+
+/*
+===========
+IN_HideMouse
+===========
+*/
+void IN_HideMouse (void)
+{
+
+	if (mouseshowtoggle)
+	{
+		ShowCursor (FALSE);
+		mouseshowtoggle = 0;
+	}
+}
+
+
+/*
+===========
+IN_ActivateMouse
+===========
+*/
+void IN_ActivateMouse (void)
+{
+
+	mouseactivatetoggle = true;
+
+	if (mouseinitialized)
+	{
+		if (dinput)
+		{
+			if (g_pMouse)
+			{
+				if (!dinput_acquired)
+				{
+					IDirectInputDevice_Acquire(g_pMouse);
+					dinput_acquired = true;
+				}
+			}
+			else
+			{
+				return;
+			}
+		}
+		else
+		{
+			if (mouseparmsvalid)
+				restore_spi = SystemParametersInfo (SPI_SETMOUSE, 0, newmouseparms, 0);
+
+			SetCursorPos (window_center_x, window_center_y);
+			SetCapture (mainwindow);
+			ClipCursor (&window_rect);
+		}
+
+		mouseactive = true;
+	}
+}
+
+
+/*
+===========
+IN_SetQuakeMouseState
+===========
+*/
+void IN_SetQuakeMouseState (void)
+{
+	if (mouseactivatetoggle)
+		IN_ActivateMouse ();
+}
+
+
+/*
+===========
+IN_DeactivateMouse
+===========
+*/
+void IN_DeactivateMouse (void)
+{
+
+	mouseactivatetoggle = false;
+
+	if (mouseinitialized)
+	{
+		if (dinput)
+		{
+			if (g_pMouse)
+			{
+				if (dinput_acquired)
+				{
+					IDirectInputDevice_Unacquire(g_pMouse);
+					dinput_acquired = false;
+				}
+			}
+		}
+		else
+		{
+		if (restore_spi)
+			SystemParametersInfo (SPI_SETMOUSE, 0, originalmouseparms, 0);
+
+		ClipCursor (NULL);
+		ReleaseCapture ();
+	}
+
+		mouseactive = false;
+	}
+}
+
+
+/*
+===========
+IN_RestoreOriginalMouseState
+===========
+*/
+void IN_RestoreOriginalMouseState (void)
+{
+	if (mouseactivatetoggle)
+	{
+		IN_DeactivateMouse ();
+		mouseactivatetoggle = true;
+	}
+
+// try to redraw the cursor so it gets reinitialized, because sometimes it
+// has garbage after the mode switch
+	ShowCursor (TRUE);
+	ShowCursor (FALSE);
+}
+
+
+/*
+===========
+IN_InitDInput
+===========
+*/
+qboolean IN_InitDInput (void)
+{
+    HRESULT		hr;
+	DIPROPDWORD	dipdw = {
+		{
+			sizeof(DIPROPDWORD),        // diph.dwSize
+			sizeof(DIPROPHEADER),       // diph.dwHeaderSize
+			0,                          // diph.dwObj
+			DIPH_DEVICE,                // diph.dwHow
+		},
+		DINPUT_BUFFERSIZE,              // dwData
+	};
+
+	if (!hInstDI)
+	{
+		hInstDI = LoadLibrary("dinput.dll");
+		
+		if (hInstDI == NULL)
+		{
+			Con_SafePrintf ("Couldn't load dinput.dll\n");
+			return false;
+		}
+	}
+
+	if (!pDirectInputCreate)
+	{
+		pDirectInputCreate = (void *)GetProcAddress(hInstDI,"DirectInputCreateA");
+
+		if (!pDirectInputCreate)
+		{
+			Con_SafePrintf ("Couldn't get DI proc addr\n");
+			return false;
+		}
+	}
+
+// register with DirectInput and get an IDirectInput to play with.
+	hr = iDirectInputCreate(global_hInstance, DIRECTINPUT_VERSION, &g_pdi, NULL);
+
+	if (FAILED(hr))
+	{
+		return false;
+	}
+
+// obtain an interface to the system mouse device.
+	hr = IDirectInput_CreateDevice(g_pdi, &GUID_SysMouse, &g_pMouse, NULL);
+
+	if (FAILED(hr))
+	{
+		Con_SafePrintf ("Couldn't open DI mouse device\n");
+		return false;
+	}
+
+// set the data format to "mouse format".
+	hr = IDirectInputDevice_SetDataFormat(g_pMouse, &df);
+
+	if (FAILED(hr))
+	{
+		Con_SafePrintf ("Couldn't set DI mouse format\n");
+		return false;
+	}
+
+// set the cooperativity level.
+	hr = IDirectInputDevice_SetCooperativeLevel(g_pMouse, mainwindow,
+			DISCL_EXCLUSIVE | DISCL_FOREGROUND);
+
+	if (FAILED(hr))
+	{
+		Con_SafePrintf ("Couldn't set DI coop level\n");
+		return false;
+	}
+
+
+// set the buffer size to DINPUT_BUFFERSIZE elements.
+// the buffer size is a DWORD property associated with the device
+	hr = IDirectInputDevice_SetProperty(g_pMouse, DIPROP_BUFFERSIZE, &dipdw.diph);
+
+	if (FAILED(hr))
+	{
+		Con_SafePrintf ("Couldn't set DI buffersize\n");
+		return false;
+	}
+
+	return true;
+}
+
+
+/*
+===========
+IN_StartupMouse
+===========
+*/
+void IN_StartupMouse (void)
+{
+	HDC			hdc;
+
+	if ( COM_CheckParm ("-nomouse") ) 
+		return; 
+
+	mouseinitialized = true;
+
+	if (COM_CheckParm ("-dinput"))
+	{
+		dinput = IN_InitDInput ();
+
+		if (dinput)
+		{
+			Con_SafePrintf ("DirectInput initialized\n");
+		}
+		else
+		{
+			Con_SafePrintf ("DirectInput not initialized\n");
+		}
+	}
+
+	if (!dinput)
+	{
+		mouseparmsvalid = SystemParametersInfo (SPI_GETMOUSE, 0, originalmouseparms, 0);
+
+		if (mouseparmsvalid)
+		{
+			if ( COM_CheckParm ("-noforcemspd") ) 
+				newmouseparms[2] = originalmouseparms[2];
+
+			if ( COM_CheckParm ("-noforcemaccel") ) 
+			{
+				newmouseparms[0] = originalmouseparms[0];
+				newmouseparms[1] = originalmouseparms[1];
+			}
+
+			if ( COM_CheckParm ("-noforcemparms") ) 
+			{
+				newmouseparms[0] = originalmouseparms[0];
+				newmouseparms[1] = originalmouseparms[1];
+				newmouseparms[2] = originalmouseparms[2];
+			}
+		}
+	}
+
+	mouse_buttons = 3;
+
+// if a fullscreen video mode was set before the mouse was initialized,
+// set the mouse state appropriately
+	if (mouseactivatetoggle)
+		IN_ActivateMouse ();
+}
+
+
+/*
+===========
+IN_Init
+===========
+*/
+void IN_Init (void)
+{
+	// mouse variables
+	Cvar_RegisterVariable (&m_filter);
+
+	// joystick variables
+	Cvar_RegisterVariable (&in_joystick);
+	Cvar_RegisterVariable (&joy_name);
+	Cvar_RegisterVariable (&joy_advanced);
+	Cvar_RegisterVariable (&joy_advaxisx);
+	Cvar_RegisterVariable (&joy_advaxisy);
+	Cvar_RegisterVariable (&joy_advaxisz);
+	Cvar_RegisterVariable (&joy_advaxisr);
+	Cvar_RegisterVariable (&joy_advaxisu);
+	Cvar_RegisterVariable (&joy_advaxisv);
+	Cvar_RegisterVariable (&joy_forwardthreshold);
+	Cvar_RegisterVariable (&joy_sidethreshold);
+	Cvar_RegisterVariable (&joy_pitchthreshold);
+	Cvar_RegisterVariable (&joy_yawthreshold);
+	Cvar_RegisterVariable (&joy_forwardsensitivity);
+	Cvar_RegisterVariable (&joy_sidesensitivity);
+	Cvar_RegisterVariable (&joy_pitchsensitivity);
+	Cvar_RegisterVariable (&joy_yawsensitivity);
+	Cvar_RegisterVariable (&joy_wwhack1);
+	Cvar_RegisterVariable (&joy_wwhack2);
+
+	Cmd_AddCommand ("force_centerview", Force_CenterView_f);
+	Cmd_AddCommand ("joyadvancedupdate", Joy_AdvancedUpdate_f);
+
+	uiWheelMessage = RegisterWindowMessage ( "MSWHEEL_ROLLMSG" );
+
+	IN_StartupMouse ();
+	IN_StartupJoystick ();
+}
+
+/*
+===========
+IN_Shutdown
+===========
+*/
+void IN_Shutdown (void)
+{
+
+	IN_DeactivateMouse ();
+	IN_ShowMouse ();
+
+    if (g_pMouse)
+	{
+		IDirectInputDevice_Release(g_pMouse);
+		g_pMouse = NULL;
+	}
+
+    if (g_pdi)
+	{
+		IDirectInput_Release(g_pdi);
+		g_pdi = NULL;
+	}
+}
+
+
+/*
+===========
+IN_MouseEvent
+===========
+*/
+void IN_MouseEvent (int mstate)
+{
+	int		i;
+
+	if (mouseactive && !dinput)
+	{
+	// perform button actions
+		for (i=0 ; i<mouse_buttons ; i++)
+		{
+			if ( (mstate & (1<<i)) &&
+				!(mouse_oldbuttonstate & (1<<i)) )
+			{
+				Key_Event (K_MOUSE1 + i, true);
+			}
+
+			if ( !(mstate & (1<<i)) &&
+				(mouse_oldbuttonstate & (1<<i)) )
+			{
+					Key_Event (K_MOUSE1 + i, false);
+			}
+		}	
+			
+		mouse_oldbuttonstate = mstate;
+	}
+}
+
+
+/*
+===========
+IN_MouseMove
+===========
+*/
+void IN_MouseMove (usercmd_t *cmd)
+{
+	int		mx, my;
+	HDC	hdc;
+	int					i;
+	DIDEVICEOBJECTDATA	od;
+	DWORD				dwElements;
+	HRESULT				hr;
+
+	if (!mouseactive)
+		return;
+
+	if (dinput)
+	{
+		mx = 0;
+		my = 0;
+
+		for (;;)
+		{
+			dwElements = 1;
+
+			hr = IDirectInputDevice_GetDeviceData(g_pMouse,
+					sizeof(DIDEVICEOBJECTDATA), &od, &dwElements, 0);
+
+			if ((hr == DIERR_INPUTLOST) || (hr == DIERR_NOTACQUIRED))
+			{
+				dinput_acquired = true;
+				IDirectInputDevice_Acquire(g_pMouse);
+				break;
+			}
+
+			/* Unable to read data or no data available */
+			if (FAILED(hr) || dwElements == 0)
+			{
+				break;
+			}
+
+			/* Look at the element to see what happened */
+
+			switch (od.dwOfs)
+			{
+				case DIMOFS_X:
+					mx += od.dwData;
+					break;
+
+				case DIMOFS_Y:
+					my += od.dwData;
+					break;
+
+				case DIMOFS_BUTTON0:
+					if (od.dwData & 0x80)
+						mstate_di |= 1;
+					else
+						mstate_di &= ~1;
+					break;
+
+				case DIMOFS_BUTTON1:
+					if (od.dwData & 0x80)
+						mstate_di |= (1<<1);
+					else
+						mstate_di &= ~(1<<1);
+					break;
+					
+				case DIMOFS_BUTTON2:
+					if (od.dwData & 0x80)
+						mstate_di |= (1<<2);
+					else
+						mstate_di &= ~(1<<2);
+					break;
+			}
+		}
+
+	// perform button actions
+		for (i=0 ; i<mouse_buttons ; i++)
+		{
+			if ( (mstate_di & (1<<i)) &&
+				!(mouse_oldbuttonstate & (1<<i)) )
+			{
+				Key_Event (K_MOUSE1 + i, true);
+			}
+
+			if ( !(mstate_di & (1<<i)) &&
+				(mouse_oldbuttonstate & (1<<i)) )
+			{
+				Key_Event (K_MOUSE1 + i, false);
+			}
+		}	
+			
+		mouse_oldbuttonstate = mstate_di;
+	}
+	else
+	{
+		GetCursorPos (&current_pos);
+	mx = current_pos.x - window_center_x + mx_accum;
+	my = current_pos.y - window_center_y + my_accum;
+	mx_accum = 0;
+	my_accum = 0;
+	}
+
+	if (m_filter.value)
+	{
+		mouse_x = (mx + old_mouse_x) * 0.5;
+		mouse_y = (my + old_mouse_y) * 0.5;
+	}
+	else
+	{
+		mouse_x = mx;
+		mouse_y = my;
+	}
+
+	old_mouse_x = mx;
+	old_mouse_y = my;
+
+	mouse_x *= sensitivity.value;
+	mouse_y *= sensitivity.value;
+
+// add mouse X/Y movement to cmd
+	if ( (in_strafe.state & 1) || (lookstrafe.value && (in_mlook.state & 1) ))
+		cmd->sidemove += m_side.value * mouse_x;
+	else
+		cl.viewangles[YAW] -= m_yaw.value * mouse_x;
+
+	if (in_mlook.state & 1)
+		V_StopPitchDrift ();
+		
+	if ( (in_mlook.state & 1) && !(in_strafe.state & 1))
+	{
+		cl.viewangles[PITCH] += m_pitch.value * mouse_y;
+		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 * mouse_y;
+		else
+			cmd->forwardmove -= m_forward.value * mouse_y;
+	}
+
+// if the mouse has moved, force it to the center, so there's room to move
+	if (mx || my)
+	{
+		SetCursorPos (window_center_x, window_center_y);
+	}
+}
+
+
+/*
+===========
+IN_Move
+===========
+*/
+void IN_Move (usercmd_t *cmd)
+{
+
+	if (ActiveApp && !Minimized)
+	{
+		IN_MouseMove (cmd);
+		IN_JoyMove (cmd);
+	}
+}
+
+
+/*
+===========
+IN_Accumulate
+===========
+*/
+void IN_Accumulate (void)
+{
+	int		mx, my;
+	HDC	hdc;
+
+	if (mouseactive)
+	{
+		GetCursorPos (&current_pos);
+
+		mx_accum += current_pos.x - window_center_x;
+		my_accum += current_pos.y - window_center_y;
+
+	// force the mouse to the center, so there's room to move
+		SetCursorPos (window_center_x, window_center_y);
+	}
+}
+
+
+/*
+===================
+IN_ClearStates
+===================
+*/
+void IN_ClearStates (void)
+{
+
+	if (mouseactive)
+	{
+		mx_accum = 0;
+		my_accum = 0;
+		mouse_oldbuttonstate = 0;
+	}
+}
+
+
+/* 
+=============== 
+IN_StartupJoystick 
+=============== 
+*/  
+void IN_StartupJoystick (void) 
+{ 
+	int			i, numdevs;
+	JOYCAPS		jc;
+	MMRESULT	mmr;
+ 
+ 	// assume no joystick
+	joy_avail = false; 
+
+	// abort startup if user requests no joystick
+	if ( COM_CheckParm ("-nojoy") ) 
+		return; 
+ 
+	// verify joystick driver is present
+	if ((numdevs = joyGetNumDevs ()) == 0)
+	{
+		Con_Printf ("\njoystick not found -- driver not present\n\n");
+		return;
+	}
+
+	// cycle through the joystick ids for the first valid one
+	for (joy_id=0 ; joy_id<numdevs ; joy_id++)
+	{
+		memset (&ji, 0, sizeof(ji));
+		ji.dwSize = sizeof(ji);
+		ji.dwFlags = JOY_RETURNCENTERED;
+
+		if ((mmr = joyGetPosEx (joy_id, &ji)) == JOYERR_NOERROR)
+			break;
+	} 
+
+	// abort startup if we didn't find a valid joystick
+	if (mmr != JOYERR_NOERROR)
+	{
+		Con_Printf ("\njoystick not found -- no valid joysticks (%x)\n\n", mmr);
+		return;
+	}
+
+	// get the capabilities of the selected joystick
+	// abort startup if command fails
+	memset (&jc, 0, sizeof(jc));
+	if ((mmr = joyGetDevCaps (joy_id, &jc, sizeof(jc))) != JOYERR_NOERROR)
+	{
+		Con_Printf ("\njoystick not found -- invalid joystick capabilities (%x)\n\n", mmr); 
+		return;
+	}
+
+	// save the joystick's number of buttons and POV status
+	joy_numbuttons = jc.wNumButtons;
+	joy_haspov = jc.wCaps & JOYCAPS_HASPOV;
+
+	// old button and POV states default to no buttons pressed
+	joy_oldbuttonstate = joy_oldpovstate = 0;
+
+	// mark the joystick as available and advanced initialization not completed
+	// this is needed as cvars are not available during initialization
+
+	joy_avail = true; 
+	joy_advancedinit = false;
+
+	Con_Printf ("\njoystick detected\n\n"); 
+}
+
+
+/*
+===========
+RawValuePointer
+===========
+*/
+PDWORD RawValuePointer (int axis)
+{
+	switch (axis)
+	{
+	case JOY_AXIS_X:
+		return &ji.dwXpos;
+	case JOY_AXIS_Y:
+		return &ji.dwYpos;
+	case JOY_AXIS_Z:
+		return &ji.dwZpos;
+	case JOY_AXIS_R:
+		return &ji.dwRpos;
+	case JOY_AXIS_U:
+		return &ji.dwUpos;
+	case JOY_AXIS_V:
+		return &ji.dwVpos;
+	}
+}
+
+
+/*
+===========
+Joy_AdvancedUpdate_f
+===========
+*/
+void Joy_AdvancedUpdate_f (void)
+{
+
+	// called once by IN_ReadJoystick and by user whenever an update is needed
+	// cvars are now available
+	int	i;
+	DWORD dwTemp;
+
+	// initialize all the maps
+	for (i = 0; i < JOY_MAX_AXES; i++)
+	{
+		dwAxisMap[i] = AxisNada;
+		dwControlMap[i] = JOY_ABSOLUTE_AXIS;
+		pdwRawValue[i] = RawValuePointer(i);
+	}
+
+	if( joy_advanced.value == 0.0)
+	{
+		// default joystick initialization
+		// 2 axes only with joystick control
+		dwAxisMap[JOY_AXIS_X] = AxisTurn;
+		// dwControlMap[JOY_AXIS_X] = JOY_ABSOLUTE_AXIS;
+		dwAxisMap[JOY_AXIS_Y] = AxisForward;
+		// dwControlMap[JOY_AXIS_Y] = JOY_ABSOLUTE_AXIS;
+	}
+	else
+	{
+		if (Q_strcmp (joy_name.string, "joystick") != 0)
+		{
+			// notify user of advanced controller
+			Con_Printf ("\n%s configured\n\n", joy_name.string);
+		}
+
+		// advanced initialization here
+		// data supplied by user via joy_axisn cvars
+		dwTemp = (DWORD) joy_advaxisx.value;
+		dwAxisMap[JOY_AXIS_X] = dwTemp & 0x0000000f;
+		dwControlMap[JOY_AXIS_X] = dwTemp & JOY_RELATIVE_AXIS;
+		dwTemp = (DWORD) joy_advaxisy.value;
+		dwAxisMap[JOY_AXIS_Y] = dwTemp & 0x0000000f;
+		dwControlMap[JOY_AXIS_Y] = dwTemp & JOY_RELATIVE_AXIS;
+		dwTemp = (DWORD) joy_advaxisz.value;
+		dwAxisMap[JOY_AXIS_Z] = dwTemp & 0x0000000f;
+		dwControlMap[JOY_AXIS_Z] = dwTemp & JOY_RELATIVE_AXIS;
+		dwTemp = (DWORD) joy_advaxisr.value;
+		dwAxisMap[JOY_AXIS_R] = dwTemp & 0x0000000f;
+		dwControlMap[JOY_AXIS_R] = dwTemp & JOY_RELATIVE_AXIS;
+		dwTemp = (DWORD) joy_advaxisu.value;
+		dwAxisMap[JOY_AXIS_U] = dwTemp & 0x0000000f;
+		dwControlMap[JOY_AXIS_U] = dwTemp & JOY_RELATIVE_AXIS;
+		dwTemp = (DWORD) joy_advaxisv.value;
+		dwAxisMap[JOY_AXIS_V] = dwTemp & 0x0000000f;
+		dwControlMap[JOY_AXIS_V] = dwTemp & JOY_RELATIVE_AXIS;
+	}
+
+	// compute the axes to collect from DirectInput
+	joy_flags = JOY_RETURNCENTERED | JOY_RETURNBUTTONS | JOY_RETURNPOV;
+	for (i = 0; i < JOY_MAX_AXES; i++)
+	{
+		if (dwAxisMap[i] != AxisNada)
+		{
+			joy_flags |= dwAxisFlags[i];
+		}
+	}
+}
+
+
+/*
+===========
+IN_Commands
+===========
+*/
+void IN_Commands (void)
+{
+	int		i, key_index;
+	DWORD	buttonstate, povstate;
+
+	if (!joy_avail)
+	{
+		return;
+	}
+
+	
+	// loop through the joystick buttons
+	// key a joystick event or auxillary event for higher number buttons for each state change
+	buttonstate = ji.dwButtons;
+	for (i=0 ; i < joy_numbuttons ; i++)
+	{
+		if ( (buttonstate & (1<<i)) && !(joy_oldbuttonstate & (1<<i)) )
+		{
+			key_index = (i < 4) ? K_JOY1 : K_AUX1;
+			Key_Event (key_index + i, true);
+		}
+
+		if ( !(buttonstate & (1<<i)) && (joy_oldbuttonstate & (1<<i)) )
+		{
+			key_index = (i < 4) ? K_JOY1 : K_AUX1;
+			Key_Event (key_index + i, false);
+		}
+	}
+	joy_oldbuttonstate = buttonstate;
+
+	if (joy_haspov)
+	{
+		// convert POV information into 4 bits of state information
+		// this avoids any potential problems related to moving from one
+		// direction to another without going through the center position
+		povstate = 0;
+		if(ji.dwPOV != JOY_POVCENTERED)
+		{
+			if (ji.dwPOV == JOY_POVFORWARD)
+				povstate |= 0x01;
+			if (ji.dwPOV == JOY_POVRIGHT)
+				povstate |= 0x02;
+			if (ji.dwPOV == JOY_POVBACKWARD)
+				povstate |= 0x04;
+			if (ji.dwPOV == JOY_POVLEFT)
+				povstate |= 0x08;
+		}
+		// determine which bits have changed and key an auxillary event for each change
+		for (i=0 ; i < 4 ; i++)
+		{
+			if ( (povstate & (1<<i)) && !(joy_oldpovstate & (1<<i)) )
+			{
+				Key_Event (K_AUX29 + i, true);
+			}
+
+			if ( !(povstate & (1<<i)) && (joy_oldpovstate & (1<<i)) )
+			{
+				Key_Event (K_AUX29 + i, false);
+			}
+		}
+		joy_oldpovstate = povstate;
+	}
+}
+
+
+/* 
+=============== 
+IN_ReadJoystick
+=============== 
+*/  
+qboolean IN_ReadJoystick (void)
+{
+
+	memset (&ji, 0, sizeof(ji));
+	ji.dwSize = sizeof(ji);
+	ji.dwFlags = joy_flags;
+
+	if (joyGetPosEx (joy_id, &ji) == JOYERR_NOERROR)
+	{
+		// this is a hack -- there is a bug in the Logitech WingMan Warrior DirectInput Driver
+		// rather than having 32768 be the zero point, they have the zero point at 32668
+		// go figure -- anyway, now we get the full resolution out of the device
+		if (joy_wwhack1.value != 0.0)
+		{
+			ji.dwUpos += 100;
+		}
+		return true;
+	}
+	else
+	{
+		// read error occurred
+		// turning off the joystick seems too harsh for 1 read error,\
+		// but what should be done?
+		// Con_Printf ("IN_ReadJoystick: no response\n");
+		// joy_avail = false;
+		return false;
+	}
+}
+
+
+/*
+===========
+IN_JoyMove
+===========
+*/
+void IN_JoyMove (usercmd_t *cmd)
+{
+	float	speed, aspeed;
+	float	fAxisValue, fTemp;
+	int		i;
+
+	// complete initialization if first time in
+	// this is needed as cvars are not available at initialization time
+	if( joy_advancedinit != true )
+	{
+		Joy_AdvancedUpdate_f();
+		joy_advancedinit = true;
+	}
+
+	// verify joystick is available and that the user wants to use it
+	if (!joy_avail || !in_joystick.value)
+	{
+		return; 
+	}
+ 
+	// collect the joystick data, if possible
+	if (IN_ReadJoystick () != true)
+	{
+		return;
+	}
+
+	if (in_speed.state & 1)
+		speed = cl_movespeedkey.value;
+	else
+		speed = 1;
+	aspeed = speed * host_frametime;
+
+	// loop through the axes
+	for (i = 0; i < JOY_MAX_AXES; i++)
+	{
+		// get the floating point zero-centered, potentially-inverted data for the current axis
+		fAxisValue = (float) *pdwRawValue[i];
+		// move centerpoint to zero
+		fAxisValue -= 32768.0;
+
+		if (joy_wwhack2.value != 0.0)
+		{
+			if (dwAxisMap[i] == AxisTurn)
+			{
+				// this is a special formula for the Logitech WingMan Warrior
+				// y=ax^b; where a = 300 and b = 1.3
+				// also x values are in increments of 800 (so this is factored out)
+				// then bounds check result to level out excessively high spin rates
+				fTemp = 300.0 * pow(abs(fAxisValue) / 800.0, 1.3);
+				if (fTemp > 14000.0)
+					fTemp = 14000.0;
+				// restore direction information
+				fAxisValue = (fAxisValue > 0.0) ? fTemp : -fTemp;
+			}
+		}
+
+		// convert range from -32768..32767 to -1..1 
+		fAxisValue /= 32768.0;
+
+		switch (dwAxisMap[i])
+		{
+		case AxisForward:
+			if ((joy_advanced.value == 0.0) && (in_mlook.state & 1))
+			{
+				// user wants forward control to become look control
+				if (fabs(fAxisValue) > joy_pitchthreshold.value)
+				{		
+					// if mouse invert is on, invert the joystick pitch value
+					// only absolute control support here (joy_advanced is false)
+					if (m_pitch.value < 0.0)
+					{
+						cl.viewangles[PITCH] -= (fAxisValue * joy_pitchsensitivity.value) * aspeed * cl_pitchspeed.value;
+					}
+					else
+					{
+						cl.viewangles[PITCH] += (fAxisValue * joy_pitchsensitivity.value) * aspeed * cl_pitchspeed.value;
+					}
+					V_StopPitchDrift();
+				}
+				else
+				{
+					// no pitch movement
+					// disable pitch return-to-center unless requested by user
+					// *** this code can be removed when the lookspring bug is fixed
+					// *** the bug always has the lookspring feature on
+					if(lookspring.value == 0.0)
+						V_StopPitchDrift();
+				}
+			}
+			else
+			{
+				// user wants forward control to be forward control
+				if (fabs(fAxisValue) > joy_forwardthreshold.value)
+				{
+					cmd->forwardmove += (fAxisValue * joy_forwardsensitivity.value) * speed * cl_forwardspeed.value;
+				}
+			}
+			break;
+
+		case AxisSide:
+			if (fabs(fAxisValue) > joy_sidethreshold.value)
+			{
+				cmd->sidemove += (fAxisValue * joy_sidesensitivity.value) * speed * cl_sidespeed.value;
+			}
+			break;
+
+		case AxisTurn:
+			if ((in_strafe.state & 1) || (lookstrafe.value && (in_mlook.state & 1)))
+			{
+				// user wants turn control to become side control
+				if (fabs(fAxisValue) > joy_sidethreshold.value)
+				{
+					cmd->sidemove -= (fAxisValue * joy_sidesensitivity.value) * speed * cl_sidespeed.value;
+				}
+			}
+			else
+			{
+				// user wants turn control to be turn control
+				if (fabs(fAxisValue) > joy_yawthreshold.value)
+				{
+					if(dwControlMap[i] == JOY_ABSOLUTE_AXIS)
+					{
+						cl.viewangles[YAW] += (fAxisValue * joy_yawsensitivity.value) * aspeed * cl_yawspeed.value;
+					}
+					else
+					{
+						cl.viewangles[YAW] += (fAxisValue * joy_yawsensitivity.value) * speed * 180.0;
+					}
+
+				}
+			}
+			break;
+
+		case AxisLook:
+			if (in_mlook.state & 1)
+			{
+				if (fabs(fAxisValue) > joy_pitchthreshold.value)
+				{
+					// pitch movement detected and pitch movement desired by user
+					if(dwControlMap[i] == JOY_ABSOLUTE_AXIS)
+					{
+						cl.viewangles[PITCH] += (fAxisValue * joy_pitchsensitivity.value) * aspeed * cl_pitchspeed.value;
+					}
+					else
+					{
+						cl.viewangles[PITCH] += (fAxisValue * joy_pitchsensitivity.value) * speed * 180.0;
+					}
+					V_StopPitchDrift();
+				}
+				else
+				{
+					// no pitch movement
+					// disable pitch return-to-center unless requested by user
+					// *** this code can be removed when the lookspring bug is fixed
+					// *** the bug always has the lookspring feature on
+					if(lookspring.value == 0.0)
+						V_StopPitchDrift();
+				}
+			}
+			break;
+
+		default:
+			break;
+		}
+	}
+
+	// bounds check pitch
+	if (cl.viewangles[PITCH] > 80.0)
+		cl.viewangles[PITCH] = 80.0;
+	if (cl.viewangles[PITCH] < -70.0)
+		cl.viewangles[PITCH] = -70.0;
+}
--- /dev/null
+++ b/QW/client/input.h
@@ -1,0 +1,34 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// input.h -- external (non-keyboard) input devices
+
+void IN_Init (void);
+
+void IN_Shutdown (void);
+
+void IN_Commands (void);
+// oportunity for devices to stick commands on the script buffer
+
+void IN_Move (usercmd_t *cmd);
+// add additional movement on top of the keyboard move cmd
+
+void IN_ModeChanged (void);
+// called whenever screen dimensions change
+
--- /dev/null
+++ b/QW/client/keys.c
@@ -1,0 +1,839 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+#include "quakedef.h"
+#ifdef _WINDOWS
+#include <windows.h>
+#endif
+/*
+
+key up events are sent even if in console mode
+
+*/
+
+
+#define		MAXCMDLINE	256
+char	key_lines[32][MAXCMDLINE];
+int		key_linepos;
+int		shift_down=false;
+int		key_lastpress;
+
+int		edit_line=0;
+int		history_line=0;
+
+keydest_t	key_dest;
+
+int		key_count;			// incremented every key event
+
+char	*keybindings[256];
+qboolean	consolekeys[256];	// if true, can't be rebound while in console
+qboolean	menubound[256];	// if true, can't be rebound while in menu
+int		keyshift[256];		// key to map to if shift held down in console
+int		key_repeats[256];	// if > 1, it is autorepeating
+qboolean	keydown[256];
+
+typedef struct
+{
+	char	*name;
+	int		keynum;
+} keyname_t;
+
+keyname_t keynames[] =
+{
+	{"TAB", K_TAB},
+	{"ENTER", K_ENTER},
+	{"ESCAPE", K_ESCAPE},
+	{"SPACE", K_SPACE},
+	{"BACKSPACE", K_BACKSPACE},
+	{"UPARROW", K_UPARROW},
+	{"DOWNARROW", K_DOWNARROW},
+	{"LEFTARROW", K_LEFTARROW},
+	{"RIGHTARROW", K_RIGHTARROW},
+
+	{"ALT", K_ALT},
+	{"CTRL", K_CTRL},
+	{"SHIFT", K_SHIFT},
+	
+	{"F1", K_F1},
+	{"F2", K_F2},
+	{"F3", K_F3},
+	{"F4", K_F4},
+	{"F5", K_F5},
+	{"F6", K_F6},
+	{"F7", K_F7},
+	{"F8", K_F8},
+	{"F9", K_F9},
+	{"F10", K_F10},
+	{"F11", K_F11},
+	{"F12", K_F12},
+
+	{"INS", K_INS},
+	{"DEL", K_DEL},
+	{"PGDN", K_PGDN},
+	{"PGUP", K_PGUP},
+	{"HOME", K_HOME},
+	{"END", K_END},
+
+	{"MOUSE1", K_MOUSE1},
+	{"MOUSE2", K_MOUSE2},
+	{"MOUSE3", K_MOUSE3},
+
+	{"JOY1", K_JOY1},
+	{"JOY2", K_JOY2},
+	{"JOY3", K_JOY3},
+	{"JOY4", K_JOY4},
+
+	{"AUX1", K_AUX1},
+	{"AUX2", K_AUX2},
+	{"AUX3", K_AUX3},
+	{"AUX4", K_AUX4},
+	{"AUX5", K_AUX5},
+	{"AUX6", K_AUX6},
+	{"AUX7", K_AUX7},
+	{"AUX8", K_AUX8},
+	{"AUX9", K_AUX9},
+	{"AUX10", K_AUX10},
+	{"AUX11", K_AUX11},
+	{"AUX12", K_AUX12},
+	{"AUX13", K_AUX13},
+	{"AUX14", K_AUX14},
+	{"AUX15", K_AUX15},
+	{"AUX16", K_AUX16},
+	{"AUX17", K_AUX17},
+	{"AUX18", K_AUX18},
+	{"AUX19", K_AUX19},
+	{"AUX20", K_AUX20},
+	{"AUX21", K_AUX21},
+	{"AUX22", K_AUX22},
+	{"AUX23", K_AUX23},
+	{"AUX24", K_AUX24},
+	{"AUX25", K_AUX25},
+	{"AUX26", K_AUX26},
+	{"AUX27", K_AUX27},
+	{"AUX28", K_AUX28},
+	{"AUX29", K_AUX29},
+	{"AUX30", K_AUX30},
+	{"AUX31", K_AUX31},
+	{"AUX32", K_AUX32},
+
+	{"PAUSE", K_PAUSE},
+
+	{"MWHEELUP", K_MWHEELUP},
+	{"MWHEELDOWN", K_MWHEELDOWN},
+
+	{"SEMICOLON", ';'},	// because a raw semicolon seperates commands
+
+	{NULL,0}
+};
+
+/*
+==============================================================================
+
+			LINE TYPING INTO THE CONSOLE
+
+==============================================================================
+*/
+
+qboolean CheckForCommand (void)
+{
+	char	command[128];
+	char	*cmd, *s;
+	int		i;
+
+	s = key_lines[edit_line]+1;
+
+	for (i=0 ; i<127 ; i++)
+		if (s[i] <= ' ')
+			break;
+		else
+			command[i] = s[i];
+	command[i] = 0;
+
+	cmd = Cmd_CompleteCommand (command);
+	if (!cmd || strcmp (cmd, command))
+		cmd = Cvar_CompleteVariable (command);
+	if (!cmd  || strcmp (cmd, command) )
+		return false;		// just a chat message
+	return true;
+}
+
+void CompleteCommand (void)
+{
+	char	*cmd, *s;
+
+	s = key_lines[edit_line]+1;
+	if (*s == '\\' || *s == '/')
+		s++;
+
+	cmd = Cmd_CompleteCommand (s);
+	if (!cmd)
+		cmd = Cvar_CompleteVariable (s);
+	if (cmd)
+	{
+		key_lines[edit_line][1] = '/';
+		Q_strcpy (key_lines[edit_line]+2, cmd);
+		key_linepos = Q_strlen(cmd)+2;
+		key_lines[edit_line][key_linepos] = ' ';
+		key_linepos++;
+		key_lines[edit_line][key_linepos] = 0;
+		return;
+	}
+}
+
+/*
+====================
+Key_Console
+
+Interactive line editing and console scrollback
+====================
+*/
+void Key_Console (int key)
+{
+#ifdef _WIN32
+	char	*cmd, *s;
+	int		i;
+	HANDLE	th;
+	char	*clipText, *textCopied;
+#endif
+	
+	if (key == K_ENTER)
+	{	// backslash text are commands, else chat
+		if (key_lines[edit_line][1] == '\\' || key_lines[edit_line][1] == '/')
+			Cbuf_AddText (key_lines[edit_line]+2);	// skip the >
+		else if (CheckForCommand())
+			Cbuf_AddText (key_lines[edit_line]+1);	// valid command
+		else
+		{	// convert to a chat message
+			if (cls.state >= ca_connected)
+				Cbuf_AddText ("say ");
+			Cbuf_AddText (key_lines[edit_line]+1);	// skip the >
+		}
+
+		Cbuf_AddText ("\n");
+		Con_Printf ("%s\n",key_lines[edit_line]);
+		edit_line = (edit_line + 1) & 31;
+		history_line = edit_line;
+		key_lines[edit_line][0] = ']';
+		key_linepos = 1;
+		if (cls.state == ca_disconnected)
+			SCR_UpdateScreen ();	// force an update, because the command
+									// may take some time
+		return;
+	}
+
+	if (key == K_TAB)
+	{	// command completion
+		CompleteCommand ();
+		return;
+	}
+	
+	if (key == K_BACKSPACE || key == K_LEFTARROW)
+	{
+		if (key_linepos > 1)
+			key_linepos--;
+		return;
+	}
+
+	if (key == K_UPARROW)
+	{
+		do
+		{
+			history_line = (history_line - 1) & 31;
+		} while (history_line != edit_line
+				&& !key_lines[history_line][1]);
+		if (history_line == edit_line)
+			history_line = (edit_line+1)&31;
+		Q_strcpy(key_lines[edit_line], key_lines[history_line]);
+		key_linepos = Q_strlen(key_lines[edit_line]);
+		return;
+	}
+
+	if (key == K_DOWNARROW)
+	{
+		if (history_line == edit_line) return;
+		do
+		{
+			history_line = (history_line + 1) & 31;
+		}
+		while (history_line != edit_line
+			&& !key_lines[history_line][1]);
+		if (history_line == edit_line)
+		{
+			key_lines[edit_line][0] = ']';
+			key_linepos = 1;
+		}
+		else
+		{
+			Q_strcpy(key_lines[edit_line], key_lines[history_line]);
+			key_linepos = Q_strlen(key_lines[edit_line]);
+		}
+		return;
+	}
+
+	if (key == K_PGUP || key==K_MWHEELUP)
+	{
+		con->display -= 2;
+		return;
+	}
+
+	if (key == K_PGDN || key==K_MWHEELDOWN)
+	{
+		con->display += 2;
+		if (con->display > con->current)
+			con->display = con->current;
+		return;
+	}
+
+	if (key == K_HOME)
+	{
+		con->display = con->current - con_totallines + 10;
+		return;
+	}
+
+	if (key == K_END)
+	{
+		con->display = con->current;
+		return;
+	}
+	
+#ifdef _WIN32
+	if ((key=='V' || key=='v') && GetKeyState(VK_CONTROL)<0) {
+		if (OpenClipboard(NULL)) {
+			th = GetClipboardData(CF_TEXT);
+			if (th) {
+				clipText = GlobalLock(th);
+				if (clipText) {
+					textCopied = malloc(GlobalSize(th)+1);
+					strcpy(textCopied, clipText);
+	/* Substitutes a NULL for every token */strtok(textCopied, "\n\r\b");
+					i = strlen(textCopied);
+					if (i+key_linepos>=MAXCMDLINE)
+						i=MAXCMDLINE-key_linepos;
+					if (i>0) {
+						textCopied[i]=0;
+						strcat(key_lines[edit_line], textCopied);
+						key_linepos+=i;;
+					}
+					free(textCopied);
+				}
+				GlobalUnlock(th);
+			}
+			CloseClipboard();
+		return;
+		}
+	}
+#endif
+
+	if (key < 32 || key > 127)
+		return;	// non printable
+		
+	if (key_linepos < MAXCMDLINE-1)
+	{
+		key_lines[edit_line][key_linepos] = key;
+		key_linepos++;
+		key_lines[edit_line][key_linepos] = 0;
+	}
+
+}
+
+//============================================================================
+
+qboolean	chat_team;
+char		chat_buffer[MAXCMDLINE];
+int			chat_bufferlen = 0;
+
+void Key_Message (int key)
+{
+
+	if (key == K_ENTER)
+	{
+		if (chat_team)
+			Cbuf_AddText ("say_team \"");
+		else
+			Cbuf_AddText ("say \"");
+		Cbuf_AddText(chat_buffer);
+		Cbuf_AddText("\"\n");
+
+		key_dest = key_game;
+		chat_bufferlen = 0;
+		chat_buffer[0] = 0;
+		return;
+	}
+
+	if (key == K_ESCAPE)
+	{
+		key_dest = key_game;
+		chat_bufferlen = 0;
+		chat_buffer[0] = 0;
+		return;
+	}
+
+	if (key < 32 || key > 127)
+		return;	// non printable
+
+	if (key == K_BACKSPACE)
+	{
+		if (chat_bufferlen)
+		{
+			chat_bufferlen--;
+			chat_buffer[chat_bufferlen] = 0;
+		}
+		return;
+	}
+
+	if (chat_bufferlen == sizeof(chat_buffer)-1)
+		return; // all full
+
+	chat_buffer[chat_bufferlen++] = key;
+	chat_buffer[chat_bufferlen] = 0;
+}
+
+//============================================================================
+
+
+/*
+===================
+Key_StringToKeynum
+
+Returns a key number to be used to index keybindings[] by looking at
+the given string.  Single ascii characters return themselves, while
+the K_* names are matched up.
+===================
+*/
+int Key_StringToKeynum (char *str)
+{
+	keyname_t	*kn;
+	
+	if (!str || !str[0])
+		return -1;
+	if (!str[1])
+		return str[0];
+
+	for (kn=keynames ; kn->name ; kn++)
+	{
+		if (!Q_strcasecmp(str,kn->name))
+			return kn->keynum;
+	}
+	return -1;
+}
+
+/*
+===================
+Key_KeynumToString
+
+Returns a string (either a single ascii char, or a K_* name) for the
+given keynum.
+FIXME: handle quote special (general escape sequence?)
+===================
+*/
+char *Key_KeynumToString (int keynum)
+{
+	keyname_t	*kn;	
+	static	char	tinystr[2];
+	
+	if (keynum == -1)
+		return "<KEY NOT FOUND>";
+	if (keynum > 32 && keynum < 127)
+	{	// printable ascii
+		tinystr[0] = keynum;
+		tinystr[1] = 0;
+		return tinystr;
+	}
+	
+	for (kn=keynames ; kn->name ; kn++)
+		if (keynum == kn->keynum)
+			return kn->name;
+
+	return "<UNKNOWN KEYNUM>";
+}
+
+
+/*
+===================
+Key_SetBinding
+===================
+*/
+void Key_SetBinding (int keynum, char *binding)
+{
+	char	*new;
+	int		l;
+			
+	if (keynum == -1)
+		return;
+
+// free old bindings
+	if (keybindings[keynum])
+	{
+		Z_Free (keybindings[keynum]);
+		keybindings[keynum] = NULL;
+	}
+			
+// allocate memory for new binding
+	l = Q_strlen (binding);	
+	new = Z_Malloc (l+1);
+	Q_strcpy (new, binding);
+	new[l] = 0;
+	keybindings[keynum] = new;	
+}
+
+/*
+===================
+Key_Unbind_f
+===================
+*/
+void Key_Unbind_f (void)
+{
+	int		b;
+
+	if (Cmd_Argc() != 2)
+	{
+		Con_Printf ("unbind <key> : remove commands from a key\n");
+		return;
+	}
+	
+	b = Key_StringToKeynum (Cmd_Argv(1));
+	if (b==-1)
+	{
+		Con_Printf ("\"%s\" isn't a valid key\n", Cmd_Argv(1));
+		return;
+	}
+
+	Key_SetBinding (b, "");
+}
+
+void Key_Unbindall_f (void)
+{
+	int		i;
+	
+	for (i=0 ; i<256 ; i++)
+		if (keybindings[i])
+			Key_SetBinding (i, "");
+}
+
+
+/*
+===================
+Key_Bind_f
+===================
+*/
+void Key_Bind_f (void)
+{
+	int			i, c, b;
+	char		cmd[1024];
+	
+	c = Cmd_Argc();
+
+	if (c != 2 && c != 3)
+	{
+		Con_Printf ("bind <key> [command] : attach a command to a key\n");
+		return;
+	}
+	b = Key_StringToKeynum (Cmd_Argv(1));
+	if (b==-1)
+	{
+		Con_Printf ("\"%s\" isn't a valid key\n", Cmd_Argv(1));
+		return;
+	}
+
+	if (c == 2)
+	{
+		if (keybindings[b])
+			Con_Printf ("\"%s\" = \"%s\"\n", Cmd_Argv(1), keybindings[b] );
+		else
+			Con_Printf ("\"%s\" is not bound\n", Cmd_Argv(1) );
+		return;
+	}
+	
+// copy the rest of the command line
+	cmd[0] = 0;		// start out with a null string
+	for (i=2 ; i< c ; i++)
+	{
+		strcat (cmd, Cmd_Argv(i));
+		if (i != (c-1))
+			strcat (cmd, " ");
+	}
+
+	Key_SetBinding (b, cmd);
+}
+
+/*
+============
+Key_WriteBindings
+
+Writes lines containing "bind key value"
+============
+*/
+void Key_WriteBindings (FILE *f)
+{
+	int		i;
+
+	for (i=0 ; i<256 ; i++)
+		if (keybindings[i])
+			fprintf (f, "bind %s \"%s\"\n", Key_KeynumToString(i), keybindings[i]);
+}
+
+
+/*
+===================
+Key_Init
+===================
+*/
+void Key_Init (void)
+{
+	int		i;
+
+	for (i=0 ; i<32 ; i++)
+	{
+		key_lines[i][0] = ']';
+		key_lines[i][1] = 0;
+	}
+	key_linepos = 1;
+	
+//
+// init ascii characters in console mode
+//
+	for (i=32 ; i<128 ; i++)
+		consolekeys[i] = true;
+	consolekeys[K_ENTER] = true;
+	consolekeys[K_TAB] = true;
+	consolekeys[K_LEFTARROW] = true;
+	consolekeys[K_RIGHTARROW] = true;
+	consolekeys[K_UPARROW] = true;
+	consolekeys[K_DOWNARROW] = true;
+	consolekeys[K_BACKSPACE] = true;
+	consolekeys[K_HOME] = true;
+	consolekeys[K_END] = true;
+	consolekeys[K_PGUP] = true;
+	consolekeys[K_PGDN] = true;
+	consolekeys[K_SHIFT] = true;
+	consolekeys[K_MWHEELUP] = true;
+	consolekeys[K_MWHEELDOWN] = true;
+	consolekeys['`'] = false;
+	consolekeys['~'] = false;
+
+	for (i=0 ; i<256 ; i++)
+		keyshift[i] = i;
+	for (i='a' ; i<='z' ; i++)
+		keyshift[i] = i - 'a' + 'A';
+	keyshift['1'] = '!';
+	keyshift['2'] = '@';
+	keyshift['3'] = '#';
+	keyshift['4'] = '$';
+	keyshift['5'] = '%';
+	keyshift['6'] = '^';
+	keyshift['7'] = '&';
+	keyshift['8'] = '*';
+	keyshift['9'] = '(';
+	keyshift['0'] = ')';
+	keyshift['-'] = '_';
+	keyshift['='] = '+';
+	keyshift[','] = '<';
+	keyshift['.'] = '>';
+	keyshift['/'] = '?';
+	keyshift[';'] = ':';
+	keyshift['\''] = '"';
+	keyshift['['] = '{';
+	keyshift[']'] = '}';
+	keyshift['`'] = '~';
+	keyshift['\\'] = '|';
+
+	menubound[K_ESCAPE] = true;
+	for (i=0 ; i<12 ; i++)
+		menubound[K_F1+i] = true;
+
+//
+// register our functions
+//
+	Cmd_AddCommand ("bind",Key_Bind_f);
+	Cmd_AddCommand ("unbind",Key_Unbind_f);
+	Cmd_AddCommand ("unbindall",Key_Unbindall_f);
+
+
+}
+
+/*
+===================
+Key_Event
+
+Called by the system between frames for both key up and key down events
+Should NOT be called during an interrupt!
+===================
+*/
+void Key_Event (int key, qboolean down)
+{
+	char	*kb;
+	char	cmd[1024];
+
+//	Con_Printf ("%i : %i\n", key, down); //@@@
+
+	keydown[key] = down;
+
+	if (!down)
+		key_repeats[key] = 0;
+
+	key_lastpress = key;
+	key_count++;
+	if (key_count <= 0)
+	{
+		return;		// just catching keys for Con_NotifyBox
+	}
+
+// update auto-repeat status
+	if (down)
+	{
+		key_repeats[key]++;
+		if (key != K_BACKSPACE 
+			&& key != K_PAUSE 
+			&& key != K_PGUP 
+			&& key != K_PGDN
+			&& key_repeats[key] > 1)
+			return;	// ignore most autorepeats
+			
+		if (key >= 200 && !keybindings[key])
+			Con_Printf ("%s is unbound, hit F4 to set.\n", Key_KeynumToString (key) );
+	}
+
+	if (key == K_SHIFT)
+		shift_down = down;
+
+//
+// handle escape specialy, so the user can never unbind it
+//
+	if (key == K_ESCAPE)
+	{
+		if (!down)
+			return;
+		switch (key_dest)
+		{
+		case key_message:
+			Key_Message (key);
+			break;
+		case key_menu:
+			M_Keydown (key);
+			break;
+		case key_game:
+		case key_console:
+			M_ToggleMenu_f ();
+			break;
+		default:
+			Sys_Error ("Bad key_dest");
+		}
+		return;
+	}
+
+//
+// key up events only generate commands if the game key binding is
+// a button command (leading + sign).  These will occur even in console mode,
+// to keep the character from continuing an action started before a console
+// switch.  Button commands include the kenum as a parameter, so multiple
+// downs can be matched with ups
+//
+	if (!down)
+	{
+		kb = keybindings[key];
+		if (kb && kb[0] == '+')
+		{
+			sprintf (cmd, "-%s %i\n", kb+1, key);
+			Cbuf_AddText (cmd);
+		}
+		if (keyshift[key] != key)
+		{
+			kb = keybindings[keyshift[key]];
+			if (kb && kb[0] == '+')
+			{
+				sprintf (cmd, "-%s %i\n", kb+1, key);
+				Cbuf_AddText (cmd);
+			}
+		}
+		return;
+	}
+
+//
+// during demo playback, most keys bring up the main menu
+//
+	if (cls.demoplayback && down && consolekeys[key] && key_dest == key_game)
+	{
+		M_ToggleMenu_f ();
+		return;
+	}
+
+//
+// if not a consolekey, send to the interpreter no matter what mode is
+//
+	if ( (key_dest == key_menu && menubound[key])
+	|| (key_dest == key_console && !consolekeys[key])
+	|| (key_dest == key_game && ( cls.state == ca_active || !consolekeys[key] ) ) )
+	{
+		kb = keybindings[key];
+		if (kb)
+		{
+			if (kb[0] == '+')
+			{	// button commands add keynum as a parm
+				sprintf (cmd, "%s %i\n", kb, key);
+				Cbuf_AddText (cmd);
+			}
+			else
+			{
+				Cbuf_AddText (kb);
+				Cbuf_AddText ("\n");
+			}
+		}
+		return;
+	}
+
+	if (!down)
+		return;		// other systems only care about key down events
+
+	if (shift_down)
+		key = keyshift[key];
+
+	switch (key_dest)
+	{
+	case key_message:
+		Key_Message (key);
+		break;
+	case key_menu:
+		M_Keydown (key);
+		break;
+
+	case key_game:
+	case key_console:
+		Key_Console (key);
+		break;
+	default:
+		Sys_Error ("Bad key_dest");
+	}
+}
+
+/*
+===================
+Key_ClearStates
+===================
+*/
+void Key_ClearStates (void)
+{
+	int		i;
+
+	for (i=0 ; i<256 ; i++)
+	{
+		keydown[i] = false;
+		key_repeats[i] = false;
+	}
+}
+
--- /dev/null
+++ b/QW/client/keys.h
@@ -1,0 +1,137 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+
+//
+// these are the key numbers that should be passed to Key_Event
+//
+#define	K_TAB			9
+#define	K_ENTER			13
+#define	K_ESCAPE		27
+#define	K_SPACE			32
+
+// normal keys should be passed as lowercased ascii
+
+#define	K_BACKSPACE		127
+#define	K_UPARROW		128
+#define	K_DOWNARROW		129
+#define	K_LEFTARROW		130
+#define	K_RIGHTARROW	131
+
+#define	K_ALT			132
+#define	K_CTRL			133
+#define	K_SHIFT			134
+#define	K_F1			135
+#define	K_F2			136
+#define	K_F3			137
+#define	K_F4			138
+#define	K_F5			139
+#define	K_F6			140
+#define	K_F7			141
+#define	K_F8			142
+#define	K_F9			143
+#define	K_F10			144
+#define	K_F11			145
+#define	K_F12			146
+#define	K_INS			147
+#define	K_DEL			148
+#define	K_PGDN			149
+#define	K_PGUP			150
+#define	K_HOME			151
+#define	K_END			152
+
+#define K_PAUSE			255
+
+//
+// mouse buttons generate virtual keys
+//
+#define	K_MOUSE1		200
+#define	K_MOUSE2		201
+#define	K_MOUSE3		202
+
+//
+// joystick buttons
+//
+#define	K_JOY1			203
+#define	K_JOY2			204
+#define	K_JOY3			205
+#define	K_JOY4			206
+
+//
+// aux keys are for multi-buttoned joysticks to generate so they can use
+// the normal binding process
+//
+#define	K_AUX1			207
+#define	K_AUX2			208
+#define	K_AUX3			209
+#define	K_AUX4			210
+#define	K_AUX5			211
+#define	K_AUX6			212
+#define	K_AUX7			213
+#define	K_AUX8			214
+#define	K_AUX9			215
+#define	K_AUX10			216
+#define	K_AUX11			217
+#define	K_AUX12			218
+#define	K_AUX13			219
+#define	K_AUX14			220
+#define	K_AUX15			221
+#define	K_AUX16			222
+#define	K_AUX17			223
+#define	K_AUX18			224
+#define	K_AUX19			225
+#define	K_AUX20			226
+#define	K_AUX21			227
+#define	K_AUX22			228
+#define	K_AUX23			229
+#define	K_AUX24			230
+#define	K_AUX25			231
+#define	K_AUX26			232
+#define	K_AUX27			233
+#define	K_AUX28			234
+#define	K_AUX29			235
+#define	K_AUX30			236
+#define	K_AUX31			237
+#define	K_AUX32			238
+
+// JACK: Intellimouse(c) Mouse Wheel Support
+
+#define K_MWHEELUP		239
+#define K_MWHEELDOWN	240
+
+
+
+typedef enum {key_game, key_console, key_message, key_menu} keydest_t;
+
+extern keydest_t	key_dest;
+extern char *keybindings[256];
+extern	int		key_repeats[256];
+extern	int		key_count;			// incremented every key event
+extern	int		key_lastpress;
+
+extern char chat_buffer[];
+extern	int chat_bufferlen;
+extern	qboolean	chat_team;
+
+void Key_Event (int key, qboolean down);
+void Key_Init (void);
+void Key_WriteBindings (FILE *f);
+void Key_SetBinding (int keynum, char *binding);
+void Key_ClearStates (void);
+
--- /dev/null
+++ b/QW/client/makefile.svgalib
@@ -1,0 +1,109 @@
+OBJS= \
+	cl_demo.o \
+	cl_ents.o \
+	cl_input.o \
+	cl_main.o \
+	cl_parse.o \
+	cl_pred.o \
+	cl_tent.o \
+	cl_cam.o \
+	cmd.o \
+	common.o \
+	console.o \
+	crc.o \
+	cvar.o \
+	d_edge.o \
+	d_fill.o \
+	d_init.o \
+	d_modech.o \
+	d_part.o \
+	d_polyse.o \
+	d_scan.o \
+	d_sky.o \
+	d_sprite.o \
+	d_surf.o \
+	d_vars.o \
+	d_zpoint.o \
+	draw.o \
+	keys.o \
+	mathlib.o \
+	md4.o \
+	menu.o \
+	model.o \
+	net_chan.o \
+	net_udp.o \
+	nonintel.o \
+	pmove.o \
+	pmovetst.o \
+	r_aclip.o \
+	r_alias.o \
+	r_bsp.o \
+	r_draw.o \
+	r_edge.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_vars.o \
+	sbar.o \
+	screen.o \
+	skin.o \
+	snd_dma.o \
+	snd_mem.o \
+	snd_mix.o \
+	view.o \
+	wad.o \
+	zone.o \
+	cd_linux.o \
+	sys_linux.o \
+	vid_svgalib.o \
+	snd_linux.o
+
+ASMOBJS= \
+	d_copy.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_aclipa.o \
+	r_aliasa.o \
+	r_drawa.o \
+	r_edgea.o \
+	r_varsa.o \
+	snd_mixa.o \
+	surf16.o \
+	surf8.o \
+	sys_dosa.o
+
+#CFLAGS=-O3 -Wall -fomit-frame-pointer -fno-strength-reduce -funroll-loops
+#CFLAGS=-mpentium -O3 -Wall -fomit-frame-pointer -fno-strength-reduce
+CFLAGS=-V2.7.2.1 -bi486-linux/ -O6 -Wall -fomit-frame-pointer -fno-strength-reduce
+#CFLAGS=-V2.7.2.1 -bi486-linux/ -O2 -g -Wall
+
+LDFLAGS = 
+
+LIBS = -lm -lvga
+TARGET = qwcl
+
+%.o : %.s
+	$(CC) $(CFLAGS) -DELF -x assembler-with-cpp -c $<
+
+#$(TARGET) : $(OBJS)
+#	$(CC) $(LDFLAGS) -o $(TARGET) $(OBJS) $(LIBS)
+
+$(TARGET) : $(ASMOBJS) $(OBJS) 
+	$(CC) $(LDFLAGS) -o $(TARGET) $(ASMOBJS) $(OBJS) $(LIBS)
+
+clean:
+	-rm $(OBJS)
+	
+clobber: clean
+	-rm $(TARGET)
--- /dev/null
+++ b/QW/client/math.asm
@@ -1,0 +1,495 @@
+ .386P
+ .model FLAT
+ externdef _d_zistepu:dword
+ externdef _d_pzbuffer:dword
+ externdef _d_zistepv:dword
+ externdef _d_zrowbytes:dword
+ externdef _d_ziorigin:dword
+ externdef _r_turb_s:dword
+ externdef _r_turb_t:dword
+ externdef _r_turb_pdest:dword
+ externdef _r_turb_spancount:dword
+ externdef _r_turb_turb:dword
+ externdef _r_turb_pbase:dword
+ externdef _r_turb_sstep:dword
+ externdef _r_turb_tstep:dword
+ externdef _r_bmodelactive:dword
+ externdef _d_sdivzstepu:dword
+ externdef _d_tdivzstepu:dword
+ externdef _d_sdivzstepv:dword
+ externdef _d_tdivzstepv:dword
+ externdef _d_sdivzorigin:dword
+ externdef _d_tdivzorigin:dword
+ externdef _sadjust:dword
+ externdef _tadjust:dword
+ externdef _bbextents:dword
+ externdef _bbextentt:dword
+ externdef _cacheblock:dword
+ externdef _d_viewbuffer:dword
+ externdef _cachewidth:dword
+ externdef _d_pzbuffer:dword
+ externdef _d_zrowbytes:dword
+ externdef _d_zwidth:dword
+ externdef _d_scantable:dword
+ externdef _r_lightptr:dword
+ externdef _r_numvblocks:dword
+ externdef _prowdestbase:dword
+ externdef _pbasesource:dword
+ externdef _r_lightwidth:dword
+ externdef _lightright:dword
+ externdef _lightrightstep:dword
+ externdef _lightdeltastep:dword
+ externdef _lightdelta:dword
+ externdef _lightright:dword
+ externdef _lightdelta:dword
+ externdef _sourcetstep:dword
+ externdef _surfrowbytes:dword
+ externdef _lightrightstep:dword
+ externdef _lightdeltastep:dword
+ externdef _r_sourcemax:dword
+ externdef _r_stepback:dword
+ externdef _colormap:dword
+ externdef _blocksize:dword
+ externdef _sourcesstep:dword
+ externdef _lightleft:dword
+ externdef _blockdivshift:dword
+ externdef _blockdivmask:dword
+ externdef _lightleftstep:dword
+ externdef _r_origin:dword
+ externdef _r_ppn:dword
+ externdef _r_pup:dword
+ externdef _r_pright:dword
+ externdef _ycenter:dword
+ externdef _xcenter:dword
+ externdef _d_vrectbottom_particle:dword
+ externdef _d_vrectright_particle:dword
+ externdef _d_vrecty:dword
+ externdef _d_vrectx:dword
+ externdef _d_pix_shift:dword
+ externdef _d_pix_min:dword
+ externdef _d_pix_max:dword
+ externdef _d_y_aspect_shift:dword
+ externdef _screenwidth:dword
+ externdef _vright:dword
+ externdef _vup:dword
+ externdef _vpn:dword
+ externdef _BOPS_Error:dword
+ externdef _snd_scaletable:dword
+ externdef _paintbuffer:dword
+ externdef _snd_linear_count:dword
+ externdef _snd_p:dword
+ externdef _snd_vol:dword
+ externdef _snd_out:dword
+ externdef _r_leftclipped:dword
+ externdef _r_leftenter:dword
+ externdef _r_rightclipped:dword
+ externdef _r_rightenter:dword
+ externdef _modelorg:dword
+ externdef _xscale:dword
+ externdef _r_refdef:dword
+ externdef _yscale:dword
+ externdef _r_leftexit:dword
+ externdef _r_rightexit:dword
+ externdef _r_lastvertvalid:dword
+ externdef _cacheoffset:dword
+ externdef _newedges:dword
+ externdef _removeedges:dword
+ externdef _r_pedge:dword
+ externdef _r_framecount:dword
+ externdef _r_u1:dword
+ externdef _r_emitted:dword
+ externdef _edge_p:dword
+ externdef _surface_p:dword
+ externdef _surfaces:dword
+ externdef _r_lzi1:dword
+ externdef _r_v1:dword
+ externdef _r_ceilv1:dword
+ externdef _r_nearzi:dword
+ externdef _r_nearzionly:dword
+ externdef _edge_aftertail:dword
+ externdef _edge_tail:dword
+ externdef _current_iv:dword
+ externdef _edge_head_u_shift20:dword
+ externdef _span_p:dword
+ externdef _edge_head:dword
+ externdef _fv:dword
+ externdef _edge_tail_u_shift20:dword
+ externdef _r_apverts:dword
+ externdef _r_anumverts:dword
+ externdef _aliastransform:dword
+ externdef _r_avertexnormals:dword
+ externdef _r_plightvec:dword
+ externdef _r_ambientlight:dword
+ externdef _r_shadelight:dword
+ externdef _aliasxcenter:dword
+ externdef _aliasycenter:dword
+ externdef _a_sstepxfrac:dword
+ externdef _r_affinetridesc:dword
+ externdef _acolormap:dword
+ externdef _d_pcolormap:dword
+ externdef _r_affinetridesc:dword
+ externdef _d_sfrac:dword
+ externdef _d_ptex:dword
+ externdef _d_pedgespanpackage:dword
+ externdef _d_tfrac:dword
+ externdef _d_light:dword
+ externdef _d_zi:dword
+ externdef _d_pdest:dword
+ externdef _d_pz:dword
+ externdef _d_aspancount:dword
+ externdef _erroradjustup:dword
+ externdef _errorterm:dword
+ externdef _d_xdenom:dword
+ externdef _r_p0:dword
+ externdef _r_p1:dword
+ externdef _r_p2:dword
+ externdef _a_tstepxfrac:dword
+ externdef _r_sstepx:dword
+ externdef _r_tstepx:dword
+ externdef _a_ststepxwhole:dword
+ externdef _zspantable:dword
+ externdef _skintable:dword
+ externdef _r_zistepx:dword
+ externdef _erroradjustdown:dword
+ externdef _d_countextrastep:dword
+ externdef _ubasestep:dword
+ externdef _a_ststepxwhole:dword
+ externdef _a_tstepxfrac:dword
+ externdef _r_lstepx:dword
+ externdef _a_spans:dword
+ externdef _erroradjustdown:dword
+ externdef _d_pdestextrastep:dword
+ externdef _d_pzextrastep:dword
+ externdef _d_sfracextrastep:dword
+ externdef _d_ptexextrastep:dword
+ externdef _d_countextrastep:dword
+ externdef _d_tfracextrastep:dword
+ externdef _d_lightextrastep:dword
+ externdef _d_ziextrastep:dword
+ externdef _d_pdestbasestep:dword
+ externdef _d_pzbasestep:dword
+ externdef _d_sfracbasestep:dword
+ externdef _d_ptexbasestep:dword
+ externdef _ubasestep:dword
+ externdef _d_tfracbasestep:dword
+ externdef _d_lightbasestep:dword
+ externdef _d_zibasestep:dword
+ externdef _zspantable:dword
+ externdef _r_lstepy:dword
+ externdef _r_sstepy:dword
+ externdef _r_tstepy:dword
+ externdef _r_zistepy:dword
+ externdef _D_PolysetSetEdgeTable:dword
+ externdef _D_RasterizeAliasPolySmooth:dword
+ externdef float_point5:dword
+ externdef Float2ToThe31nd:dword
+ externdef izistep:dword
+ externdef izi:dword
+ externdef FloatMinus2ToThe31nd:dword
+ externdef float_1:dword
+ externdef float_particle_z_clip:dword
+ externdef float_minus_1:dword
+ externdef float_0:dword
+ externdef fp_16:dword
+ externdef fp_64k:dword
+ externdef fp_1m:dword
+ externdef fp_1m_minus_1:dword
+ externdef fp_8:dword
+ externdef entryvec_table:dword
+ externdef advancetable:dword
+ externdef sstep:dword
+ externdef tstep:dword
+ externdef pspantemp:dword
+ externdef counttemp:dword
+ externdef jumptemp:dword
+ externdef reciprocal_table:dword
+ externdef DP_Count:dword
+ externdef DP_u:dword
+ externdef DP_v:dword
+ externdef DP_32768:dword
+ externdef DP_Color:dword
+ externdef DP_Pix:dword
+ externdef DP_EntryTable:dword
+ externdef pbase:dword
+ externdef s:dword
+ externdef t:dword
+ externdef sfracf:dword
+ externdef tfracf:dword
+ externdef snext:dword
+ externdef tnext:dword
+ externdef spancountminus1:dword
+ externdef zi16stepu:dword
+ externdef sdivz16stepu:dword
+ externdef tdivz16stepu:dword
+ externdef zi8stepu:dword
+ externdef sdivz8stepu:dword
+ externdef tdivz8stepu:dword
+ externdef reciprocal_table_16:dword
+ externdef entryvec_table_16:dword
+ externdef ceil_cw:dword
+ externdef single_cw:dword
+ externdef fp_64kx64k:dword
+ externdef pz:dword
+ externdef spr8entryvec_table:dword
+_DATA SEGMENT
+ align 4
+Ljmptab dd Lcase0, Lcase1, Lcase2, Lcase3
+ dd Lcase4, Lcase5, Lcase6, Lcase7
+_DATA ENDS
+_TEXT SEGMENT
+ public _Invert24To16
+_Invert24To16:
+ mov ecx,ds:dword ptr[4+esp]
+ mov edx,0100h
+ cmp ecx,edx
+ jle LOutOfRange
+ sub eax,eax
+ div ecx
+ ret
+LOutOfRange:
+ mov eax,0FFFFFFFFh
+ ret
+ align 2
+ public _TransformVector
+_TransformVector:
+ mov eax,ds:dword ptr[4+esp]
+ mov edx,ds:dword ptr[8+esp]
+ fld ds:dword ptr[eax]
+ fmul ds:dword ptr[_vright]
+ fld ds:dword ptr[eax]
+ fmul ds:dword ptr[_vup]
+ fld ds:dword ptr[eax]
+ fmul ds:dword ptr[_vpn]
+ fld ds:dword ptr[4+eax]
+ fmul ds:dword ptr[_vright+4]
+ fld ds:dword ptr[4+eax]
+ fmul ds:dword ptr[_vup+4]
+ fld ds:dword ptr[4+eax]
+ fmul ds:dword ptr[_vpn+4]
+ fxch st(2)
+ faddp st(5),st(0)
+ faddp st(3),st(0)
+ faddp st(1),st(0)
+ fld ds:dword ptr[8+eax]
+ fmul ds:dword ptr[_vright+8]
+ fld ds:dword ptr[8+eax]
+ fmul ds:dword ptr[_vup+8]
+ fld ds:dword ptr[8+eax]
+ fmul ds:dword ptr[_vpn+8]
+ fxch st(2)
+ faddp st(5),st(0)
+ faddp st(3),st(0)
+ faddp st(1),st(0)
+ fstp ds:dword ptr[8+edx]
+ fstp ds:dword ptr[4+edx]
+ fstp ds:dword ptr[edx]
+ ret
+ align 2
+ public _BoxOnPlaneSide
+_BoxOnPlaneSide:
+ push ebx
+ mov edx,ds:dword ptr[4+12+esp]
+ mov ecx,ds:dword ptr[4+4+esp]
+ xor eax,eax
+ mov ebx,ds:dword ptr[4+8+esp]
+ mov al,ds:byte ptr[17+edx]
+ cmp al,8
+ jge Lerror
+ fld ds:dword ptr[0+edx]
+ fld st(0)
+ jmp dword ptr[Ljmptab+eax*4]
+Lcase0:
+ fmul ds:dword ptr[ebx]
+ fld ds:dword ptr[0+4+edx]
+ fxch st(2)
+ fmul ds:dword ptr[ecx]
+ fxch st(2)
+ fld st(0)
+ fmul ds:dword ptr[4+ebx]
+ fld ds:dword ptr[0+8+edx]
+ fxch st(2)
+ fmul ds:dword ptr[4+ecx]
+ fxch st(2)
+ fld st(0)
+ fmul ds:dword ptr[8+ebx]
+ fxch st(5)
+ faddp st(3),st(0)
+ fmul ds:dword ptr[8+ecx]
+ fxch st(1)
+ faddp st(3),st(0)
+ fxch st(3)
+ faddp st(2),st(0)
+ jmp LSetSides
+Lcase1:
+ fmul ds:dword ptr[ecx]
+ fld ds:dword ptr[0+4+edx]
+ fxch st(2)
+ fmul ds:dword ptr[ebx]
+ fxch st(2)
+ fld st(0)
+ fmul ds:dword ptr[4+ebx]
+ fld ds:dword ptr[0+8+edx]
+ fxch st(2)
+ fmul ds:dword ptr[4+ecx]
+ fxch st(2)
+ fld st(0)
+ fmul ds:dword ptr[8+ebx]
+ fxch st(5)
+ faddp st(3),st(0)
+ fmul ds:dword ptr[8+ecx]
+ fxch st(1)
+ faddp st(3),st(0)
+ fxch st(3)
+ faddp st(2),st(0)
+ jmp LSetSides
+Lcase2:
+ fmul ds:dword ptr[ebx]
+ fld ds:dword ptr[0+4+edx]
+ fxch st(2)
+ fmul ds:dword ptr[ecx]
+ fxch st(2)
+ fld st(0)
+ fmul ds:dword ptr[4+ecx]
+ fld ds:dword ptr[0+8+edx]
+ fxch st(2)
+ fmul ds:dword ptr[4+ebx]
+ fxch st(2)
+ fld st(0)
+ fmul ds:dword ptr[8+ebx]
+ fxch st(5)
+ faddp st(3),st(0)
+ fmul ds:dword ptr[8+ecx]
+ fxch st(1)
+ faddp st(3),st(0)
+ fxch st(3)
+ faddp st(2),st(0)
+ jmp LSetSides
+Lcase3:
+ fmul ds:dword ptr[ecx]
+ fld ds:dword ptr[0+4+edx]
+ fxch st(2)
+ fmul ds:dword ptr[ebx]
+ fxch st(2)
+ fld st(0)
+ fmul ds:dword ptr[4+ecx]
+ fld ds:dword ptr[0+8+edx]
+ fxch st(2)
+ fmul ds:dword ptr[4+ebx]
+ fxch st(2)
+ fld st(0)
+ fmul ds:dword ptr[8+ebx]
+ fxch st(5)
+ faddp st(3),st(0)
+ fmul ds:dword ptr[8+ecx]
+ fxch st(1)
+ faddp st(3),st(0)
+ fxch st(3)
+ faddp st(2),st(0)
+ jmp LSetSides
+Lcase4:
+ fmul ds:dword ptr[ebx]
+ fld ds:dword ptr[0+4+edx]
+ fxch st(2)
+ fmul ds:dword ptr[ecx]
+ fxch st(2)
+ fld st(0)
+ fmul ds:dword ptr[4+ebx]
+ fld ds:dword ptr[0+8+edx]
+ fxch st(2)
+ fmul ds:dword ptr[4+ecx]
+ fxch st(2)
+ fld st(0)
+ fmul ds:dword ptr[8+ecx]
+ fxch st(5)
+ faddp st(3),st(0)
+ fmul ds:dword ptr[8+ebx]
+ fxch st(1)
+ faddp st(3),st(0)
+ fxch st(3)
+ faddp st(2),st(0)
+ jmp LSetSides
+Lcase5:
+ fmul ds:dword ptr[ecx]
+ fld ds:dword ptr[0+4+edx]
+ fxch st(2)
+ fmul ds:dword ptr[ebx]
+ fxch st(2)
+ fld st(0)
+ fmul ds:dword ptr[4+ebx]
+ fld ds:dword ptr[0+8+edx]
+ fxch st(2)
+ fmul ds:dword ptr[4+ecx]
+ fxch st(2)
+ fld st(0)
+ fmul ds:dword ptr[8+ecx]
+ fxch st(5)
+ faddp st(3),st(0)
+ fmul ds:dword ptr[8+ebx]
+ fxch st(1)
+ faddp st(3),st(0)
+ fxch st(3)
+ faddp st(2),st(0)
+ jmp LSetSides
+Lcase6:
+ fmul ds:dword ptr[ebx]
+ fld ds:dword ptr[0+4+edx]
+ fxch st(2)
+ fmul ds:dword ptr[ecx]
+ fxch st(2)
+ fld st(0)
+ fmul ds:dword ptr[4+ecx]
+ fld ds:dword ptr[0+8+edx]
+ fxch st(2)
+ fmul ds:dword ptr[4+ebx]
+ fxch st(2)
+ fld st(0)
+ fmul ds:dword ptr[8+ecx]
+ fxch st(5)
+ faddp st(3),st(0)
+ fmul ds:dword ptr[8+ebx]
+ fxch st(1)
+ faddp st(3),st(0)
+ fxch st(3)
+ faddp st(2),st(0)
+ jmp LSetSides
+Lcase7:
+ fmul ds:dword ptr[ecx]
+ fld ds:dword ptr[0+4+edx]
+ fxch st(2)
+ fmul ds:dword ptr[ebx]
+ fxch st(2)
+ fld st(0)
+ fmul ds:dword ptr[4+ecx]
+ fld ds:dword ptr[0+8+edx]
+ fxch st(2)
+ fmul ds:dword ptr[4+ebx]
+ fxch st(2)
+ fld st(0)
+ fmul ds:dword ptr[8+ecx]
+ fxch st(5)
+ faddp st(3),st(0)
+ fmul ds:dword ptr[8+ebx]
+ fxch st(1)
+ faddp st(3),st(0)
+ fxch st(3)
+ faddp st(2),st(0)
+LSetSides:
+ faddp st(2),st(0)
+ fcomp ds:dword ptr[12+edx]
+ xor ecx,ecx
+ fnstsw ax
+ fcomp ds:dword ptr[12+edx]
+ and ah,1
+ xor ah,1
+ add cl,ah
+ fnstsw ax
+ and ah,1
+ add ah,ah
+ add cl,ah
+ pop ebx
+ mov eax,ecx
+ ret
+Lerror:
+ call near ptr _BOPS_Error
+_TEXT ENDS
+ END
--- /dev/null
+++ b/QW/client/math.s
@@ -1,0 +1,417 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+//
+// math.s
+// x86 assembly-language math routines.
+
+#include "asm_i386.h"
+#include "quakeasm.h"
+
+
+#if	id386
+
+	.data
+
+	.align	4
+Ljmptab:	.long	Lcase0, Lcase1, Lcase2, Lcase3
+			.long	Lcase4, Lcase5, Lcase6, Lcase7
+
+	.text
+
+// TODO: rounding needed?
+// stack parameter offset
+#define	val	4
+
+.globl C(Invert24To16)
+C(Invert24To16):
+
+	movl	val(%esp),%ecx
+	movl	$0x100,%edx		// 0x10000000000 as dividend
+	cmpl	%edx,%ecx
+	jle		LOutOfRange
+
+	subl	%eax,%eax
+	divl	%ecx
+
+	ret
+
+LOutOfRange:
+	movl	$0xFFFFFFFF,%eax
+	ret
+
+#define	in	4
+#define out	8
+
+	.align 2
+.globl C(TransformVector)
+C(TransformVector):
+	movl	in(%esp),%eax
+	movl	out(%esp),%edx
+
+	flds	(%eax)		// in[0]
+	fmuls	C(vright)		// in[0]*vright[0]
+	flds	(%eax)		// in[0] | in[0]*vright[0]
+	fmuls	C(vup)		// in[0]*vup[0] | in[0]*vright[0]
+	flds	(%eax)		// in[0] | in[0]*vup[0] | in[0]*vright[0]
+	fmuls	C(vpn)		// in[0]*vpn[0] | in[0]*vup[0] | in[0]*vright[0]
+
+	flds	4(%eax)		// in[1] | ...
+	fmuls	C(vright)+4	// in[1]*vright[1] | ...
+	flds	4(%eax)		// in[1] | in[1]*vright[1] | ...
+	fmuls	C(vup)+4		// in[1]*vup[1] | in[1]*vright[1] | ...
+	flds	4(%eax)		// in[1] | in[1]*vup[1] | in[1]*vright[1] | ...
+	fmuls	C(vpn)+4		// in[1]*vpn[1] | in[1]*vup[1] | in[1]*vright[1] | ...
+	fxch	%st(2)		// in[1]*vright[1] | in[1]*vup[1] | in[1]*vpn[1] | ...
+
+	faddp	%st(0),%st(5)	// in[1]*vup[1] | in[1]*vpn[1] | ...
+	faddp	%st(0),%st(3)	// in[1]*vpn[1] | ...
+	faddp	%st(0),%st(1)	// vpn_accum | vup_accum | vright_accum
+
+	flds	8(%eax)		// in[2] | ...
+	fmuls	C(vright)+8	// in[2]*vright[2] | ...
+	flds	8(%eax)		// in[2] | in[2]*vright[2] | ...
+	fmuls	C(vup)+8		// in[2]*vup[2] | in[2]*vright[2] | ...
+	flds	8(%eax)		// in[2] | in[2]*vup[2] | in[2]*vright[2] | ...
+	fmuls	C(vpn)+8		// in[2]*vpn[2] | in[2]*vup[2] | in[2]*vright[2] | ...
+	fxch	%st(2)		// in[2]*vright[2] | in[2]*vup[2] | in[2]*vpn[2] | ...
+
+	faddp	%st(0),%st(5)	// in[2]*vup[2] | in[2]*vpn[2] | ...
+	faddp	%st(0),%st(3)	// in[2]*vpn[2] | ...
+	faddp	%st(0),%st(1)	// vpn_accum | vup_accum | vright_accum
+
+	fstps	8(%edx)		// out[2]
+	fstps	4(%edx)		// out[1]
+	fstps	(%edx)		// out[0]
+
+	ret
+
+
+#define EMINS	4+4
+#define EMAXS	4+8
+#define P		4+12
+
+	.align 2
+.globl C(BoxOnPlaneSide)
+C(BoxOnPlaneSide):
+	pushl	%ebx
+
+	movl	P(%esp),%edx
+	movl	EMINS(%esp),%ecx
+	xorl	%eax,%eax
+	movl	EMAXS(%esp),%ebx
+	movb	pl_signbits(%edx),%al
+	cmpb	$8,%al
+	jge		Lerror
+	flds	pl_normal(%edx)		// p->normal[0]
+	fld		%st(0)				// p->normal[0] | p->normal[0]
+	jmp		Ljmptab(,%eax,4)
+
+
+//dist1= p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
+//dist2= p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
+Lcase0:
+	fmuls	(%ebx)				// p->normal[0]*emaxs[0] | p->normal[0]
+	flds	pl_normal+4(%edx)	// p->normal[1] | p->normal[0]*emaxs[0] |
+								//  p->normal[0]
+	fxch	%st(2)				// p->normal[0] | p->normal[0]*emaxs[0] |
+								//  p->normal[1]
+	fmuls	(%ecx)				// p->normal[0]*emins[0] |
+								//  p->normal[0]*emaxs[0] | p->normal[1]
+	fxch	%st(2)				// p->normal[1] | p->normal[0]*emaxs[0] |
+								//  p->normal[0]*emins[0]
+	fld		%st(0)				// p->normal[1] | p->normal[1] |
+								//  p->normal[0]*emaxs[0] |
+								//  p->normal[0]*emins[0]
+	fmuls	4(%ebx)				// p->normal[1]*emaxs[1] | p->normal[1] |
+								//  p->normal[0]*emaxs[0] |
+								//  p->normal[0]*emins[0]
+	flds	pl_normal+8(%edx)	// p->normal[2] | p->normal[1]*emaxs[1] |
+								//  p->normal[1] | p->normal[0]*emaxs[0] |
+								//  p->normal[0]*emins[0]
+	fxch	%st(2)				// p->normal[1] | p->normal[1]*emaxs[1] |
+								//  p->normal[2] | p->normal[0]*emaxs[0] |
+								//  p->normal[0]*emins[0]
+	fmuls	4(%ecx)				// p->normal[1]*emins[1] |
+								//  p->normal[1]*emaxs[1] |
+								//  p->normal[2] | p->normal[0]*emaxs[0] |
+								//  p->normal[0]*emins[0]
+	fxch	%st(2)				// p->normal[2] | p->normal[1]*emaxs[1] |
+								//  p->normal[1]*emins[1] |
+								//  p->normal[0]*emaxs[0] |
+								//  p->normal[0]*emins[0]
+	fld		%st(0)				// p->normal[2] | p->normal[2] |
+								//  p->normal[1]*emaxs[1] |
+								//  p->normal[1]*emins[1] |
+								//  p->normal[0]*emaxs[0] |
+								//  p->normal[0]*emins[0]
+	fmuls	8(%ebx)				// p->normal[2]*emaxs[2] |
+								//  p->normal[2] |
+								//  p->normal[1]*emaxs[1] |
+								//  p->normal[1]*emins[1] |
+								//  p->normal[0]*emaxs[0] |
+								//  p->normal[0]*emins[0]
+	fxch	%st(5)				// p->normal[0]*emins[0] |
+								//  p->normal[2] |
+								//  p->normal[1]*emaxs[1] |
+								//  p->normal[1]*emins[1] |
+								//  p->normal[0]*emaxs[0] |
+								//  p->normal[2]*emaxs[2]
+	faddp	%st(0),%st(3)		//p->normal[2] |
+								// p->normal[1]*emaxs[1] |
+								// p->normal[1]*emins[1]+p->normal[0]*emins[0]|
+								// p->normal[0]*emaxs[0] |
+								// p->normal[2]*emaxs[2]
+	fmuls	8(%ecx)				//p->normal[2]*emins[2] |
+								// p->normal[1]*emaxs[1] |
+								// p->normal[1]*emins[1]+p->normal[0]*emins[0]|
+								// p->normal[0]*emaxs[0] |
+								// p->normal[2]*emaxs[2]
+	fxch	%st(1)				//p->normal[1]*emaxs[1] |
+								// p->normal[2]*emins[2] |
+								// p->normal[1]*emins[1]+p->normal[0]*emins[0]|
+								// p->normal[0]*emaxs[0] |
+								// p->normal[2]*emaxs[2]
+	faddp	%st(0),%st(3)		//p->normal[2]*emins[2] |
+								// p->normal[1]*emins[1]+p->normal[0]*emins[0]|
+								// p->normal[0]*emaxs[0]+p->normal[1]*emaxs[1]|
+								// p->normal[2]*emaxs[2]
+	fxch	%st(3)				//p->normal[2]*emaxs[2] +
+								// p->normal[1]*emins[1]+p->normal[0]*emins[0]|
+								// p->normal[0]*emaxs[0]+p->normal[1]*emaxs[1]|
+								// p->normal[2]*emins[2]
+	faddp	%st(0),%st(2)		//p->normal[1]*emins[1]+p->normal[0]*emins[0]|
+								// dist1 | p->normal[2]*emins[2]
+
+	jmp		LSetSides
+
+//dist1= p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
+//dist2= p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
+Lcase1:
+	fmuls	(%ecx)				// emins[0]
+	flds	pl_normal+4(%edx)
+	fxch	%st(2)
+	fmuls	(%ebx)				// emaxs[0]
+	fxch	%st(2)
+	fld		%st(0)
+	fmuls	4(%ebx)				// emaxs[1]
+	flds	pl_normal+8(%edx)
+	fxch	%st(2)
+	fmuls	4(%ecx)				// emins[1]
+	fxch	%st(2)
+	fld		%st(0)
+	fmuls	8(%ebx)				// emaxs[2]
+	fxch	%st(5)
+	faddp	%st(0),%st(3)
+	fmuls	8(%ecx)				// emins[2]
+	fxch	%st(1)
+	faddp	%st(0),%st(3)
+	fxch	%st(3)
+	faddp	%st(0),%st(2)
+
+	jmp		LSetSides
+
+//dist1= p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
+//dist2= p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
+Lcase2:
+	fmuls	(%ebx)				// emaxs[0]
+	flds	pl_normal+4(%edx)
+	fxch	%st(2)
+	fmuls	(%ecx)				// emins[0]
+	fxch	%st(2)
+	fld		%st(0)
+	fmuls	4(%ecx)				// emins[1]
+	flds	pl_normal+8(%edx)
+	fxch	%st(2)
+	fmuls	4(%ebx)				// emaxs[1]
+	fxch	%st(2)
+	fld		%st(0)
+	fmuls	8(%ebx)				// emaxs[2]
+	fxch	%st(5)
+	faddp	%st(0),%st(3)
+	fmuls	8(%ecx)				// emins[2]
+	fxch	%st(1)
+	faddp	%st(0),%st(3)
+	fxch	%st(3)
+	faddp	%st(0),%st(2)
+
+	jmp		LSetSides
+
+//dist1= p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
+//dist2= p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
+Lcase3:
+	fmuls	(%ecx)				// emins[0]
+	flds	pl_normal+4(%edx)
+	fxch	%st(2)
+	fmuls	(%ebx)				// emaxs[0]
+	fxch	%st(2)
+	fld		%st(0)
+	fmuls	4(%ecx)				// emins[1]
+	flds	pl_normal+8(%edx)
+	fxch	%st(2)
+	fmuls	4(%ebx)				// emaxs[1]
+	fxch	%st(2)
+	fld		%st(0)
+	fmuls	8(%ebx)				// emaxs[2]
+	fxch	%st(5)
+	faddp	%st(0),%st(3)
+	fmuls	8(%ecx)				// emins[2]
+	fxch	%st(1)
+	faddp	%st(0),%st(3)
+	fxch	%st(3)
+	faddp	%st(0),%st(2)
+
+	jmp		LSetSides
+
+//dist1= p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
+//dist2= p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
+Lcase4:
+	fmuls	(%ebx)				// emaxs[0]
+	flds	pl_normal+4(%edx)
+	fxch	%st(2)
+	fmuls	(%ecx)				// emins[0]
+	fxch	%st(2)
+	fld		%st(0)
+	fmuls	4(%ebx)				// emaxs[1]
+	flds	pl_normal+8(%edx)
+	fxch	%st(2)
+	fmuls	4(%ecx)				// emins[1]
+	fxch	%st(2)
+	fld		%st(0)
+	fmuls	8(%ecx)				// emins[2]
+	fxch	%st(5)
+	faddp	%st(0),%st(3)
+	fmuls	8(%ebx)				// emaxs[2]
+	fxch	%st(1)
+	faddp	%st(0),%st(3)
+	fxch	%st(3)
+	faddp	%st(0),%st(2)
+
+	jmp		LSetSides
+
+//dist1= p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
+//dist2= p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
+Lcase5:
+	fmuls	(%ecx)				// emins[0]
+	flds	pl_normal+4(%edx)
+	fxch	%st(2)
+	fmuls	(%ebx)				// emaxs[0]
+	fxch	%st(2)
+	fld		%st(0)
+	fmuls	4(%ebx)				// emaxs[1]
+	flds	pl_normal+8(%edx)
+	fxch	%st(2)
+	fmuls	4(%ecx)				// emins[1]
+	fxch	%st(2)
+	fld		%st(0)
+	fmuls	8(%ecx)				// emins[2]
+	fxch	%st(5)
+	faddp	%st(0),%st(3)
+	fmuls	8(%ebx)				// emaxs[2]
+	fxch	%st(1)
+	faddp	%st(0),%st(3)
+	fxch	%st(3)
+	faddp	%st(0),%st(2)
+
+	jmp		LSetSides
+
+//dist1= p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
+//dist2= p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
+Lcase6:
+	fmuls	(%ebx)				// emaxs[0]
+	flds	pl_normal+4(%edx)
+	fxch	%st(2)
+	fmuls	(%ecx)				// emins[0]
+	fxch	%st(2)
+	fld		%st(0)
+	fmuls	4(%ecx)				// emins[1]
+	flds	pl_normal+8(%edx)
+	fxch	%st(2)
+	fmuls	4(%ebx)				// emaxs[1]
+	fxch	%st(2)
+	fld		%st(0)
+	fmuls	8(%ecx)				// emins[2]
+	fxch	%st(5)
+	faddp	%st(0),%st(3)
+	fmuls	8(%ebx)				// emaxs[2]
+	fxch	%st(1)
+	faddp	%st(0),%st(3)
+	fxch	%st(3)
+	faddp	%st(0),%st(2)
+
+	jmp		LSetSides
+
+//dist1= p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
+//dist2= p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
+Lcase7:
+	fmuls	(%ecx)				// emins[0]
+	flds	pl_normal+4(%edx)
+	fxch	%st(2)
+	fmuls	(%ebx)				// emaxs[0]
+	fxch	%st(2)
+	fld		%st(0)
+	fmuls	4(%ecx)				// emins[1]
+	flds	pl_normal+8(%edx)
+	fxch	%st(2)
+	fmuls	4(%ebx)				// emaxs[1]
+	fxch	%st(2)
+	fld		%st(0)
+	fmuls	8(%ecx)				// emins[2]
+	fxch	%st(5)
+	faddp	%st(0),%st(3)
+	fmuls	8(%ebx)				// emaxs[2]
+	fxch	%st(1)
+	faddp	%st(0),%st(3)
+	fxch	%st(3)
+	faddp	%st(0),%st(2)
+
+LSetSides:
+
+//	sides = 0;
+//	if (dist1 >= p->dist)
+//		sides = 1;
+//	if (dist2 < p->dist)
+//		sides |= 2;
+
+	faddp	%st(0),%st(2)		// dist1 | dist2
+	fcomps	pl_dist(%edx)
+	xorl	%ecx,%ecx
+	fnstsw	%ax
+	fcomps	pl_dist(%edx)
+	andb	$1,%ah
+	xorb	$1,%ah
+	addb	%ah,%cl
+
+	fnstsw	%ax
+	andb	$1,%ah
+	addb	%ah,%ah
+	addb	%ah,%cl
+
+//	return sides;
+
+	popl	%ebx
+	movl	%ecx,%eax	// return status
+
+	ret
+
+
+Lerror:
+	call	C(BOPS_Error)
+
+#endif	// id386
--- /dev/null
+++ b/QW/client/mathlib.c
@@ -1,0 +1,583 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// mathlib.c -- math primitives
+
+#include <math.h>
+#include "quakedef.h"
+
+void Sys_Error (char *error, ...);
+
+vec3_t vec3_origin = {0,0,0};
+int nanmask = 255<<23;
+
+/*-----------------------------------------------------------------*/
+
+#define DEG2RAD( a ) ( a * M_PI ) / 180.0F
+
+void ProjectPointOnPlane( vec3_t dst, const vec3_t p, const vec3_t normal )
+{
+	float d;
+	vec3_t n;
+	float inv_denom;
+
+	inv_denom = 1.0F / DotProduct( normal, normal );
+
+	d = DotProduct( normal, p ) * inv_denom;
+
+	n[0] = normal[0] * inv_denom;
+	n[1] = normal[1] * inv_denom;
+	n[2] = normal[2] * inv_denom;
+
+	dst[0] = p[0] - d * n[0];
+	dst[1] = p[1] - d * n[1];
+	dst[2] = p[2] - d * n[2];
+}
+
+/*
+** assumes "src" is normalized
+*/
+void PerpendicularVector( vec3_t dst, const vec3_t src )
+{
+	int	pos;
+	int i;
+	float minelem = 1.0F;
+	vec3_t tempvec;
+
+	/*
+	** find the smallest magnitude axially aligned vector
+	*/
+	for ( pos = 0, i = 0; i < 3; i++ )
+	{
+		if ( fabs( src[i] ) < minelem )
+		{
+			pos = i;
+			minelem = fabs( src[i] );
+		}
+	}
+	tempvec[0] = tempvec[1] = tempvec[2] = 0.0F;
+	tempvec[pos] = 1.0F;
+
+	/*
+	** project the point onto the plane defined by src
+	*/
+	ProjectPointOnPlane( dst, tempvec, src );
+
+	/*
+	** normalize the result
+	*/
+	VectorNormalize( dst );
+}
+
+#ifdef _WIN32
+#pragma optimize( "", off )
+#endif
+
+
+void RotatePointAroundVector( vec3_t dst, const vec3_t dir, const vec3_t point, float degrees )
+{
+	float	m[3][3];
+	float	im[3][3];
+	float	zrot[3][3];
+	float	tmpmat[3][3];
+	float	rot[3][3];
+	int	i;
+	vec3_t vr, vup, vf;
+
+	vf[0] = dir[0];
+	vf[1] = dir[1];
+	vf[2] = dir[2];
+
+	PerpendicularVector( vr, dir );
+	CrossProduct( vr, vf, vup );
+
+	m[0][0] = vr[0];
+	m[1][0] = vr[1];
+	m[2][0] = vr[2];
+
+	m[0][1] = vup[0];
+	m[1][1] = vup[1];
+	m[2][1] = vup[2];
+
+	m[0][2] = vf[0];
+	m[1][2] = vf[1];
+	m[2][2] = vf[2];
+
+	memcpy( im, m, sizeof( im ) );
+
+	im[0][1] = m[1][0];
+	im[0][2] = m[2][0];
+	im[1][0] = m[0][1];
+	im[1][2] = m[2][1];
+	im[2][0] = m[0][2];
+	im[2][1] = m[1][2];
+
+	memset( zrot, 0, sizeof( zrot ) );
+	zrot[0][0] = zrot[1][1] = zrot[2][2] = 1.0F;
+
+	zrot[0][0] = cos( DEG2RAD( degrees ) );
+	zrot[0][1] = sin( DEG2RAD( degrees ) );
+	zrot[1][0] = -sin( DEG2RAD( degrees ) );
+	zrot[1][1] = cos( DEG2RAD( degrees ) );
+
+	R_ConcatRotations( m, zrot, tmpmat );
+	R_ConcatRotations( tmpmat, im, rot );
+
+	for ( i = 0; i < 3; i++ )
+	{
+		dst[i] = rot[i][0] * point[0] + rot[i][1] * point[1] + rot[i][2] * point[2];
+	}
+}
+
+#ifdef _WIN32
+#pragma optimize( "", on )
+#endif
+
+/*-----------------------------------------------------------------*/
+
+float	anglemod(float a)
+{
+#if 0
+	if (a >= 0)
+		a -= 360*(int)(a/360);
+	else
+		a += 360*( 1 + (int)(-a/360) );
+#endif
+	a = (360.0/65536) * ((int)(a*(65536/360.0)) & 65535);
+	return a;
+}
+
+/*
+==================
+BOPS_Error
+
+Split out like this for ASM to call.
+==================
+*/
+void BOPS_Error (void)
+{
+	Sys_Error ("BoxOnPlaneSide:  Bad signbits");
+}
+
+#if !id386
+
+/*
+==================
+BoxOnPlaneSide
+
+Returns 1, 2, or 1 + 2
+==================
+*/
+int BoxOnPlaneSide (vec3_t emins, vec3_t emaxs, mplane_t *p)
+{
+	float	dist1, dist2;
+	int		sides;
+
+#if 0	// this is done by the BOX_ON_PLANE_SIDE macro before calling this
+		// function
+// fast axial cases
+	if (p->type < 3)
+	{
+		if (p->dist <= emins[p->type])
+			return 1;
+		if (p->dist >= emaxs[p->type])
+			return 2;
+		return 3;
+	}
+#endif
+	
+// general case
+	switch (p->signbits)
+	{
+	case 0:
+dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
+dist2 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
+		break;
+	case 1:
+dist1 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
+dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
+		break;
+	case 2:
+dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
+dist2 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
+		break;
+	case 3:
+dist1 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
+dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
+		break;
+	case 4:
+dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
+dist2 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
+		break;
+	case 5:
+dist1 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
+dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
+		break;
+	case 6:
+dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
+dist2 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
+		break;
+	case 7:
+dist1 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
+dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
+		break;
+	default:
+		dist1 = dist2 = 0;		// shut up compiler
+		BOPS_Error ();
+		break;
+	}
+
+#if 0
+	int		i;
+	vec3_t	corners[2];
+
+	for (i=0 ; i<3 ; i++)
+	{
+		if (plane->normal[i] < 0)
+		{
+			corners[0][i] = emins[i];
+			corners[1][i] = emaxs[i];
+		}
+		else
+		{
+			corners[1][i] = emins[i];
+			corners[0][i] = emaxs[i];
+		}
+	}
+	dist = DotProduct (plane->normal, corners[0]) - plane->dist;
+	dist2 = DotProduct (plane->normal, corners[1]) - plane->dist;
+	sides = 0;
+	if (dist1 >= 0)
+		sides = 1;
+	if (dist2 < 0)
+		sides |= 2;
+
+#endif
+
+	sides = 0;
+	if (dist1 >= p->dist)
+		sides = 1;
+	if (dist2 < p->dist)
+		sides |= 2;
+
+#ifdef PARANOID
+if (sides == 0)
+	Sys_Error ("BoxOnPlaneSide: sides==0");
+#endif
+
+	return sides;
+}
+
+#endif
+
+
+void AngleVectors (vec3_t angles, vec3_t forward, vec3_t right, vec3_t up)
+{
+	float		angle;
+	float		sr, sp, sy, cr, cp, cy;
+	
+	angle = angles[YAW] * (M_PI*2 / 360);
+	sy = sin(angle);
+	cy = cos(angle);
+	angle = angles[PITCH] * (M_PI*2 / 360);
+	sp = sin(angle);
+	cp = cos(angle);
+	angle = angles[ROLL] * (M_PI*2 / 360);
+	sr = sin(angle);
+	cr = cos(angle);
+
+	forward[0] = cp*cy;
+	forward[1] = cp*sy;
+	forward[2] = -sp;
+	right[0] = (-1*sr*sp*cy+-1*cr*-sy);
+	right[1] = (-1*sr*sp*sy+-1*cr*cy);
+	right[2] = -1*sr*cp;
+	up[0] = (cr*sp*cy+-sr*-sy);
+	up[1] = (cr*sp*sy+-sr*cy);
+	up[2] = cr*cp;
+}
+
+int VectorCompare (vec3_t v1, vec3_t v2)
+{
+	int		i;
+	
+	for (i=0 ; i<3 ; i++)
+		if (v1[i] != v2[i])
+			return 0;
+			
+	return 1;
+}
+
+void VectorMA (vec3_t veca, float scale, vec3_t vecb, vec3_t vecc)
+{
+	vecc[0] = veca[0] + scale*vecb[0];
+	vecc[1] = veca[1] + scale*vecb[1];
+	vecc[2] = veca[2] + scale*vecb[2];
+}
+
+
+vec_t _DotProduct (vec3_t v1, vec3_t v2)
+{
+	return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2];
+}
+
+void _VectorSubtract (vec3_t veca, vec3_t vecb, vec3_t out)
+{
+	out[0] = veca[0]-vecb[0];
+	out[1] = veca[1]-vecb[1];
+	out[2] = veca[2]-vecb[2];
+}
+
+void _VectorAdd (vec3_t veca, vec3_t vecb, vec3_t out)
+{
+	out[0] = veca[0]+vecb[0];
+	out[1] = veca[1]+vecb[1];
+	out[2] = veca[2]+vecb[2];
+}
+
+void _VectorCopy (vec3_t in, vec3_t out)
+{
+	out[0] = in[0];
+	out[1] = in[1];
+	out[2] = in[2];
+}
+
+void CrossProduct (vec3_t v1, vec3_t v2, vec3_t cross)
+{
+	cross[0] = v1[1]*v2[2] - v1[2]*v2[1];
+	cross[1] = v1[2]*v2[0] - v1[0]*v2[2];
+	cross[2] = v1[0]*v2[1] - v1[1]*v2[0];
+}
+
+double sqrt(double x);
+
+vec_t Length(vec3_t v)
+{
+	int		i;
+	float	length;
+	
+	length = 0;
+	for (i=0 ; i< 3 ; i++)
+		length += v[i]*v[i];
+	length = sqrt (length);		// FIXME
+
+	return length;
+}
+
+float VectorNormalize (vec3_t v)
+{
+	float	length, ilength;
+
+	length = v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
+	length = sqrt (length);		// FIXME
+
+	if (length)
+	{
+		ilength = 1/length;
+		v[0] *= ilength;
+		v[1] *= ilength;
+		v[2] *= ilength;
+	}
+		
+	return length;
+
+}
+
+void VectorInverse (vec3_t v)
+{
+	v[0] = -v[0];
+	v[1] = -v[1];
+	v[2] = -v[2];
+}
+
+void VectorScale (vec3_t in, vec_t scale, vec3_t out)
+{
+	out[0] = in[0]*scale;
+	out[1] = in[1]*scale;
+	out[2] = in[2]*scale;
+}
+
+
+int Q_log2(int val)
+{
+	int answer=0;
+	while ((val>>=1) != 0)
+		answer++;
+	return answer;
+}
+
+
+/*
+================
+R_ConcatRotations
+================
+*/
+void R_ConcatRotations (float in1[3][3], float in2[3][3], float out[3][3])
+{
+	out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] +
+				in1[0][2] * in2[2][0];
+	out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] +
+				in1[0][2] * in2[2][1];
+	out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] +
+				in1[0][2] * in2[2][2];
+	out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] +
+				in1[1][2] * in2[2][0];
+	out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] +
+				in1[1][2] * in2[2][1];
+	out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] +
+				in1[1][2] * in2[2][2];
+	out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] +
+				in1[2][2] * in2[2][0];
+	out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] +
+				in1[2][2] * in2[2][1];
+	out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] +
+				in1[2][2] * in2[2][2];
+}
+
+
+/*
+================
+R_ConcatTransforms
+================
+*/
+void R_ConcatTransforms (float in1[3][4], float in2[3][4], float out[3][4])
+{
+	out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] +
+				in1[0][2] * in2[2][0];
+	out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] +
+				in1[0][2] * in2[2][1];
+	out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] +
+				in1[0][2] * in2[2][2];
+	out[0][3] = in1[0][0] * in2[0][3] + in1[0][1] * in2[1][3] +
+				in1[0][2] * in2[2][3] + in1[0][3];
+	out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] +
+				in1[1][2] * in2[2][0];
+	out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] +
+				in1[1][2] * in2[2][1];
+	out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] +
+				in1[1][2] * in2[2][2];
+	out[1][3] = in1[1][0] * in2[0][3] + in1[1][1] * in2[1][3] +
+				in1[1][2] * in2[2][3] + in1[1][3];
+	out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] +
+				in1[2][2] * in2[2][0];
+	out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] +
+				in1[2][2] * in2[2][1];
+	out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] +
+				in1[2][2] * in2[2][2];
+	out[2][3] = in1[2][0] * in2[0][3] + in1[2][1] * in2[1][3] +
+				in1[2][2] * in2[2][3] + in1[2][3];
+}
+
+
+/*
+===================
+FloorDivMod
+
+Returns mathematically correct (floor-based) quotient and remainder for
+numer and denom, both of which should contain no fractional part. The
+quotient must fit in 32 bits.
+====================
+*/
+
+void FloorDivMod (double numer, double denom, int *quotient,
+		int *rem)
+{
+	int		q, r;
+	double	x;
+
+#ifndef PARANOID
+	if (denom <= 0.0)
+		Sys_Error ("FloorDivMod: bad denominator %d\n", denom);
+
+//	if ((floor(numer) != numer) || (floor(denom) != denom))
+//		Sys_Error ("FloorDivMod: non-integer numer or denom %f %f\n",
+//				numer, denom);
+#endif
+
+	if (numer >= 0.0)
+	{
+
+		x = floor(numer / denom);
+		q = (int)x;
+		r = (int)floor(numer - (x * denom));
+	}
+	else
+	{
+	//
+	// perform operations with positive values, and fix mod to make floor-based
+	//
+		x = floor(-numer / denom);
+		q = -(int)x;
+		r = (int)floor(-numer - (x * denom));
+		if (r != 0)
+		{
+			q--;
+			r = (int)denom - r;
+		}
+	}
+
+	*quotient = q;
+	*rem = r;
+}
+
+
+/*
+===================
+GreatestCommonDivisor
+====================
+*/
+int GreatestCommonDivisor (int i1, int i2)
+{
+	if (i1 > i2)
+	{
+		if (i2 == 0)
+			return (i1);
+		return GreatestCommonDivisor (i2, i1 % i2);
+	}
+	else
+	{
+		if (i1 == 0)
+			return (i2);
+		return GreatestCommonDivisor (i1, i2 % i1);
+	}
+}
+
+
+#if !id386
+
+// TODO: move to nonintel.c
+
+/*
+===================
+Invert24To16
+
+Inverts an 8.24 value to a 16.16 value
+====================
+*/
+
+fixed16_t Invert24To16(fixed16_t val)
+{
+	if (val < 256)
+		return (0xFFFFFFFF);
+
+	return (fixed16_t)
+			(((double)0x10000 * (double)0x1000000 / (double)val) + 0.5);
+}
+
+#endif
--- /dev/null
+++ b/QW/client/mathlib.h
@@ -1,0 +1,91 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// mathlib.h
+
+typedef float vec_t;
+typedef vec_t vec3_t[3];
+typedef vec_t vec5_t[5];
+
+typedef	int	fixed4_t;
+typedef	int	fixed8_t;
+typedef	int	fixed16_t;
+
+#ifndef M_PI
+#define M_PI		3.14159265358979323846	// matches value in gcc v2 math.h
+#endif
+
+struct mplane_s;
+
+extern vec3_t vec3_origin;
+extern	int nanmask;
+
+#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 VectorSubtract(a,b,c) {c[0]=a[0]-b[0];c[1]=a[1]-b[1];c[2]=a[2]-b[2];}
+#define VectorAdd(a,b,c) {c[0]=a[0]+b[0];c[1]=a[1]+b[1];c[2]=a[2]+b[2];}
+#define VectorCopy(a,b) {b[0]=a[0];b[1]=a[1];b[2]=a[2];}
+
+void VectorMA (vec3_t veca, float scale, vec3_t vecb, vec3_t vecc);
+
+vec_t _DotProduct (vec3_t v1, 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);
+
+int VectorCompare (vec3_t v1, vec3_t v2);
+vec_t Length (vec3_t v);
+void CrossProduct (vec3_t v1, vec3_t v2, vec3_t cross);
+float VectorNormalize (vec3_t v);		// returns vector length
+void VectorInverse (vec3_t v);
+void VectorScale (vec3_t in, vec_t scale, vec3_t out);
+int Q_log2(int val);
+
+void R_ConcatRotations (float in1[3][3], float in2[3][3], float out[3][3]);
+void R_ConcatTransforms (float in1[3][4], float in2[3][4], float out[3][4]);
+
+void FloorDivMod (double numer, double denom, int *quotient,
+		int *rem);
+fixed16_t Invert24To16(fixed16_t val);
+fixed16_t Mul16_30(fixed16_t multiplier, fixed16_t multiplicand);
+int GreatestCommonDivisor (int i1, int i2);
+
+void AngleVectors (vec3_t angles, vec3_t forward, vec3_t right, vec3_t up);
+int BoxOnPlaneSide (vec3_t emins, vec3_t emaxs, struct mplane_s *plane);
+float	anglemod(float a);
+
+void RotatePointAroundVector( vec3_t dst, const vec3_t dir, const vec3_t point, float degrees );
+
+
+#define BOX_ON_PLANE_SIDE(emins, emaxs, p)	\
+	(((p)->type < 3)?						\
+	(										\
+		((p)->dist <= (emins)[(p)->type])?	\
+			1								\
+		:									\
+		(									\
+			((p)->dist >= (emaxs)[(p)->type])?\
+				2							\
+			:								\
+				3							\
+		)									\
+	)										\
+	:										\
+		BoxOnPlaneSide( (emins), (emaxs), (p)))
--- /dev/null
+++ b/QW/client/md4.c
@@ -1,0 +1,306 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+/* GLOBAL.H - RSAREF types and constants */
+
+#include <string.h>
+
+/* POINTER defines a generic pointer type */
+typedef unsigned char *POINTER;
+
+/* UINT2 defines a two byte word */
+typedef unsigned short int UINT2;
+
+/* UINT4 defines a four byte word */
+#ifdef __alpha__
+typedef unsigned int UINT4;
+#else
+typedef unsigned long int UINT4;
+#endif
+
+  
+/* MD4.H - header file for MD4C.C */
+
+/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. 
+
+All rights reserved.
+  
+License to copy and use this software is granted provided that it is identified as the �RSA Data Security, Inc. MD4 Message-Digest Algorithm� in all material mentioning or referencing this software or this function.
+License is also granted to make and use derivative works provided that such works are identified as �derived from the RSA Data Security, Inc. MD4 Message-Digest Algorithm� in all material mentioning or referencing the derived work.
+RSA Data Security, Inc. makes no representations concerning either the merchantability of this software or the suitability of this software for any particular purpose. It is provided �as is� without express or implied warranty of any kind.
+  
+These notices must be retained in any copies of any part of this documentation and/or software. */
+
+/* MD4 context. */
+typedef struct {
+	UINT4 state[4];				/* state (ABCD) */
+	UINT4 count[2];				/* number of bits, modulo 2^64 (lsb first) */
+	unsigned char buffer[64]; 			/* input buffer */
+} MD4_CTX;
+
+void MD4Init (MD4_CTX *);
+void MD4Update (MD4_CTX *, unsigned char *, unsigned int);
+void MD4Final (unsigned char [16], MD4_CTX *);
+  
+
+  
+/* MD4C.C - RSA Data Security, Inc., MD4 message-digest algorithm */
+/* Copyright (C) 1990-2, RSA Data Security, Inc. All rights reserved.
+  
+License to copy and use this software is granted provided that it is identified as the
+RSA Data Security, Inc. MD4 Message-Digest Algorithm
+ in all material mentioning or referencing this software or this function.
+License is also granted to make and use derivative works provided that such works are identified as 
+derived from the RSA Data Security, Inc. MD4 Message-Digest Algorithm
+in all material mentioning or referencing the derived work.
+RSA Data Security, Inc. makes no representations concerning either the merchantability of this software or the suitability of this software for any particular purpose. It is provided
+as is without express or implied warranty of any kind.
+  
+These notices must be retained in any copies of any part of this documentation and/or software. */
+
+/* Constants for MD4Transform routine.  */
+#define S11 3
+#define S12 7
+#define S13 11
+#define S14 19
+#define S21 3
+#define S22 5
+#define S23 9
+#define S24 13
+#define S31 3
+#define S32 9
+#define S33 11
+#define S34 15
+
+static void MD4Transform (UINT4 [4], unsigned char [64]);
+static void Encode (unsigned char *, UINT4 *, unsigned int);
+static void Decode (UINT4 *, unsigned char *, unsigned int);
+
+static unsigned char PADDING[64] = {
+0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+/* F, G and H are basic MD4 functions. */
+#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
+#define G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
+#define H(x, y, z) ((x) ^ (y) ^ (z))
+
+/* ROTATE_LEFT rotates x left n bits. */
+#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
+
+/* FF, GG and HH are transformations for rounds 1, 2 and 3 */
+/* Rotation is separate from addition to prevent recomputation */
+#define FF(a, b, c, d, x, s) {(a) += F ((b), (c), (d)) + (x); (a) = ROTATE_LEFT ((a), (s));}
+
+#define GG(a, b, c, d, x, s) {(a) += G ((b), (c), (d)) + (x) + (UINT4)0x5a827999; (a) = ROTATE_LEFT ((a), (s));}
+
+#define HH(a, b, c, d, x, s) {(a) += H ((b), (c), (d)) + (x) + (UINT4)0x6ed9eba1; (a) = ROTATE_LEFT ((a), (s));}
+
+
+/* MD4 initialization. Begins an MD4 operation, writing a new context. */
+void MD4Init (MD4_CTX *context)
+{
+	context->count[0] = context->count[1] = 0;
+
+/* Load magic initialization constants.*/
+context->state[0] = 0x67452301;
+context->state[1] = 0xefcdab89;
+context->state[2] = 0x98badcfe;
+context->state[3] = 0x10325476;
+}
+
+/* MD4 block update operation. Continues an MD4 message-digest operation, processing another message block, and updating the context. */
+void MD4Update (MD4_CTX *context, unsigned char *input, unsigned int inputLen)
+{
+	unsigned int i, index, partLen;
+
+	/* Compute number of bytes mod 64 */
+	index = (unsigned int)((context->count[0] >> 3) & 0x3F);
+
+	/* Update number of bits */
+	if ((context->count[0] += ((UINT4)inputLen << 3))< ((UINT4)inputLen << 3))
+		context->count[1]++;
+
+	context->count[1] += ((UINT4)inputLen >> 29);
+
+	partLen = 64 - index;
+
+	/* Transform as many times as possible.*/
+	if (inputLen >= partLen)
+	{
+ 		memcpy((POINTER)&context->buffer[index], (POINTER)input, partLen);
+ 		MD4Transform (context->state, context->buffer);
+
+ 		for (i = partLen; i + 63 < inputLen; i += 64)
+ 			MD4Transform (context->state, &input[i]);
+
+ 		index = 0;
+	}
+	else
+ 		i = 0;
+
+	/* Buffer remaining input */
+	memcpy ((POINTER)&context->buffer[index], (POINTER)&input[i], inputLen-i);
+}
+
+
+/* MD4 finalization. Ends an MD4 message-digest operation, writing the the message digest and zeroizing the context. */
+void MD4Final (unsigned char digest[16], MD4_CTX *context)
+{
+	unsigned char bits[8];
+	unsigned int index, padLen;
+
+	/* Save number of bits */
+	Encode (bits, context->count, 8);
+
+	/* Pad out to 56 mod 64.*/
+	index = (unsigned int)((context->count[0] >> 3) & 0x3f);
+	padLen = (index < 56) ? (56 - index) : (120 - index);
+	MD4Update (context, PADDING, padLen);
+
+	/* Append length (before padding) */
+	MD4Update (context, bits, 8);
+	
+	/* Store state in digest */
+	Encode (digest, context->state, 16);
+
+	/* Zeroize sensitive information.*/
+	memset ((POINTER)context, 0, sizeof (*context));
+}
+
+
+/* MD4 basic transformation. Transforms state based on block. */
+static void MD4Transform (UINT4 state[4], unsigned char block[64])
+{
+	UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
+
+	Decode (x, block, 64);
+
+/* Round 1 */
+FF (a, b, c, d, x[ 0], S11); 				/* 1 */
+FF (d, a, b, c, x[ 1], S12); 				/* 2 */
+FF (c, d, a, b, x[ 2], S13); 				/* 3 */
+FF (b, c, d, a, x[ 3], S14); 				/* 4 */
+FF (a, b, c, d, x[ 4], S11); 				/* 5 */
+FF (d, a, b, c, x[ 5], S12); 				/* 6 */
+FF (c, d, a, b, x[ 6], S13); 				/* 7 */
+FF (b, c, d, a, x[ 7], S14); 				/* 8 */
+FF (a, b, c, d, x[ 8], S11); 				/* 9 */
+FF (d, a, b, c, x[ 9], S12); 				/* 10 */
+FF (c, d, a, b, x[10], S13); 			/* 11 */
+FF (b, c, d, a, x[11], S14); 			/* 12 */
+FF (a, b, c, d, x[12], S11); 			/* 13 */
+FF (d, a, b, c, x[13], S12); 			/* 14 */
+FF (c, d, a, b, x[14], S13); 			/* 15 */
+FF (b, c, d, a, x[15], S14); 			/* 16 */
+
+/* Round 2 */
+GG (a, b, c, d, x[ 0], S21); 			/* 17 */
+GG (d, a, b, c, x[ 4], S22); 			/* 18 */
+GG (c, d, a, b, x[ 8], S23); 			/* 19 */
+GG (b, c, d, a, x[12], S24); 			/* 20 */
+GG (a, b, c, d, x[ 1], S21); 			/* 21 */
+GG (d, a, b, c, x[ 5], S22); 			/* 22 */
+GG (c, d, a, b, x[ 9], S23); 			/* 23 */
+GG (b, c, d, a, x[13], S24); 			/* 24 */
+GG (a, b, c, d, x[ 2], S21); 			/* 25 */
+GG (d, a, b, c, x[ 6], S22); 			/* 26 */
+GG (c, d, a, b, x[10], S23); 			/* 27 */
+GG (b, c, d, a, x[14], S24); 			/* 28 */
+GG (a, b, c, d, x[ 3], S21); 			/* 29 */
+GG (d, a, b, c, x[ 7], S22); 			/* 30 */
+GG (c, d, a, b, x[11], S23); 			/* 31 */
+GG (b, c, d, a, x[15], S24); 			/* 32 */
+
+/* Round 3 */
+HH (a, b, c, d, x[ 0], S31);				/* 33 */
+HH (d, a, b, c, x[ 8], S32); 			/* 34 */
+HH (c, d, a, b, x[ 4], S33); 			/* 35 */
+HH (b, c, d, a, x[12], S34); 			/* 36 */
+HH (a, b, c, d, x[ 2], S31); 			/* 37 */
+HH (d, a, b, c, x[10], S32); 			/* 38 */
+HH (c, d, a, b, x[ 6], S33); 			/* 39 */
+HH (b, c, d, a, x[14], S34); 			/* 40 */
+HH (a, b, c, d, x[ 1], S31); 			/* 41 */
+HH (d, a, b, c, x[ 9], S32); 			/* 42 */
+HH (c, d, a, b, x[ 5], S33); 			/* 43 */
+HH (b, c, d, a, x[13], S34); 			/* 44 */
+HH (a, b, c, d, x[ 3], S31); 			/* 45 */
+HH (d, a, b, c, x[11], S32); 			/* 46 */
+HH (c, d, a, b, x[ 7], S33); 			/* 47 */
+HH (b, c, d, a, x[15], S34);			/* 48 */
+
+state[0] += a;
+state[1] += b;
+state[2] += c;
+state[3] += d;
+
+	/* Zeroize sensitive information.*/
+	memset ((POINTER)x, 0, sizeof (x));
+}
+
+
+/* Encodes input (UINT4) into output (unsigned char). Assumes len is a multiple of 4. */
+static void Encode (unsigned char *output, UINT4 *input, unsigned int len)
+{
+	unsigned int i, j;
+
+	for (i = 0, j = 0; j < len; i++, j += 4) {
+ 		output[j] = (unsigned char)(input[i] & 0xff);
+ 		output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
+ 		output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
+ 		output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
+	}
+}
+
+
+/* Decodes input (unsigned char) into output (UINT4). Assumes len is a multiple of 4. */
+static void Decode (UINT4 *output, unsigned char *input, unsigned int len)
+{
+unsigned int i, j;
+
+for (i = 0, j = 0; j < len; i++, j += 4)
+ 	output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) | (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24);
+}
+
+//===================================================================
+
+unsigned Com_BlockChecksum (void *buffer, int length)
+{
+	int			digest[4];
+	unsigned	val;
+	MD4_CTX		ctx;
+
+	MD4Init (&ctx);
+	MD4Update (&ctx, (unsigned char *)buffer, length);
+	MD4Final ( (unsigned char *)digest, &ctx);
+	
+	val = digest[0] ^ digest[1] ^ digest[2] ^ digest[3];
+
+	return val;
+}
+
+void Com_BlockFullChecksum (void *buffer, int len, unsigned char *outbuf)
+{
+	MD4_CTX		ctx;
+
+	MD4Init (&ctx);
+	MD4Update (&ctx, (unsigned char *)buffer, len);
+	MD4Final ( outbuf, &ctx);
+}
--- /dev/null
+++ b/QW/client/menu.c
@@ -1,0 +1,1326 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+#include "quakedef.h"
+#include "winquake.h"
+
+void (*vid_menudrawfn)(void);
+void (*vid_menukeyfn)(int key);
+
+enum {m_none, m_main, m_singleplayer, m_load, m_save, m_multiplayer, m_setup, m_net, m_options, m_video, m_keys, m_help, m_quit, m_serialconfig, m_modemconfig, m_lanconfig, m_gameoptions, m_search, m_slist} m_state;
+
+void M_Menu_Main_f (void);
+	void M_Menu_SinglePlayer_f (void);
+		void M_Menu_Load_f (void);
+		void M_Menu_Save_f (void);
+	void M_Menu_MultiPlayer_f (void);
+		void M_Menu_Setup_f (void);
+		void M_Menu_Net_f (void);
+	void M_Menu_Options_f (void);
+		void M_Menu_Keys_f (void);
+		void M_Menu_Video_f (void);
+	void M_Menu_Help_f (void);
+	void M_Menu_Quit_f (void);
+void M_Menu_SerialConfig_f (void);
+	void M_Menu_ModemConfig_f (void);
+void M_Menu_LanConfig_f (void);
+void M_Menu_GameOptions_f (void);
+void M_Menu_Search_f (void);
+void M_Menu_ServerList_f (void);
+
+void M_Main_Draw (void);
+	void M_SinglePlayer_Draw (void);
+		void M_Load_Draw (void);
+		void M_Save_Draw (void);
+	void M_MultiPlayer_Draw (void);
+		void M_Setup_Draw (void);
+		void M_Net_Draw (void);
+	void M_Options_Draw (void);
+		void M_Keys_Draw (void);
+		void M_Video_Draw (void);
+	void M_Help_Draw (void);
+	void M_Quit_Draw (void);
+void M_SerialConfig_Draw (void);
+	void M_ModemConfig_Draw (void);
+void M_LanConfig_Draw (void);
+void M_GameOptions_Draw (void);
+void M_Search_Draw (void);
+void M_ServerList_Draw (void);
+
+void M_Main_Key (int key);
+	void M_SinglePlayer_Key (int key);
+		void M_Load_Key (int key);
+		void M_Save_Key (int key);
+	void M_MultiPlayer_Key (int key);
+		void M_Setup_Key (int key);
+		void M_Net_Key (int key);
+	void M_Options_Key (int key);
+		void M_Keys_Key (int key);
+		void M_Video_Key (int key);
+	void M_Help_Key (int key);
+	void M_Quit_Key (int key);
+void M_SerialConfig_Key (int key);
+	void M_ModemConfig_Key (int key);
+void M_LanConfig_Key (int key);
+void M_GameOptions_Key (int key);
+void M_Search_Key (int key);
+void M_ServerList_Key (int key);
+
+qboolean	m_entersound;		// play after drawing a frame, so caching
+								// won't disrupt the sound
+qboolean	m_recursiveDraw;
+
+int			m_return_state;
+qboolean	m_return_onerror;
+char		m_return_reason [32];
+
+#define StartingGame	(m_multiplayer_cursor == 1)
+#define JoiningGame		(m_multiplayer_cursor == 0)
+#define SerialConfig	(m_net_cursor == 0)
+#define DirectConfig	(m_net_cursor == 1)
+#define	IPXConfig		(m_net_cursor == 2)
+#define	TCPIPConfig		(m_net_cursor == 3)
+
+void M_ConfigureNetSubsystem(void);
+
+//=============================================================================
+/* Support Routines */
+
+/*
+================
+M_DrawCharacter
+
+Draws one solid graphics character
+================
+*/
+void M_DrawCharacter (int cx, int line, int num)
+{
+	Draw_Character ( cx + ((vid.width - 320)>>1), line, num);
+}
+
+void M_Print (int cx, int cy, char *str)
+{
+	while (*str)
+	{
+		M_DrawCharacter (cx, cy, (*str)+128);
+		str++;
+		cx += 8;
+	}
+}
+
+void M_PrintWhite (int cx, int cy, char *str)
+{
+	while (*str)
+	{
+		M_DrawCharacter (cx, cy, *str);
+		str++;
+		cx += 8;
+	}
+}
+
+void M_DrawTransPic (int x, int y, qpic_t *pic)
+{
+	Draw_TransPic (x + ((vid.width - 320)>>1), y, pic);
+}
+
+void M_DrawPic (int x, int y, qpic_t *pic)
+{
+	Draw_Pic (x + ((vid.width - 320)>>1), y, pic);
+}
+
+byte identityTable[256];
+byte translationTable[256];
+
+void M_BuildTranslationTable(int top, int bottom)
+{
+	int		j;
+	byte	*dest, *source;
+
+	for (j = 0; j < 256; j++)
+		identityTable[j] = j;
+	dest = translationTable;
+	source = identityTable;
+	memcpy (dest, source, 256);
+
+	if (top < 128)	// the artists made some backwards ranges.  sigh.
+		memcpy (dest + TOP_RANGE, source + top, 16);
+	else
+		for (j=0 ; j<16 ; j++)
+			dest[TOP_RANGE+j] = source[top+15-j];
+
+	if (bottom < 128)
+		memcpy (dest + BOTTOM_RANGE, source + bottom, 16);
+	else
+		for (j=0 ; j<16 ; j++)
+			dest[BOTTOM_RANGE+j] = source[bottom+15-j];		
+}
+
+
+void M_DrawTransPicTranslate (int x, int y, qpic_t *pic)
+{
+	Draw_TransPicTranslate (x + ((vid.width - 320)>>1), y, pic, translationTable);
+}
+
+
+void M_DrawTextBox (int x, int y, int width, int lines)
+{
+	qpic_t	*p;
+	int		cx, cy;
+	int		n;
+
+	// draw left side
+	cx = x;
+	cy = y;
+	p = Draw_CachePic ("gfx/box_tl.lmp");
+	M_DrawTransPic (cx, cy, p);
+	p = Draw_CachePic ("gfx/box_ml.lmp");
+	for (n = 0; n < lines; n++)
+	{
+		cy += 8;
+		M_DrawTransPic (cx, cy, p);
+	}
+	p = Draw_CachePic ("gfx/box_bl.lmp");
+	M_DrawTransPic (cx, cy+8, p);
+
+	// draw middle
+	cx += 8;
+	while (width > 0)
+	{
+		cy = y;
+		p = Draw_CachePic ("gfx/box_tm.lmp");
+		M_DrawTransPic (cx, cy, p);
+		p = Draw_CachePic ("gfx/box_mm.lmp");
+		for (n = 0; n < lines; n++)
+		{
+			cy += 8;
+			if (n == 1)
+				p = Draw_CachePic ("gfx/box_mm2.lmp");
+			M_DrawTransPic (cx, cy, p);
+		}
+		p = Draw_CachePic ("gfx/box_bm.lmp");
+		M_DrawTransPic (cx, cy+8, p);
+		width -= 2;
+		cx += 16;
+	}
+
+	// draw right side
+	cy = y;
+	p = Draw_CachePic ("gfx/box_tr.lmp");
+	M_DrawTransPic (cx, cy, p);
+	p = Draw_CachePic ("gfx/box_mr.lmp");
+	for (n = 0; n < lines; n++)
+	{
+		cy += 8;
+		M_DrawTransPic (cx, cy, p);
+	}
+	p = Draw_CachePic ("gfx/box_br.lmp");
+	M_DrawTransPic (cx, cy+8, p);
+}
+
+//=============================================================================
+
+int m_save_demonum;
+		
+/*
+================
+M_ToggleMenu_f
+================
+*/
+void M_ToggleMenu_f (void)
+{
+	m_entersound = true;
+
+	if (key_dest == key_menu)
+	{
+		if (m_state != m_main)
+		{
+			M_Menu_Main_f ();
+			return;
+		}
+		key_dest = key_game;
+		m_state = m_none;
+		return;
+	}
+	if (key_dest == key_console)
+	{
+		Con_ToggleConsole_f ();
+	}
+	else
+	{
+		M_Menu_Main_f ();
+	}
+}
+
+		
+//=============================================================================
+/* MAIN MENU */
+
+int	m_main_cursor;
+#define	MAIN_ITEMS	5
+
+
+void M_Menu_Main_f (void)
+{
+	if (key_dest != key_menu)
+	{
+		m_save_demonum = cls.demonum;
+		cls.demonum = -1;
+	}
+	key_dest = key_menu;
+	m_state = m_main;
+	m_entersound = true;
+}
+				
+
+void M_Main_Draw (void)
+{
+	int		f;
+	qpic_t	*p;
+
+	M_DrawTransPic (16, 4, Draw_CachePic ("gfx/qplaque.lmp") );
+	p = Draw_CachePic ("gfx/ttl_main.lmp");
+	M_DrawPic ( (320-p->width)/2, 4, p);
+	M_DrawTransPic (72, 32, Draw_CachePic ("gfx/mainmenu.lmp") );
+
+	f = (int)(realtime * 10)%6;
+	
+	M_DrawTransPic (54, 32 + m_main_cursor * 20,Draw_CachePic( va("gfx/menudot%i.lmp", f+1 ) ) );
+}
+
+
+void M_Main_Key (int key)
+{
+	switch (key)
+	{
+	case K_ESCAPE:
+		key_dest = key_game;
+		m_state = m_none;
+		cls.demonum = m_save_demonum;
+		if (cls.demonum != -1 && !cls.demoplayback && cls.state == ca_disconnected)
+			CL_NextDemo ();
+		break;
+		
+	case K_DOWNARROW:
+		S_LocalSound ("misc/menu1.wav");
+		if (++m_main_cursor >= MAIN_ITEMS)
+			m_main_cursor = 0;
+		break;
+
+	case K_UPARROW:
+		S_LocalSound ("misc/menu1.wav");
+		if (--m_main_cursor < 0)
+			m_main_cursor = MAIN_ITEMS - 1;
+		break;
+
+	case K_ENTER:
+		m_entersound = true;
+
+		switch (m_main_cursor)
+		{
+		case 0:
+			M_Menu_SinglePlayer_f ();
+			break;
+
+		case 1:
+			M_Menu_MultiPlayer_f ();
+			break;
+
+		case 2:
+			M_Menu_Options_f ();
+			break;
+
+		case 3:
+			M_Menu_Help_f ();
+			break;
+
+		case 4:
+			M_Menu_Quit_f ();
+			break;
+		}
+	}
+}
+
+
+//=============================================================================
+/* OPTIONS MENU */
+
+#define	OPTIONS_ITEMS	16
+
+#define	SLIDER_RANGE	10
+
+int		options_cursor;
+
+void M_Menu_Options_f (void)
+{
+	key_dest = key_menu;
+	m_state = m_options;
+	m_entersound = true;
+}
+
+
+void M_AdjustSliders (int dir)
+{
+	S_LocalSound ("misc/menu3.wav");
+
+	switch (options_cursor)
+	{
+	case 3:	// screen size
+		scr_viewsize.value += dir * 10;
+		if (scr_viewsize.value < 30)
+			scr_viewsize.value = 30;
+		if (scr_viewsize.value > 120)
+			scr_viewsize.value = 120;
+		Cvar_SetValue ("viewsize", scr_viewsize.value);
+		break;
+	case 4:	// gamma
+		v_gamma.value -= dir * 0.05;
+		if (v_gamma.value < 0.5)
+			v_gamma.value = 0.5;
+		if (v_gamma.value > 1)
+			v_gamma.value = 1;
+		Cvar_SetValue ("gamma", v_gamma.value);
+		break;
+	case 5:	// mouse speed
+		sensitivity.value += dir * 0.5;
+		if (sensitivity.value < 1)
+			sensitivity.value = 1;
+		if (sensitivity.value > 11)
+			sensitivity.value = 11;
+		Cvar_SetValue ("sensitivity", sensitivity.value);
+		break;
+	case 6:	// music volume
+#ifdef _WIN32
+		bgmvolume.value += dir * 1.0;
+#else
+		bgmvolume.value += dir * 0.1;
+#endif
+		if (bgmvolume.value < 0)
+			bgmvolume.value = 0;
+		if (bgmvolume.value > 1)
+			bgmvolume.value = 1;
+		Cvar_SetValue ("bgmvolume", bgmvolume.value);
+		break;
+	case 7:	// sfx volume
+		volume.value += dir * 0.1;
+		if (volume.value < 0)
+			volume.value = 0;
+		if (volume.value > 1)
+			volume.value = 1;
+		Cvar_SetValue ("volume", volume.value);
+		break;
+		
+	case 8:	// allways run
+		if (cl_forwardspeed.value > 200)
+		{
+			Cvar_SetValue ("cl_forwardspeed", 200);
+			Cvar_SetValue ("cl_backspeed", 200);
+		}
+		else
+		{
+			Cvar_SetValue ("cl_forwardspeed", 400);
+			Cvar_SetValue ("cl_backspeed", 400);
+		}
+		break;
+	
+	case 9:	// invert mouse
+		Cvar_SetValue ("m_pitch", -m_pitch.value);
+		break;
+	
+	case 10:	// lookspring
+		Cvar_SetValue ("lookspring", !lookspring.value);
+		break;
+	
+	case 11:	// lookstrafe
+		Cvar_SetValue ("lookstrafe", !lookstrafe.value);
+		break;
+
+	case 12:
+		Cvar_SetValue ("cl_sbar", !cl_sbar.value);
+		break;
+
+	case 13:
+		Cvar_SetValue ("cl_hudswap", !cl_hudswap.value);
+
+	case 15:	// _windowed_mouse
+		Cvar_SetValue ("_windowed_mouse", !_windowed_mouse.value);
+		break;
+	}
+}
+
+
+void M_DrawSlider (int x, int y, float range)
+{
+	int	i;
+
+	if (range < 0)
+		range = 0;
+	if (range > 1)
+		range = 1;
+	M_DrawCharacter (x-8, y, 128);
+	for (i=0 ; i<SLIDER_RANGE ; i++)
+		M_DrawCharacter (x + i*8, y, 129);
+	M_DrawCharacter (x+i*8, y, 130);
+	M_DrawCharacter (x + (SLIDER_RANGE-1)*8 * range, y, 131);
+}
+
+void M_DrawCheckbox (int x, int y, int on)
+{
+#if 0
+	if (on)
+		M_DrawCharacter (x, y, 131);
+	else
+		M_DrawCharacter (x, y, 129);
+#endif
+	if (on)
+		M_Print (x, y, "on");
+	else
+		M_Print (x, y, "off");
+}
+
+void M_Options_Draw (void)
+{
+	float		r;
+	qpic_t	*p;
+	
+	M_DrawTransPic (16, 4, Draw_CachePic ("gfx/qplaque.lmp") );
+	p = Draw_CachePic ("gfx/p_option.lmp");
+	M_DrawPic ( (320-p->width)/2, 4, p);
+	
+	M_Print (16, 32, "    Customize controls");
+	M_Print (16, 40, "         Go to console");
+	M_Print (16, 48, "     Reset to defaults");
+
+	M_Print (16, 56, "           Screen size");
+	r = (scr_viewsize.value - 30) / (120 - 30);
+	M_DrawSlider (220, 56, r);
+
+	M_Print (16, 64, "            Brightness");
+	r = (1.0 - v_gamma.value) / 0.5;
+	M_DrawSlider (220, 64, r);
+
+	M_Print (16, 72, "           Mouse Speed");
+	r = (sensitivity.value - 1)/10;
+	M_DrawSlider (220, 72, r);
+
+	M_Print (16, 80, "       CD Music Volume");
+	r = bgmvolume.value;
+	M_DrawSlider (220, 80, r);
+
+	M_Print (16, 88, "          Sound Volume");
+	r = volume.value;
+	M_DrawSlider (220, 88, r);
+
+	M_Print (16, 96,  "            Always Run");
+	M_DrawCheckbox (220, 96, cl_forwardspeed.value > 200);
+
+	M_Print (16, 104, "          Invert Mouse");
+	M_DrawCheckbox (220, 104, m_pitch.value < 0);
+
+	M_Print (16, 112, "            Lookspring");
+	M_DrawCheckbox (220, 112, lookspring.value);
+
+	M_Print (16, 120, "            Lookstrafe");
+	M_DrawCheckbox (220, 120, lookstrafe.value);
+
+	M_Print (16, 128, "    Use old status bar");
+	M_DrawCheckbox (220, 128, cl_sbar.value);
+
+	M_Print (16, 136, "      HUD on left side");
+	M_DrawCheckbox (220, 136, cl_hudswap.value);
+
+	if (vid_menudrawfn)
+		M_Print (16, 144, "         Video Options");
+
+#ifdef _WIN32
+	if (modestate == MS_WINDOWED)
+	{
+#endif
+		M_Print (16, 152, "             Use Mouse");
+		M_DrawCheckbox (220, 152, _windowed_mouse.value);
+#ifdef _WIN32
+	}
+#endif
+
+// cursor
+	M_DrawCharacter (200, 32 + options_cursor*8, 12+((int)(realtime*4)&1));
+}
+
+
+void M_Options_Key (int k)
+{
+	switch (k)
+	{
+	case K_ESCAPE:
+		M_Menu_Main_f ();
+		break;
+		
+	case K_ENTER:
+		m_entersound = true;
+		switch (options_cursor)
+		{
+		case 0:
+			M_Menu_Keys_f ();
+			break;
+		case 1:
+			m_state = m_none;
+			Con_ToggleConsole_f ();
+			break;
+		case 2:
+			Cbuf_AddText ("exec default.cfg\n");
+			break;
+		case 14:
+			M_Menu_Video_f ();
+			break;
+		default:
+			M_AdjustSliders (1);
+			break;
+		}
+		return;
+	
+	case K_UPARROW:
+		S_LocalSound ("misc/menu1.wav");
+		options_cursor--;
+		if (options_cursor < 0)
+			options_cursor = OPTIONS_ITEMS-1;
+		break;
+
+	case K_DOWNARROW:
+		S_LocalSound ("misc/menu1.wav");
+		options_cursor++;
+		if (options_cursor >= OPTIONS_ITEMS)
+			options_cursor = 0;
+		break;	
+
+	case K_LEFTARROW:
+		M_AdjustSliders (-1);
+		break;
+
+	case K_RIGHTARROW:
+		M_AdjustSliders (1);
+		break;
+	}
+
+	if (options_cursor == 14 && vid_menudrawfn == NULL)
+	{
+		if (k == K_UPARROW)
+			options_cursor = 13;
+		else
+			options_cursor = 0;
+	}
+
+	if ((options_cursor == 15) 
+#ifdef _WIN32
+	&& (modestate != MS_WINDOWED)
+#endif
+	)
+	{
+		if (k == K_UPARROW)
+			options_cursor = 14;
+		else
+			options_cursor = 0;
+	}
+}
+
+
+//=============================================================================
+/* KEYS MENU */
+
+char *bindnames[][2] =
+{
+{"+attack", 		"attack"},
+{"impulse 10", 		"change weapon"},
+{"+jump", 			"jump / swim up"},
+{"+forward", 		"walk forward"},
+{"+back", 			"backpedal"},
+{"+left", 			"turn left"},
+{"+right", 			"turn right"},
+{"+speed", 			"run"},
+{"+moveleft", 		"step left"},
+{"+moveright", 		"step right"},
+{"+strafe", 		"sidestep"},
+{"+lookup", 		"look up"},
+{"+lookdown", 		"look down"},
+{"centerview", 		"center view"},
+{"+mlook", 			"mouse look"},
+{"+klook", 			"keyboard look"},
+{"+moveup",			"swim up"},
+{"+movedown",		"swim down"}
+};
+
+#define	NUMCOMMANDS	(sizeof(bindnames)/sizeof(bindnames[0]))
+
+int		keys_cursor;
+int		bind_grab;
+
+void M_Menu_Keys_f (void)
+{
+	key_dest = key_menu;
+	m_state = m_keys;
+	m_entersound = true;
+}
+
+
+void M_FindKeysForCommand (char *command, int *twokeys)
+{
+	int		count;
+	int		j;
+	int		l;
+	char	*b;
+
+	twokeys[0] = twokeys[1] = -1;
+	l = strlen(command);
+	count = 0;
+
+	for (j=0 ; j<256 ; j++)
+	{
+		b = keybindings[j];
+		if (!b)
+			continue;
+		if (!strncmp (b, command, l) )
+		{
+			twokeys[count] = j;
+			count++;
+			if (count == 2)
+				break;
+		}
+	}
+}
+
+void M_UnbindCommand (char *command)
+{
+	int		j;
+	int		l;
+	char	*b;
+
+	l = strlen(command);
+
+	for (j=0 ; j<256 ; j++)
+	{
+		b = keybindings[j];
+		if (!b)
+			continue;
+		if (!strncmp (b, command, l) )
+			Key_SetBinding (j, "");
+	}
+}
+
+
+void M_Keys_Draw (void)
+{
+	int		i, l;
+	int		keys[2];
+	char	*name;
+	int		x, y;
+	qpic_t	*p;
+
+	p = Draw_CachePic ("gfx/ttl_cstm.lmp");
+	M_DrawPic ( (320-p->width)/2, 4, p);
+
+	if (bind_grab)
+		M_Print (12, 32, "Press a key or button for this action");
+	else
+		M_Print (18, 32, "Enter to change, backspace to clear");
+		
+// search for known bindings
+	for (i=0 ; i<NUMCOMMANDS ; i++)
+	{
+		y = 48 + 8*i;
+
+		M_Print (16, y, bindnames[i][1]);
+
+		l = strlen (bindnames[i][0]);
+		
+		M_FindKeysForCommand (bindnames[i][0], keys);
+		
+		if (keys[0] == -1)
+		{
+			M_Print (140, y, "???");
+		}
+		else
+		{
+			name = Key_KeynumToString (keys[0]);
+			M_Print (140, y, name);
+			x = strlen(name) * 8;
+			if (keys[1] != -1)
+			{
+				M_Print (140 + x + 8, y, "or");
+				M_Print (140 + x + 32, y, Key_KeynumToString (keys[1]));
+			}
+		}
+	}
+	
+	if (bind_grab)
+		M_DrawCharacter (130, 48 + keys_cursor*8, '=');
+	else
+		M_DrawCharacter (130, 48 + keys_cursor*8, 12+((int)(realtime*4)&1));
+}
+
+
+void M_Keys_Key (int k)
+{
+	char	cmd[80];
+	int		keys[2];
+	
+	if (bind_grab)
+	{	// defining a key
+		S_LocalSound ("misc/menu1.wav");
+		if (k == K_ESCAPE)
+		{
+			bind_grab = false;
+		}
+		else if (k != '`')
+		{
+			sprintf (cmd, "bind %s \"%s\"\n", Key_KeynumToString (k), bindnames[keys_cursor][0]);			
+			Cbuf_InsertText (cmd);
+		}
+		
+		bind_grab = false;
+		return;
+	}
+	
+	switch (k)
+	{
+	case K_ESCAPE:
+		M_Menu_Options_f ();
+		break;
+
+	case K_LEFTARROW:
+	case K_UPARROW:
+		S_LocalSound ("misc/menu1.wav");
+		keys_cursor--;
+		if (keys_cursor < 0)
+			keys_cursor = NUMCOMMANDS-1;
+		break;
+
+	case K_DOWNARROW:
+	case K_RIGHTARROW:
+		S_LocalSound ("misc/menu1.wav");
+		keys_cursor++;
+		if (keys_cursor >= NUMCOMMANDS)
+			keys_cursor = 0;
+		break;
+
+	case K_ENTER:		// go into bind mode
+		M_FindKeysForCommand (bindnames[keys_cursor][0], keys);
+		S_LocalSound ("misc/menu2.wav");
+		if (keys[1] != -1)
+			M_UnbindCommand (bindnames[keys_cursor][0]);
+		bind_grab = true;
+		break;
+
+	case K_BACKSPACE:		// delete bindings
+	case K_DEL:				// delete bindings
+		S_LocalSound ("misc/menu2.wav");
+		M_UnbindCommand (bindnames[keys_cursor][0]);
+		break;
+	}
+}
+
+//=============================================================================
+/* VIDEO MENU */
+
+void M_Menu_Video_f (void)
+{
+	key_dest = key_menu;
+	m_state = m_video;
+	m_entersound = true;
+}
+
+
+void M_Video_Draw (void)
+{
+	(*vid_menudrawfn) ();
+}
+
+
+void M_Video_Key (int key)
+{
+	(*vid_menukeyfn) (key);
+}
+
+//=============================================================================
+/* HELP MENU */
+
+int		help_page;
+#define	NUM_HELP_PAGES	6
+
+
+void M_Menu_Help_f (void)
+{
+	key_dest = key_menu;
+	m_state = m_help;
+	m_entersound = true;
+	help_page = 0;
+}
+
+
+
+void M_Help_Draw (void)
+{
+	M_DrawPic (0, 0, Draw_CachePic ( va("gfx/help%i.lmp", help_page)) );
+}
+
+
+void M_Help_Key (int key)
+{
+	switch (key)
+	{
+	case K_ESCAPE:
+		M_Menu_Main_f ();
+		break;
+		
+	case K_UPARROW:
+	case K_RIGHTARROW:
+		m_entersound = true;
+		if (++help_page >= NUM_HELP_PAGES)
+			help_page = 0;
+		break;
+
+	case K_DOWNARROW:
+	case K_LEFTARROW:
+		m_entersound = true;
+		if (--help_page < 0)
+			help_page = NUM_HELP_PAGES-1;
+		break;
+	}
+
+}
+
+//=============================================================================
+/* QUIT MENU */
+
+int		msgNumber;
+int		m_quit_prevstate;
+qboolean	wasInMenus;
+
+char *quitMessage [] = 
+{
+/* .........1.........2.... */
+  "  Are you gonna quit    ",
+  "  this game just like   ",
+  "   everything else?     ",
+  "                        ",
+ 
+  " Milord, methinks that  ",
+  "   thou art a lowly     ",
+  " quitter. Is this true? ",
+  "                        ",
+
+  " Do I need to bust your ",
+  "  face open for trying  ",
+  "        to quit?        ",
+  "                        ",
+
+  " Man, I oughta smack you",
+  "   for trying to quit!  ",
+  "     Press Y to get     ",
+  "      smacked out.      ",
+ 
+  " Press Y to quit like a ",
+  "   big loser in life.   ",
+  "  Press N to stay proud ",
+  "    and successful!     ",
+ 
+  "   If you press Y to    ",
+  "  quit, I will summon   ",
+  "  Satan all over your   ",
+  "      hard drive!       ",
+ 
+  "  Um, Asmodeus dislikes ",
+  " his children trying to ",
+  " quit. Press Y to return",
+  "   to your Tinkertoys.  ",
+ 
+  "  If you quit now, I'll ",
+  "  throw a blanket-party ",
+  "   for you next time!   ",
+  "                        "
+};
+
+void M_Menu_Quit_f (void)
+{
+	if (m_state == m_quit)
+		return;
+	wasInMenus = (key_dest == key_menu);
+	key_dest = key_menu;
+	m_quit_prevstate = m_state;
+	m_state = m_quit;
+	m_entersound = true;
+	msgNumber = rand()&7;
+}
+
+
+void M_Quit_Key (int key)
+{
+	switch (key)
+	{
+	case K_ESCAPE:
+	case 'n':
+	case 'N':
+		if (wasInMenus)
+		{
+			m_state = m_quit_prevstate;
+			m_entersound = true;
+		}
+		else
+		{
+			key_dest = key_game;
+			m_state = m_none;
+		}
+		break;
+
+	case 'Y':
+	case 'y':
+		key_dest = key_console;
+		CL_Disconnect ();
+		Sys_Quit ();
+		break;
+
+	default:
+		break;
+	}
+
+}
+
+void M_Menu_SinglePlayer_f (void) {
+	m_state = m_singleplayer;
+}
+
+void M_SinglePlayer_Draw (void) {
+	qpic_t	*p;
+
+	M_DrawTransPic (16, 4, Draw_CachePic ("gfx/qplaque.lmp") );
+//	M_DrawTransPic (16, 4, Draw_CachePic ("gfx/qplaque.lmp") );
+	p = Draw_CachePic ("gfx/ttl_sgl.lmp");
+	M_DrawPic ( (320-p->width)/2, 4, p);
+//	M_DrawTransPic (72, 32, Draw_CachePic ("gfx/sp_menu.lmp") );
+
+	M_DrawTextBox (60, 10*8, 23, 4);	
+	M_PrintWhite (92, 12*8, "QuakeWorld is for");
+	M_PrintWhite (88, 13*8, "Internet play only");
+
+}
+
+void M_SinglePlayer_Key (key) {
+	if (key == K_ESCAPE || key==K_ENTER)
+		m_state = m_main;
+}
+
+void M_Menu_MultiPlayer_f (void) {
+	m_state = m_multiplayer;
+}
+
+void M_MultiPlayer_Draw (void) {
+	qpic_t	*p;
+
+	M_DrawTransPic (16, 4, Draw_CachePic ("gfx/qplaque.lmp") );
+//	M_DrawTransPic (16, 4, Draw_CachePic ("gfx/qplaque.lmp") );
+	p = Draw_CachePic ("gfx/p_multi.lmp");
+	M_DrawPic ( (320-p->width)/2, 4, p);
+//	M_DrawTransPic (72, 32, Draw_CachePic ("gfx/sp_menu.lmp") );
+
+	M_DrawTextBox (46, 8*8, 27, 9);	
+	M_PrintWhite (72, 10*8, "If you want to find QW  ");
+	M_PrintWhite (72, 11*8, "games, head on over to: ");
+	     M_Print (72, 12*8, "   www.quakeworld.net   ");
+	M_PrintWhite (72, 13*8, "          or            ");
+	     M_Print (72, 14*8, "   www.quakespy.com     ");
+	M_PrintWhite (72, 15*8, "For pointers on getting ");
+	M_PrintWhite (72, 16*8, "        started!        ");
+}
+
+void M_MultiPlayer_Key (key) {
+	if (key == K_ESCAPE || key==K_ENTER)
+		m_state = m_main;
+}
+
+void M_Quit_Draw (void)
+{
+#define VSTR(x) #x
+#define VSTR2(x) VSTR(x)
+	char *cmsg[] = {
+//    0123456789012345678901234567890123456789
+	"0            QuakeWorld",
+	"1    version " VSTR2(VERSION) " by id Software",
+	"0Programming",
+	"1 John Carmack    Michael Abrash",
+	"1 John Cash       Christian Antkow",
+	"0Additional Programming",
+	"1 Dave 'Zoid' Kirsch",
+	"1 Jack 'morbid' Mathews",
+	"0Id Software is not responsible for",
+    "0providing technical support for",
+	"0QUAKEWORLD(tm). (c)1996 Id Software,",
+	"0Inc.  All Rights Reserved.",
+	"0QUAKEWORLD(tm) is a trademark of Id",
+	"0Software, Inc.",
+	"1NOTICE: THE COPYRIGHT AND TRADEMARK",
+	"1NOTICES APPEARING  IN YOUR COPY OF",
+	"1QUAKE(r) ARE NOT MODIFIED BY THE USE",
+	"1OF QUAKEWORLD(tm) AND REMAIN IN FULL",
+	"1FORCE.",
+	"0NIN(r) is a registered trademark",
+	"0licensed to Nothing Interactive, Inc.",
+	"0All rights reserved. Press y to exit",
+	NULL };
+	char **p;
+	int y;
+
+	if (wasInMenus)
+	{
+		m_state = m_quit_prevstate;
+		m_recursiveDraw = true;
+		M_Draw ();
+		m_state = m_quit;
+	}
+#if 1
+	M_DrawTextBox (0, 0, 38, 23);
+	y = 12;
+	for (p = cmsg; *p; p++, y += 8) {
+		if (**p == '0')
+			M_PrintWhite (16, y, *p + 1);
+		else
+			M_Print (16, y,	*p + 1);
+	}
+#else
+	M_DrawTextBox (56, 76, 24, 4);
+	M_Print (64, 84,  quitMessage[msgNumber*4+0]);
+	M_Print (64, 92,  quitMessage[msgNumber*4+1]);
+	M_Print (64, 100, quitMessage[msgNumber*4+2]);
+	M_Print (64, 108, quitMessage[msgNumber*4+3]);
+#endif
+}
+
+
+
+//=============================================================================
+/* Menu Subsystem */
+
+
+void M_Init (void)
+{
+	Cmd_AddCommand ("togglemenu", M_ToggleMenu_f);
+
+	Cmd_AddCommand ("menu_main", M_Menu_Main_f);
+	Cmd_AddCommand ("menu_options", M_Menu_Options_f);
+	Cmd_AddCommand ("menu_keys", M_Menu_Keys_f);
+	Cmd_AddCommand ("menu_video", M_Menu_Video_f);
+	Cmd_AddCommand ("help", M_Menu_Help_f);
+	Cmd_AddCommand ("menu_quit", M_Menu_Quit_f);
+}
+
+
+void M_Draw (void)
+{
+	if (m_state == m_none || key_dest != key_menu)
+		return;
+
+	if (!m_recursiveDraw)
+	{
+		scr_copyeverything = 1;
+
+		if (scr_con_current)
+		{
+			Draw_ConsoleBackground (vid.height);
+			VID_UnlockBuffer ();
+			S_ExtraUpdate ();
+			VID_LockBuffer ();
+		}
+		else
+			Draw_FadeScreen ();
+
+		scr_fullupdate = 0;
+	}
+	else
+	{
+		m_recursiveDraw = false;
+	}
+
+	switch (m_state)
+	{
+	case m_none:
+		break;
+
+	case m_main:
+		M_Main_Draw ();
+		break;
+
+	case m_singleplayer:
+		M_SinglePlayer_Draw ();
+		break;
+
+	case m_load:
+//		M_Load_Draw ();
+		break;
+
+	case m_save:
+//		M_Save_Draw ();
+		break;
+
+	case m_multiplayer:
+		M_MultiPlayer_Draw ();
+		break;
+
+	case m_setup:
+//		M_Setup_Draw ();
+		break;
+
+	case m_net:
+//		M_Net_Draw ();
+		break;
+
+	case m_options:
+		M_Options_Draw ();
+		break;
+
+	case m_keys:
+		M_Keys_Draw ();
+		break;
+
+	case m_video:
+		M_Video_Draw ();
+		break;
+
+	case m_help:
+		M_Help_Draw ();
+		break;
+
+	case m_quit:
+		M_Quit_Draw ();
+		break;
+
+	case m_serialconfig:
+//		M_SerialConfig_Draw ();
+		break;
+
+	case m_modemconfig:
+//		M_ModemConfig_Draw ();
+		break;
+
+	case m_lanconfig:
+//		M_LanConfig_Draw ();
+		break;
+
+	case m_gameoptions:
+//		M_GameOptions_Draw ();
+		break;
+
+	case m_search:
+//		M_Search_Draw ();
+		break;
+
+	case m_slist:
+//		M_ServerList_Draw ();
+		break;
+	}
+
+	if (m_entersound)
+	{
+		S_LocalSound ("misc/menu2.wav");
+		m_entersound = false;
+	}
+
+	VID_UnlockBuffer ();
+	S_ExtraUpdate ();
+	VID_LockBuffer ();
+}
+
+
+void M_Keydown (int key)
+{
+	switch (m_state)
+	{
+	case m_none:
+		return;
+
+	case m_main:
+		M_Main_Key (key);
+		return;
+
+	case m_singleplayer:
+		M_SinglePlayer_Key (key);
+		return;
+
+	case m_load:
+//		M_Load_Key (key);
+		return;
+
+	case m_save:
+//		M_Save_Key (key);
+		return;
+
+	case m_multiplayer:
+		M_MultiPlayer_Key (key);
+		return;
+
+	case m_setup:
+//		M_Setup_Key (key);
+		return;
+
+	case m_net:
+//		M_Net_Key (key);
+		return;
+
+	case m_options:
+		M_Options_Key (key);
+		return;
+
+	case m_keys:
+		M_Keys_Key (key);
+		return;
+
+	case m_video:
+		M_Video_Key (key);
+		return;
+
+	case m_help:
+		M_Help_Key (key);
+		return;
+
+	case m_quit:
+		M_Quit_Key (key);
+		return;
+
+	case m_serialconfig:
+//		M_SerialConfig_Key (key);
+		return;
+
+	case m_modemconfig:
+//		M_ModemConfig_Key (key);
+		return;
+
+	case m_lanconfig:
+//		M_LanConfig_Key (key);
+		return;
+
+	case m_gameoptions:
+//		M_GameOptions_Key (key);
+		return;
+
+	case m_search:
+//		M_Search_Key (key);
+		break;
+
+	case m_slist:
+//		M_ServerList_Key (key);
+		return;
+	}
+}
+
+
--- /dev/null
+++ b/QW/client/menu.h
@@ -1,0 +1,41 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+
+//
+// the net drivers should just set the apropriate bits in m_activenet,
+// instead of having the menu code look through their internal tables
+//
+#define	MNET_IPX		1
+#define	MNET_TCP		2
+
+extern	int	m_activenet;
+
+//
+// menus
+//
+void M_Init (void);
+void M_Keydown (int key);
+void M_Draw (void);
+void M_ToggleMenu_f (void);
+qpic_t	*M_CachePic (char *path);
+void M_DrawTextBox (int x, int y, int width, int lines);
+void M_Menu_Quit_f (void);
+
+
--- /dev/null
+++ b/QW/client/model.c
@@ -1,0 +1,1891 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// models.c -- model loading and caching
+
+// models are the only shared resource between a client and server running
+// on the same machine.
+
+#include "quakedef.h"
+#include "r_local.h"
+
+model_t	*loadmodel;
+char	loadname[32];	// for hunk tags
+
+void Mod_LoadSpriteModel (model_t *mod, void *buffer);
+void Mod_LoadBrushModel (model_t *mod, void *buffer);
+void Mod_LoadAliasModel (model_t *mod, void *buffer);
+model_t *Mod_LoadModel (model_t *mod, qboolean crash);
+
+byte	mod_novis[MAX_MAP_LEAFS/8];
+
+#define	MAX_MOD_KNOWN	256
+model_t	mod_known[MAX_MOD_KNOWN];
+int		mod_numknown;
+
+/*
+===============
+Mod_Init
+===============
+*/
+void Mod_Init (void)
+{
+	memset (mod_novis, 0xff, sizeof(mod_novis));
+}
+
+/*
+===============
+Mod_Init
+
+Caches the data if needed
+===============
+*/
+void *Mod_Extradata (model_t *mod)
+{
+	void	*r;
+	
+	r = Cache_Check (&mod->cache);
+	if (r)
+		return r;
+
+	Mod_LoadModel (mod, true);
+	
+	if (!mod->cache.data)
+		Sys_Error ("Mod_Extradata: caching failed");
+	return mod->cache.data;
+}
+
+/*
+===============
+Mod_PointInLeaf
+===============
+*/
+mleaf_t *Mod_PointInLeaf (vec3_t p, model_t *model)
+{
+	mnode_t		*node;
+	float		d;
+	mplane_t	*plane;
+	
+	if (!model || !model->nodes)
+		Sys_Error ("Mod_PointInLeaf: bad model");
+
+	node = model->nodes;
+	while (1)
+	{
+		if (node->contents < 0)
+			return (mleaf_t *)node;
+		plane = node->plane;
+		d = DotProduct (p,plane->normal) - plane->dist;
+		if (d > 0)
+			node = node->children[0];
+		else
+			node = node->children[1];
+	}
+	
+	return NULL;	// never reached
+}
+
+
+/*
+===================
+Mod_DecompressVis
+===================
+*/
+byte *Mod_DecompressVis (byte *in, model_t *model)
+{
+	static byte	decompressed[MAX_MAP_LEAFS/8];
+	int		c;
+	byte	*out;
+	int		row;
+
+	row = (model->numleafs+7)>>3;	
+	out = decompressed;
+
+#if 0
+	memcpy (out, in, row);
+#else
+	if (!in)
+	{	// no vis info, so make all visible
+		while (row)
+		{
+			*out++ = 0xff;
+			row--;
+		}
+		return decompressed;		
+	}
+
+	do
+	{
+		if (*in)
+		{
+			*out++ = *in++;
+			continue;
+		}
+	
+		c = in[1];
+		in += 2;
+		while (c)
+		{
+			*out++ = 0;
+			c--;
+		}
+	} while (out - decompressed < row);
+#endif
+	
+	return decompressed;
+}
+
+byte *Mod_LeafPVS (mleaf_t *leaf, model_t *model)
+{
+	if (leaf == model->leafs)
+		return mod_novis;
+	return Mod_DecompressVis (leaf->compressed_vis, model);
+}
+
+/*
+===================
+Mod_ClearAll
+===================
+*/
+void Mod_ClearAll (void)
+{
+	int		i;
+	model_t	*mod;
+	
+	for (i=0 , mod=mod_known ; i<mod_numknown ; i++, mod++)
+		if (mod->type != mod_alias)
+			mod->needload = true;
+}
+
+/*
+==================
+Mod_FindName
+
+==================
+*/
+model_t *Mod_FindName (char *name)
+{
+	int		i;
+	model_t	*mod;
+	
+	if (!name[0])
+		Sys_Error ("Mod_ForName: NULL name");
+		
+//
+// search the currently loaded models
+//
+	for (i=0 , mod=mod_known ; i<mod_numknown ; i++, mod++)
+		if (!strcmp (mod->name, name) )
+			break;
+			
+	if (i == mod_numknown)
+	{
+		if (mod_numknown == MAX_MOD_KNOWN)
+			Sys_Error ("mod_numknown == MAX_MOD_KNOWN");
+		strcpy (mod->name, name);
+		mod->needload = true;
+		mod_numknown++;
+	}
+
+	return mod;
+}
+
+/*
+==================
+Mod_TouchModel
+
+==================
+*/
+void Mod_TouchModel (char *name)
+{
+	model_t	*mod;
+	
+	mod = Mod_FindName (name);
+	
+	if (!mod->needload)
+	{
+		if (mod->type == mod_alias)
+			Cache_Check (&mod->cache);
+	}
+}
+
+/*
+==================
+Mod_LoadModel
+
+Loads a model into the cache
+==================
+*/
+model_t *Mod_LoadModel (model_t *mod, qboolean crash)
+{
+	void	*d;
+	unsigned *buf;
+	byte	stackbuf[1024];		// avoid dirtying the cache heap
+
+	if (!mod->needload)
+	{
+		if (mod->type == mod_alias)
+		{
+			d = Cache_Check (&mod->cache);
+			if (d)
+				return mod;
+		}
+		else
+			return mod;		// not cached at all
+	}
+
+//
+// because the world is so huge, load it one piece at a time
+//
+	if (!crash)
+	{
+	
+	}
+	
+//
+// load the file
+//
+	buf = (unsigned *)COM_LoadStackFile (mod->name, stackbuf, sizeof(stackbuf));
+	if (!buf)
+	{
+		if (crash)
+			Sys_Error ("Mod_NumForName: %s not found", mod->name);
+		return NULL;
+	}
+	
+//
+// allocate a new model
+//
+	COM_FileBase (mod->name, loadname);
+	
+	loadmodel = mod;
+
+//
+// fill it in
+//
+
+// call the apropriate loader
+	mod->needload = false;
+	
+	switch (LittleLong(*(unsigned *)buf))
+	{
+	case IDPOLYHEADER:
+		Mod_LoadAliasModel (mod, buf);
+		break;
+		
+	case IDSPRITEHEADER:
+		Mod_LoadSpriteModel (mod, buf);
+		break;
+	
+	default:
+		Mod_LoadBrushModel (mod, buf);
+		break;
+	}
+
+	return mod;
+}
+
+/*
+==================
+Mod_ForName
+
+Loads in a model for the given name
+==================
+*/
+model_t *Mod_ForName (char *name, qboolean crash)
+{
+	model_t	*mod;
+	
+	mod = Mod_FindName (name);
+	
+	return Mod_LoadModel (mod, crash);
+}
+
+
+/*
+===============================================================================
+
+					BRUSHMODEL LOADING
+
+===============================================================================
+*/
+
+byte	*mod_base;
+
+
+/*
+=================
+Mod_LoadTextures
+=================
+*/
+void Mod_LoadTextures (lump_t *l)
+{
+	int		i, j, pixels, num, max, altmax;
+	miptex_t	*mt;
+	texture_t	*tx, *tx2;
+	texture_t	*anims[10];
+	texture_t	*altanims[10];
+	dmiptexlump_t *m;
+
+	if (!l->filelen)
+	{
+		loadmodel->textures = NULL;
+		return;
+	}
+	m = (dmiptexlump_t *)(mod_base + l->fileofs);
+	
+	m->nummiptex = LittleLong (m->nummiptex);
+	
+	loadmodel->numtextures = m->nummiptex;
+	loadmodel->textures = Hunk_AllocName (m->nummiptex * sizeof(*loadmodel->textures) , loadname);
+
+	for (i=0 ; i<m->nummiptex ; i++)
+	{
+		m->dataofs[i] = LittleLong(m->dataofs[i]);
+		if (m->dataofs[i] == -1)
+			continue;
+		mt = (miptex_t *)((byte *)m + m->dataofs[i]);
+		mt->width = LittleLong (mt->width);
+		mt->height = LittleLong (mt->height);
+		for (j=0 ; j<MIPLEVELS ; j++)
+			mt->offsets[j] = LittleLong (mt->offsets[j]);
+		
+		if ( (mt->width & 15) || (mt->height & 15) )
+			Sys_Error ("Texture %s is not 16 aligned", mt->name);
+		pixels = mt->width*mt->height/64*85;
+		tx = Hunk_AllocName (sizeof(texture_t) +pixels, loadname );
+		loadmodel->textures[i] = tx;
+
+		memcpy (tx->name, mt->name, sizeof(tx->name));
+		tx->width = mt->width;
+		tx->height = mt->height;
+		for (j=0 ; j<MIPLEVELS ; j++)
+			tx->offsets[j] = mt->offsets[j] + sizeof(texture_t) - sizeof(miptex_t);
+		// the pixels immediately follow the structures
+		memcpy ( tx+1, mt+1, pixels);
+		
+		if (!Q_strncmp(mt->name,"sky",3))	
+			R_InitSky (tx);
+	}
+
+//
+// sequence the animations
+//
+	for (i=0 ; i<m->nummiptex ; i++)
+	{
+		tx = loadmodel->textures[i];
+		if (!tx || tx->name[0] != '+')
+			continue;
+		if (tx->anim_next)
+			continue;	// allready sequenced
+
+	// find the number of frames in the animation
+		memset (anims, 0, sizeof(anims));
+		memset (altanims, 0, sizeof(altanims));
+
+		max = tx->name[1];
+		altmax = 0;
+		if (max >= 'a' && max <= 'z')
+			max -= 'a' - 'A';
+		if (max >= '0' && max <= '9')
+		{
+			max -= '0';
+			altmax = 0;
+			anims[max] = tx;
+			max++;
+		}
+		else if (max >= 'A' && max <= 'J')
+		{
+			altmax = max - 'A';
+			max = 0;
+			altanims[altmax] = tx;
+			altmax++;
+		}
+		else
+			Sys_Error ("Bad animating texture %s", tx->name);
+
+		for (j=i+1 ; j<m->nummiptex ; j++)
+		{
+			tx2 = loadmodel->textures[j];
+			if (!tx2 || tx2->name[0] != '+')
+				continue;
+			if (strcmp (tx2->name+2, tx->name+2))
+				continue;
+
+			num = tx2->name[1];
+			if (num >= 'a' && num <= 'z')
+				num -= 'a' - 'A';
+			if (num >= '0' && num <= '9')
+			{
+				num -= '0';
+				anims[num] = tx2;
+				if (num+1 > max)
+					max = num + 1;
+			}
+			else if (num >= 'A' && num <= 'J')
+			{
+				num = num - 'A';
+				altanims[num] = tx2;
+				if (num+1 > altmax)
+					altmax = num+1;
+			}
+			else
+				Sys_Error ("Bad animating texture %s", tx->name);
+		}
+		
+#define	ANIM_CYCLE	2
+	// link them all together
+		for (j=0 ; j<max ; j++)
+		{
+			tx2 = anims[j];
+			if (!tx2)
+				Sys_Error ("Missing frame %i of %s",j, tx->name);
+			tx2->anim_total = max * ANIM_CYCLE;
+			tx2->anim_min = j * ANIM_CYCLE;
+			tx2->anim_max = (j+1) * ANIM_CYCLE;
+			tx2->anim_next = anims[ (j+1)%max ];
+			if (altmax)
+				tx2->alternate_anims = altanims[0];
+		}
+		for (j=0 ; j<altmax ; j++)
+		{
+			tx2 = altanims[j];
+			if (!tx2)
+				Sys_Error ("Missing frame %i of %s",j, tx->name);
+			tx2->anim_total = altmax * ANIM_CYCLE;
+			tx2->anim_min = j * ANIM_CYCLE;
+			tx2->anim_max = (j+1) * ANIM_CYCLE;
+			tx2->anim_next = altanims[ (j+1)%altmax ];
+			if (max)
+				tx2->alternate_anims = anims[0];
+		}
+	}
+}
+
+/*
+=================
+Mod_LoadLighting
+=================
+*/
+void Mod_LoadLighting (lump_t *l)
+{
+	if (!l->filelen)
+	{
+		loadmodel->lightdata = NULL;
+		return;
+	}
+	loadmodel->lightdata = Hunk_AllocName ( l->filelen, loadname);	
+	memcpy (loadmodel->lightdata, mod_base + l->fileofs, l->filelen);
+}
+
+
+/*
+=================
+Mod_LoadVisibility
+=================
+*/
+void Mod_LoadVisibility (lump_t *l)
+{
+	if (!l->filelen)
+	{
+		loadmodel->visdata = NULL;
+		return;
+	}
+	loadmodel->visdata = Hunk_AllocName ( l->filelen, loadname);	
+	memcpy (loadmodel->visdata, mod_base + l->fileofs, l->filelen);
+}
+
+
+/*
+=================
+Mod_LoadEntities
+=================
+*/
+void Mod_LoadEntities (lump_t *l)
+{
+	if (!l->filelen)
+	{
+		loadmodel->entities = NULL;
+		return;
+	}
+	loadmodel->entities = Hunk_AllocName ( l->filelen, loadname);	
+	memcpy (loadmodel->entities, mod_base + l->fileofs, l->filelen);
+}
+
+
+/*
+=================
+Mod_LoadVertexes
+=================
+*/
+void Mod_LoadVertexes (lump_t *l)
+{
+	dvertex_t	*in;
+	mvertex_t	*out;
+	int			i, count;
+
+	in = (void *)(mod_base + l->fileofs);
+	if (l->filelen % sizeof(*in))
+		Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
+	count = l->filelen / sizeof(*in);
+	out = Hunk_AllocName ( count*sizeof(*out), loadname);	
+
+	loadmodel->vertexes = out;
+	loadmodel->numvertexes = count;
+
+	for ( i=0 ; i<count ; i++, in++, out++)
+	{
+		out->position[0] = LittleFloat (in->point[0]);
+		out->position[1] = LittleFloat (in->point[1]);
+		out->position[2] = LittleFloat (in->point[2]);
+	}
+}
+
+/*
+=================
+Mod_LoadSubmodels
+=================
+*/
+void Mod_LoadSubmodels (lump_t *l)
+{
+	dmodel_t	*in;
+	dmodel_t	*out;
+	int			i, j, count;
+
+	in = (void *)(mod_base + l->fileofs);
+	if (l->filelen % sizeof(*in))
+		Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
+	count = l->filelen / sizeof(*in);
+	out = Hunk_AllocName ( count*sizeof(*out), loadname);	
+
+	loadmodel->submodels = out;
+	loadmodel->numsubmodels = count;
+
+	for ( i=0 ; i<count ; i++, in++, out++)
+	{
+		for (j=0 ; j<3 ; j++)
+		{	// spread the mins / maxs by a pixel
+			out->mins[j] = LittleFloat (in->mins[j]) - 1;
+			out->maxs[j] = LittleFloat (in->maxs[j]) + 1;
+			out->origin[j] = LittleFloat (in->origin[j]);
+		}
+		for (j=0 ; j<MAX_MAP_HULLS ; j++)
+			out->headnode[j] = LittleLong (in->headnode[j]);
+		out->visleafs = LittleLong (in->visleafs);
+		out->firstface = LittleLong (in->firstface);
+		out->numfaces = LittleLong (in->numfaces);
+	}
+}
+
+/*
+=================
+Mod_LoadEdges
+=================
+*/
+void Mod_LoadEdges (lump_t *l)
+{
+	dedge_t *in;
+	medge_t *out;
+	int 	i, count;
+
+	in = (void *)(mod_base + l->fileofs);
+	if (l->filelen % sizeof(*in))
+		Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
+	count = l->filelen / sizeof(*in);
+	out = Hunk_AllocName ( (count + 1) * sizeof(*out), loadname);	
+
+	loadmodel->edges = out;
+	loadmodel->numedges = count;
+
+	for ( i=0 ; i<count ; i++, in++, out++)
+	{
+		out->v[0] = (unsigned short)LittleShort(in->v[0]);
+		out->v[1] = (unsigned short)LittleShort(in->v[1]);
+	}
+}
+
+/*
+=================
+Mod_LoadTexinfo
+=================
+*/
+void Mod_LoadTexinfo (lump_t *l)
+{
+	texinfo_t *in;
+	mtexinfo_t *out;
+	int 	i, j, count;
+	int		miptex;
+	float	len1, len2;
+
+	in = (void *)(mod_base + l->fileofs);
+	if (l->filelen % sizeof(*in))
+		Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
+	count = l->filelen / sizeof(*in);
+	out = Hunk_AllocName ( count*sizeof(*out), loadname);	
+
+	loadmodel->texinfo = out;
+	loadmodel->numtexinfo = count;
+
+	for ( i=0 ; i<count ; i++, in++, out++)
+	{
+		for (j=0 ; j<8 ; j++)
+			out->vecs[0][j] = LittleFloat (in->vecs[0][j]);
+		len1 = Length (out->vecs[0]);
+		len2 = Length (out->vecs[1]);
+		len1 = (len1 + len2)/2;
+		if (len1 < 0.32)
+			out->mipadjust = 4;
+		else if (len1 < 0.49)
+			out->mipadjust = 3;
+		else if (len1 < 0.99)
+			out->mipadjust = 2;
+		else
+			out->mipadjust = 1;
+#if 0
+		if (len1 + len2 < 0.001)
+			out->mipadjust = 1;		// don't crash
+		else
+			out->mipadjust = 1 / floor( (len1+len2)/2 + 0.1 );
+#endif
+
+		miptex = LittleLong (in->miptex);
+		out->flags = LittleLong (in->flags);
+	
+		if (!loadmodel->textures)
+		{
+			out->texture = r_notexture_mip;	// checkerboard texture
+			out->flags = 0;
+		}
+		else
+		{
+			if (miptex >= loadmodel->numtextures)
+				Sys_Error ("miptex >= loadmodel->numtextures");
+			out->texture = loadmodel->textures[miptex];
+			if (!out->texture)
+			{
+				out->texture = r_notexture_mip; // texture not found
+				out->flags = 0;
+			}
+		}
+	}
+}
+
+/*
+================
+CalcSurfaceExtents
+
+Fills in s->texturemins[] and s->extents[]
+================
+*/
+void CalcSurfaceExtents (msurface_t *s)
+{
+	float	mins[2], maxs[2], val;
+	int		i,j, e;
+	mvertex_t	*v;
+	mtexinfo_t	*tex;
+	int		bmins[2], bmaxs[2];
+
+	mins[0] = mins[1] = 999999;
+	maxs[0] = maxs[1] = -99999;
+
+	tex = s->texinfo;
+	
+	for (i=0 ; i<s->numedges ; i++)
+	{
+		e = loadmodel->surfedges[s->firstedge+i];
+		if (e >= 0)
+			v = &loadmodel->vertexes[loadmodel->edges[e].v[0]];
+		else
+			v = &loadmodel->vertexes[loadmodel->edges[-e].v[1]];
+		
+		for (j=0 ; j<2 ; j++)
+		{
+			val = v->position[0] * tex->vecs[j][0] + 
+				v->position[1] * tex->vecs[j][1] +
+				v->position[2] * tex->vecs[j][2] +
+				tex->vecs[j][3];
+			if (val < mins[j])
+				mins[j] = val;
+			if (val > maxs[j])
+				maxs[j] = val;
+		}
+	}
+
+	for (i=0 ; i<2 ; i++)
+	{	
+		bmins[i] = floor(mins[i]/16);
+		bmaxs[i] = ceil(maxs[i]/16);
+
+		s->texturemins[i] = bmins[i] * 16;
+		s->extents[i] = (bmaxs[i] - bmins[i]) * 16;
+		if ( !(tex->flags & TEX_SPECIAL) && s->extents[i] > 256)
+			Sys_Error ("Bad surface extents");
+	}
+}
+
+
+/*
+=================
+Mod_LoadFaces
+=================
+*/
+void Mod_LoadFaces (lump_t *l)
+{
+	dface_t		*in;
+	msurface_t 	*out;
+	int			i, count, surfnum;
+	int			planenum, side;
+
+	in = (void *)(mod_base + l->fileofs);
+	if (l->filelen % sizeof(*in))
+		Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
+	count = l->filelen / sizeof(*in);
+	out = Hunk_AllocName ( count*sizeof(*out), loadname);	
+
+	loadmodel->surfaces = out;
+	loadmodel->numsurfaces = count;
+
+	for ( surfnum=0 ; surfnum<count ; surfnum++, in++, out++)
+	{
+		out->firstedge = LittleLong(in->firstedge);
+		out->numedges = LittleShort(in->numedges);		
+		out->flags = 0;
+
+		planenum = LittleShort(in->planenum);
+		side = LittleShort(in->side);
+		if (side)
+			out->flags |= SURF_PLANEBACK;			
+
+		out->plane = loadmodel->planes + planenum;
+
+		out->texinfo = loadmodel->texinfo + LittleShort (in->texinfo);
+
+		CalcSurfaceExtents (out);
+				
+	// lighting info
+
+		for (i=0 ; i<MAXLIGHTMAPS ; i++)
+			out->styles[i] = in->styles[i];
+		i = LittleLong(in->lightofs);
+		if (i == -1)
+			out->samples = NULL;
+		else
+			out->samples = loadmodel->lightdata + i;
+		
+	// set the drawing flags flag
+		
+		if (!Q_strncmp(out->texinfo->texture->name,"sky",3))	// sky
+		{
+			out->flags |= (SURF_DRAWSKY | SURF_DRAWTILED);
+			continue;
+		}
+		
+		if (!Q_strncmp(out->texinfo->texture->name,"*",1))		// turbulent
+		{
+			out->flags |= (SURF_DRAWTURB | SURF_DRAWTILED);
+			for (i=0 ; i<2 ; i++)
+			{
+				out->extents[i] = 16384;
+				out->texturemins[i] = -8192;
+			}
+			continue;
+		}
+	}
+}
+
+
+/*
+=================
+Mod_SetParent
+=================
+*/
+void Mod_SetParent (mnode_t *node, mnode_t *parent)
+{
+	node->parent = parent;
+	if (node->contents < 0)
+		return;
+	Mod_SetParent (node->children[0], node);
+	Mod_SetParent (node->children[1], node);
+}
+
+/*
+=================
+Mod_LoadNodes
+=================
+*/
+void Mod_LoadNodes (lump_t *l)
+{
+	int			i, j, count, p;
+	dnode_t		*in;
+	mnode_t 	*out;
+
+	in = (void *)(mod_base + l->fileofs);
+	if (l->filelen % sizeof(*in))
+		Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
+	count = l->filelen / sizeof(*in);
+	out = Hunk_AllocName ( count*sizeof(*out), loadname);	
+
+	loadmodel->nodes = out;
+	loadmodel->numnodes = count;
+
+	for ( i=0 ; i<count ; i++, in++, out++)
+	{
+		for (j=0 ; j<3 ; j++)
+		{
+			out->minmaxs[j] = LittleShort (in->mins[j]);
+			out->minmaxs[3+j] = LittleShort (in->maxs[j]);
+		}
+	
+		p = LittleLong(in->planenum);
+		out->plane = loadmodel->planes + p;
+
+		out->firstsurface = LittleShort (in->firstface);
+		out->numsurfaces = LittleShort (in->numfaces);
+		
+		for (j=0 ; j<2 ; j++)
+		{
+			p = LittleShort (in->children[j]);
+			if (p >= 0)
+				out->children[j] = loadmodel->nodes + p;
+			else
+				out->children[j] = (mnode_t *)(loadmodel->leafs + (-1 - p));
+		}
+	}
+	
+	Mod_SetParent (loadmodel->nodes, NULL);	// sets nodes and leafs
+}
+
+/*
+=================
+Mod_LoadLeafs
+=================
+*/
+void Mod_LoadLeafs (lump_t *l)
+{
+	dleaf_t 	*in;
+	mleaf_t 	*out;
+	int			i, j, count, p;
+
+	in = (void *)(mod_base + l->fileofs);
+	if (l->filelen % sizeof(*in))
+		Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
+	count = l->filelen / sizeof(*in);
+	out = Hunk_AllocName ( count*sizeof(*out), loadname);	
+
+	loadmodel->leafs = out;
+	loadmodel->numleafs = count;
+
+	for ( i=0 ; i<count ; i++, in++, out++)
+	{
+		for (j=0 ; j<3 ; j++)
+		{
+			out->minmaxs[j] = LittleShort (in->mins[j]);
+			out->minmaxs[3+j] = LittleShort (in->maxs[j]);
+		}
+
+		p = LittleLong(in->contents);
+		out->contents = p;
+
+		out->firstmarksurface = loadmodel->marksurfaces +
+			LittleShort(in->firstmarksurface);
+		out->nummarksurfaces = LittleShort(in->nummarksurfaces);
+		
+		p = LittleLong(in->visofs);
+		if (p == -1)
+			out->compressed_vis = NULL;
+		else
+			out->compressed_vis = loadmodel->visdata + p;
+		out->efrags = NULL;
+		
+		for (j=0 ; j<4 ; j++)
+			out->ambient_sound_level[j] = in->ambient_level[j];
+	}	
+}
+
+/*
+=================
+Mod_LoadClipnodes
+=================
+*/
+void Mod_LoadClipnodes (lump_t *l)
+{
+	dclipnode_t *in, *out;
+	int			i, count;
+	hull_t		*hull;
+
+	in = (void *)(mod_base + l->fileofs);
+	if (l->filelen % sizeof(*in))
+		Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
+	count = l->filelen / sizeof(*in);
+	out = Hunk_AllocName ( count*sizeof(*out), loadname);	
+
+	loadmodel->clipnodes = out;
+	loadmodel->numclipnodes = count;
+
+	hull = &loadmodel->hulls[1];
+	hull->clipnodes = out;
+	hull->firstclipnode = 0;
+	hull->lastclipnode = count-1;
+	hull->planes = loadmodel->planes;
+	hull->clip_mins[0] = -16;
+	hull->clip_mins[1] = -16;
+	hull->clip_mins[2] = -24;
+	hull->clip_maxs[0] = 16;
+	hull->clip_maxs[1] = 16;
+	hull->clip_maxs[2] = 32;
+
+	hull = &loadmodel->hulls[2];
+	hull->clipnodes = out;
+	hull->firstclipnode = 0;
+	hull->lastclipnode = count-1;
+	hull->planes = loadmodel->planes;
+	hull->clip_mins[0] = -32;
+	hull->clip_mins[1] = -32;
+	hull->clip_mins[2] = -24;
+	hull->clip_maxs[0] = 32;
+	hull->clip_maxs[1] = 32;
+	hull->clip_maxs[2] = 64;
+
+	for (i=0 ; i<count ; i++, out++, in++)
+	{
+		out->planenum = LittleLong(in->planenum);
+		out->children[0] = LittleShort(in->children[0]);
+		out->children[1] = LittleShort(in->children[1]);
+	}
+}
+
+/*
+=================
+Mod_MakeHull0
+
+Deplicate the drawing hull structure as a clipping hull
+=================
+*/
+void Mod_MakeHull0 (void)
+{
+	mnode_t		*in, *child;
+	dclipnode_t *out;
+	int			i, j, count;
+	hull_t		*hull;
+	
+	hull = &loadmodel->hulls[0];	
+	
+	in = loadmodel->nodes;
+	count = loadmodel->numnodes;
+	out = Hunk_AllocName ( count*sizeof(*out), loadname);	
+
+	hull->clipnodes = out;
+	hull->firstclipnode = 0;
+	hull->lastclipnode = count-1;
+	hull->planes = loadmodel->planes;
+
+	for (i=0 ; i<count ; i++, out++, in++)
+	{
+		out->planenum = in->plane - loadmodel->planes;
+		for (j=0 ; j<2 ; j++)
+		{
+			child = in->children[j];
+			if (child->contents < 0)
+				out->children[j] = child->contents;
+			else
+				out->children[j] = child - loadmodel->nodes;
+		}
+	}
+}
+
+/*
+=================
+Mod_LoadMarksurfaces
+=================
+*/
+void Mod_LoadMarksurfaces (lump_t *l)
+{	
+	int		i, j, count;
+	short		*in;
+	msurface_t **out;
+	
+	in = (void *)(mod_base + l->fileofs);
+	if (l->filelen % sizeof(*in))
+		Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
+	count = l->filelen / sizeof(*in);
+	out = Hunk_AllocName ( count*sizeof(*out), loadname);	
+
+	loadmodel->marksurfaces = out;
+	loadmodel->nummarksurfaces = count;
+
+	for ( i=0 ; i<count ; i++)
+	{
+		j = LittleShort(in[i]);
+		if (j >= loadmodel->numsurfaces)
+			Sys_Error ("Mod_ParseMarksurfaces: bad surface number");
+		out[i] = loadmodel->surfaces + j;
+	}
+}
+
+/*
+=================
+Mod_LoadSurfedges
+=================
+*/
+void Mod_LoadSurfedges (lump_t *l)
+{	
+	int		i, count;
+	int		*in, *out;
+	
+	in = (void *)(mod_base + l->fileofs);
+	if (l->filelen % sizeof(*in))
+		Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
+	count = l->filelen / sizeof(*in);
+	out = Hunk_AllocName ( count*sizeof(*out), loadname);	
+
+	loadmodel->surfedges = out;
+	loadmodel->numsurfedges = count;
+
+	for ( i=0 ; i<count ; i++)
+		out[i] = LittleLong (in[i]);
+}
+
+/*
+=================
+Mod_LoadPlanes
+=================
+*/
+void Mod_LoadPlanes (lump_t *l)
+{
+	int			i, j;
+	mplane_t	*out;
+	dplane_t 	*in;
+	int			count;
+	int			bits;
+	
+	in = (void *)(mod_base + l->fileofs);
+	if (l->filelen % sizeof(*in))
+		Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
+	count = l->filelen / sizeof(*in);
+	out = Hunk_AllocName ( count*2*sizeof(*out), loadname);	
+	
+	loadmodel->planes = out;
+	loadmodel->numplanes = count;
+
+	for ( i=0 ; i<count ; i++, in++, out++)
+	{
+		bits = 0;
+		for (j=0 ; j<3 ; j++)
+		{
+			out->normal[j] = LittleFloat (in->normal[j]);
+			if (out->normal[j] < 0)
+				bits |= 1<<j;
+		}
+
+		out->dist = LittleFloat (in->dist);
+		out->type = LittleLong (in->type);
+		out->signbits = bits;
+	}
+}
+
+/*
+=================
+RadiusFromBounds
+=================
+*/
+float RadiusFromBounds (vec3_t mins, vec3_t maxs)
+{
+	int		i;
+	vec3_t	corner;
+
+	for (i=0 ; i<3 ; i++)
+	{
+		corner[i] = fabs(mins[i]) > fabs(maxs[i]) ? fabs(mins[i]) : fabs(maxs[i]);
+	}
+
+	return Length (corner);
+}
+
+/*
+=================
+Mod_LoadBrushModel
+=================
+*/
+void Mod_LoadBrushModel (model_t *mod, void *buffer)
+{
+	int			i, j;
+	dheader_t	*header;
+	dmodel_t 	*bm;
+	
+	loadmodel->type = mod_brush;
+	
+	header = (dheader_t *)buffer;
+
+	i = LittleLong (header->version);
+	if (i != BSPVERSION)
+		Sys_Error ("Mod_LoadBrushModel: %s has wrong version number (%i should be %i)", mod->name, i, BSPVERSION);
+
+// swap all the lumps
+	mod_base = (byte *)header;
+
+	for (i=0 ; i<sizeof(dheader_t)/4 ; i++)
+		((int *)header)[i] = LittleLong ( ((int *)header)[i]);
+
+	mod->checksum = 0;
+	mod->checksum2 = 0;
+
+// checksum all of the map, except for entities
+	for (i = 0; i < HEADER_LUMPS; i++) {
+		if (i == LUMP_ENTITIES)
+			continue;
+		mod->checksum ^= Com_BlockChecksum(mod_base + header->lumps[i].fileofs, 
+			header->lumps[i].filelen);
+
+		if (i == LUMP_VISIBILITY || i == LUMP_LEAFS || i == LUMP_NODES)
+			continue;
+		mod->checksum2 ^= Com_BlockChecksum(mod_base + header->lumps[i].fileofs, 
+			header->lumps[i].filelen);
+	}
+	
+// load into heap
+
+	Mod_LoadVertexes (&header->lumps[LUMP_VERTEXES]);
+	Mod_LoadEdges (&header->lumps[LUMP_EDGES]);
+	Mod_LoadSurfedges (&header->lumps[LUMP_SURFEDGES]);
+	Mod_LoadTextures (&header->lumps[LUMP_TEXTURES]);
+	Mod_LoadLighting (&header->lumps[LUMP_LIGHTING]);
+	Mod_LoadPlanes (&header->lumps[LUMP_PLANES]);
+	Mod_LoadTexinfo (&header->lumps[LUMP_TEXINFO]);
+	Mod_LoadFaces (&header->lumps[LUMP_FACES]);
+	Mod_LoadMarksurfaces (&header->lumps[LUMP_MARKSURFACES]);
+	Mod_LoadVisibility (&header->lumps[LUMP_VISIBILITY]);
+	Mod_LoadLeafs (&header->lumps[LUMP_LEAFS]);
+	Mod_LoadNodes (&header->lumps[LUMP_NODES]);
+	Mod_LoadClipnodes (&header->lumps[LUMP_CLIPNODES]);
+	Mod_LoadEntities (&header->lumps[LUMP_ENTITIES]);
+	Mod_LoadSubmodels (&header->lumps[LUMP_MODELS]);
+
+	Mod_MakeHull0 ();
+	
+	mod->numframes = 2;		// regular and alternate animation
+	
+//
+// set up the submodels (FIXME: this is confusing)
+//
+	for (i=0 ; i<mod->numsubmodels ; i++)
+	{
+		bm = &mod->submodels[i];
+
+		mod->hulls[0].firstclipnode = bm->headnode[0];
+		for (j=1 ; j<MAX_MAP_HULLS ; j++)
+		{
+			mod->hulls[j].firstclipnode = bm->headnode[j];
+			mod->hulls[j].lastclipnode = mod->numclipnodes-1;
+		}
+		
+		mod->firstmodelsurface = bm->firstface;
+		mod->nummodelsurfaces = bm->numfaces;
+		mod->radius = RadiusFromBounds (mod->mins, mod->maxs);
+		
+		VectorCopy (bm->maxs, mod->maxs);
+		VectorCopy (bm->mins, mod->mins);
+	
+		mod->numleafs = bm->visleafs;
+
+		if (i < mod->numsubmodels-1)
+		{	// duplicate the basic information
+			char	name[10];
+
+			sprintf (name, "*%i", i+1);
+			loadmodel = Mod_FindName (name);
+			*loadmodel = *mod;
+			strcpy (loadmodel->name, name);
+			mod = loadmodel;
+		}
+	}
+}
+
+/*
+==============================================================================
+
+ALIAS MODELS
+
+==============================================================================
+*/
+
+/*
+=================
+Mod_LoadAliasFrame
+=================
+*/
+void * Mod_LoadAliasFrame (void * pin, int *pframeindex, int numv,
+	trivertx_t *pbboxmin, trivertx_t *pbboxmax, aliashdr_t *pheader, char *name)
+{
+	trivertx_t		*pframe, *pinframe;
+	int				i, j;
+	daliasframe_t	*pdaliasframe;
+
+	pdaliasframe = (daliasframe_t *)pin;
+
+	strcpy (name, pdaliasframe->name);
+
+	for (i=0 ; i<3 ; i++)
+	{
+	// these are byte values, so we don't have to worry about
+	// endianness
+		pbboxmin->v[i] = pdaliasframe->bboxmin.v[i];
+		pbboxmax->v[i] = pdaliasframe->bboxmax.v[i];
+	}
+
+	pinframe = (trivertx_t *)(pdaliasframe + 1);
+	pframe = Hunk_AllocName (numv * sizeof(*pframe), loadname);
+
+	*pframeindex = (byte *)pframe - (byte *)pheader;
+
+	for (j=0 ; j<numv ; j++)
+	{
+		int		k;
+
+	// these are all byte values, so no need to deal with endianness
+		pframe[j].lightnormalindex = pinframe[j].lightnormalindex;
+
+		for (k=0 ; k<3 ; k++)
+		{
+			pframe[j].v[k] = pinframe[j].v[k];
+		}
+	}
+
+	pinframe += numv;
+
+	return (void *)pinframe;
+}
+
+
+/*
+=================
+Mod_LoadAliasGroup
+=================
+*/
+void * Mod_LoadAliasGroup (void * pin, int *pframeindex, int numv,
+	trivertx_t *pbboxmin, trivertx_t *pbboxmax, aliashdr_t *pheader, char *name)
+{
+	daliasgroup_t		*pingroup;
+	maliasgroup_t		*paliasgroup;
+	int					i, numframes;
+	daliasinterval_t	*pin_intervals;
+	float				*poutintervals;
+	void				*ptemp;
+	
+	pingroup = (daliasgroup_t *)pin;
+
+	numframes = LittleLong (pingroup->numframes);
+
+	paliasgroup = Hunk_AllocName (sizeof (maliasgroup_t) +
+			(numframes - 1) * sizeof (paliasgroup->frames[0]), loadname);
+
+	paliasgroup->numframes = numframes;
+
+	for (i=0 ; i<3 ; i++)
+	{
+	// these are byte values, so we don't have to worry about endianness
+		pbboxmin->v[i] = pingroup->bboxmin.v[i];
+		pbboxmax->v[i] = pingroup->bboxmax.v[i];
+	}
+
+	*pframeindex = (byte *)paliasgroup - (byte *)pheader;
+
+	pin_intervals = (daliasinterval_t *)(pingroup + 1);
+
+	poutintervals = Hunk_AllocName (numframes * sizeof (float), loadname);
+
+	paliasgroup->intervals = (byte *)poutintervals - (byte *)pheader;
+
+	for (i=0 ; i<numframes ; i++)
+	{
+		*poutintervals = LittleFloat (pin_intervals->interval);
+		if (*poutintervals <= 0.0)
+			Sys_Error ("Mod_LoadAliasGroup: interval<=0");
+
+		poutintervals++;
+		pin_intervals++;
+	}
+
+	ptemp = (void *)pin_intervals;
+
+	for (i=0 ; i<numframes ; i++)
+	{
+		ptemp = Mod_LoadAliasFrame (ptemp,
+									&paliasgroup->frames[i].frame,
+									numv,
+									&paliasgroup->frames[i].bboxmin,
+									&paliasgroup->frames[i].bboxmax,
+									pheader, name);
+	}
+
+	return ptemp;
+}
+
+
+/*
+=================
+Mod_LoadAliasSkin
+=================
+*/
+void * Mod_LoadAliasSkin (void * pin, int *pskinindex, int skinsize,
+	aliashdr_t *pheader)
+{
+	int		i;
+	byte	*pskin, *pinskin;
+	unsigned short	*pusskin;
+
+	pskin = Hunk_AllocName (skinsize * r_pixbytes, loadname);
+	pinskin = (byte *)pin;
+	*pskinindex = (byte *)pskin - (byte *)pheader;
+
+	if (r_pixbytes == 1)
+	{
+		Q_memcpy (pskin, pinskin, skinsize);
+	}
+	else if (r_pixbytes == 2)
+	{
+		pusskin = (unsigned short *)pskin;
+
+		for (i=0 ; i<skinsize ; i++)
+			pusskin[i] = d_8to16table[pinskin[i]];
+	}
+	else
+	{
+		Sys_Error ("Mod_LoadAliasSkin: driver set invalid r_pixbytes: %d\n",
+				 r_pixbytes);
+	}
+
+	pinskin += skinsize;
+
+	return ((void *)pinskin);
+}
+
+
+/*
+=================
+Mod_LoadAliasSkinGroup
+=================
+*/
+void * Mod_LoadAliasSkinGroup (void * pin, int *pskinindex, int skinsize,
+	aliashdr_t *pheader)
+{
+	daliasskingroup_t		*pinskingroup;
+	maliasskingroup_t		*paliasskingroup;
+	int						i, numskins;
+	daliasskininterval_t	*pinskinintervals;
+	float					*poutskinintervals;
+	void					*ptemp;
+
+	pinskingroup = (daliasskingroup_t *)pin;
+
+	numskins = LittleLong (pinskingroup->numskins);
+
+	paliasskingroup = Hunk_AllocName (sizeof (maliasskingroup_t) +
+			(numskins - 1) * sizeof (paliasskingroup->skindescs[0]),
+			loadname);
+
+	paliasskingroup->numskins = numskins;
+
+	*pskinindex = (byte *)paliasskingroup - (byte *)pheader;
+
+	pinskinintervals = (daliasskininterval_t *)(pinskingroup + 1);
+
+	poutskinintervals = Hunk_AllocName (numskins * sizeof (float),loadname);
+
+	paliasskingroup->intervals = (byte *)poutskinintervals - (byte *)pheader;
+
+	for (i=0 ; i<numskins ; i++)
+	{
+		*poutskinintervals = LittleFloat (pinskinintervals->interval);
+		if (*poutskinintervals <= 0)
+			Sys_Error ("Mod_LoadAliasSkinGroup: interval<=0");
+
+		poutskinintervals++;
+		pinskinintervals++;
+	}
+
+	ptemp = (void *)pinskinintervals;
+
+	for (i=0 ; i<numskins ; i++)
+	{
+		ptemp = Mod_LoadAliasSkin (ptemp,
+				&paliasskingroup->skindescs[i].skin, skinsize, pheader);
+	}
+
+	return ptemp;
+}
+
+
+/*
+=================
+Mod_LoadAliasModel
+=================
+*/
+void Mod_LoadAliasModel (model_t *mod, void *buffer)
+{
+	int					i;
+	mdl_t				*pmodel, *pinmodel;
+	stvert_t			*pstverts, *pinstverts;
+	aliashdr_t			*pheader;
+	mtriangle_t			*ptri;
+	dtriangle_t			*pintriangles;
+	int					version, numframes, numskins;
+	int					size;
+	daliasframetype_t	*pframetype;
+	daliasskintype_t	*pskintype;
+	maliasskindesc_t	*pskindesc;
+	int					skinsize;
+	int					start, end, total;
+	
+	if (!strcmp(loadmodel->name, "progs/player.mdl") ||
+		!strcmp(loadmodel->name, "progs/eyes.mdl")) {
+		unsigned short crc;
+		byte *p;
+		int len;
+		char st[40];
+
+		CRC_Init(&crc);
+		for (len = com_filesize, p = buffer; len; len--, p++)
+			CRC_ProcessByte(&crc, *p);
+	
+		sprintf(st, "%d", (int) crc);
+		Info_SetValueForKey (cls.userinfo, 
+			!strcmp(loadmodel->name, "progs/player.mdl") ? pmodel_name : emodel_name,
+			st, MAX_INFO_STRING);
+
+		if (cls.state >= ca_connected) {
+			MSG_WriteByte (&cls.netchan.message, clc_stringcmd);
+			sprintf(st, "setinfo %s %d", 
+				!strcmp(loadmodel->name, "progs/player.mdl") ? pmodel_name : emodel_name,
+				(int)crc);
+			SZ_Print (&cls.netchan.message, st);
+		}
+	}
+
+	start = Hunk_LowMark ();
+
+	pinmodel = (mdl_t *)buffer;
+
+	version = LittleLong (pinmodel->version);
+	if (version != ALIAS_VERSION)
+		Sys_Error ("%s has wrong version number (%i should be %i)",
+				 mod->name, version, ALIAS_VERSION);
+
+//
+// allocate space for a working header, plus all the data except the frames,
+// skin and group info
+//
+	size = 	sizeof (aliashdr_t) + (LittleLong (pinmodel->numframes) - 1) *
+			 sizeof (pheader->frames[0]) +
+			sizeof (mdl_t) +
+			LittleLong (pinmodel->numverts) * sizeof (stvert_t) +
+			LittleLong (pinmodel->numtris) * sizeof (mtriangle_t);
+
+	pheader = Hunk_AllocName (size, loadname);
+	pmodel = (mdl_t *) ((byte *)&pheader[1] +
+			(LittleLong (pinmodel->numframes) - 1) *
+			 sizeof (pheader->frames[0]));
+	
+//	mod->cache.data = pheader;
+	mod->flags = LittleLong (pinmodel->flags);
+
+//
+// endian-adjust and copy the data, starting with the alias model header
+//
+	pmodel->boundingradius = LittleFloat (pinmodel->boundingradius);
+	pmodel->numskins = LittleLong (pinmodel->numskins);
+	pmodel->skinwidth = LittleLong (pinmodel->skinwidth);
+	pmodel->skinheight = LittleLong (pinmodel->skinheight);
+
+	if (pmodel->skinheight > MAX_LBM_HEIGHT)
+		Sys_Error ("model %s has a skin taller than %d", mod->name,
+				   MAX_LBM_HEIGHT);
+
+	pmodel->numverts = LittleLong (pinmodel->numverts);
+
+	if (pmodel->numverts <= 0)
+		Sys_Error ("model %s has no vertices", mod->name);
+
+	if (pmodel->numverts > MAXALIASVERTS)
+		Sys_Error ("model %s has too many vertices", mod->name);
+
+	pmodel->numtris = LittleLong (pinmodel->numtris);
+
+	if (pmodel->numtris <= 0)
+		Sys_Error ("model %s has no triangles", mod->name);
+
+	pmodel->numframes = LittleLong (pinmodel->numframes);
+	pmodel->size = LittleFloat (pinmodel->size) * ALIAS_BASE_SIZE_RATIO;
+	mod->synctype = LittleLong (pinmodel->synctype);
+	mod->numframes = pmodel->numframes;
+
+	for (i=0 ; i<3 ; i++)
+	{
+		pmodel->scale[i] = LittleFloat (pinmodel->scale[i]);
+		pmodel->scale_origin[i] = LittleFloat (pinmodel->scale_origin[i]);
+		pmodel->eyeposition[i] = LittleFloat (pinmodel->eyeposition[i]);
+	}
+
+	numskins = pmodel->numskins;
+	numframes = pmodel->numframes;
+
+	if (pmodel->skinwidth & 0x03)
+		Sys_Error ("Mod_LoadAliasModel: skinwidth not multiple of 4");
+
+	pheader->model = (byte *)pmodel - (byte *)pheader;
+
+//
+// load the skins
+//
+	skinsize = pmodel->skinheight * pmodel->skinwidth;
+
+	if (numskins < 1)
+		Sys_Error ("Mod_LoadAliasModel: Invalid # of skins: %d\n", numskins);
+
+	pskintype = (daliasskintype_t *)&pinmodel[1];
+
+	pskindesc = Hunk_AllocName (numskins * sizeof (maliasskindesc_t),
+								loadname);
+
+	pheader->skindesc = (byte *)pskindesc - (byte *)pheader;
+
+	for (i=0 ; i<numskins ; i++)
+	{
+		aliasskintype_t	skintype;
+
+		skintype = LittleLong (pskintype->type);
+		pskindesc[i].type = skintype;
+
+		if (skintype == ALIAS_SKIN_SINGLE)
+		{
+			pskintype = (daliasskintype_t *)
+					Mod_LoadAliasSkin (pskintype + 1,
+									   &pskindesc[i].skin,
+									   skinsize, pheader);
+		}
+		else
+		{
+			pskintype = (daliasskintype_t *)
+					Mod_LoadAliasSkinGroup (pskintype + 1,
+											&pskindesc[i].skin,
+											skinsize, pheader);
+		}
+	}
+
+//
+// set base s and t vertices
+//
+	pstverts = (stvert_t *)&pmodel[1];
+	pinstverts = (stvert_t *)pskintype;
+
+	pheader->stverts = (byte *)pstverts - (byte *)pheader;
+
+	for (i=0 ; i<pmodel->numverts ; i++)
+	{
+		pstverts[i].onseam = LittleLong (pinstverts[i].onseam);
+	// put s and t in 16.16 format
+		pstverts[i].s = LittleLong (pinstverts[i].s) << 16;
+		pstverts[i].t = LittleLong (pinstverts[i].t) << 16;
+	}
+
+//
+// set up the triangles
+//
+	ptri = (mtriangle_t *)&pstverts[pmodel->numverts];
+	pintriangles = (dtriangle_t *)&pinstverts[pmodel->numverts];
+
+	pheader->triangles = (byte *)ptri - (byte *)pheader;
+
+	for (i=0 ; i<pmodel->numtris ; i++)
+	{
+		int		j;
+
+		ptri[i].facesfront = LittleLong (pintriangles[i].facesfront);
+
+		for (j=0 ; j<3 ; j++)
+		{
+			ptri[i].vertindex[j] =
+					LittleLong (pintriangles[i].vertindex[j]);
+		}
+	}
+
+//
+// load the frames
+//
+	if (numframes < 1)
+		Sys_Error ("Mod_LoadAliasModel: Invalid # of frames: %d\n", numframes);
+
+	pframetype = (daliasframetype_t *)&pintriangles[pmodel->numtris];
+
+	for (i=0 ; i<numframes ; i++)
+	{
+		aliasframetype_t	frametype;
+
+		frametype = LittleLong (pframetype->type);
+		pheader->frames[i].type = frametype;
+
+
+		if (frametype == ALIAS_SINGLE)
+		{
+			pframetype = (daliasframetype_t *)
+					Mod_LoadAliasFrame (pframetype + 1,
+										&pheader->frames[i].frame,
+										pmodel->numverts,
+										&pheader->frames[i].bboxmin,
+										&pheader->frames[i].bboxmax,
+										pheader, pheader->frames[i].name);
+		}
+		else
+		{
+			pframetype = (daliasframetype_t *)
+					Mod_LoadAliasGroup (pframetype + 1,
+										&pheader->frames[i].frame,
+										pmodel->numverts,
+										&pheader->frames[i].bboxmin,
+										&pheader->frames[i].bboxmax,
+										pheader, pheader->frames[i].name);
+		}
+	}
+
+	mod->type = mod_alias;
+
+// FIXME: do this right
+	mod->mins[0] = mod->mins[1] = mod->mins[2] = -16;
+	mod->maxs[0] = mod->maxs[1] = mod->maxs[2] = 16;
+
+//
+// move the complete, relocatable alias model to the cache
+//	
+	end = Hunk_LowMark ();
+	total = end - start;
+	
+	Cache_Alloc (&mod->cache, total, loadname);
+	if (!mod->cache.data)
+		return;
+	memcpy (mod->cache.data, pheader, total);
+
+	Hunk_FreeToLowMark (start);
+}
+
+//=============================================================================
+
+/*
+=================
+Mod_LoadSpriteFrame
+=================
+*/
+void * Mod_LoadSpriteFrame (void * pin, mspriteframe_t **ppframe)
+{
+	dspriteframe_t		*pinframe;
+	mspriteframe_t		*pspriteframe;
+	int					i, width, height, size, origin[2];
+	unsigned short		*ppixout;
+	byte				*ppixin;
+
+	pinframe = (dspriteframe_t *)pin;
+
+	width = LittleLong (pinframe->width);
+	height = LittleLong (pinframe->height);
+	size = width * height;
+
+	pspriteframe = Hunk_AllocName (sizeof (mspriteframe_t) + size*r_pixbytes,
+								   loadname);
+
+	Q_memset (pspriteframe, 0, sizeof (mspriteframe_t) + size);
+	*ppframe = pspriteframe;
+
+	pspriteframe->width = width;
+	pspriteframe->height = height;
+	origin[0] = LittleLong (pinframe->origin[0]);
+	origin[1] = LittleLong (pinframe->origin[1]);
+
+	pspriteframe->up = origin[1];
+	pspriteframe->down = origin[1] - height;
+	pspriteframe->left = origin[0];
+	pspriteframe->right = width + origin[0];
+
+	if (r_pixbytes == 1)
+	{
+		Q_memcpy (&pspriteframe->pixels[0], (byte *)(pinframe + 1), size);
+	}
+	else if (r_pixbytes == 2)
+	{
+		ppixin = (byte *)(pinframe + 1);
+		ppixout = (unsigned short *)&pspriteframe->pixels[0];
+
+		for (i=0 ; i<size ; i++)
+			ppixout[i] = d_8to16table[ppixin[i]];
+	}
+	else
+	{
+		Sys_Error ("Mod_LoadSpriteFrame: driver set invalid r_pixbytes: %d\n",
+				 r_pixbytes);
+	}
+
+	return (void *)((byte *)pinframe + sizeof (dspriteframe_t) + size);
+}
+
+
+/*
+=================
+Mod_LoadSpriteGroup
+=================
+*/
+void * Mod_LoadSpriteGroup (void * pin, mspriteframe_t **ppframe)
+{
+	dspritegroup_t		*pingroup;
+	mspritegroup_t		*pspritegroup;
+	int					i, numframes;
+	dspriteinterval_t	*pin_intervals;
+	float				*poutintervals;
+	void				*ptemp;
+
+	pingroup = (dspritegroup_t *)pin;
+
+	numframes = LittleLong (pingroup->numframes);
+
+	pspritegroup = Hunk_AllocName (sizeof (mspritegroup_t) +
+				(numframes - 1) * sizeof (pspritegroup->frames[0]), loadname);
+
+	pspritegroup->numframes = numframes;
+
+	*ppframe = (mspriteframe_t *)pspritegroup;
+
+	pin_intervals = (dspriteinterval_t *)(pingroup + 1);
+
+	poutintervals = Hunk_AllocName (numframes * sizeof (float), loadname);
+
+	pspritegroup->intervals = poutintervals;
+
+	for (i=0 ; i<numframes ; i++)
+	{
+		*poutintervals = LittleFloat (pin_intervals->interval);
+		if (*poutintervals <= 0.0)
+			Sys_Error ("Mod_LoadSpriteGroup: interval<=0");
+
+		poutintervals++;
+		pin_intervals++;
+	}
+
+	ptemp = (void *)pin_intervals;
+
+	for (i=0 ; i<numframes ; i++)
+	{
+		ptemp = Mod_LoadSpriteFrame (ptemp, &pspritegroup->frames[i]);
+	}
+
+	return ptemp;
+}
+
+
+/*
+=================
+Mod_LoadSpriteModel
+=================
+*/
+void Mod_LoadSpriteModel (model_t *mod, void *buffer)
+{
+	int					i;
+	int					version;
+	dsprite_t			*pin;
+	msprite_t			*psprite;
+	int					numframes;
+	int					size;
+	dspriteframetype_t	*pframetype;
+	
+	pin = (dsprite_t *)buffer;
+
+	version = LittleLong (pin->version);
+	if (version != SPRITE_VERSION)
+		Sys_Error ("%s has wrong version number "
+				 "(%i should be %i)", mod->name, version, SPRITE_VERSION);
+
+	numframes = LittleLong (pin->numframes);
+
+	size = sizeof (msprite_t) +	(numframes - 1) * sizeof (psprite->frames);
+
+	psprite = Hunk_AllocName (size, loadname);
+
+	mod->cache.data = psprite;
+
+	psprite->type = LittleLong (pin->type);
+	psprite->maxwidth = LittleLong (pin->width);
+	psprite->maxheight = LittleLong (pin->height);
+	psprite->beamlength = LittleFloat (pin->beamlength);
+	mod->synctype = LittleLong (pin->synctype);
+	psprite->numframes = numframes;
+
+	mod->mins[0] = mod->mins[1] = -psprite->maxwidth/2;
+	mod->maxs[0] = mod->maxs[1] = psprite->maxwidth/2;
+	mod->mins[2] = -psprite->maxheight/2;
+	mod->maxs[2] = psprite->maxheight/2;
+	
+//
+// load the frames
+//
+	if (numframes < 1)
+		Sys_Error ("Mod_LoadSpriteModel: Invalid # of frames: %d\n", numframes);
+
+	mod->numframes = numframes;
+
+	pframetype = (dspriteframetype_t *)(pin + 1);
+
+	for (i=0 ; i<numframes ; i++)
+	{
+		spriteframetype_t	frametype;
+
+		frametype = LittleLong (pframetype->type);
+		psprite->frames[i].type = frametype;
+
+		if (frametype == SPR_SINGLE)
+		{
+			pframetype = (dspriteframetype_t *)
+					Mod_LoadSpriteFrame (pframetype + 1,
+										 &psprite->frames[i].frameptr);
+		}
+		else
+		{
+			pframetype = (dspriteframetype_t *)
+					Mod_LoadSpriteGroup (pframetype + 1,
+										 &psprite->frames[i].frameptr);
+		}
+	}
+
+	mod->type = mod_sprite;
+}
+
+//=============================================================================
+
+/*
+================
+Mod_Print
+================
+*/
+void Mod_Print (void)
+{
+	int		i;
+	model_t	*mod;
+
+	Con_Printf ("Cached models:\n");
+	for (i=0, mod=mod_known ; i < mod_numknown ; i++, mod++)
+	{
+		Con_Printf ("%8p : %s\n",mod->cache.data, mod->name);
+	}
+}
+
+
--- /dev/null
+++ b/QW/client/model.h
@@ -1,0 +1,402 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+
+#ifndef __MODEL__
+#define __MODEL__
+
+#include "modelgen.h"
+#include "spritegn.h"
+
+/*
+
+d*_t structures are on-disk representations
+m*_t structures are in-memory
+
+*/
+
+// entity effects
+
+#define	EF_BRIGHTFIELD			1
+#define	EF_MUZZLEFLASH 			2
+#define	EF_BRIGHTLIGHT 			4
+#define	EF_DIMLIGHT 			8
+#define	EF_FLAG1	 			16
+#define	EF_FLAG2	 			32
+#define EF_BLUE					64
+#define EF_RED					128
+
+/*
+==============================================================================
+
+BRUSH MODELS
+
+==============================================================================
+*/
+
+
+//
+// in memory representation
+//
+// !!! if this is changed, it must be changed in asm_draw.h too !!!
+typedef struct
+{
+	vec3_t		position;
+} mvertex_t;
+
+#define	SIDE_FRONT	0
+#define	SIDE_BACK	1
+#define	SIDE_ON		2
+
+
+// plane_t structure
+// !!! if this is changed, it must be changed in asm_i386.h too !!!
+typedef struct mplane_s
+{
+	vec3_t	normal;
+	float	dist;
+	byte	type;			// for texture axis selection and fast side tests
+	byte	signbits;		// signx + signy<<1 + signz<<1
+	byte	pad[2];
+} mplane_t;
+
+typedef struct texture_s
+{
+	char		name[16];
+	unsigned	width, height;
+	int			anim_total;				// total tenths in sequence ( 0 = no)
+	int			anim_min, anim_max;		// time for this frame min <=time< max
+	struct texture_s *anim_next;		// in the animation sequence
+	struct texture_s *alternate_anims;	// bmodels in frmae 1 use these
+	unsigned	offsets[MIPLEVELS];		// four mip maps stored
+} texture_t;
+
+
+#define	SURF_PLANEBACK		2
+#define	SURF_DRAWSKY		4
+#define SURF_DRAWSPRITE		8
+#define SURF_DRAWTURB		0x10
+#define SURF_DRAWTILED		0x20
+#define SURF_DRAWBACKGROUND	0x40
+
+// !!! if this is changed, it must be changed in asm_draw.h too !!!
+typedef struct
+{
+	unsigned short	v[2];
+	unsigned int	cachededgeoffset;
+} medge_t;
+
+typedef struct
+{
+	float		vecs[2][4];
+	float		mipadjust;
+	texture_t	*texture;
+	int			flags;
+} mtexinfo_t;
+
+typedef struct msurface_s
+{
+	int			visframe;		// should be drawn when node is crossed
+
+	int			dlightframe;
+	int			dlightbits;
+
+	mplane_t	*plane;
+	int			flags;
+
+	int			firstedge;	// look up in model->surfedges[], negative numbers
+	int			numedges;	// are backwards edges
+	
+// surface generation data
+	struct surfcache_s	*cachespots[MIPLEVELS];
+
+	short		texturemins[2];
+	short		extents[2];
+
+	mtexinfo_t	*texinfo;
+	
+// lighting info
+	byte		styles[MAXLIGHTMAPS];
+	byte		*samples;		// [numstyles*surfsize]
+} msurface_t;
+
+typedef struct mnode_s
+{
+// common with leaf
+	int			contents;		// 0, to differentiate from leafs
+	int			visframe;		// node needs to be traversed if current
+	
+	short		minmaxs[6];		// for bounding box culling
+
+	struct mnode_s	*parent;
+
+// node specific
+	mplane_t	*plane;
+	struct mnode_s	*children[2];	
+
+	unsigned short		firstsurface;
+	unsigned short		numsurfaces;
+} mnode_t;
+
+
+
+typedef struct mleaf_s
+{
+// common with node
+	int			contents;		// wil be a negative contents number
+	int			visframe;		// node needs to be traversed if current
+
+	short		minmaxs[6];		// for bounding box culling
+
+	struct mnode_s	*parent;
+
+// leaf specific
+	byte		*compressed_vis;
+	struct efrag_s	*efrags;
+
+	msurface_t	**firstmarksurface;
+	int			nummarksurfaces;
+	int			key;			// BSP sequence number for leaf's contents
+	byte		ambient_sound_level[NUM_AMBIENTS];
+} mleaf_t;
+
+// !!! if this is changed, it must be changed in asm_i386.h too !!!
+typedef struct
+{
+	dclipnode_t	*clipnodes;
+	mplane_t	*planes;
+	int			firstclipnode;
+	int			lastclipnode;
+	vec3_t		clip_mins;
+	vec3_t		clip_maxs;
+} hull_t;
+
+/*
+==============================================================================
+
+SPRITE MODELS
+
+==============================================================================
+*/
+
+
+// FIXME: shorten these?
+typedef struct mspriteframe_s
+{
+	int		width;
+	int		height;
+	void	*pcachespot;			// remove?
+	float	up, down, left, right;
+	byte	pixels[4];
+} mspriteframe_t;
+
+typedef struct
+{
+	int				numframes;
+	float			*intervals;
+	mspriteframe_t	*frames[1];
+} mspritegroup_t;
+
+typedef struct
+{
+	spriteframetype_t	type;
+	mspriteframe_t		*frameptr;
+} mspriteframedesc_t;
+
+typedef struct
+{
+	int					type;
+	int					maxwidth;
+	int					maxheight;
+	int					numframes;
+	float				beamlength;		// remove?
+	void				*cachespot;		// remove?
+	mspriteframedesc_t	frames[1];
+} msprite_t;
+
+
+/*
+==============================================================================
+
+ALIAS MODELS
+
+Alias models are position independent, so the cache manager can move them.
+==============================================================================
+*/
+
+typedef struct
+{
+	aliasframetype_t	type;
+	trivertx_t			bboxmin;
+	trivertx_t			bboxmax;
+	int					frame;
+	char				name[16];
+} maliasframedesc_t;
+
+typedef struct
+{
+	aliasskintype_t		type;
+	void				*pcachespot;
+	int					skin;
+} maliasskindesc_t;
+
+typedef struct
+{
+	trivertx_t			bboxmin;
+	trivertx_t			bboxmax;
+	int					frame;
+} maliasgroupframedesc_t;
+
+typedef struct
+{
+	int						numframes;
+	int						intervals;
+	maliasgroupframedesc_t	frames[1];
+} maliasgroup_t;
+
+typedef struct
+{
+	int					numskins;
+	int					intervals;
+	maliasskindesc_t	skindescs[1];
+} maliasskingroup_t;
+
+// !!! if this is changed, it must be changed in asm_draw.h too !!!
+typedef struct mtriangle_s {
+	int					facesfront;
+	int					vertindex[3];
+} mtriangle_t;
+
+typedef struct {
+	int					model;
+	int					stverts;
+	int					skindesc;
+	int					triangles;
+	maliasframedesc_t	frames[1];
+} aliashdr_t;
+
+//===================================================================
+
+//
+// Whole model
+//
+
+typedef enum {mod_brush, mod_sprite, mod_alias} modtype_t;
+
+#define	EF_ROCKET	1			// leave a trail
+#define	EF_GRENADE	2			// leave a trail
+#define	EF_GIB		4			// leave a trail
+#define	EF_ROTATE	8			// rotate (bonus items)
+#define	EF_TRACER	16			// green split trail
+#define	EF_ZOMGIB	32			// small blood trail
+#define	EF_TRACER2	64			// orange split trail + rotate
+#define	EF_TRACER3	128			// purple trail
+
+typedef struct model_s
+{
+	char		name[MAX_QPATH];
+	qboolean	needload;		// bmodels and sprites don't cache normally
+
+	modtype_t	type;
+	int			numframes;
+	synctype_t	synctype;
+	
+	int			flags;
+
+//
+// volume occupied by the model graphics
+//		
+	vec3_t		mins, maxs;
+	float		radius;
+
+//
+// solid volume for clipping (sent from server)
+//
+	qboolean	clipbox;
+	vec3_t		clipmins, clipmaxs;
+
+//
+// brush model
+//
+	int			firstmodelsurface, nummodelsurfaces;
+
+	int			numsubmodels;
+	dmodel_t	*submodels;
+
+	int			numplanes;
+	mplane_t	*planes;
+
+	int			numleafs;		// number of visible leafs, not counting 0
+	mleaf_t		*leafs;
+
+	int			numvertexes;
+	mvertex_t	*vertexes;
+
+	int			numedges;
+	medge_t		*edges;
+
+	int			numnodes;
+	mnode_t		*nodes;
+
+	int			numtexinfo;
+	mtexinfo_t	*texinfo;
+
+	int			numsurfaces;
+	msurface_t	*surfaces;
+
+	int			numsurfedges;
+	int			*surfedges;
+
+	int			numclipnodes;
+	dclipnode_t	*clipnodes;
+
+	int			nummarksurfaces;
+	msurface_t	**marksurfaces;
+
+	hull_t		hulls[MAX_MAP_HULLS];
+
+	int			numtextures;
+	texture_t	**textures;
+
+	byte		*visdata;
+	byte		*lightdata;
+	char		*entities;
+
+	unsigned	checksum;		// for world models only
+	unsigned	checksum2;		// for world models only
+
+//
+// additional model data
+//
+	cache_user_t	cache;		// only access through Mod_Extradata
+
+} model_t;
+
+//============================================================================
+
+void	Mod_Init (void);
+void	Mod_ClearAll (void);
+model_t *Mod_ForName (char *name, qboolean crash);
+void	*Mod_Extradata (model_t *mod);	// handles caching
+void	Mod_TouchModel (char *name);
+
+mleaf_t *Mod_PointInLeaf (float *p, model_t *model);
+byte	*Mod_LeafPVS (mleaf_t *leaf, model_t *model);
+
+#endif	// __MODEL__
--- /dev/null
+++ b/QW/client/modelgen.h
@@ -1,0 +1,134 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+//
+// modelgen.h: header file for model generation program
+//
+
+// *********************************************************
+// * This file must be identical in the modelgen directory *
+// * and in the Quake directory, because it's used to      *
+// * pass data from one to the other via model files.      *
+// *********************************************************
+
+#ifdef INCLUDELIBS
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+#include <string.h>
+
+#include "cmdlib.h"
+#include "scriplib.h"
+#include "trilib.h"
+#include "lbmlib.h"
+#include "mathlib.h"
+
+#endif
+
+#define ALIAS_VERSION	6
+
+#define ALIAS_ONSEAM				0x0020
+
+// must match definition in spritegn.h
+#ifndef SYNCTYPE_T
+#define SYNCTYPE_T
+typedef enum {ST_SYNC=0, ST_RAND } synctype_t;
+#endif
+
+typedef enum { ALIAS_SINGLE=0, ALIAS_GROUP } aliasframetype_t;
+
+typedef enum { ALIAS_SKIN_SINGLE=0, ALIAS_SKIN_GROUP } aliasskintype_t;
+
+typedef struct {
+	int			ident;
+	int			version;
+	vec3_t		scale;
+	vec3_t		scale_origin;
+	float		boundingradius;
+	vec3_t		eyeposition;
+	int			numskins;
+	int			skinwidth;
+	int			skinheight;
+	int			numverts;
+	int			numtris;
+	int			numframes;
+	synctype_t	synctype;
+	int			flags;
+	float		size;
+} mdl_t;
+
+// TODO: could be shorts
+
+typedef struct {
+	int		onseam;
+	int		s;
+	int		t;
+} stvert_t;
+
+typedef struct dtriangle_s {
+	int					facesfront;
+	int					vertindex[3];
+} dtriangle_t;
+
+#define DT_FACES_FRONT				0x0010
+
+// This mirrors trivert_t in trilib.h, is present so Quake knows how to
+// load this data
+
+typedef struct {
+	byte	v[3];
+	byte	lightnormalindex;
+} trivertx_t;
+
+typedef struct {
+	trivertx_t	bboxmin;	// lightnormal isn't used
+	trivertx_t	bboxmax;	// lightnormal isn't used
+	char		name[16];	// frame name from grabbing
+} daliasframe_t;
+
+typedef struct {
+	int			numframes;
+	trivertx_t	bboxmin;	// lightnormal isn't used
+	trivertx_t	bboxmax;	// lightnormal isn't used
+} daliasgroup_t;
+
+typedef struct {
+	int			numskins;
+} daliasskingroup_t;
+
+typedef struct {
+	float	interval;
+} daliasinterval_t;
+
+typedef struct {
+	float	interval;
+} daliasskininterval_t;
+
+typedef struct {
+	aliasframetype_t	type;
+} daliasframetype_t;
+
+typedef struct {
+	aliasskintype_t	type;
+} daliasskintype_t;
+
+#define IDPOLYHEADER	(('O'<<24)+('P'<<16)+('D'<<8)+'I')
+														// little-endian "IDPO"
+
--- /dev/null
+++ b/QW/client/net.h
@@ -1,0 +1,112 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// net.h -- quake's interface to the networking layer
+
+#define	PORT_ANY	-1
+
+typedef struct
+{
+	byte	ip[4];
+	unsigned short	port;
+	unsigned short	pad;
+} netadr_t;
+
+extern	netadr_t	net_local_adr;
+extern	netadr_t	net_from;		// address of who sent the packet
+extern	sizebuf_t	net_message;
+
+extern	cvar_t	hostname;
+
+extern	int		net_socket;
+
+void		NET_Init (int port);
+void		NET_Shutdown (void);
+qboolean	NET_GetPacket (void);
+void		NET_SendPacket (int length, void *data, netadr_t to);
+
+qboolean	NET_CompareAdr (netadr_t a, netadr_t b);
+qboolean	NET_CompareBaseAdr (netadr_t a, netadr_t b);
+char		*NET_AdrToString (netadr_t a);
+char		*NET_BaseAdrToString (netadr_t a);
+qboolean	NET_StringToAdr (char *s, netadr_t *a);
+qboolean NET_IsClientLegal(netadr_t *adr);
+
+//============================================================================
+
+#define	OLD_AVG		0.99		// total = oldtotal*OLD_AVG + new*(1-OLD_AVG)
+
+#define	MAX_LATENT	32
+
+typedef struct
+{
+	qboolean	fatal_error;
+
+	float		last_received;		// for timeouts
+
+// the statistics are cleared at each client begin, because
+// the server connecting process gives a bogus picture of the data
+	float		frame_latency;		// rolling average
+	float		frame_rate;
+
+	int			drop_count;			// dropped packets, cleared each level
+	int			good_count;			// cleared each level
+
+	netadr_t	remote_address;
+	int			qport;
+
+// bandwidth estimator
+	double		cleartime;			// if realtime > nc->cleartime, free to go
+	double		rate;				// seconds / byte
+
+// sequencing variables
+	int			incoming_sequence;
+	int			incoming_acknowledged;
+	int			incoming_reliable_acknowledged;	// single bit
+
+	int			incoming_reliable_sequence;		// single bit, maintained local
+
+	int			outgoing_sequence;
+	int			reliable_sequence;			// single bit
+	int			last_reliable_sequence;		// sequence number of last send
+
+// reliable staging and holding areas
+	sizebuf_t	message;		// writing buffer to send to server
+	byte		message_buf[MAX_MSGLEN];
+
+	int			reliable_length;
+	byte		reliable_buf[MAX_MSGLEN];	// unacked reliable message
+
+// time and size data to calculate bandwidth
+	int			outgoing_size[MAX_LATENT];
+	double		outgoing_time[MAX_LATENT];
+} netchan_t;
+
+extern	int	net_drop;		// packets dropped before this one
+
+void Netchan_Init (void);
+void Netchan_Transmit (netchan_t *chan, int length, byte *data);
+void Netchan_OutOfBand (netadr_t adr, int length, byte *data);
+void Netchan_OutOfBandPrint (netadr_t adr, char *format, ...);
+qboolean Netchan_Process (netchan_t *chan);
+void Netchan_Setup (netchan_t *chan, netadr_t adr, int qport);
+
+qboolean Netchan_CanPacket (netchan_t *chan);
+qboolean Netchan_CanReliable (netchan_t *chan);
+
--- /dev/null
+++ b/QW/client/net_chan.c
@@ -1,0 +1,452 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+
+#include "quakedef.h"
+
+#ifdef _WIN32
+#include "winquake.h"
+#endif
+
+#define	PACKET_HEADER	8
+
+/*
+
+packet header
+-------------
+31	sequence
+1	does this message contain a reliable payload
+31	acknowledge sequence
+1	acknowledge receipt of even/odd message
+16  qport
+
+The remote connection never knows if it missed a reliable message, the
+local side detects that it has been dropped by seeing a sequence acknowledge
+higher thatn the last reliable sequence, but without the correct evon/odd
+bit for the reliable set.
+
+If the sender notices that a reliable message has been dropped, it will be
+retransmitted.  It will not be retransmitted again until a message after
+the retransmit has been acknowledged and the reliable still failed to get there.
+
+if the sequence number is -1, the packet should be handled without a netcon
+
+The reliable message can be added to at any time by doing
+MSG_Write* (&netchan->message, <data>).
+
+If the message buffer is overflowed, either by a single message, or by
+multiple frames worth piling up while the last reliable transmit goes
+unacknowledged, the netchan signals a fatal error.
+
+Reliable messages are allways placed first in a packet, then the unreliable
+message is included if there is sufficient room.
+
+To the receiver, there is no distinction between the reliable and unreliable
+parts of the message, they are just processed out as a single larger message.
+
+Illogical packet sequence numbers cause the packet to be dropped, but do
+not kill the connection.  This, combined with the tight window of valid
+reliable acknowledgement numbers provides protection against malicious
+address spoofing.
+
+The qport field is a workaround for bad address translating routers that
+sometimes remap the client's source port on a packet during gameplay.
+
+If the base part of the net address matches and the qport matches, then the
+channel matches even if the IP port differs.  The IP port should be updated
+to the new value before sending out any replies.
+
+
+*/
+
+int		net_drop;
+cvar_t	showpackets = {"showpackets", "0"};
+cvar_t	showdrop = {"showdrop", "0"};
+cvar_t	qport = {"qport", "0"};
+
+/*
+===============
+Netchan_Init
+
+===============
+*/
+void Netchan_Init (void)
+{
+	int		port;
+
+	// pick a port value that should be nice and random
+#ifdef _WIN32
+	port = ((int)(timeGetTime()*1000) * time(NULL)) & 0xffff;
+#else
+	port = ((int)(getpid()+getuid()*1000) * time(NULL)) & 0xffff;
+#endif
+
+	Cvar_RegisterVariable (&showpackets);
+	Cvar_RegisterVariable (&showdrop);
+	Cvar_RegisterVariable (&qport);
+	Cvar_SetValue("qport", port);
+}
+
+/*
+===============
+Netchan_OutOfBand
+
+Sends an out-of-band datagram
+================
+*/
+void Netchan_OutOfBand (netadr_t adr, int length, byte *data)
+{
+	sizebuf_t	send;
+	byte		send_buf[MAX_MSGLEN + PACKET_HEADER];
+
+// write the packet header
+	send.data = send_buf;
+	send.maxsize = sizeof(send_buf);
+	send.cursize = 0;
+	
+	MSG_WriteLong (&send, -1);	// -1 sequence means out of band
+	SZ_Write (&send, data, length);
+
+// send the datagram
+	//zoid, no input in demo playback mode
+#ifndef SERVERONLY
+	if (!cls.demoplayback)
+#endif
+		NET_SendPacket (send.cursize, send.data, adr);
+}
+
+/*
+===============
+Netchan_OutOfBandPrint
+
+Sends a text message in an out-of-band datagram
+================
+*/
+void Netchan_OutOfBandPrint (netadr_t adr, char *format, ...)
+{
+	va_list		argptr;
+	static char		string[8192];		// ??? why static?
+	
+	va_start (argptr, format);
+	vsprintf (string, format,argptr);
+	va_end (argptr);
+
+
+	Netchan_OutOfBand (adr, strlen(string), (byte *)string);
+}
+
+
+/*
+==============
+Netchan_Setup
+
+called to open a channel to a remote system
+==============
+*/
+void Netchan_Setup (netchan_t *chan, netadr_t adr, int qport)
+{
+	memset (chan, 0, sizeof(*chan));
+	
+	chan->remote_address = adr;
+	chan->last_received = realtime;
+	
+	chan->message.data = chan->message_buf;
+	chan->message.allowoverflow = true;
+	chan->message.maxsize = sizeof(chan->message_buf);
+
+	chan->qport = qport;
+	
+	chan->rate = 1.0/2500;
+}
+
+
+/*
+===============
+Netchan_CanPacket
+
+Returns true if the bandwidth choke isn't active
+================
+*/
+#define	MAX_BACKUP	200
+qboolean Netchan_CanPacket (netchan_t *chan)
+{
+	if (chan->cleartime < realtime + MAX_BACKUP*chan->rate)
+		return true;
+	return false;
+}
+
+
+/*
+===============
+Netchan_CanReliable
+
+Returns true if the bandwidth choke isn't 
+================
+*/
+qboolean Netchan_CanReliable (netchan_t *chan)
+{
+	if (chan->reliable_length)
+		return false;			// waiting for ack
+	return Netchan_CanPacket (chan);
+}
+
+#ifdef SERVERONLY
+qboolean ServerPaused(void);
+#endif
+
+/*
+===============
+Netchan_Transmit
+
+tries to send an unreliable message to a connection, and handles the
+transmition / retransmition of the reliable messages.
+
+A 0 length will still generate a packet and deal with the reliable messages.
+================
+*/
+void Netchan_Transmit (netchan_t *chan, int length, byte *data)
+{
+	sizebuf_t	send;
+	byte		send_buf[MAX_MSGLEN + PACKET_HEADER];
+	qboolean	send_reliable;
+	unsigned	w1, w2;
+	int			i;
+
+// check for message overflow
+	if (chan->message.overflowed)
+	{
+		chan->fatal_error = true;
+		Con_Printf ("%s:Outgoing message overflow\n"
+			, NET_AdrToString (chan->remote_address));
+		return;
+	}
+
+// if the remote side dropped the last reliable message, resend it
+	send_reliable = false;
+
+	if (chan->incoming_acknowledged > chan->last_reliable_sequence
+	&& chan->incoming_reliable_acknowledged != chan->reliable_sequence)
+		send_reliable = true;
+
+// if the reliable transmit buffer is empty, copy the current message out
+	if (!chan->reliable_length && chan->message.cursize)
+	{
+		memcpy (chan->reliable_buf, chan->message_buf, chan->message.cursize);
+		chan->reliable_length = chan->message.cursize;
+		chan->message.cursize = 0;
+		chan->reliable_sequence ^= 1;
+		send_reliable = true;
+	}
+
+// write the packet header
+	send.data = send_buf;
+	send.maxsize = sizeof(send_buf);
+	send.cursize = 0;
+
+	w1 = chan->outgoing_sequence | (send_reliable<<31);
+	w2 = chan->incoming_sequence | (chan->incoming_reliable_sequence<<31);
+
+	chan->outgoing_sequence++;
+
+	MSG_WriteLong (&send, w1);
+	MSG_WriteLong (&send, w2);
+
+	// send the qport if we are a client
+#ifndef SERVERONLY
+	MSG_WriteShort (&send, cls.qport);
+#endif
+
+// copy the reliable message to the packet first
+	if (send_reliable)
+	{
+		SZ_Write (&send, chan->reliable_buf, chan->reliable_length);
+		chan->last_reliable_sequence = chan->outgoing_sequence;
+	}
+	
+// add the unreliable part if space is available
+	if (send.maxsize - send.cursize >= length)
+		SZ_Write (&send, data, length);
+
+// send the datagram
+	i = chan->outgoing_sequence & (MAX_LATENT-1);
+	chan->outgoing_size[i] = send.cursize;
+	chan->outgoing_time[i] = realtime;
+
+	//zoid, no input in demo playback mode
+#ifndef SERVERONLY
+	if (!cls.demoplayback)
+#endif
+		NET_SendPacket (send.cursize, send.data, chan->remote_address);
+
+	if (chan->cleartime < realtime)
+		chan->cleartime = realtime + send.cursize*chan->rate;
+	else
+		chan->cleartime += send.cursize*chan->rate;
+#ifdef SERVERONLY
+	if (ServerPaused())
+		chan->cleartime = realtime;
+#endif
+
+	if (showpackets.value)
+		Con_Printf ("--> s=%i(%i) a=%i(%i) %i\n"
+			, chan->outgoing_sequence
+			, send_reliable
+			, chan->incoming_sequence
+			, chan->incoming_reliable_sequence
+			, send.cursize);
+
+}
+
+/*
+=================
+Netchan_Process
+
+called when the current net_message is from remote_address
+modifies net_message so that it points to the packet payload
+=================
+*/
+qboolean Netchan_Process (netchan_t *chan)
+{
+	unsigned		sequence, sequence_ack;
+	unsigned		reliable_ack, reliable_message;
+#ifdef SERVERONLY
+	int			qport;
+#endif
+	int i;
+
+	if (
+#ifndef SERVERONLY
+			!cls.demoplayback && 
+#endif
+			!NET_CompareAdr (net_from, chan->remote_address))
+		return false;
+	
+// get sequence numbers		
+	MSG_BeginReading ();
+	sequence = MSG_ReadLong ();
+	sequence_ack = MSG_ReadLong ();
+
+	// read the qport if we are a server
+#ifdef SERVERONLY
+	qport = MSG_ReadShort ();
+#endif
+
+	reliable_message = sequence >> 31;
+	reliable_ack = sequence_ack >> 31;
+
+	sequence &= ~(1<<31);	
+	sequence_ack &= ~(1<<31);	
+
+	if (showpackets.value)
+		Con_Printf ("<-- s=%i(%i) a=%i(%i) %i\n"
+			, sequence
+			, reliable_message
+			, sequence_ack
+			, reliable_ack
+			, net_message.cursize);
+
+// get a rate estimation
+#if 0
+	if (chan->outgoing_sequence - sequence_ack < MAX_LATENT)
+	{
+		int				i;
+		double			time, rate;
+	
+		i = sequence_ack & (MAX_LATENT - 1);
+		time = realtime - chan->outgoing_time[i];
+		time -= 0.1;	// subtract 100 ms
+		if (time <= 0)
+		{	// gotta be a digital link for <100 ms ping
+			if (chan->rate > 1.0/5000)
+				chan->rate = 1.0/5000;
+		}
+		else
+		{
+			if (chan->outgoing_size[i] < 512)
+			{	// only deal with small messages
+				rate = chan->outgoing_size[i]/time;
+				if (rate > 5000)
+					rate = 5000;
+				rate = 1.0/rate;
+				if (chan->rate > rate)
+					chan->rate = rate;
+			}
+		}
+	}
+#endif
+
+//
+// discard stale or duplicated packets
+//
+	if (sequence <= (unsigned)chan->incoming_sequence)
+	{
+		if (showdrop.value)
+			Con_Printf ("%s:Out of order packet %i at %i\n"
+				, NET_AdrToString (chan->remote_address)
+				,  sequence
+				, chan->incoming_sequence);
+		return false;
+	}
+
+//
+// dropped packets don't keep the message from being used
+//
+	net_drop = sequence - (chan->incoming_sequence+1);
+	if (net_drop > 0)
+	{
+		chan->drop_count += 1;
+
+		if (showdrop.value)
+			Con_Printf ("%s:Dropped %i packets at %i\n"
+			, NET_AdrToString (chan->remote_address)
+			, sequence-(chan->incoming_sequence+1)
+			, sequence);
+	}
+
+//
+// if the current outgoing reliable message has been acknowledged
+// clear the buffer to make way for the next
+//
+	if (reliable_ack == (unsigned)chan->reliable_sequence)
+		chan->reliable_length = 0;	// it has been received
+	
+//
+// if this message contains a reliable message, bump incoming_reliable_sequence 
+//
+	chan->incoming_sequence = sequence;
+	chan->incoming_acknowledged = sequence_ack;
+	chan->incoming_reliable_acknowledged = reliable_ack;
+	if (reliable_message)
+		chan->incoming_reliable_sequence ^= 1;
+
+//
+// the message can now be read from the current message pointer
+// update statistics counters
+//
+	chan->frame_latency = chan->frame_latency*OLD_AVG
+		+ (chan->outgoing_sequence-sequence_ack)*(1.0-OLD_AVG);
+	chan->frame_rate = chan->frame_rate*OLD_AVG
+		+ (realtime-chan->last_received)*(1.0-OLD_AVG);		
+	chan->good_count += 1;
+
+	chan->last_received = realtime;
+
+	return true;
+}
+
--- /dev/null
+++ b/QW/client/net_udp.c
@@ -1,0 +1,318 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// net_main.c
+
+#include "quakedef.h"
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <sys/param.h>
+#include <sys/ioctl.h>
+#include <sys/uio.h>
+#include <arpa/inet.h>
+#include <errno.h>
+
+#if defined(sun)
+#include <unistd.h>
+#endif
+
+#ifdef sun
+#include <sys/filio.h>
+#endif
+
+#ifdef NeXT
+#include <libc.h>
+#endif
+
+netadr_t	net_local_adr;
+
+netadr_t	net_from;
+sizebuf_t	net_message;
+int			net_socket;			// non blocking, for receives
+int			net_send_socket;	// blocking, for sends
+
+#define	MAX_UDP_PACKET	8192
+byte		net_message_buffer[MAX_UDP_PACKET];
+
+int gethostname (char *, int);
+int close (int);
+
+//=============================================================================
+
+void NetadrToSockadr (netadr_t *a, struct sockaddr_in *s)
+{
+	memset (s, 0, sizeof(*s));
+	s->sin_family = AF_INET;
+
+	*(int *)&s->sin_addr = *(int *)&a->ip;
+	s->sin_port = a->port;
+}
+
+void SockadrToNetadr (struct sockaddr_in *s, netadr_t *a)
+{
+	*(int *)&a->ip = *(int *)&s->sin_addr;
+	a->port = s->sin_port;
+}
+
+qboolean	NET_CompareBaseAdr (netadr_t a, netadr_t b)
+{
+	if (a.ip[0] == b.ip[0] && a.ip[1] == b.ip[1] && a.ip[2] == b.ip[2] && a.ip[3] == b.ip[3])
+		return true;
+	return false;
+}
+
+
+qboolean	NET_CompareAdr (netadr_t a, netadr_t b)
+{
+	if (a.ip[0] == b.ip[0] && a.ip[1] == b.ip[1] && a.ip[2] == b.ip[2] && a.ip[3] == b.ip[3] && a.port == b.port)
+		return true;
+	return false;
+}
+
+char	*NET_AdrToString (netadr_t a)
+{
+	static	char	s[64];
+	
+	sprintf (s, "%i.%i.%i.%i:%i", a.ip[0], a.ip[1], a.ip[2], a.ip[3], ntohs(a.port));
+
+	return s;
+}
+
+char	*NET_BaseAdrToString (netadr_t a)
+{
+	static	char	s[64];
+	
+	sprintf (s, "%i.%i.%i.%i", a.ip[0], a.ip[1], a.ip[2], a.ip[3]);
+
+	return s;
+}
+
+/*
+=============
+NET_StringToAdr
+
+idnewt
+idnewt:28000
+192.246.40.70
+192.246.40.70:28000
+=============
+*/
+qboolean	NET_StringToAdr (char *s, netadr_t *a)
+{
+	struct hostent	*h;
+	struct sockaddr_in sadr;
+	char	*colon;
+	char	copy[128];
+	
+	
+	memset (&sadr, 0, sizeof(sadr));
+	sadr.sin_family = AF_INET;
+	
+	sadr.sin_port = 0;
+
+	strcpy (copy, s);
+	// strip off a trailing :port if present
+	for (colon = copy ; *colon ; colon++)
+		if (*colon == ':')
+		{
+			*colon = 0;
+			sadr.sin_port = htons(atoi(colon+1));	
+		}
+	
+	if (copy[0] >= '0' && copy[0] <= '9')
+	{
+		*(int *)&sadr.sin_addr = inet_addr(copy);
+	}
+	else
+	{
+		if (! (h = gethostbyname(copy)) )
+			return 0;
+		*(int *)&sadr.sin_addr = *(int *)h->h_addr_list[0];
+	}
+	
+	SockadrToNetadr (&sadr, a);
+
+	return true;
+}
+
+// Returns true if we can't bind the address locally--in other words, 
+// the IP is NOT one of our interfaces.
+qboolean NET_IsClientLegal(netadr_t *adr)
+{
+	struct sockaddr_in sadr;
+	int newsocket;
+
+#if 0
+	if (adr->ip[0] == 127)
+		return false; // no local connections period
+
+	NetadrToSockadr (adr, &sadr);
+
+	if ((newsocket = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
+		Sys_Error ("NET_IsClientLegal: socket:", strerror(errno));
+
+	sadr.sin_port = 0;
+
+	if( bind (newsocket, (void *)&sadr, sizeof(sadr)) == -1) 
+	{
+		// It is not a local address
+		close(newsocket);
+		return true;
+	}
+	close(newsocket);
+	return false;
+#else
+	return true;
+#endif
+}
+
+
+//=============================================================================
+
+qboolean NET_GetPacket (void)
+{
+	int 	ret;
+	struct sockaddr_in	from;
+	int		fromlen;
+
+	fromlen = sizeof(from);
+	ret = recvfrom (net_socket, net_message_buffer, sizeof(net_message_buffer), 0, (struct sockaddr *)&from, &fromlen);
+	if (ret == -1) {
+		if (errno == EWOULDBLOCK)
+			return false;
+		if (errno == ECONNREFUSED)
+			return false;
+		Sys_Printf ("NET_GetPacket: %s\n", strerror(errno));
+		return false;
+	}
+
+	net_message.cursize = ret;
+	SockadrToNetadr (&from, &net_from);
+
+	return ret;
+}
+
+//=============================================================================
+
+void NET_SendPacket (int length, void *data, netadr_t to)
+{
+	int ret;
+	struct sockaddr_in	addr;
+
+	NetadrToSockadr (&to, &addr);
+
+	ret = sendto (net_socket, data, length, 0, (struct sockaddr *)&addr, sizeof(addr) );
+	if (ret == -1) {
+		if (errno == EWOULDBLOCK)
+			return;
+		if (errno == ECONNREFUSED)
+			return;
+		Sys_Printf ("NET_SendPacket: %s\n", strerror(errno));
+	}
+}
+
+//=============================================================================
+
+int UDP_OpenSocket (int port)
+{
+	int newsocket;
+	struct sockaddr_in address;
+	qboolean _true = true;
+	int i;
+
+	if ((newsocket = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
+		Sys_Error ("UDP_OpenSocket: socket:", strerror(errno));
+	if (ioctl (newsocket, FIONBIO, (char *)&_true) == -1)
+		Sys_Error ("UDP_OpenSocket: ioctl FIONBIO:", strerror(errno));
+	address.sin_family = AF_INET;
+//ZOID -- check for interface binding option
+	if ((i = COM_CheckParm("-ip")) != 0 && i < com_argc) {
+		address.sin_addr.s_addr = inet_addr(com_argv[i+1]);
+		Con_Printf("Binding to IP Interface Address of %s\n",
+				inet_ntoa(address.sin_addr));
+	} else
+		address.sin_addr.s_addr = INADDR_ANY;
+	if (port == PORT_ANY)
+		address.sin_port = 0;
+	else
+		address.sin_port = htons((short)port);
+	if( bind (newsocket, (void *)&address, sizeof(address)) == -1)
+		Sys_Error ("UDP_OpenSocket: bind: %s", strerror(errno));
+
+	return newsocket;
+}
+
+void NET_GetLocalAddress (void)
+{
+	char	buff[MAXHOSTNAMELEN];
+	struct sockaddr_in	address;
+	int		namelen;
+
+	gethostname(buff, MAXHOSTNAMELEN);
+	buff[MAXHOSTNAMELEN-1] = 0;
+
+	NET_StringToAdr (buff, &net_local_adr);
+
+	namelen = sizeof(address);
+	if (getsockname (net_socket, (struct sockaddr *)&address, &namelen) == -1)
+		Sys_Error ("NET_Init: getsockname:", strerror(errno));
+	net_local_adr.port = address.sin_port;
+
+	Con_Printf("IP address %s\n", NET_AdrToString (net_local_adr) );
+}
+
+/*
+====================
+NET_Init
+====================
+*/
+void NET_Init (int port)
+{
+	//
+	// open the single socket to be used for all communications
+	//
+	net_socket = UDP_OpenSocket (port);
+
+	//
+	// init the message buffer
+	//
+	net_message.maxsize = sizeof(net_message_buffer);
+	net_message.data = net_message_buffer;
+
+	//
+	// determine my name & address
+	//
+	NET_GetLocalAddress ();
+
+	Con_Printf("UDP Initialized\n");
+}
+
+/*
+====================
+NET_Shutdown
+====================
+*/
+void	NET_Shutdown (void)
+{
+	close (net_socket);
+}
+
--- /dev/null
+++ b/QW/client/net_wins.c
@@ -1,0 +1,328 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// net_wins.c
+
+#include "quakedef.h"
+#include "winquake.h"
+
+netadr_t	net_local_adr;
+
+netadr_t	net_from;
+sizebuf_t	net_message;
+int			net_socket;
+
+#define	MAX_UDP_PACKET	(MAX_MSGLEN*2)	// one more than msg + header
+byte		net_message_buffer[MAX_UDP_PACKET];
+
+WSADATA		winsockdata;
+
+//=============================================================================
+
+void NetadrToSockadr (netadr_t *a, struct sockaddr_in *s)
+{
+	memset (s, 0, sizeof(*s));
+	s->sin_family = AF_INET;
+
+	*(int *)&s->sin_addr = *(int *)&a->ip;
+	s->sin_port = a->port;
+}
+
+void SockadrToNetadr (struct sockaddr_in *s, netadr_t *a)
+{
+	*(int *)&a->ip = *(int *)&s->sin_addr;
+	a->port = s->sin_port;
+}
+
+qboolean	NET_CompareBaseAdr (netadr_t a, netadr_t b)
+{
+	if (a.ip[0] == b.ip[0] && a.ip[1] == b.ip[1] && a.ip[2] == b.ip[2] && a.ip[3] == b.ip[3])
+		return true;
+	return false;
+}
+
+qboolean	NET_CompareAdr (netadr_t a, netadr_t b)
+{
+	if (a.ip[0] == b.ip[0] && a.ip[1] == b.ip[1] && a.ip[2] == b.ip[2] && a.ip[3] == b.ip[3] && a.port == b.port)
+		return true;
+	return false;
+}
+
+char	*NET_AdrToString (netadr_t a)
+{
+	static	char	s[64];
+	
+	sprintf (s, "%i.%i.%i.%i:%i", a.ip[0], a.ip[1], a.ip[2], a.ip[3], ntohs(a.port));
+
+	return s;
+}
+
+char	*NET_BaseAdrToString (netadr_t a)
+{
+	static	char	s[64];
+	
+	sprintf (s, "%i.%i.%i.%i", a.ip[0], a.ip[1], a.ip[2], a.ip[3]);
+
+	return s;
+}
+
+/*
+=============
+NET_StringToAdr
+
+idnewt
+idnewt:28000
+192.246.40.70
+192.246.40.70:28000
+=============
+*/
+qboolean	NET_StringToAdr (char *s, netadr_t *a)
+{
+	struct hostent	*h;
+	struct sockaddr_in sadr;
+	char	*colon;
+	char	copy[128];
+	
+	
+	memset (&sadr, 0, sizeof(sadr));
+	sadr.sin_family = AF_INET;
+	
+	sadr.sin_port = 0;
+
+	strcpy (copy, s);
+	// strip off a trailing :port if present
+	for (colon = copy ; *colon ; colon++)
+		if (*colon == ':')
+		{
+			*colon = 0;
+			sadr.sin_port = htons((short)atoi(colon+1));	
+		}
+	
+	if (copy[0] >= '0' && copy[0] <= '9')
+	{
+		*(int *)&sadr.sin_addr = inet_addr(copy);
+	}
+	else
+	{
+		if ((h = gethostbyname(copy)) == 0)
+			return 0;
+		*(int *)&sadr.sin_addr = *(int *)h->h_addr_list[0];
+	}
+	
+	SockadrToNetadr (&sadr, a);
+
+	return true;
+}
+
+// Returns true if we can't bind the address locally--in other words, 
+// the IP is NOT one of our interfaces.
+qboolean NET_IsClientLegal(netadr_t *adr)
+{
+	struct sockaddr_in sadr;
+	int newsocket;
+
+#if 0
+	if (adr->ip[0] == 127)
+		return false; // no local connections period
+
+	NetadrToSockadr (adr, &sadr);
+
+	if ((newsocket = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
+		Sys_Error ("NET_IsClientLegal: socket:", strerror(errno));
+
+	sadr.sin_port = 0;
+
+	if( bind (newsocket, (void *)&sadr, sizeof(sadr)) == -1) 
+	{
+		// It is not a local address
+		close(newsocket);
+		return true;
+	}
+	close(newsocket);
+	return false;
+#else
+	return true;
+#endif
+}
+
+//=============================================================================
+
+qboolean NET_GetPacket (void)
+{
+	int 	ret;
+	struct sockaddr_in	from;
+	int		fromlen;
+
+	fromlen = sizeof(from);
+	ret = recvfrom (net_socket, (char *)net_message_buffer, sizeof(net_message_buffer), 0, (struct sockaddr *)&from, &fromlen);
+	SockadrToNetadr (&from, &net_from);
+
+	if (ret == -1)
+	{
+		int errno = WSAGetLastError();
+
+		if (errno == WSAEWOULDBLOCK)
+			return false;
+		if (errno == WSAEMSGSIZE) {
+			Con_Printf ("Warning:  Oversize packet from %s\n",
+				NET_AdrToString (net_from));
+			return false;
+		}
+
+
+		Sys_Error ("NET_GetPacket: %s", strerror(errno));
+	}
+
+	net_message.cursize = ret;
+	if (ret == sizeof(net_message_buffer) )
+	{
+		Con_Printf ("Oversize packet from %s\n", NET_AdrToString (net_from));
+		return false;
+	}
+
+	return ret;
+}
+
+//=============================================================================
+
+void NET_SendPacket (int length, void *data, netadr_t to)
+{
+	int ret;
+	struct sockaddr_in	addr;
+
+	NetadrToSockadr (&to, &addr);
+
+	ret = sendto (net_socket, data, length, 0, (struct sockaddr *)&addr, sizeof(addr) );
+	if (ret == -1)
+	{
+		int err = WSAGetLastError();
+
+// wouldblock is silent
+        if (err == WSAEWOULDBLOCK)
+	        return;
+
+#ifndef SERVERONLY
+		if (err == WSAEADDRNOTAVAIL)
+			Con_DPrintf("NET_SendPacket Warning: %i\n", err);
+		else
+#endif
+			Con_Printf ("NET_SendPacket ERROR: %i\n", errno);
+	}
+}
+
+//=============================================================================
+
+int UDP_OpenSocket (int port)
+{
+	int newsocket;
+	struct sockaddr_in address;
+	unsigned long _true = true;
+	int i;
+
+	if ((newsocket = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
+		Sys_Error ("UDP_OpenSocket: socket:", strerror(errno));
+
+	if (ioctlsocket (newsocket, FIONBIO, &_true) == -1)
+		Sys_Error ("UDP_OpenSocket: ioctl FIONBIO:", strerror(errno));
+
+	address.sin_family = AF_INET;
+//ZOID -- check for interface binding option
+	if ((i = COM_CheckParm("-ip")) != 0 && i < com_argc) {
+		address.sin_addr.s_addr = inet_addr(com_argv[i+1]);
+		Con_Printf("Binding to IP Interface Address of %s\n",
+				inet_ntoa(address.sin_addr));
+	} else
+		address.sin_addr.s_addr = INADDR_ANY;
+
+	if (port == PORT_ANY)
+		address.sin_port = 0;
+	else
+		address.sin_port = htons((short)port);
+	if( bind (newsocket, (void *)&address, sizeof(address)) == -1)
+		Sys_Error ("UDP_OpenSocket: bind: %s", strerror(errno));
+
+	return newsocket;
+}
+
+void NET_GetLocalAddress (void)
+{
+	char	buff[512];
+	struct sockaddr_in	address;
+	int		namelen;
+
+	gethostname(buff, 512);
+	buff[512-1] = 0;
+
+	NET_StringToAdr (buff, &net_local_adr);
+
+	namelen = sizeof(address);
+	if (getsockname (net_socket, (struct sockaddr *)&address, &namelen) == -1)
+		Sys_Error ("NET_Init: getsockname:", strerror(errno));
+	net_local_adr.port = address.sin_port;
+
+	Con_Printf("IP address %s\n", NET_AdrToString (net_local_adr) );
+}
+
+/*
+====================
+NET_Init
+====================
+*/
+void NET_Init (int port)
+{
+	WORD	wVersionRequested; 
+	int		r;
+
+	wVersionRequested = MAKEWORD(1, 1); 
+
+	r = WSAStartup (MAKEWORD(1, 1), &winsockdata);
+
+	if (r)
+		Sys_Error ("Winsock initialization failed.");
+
+	//
+	// open the single socket to be used for all communications
+	//
+	net_socket = UDP_OpenSocket (port);
+
+	//
+	// init the message buffer
+	//
+	net_message.maxsize = sizeof(net_message_buffer);
+	net_message.data = net_message_buffer;
+
+	//
+	// determine my name & address
+	//
+	NET_GetLocalAddress ();
+
+	Con_Printf("UDP Initialized\n");
+}
+
+/*
+====================
+NET_Shutdown
+====================
+*/
+void	NET_Shutdown (void)
+{
+	closesocket (net_socket);
+	WSACleanup ();
+}
+
--- /dev/null
+++ b/QW/client/nonintel.c
@@ -1,0 +1,62 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+//
+// nonintel.c: code for non-Intel processors only
+//
+
+#include "quakedef.h"
+
+#if	!id386
+
+/*
+================
+R_Surf8Patch
+================
+*/
+void R_Surf8Patch ()
+{
+	// we only patch code on Intel
+}
+
+
+/*
+================
+R_Surf16Patch
+================
+*/
+void R_Surf16Patch ()
+{
+	// we only patch code on Intel
+}
+
+
+/*
+================
+R_SurfacePatch
+================
+*/
+void R_SurfacePatch (void)
+{
+	// we only patch code on Intel
+}
+
+
+#endif	// !id386
+
--- /dev/null
+++ b/QW/client/notes.txt
@@ -1,0 +1,48 @@
+
+
+movecmd_t	movecmd;
+
+
+input from 
+
+packet sender
+	wake up on alarms or input signal
+	if on input signal, set skipnextalrm
+	else
+		if skipnextalarm
+			skipnextalarm = false;
+			continue;
+	lock packet
+	get current movecmd
+	send message
+	unlock packet
+
+packet receiver
+	wake up only on packet arrival
+	identify the packet source
+	calculate exact latency
+	save the packet off
+
+
+
+
+	// cause timer messages to be issued
+	SetTimer (mainwindow, 1, 50, NULL);
+
+	// cause packet received messages to be issued
+	WSAAsyncSelect ( net_socket, mainwindow, WM_USER, FD_READ );	
+
+	if (!GetMessage (&msg, NULL, 0, 0))
+	{
+		TranslateMessage (&msg);
+		DispatchMessage (&msg);
+		while (PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE))
+		{
+			if (!GetMessage (&msg, NULL, 0, 0))
+				break;
+			TranslateMessage (&msg);
+   			DispatchMessage (&msg);
+		}
+		PrepareToBlock ();
+	}
+
--- /dev/null
+++ b/QW/client/pmove.c
@@ -1,0 +1,904 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+
+#include "quakedef.h"
+
+
+movevars_t		movevars;
+
+playermove_t	pmove;
+
+int			onground;
+int			waterlevel;
+int			watertype;
+
+float		frametime;
+
+vec3_t		forward, right, up;
+
+vec3_t	player_mins = {-16, -16, -24};
+vec3_t	player_maxs = {16, 16, 32};
+
+// #define	PM_GRAVITY			800
+// #define	PM_STOPSPEED		100
+// #define	PM_MAXSPEED			320
+// #define	PM_SPECTATORMAXSPEED	500
+// #define	PM_ACCELERATE		10
+// #define	PM_AIRACCELERATE	0.7
+// #define	PM_WATERACCELERATE	10
+// #define	PM_FRICTION			6
+// #define	PM_WATERFRICTION	1
+
+void PM_InitBoxHull (void);
+
+void Pmove_Init (void)
+{
+	PM_InitBoxHull ();
+}
+
+#define	STEPSIZE	18
+
+
+#define	BUTTON_JUMP	2
+
+
+/*
+==================
+PM_ClipVelocity
+
+Slide off of the impacting object
+returns the blocked flags (1 = floor, 2 = step / wall)
+==================
+*/
+#define	STOP_EPSILON	0.1
+
+int PM_ClipVelocity (vec3_t in, vec3_t normal, vec3_t out, float overbounce)
+{
+	float	backoff;
+	float	change;
+	int		i, blocked;
+	
+	blocked = 0;
+	if (normal[2] > 0)
+		blocked |= 1;		// floor
+	if (!normal[2])
+		blocked |= 2;		// step
+	
+	backoff = DotProduct (in, normal) * overbounce;
+
+	for (i=0 ; i<3 ; i++)
+	{
+		change = normal[i]*backoff;
+		out[i] = in[i] - change;
+		if (out[i] > -STOP_EPSILON && out[i] < STOP_EPSILON)
+			out[i] = 0;
+	}
+	
+	return blocked;
+}
+
+
+/*
+============
+PM_FlyMove
+
+The basic solid body movement clip that slides along multiple planes
+============
+*/
+#define	MAX_CLIP_PLANES	5
+
+int PM_FlyMove (void)
+{
+	int			bumpcount, numbumps;
+	vec3_t		dir;
+	float		d;
+	int			numplanes;
+	vec3_t		planes[MAX_CLIP_PLANES];
+	vec3_t		primal_velocity, original_velocity;
+	int			i, j;
+	pmtrace_t		trace;
+	vec3_t		end;
+	float		time_left;
+	int			blocked;
+	
+	numbumps = 4;
+	
+	blocked = 0;
+	VectorCopy (pmove.velocity, original_velocity);
+	VectorCopy (pmove.velocity, primal_velocity);
+	numplanes = 0;
+	
+	time_left = frametime;
+
+	for (bumpcount=0 ; bumpcount<numbumps ; bumpcount++)
+	{
+		for (i=0 ; i<3 ; i++)
+			end[i] = pmove.origin[i] + time_left * pmove.velocity[i];
+
+		trace = PM_PlayerMove (pmove.origin, end);
+
+		if (trace.startsolid || trace.allsolid)
+		{	// entity is trapped in another solid
+			VectorCopy (vec3_origin, pmove.velocity);
+			return 3;
+		}
+
+		if (trace.fraction > 0)
+		{	// actually covered some distance
+			VectorCopy (trace.endpos, pmove.origin);
+			numplanes = 0;
+		}
+
+		if (trace.fraction == 1)
+			 break;		// moved the entire distance
+
+		// save entity for contact
+		pmove.touchindex[pmove.numtouch] = trace.ent;
+		pmove.numtouch++;
+
+		if (trace.plane.normal[2] > 0.7)
+		{
+			blocked |= 1;		// floor
+		}
+		if (!trace.plane.normal[2])
+		{
+			blocked |= 2;		// step
+		}
+
+		time_left -= time_left * trace.fraction;
+		
+	// cliped to another plane
+		if (numplanes >= MAX_CLIP_PLANES)
+		{	// this shouldn't really happen
+			VectorCopy (vec3_origin, pmove.velocity);
+			break;
+		}
+
+		VectorCopy (trace.plane.normal, planes[numplanes]);
+		numplanes++;
+
+//
+// modify original_velocity so it parallels all of the clip planes
+//
+		for (i=0 ; i<numplanes ; i++)
+		{
+			PM_ClipVelocity (original_velocity, planes[i], pmove.velocity, 1);
+			for (j=0 ; j<numplanes ; j++)
+				if (j != i)
+				{
+					if (DotProduct (pmove.velocity, planes[j]) < 0)
+						break;	// not ok
+				}
+			if (j == numplanes)
+				break;
+		}
+		
+		if (i != numplanes)
+		{	// go along this plane
+		}
+		else
+		{	// go along the crease
+			if (numplanes != 2)
+			{
+//				Con_Printf ("clip velocity, numplanes == %i\n",numplanes);
+				VectorCopy (vec3_origin, pmove.velocity);
+				break;
+			}
+			CrossProduct (planes[0], planes[1], dir);
+			d = DotProduct (dir, pmove.velocity);
+			VectorScale (dir, d, pmove.velocity);
+		}
+
+//
+// if original velocity is against the original velocity, stop dead
+// to avoid tiny occilations in sloping corners
+//
+		if (DotProduct (pmove.velocity, primal_velocity) <= 0)
+		{
+			VectorCopy (vec3_origin, pmove.velocity);
+			break;
+		}
+	}
+
+	if (pmove.waterjumptime)
+	{
+		VectorCopy (primal_velocity, pmove.velocity);
+	}
+	return blocked;
+}
+
+/*
+=============
+PM_GroundMove
+
+Player is on ground, with no upwards velocity
+=============
+*/
+void PM_GroundMove (void)
+{
+	vec3_t	start, dest;
+	pmtrace_t	trace;
+	vec3_t	original, originalvel, down, up, downvel;
+	float	downdist, updist;
+
+	pmove.velocity[2] = 0;
+	if (!pmove.velocity[0] && !pmove.velocity[1] && !pmove.velocity[2])
+		return;
+
+	// first try just moving to the destination	
+	dest[0] = pmove.origin[0] + pmove.velocity[0]*frametime;
+	dest[1] = pmove.origin[1] + pmove.velocity[1]*frametime;	
+	dest[2] = pmove.origin[2];
+
+	// first try moving directly to the next spot
+	VectorCopy (dest, start);
+	trace = PM_PlayerMove (pmove.origin, dest);
+	if (trace.fraction == 1)
+	{
+		VectorCopy (trace.endpos, pmove.origin);
+		return;
+	}
+
+	// try sliding forward both on ground and up 16 pixels
+	// take the move that goes farthest
+	VectorCopy (pmove.origin, original);
+	VectorCopy (pmove.velocity, originalvel);
+
+	// slide move
+	PM_FlyMove ();
+
+	VectorCopy (pmove.origin, down);
+	VectorCopy (pmove.velocity, downvel);
+
+	VectorCopy (original, pmove.origin);
+	VectorCopy (originalvel, pmove.velocity);
+
+// move up a stair height
+	VectorCopy (pmove.origin, dest);
+	dest[2] += STEPSIZE;
+	trace = PM_PlayerMove (pmove.origin, dest);
+	if (!trace.startsolid && !trace.allsolid)
+	{
+		VectorCopy (trace.endpos, pmove.origin);
+	}
+
+// slide move
+	PM_FlyMove ();
+
+// press down the stepheight
+	VectorCopy (pmove.origin, dest);
+	dest[2] -= STEPSIZE;
+	trace = PM_PlayerMove (pmove.origin, dest);
+	if ( trace.plane.normal[2] < 0.7)
+		goto usedown;
+	if (!trace.startsolid && !trace.allsolid)
+	{
+		VectorCopy (trace.endpos, pmove.origin);
+	}
+	VectorCopy (pmove.origin, up);
+
+	// decide which one went farther
+	downdist = (down[0] - original[0])*(down[0] - original[0])
+		+ (down[1] - original[1])*(down[1] - original[1]);
+	updist = (up[0] - original[0])*(up[0] - original[0])
+		+ (up[1] - original[1])*(up[1] - original[1]);
+
+	if (downdist > updist)
+	{
+usedown:
+		VectorCopy (down, pmove.origin);
+		VectorCopy (downvel, pmove.velocity);
+	} else // copy z value from slide move
+		pmove.velocity[2] = downvel[2];
+
+// if at a dead stop, retry the move with nudges to get around lips
+
+}
+
+
+
+/*
+==================
+PM_Friction
+
+Handles both ground friction and water friction
+==================
+*/
+void PM_Friction (void)
+{
+	float	*vel;
+	float	speed, newspeed, control;
+	float	friction;
+	float	drop;
+	vec3_t	start, stop;
+	pmtrace_t		trace;
+	
+	if (pmove.waterjumptime)
+		return;
+
+	vel = pmove.velocity;
+	
+	speed = sqrt(vel[0]*vel[0] +vel[1]*vel[1] + vel[2]*vel[2]);
+	if (speed < 1)
+	{
+		vel[0] = 0;
+		vel[1] = 0;
+		return;
+	}
+
+	friction = movevars.friction;
+
+// if the leading edge is over a dropoff, increase friction
+	if (onground != -1) {
+		start[0] = stop[0] = pmove.origin[0] + vel[0]/speed*16;
+		start[1] = stop[1] = pmove.origin[1] + vel[1]/speed*16;
+		start[2] = pmove.origin[2] + player_mins[2];
+		stop[2] = start[2] - 34;
+
+		trace = PM_PlayerMove (start, stop);
+
+		if (trace.fraction == 1) {
+			friction *= 2;
+		}
+	}
+
+	drop = 0;
+
+	if (waterlevel >= 2) // apply water friction
+		drop += speed*movevars.waterfriction*waterlevel*frametime;
+	else if (onground != -1) // apply ground friction
+	{
+		control = speed < movevars.stopspeed ? movevars.stopspeed : speed;
+		drop += control*friction*frametime;
+	}
+
+
+// scale the velocity
+	newspeed = speed - drop;
+	if (newspeed < 0)
+		newspeed = 0;
+	newspeed /= speed;
+
+	vel[0] = vel[0] * newspeed;
+	vel[1] = vel[1] * newspeed;
+	vel[2] = vel[2] * newspeed;
+}
+
+
+/*
+==============
+PM_Accelerate
+==============
+*/
+void PM_Accelerate (vec3_t wishdir, float wishspeed, float accel)
+{
+	int			i;
+	float		addspeed, accelspeed, currentspeed;
+
+	if (pmove.dead)
+		return;
+	if (pmove.waterjumptime)
+		return;
+
+	currentspeed = DotProduct (pmove.velocity, wishdir);
+	addspeed = wishspeed - currentspeed;
+	if (addspeed <= 0)
+		return;
+	accelspeed = accel*frametime*wishspeed;
+	if (accelspeed > addspeed)
+		accelspeed = addspeed;
+	
+	for (i=0 ; i<3 ; i++)
+		pmove.velocity[i] += accelspeed*wishdir[i];	
+}
+
+void PM_AirAccelerate (vec3_t wishdir, float wishspeed, float accel)
+{
+	int			i;
+	float		addspeed, accelspeed, currentspeed, wishspd = wishspeed;
+		
+	if (pmove.dead)
+		return;
+	if (pmove.waterjumptime)
+		return;
+
+	if (wishspd > 30)
+		wishspd = 30;
+	currentspeed = DotProduct (pmove.velocity, wishdir);
+	addspeed = wishspd - currentspeed;
+	if (addspeed <= 0)
+		return;
+	accelspeed = accel * wishspeed * frametime;
+	if (accelspeed > addspeed)
+		accelspeed = addspeed;
+	
+	for (i=0 ; i<3 ; i++)
+		pmove.velocity[i] += accelspeed*wishdir[i];	
+}
+
+
+
+/*
+===================
+PM_WaterMove
+
+===================
+*/
+void PM_WaterMove (void)
+{
+	int		i;
+	vec3_t	wishvel;
+	float	wishspeed;
+	vec3_t	wishdir;
+	vec3_t	start, dest;
+	pmtrace_t	trace;
+
+//
+// user intentions
+//
+	for (i=0 ; i<3 ; i++)
+		wishvel[i] = forward[i]*pmove.cmd.forwardmove + right[i]*pmove.cmd.sidemove;
+
+	if (!pmove.cmd.forwardmove && !pmove.cmd.sidemove && !pmove.cmd.upmove)
+		wishvel[2] -= 60;		// drift towards bottom
+	else
+		wishvel[2] += pmove.cmd.upmove;
+
+	VectorCopy (wishvel, wishdir);
+	wishspeed = VectorNormalize(wishdir);
+
+	if (wishspeed > movevars.maxspeed)
+	{
+		VectorScale (wishvel, movevars.maxspeed/wishspeed, wishvel);
+		wishspeed = movevars.maxspeed;
+	}
+	wishspeed *= 0.7;
+
+//
+// water acceleration
+//
+//	if (pmove.waterjumptime)
+//		Con_Printf ("wm->%f, %f, %f\n", pmove.velocity[0], pmove.velocity[1], pmove.velocity[2]);
+	PM_Accelerate (wishdir, wishspeed, movevars.wateraccelerate);
+
+// assume it is a stair or a slope, so press down from stepheight above
+	VectorMA (pmove.origin, frametime, pmove.velocity, dest);
+	VectorCopy (dest, start);
+	start[2] += STEPSIZE + 1;
+	trace = PM_PlayerMove (start, dest);
+	if (!trace.startsolid && !trace.allsolid)	// FIXME: check steep slope?
+	{	// walked up the step
+		VectorCopy (trace.endpos, pmove.origin);
+		return;
+	}
+	
+	PM_FlyMove ();
+//	if (pmove.waterjumptime)
+//		Con_Printf ("<-wm%f, %f, %f\n", pmove.velocity[0], pmove.velocity[1], pmove.velocity[2]);
+}
+
+
+/*
+===================
+PM_AirMove
+
+===================
+*/
+void PM_AirMove (void)
+{
+	int			i;
+	vec3_t		wishvel;
+	float		fmove, smove;
+	vec3_t		wishdir;
+	float		wishspeed;
+
+	fmove = pmove.cmd.forwardmove;
+	smove = pmove.cmd.sidemove;
+	
+	forward[2] = 0;
+	right[2] = 0;
+	VectorNormalize (forward);
+	VectorNormalize (right);
+
+	for (i=0 ; i<2 ; i++)
+		wishvel[i] = forward[i]*fmove + right[i]*smove;
+	wishvel[2] = 0;
+
+	VectorCopy (wishvel, wishdir);
+	wishspeed = VectorNormalize(wishdir);
+
+//
+// clamp to server defined max speed
+//
+	if (wishspeed > movevars.maxspeed)
+	{
+		VectorScale (wishvel, movevars.maxspeed/wishspeed, wishvel);
+		wishspeed = movevars.maxspeed;
+	}
+	
+//	if (pmove.waterjumptime)
+//		Con_Printf ("am->%f, %f, %f\n", pmove.velocity[0], pmove.velocity[1], pmove.velocity[2]);
+
+	if ( onground != -1)
+	{
+		pmove.velocity[2] = 0;
+		PM_Accelerate (wishdir, wishspeed, movevars.accelerate);
+		pmove.velocity[2] -= movevars.entgravity * movevars.gravity * frametime;
+		PM_GroundMove ();
+	}
+	else
+	{	// not on ground, so little effect on velocity
+		PM_AirAccelerate (wishdir, wishspeed, movevars.accelerate);
+
+		// add gravity
+		pmove.velocity[2] -= movevars.entgravity * movevars.gravity * frametime;
+
+		PM_FlyMove ();
+
+	}
+
+//Con_Printf("airmove:vec: %4.2f %4.2f %4.2f\n",
+//			pmove.velocity[0],
+//			pmove.velocity[1],
+//			pmove.velocity[2]);
+//
+
+//	if (pmove.waterjumptime)
+//		Con_Printf ("<-am%f, %f, %f\n", pmove.velocity[0], pmove.velocity[1], pmove.velocity[2]);
+}
+
+
+
+/*
+=============
+PM_CatagorizePosition
+=============
+*/
+void PM_CatagorizePosition (void)
+{
+	vec3_t		point;
+	int			cont;
+	pmtrace_t		tr;
+
+// if the player hull point one unit down is solid, the player
+// is on ground
+
+// see if standing on something solid	
+	point[0] = pmove.origin[0];
+	point[1] = pmove.origin[1];
+	point[2] = pmove.origin[2] - 1;
+	if (pmove.velocity[2] > 180)
+	{
+		onground = -1;
+	}
+	else
+	{
+		tr = PM_PlayerMove (pmove.origin, point);
+		if ( tr.plane.normal[2] < 0.7)
+			onground = -1;	// too steep
+		else
+			onground = tr.ent;
+		if (onground != -1)
+		{
+			pmove.waterjumptime = 0;
+			if (!tr.startsolid && !tr.allsolid)
+				VectorCopy (tr.endpos, pmove.origin);
+		}
+
+		// standing on an entity other than the world
+		if (tr.ent > 0)
+		{
+			pmove.touchindex[pmove.numtouch] = tr.ent;
+			pmove.numtouch++;
+		}
+	}
+
+//
+// get waterlevel
+//
+	waterlevel = 0;
+	watertype = CONTENTS_EMPTY;
+
+	point[2] = pmove.origin[2] + player_mins[2] + 1;	
+	cont = PM_PointContents (point);
+
+	if (cont <= CONTENTS_WATER)
+	{
+		watertype = cont;
+		waterlevel = 1;
+		point[2] = pmove.origin[2] + (player_mins[2] + player_maxs[2])*0.5;
+		cont = PM_PointContents (point);
+		if (cont <= CONTENTS_WATER)
+		{
+			waterlevel = 2;
+			point[2] = pmove.origin[2] + 22;
+			cont = PM_PointContents (point);
+			if (cont <= CONTENTS_WATER)
+				waterlevel = 3;
+		}
+	}
+}
+
+
+/*
+=============
+JumpButton
+=============
+*/
+void JumpButton (void)
+{
+	if (pmove.dead)
+	{
+		pmove.oldbuttons |= BUTTON_JUMP;	// don't jump again until released
+		return;
+	}
+
+	if (pmove.waterjumptime)
+	{
+		pmove.waterjumptime -= frametime;
+		if (pmove.waterjumptime < 0)
+			pmove.waterjumptime = 0;
+		return;
+	}
+
+	if (waterlevel >= 2)
+	{	// swimming, not jumping
+		onground = -1;
+
+		if (watertype == CONTENTS_WATER)
+			pmove.velocity[2] = 100;
+		else if (watertype == CONTENTS_SLIME)
+			pmove.velocity[2] = 80;
+		else
+			pmove.velocity[2] = 50;
+		return;
+	}
+
+	if (onground == -1)
+		return;		// in air, so no effect
+
+	if ( pmove.oldbuttons & BUTTON_JUMP )
+		return;		// don't pogo stick
+
+	onground = -1;
+	pmove.velocity[2] += 270;
+
+	pmove.oldbuttons |= BUTTON_JUMP;	// don't jump again until released
+}
+
+/*
+=============
+CheckWaterJump
+=============
+*/
+void CheckWaterJump (void)
+{
+	vec3_t	spot;
+	int		cont;
+	vec3_t	flatforward;
+
+	if (pmove.waterjumptime)
+		return;
+
+	// ZOID, don't hop out if we just jumped in
+	if (pmove.velocity[2] < -180)
+		return; // only hop out if we are moving up
+
+	// see if near an edge
+	flatforward[0] = forward[0];
+	flatforward[1] = forward[1];
+	flatforward[2] = 0;
+	VectorNormalize (flatforward);
+
+	VectorMA (pmove.origin, 24, flatforward, spot);
+	spot[2] += 8;
+	cont = PM_PointContents (spot);
+	if (cont != CONTENTS_SOLID)
+		return;
+	spot[2] += 24;
+	cont = PM_PointContents (spot);
+	if (cont != CONTENTS_EMPTY)
+		return;
+	// jump out of water
+	VectorScale (flatforward, 50, pmove.velocity);
+	pmove.velocity[2] = 310;
+	pmove.waterjumptime = 2;	// safety net
+	pmove.oldbuttons |= BUTTON_JUMP;	// don't jump again until released
+}
+
+/*
+=================
+NudgePosition
+
+If pmove.origin is in a solid position,
+try nudging slightly on all axis to
+allow for the cut precision of the net coordinates
+=================
+*/
+void NudgePosition (void)
+{
+	vec3_t	base;
+	int		x, y, z;
+	int		i;
+	static int		sign[3] = {0, -1, 1};
+
+	VectorCopy (pmove.origin, base);
+
+	for (i=0 ; i<3 ; i++)
+		pmove.origin[i] = ((int)(pmove.origin[i]*8)) * 0.125;
+//	pmove.origin[2] += 0.124;
+
+//	if (pmove.dead)
+//		return;		// might be a squished point, so don'y bother
+//	if (PM_TestPlayerPosition (pmove.origin) )
+//		return;
+
+	for (z=0 ; z<=2 ; z++)
+	{
+		for (x=0 ; x<=2 ; x++)
+		{
+			for (y=0 ; y<=2 ; y++)
+			{
+				pmove.origin[0] = base[0] + (sign[x] * 1.0/8);
+				pmove.origin[1] = base[1] + (sign[y] * 1.0/8);
+				pmove.origin[2] = base[2] + (sign[z] * 1.0/8);
+				if (PM_TestPlayerPosition (pmove.origin))
+					return;
+			}
+		}
+	}
+	VectorCopy (base, pmove.origin);
+//	Con_DPrintf ("NudgePosition: stuck\n");
+}
+
+/*
+===============
+SpectatorMove
+===============
+*/
+void SpectatorMove (void)
+{
+	float	speed, drop, friction, control, newspeed, accel;
+	float	currentspeed, addspeed, accelspeed;
+	int			i;
+	vec3_t		wishvel;
+	float		fmove, smove;
+	vec3_t		wishdir;
+	float		wishspeed;
+#ifndef SERVERONLY
+	extern float	server_version;	// version of server we connected to
+#endif
+
+	// friction
+
+	speed = Length (pmove.velocity);
+	if (speed < 1)
+	{
+		VectorCopy (vec3_origin, pmove.velocity)
+	}
+	else
+	{
+		drop = 0;
+
+		friction = movevars.friction*1.5;	// extra friction
+		control = speed < movevars.stopspeed ? movevars.stopspeed : speed;
+		drop += control*friction*frametime;
+
+		// scale the velocity
+		newspeed = speed - drop;
+		if (newspeed < 0)
+			newspeed = 0;
+		newspeed /= speed;
+
+		VectorScale (pmove.velocity, newspeed, pmove.velocity);
+	}
+
+	// accelerate
+	fmove = pmove.cmd.forwardmove;
+	smove = pmove.cmd.sidemove;
+	
+	VectorNormalize (forward);
+	VectorNormalize (right);
+
+	for (i=0 ; i<3 ; i++)
+		wishvel[i] = forward[i]*fmove + right[i]*smove;
+	wishvel[2] += pmove.cmd.upmove;
+
+	VectorCopy (wishvel, wishdir);
+	wishspeed = VectorNormalize(wishdir);
+
+	//
+	// clamp to server defined max speed
+	//
+	if (wishspeed > movevars.spectatormaxspeed)
+	{
+		VectorScale (wishvel, movevars.spectatormaxspeed/wishspeed, wishvel);
+		wishspeed = movevars.spectatormaxspeed;
+	}
+
+	currentspeed = DotProduct(pmove.velocity, wishdir);
+	addspeed = wishspeed - currentspeed;
+	if (addspeed <= 0)
+		return;
+	accelspeed = movevars.accelerate*frametime*wishspeed;
+	if (accelspeed > addspeed)
+		accelspeed = addspeed;
+	
+	for (i=0 ; i<3 ; i++)
+		pmove.velocity[i] += accelspeed*wishdir[i];	
+
+
+	// move
+	VectorMA (pmove.origin, frametime, pmove.velocity, pmove.origin);
+}
+
+/*
+=============
+PlayerMove
+
+Returns with origin, angles, and velocity modified in place.
+
+Numtouch and touchindex[] will be set if any of the physents
+were contacted during the move.
+=============
+*/
+void PlayerMove (void)
+{
+	frametime = pmove.cmd.msec * 0.001;
+	pmove.numtouch = 0;
+
+	AngleVectors (pmove.angles, forward, right, up);
+
+	if (pmove.spectator)
+	{
+		SpectatorMove ();
+		return;
+	}
+
+	NudgePosition ();
+
+	// take angles directly from command
+	VectorCopy (pmove.cmd.angles, pmove.angles);
+
+	// set onground, watertype, and waterlevel
+	PM_CatagorizePosition ();
+
+	if (waterlevel == 2)
+		CheckWaterJump ();
+
+	if (pmove.velocity[2] < 0)
+		pmove.waterjumptime = 0;
+
+	if (pmove.cmd.buttons & BUTTON_JUMP)
+		JumpButton ();
+	else
+		pmove.oldbuttons &= ~BUTTON_JUMP;
+
+	PM_Friction ();
+
+	if (waterlevel >= 2)
+		PM_WaterMove ();
+	else
+		PM_AirMove ();
+
+	// set onground, watertype, and waterlevel for final spot
+	PM_CatagorizePosition ();
+}
+
--- /dev/null
+++ b/QW/client/pmove.h
@@ -1,0 +1,101 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+
+typedef struct
+{
+	vec3_t	normal;
+	float	dist;
+} pmplane_t;
+
+typedef struct
+{
+	qboolean	allsolid;	// if true, plane is not valid
+	qboolean	startsolid;	// if true, the initial point was in a solid area
+	qboolean	inopen, inwater;
+	float		fraction;		// time completed, 1.0 = didn't hit anything
+	vec3_t		endpos;			// final position
+	pmplane_t		plane;			// surface normal at impact
+	int			ent;			// entity the surface is on
+} pmtrace_t;
+
+
+#define	MAX_PHYSENTS	32
+typedef struct
+{
+	vec3_t	origin;
+	model_t	*model;		// only for bsp models
+	vec3_t	mins, maxs;	// only for non-bsp models
+	int		info;		// for client or server to identify
+} physent_t;
+
+
+typedef struct
+{
+	int		sequence;	// just for debugging prints
+
+	// player state
+	vec3_t	origin;
+	vec3_t	angles;
+	vec3_t	velocity;
+	int		oldbuttons;
+	float		waterjumptime;
+	qboolean	dead;
+	int		spectator;
+
+	// world state
+	int		numphysent;
+	physent_t	physents[MAX_PHYSENTS];	// 0 should be the world
+
+	// input
+	usercmd_t	cmd;
+
+	// results
+	int		numtouch;
+	int		touchindex[MAX_PHYSENTS];
+} playermove_t;
+
+typedef struct {
+	float	gravity;
+	float	stopspeed;
+	float	maxspeed;
+	float	spectatormaxspeed;
+	float	accelerate;
+	float	airaccelerate;
+	float	wateraccelerate;
+	float	friction;
+	float	waterfriction;
+	float	entgravity;
+} movevars_t;
+
+
+extern	movevars_t		movevars;
+extern	playermove_t	pmove;
+extern	int		onground;
+extern	int		waterlevel;
+extern	int		watertype;
+
+void PlayerMove (void);
+void Pmove_Init (void);
+
+int PM_HullPointContents (hull_t *hull, int num, vec3_t p);
+
+int PM_PointContents (vec3_t point);
+qboolean PM_TestPlayerPosition (vec3_t point);
+pmtrace_t PM_PlayerMove (vec3_t start, vec3_t stop);
--- /dev/null
+++ b/QW/client/pmovetst.c
@@ -1,0 +1,414 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+#include "quakedef.h"
+
+static	hull_t		box_hull;
+static	dclipnode_t	box_clipnodes[6];
+static	mplane_t	box_planes[6];
+
+extern	vec3_t player_mins;
+extern	vec3_t player_maxs;
+
+/*
+===================
+PM_InitBoxHull
+
+Set up the planes and clipnodes so that the six floats of a bounding box
+can just be stored out and get a proper hull_t structure.
+===================
+*/
+void PM_InitBoxHull (void)
+{
+	int		i;
+	int		side;
+
+	box_hull.clipnodes = box_clipnodes;
+	box_hull.planes = box_planes;
+	box_hull.firstclipnode = 0;
+	box_hull.lastclipnode = 5;
+
+	for (i=0 ; i<6 ; i++)
+	{
+		box_clipnodes[i].planenum = i;
+		
+		side = i&1;
+		
+		box_clipnodes[i].children[side] = CONTENTS_EMPTY;
+		if (i != 5)
+			box_clipnodes[i].children[side^1] = i + 1;
+		else
+			box_clipnodes[i].children[side^1] = CONTENTS_SOLID;
+		
+		box_planes[i].type = i>>1;
+		box_planes[i].normal[i>>1] = 1;
+	}
+	
+}
+
+
+/*
+===================
+PM_HullForBox
+
+To keep everything totally uniform, bounding boxes are turned into small
+BSP trees instead of being compared directly.
+===================
+*/
+hull_t	*PM_HullForBox (vec3_t mins, vec3_t maxs)
+{
+	box_planes[0].dist = maxs[0];
+	box_planes[1].dist = mins[0];
+	box_planes[2].dist = maxs[1];
+	box_planes[3].dist = mins[1];
+	box_planes[4].dist = maxs[2];
+	box_planes[5].dist = mins[2];
+
+	return &box_hull;
+}
+
+
+/*
+==================
+PM_HullPointContents
+
+==================
+*/
+int PM_HullPointContents (hull_t *hull, int num, vec3_t p)
+{
+	float		d;
+	dclipnode_t	*node;
+	mplane_t	*plane;
+
+	while (num >= 0)
+	{
+		if (num < hull->firstclipnode || num > hull->lastclipnode)
+			Sys_Error ("PM_HullPointContents: bad node number");
+	
+		node = hull->clipnodes + num;
+		plane = hull->planes + node->planenum;
+		
+		if (plane->type < 3)
+			d = p[plane->type] - plane->dist;
+		else
+			d = DotProduct (plane->normal, p) - plane->dist;
+		if (d < 0)
+			num = node->children[1];
+		else
+			num = node->children[0];
+	}
+	
+	return num;
+}
+
+/*
+==================
+PM_PointContents
+
+==================
+*/
+int PM_PointContents (vec3_t p)
+{
+	float		d;
+	dclipnode_t	*node;
+	mplane_t	*plane;
+	hull_t		*hull;
+	int			num;
+
+	hull = &pmove.physents[0].model->hulls[0];
+
+	num = hull->firstclipnode;
+
+	while (num >= 0)
+	{
+		if (num < hull->firstclipnode || num > hull->lastclipnode)
+			Sys_Error ("PM_HullPointContents: bad node number");
+	
+		node = hull->clipnodes + num;
+		plane = hull->planes + node->planenum;
+		
+		if (plane->type < 3)
+			d = p[plane->type] - plane->dist;
+		else
+			d = DotProduct (plane->normal, p) - plane->dist;
+		if (d < 0)
+			num = node->children[1];
+		else
+			num = node->children[0];
+	}
+	
+	return num;
+}
+
+/*
+===============================================================================
+
+LINE TESTING IN HULLS
+
+===============================================================================
+*/
+
+// 1/32 epsilon to keep floating point happy
+#define	DIST_EPSILON	(0.03125)
+
+/*
+==================
+PM_RecursiveHullCheck
+
+==================
+*/
+qboolean PM_RecursiveHullCheck (hull_t *hull, int num, float p1f, float p2f, vec3_t p1, vec3_t p2, pmtrace_t *trace)
+{
+	dclipnode_t	*node;
+	mplane_t	*plane;
+	float		t1, t2;
+	float		frac;
+	int			i;
+	vec3_t		mid;
+	int			side;
+	float		midf;
+
+// check for empty
+	if (num < 0)
+	{
+		if (num != CONTENTS_SOLID)
+		{
+			trace->allsolid = false;
+			if (num == CONTENTS_EMPTY)
+				trace->inopen = true;
+			else
+				trace->inwater = true;
+		}
+		else
+			trace->startsolid = true;
+		return true;		// empty
+	}
+
+	if (num < hull->firstclipnode || num > hull->lastclipnode)
+		Sys_Error ("PM_RecursiveHullCheck: bad node number");
+
+//
+// find the point distances
+//
+	node = hull->clipnodes + num;
+	plane = hull->planes + node->planenum;
+
+	if (plane->type < 3)
+	{
+		t1 = p1[plane->type] - plane->dist;
+		t2 = p2[plane->type] - plane->dist;
+	}
+	else
+	{
+		t1 = DotProduct (plane->normal, p1) - plane->dist;
+		t2 = DotProduct (plane->normal, p2) - plane->dist;
+	}
+	
+#if 1
+	if (t1 >= 0 && t2 >= 0)
+		return PM_RecursiveHullCheck (hull, node->children[0], p1f, p2f, p1, p2, trace);
+	if (t1 < 0 && t2 < 0)
+		return PM_RecursiveHullCheck (hull, node->children[1], p1f, p2f, p1, p2, trace);
+#else
+	if ( (t1 >= DIST_EPSILON && t2 >= DIST_EPSILON) || (t2 > t1 && t1 >= 0) )
+		return PM_RecursiveHullCheck (hull, node->children[0], p1f, p2f, p1, p2, trace);
+	if ( (t1 <= -DIST_EPSILON && t2 <= -DIST_EPSILON) || (t2 < t1 && t1 <= 0) )
+		return PM_RecursiveHullCheck (hull, node->children[1], p1f, p2f, p1, p2, trace);
+#endif
+
+// put the crosspoint DIST_EPSILON pixels on the near side
+	if (t1 < 0)
+		frac = (t1 + DIST_EPSILON)/(t1-t2);
+	else
+		frac = (t1 - DIST_EPSILON)/(t1-t2);
+	if (frac < 0)
+		frac = 0;
+	if (frac > 1)
+		frac = 1;
+		
+	midf = p1f + (p2f - p1f)*frac;
+	for (i=0 ; i<3 ; i++)
+		mid[i] = p1[i] + frac*(p2[i] - p1[i]);
+
+	side = (t1 < 0);
+
+// move up to the node
+	if (!PM_RecursiveHullCheck (hull, node->children[side], p1f, midf, p1, mid, trace) )
+		return false;
+
+#ifdef PARANOID
+	if (PM_HullPointContents (pm_hullmodel, mid, node->children[side])
+	== CONTENTS_SOLID)
+	{
+		Con_Printf ("mid PointInHullSolid\n");
+		return false;
+	}
+#endif
+	
+	if (PM_HullPointContents (hull, node->children[side^1], mid)
+	!= CONTENTS_SOLID)
+// go past the node
+		return PM_RecursiveHullCheck (hull, node->children[side^1], midf, p2f, mid, p2, trace);
+	
+	if (trace->allsolid)
+		return false;		// never got out of the solid area
+		
+//==================
+// the other side of the node is solid, this is the impact point
+//==================
+	if (!side)
+	{
+		VectorCopy (plane->normal, trace->plane.normal);
+		trace->plane.dist = plane->dist;
+	}
+	else
+	{
+		VectorSubtract (vec3_origin, plane->normal, trace->plane.normal);
+		trace->plane.dist = -plane->dist;
+	}
+
+	while (PM_HullPointContents (hull, hull->firstclipnode, mid)
+	== CONTENTS_SOLID)
+	{ // shouldn't really happen, but does occasionally
+		frac -= 0.1;
+		if (frac < 0)
+		{
+			trace->fraction = midf;
+			VectorCopy (mid, trace->endpos);
+			Con_DPrintf ("backup past 0\n");
+			return false;
+		}
+		midf = p1f + (p2f - p1f)*frac;
+		for (i=0 ; i<3 ; i++)
+			mid[i] = p1[i] + frac*(p2[i] - p1[i]);
+	}
+
+	trace->fraction = midf;
+	VectorCopy (mid, trace->endpos);
+
+	return false;
+}
+
+
+/*
+================
+PM_TestPlayerPosition
+
+Returns false if the given player position is not valid (in solid)
+================
+*/
+qboolean PM_TestPlayerPosition (vec3_t pos)
+{
+	int			i;
+	physent_t	*pe;
+	vec3_t		mins, maxs, test;
+	hull_t		*hull;
+
+	for (i=0 ; i< pmove.numphysent ; i++)
+	{
+		pe = &pmove.physents[i];
+	// get the clipping hull
+		if (pe->model)
+			hull = &pmove.physents[i].model->hulls[1];
+		else
+		{
+			VectorSubtract (pe->mins, player_maxs, mins);
+			VectorSubtract (pe->maxs, player_mins, maxs);
+			hull = PM_HullForBox (mins, maxs);
+		}
+
+		VectorSubtract (pos, pe->origin, test);
+
+		if (PM_HullPointContents (hull, hull->firstclipnode, test) == CONTENTS_SOLID)
+			return false;
+	}
+
+	return true;
+}
+
+/*
+================
+PM_PlayerMove
+================
+*/
+pmtrace_t PM_PlayerMove (vec3_t start, vec3_t end)
+{
+	pmtrace_t		trace, total;
+	vec3_t		offset;
+	vec3_t		start_l, end_l;
+	hull_t		*hull;
+	int			i;
+	physent_t	*pe;
+	vec3_t		mins, maxs;
+
+// fill in a default trace
+	memset (&total, 0, sizeof(pmtrace_t));
+	total.fraction = 1;
+	total.ent = -1;
+	VectorCopy (end, total.endpos);
+
+	for (i=0 ; i< pmove.numphysent ; i++)
+	{
+		pe = &pmove.physents[i];
+	// get the clipping hull
+		if (pe->model)
+			hull = &pmove.physents[i].model->hulls[1];
+		else
+		{
+			VectorSubtract (pe->mins, player_maxs, mins);
+			VectorSubtract (pe->maxs, player_mins, maxs);
+			hull = PM_HullForBox (mins, maxs);
+		}
+
+	// PM_HullForEntity (ent, mins, maxs, offset);
+	VectorCopy (pe->origin, offset);
+
+		VectorSubtract (start, offset, start_l);
+		VectorSubtract (end, offset, end_l);
+
+	// fill in a default trace
+		memset (&trace, 0, sizeof(pmtrace_t));
+		trace.fraction = 1;
+		trace.allsolid = true;
+//		trace.startsolid = true;
+		VectorCopy (end, trace.endpos);
+
+	// trace a line through the apropriate clipping hull
+		PM_RecursiveHullCheck (hull, hull->firstclipnode, 0, 1, start_l, end_l, &trace);
+
+		if (trace.allsolid)
+			trace.startsolid = true;
+		if (trace.startsolid)
+			trace.fraction = 0;
+
+	// did we clip the move?
+		if (trace.fraction < total.fraction)
+		{
+			// fix trace up by the offset
+			VectorAdd (trace.endpos, offset, trace.endpos);
+			total = trace;
+			total.ent = i;
+		}
+
+	}
+
+	return total;
+}
+
+
--- /dev/null
+++ b/QW/client/protocol.h
@@ -1,0 +1,282 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// protocol.h -- communications protocols
+
+#define	PROTOCOL_VERSION	28
+
+#define QW_CHECK_HASH 0x5157
+
+//=========================================
+
+#define	PORT_CLIENT	27001
+#define	PORT_MASTER	27000
+#define	PORT_SERVER	27500
+
+//=========================================
+
+// out of band message id bytes
+
+// M = master, S = server, C = client, A = any
+// the second character will allways be \n if the message isn't a single
+// byte long (?? not true anymore?)
+
+#define	S2C_CHALLENGE		'c'
+#define	S2C_CONNECTION		'j'
+#define	A2A_PING			'k'	// respond with an A2A_ACK
+#define	A2A_ACK				'l'	// general acknowledgement without info
+#define	A2A_NACK			'm'	// [+ comment] general failure
+#define A2A_ECHO			'e' // for echoing
+#define	A2C_PRINT			'n'	// print a message on client
+
+#define	S2M_HEARTBEAT		'a'	// + serverinfo + userlist + fraglist
+#define	A2C_CLIENT_COMMAND	'B'	// + command line
+#define	S2M_SHUTDOWN		'C'
+
+
+//==================
+// note that there are some defs.qc that mirror to these numbers
+// also related to svc_strings[] in cl_parse
+//==================
+
+//
+// server to client
+//
+#define	svc_bad				0
+#define	svc_nop				1
+#define	svc_disconnect		2
+#define	svc_updatestat		3	// [byte] [byte]
+//define	svc_version			4	// [long] server version
+#define	svc_setview			5	// [short] entity number
+#define	svc_sound			6	// <see code>
+//define	svc_time			7	// [float] server time
+#define	svc_print			8	// [byte] id [string] null terminated string
+#define	svc_stufftext		9	// [string] stuffed into client's console buffer
+								// the string should be \n terminated
+#define	svc_setangle		10	// [angle3] set the view angle to this absolute value
+	
+#define	svc_serverdata		11	// [long] protocol ...
+#define	svc_lightstyle		12	// [byte] [string]
+//define	svc_updatename		13	// [byte] [string]
+#define	svc_updatefrags		14	// [byte] [short]
+//define	svc_clientdata		15	// <shortbits + data>
+#define	svc_stopsound		16	// <see code>
+//define	svc_updatecolors	17	// [byte] [byte] [byte]
+//define	svc_particle		18	// [vec3] <variable>
+#define	svc_damage			19
+	
+#define	svc_spawnstatic		20
+//	svc_spawnbinary		21
+#define	svc_spawnbaseline	22
+	
+#define	svc_temp_entity		23	// variable
+#define	svc_setpause		24	// [byte] on / off
+//	svc_signonnum		25	// [byte]  used for the signon sequence
+
+#define	svc_centerprint		26	// [string] to put in center of the screen
+
+#define	svc_killedmonster	27
+#define	svc_foundsecret		28
+
+#define	svc_spawnstaticsound	29	// [coord3] [byte] samp [byte] vol [byte] aten
+
+#define	svc_intermission	30		// [vec3_t] origin [vec3_t] angle
+#define	svc_finale			31		// [string] text
+
+#define	svc_cdtrack			32		// [byte] track
+#define svc_sellscreen		33
+
+#define	svc_smallkick		34		// set client punchangle to 2
+#define	svc_bigkick			35		// set client punchangle to 4
+
+#define	svc_updateping		36		// [byte] [short]
+#define	svc_updateentertime	37		// [byte] [float]
+
+#define	svc_updatestatlong	38		// [byte] [long]
+
+#define	svc_muzzleflash		39		// [short] entity
+
+#define	svc_updateuserinfo	40		// [byte] slot [long] uid
+									// [string] userinfo
+
+#define	svc_download		41		// [short] size [size bytes]
+#define	svc_playerinfo		42		// variable
+#define	svc_nails			43		// [byte] num [48 bits] xyzpy 12 12 12 4 8 
+#define	svc_chokecount		44		// [byte] packets choked
+#define	svc_modellist		45		// [strings]
+#define	svc_soundlist		46		// [strings]
+#define	svc_packetentities	47		// [...]
+#define	svc_deltapacketentities	48		// [...]
+#define svc_maxspeed		49		// maxspeed change, for prediction
+#define svc_entgravity		50		// gravity change, for prediction
+#define svc_setinfo			51		// setinfo on a client
+#define svc_serverinfo		52		// serverinfo
+#define svc_updatepl		53		// [byte] [byte]
+
+
+//==============================================
+
+//
+// client to server
+//
+#define	clc_bad			0
+#define	clc_nop 		1
+//define	clc_doublemove	2
+#define	clc_move		3		// [[usercmd_t]
+#define	clc_stringcmd	4		// [string] message
+#define	clc_delta		5		// [byte] sequence number, requests delta compression of message
+#define clc_tmove		6		// teleport request, spectator only
+#define clc_upload		7		// teleport request, spectator only
+
+
+//==============================================
+
+// playerinfo flags from server
+// playerinfo allways sends: playernum, flags, origin[] and framenumber
+
+#define	PF_MSEC			(1<<0)
+#define	PF_COMMAND		(1<<1)
+#define	PF_VELOCITY1	(1<<2)
+#define	PF_VELOCITY2	(1<<3)
+#define	PF_VELOCITY3	(1<<4)
+#define	PF_MODEL		(1<<5)
+#define	PF_SKINNUM		(1<<6)
+#define	PF_EFFECTS		(1<<7)
+#define	PF_WEAPONFRAME	(1<<8)		// only sent for view player
+#define	PF_DEAD			(1<<9)		// don't block movement any more
+#define	PF_GIB			(1<<10)		// offset the view height differently
+#define	PF_NOGRAV		(1<<11)		// don't apply gravity for prediction
+
+//==============================================
+
+// if the high bit of the client to server byte is set, the low bits are
+// client move cmd bits
+// ms and angle2 are allways sent, the others are optional
+#define	CM_ANGLE1 	(1<<0)
+#define	CM_ANGLE3 	(1<<1)
+#define	CM_FORWARD	(1<<2)
+#define	CM_SIDE		(1<<3)
+#define	CM_UP		(1<<4)
+#define	CM_BUTTONS	(1<<5)
+#define	CM_IMPULSE	(1<<6)
+#define	CM_ANGLE2 	(1<<7)
+
+//==============================================
+
+// the first 16 bits of a packetentities update holds 9 bits
+// of entity number and 7 bits of flags
+#define	U_ORIGIN1	(1<<9)
+#define	U_ORIGIN2	(1<<10)
+#define	U_ORIGIN3	(1<<11)
+#define	U_ANGLE2	(1<<12)
+#define	U_FRAME		(1<<13)
+#define	U_REMOVE	(1<<14)		// REMOVE this entity, don't add it
+#define	U_MOREBITS	(1<<15)
+
+// if MOREBITS is set, these additional flags are read in next
+#define	U_ANGLE1	(1<<0)
+#define	U_ANGLE3	(1<<1)
+#define	U_MODEL		(1<<2)
+#define	U_COLORMAP	(1<<3)
+#define	U_SKIN		(1<<4)
+#define	U_EFFECTS	(1<<5)
+#define	U_SOLID		(1<<6)		// the entity should be solid for prediction
+
+//==============================================
+
+// a sound with no channel is a local only sound
+// the sound field has bits 0-2: channel, 3-12: entity
+#define	SND_VOLUME		(1<<15)		// a byte
+#define	SND_ATTENUATION	(1<<14)		// a byte
+
+#define DEFAULT_SOUND_PACKET_VOLUME 255
+#define DEFAULT_SOUND_PACKET_ATTENUATION 1.0
+
+// svc_print messages have an id, so messages can be filtered
+#define	PRINT_LOW			0
+#define	PRINT_MEDIUM		1
+#define	PRINT_HIGH			2
+#define	PRINT_CHAT			3	// also go to chat buffer
+
+//
+// temp entity events
+//
+#define	TE_SPIKE			0
+#define	TE_SUPERSPIKE		1
+#define	TE_GUNSHOT			2
+#define	TE_EXPLOSION		3
+#define	TE_TAREXPLOSION		4
+#define	TE_LIGHTNING1		5
+#define	TE_LIGHTNING2		6
+#define	TE_WIZSPIKE			7
+#define	TE_KNIGHTSPIKE		8
+#define	TE_LIGHTNING3		9
+#define	TE_LAVASPLASH		10
+#define	TE_TELEPORT			11
+#define	TE_BLOOD			12
+#define	TE_LIGHTNINGBLOOD	13
+
+
+/*
+==========================================================
+
+  ELEMENTS COMMUNICATED ACROSS THE NET
+
+==========================================================
+*/
+
+#define	MAX_CLIENTS		32
+
+#define	UPDATE_BACKUP	64	// copies of entity_state_t to keep buffered
+							// must be power of two
+#define	UPDATE_MASK		(UPDATE_BACKUP-1)
+
+// entity_state_t is the information conveyed from the server
+// in an update message
+typedef struct
+{
+	int		number;			// edict index
+
+	int		flags;			// nolerp, etc
+	vec3_t	origin;
+	vec3_t	angles;
+	int		modelindex;
+	int		frame;
+	int		colormap;
+	int		skinnum;
+	int		effects;
+} entity_state_t;
+
+
+#define	MAX_PACKET_ENTITIES	64	// doesn't count nails
+typedef struct
+{
+	int		num_entities;
+	entity_state_t	entities[MAX_PACKET_ENTITIES];
+} packet_entities_t;
+
+typedef struct usercmd_s
+{
+	byte	msec;
+	vec3_t	angles;
+	short	forwardmove, sidemove, upmove;
+	byte	buttons;
+	byte	impulse;
+} usercmd_t;
+
--- /dev/null
+++ b/QW/client/q.bat
@@ -1,0 +1,1 @@
+dos\quake -basedir \quake\v2 %1 %2 %3 %4 %5 %6 %7 %8 %9
binary files /dev/null b/QW/client/qe3.ico differ
--- /dev/null
+++ b/QW/client/quakeasm.h
@@ -1,0 +1,274 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+//
+// quakeasm.h: general asm header file
+//
+
+#ifdef _WIN32
+#define __i386__	1
+#endif
+
+#ifdef	__i386__
+#define id386	1
+#else
+#define id386	0
+#endif
+
+// !!! must be kept the same as in d_iface.h !!!
+#define TRANSPARENT_COLOR	255
+
+#ifndef NeXT
+#ifndef GLQUAKE
+	.extern C(d_zistepu)
+	.extern C(d_pzbuffer)
+	.extern C(d_zistepv)
+	.extern C(d_zrowbytes)
+	.extern C(d_ziorigin)
+	.extern C(r_turb_s)
+	.extern C(r_turb_t)
+	.extern C(r_turb_pdest)
+	.extern C(r_turb_spancount)
+	.extern C(r_turb_turb)
+	.extern C(r_turb_pbase)
+	.extern C(r_turb_sstep)
+	.extern C(r_turb_tstep)
+	.extern	C(r_bmodelactive)
+	.extern	C(d_sdivzstepu)
+	.extern	C(d_tdivzstepu)
+	.extern	C(d_sdivzstepv)
+	.extern	C(d_tdivzstepv)
+	.extern	C(d_sdivzorigin)
+	.extern	C(d_tdivzorigin)
+	.extern	C(sadjust)
+	.extern	C(tadjust)
+	.extern	C(bbextents)
+	.extern	C(bbextentt)
+	.extern	C(cacheblock)
+	.extern	C(d_viewbuffer)
+	.extern	C(cachewidth)
+	.extern	C(d_pzbuffer)
+	.extern	C(d_zrowbytes)
+	.extern	C(d_zwidth)
+	.extern C(d_scantable)
+	.extern C(r_lightptr)
+	.extern C(r_numvblocks)
+	.extern C(prowdestbase)
+	.extern C(pbasesource)
+	.extern C(r_lightwidth)
+	.extern C(lightright)
+	.extern C(lightrightstep)
+	.extern C(lightdeltastep)
+	.extern C(lightdelta)
+	.extern C(lightright)
+	.extern C(lightdelta)
+	.extern C(sourcetstep)
+	.extern C(surfrowbytes)
+	.extern C(lightrightstep)
+	.extern C(lightdeltastep)
+	.extern C(r_sourcemax)
+	.extern C(r_stepback)
+	.extern C(colormap)
+	.extern C(blocksize)
+	.extern C(sourcesstep)
+	.extern C(lightleft)
+	.extern C(blockdivshift)
+	.extern C(blockdivmask)
+	.extern C(lightleftstep)
+	.extern C(r_origin)
+	.extern C(r_ppn)
+	.extern C(r_pup)
+	.extern C(r_pright)
+	.extern C(ycenter)
+	.extern C(xcenter)
+	.extern C(d_vrectbottom_particle)
+	.extern C(d_vrectright_particle)
+	.extern C(d_vrecty)
+	.extern C(d_vrectx)
+	.extern C(d_pix_shift)
+	.extern C(d_pix_min)
+	.extern C(d_pix_max)
+	.extern C(d_y_aspect_shift)
+	.extern C(screenwidth)
+	.extern C(r_leftclipped)
+	.extern C(r_leftenter)
+	.extern C(r_rightclipped)
+	.extern C(r_rightenter)
+	.extern C(modelorg)
+	.extern C(xscale)
+	.extern C(r_refdef)
+	.extern C(yscale)
+	.extern C(r_leftexit)
+	.extern C(r_rightexit)
+	.extern C(r_lastvertvalid)
+	.extern C(cacheoffset)
+	.extern C(newedges)
+	.extern C(removeedges)
+	.extern C(r_pedge)
+	.extern C(r_framecount)
+	.extern C(r_u1)
+	.extern C(r_emitted)
+	.extern C(edge_p)
+	.extern C(surface_p)
+	.extern C(surfaces)
+	.extern C(r_lzi1)
+	.extern C(r_v1)
+	.extern C(r_ceilv1)
+	.extern C(r_nearzi)
+	.extern C(r_nearzionly)
+	.extern C(edge_aftertail)
+	.extern C(edge_tail)
+	.extern C(current_iv)
+	.extern C(edge_head_u_shift20)
+	.extern C(span_p)
+	.extern C(edge_head)
+	.extern C(fv)
+	.extern C(edge_tail_u_shift20)
+	.extern C(r_apverts)
+	.extern C(r_anumverts)
+	.extern C(aliastransform)
+	.extern C(r_avertexnormals)
+	.extern C(r_plightvec)
+	.extern C(r_ambientlight)
+	.extern C(r_shadelight)
+	.extern C(aliasxcenter)
+	.extern C(aliasycenter)
+	.extern C(a_sstepxfrac)
+	.extern C(r_affinetridesc)
+	.extern C(acolormap)
+	.extern C(d_pcolormap)
+	.extern C(r_affinetridesc)
+	.extern C(d_sfrac)
+	.extern C(d_ptex)
+	.extern C(d_pedgespanpackage)
+	.extern C(d_tfrac)
+	.extern C(d_light)
+	.extern C(d_zi)
+	.extern C(d_pdest)
+	.extern C(d_pz)
+	.extern C(d_aspancount)
+	.extern C(erroradjustup)
+	.extern C(errorterm)
+	.extern C(d_xdenom)
+	.extern C(r_p0)
+	.extern C(r_p1)
+	.extern C(r_p2)
+	.extern C(a_tstepxfrac)
+	.extern C(r_sstepx)
+	.extern C(r_tstepx)
+	.extern C(a_ststepxwhole)
+	.extern C(zspantable)
+	.extern C(skintable)
+	.extern C(r_zistepx)
+	.extern C(erroradjustdown)
+	.extern C(d_countextrastep)
+	.extern C(ubasestep)
+	.extern C(a_ststepxwhole)
+	.extern C(a_tstepxfrac)
+	.extern C(r_lstepx)
+	.extern C(a_spans)
+	.extern C(erroradjustdown)
+	.extern C(d_pdestextrastep)
+	.extern C(d_pzextrastep)
+	.extern C(d_sfracextrastep)
+	.extern C(d_ptexextrastep)
+	.extern C(d_countextrastep)
+	.extern C(d_tfracextrastep)
+	.extern C(d_lightextrastep)
+	.extern C(d_ziextrastep)
+	.extern C(d_pdestbasestep)
+	.extern C(d_pzbasestep)
+	.extern C(d_sfracbasestep)
+	.extern C(d_ptexbasestep)
+	.extern C(ubasestep)
+	.extern C(d_tfracbasestep)
+	.extern C(d_lightbasestep)
+	.extern C(d_zibasestep)
+	.extern C(zspantable)
+	.extern C(r_lstepy)
+	.extern C(r_sstepy)
+	.extern C(r_tstepy)
+	.extern C(r_zistepy)
+	.extern C(D_PolysetSetEdgeTable)
+	.extern C(D_RasterizeAliasPolySmooth)
+
+	.extern float_point5
+	.extern Float2ToThe31nd
+	.extern izistep
+	.extern izi
+	.extern FloatMinus2ToThe31nd
+	.extern float_1
+	.extern float_particle_z_clip
+	.extern float_minus_1
+	.extern float_0
+	.extern fp_16
+	.extern fp_64k
+	.extern fp_1m
+	.extern fp_1m_minus_1
+	.extern fp_8 
+	.extern entryvec_table
+	.extern advancetable
+	.extern sstep
+	.extern tstep
+	.extern pspantemp
+	.extern counttemp
+	.extern jumptemp
+	.extern reciprocal_table
+	.extern DP_Count
+	.extern DP_u
+	.extern DP_v
+	.extern DP_32768
+	.extern DP_Color
+	.extern DP_Pix
+	.extern DP_EntryTable
+	.extern	pbase
+	.extern s
+	.extern t
+	.extern sfracf
+	.extern tfracf
+	.extern snext
+	.extern tnext
+	.extern	spancountminus1
+	.extern zi16stepu
+	.extern sdivz16stepu
+	.extern tdivz16stepu
+	.extern	zi8stepu
+	.extern sdivz8stepu
+	.extern tdivz8stepu
+	.extern reciprocal_table_16
+	.extern entryvec_table_16
+	.extern ceil_cw
+	.extern single_cw
+	.extern fp_64kx64k
+	.extern pz
+	.extern spr8entryvec_table
+#endif
+
+	.extern C(snd_scaletable)
+	.extern C(paintbuffer)
+	.extern C(snd_linear_count)
+	.extern C(snd_p)
+	.extern C(snd_vol)
+	.extern C(snd_out)
+	.extern C(vright)
+	.extern C(vup)
+	.extern C(vpn)
+	.extern C(BOPS_Error)
+
+#endif
--- /dev/null
+++ b/QW/client/quakedef.h
@@ -1,0 +1,142 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// quakedef.h -- primary header for client
+
+#define	QUAKE_GAME			// as opposed to utilities
+
+//define	PARANOID			// speed sapping error checking
+
+#ifdef _WIN32
+#pragma warning( disable : 4244 4127 4201 4214 4514 4305 4115 4018)
+#endif
+
+
+#include <math.h>
+#include <string.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <setjmp.h>
+#include <time.h>
+
+#include "bothdefs.h"
+
+#include "common.h"
+#include "bspfile.h"
+#include "vid.h"
+#include "sys.h"
+#include "zone.h"
+#include "mathlib.h"
+#include "wad.h"
+#include "draw.h"
+#include "cvar.h"
+#include "screen.h"
+#include "net.h"
+#include "protocol.h"
+#include "cmd.h"
+#include "sbar.h"
+#include "sound.h"
+#include "render.h"
+#include "client.h"
+
+#ifdef GLQUAKE
+#include "gl_model.h"
+#else
+#include "model.h"
+#include "d_iface.h"
+#endif
+
+#include "input.h"
+#include "keys.h"
+#include "console.h"
+#include "view.h"
+#include "menu.h"
+#include "crc.h"
+#include "cdaudio.h"
+#include "pmove.h"
+
+#ifdef GLQUAKE
+#include "glquake.h"
+#endif
+
+#ifndef max
+#define max(a,b) ((a) > (b) ? (a) : (b))
+#define min(a,b) ((a) < (b) ? (a) : (b))
+#endif
+
+//=============================================================================
+
+// the host system specifies the base of the directory tree, the
+// command line parms passed to the program, and the amount of memory
+// available for the program to use
+
+typedef struct
+{
+	char	*basedir;
+	char	*cachedir;		// for development over ISDN lines
+	int		argc;
+	char	**argv;
+	void	*membase;
+	int		memsize;
+} quakeparms_t;
+
+
+//=============================================================================
+
+#define MAX_NUM_ARGVS	50
+
+
+extern qboolean noclip_anglehack;
+
+
+//
+// host
+//
+extern	quakeparms_t host_parms;
+
+extern	cvar_t		sys_ticrate;
+extern	cvar_t		sys_nostdout;
+extern	cvar_t		developer;
+
+extern	cvar_t	password;
+
+extern	qboolean	host_initialized;		// true if into command execution
+extern	double		host_frametime;
+extern	byte		*host_basepal;
+extern	byte		*host_colormap;
+extern	int			host_framecount;	// incremented every frame, never reset
+extern	double		realtime;			// not bounded in any way, changed at
+										// start of every frame, never reset
+
+void Host_ServerFrame (void);
+void Host_InitCommands (void);
+void Host_Init (quakeparms_t *parms);
+void Host_Shutdown(void);
+void Host_Error (char *error, ...);
+void Host_EndGame (char *message, ...);
+qboolean Host_SimulationTime(float time);
+void Host_Frame (float time);
+void Host_Quit_f (void);
+void Host_ClientCommands (char *fmt, ...);
+void Host_ShutdownServer (qboolean crash);
+
+extern qboolean		msg_suppress_1;		// suppresses resolution and cache size console output
+										//  an fullscreen DIB focus gain/loss
+
binary files /dev/null b/QW/client/quakeworld.bmp differ
--- /dev/null
+++ b/QW/client/qwcl.dsp
@@ -1,0 +1,2213 @@
+# Microsoft Developer Studio Project File - Name="qwcl" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+
+CFG=qwcl - Win32 Release
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "qwcl.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "qwcl.mak" CFG="qwcl - Win32 Release"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "qwcl - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "qwcl - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE "qwcl - Win32 GLDebug" (based on "Win32 (x86) Application")
+!MESSAGE "qwcl - Win32 GLRelease" (based on "Win32 (x86) Application")
+!MESSAGE 
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir ".\Release"
+# PROP BASE Intermediate_Dir ".\Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir ".\Release"
+# PROP Intermediate_Dir ".\Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c
+# ADD CPP /nologo /G5 /GX /O2 /I "..\dxsdk\sdk\inc" /I "..\scitech\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FR /YX /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
+# ADD LINK32 ..\scitech\lib\win32\vc\mgllt.lib ..\dxsdk\sdk\lib\dxguid.lib opengl32.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib winmm.lib /nologo /subsystem:windows /incremental:yes /machine:I386
+# SUBTRACT LINK32 /nodefaultlib
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir ".\Debug"
+# PROP BASE Intermediate_Dir ".\Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir ".\Debug"
+# PROP Intermediate_Dir ".\Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c
+# ADD CPP /nologo /G5 /ML /Gm /GX /ZI /Od /I "..\dxsdk\sdk\inc" /I "..\scitech\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /YX /FD /c
+# ADD BASE MTL /nologo /D "_DEBUG" /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386
+# ADD LINK32 ..\scitech\lib\win32\vc\mgllt.lib ..\dxsdk\sdk\lib\dxguid.lib opengl32.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib winmm.lib /nologo /subsystem:windows /debug /machine:I386
+# SUBTRACT LINK32 /profile /map /nodefaultlib
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLDebug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir ".\qwcl___0"
+# PROP BASE Intermediate_Dir ".\qwcl___0"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir ".\GLDebug"
+# PROP Intermediate_Dir ".\GLDebug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /ML /Gm /GX /Zi /Od /I "e:\msdev\projects\dxsdk\sdk\inc" /I "e:\msdev\projects\scitech\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /YX /c
+# ADD CPP /nologo /G5 /ML /GX /ZI /Od /I "..\dxsdk\sdk\inc" /I "..\scitech\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "GLQUAKE" /FR /YX /FD /c
+# ADD BASE MTL /nologo /D "_DEBUG" /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 opengl32.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib winmm.lib e:\msdev\projects\scitech\lib\win32\vc\mgllt.lib /nologo /subsystem:windows /debug /machine:I386
+# SUBTRACT BASE LINK32 /nodefaultlib
+# ADD LINK32 comctl32.lib glu32.lib ..\dxsdk\sdk\lib\dxguid.lib opengl32.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib winmm.lib /nologo /subsystem:windows /debug /machine:I386 /out:".\GLDebug\glqwcl.exe"
+# SUBTRACT LINK32 /incremental:no /nodefaultlib
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLRelease"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir ".\qwcl___W"
+# PROP BASE Intermediate_Dir ".\qwcl___W"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir ".\GLRelease"
+# PROP Intermediate_Dir ".\GLRelease"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /G5 /ML /GX /Zi /Od /I "e:\msdev\projects\dxsdk\sdk\inc" /I "e:\msdev\projects\scitech\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "GLQUAKE" /FR /YX /c
+# ADD CPP /nologo /G5 /ML /GX /Ot /Ow /I "..\dxsdk\sdk\inc" /I "..\scitech\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "GLQUAKE" /YX /FD /c
+# ADD BASE MTL /nologo /D "_DEBUG" /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 e:\msdev\projects\winquake\dxsdk\sdk\lib\dxguid.lib winmm.lib wsock32.lib opengl32.lib glu32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /out:"GLDebug/glqwcl.exe"
+# SUBTRACT BASE LINK32 /nodefaultlib
+# ADD LINK32 comctl32.lib glu32.lib ..\dxsdk\sdk\lib\dxguid.lib opengl32.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib winmm.lib /nologo /subsystem:windows /incremental:no /debug /machine:I386 /out:".\GLRelease\glqwcl.exe"
+# SUBTRACT LINK32 /nodefaultlib
+
+!ENDIF 
+
+# Begin Target
+
+# Name "qwcl - Win32 Release"
+# Name "qwcl - Win32 Debug"
+# Name "qwcl - Win32 GLDebug"
+# Name "qwcl - Win32 GLRelease"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;hpj;bat;for;f90"
+# Begin Source File
+
+SOURCE=.\cd_win.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\cl_cam.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\cl_demo.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\cl_ents.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\cl_input.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\cl_main.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\cl_parse.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\cl_pred.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\cl_tent.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\cmd.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\common.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\console.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\crc.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\cvar.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\d_draw.s
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+# Begin Custom Build
+OutDir=.\Release
+InputPath=.\d_draw.s
+InputName=d_draw
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) 
+	..\gas2masm\debug\gas2masm.exe < $(OUTDIR)\$(InputName).spp          >$(OUTDIR)\$(InputName).asm 
+	ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi                                                                                                                                                                                                                           $(OUTDIR)\$(InputName).asm 
+	del $(OUTDIR)\$(InputName).spp 
+	
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+# Begin Custom Build - GAS2MASM Conversion
+OutDir=.\Debug
+InputPath=.\d_draw.s
+InputName=d_draw
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) 
+	..\gas2masm\debug\gas2masm.exe < $(OUTDIR)\$(InputName).spp          >$(OUTDIR)\$(InputName).asm 
+	ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi                                                                                                                                                                                                                           $(OUTDIR)\$(InputName).asm 
+	del $(OUTDIR)\$(InputName).spp 
+	
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLDebug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLRelease"
+
+# PROP BASE Exclude_From_Build 1
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\d_draw16.s
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+# Begin Custom Build
+OutDir=.\Release
+InputPath=.\d_draw16.s
+InputName=d_draw16
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) 
+	..\gas2masm\debug\gas2masm.exe < $(OUTDIR)\$(InputName).spp          >$(OUTDIR)\$(InputName).asm 
+	ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi                                                                                                                                                                                                                           $(OUTDIR)\$(InputName).asm 
+	del $(OUTDIR)\$(InputName).spp 
+	
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+# Begin Custom Build - GAS2MASM Conversion
+OutDir=.\Debug
+InputPath=.\d_draw16.s
+InputName=d_draw16
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) 
+	..\gas2masm\debug\gas2masm.exe < $(OUTDIR)\$(InputName).spp          >$(OUTDIR)\$(InputName).asm 
+	ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi                                                                                                                                                                                                                           $(OUTDIR)\$(InputName).asm 
+	del $(OUTDIR)\$(InputName).spp 
+	
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLDebug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLRelease"
+
+# PROP BASE Exclude_From_Build 1
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\d_edge.c
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLDebug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLRelease"
+
+# PROP BASE Exclude_From_Build 1
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\d_fill.c
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLDebug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLRelease"
+
+# PROP BASE Exclude_From_Build 1
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\d_init.c
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLDebug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLRelease"
+
+# PROP BASE Exclude_From_Build 1
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\d_modech.c
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLDebug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLRelease"
+
+# PROP BASE Exclude_From_Build 1
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\d_part.c
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLDebug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLRelease"
+
+# PROP BASE Exclude_From_Build 1
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\d_parta.s
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+# Begin Custom Build
+OutDir=.\Release
+InputPath=.\d_parta.s
+InputName=d_parta
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) 
+	..\gas2masm\debug\gas2masm.exe < $(OUTDIR)\$(InputName).spp          >$(OUTDIR)\$(InputName).asm 
+	ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi                                                                                                                                                                                                                           $(OUTDIR)\$(InputName).asm 
+	del $(OUTDIR)\$(InputName).spp 
+	
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+# Begin Custom Build - GAS2MASM Conversion
+OutDir=.\Debug
+InputPath=.\d_parta.s
+InputName=d_parta
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) 
+	..\gas2masm\debug\gas2masm.exe < $(OUTDIR)\$(InputName).spp          >$(OUTDIR)\$(InputName).asm 
+	ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi                                                                                                                                                                                                                           $(OUTDIR)\$(InputName).asm 
+	del $(OUTDIR)\$(InputName).spp 
+	
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLDebug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLRelease"
+
+# PROP BASE Exclude_From_Build 1
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\d_polysa.s
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+# Begin Custom Build
+OutDir=.\Release
+InputPath=.\d_polysa.s
+InputName=d_polysa
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) 
+	..\gas2masm\debug\gas2masm.exe < $(OUTDIR)\$(InputName).spp          >$(OUTDIR)\$(InputName).asm 
+	ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi                                                                                                                                                                                                                           $(OUTDIR)\$(InputName).asm 
+	del $(OUTDIR)\$(InputName).spp 
+	
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+# Begin Custom Build - GAS2MASM Conversion
+OutDir=.\Debug
+InputPath=.\d_polysa.s
+InputName=d_polysa
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) 
+	..\gas2masm\debug\gas2masm.exe < $(OUTDIR)\$(InputName).spp          >$(OUTDIR)\$(InputName).asm 
+	ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi                                                                                                                                                                                                                           $(OUTDIR)\$(InputName).asm 
+	del $(OUTDIR)\$(InputName).spp 
+	
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLDebug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLRelease"
+
+# PROP BASE Exclude_From_Build 1
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\d_polyse.c
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLDebug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLRelease"
+
+# PROP BASE Exclude_From_Build 1
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\d_scan.c
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLDebug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLRelease"
+
+# PROP BASE Exclude_From_Build 1
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\d_scana.s
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+# Begin Custom Build
+OutDir=.\Release
+InputPath=.\d_scana.s
+InputName=d_scana
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) 
+	..\gas2masm\debug\gas2masm.exe < $(OUTDIR)\$(InputName).spp          >$(OUTDIR)\$(InputName).asm 
+	ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi                                                                                                                                                                                                                           $(OUTDIR)\$(InputName).asm 
+	del $(OUTDIR)\$(InputName).spp 
+	
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+# Begin Custom Build - GAS2MASM Conversion
+OutDir=.\Debug
+InputPath=.\d_scana.s
+InputName=d_scana
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) 
+	..\gas2masm\debug\gas2masm.exe < $(OUTDIR)\$(InputName).spp          >$(OUTDIR)\$(InputName).asm 
+	ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi                                                                                                                                                                                                                           $(OUTDIR)\$(InputName).asm 
+	del $(OUTDIR)\$(InputName).spp 
+	
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLDebug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLRelease"
+
+# PROP BASE Exclude_From_Build 1
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\d_sky.c
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLDebug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLRelease"
+
+# PROP BASE Exclude_From_Build 1
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\d_spr8.s
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+# Begin Custom Build
+OutDir=.\Release
+InputPath=.\d_spr8.s
+InputName=d_spr8
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) 
+	..\gas2masm\debug\gas2masm.exe < $(OUTDIR)\$(InputName).spp          >$(OUTDIR)\$(InputName).asm 
+	ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi                                                                                                                                                                                                                           $(OUTDIR)\$(InputName).asm 
+	del $(OUTDIR)\$(InputName).spp 
+	
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+# Begin Custom Build - GAS2MASM Conversion
+OutDir=.\Debug
+InputPath=.\d_spr8.s
+InputName=d_spr8
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) 
+	..\gas2masm\debug\gas2masm.exe < $(OUTDIR)\$(InputName).spp          >$(OUTDIR)\$(InputName).asm 
+	ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi                                                                                                                                                                                                                           $(OUTDIR)\$(InputName).asm 
+	del $(OUTDIR)\$(InputName).spp 
+	
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLDebug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLRelease"
+
+# PROP BASE Exclude_From_Build 1
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\d_sprite.c
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLDebug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLRelease"
+
+# PROP BASE Exclude_From_Build 1
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\d_surf.c
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLDebug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLRelease"
+
+# PROP BASE Exclude_From_Build 1
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\d_vars.c
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLDebug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLRelease"
+
+# PROP BASE Exclude_From_Build 1
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\d_varsa.s
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+# Begin Custom Build
+OutDir=.\Release
+InputPath=.\d_varsa.s
+InputName=d_varsa
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) 
+	..\gas2masm\debug\gas2masm.exe < $(OUTDIR)\$(InputName).spp          >$(OUTDIR)\$(InputName).asm 
+	ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi                                                                                                                                                                                                                           $(OUTDIR)\$(InputName).asm 
+	del $(OUTDIR)\$(InputName).spp 
+	
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+# Begin Custom Build - GAS2MASM Conversion
+OutDir=.\Debug
+InputPath=.\d_varsa.s
+InputName=d_varsa
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) 
+	..\gas2masm\debug\gas2masm.exe < $(OUTDIR)\$(InputName).spp          >$(OUTDIR)\$(InputName).asm 
+	ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi                                                                                                                                                                                                                           $(OUTDIR)\$(InputName).asm 
+	del $(OUTDIR)\$(InputName).spp 
+	
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLDebug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLRelease"
+
+# PROP BASE Exclude_From_Build 1
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\d_zpoint.c
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLDebug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLRelease"
+
+# PROP BASE Exclude_From_Build 1
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\draw.c
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLDebug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLRelease"
+
+# PROP BASE Exclude_From_Build 1
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\gl_draw.c
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLDebug"
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLRelease"
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\gl_mesh.c
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLDebug"
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLRelease"
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\gl_model.c
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLDebug"
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLRelease"
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\gl_ngraph.c
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLDebug"
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLRelease"
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\gl_refrag.c
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLDebug"
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLRelease"
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\gl_rlight.c
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLDebug"
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLRelease"
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\gl_rmain.c
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLDebug"
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLRelease"
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\gl_rmisc.c
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLDebug"
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLRelease"
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\gl_rsurf.c
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLDebug"
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLRelease"
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\gl_screen.c
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLDebug"
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLRelease"
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\gl_test.c
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLDebug"
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLRelease"
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\gl_vidnt.c
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLDebug"
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLRelease"
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\gl_warp.c
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLDebug"
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLRelease"
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\in_win.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\keys.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\math.s
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+# Begin Custom Build
+OutDir=.\Release
+InputPath=.\math.s
+InputName=math
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) 
+	..\gas2masm\debug\gas2masm.exe < $(OUTDIR)\$(InputName).spp          >$(OUTDIR)\$(InputName).asm 
+	ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi                                                                                                                                                                                                                           $(OUTDIR)\$(InputName).asm 
+	del $(OUTDIR)\$(InputName).spp 
+	
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+# Begin Custom Build - GAS2MASM Conversion
+OutDir=.\Debug
+InputPath=.\math.s
+InputName=math
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) 
+	..\gas2masm\debug\gas2masm.exe < $(OUTDIR)\$(InputName).spp          >$(OUTDIR)\$(InputName).asm 
+	ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi                                                                                                                                                                                                                           $(OUTDIR)\$(InputName).asm 
+	del $(OUTDIR)\$(InputName).spp 
+	
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLDebug"
+
+# Begin Custom Build
+OutDir=.\GLDebug
+InputPath=.\math.s
+InputName=math
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	cl /EP /DGLQUAKE > $(OUTDIR)\$(InputName).spp $(InputPath) 
+	..\gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp >          $(OUTDIR)\$(InputName).asm 
+	ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi                                                                                                                                                                                                                           $(OUTDIR)\$(InputName).asm 
+	del $(OUTDIR)\$(InputName).spp 
+	
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLRelease"
+
+# Begin Custom Build
+OutDir=.\GLRelease
+InputPath=.\math.s
+InputName=math
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	cl /EP /DGLQUAKE > $(OUTDIR)\$(InputName).spp $(InputPath) 
+	..\gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp >          $(OUTDIR)\$(InputName).asm 
+	ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi                                                                                                                                                                                                                           $(OUTDIR)\$(InputName).asm 
+	del $(OUTDIR)\$(InputName).spp 
+	
+# End Custom Build
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\mathlib.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\md4.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\menu.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\model.c
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLDebug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLRelease"
+
+# PROP BASE Exclude_From_Build 1
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\net_chan.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\net_wins.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\nonintel.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\pmove.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\pmovetst.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\r_aclip.c
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLDebug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLRelease"
+
+# PROP BASE Exclude_From_Build 1
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\r_aclipa.s
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+# Begin Custom Build
+OutDir=.\Release
+InputPath=.\r_aclipa.s
+InputName=r_aclipa
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) 
+	..\gas2masm\debug\gas2masm.exe < $(OUTDIR)\$(InputName).spp          >$(OUTDIR)\$(InputName).asm 
+	ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi                                                                                                                                                                                                                           $(OUTDIR)\$(InputName).asm 
+	del $(OUTDIR)\$(InputName).spp 
+	
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+# Begin Custom Build - GAS2MASM Conversion
+OutDir=.\Debug
+InputPath=.\r_aclipa.s
+InputName=r_aclipa
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) 
+	..\gas2masm\debug\gas2masm.exe < $(OUTDIR)\$(InputName).spp          >$(OUTDIR)\$(InputName).asm 
+	ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi                                                                                                                                                                                                                           $(OUTDIR)\$(InputName).asm 
+	del $(OUTDIR)\$(InputName).spp 
+	
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLDebug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLRelease"
+
+# PROP BASE Exclude_From_Build 1
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\r_alias.c
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLDebug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLRelease"
+
+# PROP BASE Exclude_From_Build 1
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\r_aliasa.s
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+# Begin Custom Build
+OutDir=.\Release
+InputPath=.\r_aliasa.s
+InputName=r_aliasa
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) 
+	..\gas2masm\debug\gas2masm.exe < $(OUTDIR)\$(InputName).spp          >$(OUTDIR)\$(InputName).asm 
+	ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi                                                                                                                                                                                                                           $(OUTDIR)\$(InputName).asm 
+	del $(OUTDIR)\$(InputName).spp 
+	
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+# Begin Custom Build - GAS2MASM Conversion
+OutDir=.\Debug
+InputPath=.\r_aliasa.s
+InputName=r_aliasa
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) 
+	..\gas2masm\debug\gas2masm.exe < $(OUTDIR)\$(InputName).spp          >$(OUTDIR)\$(InputName).asm 
+	ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi                                                                                                                                                                                                                           $(OUTDIR)\$(InputName).asm 
+	del $(OUTDIR)\$(InputName).spp 
+	
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLDebug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLRelease"
+
+# PROP BASE Exclude_From_Build 1
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\r_bsp.c
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLDebug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLRelease"
+
+# PROP BASE Exclude_From_Build 1
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\r_draw.c
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLDebug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLRelease"
+
+# PROP BASE Exclude_From_Build 1
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\r_drawa.s
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+# Begin Custom Build
+OutDir=.\Release
+InputPath=.\r_drawa.s
+InputName=r_drawa
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) 
+	..\gas2masm\debug\gas2masm.exe < $(OUTDIR)\$(InputName).spp          >$(OUTDIR)\$(InputName).asm 
+	ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi                                                                                                                                                                                                                           $(OUTDIR)\$(InputName).asm 
+	del $(OUTDIR)\$(InputName).spp 
+	
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+# Begin Custom Build - GAS2MASM Conversion
+OutDir=.\Debug
+InputPath=.\r_drawa.s
+InputName=r_drawa
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) 
+	..\gas2masm\debug\gas2masm.exe < $(OUTDIR)\$(InputName).spp          >$(OUTDIR)\$(InputName).asm 
+	ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi                                                                                                                                                                                                                           $(OUTDIR)\$(InputName).asm 
+	del $(OUTDIR)\$(InputName).spp 
+	
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLDebug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLRelease"
+
+# PROP BASE Exclude_From_Build 1
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\r_edge.c
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLDebug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLRelease"
+
+# PROP BASE Exclude_From_Build 1
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\r_edgea.s
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+# Begin Custom Build
+OutDir=.\Release
+InputPath=.\r_edgea.s
+InputName=r_edgea
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) 
+	..\gas2masm\debug\gas2masm.exe < $(OUTDIR)\$(InputName).spp          >$(OUTDIR)\$(InputName).asm 
+	ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi                                                                                                                                                                                                                           $(OUTDIR)\$(InputName).asm 
+	del $(OUTDIR)\$(InputName).spp 
+	
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+# Begin Custom Build - GAS2MASM Conversion
+OutDir=.\Debug
+InputPath=.\r_edgea.s
+InputName=r_edgea
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) 
+	..\gas2masm\debug\gas2masm.exe < $(OUTDIR)\$(InputName).spp          >$(OUTDIR)\$(InputName).asm 
+	ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi                                                                                                                                                                                                                           $(OUTDIR)\$(InputName).asm 
+	del $(OUTDIR)\$(InputName).spp 
+	
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLDebug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLRelease"
+
+# PROP BASE Exclude_From_Build 1
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\r_efrag.c
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLDebug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLRelease"
+
+# PROP BASE Exclude_From_Build 1
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\r_light.c
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLDebug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLRelease"
+
+# PROP BASE Exclude_From_Build 1
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\r_main.c
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLDebug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLRelease"
+
+# PROP BASE Exclude_From_Build 1
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\r_misc.c
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLDebug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLRelease"
+
+# PROP BASE Exclude_From_Build 1
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\r_part.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\r_sky.c
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLDebug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLRelease"
+
+# PROP BASE Exclude_From_Build 1
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\r_sprite.c
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLDebug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLRelease"
+
+# PROP BASE Exclude_From_Build 1
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\r_surf.c
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLDebug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLRelease"
+
+# PROP BASE Exclude_From_Build 1
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\r_vars.c
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLDebug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLRelease"
+
+# PROP BASE Exclude_From_Build 1
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\r_varsa.s
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+# Begin Custom Build
+OutDir=.\Release
+InputPath=.\r_varsa.s
+InputName=r_varsa
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) 
+	..\gas2masm\debug\gas2masm.exe < $(OUTDIR)\$(InputName).spp          >$(OUTDIR)\$(InputName).asm 
+	ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi                                                                                                                                                                                                                           $(OUTDIR)\$(InputName).asm 
+	del $(OUTDIR)\$(InputName).spp 
+	
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+# Begin Custom Build - GAS2MASM Conversion
+OutDir=.\Debug
+InputPath=.\r_varsa.s
+InputName=r_varsa
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) 
+	..\gas2masm\debug\gas2masm.exe < $(OUTDIR)\$(InputName).spp          >$(OUTDIR)\$(InputName).asm 
+	ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi                                                                                                                                                                                                                           $(OUTDIR)\$(InputName).asm 
+	del $(OUTDIR)\$(InputName).spp 
+	
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLDebug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLRelease"
+
+# PROP BASE Exclude_From_Build 1
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\sbar.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\screen.c
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLDebug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLRelease"
+
+# PROP BASE Exclude_From_Build 1
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\skin.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\snd_dma.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\snd_mem.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\snd_mix.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\snd_mixa.s
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+# Begin Custom Build
+OutDir=.\Release
+InputPath=.\snd_mixa.s
+InputName=snd_mixa
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) 
+	..\gas2masm\debug\gas2masm.exe < $(OUTDIR)\$(InputName).spp          >$(OUTDIR)\$(InputName).asm 
+	ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi                                                                                                                                                                                                                           $(OUTDIR)\$(InputName).asm 
+	del $(OUTDIR)\$(InputName).spp 
+	
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+# Begin Custom Build - GAS2MASM Conversion
+OutDir=.\Debug
+InputPath=.\snd_mixa.s
+InputName=snd_mixa
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) 
+	..\gas2masm\debug\gas2masm.exe < $(OUTDIR)\$(InputName).spp          >$(OUTDIR)\$(InputName).asm 
+	ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi                                                                                                                                                                                                                           $(OUTDIR)\$(InputName).asm 
+	del $(OUTDIR)\$(InputName).spp 
+	
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLDebug"
+
+# Begin Custom Build
+OutDir=.\GLDebug
+InputPath=.\snd_mixa.s
+InputName=snd_mixa
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	cl /EP /DGLQUAKE > $(OUTDIR)\$(InputName).spp $(InputPath) 
+	..\gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp >          $(OUTDIR)\$(InputName).asm 
+	ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi                                                                                                                                                                                                                           $(OUTDIR)\$(InputName).asm 
+	del $(OUTDIR)\$(InputName).spp 
+	
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLRelease"
+
+# Begin Custom Build
+OutDir=.\GLRelease
+InputPath=.\snd_mixa.s
+InputName=snd_mixa
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	cl /EP /DGLQUAKE > $(OUTDIR)\$(InputName).spp $(InputPath) 
+	..\gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp >          $(OUTDIR)\$(InputName).asm 
+	ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi                                                                                                                                                                                                                           $(OUTDIR)\$(InputName).asm 
+	del $(OUTDIR)\$(InputName).spp 
+	
+# End Custom Build
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\snd_win.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\surf16.s
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+# Begin Custom Build
+OutDir=.\Release
+InputPath=.\surf16.s
+InputName=surf16
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) 
+	..\gas2masm\debug\gas2masm.exe < $(OUTDIR)\$(InputName).spp          >$(OUTDIR)\$(InputName).asm 
+	ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi                                                                                                                                                                                                                           $(OUTDIR)\$(InputName).asm 
+	del $(OUTDIR)\$(InputName).spp 
+	
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+# Begin Custom Build - GAS2MASM Conversion
+OutDir=.\Debug
+InputPath=.\surf16.s
+InputName=surf16
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) 
+	..\gas2masm\debug\gas2masm.exe < $(OUTDIR)\$(InputName).spp          >$(OUTDIR)\$(InputName).asm 
+	ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi                                                                                                                                                                                                                           $(OUTDIR)\$(InputName).asm 
+	del $(OUTDIR)\$(InputName).spp 
+	
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLDebug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLRelease"
+
+# PROP BASE Exclude_From_Build 1
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\surf8.s
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+# Begin Custom Build
+OutDir=.\Release
+InputPath=.\surf8.s
+InputName=surf8
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) 
+	..\gas2masm\debug\gas2masm.exe < $(OUTDIR)\$(InputName).spp          >$(OUTDIR)\$(InputName).asm 
+	ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi                                                                                                                                                                                                                           $(OUTDIR)\$(InputName).asm 
+	del $(OUTDIR)\$(InputName).spp 
+	
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+# Begin Custom Build - GAS2MASM Conversion
+OutDir=.\Debug
+InputPath=.\surf8.s
+InputName=surf8
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) 
+	..\gas2masm\debug\gas2masm.exe < $(OUTDIR)\$(InputName).spp          >$(OUTDIR)\$(InputName).asm 
+	ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi                                                                                                                                                                                                                           $(OUTDIR)\$(InputName).asm 
+	del $(OUTDIR)\$(InputName).spp 
+	
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLDebug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLRelease"
+
+# PROP BASE Exclude_From_Build 1
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\sys_win.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\sys_wina.s
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+# Begin Custom Build
+OutDir=.\Release
+InputPath=.\sys_wina.s
+InputName=sys_wina
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) 
+	..\gas2masm\debug\gas2masm.exe < $(OUTDIR)\$(InputName).spp          >$(OUTDIR)\$(InputName).asm 
+	ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi                                                                                                                                                                                                                           $(OUTDIR)\$(InputName).asm 
+	del $(OUTDIR)\$(InputName).spp 
+	
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+# Begin Custom Build - GAS2MASM Conversion
+OutDir=.\Debug
+InputPath=.\sys_wina.s
+InputName=sys_wina
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) 
+	..\gas2masm\debug\gas2masm.exe < $(OUTDIR)\$(InputName).spp          >$(OUTDIR)\$(InputName).asm 
+	ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi                                                                                                                                                                                                                           $(OUTDIR)\$(InputName).asm 
+	del $(OUTDIR)\$(InputName).spp 
+	
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLDebug"
+
+# Begin Custom Build
+OutDir=.\GLDebug
+InputPath=.\sys_wina.s
+InputName=sys_wina
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	cl /EP /DGLQUAKE > $(OUTDIR)\$(InputName).spp $(InputPath) 
+	..\gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp >          $(OUTDIR)\$(InputName).asm 
+	ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi                                                                                                                                                                                                                           $(OUTDIR)\$(InputName).asm 
+	del $(OUTDIR)\$(InputName).spp 
+	
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLRelease"
+
+# Begin Custom Build
+OutDir=.\GLRelease
+InputPath=.\sys_wina.s
+InputName=sys_wina
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	cl /EP /DGLQUAKE > $(OUTDIR)\$(InputName).spp $(InputPath) 
+	..\gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp >          $(OUTDIR)\$(InputName).asm 
+	ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi                                                                                                                                                                                                                           $(OUTDIR)\$(InputName).asm 
+	del $(OUTDIR)\$(InputName).spp 
+	
+# End Custom Build
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\vid_win.c
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLDebug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLRelease"
+
+# PROP BASE Exclude_From_Build 1
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\view.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\wad.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\winquake.rc
+# End Source File
+# Begin Source File
+
+SOURCE=.\zone.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd"
+# Begin Source File
+
+SOURCE=.\adivtab.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\anorm_dots.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\anorms.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\bothdefs.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\bspfile.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\cdaudio.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\client.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\cmd.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\common.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\console.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\crc.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\cvar.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\d_iface.h
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLDebug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLRelease"
+
+# PROP BASE Exclude_From_Build 1
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\d_ifacea.h
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLDebug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLRelease"
+
+# PROP BASE Exclude_From_Build 1
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\d_local.h
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLDebug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GLRelease"
+
+# PROP BASE Exclude_From_Build 1
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\draw.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\gl_model.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\gl_warp_sin.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\glquake.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\input.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\keys.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\quake\v2\master\masterpr.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\mathlib.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\menu.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\model.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\modelgen.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\net.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\pmove.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\protocol.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\quakedef.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\r_local.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\r_shared.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\render.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\sbar.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\screen.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\sound.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\spritegn.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\sys.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\vid.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\view.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\wad.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\winquake.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\zone.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe"
+# Begin Source File
+
+SOURCE=.\qe3.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\quakeworld.bmp
+# End Source File
+# Begin Source File
+
+SOURCE=.\qwcl2.ico
+# End Source File
+# End Group
+# End Target
+# End Project
--- /dev/null
+++ b/QW/client/qwcl.dsw
@@ -1,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 5.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "qwcl"=.\qwcl.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
--- /dev/null
+++ b/QW/client/qwcl.mak
@@ -1,0 +1,10009 @@
+# Microsoft Developer Studio Generated NMAKE File, Format Version 4.20
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+
+!IF "$(CFG)" == ""
+CFG=qwcl - Win32 GL Debug
+!MESSAGE No configuration specified.  Defaulting to qwcl - Win32 GL Debug.
+!ENDIF 
+
+!IF "$(CFG)" != "qwcl - Win32 Release" && "$(CFG)" != "qwcl - Win32 Debug" &&\
+ "$(CFG)" != "qwcl - Win32 GL Debug" && "$(CFG)" != "qwcl - Win32 GL Release"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE on this makefile
+!MESSAGE by defining the macro CFG on the command line.  For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "qwcl.mak" CFG="qwcl - Win32 GL Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "qwcl - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "qwcl - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE "qwcl - Win32 GL Debug" (based on "Win32 (x86) Application")
+!MESSAGE "qwcl - Win32 GL Release" (based on "Win32 (x86) Application")
+!MESSAGE 
+!ERROR An invalid configuration is specified.
+!ENDIF 
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE 
+NULL=nul
+!ENDIF 
+################################################################################
+# Begin Project
+# PROP Target_Last_Scanned "qwcl - Win32 GL Debug"
+MTL=mktyplib.exe
+CPP=cl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "qwcl___W"
+# PROP BASE Intermediate_Dir "qwcl___W"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "release"
+# PROP Intermediate_Dir "release"
+# PROP Target_Dir ""
+OUTDIR=.\release
+INTDIR=.\release
+
+ALL : "$(OUTDIR)\qwcl.exe"
+
+CLEAN : 
+	-@erase "$(INTDIR)\cd_win.obj"
+	-@erase "$(INTDIR)\cl_cam.obj"
+	-@erase "$(INTDIR)\cl_demo.obj"
+	-@erase "$(INTDIR)\cl_ents.obj"
+	-@erase "$(INTDIR)\cl_input.obj"
+	-@erase "$(INTDIR)\cl_main.obj"
+	-@erase "$(INTDIR)\cl_parse.obj"
+	-@erase "$(INTDIR)\cl_pred.obj"
+	-@erase "$(INTDIR)\cl_tent.obj"
+	-@erase "$(INTDIR)\cmd.obj"
+	-@erase "$(INTDIR)\common.obj"
+	-@erase "$(INTDIR)\console.obj"
+	-@erase "$(INTDIR)\crc.obj"
+	-@erase "$(INTDIR)\cvar.obj"
+	-@erase "$(INTDIR)\d_draw.obj"
+	-@erase "$(INTDIR)\d_draw16.obj"
+	-@erase "$(INTDIR)\d_edge.obj"
+	-@erase "$(INTDIR)\d_fill.obj"
+	-@erase "$(INTDIR)\d_init.obj"
+	-@erase "$(INTDIR)\d_modech.obj"
+	-@erase "$(INTDIR)\d_part.obj"
+	-@erase "$(INTDIR)\d_parta.obj"
+	-@erase "$(INTDIR)\d_polysa.obj"
+	-@erase "$(INTDIR)\d_polyse.obj"
+	-@erase "$(INTDIR)\d_scan.obj"
+	-@erase "$(INTDIR)\d_scana.obj"
+	-@erase "$(INTDIR)\d_sky.obj"
+	-@erase "$(INTDIR)\d_spr8.obj"
+	-@erase "$(INTDIR)\d_sprite.obj"
+	-@erase "$(INTDIR)\d_surf.obj"
+	-@erase "$(INTDIR)\d_vars.obj"
+	-@erase "$(INTDIR)\d_varsa.obj"
+	-@erase "$(INTDIR)\d_zpoint.obj"
+	-@erase "$(INTDIR)\draw.obj"
+	-@erase "$(INTDIR)\in_win.obj"
+	-@erase "$(INTDIR)\keys.obj"
+	-@erase "$(INTDIR)\math.obj"
+	-@erase "$(INTDIR)\mathlib.obj"
+	-@erase "$(INTDIR)\md4.obj"
+	-@erase "$(INTDIR)\menu.obj"
+	-@erase "$(INTDIR)\model.obj"
+	-@erase "$(INTDIR)\net_chan.obj"
+	-@erase "$(INTDIR)\net_wins.obj"
+	-@erase "$(INTDIR)\pmove.obj"
+	-@erase "$(INTDIR)\pmovetst.obj"
+	-@erase "$(INTDIR)\r_aclip.obj"
+	-@erase "$(INTDIR)\r_aclipa.obj"
+	-@erase "$(INTDIR)\r_alias.obj"
+	-@erase "$(INTDIR)\r_aliasa.obj"
+	-@erase "$(INTDIR)\r_bsp.obj"
+	-@erase "$(INTDIR)\r_draw.obj"
+	-@erase "$(INTDIR)\r_drawa.obj"
+	-@erase "$(INTDIR)\r_edge.obj"
+	-@erase "$(INTDIR)\r_edgea.obj"
+	-@erase "$(INTDIR)\r_efrag.obj"
+	-@erase "$(INTDIR)\r_light.obj"
+	-@erase "$(INTDIR)\r_main.obj"
+	-@erase "$(INTDIR)\r_misc.obj"
+	-@erase "$(INTDIR)\r_part.obj"
+	-@erase "$(INTDIR)\r_sky.obj"
+	-@erase "$(INTDIR)\r_sprite.obj"
+	-@erase "$(INTDIR)\r_surf.obj"
+	-@erase "$(INTDIR)\r_vars.obj"
+	-@erase "$(INTDIR)\r_varsa.obj"
+	-@erase "$(INTDIR)\sbar.obj"
+	-@erase "$(INTDIR)\screen.obj"
+	-@erase "$(INTDIR)\skin.obj"
+	-@erase "$(INTDIR)\snd_dma.obj"
+	-@erase "$(INTDIR)\snd_mem.obj"
+	-@erase "$(INTDIR)\snd_mix.obj"
+	-@erase "$(INTDIR)\snd_mixa.obj"
+	-@erase "$(INTDIR)\snd_win.obj"
+	-@erase "$(INTDIR)\surf16.obj"
+	-@erase "$(INTDIR)\surf8.obj"
+	-@erase "$(INTDIR)\sys_win.obj"
+	-@erase "$(INTDIR)\sys_wina.obj"
+	-@erase "$(INTDIR)\vid_win.obj"
+	-@erase "$(INTDIR)\view.obj"
+	-@erase "$(INTDIR)\wad.obj"
+	-@erase "$(INTDIR)\winquake.res"
+	-@erase "$(INTDIR)\zone.obj"
+	-@erase "$(OUTDIR)\qwcl.exe"
+
+"$(OUTDIR)" :
+    if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c
+# ADD CPP /nologo /GX /O2 /I "..\..\scitech\include" /I "..\..\dxsdk\sdk\inc" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c
+# SUBTRACT CPP /X
+CPP_PROJ=/nologo /ML /GX /O2 /I "..\..\scitech\include" /I\
+ "..\..\dxsdk\sdk\inc" /D "WIN32" /D "NDEBUG" /D "_WINDOWS"\
+ /Fp"$(INTDIR)/qwcl.pch" /YX /Fo"$(INTDIR)/" /c 
+CPP_OBJS=.\release/
+CPP_SBRS=.\.
+# ADD BASE MTL /nologo /D "NDEBUG" /win32
+# ADD MTL /nologo /D "NDEBUG" /win32
+MTL_PROJ=/nologo /D "NDEBUG" /win32 
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+RSC_PROJ=/l 0x409 /fo"$(INTDIR)/winquake.res" /d "NDEBUG" 
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+BSC32_FLAGS=/nologo /o"$(OUTDIR)/qwcl.bsc" 
+BSC32_SBRS= \
+	
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
+# ADD LINK32 ..\..\scitech\lib\win32\vc\mgllt.lib ..\..\dxsdk\sdk\lib\dxguid.lib comctl32.lib wsock32.lib winmm.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
+LINK32_FLAGS=..\..\scitech\lib\win32\vc\mgllt.lib\
+ ..\..\dxsdk\sdk\lib\dxguid.lib comctl32.lib wsock32.lib winmm.lib kernel32.lib\
+ user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib\
+ ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo\
+ /subsystem:windows /incremental:no /pdb:"$(OUTDIR)/qwcl.pdb" /machine:I386\
+ /out:"$(OUTDIR)/qwcl.exe" 
+LINK32_OBJS= \
+	"$(INTDIR)\cd_win.obj" \
+	"$(INTDIR)\cl_cam.obj" \
+	"$(INTDIR)\cl_demo.obj" \
+	"$(INTDIR)\cl_ents.obj" \
+	"$(INTDIR)\cl_input.obj" \
+	"$(INTDIR)\cl_main.obj" \
+	"$(INTDIR)\cl_parse.obj" \
+	"$(INTDIR)\cl_pred.obj" \
+	"$(INTDIR)\cl_tent.obj" \
+	"$(INTDIR)\cmd.obj" \
+	"$(INTDIR)\common.obj" \
+	"$(INTDIR)\console.obj" \
+	"$(INTDIR)\crc.obj" \
+	"$(INTDIR)\cvar.obj" \
+	"$(INTDIR)\d_draw.obj" \
+	"$(INTDIR)\d_draw16.obj" \
+	"$(INTDIR)\d_edge.obj" \
+	"$(INTDIR)\d_fill.obj" \
+	"$(INTDIR)\d_init.obj" \
+	"$(INTDIR)\d_modech.obj" \
+	"$(INTDIR)\d_part.obj" \
+	"$(INTDIR)\d_parta.obj" \
+	"$(INTDIR)\d_polysa.obj" \
+	"$(INTDIR)\d_polyse.obj" \
+	"$(INTDIR)\d_scan.obj" \
+	"$(INTDIR)\d_scana.obj" \
+	"$(INTDIR)\d_sky.obj" \
+	"$(INTDIR)\d_spr8.obj" \
+	"$(INTDIR)\d_sprite.obj" \
+	"$(INTDIR)\d_surf.obj" \
+	"$(INTDIR)\d_vars.obj" \
+	"$(INTDIR)\d_varsa.obj" \
+	"$(INTDIR)\d_zpoint.obj" \
+	"$(INTDIR)\draw.obj" \
+	"$(INTDIR)\in_win.obj" \
+	"$(INTDIR)\keys.obj" \
+	"$(INTDIR)\math.obj" \
+	"$(INTDIR)\mathlib.obj" \
+	"$(INTDIR)\md4.obj" \
+	"$(INTDIR)\menu.obj" \
+	"$(INTDIR)\model.obj" \
+	"$(INTDIR)\net_chan.obj" \
+	"$(INTDIR)\net_wins.obj" \
+	"$(INTDIR)\pmove.obj" \
+	"$(INTDIR)\pmovetst.obj" \
+	"$(INTDIR)\r_aclip.obj" \
+	"$(INTDIR)\r_aclipa.obj" \
+	"$(INTDIR)\r_alias.obj" \
+	"$(INTDIR)\r_aliasa.obj" \
+	"$(INTDIR)\r_bsp.obj" \
+	"$(INTDIR)\r_draw.obj" \
+	"$(INTDIR)\r_drawa.obj" \
+	"$(INTDIR)\r_edge.obj" \
+	"$(INTDIR)\r_edgea.obj" \
+	"$(INTDIR)\r_efrag.obj" \
+	"$(INTDIR)\r_light.obj" \
+	"$(INTDIR)\r_main.obj" \
+	"$(INTDIR)\r_misc.obj" \
+	"$(INTDIR)\r_part.obj" \
+	"$(INTDIR)\r_sky.obj" \
+	"$(INTDIR)\r_sprite.obj" \
+	"$(INTDIR)\r_surf.obj" \
+	"$(INTDIR)\r_vars.obj" \
+	"$(INTDIR)\r_varsa.obj" \
+	"$(INTDIR)\sbar.obj" \
+	"$(INTDIR)\screen.obj" \
+	"$(INTDIR)\skin.obj" \
+	"$(INTDIR)\snd_dma.obj" \
+	"$(INTDIR)\snd_mem.obj" \
+	"$(INTDIR)\snd_mix.obj" \
+	"$(INTDIR)\snd_mixa.obj" \
+	"$(INTDIR)\snd_win.obj" \
+	"$(INTDIR)\surf16.obj" \
+	"$(INTDIR)\surf8.obj" \
+	"$(INTDIR)\sys_win.obj" \
+	"$(INTDIR)\sys_wina.obj" \
+	"$(INTDIR)\vid_win.obj" \
+	"$(INTDIR)\view.obj" \
+	"$(INTDIR)\wad.obj" \
+	"$(INTDIR)\winquake.res" \
+	"$(INTDIR)\zone.obj"
+
+"$(OUTDIR)\qwcl.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+    $(LINK32) @<<
+  $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "qwcl___0"
+# PROP BASE Intermediate_Dir "qwcl___0"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "debug"
+# PROP Intermediate_Dir "debug"
+# PROP Target_Dir ""
+OUTDIR=.\debug
+INTDIR=.\debug
+
+ALL : "$(OUTDIR)\qwcl.exe" "$(OUTDIR)\qwcl.bsc"
+
+CLEAN : 
+	-@erase "$(INTDIR)\cd_win.obj"
+	-@erase "$(INTDIR)\cd_win.sbr"
+	-@erase "$(INTDIR)\cl_cam.obj"
+	-@erase "$(INTDIR)\cl_cam.sbr"
+	-@erase "$(INTDIR)\cl_demo.obj"
+	-@erase "$(INTDIR)\cl_demo.sbr"
+	-@erase "$(INTDIR)\cl_ents.obj"
+	-@erase "$(INTDIR)\cl_ents.sbr"
+	-@erase "$(INTDIR)\cl_input.obj"
+	-@erase "$(INTDIR)\cl_input.sbr"
+	-@erase "$(INTDIR)\cl_main.obj"
+	-@erase "$(INTDIR)\cl_main.sbr"
+	-@erase "$(INTDIR)\cl_parse.obj"
+	-@erase "$(INTDIR)\cl_parse.sbr"
+	-@erase "$(INTDIR)\cl_pred.obj"
+	-@erase "$(INTDIR)\cl_pred.sbr"
+	-@erase "$(INTDIR)\cl_tent.obj"
+	-@erase "$(INTDIR)\cl_tent.sbr"
+	-@erase "$(INTDIR)\cmd.obj"
+	-@erase "$(INTDIR)\cmd.sbr"
+	-@erase "$(INTDIR)\common.obj"
+	-@erase "$(INTDIR)\common.sbr"
+	-@erase "$(INTDIR)\console.obj"
+	-@erase "$(INTDIR)\console.sbr"
+	-@erase "$(INTDIR)\crc.obj"
+	-@erase "$(INTDIR)\crc.sbr"
+	-@erase "$(INTDIR)\cvar.obj"
+	-@erase "$(INTDIR)\cvar.sbr"
+	-@erase "$(INTDIR)\d_draw.obj"
+	-@erase "$(INTDIR)\d_draw16.obj"
+	-@erase "$(INTDIR)\d_edge.obj"
+	-@erase "$(INTDIR)\d_edge.sbr"
+	-@erase "$(INTDIR)\d_fill.obj"
+	-@erase "$(INTDIR)\d_fill.sbr"
+	-@erase "$(INTDIR)\d_init.obj"
+	-@erase "$(INTDIR)\d_init.sbr"
+	-@erase "$(INTDIR)\d_modech.obj"
+	-@erase "$(INTDIR)\d_modech.sbr"
+	-@erase "$(INTDIR)\d_part.obj"
+	-@erase "$(INTDIR)\d_part.sbr"
+	-@erase "$(INTDIR)\d_parta.obj"
+	-@erase "$(INTDIR)\d_polysa.obj"
+	-@erase "$(INTDIR)\d_polyse.obj"
+	-@erase "$(INTDIR)\d_polyse.sbr"
+	-@erase "$(INTDIR)\d_scan.obj"
+	-@erase "$(INTDIR)\d_scan.sbr"
+	-@erase "$(INTDIR)\d_scana.obj"
+	-@erase "$(INTDIR)\d_sky.obj"
+	-@erase "$(INTDIR)\d_sky.sbr"
+	-@erase "$(INTDIR)\d_spr8.obj"
+	-@erase "$(INTDIR)\d_sprite.obj"
+	-@erase "$(INTDIR)\d_sprite.sbr"
+	-@erase "$(INTDIR)\d_surf.obj"
+	-@erase "$(INTDIR)\d_surf.sbr"
+	-@erase "$(INTDIR)\d_vars.obj"
+	-@erase "$(INTDIR)\d_vars.sbr"
+	-@erase "$(INTDIR)\d_varsa.obj"
+	-@erase "$(INTDIR)\d_zpoint.obj"
+	-@erase "$(INTDIR)\d_zpoint.sbr"
+	-@erase "$(INTDIR)\draw.obj"
+	-@erase "$(INTDIR)\draw.sbr"
+	-@erase "$(INTDIR)\in_win.obj"
+	-@erase "$(INTDIR)\in_win.sbr"
+	-@erase "$(INTDIR)\keys.obj"
+	-@erase "$(INTDIR)\keys.sbr"
+	-@erase "$(INTDIR)\math.obj"
+	-@erase "$(INTDIR)\mathlib.obj"
+	-@erase "$(INTDIR)\mathlib.sbr"
+	-@erase "$(INTDIR)\md4.obj"
+	-@erase "$(INTDIR)\md4.sbr"
+	-@erase "$(INTDIR)\menu.obj"
+	-@erase "$(INTDIR)\menu.sbr"
+	-@erase "$(INTDIR)\model.obj"
+	-@erase "$(INTDIR)\model.sbr"
+	-@erase "$(INTDIR)\net_chan.obj"
+	-@erase "$(INTDIR)\net_chan.sbr"
+	-@erase "$(INTDIR)\net_wins.obj"
+	-@erase "$(INTDIR)\net_wins.sbr"
+	-@erase "$(INTDIR)\pmove.obj"
+	-@erase "$(INTDIR)\pmove.sbr"
+	-@erase "$(INTDIR)\pmovetst.obj"
+	-@erase "$(INTDIR)\pmovetst.sbr"
+	-@erase "$(INTDIR)\r_aclip.obj"
+	-@erase "$(INTDIR)\r_aclip.sbr"
+	-@erase "$(INTDIR)\r_aclipa.obj"
+	-@erase "$(INTDIR)\r_alias.obj"
+	-@erase "$(INTDIR)\r_alias.sbr"
+	-@erase "$(INTDIR)\r_aliasa.obj"
+	-@erase "$(INTDIR)\r_bsp.obj"
+	-@erase "$(INTDIR)\r_bsp.sbr"
+	-@erase "$(INTDIR)\r_draw.obj"
+	-@erase "$(INTDIR)\r_draw.sbr"
+	-@erase "$(INTDIR)\r_drawa.obj"
+	-@erase "$(INTDIR)\r_edge.obj"
+	-@erase "$(INTDIR)\r_edge.sbr"
+	-@erase "$(INTDIR)\r_edgea.obj"
+	-@erase "$(INTDIR)\r_efrag.obj"
+	-@erase "$(INTDIR)\r_efrag.sbr"
+	-@erase "$(INTDIR)\r_light.obj"
+	-@erase "$(INTDIR)\r_light.sbr"
+	-@erase "$(INTDIR)\r_main.obj"
+	-@erase "$(INTDIR)\r_main.sbr"
+	-@erase "$(INTDIR)\r_misc.obj"
+	-@erase "$(INTDIR)\r_misc.sbr"
+	-@erase "$(INTDIR)\r_part.obj"
+	-@erase "$(INTDIR)\r_part.sbr"
+	-@erase "$(INTDIR)\r_sky.obj"
+	-@erase "$(INTDIR)\r_sky.sbr"
+	-@erase "$(INTDIR)\r_sprite.obj"
+	-@erase "$(INTDIR)\r_sprite.sbr"
+	-@erase "$(INTDIR)\r_surf.obj"
+	-@erase "$(INTDIR)\r_surf.sbr"
+	-@erase "$(INTDIR)\r_vars.obj"
+	-@erase "$(INTDIR)\r_vars.sbr"
+	-@erase "$(INTDIR)\r_varsa.obj"
+	-@erase "$(INTDIR)\sbar.obj"
+	-@erase "$(INTDIR)\sbar.sbr"
+	-@erase "$(INTDIR)\screen.obj"
+	-@erase "$(INTDIR)\screen.sbr"
+	-@erase "$(INTDIR)\skin.obj"
+	-@erase "$(INTDIR)\skin.sbr"
+	-@erase "$(INTDIR)\snd_dma.obj"
+	-@erase "$(INTDIR)\snd_dma.sbr"
+	-@erase "$(INTDIR)\snd_mem.obj"
+	-@erase "$(INTDIR)\snd_mem.sbr"
+	-@erase "$(INTDIR)\snd_mix.obj"
+	-@erase "$(INTDIR)\snd_mix.sbr"
+	-@erase "$(INTDIR)\snd_mixa.obj"
+	-@erase "$(INTDIR)\snd_win.obj"
+	-@erase "$(INTDIR)\snd_win.sbr"
+	-@erase "$(INTDIR)\surf16.obj"
+	-@erase "$(INTDIR)\surf8.obj"
+	-@erase "$(INTDIR)\sys_win.obj"
+	-@erase "$(INTDIR)\sys_win.sbr"
+	-@erase "$(INTDIR)\sys_wina.obj"
+	-@erase "$(INTDIR)\vc40.idb"
+	-@erase "$(INTDIR)\vc40.pdb"
+	-@erase "$(INTDIR)\vid_win.obj"
+	-@erase "$(INTDIR)\vid_win.sbr"
+	-@erase "$(INTDIR)\view.obj"
+	-@erase "$(INTDIR)\view.sbr"
+	-@erase "$(INTDIR)\wad.obj"
+	-@erase "$(INTDIR)\wad.sbr"
+	-@erase "$(INTDIR)\winquake.res"
+	-@erase "$(INTDIR)\zone.obj"
+	-@erase "$(INTDIR)\zone.sbr"
+	-@erase "$(OUTDIR)\qwcl.bsc"
+	-@erase "$(OUTDIR)\qwcl.exe"
+	-@erase "$(OUTDIR)\qwcl.ilk"
+	-@erase "$(OUTDIR)\qwcl.pdb"
+
+"$(OUTDIR)" :
+    if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c
+# ADD CPP /nologo /Gm /GX /Zi /Od /I "..\..\scitech\include" /I "..\..\dxsdk\sdk\inc" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /YX /c
+# SUBTRACT CPP /X
+CPP_PROJ=/nologo /MLd /Gm /GX /Zi /Od /I "..\..\scitech\include" /I\
+ "..\..\dxsdk\sdk\inc" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR"$(INTDIR)/"\
+ /Fp"$(INTDIR)/qwcl.pch" /YX /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c 
+CPP_OBJS=.\debug/
+CPP_SBRS=.\debug/
+# ADD BASE MTL /nologo /D "_DEBUG" /win32
+# ADD MTL /nologo /D "_DEBUG" /win32
+MTL_PROJ=/nologo /D "_DEBUG" /win32 
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+RSC_PROJ=/l 0x409 /fo"$(INTDIR)/winquake.res" /d "_DEBUG" 
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+BSC32_FLAGS=/nologo /o"$(OUTDIR)/qwcl.bsc" 
+BSC32_SBRS= \
+	"$(INTDIR)\cd_win.sbr" \
+	"$(INTDIR)\cl_cam.sbr" \
+	"$(INTDIR)\cl_demo.sbr" \
+	"$(INTDIR)\cl_ents.sbr" \
+	"$(INTDIR)\cl_input.sbr" \
+	"$(INTDIR)\cl_main.sbr" \
+	"$(INTDIR)\cl_parse.sbr" \
+	"$(INTDIR)\cl_pred.sbr" \
+	"$(INTDIR)\cl_tent.sbr" \
+	"$(INTDIR)\cmd.sbr" \
+	"$(INTDIR)\common.sbr" \
+	"$(INTDIR)\console.sbr" \
+	"$(INTDIR)\crc.sbr" \
+	"$(INTDIR)\cvar.sbr" \
+	"$(INTDIR)\d_edge.sbr" \
+	"$(INTDIR)\d_fill.sbr" \
+	"$(INTDIR)\d_init.sbr" \
+	"$(INTDIR)\d_modech.sbr" \
+	"$(INTDIR)\d_part.sbr" \
+	"$(INTDIR)\d_polyse.sbr" \
+	"$(INTDIR)\d_scan.sbr" \
+	"$(INTDIR)\d_sky.sbr" \
+	"$(INTDIR)\d_sprite.sbr" \
+	"$(INTDIR)\d_surf.sbr" \
+	"$(INTDIR)\d_vars.sbr" \
+	"$(INTDIR)\d_zpoint.sbr" \
+	"$(INTDIR)\draw.sbr" \
+	"$(INTDIR)\in_win.sbr" \
+	"$(INTDIR)\keys.sbr" \
+	"$(INTDIR)\mathlib.sbr" \
+	"$(INTDIR)\md4.sbr" \
+	"$(INTDIR)\menu.sbr" \
+	"$(INTDIR)\model.sbr" \
+	"$(INTDIR)\net_chan.sbr" \
+	"$(INTDIR)\net_wins.sbr" \
+	"$(INTDIR)\pmove.sbr" \
+	"$(INTDIR)\pmovetst.sbr" \
+	"$(INTDIR)\r_aclip.sbr" \
+	"$(INTDIR)\r_alias.sbr" \
+	"$(INTDIR)\r_bsp.sbr" \
+	"$(INTDIR)\r_draw.sbr" \
+	"$(INTDIR)\r_edge.sbr" \
+	"$(INTDIR)\r_efrag.sbr" \
+	"$(INTDIR)\r_light.sbr" \
+	"$(INTDIR)\r_main.sbr" \
+	"$(INTDIR)\r_misc.sbr" \
+	"$(INTDIR)\r_part.sbr" \
+	"$(INTDIR)\r_sky.sbr" \
+	"$(INTDIR)\r_sprite.sbr" \
+	"$(INTDIR)\r_surf.sbr" \
+	"$(INTDIR)\r_vars.sbr" \
+	"$(INTDIR)\sbar.sbr" \
+	"$(INTDIR)\screen.sbr" \
+	"$(INTDIR)\skin.sbr" \
+	"$(INTDIR)\snd_dma.sbr" \
+	"$(INTDIR)\snd_mem.sbr" \
+	"$(INTDIR)\snd_mix.sbr" \
+	"$(INTDIR)\snd_win.sbr" \
+	"$(INTDIR)\sys_win.sbr" \
+	"$(INTDIR)\vid_win.sbr" \
+	"$(INTDIR)\view.sbr" \
+	"$(INTDIR)\wad.sbr" \
+	"$(INTDIR)\zone.sbr"
+
+"$(OUTDIR)\qwcl.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
+    $(BSC32) @<<
+  $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386
+# ADD LINK32 ..\..\scitech\lib\win32\vc\mgllt.lib ..\..\dxsdk\sdk\lib\dxguid.lib comctl32.lib wsock32.lib winmm.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386
+# SUBTRACT LINK32 /verbose
+LINK32_FLAGS=..\..\scitech\lib\win32\vc\mgllt.lib\
+ ..\..\dxsdk\sdk\lib\dxguid.lib comctl32.lib wsock32.lib winmm.lib kernel32.lib\
+ user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib\
+ ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo\
+ /subsystem:windows /incremental:yes /pdb:"$(OUTDIR)/qwcl.pdb" /debug\
+ /machine:I386 /out:"$(OUTDIR)/qwcl.exe" 
+LINK32_OBJS= \
+	"$(INTDIR)\cd_win.obj" \
+	"$(INTDIR)\cl_cam.obj" \
+	"$(INTDIR)\cl_demo.obj" \
+	"$(INTDIR)\cl_ents.obj" \
+	"$(INTDIR)\cl_input.obj" \
+	"$(INTDIR)\cl_main.obj" \
+	"$(INTDIR)\cl_parse.obj" \
+	"$(INTDIR)\cl_pred.obj" \
+	"$(INTDIR)\cl_tent.obj" \
+	"$(INTDIR)\cmd.obj" \
+	"$(INTDIR)\common.obj" \
+	"$(INTDIR)\console.obj" \
+	"$(INTDIR)\crc.obj" \
+	"$(INTDIR)\cvar.obj" \
+	"$(INTDIR)\d_draw.obj" \
+	"$(INTDIR)\d_draw16.obj" \
+	"$(INTDIR)\d_edge.obj" \
+	"$(INTDIR)\d_fill.obj" \
+	"$(INTDIR)\d_init.obj" \
+	"$(INTDIR)\d_modech.obj" \
+	"$(INTDIR)\d_part.obj" \
+	"$(INTDIR)\d_parta.obj" \
+	"$(INTDIR)\d_polysa.obj" \
+	"$(INTDIR)\d_polyse.obj" \
+	"$(INTDIR)\d_scan.obj" \
+	"$(INTDIR)\d_scana.obj" \
+	"$(INTDIR)\d_sky.obj" \
+	"$(INTDIR)\d_spr8.obj" \
+	"$(INTDIR)\d_sprite.obj" \
+	"$(INTDIR)\d_surf.obj" \
+	"$(INTDIR)\d_vars.obj" \
+	"$(INTDIR)\d_varsa.obj" \
+	"$(INTDIR)\d_zpoint.obj" \
+	"$(INTDIR)\draw.obj" \
+	"$(INTDIR)\in_win.obj" \
+	"$(INTDIR)\keys.obj" \
+	"$(INTDIR)\math.obj" \
+	"$(INTDIR)\mathlib.obj" \
+	"$(INTDIR)\md4.obj" \
+	"$(INTDIR)\menu.obj" \
+	"$(INTDIR)\model.obj" \
+	"$(INTDIR)\net_chan.obj" \
+	"$(INTDIR)\net_wins.obj" \
+	"$(INTDIR)\pmove.obj" \
+	"$(INTDIR)\pmovetst.obj" \
+	"$(INTDIR)\r_aclip.obj" \
+	"$(INTDIR)\r_aclipa.obj" \
+	"$(INTDIR)\r_alias.obj" \
+	"$(INTDIR)\r_aliasa.obj" \
+	"$(INTDIR)\r_bsp.obj" \
+	"$(INTDIR)\r_draw.obj" \
+	"$(INTDIR)\r_drawa.obj" \
+	"$(INTDIR)\r_edge.obj" \
+	"$(INTDIR)\r_edgea.obj" \
+	"$(INTDIR)\r_efrag.obj" \
+	"$(INTDIR)\r_light.obj" \
+	"$(INTDIR)\r_main.obj" \
+	"$(INTDIR)\r_misc.obj" \
+	"$(INTDIR)\r_part.obj" \
+	"$(INTDIR)\r_sky.obj" \
+	"$(INTDIR)\r_sprite.obj" \
+	"$(INTDIR)\r_surf.obj" \
+	"$(INTDIR)\r_vars.obj" \
+	"$(INTDIR)\r_varsa.obj" \
+	"$(INTDIR)\sbar.obj" \
+	"$(INTDIR)\screen.obj" \
+	"$(INTDIR)\skin.obj" \
+	"$(INTDIR)\snd_dma.obj" \
+	"$(INTDIR)\snd_mem.obj" \
+	"$(INTDIR)\snd_mix.obj" \
+	"$(INTDIR)\snd_mixa.obj" \
+	"$(INTDIR)\snd_win.obj" \
+	"$(INTDIR)\surf16.obj" \
+	"$(INTDIR)\surf8.obj" \
+	"$(INTDIR)\sys_win.obj" \
+	"$(INTDIR)\sys_wina.obj" \
+	"$(INTDIR)\vid_win.obj" \
+	"$(INTDIR)\view.obj" \
+	"$(INTDIR)\wad.obj" \
+	"$(INTDIR)\winquake.res" \
+	"$(INTDIR)\zone.obj"
+
+"$(OUTDIR)\qwcl.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+    $(LINK32) @<<
+  $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "GL Debug"
+# PROP BASE Intermediate_Dir "GL Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "GLDebug"
+# PROP Intermediate_Dir "GLDebug"
+# PROP Target_Dir ""
+OUTDIR=.\GLDebug
+INTDIR=.\GLDebug
+
+ALL : "$(OUTDIR)\glqwcl.exe" "$(OUTDIR)\qwcl.bsc"
+
+CLEAN : 
+	-@erase "$(INTDIR)\cd_win.obj"
+	-@erase "$(INTDIR)\cd_win.sbr"
+	-@erase "$(INTDIR)\cl_cam.obj"
+	-@erase "$(INTDIR)\cl_cam.sbr"
+	-@erase "$(INTDIR)\cl_demo.obj"
+	-@erase "$(INTDIR)\cl_demo.sbr"
+	-@erase "$(INTDIR)\cl_ents.obj"
+	-@erase "$(INTDIR)\cl_ents.sbr"
+	-@erase "$(INTDIR)\cl_input.obj"
+	-@erase "$(INTDIR)\cl_input.sbr"
+	-@erase "$(INTDIR)\cl_main.obj"
+	-@erase "$(INTDIR)\cl_main.sbr"
+	-@erase "$(INTDIR)\cl_parse.obj"
+	-@erase "$(INTDIR)\cl_parse.sbr"
+	-@erase "$(INTDIR)\cl_pred.obj"
+	-@erase "$(INTDIR)\cl_pred.sbr"
+	-@erase "$(INTDIR)\cl_tent.obj"
+	-@erase "$(INTDIR)\cl_tent.sbr"
+	-@erase "$(INTDIR)\cmd.obj"
+	-@erase "$(INTDIR)\cmd.sbr"
+	-@erase "$(INTDIR)\common.obj"
+	-@erase "$(INTDIR)\common.sbr"
+	-@erase "$(INTDIR)\console.obj"
+	-@erase "$(INTDIR)\console.sbr"
+	-@erase "$(INTDIR)\crc.obj"
+	-@erase "$(INTDIR)\crc.sbr"
+	-@erase "$(INTDIR)\cvar.obj"
+	-@erase "$(INTDIR)\cvar.sbr"
+	-@erase "$(INTDIR)\gl_draw.obj"
+	-@erase "$(INTDIR)\gl_draw.sbr"
+	-@erase "$(INTDIR)\gl_mesh.obj"
+	-@erase "$(INTDIR)\gl_mesh.sbr"
+	-@erase "$(INTDIR)\gl_model.obj"
+	-@erase "$(INTDIR)\gl_model.sbr"
+	-@erase "$(INTDIR)\gl_ngraph.obj"
+	-@erase "$(INTDIR)\gl_ngraph.sbr"
+	-@erase "$(INTDIR)\gl_refrag.obj"
+	-@erase "$(INTDIR)\gl_refrag.sbr"
+	-@erase "$(INTDIR)\gl_rlight.obj"
+	-@erase "$(INTDIR)\gl_rlight.sbr"
+	-@erase "$(INTDIR)\gl_rmain.obj"
+	-@erase "$(INTDIR)\gl_rmain.sbr"
+	-@erase "$(INTDIR)\gl_rmisc.obj"
+	-@erase "$(INTDIR)\gl_rmisc.sbr"
+	-@erase "$(INTDIR)\gl_rsurf.obj"
+	-@erase "$(INTDIR)\gl_rsurf.sbr"
+	-@erase "$(INTDIR)\gl_screen.obj"
+	-@erase "$(INTDIR)\gl_screen.sbr"
+	-@erase "$(INTDIR)\gl_test.obj"
+	-@erase "$(INTDIR)\gl_test.sbr"
+	-@erase "$(INTDIR)\gl_vidnt.obj"
+	-@erase "$(INTDIR)\gl_vidnt.sbr"
+	-@erase "$(INTDIR)\gl_warp.obj"
+	-@erase "$(INTDIR)\gl_warp.sbr"
+	-@erase "$(INTDIR)\in_win.obj"
+	-@erase "$(INTDIR)\in_win.sbr"
+	-@erase "$(INTDIR)\keys.obj"
+	-@erase "$(INTDIR)\keys.sbr"
+	-@erase "$(INTDIR)\math.obj"
+	-@erase "$(INTDIR)\mathlib.obj"
+	-@erase "$(INTDIR)\mathlib.sbr"
+	-@erase "$(INTDIR)\md4.obj"
+	-@erase "$(INTDIR)\md4.sbr"
+	-@erase "$(INTDIR)\menu.obj"
+	-@erase "$(INTDIR)\menu.sbr"
+	-@erase "$(INTDIR)\net_chan.obj"
+	-@erase "$(INTDIR)\net_chan.sbr"
+	-@erase "$(INTDIR)\net_wins.obj"
+	-@erase "$(INTDIR)\net_wins.sbr"
+	-@erase "$(INTDIR)\pmove.obj"
+	-@erase "$(INTDIR)\pmove.sbr"
+	-@erase "$(INTDIR)\pmovetst.obj"
+	-@erase "$(INTDIR)\pmovetst.sbr"
+	-@erase "$(INTDIR)\r_part.obj"
+	-@erase "$(INTDIR)\r_part.sbr"
+	-@erase "$(INTDIR)\sbar.obj"
+	-@erase "$(INTDIR)\sbar.sbr"
+	-@erase "$(INTDIR)\skin.obj"
+	-@erase "$(INTDIR)\skin.sbr"
+	-@erase "$(INTDIR)\snd_dma.obj"
+	-@erase "$(INTDIR)\snd_dma.sbr"
+	-@erase "$(INTDIR)\snd_mem.obj"
+	-@erase "$(INTDIR)\snd_mem.sbr"
+	-@erase "$(INTDIR)\snd_mix.obj"
+	-@erase "$(INTDIR)\snd_mix.sbr"
+	-@erase "$(INTDIR)\snd_mixa.obj"
+	-@erase "$(INTDIR)\snd_win.obj"
+	-@erase "$(INTDIR)\snd_win.sbr"
+	-@erase "$(INTDIR)\sys_win.obj"
+	-@erase "$(INTDIR)\sys_win.sbr"
+	-@erase "$(INTDIR)\sys_wina.obj"
+	-@erase "$(INTDIR)\vc40.idb"
+	-@erase "$(INTDIR)\vc40.pdb"
+	-@erase "$(INTDIR)\view.obj"
+	-@erase "$(INTDIR)\view.sbr"
+	-@erase "$(INTDIR)\wad.obj"
+	-@erase "$(INTDIR)\wad.sbr"
+	-@erase "$(INTDIR)\winquake.res"
+	-@erase "$(INTDIR)\zone.obj"
+	-@erase "$(INTDIR)\zone.sbr"
+	-@erase "$(OUTDIR)\glqwcl.exe"
+	-@erase "$(OUTDIR)\glqwcl.ilk"
+	-@erase "$(OUTDIR)\glqwcl.pdb"
+	-@erase "$(OUTDIR)\qwcl.bsc"
+
+"$(OUTDIR)" :
+    if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /YX /c
+# ADD CPP /nologo /Gm /GX /Zi /Od /I "..\..\scitech\include" /I "..\..\dxsdk\sdk\inc" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "GLQUAKE" /FR /YX /c
+# SUBTRACT CPP /X
+CPP_PROJ=/nologo /MLd /Gm /GX /Zi /Od /I "..\..\scitech\include" /I\
+ "..\..\dxsdk\sdk\inc" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "GLQUAKE"\
+ /FR"$(INTDIR)/" /Fp"$(INTDIR)/qwcl.pch" /YX /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c 
+CPP_OBJS=.\GLDebug/
+CPP_SBRS=.\GLDebug/
+# ADD BASE MTL /nologo /D "_DEBUG" /win32
+# ADD MTL /nologo /D "_DEBUG" /win32
+MTL_PROJ=/nologo /D "_DEBUG" /win32 
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+RSC_PROJ=/l 0x409 /fo"$(INTDIR)/winquake.res" /d "_DEBUG" 
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+BSC32_FLAGS=/nologo /o"$(OUTDIR)/qwcl.bsc" 
+BSC32_SBRS= \
+	"$(INTDIR)\cd_win.sbr" \
+	"$(INTDIR)\cl_cam.sbr" \
+	"$(INTDIR)\cl_demo.sbr" \
+	"$(INTDIR)\cl_ents.sbr" \
+	"$(INTDIR)\cl_input.sbr" \
+	"$(INTDIR)\cl_main.sbr" \
+	"$(INTDIR)\cl_parse.sbr" \
+	"$(INTDIR)\cl_pred.sbr" \
+	"$(INTDIR)\cl_tent.sbr" \
+	"$(INTDIR)\cmd.sbr" \
+	"$(INTDIR)\common.sbr" \
+	"$(INTDIR)\console.sbr" \
+	"$(INTDIR)\crc.sbr" \
+	"$(INTDIR)\cvar.sbr" \
+	"$(INTDIR)\gl_draw.sbr" \
+	"$(INTDIR)\gl_mesh.sbr" \
+	"$(INTDIR)\gl_model.sbr" \
+	"$(INTDIR)\gl_ngraph.sbr" \
+	"$(INTDIR)\gl_refrag.sbr" \
+	"$(INTDIR)\gl_rlight.sbr" \
+	"$(INTDIR)\gl_rmain.sbr" \
+	"$(INTDIR)\gl_rmisc.sbr" \
+	"$(INTDIR)\gl_rsurf.sbr" \
+	"$(INTDIR)\gl_screen.sbr" \
+	"$(INTDIR)\gl_test.sbr" \
+	"$(INTDIR)\gl_vidnt.sbr" \
+	"$(INTDIR)\gl_warp.sbr" \
+	"$(INTDIR)\in_win.sbr" \
+	"$(INTDIR)\keys.sbr" \
+	"$(INTDIR)\mathlib.sbr" \
+	"$(INTDIR)\md4.sbr" \
+	"$(INTDIR)\menu.sbr" \
+	"$(INTDIR)\net_chan.sbr" \
+	"$(INTDIR)\net_wins.sbr" \
+	"$(INTDIR)\pmove.sbr" \
+	"$(INTDIR)\pmovetst.sbr" \
+	"$(INTDIR)\r_part.sbr" \
+	"$(INTDIR)\sbar.sbr" \
+	"$(INTDIR)\skin.sbr" \
+	"$(INTDIR)\snd_dma.sbr" \
+	"$(INTDIR)\snd_mem.sbr" \
+	"$(INTDIR)\snd_mix.sbr" \
+	"$(INTDIR)\snd_win.sbr" \
+	"$(INTDIR)\sys_win.sbr" \
+	"$(INTDIR)\view.sbr" \
+	"$(INTDIR)\wad.sbr" \
+	"$(INTDIR)\zone.sbr"
+
+"$(OUTDIR)\qwcl.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
+    $(BSC32) @<<
+  $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+# ADD BASE LINK32 ..\..\dxsdk\sdk\lib\dxguid.lib ..\..\scitech\lib\win32\vc\mgllt.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386
+# ADD LINK32 opengl32.lib ..\..\dxsdk\sdk\lib\dxguid.lib comctl32.lib wsock32.lib winmm.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /out:"GLDebug/glqwcl.exe"
+LINK32_FLAGS=opengl32.lib ..\..\dxsdk\sdk\lib\dxguid.lib comctl32.lib\
+ wsock32.lib winmm.lib kernel32.lib user32.lib gdi32.lib winspool.lib\
+ comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib\
+ odbc32.lib odbccp32.lib /nologo /subsystem:windows /incremental:yes\
+ /pdb:"$(OUTDIR)/glqwcl.pdb" /debug /machine:I386 /out:"$(OUTDIR)/glqwcl.exe" 
+LINK32_OBJS= \
+	"$(INTDIR)\cd_win.obj" \
+	"$(INTDIR)\cl_cam.obj" \
+	"$(INTDIR)\cl_demo.obj" \
+	"$(INTDIR)\cl_ents.obj" \
+	"$(INTDIR)\cl_input.obj" \
+	"$(INTDIR)\cl_main.obj" \
+	"$(INTDIR)\cl_parse.obj" \
+	"$(INTDIR)\cl_pred.obj" \
+	"$(INTDIR)\cl_tent.obj" \
+	"$(INTDIR)\cmd.obj" \
+	"$(INTDIR)\common.obj" \
+	"$(INTDIR)\console.obj" \
+	"$(INTDIR)\crc.obj" \
+	"$(INTDIR)\cvar.obj" \
+	"$(INTDIR)\gl_draw.obj" \
+	"$(INTDIR)\gl_mesh.obj" \
+	"$(INTDIR)\gl_model.obj" \
+	"$(INTDIR)\gl_ngraph.obj" \
+	"$(INTDIR)\gl_refrag.obj" \
+	"$(INTDIR)\gl_rlight.obj" \
+	"$(INTDIR)\gl_rmain.obj" \
+	"$(INTDIR)\gl_rmisc.obj" \
+	"$(INTDIR)\gl_rsurf.obj" \
+	"$(INTDIR)\gl_screen.obj" \
+	"$(INTDIR)\gl_test.obj" \
+	"$(INTDIR)\gl_vidnt.obj" \
+	"$(INTDIR)\gl_warp.obj" \
+	"$(INTDIR)\in_win.obj" \
+	"$(INTDIR)\keys.obj" \
+	"$(INTDIR)\math.obj" \
+	"$(INTDIR)\mathlib.obj" \
+	"$(INTDIR)\md4.obj" \
+	"$(INTDIR)\menu.obj" \
+	"$(INTDIR)\net_chan.obj" \
+	"$(INTDIR)\net_wins.obj" \
+	"$(INTDIR)\pmove.obj" \
+	"$(INTDIR)\pmovetst.obj" \
+	"$(INTDIR)\r_part.obj" \
+	"$(INTDIR)\sbar.obj" \
+	"$(INTDIR)\skin.obj" \
+	"$(INTDIR)\snd_dma.obj" \
+	"$(INTDIR)\snd_mem.obj" \
+	"$(INTDIR)\snd_mix.obj" \
+	"$(INTDIR)\snd_mixa.obj" \
+	"$(INTDIR)\snd_win.obj" \
+	"$(INTDIR)\sys_win.obj" \
+	"$(INTDIR)\sys_wina.obj" \
+	"$(INTDIR)\view.obj" \
+	"$(INTDIR)\wad.obj" \
+	"$(INTDIR)\winquake.res" \
+	"$(INTDIR)\zone.obj"
+
+"$(OUTDIR)\glqwcl.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+    $(LINK32) @<<
+  $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "GL Release"
+# PROP BASE Intermediate_Dir "GL Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "GLRelease"
+# PROP Intermediate_Dir "GLRelease"
+# PROP Target_Dir ""
+OUTDIR=.\GLRelease
+INTDIR=.\GLRelease
+
+ALL : "$(OUTDIR)\glqwcl.exe"
+
+CLEAN : 
+	-@erase "$(INTDIR)\cd_win.obj"
+	-@erase "$(INTDIR)\cl_cam.obj"
+	-@erase "$(INTDIR)\cl_demo.obj"
+	-@erase "$(INTDIR)\cl_ents.obj"
+	-@erase "$(INTDIR)\cl_input.obj"
+	-@erase "$(INTDIR)\cl_main.obj"
+	-@erase "$(INTDIR)\cl_parse.obj"
+	-@erase "$(INTDIR)\cl_pred.obj"
+	-@erase "$(INTDIR)\cl_tent.obj"
+	-@erase "$(INTDIR)\cmd.obj"
+	-@erase "$(INTDIR)\common.obj"
+	-@erase "$(INTDIR)\console.obj"
+	-@erase "$(INTDIR)\crc.obj"
+	-@erase "$(INTDIR)\cvar.obj"
+	-@erase "$(INTDIR)\gl_draw.obj"
+	-@erase "$(INTDIR)\gl_mesh.obj"
+	-@erase "$(INTDIR)\gl_model.obj"
+	-@erase "$(INTDIR)\gl_ngraph.obj"
+	-@erase "$(INTDIR)\gl_refrag.obj"
+	-@erase "$(INTDIR)\gl_rlight.obj"
+	-@erase "$(INTDIR)\gl_rmain.obj"
+	-@erase "$(INTDIR)\gl_rmisc.obj"
+	-@erase "$(INTDIR)\gl_rsurf.obj"
+	-@erase "$(INTDIR)\gl_screen.obj"
+	-@erase "$(INTDIR)\gl_test.obj"
+	-@erase "$(INTDIR)\gl_vidnt.obj"
+	-@erase "$(INTDIR)\gl_warp.obj"
+	-@erase "$(INTDIR)\in_win.obj"
+	-@erase "$(INTDIR)\keys.obj"
+	-@erase "$(INTDIR)\math.obj"
+	-@erase "$(INTDIR)\mathlib.obj"
+	-@erase "$(INTDIR)\md4.obj"
+	-@erase "$(INTDIR)\menu.obj"
+	-@erase "$(INTDIR)\net_chan.obj"
+	-@erase "$(INTDIR)\net_wins.obj"
+	-@erase "$(INTDIR)\pmove.obj"
+	-@erase "$(INTDIR)\pmovetst.obj"
+	-@erase "$(INTDIR)\r_part.obj"
+	-@erase "$(INTDIR)\sbar.obj"
+	-@erase "$(INTDIR)\skin.obj"
+	-@erase "$(INTDIR)\snd_dma.obj"
+	-@erase "$(INTDIR)\snd_mem.obj"
+	-@erase "$(INTDIR)\snd_mix.obj"
+	-@erase "$(INTDIR)\snd_mixa.obj"
+	-@erase "$(INTDIR)\snd_win.obj"
+	-@erase "$(INTDIR)\sys_win.obj"
+	-@erase "$(INTDIR)\sys_wina.obj"
+	-@erase "$(INTDIR)\view.obj"
+	-@erase "$(INTDIR)\wad.obj"
+	-@erase "$(INTDIR)\winquake.res"
+	-@erase "$(INTDIR)\zone.obj"
+	-@erase "$(OUTDIR)\glqwcl.exe"
+
+"$(OUTDIR)" :
+    if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c
+# ADD CPP /nologo /GX /O2 /I "..\..\scitech\include" /I "..\..\dxsdk\sdk\inc" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "GLQUAKE" /YX /c
+# SUBTRACT CPP /X
+CPP_PROJ=/nologo /ML /GX /O2 /I "..\..\scitech\include" /I\
+ "..\..\dxsdk\sdk\inc" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "GLQUAKE"\
+ /Fp"$(INTDIR)/qwcl.pch" /YX /Fo"$(INTDIR)/" /c 
+CPP_OBJS=.\GLRelease/
+CPP_SBRS=.\.
+# ADD BASE MTL /nologo /D "NDEBUG" /win32
+# ADD MTL /nologo /D "NDEBUG" /win32
+MTL_PROJ=/nologo /D "NDEBUG" /win32 
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+RSC_PROJ=/l 0x409 /fo"$(INTDIR)/winquake.res" /d "NDEBUG" 
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+BSC32_FLAGS=/nologo /o"$(OUTDIR)/qwcl.bsc" 
+BSC32_SBRS= \
+	
+LINK32=link.exe
+# ADD BASE LINK32 ..\..\dxsdk\sdk\lib\dxguid.lib ..\..\scitech\lib\win32\vc\mgllt.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
+# ADD LINK32 opengl32.lib ..\..\dxsdk\sdk\lib\dxguid.lib comctl32.lib wsock32.lib winmm.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"GLRelease/glqwcl.exe"
+LINK32_FLAGS=opengl32.lib ..\..\dxsdk\sdk\lib\dxguid.lib comctl32.lib\
+ wsock32.lib winmm.lib kernel32.lib user32.lib gdi32.lib winspool.lib\
+ comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib\
+ odbc32.lib odbccp32.lib /nologo /subsystem:windows /incremental:no\
+ /pdb:"$(OUTDIR)/glqwcl.pdb" /machine:I386 /out:"$(OUTDIR)/glqwcl.exe" 
+LINK32_OBJS= \
+	"$(INTDIR)\cd_win.obj" \
+	"$(INTDIR)\cl_cam.obj" \
+	"$(INTDIR)\cl_demo.obj" \
+	"$(INTDIR)\cl_ents.obj" \
+	"$(INTDIR)\cl_input.obj" \
+	"$(INTDIR)\cl_main.obj" \
+	"$(INTDIR)\cl_parse.obj" \
+	"$(INTDIR)\cl_pred.obj" \
+	"$(INTDIR)\cl_tent.obj" \
+	"$(INTDIR)\cmd.obj" \
+	"$(INTDIR)\common.obj" \
+	"$(INTDIR)\console.obj" \
+	"$(INTDIR)\crc.obj" \
+	"$(INTDIR)\cvar.obj" \
+	"$(INTDIR)\gl_draw.obj" \
+	"$(INTDIR)\gl_mesh.obj" \
+	"$(INTDIR)\gl_model.obj" \
+	"$(INTDIR)\gl_ngraph.obj" \
+	"$(INTDIR)\gl_refrag.obj" \
+	"$(INTDIR)\gl_rlight.obj" \
+	"$(INTDIR)\gl_rmain.obj" \
+	"$(INTDIR)\gl_rmisc.obj" \
+	"$(INTDIR)\gl_rsurf.obj" \
+	"$(INTDIR)\gl_screen.obj" \
+	"$(INTDIR)\gl_test.obj" \
+	"$(INTDIR)\gl_vidnt.obj" \
+	"$(INTDIR)\gl_warp.obj" \
+	"$(INTDIR)\in_win.obj" \
+	"$(INTDIR)\keys.obj" \
+	"$(INTDIR)\math.obj" \
+	"$(INTDIR)\mathlib.obj" \
+	"$(INTDIR)\md4.obj" \
+	"$(INTDIR)\menu.obj" \
+	"$(INTDIR)\net_chan.obj" \
+	"$(INTDIR)\net_wins.obj" \
+	"$(INTDIR)\pmove.obj" \
+	"$(INTDIR)\pmovetst.obj" \
+	"$(INTDIR)\r_part.obj" \
+	"$(INTDIR)\sbar.obj" \
+	"$(INTDIR)\skin.obj" \
+	"$(INTDIR)\snd_dma.obj" \
+	"$(INTDIR)\snd_mem.obj" \
+	"$(INTDIR)\snd_mix.obj" \
+	"$(INTDIR)\snd_mixa.obj" \
+	"$(INTDIR)\snd_win.obj" \
+	"$(INTDIR)\sys_win.obj" \
+	"$(INTDIR)\sys_wina.obj" \
+	"$(INTDIR)\view.obj" \
+	"$(INTDIR)\wad.obj" \
+	"$(INTDIR)\winquake.res" \
+	"$(INTDIR)\zone.obj"
+
+"$(OUTDIR)\glqwcl.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+    $(LINK32) @<<
+  $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ENDIF 
+
+.c{$(CPP_OBJS)}.obj:
+   $(CPP) $(CPP_PROJ) $<  
+
+.cpp{$(CPP_OBJS)}.obj:
+   $(CPP) $(CPP_PROJ) $<  
+
+.cxx{$(CPP_OBJS)}.obj:
+   $(CPP) $(CPP_PROJ) $<  
+
+.c{$(CPP_SBRS)}.sbr:
+   $(CPP) $(CPP_PROJ) $<  
+
+.cpp{$(CPP_SBRS)}.sbr:
+   $(CPP) $(CPP_PROJ) $<  
+
+.cxx{$(CPP_SBRS)}.sbr:
+   $(CPP) $(CPP_PROJ) $<  
+
+################################################################################
+# Begin Target
+
+# Name "qwcl - Win32 Release"
+# Name "qwcl - Win32 Debug"
+# Name "qwcl - Win32 GL Debug"
+# Name "qwcl - Win32 GL Release"
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Debug"
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Release"
+
+!ENDIF 
+
+################################################################################
+# Begin Source File
+
+SOURCE=.\cd_win.c
+DEP_CPP_CD_WI=\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\zone.h"\
+	
+NODEP_CPP_CD_WI=\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+
+"$(INTDIR)\cd_win.obj" : $(SOURCE) $(DEP_CPP_CD_WI) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+
+"$(INTDIR)\cd_win.obj" : $(SOURCE) $(DEP_CPP_CD_WI) "$(INTDIR)"
+
+"$(INTDIR)\cd_win.sbr" : $(SOURCE) $(DEP_CPP_CD_WI) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Debug"
+
+
+"$(INTDIR)\cd_win.obj" : $(SOURCE) $(DEP_CPP_CD_WI) "$(INTDIR)"
+
+"$(INTDIR)\cd_win.sbr" : $(SOURCE) $(DEP_CPP_CD_WI) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Release"
+
+
+"$(INTDIR)\cd_win.obj" : $(SOURCE) $(DEP_CPP_CD_WI) "$(INTDIR)"
+
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\cl_cam.c
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+DEP_CPP_CL_CA=\
+	"..\..\scitech\include\debug.h"\
+	"..\..\scitech\include\mgldos.h"\
+	"..\..\scitech\include\mglwin.h"\
+	"..\..\scitech\include\mgraph.h"\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\winquake.h"\
+	".\zone.h"\
+	
+NODEP_CPP_CL_CA=\
+	"..\..\scitech\include\mglrect.hpp"\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+"$(INTDIR)\cl_cam.obj" : $(SOURCE) $(DEP_CPP_CL_CA) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+DEP_CPP_CL_CA=\
+	"..\..\scitech\include\debug.h"\
+	"..\..\scitech\include\mgldos.h"\
+	"..\..\scitech\include\mglwin.h"\
+	"..\..\scitech\include\mgraph.h"\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\winquake.h"\
+	".\zone.h"\
+	
+NODEP_CPP_CL_CA=\
+	"..\..\scitech\include\mglrect.hpp"\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+"$(INTDIR)\cl_cam.obj" : $(SOURCE) $(DEP_CPP_CL_CA) "$(INTDIR)"
+
+"$(INTDIR)\cl_cam.sbr" : $(SOURCE) $(DEP_CPP_CL_CA) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Debug"
+
+DEP_CPP_CL_CA=\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\winquake.h"\
+	".\zone.h"\
+	
+NODEP_CPP_CL_CA=\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+"$(INTDIR)\cl_cam.obj" : $(SOURCE) $(DEP_CPP_CL_CA) "$(INTDIR)"
+
+"$(INTDIR)\cl_cam.sbr" : $(SOURCE) $(DEP_CPP_CL_CA) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Release"
+
+DEP_CPP_CL_CA=\
+	"..\..\scitech\include\debug.h"\
+	"..\..\scitech\include\mgldos.h"\
+	"..\..\scitech\include\mglwin.h"\
+	"..\..\scitech\include\mgraph.h"\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\winquake.h"\
+	".\zone.h"\
+	
+NODEP_CPP_CL_CA=\
+	"..\..\scitech\include\mglrect.hpp"\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+"$(INTDIR)\cl_cam.obj" : $(SOURCE) $(DEP_CPP_CL_CA) "$(INTDIR)"
+
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\cl_demo.c
+DEP_CPP_CL_DE=\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\zone.h"\
+	
+NODEP_CPP_CL_DE=\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+
+"$(INTDIR)\cl_demo.obj" : $(SOURCE) $(DEP_CPP_CL_DE) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+
+"$(INTDIR)\cl_demo.obj" : $(SOURCE) $(DEP_CPP_CL_DE) "$(INTDIR)"
+
+"$(INTDIR)\cl_demo.sbr" : $(SOURCE) $(DEP_CPP_CL_DE) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Debug"
+
+
+"$(INTDIR)\cl_demo.obj" : $(SOURCE) $(DEP_CPP_CL_DE) "$(INTDIR)"
+
+"$(INTDIR)\cl_demo.sbr" : $(SOURCE) $(DEP_CPP_CL_DE) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Release"
+
+
+"$(INTDIR)\cl_demo.obj" : $(SOURCE) $(DEP_CPP_CL_DE) "$(INTDIR)"
+
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\cl_ents.c
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+DEP_CPP_CL_EN=\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\zone.h"\
+	
+NODEP_CPP_CL_EN=\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+"$(INTDIR)\cl_ents.obj" : $(SOURCE) $(DEP_CPP_CL_EN) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+DEP_CPP_CL_EN=\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\zone.h"\
+	
+NODEP_CPP_CL_EN=\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+"$(INTDIR)\cl_ents.obj" : $(SOURCE) $(DEP_CPP_CL_EN) "$(INTDIR)"
+
+"$(INTDIR)\cl_ents.sbr" : $(SOURCE) $(DEP_CPP_CL_EN) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Debug"
+
+DEP_CPP_CL_EN=\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\cvar.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\mathlib.h"\
+	".\net.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\wad.h"\
+	".\zone.h"\
+	
+
+"$(INTDIR)\cl_ents.obj" : $(SOURCE) $(DEP_CPP_CL_EN) "$(INTDIR)"
+
+"$(INTDIR)\cl_ents.sbr" : $(SOURCE) $(DEP_CPP_CL_EN) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Release"
+
+DEP_CPP_CL_EN=\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\zone.h"\
+	
+NODEP_CPP_CL_EN=\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+"$(INTDIR)\cl_ents.obj" : $(SOURCE) $(DEP_CPP_CL_EN) "$(INTDIR)"
+
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\cl_input.c
+DEP_CPP_CL_IN=\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\zone.h"\
+	
+NODEP_CPP_CL_IN=\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+
+"$(INTDIR)\cl_input.obj" : $(SOURCE) $(DEP_CPP_CL_IN) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+
+"$(INTDIR)\cl_input.obj" : $(SOURCE) $(DEP_CPP_CL_IN) "$(INTDIR)"
+
+"$(INTDIR)\cl_input.sbr" : $(SOURCE) $(DEP_CPP_CL_IN) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Debug"
+
+
+"$(INTDIR)\cl_input.obj" : $(SOURCE) $(DEP_CPP_CL_IN) "$(INTDIR)"
+
+"$(INTDIR)\cl_input.sbr" : $(SOURCE) $(DEP_CPP_CL_IN) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Release"
+
+
+"$(INTDIR)\cl_input.obj" : $(SOURCE) $(DEP_CPP_CL_IN) "$(INTDIR)"
+
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\cl_main.c
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+DEP_CPP_CL_MA=\
+	"..\..\scitech\include\debug.h"\
+	"..\..\scitech\include\mgldos.h"\
+	"..\..\scitech\include\mglwin.h"\
+	"..\..\scitech\include\mgraph.h"\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\cvar.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\mathlib.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\wad.h"\
+	".\winquake.h"\
+	".\zone.h"\
+	
+NODEP_CPP_CL_MA=\
+	"..\..\scitech\include\mglrect.hpp"\
+	
+
+"$(INTDIR)\cl_main.obj" : $(SOURCE) $(DEP_CPP_CL_MA) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+DEP_CPP_CL_MA=\
+	"..\..\scitech\include\debug.h"\
+	"..\..\scitech\include\mgldos.h"\
+	"..\..\scitech\include\mglwin.h"\
+	"..\..\scitech\include\mgraph.h"\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\cvar.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\mathlib.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\wad.h"\
+	".\winquake.h"\
+	".\zone.h"\
+	
+NODEP_CPP_CL_MA=\
+	"..\..\scitech\include\mglrect.hpp"\
+	
+
+"$(INTDIR)\cl_main.obj" : $(SOURCE) $(DEP_CPP_CL_MA) "$(INTDIR)"
+
+"$(INTDIR)\cl_main.sbr" : $(SOURCE) $(DEP_CPP_CL_MA) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Debug"
+
+DEP_CPP_CL_MA=\
+	"..\..\scitech\include\mgraph.h"\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\cvar.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\mathlib.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\wad.h"\
+	".\winquake.h"\
+	".\zone.h"\
+	
+
+"$(INTDIR)\cl_main.obj" : $(SOURCE) $(DEP_CPP_CL_MA) "$(INTDIR)"
+
+"$(INTDIR)\cl_main.sbr" : $(SOURCE) $(DEP_CPP_CL_MA) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Release"
+
+DEP_CPP_CL_MA=\
+	"..\..\scitech\include\debug.h"\
+	"..\..\scitech\include\mgldos.h"\
+	"..\..\scitech\include\mglwin.h"\
+	"..\..\scitech\include\mgraph.h"\
+	".\quakedef.h"\
+	".\winquake.h"\
+	
+NODEP_CPP_CL_MA=\
+	"..\..\scitech\include\mglrect.hpp"\
+	
+
+"$(INTDIR)\cl_main.obj" : $(SOURCE) $(DEP_CPP_CL_MA) "$(INTDIR)"
+
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\cl_parse.c
+DEP_CPP_CL_PA=\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\zone.h"\
+	
+NODEP_CPP_CL_PA=\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+
+"$(INTDIR)\cl_parse.obj" : $(SOURCE) $(DEP_CPP_CL_PA) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+
+"$(INTDIR)\cl_parse.obj" : $(SOURCE) $(DEP_CPP_CL_PA) "$(INTDIR)"
+
+"$(INTDIR)\cl_parse.sbr" : $(SOURCE) $(DEP_CPP_CL_PA) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Debug"
+
+
+"$(INTDIR)\cl_parse.obj" : $(SOURCE) $(DEP_CPP_CL_PA) "$(INTDIR)"
+
+"$(INTDIR)\cl_parse.sbr" : $(SOURCE) $(DEP_CPP_CL_PA) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Release"
+
+
+"$(INTDIR)\cl_parse.obj" : $(SOURCE) $(DEP_CPP_CL_PA) "$(INTDIR)"
+
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\cl_pred.c
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+DEP_CPP_CL_PR=\
+	"..\..\scitech\include\debug.h"\
+	"..\..\scitech\include\mgldos.h"\
+	"..\..\scitech\include\mglwin.h"\
+	"..\..\scitech\include\mgraph.h"\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\winquake.h"\
+	".\zone.h"\
+	
+NODEP_CPP_CL_PR=\
+	"..\..\scitech\include\mglrect.hpp"\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+"$(INTDIR)\cl_pred.obj" : $(SOURCE) $(DEP_CPP_CL_PR) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+DEP_CPP_CL_PR=\
+	"..\..\scitech\include\debug.h"\
+	"..\..\scitech\include\mgldos.h"\
+	"..\..\scitech\include\mglwin.h"\
+	"..\..\scitech\include\mgraph.h"\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\winquake.h"\
+	".\zone.h"\
+	
+NODEP_CPP_CL_PR=\
+	"..\..\scitech\include\mglrect.hpp"\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+"$(INTDIR)\cl_pred.obj" : $(SOURCE) $(DEP_CPP_CL_PR) "$(INTDIR)"
+
+"$(INTDIR)\cl_pred.sbr" : $(SOURCE) $(DEP_CPP_CL_PR) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Debug"
+
+DEP_CPP_CL_PR=\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\winquake.h"\
+	".\zone.h"\
+	
+NODEP_CPP_CL_PR=\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+"$(INTDIR)\cl_pred.obj" : $(SOURCE) $(DEP_CPP_CL_PR) "$(INTDIR)"
+
+"$(INTDIR)\cl_pred.sbr" : $(SOURCE) $(DEP_CPP_CL_PR) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Release"
+
+DEP_CPP_CL_PR=\
+	"..\..\scitech\include\debug.h"\
+	"..\..\scitech\include\mgldos.h"\
+	"..\..\scitech\include\mglwin.h"\
+	"..\..\scitech\include\mgraph.h"\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\winquake.h"\
+	".\zone.h"\
+	
+NODEP_CPP_CL_PR=\
+	"..\..\scitech\include\mglrect.hpp"\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+"$(INTDIR)\cl_pred.obj" : $(SOURCE) $(DEP_CPP_CL_PR) "$(INTDIR)"
+
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\cl_tent.c
+DEP_CPP_CL_TE=\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\zone.h"\
+	
+NODEP_CPP_CL_TE=\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+
+"$(INTDIR)\cl_tent.obj" : $(SOURCE) $(DEP_CPP_CL_TE) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+
+"$(INTDIR)\cl_tent.obj" : $(SOURCE) $(DEP_CPP_CL_TE) "$(INTDIR)"
+
+"$(INTDIR)\cl_tent.sbr" : $(SOURCE) $(DEP_CPP_CL_TE) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Debug"
+
+
+"$(INTDIR)\cl_tent.obj" : $(SOURCE) $(DEP_CPP_CL_TE) "$(INTDIR)"
+
+"$(INTDIR)\cl_tent.sbr" : $(SOURCE) $(DEP_CPP_CL_TE) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Release"
+
+
+"$(INTDIR)\cl_tent.obj" : $(SOURCE) $(DEP_CPP_CL_TE) "$(INTDIR)"
+
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\cmd.c
+DEP_CPP_CMD_C=\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\zone.h"\
+	
+NODEP_CPP_CMD_C=\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+
+"$(INTDIR)\cmd.obj" : $(SOURCE) $(DEP_CPP_CMD_C) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+
+"$(INTDIR)\cmd.obj" : $(SOURCE) $(DEP_CPP_CMD_C) "$(INTDIR)"
+
+"$(INTDIR)\cmd.sbr" : $(SOURCE) $(DEP_CPP_CMD_C) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Debug"
+
+
+"$(INTDIR)\cmd.obj" : $(SOURCE) $(DEP_CPP_CMD_C) "$(INTDIR)"
+
+"$(INTDIR)\cmd.sbr" : $(SOURCE) $(DEP_CPP_CMD_C) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Release"
+
+
+"$(INTDIR)\cmd.obj" : $(SOURCE) $(DEP_CPP_CMD_C) "$(INTDIR)"
+
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\common.c
+DEP_CPP_COMMO=\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\zone.h"\
+	
+NODEP_CPP_COMMO=\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\qwsvdef.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+
+"$(INTDIR)\common.obj" : $(SOURCE) $(DEP_CPP_COMMO) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+
+"$(INTDIR)\common.obj" : $(SOURCE) $(DEP_CPP_COMMO) "$(INTDIR)"
+
+"$(INTDIR)\common.sbr" : $(SOURCE) $(DEP_CPP_COMMO) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Debug"
+
+
+"$(INTDIR)\common.obj" : $(SOURCE) $(DEP_CPP_COMMO) "$(INTDIR)"
+
+"$(INTDIR)\common.sbr" : $(SOURCE) $(DEP_CPP_COMMO) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Release"
+
+
+"$(INTDIR)\common.obj" : $(SOURCE) $(DEP_CPP_COMMO) "$(INTDIR)"
+
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\console.c
+DEP_CPP_CONSO=\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\zone.h"\
+	
+NODEP_CPP_CONSO=\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+
+"$(INTDIR)\console.obj" : $(SOURCE) $(DEP_CPP_CONSO) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+
+"$(INTDIR)\console.obj" : $(SOURCE) $(DEP_CPP_CONSO) "$(INTDIR)"
+
+"$(INTDIR)\console.sbr" : $(SOURCE) $(DEP_CPP_CONSO) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Debug"
+
+
+"$(INTDIR)\console.obj" : $(SOURCE) $(DEP_CPP_CONSO) "$(INTDIR)"
+
+"$(INTDIR)\console.sbr" : $(SOURCE) $(DEP_CPP_CONSO) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Release"
+
+
+"$(INTDIR)\console.obj" : $(SOURCE) $(DEP_CPP_CONSO) "$(INTDIR)"
+
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\crc.c
+DEP_CPP_CRC_C=\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\zone.h"\
+	
+NODEP_CPP_CRC_C=\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+
+"$(INTDIR)\crc.obj" : $(SOURCE) $(DEP_CPP_CRC_C) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+
+"$(INTDIR)\crc.obj" : $(SOURCE) $(DEP_CPP_CRC_C) "$(INTDIR)"
+
+"$(INTDIR)\crc.sbr" : $(SOURCE) $(DEP_CPP_CRC_C) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Debug"
+
+
+"$(INTDIR)\crc.obj" : $(SOURCE) $(DEP_CPP_CRC_C) "$(INTDIR)"
+
+"$(INTDIR)\crc.sbr" : $(SOURCE) $(DEP_CPP_CRC_C) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Release"
+
+
+"$(INTDIR)\crc.obj" : $(SOURCE) $(DEP_CPP_CRC_C) "$(INTDIR)"
+
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\cvar.c
+DEP_CPP_CVAR_=\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\zone.h"\
+	
+NODEP_CPP_CVAR_=\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\qwsvdef.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+
+"$(INTDIR)\cvar.obj" : $(SOURCE) $(DEP_CPP_CVAR_) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+
+"$(INTDIR)\cvar.obj" : $(SOURCE) $(DEP_CPP_CVAR_) "$(INTDIR)"
+
+"$(INTDIR)\cvar.sbr" : $(SOURCE) $(DEP_CPP_CVAR_) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Debug"
+
+
+"$(INTDIR)\cvar.obj" : $(SOURCE) $(DEP_CPP_CVAR_) "$(INTDIR)"
+
+"$(INTDIR)\cvar.sbr" : $(SOURCE) $(DEP_CPP_CVAR_) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Release"
+
+
+"$(INTDIR)\cvar.obj" : $(SOURCE) $(DEP_CPP_CVAR_) "$(INTDIR)"
+
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\d_edge.c
+DEP_CPP_D_EDG=\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\d_local.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\r_shared.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\zone.h"\
+	
+NODEP_CPP_D_EDG=\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+
+"$(INTDIR)\d_edge.obj" : $(SOURCE) $(DEP_CPP_D_EDG) "$(INTDIR)"
+   $(CPP) /nologo /ML /GX /O2 /I "..\..\scitech\include" /I\
+ "..\..\dxsdk\sdk\inc" /D "WIN32" /D "NDEBUG" /D "_WINDOWS"\
+ /Fp"$(INTDIR)/qwcl.pch" /YX /Fo"$(INTDIR)/" /c $(SOURCE)
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+
+BuildCmds= \
+	$(CPP) /nologo /MLd /Gm /GX /Zi /Od /I "..\..\scitech\include" /I\
+ "..\..\dxsdk\sdk\inc" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR"$(INTDIR)/"\
+ /Fp"$(INTDIR)/qwcl.pch" /YX /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c $(SOURCE) \
+	
+
+"$(INTDIR)\d_edge.obj" : $(SOURCE) $(DEP_CPP_D_EDG) "$(INTDIR)"
+   $(BuildCmds)
+
+"$(INTDIR)\d_edge.sbr" : $(SOURCE) $(DEP_CPP_D_EDG) "$(INTDIR)"
+   $(BuildCmds)
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Release"
+
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\d_fill.c
+DEP_CPP_D_FIL=\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\zone.h"\
+	
+NODEP_CPP_D_FIL=\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+
+"$(INTDIR)\d_fill.obj" : $(SOURCE) $(DEP_CPP_D_FIL) "$(INTDIR)"
+   $(CPP) /nologo /ML /GX /O2 /I "..\..\scitech\include" /I\
+ "..\..\dxsdk\sdk\inc" /D "WIN32" /D "NDEBUG" /D "_WINDOWS"\
+ /Fp"$(INTDIR)/qwcl.pch" /YX /Fo"$(INTDIR)/" /c $(SOURCE)
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+
+BuildCmds= \
+	$(CPP) /nologo /MLd /Gm /GX /Zi /Od /I "..\..\scitech\include" /I\
+ "..\..\dxsdk\sdk\inc" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR"$(INTDIR)/"\
+ /Fp"$(INTDIR)/qwcl.pch" /YX /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c $(SOURCE) \
+	
+
+"$(INTDIR)\d_fill.obj" : $(SOURCE) $(DEP_CPP_D_FIL) "$(INTDIR)"
+   $(BuildCmds)
+
+"$(INTDIR)\d_fill.sbr" : $(SOURCE) $(DEP_CPP_D_FIL) "$(INTDIR)"
+   $(BuildCmds)
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Release"
+
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\d_init.c
+DEP_CPP_D_INI=\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\d_local.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\r_shared.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\zone.h"\
+	
+NODEP_CPP_D_INI=\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+
+"$(INTDIR)\d_init.obj" : $(SOURCE) $(DEP_CPP_D_INI) "$(INTDIR)"
+   $(CPP) /nologo /ML /GX /O2 /I "..\..\scitech\include" /I\
+ "..\..\dxsdk\sdk\inc" /D "WIN32" /D "NDEBUG" /D "_WINDOWS"\
+ /Fp"$(INTDIR)/qwcl.pch" /YX /Fo"$(INTDIR)/" /c $(SOURCE)
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+
+BuildCmds= \
+	$(CPP) /nologo /MLd /Gm /GX /Zi /Od /I "..\..\scitech\include" /I\
+ "..\..\dxsdk\sdk\inc" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR"$(INTDIR)/"\
+ /Fp"$(INTDIR)/qwcl.pch" /YX /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c $(SOURCE) \
+	
+
+"$(INTDIR)\d_init.obj" : $(SOURCE) $(DEP_CPP_D_INI) "$(INTDIR)"
+   $(BuildCmds)
+
+"$(INTDIR)\d_init.sbr" : $(SOURCE) $(DEP_CPP_D_INI) "$(INTDIR)"
+   $(BuildCmds)
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Release"
+
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\d_modech.c
+DEP_CPP_D_MOD=\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\d_local.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\r_shared.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\zone.h"\
+	
+NODEP_CPP_D_MOD=\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+
+"$(INTDIR)\d_modech.obj" : $(SOURCE) $(DEP_CPP_D_MOD) "$(INTDIR)"
+   $(CPP) /nologo /ML /GX /O2 /I "..\..\scitech\include" /I\
+ "..\..\dxsdk\sdk\inc" /D "WIN32" /D "NDEBUG" /D "_WINDOWS"\
+ /Fp"$(INTDIR)/qwcl.pch" /YX /Fo"$(INTDIR)/" /c $(SOURCE)
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+
+BuildCmds= \
+	$(CPP) /nologo /MLd /Gm /GX /Zi /Od /I "..\..\scitech\include" /I\
+ "..\..\dxsdk\sdk\inc" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR"$(INTDIR)/"\
+ /Fp"$(INTDIR)/qwcl.pch" /YX /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c $(SOURCE) \
+	
+
+"$(INTDIR)\d_modech.obj" : $(SOURCE) $(DEP_CPP_D_MOD) "$(INTDIR)"
+   $(BuildCmds)
+
+"$(INTDIR)\d_modech.sbr" : $(SOURCE) $(DEP_CPP_D_MOD) "$(INTDIR)"
+   $(BuildCmds)
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Release"
+
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\d_part.c
+DEP_CPP_D_PAR=\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\d_local.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\r_shared.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\zone.h"\
+	
+NODEP_CPP_D_PAR=\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+
+"$(INTDIR)\d_part.obj" : $(SOURCE) $(DEP_CPP_D_PAR) "$(INTDIR)"
+   $(CPP) /nologo /ML /GX /O2 /I "..\..\scitech\include" /I\
+ "..\..\dxsdk\sdk\inc" /D "WIN32" /D "NDEBUG" /D "_WINDOWS"\
+ /Fp"$(INTDIR)/qwcl.pch" /YX /Fo"$(INTDIR)/" /c $(SOURCE)
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+
+BuildCmds= \
+	$(CPP) /nologo /MLd /Gm /GX /Zi /Od /I "..\..\scitech\include" /I\
+ "..\..\dxsdk\sdk\inc" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR"$(INTDIR)/"\
+ /Fp"$(INTDIR)/qwcl.pch" /YX /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c $(SOURCE) \
+	
+
+"$(INTDIR)\d_part.obj" : $(SOURCE) $(DEP_CPP_D_PAR) "$(INTDIR)"
+   $(BuildCmds)
+
+"$(INTDIR)\d_part.sbr" : $(SOURCE) $(DEP_CPP_D_PAR) "$(INTDIR)"
+   $(BuildCmds)
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Release"
+
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\d_polyse.c
+DEP_CPP_D_POL=\
+	".\adivtab.h"\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\d_local.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\r_local.h"\
+	".\r_shared.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\zone.h"\
+	
+NODEP_CPP_D_POL=\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+
+"$(INTDIR)\d_polyse.obj" : $(SOURCE) $(DEP_CPP_D_POL) "$(INTDIR)"
+   $(CPP) /nologo /ML /GX /O2 /I "..\..\scitech\include" /I\
+ "..\..\dxsdk\sdk\inc" /D "WIN32" /D "NDEBUG" /D "_WINDOWS"\
+ /Fp"$(INTDIR)/qwcl.pch" /YX /Fo"$(INTDIR)/" /c $(SOURCE)
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+
+BuildCmds= \
+	$(CPP) /nologo /MLd /Gm /GX /Zi /Od /I "..\..\scitech\include" /I\
+ "..\..\dxsdk\sdk\inc" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR"$(INTDIR)/"\
+ /Fp"$(INTDIR)/qwcl.pch" /YX /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c $(SOURCE) \
+	
+
+"$(INTDIR)\d_polyse.obj" : $(SOURCE) $(DEP_CPP_D_POL) "$(INTDIR)"
+   $(BuildCmds)
+
+"$(INTDIR)\d_polyse.sbr" : $(SOURCE) $(DEP_CPP_D_POL) "$(INTDIR)"
+   $(BuildCmds)
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Release"
+
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\d_scan.c
+DEP_CPP_D_SCA=\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\d_local.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\r_local.h"\
+	".\r_shared.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\zone.h"\
+	
+NODEP_CPP_D_SCA=\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+
+"$(INTDIR)\d_scan.obj" : $(SOURCE) $(DEP_CPP_D_SCA) "$(INTDIR)"
+   $(CPP) /nologo /ML /GX /O2 /I "..\..\scitech\include" /I\
+ "..\..\dxsdk\sdk\inc" /D "WIN32" /D "NDEBUG" /D "_WINDOWS"\
+ /Fp"$(INTDIR)/qwcl.pch" /YX /Fo"$(INTDIR)/" /c $(SOURCE)
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+
+BuildCmds= \
+	$(CPP) /nologo /MLd /Gm /GX /Zi /Od /I "..\..\scitech\include" /I\
+ "..\..\dxsdk\sdk\inc" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR"$(INTDIR)/"\
+ /Fp"$(INTDIR)/qwcl.pch" /YX /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c $(SOURCE) \
+	
+
+"$(INTDIR)\d_scan.obj" : $(SOURCE) $(DEP_CPP_D_SCA) "$(INTDIR)"
+   $(BuildCmds)
+
+"$(INTDIR)\d_scan.sbr" : $(SOURCE) $(DEP_CPP_D_SCA) "$(INTDIR)"
+   $(BuildCmds)
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Release"
+
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\d_sky.c
+DEP_CPP_D_SKY=\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\d_local.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\r_local.h"\
+	".\r_shared.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\zone.h"\
+	
+NODEP_CPP_D_SKY=\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+
+"$(INTDIR)\d_sky.obj" : $(SOURCE) $(DEP_CPP_D_SKY) "$(INTDIR)"
+   $(CPP) /nologo /ML /GX /O2 /I "..\..\scitech\include" /I\
+ "..\..\dxsdk\sdk\inc" /D "WIN32" /D "NDEBUG" /D "_WINDOWS"\
+ /Fp"$(INTDIR)/qwcl.pch" /YX /Fo"$(INTDIR)/" /c $(SOURCE)
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+
+BuildCmds= \
+	$(CPP) /nologo /MLd /Gm /GX /Zi /Od /I "..\..\scitech\include" /I\
+ "..\..\dxsdk\sdk\inc" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR"$(INTDIR)/"\
+ /Fp"$(INTDIR)/qwcl.pch" /YX /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c $(SOURCE) \
+	
+
+"$(INTDIR)\d_sky.obj" : $(SOURCE) $(DEP_CPP_D_SKY) "$(INTDIR)"
+   $(BuildCmds)
+
+"$(INTDIR)\d_sky.sbr" : $(SOURCE) $(DEP_CPP_D_SKY) "$(INTDIR)"
+   $(BuildCmds)
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Release"
+
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\d_sprite.c
+DEP_CPP_D_SPR=\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\d_local.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\r_shared.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\zone.h"\
+	
+NODEP_CPP_D_SPR=\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+
+"$(INTDIR)\d_sprite.obj" : $(SOURCE) $(DEP_CPP_D_SPR) "$(INTDIR)"
+   $(CPP) /nologo /ML /GX /O2 /I "..\..\scitech\include" /I\
+ "..\..\dxsdk\sdk\inc" /D "WIN32" /D "NDEBUG" /D "_WINDOWS"\
+ /Fp"$(INTDIR)/qwcl.pch" /YX /Fo"$(INTDIR)/" /c $(SOURCE)
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+
+BuildCmds= \
+	$(CPP) /nologo /MLd /Gm /GX /Zi /Od /I "..\..\scitech\include" /I\
+ "..\..\dxsdk\sdk\inc" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR"$(INTDIR)/"\
+ /Fp"$(INTDIR)/qwcl.pch" /YX /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c $(SOURCE) \
+	
+
+"$(INTDIR)\d_sprite.obj" : $(SOURCE) $(DEP_CPP_D_SPR) "$(INTDIR)"
+   $(BuildCmds)
+
+"$(INTDIR)\d_sprite.sbr" : $(SOURCE) $(DEP_CPP_D_SPR) "$(INTDIR)"
+   $(BuildCmds)
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Release"
+
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\d_surf.c
+DEP_CPP_D_SUR=\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\d_local.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\r_local.h"\
+	".\r_shared.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\zone.h"\
+	
+NODEP_CPP_D_SUR=\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+
+"$(INTDIR)\d_surf.obj" : $(SOURCE) $(DEP_CPP_D_SUR) "$(INTDIR)"
+   $(CPP) /nologo /ML /GX /O2 /I "..\..\scitech\include" /I\
+ "..\..\dxsdk\sdk\inc" /D "WIN32" /D "NDEBUG" /D "_WINDOWS"\
+ /Fp"$(INTDIR)/qwcl.pch" /YX /Fo"$(INTDIR)/" /c $(SOURCE)
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+
+BuildCmds= \
+	$(CPP) /nologo /MLd /Gm /GX /Zi /Od /I "..\..\scitech\include" /I\
+ "..\..\dxsdk\sdk\inc" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR"$(INTDIR)/"\
+ /Fp"$(INTDIR)/qwcl.pch" /YX /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c $(SOURCE) \
+	
+
+"$(INTDIR)\d_surf.obj" : $(SOURCE) $(DEP_CPP_D_SUR) "$(INTDIR)"
+   $(BuildCmds)
+
+"$(INTDIR)\d_surf.sbr" : $(SOURCE) $(DEP_CPP_D_SUR) "$(INTDIR)"
+   $(BuildCmds)
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Release"
+
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\d_vars.c
+DEP_CPP_D_VAR=\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\zone.h"\
+	
+NODEP_CPP_D_VAR=\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+
+"$(INTDIR)\d_vars.obj" : $(SOURCE) $(DEP_CPP_D_VAR) "$(INTDIR)"
+   $(CPP) /nologo /ML /GX /O2 /I "..\..\scitech\include" /I\
+ "..\..\dxsdk\sdk\inc" /D "WIN32" /D "NDEBUG" /D "_WINDOWS"\
+ /Fp"$(INTDIR)/qwcl.pch" /YX /Fo"$(INTDIR)/" /c $(SOURCE)
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+
+BuildCmds= \
+	$(CPP) /nologo /MLd /Gm /GX /Zi /Od /I "..\..\scitech\include" /I\
+ "..\..\dxsdk\sdk\inc" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR"$(INTDIR)/"\
+ /Fp"$(INTDIR)/qwcl.pch" /YX /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c $(SOURCE) \
+	
+
+"$(INTDIR)\d_vars.obj" : $(SOURCE) $(DEP_CPP_D_VAR) "$(INTDIR)"
+   $(BuildCmds)
+
+"$(INTDIR)\d_vars.sbr" : $(SOURCE) $(DEP_CPP_D_VAR) "$(INTDIR)"
+   $(BuildCmds)
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Release"
+
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\d_zpoint.c
+DEP_CPP_D_ZPO=\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\d_local.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\r_shared.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\zone.h"\
+	
+NODEP_CPP_D_ZPO=\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+
+"$(INTDIR)\d_zpoint.obj" : $(SOURCE) $(DEP_CPP_D_ZPO) "$(INTDIR)"
+   $(CPP) /nologo /ML /GX /O2 /I "..\..\scitech\include" /I\
+ "..\..\dxsdk\sdk\inc" /D "WIN32" /D "NDEBUG" /D "_WINDOWS"\
+ /Fp"$(INTDIR)/qwcl.pch" /YX /Fo"$(INTDIR)/" /c $(SOURCE)
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+
+BuildCmds= \
+	$(CPP) /nologo /MLd /Gm /GX /Zi /Od /I "..\..\scitech\include" /I\
+ "..\..\dxsdk\sdk\inc" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR"$(INTDIR)/"\
+ /Fp"$(INTDIR)/qwcl.pch" /YX /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c $(SOURCE) \
+	
+
+"$(INTDIR)\d_zpoint.obj" : $(SOURCE) $(DEP_CPP_D_ZPO) "$(INTDIR)"
+   $(BuildCmds)
+
+"$(INTDIR)\d_zpoint.sbr" : $(SOURCE) $(DEP_CPP_D_ZPO) "$(INTDIR)"
+   $(BuildCmds)
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Release"
+
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\draw.c
+DEP_CPP_DRAW_=\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\zone.h"\
+	
+NODEP_CPP_DRAW_=\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+
+"$(INTDIR)\draw.obj" : $(SOURCE) $(DEP_CPP_DRAW_) "$(INTDIR)"
+   $(CPP) /nologo /ML /GX /O2 /I "..\..\scitech\include" /I\
+ "..\..\dxsdk\sdk\inc" /D "WIN32" /D "NDEBUG" /D "_WINDOWS"\
+ /Fp"$(INTDIR)/qwcl.pch" /YX /Fo"$(INTDIR)/" /c $(SOURCE)
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+
+BuildCmds= \
+	$(CPP) /nologo /MLd /Gm /GX /Zi /Od /I "..\..\scitech\include" /I\
+ "..\..\dxsdk\sdk\inc" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR"$(INTDIR)/"\
+ /Fp"$(INTDIR)/qwcl.pch" /YX /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c $(SOURCE) \
+	
+
+"$(INTDIR)\draw.obj" : $(SOURCE) $(DEP_CPP_DRAW_) "$(INTDIR)"
+   $(BuildCmds)
+
+"$(INTDIR)\draw.sbr" : $(SOURCE) $(DEP_CPP_DRAW_) "$(INTDIR)"
+   $(BuildCmds)
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Release"
+
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\gl_draw.c
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+# PROP Exclude_From_Build 1
+DEP_CPP_GL_DR=\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\zone.h"\
+	
+NODEP_CPP_GL_DR=\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+# PROP Exclude_From_Build 1
+DEP_CPP_GL_DR=\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\zone.h"\
+	
+NODEP_CPP_GL_DR=\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Debug"
+
+DEP_CPP_GL_DR=\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\cvar.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\mathlib.h"\
+	".\net.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\wad.h"\
+	".\zone.h"\
+	
+
+BuildCmds= \
+	$(CPP) /nologo /MLd /Gm /GX /Zi /Od /I "..\..\scitech\include" /I\
+ "..\..\dxsdk\sdk\inc" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "GLQUAKE"\
+ /FR"$(INTDIR)/" /Fp"$(INTDIR)/qwcl.pch" /YX /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c\
+ $(SOURCE) \
+	
+
+"$(INTDIR)\gl_draw.obj" : $(SOURCE) $(DEP_CPP_GL_DR) "$(INTDIR)"
+   $(BuildCmds)
+
+"$(INTDIR)\gl_draw.sbr" : $(SOURCE) $(DEP_CPP_GL_DR) "$(INTDIR)"
+   $(BuildCmds)
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Release"
+
+DEP_CPP_GL_DR=\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\zone.h"\
+	
+NODEP_CPP_GL_DR=\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+"$(INTDIR)\gl_draw.obj" : $(SOURCE) $(DEP_CPP_GL_DR) "$(INTDIR)"
+   $(CPP) /nologo /ML /GX /O2 /I "..\..\scitech\include" /I\
+ "..\..\dxsdk\sdk\inc" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "GLQUAKE"\
+ /Fp"$(INTDIR)/qwcl.pch" /YX /Fo"$(INTDIR)/" /c $(SOURCE)
+
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\gl_mesh.c
+DEP_CPP_GL_ME=\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\zone.h"\
+	
+NODEP_CPP_GL_ME=\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Debug"
+
+
+BuildCmds= \
+	$(CPP) /nologo /MLd /Gm /GX /Zi /Od /I "..\..\scitech\include" /I\
+ "..\..\dxsdk\sdk\inc" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "GLQUAKE"\
+ /FR"$(INTDIR)/" /Fp"$(INTDIR)/qwcl.pch" /YX /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c\
+ $(SOURCE) \
+	
+
+"$(INTDIR)\gl_mesh.obj" : $(SOURCE) $(DEP_CPP_GL_ME) "$(INTDIR)"
+   $(BuildCmds)
+
+"$(INTDIR)\gl_mesh.sbr" : $(SOURCE) $(DEP_CPP_GL_ME) "$(INTDIR)"
+   $(BuildCmds)
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Release"
+
+
+"$(INTDIR)\gl_mesh.obj" : $(SOURCE) $(DEP_CPP_GL_ME) "$(INTDIR)"
+   $(CPP) /nologo /ML /GX /O2 /I "..\..\scitech\include" /I\
+ "..\..\dxsdk\sdk\inc" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "GLQUAKE"\
+ /Fp"$(INTDIR)/qwcl.pch" /YX /Fo"$(INTDIR)/" /c $(SOURCE)
+
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\gl_model.c
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+# PROP Exclude_From_Build 1
+DEP_CPP_GL_MO=\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\zone.h"\
+	
+NODEP_CPP_GL_MO=\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+# PROP Exclude_From_Build 1
+DEP_CPP_GL_MO=\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\zone.h"\
+	
+NODEP_CPP_GL_MO=\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Debug"
+
+DEP_CPP_GL_MO=\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\cvar.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\mathlib.h"\
+	".\net.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\wad.h"\
+	".\zone.h"\
+	
+
+BuildCmds= \
+	$(CPP) /nologo /MLd /Gm /GX /Zi /Od /I "..\..\scitech\include" /I\
+ "..\..\dxsdk\sdk\inc" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "GLQUAKE"\
+ /FR"$(INTDIR)/" /Fp"$(INTDIR)/qwcl.pch" /YX /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c\
+ $(SOURCE) \
+	
+
+"$(INTDIR)\gl_model.obj" : $(SOURCE) $(DEP_CPP_GL_MO) "$(INTDIR)"
+   $(BuildCmds)
+
+"$(INTDIR)\gl_model.sbr" : $(SOURCE) $(DEP_CPP_GL_MO) "$(INTDIR)"
+   $(BuildCmds)
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Release"
+
+DEP_CPP_GL_MO=\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\zone.h"\
+	
+NODEP_CPP_GL_MO=\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+"$(INTDIR)\gl_model.obj" : $(SOURCE) $(DEP_CPP_GL_MO) "$(INTDIR)"
+   $(CPP) /nologo /ML /GX /O2 /I "..\..\scitech\include" /I\
+ "..\..\dxsdk\sdk\inc" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "GLQUAKE"\
+ /Fp"$(INTDIR)/qwcl.pch" /YX /Fo"$(INTDIR)/" /c $(SOURCE)
+
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\gl_ngraph.c
+DEP_CPP_GL_NG=\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\zone.h"\
+	
+NODEP_CPP_GL_NG=\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Debug"
+
+
+BuildCmds= \
+	$(CPP) /nologo /MLd /Gm /GX /Zi /Od /I "..\..\scitech\include" /I\
+ "..\..\dxsdk\sdk\inc" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "GLQUAKE"\
+ /FR"$(INTDIR)/" /Fp"$(INTDIR)/qwcl.pch" /YX /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c\
+ $(SOURCE) \
+	
+
+"$(INTDIR)\gl_ngraph.obj" : $(SOURCE) $(DEP_CPP_GL_NG) "$(INTDIR)"
+   $(BuildCmds)
+
+"$(INTDIR)\gl_ngraph.sbr" : $(SOURCE) $(DEP_CPP_GL_NG) "$(INTDIR)"
+   $(BuildCmds)
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Release"
+
+
+"$(INTDIR)\gl_ngraph.obj" : $(SOURCE) $(DEP_CPP_GL_NG) "$(INTDIR)"
+   $(CPP) /nologo /ML /GX /O2 /I "..\..\scitech\include" /I\
+ "..\..\dxsdk\sdk\inc" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "GLQUAKE"\
+ /Fp"$(INTDIR)/qwcl.pch" /YX /Fo"$(INTDIR)/" /c $(SOURCE)
+
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\gl_refrag.c
+DEP_CPP_GL_RE=\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\zone.h"\
+	
+NODEP_CPP_GL_RE=\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Debug"
+
+
+BuildCmds= \
+	$(CPP) /nologo /MLd /Gm /GX /Zi /Od /I "..\..\scitech\include" /I\
+ "..\..\dxsdk\sdk\inc" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "GLQUAKE"\
+ /FR"$(INTDIR)/" /Fp"$(INTDIR)/qwcl.pch" /YX /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c\
+ $(SOURCE) \
+	
+
+"$(INTDIR)\gl_refrag.obj" : $(SOURCE) $(DEP_CPP_GL_RE) "$(INTDIR)"
+   $(BuildCmds)
+
+"$(INTDIR)\gl_refrag.sbr" : $(SOURCE) $(DEP_CPP_GL_RE) "$(INTDIR)"
+   $(BuildCmds)
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Release"
+
+
+"$(INTDIR)\gl_refrag.obj" : $(SOURCE) $(DEP_CPP_GL_RE) "$(INTDIR)"
+   $(CPP) /nologo /ML /GX /O2 /I "..\..\scitech\include" /I\
+ "..\..\dxsdk\sdk\inc" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "GLQUAKE"\
+ /Fp"$(INTDIR)/qwcl.pch" /YX /Fo"$(INTDIR)/" /c $(SOURCE)
+
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\gl_rlight.c
+DEP_CPP_GL_RL=\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\zone.h"\
+	
+NODEP_CPP_GL_RL=\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Debug"
+
+
+BuildCmds= \
+	$(CPP) /nologo /MLd /Gm /GX /Zi /Od /I "..\..\scitech\include" /I\
+ "..\..\dxsdk\sdk\inc" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "GLQUAKE"\
+ /FR"$(INTDIR)/" /Fp"$(INTDIR)/qwcl.pch" /YX /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c\
+ $(SOURCE) \
+	
+
+"$(INTDIR)\gl_rlight.obj" : $(SOURCE) $(DEP_CPP_GL_RL) "$(INTDIR)"
+   $(BuildCmds)
+
+"$(INTDIR)\gl_rlight.sbr" : $(SOURCE) $(DEP_CPP_GL_RL) "$(INTDIR)"
+   $(BuildCmds)
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Release"
+
+
+"$(INTDIR)\gl_rlight.obj" : $(SOURCE) $(DEP_CPP_GL_RL) "$(INTDIR)"
+   $(CPP) /nologo /ML /GX /O2 /I "..\..\scitech\include" /I\
+ "..\..\dxsdk\sdk\inc" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "GLQUAKE"\
+ /Fp"$(INTDIR)/qwcl.pch" /YX /Fo"$(INTDIR)/" /c $(SOURCE)
+
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\gl_rmain.c
+DEP_CPP_GL_RM=\
+	".\anorm_dots.h"\
+	".\anorms.h"\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\zone.h"\
+	
+NODEP_CPP_GL_RM=\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Debug"
+
+
+BuildCmds= \
+	$(CPP) /nologo /MLd /Gm /GX /Zi /Od /I "..\..\scitech\include" /I\
+ "..\..\dxsdk\sdk\inc" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "GLQUAKE"\
+ /FR"$(INTDIR)/" /Fp"$(INTDIR)/qwcl.pch" /YX /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c\
+ $(SOURCE) \
+	
+
+"$(INTDIR)\gl_rmain.obj" : $(SOURCE) $(DEP_CPP_GL_RM) "$(INTDIR)"
+   $(BuildCmds)
+
+"$(INTDIR)\gl_rmain.sbr" : $(SOURCE) $(DEP_CPP_GL_RM) "$(INTDIR)"
+   $(BuildCmds)
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Release"
+
+
+"$(INTDIR)\gl_rmain.obj" : $(SOURCE) $(DEP_CPP_GL_RM) "$(INTDIR)"
+   $(CPP) /nologo /ML /GX /O2 /I "..\..\scitech\include" /I\
+ "..\..\dxsdk\sdk\inc" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "GLQUAKE"\
+ /Fp"$(INTDIR)/qwcl.pch" /YX /Fo"$(INTDIR)/" /c $(SOURCE)
+
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\gl_rmisc.c
+DEP_CPP_GL_RMI=\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\zone.h"\
+	
+NODEP_CPP_GL_RMI=\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Debug"
+
+
+BuildCmds= \
+	$(CPP) /nologo /MLd /Gm /GX /Zi /Od /I "..\..\scitech\include" /I\
+ "..\..\dxsdk\sdk\inc" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "GLQUAKE"\
+ /FR"$(INTDIR)/" /Fp"$(INTDIR)/qwcl.pch" /YX /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c\
+ $(SOURCE) \
+	
+
+"$(INTDIR)\gl_rmisc.obj" : $(SOURCE) $(DEP_CPP_GL_RMI) "$(INTDIR)"
+   $(BuildCmds)
+
+"$(INTDIR)\gl_rmisc.sbr" : $(SOURCE) $(DEP_CPP_GL_RMI) "$(INTDIR)"
+   $(BuildCmds)
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Release"
+
+
+"$(INTDIR)\gl_rmisc.obj" : $(SOURCE) $(DEP_CPP_GL_RMI) "$(INTDIR)"
+   $(CPP) /nologo /ML /GX /O2 /I "..\..\scitech\include" /I\
+ "..\..\dxsdk\sdk\inc" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "GLQUAKE"\
+ /Fp"$(INTDIR)/qwcl.pch" /YX /Fo"$(INTDIR)/" /c $(SOURCE)
+
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\gl_rsurf.c
+DEP_CPP_GL_RS=\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\zone.h"\
+	
+NODEP_CPP_GL_RS=\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Debug"
+
+
+BuildCmds= \
+	$(CPP) /nologo /MLd /Gm /GX /Zi /Od /I "..\..\scitech\include" /I\
+ "..\..\dxsdk\sdk\inc" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "GLQUAKE"\
+ /FR"$(INTDIR)/" /Fp"$(INTDIR)/qwcl.pch" /YX /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c\
+ $(SOURCE) \
+	
+
+"$(INTDIR)\gl_rsurf.obj" : $(SOURCE) $(DEP_CPP_GL_RS) "$(INTDIR)"
+   $(BuildCmds)
+
+"$(INTDIR)\gl_rsurf.sbr" : $(SOURCE) $(DEP_CPP_GL_RS) "$(INTDIR)"
+   $(BuildCmds)
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Release"
+
+
+"$(INTDIR)\gl_rsurf.obj" : $(SOURCE) $(DEP_CPP_GL_RS) "$(INTDIR)"
+   $(CPP) /nologo /ML /GX /O2 /I "..\..\scitech\include" /I\
+ "..\..\dxsdk\sdk\inc" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "GLQUAKE"\
+ /Fp"$(INTDIR)/qwcl.pch" /YX /Fo"$(INTDIR)/" /c $(SOURCE)
+
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\gl_screen.c
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+# PROP Exclude_From_Build 1
+DEP_CPP_GL_SC=\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\zone.h"\
+	
+NODEP_CPP_GL_SC=\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+# PROP Exclude_From_Build 1
+DEP_CPP_GL_SC=\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\zone.h"\
+	
+NODEP_CPP_GL_SC=\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Debug"
+
+DEP_CPP_GL_SC=\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\cvar.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\mathlib.h"\
+	".\net.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\wad.h"\
+	".\zone.h"\
+	
+
+BuildCmds= \
+	$(CPP) /nologo /MLd /Gm /GX /Zi /Od /I "..\..\scitech\include" /I\
+ "..\..\dxsdk\sdk\inc" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "GLQUAKE"\
+ /FR"$(INTDIR)/" /Fp"$(INTDIR)/qwcl.pch" /YX /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c\
+ $(SOURCE) \
+	
+
+"$(INTDIR)\gl_screen.obj" : $(SOURCE) $(DEP_CPP_GL_SC) "$(INTDIR)"
+   $(BuildCmds)
+
+"$(INTDIR)\gl_screen.sbr" : $(SOURCE) $(DEP_CPP_GL_SC) "$(INTDIR)"
+   $(BuildCmds)
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Release"
+
+DEP_CPP_GL_SC=\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\zone.h"\
+	
+NODEP_CPP_GL_SC=\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+"$(INTDIR)\gl_screen.obj" : $(SOURCE) $(DEP_CPP_GL_SC) "$(INTDIR)"
+   $(CPP) /nologo /ML /GX /O2 /I "..\..\scitech\include" /I\
+ "..\..\dxsdk\sdk\inc" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "GLQUAKE"\
+ /Fp"$(INTDIR)/qwcl.pch" /YX /Fo"$(INTDIR)/" /c $(SOURCE)
+
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\gl_test.c
+DEP_CPP_GL_TE=\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\zone.h"\
+	
+NODEP_CPP_GL_TE=\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Debug"
+
+
+BuildCmds= \
+	$(CPP) /nologo /MLd /Gm /GX /Zi /Od /I "..\..\scitech\include" /I\
+ "..\..\dxsdk\sdk\inc" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "GLQUAKE"\
+ /FR"$(INTDIR)/" /Fp"$(INTDIR)/qwcl.pch" /YX /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c\
+ $(SOURCE) \
+	
+
+"$(INTDIR)\gl_test.obj" : $(SOURCE) $(DEP_CPP_GL_TE) "$(INTDIR)"
+   $(BuildCmds)
+
+"$(INTDIR)\gl_test.sbr" : $(SOURCE) $(DEP_CPP_GL_TE) "$(INTDIR)"
+   $(BuildCmds)
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Release"
+
+
+"$(INTDIR)\gl_test.obj" : $(SOURCE) $(DEP_CPP_GL_TE) "$(INTDIR)"
+   $(CPP) /nologo /ML /GX /O2 /I "..\..\scitech\include" /I\
+ "..\..\dxsdk\sdk\inc" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "GLQUAKE"\
+ /Fp"$(INTDIR)/qwcl.pch" /YX /Fo"$(INTDIR)/" /c $(SOURCE)
+
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\gl_vidnt.c
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+# PROP Exclude_From_Build 1
+DEP_CPP_GL_VI=\
+	"..\..\scitech\include\debug.h"\
+	"..\..\scitech\include\mgldos.h"\
+	"..\..\scitech\include\mglwin.h"\
+	"..\..\scitech\include\mgraph.h"\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\cvar.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\mathlib.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\wad.h"\
+	".\winquake.h"\
+	".\zone.h"\
+	
+NODEP_CPP_GL_VI=\
+	"..\..\scitech\include\mglrect.hpp"\
+	
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+# PROP Exclude_From_Build 1
+DEP_CPP_GL_VI=\
+	"..\..\scitech\include\debug.h"\
+	"..\..\scitech\include\mgldos.h"\
+	"..\..\scitech\include\mglwin.h"\
+	"..\..\scitech\include\mgraph.h"\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\cvar.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\mathlib.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\wad.h"\
+	".\winquake.h"\
+	".\zone.h"\
+	
+NODEP_CPP_GL_VI=\
+	"..\..\scitech\include\mglrect.hpp"\
+	
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Debug"
+
+DEP_CPP_GL_VI=\
+	"..\..\scitech\include\mgraph.h"\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\cvar.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\mathlib.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\wad.h"\
+	".\winquake.h"\
+	".\zone.h"\
+	
+
+BuildCmds= \
+	$(CPP) /nologo /MLd /Gm /GX /Zi /Od /I "..\..\scitech\include" /I\
+ "..\..\dxsdk\sdk\inc" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "GLQUAKE"\
+ /FR"$(INTDIR)/" /Fp"$(INTDIR)/qwcl.pch" /YX /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c\
+ $(SOURCE) \
+	
+
+"$(INTDIR)\gl_vidnt.obj" : $(SOURCE) $(DEP_CPP_GL_VI) "$(INTDIR)"
+   $(BuildCmds)
+
+"$(INTDIR)\gl_vidnt.sbr" : $(SOURCE) $(DEP_CPP_GL_VI) "$(INTDIR)"
+   $(BuildCmds)
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Release"
+
+DEP_CPP_GL_VI=\
+	"..\..\scitech\include\debug.h"\
+	"..\..\scitech\include\mgldos.h"\
+	"..\..\scitech\include\mglwin.h"\
+	"..\..\scitech\include\mgraph.h"\
+	".\quakedef.h"\
+	".\winquake.h"\
+	
+NODEP_CPP_GL_VI=\
+	"..\..\scitech\include\mglrect.hpp"\
+	
+
+"$(INTDIR)\gl_vidnt.obj" : $(SOURCE) $(DEP_CPP_GL_VI) "$(INTDIR)"
+   $(CPP) /nologo /ML /GX /O2 /I "..\..\scitech\include" /I\
+ "..\..\dxsdk\sdk\inc" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "GLQUAKE"\
+ /Fp"$(INTDIR)/qwcl.pch" /YX /Fo"$(INTDIR)/" /c $(SOURCE)
+
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\gl_warp.c
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+# PROP Exclude_From_Build 1
+DEP_CPP_GL_WA=\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\gl_warp_sin.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\zone.h"\
+	
+NODEP_CPP_GL_WA=\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+# PROP Exclude_From_Build 1
+DEP_CPP_GL_WA=\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\gl_warp_sin.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\zone.h"\
+	
+NODEP_CPP_GL_WA=\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Debug"
+
+DEP_CPP_GL_WA=\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\cvar.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\gl_warp_sin.h"\
+	".\mathlib.h"\
+	".\net.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\wad.h"\
+	".\zone.h"\
+	
+
+BuildCmds= \
+	$(CPP) /nologo /MLd /Gm /GX /Zi /Od /I "..\..\scitech\include" /I\
+ "..\..\dxsdk\sdk\inc" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "GLQUAKE"\
+ /FR"$(INTDIR)/" /Fp"$(INTDIR)/qwcl.pch" /YX /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c\
+ $(SOURCE) \
+	
+
+"$(INTDIR)\gl_warp.obj" : $(SOURCE) $(DEP_CPP_GL_WA) "$(INTDIR)"
+   $(BuildCmds)
+
+"$(INTDIR)\gl_warp.sbr" : $(SOURCE) $(DEP_CPP_GL_WA) "$(INTDIR)"
+   $(BuildCmds)
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Release"
+
+DEP_CPP_GL_WA=\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\gl_warp_sin.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\zone.h"\
+	
+NODEP_CPP_GL_WA=\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+"$(INTDIR)\gl_warp.obj" : $(SOURCE) $(DEP_CPP_GL_WA) "$(INTDIR)"
+   $(CPP) /nologo /ML /GX /O2 /I "..\..\scitech\include" /I\
+ "..\..\dxsdk\sdk\inc" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "GLQUAKE"\
+ /Fp"$(INTDIR)/qwcl.pch" /YX /Fo"$(INTDIR)/" /c $(SOURCE)
+
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\in_win.c
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+DEP_CPP_IN_WI=\
+	"..\..\dxsdk\sdk\inc\dinput.h"\
+	"..\..\scitech\include\debug.h"\
+	"..\..\scitech\include\mgldos.h"\
+	"..\..\scitech\include\mglwin.h"\
+	"..\..\scitech\include\mgraph.h"\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\winquake.h"\
+	".\zone.h"\
+	
+NODEP_CPP_IN_WI=\
+	"..\..\scitech\include\mglrect.hpp"\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+"$(INTDIR)\in_win.obj" : $(SOURCE) $(DEP_CPP_IN_WI) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+DEP_CPP_IN_WI=\
+	"..\..\dxsdk\sdk\inc\dinput.h"\
+	"..\..\scitech\include\debug.h"\
+	"..\..\scitech\include\mgldos.h"\
+	"..\..\scitech\include\mglwin.h"\
+	"..\..\scitech\include\mgraph.h"\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\winquake.h"\
+	".\zone.h"\
+	
+NODEP_CPP_IN_WI=\
+	"..\..\scitech\include\mglrect.hpp"\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+"$(INTDIR)\in_win.obj" : $(SOURCE) $(DEP_CPP_IN_WI) "$(INTDIR)"
+
+"$(INTDIR)\in_win.sbr" : $(SOURCE) $(DEP_CPP_IN_WI) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Debug"
+
+DEP_CPP_IN_WI=\
+	"..\..\dxsdk\sdk\inc\dinput.h"\
+	"..\..\scitech\include\mgraph.h"\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\cvar.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\mathlib.h"\
+	".\net.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\wad.h"\
+	".\winquake.h"\
+	".\zone.h"\
+	
+
+"$(INTDIR)\in_win.obj" : $(SOURCE) $(DEP_CPP_IN_WI) "$(INTDIR)"
+
+"$(INTDIR)\in_win.sbr" : $(SOURCE) $(DEP_CPP_IN_WI) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Release"
+
+DEP_CPP_IN_WI=\
+	"..\..\dxsdk\sdk\inc\dinput.h"\
+	"..\..\scitech\include\debug.h"\
+	"..\..\scitech\include\mgldos.h"\
+	"..\..\scitech\include\mglwin.h"\
+	"..\..\scitech\include\mgraph.h"\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\winquake.h"\
+	".\zone.h"\
+	
+NODEP_CPP_IN_WI=\
+	"..\..\scitech\include\mglrect.hpp"\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+"$(INTDIR)\in_win.obj" : $(SOURCE) $(DEP_CPP_IN_WI) "$(INTDIR)"
+
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\keys.c
+DEP_CPP_KEYS_=\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\zone.h"\
+	
+NODEP_CPP_KEYS_=\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+
+"$(INTDIR)\keys.obj" : $(SOURCE) $(DEP_CPP_KEYS_) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+
+"$(INTDIR)\keys.obj" : $(SOURCE) $(DEP_CPP_KEYS_) "$(INTDIR)"
+
+"$(INTDIR)\keys.sbr" : $(SOURCE) $(DEP_CPP_KEYS_) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Debug"
+
+
+"$(INTDIR)\keys.obj" : $(SOURCE) $(DEP_CPP_KEYS_) "$(INTDIR)"
+
+"$(INTDIR)\keys.sbr" : $(SOURCE) $(DEP_CPP_KEYS_) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Release"
+
+
+"$(INTDIR)\keys.obj" : $(SOURCE) $(DEP_CPP_KEYS_) "$(INTDIR)"
+
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\mathlib.c
+DEP_CPP_MATHL=\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\zone.h"\
+	
+NODEP_CPP_MATHL=\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+
+"$(INTDIR)\mathlib.obj" : $(SOURCE) $(DEP_CPP_MATHL) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+
+"$(INTDIR)\mathlib.obj" : $(SOURCE) $(DEP_CPP_MATHL) "$(INTDIR)"
+
+"$(INTDIR)\mathlib.sbr" : $(SOURCE) $(DEP_CPP_MATHL) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Debug"
+
+
+"$(INTDIR)\mathlib.obj" : $(SOURCE) $(DEP_CPP_MATHL) "$(INTDIR)"
+
+"$(INTDIR)\mathlib.sbr" : $(SOURCE) $(DEP_CPP_MATHL) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Release"
+
+
+"$(INTDIR)\mathlib.obj" : $(SOURCE) $(DEP_CPP_MATHL) "$(INTDIR)"
+
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\md4.c
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+
+"$(INTDIR)\md4.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+
+"$(INTDIR)\md4.obj" : $(SOURCE) "$(INTDIR)"
+
+"$(INTDIR)\md4.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Debug"
+
+
+"$(INTDIR)\md4.obj" : $(SOURCE) "$(INTDIR)"
+
+"$(INTDIR)\md4.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Release"
+
+
+"$(INTDIR)\md4.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\menu.c
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+DEP_CPP_MENU_=\
+	"..\..\scitech\include\debug.h"\
+	"..\..\scitech\include\mgldos.h"\
+	"..\..\scitech\include\mglwin.h"\
+	"..\..\scitech\include\mgraph.h"\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\cvar.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\mathlib.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\wad.h"\
+	".\winquake.h"\
+	".\zone.h"\
+	
+NODEP_CPP_MENU_=\
+	"..\..\scitech\include\mglrect.hpp"\
+	
+
+"$(INTDIR)\menu.obj" : $(SOURCE) $(DEP_CPP_MENU_) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+DEP_CPP_MENU_=\
+	"..\..\scitech\include\debug.h"\
+	"..\..\scitech\include\mgldos.h"\
+	"..\..\scitech\include\mglwin.h"\
+	"..\..\scitech\include\mgraph.h"\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\cvar.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\mathlib.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\wad.h"\
+	".\winquake.h"\
+	".\zone.h"\
+	
+NODEP_CPP_MENU_=\
+	"..\..\scitech\include\mglrect.hpp"\
+	
+
+"$(INTDIR)\menu.obj" : $(SOURCE) $(DEP_CPP_MENU_) "$(INTDIR)"
+
+"$(INTDIR)\menu.sbr" : $(SOURCE) $(DEP_CPP_MENU_) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Debug"
+
+DEP_CPP_MENU_=\
+	"..\..\scitech\include\mgraph.h"\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\cvar.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\mathlib.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\wad.h"\
+	".\winquake.h"\
+	".\zone.h"\
+	
+
+"$(INTDIR)\menu.obj" : $(SOURCE) $(DEP_CPP_MENU_) "$(INTDIR)"
+
+"$(INTDIR)\menu.sbr" : $(SOURCE) $(DEP_CPP_MENU_) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Release"
+
+DEP_CPP_MENU_=\
+	"..\..\scitech\include\debug.h"\
+	"..\..\scitech\include\mgldos.h"\
+	"..\..\scitech\include\mglwin.h"\
+	"..\..\scitech\include\mgraph.h"\
+	".\quakedef.h"\
+	".\winquake.h"\
+	
+NODEP_CPP_MENU_=\
+	"..\..\scitech\include\mglrect.hpp"\
+	
+
+"$(INTDIR)\menu.obj" : $(SOURCE) $(DEP_CPP_MENU_) "$(INTDIR)"
+
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\model.c
+DEP_CPP_MODEL=\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\r_local.h"\
+	".\r_shared.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\zone.h"\
+	
+NODEP_CPP_MODEL=\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+
+"$(INTDIR)\model.obj" : $(SOURCE) $(DEP_CPP_MODEL) "$(INTDIR)"
+   $(CPP) /nologo /ML /GX /O2 /I "..\..\scitech\include" /I\
+ "..\..\dxsdk\sdk\inc" /D "WIN32" /D "NDEBUG" /D "_WINDOWS"\
+ /Fp"$(INTDIR)/qwcl.pch" /YX /Fo"$(INTDIR)/" /c $(SOURCE)
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+
+BuildCmds= \
+	$(CPP) /nologo /MLd /Gm /GX /Zi /Od /I "..\..\scitech\include" /I\
+ "..\..\dxsdk\sdk\inc" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR"$(INTDIR)/"\
+ /Fp"$(INTDIR)/qwcl.pch" /YX /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c $(SOURCE) \
+	
+
+"$(INTDIR)\model.obj" : $(SOURCE) $(DEP_CPP_MODEL) "$(INTDIR)"
+   $(BuildCmds)
+
+"$(INTDIR)\model.sbr" : $(SOURCE) $(DEP_CPP_MODEL) "$(INTDIR)"
+   $(BuildCmds)
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Release"
+
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\net_chan.c
+DEP_CPP_NET_C=\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\zone.h"\
+	
+NODEP_CPP_NET_C=\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+
+"$(INTDIR)\net_chan.obj" : $(SOURCE) $(DEP_CPP_NET_C) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+
+"$(INTDIR)\net_chan.obj" : $(SOURCE) $(DEP_CPP_NET_C) "$(INTDIR)"
+
+"$(INTDIR)\net_chan.sbr" : $(SOURCE) $(DEP_CPP_NET_C) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Debug"
+
+
+"$(INTDIR)\net_chan.obj" : $(SOURCE) $(DEP_CPP_NET_C) "$(INTDIR)"
+
+"$(INTDIR)\net_chan.sbr" : $(SOURCE) $(DEP_CPP_NET_C) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Release"
+
+
+"$(INTDIR)\net_chan.obj" : $(SOURCE) $(DEP_CPP_NET_C) "$(INTDIR)"
+
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\net_wins.c
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+DEP_CPP_NET_W=\
+	"..\..\scitech\include\debug.h"\
+	"..\..\scitech\include\mgldos.h"\
+	"..\..\scitech\include\mglwin.h"\
+	"..\..\scitech\include\mgraph.h"\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\winquake.h"\
+	".\zone.h"\
+	
+NODEP_CPP_NET_W=\
+	"..\..\scitech\include\mglrect.hpp"\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+"$(INTDIR)\net_wins.obj" : $(SOURCE) $(DEP_CPP_NET_W) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+DEP_CPP_NET_W=\
+	"..\..\scitech\include\debug.h"\
+	"..\..\scitech\include\mgldos.h"\
+	"..\..\scitech\include\mglwin.h"\
+	"..\..\scitech\include\mgraph.h"\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\winquake.h"\
+	".\zone.h"\
+	
+NODEP_CPP_NET_W=\
+	"..\..\scitech\include\mglrect.hpp"\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+"$(INTDIR)\net_wins.obj" : $(SOURCE) $(DEP_CPP_NET_W) "$(INTDIR)"
+
+"$(INTDIR)\net_wins.sbr" : $(SOURCE) $(DEP_CPP_NET_W) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Debug"
+
+DEP_CPP_NET_W=\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\winquake.h"\
+	".\zone.h"\
+	
+NODEP_CPP_NET_W=\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+"$(INTDIR)\net_wins.obj" : $(SOURCE) $(DEP_CPP_NET_W) "$(INTDIR)"
+
+"$(INTDIR)\net_wins.sbr" : $(SOURCE) $(DEP_CPP_NET_W) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Release"
+
+DEP_CPP_NET_W=\
+	"..\..\scitech\include\debug.h"\
+	"..\..\scitech\include\mgldos.h"\
+	"..\..\scitech\include\mglwin.h"\
+	"..\..\scitech\include\mgraph.h"\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\winquake.h"\
+	".\zone.h"\
+	
+NODEP_CPP_NET_W=\
+	"..\..\scitech\include\mglrect.hpp"\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+"$(INTDIR)\net_wins.obj" : $(SOURCE) $(DEP_CPP_NET_W) "$(INTDIR)"
+
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\pmove.c
+DEP_CPP_PMOVE=\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\zone.h"\
+	
+NODEP_CPP_PMOVE=\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+
+"$(INTDIR)\pmove.obj" : $(SOURCE) $(DEP_CPP_PMOVE) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+
+"$(INTDIR)\pmove.obj" : $(SOURCE) $(DEP_CPP_PMOVE) "$(INTDIR)"
+
+"$(INTDIR)\pmove.sbr" : $(SOURCE) $(DEP_CPP_PMOVE) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Debug"
+
+
+"$(INTDIR)\pmove.obj" : $(SOURCE) $(DEP_CPP_PMOVE) "$(INTDIR)"
+
+"$(INTDIR)\pmove.sbr" : $(SOURCE) $(DEP_CPP_PMOVE) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Release"
+
+
+"$(INTDIR)\pmove.obj" : $(SOURCE) $(DEP_CPP_PMOVE) "$(INTDIR)"
+
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\pmovetst.c
+DEP_CPP_PMOVET=\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\zone.h"\
+	
+NODEP_CPP_PMOVET=\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+
+"$(INTDIR)\pmovetst.obj" : $(SOURCE) $(DEP_CPP_PMOVET) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+
+"$(INTDIR)\pmovetst.obj" : $(SOURCE) $(DEP_CPP_PMOVET) "$(INTDIR)"
+
+"$(INTDIR)\pmovetst.sbr" : $(SOURCE) $(DEP_CPP_PMOVET) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Debug"
+
+
+"$(INTDIR)\pmovetst.obj" : $(SOURCE) $(DEP_CPP_PMOVET) "$(INTDIR)"
+
+"$(INTDIR)\pmovetst.sbr" : $(SOURCE) $(DEP_CPP_PMOVET) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Release"
+
+
+"$(INTDIR)\pmovetst.obj" : $(SOURCE) $(DEP_CPP_PMOVET) "$(INTDIR)"
+
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\r_aclip.c
+DEP_CPP_R_ACL=\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\d_local.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\r_local.h"\
+	".\r_shared.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\zone.h"\
+	
+NODEP_CPP_R_ACL=\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+
+"$(INTDIR)\r_aclip.obj" : $(SOURCE) $(DEP_CPP_R_ACL) "$(INTDIR)"
+   $(CPP) /nologo /ML /GX /O2 /I "..\..\scitech\include" /I\
+ "..\..\dxsdk\sdk\inc" /D "WIN32" /D "NDEBUG" /D "_WINDOWS"\
+ /Fp"$(INTDIR)/qwcl.pch" /YX /Fo"$(INTDIR)/" /c $(SOURCE)
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+
+BuildCmds= \
+	$(CPP) /nologo /MLd /Gm /GX /Zi /Od /I "..\..\scitech\include" /I\
+ "..\..\dxsdk\sdk\inc" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR"$(INTDIR)/"\
+ /Fp"$(INTDIR)/qwcl.pch" /YX /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c $(SOURCE) \
+	
+
+"$(INTDIR)\r_aclip.obj" : $(SOURCE) $(DEP_CPP_R_ACL) "$(INTDIR)"
+   $(BuildCmds)
+
+"$(INTDIR)\r_aclip.sbr" : $(SOURCE) $(DEP_CPP_R_ACL) "$(INTDIR)"
+   $(BuildCmds)
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Release"
+
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\r_alias.c
+DEP_CPP_R_ALI=\
+	".\anorms.h"\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\d_local.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\r_local.h"\
+	".\r_shared.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\zone.h"\
+	
+NODEP_CPP_R_ALI=\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+
+"$(INTDIR)\r_alias.obj" : $(SOURCE) $(DEP_CPP_R_ALI) "$(INTDIR)"
+   $(CPP) /nologo /ML /GX /O2 /I "..\..\scitech\include" /I\
+ "..\..\dxsdk\sdk\inc" /D "WIN32" /D "NDEBUG" /D "_WINDOWS"\
+ /Fp"$(INTDIR)/qwcl.pch" /YX /Fo"$(INTDIR)/" /c $(SOURCE)
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+
+BuildCmds= \
+	$(CPP) /nologo /MLd /Gm /GX /Zi /Od /I "..\..\scitech\include" /I\
+ "..\..\dxsdk\sdk\inc" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR"$(INTDIR)/"\
+ /Fp"$(INTDIR)/qwcl.pch" /YX /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c $(SOURCE) \
+	
+
+"$(INTDIR)\r_alias.obj" : $(SOURCE) $(DEP_CPP_R_ALI) "$(INTDIR)"
+   $(BuildCmds)
+
+"$(INTDIR)\r_alias.sbr" : $(SOURCE) $(DEP_CPP_R_ALI) "$(INTDIR)"
+   $(BuildCmds)
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Release"
+
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\r_bsp.c
+DEP_CPP_R_BSP=\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\r_local.h"\
+	".\r_shared.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\zone.h"\
+	
+NODEP_CPP_R_BSP=\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+
+"$(INTDIR)\r_bsp.obj" : $(SOURCE) $(DEP_CPP_R_BSP) "$(INTDIR)"
+   $(CPP) /nologo /ML /GX /O2 /I "..\..\scitech\include" /I\
+ "..\..\dxsdk\sdk\inc" /D "WIN32" /D "NDEBUG" /D "_WINDOWS"\
+ /Fp"$(INTDIR)/qwcl.pch" /YX /Fo"$(INTDIR)/" /c $(SOURCE)
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+
+BuildCmds= \
+	$(CPP) /nologo /MLd /Gm /GX /Zi /Od /I "..\..\scitech\include" /I\
+ "..\..\dxsdk\sdk\inc" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR"$(INTDIR)/"\
+ /Fp"$(INTDIR)/qwcl.pch" /YX /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c $(SOURCE) \
+	
+
+"$(INTDIR)\r_bsp.obj" : $(SOURCE) $(DEP_CPP_R_BSP) "$(INTDIR)"
+   $(BuildCmds)
+
+"$(INTDIR)\r_bsp.sbr" : $(SOURCE) $(DEP_CPP_R_BSP) "$(INTDIR)"
+   $(BuildCmds)
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Release"
+
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\r_draw.c
+DEP_CPP_R_DRA=\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\d_local.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\r_local.h"\
+	".\r_shared.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\zone.h"\
+	
+NODEP_CPP_R_DRA=\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+
+"$(INTDIR)\r_draw.obj" : $(SOURCE) $(DEP_CPP_R_DRA) "$(INTDIR)"
+   $(CPP) /nologo /ML /GX /O2 /I "..\..\scitech\include" /I\
+ "..\..\dxsdk\sdk\inc" /D "WIN32" /D "NDEBUG" /D "_WINDOWS"\
+ /Fp"$(INTDIR)/qwcl.pch" /YX /Fo"$(INTDIR)/" /c $(SOURCE)
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+
+BuildCmds= \
+	$(CPP) /nologo /MLd /Gm /GX /Zi /Od /I "..\..\scitech\include" /I\
+ "..\..\dxsdk\sdk\inc" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR"$(INTDIR)/"\
+ /Fp"$(INTDIR)/qwcl.pch" /YX /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c $(SOURCE) \
+	
+
+"$(INTDIR)\r_draw.obj" : $(SOURCE) $(DEP_CPP_R_DRA) "$(INTDIR)"
+   $(BuildCmds)
+
+"$(INTDIR)\r_draw.sbr" : $(SOURCE) $(DEP_CPP_R_DRA) "$(INTDIR)"
+   $(BuildCmds)
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Release"
+
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\r_edge.c
+DEP_CPP_R_EDG=\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\r_local.h"\
+	".\r_shared.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\zone.h"\
+	
+NODEP_CPP_R_EDG=\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+
+"$(INTDIR)\r_edge.obj" : $(SOURCE) $(DEP_CPP_R_EDG) "$(INTDIR)"
+   $(CPP) /nologo /ML /GX /O2 /I "..\..\scitech\include" /I\
+ "..\..\dxsdk\sdk\inc" /D "WIN32" /D "NDEBUG" /D "_WINDOWS"\
+ /Fp"$(INTDIR)/qwcl.pch" /YX /Fo"$(INTDIR)/" /c $(SOURCE)
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+
+BuildCmds= \
+	$(CPP) /nologo /MLd /Gm /GX /Zi /Od /I "..\..\scitech\include" /I\
+ "..\..\dxsdk\sdk\inc" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR"$(INTDIR)/"\
+ /Fp"$(INTDIR)/qwcl.pch" /YX /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c $(SOURCE) \
+	
+
+"$(INTDIR)\r_edge.obj" : $(SOURCE) $(DEP_CPP_R_EDG) "$(INTDIR)"
+   $(BuildCmds)
+
+"$(INTDIR)\r_edge.sbr" : $(SOURCE) $(DEP_CPP_R_EDG) "$(INTDIR)"
+   $(BuildCmds)
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Release"
+
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\r_efrag.c
+DEP_CPP_R_EFR=\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\r_local.h"\
+	".\r_shared.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\zone.h"\
+	
+NODEP_CPP_R_EFR=\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+
+"$(INTDIR)\r_efrag.obj" : $(SOURCE) $(DEP_CPP_R_EFR) "$(INTDIR)"
+   $(CPP) /nologo /ML /GX /O2 /I "..\..\scitech\include" /I\
+ "..\..\dxsdk\sdk\inc" /D "WIN32" /D "NDEBUG" /D "_WINDOWS"\
+ /Fp"$(INTDIR)/qwcl.pch" /YX /Fo"$(INTDIR)/" /c $(SOURCE)
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+
+BuildCmds= \
+	$(CPP) /nologo /MLd /Gm /GX /Zi /Od /I "..\..\scitech\include" /I\
+ "..\..\dxsdk\sdk\inc" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR"$(INTDIR)/"\
+ /Fp"$(INTDIR)/qwcl.pch" /YX /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c $(SOURCE) \
+	
+
+"$(INTDIR)\r_efrag.obj" : $(SOURCE) $(DEP_CPP_R_EFR) "$(INTDIR)"
+   $(BuildCmds)
+
+"$(INTDIR)\r_efrag.sbr" : $(SOURCE) $(DEP_CPP_R_EFR) "$(INTDIR)"
+   $(BuildCmds)
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Release"
+
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\r_light.c
+DEP_CPP_R_LIG=\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\r_local.h"\
+	".\r_shared.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\zone.h"\
+	
+NODEP_CPP_R_LIG=\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+
+"$(INTDIR)\r_light.obj" : $(SOURCE) $(DEP_CPP_R_LIG) "$(INTDIR)"
+   $(CPP) /nologo /ML /GX /O2 /I "..\..\scitech\include" /I\
+ "..\..\dxsdk\sdk\inc" /D "WIN32" /D "NDEBUG" /D "_WINDOWS"\
+ /Fp"$(INTDIR)/qwcl.pch" /YX /Fo"$(INTDIR)/" /c $(SOURCE)
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+
+BuildCmds= \
+	$(CPP) /nologo /MLd /Gm /GX /Zi /Od /I "..\..\scitech\include" /I\
+ "..\..\dxsdk\sdk\inc" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR"$(INTDIR)/"\
+ /Fp"$(INTDIR)/qwcl.pch" /YX /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c $(SOURCE) \
+	
+
+"$(INTDIR)\r_light.obj" : $(SOURCE) $(DEP_CPP_R_LIG) "$(INTDIR)"
+   $(BuildCmds)
+
+"$(INTDIR)\r_light.sbr" : $(SOURCE) $(DEP_CPP_R_LIG) "$(INTDIR)"
+   $(BuildCmds)
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Release"
+
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\r_main.c
+DEP_CPP_R_MAI=\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\r_local.h"\
+	".\r_shared.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\zone.h"\
+	
+NODEP_CPP_R_MAI=\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+
+"$(INTDIR)\r_main.obj" : $(SOURCE) $(DEP_CPP_R_MAI) "$(INTDIR)"
+   $(CPP) /nologo /ML /GX /O2 /I "..\..\scitech\include" /I\
+ "..\..\dxsdk\sdk\inc" /D "WIN32" /D "NDEBUG" /D "_WINDOWS"\
+ /Fp"$(INTDIR)/qwcl.pch" /YX /Fo"$(INTDIR)/" /c $(SOURCE)
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+
+BuildCmds= \
+	$(CPP) /nologo /MLd /Gm /GX /Zi /Od /I "..\..\scitech\include" /I\
+ "..\..\dxsdk\sdk\inc" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR"$(INTDIR)/"\
+ /Fp"$(INTDIR)/qwcl.pch" /YX /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c $(SOURCE) \
+	
+
+"$(INTDIR)\r_main.obj" : $(SOURCE) $(DEP_CPP_R_MAI) "$(INTDIR)"
+   $(BuildCmds)
+
+"$(INTDIR)\r_main.sbr" : $(SOURCE) $(DEP_CPP_R_MAI) "$(INTDIR)"
+   $(BuildCmds)
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Release"
+
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\r_misc.c
+DEP_CPP_R_MIS=\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\r_local.h"\
+	".\r_shared.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\zone.h"\
+	
+NODEP_CPP_R_MIS=\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+
+"$(INTDIR)\r_misc.obj" : $(SOURCE) $(DEP_CPP_R_MIS) "$(INTDIR)"
+   $(CPP) /nologo /ML /GX /O2 /I "..\..\scitech\include" /I\
+ "..\..\dxsdk\sdk\inc" /D "WIN32" /D "NDEBUG" /D "_WINDOWS"\
+ /Fp"$(INTDIR)/qwcl.pch" /YX /Fo"$(INTDIR)/" /c $(SOURCE)
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+
+BuildCmds= \
+	$(CPP) /nologo /MLd /Gm /GX /Zi /Od /I "..\..\scitech\include" /I\
+ "..\..\dxsdk\sdk\inc" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR"$(INTDIR)/"\
+ /Fp"$(INTDIR)/qwcl.pch" /YX /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c $(SOURCE) \
+	
+
+"$(INTDIR)\r_misc.obj" : $(SOURCE) $(DEP_CPP_R_MIS) "$(INTDIR)"
+   $(BuildCmds)
+
+"$(INTDIR)\r_misc.sbr" : $(SOURCE) $(DEP_CPP_R_MIS) "$(INTDIR)"
+   $(BuildCmds)
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Release"
+
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\r_part.c
+DEP_CPP_R_PAR=\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\r_local.h"\
+	".\r_shared.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\zone.h"\
+	
+NODEP_CPP_R_PAR=\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+
+"$(INTDIR)\r_part.obj" : $(SOURCE) $(DEP_CPP_R_PAR) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+
+"$(INTDIR)\r_part.obj" : $(SOURCE) $(DEP_CPP_R_PAR) "$(INTDIR)"
+
+"$(INTDIR)\r_part.sbr" : $(SOURCE) $(DEP_CPP_R_PAR) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Debug"
+
+# PROP Exclude_From_Build 0
+
+"$(INTDIR)\r_part.obj" : $(SOURCE) $(DEP_CPP_R_PAR) "$(INTDIR)"
+
+"$(INTDIR)\r_part.sbr" : $(SOURCE) $(DEP_CPP_R_PAR) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Release"
+
+# PROP Exclude_From_Build 0
+
+"$(INTDIR)\r_part.obj" : $(SOURCE) $(DEP_CPP_R_PAR) "$(INTDIR)"
+
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\r_sky.c
+DEP_CPP_R_SKY=\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\d_local.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\r_local.h"\
+	".\r_shared.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\zone.h"\
+	
+NODEP_CPP_R_SKY=\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+
+"$(INTDIR)\r_sky.obj" : $(SOURCE) $(DEP_CPP_R_SKY) "$(INTDIR)"
+   $(CPP) /nologo /ML /GX /O2 /I "..\..\scitech\include" /I\
+ "..\..\dxsdk\sdk\inc" /D "WIN32" /D "NDEBUG" /D "_WINDOWS"\
+ /Fp"$(INTDIR)/qwcl.pch" /YX /Fo"$(INTDIR)/" /c $(SOURCE)
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+
+BuildCmds= \
+	$(CPP) /nologo /MLd /Gm /GX /Zi /Od /I "..\..\scitech\include" /I\
+ "..\..\dxsdk\sdk\inc" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR"$(INTDIR)/"\
+ /Fp"$(INTDIR)/qwcl.pch" /YX /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c $(SOURCE) \
+	
+
+"$(INTDIR)\r_sky.obj" : $(SOURCE) $(DEP_CPP_R_SKY) "$(INTDIR)"
+   $(BuildCmds)
+
+"$(INTDIR)\r_sky.sbr" : $(SOURCE) $(DEP_CPP_R_SKY) "$(INTDIR)"
+   $(BuildCmds)
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Release"
+
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\r_sprite.c
+DEP_CPP_R_SPR=\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\r_local.h"\
+	".\r_shared.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\zone.h"\
+	
+NODEP_CPP_R_SPR=\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+
+"$(INTDIR)\r_sprite.obj" : $(SOURCE) $(DEP_CPP_R_SPR) "$(INTDIR)"
+   $(CPP) /nologo /ML /GX /O2 /I "..\..\scitech\include" /I\
+ "..\..\dxsdk\sdk\inc" /D "WIN32" /D "NDEBUG" /D "_WINDOWS"\
+ /Fp"$(INTDIR)/qwcl.pch" /YX /Fo"$(INTDIR)/" /c $(SOURCE)
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+
+BuildCmds= \
+	$(CPP) /nologo /MLd /Gm /GX /Zi /Od /I "..\..\scitech\include" /I\
+ "..\..\dxsdk\sdk\inc" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR"$(INTDIR)/"\
+ /Fp"$(INTDIR)/qwcl.pch" /YX /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c $(SOURCE) \
+	
+
+"$(INTDIR)\r_sprite.obj" : $(SOURCE) $(DEP_CPP_R_SPR) "$(INTDIR)"
+   $(BuildCmds)
+
+"$(INTDIR)\r_sprite.sbr" : $(SOURCE) $(DEP_CPP_R_SPR) "$(INTDIR)"
+   $(BuildCmds)
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Release"
+
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\r_surf.c
+DEP_CPP_R_SUR=\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\r_local.h"\
+	".\r_shared.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\zone.h"\
+	
+NODEP_CPP_R_SUR=\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+
+"$(INTDIR)\r_surf.obj" : $(SOURCE) $(DEP_CPP_R_SUR) "$(INTDIR)"
+   $(CPP) /nologo /ML /GX /O2 /I "..\..\scitech\include" /I\
+ "..\..\dxsdk\sdk\inc" /D "WIN32" /D "NDEBUG" /D "_WINDOWS"\
+ /Fp"$(INTDIR)/qwcl.pch" /YX /Fo"$(INTDIR)/" /c $(SOURCE)
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+
+BuildCmds= \
+	$(CPP) /nologo /MLd /Gm /GX /Zi /Od /I "..\..\scitech\include" /I\
+ "..\..\dxsdk\sdk\inc" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR"$(INTDIR)/"\
+ /Fp"$(INTDIR)/qwcl.pch" /YX /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c $(SOURCE) \
+	
+
+"$(INTDIR)\r_surf.obj" : $(SOURCE) $(DEP_CPP_R_SUR) "$(INTDIR)"
+   $(BuildCmds)
+
+"$(INTDIR)\r_surf.sbr" : $(SOURCE) $(DEP_CPP_R_SUR) "$(INTDIR)"
+   $(BuildCmds)
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Release"
+
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\r_vars.c
+DEP_CPP_R_VAR=\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\zone.h"\
+	
+NODEP_CPP_R_VAR=\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+
+"$(INTDIR)\r_vars.obj" : $(SOURCE) $(DEP_CPP_R_VAR) "$(INTDIR)"
+   $(CPP) /nologo /ML /GX /O2 /I "..\..\scitech\include" /I\
+ "..\..\dxsdk\sdk\inc" /D "WIN32" /D "NDEBUG" /D "_WINDOWS"\
+ /Fp"$(INTDIR)/qwcl.pch" /YX /Fo"$(INTDIR)/" /c $(SOURCE)
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+
+BuildCmds= \
+	$(CPP) /nologo /MLd /Gm /GX /Zi /Od /I "..\..\scitech\include" /I\
+ "..\..\dxsdk\sdk\inc" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR"$(INTDIR)/"\
+ /Fp"$(INTDIR)/qwcl.pch" /YX /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c $(SOURCE) \
+	
+
+"$(INTDIR)\r_vars.obj" : $(SOURCE) $(DEP_CPP_R_VAR) "$(INTDIR)"
+   $(BuildCmds)
+
+"$(INTDIR)\r_vars.sbr" : $(SOURCE) $(DEP_CPP_R_VAR) "$(INTDIR)"
+   $(BuildCmds)
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Release"
+
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\sbar.c
+DEP_CPP_SBAR_=\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\zone.h"\
+	
+NODEP_CPP_SBAR_=\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+
+"$(INTDIR)\sbar.obj" : $(SOURCE) $(DEP_CPP_SBAR_) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+
+"$(INTDIR)\sbar.obj" : $(SOURCE) $(DEP_CPP_SBAR_) "$(INTDIR)"
+
+"$(INTDIR)\sbar.sbr" : $(SOURCE) $(DEP_CPP_SBAR_) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Debug"
+
+
+"$(INTDIR)\sbar.obj" : $(SOURCE) $(DEP_CPP_SBAR_) "$(INTDIR)"
+
+"$(INTDIR)\sbar.sbr" : $(SOURCE) $(DEP_CPP_SBAR_) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Release"
+
+
+"$(INTDIR)\sbar.obj" : $(SOURCE) $(DEP_CPP_SBAR_) "$(INTDIR)"
+
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\screen.c
+DEP_CPP_SCREE=\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\r_local.h"\
+	".\r_shared.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\zone.h"\
+	
+NODEP_CPP_SCREE=\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+
+"$(INTDIR)\screen.obj" : $(SOURCE) $(DEP_CPP_SCREE) "$(INTDIR)"
+   $(CPP) /nologo /ML /GX /O2 /I "..\..\scitech\include" /I\
+ "..\..\dxsdk\sdk\inc" /D "WIN32" /D "NDEBUG" /D "_WINDOWS"\
+ /Fp"$(INTDIR)/qwcl.pch" /YX /Fo"$(INTDIR)/" /c $(SOURCE)
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+
+BuildCmds= \
+	$(CPP) /nologo /MLd /Gm /GX /Zi /Od /I "..\..\scitech\include" /I\
+ "..\..\dxsdk\sdk\inc" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR"$(INTDIR)/"\
+ /Fp"$(INTDIR)/qwcl.pch" /YX /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c $(SOURCE) \
+	
+
+"$(INTDIR)\screen.obj" : $(SOURCE) $(DEP_CPP_SCREE) "$(INTDIR)"
+   $(BuildCmds)
+
+"$(INTDIR)\screen.sbr" : $(SOURCE) $(DEP_CPP_SCREE) "$(INTDIR)"
+   $(BuildCmds)
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Release"
+
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\skin.c
+DEP_CPP_SKIN_=\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\zone.h"\
+	
+NODEP_CPP_SKIN_=\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+
+"$(INTDIR)\skin.obj" : $(SOURCE) $(DEP_CPP_SKIN_) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+
+"$(INTDIR)\skin.obj" : $(SOURCE) $(DEP_CPP_SKIN_) "$(INTDIR)"
+
+"$(INTDIR)\skin.sbr" : $(SOURCE) $(DEP_CPP_SKIN_) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Debug"
+
+
+"$(INTDIR)\skin.obj" : $(SOURCE) $(DEP_CPP_SKIN_) "$(INTDIR)"
+
+"$(INTDIR)\skin.sbr" : $(SOURCE) $(DEP_CPP_SKIN_) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Release"
+
+
+"$(INTDIR)\skin.obj" : $(SOURCE) $(DEP_CPP_SKIN_) "$(INTDIR)"
+
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\snd_dma.c
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+DEP_CPP_SND_D=\
+	"..\..\scitech\include\debug.h"\
+	"..\..\scitech\include\mgldos.h"\
+	"..\..\scitech\include\mglwin.h"\
+	"..\..\scitech\include\mgraph.h"\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\winquake.h"\
+	".\zone.h"\
+	
+NODEP_CPP_SND_D=\
+	"..\..\scitech\include\mglrect.hpp"\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+"$(INTDIR)\snd_dma.obj" : $(SOURCE) $(DEP_CPP_SND_D) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+DEP_CPP_SND_D=\
+	"..\..\scitech\include\debug.h"\
+	"..\..\scitech\include\mgldos.h"\
+	"..\..\scitech\include\mglwin.h"\
+	"..\..\scitech\include\mgraph.h"\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\winquake.h"\
+	".\zone.h"\
+	
+NODEP_CPP_SND_D=\
+	"..\..\scitech\include\mglrect.hpp"\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+"$(INTDIR)\snd_dma.obj" : $(SOURCE) $(DEP_CPP_SND_D) "$(INTDIR)"
+
+"$(INTDIR)\snd_dma.sbr" : $(SOURCE) $(DEP_CPP_SND_D) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Debug"
+
+DEP_CPP_SND_D=\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\winquake.h"\
+	".\zone.h"\
+	
+NODEP_CPP_SND_D=\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+"$(INTDIR)\snd_dma.obj" : $(SOURCE) $(DEP_CPP_SND_D) "$(INTDIR)"
+
+"$(INTDIR)\snd_dma.sbr" : $(SOURCE) $(DEP_CPP_SND_D) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Release"
+
+DEP_CPP_SND_D=\
+	"..\..\scitech\include\debug.h"\
+	"..\..\scitech\include\mgldos.h"\
+	"..\..\scitech\include\mglwin.h"\
+	"..\..\scitech\include\mgraph.h"\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\winquake.h"\
+	".\zone.h"\
+	
+NODEP_CPP_SND_D=\
+	"..\..\scitech\include\mglrect.hpp"\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+"$(INTDIR)\snd_dma.obj" : $(SOURCE) $(DEP_CPP_SND_D) "$(INTDIR)"
+
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\snd_mem.c
+DEP_CPP_SND_M=\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\zone.h"\
+	
+NODEP_CPP_SND_M=\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+
+"$(INTDIR)\snd_mem.obj" : $(SOURCE) $(DEP_CPP_SND_M) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+
+"$(INTDIR)\snd_mem.obj" : $(SOURCE) $(DEP_CPP_SND_M) "$(INTDIR)"
+
+"$(INTDIR)\snd_mem.sbr" : $(SOURCE) $(DEP_CPP_SND_M) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Debug"
+
+
+"$(INTDIR)\snd_mem.obj" : $(SOURCE) $(DEP_CPP_SND_M) "$(INTDIR)"
+
+"$(INTDIR)\snd_mem.sbr" : $(SOURCE) $(DEP_CPP_SND_M) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Release"
+
+
+"$(INTDIR)\snd_mem.obj" : $(SOURCE) $(DEP_CPP_SND_M) "$(INTDIR)"
+
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\snd_mix.c
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+DEP_CPP_SND_MI=\
+	"..\..\scitech\include\debug.h"\
+	"..\..\scitech\include\mgldos.h"\
+	"..\..\scitech\include\mglwin.h"\
+	"..\..\scitech\include\mgraph.h"\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\winquake.h"\
+	".\zone.h"\
+	
+NODEP_CPP_SND_MI=\
+	"..\..\scitech\include\mglrect.hpp"\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+"$(INTDIR)\snd_mix.obj" : $(SOURCE) $(DEP_CPP_SND_MI) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+DEP_CPP_SND_MI=\
+	"..\..\scitech\include\debug.h"\
+	"..\..\scitech\include\mgldos.h"\
+	"..\..\scitech\include\mglwin.h"\
+	"..\..\scitech\include\mgraph.h"\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\winquake.h"\
+	".\zone.h"\
+	
+NODEP_CPP_SND_MI=\
+	"..\..\scitech\include\mglrect.hpp"\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+"$(INTDIR)\snd_mix.obj" : $(SOURCE) $(DEP_CPP_SND_MI) "$(INTDIR)"
+
+"$(INTDIR)\snd_mix.sbr" : $(SOURCE) $(DEP_CPP_SND_MI) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Debug"
+
+DEP_CPP_SND_MI=\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\winquake.h"\
+	".\zone.h"\
+	
+NODEP_CPP_SND_MI=\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+"$(INTDIR)\snd_mix.obj" : $(SOURCE) $(DEP_CPP_SND_MI) "$(INTDIR)"
+
+"$(INTDIR)\snd_mix.sbr" : $(SOURCE) $(DEP_CPP_SND_MI) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Release"
+
+DEP_CPP_SND_MI=\
+	"..\..\scitech\include\debug.h"\
+	"..\..\scitech\include\mgldos.h"\
+	"..\..\scitech\include\mglwin.h"\
+	"..\..\scitech\include\mgraph.h"\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\winquake.h"\
+	".\zone.h"\
+	
+NODEP_CPP_SND_MI=\
+	"..\..\scitech\include\mglrect.hpp"\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+"$(INTDIR)\snd_mix.obj" : $(SOURCE) $(DEP_CPP_SND_MI) "$(INTDIR)"
+
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\snd_win.c
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+DEP_CPP_SND_W=\
+	"..\..\scitech\include\debug.h"\
+	"..\..\scitech\include\mgldos.h"\
+	"..\..\scitech\include\mglwin.h"\
+	"..\..\scitech\include\mgraph.h"\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\winquake.h"\
+	".\zone.h"\
+	
+NODEP_CPP_SND_W=\
+	"..\..\scitech\include\mglrect.hpp"\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+"$(INTDIR)\snd_win.obj" : $(SOURCE) $(DEP_CPP_SND_W) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+DEP_CPP_SND_W=\
+	"..\..\scitech\include\debug.h"\
+	"..\..\scitech\include\mgldos.h"\
+	"..\..\scitech\include\mglwin.h"\
+	"..\..\scitech\include\mgraph.h"\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\winquake.h"\
+	".\zone.h"\
+	
+NODEP_CPP_SND_W=\
+	"..\..\scitech\include\mglrect.hpp"\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+"$(INTDIR)\snd_win.obj" : $(SOURCE) $(DEP_CPP_SND_W) "$(INTDIR)"
+
+"$(INTDIR)\snd_win.sbr" : $(SOURCE) $(DEP_CPP_SND_W) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Debug"
+
+DEP_CPP_SND_W=\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\winquake.h"\
+	".\zone.h"\
+	
+NODEP_CPP_SND_W=\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+"$(INTDIR)\snd_win.obj" : $(SOURCE) $(DEP_CPP_SND_W) "$(INTDIR)"
+
+"$(INTDIR)\snd_win.sbr" : $(SOURCE) $(DEP_CPP_SND_W) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Release"
+
+DEP_CPP_SND_W=\
+	"..\..\scitech\include\debug.h"\
+	"..\..\scitech\include\mgldos.h"\
+	"..\..\scitech\include\mglwin.h"\
+	"..\..\scitech\include\mgraph.h"\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\winquake.h"\
+	".\zone.h"\
+	
+NODEP_CPP_SND_W=\
+	"..\..\scitech\include\mglrect.hpp"\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+"$(INTDIR)\snd_win.obj" : $(SOURCE) $(DEP_CPP_SND_W) "$(INTDIR)"
+
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\sys_win.c
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+DEP_CPP_SYS_W=\
+	"..\..\scitech\include\debug.h"\
+	"..\..\scitech\include\mgldos.h"\
+	"..\..\scitech\include\mglwin.h"\
+	"..\..\scitech\include\mgraph.h"\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\cvar.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\mathlib.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\wad.h"\
+	".\winquake.h"\
+	".\zone.h"\
+	
+NODEP_CPP_SYS_W=\
+	"..\..\scitech\include\mglrect.hpp"\
+	
+
+"$(INTDIR)\sys_win.obj" : $(SOURCE) $(DEP_CPP_SYS_W) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+DEP_CPP_SYS_W=\
+	"..\..\scitech\include\debug.h"\
+	"..\..\scitech\include\mgldos.h"\
+	"..\..\scitech\include\mglwin.h"\
+	"..\..\scitech\include\mgraph.h"\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\cvar.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\mathlib.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\wad.h"\
+	".\winquake.h"\
+	".\zone.h"\
+	
+NODEP_CPP_SYS_W=\
+	"..\..\scitech\include\mglrect.hpp"\
+	
+
+"$(INTDIR)\sys_win.obj" : $(SOURCE) $(DEP_CPP_SYS_W) "$(INTDIR)"
+
+"$(INTDIR)\sys_win.sbr" : $(SOURCE) $(DEP_CPP_SYS_W) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Debug"
+
+DEP_CPP_SYS_W=\
+	"..\..\scitech\include\mgraph.h"\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\cvar.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\mathlib.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\wad.h"\
+	".\winquake.h"\
+	".\zone.h"\
+	
+
+"$(INTDIR)\sys_win.obj" : $(SOURCE) $(DEP_CPP_SYS_W) "$(INTDIR)"
+
+"$(INTDIR)\sys_win.sbr" : $(SOURCE) $(DEP_CPP_SYS_W) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Release"
+
+DEP_CPP_SYS_W=\
+	"..\..\scitech\include\debug.h"\
+	"..\..\scitech\include\mgldos.h"\
+	"..\..\scitech\include\mglwin.h"\
+	"..\..\scitech\include\mgraph.h"\
+	".\quakedef.h"\
+	".\winquake.h"\
+	
+NODEP_CPP_SYS_W=\
+	"..\..\scitech\include\mglrect.hpp"\
+	
+
+"$(INTDIR)\sys_win.obj" : $(SOURCE) $(DEP_CPP_SYS_W) "$(INTDIR)"
+
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\vid_win.c
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+DEP_CPP_VID_W=\
+	"..\..\scitech\include\debug.h"\
+	"..\..\scitech\include\mgldos.h"\
+	"..\..\scitech\include\mglwin.h"\
+	"..\..\scitech\include\mgraph.h"\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\cvar.h"\
+	".\d_local.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\mathlib.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\r_shared.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\wad.h"\
+	".\winquake.h"\
+	".\zone.h"\
+	
+NODEP_CPP_VID_W=\
+	"..\..\scitech\include\mglrect.hpp"\
+	
+
+"$(INTDIR)\vid_win.obj" : $(SOURCE) $(DEP_CPP_VID_W) "$(INTDIR)"
+   $(CPP) /nologo /ML /GX /O2 /I "..\..\scitech\include" /I\
+ "..\..\dxsdk\sdk\inc" /D "WIN32" /D "NDEBUG" /D "_WINDOWS"\
+ /Fp"$(INTDIR)/qwcl.pch" /YX /Fo"$(INTDIR)/" /c $(SOURCE)
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+DEP_CPP_VID_W=\
+	"..\..\scitech\include\debug.h"\
+	"..\..\scitech\include\mgldos.h"\
+	"..\..\scitech\include\mglwin.h"\
+	"..\..\scitech\include\mgraph.h"\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\cvar.h"\
+	".\d_local.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\mathlib.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\r_shared.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\wad.h"\
+	".\winquake.h"\
+	".\zone.h"\
+	
+NODEP_CPP_VID_W=\
+	"..\..\scitech\include\mglrect.hpp"\
+	
+
+BuildCmds= \
+	$(CPP) /nologo /MLd /Gm /GX /Zi /Od /I "..\..\scitech\include" /I\
+ "..\..\dxsdk\sdk\inc" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR"$(INTDIR)/"\
+ /Fp"$(INTDIR)/qwcl.pch" /YX /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c $(SOURCE) \
+	
+
+"$(INTDIR)\vid_win.obj" : $(SOURCE) $(DEP_CPP_VID_W) "$(INTDIR)"
+   $(BuildCmds)
+
+"$(INTDIR)\vid_win.sbr" : $(SOURCE) $(DEP_CPP_VID_W) "$(INTDIR)"
+   $(BuildCmds)
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Debug"
+
+# PROP Exclude_From_Build 1
+DEP_CPP_VID_W=\
+	"..\..\scitech\include\mgraph.h"\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\cvar.h"\
+	".\d_local.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\mathlib.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\r_shared.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\wad.h"\
+	".\winquake.h"\
+	".\zone.h"\
+	
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Release"
+
+# PROP Exclude_From_Build 1
+DEP_CPP_VID_W=\
+	"..\..\scitech\include\debug.h"\
+	"..\..\scitech\include\mgldos.h"\
+	"..\..\scitech\include\mglwin.h"\
+	"..\..\scitech\include\mgraph.h"\
+	".\d_local.h"\
+	".\quakedef.h"\
+	".\r_shared.h"\
+	".\winquake.h"\
+	
+NODEP_CPP_VID_W=\
+	"..\..\scitech\include\mglrect.hpp"\
+	
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\view.c
+DEP_CPP_VIEW_=\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\r_local.h"\
+	".\r_shared.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\zone.h"\
+	
+NODEP_CPP_VIEW_=\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+
+"$(INTDIR)\view.obj" : $(SOURCE) $(DEP_CPP_VIEW_) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+
+"$(INTDIR)\view.obj" : $(SOURCE) $(DEP_CPP_VIEW_) "$(INTDIR)"
+
+"$(INTDIR)\view.sbr" : $(SOURCE) $(DEP_CPP_VIEW_) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Debug"
+
+
+"$(INTDIR)\view.obj" : $(SOURCE) $(DEP_CPP_VIEW_) "$(INTDIR)"
+
+"$(INTDIR)\view.sbr" : $(SOURCE) $(DEP_CPP_VIEW_) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Release"
+
+
+"$(INTDIR)\view.obj" : $(SOURCE) $(DEP_CPP_VIEW_) "$(INTDIR)"
+
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\wad.c
+DEP_CPP_WAD_C=\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\zone.h"\
+	
+NODEP_CPP_WAD_C=\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+
+"$(INTDIR)\wad.obj" : $(SOURCE) $(DEP_CPP_WAD_C) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+
+"$(INTDIR)\wad.obj" : $(SOURCE) $(DEP_CPP_WAD_C) "$(INTDIR)"
+
+"$(INTDIR)\wad.sbr" : $(SOURCE) $(DEP_CPP_WAD_C) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Debug"
+
+
+"$(INTDIR)\wad.obj" : $(SOURCE) $(DEP_CPP_WAD_C) "$(INTDIR)"
+
+"$(INTDIR)\wad.sbr" : $(SOURCE) $(DEP_CPP_WAD_C) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Release"
+
+
+"$(INTDIR)\wad.obj" : $(SOURCE) $(DEP_CPP_WAD_C) "$(INTDIR)"
+
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\zone.c
+DEP_CPP_ZONE_=\
+	".\bothdefs.h"\
+	".\bspfile.h"\
+	".\cdaudio.h"\
+	".\client.h"\
+	".\cmd.h"\
+	".\common.h"\
+	".\console.h"\
+	".\crc.h"\
+	".\cvar.h"\
+	".\d_iface.h"\
+	".\draw.h"\
+	".\gl_model.h"\
+	".\glquake.h"\
+	".\input.h"\
+	".\keys.h"\
+	".\mathlib.h"\
+	".\menu.h"\
+	".\model.h"\
+	".\modelgen.h"\
+	".\net.h"\
+	".\pmove.h"\
+	".\protocol.h"\
+	".\quakedef.h"\
+	".\render.h"\
+	".\sbar.h"\
+	".\screen.h"\
+	".\sound.h"\
+	".\spritegn.h"\
+	".\sys.h"\
+	".\vid.h"\
+	".\view.h"\
+	".\wad.h"\
+	".\zone.h"\
+	
+NODEP_CPP_ZONE_=\
+	".\cmdlib.h"\
+	".\dictlib.h"\
+	".\lbmlib.h"\
+	".\scriplib.h"\
+	".\trilib.h"\
+	
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+
+"$(INTDIR)\zone.obj" : $(SOURCE) $(DEP_CPP_ZONE_) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+
+"$(INTDIR)\zone.obj" : $(SOURCE) $(DEP_CPP_ZONE_) "$(INTDIR)"
+
+"$(INTDIR)\zone.sbr" : $(SOURCE) $(DEP_CPP_ZONE_) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Debug"
+
+
+"$(INTDIR)\zone.obj" : $(SOURCE) $(DEP_CPP_ZONE_) "$(INTDIR)"
+
+"$(INTDIR)\zone.sbr" : $(SOURCE) $(DEP_CPP_ZONE_) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Release"
+
+
+"$(INTDIR)\zone.obj" : $(SOURCE) $(DEP_CPP_ZONE_) "$(INTDIR)"
+
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\d_draw.s
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+# Begin Custom Build - GAS Assembly
+OutDir=.\release
+InputPath=.\d_draw.s
+InputName=d_draw
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+   cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath)
+   gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp\
+   >$(OUTDIR)\$(InputName).asm
+   ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi\
+   $(OUTDIR)\$(InputName).asm
+   del $(OUTDIR)\$(InputName).spp
+
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+# Begin Custom Build - GAS Assembly
+OutDir=.\debug
+InputPath=.\d_draw.s
+InputName=d_draw
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+   cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath)
+   gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp\
+   >$(OUTDIR)\$(InputName).asm
+   ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi\
+   $(OUTDIR)\$(InputName).asm
+   del $(OUTDIR)\$(InputName).spp
+
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Release"
+
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\d_draw16.s
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+# Begin Custom Build - GAS Assembly
+OutDir=.\release
+InputPath=.\d_draw16.s
+InputName=d_draw16
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+   cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath)
+   gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp\
+   >$(OUTDIR)\$(InputName).asm
+   ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi\
+   $(OUTDIR)\$(InputName).asm
+   del $(OUTDIR)\$(InputName).spp
+
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+# Begin Custom Build - GAS Assembly
+OutDir=.\debug
+InputPath=.\d_draw16.s
+InputName=d_draw16
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+   cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath)
+   gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp\
+   >$(OUTDIR)\$(InputName).asm
+   ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi\
+   $(OUTDIR)\$(InputName).asm
+   del $(OUTDIR)\$(InputName).spp
+
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Release"
+
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\d_parta.s
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+# Begin Custom Build - GAS Assembly
+OutDir=.\release
+InputPath=.\d_parta.s
+InputName=d_parta
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+   cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath)
+   gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp\
+   >$(OUTDIR)\$(InputName).asm
+   ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi\
+   $(OUTDIR)\$(InputName).asm
+   del $(OUTDIR)\$(InputName).spp
+
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+# Begin Custom Build - GAS Assembly
+OutDir=.\debug
+InputPath=.\d_parta.s
+InputName=d_parta
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+   cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath)
+   gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp\
+   >$(OUTDIR)\$(InputName).asm
+   ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi\
+   $(OUTDIR)\$(InputName).asm
+   del $(OUTDIR)\$(InputName).spp
+
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Release"
+
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\d_polysa.s
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+# Begin Custom Build - GAS Assembly
+OutDir=.\release
+InputPath=.\d_polysa.s
+InputName=d_polysa
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+   cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath)
+   gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp\
+   >$(OUTDIR)\$(InputName).asm
+   ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi\
+   $(OUTDIR)\$(InputName).asm
+   del $(OUTDIR)\$(InputName).spp
+
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+# Begin Custom Build - GAS Assembly
+OutDir=.\debug
+InputPath=.\d_polysa.s
+InputName=d_polysa
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+   cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath)
+   gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp\
+   >$(OUTDIR)\$(InputName).asm
+   ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi\
+   $(OUTDIR)\$(InputName).asm
+   del $(OUTDIR)\$(InputName).spp
+
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Release"
+
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\d_scana.s
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+# Begin Custom Build - GAS Assembly
+OutDir=.\release
+InputPath=.\d_scana.s
+InputName=d_scana
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+   cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath)
+   gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp\
+   >$(OUTDIR)\$(InputName).asm
+   ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi\
+   $(OUTDIR)\$(InputName).asm
+   del $(OUTDIR)\$(InputName).spp
+
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+# Begin Custom Build - GAS Assembly
+OutDir=.\debug
+InputPath=.\d_scana.s
+InputName=d_scana
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+   cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath)
+   gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp\
+   >$(OUTDIR)\$(InputName).asm
+   ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi\
+   $(OUTDIR)\$(InputName).asm
+   del $(OUTDIR)\$(InputName).spp
+
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Release"
+
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\d_spr8.s
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+# Begin Custom Build - GAS Assembly
+OutDir=.\release
+InputPath=.\d_spr8.s
+InputName=d_spr8
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+   cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath)
+   gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp\
+   >$(OUTDIR)\$(InputName).asm
+   ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi\
+   $(OUTDIR)\$(InputName).asm
+   del $(OUTDIR)\$(InputName).spp
+
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+# Begin Custom Build - GAS Assembly
+OutDir=.\debug
+InputPath=.\d_spr8.s
+InputName=d_spr8
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+   cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath)
+   gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp\
+   >$(OUTDIR)\$(InputName).asm
+   ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi\
+   $(OUTDIR)\$(InputName).asm
+   del $(OUTDIR)\$(InputName).spp
+
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Release"
+
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\d_varsa.s
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+# Begin Custom Build - GAS Assembly
+OutDir=.\release
+InputPath=.\d_varsa.s
+InputName=d_varsa
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+   cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath)
+   gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp\
+   >$(OUTDIR)\$(InputName).asm
+   ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi\
+   $(OUTDIR)\$(InputName).asm
+   del $(OUTDIR)\$(InputName).spp
+
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+# Begin Custom Build - GAS Assembly
+OutDir=.\debug
+InputPath=.\d_varsa.s
+InputName=d_varsa
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+   cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath)
+   gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp\
+   >$(OUTDIR)\$(InputName).asm
+   ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi\
+   $(OUTDIR)\$(InputName).asm
+   del $(OUTDIR)\$(InputName).spp
+
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Release"
+
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\math.s
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+# Begin Custom Build - GAS Assembly
+OutDir=.\release
+InputPath=.\math.s
+InputName=math
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+   cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath)
+   gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp\
+   >$(OUTDIR)\$(InputName).asm
+   ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi\
+   $(OUTDIR)\$(InputName).asm
+   del $(OUTDIR)\$(InputName).spp
+
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+# Begin Custom Build - GAS Assembly
+OutDir=.\debug
+InputPath=.\math.s
+InputName=math
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+   cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath)
+   gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp\
+   >$(OUTDIR)\$(InputName).asm
+   ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi\
+   $(OUTDIR)\$(InputName).asm
+   del $(OUTDIR)\$(InputName).spp
+
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Debug"
+
+# Begin Custom Build - GAS Assembly
+OutDir=.\GLDebug
+InputPath=.\math.s
+InputName=math
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+   cl /EP /DGLQUAKE > $(OUTDIR)\$(InputName).spp $(InputPath)
+   gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp\
+   >$(OUTDIR)\$(InputName).asm
+   ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi\
+   $(OUTDIR)\$(InputName).asm
+   del $(OUTDIR)\$(InputName).spp
+
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Release"
+
+# Begin Custom Build - GAS Assembly
+OutDir=.\GLRelease
+InputPath=.\math.s
+InputName=math
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+   cl /EP /DGLQUAKE > $(OUTDIR)\$(InputName).spp $(InputPath)
+   gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp\
+   >$(OUTDIR)\$(InputName).asm
+   ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi\
+   $(OUTDIR)\$(InputName).asm
+   del $(OUTDIR)\$(InputName).spp
+
+# End Custom Build
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\r_aclipa.s
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+# Begin Custom Build - GAS Assembly
+OutDir=.\release
+InputPath=.\r_aclipa.s
+InputName=r_aclipa
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+   cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath)
+   gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp\
+   >$(OUTDIR)\$(InputName).asm
+   ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi\
+   $(OUTDIR)\$(InputName).asm
+   del $(OUTDIR)\$(InputName).spp
+
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+# Begin Custom Build - GAS Assembly
+OutDir=.\debug
+InputPath=.\r_aclipa.s
+InputName=r_aclipa
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+   cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath)
+   gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp\
+   >$(OUTDIR)\$(InputName).asm
+   ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi\
+   $(OUTDIR)\$(InputName).asm
+   del $(OUTDIR)\$(InputName).spp
+
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Release"
+
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\r_aliasa.s
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+# Begin Custom Build - GAS Assembly
+OutDir=.\release
+InputPath=.\r_aliasa.s
+InputName=r_aliasa
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+   cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath)
+   gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp\
+   >$(OUTDIR)\$(InputName).asm
+   ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi\
+   $(OUTDIR)\$(InputName).asm
+   del $(OUTDIR)\$(InputName).spp
+
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+# Begin Custom Build - GAS Assembly
+OutDir=.\debug
+InputPath=.\r_aliasa.s
+InputName=r_aliasa
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+   cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath)
+   gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp\
+   >$(OUTDIR)\$(InputName).asm
+   ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi\
+   $(OUTDIR)\$(InputName).asm
+   del $(OUTDIR)\$(InputName).spp
+
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Release"
+
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\r_drawa.s
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+# Begin Custom Build - GAS Assembly
+OutDir=.\release
+InputPath=.\r_drawa.s
+InputName=r_drawa
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+   cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath)
+   gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp\
+   >$(OUTDIR)\$(InputName).asm
+   ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi\
+   $(OUTDIR)\$(InputName).asm
+   del $(OUTDIR)\$(InputName).spp
+
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+# Begin Custom Build - GAS Assembly
+OutDir=.\debug
+InputPath=.\r_drawa.s
+InputName=r_drawa
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+   cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath)
+   gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp\
+   >$(OUTDIR)\$(InputName).asm
+   ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi\
+   $(OUTDIR)\$(InputName).asm
+   del $(OUTDIR)\$(InputName).spp
+
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Release"
+
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\r_edgea.s
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+# Begin Custom Build - GAS Assembly
+OutDir=.\release
+InputPath=.\r_edgea.s
+InputName=r_edgea
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+   cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath)
+   gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp\
+   >$(OUTDIR)\$(InputName).asm
+   ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi\
+   $(OUTDIR)\$(InputName).asm
+   del $(OUTDIR)\$(InputName).spp
+
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+# Begin Custom Build - GAS Assembly
+OutDir=.\debug
+InputPath=.\r_edgea.s
+InputName=r_edgea
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+   cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath)
+   gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp\
+   >$(OUTDIR)\$(InputName).asm
+   ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi\
+   $(OUTDIR)\$(InputName).asm
+   del $(OUTDIR)\$(InputName).spp
+
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Release"
+
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\r_varsa.s
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+# Begin Custom Build - GAS Assembly
+OutDir=.\release
+InputPath=.\r_varsa.s
+InputName=r_varsa
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+   cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath)
+   gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp\
+   >$(OUTDIR)\$(InputName).asm
+   ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi\
+   $(OUTDIR)\$(InputName).asm
+   del $(OUTDIR)\$(InputName).spp
+
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+# Begin Custom Build - GAS Assembly
+OutDir=.\debug
+InputPath=.\r_varsa.s
+InputName=r_varsa
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+   cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath)
+   gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp\
+   >$(OUTDIR)\$(InputName).asm
+   ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi\
+   $(OUTDIR)\$(InputName).asm
+   del $(OUTDIR)\$(InputName).spp
+
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Release"
+
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\snd_mixa.s
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+# Begin Custom Build - GAS Assembly
+OutDir=.\release
+InputPath=.\snd_mixa.s
+InputName=snd_mixa
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+   cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath)
+   gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp\
+   >$(OUTDIR)\$(InputName).asm
+   ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi\
+   $(OUTDIR)\$(InputName).asm
+   del $(OUTDIR)\$(InputName).spp
+
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+# Begin Custom Build - GAS Assembly
+OutDir=.\debug
+InputPath=.\snd_mixa.s
+InputName=snd_mixa
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+   cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath)
+   gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp\
+   >$(OUTDIR)\$(InputName).asm
+   ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi\
+   $(OUTDIR)\$(InputName).asm
+   del $(OUTDIR)\$(InputName).spp
+
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Debug"
+
+# Begin Custom Build - GAS Assembly
+OutDir=.\GLDebug
+InputPath=.\snd_mixa.s
+InputName=snd_mixa
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+   cl /EP /DGLQUAKE > $(OUTDIR)\$(InputName).spp $(InputPath)
+   gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp\
+   >$(OUTDIR)\$(InputName).asm
+   ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi\
+   $(OUTDIR)\$(InputName).asm
+   del $(OUTDIR)\$(InputName).spp
+
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Release"
+
+# Begin Custom Build - GAS Assembly
+OutDir=.\GLRelease
+InputPath=.\snd_mixa.s
+InputName=snd_mixa
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+   cl /EP /DGLQUAKE > $(OUTDIR)\$(InputName).spp $(InputPath)
+   gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp\
+   >$(OUTDIR)\$(InputName).asm
+   ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi\
+   $(OUTDIR)\$(InputName).asm
+   del $(OUTDIR)\$(InputName).spp
+
+# End Custom Build
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\surf16.s
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+# Begin Custom Build - GAS Assembly
+OutDir=.\release
+InputPath=.\surf16.s
+InputName=surf16
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+   cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath)
+   gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp\
+   >$(OUTDIR)\$(InputName).asm
+   ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi\
+   $(OUTDIR)\$(InputName).asm
+   del $(OUTDIR)\$(InputName).spp
+
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+# Begin Custom Build - GAS Assembly
+OutDir=.\debug
+InputPath=.\surf16.s
+InputName=surf16
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+   cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath)
+   gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp\
+   >$(OUTDIR)\$(InputName).asm
+   ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi\
+   $(OUTDIR)\$(InputName).asm
+   del $(OUTDIR)\$(InputName).spp
+
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Release"
+
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\surf8.s
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+# Begin Custom Build - GAS Assembly
+OutDir=.\release
+InputPath=.\surf8.s
+InputName=surf8
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+   cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath)
+   gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp\
+   >$(OUTDIR)\$(InputName).asm
+   ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi\
+   $(OUTDIR)\$(InputName).asm
+   del $(OUTDIR)\$(InputName).spp
+
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+# Begin Custom Build - GAS Assembly
+OutDir=.\debug
+InputPath=.\surf8.s
+InputName=surf8
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+   cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath)
+   gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp\
+   >$(OUTDIR)\$(InputName).asm
+   ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi\
+   $(OUTDIR)\$(InputName).asm
+   del $(OUTDIR)\$(InputName).spp
+
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Release"
+
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\sys_wina.s
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+# Begin Custom Build - GAS Assembly
+OutDir=.\release
+InputPath=.\sys_wina.s
+InputName=sys_wina
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+   cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath)
+   gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp\
+   >$(OUTDIR)\$(InputName).asm
+   ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi\
+   $(OUTDIR)\$(InputName).asm
+   del $(OUTDIR)\$(InputName).spp
+
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+# Begin Custom Build - GAS Assembly
+OutDir=.\debug
+InputPath=.\sys_wina.s
+InputName=sys_wina
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+   cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath)
+   gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp\
+   >$(OUTDIR)\$(InputName).asm
+   ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi\
+   $(OUTDIR)\$(InputName).asm
+   del $(OUTDIR)\$(InputName).spp
+
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Debug"
+
+# Begin Custom Build - GAS Assembly
+OutDir=.\GLDebug
+InputPath=.\sys_wina.s
+InputName=sys_wina
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+   cl /EP /DGLQUAKE > $(OUTDIR)\$(InputName).spp $(InputPath)
+   gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp\
+   >$(OUTDIR)\$(InputName).asm
+   ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi\
+   $(OUTDIR)\$(InputName).asm
+   del $(OUTDIR)\$(InputName).spp
+
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Release"
+
+# Begin Custom Build - GAS Assembly
+OutDir=.\GLRelease
+InputPath=.\sys_wina.s
+InputName=sys_wina
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+   cl /EP /DGLQUAKE > $(OUTDIR)\$(InputName).spp $(InputPath)
+   gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp\
+   >$(OUTDIR)\$(InputName).asm
+   ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi\
+   $(OUTDIR)\$(InputName).asm
+   del $(OUTDIR)\$(InputName).spp
+
+# End Custom Build
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\winquake.rc
+DEP_RSC_WINQU=\
+	".\quakeworld.bmp"\
+	".\qwcl2.ico"\
+	
+
+!IF  "$(CFG)" == "qwcl - Win32 Release"
+
+
+"$(INTDIR)\winquake.res" : $(SOURCE) $(DEP_RSC_WINQU) "$(INTDIR)"
+   $(RSC) $(RSC_PROJ) $(SOURCE)
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 Debug"
+
+
+"$(INTDIR)\winquake.res" : $(SOURCE) $(DEP_RSC_WINQU) "$(INTDIR)"
+   $(RSC) $(RSC_PROJ) $(SOURCE)
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Debug"
+
+
+"$(INTDIR)\winquake.res" : $(SOURCE) $(DEP_RSC_WINQU) "$(INTDIR)"
+   $(RSC) $(RSC_PROJ) $(SOURCE)
+
+
+!ELSEIF  "$(CFG)" == "qwcl - Win32 GL Release"
+
+
+"$(INTDIR)\winquake.res" : $(SOURCE) $(DEP_RSC_WINQU) "$(INTDIR)"
+   $(RSC) $(RSC_PROJ) $(SOURCE)
+
+
+!ENDIF 
+
+# End Source File
+# End Target
+# End Project
+################################################################################
binary files /dev/null b/QW/client/qwcl.mdp differ
--- /dev/null
+++ b/QW/client/qwcl.plg
@@ -1,0 +1,549 @@
+<html>
+<body>
+<pre>
+<h1>Build Log</h1>
+<h3>
+--------------------Configuration: qwcl - Win32 Release--------------------
+</h3>
+<h3>Command Lines</h3>
+Creating temporary file "C:\TEMP\RSP761.bat" with contents
+[
+@echo off
+cl /EP > .\Release\sys_wina.spp .\sys_wina.s
+..\gas2masm\debug\gas2masm.exe < .\Release\sys_wina.spp          >.\Release\sys_wina.asm
+ml /c /Cp /coff /Fo.\Release\sys_wina.obj /Zm /Zi                                                                                                                                                                                                                           .\Release\sys_wina.asm
+del .\Release\sys_wina.spp
+]
+Creating command line "C:\TEMP\RSP761.bat"
+Creating temporary file "C:\TEMP\RSP762.bat" with contents
+[
+@echo off
+cl /EP > .\Release\surf8.spp .\surf8.s
+..\gas2masm\debug\gas2masm.exe < .\Release\surf8.spp          >.\Release\surf8.asm
+ml /c /Cp /coff /Fo.\Release\surf8.obj /Zm /Zi                                                                                                                                                                                                                           .\Release\surf8.asm
+del .\Release\surf8.spp
+]
+Creating command line "C:\TEMP\RSP762.bat"
+Creating temporary file "C:\TEMP\RSP763.bat" with contents
+[
+@echo off
+cl /EP > .\Release\surf16.spp .\surf16.s
+..\gas2masm\debug\gas2masm.exe < .\Release\surf16.spp          >.\Release\surf16.asm
+ml /c /Cp /coff /Fo.\Release\surf16.obj /Zm /Zi                                                                                                                                                                                                                           .\Release\surf16.asm
+del .\Release\surf16.spp
+]
+Creating command line "C:\TEMP\RSP763.bat"
+Creating temporary file "C:\TEMP\RSP764.bat" with contents
+[
+@echo off
+cl /EP > .\Release\snd_mixa.spp .\snd_mixa.s
+..\gas2masm\debug\gas2masm.exe < .\Release\snd_mixa.spp          >.\Release\snd_mixa.asm
+ml /c /Cp /coff /Fo.\Release\snd_mixa.obj /Zm /Zi                                                                                                                                                                                                                           .\Release\snd_mixa.asm
+del .\Release\snd_mixa.spp
+]
+Creating command line "C:\TEMP\RSP764.bat"
+Creating temporary file "C:\TEMP\RSP765.bat" with contents
+[
+@echo off
+cl /EP > .\Release\r_varsa.spp .\r_varsa.s
+..\gas2masm\debug\gas2masm.exe < .\Release\r_varsa.spp          >.\Release\r_varsa.asm
+ml /c /Cp /coff /Fo.\Release\r_varsa.obj /Zm /Zi                                                                                                                                                                                                                           .\Release\r_varsa.asm
+del .\Release\r_varsa.spp
+]
+Creating command line "C:\TEMP\RSP765.bat"
+Creating temporary file "C:\TEMP\RSP766.bat" with contents
+[
+@echo off
+cl /EP > .\Release\r_edgea.spp .\r_edgea.s
+..\gas2masm\debug\gas2masm.exe < .\Release\r_edgea.spp          >.\Release\r_edgea.asm
+ml /c /Cp /coff /Fo.\Release\r_edgea.obj /Zm /Zi                                                                                                                                                                                                                           .\Release\r_edgea.asm
+del .\Release\r_edgea.spp
+]
+Creating command line "C:\TEMP\RSP766.bat"
+Creating temporary file "C:\TEMP\RSP767.bat" with contents
+[
+@echo off
+cl /EP > .\Release\r_drawa.spp .\r_drawa.s
+..\gas2masm\debug\gas2masm.exe < .\Release\r_drawa.spp          >.\Release\r_drawa.asm
+ml /c /Cp /coff /Fo.\Release\r_drawa.obj /Zm /Zi                                                                                                                                                                                                                           .\Release\r_drawa.asm
+del .\Release\r_drawa.spp
+]
+Creating command line "C:\TEMP\RSP767.bat"
+Creating temporary file "C:\TEMP\RSP768.bat" with contents
+[
+@echo off
+cl /EP > .\Release\r_aliasa.spp .\r_aliasa.s
+..\gas2masm\debug\gas2masm.exe < .\Release\r_aliasa.spp          >.\Release\r_aliasa.asm
+ml /c /Cp /coff /Fo.\Release\r_aliasa.obj /Zm /Zi                                                                                                                                                                                                                           .\Release\r_aliasa.asm
+del .\Release\r_aliasa.spp
+]
+Creating command line "C:\TEMP\RSP768.bat"
+Creating temporary file "C:\TEMP\RSP769.bat" with contents
+[
+@echo off
+cl /EP > .\Release\r_aclipa.spp .\r_aclipa.s
+..\gas2masm\debug\gas2masm.exe < .\Release\r_aclipa.spp          >.\Release\r_aclipa.asm
+ml /c /Cp /coff /Fo.\Release\r_aclipa.obj /Zm /Zi                                                                                                                                                                                                                           .\Release\r_aclipa.asm
+del .\Release\r_aclipa.spp
+]
+Creating command line "C:\TEMP\RSP769.bat"
+Creating temporary file "C:\TEMP\RSP76A.bat" with contents
+[
+@echo off
+cl /EP > .\Release\math.spp .\math.s
+..\gas2masm\debug\gas2masm.exe < .\Release\math.spp          >.\Release\math.asm
+ml /c /Cp /coff /Fo.\Release\math.obj /Zm /Zi                                                                                                                                                                                                                           .\Release\math.asm
+del .\Release\math.spp
+]
+Creating command line "C:\TEMP\RSP76A.bat"
+Creating temporary file "C:\TEMP\RSP76B.bat" with contents
+[
+@echo off
+cl /EP > .\Release\d_varsa.spp .\d_varsa.s
+..\gas2masm\debug\gas2masm.exe < .\Release\d_varsa.spp          >.\Release\d_varsa.asm
+ml /c /Cp /coff /Fo.\Release\d_varsa.obj /Zm /Zi                                                                                                                                                                                                                           .\Release\d_varsa.asm
+del .\Release\d_varsa.spp
+]
+Creating command line "C:\TEMP\RSP76B.bat"
+Creating temporary file "C:\TEMP\RSP76C.bat" with contents
+[
+@echo off
+cl /EP > .\Release\d_spr8.spp .\d_spr8.s
+..\gas2masm\debug\gas2masm.exe < .\Release\d_spr8.spp          >.\Release\d_spr8.asm
+ml /c /Cp /coff /Fo.\Release\d_spr8.obj /Zm /Zi                                                                                                                                                                                                                           .\Release\d_spr8.asm
+del .\Release\d_spr8.spp
+]
+Creating command line "C:\TEMP\RSP76C.bat"
+Creating temporary file "C:\TEMP\RSP76D.bat" with contents
+[
+@echo off
+cl /EP > .\Release\d_scana.spp .\d_scana.s
+..\gas2masm\debug\gas2masm.exe < .\Release\d_scana.spp          >.\Release\d_scana.asm
+ml /c /Cp /coff /Fo.\Release\d_scana.obj /Zm /Zi                                                                                                                                                                                                                           .\Release\d_scana.asm
+del .\Release\d_scana.spp
+]
+Creating command line "C:\TEMP\RSP76D.bat"
+Creating temporary file "C:\TEMP\RSP76E.bat" with contents
+[
+@echo off
+cl /EP > .\Release\d_polysa.spp .\d_polysa.s
+..\gas2masm\debug\gas2masm.exe < .\Release\d_polysa.spp          >.\Release\d_polysa.asm
+ml /c /Cp /coff /Fo.\Release\d_polysa.obj /Zm /Zi                                                                                                                                                                                                                           .\Release\d_polysa.asm
+del .\Release\d_polysa.spp
+]
+Creating command line "C:\TEMP\RSP76E.bat"
+Creating temporary file "C:\TEMP\RSP76F.bat" with contents
+[
+@echo off
+cl /EP > .\Release\d_parta.spp .\d_parta.s
+..\gas2masm\debug\gas2masm.exe < .\Release\d_parta.spp          >.\Release\d_parta.asm
+ml /c /Cp /coff /Fo.\Release\d_parta.obj /Zm /Zi                                                                                                                                                                                                                           .\Release\d_parta.asm
+del .\Release\d_parta.spp
+]
+Creating command line "C:\TEMP\RSP76F.bat"
+Creating temporary file "C:\TEMP\RSP770.bat" with contents
+[
+@echo off
+cl /EP > .\Release\d_draw16.spp .\d_draw16.s
+..\gas2masm\debug\gas2masm.exe < .\Release\d_draw16.spp          >.\Release\d_draw16.asm
+ml /c /Cp /coff /Fo.\Release\d_draw16.obj /Zm /Zi                                                                                                                                                                                                                           .\Release\d_draw16.asm
+del .\Release\d_draw16.spp
+]
+Creating command line "C:\TEMP\RSP770.bat"
+Creating temporary file "C:\TEMP\RSP771.bat" with contents
+[
+@echo off
+cl /EP > .\Release\d_draw.spp .\d_draw.s
+..\gas2masm\debug\gas2masm.exe < .\Release\d_draw.spp          >.\Release\d_draw.asm
+ml /c /Cp /coff /Fo.\Release\d_draw.obj /Zm /Zi                                                                                                                                                                                                                           .\Release\d_draw.asm
+del .\Release\d_draw.spp
+]
+Creating command line "C:\TEMP\RSP771.bat"
+Creating command line "rc.exe /l 0x409 /fo".\Release/winquake.res" /d "NDEBUG" "D:\Work\quake source\QW\client\winquake.rc"" 
+Performing Custom Build Step on .\sys_wina.s
+Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for 80x86
+Copyright (C) Microsoft Corp 1984-1998. All rights reserved.
+
+sys_wina.s
+Microsoft (R) Macro Assembler Version 6.11
+Copyright (C) Microsoft Corp 1981-1993.  All rights reserved.
+
+ Assembling: .\Release\sys_wina.asm
+Performing Custom Build Step on .\surf8.s
+Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for 80x86
+Copyright (C) Microsoft Corp 1984-1998. All rights reserved.
+
+surf8.s
+Microsoft (R) Macro Assembler Version 6.11
+Copyright (C) Microsoft Corp 1981-1993.  All rights reserved.
+
+ Assembling: .\Release\surf8.asm
+Performing Custom Build Step on .\surf16.s
+Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for 80x86
+Copyright (C) Microsoft Corp 1984-1998. All rights reserved.
+
+surf16.s
+Microsoft (R) Macro Assembler Version 6.11
+Copyright (C) Microsoft Corp 1981-1993.  All rights reserved.
+
+ Assembling: .\Release\surf16.asm
+Performing Custom Build Step on .\snd_mixa.s
+Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for 80x86
+Copyright (C) Microsoft Corp 1984-1998. All rights reserved.
+
+snd_mixa.s
+Microsoft (R) Macro Assembler Version 6.11
+Copyright (C) Microsoft Corp 1981-1993.  All rights reserved.
+
+ Assembling: .\Release\snd_mixa.asm
+Performing Custom Build Step on .\r_varsa.s
+Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for 80x86
+Copyright (C) Microsoft Corp 1984-1998. All rights reserved.
+
+r_varsa.s
+Microsoft (R) Macro Assembler Version 6.11
+Copyright (C) Microsoft Corp 1981-1993.  All rights reserved.
+
+ Assembling: .\Release\r_varsa.asm
+Performing Custom Build Step on .\r_edgea.s
+Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for 80x86
+Copyright (C) Microsoft Corp 1984-1998. All rights reserved.
+
+r_edgea.s
+Microsoft (R) Macro Assembler Version 6.11
+Copyright (C) Microsoft Corp 1981-1993.  All rights reserved.
+
+ Assembling: .\Release\r_edgea.asm
+Performing Custom Build Step on .\r_drawa.s
+Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for 80x86
+Copyright (C) Microsoft Corp 1984-1998. All rights reserved.
+
+r_drawa.s
+Microsoft (R) Macro Assembler Version 6.11
+Copyright (C) Microsoft Corp 1981-1993.  All rights reserved.
+
+ Assembling: .\Release\r_drawa.asm
+Performing Custom Build Step on .\r_aliasa.s
+Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for 80x86
+Copyright (C) Microsoft Corp 1984-1998. All rights reserved.
+
+r_aliasa.s
+Microsoft (R) Macro Assembler Version 6.11
+Copyright (C) Microsoft Corp 1981-1993.  All rights reserved.
+
+ Assembling: .\Release\r_aliasa.asm
+Performing Custom Build Step on .\r_aclipa.s
+Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for 80x86
+Copyright (C) Microsoft Corp 1984-1998. All rights reserved.
+
+r_aclipa.s
+Microsoft (R) Macro Assembler Version 6.11
+Copyright (C) Microsoft Corp 1981-1993.  All rights reserved.
+
+ Assembling: .\Release\r_aclipa.asm
+Performing Custom Build Step on .\math.s
+Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for 80x86
+Copyright (C) Microsoft Corp 1984-1998. All rights reserved.
+
+math.s
+Microsoft (R) Macro Assembler Version 6.11
+Copyright (C) Microsoft Corp 1981-1993.  All rights reserved.
+
+ Assembling: .\Release\math.asm
+Performing Custom Build Step on .\d_varsa.s
+Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for 80x86
+Copyright (C) Microsoft Corp 1984-1998. All rights reserved.
+
+d_varsa.s
+Microsoft (R) Macro Assembler Version 6.11
+Copyright (C) Microsoft Corp 1981-1993.  All rights reserved.
+
+ Assembling: .\Release\d_varsa.asm
+Performing Custom Build Step on .\d_spr8.s
+Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for 80x86
+Copyright (C) Microsoft Corp 1984-1998. All rights reserved.
+
+d_spr8.s
+Microsoft (R) Macro Assembler Version 6.11
+Copyright (C) Microsoft Corp 1981-1993.  All rights reserved.
+
+ Assembling: .\Release\d_spr8.asm
+Performing Custom Build Step on .\d_scana.s
+Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for 80x86
+Copyright (C) Microsoft Corp 1984-1998. All rights reserved.
+
+d_scana.s
+Microsoft (R) Macro Assembler Version 6.11
+Copyright (C) Microsoft Corp 1981-1993.  All rights reserved.
+
+ Assembling: .\Release\d_scana.asm
+Performing Custom Build Step on .\d_polysa.s
+Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for 80x86
+Copyright (C) Microsoft Corp 1984-1998. All rights reserved.
+
+d_polysa.s
+Microsoft (R) Macro Assembler Version 6.11
+Copyright (C) Microsoft Corp 1981-1993.  All rights reserved.
+
+ Assembling: .\Release\d_polysa.asm
+Performing Custom Build Step on .\d_parta.s
+Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for 80x86
+Copyright (C) Microsoft Corp 1984-1998. All rights reserved.
+
+d_parta.s
+Microsoft (R) Macro Assembler Version 6.11
+Copyright (C) Microsoft Corp 1981-1993.  All rights reserved.
+
+ Assembling: .\Release\d_parta.asm
+Performing Custom Build Step on .\d_draw16.s
+Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for 80x86
+Copyright (C) Microsoft Corp 1984-1998. All rights reserved.
+
+d_draw16.s
+Microsoft (R) Macro Assembler Version 6.11
+Copyright (C) Microsoft Corp 1981-1993.  All rights reserved.
+
+ Assembling: .\Release\d_draw16.asm
+Performing Custom Build Step on .\d_draw.s
+Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for 80x86
+Copyright (C) Microsoft Corp 1984-1998. All rights reserved.
+
+d_draw.s
+Microsoft (R) Macro Assembler Version 6.11
+Copyright (C) Microsoft Corp 1981-1993.  All rights reserved.
+
+ Assembling: .\Release\d_draw.asm
+Creating temporary file "C:\TEMP\RSP772.tmp" with contents
+[
+/nologo /G5 /ML /GX /O2 /I "..\dxsdk\sdk\inc" /I "..\scitech\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FR".\Release/" /Fp".\Release/qwcl.pch" /YX /Fo".\Release/" /Fd".\Release/" /FD /c 
+"D:\Work\quake source\QW\client\cd_win.c"
+"D:\Work\quake source\QW\client\cl_cam.c"
+"D:\Work\quake source\QW\client\cl_demo.c"
+"D:\Work\quake source\QW\client\cl_ents.c"
+"D:\Work\quake source\QW\client\cl_input.c"
+"D:\Work\quake source\QW\client\cl_main.c"
+"D:\Work\quake source\QW\client\cl_parse.c"
+"D:\Work\quake source\QW\client\cl_pred.c"
+"D:\Work\quake source\QW\client\cl_tent.c"
+"D:\Work\quake source\QW\client\cmd.c"
+"D:\Work\quake source\QW\client\common.c"
+"D:\Work\quake source\QW\client\console.c"
+"D:\Work\quake source\QW\client\crc.c"
+"D:\Work\quake source\QW\client\cvar.c"
+"D:\Work\quake source\QW\client\d_edge.c"
+"D:\Work\quake source\QW\client\d_fill.c"
+"D:\Work\quake source\QW\client\d_init.c"
+"D:\Work\quake source\QW\client\d_modech.c"
+"D:\Work\quake source\QW\client\d_part.c"
+"D:\Work\quake source\QW\client\d_polyse.c"
+"D:\Work\quake source\QW\client\d_scan.c"
+"D:\Work\quake source\QW\client\d_sky.c"
+"D:\Work\quake source\QW\client\d_sprite.c"
+"D:\Work\quake source\QW\client\d_surf.c"
+"D:\Work\quake source\QW\client\d_vars.c"
+"D:\Work\quake source\QW\client\d_zpoint.c"
+"D:\Work\quake source\QW\client\draw.c"
+"D:\Work\quake source\QW\client\in_win.c"
+"D:\Work\quake source\QW\client\keys.c"
+"D:\Work\quake source\QW\client\mathlib.c"
+"D:\Work\quake source\QW\client\md4.c"
+"D:\Work\quake source\QW\client\menu.c"
+"D:\Work\quake source\QW\client\model.c"
+"D:\Work\quake source\QW\client\net_chan.c"
+"D:\Work\quake source\QW\client\net_wins.c"
+"D:\Work\quake source\QW\client\nonintel.c"
+"D:\Work\quake source\QW\client\pmove.c"
+"D:\Work\quake source\QW\client\pmovetst.c"
+"D:\Work\quake source\QW\client\r_aclip.c"
+"D:\Work\quake source\QW\client\r_alias.c"
+"D:\Work\quake source\QW\client\r_bsp.c"
+"D:\Work\quake source\QW\client\r_draw.c"
+"D:\Work\quake source\QW\client\r_edge.c"
+"D:\Work\quake source\QW\client\r_efrag.c"
+"D:\Work\quake source\QW\client\r_light.c"
+"D:\Work\quake source\QW\client\r_main.c"
+"D:\Work\quake source\QW\client\r_misc.c"
+"D:\Work\quake source\QW\client\r_part.c"
+"D:\Work\quake source\QW\client\r_sky.c"
+"D:\Work\quake source\QW\client\r_sprite.c"
+"D:\Work\quake source\QW\client\r_surf.c"
+"D:\Work\quake source\QW\client\r_vars.c"
+"D:\Work\quake source\QW\client\sbar.c"
+"D:\Work\quake source\QW\client\screen.c"
+"D:\Work\quake source\QW\client\skin.c"
+"D:\Work\quake source\QW\client\snd_dma.c"
+"D:\Work\quake source\QW\client\snd_mem.c"
+"D:\Work\quake source\QW\client\snd_mix.c"
+"D:\Work\quake source\QW\client\snd_win.c"
+"D:\Work\quake source\QW\client\sys_win.c"
+"D:\Work\quake source\QW\client\vid_win.c"
+"D:\Work\quake source\QW\client\view.c"
+"D:\Work\quake source\QW\client\wad.c"
+"D:\Work\quake source\QW\client\zone.c"
+]
+Creating command line "cl.exe @C:\TEMP\RSP772.tmp" 
+Creating temporary file "C:\TEMP\RSP773.tmp" with contents
+[
+..\scitech\lib\win32\vc\mgllt.lib ..\dxsdk\sdk\lib\dxguid.lib opengl32.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib winmm.lib /nologo /subsystem:windows /incremental:yes /pdb:".\Release/qwcl.pdb" /machine:I386 /out:".\Release/qwcl.exe" 
+".\Release\cd_win.obj"
+".\Release\cl_cam.obj"
+".\Release\cl_demo.obj"
+".\Release\cl_ents.obj"
+".\Release\cl_input.obj"
+".\Release\cl_main.obj"
+".\Release\cl_parse.obj"
+".\Release\cl_pred.obj"
+".\Release\cl_tent.obj"
+".\Release\cmd.obj"
+".\Release\common.obj"
+".\Release\console.obj"
+".\Release\crc.obj"
+".\Release\cvar.obj"
+".\Release\d_edge.obj"
+".\Release\d_fill.obj"
+".\Release\d_init.obj"
+".\Release\d_modech.obj"
+".\Release\d_part.obj"
+".\Release\d_polyse.obj"
+".\Release\d_scan.obj"
+".\Release\d_sky.obj"
+".\Release\d_sprite.obj"
+".\Release\d_surf.obj"
+".\Release\d_vars.obj"
+".\Release\d_zpoint.obj"
+".\Release\draw.obj"
+".\Release\in_win.obj"
+".\Release\keys.obj"
+".\Release\mathlib.obj"
+".\Release\md4.obj"
+".\Release\menu.obj"
+".\Release\model.obj"
+".\Release\net_chan.obj"
+".\Release\net_wins.obj"
+".\Release\nonintel.obj"
+".\Release\pmove.obj"
+".\Release\pmovetst.obj"
+".\Release\r_aclip.obj"
+".\Release\r_alias.obj"
+".\Release\r_bsp.obj"
+".\Release\r_draw.obj"
+".\Release\r_edge.obj"
+".\Release\r_efrag.obj"
+".\Release\r_light.obj"
+".\Release\r_main.obj"
+".\Release\r_misc.obj"
+".\Release\r_part.obj"
+".\Release\r_sky.obj"
+".\Release\r_sprite.obj"
+".\Release\r_surf.obj"
+".\Release\r_vars.obj"
+".\Release\sbar.obj"
+".\Release\screen.obj"
+".\Release\skin.obj"
+".\Release\snd_dma.obj"
+".\Release\snd_mem.obj"
+".\Release\snd_mix.obj"
+".\Release\snd_win.obj"
+".\Release\sys_win.obj"
+".\Release\vid_win.obj"
+".\Release\view.obj"
+".\Release\wad.obj"
+".\Release\zone.obj"
+".\Release\winquake.res"
+".\Release\d_draw.obj"
+".\Release\d_draw16.obj"
+".\Release\d_parta.obj"
+".\Release\d_polysa.obj"
+".\Release\d_scana.obj"
+".\Release\d_spr8.obj"
+".\Release\d_varsa.obj"
+".\Release\math.obj"
+".\Release\r_aclipa.obj"
+".\Release\r_aliasa.obj"
+".\Release\r_drawa.obj"
+".\Release\r_edgea.obj"
+".\Release\r_varsa.obj"
+".\Release\snd_mixa.obj"
+".\Release\surf16.obj"
+".\Release\surf8.obj"
+".\Release\sys_wina.obj"
+]
+Creating command line "link.exe @C:\TEMP\RSP773.tmp"
+<h3>Output Window</h3>
+Compiling resources...
+Compiling...
+cd_win.c
+cl_cam.c
+cl_demo.c
+cl_ents.c
+cl_input.c
+cl_main.c
+cl_parse.c
+cl_pred.c
+cl_tent.c
+cmd.c
+common.c
+console.c
+crc.c
+cvar.c
+d_edge.c
+d_fill.c
+d_init.c
+d_modech.c
+d_part.c
+d_polyse.c
+d_scan.c
+d_sky.c
+d_sprite.c
+d_surf.c
+d_vars.c
+d_zpoint.c
+draw.c
+in_win.c
+keys.c
+D:\Work\quake source\QW\client\in_win.c(876) : warning C4715: 'RawValuePointer' : not all control paths return a value
+mathlib.c
+md4.c
+menu.c
+model.c
+net_chan.c
+net_wins.c
+nonintel.c
+pmove.c
+pmovetst.c
+r_aclip.c
+r_alias.c
+r_bsp.c
+r_draw.c
+r_edge.c
+r_efrag.c
+r_light.c
+r_main.c
+r_misc.c
+r_part.c
+r_sky.c
+r_sprite.c
+r_surf.c
+r_vars.c
+sbar.c
+screen.c
+skin.c
+snd_dma.c
+snd_mem.c
+snd_mix.c
+snd_win.c
+sys_win.c
+vid_win.c
+view.c
+D:\Work\quake source\QW\client\vid_win.c(388) : warning C4715: 'VID_Suspend' : not all control paths return a value
+wad.c
+zone.c
+Linking...
+
+
+
+<h3>Results</h3>
+qwcl.exe - 0 error(s), 2 warning(s)
+</pre>
+</body>
+</html>
binary files /dev/null b/QW/client/qwcl2.ico differ
--- /dev/null
+++ b/QW/client/r_aclip.c
@@ -1,0 +1,350 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// r_aclip.c: clip routines for drawing Alias models directly to the screen
+
+#include "quakedef.h"
+#include "r_local.h"
+#include "d_local.h"
+
+static finalvert_t		fv[2][8];
+static auxvert_t		av[8];
+
+void R_AliasProjectFinalVert (finalvert_t *fv, auxvert_t *av);
+void R_Alias_clip_top (finalvert_t *pfv0, finalvert_t *pfv1,
+	finalvert_t *out);
+void R_Alias_clip_bottom (finalvert_t *pfv0, finalvert_t *pfv1,
+	finalvert_t *out);
+void R_Alias_clip_left (finalvert_t *pfv0, finalvert_t *pfv1,
+	finalvert_t *out);
+void R_Alias_clip_right (finalvert_t *pfv0, finalvert_t *pfv1,
+	finalvert_t *out);
+
+
+/*
+================
+R_Alias_clip_z
+
+pfv0 is the unclipped vertex, pfv1 is the z-clipped vertex
+================
+*/
+void R_Alias_clip_z (finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out)
+{
+	float		scale;
+	auxvert_t	*pav0, *pav1, avout;
+
+	pav0 = &av[pfv0 - &fv[0][0]];
+	pav1 = &av[pfv1 - &fv[0][0]];
+
+	if (pfv0->v[1] >= pfv1->v[1])
+	{
+		scale = (ALIAS_Z_CLIP_PLANE - pav0->fv[2]) /
+				(pav1->fv[2] - pav0->fv[2]);
+	
+		avout.fv[0] = pav0->fv[0] + (pav1->fv[0] - pav0->fv[0]) * scale;
+		avout.fv[1] = pav0->fv[1] + (pav1->fv[1] - pav0->fv[1]) * scale;
+		avout.fv[2] = ALIAS_Z_CLIP_PLANE;
+	
+		out->v[2] =	pfv0->v[2] + (pfv1->v[2] - pfv0->v[2]) * scale;
+		out->v[3] =	pfv0->v[3] + (pfv1->v[3] - pfv0->v[3]) * scale;
+		out->v[4] =	pfv0->v[4] + (pfv1->v[4] - pfv0->v[4]) * scale;
+	}
+	else
+	{
+		scale = (ALIAS_Z_CLIP_PLANE - pav1->fv[2]) /
+				(pav0->fv[2] - pav1->fv[2]);
+	
+		avout.fv[0] = pav1->fv[0] + (pav0->fv[0] - pav1->fv[0]) * scale;
+		avout.fv[1] = pav1->fv[1] + (pav0->fv[1] - pav1->fv[1]) * scale;
+		avout.fv[2] = ALIAS_Z_CLIP_PLANE;
+	
+		out->v[2] =	pfv1->v[2] + (pfv0->v[2] - pfv1->v[2]) * scale;
+		out->v[3] =	pfv1->v[3] + (pfv0->v[3] - pfv1->v[3]) * scale;
+		out->v[4] =	pfv1->v[4] + (pfv0->v[4] - pfv1->v[4]) * scale;
+	}
+
+	R_AliasProjectFinalVert (out, &avout);
+
+	if (out->v[0] < r_refdef.aliasvrect.x)
+		out->flags |= ALIAS_LEFT_CLIP;
+	if (out->v[1] < r_refdef.aliasvrect.y)
+		out->flags |= ALIAS_TOP_CLIP;
+	if (out->v[0] > r_refdef.aliasvrectright)
+		out->flags |= ALIAS_RIGHT_CLIP;
+	if (out->v[1] > r_refdef.aliasvrectbottom)
+		out->flags |= ALIAS_BOTTOM_CLIP;	
+}
+
+
+#if	!id386
+
+void R_Alias_clip_left (finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out)
+{
+	float		scale;
+	int			i;
+
+	if (pfv0->v[1] >= pfv1->v[1])
+	{
+		scale = (float)(r_refdef.aliasvrect.x - pfv0->v[0]) /
+				(pfv1->v[0] - pfv0->v[0]);
+		for (i=0 ; i<6 ; i++)
+			out->v[i] = pfv0->v[i] + (pfv1->v[i] - pfv0->v[i])*scale + 0.5;
+	}
+	else
+	{
+		scale = (float)(r_refdef.aliasvrect.x - pfv1->v[0]) /
+				(pfv0->v[0] - pfv1->v[0]);
+		for (i=0 ; i<6 ; i++)
+			out->v[i] = pfv1->v[i] + (pfv0->v[i] - pfv1->v[i])*scale + 0.5;
+	}
+}
+
+
+void R_Alias_clip_right (finalvert_t *pfv0, finalvert_t *pfv1,
+	finalvert_t *out)
+{
+	float		scale;
+	int			i;
+
+	if (pfv0->v[1] >= pfv1->v[1])
+	{
+		scale = (float)(r_refdef.aliasvrectright - pfv0->v[0]) /
+				(pfv1->v[0] - pfv0->v[0]);
+		for (i=0 ; i<6 ; i++)
+			out->v[i] = pfv0->v[i] + (pfv1->v[i] - pfv0->v[i])*scale + 0.5;
+	}
+	else
+	{
+		scale = (float)(r_refdef.aliasvrectright - pfv1->v[0]) /
+				(pfv0->v[0] - pfv1->v[0]);
+		for (i=0 ; i<6 ; i++)
+			out->v[i] = pfv1->v[i] + (pfv0->v[i] - pfv1->v[i])*scale + 0.5;
+	}
+}
+
+
+void R_Alias_clip_top (finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out)
+{
+	float		scale;
+	int			i;
+
+	if (pfv0->v[1] >= pfv1->v[1])
+	{
+		scale = (float)(r_refdef.aliasvrect.y - pfv0->v[1]) /
+				(pfv1->v[1] - pfv0->v[1]);
+		for (i=0 ; i<6 ; i++)
+			out->v[i] = pfv0->v[i] + (pfv1->v[i] - pfv0->v[i])*scale + 0.5;
+	}
+	else
+	{
+		scale = (float)(r_refdef.aliasvrect.y - pfv1->v[1]) /
+				(pfv0->v[1] - pfv1->v[1]);
+		for (i=0 ; i<6 ; i++)
+			out->v[i] = pfv1->v[i] + (pfv0->v[i] - pfv1->v[i])*scale + 0.5;
+	}
+}
+
+
+void R_Alias_clip_bottom (finalvert_t *pfv0, finalvert_t *pfv1,
+	finalvert_t *out)
+{
+	float		scale;
+	int			i;
+
+	if (pfv0->v[1] >= pfv1->v[1])
+	{
+		scale = (float)(r_refdef.aliasvrectbottom - pfv0->v[1]) /
+				(pfv1->v[1] - pfv0->v[1]);
+
+		for (i=0 ; i<6 ; i++)
+			out->v[i] = pfv0->v[i] + (pfv1->v[i] - pfv0->v[i])*scale + 0.5;
+	}
+	else
+	{
+		scale = (float)(r_refdef.aliasvrectbottom - pfv1->v[1]) /
+				(pfv0->v[1] - pfv1->v[1]);
+
+		for (i=0 ; i<6 ; i++)
+			out->v[i] = pfv1->v[i] + (pfv0->v[i] - pfv1->v[i])*scale + 0.5;
+	}
+}
+
+#endif
+
+
+int R_AliasClip (finalvert_t *in, finalvert_t *out, int flag, int count,
+	void(*clip)(finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out) )
+{
+	int			i,j,k;
+	int			flags, oldflags;
+	
+	j = count-1;
+	k = 0;
+	for (i=0 ; i<count ; j = i, i++)
+	{
+		oldflags = in[j].flags & flag;
+		flags = in[i].flags & flag;
+
+		if (flags && oldflags)
+			continue;
+		if (oldflags ^ flags)
+		{
+			clip (&in[j], &in[i], &out[k]);
+			out[k].flags = 0;
+			if (out[k].v[0] < r_refdef.aliasvrect.x)
+				out[k].flags |= ALIAS_LEFT_CLIP;
+			if (out[k].v[1] < r_refdef.aliasvrect.y)
+				out[k].flags |= ALIAS_TOP_CLIP;
+			if (out[k].v[0] > r_refdef.aliasvrectright)
+				out[k].flags |= ALIAS_RIGHT_CLIP;
+			if (out[k].v[1] > r_refdef.aliasvrectbottom)
+				out[k].flags |= ALIAS_BOTTOM_CLIP;	
+			k++;
+		}
+		if (!flags)
+		{
+			out[k] = in[i];
+			k++;
+		}
+	}
+	
+	return k;
+}
+
+
+/*
+================
+R_AliasClipTriangle
+================
+*/
+void R_AliasClipTriangle (mtriangle_t *ptri)
+{
+	int				i, k, pingpong;
+	mtriangle_t		mtri;
+	unsigned		clipflags;
+
+// copy vertexes and fix seam texture coordinates
+	if (ptri->facesfront)
+	{
+		fv[0][0] = pfinalverts[ptri->vertindex[0]];
+		fv[0][1] = pfinalverts[ptri->vertindex[1]];
+		fv[0][2] = pfinalverts[ptri->vertindex[2]];
+	}
+	else
+	{
+		for (i=0 ; i<3 ; i++)
+		{
+			fv[0][i] = pfinalverts[ptri->vertindex[i]];
+	
+			if (!ptri->facesfront && (fv[0][i].flags & ALIAS_ONSEAM) )
+				fv[0][i].v[2] += r_affinetridesc.seamfixupX16;
+		}
+	}
+
+// clip
+	clipflags = fv[0][0].flags | fv[0][1].flags | fv[0][2].flags;
+
+	if (clipflags & ALIAS_Z_CLIP)
+	{
+		for (i=0 ; i<3 ; i++)
+			av[i] = pauxverts[ptri->vertindex[i]];
+
+		k = R_AliasClip (fv[0], fv[1], ALIAS_Z_CLIP, 3, R_Alias_clip_z);
+		if (k == 0)
+			return;
+
+		pingpong = 1;
+		clipflags = fv[1][0].flags | fv[1][1].flags | fv[1][2].flags;
+	}
+	else
+	{
+		pingpong = 0;
+		k = 3;
+	}
+
+	if (clipflags & ALIAS_LEFT_CLIP)
+	{
+		k = R_AliasClip (fv[pingpong], fv[pingpong ^ 1],
+							ALIAS_LEFT_CLIP, k, R_Alias_clip_left);
+		if (k == 0)
+			return;
+
+		pingpong ^= 1;
+	}
+
+	if (clipflags & ALIAS_RIGHT_CLIP)
+	{
+		k = R_AliasClip (fv[pingpong], fv[pingpong ^ 1],
+							ALIAS_RIGHT_CLIP, k, R_Alias_clip_right);
+		if (k == 0)
+			return;
+
+		pingpong ^= 1;
+	}
+
+	if (clipflags & ALIAS_BOTTOM_CLIP)
+	{
+		k = R_AliasClip (fv[pingpong], fv[pingpong ^ 1],
+							ALIAS_BOTTOM_CLIP, k, R_Alias_clip_bottom);
+		if (k == 0)
+			return;
+
+		pingpong ^= 1;
+	}
+
+	if (clipflags & ALIAS_TOP_CLIP)
+	{
+		k = R_AliasClip (fv[pingpong], fv[pingpong ^ 1],
+							ALIAS_TOP_CLIP, k, R_Alias_clip_top);
+		if (k == 0)
+			return;
+
+		pingpong ^= 1;
+	}
+
+	for (i=0 ; i<k ; i++)
+	{
+		if (fv[pingpong][i].v[0] < r_refdef.aliasvrect.x)
+			fv[pingpong][i].v[0] = r_refdef.aliasvrect.x;
+		else if (fv[pingpong][i].v[0] > r_refdef.aliasvrectright)
+			fv[pingpong][i].v[0] = r_refdef.aliasvrectright;
+
+		if (fv[pingpong][i].v[1] < r_refdef.aliasvrect.y)
+			fv[pingpong][i].v[1] = r_refdef.aliasvrect.y;
+		else if (fv[pingpong][i].v[1] > r_refdef.aliasvrectbottom)
+			fv[pingpong][i].v[1] = r_refdef.aliasvrectbottom;
+
+		fv[pingpong][i].flags = 0;
+	}
+
+// draw triangles
+	mtri.facesfront = ptri->facesfront;
+	r_affinetridesc.ptriangles = &mtri;
+	r_affinetridesc.pfinalverts = fv[pingpong];
+
+// FIXME: do all at once as trifan?
+	mtri.vertindex[0] = 0;
+	for (i=1 ; i<k-1 ; i++)
+	{
+		mtri.vertindex[1] = i;
+		mtri.vertindex[2] = i+1;
+		D_PolysetDraw ();
+	}
+}
+
--- /dev/null
+++ b/QW/client/r_aclipa.asm
@@ -1,0 +1,345 @@
+ .386P
+ .model FLAT
+ externdef _d_zistepu:dword
+ externdef _d_pzbuffer:dword
+ externdef _d_zistepv:dword
+ externdef _d_zrowbytes:dword
+ externdef _d_ziorigin:dword
+ externdef _r_turb_s:dword
+ externdef _r_turb_t:dword
+ externdef _r_turb_pdest:dword
+ externdef _r_turb_spancount:dword
+ externdef _r_turb_turb:dword
+ externdef _r_turb_pbase:dword
+ externdef _r_turb_sstep:dword
+ externdef _r_turb_tstep:dword
+ externdef _r_bmodelactive:dword
+ externdef _d_sdivzstepu:dword
+ externdef _d_tdivzstepu:dword
+ externdef _d_sdivzstepv:dword
+ externdef _d_tdivzstepv:dword
+ externdef _d_sdivzorigin:dword
+ externdef _d_tdivzorigin:dword
+ externdef _sadjust:dword
+ externdef _tadjust:dword
+ externdef _bbextents:dword
+ externdef _bbextentt:dword
+ externdef _cacheblock:dword
+ externdef _d_viewbuffer:dword
+ externdef _cachewidth:dword
+ externdef _d_pzbuffer:dword
+ externdef _d_zrowbytes:dword
+ externdef _d_zwidth:dword
+ externdef _d_scantable:dword
+ externdef _r_lightptr:dword
+ externdef _r_numvblocks:dword
+ externdef _prowdestbase:dword
+ externdef _pbasesource:dword
+ externdef _r_lightwidth:dword
+ externdef _lightright:dword
+ externdef _lightrightstep:dword
+ externdef _lightdeltastep:dword
+ externdef _lightdelta:dword
+ externdef _lightright:dword
+ externdef _lightdelta:dword
+ externdef _sourcetstep:dword
+ externdef _surfrowbytes:dword
+ externdef _lightrightstep:dword
+ externdef _lightdeltastep:dword
+ externdef _r_sourcemax:dword
+ externdef _r_stepback:dword
+ externdef _colormap:dword
+ externdef _blocksize:dword
+ externdef _sourcesstep:dword
+ externdef _lightleft:dword
+ externdef _blockdivshift:dword
+ externdef _blockdivmask:dword
+ externdef _lightleftstep:dword
+ externdef _r_origin:dword
+ externdef _r_ppn:dword
+ externdef _r_pup:dword
+ externdef _r_pright:dword
+ externdef _ycenter:dword
+ externdef _xcenter:dword
+ externdef _d_vrectbottom_particle:dword
+ externdef _d_vrectright_particle:dword
+ externdef _d_vrecty:dword
+ externdef _d_vrectx:dword
+ externdef _d_pix_shift:dword
+ externdef _d_pix_min:dword
+ externdef _d_pix_max:dword
+ externdef _d_y_aspect_shift:dword
+ externdef _screenwidth:dword
+ externdef _vright:dword
+ externdef _vup:dword
+ externdef _vpn:dword
+ externdef _BOPS_Error:dword
+ externdef _snd_scaletable:dword
+ externdef _paintbuffer:dword
+ externdef _snd_linear_count:dword
+ externdef _snd_p:dword
+ externdef _snd_vol:dword
+ externdef _snd_out:dword
+ externdef _r_leftclipped:dword
+ externdef _r_leftenter:dword
+ externdef _r_rightclipped:dword
+ externdef _r_rightenter:dword
+ externdef _modelorg:dword
+ externdef _xscale:dword
+ externdef _r_refdef:dword
+ externdef _yscale:dword
+ externdef _r_leftexit:dword
+ externdef _r_rightexit:dword
+ externdef _r_lastvertvalid:dword
+ externdef _cacheoffset:dword
+ externdef _newedges:dword
+ externdef _removeedges:dword
+ externdef _r_pedge:dword
+ externdef _r_framecount:dword
+ externdef _r_u1:dword
+ externdef _r_emitted:dword
+ externdef _edge_p:dword
+ externdef _surface_p:dword
+ externdef _surfaces:dword
+ externdef _r_lzi1:dword
+ externdef _r_v1:dword
+ externdef _r_ceilv1:dword
+ externdef _r_nearzi:dword
+ externdef _r_nearzionly:dword
+ externdef _edge_aftertail:dword
+ externdef _edge_tail:dword
+ externdef _current_iv:dword
+ externdef _edge_head_u_shift20:dword
+ externdef _span_p:dword
+ externdef _edge_head:dword
+ externdef _fv:dword
+ externdef _edge_tail_u_shift20:dword
+ externdef _r_apverts:dword
+ externdef _r_anumverts:dword
+ externdef _aliastransform:dword
+ externdef _r_avertexnormals:dword
+ externdef _r_plightvec:dword
+ externdef _r_ambientlight:dword
+ externdef _r_shadelight:dword
+ externdef _aliasxcenter:dword
+ externdef _aliasycenter:dword
+ externdef _a_sstepxfrac:dword
+ externdef _r_affinetridesc:dword
+ externdef _acolormap:dword
+ externdef _d_pcolormap:dword
+ externdef _r_affinetridesc:dword
+ externdef _d_sfrac:dword
+ externdef _d_ptex:dword
+ externdef _d_pedgespanpackage:dword
+ externdef _d_tfrac:dword
+ externdef _d_light:dword
+ externdef _d_zi:dword
+ externdef _d_pdest:dword
+ externdef _d_pz:dword
+ externdef _d_aspancount:dword
+ externdef _erroradjustup:dword
+ externdef _errorterm:dword
+ externdef _d_xdenom:dword
+ externdef _r_p0:dword
+ externdef _r_p1:dword
+ externdef _r_p2:dword
+ externdef _a_tstepxfrac:dword
+ externdef _r_sstepx:dword
+ externdef _r_tstepx:dword
+ externdef _a_ststepxwhole:dword
+ externdef _zspantable:dword
+ externdef _skintable:dword
+ externdef _r_zistepx:dword
+ externdef _erroradjustdown:dword
+ externdef _d_countextrastep:dword
+ externdef _ubasestep:dword
+ externdef _a_ststepxwhole:dword
+ externdef _a_tstepxfrac:dword
+ externdef _r_lstepx:dword
+ externdef _a_spans:dword
+ externdef _erroradjustdown:dword
+ externdef _d_pdestextrastep:dword
+ externdef _d_pzextrastep:dword
+ externdef _d_sfracextrastep:dword
+ externdef _d_ptexextrastep:dword
+ externdef _d_countextrastep:dword
+ externdef _d_tfracextrastep:dword
+ externdef _d_lightextrastep:dword
+ externdef _d_ziextrastep:dword
+ externdef _d_pdestbasestep:dword
+ externdef _d_pzbasestep:dword
+ externdef _d_sfracbasestep:dword
+ externdef _d_ptexbasestep:dword
+ externdef _ubasestep:dword
+ externdef _d_tfracbasestep:dword
+ externdef _d_lightbasestep:dword
+ externdef _d_zibasestep:dword
+ externdef _zspantable:dword
+ externdef _r_lstepy:dword
+ externdef _r_sstepy:dword
+ externdef _r_tstepy:dword
+ externdef _r_zistepy:dword
+ externdef _D_PolysetSetEdgeTable:dword
+ externdef _D_RasterizeAliasPolySmooth:dword
+ externdef float_point5:dword
+ externdef Float2ToThe31nd:dword
+ externdef izistep:dword
+ externdef izi:dword
+ externdef FloatMinus2ToThe31nd:dword
+ externdef float_1:dword
+ externdef float_particle_z_clip:dword
+ externdef float_minus_1:dword
+ externdef float_0:dword
+ externdef fp_16:dword
+ externdef fp_64k:dword
+ externdef fp_1m:dword
+ externdef fp_1m_minus_1:dword
+ externdef fp_8:dword
+ externdef entryvec_table:dword
+ externdef advancetable:dword
+ externdef sstep:dword
+ externdef tstep:dword
+ externdef pspantemp:dword
+ externdef counttemp:dword
+ externdef jumptemp:dword
+ externdef reciprocal_table:dword
+ externdef DP_Count:dword
+ externdef DP_u:dword
+ externdef DP_v:dword
+ externdef DP_32768:dword
+ externdef DP_Color:dword
+ externdef DP_Pix:dword
+ externdef DP_EntryTable:dword
+ externdef pbase:dword
+ externdef s:dword
+ externdef t:dword
+ externdef sfracf:dword
+ externdef tfracf:dword
+ externdef snext:dword
+ externdef tnext:dword
+ externdef spancountminus1:dword
+ externdef zi16stepu:dword
+ externdef sdivz16stepu:dword
+ externdef tdivz16stepu:dword
+ externdef zi8stepu:dword
+ externdef sdivz8stepu:dword
+ externdef tdivz8stepu:dword
+ externdef reciprocal_table_16:dword
+ externdef entryvec_table_16:dword
+ externdef ceil_cw:dword
+ externdef single_cw:dword
+ externdef fp_64kx64k:dword
+ externdef pz:dword
+ externdef spr8entryvec_table:dword
+_DATA SEGMENT
+Ltemp0 dd 0
+Ltemp1 dd 0
+_DATA ENDS
+_TEXT SEGMENT
+ public _R_Alias_clip_bottom
+_R_Alias_clip_bottom:
+ push esi
+ push edi
+ mov esi,ds:dword ptr[8+4+esp]
+ mov edi,ds:dword ptr[8+8+esp]
+ mov eax,ds:dword ptr[_r_refdef+52]
+LDoForwardOrBackward:
+ mov edx,ds:dword ptr[0+4+esi]
+ mov ecx,ds:dword ptr[0+4+edi]
+ cmp edx,ecx
+ jl LDoForward
+ mov ecx,ds:dword ptr[0+4+esi]
+ mov edx,ds:dword ptr[0+4+edi]
+ mov edi,ds:dword ptr[8+4+esp]
+ mov esi,ds:dword ptr[8+8+esp]
+LDoForward:
+ sub ecx,edx
+ sub eax,edx
+ mov ds:dword ptr[Ltemp1],ecx
+ mov ds:dword ptr[Ltemp0],eax
+ fild ds:dword ptr[Ltemp1]
+ fild ds:dword ptr[Ltemp0]
+ mov edx,ds:dword ptr[8+12+esp]
+ mov eax,2
+ fdivrp st(1),st(0)
+LDo3Forward:
+ fild ds:dword ptr[0+0+esi]
+ fild ds:dword ptr[0+0+edi]
+ fild ds:dword ptr[0+4+esi]
+ fild ds:dword ptr[0+4+edi]
+ fild ds:dword ptr[0+8+esi]
+ fild ds:dword ptr[0+8+edi]
+ fxch st(5)
+ fsub st(4),st(0)
+ fxch st(3)
+ fsub st(2),st(0)
+ fxch st(1)
+ fsub st(5),st(0)
+ fxch st(6)
+ fmul st(4),st(0)
+ add edi,12
+ fmul st(2),st(0)
+ add esi,12
+ add edx,12
+ fmul st(5),st(0)
+ fxch st(3)
+ faddp st(4),st(0)
+ faddp st(1),st(0)
+ fxch st(4)
+ faddp st(3),st(0)
+ fxch st(1)
+ fadd ds:dword ptr[float_point5]
+ fxch st(3)
+ fadd ds:dword ptr[float_point5]
+ fxch st(2)
+ fadd ds:dword ptr[float_point5]
+ fxch st(3)
+ fistp ds:dword ptr[0+0-12+edx]
+ fxch st(1)
+ fistp ds:dword ptr[0+4-12+edx]
+ fxch st(1)
+ fistp ds:dword ptr[0+8-12+edx]
+ dec eax
+ jnz LDo3Forward
+ fstp st(0)
+ pop edi
+ pop esi
+ ret
+ public _R_Alias_clip_top
+_R_Alias_clip_top:
+ push esi
+ push edi
+ mov esi,ds:dword ptr[8+4+esp]
+ mov edi,ds:dword ptr[8+8+esp]
+ mov eax,ds:dword ptr[_r_refdef+20+4]
+ jmp LDoForwardOrBackward
+ public _R_Alias_clip_right
+_R_Alias_clip_right:
+ push esi
+ push edi
+ mov esi,ds:dword ptr[8+4+esp]
+ mov edi,ds:dword ptr[8+8+esp]
+ mov eax,ds:dword ptr[_r_refdef+48]
+LRightLeftEntry:
+ mov edx,ds:dword ptr[0+4+esi]
+ mov ecx,ds:dword ptr[0+4+edi]
+ cmp edx,ecx
+ mov edx,ds:dword ptr[0+0+esi]
+ mov ecx,ds:dword ptr[0+0+edi]
+ jl LDoForward2
+ mov ecx,ds:dword ptr[0+0+esi]
+ mov edx,ds:dword ptr[0+0+edi]
+ mov edi,ds:dword ptr[8+4+esp]
+ mov esi,ds:dword ptr[8+8+esp]
+LDoForward2:
+ jmp LDoForward
+ public _R_Alias_clip_left
+_R_Alias_clip_left:
+ push esi
+ push edi
+ mov esi,ds:dword ptr[8+4+esp]
+ mov edi,ds:dword ptr[8+8+esp]
+ mov eax,ds:dword ptr[_r_refdef+20+0]
+ jmp LRightLeftEntry
+_TEXT ENDS
+ END
--- /dev/null
+++ b/QW/client/r_aclipa.s
@@ -1,0 +1,216 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+//
+// r_aliasa.s
+// x86 assembly-language Alias model transform and project code.
+//
+
+#include "asm_i386.h"
+#include "quakeasm.h"
+#include "asm_draw.h"
+#include "d_ifacea.h"
+
+#if id386
+
+	.data
+Ltemp0:	.long	0
+Ltemp1:	.long	0
+
+	.text
+
+#define pfv0		8+4
+#define pfv1		8+8
+#define out			8+12
+
+.globl C(R_Alias_clip_bottom)
+C(R_Alias_clip_bottom):
+	pushl	%esi
+	pushl	%edi
+
+	movl	pfv0(%esp),%esi
+	movl	pfv1(%esp),%edi
+
+	movl	C(r_refdef)+rd_aliasvrectbottom,%eax
+
+LDoForwardOrBackward:
+
+	movl	fv_v+4(%esi),%edx
+	movl	fv_v+4(%edi),%ecx
+
+	cmpl	%ecx,%edx
+	jl		LDoForward
+
+	movl	fv_v+4(%esi),%ecx
+	movl	fv_v+4(%edi),%edx
+	movl	pfv0(%esp),%edi
+	movl	pfv1(%esp),%esi
+
+LDoForward:
+
+	subl	%edx,%ecx
+	subl	%edx,%eax
+	movl	%ecx,Ltemp1
+	movl	%eax,Ltemp0
+	fildl	Ltemp1
+	fildl	Ltemp0
+	movl	out(%esp),%edx
+	movl	$2,%eax
+
+	fdivp	%st(0),%st(1)					// scale
+
+LDo3Forward:
+	fildl	fv_v+0(%esi)	// fv0v0 | scale
+	fildl	fv_v+0(%edi)	// fv1v0 | fv0v0 | scale
+	fildl	fv_v+4(%esi)	// fv0v1 | fv1v0 | fv0v0 | scale
+	fildl	fv_v+4(%edi)	// fv1v1 | fv0v1 | fv1v0 | fv0v0 | scale
+	fildl	fv_v+8(%esi)	// fv0v2 | fv1v1 | fv0v1 | fv1v0 | fv0v0 | scale
+	fildl	fv_v+8(%edi)	// fv1v2 | fv0v2 | fv1v1 | fv0v1 | fv1v0 | fv0v0 |
+							//  scale
+	fxch	%st(5)			// fv0v0 | fv0v2 | fv1v1 | fv0v1 | fv1v0 | fv1v2 |
+							//  scale
+	fsubr	%st(0),%st(4)	// fv0v0 | fv0v2 | fv1v1 | fv0v1 | fv1v0-fv0v0 |
+							//  fv1v2 | scale
+	fxch	%st(3)			// fv0v1 | fv0v2 | fv1v1 | fv0v0 | fv1v0-fv0v0 |
+							//  fv1v2 | scale
+	fsubr	%st(0),%st(2)	// fv0v1 | fv0v2 | fv1v1-fv0v1 | fv0v0 |
+							//  fv1v0-fv0v0 | fv1v2 | scale
+	fxch	%st(1)			// fv0v2 | fv0v1 | fv1v1-fv0v1 | fv0v0 |
+							//  fv1v0-fv0v0 | fv1v2 | scale
+	fsubr	%st(0),%st(5)	// fv0v2 | fv0v1 | fv1v1-fv0v1 | fv0v0 |
+							//  fv1v0-fv0v0 | fv1v2-fv0v2 | scale
+	fxch	%st(6)			// scale | fv0v1 | fv1v1-fv0v1 | fv0v0 |
+							//  fv1v0-fv0v0 | fv1v2-fv0v2 | fv0v2
+	fmul	%st(0),%st(4)	// scale | fv0v1 | fv1v1-fv0v1 | fv0v0 |
+							//  (fv1v0-fv0v0)*scale | fv1v2-fv0v2 | fv0v2
+	addl	$12,%edi
+	fmul	%st(0),%st(2)	// scale | fv0v1 | (fv1v1-fv0v1)*scale | fv0v0 |
+							//  (fv1v0-fv0v0)*scale | fv1v2-fv0v2 | fv0v2
+	addl	$12,%esi
+	addl	$12,%edx
+	fmul	%st(0),%st(5)	// scale | fv0v1 | (fv1v1-fv0v1)*scale | fv0v0 |
+							//  (fv1v0-fv0v0)*scale | (fv1v2-fv0v2)*scale |
+							//  fv0v2
+	fxch	%st(3)			// fv0v0 | fv0v1 | (fv1v1-fv0v1)*scale | scale |
+							//  (fv1v0-fv0v0)*scale | (fv1v2-fv0v2)*scale |
+							//  fv0v2
+	faddp	%st(0),%st(4)	// fv0v1 | (fv1v1-fv0v1)*scale | scale |
+							//  fv0v0+(fv1v0-fv0v0)*scale |
+							//  (fv1v2-fv0v2)*scale | fv0v2
+	faddp	%st(0),%st(1)	// fv0v1+(fv1v1-fv0v1)*scale | scale |
+							//  fv0v0+(fv1v0-fv0v0)*scale |
+							//  (fv1v2-fv0v2)*scale | fv0v2
+	fxch	%st(4)			// fv0v2 | scale | fv0v0+(fv1v0-fv0v0)*scale |
+							//  (fv1v2-fv0v2)*scale | fv0v1+(fv1v1-fv0v1)*scale
+	faddp	%st(0),%st(3)	// scale | fv0v0+(fv1v0-fv0v0)*scale |
+							//  fv0v2+(fv1v2-fv0v2)*scale |
+							//  fv0v1+(fv1v1-fv0v1)*scale
+	fxch	%st(1)			// fv0v0+(fv1v0-fv0v0)*scale | scale | 
+							//  fv0v2+(fv1v2-fv0v2)*scale |
+							//  fv0v1+(fv1v1-fv0v1)*scale
+	fadds	float_point5
+	fxch	%st(3)			// fv0v1+(fv1v1-fv0v1)*scale | scale | 
+							//  fv0v2+(fv1v2-fv0v2)*scale |
+							//  fv0v0+(fv1v0-fv0v0)*scale
+	fadds	float_point5
+	fxch	%st(2)			// fv0v2+(fv1v2-fv0v2)*scale | scale | 
+							//  fv0v1+(fv1v1-fv0v1)*scale |
+							//  fv0v0+(fv1v0-fv0v0)*scale
+	fadds	float_point5
+	fxch	%st(3)			// fv0v0+(fv1v0-fv0v0)*scale | scale | 
+							//  fv0v1+(fv1v1-fv0v1)*scale |
+							//  fv0v2+(fv1v2-fv0v2)*scale
+	fistpl	fv_v+0-12(%edx)	// scale | fv0v1+(fv1v1-fv0v1)*scale |
+							//  fv0v2+(fv1v2-fv0v2)*scale
+	fxch	%st(1)			// fv0v1+(fv1v1-fv0v1)*scale | scale |
+							//  fv0v2+(fv1v2-fv0v2)*scale | scale
+	fistpl	fv_v+4-12(%edx)	// scale | fv0v2+(fv1v2-fv0v2)*scale
+	fxch	%st(1)			// fv0v2+(fv1v2-fv0v2)*sc | scale
+	fistpl	fv_v+8-12(%edx)	// scale
+
+	decl	%eax
+	jnz		LDo3Forward
+
+	fstp	%st(0)
+
+	popl	%edi
+	popl	%esi
+
+	ret
+
+
+.globl C(R_Alias_clip_top)
+C(R_Alias_clip_top):
+	pushl	%esi
+	pushl	%edi
+
+	movl	pfv0(%esp),%esi
+	movl	pfv1(%esp),%edi
+
+	movl	C(r_refdef)+rd_aliasvrect+4,%eax
+	jmp		LDoForwardOrBackward
+
+
+
+.globl C(R_Alias_clip_right)
+C(R_Alias_clip_right):
+	pushl	%esi
+	pushl	%edi
+
+	movl	pfv0(%esp),%esi
+	movl	pfv1(%esp),%edi
+
+	movl	C(r_refdef)+rd_aliasvrectright,%eax
+
+LRightLeftEntry:
+
+
+	movl	fv_v+4(%esi),%edx
+	movl	fv_v+4(%edi),%ecx
+
+	cmpl	%ecx,%edx
+	movl	fv_v+0(%esi),%edx
+
+	movl	fv_v+0(%edi),%ecx
+	jl		LDoForward2
+
+	movl	fv_v+0(%esi),%ecx
+	movl	fv_v+0(%edi),%edx
+	movl	pfv0(%esp),%edi
+	movl	pfv1(%esp),%esi
+
+LDoForward2:
+
+	jmp		LDoForward
+
+
+.globl C(R_Alias_clip_left)
+C(R_Alias_clip_left):
+	pushl	%esi
+	pushl	%edi
+
+	movl	pfv0(%esp),%esi
+	movl	pfv1(%esp),%edi
+
+	movl	C(r_refdef)+rd_aliasvrect+0,%eax
+	jmp		LRightLeftEntry
+
+
+#endif	// id386
+
--- /dev/null
+++ b/QW/client/r_alias.c
@@ -1,0 +1,768 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// r_alias.c: routines for setting up to draw alias models
+
+#include "quakedef.h"
+#include "r_local.h"
+#include "d_local.h"	// FIXME: shouldn't be needed (is needed for patch
+						// right now, but that should move)
+
+#define LIGHT_MIN	5		// lowest light value we'll allow, to avoid the
+							//  need for inner-loop light clamping
+
+mtriangle_t		*ptriangles;
+affinetridesc_t	r_affinetridesc;
+
+void *			acolormap;	// FIXME: should go away
+
+trivertx_t		*r_apverts;
+
+// TODO: these probably will go away with optimized rasterization
+mdl_t				*pmdl;
+vec3_t				r_plightvec;
+int					r_ambientlight;
+float				r_shadelight;
+aliashdr_t			*paliashdr;
+finalvert_t			*pfinalverts;
+auxvert_t			*pauxverts;
+static float		ziscale;
+static model_t		*pmodel;
+
+static vec3_t		alias_forward, alias_right, alias_up;
+
+static maliasskindesc_t	*pskindesc;
+
+int				r_amodels_drawn;
+int				a_skinwidth;
+int				r_anumverts;
+
+float	aliastransform[3][4];
+
+typedef struct {
+	int	index0;
+	int	index1;
+} aedge_t;
+
+static aedge_t	aedges[12] = {
+{0, 1}, {1, 2}, {2, 3}, {3, 0},
+{4, 5}, {5, 6}, {6, 7}, {7, 4},
+{0, 5}, {1, 4}, {2, 7}, {3, 6}
+};
+
+#define NUMVERTEXNORMALS	162
+
+float	r_avertexnormals[NUMVERTEXNORMALS][3] = {
+#include "anorms.h"
+};
+
+void R_AliasTransformAndProjectFinalVerts (finalvert_t *fv,
+	stvert_t *pstverts);
+void R_AliasSetUpTransform (int trivial_accept);
+void R_AliasTransformVector (vec3_t in, vec3_t out);
+void R_AliasTransformFinalVert (finalvert_t *fv, auxvert_t *av,
+	trivertx_t *pverts, stvert_t *pstverts);
+void R_AliasProjectFinalVert (finalvert_t *fv, auxvert_t *av);
+
+
+/*
+================
+R_AliasCheckBBox
+================
+*/
+qboolean R_AliasCheckBBox (void)
+{
+	int					i, flags, frame, numv;
+	aliashdr_t			*pahdr;
+	float				zi, basepts[8][3], v0, v1, frac;
+	finalvert_t			*pv0, *pv1, viewpts[16];
+	auxvert_t			*pa0, *pa1, viewaux[16];
+	maliasframedesc_t	*pframedesc;
+	qboolean			zclipped, zfullyclipped;
+	unsigned			anyclip, allclip;
+	int					minz;
+	
+// expand, rotate, and translate points into worldspace
+
+	currententity->trivial_accept = 0;
+	pmodel = currententity->model;
+	pahdr = Mod_Extradata (pmodel);
+	pmdl = (mdl_t *)((byte *)pahdr + pahdr->model);
+
+	R_AliasSetUpTransform (0);
+
+// construct the base bounding box for this frame
+	frame = currententity->frame;
+// TODO: don't repeat this check when drawing?
+	if ((frame >= pmdl->numframes) || (frame < 0))
+	{
+		Con_DPrintf ("No such frame %d %s\n", frame,
+				pmodel->name);
+		frame = 0;
+	}
+
+	pframedesc = &pahdr->frames[frame];
+
+// x worldspace coordinates
+	basepts[0][0] = basepts[1][0] = basepts[2][0] = basepts[3][0] =
+			(float)pframedesc->bboxmin.v[0];
+	basepts[4][0] = basepts[5][0] = basepts[6][0] = basepts[7][0] =
+			(float)pframedesc->bboxmax.v[0];
+
+// y worldspace coordinates
+	basepts[0][1] = basepts[3][1] = basepts[5][1] = basepts[6][1] =
+			(float)pframedesc->bboxmin.v[1];
+	basepts[1][1] = basepts[2][1] = basepts[4][1] = basepts[7][1] =
+			(float)pframedesc->bboxmax.v[1];
+
+// z worldspace coordinates
+	basepts[0][2] = basepts[1][2] = basepts[4][2] = basepts[5][2] =
+			(float)pframedesc->bboxmin.v[2];
+	basepts[2][2] = basepts[3][2] = basepts[6][2] = basepts[7][2] =
+			(float)pframedesc->bboxmax.v[2];
+
+	zclipped = false;
+	zfullyclipped = true;
+
+	minz = 9999;
+	for (i=0; i<8 ; i++)
+	{
+		R_AliasTransformVector  (&basepts[i][0], &viewaux[i].fv[0]);
+
+		if (viewaux[i].fv[2] < ALIAS_Z_CLIP_PLANE)
+		{
+		// we must clip points that are closer than the near clip plane
+			viewpts[i].flags = ALIAS_Z_CLIP;
+			zclipped = true;
+		}
+		else
+		{
+			if (viewaux[i].fv[2] < minz)
+				minz = viewaux[i].fv[2];
+			viewpts[i].flags = 0;
+			zfullyclipped = false;
+		}
+	}
+
+	
+	if (zfullyclipped)
+	{
+		return false;	// everything was near-z-clipped
+	}
+
+	numv = 8;
+
+	if (zclipped)
+	{
+	// organize points by edges, use edges to get new points (possible trivial
+	// reject)
+		for (i=0 ; i<12 ; i++)
+		{
+		// edge endpoints
+			pv0 = &viewpts[aedges[i].index0];
+			pv1 = &viewpts[aedges[i].index1];
+			pa0 = &viewaux[aedges[i].index0];
+			pa1 = &viewaux[aedges[i].index1];
+
+		// if one end is clipped and the other isn't, make a new point
+			if (pv0->flags ^ pv1->flags)
+			{
+				frac = (ALIAS_Z_CLIP_PLANE - pa0->fv[2]) /
+					   (pa1->fv[2] - pa0->fv[2]);
+				viewaux[numv].fv[0] = pa0->fv[0] +
+						(pa1->fv[0] - pa0->fv[0]) * frac;
+				viewaux[numv].fv[1] = pa0->fv[1] +
+						(pa1->fv[1] - pa0->fv[1]) * frac;
+				viewaux[numv].fv[2] = ALIAS_Z_CLIP_PLANE;
+				viewpts[numv].flags = 0;
+				numv++;
+			}
+		}
+	}
+
+// project the vertices that remain after clipping
+	anyclip = 0;
+	allclip = ALIAS_XY_CLIP_MASK;
+
+// TODO: probably should do this loop in ASM, especially if we use floats
+	for (i=0 ; i<numv ; i++)
+	{
+	// we don't need to bother with vertices that were z-clipped
+		if (viewpts[i].flags & ALIAS_Z_CLIP)
+			continue;
+
+		zi = 1.0 / viewaux[i].fv[2];
+
+	// FIXME: do with chop mode in ASM, or convert to float
+		v0 = (viewaux[i].fv[0] * xscale * zi) + xcenter;
+		v1 = (viewaux[i].fv[1] * yscale * zi) + ycenter;
+
+		flags = 0;
+
+		if (v0 < r_refdef.fvrectx)
+			flags |= ALIAS_LEFT_CLIP;
+		if (v1 < r_refdef.fvrecty)
+			flags |= ALIAS_TOP_CLIP;
+		if (v0 > r_refdef.fvrectright)
+			flags |= ALIAS_RIGHT_CLIP;
+		if (v1 > r_refdef.fvrectbottom)
+			flags |= ALIAS_BOTTOM_CLIP;
+
+		anyclip |= flags;
+		allclip &= flags;
+	}
+
+	if (allclip)
+		return false;	// trivial reject off one side
+
+	currententity->trivial_accept = !anyclip & !zclipped;
+
+	if (currententity->trivial_accept)
+	{
+		if (minz > (r_aliastransition + (pmdl->size * r_resfudge)))
+		{
+			currententity->trivial_accept |= 2;
+		}
+	}
+
+	return true;
+}
+
+
+/*
+================
+R_AliasTransformVector
+================
+*/
+void R_AliasTransformVector (vec3_t in, vec3_t out)
+{
+	out[0] = DotProduct(in, aliastransform[0]) + aliastransform[0][3];
+	out[1] = DotProduct(in, aliastransform[1]) + aliastransform[1][3];
+	out[2] = DotProduct(in, aliastransform[2]) + aliastransform[2][3];
+}
+
+
+/*
+================
+R_AliasPreparePoints
+
+General clipped case
+================
+*/
+void R_AliasPreparePoints (void)
+{
+	int			i;
+	stvert_t	*pstverts;
+	finalvert_t	*fv;
+	auxvert_t	*av;
+	mtriangle_t	*ptri;
+	finalvert_t	*pfv[3];
+
+	pstverts = (stvert_t *)((byte *)paliashdr + paliashdr->stverts);
+	r_anumverts = pmdl->numverts;
+ 	fv = pfinalverts;
+	av = pauxverts;
+
+	for (i=0 ; i<r_anumverts ; i++, fv++, av++, r_apverts++, pstverts++)
+	{
+		R_AliasTransformFinalVert (fv, av, r_apverts, pstverts);
+		if (av->fv[2] < ALIAS_Z_CLIP_PLANE)
+			fv->flags |= ALIAS_Z_CLIP;
+		else
+		{
+			 R_AliasProjectFinalVert (fv, av);
+
+			if (fv->v[0] < r_refdef.aliasvrect.x)
+				fv->flags |= ALIAS_LEFT_CLIP;
+			if (fv->v[1] < r_refdef.aliasvrect.y)
+				fv->flags |= ALIAS_TOP_CLIP;
+			if (fv->v[0] > r_refdef.aliasvrectright)
+				fv->flags |= ALIAS_RIGHT_CLIP;
+			if (fv->v[1] > r_refdef.aliasvrectbottom)
+				fv->flags |= ALIAS_BOTTOM_CLIP;	
+		}
+	}
+
+//
+// clip and draw all triangles
+//
+	r_affinetridesc.numtriangles = 1;
+
+	ptri = (mtriangle_t *)((byte *)paliashdr + paliashdr->triangles);
+	for (i=0 ; i<pmdl->numtris ; i++, ptri++)
+	{
+		pfv[0] = &pfinalverts[ptri->vertindex[0]];
+		pfv[1] = &pfinalverts[ptri->vertindex[1]];
+		pfv[2] = &pfinalverts[ptri->vertindex[2]];
+
+		if ( pfv[0]->flags & pfv[1]->flags & pfv[2]->flags & (ALIAS_XY_CLIP_MASK | ALIAS_Z_CLIP) )
+			continue;		// completely clipped
+		
+		if ( ! ( (pfv[0]->flags | pfv[1]->flags | pfv[2]->flags) &
+			(ALIAS_XY_CLIP_MASK | ALIAS_Z_CLIP) ) )
+		{	// totally unclipped
+			r_affinetridesc.pfinalverts = pfinalverts;
+			r_affinetridesc.ptriangles = ptri;
+			D_PolysetDraw ();
+		}
+		else		
+		{	// partially clipped
+			R_AliasClipTriangle (ptri);
+		}
+	}
+}
+
+
+/*
+================
+R_AliasSetUpTransform
+================
+*/
+void R_AliasSetUpTransform (int trivial_accept)
+{
+	int				i;
+	float			rotationmatrix[3][4], t2matrix[3][4];
+	static float	tmatrix[3][4];
+	static float	viewmatrix[3][4];
+	vec3_t			angles;
+
+// TODO: should really be stored with the entity instead of being reconstructed
+// TODO: should use a look-up table
+// TODO: could cache lazily, stored in the entity
+
+	angles[ROLL] = currententity->angles[ROLL];
+	angles[PITCH] = -currententity->angles[PITCH];
+	angles[YAW] = currententity->angles[YAW];
+	AngleVectors (angles, alias_forward, alias_right, alias_up);
+
+	tmatrix[0][0] = pmdl->scale[0];
+	tmatrix[1][1] = pmdl->scale[1];
+	tmatrix[2][2] = pmdl->scale[2];
+
+	tmatrix[0][3] = pmdl->scale_origin[0];
+	tmatrix[1][3] = pmdl->scale_origin[1];
+	tmatrix[2][3] = pmdl->scale_origin[2];
+
+// TODO: can do this with simple matrix rearrangement
+
+	for (i=0 ; i<3 ; i++)
+	{
+		t2matrix[i][0] = alias_forward[i];
+		t2matrix[i][1] = -alias_right[i];
+		t2matrix[i][2] = alias_up[i];
+	}
+
+	t2matrix[0][3] = -modelorg[0];
+	t2matrix[1][3] = -modelorg[1];
+	t2matrix[2][3] = -modelorg[2];
+
+// FIXME: can do more efficiently than full concatenation
+	R_ConcatTransforms (t2matrix, tmatrix, rotationmatrix);
+
+// TODO: should be global, set when vright, etc., set
+	VectorCopy (vright, viewmatrix[0]);
+	VectorCopy (vup, viewmatrix[1]);
+	VectorInverse (viewmatrix[1]);
+	VectorCopy (vpn, viewmatrix[2]);
+
+//	viewmatrix[0][3] = 0;
+//	viewmatrix[1][3] = 0;
+//	viewmatrix[2][3] = 0;
+
+	R_ConcatTransforms (viewmatrix, rotationmatrix, aliastransform);
+
+// do the scaling up of x and y to screen coordinates as part of the transform
+// for the unclipped case (it would mess up clipping in the clipped case).
+// Also scale down z, so 1/z is scaled 31 bits for free, and scale down x and y
+// correspondingly so the projected x and y come out right
+// FIXME: make this work for clipped case too?
+	if (trivial_accept)
+	{
+		for (i=0 ; i<4 ; i++)
+		{
+			aliastransform[0][i] *= aliasxscale *
+					(1.0 / ((float)0x8000 * 0x10000));
+			aliastransform[1][i] *= aliasyscale *
+					(1.0 / ((float)0x8000 * 0x10000));
+			aliastransform[2][i] *= 1.0 / ((float)0x8000 * 0x10000);
+
+		}
+	}
+}
+
+
+/*
+================
+R_AliasTransformFinalVert
+================
+*/
+void R_AliasTransformFinalVert (finalvert_t *fv, auxvert_t *av,
+	trivertx_t *pverts, stvert_t *pstverts)
+{
+	int		temp;
+	float	lightcos, *plightnormal;
+
+	av->fv[0] = DotProduct(pverts->v, aliastransform[0]) +
+			aliastransform[0][3];
+	av->fv[1] = DotProduct(pverts->v, aliastransform[1]) +
+			aliastransform[1][3];
+	av->fv[2] = DotProduct(pverts->v, aliastransform[2]) +
+			aliastransform[2][3];
+
+	fv->v[2] = pstverts->s;
+	fv->v[3] = pstverts->t;
+
+	fv->flags = pstverts->onseam;
+
+// lighting
+	plightnormal = r_avertexnormals[pverts->lightnormalindex];
+	lightcos = DotProduct (plightnormal, r_plightvec);
+	temp = r_ambientlight;
+
+	if (lightcos < 0)
+	{
+		temp += (int)(r_shadelight * lightcos);
+
+	// clamp; because we limited the minimum ambient and shading light, we
+	// don't have to clamp low light, just bright
+		if (temp < 0)
+			temp = 0;
+	}
+
+	fv->v[4] = temp;
+}
+
+
+#if	!id386
+
+/*
+================
+R_AliasTransformAndProjectFinalVerts
+================
+*/
+void R_AliasTransformAndProjectFinalVerts (finalvert_t *fv, stvert_t *pstverts)
+{
+	int			i, temp;
+	float		lightcos, *plightnormal, zi;
+	trivertx_t	*pverts;
+
+	pverts = r_apverts;
+
+	for (i=0 ; i<r_anumverts ; i++, fv++, pverts++, pstverts++)
+	{
+	// transform and project
+		zi = 1.0 / (DotProduct(pverts->v, aliastransform[2]) +
+				aliastransform[2][3]);
+
+	// x, y, and z are scaled down by 1/2**31 in the transform, so 1/z is
+	// scaled up by 1/2**31, and the scaling cancels out for x and y in the
+	// projection
+		fv->v[5] = zi;
+
+		fv->v[0] = ((DotProduct(pverts->v, aliastransform[0]) +
+				aliastransform[0][3]) * zi) + aliasxcenter;
+		fv->v[1] = ((DotProduct(pverts->v, aliastransform[1]) +
+				aliastransform[1][3]) * zi) + aliasycenter;
+
+		fv->v[2] = pstverts->s;
+		fv->v[3] = pstverts->t;
+		fv->flags = pstverts->onseam;
+
+	// lighting
+		plightnormal = r_avertexnormals[pverts->lightnormalindex];
+		lightcos = DotProduct (plightnormal, r_plightvec);
+		temp = r_ambientlight;
+
+		if (lightcos < 0)
+		{
+			temp += (int)(r_shadelight * lightcos);
+
+		// clamp; because we limited the minimum ambient and shading light, we
+		// don't have to clamp low light, just bright
+			if (temp < 0)
+				temp = 0;
+		}
+
+		fv->v[4] = temp;
+	}
+}
+
+#endif
+
+
+/*
+================
+R_AliasProjectFinalVert
+================
+*/
+void R_AliasProjectFinalVert (finalvert_t *fv, auxvert_t *av)
+{
+	float	zi;
+
+// project points
+	zi = 1.0 / av->fv[2];
+
+	fv->v[5] = zi * ziscale;
+
+	fv->v[0] = (av->fv[0] * aliasxscale * zi) + aliasxcenter;
+	fv->v[1] = (av->fv[1] * aliasyscale * zi) + aliasycenter;
+}
+
+
+/*
+================
+R_AliasPrepareUnclippedPoints
+================
+*/
+void R_AliasPrepareUnclippedPoints (void)
+{
+	stvert_t	*pstverts;
+	finalvert_t	*fv;
+
+	pstverts = (stvert_t *)((byte *)paliashdr + paliashdr->stverts);
+	r_anumverts = pmdl->numverts;
+// FIXME: just use pfinalverts directly?
+	fv = pfinalverts;
+
+	R_AliasTransformAndProjectFinalVerts (fv, pstverts);
+
+	if (r_affinetridesc.drawtype)
+		D_PolysetDrawFinalVerts (fv, r_anumverts);
+
+	r_affinetridesc.pfinalverts = pfinalverts;
+	r_affinetridesc.ptriangles = (mtriangle_t *)
+			((byte *)paliashdr + paliashdr->triangles);
+	r_affinetridesc.numtriangles = pmdl->numtris;
+
+	D_PolysetDraw ();
+}
+
+/*
+===============
+R_AliasSetupSkin
+===============
+*/
+void R_AliasSetupSkin (void)
+{
+	int					skinnum;
+	int					i, numskins;
+	maliasskingroup_t	*paliasskingroup;
+	float				*pskinintervals, fullskininterval;
+	float				skintargettime, skintime;
+
+	skinnum = currententity->skinnum;
+	if ((skinnum >= pmdl->numskins) || (skinnum < 0))
+	{
+		Con_DPrintf ("R_AliasSetupSkin: no such skin # %d\n", skinnum);
+		skinnum = 0;
+	}
+
+	pskindesc = ((maliasskindesc_t *)
+			((byte *)paliashdr + paliashdr->skindesc)) + skinnum;
+	a_skinwidth = pmdl->skinwidth;
+
+	if (pskindesc->type == ALIAS_SKIN_GROUP)
+	{
+		paliasskingroup = (maliasskingroup_t *)((byte *)paliashdr +
+				pskindesc->skin);
+		pskinintervals = (float *)
+				((byte *)paliashdr + paliasskingroup->intervals);
+		numskins = paliasskingroup->numskins;
+		fullskininterval = pskinintervals[numskins-1];
+	
+		skintime = cl.time + currententity->syncbase;
+	
+	// when loading in Mod_LoadAliasSkinGroup, we guaranteed all interval
+	// values are positive, so we don't have to worry about division by 0
+		skintargettime = skintime -
+				((int)(skintime / fullskininterval)) * fullskininterval;
+	
+		for (i=0 ; i<(numskins-1) ; i++)
+		{
+			if (pskinintervals[i] > skintargettime)
+				break;
+		}
+	
+		pskindesc = &paliasskingroup->skindescs[i];
+	}
+
+	r_affinetridesc.pskindesc = pskindesc;
+	r_affinetridesc.pskin = (void *)((byte *)paliashdr + pskindesc->skin);
+	r_affinetridesc.skinwidth = a_skinwidth;
+	r_affinetridesc.seamfixupX16 =  (a_skinwidth >> 1) << 16;
+	r_affinetridesc.skinheight = pmdl->skinheight;
+
+	if (currententity->scoreboard)
+	{
+		byte	*base;
+
+		if (!currententity->scoreboard->skin)
+			Skin_Find (currententity->scoreboard);
+		base = Skin_Cache (currententity->scoreboard->skin);
+		if (base)
+		{
+			r_affinetridesc.pskin = base;
+			r_affinetridesc.skinwidth = 320;
+			r_affinetridesc.skinheight = 200;
+		}
+	}
+}
+
+/*
+================
+R_AliasSetupLighting
+================
+*/
+void R_AliasSetupLighting (alight_t *plighting)
+{
+
+// guarantee that no vertex will ever be lit below LIGHT_MIN, so we don't have
+// to clamp off the bottom
+	r_ambientlight = plighting->ambientlight;
+
+	if (r_ambientlight < LIGHT_MIN)
+		r_ambientlight = LIGHT_MIN;
+
+	r_ambientlight = (255 - r_ambientlight) << VID_CBITS;
+
+	if (r_ambientlight < LIGHT_MIN)
+		r_ambientlight = LIGHT_MIN;
+
+	r_shadelight = plighting->shadelight;
+
+	if (r_shadelight < 0)
+		r_shadelight = 0;
+
+	r_shadelight *= VID_GRADES;
+
+// rotate the lighting vector into the model's frame of reference
+	r_plightvec[0] = DotProduct (plighting->plightvec, alias_forward);
+	r_plightvec[1] = -DotProduct (plighting->plightvec, alias_right);
+	r_plightvec[2] = DotProduct (plighting->plightvec, alias_up);
+}
+
+/*
+=================
+R_AliasSetupFrame
+
+set r_apverts
+=================
+*/
+void R_AliasSetupFrame (void)
+{
+	int				frame;
+	int				i, numframes;
+	maliasgroup_t	*paliasgroup;
+	float			*pintervals, fullinterval, targettime, time;
+
+	frame = currententity->frame;
+	if ((frame >= pmdl->numframes) || (frame < 0))
+	{
+		Con_DPrintf ("R_AliasSetupFrame: no such frame %d\n", frame);
+		frame = 0;
+	}
+
+	if (paliashdr->frames[frame].type == ALIAS_SINGLE)
+	{
+		r_apverts = (trivertx_t *)
+				((byte *)paliashdr + paliashdr->frames[frame].frame);
+		return;
+	}
+	
+	paliasgroup = (maliasgroup_t *)
+				((byte *)paliashdr + paliashdr->frames[frame].frame);
+	pintervals = (float *)((byte *)paliashdr + paliasgroup->intervals);
+	numframes = paliasgroup->numframes;
+	fullinterval = pintervals[numframes-1];
+
+	time = cl.time + currententity->syncbase;
+
+//
+// when loading in Mod_LoadAliasGroup, we guaranteed all interval values
+// are positive, so we don't have to worry about division by 0
+//
+	targettime = time - ((int)(time / fullinterval)) * fullinterval;
+
+	for (i=0 ; i<(numframes-1) ; i++)
+	{
+		if (pintervals[i] > targettime)
+			break;
+	}
+
+	r_apverts = (trivertx_t *)
+				((byte *)paliashdr + paliasgroup->frames[i].frame);
+}
+
+
+/*
+================
+R_AliasDrawModel
+================
+*/
+void R_AliasDrawModel (alight_t *plighting)
+{
+	finalvert_t		finalverts[MAXALIASVERTS +
+						((CACHE_SIZE - 1) / sizeof(finalvert_t)) + 1];
+	auxvert_t		auxverts[MAXALIASVERTS];
+
+	r_amodels_drawn++;
+
+// cache align
+	pfinalverts = (finalvert_t *)
+			(((long)&finalverts[0] + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1));
+	pauxverts = &auxverts[0];
+
+	paliashdr = (aliashdr_t *)Mod_Extradata (currententity->model);
+	pmdl = (mdl_t *)((byte *)paliashdr + paliashdr->model);
+
+	R_AliasSetupSkin ();
+	R_AliasSetUpTransform (currententity->trivial_accept);
+	R_AliasSetupLighting (plighting);
+	R_AliasSetupFrame ();
+
+	if (!currententity->colormap)
+		Sys_Error ("R_AliasDrawModel: !currententity->colormap");
+
+	r_affinetridesc.drawtype = (currententity->trivial_accept == 3) &&
+			r_recursiveaffinetriangles;
+
+	if (r_affinetridesc.drawtype)
+	{
+		D_PolysetUpdateTables ();		// FIXME: precalc...
+	}
+	else
+	{
+#if id386
+		D_Aff8Patch (currententity->colormap);
+#endif
+	}
+
+	acolormap = currententity->colormap;
+
+	if (currententity != &cl.viewent)
+		ziscale = (float)0x8000 * (float)0x10000;
+	else
+		ziscale = (float)0x8000 * (float)0x10000 * 3.0;
+
+	if (currententity->trivial_accept)
+		R_AliasPrepareUnclippedPoints ();
+	else
+		R_AliasPreparePoints ();
+}
+
--- /dev/null
+++ b/QW/client/r_aliasa.asm
@@ -1,0 +1,354 @@
+ .386P
+ .model FLAT
+ externdef _d_zistepu:dword
+ externdef _d_pzbuffer:dword
+ externdef _d_zistepv:dword
+ externdef _d_zrowbytes:dword
+ externdef _d_ziorigin:dword
+ externdef _r_turb_s:dword
+ externdef _r_turb_t:dword
+ externdef _r_turb_pdest:dword
+ externdef _r_turb_spancount:dword
+ externdef _r_turb_turb:dword
+ externdef _r_turb_pbase:dword
+ externdef _r_turb_sstep:dword
+ externdef _r_turb_tstep:dword
+ externdef _r_bmodelactive:dword
+ externdef _d_sdivzstepu:dword
+ externdef _d_tdivzstepu:dword
+ externdef _d_sdivzstepv:dword
+ externdef _d_tdivzstepv:dword
+ externdef _d_sdivzorigin:dword
+ externdef _d_tdivzorigin:dword
+ externdef _sadjust:dword
+ externdef _tadjust:dword
+ externdef _bbextents:dword
+ externdef _bbextentt:dword
+ externdef _cacheblock:dword
+ externdef _d_viewbuffer:dword
+ externdef _cachewidth:dword
+ externdef _d_pzbuffer:dword
+ externdef _d_zrowbytes:dword
+ externdef _d_zwidth:dword
+ externdef _d_scantable:dword
+ externdef _r_lightptr:dword
+ externdef _r_numvblocks:dword
+ externdef _prowdestbase:dword
+ externdef _pbasesource:dword
+ externdef _r_lightwidth:dword
+ externdef _lightright:dword
+ externdef _lightrightstep:dword
+ externdef _lightdeltastep:dword
+ externdef _lightdelta:dword
+ externdef _lightright:dword
+ externdef _lightdelta:dword
+ externdef _sourcetstep:dword
+ externdef _surfrowbytes:dword
+ externdef _lightrightstep:dword
+ externdef _lightdeltastep:dword
+ externdef _r_sourcemax:dword
+ externdef _r_stepback:dword
+ externdef _colormap:dword
+ externdef _blocksize:dword
+ externdef _sourcesstep:dword
+ externdef _lightleft:dword
+ externdef _blockdivshift:dword
+ externdef _blockdivmask:dword
+ externdef _lightleftstep:dword
+ externdef _r_origin:dword
+ externdef _r_ppn:dword
+ externdef _r_pup:dword
+ externdef _r_pright:dword
+ externdef _ycenter:dword
+ externdef _xcenter:dword
+ externdef _d_vrectbottom_particle:dword
+ externdef _d_vrectright_particle:dword
+ externdef _d_vrecty:dword
+ externdef _d_vrectx:dword
+ externdef _d_pix_shift:dword
+ externdef _d_pix_min:dword
+ externdef _d_pix_max:dword
+ externdef _d_y_aspect_shift:dword
+ externdef _screenwidth:dword
+ externdef _vright:dword
+ externdef _vup:dword
+ externdef _vpn:dword
+ externdef _BOPS_Error:dword
+ externdef _snd_scaletable:dword
+ externdef _paintbuffer:dword
+ externdef _snd_linear_count:dword
+ externdef _snd_p:dword
+ externdef _snd_vol:dword
+ externdef _snd_out:dword
+ externdef _r_leftclipped:dword
+ externdef _r_leftenter:dword
+ externdef _r_rightclipped:dword
+ externdef _r_rightenter:dword
+ externdef _modelorg:dword
+ externdef _xscale:dword
+ externdef _r_refdef:dword
+ externdef _yscale:dword
+ externdef _r_leftexit:dword
+ externdef _r_rightexit:dword
+ externdef _r_lastvertvalid:dword
+ externdef _cacheoffset:dword
+ externdef _newedges:dword
+ externdef _removeedges:dword
+ externdef _r_pedge:dword
+ externdef _r_framecount:dword
+ externdef _r_u1:dword
+ externdef _r_emitted:dword
+ externdef _edge_p:dword
+ externdef _surface_p:dword
+ externdef _surfaces:dword
+ externdef _r_lzi1:dword
+ externdef _r_v1:dword
+ externdef _r_ceilv1:dword
+ externdef _r_nearzi:dword
+ externdef _r_nearzionly:dword
+ externdef _edge_aftertail:dword
+ externdef _edge_tail:dword
+ externdef _current_iv:dword
+ externdef _edge_head_u_shift20:dword
+ externdef _span_p:dword
+ externdef _edge_head:dword
+ externdef _fv:dword
+ externdef _edge_tail_u_shift20:dword
+ externdef _r_apverts:dword
+ externdef _r_anumverts:dword
+ externdef _aliastransform:dword
+ externdef _r_avertexnormals:dword
+ externdef _r_plightvec:dword
+ externdef _r_ambientlight:dword
+ externdef _r_shadelight:dword
+ externdef _aliasxcenter:dword
+ externdef _aliasycenter:dword
+ externdef _a_sstepxfrac:dword
+ externdef _r_affinetridesc:dword
+ externdef _acolormap:dword
+ externdef _d_pcolormap:dword
+ externdef _r_affinetridesc:dword
+ externdef _d_sfrac:dword
+ externdef _d_ptex:dword
+ externdef _d_pedgespanpackage:dword
+ externdef _d_tfrac:dword
+ externdef _d_light:dword
+ externdef _d_zi:dword
+ externdef _d_pdest:dword
+ externdef _d_pz:dword
+ externdef _d_aspancount:dword
+ externdef _erroradjustup:dword
+ externdef _errorterm:dword
+ externdef _d_xdenom:dword
+ externdef _r_p0:dword
+ externdef _r_p1:dword
+ externdef _r_p2:dword
+ externdef _a_tstepxfrac:dword
+ externdef _r_sstepx:dword
+ externdef _r_tstepx:dword
+ externdef _a_ststepxwhole:dword
+ externdef _zspantable:dword
+ externdef _skintable:dword
+ externdef _r_zistepx:dword
+ externdef _erroradjustdown:dword
+ externdef _d_countextrastep:dword
+ externdef _ubasestep:dword
+ externdef _a_ststepxwhole:dword
+ externdef _a_tstepxfrac:dword
+ externdef _r_lstepx:dword
+ externdef _a_spans:dword
+ externdef _erroradjustdown:dword
+ externdef _d_pdestextrastep:dword
+ externdef _d_pzextrastep:dword
+ externdef _d_sfracextrastep:dword
+ externdef _d_ptexextrastep:dword
+ externdef _d_countextrastep:dword
+ externdef _d_tfracextrastep:dword
+ externdef _d_lightextrastep:dword
+ externdef _d_ziextrastep:dword
+ externdef _d_pdestbasestep:dword
+ externdef _d_pzbasestep:dword
+ externdef _d_sfracbasestep:dword
+ externdef _d_ptexbasestep:dword
+ externdef _ubasestep:dword
+ externdef _d_tfracbasestep:dword
+ externdef _d_lightbasestep:dword
+ externdef _d_zibasestep:dword
+ externdef _zspantable:dword
+ externdef _r_lstepy:dword
+ externdef _r_sstepy:dword
+ externdef _r_tstepy:dword
+ externdef _r_zistepy:dword
+ externdef _D_PolysetSetEdgeTable:dword
+ externdef _D_RasterizeAliasPolySmooth:dword
+ externdef float_point5:dword
+ externdef Float2ToThe31nd:dword
+ externdef izistep:dword
+ externdef izi:dword
+ externdef FloatMinus2ToThe31nd:dword
+ externdef float_1:dword
+ externdef float_particle_z_clip:dword
+ externdef float_minus_1:dword
+ externdef float_0:dword
+ externdef fp_16:dword
+ externdef fp_64k:dword
+ externdef fp_1m:dword
+ externdef fp_1m_minus_1:dword
+ externdef fp_8:dword
+ externdef entryvec_table:dword
+ externdef advancetable:dword
+ externdef sstep:dword
+ externdef tstep:dword
+ externdef pspantemp:dword
+ externdef counttemp:dword
+ externdef jumptemp:dword
+ externdef reciprocal_table:dword
+ externdef DP_Count:dword
+ externdef DP_u:dword
+ externdef DP_v:dword
+ externdef DP_32768:dword
+ externdef DP_Color:dword
+ externdef DP_Pix:dword
+ externdef DP_EntryTable:dword
+ externdef pbase:dword
+ externdef s:dword
+ externdef t:dword
+ externdef sfracf:dword
+ externdef tfracf:dword
+ externdef snext:dword
+ externdef tnext:dword
+ externdef spancountminus1:dword
+ externdef zi16stepu:dword
+ externdef sdivz16stepu:dword
+ externdef tdivz16stepu:dword
+ externdef zi8stepu:dword
+ externdef sdivz8stepu:dword
+ externdef tdivz8stepu:dword
+ externdef reciprocal_table_16:dword
+ externdef entryvec_table_16:dword
+ externdef ceil_cw:dword
+ externdef single_cw:dword
+ externdef fp_64kx64k:dword
+ externdef pz:dword
+ externdef spr8entryvec_table:dword
+_DATA SEGMENT
+Lfloat_1 dd 1.0
+Ltemp dd 0
+Lcoords dd 0, 0, 0
+_DATA ENDS
+_TEXT SEGMENT
+ public _R_AliasTransformAndProjectFinalVerts
+_R_AliasTransformAndProjectFinalVerts:
+ push ebp
+ push edi
+ push esi
+ mov esi,ds:dword ptr[_r_apverts]
+ mov ebp,ds:dword ptr[12+8+esp]
+ mov edi,ds:dword ptr[12+4+esp]
+ mov ecx,ds:dword ptr[_r_anumverts]
+ sub edx,edx
+Lloop:
+ mov dl,ds:byte ptr[esi]
+ mov ds:byte ptr[Lcoords],dl
+ fild ds:dword ptr[Lcoords]
+ mov dl,ds:byte ptr[1+esi]
+ mov ds:byte ptr[Lcoords+4],dl
+ fild ds:dword ptr[Lcoords+4]
+ mov dl,ds:byte ptr[2+esi]
+ mov ds:byte ptr[Lcoords+8],dl
+ fild ds:dword ptr[Lcoords+8]
+ fld st(2)
+ fmul ds:dword ptr[_aliastransform+32]
+ fld st(2)
+ fmul ds:dword ptr[_aliastransform+36]
+ fxch st(1)
+ fadd ds:dword ptr[_aliastransform+44]
+ fld st(2)
+ fmul ds:dword ptr[_aliastransform+40]
+ fxch st(1)
+ faddp st(2),st(0)
+ mov dl,ds:byte ptr[3+esi]
+ mov eax,ds:dword ptr[4+ebp]
+ mov ds:dword ptr[0+8+edi],eax
+ faddp st(1),st(0)
+ mov eax,ds:dword ptr[8+ebp]
+ mov ds:dword ptr[0+12+edi],eax
+ fdivr ds:dword ptr[Lfloat_1]
+ mov eax,ds:dword ptr[0+ebp]
+ mov ds:dword ptr[24+edi],eax
+ mov eax,ds:dword ptr[32+edi]
+ mov eax,ds:dword ptr[12+ebp]
+ mov eax,ds:dword ptr[4+esi]
+ lea eax,ds:dword ptr[edx+edx*2]
+ fxch st(3)
+ fld ds:dword ptr[_r_avertexnormals+eax*4]
+ fmul ds:dword ptr[_r_plightvec]
+ fld ds:dword ptr[_r_avertexnormals+4+eax*4]
+ fmul ds:dword ptr[_r_plightvec+4]
+ fld ds:dword ptr[_r_avertexnormals+8+eax*4]
+ fmul ds:dword ptr[_r_plightvec+8]
+ fxch st(1)
+ faddp st(2),st(0)
+ fld st(2)
+ fmul ds:dword ptr[_aliastransform+0]
+ fxch st(2)
+ faddp st(1),st(0)
+ fst ds:dword ptr[Ltemp]
+ mov eax,ds:dword ptr[_r_ambientlight]
+ mov dl,ds:byte ptr[Ltemp+3]
+ test dl,080h
+ jz Lsavelight
+ fmul ds:dword ptr[_r_shadelight]
+ fistp ds:dword ptr[Ltemp]
+ add eax,ds:dword ptr[Ltemp]
+ jns Lp1
+ sub eax,eax
+Lp1:
+ fxch st(1)
+ fmul ds:dword ptr[_aliastransform+16]
+ fxch st(3)
+ fld st(0)
+ fmul ds:dword ptr[_aliastransform+4]
+ fxch st(1)
+ mov ds:dword ptr[0+16+edi],eax
+ fmul ds:dword ptr[_aliastransform+20]
+ fxch st(2)
+ fadd ds:dword ptr[_aliastransform+12]
+ fxch st(4)
+ fadd ds:dword ptr[_aliastransform+28]
+ fxch st(3)
+ fld st(0)
+ fmul ds:dword ptr[_aliastransform+8]
+ fxch st(1)
+ fmul ds:dword ptr[_aliastransform+24]
+ fxch st(5)
+ faddp st(2),st(0)
+ fxch st(3)
+ faddp st(2),st(0)
+ add esi,4
+ faddp st(2),st(0)
+ faddp st(2),st(0)
+ add ebp,12
+ fmul st(0),st(2)
+ fxch st(1)
+ fmul st(0),st(2)
+ fxch st(1)
+ fadd ds:dword ptr[_aliasxcenter]
+ fxch st(1)
+ fadd ds:dword ptr[_aliasycenter]
+ fxch st(2)
+ fistp ds:dword ptr[0+20+edi]
+ fistp ds:dword ptr[0+0+edi]
+ fistp ds:dword ptr[0+4+edi]
+ add edi,32
+ dec ecx
+ jnz Lloop
+ pop esi
+ pop edi
+ pop ebp
+ ret
+Lsavelight:
+ fstp st(0)
+ jmp Lp1
+_TEXT ENDS
+ END
--- /dev/null
+++ b/QW/client/r_aliasa.s
@@ -1,0 +1,237 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+//
+// r_aliasa.s
+// x86 assembly-language Alias model transform and project code.
+//
+
+#include "asm_i386.h"
+#include "quakeasm.h"
+#include "asm_draw.h"
+#include "d_ifacea.h"
+
+#if id386
+
+	.data
+
+Lfloat_1:	.single	1.0
+Ltemp:		.long	0
+Lcoords:	.long	0, 0, 0
+
+	.text
+
+#define fv			12+4
+#define pstverts	12+8
+
+.globl C(R_AliasTransformAndProjectFinalVerts)
+C(R_AliasTransformAndProjectFinalVerts):
+	pushl	%ebp				// preserve caller's stack frame
+	pushl	%edi
+	pushl	%esi				// preserve register variables
+
+//	int			i, temp;
+//	float		lightcos, *plightnormal, zi;
+//	trivertx_t	*pverts;
+
+//	pverts = r_apverts;
+	movl	C(r_apverts),%esi
+
+//	for (i=0 ; i<r_anumverts ; i++, fv++, pverts++, pstverts++)
+//	{
+	movl	pstverts(%esp),%ebp
+	movl	fv(%esp),%edi
+	movl	C(r_anumverts),%ecx
+	subl	%edx,%edx
+
+Lloop:
+
+//	// transform and project
+//		zi = 1.0 / (DotProduct(pverts->v, aliastransform[2]) +
+//				aliastransform[2][3]);
+	movb	(%esi),%dl
+	movb	%dl,Lcoords
+	fildl	Lcoords				// v[0]
+	movb	1(%esi),%dl
+	movb	%dl,Lcoords+4
+	fildl	Lcoords+4			// v[1] | v[0]
+	movb	2(%esi),%dl	
+	movb	%dl,Lcoords+8
+	fildl	Lcoords+8			// v[2] | v[1] | v[0]
+
+	fld		%st(2)				// v[0] | v[2] | v[1] | v[0]
+	fmuls	C(aliastransform)+32 // accum | v[2] | v[1] | v[0]
+	fld		%st(2)				// v[1] | accum | v[2] | v[1] | v[0]
+	fmuls	C(aliastransform)+36 // accum2 | accum | v[2] | v[1] | v[0]
+	fxch	%st(1)				// accum | accum2 | v[2] | v[1] | v[0]
+	fadds	C(aliastransform)+44 // accum | accum2 | v[2] | v[1] | v[0]
+	fld		%st(2)				// v[2] | accum | accum2 | v[2] | v[1] | v[0]
+	fmuls	C(aliastransform)+40 // accum3 | accum | accum2 | v[2] | v[1] |
+								 //  v[0]
+	fxch	%st(1)				// accum | accum3 | accum2 | v[2] | v[1] | v[0]
+	faddp	%st(0),%st(2)		// accum3 | accum | v[2] | v[1] | v[0]
+	movb	tv_lightnormalindex(%esi),%dl
+	movl	stv_s(%ebp),%eax
+	movl	%eax,fv_v+8(%edi)
+	faddp	%st(0),%st(1)		// z | v[2] | v[1] | v[0]
+
+	movl	stv_t(%ebp),%eax
+	movl	%eax,fv_v+12(%edi)
+
+//	// lighting
+//		plightnormal = r_avertexnormals[pverts->lightnormalindex];
+
+	fdivrs	Lfloat_1			// zi | v[2] | v[1] | v[0]
+
+//		fv->v[2] = pstverts->s;
+//		fv->v[3] = pstverts->t;
+//		fv->flags = pstverts->onseam;
+	movl	stv_onseam(%ebp),%eax
+	movl	%eax,fv_flags(%edi)
+
+	movl	fv_size(%edi),%eax
+	movl	stv_size(%ebp),%eax
+	movl	4(%esi),%eax
+
+	leal	(%edx,%edx,2),%eax	// index*3
+
+	fxch	%st(3)				// v[0] | v[2] | v[1] | zi
+
+//		lightcos = DotProduct (plightnormal, r_plightvec);
+	flds	C(r_avertexnormals)(,%eax,4)
+	fmuls	C(r_plightvec)
+	flds	C(r_avertexnormals)+4(,%eax,4)
+	fmuls	C(r_plightvec)+4
+	flds	C(r_avertexnormals)+8(,%eax,4)
+	fmuls	C(r_plightvec)+8
+	fxch	%st(1)
+	faddp	%st(0),%st(2)
+	fld		%st(2)				 // v[0] | laccum | laccum2 | v[0] | v[2] |
+								 //  v[1] | zi
+	fmuls	C(aliastransform)+0  // xaccum | laccum | laccum2 | v[0] | v[2] |
+								 //  v[1] | zi
+	fxch	%st(2)				 // laccum2 | laccum | xaccum | v[0] | v[2] |
+								 //  v[1] | zi
+	faddp	%st(0),%st(1)		 // laccum | xaccum | v[0] | v[2] | v[1] | zi
+
+//		temp = r_ambientlight;
+//		if (lightcos < 0)
+//		{
+	fsts	Ltemp
+	movl	C(r_ambientlight),%eax
+	movb	Ltemp+3,%dl
+	testb	$0x80,%dl
+	jz		Lsavelight	// no need to clamp if only ambient lit, because
+						//  r_ambientlight is preclamped
+
+//			temp += (int)(r_shadelight * lightcos);
+	fmuls	C(r_shadelight)
+// FIXME: fast float->int conversion?
+	fistpl	Ltemp
+	addl	Ltemp,%eax
+
+//		// clamp; because we limited the minimum ambient and shading light, we
+//		// don't have to clamp low light, just bright
+//			if (temp < 0)
+//				temp = 0;
+	jns		Lp1
+	subl	%eax,%eax
+
+//		}
+
+Lp1:
+
+//		fv->v[4] = temp;
+//
+//	// x, y, and z are scaled down by 1/2**31 in the transform, so 1/z is
+//	// scaled up by 1/2**31, and the scaling cancels out for x and y in the
+//	// projection
+//		fv->v[0] = ((DotProduct(pverts->v, aliastransform[0]) +
+//				aliastransform[0][3]) * zi) + aliasxcenter;
+//		fv->v[1] = ((DotProduct(pverts->v, aliastransform[1]) +
+//				aliastransform[1][3]) * zi) + aliasycenter;
+//		fv->v[5] = zi;
+	fxch	%st(1)				 // v[0] | xaccum | v[2] | v[1] | zi
+	fmuls	C(aliastransform)+16 // yaccum | xaccum | v[2] | v[1] | zi
+	fxch	%st(3)				 // v[1] | xaccum | v[2] | yaccum | zi
+	fld		%st(0)				 // v[1] | v[1] | xaccum | v[2] | yaccum | zi
+	fmuls	C(aliastransform)+4	 // xaccum2 | v[1] | xaccum | v[2] | yaccum |zi
+	fxch	%st(1)				 // v[1] | xaccum2 | xaccum | v[2] | yaccum |zi
+	movl	%eax,fv_v+16(%edi)
+	fmuls	C(aliastransform)+20 // yaccum2 | xaccum2 | xaccum | v[2] | yaccum|
+								 //  zi
+	fxch	%st(2)				 // xaccum | xaccum2 | yaccum2 | v[2] | yaccum|
+								 //  zi
+	fadds	C(aliastransform)+12 // xaccum | xaccum2 | yaccum2 | v[2] | yaccum|
+								 //  zi
+	fxch	%st(4)				 // yaccum | xaccum2 | yaccum2 | v[2] | xaccum|
+								 //  zi
+	fadds	C(aliastransform)+28 // yaccum | xaccum2 | yaccum2 | v[2] | xaccum|
+								 //  zi
+	fxch	%st(3)				 // v[2] | xaccum2 | yaccum2 | yaccum | xaccum|
+								 //  zi
+	fld		%st(0)				 // v[2] | v[2] | xaccum2 | yaccum2 | yaccum |
+								 //  xaccum | zi
+	fmuls	C(aliastransform)+8	 // xaccum3 | v[2] | xaccum2 | yaccum2 |yaccum|
+								 //  xaccum | zi
+	fxch	%st(1)				 // v[2] | xaccum3 | xaccum2 | yaccum2 |yaccum|
+								 //  xaccum | zi
+	fmuls	C(aliastransform)+24 // yaccum3 | xaccum3 | xaccum2 | yaccum2 |
+								 // yaccum | xaccum | zi
+	fxch	%st(5)				 // xaccum | xaccum3 | xaccum2 | yaccum2 |
+								 // yaccum | yaccum3 | zi
+	faddp	%st(0),%st(2)		 // xaccum3 | xaccum | yaccum2 | yaccum |
+								 //  yaccum3 | zi
+	fxch	%st(3)				 // yaccum | xaccum | yaccum2 | xaccum3 |
+								 //  yaccum3 | zi
+	faddp	%st(0),%st(2)		 // xaccum | yaccum | xaccum3 | yaccum3 | zi
+	addl	$(tv_size),%esi
+	faddp	%st(0),%st(2)		 // yaccum | x | yaccum3 | zi
+	faddp	%st(0),%st(2)		 // x | y | zi
+	addl	$(stv_size),%ebp
+	fmul	%st(2),%st(0)		 // x/z | y | zi
+	fxch	%st(1)				 // y | x/z | zi
+	fmul	%st(2),%st(0)		 // y/z | x/z | zi
+	fxch	%st(1)				 // x/z | y/z | zi
+	fadds	C(aliasxcenter)		 // u | y/z | zi
+	fxch	%st(1)				 // y/z | u | zi
+	fadds	C(aliasycenter)		 // v | u | zi
+	fxch	%st(2)				 // zi | u | v
+// FIXME: fast float->int conversion?
+	fistpl	fv_v+20(%edi)		 // u | v
+	fistpl	fv_v+0(%edi)		 // v
+	fistpl	fv_v+4(%edi)
+
+//	}
+
+	addl	$(fv_size),%edi
+	decl	%ecx
+	jnz		Lloop
+
+	popl	%esi				// restore register variables
+	popl	%edi
+	popl	%ebp				// restore the caller's stack frame
+	ret
+
+Lsavelight:
+	fstp	%st(0)
+	jmp		Lp1
+
+#endif	// id386
+
--- /dev/null
+++ b/QW/client/r_bsp.c
@@ -1,0 +1,674 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// r_bsp.c
+
+#include "quakedef.h"
+#include "r_local.h"
+
+//
+// current entity info
+//
+qboolean		insubmodel;
+entity_t		*currententity;
+vec3_t			modelorg, base_modelorg;
+								// modelorg is the viewpoint reletive to
+								// the currently rendering entity
+vec3_t			r_entorigin;	// the currently rendering entity in world
+								// coordinates
+
+float			entity_rotation[3][3];
+
+vec3_t			r_worldmodelorg;
+
+int				r_currentbkey;
+
+typedef enum {touchessolid, drawnode, nodrawnode} solidstate_t;
+
+#define MAX_BMODEL_VERTS	500			// 6K
+#define MAX_BMODEL_EDGES	1000		// 12K
+
+static mvertex_t	*pbverts;
+static bedge_t		*pbedges;
+static int			numbverts, numbedges;
+
+static mvertex_t	*pfrontenter, *pfrontexit;
+
+static qboolean		makeclippededge;
+
+
+//===========================================================================
+
+/*
+================
+R_EntityRotate
+================
+*/
+void R_EntityRotate (vec3_t vec)
+{
+	vec3_t	tvec;
+
+	VectorCopy (vec, tvec);
+	vec[0] = DotProduct (entity_rotation[0], tvec);
+	vec[1] = DotProduct (entity_rotation[1], tvec);
+	vec[2] = DotProduct (entity_rotation[2], tvec);
+}
+
+
+/*
+================
+R_RotateBmodel
+================
+*/
+void R_RotateBmodel (void)
+{
+	float	angle, s, c, temp1[3][3], temp2[3][3], temp3[3][3];
+
+// TODO: should use a look-up table
+// TODO: should really be stored with the entity instead of being reconstructed
+// TODO: could cache lazily, stored in the entity
+// TODO: share work with R_SetUpAliasTransform
+
+// yaw
+	angle = currententity->angles[YAW];		
+	angle = angle * M_PI*2 / 360;
+	s = sin(angle);
+	c = cos(angle);
+
+	temp1[0][0] = c;
+	temp1[0][1] = s;
+	temp1[0][2] = 0;
+	temp1[1][0] = -s;
+	temp1[1][1] = c;
+	temp1[1][2] = 0;
+	temp1[2][0] = 0;
+	temp1[2][1] = 0;
+	temp1[2][2] = 1;
+
+
+// pitch
+	angle = currententity->angles[PITCH];		
+	angle = angle * M_PI*2 / 360;
+	s = sin(angle);
+	c = cos(angle);
+
+	temp2[0][0] = c;
+	temp2[0][1] = 0;
+	temp2[0][2] = -s;
+	temp2[1][0] = 0;
+	temp2[1][1] = 1;
+	temp2[1][2] = 0;
+	temp2[2][0] = s;
+	temp2[2][1] = 0;
+	temp2[2][2] = c;
+
+	R_ConcatRotations (temp2, temp1, temp3);
+
+// roll
+	angle = currententity->angles[ROLL];		
+	angle = angle * M_PI*2 / 360;
+	s = sin(angle);
+	c = cos(angle);
+
+	temp1[0][0] = 1;
+	temp1[0][1] = 0;
+	temp1[0][2] = 0;
+	temp1[1][0] = 0;
+	temp1[1][1] = c;
+	temp1[1][2] = s;
+	temp1[2][0] = 0;
+	temp1[2][1] = -s;
+	temp1[2][2] = c;
+
+	R_ConcatRotations (temp1, temp3, entity_rotation);
+
+//
+// rotate modelorg and the transformation matrix
+//
+	R_EntityRotate (modelorg);
+	R_EntityRotate (vpn);
+	R_EntityRotate (vright);
+	R_EntityRotate (vup);
+
+	R_TransformFrustum ();
+}
+
+
+/*
+================
+R_RecursiveClipBPoly
+================
+*/
+void R_RecursiveClipBPoly (bedge_t *pedges, mnode_t *pnode, msurface_t *psurf)
+{
+	bedge_t		*psideedges[2], *pnextedge, *ptedge;
+	int			i, side, lastside;
+	float		dist, frac, lastdist;
+	mplane_t	*splitplane, tplane;
+	mvertex_t	*pvert, *plastvert, *ptvert;
+	mnode_t		*pn;
+
+	psideedges[0] = psideedges[1] = NULL;
+
+	makeclippededge = false;
+
+// transform the BSP plane into model space
+// FIXME: cache these?
+	splitplane = pnode->plane;
+	tplane.dist = splitplane->dist -
+			DotProduct(r_entorigin, splitplane->normal);
+	tplane.normal[0] = DotProduct (entity_rotation[0], splitplane->normal);
+	tplane.normal[1] = DotProduct (entity_rotation[1], splitplane->normal);
+	tplane.normal[2] = DotProduct (entity_rotation[2], splitplane->normal);
+
+// clip edges to BSP plane
+	for ( ; pedges ; pedges = pnextedge)
+	{
+		pnextedge = pedges->pnext;
+
+	// set the status for the last point as the previous point
+	// FIXME: cache this stuff somehow?
+		plastvert = pedges->v[0];
+		lastdist = DotProduct (plastvert->position, tplane.normal) -
+				   tplane.dist;
+
+		if (lastdist > 0)
+			lastside = 0;
+		else
+			lastside = 1;
+
+		pvert = pedges->v[1];
+
+		dist = DotProduct (pvert->position, tplane.normal) - tplane.dist;
+
+		if (dist > 0)
+			side = 0;
+		else
+			side = 1;
+
+		if (side != lastside)
+		{
+		// clipped
+			if (numbverts >= MAX_BMODEL_VERTS)
+				return;
+
+		// generate the clipped vertex
+			frac = lastdist / (lastdist - dist);
+			ptvert = &pbverts[numbverts++];
+			ptvert->position[0] = plastvert->position[0] +
+					frac * (pvert->position[0] -
+					plastvert->position[0]);
+			ptvert->position[1] = plastvert->position[1] +
+					frac * (pvert->position[1] -
+					plastvert->position[1]);
+			ptvert->position[2] = plastvert->position[2] +
+					frac * (pvert->position[2] -
+					plastvert->position[2]);
+
+		// split into two edges, one on each side, and remember entering
+		// and exiting points
+		// FIXME: share the clip edge by having a winding direction flag?
+			if (numbedges >= (MAX_BMODEL_EDGES - 1))
+			{
+				Con_Printf ("Out of edges for bmodel\n");
+				return;
+			}
+
+			ptedge = &pbedges[numbedges];
+			ptedge->pnext = psideedges[lastside];
+			psideedges[lastside] = ptedge;
+			ptedge->v[0] = plastvert;
+			ptedge->v[1] = ptvert;
+
+			ptedge = &pbedges[numbedges + 1];
+			ptedge->pnext = psideedges[side];
+			psideedges[side] = ptedge;
+			ptedge->v[0] = ptvert;
+			ptedge->v[1] = pvert;
+
+			numbedges += 2;
+
+			if (side == 0)
+			{
+			// entering for front, exiting for back
+				pfrontenter = ptvert;
+				makeclippededge = true;
+			}
+			else
+			{
+				pfrontexit = ptvert;
+				makeclippededge = true;
+			}
+		}
+		else
+		{
+		// add the edge to the appropriate side
+			pedges->pnext = psideedges[side];
+			psideedges[side] = pedges;
+		}
+	}
+
+// if anything was clipped, reconstitute and add the edges along the clip
+// plane to both sides (but in opposite directions)
+	if (makeclippededge)
+	{
+		if (numbedges >= (MAX_BMODEL_EDGES - 2))
+		{
+			Con_Printf ("Out of edges for bmodel\n");
+			return;
+		}
+
+		ptedge = &pbedges[numbedges];
+		ptedge->pnext = psideedges[0];
+		psideedges[0] = ptedge;
+		ptedge->v[0] = pfrontexit;
+		ptedge->v[1] = pfrontenter;
+
+		ptedge = &pbedges[numbedges + 1];
+		ptedge->pnext = psideedges[1];
+		psideedges[1] = ptedge;
+		ptedge->v[0] = pfrontenter;
+		ptedge->v[1] = pfrontexit;
+
+		numbedges += 2;
+	}
+
+// draw or recurse further
+	for (i=0 ; i<2 ; i++)
+	{
+		if (psideedges[i])
+		{
+		// draw if we've reached a non-solid leaf, done if all that's left is a
+		// solid leaf, and continue down the tree if it's not a leaf
+			pn = pnode->children[i];
+
+		// we're done with this branch if the node or leaf isn't in the PVS
+			if (pn->visframe == r_visframecount)
+			{
+				if (pn->contents < 0)
+				{
+					if (pn->contents != CONTENTS_SOLID)
+					{
+						r_currentbkey = ((mleaf_t *)pn)->key;
+						R_RenderBmodelFace (psideedges[i], psurf);
+					}
+				}
+				else
+				{
+					R_RecursiveClipBPoly (psideedges[i], pnode->children[i],
+									  psurf);
+				}
+			}
+		}
+	}
+}
+
+
+/*
+================
+R_DrawSolidClippedSubmodelPolygons
+================
+*/
+void R_DrawSolidClippedSubmodelPolygons (model_t *pmodel)
+{
+	int			i, j, lindex;
+	vec_t		dot;
+	msurface_t	*psurf;
+	int			numsurfaces;
+	mplane_t	*pplane;
+	mvertex_t	bverts[MAX_BMODEL_VERTS];
+	bedge_t		bedges[MAX_BMODEL_EDGES], *pbedge;
+	medge_t		*pedge, *pedges;
+
+// FIXME: use bounding-box-based frustum clipping info?
+
+	psurf = &pmodel->surfaces[pmodel->firstmodelsurface];
+	numsurfaces = pmodel->nummodelsurfaces;
+	pedges = pmodel->edges;
+
+	for (i=0 ; i<numsurfaces ; i++, psurf++)
+	{
+	// find which side of the node we are on
+		pplane = psurf->plane;
+
+		dot = DotProduct (modelorg, pplane->normal) - pplane->dist;
+
+	// draw the polygon
+		if (((psurf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) ||
+			(!(psurf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON)))
+		{
+		// FIXME: use bounding-box-based frustum clipping info?
+
+		// copy the edges to bedges, flipping if necessary so always
+		// clockwise winding
+		// FIXME: if edges and vertices get caches, these assignments must move
+		// outside the loop, and overflow checking must be done here
+			pbverts = bverts;
+			pbedges = bedges;
+			numbverts = numbedges = 0;
+
+			if (psurf->numedges > 0)
+			{
+				pbedge = &bedges[numbedges];
+				numbedges += psurf->numedges;
+
+				for (j=0 ; j<psurf->numedges ; j++)
+				{
+				   lindex = pmodel->surfedges[psurf->firstedge+j];
+
+					if (lindex > 0)
+					{
+						pedge = &pedges[lindex];
+						pbedge[j].v[0] = &r_pcurrentvertbase[pedge->v[0]];
+						pbedge[j].v[1] = &r_pcurrentvertbase[pedge->v[1]];
+					}
+					else
+					{
+						lindex = -lindex;
+						pedge = &pedges[lindex];
+						pbedge[j].v[0] = &r_pcurrentvertbase[pedge->v[1]];
+						pbedge[j].v[1] = &r_pcurrentvertbase[pedge->v[0]];
+					}
+
+					pbedge[j].pnext = &pbedge[j+1];
+				}
+
+				pbedge[j-1].pnext = NULL;	// mark end of edges
+
+				R_RecursiveClipBPoly (pbedge, currententity->topnode, psurf);
+			}
+			else
+			{
+				Sys_Error ("no edges in bmodel");
+			}
+		}
+	}
+}
+
+
+/*
+================
+R_DrawSubmodelPolygons
+================
+*/
+void R_DrawSubmodelPolygons (model_t *pmodel, int clipflags)
+{
+	int			i;
+	vec_t		dot;
+	msurface_t	*psurf;
+	int			numsurfaces;
+	mplane_t	*pplane;
+
+// FIXME: use bounding-box-based frustum clipping info?
+
+	psurf = &pmodel->surfaces[pmodel->firstmodelsurface];
+	numsurfaces = pmodel->nummodelsurfaces;
+
+	for (i=0 ; i<numsurfaces ; i++, psurf++)
+	{
+	// find which side of the node we are on
+		pplane = psurf->plane;
+
+		dot = DotProduct (modelorg, pplane->normal) - pplane->dist;
+
+	// draw the polygon
+		if (((psurf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) ||
+			(!(psurf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON)))
+		{
+			r_currentkey = ((mleaf_t *)currententity->topnode)->key;
+
+		// FIXME: use bounding-box-based frustum clipping info?
+			R_RenderFace (psurf, clipflags);
+		}
+	}
+}
+
+
+/*
+================
+R_RecursiveWorldNode
+================
+*/
+void R_RecursiveWorldNode (mnode_t *node, int clipflags)
+{
+	int			i, c, side, *pindex;
+	vec3_t		acceptpt, rejectpt;
+	mplane_t	*plane;
+	msurface_t	*surf, **mark;
+	mleaf_t		*pleaf;
+	double		d, dot;
+
+	if (node->contents == CONTENTS_SOLID)
+		return;		// solid
+
+	if (node->visframe != r_visframecount)
+		return;
+
+// cull the clipping planes if not trivial accept
+// FIXME: the compiler is doing a lousy job of optimizing here; it could be
+//  twice as fast in ASM
+	if (clipflags)
+	{
+		for (i=0 ; i<4 ; i++)
+		{
+			if (! (clipflags & (1<<i)) )
+				continue;	// don't need to clip against it
+
+		// generate accept and reject points
+		// FIXME: do with fast look-ups or integer tests based on the sign bit
+		// of the floating point values
+
+			pindex = pfrustum_indexes[i];
+
+			rejectpt[0] = (float)node->minmaxs[pindex[0]];
+			rejectpt[1] = (float)node->minmaxs[pindex[1]];
+			rejectpt[2] = (float)node->minmaxs[pindex[2]];
+			
+			d = DotProduct (rejectpt, view_clipplanes[i].normal);
+			d -= view_clipplanes[i].dist;
+
+			if (d <= 0)
+				return;
+
+			acceptpt[0] = (float)node->minmaxs[pindex[3+0]];
+			acceptpt[1] = (float)node->minmaxs[pindex[3+1]];
+			acceptpt[2] = (float)node->minmaxs[pindex[3+2]];
+
+			d = DotProduct (acceptpt, view_clipplanes[i].normal);
+			d -= view_clipplanes[i].dist;
+
+			if (d >= 0)
+				clipflags &= ~(1<<i);	// node is entirely on screen
+		}
+	}
+	
+// if a leaf node, draw stuff
+	if (node->contents < 0)
+	{
+		pleaf = (mleaf_t *)node;
+
+		mark = pleaf->firstmarksurface;
+		c = pleaf->nummarksurfaces;
+
+		if (c)
+		{
+			do
+			{
+				(*mark)->visframe = r_framecount;
+				mark++;
+			} while (--c);
+		}
+
+	// deal with model fragments in this leaf
+		if (pleaf->efrags)
+		{
+			R_StoreEfrags (&pleaf->efrags);
+		}
+
+		pleaf->key = r_currentkey;
+		r_currentkey++;		// all bmodels in a leaf share the same key
+	}
+	else
+	{
+	// node is just a decision point, so go down the apropriate sides
+
+	// find which side of the node we are on
+		plane = node->plane;
+
+		switch (plane->type)
+		{
+		case PLANE_X:
+			dot = modelorg[0] - plane->dist;
+			break;
+		case PLANE_Y:
+			dot = modelorg[1] - plane->dist;
+			break;
+		case PLANE_Z:
+			dot = modelorg[2] - plane->dist;
+			break;
+		default:
+			dot = DotProduct (modelorg, plane->normal) - plane->dist;
+			break;
+		}
+	
+		if (dot >= 0)
+			side = 0;
+		else
+			side = 1;
+
+	// recurse down the children, front side first
+		R_RecursiveWorldNode (node->children[side], clipflags);
+
+	// draw stuff
+		c = node->numsurfaces;
+
+		if (c)
+		{
+			surf = cl.worldmodel->surfaces + node->firstsurface;
+
+			if (dot < -BACKFACE_EPSILON)
+			{
+				do
+				{
+					if ((surf->flags & SURF_PLANEBACK) &&
+						(surf->visframe == r_framecount))
+					{
+						if (r_drawpolys)
+						{
+							if (r_worldpolysbacktofront)
+							{
+								if (numbtofpolys < MAX_BTOFPOLYS)
+								{
+									pbtofpolys[numbtofpolys].clipflags =
+											clipflags;
+									pbtofpolys[numbtofpolys].psurf = surf;
+									numbtofpolys++;
+								}
+							}
+							else
+							{
+								R_RenderPoly (surf, clipflags);
+							}
+						}
+						else
+						{
+							R_RenderFace (surf, clipflags);
+						}
+					}
+
+					surf++;
+				} while (--c);
+			}
+			else if (dot > BACKFACE_EPSILON)
+			{
+				do
+				{
+					if (!(surf->flags & SURF_PLANEBACK) &&
+						(surf->visframe == r_framecount))
+					{
+						if (r_drawpolys)
+						{
+							if (r_worldpolysbacktofront)
+							{
+								if (numbtofpolys < MAX_BTOFPOLYS)
+								{
+									pbtofpolys[numbtofpolys].clipflags =
+											clipflags;
+									pbtofpolys[numbtofpolys].psurf = surf;
+									numbtofpolys++;
+								}
+							}
+							else
+							{
+								R_RenderPoly (surf, clipflags);
+							}
+						}
+						else
+						{
+							R_RenderFace (surf, clipflags);
+						}
+					}
+
+					surf++;
+				} while (--c);
+			}
+
+		// all surfaces on the same node share the same sequence number
+			r_currentkey++;
+		}
+
+	// recurse down the back side
+		R_RecursiveWorldNode (node->children[!side], clipflags);
+	}
+}
+
+
+
+/*
+================
+R_RenderWorld
+================
+*/
+void R_RenderWorld (void)
+{
+	int			i;
+	model_t		*clmodel;
+	btofpoly_t	btofpolys[MAX_BTOFPOLYS];
+
+	pbtofpolys = btofpolys;
+
+	currententity = &r_worldentity;
+	VectorCopy (r_origin, modelorg);
+	clmodel = currententity->model;
+	r_pcurrentvertbase = clmodel->vertexes;
+
+	R_RecursiveWorldNode (clmodel->nodes, 15);
+
+// if the driver wants the polygons back to front, play the visible ones back
+// in that order
+	if (r_worldpolysbacktofront)
+	{
+		for (i=numbtofpolys-1 ; i>=0 ; i--)
+		{
+			R_RenderPoly (btofpolys[i].psurf, btofpolys[i].clipflags);
+		}
+	}
+}
+
+
--- /dev/null
+++ b/QW/client/r_draw.c
@@ -1,0 +1,908 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+
+// r_draw.c
+
+#include "quakedef.h"
+#include "r_local.h"
+#include "d_local.h"	// FIXME: shouldn't need to include this
+
+#define MAXLEFTCLIPEDGES		100
+
+// !!! if these are changed, they must be changed in asm_draw.h too !!!
+#define FULLY_CLIPPED_CACHED	0x80000000
+#define FRAMECOUNT_MASK			0x7FFFFFFF
+
+unsigned int	cacheoffset;
+
+int			c_faceclip;					// number of faces clipped
+
+zpointdesc_t	r_zpointdesc;
+
+polydesc_t		r_polydesc;
+
+
+
+clipplane_t	*entity_clipplanes;
+clipplane_t	view_clipplanes[4];
+clipplane_t	world_clipplanes[16];
+
+medge_t			*r_pedge;
+
+qboolean		r_leftclipped, r_rightclipped;
+static qboolean	makeleftedge, makerightedge;
+qboolean		r_nearzionly;
+
+int		sintable[1280];
+int		intsintable[1280];
+
+mvertex_t	r_leftenter, r_leftexit;
+mvertex_t	r_rightenter, r_rightexit;
+
+typedef struct
+{
+	float	u,v;
+	int		ceilv;
+} evert_t;
+
+int				r_emitted;
+float			r_nearzi;
+float			r_u1, r_v1, r_lzi1;
+int				r_ceilv1;
+
+qboolean	r_lastvertvalid;
+
+
+#if	!id386
+
+/*
+================
+R_EmitEdge
+================
+*/
+void R_EmitEdge (mvertex_t *pv0, mvertex_t *pv1)
+{
+	edge_t	*edge, *pcheck;
+	int		u_check;
+	float	u, u_step;
+	vec3_t	local, transformed;
+	float	*world;
+	int		v, v2, ceilv0;
+	float	scale, lzi0, u0, v0;
+	int		side;
+
+	if (r_lastvertvalid)
+	{
+		u0 = r_u1;
+		v0 = r_v1;
+		lzi0 = r_lzi1;
+		ceilv0 = r_ceilv1;
+	}
+	else
+	{
+		world = &pv0->position[0];
+	
+	// transform and project
+		VectorSubtract (world, modelorg, local);
+		TransformVector (local, transformed);
+	
+		if (transformed[2] < NEAR_CLIP)
+			transformed[2] = NEAR_CLIP;
+	
+		lzi0 = 1.0 / transformed[2];
+	
+	// FIXME: build x/yscale into transform?
+		scale = xscale * lzi0;
+		u0 = (xcenter + scale*transformed[0]);
+		if (u0 < r_refdef.fvrectx_adj)
+			u0 = r_refdef.fvrectx_adj;
+		if (u0 > r_refdef.fvrectright_adj)
+			u0 = r_refdef.fvrectright_adj;
+	
+		scale = yscale * lzi0;
+		v0 = (ycenter - scale*transformed[1]);
+		if (v0 < r_refdef.fvrecty_adj)
+			v0 = r_refdef.fvrecty_adj;
+		if (v0 > r_refdef.fvrectbottom_adj)
+			v0 = r_refdef.fvrectbottom_adj;
+	
+		ceilv0 = (int) ceil(v0);
+	}
+
+	world = &pv1->position[0];
+
+// transform and project
+	VectorSubtract (world, modelorg, local);
+	TransformVector (local, transformed);
+
+	if (transformed[2] < NEAR_CLIP)
+		transformed[2] = NEAR_CLIP;
+
+	r_lzi1 = 1.0 / transformed[2];
+
+	scale = xscale * r_lzi1;
+	r_u1 = (xcenter + scale*transformed[0]);
+	if (r_u1 < r_refdef.fvrectx_adj)
+		r_u1 = r_refdef.fvrectx_adj;
+	if (r_u1 > r_refdef.fvrectright_adj)
+		r_u1 = r_refdef.fvrectright_adj;
+
+	scale = yscale * r_lzi1;
+	r_v1 = (ycenter - scale*transformed[1]);
+	if (r_v1 < r_refdef.fvrecty_adj)
+		r_v1 = r_refdef.fvrecty_adj;
+	if (r_v1 > r_refdef.fvrectbottom_adj)
+		r_v1 = r_refdef.fvrectbottom_adj;
+
+	if (r_lzi1 > lzi0)
+		lzi0 = r_lzi1;
+
+	if (lzi0 > r_nearzi)	// for mipmap finding
+		r_nearzi = lzi0;
+
+// for right edges, all we want is the effect on 1/z
+	if (r_nearzionly)
+		return;
+
+	r_emitted = 1;
+
+	r_ceilv1 = (int) ceil(r_v1);
+
+
+// create the edge
+	if (ceilv0 == r_ceilv1)
+	{
+	// we cache unclipped horizontal edges as fully clipped
+		if (cacheoffset != 0x7FFFFFFF)
+		{
+			cacheoffset = FULLY_CLIPPED_CACHED |
+					(r_framecount & FRAMECOUNT_MASK);
+		}
+
+		return;		// horizontal edge
+	}
+
+	side = ceilv0 > r_ceilv1;
+
+	edge = edge_p++;
+
+	edge->owner = r_pedge;
+
+	edge->nearzi = lzi0;
+
+	if (side == 0)
+	{
+	// trailing edge (go from p1 to p2)
+		v = ceilv0;
+		v2 = r_ceilv1 - 1;
+
+		edge->surfs[0] = surface_p - surfaces;
+		edge->surfs[1] = 0;
+
+		u_step = ((r_u1 - u0) / (r_v1 - v0));
+		u = u0 + ((float)v - v0) * u_step;
+	}
+	else
+	{
+	// leading edge (go from p2 to p1)
+		v2 = ceilv0 - 1;
+		v = r_ceilv1;
+
+		edge->surfs[0] = 0;
+		edge->surfs[1] = surface_p - surfaces;
+
+		u_step = ((u0 - r_u1) / (v0 - r_v1));
+		u = r_u1 + ((float)v - r_v1) * u_step;
+	}
+
+	edge->u_step = u_step*0x100000;
+	edge->u = u*0x100000 + 0xFFFFF;
+
+// we need to do this to avoid stepping off the edges if a very nearly
+// horizontal edge is less than epsilon above a scan, and numeric error causes
+// it to incorrectly extend to the scan, and the extension of the line goes off
+// the edge of the screen
+// FIXME: is this actually needed?
+	if (edge->u < r_refdef.vrect_x_adj_shift20)
+		edge->u = r_refdef.vrect_x_adj_shift20;
+	if (edge->u > r_refdef.vrectright_adj_shift20)
+		edge->u = r_refdef.vrectright_adj_shift20;
+
+//
+// sort the edge in normally
+//
+	u_check = edge->u;
+	if (edge->surfs[0])
+		u_check++;	// sort trailers after leaders
+
+	if (!newedges[v] || newedges[v]->u >= u_check)
+	{
+		edge->next = newedges[v];
+		newedges[v] = edge;
+	}
+	else
+	{
+		pcheck = newedges[v];
+		while (pcheck->next && pcheck->next->u < u_check)
+			pcheck = pcheck->next;
+		edge->next = pcheck->next;
+		pcheck->next = edge;
+	}
+
+	edge->nextremove = removeedges[v2];
+	removeedges[v2] = edge;
+}
+
+
+/*
+================
+R_ClipEdge
+================
+*/
+void R_ClipEdge (mvertex_t *pv0, mvertex_t *pv1, clipplane_t *clip)
+{
+	float		d0, d1, f;
+	mvertex_t	clipvert;
+
+	if (clip)
+	{
+		do
+		{
+			d0 = DotProduct (pv0->position, clip->normal) - clip->dist;
+			d1 = DotProduct (pv1->position, clip->normal) - clip->dist;
+
+			if (d0 >= 0)
+			{
+			// point 0 is unclipped
+				if (d1 >= 0)
+				{
+				// both points are unclipped
+					continue;
+				}
+
+			// only point 1 is clipped
+
+			// we don't cache clipped edges
+				cacheoffset = 0x7FFFFFFF;
+
+				f = d0 / (d0 - d1);
+				clipvert.position[0] = pv0->position[0] +
+						f * (pv1->position[0] - pv0->position[0]);
+				clipvert.position[1] = pv0->position[1] +
+						f * (pv1->position[1] - pv0->position[1]);
+				clipvert.position[2] = pv0->position[2] +
+						f * (pv1->position[2] - pv0->position[2]);
+
+				if (clip->leftedge)
+				{
+					r_leftclipped = true;
+					r_leftexit = clipvert;
+				}
+				else if (clip->rightedge)
+				{
+					r_rightclipped = true;
+					r_rightexit = clipvert;
+				}
+
+				R_ClipEdge (pv0, &clipvert, clip->next);
+				return;
+			}
+			else
+			{
+			// point 0 is clipped
+				if (d1 < 0)
+				{
+				// both points are clipped
+				// we do cache fully clipped edges
+					if (!r_leftclipped)
+						cacheoffset = FULLY_CLIPPED_CACHED |
+								(r_framecount & FRAMECOUNT_MASK);
+					return;
+				}
+
+			// only point 0 is clipped
+				r_lastvertvalid = false;
+
+			// we don't cache partially clipped edges
+				cacheoffset = 0x7FFFFFFF;
+
+				f = d0 / (d0 - d1);
+				clipvert.position[0] = pv0->position[0] +
+						f * (pv1->position[0] - pv0->position[0]);
+				clipvert.position[1] = pv0->position[1] +
+						f * (pv1->position[1] - pv0->position[1]);
+				clipvert.position[2] = pv0->position[2] +
+						f * (pv1->position[2] - pv0->position[2]);
+
+				if (clip->leftedge)
+				{
+					r_leftclipped = true;
+					r_leftenter = clipvert;
+				}
+				else if (clip->rightedge)
+				{
+					r_rightclipped = true;
+					r_rightenter = clipvert;
+				}
+
+				R_ClipEdge (&clipvert, pv1, clip->next);
+				return;
+			}
+		} while ((clip = clip->next) != NULL);
+	}
+
+// add the edge
+	R_EmitEdge (pv0, pv1);
+}
+
+#endif	// !id386
+
+
+/*
+================
+R_EmitCachedEdge
+================
+*/
+void R_EmitCachedEdge (void)
+{
+	edge_t		*pedge_t;
+
+	pedge_t = (edge_t *)((unsigned long)r_edges + r_pedge->cachededgeoffset);
+
+	if (!pedge_t->surfs[0])
+		pedge_t->surfs[0] = surface_p - surfaces;
+	else
+		pedge_t->surfs[1] = surface_p - surfaces;
+
+	if (pedge_t->nearzi > r_nearzi)	// for mipmap finding
+		r_nearzi = pedge_t->nearzi;
+
+	r_emitted = 1;
+}
+
+
+/*
+================
+R_RenderFace
+================
+*/
+void R_RenderFace (msurface_t *fa, int clipflags)
+{
+	int			i, lindex;
+	unsigned	mask;
+	mplane_t	*pplane;
+	float		distinv;
+	vec3_t		p_normal;
+	medge_t		*pedges, tedge;
+	clipplane_t	*pclip;
+
+// skip out if no more surfs
+	if ((surface_p) >= surf_max)
+	{
+		r_outofsurfaces++;
+		return;
+	}
+
+// ditto if not enough edges left, or switch to auxedges if possible
+	if ((edge_p + fa->numedges + 4) >= edge_max)
+	{
+		r_outofedges += fa->numedges;
+		return;
+	}
+
+	c_faceclip++;
+
+// set up clip planes
+	pclip = NULL;
+
+	for (i=3, mask = 0x08 ; i>=0 ; i--, mask >>= 1)
+	{
+		if (clipflags & mask)
+		{
+			view_clipplanes[i].next = pclip;
+			pclip = &view_clipplanes[i];
+		}
+	}
+
+// push the edges through
+	r_emitted = 0;
+	r_nearzi = 0;
+	r_nearzionly = false;
+	makeleftedge = makerightedge = false;
+	pedges = currententity->model->edges;
+	r_lastvertvalid = false;
+
+	for (i=0 ; i<fa->numedges ; i++)
+	{
+		lindex = currententity->model->surfedges[fa->firstedge + i];
+
+		if (lindex > 0)
+		{
+			r_pedge = &pedges[lindex];
+
+		// if the edge is cached, we can just reuse the edge
+			if (!insubmodel)
+			{
+				if (r_pedge->cachededgeoffset & FULLY_CLIPPED_CACHED)
+				{
+					if ((r_pedge->cachededgeoffset & FRAMECOUNT_MASK) ==
+						r_framecount)
+					{
+						r_lastvertvalid = false;
+						continue;
+					}
+				}
+				else
+				{
+					if ((((unsigned long)edge_p - (unsigned long)r_edges) >
+						 r_pedge->cachededgeoffset) &&
+						(((edge_t *)((unsigned long)r_edges +
+						 r_pedge->cachededgeoffset))->owner == r_pedge))
+					{
+						R_EmitCachedEdge ();
+						r_lastvertvalid = false;
+						continue;
+					}
+				}
+			}
+
+		// assume it's cacheable
+			cacheoffset = (byte *)edge_p - (byte *)r_edges;
+			r_leftclipped = r_rightclipped = false;
+			R_ClipEdge (&r_pcurrentvertbase[r_pedge->v[0]],
+						&r_pcurrentvertbase[r_pedge->v[1]],
+						pclip);
+			r_pedge->cachededgeoffset = cacheoffset;
+
+			if (r_leftclipped)
+				makeleftedge = true;
+			if (r_rightclipped)
+				makerightedge = true;
+			r_lastvertvalid = true;
+		}
+		else
+		{
+			lindex = -lindex;
+			r_pedge = &pedges[lindex];
+		// if the edge is cached, we can just reuse the edge
+			if (!insubmodel)
+			{
+				if (r_pedge->cachededgeoffset & FULLY_CLIPPED_CACHED)
+				{
+					if ((r_pedge->cachededgeoffset & FRAMECOUNT_MASK) ==
+						r_framecount)
+					{
+						r_lastvertvalid = false;
+						continue;
+					}
+				}
+				else
+				{
+				// it's cached if the cached edge is valid and is owned
+				// by this medge_t
+					if ((((unsigned long)edge_p - (unsigned long)r_edges) >
+						 r_pedge->cachededgeoffset) &&
+						(((edge_t *)((unsigned long)r_edges +
+						 r_pedge->cachededgeoffset))->owner == r_pedge))
+					{
+						R_EmitCachedEdge ();
+						r_lastvertvalid = false;
+						continue;
+					}
+				}
+			}
+
+		// assume it's cacheable
+			cacheoffset = (byte *)edge_p - (byte *)r_edges;
+			r_leftclipped = r_rightclipped = false;
+			R_ClipEdge (&r_pcurrentvertbase[r_pedge->v[1]],
+						&r_pcurrentvertbase[r_pedge->v[0]],
+						pclip);
+			r_pedge->cachededgeoffset = cacheoffset;
+
+			if (r_leftclipped)
+				makeleftedge = true;
+			if (r_rightclipped)
+				makerightedge = true;
+			r_lastvertvalid = true;
+		}
+	}
+
+// if there was a clip off the left edge, add that edge too
+// FIXME: faster to do in screen space?
+// FIXME: share clipped edges?
+	if (makeleftedge)
+	{
+		r_pedge = &tedge;
+		r_lastvertvalid = false;
+		R_ClipEdge (&r_leftexit, &r_leftenter, pclip->next);
+	}
+
+// if there was a clip off the right edge, get the right r_nearzi
+	if (makerightedge)
+	{
+		r_pedge = &tedge;
+		r_lastvertvalid = false;
+		r_nearzionly = true;
+		R_ClipEdge (&r_rightexit, &r_rightenter, view_clipplanes[1].next);
+	}
+
+// if no edges made it out, return without posting the surface
+	if (!r_emitted)
+		return;
+
+	r_polycount++;
+
+	surface_p->data = (void *)fa;
+	surface_p->nearzi = r_nearzi;
+	surface_p->flags = fa->flags;
+	surface_p->insubmodel = insubmodel;
+	surface_p->spanstate = 0;
+	surface_p->entity = currententity;
+	surface_p->key = r_currentkey++;
+	surface_p->spans = NULL;
+
+	pplane = fa->plane;
+// FIXME: cache this?
+	TransformVector (pplane->normal, p_normal);
+// FIXME: cache this?
+	distinv = 1.0 / (pplane->dist - DotProduct (modelorg, pplane->normal));
+
+	surface_p->d_zistepu = p_normal[0] * xscaleinv * distinv;
+	surface_p->d_zistepv = -p_normal[1] * yscaleinv * distinv;
+	surface_p->d_ziorigin = p_normal[2] * distinv -
+			xcenter * surface_p->d_zistepu -
+			ycenter * surface_p->d_zistepv;
+
+//JDC	VectorCopy (r_worldmodelorg, surface_p->modelorg);
+	surface_p++;
+}
+
+
+/*
+================
+R_RenderBmodelFace
+================
+*/
+void R_RenderBmodelFace (bedge_t *pedges, msurface_t *psurf)
+{
+	int			i;
+	unsigned	mask;
+	mplane_t	*pplane;
+	float		distinv;
+	vec3_t		p_normal;
+	medge_t		tedge;
+	clipplane_t	*pclip;
+
+// skip out if no more surfs
+	if (surface_p >= surf_max)
+	{
+		r_outofsurfaces++;
+		return;
+	}
+
+// ditto if not enough edges left, or switch to auxedges if possible
+	if ((edge_p + psurf->numedges + 4) >= edge_max)
+	{
+		r_outofedges += psurf->numedges;
+		return;
+	}
+
+	c_faceclip++;
+
+// this is a dummy to give the caching mechanism someplace to write to
+	r_pedge = &tedge;
+
+// set up clip planes
+	pclip = NULL;
+
+	for (i=3, mask = 0x08 ; i>=0 ; i--, mask >>= 1)
+	{
+		if (r_clipflags & mask)
+		{
+			view_clipplanes[i].next = pclip;
+			pclip = &view_clipplanes[i];
+		}
+	}
+
+// push the edges through
+	r_emitted = 0;
+	r_nearzi = 0;
+	r_nearzionly = false;
+	makeleftedge = makerightedge = false;
+// FIXME: keep clipped bmodel edges in clockwise order so last vertex caching
+// can be used?
+	r_lastvertvalid = false;
+
+	for ( ; pedges ; pedges = pedges->pnext)
+	{
+		r_leftclipped = r_rightclipped = false;
+		R_ClipEdge (pedges->v[0], pedges->v[1], pclip);
+
+		if (r_leftclipped)
+			makeleftedge = true;
+		if (r_rightclipped)
+			makerightedge = true;
+	}
+
+// if there was a clip off the left edge, add that edge too
+// FIXME: faster to do in screen space?
+// FIXME: share clipped edges?
+	if (makeleftedge)
+	{
+		r_pedge = &tedge;
+		R_ClipEdge (&r_leftexit, &r_leftenter, pclip->next);
+	}
+
+// if there was a clip off the right edge, get the right r_nearzi
+	if (makerightedge)
+	{
+		r_pedge = &tedge;
+		r_nearzionly = true;
+		R_ClipEdge (&r_rightexit, &r_rightenter, view_clipplanes[1].next);
+	}
+
+// if no edges made it out, return without posting the surface
+	if (!r_emitted)
+		return;
+
+	r_polycount++;
+
+	surface_p->data = (void *)psurf;
+	surface_p->nearzi = r_nearzi;
+	surface_p->flags = psurf->flags;
+	surface_p->insubmodel = true;
+	surface_p->spanstate = 0;
+	surface_p->entity = currententity;
+	surface_p->key = r_currentbkey;
+	surface_p->spans = NULL;
+
+	pplane = psurf->plane;
+// FIXME: cache this?
+	TransformVector (pplane->normal, p_normal);
+// FIXME: cache this?
+	distinv = 1.0 / (pplane->dist - DotProduct (modelorg, pplane->normal));
+
+	surface_p->d_zistepu = p_normal[0] * xscaleinv * distinv;
+	surface_p->d_zistepv = -p_normal[1] * yscaleinv * distinv;
+	surface_p->d_ziorigin = p_normal[2] * distinv -
+			xcenter * surface_p->d_zistepu -
+			ycenter * surface_p->d_zistepv;
+
+//JDC	VectorCopy (r_worldmodelorg, surface_p->modelorg);
+	surface_p++;
+}
+
+
+/*
+================
+R_RenderPoly
+================
+*/
+void R_RenderPoly (msurface_t *fa, int clipflags)
+{
+	int			i, lindex, lnumverts, s_axis, t_axis;
+	float		dist, lastdist, lzi, scale, u, v, frac;
+	unsigned	mask;
+	vec3_t		local, transformed;
+	clipplane_t	*pclip;
+	medge_t		*pedges;
+	mplane_t	*pplane;
+	mvertex_t	verts[2][100];	//FIXME: do real number
+	polyvert_t	pverts[100];	//FIXME: do real number, safely
+	int			vertpage, newverts, newpage, lastvert;
+	qboolean	visible;
+
+// FIXME: clean this up and make it faster
+// FIXME: guard against running out of vertices
+
+	s_axis = t_axis = 0;	// keep compiler happy
+
+// set up clip planes
+	pclip = NULL;
+
+	for (i=3, mask = 0x08 ; i>=0 ; i--, mask >>= 1)
+	{
+		if (clipflags & mask)
+		{
+			view_clipplanes[i].next = pclip;
+			pclip = &view_clipplanes[i];
+		}
+	}
+
+// reconstruct the polygon
+// FIXME: these should be precalculated and loaded off disk
+	pedges = currententity->model->edges;
+	lnumverts = fa->numedges;
+	vertpage = 0;
+
+	for (i=0 ; i<lnumverts ; i++)
+	{
+		lindex = currententity->model->surfedges[fa->firstedge + i];
+
+		if (lindex > 0)
+		{
+			r_pedge = &pedges[lindex];
+			verts[0][i] = r_pcurrentvertbase[r_pedge->v[0]];
+		}
+		else
+		{
+			r_pedge = &pedges[-lindex];
+			verts[0][i] = r_pcurrentvertbase[r_pedge->v[1]];
+		}
+	}
+
+// clip the polygon, done if not visible
+	while (pclip)
+	{
+		lastvert = lnumverts - 1;
+		lastdist = DotProduct (verts[vertpage][lastvert].position,
+							   pclip->normal) - pclip->dist;
+
+		visible = false;
+		newverts = 0;
+		newpage = vertpage ^ 1;
+
+		for (i=0 ; i<lnumverts ; i++)
+		{
+			dist = DotProduct (verts[vertpage][i].position, pclip->normal) -
+					pclip->dist;
+
+			if ((lastdist > 0) != (dist > 0))
+			{
+				frac = dist / (dist - lastdist);
+				verts[newpage][newverts].position[0] =
+						verts[vertpage][i].position[0] +
+						((verts[vertpage][lastvert].position[0] -
+						  verts[vertpage][i].position[0]) * frac);
+				verts[newpage][newverts].position[1] =
+						verts[vertpage][i].position[1] +
+						((verts[vertpage][lastvert].position[1] -
+						  verts[vertpage][i].position[1]) * frac);
+				verts[newpage][newverts].position[2] =
+						verts[vertpage][i].position[2] +
+						((verts[vertpage][lastvert].position[2] -
+						  verts[vertpage][i].position[2]) * frac);
+				newverts++;
+			}
+
+			if (dist >= 0)
+			{
+				verts[newpage][newverts] = verts[vertpage][i];
+				newverts++;
+				visible = true;
+			}
+
+			lastvert = i;
+			lastdist = dist;
+		}
+
+		if (!visible || (newverts < 3))
+			return;
+
+		lnumverts = newverts;
+		vertpage ^= 1;
+		pclip = pclip->next;
+	}
+
+// transform and project, remembering the z values at the vertices and
+// r_nearzi, and extract the s and t coordinates at the vertices
+	pplane = fa->plane;
+	switch (pplane->type)
+	{
+	case PLANE_X:
+	case PLANE_ANYX:
+		s_axis = 1;
+		t_axis = 2;
+		break;
+	case PLANE_Y:
+	case PLANE_ANYY:
+		s_axis = 0;
+		t_axis = 2;
+		break;
+	case PLANE_Z:
+	case PLANE_ANYZ:
+		s_axis = 0;
+		t_axis = 1;
+		break;
+	}
+
+	r_nearzi = 0;
+
+	for (i=0 ; i<lnumverts ; i++)
+	{
+	// transform and project
+		VectorSubtract (verts[vertpage][i].position, modelorg, local);
+		TransformVector (local, transformed);
+
+		if (transformed[2] < NEAR_CLIP)
+			transformed[2] = NEAR_CLIP;
+
+		lzi = 1.0 / transformed[2];
+
+		if (lzi > r_nearzi)	// for mipmap finding
+			r_nearzi = lzi;
+
+	// FIXME: build x/yscale into transform?
+		scale = xscale * lzi;
+		u = (xcenter + scale*transformed[0]);
+		if (u < r_refdef.fvrectx_adj)
+			u = r_refdef.fvrectx_adj;
+		if (u > r_refdef.fvrectright_adj)
+			u = r_refdef.fvrectright_adj;
+
+		scale = yscale * lzi;
+		v = (ycenter - scale*transformed[1]);
+		if (v < r_refdef.fvrecty_adj)
+			v = r_refdef.fvrecty_adj;
+		if (v > r_refdef.fvrectbottom_adj)
+			v = r_refdef.fvrectbottom_adj;
+
+		pverts[i].u = u;
+		pverts[i].v = v;
+		pverts[i].zi = lzi;
+		pverts[i].s = verts[vertpage][i].position[s_axis];
+		pverts[i].t = verts[vertpage][i].position[t_axis];
+	}
+
+// build the polygon descriptor, including fa, r_nearzi, and u, v, s, t, and z
+// for each vertex
+	r_polydesc.numverts = lnumverts;
+	r_polydesc.nearzi = r_nearzi;
+	r_polydesc.pcurrentface = fa;
+	r_polydesc.pverts = pverts;
+
+// draw the polygon
+	D_DrawPoly ();
+}
+
+
+/*
+================
+R_ZDrawSubmodelPolys
+================
+*/
+void R_ZDrawSubmodelPolys (model_t *pmodel)
+{
+	int			i, numsurfaces;
+	msurface_t	*psurf;
+	float		dot;
+	mplane_t	*pplane;
+
+	psurf = &pmodel->surfaces[pmodel->firstmodelsurface];
+	numsurfaces = pmodel->nummodelsurfaces;
+
+	for (i=0 ; i<numsurfaces ; i++, psurf++)
+	{
+	// find which side of the node we are on
+		pplane = psurf->plane;
+
+		dot = DotProduct (modelorg, pplane->normal) - pplane->dist;
+
+	// draw the polygon
+		if (((psurf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) ||
+			(!(psurf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON)))
+		{
+		// FIXME: use bounding-box-based frustum clipping info?
+			R_RenderPoly (psurf, 15);
+		}
+	}
+}
+
--- /dev/null
+++ b/QW/client/r_drawa.asm
@@ -1,0 +1,673 @@
+ .386P
+ .model FLAT
+ externdef _d_zistepu:dword
+ externdef _d_pzbuffer:dword
+ externdef _d_zistepv:dword
+ externdef _d_zrowbytes:dword
+ externdef _d_ziorigin:dword
+ externdef _r_turb_s:dword
+ externdef _r_turb_t:dword
+ externdef _r_turb_pdest:dword
+ externdef _r_turb_spancount:dword
+ externdef _r_turb_turb:dword
+ externdef _r_turb_pbase:dword
+ externdef _r_turb_sstep:dword
+ externdef _r_turb_tstep:dword
+ externdef _r_bmodelactive:dword
+ externdef _d_sdivzstepu:dword
+ externdef _d_tdivzstepu:dword
+ externdef _d_sdivzstepv:dword
+ externdef _d_tdivzstepv:dword
+ externdef _d_sdivzorigin:dword
+ externdef _d_tdivzorigin:dword
+ externdef _sadjust:dword
+ externdef _tadjust:dword
+ externdef _bbextents:dword
+ externdef _bbextentt:dword
+ externdef _cacheblock:dword
+ externdef _d_viewbuffer:dword
+ externdef _cachewidth:dword
+ externdef _d_pzbuffer:dword
+ externdef _d_zrowbytes:dword
+ externdef _d_zwidth:dword
+ externdef _d_scantable:dword
+ externdef _r_lightptr:dword
+ externdef _r_numvblocks:dword
+ externdef _prowdestbase:dword
+ externdef _pbasesource:dword
+ externdef _r_lightwidth:dword
+ externdef _lightright:dword
+ externdef _lightrightstep:dword
+ externdef _lightdeltastep:dword
+ externdef _lightdelta:dword
+ externdef _lightright:dword
+ externdef _lightdelta:dword
+ externdef _sourcetstep:dword
+ externdef _surfrowbytes:dword
+ externdef _lightrightstep:dword
+ externdef _lightdeltastep:dword
+ externdef _r_sourcemax:dword
+ externdef _r_stepback:dword
+ externdef _colormap:dword
+ externdef _blocksize:dword
+ externdef _sourcesstep:dword
+ externdef _lightleft:dword
+ externdef _blockdivshift:dword
+ externdef _blockdivmask:dword
+ externdef _lightleftstep:dword
+ externdef _r_origin:dword
+ externdef _r_ppn:dword
+ externdef _r_pup:dword
+ externdef _r_pright:dword
+ externdef _ycenter:dword
+ externdef _xcenter:dword
+ externdef _d_vrectbottom_particle:dword
+ externdef _d_vrectright_particle:dword
+ externdef _d_vrecty:dword
+ externdef _d_vrectx:dword
+ externdef _d_pix_shift:dword
+ externdef _d_pix_min:dword
+ externdef _d_pix_max:dword
+ externdef _d_y_aspect_shift:dword
+ externdef _screenwidth:dword
+ externdef _vright:dword
+ externdef _vup:dword
+ externdef _vpn:dword
+ externdef _BOPS_Error:dword
+ externdef _snd_scaletable:dword
+ externdef _paintbuffer:dword
+ externdef _snd_linear_count:dword
+ externdef _snd_p:dword
+ externdef _snd_vol:dword
+ externdef _snd_out:dword
+ externdef _r_leftclipped:dword
+ externdef _r_leftenter:dword
+ externdef _r_rightclipped:dword
+ externdef _r_rightenter:dword
+ externdef _modelorg:dword
+ externdef _xscale:dword
+ externdef _r_refdef:dword
+ externdef _yscale:dword
+ externdef _r_leftexit:dword
+ externdef _r_rightexit:dword
+ externdef _r_lastvertvalid:dword
+ externdef _cacheoffset:dword
+ externdef _newedges:dword
+ externdef _removeedges:dword
+ externdef _r_pedge:dword
+ externdef _r_framecount:dword
+ externdef _r_u1:dword
+ externdef _r_emitted:dword
+ externdef _edge_p:dword
+ externdef _surface_p:dword
+ externdef _surfaces:dword
+ externdef _r_lzi1:dword
+ externdef _r_v1:dword
+ externdef _r_ceilv1:dword
+ externdef _r_nearzi:dword
+ externdef _r_nearzionly:dword
+ externdef _edge_aftertail:dword
+ externdef _edge_tail:dword
+ externdef _current_iv:dword
+ externdef _edge_head_u_shift20:dword
+ externdef _span_p:dword
+ externdef _edge_head:dword
+ externdef _fv:dword
+ externdef _edge_tail_u_shift20:dword
+ externdef _r_apverts:dword
+ externdef _r_anumverts:dword
+ externdef _aliastransform:dword
+ externdef _r_avertexnormals:dword
+ externdef _r_plightvec:dword
+ externdef _r_ambientlight:dword
+ externdef _r_shadelight:dword
+ externdef _aliasxcenter:dword
+ externdef _aliasycenter:dword
+ externdef _a_sstepxfrac:dword
+ externdef _r_affinetridesc:dword
+ externdef _acolormap:dword
+ externdef _d_pcolormap:dword
+ externdef _r_affinetridesc:dword
+ externdef _d_sfrac:dword
+ externdef _d_ptex:dword
+ externdef _d_pedgespanpackage:dword
+ externdef _d_tfrac:dword
+ externdef _d_light:dword
+ externdef _d_zi:dword
+ externdef _d_pdest:dword
+ externdef _d_pz:dword
+ externdef _d_aspancount:dword
+ externdef _erroradjustup:dword
+ externdef _errorterm:dword
+ externdef _d_xdenom:dword
+ externdef _r_p0:dword
+ externdef _r_p1:dword
+ externdef _r_p2:dword
+ externdef _a_tstepxfrac:dword
+ externdef _r_sstepx:dword
+ externdef _r_tstepx:dword
+ externdef _a_ststepxwhole:dword
+ externdef _zspantable:dword
+ externdef _skintable:dword
+ externdef _r_zistepx:dword
+ externdef _erroradjustdown:dword
+ externdef _d_countextrastep:dword
+ externdef _ubasestep:dword
+ externdef _a_ststepxwhole:dword
+ externdef _a_tstepxfrac:dword
+ externdef _r_lstepx:dword
+ externdef _a_spans:dword
+ externdef _erroradjustdown:dword
+ externdef _d_pdestextrastep:dword
+ externdef _d_pzextrastep:dword
+ externdef _d_sfracextrastep:dword
+ externdef _d_ptexextrastep:dword
+ externdef _d_countextrastep:dword
+ externdef _d_tfracextrastep:dword
+ externdef _d_lightextrastep:dword
+ externdef _d_ziextrastep:dword
+ externdef _d_pdestbasestep:dword
+ externdef _d_pzbasestep:dword
+ externdef _d_sfracbasestep:dword
+ externdef _d_ptexbasestep:dword
+ externdef _ubasestep:dword
+ externdef _d_tfracbasestep:dword
+ externdef _d_lightbasestep:dword
+ externdef _d_zibasestep:dword
+ externdef _zspantable:dword
+ externdef _r_lstepy:dword
+ externdef _r_sstepy:dword
+ externdef _r_tstepy:dword
+ externdef _r_zistepy:dword
+ externdef _D_PolysetSetEdgeTable:dword
+ externdef _D_RasterizeAliasPolySmooth:dword
+ externdef float_point5:dword
+ externdef Float2ToThe31nd:dword
+ externdef izistep:dword
+ externdef izi:dword
+ externdef FloatMinus2ToThe31nd:dword
+ externdef float_1:dword
+ externdef float_particle_z_clip:dword
+ externdef float_minus_1:dword
+ externdef float_0:dword
+ externdef fp_16:dword
+ externdef fp_64k:dword
+ externdef fp_1m:dword
+ externdef fp_1m_minus_1:dword
+ externdef fp_8:dword
+ externdef entryvec_table:dword
+ externdef advancetable:dword
+ externdef sstep:dword
+ externdef tstep:dword
+ externdef pspantemp:dword
+ externdef counttemp:dword
+ externdef jumptemp:dword
+ externdef reciprocal_table:dword
+ externdef DP_Count:dword
+ externdef DP_u:dword
+ externdef DP_v:dword
+ externdef DP_32768:dword
+ externdef DP_Color:dword
+ externdef DP_Pix:dword
+ externdef DP_EntryTable:dword
+ externdef pbase:dword
+ externdef s:dword
+ externdef t:dword
+ externdef sfracf:dword
+ externdef tfracf:dword
+ externdef snext:dword
+ externdef tnext:dword
+ externdef spancountminus1:dword
+ externdef zi16stepu:dword
+ externdef sdivz16stepu:dword
+ externdef tdivz16stepu:dword
+ externdef zi8stepu:dword
+ externdef sdivz8stepu:dword
+ externdef tdivz8stepu:dword
+ externdef reciprocal_table_16:dword
+ externdef entryvec_table_16:dword
+ externdef ceil_cw:dword
+ externdef single_cw:dword
+ externdef fp_64kx64k:dword
+ externdef pz:dword
+ externdef spr8entryvec_table:dword
+_DATA SEGMENT
+Ld0 dd 0.0
+Ld1 dd 0.0
+Lstack dd 0
+Lfp_near_clip dd 0.01
+Lceilv0 dd 0
+Lv dd 0
+Lu0 dd 0
+Lv0 dd 0
+Lzi0 dd 0
+_DATA ENDS
+_TEXT SEGMENT
+ align 4
+ public _R_ClipEdge
+_R_ClipEdge:
+ push esi
+ push edi
+ push ebx
+ mov ds:dword ptr[Lstack],esp
+ mov ebx,ds:dword ptr[12+12+esp]
+ mov esi,ds:dword ptr[4+12+esp]
+ mov edx,ds:dword ptr[8+12+esp]
+ test ebx,ebx
+ jz Lemit
+Lcliploop:
+ fld ds:dword ptr[0+0+esi]
+ fmul ds:dword ptr[0+0+ebx]
+ fld ds:dword ptr[0+4+esi]
+ fmul ds:dword ptr[0+4+ebx]
+ fld ds:dword ptr[0+8+esi]
+ fmul ds:dword ptr[0+8+ebx]
+ fxch st(1)
+ faddp st(2),st(0)
+ fld ds:dword ptr[0+0+edx]
+ fmul ds:dword ptr[0+0+ebx]
+ fld ds:dword ptr[0+4+edx]
+ fmul ds:dword ptr[0+4+ebx]
+ fld ds:dword ptr[0+8+edx]
+ fmul ds:dword ptr[0+8+ebx]
+ fxch st(1)
+ faddp st(2),st(0)
+ fxch st(3)
+ faddp st(2),st(0)
+ faddp st(2),st(0)
+ fsub ds:dword ptr[12+ebx]
+ fxch st(1)
+ fsub ds:dword ptr[12+ebx]
+ fxch st(1)
+ fstp ds:dword ptr[Ld0]
+ fstp ds:dword ptr[Ld1]
+ mov eax,ds:dword ptr[Ld0]
+ mov ecx,ds:dword ptr[Ld1]
+ or ecx,eax
+ js Lp2
+Lcontinue:
+ mov ebx,ds:dword ptr[16+ebx]
+ test ebx,ebx
+ jnz Lcliploop
+Lemit:
+ fldcw ds:word ptr[ceil_cw]
+ cmp ds:dword ptr[_r_lastvertvalid],0
+ jz LCalcFirst
+ mov eax,ds:dword ptr[_r_lzi1]
+ mov ecx,ds:dword ptr[_r_u1]
+ mov ds:dword ptr[Lzi0],eax
+ mov ds:dword ptr[Lu0],ecx
+ mov ecx,ds:dword ptr[_r_v1]
+ mov eax,ds:dword ptr[_r_ceilv1]
+ mov ds:dword ptr[Lv0],ecx
+ mov ds:dword ptr[Lceilv0],eax
+ jmp LCalcSecond
+LCalcFirst:
+ call near ptr LTransformAndProject
+ fst ds:dword ptr[Lv0]
+ fxch st(2)
+ fstp ds:dword ptr[Lu0]
+ fstp ds:dword ptr[Lzi0]
+ fistp ds:dword ptr[Lceilv0]
+LCalcSecond:
+ mov esi,edx
+ call near ptr LTransformAndProject
+ fld ds:dword ptr[Lu0]
+ fxch st(3)
+ fld ds:dword ptr[Lzi0]
+ fxch st(3)
+ fld ds:dword ptr[Lv0]
+ fxch st(3)
+ fist ds:dword ptr[_r_ceilv1]
+ fldcw ds:word ptr[single_cw]
+ fst ds:dword ptr[_r_v1]
+ fxch st(4)
+ fcom st(1)
+ fnstsw ax
+ test ah,1
+ jz LP0
+ fstp st(0)
+ fld st(0)
+LP0:
+ fxch st(1)
+ fstp ds:dword ptr[_r_lzi1]
+ fxch st(1)
+ fst ds:dword ptr[_r_u1]
+ fxch st(1)
+ fcom ds:dword ptr[_r_nearzi]
+ fnstsw ax
+ test ah,045h
+ jnz LP1
+ fst ds:dword ptr[_r_nearzi]
+LP1:
+ mov eax,ds:dword ptr[_r_nearzionly]
+ test eax,eax
+ jz LP2
+LPop5AndDone:
+ mov eax,ds:dword ptr[_cacheoffset]
+ mov edx,ds:dword ptr[_r_framecount]
+ cmp eax,07FFFFFFFh
+ jz LDoPop
+ and edx,07FFFFFFFh
+ or edx,080000000h
+ mov ds:dword ptr[_cacheoffset],edx
+LDoPop:
+ fstp st(0)
+ fstp st(0)
+ fstp st(0)
+ fstp st(0)
+ fstp st(0)
+ jmp Ldone
+LP2:
+ mov ebx,ds:dword ptr[Lceilv0]
+ mov edi,ds:dword ptr[_edge_p]
+ mov ecx,ds:dword ptr[_r_ceilv1]
+ mov edx,edi
+ mov esi,ds:dword ptr[_r_pedge]
+ add edx,32
+ cmp ebx,ecx
+ jz LPop5AndDone
+ mov eax,ds:dword ptr[_r_pedge]
+ mov ds:dword ptr[28+edi],eax
+ fstp ds:dword ptr[24+edi]
+ jc LSide0
+LSide1:
+ fsubp st(3),st(0)
+ fsub st(0),st(1)
+ fdivp st(2),st(0)
+ mov ds:dword ptr[_r_emitted],1
+ mov ds:dword ptr[_edge_p],edx
+ mov eax,ds:dword ptr[edx]
+ mov eax,ecx
+ lea ecx,ds:dword ptr[-1+ebx]
+ mov ebx,eax
+ mov eax,ds:dword ptr[_surface_p]
+ mov esi,ds:dword ptr[_surfaces]
+ sub edx,edx
+ sub eax,esi
+ shr eax,6
+ mov ds:dword ptr[16+edi],edx
+ mov ds:dword ptr[16+2+edi],eax
+ sub esi,esi
+ mov ds:dword ptr[Lv],ebx
+ fild ds:dword ptr[Lv]
+ fsubrp st(1),st(0)
+ fmul st(0),st(1)
+ fadd ds:dword ptr[_r_u1]
+ jmp LSideDone
+LSide0:
+ fsub st(0),st(3)
+ fxch st(2)
+ fsub st(0),st(1)
+ fdivp st(2),st(0)
+ mov ds:dword ptr[_r_emitted],1
+ mov ds:dword ptr[_edge_p],edx
+ mov eax,ds:dword ptr[edx]
+ dec ecx
+ mov eax,ds:dword ptr[_surface_p]
+ mov esi,ds:dword ptr[_surfaces]
+ sub edx,edx
+ sub eax,esi
+ shr eax,6
+ mov ds:dword ptr[16+2+edi],edx
+ mov ds:dword ptr[16+edi],eax
+ mov esi,1
+ mov ds:dword ptr[Lv],ebx
+ fild ds:dword ptr[Lv]
+ fsubrp st(1),st(0)
+ fmul st(0),st(1)
+ faddp st(2),st(0)
+ fxch st(1)
+LSideDone:
+ fmul ds:dword ptr[fp_1m]
+ fxch st(1)
+ fmul ds:dword ptr[fp_1m]
+ fxch st(1)
+ fadd ds:dword ptr[fp_1m_minus_1]
+ fxch st(1)
+ fistp ds:dword ptr[4+edi]
+ fistp ds:dword ptr[0+edi]
+ mov eax,ds:dword ptr[0+edi]
+ mov edx,ds:dword ptr[_r_refdef+76]
+ cmp eax,edx
+ jl LP4
+ mov edx,ds:dword ptr[_r_refdef+80]
+ cmp eax,edx
+ jng LP5
+LP4:
+ mov ds:dword ptr[0+edi],edx
+ mov eax,edx
+LP5:
+ add eax,esi
+ mov esi,ds:dword ptr[_newedges+ebx*4]
+ test esi,esi
+ jz LDoFirst
+ cmp ds:dword ptr[0+esi],eax
+ jl LNotFirst
+LDoFirst:
+ mov ds:dword ptr[12+edi],esi
+ mov ds:dword ptr[_newedges+ebx*4],edi
+ jmp LSetRemove
+LNotFirst:
+LFindInsertLoop:
+ mov edx,esi
+ mov esi,ds:dword ptr[12+esi]
+ test esi,esi
+ jz LInsertFound
+ cmp ds:dword ptr[0+esi],eax
+ jl LFindInsertLoop
+LInsertFound:
+ mov ds:dword ptr[12+edi],esi
+ mov ds:dword ptr[12+edx],edi
+LSetRemove:
+ mov eax,ds:dword ptr[_removeedges+ecx*4]
+ mov ds:dword ptr[_removeedges+ecx*4],edi
+ mov ds:dword ptr[20+edi],eax
+Ldone:
+ mov esp,ds:dword ptr[Lstack]
+ pop ebx
+ pop edi
+ pop esi
+ ret
+Lp2:
+ test eax,eax
+ jns Lp1
+ mov eax,ds:dword ptr[Ld1]
+ test eax,eax
+ jns Lp3
+ mov eax,ds:dword ptr[_r_leftclipped]
+ mov ecx,ds:dword ptr[_r_pedge]
+ test eax,eax
+ jnz Ldone
+ mov eax,ds:dword ptr[_r_framecount]
+ and eax,07FFFFFFFh
+ or eax,080000000h
+ mov ds:dword ptr[_cacheoffset],eax
+ jmp Ldone
+Lp1:
+ fld ds:dword ptr[Ld0]
+ fld ds:dword ptr[Ld1]
+ fsubr st(0),st(1)
+ mov ds:dword ptr[_cacheoffset],07FFFFFFFh
+ fdivp st(1),st(0)
+ sub esp,12
+ fld ds:dword ptr[0+8+edx]
+ fsub ds:dword ptr[0+8+esi]
+ fld ds:dword ptr[0+4+edx]
+ fsub ds:dword ptr[0+4+esi]
+ fld ds:dword ptr[0+0+edx]
+ fsub ds:dword ptr[0+0+esi]
+ mov edx,esp
+ mov eax,ds:dword ptr[20+ebx]
+ test al,al
+ fmul st(0),st(3)
+ fxch st(1)
+ fmul st(0),st(3)
+ fxch st(2)
+ fmulp st(3),st(0)
+ fadd ds:dword ptr[0+0+esi]
+ fxch st(1)
+ fadd ds:dword ptr[0+4+esi]
+ fxch st(2)
+ fadd ds:dword ptr[0+8+esi]
+ fxch st(1)
+ fstp ds:dword ptr[0+0+esp]
+ fstp ds:dword ptr[0+8+esp]
+ fstp ds:dword ptr[0+4+esp]
+ jz Ltestright
+ mov ds:dword ptr[_r_leftclipped],1
+ mov eax,ds:dword ptr[0+0+esp]
+ mov ds:dword ptr[_r_leftexit+0+0],eax
+ mov eax,ds:dword ptr[0+4+esp]
+ mov ds:dword ptr[_r_leftexit+0+4],eax
+ mov eax,ds:dword ptr[0+8+esp]
+ mov ds:dword ptr[_r_leftexit+0+8],eax
+ jmp Lcontinue
+Ltestright:
+ test ah,ah
+ jz Lcontinue
+ mov ds:dword ptr[_r_rightclipped],1
+ mov eax,ds:dword ptr[0+0+esp]
+ mov ds:dword ptr[_r_rightexit+0+0],eax
+ mov eax,ds:dword ptr[0+4+esp]
+ mov ds:dword ptr[_r_rightexit+0+4],eax
+ mov eax,ds:dword ptr[0+8+esp]
+ mov ds:dword ptr[_r_rightexit+0+8],eax
+ jmp Lcontinue
+Lp3:
+ mov ds:dword ptr[_r_lastvertvalid],0
+ fld ds:dword ptr[Ld0]
+ fld ds:dword ptr[Ld1]
+ fsubr st(0),st(1)
+ mov ds:dword ptr[_cacheoffset],07FFFFFFFh
+ fdivp st(1),st(0)
+ sub esp,12
+ fld ds:dword ptr[0+8+edx]
+ fsub ds:dword ptr[0+8+esi]
+ fld ds:dword ptr[0+4+edx]
+ fsub ds:dword ptr[0+4+esi]
+ fld ds:dword ptr[0+0+edx]
+ fsub ds:dword ptr[0+0+esi]
+ mov eax,ds:dword ptr[20+ebx]
+ test al,al
+ fmul st(0),st(3)
+ fxch st(1)
+ fmul st(0),st(3)
+ fxch st(2)
+ fmulp st(3),st(0)
+ fadd ds:dword ptr[0+0+esi]
+ fxch st(1)
+ fadd ds:dword ptr[0+4+esi]
+ fxch st(2)
+ fadd ds:dword ptr[0+8+esi]
+ fxch st(1)
+ fstp ds:dword ptr[0+0+esp]
+ fstp ds:dword ptr[0+8+esp]
+ fstp ds:dword ptr[0+4+esp]
+ mov esi,esp
+ jz Ltestright2
+ mov ds:dword ptr[_r_leftclipped],1
+ mov eax,ds:dword ptr[0+0+esp]
+ mov ds:dword ptr[_r_leftenter+0+0],eax
+ mov eax,ds:dword ptr[0+4+esp]
+ mov ds:dword ptr[_r_leftenter+0+4],eax
+ mov eax,ds:dword ptr[0+8+esp]
+ mov ds:dword ptr[_r_leftenter+0+8],eax
+ jmp Lcontinue
+Ltestright2:
+ test ah,ah
+ jz Lcontinue
+ mov ds:dword ptr[_r_rightclipped],1
+ mov eax,ds:dword ptr[0+0+esp]
+ mov ds:dword ptr[_r_rightenter+0+0],eax
+ mov eax,ds:dword ptr[0+4+esp]
+ mov ds:dword ptr[_r_rightenter+0+4],eax
+ mov eax,ds:dword ptr[0+8+esp]
+ mov ds:dword ptr[_r_rightenter+0+8],eax
+ jmp Lcontinue
+LTransformAndProject:
+ fld ds:dword ptr[0+0+esi]
+ fsub ds:dword ptr[_modelorg+0]
+ fld ds:dword ptr[0+4+esi]
+ fsub ds:dword ptr[_modelorg+4]
+ fld ds:dword ptr[0+8+esi]
+ fsub ds:dword ptr[_modelorg+8]
+ fxch st(2)
+ fld st(0)
+ fmul ds:dword ptr[_vpn+0]
+ fld st(1)
+ fmul ds:dword ptr[_vright+0]
+ fxch st(2)
+ fmul ds:dword ptr[_vup+0]
+ fld st(3)
+ fmul ds:dword ptr[_vpn+4]
+ fld st(4)
+ fmul ds:dword ptr[_vright+4]
+ fxch st(5)
+ fmul ds:dword ptr[_vup+4]
+ fxch st(1)
+ faddp st(3),st(0)
+ fxch st(3)
+ faddp st(4),st(0)
+ faddp st(2),st(0)
+ fld st(3)
+ fmul ds:dword ptr[_vpn+8]
+ fld st(4)
+ fmul ds:dword ptr[_vright+8]
+ fxch st(5)
+ fmul ds:dword ptr[_vup+8]
+ fxch st(1)
+ faddp st(2),st(0)
+ fxch st(4)
+ faddp st(3),st(0)
+ fxch st(1)
+ faddp st(3),st(0)
+ fcom ds:dword ptr[Lfp_near_clip]
+ fnstsw ax
+ test ah,1
+ jz LNoClip
+ fstp st(0)
+ fld ds:dword ptr[Lfp_near_clip]
+LNoClip:
+ fdivr ds:dword ptr[float_1]
+ fxch st(1)
+ fld ds:dword ptr[_xscale]
+ fmul st(0),st(2)
+ fmulp st(1),st(0)
+ fadd ds:dword ptr[_xcenter]
+ fcom ds:dword ptr[_r_refdef+68]
+ fnstsw ax
+ test ah,1
+ jz LClampP0
+ fstp st(0)
+ fld ds:dword ptr[_r_refdef+68]
+LClampP0:
+ fcom ds:dword ptr[_r_refdef+84]
+ fnstsw ax
+ test ah,045h
+ jnz LClampP1
+ fstp st(0)
+ fld ds:dword ptr[_r_refdef+84]
+LClampP1:
+ fld st(1)
+ fmul ds:dword ptr[_yscale]
+ fmulp st(3),st(0)
+ fxch st(2)
+ fsubr ds:dword ptr[_ycenter]
+ fcom ds:dword ptr[_r_refdef+72]
+ fnstsw ax
+ test ah,1
+ jz LClampP2
+ fstp st(0)
+ fld ds:dword ptr[_r_refdef+72]
+LClampP2:
+ fcom ds:dword ptr[_r_refdef+88]
+ fnstsw ax
+ test ah,045h
+ jnz LClampP3
+ fstp st(0)
+ fld ds:dword ptr[_r_refdef+88]
+LClampP3:
+ ret
+_TEXT ENDS
+ END
--- /dev/null
+++ b/QW/client/r_drawa.s
@@ -1,0 +1,838 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+//
+// r_drawa.s
+// x86 assembly-language edge clipping and emission code
+//
+
+#include "asm_i386.h"
+#include "quakeasm.h"
+#include "asm_draw.h"
+#include "d_ifacea.h"
+
+#if	id386
+
+// !!! if these are changed, they must be changed in r_draw.c too !!!
+#define FULLY_CLIPPED_CACHED	0x80000000
+#define FRAMECOUNT_MASK			0x7FFFFFFF
+
+	.data
+
+Ld0:			.single		0.0
+Ld1:			.single		0.0
+Lstack:			.long		0
+Lfp_near_clip:	.single		NEAR_CLIP
+Lceilv0:		.long		0
+Lv:				.long		0
+Lu0:			.long		0
+Lv0:			.long		0
+Lzi0:			.long		0
+
+	.text
+
+//----------------------------------------------------------------------
+// edge clipping code
+//----------------------------------------------------------------------
+
+#define pv0		4+12
+#define pv1		8+12
+#define clip	12+12
+
+	.align 4
+.globl C(R_ClipEdge)
+C(R_ClipEdge):
+	pushl	%esi				// preserve register variables
+	pushl	%edi
+	pushl	%ebx
+	movl	%esp,Lstack			// for clearing the stack later
+
+//	float		d0, d1, f;
+//	mvertex_t	clipvert;
+
+	movl	clip(%esp),%ebx
+	movl	pv0(%esp),%esi
+	movl	pv1(%esp),%edx
+
+//	if (clip)
+//	{
+	testl	%ebx,%ebx
+	jz		Lemit
+
+//		do
+//		{
+
+Lcliploop:
+
+//			d0 = DotProduct (pv0->position, clip->normal) - clip->dist;
+//			d1 = DotProduct (pv1->position, clip->normal) - clip->dist;
+	flds	mv_position+0(%esi)
+	fmuls	cp_normal+0(%ebx)
+	flds	mv_position+4(%esi)
+	fmuls	cp_normal+4(%ebx)
+	flds	mv_position+8(%esi)
+	fmuls	cp_normal+8(%ebx)
+	fxch	%st(1)
+	faddp	%st(0),%st(2)		// d0mul2 | d0add0
+
+	flds	mv_position+0(%edx)
+	fmuls	cp_normal+0(%ebx)
+	flds	mv_position+4(%edx)
+	fmuls	cp_normal+4(%ebx)
+	flds	mv_position+8(%edx)
+	fmuls	cp_normal+8(%ebx)
+	fxch	%st(1)
+	faddp	%st(0),%st(2)		// d1mul2 | d1add0 | d0mul2 | d0add0
+	fxch	%st(3)				// d0add0 | d1add0 | d0mul2 | d1mul2
+
+	faddp	%st(0),%st(2)		// d1add0 | dot0 | d1mul2 
+	faddp	%st(0),%st(2)		// dot0 | dot1
+
+	fsubs	cp_dist(%ebx)		// d0 | dot1
+	fxch	%st(1)				// dot1 | d0
+	fsubs	cp_dist(%ebx)		// d1 | d0
+	fxch	%st(1)
+	fstps	Ld0
+	fstps	Ld1
+
+//			if (d0 >= 0)
+//			{
+	movl	Ld0,%eax
+	movl	Ld1,%ecx
+	orl		%eax,%ecx
+	js		Lp2
+
+// both points are unclipped
+
+Lcontinue:
+
+//
+//				R_ClipEdge (&clipvert, pv1, clip->next);
+//				return;
+//			}
+//		} while ((clip = clip->next) != NULL);
+	movl	cp_next(%ebx),%ebx
+	testl	%ebx,%ebx
+	jnz		Lcliploop
+
+//	}
+
+//// add the edge
+//	R_EmitEdge (pv0, pv1);
+Lemit:
+
+//
+// set integer rounding to ceil mode, set to single precision
+//
+// FIXME: do away with by manually extracting integers from floats?
+// FIXME: set less often
+	fldcw	ceil_cw
+
+//	edge_t	*edge, *pcheck;
+//	int		u_check;
+//	float	u, u_step;
+//	vec3_t	local, transformed;
+//	float	*world;
+//	int		v, v2, ceilv0;
+//	float	scale, lzi0, u0, v0;
+//	int		side;
+
+//	if (r_lastvertvalid)
+//	{
+	cmpl	$0,C(r_lastvertvalid)
+	jz		LCalcFirst
+
+//		u0 = r_u1;
+//		v0 = r_v1;
+//		lzi0 = r_lzi1;
+//		ceilv0 = r_ceilv1;
+	movl	C(r_lzi1),%eax
+	movl	C(r_u1),%ecx
+	movl	%eax,Lzi0
+	movl	%ecx,Lu0
+	movl	C(r_v1),%ecx
+	movl	C(r_ceilv1),%eax
+	movl	%ecx,Lv0
+	movl	%eax,Lceilv0
+	jmp		LCalcSecond
+
+//	}
+
+LCalcFirst:
+
+//	else
+//	{
+//		world = &pv0->position[0];
+
+	call	LTransformAndProject	// v0 | lzi0 | u0
+
+	fsts	Lv0
+	fxch	%st(2)					// u0 | lzi0 | v0
+	fstps	Lu0						// lzi0 | v0
+	fstps	Lzi0					// v0
+
+//		ceilv0 = (int)(v0 - 2000) + 2000; // ceil(v0);
+	fistpl	Lceilv0
+
+//	}
+
+LCalcSecond:
+
+//	world = &pv1->position[0];
+	movl	%edx,%esi
+
+	call	LTransformAndProject	// v1 | lzi1 | u1
+
+	flds	Lu0						// u0 | v1 | lzi1 | u1
+	fxch	%st(3)					// u1 | v1 | lzi1 | u0
+	flds	Lzi0					// lzi0 | u1 | v1 | lzi1 | u0
+	fxch	%st(3)					// lzi1 | u1 | v1 | lzi0 | u0
+	flds	Lv0						// v0 | lzi1 | u1 | v1 | lzi0 | u0
+	fxch	%st(3)					// v1 | lzi1 | u1 | v0 | lzi0 | u0
+
+//	r_ceilv1 = (int)(r_v1 - 2000) + 2000; // ceil(r_v1);
+	fistl	C(r_ceilv1)
+
+	fldcw	single_cw				// put back normal floating-point state
+
+	fsts	C(r_v1)
+	fxch	%st(4)					// lzi0 | lzi1 | u1 | v0 | v1 | u0
+
+//	if (r_lzi1 > lzi0)
+//		lzi0 = r_lzi1;
+	fcom	%st(1)
+	fnstsw	%ax
+	testb	$1,%ah
+	jz		LP0
+	fstp	%st(0)
+	fld		%st(0)
+LP0:
+
+	fxch	%st(1)					// lzi1 | lzi0 | u1 | v0 | v1 | u0
+	fstps	C(r_lzi1)				// lzi0 | u1 | v0 | v1 | u0
+	fxch	%st(1)
+	fsts	C(r_u1)
+	fxch	%st(1)
+
+//	if (lzi0 > r_nearzi)	// for mipmap finding
+//		r_nearzi = lzi0;
+	fcoms	C(r_nearzi)
+	fnstsw	%ax
+	testb	$0x45,%ah
+	jnz		LP1
+	fsts	C(r_nearzi)
+LP1:
+
+// // for right edges, all we want is the effect on 1/z
+//	if (r_nearzionly)
+//		return;
+	movl	C(r_nearzionly),%eax
+	testl	%eax,%eax
+	jz		LP2
+LPop5AndDone:
+	movl	C(cacheoffset),%eax
+	movl	C(r_framecount),%edx
+	cmpl	$0x7FFFFFFF,%eax
+	jz		LDoPop
+	andl	$(FRAMECOUNT_MASK),%edx
+	orl		$(FULLY_CLIPPED_CACHED),%edx
+	movl	%edx,C(cacheoffset)
+
+LDoPop:
+	fstp	%st(0)			// u1 | v0 | v1 | u0
+	fstp	%st(0)			// v0 | v1 | u0
+	fstp	%st(0)			// v1 | u0
+	fstp	%st(0)			// u0
+	fstp	%st(0)
+	jmp		Ldone
+
+LP2:
+
+// // create the edge
+//	if (ceilv0 == r_ceilv1)
+//		return;		// horizontal edge
+	movl	Lceilv0,%ebx
+	movl	C(edge_p),%edi
+	movl	C(r_ceilv1),%ecx
+	movl	%edi,%edx
+	movl	C(r_pedge),%esi
+	addl	$(et_size),%edx
+	cmpl	%ecx,%ebx
+	jz		LPop5AndDone
+
+	movl	C(r_pedge),%eax
+	movl	%eax,et_owner(%edi)
+
+//	side = ceilv0 > r_ceilv1;
+//
+//	edge->nearzi = lzi0;
+	fstps	et_nearzi(%edi)		// u1 | v0 | v1 | u0
+
+//	if (side == 1)
+//	{
+	jc		LSide0
+
+LSide1:
+
+//	// leading edge (go from p2 to p1)
+
+//		u_step = ((u0 - r_u1) / (v0 - r_v1));
+	fsubrp	%st(0),%st(3)		// v0 | v1 | u0-u1
+	fsub	%st(1),%st(0)		// v0-v1 | v1 | u0-u1
+	fdivrp	%st(0),%st(2)		// v1 | ustep
+
+//	r_emitted = 1;
+	movl	$1,C(r_emitted)
+
+//	edge = edge_p++;
+	movl	%edx,C(edge_p)
+
+// pretouch next edge
+	movl	(%edx),%eax
+
+//		v2 = ceilv0 - 1;
+//		v = r_ceilv1;
+	movl	%ecx,%eax
+	leal	-1(%ebx),%ecx
+	movl	%eax,%ebx
+
+//		edge->surfs[0] = 0;
+//		edge->surfs[1] = surface_p - surfaces;
+	movl	C(surface_p),%eax
+	movl	C(surfaces),%esi
+	subl	%edx,%edx
+	subl	%esi,%eax
+	shrl	$(SURF_T_SHIFT),%eax
+	movl	%edx,et_surfs(%edi)
+	movl	%eax,et_surfs+2(%edi)
+
+	subl	%esi,%esi
+
+//		u = r_u1 + ((float)v - r_v1) * u_step;
+	movl	%ebx,Lv
+	fildl	Lv					// v | v1 | ustep
+	fsubp	%st(0),%st(1)		// v-v1 | ustep
+	fmul	%st(1),%st(0)		// (v-v1)*ustep | ustep
+	fadds	C(r_u1)				// u | ustep
+
+	jmp		LSideDone
+
+//	}
+
+LSide0:
+
+//	else
+//	{
+//	// trailing edge (go from p1 to p2)
+
+//		u_step = ((r_u1 - u0) / (r_v1 - v0));
+	fsub	%st(3),%st(0)		// u1-u0 | v0 | v1 | u0
+	fxch	%st(2)				// v1 | v0 | u1-u0 | u0
+	fsub	%st(1),%st(0)		// v1-v0 | v0 | u1-u0 | u0
+	fdivrp	%st(0),%st(2)		// v0 | ustep | u0
+
+//	r_emitted = 1;
+	movl	$1,C(r_emitted)
+
+//	edge = edge_p++;
+	movl	%edx,C(edge_p)
+
+// pretouch next edge
+	movl	(%edx),%eax
+
+//		v = ceilv0;
+//		v2 = r_ceilv1 - 1;
+	decl	%ecx
+
+//		edge->surfs[0] = surface_p - surfaces;
+//		edge->surfs[1] = 0;
+	movl	C(surface_p),%eax
+	movl	C(surfaces),%esi
+	subl	%edx,%edx
+	subl	%esi,%eax
+	shrl	$(SURF_T_SHIFT),%eax
+	movl	%edx,et_surfs+2(%edi)
+	movl	%eax,et_surfs(%edi)
+
+	movl	$1,%esi
+
+//		u = u0 + ((float)v - v0) * u_step;
+	movl	%ebx,Lv
+	fildl	Lv					// v | v0 | ustep | u0
+	fsubp	%st(0),%st(1)		// v-v0 | ustep | u0
+	fmul	%st(1),%st(0)		// (v-v0)*ustep | ustep | u0
+	faddp	%st(0),%st(2)		// ustep | u
+	fxch	%st(1)				// u | ustep
+
+//	}
+
+LSideDone:
+
+//	edge->u_step = u_step*0x100000;
+//	edge->u = u*0x100000 + 0xFFFFF;
+
+	fmuls	fp_1m				// u*0x100000 | ustep
+	fxch	%st(1)				// ustep | u*0x100000
+	fmuls	fp_1m				// ustep*0x100000 | u*0x100000
+	fxch	%st(1)				// u*0x100000 | ustep*0x100000
+	fadds	fp_1m_minus_1		// u*0x100000 + 0xFFFFF | ustep*0x100000
+	fxch	%st(1)				// ustep*0x100000 | u*0x100000 + 0xFFFFF
+	fistpl	et_u_step(%edi)		// u*0x100000 + 0xFFFFF
+	fistpl	et_u(%edi)
+
+// // we need to do this to avoid stepping off the edges if a very nearly
+// // horizontal edge is less than epsilon above a scan, and numeric error
+// // causes it to incorrectly extend to the scan, and the extension of the
+// // line goes off the edge of the screen
+// // FIXME: is this actually needed?
+//	if (edge->u < r_refdef.vrect_x_adj_shift20)
+//		edge->u = r_refdef.vrect_x_adj_shift20;
+//	if (edge->u > r_refdef.vrectright_adj_shift20)
+//		edge->u = r_refdef.vrectright_adj_shift20;
+	movl	et_u(%edi),%eax
+	movl	C(r_refdef)+rd_vrect_x_adj_shift20,%edx
+	cmpl	%edx,%eax
+	jl		LP4
+	movl	C(r_refdef)+rd_vrectright_adj_shift20,%edx
+	cmpl	%edx,%eax
+	jng		LP5
+LP4:
+	movl	%edx,et_u(%edi)
+	movl	%edx,%eax
+LP5:
+
+// // sort the edge in normally
+//	u_check = edge->u;
+//
+//	if (edge->surfs[0])
+//		u_check++;	// sort trailers after leaders
+	addl	%esi,%eax
+
+//	if (!newedges[v] || newedges[v]->u >= u_check)
+//	{
+	movl	C(newedges)(,%ebx,4),%esi
+	testl	%esi,%esi
+	jz		LDoFirst
+	cmpl	%eax,et_u(%esi)
+	jl		LNotFirst
+LDoFirst:
+
+//		edge->next = newedges[v];
+//		newedges[v] = edge;
+	movl	%esi,et_next(%edi)
+	movl	%edi,C(newedges)(,%ebx,4)
+
+	jmp		LSetRemove
+
+//	}
+
+LNotFirst:
+
+//	else
+//	{
+//		pcheck = newedges[v];
+//
+//		while (pcheck->next && pcheck->next->u < u_check)
+//			pcheck = pcheck->next;
+LFindInsertLoop:
+	movl	%esi,%edx
+	movl	et_next(%esi),%esi
+	testl	%esi,%esi
+	jz		LInsertFound
+	cmpl	%eax,et_u(%esi)
+	jl		LFindInsertLoop
+
+LInsertFound:
+
+//		edge->next = pcheck->next;
+//		pcheck->next = edge;
+	movl	%esi,et_next(%edi)
+	movl	%edi,et_next(%edx)
+
+//	}
+
+LSetRemove:
+
+//	edge->nextremove = removeedges[v2];
+//	removeedges[v2] = edge;
+	movl	C(removeedges)(,%ecx,4),%eax
+	movl	%edi,C(removeedges)(,%ecx,4)
+	movl	%eax,et_nextremove(%edi)
+
+Ldone:
+	movl	Lstack,%esp			// clear temporary variables from stack
+
+	popl	%ebx				// restore register variables
+	popl	%edi
+	popl	%esi
+	ret
+
+// at least one point is clipped
+
+Lp2:
+	testl	%eax,%eax
+	jns		Lp1
+
+//			else
+//			{
+//			// point 0 is clipped
+
+//				if (d1 < 0)
+//				{
+	movl	Ld1,%eax
+	testl	%eax,%eax
+	jns		Lp3
+
+//				// both points are clipped
+//				// we do cache fully clipped edges
+//					if (!leftclipped)
+	movl	C(r_leftclipped),%eax
+	movl	C(r_pedge),%ecx
+	testl	%eax,%eax
+	jnz		Ldone
+
+//						r_pedge->framecount = r_framecount;
+	movl	C(r_framecount),%eax
+	andl	$(FRAMECOUNT_MASK),%eax
+	orl		$(FULLY_CLIPPED_CACHED),%eax
+	movl	%eax,C(cacheoffset)
+
+//					return;
+	jmp		Ldone
+
+//				}
+
+Lp1:
+
+//			// point 0 is unclipped
+//				if (d1 >= 0)
+//				{
+//				// both points are unclipped
+//					continue;
+
+//			// only point 1 is clipped
+
+//				f = d0 / (d0 - d1);
+	flds	Ld0
+	flds	Ld1
+	fsubr	%st(1),%st(0)
+
+//			// we don't cache partially clipped edges
+	movl	$0x7FFFFFFF,C(cacheoffset)
+
+	fdivrp	%st(0),%st(1)
+
+	subl	$(mv_size),%esp			// allocate space for clipvert
+
+//				clipvert.position[0] = pv0->position[0] +
+//						f * (pv1->position[0] - pv0->position[0]);
+//				clipvert.position[1] = pv0->position[1] +
+//						f * (pv1->position[1] - pv0->position[1]);
+//				clipvert.position[2] = pv0->position[2] +
+//						f * (pv1->position[2] - pv0->position[2]);
+	flds	mv_position+8(%edx)
+	fsubs	mv_position+8(%esi)
+	flds	mv_position+4(%edx)
+	fsubs	mv_position+4(%esi)
+	flds	mv_position+0(%edx)
+	fsubs	mv_position+0(%esi)		// 0 | 1 | 2
+
+// replace pv1 with the clip point
+	movl	%esp,%edx
+	movl	cp_leftedge(%ebx),%eax
+	testb	%al,%al
+
+	fmul	%st(3),%st(0)
+	fxch	%st(1)					// 1 | 0 | 2
+	fmul	%st(3),%st(0)
+	fxch	%st(2)					// 2 | 0 | 1
+	fmulp	%st(0),%st(3)			// 0 | 1 | 2
+	fadds	mv_position+0(%esi)
+	fxch	%st(1)					// 1 | 0 | 2
+	fadds	mv_position+4(%esi)
+	fxch	%st(2)					// 2 | 0 | 1
+	fadds	mv_position+8(%esi)
+	fxch	%st(1)					// 0 | 2 | 1
+	fstps	mv_position+0(%esp)		// 2 | 1
+	fstps	mv_position+8(%esp)		// 1
+	fstps	mv_position+4(%esp)
+
+//				if (clip->leftedge)
+//				{
+	jz		Ltestright
+
+//					r_leftclipped = true;
+//					r_leftexit = clipvert;
+	movl	$1,C(r_leftclipped)
+	movl	mv_position+0(%esp),%eax
+	movl	%eax,C(r_leftexit)+mv_position+0
+	movl	mv_position+4(%esp),%eax
+	movl	%eax,C(r_leftexit)+mv_position+4
+	movl	mv_position+8(%esp),%eax
+	movl	%eax,C(r_leftexit)+mv_position+8
+
+	jmp		Lcontinue
+
+//				}
+
+Ltestright:
+//				else if (clip->rightedge)
+//				{
+	testb	%ah,%ah
+	jz		Lcontinue
+
+//					r_rightclipped = true;
+//					r_rightexit = clipvert;
+	movl	$1,C(r_rightclipped)
+	movl	mv_position+0(%esp),%eax
+	movl	%eax,C(r_rightexit)+mv_position+0
+	movl	mv_position+4(%esp),%eax
+	movl	%eax,C(r_rightexit)+mv_position+4
+	movl	mv_position+8(%esp),%eax
+	movl	%eax,C(r_rightexit)+mv_position+8
+
+//				}
+//
+//				R_ClipEdge (pv0, &clipvert, clip->next);
+//				return;
+//			}
+	jmp		Lcontinue
+
+//			}
+
+Lp3:
+
+//			// only point 0 is clipped
+//				r_lastvertvalid = false;
+
+	movl	$0,C(r_lastvertvalid)
+
+//				f = d0 / (d0 - d1);
+	flds	Ld0
+	flds	Ld1
+	fsubr	%st(1),%st(0)
+
+//			// we don't cache partially clipped edges
+	movl	$0x7FFFFFFF,C(cacheoffset)
+
+	fdivrp	%st(0),%st(1)
+
+	subl	$(mv_size),%esp			// allocate space for clipvert
+
+//				clipvert.position[0] = pv0->position[0] +
+//						f * (pv1->position[0] - pv0->position[0]);
+//				clipvert.position[1] = pv0->position[1] +
+//						f * (pv1->position[1] - pv0->position[1]);
+//				clipvert.position[2] = pv0->position[2] +
+//						f * (pv1->position[2] - pv0->position[2]);
+	flds	mv_position+8(%edx)
+	fsubs	mv_position+8(%esi)
+	flds	mv_position+4(%edx)
+	fsubs	mv_position+4(%esi)
+	flds	mv_position+0(%edx)
+	fsubs	mv_position+0(%esi)		// 0 | 1 | 2
+
+	movl	cp_leftedge(%ebx),%eax
+	testb	%al,%al
+
+	fmul	%st(3),%st(0)
+	fxch	%st(1)					// 1 | 0 | 2
+	fmul	%st(3),%st(0)
+	fxch	%st(2)					// 2 | 0 | 1
+	fmulp	%st(0),%st(3)			// 0 | 1 | 2
+	fadds	mv_position+0(%esi)
+	fxch	%st(1)					// 1 | 0 | 2
+	fadds	mv_position+4(%esi)
+	fxch	%st(2)					// 2 | 0 | 1
+	fadds	mv_position+8(%esi)
+	fxch	%st(1)					// 0 | 2 | 1
+	fstps	mv_position+0(%esp)		// 2 | 1
+	fstps	mv_position+8(%esp)		// 1
+	fstps	mv_position+4(%esp)
+
+// replace pv0 with the clip point
+	movl	%esp,%esi
+
+//				if (clip->leftedge)
+//				{
+	jz		Ltestright2
+
+//					r_leftclipped = true;
+//					r_leftenter = clipvert;
+	movl	$1,C(r_leftclipped)
+	movl	mv_position+0(%esp),%eax
+	movl	%eax,C(r_leftenter)+mv_position+0
+	movl	mv_position+4(%esp),%eax
+	movl	%eax,C(r_leftenter)+mv_position+4
+	movl	mv_position+8(%esp),%eax
+	movl	%eax,C(r_leftenter)+mv_position+8
+
+	jmp		Lcontinue
+
+//				}
+
+Ltestright2:
+//				else if (clip->rightedge)
+//				{
+	testb	%ah,%ah
+	jz		Lcontinue
+
+//					r_rightclipped = true;
+//					r_rightenter = clipvert;
+	movl	$1,C(r_rightclipped)
+	movl	mv_position+0(%esp),%eax
+	movl	%eax,C(r_rightenter)+mv_position+0
+	movl	mv_position+4(%esp),%eax
+	movl	%eax,C(r_rightenter)+mv_position+4
+	movl	mv_position+8(%esp),%eax
+	movl	%eax,C(r_rightenter)+mv_position+8
+
+//				}
+	jmp		Lcontinue
+
+// %esi = vec3_t point to transform and project
+// %edx preserved
+LTransformAndProject:
+
+//	// transform and project
+//		VectorSubtract (world, modelorg, local);
+	flds	mv_position+0(%esi)
+	fsubs	C(modelorg)+0
+	flds	mv_position+4(%esi)
+	fsubs	C(modelorg)+4
+	flds	mv_position+8(%esi)	
+	fsubs	C(modelorg)+8
+	fxch	%st(2)				// local[0] | local[1] | local[2]
+
+//		TransformVector (local, transformed);
+//	
+//		if (transformed[2] < NEAR_CLIP)
+//			transformed[2] = NEAR_CLIP;
+//	
+//		lzi0 = 1.0 / transformed[2];
+	fld		%st(0)				// local[0] | local[0] | local[1] | local[2]
+	fmuls	C(vpn)+0			// zm0 | local[0] | local[1] | local[2]
+	fld		%st(1)				// local[0] | zm0 | local[0] | local[1] |
+								//  local[2]
+	fmuls	C(vright)+0			// xm0 | zm0 | local[0] | local[1] | local[2]
+	fxch	%st(2)				// local[0] | zm0 | xm0 | local[1] | local[2]
+	fmuls	C(vup)+0			// ym0 |  zm0 | xm0 | local[1] | local[2]
+	fld		%st(3)				// local[1] | ym0 |  zm0 | xm0 | local[1] |
+								//  local[2]
+	fmuls	C(vpn)+4			// zm1 | ym0 | zm0 | xm0 | local[1] |
+								//  local[2]
+	fld		%st(4)				// local[1] | zm1 | ym0 | zm0 | xm0 |
+								//  local[1] | local[2]
+	fmuls	C(vright)+4			// xm1 | zm1 | ym0 |  zm0 | xm0 |
+								//  local[1] | local[2]
+	fxch	%st(5)				// local[1] | zm1 | ym0 | zm0 | xm0 |
+								//  xm1 | local[2]
+	fmuls	C(vup)+4			// ym1 | zm1 | ym0 | zm0 | xm0 |
+								//  xm1 | local[2]
+	fxch	%st(1)				// zm1 | ym1 | ym0 | zm0 | xm0 |
+								//  xm1 | local[2]
+	faddp	%st(0),%st(3)		// ym1 | ym0 | zm2 | xm0 | xm1 | local[2]
+	fxch	%st(3)				// xm0 | ym0 | zm2 | ym1 | xm1 | local[2]
+	faddp	%st(0),%st(4)		// ym0 | zm2 | ym1 | xm2 | local[2]
+	faddp	%st(0),%st(2)		// zm2 | ym2 | xm2 | local[2]
+	fld		%st(3)				// local[2] | zm2 | ym2 | xm2 | local[2]
+	fmuls	C(vpn)+8			// zm3 | zm2 | ym2 | xm2 | local[2]
+	fld		%st(4)				// local[2] | zm3 | zm2 | ym2 | xm2 | local[2]
+	fmuls	C(vright)+8			// xm3 | zm3 | zm2 | ym2 | xm2 | local[2]
+	fxch	%st(5)				// local[2] | zm3 | zm2 | ym2 | xm2 | xm3
+	fmuls	C(vup)+8			// ym3 | zm3 | zm2 | ym2 | xm2 | xm3
+	fxch	%st(1)				// zm3 | ym3 | zm2 | ym2 | xm2 | xm3
+	faddp	%st(0),%st(2)		// ym3 | zm4 | ym2 | xm2 | xm3
+	fxch	%st(4)				// xm3 | zm4 | ym2 | xm2 | ym3
+	faddp	%st(0),%st(3)		// zm4 | ym2 | xm4 | ym3
+	fxch	%st(1)				// ym2 | zm4 | xm4 | ym3
+	faddp	%st(0),%st(3)		// zm4 | xm4 | ym4
+
+	fcoms	Lfp_near_clip
+	fnstsw	%ax
+	testb	$1,%ah
+	jz		LNoClip
+	fstp	%st(0)
+	flds	Lfp_near_clip
+
+LNoClip:
+
+	fdivrs	float_1				// lzi0 | x | y
+	fxch	%st(1)				// x | lzi0 | y
+
+//	// FIXME: build x/yscale into transform?
+//		scale = xscale * lzi0;
+//		u0 = (xcenter + scale*transformed[0]);
+	flds	C(xscale)			// xscale | x | lzi0 | y
+	fmul	%st(2),%st(0)		// scale | x | lzi0 | y
+	fmulp	%st(0),%st(1)		// scale*x | lzi0 | y
+	fadds	C(xcenter)			// u0 | lzi0 | y
+
+//		if (u0 < r_refdef.fvrectx_adj)
+//			u0 = r_refdef.fvrectx_adj;
+//		if (u0 > r_refdef.fvrectright_adj)
+//			u0 = r_refdef.fvrectright_adj;
+// FIXME: use integer compares of floats?
+	fcoms	C(r_refdef)+rd_fvrectx_adj
+	fnstsw	%ax
+	testb	$1,%ah
+	jz		LClampP0
+	fstp	%st(0)
+	flds	C(r_refdef)+rd_fvrectx_adj
+LClampP0:
+	fcoms	C(r_refdef)+rd_fvrectright_adj
+	fnstsw	%ax
+	testb	$0x45,%ah
+	jnz		LClampP1
+	fstp	%st(0)
+	flds	C(r_refdef)+rd_fvrectright_adj
+LClampP1:
+
+	fld		%st(1)				// lzi0 | u0 | lzi0 | y
+
+//		scale = yscale * lzi0;
+//		v0 = (ycenter - scale*transformed[1]);
+	fmuls	C(yscale)			// scale | u0 | lzi0 | y
+	fmulp	%st(0),%st(3)		// u0 | lzi0 | scale*y
+	fxch	%st(2)				// scale*y | lzi0 | u0
+	fsubrs	C(ycenter)			// v0 | lzi0 | u0
+
+//		if (v0 < r_refdef.fvrecty_adj)
+//			v0 = r_refdef.fvrecty_adj;
+//		if (v0 > r_refdef.fvrectbottom_adj)
+//			v0 = r_refdef.fvrectbottom_adj;
+// FIXME: use integer compares of floats?
+	fcoms	C(r_refdef)+rd_fvrecty_adj
+	fnstsw	%ax
+	testb	$1,%ah
+	jz		LClampP2
+	fstp	%st(0)
+	flds	C(r_refdef)+rd_fvrecty_adj
+LClampP2:
+	fcoms	C(r_refdef)+rd_fvrectbottom_adj
+	fnstsw	%ax
+	testb	$0x45,%ah
+	jnz		LClampP3
+	fstp	%st(0)
+	flds	C(r_refdef)+rd_fvrectbottom_adj
+LClampP3:
+	ret
+
+#endif	// id386
+
--- /dev/null
+++ b/QW/client/r_edge.c
@@ -1,0 +1,770 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// r_edge.c
+
+#include "quakedef.h"
+#include "r_local.h"
+
+#if 0
+// FIXME
+the complex cases add new polys on most lines, so dont optimize for keeping them the same
+have multiple free span lists to try to get better coherence?
+low depth complexity -- 1 to 3 or so
+
+this breaks spans at every edge, even hidden ones (bad)
+
+have a sentinal at both ends?
+#endif
+
+
+edge_t	*auxedges;
+edge_t	*r_edges, *edge_p, *edge_max;
+
+surf_t	*surfaces, *surface_p, *surf_max;
+
+// surfaces are generated in back to front order by the bsp, so if a surf
+// pointer is greater than another one, it should be drawn in front
+// surfaces[1] is the background, and is used as the active surface stack
+
+edge_t	*newedges[MAXHEIGHT];
+edge_t	*removeedges[MAXHEIGHT];
+
+espan_t	*span_p, *max_span_p;
+
+int		r_currentkey;
+
+extern	int	screenwidth;
+
+int	current_iv;
+
+int	edge_head_u_shift20, edge_tail_u_shift20;
+
+static void (*pdrawfunc)(void);
+
+edge_t	edge_head;
+edge_t	edge_tail;
+edge_t	edge_aftertail;
+edge_t	edge_sentinel;
+
+float	fv;
+
+void R_GenerateSpans (void);
+void R_GenerateSpansBackward (void);
+
+void R_LeadingEdge (edge_t *edge);
+void R_LeadingEdgeBackwards (edge_t *edge);
+void R_TrailingEdge (surf_t *surf, edge_t *edge);
+
+
+//=============================================================================
+
+
+/*
+==============
+R_DrawCulledPolys
+==============
+*/
+void R_DrawCulledPolys (void)
+{
+	surf_t			*s;
+	msurface_t		*pface;
+
+	currententity = &r_worldentity;
+
+	if (r_worldpolysbacktofront)
+	{
+		for (s=surface_p-1 ; s>&surfaces[1] ; s--)
+		{
+			if (!s->spans)
+				continue;
+
+			if (!(s->flags & SURF_DRAWBACKGROUND))
+			{
+				pface = (msurface_t *)s->data;
+				R_RenderPoly (pface, 15);
+			}
+		}
+	}
+	else
+	{
+		for (s = &surfaces[1] ; s<surface_p ; s++)
+		{
+			if (!s->spans)
+				continue;
+
+			if (!(s->flags & SURF_DRAWBACKGROUND))
+			{
+				pface = (msurface_t *)s->data;
+				R_RenderPoly (pface, 15);
+			}
+		}
+	}
+}
+
+
+/*
+==============
+R_BeginEdgeFrame
+==============
+*/
+void R_BeginEdgeFrame (void)
+{
+	int		v;
+
+	edge_p = r_edges;
+	edge_max = &r_edges[r_numallocatededges];
+
+	surface_p = &surfaces[2];	// background is surface 1,
+								//  surface 0 is a dummy
+	surfaces[1].spans = NULL;	// no background spans yet
+	surfaces[1].flags = SURF_DRAWBACKGROUND;
+
+// put the background behind everything in the world
+	if (r_draworder.value)
+	{
+		pdrawfunc = R_GenerateSpansBackward;
+		surfaces[1].key = 0;
+		r_currentkey = 1;
+	}
+	else
+	{
+		pdrawfunc = R_GenerateSpans;
+		surfaces[1].key = 0x7FFFFFFF;
+		r_currentkey = 0;
+	}
+
+// FIXME: set with memset
+	for (v=r_refdef.vrect.y ; v<r_refdef.vrectbottom ; v++)
+	{
+		newedges[v] = removeedges[v] = NULL;
+	}
+}
+
+
+#if	!id386
+
+/*
+==============
+R_InsertNewEdges
+
+Adds the edges in the linked list edgestoadd, adding them to the edges in the
+linked list edgelist.  edgestoadd is assumed to be sorted on u, and non-empty (this is actually newedges[v]).  edgelist is assumed to be sorted on u, with a
+sentinel at the end (actually, this is the active edge table starting at
+edge_head.next).
+==============
+*/
+void R_InsertNewEdges (edge_t *edgestoadd, edge_t *edgelist)
+{
+	edge_t	*next_edge;
+
+	do
+	{
+		next_edge = edgestoadd->next;
+edgesearch:
+		if (edgelist->u >= edgestoadd->u)
+			goto addedge;
+		edgelist=edgelist->next;
+		if (edgelist->u >= edgestoadd->u)
+			goto addedge;
+		edgelist=edgelist->next;
+		if (edgelist->u >= edgestoadd->u)
+			goto addedge;
+		edgelist=edgelist->next;
+		if (edgelist->u >= edgestoadd->u)
+			goto addedge;
+		edgelist=edgelist->next;
+		goto edgesearch;
+
+	// insert edgestoadd before edgelist
+addedge:
+		edgestoadd->next = edgelist;
+		edgestoadd->prev = edgelist->prev;
+		edgelist->prev->next = edgestoadd;
+		edgelist->prev = edgestoadd;
+	} while ((edgestoadd = next_edge) != NULL);
+}
+
+#endif	// !id386
+	
+
+#if	!id386
+
+/*
+==============
+R_RemoveEdges
+==============
+*/
+void R_RemoveEdges (edge_t *pedge)
+{
+
+	do
+	{
+		pedge->next->prev = pedge->prev;
+		pedge->prev->next = pedge->next;
+	} while ((pedge = pedge->nextremove) != NULL);
+}
+
+#endif	// !id386
+
+
+#if	!id386
+
+/*
+==============
+R_StepActiveU
+==============
+*/
+void R_StepActiveU (edge_t *pedge)
+{
+	edge_t		*pnext_edge, *pwedge;
+
+	while (1)
+	{
+nextedge:
+		pedge->u += pedge->u_step;
+		if (pedge->u < pedge->prev->u)
+			goto pushback;
+		pedge = pedge->next;
+			
+		pedge->u += pedge->u_step;
+		if (pedge->u < pedge->prev->u)
+			goto pushback;
+		pedge = pedge->next;
+			
+		pedge->u += pedge->u_step;
+		if (pedge->u < pedge->prev->u)
+			goto pushback;
+		pedge = pedge->next;
+			
+		pedge->u += pedge->u_step;
+		if (pedge->u < pedge->prev->u)
+			goto pushback;
+		pedge = pedge->next;
+			
+		goto nextedge;		
+		
+pushback:
+		if (pedge == &edge_aftertail)
+			return;
+			
+	// push it back to keep it sorted		
+		pnext_edge = pedge->next;
+
+	// pull the edge out of the edge list
+		pedge->next->prev = pedge->prev;
+		pedge->prev->next = pedge->next;
+
+	// find out where the edge goes in the edge list
+		pwedge = pedge->prev->prev;
+
+		while (pwedge->u > pedge->u)
+		{
+			pwedge = pwedge->prev;
+		}
+
+	// put the edge back into the edge list
+		pedge->next = pwedge->next;
+		pedge->prev = pwedge;
+		pedge->next->prev = pedge;
+		pwedge->next = pedge;
+
+		pedge = pnext_edge;
+		if (pedge == &edge_tail)
+			return;
+	}
+}
+
+#endif	// !id386
+
+
+/*
+==============
+R_CleanupSpan
+==============
+*/
+void R_CleanupSpan ()
+{
+	surf_t	*surf;
+	int		iu;
+	espan_t	*span;
+
+// now that we've reached the right edge of the screen, we're done with any
+// unfinished surfaces, so emit a span for whatever's on top
+	surf = surfaces[1].next;
+	iu = edge_tail_u_shift20;
+	if (iu > surf->last_u)
+	{
+		span = span_p++;
+		span->u = surf->last_u;
+		span->count = iu - span->u;
+		span->v = current_iv;
+		span->pnext = surf->spans;
+		surf->spans = span;
+	}
+
+// reset spanstate for all surfaces in the surface stack
+	do
+	{
+		surf->spanstate = 0;
+		surf = surf->next;
+	} while (surf != &surfaces[1]);
+}
+
+
+/*
+==============
+R_LeadingEdgeBackwards
+==============
+*/
+void R_LeadingEdgeBackwards (edge_t *edge)
+{
+	espan_t			*span;
+	surf_t			*surf, *surf2;
+	int				iu;
+
+// it's adding a new surface in, so find the correct place
+	surf = &surfaces[edge->surfs[1]];
+
+// don't start a span if this is an inverted span, with the end
+// edge preceding the start edge (that is, we've already seen the
+// end edge)
+	if (++surf->spanstate == 1)
+	{
+		surf2 = surfaces[1].next;
+
+		if (surf->key > surf2->key)
+			goto newtop;
+
+	// if it's two surfaces on the same plane, the one that's already
+	// active is in front, so keep going unless it's a bmodel
+		if (surf->insubmodel && (surf->key == surf2->key))
+		{
+		// must be two bmodels in the same leaf; don't care, because they'll
+		// never be farthest anyway
+			goto newtop;
+		}
+
+continue_search:
+
+		do
+		{
+			surf2 = surf2->next;
+		} while (surf->key < surf2->key);
+
+		if (surf->key == surf2->key)
+		{
+		// if it's two surfaces on the same plane, the one that's already
+		// active is in front, so keep going unless it's a bmodel
+			if (!surf->insubmodel)
+				goto continue_search;
+
+		// must be two bmodels in the same leaf; don't care which is really
+		// in front, because they'll never be farthest anyway
+		}
+
+		goto gotposition;
+
+newtop:
+	// emit a span (obscures current top)
+		iu = edge->u >> 20;
+
+		if (iu > surf2->last_u)
+		{
+			span = span_p++;
+			span->u = surf2->last_u;
+			span->count = iu - span->u;
+			span->v = current_iv;
+			span->pnext = surf2->spans;
+			surf2->spans = span;
+		}
+
+		// set last_u on the new span
+		surf->last_u = iu;
+				
+gotposition:
+	// insert before surf2
+		surf->next = surf2;
+		surf->prev = surf2->prev;
+		surf2->prev->next = surf;
+		surf2->prev = surf;
+	}
+}
+
+
+/*
+==============
+R_TrailingEdge
+==============
+*/
+void R_TrailingEdge (surf_t *surf, edge_t *edge)
+{
+	espan_t			*span;
+	int				iu;
+
+// don't generate a span if this is an inverted span, with the end
+// edge preceding the start edge (that is, we haven't seen the
+// start edge yet)
+	if (--surf->spanstate == 0)
+	{
+		if (surf->insubmodel)
+			r_bmodelactive--;
+
+		if (surf == surfaces[1].next)
+		{
+		// emit a span (current top going away)
+			iu = edge->u >> 20;
+			if (iu > surf->last_u)
+			{
+				span = span_p++;
+				span->u = surf->last_u;
+				span->count = iu - span->u;
+				span->v = current_iv;
+				span->pnext = surf->spans;
+				surf->spans = span;
+			}
+
+		// set last_u on the surface below
+			surf->next->last_u = iu;
+		}
+
+		surf->prev->next = surf->next;
+		surf->next->prev = surf->prev;
+	}
+}
+
+
+#if	!id386
+
+/*
+==============
+R_LeadingEdge
+==============
+*/
+void R_LeadingEdge (edge_t *edge)
+{
+	espan_t			*span;
+	surf_t			*surf, *surf2;
+	int				iu;
+	double			fu, newzi, testzi, newzitop, newzibottom;
+
+	if (edge->surfs[1])
+	{
+	// it's adding a new surface in, so find the correct place
+		surf = &surfaces[edge->surfs[1]];
+
+	// don't start a span if this is an inverted span, with the end
+	// edge preceding the start edge (that is, we've already seen the
+	// end edge)
+		if (++surf->spanstate == 1)
+		{
+			if (surf->insubmodel)
+				r_bmodelactive++;
+
+			surf2 = surfaces[1].next;
+
+			if (surf->key < surf2->key)
+				goto newtop;
+
+		// if it's two surfaces on the same plane, the one that's already
+		// active is in front, so keep going unless it's a bmodel
+			if (surf->insubmodel && (surf->key == surf2->key))
+			{
+			// must be two bmodels in the same leaf; sort on 1/z
+				fu = (float)(edge->u - 0xFFFFF) * (1.0 / 0x100000);
+				newzi = surf->d_ziorigin + fv*surf->d_zistepv +
+						fu*surf->d_zistepu;
+				newzibottom = newzi * 0.99;
+
+				testzi = surf2->d_ziorigin + fv*surf2->d_zistepv +
+						fu*surf2->d_zistepu;
+
+				if (newzibottom >= testzi)
+				{
+					goto newtop;
+				}
+
+				newzitop = newzi * 1.01;
+				if (newzitop >= testzi)
+				{
+					if (surf->d_zistepu >= surf2->d_zistepu)
+					{
+						goto newtop;
+					}
+				}
+			}
+
+continue_search:
+
+			do
+			{
+				surf2 = surf2->next;
+			} while (surf->key > surf2->key);
+
+			if (surf->key == surf2->key)
+			{
+			// if it's two surfaces on the same plane, the one that's already
+			// active is in front, so keep going unless it's a bmodel
+				if (!surf->insubmodel)
+					goto continue_search;
+
+			// must be two bmodels in the same leaf; sort on 1/z
+				fu = (float)(edge->u - 0xFFFFF) * (1.0 / 0x100000);
+				newzi = surf->d_ziorigin + fv*surf->d_zistepv +
+						fu*surf->d_zistepu;
+				newzibottom = newzi * 0.99;
+
+				testzi = surf2->d_ziorigin + fv*surf2->d_zistepv +
+						fu*surf2->d_zistepu;
+
+				if (newzibottom >= testzi)
+				{
+					goto gotposition;
+				}
+
+				newzitop = newzi * 1.01;
+				if (newzitop >= testzi)
+				{
+					if (surf->d_zistepu >= surf2->d_zistepu)
+					{
+						goto gotposition;
+					}
+				}
+
+				goto continue_search;
+			}
+
+			goto gotposition;
+
+newtop:
+		// emit a span (obscures current top)
+			iu = edge->u >> 20;
+
+			if (iu > surf2->last_u)
+			{
+				span = span_p++;
+				span->u = surf2->last_u;
+				span->count = iu - span->u;
+				span->v = current_iv;
+				span->pnext = surf2->spans;
+				surf2->spans = span;
+			}
+
+			// set last_u on the new span
+			surf->last_u = iu;
+				
+gotposition:
+		// insert before surf2
+			surf->next = surf2;
+			surf->prev = surf2->prev;
+			surf2->prev->next = surf;
+			surf2->prev = surf;
+		}
+	}
+}
+
+
+/*
+==============
+R_GenerateSpans
+==============
+*/
+void R_GenerateSpans (void)
+{
+	edge_t			*edge;
+	surf_t			*surf;
+
+	r_bmodelactive = 0;
+
+// clear active surfaces to just the background surface
+	surfaces[1].next = surfaces[1].prev = &surfaces[1];
+	surfaces[1].last_u = edge_head_u_shift20;
+
+// generate spans
+	for (edge=edge_head.next ; edge != &edge_tail; edge=edge->next)
+	{			
+		if (edge->surfs[0])
+		{
+		// it has a left surface, so a surface is going away for this span
+			surf = &surfaces[edge->surfs[0]];
+
+			R_TrailingEdge (surf, edge);
+
+			if (!edge->surfs[1])
+				continue;
+		}
+
+		R_LeadingEdge (edge);
+	}
+
+	R_CleanupSpan ();
+}
+
+#endif	// !id386
+
+
+/*
+==============
+R_GenerateSpansBackward
+==============
+*/
+void R_GenerateSpansBackward (void)
+{
+	edge_t			*edge;
+
+	r_bmodelactive = 0;
+
+// clear active surfaces to just the background surface
+	surfaces[1].next = surfaces[1].prev = &surfaces[1];
+	surfaces[1].last_u = edge_head_u_shift20;
+
+// generate spans
+	for (edge=edge_head.next ; edge != &edge_tail; edge=edge->next)
+	{			
+		if (edge->surfs[0])
+			R_TrailingEdge (&surfaces[edge->surfs[0]], edge);
+
+		if (edge->surfs[1])
+			R_LeadingEdgeBackwards (edge);
+	}
+
+	R_CleanupSpan ();
+}
+
+
+/*
+==============
+R_ScanEdges
+
+Input: 
+newedges[] array
+	this has links to edges, which have links to surfaces
+
+Output:
+Each surface has a linked list of its visible spans
+==============
+*/
+void R_ScanEdges (void)
+{
+	int		iv, bottom;
+	byte	basespans[MAXSPANS*sizeof(espan_t)+CACHE_SIZE];
+	espan_t	*basespan_p;
+	surf_t	*s;
+
+	basespan_p = (espan_t *)
+			((long)(basespans + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1));
+	max_span_p = &basespan_p[MAXSPANS - r_refdef.vrect.width];
+
+	span_p = basespan_p;
+
+// clear active edges to just the background edges around the whole screen
+// FIXME: most of this only needs to be set up once
+	edge_head.u = r_refdef.vrect.x << 20;
+	edge_head_u_shift20 = edge_head.u >> 20;
+	edge_head.u_step = 0;
+	edge_head.prev = NULL;
+	edge_head.next = &edge_tail;
+	edge_head.surfs[0] = 0;
+	edge_head.surfs[1] = 1;
+	
+	edge_tail.u = (r_refdef.vrectright << 20) + 0xFFFFF;
+	edge_tail_u_shift20 = edge_tail.u >> 20;
+	edge_tail.u_step = 0;
+	edge_tail.prev = &edge_head;
+	edge_tail.next = &edge_aftertail;
+	edge_tail.surfs[0] = 1;
+	edge_tail.surfs[1] = 0;
+	
+	edge_aftertail.u = -1;		// force a move
+	edge_aftertail.u_step = 0;
+	edge_aftertail.next = &edge_sentinel;
+	edge_aftertail.prev = &edge_tail;
+
+// FIXME: do we need this now that we clamp x in r_draw.c?
+	edge_sentinel.u = 2000 << 24;		// make sure nothing sorts past this
+	edge_sentinel.prev = &edge_aftertail;
+
+//	
+// process all scan lines
+//
+	bottom = r_refdef.vrectbottom - 1;
+
+	for (iv=r_refdef.vrect.y ; iv<bottom ; iv++)
+	{
+		current_iv = iv;
+		fv = (float)iv;
+
+	// mark that the head (background start) span is pre-included
+		surfaces[1].spanstate = 1;
+
+		if (newedges[iv])
+		{
+			R_InsertNewEdges (newedges[iv], edge_head.next);
+		}
+
+		(*pdrawfunc) ();
+
+	// flush the span list if we can't be sure we have enough spans left for
+	// the next scan
+		if (span_p > max_span_p)
+		{
+			VID_UnlockBuffer ();
+			S_ExtraUpdate ();	// don't let sound get messed up if going slow
+			VID_LockBuffer ();
+		
+			if (r_drawculledpolys)
+				R_DrawCulledPolys ();
+			else
+				D_DrawSurfaces ();
+
+		// clear the surface span pointers
+			for (s = &surfaces[1] ; s<surface_p ; s++)
+				s->spans = NULL;
+
+			span_p = basespan_p;
+		}
+
+		if (removeedges[iv])
+			R_RemoveEdges (removeedges[iv]);
+
+		if (edge_head.next != &edge_tail)
+			R_StepActiveU (edge_head.next);
+	}
+
+// do the last scan (no need to step or sort or remove on the last scan)
+
+	current_iv = iv;
+	fv = (float)iv;
+
+// mark that the head (background start) span is pre-included
+	surfaces[1].spanstate = 1;
+
+	if (newedges[iv])
+		R_InsertNewEdges (newedges[iv], edge_head.next);
+
+	(*pdrawfunc) ();
+
+// draw whatever's left in the span list
+	if (r_drawculledpolys)
+		R_DrawCulledPolys ();
+	else
+		D_DrawSurfaces ();
+}
+
+
--- /dev/null
+++ b/QW/client/r_edgea.asm
@@ -1,0 +1,699 @@
+ .386P
+ .model FLAT
+ externdef _d_zistepu:dword
+ externdef _d_pzbuffer:dword
+ externdef _d_zistepv:dword
+ externdef _d_zrowbytes:dword
+ externdef _d_ziorigin:dword
+ externdef _r_turb_s:dword
+ externdef _r_turb_t:dword
+ externdef _r_turb_pdest:dword
+ externdef _r_turb_spancount:dword
+ externdef _r_turb_turb:dword
+ externdef _r_turb_pbase:dword
+ externdef _r_turb_sstep:dword
+ externdef _r_turb_tstep:dword
+ externdef _r_bmodelactive:dword
+ externdef _d_sdivzstepu:dword
+ externdef _d_tdivzstepu:dword
+ externdef _d_sdivzstepv:dword
+ externdef _d_tdivzstepv:dword
+ externdef _d_sdivzorigin:dword
+ externdef _d_tdivzorigin:dword
+ externdef _sadjust:dword
+ externdef _tadjust:dword
+ externdef _bbextents:dword
+ externdef _bbextentt:dword
+ externdef _cacheblock:dword
+ externdef _d_viewbuffer:dword
+ externdef _cachewidth:dword
+ externdef _d_pzbuffer:dword
+ externdef _d_zrowbytes:dword
+ externdef _d_zwidth:dword
+ externdef _d_scantable:dword
+ externdef _r_lightptr:dword
+ externdef _r_numvblocks:dword
+ externdef _prowdestbase:dword
+ externdef _pbasesource:dword
+ externdef _r_lightwidth:dword
+ externdef _lightright:dword
+ externdef _lightrightstep:dword
+ externdef _lightdeltastep:dword
+ externdef _lightdelta:dword
+ externdef _lightright:dword
+ externdef _lightdelta:dword
+ externdef _sourcetstep:dword
+ externdef _surfrowbytes:dword
+ externdef _lightrightstep:dword
+ externdef _lightdeltastep:dword
+ externdef _r_sourcemax:dword
+ externdef _r_stepback:dword
+ externdef _colormap:dword
+ externdef _blocksize:dword
+ externdef _sourcesstep:dword
+ externdef _lightleft:dword
+ externdef _blockdivshift:dword
+ externdef _blockdivmask:dword
+ externdef _lightleftstep:dword
+ externdef _r_origin:dword
+ externdef _r_ppn:dword
+ externdef _r_pup:dword
+ externdef _r_pright:dword
+ externdef _ycenter:dword
+ externdef _xcenter:dword
+ externdef _d_vrectbottom_particle:dword
+ externdef _d_vrectright_particle:dword
+ externdef _d_vrecty:dword
+ externdef _d_vrectx:dword
+ externdef _d_pix_shift:dword
+ externdef _d_pix_min:dword
+ externdef _d_pix_max:dword
+ externdef _d_y_aspect_shift:dword
+ externdef _screenwidth:dword
+ externdef _vright:dword
+ externdef _vup:dword
+ externdef _vpn:dword
+ externdef _BOPS_Error:dword
+ externdef _snd_scaletable:dword
+ externdef _paintbuffer:dword
+ externdef _snd_linear_count:dword
+ externdef _snd_p:dword
+ externdef _snd_vol:dword
+ externdef _snd_out:dword
+ externdef _r_leftclipped:dword
+ externdef _r_leftenter:dword
+ externdef _r_rightclipped:dword
+ externdef _r_rightenter:dword
+ externdef _modelorg:dword
+ externdef _xscale:dword
+ externdef _r_refdef:dword
+ externdef _yscale:dword
+ externdef _r_leftexit:dword
+ externdef _r_rightexit:dword
+ externdef _r_lastvertvalid:dword
+ externdef _cacheoffset:dword
+ externdef _newedges:dword
+ externdef _removeedges:dword
+ externdef _r_pedge:dword
+ externdef _r_framecount:dword
+ externdef _r_u1:dword
+ externdef _r_emitted:dword
+ externdef _edge_p:dword
+ externdef _surface_p:dword
+ externdef _surfaces:dword
+ externdef _r_lzi1:dword
+ externdef _r_v1:dword
+ externdef _r_ceilv1:dword
+ externdef _r_nearzi:dword
+ externdef _r_nearzionly:dword
+ externdef _edge_aftertail:dword
+ externdef _edge_tail:dword
+ externdef _current_iv:dword
+ externdef _edge_head_u_shift20:dword
+ externdef _span_p:dword
+ externdef _edge_head:dword
+ externdef _fv:dword
+ externdef _edge_tail_u_shift20:dword
+ externdef _r_apverts:dword
+ externdef _r_anumverts:dword
+ externdef _aliastransform:dword
+ externdef _r_avertexnormals:dword
+ externdef _r_plightvec:dword
+ externdef _r_ambientlight:dword
+ externdef _r_shadelight:dword
+ externdef _aliasxcenter:dword
+ externdef _aliasycenter:dword
+ externdef _a_sstepxfrac:dword
+ externdef _r_affinetridesc:dword
+ externdef _acolormap:dword
+ externdef _d_pcolormap:dword
+ externdef _r_affinetridesc:dword
+ externdef _d_sfrac:dword
+ externdef _d_ptex:dword
+ externdef _d_pedgespanpackage:dword
+ externdef _d_tfrac:dword
+ externdef _d_light:dword
+ externdef _d_zi:dword
+ externdef _d_pdest:dword
+ externdef _d_pz:dword
+ externdef _d_aspancount:dword
+ externdef _erroradjustup:dword
+ externdef _errorterm:dword
+ externdef _d_xdenom:dword
+ externdef _r_p0:dword
+ externdef _r_p1:dword
+ externdef _r_p2:dword
+ externdef _a_tstepxfrac:dword
+ externdef _r_sstepx:dword
+ externdef _r_tstepx:dword
+ externdef _a_ststepxwhole:dword
+ externdef _zspantable:dword
+ externdef _skintable:dword
+ externdef _r_zistepx:dword
+ externdef _erroradjustdown:dword
+ externdef _d_countextrastep:dword
+ externdef _ubasestep:dword
+ externdef _a_ststepxwhole:dword
+ externdef _a_tstepxfrac:dword
+ externdef _r_lstepx:dword
+ externdef _a_spans:dword
+ externdef _erroradjustdown:dword
+ externdef _d_pdestextrastep:dword
+ externdef _d_pzextrastep:dword
+ externdef _d_sfracextrastep:dword
+ externdef _d_ptexextrastep:dword
+ externdef _d_countextrastep:dword
+ externdef _d_tfracextrastep:dword
+ externdef _d_lightextrastep:dword
+ externdef _d_ziextrastep:dword
+ externdef _d_pdestbasestep:dword
+ externdef _d_pzbasestep:dword
+ externdef _d_sfracbasestep:dword
+ externdef _d_ptexbasestep:dword
+ externdef _ubasestep:dword
+ externdef _d_tfracbasestep:dword
+ externdef _d_lightbasestep:dword
+ externdef _d_zibasestep:dword
+ externdef _zspantable:dword
+ externdef _r_lstepy:dword
+ externdef _r_sstepy:dword
+ externdef _r_tstepy:dword
+ externdef _r_zistepy:dword
+ externdef _D_PolysetSetEdgeTable:dword
+ externdef _D_RasterizeAliasPolySmooth:dword
+ externdef float_point5:dword
+ externdef Float2ToThe31nd:dword
+ externdef izistep:dword
+ externdef izi:dword
+ externdef FloatMinus2ToThe31nd:dword
+ externdef float_1:dword
+ externdef float_particle_z_clip:dword
+ externdef float_minus_1:dword
+ externdef float_0:dword
+ externdef fp_16:dword
+ externdef fp_64k:dword
+ externdef fp_1m:dword
+ externdef fp_1m_minus_1:dword
+ externdef fp_8:dword
+ externdef entryvec_table:dword
+ externdef advancetable:dword
+ externdef sstep:dword
+ externdef tstep:dword
+ externdef pspantemp:dword
+ externdef counttemp:dword
+ externdef jumptemp:dword
+ externdef reciprocal_table:dword
+ externdef DP_Count:dword
+ externdef DP_u:dword
+ externdef DP_v:dword
+ externdef DP_32768:dword
+ externdef DP_Color:dword
+ externdef DP_Pix:dword
+ externdef DP_EntryTable:dword
+ externdef pbase:dword
+ externdef s:dword
+ externdef t:dword
+ externdef sfracf:dword
+ externdef tfracf:dword
+ externdef snext:dword
+ externdef tnext:dword
+ externdef spancountminus1:dword
+ externdef zi16stepu:dword
+ externdef sdivz16stepu:dword
+ externdef tdivz16stepu:dword
+ externdef zi8stepu:dword
+ externdef sdivz8stepu:dword
+ externdef tdivz8stepu:dword
+ externdef reciprocal_table_16:dword
+ externdef entryvec_table_16:dword
+ externdef ceil_cw:dword
+ externdef single_cw:dword
+ externdef fp_64kx64k:dword
+ externdef pz:dword
+ externdef spr8entryvec_table:dword
+_DATA SEGMENT
+Ltemp dd 0
+float_1_div_0100000h dd 035800000h
+float_point_999 dd 0.999
+float_1_point_001 dd 1.001
+_DATA ENDS
+_TEXT SEGMENT
+ public _R_EdgeCodeStart
+_R_EdgeCodeStart:
+ public _R_InsertNewEdges
+_R_InsertNewEdges:
+ push edi
+ push esi
+ mov edx,ds:dword ptr[4+8+esp]
+ push ebx
+ mov ecx,ds:dword ptr[8+12+esp]
+LDoNextEdge:
+ mov eax,ds:dword ptr[0+edx]
+ mov edi,edx
+LContinueSearch:
+ mov ebx,ds:dword ptr[0+ecx]
+ mov esi,ds:dword ptr[12+ecx]
+ cmp eax,ebx
+ jle LAddedge
+ mov ebx,ds:dword ptr[0+esi]
+ mov ecx,ds:dword ptr[12+esi]
+ cmp eax,ebx
+ jle LAddedge2
+ mov ebx,ds:dword ptr[0+ecx]
+ mov esi,ds:dword ptr[12+ecx]
+ cmp eax,ebx
+ jle LAddedge
+ mov ebx,ds:dword ptr[0+esi]
+ mov ecx,ds:dword ptr[12+esi]
+ cmp eax,ebx
+ jg LContinueSearch
+LAddedge2:
+ mov edx,ds:dword ptr[12+edx]
+ mov ebx,ds:dword ptr[8+esi]
+ mov ds:dword ptr[12+edi],esi
+ mov ds:dword ptr[8+edi],ebx
+ mov ds:dword ptr[12+ebx],edi
+ mov ds:dword ptr[8+esi],edi
+ mov ecx,esi
+ cmp edx,0
+ jnz LDoNextEdge
+ jmp LDone
+ align 4
+LAddedge:
+ mov edx,ds:dword ptr[12+edx]
+ mov ebx,ds:dword ptr[8+ecx]
+ mov ds:dword ptr[12+edi],ecx
+ mov ds:dword ptr[8+edi],ebx
+ mov ds:dword ptr[12+ebx],edi
+ mov ds:dword ptr[8+ecx],edi
+ cmp edx,0
+ jnz LDoNextEdge
+LDone:
+ pop ebx
+ pop esi
+ pop edi
+ ret
+ public _R_RemoveEdges
+_R_RemoveEdges:
+ push ebx
+ mov eax,ds:dword ptr[4+4+esp]
+Lre_loop:
+ mov ecx,ds:dword ptr[12+eax]
+ mov ebx,ds:dword ptr[20+eax]
+ mov edx,ds:dword ptr[8+eax]
+ test ebx,ebx
+ mov ds:dword ptr[8+ecx],edx
+ jz Lre_done
+ mov ds:dword ptr[12+edx],ecx
+ mov ecx,ds:dword ptr[12+ebx]
+ mov edx,ds:dword ptr[8+ebx]
+ mov eax,ds:dword ptr[20+ebx]
+ mov ds:dword ptr[8+ecx],edx
+ test eax,eax
+ mov ds:dword ptr[12+edx],ecx
+ jnz Lre_loop
+ pop ebx
+ ret
+Lre_done:
+ mov ds:dword ptr[12+edx],ecx
+ pop ebx
+ ret
+ public _R_StepActiveU
+_R_StepActiveU:
+ push edi
+ mov edx,ds:dword ptr[4+4+esp]
+ push esi
+ push ebx
+ mov esi,ds:dword ptr[8+edx]
+LNewEdge:
+ mov edi,ds:dword ptr[0+esi]
+LNextEdge:
+ mov eax,ds:dword ptr[0+edx]
+ mov ebx,ds:dword ptr[4+edx]
+ add eax,ebx
+ mov esi,ds:dword ptr[12+edx]
+ mov ds:dword ptr[0+edx],eax
+ cmp eax,edi
+ jl LPushBack
+ mov edi,ds:dword ptr[0+esi]
+ mov ebx,ds:dword ptr[4+esi]
+ add edi,ebx
+ mov edx,ds:dword ptr[12+esi]
+ mov ds:dword ptr[0+esi],edi
+ cmp edi,eax
+ jl LPushBack2
+ mov eax,ds:dword ptr[0+edx]
+ mov ebx,ds:dword ptr[4+edx]
+ add eax,ebx
+ mov esi,ds:dword ptr[12+edx]
+ mov ds:dword ptr[0+edx],eax
+ cmp eax,edi
+ jl LPushBack
+ mov edi,ds:dword ptr[0+esi]
+ mov ebx,ds:dword ptr[4+esi]
+ add edi,ebx
+ mov edx,ds:dword ptr[12+esi]
+ mov ds:dword ptr[0+esi],edi
+ cmp edi,eax
+ jnl LNextEdge
+LPushBack2:
+ mov ebx,edx
+ mov eax,edi
+ mov edx,esi
+ mov esi,ebx
+LPushBack:
+ mov ecx,ds:dword ptr[8+edx]
+ mov ebx,ds:dword ptr[12+edx]
+ cmp edx,offset _edge_aftertail
+ jz LUDone
+ mov edi,ds:dword ptr[8+ecx]
+ mov ds:dword ptr[8+esi],ecx
+ mov ds:dword ptr[12+ecx],ebx
+LPushBackLoop:
+ mov ecx,ds:dword ptr[8+edi]
+ mov ebx,ds:dword ptr[0+edi]
+ cmp eax,ebx
+ jnl LPushBackFound
+ mov edi,ds:dword ptr[8+ecx]
+ mov ebx,ds:dword ptr[0+ecx]
+ cmp eax,ebx
+ jl LPushBackLoop
+ mov edi,ecx
+LPushBackFound:
+ mov ebx,ds:dword ptr[12+edi]
+ mov ds:dword ptr[8+edx],edi
+ mov ds:dword ptr[12+edx],ebx
+ mov ds:dword ptr[12+edi],edx
+ mov ds:dword ptr[8+ebx],edx
+ mov edx,esi
+ mov esi,ds:dword ptr[8+esi]
+ cmp edx,offset _edge_tail
+ jnz LNewEdge
+LUDone:
+ pop ebx
+ pop esi
+ pop edi
+ ret
+ align 4
+TrailingEdge:
+ mov eax,ds:dword ptr[20+esi]
+ dec eax
+ jnz LInverted
+ mov ds:dword ptr[20+esi],eax
+ mov ecx,ds:dword ptr[40+esi]
+ mov edx,ds:dword ptr[12345678h]
+LPatch0:
+ mov eax,ds:dword ptr[_r_bmodelactive]
+ sub eax,ecx
+ cmp edx,esi
+ mov ds:dword ptr[_r_bmodelactive],eax
+ jnz LNoEmit
+ mov eax,ds:dword ptr[0+ebx]
+ shr eax,20
+ mov edx,ds:dword ptr[16+esi]
+ mov ecx,ds:dword ptr[0+esi]
+ cmp eax,edx
+ jle LNoEmit2
+ mov ds:dword ptr[16+ecx],eax
+ sub eax,edx
+ mov ds:dword ptr[0+ebp],edx
+ mov ds:dword ptr[8+ebp],eax
+ mov eax,ds:dword ptr[_current_iv]
+ mov ds:dword ptr[4+ebp],eax
+ mov eax,ds:dword ptr[8+esi]
+ mov ds:dword ptr[12+ebp],eax
+ mov ds:dword ptr[8+esi],ebp
+ add ebp,16
+ mov edx,ds:dword ptr[0+esi]
+ mov esi,ds:dword ptr[4+esi]
+ mov ds:dword ptr[0+esi],edx
+ mov ds:dword ptr[4+edx],esi
+ ret
+LNoEmit2:
+ mov ds:dword ptr[16+ecx],eax
+ mov edx,ds:dword ptr[0+esi]
+ mov esi,ds:dword ptr[4+esi]
+ mov ds:dword ptr[0+esi],edx
+ mov ds:dword ptr[4+edx],esi
+ ret
+LNoEmit:
+ mov edx,ds:dword ptr[0+esi]
+ mov esi,ds:dword ptr[4+esi]
+ mov ds:dword ptr[0+esi],edx
+ mov ds:dword ptr[4+edx],esi
+ ret
+LInverted:
+ mov ds:dword ptr[20+esi],eax
+ ret
+Lgs_trailing:
+ push offset Lgs_nextedge
+ jmp TrailingEdge
+ public _R_GenerateSpans
+_R_GenerateSpans:
+ push ebp
+ push edi
+ push esi
+ push ebx
+ mov eax,ds:dword ptr[_surfaces]
+ mov edx,ds:dword ptr[_edge_head_u_shift20]
+ add eax,64
+ mov ebp,ds:dword ptr[_span_p]
+ mov ds:dword ptr[_r_bmodelactive],0
+ mov ds:dword ptr[0+eax],eax
+ mov ds:dword ptr[4+eax],eax
+ mov ds:dword ptr[16+eax],edx
+ mov ebx,ds:dword ptr[_edge_head+12]
+ cmp ebx,offset _edge_tail
+ jz Lgs_lastspan
+Lgs_edgeloop:
+ mov edi,ds:dword ptr[16+ebx]
+ mov eax,ds:dword ptr[_surfaces]
+ mov esi,edi
+ and edi,0FFFF0000h
+ and esi,0FFFFh
+ jz Lgs_leading
+ shl esi,6
+ add esi,eax
+ test edi,edi
+ jz Lgs_trailing
+ call near ptr TrailingEdge
+ mov eax,ds:dword ptr[_surfaces]
+Lgs_leading:
+ shr edi,16-6
+ mov eax,ds:dword ptr[_surfaces]
+ add edi,eax
+ mov esi,ds:dword ptr[12345678h]
+LPatch2:
+ mov edx,ds:dword ptr[20+edi]
+ mov eax,ds:dword ptr[40+edi]
+ test eax,eax
+ jnz Lbmodel_leading
+ test edx,edx
+ jnz Lxl_done
+ inc edx
+ mov eax,ds:dword ptr[12+edi]
+ mov ds:dword ptr[20+edi],edx
+ mov ecx,ds:dword ptr[12+esi]
+ cmp eax,ecx
+ jl Lnewtop
+Lsortloopnb:
+ mov esi,ds:dword ptr[0+esi]
+ mov ecx,ds:dword ptr[12+esi]
+ cmp eax,ecx
+ jge Lsortloopnb
+ jmp LInsertAndExit
+ align 4
+Lbmodel_leading:
+ test edx,edx
+ jnz Lxl_done
+ mov ecx,ds:dword ptr[_r_bmodelactive]
+ inc edx
+ inc ecx
+ mov ds:dword ptr[20+edi],edx
+ mov ds:dword ptr[_r_bmodelactive],ecx
+ mov eax,ds:dword ptr[12+edi]
+ mov ecx,ds:dword ptr[12+esi]
+ cmp eax,ecx
+ jl Lnewtop
+ jz Lzcheck_for_newtop
+Lsortloop:
+ mov esi,ds:dword ptr[0+esi]
+ mov ecx,ds:dword ptr[12+esi]
+ cmp eax,ecx
+ jg Lsortloop
+ jne LInsertAndExit
+ mov eax,ds:dword ptr[0+ebx]
+ sub eax,0FFFFFh
+ mov ds:dword ptr[Ltemp],eax
+ fild ds:dword ptr[Ltemp]
+ fmul ds:dword ptr[float_1_div_0100000h]
+ fld st(0)
+ fmul ds:dword ptr[48+edi]
+ fld ds:dword ptr[_fv]
+ fmul ds:dword ptr[52+edi]
+ fxch st(1)
+ fadd ds:dword ptr[44+edi]
+ fld ds:dword ptr[48+esi]
+ fmul st(0),st(3)
+ fxch st(1)
+ faddp st(2),st(0)
+ fld ds:dword ptr[_fv]
+ fmul ds:dword ptr[52+esi]
+ fld st(2)
+ fmul ds:dword ptr[float_point_999]
+ fxch st(2)
+ fadd ds:dword ptr[44+esi]
+ faddp st(1),st(0)
+ fxch st(1)
+ fcomp st(1)
+ fxch st(1)
+ fmul ds:dword ptr[float_1_point_001]
+ fxch st(1)
+ fnstsw ax
+ test ah,001h
+ jz Lgotposition_fpop3
+ fcomp st(1)
+ fnstsw ax
+ test ah,045h
+ jz Lsortloop_fpop2
+ fld ds:dword ptr[48+edi]
+ fcomp ds:dword ptr[48+esi]
+ fnstsw ax
+ test ah,001h
+ jz Lgotposition_fpop2
+ fstp st(0)
+ fstp st(0)
+ mov eax,ds:dword ptr[12+edi]
+ jmp Lsortloop
+Lgotposition_fpop3:
+ fstp st(0)
+Lgotposition_fpop2:
+ fstp st(0)
+ fstp st(0)
+ jmp LInsertAndExit
+Lnewtop_fpop3:
+ fstp st(0)
+Lnewtop_fpop2:
+ fstp st(0)
+ fstp st(0)
+ mov eax,ds:dword ptr[12+edi]
+Lnewtop:
+ mov eax,ds:dword ptr[0+ebx]
+ mov edx,ds:dword ptr[16+esi]
+ shr eax,20
+ mov ds:dword ptr[16+edi],eax
+ cmp eax,edx
+ jle LInsertAndExit
+ sub eax,edx
+ mov ds:dword ptr[0+ebp],edx
+ mov ds:dword ptr[8+ebp],eax
+ mov eax,ds:dword ptr[_current_iv]
+ mov ds:dword ptr[4+ebp],eax
+ mov eax,ds:dword ptr[8+esi]
+ mov ds:dword ptr[12+ebp],eax
+ mov ds:dword ptr[8+esi],ebp
+ add ebp,16
+LInsertAndExit:
+ mov ds:dword ptr[0+edi],esi
+ mov eax,ds:dword ptr[4+esi]
+ mov ds:dword ptr[4+edi],eax
+ mov ds:dword ptr[4+esi],edi
+ mov ds:dword ptr[0+eax],edi
+Lgs_nextedge:
+ mov ebx,ds:dword ptr[12+ebx]
+ cmp ebx,offset _edge_tail
+ jnz Lgs_edgeloop
+Lgs_lastspan:
+ mov esi,ds:dword ptr[12345678h]
+LPatch3:
+ mov eax,ds:dword ptr[_edge_tail_u_shift20]
+ xor ecx,ecx
+ mov edx,ds:dword ptr[16+esi]
+ sub eax,edx
+ jle Lgs_resetspanstate
+ mov ds:dword ptr[0+ebp],edx
+ mov ds:dword ptr[8+ebp],eax
+ mov eax,ds:dword ptr[_current_iv]
+ mov ds:dword ptr[4+ebp],eax
+ mov eax,ds:dword ptr[8+esi]
+ mov ds:dword ptr[12+ebp],eax
+ mov ds:dword ptr[8+esi],ebp
+ add ebp,16
+Lgs_resetspanstate:
+ mov ds:dword ptr[20+esi],ecx
+ mov esi,ds:dword ptr[0+esi]
+ cmp esi,012345678h
+LPatch4:
+ jnz Lgs_resetspanstate
+ mov ds:dword ptr[_span_p],ebp
+ pop ebx
+ pop esi
+ pop edi
+ pop ebp
+ ret
+ align 4
+Lxl_done:
+ inc edx
+ mov ds:dword ptr[20+edi],edx
+ jmp Lgs_nextedge
+ align 4
+Lzcheck_for_newtop:
+ mov eax,ds:dword ptr[0+ebx]
+ sub eax,0FFFFFh
+ mov ds:dword ptr[Ltemp],eax
+ fild ds:dword ptr[Ltemp]
+ fmul ds:dword ptr[float_1_div_0100000h]
+ fld st(0)
+ fmul ds:dword ptr[48+edi]
+ fld ds:dword ptr[_fv]
+ fmul ds:dword ptr[52+edi]
+ fxch st(1)
+ fadd ds:dword ptr[44+edi]
+ fld ds:dword ptr[48+esi]
+ fmul st(0),st(3)
+ fxch st(1)
+ faddp st(2),st(0)
+ fld ds:dword ptr[_fv]
+ fmul ds:dword ptr[52+esi]
+ fld st(2)
+ fmul ds:dword ptr[float_point_999]
+ fxch st(2)
+ fadd ds:dword ptr[44+esi]
+ faddp st(1),st(0)
+ fxch st(1)
+ fcomp st(1)
+ fxch st(1)
+ fmul ds:dword ptr[float_1_point_001]
+ fxch st(1)
+ fnstsw ax
+ test ah,001h
+ jz Lnewtop_fpop3
+ fcomp st(1)
+ fnstsw ax
+ test ah,045h
+ jz Lsortloop_fpop2
+ fld ds:dword ptr[48+edi]
+ fcomp ds:dword ptr[48+esi]
+ fnstsw ax
+ test ah,001h
+ jz Lnewtop_fpop2
+Lsortloop_fpop2:
+ fstp st(0)
+ fstp st(0)
+ mov eax,ds:dword ptr[12+edi]
+ jmp Lsortloop
+ public _R_EdgeCodeEnd
+_R_EdgeCodeEnd:
+ align 4
+ public _R_SurfacePatch
+_R_SurfacePatch:
+ mov eax,ds:dword ptr[_surfaces]
+ add eax,64
+ mov ds:dword ptr[LPatch4-4],eax
+ add eax,0
+ mov ds:dword ptr[LPatch0-4],eax
+ mov ds:dword ptr[LPatch2-4],eax
+ mov ds:dword ptr[LPatch3-4],eax
+ ret
+_TEXT ENDS
+ END
--- /dev/null
+++ b/QW/client/r_edgea.s
@@ -1,0 +1,750 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+//
+// r_edgea.s
+// x86 assembly-language edge-processing code.
+//
+
+#include "asm_i386.h"
+#include "quakeasm.h"
+#include "asm_draw.h"
+
+#if	id386
+
+	.data
+Ltemp:					.long	0
+float_1_div_0100000h:	.long	0x35800000	// 1.0/(float)0x100000
+float_point_999:		.single	0.999
+float_1_point_001:		.single	1.001
+
+	.text
+
+//--------------------------------------------------------------------
+
+#define edgestoadd	4+8		// note odd stack offsets because of interleaving
+#define edgelist	8+12	// with pushes
+
+.globl C(R_EdgeCodeStart)
+C(R_EdgeCodeStart):
+
+.globl C(R_InsertNewEdges)
+C(R_InsertNewEdges):
+	pushl	%edi
+	pushl	%esi				// preserve register variables
+	movl	edgestoadd(%esp),%edx
+	pushl	%ebx
+	movl	edgelist(%esp),%ecx
+
+LDoNextEdge:
+	movl	et_u(%edx),%eax
+	movl	%edx,%edi
+
+LContinueSearch:
+	movl	et_u(%ecx),%ebx
+	movl	et_next(%ecx),%esi
+	cmpl	%ebx,%eax
+	jle		LAddedge
+	movl	et_u(%esi),%ebx
+	movl	et_next(%esi),%ecx
+	cmpl	%ebx,%eax
+	jle		LAddedge2
+	movl	et_u(%ecx),%ebx
+	movl	et_next(%ecx),%esi
+	cmpl	%ebx,%eax
+	jle		LAddedge
+	movl	et_u(%esi),%ebx
+	movl	et_next(%esi),%ecx
+	cmpl	%ebx,%eax
+	jg		LContinueSearch
+
+LAddedge2:
+	movl	et_next(%edx),%edx
+	movl	et_prev(%esi),%ebx
+	movl	%esi,et_next(%edi)
+	movl	%ebx,et_prev(%edi)
+	movl	%edi,et_next(%ebx)
+	movl	%edi,et_prev(%esi)
+	movl	%esi,%ecx
+
+	cmpl	$0,%edx
+	jnz		LDoNextEdge
+	jmp		LDone
+
+	.align 4
+LAddedge:
+	movl	et_next(%edx),%edx
+	movl	et_prev(%ecx),%ebx
+	movl	%ecx,et_next(%edi)
+	movl	%ebx,et_prev(%edi)
+	movl	%edi,et_next(%ebx)
+	movl	%edi,et_prev(%ecx)
+
+	cmpl	$0,%edx
+	jnz		LDoNextEdge
+
+LDone:
+	popl	%ebx				// restore register variables
+	popl	%esi
+	popl	%edi
+
+	ret
+
+//--------------------------------------------------------------------
+
+#define predge	4+4
+
+.globl C(R_RemoveEdges)
+C(R_RemoveEdges):
+	pushl	%ebx
+	movl	predge(%esp),%eax
+
+Lre_loop:
+	movl	et_next(%eax),%ecx
+	movl	et_nextremove(%eax),%ebx
+	movl	et_prev(%eax),%edx
+	testl	%ebx,%ebx
+	movl	%edx,et_prev(%ecx)
+	jz		Lre_done
+	movl	%ecx,et_next(%edx)
+
+	movl	et_next(%ebx),%ecx
+	movl	et_prev(%ebx),%edx
+	movl	et_nextremove(%ebx),%eax
+	movl	%edx,et_prev(%ecx)
+	testl	%eax,%eax
+	movl	%ecx,et_next(%edx)
+	jnz		Lre_loop
+
+	popl	%ebx
+	ret
+
+Lre_done:
+	movl	%ecx,et_next(%edx)
+	popl	%ebx
+
+	ret
+
+//--------------------------------------------------------------------
+
+#define pedgelist	4+4		// note odd stack offset because of interleaving
+							// with pushes
+
+.globl C(R_StepActiveU)
+C(R_StepActiveU):
+	pushl	%edi
+	movl	pedgelist(%esp),%edx
+	pushl	%esi				// preserve register variables
+	pushl	%ebx
+
+	movl	et_prev(%edx),%esi
+
+LNewEdge:
+	movl	et_u(%esi),%edi
+
+LNextEdge:
+	movl	et_u(%edx),%eax
+	movl	et_u_step(%edx),%ebx
+	addl	%ebx,%eax
+	movl	et_next(%edx),%esi
+	movl	%eax,et_u(%edx)
+	cmpl	%edi,%eax
+	jl		LPushBack
+
+	movl	et_u(%esi),%edi
+	movl	et_u_step(%esi),%ebx
+	addl	%ebx,%edi
+	movl	et_next(%esi),%edx
+	movl	%edi,et_u(%esi)
+	cmpl	%eax,%edi
+	jl		LPushBack2
+
+	movl	et_u(%edx),%eax
+	movl	et_u_step(%edx),%ebx
+	addl	%ebx,%eax
+	movl	et_next(%edx),%esi
+	movl	%eax,et_u(%edx)
+	cmpl	%edi,%eax
+	jl		LPushBack
+
+	movl	et_u(%esi),%edi
+	movl	et_u_step(%esi),%ebx
+	addl	%ebx,%edi
+	movl	et_next(%esi),%edx
+	movl	%edi,et_u(%esi)
+	cmpl	%eax,%edi
+	jnl		LNextEdge
+
+LPushBack2:
+	movl	%edx,%ebx
+	movl	%edi,%eax
+	movl	%esi,%edx
+	movl	%ebx,%esi
+
+LPushBack:
+// push it back to keep it sorted
+	movl	et_prev(%edx),%ecx
+	movl	et_next(%edx),%ebx
+
+// done if the -1 in edge_aftertail triggered this
+	cmpl	$(C(edge_aftertail)),%edx
+	jz		LUDone
+
+// pull the edge out of the edge list
+	movl	et_prev(%ecx),%edi
+	movl	%ecx,et_prev(%esi)
+	movl	%ebx,et_next(%ecx)
+
+// find out where the edge goes in the edge list
+LPushBackLoop:
+	movl	et_prev(%edi),%ecx
+	movl	et_u(%edi),%ebx
+	cmpl	%ebx,%eax
+	jnl		LPushBackFound
+
+	movl	et_prev(%ecx),%edi
+	movl	et_u(%ecx),%ebx
+	cmpl	%ebx,%eax
+	jl		LPushBackLoop
+
+	movl	%ecx,%edi
+
+// put the edge back into the edge list
+LPushBackFound:
+	movl	et_next(%edi),%ebx
+	movl	%edi,et_prev(%edx)
+	movl	%ebx,et_next(%edx)
+	movl	%edx,et_next(%edi)
+	movl	%edx,et_prev(%ebx)
+
+	movl	%esi,%edx
+	movl	et_prev(%esi),%esi
+
+	cmpl	$(C(edge_tail)),%edx
+	jnz		LNewEdge
+
+LUDone:
+	popl	%ebx				// restore register variables
+	popl	%esi
+	popl	%edi
+
+	ret
+
+//--------------------------------------------------------------------
+
+#define surf	4		// note this is loaded before any pushes
+
+	.align 4
+TrailingEdge:
+	movl	st_spanstate(%esi),%eax	// check for edge inversion
+	decl	%eax
+	jnz		LInverted
+
+	movl	%eax,st_spanstate(%esi)
+	movl	st_insubmodel(%esi),%ecx
+	movl	0x12345678,%edx		// surfaces[1].st_next
+LPatch0:
+	movl	C(r_bmodelactive),%eax
+	subl	%ecx,%eax
+	cmpl	%esi,%edx
+	movl	%eax,C(r_bmodelactive)
+	jnz		LNoEmit				// surface isn't on top, just remove
+
+// emit a span (current top going away)
+	movl	et_u(%ebx),%eax
+	shrl	$20,%eax				// iu = integral pixel u
+	movl	st_last_u(%esi),%edx
+	movl	st_next(%esi),%ecx
+	cmpl	%edx,%eax
+	jle		LNoEmit2				// iu <= surf->last_u, so nothing to emit
+
+	movl	%eax,st_last_u(%ecx)	// surf->next->last_u = iu;
+	subl	%edx,%eax
+	movl	%edx,espan_t_u(%ebp)		// span->u = surf->last_u;
+
+	movl	%eax,espan_t_count(%ebp)	// span->count = iu - span->u;
+	movl	C(current_iv),%eax
+	movl	%eax,espan_t_v(%ebp)		// span->v = current_iv;
+	movl	st_spans(%esi),%eax
+	movl	%eax,espan_t_pnext(%ebp)	// span->pnext = surf->spans;
+	movl	%ebp,st_spans(%esi)			// surf->spans = span;
+	addl	$(espan_t_size),%ebp
+
+	movl	st_next(%esi),%edx		// remove the surface from the surface
+	movl	st_prev(%esi),%esi		// stack
+
+	movl	%edx,st_next(%esi)
+	movl	%esi,st_prev(%edx)
+	ret
+
+LNoEmit2:
+	movl	%eax,st_last_u(%ecx)	// surf->next->last_u = iu;
+	movl	st_next(%esi),%edx		// remove the surface from the surface
+	movl	st_prev(%esi),%esi		// stack
+
+	movl	%edx,st_next(%esi)
+	movl	%esi,st_prev(%edx)
+	ret
+
+LNoEmit:
+	movl	st_next(%esi),%edx		// remove the surface from the surface
+	movl	st_prev(%esi),%esi		// stack
+
+	movl	%edx,st_next(%esi)
+	movl	%esi,st_prev(%edx)
+	ret
+
+LInverted:
+	movl	%eax,st_spanstate(%esi)
+	ret
+
+//--------------------------------------------------------------------
+
+// trailing edge only
+Lgs_trailing:
+	pushl	$Lgs_nextedge
+	jmp		TrailingEdge
+
+
+.globl C(R_GenerateSpans)
+C(R_GenerateSpans):
+	pushl	%ebp				// preserve caller's stack frame
+	pushl	%edi
+	pushl	%esi				// preserve register variables
+	pushl	%ebx
+
+// clear active surfaces to just the background surface
+	movl	C(surfaces),%eax
+	movl	C(edge_head_u_shift20),%edx
+	addl	$(st_size),%eax
+// %ebp = span_p throughout
+	movl	C(span_p),%ebp
+
+	movl	$0,C(r_bmodelactive)
+
+	movl	%eax,st_next(%eax)
+	movl	%eax,st_prev(%eax)
+	movl	%edx,st_last_u(%eax)
+	movl	C(edge_head)+et_next,%ebx		// edge=edge_head.next
+
+// generate spans
+	cmpl	$(C(edge_tail)),%ebx		// done if empty list
+	jz		Lgs_lastspan
+
+Lgs_edgeloop:
+
+	movl	et_surfs(%ebx),%edi
+	movl	C(surfaces),%eax
+	movl	%edi,%esi
+	andl	$0xFFFF0000,%edi
+	andl	$0xFFFF,%esi
+	jz		Lgs_leading		// not a trailing edge
+
+// it has a left surface, so a surface is going away for this span
+	shll	$(SURF_T_SHIFT),%esi
+	addl	%eax,%esi
+	testl	%edi,%edi
+	jz		Lgs_trailing
+
+// both leading and trailing
+	call	TrailingEdge
+	movl	C(surfaces),%eax
+
+// ---------------------------------------------------------------
+// handle a leading edge
+// ---------------------------------------------------------------
+
+Lgs_leading:
+	shrl	$16-SURF_T_SHIFT,%edi
+	movl	C(surfaces),%eax
+	addl	%eax,%edi
+	movl	0x12345678,%esi		// surf2 = surfaces[1].next;
+LPatch2:
+	movl	st_spanstate(%edi),%edx
+	movl	st_insubmodel(%edi),%eax
+	testl	%eax,%eax
+	jnz		Lbmodel_leading
+
+// handle a leading non-bmodel edge
+
+// don't start a span if this is an inverted span, with the end edge preceding
+// the start edge (that is, we've already seen the end edge)
+	testl	%edx,%edx
+	jnz		Lxl_done
+
+
+// if (surf->key < surf2->key)
+//		goto newtop;
+	incl	%edx
+	movl	st_key(%edi),%eax
+	movl	%edx,st_spanstate(%edi)
+	movl	st_key(%esi),%ecx
+	cmpl	%ecx,%eax
+	jl		Lnewtop
+
+// main sorting loop to search through surface stack until insertion point
+// found. Always terminates because background surface is sentinel
+// do
+// {
+// 		surf2 = surf2->next;
+// } while (surf->key >= surf2->key);
+Lsortloopnb:
+	movl	st_next(%esi),%esi
+	movl	st_key(%esi),%ecx
+	cmpl	%ecx,%eax
+	jge		Lsortloopnb
+
+	jmp		LInsertAndExit
+
+
+// handle a leading bmodel edge
+	.align	4
+Lbmodel_leading:
+
+// don't start a span if this is an inverted span, with the end edge preceding
+// the start edge (that is, we've already seen the end edge)
+	testl	%edx,%edx
+	jnz		Lxl_done
+
+	movl	C(r_bmodelactive),%ecx
+	incl	%edx
+	incl	%ecx
+	movl	%edx,st_spanstate(%edi)
+	movl	%ecx,C(r_bmodelactive)
+
+// if (surf->key < surf2->key)
+//		goto newtop;
+	movl	st_key(%edi),%eax
+	movl	st_key(%esi),%ecx
+	cmpl	%ecx,%eax
+	jl		Lnewtop
+
+// if ((surf->key == surf2->key) && surf->insubmodel)
+// {
+	jz		Lzcheck_for_newtop
+
+// main sorting loop to search through surface stack until insertion point
+// found. Always terminates because background surface is sentinel
+// do
+// {
+// 		surf2 = surf2->next;
+// } while (surf->key > surf2->key);
+Lsortloop:
+	movl	st_next(%esi),%esi
+	movl	st_key(%esi),%ecx
+	cmpl	%ecx,%eax
+	jg		Lsortloop
+
+	jne		LInsertAndExit
+
+// Do 1/z sorting to see if we've arrived in the right position
+	movl	et_u(%ebx),%eax
+	subl	$0xFFFFF,%eax
+	movl	%eax,Ltemp
+	fildl	Ltemp
+
+	fmuls	float_1_div_0100000h // fu = (float)(edge->u - 0xFFFFF) *
+								//      (1.0 / 0x100000);
+
+	fld		%st(0)				// fu | fu
+	fmuls	st_d_zistepu(%edi)	// fu*surf->d_zistepu | fu
+	flds	C(fv)					// fv | fu*surf->d_zistepu | fu
+	fmuls	st_d_zistepv(%edi)	// fv*surf->d_zistepv | fu*surf->d_zistepu | fu
+	fxch	%st(1)				// fu*surf->d_zistepu | fv*surf->d_zistepv | fu
+	fadds	st_d_ziorigin(%edi)	// fu*surf->d_zistepu + surf->d_ziorigin |
+								//  fv*surf->d_zistepv | fu
+
+	flds	st_d_zistepu(%esi)	// surf2->d_zistepu |
+								//  fu*surf->d_zistepu + surf->d_ziorigin |
+								//  fv*surf->d_zistepv | fu
+	fmul	%st(3),%st(0)		// fu*surf2->d_zistepu |
+								//  fu*surf->d_zistepu + surf->d_ziorigin |
+								//  fv*surf->d_zistepv | fu
+	fxch	%st(1)				// fu*surf->d_zistepu + surf->d_ziorigin |
+								//  fu*surf2->d_zistepu |
+								//  fv*surf->d_zistepv | fu
+	faddp	%st(0),%st(2)		// fu*surf2->d_zistepu | newzi | fu
+
+	flds	C(fv)					// fv | fu*surf2->d_zistepu | newzi | fu
+	fmuls	st_d_zistepv(%esi)	// fv*surf2->d_zistepv |
+								//  fu*surf2->d_zistepu | newzi | fu
+	fld		%st(2)				// newzi | fv*surf2->d_zistepv |
+								//  fu*surf2->d_zistepu | newzi | fu
+	fmuls	float_point_999		// newzibottom | fv*surf2->d_zistepv |
+								//  fu*surf2->d_zistepu | newzi | fu
+
+	fxch	%st(2)				// fu*surf2->d_zistepu | fv*surf2->d_zistepv |
+								//  newzibottom | newzi | fu
+	fadds	st_d_ziorigin(%esi)	// fu*surf2->d_zistepu + surf2->d_ziorigin |
+								//  fv*surf2->d_zistepv | newzibottom | newzi |
+								//  fu
+	faddp	%st(0),%st(1)		// testzi | newzibottom | newzi | fu
+	fxch	%st(1)				// newzibottom | testzi | newzi | fu
+
+// if (newzibottom >= testzi)
+//     goto Lgotposition;
+
+	fcomp	%st(1)				// testzi | newzi | fu
+
+	fxch	%st(1)				// newzi | testzi | fu
+	fmuls	float_1_point_001	// newzitop | testzi | fu
+	fxch	%st(1)				// testzi | newzitop | fu
+
+	fnstsw	%ax
+	testb	$0x01,%ah
+	jz		Lgotposition_fpop3
+
+// if (newzitop >= testzi)
+// {
+
+	fcomp	%st(1)				// newzitop | fu
+	fnstsw	%ax
+	testb	$0x45,%ah
+	jz		Lsortloop_fpop2
+
+// if (surf->d_zistepu >= surf2->d_zistepu)
+//     goto newtop;
+
+	flds	st_d_zistepu(%edi)	// surf->d_zistepu | newzitop| fu
+	fcomps	st_d_zistepu(%esi)	// newzitop | fu
+	fnstsw	%ax
+	testb	$0x01,%ah
+	jz		Lgotposition_fpop2
+
+	fstp	%st(0)				// clear the FPstack
+	fstp	%st(0)
+	movl	st_key(%edi),%eax
+	jmp		Lsortloop
+
+
+Lgotposition_fpop3:
+	fstp	%st(0)
+Lgotposition_fpop2:
+	fstp	%st(0)
+	fstp	%st(0)
+	jmp		LInsertAndExit
+
+
+// emit a span (obscures current top)
+
+Lnewtop_fpop3:
+	fstp	%st(0)
+Lnewtop_fpop2:
+	fstp	%st(0)
+	fstp	%st(0)
+	movl	st_key(%edi),%eax		// reload the sorting key
+
+Lnewtop:
+	movl	et_u(%ebx),%eax
+	movl	st_last_u(%esi),%edx
+	shrl	$20,%eax				// iu = integral pixel u
+	movl	%eax,st_last_u(%edi)	// surf->last_u = iu;
+	cmpl	%edx,%eax
+	jle		LInsertAndExit			// iu <= surf->last_u, so nothing to emit
+
+	subl	%edx,%eax
+	movl	%edx,espan_t_u(%ebp)		// span->u = surf->last_u;
+
+	movl	%eax,espan_t_count(%ebp)	// span->count = iu - span->u;
+	movl	C(current_iv),%eax
+	movl	%eax,espan_t_v(%ebp)		// span->v = current_iv;
+	movl	st_spans(%esi),%eax
+	movl	%eax,espan_t_pnext(%ebp)	// span->pnext = surf->spans;
+	movl	%ebp,st_spans(%esi)			// surf->spans = span;
+	addl	$(espan_t_size),%ebp
+
+LInsertAndExit:
+// insert before surf2
+	movl	%esi,st_next(%edi)		// surf->next = surf2;
+	movl	st_prev(%esi),%eax
+	movl	%eax,st_prev(%edi)		// surf->prev = surf2->prev;
+	movl	%edi,st_prev(%esi)		// surf2->prev = surf;
+	movl	%edi,st_next(%eax)		// surf2->prev->next = surf;
+
+// ---------------------------------------------------------------
+// leading edge done
+// ---------------------------------------------------------------
+
+// ---------------------------------------------------------------
+// see if there are any more edges
+// ---------------------------------------------------------------
+
+Lgs_nextedge:
+	movl	et_next(%ebx),%ebx
+	cmpl	$(C(edge_tail)),%ebx
+	jnz		Lgs_edgeloop
+
+// clean up at the right edge
+Lgs_lastspan:
+
+// now that we've reached the right edge of the screen, we're done with any
+// unfinished surfaces, so emit a span for whatever's on top
+	movl	0x12345678,%esi		// surfaces[1].st_next
+LPatch3:
+	movl	C(edge_tail_u_shift20),%eax
+	xorl	%ecx,%ecx
+	movl	st_last_u(%esi),%edx
+	subl	%edx,%eax
+	jle		Lgs_resetspanstate
+
+	movl	%edx,espan_t_u(%ebp)
+	movl	%eax,espan_t_count(%ebp)
+	movl	C(current_iv),%eax
+	movl	%eax,espan_t_v(%ebp)
+	movl	st_spans(%esi),%eax
+	movl	%eax,espan_t_pnext(%ebp)
+	movl	%ebp,st_spans(%esi)
+	addl	$(espan_t_size),%ebp
+
+// reset spanstate for all surfaces in the surface stack
+Lgs_resetspanstate:
+	movl	%ecx,st_spanstate(%esi)
+	movl	st_next(%esi),%esi
+	cmpl	$0x12345678,%esi		// &surfaces[1]
+LPatch4:
+	jnz		Lgs_resetspanstate
+
+// store the final span_p
+	movl	%ebp,C(span_p)
+
+	popl	%ebx				// restore register variables
+	popl	%esi
+	popl	%edi
+	popl	%ebp				// restore the caller's stack frame
+	ret
+
+
+// ---------------------------------------------------------------
+// 1/z sorting for bmodels in the same leaf
+// ---------------------------------------------------------------
+	.align	4
+Lxl_done:
+	incl	%edx
+	movl	%edx,st_spanstate(%edi)
+
+	jmp		Lgs_nextedge
+
+
+	.align	4
+Lzcheck_for_newtop:
+	movl	et_u(%ebx),%eax
+	subl	$0xFFFFF,%eax
+	movl	%eax,Ltemp
+	fildl	Ltemp
+
+	fmuls	float_1_div_0100000h // fu = (float)(edge->u - 0xFFFFF) *
+								//      (1.0 / 0x100000);
+
+	fld		%st(0)				// fu | fu
+	fmuls	st_d_zistepu(%edi)	// fu*surf->d_zistepu | fu
+	flds	C(fv)				// fv | fu*surf->d_zistepu | fu
+	fmuls	st_d_zistepv(%edi)	// fv*surf->d_zistepv | fu*surf->d_zistepu | fu
+	fxch	%st(1)				// fu*surf->d_zistepu | fv*surf->d_zistepv | fu
+	fadds	st_d_ziorigin(%edi)	// fu*surf->d_zistepu + surf->d_ziorigin |
+								//  fv*surf->d_zistepv | fu
+
+	flds	st_d_zistepu(%esi)	// surf2->d_zistepu |
+								//  fu*surf->d_zistepu + surf->d_ziorigin |
+								//  fv*surf->d_zistepv | fu
+	fmul	%st(3),%st(0)		// fu*surf2->d_zistepu |
+								//  fu*surf->d_zistepu + surf->d_ziorigin |
+								//  fv*surf->d_zistepv | fu
+	fxch	%st(1)				// fu*surf->d_zistepu + surf->d_ziorigin |
+								//  fu*surf2->d_zistepu |
+								//  fv*surf->d_zistepv | fu
+	faddp	%st(0),%st(2)		// fu*surf2->d_zistepu | newzi | fu
+
+	flds	C(fv)				// fv | fu*surf2->d_zistepu | newzi | fu
+	fmuls	st_d_zistepv(%esi)	// fv*surf2->d_zistepv |
+								//  fu*surf2->d_zistepu | newzi | fu
+	fld		%st(2)				// newzi | fv*surf2->d_zistepv |
+								//  fu*surf2->d_zistepu | newzi | fu
+	fmuls	float_point_999		// newzibottom | fv*surf2->d_zistepv |
+								//  fu*surf2->d_zistepu | newzi | fu
+
+	fxch	%st(2)				// fu*surf2->d_zistepu | fv*surf2->d_zistepv |
+								//  newzibottom | newzi | fu
+	fadds	st_d_ziorigin(%esi)	// fu*surf2->d_zistepu + surf2->d_ziorigin |
+								//  fv*surf2->d_zistepv | newzibottom | newzi |
+								//  fu
+	faddp	%st(0),%st(1)		// testzi | newzibottom | newzi | fu
+	fxch	%st(1)				// newzibottom | testzi | newzi | fu
+
+// if (newzibottom >= testzi)
+//     goto newtop;
+
+	fcomp	%st(1)				// testzi | newzi | fu
+
+	fxch	%st(1)				// newzi | testzi | fu
+	fmuls	float_1_point_001	// newzitop | testzi | fu
+	fxch	%st(1)				// testzi | newzitop | fu
+
+	fnstsw	%ax
+	testb	$0x01,%ah
+	jz		Lnewtop_fpop3
+
+// if (newzitop >= testzi)
+// {
+
+	fcomp	%st(1)				// newzitop | fu
+	fnstsw	%ax
+	testb	$0x45,%ah
+	jz		Lsortloop_fpop2
+
+// if (surf->d_zistepu >= surf2->d_zistepu)
+//     goto newtop;
+
+	flds	st_d_zistepu(%edi)	// surf->d_zistepu | newzitop | fu
+	fcomps	st_d_zistepu(%esi)	// newzitop | fu
+	fnstsw	%ax
+	testb	$0x01,%ah
+	jz		Lnewtop_fpop2
+
+Lsortloop_fpop2:
+	fstp	%st(0)				// clear the FP stack
+	fstp	%st(0)
+	movl	st_key(%edi),%eax
+	jmp		Lsortloop
+
+
+.globl C(R_EdgeCodeEnd)
+C(R_EdgeCodeEnd):
+
+
+//----------------------------------------------------------------------
+// Surface array address code patching routine
+//----------------------------------------------------------------------
+
+	.align 4
+.globl C(R_SurfacePatch)
+C(R_SurfacePatch):
+
+	movl	C(surfaces),%eax
+	addl	$(st_size),%eax
+	movl	%eax,LPatch4-4
+
+	addl	$(st_next),%eax
+	movl	%eax,LPatch0-4
+	movl	%eax,LPatch2-4
+	movl	%eax,LPatch3-4
+
+	ret
+
+#endif	// id386
+
--- /dev/null
+++ b/QW/client/r_efrag.c
@@ -1,0 +1,276 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// r_efrag.c
+
+#include "quakedef.h"
+#include "r_local.h"
+
+mnode_t	*r_pefragtopnode;
+
+
+//===========================================================================
+
+/*
+===============================================================================
+
+					ENTITY FRAGMENT FUNCTIONS
+
+===============================================================================
+*/
+
+efrag_t		**lastlink;
+
+vec3_t		r_emins, r_emaxs;
+
+entity_t	*r_addent;
+
+
+/*
+================
+R_RemoveEfrags
+
+Call when removing an object from the world or moving it to another position
+================
+*/
+void R_RemoveEfrags (entity_t *ent)
+{
+	efrag_t		*ef, *old, *walk, **prev;
+	
+	ef = ent->efrag;
+	
+	while (ef)
+	{
+		prev = &ef->leaf->efrags;
+		while (1)
+		{
+			walk = *prev;
+			if (!walk)
+				break;
+			if (walk == ef)
+			{	// remove this fragment
+				*prev = ef->leafnext;
+				break;
+			}
+			else
+				prev = &walk->leafnext;
+		}
+				
+		old = ef;
+		ef = ef->entnext;
+		
+	// put it on the free list
+		old->entnext = cl.free_efrags;
+		cl.free_efrags = old;
+	}
+	
+	ent->efrag = NULL; 
+}
+
+/*
+===================
+R_SplitEntityOnNode
+===================
+*/
+void R_SplitEntityOnNode (mnode_t *node)
+{
+	efrag_t		*ef;
+	mplane_t	*splitplane;
+	mleaf_t		*leaf;
+	int			sides;
+	
+	if (node->contents == CONTENTS_SOLID)
+	{
+		return;
+	}
+	
+// add an efrag if the node is a leaf
+
+	if ( node->contents < 0)
+	{
+		if (!r_pefragtopnode)
+			r_pefragtopnode = node;
+
+		leaf = (mleaf_t *)node;
+
+// grab an efrag off the free list
+		ef = cl.free_efrags;
+		if (!ef)
+		{
+			Con_Printf ("Too many efrags!\n");
+			return;		// no free fragments...
+		}
+		cl.free_efrags = cl.free_efrags->entnext;
+
+		ef->entity = r_addent;
+		
+// add the entity link	
+		*lastlink = ef;
+		lastlink = &ef->entnext;
+		ef->entnext = NULL;
+		
+// set the leaf links
+		ef->leaf = leaf;
+		ef->leafnext = leaf->efrags;
+		leaf->efrags = ef;
+			
+		return;
+	}
+	
+// NODE_MIXED
+
+	splitplane = node->plane;
+	sides = BOX_ON_PLANE_SIDE(r_emins, r_emaxs, splitplane);
+	
+	if (sides == 3)
+	{
+	// split on this plane
+	// if this is the first splitter of this bmodel, remember it
+		if (!r_pefragtopnode)
+			r_pefragtopnode = node;
+	}
+	
+// recurse down the contacted sides
+	if (sides & 1)
+		R_SplitEntityOnNode (node->children[0]);
+		
+	if (sides & 2)
+		R_SplitEntityOnNode (node->children[1]);
+}
+
+
+/*
+===================
+R_SplitEntityOnNode2
+===================
+*/
+void R_SplitEntityOnNode2 (mnode_t *node)
+{
+	mplane_t	*splitplane;
+	int			sides;
+
+	if (node->visframe != r_visframecount)
+		return;
+	
+	if (node->contents < 0)
+	{
+		if (node->contents != CONTENTS_SOLID)
+			r_pefragtopnode = node; // we've reached a non-solid leaf, so it's
+									//  visible and not BSP clipped
+		return;
+	}
+	
+	splitplane = node->plane;
+	sides = BOX_ON_PLANE_SIDE(r_emins, r_emaxs, splitplane);
+	
+	if (sides == 3)
+	{
+	// remember first splitter
+		r_pefragtopnode = node;
+		return;
+	}
+	
+// not split yet; recurse down the contacted side
+	if (sides & 1)
+		R_SplitEntityOnNode2 (node->children[0]);
+	else
+		R_SplitEntityOnNode2 (node->children[1]);
+}
+
+
+/*
+===========
+R_AddEfrags
+===========
+*/
+void R_AddEfrags (entity_t *ent)
+{
+	model_t		*entmodel;
+	int			i;
+		
+	if (!ent->model)
+		return;
+
+	if (ent == &r_worldentity)
+		return;		// never add the world
+
+	r_addent = ent;
+			
+	lastlink = &ent->efrag;
+	r_pefragtopnode = NULL;
+	
+	entmodel = ent->model;
+
+	for (i=0 ; i<3 ; i++)
+	{
+		r_emins[i] = ent->origin[i] + entmodel->mins[i];
+		r_emaxs[i] = ent->origin[i] + entmodel->maxs[i];
+	}
+
+	R_SplitEntityOnNode (cl.worldmodel->nodes);
+
+	ent->topnode = r_pefragtopnode;
+}
+
+
+/*
+================
+R_StoreEfrags
+
+// FIXME: a lot of this goes away with edge-based
+================
+*/
+void R_StoreEfrags (efrag_t **ppefrag)
+{
+	entity_t	*pent;
+	model_t		*clmodel;
+	efrag_t		*pefrag;
+
+
+	while ((pefrag = *ppefrag) != NULL)
+	{
+		pent = pefrag->entity;
+		clmodel = pent->model;
+
+		switch (clmodel->type)
+		{
+		case mod_alias:
+		case mod_brush:
+		case mod_sprite:
+			pent = pefrag->entity;
+
+			if ((pent->visframe != r_framecount) &&
+				(cl_numvisedicts < MAX_VISEDICTS))
+			{
+				cl_visedicts[cl_numvisedicts++] = *pent;
+
+			// mark that we've recorded this entity for this frame
+				pent->visframe = r_framecount;
+			}
+
+			ppefrag = &pefrag->leafnext;
+			break;
+
+		default:	
+			Sys_Error ("R_StoreEfrags: Bad entity type %d\n", clmodel->type);
+		}
+	}
+}
+
+
--- /dev/null
+++ b/QW/client/r_light.c
@@ -1,0 +1,260 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// r_light.c
+
+#include "quakedef.h"
+#include "r_local.h"
+
+int	r_dlightframecount;
+
+
+/*
+==================
+R_AnimateLight
+==================
+*/
+void R_AnimateLight (void)
+{
+	int			i,j,k;
+	
+//
+// light animations
+// 'm' is normal light, 'a' is no light, 'z' is double bright
+	i = (int)(cl.time*10);
+	for (j=0 ; j<MAX_LIGHTSTYLES ; j++)
+	{
+		if (!cl_lightstyle[j].length)
+		{
+			d_lightstylevalue[j] = 256;
+			continue;
+		}
+		k = i % cl_lightstyle[j].length;
+		k = cl_lightstyle[j].map[k] - 'a';
+		k = k*22;
+		d_lightstylevalue[j] = k;
+	}	
+}
+
+
+/*
+=============================================================================
+
+DYNAMIC LIGHTS
+
+=============================================================================
+*/
+
+/*
+=============
+R_MarkLights
+=============
+*/
+void R_MarkLights (dlight_t *light, int bit, mnode_t *node)
+{
+	mplane_t	*splitplane;
+	float		dist;
+	msurface_t	*surf;
+	int			i;
+	
+	if (node->contents < 0)
+		return;
+
+	splitplane = node->plane;
+	dist = DotProduct (light->origin, splitplane->normal) - splitplane->dist;
+	
+	if (dist > light->radius)
+	{
+		R_MarkLights (light, bit, node->children[0]);
+		return;
+	}
+	if (dist < -light->radius)
+	{
+		R_MarkLights (light, bit, node->children[1]);
+		return;
+	}
+		
+// mark the polygons
+	surf = cl.worldmodel->surfaces + node->firstsurface;
+	for (i=0 ; i<node->numsurfaces ; i++, surf++)
+	{
+		if (surf->dlightframe != r_dlightframecount)
+		{
+			surf->dlightbits = 0;
+			surf->dlightframe = r_dlightframecount;
+		}
+		surf->dlightbits |= bit;
+	}
+
+	R_MarkLights (light, bit, node->children[0]);
+	R_MarkLights (light, bit, node->children[1]);
+}
+
+
+/*
+=============
+R_PushDlights
+=============
+*/
+void R_PushDlights (void)
+{
+	int		i;
+	dlight_t	*l;
+
+	r_dlightframecount = r_framecount + 1;	// because the count hasn't
+											//  advanced yet for this frame
+	l = cl_dlights;
+
+	for (i=0 ; i<MAX_DLIGHTS ; i++, l++)
+	{
+		if (l->die < cl.time || !l->radius)
+			continue;
+		R_MarkLights ( l, 1<<i, cl.worldmodel->nodes );
+	}
+}
+
+
+/*
+=============================================================================
+
+LIGHT SAMPLING
+
+=============================================================================
+*/
+
+int RecursiveLightPoint (mnode_t *node, vec3_t start, vec3_t end)
+{
+	int			r;
+	float		front, back, frac;
+	int			side;
+	mplane_t	*plane;
+	vec3_t		mid;
+	msurface_t	*surf;
+	int			s, t, ds, dt;
+	int			i;
+	mtexinfo_t	*tex;
+	byte		*lightmap;
+	unsigned	scale;
+	int			maps;
+
+	if (node->contents < 0)
+		return -1;		// didn't hit anything
+	
+// calculate mid point
+
+// FIXME: optimize for axial
+	plane = node->plane;
+	front = DotProduct (start, plane->normal) - plane->dist;
+	back = DotProduct (end, plane->normal) - plane->dist;
+	side = front < 0;
+	
+	if ( (back < 0) == side)
+		return RecursiveLightPoint (node->children[side], start, end);
+	
+	frac = front / (front-back);
+	mid[0] = start[0] + (end[0] - start[0])*frac;
+	mid[1] = start[1] + (end[1] - start[1])*frac;
+	mid[2] = start[2] + (end[2] - start[2])*frac;
+	
+// go down front side	
+	r = RecursiveLightPoint (node->children[side], start, mid);
+	if (r >= 0)
+		return r;		// hit something
+		
+	if ( (back < 0) == side )
+		return -1;		// didn't hit anuthing
+		
+// check for impact on this node
+
+	surf = cl.worldmodel->surfaces + node->firstsurface;
+	for (i=0 ; i<node->numsurfaces ; i++, surf++)
+	{
+		if (surf->flags & SURF_DRAWTILED)
+			continue;	// no lightmaps
+
+		tex = surf->texinfo;
+		
+		s = DotProduct (mid, tex->vecs[0]) + tex->vecs[0][3];
+		t = DotProduct (mid, tex->vecs[1]) + tex->vecs[1][3];;
+
+		if (s < surf->texturemins[0] ||
+		t < surf->texturemins[1])
+			continue;
+		
+		ds = s - surf->texturemins[0];
+		dt = t - surf->texturemins[1];
+		
+		if ( ds > surf->extents[0] || dt > surf->extents[1] )
+			continue;
+
+		if (!surf->samples)
+			return 0;
+
+		ds >>= 4;
+		dt >>= 4;
+
+		lightmap = surf->samples;
+		r = 0;
+		if (lightmap)
+		{
+
+			lightmap += dt * ((surf->extents[0]>>4)+1) + ds;
+
+			for (maps = 0 ; maps < MAXLIGHTMAPS && surf->styles[maps] != 255 ;
+					maps++)
+			{
+				scale = d_lightstylevalue[surf->styles[maps]];
+				r += *lightmap * scale;
+				lightmap += ((surf->extents[0]>>4)+1) *
+						((surf->extents[1]>>4)+1);
+			}
+			
+			r >>= 8;
+		}
+		
+		return r;
+	}
+
+// go down back side
+	return RecursiveLightPoint (node->children[!side], mid, end);
+}
+
+int R_LightPoint (vec3_t p)
+{
+	vec3_t		end;
+	int			r;
+	
+	if (!cl.worldmodel->lightdata)
+		return 255;
+	
+	end[0] = p[0];
+	end[1] = p[1];
+	end[2] = p[2] - 2048;
+	
+	r = RecursiveLightPoint (cl.worldmodel->nodes, p, end);
+	
+	if (r == -1)
+		r = 0;
+
+	if (r < r_refdef.ambientlight)
+		r = r_refdef.ambientlight;
+
+	return r;
+}
+
--- /dev/null
+++ b/QW/client/r_local.h
@@ -1,0 +1,317 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// r_local.h -- private refresh defs
+
+#ifndef GLQUAKE
+
+#include "r_shared.h"
+
+#define ALIAS_BASE_SIZE_RATIO		(1.0 / 11.0)
+					// normalizing factor so player model works out to about
+					//  1 pixel per triangle
+
+#define BMODEL_FULLY_CLIPPED	0x10 // value returned by R_BmodelCheckBBox ()
+									 //  if bbox is trivially rejected
+
+//===========================================================================
+// viewmodel lighting
+
+typedef struct {
+	int			ambientlight;
+	int			shadelight;
+	float		*plightvec;
+} alight_t;
+
+//===========================================================================
+// clipped bmodel edges
+
+typedef struct bedge_s
+{
+	mvertex_t		*v[2];
+	struct bedge_s	*pnext;
+} bedge_t;
+
+typedef struct {
+	float	fv[3];		// viewspace x, y
+} auxvert_t;
+
+//===========================================================================
+
+extern cvar_t	r_draworder;
+extern cvar_t	r_speeds;
+extern cvar_t	r_timegraph;
+extern cvar_t	r_graphheight;
+extern cvar_t	r_clearcolor;
+extern cvar_t	r_waterwarp;
+extern cvar_t	r_fullbright;
+extern cvar_t	r_drawentities;
+extern cvar_t	r_aliasstats;
+extern cvar_t	r_dspeeds;
+extern cvar_t	r_drawflat;
+extern cvar_t	r_ambient;
+extern cvar_t	r_reportsurfout;
+extern cvar_t	r_maxsurfs;
+extern cvar_t	r_numsurfs;
+extern cvar_t	r_reportedgeout;
+extern cvar_t	r_maxedges;
+extern cvar_t	r_numedges;
+
+#define XCENTERING	(1.0 / 2.0)
+#define YCENTERING	(1.0 / 2.0)
+
+#define CLIP_EPSILON		0.001
+
+#define BACKFACE_EPSILON	0.01
+
+//===========================================================================
+
+#define	DIST_NOT_SET	98765
+
+// !!! if this is changed, it must be changed in asm_draw.h too !!!
+typedef struct clipplane_s
+{
+	vec3_t		normal;
+	float		dist;
+	struct		clipplane_s	*next;
+	byte		leftedge;
+	byte		rightedge;
+	byte		reserved[2];
+} clipplane_t;
+
+extern	clipplane_t	view_clipplanes[4];
+
+//=============================================================================
+
+void R_RenderWorld (void);
+
+//=============================================================================
+
+extern	mplane_t	screenedge[4];
+
+extern	vec3_t	r_origin;
+
+extern	vec3_t	r_entorigin;
+
+extern	float	screenAspect;
+extern	float	verticalFieldOfView;
+extern	float	xOrigin, yOrigin;
+
+extern	int		r_visframecount;
+
+//=============================================================================
+
+extern int	vstartscan;
+
+
+void R_ClearPolyList (void);
+void R_DrawPolyList (void);
+
+//
+// current entity info
+//
+extern	qboolean		insubmodel;
+extern	vec3_t			r_worldmodelorg;
+
+
+void R_DrawSprite (void);
+void R_RenderFace (msurface_t *fa, int clipflags);
+void R_RenderPoly (msurface_t *fa, int clipflags);
+void R_RenderBmodelFace (bedge_t *pedges, msurface_t *psurf);
+void R_TransformPlane (mplane_t *p, float *normal, float *dist);
+void R_TransformFrustum (void);
+void R_SetSkyFrame (void);
+void R_DrawSurfaceBlock16 (void);
+void R_DrawSurfaceBlock8 (void);
+texture_t *R_TextureAnimation (texture_t *base);
+
+#if	id386
+
+void R_DrawSurfaceBlock8_mip0 (void);
+void R_DrawSurfaceBlock8_mip1 (void);
+void R_DrawSurfaceBlock8_mip2 (void);
+void R_DrawSurfaceBlock8_mip3 (void);
+
+#endif
+
+void R_GenSkyTile (void *pdest);
+void R_GenSkyTile16 (void *pdest);
+void R_Surf8Patch (void);
+void R_Surf16Patch (void);
+void R_DrawSubmodelPolygons (model_t *pmodel, int clipflags);
+void R_DrawSolidClippedSubmodelPolygons (model_t *pmodel);
+
+void R_AddPolygonEdges (emitpoint_t *pverts, int numverts, int miplevel);
+surf_t *R_GetSurf (void);
+void R_AliasDrawModel (alight_t *plighting);
+void R_BeginEdgeFrame (void);
+void R_ScanEdges (void);
+void D_DrawSurfaces (void);
+void R_InsertNewEdges (edge_t *edgestoadd, edge_t *edgelist);
+void R_StepActiveU (edge_t *pedge);
+void R_RemoveEdges (edge_t *pedge);
+
+extern void R_Surf8Start (void);
+extern void R_Surf8End (void);
+extern void R_Surf16Start (void);
+extern void R_Surf16End (void);
+extern void R_EdgeCodeStart (void);
+extern void R_EdgeCodeEnd (void);
+
+extern void R_RotateBmodel (void);
+
+extern int	c_faceclip;
+extern int	r_polycount;
+extern int	r_wholepolycount;
+
+extern	model_t		*cl_worldmodel;
+
+extern int		*pfrustum_indexes[4];
+
+// !!! if this is changed, it must be changed in asm_draw.h too !!!
+#define	NEAR_CLIP	0.01
+
+extern int			ubasestep, errorterm, erroradjustup, erroradjustdown;
+extern int			vstartscan;
+
+extern fixed16_t	sadjust, tadjust;
+extern fixed16_t	bbextents, bbextentt;
+
+#define MAXBVERTINDEXES	1000	// new clipped vertices when clipping bmodels
+								//  to the world BSP
+extern mvertex_t	*r_ptverts, *r_ptvertsmax;
+
+extern vec3_t			sbaseaxis[3], tbaseaxis[3];
+extern float			entity_rotation[3][3];
+
+extern int		reinit_surfcache;
+
+extern int		r_currentkey;
+extern int		r_currentbkey;
+
+typedef struct btofpoly_s {
+	int			clipflags;
+	msurface_t	*psurf;
+} btofpoly_t;
+
+#define MAX_BTOFPOLYS	5000	// FIXME: tune this
+
+extern int			numbtofpolys;
+extern btofpoly_t	*pbtofpolys;
+
+void	R_InitTurb (void);
+void	R_ZDrawSubmodelPolys (model_t *clmodel);
+
+//=========================================================
+// Alias models
+//=========================================================
+
+#define MAXALIASVERTS		2000	// TODO: tune this
+#define ALIAS_Z_CLIP_PLANE	5
+
+extern int				numverts;
+extern int				a_skinwidth;
+extern mtriangle_t		*ptriangles;
+extern int				numtriangles;
+extern aliashdr_t		*paliashdr;
+extern mdl_t			*pmdl;
+extern float			leftclip, topclip, rightclip, bottomclip;
+extern int				r_acliptype;
+extern finalvert_t		*pfinalverts;
+extern auxvert_t		*pauxverts;
+
+qboolean R_AliasCheckBBox (void);
+
+//=========================================================
+// turbulence stuff
+
+#define	AMP		8*0x10000
+#define	AMP2	3
+#define	SPEED	20
+
+//=========================================================
+// particle stuff
+
+void R_DrawParticles (void);
+void R_InitParticles (void);
+void R_ClearParticles (void);
+void R_ReadPointFile_f (void);
+void R_SurfacePatch (void);
+
+extern int		r_amodels_drawn;
+extern edge_t	*auxedges;
+extern int		r_numallocatededges;
+extern edge_t	*r_edges, *edge_p, *edge_max;
+
+extern	edge_t	*newedges[MAXHEIGHT];
+extern	edge_t	*removeedges[MAXHEIGHT];
+
+extern	int	screenwidth;
+
+// FIXME: make stack vars when debugging done
+extern	edge_t	edge_head;
+extern	edge_t	edge_tail;
+extern	edge_t	edge_aftertail;
+extern int		r_bmodelactive;
+extern vrect_t	*pconupdate;
+
+extern float		aliasxscale, aliasyscale, aliasxcenter, aliasycenter;
+extern float		r_aliastransition, r_resfudge;
+
+extern int		r_outofsurfaces;
+extern int		r_outofedges;
+
+extern mvertex_t	*r_pcurrentvertbase;
+extern int			r_maxvalidedgeoffset;
+
+void R_AliasClipTriangle (mtriangle_t *ptri);
+
+extern float	r_time1;
+extern float	dp_time1, dp_time2, db_time1, db_time2, rw_time1, rw_time2;
+extern float	se_time1, se_time2, de_time1, de_time2, dv_time1, dv_time2;
+extern int		r_frustum_indexes[4*6];
+extern int		r_maxsurfsseen, r_maxedgesseen, r_cnumsurfs;
+extern qboolean	r_surfsonstack;
+extern cshift_t	cshift_water;
+extern qboolean	r_dowarpold, r_viewchanged;
+
+extern mleaf_t	*r_viewleaf, *r_oldviewleaf;
+
+extern vec3_t	r_emins, r_emaxs;
+extern mnode_t	*r_pefragtopnode;
+extern int		r_clipflags;
+extern int		r_dlightframecount;
+extern qboolean	r_fov_greater_than_90;
+
+void R_StoreEfrags (efrag_t **ppefrag);
+void R_TimeRefresh_f (void);
+void R_TimeGraph (void);
+void R_PrintAliasStats (void);
+void R_PrintTimes (void);
+void R_PrintDSpeeds (void);
+void R_AnimateLight (void);
+int R_LightPoint (vec3_t p);
+void R_SetupFrame (void);
+void R_cshift_f (void);
+void R_EmitEdge (mvertex_t *pv0, mvertex_t *pv1);
+void R_ClipEdge (mvertex_t *pv0, mvertex_t *pv1, clipplane_t *clip);
+void R_SplitEntityOnNode2 (mnode_t *node);
+void R_MarkLights (dlight_t *light, int bit, mnode_t *node);
+
+#endif //GLQUAKE
\ No newline at end of file
--- /dev/null
+++ b/QW/client/r_main.c
@@ -1,0 +1,1104 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// r_main.c
+
+#include "quakedef.h"
+#include "r_local.h"
+
+//define	PASSAGES
+
+void		*colormap;
+vec3_t		viewlightvec;
+alight_t	r_viewlighting = {128, 192, viewlightvec};
+float		r_time1;
+int			r_numallocatededges;
+qboolean	r_drawpolys;
+qboolean	r_drawculledpolys;
+qboolean	r_worldpolysbacktofront;
+qboolean	r_recursiveaffinetriangles = true;
+int			r_pixbytes = 1;
+float		r_aliasuvscale = 1.0;
+int			r_outofsurfaces;
+int			r_outofedges;
+
+qboolean	r_dowarp, r_dowarpold, r_viewchanged;
+
+int			numbtofpolys;
+btofpoly_t	*pbtofpolys;
+mvertex_t	*r_pcurrentvertbase;
+
+int			c_surf;
+int			r_maxsurfsseen, r_maxedgesseen, r_cnumsurfs;
+qboolean	r_surfsonstack;
+int			r_clipflags;
+
+byte		*r_warpbuffer;
+
+byte		*r_stack_start;
+
+qboolean	r_fov_greater_than_90;
+
+entity_t	r_worldentity;
+
+//
+// view origin
+//
+vec3_t	vup, base_vup;
+vec3_t	vpn, base_vpn;
+vec3_t	vright, base_vright;
+vec3_t	r_origin;
+
+//
+// screen size info
+//
+refdef_t	r_refdef;
+float		xcenter, ycenter;
+float		xscale, yscale;
+float		xscaleinv, yscaleinv;
+float		xscaleshrink, yscaleshrink;
+float		aliasxscale, aliasyscale, aliasxcenter, aliasycenter;
+
+int		screenwidth;
+
+float	pixelAspect;
+float	screenAspect;
+float	verticalFieldOfView;
+float	xOrigin, yOrigin;
+
+mplane_t	screenedge[4];
+
+//
+// refresh flags
+//
+int		r_framecount = 1;	// so frame counts initialized to 0 don't match
+int		r_visframecount;
+int		d_spanpixcount;
+int		r_polycount;
+int		r_drawnpolycount;
+int		r_wholepolycount;
+
+int			*pfrustum_indexes[4];
+int			r_frustum_indexes[4*6];
+
+int		reinit_surfcache = 1;	// if 1, surface cache is currently empty and
+								// must be reinitialized for current cache size
+
+mleaf_t		*r_viewleaf, *r_oldviewleaf;
+
+texture_t	*r_notexture_mip;
+
+float		r_aliastransition, r_resfudge;
+
+int		d_lightstylevalue[256];	// 8.8 fraction of base light value
+
+float	dp_time1, dp_time2, db_time1, db_time2, rw_time1, rw_time2;
+float	se_time1, se_time2, de_time1, de_time2, dv_time1, dv_time2;
+
+void R_MarkLeaves (void);
+
+cvar_t	r_draworder = {"r_draworder","0"};
+cvar_t	r_speeds = {"r_speeds","0"};
+cvar_t	r_timegraph = {"r_timegraph","0"};
+cvar_t	r_netgraph = {"r_netgraph","0"};
+cvar_t	r_zgraph = {"r_zgraph","0"};
+cvar_t	r_graphheight = {"r_graphheight","15"};
+cvar_t	r_clearcolor = {"r_clearcolor","2"};
+cvar_t	r_waterwarp = {"r_waterwarp","1"};
+cvar_t	r_fullbright = {"r_fullbright","0"};
+cvar_t	r_drawentities = {"r_drawentities","1"};
+cvar_t	r_drawviewmodel = {"r_drawviewmodel","1"};
+cvar_t	r_aliasstats = {"r_polymodelstats","0"};
+cvar_t	r_dspeeds = {"r_dspeeds","0"};
+cvar_t	r_drawflat = {"r_drawflat", "0"};
+cvar_t	r_ambient = {"r_ambient", "0"};
+cvar_t	r_reportsurfout = {"r_reportsurfout", "0"};
+cvar_t	r_maxsurfs = {"r_maxsurfs", "0"};
+cvar_t	r_numsurfs = {"r_numsurfs", "0"};
+cvar_t	r_reportedgeout = {"r_reportedgeout", "0"};
+cvar_t	r_maxedges = {"r_maxedges", "0"};
+cvar_t	r_numedges = {"r_numedges", "0"};
+cvar_t	r_aliastransbase = {"r_aliastransbase", "200"};
+cvar_t	r_aliastransadj = {"r_aliastransadj", "100"};
+
+extern cvar_t	scr_fov;
+
+void CreatePassages (void);
+void SetVisibilityByPassages (void);
+
+void R_NetGraph (void);
+void R_ZGraph (void);
+
+/*
+==================
+R_InitTextures
+==================
+*/
+void	R_InitTextures (void)
+{
+	int		x,y, m;
+	byte	*dest;
+	
+// create a simple checkerboard texture for the default
+	r_notexture_mip = Hunk_AllocName (sizeof(texture_t) + 16*16+8*8+4*4+2*2, "notexture");
+	
+	r_notexture_mip->width = r_notexture_mip->height = 16;
+	r_notexture_mip->offsets[0] = sizeof(texture_t);
+	r_notexture_mip->offsets[1] = r_notexture_mip->offsets[0] + 16*16;
+	r_notexture_mip->offsets[2] = r_notexture_mip->offsets[1] + 8*8;
+	r_notexture_mip->offsets[3] = r_notexture_mip->offsets[2] + 4*4;
+	
+	for (m=0 ; m<4 ; m++)
+	{
+		dest = (byte *)r_notexture_mip + r_notexture_mip->offsets[m];
+		for (y=0 ; y< (16>>m) ; y++)
+			for (x=0 ; x< (16>>m) ; x++)
+			{
+				if (  (y< (8>>m) ) ^ (x< (8>>m) ) )
+					*dest++ = 0;
+				else
+					*dest++ = 0xff;
+			}
+	}	
+}
+
+/*
+===============
+R_Init
+===============
+*/
+void R_Init (void)
+{
+	int		dummy;
+	
+// get stack position so we can guess if we are going to overflow
+	r_stack_start = (byte *)&dummy;
+	
+	R_InitTurb ();
+	
+	Cmd_AddCommand ("timerefresh", R_TimeRefresh_f);	
+	Cmd_AddCommand ("pointfile", R_ReadPointFile_f);	
+
+	Cvar_RegisterVariable (&r_draworder);
+	Cvar_RegisterVariable (&r_speeds);
+	Cvar_RegisterVariable (&r_timegraph);
+	Cvar_RegisterVariable (&r_netgraph);
+	Cvar_RegisterVariable (&r_zgraph);
+	Cvar_RegisterVariable (&r_graphheight);
+	Cvar_RegisterVariable (&r_drawflat);
+	Cvar_RegisterVariable (&r_ambient);
+	Cvar_RegisterVariable (&r_clearcolor);
+	Cvar_RegisterVariable (&r_waterwarp);
+	Cvar_RegisterVariable (&r_fullbright);
+	Cvar_RegisterVariable (&r_drawentities);
+	Cvar_RegisterVariable (&r_drawviewmodel);
+	Cvar_RegisterVariable (&r_aliasstats);
+	Cvar_RegisterVariable (&r_dspeeds);
+	Cvar_RegisterVariable (&r_reportsurfout);
+	Cvar_RegisterVariable (&r_maxsurfs);
+	Cvar_RegisterVariable (&r_numsurfs);
+	Cvar_RegisterVariable (&r_reportedgeout);
+	Cvar_RegisterVariable (&r_maxedges);
+	Cvar_RegisterVariable (&r_numedges);
+	Cvar_RegisterVariable (&r_aliastransbase);
+	Cvar_RegisterVariable (&r_aliastransadj);
+
+	Cvar_SetValue ("r_maxedges", (float)NUMSTACKEDGES);
+	Cvar_SetValue ("r_maxsurfs", (float)NUMSTACKSURFACES);
+
+	view_clipplanes[0].leftedge = true;
+	view_clipplanes[1].rightedge = true;
+	view_clipplanes[1].leftedge = view_clipplanes[2].leftedge =
+			view_clipplanes[3].leftedge = false;
+	view_clipplanes[0].rightedge = view_clipplanes[2].rightedge =
+			view_clipplanes[3].rightedge = false;
+
+	r_refdef.xOrigin = XCENTERING;
+	r_refdef.yOrigin = YCENTERING;
+
+	R_InitParticles ();
+
+// TODO: collect 386-specific code in one place
+#if	id386
+	Sys_MakeCodeWriteable ((long)R_EdgeCodeStart,
+					     (long)R_EdgeCodeEnd - (long)R_EdgeCodeStart);
+#endif	// id386
+
+	D_Init ();
+}
+
+/*
+===============
+R_NewMap
+===============
+*/
+void R_NewMap (void)
+{
+	int		i;
+	
+	memset (&r_worldentity, 0, sizeof(r_worldentity));
+	r_worldentity.model = cl.worldmodel;
+
+// clear out efrags in case the level hasn't been reloaded
+// FIXME: is this one short?
+	for (i=0 ; i<cl.worldmodel->numleafs ; i++)
+		cl.worldmodel->leafs[i].efrags = NULL;
+		 	
+	r_viewleaf = NULL;
+	R_ClearParticles ();
+
+	r_cnumsurfs = r_maxsurfs.value;
+
+	if (r_cnumsurfs <= MINSURFACES)
+		r_cnumsurfs = MINSURFACES;
+
+	if (r_cnumsurfs > NUMSTACKSURFACES)
+	{
+		surfaces = Hunk_AllocName (r_cnumsurfs * sizeof(surf_t), "surfaces");
+		surface_p = surfaces;
+		surf_max = &surfaces[r_cnumsurfs];
+		r_surfsonstack = false;
+	// surface 0 doesn't really exist; it's just a dummy because index 0
+	// is used to indicate no edge attached to surface
+		surfaces--;
+		R_SurfacePatch ();
+	}
+	else
+	{
+		r_surfsonstack = true;
+	}
+
+	r_maxedgesseen = 0;
+	r_maxsurfsseen = 0;
+
+	r_numallocatededges = r_maxedges.value;
+
+	if (r_numallocatededges < MINEDGES)
+		r_numallocatededges = MINEDGES;
+
+	if (r_numallocatededges <= NUMSTACKEDGES)
+	{
+		auxedges = NULL;
+	}
+	else
+	{
+		auxedges = Hunk_AllocName (r_numallocatededges * sizeof(edge_t),
+								   "edges");
+	}
+
+	r_dowarpold = false;
+	r_viewchanged = false;
+}
+
+
+/*
+===============
+R_SetVrect
+===============
+*/
+void R_SetVrect (vrect_t *pvrectin, vrect_t *pvrect, int lineadj)
+{
+	int		h;
+	float	size;
+	qboolean full = false;
+
+	if (scr_viewsize.value >= 100.0) {
+		size = 100.0;
+		full = true;
+	} else
+		size = scr_viewsize.value;
+
+	if (cl.intermission)
+	{
+		full = true;
+		size = 100.0;
+		lineadj = 0;
+	}
+	size /= 100.0;
+
+	if (!cl_sbar.value && full)
+		h = pvrectin->height;
+	else
+		h = pvrectin->height - lineadj;
+
+//	h = (!cl_sbar.value && size==1.0) ? pvrectin->height : (pvrectin->height - lineadj);
+//	h = pvrectin->height - lineadj;
+	if (full)
+		pvrect->width = pvrectin->width;
+	else
+		pvrect->width = pvrectin->width * size;
+	if (pvrect->width < 96)
+	{
+		size = 96.0 / pvrectin->width;
+		pvrect->width = 96;	// min for icons
+	}
+	pvrect->width &= ~7;
+	pvrect->height = pvrectin->height * size;
+	if (cl_sbar.value || !full) {
+		if (pvrect->height > pvrectin->height - lineadj)
+			pvrect->height = pvrectin->height - lineadj;
+	} else
+		if (pvrect->height > pvrectin->height)
+			pvrect->height = pvrectin->height;
+
+	pvrect->height &= ~1;
+
+	pvrect->x = (pvrectin->width - pvrect->width)/2;
+	if (full)
+		pvrect->y = 0;
+	else
+		pvrect->y = (h - pvrect->height)/2;
+}
+
+
+/*
+===============
+R_ViewChanged
+
+Called every time the vid structure or r_refdef changes.
+Guaranteed to be called before the first refresh
+===============
+*/
+void R_ViewChanged (vrect_t *pvrect, int lineadj, float aspect)
+{
+	int		i;
+	float	res_scale;
+
+	r_viewchanged = true;
+
+	R_SetVrect (pvrect, &r_refdef.vrect, lineadj);
+
+	r_refdef.horizontalFieldOfView = 2.0 * tan (r_refdef.fov_x/360*M_PI);
+	r_refdef.fvrectx = (float)r_refdef.vrect.x;
+	r_refdef.fvrectx_adj = (float)r_refdef.vrect.x - 0.5;
+	r_refdef.vrect_x_adj_shift20 = (r_refdef.vrect.x<<20) + (1<<19) - 1;
+	r_refdef.fvrecty = (float)r_refdef.vrect.y;
+	r_refdef.fvrecty_adj = (float)r_refdef.vrect.y - 0.5;
+	r_refdef.vrectright = r_refdef.vrect.x + r_refdef.vrect.width;
+	r_refdef.vrectright_adj_shift20 = (r_refdef.vrectright<<20) + (1<<19) - 1;
+	r_refdef.fvrectright = (float)r_refdef.vrectright;
+	r_refdef.fvrectright_adj = (float)r_refdef.vrectright - 0.5;
+	r_refdef.vrectrightedge = (float)r_refdef.vrectright - 0.99;
+	r_refdef.vrectbottom = r_refdef.vrect.y + r_refdef.vrect.height;
+	r_refdef.fvrectbottom = (float)r_refdef.vrectbottom;
+	r_refdef.fvrectbottom_adj = (float)r_refdef.vrectbottom - 0.5;
+
+	r_refdef.aliasvrect.x = (int)(r_refdef.vrect.x * r_aliasuvscale);
+	r_refdef.aliasvrect.y = (int)(r_refdef.vrect.y * r_aliasuvscale);
+	r_refdef.aliasvrect.width = (int)(r_refdef.vrect.width * r_aliasuvscale);
+	r_refdef.aliasvrect.height = (int)(r_refdef.vrect.height * r_aliasuvscale);
+	r_refdef.aliasvrectright = r_refdef.aliasvrect.x +
+			r_refdef.aliasvrect.width;
+	r_refdef.aliasvrectbottom = r_refdef.aliasvrect.y +
+			r_refdef.aliasvrect.height;
+
+	pixelAspect = aspect;
+	xOrigin = r_refdef.xOrigin;
+	yOrigin = r_refdef.yOrigin;
+	
+	screenAspect = r_refdef.vrect.width*pixelAspect /
+			r_refdef.vrect.height;
+// 320*200 1.0 pixelAspect = 1.6 screenAspect
+// 320*240 1.0 pixelAspect = 1.3333 screenAspect
+// proper 320*200 pixelAspect = 0.8333333
+
+	verticalFieldOfView = r_refdef.horizontalFieldOfView / screenAspect;
+
+// values for perspective projection
+// if math were exact, the values would range from 0.5 to to range+0.5
+// hopefully they wll be in the 0.000001 to range+.999999 and truncate
+// the polygon rasterization will never render in the first row or column
+// but will definately render in the [range] row and column, so adjust the
+// buffer origin to get an exact edge to edge fill
+	xcenter = ((float)r_refdef.vrect.width * XCENTERING) +
+			r_refdef.vrect.x - 0.5;
+	aliasxcenter = xcenter * r_aliasuvscale;
+	ycenter = ((float)r_refdef.vrect.height * YCENTERING) +
+			r_refdef.vrect.y - 0.5;
+	aliasycenter = ycenter * r_aliasuvscale;
+
+	xscale = r_refdef.vrect.width / r_refdef.horizontalFieldOfView;
+	aliasxscale = xscale * r_aliasuvscale;
+	xscaleinv = 1.0 / xscale;
+	yscale = xscale * pixelAspect;
+	aliasyscale = yscale * r_aliasuvscale;
+	yscaleinv = 1.0 / yscale;
+	xscaleshrink = (r_refdef.vrect.width-6)/r_refdef.horizontalFieldOfView;
+	yscaleshrink = xscaleshrink*pixelAspect;
+
+// left side clip
+	screenedge[0].normal[0] = -1.0 / (xOrigin*r_refdef.horizontalFieldOfView);
+	screenedge[0].normal[1] = 0;
+	screenedge[0].normal[2] = 1;
+	screenedge[0].type = PLANE_ANYZ;
+	
+// right side clip
+	screenedge[1].normal[0] =
+			1.0 / ((1.0-xOrigin)*r_refdef.horizontalFieldOfView);
+	screenedge[1].normal[1] = 0;
+	screenedge[1].normal[2] = 1;
+	screenedge[1].type = PLANE_ANYZ;
+	
+// top side clip
+	screenedge[2].normal[0] = 0;
+	screenedge[2].normal[1] = -1.0 / (yOrigin*verticalFieldOfView);
+	screenedge[2].normal[2] = 1;
+	screenedge[2].type = PLANE_ANYZ;
+	
+// bottom side clip
+	screenedge[3].normal[0] = 0;
+	screenedge[3].normal[1] = 1.0 / ((1.0-yOrigin)*verticalFieldOfView);
+	screenedge[3].normal[2] = 1;	
+	screenedge[3].type = PLANE_ANYZ;
+	
+	for (i=0 ; i<4 ; i++)
+		VectorNormalize (screenedge[i].normal);
+
+	res_scale = sqrt ((double)(r_refdef.vrect.width * r_refdef.vrect.height) /
+			          (320.0 * 152.0)) *
+			(2.0 / r_refdef.horizontalFieldOfView);
+	r_aliastransition = r_aliastransbase.value * res_scale;
+	r_resfudge = r_aliastransadj.value * res_scale;
+
+	if (scr_fov.value <= 90.0)
+		r_fov_greater_than_90 = false;
+	else
+		r_fov_greater_than_90 = true;
+
+// TODO: collect 386-specific code in one place
+#if id386
+	if (r_pixbytes == 1)
+	{
+		Sys_MakeCodeWriteable ((long)R_Surf8Start,
+						     (long)R_Surf8End - (long)R_Surf8Start);
+		colormap = vid.colormap;
+		R_Surf8Patch ();
+	}
+	else
+	{
+		Sys_MakeCodeWriteable ((long)R_Surf16Start,
+						     (long)R_Surf16End - (long)R_Surf16Start);
+		colormap = vid.colormap16;
+		R_Surf16Patch ();
+	}
+#endif	// id386
+
+	D_ViewChanged ();
+}
+
+
+/*
+===============
+R_MarkLeaves
+===============
+*/
+void R_MarkLeaves (void)
+{
+	byte	*vis;
+	mnode_t	*node;
+	int		i;
+
+	if (r_oldviewleaf == r_viewleaf)
+		return;
+	
+	r_visframecount++;
+	r_oldviewleaf = r_viewleaf;
+
+	vis = Mod_LeafPVS (r_viewleaf, cl.worldmodel);
+		
+	for (i=0 ; i<cl.worldmodel->numleafs ; i++)
+	{
+		if (vis[i>>3] & (1<<(i&7)))
+		{
+			node = (mnode_t *)&cl.worldmodel->leafs[i+1];
+			do
+			{
+				if (node->visframe == r_visframecount)
+					break;
+				node->visframe = r_visframecount;
+				node = node->parent;
+			} while (node);
+		}
+	}
+}
+
+
+/*
+=============
+R_DrawEntitiesOnList
+=============
+*/
+void R_DrawEntitiesOnList (void)
+{
+	int			i, j;
+	int			lnum;
+	alight_t	lighting;
+// FIXME: remove and do real lighting
+	float		lightvec[3] = {-1, 0, 0};
+	vec3_t		dist;
+	float		add;
+
+	if (!r_drawentities.value)
+		return;
+
+	for (i=0 ; i<cl_numvisedicts ; i++)
+	{
+		currententity = &cl_visedicts[i];
+
+		switch (currententity->model->type)
+		{
+		case mod_sprite:
+			VectorCopy (currententity->origin, r_entorigin);
+			VectorSubtract (r_origin, r_entorigin, modelorg);
+			R_DrawSprite ();
+			break;
+
+		case mod_alias:
+			VectorCopy (currententity->origin, r_entorigin);
+			VectorSubtract (r_origin, r_entorigin, modelorg);
+
+		// see if the bounding box lets us trivially reject, also sets
+		// trivial accept status
+			if (R_AliasCheckBBox ())
+			{
+				j = R_LightPoint (currententity->origin);
+	
+				lighting.ambientlight = j;
+				lighting.shadelight = j;
+
+				lighting.plightvec = lightvec;
+
+				for (lnum=0 ; lnum<MAX_DLIGHTS ; lnum++)
+				{
+					if (cl_dlights[lnum].die >= cl.time)
+					{
+						VectorSubtract (currententity->origin,
+										cl_dlights[lnum].origin,
+										dist);
+						add = cl_dlights[lnum].radius - Length(dist);
+	
+						if (add > 0)
+							lighting.ambientlight += add;
+					}
+				}
+	
+			// clamp lighting so it doesn't overbright as much
+				if (lighting.ambientlight > 128)
+					lighting.ambientlight = 128;
+				if (lighting.ambientlight + lighting.shadelight > 192)
+					lighting.shadelight = 192 - lighting.ambientlight;
+
+				R_AliasDrawModel (&lighting);
+			}
+
+			break;
+
+		default:
+			break;
+		}
+	}
+}
+
+/*
+=============
+R_DrawViewModel
+=============
+*/
+void R_DrawViewModel (void)
+{
+// FIXME: remove and do real lighting
+	float		lightvec[3] = {-1, 0, 0};
+	int			j;
+	int			lnum;
+	vec3_t		dist;
+	float		add;
+	dlight_t	*dl;
+	
+	if (!r_drawviewmodel.value || r_fov_greater_than_90 || !Cam_DrawViewModel())
+		return;
+
+	if (cl.stats[STAT_ITEMS] & IT_INVISIBILITY)
+		return;
+
+	if (cl.stats[STAT_HEALTH] <= 0)
+		return;
+
+	currententity = &cl.viewent;
+	if (!currententity->model)
+		return;
+
+	VectorCopy (currententity->origin, r_entorigin);
+	VectorSubtract (r_origin, r_entorigin, modelorg);
+
+	VectorCopy (vup, viewlightvec);
+	VectorInverse (viewlightvec);
+
+	j = R_LightPoint (currententity->origin);
+
+	if (j < 24)
+		j = 24;		// allways give some light on gun
+	r_viewlighting.ambientlight = j;
+	r_viewlighting.shadelight = j;
+
+// add dynamic lights		
+	for (lnum=0 ; lnum<MAX_DLIGHTS ; lnum++)
+	{
+		dl = &cl_dlights[lnum];
+		if (!dl->radius)
+			continue;
+		if (!dl->radius)
+			continue;
+		if (dl->die < cl.time)
+			continue;
+
+		VectorSubtract (currententity->origin, dl->origin, dist);
+		add = dl->radius - Length(dist);
+		if (add > 0)
+			r_viewlighting.ambientlight += add;
+	}
+
+// clamp lighting so it doesn't overbright as much
+	if (r_viewlighting.ambientlight > 128)
+		r_viewlighting.ambientlight = 128;
+	if (r_viewlighting.ambientlight + r_viewlighting.shadelight > 192)
+		r_viewlighting.shadelight = 192 - r_viewlighting.ambientlight;
+
+	r_viewlighting.plightvec = lightvec;
+
+	R_AliasDrawModel (&r_viewlighting);
+}
+
+
+/*
+=============
+R_BmodelCheckBBox
+=============
+*/
+int R_BmodelCheckBBox (model_t *clmodel, float *minmaxs)
+{
+	int			i, *pindex, clipflags;
+	vec3_t		acceptpt, rejectpt;
+	double		d;
+
+	clipflags = 0;
+
+	if (currententity->angles[0] || currententity->angles[1]
+		|| currententity->angles[2])
+	{
+		for (i=0 ; i<4 ; i++)
+		{
+			d = DotProduct (currententity->origin, view_clipplanes[i].normal);
+			d -= view_clipplanes[i].dist;
+
+			if (d <= -clmodel->radius)
+				return BMODEL_FULLY_CLIPPED;
+
+			if (d <= clmodel->radius)
+				clipflags |= (1<<i);
+		}
+	}
+	else
+	{
+		for (i=0 ; i<4 ; i++)
+		{
+		// generate accept and reject points
+		// FIXME: do with fast look-ups or integer tests based on the sign bit
+		// of the floating point values
+
+			pindex = pfrustum_indexes[i];
+
+			rejectpt[0] = minmaxs[pindex[0]];
+			rejectpt[1] = minmaxs[pindex[1]];
+			rejectpt[2] = minmaxs[pindex[2]];
+			
+			d = DotProduct (rejectpt, view_clipplanes[i].normal);
+			d -= view_clipplanes[i].dist;
+
+			if (d <= 0)
+				return BMODEL_FULLY_CLIPPED;
+
+			acceptpt[0] = minmaxs[pindex[3+0]];
+			acceptpt[1] = minmaxs[pindex[3+1]];
+			acceptpt[2] = minmaxs[pindex[3+2]];
+
+			d = DotProduct (acceptpt, view_clipplanes[i].normal);
+			d -= view_clipplanes[i].dist;
+
+			if (d <= 0)
+				clipflags |= (1<<i);
+		}
+	}
+
+	return clipflags;
+}
+
+
+/*
+=============
+R_DrawBEntitiesOnList
+=============
+*/
+void R_DrawBEntitiesOnList (void)
+{
+	int			i, j, k, clipflags;
+	vec3_t		oldorigin;
+	model_t		*clmodel;
+	float		minmaxs[6];
+
+	if (!r_drawentities.value)
+		return;
+
+	VectorCopy (modelorg, oldorigin);
+	insubmodel = true;
+	r_dlightframecount = r_framecount;
+
+	for (i=0 ; i<cl_numvisedicts ; i++)
+	{
+		currententity = &cl_visedicts[i];
+
+		switch (currententity->model->type)
+		{
+		case mod_brush:
+
+			clmodel = currententity->model;
+
+		// see if the bounding box lets us trivially reject, also sets
+		// trivial accept status
+			for (j=0 ; j<3 ; j++)
+			{
+				minmaxs[j] = currententity->origin[j] +
+						clmodel->mins[j];
+				minmaxs[3+j] = currententity->origin[j] +
+						clmodel->maxs[j];
+			}
+
+			clipflags = R_BmodelCheckBBox (clmodel, minmaxs);
+
+			if (clipflags != BMODEL_FULLY_CLIPPED)
+			{
+				VectorCopy (currententity->origin, r_entorigin);
+				VectorSubtract (r_origin, r_entorigin, modelorg);
+			// FIXME: is this needed?
+				VectorCopy (modelorg, r_worldmodelorg);
+		
+				r_pcurrentvertbase = clmodel->vertexes;
+		
+			// FIXME: stop transforming twice
+				R_RotateBmodel ();
+
+			// calculate dynamic lighting for bmodel if it's not an
+			// instanced model
+				if (clmodel->firstmodelsurface != 0)
+				{
+					for (k=0 ; k<MAX_DLIGHTS ; k++)
+					{
+						if ((cl_dlights[k].die < cl.time) ||
+							(!cl_dlights[k].radius))
+						{
+							continue;
+						}
+
+						R_MarkLights (&cl_dlights[k], 1<<k,
+							clmodel->nodes + clmodel->hulls[0].firstclipnode);
+					}
+				}
+
+			// if the driver wants polygons, deliver those. Z-buffering is on
+			// at this point, so no clipping to the world tree is needed, just
+			// frustum clipping
+				if (r_drawpolys | r_drawculledpolys)
+				{
+					R_ZDrawSubmodelPolys (clmodel);
+				}
+				else
+				{
+					r_pefragtopnode = NULL;
+
+					for (j=0 ; j<3 ; j++)
+					{
+						r_emins[j] = minmaxs[j];
+						r_emaxs[j] = minmaxs[3+j];
+					}
+
+					R_SplitEntityOnNode2 (cl.worldmodel->nodes);
+
+					if (r_pefragtopnode)
+					{
+						currententity->topnode = r_pefragtopnode;
+	
+						if (r_pefragtopnode->contents >= 0)
+						{
+						// not a leaf; has to be clipped to the world BSP
+							r_clipflags = clipflags;
+							R_DrawSolidClippedSubmodelPolygons (clmodel);
+						}
+						else
+						{
+						// falls entirely in one leaf, so we just put all the
+						// edges in the edge list and let 1/z sorting handle
+						// drawing order
+							R_DrawSubmodelPolygons (clmodel, clipflags);
+						}
+	
+						currententity->topnode = NULL;
+					}
+				}
+
+			// put back world rotation and frustum clipping		
+			// FIXME: R_RotateBmodel should just work off base_vxx
+				VectorCopy (base_vpn, vpn);
+				VectorCopy (base_vup, vup);
+				VectorCopy (base_vright, vright);
+				VectorCopy (base_modelorg, modelorg);
+				VectorCopy (oldorigin, modelorg);
+				R_TransformFrustum ();
+			}
+
+			break;
+
+		default:
+			break;
+		}
+	}
+
+	insubmodel = false;
+}
+
+
+/*
+================
+R_EdgeDrawing
+================
+*/
+void R_EdgeDrawing (void)
+{
+	edge_t	ledges[NUMSTACKEDGES +
+				((CACHE_SIZE - 1) / sizeof(edge_t)) + 1];
+	surf_t	lsurfs[NUMSTACKSURFACES +
+				((CACHE_SIZE - 1) / sizeof(surf_t)) + 1];
+
+	if (auxedges)
+	{
+		r_edges = auxedges;
+	}
+	else
+	{
+		r_edges =  (edge_t *)
+				(((long)&ledges[0] + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1));
+	}
+
+	if (r_surfsonstack)
+	{
+		surfaces =  (surf_t *)
+				(((long)&lsurfs[0] + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1));
+		surf_max = &surfaces[r_cnumsurfs];
+	// surface 0 doesn't really exist; it's just a dummy because index 0
+	// is used to indicate no edge attached to surface
+		surfaces--;
+		R_SurfacePatch ();
+	}
+
+	R_BeginEdgeFrame ();
+
+	if (r_dspeeds.value)
+	{
+		rw_time1 = Sys_DoubleTime ();
+	}
+
+	R_RenderWorld ();
+
+	if (r_drawculledpolys)
+		R_ScanEdges ();
+
+// only the world can be drawn back to front with no z reads or compares, just
+// z writes, so have the driver turn z compares on now
+	D_TurnZOn ();
+
+	if (r_dspeeds.value)
+	{
+		rw_time2 = Sys_DoubleTime ();
+		db_time1 = rw_time2;
+	}
+
+	R_DrawBEntitiesOnList ();
+
+	if (r_dspeeds.value)
+	{
+		db_time2 = Sys_DoubleTime ();
+		se_time1 = db_time2;
+	}
+
+	if (!r_dspeeds.value)
+	{
+		VID_UnlockBuffer ();
+		S_ExtraUpdate ();	// don't let sound get messed up if going slow
+		VID_LockBuffer ();
+	}
+	
+	if (!(r_drawpolys | r_drawculledpolys))
+		R_ScanEdges ();
+}
+
+
+/*
+================
+R_RenderView
+
+r_refdef must be set before the first call
+================
+*/
+void R_RenderView_ (void)
+{
+	byte	warpbuffer[WARP_WIDTH * WARP_HEIGHT];
+
+	r_warpbuffer = warpbuffer;
+
+	if (r_timegraph.value || r_speeds.value || r_dspeeds.value)
+		r_time1 = Sys_DoubleTime ();
+
+	R_SetupFrame ();
+
+#ifdef PASSAGES
+SetVisibilityByPassages ();
+#else
+	R_MarkLeaves ();	// done here so we know if we're in water
+#endif
+
+// make FDIV fast. This reduces timing precision after we've been running for a
+// while, so we don't do it globally.  This also sets chop mode, and we do it
+// here so that setup stuff like the refresh area calculations match what's
+// done in screen.c
+	Sys_LowFPPrecision ();
+
+	if (!r_worldentity.model || !cl.worldmodel)
+		Sys_Error ("R_RenderView: NULL worldmodel");
+		
+	if (!r_dspeeds.value)
+	{
+		VID_UnlockBuffer ();
+		S_ExtraUpdate ();	// don't let sound get messed up if going slow
+		VID_LockBuffer ();
+	}
+	
+	R_EdgeDrawing ();
+
+	if (!r_dspeeds.value)
+	{
+		VID_UnlockBuffer ();
+		S_ExtraUpdate ();	// don't let sound get messed up if going slow
+		VID_LockBuffer ();
+	}
+	
+	if (r_dspeeds.value)
+	{
+		se_time2 = Sys_DoubleTime ();
+		de_time1 = se_time2;
+	}
+
+	R_DrawEntitiesOnList ();
+
+	if (r_dspeeds.value)
+	{
+		de_time2 = Sys_DoubleTime ();
+		dv_time1 = de_time2;
+	}
+
+	R_DrawViewModel ();
+
+	if (r_dspeeds.value)
+	{
+		dv_time2 = Sys_DoubleTime ();
+		dp_time1 = Sys_DoubleTime ();
+	}
+
+	R_DrawParticles ();
+
+	if (r_dspeeds.value)
+		dp_time2 = Sys_DoubleTime ();
+
+	if (r_dowarp)
+		D_WarpScreen ();
+
+	V_SetContentsColor (r_viewleaf->contents);
+
+	if (r_timegraph.value)
+		R_TimeGraph ();
+
+	if (r_netgraph.value)
+		R_NetGraph ();
+
+	if (r_zgraph.value)
+		R_ZGraph ();
+
+	if (r_aliasstats.value)
+		R_PrintAliasStats ();
+		
+	if (r_speeds.value)
+		R_PrintTimes ();
+
+	if (r_dspeeds.value)
+		R_PrintDSpeeds ();
+
+	if (r_reportsurfout.value && r_outofsurfaces)
+		Con_Printf ("Short %d surfaces\n", r_outofsurfaces);
+
+	if (r_reportedgeout.value && r_outofedges)
+		Con_Printf ("Short roughly %d edges\n", r_outofedges * 2 / 3);
+
+// back to high floating-point precision
+	Sys_HighFPPrecision ();
+}
+
+void R_RenderView (void)
+{
+	int		dummy;
+	int		delta;
+	
+	delta = (byte *)&dummy - r_stack_start;
+	if (delta < -10000 || delta > 10000)
+		Sys_Error ("R_RenderView: called without enough stack");
+
+	if ( Hunk_LowMark() & 3 )
+		Sys_Error ("Hunk is missaligned");
+
+	if ( (long)(&dummy) & 3 )
+		Sys_Error ("Stack is missaligned");
+
+	if ( (long)(&r_warpbuffer) & 3 )
+		Sys_Error ("Globals are missaligned");
+
+	R_RenderView_ ();
+}
+
+/*
+================
+R_InitTurb
+================
+*/
+void R_InitTurb (void)
+{
+	int		i;
+	
+	for (i=0 ; i<1280 ; i++)
+	{
+		sintable[i] = AMP + sin(i*3.14159*2/CYCLE)*AMP;
+		intsintable[i] = AMP2 + sin(i*3.14159*2/CYCLE)*AMP2;	// AMP2, not 20
+	}
+}
+
--- /dev/null
+++ b/QW/client/r_misc.c
@@ -1,0 +1,596 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// r_misc.c
+
+#include "quakedef.h"
+#include "r_local.h"
+
+
+/*
+===============
+R_CheckVariables
+===============
+*/
+void R_CheckVariables (void)
+{
+#if 0
+	static float	oldbright;
+
+	if (r_fullbright.value != oldbright)
+	{
+		oldbright = r_fullbright.value;
+		D_FlushCaches ();	// so all lighting changes
+	}
+#endif
+}
+
+
+/*
+============
+Show
+
+Debugging use
+============
+*/
+void Show (void)
+{
+	vrect_t	vr;
+
+	vr.x = vr.y = 0;
+	vr.width = vid.width;
+	vr.height = vid.height;
+	vr.pnext = NULL;
+	VID_Update (&vr);
+}
+
+/*
+====================
+R_TimeRefresh_f
+
+For program optimization
+====================
+*/
+void R_TimeRefresh_f (void)
+{
+	int			i;
+	float		start, stop, time;
+	int			startangle;
+	vrect_t		vr;
+
+	startangle = r_refdef.viewangles[1];
+	
+	start = Sys_DoubleTime ();
+	for (i=0 ; i<128 ; i++)
+	{
+		r_refdef.viewangles[1] = i/128.0*360.0;
+
+		VID_LockBuffer ();
+
+		R_RenderView ();
+
+		VID_UnlockBuffer ();
+
+		vr.x = r_refdef.vrect.x;
+		vr.y = r_refdef.vrect.y;
+		vr.width = r_refdef.vrect.width;
+		vr.height = r_refdef.vrect.height;
+		vr.pnext = NULL;
+		VID_Update (&vr);
+	}
+	stop = Sys_DoubleTime ();
+	time = stop-start;
+	Con_Printf ("%f seconds (%f fps)\n", time, 128/time);
+	
+	r_refdef.viewangles[1] = startangle;
+}
+
+/*
+================
+R_LineGraph
+
+Only called by R_DisplayTime
+================
+*/
+void R_LineGraph (int x, int y, int h)
+{
+	int		i;
+	byte	*dest;
+	int		s;
+	int		color;
+
+// FIXME: should be disabled on no-buffer adapters, or should be in the driver
+	
+//	x += r_refdef.vrect.x;
+//	y += r_refdef.vrect.y;
+	
+	dest = vid.buffer + vid.rowbytes*y + x;
+	
+	s = r_graphheight.value;
+
+	if (h == 10000)
+		color = 0x6f;	// yellow
+	else if (h == 9999)
+		color = 0x4f;	// red
+	else if (h == 9998)
+		color = 0xd0;	// blue
+	else
+		color = 0xff;	// pink
+
+	if (h>s)
+		h = s;
+	
+	for (i=0 ; i<h ; i++, dest -= vid.rowbytes*2)
+	{
+		dest[0] = color;
+//		*(dest-vid.rowbytes) = 0x30;
+	}
+#if 0
+	for ( ; i<s ; i++, dest -= vid.rowbytes*2)
+	{
+		dest[0] = 0x30;
+		*(dest-vid.rowbytes) = 0x30;
+	}
+#endif
+}
+
+/*
+==============
+R_TimeGraph
+
+Performance monitoring tool
+==============
+*/
+#define	MAX_TIMINGS		100
+extern float mouse_x, mouse_y;
+int		graphval;
+void R_TimeGraph (void)
+{
+	static	int		timex;
+	int		a;
+	float	r_time2;
+	static byte	r_timings[MAX_TIMINGS];
+	int		x;
+	
+	r_time2 = Sys_DoubleTime ();
+
+	a = (r_time2-r_time1)/0.01;
+//a = fabs(mouse_y * 0.05);
+//a = (int)((r_refdef.vieworg[2] + 1024)/1)%(int)r_graphheight.value;
+//a = (int)((pmove.velocity[2] + 500)/10);
+//a = fabs(velocity[0])/20;
+//a = ((int)fabs(origin[0])/8)%20;
+//a = (cl.idealpitch + 30)/5;
+//a = (int)(cl.simangles[YAW] * 64/360) & 63;
+a = graphval;
+
+	r_timings[timex] = a;
+	a = timex;
+
+	if (r_refdef.vrect.width <= MAX_TIMINGS)
+		x = r_refdef.vrect.width-1;
+	else
+		x = r_refdef.vrect.width -
+				(r_refdef.vrect.width - MAX_TIMINGS)/2;
+	do
+	{
+		R_LineGraph (x, r_refdef.vrect.height-2, r_timings[a]);
+		if (x==0)
+			break;		// screen too small to hold entire thing
+		x--;
+		a--;
+		if (a == -1)
+			a = MAX_TIMINGS-1;
+	} while (a != timex);
+
+	timex = (timex+1)%MAX_TIMINGS;
+}
+
+/*
+==============
+R_NetGraph
+==============
+*/
+void R_NetGraph (void)
+{
+	int		a, x, y, y2, w, i;
+	frame_t	*frame;
+	int lost;
+	char st[80];
+
+	if (vid.width - 16 <= NET_TIMINGS)
+		w = vid.width - 16;
+	else
+		w = NET_TIMINGS;
+
+	x =	-((vid.width - 320)>>1);
+	y = vid.height - sb_lines - 24 - (int)r_graphheight.value*2 - 2;
+
+	M_DrawTextBox (x, y, (w+7)/8, ((int)r_graphheight.value*2+7)/8 + 1);
+	y2 = y + 8;
+	y = vid.height - sb_lines - 8 - 2;
+
+	x = 8;
+	lost = CL_CalcNet();
+	for (a=NET_TIMINGS-w ; a<w ; a++)
+	{
+		i = (cls.netchan.outgoing_sequence-a) & NET_TIMINGSMASK;
+		R_LineGraph (x+w-1-a, y, packet_latency[i]);
+	}
+	sprintf(st, "%3i%% packet loss", lost);
+	Draw_String(8, y2, st);
+}
+
+/*
+==============
+R_ZGraph
+==============
+*/
+void R_ZGraph (void)
+{
+	int		a, x, w, i;
+	static	int	height[256];
+
+	if (r_refdef.vrect.width <= 256)
+		w = r_refdef.vrect.width;
+	else
+		w = 256;
+
+	height[r_framecount&255] = ((int)r_origin[2]) & 31;
+
+	x = 0;
+	for (a=0 ; a<w ; a++)
+	{
+		i = (r_framecount-a) & 255;
+		R_LineGraph (x+w-1-a, r_refdef.vrect.height-2, height[i]);
+	}
+}
+
+/*
+=============
+R_PrintTimes
+=============
+*/
+void R_PrintTimes (void)
+{
+	float	r_time2;
+	float		ms;
+
+	r_time2 = Sys_DoubleTime ();
+
+	ms = 1000* (r_time2 - r_time1);
+	
+	Con_Printf ("%5.1f ms %3i/%3i/%3i poly %3i surf\n",
+				ms, c_faceclip, r_polycount, r_drawnpolycount, c_surf);
+	c_surf = 0;
+}
+
+
+/*
+=============
+R_PrintDSpeeds
+=============
+*/
+void R_PrintDSpeeds (void)
+{
+	float	ms, dp_time, r_time2, rw_time, db_time, se_time, de_time, dv_time;
+
+	r_time2 = Sys_DoubleTime ();
+
+	dp_time = (dp_time2 - dp_time1) * 1000;
+	rw_time = (rw_time2 - rw_time1) * 1000;
+	db_time = (db_time2 - db_time1) * 1000;
+	se_time = (se_time2 - se_time1) * 1000;
+	de_time = (de_time2 - de_time1) * 1000;
+	dv_time = (dv_time2 - dv_time1) * 1000;
+	ms = (r_time2 - r_time1) * 1000;
+
+	Con_Printf ("%3i %4.1fp %3iw %4.1fb %3is %4.1fe %4.1fv\n",
+				(int)ms, dp_time, (int)rw_time, db_time, (int)se_time, de_time,
+				dv_time);
+}
+
+
+/*
+=============
+R_PrintAliasStats
+=============
+*/
+void R_PrintAliasStats (void)
+{
+	Con_Printf ("%3i polygon model drawn\n", r_amodels_drawn);
+}
+
+
+void WarpPalette (void)
+{
+	int		i,j;
+	byte	newpalette[768];
+	int		basecolor[3];
+	
+	basecolor[0] = 130;
+	basecolor[1] = 80;
+	basecolor[2] = 50;
+
+// pull the colors halfway to bright brown
+	for (i=0 ; i<256 ; i++)
+	{
+		for (j=0 ; j<3 ; j++)
+		{
+			newpalette[i*3+j] = (host_basepal[i*3+j] + basecolor[j])/2;
+		}
+	}
+	
+	VID_ShiftPalette (newpalette);
+}
+
+
+/*
+===================
+R_TransformFrustum
+===================
+*/
+void R_TransformFrustum (void)
+{
+	int		i;
+	vec3_t	v, v2;
+	
+	for (i=0 ; i<4 ; i++)
+	{
+		v[0] = screenedge[i].normal[2];
+		v[1] = -screenedge[i].normal[0];
+		v[2] = screenedge[i].normal[1];
+
+		v2[0] = v[1]*vright[0] + v[2]*vup[0] + v[0]*vpn[0];
+		v2[1] = v[1]*vright[1] + v[2]*vup[1] + v[0]*vpn[1];
+		v2[2] = v[1]*vright[2] + v[2]*vup[2] + v[0]*vpn[2];
+
+		VectorCopy (v2, view_clipplanes[i].normal);
+
+		view_clipplanes[i].dist = DotProduct (modelorg, v2);
+	}
+}
+
+
+#if !id386
+
+/*
+================
+TransformVector
+================
+*/
+void TransformVector (vec3_t in, vec3_t out)
+{
+	out[0] = DotProduct(in,vright);
+	out[1] = DotProduct(in,vup);
+	out[2] = DotProduct(in,vpn);		
+}
+
+#endif
+
+
+/*
+================
+R_TransformPlane
+================
+*/
+void R_TransformPlane (mplane_t *p, float *normal, float *dist)
+{
+	float	d;
+	
+	d = DotProduct (r_origin, p->normal);
+	*dist = p->dist - d;
+// TODO: when we have rotating entities, this will need to use the view matrix
+	TransformVector (p->normal, normal);
+}
+
+
+/*
+===============
+R_SetUpFrustumIndexes
+===============
+*/
+void R_SetUpFrustumIndexes (void)
+{
+	int		i, j, *pindex;
+
+	pindex = r_frustum_indexes;
+
+	for (i=0 ; i<4 ; i++)
+	{
+		for (j=0 ; j<3 ; j++)
+		{
+			if (view_clipplanes[i].normal[j] < 0)
+			{
+				pindex[j] = j;
+				pindex[j+3] = j+3;
+			}
+			else
+			{
+				pindex[j] = j+3;
+				pindex[j+3] = j;
+			}
+		}
+
+	// FIXME: do just once at start
+		pfrustum_indexes[i] = pindex;
+		pindex += 6;
+	}
+}
+
+
+/*
+===============
+R_SetupFrame
+===============
+*/
+void R_SetupFrame (void)
+{
+	int				edgecount;
+	vrect_t			vrect;
+	float			w, h;
+
+// don't allow cheats in multiplayer
+r_draworder.value = 0;
+r_fullbright.value = 0;
+r_ambient.value = 0;
+r_drawflat.value = 0;
+
+	if (r_numsurfs.value)
+	{
+		if ((surface_p - surfaces) > r_maxsurfsseen)
+			r_maxsurfsseen = surface_p - surfaces;
+
+		Con_Printf ("Used %d of %d surfs; %d max\n", surface_p - surfaces,
+				surf_max - surfaces, r_maxsurfsseen);
+	}
+
+	if (r_numedges.value)
+	{
+		edgecount = edge_p - r_edges;
+
+		if (edgecount > r_maxedgesseen)
+			r_maxedgesseen = edgecount;
+
+		Con_Printf ("Used %d of %d edges; %d max\n", edgecount,
+				r_numallocatededges, r_maxedgesseen);
+	}
+
+	r_refdef.ambientlight = r_ambient.value;
+
+	if (r_refdef.ambientlight < 0)
+		r_refdef.ambientlight = 0;
+
+//	if (!sv.active)
+		r_draworder.value = 0;	// don't let cheaters look behind walls
+		
+	R_CheckVariables ();
+	
+	R_AnimateLight ();
+
+	r_framecount++;
+
+	numbtofpolys = 0;
+
+// debugging
+#if 0
+r_refdef.vieworg[0]=  80;
+r_refdef.vieworg[1]=      64;
+r_refdef.vieworg[2]=      40;
+r_refdef.viewangles[0]=    0;
+r_refdef.viewangles[1]=    46.763641357;
+r_refdef.viewangles[2]=    0;
+#endif
+
+// build the transformation matrix for the given view angles
+	VectorCopy (r_refdef.vieworg, modelorg);
+	VectorCopy (r_refdef.vieworg, r_origin);
+
+	AngleVectors (r_refdef.viewangles, vpn, vright, vup);
+
+// current viewleaf
+	r_oldviewleaf = r_viewleaf;
+	r_viewleaf = Mod_PointInLeaf (r_origin, cl.worldmodel);
+
+	r_dowarpold = r_dowarp;
+	r_dowarp = r_waterwarp.value && (r_viewleaf->contents <= CONTENTS_WATER);
+
+	if ((r_dowarp != r_dowarpold) || r_viewchanged)
+	{
+		if (r_dowarp)
+		{
+			if ((vid.width <= vid.maxwarpwidth) &&
+				(vid.height <= vid.maxwarpheight))
+			{
+				vrect.x = 0;
+				vrect.y = 0;
+				vrect.width = vid.width;
+				vrect.height = vid.height;
+
+				R_ViewChanged (&vrect, sb_lines, vid.aspect);
+			}
+			else
+			{
+				w = vid.width;
+				h = vid.height;
+
+				if (w > vid.maxwarpwidth)
+				{
+					h *= (float)vid.maxwarpwidth / w;
+					w = vid.maxwarpwidth;
+				}
+
+				if (h > vid.maxwarpheight)
+				{
+					h = vid.maxwarpheight;
+					w *= (float)vid.maxwarpheight / h;
+				}
+
+				vrect.x = 0;
+				vrect.y = 0;
+				vrect.width = (int)w;
+				vrect.height = (int)h;
+
+				R_ViewChanged (&vrect,
+							   (int)((float)sb_lines * (h/(float)vid.height)),
+							   vid.aspect * (h / w) *
+								 ((float)vid.width / (float)vid.height));
+			}
+		}
+		else
+		{
+			vrect.x = 0;
+			vrect.y = 0;
+			vrect.width = vid.width;
+			vrect.height = vid.height;
+
+			R_ViewChanged (&vrect, sb_lines, vid.aspect);
+		}
+
+		r_viewchanged = false;
+	}
+
+// start off with just the four screen edge clip planes
+	R_TransformFrustum ();
+
+// save base values
+	VectorCopy (vpn, base_vpn);
+	VectorCopy (vright, base_vright);
+	VectorCopy (vup, base_vup);
+	VectorCopy (modelorg, base_modelorg);
+
+	R_SetSkyFrame ();
+
+	R_SetUpFrustumIndexes ();
+
+	r_cache_thrash = false;
+
+// clear frame counts
+	c_faceclip = 0;
+	d_spanpixcount = 0;
+	r_polycount = 0;
+	r_drawnpolycount = 0;
+	r_wholepolycount = 0;
+	r_amodels_drawn = 0;
+	r_outofsurfaces = 0;
+	r_outofedges = 0;
+
+	D_SetupFrame ();
+}
+
--- /dev/null
+++ b/QW/client/r_part.c
@@ -1,0 +1,615 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+
+#include "quakedef.h"
+#include "r_local.h"
+
+#define MAX_PARTICLES			2048	// default max # of particles at one
+										//  time
+#define ABSOLUTE_MIN_PARTICLES	512		// no fewer than this no matter what's
+										//  on the command line
+
+int		ramp1[8] = {0x6f, 0x6d, 0x6b, 0x69, 0x67, 0x65, 0x63, 0x61};
+int		ramp2[8] = {0x6f, 0x6e, 0x6d, 0x6c, 0x6b, 0x6a, 0x68, 0x66};
+int		ramp3[8] = {0x6d, 0x6b, 6, 5, 4, 3};
+
+particle_t	*active_particles, *free_particles;
+
+particle_t	*particles;
+int			r_numparticles;
+
+vec3_t			r_pright, r_pup, r_ppn;
+
+
+/*
+===============
+R_InitParticles
+===============
+*/
+void R_InitParticles (void)
+{
+	int		i;
+
+	i = COM_CheckParm ("-particles");
+
+	if (i)
+	{
+		r_numparticles = (int)(Q_atoi(com_argv[i+1]));
+		if (r_numparticles < ABSOLUTE_MIN_PARTICLES)
+			r_numparticles = ABSOLUTE_MIN_PARTICLES;
+	}
+	else
+	{
+		r_numparticles = MAX_PARTICLES;
+	}
+
+	particles = (particle_t *)
+			Hunk_AllocName (r_numparticles * sizeof(particle_t), "particles");
+}
+
+
+/*
+===============
+R_ClearParticles
+===============
+*/
+void R_ClearParticles (void)
+{
+	int		i;
+	
+	free_particles = &particles[0];
+	active_particles = NULL;
+
+	for (i=0 ;i<r_numparticles ; i++)
+		particles[i].next = &particles[i+1];
+	particles[r_numparticles-1].next = NULL;
+}
+
+
+void R_ReadPointFile_f (void)
+{
+	FILE	*f;
+	vec3_t	org;
+	int		r;
+	int		c;
+	particle_t	*p;
+	char	name[MAX_OSPATH];
+	
+// FIXME	sprintf (name,"maps/%s.pts", sv.name);
+
+	COM_FOpenFile (name, &f);
+	if (!f)
+	{
+		Con_Printf ("couldn't open %s\n", name);
+		return;
+	}
+	
+	Con_Printf ("Reading %s...\n", name);
+	c = 0;
+	for ( ;; )
+	{
+		r = fscanf (f,"%f %f %f\n", &org[0], &org[1], &org[2]);
+		if (r != 3)
+			break;
+		c++;
+		
+		if (!free_particles)
+		{
+			Con_Printf ("Not enough free particles\n");
+			break;
+		}
+		p = free_particles;
+		free_particles = p->next;
+		p->next = active_particles;
+		active_particles = p;
+		
+		p->die = 99999;
+		p->color = (-c)&15;
+		p->type = pt_static;
+		VectorCopy (vec3_origin, p->vel);
+		VectorCopy (org, p->org);
+	}
+
+	fclose (f);
+	Con_Printf ("%i points read\n", c);
+}
+	
+/*
+===============
+R_ParticleExplosion
+
+===============
+*/
+void R_ParticleExplosion (vec3_t org)
+{
+	int			i, j;
+	particle_t	*p;
+	
+	for (i=0 ; i<1024 ; i++)
+	{
+		if (!free_particles)
+			return;
+		p = free_particles;
+		free_particles = p->next;
+		p->next = active_particles;
+		active_particles = p;
+
+		p->die = cl.time + 5;
+		p->color = ramp1[0];
+		p->ramp = rand()&3;
+		if (i & 1)
+		{
+			p->type = pt_explode;
+			for (j=0 ; j<3 ; j++)
+			{
+				p->org[j] = org[j] + ((rand()%32)-16);
+				p->vel[j] = (rand()%512)-256;
+			}
+		}
+		else
+		{
+			p->type = pt_explode2;
+			for (j=0 ; j<3 ; j++)
+			{
+				p->org[j] = org[j] + ((rand()%32)-16);
+				p->vel[j] = (rand()%512)-256;
+			}
+		}
+	}
+}
+
+/*
+===============
+R_BlobExplosion
+
+===============
+*/
+void R_BlobExplosion (vec3_t org)
+{
+	int			i, j;
+	particle_t	*p;
+	
+	for (i=0 ; i<1024 ; i++)
+	{
+		if (!free_particles)
+			return;
+		p = free_particles;
+		free_particles = p->next;
+		p->next = active_particles;
+		active_particles = p;
+
+		p->die = cl.time + 1 + (rand()&8)*0.05;
+
+		if (i & 1)
+		{
+			p->type = pt_blob;
+			p->color = 66 + rand()%6;
+			for (j=0 ; j<3 ; j++)
+			{
+				p->org[j] = org[j] + ((rand()%32)-16);
+				p->vel[j] = (rand()%512)-256;
+			}
+		}
+		else
+		{
+			p->type = pt_blob2;
+			p->color = 150 + rand()%6;
+			for (j=0 ; j<3 ; j++)
+			{
+				p->org[j] = org[j] + ((rand()%32)-16);
+				p->vel[j] = (rand()%512)-256;
+			}
+		}
+	}
+}
+
+/*
+===============
+R_RunParticleEffect
+
+===============
+*/
+void R_RunParticleEffect (vec3_t org, vec3_t dir, int color, int count)
+{
+	int			i, j;
+	particle_t	*p;
+	int			scale;
+
+	if (count > 130)
+		scale = 3;
+	else if (count > 20)
+		scale = 2;
+	else
+		scale = 1;
+
+	for (i=0 ; i<count ; i++)
+	{
+		if (!free_particles)
+			return;
+		p = free_particles;
+		free_particles = p->next;
+		p->next = active_particles;
+		active_particles = p;
+
+		p->die = cl.time + 0.1*(rand()%5);
+		p->color = (color&~7) + (rand()&7);
+		p->type = pt_grav;
+		for (j=0 ; j<3 ; j++)
+		{
+			p->org[j] = org[j] + scale*((rand()&15)-8);
+			p->vel[j] = dir[j]*15;// + (rand()%300)-150;
+		}
+	}
+}
+
+
+/*
+===============
+R_LavaSplash
+
+===============
+*/
+void R_LavaSplash (vec3_t org)
+{
+	int			i, j, k;
+	particle_t	*p;
+	float		vel;
+	vec3_t		dir;
+
+	for (i=-16 ; i<16 ; i++)
+		for (j=-16 ; j<16 ; j++)
+			for (k=0 ; k<1 ; k++)
+			{
+				if (!free_particles)
+					return;
+				p = free_particles;
+				free_particles = p->next;
+				p->next = active_particles;
+				active_particles = p;
+		
+				p->die = cl.time + 2 + (rand()&31) * 0.02;
+				p->color = 224 + (rand()&7);
+				p->type = pt_grav;
+				
+				dir[0] = j*8 + (rand()&7);
+				dir[1] = i*8 + (rand()&7);
+				dir[2] = 256;
+	
+				p->org[0] = org[0] + dir[0];
+				p->org[1] = org[1] + dir[1];
+				p->org[2] = org[2] + (rand()&63);
+	
+				VectorNormalize (dir);						
+				vel = 50 + (rand()&63);
+				VectorScale (dir, vel, p->vel);
+			}
+}
+
+/*
+===============
+R_TeleportSplash
+
+===============
+*/
+void R_TeleportSplash (vec3_t org)
+{
+	int			i, j, k;
+	particle_t	*p;
+	float		vel;
+	vec3_t		dir;
+
+	for (i=-16 ; i<16 ; i+=4)
+		for (j=-16 ; j<16 ; j+=4)
+			for (k=-24 ; k<32 ; k+=4)
+			{
+				if (!free_particles)
+					return;
+				p = free_particles;
+				free_particles = p->next;
+				p->next = active_particles;
+				active_particles = p;
+		
+				p->die = cl.time + 0.2 + (rand()&7) * 0.02;
+				p->color = 7 + (rand()&7);
+				p->type = pt_grav;
+				
+				dir[0] = j*8;
+				dir[1] = i*8;
+				dir[2] = k*8;
+	
+				p->org[0] = org[0] + i + (rand()&3);
+				p->org[1] = org[1] + j + (rand()&3);
+				p->org[2] = org[2] + k + (rand()&3);
+	
+				VectorNormalize (dir);						
+				vel = 50 + (rand()&63);
+				VectorScale (dir, vel, p->vel);
+			}
+}
+
+void R_RocketTrail (vec3_t start, vec3_t end, int type)
+{
+	vec3_t	vec;
+	float	len;
+	int			j;
+	particle_t	*p;
+
+	VectorSubtract (end, start, vec);
+	len = VectorNormalize (vec);
+	while (len > 0)
+	{
+		len -= 3;
+
+		if (!free_particles)
+			return;
+		p = free_particles;
+		free_particles = p->next;
+		p->next = active_particles;
+		active_particles = p;
+		
+		VectorCopy (vec3_origin, p->vel);
+		p->die = cl.time + 2;
+
+		if (type == 4)
+		{	// slight blood
+			p->type = pt_slowgrav;
+			p->color = 67 + (rand()&3);
+			for (j=0 ; j<3 ; j++)
+				p->org[j] = start[j] + ((rand()%6)-3);
+			len -= 3;
+		}
+		else if (type == 2)
+		{	// blood
+			p->type = pt_slowgrav;
+			p->color = 67 + (rand()&3);
+			for (j=0 ; j<3 ; j++)
+				p->org[j] = start[j] + ((rand()%6)-3);
+		}
+		else if (type == 6)
+		{	// voor trail
+			p->color = 9*16 + 8 + (rand()&3);
+			p->type = pt_static;
+			p->die = cl.time + 0.3;
+			for (j=0 ; j<3 ; j++)
+				p->org[j] = start[j] + ((rand()&15)-8);
+		}
+		else if (type == 1)
+		{	// smoke smoke
+			p->ramp = (rand()&3) + 2;
+			p->color = ramp3[(int)p->ramp];
+			p->type = pt_fire;
+			for (j=0 ; j<3 ; j++)
+				p->org[j] = start[j] + ((rand()%6)-3);
+		}
+		else if (type == 0)
+		{	// rocket trail
+			p->ramp = (rand()&3);
+			p->color = ramp3[(int)p->ramp];
+			p->type = pt_fire;
+			for (j=0 ; j<3 ; j++)
+				p->org[j] = start[j] + ((rand()%6)-3);
+		}
+		else if (type == 3 || type == 5)
+		{	// tracer
+			static int tracercount;
+
+			p->die = cl.time + 0.5;
+			p->type = pt_static;
+			if (type == 3)
+				p->color = 52 + ((tracercount&4)<<1);
+			else
+				p->color = 230 + ((tracercount&4)<<1);
+			
+			tracercount++;
+
+			VectorCopy (start, p->org);
+			if (tracercount & 1)
+			{
+				p->vel[0] = 30*vec[1];
+				p->vel[1] = 30*-vec[0];
+			}
+			else
+			{
+				p->vel[0] = 30*-vec[1];
+				p->vel[1] = 30*vec[0];
+			}
+			
+		}
+		
+
+		VectorAdd (start, vec, start);
+	}
+}
+
+
+/*
+===============
+R_DrawParticles
+===============
+*/
+void R_DrawParticles (void)
+{
+	particle_t		*p, *kill;
+	float			grav;
+	int				i;
+	float			time2, time3;
+	float			time1;
+	float			dvel;
+	float			frametime;
+#ifdef GLQUAKE
+	unsigned char	*at;
+	unsigned char	theAlpha;
+	vec3_t			up, right;
+	float			scale;
+	qboolean		alphaTestEnabled;
+    
+	GL_Bind(particletexture);
+	alphaTestEnabled = glIsEnabled(GL_ALPHA_TEST);
+	
+	if (alphaTestEnabled)
+		glDisable(GL_ALPHA_TEST);
+	glEnable (GL_BLEND);
+	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+	glBegin (GL_TRIANGLES);
+
+	VectorScale (vup, 1.5, up);
+	VectorScale (vright, 1.5, right);
+#else
+	D_StartParticles ();
+
+	VectorScale (vright, xscaleshrink, r_pright);
+	VectorScale (vup, yscaleshrink, r_pup);
+	VectorCopy (vpn, r_ppn);
+#endif
+
+	frametime = host_frametime;
+	time3 = frametime * 15;
+	time2 = frametime * 10; // 15;
+	time1 = frametime * 5;
+	grav = frametime * 800 * 0.05;
+	dvel = 4*frametime;
+	
+	for ( ;; ) 
+	{
+		kill = active_particles;
+		if (kill && kill->die < cl.time)
+		{
+			active_particles = kill->next;
+			kill->next = free_particles;
+			free_particles = kill;
+			continue;
+		}
+		break;
+	}
+
+	for (p=active_particles ; p ; p=p->next)
+	{
+		for ( ;; )
+		{
+			kill = p->next;
+			if (kill && kill->die < cl.time)
+			{
+				p->next = kill->next;
+				kill->next = free_particles;
+				free_particles = kill;
+				continue;
+			}
+			break;
+		}
+
+#ifdef GLQUAKE
+		// hack a scale up to keep particles from disapearing
+		scale = (p->org[0] - r_origin[0])*vpn[0] + (p->org[1] - r_origin[1])*vpn[1]
+			+ (p->org[2] - r_origin[2])*vpn[2];
+		if (scale < 20)
+			scale = 1;
+		else
+			scale = 1 + scale * 0.004;
+		at = (byte *)&d_8to24table[(int)p->color];
+		if (p->type==pt_fire)
+			theAlpha = 255*(6-p->ramp)/6;
+//			theAlpha = 192;
+//		else if (p->type==pt_explode || p->type==pt_explode2)
+//			theAlpha = 255*(8-p->ramp)/8;
+		else
+			theAlpha = 255;
+		glColor4ub (*at, *(at+1), *(at+2), theAlpha);
+//		glColor3ubv (at);
+//		glColor3ubv ((byte *)&d_8to24table[(int)p->color]);
+		glTexCoord2f (0,0);
+		glVertex3fv (p->org);
+		glTexCoord2f (1,0);
+		glVertex3f (p->org[0] + up[0]*scale, p->org[1] + up[1]*scale, p->org[2] + up[2]*scale);
+		glTexCoord2f (0,1);
+		glVertex3f (p->org[0] + right[0]*scale, p->org[1] + right[1]*scale, p->org[2] + right[2]*scale);
+
+#else
+		D_DrawParticle (p);
+#endif
+
+		p->org[0] += p->vel[0]*frametime;
+		p->org[1] += p->vel[1]*frametime;
+		p->org[2] += p->vel[2]*frametime;
+		
+		switch (p->type)
+		{
+		case pt_static:
+			break;
+		case pt_fire:
+			p->ramp += time1;
+			if (p->ramp >= 6)
+				p->die = -1;
+			else
+				p->color = ramp3[(int)p->ramp];
+			p->vel[2] += grav;
+			break;
+
+		case pt_explode:
+			p->ramp += time2;
+			if (p->ramp >=8)
+				p->die = -1;
+			else
+				p->color = ramp1[(int)p->ramp];
+			for (i=0 ; i<3 ; i++)
+				p->vel[i] += p->vel[i]*dvel;
+			p->vel[2] -= grav;
+			break;
+
+		case pt_explode2:
+			p->ramp += time3;
+			if (p->ramp >=8)
+				p->die = -1;
+			else
+				p->color = ramp2[(int)p->ramp];
+			for (i=0 ; i<3 ; i++)
+				p->vel[i] -= p->vel[i]*frametime;
+			p->vel[2] -= grav;
+			break;
+
+		case pt_blob:
+			for (i=0 ; i<3 ; i++)
+				p->vel[i] += p->vel[i]*dvel;
+			p->vel[2] -= grav;
+			break;
+
+		case pt_blob2:
+			for (i=0 ; i<2 ; i++)
+				p->vel[i] -= p->vel[i]*dvel;
+			p->vel[2] -= grav;
+			break;
+
+		case pt_slowgrav:
+		case pt_grav:
+			p->vel[2] -= grav;
+			break;
+		}
+	}
+
+#ifdef GLQUAKE
+	glEnd ();
+	glDisable (GL_BLEND);
+	if (alphaTestEnabled)
+		glEnable(GL_ALPHA_TEST);
+	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+#else
+	D_EndParticles ();
+#endif
+}
+
--- /dev/null
+++ b/QW/client/r_shared.h
@@ -1,0 +1,154 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+#ifndef GLQUAKE
+// r_shared.h: general refresh-related stuff shared between the refresh and the
+// driver
+
+// FIXME: clean up and move into d_iface.h
+
+#ifndef _R_SHARED_H_
+#define _R_SHARED_H_
+
+#define	MAXVERTS	16					// max points in a surface polygon
+#define MAXWORKINGVERTS	(MAXVERTS+4)	// max points in an intermediate
+										//  polygon (while processing)
+// !!! if this is changed, it must be changed in d_ifacea.h too !!!
+#define	MAXHEIGHT	1024
+#define	MAXWIDTH	1280
+
+#define INFINITE_DISTANCE	0x10000		// distance that's always guaranteed to
+										//  be farther away than anything in
+										//  the scene
+
+//===================================================================
+
+extern void	R_DrawLine (polyvert_t *polyvert0, polyvert_t *polyvert1);
+
+extern int		cachewidth;
+extern pixel_t	*cacheblock;
+extern int		screenwidth;
+
+extern	float	pixelAspect;
+
+extern int		r_drawnpolycount;
+
+extern cvar_t	r_clearcolor;
+
+extern int	sintable[1280];
+extern int	intsintable[1280];
+
+extern	vec3_t	vup, base_vup;
+extern	vec3_t	vpn, base_vpn;
+extern	vec3_t	vright, base_vright;
+extern	entity_t		*currententity;
+
+#define NUMSTACKEDGES		2000
+#define	MINEDGES			NUMSTACKEDGES
+#define NUMSTACKSURFACES	1000
+#define MINSURFACES			NUMSTACKSURFACES
+#define	MAXSPANS			3000
+
+// !!! if this is changed, it must be changed in asm_draw.h too !!!
+typedef struct espan_s
+{
+	int				u, v, count;
+	struct espan_s	*pnext;
+} espan_t;
+
+// FIXME: compress, make a union if that will help
+// insubmodel is only 1, flags is fewer than 32, spanstate could be a byte
+typedef struct surf_s
+{
+	struct surf_s	*next;			// active surface stack in r_edge.c
+	struct surf_s	*prev;			// used in r_edge.c for active surf stack
+	struct espan_s	*spans;			// pointer to linked list of spans to draw
+	int			key;				// sorting key (BSP order)
+	int			last_u;				// set during tracing
+	int			spanstate;			// 0 = not in span
+									// 1 = in span
+									// -1 = in inverted span (end before
+									//  start)
+	int			flags;				// currentface flags
+	void		*data;				// associated data like msurface_t
+	entity_t	*entity;
+	float		nearzi;				// nearest 1/z on surface, for mipmapping
+	qboolean	insubmodel;
+	float		d_ziorigin, d_zistepu, d_zistepv;
+
+	int			pad[2];				// to 64 bytes
+} surf_t;
+
+extern	surf_t	*surfaces, *surface_p, *surf_max;
+
+// surfaces are generated in back to front order by the bsp, so if a surf
+// pointer is greater than another one, it should be drawn in front
+// surfaces[1] is the background, and is used as the active surface stack.
+// surfaces[0] is a dummy, because index 0 is used to indicate no surface
+//  attached to an edge_t
+
+//===================================================================
+
+extern vec3_t	sxformaxis[4];	// s axis transformed into viewspace
+extern vec3_t	txformaxis[4];	// t axis transformed into viewspac
+
+extern vec3_t	modelorg, base_modelorg;
+
+extern	float	xcenter, ycenter;
+extern	float	xscale, yscale;
+extern	float	xscaleinv, yscaleinv;
+extern	float	xscaleshrink, yscaleshrink;
+
+extern	int d_lightstylevalue[256]; // 8.8 frac of base light value
+
+extern void TransformVector (vec3_t in, vec3_t out);
+extern void SetUpForLineScan(fixed8_t startvertu, fixed8_t startvertv,
+	fixed8_t endvertu, fixed8_t endvertv);
+
+extern int	r_skymade;
+extern void R_MakeSky (void);
+
+extern int	ubasestep, errorterm, erroradjustup, erroradjustdown;
+
+// flags in finalvert_t.flags
+#define ALIAS_LEFT_CLIP				0x0001
+#define ALIAS_TOP_CLIP				0x0002
+#define ALIAS_RIGHT_CLIP			0x0004
+#define ALIAS_BOTTOM_CLIP			0x0008
+#define ALIAS_Z_CLIP				0x0010
+// !!! if this is changed, it must be changed in d_ifacea.h too !!!
+#define ALIAS_ONSEAM				0x0020	// also defined in modelgen.h;
+											//  must be kept in sync
+#define ALIAS_XY_CLIP_MASK			0x000F
+
+// !!! if this is changed, it must be changed in asm_draw.h too !!!
+typedef struct edge_s
+{
+	fixed16_t		u;
+	fixed16_t		u_step;
+	struct edge_s	*prev, *next;
+	unsigned short	surfs[2];
+	struct edge_s	*nextremove;
+	float			nearzi;
+	medge_t			*owner;
+} edge_t;
+
+#endif	// _R_SHARED_H_
+
+#endif	// GLQUAKE
--- /dev/null
+++ b/QW/client/r_sky.c
@@ -1,0 +1,280 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// r_sky.c
+
+#include "quakedef.h"
+#include "r_local.h"
+#include "d_local.h"
+
+
+int		iskyspeed = 8;
+int		iskyspeed2 = 2;
+float	skyspeed, skyspeed2;
+
+float		skytime;
+
+byte		*r_skysource;
+
+int r_skymade;
+int r_skydirect;		// not used?
+
+
+// TODO: clean up these routines
+
+byte	bottomsky[128*131];
+byte	bottommask[128*131];
+byte	newsky[128*256];	// newsky and topsky both pack in here, 128 bytes
+							//  of newsky on the left of each scan, 128 bytes
+							//  of topsky on the right, because the low-level
+							//  drawers need 256-byte scan widths
+
+
+/*
+=============
+R_InitSky
+
+A sky texture is 256*128, with the right side being a masked overlay
+==============
+*/
+void R_InitSky (texture_t *mt)
+{
+	int			i, j;
+	byte		*src;
+
+	src = (byte *)mt + mt->offsets[0];
+
+	for (i=0 ; i<128 ; i++)
+	{
+		for (j=0 ; j<128 ; j++)
+		{
+			newsky[(i*256) + j + 128] = src[i*256 + j + 128];
+		}
+	}
+
+	for (i=0 ; i<128 ; i++)
+	{
+		for (j=0 ; j<131 ; j++)
+		{
+			if (src[i*256 + (j & 0x7F)])
+			{
+				bottomsky[(i*131) + j] = src[i*256 + (j & 0x7F)];
+				bottommask[(i*131) + j] = 0;
+			}
+			else
+			{
+				bottomsky[(i*131) + j] = 0;
+				bottommask[(i*131) + j] = 0xff;
+			}
+		}
+	}
+	
+	r_skysource = newsky;
+}
+
+
+/*
+=================
+R_MakeSky
+=================
+*/
+void R_MakeSky (void)
+{
+	int			x, y;
+	int			ofs, baseofs;
+	int			xshift, yshift;
+	unsigned	*pnewsky;
+	static int	xlast = -1, ylast = -1;
+
+	xshift = skytime*skyspeed;
+	yshift = skytime*skyspeed;
+
+	if ((xshift == xlast) && (yshift == ylast))
+		return;
+
+	xlast = xshift;
+	ylast = yshift;
+	
+	pnewsky = (unsigned *)&newsky[0];
+
+	for (y=0 ; y<SKYSIZE ; y++)
+	{
+		baseofs = ((y+yshift) & SKYMASK) * 131;
+
+// FIXME: clean this up
+#if UNALIGNED_OK
+
+		for (x=0 ; x<SKYSIZE ; x += 4)
+		{
+			ofs = baseofs + ((x+xshift) & SKYMASK);
+
+		// PORT: unaligned dword access to bottommask and bottomsky
+
+			*pnewsky = (*(pnewsky + (128 / sizeof (unsigned))) &
+						*(unsigned *)&bottommask[ofs]) |
+						*(unsigned *)&bottomsky[ofs];
+			pnewsky++;
+		}
+
+#else
+
+		for (x=0 ; x<SKYSIZE ; x++)
+		{
+			ofs = baseofs + ((x+xshift) & SKYMASK);
+
+			*(byte *)pnewsky = (*((byte *)pnewsky + 128) &
+						*(byte *)&bottommask[ofs]) |
+						*(byte *)&bottomsky[ofs];
+			pnewsky = (unsigned *)((byte *)pnewsky + 1);
+		}
+
+#endif
+
+		pnewsky += 128 / sizeof (unsigned);
+	}
+
+	r_skymade = 1;
+}
+
+
+/*
+=================
+R_GenSkyTile
+=================
+*/
+void R_GenSkyTile (void *pdest)
+{
+	int			x, y;
+	int			ofs, baseofs;
+	int			xshift, yshift;
+	unsigned	*pnewsky;
+	unsigned	*pd;
+
+	xshift = skytime*skyspeed;
+	yshift = skytime*skyspeed;
+
+	pnewsky = (unsigned *)&newsky[0];
+	pd = (unsigned *)pdest;
+
+	for (y=0 ; y<SKYSIZE ; y++)
+	{
+		baseofs = ((y+yshift) & SKYMASK) * 131;
+
+// FIXME: clean this up
+#if UNALIGNED_OK
+
+		for (x=0 ; x<SKYSIZE ; x += 4)
+		{
+			ofs = baseofs + ((x+xshift) & SKYMASK);
+
+		// PORT: unaligned dword access to bottommask and bottomsky
+
+			*pd = (*(pnewsky + (128 / sizeof (unsigned))) &
+				   *(unsigned *)&bottommask[ofs]) |
+				   *(unsigned *)&bottomsky[ofs];
+			pnewsky++;
+			pd++;
+		}
+
+#else
+
+		for (x=0 ; x<SKYSIZE ; x++)
+		{
+			ofs = baseofs + ((x+xshift) & SKYMASK);
+
+			*(byte *)pd = (*((byte *)pnewsky + 128) &
+						*(byte *)&bottommask[ofs]) |
+						*(byte *)&bottomsky[ofs];
+			pnewsky = (unsigned *)((byte *)pnewsky + 1);
+			pd = (unsigned *)((byte *)pd + 1);
+		}
+
+#endif
+
+		pnewsky += 128 / sizeof (unsigned);
+	}
+}
+
+
+/*
+=================
+R_GenSkyTile16
+=================
+*/
+void R_GenSkyTile16 (void *pdest)
+{
+	int				x, y;
+	int				ofs, baseofs;
+	int				xshift, yshift;
+	byte			*pnewsky;
+	unsigned short	*pd;
+
+	xshift = skytime * skyspeed;
+	yshift = skytime * skyspeed;
+
+	pnewsky = (byte *)&newsky[0];
+	pd = (unsigned short *)pdest;
+
+	for (y=0 ; y<SKYSIZE ; y++)
+	{
+		baseofs = ((y+yshift) & SKYMASK) * 131;
+
+// FIXME: clean this up
+// FIXME: do faster unaligned version?
+		for (x=0 ; x<SKYSIZE ; x++)
+		{
+			ofs = baseofs + ((x+xshift) & SKYMASK);
+
+			*pd = d_8to16table[(*(pnewsky + 128) &
+					*(byte *)&bottommask[ofs]) |
+					*(byte *)&bottomsky[ofs]];
+			pnewsky++;
+			pd++;
+		}
+
+		pnewsky += TILE_SIZE;
+	}
+}
+
+
+/*
+=============
+R_SetSkyFrame
+==============
+*/
+void R_SetSkyFrame (void)
+{
+	int		g, s1, s2;
+	float	temp;
+
+	skyspeed = iskyspeed;
+	skyspeed2 = iskyspeed2;
+
+	g = GreatestCommonDivisor (iskyspeed, iskyspeed2);
+	s1 = iskyspeed / g;
+	s2 = iskyspeed2 / g;
+	temp = SKYSIZE * s1 * s2;
+
+	skytime = cl.time - ((int)(cl.time / temp) * temp);
+	
+
+	r_skymade = 0;
+}
+
+
--- /dev/null
+++ b/QW/client/r_sprite.c
@@ -1,0 +1,401 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// r_sprite.c
+
+#include "quakedef.h"
+#include "r_local.h"
+
+static int				clip_current;
+static vec5_t			clip_verts[2][MAXWORKINGVERTS];
+static int				sprite_width, sprite_height;
+
+spritedesc_t			r_spritedesc;
+	
+
+/*
+================
+R_RotateSprite
+================
+*/
+void R_RotateSprite (float beamlength)
+{
+	vec3_t	vec;
+	
+	if (beamlength == 0.0)
+		return;
+
+	VectorScale (r_spritedesc.vpn, -beamlength, vec);
+	VectorAdd (r_entorigin, vec, r_entorigin);
+	VectorSubtract (modelorg, vec, modelorg);
+}
+
+
+/*
+=============
+R_ClipSpriteFace
+
+Clips the winding at clip_verts[clip_current] and changes clip_current
+Throws out the back side
+==============
+*/
+int R_ClipSpriteFace (int nump, clipplane_t *pclipplane)
+{
+	int		i, outcount;
+	float	dists[MAXWORKINGVERTS+1];
+	float	frac, clipdist, *pclipnormal;
+	float	*in, *instep, *outstep, *vert2;
+
+	clipdist = pclipplane->dist;
+	pclipnormal = pclipplane->normal;
+	
+// calc dists
+	if (clip_current)
+	{
+		in = clip_verts[1][0];
+		outstep = clip_verts[0][0];
+		clip_current = 0;
+	}
+	else
+	{
+		in = clip_verts[0][0];
+		outstep = clip_verts[1][0];
+		clip_current = 1;
+	}
+	
+	instep = in;
+	for (i=0 ; i<nump ; i++, instep += sizeof (vec5_t) / sizeof (float))
+	{
+		dists[i] = DotProduct (instep, pclipnormal) - clipdist;
+	}
+	
+// handle wraparound case
+	dists[nump] = dists[0];
+	Q_memcpy (instep, in, sizeof (vec5_t));
+
+
+// clip the winding
+	instep = in;
+	outcount = 0;
+
+	for (i=0 ; i<nump ; i++, instep += sizeof (vec5_t) / sizeof (float))
+	{
+		if (dists[i] >= 0)
+		{
+			Q_memcpy (outstep, instep, sizeof (vec5_t));
+			outstep += sizeof (vec5_t) / sizeof (float);
+			outcount++;
+		}
+
+		if (dists[i] == 0 || dists[i+1] == 0)
+			continue;
+
+		if ( (dists[i] > 0) == (dists[i+1] > 0) )
+			continue;
+			
+	// split it into a new vertex
+		frac = dists[i] / (dists[i] - dists[i+1]);
+			
+		vert2 = instep + sizeof (vec5_t) / sizeof (float);
+		
+		outstep[0] = instep[0] + frac*(vert2[0] - instep[0]);
+		outstep[1] = instep[1] + frac*(vert2[1] - instep[1]);
+		outstep[2] = instep[2] + frac*(vert2[2] - instep[2]);
+		outstep[3] = instep[3] + frac*(vert2[3] - instep[3]);
+		outstep[4] = instep[4] + frac*(vert2[4] - instep[4]);
+
+		outstep += sizeof (vec5_t) / sizeof (float);
+		outcount++;
+	}	
+	
+	return outcount;
+}
+
+
+/*
+================
+R_SetupAndDrawSprite
+================
+*/
+void R_SetupAndDrawSprite ()
+{
+	int			i, nump;
+	float		dot, scale, *pv;
+	vec5_t		*pverts;
+	vec3_t		left, up, right, down, transformed, local;
+	emitpoint_t	outverts[MAXWORKINGVERTS+1], *pout;
+
+	dot = DotProduct (r_spritedesc.vpn, modelorg);
+
+// backface cull
+	if (dot >= 0)
+		return;
+
+// build the sprite poster in worldspace
+	VectorScale (r_spritedesc.vright, r_spritedesc.pspriteframe->right, right);
+	VectorScale (r_spritedesc.vup, r_spritedesc.pspriteframe->up, up);
+	VectorScale (r_spritedesc.vright, r_spritedesc.pspriteframe->left, left);
+	VectorScale (r_spritedesc.vup, r_spritedesc.pspriteframe->down, down);
+
+	pverts = clip_verts[0];
+
+	pverts[0][0] = r_entorigin[0] + up[0] + left[0];
+	pverts[0][1] = r_entorigin[1] + up[1] + left[1];
+	pverts[0][2] = r_entorigin[2] + up[2] + left[2];
+	pverts[0][3] = 0;
+	pverts[0][4] = 0;
+
+	pverts[1][0] = r_entorigin[0] + up[0] + right[0];
+	pverts[1][1] = r_entorigin[1] + up[1] + right[1];
+	pverts[1][2] = r_entorigin[2] + up[2] + right[2];
+	pverts[1][3] = sprite_width;
+	pverts[1][4] = 0;
+
+	pverts[2][0] = r_entorigin[0] + down[0] + right[0];
+	pverts[2][1] = r_entorigin[1] + down[1] + right[1];
+	pverts[2][2] = r_entorigin[2] + down[2] + right[2];
+	pverts[2][3] = sprite_width;
+	pverts[2][4] = sprite_height;
+
+	pverts[3][0] = r_entorigin[0] + down[0] + left[0];
+	pverts[3][1] = r_entorigin[1] + down[1] + left[1];
+	pverts[3][2] = r_entorigin[2] + down[2] + left[2];
+	pverts[3][3] = 0;
+	pverts[3][4] = sprite_height;
+
+// clip to the frustum in worldspace
+	nump = 4;
+	clip_current = 0;
+
+	for (i=0 ; i<4 ; i++)
+	{
+		nump = R_ClipSpriteFace (nump, &view_clipplanes[i]);
+		if (nump < 3)
+			return;
+		if (nump >= MAXWORKINGVERTS)
+			Sys_Error("R_SetupAndDrawSprite: too many points");
+	}
+
+// transform vertices into viewspace and project
+	pv = &clip_verts[clip_current][0][0];
+	r_spritedesc.nearzi = -999999;
+
+	for (i=0 ; i<nump ; i++)
+	{
+		VectorSubtract (pv, r_origin, local);
+		TransformVector (local, transformed);
+
+		if (transformed[2] < NEAR_CLIP)
+			transformed[2] = NEAR_CLIP;
+
+		pout = &outverts[i];
+		pout->zi = 1.0 / transformed[2];
+		if (pout->zi > r_spritedesc.nearzi)
+			r_spritedesc.nearzi = pout->zi;
+
+		pout->s = pv[3];
+		pout->t = pv[4];
+		
+		scale = xscale * pout->zi;
+		pout->u = (xcenter + scale * transformed[0]);
+
+		scale = yscale * pout->zi;
+		pout->v = (ycenter - scale * transformed[1]);
+
+		pv += sizeof (vec5_t) / sizeof (pv);
+	}
+
+// draw it
+	r_spritedesc.nump = nump;
+	r_spritedesc.pverts = outverts;
+	D_DrawSprite ();
+}
+
+
+/*
+================
+R_GetSpriteframe
+================
+*/
+mspriteframe_t *R_GetSpriteframe (msprite_t *psprite)
+{
+	mspritegroup_t	*pspritegroup;
+	mspriteframe_t	*pspriteframe;
+	int				i, numframes, frame;
+	float			*pintervals, fullinterval, targettime, time;
+
+	frame = currententity->frame;
+
+	if ((frame >= psprite->numframes) || (frame < 0))
+	{
+		Con_Printf ("R_DrawSprite: no such frame %d\n", frame);
+		frame = 0;
+	}
+
+	if (psprite->frames[frame].type == SPR_SINGLE)
+	{
+		pspriteframe = psprite->frames[frame].frameptr;
+	}
+	else
+	{
+		pspritegroup = (mspritegroup_t *)psprite->frames[frame].frameptr;
+		pintervals = pspritegroup->intervals;
+		numframes = pspritegroup->numframes;
+		fullinterval = pintervals[numframes-1];
+
+		time = cl.time + currententity->syncbase;
+
+	// when loading in Mod_LoadSpriteGroup, we guaranteed all interval values
+	// are positive, so we don't have to worry about division by 0
+		targettime = time - ((int)(time / fullinterval)) * fullinterval;
+
+		for (i=0 ; i<(numframes-1) ; i++)
+		{
+			if (pintervals[i] > targettime)
+				break;
+		}
+
+		pspriteframe = pspritegroup->frames[i];
+	}
+
+	return pspriteframe;
+}
+
+
+/*
+================
+R_DrawSprite
+================
+*/
+void R_DrawSprite (void)
+{
+	int				i;
+	msprite_t		*psprite;
+	vec3_t			tvec;
+	float			dot, angle, sr, cr;
+
+	psprite = currententity->model->cache.data;
+
+	r_spritedesc.pspriteframe = R_GetSpriteframe (psprite);
+
+	sprite_width = r_spritedesc.pspriteframe->width;
+	sprite_height = r_spritedesc.pspriteframe->height;
+
+// TODO: make this caller-selectable
+	if (psprite->type == SPR_FACING_UPRIGHT)
+	{
+	// generate the sprite's axes, with vup straight up in worldspace, and
+	// r_spritedesc.vright perpendicular to modelorg.
+	// This will not work if the view direction is very close to straight up or
+	// down, because the cross product will be between two nearly parallel
+	// vectors and starts to approach an undefined state, so we don't draw if
+	// the two vectors are less than 1 degree apart
+		tvec[0] = -modelorg[0];
+		tvec[1] = -modelorg[1];
+		tvec[2] = -modelorg[2];
+		VectorNormalize (tvec);
+		dot = tvec[2];	// same as DotProduct (tvec, r_spritedesc.vup) because
+						//  r_spritedesc.vup is 0, 0, 1
+		if ((dot > 0.999848) || (dot < -0.999848))	// cos(1 degree) = 0.999848
+			return;
+		r_spritedesc.vup[0] = 0;
+		r_spritedesc.vup[1] = 0;
+		r_spritedesc.vup[2] = 1;
+		r_spritedesc.vright[0] = tvec[1];
+								// CrossProduct(r_spritedesc.vup, -modelorg,
+		r_spritedesc.vright[1] = -tvec[0];
+								//              r_spritedesc.vright)
+		r_spritedesc.vright[2] = 0;
+		VectorNormalize (r_spritedesc.vright);
+		r_spritedesc.vpn[0] = -r_spritedesc.vright[1];
+		r_spritedesc.vpn[1] = r_spritedesc.vright[0];
+		r_spritedesc.vpn[2] = 0;
+					// CrossProduct (r_spritedesc.vright, r_spritedesc.vup,
+					//  r_spritedesc.vpn)
+	}
+	else if (psprite->type == SPR_VP_PARALLEL)
+	{
+	// generate the sprite's axes, completely parallel to the viewplane. There
+	// are no problem situations, because the sprite is always in the same
+	// position relative to the viewer
+		for (i=0 ; i<3 ; i++)
+		{
+			r_spritedesc.vup[i] = vup[i];
+			r_spritedesc.vright[i] = vright[i];
+			r_spritedesc.vpn[i] = vpn[i];
+		}
+	}
+	else if (psprite->type == SPR_VP_PARALLEL_UPRIGHT)
+	{
+	// generate the sprite's axes, with vup straight up in worldspace, and
+	// r_spritedesc.vright parallel to the viewplane.
+	// This will not work if the view direction is very close to straight up or
+	// down, because the cross product will be between two nearly parallel
+	// vectors and starts to approach an undefined state, so we don't draw if
+	// the two vectors are less than 1 degree apart
+		dot = vpn[2];	// same as DotProduct (vpn, r_spritedesc.vup) because
+						//  r_spritedesc.vup is 0, 0, 1
+		if ((dot > 0.999848) || (dot < -0.999848))	// cos(1 degree) = 0.999848
+			return;
+		r_spritedesc.vup[0] = 0;
+		r_spritedesc.vup[1] = 0;
+		r_spritedesc.vup[2] = 1;
+		r_spritedesc.vright[0] = vpn[1];
+										// CrossProduct (r_spritedesc.vup, vpn,
+		r_spritedesc.vright[1] = -vpn[0];	//  r_spritedesc.vright)
+		r_spritedesc.vright[2] = 0;
+		VectorNormalize (r_spritedesc.vright);
+		r_spritedesc.vpn[0] = -r_spritedesc.vright[1];
+		r_spritedesc.vpn[1] = r_spritedesc.vright[0];
+		r_spritedesc.vpn[2] = 0;
+					// CrossProduct (r_spritedesc.vright, r_spritedesc.vup,
+					//  r_spritedesc.vpn)
+	}
+	else if (psprite->type == SPR_ORIENTED)
+	{
+	// generate the sprite's axes, according to the sprite's world orientation
+		AngleVectors (currententity->angles, r_spritedesc.vpn,
+					  r_spritedesc.vright, r_spritedesc.vup);
+	}
+	else if (psprite->type == SPR_VP_PARALLEL_ORIENTED)
+	{
+	// generate the sprite's axes, parallel to the viewplane, but rotated in
+	// that plane around the center according to the sprite entity's roll
+	// angle. So vpn stays the same, but vright and vup rotate
+		angle = currententity->angles[ROLL] * (M_PI*2 / 360);
+		sr = sin(angle);
+		cr = cos(angle);
+
+		for (i=0 ; i<3 ; i++)
+		{
+			r_spritedesc.vpn[i] = vpn[i];
+			r_spritedesc.vright[i] = vright[i] * cr + vup[i] * sr;
+			r_spritedesc.vup[i] = vright[i] * -sr + vup[i] * cr;
+		}
+	}
+	else
+	{
+		Sys_Error ("R_DrawSprite: Bad sprite type %d", psprite->type);
+	}
+
+	R_RotateSprite (psprite->beamlength);
+
+	R_SetupAndDrawSprite ();
+}
+
--- /dev/null
+++ b/QW/client/r_surf.c
@@ -1,0 +1,661 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// r_surf.c: surface-related refresh code
+
+#include "quakedef.h"
+#include "r_local.h"
+
+drawsurf_t	r_drawsurf;
+
+int				lightleft, sourcesstep, blocksize, sourcetstep;
+int				lightdelta, lightdeltastep;
+int				lightright, lightleftstep, lightrightstep, blockdivshift;
+unsigned		blockdivmask;
+void			*prowdestbase;
+unsigned char	*pbasesource;
+int				surfrowbytes;	// used by ASM files
+unsigned		*r_lightptr;
+int				r_stepback;
+int				r_lightwidth;
+int				r_numhblocks, r_numvblocks;
+unsigned char	*r_source, *r_sourcemax;
+
+void R_DrawSurfaceBlock8_mip0 (void);
+void R_DrawSurfaceBlock8_mip1 (void);
+void R_DrawSurfaceBlock8_mip2 (void);
+void R_DrawSurfaceBlock8_mip3 (void);
+
+static void	(*surfmiptable[4])(void) = {
+	R_DrawSurfaceBlock8_mip0,
+	R_DrawSurfaceBlock8_mip1,
+	R_DrawSurfaceBlock8_mip2,
+	R_DrawSurfaceBlock8_mip3
+};
+
+
+
+unsigned		blocklights[18*18];
+
+/*
+===============
+R_AddDynamicLights
+===============
+*/
+void R_AddDynamicLights (void)
+{
+	msurface_t *surf;
+	int			lnum;
+	int			sd, td;
+	float		dist, rad, minlight;
+	vec3_t		impact, local;
+	int			s, t;
+	int			i;
+	int			smax, tmax;
+	mtexinfo_t	*tex;
+
+	surf = r_drawsurf.surf;
+	smax = (surf->extents[0]>>4)+1;
+	tmax = (surf->extents[1]>>4)+1;
+	tex = surf->texinfo;
+
+	for (lnum=0 ; lnum<MAX_DLIGHTS ; lnum++)
+	{
+		if ( !(surf->dlightbits & (1<<lnum) ) )
+			continue;		// not lit by this light
+
+		rad = cl_dlights[lnum].radius;
+		dist = DotProduct (cl_dlights[lnum].origin, surf->plane->normal) -
+				surf->plane->dist;
+		rad -= fabs(dist);
+		minlight = cl_dlights[lnum].minlight;
+		if (rad < minlight)
+			continue;
+		minlight = rad - minlight;
+
+		for (i=0 ; i<3 ; i++)
+		{
+			impact[i] = cl_dlights[lnum].origin[i] -
+					surf->plane->normal[i]*dist;
+		}
+
+		local[0] = DotProduct (impact, tex->vecs[0]) + tex->vecs[0][3];
+		local[1] = DotProduct (impact, tex->vecs[1]) + tex->vecs[1][3];
+
+		local[0] -= surf->texturemins[0];
+		local[1] -= surf->texturemins[1];
+		
+		for (t = 0 ; t<tmax ; t++)
+		{
+			td = local[1] - t*16;
+			if (td < 0)
+				td = -td;
+			for (s=0 ; s<smax ; s++)
+			{
+				sd = local[0] - s*16;
+				if (sd < 0)
+					sd = -sd;
+				if (sd > td)
+					dist = sd + (td>>1);
+				else
+					dist = td + (sd>>1);
+				if (dist < minlight)
+					blocklights[t*smax + s] += (rad - dist)*256;
+			}
+		}
+	}
+}
+
+/*
+===============
+R_BuildLightMap
+
+Combine and scale multiple lightmaps into the 8.8 format in blocklights
+===============
+*/
+void R_BuildLightMap (void)
+{
+	int			smax, tmax;
+	int			t;
+	int			i, size;
+	byte		*lightmap;
+	unsigned	scale;
+	int			maps;
+	msurface_t	*surf;
+
+	surf = r_drawsurf.surf;
+
+	smax = (surf->extents[0]>>4)+1;
+	tmax = (surf->extents[1]>>4)+1;
+	size = smax*tmax;
+	lightmap = surf->samples;
+
+	if (/* r_fullbright.value || */ !cl.worldmodel->lightdata)
+	{
+		for (i=0 ; i<size ; i++)
+			blocklights[i] = 0;
+		return;
+	}
+
+// clear to ambient
+	for (i=0 ; i<size ; i++)
+		blocklights[i] = r_refdef.ambientlight<<8;
+
+
+// add all the lightmaps
+	if (lightmap)
+		for (maps = 0 ; maps < MAXLIGHTMAPS && surf->styles[maps] != 255 ;
+			 maps++)
+		{
+			scale = r_drawsurf.lightadj[maps];	// 8.8 fraction		
+			for (i=0 ; i<size ; i++)
+				blocklights[i] += lightmap[i] * scale;
+			lightmap += size;	// skip to next lightmap
+		}
+
+// add all the dynamic lights
+	if (surf->dlightframe == r_framecount)
+		R_AddDynamicLights ();
+
+// bound, invert, and shift
+	for (i=0 ; i<size ; i++)
+	{
+		t = (255*256 - (int)blocklights[i]) >> (8 - VID_CBITS);
+
+		if (t < (1 << 6))
+			t = (1 << 6);
+
+		blocklights[i] = t;
+	}
+}
+
+
+/*
+===============
+R_TextureAnimation
+
+Returns the proper texture for a given time and base texture
+===============
+*/
+texture_t *R_TextureAnimation (texture_t *base)
+{
+	int		reletive;
+	int		count;
+
+	if (currententity->frame)
+	{
+		if (base->alternate_anims)
+			base = base->alternate_anims;
+	}
+	
+	if (!base->anim_total)
+		return base;
+
+	reletive = (int)(cl.time*10) % base->anim_total;
+
+	count = 0;	
+	while (base->anim_min > reletive || base->anim_max <= reletive)
+	{
+		base = base->anim_next;
+		if (!base)
+			Sys_Error ("R_TextureAnimation: broken cycle");
+		if (++count > 100)
+			Sys_Error ("R_TextureAnimation: infinite cycle");
+	}
+
+	return base;
+}
+
+
+/*
+===============
+R_DrawSurface
+===============
+*/
+void R_DrawSurface (void)
+{
+	unsigned char	*basetptr;
+	int				smax, tmax, twidth;
+	int				u;
+	int				soffset, basetoffset, texwidth;
+	int				horzblockstep;
+	unsigned char	*pcolumndest;
+	void			(*pblockdrawer)(void);
+	texture_t		*mt;
+
+// calculate the lightings
+	R_BuildLightMap ();
+	
+	surfrowbytes = r_drawsurf.rowbytes;
+
+	mt = r_drawsurf.texture;
+	
+	r_source = (byte *)mt + mt->offsets[r_drawsurf.surfmip];
+	
+// the fractional light values should range from 0 to (VID_GRADES - 1) << 16
+// from a source range of 0 - 255
+	
+	texwidth = mt->width >> r_drawsurf.surfmip;
+
+	blocksize = 16 >> r_drawsurf.surfmip;
+	blockdivshift = 4 - r_drawsurf.surfmip;
+	blockdivmask = (1 << blockdivshift) - 1;
+	
+	r_lightwidth = (r_drawsurf.surf->extents[0]>>4)+1;
+
+	r_numhblocks = r_drawsurf.surfwidth >> blockdivshift;
+	r_numvblocks = r_drawsurf.surfheight >> blockdivshift;
+
+//==============================
+
+	if (r_pixbytes == 1)
+	{
+		pblockdrawer = surfmiptable[r_drawsurf.surfmip];
+	// TODO: only needs to be set when there is a display settings change
+		horzblockstep = blocksize;
+	}
+	else
+	{
+		pblockdrawer = R_DrawSurfaceBlock16;
+	// TODO: only needs to be set when there is a display settings change
+		horzblockstep = blocksize << 1;
+	}
+
+	smax = mt->width >> r_drawsurf.surfmip;
+	twidth = texwidth;
+	tmax = mt->height >> r_drawsurf.surfmip;
+	sourcetstep = texwidth;
+	r_stepback = tmax * twidth;
+
+	r_sourcemax = r_source + (tmax * smax);
+
+	soffset = r_drawsurf.surf->texturemins[0];
+	basetoffset = r_drawsurf.surf->texturemins[1];
+
+// << 16 components are to guarantee positive values for %
+	soffset = ((soffset >> r_drawsurf.surfmip) + (smax << 16)) % smax;
+	basetptr = &r_source[((((basetoffset >> r_drawsurf.surfmip) 
+		+ (tmax << 16)) % tmax) * twidth)];
+
+	pcolumndest = r_drawsurf.surfdat;
+
+	for (u=0 ; u<r_numhblocks; u++)
+	{
+		r_lightptr = blocklights + u;
+
+		prowdestbase = pcolumndest;
+
+		pbasesource = basetptr + soffset;
+
+		(*pblockdrawer)();
+
+		soffset = soffset + blocksize;
+		if (soffset >= smax)
+			soffset = 0;
+
+		pcolumndest += horzblockstep;
+	}
+}
+
+
+//=============================================================================
+
+#if	!id386
+
+/*
+================
+R_DrawSurfaceBlock8_mip0
+================
+*/
+void R_DrawSurfaceBlock8_mip0 (void)
+{
+	int				v, i, b, lightstep, lighttemp, light;
+	unsigned char	pix, *psource, *prowdest;
+
+	psource = pbasesource;
+	prowdest = prowdestbase;
+
+	for (v=0 ; v<r_numvblocks ; v++)
+	{
+	// FIXME: make these locals?
+	// FIXME: use delta rather than both right and left, like ASM?
+		lightleft = r_lightptr[0];
+		lightright = r_lightptr[1];
+		r_lightptr += r_lightwidth;
+		lightleftstep = (r_lightptr[0] - lightleft) >> 4;
+		lightrightstep = (r_lightptr[1] - lightright) >> 4;
+
+		for (i=0 ; i<16 ; i++)
+		{
+			lighttemp = lightleft - lightright;
+			lightstep = lighttemp >> 4;
+
+			light = lightright;
+
+			for (b=15; b>=0; b--)
+			{
+				pix = psource[b];
+				prowdest[b] = ((unsigned char *)vid.colormap)
+						[(light & 0xFF00) + pix];
+				light += lightstep;
+			}
+	
+			psource += sourcetstep;
+			lightright += lightrightstep;
+			lightleft += lightleftstep;
+			prowdest += surfrowbytes;
+		}
+
+		if (psource >= r_sourcemax)
+			psource -= r_stepback;
+	}
+}
+
+
+/*
+================
+R_DrawSurfaceBlock8_mip1
+================
+*/
+void R_DrawSurfaceBlock8_mip1 (void)
+{
+	int				v, i, b, lightstep, lighttemp, light;
+	unsigned char	pix, *psource, *prowdest;
+
+	psource = pbasesource;
+	prowdest = prowdestbase;
+
+	for (v=0 ; v<r_numvblocks ; v++)
+	{
+	// FIXME: make these locals?
+	// FIXME: use delta rather than both right and left, like ASM?
+		lightleft = r_lightptr[0];
+		lightright = r_lightptr[1];
+		r_lightptr += r_lightwidth;
+		lightleftstep = (r_lightptr[0] - lightleft) >> 3;
+		lightrightstep = (r_lightptr[1] - lightright) >> 3;
+
+		for (i=0 ; i<8 ; i++)
+		{
+			lighttemp = lightleft - lightright;
+			lightstep = lighttemp >> 3;
+
+			light = lightright;
+
+			for (b=7; b>=0; b--)
+			{
+				pix = psource[b];
+				prowdest[b] = ((unsigned char *)vid.colormap)
+						[(light & 0xFF00) + pix];
+				light += lightstep;
+			}
+	
+			psource += sourcetstep;
+			lightright += lightrightstep;
+			lightleft += lightleftstep;
+			prowdest += surfrowbytes;
+		}
+
+		if (psource >= r_sourcemax)
+			psource -= r_stepback;
+	}
+}
+
+
+/*
+================
+R_DrawSurfaceBlock8_mip2
+================
+*/
+void R_DrawSurfaceBlock8_mip2 (void)
+{
+	int				v, i, b, lightstep, lighttemp, light;
+	unsigned char	pix, *psource, *prowdest;
+
+	psource = pbasesource;
+	prowdest = prowdestbase;
+
+	for (v=0 ; v<r_numvblocks ; v++)
+	{
+	// FIXME: make these locals?
+	// FIXME: use delta rather than both right and left, like ASM?
+		lightleft = r_lightptr[0];
+		lightright = r_lightptr[1];
+		r_lightptr += r_lightwidth;
+		lightleftstep = (r_lightptr[0] - lightleft) >> 2;
+		lightrightstep = (r_lightptr[1] - lightright) >> 2;
+
+		for (i=0 ; i<4 ; i++)
+		{
+			lighttemp = lightleft - lightright;
+			lightstep = lighttemp >> 2;
+
+			light = lightright;
+
+			for (b=3; b>=0; b--)
+			{
+				pix = psource[b];
+				prowdest[b] = ((unsigned char *)vid.colormap)
+						[(light & 0xFF00) + pix];
+				light += lightstep;
+			}
+	
+			psource += sourcetstep;
+			lightright += lightrightstep;
+			lightleft += lightleftstep;
+			prowdest += surfrowbytes;
+		}
+
+		if (psource >= r_sourcemax)
+			psource -= r_stepback;
+	}
+}
+
+
+/*
+================
+R_DrawSurfaceBlock8_mip3
+================
+*/
+void R_DrawSurfaceBlock8_mip3 (void)
+{
+	int				v, i, b, lightstep, lighttemp, light;
+	unsigned char	pix, *psource, *prowdest;
+
+	psource = pbasesource;
+	prowdest = prowdestbase;
+
+	for (v=0 ; v<r_numvblocks ; v++)
+	{
+	// FIXME: make these locals?
+	// FIXME: use delta rather than both right and left, like ASM?
+		lightleft = r_lightptr[0];
+		lightright = r_lightptr[1];
+		r_lightptr += r_lightwidth;
+		lightleftstep = (r_lightptr[0] - lightleft) >> 1;
+		lightrightstep = (r_lightptr[1] - lightright) >> 1;
+
+		for (i=0 ; i<2 ; i++)
+		{
+			lighttemp = lightleft - lightright;
+			lightstep = lighttemp >> 1;
+
+			light = lightright;
+
+			for (b=1; b>=0; b--)
+			{
+				pix = psource[b];
+				prowdest[b] = ((unsigned char *)vid.colormap)
+						[(light & 0xFF00) + pix];
+				light += lightstep;
+			}
+	
+			psource += sourcetstep;
+			lightright += lightrightstep;
+			lightleft += lightleftstep;
+			prowdest += surfrowbytes;
+		}
+
+		if (psource >= r_sourcemax)
+			psource -= r_stepback;
+	}
+}
+
+
+/*
+================
+R_DrawSurfaceBlock16
+
+FIXME: make this work
+================
+*/
+void R_DrawSurfaceBlock16 (void)
+{
+	int				k;
+	unsigned char	*psource;
+	int				lighttemp, lightstep, light;
+	unsigned short	*prowdest;
+
+	prowdest = (unsigned short *)prowdestbase;
+
+	for (k=0 ; k<blocksize ; k++)
+	{
+		unsigned short	*pdest;
+		unsigned char	pix;
+		int				b;
+
+		psource = pbasesource;
+		lighttemp = lightright - lightleft;
+		lightstep = lighttemp >> blockdivshift;
+
+		light = lightleft;
+		pdest = prowdest;
+
+		for (b=0; b<blocksize; b++)
+		{
+			pix = *psource;
+			*pdest = vid.colormap16[(light & 0xFF00) + pix];
+			psource += sourcesstep;
+			pdest++;
+			light += lightstep;
+		}
+
+		pbasesource += sourcetstep;
+		lightright += lightrightstep;
+		lightleft += lightleftstep;
+		prowdest = (unsigned short *)((long)prowdest + surfrowbytes);
+	}
+
+	prowdestbase = prowdest;
+}
+
+#endif
+
+
+//============================================================================
+
+/*
+================
+R_GenTurbTile
+================
+*/
+void R_GenTurbTile (pixel_t *pbasetex, void *pdest)
+{
+	int		*turb;
+	int		i, j, s, t;
+	byte	*pd;
+	
+	turb = sintable + ((int)(cl.time*SPEED)&(CYCLE-1));
+	pd = (byte *)pdest;
+
+	for (i=0 ; i<TILE_SIZE ; i++)
+	{
+		for (j=0 ; j<TILE_SIZE ; j++)
+		{	
+			s = (((j << 16) + turb[i & (CYCLE-1)]) >> 16) & 63;
+			t = (((i << 16) + turb[j & (CYCLE-1)]) >> 16) & 63;
+			*pd++ = *(pbasetex + (t<<6) + s);
+		}
+	}
+}
+
+
+/*
+================
+R_GenTurbTile16
+================
+*/
+void R_GenTurbTile16 (pixel_t *pbasetex, void *pdest)
+{
+	int				*turb;
+	int				i, j, s, t;
+	unsigned short	*pd;
+
+	turb = sintable + ((int)(cl.time*SPEED)&(CYCLE-1));
+	pd = (unsigned short *)pdest;
+
+	for (i=0 ; i<TILE_SIZE ; i++)
+	{
+		for (j=0 ; j<TILE_SIZE ; j++)
+		{	
+			s = (((j << 16) + turb[i & (CYCLE-1)]) >> 16) & 63;
+			t = (((i << 16) + turb[j & (CYCLE-1)]) >> 16) & 63;
+			*pd++ = d_8to16table[*(pbasetex + (t<<6) + s)];
+		}
+	}
+}
+
+
+/*
+================
+R_GenTile
+================
+*/
+void R_GenTile (msurface_t *psurf, void *pdest)
+{
+	if (psurf->flags & SURF_DRAWTURB)
+	{
+		if (r_pixbytes == 1)
+		{
+			R_GenTurbTile ((pixel_t *)
+				((byte *)psurf->texinfo->texture + psurf->texinfo->texture->offsets[0]), pdest);
+		}
+		else
+		{
+			R_GenTurbTile16 ((pixel_t *)
+				((byte *)psurf->texinfo->texture + psurf->texinfo->texture->offsets[0]), pdest);
+		}
+	}
+	else if (psurf->flags & SURF_DRAWSKY)
+	{
+		if (r_pixbytes == 1)
+		{
+			R_GenSkyTile (pdest);
+		}
+		else
+		{
+			R_GenSkyTile16 (pdest);
+		}
+	}
+	else
+	{
+		Sys_Error ("Unknown tile type");
+	}
+}
+
--- /dev/null
+++ b/QW/client/r_vars.c
@@ -1,0 +1,39 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// r_vars.c: global refresh variables
+
+#include	"quakedef.h"
+
+#if	!id386
+
+// all global and static refresh variables are collected in a contiguous block
+// to avoid cache conflicts.
+
+//-------------------------------------------------------
+// global refresh variables
+//-------------------------------------------------------
+
+// FIXME: make into one big structure, like cl or sv
+// FIXME: do separately for refresh engine and driver
+
+int	r_bmodelactive;
+
+#endif	// !id386
+
--- /dev/null
+++ b/QW/client/r_varsa.asm
@@ -1,0 +1,258 @@
+ .386P
+ .model FLAT
+ externdef _d_zistepu:dword
+ externdef _d_pzbuffer:dword
+ externdef _d_zistepv:dword
+ externdef _d_zrowbytes:dword
+ externdef _d_ziorigin:dword
+ externdef _r_turb_s:dword
+ externdef _r_turb_t:dword
+ externdef _r_turb_pdest:dword
+ externdef _r_turb_spancount:dword
+ externdef _r_turb_turb:dword
+ externdef _r_turb_pbase:dword
+ externdef _r_turb_sstep:dword
+ externdef _r_turb_tstep:dword
+ externdef _r_bmodelactive:dword
+ externdef _d_sdivzstepu:dword
+ externdef _d_tdivzstepu:dword
+ externdef _d_sdivzstepv:dword
+ externdef _d_tdivzstepv:dword
+ externdef _d_sdivzorigin:dword
+ externdef _d_tdivzorigin:dword
+ externdef _sadjust:dword
+ externdef _tadjust:dword
+ externdef _bbextents:dword
+ externdef _bbextentt:dword
+ externdef _cacheblock:dword
+ externdef _d_viewbuffer:dword
+ externdef _cachewidth:dword
+ externdef _d_pzbuffer:dword
+ externdef _d_zrowbytes:dword
+ externdef _d_zwidth:dword
+ externdef _d_scantable:dword
+ externdef _r_lightptr:dword
+ externdef _r_numvblocks:dword
+ externdef _prowdestbase:dword
+ externdef _pbasesource:dword
+ externdef _r_lightwidth:dword
+ externdef _lightright:dword
+ externdef _lightrightstep:dword
+ externdef _lightdeltastep:dword
+ externdef _lightdelta:dword
+ externdef _lightright:dword
+ externdef _lightdelta:dword
+ externdef _sourcetstep:dword
+ externdef _surfrowbytes:dword
+ externdef _lightrightstep:dword
+ externdef _lightdeltastep:dword
+ externdef _r_sourcemax:dword
+ externdef _r_stepback:dword
+ externdef _colormap:dword
+ externdef _blocksize:dword
+ externdef _sourcesstep:dword
+ externdef _lightleft:dword
+ externdef _blockdivshift:dword
+ externdef _blockdivmask:dword
+ externdef _lightleftstep:dword
+ externdef _r_origin:dword
+ externdef _r_ppn:dword
+ externdef _r_pup:dword
+ externdef _r_pright:dword
+ externdef _ycenter:dword
+ externdef _xcenter:dword
+ externdef _d_vrectbottom_particle:dword
+ externdef _d_vrectright_particle:dword
+ externdef _d_vrecty:dword
+ externdef _d_vrectx:dword
+ externdef _d_pix_shift:dword
+ externdef _d_pix_min:dword
+ externdef _d_pix_max:dword
+ externdef _d_y_aspect_shift:dword
+ externdef _screenwidth:dword
+ externdef _vright:dword
+ externdef _vup:dword
+ externdef _vpn:dword
+ externdef _BOPS_Error:dword
+ externdef _snd_scaletable:dword
+ externdef _paintbuffer:dword
+ externdef _snd_linear_count:dword
+ externdef _snd_p:dword
+ externdef _snd_vol:dword
+ externdef _snd_out:dword
+ externdef _r_leftclipped:dword
+ externdef _r_leftenter:dword
+ externdef _r_rightclipped:dword
+ externdef _r_rightenter:dword
+ externdef _modelorg:dword
+ externdef _xscale:dword
+ externdef _r_refdef:dword
+ externdef _yscale:dword
+ externdef _r_leftexit:dword
+ externdef _r_rightexit:dword
+ externdef _r_lastvertvalid:dword
+ externdef _cacheoffset:dword
+ externdef _newedges:dword
+ externdef _removeedges:dword
+ externdef _r_pedge:dword
+ externdef _r_framecount:dword
+ externdef _r_u1:dword
+ externdef _r_emitted:dword
+ externdef _edge_p:dword
+ externdef _surface_p:dword
+ externdef _surfaces:dword
+ externdef _r_lzi1:dword
+ externdef _r_v1:dword
+ externdef _r_ceilv1:dword
+ externdef _r_nearzi:dword
+ externdef _r_nearzionly:dword
+ externdef _edge_aftertail:dword
+ externdef _edge_tail:dword
+ externdef _current_iv:dword
+ externdef _edge_head_u_shift20:dword
+ externdef _span_p:dword
+ externdef _edge_head:dword
+ externdef _fv:dword
+ externdef _edge_tail_u_shift20:dword
+ externdef _r_apverts:dword
+ externdef _r_anumverts:dword
+ externdef _aliastransform:dword
+ externdef _r_avertexnormals:dword
+ externdef _r_plightvec:dword
+ externdef _r_ambientlight:dword
+ externdef _r_shadelight:dword
+ externdef _aliasxcenter:dword
+ externdef _aliasycenter:dword
+ externdef _a_sstepxfrac:dword
+ externdef _r_affinetridesc:dword
+ externdef _acolormap:dword
+ externdef _d_pcolormap:dword
+ externdef _r_affinetridesc:dword
+ externdef _d_sfrac:dword
+ externdef _d_ptex:dword
+ externdef _d_pedgespanpackage:dword
+ externdef _d_tfrac:dword
+ externdef _d_light:dword
+ externdef _d_zi:dword
+ externdef _d_pdest:dword
+ externdef _d_pz:dword
+ externdef _d_aspancount:dword
+ externdef _erroradjustup:dword
+ externdef _errorterm:dword
+ externdef _d_xdenom:dword
+ externdef _r_p0:dword
+ externdef _r_p1:dword
+ externdef _r_p2:dword
+ externdef _a_tstepxfrac:dword
+ externdef _r_sstepx:dword
+ externdef _r_tstepx:dword
+ externdef _a_ststepxwhole:dword
+ externdef _zspantable:dword
+ externdef _skintable:dword
+ externdef _r_zistepx:dword
+ externdef _erroradjustdown:dword
+ externdef _d_countextrastep:dword
+ externdef _ubasestep:dword
+ externdef _a_ststepxwhole:dword
+ externdef _a_tstepxfrac:dword
+ externdef _r_lstepx:dword
+ externdef _a_spans:dword
+ externdef _erroradjustdown:dword
+ externdef _d_pdestextrastep:dword
+ externdef _d_pzextrastep:dword
+ externdef _d_sfracextrastep:dword
+ externdef _d_ptexextrastep:dword
+ externdef _d_countextrastep:dword
+ externdef _d_tfracextrastep:dword
+ externdef _d_lightextrastep:dword
+ externdef _d_ziextrastep:dword
+ externdef _d_pdestbasestep:dword
+ externdef _d_pzbasestep:dword
+ externdef _d_sfracbasestep:dword
+ externdef _d_ptexbasestep:dword
+ externdef _ubasestep:dword
+ externdef _d_tfracbasestep:dword
+ externdef _d_lightbasestep:dword
+ externdef _d_zibasestep:dword
+ externdef _zspantable:dword
+ externdef _r_lstepy:dword
+ externdef _r_sstepy:dword
+ externdef _r_tstepy:dword
+ externdef _r_zistepy:dword
+ externdef _D_PolysetSetEdgeTable:dword
+ externdef _D_RasterizeAliasPolySmooth:dword
+ externdef float_point5:dword
+ externdef Float2ToThe31nd:dword
+ externdef izistep:dword
+ externdef izi:dword
+ externdef FloatMinus2ToThe31nd:dword
+ externdef float_1:dword
+ externdef float_particle_z_clip:dword
+ externdef float_minus_1:dword
+ externdef float_0:dword
+ externdef fp_16:dword
+ externdef fp_64k:dword
+ externdef fp_1m:dword
+ externdef fp_1m_minus_1:dword
+ externdef fp_8:dword
+ externdef entryvec_table:dword
+ externdef advancetable:dword
+ externdef sstep:dword
+ externdef tstep:dword
+ externdef pspantemp:dword
+ externdef counttemp:dword
+ externdef jumptemp:dword
+ externdef reciprocal_table:dword
+ externdef DP_Count:dword
+ externdef DP_u:dword
+ externdef DP_v:dword
+ externdef DP_32768:dword
+ externdef DP_Color:dword
+ externdef DP_Pix:dword
+ externdef DP_EntryTable:dword
+ externdef pbase:dword
+ externdef s:dword
+ externdef t:dword
+ externdef sfracf:dword
+ externdef tfracf:dword
+ externdef snext:dword
+ externdef tnext:dword
+ externdef spancountminus1:dword
+ externdef zi16stepu:dword
+ externdef sdivz16stepu:dword
+ externdef tdivz16stepu:dword
+ externdef zi8stepu:dword
+ externdef sdivz8stepu:dword
+ externdef tdivz8stepu:dword
+ externdef reciprocal_table_16:dword
+ externdef entryvec_table_16:dword
+ externdef ceil_cw:dword
+ externdef single_cw:dword
+ externdef fp_64kx64k:dword
+ externdef pz:dword
+ externdef spr8entryvec_table:dword
+_DATA SEGMENT
+ public float_1, float_particle_z_clip, float_point5
+ public float_minus_1, float_0
+float_0 dd 0.0
+float_1 dd 1.0
+float_minus_1 dd -1.0
+float_particle_z_clip dd 8.0
+float_point5 dd 0.5
+ public fp_16, fp_64k, fp_1m, fp_64kx64k
+ public fp_1m_minus_1
+ public fp_8
+fp_1m dd 1048576.0
+fp_1m_minus_1 dd 1048575.0
+fp_64k dd 65536.0
+fp_8 dd 8.0
+fp_16 dd 16.0
+fp_64kx64k dd 04f000000h
+ public FloatZero, Float2ToThe31nd, FloatMinus2ToThe31nd
+FloatZero dd 0
+Float2ToThe31nd dd 04f000000h
+FloatMinus2ToThe31nd dd 0cf000000h
+ public _r_bmodelactive
+_r_bmodelactive dd 0
+_DATA ENDS
+ END
--- /dev/null
+++ b/QW/client/r_varsa.s
@@ -1,0 +1,64 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+//
+// r_varsa.s
+//
+
+#include "asm_i386.h"
+#include "quakeasm.h"
+#include "asm_draw.h"
+#include "d_ifacea.h"
+
+#if id386
+
+	.data
+
+//-------------------------------------------------------
+// ASM-only variables
+//-------------------------------------------------------
+.globl	float_1, float_particle_z_clip, float_point5
+.globl	float_minus_1, float_0
+float_0:		.single	0.0
+float_1:		.single	1.0
+float_minus_1:	.single	-1.0
+float_particle_z_clip:	.single	PARTICLE_Z_CLIP
+float_point5:	.single	0.5
+
+.globl	fp_16, fp_64k, fp_1m, fp_64kx64k
+.globl	fp_1m_minus_1
+.globl	fp_8 
+fp_1m:			.single	1048576.0
+fp_1m_minus_1:	.single	1048575.0
+fp_64k:			.single	65536.0
+fp_8:			.single	8.0
+fp_16:			.single	16.0
+fp_64kx64k:		.long	0x4f000000	// (float)0x8000*0x10000
+
+
+.globl	FloatZero, Float2ToThe31nd, FloatMinus2ToThe31nd
+FloatZero:				.long	0
+Float2ToThe31nd:		.long	0x4f000000
+FloatMinus2ToThe31nd:	.long	0xcf000000
+
+.globl	C(r_bmodelactive)
+C(r_bmodelactive):	.long	0
+
+#endif	// id386
+
--- /dev/null
+++ b/QW/client/render.h
@@ -1,0 +1,153 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+
+// refresh.h -- public interface to refresh functions
+
+#define	TOP_RANGE		16			// soldier uniform colors
+#define	BOTTOM_RANGE	96
+
+//=============================================================================
+
+typedef struct efrag_s
+{
+	struct mleaf_s		*leaf;
+	struct efrag_s		*leafnext;
+	struct entity_s		*entity;
+	struct efrag_s		*entnext;
+} efrag_t;
+
+
+typedef struct entity_s
+{
+	int						keynum;			// for matching entities in different frames
+	vec3_t					origin;
+	vec3_t					angles;	
+	struct model_s			*model;			// NULL = no model
+	int						frame;
+	byte					*colormap;
+	int						skinnum;		// for Alias models
+
+	struct player_info_s	*scoreboard;	// identify player
+
+	float					syncbase;
+
+	struct efrag_s			*efrag;			// linked list of efrags (FIXME)
+	int						visframe;		// last frame this entity was
+											// found in an active leaf
+											// only used for static objects
+											
+	int						dlightframe;	// dynamic lighting
+	int						dlightbits;
+	
+// FIXME: could turn these into a union
+	int						trivial_accept;
+	struct mnode_s			*topnode;		// for bmodels, first world node
+											//  that splits bmodel, or NULL if
+											//  not split
+} entity_t;
+
+// !!! if this is changed, it must be changed in asm_draw.h too !!!
+typedef struct
+{
+	vrect_t		vrect;				// subwindow in video for refresh
+									// FIXME: not need vrect next field here?
+	vrect_t		aliasvrect;			// scaled Alias version
+	int			vrectright, vrectbottom;	// right & bottom screen coords
+	int			aliasvrectright, aliasvrectbottom;	// scaled Alias versions
+	float		vrectrightedge;			// rightmost right edge we care about,
+										//  for use in edge list
+	float		fvrectx, fvrecty;		// for floating-point compares
+	float		fvrectx_adj, fvrecty_adj; // left and top edges, for clamping
+	int			vrect_x_adj_shift20;	// (vrect.x + 0.5 - epsilon) << 20
+	int			vrectright_adj_shift20;	// (vrectright + 0.5 - epsilon) << 20
+	float		fvrectright_adj, fvrectbottom_adj;
+										// right and bottom edges, for clamping
+	float		fvrectright;			// rightmost edge, for Alias clamping
+	float		fvrectbottom;			// bottommost edge, for Alias clamping
+	float		horizontalFieldOfView;	// at Z = 1.0, this many X is visible 
+										// 2.0 = 90 degrees
+	float		xOrigin;			// should probably allways be 0.5
+	float		yOrigin;			// between be around 0.3 to 0.5
+
+	vec3_t		vieworg;
+	vec3_t		viewangles;
+
+	float		fov_x, fov_y;
+	
+	int			ambientlight;
+} refdef_t;
+
+
+//
+// refresh
+//
+extern	int		reinit_surfcache;
+
+
+extern	refdef_t	r_refdef;
+extern vec3_t	r_origin, vpn, vright, vup;
+
+extern	struct texture_s	*r_notexture_mip;
+
+extern	entity_t	r_worldentity;
+
+void R_Init (void);
+void R_InitTextures (void);
+void R_InitEfrags (void);
+void R_RenderView (void);		// must set r_refdef first
+void R_ViewChanged (vrect_t *pvrect, int lineadj, float aspect);
+								// called whenever r_refdef or vid change
+void R_InitSky (struct texture_s *mt);	// called at level load
+
+void R_AddEfrags (entity_t *ent);
+void R_RemoveEfrags (entity_t *ent);
+
+void R_NewMap (void);
+
+
+void R_ParseParticleEffect (void);
+void R_RunParticleEffect (vec3_t org, vec3_t dir, int color, int count);
+void R_RocketTrail (vec3_t start, vec3_t end, int type);
+
+void R_EntityParticles (entity_t *ent);
+void R_BlobExplosion (vec3_t org);
+void R_ParticleExplosion (vec3_t org);
+void R_LavaSplash (vec3_t org);
+void R_TeleportSplash (vec3_t org);
+
+void R_PushDlights (void);
+void R_InitParticles (void);
+void R_ClearParticles (void);
+void R_DrawParticles (void);
+void R_DrawWaterSurfaces (void);
+
+
+//
+// surface cache related
+//
+extern	int		reinit_surfcache;	// if 1, surface cache is currently empty and
+extern qboolean	r_cache_thrash;	// set if thrashing the surface cache
+
+int	D_SurfaceCacheForRes (int width, int height);
+void D_FlushCaches (void);
+void D_DeleteSurfaceCache (void);
+void D_InitCaches (void *buffer, int size);
+void R_SetVrect (vrect_t *pvrect, vrect_t *pvrectin, int lineadj);
+
--- /dev/null
+++ b/QW/client/resource.h
@@ -1,0 +1,21 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by winquake.rc
+//
+#define IDS_STRING1                     1
+#define IDI_ICON2                       1
+#define IDD_DIALOG1                     108
+#define IDD_PROGRESS                    109
+#define IDB_QWBITMAP                    112
+#define IDC_PROGRESS                    1000
+
+// Next default values for new objects
+// 
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE        115
+#define _APS_NEXT_COMMAND_VALUE         40001
+#define _APS_NEXT_CONTROL_VALUE         1001
+#define _APS_NEXT_SYMED_VALUE           101
+#endif
+#endif
--- /dev/null
+++ b/QW/client/sbar.c
@@ -1,0 +1,1330 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// sbar.c -- status bar code
+
+#include "quakedef.h"
+
+
+int			sb_updates;		// if >= vid.numpages, no update needed
+
+#define STAT_MINUS		10	// num frame for '-' stats digit
+qpic_t		*sb_nums[2][11];
+qpic_t		*sb_colon, *sb_slash;
+qpic_t		*sb_ibar;
+qpic_t		*sb_sbar;
+qpic_t		*sb_scorebar;
+
+qpic_t		*sb_weapons[7][8];	// 0 is active, 1 is owned, 2-5 are flashes
+qpic_t		*sb_ammo[4];
+qpic_t		*sb_sigil[4];
+qpic_t		*sb_armor[3];
+qpic_t		*sb_items[32];
+
+qpic_t	*sb_faces[7][2];		// 0 is gibbed, 1 is dead, 2-6 are alive
+							// 0 is static, 1 is temporary animation
+qpic_t	*sb_face_invis;
+qpic_t	*sb_face_quad;
+qpic_t	*sb_face_invuln;
+qpic_t	*sb_face_invis_invuln;
+
+qboolean	sb_showscores;
+qboolean	sb_showteamscores;
+
+int			sb_lines;			// scan lines to draw
+
+void Sbar_DeathmatchOverlay (int start);
+void Sbar_TeamOverlay (void);
+void Sbar_MiniDeathmatchOverlay (void);
+
+static qboolean largegame = false;
+
+/*
+===============
+Sbar_ShowTeamScores
+
+Tab key down
+===============
+*/
+void Sbar_ShowTeamScores (void)
+{
+	if (sb_showteamscores)
+		return;
+
+	sb_showteamscores = true;
+	sb_updates = 0;
+}
+
+/*
+===============
+Sbar_DontShowTeamScores
+
+Tab key up
+===============
+*/
+void Sbar_DontShowTeamScores (void)
+{
+	sb_showteamscores = false;
+	sb_updates = 0;
+}
+
+/*
+===============
+Sbar_ShowScores
+
+Tab key down
+===============
+*/
+void Sbar_ShowScores (void)
+{
+	if (sb_showscores)
+		return;
+
+	sb_showscores = true;
+	sb_updates = 0;
+}
+
+/*
+===============
+Sbar_DontShowScores
+
+Tab key up
+===============
+*/
+void Sbar_DontShowScores (void)
+{
+	sb_showscores = false;
+	sb_updates = 0;
+}
+
+/*
+===============
+Sbar_Changed
+===============
+*/
+void Sbar_Changed (void)
+{
+	sb_updates = 0;	// update next frame
+}
+
+/*
+===============
+Sbar_Init
+===============
+*/
+void Sbar_Init (void)
+{
+	int		i;
+
+	for (i=0 ; i<10 ; i++)
+	{
+		sb_nums[0][i] = Draw_PicFromWad (va("num_%i",i));
+		sb_nums[1][i] = Draw_PicFromWad (va("anum_%i",i));
+	}
+
+	sb_nums[0][10] = Draw_PicFromWad ("num_minus");
+	sb_nums[1][10] = Draw_PicFromWad ("anum_minus");
+
+	sb_colon = Draw_PicFromWad ("num_colon");
+	sb_slash = Draw_PicFromWad ("num_slash");
+
+	sb_weapons[0][0] = Draw_PicFromWad ("inv_shotgun");
+	sb_weapons[0][1] = Draw_PicFromWad ("inv_sshotgun");
+	sb_weapons[0][2] = Draw_PicFromWad ("inv_nailgun");
+	sb_weapons[0][3] = Draw_PicFromWad ("inv_snailgun");
+	sb_weapons[0][4] = Draw_PicFromWad ("inv_rlaunch");
+	sb_weapons[0][5] = Draw_PicFromWad ("inv_srlaunch");
+	sb_weapons[0][6] = Draw_PicFromWad ("inv_lightng");
+	
+	sb_weapons[1][0] = Draw_PicFromWad ("inv2_shotgun");
+	sb_weapons[1][1] = Draw_PicFromWad ("inv2_sshotgun");
+	sb_weapons[1][2] = Draw_PicFromWad ("inv2_nailgun");
+	sb_weapons[1][3] = Draw_PicFromWad ("inv2_snailgun");
+	sb_weapons[1][4] = Draw_PicFromWad ("inv2_rlaunch");
+	sb_weapons[1][5] = Draw_PicFromWad ("inv2_srlaunch");
+	sb_weapons[1][6] = Draw_PicFromWad ("inv2_lightng");
+	
+	for (i=0 ; i<5 ; i++)
+	{
+		sb_weapons[2+i][0] = Draw_PicFromWad (va("inva%i_shotgun",i+1));
+		sb_weapons[2+i][1] = Draw_PicFromWad (va("inva%i_sshotgun",i+1));
+		sb_weapons[2+i][2] = Draw_PicFromWad (va("inva%i_nailgun",i+1));
+		sb_weapons[2+i][3] = Draw_PicFromWad (va("inva%i_snailgun",i+1));
+		sb_weapons[2+i][4] = Draw_PicFromWad (va("inva%i_rlaunch",i+1));
+		sb_weapons[2+i][5] = Draw_PicFromWad (va("inva%i_srlaunch",i+1));
+		sb_weapons[2+i][6] = Draw_PicFromWad (va("inva%i_lightng",i+1));
+	}
+
+	sb_ammo[0] = Draw_PicFromWad ("sb_shells");
+	sb_ammo[1] = Draw_PicFromWad ("sb_nails");
+	sb_ammo[2] = Draw_PicFromWad ("sb_rocket");
+	sb_ammo[3] = Draw_PicFromWad ("sb_cells");
+
+	sb_armor[0] = Draw_PicFromWad ("sb_armor1");
+	sb_armor[1] = Draw_PicFromWad ("sb_armor2");
+	sb_armor[2] = Draw_PicFromWad ("sb_armor3");
+
+	sb_items[0] = Draw_PicFromWad ("sb_key1");
+	sb_items[1] = Draw_PicFromWad ("sb_key2");
+	sb_items[2] = Draw_PicFromWad ("sb_invis");
+	sb_items[3] = Draw_PicFromWad ("sb_invuln");
+	sb_items[4] = Draw_PicFromWad ("sb_suit");
+	sb_items[5] = Draw_PicFromWad ("sb_quad");
+
+	sb_sigil[0] = Draw_PicFromWad ("sb_sigil1");
+	sb_sigil[1] = Draw_PicFromWad ("sb_sigil2");
+	sb_sigil[2] = Draw_PicFromWad ("sb_sigil3");
+	sb_sigil[3] = Draw_PicFromWad ("sb_sigil4");
+
+	sb_faces[4][0] = Draw_PicFromWad ("face1");
+	sb_faces[4][1] = Draw_PicFromWad ("face_p1");
+	sb_faces[3][0] = Draw_PicFromWad ("face2");
+	sb_faces[3][1] = Draw_PicFromWad ("face_p2");
+	sb_faces[2][0] = Draw_PicFromWad ("face3");
+	sb_faces[2][1] = Draw_PicFromWad ("face_p3");
+	sb_faces[1][0] = Draw_PicFromWad ("face4");
+	sb_faces[1][1] = Draw_PicFromWad ("face_p4");
+	sb_faces[0][0] = Draw_PicFromWad ("face5");
+	sb_faces[0][1] = Draw_PicFromWad ("face_p5");
+
+	sb_face_invis = Draw_PicFromWad ("face_invis");
+	sb_face_invuln = Draw_PicFromWad ("face_invul2");
+	sb_face_invis_invuln = Draw_PicFromWad ("face_inv2");
+	sb_face_quad = Draw_PicFromWad ("face_quad");
+
+	Cmd_AddCommand ("+showscores", Sbar_ShowScores);
+	Cmd_AddCommand ("-showscores", Sbar_DontShowScores);
+		
+	Cmd_AddCommand ("+showteamscores", Sbar_ShowTeamScores);
+	Cmd_AddCommand ("-showteamscores", Sbar_DontShowTeamScores);
+		
+	sb_sbar = Draw_PicFromWad ("sbar");
+	sb_ibar = Draw_PicFromWad ("ibar");
+	sb_scorebar = Draw_PicFromWad ("scorebar");
+}
+
+
+//=============================================================================
+
+// drawing routines are reletive to the status bar location
+
+/*
+=============
+Sbar_DrawPic
+=============
+*/
+void Sbar_DrawPic (int x, int y, qpic_t *pic)
+{
+	Draw_Pic (x /* + ((vid.width - 320)>>1) */, y + (vid.height-SBAR_HEIGHT), pic);
+}
+
+/*
+=============
+Sbar_DrawSubPic
+=============
+JACK: Draws a portion of the picture in the status bar.
+*/
+
+void Sbar_DrawSubPic(int x, int y, qpic_t *pic, int srcx, int srcy, int width, int height) 
+{
+	Draw_SubPic (x, y+(vid.height-SBAR_HEIGHT), pic, srcx, srcy, width, height);
+}
+
+
+/*
+=============
+Sbar_DrawTransPic
+=============
+*/
+void Sbar_DrawTransPic (int x, int y, qpic_t *pic)
+{
+	Draw_TransPic (x /*+ ((vid.width - 320)>>1) */, y + (vid.height-SBAR_HEIGHT), pic);
+}
+
+/*
+================
+Sbar_DrawCharacter
+
+Draws one solid graphics character
+================
+*/
+void Sbar_DrawCharacter (int x, int y, int num)
+{
+	Draw_Character ( x /*+ ((vid.width - 320)>>1) */ + 4, y + vid.height-SBAR_HEIGHT, num);
+}
+
+/*
+================
+Sbar_DrawString
+================
+*/
+void Sbar_DrawString (int x, int y, char *str)
+{
+	Draw_String (x /*+ ((vid.width - 320)>>1) */, y+ vid.height-SBAR_HEIGHT, str);
+}
+
+/*
+=============
+Sbar_itoa
+=============
+*/
+int Sbar_itoa (int num, char *buf)
+{
+	char	*str;
+	int		pow10;
+	int		dig;
+	
+	str = buf;
+	
+	if (num < 0)
+	{
+		*str++ = '-';
+		num = -num;
+	}
+	
+	for (pow10 = 10 ; num >= pow10 ; pow10 *= 10)
+	;
+	
+	do
+	{
+		pow10 /= 10;
+		dig = num/pow10;
+		*str++ = '0'+dig;
+		num -= dig*pow10;
+	} while (pow10 != 1);
+	
+	*str = 0;
+	
+	return str-buf;
+}
+
+
+/*
+=============
+Sbar_DrawNum
+=============
+*/
+void Sbar_DrawNum (int x, int y, int num, int digits, int color)
+{
+	char			str[12];
+	char			*ptr;
+	int				l, frame;
+
+	l = Sbar_itoa (num, str);
+	ptr = str;
+	if (l > digits)
+		ptr += (l-digits);
+	if (l < digits)
+		x += (digits-l)*24;
+
+	while (*ptr)
+	{
+		if (*ptr == '-')
+			frame = STAT_MINUS;
+		else
+			frame = *ptr -'0';
+
+		Sbar_DrawTransPic (x,y,sb_nums[color][frame]);
+		x += 24;
+		ptr++;
+	}
+}
+
+//=============================================================================
+
+//ZOID: this should be MAX_CLIENTS, not MAX_SCOREBOARD!!
+//int		fragsort[MAX_SCOREBOARD];
+int		fragsort[MAX_CLIENTS];
+int		scoreboardlines;
+typedef struct {
+	char team[16+1];
+	int frags;
+	int players;
+	int plow, phigh, ptotal;
+} team_t;
+team_t teams[MAX_CLIENTS];
+int teamsort[MAX_CLIENTS];
+int scoreboardteams;
+
+/*
+===============
+Sbar_SortFrags
+===============
+*/
+void Sbar_SortFrags (qboolean includespec)
+{
+	int		i, j, k;
+		
+// sort by frags
+	scoreboardlines = 0;
+	for (i=0 ; i<MAX_CLIENTS ; i++)
+	{
+		if (cl.players[i].name[0] &&
+			(!cl.players[i].spectator || includespec))
+		{
+			fragsort[scoreboardlines] = i;
+			scoreboardlines++;
+			if (cl.players[i].spectator)
+				cl.players[i].frags = -999;
+		}
+	}
+		
+	for (i=0 ; i<scoreboardlines ; i++)
+		for (j=0 ; j<scoreboardlines-1-i ; j++)
+			if (cl.players[fragsort[j]].frags < cl.players[fragsort[j+1]].frags)
+			{
+				k = fragsort[j];
+				fragsort[j] = fragsort[j+1];
+				fragsort[j+1] = k;
+			}
+}
+
+void Sbar_SortTeams (void)
+{
+	int				i, j, k;
+	player_info_t	*s;
+	int				teamplay;
+	char t[16+1];
+
+// request new ping times every two second
+	scoreboardteams = 0;
+
+	teamplay = atoi(Info_ValueForKey(cl.serverinfo, "teamplay"));
+	if (!teamplay)
+		return;
+
+// sort the teams
+	memset(teams, 0, sizeof(teams));
+	for (i = 0; i < MAX_CLIENTS; i++)
+		teams[i].plow = 999;
+
+	for (i = 0; i < MAX_CLIENTS; i++) {
+		s = &cl.players[i];
+		if (!s->name[0])
+			continue;
+		if (s->spectator)
+			continue;
+
+		// find his team in the list
+		t[16] = 0;
+		strncpy(t, Info_ValueForKey(s->userinfo, "team"), 16);
+		if (!t || !t[0])
+			continue; // not on team
+		for (j = 0; j < scoreboardteams; j++)
+			if (!strcmp(teams[j].team, t)) {
+				teams[j].frags += s->frags;
+				teams[j].players++;
+				goto addpinginfo;
+			}
+		if (j == scoreboardteams) { // must add him
+			j = scoreboardteams++;
+			strcpy(teams[j].team, t);
+			teams[j].frags = s->frags;
+			teams[j].players = 1;
+addpinginfo:
+			if (teams[j].plow > s->ping)
+				teams[j].plow = s->ping;
+			if (teams[j].phigh < s->ping)
+				teams[j].phigh = s->ping;
+			teams[j].ptotal += s->ping;
+		}
+	}
+
+	// sort
+	for (i = 0; i < scoreboardteams; i++)
+		teamsort[i] = i;
+
+	// good 'ol bubble sort
+	for (i = 0; i < scoreboardteams - 1; i++)
+		for (j = i + 1; j < scoreboardteams; j++)
+			if (teams[teamsort[i]].frags < teams[teamsort[j]].frags) {
+				k = teamsort[i];
+				teamsort[i] = teamsort[j];
+				teamsort[j] = k;
+			}
+}
+
+int	Sbar_ColorForMap (int m)
+{
+	m = (m < 0) ? 0 : ((m > 13) ? 13 : m);
+
+	m *= 16;
+	return m < 128 ? m + 8 : m + 8;
+}
+
+
+/*
+===============
+Sbar_SoloScoreboard
+===============
+*/
+void Sbar_SoloScoreboard (void)
+{
+	char	str[80];
+	int		minutes, seconds, tens, units;
+
+	Sbar_DrawPic (0, 0, sb_scorebar);
+
+	// time
+	minutes = cl.time / 60;
+	seconds = cl.time - 60*minutes;
+	tens = seconds / 10;
+	units = seconds - 10*tens;
+	sprintf (str,"Time :%3i:%i%i", minutes, tens, units);
+	Sbar_DrawString (184, 4, str);
+}
+
+//=============================================================================
+
+/*
+===============
+Sbar_DrawInventory
+===============
+*/
+void Sbar_DrawInventory (void)
+{	
+	int		i;
+	char	num[6];
+	float	time;
+	int		flashon;
+	qboolean	headsup;
+	qboolean    hudswap;
+
+	headsup = !(cl_sbar.value || scr_viewsize.value<100);
+	hudswap = cl_hudswap.value; // Get that nasty float out :)
+
+	if (!headsup)
+		Sbar_DrawPic (0, -24, sb_ibar);
+// weapons
+	for (i=0 ; i<7 ; i++)
+	{
+		if (cl.stats[STAT_ITEMS] & (IT_SHOTGUN<<i) )
+		{
+			time = cl.item_gettime[i];
+			flashon = (int)((cl.time - time)*10);
+			if (flashon < 0)
+				flashon = 0;
+			if (flashon >= 10)
+			{
+				if ( cl.stats[STAT_ACTIVEWEAPON] == (IT_SHOTGUN<<i)  )
+					flashon = 1;
+				else
+					flashon = 0;
+			}
+			else
+				flashon = (flashon%5) + 2;
+
+			if (headsup) {
+				if (i || vid.height>200)
+					Sbar_DrawSubPic ((hudswap) ? 0 : (vid.width-24),-68-(7-i)*16 , sb_weapons[flashon][i],0,0,24,16);
+			
+			} else 
+			Sbar_DrawPic (i*24, -16, sb_weapons[flashon][i]);
+//			Sbar_DrawSubPic (0,0,20,20,i*24, -16, sb_weapons[flashon][i]);
+
+			if (flashon > 1)
+				sb_updates = 0;		// force update to remove flash
+		}
+	}
+
+// ammo counts
+	for (i=0 ; i<4 ; i++)
+	{
+		sprintf (num, "%3i",cl.stats[STAT_SHELLS+i] );
+		if (headsup) {
+//			Sbar_DrawSubPic(3, -24, sb_ibar, 3, 0, 42,11);
+			Sbar_DrawSubPic((hudswap) ? 0 : (vid.width-42), -24 - (4-i)*11, sb_ibar, 3+(i*48), 0, 42, 11);
+			if (num[0] != ' ')
+				Sbar_DrawCharacter ( (hudswap) ? 3 : (vid.width-39), -24 - (4-i)*11, 18 + num[0] - '0');
+			if (num[1] != ' ')
+				Sbar_DrawCharacter ( (hudswap) ? 11 : (vid.width-31), -24 - (4-i)*11, 18 + num[1] - '0');
+			if (num[2] != ' ')
+				Sbar_DrawCharacter ( (hudswap) ? 19 : (vid.width-23), -24 - (4-i)*11, 18 + num[2] - '0');
+		} else {
+		if (num[0] != ' ')
+			Sbar_DrawCharacter ( (6*i+1)*8 - 2, -24, 18 + num[0] - '0');
+		if (num[1] != ' ')
+			Sbar_DrawCharacter ( (6*i+2)*8 - 2, -24, 18 + num[1] - '0');
+		if (num[2] != ' ')
+			Sbar_DrawCharacter ( (6*i+3)*8 - 2, -24, 18 + num[2] - '0');
+	}
+	}
+	
+	flashon = 0;
+// items
+	for (i=0 ; i<6 ; i++)
+		if (cl.stats[STAT_ITEMS] & (1<<(17+i)))
+		{
+			time = cl.item_gettime[17+i];
+			if (time &&	time > cl.time - 2 && flashon )
+			{	// flash frame
+				sb_updates = 0;
+			}
+			else
+				Sbar_DrawPic (192 + i*16, -16, sb_items[i]);		
+			if (time &&	time > cl.time - 2)
+				sb_updates = 0;
+		}
+
+// sigils
+	for (i=0 ; i<4 ; i++)
+		if (cl.stats[STAT_ITEMS] & (1<<(28+i)))
+		{
+			time = cl.item_gettime[28+i];
+			if (time &&	time > cl.time - 2 && flashon )
+			{	// flash frame
+				sb_updates = 0;
+			}
+			else
+				Sbar_DrawPic (320-32 + i*8, -16, sb_sigil[i]);		
+			if (time &&	time > cl.time - 2)
+				sb_updates = 0;
+		}
+}
+
+//=============================================================================
+
+/*
+===============
+Sbar_DrawFrags
+===============
+*/
+void Sbar_DrawFrags (void)
+{	
+	int				i, k, l;
+	int				top, bottom;
+	int				x, y, f;
+	char			num[12];
+	player_info_t	*s;
+	
+	Sbar_SortFrags (false);
+
+// draw the text
+	l = scoreboardlines <= 4 ? scoreboardlines : 4;
+	
+	x = 23;
+//	xofs = (vid.width - 320)>>1;
+	y = vid.height - SBAR_HEIGHT - 23;
+
+	for (i=0 ; i<l ; i++)
+	{
+		k = fragsort[i];
+		s = &cl.players[k];
+		if (!s->name[0])
+			continue;
+		if (s->spectator)
+			continue;
+
+	// draw background
+		top = s->topcolor;
+		bottom = s->bottomcolor;
+		top = (top < 0) ? 0 : ((top > 13) ? 13 : top);
+		bottom = (bottom < 0) ? 0 : ((bottom > 13) ? 13 : bottom);
+
+		top = Sbar_ColorForMap (top);
+		bottom = Sbar_ColorForMap (bottom);
+	
+//		Draw_Fill (xofs + x*8 + 10, y, 28, 4, top);
+//		Draw_Fill (xofs + x*8 + 10, y+4, 28, 3, bottom);
+		Draw_Fill (x*8 + 10, y, 28, 4, top);
+		Draw_Fill (x*8 + 10, y+4, 28, 3, bottom);
+
+	// draw number
+		f = s->frags;
+		sprintf (num, "%3i",f);
+		
+		Sbar_DrawCharacter ( (x+1)*8 , -24, num[0]);
+		Sbar_DrawCharacter ( (x+2)*8 , -24, num[1]);
+		Sbar_DrawCharacter ( (x+3)*8 , -24, num[2]);
+
+		if (k == cl.playernum)
+		{
+			Sbar_DrawCharacter (x*8+2, -24, 16);
+			Sbar_DrawCharacter ( (x+4)*8-4, -24, 17);
+		}
+		x+=4;
+	}
+}
+
+//=============================================================================
+
+
+/*
+===============
+Sbar_DrawFace
+===============
+*/
+void Sbar_DrawFace (void)
+{
+	int		f, anim;
+
+	if ( (cl.stats[STAT_ITEMS] & (IT_INVISIBILITY | IT_INVULNERABILITY) )
+	== (IT_INVISIBILITY | IT_INVULNERABILITY) )
+	{
+		Sbar_DrawPic (112, 0, sb_face_invis_invuln);
+		return;
+	}
+	if (cl.stats[STAT_ITEMS] & IT_QUAD) 
+	{
+		Sbar_DrawPic (112, 0, sb_face_quad );
+		return;
+	}
+	if (cl.stats[STAT_ITEMS] & IT_INVISIBILITY) 
+	{
+		Sbar_DrawPic (112, 0, sb_face_invis );
+		return;
+	}
+	if (cl.stats[STAT_ITEMS] & IT_INVULNERABILITY) 
+	{
+		Sbar_DrawPic (112, 0, sb_face_invuln);
+		return;
+	}
+
+	if (cl.stats[STAT_HEALTH] >= 100)
+		f = 4;
+	else
+		f = cl.stats[STAT_HEALTH] / 20;
+	
+	if (cl.time <= cl.faceanimtime)
+	{
+		anim = 1;
+		sb_updates = 0;		// make sure the anim gets drawn over
+	}
+	else
+		anim = 0;
+	Sbar_DrawPic (112, 0, sb_faces[f][anim]);
+}
+
+/*
+=============
+Sbar_DrawNormal
+=============
+*/
+void Sbar_DrawNormal (void)
+{
+	if (cl_sbar.value || scr_viewsize.value<100)
+	Sbar_DrawPic (0, 0, sb_sbar);
+
+// armor
+	if (cl.stats[STAT_ITEMS] & IT_INVULNERABILITY)
+	{
+		Sbar_DrawNum (24, 0, 666, 3, 1);
+		Sbar_DrawPic (0, 0, draw_disc);
+	}
+	else
+	{
+		Sbar_DrawNum (24, 0, cl.stats[STAT_ARMOR], 3
+		, cl.stats[STAT_ARMOR] <= 25);
+		if (cl.stats[STAT_ITEMS] & IT_ARMOR3)
+			Sbar_DrawPic (0, 0, sb_armor[2]);
+		else if (cl.stats[STAT_ITEMS] & IT_ARMOR2)
+			Sbar_DrawPic (0, 0, sb_armor[1]);
+		else if (cl.stats[STAT_ITEMS] & IT_ARMOR1)
+			Sbar_DrawPic (0, 0, sb_armor[0]);
+	}
+	
+// face
+	Sbar_DrawFace ();
+	
+// health
+	Sbar_DrawNum (136, 0, cl.stats[STAT_HEALTH], 3
+	, cl.stats[STAT_HEALTH] <= 25);
+
+// ammo icon
+	if (cl.stats[STAT_ITEMS] & IT_SHELLS)
+		Sbar_DrawPic (224, 0, sb_ammo[0]);
+	else if (cl.stats[STAT_ITEMS] & IT_NAILS)
+		Sbar_DrawPic (224, 0, sb_ammo[1]);
+	else if (cl.stats[STAT_ITEMS] & IT_ROCKETS)
+		Sbar_DrawPic (224, 0, sb_ammo[2]);
+	else if (cl.stats[STAT_ITEMS] & IT_CELLS)
+		Sbar_DrawPic (224, 0, sb_ammo[3]);
+	
+	Sbar_DrawNum (248, 0, cl.stats[STAT_AMMO], 3
+	, cl.stats[STAT_AMMO] <= 10);
+}
+
+/*
+===============
+Sbar_Draw
+===============
+*/
+void Sbar_Draw (void)
+{
+	qboolean headsup;
+	char st[512];
+
+	headsup = !(cl_sbar.value || scr_viewsize.value<100);
+	if ((sb_updates >= vid.numpages) && !headsup)
+		return;
+
+	if (scr_con_current == vid.height)
+		return;		// console is full screen
+
+	scr_copyeverything = 1;
+//	scr_fullupdate = 0;
+
+	sb_updates++;
+		
+// top line
+	if (sb_lines > 24)
+	{
+		if (!cl.spectator || autocam == CAM_TRACK)
+			Sbar_DrawInventory ();
+		if (!headsup || vid.width<512)
+			Sbar_DrawFrags ();
+	}	
+
+// main area
+	if (sb_lines > 0)
+	{
+		if (cl.spectator) {
+			if (autocam != CAM_TRACK) {
+				Sbar_DrawPic (0, 0, sb_scorebar);
+				Sbar_DrawString (160-7*8,4, "SPECTATOR MODE");
+				Sbar_DrawString(160-14*8+4, 12, "Press [ATTACK] for AutoCamera");
+			} else {
+				if (sb_showscores || cl.stats[STAT_HEALTH] <= 0)
+					Sbar_SoloScoreboard ();
+				else
+					Sbar_DrawNormal ();
+
+//					Sbar_DrawString (160-14*8+4,4, "SPECTATOR MODE - TRACK CAMERA");
+				sprintf(st, "Tracking %-.13s, [JUMP] for next",
+						cl.players[spec_track].name);
+				Sbar_DrawString(0, -8, st);
+			}
+		} else if (sb_showscores || cl.stats[STAT_HEALTH] <= 0)
+			Sbar_SoloScoreboard ();
+		else
+			Sbar_DrawNormal ();
+	}
+
+// main screen deathmatch rankings
+	// if we're dead show team scores in team games
+	if (cl.stats[STAT_HEALTH] <= 0 && !cl.spectator)
+		if (atoi(Info_ValueForKey(cl.serverinfo, "teamplay")) > 0 &&
+			!sb_showscores)
+			Sbar_TeamOverlay();
+		else
+			Sbar_DeathmatchOverlay (0);
+	else if (sb_showscores)
+		Sbar_DeathmatchOverlay (0);
+	else if (sb_showteamscores)
+		Sbar_TeamOverlay();
+
+#ifdef GLQUAKE
+	if (sb_showscores || sb_showteamscores || 
+		cl.stats[STAT_HEALTH] <= 0)
+		sb_updates = 0;
+	// clear unused areas in gl
+#if 0
+	{
+		int x = (vid.width - 320)>>1;
+
+		// left
+		if (x > 0) {
+			Draw_TileClear (0, vid.height - sb_lines, x, sb_lines);
+			Draw_TileClear (x+320, vid.height - sb_lines, vid.width - x+320, sb_lines);
+		}
+	}
+#endif
+	if (vid.width > 320 && !headsup)
+		Draw_TileClear (320, vid.height - sb_lines, vid.width - 320, sb_lines);
+#endif
+
+	if (sb_lines > 0)
+		Sbar_MiniDeathmatchOverlay ();
+}
+
+//=============================================================================
+
+/*
+==================
+Sbar_IntermissionNumber
+
+==================
+*/
+void Sbar_IntermissionNumber (int x, int y, int num, int digits, int color)
+{
+	char			str[12];
+	char			*ptr;
+	int				l, frame;
+
+	l = Sbar_itoa (num, str);
+	ptr = str;
+	if (l > digits)
+		ptr += (l-digits);
+	if (l < digits)
+		x += (digits-l)*24;
+
+	while (*ptr)
+	{
+		if (*ptr == '-')
+			frame = STAT_MINUS;
+		else
+			frame = *ptr -'0';
+
+		Draw_TransPic (x,y,sb_nums[color][frame]);
+		x += 24;
+		ptr++;
+	}
+}
+
+/*
+==================
+Sbar_TeamOverlay
+
+team frags
+added by Zoid
+==================
+*/
+void Sbar_TeamOverlay (void)
+{
+	qpic_t			*pic;
+	int				i, k, l;
+	int				x, y;
+	char			num[12];
+	int				teamplay;
+	char			team[5];
+	team_t *tm;
+	int plow, phigh, pavg;
+
+// request new ping times every two second
+	teamplay = atoi(Info_ValueForKey(cl.serverinfo, "teamplay"));
+
+	if (!teamplay) {
+		Sbar_DeathmatchOverlay(0);
+		return;
+	}
+
+	scr_copyeverything = 1;
+	scr_fullupdate = 0;
+
+	pic = Draw_CachePic ("gfx/ranking.lmp");
+	Draw_Pic (160-pic->width/2, 0, pic);
+
+	y = 24;
+	x = 36;
+	Draw_String(x, y, "low/avg/high team total players");
+	y += 8;
+//	Draw_String(x, y, "------------ ---- ----- -------");
+	Draw_String(x, y, "\x1d\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1f \x1d\x1e\x1e\x1f \x1d\x1e\x1e\x1e\x1f \x1d\x1e\x1e\x1e\x1e\x1e\x1f");
+	y += 8;
+
+// sort the teams
+	Sbar_SortTeams();
+
+// draw the text
+	l = scoreboardlines;
+
+	for (i=0 ; i < scoreboardteams && y <= vid.height-10 ; i++)
+	{
+		k = teamsort[i];
+		tm = teams + k;
+
+	// draw pings
+		plow = tm->plow;
+		if (plow < 0 || plow > 999)
+			plow = 999;
+		phigh = tm->phigh;
+		if (phigh < 0 || phigh > 999)
+			phigh = 999;
+		if (!tm->players)
+			pavg = 999;
+		else
+			pavg = tm->ptotal / tm->players;
+		if (pavg < 0 || pavg > 999)
+			pavg = 999;
+
+		sprintf (num, "%3i/%3i/%3i", plow, pavg, phigh);
+		Draw_String ( x, y, num);
+
+	// draw team
+		team[4] = 0;
+		strncpy (team, tm->team, 4);
+		Draw_String (x + 104, y, team);
+
+	// draw total
+		sprintf (num, "%5i", tm->frags);
+		Draw_String (x + 104 + 40, y, num);
+		
+	// draw players
+		sprintf (num, "%5i", tm->players);
+		Draw_String (x + 104 + 88, y, num);
+		
+		if (!strncmp(Info_ValueForKey(cl.players[cl.playernum].userinfo,
+			"team"), tm->team, 16)) {
+			Draw_Character ( x + 104 - 8, y, 16);
+			Draw_Character ( x + 104 + 32, y, 17);
+		}
+		
+		y += 8;
+	}
+	y += 8;
+	Sbar_DeathmatchOverlay(y);
+}
+
+/*
+==================
+Sbar_DeathmatchOverlay
+
+ping time frags name
+==================
+*/
+void Sbar_DeathmatchOverlay (int start)
+{
+	qpic_t			*pic;
+	int				i, k, l;
+	int				top, bottom;
+	int				x, y, f;
+	char			num[12];
+	player_info_t	*s;
+	int				total;
+	int				minutes;
+	int				p;
+	int				teamplay;
+	char			team[5];
+	int				skip = 10;
+
+	if (largegame)
+		skip = 8;
+
+// request new ping times every two second
+	if (realtime - cl.last_ping_request > 2)
+	{
+		cl.last_ping_request = realtime;
+		MSG_WriteByte (&cls.netchan.message, clc_stringcmd);
+		SZ_Print (&cls.netchan.message, "pings");
+	}
+
+	teamplay = atoi(Info_ValueForKey(cl.serverinfo, "teamplay"));
+
+	scr_copyeverything = 1;
+	scr_fullupdate = 0;
+
+	if (!start) {
+		pic = Draw_CachePic ("gfx/ranking.lmp");
+		Draw_Pic (160-pic->width/2, 0, pic);
+	}
+
+// scores	
+	Sbar_SortFrags (true);
+
+// draw the text
+	l = scoreboardlines;
+
+	if (start)
+		y = start;
+	else
+		y = 24;
+	if (teamplay)
+	{
+		x = 4;
+//                            0    40 64   104   152  192 
+		Draw_String ( x , y, "ping pl time frags team name");
+		y += 8;
+//		Draw_String ( x , y, "---- -- ---- ----- ---- ----------------");
+		Draw_String ( x , y, "\x1d\x1e\x1e\x1f \x1d\x1f \x1d\x1e\x1e\x1f \x1d\x1e\x1e\x1e\x1f \x1d\x1e\x1e\x1f \x1d\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1f");
+		y += 8;
+	}
+	else
+	{
+		x = 16;
+//                            0    40 64   104   152
+		Draw_String ( x , y, "ping pl time frags name");
+		y += 8;
+//		Draw_String ( x , y, "---- -- ---- ----- ----------------");
+		Draw_String ( x , y, "\x1d\x1e\x1e\x1f \x1d\x1f \x1d\x1e\x1e\x1f \x1d\x1e\x1e\x1e\x1f \x1d\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1f");
+		y += 8;
+	}
+
+	for (i=0 ; i<l && y <= vid.height-10 ; i++)
+	{
+		k = fragsort[i];
+		s = &cl.players[k];
+		if (!s->name[0])
+			continue;
+
+		// draw ping
+		p = s->ping;
+		if (p < 0 || p > 999)
+			p = 999;
+		sprintf (num, "%4i", p);
+		Draw_String ( x, y, num);
+
+		// draw pl
+		p = s->pl;
+		sprintf (num, "%3i", p);
+		if (p > 25)
+			Draw_Alt_String ( x+32, y, num);
+		else
+			Draw_String ( x+32, y, num);
+
+		if (s->spectator)
+		{
+			Draw_String (x+40, y, "(spectator)");
+			// draw name
+			if (teamplay)
+				Draw_String (x+152+40, y, s->name);
+			else
+				Draw_String (x+152, y, s->name);
+			y += skip;
+			continue;
+		}
+
+
+		// draw time
+		if (cl.intermission)
+			total = cl.completed_time - s->entertime;
+		else
+			total = realtime - s->entertime;
+		minutes = (int)total/60;
+		sprintf (num, "%4i", minutes);
+		Draw_String ( x+64 , y, num);
+
+		// draw background
+		top = s->topcolor;
+		bottom = s->bottomcolor;
+		top = Sbar_ColorForMap (top);
+		bottom = Sbar_ColorForMap (bottom);
+	
+		if (largegame)
+			Draw_Fill ( x+104, y+1, 40, 3, top);
+		else
+			Draw_Fill ( x+104, y, 40, 4, top);
+		Draw_Fill ( x+104, y+4, 40, 4, bottom);
+
+	// draw number
+		f = s->frags;
+		sprintf (num, "%3i",f);
+		
+		Draw_Character ( x+112 , y, num[0]);
+		Draw_Character ( x+120 , y, num[1]);
+		Draw_Character ( x+128 , y, num[2]);
+
+		if (k == cl.playernum)
+		{
+			Draw_Character ( x + 104, y, 16);
+			Draw_Character ( x + 136, y, 17);
+		}
+		
+		// team
+		if (teamplay)
+		{
+			team[4] = 0;
+			strncpy (team, Info_ValueForKey(s->userinfo, "team"), 4);
+			Draw_String (x+152, y, team);
+		}
+
+		// draw name
+		if (teamplay)
+			Draw_String (x+152+40, y, s->name);
+		else
+			Draw_String (x+152, y, s->name);
+		
+		y += skip;
+	}
+
+	if (y >= vid.height-10) // we ran over the screen size, squish
+		largegame = true;
+}
+
+/*
+==================
+Sbar_MiniDeathmatchOverlay
+
+frags name
+frags team name
+displayed to right of status bar if there's room
+==================
+*/
+void Sbar_MiniDeathmatchOverlay (void)
+{
+	int				i, k;
+	int				top, bottom;
+	int				x, y, f;
+	char			num[12];
+	player_info_t	*s;
+	int				teamplay;
+	char			team[5];
+	int				numlines;
+	char			name[16+1];
+	team_t			*tm;
+
+	if (vid.width < 512 || !sb_lines)
+		return; // not enuff room
+
+	teamplay = atoi(Info_ValueForKey(cl.serverinfo, "teamplay"));
+
+	scr_copyeverything = 1;
+	scr_fullupdate = 0;
+
+// scores	
+	Sbar_SortFrags (false);
+	if (vid.width >= 640)
+		Sbar_SortTeams();
+
+	if (!scoreboardlines)
+		return; // no one there?
+
+// draw the text
+	y = vid.height - sb_lines - 1;
+	numlines = sb_lines/8;
+	if (numlines < 3)
+		return; // not enough room
+
+	// find us
+	for (i=0 ; i < scoreboardlines; i++)
+		if (fragsort[i] == cl.playernum)
+			break;
+
+	if (i == scoreboardlines) // we're not there, we are probably a spectator, just display top
+		i = 0;
+	else // figure out start
+		i = i - numlines/2;
+
+	if (i > scoreboardlines - numlines)
+		i = scoreboardlines - numlines;
+	if (i < 0)
+		i = 0;
+
+	x = 324;
+
+	for (/* */ ; i < scoreboardlines && y < vid.height - 8 + 1; i++)
+	{
+		k = fragsort[i];
+		s = &cl.players[k];
+		if (!s->name[0])
+			continue;
+
+	// draw ping
+		top = s->topcolor;
+		bottom = s->bottomcolor;
+		top = Sbar_ColorForMap (top);
+		bottom = Sbar_ColorForMap (bottom);
+	
+		Draw_Fill ( x, y+1, 40, 3, top);
+		Draw_Fill ( x, y+4, 40, 4, bottom);
+
+	// draw number
+		f = s->frags;
+		sprintf (num, "%3i",f);
+		
+		Draw_Character ( x+8 , y, num[0]);
+		Draw_Character ( x+16, y, num[1]);
+		Draw_Character ( x+24, y, num[2]);
+
+		if (k == cl.playernum)
+		{
+			Draw_Character ( x, y, 16);
+			Draw_Character ( x + 32, y, 17);
+		}
+		
+	// team
+		if (teamplay)
+		{
+			team[4] = 0;
+			strncpy (team, Info_ValueForKey(s->userinfo, "team"), 4);
+			Draw_String (x+48, y, team);
+		}
+
+	// draw name
+		name[16] = 0;
+		strncpy(name, s->name, 16);
+		if (teamplay)
+			Draw_String (x+48+40, y, name);
+		else
+			Draw_String (x+48, y, name);
+		y += 8;
+	}
+
+	// draw teams if room
+	if (vid.width < 640 || !teamplay)
+		return;
+
+	// draw seperator
+	x += 208;
+	for (y = vid.height - sb_lines; y < vid.height - 6; y += 2)
+		Draw_Character(x, y, 14);
+
+	x += 16;
+
+	y = vid.height - sb_lines;
+	for (i=0 ; i < scoreboardteams && y <= vid.height; i++)
+	{
+		k = teamsort[i];
+		tm = teams + k;
+
+	// draw pings
+		team[4] = 0;
+		strncpy (team, tm->team, 4);
+		Draw_String (x, y, team);
+
+	// draw total
+		sprintf (num, "%5i", tm->frags);
+		Draw_String (x + 40, y, num);
+		
+		if (!strncmp(Info_ValueForKey(cl.players[cl.playernum].userinfo,
+			"team"), tm->team, 16)) {
+			Draw_Character ( x - 8, y, 16);
+			Draw_Character ( x + 32, y, 17);
+		}
+		
+		y += 8;
+	}
+
+}
+
+
+/*
+==================
+Sbar_IntermissionOverlay
+
+==================
+*/
+void Sbar_IntermissionOverlay (void)
+{
+	scr_copyeverything = 1;
+	scr_fullupdate = 0;
+
+	if (atoi(Info_ValueForKey(cl.serverinfo, "teamplay")) > 0 && !sb_showscores)
+		Sbar_TeamOverlay ();
+	else
+		Sbar_DeathmatchOverlay (0);
+}
+
+
+/*
+==================
+Sbar_FinaleOverlay
+
+==================
+*/
+void Sbar_FinaleOverlay (void)
+{
+	qpic_t	*pic;
+
+	scr_copyeverything = 1;
+
+	pic = Draw_CachePic ("gfx/finale.lmp");
+	Draw_TransPic ( (vid.width-pic->width)/2, 16, pic);
+}
+
+
--- /dev/null
+++ b/QW/client/sbar.h
@@ -1,0 +1,39 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+
+// the status bar is only redrawn if something has changed, but if anything
+// does, the entire thing will be redrawn for the next vid.numpages frames.
+
+#define	SBAR_HEIGHT		24
+
+extern	int			sb_lines;			// scan lines to draw
+
+void Sbar_Init (void);
+
+void Sbar_Changed (void);
+// call whenever any of the client stats represented on the sbar changes
+
+void Sbar_Draw (void);
+// called every frame by screen
+
+void Sbar_IntermissionOverlay (void);
+// called each frame after the level has been completed
+
+void Sbar_FinaleOverlay (void);
--- /dev/null
+++ b/QW/client/screen.c
@@ -1,0 +1,1176 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// screen.c -- master for refresh, status bar, console, chat, notify, etc
+
+#include "quakedef.h"
+#include "r_local.h"
+
+#include <time.h>
+
+/*
+
+background clear
+rendering
+turtle/net/ram icons
+sbar
+centerprint / slow centerprint
+notify lines
+intermission / finale overlay
+loading plaque
+console
+menu
+
+required background clears
+required update regions
+
+
+syncronous draw mode or async
+One off screen buffer, with updates either copied or xblited
+Need to double buffer?
+
+
+async draw will require the refresh area to be cleared, because it will be
+xblited, but sync draw can just ignore it.
+
+sync
+draw
+
+CenterPrint ()
+SlowPrint ()
+Screen_Update ();
+Con_Printf ();
+
+net 
+turn off messages option
+
+the refresh is allways rendered, unless the console is full screen
+
+
+console is:
+	notify lines
+	half
+	full
+	
+
+*/
+
+
+// only the refresh window will be updated unless these variables are flagged 
+int			scr_copytop;
+int			scr_copyeverything;
+
+float		scr_con_current;
+float		scr_conlines;		// lines of console to display
+
+float		oldscreensize, oldfov;
+float		oldsbar;
+cvar_t		scr_viewsize = {"viewsize","100", true};
+cvar_t		scr_fov = {"fov","90"};	// 10 - 170
+cvar_t		scr_conspeed = {"scr_conspeed","300"};
+cvar_t		scr_centertime = {"scr_centertime","2"};
+cvar_t		scr_showram = {"showram","1"};
+cvar_t		scr_showturtle = {"showturtle","0"};
+cvar_t		scr_showpause = {"showpause","1"};
+cvar_t		scr_printspeed = {"scr_printspeed","8"};
+cvar_t		scr_allowsnap = {"scr_allowsnap", "1"};
+
+qboolean	scr_initialized;		// ready to draw
+
+qpic_t		*scr_ram;
+qpic_t		*scr_net;
+qpic_t		*scr_turtle;
+
+int			scr_fullupdate;
+
+int			clearconsole;
+int			clearnotify;
+
+int			sb_lines;
+
+viddef_t	vid;				// global video state
+
+vrect_t		*pconupdate;
+vrect_t		scr_vrect;
+
+qboolean	scr_disabled_for_loading;
+
+qboolean	scr_skipupdate;
+
+qboolean	block_drawing;
+
+void SCR_ScreenShot_f (void);
+void SCR_RSShot_f (void);
+
+/*
+===============================================================================
+
+CENTER PRINTING
+
+===============================================================================
+*/
+
+char		scr_centerstring[1024];
+float		scr_centertime_start;	// for slow victory printing
+float		scr_centertime_off;
+int			scr_center_lines;
+int			scr_erase_lines;
+int			scr_erase_center;
+
+/*
+==============
+SCR_CenterPrint
+
+Called for important messages that should stay in the center of the screen
+for a few moments
+==============
+*/
+void SCR_CenterPrint (char *str)
+{
+	strncpy (scr_centerstring, str, sizeof(scr_centerstring)-1);
+	scr_centertime_off = scr_centertime.value;
+	scr_centertime_start = cl.time;
+
+// count the number of lines for centering
+	scr_center_lines = 1;
+	while (*str)
+	{
+		if (*str == '\n')
+			scr_center_lines++;
+		str++;
+	}
+}
+
+void SCR_EraseCenterString (void)
+{
+	int		y;
+
+	if (scr_erase_center++ > vid.numpages)
+	{
+		scr_erase_lines = 0;
+		return;
+	}
+
+	if (scr_center_lines <= 4)
+		y = vid.height*0.35;
+	else
+		y = 48;
+
+	scr_copytop = 1;
+	Draw_TileClear (0, y, vid.width, min(8*scr_erase_lines, vid.height - y - 1));
+}
+
+void SCR_DrawCenterString (void)
+{
+	char	*start;
+	int		l;
+	int		j;
+	int		x, y;
+	int		remaining;
+
+// the finale prints the characters one at a time
+	if (cl.intermission)
+		remaining = scr_printspeed.value * (cl.time - scr_centertime_start);
+	else
+		remaining = 9999;
+
+	scr_erase_center = 0;
+	start = scr_centerstring;
+
+	if (scr_center_lines <= 4)
+		y = vid.height*0.35;
+	else
+		y = 48;
+
+	do	
+	{
+	// scan the width of the line
+		for (l=0 ; l<40 ; l++)
+			if (start[l] == '\n' || !start[l])
+				break;
+		x = (vid.width - l*8)/2;
+		for (j=0 ; j<l ; j++, x+=8)
+		{
+			Draw_Character (x, y, start[j]);	
+			if (!remaining--)
+				return;
+		}
+			
+		y += 8;
+
+		while (*start && *start != '\n')
+			start++;
+
+		if (!*start)
+			break;
+		start++;		// skip the \n
+	} while (1);
+}
+
+void SCR_CheckDrawCenterString (void)
+{
+	scr_copytop = 1;
+	if (scr_center_lines > scr_erase_lines)
+		scr_erase_lines = scr_center_lines;
+
+	scr_centertime_off -= host_frametime;
+	
+	if (scr_centertime_off <= 0 && !cl.intermission)
+		return;
+	if (key_dest != key_game)
+		return;
+
+	SCR_DrawCenterString ();
+}
+
+//=============================================================================
+
+/*
+====================
+CalcFov
+====================
+*/
+float CalcFov (float fov_x, float width, float height)
+{
+        float   a;
+        float   x;
+
+        if (fov_x < 1 || fov_x > 179)
+                Sys_Error ("Bad fov: %f", fov_x);
+
+        x = width/tan(fov_x/360*M_PI);
+
+        a = atan (height/x);
+
+        a = a*360/M_PI;
+
+        return a;
+}
+
+/*
+=================
+SCR_CalcRefdef
+
+Must be called whenever vid changes
+Internal use only
+=================
+*/
+static void SCR_CalcRefdef (void)
+{
+	vrect_t		vrect;
+	float		size;
+
+	scr_fullupdate = 0;		// force a background redraw
+	vid.recalc_refdef = 0;
+
+// force the status bar to redraw
+	Sbar_Changed ();
+
+//========================================
+	
+// bound viewsize
+	if (scr_viewsize.value < 30)
+		Cvar_Set ("viewsize","30");
+	if (scr_viewsize.value > 120)
+		Cvar_Set ("viewsize","120");
+
+// bound field of view
+	if (scr_fov.value < 10)
+		Cvar_Set ("fov","10");
+	if (scr_fov.value > 170)
+		Cvar_Set ("fov","170");
+
+	r_refdef.fov_x = scr_fov.value;
+	r_refdef.fov_y = CalcFov (r_refdef.fov_x, r_refdef.vrect.width, r_refdef.vrect.height);
+
+// intermission is always full screen	
+	if (cl.intermission)
+		size = 120;
+	else
+		size = scr_viewsize.value;
+
+	if (size >= 120)
+		sb_lines = 0;		// no status bar at all
+	else if (size >= 110)
+		sb_lines = 24;		// no inventory
+	else
+		sb_lines = 24+16+8;
+
+// these calculations mirror those in R_Init() for r_refdef, but take no
+// account of water warping
+	vrect.x = 0;
+	vrect.y = 0;
+	vrect.width = vid.width;
+	vrect.height = vid.height;
+
+	R_SetVrect (&vrect, &scr_vrect, sb_lines);
+
+// guard against going from one mode to another that's less than half the
+// vertical resolution
+	if (scr_con_current > vid.height)
+		scr_con_current = vid.height;
+
+// notify the refresh of the change
+	R_ViewChanged (&vrect, sb_lines, vid.aspect);
+}
+
+
+/*
+=================
+SCR_SizeUp_f
+
+Keybinding command
+=================
+*/
+void SCR_SizeUp_f (void)
+{
+	if (scr_viewsize.value < 120) {
+	Cvar_SetValue ("viewsize",scr_viewsize.value+10);
+	vid.recalc_refdef = 1;
+	}
+}
+
+
+/*
+=================
+SCR_SizeDown_f
+
+Keybinding command
+=================
+*/
+void SCR_SizeDown_f (void)
+{
+	Cvar_SetValue ("viewsize",scr_viewsize.value-10);
+	vid.recalc_refdef = 1;
+}
+
+//============================================================================
+
+/*
+==================
+SCR_Init
+==================
+*/
+void SCR_Init (void)
+{
+	Cvar_RegisterVariable (&scr_fov);
+	Cvar_RegisterVariable (&scr_viewsize);
+	Cvar_RegisterVariable (&scr_conspeed);
+	Cvar_RegisterVariable (&scr_showram);
+	Cvar_RegisterVariable (&scr_showturtle);
+	Cvar_RegisterVariable (&scr_showpause);
+	Cvar_RegisterVariable (&scr_centertime);
+	Cvar_RegisterVariable (&scr_printspeed);
+	Cvar_RegisterVariable (&scr_allowsnap);
+
+//
+// register our commands
+//
+	Cmd_AddCommand ("screenshot",SCR_ScreenShot_f);
+	Cmd_AddCommand ("snap",SCR_RSShot_f);
+	Cmd_AddCommand ("sizeup",SCR_SizeUp_f);
+	Cmd_AddCommand ("sizedown",SCR_SizeDown_f);
+
+	scr_ram = W_GetLumpName ("ram");
+	scr_net = W_GetLumpName ("net");
+	scr_turtle = W_GetLumpName ("turtle");
+
+	scr_initialized = true;
+}
+
+
+
+/*
+==============
+SCR_DrawRam
+==============
+*/
+void SCR_DrawRam (void)
+{
+	if (!scr_showram.value)
+		return;
+
+	if (!r_cache_thrash)
+		return;
+
+	Draw_Pic (scr_vrect.x+32, scr_vrect.y, scr_ram);
+}
+
+/*
+==============
+SCR_DrawTurtle
+==============
+*/
+void SCR_DrawTurtle (void)
+{
+	static int	count;
+	
+	if (!scr_showturtle.value)
+		return;
+
+	if (host_frametime < 0.1)
+	{
+		count = 0;
+		return;
+	}
+
+	count++;
+	if (count < 3)
+		return;
+
+	Draw_Pic (scr_vrect.x, scr_vrect.y, scr_turtle);
+}
+
+/*
+==============
+SCR_DrawNet
+==============
+*/
+void SCR_DrawNet (void)
+{
+	if (cls.netchan.outgoing_sequence - cls.netchan.incoming_acknowledged < UPDATE_BACKUP-1)
+		return;
+	if (cls.demoplayback)
+		return;
+
+	Draw_Pic (scr_vrect.x+64, scr_vrect.y, scr_net);
+}
+
+void SCR_DrawFPS (void)
+{
+	extern cvar_t show_fps;
+	static double lastframetime;
+	double t;
+	extern int fps_count;
+	static lastfps;
+	int x, y;
+	char st[80];
+
+	if (!show_fps.value)
+		return;
+
+	t = Sys_DoubleTime();
+	if ((t - lastframetime) >= 1.0) {
+		lastfps = fps_count;
+		fps_count = 0;
+		lastframetime = t;
+	}
+
+	sprintf(st, "%3d FPS", lastfps);
+	x = vid.width - strlen(st) * 8 - 8;
+	y = vid.height - sb_lines - 8;
+//	Draw_TileClear(x, y, strlen(st) * 8, 8);
+	Draw_String(x, y, st);
+}
+
+/*
+==============
+DrawPause
+==============
+*/
+void SCR_DrawPause (void)
+{
+	qpic_t	*pic;
+
+	if (!scr_showpause.value)		// turn off for screenshots
+		return;
+
+	if (!cl.paused)
+		return;
+
+	pic = Draw_CachePic ("gfx/pause.lmp");
+	Draw_Pic ( (vid.width - pic->width)/2, 
+		(vid.height - 48 - pic->height)/2, pic);
+}
+
+
+//=============================================================================
+
+
+/*
+==================
+SCR_SetUpToDrawConsole
+==================
+*/
+void SCR_SetUpToDrawConsole (void)
+{
+	Con_CheckResize ();
+	
+// decide on the height of the console
+	if (cls.state != ca_active)
+	{
+		scr_conlines = vid.height;		// full screen
+		scr_con_current = scr_conlines;
+	}
+	else if (key_dest == key_console)
+		scr_conlines = vid.height/2;	// half screen
+	else
+		scr_conlines = 0;				// none visible
+	
+	if (scr_conlines < scr_con_current)
+	{
+		scr_con_current -= scr_conspeed.value*host_frametime;
+		if (scr_conlines > scr_con_current)
+			scr_con_current = scr_conlines;
+
+	}
+	else if (scr_conlines > scr_con_current)
+	{
+		scr_con_current += scr_conspeed.value*host_frametime;
+		if (scr_conlines < scr_con_current)
+			scr_con_current = scr_conlines;
+	}
+
+	if (clearconsole++ < vid.numpages)
+	{
+		scr_copytop = 1;
+		Draw_TileClear (0,(int)scr_con_current,vid.width, vid.height - (int)scr_con_current);
+		Sbar_Changed ();
+	}
+	else if (clearnotify++ < vid.numpages)
+	{
+		scr_copytop = 1;
+		Draw_TileClear (0,0,vid.width, con_notifylines);
+	}
+	else
+		con_notifylines = 0;
+}
+	
+/*
+==================
+SCR_DrawConsole
+==================
+*/
+void SCR_DrawConsole (void)
+{
+	if (scr_con_current)
+	{
+		scr_copyeverything = 1;
+		Con_DrawConsole (scr_con_current);
+		clearconsole = 0;
+	}
+	else
+	{
+		if (key_dest == key_game || key_dest == key_message)
+			Con_DrawNotify ();	// only draw notify in game
+	}
+}
+
+
+/* 
+============================================================================== 
+ 
+						SCREEN SHOTS 
+ 
+============================================================================== 
+*/ 
+
+
+/* 
+============== 
+WritePCXfile 
+============== 
+*/ 
+void WritePCXfile (char *filename, byte *data, int width, int height,
+	int rowbytes, byte *palette, qboolean upload) 
+{
+	int		i, j, length;
+	pcx_t	*pcx;
+	byte		*pack;
+	  
+	pcx = Hunk_TempAlloc (width*height*2+1000);
+	if (pcx == NULL)
+	{
+		Con_Printf("SCR_ScreenShot_f: not enough memory\n");
+		return;
+	} 
+ 
+	pcx->manufacturer = 0x0a;	// PCX id
+	pcx->version = 5;			// 256 color
+ 	pcx->encoding = 1;		// uncompressed
+	pcx->bits_per_pixel = 8;		// 256 color
+	pcx->xmin = 0;
+	pcx->ymin = 0;
+	pcx->xmax = LittleShort((short)(width-1));
+	pcx->ymax = LittleShort((short)(height-1));
+	pcx->hres = LittleShort((short)width);
+	pcx->vres = LittleShort((short)height);
+	Q_memset (pcx->palette,0,sizeof(pcx->palette));
+	pcx->color_planes = 1;		// chunky image
+	pcx->bytes_per_line = LittleShort((short)width);
+	pcx->palette_type = LittleShort(2);		// not a grey scale
+	Q_memset (pcx->filler,0,sizeof(pcx->filler));
+
+// pack the image
+	pack = &pcx->data;
+	
+	for (i=0 ; i<height ; i++)
+	{
+		for (j=0 ; j<width ; j++)
+		{
+			if ( (*data & 0xc0) != 0xc0)
+				*pack++ = *data++;
+			else
+			{
+				*pack++ = 0xc1;
+				*pack++ = *data++;
+			}
+		}
+
+		data += rowbytes - width;
+	}
+			
+// write the palette
+	*pack++ = 0x0c;	// palette ID byte
+	for (i=0 ; i<768 ; i++)
+		*pack++ = *palette++;
+		
+// write output file 
+	length = pack - (byte *)pcx;
+	if (upload)
+		CL_StartUpload((void *)pcx, length);
+	else
+		COM_WriteFile (filename, pcx, length);
+} 
+ 
+
+
+/* 
+================== 
+SCR_ScreenShot_f
+================== 
+*/  
+void SCR_ScreenShot_f (void) 
+{ 
+	int     i; 
+	char		pcxname[80]; 
+	char		checkname[MAX_OSPATH];
+
+// 
+// find a file name to save it to 
+// 
+	strcpy(pcxname,"quake00.pcx");
+		
+	for (i=0 ; i<=99 ; i++) 
+	{ 
+		pcxname[5] = i/10 + '0'; 
+		pcxname[6] = i%10 + '0'; 
+		sprintf (checkname, "%s/%s", com_gamedir, pcxname);
+		if (Sys_FileTime(checkname) == -1)
+			break;	// file doesn't exist
+	} 
+	if (i==100) 
+	{
+		Con_Printf ("SCR_ScreenShot_f: Couldn't create a PCX"); 
+		return;
+	}
+ 
+// 
+// save the pcx file 
+// 
+	D_EnableBackBufferAccess ();	// enable direct drawing of console to back
+									//  buffer
+
+	WritePCXfile (pcxname, vid.buffer, vid.width, vid.height, vid.rowbytes,
+				  host_basepal, false);
+
+	D_DisableBackBufferAccess ();	// for adapters that can't stay mapped in
+									//  for linear writes all the time
+
+	Con_Printf ("Wrote %s\n", pcxname);
+} 
+
+/*
+Find closest color in the palette for named color
+*/
+int MipColor(int r, int g, int b)
+{
+	int i;
+	float dist;
+	int best;
+	float bestdist;
+	int r1, g1, b1;
+	static int lr = -1, lg = -1, lb = -1;
+	static int lastbest;
+
+	if (r == lr && g == lg && b == lb)
+		return lastbest;
+
+	bestdist = 256*256*3;
+
+	for (i = 0; i < 256; i++) {
+		r1 = host_basepal[i*3] - r;
+		g1 = host_basepal[i*3+1] - g;
+		b1 = host_basepal[i*3+2] - b;
+		dist = r1*r1 + g1*g1 + b1*b1;
+		if (dist < bestdist) {
+			bestdist = dist;
+			best = i;
+		}
+	}
+	lr = r; lg = g; lb = b;
+	lastbest = best;
+	return best;
+}
+
+// in draw.c
+extern byte		*draw_chars;				// 8*8 graphic characters
+
+void SCR_DrawCharToSnap (int num, byte *dest, int width)
+{
+	int		row, col;
+	byte	*source;
+	int		drawline;
+	int		x;
+
+	row = num>>4;
+	col = num&15;
+	source = draw_chars + (row<<10) + (col<<3);
+
+	drawline = 8;
+
+	while (drawline--)
+	{
+		for (x=0 ; x<8 ; x++)
+			if (source[x])
+				dest[x] = source[x];
+			else
+				dest[x] = 98;
+		source += 128;
+		dest += width;
+	}
+
+}
+
+void SCR_DrawStringToSnap (const char *s, byte *buf, int x, int y, int width)
+{
+	byte *dest;
+	const unsigned char *p;
+
+	dest = buf + ((y * width) + x);
+
+	p = (const unsigned char *)s;
+	while (*p) {
+		SCR_DrawCharToSnap(*p++, dest, width);
+		dest += 8;
+	}
+}
+
+
+/* 
+================== 
+SCR_RSShot_f
+================== 
+*/  
+void SCR_RSShot_f (void) 
+{ 
+	int     i, x, y;
+	unsigned char		*src, *dest;
+	char		pcxname[80]; 
+	char		checkname[MAX_OSPATH];
+	unsigned char		*newbuf, *srcbuf;
+	int srcrowbytes;
+	int w, h;
+	int dx, dy, dex, dey, nx;
+	int r, b, g;
+	int count;
+	float fracw, frach;
+	char st[80];
+	time_t now;
+
+	if (CL_IsUploading())
+		return; // already one pending
+
+	if (cls.state < ca_onserver)
+		return; // gotta be connected
+
+	if (!scr_allowsnap.value) {
+		MSG_WriteByte (&cls.netchan.message, clc_stringcmd);
+		SZ_Print (&cls.netchan.message, "snap\n");
+		Con_Printf("Refusing remote screen shot request.\n");
+		return;
+	}
+
+	Con_Printf("Remote screen shot requested.\n");
+
+#if 0
+// 
+// find a file name to save it to 
+// 
+	strcpy(pcxname,"mquake00.pcx");
+		
+	for (i=0 ; i<=99 ; i++) 
+	{ 
+		pcxname[6] = i/10 + '0'; 
+		pcxname[7] = i%10 + '0'; 
+		sprintf (checkname, "%s/%s", com_gamedir, pcxname);
+		if (Sys_FileTime(checkname) == -1)
+			break;	// file doesn't exist
+	} 
+	if (i==100) 
+	{
+		Con_Printf ("SCR_ScreenShot_f: Couldn't create a PCX"); 
+		return;
+	}
+#endif
+ 
+// 
+// save the pcx file 
+// 
+	D_EnableBackBufferAccess ();	// enable direct drawing of console to back
+									//  buffer
+
+	w = (vid.width < RSSHOT_WIDTH) ? vid.width : RSSHOT_WIDTH;
+	h = (vid.height < RSSHOT_HEIGHT) ? vid.height : RSSHOT_HEIGHT;
+
+	fracw = (float)vid.width / (float)w;
+	frach = (float)vid.height / (float)h;
+
+	newbuf = malloc(w*h);
+
+	for (y = 0; y < h; y++) {
+		dest = newbuf + (w * y);
+
+		for (x = 0; x < w; x++) {
+			r = g = b = 0;
+
+			dx = x * fracw;
+			dex = (x + 1) * fracw;
+			if (dex == dx) dex++; // at least one
+			dy = y * frach;
+			dey = (y + 1) * frach;
+			if (dey == dy) dey++; // at least one
+
+			count = 0;
+			for (/* */; dy < dey; dy++) {
+				src = vid.buffer + (vid.rowbytes * dy) + dx;
+				for (nx = dx; nx < dex; nx++) {
+					r += host_basepal[*src * 3];
+					g += host_basepal[*src * 3+1];
+					b += host_basepal[*src * 3+2];
+					src++;
+					count++;
+				}
+			}
+			r /= count;
+			g /= count;
+			b /= count;
+			*dest++ = MipColor(r, g, b);
+		}
+	}
+
+	time(&now);
+	strcpy(st, ctime(&now));
+	st[strlen(st) - 1] = 0;
+	SCR_DrawStringToSnap (st, newbuf, w - strlen(st)*8, 0, w);
+
+	strncpy(st, cls.servername, sizeof(st));
+	st[sizeof(st) - 1] = 0;
+	SCR_DrawStringToSnap (st, newbuf, w - strlen(st)*8, 10, w);
+
+	strncpy(st, name.string, sizeof(st));
+	st[sizeof(st) - 1] = 0;
+	SCR_DrawStringToSnap (st, newbuf, w - strlen(st)*8, 20, w);
+
+	WritePCXfile (pcxname, newbuf, w, h, w, host_basepal, true);
+
+	free(newbuf);
+
+	D_DisableBackBufferAccess ();	// for adapters that can't stay mapped in
+									//  for linear writes all the time
+
+//	Con_Printf ("Wrote %s\n", pcxname);
+	Con_Printf ("Sending shot to server...\n");
+} 
+
+
+//=============================================================================
+
+char	*scr_notifystring;
+qboolean	scr_drawdialog;
+
+void SCR_DrawNotifyString (void)
+{
+	char	*start;
+	int		l;
+	int		j;
+	int		x, y;
+
+	start = scr_notifystring;
+
+	y = vid.height*0.35;
+
+	do	
+	{
+	// scan the width of the line
+		for (l=0 ; l<40 ; l++)
+			if (start[l] == '\n' || !start[l])
+				break;
+		x = (vid.width - l*8)/2;
+		for (j=0 ; j<l ; j++, x+=8)
+			Draw_Character (x, y, start[j]);	
+			
+		y += 8;
+
+		while (*start && *start != '\n')
+			start++;
+
+		if (!*start)
+			break;
+		start++;		// skip the \n
+	} while (1);
+}
+
+/*
+==================
+SCR_ModalMessage
+
+Displays a text string in the center of the screen and waits for a Y or N
+keypress.  
+==================
+*/
+int SCR_ModalMessage (char *text)
+{
+	scr_notifystring = text;
+ 
+// draw a fresh screen
+	scr_fullupdate = 0;
+	scr_drawdialog = true;
+	SCR_UpdateScreen ();
+	scr_drawdialog = false;
+	
+	S_ClearBuffer ();		// so dma doesn't loop current sound
+
+	do
+	{
+		key_count = -1;		// wait for a key down and up
+		Sys_SendKeyEvents ();
+	} while (key_lastpress != 'y' && key_lastpress != 'n' && key_lastpress != K_ESCAPE);
+
+	scr_fullupdate = 0;
+	SCR_UpdateScreen ();
+
+	return key_lastpress == 'y';
+}
+
+
+//=============================================================================
+
+/*
+===============
+SCR_BringDownConsole
+
+Brings the console down and fades the palettes back to normal
+================
+*/
+void SCR_BringDownConsole (void)
+{
+	int		i;
+	
+	scr_centertime_off = 0;
+	
+	for (i=0 ; i<20 && scr_conlines != scr_con_current ; i++)
+		SCR_UpdateScreen ();
+
+	cl.cshifts[0].percent = 0;		// no area contents palette on next frame
+	VID_SetPalette (host_basepal);
+}
+
+
+/*
+==================
+SCR_UpdateScreen
+
+This is called every frame, and can also be called explicitly to flush
+text to the screen.
+
+WARNING: be very careful calling this from elsewhere, because the refresh
+needs almost the entire 256k of stack space!
+==================
+*/
+void SCR_UpdateScreen (void)
+{
+	static float	oldscr_viewsize;
+	vrect_t		vrect;
+
+	if (scr_skipupdate || block_drawing)
+		return;
+
+	if (scr_disabled_for_loading)
+		return;
+
+#ifdef _WIN32
+	{	// don't suck up any cpu if minimized
+		extern int Minimized;
+
+		if (Minimized)
+			return;
+	}
+#endif
+
+	scr_copytop = 0;
+	scr_copyeverything = 0;
+
+	if (!scr_initialized || !con_initialized)
+		return;				// not initialized yet
+
+	if (scr_viewsize.value != oldscr_viewsize)
+	{
+		oldscr_viewsize = scr_viewsize.value;
+		vid.recalc_refdef = 1;
+	}
+	
+//
+// check for vid changes
+//
+	if (oldfov != scr_fov.value)
+	{
+		oldfov = scr_fov.value;
+		vid.recalc_refdef = true;
+	}
+	
+	if (oldscreensize != scr_viewsize.value)
+	{
+		oldscreensize = scr_viewsize.value;
+		vid.recalc_refdef = true;
+	}
+
+	if (oldsbar != cl_sbar.value)
+	{
+		oldsbar = cl_sbar.value;
+		vid.recalc_refdef = true;
+	}
+	
+	if (vid.recalc_refdef)
+	{
+		// something changed, so reorder the screen
+		SCR_CalcRefdef ();
+	}
+
+//
+// do 3D refresh drawing, and then update the screen
+//
+	D_EnableBackBufferAccess ();	// of all overlay stuff if drawing directly
+
+	if (scr_fullupdate++ < vid.numpages)
+	{	// clear the entire screen
+		scr_copyeverything = 1;
+		Draw_TileClear (0,0,vid.width,vid.height);
+		Sbar_Changed ();
+	}
+
+	pconupdate = NULL;
+
+
+	SCR_SetUpToDrawConsole ();
+	SCR_EraseCenterString ();
+	
+	D_DisableBackBufferAccess ();	// for adapters that can't stay mapped in
+									//  for linear writes all the time
+
+	VID_LockBuffer ();
+	V_RenderView ();
+	VID_UnlockBuffer ();
+
+	D_EnableBackBufferAccess ();	// of all overlay stuff if drawing directly
+
+	if (scr_drawdialog)
+	{
+		Sbar_Draw ();
+		Draw_FadeScreen ();
+		SCR_DrawNotifyString ();
+		scr_copyeverything = true;
+	}
+	else if (cl.intermission == 1 && key_dest == key_game)
+	{
+		Sbar_IntermissionOverlay ();
+	}
+	else if (cl.intermission == 2 && key_dest == key_game)
+	{
+		Sbar_FinaleOverlay ();
+		SCR_CheckDrawCenterString ();
+	}
+	else
+	{
+		SCR_DrawRam ();
+		SCR_DrawNet ();
+		SCR_DrawTurtle ();
+		SCR_DrawPause ();
+		SCR_DrawFPS ();
+		SCR_CheckDrawCenterString ();
+		Sbar_Draw ();
+		SCR_DrawConsole ();	
+		M_Draw ();
+	}
+
+
+	D_DisableBackBufferAccess ();	// for adapters that can't stay mapped in
+									//  for linear writes all the time
+	if (pconupdate)
+	{
+		D_UpdateRects (pconupdate);
+	}
+
+	V_UpdatePalette ();
+
+//
+// update one of three areas
+//
+	if (scr_copyeverything)
+	{
+		vrect.x = 0;
+		vrect.y = 0;
+		vrect.width = vid.width;
+		vrect.height = vid.height;
+		vrect.pnext = 0;
+	
+		VID_Update (&vrect);
+	}
+	else if (scr_copytop)
+	{
+		vrect.x = 0;
+		vrect.y = 0;
+		vrect.width = vid.width;
+		vrect.height = vid.height - sb_lines;
+		vrect.pnext = 0;
+	
+		VID_Update (&vrect);
+	}	
+	else
+	{
+		vrect.x = scr_vrect.x;
+		vrect.y = scr_vrect.y;
+		vrect.width = scr_vrect.width;
+		vrect.height = scr_vrect.height;
+		vrect.pnext = 0;
+	
+		VID_Update (&vrect);
+	}	
+}
+
+/*
+==================
+SCR_UpdateWholeScreen
+==================
+*/
+void SCR_UpdateWholeScreen (void)
+{
+	scr_fullupdate = 0;
+	SCR_UpdateScreen ();
+}
--- /dev/null
+++ b/QW/client/screen.h
@@ -1,0 +1,53 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// screen.h
+
+void SCR_Init (void);
+
+void SCR_UpdateScreen (void);
+
+
+void SCR_SizeUp (void);
+void SCR_SizeDown (void);
+void SCR_BringDownConsole (void);
+void SCR_CenterPrint (char *str);
+
+int SCR_ModalMessage (char *text);
+
+extern	float		scr_con_current;
+extern	float		scr_conlines;		// lines of console to display
+
+extern	int			scr_fullupdate;	// set to 0 to force full redraw
+extern	int			sb_lines;
+
+extern	int			clearnotify;	// set to 0 whenever notify text is drawn
+extern	qboolean	scr_disabled_for_loading;
+
+extern	cvar_t		scr_viewsize;
+
+extern cvar_t scr_viewsize;
+
+// only the refresh window will be updated unless these variables are flagged 
+extern	int			scr_copytop;
+extern	int			scr_copyeverything;
+
+qboolean	scr_skipupdate;
+
+qboolean	block_drawing;
--- /dev/null
+++ b/QW/client/skin.c
@@ -1,0 +1,301 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+
+#include "quakedef.h"
+
+cvar_t		baseskin = {"baseskin", "base"};
+cvar_t		noskins = {"noskins", "0"};
+
+char		allskins[128];
+#define	MAX_CACHED_SKINS		128
+skin_t		skins[MAX_CACHED_SKINS];
+int			numskins;
+
+/*
+================
+Skin_Find
+
+  Determines the best skin for the given scoreboard
+  slot, and sets scoreboard->skin
+
+================
+*/
+void Skin_Find (player_info_t *sc)
+{
+	skin_t		*skin;
+	int			i;
+	char		name[128], *s;
+
+	if (allskins[0])
+		strcpy (name, allskins);
+	else
+	{
+		s = Info_ValueForKey (sc->userinfo, "skin");
+		if (s && s[0])
+			strcpy (name, s);
+		else
+			strcpy (name, baseskin.string);
+	}
+
+	if (strstr (name, "..") || *name == '.')
+		strcpy (name, "base");
+
+	COM_StripExtension (name, name);
+
+	for (i=0 ; i<numskins ; i++)
+	{
+		if (!strcmp (name, skins[i].name))
+		{
+			sc->skin = &skins[i];
+			Skin_Cache (sc->skin);
+			return;
+		}
+	}
+
+	if (numskins == MAX_CACHED_SKINS)
+	{	// ran out of spots, so flush everything
+		Skin_Skins_f ();
+		return;
+	}
+
+	skin = &skins[numskins];
+	sc->skin = skin;
+	numskins++;
+
+	memset (skin, 0, sizeof(*skin));
+	strncpy(skin->name, name, sizeof(skin->name) - 1);
+}
+
+
+/*
+==========
+Skin_Cache
+
+Returns a pointer to the skin bitmap, or NULL to use the default
+==========
+*/
+byte	*Skin_Cache (skin_t *skin)
+{
+	char	name[1024];
+	byte	*raw;
+	byte	*out, *pix;
+	pcx_t	*pcx;
+	int		x, y;
+	int		dataByte;
+	int		runLength;
+
+	if (cls.downloadtype == dl_skin)
+		return NULL;		// use base until downloaded
+
+	if (noskins.value==1) // JACK: So NOSKINS > 1 will show skins, but
+		return NULL;	  // not download new ones.
+
+	if (skin->failedload)
+		return NULL;
+
+	out = Cache_Check (&skin->cache);
+	if (out)
+		return out;
+
+//
+// load the pic from disk
+//
+	sprintf (name, "skins/%s.pcx", skin->name);
+	raw = COM_LoadTempFile (name);
+	if (!raw)
+	{
+		Con_Printf ("Couldn't load skin %s\n", name);
+		sprintf (name, "skins/%s.pcx", baseskin.string);
+		raw = COM_LoadTempFile (name);
+		if (!raw)
+		{
+			skin->failedload = true;
+			return NULL;
+		}
+	}
+
+//
+// parse the PCX file
+//
+	pcx = (pcx_t *)raw;
+	raw = &pcx->data;
+
+	if (pcx->manufacturer != 0x0a
+		|| pcx->version != 5
+		|| pcx->encoding != 1
+		|| pcx->bits_per_pixel != 8
+		|| pcx->xmax >= 320
+		|| pcx->ymax >= 200)
+	{
+		skin->failedload = true;
+		Con_Printf ("Bad skin %s\n", name);
+		return NULL;
+	}
+	
+	out = Cache_Alloc (&skin->cache, 320*200, skin->name);
+	if (!out)
+		Sys_Error ("Skin_Cache: couldn't allocate");
+
+	pix = out;
+	memset (out, 0, 320*200);
+
+	for (y=0 ; y<pcx->ymax ; y++, pix += 320)
+	{
+		for (x=0 ; x<=pcx->xmax ; )
+		{
+			if (raw - (byte*)pcx > com_filesize) 
+			{
+				Cache_Free (&skin->cache);
+				skin->failedload = true;
+				Con_Printf ("Skin %s was malformed.  You should delete it.\n", name);
+				return NULL;
+			}
+			dataByte = *raw++;
+
+			if((dataByte & 0xC0) == 0xC0)
+			{
+				runLength = dataByte & 0x3F;
+				if (raw - (byte*)pcx > com_filesize) 
+				{
+					Cache_Free (&skin->cache);
+					skin->failedload = true;
+					Con_Printf ("Skin %s was malformed.  You should delete it.\n", name);
+					return NULL;
+				}
+				dataByte = *raw++;
+			}
+			else
+				runLength = 1;
+
+			// skin sanity check
+			if (runLength + x > pcx->xmax + 2) {
+				Cache_Free (&skin->cache);
+				skin->failedload = true;
+				Con_Printf ("Skin %s was malformed.  You should delete it.\n", name);
+				return NULL;
+			}
+			while(runLength-- > 0)
+				pix[x++] = dataByte;
+		}
+
+	}
+
+	if ( raw - (byte *)pcx > com_filesize)
+	{
+		Cache_Free (&skin->cache);
+		skin->failedload = true;
+		Con_Printf ("Skin %s was malformed.  You should delete it.\n", name);
+		return NULL;
+	}
+
+	skin->failedload = false;
+
+	return out;
+}
+
+
+/*
+=================
+Skin_NextDownload
+=================
+*/
+void Skin_NextDownload (void)
+{
+	player_info_t	*sc;
+	int			i;
+
+	if (cls.downloadnumber == 0)
+		Con_Printf ("Checking skins...\n");
+	cls.downloadtype = dl_skin;
+
+	for ( 
+		; cls.downloadnumber != MAX_CLIENTS
+		; cls.downloadnumber++)
+	{
+		sc = &cl.players[cls.downloadnumber];
+		if (!sc->name[0])
+			continue;
+		Skin_Find (sc);
+		if (noskins.value)
+			continue;
+		if (!CL_CheckOrDownloadFile(va("skins/%s.pcx", sc->skin->name)))
+			return;		// started a download
+	}
+
+	cls.downloadtype = dl_none;
+
+	// now load them in for real
+	for (i=0 ; i<MAX_CLIENTS ; i++)
+	{
+		sc = &cl.players[i];
+		if (!sc->name[0])
+			continue;
+		Skin_Cache (sc->skin);
+#ifdef GLQUAKE
+		sc->skin = NULL;
+#endif
+	}
+
+	if (cls.state != ca_active)
+	{	// get next signon phase
+		MSG_WriteByte (&cls.netchan.message, clc_stringcmd);
+		MSG_WriteString (&cls.netchan.message,
+			va("begin %i", cl.servercount));
+		Cache_Report ();		// print remaining memory
+	}
+}
+
+
+/*
+==========
+Skin_Skins_f
+
+Refind all skins, downloading if needed.
+==========
+*/
+void	Skin_Skins_f (void)
+{
+	int		i;
+
+	for (i=0 ; i<numskins ; i++)
+	{
+		if (skins[i].cache.data)
+			Cache_Free (&skins[i].cache);
+	}
+	numskins = 0;
+
+	cls.downloadnumber = 0;
+	cls.downloadtype = dl_skin;
+	Skin_NextDownload ();
+}
+
+
+/*
+==========
+Skin_AllSkins_f
+
+Sets all skins to one specific one
+==========
+*/
+void	Skin_AllSkins_f (void)
+{
+	strcpy (allskins, Cmd_Argv(1));
+	Skin_Skins_f ();
+}
--- /dev/null
+++ b/QW/client/snd_dma.c
@@ -1,0 +1,1017 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// snd_dma.c -- main control for any streaming sound output device
+
+#include "quakedef.h"
+
+#ifdef _WIN32
+#include "winquake.h"
+#endif
+
+void S_Play(void);
+void S_PlayVol(void);
+void S_SoundList(void);
+void S_Update_();
+void S_StopAllSounds(qboolean clear);
+void S_StopAllSoundsC(void);
+
+// QuakeWorld hack...
+#define	viewentity	playernum+1
+
+// =======================================================================
+// Internal sound data & structures
+// =======================================================================
+
+channel_t   channels[MAX_CHANNELS];
+int			total_channels;
+
+int				snd_blocked = 0;
+static qboolean	snd_ambient = 1;
+qboolean		snd_initialized = false;
+
+// pointer should go away
+volatile dma_t  *shm = 0;
+volatile dma_t sn;
+
+vec3_t		listener_origin;
+vec3_t		listener_forward;
+vec3_t		listener_right;
+vec3_t		listener_up;
+vec_t		sound_nominal_clip_dist=1000.0;
+
+int			soundtime;		// sample PAIRS
+int   		paintedtime; 	// sample PAIRS
+
+
+#define	MAX_SFX		512
+sfx_t		*known_sfx;		// hunk allocated [MAX_SFX]
+int			num_sfx;
+
+sfx_t		*ambient_sfx[NUM_AMBIENTS];
+
+int 		desired_speed = 11025;
+int 		desired_bits = 16;
+
+int sound_started=0;
+
+cvar_t bgmvolume = {"bgmvolume", "1", true};
+cvar_t volume = {"volume", "0.7", true};
+
+cvar_t nosound = {"nosound", "0"};
+cvar_t precache = {"precache", "1"};
+cvar_t loadas8bit = {"loadas8bit", "0"};
+cvar_t bgmbuffer = {"bgmbuffer", "4096"};
+cvar_t ambient_level = {"ambient_level", "0.3"};
+cvar_t ambient_fade = {"ambient_fade", "100"};
+cvar_t snd_noextraupdate = {"snd_noextraupdate", "0"};
+cvar_t snd_show = {"snd_show", "0"};
+cvar_t _snd_mixahead = {"_snd_mixahead", "0.1", true};
+
+
+// ====================================================================
+// User-setable variables
+// ====================================================================
+
+
+//
+// Fake dma is a synchronous faking of the DMA progress used for
+// isolating performance in the renderer.  The fakedma_updates is
+// number of times S_Update() is called per second.
+//
+
+qboolean fakedma = false;
+int fakedma_updates = 15;
+
+
+void S_AmbientOff (void)
+{
+	snd_ambient = false;
+}
+
+
+void S_AmbientOn (void)
+{
+	snd_ambient = true;
+}
+
+
+void S_SoundInfo_f(void)
+{
+	if (!sound_started || !shm)
+	{
+		Con_Printf ("sound system not started\n");
+		return;
+	}
+	
+    Con_Printf("%5d stereo\n", shm->channels - 1);
+    Con_Printf("%5d samples\n", shm->samples);
+    Con_Printf("%5d samplepos\n", shm->samplepos);
+    Con_Printf("%5d samplebits\n", shm->samplebits);
+    Con_Printf("%5d submission_chunk\n", shm->submission_chunk);
+    Con_Printf("%5d speed\n", shm->speed);
+    Con_Printf("0x%x dma buffer\n", shm->buffer);
+	Con_Printf("%5d total_channels\n", total_channels);
+}
+
+
+/*
+================
+S_Startup
+================
+*/
+
+void S_Startup (void)
+{
+	int		rc;
+
+	if (!snd_initialized)
+		return;
+
+	if (!fakedma)
+	{
+		rc = SNDDMA_Init();
+
+		if (!rc)
+		{
+#ifndef	_WIN32
+			Con_Printf("S_Startup: SNDDMA_Init failed.\n");
+#endif
+			sound_started = 0;
+			return;
+		}
+	}
+
+	sound_started = 1;
+}
+
+
+/*
+================
+S_Init
+================
+*/
+void S_Init (void)
+{
+
+//	Con_Printf("\nSound Initialization\n");
+
+	if (COM_CheckParm("-nosound"))
+		return;
+
+	if (COM_CheckParm("-simsound"))
+		fakedma = true;
+
+	Cmd_AddCommand("play", S_Play);
+	Cmd_AddCommand("playvol", S_PlayVol);
+	Cmd_AddCommand("stopsound", S_StopAllSoundsC);
+	Cmd_AddCommand("soundlist", S_SoundList);
+	Cmd_AddCommand("soundinfo", S_SoundInfo_f);
+
+	Cvar_RegisterVariable(&nosound);
+	Cvar_RegisterVariable(&volume);
+	Cvar_RegisterVariable(&precache);
+	Cvar_RegisterVariable(&loadas8bit);
+	Cvar_RegisterVariable(&bgmvolume);
+	Cvar_RegisterVariable(&bgmbuffer);
+	Cvar_RegisterVariable(&ambient_level);
+	Cvar_RegisterVariable(&ambient_fade);
+	Cvar_RegisterVariable(&snd_noextraupdate);
+	Cvar_RegisterVariable(&snd_show);
+	Cvar_RegisterVariable(&_snd_mixahead);
+
+	if (host_parms.memsize < 0x800000)
+	{
+		Cvar_Set ("loadas8bit", "1");
+		Con_Printf ("loading all sounds as 8bit\n");
+	}
+
+
+
+	snd_initialized = true;
+
+	S_Startup ();
+
+	SND_InitScaletable ();
+
+	known_sfx = Hunk_AllocName (MAX_SFX*sizeof(sfx_t), "sfx_t");
+	num_sfx = 0;
+
+// create a piece of DMA memory
+
+	if (fakedma)
+	{
+		shm = (void *) Hunk_AllocName(sizeof(*shm), "shm");
+		shm->splitbuffer = 0;
+		shm->samplebits = 16;
+		shm->speed = 22050;
+		shm->channels = 2;
+		shm->samples = 32768;
+		shm->samplepos = 0;
+		shm->soundalive = true;
+		shm->gamealive = true;
+		shm->submission_chunk = 1;
+		shm->buffer = Hunk_AllocName(1<<16, "shmbuf");
+	}
+
+//	Con_Printf ("Sound sampling rate: %i\n", shm->speed);
+
+	// provides a tick sound until washed clean
+
+//	if (shm->buffer)
+//		shm->buffer[4] = shm->buffer[5] = 0x7f;	// force a pop for debugging
+
+	ambient_sfx[AMBIENT_WATER] = S_PrecacheSound ("ambience/water1.wav");
+	ambient_sfx[AMBIENT_SKY] = S_PrecacheSound ("ambience/wind2.wav");
+
+	S_StopAllSounds (true);
+}
+
+
+// =======================================================================
+// Shutdown sound engine
+// =======================================================================
+
+void S_Shutdown(void)
+{
+
+	if (!sound_started)
+		return;
+
+	if (shm)
+		shm->gamealive = 0;
+
+	shm = 0;
+	sound_started = 0;
+
+	if (!fakedma)
+	{
+		SNDDMA_Shutdown();
+	}
+}
+
+
+// =======================================================================
+// Load a sound
+// =======================================================================
+
+/*
+==================
+S_FindName
+
+==================
+*/
+sfx_t *S_FindName (char *name)
+{
+	int		i;
+	sfx_t	*sfx;
+
+	if (!name)
+		Sys_Error ("S_FindName: NULL\n");
+
+	if (Q_strlen(name) >= MAX_QPATH)
+		Sys_Error ("Sound name too long: %s", name);
+
+// see if already loaded
+	for (i=0 ; i < num_sfx ; i++)
+		if (!Q_strcmp(known_sfx[i].name, name))
+		{
+			return &known_sfx[i];
+		}
+
+	if (num_sfx == MAX_SFX)
+		Sys_Error ("S_FindName: out of sfx_t");
+	
+	sfx = &known_sfx[i];
+	strcpy (sfx->name, name);
+
+	num_sfx++;
+	
+	return sfx;
+}
+
+
+/*
+==================
+S_TouchSound
+
+==================
+*/
+void S_TouchSound (char *name)
+{
+	sfx_t	*sfx;
+	
+	if (!sound_started)
+		return;
+
+	sfx = S_FindName (name);
+	Cache_Check (&sfx->cache);
+}
+
+/*
+==================
+S_PrecacheSound
+
+==================
+*/
+sfx_t *S_PrecacheSound (char *name)
+{
+	sfx_t	*sfx;
+
+	if (!sound_started || nosound.value)
+		return NULL;
+
+	sfx = S_FindName (name);
+	
+// cache it in
+	if (precache.value)
+		S_LoadSound (sfx);
+	
+	return sfx;
+}
+
+
+//=============================================================================
+
+/*
+=================
+SND_PickChannel
+=================
+*/
+channel_t *SND_PickChannel(int entnum, int entchannel)
+{
+    int ch_idx;
+    int first_to_die;
+    int life_left;
+
+// Check for replacement sound, or find the best one to replace
+    first_to_die = -1;
+    life_left = 0x7fffffff;
+    for (ch_idx=NUM_AMBIENTS ; ch_idx < NUM_AMBIENTS + MAX_DYNAMIC_CHANNELS ; ch_idx++)
+    {
+		if (entchannel != 0		// channel 0 never overrides
+		&& channels[ch_idx].entnum == entnum
+		&& (channels[ch_idx].entchannel == entchannel || entchannel == -1) )
+		{	// allways override sound from same entity
+			first_to_die = ch_idx;
+			break;
+		}
+
+		// don't let monster sounds override player sounds
+		if (channels[ch_idx].entnum == cl.viewentity && entnum != cl.viewentity && channels[ch_idx].sfx)
+			continue;
+
+		if (channels[ch_idx].end - paintedtime < life_left)
+		{
+			life_left = channels[ch_idx].end - paintedtime;
+			first_to_die = ch_idx;
+		}
+   }
+
+	if (first_to_die == -1)
+		return NULL;
+
+	if (channels[first_to_die].sfx)
+		channels[first_to_die].sfx = NULL;
+
+    return &channels[first_to_die];    
+}       
+
+/*
+=================
+SND_Spatialize
+=================
+*/
+void SND_Spatialize(channel_t *ch)
+{
+    vec_t dot;
+    vec_t dist;
+    vec_t lscale, rscale, scale;
+    vec3_t source_vec;
+	sfx_t *snd;
+
+// anything coming from the view entity will allways be full volume
+	if (ch->entnum == cl.viewentity)
+	{
+		ch->leftvol = ch->master_vol;
+		ch->rightvol = ch->master_vol;
+		return;
+	}
+
+// calculate stereo seperation and distance attenuation
+
+	snd = ch->sfx;
+	VectorSubtract(ch->origin, listener_origin, source_vec);
+	
+	dist = VectorNormalize(source_vec) * ch->dist_mult;
+	
+	dot = DotProduct(listener_right, source_vec);
+
+	if (shm->channels == 1)
+	{
+		rscale = 1.0;
+		lscale = 1.0;
+	}
+	else
+	{
+		rscale = 1.0 + dot;
+		lscale = 1.0 - dot;
+	}
+
+// add in distance effect
+	scale = (1.0 - dist) * rscale;
+	ch->rightvol = (int) (ch->master_vol * scale);
+	if (ch->rightvol < 0)
+		ch->rightvol = 0;
+
+	scale = (1.0 - dist) * lscale;
+	ch->leftvol = (int) (ch->master_vol * scale);
+	if (ch->leftvol < 0)
+		ch->leftvol = 0;
+}           
+
+
+// =======================================================================
+// Start a sound effect
+// =======================================================================
+
+void S_StartSound(int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float fvol, float attenuation)
+{
+	channel_t *target_chan, *check;
+	sfxcache_t	*sc;
+	int		vol;
+	int		ch_idx;
+	int		skip;
+
+	if (!sound_started)
+		return;
+
+	if (!sfx)
+		return;
+
+	if (nosound.value)
+		return;
+
+	vol = fvol*255;
+
+// pick a channel to play on
+	target_chan = SND_PickChannel(entnum, entchannel);
+	if (!target_chan)
+		return;
+		
+// spatialize
+	memset (target_chan, 0, sizeof(*target_chan));
+	VectorCopy(origin, target_chan->origin);
+	target_chan->dist_mult = attenuation / sound_nominal_clip_dist;
+	target_chan->master_vol = vol;
+	target_chan->entnum = entnum;
+	target_chan->entchannel = entchannel;
+	SND_Spatialize(target_chan);
+
+	if (!target_chan->leftvol && !target_chan->rightvol)
+		return;		// not audible at all
+
+// new channel
+	sc = S_LoadSound (sfx);
+	if (!sc)
+	{
+		target_chan->sfx = NULL;
+		return;		// couldn't load the sound's data
+	}
+
+	target_chan->sfx = sfx;
+	target_chan->pos = 0.0;
+    target_chan->end = paintedtime + sc->length;	
+
+// if an identical sound has also been started this frame, offset the pos
+// a bit to keep it from just making the first one louder
+	check = &channels[NUM_AMBIENTS];
+    for (ch_idx=NUM_AMBIENTS ; ch_idx < NUM_AMBIENTS + MAX_DYNAMIC_CHANNELS ; ch_idx++, check++)
+    {
+		if (check == target_chan)
+			continue;
+		if (check->sfx == sfx && !check->pos)
+		{
+			skip = rand () % (int)(0.1*shm->speed);
+			if (skip >= target_chan->end)
+				skip = target_chan->end - 1;
+			target_chan->pos += skip;
+			target_chan->end -= skip;
+			break;
+		}
+		
+	}
+}
+
+void S_StopSound(int entnum, int entchannel)
+{
+	int i;
+
+	for (i=0 ; i<MAX_DYNAMIC_CHANNELS ; i++)
+	{
+		if (channels[i].entnum == entnum
+			&& channels[i].entchannel == entchannel)
+		{
+			channels[i].end = 0;
+			channels[i].sfx = NULL;
+			return;
+		}
+	}
+}
+
+void S_StopAllSounds(qboolean clear)
+{
+	int		i;
+
+	if (!sound_started)
+		return;
+
+	total_channels = MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS;	// no statics
+
+	for (i=0 ; i<MAX_CHANNELS ; i++)
+		if (channels[i].sfx)
+			channels[i].sfx = NULL;
+
+	Q_memset(channels, 0, MAX_CHANNELS * sizeof(channel_t));
+
+	if (clear)
+		S_ClearBuffer ();
+}
+
+void S_StopAllSoundsC (void)
+{
+	S_StopAllSounds (true);
+}
+
+void S_ClearBuffer (void)
+{
+	int		clear;
+		
+#ifdef _WIN32
+	if (!sound_started || !shm || (!shm->buffer && !pDSBuf))
+#else
+	if (!sound_started || !shm || !shm->buffer)
+#endif
+		return;
+
+	if (shm->samplebits == 8)
+		clear = 0x80;
+	else
+		clear = 0;
+
+#ifdef _WIN32
+	if (pDSBuf)
+	{
+		DWORD	dwSize;
+		DWORD	*pData;
+		int		reps;
+		HRESULT	hresult;
+
+		reps = 0;
+
+		while ((hresult = pDSBuf->lpVtbl->Lock(pDSBuf, 0, gSndBufSize, &pData, &dwSize, NULL, NULL, 0)) != DS_OK)
+		{
+			if (hresult != DSERR_BUFFERLOST)
+			{
+				Con_Printf ("S_ClearBuffer: DS::Lock Sound Buffer Failed\n");
+				S_Shutdown ();
+				return;
+			}
+
+			if (++reps > 10000)
+			{
+				Con_Printf ("S_ClearBuffer: DS: couldn't restore buffer\n");
+				S_Shutdown ();
+				return;
+			}
+		}
+
+		Q_memset(pData, clear, shm->samples * shm->samplebits/8);
+
+		pDSBuf->lpVtbl->Unlock(pDSBuf, pData, dwSize, NULL, 0);
+	
+	}
+	else
+#endif
+	{
+		Q_memset(shm->buffer, clear, shm->samples * shm->samplebits/8);
+	}
+}
+
+
+/*
+=================
+S_StaticSound
+=================
+*/
+void S_StaticSound (sfx_t *sfx, vec3_t origin, float vol, float attenuation)
+{
+	channel_t	*ss;
+	sfxcache_t		*sc;
+
+	if (!sfx)
+		return;
+
+	if (total_channels == MAX_CHANNELS)
+	{
+		Con_Printf ("total_channels == MAX_CHANNELS\n");
+		return;
+	}
+
+	ss = &channels[total_channels];
+	total_channels++;
+
+	sc = S_LoadSound (sfx);
+	if (!sc)
+		return;
+
+	if (sc->loopstart == -1)
+	{
+		Con_Printf ("Sound %s not looped\n", sfx->name);
+		return;
+	}
+	
+	ss->sfx = sfx;
+	VectorCopy (origin, ss->origin);
+	ss->master_vol = vol;
+	ss->dist_mult = (attenuation/64) / sound_nominal_clip_dist;
+    ss->end = paintedtime + sc->length;	
+	
+	SND_Spatialize (ss);
+}
+
+
+//=============================================================================
+
+/*
+===================
+S_UpdateAmbientSounds
+===================
+*/
+void S_UpdateAmbientSounds (void)
+{
+	mleaf_t		*l;
+	float		vol;
+	int			ambient_channel;
+	channel_t	*chan;
+
+	if (!snd_ambient)
+		return;
+
+// calc ambient sound levels
+	if (!cl.worldmodel)
+		return;
+
+	l = Mod_PointInLeaf (listener_origin, cl.worldmodel);
+	if (!l || !ambient_level.value)
+	{
+		for (ambient_channel = 0 ; ambient_channel< NUM_AMBIENTS ; ambient_channel++)
+			channels[ambient_channel].sfx = NULL;
+		return;
+	}
+
+	for (ambient_channel = 0 ; ambient_channel< NUM_AMBIENTS ; ambient_channel++)
+	{
+		chan = &channels[ambient_channel];	
+		chan->sfx = ambient_sfx[ambient_channel];
+	
+		vol = ambient_level.value * l->ambient_sound_level[ambient_channel];
+		if (vol < 8)
+			vol = 0;
+
+	// don't adjust volume too fast
+		if (chan->master_vol < vol)
+		{
+			chan->master_vol += host_frametime * ambient_fade.value;
+			if (chan->master_vol > vol)
+				chan->master_vol = vol;
+		}
+		else if (chan->master_vol > vol)
+		{
+			chan->master_vol -= host_frametime * ambient_fade.value;
+			if (chan->master_vol < vol)
+				chan->master_vol = vol;
+		}
+		
+		chan->leftvol = chan->rightvol = chan->master_vol;
+	}
+}
+
+
+/*
+============
+S_Update
+
+Called once each time through the main loop
+============
+*/
+void S_Update(vec3_t origin, vec3_t forward, vec3_t right, vec3_t up)
+{
+	int			i, j;
+	int			total;
+	channel_t	*ch;
+	channel_t	*combine;
+
+	if (!sound_started || (snd_blocked > 0))
+		return;
+
+	VectorCopy(origin, listener_origin);
+	VectorCopy(forward, listener_forward);
+	VectorCopy(right, listener_right);
+	VectorCopy(up, listener_up);
+	
+// update general area ambient sound sources
+	S_UpdateAmbientSounds ();
+
+	combine = NULL;
+
+// update spatialization for static and dynamic sounds	
+	ch = channels+NUM_AMBIENTS;
+	for (i=NUM_AMBIENTS ; i<total_channels; i++, ch++)
+	{
+		if (!ch->sfx)
+			continue;
+		SND_Spatialize(ch);         // respatialize channel
+		if (!ch->leftvol && !ch->rightvol)
+			continue;
+
+	// try to combine static sounds with a previous channel of the same
+	// sound effect so we don't mix five torches every frame
+	
+		if (i >= MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS)
+		{
+		// see if it can just use the last one
+			if (combine && combine->sfx == ch->sfx)
+			{
+				combine->leftvol += ch->leftvol;
+				combine->rightvol += ch->rightvol;
+				ch->leftvol = ch->rightvol = 0;
+				continue;
+			}
+		// search for one
+			combine = channels+MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS;
+			for (j=MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS ; j<i; j++, combine++)
+				if (combine->sfx == ch->sfx)
+					break;
+					
+			if (j == total_channels)
+			{
+				combine = NULL;
+			}
+			else
+			{
+				if (combine != ch)
+				{
+					combine->leftvol += ch->leftvol;
+					combine->rightvol += ch->rightvol;
+					ch->leftvol = ch->rightvol = 0;
+				}
+				continue;
+			}
+		}
+		
+		
+	}
+
+//
+// debugging output
+//
+	if (snd_show.value)
+	{
+		total = 0;
+		ch = channels;
+		for (i=0 ; i<total_channels; i++, ch++)
+			if (ch->sfx && (ch->leftvol || ch->rightvol) )
+			{
+				//Con_Printf ("%3i %3i %s\n", ch->leftvol, ch->rightvol, ch->sfx->name);
+				total++;
+			}
+		
+		Con_Printf ("----(%i)----\n", total);
+	}
+
+// mix some sound
+	S_Update_();
+}
+
+void GetSoundtime(void)
+{
+	int		samplepos;
+	static	int		buffers;
+	static	int		oldsamplepos;
+	int		fullsamples;
+	
+	fullsamples = shm->samples / shm->channels;
+
+// it is possible to miscount buffers if it has wrapped twice between
+// calls to S_Update.  Oh well.
+	samplepos = SNDDMA_GetDMAPos();
+
+	if (samplepos < oldsamplepos)
+	{
+		buffers++;					// buffer wrapped
+		
+		if (paintedtime > 0x40000000)
+		{	// time to chop things off to avoid 32 bit limits
+			buffers = 0;
+			paintedtime = fullsamples;
+			S_StopAllSounds (true);
+		}
+	}
+	oldsamplepos = samplepos;
+
+	soundtime = buffers*fullsamples + samplepos/shm->channels;
+}
+
+void S_ExtraUpdate (void)
+{
+
+#ifdef _WIN32
+	IN_Accumulate ();
+#endif
+
+	if (snd_noextraupdate.value)
+		return;		// don't pollute timings
+	S_Update_();
+}
+
+
+
+void S_Update_(void)
+{
+	unsigned        endtime;
+	int				samps;
+	
+	if (!sound_started || (snd_blocked > 0))
+		return;
+
+// Updates DMA time
+	GetSoundtime();
+
+// check to make sure that we haven't overshot
+	if (paintedtime < soundtime)
+	{
+		//Con_Printf ("S_Update_ : overflow\n");
+		paintedtime = soundtime;
+	}
+
+// mix ahead of current position
+	endtime = soundtime + _snd_mixahead.value * shm->speed;
+	samps = shm->samples >> (shm->channels-1);
+	if (endtime - soundtime > samps)
+		endtime = soundtime + samps;
+
+#ifdef _WIN32
+// if the buffer was lost or stopped, restore it and/or restart it
+	{
+		DWORD	dwStatus;
+
+		if (pDSBuf)
+		{
+			if (pDSBuf->lpVtbl->GetStatus (pDSBuf, &dwStatus) != DD_OK)
+				Con_Printf ("Couldn't get sound buffer status\n");
+			
+			if (dwStatus & DSBSTATUS_BUFFERLOST)
+				pDSBuf->lpVtbl->Restore (pDSBuf);
+			
+			if (!(dwStatus & DSBSTATUS_PLAYING))
+				pDSBuf->lpVtbl->Play(pDSBuf, 0, 0, DSBPLAY_LOOPING);
+		}
+	}
+#endif
+
+	S_PaintChannels (endtime);
+
+	SNDDMA_Submit ();
+}
+
+/*
+===============================================================================
+
+console functions
+
+===============================================================================
+*/
+
+void S_Play(void)
+{
+	static int hash=345;
+	int 	i;
+	char name[256];
+	sfx_t	*sfx;
+	
+	i = 1;
+	while (i<Cmd_Argc())
+	{
+		if (!Q_strrchr(Cmd_Argv(i), '.'))
+		{
+			Q_strcpy(name, Cmd_Argv(i));
+			Q_strcat(name, ".wav");
+		}
+		else
+			Q_strcpy(name, Cmd_Argv(i));
+		sfx = S_PrecacheSound(name);
+		S_StartSound(hash++, 0, sfx, listener_origin, 1.0, 1.0);
+		i++;
+	}
+}
+
+void S_PlayVol(void)
+{
+	static int hash=543;
+	int i;
+	float vol;
+	char name[256];
+	sfx_t	*sfx;
+	
+	i = 1;
+	while (i<Cmd_Argc())
+	{
+		if (!Q_strrchr(Cmd_Argv(i), '.'))
+		{
+			Q_strcpy(name, Cmd_Argv(i));
+			Q_strcat(name, ".wav");
+		}
+		else
+			Q_strcpy(name, Cmd_Argv(i));
+		sfx = S_PrecacheSound(name);
+		vol = Q_atof(Cmd_Argv(i+1));
+		S_StartSound(hash++, 0, sfx, listener_origin, vol, 1.0);
+		i+=2;
+	}
+}
+
+void S_SoundList(void)
+{
+	int		i;
+	sfx_t	*sfx;
+	sfxcache_t	*sc;
+	int		size, total;
+
+	total = 0;
+	for (sfx=known_sfx, i=0 ; i<num_sfx ; i++, sfx++)
+	{
+		sc = Cache_Check (&sfx->cache);
+		if (!sc)
+			continue;
+		size = sc->length*sc->width*(sc->stereo+1);
+		total += size;
+		if (sc->loopstart >= 0)
+			Con_Printf ("L");
+		else
+			Con_Printf (" ");
+		Con_Printf("(%2db) %6i : %s\n",sc->width*8,  size, sfx->name);
+	}
+	Con_Printf ("Total resident: %i\n", total);
+}
+
+
+void S_LocalSound (char *sound)
+{
+	sfx_t	*sfx;
+
+	if (nosound.value)
+		return;
+	if (!sound_started)
+		return;
+		
+	sfx = S_PrecacheSound (sound);
+	if (!sfx)
+	{
+		Con_Printf ("S_LocalSound: can't cache %s\n", sound);
+		return;
+	}
+	S_StartSound (cl.viewentity, -1, sfx, vec3_origin, 1, 1);
+}
+
+
+void S_ClearPrecache (void)
+{
+}
+
+
+void S_BeginPrecaching (void)
+{
+}
+
+
+void S_EndPrecaching (void)
+{
+}
+
--- /dev/null
+++ b/QW/client/snd_linux.c
@@ -1,0 +1,250 @@
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/shm.h>
+#include <sys/wait.h>
+#include <linux/soundcard.h>
+#include <stdio.h>
+#include "quakedef.h"
+
+int audio_fd;
+int snd_inited;
+
+static int tryrates[] = { 11025, 22051, 44100, 8000 };
+
+qboolean SNDDMA_Init(void)
+{
+
+	int rc;
+    int fmt;
+	int tmp;
+    int i;
+    char *s;
+	struct audio_buf_info info;
+	int caps;
+
+	snd_inited = 0;
+
+// open /dev/dsp, confirm capability to mmap, and get size of dma buffer
+
+    audio_fd = open("/dev/dsp", O_RDWR);
+    if (audio_fd < 0)
+	{
+		perror("/dev/dsp");
+        Con_Printf("Could not open /dev/dsp\n");
+		return 0;
+	}
+
+    rc = ioctl(audio_fd, SNDCTL_DSP_RESET, 0);
+    if (rc < 0)
+	{
+		perror("/dev/dsp");
+		Con_Printf("Could not reset /dev/dsp\n");
+		close(audio_fd);
+		return 0;
+	}
+
+	if (ioctl(audio_fd, SNDCTL_DSP_GETCAPS, &caps)==-1)
+	{
+		perror("/dev/dsp");
+        Con_Printf("Sound driver too old\n");
+		close(audio_fd);
+		return 0;
+	}
+
+	if (!(caps & DSP_CAP_TRIGGER) || !(caps & DSP_CAP_MMAP))
+	{
+		Con_Printf("Sorry but your soundcard can't do this\n");
+		close(audio_fd);
+		return 0;
+	}
+
+    if (ioctl(audio_fd, SNDCTL_DSP_GETOSPACE, &info)==-1)
+    {   
+        perror("GETOSPACE");
+		Con_Printf("Um, can't do GETOSPACE?\n");
+		close(audio_fd);
+		return 0;
+    }
+    
+	shm = &sn;
+    shm->splitbuffer = 0;
+
+// set sample bits & speed
+
+    s = getenv("QUAKE_SOUND_SAMPLEBITS");
+    if (s) shm->samplebits = atoi(s);
+	else if ((i = COM_CheckParm("-sndbits")) != 0)
+		shm->samplebits = atoi(com_argv[i+1]);
+	if (shm->samplebits != 16 && shm->samplebits != 8)
+    {
+        ioctl(audio_fd, SNDCTL_DSP_GETFMTS, &fmt);
+        if (fmt & AFMT_S16_LE) shm->samplebits = 16;
+        else if (fmt & AFMT_U8) shm->samplebits = 8;
+    }
+
+    s = getenv("QUAKE_SOUND_SPEED");
+    if (s) shm->speed = atoi(s);
+	else if ((i = COM_CheckParm("-sndspeed")) != 0)
+		shm->speed = atoi(com_argv[i+1]);
+    else
+    {
+        for (i=0 ; i<sizeof(tryrates)/4 ; i++)
+            if (!ioctl(audio_fd, SNDCTL_DSP_SPEED, &tryrates[i])) break;
+        shm->speed = tryrates[i];
+    }
+
+    s = getenv("QUAKE_SOUND_CHANNELS");
+    if (s) shm->channels = atoi(s);
+	else if ((i = COM_CheckParm("-sndmono")) != 0)
+		shm->channels = 1;
+	else if ((i = COM_CheckParm("-sndstereo")) != 0)
+		shm->channels = 2;
+    else shm->channels = 2;
+
+	shm->samples = info.fragstotal * info.fragsize / (shm->samplebits/8);
+	shm->submission_chunk = 1;
+
+// memory map the dma buffer
+
+	shm->buffer = (unsigned char *) mmap(NULL, info.fragstotal
+		* info.fragsize, PROT_WRITE, MAP_FILE|MAP_SHARED, audio_fd, 0);
+	if (!shm->buffer)
+	{
+		perror("/dev/dsp");
+		Con_Printf("Could not mmap /dev/dsp\n");
+		close(audio_fd);
+		return 0;
+	}
+
+	tmp = 0;
+	if (shm->channels == 2)
+		tmp = 1;
+    rc = ioctl(audio_fd, SNDCTL_DSP_STEREO, &tmp);
+    if (rc < 0)
+    {
+		perror("/dev/dsp");
+        Con_Printf("Could not set /dev/dsp to stereo=%d", shm->channels);
+		close(audio_fd);
+        return 0;
+    }
+	if (tmp)
+		shm->channels = 2;
+	else
+		shm->channels = 1;
+
+    rc = ioctl(audio_fd, SNDCTL_DSP_SPEED, &shm->speed);
+    if (rc < 0)
+    {
+		perror("/dev/dsp");
+        Con_Printf("Could not set /dev/dsp speed to %d", shm->speed);
+		close(audio_fd);
+        return 0;
+    }
+
+    if (shm->samplebits == 16)
+    {
+        rc = AFMT_S16_LE;
+        rc = ioctl(audio_fd, SNDCTL_DSP_SETFMT, &rc);
+        if (rc < 0)
+		{
+			perror("/dev/dsp");
+			Con_Printf("Could not support 16-bit data.  Try 8-bit.\n");
+			close(audio_fd);
+			return 0;
+		}
+    }
+    else if (shm->samplebits == 8)
+    {
+        rc = AFMT_U8;
+        rc = ioctl(audio_fd, SNDCTL_DSP_SETFMT, &rc);
+        if (rc < 0)
+		{
+			perror("/dev/dsp");
+			Con_Printf("Could not support 8-bit data.\n");
+			close(audio_fd);
+			return 0;
+		}
+    }
+	else
+	{
+		perror("/dev/dsp");
+		Con_Printf("%d-bit sound not supported.", shm->samplebits);
+		close(audio_fd);
+		return 0;
+	}
+
+// toggle the trigger & start her up
+
+    tmp = 0;
+    rc  = ioctl(audio_fd, SNDCTL_DSP_SETTRIGGER, &tmp);
+	if (rc < 0)
+	{
+		perror("/dev/dsp");
+		Con_Printf("Could not toggle.\n");
+		close(audio_fd);
+		return 0;
+	}
+    tmp = PCM_ENABLE_OUTPUT;
+    rc = ioctl(audio_fd, SNDCTL_DSP_SETTRIGGER, &tmp);
+	if (rc < 0)
+	{
+		perror("/dev/dsp");
+		Con_Printf("Could not toggle.\n");
+		close(audio_fd);
+		return 0;
+	}
+
+	shm->samplepos = 0;
+
+	snd_inited = 1;
+	return 1;
+
+}
+
+int SNDDMA_GetDMAPos(void)
+{
+
+	struct count_info count;
+
+	if (!snd_inited) return 0;
+
+	if (ioctl(audio_fd, SNDCTL_DSP_GETOPTR, &count)==-1)
+	{
+		perror("/dev/dsp");
+		Con_Printf("Uh, sound dead.\n");
+		close(audio_fd);
+		snd_inited = 0;
+		return 0;
+	}
+//	shm->samplepos = (count.bytes / (shm->samplebits / 8)) & (shm->samples-1);
+//	fprintf(stderr, "%d    \r", count.ptr);
+	shm->samplepos = count.ptr / (shm->samplebits / 8);
+
+	return shm->samplepos;
+
+}
+
+void SNDDMA_Shutdown(void)
+{
+	if (snd_inited)
+	{
+		close(audio_fd);
+		snd_inited = 0;
+	}
+}
+
+/*
+==============
+SNDDMA_Submit
+
+Send sound to device if buffer isn't really the dma buffer
+===============
+*/
+void SNDDMA_Submit(void)
+{
+}
+
--- /dev/null
+++ b/QW/client/snd_mem.c
@@ -1,0 +1,343 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// snd_mem.c: sound caching
+
+#include "quakedef.h"
+
+int			cache_full_cycle;
+
+byte *S_Alloc (int size);
+
+/*
+================
+ResampleSfx
+================
+*/
+void ResampleSfx (sfx_t *sfx, int inrate, int inwidth, byte *data)
+{
+	int		outcount;
+	int		srcsample;
+	float	stepscale;
+	int		i;
+	int		sample, samplefrac, fracstep;
+	sfxcache_t	*sc;
+	
+	sc = Cache_Check (&sfx->cache);
+	if (!sc)
+		return;
+
+	stepscale = (float)inrate / shm->speed;	// this is usually 0.5, 1, or 2
+
+	outcount = sc->length / stepscale;
+	sc->length = outcount;
+	if (sc->loopstart != -1)
+		sc->loopstart = sc->loopstart / stepscale;
+
+	sc->speed = shm->speed;
+	if (loadas8bit.value)
+		sc->width = 1;
+	else
+		sc->width = inwidth;
+	sc->stereo = 0;
+
+// resample / decimate to the current source rate
+
+	if (stepscale == 1 && inwidth == 1 && sc->width == 1)
+	{
+// fast special case
+		for (i=0 ; i<outcount ; i++)
+			((signed char *)sc->data)[i]
+			= (int)( (unsigned char)(data[i]) - 128);
+	}
+	else
+	{
+// general case
+		samplefrac = 0;
+		fracstep = stepscale*256;
+		for (i=0 ; i<outcount ; i++)
+		{
+			srcsample = samplefrac >> 8;
+			samplefrac += fracstep;
+			if (inwidth == 2)
+				sample = LittleShort ( ((short *)data)[srcsample] );
+			else
+				sample = (int)( (unsigned char)(data[srcsample]) - 128) << 8;
+			if (sc->width == 2)
+				((short *)sc->data)[i] = sample;
+			else
+				((signed char *)sc->data)[i] = sample >> 8;
+		}
+	}
+}
+
+//=============================================================================
+
+/*
+==============
+S_LoadSound
+==============
+*/
+sfxcache_t *S_LoadSound (sfx_t *s)
+{
+    char	namebuffer[256];
+	byte	*data;
+	wavinfo_t	info;
+	int		len;
+	float	stepscale;
+	sfxcache_t	*sc;
+	byte	stackbuf[1*1024];		// avoid dirtying the cache heap
+
+// see if still in memory
+	sc = Cache_Check (&s->cache);
+	if (sc)
+		return sc;
+
+//Con_Printf ("S_LoadSound: %x\n", (int)stackbuf);
+// load it in
+    Q_strcpy(namebuffer, "sound/");
+    Q_strcat(namebuffer, s->name);
+
+//	Con_Printf ("loading %s\n",namebuffer);
+
+	data = COM_LoadStackFile(namebuffer, stackbuf, sizeof(stackbuf));
+
+	if (!data)
+	{
+		Con_Printf ("Couldn't load %s\n", namebuffer);
+		return NULL;
+	}
+
+	info = GetWavinfo (s->name, data, com_filesize);
+	if (info.channels != 1)
+	{
+		Con_Printf ("%s is a stereo sample\n",s->name);
+		return NULL;
+	}
+
+	stepscale = (float)info.rate / shm->speed;	
+	len = info.samples / stepscale;
+
+	len = len * info.width * info.channels;
+
+	sc = Cache_Alloc ( &s->cache, len + sizeof(sfxcache_t), s->name);
+	if (!sc)
+		return NULL;
+	
+	sc->length = info.samples;
+	sc->loopstart = info.loopstart;
+	sc->speed = info.rate;
+	sc->width = info.width;
+	sc->stereo = info.channels;
+
+	ResampleSfx (s, sc->speed, sc->width, data + info.dataofs);
+
+	return sc;
+}
+
+
+
+/*
+===============================================================================
+
+WAV loading
+
+===============================================================================
+*/
+
+
+byte	*data_p;
+byte 	*iff_end;
+byte 	*last_chunk;
+byte 	*iff_data;
+int 	iff_chunk_len;
+
+
+short GetLittleShort(void)
+{
+	short val = 0;
+	val = *data_p;
+	val = val + (*(data_p+1)<<8);
+	data_p += 2;
+	return val;
+}
+
+int GetLittleLong(void)
+{
+	int val = 0;
+	val = *data_p;
+	val = val + (*(data_p+1)<<8);
+	val = val + (*(data_p+2)<<16);
+	val = val + (*(data_p+3)<<24);
+	data_p += 4;
+	return val;
+}
+
+void FindNextChunk(char *name)
+{
+	while (1)
+	{
+		data_p=last_chunk;
+
+		if (data_p >= iff_end)
+		{	// didn't find the chunk
+			data_p = NULL;
+			return;
+		}
+		
+		data_p += 4;
+		iff_chunk_len = GetLittleLong();
+		if (iff_chunk_len < 0)
+		{
+			data_p = NULL;
+			return;
+		}
+//		if (iff_chunk_len > 1024*1024)
+//			Sys_Error ("FindNextChunk: %i length is past the 1 meg sanity limit", iff_chunk_len);
+		data_p -= 8;
+		last_chunk = data_p + 8 + ( (iff_chunk_len + 1) & ~1 );
+		if (!Q_strncmp(data_p, name, 4))
+			return;
+	}
+}
+
+void FindChunk(char *name)
+{
+	last_chunk = iff_data;
+	FindNextChunk (name);
+}
+
+
+#if 0
+void DumpChunks(void)
+{
+	char	str[5];
+	
+	str[4] = 0;
+	data_p=iff_data;
+	do
+	{
+		memcpy (str, data_p, 4);
+		data_p += 4;
+		iff_chunk_len = GetLittleLong();
+		Con_Printf ("0x%x : %s (%d)\n", (int)(data_p - 4), str, iff_chunk_len);
+		data_p += (iff_chunk_len + 1) & ~1;
+	} while (data_p < iff_end);
+}
+#endif
+
+/*
+============
+GetWavinfo
+============
+*/
+wavinfo_t GetWavinfo (char *name, byte *wav, int wavlength)
+{
+	wavinfo_t	info;
+	int     i;
+	int     format;
+	int		samples;
+
+	memset (&info, 0, sizeof(info));
+
+	if (!wav)
+		return info;
+		
+	iff_data = wav;
+	iff_end = wav + wavlength;
+
+// find "RIFF" chunk
+	FindChunk("RIFF");
+	if (!(data_p && !Q_strncmp(data_p+8, "WAVE", 4)))
+	{
+		Con_Printf("Missing RIFF/WAVE chunks\n");
+		return info;
+	}
+
+// get "fmt " chunk
+	iff_data = data_p + 12;
+// DumpChunks ();
+
+	FindChunk("fmt ");
+	if (!data_p)
+	{
+		Con_Printf("Missing fmt chunk\n");
+		return info;
+	}
+	data_p += 8;
+	format = GetLittleShort();
+	if (format != 1)
+	{
+		Con_Printf("Microsoft PCM format only\n");
+		return info;
+	}
+
+	info.channels = GetLittleShort();
+	info.rate = GetLittleLong();
+	data_p += 4+2;
+	info.width = GetLittleShort() / 8;
+
+// get cue chunk
+	FindChunk("cue ");
+	if (data_p)
+	{
+		data_p += 32;
+		info.loopstart = GetLittleLong();
+//		Con_Printf("loopstart=%d\n", sfx->loopstart);
+
+	// if the next chunk is a LIST chunk, look for a cue length marker
+		FindNextChunk ("LIST");
+		if (data_p)
+		{
+			if (!strncmp (data_p + 28, "mark", 4))
+			{	// this is not a proper parse, but it works with cooledit...
+				data_p += 24;
+				i = GetLittleLong ();	// samples in loop
+				info.samples = info.loopstart + i;
+//				Con_Printf("looped length: %i\n", i);
+			}
+		}
+	}
+	else
+		info.loopstart = -1;
+
+// find data chunk
+	FindChunk("data");
+	if (!data_p)
+	{
+		Con_Printf("Missing data chunk\n");
+		return info;
+	}
+
+	data_p += 4;
+	samples = GetLittleLong () / info.width;
+
+	if (info.samples)
+	{
+		if (samples < info.samples)
+			Sys_Error ("Sound %s has a bad loop length", name);
+	}
+	else
+		info.samples = samples;
+
+	info.dataofs = data_p - wav;
+	
+	return info;
+}
+
--- /dev/null
+++ b/QW/client/snd_mix.c
@@ -1,0 +1,398 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// snd_mix.c -- portable code to mix sounds for snd_dma.c
+
+#include "quakedef.h"
+
+#ifdef _WIN32
+#include "winquake.h"
+#else
+#define DWORD	unsigned long
+#endif
+
+#define	PAINTBUFFER_SIZE	512
+portable_samplepair_t paintbuffer[PAINTBUFFER_SIZE];
+int		snd_scaletable[32][256];
+int 	*snd_p, snd_linear_count, snd_vol;
+short	*snd_out;
+
+void Snd_WriteLinearBlastStereo16 (void);
+
+#if	!id386
+void Snd_WriteLinearBlastStereo16 (void)
+{
+	int		i;
+	int		val;
+
+	for (i=0 ; i<snd_linear_count ; i+=2)
+	{
+		val = (snd_p[i]*snd_vol)>>8;
+		if (val > 0x7fff)
+			snd_out[i] = 0x7fff;
+		else if (val < (short)0x8000)
+			snd_out[i] = (short)0x8000;
+		else
+			snd_out[i] = val;
+
+		val = (snd_p[i+1]*snd_vol)>>8;
+		if (val > 0x7fff)
+			snd_out[i+1] = 0x7fff;
+		else if (val < (short)0x8000)
+			snd_out[i+1] = (short)0x8000;
+		else
+			snd_out[i+1] = val;
+	}
+}
+#endif
+
+void S_TransferStereo16 (int endtime)
+{
+	int		lpos;
+	int		lpaintedtime;
+	DWORD	*pbuf;
+#ifdef _WIN32
+	int		reps;
+	DWORD	dwSize,dwSize2;
+	DWORD	*pbuf2;
+	HRESULT	hresult;
+#endif
+	
+	snd_vol = volume.value*256;
+
+	snd_p = (int *) paintbuffer;
+	lpaintedtime = paintedtime;
+
+#ifdef _WIN32
+	if (pDSBuf)
+	{
+		reps = 0;
+
+		while ((hresult = pDSBuf->lpVtbl->Lock(pDSBuf, 0, gSndBufSize, &pbuf, &dwSize, 
+									   &pbuf2, &dwSize2, 0)) != DS_OK)
+		{
+			if (hresult != DSERR_BUFFERLOST)
+			{
+				Con_Printf ("S_TransferStereo16: DS::Lock Sound Buffer Failed\n");
+				S_Shutdown ();
+				S_Startup ();
+				return;
+			}
+
+			if (++reps > 10000)
+			{
+				Con_Printf ("S_TransferStereo16: DS: couldn't restore buffer\n");
+				S_Shutdown ();
+				S_Startup ();
+				return;
+			}
+		}
+	}
+	else
+#endif
+	{
+		pbuf = (DWORD *)shm->buffer;
+	}
+
+	while (lpaintedtime < endtime)
+	{
+	// handle recirculating buffer issues
+		lpos = lpaintedtime & ((shm->samples>>1)-1);
+
+		snd_out = (short *) pbuf + (lpos<<1);
+
+		snd_linear_count = (shm->samples>>1) - lpos;
+		if (lpaintedtime + snd_linear_count > endtime)
+			snd_linear_count = endtime - lpaintedtime;
+
+		snd_linear_count <<= 1;
+
+	// write a linear blast of samples
+		Snd_WriteLinearBlastStereo16 ();
+
+		snd_p += snd_linear_count;
+		lpaintedtime += (snd_linear_count>>1);
+	}
+
+#ifdef _WIN32
+	if (pDSBuf)
+		pDSBuf->lpVtbl->Unlock(pDSBuf, pbuf, dwSize, NULL, 0);
+#endif
+}
+
+void S_TransferPaintBuffer(int endtime)
+{
+	int 	out_idx;
+	int 	count;
+	int 	out_mask;
+	int 	*p;
+	int 	step;
+	int		val;
+	int		snd_vol;
+	DWORD	*pbuf;
+#ifdef _WIN32
+	int		reps;
+	DWORD	dwSize,dwSize2;
+	DWORD	*pbuf2;
+	HRESULT	hresult;
+#endif
+
+	if (shm->samplebits == 16 && shm->channels == 2)
+	{
+		S_TransferStereo16 (endtime);
+		return;
+	}
+	
+	p = (int *) paintbuffer;
+	count = (endtime - paintedtime) * shm->channels;
+	out_mask = shm->samples - 1; 
+	out_idx = paintedtime * shm->channels & out_mask;
+	step = 3 - shm->channels;
+	snd_vol = volume.value*256;
+
+#ifdef _WIN32
+	if (pDSBuf)
+	{
+		reps = 0;
+
+		while ((hresult = pDSBuf->lpVtbl->Lock(pDSBuf, 0, gSndBufSize, &pbuf, &dwSize, 
+									   &pbuf2,&dwSize2, 0)) != DS_OK)
+		{
+			if (hresult != DSERR_BUFFERLOST)
+			{
+				Con_Printf ("S_TransferPaintBuffer: DS::Lock Sound Buffer Failed\n");
+				S_Shutdown ();
+				S_Startup ();
+				return;
+			}
+
+			if (++reps > 10000)
+			{
+				Con_Printf ("S_TransferPaintBuffer: DS: couldn't restore buffer\n");
+				S_Shutdown ();
+				S_Startup ();
+				return;
+			}
+		}
+	}
+	else
+#endif
+	{
+		pbuf = (DWORD *)shm->buffer;
+	}
+
+	if (shm->samplebits == 16)
+	{
+		short *out = (short *) pbuf;
+		while (count--)
+		{
+			val = (*p * snd_vol) >> 8;
+			p+= step;
+			if (val > 0x7fff)
+				val = 0x7fff;
+			else if (val < (short)0x8000)
+				val = (short)0x8000;
+			out[out_idx] = val;
+			out_idx = (out_idx + 1) & out_mask;
+		}
+	}
+	else if (shm->samplebits == 8)
+	{
+		unsigned char *out = (unsigned char *) pbuf;
+		while (count--)
+		{
+			val = (*p * snd_vol) >> 8;
+			p+= step;
+			if (val > 0x7fff)
+				val = 0x7fff;
+			else if (val < (short)0x8000)
+				val = (short)0x8000;
+			out[out_idx] = (val>>8) + 128;
+			out_idx = (out_idx + 1) & out_mask;
+		}
+	}
+
+#ifdef _WIN32
+	if (pDSBuf) {
+		DWORD dwNewpos, dwWrite;
+		int il = paintedtime;
+		int ir = endtime - paintedtime;
+		
+		ir += il;
+
+		pDSBuf->lpVtbl->Unlock(pDSBuf, pbuf, dwSize, NULL, 0);
+
+		pDSBuf->lpVtbl->GetCurrentPosition(pDSBuf, &dwNewpos, &dwWrite);
+
+//		if ((dwNewpos >= il) && (dwNewpos <= ir))
+//			Con_Printf("%d-%d p %d c\n", il, ir, dwNewpos);
+	}
+#endif
+}
+
+
+/*
+===============================================================================
+
+CHANNEL MIXING
+
+===============================================================================
+*/
+
+void SND_PaintChannelFrom8 (channel_t *ch, sfxcache_t *sc, int endtime);
+void SND_PaintChannelFrom16 (channel_t *ch, sfxcache_t *sc, int endtime);
+
+void S_PaintChannels(int endtime)
+{
+	int 	i;
+	int 	end;
+	channel_t *ch;
+	sfxcache_t	*sc;
+	int		ltime, count;
+
+	while (paintedtime < endtime)
+	{
+	// if paintbuffer is smaller than DMA buffer
+		end = endtime;
+		if (endtime - paintedtime > PAINTBUFFER_SIZE)
+			end = paintedtime + PAINTBUFFER_SIZE;
+
+	// clear the paint buffer
+		Q_memset(paintbuffer, 0, (end - paintedtime) * sizeof(portable_samplepair_t));
+
+	// paint in the channels.
+		ch = channels;
+		for (i=0; i<total_channels ; i++, ch++)
+		{
+			if (!ch->sfx)
+				continue;
+			if (!ch->leftvol && !ch->rightvol)
+				continue;
+			sc = S_LoadSound (ch->sfx);
+			if (!sc)
+				continue;
+
+			ltime = paintedtime;
+
+			while (ltime < end)
+			{	// paint up to end
+				if (ch->end < end)
+					count = ch->end - ltime;
+				else
+					count = end - ltime;
+
+				if (count > 0)
+				{	
+					if (sc->width == 1)
+						SND_PaintChannelFrom8(ch, sc, count);
+					else
+						SND_PaintChannelFrom16(ch, sc, count);
+	
+					ltime += count;
+				}
+
+			// if at end of loop, restart
+				if (ltime >= ch->end)
+				{
+					if (sc->loopstart >= 0)
+					{
+						ch->pos = sc->loopstart;
+						ch->end = ltime + sc->length - ch->pos;
+					}
+					else				
+					{	// channel just stopped
+						ch->sfx = NULL;
+						break;
+					}
+				}
+			}
+															  
+		}
+
+	// transfer out according to DMA format
+		S_TransferPaintBuffer(end);
+		paintedtime = end;
+	}
+}
+
+void SND_InitScaletable (void)
+{
+	int		i, j;
+	
+	for (i=0 ; i<32 ; i++)
+		for (j=0 ; j<256 ; j++)
+			snd_scaletable[i][j] = ((signed char)j) * i * 8;
+}
+
+
+#if	!id386
+
+void SND_PaintChannelFrom8 (channel_t *ch, sfxcache_t *sc, int count)
+{
+	int 	data;
+	int		*lscale, *rscale;
+	unsigned char *sfx;
+	int		i;
+
+	if (ch->leftvol > 255)
+		ch->leftvol = 255;
+	if (ch->rightvol > 255)
+		ch->rightvol = 255;
+		
+	lscale = snd_scaletable[ch->leftvol >> 3];
+	rscale = snd_scaletable[ch->rightvol >> 3];
+	sfx = (signed char *)sc->data + ch->pos;
+
+	for (i=0 ; i<count ; i++)
+	{
+		data = sfx[i];
+		paintbuffer[i].left += lscale[data];
+		paintbuffer[i].right += rscale[data];
+	}
+	
+	ch->pos += count;
+}
+
+#endif	// !id386
+
+
+void SND_PaintChannelFrom16 (channel_t *ch, sfxcache_t *sc, int count)
+{
+	int data;
+	int left, right;
+	int leftvol, rightvol;
+	signed short *sfx;
+	int	i;
+
+	leftvol = ch->leftvol;
+	rightvol = ch->rightvol;
+	sfx = (signed short *)sc->data + ch->pos;
+
+	for (i=0 ; i<count ; i++)
+	{
+		data = sfx[i];
+		left = (data * leftvol) >> 8;
+		right = (data * rightvol) >> 8;
+		paintbuffer[i].left += left;
+		paintbuffer[i].right += right;
+	}
+
+	ch->pos += count;
+}
+
--- /dev/null
+++ b/QW/client/snd_mixa.asm
@@ -1,0 +1,346 @@
+ .386P
+ .model FLAT
+ externdef _d_zistepu:dword
+ externdef _d_pzbuffer:dword
+ externdef _d_zistepv:dword
+ externdef _d_zrowbytes:dword
+ externdef _d_ziorigin:dword
+ externdef _r_turb_s:dword
+ externdef _r_turb_t:dword
+ externdef _r_turb_pdest:dword
+ externdef _r_turb_spancount:dword
+ externdef _r_turb_turb:dword
+ externdef _r_turb_pbase:dword
+ externdef _r_turb_sstep:dword
+ externdef _r_turb_tstep:dword
+ externdef _r_bmodelactive:dword
+ externdef _d_sdivzstepu:dword
+ externdef _d_tdivzstepu:dword
+ externdef _d_sdivzstepv:dword
+ externdef _d_tdivzstepv:dword
+ externdef _d_sdivzorigin:dword
+ externdef _d_tdivzorigin:dword
+ externdef _sadjust:dword
+ externdef _tadjust:dword
+ externdef _bbextents:dword
+ externdef _bbextentt:dword
+ externdef _cacheblock:dword
+ externdef _d_viewbuffer:dword
+ externdef _cachewidth:dword
+ externdef _d_pzbuffer:dword
+ externdef _d_zrowbytes:dword
+ externdef _d_zwidth:dword
+ externdef _d_scantable:dword
+ externdef _r_lightptr:dword
+ externdef _r_numvblocks:dword
+ externdef _prowdestbase:dword
+ externdef _pbasesource:dword
+ externdef _r_lightwidth:dword
+ externdef _lightright:dword
+ externdef _lightrightstep:dword
+ externdef _lightdeltastep:dword
+ externdef _lightdelta:dword
+ externdef _lightright:dword
+ externdef _lightdelta:dword
+ externdef _sourcetstep:dword
+ externdef _surfrowbytes:dword
+ externdef _lightrightstep:dword
+ externdef _lightdeltastep:dword
+ externdef _r_sourcemax:dword
+ externdef _r_stepback:dword
+ externdef _colormap:dword
+ externdef _blocksize:dword
+ externdef _sourcesstep:dword
+ externdef _lightleft:dword
+ externdef _blockdivshift:dword
+ externdef _blockdivmask:dword
+ externdef _lightleftstep:dword
+ externdef _r_origin:dword
+ externdef _r_ppn:dword
+ externdef _r_pup:dword
+ externdef _r_pright:dword
+ externdef _ycenter:dword
+ externdef _xcenter:dword
+ externdef _d_vrectbottom_particle:dword
+ externdef _d_vrectright_particle:dword
+ externdef _d_vrecty:dword
+ externdef _d_vrectx:dword
+ externdef _d_pix_shift:dword
+ externdef _d_pix_min:dword
+ externdef _d_pix_max:dword
+ externdef _d_y_aspect_shift:dword
+ externdef _screenwidth:dword
+ externdef _vright:dword
+ externdef _vup:dword
+ externdef _vpn:dword
+ externdef _BOPS_Error:dword
+ externdef _snd_scaletable:dword
+ externdef _paintbuffer:dword
+ externdef _snd_linear_count:dword
+ externdef _snd_p:dword
+ externdef _snd_vol:dword
+ externdef _snd_out:dword
+ externdef _r_leftclipped:dword
+ externdef _r_leftenter:dword
+ externdef _r_rightclipped:dword
+ externdef _r_rightenter:dword
+ externdef _modelorg:dword
+ externdef _xscale:dword
+ externdef _r_refdef:dword
+ externdef _yscale:dword
+ externdef _r_leftexit:dword
+ externdef _r_rightexit:dword
+ externdef _r_lastvertvalid:dword
+ externdef _cacheoffset:dword
+ externdef _newedges:dword
+ externdef _removeedges:dword
+ externdef _r_pedge:dword
+ externdef _r_framecount:dword
+ externdef _r_u1:dword
+ externdef _r_emitted:dword
+ externdef _edge_p:dword
+ externdef _surface_p:dword
+ externdef _surfaces:dword
+ externdef _r_lzi1:dword
+ externdef _r_v1:dword
+ externdef _r_ceilv1:dword
+ externdef _r_nearzi:dword
+ externdef _r_nearzionly:dword
+ externdef _edge_aftertail:dword
+ externdef _edge_tail:dword
+ externdef _current_iv:dword
+ externdef _edge_head_u_shift20:dword
+ externdef _span_p:dword
+ externdef _edge_head:dword
+ externdef _fv:dword
+ externdef _edge_tail_u_shift20:dword
+ externdef _r_apverts:dword
+ externdef _r_anumverts:dword
+ externdef _aliastransform:dword
+ externdef _r_avertexnormals:dword
+ externdef _r_plightvec:dword
+ externdef _r_ambientlight:dword
+ externdef _r_shadelight:dword
+ externdef _aliasxcenter:dword
+ externdef _aliasycenter:dword
+ externdef _a_sstepxfrac:dword
+ externdef _r_affinetridesc:dword
+ externdef _acolormap:dword
+ externdef _d_pcolormap:dword
+ externdef _r_affinetridesc:dword
+ externdef _d_sfrac:dword
+ externdef _d_ptex:dword
+ externdef _d_pedgespanpackage:dword
+ externdef _d_tfrac:dword
+ externdef _d_light:dword
+ externdef _d_zi:dword
+ externdef _d_pdest:dword
+ externdef _d_pz:dword
+ externdef _d_aspancount:dword
+ externdef _erroradjustup:dword
+ externdef _errorterm:dword
+ externdef _d_xdenom:dword
+ externdef _r_p0:dword
+ externdef _r_p1:dword
+ externdef _r_p2:dword
+ externdef _a_tstepxfrac:dword
+ externdef _r_sstepx:dword
+ externdef _r_tstepx:dword
+ externdef _a_ststepxwhole:dword
+ externdef _zspantable:dword
+ externdef _skintable:dword
+ externdef _r_zistepx:dword
+ externdef _erroradjustdown:dword
+ externdef _d_countextrastep:dword
+ externdef _ubasestep:dword
+ externdef _a_ststepxwhole:dword
+ externdef _a_tstepxfrac:dword
+ externdef _r_lstepx:dword
+ externdef _a_spans:dword
+ externdef _erroradjustdown:dword
+ externdef _d_pdestextrastep:dword
+ externdef _d_pzextrastep:dword
+ externdef _d_sfracextrastep:dword
+ externdef _d_ptexextrastep:dword
+ externdef _d_countextrastep:dword
+ externdef _d_tfracextrastep:dword
+ externdef _d_lightextrastep:dword
+ externdef _d_ziextrastep:dword
+ externdef _d_pdestbasestep:dword
+ externdef _d_pzbasestep:dword
+ externdef _d_sfracbasestep:dword
+ externdef _d_ptexbasestep:dword
+ externdef _ubasestep:dword
+ externdef _d_tfracbasestep:dword
+ externdef _d_lightbasestep:dword
+ externdef _d_zibasestep:dword
+ externdef _zspantable:dword
+ externdef _r_lstepy:dword
+ externdef _r_sstepy:dword
+ externdef _r_tstepy:dword
+ externdef _r_zistepy:dword
+ externdef _D_PolysetSetEdgeTable:dword
+ externdef _D_RasterizeAliasPolySmooth:dword
+ externdef float_point5:dword
+ externdef Float2ToThe31nd:dword
+ externdef izistep:dword
+ externdef izi:dword
+ externdef FloatMinus2ToThe31nd:dword
+ externdef float_1:dword
+ externdef float_particle_z_clip:dword
+ externdef float_minus_1:dword
+ externdef float_0:dword
+ externdef fp_16:dword
+ externdef fp_64k:dword
+ externdef fp_1m:dword
+ externdef fp_1m_minus_1:dword
+ externdef fp_8:dword
+ externdef entryvec_table:dword
+ externdef advancetable:dword
+ externdef sstep:dword
+ externdef tstep:dword
+ externdef pspantemp:dword
+ externdef counttemp:dword
+ externdef jumptemp:dword
+ externdef reciprocal_table:dword
+ externdef DP_Count:dword
+ externdef DP_u:dword
+ externdef DP_v:dword
+ externdef DP_32768:dword
+ externdef DP_Color:dword
+ externdef DP_Pix:dword
+ externdef DP_EntryTable:dword
+ externdef pbase:dword
+ externdef s:dword
+ externdef t:dword
+ externdef sfracf:dword
+ externdef tfracf:dword
+ externdef snext:dword
+ externdef tnext:dword
+ externdef spancountminus1:dword
+ externdef zi16stepu:dword
+ externdef sdivz16stepu:dword
+ externdef tdivz16stepu:dword
+ externdef zi8stepu:dword
+ externdef sdivz8stepu:dword
+ externdef tdivz8stepu:dword
+ externdef reciprocal_table_16:dword
+ externdef entryvec_table_16:dword
+ externdef ceil_cw:dword
+ externdef single_cw:dword
+ externdef fp_64kx64k:dword
+ externdef pz:dword
+ externdef spr8entryvec_table:dword
+_TEXT SEGMENT
+ public _SND_PaintChannelFrom8
+_SND_PaintChannelFrom8:
+ push esi
+ push edi
+ push ebx
+ push ebp
+ mov ebx,ds:dword ptr[4+16+esp]
+ mov esi,ds:dword ptr[8+16+esp]
+ mov eax,ds:dword ptr[4+ebx]
+ mov edx,ds:dword ptr[8+ebx]
+ cmp eax,255
+ jna LLeftSet
+ mov eax,255
+LLeftSet:
+ cmp edx,255
+ jna LRightSet
+ mov edx,255
+LRightSet:
+ and eax,0F8h
+ add esi,20
+ and edx,0F8h
+ mov edi,ds:dword ptr[16+ebx]
+ mov ecx,ds:dword ptr[12+16+esp]
+ add esi,edi
+ shl eax,7
+ add edi,ecx
+ shl edx,7
+ mov ds:dword ptr[16+ebx],edi
+ add eax,offset _snd_scaletable
+ add edx,offset _snd_scaletable
+ sub ebx,ebx
+ mov bl,ds:byte ptr[-1+esi+ecx*1]
+ test ecx,1
+ jz LMix8Loop
+ mov edi,ds:dword ptr[eax+ebx*4]
+ mov ebp,ds:dword ptr[edx+ebx*4]
+ add edi,ds:dword ptr[_paintbuffer+0-8+ecx*8]
+ add ebp,ds:dword ptr[_paintbuffer+4-8+ecx*8]
+ mov ds:dword ptr[_paintbuffer+0-8+ecx*8],edi
+ mov ds:dword ptr[_paintbuffer+4-8+ecx*8],ebp
+ mov bl,ds:byte ptr[-2+esi+ecx*1]
+ dec ecx
+ jz LDone
+LMix8Loop:
+ mov edi,ds:dword ptr[eax+ebx*4]
+ mov ebp,ds:dword ptr[edx+ebx*4]
+ add edi,ds:dword ptr[_paintbuffer+0-8+ecx*8]
+ add ebp,ds:dword ptr[_paintbuffer+4-8+ecx*8]
+ mov bl,ds:byte ptr[-2+esi+ecx*1]
+ mov ds:dword ptr[_paintbuffer+0-8+ecx*8],edi
+ mov ds:dword ptr[_paintbuffer+4-8+ecx*8],ebp
+ mov edi,ds:dword ptr[eax+ebx*4]
+ mov ebp,ds:dword ptr[edx+ebx*4]
+ mov bl,ds:byte ptr[-3+esi+ecx*1]
+ add edi,ds:dword ptr[_paintbuffer+0-8*2+ecx*8]
+ add ebp,ds:dword ptr[_paintbuffer+4-8*2+ecx*8]
+ mov ds:dword ptr[_paintbuffer+0-8*2+ecx*8],edi
+ mov ds:dword ptr[_paintbuffer+4-8*2+ecx*8],ebp
+ sub ecx,2
+ jnz LMix8Loop
+LDone:
+ pop ebp
+ pop ebx
+ pop edi
+ pop esi
+ ret
+ public _Snd_WriteLinearBlastStereo16
+_Snd_WriteLinearBlastStereo16:
+ push esi
+ push edi
+ push ebx
+ mov ecx,ds:dword ptr[_snd_linear_count]
+ mov ebx,ds:dword ptr[_snd_p]
+ mov esi,ds:dword ptr[_snd_vol]
+ mov edi,ds:dword ptr[_snd_out]
+LWLBLoopTop:
+ mov eax,ds:dword ptr[-8+ebx+ecx*4]
+ imul eax,esi
+ sar eax,8
+ cmp eax,07FFFh
+ jg LClampHigh
+ cmp eax,0FFFF8000h
+ jnl LClampDone
+ mov eax,0FFFF8000h
+ jmp LClampDone
+LClampHigh:
+ mov eax,07FFFh
+LClampDone:
+ mov edx,ds:dword ptr[-4+ebx+ecx*4]
+ imul edx,esi
+ sar edx,8
+ cmp edx,07FFFh
+ jg LClampHigh2
+ cmp edx,0FFFF8000h
+ jnl LClampDone2
+ mov edx,0FFFF8000h
+ jmp LClampDone2
+LClampHigh2:
+ mov edx,07FFFh
+LClampDone2:
+ shl edx,16
+ and eax,0FFFFh
+ or edx,eax
+ mov ds:dword ptr[-4+edi+ecx*2],edx
+ sub ecx,2
+ jnz LWLBLoopTop
+ pop ebx
+ pop edi
+ pop esi
+ ret
+_TEXT ENDS
+ END
--- /dev/null
+++ b/QW/client/snd_mixa.s
@@ -1,0 +1,218 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+//
+// snd_mixa.s
+// x86 assembly-language sound code
+//
+
+#include "asm_i386.h"
+#include "quakeasm.h"
+
+#if	id386
+
+	.text
+
+//----------------------------------------------------------------------
+// 8-bit sound-mixing code
+//----------------------------------------------------------------------
+
+#define ch		4+16
+#define sc		8+16
+#define count	12+16
+
+.globl C(SND_PaintChannelFrom8)
+C(SND_PaintChannelFrom8):
+	pushl	%esi				// preserve register variables
+	pushl	%edi
+	pushl	%ebx
+	pushl	%ebp
+
+//	int 	data;
+//	short	*lscale, *rscale;
+//	unsigned char *sfx;
+//	int		i;
+
+	movl	ch(%esp),%ebx
+	movl	sc(%esp),%esi
+
+//	if (ch->leftvol > 255)
+//		ch->leftvol = 255;
+//	if (ch->rightvol > 255)
+//		ch->rightvol = 255;
+	movl	ch_leftvol(%ebx),%eax
+	movl	ch_rightvol(%ebx),%edx
+	cmpl	$255,%eax
+	jna		LLeftSet
+	movl	$255,%eax
+LLeftSet:
+	cmpl	$255,%edx
+	jna		LRightSet
+	movl	$255,%edx
+LRightSet:
+
+//	lscale = snd_scaletable[ch->leftvol >> 3];
+//	rscale = snd_scaletable[ch->rightvol >> 3];
+//	sfx = (signed char *)sc->data + ch->pos;
+//	ch->pos += count;
+	andl	$0xF8,%eax
+	addl	$(sfxc_data),%esi
+	andl	$0xF8,%edx
+	movl	ch_pos(%ebx),%edi
+	movl	count(%esp),%ecx
+	addl	%edi,%esi
+	shll	$7,%eax
+	addl	%ecx,%edi
+	shll	$7,%edx
+	movl	%edi,ch_pos(%ebx)
+	addl	$(C(snd_scaletable)),%eax
+	addl	$(C(snd_scaletable)),%edx
+	subl	%ebx,%ebx
+	movb	-1(%esi,%ecx,1),%bl
+
+	testl	$1,%ecx
+	jz		LMix8Loop
+
+	movl	(%eax,%ebx,4),%edi
+	movl	(%edx,%ebx,4),%ebp
+	addl	C(paintbuffer)+psp_left-psp_size(,%ecx,psp_size),%edi
+	addl	C(paintbuffer)+psp_right-psp_size(,%ecx,psp_size),%ebp
+	movl	%edi,C(paintbuffer)+psp_left-psp_size(,%ecx,psp_size)
+	movl	%ebp,C(paintbuffer)+psp_right-psp_size(,%ecx,psp_size)
+	movb	-2(%esi,%ecx,1),%bl
+
+	decl	%ecx
+	jz		LDone
+
+//	for (i=0 ; i<count ; i++)
+//	{
+LMix8Loop:
+
+//		data = sfx[i];
+//		paintbuffer[i].left += lscale[data];
+//		paintbuffer[i].right += rscale[data];
+	movl	(%eax,%ebx,4),%edi
+	movl	(%edx,%ebx,4),%ebp
+	addl	C(paintbuffer)+psp_left-psp_size(,%ecx,psp_size),%edi
+	addl	C(paintbuffer)+psp_right-psp_size(,%ecx,psp_size),%ebp
+	movb	-2(%esi,%ecx,1),%bl
+	movl	%edi,C(paintbuffer)+psp_left-psp_size(,%ecx,psp_size)
+	movl	%ebp,C(paintbuffer)+psp_right-psp_size(,%ecx,psp_size)
+
+	movl	(%eax,%ebx,4),%edi
+	movl	(%edx,%ebx,4),%ebp
+	movb	-3(%esi,%ecx,1),%bl
+	addl	C(paintbuffer)+psp_left-psp_size*2(,%ecx,psp_size),%edi
+	addl	C(paintbuffer)+psp_right-psp_size*2(,%ecx,psp_size),%ebp
+	movl	%edi,C(paintbuffer)+psp_left-psp_size*2(,%ecx,psp_size)
+	movl	%ebp,C(paintbuffer)+psp_right-psp_size*2(,%ecx,psp_size)
+
+//	}
+	subl	$2,%ecx
+	jnz		LMix8Loop
+
+LDone:
+	popl	%ebp
+	popl	%ebx
+	popl	%edi
+	popl	%esi
+
+	ret
+
+
+//----------------------------------------------------------------------
+// Transfer of stereo buffer to 16-bit DMA buffer code
+//----------------------------------------------------------------------
+
+.globl C(Snd_WriteLinearBlastStereo16)
+C(Snd_WriteLinearBlastStereo16):
+	pushl	%esi				// preserve register variables
+	pushl	%edi
+	pushl	%ebx
+
+//	int		i;
+//	int		val;
+	movl	C(snd_linear_count),%ecx
+	movl	C(snd_p),%ebx
+	movl	C(snd_vol),%esi
+	movl	C(snd_out),%edi
+
+//	for (i=0 ; i<snd_linear_count ; i+=2)
+//	{
+LWLBLoopTop:
+
+//		val = (snd_p[i]*snd_vol)>>8;
+//		if (val > 0x7fff)
+//			snd_out[i] = 0x7fff;
+//		else if (val < (short)0x8000)
+//			snd_out[i] = (short)0x8000;
+//		else
+//			snd_out[i] = val;
+	movl	-8(%ebx,%ecx,4),%eax
+	imull	%esi,%eax
+	sarl	$8,%eax
+	cmpl	$0x7FFF,%eax
+	jg		LClampHigh
+	cmpl	$0xFFFF8000,%eax
+	jnl		LClampDone
+	movl	$0xFFFF8000,%eax
+	jmp		LClampDone
+LClampHigh:
+	movl	$0x7FFF,%eax
+LClampDone:
+
+//		val = (snd_p[i+1]*snd_vol)>>8;
+//		if (val > 0x7fff)
+//			snd_out[i+1] = 0x7fff;
+//		else if (val < (short)0x8000)
+//			snd_out[i+1] = (short)0x8000;
+//		else
+//			snd_out[i+1] = val;
+	movl	-4(%ebx,%ecx,4),%edx
+	imull	%esi,%edx
+	sarl	$8,%edx
+	cmpl	$0x7FFF,%edx
+	jg		LClampHigh2
+	cmpl	$0xFFFF8000,%edx
+	jnl		LClampDone2
+	movl	$0xFFFF8000,%edx
+	jmp		LClampDone2
+LClampHigh2:
+	movl	$0x7FFF,%edx
+LClampDone2:
+	shll	$16,%edx
+	andl	$0xFFFF,%eax
+	orl		%eax,%edx
+	movl	%edx,-4(%edi,%ecx,2)
+
+//	}
+	subl	$2,%ecx
+	jnz		LWLBLoopTop
+
+//	snd_p += snd_linear_count;
+
+	popl	%ebx
+	popl	%edi
+	popl	%esi
+
+	ret
+
+
+#endif	// id386
+
--- /dev/null
+++ b/QW/client/snd_win.c
@@ -1,0 +1,727 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+#include "quakedef.h"
+#include "winquake.h"
+
+#define iDirectSoundCreate(a,b,c)	pDirectSoundCreate(a,b,c)
+
+HRESULT (WINAPI *pDirectSoundCreate)(GUID FAR *lpGUID, LPDIRECTSOUND FAR *lplpDS, IUnknown FAR *pUnkOuter);
+
+// 64K is > 1 second at 16-bit, 22050 Hz
+#define	WAV_BUFFERS				64
+#define	WAV_MASK				0x3F
+#define	WAV_BUFFER_SIZE			0x0400
+#define SECONDARY_BUFFER_SIZE	0x10000
+
+typedef enum {SIS_SUCCESS, SIS_FAILURE, SIS_NOTAVAIL} sndinitstat;
+
+static qboolean	wavonly;
+static qboolean	dsound_init;
+static qboolean	wav_init;
+static qboolean	snd_firsttime = true, snd_isdirect, snd_iswave;
+static qboolean	primary_format_set;
+
+static int	sample16;
+static int	snd_sent, snd_completed;
+
+
+/* 
+ * Global variables. Must be visible to window-procedure function 
+ *  so it can unlock and free the data block after it has been played. 
+ */ 
+
+HANDLE		hData;
+HPSTR		lpData, lpData2;
+
+HGLOBAL		hWaveHdr;
+LPWAVEHDR	lpWaveHdr;
+
+HWAVEOUT    hWaveOut; 
+
+WAVEOUTCAPS	wavecaps;
+
+DWORD	gSndBufSize;
+
+MMTIME		mmstarttime;
+
+LPDIRECTSOUND pDS;
+LPDIRECTSOUNDBUFFER pDSBuf, pDSPBuf;
+
+HINSTANCE hInstDS;
+
+qboolean SNDDMA_InitDirect (void);
+qboolean SNDDMA_InitWav (void);
+
+
+/*
+==================
+S_BlockSound
+==================
+*/
+void S_BlockSound (void)
+{
+
+// DirectSound takes care of blocking itself
+	if (snd_iswave)
+	{
+		snd_blocked++;
+
+		if (snd_blocked == 1)
+			waveOutReset (hWaveOut);
+	}
+}
+
+
+/*
+==================
+S_UnblockSound
+==================
+*/
+void S_UnblockSound (void)
+{
+
+// DirectSound takes care of blocking itself
+	if (snd_iswave)
+	{
+		snd_blocked--;
+	}
+}
+
+
+/*
+==================
+FreeSound
+==================
+*/
+void FreeSound (void)
+{
+	int		i;
+
+	if (pDSBuf)
+	{
+		pDSBuf->lpVtbl->Stop(pDSBuf);
+		pDSBuf->lpVtbl->Release(pDSBuf);
+	}
+
+// only release primary buffer if it's not also the mixing buffer we just released
+	if (pDSPBuf && (pDSBuf != pDSPBuf))
+	{
+		pDSPBuf->lpVtbl->Release(pDSPBuf);
+	}
+
+	if (pDS)
+	{
+		pDS->lpVtbl->SetCooperativeLevel (pDS, mainwindow, DSSCL_NORMAL);
+		pDS->lpVtbl->Release(pDS);
+	}
+
+	if (hWaveOut)
+	{
+		waveOutReset (hWaveOut);
+
+		if (lpWaveHdr)
+		{
+			for (i=0 ; i< WAV_BUFFERS ; i++)
+				waveOutUnprepareHeader (hWaveOut, lpWaveHdr+i, sizeof(WAVEHDR));
+		}
+
+		waveOutClose (hWaveOut);
+
+		if (hWaveHdr)
+		{
+			GlobalUnlock(hWaveHdr); 
+			GlobalFree(hWaveHdr);
+		}
+
+		if (hData)
+		{
+			GlobalUnlock(hData);
+			GlobalFree(hData);
+		}
+
+	}
+
+	pDS = NULL;
+	pDSBuf = NULL;
+	pDSPBuf = NULL;
+	hWaveOut = 0;
+	hData = 0;
+	hWaveHdr = 0;
+	lpData = NULL;
+	lpWaveHdr = NULL;
+	dsound_init = false;
+	wav_init = false;
+}
+
+
+/*
+==================
+SNDDMA_InitDirect
+
+Direct-Sound support
+==================
+*/
+sndinitstat SNDDMA_InitDirect (void)
+{
+	DSBUFFERDESC	dsbuf;
+	DSBCAPS			dsbcaps;
+	DWORD			dwSize, dwWrite;
+	DSCAPS			dscaps;
+	WAVEFORMATEX	format, pformat; 
+	HRESULT			hresult;
+	int				reps;
+
+	memset ((void *)&sn, 0, sizeof (sn));
+
+	shm = &sn;
+
+	shm->channels = 2;
+	shm->samplebits = 16;
+	shm->speed = 11025;
+
+	memset (&format, 0, sizeof(format));
+	format.wFormatTag = WAVE_FORMAT_PCM;
+    format.nChannels = shm->channels;
+    format.wBitsPerSample = shm->samplebits;
+    format.nSamplesPerSec = shm->speed;
+    format.nBlockAlign = format.nChannels
+		*format.wBitsPerSample / 8;
+    format.cbSize = 0;
+    format.nAvgBytesPerSec = format.nSamplesPerSec
+		*format.nBlockAlign; 
+
+	if (!hInstDS)
+	{
+		hInstDS = LoadLibrary("dsound.dll");
+		
+		if (hInstDS == NULL)
+		{
+			Con_SafePrintf ("Couldn't load dsound.dll\n");
+			return SIS_FAILURE;
+		}
+
+		pDirectSoundCreate = (void *)GetProcAddress(hInstDS,"DirectSoundCreate");
+
+		if (!pDirectSoundCreate)
+		{
+			Con_SafePrintf ("Couldn't get DS proc addr\n");
+			return SIS_FAILURE;
+		}
+	}
+
+	while ((hresult = iDirectSoundCreate(NULL, &pDS, NULL)) != DS_OK)
+	{
+		if (hresult != DSERR_ALLOCATED)
+		{
+			Con_SafePrintf ("DirectSound create failed\n");
+			return SIS_FAILURE;
+		}
+
+		if (MessageBox (NULL,
+						"The sound hardware is in use by another app.\n\n"
+					    "Select Retry to try to start sound again or Cancel to run Quake with no sound.",
+						"Sound not available",
+						MB_RETRYCANCEL | MB_SETFOREGROUND | MB_ICONEXCLAMATION) != IDRETRY)
+		{
+			Con_SafePrintf ("DirectSoundCreate failure\n"
+							"  hardware already in use\n");
+			return SIS_NOTAVAIL;
+		}
+	}
+
+	dscaps.dwSize = sizeof(dscaps);
+
+	if (DS_OK != pDS->lpVtbl->GetCaps (pDS, &dscaps))
+	{
+		Con_SafePrintf ("Couldn't get DS caps\n");
+	}
+
+	if (dscaps.dwFlags & DSCAPS_EMULDRIVER)
+	{
+		Con_SafePrintf ("No DirectSound driver installed\n");
+		FreeSound ();
+		return SIS_FAILURE;
+	}
+
+	if (DS_OK != pDS->lpVtbl->SetCooperativeLevel (pDS, mainwindow, DSSCL_EXCLUSIVE))
+	{
+		Con_SafePrintf ("Set coop level failed\n");
+		FreeSound ();
+		return SIS_FAILURE;
+	}
+
+// get access to the primary buffer, if possible, so we can set the
+// sound hardware format
+	memset (&dsbuf, 0, sizeof(dsbuf));
+	dsbuf.dwSize = sizeof(DSBUFFERDESC);
+	dsbuf.dwFlags = DSBCAPS_PRIMARYBUFFER;
+	dsbuf.dwBufferBytes = 0;
+	dsbuf.lpwfxFormat = NULL;
+
+	memset(&dsbcaps, 0, sizeof(dsbcaps));
+	dsbcaps.dwSize = sizeof(dsbcaps);
+	primary_format_set = false;
+
+	if (!COM_CheckParm ("-snoforceformat"))
+	{
+		if (DS_OK == pDS->lpVtbl->CreateSoundBuffer(pDS, &dsbuf, &pDSPBuf, NULL))
+		{
+			pformat = format;
+
+			if (DS_OK != pDSPBuf->lpVtbl->SetFormat (pDSPBuf, &pformat))
+			{
+//				if (snd_firsttime)
+//					Con_SafePrintf ("Set primary sound buffer format: no\n");
+			}
+			else
+//			{
+//				if (snd_firsttime)
+//					Con_SafePrintf ("Set primary sound buffer format: yes\n");
+
+				primary_format_set = true;
+//			}
+		}
+	}
+
+	if (!primary_format_set || !COM_CheckParm ("-primarysound"))
+	{
+	// create the secondary buffer we'll actually work with
+		memset (&dsbuf, 0, sizeof(dsbuf));
+		dsbuf.dwSize = sizeof(DSBUFFERDESC);
+		dsbuf.dwFlags = DSBCAPS_CTRLFREQUENCY | DSBCAPS_LOCSOFTWARE;
+		dsbuf.dwBufferBytes = SECONDARY_BUFFER_SIZE;
+		dsbuf.lpwfxFormat = &format;
+
+		memset(&dsbcaps, 0, sizeof(dsbcaps));
+		dsbcaps.dwSize = sizeof(dsbcaps);
+
+		if (DS_OK != pDS->lpVtbl->CreateSoundBuffer(pDS, &dsbuf, &pDSBuf, NULL))
+		{
+			Con_SafePrintf ("DS:CreateSoundBuffer Failed");
+			FreeSound ();
+			return SIS_FAILURE;
+		}
+
+		shm->channels = format.nChannels;
+		shm->samplebits = format.wBitsPerSample;
+		shm->speed = format.nSamplesPerSec;
+
+		if (DS_OK != pDSBuf->lpVtbl->GetCaps (pDSBuf, &dsbcaps))
+		{
+			Con_SafePrintf ("DS:GetCaps failed\n");
+			FreeSound ();
+			return SIS_FAILURE;
+		}
+
+//		if (snd_firsttime)
+//			Con_SafePrintf ("Using secondary sound buffer\n");
+	}
+	else
+	{
+		if (DS_OK != pDS->lpVtbl->SetCooperativeLevel (pDS, mainwindow, DSSCL_WRITEPRIMARY))
+		{
+			Con_SafePrintf ("Set coop level failed\n");
+			FreeSound ();
+			return SIS_FAILURE;
+		}
+
+		if (DS_OK != pDSPBuf->lpVtbl->GetCaps (pDSPBuf, &dsbcaps))
+		{
+			Con_Printf ("DS:GetCaps failed\n");
+			return SIS_FAILURE;
+		}
+
+		pDSBuf = pDSPBuf;
+//		Con_SafePrintf ("Using primary sound buffer\n");
+	}
+
+	// Make sure mixer is active
+	pDSBuf->lpVtbl->Play(pDSBuf, 0, 0, DSBPLAY_LOOPING);
+
+/*	if (snd_firsttime)
+		Con_SafePrintf("   %d channel(s)\n"
+		               "   %d bits/sample\n"
+					   "   %d bytes/sec\n",
+					   shm->channels, shm->samplebits, shm->speed);*/
+	
+	gSndBufSize = dsbcaps.dwBufferBytes;
+
+// initialize the buffer
+	reps = 0;
+
+	while ((hresult = pDSBuf->lpVtbl->Lock(pDSBuf, 0, gSndBufSize, &lpData, &dwSize, NULL, NULL, 0)) != DS_OK)
+	{
+		if (hresult != DSERR_BUFFERLOST)
+		{
+			Con_SafePrintf ("SNDDMA_InitDirect: DS::Lock Sound Buffer Failed\n");
+			FreeSound ();
+			return SIS_FAILURE;
+		}
+
+		if (++reps > 10000)
+		{
+			Con_SafePrintf ("SNDDMA_InitDirect: DS: couldn't restore buffer\n");
+			FreeSound ();
+			return SIS_FAILURE;
+		}
+
+	}
+
+	memset(lpData, 0, dwSize);
+//		lpData[4] = lpData[5] = 0x7f;	// force a pop for debugging
+
+	pDSBuf->lpVtbl->Unlock(pDSBuf, lpData, dwSize, NULL, 0);
+
+	/* we don't want anyone to access the buffer directly w/o locking it first. */
+	lpData = NULL; 
+
+	pDSBuf->lpVtbl->Stop(pDSBuf);
+	pDSBuf->lpVtbl->GetCurrentPosition(pDSBuf, &mmstarttime.u.sample, &dwWrite);
+	pDSBuf->lpVtbl->Play(pDSBuf, 0, 0, DSBPLAY_LOOPING);
+
+	shm->soundalive = true;
+	shm->splitbuffer = false;
+	shm->samples = gSndBufSize/(shm->samplebits/8);
+	shm->samplepos = 0;
+	shm->submission_chunk = 1;
+	shm->buffer = (unsigned char *) lpData;
+	sample16 = (shm->samplebits/8) - 1;
+
+	dsound_init = true;
+
+	return SIS_SUCCESS;
+}
+
+
+/*
+==================
+SNDDM_InitWav
+
+Crappy windows multimedia base
+==================
+*/
+qboolean SNDDMA_InitWav (void)
+{
+	WAVEFORMATEX  format; 
+	int				i;
+	HRESULT			hr;
+	
+	snd_sent = 0;
+	snd_completed = 0;
+
+	shm = &sn;
+
+	shm->channels = 2;
+	shm->samplebits = 16;
+	shm->speed = 11025;
+
+	memset (&format, 0, sizeof(format));
+	format.wFormatTag = WAVE_FORMAT_PCM;
+	format.nChannels = shm->channels;
+	format.wBitsPerSample = shm->samplebits;
+	format.nSamplesPerSec = shm->speed;
+	format.nBlockAlign = format.nChannels
+		*format.wBitsPerSample / 8;
+	format.cbSize = 0;
+	format.nAvgBytesPerSec = format.nSamplesPerSec
+		*format.nBlockAlign; 
+	
+	/* Open a waveform device for output using window callback. */ 
+	while ((hr = waveOutOpen((LPHWAVEOUT)&hWaveOut, WAVE_MAPPER, 
+					&format, 
+					0, 0L, CALLBACK_NULL)) != MMSYSERR_NOERROR)
+	{
+		if (hr != MMSYSERR_ALLOCATED)
+		{
+			Con_SafePrintf ("waveOutOpen failed\n");
+			return false;
+		}
+
+		if (MessageBox (NULL,
+						"The sound hardware is in use by another app.\n\n"
+					    "Select Retry to try to start sound again or Cancel to run Quake with no sound.",
+						"Sound not available",
+						MB_RETRYCANCEL | MB_SETFOREGROUND | MB_ICONEXCLAMATION) != IDRETRY)
+		{
+			Con_SafePrintf ("waveOutOpen failure;\n"
+							"  hardware already in use\n");
+			return false;
+		}
+	} 
+
+	/* 
+	 * Allocate and lock memory for the waveform data. The memory 
+	 * for waveform data must be globally allocated with 
+	 * GMEM_MOVEABLE and GMEM_SHARE flags. 
+
+	*/ 
+	gSndBufSize = WAV_BUFFERS*WAV_BUFFER_SIZE;
+	hData = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, gSndBufSize); 
+	if (!hData) 
+	{ 
+		Con_SafePrintf ("Sound: Out of memory.\n");
+		FreeSound ();
+		return false; 
+	}
+	lpData = GlobalLock(hData);
+	if (!lpData)
+	{ 
+		Con_SafePrintf ("Sound: Failed to lock.\n");
+		FreeSound ();
+		return false; 
+	} 
+	memset (lpData, 0, gSndBufSize);
+
+	/* 
+	 * Allocate and lock memory for the header. This memory must 
+	 * also be globally allocated with GMEM_MOVEABLE and 
+	 * GMEM_SHARE flags. 
+	 */ 
+	hWaveHdr = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, 
+		(DWORD) sizeof(WAVEHDR) * WAV_BUFFERS); 
+
+	if (hWaveHdr == NULL)
+	{ 
+		Con_SafePrintf ("Sound: Failed to Alloc header.\n");
+		FreeSound ();
+		return false; 
+	} 
+
+	lpWaveHdr = (LPWAVEHDR) GlobalLock(hWaveHdr); 
+
+	if (lpWaveHdr == NULL)
+	{ 
+		Con_SafePrintf ("Sound: Failed to lock header.\n");
+		FreeSound ();
+		return false; 
+	}
+
+	memset (lpWaveHdr, 0, sizeof(WAVEHDR) * WAV_BUFFERS);
+
+	/* After allocation, set up and prepare headers. */ 
+	for (i=0 ; i<WAV_BUFFERS ; i++)
+	{
+		lpWaveHdr[i].dwBufferLength = WAV_BUFFER_SIZE; 
+		lpWaveHdr[i].lpData = lpData + i*WAV_BUFFER_SIZE;
+
+		if (waveOutPrepareHeader(hWaveOut, lpWaveHdr+i, sizeof(WAVEHDR)) !=
+				MMSYSERR_NOERROR)
+		{
+			Con_SafePrintf ("Sound: failed to prepare wave headers\n");
+			FreeSound ();
+			return false;
+		}
+	}
+
+	shm->soundalive = true;
+	shm->splitbuffer = false;
+	shm->samples = gSndBufSize/(shm->samplebits/8);
+	shm->samplepos = 0;
+	shm->submission_chunk = 1;
+	shm->buffer = (unsigned char *) lpData;
+	sample16 = (shm->samplebits/8) - 1;
+
+	wav_init = true;
+
+	return true;
+}
+
+/*
+==================
+SNDDMA_Init
+
+Try to find a sound device to mix for.
+Returns false if nothing is found.
+==================
+*/
+
+int SNDDMA_Init(void)
+{
+	sndinitstat	stat;
+
+	if (COM_CheckParm ("-wavonly"))
+		wavonly = true;
+
+	dsound_init = wav_init = 0;
+
+	stat = SIS_FAILURE;	// assume DirectSound won't initialize
+
+	/* Init DirectSound */
+	if (!wavonly)
+	{
+		if (snd_firsttime || snd_isdirect)
+		{
+			stat = SNDDMA_InitDirect ();;
+
+			if (stat == SIS_SUCCESS)
+			{
+				snd_isdirect = true;
+
+				if (snd_firsttime)
+					Con_SafePrintf ("DirectSound initialized\n");
+			}
+			else
+			{
+				snd_isdirect = false;
+				Con_SafePrintf ("DirectSound failed to init\n");
+			}
+		}
+	}
+
+// if DirectSound didn't succeed in initializing, try to initialize
+// waveOut sound, unless DirectSound failed because the hardware is
+// already allocated (in which case the user has already chosen not
+// to have sound)
+	if (!dsound_init && (stat != SIS_NOTAVAIL))
+	{
+		if (snd_firsttime || snd_iswave)
+		{
+
+			snd_iswave = SNDDMA_InitWav ();
+
+			if (snd_iswave)
+			{
+				if (snd_firsttime)
+					Con_SafePrintf ("Wave sound initialized\n");
+			}
+			else
+			{
+				Con_SafePrintf ("Wave sound failed to init\n");
+			}
+		}
+	}
+
+	snd_firsttime = false;
+
+	if (!dsound_init && !wav_init)
+	{
+		if (snd_firsttime)
+			Con_SafePrintf ("No sound device initialized\n");
+
+		return 0;
+	}
+
+	return 1;
+}
+
+/*
+==============
+SNDDMA_GetDMAPos
+
+return the current sample position (in mono samples read)
+inside the recirculating dma buffer, so the mixing code will know
+how many sample are required to fill it up.
+===============
+*/
+int SNDDMA_GetDMAPos(void)
+{
+	MMTIME	mmtime;
+	int		s;
+	DWORD	dwWrite;
+
+	if (dsound_init) 
+	{
+		mmtime.wType = TIME_SAMPLES;
+		pDSBuf->lpVtbl->GetCurrentPosition(pDSBuf, &mmtime.u.sample, &dwWrite);
+		s = mmtime.u.sample - mmstarttime.u.sample;
+	}
+	else if (wav_init)
+	{
+		s = snd_sent * WAV_BUFFER_SIZE;
+	}
+
+
+	s >>= sample16;
+
+	s &= (shm->samples-1);
+
+	return s;
+}
+
+/*
+==============
+SNDDMA_Submit
+
+Send sound to device if buffer isn't really the dma buffer
+===============
+*/
+void SNDDMA_Submit(void)
+{
+	LPWAVEHDR	h;
+	int			wResult;
+
+	if (!wav_init)
+		return;
+
+	//
+	// find which sound blocks have completed
+	//
+	while (1)
+	{
+		if ( snd_completed == snd_sent )
+		{
+			Con_DPrintf ("Sound overrun\n");
+			break;
+		}
+
+		if ( ! (lpWaveHdr[ snd_completed & WAV_MASK].dwFlags & WHDR_DONE) )
+		{
+			break;
+		}
+
+		snd_completed++;	// this buffer has been played
+	}
+
+	//
+	// submit two new sound blocks
+	//
+	while (((snd_sent - snd_completed) >> sample16) < 4)
+	{
+		h = lpWaveHdr + ( snd_sent&WAV_MASK );
+
+		snd_sent++;
+		/* 
+		 * Now the data block can be sent to the output device. The 
+		 * waveOutWrite function returns immediately and waveform 
+		 * data is sent to the output device in the background. 
+		 */ 
+		wResult = waveOutWrite(hWaveOut, h, sizeof(WAVEHDR)); 
+
+		if (wResult != MMSYSERR_NOERROR)
+		{ 
+			Con_SafePrintf ("Failed to write block to device\n");
+			FreeSound ();
+			return; 
+		} 
+	}
+}
+
+/*
+==============
+SNDDMA_Shutdown
+
+Reset the sound device for exiting
+===============
+*/
+void SNDDMA_Shutdown(void)
+{
+	FreeSound ();
+}
+
--- /dev/null
+++ b/QW/client/sound.h
@@ -1,0 +1,174 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// sound.h -- client sound i/o functions
+
+#ifndef __SOUND__
+#define __SOUND__
+
+// !!! if this is changed, it much be changed in asm_i386.h too !!!
+typedef struct
+{
+	int left;
+	int right;
+} portable_samplepair_t;
+
+typedef struct sfx_s
+{
+	char 	name[MAX_QPATH];
+	cache_user_t	cache;
+} sfx_t;
+
+// !!! if this is changed, it much be changed in asm_i386.h too !!!
+typedef struct
+{
+	int 	length;
+	int 	loopstart;
+	int 	speed;
+	int 	width;
+	int 	stereo;
+	byte	data[1];		// variable sized
+} sfxcache_t;
+
+typedef struct
+{
+	qboolean		gamealive;
+	qboolean		soundalive;
+	qboolean		splitbuffer;
+	int				channels;
+	int				samples;				// mono samples in buffer
+	int				submission_chunk;		// don't mix less than this #
+	int				samplepos;				// in mono samples
+	int				samplebits;
+	int				speed;
+	unsigned char	*buffer;
+} dma_t;
+
+// !!! if this is changed, it much be changed in asm_i386.h too !!!
+typedef struct
+{
+	sfx_t	*sfx;			// sfx number
+	int		leftvol;		// 0-255 volume
+	int		rightvol;		// 0-255 volume
+	int		end;			// end time in global paintsamples
+	int 	pos;			// sample position in sfx
+	int		looping;		// where to loop, -1 = no looping
+	int		entnum;			// to allow overriding a specific sound
+	int		entchannel;		//
+	vec3_t	origin;			// origin of sound effect
+	vec_t	dist_mult;		// distance multiplier (attenuation/clipK)
+	int		master_vol;		// 0-255 master volume
+} channel_t;
+
+typedef struct
+{
+	int		rate;
+	int		width;
+	int		channels;
+	int		loopstart;
+	int		samples;
+	int		dataofs;		// chunk starts this many bytes from file start
+} wavinfo_t;
+
+void S_Init (void);
+void S_Startup (void);
+void S_Shutdown (void);
+void S_StartSound (int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float fvol,  float attenuation);
+void S_StaticSound (sfx_t *sfx, vec3_t origin, float vol, float attenuation);
+void S_StopSound (int entnum, int entchannel);
+void S_StopAllSounds(qboolean clear);
+void S_ClearBuffer (void);
+void S_Update (vec3_t origin, vec3_t v_forward, vec3_t v_right, vec3_t v_up);
+void S_ExtraUpdate (void);
+
+sfx_t *S_PrecacheSound (char *sample);
+void S_TouchSound (char *sample);
+void S_ClearPrecache (void);
+void S_BeginPrecaching (void);
+void S_EndPrecaching (void);
+void S_PaintChannels(int endtime);
+void S_InitPaintChannels (void);
+
+// picks a channel based on priorities, empty slots, number of channels
+channel_t *SND_PickChannel(int entnum, int entchannel);
+
+// spatializes a channel
+void SND_Spatialize(channel_t *ch);
+
+// initializes cycling through a DMA buffer and returns information on it
+qboolean SNDDMA_Init(void);
+
+// gets the current DMA position
+int SNDDMA_GetDMAPos(void);
+
+// shutdown the DMA xfer.
+void SNDDMA_Shutdown(void);
+
+// ====================================================================
+// User-setable variables
+// ====================================================================
+
+#define	MAX_CHANNELS			128
+#define	MAX_DYNAMIC_CHANNELS	8
+
+
+extern	channel_t   channels[MAX_CHANNELS];
+// 0 to MAX_DYNAMIC_CHANNELS-1	= normal entity sounds
+// MAX_DYNAMIC_CHANNELS to MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS -1 = water, etc
+// MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS to total_channels = static sounds
+
+extern	int			total_channels;
+
+//
+// Fake dma is a synchronous faking of the DMA progress used for
+// isolating performance in the renderer.  The fakedma_updates is
+// number of times S_Update() is called per second.
+//
+
+extern qboolean 		fakedma;
+extern int 			fakedma_updates;
+extern int		paintedtime;
+extern vec3_t listener_origin;
+extern vec3_t listener_forward;
+extern vec3_t listener_right;
+extern vec3_t listener_up;
+extern volatile dma_t *shm;
+extern volatile dma_t sn;
+extern vec_t sound_nominal_clip_dist;
+
+extern	cvar_t loadas8bit;
+extern	cvar_t bgmvolume;
+extern	cvar_t volume;
+
+extern qboolean	snd_initialized;
+
+extern int		snd_blocked;
+
+void S_LocalSound (char *s);
+sfxcache_t *S_LoadSound (sfx_t *s);
+
+wavinfo_t GetWavinfo (char *name, byte *wav, int wavlength);
+
+void SND_InitScaletable (void);
+void SNDDMA_Submit(void);
+
+void S_AmbientOff (void);
+void S_AmbientOn (void);
+
+#endif
--- /dev/null
+++ b/QW/client/spritegn.h
@@ -1,0 +1,110 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+//
+// spritegn.h: header file for sprite generation program
+//
+
+// **********************************************************
+// * This file must be identical in the spritegen directory *
+// * and in the Quake directory, because it's used to       *
+// * pass data from one to the other via .spr files.        *
+// **********************************************************
+
+//-------------------------------------------------------
+// This program generates .spr sprite package files.
+// The format of the files is as follows:
+//
+// dsprite_t file header structure
+// <repeat dsprite_t.numframes times>
+//   <if spritegroup, repeat dspritegroup_t.numframes times>
+//     dspriteframe_t frame header structure
+//     sprite bitmap
+//   <else (single sprite frame)>
+//     dspriteframe_t frame header structure
+//     sprite bitmap
+// <endrepeat>
+//-------------------------------------------------------
+
+#ifdef INCLUDELIBS
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+#include <string.h>
+
+#include "cmdlib.h"
+#include "scriplib.h"
+#include "dictlib.h"
+#include "trilib.h"
+#include "lbmlib.h"
+#include "mathlib.h"
+
+#endif
+
+#define SPRITE_VERSION	1
+
+// must match definition in modelgen.h
+#ifndef SYNCTYPE_T
+#define SYNCTYPE_T
+typedef enum {ST_SYNC=0, ST_RAND } synctype_t;
+#endif
+
+// TODO: shorten these?
+typedef struct {
+	int			ident;
+	int			version;
+	int			type;
+	float		boundingradius;
+	int			width;
+	int			height;
+	int			numframes;
+	float		beamlength;
+	synctype_t	synctype;
+} dsprite_t;
+
+#define SPR_VP_PARALLEL_UPRIGHT		0
+#define SPR_FACING_UPRIGHT			1
+#define SPR_VP_PARALLEL				2
+#define SPR_ORIENTED				3
+#define SPR_VP_PARALLEL_ORIENTED	4
+
+typedef struct {
+	int			origin[2];
+	int			width;
+	int			height;
+} dspriteframe_t;
+
+typedef struct {
+	int			numframes;
+} dspritegroup_t;
+
+typedef struct {
+	float	interval;
+} dspriteinterval_t;
+
+typedef enum { SPR_SINGLE=0, SPR_GROUP } spriteframetype_t;
+
+typedef struct {
+	spriteframetype_t	type;
+} dspriteframetype_t;
+
+#define IDSPRITEHEADER	(('P'<<24)+('S'<<16)+('D'<<8)+'I')
+														// little-endian "IDSP"
+
--- /dev/null
+++ b/QW/client/surf16.asm
@@ -1,0 +1,458 @@
+ .386P
+ .model FLAT
+ externdef _d_zistepu:dword
+ externdef _d_pzbuffer:dword
+ externdef _d_zistepv:dword
+ externdef _d_zrowbytes:dword
+ externdef _d_ziorigin:dword
+ externdef _r_turb_s:dword
+ externdef _r_turb_t:dword
+ externdef _r_turb_pdest:dword
+ externdef _r_turb_spancount:dword
+ externdef _r_turb_turb:dword
+ externdef _r_turb_pbase:dword
+ externdef _r_turb_sstep:dword
+ externdef _r_turb_tstep:dword
+ externdef _r_bmodelactive:dword
+ externdef _d_sdivzstepu:dword
+ externdef _d_tdivzstepu:dword
+ externdef _d_sdivzstepv:dword
+ externdef _d_tdivzstepv:dword
+ externdef _d_sdivzorigin:dword
+ externdef _d_tdivzorigin:dword
+ externdef _sadjust:dword
+ externdef _tadjust:dword
+ externdef _bbextents:dword
+ externdef _bbextentt:dword
+ externdef _cacheblock:dword
+ externdef _d_viewbuffer:dword
+ externdef _cachewidth:dword
+ externdef _d_pzbuffer:dword
+ externdef _d_zrowbytes:dword
+ externdef _d_zwidth:dword
+ externdef _d_scantable:dword
+ externdef _r_lightptr:dword
+ externdef _r_numvblocks:dword
+ externdef _prowdestbase:dword
+ externdef _pbasesource:dword
+ externdef _r_lightwidth:dword
+ externdef _lightright:dword
+ externdef _lightrightstep:dword
+ externdef _lightdeltastep:dword
+ externdef _lightdelta:dword
+ externdef _lightright:dword
+ externdef _lightdelta:dword
+ externdef _sourcetstep:dword
+ externdef _surfrowbytes:dword
+ externdef _lightrightstep:dword
+ externdef _lightdeltastep:dword
+ externdef _r_sourcemax:dword
+ externdef _r_stepback:dword
+ externdef _colormap:dword
+ externdef _blocksize:dword
+ externdef _sourcesstep:dword
+ externdef _lightleft:dword
+ externdef _blockdivshift:dword
+ externdef _blockdivmask:dword
+ externdef _lightleftstep:dword
+ externdef _r_origin:dword
+ externdef _r_ppn:dword
+ externdef _r_pup:dword
+ externdef _r_pright:dword
+ externdef _ycenter:dword
+ externdef _xcenter:dword
+ externdef _d_vrectbottom_particle:dword
+ externdef _d_vrectright_particle:dword
+ externdef _d_vrecty:dword
+ externdef _d_vrectx:dword
+ externdef _d_pix_shift:dword
+ externdef _d_pix_min:dword
+ externdef _d_pix_max:dword
+ externdef _d_y_aspect_shift:dword
+ externdef _screenwidth:dword
+ externdef _vright:dword
+ externdef _vup:dword
+ externdef _vpn:dword
+ externdef _BOPS_Error:dword
+ externdef _snd_scaletable:dword
+ externdef _paintbuffer:dword
+ externdef _snd_linear_count:dword
+ externdef _snd_p:dword
+ externdef _snd_vol:dword
+ externdef _snd_out:dword
+ externdef _r_leftclipped:dword
+ externdef _r_leftenter:dword
+ externdef _r_rightclipped:dword
+ externdef _r_rightenter:dword
+ externdef _modelorg:dword
+ externdef _xscale:dword
+ externdef _r_refdef:dword
+ externdef _yscale:dword
+ externdef _r_leftexit:dword
+ externdef _r_rightexit:dword
+ externdef _r_lastvertvalid:dword
+ externdef _cacheoffset:dword
+ externdef _newedges:dword
+ externdef _removeedges:dword
+ externdef _r_pedge:dword
+ externdef _r_framecount:dword
+ externdef _r_u1:dword
+ externdef _r_emitted:dword
+ externdef _edge_p:dword
+ externdef _surface_p:dword
+ externdef _surfaces:dword
+ externdef _r_lzi1:dword
+ externdef _r_v1:dword
+ externdef _r_ceilv1:dword
+ externdef _r_nearzi:dword
+ externdef _r_nearzionly:dword
+ externdef _edge_aftertail:dword
+ externdef _edge_tail:dword
+ externdef _current_iv:dword
+ externdef _edge_head_u_shift20:dword
+ externdef _span_p:dword
+ externdef _edge_head:dword
+ externdef _fv:dword
+ externdef _edge_tail_u_shift20:dword
+ externdef _r_apverts:dword
+ externdef _r_anumverts:dword
+ externdef _aliastransform:dword
+ externdef _r_avertexnormals:dword
+ externdef _r_plightvec:dword
+ externdef _r_ambientlight:dword
+ externdef _r_shadelight:dword
+ externdef _aliasxcenter:dword
+ externdef _aliasycenter:dword
+ externdef _a_sstepxfrac:dword
+ externdef _r_affinetridesc:dword
+ externdef _acolormap:dword
+ externdef _d_pcolormap:dword
+ externdef _r_affinetridesc:dword
+ externdef _d_sfrac:dword
+ externdef _d_ptex:dword
+ externdef _d_pedgespanpackage:dword
+ externdef _d_tfrac:dword
+ externdef _d_light:dword
+ externdef _d_zi:dword
+ externdef _d_pdest:dword
+ externdef _d_pz:dword
+ externdef _d_aspancount:dword
+ externdef _erroradjustup:dword
+ externdef _errorterm:dword
+ externdef _d_xdenom:dword
+ externdef _r_p0:dword
+ externdef _r_p1:dword
+ externdef _r_p2:dword
+ externdef _a_tstepxfrac:dword
+ externdef _r_sstepx:dword
+ externdef _r_tstepx:dword
+ externdef _a_ststepxwhole:dword
+ externdef _zspantable:dword
+ externdef _skintable:dword
+ externdef _r_zistepx:dword
+ externdef _erroradjustdown:dword
+ externdef _d_countextrastep:dword
+ externdef _ubasestep:dword
+ externdef _a_ststepxwhole:dword
+ externdef _a_tstepxfrac:dword
+ externdef _r_lstepx:dword
+ externdef _a_spans:dword
+ externdef _erroradjustdown:dword
+ externdef _d_pdestextrastep:dword
+ externdef _d_pzextrastep:dword
+ externdef _d_sfracextrastep:dword
+ externdef _d_ptexextrastep:dword
+ externdef _d_countextrastep:dword
+ externdef _d_tfracextrastep:dword
+ externdef _d_lightextrastep:dword
+ externdef _d_ziextrastep:dword
+ externdef _d_pdestbasestep:dword
+ externdef _d_pzbasestep:dword
+ externdef _d_sfracbasestep:dword
+ externdef _d_ptexbasestep:dword
+ externdef _ubasestep:dword
+ externdef _d_tfracbasestep:dword
+ externdef _d_lightbasestep:dword
+ externdef _d_zibasestep:dword
+ externdef _zspantable:dword
+ externdef _r_lstepy:dword
+ externdef _r_sstepy:dword
+ externdef _r_tstepy:dword
+ externdef _r_zistepy:dword
+ externdef _D_PolysetSetEdgeTable:dword
+ externdef _D_RasterizeAliasPolySmooth:dword
+ externdef float_point5:dword
+ externdef Float2ToThe31nd:dword
+ externdef izistep:dword
+ externdef izi:dword
+ externdef FloatMinus2ToThe31nd:dword
+ externdef float_1:dword
+ externdef float_particle_z_clip:dword
+ externdef float_minus_1:dword
+ externdef float_0:dword
+ externdef fp_16:dword
+ externdef fp_64k:dword
+ externdef fp_1m:dword
+ externdef fp_1m_minus_1:dword
+ externdef fp_8:dword
+ externdef entryvec_table:dword
+ externdef advancetable:dword
+ externdef sstep:dword
+ externdef tstep:dword
+ externdef pspantemp:dword
+ externdef counttemp:dword
+ externdef jumptemp:dword
+ externdef reciprocal_table:dword
+ externdef DP_Count:dword
+ externdef DP_u:dword
+ externdef DP_v:dword
+ externdef DP_32768:dword
+ externdef DP_Color:dword
+ externdef DP_Pix:dword
+ externdef DP_EntryTable:dword
+ externdef pbase:dword
+ externdef s:dword
+ externdef t:dword
+ externdef sfracf:dword
+ externdef tfracf:dword
+ externdef snext:dword
+ externdef tnext:dword
+ externdef spancountminus1:dword
+ externdef zi16stepu:dword
+ externdef sdivz16stepu:dword
+ externdef tdivz16stepu:dword
+ externdef zi8stepu:dword
+ externdef sdivz8stepu:dword
+ externdef tdivz8stepu:dword
+ externdef reciprocal_table_16:dword
+ externdef entryvec_table_16:dword
+ externdef ceil_cw:dword
+ externdef single_cw:dword
+ externdef fp_64kx64k:dword
+ externdef pz:dword
+ externdef spr8entryvec_table:dword
+_DATA SEGMENT
+k dd 0
+loopentry dd 0
+ align 4
+blockjumptable16:
+ dd LEnter2_16
+ dd LEnter4_16
+ dd 0, LEnter8_16
+ dd 0, 0, 0, LEnter16_16
+_DATA ENDS
+_TEXT SEGMENT
+ align 4
+ public _R_Surf16Start
+_R_Surf16Start:
+ align 4
+ public _R_DrawSurfaceBlock16
+_R_DrawSurfaceBlock16:
+ push ebp
+ push edi
+ push esi
+ push ebx
+ mov eax,ds:dword ptr[_blocksize]
+ mov edi,ds:dword ptr[_prowdestbase]
+ mov esi,ds:dword ptr[_pbasesource]
+ mov ebx,ds:dword ptr[_sourcesstep]
+ mov ecx,ds:dword ptr[blockjumptable16-4+eax*2]
+ mov ds:dword ptr[k],eax
+ mov ds:dword ptr[loopentry],ecx
+ mov edx,ds:dword ptr[_lightleft]
+ mov ebp,ds:dword ptr[_lightright]
+Lblockloop16:
+ sub ebp,edx
+ mov cl,ds:byte ptr[_blockdivshift]
+ sar ebp,cl
+ jns Lp1_16
+ test ebp,ds:dword ptr[_blockdivmask]
+ jz Lp1_16
+ inc ebp
+Lp1_16:
+ sub eax,eax
+ sub ecx,ecx
+ jmp dword ptr[loopentry]
+ align 4
+LEnter16_16:
+ mov al,ds:byte ptr[esi]
+ mov cl,ds:byte ptr[esi+ebx]
+ mov ah,dh
+ add edx,ebp
+ mov ch,dh
+ lea esi,ds:dword ptr[esi+ebx*2]
+ mov ax,ds:word ptr[12345678h+eax*2]
+LBPatch0:
+ add edx,ebp
+ mov ds:word ptr[edi],ax
+ mov cx,ds:word ptr[12345678h+ecx*2]
+LBPatch1:
+ mov ds:word ptr[2+edi],cx
+ add edi,04h
+ mov al,ds:byte ptr[esi]
+ mov cl,ds:byte ptr[esi+ebx]
+ mov ah,dh
+ add edx,ebp
+ mov ch,dh
+ lea esi,ds:dword ptr[esi+ebx*2]
+ mov ax,ds:word ptr[12345678h+eax*2]
+LBPatch2:
+ add edx,ebp
+ mov ds:word ptr[edi],ax
+ mov cx,ds:word ptr[12345678h+ecx*2]
+LBPatch3:
+ mov ds:word ptr[2+edi],cx
+ add edi,04h
+ mov al,ds:byte ptr[esi]
+ mov cl,ds:byte ptr[esi+ebx]
+ mov ah,dh
+ add edx,ebp
+ mov ch,dh
+ lea esi,ds:dword ptr[esi+ebx*2]
+ mov ax,ds:word ptr[12345678h+eax*2]
+LBPatch4:
+ add edx,ebp
+ mov ds:word ptr[edi],ax
+ mov cx,ds:word ptr[12345678h+ecx*2]
+LBPatch5:
+ mov ds:word ptr[2+edi],cx
+ add edi,04h
+ mov al,ds:byte ptr[esi]
+ mov cl,ds:byte ptr[esi+ebx]
+ mov ah,dh
+ add edx,ebp
+ mov ch,dh
+ lea esi,ds:dword ptr[esi+ebx*2]
+ mov ax,ds:word ptr[12345678h+eax*2]
+LBPatch6:
+ add edx,ebp
+ mov ds:word ptr[edi],ax
+ mov cx,ds:word ptr[12345678h+ecx*2]
+LBPatch7:
+ mov ds:word ptr[2+edi],cx
+ add edi,04h
+LEnter8_16:
+ mov al,ds:byte ptr[esi]
+ mov cl,ds:byte ptr[esi+ebx]
+ mov ah,dh
+ add edx,ebp
+ mov ch,dh
+ lea esi,ds:dword ptr[esi+ebx*2]
+ mov ax,ds:word ptr[12345678h+eax*2]
+LBPatch8:
+ add edx,ebp
+ mov ds:word ptr[edi],ax
+ mov cx,ds:word ptr[12345678h+ecx*2]
+LBPatch9:
+ mov ds:word ptr[2+edi],cx
+ add edi,04h
+ mov al,ds:byte ptr[esi]
+ mov cl,ds:byte ptr[esi+ebx]
+ mov ah,dh
+ add edx,ebp
+ mov ch,dh
+ lea esi,ds:dword ptr[esi+ebx*2]
+ mov ax,ds:word ptr[12345678h+eax*2]
+LBPatch10:
+ add edx,ebp
+ mov ds:word ptr[edi],ax
+ mov cx,ds:word ptr[12345678h+ecx*2]
+LBPatch11:
+ mov ds:word ptr[2+edi],cx
+ add edi,04h
+LEnter4_16:
+ mov al,ds:byte ptr[esi]
+ mov cl,ds:byte ptr[esi+ebx]
+ mov ah,dh
+ add edx,ebp
+ mov ch,dh
+ lea esi,ds:dword ptr[esi+ebx*2]
+ mov ax,ds:word ptr[12345678h+eax*2]
+LBPatch12:
+ add edx,ebp
+ mov ds:word ptr[edi],ax
+ mov cx,ds:word ptr[12345678h+ecx*2]
+LBPatch13:
+ mov ds:word ptr[2+edi],cx
+ add edi,04h
+LEnter2_16:
+ mov al,ds:byte ptr[esi]
+ mov cl,ds:byte ptr[esi+ebx]
+ mov ah,dh
+ add edx,ebp
+ mov ch,dh
+ lea esi,ds:dword ptr[esi+ebx*2]
+ mov ax,ds:word ptr[12345678h+eax*2]
+LBPatch14:
+ add edx,ebp
+ mov ds:word ptr[edi],ax
+ mov cx,ds:word ptr[12345678h+ecx*2]
+LBPatch15:
+ mov ds:word ptr[2+edi],cx
+ add edi,04h
+ mov esi,ds:dword ptr[_pbasesource]
+ mov edx,ds:dword ptr[_lightleft]
+ mov ebp,ds:dword ptr[_lightright]
+ mov eax,ds:dword ptr[_sourcetstep]
+ mov ecx,ds:dword ptr[_lightrightstep]
+ mov edi,ds:dword ptr[_prowdestbase]
+ add esi,eax
+ add ebp,ecx
+ mov eax,ds:dword ptr[_lightleftstep]
+ mov ecx,ds:dword ptr[_surfrowbytes]
+ add edx,eax
+ add edi,ecx
+ mov ds:dword ptr[_pbasesource],esi
+ mov ds:dword ptr[_lightright],ebp
+ mov eax,ds:dword ptr[k]
+ mov ds:dword ptr[_lightleft],edx
+ dec eax
+ mov ds:dword ptr[_prowdestbase],edi
+ mov ds:dword ptr[k],eax
+ jnz Lblockloop16
+ pop ebx
+ pop esi
+ pop edi
+ pop ebp
+ ret
+ public _R_Surf16End
+_R_Surf16End:
+_TEXT ENDS
+_DATA SEGMENT
+ align 4
+LPatchTable16:
+ dd LBPatch0-4
+ dd LBPatch1-4
+ dd LBPatch2-4
+ dd LBPatch3-4
+ dd LBPatch4-4
+ dd LBPatch5-4
+ dd LBPatch6-4
+ dd LBPatch7-4
+ dd LBPatch8-4
+ dd LBPatch9-4
+ dd LBPatch10-4
+ dd LBPatch11-4
+ dd LBPatch12-4
+ dd LBPatch13-4
+ dd LBPatch14-4
+ dd LBPatch15-4
+_DATA ENDS
+_TEXT SEGMENT
+ align 4
+ public _R_Surf16Patch
+_R_Surf16Patch:
+ push ebx
+ mov eax,ds:dword ptr[_colormap]
+ mov ebx,offset LPatchTable16
+ mov ecx,16
+LPatchLoop16:
+ mov edx,ds:dword ptr[ebx]
+ add ebx,4
+ mov ds:dword ptr[edx],eax
+ dec ecx
+ jnz LPatchLoop16
+ pop ebx
+ ret
+_TEXT ENDS
+ END
--- /dev/null
+++ b/QW/client/surf16.s
@@ -1,0 +1,172 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+//
+// surf16.s
+// x86 assembly-language 16 bpp surface block drawing code.
+//
+
+#include "asm_i386.h"
+#include "quakeasm.h"
+#include "asm_draw.h"
+
+#if id386
+
+//----------------------------------------------------------------------
+// Surface block drawer
+//----------------------------------------------------------------------
+
+	.data
+
+k:			.long	0
+loopentry:	.long	0
+
+	.align	4
+blockjumptable16:
+	.long	LEnter2_16
+	.long	LEnter4_16
+	.long	0, LEnter8_16
+	.long	0, 0, 0, LEnter16_16
+
+
+	.text
+
+	.align 4
+.globl C(R_Surf16Start)
+C(R_Surf16Start):
+
+	.align 4
+.globl C(R_DrawSurfaceBlock16)
+C(R_DrawSurfaceBlock16):
+	pushl	%ebp				// preserve caller's stack frame
+	pushl	%edi
+	pushl	%esi				// preserve register variables
+	pushl	%ebx
+
+	movl	C(blocksize),%eax
+	movl	C(prowdestbase),%edi
+	movl	C(pbasesource),%esi
+	movl	C(sourcesstep),%ebx
+	movl	blockjumptable16-4(,%eax,2),%ecx
+	movl	%eax,k
+	movl	%ecx,loopentry
+	movl	C(lightleft),%edx
+	movl	C(lightright),%ebp
+
+Lblockloop16:
+
+	subl	%edx,%ebp
+	movb	C(blockdivshift),%cl
+	sarl	%cl,%ebp
+	jns		Lp1_16
+	testl	C(blockdivmask),%ebp
+	jz		Lp1_16
+	incl	%ebp
+Lp1_16:
+
+	subl	%eax,%eax
+	subl	%ecx,%ecx	// high words must be 0 in loop for addressing
+
+	jmp		*loopentry
+
+	.align	4
+
+#include "block16.h"
+
+	movl	C(pbasesource),%esi
+	movl	C(lightleft),%edx
+	movl	C(lightright),%ebp
+	movl	C(sourcetstep),%eax
+	movl	C(lightrightstep),%ecx
+	movl	C(prowdestbase),%edi
+
+	addl	%eax,%esi
+	addl	%ecx,%ebp
+
+	movl	C(lightleftstep),%eax
+	movl	C(surfrowbytes),%ecx
+
+	addl	%eax,%edx
+	addl	%ecx,%edi
+
+	movl	%esi,C(pbasesource)
+	movl	%ebp,C(lightright)
+	movl	k,%eax
+	movl	%edx,C(lightleft)
+	decl	%eax
+	movl	%edi,C(prowdestbase)
+	movl	%eax,k
+	jnz		Lblockloop16
+
+	popl	%ebx				// restore register variables
+	popl	%esi
+	popl	%edi
+	popl	%ebp				// restore the caller's stack frame
+	ret
+
+.globl C(R_Surf16End)
+C(R_Surf16End):
+
+//----------------------------------------------------------------------
+// Code patching routines
+//----------------------------------------------------------------------
+	.data
+
+	.align 4
+LPatchTable16:
+	.long	LBPatch0-4
+	.long	LBPatch1-4
+	.long	LBPatch2-4
+	.long	LBPatch3-4
+	.long	LBPatch4-4
+	.long	LBPatch5-4
+	.long	LBPatch6-4
+	.long	LBPatch7-4
+	.long	LBPatch8-4
+	.long	LBPatch9-4
+	.long	LBPatch10-4
+	.long	LBPatch11-4
+	.long	LBPatch12-4
+	.long	LBPatch13-4
+	.long	LBPatch14-4
+	.long	LBPatch15-4
+
+	.text
+
+	.align 4
+.globl C(R_Surf16Patch)
+C(R_Surf16Patch):
+	pushl	%ebx
+
+	movl	C(colormap),%eax
+	movl	$LPatchTable16,%ebx
+	movl	$16,%ecx
+LPatchLoop16:
+	movl	(%ebx),%edx
+	addl	$4,%ebx
+	movl	%eax,(%edx)
+	decl	%ecx
+	jnz		LPatchLoop16
+
+	popl	%ebx
+
+	ret
+
+
+#endif	// id386
--- /dev/null
+++ b/QW/client/surf8.asm
@@ -1,0 +1,719 @@
+ .386P
+ .model FLAT
+ externdef _d_zistepu:dword
+ externdef _d_pzbuffer:dword
+ externdef _d_zistepv:dword
+ externdef _d_zrowbytes:dword
+ externdef _d_ziorigin:dword
+ externdef _r_turb_s:dword
+ externdef _r_turb_t:dword
+ externdef _r_turb_pdest:dword
+ externdef _r_turb_spancount:dword
+ externdef _r_turb_turb:dword
+ externdef _r_turb_pbase:dword
+ externdef _r_turb_sstep:dword
+ externdef _r_turb_tstep:dword
+ externdef _r_bmodelactive:dword
+ externdef _d_sdivzstepu:dword
+ externdef _d_tdivzstepu:dword
+ externdef _d_sdivzstepv:dword
+ externdef _d_tdivzstepv:dword
+ externdef _d_sdivzorigin:dword
+ externdef _d_tdivzorigin:dword
+ externdef _sadjust:dword
+ externdef _tadjust:dword
+ externdef _bbextents:dword
+ externdef _bbextentt:dword
+ externdef _cacheblock:dword
+ externdef _d_viewbuffer:dword
+ externdef _cachewidth:dword
+ externdef _d_pzbuffer:dword
+ externdef _d_zrowbytes:dword
+ externdef _d_zwidth:dword
+ externdef _d_scantable:dword
+ externdef _r_lightptr:dword
+ externdef _r_numvblocks:dword
+ externdef _prowdestbase:dword
+ externdef _pbasesource:dword
+ externdef _r_lightwidth:dword
+ externdef _lightright:dword
+ externdef _lightrightstep:dword
+ externdef _lightdeltastep:dword
+ externdef _lightdelta:dword
+ externdef _lightright:dword
+ externdef _lightdelta:dword
+ externdef _sourcetstep:dword
+ externdef _surfrowbytes:dword
+ externdef _lightrightstep:dword
+ externdef _lightdeltastep:dword
+ externdef _r_sourcemax:dword
+ externdef _r_stepback:dword
+ externdef _colormap:dword
+ externdef _blocksize:dword
+ externdef _sourcesstep:dword
+ externdef _lightleft:dword
+ externdef _blockdivshift:dword
+ externdef _blockdivmask:dword
+ externdef _lightleftstep:dword
+ externdef _r_origin:dword
+ externdef _r_ppn:dword
+ externdef _r_pup:dword
+ externdef _r_pright:dword
+ externdef _ycenter:dword
+ externdef _xcenter:dword
+ externdef _d_vrectbottom_particle:dword
+ externdef _d_vrectright_particle:dword
+ externdef _d_vrecty:dword
+ externdef _d_vrectx:dword
+ externdef _d_pix_shift:dword
+ externdef _d_pix_min:dword
+ externdef _d_pix_max:dword
+ externdef _d_y_aspect_shift:dword
+ externdef _screenwidth:dword
+ externdef _vright:dword
+ externdef _vup:dword
+ externdef _vpn:dword
+ externdef _BOPS_Error:dword
+ externdef _snd_scaletable:dword
+ externdef _paintbuffer:dword
+ externdef _snd_linear_count:dword
+ externdef _snd_p:dword
+ externdef _snd_vol:dword
+ externdef _snd_out:dword
+ externdef _r_leftclipped:dword
+ externdef _r_leftenter:dword
+ externdef _r_rightclipped:dword
+ externdef _r_rightenter:dword
+ externdef _modelorg:dword
+ externdef _xscale:dword
+ externdef _r_refdef:dword
+ externdef _yscale:dword
+ externdef _r_leftexit:dword
+ externdef _r_rightexit:dword
+ externdef _r_lastvertvalid:dword
+ externdef _cacheoffset:dword
+ externdef _newedges:dword
+ externdef _removeedges:dword
+ externdef _r_pedge:dword
+ externdef _r_framecount:dword
+ externdef _r_u1:dword
+ externdef _r_emitted:dword
+ externdef _edge_p:dword
+ externdef _surface_p:dword
+ externdef _surfaces:dword
+ externdef _r_lzi1:dword
+ externdef _r_v1:dword
+ externdef _r_ceilv1:dword
+ externdef _r_nearzi:dword
+ externdef _r_nearzionly:dword
+ externdef _edge_aftertail:dword
+ externdef _edge_tail:dword
+ externdef _current_iv:dword
+ externdef _edge_head_u_shift20:dword
+ externdef _span_p:dword
+ externdef _edge_head:dword
+ externdef _fv:dword
+ externdef _edge_tail_u_shift20:dword
+ externdef _r_apverts:dword
+ externdef _r_anumverts:dword
+ externdef _aliastransform:dword
+ externdef _r_avertexnormals:dword
+ externdef _r_plightvec:dword
+ externdef _r_ambientlight:dword
+ externdef _r_shadelight:dword
+ externdef _aliasxcenter:dword
+ externdef _aliasycenter:dword
+ externdef _a_sstepxfrac:dword
+ externdef _r_affinetridesc:dword
+ externdef _acolormap:dword
+ externdef _d_pcolormap:dword
+ externdef _r_affinetridesc:dword
+ externdef _d_sfrac:dword
+ externdef _d_ptex:dword
+ externdef _d_pedgespanpackage:dword
+ externdef _d_tfrac:dword
+ externdef _d_light:dword
+ externdef _d_zi:dword
+ externdef _d_pdest:dword
+ externdef _d_pz:dword
+ externdef _d_aspancount:dword
+ externdef _erroradjustup:dword
+ externdef _errorterm:dword
+ externdef _d_xdenom:dword
+ externdef _r_p0:dword
+ externdef _r_p1:dword
+ externdef _r_p2:dword
+ externdef _a_tstepxfrac:dword
+ externdef _r_sstepx:dword
+ externdef _r_tstepx:dword
+ externdef _a_ststepxwhole:dword
+ externdef _zspantable:dword
+ externdef _skintable:dword
+ externdef _r_zistepx:dword
+ externdef _erroradjustdown:dword
+ externdef _d_countextrastep:dword
+ externdef _ubasestep:dword
+ externdef _a_ststepxwhole:dword
+ externdef _a_tstepxfrac:dword
+ externdef _r_lstepx:dword
+ externdef _a_spans:dword
+ externdef _erroradjustdown:dword
+ externdef _d_pdestextrastep:dword
+ externdef _d_pzextrastep:dword
+ externdef _d_sfracextrastep:dword
+ externdef _d_ptexextrastep:dword
+ externdef _d_countextrastep:dword
+ externdef _d_tfracextrastep:dword
+ externdef _d_lightextrastep:dword
+ externdef _d_ziextrastep:dword
+ externdef _d_pdestbasestep:dword
+ externdef _d_pzbasestep:dword
+ externdef _d_sfracbasestep:dword
+ externdef _d_ptexbasestep:dword
+ externdef _ubasestep:dword
+ externdef _d_tfracbasestep:dword
+ externdef _d_lightbasestep:dword
+ externdef _d_zibasestep:dword
+ externdef _zspantable:dword
+ externdef _r_lstepy:dword
+ externdef _r_sstepy:dword
+ externdef _r_tstepy:dword
+ externdef _r_zistepy:dword
+ externdef _D_PolysetSetEdgeTable:dword
+ externdef _D_RasterizeAliasPolySmooth:dword
+ externdef float_point5:dword
+ externdef Float2ToThe31nd:dword
+ externdef izistep:dword
+ externdef izi:dword
+ externdef FloatMinus2ToThe31nd:dword
+ externdef float_1:dword
+ externdef float_particle_z_clip:dword
+ externdef float_minus_1:dword
+ externdef float_0:dword
+ externdef fp_16:dword
+ externdef fp_64k:dword
+ externdef fp_1m:dword
+ externdef fp_1m_minus_1:dword
+ externdef fp_8:dword
+ externdef entryvec_table:dword
+ externdef advancetable:dword
+ externdef sstep:dword
+ externdef tstep:dword
+ externdef pspantemp:dword
+ externdef counttemp:dword
+ externdef jumptemp:dword
+ externdef reciprocal_table:dword
+ externdef DP_Count:dword
+ externdef DP_u:dword
+ externdef DP_v:dword
+ externdef DP_32768:dword
+ externdef DP_Color:dword
+ externdef DP_Pix:dword
+ externdef DP_EntryTable:dword
+ externdef pbase:dword
+ externdef s:dword
+ externdef t:dword
+ externdef sfracf:dword
+ externdef tfracf:dword
+ externdef snext:dword
+ externdef tnext:dword
+ externdef spancountminus1:dword
+ externdef zi16stepu:dword
+ externdef sdivz16stepu:dword
+ externdef tdivz16stepu:dword
+ externdef zi8stepu:dword
+ externdef sdivz8stepu:dword
+ externdef tdivz8stepu:dword
+ externdef reciprocal_table_16:dword
+ externdef entryvec_table_16:dword
+ externdef ceil_cw:dword
+ externdef single_cw:dword
+ externdef fp_64kx64k:dword
+ externdef pz:dword
+ externdef spr8entryvec_table:dword
+_DATA SEGMENT
+sb_v dd 0
+_DATA ENDS
+_TEXT SEGMENT
+ align 4
+ public _R_Surf8Start
+_R_Surf8Start:
+ align 4
+ public _R_DrawSurfaceBlock8_mip0
+_R_DrawSurfaceBlock8_mip0:
+ push ebp
+ push edi
+ push esi
+ push ebx
+ mov ebx,ds:dword ptr[_r_lightptr]
+ mov eax,ds:dword ptr[_r_numvblocks]
+ mov ds:dword ptr[sb_v],eax
+ mov edi,ds:dword ptr[_prowdestbase]
+ mov esi,ds:dword ptr[_pbasesource]
+Lv_loop_mip0:
+ mov eax,ds:dword ptr[ebx]
+ mov edx,ds:dword ptr[4+ebx]
+ mov ebp,eax
+ mov ecx,ds:dword ptr[_r_lightwidth]
+ mov ds:dword ptr[_lightright],edx
+ sub ebp,edx
+ and ebp,0FFFFFh
+ lea ebx,ds:dword ptr[ebx+ecx*4]
+ mov ds:dword ptr[_r_lightptr],ebx
+ mov ecx,ds:dword ptr[4+ebx]
+ mov ebx,ds:dword ptr[ebx]
+ sub ebx,eax
+ sub ecx,edx
+ sar ecx,4
+ or ebp,0F0000000h
+ sar ebx,4
+ mov ds:dword ptr[_lightrightstep],ecx
+ sub ebx,ecx
+ and ebx,0FFFFFh
+ or ebx,0F0000000h
+ sub ecx,ecx
+ mov ds:dword ptr[_lightdeltastep],ebx
+ sub ebx,ebx
+Lblockloop8_mip0:
+ mov ds:dword ptr[_lightdelta],ebp
+ mov cl,ds:byte ptr[14+esi]
+ sar ebp,4
+ mov bh,dh
+ mov bl,ds:byte ptr[15+esi]
+ add edx,ebp
+ mov ch,dh
+ add edx,ebp
+ mov ah,ds:byte ptr[12345678h+ebx]
+LBPatch0:
+ mov bl,ds:byte ptr[13+esi]
+ mov al,ds:byte ptr[12345678h+ecx]
+LBPatch1:
+ mov cl,ds:byte ptr[12+esi]
+ mov bh,dh
+ add edx,ebp
+ ror eax,16
+ mov ch,dh
+ add edx,ebp
+ mov ah,ds:byte ptr[12345678h+ebx]
+LBPatch2:
+ mov bl,ds:byte ptr[11+esi]
+ mov al,ds:byte ptr[12345678h+ecx]
+LBPatch3:
+ mov cl,ds:byte ptr[10+esi]
+ mov ds:dword ptr[12+edi],eax
+ mov bh,dh
+ add edx,ebp
+ mov ch,dh
+ add edx,ebp
+ mov ah,ds:byte ptr[12345678h+ebx]
+LBPatch4:
+ mov bl,ds:byte ptr[9+esi]
+ mov al,ds:byte ptr[12345678h+ecx]
+LBPatch5:
+ mov cl,ds:byte ptr[8+esi]
+ mov bh,dh
+ add edx,ebp
+ ror eax,16
+ mov ch,dh
+ add edx,ebp
+ mov ah,ds:byte ptr[12345678h+ebx]
+LBPatch6:
+ mov bl,ds:byte ptr[7+esi]
+ mov al,ds:byte ptr[12345678h+ecx]
+LBPatch7:
+ mov cl,ds:byte ptr[6+esi]
+ mov ds:dword ptr[8+edi],eax
+ mov bh,dh
+ add edx,ebp
+ mov ch,dh
+ add edx,ebp
+ mov ah,ds:byte ptr[12345678h+ebx]
+LBPatch8:
+ mov bl,ds:byte ptr[5+esi]
+ mov al,ds:byte ptr[12345678h+ecx]
+LBPatch9:
+ mov cl,ds:byte ptr[4+esi]
+ mov bh,dh
+ add edx,ebp
+ ror eax,16
+ mov ch,dh
+ add edx,ebp
+ mov ah,ds:byte ptr[12345678h+ebx]
+LBPatch10:
+ mov bl,ds:byte ptr[3+esi]
+ mov al,ds:byte ptr[12345678h+ecx]
+LBPatch11:
+ mov cl,ds:byte ptr[2+esi]
+ mov ds:dword ptr[4+edi],eax
+ mov bh,dh
+ add edx,ebp
+ mov ch,dh
+ add edx,ebp
+ mov ah,ds:byte ptr[12345678h+ebx]
+LBPatch12:
+ mov bl,ds:byte ptr[1+esi]
+ mov al,ds:byte ptr[12345678h+ecx]
+LBPatch13:
+ mov cl,ds:byte ptr[esi]
+ mov bh,dh
+ add edx,ebp
+ ror eax,16
+ mov ch,dh
+ mov ah,ds:byte ptr[12345678h+ebx]
+LBPatch14:
+ mov edx,ds:dword ptr[_lightright]
+ mov al,ds:byte ptr[12345678h+ecx]
+LBPatch15:
+ mov ebp,ds:dword ptr[_lightdelta]
+ mov ds:dword ptr[edi],eax
+ add esi,ds:dword ptr[_sourcetstep]
+ add edi,ds:dword ptr[_surfrowbytes]
+ add edx,ds:dword ptr[_lightrightstep]
+ add ebp,ds:dword ptr[_lightdeltastep]
+ mov ds:dword ptr[_lightright],edx
+ jc Lblockloop8_mip0
+ cmp esi,ds:dword ptr[_r_sourcemax]
+ jb LSkip_mip0
+ sub esi,ds:dword ptr[_r_stepback]
+LSkip_mip0:
+ mov ebx,ds:dword ptr[_r_lightptr]
+ dec ds:dword ptr[sb_v]
+ jnz Lv_loop_mip0
+ pop ebx
+ pop esi
+ pop edi
+ pop ebp
+ ret
+ align 4
+ public _R_DrawSurfaceBlock8_mip1
+_R_DrawSurfaceBlock8_mip1:
+ push ebp
+ push edi
+ push esi
+ push ebx
+ mov ebx,ds:dword ptr[_r_lightptr]
+ mov eax,ds:dword ptr[_r_numvblocks]
+ mov ds:dword ptr[sb_v],eax
+ mov edi,ds:dword ptr[_prowdestbase]
+ mov esi,ds:dword ptr[_pbasesource]
+Lv_loop_mip1:
+ mov eax,ds:dword ptr[ebx]
+ mov edx,ds:dword ptr[4+ebx]
+ mov ebp,eax
+ mov ecx,ds:dword ptr[_r_lightwidth]
+ mov ds:dword ptr[_lightright],edx
+ sub ebp,edx
+ and ebp,0FFFFFh
+ lea ebx,ds:dword ptr[ebx+ecx*4]
+ mov ds:dword ptr[_r_lightptr],ebx
+ mov ecx,ds:dword ptr[4+ebx]
+ mov ebx,ds:dword ptr[ebx]
+ sub ebx,eax
+ sub ecx,edx
+ sar ecx,3
+ or ebp,070000000h
+ sar ebx,3
+ mov ds:dword ptr[_lightrightstep],ecx
+ sub ebx,ecx
+ and ebx,0FFFFFh
+ or ebx,0F0000000h
+ sub ecx,ecx
+ mov ds:dword ptr[_lightdeltastep],ebx
+ sub ebx,ebx
+Lblockloop8_mip1:
+ mov ds:dword ptr[_lightdelta],ebp
+ mov cl,ds:byte ptr[6+esi]
+ sar ebp,3
+ mov bh,dh
+ mov bl,ds:byte ptr[7+esi]
+ add edx,ebp
+ mov ch,dh
+ add edx,ebp
+ mov ah,ds:byte ptr[12345678h+ebx]
+LBPatch22:
+ mov bl,ds:byte ptr[5+esi]
+ mov al,ds:byte ptr[12345678h+ecx]
+LBPatch23:
+ mov cl,ds:byte ptr[4+esi]
+ mov bh,dh
+ add edx,ebp
+ ror eax,16
+ mov ch,dh
+ add edx,ebp
+ mov ah,ds:byte ptr[12345678h+ebx]
+LBPatch24:
+ mov bl,ds:byte ptr[3+esi]
+ mov al,ds:byte ptr[12345678h+ecx]
+LBPatch25:
+ mov cl,ds:byte ptr[2+esi]
+ mov ds:dword ptr[4+edi],eax
+ mov bh,dh
+ add edx,ebp
+ mov ch,dh
+ add edx,ebp
+ mov ah,ds:byte ptr[12345678h+ebx]
+LBPatch26:
+ mov bl,ds:byte ptr[1+esi]
+ mov al,ds:byte ptr[12345678h+ecx]
+LBPatch27:
+ mov cl,ds:byte ptr[esi]
+ mov bh,dh
+ add edx,ebp
+ ror eax,16
+ mov ch,dh
+ mov ah,ds:byte ptr[12345678h+ebx]
+LBPatch28:
+ mov edx,ds:dword ptr[_lightright]
+ mov al,ds:byte ptr[12345678h+ecx]
+LBPatch29:
+ mov ebp,ds:dword ptr[_lightdelta]
+ mov ds:dword ptr[edi],eax
+ mov eax,ds:dword ptr[_sourcetstep]
+ add esi,eax
+ mov eax,ds:dword ptr[_surfrowbytes]
+ add edi,eax
+ mov eax,ds:dword ptr[_lightrightstep]
+ add edx,eax
+ mov eax,ds:dword ptr[_lightdeltastep]
+ add ebp,eax
+ mov ds:dword ptr[_lightright],edx
+ jc Lblockloop8_mip1
+ cmp esi,ds:dword ptr[_r_sourcemax]
+ jb LSkip_mip1
+ sub esi,ds:dword ptr[_r_stepback]
+LSkip_mip1:
+ mov ebx,ds:dword ptr[_r_lightptr]
+ dec ds:dword ptr[sb_v]
+ jnz Lv_loop_mip1
+ pop ebx
+ pop esi
+ pop edi
+ pop ebp
+ ret
+ align 4
+ public _R_DrawSurfaceBlock8_mip2
+_R_DrawSurfaceBlock8_mip2:
+ push ebp
+ push edi
+ push esi
+ push ebx
+ mov ebx,ds:dword ptr[_r_lightptr]
+ mov eax,ds:dword ptr[_r_numvblocks]
+ mov ds:dword ptr[sb_v],eax
+ mov edi,ds:dword ptr[_prowdestbase]
+ mov esi,ds:dword ptr[_pbasesource]
+Lv_loop_mip2:
+ mov eax,ds:dword ptr[ebx]
+ mov edx,ds:dword ptr[4+ebx]
+ mov ebp,eax
+ mov ecx,ds:dword ptr[_r_lightwidth]
+ mov ds:dword ptr[_lightright],edx
+ sub ebp,edx
+ and ebp,0FFFFFh
+ lea ebx,ds:dword ptr[ebx+ecx*4]
+ mov ds:dword ptr[_r_lightptr],ebx
+ mov ecx,ds:dword ptr[4+ebx]
+ mov ebx,ds:dword ptr[ebx]
+ sub ebx,eax
+ sub ecx,edx
+ sar ecx,2
+ or ebp,030000000h
+ sar ebx,2
+ mov ds:dword ptr[_lightrightstep],ecx
+ sub ebx,ecx
+ and ebx,0FFFFFh
+ or ebx,0F0000000h
+ sub ecx,ecx
+ mov ds:dword ptr[_lightdeltastep],ebx
+ sub ebx,ebx
+Lblockloop8_mip2:
+ mov ds:dword ptr[_lightdelta],ebp
+ mov cl,ds:byte ptr[2+esi]
+ sar ebp,2
+ mov bh,dh
+ mov bl,ds:byte ptr[3+esi]
+ add edx,ebp
+ mov ch,dh
+ add edx,ebp
+ mov ah,ds:byte ptr[12345678h+ebx]
+LBPatch18:
+ mov bl,ds:byte ptr[1+esi]
+ mov al,ds:byte ptr[12345678h+ecx]
+LBPatch19:
+ mov cl,ds:byte ptr[esi]
+ mov bh,dh
+ add edx,ebp
+ ror eax,16
+ mov ch,dh
+ mov ah,ds:byte ptr[12345678h+ebx]
+LBPatch20:
+ mov edx,ds:dword ptr[_lightright]
+ mov al,ds:byte ptr[12345678h+ecx]
+LBPatch21:
+ mov ebp,ds:dword ptr[_lightdelta]
+ mov ds:dword ptr[edi],eax
+ mov eax,ds:dword ptr[_sourcetstep]
+ add esi,eax
+ mov eax,ds:dword ptr[_surfrowbytes]
+ add edi,eax
+ mov eax,ds:dword ptr[_lightrightstep]
+ add edx,eax
+ mov eax,ds:dword ptr[_lightdeltastep]
+ add ebp,eax
+ mov ds:dword ptr[_lightright],edx
+ jc Lblockloop8_mip2
+ cmp esi,ds:dword ptr[_r_sourcemax]
+ jb LSkip_mip2
+ sub esi,ds:dword ptr[_r_stepback]
+LSkip_mip2:
+ mov ebx,ds:dword ptr[_r_lightptr]
+ dec ds:dword ptr[sb_v]
+ jnz Lv_loop_mip2
+ pop ebx
+ pop esi
+ pop edi
+ pop ebp
+ ret
+ align 4
+ public _R_DrawSurfaceBlock8_mip3
+_R_DrawSurfaceBlock8_mip3:
+ push ebp
+ push edi
+ push esi
+ push ebx
+ mov ebx,ds:dword ptr[_r_lightptr]
+ mov eax,ds:dword ptr[_r_numvblocks]
+ mov ds:dword ptr[sb_v],eax
+ mov edi,ds:dword ptr[_prowdestbase]
+ mov esi,ds:dword ptr[_pbasesource]
+Lv_loop_mip3:
+ mov eax,ds:dword ptr[ebx]
+ mov edx,ds:dword ptr[4+ebx]
+ mov ebp,eax
+ mov ecx,ds:dword ptr[_r_lightwidth]
+ mov ds:dword ptr[_lightright],edx
+ sub ebp,edx
+ and ebp,0FFFFFh
+ lea ebx,ds:dword ptr[ebx+ecx*4]
+ mov ds:dword ptr[_lightdelta],ebp
+ mov ds:dword ptr[_r_lightptr],ebx
+ mov ecx,ds:dword ptr[4+ebx]
+ mov ebx,ds:dword ptr[ebx]
+ sub ebx,eax
+ sub ecx,edx
+ sar ecx,1
+ sar ebx,1
+ mov ds:dword ptr[_lightrightstep],ecx
+ sub ebx,ecx
+ and ebx,0FFFFFh
+ sar ebp,1
+ or ebx,0F0000000h
+ mov ds:dword ptr[_lightdeltastep],ebx
+ sub ebx,ebx
+ mov bl,ds:byte ptr[1+esi]
+ sub ecx,ecx
+ mov bh,dh
+ mov cl,ds:byte ptr[esi]
+ add edx,ebp
+ mov ch,dh
+ mov al,ds:byte ptr[12345678h+ebx]
+LBPatch16:
+ mov edx,ds:dword ptr[_lightright]
+ mov ds:byte ptr[1+edi],al
+ mov al,ds:byte ptr[12345678h+ecx]
+LBPatch17:
+ mov ds:byte ptr[edi],al
+ mov eax,ds:dword ptr[_sourcetstep]
+ add esi,eax
+ mov eax,ds:dword ptr[_surfrowbytes]
+ add edi,eax
+ mov eax,ds:dword ptr[_lightdeltastep]
+ mov ebp,ds:dword ptr[_lightdelta]
+ mov cl,ds:byte ptr[esi]
+ add ebp,eax
+ mov eax,ds:dword ptr[_lightrightstep]
+ sar ebp,1
+ add edx,eax
+ mov bh,dh
+ mov bl,ds:byte ptr[1+esi]
+ add edx,ebp
+ mov ch,dh
+ mov al,ds:byte ptr[12345678h+ebx]
+LBPatch30:
+ mov edx,ds:dword ptr[_sourcetstep]
+ mov ds:byte ptr[1+edi],al
+ mov al,ds:byte ptr[12345678h+ecx]
+LBPatch31:
+ mov ds:byte ptr[edi],al
+ mov ebp,ds:dword ptr[_surfrowbytes]
+ add esi,edx
+ add edi,ebp
+ cmp esi,ds:dword ptr[_r_sourcemax]
+ jb LSkip_mip3
+ sub esi,ds:dword ptr[_r_stepback]
+LSkip_mip3:
+ mov ebx,ds:dword ptr[_r_lightptr]
+ dec ds:dword ptr[sb_v]
+ jnz Lv_loop_mip3
+ pop ebx
+ pop esi
+ pop edi
+ pop ebp
+ ret
+ public _R_Surf8End
+_R_Surf8End:
+_TEXT ENDS
+_DATA SEGMENT
+ align 4
+LPatchTable8:
+ dd LBPatch0-4
+ dd LBPatch1-4
+ dd LBPatch2-4
+ dd LBPatch3-4
+ dd LBPatch4-4
+ dd LBPatch5-4
+ dd LBPatch6-4
+ dd LBPatch7-4
+ dd LBPatch8-4
+ dd LBPatch9-4
+ dd LBPatch10-4
+ dd LBPatch11-4
+ dd LBPatch12-4
+ dd LBPatch13-4
+ dd LBPatch14-4
+ dd LBPatch15-4
+ dd LBPatch16-4
+ dd LBPatch17-4
+ dd LBPatch18-4
+ dd LBPatch19-4
+ dd LBPatch20-4
+ dd LBPatch21-4
+ dd LBPatch22-4
+ dd LBPatch23-4
+ dd LBPatch24-4
+ dd LBPatch25-4
+ dd LBPatch26-4
+ dd LBPatch27-4
+ dd LBPatch28-4
+ dd LBPatch29-4
+ dd LBPatch30-4
+ dd LBPatch31-4
+_DATA ENDS
+_TEXT SEGMENT
+ align 4
+ public _R_Surf8Patch
+_R_Surf8Patch:
+ push ebx
+ mov eax,ds:dword ptr[_colormap]
+ mov ebx,offset LPatchTable8
+ mov ecx,32
+LPatchLoop8:
+ mov edx,ds:dword ptr[ebx]
+ add ebx,4
+ mov ds:dword ptr[edx],eax
+ dec ecx
+ jnz LPatchLoop8
+ pop ebx
+ ret
+_TEXT ENDS
+ END
--- /dev/null
+++ b/QW/client/surf8.s
@@ -1,0 +1,783 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+//
+// surf8.s
+// x86 assembly-language 8 bpp surface block drawing code.
+//
+
+#include "asm_i386.h"
+#include "quakeasm.h"
+#include "asm_draw.h"
+
+#if	id386
+
+	.data
+
+sb_v:		.long	0
+
+	.text
+
+	.align 4
+.globl C(R_Surf8Start)
+C(R_Surf8Start):
+
+//----------------------------------------------------------------------
+// Surface block drawer for mip level 0
+//----------------------------------------------------------------------
+
+	.align 4
+.globl C(R_DrawSurfaceBlock8_mip0)
+C(R_DrawSurfaceBlock8_mip0):
+	pushl	%ebp				// preserve caller's stack frame
+	pushl	%edi
+	pushl	%esi				// preserve register variables
+	pushl	%ebx
+
+//		for (v=0 ; v<numvblocks ; v++)
+//		{
+	movl	C(r_lightptr),%ebx
+	movl	C(r_numvblocks),%eax
+
+	movl	%eax,sb_v
+	movl	C(prowdestbase),%edi
+
+	movl	C(pbasesource),%esi
+
+Lv_loop_mip0:
+
+//			lightleft = lightptr[0];
+//			lightright = lightptr[1];
+//			lightdelta = (lightleft - lightright) & 0xFFFFF;
+	movl	(%ebx),%eax			// lightleft
+	movl	4(%ebx),%edx		// lightright
+
+	movl	%eax,%ebp
+	movl	C(r_lightwidth),%ecx
+
+	movl	%edx,C(lightright)
+	subl	%edx,%ebp
+
+	andl	$0xFFFFF,%ebp
+	leal	(%ebx,%ecx,4),%ebx
+
+//			lightptr += lightwidth;
+	movl	%ebx,C(r_lightptr)
+
+//			lightleftstep = (lightptr[0] - lightleft) >> blockdivshift;
+//			lightrightstep = (lightptr[1] - lightright) >> blockdivshift;
+//			lightdeltastep = ((lightleftstep - lightrightstep) & 0xFFFFF) |
+//					0xF0000000;
+	movl	4(%ebx),%ecx	// lightptr[1]
+	movl	(%ebx),%ebx		// lightptr[0]
+
+	subl	%eax,%ebx
+	subl	%edx,%ecx
+
+	sarl	$4,%ecx
+	orl		$0xF0000000,%ebp
+
+	sarl	$4,%ebx
+	movl	%ecx,C(lightrightstep)
+
+	subl	%ecx,%ebx
+	andl	$0xFFFFF,%ebx
+
+	orl		$0xF0000000,%ebx
+	subl	%ecx,%ecx	// high word must be 0 in loop for addressing
+
+	movl	%ebx,C(lightdeltastep)
+	subl	%ebx,%ebx	// high word must be 0 in loop for addressing
+
+Lblockloop8_mip0:
+	movl	%ebp,C(lightdelta)
+	movb	14(%esi),%cl
+
+	sarl	$4,%ebp
+	movb	%dh,%bh
+
+	movb	15(%esi),%bl
+	addl	%ebp,%edx
+
+	movb	%dh,%ch
+	addl	%ebp,%edx
+
+	movb	0x12345678(%ebx),%ah
+LBPatch0:
+	movb	13(%esi),%bl
+
+	movb	0x12345678(%ecx),%al
+LBPatch1:
+	movb	12(%esi),%cl
+
+	movb	%dh,%bh
+	addl	%ebp,%edx
+
+	rorl	$16,%eax
+	movb	%dh,%ch
+
+	addl	%ebp,%edx
+	movb	0x12345678(%ebx),%ah
+LBPatch2:
+
+	movb	11(%esi),%bl
+	movb	0x12345678(%ecx),%al
+LBPatch3:
+
+	movb	10(%esi),%cl
+	movl	%eax,12(%edi)
+
+	movb	%dh,%bh
+	addl	%ebp,%edx
+
+	movb	%dh,%ch
+	addl	%ebp,%edx
+
+	movb	0x12345678(%ebx),%ah
+LBPatch4:
+	movb	9(%esi),%bl
+
+	movb	0x12345678(%ecx),%al
+LBPatch5:
+	movb	8(%esi),%cl
+
+	movb	%dh,%bh
+	addl	%ebp,%edx
+
+	rorl	$16,%eax
+	movb	%dh,%ch
+
+	addl	%ebp,%edx
+	movb	0x12345678(%ebx),%ah
+LBPatch6:
+
+	movb	7(%esi),%bl
+	movb	0x12345678(%ecx),%al
+LBPatch7:
+
+	movb	6(%esi),%cl
+	movl	%eax,8(%edi)
+
+	movb	%dh,%bh
+	addl	%ebp,%edx
+
+	movb	%dh,%ch
+	addl	%ebp,%edx
+
+	movb	0x12345678(%ebx),%ah
+LBPatch8:
+	movb	5(%esi),%bl
+
+	movb	0x12345678(%ecx),%al
+LBPatch9:
+	movb	4(%esi),%cl
+
+	movb	%dh,%bh
+	addl	%ebp,%edx
+
+	rorl	$16,%eax
+	movb	%dh,%ch
+
+	addl	%ebp,%edx
+	movb	0x12345678(%ebx),%ah
+LBPatch10:
+
+	movb	3(%esi),%bl
+	movb	0x12345678(%ecx),%al
+LBPatch11:
+
+	movb	2(%esi),%cl
+	movl	%eax,4(%edi)
+
+	movb	%dh,%bh
+	addl	%ebp,%edx
+
+	movb	%dh,%ch
+	addl	%ebp,%edx
+
+	movb	0x12345678(%ebx),%ah
+LBPatch12:
+	movb	1(%esi),%bl
+
+	movb	0x12345678(%ecx),%al
+LBPatch13:
+	movb	(%esi),%cl
+
+	movb	%dh,%bh
+	addl	%ebp,%edx
+
+	rorl	$16,%eax
+	movb	%dh,%ch
+
+	movb	0x12345678(%ebx),%ah
+LBPatch14:
+	movl	C(lightright),%edx
+
+	movb	0x12345678(%ecx),%al
+LBPatch15:
+	movl	C(lightdelta),%ebp
+
+	movl	%eax,(%edi)
+
+	addl	C(sourcetstep),%esi
+	addl	C(surfrowbytes),%edi
+
+	addl	C(lightrightstep),%edx
+	addl	C(lightdeltastep),%ebp
+
+	movl	%edx,C(lightright)
+	jc		Lblockloop8_mip0
+
+//			if (pbasesource >= r_sourcemax)
+//				pbasesource -= stepback;
+
+	cmpl	C(r_sourcemax),%esi
+	jb		LSkip_mip0
+	subl	C(r_stepback),%esi
+LSkip_mip0:
+
+	movl	C(r_lightptr),%ebx
+	decl	sb_v
+
+	jnz		Lv_loop_mip0
+
+	popl	%ebx				// restore register variables
+	popl	%esi
+	popl	%edi
+	popl	%ebp				// restore the caller's stack frame
+	ret
+
+
+//----------------------------------------------------------------------
+// Surface block drawer for mip level 1
+//----------------------------------------------------------------------
+
+	.align 4
+.globl C(R_DrawSurfaceBlock8_mip1)
+C(R_DrawSurfaceBlock8_mip1):
+	pushl	%ebp				// preserve caller's stack frame
+	pushl	%edi
+	pushl	%esi				// preserve register variables
+	pushl	%ebx
+
+//		for (v=0 ; v<numvblocks ; v++)
+//		{
+	movl	C(r_lightptr),%ebx
+	movl	C(r_numvblocks),%eax
+
+	movl	%eax,sb_v
+	movl	C(prowdestbase),%edi
+
+	movl	C(pbasesource),%esi
+
+Lv_loop_mip1:
+
+//			lightleft = lightptr[0];
+//			lightright = lightptr[1];
+//			lightdelta = (lightleft - lightright) & 0xFFFFF;
+	movl	(%ebx),%eax			// lightleft
+	movl	4(%ebx),%edx		// lightright
+
+	movl	%eax,%ebp
+	movl	C(r_lightwidth),%ecx
+
+	movl	%edx,C(lightright)
+	subl	%edx,%ebp
+
+	andl	$0xFFFFF,%ebp
+	leal	(%ebx,%ecx,4),%ebx
+
+//			lightptr += lightwidth;
+	movl	%ebx,C(r_lightptr)
+
+//			lightleftstep = (lightptr[0] - lightleft) >> blockdivshift;
+//			lightrightstep = (lightptr[1] - lightright) >> blockdivshift;
+//			lightdeltastep = ((lightleftstep - lightrightstep) & 0xFFFFF) |
+//					0xF0000000;
+	movl	4(%ebx),%ecx	// lightptr[1]
+	movl	(%ebx),%ebx		// lightptr[0]
+
+	subl	%eax,%ebx
+	subl	%edx,%ecx
+
+	sarl	$3,%ecx
+	orl		$0x70000000,%ebp
+
+	sarl	$3,%ebx
+	movl	%ecx,C(lightrightstep)
+
+	subl	%ecx,%ebx
+	andl	$0xFFFFF,%ebx
+
+	orl		$0xF0000000,%ebx
+	subl	%ecx,%ecx	// high word must be 0 in loop for addressing
+
+	movl	%ebx,C(lightdeltastep)
+	subl	%ebx,%ebx	// high word must be 0 in loop for addressing
+
+Lblockloop8_mip1:
+	movl	%ebp,C(lightdelta)
+	movb	6(%esi),%cl
+
+	sarl	$3,%ebp
+	movb	%dh,%bh
+
+	movb	7(%esi),%bl
+	addl	%ebp,%edx
+
+	movb	%dh,%ch
+	addl	%ebp,%edx
+
+	movb	0x12345678(%ebx),%ah
+LBPatch22:
+	movb	5(%esi),%bl
+
+	movb	0x12345678(%ecx),%al
+LBPatch23:
+	movb	4(%esi),%cl
+
+	movb	%dh,%bh
+	addl	%ebp,%edx
+
+	rorl	$16,%eax
+	movb	%dh,%ch
+
+	addl	%ebp,%edx
+	movb	0x12345678(%ebx),%ah
+LBPatch24:
+
+	movb	3(%esi),%bl
+	movb	0x12345678(%ecx),%al
+LBPatch25:
+
+	movb	2(%esi),%cl
+	movl	%eax,4(%edi)
+
+	movb	%dh,%bh
+	addl	%ebp,%edx
+
+	movb	%dh,%ch
+	addl	%ebp,%edx
+
+	movb	0x12345678(%ebx),%ah
+LBPatch26:
+	movb	1(%esi),%bl
+
+	movb	0x12345678(%ecx),%al
+LBPatch27:
+	movb	(%esi),%cl
+
+	movb	%dh,%bh
+	addl	%ebp,%edx
+
+	rorl	$16,%eax
+	movb	%dh,%ch
+
+	movb	0x12345678(%ebx),%ah
+LBPatch28:
+	movl	C(lightright),%edx
+
+	movb	0x12345678(%ecx),%al
+LBPatch29:
+	movl	C(lightdelta),%ebp
+
+	movl	%eax,(%edi)
+	movl	C(sourcetstep),%eax
+
+	addl	%eax,%esi
+	movl	C(surfrowbytes),%eax
+
+	addl	%eax,%edi
+	movl	C(lightrightstep),%eax
+
+	addl	%eax,%edx
+	movl	C(lightdeltastep),%eax
+
+	addl	%eax,%ebp
+	movl	%edx,C(lightright)
+
+	jc		Lblockloop8_mip1
+
+//			if (pbasesource >= r_sourcemax)
+//				pbasesource -= stepback;
+
+	cmpl	C(r_sourcemax),%esi
+	jb		LSkip_mip1
+	subl	C(r_stepback),%esi
+LSkip_mip1:
+
+	movl	C(r_lightptr),%ebx
+	decl	sb_v
+
+	jnz		Lv_loop_mip1
+
+	popl	%ebx				// restore register variables
+	popl	%esi
+	popl	%edi
+	popl	%ebp				// restore the caller's stack frame
+	ret
+
+
+//----------------------------------------------------------------------
+// Surface block drawer for mip level 2
+//----------------------------------------------------------------------
+
+	.align 4
+.globl C(R_DrawSurfaceBlock8_mip2)
+C(R_DrawSurfaceBlock8_mip2):
+	pushl	%ebp				// preserve caller's stack frame
+	pushl	%edi
+	pushl	%esi				// preserve register variables
+	pushl	%ebx
+
+//		for (v=0 ; v<numvblocks ; v++)
+//		{
+	movl	C(r_lightptr),%ebx
+	movl	C(r_numvblocks),%eax
+
+	movl	%eax,sb_v
+	movl	C(prowdestbase),%edi
+
+	movl	C(pbasesource),%esi
+
+Lv_loop_mip2:
+
+//			lightleft = lightptr[0];
+//			lightright = lightptr[1];
+//			lightdelta = (lightleft - lightright) & 0xFFFFF;
+	movl	(%ebx),%eax			// lightleft
+	movl	4(%ebx),%edx		// lightright
+
+	movl	%eax,%ebp
+	movl	C(r_lightwidth),%ecx
+
+	movl	%edx,C(lightright)
+	subl	%edx,%ebp
+
+	andl	$0xFFFFF,%ebp
+	leal	(%ebx,%ecx,4),%ebx
+
+//			lightptr += lightwidth;
+	movl	%ebx,C(r_lightptr)
+
+//			lightleftstep = (lightptr[0] - lightleft) >> blockdivshift;
+//			lightrightstep = (lightptr[1] - lightright) >> blockdivshift;
+//			lightdeltastep = ((lightleftstep - lightrightstep) & 0xFFFFF) |
+//					0xF0000000;
+	movl	4(%ebx),%ecx	// lightptr[1]
+	movl	(%ebx),%ebx		// lightptr[0]
+
+	subl	%eax,%ebx
+	subl	%edx,%ecx
+
+	sarl	$2,%ecx
+	orl		$0x30000000,%ebp
+
+	sarl	$2,%ebx
+	movl	%ecx,C(lightrightstep)
+
+	subl	%ecx,%ebx
+
+	andl	$0xFFFFF,%ebx
+
+	orl		$0xF0000000,%ebx
+	subl	%ecx,%ecx	// high word must be 0 in loop for addressing
+
+	movl	%ebx,C(lightdeltastep)
+	subl	%ebx,%ebx	// high word must be 0 in loop for addressing
+
+Lblockloop8_mip2:
+	movl	%ebp,C(lightdelta)
+	movb	2(%esi),%cl
+
+	sarl	$2,%ebp
+	movb	%dh,%bh
+
+	movb	3(%esi),%bl
+	addl	%ebp,%edx
+
+	movb	%dh,%ch
+	addl	%ebp,%edx
+
+	movb	0x12345678(%ebx),%ah
+LBPatch18:
+	movb	1(%esi),%bl
+
+	movb	0x12345678(%ecx),%al
+LBPatch19:
+	movb	(%esi),%cl
+
+	movb	%dh,%bh
+	addl	%ebp,%edx
+
+	rorl	$16,%eax
+	movb	%dh,%ch
+
+	movb	0x12345678(%ebx),%ah
+LBPatch20:
+	movl	C(lightright),%edx
+
+	movb	0x12345678(%ecx),%al
+LBPatch21:
+	movl	C(lightdelta),%ebp
+
+	movl	%eax,(%edi)
+	movl	C(sourcetstep),%eax
+
+	addl	%eax,%esi
+	movl	C(surfrowbytes),%eax
+
+	addl	%eax,%edi
+	movl	C(lightrightstep),%eax
+
+	addl	%eax,%edx
+	movl	C(lightdeltastep),%eax
+
+	addl	%eax,%ebp
+	movl	%edx,C(lightright)
+
+	jc		Lblockloop8_mip2
+
+//			if (pbasesource >= r_sourcemax)
+//				pbasesource -= stepback;
+
+	cmpl	C(r_sourcemax),%esi
+	jb		LSkip_mip2
+	subl	C(r_stepback),%esi
+LSkip_mip2:
+
+	movl	C(r_lightptr),%ebx
+	decl	sb_v
+
+	jnz		Lv_loop_mip2
+
+	popl	%ebx				// restore register variables
+	popl	%esi
+	popl	%edi
+	popl	%ebp				// restore the caller's stack frame
+	ret
+
+
+//----------------------------------------------------------------------
+// Surface block drawer for mip level 3
+//----------------------------------------------------------------------
+
+	.align 4
+.globl C(R_DrawSurfaceBlock8_mip3)
+C(R_DrawSurfaceBlock8_mip3):
+	pushl	%ebp				// preserve caller's stack frame
+	pushl	%edi
+	pushl	%esi				// preserve register variables
+	pushl	%ebx
+
+//		for (v=0 ; v<numvblocks ; v++)
+//		{
+	movl	C(r_lightptr),%ebx
+	movl	C(r_numvblocks),%eax
+
+	movl	%eax,sb_v
+	movl	C(prowdestbase),%edi
+
+	movl	C(pbasesource),%esi
+
+Lv_loop_mip3:
+
+//			lightleft = lightptr[0];
+//			lightright = lightptr[1];
+//			lightdelta = (lightleft - lightright) & 0xFFFFF;
+	movl	(%ebx),%eax			// lightleft
+	movl	4(%ebx),%edx		// lightright
+
+	movl	%eax,%ebp
+	movl	C(r_lightwidth),%ecx
+
+	movl	%edx,C(lightright)
+	subl	%edx,%ebp
+
+	andl	$0xFFFFF,%ebp
+	leal	(%ebx,%ecx,4),%ebx
+
+	movl	%ebp,C(lightdelta)
+//			lightptr += lightwidth;
+	movl	%ebx,C(r_lightptr)
+
+//			lightleftstep = (lightptr[0] - lightleft) >> blockdivshift;
+//			lightrightstep = (lightptr[1] - lightright) >> blockdivshift;
+//			lightdeltastep = ((lightleftstep - lightrightstep) & 0xFFFFF) |
+//					0xF0000000;
+	movl	4(%ebx),%ecx	// lightptr[1]
+	movl	(%ebx),%ebx		// lightptr[0]
+
+	subl	%eax,%ebx
+	subl	%edx,%ecx
+
+	sarl	$1,%ecx
+
+	sarl	$1,%ebx
+	movl	%ecx,C(lightrightstep)
+
+	subl	%ecx,%ebx
+	andl	$0xFFFFF,%ebx
+
+	sarl	$1,%ebp
+	orl		$0xF0000000,%ebx
+
+	movl	%ebx,C(lightdeltastep)
+	subl	%ebx,%ebx	// high word must be 0 in loop for addressing
+
+	movb	1(%esi),%bl
+	subl	%ecx,%ecx	// high word must be 0 in loop for addressing
+
+	movb	%dh,%bh
+	movb	(%esi),%cl
+
+	addl	%ebp,%edx
+	movb	%dh,%ch
+
+	movb	0x12345678(%ebx),%al
+LBPatch16:
+	movl	C(lightright),%edx
+
+	movb	%al,1(%edi)
+	movb	0x12345678(%ecx),%al
+LBPatch17:
+
+	movb	%al,(%edi)
+	movl	C(sourcetstep),%eax
+
+	addl	%eax,%esi
+	movl	C(surfrowbytes),%eax
+
+	addl	%eax,%edi
+	movl	C(lightdeltastep),%eax
+
+	movl	C(lightdelta),%ebp
+	movb	(%esi),%cl
+
+	addl	%eax,%ebp
+	movl	C(lightrightstep),%eax
+
+	sarl	$1,%ebp
+	addl	%eax,%edx
+
+	movb	%dh,%bh
+	movb	1(%esi),%bl
+
+	addl	%ebp,%edx
+	movb	%dh,%ch
+
+	movb	0x12345678(%ebx),%al
+LBPatch30:
+	movl	C(sourcetstep),%edx
+
+	movb	%al,1(%edi)
+	movb	0x12345678(%ecx),%al
+LBPatch31:
+
+	movb	%al,(%edi)
+	movl	C(surfrowbytes),%ebp
+
+	addl	%edx,%esi
+	addl	%ebp,%edi
+
+//			if (pbasesource >= r_sourcemax)
+//				pbasesource -= stepback;
+
+	cmpl	C(r_sourcemax),%esi
+	jb		LSkip_mip3
+	subl	C(r_stepback),%esi
+LSkip_mip3:
+
+	movl	C(r_lightptr),%ebx
+	decl	sb_v
+
+	jnz		Lv_loop_mip3
+
+	popl	%ebx				// restore register variables
+	popl	%esi
+	popl	%edi
+	popl	%ebp				// restore the caller's stack frame
+	ret
+
+
+.globl C(R_Surf8End)
+C(R_Surf8End):
+
+//----------------------------------------------------------------------
+// Code patching routines
+//----------------------------------------------------------------------
+	.data
+
+	.align 4
+LPatchTable8:
+	.long	LBPatch0-4
+	.long	LBPatch1-4
+	.long	LBPatch2-4
+	.long	LBPatch3-4
+	.long	LBPatch4-4
+	.long	LBPatch5-4
+	.long	LBPatch6-4
+	.long	LBPatch7-4
+	.long	LBPatch8-4
+	.long	LBPatch9-4
+	.long	LBPatch10-4
+	.long	LBPatch11-4
+	.long	LBPatch12-4
+	.long	LBPatch13-4
+	.long	LBPatch14-4
+	.long	LBPatch15-4
+	.long	LBPatch16-4
+	.long	LBPatch17-4
+	.long	LBPatch18-4
+	.long	LBPatch19-4
+	.long	LBPatch20-4
+	.long	LBPatch21-4
+	.long	LBPatch22-4
+	.long	LBPatch23-4
+	.long	LBPatch24-4
+	.long	LBPatch25-4
+	.long	LBPatch26-4
+	.long	LBPatch27-4
+	.long	LBPatch28-4
+	.long	LBPatch29-4
+	.long	LBPatch30-4
+	.long	LBPatch31-4
+
+	.text
+
+	.align 4
+.globl C(R_Surf8Patch)
+C(R_Surf8Patch):
+	pushl	%ebx
+
+	movl	C(colormap),%eax
+	movl	$LPatchTable8,%ebx
+	movl	$32,%ecx
+LPatchLoop8:
+	movl	(%ebx),%edx
+	addl	$4,%ebx
+	movl	%eax,(%edx)
+	decl	%ecx
+	jnz		LPatchLoop8
+
+	popl	%ebx
+
+	ret
+
+#endif	// id386
--- /dev/null
+++ b/QW/client/sys.h
@@ -1,0 +1,71 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// sys.h -- non-portable functions
+
+//
+// file IO
+//
+
+// returns the file size
+// return -1 if file is not present
+// the file should be in BINARY mode for stupid OSs that care
+int Sys_FileOpenRead (char *path, int *hndl);
+
+int Sys_FileOpenWrite (char *path);
+void Sys_FileClose (int handle);
+void Sys_FileSeek (int handle, int position);
+int Sys_FileRead (int handle, void *dest, int count);
+int Sys_FileWrite (int handle, void *data, int count);
+int	Sys_FileTime (char *path);
+void Sys_mkdir (char *path);
+
+//
+// memory protection
+//
+void Sys_MakeCodeWriteable (unsigned long startaddr, unsigned long length);
+
+//
+// system IO
+//
+void Sys_DebugLog(char *file, char *fmt, ...);
+
+void Sys_Error (char *error, ...);
+// an error will cause the entire program to exit
+
+void Sys_Printf (char *fmt, ...);
+// send text to the console
+
+void Sys_Quit (void);
+
+double Sys_DoubleTime (void);
+
+char *Sys_ConsoleInput (void);
+
+void Sys_Sleep (void);
+// called to yield for a little bit so as
+// not to hog cpu when paused or debugging
+
+void Sys_SendKeyEvents (void);
+// Perform Key_Event () callbacks until the input que is empty
+
+void Sys_LowFPPrecision (void);
+void Sys_HighFPPrecision (void);
+void Sys_SetFPCW (void);
+
--- /dev/null
+++ b/QW/client/sys_dosa.s
@@ -1,0 +1,95 @@
+//
+// sys_dosa.s
+// x86 assembly-language DOS-dependent routines.
+
+#include "asm_i386.h"
+#include "quakeasm.h"
+
+
+	.data
+
+	.align	4
+fpenv:
+	.long	0, 0, 0, 0, 0, 0, 0, 0
+
+	.text
+
+.globl C(MaskExceptions)
+C(MaskExceptions):
+	fnstenv	fpenv
+	orl		$0x3F,fpenv
+	fldenv	fpenv
+
+	ret
+
+#if 0
+.globl C(unmaskexceptions)
+C(unmaskexceptions):
+	fnstenv	fpenv
+	andl		$0xFFFFFFE0,fpenv
+	fldenv	fpenv
+
+	ret
+#endif
+
+	.data
+
+	.align	4
+.globl	ceil_cw, single_cw, full_cw, cw, pushed_cw
+ceil_cw:	.long	0
+single_cw:	.long	0
+full_cw:	.long	0
+cw:			.long	0
+pushed_cw:	.long	0
+
+	.text
+
+.globl C(Sys_LowFPPrecision)
+C(Sys_LowFPPrecision):
+	fldcw	single_cw
+
+	ret
+
+.globl C(Sys_HighFPPrecision)
+C(Sys_HighFPPrecision):
+	fldcw	full_cw
+
+	ret
+
+.globl C(Sys_PushFPCW_SetHigh)
+C(Sys_PushFPCW_SetHigh):
+	fnstcw	pushed_cw
+	fldcw	full_cw
+
+	ret
+
+.globl C(Sys_PopFPCW)
+C(Sys_PopFPCW):
+	fldcw	pushed_cw
+
+	ret
+
+.globl C(Sys_SetFPCW)
+C(Sys_SetFPCW):
+	fnstcw	cw
+	movl	cw,%eax
+#if	id386
+	andb	$0xF0,%ah
+	orb		$0x03,%ah	// round mode, 64-bit precision
+#endif
+	movl	%eax,full_cw
+
+#if	id386
+	andb	$0xF0,%ah
+	orb		$0x0C,%ah	// chop mode, single precision
+#endif
+	movl	%eax,single_cw
+
+#if	id386
+	andb	$0xF0,%ah
+	orb		$0x08,%ah	// ceil mode, single precision
+#endif
+	movl	%eax,ceil_cw
+
+	ret
+
--- /dev/null
+++ b/QW/client/sys_linux.c
@@ -1,0 +1,428 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+#include <unistd.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <ctype.h>
+#include <sys/wait.h>
+#include <sys/mman.h>
+#include <errno.h>
+
+#include "quakedef.h"
+
+int noconinput = 0;
+int nostdout = 0;
+
+char *basedir = ".";
+char *cachedir = "/tmp";
+
+cvar_t  sys_linerefresh = {"sys_linerefresh","0"};// set for entity display
+
+// =======================================================================
+// General routines
+// =======================================================================
+
+void Sys_DebugNumber(int y, int val)
+{
+}
+
+/*
+void Sys_Printf (char *fmt, ...)
+{
+	va_list		argptr;
+	char		text[1024];
+	
+	va_start (argptr,fmt);
+	vsprintf (text,fmt,argptr);
+	va_end (argptr);
+	fprintf(stderr, "%s", text);
+	
+	Con_Print (text);
+}
+
+void Sys_Printf (char *fmt, ...)
+{
+
+    va_list     argptr;
+    char        text[1024], *t_p;
+    int         l, r;
+
+    if (nostdout)
+        return;
+
+    va_start (argptr,fmt);
+    vsprintf (text,fmt,argptr);
+    va_end (argptr);
+
+    l = strlen(text);
+    t_p = text;
+
+// make sure everything goes through, even though we are non-blocking
+    while (l)
+    {
+        r = write (1, text, l);
+        if (r != l)
+            sleep (0);
+        if (r > 0)
+        {
+            t_p += r;
+            l -= r;
+        }
+    }
+
+}
+*/
+
+void Sys_Printf (char *fmt, ...)
+{
+	va_list		argptr;
+	char		text[2048];
+	unsigned char		*p;
+
+	va_start (argptr,fmt);
+	vsprintf (text,fmt,argptr);
+	va_end (argptr);
+
+	if (strlen(text) > sizeof(text))
+		Sys_Error("memory overwrite in Sys_Printf");
+
+    if (nostdout)
+        return;
+
+	for (p = (unsigned char *)text; *p; p++)
+		if ((*p > 128 || *p < 32) && *p != 10 && *p != 13 && *p != 9)
+			printf("[%02x]", *p);
+		else
+			putc(*p, stdout);
+}
+
+void Sys_Quit (void)
+{
+	Host_Shutdown();
+    fcntl (0, F_SETFL, fcntl (0, F_GETFL, 0) & ~FNDELAY);
+	exit(0);
+}
+
+void Sys_Init(void)
+{
+#if id386
+	Sys_SetFPCW();
+#endif
+}
+
+void Sys_Error (char *error, ...)
+{ 
+    va_list     argptr;
+    char        string[1024];
+
+// change stdin to non blocking
+    fcntl (0, F_SETFL, fcntl (0, F_GETFL, 0) & ~FNDELAY);
+    
+    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[1024];
+    
+    va_start (argptr,warning);
+    vsprintf (string,warning,argptr);
+    va_end (argptr);
+	fprintf(stderr, "Warning: %s", string);
+} 
+
+/*
+============
+Sys_FileTime
+
+returns -1 if not present
+============
+*/
+int	Sys_FileTime (char *path)
+{
+	struct	stat	buf;
+	
+	if (stat (path,&buf) == -1)
+		return -1;
+	
+	return buf.st_mtime;
+}
+
+
+void Sys_mkdir (char *path)
+{
+    mkdir (path, 0777);
+}
+
+int Sys_FileOpenRead (char *path, int *handle)
+{
+	int	h;
+	struct stat	fileinfo;
+    
+	
+	h = open (path, O_RDONLY, 0666);
+	*handle = h;
+	if (h == -1)
+		return -1;
+	
+	if (fstat (h,&fileinfo) == -1)
+		Sys_Error ("Error fstating %s", path);
+
+	return fileinfo.st_size;
+}
+
+int Sys_FileOpenWrite (char *path)
+{
+	int     handle;
+
+	umask (0);
+	
+	handle = open(path,O_RDWR | O_CREAT | O_TRUNC
+	, 0666);
+
+	if (handle == -1)
+		Sys_Error ("Error opening %s: %s", path,strerror(errno));
+
+	return handle;
+}
+
+int Sys_FileWrite (int handle, void *src, int count)
+{
+	return write (handle, src, count);
+}
+
+void Sys_FileClose (int handle)
+{
+	close (handle);
+}
+
+void Sys_FileSeek (int handle, int position)
+{
+	lseek (handle, position, SEEK_SET);
+}
+
+int Sys_FileRead (int handle, void *dest, int count)
+{
+    return read (handle, dest, count);
+}
+
+void Sys_DebugLog(char *file, char *fmt, ...)
+{
+    va_list argptr; 
+    static char data[1024];
+    int fd;
+    
+    va_start(argptr, fmt);
+    vsprintf(data, fmt, argptr);
+    va_end(argptr);
+//    fd = open(file, O_WRONLY | O_BINARY | O_CREAT | O_APPEND, 0666);
+    fd = open(file, O_WRONLY | O_CREAT | O_APPEND, 0666);
+    write(fd, data, strlen(data));
+    close(fd);
+}
+
+void Sys_EditFile(char *filename)
+{
+
+	char cmd[256];
+	char *term;
+	char *editor;
+
+	term = getenv("TERM");
+	if (term && !strcmp(term, "xterm"))
+	{
+		editor = getenv("VISUAL");
+		if (!editor)
+			editor = getenv("EDITOR");
+		if (!editor)
+			editor = getenv("EDIT");
+		if (!editor)
+			editor = "vi";
+		sprintf(cmd, "xterm -e %s %s", editor, filename);
+		system(cmd);
+	}
+
+}
+
+double Sys_DoubleTime (void)
+{
+    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;
+}
+
+// =======================================================================
+// Sleeps for microseconds
+// =======================================================================
+
+static volatile int oktogo;
+
+void alarm_handler(int x)
+{
+	oktogo=1;
+}
+
+void Sys_LineRefresh(void)
+{
+}
+
+void floating_point_exception_handler(int whatever)
+{
+//	Sys_Warn("floating point exception\n");
+	signal(SIGFPE, floating_point_exception_handler);
+}
+
+char *Sys_ConsoleInput(void)
+{
+#if 0
+    static char text[256];
+    int     len;
+
+	if (cls.state == ca_dedicated) {
+		len = read (0, text, sizeof(text));
+		if (len < 1)
+			return NULL;
+		text[len-1] = 0;    // rip off the /n and terminate
+
+		return text;
+	}
+#endif
+	return NULL;
+}
+
+#if !id386
+void Sys_HighFPPrecision (void)
+{
+}
+
+void Sys_LowFPPrecision (void)
+{
+}
+#endif
+
+int		skipframes;
+
+int main (int c, char **v)
+{
+
+	double		time, oldtime, newtime;
+	quakeparms_t parms;
+	int j;
+
+//	static char cwd[1024];
+
+//	signal(SIGFPE, floating_point_exception_handler);
+	signal(SIGFPE, SIG_IGN);
+
+	memset(&parms, 0, sizeof(parms));
+
+	COM_InitArgv(c, v);
+	parms.argc = com_argc;
+	parms.argv = com_argv;
+
+	parms.memsize = 16*1024*1024;
+
+	j = COM_CheckParm("-mem");
+	if (j)
+		parms.memsize = (int) (Q_atof(com_argv[j+1]) * 1024 * 1024);
+	parms.membase = malloc (parms.memsize);
+
+	parms.basedir = basedir;
+// caching is disabled by default, use -cachedir to enable
+//	parms.cachedir = cachedir;
+
+	noconinput = COM_CheckParm("-noconinput");
+	if (!noconinput)
+		fcntl(0, F_SETFL, fcntl (0, F_GETFL, 0) | FNDELAY);
+
+	if (COM_CheckParm("-nostdout"))
+		nostdout = 1;
+
+	Sys_Init();
+
+    Host_Init(&parms);
+
+    oldtime = Sys_DoubleTime ();
+    while (1)
+    {
+// find time spent rendering last frame
+        newtime = Sys_DoubleTime ();
+        time = newtime - oldtime;
+
+		Host_Frame(time);
+		oldtime = newtime;
+    }
+
+}
+
+
+/*
+================
+Sys_MakeCodeWriteable
+================
+*/
+void Sys_MakeCodeWriteable (unsigned long startaddr, unsigned long length)
+{
+
+	int r;
+	unsigned long addr;
+	int psize = getpagesize();
+
+	addr = (startaddr & ~(psize-1)) - psize;
+
+//	fprintf(stderr, "writable code %lx(%lx)-%lx, length=%lx\n", startaddr,
+//			addr, startaddr+length, length);
+
+	r = mprotect((char*)addr, length + startaddr - addr + psize, 7);
+
+	if (r < 0)
+    		Sys_Error("Protection change failed\n");
+
+}
+
--- /dev/null
+++ b/QW/client/sys_null.c
@@ -1,0 +1,142 @@
+// sys_null.h -- null system driver to aid porting efforts
+
+#include "quakedef.h"
+#include "errno.h"
+
+
+/*
+================
+filelength
+================
+*/
+int filelength (FILE *f)
+{
+	int		pos;
+	int		end;
+
+	pos = ftell (f);
+	fseek (f, 0, SEEK_END);
+	end = ftell (f);
+	fseek (f, pos, SEEK_SET);
+
+	return end;
+}
+
+
+int	Sys_FileTime (char *path)
+{
+	FILE	*f;
+	
+	f = fopen(path, "rb");
+	if (f)
+	{
+		fclose(f);
+		return 1;
+	}
+	
+	return -1;
+}
+
+void Sys_mkdir (char *path)
+{
+}
+
+
+/*
+===============================================================================
+
+SYSTEM IO
+
+===============================================================================
+*/
+
+void Sys_MakeCodeWriteable (unsigned long startaddr, unsigned long length)
+{
+}
+
+
+void Sys_DebugLog(char *file, char *fmt, ...)
+{
+}
+
+void Sys_Error (char *error, ...)
+{
+	va_list		argptr;
+
+	printf ("I_Error: ");	
+	va_start (argptr,error);
+	vprintf (error,argptr);
+	va_end (argptr);
+	printf ("\n");
+
+	exit (1);
+}
+
+void Sys_Printf (char *fmt, ...)
+{
+	va_list		argptr;
+	
+	va_start (argptr,fmt);
+	vprintf (fmt,argptr);
+	va_end (argptr);
+}
+
+void Sys_Quit (void)
+{
+	exit (0);
+}
+
+double Sys_FloatTime (void)
+{
+	static double t;
+	
+	t += 0.1;
+	
+	return t;
+}
+
+char *Sys_ConsoleInput (void)
+{
+	return NULL;
+}
+
+void Sys_Sleep (void)
+{
+}
+
+void Sys_SendKeyEvents (void)
+{
+}
+
+void Sys_HighFPPrecision (void)
+{
+}
+
+void Sys_LowFPPrecision (void)
+{
+}
+
+//=============================================================================
+
+void main (int argc, char **argv)
+{
+	quakeparms_t	parms;
+
+	parms.memsize = 5861376;
+	parms.membase = malloc (parms.memsize);
+	parms.basedir = ".";
+
+	COM_InitArgv (argc, argv);
+
+	parms.argc = com_argc;
+	parms.argv = com_argv;
+
+	printf ("Host_Init\n");
+	Host_Init (&parms);
+	while (1)
+	{
+		Host_Frame (0.1);
+	}
+}
+
+
--- /dev/null
+++ b/QW/client/sys_win.c
@@ -1,0 +1,698 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// sys_win.h
+
+#include "quakedef.h"
+#include "winquake.h"
+#include "resource.h"
+#include "errno.h"
+#include "fcntl.h"
+#include <limits.h>
+
+#define MINIMUM_WIN_MEMORY	0x0c00000
+#define MAXIMUM_WIN_MEMORY	0x1000000
+
+#define PAUSE_SLEEP		50				// sleep time on pause or minimization
+#define NOT_FOCUS_SLEEP	20				// sleep time when not focus
+
+int		starttime;
+qboolean ActiveApp, Minimized;
+qboolean	WinNT;
+
+HWND	hwnd_dialog;		// startup dialog box
+
+static double		pfreq;
+static double		curtime = 0.0;
+static double		lastcurtime = 0.0;
+static int			lowshift;
+static HANDLE		hinput, houtput;
+
+HANDLE		qwclsemaphore;
+
+static HANDLE	tevent;
+
+void Sys_InitFloatTime (void);
+
+void MaskExceptions (void);
+void Sys_PopFPCW (void);
+void Sys_PushFPCW_SetHigh (void);
+
+void Sys_DebugLog(char *file, char *fmt, ...)
+{
+    va_list argptr; 
+    static char data[1024];
+    int fd;
+    
+    va_start(argptr, fmt);
+    vsprintf(data, fmt, argptr);
+    va_end(argptr);
+    fd = open(file, O_WRONLY | O_CREAT | O_APPEND, 0666);
+    write(fd, data, strlen(data));
+    close(fd);
+};
+
+/*
+===============================================================================
+
+FILE IO
+
+===============================================================================
+*/
+
+/*
+================
+filelength
+================
+*/
+int filelength (FILE *f)
+{
+	int		pos;
+	int		end;
+
+	pos = ftell (f);
+	fseek (f, 0, SEEK_END);
+	end = ftell (f);
+	fseek (f, pos, SEEK_SET);
+
+	return end;
+}
+
+
+int	Sys_FileTime (char *path)
+{
+	FILE	*f;
+	int		t, retval;
+
+	t = VID_ForceUnlockedAndReturnState ();
+	
+	f = fopen(path, "rb");
+
+	if (f)
+	{
+		fclose(f);
+		retval = 1;
+	}
+	else
+	{
+		retval = -1;
+	}
+	
+	VID_ForceLockState (t);
+	return retval;
+}
+
+void Sys_mkdir (char *path)
+{
+	_mkdir (path);
+}
+
+
+/*
+===============================================================================
+
+SYSTEM IO
+
+===============================================================================
+*/
+
+/*
+================
+Sys_MakeCodeWriteable
+================
+*/
+void Sys_MakeCodeWriteable (unsigned long startaddr, unsigned long length)
+{
+	DWORD  flOldProtect;
+
+//@@@ copy on write or just read-write?
+	if (!VirtualProtect((LPVOID)startaddr, length, PAGE_READWRITE, &flOldProtect))
+   		Sys_Error("Protection change failed\n");
+}
+
+
+/*
+================
+Sys_Init
+================
+*/
+void Sys_Init (void)
+{
+	LARGE_INTEGER	PerformanceFreq;
+	unsigned int	lowpart, highpart;
+	OSVERSIONINFO	vinfo;
+
+#ifndef SERVERONLY
+	// allocate a named semaphore on the client so the
+	// front end can tell if it is alive
+
+	// mutex will fail if semephore allready exists
+    qwclsemaphore = CreateMutex(
+        NULL,         /* Security attributes */
+        0,            /* owner       */
+        "qwcl"); /* Semaphore name      */
+	if (!qwclsemaphore)
+		Sys_Error ("QWCL is already running on this system");
+	CloseHandle (qwclsemaphore);
+
+    qwclsemaphore = CreateSemaphore(
+        NULL,         /* Security attributes */
+        0,            /* Initial count       */
+        1,            /* Maximum count       */
+        "qwcl"); /* Semaphore name      */
+#endif
+
+	MaskExceptions ();
+	Sys_SetFPCW ();
+
+#if 0
+	if (!QueryPerformanceFrequency (&PerformanceFreq))
+		Sys_Error ("No hardware timer available");
+
+// get 32 out of the 64 time bits such that we have around
+// 1 microsecond resolution
+	lowpart = (unsigned int)PerformanceFreq.LowPart;
+	highpart = (unsigned int)PerformanceFreq.HighPart;
+	lowshift = 0;
+
+	while (highpart || (lowpart > 2000000.0))
+	{
+		lowshift++;
+		lowpart >>= 1;
+		lowpart |= (highpart & 1) << 31;
+		highpart >>= 1;
+	}
+
+	pfreq = 1.0 / (double)lowpart;
+
+	Sys_InitFloatTime ();
+#endif
+
+	// make sure the timer is high precision, otherwise
+	// NT gets 18ms resolution
+	timeBeginPeriod( 1 );
+
+	vinfo.dwOSVersionInfoSize = sizeof(vinfo);
+
+	if (!GetVersionEx (&vinfo))
+		Sys_Error ("Couldn't get OS info");
+
+	if ((vinfo.dwMajorVersion < 4) ||
+		(vinfo.dwPlatformId == VER_PLATFORM_WIN32s))
+	{
+		Sys_Error ("QuakeWorld requires at least Win95 or NT 4.0");
+	}
+	
+	if (vinfo.dwPlatformId == VER_PLATFORM_WIN32_NT)
+		WinNT = true;
+	else
+		WinNT = false;
+}
+
+
+void Sys_Error (char *error, ...)
+{
+	va_list		argptr;
+	char		text[1024], text2[1024];
+	DWORD		dummy;
+
+	Host_Shutdown ();
+
+	va_start (argptr, error);
+	vsprintf (text, error, argptr);
+	va_end (argptr);
+
+	MessageBox(NULL, text, "Error", 0 /* MB_OK */ );
+
+#ifndef SERVERONLY
+	CloseHandle (qwclsemaphore);
+#endif
+
+	exit (1);
+}
+
+void Sys_Printf (char *fmt, ...)
+{
+	va_list		argptr;
+	char		text[1024];
+	DWORD		dummy;
+	
+	va_start (argptr,fmt);
+	vprintf (fmt, argptr);
+	va_end (argptr);
+}
+
+void Sys_Quit (void)
+{
+	VID_ForceUnlockedAndReturnState ();
+
+	Host_Shutdown();
+#ifndef SERVERONLY
+	if (tevent)
+		CloseHandle (tevent);
+
+	if (qwclsemaphore)
+		CloseHandle (qwclsemaphore);
+#endif
+
+	exit (0);
+}
+
+
+#if 0
+/*
+================
+Sys_DoubleTime
+================
+*/
+double Sys_DoubleTime (void)
+{
+	static int			sametimecount;
+	static unsigned int	oldtime;
+	static int			first = 1;
+	LARGE_INTEGER		PerformanceCount;
+	unsigned int		temp, t2;
+	double				time;
+
+	Sys_PushFPCW_SetHigh ();
+
+	QueryPerformanceCounter (&PerformanceCount);
+
+	temp = ((unsigned int)PerformanceCount.LowPart >> lowshift) |
+		   ((unsigned int)PerformanceCount.HighPart << (32 - lowshift));
+
+	if (first)
+	{
+		oldtime = temp;
+		first = 0;
+	}
+	else
+	{
+	// check for turnover or backward time
+		if ((temp <= oldtime) && ((oldtime - temp) < 0x10000000))
+		{
+			oldtime = temp;	// so we can't get stuck
+		}
+		else
+		{
+			t2 = temp - oldtime;
+
+			time = (double)t2 * pfreq;
+			oldtime = temp;
+
+			curtime += time;
+
+			if (curtime == lastcurtime)
+			{
+				sametimecount++;
+
+				if (sametimecount > 100000)
+				{
+					curtime += 1.0;
+					sametimecount = 0;
+				}
+			}
+			else
+			{
+				sametimecount = 0;
+			}
+
+			lastcurtime = curtime;
+		}
+	}
+
+	Sys_PopFPCW ();
+
+    return curtime;
+}
+
+/*
+================
+Sys_InitFloatTime
+================
+*/
+void Sys_InitFloatTime (void)
+{
+	int		j;
+
+	Sys_DoubleTime ();
+
+	j = COM_CheckParm("-starttime");
+
+	if (j)
+	{
+		curtime = (double) (Q_atof(com_argv[j+1]));
+	}
+	else
+	{
+		curtime = 0.0;
+	}
+
+	lastcurtime = curtime;
+}
+
+#endif
+
+double Sys_DoubleTime (void)
+{
+	static DWORD starttime;
+	static qboolean first = true;
+	DWORD now;
+	double t;
+
+	now = timeGetTime();
+
+	if (first) {
+		first = false;
+		starttime = now;
+		return 0.0;
+	}
+	
+	if (now < starttime) // wrapped?
+		return (now / 1000.0) + (LONG_MAX - starttime / 1000.0);
+
+	if (now - starttime == 0)
+		return 0.0;
+
+	return (now - starttime) / 1000.0;
+}
+
+char *Sys_ConsoleInput (void)
+{
+	static char	text[256];
+	static int		len;
+	INPUT_RECORD	recs[1024];
+	int		count;
+	int		i, dummy;
+	int		ch, numread, numevents;
+	HANDLE	th;
+	char	*clipText, *textCopied;
+
+	for ( ;; )
+	{
+		if (!GetNumberOfConsoleInputEvents (hinput, &numevents))
+			Sys_Error ("Error getting # of console events");
+
+		if (numevents <= 0)
+			break;
+
+		if (!ReadConsoleInput(hinput, recs, 1, &numread))
+			Sys_Error ("Error reading console input");
+
+		if (numread != 1)
+			Sys_Error ("Couldn't read console input");
+
+		if (recs[0].EventType == KEY_EVENT)
+		{
+			if (!recs[0].Event.KeyEvent.bKeyDown)
+			{
+				ch = recs[0].Event.KeyEvent.uChar.AsciiChar;
+
+				switch (ch)
+				{
+					case '\r':
+						WriteFile(houtput, "\r\n", 2, &dummy, NULL);	
+
+						if (len)
+						{
+							text[len] = 0;
+							len = 0;
+							return text;
+						}
+						break;
+
+					case '\b':
+						WriteFile(houtput, "\b \b", 3, &dummy, NULL);	
+						if (len)
+						{
+							len--;
+							putch('\b');
+						}
+						break;
+
+					default:
+						Con_Printf("Stupid: %d\n", recs[0].Event.KeyEvent.dwControlKeyState);
+						if (((ch=='V' || ch=='v') && (recs[0].Event.KeyEvent.dwControlKeyState & 
+							(LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED))) || ((recs[0].Event.KeyEvent.dwControlKeyState 
+							& SHIFT_PRESSED) && (recs[0].Event.KeyEvent.wVirtualKeyCode
+							==VK_INSERT))) {
+							if (OpenClipboard(NULL)) {
+								th = GetClipboardData(CF_TEXT);
+								if (th) {
+									clipText = GlobalLock(th);
+									if (clipText) {
+										textCopied = malloc(GlobalSize(th)+1);
+										strcpy(textCopied, clipText);
+/* Substitutes a NULL for every token */strtok(textCopied, "\n\r\b");
+										i = strlen(textCopied);
+										if (i+len>=256)
+											i=256-len;
+										if (i>0) {
+											textCopied[i]=0;
+											text[len]=0;
+											strcat(text, textCopied);
+											len+=dummy;
+											WriteFile(houtput, textCopied, i, &dummy, NULL);
+										}
+										free(textCopied);
+									}
+									GlobalUnlock(th);
+								}
+								CloseClipboard();
+							}
+						} else if (ch >= ' ')
+						{
+							WriteFile(houtput, &ch, 1, &dummy, NULL);	
+							text[len] = ch;
+							len = (len + 1) & 0xff;
+						}
+
+						break;
+
+				}
+			}
+		}
+	}
+
+	return NULL;
+}
+
+void Sys_Sleep (void)
+{
+}
+
+
+void Sys_SendKeyEvents (void)
+{
+    MSG        msg;
+
+	while (PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE))
+	{
+	// we always update if there are any event, even if we're paused
+		scr_skipupdate = 0;
+
+		if (!GetMessage (&msg, NULL, 0, 0))
+			Sys_Quit ();
+      	TranslateMessage (&msg);
+      	DispatchMessage (&msg);
+	}
+}
+
+
+
+/*
+==============================================================================
+
+ WINDOWS CRAP
+
+==============================================================================
+*/
+
+/*
+==================
+WinMain
+==================
+*/
+void SleepUntilInput (int time)
+{
+
+	MsgWaitForMultipleObjects(1, &tevent, FALSE, time, QS_ALLINPUT);
+}
+
+
+
+/*
+==================
+WinMain
+==================
+*/
+HINSTANCE	global_hInstance;
+int			global_nCmdShow;
+char		*argv[MAX_NUM_ARGVS];
+static char	*empty_string = "";
+HWND		hwnd_dialog;
+
+
+int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
+{
+    MSG				msg;
+	quakeparms_t	parms;
+	double			time, oldtime, newtime;
+	MEMORYSTATUS	lpBuffer;
+	static	char	cwd[1024];
+	int				t;
+	RECT			rect;
+
+    /* previous instances do not exist in Win32 */
+    if (hPrevInstance)
+        return 0;
+
+	global_hInstance = hInstance;
+	global_nCmdShow = nCmdShow;
+
+	lpBuffer.dwLength = sizeof(MEMORYSTATUS);
+	GlobalMemoryStatus (&lpBuffer);
+
+	if (!GetCurrentDirectory (sizeof(cwd), cwd))
+		Sys_Error ("Couldn't determine current directory");
+
+	if (cwd[Q_strlen(cwd)-1] == '/')
+		cwd[Q_strlen(cwd)-1] = 0;
+
+	parms.basedir = cwd;
+	parms.cachedir = NULL;
+
+	parms.argc = 1;
+	argv[0] = empty_string;
+
+	while (*lpCmdLine && (parms.argc < MAX_NUM_ARGVS))
+	{
+		while (*lpCmdLine && ((*lpCmdLine <= 32) || (*lpCmdLine > 126)))
+			lpCmdLine++;
+
+		if (*lpCmdLine)
+		{
+			argv[parms.argc] = lpCmdLine;
+			parms.argc++;
+
+			while (*lpCmdLine && ((*lpCmdLine > 32) && (*lpCmdLine <= 126)))
+				lpCmdLine++;
+
+			if (*lpCmdLine)
+			{
+				*lpCmdLine = 0;
+				lpCmdLine++;
+			}
+			
+		}
+	}
+
+	parms.argv = argv;
+
+	COM_InitArgv (parms.argc, parms.argv);
+
+	parms.argc = com_argc;
+	parms.argv = com_argv;
+
+	hwnd_dialog = CreateDialog(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), NULL, NULL);
+
+	if (hwnd_dialog)
+	{
+		if (GetWindowRect (hwnd_dialog, &rect))
+		{
+			if (rect.left > (rect.top * 2))
+			{
+				SetWindowPos (hwnd_dialog, 0,
+					(rect.left / 2) - ((rect.right - rect.left) / 2),
+					rect.top, 0, 0,
+					SWP_NOZORDER | SWP_NOSIZE);
+			}
+		}
+
+		ShowWindow (hwnd_dialog, SW_SHOWDEFAULT);
+		UpdateWindow (hwnd_dialog);
+		SetForegroundWindow (hwnd_dialog);
+	}
+
+// take the greater of all the available memory or half the total memory,
+// but at least 8 Mb and no more than 16 Mb, unless they explicitly
+// request otherwise
+	parms.memsize = lpBuffer.dwAvailPhys;
+
+	if (parms.memsize < MINIMUM_WIN_MEMORY)
+		parms.memsize = MINIMUM_WIN_MEMORY;
+
+	if (parms.memsize < (lpBuffer.dwTotalPhys >> 1))
+		parms.memsize = lpBuffer.dwTotalPhys >> 1;
+
+	if (parms.memsize > MAXIMUM_WIN_MEMORY)
+		parms.memsize = MAXIMUM_WIN_MEMORY;
+
+	if (COM_CheckParm ("-heapsize"))
+	{
+		t = COM_CheckParm("-heapsize") + 1;
+
+		if (t < com_argc)
+			parms.memsize = Q_atoi (com_argv[t]) * 1024;
+	}
+
+	parms.membase = malloc (parms.memsize);
+
+	if (!parms.membase)
+		Sys_Error ("Not enough memory free; check disk space\n");
+
+	tevent = CreateEvent(NULL, FALSE, FALSE, NULL);
+
+	if (!tevent)
+		Sys_Error ("Couldn't create event");
+
+	Sys_Init ();
+
+// because sound is off until we become active
+	S_BlockSound ();
+
+	Sys_Printf ("Host_Init\n");
+	Host_Init (&parms);
+
+	oldtime = Sys_DoubleTime ();
+
+    /* main window message loop */
+	while (1)
+	{
+	// yield the CPU for a little while when paused, minimized, or not the focus
+		if ((cl.paused && (!ActiveApp && !DDActive)) || Minimized || block_drawing)
+		{
+			SleepUntilInput (PAUSE_SLEEP);
+			scr_skipupdate = 1;		// no point in bothering to draw
+		}
+		else if (!ActiveApp && !DDActive)
+		{
+			SleepUntilInput (NOT_FOCUS_SLEEP);
+		}
+
+		newtime = Sys_DoubleTime ();
+		time = newtime - oldtime;
+		Host_Frame (time);
+		oldtime = newtime;
+	}
+
+    /* return success of application */
+    return TRUE;
+}
+
--- /dev/null
+++ b/QW/client/sys_wina.asm
@@ -1,0 +1,289 @@
+ .386P
+ .model FLAT
+ externdef _d_zistepu:dword
+ externdef _d_pzbuffer:dword
+ externdef _d_zistepv:dword
+ externdef _d_zrowbytes:dword
+ externdef _d_ziorigin:dword
+ externdef _r_turb_s:dword
+ externdef _r_turb_t:dword
+ externdef _r_turb_pdest:dword
+ externdef _r_turb_spancount:dword
+ externdef _r_turb_turb:dword
+ externdef _r_turb_pbase:dword
+ externdef _r_turb_sstep:dword
+ externdef _r_turb_tstep:dword
+ externdef _r_bmodelactive:dword
+ externdef _d_sdivzstepu:dword
+ externdef _d_tdivzstepu:dword
+ externdef _d_sdivzstepv:dword
+ externdef _d_tdivzstepv:dword
+ externdef _d_sdivzorigin:dword
+ externdef _d_tdivzorigin:dword
+ externdef _sadjust:dword
+ externdef _tadjust:dword
+ externdef _bbextents:dword
+ externdef _bbextentt:dword
+ externdef _cacheblock:dword
+ externdef _d_viewbuffer:dword
+ externdef _cachewidth:dword
+ externdef _d_pzbuffer:dword
+ externdef _d_zrowbytes:dword
+ externdef _d_zwidth:dword
+ externdef _d_scantable:dword
+ externdef _r_lightptr:dword
+ externdef _r_numvblocks:dword
+ externdef _prowdestbase:dword
+ externdef _pbasesource:dword
+ externdef _r_lightwidth:dword
+ externdef _lightright:dword
+ externdef _lightrightstep:dword
+ externdef _lightdeltastep:dword
+ externdef _lightdelta:dword
+ externdef _lightright:dword
+ externdef _lightdelta:dword
+ externdef _sourcetstep:dword
+ externdef _surfrowbytes:dword
+ externdef _lightrightstep:dword
+ externdef _lightdeltastep:dword
+ externdef _r_sourcemax:dword
+ externdef _r_stepback:dword
+ externdef _colormap:dword
+ externdef _blocksize:dword
+ externdef _sourcesstep:dword
+ externdef _lightleft:dword
+ externdef _blockdivshift:dword
+ externdef _blockdivmask:dword
+ externdef _lightleftstep:dword
+ externdef _r_origin:dword
+ externdef _r_ppn:dword
+ externdef _r_pup:dword
+ externdef _r_pright:dword
+ externdef _ycenter:dword
+ externdef _xcenter:dword
+ externdef _d_vrectbottom_particle:dword
+ externdef _d_vrectright_particle:dword
+ externdef _d_vrecty:dword
+ externdef _d_vrectx:dword
+ externdef _d_pix_shift:dword
+ externdef _d_pix_min:dword
+ externdef _d_pix_max:dword
+ externdef _d_y_aspect_shift:dword
+ externdef _screenwidth:dword
+ externdef _vright:dword
+ externdef _vup:dword
+ externdef _vpn:dword
+ externdef _BOPS_Error:dword
+ externdef _snd_scaletable:dword
+ externdef _paintbuffer:dword
+ externdef _snd_linear_count:dword
+ externdef _snd_p:dword
+ externdef _snd_vol:dword
+ externdef _snd_out:dword
+ externdef _r_leftclipped:dword
+ externdef _r_leftenter:dword
+ externdef _r_rightclipped:dword
+ externdef _r_rightenter:dword
+ externdef _modelorg:dword
+ externdef _xscale:dword
+ externdef _r_refdef:dword
+ externdef _yscale:dword
+ externdef _r_leftexit:dword
+ externdef _r_rightexit:dword
+ externdef _r_lastvertvalid:dword
+ externdef _cacheoffset:dword
+ externdef _newedges:dword
+ externdef _removeedges:dword
+ externdef _r_pedge:dword
+ externdef _r_framecount:dword
+ externdef _r_u1:dword
+ externdef _r_emitted:dword
+ externdef _edge_p:dword
+ externdef _surface_p:dword
+ externdef _surfaces:dword
+ externdef _r_lzi1:dword
+ externdef _r_v1:dword
+ externdef _r_ceilv1:dword
+ externdef _r_nearzi:dword
+ externdef _r_nearzionly:dword
+ externdef _edge_aftertail:dword
+ externdef _edge_tail:dword
+ externdef _current_iv:dword
+ externdef _edge_head_u_shift20:dword
+ externdef _span_p:dword
+ externdef _edge_head:dword
+ externdef _fv:dword
+ externdef _edge_tail_u_shift20:dword
+ externdef _r_apverts:dword
+ externdef _r_anumverts:dword
+ externdef _aliastransform:dword
+ externdef _r_avertexnormals:dword
+ externdef _r_plightvec:dword
+ externdef _r_ambientlight:dword
+ externdef _r_shadelight:dword
+ externdef _aliasxcenter:dword
+ externdef _aliasycenter:dword
+ externdef _a_sstepxfrac:dword
+ externdef _r_affinetridesc:dword
+ externdef _acolormap:dword
+ externdef _d_pcolormap:dword
+ externdef _r_affinetridesc:dword
+ externdef _d_sfrac:dword
+ externdef _d_ptex:dword
+ externdef _d_pedgespanpackage:dword
+ externdef _d_tfrac:dword
+ externdef _d_light:dword
+ externdef _d_zi:dword
+ externdef _d_pdest:dword
+ externdef _d_pz:dword
+ externdef _d_aspancount:dword
+ externdef _erroradjustup:dword
+ externdef _errorterm:dword
+ externdef _d_xdenom:dword
+ externdef _r_p0:dword
+ externdef _r_p1:dword
+ externdef _r_p2:dword
+ externdef _a_tstepxfrac:dword
+ externdef _r_sstepx:dword
+ externdef _r_tstepx:dword
+ externdef _a_ststepxwhole:dword
+ externdef _zspantable:dword
+ externdef _skintable:dword
+ externdef _r_zistepx:dword
+ externdef _erroradjustdown:dword
+ externdef _d_countextrastep:dword
+ externdef _ubasestep:dword
+ externdef _a_ststepxwhole:dword
+ externdef _a_tstepxfrac:dword
+ externdef _r_lstepx:dword
+ externdef _a_spans:dword
+ externdef _erroradjustdown:dword
+ externdef _d_pdestextrastep:dword
+ externdef _d_pzextrastep:dword
+ externdef _d_sfracextrastep:dword
+ externdef _d_ptexextrastep:dword
+ externdef _d_countextrastep:dword
+ externdef _d_tfracextrastep:dword
+ externdef _d_lightextrastep:dword
+ externdef _d_ziextrastep:dword
+ externdef _d_pdestbasestep:dword
+ externdef _d_pzbasestep:dword
+ externdef _d_sfracbasestep:dword
+ externdef _d_ptexbasestep:dword
+ externdef _ubasestep:dword
+ externdef _d_tfracbasestep:dword
+ externdef _d_lightbasestep:dword
+ externdef _d_zibasestep:dword
+ externdef _zspantable:dword
+ externdef _r_lstepy:dword
+ externdef _r_sstepy:dword
+ externdef _r_tstepy:dword
+ externdef _r_zistepy:dword
+ externdef _D_PolysetSetEdgeTable:dword
+ externdef _D_RasterizeAliasPolySmooth:dword
+ externdef float_point5:dword
+ externdef Float2ToThe31nd:dword
+ externdef izistep:dword
+ externdef izi:dword
+ externdef FloatMinus2ToThe31nd:dword
+ externdef float_1:dword
+ externdef float_particle_z_clip:dword
+ externdef float_minus_1:dword
+ externdef float_0:dword
+ externdef fp_16:dword
+ externdef fp_64k:dword
+ externdef fp_1m:dword
+ externdef fp_1m_minus_1:dword
+ externdef fp_8:dword
+ externdef entryvec_table:dword
+ externdef advancetable:dword
+ externdef sstep:dword
+ externdef tstep:dword
+ externdef pspantemp:dword
+ externdef counttemp:dword
+ externdef jumptemp:dword
+ externdef reciprocal_table:dword
+ externdef DP_Count:dword
+ externdef DP_u:dword
+ externdef DP_v:dword
+ externdef DP_32768:dword
+ externdef DP_Color:dword
+ externdef DP_Pix:dword
+ externdef DP_EntryTable:dword
+ externdef pbase:dword
+ externdef s:dword
+ externdef t:dword
+ externdef sfracf:dword
+ externdef tfracf:dword
+ externdef snext:dword
+ externdef tnext:dword
+ externdef spancountminus1:dword
+ externdef zi16stepu:dword
+ externdef sdivz16stepu:dword
+ externdef tdivz16stepu:dword
+ externdef zi8stepu:dword
+ externdef sdivz8stepu:dword
+ externdef tdivz8stepu:dword
+ externdef reciprocal_table_16:dword
+ externdef entryvec_table_16:dword
+ externdef ceil_cw:dword
+ externdef single_cw:dword
+ externdef fp_64kx64k:dword
+ externdef pz:dword
+ externdef spr8entryvec_table:dword
+_DATA SEGMENT
+ align 4
+fpenv:
+ dd 0, 0, 0, 0, 0, 0, 0, 0
+_DATA ENDS
+_TEXT SEGMENT
+ public _MaskExceptions
+_MaskExceptions:
+ fnstenv ds:dword ptr[fpenv]
+ or ds:dword ptr[fpenv],03Fh
+ fldenv ds:dword ptr[fpenv]
+ ret
+_TEXT ENDS
+_DATA SEGMENT
+ align 4
+ public ceil_cw, single_cw, full_cw, cw, pushed_cw
+ceil_cw dd 0
+single_cw dd 0
+full_cw dd 0
+cw dd 0
+pushed_cw dd 0
+_DATA ENDS
+_TEXT SEGMENT
+ public _Sys_LowFPPrecision
+_Sys_LowFPPrecision:
+ fldcw ds:word ptr[single_cw]
+ ret
+ public _Sys_HighFPPrecision
+_Sys_HighFPPrecision:
+ fldcw ds:word ptr[full_cw]
+ ret
+ public _Sys_PushFPCW_SetHigh
+_Sys_PushFPCW_SetHigh:
+ fnstcw ds:word ptr[pushed_cw]
+ fldcw ds:word ptr[full_cw]
+ ret
+ public _Sys_PopFPCW
+_Sys_PopFPCW:
+ fldcw ds:word ptr[pushed_cw]
+ ret
+ public _Sys_SetFPCW
+_Sys_SetFPCW:
+ fnstcw ds:word ptr[cw]
+ mov eax,ds:dword ptr[cw]
+ and ah,0F0h
+ or ah,003h
+ mov ds:dword ptr[full_cw],eax
+ and ah,0F0h
+ or ah,00Ch
+ mov ds:dword ptr[single_cw],eax
+ and ah,0F0h
+ or ah,008h
+ mov ds:dword ptr[ceil_cw],eax
+ ret
+_TEXT ENDS
+ END
--- /dev/null
+++ b/QW/client/sys_wina.s
@@ -1,0 +1,115 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+//
+// sys_wina.s
+// x86 assembly-language Win-dependent routines.
+
+#include "asm_i386.h"
+#include "quakeasm.h"
+
+//@@@ should be id386-dependent, and have an equivalent C path
+
+	.data
+
+	.align	4
+fpenv:
+	.long	0, 0, 0, 0, 0, 0, 0, 0
+
+	.text
+
+.globl C(MaskExceptions)
+C(MaskExceptions):
+	fnstenv	fpenv
+	orl		$0x3F,fpenv
+	fldenv	fpenv
+
+	ret
+
+#if 0
+.globl C(unmaskexceptions)
+C(unmaskexceptions):
+	fnstenv	fpenv
+	andl		$0xFFFFFFE0,fpenv
+	fldenv	fpenv
+
+	ret
+#endif
+
+	.data
+
+	.align	4
+.globl	ceil_cw, single_cw, full_cw, cw, pushed_cw
+ceil_cw:	.long	0
+single_cw:	.long	0
+full_cw:	.long	0
+cw:			.long	0
+pushed_cw:	.long	0
+
+	.text
+
+.globl C(Sys_LowFPPrecision)
+C(Sys_LowFPPrecision):
+	fldcw	single_cw
+
+	ret
+
+.globl C(Sys_HighFPPrecision)
+C(Sys_HighFPPrecision):
+	fldcw	full_cw
+
+	ret
+
+.globl C(Sys_PushFPCW_SetHigh)
+C(Sys_PushFPCW_SetHigh):
+	fnstcw	pushed_cw
+	fldcw	full_cw
+
+	ret
+
+.globl C(Sys_PopFPCW)
+C(Sys_PopFPCW):
+	fldcw	pushed_cw
+
+	ret
+
+.globl C(Sys_SetFPCW)
+C(Sys_SetFPCW):
+	fnstcw	cw
+	movl	cw,%eax
+#if	id386
+	andb	$0xF0,%ah
+	orb		$0x03,%ah	// round mode, 64-bit precision
+#endif
+	movl	%eax,full_cw
+
+#if	id386
+	andb	$0xF0,%ah
+	orb		$0x0C,%ah	// chop mode, single precision
+#endif
+	movl	%eax,single_cw
+
+#if	id386
+	andb	$0xF0,%ah
+	orb		$0x08,%ah	// ceil mode, single precision
+#endif
+	movl	%eax,ceil_cw
+
+	ret
+
--- /dev/null
+++ b/QW/client/vid.h
@@ -1,0 +1,92 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// vid.h -- video driver defs
+
+#define VID_CBITS	6
+#define VID_GRADES	(1 << VID_CBITS)
+
+// a pixel can be one, two, or four bytes
+typedef byte pixel_t;
+
+typedef struct vrect_s
+{
+	int				x,y,width,height;
+	struct vrect_s	*pnext;
+} vrect_t;
+
+typedef struct
+{
+	pixel_t			*buffer;		// invisible buffer
+	pixel_t			*colormap;		// 256 * VID_GRADES size
+	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;
+	float			aspect;		// width / height -- < 0 is taller than wide
+	int				numpages;
+	int				recalc_refdef;	// if true, recalc vid-based stuff
+	pixel_t			*conbuffer;
+	int				conrowbytes;
+	unsigned		conwidth;
+	unsigned		conheight;
+	int				maxwarpwidth;
+	int				maxwarpheight;
+	pixel_t			*direct;		// direct drawing to framebuffer, if not
+									//  NULL
+} viddef_t;
+
+extern	viddef_t	vid;				// global video state
+extern	unsigned short	d_8to16table[256];
+extern	unsigned	d_8to24table[256];
+extern void (*vid_menudrawfn)(void);
+extern void (*vid_menukeyfn)(int key);
+
+void	VID_SetPalette (unsigned char *palette);
+// called at startup and after any gamma correction
+
+void	VID_ShiftPalette (unsigned char *palette);
+// called for bonus and pain flashes, and for underwater color changes
+
+void	VID_Init (unsigned char *palette);
+// Called at startup to set up translation tables, takes 256 8 bit RGB values
+// the palette data will go away after the call, so it must be copied off if
+// the video driver will need it again
+
+void	VID_Shutdown (void);
+// Called at shutdown
+
+void	VID_Update (vrect_t *rects);
+// flushes the given rectangles from the view buffer to the screen
+
+int VID_SetMode (int modenum, unsigned char *palette);
+// sets the mode; only used by the Quake engine for resetting to mode 0 (the
+// base mode) on memory allocation failures
+
+void VID_HandlePause (qboolean pause);
+// called only on Win32, when pause happens, so the mouse can be released
+
+void VID_LockBuffer (void);
+void VID_UnlockBuffer (void);
+
+#ifdef GLQUAKE
+qboolean VID_Is8bit(void);
+#endif
+
--- /dev/null
+++ b/QW/client/vid_null.c
@@ -1,0 +1,68 @@
+// vid_null.c -- null video driver to aid porting efforts
+
+#include "quakedef.h"
+#include "d_local.h"
+
+viddef_t	vid;				// global video state
+
+#define	BASEWIDTH	320
+#define	BASEHEIGHT	200
+
+byte	vid_buffer[BASEWIDTH*BASEHEIGHT];
+short	zbuffer[BASEWIDTH*BASEHEIGHT];
+byte	surfcache[256*1024];
+
+unsigned short	d_8to16table[256];
+unsigned	d_8to24table[256];
+
+void	VID_SetPalette (unsigned char *palette)
+{
+}
+
+void	VID_ShiftPalette (unsigned char *palette)
+{
+}
+
+void	VID_Init (unsigned char *palette)
+{
+	vid.maxwarpwidth = vid.width = vid.conwidth = BASEWIDTH;
+	vid.maxwarpheight = vid.height = vid.conheight = BASEHEIGHT;
+	vid.aspect = 1.0;
+	vid.numpages = 1;
+	vid.colormap = host_colormap;
+	vid.fullbright = 256 - LittleLong (*((int *)vid.colormap + 2048));
+	vid.buffer = vid.conbuffer = vid_buffer;
+	vid.rowbytes = vid.conrowbytes = BASEWIDTH;
+	
+	d_pzbuffer = zbuffer;
+	D_InitCaches (surfcache, sizeof(surfcache));
+}
+
+void	VID_Shutdown (void)
+{
+}
+
+void	VID_Update (vrect_t *rects)
+{
+}
+
+/*
+================
+D_BeginDirectRect
+================
+*/
+void D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height)
+{
+}
+
+
+/*
+================
+D_EndDirectRect
+================
+*/
+void D_EndDirectRect (int x, int y, int width, int height)
+{
+}
+
+
--- /dev/null
+++ b/QW/client/vid_svgalib.c
@@ -1,0 +1,1025 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+#include <termios.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/vt.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <signal.h>
+
+#include <asm/io.h>
+
+#include "vga.h"
+#include "vgakeyboard.h"
+#include "vgamouse.h"
+
+#include "quakedef.h"
+#include "d_local.h"
+
+#define stringify(m) { #m, m }
+
+unsigned short       d_8to16table[256];
+static byte		*vid_surfcache;
+static int		VID_highhunkmark;
+
+int num_modes;
+vga_modeinfo *modes;
+int current_mode;
+
+int num_shades=32;
+
+struct
+{
+	char *name;
+	int num;
+} mice[] =
+{
+	stringify(MOUSE_MICROSOFT),
+	stringify(MOUSE_MOUSESYSTEMS),
+	stringify(MOUSE_MMSERIES),
+	stringify(MOUSE_LOGITECH),
+	stringify(MOUSE_BUSMOUSE),
+	stringify(MOUSE_PS2),
+};
+
+static unsigned char scantokey[128];
+static byte vid_current_palette[768];
+
+int num_mice = sizeof (mice) / sizeof(mice[0]);
+
+int	d_con_indirect = 0;
+
+int		svgalib_inited=0;
+int		UseMouse = 1;
+int		UseDisplay = 1;
+int		UseKeyboard = 1;
+
+int		mouserate = MOUSE_DEFAULTSAMPLERATE;
+
+cvar_t		vid_mode = {"vid_mode","5",false};
+cvar_t		vid_redrawfull = {"vid_redrawfull","0",false};
+cvar_t		vid_waitforrefresh = {"vid_waitforrefresh","0",true};
+ 
+char	*framebuffer_ptr;
+
+cvar_t  mouse_button_commands[3] =
+{
+    {"mouse1","+attack"},
+    {"mouse2","+strafe"},
+    {"mouse3","+forward"},
+};
+
+int     mouse_buttons;
+int     mouse_buttonstate;
+int     mouse_oldbuttonstate;
+float   mouse_x, mouse_y;
+float	old_mouse_x, old_mouse_y;
+int		mx, my;
+
+cvar_t _windowed_mouse = {"_windowed_mouse", "1", true};
+cvar_t	m_filter = {"m_filter","0"};
+
+static byte     backingbuf[48*24];
+
+int		VGA_width, VGA_height, VGA_rowbytes, VGA_bufferrowbytes, VGA_planar;
+byte	*VGA_pagebase;
+
+void VGA_UpdatePlanarScreen (void *srcbuffer);
+
+void D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height)
+{
+	int i, j, k, plane, reps, repshift, offset, vidpage, off;
+
+	if (!svgalib_inited || !vid.direct || !vga_oktowrite()) return;
+
+	if (vid.aspect > 1.5)
+	{
+		reps = 2;
+		repshift = 1;
+	} else {
+		reps = 1;
+		repshift = 0;
+	}
+
+	vidpage = 0;
+	vga_setpage(0);
+
+	if (VGA_planar)
+	{
+		for (plane=0 ; plane<4 ; plane++)
+		{
+		// select the correct plane for reading and writing
+			outb(0x02, 0x3C4);
+			outb(1 << plane, 0x3C5);
+			outb(4, 0x3CE);
+			outb(plane, 0x3CF);
+
+			for (i=0 ; i<(height << repshift) ; i += reps)
+			{
+				for (k=0 ; k<reps ; k++)
+				{
+					for (j=0 ; j<(width >> 2) ; j++)
+					{
+						backingbuf[(i + k) * 24 + (j << 2) + plane] =
+								vid.direct[(y + i + k) * VGA_rowbytes +
+								(x >> 2) + j];
+						vid.direct[(y + i + k) * VGA_rowbytes + (x>>2) + j] =
+								pbitmap[(i >> repshift) * 24 +
+								(j << 2) + plane];
+					}
+				}
+			}
+		}
+	} else {
+		for (i=0 ; i<(height << repshift) ; i += reps)
+		{
+			for (j=0 ; j<reps ; j++)
+			{
+				offset = x + ((y << repshift) + i + j) * vid.rowbytes;
+				off = offset % 0x10000;
+				if ((offset / 0x10000) != vidpage) {
+					vidpage=offset / 0x10000;
+					vga_setpage(vidpage);
+				}
+				memcpy (&backingbuf[(i + j) * 24],
+						vid.direct + off, width);
+				memcpy (vid.direct + off,
+						&pbitmap[(i >> repshift)*width], width);
+			}
+		}
+	}
+}
+
+void D_EndDirectRect (int x, int y, int width, int height)
+{
+	int i, j, k, plane, reps, repshift, offset, vidpage, off;
+
+	if (!svgalib_inited || !vid.direct || !vga_oktowrite()) return;
+
+	if (vid.aspect > 1.5)
+	{
+		reps = 2;
+		repshift = 1;
+	} else {
+		reps = 1;
+		repshift = 0;
+	}
+
+	vidpage = 0;
+	vga_setpage(0);
+
+	if (VGA_planar)
+	{
+		for (plane=0 ; plane<4 ; plane++)
+		{
+		// select the correct plane for writing
+			outb(2, 0x3C4);
+			outb(1 << plane, 0x3C5);
+			outb(4, 0x3CE);
+			outb(plane, 0x3CF);
+
+			for (i=0 ; i<(height << repshift) ; i += reps)
+			{
+				for (k=0 ; k<reps ; k++)
+				{
+					for (j=0 ; j<(width >> 2) ; j++)
+					{
+						vid.direct[(y + i + k) * VGA_rowbytes + (x>>2) + j] =
+								backingbuf[(i + k) * 24 + (j << 2) + plane];
+					}
+				}
+			}
+		}
+	} else {
+		for (i=0 ; i<(height << repshift) ; i += reps)
+		{
+			for (j=0 ; j<reps ; j++)
+			{
+				offset = x + ((y << repshift) + i + j) * vid.rowbytes;
+				off = offset % 0x10000;
+				if ((offset / 0x10000) != vidpage) {
+					vidpage=offset / 0x10000;
+					vga_setpage(vidpage);
+				}
+				memcpy (vid.direct + off, 
+						&backingbuf[(i +j)*24],
+						width);
+			}
+		}
+	}
+}
+
+/*
+=================
+VID_Gamma_f
+
+Keybinding command
+=================
+*/
+void VID_Gamma_f (void)
+{
+	float	gamma, f, inf;
+	unsigned char	palette[768];
+	int		i;
+
+	if (Cmd_Argc () == 2)
+	{
+		gamma = Q_atof (Cmd_Argv(1));
+
+		for (i=0 ; i<768 ; i++)
+		{
+			f = pow ( (host_basepal[i]+1)/256.0 , gamma );
+			inf = f*255 + 0.5;
+			if (inf < 0)
+				inf = 0;
+			if (inf > 255)
+				inf = 255;
+			palette[i] = inf;
+		}
+
+		VID_SetPalette (palette);
+
+		vid.recalc_refdef = 1;				// force a surface cache flush
+	}
+}
+
+void VID_DescribeMode_f (void)
+{
+	int modenum;
+	
+	modenum = Q_atoi (Cmd_Argv(1));
+	if ((modenum >= num_modes) || (modenum < 0 ) || !modes[modenum].width)
+		Con_Printf("Invalid video mode: %d!\n",modenum);
+	Con_Printf("%d: %d x %d - ",modenum,modes[modenum].width,modes[modenum].height);
+	if (modes[modenum].bytesperpixel == 0)
+		Con_Printf("ModeX\n");
+	else
+		Con_Printf("%d bpp\n", modes[modenum].bytesperpixel<<3);
+}
+
+void VID_DescribeModes_f (void)
+{
+	int i;
+	
+	for (i=0;i<num_modes;i++)
+		if (modes[i].width) {
+			Con_Printf("%d: %d x %d - ", i, modes[i].width,modes[i].height);
+			if (modes[i].bytesperpixel == 0)
+				Con_Printf("ModeX\n");
+			else
+				Con_Printf("%d bpp\n", modes[i].bytesperpixel<<3);
+		}
+}
+
+/*
+================
+VID_NumModes
+================
+*/
+int VID_NumModes ()
+{
+	int i,i1=0;
+	
+	for (i=0;i<num_modes;i++)
+		i1+=(modes[i].width?1:0);
+	return (i1);
+}
+
+void VID_NumModes_f (void)
+{
+	Con_Printf("%d modes\n",VID_NumModes());
+}
+
+void VID_Debug_f (void)
+{
+	Con_Printf("mode: %d\n",current_mode);
+	Con_Printf("height x width: %d x %d\n",vid.height,vid.width);
+	Con_Printf("bpp: %d\n",modes[current_mode].bytesperpixel*8);
+	Con_Printf("vid.aspect: %f\n",vid.aspect);
+}
+
+
+
+void VID_InitModes(void)
+{
+
+	int i;
+
+// get complete information on all modes
+
+	num_modes = vga_lastmodenumber()+1;
+	modes = Z_Malloc(num_modes * sizeof(vga_modeinfo));
+	for (i=0 ; i<num_modes ; i++)
+	{
+		if (vga_hasmode(i))
+			Q_memcpy(&modes[i], vga_getmodeinfo(i), sizeof (vga_modeinfo));
+		else
+			modes[i].width = 0; // means not available
+	}
+
+// filter for modes i don't support
+
+	for (i=0 ; i<num_modes ; i++)
+	{
+		if (modes[i].bytesperpixel != 1 && modes[i].colors != 256) 
+			modes[i].width = 0;
+	}
+
+}
+
+int get_mode(char *name, int width, int height, int depth)
+{
+
+	int i;
+	int ok, match;
+
+	match = (!!width) + (!!height)*2 + (!!depth)*4;
+
+	if (name)
+	{
+		i = vga_getmodenumber(name);
+		if (!modes[i].width)
+		{
+			Sys_Printf("Mode [%s] not supported\n", name);
+			i = G320x200x256;
+		}
+	}
+	else
+	{
+		for (i=0 ; i<num_modes ; i++)
+			if (modes[i].width)
+			{
+				ok = (modes[i].width == width)
+					+ (modes[i].height == height)*2
+					+ (modes[i].bytesperpixel == depth/8)*4;
+				if ((ok & match) == ok)
+					break;
+			}
+		if (i==num_modes)
+		{
+			Sys_Printf("Mode %dx%d (%d bits) not supported\n",
+				width, height, depth);
+			i = G320x200x256;
+		}
+	}
+
+	return i;
+
+}
+
+int matchmouse(int mouse, char *name)
+{
+	int i;
+	for (i=0 ; i<num_mice ; i++)
+		if (!strcmp(mice[i].name, name))
+			return i;
+	return mouse;
+}
+
+#if 0
+
+void vtswitch(int newconsole)
+{
+
+	int fd;
+	struct vt_stat x;
+
+// switch consoles and wait until reactivated
+	fd = open("/dev/console", O_RDONLY);
+	ioctl(fd, VT_GETSTATE, &x);
+	ioctl(fd, VT_ACTIVATE, newconsole);
+	ioctl(fd, VT_WAITACTIVE, x.v_active);
+	close(fd);
+
+}
+
+#endif
+
+void keyhandler(int scancode, int state)
+{
+	
+	int sc;
+
+	sc = scancode & 0x7f;
+//	Con_Printf("scancode=%x (%d%s)\n", scancode, sc, scancode&0x80?"+128":"");
+	Key_Event(scantokey[sc], state == KEY_EVENTPRESS);
+
+}
+
+void VID_Shutdown(void)
+{
+
+	if (!svgalib_inited) return;
+
+//	printf("shutdown graphics called\n");
+	if (UseKeyboard)
+		keyboard_close();
+	if (UseDisplay)
+		vga_setmode(TEXT);
+//	printf("shutdown graphics finished\n");
+
+	svgalib_inited = 0;
+
+}
+
+void VID_ShiftPalette(unsigned char *p)
+{
+	VID_SetPalette(p);
+}
+
+void VID_SetPalette(byte *palette)
+{
+
+	static int tmppal[256*3];
+	int *tp;
+	int i;
+
+	if (!svgalib_inited)
+		return;
+
+	memcpy(vid_current_palette, palette, sizeof(vid_current_palette));
+
+	if (vga_getcolors() == 256)
+	{
+
+		tp = tmppal;
+		for (i=256*3 ; i ; i--)
+			*(tp++) = *(palette++) >> 2;
+
+		if (UseDisplay && vga_oktowrite())
+			vga_setpalvec(0, 256, tmppal);
+
+	}
+}
+
+int VID_SetMode (int modenum, unsigned char *palette)
+{
+	int bsize, zsize, tsize;
+
+	if ((modenum >= num_modes) || (modenum < 0) || !modes[modenum].width)
+	{
+		Cvar_SetValue ("vid_mode", (float)current_mode);
+		
+		Con_Printf("No such video mode: %d\n",modenum);
+		
+		return 0;
+	}
+
+	Cvar_SetValue ("vid_mode", (float)modenum);
+	
+	current_mode=modenum;
+
+	vid.width = modes[current_mode].width;
+	vid.height = modes[current_mode].height;
+
+	VGA_width = modes[current_mode].width;
+	VGA_height = modes[current_mode].height;
+	VGA_planar = modes[current_mode].bytesperpixel == 0;
+	VGA_rowbytes = modes[current_mode].linewidth;
+	vid.rowbytes = modes[current_mode].linewidth;
+	if (VGA_planar) {
+		VGA_bufferrowbytes = modes[current_mode].linewidth * 4;
+		vid.rowbytes = modes[current_mode].linewidth*4;
+	}
+
+	vid.aspect = ((float)vid.height / (float)vid.width) * (320.0 / 240.0);
+	vid.colormap = (pixel_t *) host_colormap;
+	vid.fullbright = 256 - LittleLong (*((int *)vid.colormap + 2048));
+	vid.conrowbytes = vid.rowbytes;
+	vid.conwidth = vid.width;
+	vid.conheight = vid.height;
+	vid.numpages = 1;
+	
+	vid.maxwarpwidth = WARP_WIDTH;
+	vid.maxwarpheight = WARP_HEIGHT;
+
+	// alloc zbuffer and surface cache
+	if (d_pzbuffer) {
+		D_FlushCaches();
+		Hunk_FreeToHighMark (VID_highhunkmark);
+		d_pzbuffer = NULL;
+		vid_surfcache = NULL;
+	}
+
+	bsize = vid.rowbytes * vid.height;
+	tsize = D_SurfaceCacheForRes (vid.width, vid.height);
+	zsize = vid.width * vid.height * sizeof(*d_pzbuffer);
+
+	VID_highhunkmark = Hunk_HighMark ();
+
+	d_pzbuffer = Hunk_HighAllocName (bsize+tsize+zsize, "video");
+
+	vid_surfcache = ((byte *)d_pzbuffer) + zsize;
+
+	vid.conbuffer = vid.buffer = (pixel_t *)(((byte *)d_pzbuffer) + zsize + tsize);
+
+	D_InitCaches (vid_surfcache, tsize);
+
+// get goin'
+
+	vga_setmode(current_mode);
+	VID_SetPalette(palette);
+
+	VGA_pagebase = vid.direct = framebuffer_ptr = (char *) vga_getgraphmem();
+//		if (vga_setlinearaddressing()>0)
+//			framebuffer_ptr = (char *) vga_getgraphmem();
+	if (!framebuffer_ptr)
+		Sys_Error("This mode isn't hapnin'\n");
+
+	vga_setpage(0);
+
+	svgalib_inited=1;
+
+	vid.recalc_refdef = 1;				// force a surface cache flush
+
+	return 0;
+}
+
+void VID_Init(unsigned char *palette)
+{
+
+	int i;
+	int w, h, d;
+
+	S_Init(); // sound gets initialized here
+
+	if (svgalib_inited)
+		return;
+
+//	Cmd_AddCommand ("gamma", VID_Gamma_f);
+
+	if (UseDisplay)
+	{
+		vga_init();
+
+		VID_InitModes();
+
+		Cvar_RegisterVariable (&vid_mode);
+		Cvar_RegisterVariable (&vid_redrawfull);
+		Cvar_RegisterVariable (&vid_waitforrefresh);
+		
+		Cmd_AddCommand("vid_nummodes", VID_NumModes_f);
+		Cmd_AddCommand("vid_describemode", VID_DescribeMode_f);
+		Cmd_AddCommand("vid_describemodes", VID_DescribeModes_f);
+		Cmd_AddCommand("vid_debug", VID_Debug_f);
+
+	// interpret command-line params
+
+		w = h = d = 0;
+		if (getenv("GSVGAMODE"))
+			current_mode = get_mode(getenv("GSVGAMODE"), w, h, d);
+		else if (COM_CheckParm("-mode"))
+			current_mode = get_mode(com_argv[COM_CheckParm("-mode")+1], w, h, d);
+		else if (COM_CheckParm("-w") || COM_CheckParm("-h")
+			|| COM_CheckParm("-d"))
+		{
+			if (COM_CheckParm("-w"))
+				w = Q_atoi(com_argv[COM_CheckParm("-w")+1]);
+			if (COM_CheckParm("-h"))
+				h = Q_atoi(com_argv[COM_CheckParm("-h")+1]);
+			if (COM_CheckParm("-d"))
+				d = Q_atoi(com_argv[COM_CheckParm("-d")+1]);
+			current_mode = get_mode(0, w, h, d);
+		}
+		else
+			current_mode = G320x200x256;
+
+	// set vid parameters
+		VID_SetMode(current_mode, palette);
+
+		VID_SetPalette(palette);
+
+		// we do want to run in the background when switched away
+		vga_runinbackground(1);	
+	}
+
+	if (COM_CheckParm("-nokbd")) UseKeyboard = 0;
+
+	if (UseKeyboard)
+	{
+		for (i=0 ; i<128 ; i++)
+			scantokey[i] = ' ';
+
+		scantokey[  1] = K_ESCAPE;
+		scantokey[  2] = '1';
+		scantokey[  3] = '2';
+		scantokey[  4] = '3';
+		scantokey[  5] = '4';
+		scantokey[  6] = '5';
+		scantokey[  7] = '6';
+		scantokey[  8] = '7';
+		scantokey[  9] = '8';
+		scantokey[ 10] = '9';
+		scantokey[ 11] = '0';
+		scantokey[ 12] = '-';
+		scantokey[ 13] = '=';
+		scantokey[ 14] = K_BACKSPACE;
+		scantokey[ 15] = K_TAB;
+		scantokey[ 16] = 'q';       
+		scantokey[ 17] = 'w';       
+		scantokey[ 18] = 'e';       
+		scantokey[ 19] = 'r';       
+		scantokey[ 20] = 't';       
+		scantokey[ 21] = 'y';       
+		scantokey[ 22] = 'u';       
+		scantokey[ 23] = 'i';       
+		scantokey[ 24] = 'o';       
+		scantokey[ 25] = 'p';       
+		scantokey[ 26] = '[';
+		scantokey[ 27] = ']';
+		scantokey[ 28] = K_ENTER;
+		scantokey[ 29] = K_CTRL; //left
+		scantokey[ 30] = 'a';
+		scantokey[ 31] = 's';       
+		scantokey[ 32] = 'd';       
+		scantokey[ 33] = 'f';       
+		scantokey[ 34] = 'g';       
+		scantokey[ 35] = 'h';       
+		scantokey[ 36] = 'j';       
+		scantokey[ 37] = 'k';       
+		scantokey[ 38] = 'l';       
+		scantokey[ 39] = ';';
+		scantokey[ 40] = '\'';
+		scantokey[ 41] = '`';
+		scantokey[ 42] = K_SHIFT; //left
+		scantokey[ 43] = '\\';
+		scantokey[ 44] = 'z';       
+		scantokey[ 45] = 'x';  
+		scantokey[ 46] = 'c';
+		scantokey[ 47] = 'v';       
+		scantokey[ 48] = 'b';
+		scantokey[ 49] = 'n';       
+		scantokey[ 50] = 'm';       
+		scantokey[ 51] = ',';
+		scantokey[ 52] = '.';
+		scantokey[ 53] = '/';
+		scantokey[ 54] = K_SHIFT; //right
+		scantokey[ 55] = '*'; //keypad
+		scantokey[ 56] = K_ALT; //left
+		scantokey[ 57] = ' ';
+		// 58 caps lock
+		scantokey[ 59] = K_F1;
+		scantokey[ 60] = K_F2;
+		scantokey[ 61] = K_F3;
+		scantokey[ 62] = K_F4;
+		scantokey[ 63] = K_F5;
+		scantokey[ 64] = K_F6;
+		scantokey[ 65] = K_F7;
+		scantokey[ 66] = K_F8;
+		scantokey[ 67] = K_F9;
+		scantokey[ 68] = K_F10;
+		// 69 numlock
+		// 70 scrollock
+		scantokey[ 71] = K_HOME;
+		scantokey[ 72] = K_UPARROW;
+		scantokey[ 73] = K_PGUP;
+		scantokey[ 74] = '-';
+		scantokey[ 75] = K_LEFTARROW;
+		scantokey[ 76] = '5';
+		scantokey[ 77] = K_RIGHTARROW;
+		scantokey[ 79] = K_END;
+		scantokey[ 78] = '+';
+		scantokey[ 80] = K_DOWNARROW;
+		scantokey[ 81] = K_PGDN;
+		scantokey[ 82] = K_INS;
+		scantokey[ 83] = K_DEL;
+		// 84 to 86 not used
+		scantokey[ 87] = K_F11;
+		scantokey[ 88] = K_F12;
+		// 89 to 95 not used
+		scantokey[ 96] = K_ENTER; //keypad enter
+		scantokey[ 97] = K_CTRL; //right
+		scantokey[ 98] = '/';
+		scantokey[ 99] = K_F12; // print screen, bind to screenshot by default
+		scantokey[100] = K_ALT; // right
+
+		scantokey[101] = K_PAUSE; // break
+		scantokey[102] = K_HOME;
+		scantokey[103] = K_UPARROW;
+		scantokey[104] = K_PGUP;
+		scantokey[105] = K_LEFTARROW;
+		scantokey[106] = K_RIGHTARROW;
+		scantokey[107] = K_END;
+		scantokey[108] = K_DOWNARROW;
+		scantokey[109] = K_PGDN;
+		scantokey[110] = K_INS;
+		scantokey[111] = K_DEL;
+
+		scantokey[119] = K_PAUSE;
+
+		if (keyboard_init())
+			Sys_Error("keyboard_init() failed");
+		keyboard_seteventhandler(keyhandler);
+	}
+
+}
+
+void VID_Update(vrect_t *rects)
+{
+	if (!svgalib_inited)
+		return;
+
+	if (!vga_oktowrite())
+		return; // can't update screen if it's not active
+
+	if (vid_waitforrefresh.value)
+		vga_waitretrace();
+
+	if (VGA_planar)
+		VGA_UpdatePlanarScreen (vid.buffer);
+
+	else if (vid_redrawfull.value) {
+		int total = vid.rowbytes * vid.height;
+		int offset;
+
+		for (offset=0;offset<total;offset+=0x10000) {
+			vga_setpage(offset/0x10000);
+			memcpy(framebuffer_ptr,
+					vid.buffer + offset,
+					((total-offset>0x10000)?0x10000:(total-offset)));
+		}
+	} else {
+		int ycount;
+		int offset;
+		int vidpage=0;
+
+		vga_setpage(0);
+
+		while (rects)
+		{
+			ycount = rects->height;
+			offset = rects->y * vid.rowbytes + rects->x;
+			while (ycount--)
+			{
+				register int i = offset % 0x10000;
+	
+				if ((offset / 0x10000) != vidpage) {
+					vidpage=offset / 0x10000;
+					vga_setpage(vidpage);
+				}
+				if (rects->width + i > 0x10000) {
+					memcpy(framebuffer_ptr + i, 
+							vid.buffer + offset, 
+							0x10000 - i);
+					vga_setpage(++vidpage);
+					memcpy(framebuffer_ptr,
+							vid.buffer + offset + 0x10000 - i, 
+							rects->width - 0x10000 + i);
+				} else
+					memcpy(framebuffer_ptr + i, 
+							vid.buffer + offset, 
+							rects->width);
+				offset += vid.rowbytes;
+			}
+	
+			rects = rects->pnext;
+		}
+	}
+	
+	if (vid_mode.value != current_mode)
+		VID_SetMode ((int)vid_mode.value, vid_current_palette);
+}
+
+static int dither;
+
+void VID_DitherOn(void)
+{
+    if (dither == 0)
+    {
+//		R_ViewChanged (&vrect, sb_lines, vid.aspect);
+        dither = 1;
+    }
+}
+
+void VID_DitherOff(void)
+{
+    if (dither)
+    {
+//		R_ViewChanged (&vrect, sb_lines, vid.aspect);
+        dither = 0;
+    }
+}
+
+void Sys_SendKeyEvents(void)
+{
+	if (!svgalib_inited)
+		return;
+
+	if (UseKeyboard)
+		while (keyboard_update());
+}
+
+void Force_CenterView_f (void)
+{
+	cl.viewangles[PITCH] = 0;
+}
+
+
+void mousehandler(int buttonstate, int dx, int dy)
+{
+	mouse_buttonstate = buttonstate;
+	mx += dx;
+	my += dy;
+}
+
+void IN_Init(void)
+{
+
+	int mtype;
+	char *mousedev;
+	int mouserate;
+
+	Cvar_RegisterVariable (&m_filter);
+
+	if (UseMouse)
+	{
+		Cvar_RegisterVariable (&mouse_button_commands[0]);
+		Cvar_RegisterVariable (&mouse_button_commands[1]);
+		Cvar_RegisterVariable (&mouse_button_commands[2]);
+		Cmd_AddCommand ("force_centerview", Force_CenterView_f);
+
+		mouse_buttons = 3;
+
+		mtype = vga_getmousetype();
+
+		mousedev = "/dev/mouse";
+		if (getenv("MOUSEDEV")) mousedev = getenv("MOUSEDEV");
+		if (COM_CheckParm("-mdev"))
+			mousedev = com_argv[COM_CheckParm("-mdev")+1];
+
+		mouserate = 1200;
+		if (getenv("MOUSERATE")) mouserate = atoi(getenv("MOUSERATE"));
+		if (COM_CheckParm("-mrate"))
+			mouserate = atoi(com_argv[COM_CheckParm("-mrate")+1]);
+
+//		printf("Mouse: dev=%s,type=%s,speed=%d\n",
+//			mousedev, mice[mtype].name, mouserate);
+		if (mouse_init(mousedev, mtype, mouserate))
+		{
+			Con_Printf("No mouse found\n");
+			UseMouse = 0;
+		}
+		else
+			mouse_seteventhandler(mousehandler);
+
+	}
+
+}
+
+void IN_Shutdown(void)
+{
+	if (UseMouse)
+		mouse_close();
+}
+
+/*
+===========
+IN_Commands
+===========
+*/
+void IN_Commands (void)
+{
+	if (UseMouse /*&& cls.state != ca_dedicated*/)
+	{
+		// poll mouse values
+		while (mouse_update())
+			;
+
+		// perform button actions
+		if ((mouse_buttonstate & MOUSE_LEFTBUTTON) &&
+			!(mouse_oldbuttonstate & MOUSE_LEFTBUTTON))
+			Key_Event (K_MOUSE1, true);
+		else if (!(mouse_buttonstate & MOUSE_LEFTBUTTON) &&
+			(mouse_oldbuttonstate & MOUSE_LEFTBUTTON))
+			Key_Event (K_MOUSE1, false);
+
+		if ((mouse_buttonstate & MOUSE_RIGHTBUTTON) &&
+			!(mouse_oldbuttonstate & MOUSE_RIGHTBUTTON))
+			Key_Event (K_MOUSE2, true);
+		else if (!(mouse_buttonstate & MOUSE_RIGHTBUTTON) &&
+			(mouse_oldbuttonstate & MOUSE_RIGHTBUTTON))
+			Key_Event (K_MOUSE2, false);
+
+		if ((mouse_buttonstate & MOUSE_MIDDLEBUTTON) &&
+			!(mouse_oldbuttonstate & MOUSE_MIDDLEBUTTON))
+			Key_Event (K_MOUSE3, true);
+		else if (!(mouse_buttonstate & MOUSE_MIDDLEBUTTON) &&
+			(mouse_oldbuttonstate & MOUSE_MIDDLEBUTTON))
+			Key_Event (K_MOUSE3, false);
+
+		mouse_oldbuttonstate = mouse_buttonstate;
+	}
+}
+
+/*
+===========
+IN_Move
+===========
+*/
+void IN_MouseMove (usercmd_t *cmd)
+{
+	if (!UseMouse)
+		return;
+
+	// poll mouse values
+	while (mouse_update())
+		;
+
+	if (m_filter.value)
+	{
+		mouse_x = (mx + old_mouse_x) * 0.5;
+		mouse_y = (my + old_mouse_y) * 0.5;
+	}
+	else
+	{
+		mouse_x = mx;
+		mouse_y = my;
+	}
+	old_mouse_x = mx;
+	old_mouse_y = my;
+	mx = my = 0; // clear for next update
+
+	mouse_x *= sensitivity.value;
+	mouse_y *= sensitivity.value;
+
+// add mouse X/Y movement to cmd
+	if ( (in_strafe.state & 1) || (lookstrafe.value && (in_mlook.state & 1) ))
+		cmd->sidemove += m_side.value * mouse_x;
+	else
+		cl.viewangles[YAW] -= m_yaw.value * mouse_x;
+	
+	if (in_mlook.state & 1)
+		V_StopPitchDrift ();
+		
+	if ( (in_mlook.state & 1) && !(in_strafe.state & 1))
+	{
+		cl.viewangles[PITCH] += m_pitch.value * mouse_y;
+		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 * mouse_y;
+		else
+			cmd->forwardmove -= m_forward.value * mouse_y;
+	}
+}
+
+void IN_Move (usercmd_t *cmd)
+{
+	IN_MouseMove(cmd);
+}
+
+
+/*
+================
+VID_ModeInfo
+================
+*/
+char *VID_ModeInfo (int modenum)
+{
+	static char	*badmodestr = "Bad mode number";
+	static char modestr[40];
+
+	if (modenum == 0)
+	{
+		sprintf (modestr, "%d x %d, %d bpp",
+				 vid.width, vid.height, modes[current_mode].bytesperpixel*8);
+		return (modestr);
+	}
+	else
+	{
+		return (badmodestr);
+	}
+}
+
+void VID_LockBuffer (void)
+{
+}
+
+void VID_UnlockBuffer (void)
+{
+}
+
+
--- /dev/null
+++ b/QW/client/vid_win.c
@@ -1,0 +1,3391 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// vid_win.c -- Win32 video driver
+
+#include "quakedef.h"
+#include "winquake.h"
+#include "d_local.h"
+#include "resource.h"
+
+#define	MINIMUM_MEMORY	0x550000
+
+#define MAX_MODE_LIST	30
+#define VID_ROW_SIZE	3
+
+qboolean	dibonly;
+
+extern int		Minimized;
+
+HWND		mainwindow;
+
+HWND WINAPI InitializeWindow (HINSTANCE hInstance, int nCmdShow);
+
+int			DIBWidth, DIBHeight;
+qboolean	DDActive;
+RECT		WindowRect;
+DWORD		WindowStyle, ExWindowStyle;
+
+int			window_center_x, window_center_y, window_x, window_y, window_width, window_height;
+RECT		window_rect;
+
+static DEVMODE	gdevmode;
+static qboolean	startwindowed = 0, windowed_mode_set;
+static int		firstupdate = 1;
+static qboolean	vid_initialized = false, vid_palettized;
+static int		lockcount;
+static int		vid_fulldib_on_focus_mode;
+static qboolean	force_minimized, in_mode_set, is_mode0x13, force_mode_set;
+static int		vid_stretched, windowed_mouse;
+static qboolean	palette_changed, syscolchg, vid_mode_set, hide_window, pal_is_nostatic;
+static HICON	hIcon;
+
+qboolean mouseactive; // from in_win.c
+
+viddef_t	vid;				// global video state
+
+#define MODE_WINDOWED			0
+#define MODE_SETTABLE_WINDOW	2
+#define NO_MODE					(MODE_WINDOWED - 1)
+#define MODE_FULLSCREEN_DEFAULT	(MODE_WINDOWED + 3)
+
+// Note that 0 is MODE_WINDOWED
+cvar_t		vid_mode = {"vid_mode","0", false};
+// Note that 0 is MODE_WINDOWED
+cvar_t		_vid_default_mode = {"_vid_default_mode","0", true};
+// Note that 3 is MODE_FULLSCREEN_DEFAULT
+cvar_t		_vid_default_mode_win = {"_vid_default_mode_win","3", true};
+cvar_t		vid_wait = {"vid_wait","0"};
+cvar_t		vid_nopageflip = {"vid_nopageflip","0", true};
+cvar_t		_vid_wait_override = {"_vid_wait_override", "0", true};
+cvar_t		vid_config_x = {"vid_config_x","800", true};
+cvar_t		vid_config_y = {"vid_config_y","600", true};
+cvar_t		vid_stretch_by_2 = {"vid_stretch_by_2","1", true};
+cvar_t		_windowed_mouse = {"_windowed_mouse","0", true};
+cvar_t		vid_fullscreen_mode = {"vid_fullscreen_mode","3", true};
+cvar_t		vid_windowed_mode = {"vid_windowed_mode","0", true};
+cvar_t		block_switch = {"block_switch","0", true};
+cvar_t		vid_window_x = {"vid_window_x", "0", true};
+cvar_t		vid_window_y = {"vid_window_y", "0", true};
+
+typedef struct {
+	int		width;
+	int		height;
+} lmode_t;
+
+lmode_t	lowresmodes[] = {
+	{320, 200},
+	{320, 240},
+	{400, 300},
+	{512, 384},
+};
+
+int			vid_modenum = NO_MODE;
+int			vid_testingmode, vid_realmode;
+double		vid_testendtime;
+int			vid_default = MODE_WINDOWED;
+static int	windowed_default;
+
+modestate_t	modestate = MS_UNINIT;
+
+static byte		*vid_surfcache;
+static int		vid_surfcachesize;
+static int		VID_highhunkmark;
+
+unsigned char	vid_curpal[256*3];
+
+unsigned short	d_8to16table[256];
+unsigned	d_8to24table[256];
+
+int     driver = grDETECT,mode;
+bool    useWinDirect = true, useDirectDraw = true;
+MGLDC	*mgldc = NULL,*memdc = NULL,*dibdc = NULL,*windc = NULL;
+
+typedef struct {
+	modestate_t	type;
+	int			width;
+	int			height;
+	int			modenum;
+	int			mode13;
+	int			stretched;
+	int			dib;
+	int			fullscreen;
+	int			bpp;
+	int			halfscreen;
+	char		modedesc[13];
+} vmode_t;
+
+static vmode_t	modelist[MAX_MODE_LIST];
+static int		nummodes;
+static vmode_t	*pcurrentmode;
+
+int		aPage;					// Current active display page
+int		vPage;					// Current visible display page
+int		waitVRT = true;			// True to wait for retrace on flip
+
+static vmode_t	badmode;
+
+static byte	backingbuf[48*24];
+
+void VID_MenuDraw (void);
+void VID_MenuKey (int key);
+
+LONG WINAPI MainWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
+void AppActivate(BOOL fActive, BOOL minimize);
+
+
+/*
+================
+VID_RememberWindowPos
+================
+*/
+void VID_RememberWindowPos (void)
+{
+	RECT	rect;
+
+	if (GetWindowRect (mainwindow, &rect))
+	{
+		if ((rect.left < GetSystemMetrics (SM_CXSCREEN)) &&
+			(rect.top < GetSystemMetrics (SM_CYSCREEN))  &&
+			(rect.right > 0)                             &&
+			(rect.bottom > 0))
+		{
+			Cvar_SetValue ("vid_window_x", (float)rect.left);
+			Cvar_SetValue ("vid_window_y", (float)rect.top);
+		}
+	}
+}
+
+
+/*
+================
+VID_CheckWindowXY
+================
+*/
+void VID_CheckWindowXY (void)
+{
+
+	if (((int)vid_window_x.value > (GetSystemMetrics (SM_CXSCREEN) - 160)) ||
+		((int)vid_window_y.value > (GetSystemMetrics (SM_CYSCREEN) - 120)) ||
+		((int)vid_window_x.value < 0)									   ||
+		((int)vid_window_y.value < 0))
+	{
+		Cvar_SetValue ("vid_window_x", 0.0);
+		Cvar_SetValue ("vid_window_y", 0.0 );
+	}
+}
+
+
+/*
+================
+VID_UpdateWindowStatus
+================
+*/
+void VID_UpdateWindowStatus (void)
+{
+
+	window_rect.left = window_x;
+	window_rect.top = window_y;
+	window_rect.right = window_x + window_width;
+	window_rect.bottom = window_y + window_height;
+	window_center_x = (window_rect.left + window_rect.right) / 2;
+	window_center_y = (window_rect.top + window_rect.bottom) / 2;
+
+	IN_UpdateClipCursor ();
+}
+
+
+/*
+================
+ClearAllStates
+================
+*/
+void ClearAllStates (void)
+{
+	int		i;
+	
+// send an up event for each key, to make sure the server clears them all
+	for (i=0 ; i<256 ; i++)
+	{
+		Key_Event (i, false);
+	}
+
+	Key_ClearStates ();
+	IN_ClearStates ();
+}
+
+
+/*
+================
+VID_CheckAdequateMem
+================
+*/
+qboolean VID_CheckAdequateMem (int width, int height)
+{
+	int		tbuffersize;
+
+	tbuffersize = width * height * sizeof (*d_pzbuffer);
+
+	tbuffersize += D_SurfaceCacheForRes (width, height);
+
+// see if there's enough memory, allowing for the normal mode 0x13 pixel,
+// z, and surface buffers
+	if ((host_parms.memsize - tbuffersize + SURFCACHE_SIZE_AT_320X200 +
+		 0x10000 * 3) < MINIMUM_MEMORY)
+	{
+		return false;		// not enough memory for mode
+	}
+
+	return true;
+}
+
+
+/*
+================
+VID_AllocBuffers
+================
+*/
+qboolean VID_AllocBuffers (int width, int height)
+{
+	int		tsize, tbuffersize;
+
+	tbuffersize = width * height * sizeof (*d_pzbuffer);
+
+	tsize = D_SurfaceCacheForRes (width, height);
+
+	tbuffersize += tsize;
+
+// see if there's enough memory, allowing for the normal mode 0x13 pixel,
+// z, and surface buffers
+	if ((host_parms.memsize - tbuffersize + SURFCACHE_SIZE_AT_320X200 +
+		 0x10000 * 3) < MINIMUM_MEMORY)
+	{
+		Con_SafePrintf ("Not enough memory for video mode\n");
+		return false;		// not enough memory for mode
+	}
+
+	vid_surfcachesize = tsize;
+
+	if (d_pzbuffer)
+	{
+		D_FlushCaches ();
+		Hunk_FreeToHighMark (VID_highhunkmark);
+		d_pzbuffer = NULL;
+	}
+
+	VID_highhunkmark = Hunk_HighMark ();
+
+	d_pzbuffer = Hunk_HighAllocName (tbuffersize, "video");
+
+	vid_surfcache = (byte *)d_pzbuffer +
+			width * height * sizeof (*d_pzbuffer);
+	
+	return true;
+}
+
+
+void initFatalError(void)
+{
+	MGL_exit();
+	MGL_fatalError(MGL_errorMsg(MGL_result()));
+	exit(EXIT_FAILURE);
+}
+
+#if 0 //def NEW_SUSPEND
+
+int VID_Suspend (MGLDC *dc, int flags)
+{
+	int i;
+	if (flags & MGL_DEACTIVATE)
+	{
+		IN_RestoreOriginalMouseState ();
+		CDAudio_Pause ();
+
+		// keep WM_PAINT from trying to redraw
+		in_mode_set = true;
+		block_drawing = true;
+	}
+	else if (flags & MGL_REACTIVATE)
+	{
+		IN_SetQuakeMouseState ();
+		// fix the leftover Alt from any Alt-Tab or the like that switched us away
+		ClearAllStates ();
+		CDAudio_Resume ();
+		in_mode_set = false;
+
+		block_drawing = false;
+//		vid.recalc_refdef = 1;
+		force_mode_set = 1;
+		i = msg_suppress_1;
+		msg_suppress_1 = 1;
+		VID_Fullscreen_f();
+		msg_suppress_1 = i;
+		force_mode_set = 0;
+	}
+
+	return 1;
+}
+
+#else
+
+int VID_Suspend (MGLDC *dc, int flags)
+{
+
+	if (flags & MGL_DEACTIVATE)
+	{
+	// FIXME: this doesn't currently work on NT
+		if (block_switch.value && !WinNT)
+		{
+			return MGL_NO_DEACTIVATE;
+		}
+
+		S_BlockSound ();
+		S_ClearBuffer ();
+
+		IN_RestoreOriginalMouseState ();
+		CDAudio_Pause ();
+
+	// keep WM_PAINT from trying to redraw
+		in_mode_set = true;
+
+		block_drawing = true;	// so we don't try to draw while switched away
+
+		return MGL_NO_SUSPEND_APP;
+	}
+	else if (flags & MGL_REACTIVATE)
+	{
+		IN_SetQuakeMouseState ();
+	// fix the leftover Alt from any Alt-Tab or the like that switched us away
+		ClearAllStates ();
+		CDAudio_Resume ();
+		S_UnblockSound ();
+
+		in_mode_set = false;
+
+		vid.recalc_refdef = 1;
+
+		block_drawing = false;
+
+		return MGL_NO_SUSPEND_APP;
+	}
+
+}
+#endif
+
+
+void registerAllDispDrivers(void)
+{
+	/* Event though these driver require WinDirect, we register
+	 * them so that they will still be available even if DirectDraw
+	 * is present and the user has disable the high performance
+	 * WinDirect modes.
+	 */
+	MGL_registerDriver(MGL_VGA8NAME,VGA8_driver);
+//	MGL_registerDriver(MGL_VGAXNAME,VGAX_driver);
+
+	/* Register display drivers */
+	if (useWinDirect)
+	{
+//we don't want VESA 1.X drivers		MGL_registerDriver(MGL_SVGA8NAME,SVGA8_driver);
+		MGL_registerDriver(MGL_LINEAR8NAME,LINEAR8_driver);
+
+		if (!COM_CheckParm ("-novbeaf"))
+			MGL_registerDriver(MGL_ACCEL8NAME,ACCEL8_driver);
+	}
+
+	if (useDirectDraw)
+	{
+		MGL_registerDriver(MGL_DDRAW8NAME,DDRAW8_driver);
+	}
+}
+
+
+void registerAllMemDrivers(void)
+{
+	/* Register memory context drivers */
+	MGL_registerDriver(MGL_PACKED8NAME,PACKED8_driver);
+}
+
+
+void VID_InitMGLFull (HINSTANCE hInstance)
+{
+	int			i, xRes, yRes, bits, vMode, lowres, curmode, temp;
+	int			lowstretchedres, stretchedmode, lowstretched;
+    uchar		*m;
+
+// FIXME: NT is checked for because MGL currently has a bug that causes it
+// to try to use WinDirect modes even on NT
+	if (COM_CheckParm("-nowindirect") ||
+		COM_CheckParm("-nowd") ||
+		COM_CheckParm("-novesa") ||
+		WinNT)
+	{
+		useWinDirect = false;
+	}
+
+	if (COM_CheckParm("-nodirectdraw") || COM_CheckParm("-noddraw") || COM_CheckParm("-nodd"))
+		useDirectDraw = false;
+
+	// Initialise the MGL
+	MGL_unregisterAllDrivers();
+	registerAllDispDrivers();
+	registerAllMemDrivers();
+	MGL_detectGraph(&driver,&mode);
+	m = MGL_availableModes();
+
+	if (m[0] != 0xFF)
+	{
+		lowres = lowstretchedres = 99999;
+		lowstretched = 0;
+		curmode = 0;
+
+	// find the lowest-res mode, or a mode we can stretch up to and get
+	// lowest-res that way
+		for (i = 0; m[i] != 0xFF; i++)
+		{
+			MGL_modeResolution(m[i], &xRes, &yRes,&bits);
+
+			if ((bits == 8) &&
+				(xRes <= MAXWIDTH) &&
+				(yRes <= MAXHEIGHT) &&
+				(curmode < MAX_MODE_LIST))
+			{
+				if (m[i] == grVGA_320x200x256)
+					is_mode0x13 = true;
+
+				if (!COM_CheckParm("-noforcevga"))
+				{
+					if (m[i] == grVGA_320x200x256)
+					{
+						mode = i;
+						break;
+					}
+				}
+
+				if (xRes < lowres)
+				{
+					lowres = xRes;
+					mode = i;
+				}
+
+				if ((xRes < lowstretchedres) && ((xRes >> 1) >= 320))
+				{
+					lowstretchedres = xRes >> 1;
+					stretchedmode = i;
+				}
+			}
+
+			curmode++;
+		}
+
+	// if there's a mode we can stretch by 2 up to, thereby effectively getting
+	// a lower-res mode than the lowest-res real but still at least 320x200, that
+	// will be our default mode
+		if (lowstretchedres < lowres)
+		{
+			mode = stretchedmode;
+			lowres = lowstretchedres;
+			lowstretched = 1;
+		}
+
+	// build the mode list, leaving room for the low-res stretched mode, if any
+		nummodes++;		// leave room for default mode
+
+		for (i = 0; m[i] != 0xFF; i++)
+		{
+			MGL_modeResolution(m[i], &xRes, &yRes,&bits);
+
+			if ((bits == 8) &&
+				(xRes <= MAXWIDTH) &&
+				(yRes <= MAXHEIGHT) &&
+				(nummodes < MAX_MODE_LIST))
+			{
+				if (i == mode)
+				{
+					if (lowstretched)
+					{
+						stretchedmode = nummodes;
+						curmode = nummodes++;
+					}
+					else
+					{
+						curmode = MODE_FULLSCREEN_DEFAULT;
+					}
+				}
+				else
+				{
+					curmode = nummodes++;
+				}
+
+				modelist[curmode].type = MS_FULLSCREEN;
+				modelist[curmode].width = xRes;
+				modelist[curmode].height = yRes;
+				sprintf (modelist[curmode].modedesc, "%dx%d", xRes, yRes);
+
+				if (m[i] == grVGA_320x200x256)
+					modelist[curmode].mode13 = 1;
+				else
+					modelist[curmode].mode13 = 0;
+
+				modelist[curmode].modenum = m[i];
+				modelist[curmode].stretched = 0;
+				modelist[curmode].dib = 0;
+				modelist[curmode].fullscreen = 1;
+				modelist[curmode].halfscreen = 0;
+				modelist[curmode].bpp = 8;
+			}
+		}
+
+		if (lowstretched)
+		{
+			modelist[MODE_FULLSCREEN_DEFAULT] = modelist[stretchedmode];
+			modelist[MODE_FULLSCREEN_DEFAULT].stretched = 1;
+			modelist[MODE_FULLSCREEN_DEFAULT].width >>= 1;
+			modelist[MODE_FULLSCREEN_DEFAULT].height >>= 1;
+			sprintf (modelist[MODE_FULLSCREEN_DEFAULT].modedesc, "%dx%d",
+					 modelist[MODE_FULLSCREEN_DEFAULT].width,
+					 modelist[MODE_FULLSCREEN_DEFAULT].height);
+		}
+
+		vid_default = MODE_FULLSCREEN_DEFAULT;
+
+		temp = m[0];
+
+		if (!MGL_init(&driver, &temp, ""))
+		{
+			initFatalError();
+		}
+	}
+
+	MGL_setSuspendAppCallback(VID_Suspend);
+}
+
+
+MGLDC *createDisplayDC(int forcemem)
+/****************************************************************************
+*
+* Function:     createDisplayDC
+* Returns:      Pointer to the MGL device context to use for the application
+*
+* Description:  Initialises the MGL and creates an appropriate display
+*               device context to be used by the GUI. This creates and
+*               apropriate device context depending on the system being
+*               compile for, and should be the only place where system
+*               specific code is required.
+*
+****************************************************************************/
+{
+    MGLDC			*dc;
+	pixel_format_t	pf;
+	int				npages;
+
+	// Start the specified video mode
+	if (!MGL_changeDisplayMode(mode))
+		initFatalError();
+
+	npages = MGL_availablePages(mode);
+
+	if (npages > 3)
+		npages = 3;
+
+	if (!COM_CheckParm ("-notriplebuf"))
+	{
+		if (npages > 2)
+		{
+			npages = 2;
+		}
+	}
+
+	if ((dc = MGL_createDisplayDC(npages)) == NULL)
+		return NULL;
+
+	if (!forcemem && (MGL_surfaceAccessType(dc)) == MGL_LINEAR_ACCESS && (dc->mi.maxPage > 0))
+	{
+		MGL_makeCurrentDC(dc);
+		memdc = NULL;
+	}
+	else
+	{
+		// Set up for blitting from a memory buffer
+		memdc = MGL_createMemoryDC(MGL_sizex(dc)+1,MGL_sizey(dc)+1,8,&pf);
+		MGL_makeCurrentDC(memdc);
+	}
+
+	// Enable page flipping even for even for blitted surfaces
+	if (forcemem)
+	{
+		vid.numpages = 1;
+	}
+	else
+	{
+		vid.numpages = dc->mi.maxPage + 1;
+
+		if (vid.numpages > 1)
+		{
+			// Set up for page flipping
+			MGL_setActivePage(dc, aPage = 1);
+			MGL_setVisualPage(dc, vPage = 0, false);
+		}
+
+		if (vid.numpages > 3)
+			vid.numpages = 3;
+	}
+
+	if (vid.numpages == 2)
+		waitVRT = true;
+	else
+		waitVRT = false;
+
+	return dc;
+}
+
+
+void VID_InitMGLDIB (HINSTANCE hInstance)
+{
+	WNDCLASS		wc;
+	HDC				hdc;
+	int				i;
+
+	hIcon = LoadIcon (hInstance, MAKEINTRESOURCE (IDI_ICON2));
+
+	/* Register the frame class */
+    wc.style         = 0;
+    wc.lpfnWndProc   = (WNDPROC)MainWndProc;
+    wc.cbClsExtra    = 0;
+    wc.cbWndExtra    = 0;
+    wc.hInstance     = hInstance;
+    wc.hIcon         = 0;
+    wc.hCursor       = LoadCursor (NULL,IDC_ARROW);
+	wc.hbrBackground = NULL;
+    wc.lpszMenuName  = 0;
+    wc.lpszClassName = "WinQuake";
+
+    if (!RegisterClass (&wc) )
+		Sys_Error ("Couldn't register window class");
+
+	/* Find the size for the DIB window */
+	/* Initialise the MGL for windowed operation */
+	MGL_setAppInstance(hInstance);
+	registerAllMemDrivers();
+	MGL_initWindowed("");
+
+	modelist[0].type = MS_WINDOWED;
+	modelist[0].width = 320;
+	modelist[0].height = 240;
+	strcpy (modelist[0].modedesc, "320x240");
+	modelist[0].mode13 = 0;
+	modelist[0].modenum = MODE_WINDOWED;
+	modelist[0].stretched = 0;
+	modelist[0].dib = 1;
+	modelist[0].fullscreen = 0;
+	modelist[0].halfscreen = 0;
+	modelist[0].bpp = 8;
+
+	modelist[1].type = MS_WINDOWED;
+	modelist[1].width = 640;
+	modelist[1].height = 480;
+	strcpy (modelist[1].modedesc, "640x480");
+	modelist[1].mode13 = 0;
+	modelist[1].modenum = MODE_WINDOWED + 1;
+	modelist[1].stretched = 1;
+	modelist[1].dib = 1;
+	modelist[1].fullscreen = 0;
+	modelist[1].halfscreen = 0;
+	modelist[1].bpp = 8;
+
+	modelist[2].type = MS_WINDOWED;
+	modelist[2].width = 800;
+	modelist[2].height = 600;
+	strcpy (modelist[2].modedesc, "800x600");
+	modelist[2].mode13 = 0;
+	modelist[2].modenum = MODE_WINDOWED + 2;
+	modelist[2].stretched = 1;
+	modelist[2].dib = 1;
+	modelist[2].fullscreen = 0;
+	modelist[2].halfscreen = 0;
+	modelist[2].bpp = 8;
+
+// automatically stretch the default mode up if > 640x480 desktop resolution
+	hdc = GetDC(NULL);
+
+	if ((GetDeviceCaps(hdc, HORZRES) > 640) && !COM_CheckParm("-noautostretch"))
+	{
+		vid_default = MODE_WINDOWED + 1;
+	}
+	else
+	{
+		vid_default = MODE_WINDOWED;
+	}
+
+	windowed_default = vid_default;
+
+	ReleaseDC(NULL,hdc);
+
+	nummodes = 3;	// reserve space for windowed mode
+
+	DDActive = 0;
+}
+
+
+/*
+=================
+VID_InitFullDIB
+=================
+*/
+void VID_InitFullDIB (HINSTANCE hInstance)
+{
+	DEVMODE	devmode;
+	int		i, j, modenum, cmodes, existingmode, originalnummodes, lowestres;
+	int		numlowresmodes, bpp, done;
+	int		cstretch, istretch, mstretch;
+	BOOL	stat;
+
+// enumerate 8 bpp modes
+	originalnummodes = nummodes;
+	modenum = 0;
+	lowestres = 99999;
+
+	do
+	{
+		stat = EnumDisplaySettings (NULL, modenum, &devmode);
+
+		if ((devmode.dmBitsPerPel == 8) &&
+			(devmode.dmPelsWidth <= MAXWIDTH) &&
+			(devmode.dmPelsHeight <= MAXHEIGHT) &&
+			(nummodes < MAX_MODE_LIST))
+		{
+			devmode.dmFields = DM_BITSPERPEL |
+							   DM_PELSWIDTH |
+							   DM_PELSHEIGHT;
+
+			if (ChangeDisplaySettings (&devmode, CDS_TEST | CDS_FULLSCREEN) ==
+					DISP_CHANGE_SUCCESSFUL)
+			{
+				modelist[nummodes].type = MS_FULLDIB;
+				modelist[nummodes].width = devmode.dmPelsWidth;
+				modelist[nummodes].height = devmode.dmPelsHeight;
+				modelist[nummodes].modenum = 0;
+				modelist[nummodes].mode13 = 0;
+				modelist[nummodes].stretched = 0;
+				modelist[nummodes].halfscreen = 0;
+				modelist[nummodes].dib = 1;
+				modelist[nummodes].fullscreen = 1;
+				modelist[nummodes].bpp = devmode.dmBitsPerPel;
+				sprintf (modelist[nummodes].modedesc, "%dx%d",
+						 devmode.dmPelsWidth, devmode.dmPelsHeight);
+
+			// if the width is more than twice the height, reduce it by half because this
+			// is probably a dual-screen monitor
+				if (!COM_CheckParm("-noadjustaspect"))
+				{
+					if (modelist[nummodes].width > (modelist[nummodes].height << 1))
+					{
+						modelist[nummodes].width >>= 1;
+						modelist[nummodes].halfscreen = 1;
+						sprintf (modelist[nummodes].modedesc, "%dx%d",
+								 modelist[nummodes].width,
+								 modelist[nummodes].height);
+					}
+				}
+
+				for (i=originalnummodes, existingmode = 0 ; i<nummodes ; i++)
+				{
+					if ((modelist[nummodes].width == modelist[i].width) &&
+						(modelist[nummodes].height == modelist[i].height))
+					{
+						existingmode = 1;
+						break;
+					}
+				}
+
+				if (!existingmode)
+				{
+					if (modelist[nummodes].width < lowestres)
+						lowestres = modelist[nummodes].width;
+
+					nummodes++;
+				}
+			}
+		}
+
+		modenum++;
+	} while (stat);
+
+// see if any of them were actually settable; if so, this is our mode list,
+// else enumerate all modes; our mode list is whichever ones are settable
+// with > 8 bpp
+	if (nummodes == originalnummodes)
+	{
+		modenum = 0;
+		lowestres = 99999;
+
+		Con_SafePrintf ("No 8-bpp fullscreen DIB modes found\n");
+
+		do
+		{
+			stat = EnumDisplaySettings (NULL, modenum, &devmode);
+
+			if ((((devmode.dmPelsWidth <= MAXWIDTH) &&
+				  (devmode.dmPelsHeight <= MAXHEIGHT)) ||
+				 (!COM_CheckParm("-noadjustaspect") &&
+				  (devmode.dmPelsWidth <= (MAXWIDTH*2)) &&
+				  (devmode.dmPelsWidth > (devmode.dmPelsHeight*2)))) &&
+				(nummodes < MAX_MODE_LIST) &&
+				(devmode.dmBitsPerPel > 8))
+			{
+				devmode.dmFields = DM_BITSPERPEL |
+								   DM_PELSWIDTH |
+								   DM_PELSHEIGHT;
+
+				if (ChangeDisplaySettings (&devmode, CDS_TEST | CDS_FULLSCREEN) ==
+						DISP_CHANGE_SUCCESSFUL)
+				{
+					modelist[nummodes].type = MS_FULLDIB;
+					modelist[nummodes].width = devmode.dmPelsWidth;
+					modelist[nummodes].height = devmode.dmPelsHeight;
+					modelist[nummodes].modenum = 0;
+					modelist[nummodes].mode13 = 0;
+					modelist[nummodes].stretched = 0;
+					modelist[nummodes].halfscreen = 0;
+					modelist[nummodes].dib = 1;
+					modelist[nummodes].fullscreen = 1;
+					modelist[nummodes].bpp = devmode.dmBitsPerPel;
+					sprintf (modelist[nummodes].modedesc, "%dx%d",
+							 devmode.dmPelsWidth, devmode.dmPelsHeight);
+
+				// if the width is more than twice the height, reduce it by half because this
+				// is probably a dual-screen monitor
+					if (!COM_CheckParm("-noadjustaspect"))
+					{
+						if (modelist[nummodes].width > (modelist[nummodes].height*2))
+						{
+							modelist[nummodes].width >>= 1;
+							modelist[nummodes].halfscreen = 1;
+							sprintf (modelist[nummodes].modedesc, "%dx%d",
+									 modelist[nummodes].width,
+									 modelist[nummodes].height);
+						}
+					}
+
+					for (i=originalnummodes, existingmode = 0 ; i<nummodes ; i++)
+					{
+						if ((modelist[nummodes].width == modelist[i].width) &&
+							(modelist[nummodes].height == modelist[i].height))
+						{
+						// pick the lowest available bpp
+							if (modelist[nummodes].bpp < modelist[i].bpp)
+								modelist[i] = modelist[nummodes];
+
+							existingmode = 1;
+							break;
+						}
+					}
+
+					if (!existingmode)
+					{
+						if (modelist[nummodes].width < lowestres)
+							lowestres = modelist[nummodes].width;
+
+						nummodes++;
+					}
+				}
+			}
+
+			modenum++;
+		} while (stat);
+	}
+
+// see if there are any low-res modes that aren't being reported
+	numlowresmodes = sizeof(lowresmodes) / sizeof(lowresmodes[0]);
+	bpp = 8;
+	done = 0;
+
+// first make sure the driver doesn't just answer yes to all tests
+	devmode.dmBitsPerPel = 8;
+	devmode.dmPelsWidth = 42;
+	devmode.dmPelsHeight = 37;
+	devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
+
+	if (ChangeDisplaySettings (&devmode, CDS_TEST | CDS_FULLSCREEN) ==
+			DISP_CHANGE_SUCCESSFUL)
+	{
+		done = 1;
+	}
+
+	while (!done)
+	{
+		for (j=0 ; (j<numlowresmodes) && (nummodes < MAX_MODE_LIST) ; j++)
+		{
+			devmode.dmBitsPerPel = bpp;
+			devmode.dmPelsWidth = lowresmodes[j].width;
+			devmode.dmPelsHeight = lowresmodes[j].height;
+			devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
+
+			if (ChangeDisplaySettings (&devmode, CDS_TEST | CDS_FULLSCREEN) ==
+					DISP_CHANGE_SUCCESSFUL)
+			{
+					modelist[nummodes].type = MS_FULLDIB;
+					modelist[nummodes].width = devmode.dmPelsWidth;
+					modelist[nummodes].height = devmode.dmPelsHeight;
+					modelist[nummodes].modenum = 0;
+					modelist[nummodes].mode13 = 0;
+					modelist[nummodes].stretched = 0;
+					modelist[nummodes].halfscreen = 0;
+					modelist[nummodes].dib = 1;
+					modelist[nummodes].fullscreen = 1;
+					modelist[nummodes].bpp = devmode.dmBitsPerPel;
+					sprintf (modelist[nummodes].modedesc, "%dx%d",
+							 devmode.dmPelsWidth, devmode.dmPelsHeight);
+
+			// we only want the lowest-bpp version of each mode
+				for (i=originalnummodes, existingmode = 0 ; i<nummodes ; i++)
+				{
+					if ((modelist[nummodes].width == modelist[i].width)   &&
+						(modelist[nummodes].height == modelist[i].height) &&
+						(modelist[nummodes].bpp >= modelist[i].bpp))
+					{
+						existingmode = 1;
+						break;
+					}
+				}
+
+				if (!existingmode)
+				{
+					if (modelist[nummodes].width < lowestres)
+						lowestres = modelist[nummodes].width;
+
+					nummodes++;
+				}
+			}
+		}
+
+		switch (bpp)
+		{
+			case 8:
+				bpp = 16;
+				break;
+
+			case 16:
+				bpp = 32;
+				break;
+
+			case 32:
+				done = 1;
+				break;
+		}
+	}
+
+// now add the lowest stretch-by-2 pseudo-modes between 320-wide
+// (inclusive) and lowest real res (not inclusive)
+// don't bother if we have a real VGA mode 0x13 mode
+	if (!is_mode0x13)
+	{
+		for (i=originalnummodes, cstretch=0 ; i<nummodes ; i++)
+		{
+			if (((modelist[i].width >> 1) < lowestres) &&
+				((modelist[i].width >> 1) >= 320))
+			{
+				lowestres = modelist[i].width >> 1;
+				cstretch = 1;
+				mstretch = i;
+			}
+		}
+
+		if ((nummodes + cstretch) > MAX_MODE_LIST)
+			cstretch = MAX_MODE_LIST - nummodes;
+
+		if (cstretch > 0)
+		{
+			for (i=(nummodes-1) ; i>=originalnummodes ; i--)
+				modelist[i+cstretch] = modelist[i];
+
+			nummodes += cstretch;
+			istretch = originalnummodes;
+
+			modelist[istretch] = modelist[mstretch];
+			modelist[istretch].width >>= 1;
+			modelist[istretch].height >>= 1;
+			modelist[istretch].stretched = 1;
+			sprintf (modelist[istretch].modedesc, "%dx%d",
+					 modelist[istretch].width, modelist[istretch].height);
+		}
+	}
+
+	if (nummodes != originalnummodes)
+		vid_default = MODE_FULLSCREEN_DEFAULT;
+	else
+		Con_SafePrintf ("No fullscreen DIB modes found\n");
+}
+
+
+/*
+=================
+VID_NumModes
+=================
+*/
+int VID_NumModes (void)
+{
+	return nummodes;
+}
+
+	
+/*
+=================
+VID_GetModePtr
+=================
+*/
+vmode_t *VID_GetModePtr (int modenum)
+{
+
+	if ((modenum >= 0) && (modenum < nummodes))
+		return &modelist[modenum];
+	else
+		return &badmode;
+}
+
+
+/*
+=================
+VID_CheckModedescFixup
+=================
+*/
+void VID_CheckModedescFixup (int mode)
+{
+	int		x, y, stretch;
+
+	if (mode == MODE_SETTABLE_WINDOW)
+	{
+		modelist[mode].stretched = (int)vid_stretch_by_2.value;
+		stretch = modelist[mode].stretched;
+
+		if (vid_config_x.value < (320 << stretch))
+			vid_config_x.value = 320 << stretch;
+
+		if (vid_config_y.value < (200 << stretch))
+			vid_config_y.value = 200 << stretch;
+
+		x = (int)vid_config_x.value;
+		y = (int)vid_config_y.value;
+		sprintf (modelist[mode].modedesc, "%dx%d", x, y);
+		modelist[mode].width = x;
+		modelist[mode].height = y;
+	}
+}
+
+
+/*
+=================
+VID_GetModeDescriptionMemCheck
+=================
+*/
+char *VID_GetModeDescriptionMemCheck (int mode)
+{
+	char		*pinfo;
+	vmode_t		*pv;
+
+	if ((mode < 0) || (mode >= nummodes))
+		return NULL;
+
+	VID_CheckModedescFixup (mode);
+
+	pv = VID_GetModePtr (mode);
+	pinfo = pv->modedesc;
+
+	if (VID_CheckAdequateMem (pv->width, pv->height))
+	{
+		return pinfo;
+	}
+	else
+	{
+		return NULL;
+	}
+}
+
+
+/*
+=================
+VID_GetModeDescription
+=================
+*/
+char *VID_GetModeDescription (int mode)
+{
+	char		*pinfo;
+	vmode_t		*pv;
+
+	if ((mode < 0) || (mode >= nummodes))
+		return NULL;
+
+	VID_CheckModedescFixup (mode);
+
+	pv = VID_GetModePtr (mode);
+	pinfo = pv->modedesc;
+	return pinfo;
+}
+
+
+/*
+=================
+VID_GetModeDescription2
+
+Tacks on "windowed" or "fullscreen"
+=================
+*/
+char *VID_GetModeDescription2 (int mode)
+{
+	static char	pinfo[40];
+	vmode_t		*pv;
+
+	if ((mode < 0) || (mode >= nummodes))
+		return NULL;
+
+	VID_CheckModedescFixup (mode);
+
+	pv = VID_GetModePtr (mode);
+
+	if (modelist[mode].type == MS_FULLSCREEN)
+	{
+		sprintf(pinfo,"%s fullscreen", pv->modedesc);
+	}
+	else if (modelist[mode].type == MS_FULLDIB)
+	{
+		sprintf(pinfo,"%s fullscreen", pv->modedesc);
+	}
+	else
+	{
+		sprintf(pinfo, "%s windowed", pv->modedesc);
+	}
+
+	return pinfo;
+}
+
+
+// KJB: Added this to return the mode driver name in description for console
+
+char *VID_GetExtModeDescription (int mode)
+{
+	static char	pinfo[40];
+	vmode_t		*pv;
+
+	if ((mode < 0) || (mode >= nummodes))
+		return NULL;
+
+	VID_CheckModedescFixup (mode);
+
+	pv = VID_GetModePtr (mode);
+	if (modelist[mode].type == MS_FULLSCREEN)
+	{
+		sprintf(pinfo,"%s fullscreen %s",pv->modedesc,
+				MGL_modeDriverName(pv->modenum));
+	}
+	else if (modelist[mode].type == MS_FULLDIB)
+	{
+		sprintf(pinfo,"%s fullscreen DIB", pv->modedesc);
+	}
+	else
+	{
+		sprintf(pinfo, "%s windowed", pv->modedesc);
+	}
+
+	return pinfo;
+}
+
+
+void DestroyDIBWindow (void)
+{
+
+	if (modestate == MS_WINDOWED)
+	{
+	// destroy the associated MGL DC's; the window gets reused
+		if (windc)
+			MGL_destroyDC(windc);
+		if (dibdc)
+			MGL_destroyDC(dibdc);
+		windc = dibdc = NULL;
+	}
+}
+
+
+void DestroyFullscreenWindow (void)
+{
+
+	if (modestate == MS_FULLSCREEN)
+	{
+	// destroy the existing fullscreen mode and DC's
+		if (mgldc)
+			MGL_destroyDC (mgldc);
+		if (memdc)
+			MGL_destroyDC (memdc);
+		mgldc = memdc = NULL;
+	}
+}
+
+
+
+void DestroyFullDIBWindow (void)
+{
+	if (modestate == MS_FULLDIB)
+	{
+		ChangeDisplaySettings (NULL, CDS_FULLSCREEN);
+
+	// Destroy the fullscreen DIB window and associated MGL DC's
+		if (windc)
+			MGL_destroyDC(windc);
+		if (dibdc)
+			MGL_destroyDC(dibdc);
+		windc = dibdc = NULL;
+	}
+}
+
+
+qboolean VID_SetWindowedMode (int modenum)
+{
+	HDC				hdc;
+	pixel_format_t	pf;
+	qboolean		stretched;
+	int				lastmodestate;
+	LONG			wlong;
+
+	if (!windowed_mode_set)
+	{
+		if (COM_CheckParm ("-resetwinpos"))
+		{
+			Cvar_SetValue ("vid_window_x", 0.0);
+			Cvar_SetValue ("vid_window_y", 0.0);
+		}
+
+		windowed_mode_set;
+	}
+
+	VID_CheckModedescFixup (modenum);
+
+	DDActive = 0;
+	lastmodestate = modestate;
+
+	DestroyFullscreenWindow ();
+	DestroyFullDIBWindow ();
+
+	if (windc)
+		MGL_destroyDC(windc);
+	if (dibdc)
+		MGL_destroyDC(dibdc);
+	windc = dibdc = NULL;
+
+// KJB: Signal to the MGL that we are going back to windowed mode
+	if (!MGL_changeDisplayMode(grWINDOWED))
+		initFatalError();
+
+	WindowRect.top = WindowRect.left = 0;
+
+	WindowRect.right = modelist[modenum].width;
+	WindowRect.bottom = modelist[modenum].height;
+	stretched = modelist[modenum].stretched;
+
+	DIBWidth = modelist[modenum].width;
+	DIBHeight = modelist[modenum].height;
+
+	if (stretched)
+	{
+		DIBWidth >>= 1;
+		DIBHeight >>= 1;
+	}
+
+	WindowStyle = WS_OVERLAPPED | WS_BORDER | WS_CAPTION | WS_SYSMENU |
+				  WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_CLIPSIBLINGS |
+				  WS_CLIPCHILDREN;
+	ExWindowStyle = 0;
+	AdjustWindowRectEx(&WindowRect, WindowStyle, FALSE, 0);
+
+// the first time we're called to set the mode, create the window we'll use
+// for the rest of the session
+	if (!vid_mode_set)
+	{
+		mainwindow = CreateWindowEx (
+			 ExWindowStyle,
+			 "WinQuake",
+			 "WinQuake",
+			 WindowStyle,
+			 0, 0,
+			 WindowRect.right - WindowRect.left,
+			 WindowRect.bottom - WindowRect.top,
+			 NULL,
+			 NULL,
+			 global_hInstance,
+			 NULL);
+
+		if (!mainwindow)
+			Sys_Error ("Couldn't create DIB window");
+
+	// tell MGL to use this window for fullscreen modes
+		MGL_registerFullScreenWindow (mainwindow);
+
+		vid_mode_set = true;
+	}
+	else
+	{
+		SetWindowLong(mainwindow, GWL_STYLE, WindowStyle | WS_VISIBLE);
+		SetWindowLong(mainwindow, GWL_EXSTYLE, ExWindowStyle);
+	}
+
+	if (!SetWindowPos (mainwindow,
+						   NULL,
+						   0, 0,
+						   WindowRect.right - WindowRect.left,
+						   WindowRect.bottom - WindowRect.top,
+						   SWP_NOCOPYBITS | SWP_NOZORDER |
+						    SWP_HIDEWINDOW))
+		{
+			Sys_Error ("Couldn't resize DIB window");
+		}
+
+	if (hide_window)
+		return true;
+
+// position and show the DIB window
+	VID_CheckWindowXY ();
+	SetWindowPos (mainwindow, NULL, (int)vid_window_x.value,
+				  (int)vid_window_y.value, 0, 0,
+				  SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW | SWP_DRAWFRAME);
+
+	if (force_minimized)
+		ShowWindow (mainwindow, SW_MINIMIZE);
+	else
+		ShowWindow (mainwindow, SW_SHOWDEFAULT);
+
+	UpdateWindow (mainwindow);
+
+	modestate = MS_WINDOWED;
+	vid_fulldib_on_focus_mode = 0;
+
+// because we have set the background brush for the window to NULL
+// (to avoid flickering when re-sizing the window on the desktop),
+// we clear the window to black when created, otherwise it will be
+// empty while Quake starts up.
+	hdc = GetDC(mainwindow);
+	PatBlt(hdc,0,0,WindowRect.right,WindowRect.bottom,BLACKNESS);
+	ReleaseDC(mainwindow, hdc);
+
+	/* Create the MGL window DC and the MGL memory DC */
+	if ((windc = MGL_createWindowedDC(mainwindow)) == NULL)
+		MGL_fatalError("Unable to create Windowed DC!");
+
+	if ((dibdc = MGL_createMemoryDC(DIBWidth,DIBHeight,8,&pf)) == NULL)
+		MGL_fatalError("Unable to create Memory DC!");
+
+	MGL_makeCurrentDC(dibdc);
+
+	vid.buffer = vid.conbuffer = vid.direct = dibdc->surface;
+	vid.rowbytes = vid.conrowbytes = dibdc->mi.bytesPerLine;
+	vid.numpages = 1;
+	vid.maxwarpwidth = WARP_WIDTH;
+	vid.maxwarpheight = WARP_HEIGHT;
+	vid.height = vid.conheight = DIBHeight;
+	vid.width = vid.conwidth = DIBWidth;
+	vid.aspect = ((float)vid.height / (float)vid.width) *
+				(320.0 / 240.0);
+
+	vid_stretched = stretched;
+
+	SendMessage (mainwindow, WM_SETICON, (WPARAM)TRUE, (LPARAM)hIcon);
+	SendMessage (mainwindow, WM_SETICON, (WPARAM)FALSE, (LPARAM)hIcon);
+
+	return true;
+}
+
+
+qboolean VID_SetFullscreenMode (int modenum)
+{
+
+	DDActive = 1;
+
+	DestroyDIBWindow ();
+	DestroyFullDIBWindow ();
+
+	mode = modelist[modenum].modenum;
+
+	// Destroy old DC's, resetting back to fullscreen mode
+	if (mgldc)
+		MGL_destroyDC (mgldc);
+	if (memdc)
+		MGL_destroyDC (memdc);
+	mgldc = memdc = NULL;
+
+	if ((mgldc = createDisplayDC (modelist[modenum].stretched ||
+		 (int)vid_nopageflip.value)) == NULL)
+	{
+		return false;
+	}
+
+	modestate = MS_FULLSCREEN;
+	vid_fulldib_on_focus_mode = 0;
+
+	vid.buffer = vid.conbuffer = vid.direct = NULL;
+	vid.maxwarpwidth = WARP_WIDTH;
+	vid.maxwarpheight = WARP_HEIGHT;
+	DIBHeight = vid.height = vid.conheight = modelist[modenum].height;
+	DIBWidth = vid.width = vid.conwidth = modelist[modenum].width;
+	vid.aspect = ((float)vid.height / (float)vid.width) *
+				(320.0 / 240.0);
+
+	vid_stretched = modelist[modenum].stretched;
+
+// needed because we're not getting WM_MOVE messages fullscreen on NT
+	window_x = 0;
+	window_y = 0;
+
+// set the large icon, so the Quake icon will show up in the taskbar
+	SendMessage (mainwindow, WM_SETICON, (WPARAM)1, (LPARAM)hIcon);
+	SendMessage (mainwindow, WM_SETICON, (WPARAM)0, (LPARAM)hIcon);
+
+// shouldn't be needed, but Kendall needs to let us get the activation
+// message for this not to be needed on NT
+	AppActivate (true, false);
+
+	return true;
+}
+
+
+qboolean VID_SetFullDIBMode (int modenum)
+{
+	HDC				hdc;
+	pixel_format_t	pf;
+	int				lastmodestate;
+
+	DDActive = 0;
+
+	DestroyFullscreenWindow ();
+	DestroyDIBWindow ();
+
+	if (windc)
+		MGL_destroyDC(windc);
+	if (dibdc)
+		MGL_destroyDC(dibdc);
+	windc = dibdc = NULL;
+
+	// KJB: Signal to the MGL that we are going back to windowed mode
+	if (!MGL_changeDisplayMode(grWINDOWED))
+		initFatalError();
+
+	gdevmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
+	gdevmode.dmBitsPerPel = modelist[modenum].bpp;
+	gdevmode.dmPelsWidth = modelist[modenum].width << modelist[modenum].stretched <<
+						   modelist[modenum].halfscreen;
+	gdevmode.dmPelsHeight = modelist[modenum].height << modelist[modenum].stretched;
+	gdevmode.dmSize = sizeof (gdevmode);
+
+	if (ChangeDisplaySettings (&gdevmode, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL)
+		Sys_Error ("Couldn't set fullscreen DIB mode");
+
+	lastmodestate = modestate;
+	modestate = MS_FULLDIB;
+	vid_fulldib_on_focus_mode = modenum;
+
+	WindowRect.top = WindowRect.left = 0;
+
+	hdc = GetDC(NULL);
+
+	WindowRect.right = modelist[modenum].width << modelist[modenum].stretched;
+	WindowRect.bottom = modelist[modenum].height << modelist[modenum].stretched;
+
+	ReleaseDC(NULL,hdc);
+
+	DIBWidth = modelist[modenum].width;
+	DIBHeight = modelist[modenum].height;
+
+	WindowStyle = WS_POPUP | WS_SYSMENU | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
+	ExWindowStyle = 0;
+	AdjustWindowRectEx(&WindowRect, WindowStyle, FALSE, 0);
+
+	SetWindowLong(mainwindow, GWL_STYLE, WindowStyle | WS_VISIBLE);
+	SetWindowLong(mainwindow, GWL_EXSTYLE, ExWindowStyle);
+
+	if (!SetWindowPos (mainwindow,
+						   NULL,
+						   0, 0,
+						   WindowRect.right - WindowRect.left,
+						   WindowRect.bottom - WindowRect.top,
+						   SWP_NOCOPYBITS | SWP_NOZORDER))
+		{
+			Sys_Error ("Couldn't resize DIB window");
+		}
+
+// position and show the DIB window
+	SetWindowPos (mainwindow, HWND_TOPMOST, 0, 0, 0, 0,
+				  SWP_NOSIZE | SWP_SHOWWINDOW | SWP_DRAWFRAME);
+	ShowWindow (mainwindow, SW_SHOWDEFAULT);
+	UpdateWindow (mainwindow);
+
+	// Because we have set the background brush for the window to NULL
+	// (to avoid flickering when re-sizing the window on the desktop), we
+	// clear the window to black when created, otherwise it will be
+	// empty while Quake starts up.
+	hdc = GetDC(mainwindow);
+	PatBlt(hdc,0,0,WindowRect.right,WindowRect.bottom,BLACKNESS);
+	ReleaseDC(mainwindow, hdc);
+
+	/* Create the MGL window DC and the MGL memory DC */
+	if ((windc = MGL_createWindowedDC(mainwindow)) == NULL)
+		MGL_fatalError("Unable to create Fullscreen DIB DC!");
+
+	if ((dibdc = MGL_createMemoryDC(DIBWidth,DIBHeight,8,&pf)) == NULL)
+		MGL_fatalError("Unable to create Memory DC!");
+
+	MGL_makeCurrentDC(dibdc);
+
+	vid.buffer = vid.conbuffer = vid.direct = dibdc->surface;
+	vid.rowbytes = vid.conrowbytes = dibdc->mi.bytesPerLine;
+	vid.numpages = 1;
+	vid.maxwarpwidth = WARP_WIDTH;
+	vid.maxwarpheight = WARP_HEIGHT;
+	vid.height = vid.conheight = DIBHeight;
+	vid.width = vid.conwidth = DIBWidth;
+	vid.aspect = ((float)vid.height / (float)vid.width) *
+				(320.0 / 240.0);
+
+	vid_stretched = modelist[modenum].stretched;
+
+// needed because we're not getting WM_MOVE messages fullscreen on NT
+	window_x = 0;
+	window_y = 0;
+
+	return true;
+}
+
+
+void VID_RestoreOldMode (int original_mode)
+{
+	static qboolean	inerror = false;
+
+	if (inerror)
+		return;
+
+	in_mode_set = false;
+	inerror = true;
+
+// make sure mode set happens (video mode changes)
+	vid_modenum = original_mode - 1;
+
+	if (!VID_SetMode (original_mode, vid_curpal))
+	{
+		vid_modenum = MODE_WINDOWED - 1;
+
+		if (!VID_SetMode (windowed_default, vid_curpal))
+			Sys_Error ("Can't set any video mode");
+	}
+
+	inerror = false;
+}
+
+
+void VID_SetDefaultMode (void)
+{
+
+	if (vid_initialized)
+		VID_SetMode (0, vid_curpal);
+
+	IN_DeactivateMouse ();
+}
+
+
+int VID_SetMode (int modenum, unsigned char *palette)
+{
+	int				original_mode, temp, dummy;
+	qboolean		stat;
+    MSG				msg;
+	HDC				hdc;
+
+	while ((modenum >= nummodes) || (modenum < 0))
+	{
+		if (vid_modenum == NO_MODE)
+		{
+			if (modenum == vid_default)
+			{
+				modenum = windowed_default;
+			}
+			else
+			{
+				modenum = vid_default;
+			}
+
+			Cvar_SetValue ("vid_mode", (float)modenum);
+		}
+		else
+		{
+			Cvar_SetValue ("vid_mode", (float)vid_modenum);
+			return 0;
+		}
+	}
+
+	if (!force_mode_set && (modenum == vid_modenum))
+		return true;
+
+// so Con_Printfs don't mess us up by forcing vid and snd updates
+	temp = scr_disabled_for_loading;
+	scr_disabled_for_loading = true;
+	in_mode_set = true;
+
+	CDAudio_Pause ();
+	S_ClearBuffer ();
+
+	if (vid_modenum == NO_MODE)
+		original_mode = windowed_default;
+	else
+		original_mode = vid_modenum;
+
+	// Set either the fullscreen or windowed mode
+	if (modelist[modenum].type == MS_WINDOWED)
+	{
+		if (_windowed_mouse.value && key_dest == key_game)
+		{
+			stat = VID_SetWindowedMode(modenum);
+			IN_ActivateMouse ();
+			IN_HideMouse ();
+		}
+		else
+		{
+			IN_DeactivateMouse ();
+			IN_ShowMouse ();
+			stat = VID_SetWindowedMode(modenum);
+		}
+	}
+	else if (modelist[modenum].type == MS_FULLDIB)
+	{
+		stat = VID_SetFullDIBMode(modenum);
+		IN_ActivateMouse ();
+		IN_HideMouse ();
+	}
+	else
+	{
+		stat = VID_SetFullscreenMode(modenum);
+		IN_ActivateMouse ();
+		IN_HideMouse ();
+	}
+
+	window_width = vid.width << vid_stretched;
+	window_height = vid.height << vid_stretched;
+	VID_UpdateWindowStatus ();
+
+	CDAudio_Resume ();
+	scr_disabled_for_loading = temp;
+
+	if (!stat)
+	{
+		VID_RestoreOldMode (original_mode);
+		return false;
+	}
+
+	if (hide_window)
+		return true;
+
+// now we try to make sure we get the focus on the mode switch, because
+// sometimes in some systems we don't.  We grab the foreground, then
+// finish setting up, pump all our messages, and sleep for a little while
+// to let messages finish bouncing around the system, then we put
+// ourselves at the top of the z order, then grab the foreground again,
+// Who knows if it helps, but it probably doesn't hurt
+	if (!force_minimized)
+		SetForegroundWindow (mainwindow);
+
+	hdc = GetDC(NULL);
+
+	if (GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE)
+		vid_palettized = true;
+	else
+		vid_palettized = false;
+
+	VID_SetPalette (palette);
+
+	ReleaseDC(NULL,hdc);
+
+	vid_modenum = modenum;
+	Cvar_SetValue ("vid_mode", (float)vid_modenum);
+
+	if (!VID_AllocBuffers (vid.width, vid.height))
+	{
+	// couldn't get memory for this mode; try to fall back to previous mode
+		VID_RestoreOldMode (original_mode);
+		return false;
+	}
+
+	D_InitCaches (vid_surfcache, vid_surfcachesize);
+
+	while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE))
+	{
+      	TranslateMessage (&msg);
+      	DispatchMessage (&msg);
+	}
+
+	Sleep (100);
+
+	if (!force_minimized)
+	{
+		SetWindowPos (mainwindow, HWND_TOP, 0, 0, 0, 0,
+				  SWP_DRAWFRAME | SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW |
+				  SWP_NOCOPYBITS);
+
+		SetForegroundWindow (mainwindow);
+	}
+
+// fix the leftover Alt from any Alt-Tab or the like that switched us away
+	ClearAllStates ();
+
+	if (!msg_suppress_1)
+		Con_SafePrintf ("Video mode %s initialized\n", VID_GetModeDescription (vid_modenum));
+
+	VID_SetPalette (palette);
+
+	in_mode_set = false;
+	vid.recalc_refdef = 1;
+
+	return true;
+}
+
+void VID_LockBuffer (void)
+{
+
+	if (dibdc)
+		return;
+
+	lockcount++;
+
+	if (lockcount > 1)
+		return;
+
+	MGL_beginDirectAccess();
+
+	if (memdc)
+	{
+		// Update surface pointer for linear access modes
+		vid.buffer = vid.conbuffer = vid.direct = memdc->surface;
+		vid.rowbytes = vid.conrowbytes = memdc->mi.bytesPerLine;
+	}
+	else if (mgldc)
+	{
+		// Update surface pointer for linear access modes
+		vid.buffer = vid.conbuffer = vid.direct = mgldc->surface;
+		vid.rowbytes = vid.conrowbytes = mgldc->mi.bytesPerLine;
+	}
+
+	if (r_dowarp)
+		d_viewbuffer = r_warpbuffer;
+	else
+		d_viewbuffer = (void *)(byte *)vid.buffer;
+
+	if (r_dowarp)
+		screenwidth = WARP_WIDTH;
+	else
+		screenwidth = vid.rowbytes;
+
+	if (lcd_x.value)
+		screenwidth <<= 1;
+}
+		
+		
+void VID_UnlockBuffer (void)
+{
+	if (dibdc)
+		return;
+
+	lockcount--;
+
+	if (lockcount > 0)
+		return;
+
+	if (lockcount < 0)
+		Sys_Error ("Unbalanced unlock");
+
+	MGL_endDirectAccess();
+
+// to turn up any unlocked accesses
+	vid.buffer = vid.conbuffer = vid.direct = d_viewbuffer = NULL;
+
+}
+
+
+int VID_ForceUnlockedAndReturnState (void)
+{
+	int	lk;
+
+	if (!lockcount)
+		return 0;
+
+	lk = lockcount;
+
+	if (dibdc)
+	{
+		lockcount = 0;
+	}
+	else
+	{
+		lockcount = 1;
+		VID_UnlockBuffer ();
+	}
+
+	return lk;
+}
+
+
+void VID_ForceLockState (int lk)
+{
+
+	if (!dibdc && lk)
+	{
+		lockcount = 0;
+		VID_LockBuffer ();
+	}
+
+	lockcount = lk;
+}
+
+
+void	VID_SetPalette (unsigned char *palette)
+{
+	INT			i;
+	palette_t	pal[256];
+    HDC			hdc;
+
+	if (!Minimized)
+	{
+		palette_changed = true;
+
+	// make sure we have the static colors if we're the active app
+		hdc = GetDC(NULL);
+
+		if (vid_palettized && ActiveApp)
+		{
+			if (GetSystemPaletteUse(hdc) == SYSPAL_STATIC)
+			{
+			// switch to SYSPAL_NOSTATIC and remap the colors
+				SetSystemPaletteUse(hdc, SYSPAL_NOSTATIC);
+				syscolchg = true;
+				pal_is_nostatic = true;
+			}
+		}
+
+		ReleaseDC(NULL,hdc);
+
+		// Translate the palette values to an MGL palette array and
+		// set the values.
+		for (i = 0; i < 256; i++)
+		{
+			pal[i].red = palette[i*3];
+			pal[i].green = palette[i*3+1];
+			pal[i].blue = palette[i*3+2];
+		}
+
+		if (DDActive)
+		{
+			if (!mgldc)
+				return;
+
+			MGL_setPalette(mgldc,pal,256,0);
+			MGL_realizePalette(mgldc,256,0,false);
+			if (memdc)
+				MGL_setPalette(memdc,pal,256,0);
+		}
+		else
+		{
+			if (!windc)
+				return;
+
+			MGL_setPalette(windc,pal,256,0);
+			MGL_realizePalette(windc,256,0,false);
+			if (dibdc)
+			{
+				MGL_setPalette(dibdc,pal,256,0);
+				MGL_realizePalette(dibdc,256,0,false);
+			}
+		}
+	}
+
+	memcpy (vid_curpal, palette, sizeof(vid_curpal));
+
+	if (syscolchg)
+	{
+		PostMessage (HWND_BROADCAST, WM_SYSCOLORCHANGE, (WPARAM)0, (LPARAM)0);
+		syscolchg = false;
+	}
+}
+
+
+void	VID_ShiftPalette (unsigned char *palette)
+{
+	VID_SetPalette (palette);
+}
+
+
+/*
+=================
+VID_DescribeCurrentMode_f
+=================
+*/
+void VID_DescribeCurrentMode_f (void)
+{
+	Con_Printf ("%s\n", VID_GetExtModeDescription (vid_modenum));
+}
+
+
+/*
+=================
+VID_NumModes_f
+=================
+*/
+void VID_NumModes_f (void)
+{
+
+	if (nummodes == 1)
+		Con_Printf ("%d video mode is available\n", nummodes);
+	else
+		Con_Printf ("%d video modes are available\n", nummodes);
+}
+
+
+/*
+=================
+VID_DescribeMode_f
+=================
+*/
+void VID_DescribeMode_f (void)
+{
+	int		modenum;
+	
+	modenum = Q_atoi (Cmd_Argv(1));
+
+	Con_Printf ("%s\n", VID_GetExtModeDescription (modenum));
+}
+
+
+/*
+=================
+VID_DescribeModes_f
+=================
+*/
+void VID_DescribeModes_f (void)
+{
+	int			i, lnummodes;
+	char		*pinfo;
+	qboolean	na;
+	vmode_t		*pv;
+
+	na = false;
+
+	lnummodes = VID_NumModes ();
+
+	for (i=0 ; i<lnummodes ; i++)
+	{
+		pv = VID_GetModePtr (i);
+		pinfo = VID_GetExtModeDescription (i);
+
+		if (VID_CheckAdequateMem (pv->width, pv->height))
+		{
+			Con_Printf ("%2d: %s\n", i, pinfo);
+		}
+		else
+		{
+			Con_Printf ("**: %s\n", pinfo);
+			na = true;
+		}
+	}
+
+	if (na)
+	{
+		Con_Printf ("\n[**: not enough system RAM for mode]\n");
+	}
+}
+
+
+/*
+=================
+VID_TestMode_f
+=================
+*/
+void VID_TestMode_f (void)
+{
+	int		modenum;
+	double	testduration;
+
+	if (!vid_testingmode)
+	{
+		modenum = Q_atoi (Cmd_Argv(1));
+
+		if (VID_SetMode (modenum, vid_curpal))
+		{
+			vid_testingmode = 1;
+			testduration = Q_atof (Cmd_Argv(2));
+			if (testduration == 0)
+				testduration = 5.0;
+			vid_testendtime = realtime + testduration;
+		}
+	}
+}
+
+/*
+=================
+VID_Windowed_f
+=================
+*/
+void VID_Windowed_f (void)
+{
+
+	VID_SetMode ((int)vid_windowed_mode.value, vid_curpal);
+}
+
+
+/*
+=================
+VID_Fullscreen_f
+=================
+*/
+void VID_Fullscreen_f (void)
+{
+
+	VID_SetMode ((int)vid_fullscreen_mode.value, vid_curpal);
+}
+
+/*
+=================
+VID_Minimize_f
+=================
+*/
+void VID_Minimize_f (void)
+{
+
+// we only support minimizing windows; if you're fullscreen,
+// switch to windowed first
+	if (modestate == MS_WINDOWED)
+		ShowWindow (mainwindow, SW_MINIMIZE);
+}
+
+
+
+/*
+=================
+VID_ForceMode_f
+=================
+*/
+void VID_ForceMode_f (void)
+{
+	int		modenum;
+	double	testduration;
+
+	if (!vid_testingmode)
+	{
+		modenum = Q_atoi (Cmd_Argv(1));
+
+		force_mode_set = 1;
+		VID_SetMode (modenum, vid_curpal);
+		force_mode_set = 0;
+	}
+}
+
+
+void	VID_Init (unsigned char *palette)
+{
+	int		i, bestmatch, bestmatchmetric, t, dr, dg, db;
+	int		basenummodes;
+	byte	*ptmp;
+
+	Cvar_RegisterVariable (&vid_mode);
+	Cvar_RegisterVariable (&vid_wait);
+	Cvar_RegisterVariable (&vid_nopageflip);
+	Cvar_RegisterVariable (&_vid_wait_override);
+	Cvar_RegisterVariable (&_vid_default_mode);
+	Cvar_RegisterVariable (&_vid_default_mode_win);
+	Cvar_RegisterVariable (&vid_config_x);
+	Cvar_RegisterVariable (&vid_config_y);
+	Cvar_RegisterVariable (&vid_stretch_by_2);
+	Cvar_RegisterVariable (&_windowed_mouse);
+	Cvar_RegisterVariable (&vid_fullscreen_mode);
+	Cvar_RegisterVariable (&vid_windowed_mode);
+	Cvar_RegisterVariable (&block_switch);
+	Cvar_RegisterVariable (&vid_window_x);
+	Cvar_RegisterVariable (&vid_window_y);
+
+	Cmd_AddCommand ("vid_testmode", VID_TestMode_f);
+	Cmd_AddCommand ("vid_nummodes", VID_NumModes_f);
+	Cmd_AddCommand ("vid_describecurrentmode", VID_DescribeCurrentMode_f);
+	Cmd_AddCommand ("vid_describemode", VID_DescribeMode_f);
+	Cmd_AddCommand ("vid_describemodes", VID_DescribeModes_f);
+	Cmd_AddCommand ("vid_forcemode", VID_ForceMode_f);
+	Cmd_AddCommand ("vid_windowed", VID_Windowed_f);
+	Cmd_AddCommand ("vid_fullscreen", VID_Fullscreen_f);
+	Cmd_AddCommand ("vid_minimize", VID_Minimize_f);
+
+	if (COM_CheckParm ("-dibonly"))
+		dibonly = true;
+
+	VID_InitMGLDIB (global_hInstance);
+
+	basenummodes = nummodes;
+
+	if (!dibonly)
+		VID_InitMGLFull (global_hInstance);
+
+// if there are no non-windowed modes, or only windowed and mode 0x13, then use
+// fullscreen DIBs as well
+	if (((nummodes == basenummodes) ||
+		 ((nummodes == (basenummodes + 1)) && is_mode0x13)) &&
+		!COM_CheckParm ("-nofulldib"))
+
+	{
+		VID_InitFullDIB (global_hInstance);
+	}
+
+	vid.maxwarpwidth = WARP_WIDTH;
+	vid.maxwarpheight = WARP_HEIGHT;
+	vid.colormap = host_colormap;
+	vid.fullbright = 256 - LittleLong (*((int *)vid.colormap + 2048));
+	vid_testingmode = 0;
+
+// GDI doesn't let us remap palette index 0, so we'll remap color
+// mappings from that black to another one
+	bestmatchmetric = 256*256*3;
+
+	for (i=1 ; i<256 ; i++)
+	{
+		dr = palette[0] - palette[i*3];
+		dg = palette[1] - palette[i*3+1];
+		db = palette[2] - palette[i*3+2];
+
+		t = (dr * dr) + (dg * dg) + (db * db);
+
+		if (t < bestmatchmetric)
+		{
+			bestmatchmetric = t;
+			bestmatch = i;
+
+			if (t == 0)
+				break;
+		}
+	}
+
+	for (i=0, ptmp = vid.colormap ; i<(1<<(VID_CBITS+8)) ; i++, ptmp++)
+	{
+		if (*ptmp == 0)
+			*ptmp = bestmatch;
+	}
+
+	if (COM_CheckParm("-startwindowed"))
+	{
+		startwindowed = 1;
+		vid_default = windowed_default;
+	}
+
+	if (hwnd_dialog)
+		DestroyWindow (hwnd_dialog);
+
+// sound initialization has to go here, preceded by a windowed mode set,
+// so there's a window for DirectSound to work with but we're not yet
+// fullscreen so the "hardware already in use" dialog is visible if it
+// gets displayed
+
+// keep the window minimized until we're ready for the first real mode set
+	hide_window = true;
+	VID_SetMode (MODE_WINDOWED, palette);
+	hide_window = false;
+	S_Init ();
+
+	vid_initialized = true;
+
+	force_mode_set = true;
+	VID_SetMode (vid_default, palette);
+	force_mode_set = false;
+
+	vid_realmode = vid_modenum;
+
+	VID_SetPalette (palette);
+
+	vid_menudrawfn = VID_MenuDraw;
+	vid_menukeyfn = VID_MenuKey;
+
+	strcpy (badmode.modedesc, "Bad mode");
+}
+
+
+void	VID_Shutdown (void)
+{
+	HDC				hdc;
+	int				dummy;
+
+	if (vid_initialized)
+	{
+		if (modestate == MS_FULLDIB)
+			ChangeDisplaySettings (NULL, CDS_FULLSCREEN);
+
+		PostMessage (HWND_BROADCAST, WM_PALETTECHANGED, (WPARAM)mainwindow, (LPARAM)0);
+		PostMessage (HWND_BROADCAST, WM_SYSCOLORCHANGE, (WPARAM)0, (LPARAM)0);
+
+		AppActivate(false, false);
+		DestroyDIBWindow ();
+		DestroyFullscreenWindow ();
+		DestroyFullDIBWindow ();
+
+		if (hwnd_dialog)
+			DestroyWindow (hwnd_dialog);
+
+		if (mainwindow)
+			DestroyWindow(mainwindow);
+
+		MGL_exit();
+
+		vid_testingmode = 0;
+		vid_initialized = 0;
+	}
+}
+
+
+/*
+================
+FlipScreen
+================
+*/
+void FlipScreen(vrect_t *rects)
+{
+	HRESULT		ddrval;
+
+	// Flip the surfaces
+
+	if (DDActive)
+	{
+		if (mgldc)
+		{
+			if (memdc)
+			{
+				while (rects)
+				{
+					if (vid_stretched)
+					{
+						MGL_stretchBltCoord(mgldc, memdc,
+									rects->x,
+									rects->y,
+									rects->x + rects->width,
+									rects->y + rects->height,
+									rects->x << 1,
+									rects->y << 1,
+									(rects->x + rects->width) << 1,
+									(rects->y + rects->height) << 1);
+					}
+					else
+					{
+						MGL_bitBltCoord(mgldc, memdc,
+									rects->x, rects->y,
+									(rects->x + rects->width),
+									(rects->y + rects->height),
+									rects->x, rects->y, MGL_REPLACE_MODE);
+					}
+
+					rects = rects->pnext;
+				}
+			}
+
+			if (vid.numpages > 1)
+			{
+				// We have a flipping surface, so do a hard page flip
+				aPage = (aPage+1) % vid.numpages;
+				vPage = (vPage+1) % vid.numpages;
+				MGL_setActivePage(mgldc,aPage);
+				MGL_setVisualPage(mgldc,vPage,waitVRT);
+			}
+		}
+	}
+	else
+	{
+		HDC hdcScreen;
+
+		hdcScreen = GetDC(mainwindow);
+
+		if (windc && dibdc)
+		{
+			MGL_setWinDC(windc,hdcScreen);
+
+			while (rects)
+			{
+				if (vid_stretched)
+				{
+					MGL_stretchBltCoord(windc,dibdc,
+						rects->x, rects->y,
+						rects->x + rects->width, rects->y + rects->height,
+						rects->x << 1, rects->y << 1,
+						(rects->x + rects->width) << 1,
+						(rects->y + rects->height) << 1);
+				}
+				else
+				{
+					MGL_bitBltCoord(windc,dibdc,
+						rects->x, rects->y,
+						rects->x + rects->width, rects->y + rects->height,
+						rects->x, rects->y, MGL_REPLACE_MODE);
+				}
+
+				rects = rects->pnext;
+			}
+		}
+
+		ReleaseDC(mainwindow, hdcScreen);
+	}
+}
+
+
+void	VID_Update (vrect_t *rects)
+{
+	vrect_t	rect;
+	RECT	trect;
+
+	if (!vid_palettized && palette_changed)
+	{
+		palette_changed = false;
+		rect.x = 0;
+		rect.y = 0;
+		rect.width = vid.width;
+		rect.height = vid.height;
+		rect.pnext = NULL;
+		rects = &rect;
+	}
+
+	if (firstupdate)
+	{
+		if (modestate == MS_WINDOWED)
+		{
+			GetWindowRect (mainwindow, &trect);
+
+			if ((trect.left != (int)vid_window_x.value) ||
+				(trect.top  != (int)vid_window_y.value))
+			{
+				if (COM_CheckParm ("-resetwinpos"))
+				{
+					Cvar_SetValue ("vid_window_x", 0.0);
+					Cvar_SetValue ("vid_window_y", 0.0);
+				}
+
+				VID_CheckWindowXY ();
+				SetWindowPos (mainwindow, NULL, (int)vid_window_x.value,
+				  (int)vid_window_y.value, 0, 0,
+				  SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW | SWP_DRAWFRAME);
+			}
+		}
+
+		if ((_vid_default_mode_win.value != vid_default) &&
+			(!startwindowed || (_vid_default_mode_win.value < MODE_FULLSCREEN_DEFAULT)))
+		{
+			firstupdate = 0;
+
+			if (COM_CheckParm ("-resetwinpos"))
+			{
+				Cvar_SetValue ("vid_window_x", 0.0);
+				Cvar_SetValue ("vid_window_y", 0.0);
+			}
+
+			if ((_vid_default_mode_win.value < 0) ||
+				(_vid_default_mode_win.value >= nummodes))
+			{
+				Cvar_SetValue ("_vid_default_mode_win", windowed_default);
+			}
+
+			Cvar_SetValue ("vid_mode", _vid_default_mode_win.value);
+		}
+	}
+
+	// We've drawn the frame; copy it to the screen
+	FlipScreen (rects);
+
+	if (vid_testingmode)
+	{
+		if (realtime >= vid_testendtime)
+		{
+			VID_SetMode (vid_realmode, vid_curpal);
+			vid_testingmode = 0;
+		}
+	}
+	else
+	{
+		if ((int)vid_mode.value != vid_realmode)
+		{
+			VID_SetMode ((int)vid_mode.value, vid_curpal);
+			Cvar_SetValue ("vid_mode", (float)vid_modenum);
+								// so if mode set fails, we don't keep on
+								//  trying to set that mode
+			vid_realmode = vid_modenum;
+		}
+	}
+
+// handle the mouse state when windowed if that's changed
+	if (modestate == MS_WINDOWED)
+	{
+		if (!_windowed_mouse.value) {
+			if (windowed_mouse)	{
+				IN_DeactivateMouse ();
+				IN_ShowMouse ();
+			}
+			windowed_mouse = false;
+		} else {
+			windowed_mouse = true;
+			if (key_dest == key_game && !mouseactive && ActiveApp) {
+				IN_ActivateMouse ();
+				IN_HideMouse ();
+			} else if (mouseactive && key_dest != key_game) {
+				IN_DeactivateMouse ();
+				IN_ShowMouse ();
+			}
+		}
+	}
+}
+
+
+/*
+================
+D_BeginDirectRect
+================
+*/
+void D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height)
+{
+	int		i, j, reps, repshift;
+	vrect_t	rect;
+
+	if (!vid_initialized)
+		return;
+
+	if (vid.aspect > 1.5)
+	{
+		reps = 2;
+		repshift = 1;
+	}
+	else
+	{
+		reps = 1;
+		repshift = 0;
+	}
+
+	if (vid.numpages == 1)
+	{
+		VID_LockBuffer ();
+
+		if (!vid.direct)
+			Sys_Error ("NULL vid.direct pointer");
+
+		for (i=0 ; i<(height << repshift) ; i += reps)
+		{
+			for (j=0 ; j<reps ; j++)
+			{
+				memcpy (&backingbuf[(i + j) * 24],
+						vid.direct + x + ((y << repshift) + i + j) * vid.rowbytes,
+						width);
+				memcpy (vid.direct + x + ((y << repshift) + i + j) * vid.rowbytes,
+						&pbitmap[(i >> repshift) * width],
+						width);
+			}
+		}
+
+		VID_UnlockBuffer ();
+
+		rect.x = x;
+		rect.y = y;
+		rect.width = width;
+		rect.height = height << repshift;
+		rect.pnext = NULL;
+
+		FlipScreen (&rect);
+	}
+	else
+	{
+	// unlock if locked
+		if (lockcount > 0)
+			MGL_endDirectAccess();
+
+	// set the active page to the displayed page
+		MGL_setActivePage (mgldc, vPage);
+
+	// lock the screen
+		MGL_beginDirectAccess ();
+
+	// save from and draw to screen
+		for (i=0 ; i<(height << repshift) ; i += reps)
+		{
+			for (j=0 ; j<reps ; j++)
+			{
+				memcpy (&backingbuf[(i + j) * 24],
+						(byte *)mgldc->surface + x +
+						 ((y << repshift) + i + j) * mgldc->mi.bytesPerLine,
+						width);
+				memcpy ((byte *)mgldc->surface + x +
+						 ((y << repshift) + i + j) * mgldc->mi.bytesPerLine,
+						&pbitmap[(i >> repshift) * width],
+						width);
+			}
+		}
+
+	// unlock the screen
+		MGL_endDirectAccess ();
+
+	// restore the original active page
+		MGL_setActivePage (mgldc, aPage);
+
+	// relock the screen if it was locked
+		if (lockcount > 0)
+			MGL_beginDirectAccess();
+	}
+}
+
+
+/*
+================
+D_EndDirectRect
+================
+*/
+void D_EndDirectRect (int x, int y, int width, int height)
+{
+	int		i, j, reps, repshift;
+	vrect_t	rect;
+
+	if (!vid_initialized)
+		return;
+
+	if (vid.aspect > 1.5)
+	{
+		reps = 2;
+		repshift = 1;
+	}
+	else
+	{
+		reps = 1;
+		repshift = 0;
+	}
+
+	if (vid.numpages == 1)
+	{
+		VID_LockBuffer ();
+
+		if (!vid.direct)
+			Sys_Error ("NULL vid.direct pointer");
+
+		for (i=0 ; i<(height << repshift) ; i += reps)
+		{
+			for (j=0 ; j<reps ; j++)
+			{
+				memcpy (vid.direct + x + ((y << repshift) + i + j) * vid.rowbytes,
+						&backingbuf[(i + j) * 24],
+						width);
+			}
+		}
+
+		VID_UnlockBuffer ();
+
+		rect.x = x;
+		rect.y = y;
+		rect.width = width;
+		rect.height = height << repshift;
+		rect.pnext = NULL;
+
+		FlipScreen (&rect);
+	}
+	else
+	{
+	// unlock if locked
+		if (lockcount > 0)
+			MGL_endDirectAccess();
+
+	// set the active page to the displayed page
+		MGL_setActivePage (mgldc, vPage);
+
+	// lock the screen
+		MGL_beginDirectAccess ();
+
+	// restore to the screen
+		for (i=0 ; i<(height << repshift) ; i += reps)
+		{
+			for (j=0 ; j<reps ; j++)
+			{
+				memcpy ((byte *)mgldc->surface + x +
+						 ((y << repshift) + i + j) * mgldc->mi.bytesPerLine,
+						&backingbuf[(i + j) * 24],
+						width);
+			}
+		}
+
+	// unlock the screen
+		MGL_endDirectAccess ();
+
+	// restore the original active page
+		MGL_setActivePage (mgldc, aPage);
+
+	// relock the screen if it was locked
+		if (lockcount > 0)
+			MGL_beginDirectAccess();
+	}
+}
+
+
+//==========================================================================
+
+byte        scantokey[128] = 
+					{ 
+//  0           1       2       3       4       5       6       7 
+//  8           9       A       B       C       D       E       F 
+	0  ,    27,     '1',    '2',    '3',    '4',    '5',    '6', 
+	'7',    '8',    '9',    '0',    '-',    '=',    K_BACKSPACE, 9, // 0 
+	'q',    'w',    'e',    'r',    't',    'y',    'u',    'i', 
+	'o',    'p',    '[',    ']',    13 ,    K_CTRL,'a',  's',      // 1 
+	'd',    'f',    'g',    'h',    'j',    'k',    'l',    ';', 
+	'\'' ,    '`',    K_SHIFT,'\\',  'z',    'x',    'c',    'v',      // 2 
+	'b',    'n',    'm',    ',',    '.',    '/',    K_SHIFT,'*', 
+	K_ALT,' ',   0  ,    K_F1, K_F2, K_F3, K_F4, K_F5,   // 3 
+	K_F6, K_F7, K_F8, K_F9, K_F10,  K_PAUSE,    0  , K_HOME, 
+	K_UPARROW,K_PGUP,'-',K_LEFTARROW,'5',K_RIGHTARROW,'+',K_END, //4 
+	K_DOWNARROW,K_PGDN,K_INS,K_DEL,0,0,             0,              K_F11, 
+	K_F12,0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0,        // 5
+	0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0, 
+	0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0,        // 6 
+	0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0, 
+	0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0         // 7 
+}; 
+
+/*
+=======
+MapKey
+
+Map from windows to quake keynums
+=======
+*/
+int MapKey (int key)
+{
+	key = (key>>16)&255;
+	if (key > 127)
+		return 0;
+
+	return scantokey[key];
+}
+
+void AppActivate(BOOL fActive, BOOL minimize)
+/****************************************************************************
+*
+* Function:     AppActivate
+* Parameters:   fActive - True if app is activating
+*
+* Description:  If the application is activating, then swap the system
+*               into SYSPAL_NOSTATIC mode so that our palettes will display
+*               correctly.
+*
+****************************************************************************/
+{
+    HDC			hdc;
+    int			i, t;
+	static BOOL	sound_active;
+
+	ActiveApp = fActive;
+
+// messy, but it seems to work
+	if (vid_fulldib_on_focus_mode)
+	{
+	Minimized = minimize;
+
+	if (Minimized)
+			ActiveApp = false;
+	}
+
+	MGL_appActivate(windc, ActiveApp);
+
+	if (vid_initialized)
+	{
+	// yield the palette if we're losing the focus
+		hdc = GetDC(NULL);
+
+		if (GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE)
+		{
+			if (ActiveApp)
+			{
+				if ((modestate == MS_WINDOWED) || (modestate == MS_FULLDIB))
+				{
+				if (GetSystemPaletteUse(hdc) == SYSPAL_STATIC)
+				{
+				// switch to SYSPAL_NOSTATIC and remap the colors
+					SetSystemPaletteUse(hdc, SYSPAL_NOSTATIC);
+					syscolchg = true;
+						pal_is_nostatic = true;
+				}
+			}
+			}
+			else if (pal_is_nostatic)
+			{
+				if (GetSystemPaletteUse(hdc) == SYSPAL_NOSTATIC)
+				{
+				// switch back to SYSPAL_STATIC and the old mapping
+					SetSystemPaletteUse(hdc, SYSPAL_STATIC);
+					syscolchg = true;
+				}
+
+				pal_is_nostatic = false;
+			}
+		}
+
+		if (!Minimized)
+			VID_SetPalette (vid_curpal);
+
+		scr_fullupdate = 0;
+
+		ReleaseDC(NULL,hdc);
+	}
+
+// enable/disable sound on focus gain/loss
+	if (!ActiveApp && sound_active)
+	{
+		S_BlockSound ();
+		S_ClearBuffer ();
+		sound_active = false;
+	}
+	else if (ActiveApp && !sound_active)
+	{
+		S_UnblockSound ();
+		S_ClearBuffer ();
+		sound_active = true;
+	}
+
+// minimize/restore fulldib windows/mouse-capture normal windows on demand
+	if (!in_mode_set)
+	{
+		if (ActiveApp)
+		{
+			if (vid_fulldib_on_focus_mode)
+			{
+				if (vid_initialized)
+				{
+					msg_suppress_1 = true;	// don't want to see normal mode set message
+					VID_SetMode (vid_fulldib_on_focus_mode, vid_curpal);
+					msg_suppress_1 = false;
+
+					t = in_mode_set;
+					in_mode_set = true;
+					AppActivate (true, false);
+					in_mode_set = t;
+				}
+
+				IN_ActivateMouse ();
+				IN_HideMouse ();
+			}
+			else if ((modestate == MS_WINDOWED) && _windowed_mouse.value && key_dest == key_game)
+			{
+				IN_ActivateMouse ();
+				IN_HideMouse ();
+			}
+		}
+
+		if (!ActiveApp)
+		{
+			if (modestate == MS_FULLDIB)
+			{
+				if (vid_initialized)
+				{
+					force_minimized = true;
+					i = vid_fulldib_on_focus_mode;
+					msg_suppress_1 = true;	// don't want to see normal mode set message
+					VID_SetMode (windowed_default, vid_curpal);
+					msg_suppress_1 = false;
+					vid_fulldib_on_focus_mode = i;
+					force_minimized = false;
+
+				// we never seem to get WM_ACTIVATE inactive from this mode set, so we'll
+				// do it manually
+					t = in_mode_set;
+					in_mode_set = true;
+					AppActivate (false, true);
+					in_mode_set = t;
+				}
+
+				IN_DeactivateMouse ();
+				IN_ShowMouse ();
+			}
+			else if ((modestate == MS_WINDOWED) && _windowed_mouse.value /* && mouseactive */)
+			{
+				IN_DeactivateMouse ();
+				IN_ShowMouse ();
+			}
+		}
+	}
+}
+
+
+/*
+================
+VID_HandlePause
+================
+*/
+void VID_HandlePause (qboolean pause)
+{
+#if 0
+	if ((modestate == MS_WINDOWED) && _windowed_mouse.value)
+	{
+		if (pause)
+		{
+			IN_DeactivateMouse ();
+			IN_ShowMouse ();
+		}
+		else
+		{
+			IN_ActivateMouse ();
+			IN_HideMouse ();
+		}
+	}
+#endif
+}
+
+			
+/*
+===================================================================
+
+MAIN WINDOW
+
+===================================================================
+*/
+
+LONG CDAudio_MessageHandler(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
+
+/* main window procedure */
+LONG WINAPI MainWndProc (
+    HWND    hWnd,
+    UINT    uMsg,
+    WPARAM  wParam,
+    LPARAM  lParam)
+{
+	LONG			lRet = 0;
+	int				fwKeys, xPos, yPos, fActive, fMinimized, temp;
+	HDC				hdc;
+	PAINTSTRUCT		ps;
+	extern unsigned int uiWheelMessage;
+	static int		recursiveflag;
+
+	if ( uMsg == uiWheelMessage ) {
+		uMsg = WM_MOUSEWHEEL;
+		wParam <<= 16;
+	}
+
+
+	switch (uMsg)
+	{
+		case WM_CREATE:
+			break;
+
+		case WM_SYSCOMMAND:
+
+		// Check for maximize being hit
+			switch (wParam & ~0x0F)
+			{
+				case SC_MAXIMIZE:
+				// if minimized, bring up as a window before going fullscreen,
+				// so MGL will have the right state to restore
+					if (Minimized)
+					{
+						force_mode_set = true;
+						VID_SetMode (vid_modenum, vid_curpal);
+						force_mode_set = false;
+					}
+
+					VID_SetMode ((int)vid_fullscreen_mode.value, vid_curpal);
+					break;
+
+                case SC_SCREENSAVE:
+                case SC_MONITORPOWER:
+					if (modestate != MS_WINDOWED)
+					{
+					// don't call DefWindowProc() because we don't want to start
+					// the screen saver fullscreen
+						break;
+					}
+
+				// fall through windowed and allow the screen saver to start
+
+				default:
+				if (!in_mode_set)
+				{
+					S_BlockSound ();
+					S_ClearBuffer ();
+				}
+
+				lRet = DefWindowProc (hWnd, uMsg, wParam, lParam);
+
+				if (!in_mode_set)
+				{
+					S_UnblockSound ();
+				}
+			}
+			break;
+
+		case WM_MOVE:
+			window_x = (int) LOWORD(lParam);
+			window_y = (int) HIWORD(lParam);
+			VID_UpdateWindowStatus ();
+
+			if ((modestate == MS_WINDOWED) && !in_mode_set && !Minimized)
+				VID_RememberWindowPos ();
+
+			break;
+
+		case WM_SIZE:
+			Minimized = false;
+			
+			if (!(wParam & SIZE_RESTORED))
+			{
+				if (wParam & SIZE_MINIMIZED)
+					Minimized = true;
+			}
+			break;
+
+		case WM_SYSCHAR:
+		// keep Alt-Space from happening
+			break;
+
+		case WM_ACTIVATE:
+			fActive = LOWORD(wParam);
+			fMinimized = (BOOL) HIWORD(wParam);
+			AppActivate(!(fActive == WA_INACTIVE), fMinimized);
+
+		// fix the leftover Alt from any Alt-Tab or the like that switched us away
+			ClearAllStates ();
+
+			if (!in_mode_set)
+			{
+				if (windc)
+					MGL_activatePalette(windc,true);
+
+				VID_SetPalette(vid_curpal);
+			}
+
+			break;
+
+		case WM_PAINT:
+			hdc = BeginPaint(hWnd, &ps);
+
+			if (!in_mode_set && host_initialized)
+				SCR_UpdateWholeScreen ();
+
+			EndPaint(hWnd, &ps);
+			break;
+
+		case WM_KEYDOWN:
+		case WM_SYSKEYDOWN:
+			if (!in_mode_set)
+				Key_Event (MapKey(lParam), true);
+			break;
+
+		case WM_KEYUP:
+		case WM_SYSKEYUP:
+			if (!in_mode_set)
+				Key_Event (MapKey(lParam), false);
+			break;
+
+	// this is complicated because Win32 seems to pack multiple mouse events into
+	// one update sometimes, so we always check all states and look for events
+		case WM_LBUTTONDOWN:
+		case WM_LBUTTONUP:
+		case WM_RBUTTONDOWN:
+		case WM_RBUTTONUP:
+		case WM_MBUTTONDOWN:
+		case WM_MBUTTONUP:
+		case WM_MOUSEMOVE:
+			if (!in_mode_set)
+			{
+				temp = 0;
+
+				if (wParam & MK_LBUTTON)
+					temp |= 1;
+
+				if (wParam & MK_RBUTTON)
+					temp |= 2;
+
+				if (wParam & MK_MBUTTON)
+					temp |= 4;
+
+				IN_MouseEvent (temp);
+			}
+			break;
+		// JACK: This is the mouse wheel with the Intellimouse
+		// Its delta is either positive or neg, and we generate the proper
+		// Event.
+		case WM_MOUSEWHEEL: 
+			if ((short) HIWORD(wParam) > 0) {
+				Key_Event(K_MWHEELUP, true);
+				Key_Event(K_MWHEELUP, false);
+			} else {
+				Key_Event(K_MWHEELDOWN, true);
+				Key_Event(K_MWHEELDOWN, false);
+			}
+			break;
+		// KJB: Added these new palette functions
+		case WM_PALETTECHANGED:
+			if ((HWND)wParam == hWnd)
+				break;
+			/* Fall through to WM_QUERYNEWPALETTE */
+		case WM_QUERYNEWPALETTE:
+			hdc = GetDC(NULL);
+
+			if (GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE)
+				vid_palettized = true;
+			else
+				vid_palettized = false;
+
+			ReleaseDC(NULL,hdc);
+
+			scr_fullupdate = 0;
+
+			if (vid_initialized && !in_mode_set && windc && MGL_activatePalette(windc,false) && !Minimized)
+			{
+				VID_SetPalette (vid_curpal);
+				InvalidateRect (mainwindow, NULL, false);
+
+			// specifically required if WM_QUERYNEWPALETTE realizes a new palette
+				lRet = TRUE;
+			}
+			break;
+
+		case WM_DISPLAYCHANGE:
+			if (!in_mode_set && (modestate == MS_WINDOWED) && !vid_fulldib_on_focus_mode)
+			{
+				force_mode_set = true;
+				VID_SetMode (vid_modenum, vid_curpal);
+				force_mode_set = false;
+			}
+			break;
+
+   	    case WM_CLOSE:
+		// this causes Close in the right-click task bar menu not to work, but right
+		// now bad things happen if Close is handled in that case (garbage and a
+		// crash on Win95)
+			if (!in_mode_set)
+			{
+				if (MessageBox (mainwindow, "Are you sure you want to quit?", "Confirm Exit",
+							MB_YESNO | MB_SETFOREGROUND | MB_ICONQUESTION) == IDYES)
+				{
+					Sys_Quit ();
+				}
+			}
+			break;
+
+		case MM_MCINOTIFY:
+            lRet = CDAudio_MessageHandler (hWnd, uMsg, wParam, lParam);
+			break;
+
+		default:
+            /* pass all unhandled messages to DefWindowProc */
+            lRet = DefWindowProc (hWnd, uMsg, wParam, lParam);
+	        break;
+    }
+
+    /* return 0 if handled message, 1 if not */
+    return lRet;
+}
+
+
+extern void M_Menu_Options_f (void);
+extern void M_Print (int cx, int cy, char *str);
+extern void M_PrintWhite (int cx, int cy, char *str);
+extern void M_DrawCharacter (int cx, int line, int num);
+extern void M_DrawTransPic (int x, int y, qpic_t *pic);
+extern void M_DrawPic (int x, int y, qpic_t *pic);
+
+static int	vid_line, vid_wmodes;
+
+typedef struct
+{
+	int		modenum;
+	char	*desc;
+	int		iscur;
+	int		ismode13;
+	int		width;
+} modedesc_t;
+
+#define MAX_COLUMN_SIZE		5
+#define MODE_AREA_HEIGHT	(MAX_COLUMN_SIZE + 6)
+#define MAX_MODEDESCS		(MAX_COLUMN_SIZE*3)
+
+static modedesc_t	modedescs[MAX_MODEDESCS];
+
+/*
+================
+VID_MenuDraw
+================
+*/
+void VID_MenuDraw (void)
+{
+	qpic_t		*p;
+	char		*ptr;
+	int			lnummodes, i, j, k, column, row, dup, dupmode;
+	char		temp[100];
+	vmode_t		*pv;
+	modedesc_t	tmodedesc;
+
+	p = Draw_CachePic ("gfx/vidmodes.lmp");
+	M_DrawPic ( (320-p->width)/2, 4, p);
+
+	for (i=0 ; i<3 ; i++)
+	{
+		ptr = VID_GetModeDescriptionMemCheck (i);
+		modedescs[i].modenum = modelist[i].modenum;
+		modedescs[i].desc = ptr;
+		modedescs[i].ismode13 = 0;
+		modedescs[i].iscur = 0;
+
+		if (vid_modenum == i)
+			modedescs[i].iscur = 1;
+	}
+
+	vid_wmodes = 3;
+	lnummodes = VID_NumModes ();
+	
+	for (i=3 ; i<lnummodes ; i++)
+	{
+		ptr = VID_GetModeDescriptionMemCheck (i);
+		pv = VID_GetModePtr (i);
+
+	// we only have room for 15 fullscreen modes, so don't allow
+	// 360-wide modes, because if there are 5 320-wide modes and
+	// 5 360-wide modes, we'll run out of space
+		if (ptr && ((pv->width != 360) || COM_CheckParm("-allow360")))
+		{
+			dup = 0;
+
+			for (j=3 ; j<vid_wmodes ; j++)
+			{
+				if (!strcmp (modedescs[j].desc, ptr))
+				{
+					dup = 1;
+					dupmode = j;
+					break;
+				}
+			}
+
+			if (dup || (vid_wmodes < MAX_MODEDESCS))       
+			{
+				if (!dup || !modedescs[dupmode].ismode13 || COM_CheckParm("-noforcevga"))
+				{
+					if (dup)
+					{
+						k = dupmode;
+					}
+					else
+					{
+						k = vid_wmodes;
+					}
+
+					modedescs[k].modenum = i;
+					modedescs[k].desc = ptr;
+					modedescs[k].ismode13 = pv->mode13;
+					modedescs[k].iscur = 0;
+					modedescs[k].width = pv->width;
+
+					if (i == vid_modenum)
+						modedescs[k].iscur = 1;
+
+					if (!dup)
+						vid_wmodes++;
+				}
+			}
+		}
+	}
+
+// sort the modes on width (to handle picking up oddball dibonly modes
+// after all the others)
+	for (i=3 ; i<(vid_wmodes-1) ; i++)
+	{
+		for (j=(i+1) ; j<vid_wmodes ; j++)
+		{
+			if (modedescs[i].width > modedescs[j].width)
+			{
+				tmodedesc = modedescs[i];
+				modedescs[i] = modedescs[j];
+				modedescs[j] = tmodedesc;
+			}
+		}
+	}
+
+
+	M_Print (13*8, 36, "Windowed Modes");
+
+	column = 16;
+	row = 36+2*8;
+
+	for (i=0 ; i<3; i++)
+	{
+		if (modedescs[i].iscur)
+			M_PrintWhite (column, row, modedescs[i].desc);
+		else
+			M_Print (column, row, modedescs[i].desc);
+
+		column += 13*8;
+	}
+
+	if (vid_wmodes > 3)
+	{
+		M_Print (12*8, 36+4*8, "Fullscreen Modes");
+
+		column = 16;
+		row = 36+6*8;
+
+		for (i=3 ; i<vid_wmodes ; i++)
+		{
+			if (modedescs[i].iscur)
+				M_PrintWhite (column, row, modedescs[i].desc);
+			else
+				M_Print (column, row, modedescs[i].desc);
+
+			column += 13*8;
+
+			if (((i - 3) % VID_ROW_SIZE) == (VID_ROW_SIZE - 1))
+			{
+				column = 16;
+				row += 8;
+			}
+		}
+	}
+
+// line cursor
+	if (vid_testingmode)
+	{
+		sprintf (temp, "TESTING %s",
+				modedescs[vid_line].desc);
+		M_Print (13*8, 36 + MODE_AREA_HEIGHT * 8 + 8*4, temp);
+		M_Print (9*8, 36 + MODE_AREA_HEIGHT * 8 + 8*6,
+				"Please wait 5 seconds...");
+	}
+	else
+	{
+		M_Print (9*8, 36 + MODE_AREA_HEIGHT * 8 + 8,
+				"Press Enter to set mode");
+		M_Print (6*8, 36 + MODE_AREA_HEIGHT * 8 + 8*3,
+				"T to test mode for 5 seconds");
+		ptr = VID_GetModeDescription2 (vid_modenum);
+
+		if (ptr)
+		{
+			sprintf (temp, "D to set default: %s", ptr);
+			M_Print (2*8, 36 + MODE_AREA_HEIGHT * 8 + 8*5, temp);
+		}
+
+		ptr = VID_GetModeDescription2 ((int)_vid_default_mode_win.value);
+
+		if (ptr)
+		{
+			sprintf (temp, "Current default: %s", ptr);
+			M_Print (3*8, 36 + MODE_AREA_HEIGHT * 8 + 8*6, temp);
+		}
+
+		M_Print (15*8, 36 + MODE_AREA_HEIGHT * 8 + 8*8,
+				"Esc to exit");
+
+		row = 36 + 2*8 + (vid_line / VID_ROW_SIZE) * 8;
+		column = 8 + (vid_line % VID_ROW_SIZE) * 13*8;
+
+		if (vid_line >= 3)
+			row += 3*8;
+
+		M_DrawCharacter (column, row, 12+((int)(realtime*4)&1));
+	}
+}
+
+
+/*
+================
+VID_MenuKey
+================
+*/
+void VID_MenuKey (int key)
+{
+	if (vid_testingmode)
+		return;
+
+	switch (key)
+	{
+	case K_ESCAPE:
+		S_LocalSound ("misc/menu1.wav");
+		M_Menu_Options_f ();
+		break;
+
+	case K_LEFTARROW:
+
+		S_LocalSound ("misc/menu1.wav");
+		vid_line = ((vid_line / VID_ROW_SIZE) * VID_ROW_SIZE) +
+				   ((vid_line + 2) % VID_ROW_SIZE);
+
+		if (vid_line >= vid_wmodes)
+			vid_line = vid_wmodes - 1;
+		break;
+
+	case K_RIGHTARROW:
+		S_LocalSound ("misc/menu1.wav");
+		vid_line = ((vid_line / VID_ROW_SIZE) * VID_ROW_SIZE) +
+				   ((vid_line + 4) % VID_ROW_SIZE);
+
+		if (vid_line >= vid_wmodes)
+			vid_line = (vid_line / VID_ROW_SIZE) * VID_ROW_SIZE;
+		break;
+
+	case K_UPARROW:
+		S_LocalSound ("misc/menu1.wav");
+		vid_line -= VID_ROW_SIZE;
+
+		if (vid_line < 0)
+		{
+			vid_line += ((vid_wmodes + (VID_ROW_SIZE - 1)) /
+					VID_ROW_SIZE) * VID_ROW_SIZE;
+
+			while (vid_line >= vid_wmodes)
+				vid_line -= VID_ROW_SIZE;
+		}
+		break;
+
+	case K_DOWNARROW:
+		S_LocalSound ("misc/menu1.wav");
+		vid_line += VID_ROW_SIZE;
+
+		if (vid_line >= vid_wmodes)
+		{
+			vid_line -= ((vid_wmodes + (VID_ROW_SIZE - 1)) /
+					VID_ROW_SIZE) * VID_ROW_SIZE;
+
+			while (vid_line < 0)
+				vid_line += VID_ROW_SIZE;
+		}
+		break;
+
+	case K_ENTER:
+		S_LocalSound ("misc/menu1.wav");
+		VID_SetMode (modedescs[vid_line].modenum, vid_curpal);
+		break;
+
+	case 'T':
+	case 't':
+		S_LocalSound ("misc/menu1.wav");
+	// have to set this before setting the mode because WM_PAINT
+	// happens during the mode set and does a VID_Update, which
+	// checks vid_testingmode
+		vid_testingmode = 1;
+		vid_testendtime = realtime + 5.0;
+
+		if (!VID_SetMode (modedescs[vid_line].modenum, vid_curpal))
+		{
+			vid_testingmode = 0;
+		}
+		break;
+
+	case 'D':
+	case 'd':
+		S_LocalSound ("misc/menu1.wav");
+		firstupdate = 0;
+		Cvar_SetValue ("_vid_default_mode_win", vid_modenum);
+		break;
+
+	default:
+		break;
+	}
+}
--- /dev/null
+++ b/QW/client/vid_x.c
@@ -1,0 +1,1116 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// vid_x.c -- general x video driver
+
+#define _BSD
+
+typedef unsigned short PIXEL;
+
+#include <ctype.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/Xatom.h>
+#include <X11/keysym.h>
+#include <X11/extensions/XShm.h>
+
+#include "quakedef.h"
+#include "d_local.h"
+
+cvar_t		_windowed_mouse = {"_windowed_mouse","0", true};
+cvar_t		m_filter = {"m_filter","0", true};
+float old_windowed_mouse;
+
+// not used
+int		VGA_width, VGA_height, VGA_rowbytes, VGA_bufferrowbytes, VGA_planar;
+byte	*VGA_pagebase;
+
+
+qboolean        mouse_avail;
+int             mouse_buttons=3;
+int             mouse_oldbuttonstate;
+int             mouse_buttonstate;
+float   mouse_x, mouse_y;
+float   old_mouse_x, old_mouse_y;
+int p_mouse_x;
+int p_mouse_y;
+int ignorenext;
+int bits_per_pixel;
+
+typedef struct
+{
+	int input;
+	int output;
+} keymap_t;
+
+viddef_t vid; // global video state
+unsigned short d_8to16table[256];
+
+int		num_shades=32;
+
+int	d_con_indirect = 0;
+
+int		vid_buffersize;
+
+static qboolean			doShm;
+static Display			*x_disp;
+static Colormap			x_cmap;
+static Window			x_win;
+static GC				x_gc;
+static Visual			*x_vis;
+static XVisualInfo		*x_visinfo;
+//static XImage			*x_image;
+
+static int				x_shmeventtype;
+//static XShmSegmentInfo	x_shminfo;
+
+static qboolean			oktodraw = false;
+
+int XShmQueryExtension(Display *);
+int XShmGetEventBase(Display *);
+
+int current_framebuffer;
+static XImage			*x_framebuffer[2] = { 0, 0 };
+static XShmSegmentInfo	x_shminfo[2];
+
+static int verbose=0;
+
+static byte current_palette[768];
+
+static long X11_highhunkmark;
+static long X11_buffersize;
+
+int vid_surfcachesize;
+void *vid_surfcache;
+
+void (*vid_menudrawfn)(void);
+void (*vid_menukeyfn)(int key);
+void VID_MenuKey (int key);
+
+static PIXEL st2d_8to16table[256];
+static int shiftmask_fl=0;
+static long r_shift,g_shift,b_shift;
+static unsigned long r_mask,g_mask,b_mask;
+
+void shiftmask_init()
+{
+    unsigned int x;
+    r_mask=x_vis->red_mask;
+    g_mask=x_vis->green_mask;
+    b_mask=x_vis->blue_mask;
+    for(r_shift=-8,x=1;x<r_mask;x=x<<1)r_shift++;
+    for(g_shift=-8,x=1;x<g_mask;x=x<<1)g_shift++;
+    for(b_shift=-8,x=1;x<b_mask;x=x<<1)b_shift++;
+    shiftmask_fl=1;
+}
+
+PIXEL xlib_rgb(int r,int g,int b)
+{
+    PIXEL p;
+    if(shiftmask_fl==0) shiftmask_init();
+    p=0;
+
+    if(r_shift>0) {
+        p=(r<<(r_shift))&r_mask;
+    } else if(r_shift<0) {
+        p=(r>>(-r_shift))&r_mask;
+    } else p|=(r&r_mask);
+
+    if(g_shift>0) {
+        p|=(g<<(g_shift))&g_mask;
+    } else if(g_shift<0) {
+        p|=(g>>(-g_shift))&g_mask;
+    } else p|=(g&g_mask);
+
+    if(b_shift>0) {
+        p|=(b<<(b_shift))&b_mask;
+    } else if(b_shift<0) {
+        p|=(b>>(-b_shift))&b_mask;
+    } else p|=(b&b_mask);
+
+    return p;
+}
+
+void st2_fixup( XImage *framebuf, int x, int y, int width, int height)
+{
+	int xi,yi;
+	unsigned char *src;
+	PIXEL *dest;
+
+	if( (x<0)||(y<0) )return;
+
+	for (yi = y; yi < (y+height); yi++) {
+		src = &framebuf->data [yi * framebuf->bytes_per_line];
+		dest = (PIXEL*)src;
+		for(xi = (x+width-1); xi >= x; xi--) {
+			dest[xi] = st2d_8to16table[src[xi]];
+		}
+	}
+}
+
+
+// ========================================================================
+// Tragic death handler
+// ========================================================================
+
+void TragicDeath(int signal_num)
+{
+	XAutoRepeatOn(x_disp);
+	XCloseDisplay(x_disp);
+	Sys_Error("This death brought to you by the number %d\n", signal_num);
+}
+
+// ========================================================================
+// makes a null cursor
+// ========================================================================
+
+static Cursor CreateNullCursor(Display *display, Window root)
+{
+    Pixmap cursormask; 
+    XGCValues xgc;
+    GC gc;
+    XColor dummycolour;
+    Cursor cursor;
+
+    cursormask = XCreatePixmap(display, root, 1, 1, 1/*depth*/);
+    xgc.function = GXclear;
+    gc =  XCreateGC(display, cursormask, GCFunction, &xgc);
+    XFillRectangle(display, cursormask, gc, 0, 0, 1, 1);
+    dummycolour.pixel = 0;
+    dummycolour.red = 0;
+    dummycolour.flags = 04;
+    cursor = XCreatePixmapCursor(display, cursormask, cursormask,
+          &dummycolour,&dummycolour, 0,0);
+    XFreePixmap(display,cursormask);
+    XFreeGC(display,gc);
+    return cursor;
+}
+
+void ResetFrameBuffer(void)
+{
+	int mem;
+	int pwidth;
+
+	if (x_framebuffer[0])
+	{
+		free(x_framebuffer[0]->data);
+		free(x_framebuffer[0]);
+	}
+
+	if (d_pzbuffer)
+	{
+		D_FlushCaches ();
+		Hunk_FreeToHighMark (X11_highhunkmark);
+		d_pzbuffer = NULL;
+	}
+	X11_highhunkmark = Hunk_HighMark ();
+
+// alloc an extra line in case we want to wrap, and allocate the z-buffer
+	X11_buffersize = vid.width * vid.height * sizeof (*d_pzbuffer);
+
+	vid_surfcachesize = D_SurfaceCacheForRes (vid.width, vid.height);
+
+	X11_buffersize += vid_surfcachesize;
+
+	d_pzbuffer = Hunk_HighAllocName (X11_buffersize, "video");
+	if (d_pzbuffer == NULL)
+		Sys_Error ("Not enough memory for video mode\n");
+
+	vid_surfcache = (byte *) d_pzbuffer
+		+ vid.width * vid.height * sizeof (*d_pzbuffer);
+
+	D_InitCaches(vid_surfcache, vid_surfcachesize);
+
+	pwidth = x_visinfo->depth / 8;
+	if (pwidth == 3) pwidth = 4;
+	mem = ((vid.width*pwidth+7)&~7) * vid.height;
+
+	x_framebuffer[0] = XCreateImage(	x_disp,
+		x_vis,
+		x_visinfo->depth,
+		ZPixmap,
+		0,
+		malloc(mem),
+		vid.width, vid.height,
+		32,
+		0);
+
+	if (!x_framebuffer[0])
+		Sys_Error("VID: XCreateImage failed\n");
+
+	vid.buffer = (byte*) (x_framebuffer[0]);
+	vid.conbuffer = vid.buffer;
+
+}
+
+void ResetSharedFrameBuffers(void)
+{
+
+	int size;
+	int key;
+	int minsize = getpagesize();
+	int frm;
+
+	if (d_pzbuffer)
+	{
+		D_FlushCaches ();
+		Hunk_FreeToHighMark (X11_highhunkmark);
+		d_pzbuffer = NULL;
+	}
+
+	X11_highhunkmark = Hunk_HighMark ();
+
+// alloc an extra line in case we want to wrap, and allocate the z-buffer
+	X11_buffersize = vid.width * vid.height * sizeof (*d_pzbuffer);
+
+	vid_surfcachesize = D_SurfaceCacheForRes (vid.width, vid.height);
+
+	X11_buffersize += vid_surfcachesize;
+
+	d_pzbuffer = Hunk_HighAllocName (X11_buffersize, "video");
+	if (d_pzbuffer == NULL)
+		Sys_Error ("Not enough memory for video mode\n");
+
+	vid_surfcache = (byte *) d_pzbuffer
+		+ vid.width * vid.height * sizeof (*d_pzbuffer);
+
+	D_InitCaches(vid_surfcache, vid_surfcachesize);
+
+	for (frm=0 ; frm<2 ; frm++)
+	{
+
+	// free up old frame buffer memory
+
+		if (x_framebuffer[frm])
+		{
+			XShmDetach(x_disp, &x_shminfo[frm]);
+			free(x_framebuffer[frm]);
+			shmdt(x_shminfo[frm].shmaddr);
+		}
+
+	// create the image
+
+		x_framebuffer[frm] = XShmCreateImage(	x_disp,
+						x_vis,
+						x_visinfo->depth,
+						ZPixmap,
+						0,
+						&x_shminfo[frm],
+						vid.width,
+						vid.height );
+
+	// grab shared memory
+
+		size = x_framebuffer[frm]->bytes_per_line
+			* x_framebuffer[frm]->height;
+		if (size < minsize)
+			Sys_Error("VID: Window must use at least %d bytes\n", minsize);
+
+		key = random();
+		x_shminfo[frm].shmid = shmget((key_t)key, size, IPC_CREAT|0777);
+		if (x_shminfo[frm].shmid==-1)
+			Sys_Error("VID: Could not get any shared memory\n");
+
+		// attach to the shared memory segment
+		x_shminfo[frm].shmaddr =
+			(void *) shmat(x_shminfo[frm].shmid, 0, 0);
+
+		printf("VID: shared memory id=%d, addr=0x%lx\n", x_shminfo[frm].shmid,
+			(long) x_shminfo[frm].shmaddr);
+
+		x_framebuffer[frm]->data = x_shminfo[frm].shmaddr;
+
+	// get the X server to attach to it
+
+		if (!XShmAttach(x_disp, &x_shminfo[frm]))
+			Sys_Error("VID: XShmAttach() failed\n");
+		XSync(x_disp, 0);
+		shmctl(x_shminfo[frm].shmid, IPC_RMID, 0);
+
+	}
+
+}
+
+// Called at startup to set up translation tables, takes 256 8 bit RGB values
+// the palette data will go away after the call, so it must be copied off if
+// the video driver will need it again
+
+void	VID_Init (unsigned char *palette)
+{
+
+   int pnum, i;
+   XVisualInfo template;
+   int num_visuals;
+   int template_mask;
+
+	S_Init();
+   
+   ignorenext=0;
+   vid.width = 320;
+   vid.height = 200;
+   vid.maxwarpwidth = WARP_WIDTH;
+   vid.maxwarpheight = WARP_HEIGHT;
+   vid.numpages = 2;
+   vid.colormap = host_colormap;
+   //	vid.cbits = VID_CBITS;
+   //	vid.grades = VID_GRADES;
+   vid.fullbright = 256 - LittleLong (*((int *)vid.colormap + 2048));
+   
+	srandom(getpid());
+
+	verbose=COM_CheckParm("-verbose");
+
+// open the display
+	x_disp = XOpenDisplay(0);
+	if (!x_disp)
+	{
+		if (getenv("DISPLAY"))
+			Sys_Error("VID: Could not open display [%s]\n",
+				getenv("DISPLAY"));
+		else
+			Sys_Error("VID: Could not open local display\n");
+	}
+
+// catch signals so i can turn on auto-repeat
+
+	{
+		struct sigaction sa;
+		sigaction(SIGINT, 0, &sa);
+		sa.sa_handler = TragicDeath;
+		sigaction(SIGINT, &sa, 0);
+		sigaction(SIGTERM, &sa, 0);
+	}
+
+	XAutoRepeatOff(x_disp);
+
+// for debugging only
+	XSynchronize(x_disp, True);
+
+// check for command-line window size
+	if ((pnum=COM_CheckParm("-winsize")))
+	{
+		if (pnum >= com_argc-2)
+			Sys_Error("VID: -winsize <width> <height>\n");
+		vid.width = Q_atoi(com_argv[pnum+1]);
+		vid.height = Q_atoi(com_argv[pnum+2]);
+		if (!vid.width || !vid.height)
+			Sys_Error("VID: Bad window width/height\n");
+	}
+	if ((pnum=COM_CheckParm("-width"))) {
+		if (pnum >= com_argc-1)
+			Sys_Error("VID: -width <width>\n");
+		vid.width = Q_atoi(com_argv[pnum+1]);
+		if (!vid.width)
+			Sys_Error("VID: Bad window width\n");
+	}
+	if ((pnum=COM_CheckParm("-height"))) {
+		if (pnum >= com_argc-1)
+			Sys_Error("VID: -height <height>\n");
+		vid.height = Q_atoi(com_argv[pnum+1]);
+		if (!vid.height)
+			Sys_Error("VID: Bad window height\n");
+	}
+
+	template_mask = 0;
+
+// specify a visual id
+	if ((pnum=COM_CheckParm("-visualid")))
+	{
+		if (pnum >= com_argc-1)
+			Sys_Error("VID: -visualid <id#>\n");
+		template.visualid = Q_atoi(com_argv[pnum+1]);
+		template_mask = VisualIDMask;
+	}
+
+// If not specified, use default visual
+	else
+	{
+		int screen;
+		screen = XDefaultScreen(x_disp);
+		template.visualid =
+			XVisualIDFromVisual(XDefaultVisual(x_disp, screen));
+		template_mask = VisualIDMask;
+	}
+
+// pick a visual- warn if more than one was available
+	x_visinfo = XGetVisualInfo(x_disp, template_mask, &template, &num_visuals);
+	if (num_visuals > 1)
+	{
+		printf("Found more than one visual id at depth %d:\n", template.depth);
+		for (i=0 ; i<num_visuals ; i++)
+			printf("	-visualid %d\n", (int)(x_visinfo[i].visualid));
+	}
+	else if (num_visuals == 0)
+	{
+		if (template_mask == VisualIDMask)
+			Sys_Error("VID: Bad visual id %d\n", template.visualid);
+		else
+			Sys_Error("VID: No visuals at depth %d\n", template.depth);
+	}
+
+	if (verbose)
+	{
+		printf("Using visualid %d:\n", (int)(x_visinfo->visualid));
+		printf("	screen %d\n", x_visinfo->screen);
+		printf("	red_mask 0x%x\n", (int)(x_visinfo->red_mask));
+		printf("	green_mask 0x%x\n", (int)(x_visinfo->green_mask));
+		printf("	blue_mask 0x%x\n", (int)(x_visinfo->blue_mask));
+		printf("	colormap_size %d\n", x_visinfo->colormap_size);
+		printf("	bits_per_rgb %d\n", x_visinfo->bits_per_rgb);
+	}
+
+	x_vis = x_visinfo->visual;
+
+// setup attributes for main window
+	{
+	   int attribmask = CWEventMask  | CWColormap | CWBorderPixel;
+	   XSetWindowAttributes attribs;
+	   Colormap tmpcmap;
+	   
+	   tmpcmap = XCreateColormap(x_disp, XRootWindow(x_disp,
+							 x_visinfo->screen), x_vis, AllocNone);
+	   
+           attribs.event_mask = StructureNotifyMask | KeyPressMask
+	     | KeyReleaseMask | ExposureMask | PointerMotionMask |
+	     ButtonPressMask | ButtonReleaseMask;
+	   attribs.border_pixel = 0;
+	   attribs.colormap = tmpcmap;
+
+// create the main window
+		x_win = XCreateWindow(	x_disp,
+			XRootWindow(x_disp, x_visinfo->screen),
+			0, 0,	// x, y
+			vid.width, vid.height,
+			0, // borderwidth
+			x_visinfo->depth,
+			InputOutput,
+			x_vis,
+			attribmask,
+			&attribs );
+		XStoreName( x_disp,x_win,"xquake");
+
+
+		if (x_visinfo->class != TrueColor)
+			XFreeColormap(x_disp, tmpcmap);
+
+	}
+
+	if (x_visinfo->depth == 8)
+	{
+
+	// create and upload the palette
+		if (x_visinfo->class == PseudoColor)
+		{
+			x_cmap = XCreateColormap(x_disp, x_win, x_vis, AllocAll);
+			VID_SetPalette(palette);
+			XSetWindowColormap(x_disp, x_win, x_cmap);
+		}
+
+	}
+
+// inviso cursor
+	XDefineCursor(x_disp, x_win, CreateNullCursor(x_disp, x_win));
+
+// create the GC
+	{
+		XGCValues xgcvalues;
+		int valuemask = GCGraphicsExposures;
+		xgcvalues.graphics_exposures = False;
+		x_gc = XCreateGC(x_disp, x_win, valuemask, &xgcvalues );
+	}
+
+// map the window
+	XMapWindow(x_disp, x_win);
+
+// wait for first exposure event
+	{
+		XEvent event;
+		do
+		{
+			XNextEvent(x_disp, &event);
+			if (event.type == Expose && !event.xexpose.count)
+				oktodraw = true;
+		} while (!oktodraw);
+	}
+// now safe to draw
+
+// even if MITSHM is available, make sure it's a local connection
+	if (XShmQueryExtension(x_disp))
+	{
+		char *displayname;
+		doShm = true;
+		displayname = (char *) getenv("DISPLAY");
+		if (displayname)
+		{
+			char *d = displayname;
+			while (*d && (*d != ':')) d++;
+			if (*d) *d = 0;
+			if (!(!strcasecmp(displayname, "unix") || !*displayname))
+				doShm = false;
+		}
+	}
+
+	if (doShm)
+	{
+		x_shmeventtype = XShmGetEventBase(x_disp) + ShmCompletion;
+		ResetSharedFrameBuffers();
+	}
+	else
+		ResetFrameBuffer();
+
+	current_framebuffer = 0;
+	vid.rowbytes = x_framebuffer[0]->bytes_per_line;
+	vid.buffer = x_framebuffer[0]->data;
+	vid.direct = 0;
+	vid.conbuffer = x_framebuffer[0]->data;
+	vid.conrowbytes = vid.rowbytes;
+	vid.conwidth = vid.width;
+	vid.conheight = vid.height;
+	vid.aspect = ((float)vid.height / (float)vid.width) * (320.0 / 240.0);
+
+//	XSynchronize(x_disp, False);
+
+}
+
+void VID_ShiftPalette(unsigned char *p)
+{
+	VID_SetPalette(p);
+}
+
+
+
+void VID_SetPalette(unsigned char *palette)
+{
+
+	int i;
+	XColor colors[256];
+
+	for(i=0;i<256;i++)
+		st2d_8to16table[i]= xlib_rgb(palette[i*3],
+			palette[i*3+1],palette[i*3+2]);
+
+	if (x_visinfo->class == PseudoColor && x_visinfo->depth == 8)
+	{
+		if (palette != current_palette)
+			memcpy(current_palette, palette, 768);
+		for (i=0 ; i<256 ; i++)
+		{
+			colors[i].pixel = i;
+			colors[i].flags = DoRed|DoGreen|DoBlue;
+			colors[i].red = palette[i*3] * 257;
+			colors[i].green = palette[i*3+1] * 257;
+			colors[i].blue = palette[i*3+2] * 257;
+		}
+		XStoreColors(x_disp, x_cmap, colors, 256);
+	}
+
+}
+
+// Called at shutdown
+
+void	VID_Shutdown (void)
+{
+	Con_Printf("VID_Shutdown\n");
+	XAutoRepeatOn(x_disp);
+	XCloseDisplay(x_disp);
+}
+
+int XLateKey(XKeyEvent *ev)
+{
+
+	int key;
+	char buf[64];
+	KeySym keysym;
+
+	key = 0;
+
+	XLookupString(ev, buf, sizeof buf, &keysym, 0);
+
+	switch(keysym)
+	{
+		case XK_KP_Page_Up:
+		case XK_Page_Up:	 key = K_PGUP; break;
+
+		case XK_KP_Page_Down:
+		case XK_Page_Down:	 key = K_PGDN; break;
+
+		case XK_KP_Home:
+		case XK_Home:	 key = K_HOME; break;
+
+		case XK_KP_End:
+		case XK_End:	 key = K_END; break;
+
+		case XK_KP_Left:
+		case XK_Left:	 key = K_LEFTARROW; break;
+
+		case XK_KP_Right:
+		case XK_Right:	key = K_RIGHTARROW;		break;
+
+		case XK_KP_Down:
+		case XK_Down:	 key = K_DOWNARROW; break;
+
+		case XK_KP_Up:
+		case XK_Up:		 key = K_UPARROW;	 break;
+
+		case XK_Escape: key = K_ESCAPE;		break;
+
+		case XK_KP_Enter:
+		case XK_Return: key = K_ENTER;		 break;
+
+		case XK_Tab:		key = K_TAB;			 break;
+
+		case XK_F1:		 key = K_F1;				break;
+
+		case XK_F2:		 key = K_F2;				break;
+
+		case XK_F3:		 key = K_F3;				break;
+
+		case XK_F4:		 key = K_F4;				break;
+
+		case XK_F5:		 key = K_F5;				break;
+
+		case XK_F6:		 key = K_F6;				break;
+
+		case XK_F7:		 key = K_F7;				break;
+
+		case XK_F8:		 key = K_F8;				break;
+
+		case XK_F9:		 key = K_F9;				break;
+
+		case XK_F10:		key = K_F10;			 break;
+
+		case XK_F11:		key = K_F11;			 break;
+
+		case XK_F12:		key = K_F12;			 break;
+
+		case XK_BackSpace: key = K_BACKSPACE; break;
+
+		case XK_KP_Delete:
+		case XK_Delete: key = K_DEL; break;
+
+		case XK_Pause:	key = K_PAUSE;		 break;
+
+		case XK_Shift_L:
+		case XK_Shift_R:	key = K_SHIFT;		break;
+
+		case XK_Execute: 
+		case XK_Control_L: 
+		case XK_Control_R:	key = K_CTRL;		 break;
+
+		case XK_Alt_L:	
+		case XK_Meta_L: 
+		case XK_Alt_R:	
+		case XK_Meta_R: key = K_ALT;			break;
+
+		case XK_KP_Begin: key = K_AUX30;	break;
+
+		case XK_Insert:
+		case XK_KP_Insert: key = K_INS; break;
+
+		case XK_KP_Multiply: key = '*'; break;
+		case XK_KP_Add: key = '+'; break;
+		case XK_KP_Subtract: key = '-'; break;
+		case XK_KP_Divide: key = '/'; break;
+
+#if 0
+		case 0x021: key = '1';break;/* [!] */
+		case 0x040: key = '2';break;/* [@] */
+		case 0x023: key = '3';break;/* [#] */
+		case 0x024: key = '4';break;/* [$] */
+		case 0x025: key = '5';break;/* [%] */
+		case 0x05e: key = '6';break;/* [^] */
+		case 0x026: key = '7';break;/* [&] */
+		case 0x02a: key = '8';break;/* [*] */
+		case 0x028: key = '9';;break;/* [(] */
+		case 0x029: key = '0';break;/* [)] */
+		case 0x05f: key = '-';break;/* [_] */
+		case 0x02b: key = '=';break;/* [+] */
+		case 0x07c: key = '\'';break;/* [|] */
+		case 0x07d: key = '[';break;/* [}] */
+		case 0x07b: key = ']';break;/* [{] */
+		case 0x022: key = '\'';break;/* ["] */
+		case 0x03a: key = ';';break;/* [:] */
+		case 0x03f: key = '/';break;/* [?] */
+		case 0x03e: key = '.';break;/* [>] */
+		case 0x03c: key = ',';break;/* [<] */
+#endif
+
+		default:
+			key = *(unsigned char*)buf;
+			if (key >= 'A' && key <= 'Z')
+				key = key - 'A' + 'a';
+//			fprintf(stdout, "case 0x0%x: key = ___;break;/* [%c] */\n", keysym);
+			break;
+	} 
+
+	return key;
+}
+
+struct
+{
+	int key;
+	int down;
+} keyq[64];
+int keyq_head=0;
+int keyq_tail=0;
+
+int config_notify=0;
+int config_notify_width;
+int config_notify_height;
+						      
+void GetEvent(void)
+{
+	XEvent x_event;
+	int b;
+   
+	XNextEvent(x_disp, &x_event);
+	switch(x_event.type) {
+	case KeyPress:
+		keyq[keyq_head].key = XLateKey(&x_event.xkey);
+		keyq[keyq_head].down = true;
+		keyq_head = (keyq_head + 1) & 63;
+		break;
+	case KeyRelease:
+		keyq[keyq_head].key = XLateKey(&x_event.xkey);
+		keyq[keyq_head].down = false;
+		keyq_head = (keyq_head + 1) & 63;
+		break;
+
+	case MotionNotify:
+		if (_windowed_mouse.value) {
+			mouse_x = (float) ((int)x_event.xmotion.x - (int)(vid.width/2));
+			mouse_y = (float) ((int)x_event.xmotion.y - (int)(vid.height/2));
+//printf("m: x=%d,y=%d, mx=%3.2f,my=%3.2f\n", 
+//	x_event.xmotion.x, x_event.xmotion.y, mouse_x, mouse_y);
+
+			/* move the mouse to the window center again */
+			XSelectInput(x_disp,x_win,StructureNotifyMask|KeyPressMask
+				|KeyReleaseMask|ExposureMask
+				|ButtonPressMask
+				|ButtonReleaseMask);
+			XWarpPointer(x_disp,None,x_win,0,0,0,0, 
+				(vid.width/2),(vid.height/2));
+			XSelectInput(x_disp,x_win,StructureNotifyMask|KeyPressMask
+				|KeyReleaseMask|ExposureMask
+				|PointerMotionMask|ButtonPressMask
+				|ButtonReleaseMask);
+		} else {
+			mouse_x = (float) (x_event.xmotion.x-p_mouse_x);
+			mouse_y = (float) (x_event.xmotion.y-p_mouse_y);
+			p_mouse_x=x_event.xmotion.x;
+			p_mouse_y=x_event.xmotion.y;
+		}
+		break;
+
+	case ButtonPress:
+		b=-1;
+		if (x_event.xbutton.button == 1)
+			b = 0;
+		else if (x_event.xbutton.button == 2)
+			b = 2;
+		else if (x_event.xbutton.button == 3)
+			b = 1;
+		if (b>=0)
+			mouse_buttonstate |= 1<<b;
+		break;
+
+	case ButtonRelease:
+		b=-1;
+		if (x_event.xbutton.button == 1)
+			b = 0;
+		else if (x_event.xbutton.button == 2)
+			b = 2;
+		else if (x_event.xbutton.button == 3)
+			b = 1;
+		if (b>=0)
+			mouse_buttonstate &= ~(1<<b);
+		break;
+	
+	case ConfigureNotify:
+//printf("config notify\n");
+		config_notify_width = x_event.xconfigure.width;
+		config_notify_height = x_event.xconfigure.height;
+		config_notify = 1;
+		break;
+
+	default:
+		if (doShm && x_event.type == x_shmeventtype)
+			oktodraw = true;
+	}
+   
+	if (old_windowed_mouse != _windowed_mouse.value) {
+		old_windowed_mouse = _windowed_mouse.value;
+
+		if (!_windowed_mouse.value) {
+			/* ungrab the pointer */
+			XUngrabPointer(x_disp,CurrentTime);
+		} else {
+			/* grab the pointer */
+			XGrabPointer(x_disp,x_win,True,0,GrabModeAsync,
+				GrabModeAsync,x_win,None,CurrentTime);
+		}
+	}
+}
+
+// flushes the given rectangles from the view buffer to the screen
+
+void	VID_Update (vrect_t *rects)
+{
+
+// if the window changes dimension, skip this frame
+
+	if (config_notify)
+	{
+		fprintf(stderr, "config notify\n");
+		config_notify = 0;
+		vid.width = config_notify_width & ~7;
+		vid.height = config_notify_height;
+		if (doShm)
+			ResetSharedFrameBuffers();
+		else
+			ResetFrameBuffer();
+		vid.rowbytes = x_framebuffer[0]->bytes_per_line;
+		vid.buffer = x_framebuffer[current_framebuffer]->data;
+		vid.conbuffer = vid.buffer;
+		vid.conwidth = vid.width;
+		vid.conheight = vid.height;
+		vid.conrowbytes = vid.rowbytes;
+		vid.recalc_refdef = 1;				// force a surface cache flush
+		Con_CheckResize();
+		Con_Clear_f();
+		return;
+	}
+
+	if (doShm)
+	{
+
+		while (rects)
+		{
+			if (x_visinfo->depth != 8)
+				st2_fixup( x_framebuffer[current_framebuffer], 
+					rects->x, rects->y, rects->width,
+					rects->height);
+			if (!XShmPutImage(x_disp, x_win, x_gc,
+				x_framebuffer[current_framebuffer], rects->x, rects->y,
+				rects->x, rects->y, rects->width, rects->height, True))
+					Sys_Error("VID_Update: XShmPutImage failed\n");
+			oktodraw = false;
+			while (!oktodraw) GetEvent();
+			rects = rects->pnext;
+		}
+		current_framebuffer = !current_framebuffer;
+		vid.buffer = x_framebuffer[current_framebuffer]->data;
+		vid.conbuffer = vid.buffer;
+		XSync(x_disp, False);
+	}
+	else
+	{
+		while (rects)
+		{
+			if (x_visinfo->depth != 8)
+				st2_fixup( x_framebuffer[current_framebuffer], 
+					rects->x, rects->y, rects->width,
+					rects->height);
+			XPutImage(x_disp, x_win, x_gc, x_framebuffer[0], rects->x,
+				rects->y, rects->x, rects->y, rects->width, rects->height);
+			rects = rects->pnext;
+		}
+		XSync(x_disp, False);
+	}
+
+}
+
+static int dither;
+
+void VID_DitherOn(void)
+{
+    if (dither == 0)
+    {
+		vid.recalc_refdef = 1;
+        dither = 1;
+    }
+}
+
+void VID_DitherOff(void)
+{
+    if (dither)
+    {
+		vid.recalc_refdef = 1;
+        dither = 0;
+    }
+}
+
+int Sys_OpenWindow(void)
+{
+	return 0;
+}
+
+void Sys_EraseWindow(int window)
+{
+}
+
+void Sys_DrawCircle(int window, int x, int y, int r)
+{
+}
+
+void Sys_DisplayWindow(int window)
+{
+}
+
+void Sys_SendKeyEvents(void)
+{
+// get events from x server
+	if (x_disp)
+	{
+		while (XPending(x_disp)) GetEvent();
+		while (keyq_head != keyq_tail)
+		{
+			Key_Event(keyq[keyq_tail].key, keyq[keyq_tail].down);
+			keyq_tail = (keyq_tail + 1) & 63;
+		}
+	}
+}
+
+#if 0
+char *Sys_ConsoleInput (void)
+{
+
+	static char	text[256];
+	int		len;
+	fd_set  readfds;
+	int		ready;
+	struct timeval timeout;
+
+	timeout.tv_sec = 0;
+	timeout.tv_usec = 0;
+	FD_ZERO(&readfds);
+	FD_SET(0, &readfds);
+	ready = select(1, &readfds, 0, 0, &timeout);
+
+	if (ready>0)
+	{
+		len = read (0, text, sizeof(text));
+		if (len >= 1)
+		{
+			text[len-1] = 0;	// rip off the /n and terminate
+			return text;
+		}
+	}
+
+	return 0;
+	
+}
+#endif
+
+void D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height)
+{
+// direct drawing of the "accessing disk" icon isn't supported under Linux
+}
+
+void D_EndDirectRect (int x, int y, int width, int height)
+{
+// direct drawing of the "accessing disk" icon isn't supported under Linux
+}
+
+void IN_Init (void)
+{
+	Cvar_RegisterVariable (&_windowed_mouse);
+	Cvar_RegisterVariable (&m_filter);
+   if ( COM_CheckParm ("-nomouse") )
+     return;
+   mouse_x = mouse_y = 0.0;
+   mouse_avail = 1;
+}
+
+void IN_Shutdown (void)
+{
+   mouse_avail = 0;
+}
+
+void IN_Commands (void)
+{
+	int i;
+   
+	if (!mouse_avail) return;
+   
+	for (i=0 ; i<mouse_buttons ; i++) {
+		if ( (mouse_buttonstate & (1<<i)) && !(mouse_oldbuttonstate & (1<<i)) )
+			Key_Event (K_MOUSE1 + i, true);
+
+		if ( !(mouse_buttonstate & (1<<i)) && (mouse_oldbuttonstate & (1<<i)) )
+			Key_Event (K_MOUSE1 + i, false);
+	}
+	mouse_oldbuttonstate = mouse_buttonstate;
+}
+
+void IN_Move (usercmd_t *cmd)
+{
+	if (!mouse_avail)
+		return;
+   
+	if (m_filter.value) {
+		mouse_x = (mouse_x + old_mouse_x) * 0.5;
+		mouse_y = (mouse_y + old_mouse_y) * 0.5;
+	}
+
+	old_mouse_x = mouse_x;
+	old_mouse_y = mouse_y;
+   
+	mouse_x *= sensitivity.value;
+	mouse_y *= sensitivity.value;
+   
+	if ( (in_strafe.state & 1) || (lookstrafe.value && (in_mlook.state & 1) ))
+		cmd->sidemove += m_side.value * mouse_x;
+	else
+		cl.viewangles[YAW] -= m_yaw.value * mouse_x;
+	if (in_mlook.state & 1)
+		V_StopPitchDrift ();
+   
+	if ( (in_mlook.state & 1) && !(in_strafe.state & 1)) {
+		cl.viewangles[PITCH] += m_pitch.value * mouse_y;
+		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 * mouse_y;
+		else
+			cmd->forwardmove -= m_forward.value * mouse_y;
+	}
+	mouse_x = mouse_y = 0.0;
+}
+
+void VID_LockBuffer (void)
+{
+}
+
+void VID_UnlockBuffer (void)
+{
+}
+
--- /dev/null
+++ b/QW/client/view.c
@@ -1,0 +1,1072 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// view.c -- player eye positioning
+
+#include "quakedef.h"
+#include "r_local.h"
+
+/*
+
+The view is allowed to move slightly from it's true position for bobbing,
+but if it exceeds 8 pixels linear distance (spherical, not box), the list of
+entities sent from the server may not include everything in the pvs, especially
+when crossing a water boudnary.
+
+*/
+
+cvar_t	lcd_x = {"lcd_x", "0"};	// FIXME: make this work sometime...
+
+cvar_t	cl_rollspeed = {"cl_rollspeed", "200"};
+cvar_t	cl_rollangle = {"cl_rollangle", "2.0"};
+
+cvar_t	cl_bob = {"cl_bob","0.02", false};
+cvar_t	cl_bobcycle = {"cl_bobcycle","0.6", false};
+cvar_t	cl_bobup = {"cl_bobup","0.5", false};
+
+cvar_t	v_kicktime = {"v_kicktime", "0.5", false};
+cvar_t	v_kickroll = {"v_kickroll", "0.6", false};
+cvar_t	v_kickpitch = {"v_kickpitch", "0.6", false};
+
+cvar_t	v_iyaw_cycle = {"v_iyaw_cycle", "2", false};
+cvar_t	v_iroll_cycle = {"v_iroll_cycle", "0.5", false};
+cvar_t	v_ipitch_cycle = {"v_ipitch_cycle", "1", false};
+cvar_t	v_iyaw_level = {"v_iyaw_level", "0.3", false};
+cvar_t	v_iroll_level = {"v_iroll_level", "0.1", false};
+cvar_t	v_ipitch_level = {"v_ipitch_level", "0.3", false};
+
+cvar_t	v_idlescale = {"v_idlescale", "0", false};
+
+cvar_t	crosshair = {"crosshair", "0", true};
+cvar_t	crosshaircolor = {"crosshaircolor", "79", true};
+
+cvar_t  cl_crossx = {"cl_crossx", "0", true};
+cvar_t  cl_crossy = {"cl_crossy", "0", true};
+
+#ifdef GLQUAKE
+cvar_t	gl_cshiftpercent = {"gl_cshiftpercent", "100", false};
+#endif
+
+cvar_t  v_contentblend = {"v_contentblend", "1", false};
+
+float	v_dmg_time, v_dmg_roll, v_dmg_pitch;
+
+extern	int			in_forward, in_forward2, in_back;
+
+frame_t		*view_frame;
+player_state_t		*view_message;
+
+/*
+===============
+V_CalcRoll
+
+===============
+*/
+float V_CalcRoll (vec3_t angles, vec3_t velocity)
+{
+	vec3_t	forward, right, up;
+	float	sign;
+	float	side;
+	float	value;
+	
+	AngleVectors (angles, forward, right, up);
+	side = DotProduct (velocity, right);
+	sign = side < 0 ? -1 : 1;
+	side = fabs(side);
+	
+	value = cl_rollangle.value;
+
+	if (side < cl_rollspeed.value)
+		side = side * value / cl_rollspeed.value;
+	else
+		side = value;
+	
+	return side*sign;
+	
+}
+
+
+/*
+===============
+V_CalcBob
+
+===============
+*/
+float V_CalcBob (void)
+{
+	static	double	bobtime;
+	static float	bob;
+	float	cycle;
+	
+	if (cl.spectator)
+		return 0;
+
+	if (onground == -1)
+		return bob;		// just use old value
+
+	bobtime += host_frametime;
+	cycle = bobtime - (int)(bobtime/cl_bobcycle.value)*cl_bobcycle.value;
+	cycle /= cl_bobcycle.value;
+	if (cycle < cl_bobup.value)
+		cycle = M_PI * cycle / cl_bobup.value;
+	else
+		cycle = M_PI + M_PI*(cycle-cl_bobup.value)/(1.0 - cl_bobup.value);
+
+// bob is proportional to simulated velocity in the xy plane
+// (don't count Z, or jumping messes it up)
+
+	bob = sqrt(cl.simvel[0]*cl.simvel[0] + cl.simvel[1]*cl.simvel[1]) * cl_bob.value;
+	bob = bob*0.3 + bob*0.7*sin(cycle);
+	if (bob > 4)
+		bob = 4;
+	else if (bob < -7)
+		bob = -7;
+	return bob;
+	
+}
+
+
+//=============================================================================
+
+
+cvar_t	v_centermove = {"v_centermove", "0.15", false};
+cvar_t	v_centerspeed = {"v_centerspeed","500"};
+
+
+void V_StartPitchDrift (void)
+{
+#if 1
+	if (cl.laststop == cl.time)
+	{
+		return;		// something else is keeping it from drifting
+	}
+#endif
+	if (cl.nodrift || !cl.pitchvel)
+	{
+		cl.pitchvel = v_centerspeed.value;
+		cl.nodrift = false;
+		cl.driftmove = 0;
+	}
+}
+
+void V_StopPitchDrift (void)
+{
+	cl.laststop = cl.time;
+	cl.nodrift = true;
+	cl.pitchvel = 0;
+}
+
+/*
+===============
+V_DriftPitch
+
+Moves the client pitch angle towards cl.idealpitch sent by the server.
+
+If the user is adjusting pitch manually, either with lookup/lookdown,
+mlook and mouse, or klook and keyboard, pitch drifting is constantly stopped.
+
+Drifting is enabled when the center view key is hit, mlook is released and
+lookspring is non 0, or when 
+===============
+*/
+void V_DriftPitch (void)
+{
+	float		delta, move;
+
+	if (view_message->onground == -1 || cls.demoplayback )
+	{
+		cl.driftmove = 0;
+		cl.pitchvel = 0;
+		return;
+	}
+
+// don't count small mouse motion
+	if (cl.nodrift)
+	{
+		if ( fabs(cl.frames[(cls.netchan.outgoing_sequence-1)&UPDATE_MASK].cmd.forwardmove) < 200)
+			cl.driftmove = 0;
+		else
+			cl.driftmove += host_frametime;
+	
+		if ( cl.driftmove > v_centermove.value)
+		{
+			V_StartPitchDrift ();
+		}
+		return;
+	}
+	
+	delta = 0 - cl.viewangles[PITCH];
+
+	if (!delta)
+	{
+		cl.pitchvel = 0;
+		return;
+	}
+
+	move = host_frametime * cl.pitchvel;
+	cl.pitchvel += host_frametime * v_centerspeed.value;
+	
+//Con_Printf ("move: %f (%f)\n", move, host_frametime);
+
+	if (delta > 0)
+	{
+		if (move > delta)
+		{
+			cl.pitchvel = 0;
+			move = delta;
+		}
+		cl.viewangles[PITCH] += move;
+	}
+	else if (delta < 0)
+	{
+		if (move > -delta)
+		{
+			cl.pitchvel = 0;
+			move = -delta;
+		}
+		cl.viewangles[PITCH] -= move;
+	}
+}
+
+
+
+
+
+/*
+============================================================================== 
+ 
+						PALETTE FLASHES 
+ 
+============================================================================== 
+*/ 
+ 
+ 
+cshift_t	cshift_empty = { {130,80,50}, 0 };
+cshift_t	cshift_water = { {130,80,50}, 128 };
+cshift_t	cshift_slime = { {0,25,5}, 150 };
+cshift_t	cshift_lava = { {255,80,0}, 150 };
+
+cvar_t		v_gamma = {"gamma", "1", true};
+
+byte		gammatable[256];	// palette is sent through this
+
+
+#ifdef	GLQUAKE
+byte		ramps[3][256];
+float		v_blend[4];		// rgba 0.0 - 1.0
+#endif	// GLQUAKE
+
+void BuildGammaTable (float g)
+{
+	int		i, inf;
+	
+	if (g == 1.0)
+	{
+		for (i=0 ; i<256 ; i++)
+			gammatable[i] = i;
+		return;
+	}
+	
+	for (i=0 ; i<256 ; i++)
+	{
+		inf = 255 * pow ( (i+0.5)/255.5 , g ) + 0.5;
+		if (inf < 0)
+			inf = 0;
+		if (inf > 255)
+			inf = 255;
+		gammatable[i] = inf;
+	}
+}
+
+/*
+=================
+V_CheckGamma
+=================
+*/
+qboolean V_CheckGamma (void)
+{
+	static float oldgammavalue;
+	
+	if (v_gamma.value == oldgammavalue)
+		return false;
+	oldgammavalue = v_gamma.value;
+	
+	BuildGammaTable (v_gamma.value);
+	vid.recalc_refdef = 1;				// force a surface cache flush
+	
+	return true;
+}
+
+
+
+/*
+===============
+V_ParseDamage
+===============
+*/
+void V_ParseDamage (void)
+{
+	int		armor, blood;
+	vec3_t	from;
+	int		i;
+	vec3_t	forward, right, up;
+	float	side;
+	float	count;
+	
+	armor = MSG_ReadByte ();
+	blood = MSG_ReadByte ();
+	for (i=0 ; i<3 ; i++)
+		from[i] = MSG_ReadCoord ();
+
+	count = blood*0.5 + armor*0.5;
+	if (count < 10)
+		count = 10;
+
+	cl.faceanimtime = cl.time + 0.2;		// but sbar face into pain frame
+
+	cl.cshifts[CSHIFT_DAMAGE].percent += 3*count;
+	if (cl.cshifts[CSHIFT_DAMAGE].percent < 0)
+		cl.cshifts[CSHIFT_DAMAGE].percent = 0;
+	if (cl.cshifts[CSHIFT_DAMAGE].percent > 150)
+		cl.cshifts[CSHIFT_DAMAGE].percent = 150;
+
+	if (armor > blood)		
+	{
+		cl.cshifts[CSHIFT_DAMAGE].destcolor[0] = 200;
+		cl.cshifts[CSHIFT_DAMAGE].destcolor[1] = 100;
+		cl.cshifts[CSHIFT_DAMAGE].destcolor[2] = 100;
+	}
+	else if (armor)
+	{
+		cl.cshifts[CSHIFT_DAMAGE].destcolor[0] = 220;
+		cl.cshifts[CSHIFT_DAMAGE].destcolor[1] = 50;
+		cl.cshifts[CSHIFT_DAMAGE].destcolor[2] = 50;
+	}
+	else
+	{
+		cl.cshifts[CSHIFT_DAMAGE].destcolor[0] = 255;
+		cl.cshifts[CSHIFT_DAMAGE].destcolor[1] = 0;
+		cl.cshifts[CSHIFT_DAMAGE].destcolor[2] = 0;
+	}
+
+//
+// calculate view angle kicks
+//
+	VectorSubtract (from, cl.simorg, from);
+	VectorNormalize (from);
+	
+	AngleVectors (cl.simangles, forward, right, up);
+
+	side = DotProduct (from, right);
+	v_dmg_roll = count*side*v_kickroll.value;
+	
+	side = DotProduct (from, forward);
+	v_dmg_pitch = count*side*v_kickpitch.value;
+
+	v_dmg_time = v_kicktime.value;
+}
+
+
+/*
+==================
+V_cshift_f
+==================
+*/
+void V_cshift_f (void)
+{
+	cshift_empty.destcolor[0] = atoi(Cmd_Argv(1));
+	cshift_empty.destcolor[1] = atoi(Cmd_Argv(2));
+	cshift_empty.destcolor[2] = atoi(Cmd_Argv(3));
+	cshift_empty.percent = atoi(Cmd_Argv(4));
+}
+
+
+/*
+==================
+V_BonusFlash_f
+
+When you run over an item, the server sends this command
+==================
+*/
+void V_BonusFlash_f (void)
+{
+	cl.cshifts[CSHIFT_BONUS].destcolor[0] = 215;
+	cl.cshifts[CSHIFT_BONUS].destcolor[1] = 186;
+	cl.cshifts[CSHIFT_BONUS].destcolor[2] = 69;
+	cl.cshifts[CSHIFT_BONUS].percent = 50;
+}
+
+/*
+=============
+V_SetContentsColor
+
+Underwater, lava, etc each has a color shift
+=============
+*/
+void V_SetContentsColor (int contents)
+{
+	if (!v_contentblend.value) {
+		cl.cshifts[CSHIFT_CONTENTS] = cshift_empty;
+		return;
+	}
+
+	switch (contents)
+	{
+	case CONTENTS_EMPTY:
+		cl.cshifts[CSHIFT_CONTENTS] = cshift_empty;
+		break;
+	case CONTENTS_LAVA:
+		cl.cshifts[CSHIFT_CONTENTS] = cshift_lava;
+		break;
+	case CONTENTS_SOLID:
+	case CONTENTS_SLIME:
+		cl.cshifts[CSHIFT_CONTENTS] = cshift_slime;
+		break;
+	default:
+		cl.cshifts[CSHIFT_CONTENTS] = cshift_water;
+	}
+}
+
+/*
+=============
+V_CalcPowerupCshift
+=============
+*/
+void V_CalcPowerupCshift (void)
+{
+	if (cl.stats[STAT_ITEMS] & IT_QUAD)
+	{
+		cl.cshifts[CSHIFT_POWERUP].destcolor[0] = 0;
+		cl.cshifts[CSHIFT_POWERUP].destcolor[1] = 0;
+		cl.cshifts[CSHIFT_POWERUP].destcolor[2] = 255;
+		cl.cshifts[CSHIFT_POWERUP].percent = 30;
+	}
+	else if (cl.stats[STAT_ITEMS] & IT_SUIT)
+	{
+		cl.cshifts[CSHIFT_POWERUP].destcolor[0] = 0;
+		cl.cshifts[CSHIFT_POWERUP].destcolor[1] = 255;
+		cl.cshifts[CSHIFT_POWERUP].destcolor[2] = 0;
+		cl.cshifts[CSHIFT_POWERUP].percent = 20;
+	}
+	else if (cl.stats[STAT_ITEMS] & IT_INVISIBILITY)
+	{
+		cl.cshifts[CSHIFT_POWERUP].destcolor[0] = 100;
+		cl.cshifts[CSHIFT_POWERUP].destcolor[1] = 100;
+		cl.cshifts[CSHIFT_POWERUP].destcolor[2] = 100;
+		cl.cshifts[CSHIFT_POWERUP].percent = 100;
+	}
+	else if (cl.stats[STAT_ITEMS] & IT_INVULNERABILITY)
+	{
+		cl.cshifts[CSHIFT_POWERUP].destcolor[0] = 255;
+		cl.cshifts[CSHIFT_POWERUP].destcolor[1] = 255;
+		cl.cshifts[CSHIFT_POWERUP].destcolor[2] = 0;
+		cl.cshifts[CSHIFT_POWERUP].percent = 30;
+	}
+	else
+		cl.cshifts[CSHIFT_POWERUP].percent = 0;
+}
+
+
+/*
+=============
+V_CalcBlend
+=============
+*/
+#ifdef	GLQUAKE
+void V_CalcBlend (void)
+{
+	float	r, g, b, a, a2;
+	int		j;
+
+	r = 0;
+	g = 0;
+	b = 0;
+	a = 0;
+
+	for (j=0 ; j<NUM_CSHIFTS ; j++)	
+	{
+		if (!gl_cshiftpercent.value)
+			continue;
+
+		a2 = ((cl.cshifts[j].percent * gl_cshiftpercent.value) / 100.0) / 255.0;
+
+//		a2 = (cl.cshifts[j].percent/2)/255.0;
+		if (!a2)
+			continue;
+		a = a + a2*(1-a);
+//Con_Printf ("j:%i a:%f\n", j, a);
+		a2 = a2/a;
+		r = r*(1-a2) + cl.cshifts[j].destcolor[0]*a2;
+		g = g*(1-a2) + cl.cshifts[j].destcolor[1]*a2;
+		b = b*(1-a2) + cl.cshifts[j].destcolor[2]*a2;
+	}
+
+	v_blend[0] = r/255.0;
+	v_blend[1] = g/255.0;
+	v_blend[2] = b/255.0;
+	v_blend[3] = a;
+	if (v_blend[3] > 1)
+		v_blend[3] = 1;
+	if (v_blend[3] < 0)
+		v_blend[3] = 0;
+}
+#endif
+
+/*
+=============
+V_UpdatePalette
+=============
+*/
+#ifdef	GLQUAKE
+void V_UpdatePalette (void)
+{
+	int		i, j;
+	qboolean	new;
+	byte	*basepal, *newpal;
+	byte	pal[768];
+	float	r,g,b,a;
+	int		ir, ig, ib;
+	qboolean force;
+
+	V_CalcPowerupCshift ();
+	
+	new = false;
+	
+	for (i=0 ; i<NUM_CSHIFTS ; i++)
+	{
+		if (cl.cshifts[i].percent != cl.prev_cshifts[i].percent)
+		{
+			new = true;
+			cl.prev_cshifts[i].percent = cl.cshifts[i].percent;
+		}
+		for (j=0 ; j<3 ; j++)
+			if (cl.cshifts[i].destcolor[j] != cl.prev_cshifts[i].destcolor[j])
+			{
+				new = true;
+				cl.prev_cshifts[i].destcolor[j] = cl.cshifts[i].destcolor[j];
+			}
+	}
+
+// drop the damage value
+	cl.cshifts[CSHIFT_DAMAGE].percent -= host_frametime*150;
+	if (cl.cshifts[CSHIFT_DAMAGE].percent <= 0)
+		cl.cshifts[CSHIFT_DAMAGE].percent = 0;
+
+// drop the bonus value
+	cl.cshifts[CSHIFT_BONUS].percent -= host_frametime*100;
+	if (cl.cshifts[CSHIFT_BONUS].percent <= 0)
+		cl.cshifts[CSHIFT_BONUS].percent = 0;
+
+	force = V_CheckGamma ();
+	if (!new && !force)
+		return;
+
+	V_CalcBlend ();
+
+//Con_Printf("b: %4.2f %4.2f %4.2f %4.6f\n", v_blend[0],	v_blend[1],	v_blend[2],	v_blend[3]);
+
+	a = v_blend[3];
+	r = 255*v_blend[0]*a;
+	g = 255*v_blend[1]*a;
+	b = 255*v_blend[2]*a;
+
+	a = 1-a;
+	for (i=0 ; i<256 ; i++)
+	{
+		ir = i*a + r;
+		ig = i*a + g;
+		ib = i*a + b;
+		if (ir > 255)
+			ir = 255;
+		if (ig > 255)
+			ig = 255;
+		if (ib > 255)
+			ib = 255;
+
+		ramps[0][i] = gammatable[ir];
+		ramps[1][i] = gammatable[ig];
+		ramps[2][i] = gammatable[ib];
+	}
+
+	basepal = host_basepal;
+	newpal = pal;
+	
+	for (i=0 ; i<256 ; i++)
+	{
+		ir = basepal[0];
+		ig = basepal[1];
+		ib = basepal[2];
+		basepal += 3;
+		
+		newpal[0] = ramps[0][ir];
+		newpal[1] = ramps[1][ig];
+		newpal[2] = ramps[2][ib];
+		newpal += 3;
+	}
+
+	VID_ShiftPalette (pal);	
+}
+#else	// !GLQUAKE
+/*
+=============
+V_UpdatePalette
+=============
+*/
+void V_UpdatePalette (void)
+{
+	int		i, j;
+	qboolean	new;
+	byte	*basepal, *newpal;
+	byte	pal[768];
+	int		r,g,b;
+	qboolean force;
+
+	V_CalcPowerupCshift ();
+	
+	new = false;
+	
+	for (i=0 ; i<NUM_CSHIFTS ; i++)
+	{
+		if (cl.cshifts[i].percent != cl.prev_cshifts[i].percent)
+		{
+			new = true;
+			cl.prev_cshifts[i].percent = cl.cshifts[i].percent;
+		}
+		for (j=0 ; j<3 ; j++)
+			if (cl.cshifts[i].destcolor[j] != cl.prev_cshifts[i].destcolor[j])
+			{
+				new = true;
+				cl.prev_cshifts[i].destcolor[j] = cl.cshifts[i].destcolor[j];
+			}
+	}
+	
+// drop the damage value
+	cl.cshifts[CSHIFT_DAMAGE].percent -= host_frametime*150;
+	if (cl.cshifts[CSHIFT_DAMAGE].percent <= 0)
+		cl.cshifts[CSHIFT_DAMAGE].percent = 0;
+
+// drop the bonus value
+	cl.cshifts[CSHIFT_BONUS].percent -= host_frametime*100;
+	if (cl.cshifts[CSHIFT_BONUS].percent <= 0)
+		cl.cshifts[CSHIFT_BONUS].percent = 0;
+
+	force = V_CheckGamma ();
+	if (!new && !force)
+		return;
+			
+	basepal = host_basepal;
+	newpal = pal;
+	
+	for (i=0 ; i<256 ; i++)
+	{
+		r = basepal[0];
+		g = basepal[1];
+		b = basepal[2];
+		basepal += 3;
+	
+		for (j=0 ; j<NUM_CSHIFTS ; j++)	
+		{
+			r += (cl.cshifts[j].percent*(cl.cshifts[j].destcolor[0]-r))>>8;
+			g += (cl.cshifts[j].percent*(cl.cshifts[j].destcolor[1]-g))>>8;
+			b += (cl.cshifts[j].percent*(cl.cshifts[j].destcolor[2]-b))>>8;
+		}
+		
+		newpal[0] = gammatable[r];
+		newpal[1] = gammatable[g];
+		newpal[2] = gammatable[b];
+		newpal += 3;
+	}
+
+	VID_ShiftPalette (pal);	
+}
+
+#endif	// !GLQUAKE
+
+/* 
+============================================================================== 
+ 
+						VIEW RENDERING 
+ 
+============================================================================== 
+*/ 
+
+float angledelta (float a)
+{
+	a = anglemod(a);
+	if (a > 180)
+		a -= 360;
+	return a;
+}
+
+/*
+==================
+CalcGunAngle
+==================
+*/
+void CalcGunAngle (void)
+{	
+	float	yaw, pitch, move;
+	static float oldyaw = 0;
+	static float oldpitch = 0;
+	
+	yaw = r_refdef.viewangles[YAW];
+	pitch = -r_refdef.viewangles[PITCH];
+
+	yaw = angledelta(yaw - r_refdef.viewangles[YAW]) * 0.4;
+	if (yaw > 10)
+		yaw = 10;
+	if (yaw < -10)
+		yaw = -10;
+	pitch = angledelta(-pitch - r_refdef.viewangles[PITCH]) * 0.4;
+	if (pitch > 10)
+		pitch = 10;
+	if (pitch < -10)
+		pitch = -10;
+	move = host_frametime*20;
+	if (yaw > oldyaw)
+	{
+		if (oldyaw + move < yaw)
+			yaw = oldyaw + move;
+	}
+	else
+	{
+		if (oldyaw - move > yaw)
+			yaw = oldyaw - move;
+	}
+	
+	if (pitch > oldpitch)
+	{
+		if (oldpitch + move < pitch)
+			pitch = oldpitch + move;
+	}
+	else
+	{
+		if (oldpitch - move > pitch)
+			pitch = oldpitch - move;
+	}
+	
+	oldyaw = yaw;
+	oldpitch = pitch;
+
+	cl.viewent.angles[YAW] = r_refdef.viewangles[YAW] + yaw;
+	cl.viewent.angles[PITCH] = - (r_refdef.viewangles[PITCH] + pitch);
+}
+
+/*
+==============
+V_BoundOffsets
+==============
+*/
+void V_BoundOffsets (void)
+{
+// absolutely bound refresh reletive to entity clipping hull
+// so the view can never be inside a solid wall
+
+	if (r_refdef.vieworg[0] < cl.simorg[0] - 14)
+		r_refdef.vieworg[0] = cl.simorg[0] - 14;
+	else if (r_refdef.vieworg[0] > cl.simorg[0] + 14)
+		r_refdef.vieworg[0] = cl.simorg[0] + 14;
+	if (r_refdef.vieworg[1] < cl.simorg[1] - 14)
+		r_refdef.vieworg[1] = cl.simorg[1] - 14;
+	else if (r_refdef.vieworg[1] > cl.simorg[1] + 14)
+		r_refdef.vieworg[1] = cl.simorg[1] + 14;
+	if (r_refdef.vieworg[2] < cl.simorg[2] - 22)
+		r_refdef.vieworg[2] = cl.simorg[2] - 22;
+	else if (r_refdef.vieworg[2] > cl.simorg[2] + 30)
+		r_refdef.vieworg[2] = cl.simorg[2] + 30;
+}
+
+/*
+==============
+V_AddIdle
+
+Idle swaying
+==============
+*/
+void V_AddIdle (void)
+{
+	r_refdef.viewangles[ROLL] += v_idlescale.value * sin(cl.time*v_iroll_cycle.value) * v_iroll_level.value;
+	r_refdef.viewangles[PITCH] += v_idlescale.value * sin(cl.time*v_ipitch_cycle.value) * v_ipitch_level.value;
+	r_refdef.viewangles[YAW] += v_idlescale.value * sin(cl.time*v_iyaw_cycle.value) * v_iyaw_level.value;
+
+	cl.viewent.angles[ROLL] -= v_idlescale.value * sin(cl.time*v_iroll_cycle.value) * v_iroll_level.value;
+	cl.viewent.angles[PITCH] -= v_idlescale.value * sin(cl.time*v_ipitch_cycle.value) * v_ipitch_level.value;
+	cl.viewent.angles[YAW] -= v_idlescale.value * sin(cl.time*v_iyaw_cycle.value) * v_iyaw_level.value;
+}
+
+
+/*
+==============
+V_CalcViewRoll
+
+Roll is induced by movement and damage
+==============
+*/
+void V_CalcViewRoll (void)
+{
+	float		side;
+		
+	side = V_CalcRoll (cl.simangles, cl.simvel);
+	r_refdef.viewangles[ROLL] += side;
+
+	if (v_dmg_time > 0)
+	{
+		r_refdef.viewangles[ROLL] += v_dmg_time/v_kicktime.value*v_dmg_roll;
+		r_refdef.viewangles[PITCH] += v_dmg_time/v_kicktime.value*v_dmg_pitch;
+		v_dmg_time -= host_frametime;
+	}
+
+}
+
+
+/*
+==================
+V_CalcIntermissionRefdef
+
+==================
+*/
+void V_CalcIntermissionRefdef (void)
+{
+	entity_t	*view;
+	float		old;
+
+// view is the weapon model
+	view = &cl.viewent;
+
+	VectorCopy (cl.simorg, r_refdef.vieworg);
+	VectorCopy (cl.simangles, r_refdef.viewangles);
+	view->model = NULL;
+
+// allways idle in intermission
+	old = v_idlescale.value;
+	v_idlescale.value = 1;
+	V_AddIdle ();
+	v_idlescale.value = old;
+}
+
+/*
+==================
+V_CalcRefdef
+
+==================
+*/
+void V_CalcRefdef (void)
+{
+	entity_t	*view;
+	int			i;
+	vec3_t		forward, right, up;
+	float		bob;
+	static float oldz = 0;
+
+	V_DriftPitch ();
+
+// view is the weapon model (only visible from inside body)
+	view = &cl.viewent;
+
+	bob = V_CalcBob ();
+	
+// refresh position from simulated origin
+	VectorCopy (cl.simorg, r_refdef.vieworg);
+
+	r_refdef.vieworg[2] += bob;
+
+// never let it sit exactly on a node line, because a water plane can
+// dissapear when viewed with the eye exactly on it.
+// the server protocol only specifies to 1/8 pixel, so add 1/16 in each axis
+	r_refdef.vieworg[0] += 1.0/16;
+	r_refdef.vieworg[1] += 1.0/16;
+	r_refdef.vieworg[2] += 1.0/16;
+
+	VectorCopy (cl.simangles, r_refdef.viewangles);
+	V_CalcViewRoll ();
+	V_AddIdle ();
+
+	if (view_message->flags & PF_GIB)
+		r_refdef.vieworg[2] += 8;	// gib view height
+	else if (view_message->flags & PF_DEAD)
+		r_refdef.vieworg[2] -= 16;	// corpse view height
+	else
+		r_refdef.vieworg[2] += 22;	// view height
+
+	if (view_message->flags & PF_DEAD)		// PF_GIB will also set PF_DEAD
+		r_refdef.viewangles[ROLL] = 80;	// dead view angle
+
+
+// offsets
+	AngleVectors (cl.simangles, forward, right, up);
+	
+// set up gun position
+	VectorCopy (cl.simangles, view->angles);
+	
+	CalcGunAngle ();
+
+	VectorCopy (cl.simorg, view->origin);
+	view->origin[2] += 22;
+
+	for (i=0 ; i<3 ; i++)
+	{
+		view->origin[i] += forward[i]*bob*0.4;
+//		view->origin[i] += right[i]*bob*0.4;
+//		view->origin[i] += up[i]*bob*0.8;
+	}
+	view->origin[2] += bob;
+
+// fudge position around to keep amount of weapon visible
+// roughly equal with different FOV
+	if (scr_viewsize.value == 110)
+		view->origin[2] += 1;
+	else if (scr_viewsize.value == 100)
+		view->origin[2] += 2;
+	else if (scr_viewsize.value == 90)
+		view->origin[2] += 1;
+	else if (scr_viewsize.value == 80)
+		view->origin[2] += 0.5;
+
+	if (view_message->flags & (PF_GIB|PF_DEAD) )
+ 		view->model = NULL;
+ 	else
+		view->model = cl.model_precache[cl.stats[STAT_WEAPON]];
+	view->frame = view_message->weaponframe;
+	view->colormap = vid.colormap;
+
+// set up the refresh position
+	r_refdef.viewangles[PITCH] += cl.punchangle;
+
+// smooth out stair step ups
+	if ( (view_message->onground != -1) && (cl.simorg[2] - oldz > 0) )
+	{
+		float steptime;
+		
+		steptime = host_frametime;
+	
+		oldz += steptime * 80;
+		if (oldz > cl.simorg[2])
+			oldz = cl.simorg[2];
+		if (cl.simorg[2] - oldz > 12)
+			oldz = cl.simorg[2] - 12;
+		r_refdef.vieworg[2] += oldz - cl.simorg[2];
+		view->origin[2] += oldz - cl.simorg[2];
+	}
+	else
+		oldz = cl.simorg[2];
+}
+
+/*
+=============
+DropPunchAngle
+=============
+*/
+void DropPunchAngle (void)
+{
+	cl.punchangle -= 10*host_frametime;
+	if (cl.punchangle < 0)
+		cl.punchangle = 0;
+}
+
+/*
+==================
+V_RenderView
+
+The player's clipping box goes from (-16 -16 -24) to (16 16 32) from
+the entity origin, so any view position inside that will be valid
+==================
+*/
+extern vrect_t scr_vrect;
+
+void V_RenderView (void)
+{
+//	if (cl.simangles[ROLL])
+//		Sys_Error ("cl.simangles[ROLL]");	// DEBUG
+cl.simangles[ROLL] = 0;	// FIXME @@@ 
+
+	if (cls.state != ca_active)
+		return;
+
+	view_frame = &cl.frames[cls.netchan.incoming_sequence & UPDATE_MASK];
+	view_message = &view_frame->playerstate[cl.playernum];
+
+	DropPunchAngle ();
+	if (cl.intermission)
+	{	// intermission / finale rendering
+		V_CalcIntermissionRefdef ();	
+	}
+	else
+	{
+		V_CalcRefdef ();
+	}
+
+	R_PushDlights ();
+	R_RenderView ();
+	
+#ifndef GLQUAKE
+	if (crosshair.value)
+		Draw_Crosshair();
+#endif
+		
+}
+
+//============================================================================
+
+/*
+=============
+V_Init
+=============
+*/
+void V_Init (void)
+{
+	Cmd_AddCommand ("v_cshift", V_cshift_f);	
+	Cmd_AddCommand ("bf", V_BonusFlash_f);
+	Cmd_AddCommand ("centerview", V_StartPitchDrift);
+
+	Cvar_RegisterVariable (&v_centermove);
+	Cvar_RegisterVariable (&v_centerspeed);
+
+	Cvar_RegisterVariable (&v_iyaw_cycle);
+	Cvar_RegisterVariable (&v_iroll_cycle);
+	Cvar_RegisterVariable (&v_ipitch_cycle);
+	Cvar_RegisterVariable (&v_iyaw_level);
+	Cvar_RegisterVariable (&v_iroll_level);
+	Cvar_RegisterVariable (&v_ipitch_level);
+
+	Cvar_RegisterVariable (&v_contentblend);
+
+	Cvar_RegisterVariable (&v_idlescale);
+	Cvar_RegisterVariable (&crosshaircolor);
+	Cvar_RegisterVariable (&crosshair);
+	Cvar_RegisterVariable (&cl_crossx);
+	Cvar_RegisterVariable (&cl_crossy);
+#ifdef GLQUAKE
+	Cvar_RegisterVariable (&gl_cshiftpercent);
+#endif
+
+	Cvar_RegisterVariable (&cl_rollspeed);
+	Cvar_RegisterVariable (&cl_rollangle);
+	Cvar_RegisterVariable (&cl_bob);
+	Cvar_RegisterVariable (&cl_bobcycle);
+	Cvar_RegisterVariable (&cl_bobup);
+
+	Cvar_RegisterVariable (&v_kicktime);
+	Cvar_RegisterVariable (&v_kickroll);
+	Cvar_RegisterVariable (&v_kickpitch);	
+
+	BuildGammaTable (1.0);	// no gamma yet
+	Cvar_RegisterVariable (&v_gamma);
+}
+
+
--- /dev/null
+++ b/QW/client/view.h
@@ -1,0 +1,32 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// view.h
+
+extern	cvar_t		v_gamma;
+extern	cvar_t		lcd_x;
+#ifdef GLQUAKE
+extern float v_blend[4];
+#endif
+
+void V_Init (void);
+void V_RenderView (void);
+float V_CalcRoll (vec3_t angles, vec3_t velocity);
+void V_UpdatePalette (void);
+
--- /dev/null
+++ b/QW/client/wad.c
@@ -1,0 +1,158 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// wad.c
+
+#include "quakedef.h"
+
+int			wad_numlumps;
+lumpinfo_t	*wad_lumps;
+byte		*wad_base;
+
+void SwapPic (qpic_t *pic);
+
+/*
+==================
+W_CleanupName
+
+Lowercases name and pads with spaces and a terminating 0 to the length of
+lumpinfo_t->name.
+Used so lumpname lookups can proceed rapidly by comparing 4 chars at a time
+Space padding is so names can be printed nicely in tables.
+Can safely be performed in place.
+==================
+*/
+void W_CleanupName (char *in, char *out)
+{
+	int		i;
+	int		c;
+	
+	for (i=0 ; i<16 ; i++ )
+	{
+		c = in[i];
+		if (!c)
+			break;
+			
+		if (c >= 'A' && c <= 'Z')
+			c += ('a' - 'A');
+		out[i] = c;
+	}
+	
+	for ( ; i< 16 ; i++ )
+		out[i] = 0;
+}
+
+
+
+/*
+====================
+W_LoadWadFile
+====================
+*/
+void W_LoadWadFile (char *filename)
+{
+	lumpinfo_t		*lump_p;
+	wadinfo_t		*header;
+	unsigned		i;
+	int				infotableofs;
+	
+	wad_base = COM_LoadHunkFile (filename);
+	if (!wad_base)
+		Sys_Error ("W_LoadWadFile: couldn't load %s", filename);
+
+	header = (wadinfo_t *)wad_base;
+	
+	if (header->identification[0] != 'W'
+	|| header->identification[1] != 'A'
+	|| header->identification[2] != 'D'
+	|| header->identification[3] != '2')
+		Sys_Error ("Wad file %s doesn't have WAD2 id\n",filename);
+		
+	wad_numlumps = LittleLong(header->numlumps);
+	infotableofs = LittleLong(header->infotableofs);
+	wad_lumps = (lumpinfo_t *)(wad_base + infotableofs);
+	
+	for (i=0, lump_p = wad_lumps ; i<wad_numlumps ; i++,lump_p++)
+	{
+		lump_p->filepos = LittleLong(lump_p->filepos);
+		lump_p->size = LittleLong(lump_p->size);
+		W_CleanupName (lump_p->name, lump_p->name);
+		if (lump_p->type == TYP_QPIC)
+			SwapPic ( (qpic_t *)(wad_base + lump_p->filepos));
+	}
+}
+
+
+/*
+=============
+W_GetLumpinfo
+=============
+*/
+lumpinfo_t	*W_GetLumpinfo (char *name)
+{
+	int		i;
+	lumpinfo_t	*lump_p;
+	char	clean[16];
+	
+	W_CleanupName (name, clean);
+	
+	for (lump_p=wad_lumps, i=0 ; i<wad_numlumps ; i++,lump_p++)
+	{
+		if (!strcmp(clean, lump_p->name))
+			return lump_p;
+	}
+	
+	Sys_Error ("W_GetLumpinfo: %s not found", name);
+	return NULL;
+}
+
+void *W_GetLumpName (char *name)
+{
+	lumpinfo_t	*lump;
+	
+	lump = W_GetLumpinfo (name);
+	
+	return (void *)(wad_base + lump->filepos);
+}
+
+void *W_GetLumpNum (int num)
+{
+	lumpinfo_t	*lump;
+	
+	if (num < 0 || num > wad_numlumps)
+		Sys_Error ("W_GetLumpNum: bad number: %i", num);
+		
+	lump = wad_lumps + num;
+	
+	return (void *)(wad_base + lump->filepos);
+}
+
+/*
+=============================================================================
+
+automatic byte swapping
+
+=============================================================================
+*/
+
+void SwapPic (qpic_t *pic)
+{
+	pic->width = LittleLong(pic->width);
+	pic->height = LittleLong(pic->height);	
+}
--- /dev/null
+++ b/QW/client/wad.h
@@ -1,0 +1,75 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// wad.h
+
+//===============
+//   TYPES
+//===============
+
+#define	CMP_NONE		0
+#define	CMP_LZSS		1
+
+#define	TYP_NONE		0
+#define	TYP_LABEL		1
+
+#define	TYP_LUMPY		64				// 64 + grab command number
+#define	TYP_PALETTE		64
+#define	TYP_QTEX		65
+#define	TYP_QPIC		66
+#define	TYP_SOUND		67
+#define	TYP_MIPTEX		68
+
+typedef struct
+{
+	int			width, height;
+	byte		data[4];			// variably sized
+} qpic_t;
+
+
+
+typedef struct
+{
+	char		identification[4];		// should be WAD2 or 2DAW
+	int			numlumps;
+	int			infotableofs;
+} wadinfo_t;
+
+typedef struct
+{
+	int			filepos;
+	int			disksize;
+	int			size;					// uncompressed
+	char		type;
+	char		compression;
+	char		pad1, pad2;
+	char		name[16];				// must be null terminated
+} lumpinfo_t;
+
+extern	int			wad_numlumps;
+extern	lumpinfo_t	*wad_lumps;
+extern	byte		*wad_base;
+
+void	W_LoadWadFile (char *filename);
+void	W_CleanupName (char *in, char *out);
+lumpinfo_t	*W_GetLumpinfo (char *name);
+void	*W_GetLumpName (char *name);
+void	*W_GetLumpNum (int num);
+
+void SwapPic (qpic_t *pic);
binary files /dev/null b/QW/client/winquake.aps differ
--- /dev/null
+++ b/QW/client/winquake.h
@@ -1,0 +1,114 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// winquake.h: Win32-specific Quake header file
+
+#ifdef _WIN32 
+#pragma warning( disable : 4229 )  // mgraph gets this
+
+#include <windows.h>
+#define WM_MOUSEWHEEL                   0x020A
+
+#ifndef SERVERONLY
+#include <ddraw.h>
+#include <dsound.h>
+#ifndef GLQUAKE
+#include <mgraph.h>
+#endif
+#endif
+
+extern	HINSTANCE	global_hInstance;
+extern	int			global_nCmdShow;
+
+#ifndef SERVERONLY
+
+extern LPDIRECTDRAW		lpDD;
+extern qboolean			DDActive;
+extern LPDIRECTDRAWSURFACE	lpPrimary;
+extern LPDIRECTDRAWSURFACE	lpFrontBuffer;
+extern LPDIRECTDRAWSURFACE	lpBackBuffer;
+extern LPDIRECTDRAWPALETTE	lpDDPal;
+extern LPDIRECTSOUND pDS;
+extern LPDIRECTSOUNDBUFFER pDSBuf;
+
+extern DWORD gSndBufSize;
+//#define SNDBUFSIZE 65536
+
+void	VID_LockBuffer (void);
+void	VID_UnlockBuffer (void);
+
+#endif
+
+typedef enum {MS_WINDOWED, MS_FULLSCREEN, MS_FULLDIB, MS_UNINIT} modestate_t;
+
+extern modestate_t	modestate;
+
+extern HWND			mainwindow;
+extern qboolean		ActiveApp, Minimized;
+
+extern qboolean	WinNT;
+
+int VID_ForceUnlockedAndReturnState (void);
+void VID_ForceLockState (int lk);
+
+void IN_ShowMouse (void);
+void IN_DeactivateMouse (void);
+void IN_HideMouse (void);
+void IN_ActivateMouse (void);
+void IN_RestoreOriginalMouseState (void);
+void IN_SetQuakeMouseState (void);
+void IN_MouseEvent (int mstate);
+
+extern qboolean	winsock_lib_initialized;
+
+extern int		window_center_x, window_center_y;
+extern RECT		window_rect;
+
+extern qboolean	mouseinitialized;
+extern HWND		hwnd_dialog;
+
+extern HANDLE	hinput, houtput;
+
+void IN_UpdateClipCursor (void);
+void CenterWindow(HWND hWndCenter, int width, int height, BOOL lefttopjustify);
+
+void S_BlockSound (void);
+void S_UnblockSound (void);
+
+void VID_SetDefaultMode (void);
+
+int (PASCAL FAR *pWSAStartup)(WORD wVersionRequired, LPWSADATA lpWSAData);
+int (PASCAL FAR *pWSACleanup)(void);
+int (PASCAL FAR *pWSAGetLastError)(void);
+SOCKET (PASCAL FAR *psocket)(int af, int type, int protocol);
+int (PASCAL FAR *pioctlsocket)(SOCKET s, long cmd, u_long FAR *argp);
+int (PASCAL FAR *psetsockopt)(SOCKET s, int level, int optname,
+							  const char FAR * optval, int optlen);
+int (PASCAL FAR *precvfrom)(SOCKET s, char FAR * buf, int len, int flags,
+							struct sockaddr FAR *from, int FAR * fromlen);
+int (PASCAL FAR *psendto)(SOCKET s, const char FAR * buf, int len, int flags,
+						  const struct sockaddr FAR *to, int tolen);
+int (PASCAL FAR *pclosesocket)(SOCKET s);
+int (PASCAL FAR *pgethostname)(char FAR * name, int namelen);
+struct hostent FAR * (PASCAL FAR *pgethostbyname)(const char FAR * name);
+struct hostent FAR * (PASCAL FAR *pgethostbyaddr)(const char FAR * addr,
+												  int len, int type);
+int (PASCAL FAR *pgetsockname)(SOCKET s, struct sockaddr FAR *name,
+							   int FAR * namelen);
+#endif
--- /dev/null
+++ b/QW/client/winquake.rc
@@ -1,0 +1,137 @@
+//Microsoft Developer Studio generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE DISCARDABLE 
+BEGIN
+    "resource.h\0"
+END
+
+2 TEXTINCLUDE DISCARDABLE 
+BEGIN
+    "#include ""afxres.h""\r\n"
+    "\0"
+END
+
+3 TEXTINCLUDE DISCARDABLE 
+BEGIN
+    "\r\n"
+    "\0"
+END
+
+#endif    // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDI_ICON2               ICON    DISCARDABLE     "qwcl2.ico"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_DIALOG1 DIALOGEX 0, 0, 167, 27
+STYLE DS_MODALFRAME | DS_SETFOREGROUND | DS_3DLOOK | DS_CENTER | WS_POPUP | 
+    WS_VISIBLE
+EXSTYLE WS_EX_TOOLWINDOW | WS_EX_CLIENTEDGE
+FONT 16, "Times New Roman", 0, 0, 0x1
+BEGIN
+    CONTROL         112,IDC_STATIC,"Static",SS_BITMAP | SS_REALSIZEIMAGE,0,0,
+                    167,28
+END
+
+IDD_PROGRESS DIALOGEX 0, 0, 333, 75
+STYLE DS_MODALFRAME | DS_SETFOREGROUND | DS_3DLOOK | DS_CENTER | WS_POPUP | 
+    WS_VISIBLE
+EXSTYLE WS_EX_TOOLWINDOW | WS_EX_CLIENTEDGE
+FONT 8, "MS Sans Serif", 0, 0, 0x1
+BEGIN
+    LTEXT           "Creating 15 bit inverse palette.  This is only done once, so just be patient for the next 30-60 seconds.",
+                    IDC_STATIC,7,51,319,10
+    CONTROL         112,IDC_STATIC,"Static",SS_BITMAP | SS_REALSIZEIMAGE,0,0,
+                    333,49
+    CONTROL         "Progress1",IDC_PROGRESS,"msctls_progress32",0x0,7,61,
+                    319,11
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Bitmap
+//
+
+IDB_QWBITMAP            BITMAP  DISCARDABLE     "quakeworld.bmp"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO DISCARDABLE 
+BEGIN
+    IDD_PROGRESS, DIALOG
+    BEGIN
+        VERTGUIDE, 7
+        VERTGUIDE, 326
+    END
+END
+#endif    // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// String Table
+//
+
+STRINGTABLE DISCARDABLE 
+BEGIN
+    IDS_STRING1             "WinQuake"
+END
+
+#endif    // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif    // not APSTUDIO_INVOKED
+
--- /dev/null
+++ b/QW/client/zone.c
@@ -1,0 +1,940 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// Z_zone.c
+
+#include "quakedef.h"
+
+#define	DYNAMIC_SIZE	0x20000
+
+#define	ZONEID	0x1d4a11
+#define MINFRAGMENT	64
+
+typedef struct memblock_s
+{
+	int		size;           // including the header and possibly tiny fragments
+	int     tag;            // a tag of 0 is a free block
+	int     id;        		// should be ZONEID
+	struct memblock_s       *next, *prev;
+	int		pad;			// pad to 64 bit boundary
+} memblock_t;
+
+typedef struct
+{
+	int		size;		// total bytes malloced, including header
+	memblock_t	blocklist;		// start / end cap for linked list
+	memblock_t	*rover;
+} memzone_t;
+
+void Cache_FreeLow (int new_low_hunk);
+void Cache_FreeHigh (int new_high_hunk);
+
+
+/*
+==============================================================================
+
+						ZONE MEMORY ALLOCATION
+
+There is never any space between memblocks, and there will never be two
+contiguous free memblocks.
+
+The rover can be left pointing at a non-empty block
+
+The zone calls are pretty much only used for small strings and structures,
+all big things are allocated on the hunk.
+==============================================================================
+*/
+
+memzone_t	*mainzone;
+
+void Z_ClearZone (memzone_t *zone, int size);
+
+
+/*
+========================
+Z_ClearZone
+========================
+*/
+void Z_ClearZone (memzone_t *zone, int size)
+{
+	memblock_t	*block;
+	
+// set the entire zone to one free block
+
+	zone->blocklist.next = zone->blocklist.prev = block =
+		(memblock_t *)( (byte *)zone + sizeof(memzone_t) );
+	zone->blocklist.tag = 1;	// in use block
+	zone->blocklist.id = 0;
+	zone->blocklist.size = 0;
+	zone->rover = block;
+	
+	block->prev = block->next = &zone->blocklist;
+	block->tag = 0;			// free block
+	block->id = ZONEID;
+	block->size = size - sizeof(memzone_t);
+}
+
+
+/*
+========================
+Z_Free
+========================
+*/
+void Z_Free (void *ptr)
+{
+	memblock_t	*block, *other;
+	
+	if (!ptr)
+		Sys_Error ("Z_Free: NULL pointer");
+
+	block = (memblock_t *) ( (byte *)ptr - sizeof(memblock_t));
+	if (block->id != ZONEID)
+		Sys_Error ("Z_Free: freed a pointer without ZONEID");
+	if (block->tag == 0)
+		Sys_Error ("Z_Free: freed a freed pointer");
+
+	block->tag = 0;		// mark as free
+	
+	other = block->prev;
+	if (!other->tag)
+	{	// merge with previous free block
+		other->size += block->size;
+		other->next = block->next;
+		other->next->prev = other;
+		if (block == mainzone->rover)
+			mainzone->rover = other;
+		block = other;
+	}
+	
+	other = block->next;
+	if (!other->tag)
+	{	// merge the next free block onto the end
+		block->size += other->size;
+		block->next = other->next;
+		block->next->prev = block;
+		if (other == mainzone->rover)
+			mainzone->rover = block;
+	}
+}
+
+
+/*
+========================
+Z_Malloc
+========================
+*/
+void *Z_Malloc (int size)
+{
+	void	*buf;
+	
+Z_CheckHeap ();	// DEBUG
+	buf = Z_TagMalloc (size, 1);
+	if (!buf)
+		Sys_Error ("Z_Malloc: failed on allocation of %i bytes",size);
+	Q_memset (buf, 0, size);
+
+	return buf;
+}
+
+void *Z_TagMalloc (int size, int tag)
+{
+	int		extra;
+	memblock_t	*start, *rover, *new, *base;
+
+	if (!tag)
+		Sys_Error ("Z_TagMalloc: tried to use a 0 tag");
+
+//
+// scan through the block list looking for the first free block
+// of sufficient size
+//
+	size += sizeof(memblock_t);	// account for size of block header
+	size += 4;					// space for memory trash tester
+	size = (size + 7) & ~7;		// align to 8-byte boundary
+	
+	base = rover = mainzone->rover;
+	start = base->prev;
+	
+	do
+	{
+		if (rover == start)	// scaned all the way around the list
+			return NULL;
+		if (rover->tag)
+			base = rover = rover->next;
+		else
+			rover = rover->next;
+	} while (base->tag || base->size < size);
+	
+//
+// found a block big enough
+//
+	extra = base->size - size;
+	if (extra >  MINFRAGMENT)
+	{	// there will be a free fragment after the allocated block
+		new = (memblock_t *) ((byte *)base + size );
+		new->size = extra;
+		new->tag = 0;			// free block
+		new->prev = base;
+		new->id = ZONEID;
+		new->next = base->next;
+		new->next->prev = new;
+		base->next = new;
+		base->size = size;
+	}
+	
+	base->tag = tag;				// no longer a free block
+	
+	mainzone->rover = base->next;	// next allocation will start looking here
+	
+	base->id = ZONEID;
+
+// marker for memory trash testing
+	*(int *)((byte *)base + base->size - 4) = ZONEID;
+
+	return (void *) ((byte *)base + sizeof(memblock_t));
+}
+
+
+/*
+========================
+Z_Print
+========================
+*/
+void Z_Print (memzone_t *zone)
+{
+	memblock_t	*block;
+	
+	Con_Printf ("zone size: %i  location: %p\n",mainzone->size,mainzone);
+	
+	for (block = zone->blocklist.next ; ; block = block->next)
+	{
+		Con_Printf ("block:%p    size:%7i    tag:%3i\n",
+			block, block->size, block->tag);
+		
+		if (block->next == &zone->blocklist)
+			break;			// all blocks have been hit	
+		if ( (byte *)block + block->size != (byte *)block->next)
+			Con_Printf ("ERROR: block size does not touch the next block\n");
+		if ( block->next->prev != block)
+			Con_Printf ("ERROR: next block doesn't have proper back link\n");
+		if (!block->tag && !block->next->tag)
+			Con_Printf ("ERROR: two consecutive free blocks\n");
+	}
+}
+
+
+/*
+========================
+Z_CheckHeap
+========================
+*/
+void Z_CheckHeap (void)
+{
+	memblock_t	*block;
+	
+	for (block = mainzone->blocklist.next ; ; block = block->next)
+	{
+		if (block->next == &mainzone->blocklist)
+			break;			// all blocks have been hit	
+		if ( (byte *)block + block->size != (byte *)block->next)
+			Sys_Error ("Z_CheckHeap: block size does not touch the next block\n");
+		if ( block->next->prev != block)
+			Sys_Error ("Z_CheckHeap: next block doesn't have proper back link\n");
+		if (!block->tag && !block->next->tag)
+			Sys_Error ("Z_CheckHeap: two consecutive free blocks\n");
+	}
+}
+
+//============================================================================
+
+#define	HUNK_SENTINAL	0x1df001ed
+
+typedef struct
+{
+	int		sentinal;
+	int		size;		// including sizeof(hunk_t), -1 = not allocated
+	char	name[8];
+} hunk_t;
+
+byte	*hunk_base;
+int		hunk_size;
+
+int		hunk_low_used;
+int		hunk_high_used;
+
+qboolean	hunk_tempactive;
+int		hunk_tempmark;
+
+void R_FreeTextures (void);
+
+/*
+==============
+Hunk_Check
+
+Run consistancy and sentinal trahing checks
+==============
+*/
+void Hunk_Check (void)
+{
+	hunk_t	*h;
+	
+	for (h = (hunk_t *)hunk_base ; (byte *)h != hunk_base + hunk_low_used ; )
+	{
+		if (h->sentinal != HUNK_SENTINAL)
+			Sys_Error ("Hunk_Check: trahsed sentinal");
+		if (h->size < 16 || h->size + (byte *)h - hunk_base > hunk_size)
+			Sys_Error ("Hunk_Check: bad size");
+		h = (hunk_t *)((byte *)h+h->size);
+	}
+}
+
+/*
+==============
+Hunk_Print
+
+If "all" is specified, every single allocation is printed.
+Otherwise, allocations with the same name will be totaled up before printing.
+==============
+*/
+void Hunk_Print (qboolean all)
+{
+	hunk_t	*h, *next, *endlow, *starthigh, *endhigh;
+	int		count, sum;
+	int		totalblocks;
+	char	name[9];
+
+	name[8] = 0;
+	count = 0;
+	sum = 0;
+	totalblocks = 0;
+	
+	h = (hunk_t *)hunk_base;
+	endlow = (hunk_t *)(hunk_base + hunk_low_used);
+	starthigh = (hunk_t *)(hunk_base + hunk_size - hunk_high_used);
+	endhigh = (hunk_t *)(hunk_base + hunk_size);
+
+	Con_Printf ("          :%8i total hunk size\n", hunk_size);
+	Con_Printf ("-------------------------\n");
+
+	while (1)
+	{
+	//
+	// skip to the high hunk if done with low hunk
+	//
+		if ( h == endlow )
+		{
+			Con_Printf ("-------------------------\n");
+			Con_Printf ("          :%8i REMAINING\n", hunk_size - hunk_low_used - hunk_high_used);
+			Con_Printf ("-------------------------\n");
+			h = starthigh;
+		}
+		
+	//
+	// if totally done, break
+	//
+		if ( h == endhigh )
+			break;
+
+	//
+	// run consistancy checks
+	//
+		if (h->sentinal != HUNK_SENTINAL)
+			Sys_Error ("Hunk_Check: trahsed sentinal");
+		if (h->size < 16 || h->size + (byte *)h - hunk_base > hunk_size)
+			Sys_Error ("Hunk_Check: bad size");
+			
+		next = (hunk_t *)((byte *)h+h->size);
+		count++;
+		totalblocks++;
+		sum += h->size;
+
+	//
+	// print the single block
+	//
+		memcpy (name, h->name, 8);
+		if (all)
+			Con_Printf ("%8p :%8i %8s\n",h, h->size, name);
+			
+	//
+	// print the total
+	//
+		if (next == endlow || next == endhigh || 
+		strncmp (h->name, next->name, 8) )
+		{
+			if (!all)
+				Con_Printf ("          :%8i %8s (TOTAL)\n",sum, name);
+			count = 0;
+			sum = 0;
+		}
+
+		h = next;
+	}
+
+	Con_Printf ("-------------------------\n");
+	Con_Printf ("%8i total blocks\n", totalblocks);
+	
+}
+
+/*
+===================
+Hunk_AllocName
+===================
+*/
+void *Hunk_AllocName (int size, char *name)
+{
+	hunk_t	*h;
+	
+#ifdef PARANOID
+	Hunk_Check ();
+#endif
+
+	if (size < 0)
+		Sys_Error ("Hunk_Alloc: bad size: %i", size);
+		
+	size = sizeof(hunk_t) + ((size+15)&~15);
+	
+	if (hunk_size - hunk_low_used - hunk_high_used < size)
+//		Sys_Error ("Hunk_Alloc: failed on %i bytes",size);
+#ifdef _WIN32
+	  	Sys_Error ("Not enough RAM allocated.  Try starting using \"-heapsize 16000\" on the QuakeWorld command line.");
+#else
+	  	Sys_Error ("Not enough RAM allocated.  Try starting using \"-mem 16\" on the QuakeWorld command line.");
+#endif
+	
+	h = (hunk_t *)(hunk_base + hunk_low_used);
+	hunk_low_used += size;
+
+	Cache_FreeLow (hunk_low_used);
+
+	memset (h, 0, size);
+	
+	h->size = size;
+	h->sentinal = HUNK_SENTINAL;
+	Q_strncpy (h->name, name, 8);
+	
+	return (void *)(h+1);
+}
+
+/*
+===================
+Hunk_Alloc
+===================
+*/
+void *Hunk_Alloc (int size)
+{
+	return Hunk_AllocName (size, "unknown");
+}
+
+int	Hunk_LowMark (void)
+{
+	return hunk_low_used;
+}
+
+void Hunk_FreeToLowMark (int mark)
+{
+	if (mark < 0 || mark > hunk_low_used)
+		Sys_Error ("Hunk_FreeToLowMark: bad mark %i", mark);
+	memset (hunk_base + mark, 0, hunk_low_used - mark);
+	hunk_low_used = mark;
+}
+
+int	Hunk_HighMark (void)
+{
+	if (hunk_tempactive)
+	{
+		hunk_tempactive = false;
+		Hunk_FreeToHighMark (hunk_tempmark);
+	}
+
+	return hunk_high_used;
+}
+
+void Hunk_FreeToHighMark (int mark)
+{
+	if (hunk_tempactive)
+	{
+		hunk_tempactive = false;
+		Hunk_FreeToHighMark (hunk_tempmark);
+	}
+	if (mark < 0 || mark > hunk_high_used)
+		Sys_Error ("Hunk_FreeToHighMark: bad mark %i", mark);
+	memset (hunk_base + hunk_size - hunk_high_used, 0, hunk_high_used - mark);
+	hunk_high_used = mark;
+}
+
+
+/*
+===================
+Hunk_HighAllocName
+===================
+*/
+void *Hunk_HighAllocName (int size, char *name)
+{
+	hunk_t	*h;
+
+	if (size < 0)
+		Sys_Error ("Hunk_HighAllocName: bad size: %i", size);
+
+	if (hunk_tempactive)
+	{
+		Hunk_FreeToHighMark (hunk_tempmark);
+		hunk_tempactive = false;
+	}
+
+#ifdef PARANOID
+	Hunk_Check ();
+#endif
+
+	size = sizeof(hunk_t) + ((size+15)&~15);
+
+	if (hunk_size - hunk_low_used - hunk_high_used < size)
+	{
+		Con_Printf ("Hunk_HighAlloc: failed on %i bytes\n",size);
+		return NULL;
+	}
+
+	hunk_high_used += size;
+	Cache_FreeHigh (hunk_high_used);
+
+	h = (hunk_t *)(hunk_base + hunk_size - hunk_high_used);
+
+	memset (h, 0, size);
+	h->size = size;
+	h->sentinal = HUNK_SENTINAL;
+	Q_strncpy (h->name, name, 8);
+
+	return (void *)(h+1);
+}
+
+
+/*
+=================
+Hunk_TempAlloc
+
+Return space from the top of the hunk
+=================
+*/
+void *Hunk_TempAlloc (int size)
+{
+	void	*buf;
+
+	size = (size+15)&~15;
+	
+	if (hunk_tempactive)
+	{
+		Hunk_FreeToHighMark (hunk_tempmark);
+		hunk_tempactive = false;
+	}
+	
+	hunk_tempmark = Hunk_HighMark ();
+
+	buf = Hunk_HighAllocName (size, "temp");
+
+	hunk_tempactive = true;
+
+	return buf;
+}
+
+/*
+===============================================================================
+
+CACHE MEMORY
+
+===============================================================================
+*/
+
+typedef struct cache_system_s
+{
+	int						size;		// including this header
+	cache_user_t			*user;
+	char					name[16];
+	struct cache_system_s	*prev, *next;
+	struct cache_system_s	*lru_prev, *lru_next;	// for LRU flushing	
+} cache_system_t;
+
+cache_system_t *Cache_TryAlloc (int size, qboolean nobottom);
+
+cache_system_t	cache_head;
+
+/*
+===========
+Cache_Move
+===========
+*/
+void Cache_Move ( cache_system_t *c)
+{
+	cache_system_t		*new;
+
+// we are clearing up space at the bottom, so only allocate it late
+	new = Cache_TryAlloc (c->size, true);
+	if (new)
+	{
+//		Con_Printf ("cache_move ok\n");
+
+		Q_memcpy ( new+1, c+1, c->size - sizeof(cache_system_t) );
+		new->user = c->user;
+		Q_memcpy (new->name, c->name, sizeof(new->name));
+		Cache_Free (c->user);
+		new->user->data = (void *)(new+1);
+	}
+	else
+	{
+//		Con_Printf ("cache_move failed\n");
+
+		Cache_Free (c->user);		// tough luck...
+	}
+}
+
+/*
+============
+Cache_FreeLow
+
+Throw things out until the hunk can be expanded to the given point
+============
+*/
+void Cache_FreeLow (int new_low_hunk)
+{
+	cache_system_t	*c;
+	
+	while (1)
+	{
+		c = cache_head.next;
+		if (c == &cache_head)
+			return;		// nothing in cache at all
+		if ((byte *)c >= hunk_base + new_low_hunk)
+			return;		// there is space to grow the hunk
+		Cache_Move ( c );	// reclaim the space
+	}
+}
+
+/*
+============
+Cache_FreeHigh
+
+Throw things out until the hunk can be expanded to the given point
+============
+*/
+void Cache_FreeHigh (int new_high_hunk)
+{
+	cache_system_t	*c, *prev;
+	
+	prev = NULL;
+	while (1)
+	{
+		c = cache_head.prev;
+		if (c == &cache_head)
+			return;		// nothing in cache at all
+		if ( (byte *)c + c->size <= hunk_base + hunk_size - new_high_hunk)
+			return;		// there is space to grow the hunk
+		if (c == prev)
+			Cache_Free (c->user);	// didn't move out of the way
+		else
+		{
+			Cache_Move (c);	// try to move it
+			prev = c;
+		}
+	}
+}
+
+void Cache_UnlinkLRU (cache_system_t *cs)
+{
+	if (!cs->lru_next || !cs->lru_prev)
+		Sys_Error ("Cache_UnlinkLRU: NULL link");
+
+	cs->lru_next->lru_prev = cs->lru_prev;
+	cs->lru_prev->lru_next = cs->lru_next;
+	
+	cs->lru_prev = cs->lru_next = NULL;
+}
+
+void Cache_MakeLRU (cache_system_t *cs)
+{
+	if (cs->lru_next || cs->lru_prev)
+		Sys_Error ("Cache_MakeLRU: active link");
+
+	cache_head.lru_next->lru_prev = cs;
+	cs->lru_next = cache_head.lru_next;
+	cs->lru_prev = &cache_head;
+	cache_head.lru_next = cs;
+}
+
+/*
+============
+Cache_TryAlloc
+
+Looks for a free block of memory between the high and low hunk marks
+Size should already include the header and padding
+============
+*/
+cache_system_t *Cache_TryAlloc (int size, qboolean nobottom)
+{
+	cache_system_t	*cs, *new;
+	
+// is the cache completely empty?
+
+	if (!nobottom && cache_head.prev == &cache_head)
+	{
+		if (hunk_size - hunk_high_used - hunk_low_used < size)
+			Sys_Error ("Cache_TryAlloc: %i is greater then free hunk", size);
+
+		new = (cache_system_t *) (hunk_base + hunk_low_used);
+		memset (new, 0, sizeof(*new));
+		new->size = size;
+
+		cache_head.prev = cache_head.next = new;
+		new->prev = new->next = &cache_head;
+		
+		Cache_MakeLRU (new);
+		return new;
+	}
+	
+// search from the bottom up for space
+
+	new = (cache_system_t *) (hunk_base + hunk_low_used);
+	cs = cache_head.next;
+	
+	do
+	{
+		if (!nobottom || cs != cache_head.next)
+		{
+			if ( (byte *)cs - (byte *)new >= size)
+			{	// found space
+				memset (new, 0, sizeof(*new));
+				new->size = size;
+				
+				new->next = cs;
+				new->prev = cs->prev;
+				cs->prev->next = new;
+				cs->prev = new;
+				
+				Cache_MakeLRU (new);
+	
+				return new;
+			}
+		}
+
+	// continue looking		
+		new = (cache_system_t *)((byte *)cs + cs->size);
+		cs = cs->next;
+
+	} while (cs != &cache_head);
+	
+// try to allocate one at the very end
+	if ( hunk_base + hunk_size - hunk_high_used - (byte *)new >= size)
+	{
+		memset (new, 0, sizeof(*new));
+		new->size = size;
+		
+		new->next = &cache_head;
+		new->prev = cache_head.prev;
+		cache_head.prev->next = new;
+		cache_head.prev = new;
+		
+		Cache_MakeLRU (new);
+
+		return new;
+	}
+	
+	return NULL;		// couldn't allocate
+}
+
+/*
+============
+Cache_Flush
+
+Throw everything out, so new data will be demand cached
+============
+*/
+void Cache_Flush (void)
+{
+	while (cache_head.next != &cache_head)
+		Cache_Free ( cache_head.next->user );	// reclaim the space
+}
+
+
+/*
+============
+Cache_Print
+
+============
+*/
+void Cache_Print (void)
+{
+	cache_system_t	*cd;
+
+	for (cd = cache_head.next ; cd != &cache_head ; cd = cd->next)
+	{
+		Con_Printf ("%8i : %s\n", cd->size, cd->name);
+	}
+}
+
+/*
+============
+Cache_Report
+
+============
+*/
+void Cache_Report (void)
+{
+	Con_DPrintf ("%4.1f megabyte data cache\n", (hunk_size - hunk_high_used - hunk_low_used) / (float)(1024*1024) );
+}
+
+/*
+============
+Cache_Compact
+
+============
+*/
+void Cache_Compact (void)
+{
+}
+
+/*
+============
+Cache_Init
+
+============
+*/
+void Cache_Init (void)
+{
+	cache_head.next = cache_head.prev = &cache_head;
+	cache_head.lru_next = cache_head.lru_prev = &cache_head;
+
+	Cmd_AddCommand ("flush", Cache_Flush);
+}
+
+/*
+==============
+Cache_Free
+
+Frees the memory and removes it from the LRU list
+==============
+*/
+void Cache_Free (cache_user_t *c)
+{
+	cache_system_t	*cs;
+
+	if (!c->data)
+		Sys_Error ("Cache_Free: not allocated");
+
+	cs = ((cache_system_t *)c->data) - 1;
+
+	cs->prev->next = cs->next;
+	cs->next->prev = cs->prev;
+	cs->next = cs->prev = NULL;
+
+	c->data = NULL;
+
+	Cache_UnlinkLRU (cs);
+}
+
+
+
+/*
+==============
+Cache_Check
+==============
+*/
+void *Cache_Check (cache_user_t *c)
+{
+	cache_system_t	*cs;
+
+	if (!c->data)
+		return NULL;
+
+	cs = ((cache_system_t *)c->data) - 1;
+
+// move to head of LRU
+	Cache_UnlinkLRU (cs);
+	Cache_MakeLRU (cs);
+	
+	return c->data;
+}
+
+
+/*
+==============
+Cache_Alloc
+==============
+*/
+void *Cache_Alloc (cache_user_t *c, int size, char *name)
+{
+	cache_system_t	*cs;
+
+	if (c->data)
+		Sys_Error ("Cache_Alloc: allready allocated");
+	
+	if (size <= 0)
+		Sys_Error ("Cache_Alloc: size %i", size);
+
+	size = (size + sizeof(cache_system_t) + 15) & ~15;
+
+// find memory for it	
+	while (1)
+	{
+		cs = Cache_TryAlloc (size, false);
+		if (cs)
+		{
+			strncpy (cs->name, name, sizeof(cs->name)-1);
+			c->data = (void *)(cs+1);
+			cs->user = c;
+			break;
+		}
+	
+	// free the least recently used cahedat
+		if (cache_head.lru_prev == &cache_head)
+			Sys_Error ("Cache_Alloc: out of memory");
+													// not enough memory at all
+		Cache_Free ( cache_head.lru_prev->user );
+	} 
+	
+	return Cache_Check (c);
+}
+
+//============================================================================
+
+
+/*
+========================
+Memory_Init
+========================
+*/
+void Memory_Init (void *buf, int size)
+{
+	int p;
+	int zonesize = DYNAMIC_SIZE;
+
+	hunk_base = buf;
+	hunk_size = size;
+	hunk_low_used = 0;
+	hunk_high_used = 0;
+	
+	Cache_Init ();
+	p = COM_CheckParm ("-zone");
+	if (p)
+	{
+		if (p < com_argc-1)
+			zonesize = Q_atoi (com_argv[p+1]) * 1024;
+		else
+			Sys_Error ("Memory_Init: you must specify a size in KB after -zone");
+	}
+	mainzone = Hunk_AllocName ( zonesize, "zone" );
+	Z_ClearZone (mainzone, zonesize);
+}
+
--- /dev/null
+++ b/QW/client/zone.h
@@ -1,0 +1,131 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+/*
+ memory allocation
+
+
+H_??? The hunk manages the entire memory block given to quake.  It must be
+contiguous.  Memory can be allocated from either the low or high end in a
+stack fashion.  The only way memory is released is by resetting one of the
+pointers.
+
+Hunk allocations should be given a name, so the Hunk_Print () function
+can display usage.
+
+Hunk allocations are guaranteed to be 16 byte aligned.
+
+The video buffers are allocated high to avoid leaving a hole underneath
+server allocations when changing to a higher video mode.
+
+
+Z_??? Zone memory functions used for small, dynamic allocations like text
+strings from command input.  There is only about 48K for it, allocated at
+the very bottom of the hunk.
+
+Cache_??? Cache memory is for objects that can be dynamically loaded and
+can usefully stay persistant between levels.  The size of the cache
+fluctuates from level to level.
+
+To allocate a cachable object
+
+
+Temp_??? Temp memory is used for file loading and surface caching.  The size
+of the cache memory is adjusted so that there is a minimum of 512k remaining
+for temp memory.
+
+
+------ Top of Memory -------
+
+high hunk allocations
+
+<--- high hunk reset point held by vid
+
+video buffer
+
+z buffer
+
+surface cache
+
+<--- high hunk used
+
+cachable memory
+
+<--- low hunk used
+
+client and server low hunk allocations
+
+<-- low hunk reset point held by host
+
+startup hunk allocations
+
+Zone block
+
+----- Bottom of Memory -----
+
+
+
+*/
+
+void Memory_Init (void *buf, int size);
+
+void Z_Free (void *ptr);
+void *Z_Malloc (int size);			// returns 0 filled memory
+void *Z_TagMalloc (int size, int tag);
+
+void Z_DumpHeap (void);
+void Z_CheckHeap (void);
+int Z_FreeMemory (void);
+
+void *Hunk_Alloc (int size);		// returns 0 filled memory
+void *Hunk_AllocName (int size, char *name);
+
+void *Hunk_HighAllocName (int size, char *name);
+
+int	Hunk_LowMark (void);
+void Hunk_FreeToLowMark (int mark);
+
+int	Hunk_HighMark (void);
+void Hunk_FreeToHighMark (int mark);
+
+void *Hunk_TempAlloc (int size);
+
+void Hunk_Check (void);
+
+typedef struct cache_user_s
+{
+	void	*data;
+} cache_user_t;
+
+void Cache_Flush (void);
+
+void *Cache_Check (cache_user_t *c);
+// returns the cached data, and moves to the head of the LRU list
+// if present, otherwise returns NULL
+
+void Cache_Free (cache_user_t *c);
+
+void *Cache_Alloc (cache_user_t *c, int size, char *name);
+// Returns NULL if all purgable data was tossed and there still
+// wasn't enough room.
+
+void Cache_Report (void);
+
+
+
--- /dev/null
+++ b/QW/cmds.txt
@@ -1,0 +1,436 @@
+Client
+------
+
+Commands:
+
+cd
++moveup -moveup
++movedown -movedown
++left -left
++right -right
++forward -forward
++back -back
++lookup -lookup
++lookdown -lookdown
++strafe -strafe
++moveleft -moveleft
++moveright -moveright
++speed -speed
++attack -attack
++use -use
++jump -jump
++klook -klook
++mlook -mlook
+impulse
+version", CL_Version_f
+changing", CL_Changing_f
+disconnect", CL_Disconnect_f
+record", CL_Record_f
+stop", CL_Stop_f
+playdemo", CL_PlayDemo_f
+timedemo", CL_TimeDemo_f
+skins", Skin_Skins_f
+allskins", Skin_AllSkins_f
+quit", CL_Quit_f
+connect", CL_Connect_f
+reconnect", CL_Reconnect_f
+rcon", CL_Rcon_f
+packet", CL_Packet_f
+user", CL_User_f
+users", CL_Users_f
+setinfo", CL_SetInfo_f
+fullinfo", CL_FullInfo_f
+fullserverinfo", CL_FullServerinfo_f
+color", CL_Color_f
+download", CL_Download_f
+kill", NULL
+say", NULL
+say_team", NULL
+serverinfo", NULL
+windows", CL_Windows_f
+version", CL_Version_f
+changing", CL_Changing_f
+disconnect", CL_Disconnect_f
+record", CL_Record_f
+stop", CL_Stop_f
+playdemo", CL_PlayDemo_f
+timedemo", CL_TimeDemo_f
+skins", Skin_Skins_f
+allskins", Skin_AllSkins_f
+quit", CL_Quit_f
+connect", CL_Connect_f
+reconnect", CL_Reconnect_f
+rcon", CL_Rcon_f
+packet", CL_Packet_f
+user", CL_User_f
+users", CL_Users_f
+setinfo", CL_SetInfo_f
+fullinfo", CL_FullInfo_f
+fullserverinfo", CL_FullServerinfo_f
+color", CL_Color_f
+download", CL_Download_f
+kill", NULL
+say", NULL
+say_team", NULL
+serverinfo", NULL
+windows", CL_Windows_f
+stuffcmds",Cmd_StuffCmds_f
+exec",Cmd_Exec_f
+echo",Cmd_Echo_f
+alias",Cmd_Alias_f
+wait", Cmd_Wait_f
+cmd", Cmd_ForwardToServer_f
+path", COM_Path_f
+path", COM_Path_f
+toggleconsole", Con_ToggleConsole_f
+togglechat", Con_ToggleChat_f
+messagemode", Con_MessageMode_f
+messagemode2", Con_MessageMode2_f
+clear", Con_Clear_f
+gl_texturemode", &Draw_TextureMode_f
+timerefresh", R_TimeRefresh_f	
+envmap", R_Envmap_f	
+pointfile", R_ReadPointFile_f	
+screenshot",SCR_ScreenShot_f
+sizeup",SCR_SizeUp_f
+sizedown",SCR_SizeDown_f
+vid_nummodes", VID_NumModes_f
+vid_describecurrentmode", VID_DescribeCurrentMode_f
+vid_describemode", VID_DescribeMode_f
+vid_describemodes", VID_DescribeModes_f
+force_centerview", Force_CenterView_f
+joyadvancedupdate", Joy_AdvancedUpdate_f
+bind",Key_Bind_f
+unbind",Key_Unbind_f
+unbindall",Key_Unbindall_f
+togglemenu", M_ToggleMenu_f
+menu_main", M_Menu_Main_f
+menu_options", M_Menu_Options_f
+menu_keys", M_Menu_Keys_f
+menu_video", M_Menu_Video_f
+help", M_Menu_Help_f
+menu_quit", M_Menu_Quit_f
+togglemenu", M_ToggleMenu_f
+menu_main", M_Menu_Main_f
+menu_options", M_Menu_Options_f
+menu_keys", M_Menu_Keys_f
+menu_video", M_Menu_Video_f
+help", M_Menu_Help_f
+menu_quit", M_Menu_Quit_f
+timerefresh", R_TimeRefresh_f	
+pointfile", R_ReadPointFile_f	
++showscores", Sbar_ShowScores
+-showscores", Sbar_DontShowScores
++showteamscores", Sbar_ShowTeamScores
+-showteamscores", Sbar_DontShowTeamScores
+screenshot",SCR_ScreenShot_f
+sizeup",SCR_SizeUp_f
+sizedown",SCR_SizeDown_f
+play", S_Play
+playvol", S_PlayVol
+stopsound", S_StopAllSoundsC
+soundlist", S_SoundList
+soundinfo", S_SoundInfo_f
+vid_nummodes", VID_NumModes_f
+vid_describemode", VID_DescribeMode_f
+vid_describemodes", VID_DescribeModes_f
+vid_debug", VID_Debug_f
+force_centerview", Force_CenterView_f
+vid_testmode", VID_TestMode_f
+vid_nummodes", VID_NumModes_f
+vid_describecurrentmode", VID_DescribeCurrentMode_f
+vid_describemode", VID_DescribeMode_f
+vid_describemodes", VID_DescribeModes_f
+vid_forcemode", VID_ForceMode_f
+vid_windowed", VID_Windowed_f
+vid_fullscreen", VID_Fullscreen_f
+vid_minimize", VID_Minimize_f
+vid_testmode", VID_TestMode_f
+vid_nummodes", VID_NumModes_f
+vid_describecurrentmode", VID_DescribeCurrentMode_f
+vid_describemode", VID_DescribeMode_f
+vid_describemodes", VID_DescribeModes_f
+vid_forcemode", VID_ForceMode_f
+vid_windowed", VID_Windowed_f
+vid_fullscreen", VID_Fullscreen_f
+vid_minimize", VID_Minimize_f
+v_cshift", V_cshift_f	
+bf", V_BonusFlash_f
+centerview", V_StartPitchDrift
+flush", Cache_Flush
+
+CVars:
+
+cl_nodelta
+host_speeds
+developer
+cl_warncmd
+cl_upspeed
+cl_forwardspeed
+cl_backspeed
+cl_sidespeed
+cl_movespeedkey
+cl_yawspeed
+cl_pitchspeed
+cl_anglespeedkey
+cl_shownet
+cl_timeout
+cl_hightrack
+lookspring
+lookstrafe
+sensitivity
+m_pitch
+m_yaw
+m_forward
+m_side
+rcon_password
+rcon_address
+entlatency
+cl_predict_players
+baseskin
+noskins
+name
+password
+spectator
+skin
+team
+topcolor
+bottomcolor
+rate
+msg
+noaim
+cl_pushlatency
+cl_nopred
+registered
+con_notifytime
+host_framerate
+d_subdiv16
+d_mipcap
+d_mipscale
+gl_nobind
+gl_max_size
+gl_picmip
+r_norefresh
+r_lightmap
+r_fullbright
+r_drawentities
+r_drawviewmodel
+r_shadows
+r_mirroralpha
+r_wateralpha
+r_dynamic
+r_novis
+r_speeds
+gl_clear
+gl_texsort
+gl_cull
+gl_smoothmodels
+gl_affinemodels
+gl_polyblend
+gl_flashblend
+gl_playermip
+gl_nocolors
+gl_keeptjunctions
+gl_reporttjunctions
+scr_fov
+scr_viewsize
+scr_conspeed
+scr_showram
+scr_showturtle
+scr_showpause
+scr_centertime
+scr_printspeed
+vid_mode
+vid_wait
+vid_nopageflip
+_vid_wait_override
+_vid_default_mode
+_vid_default_mode_win
+vid_config_x
+vid_config_y
+vid_stretch_by_2
+_windowed_mouse
+gl_ztrick
+m_filter
+in_joystick
+joy_name
+joy_advanced
+joy_advaxisx
+joy_advaxisy
+joy_advaxisz
+joy_advaxisr
+joy_advaxisu
+joy_advaxisv
+joy_forwardthreshold
+joy_sidethreshold
+joy_pitchthreshold
+joy_yawthreshold
+joy_forwardsensitivity
+joy_sidesensitivity
+joy_pitchsensitivity
+joy_yawsensitivity
+joy_wwhack1
+joy_wwhack2
+showpackets
+showdrop
+r_draworder
+r_speeds
+r_timegraph
+r_netgraph
+r_zgraph
+r_graphheight
+r_drawflat
+r_ambient
+r_clearcolor
+r_waterwarp
+r_fullbright
+r_drawentities
+r_drawviewmodel
+r_aliasstats
+r_dspeeds
+r_reportsurfout
+r_maxsurfs
+r_numsurfs
+r_reportedgeout
+r_maxedges
+r_numedges
+r_aliastransbase
+r_aliastransadj
+scr_fov
+scr_viewsize
+scr_conspeed
+scr_showram
+scr_showturtle
+scr_showpause
+scr_centertime
+scr_printspeed
+nosound
+volume
+precache
+loadas8bit
+bgmvolume
+bgmbuffer
+ambient_level
+ambient_fade
+snd_noextraupdate
+snd_show
+_snd_mixahead
+vid_mode
+vid_redrawfull
+vid_waitforrefresh
+mouse_button_commands[0]
+mouse_button_commands[1]
+mouse_button_commands[2]
+vid_mode
+vid_wait
+vid_nopageflip
+_vid_wait_override
+_vid_default_mode
+_vid_default_mode_win
+vid_config_x
+vid_config_y
+vid_stretch_by_2
+_windowed_mouse
+vid_fullscreen_mode
+vid_windowed_mode
+block_switch
+vid_window_x
+vid_window_y
+vid_mode
+vid_wait
+vid_nopageflip
+_vid_wait_override
+_vid_default_mode
+_vid_default_mode_win
+vid_config_x
+vid_config_y
+vid_stretch_by_2
+_windowed_mouse
+vid_fullscreen_mode
+vid_windowed_mode
+block_switch
+vid_window_x
+vid_window_y
+v_centermove
+v_centerspeed
+v_iyaw_cycle
+v_iroll_cycle
+v_ipitch_cycle
+v_iyaw_level
+v_iroll_level
+v_ipitch_level
+v_idlescale
+crosshair
+cl_rollspeed
+cl_rollangle
+cl_bob
+cl_bobcycle
+cl_bobup
+v_kicktime
+v_kickroll
+v_kickpitch	
+v_gamma
+
+
+Server
+------
+
+Commands:
+edict", ED_PrintEdict_f
+edicts", ED_PrintEdicts
+edictcount", ED_Count
+profile", PR_Profile_f
+logfile", SV_Logfile_f
+fraglogfile", SV_Fraglogfile_f
+kick", SV_Kick_f
+status", SV_Status_f
+map", SV_Map_f
+setmaster", SV_SetMaster_f
+say", SV_ConSay_f
+heartbeat", SV_Heartbeat_f
+quit", SV_Quit_f
+god", SV_God_f
+give", SV_Give_f
+noclip", SV_Noclip_f
+serverinfo", SV_Serverinfo_f
+user", SV_User_f
+gamedir", SV_Gamedir_f
+sv_gamedir", SV_Gamedir
+addip", SV_AddIP_f
+removeip", SV_RemoveIP_f
+listip", SV_ListIP_f
+writeip", SV_WriteIP_f
+
+Cvars:
+rcon_password
+password
+spectator_password
+sv_mintic
+sv_maxtic
+fraglimit
+timelimit
+teamplay
+samelevel
+maxclients
+maxspectators
+hostname
+deathmatch
+spawn
+developer
+timeout
+zombietime
+sv_maxvelocity
+sv_gravity
+sv_aim
+filterban
+allow_download
+allow_download_skins
+allow_download_models
+allow_download_sounds
+allow_download_maps
+cl_rollspeed
+cl_rollangle
+sv_spectalk
+sys_nostdout
+sys_extrasleep
+sys_nostdout
--- /dev/null
+++ b/QW/docs/glqwcl-readme.txt
@@ -1,0 +1,144 @@
+GLQWCL v2.20
+
+3dfx owners -- read the 3dfx.txt file.
+
+On a standard OpenGL system, all you should need to do to run glqwcl is put 
+glqwcl.exe in your quake directory, and run it from there.  DO NOT install 
+the opengl32.dll unless you have a 3dfx!  Glquake should change the screen 
+resolution to 640*480*32k colors and run full screen by default.
+
+If you are running win-95, your desktop must be set to 32k or 64k colors 
+before running glqwcl.  NT can switch automatically.
+
+Theoretically, glqwcl will run on any compliant OpenGL that supports the 
+texture objects extensions, but unless it is very powerfull hardware that 
+accelerates everything needed, the game play will not be acceptable.  If it 
+has to go through any software emulation paths, the performance will likely 
+by well under one frame per second.
+
+At this time (march '97), the only standard opengl hardware that can play 
+glqwcl reasonably is an intergraph realizm, which is a VERY expensive card.  
+3dlabs has been improving their performance significantly, but with the 
+available drivers it still isn't good enough to play.  Some of the current 
+3dlabs drivers for glint and permedia baords can also crash NT when exiting 
+from a full screen run, so I don't recommend running glqwcl on 3dlabs 
+hardware.
+
+3dfx has provided an opengl32.dll that implements everything glqwcl needs, 
+but it is not a full opengl implementation.  Other opengl applications are 
+very unlikely to work with it, so consider it basically a "glqwcl driver".  
+See the encluded 3dfx.txt for specific instalation notes.  3dfx can only run 
+full screen, but you must still have your desktop set to a 16 bit color mode 
+for glqwcl to start.
+
+resolution options
+------------------
+We had dynamic resolution changing in glqwcl for a while, but every single 
+opengl driver I tried it on messed up in one way or another, so it is now 
+limited to startup time only.
+
+glqwcl -window
+This will start glqwcl in a window on your desktop instead of switching the 
+screen to lower resolution and covering everything.
+
+glqwcl -width 800 -height 600
+Tries to run glqwcl at the specified resolution.  Combined with -window, it 
+creates a desktop window that size, otherwise it tries to set a full screen 
+resolution.
+
+texture options
+---------------
+The amount of textures used in the game can have a large impact on performance.  
+There are several options that let you trade off visual quality for better 
+performance.
+
+There is no way to flush already loaded textures, so it is best to change 
+these options on the command line, or they will only take effect on some of 
+the textures when you change levels.
+
+OpenGL only allows textures to repeat on power of two boundaries (32, 64, 
+128, etc), but software quake had a number of textures that repeated at 24 
+or 96 pixel boundaries.  These need to be either stretched out to the next 
+higher size, or shrunk down to the next lower.  By default, they are filtered 
+down to the smaller size, but you can cause it to use the larger size if you 
+really want by using: 
+
+glqwcl +gl_round_down 0
+This will generally run well on a normal 4 MB 3dfx card, but for other cards 
+that have either worse texture management or slower texture swapping speeds, 
+there are some additional settings that can drastically lower the amount of 
+textures to be managed.
+
+glqwcl +gl_picmip 1
+This causes all textures to have one half the dimensions they otherwise would.  
+This makes them blurry, but very small.  You can set this to 2 to make the 
+textures one quarter the resolution on each axis for REALLY blurry textures.
+
+glqwcl +gl_playermip 1
+This is similar to picmip, but is only used for other players in deathmatch.  
+Each player in a deathmatch requires an individual skin texture, so this can 
+be a serious problem for texture management.  It wouldn't be unreasonable to 
+set this to 2 or even 3 if you are playing competatively (and don't care if 
+the other guys have smudged skins).  If you change this during the game, it 
+will take effect as soon as a player changes their skin colors.
+
+run time options
+----------------
+At the console, you can set these values to effect drawing.
+
+gl_texturemode GL_NEAREST
+Sets texture mapping to point sampled, which may be faster on some GL systems 
+(not on 3dfx).
+
+gl_texturemode GL_LINEAR_MIPMAP
+This is the default texture mode.
+
+gl_texturemode GL_LINEAR_MIPMAP_LINEAR
+This is the highest quality texture mapping (trilinear), but only very high 
+end hardware (intergraph intense 3D / realizm) supports it.  Not that big of 
+a deal, actually.
+
+gl_finish 0
+This causes the game to not issue a glFinish() call each frame, which may make 
+some hardware run faster.  If this is cleared, the 3dfx will back up a number 
+of frames and not be very playable.
+
+gl_flashblend 0
+By default, glqwcl just draws a shaded ball around objects that are emiting 
+light.  Clearing this variable will cause it to properly relight the world 
+like normal quake, but it can be a significant speed hit on some systems.
+
+gl_ztrick 0
+Glquake uses a buffering method that avoids clearing the Z buffer, but some 
+hardware platforms don't like it.  If the status bar and console are flashing 
+every other frame, clear this variable.
+
+gl_keeptjunctions 0
+If you clear this, glqwcl will remove colinear vertexes when it reloads the 
+level.  This can give a few percent speedup, but it can leave a couple stray 
+blinking pixels on the screen.
+
+novelty features
+----------------
+These are some rendering tricks that were easy to do in glqwcl.  They aren't 
+very robust, but they are pretty cool to look at.
+
+r_shadows 1
+This causes every object to cast a shadow.
+
+r_wateralpha 0.7
+This sets the opacity of water textures, so you can see through it in properly 
+processed maps.  0.3 is very faint, almost like fog.  1 is completely solid 
+(the default).  Unfortunately, the standard quake maps don't contain any 
+visibility information for seeing past water surfaces, so you can't just play 
+quake with this turned on.  If you just want to see what it looks like, you 
+can set "r_novis 1", but that will make things go very slow.  When I get a 
+chance, I will probably release some maps that have been processed properly 
+for this.
+
+r_mirroralpha 0.3
+This changes one particular texture (the stained glass texture in the EASY 
+start hall) into a mirror.  The value is the opacity of the mirror surface.
+
+
+
--- /dev/null
+++ b/QW/docs/qwcl-readme.txt
@@ -1,0 +1,955 @@
+--------------------------
+| qwcl-readme.txt        |
+| QWCL documentation     |
+| 5/11/98                |
+|                        |
+| Based on WinQuake      |
+| 3/21/97                |
+--------------------------
+
+QWCL is a native Win32 version of Quake, optimized for internet
+play, and will run on either Win95 or Windows NT 4.0 or later.  It is
+designed to take advantage of whatever enhanced video, sound, and input
+capabilities (such as DirectX or VESA VBE video modes) are present,
+but has fallback functionality so it can run on any Win95 or NT 4.0
+or later system, even if neither DirectX nor VESA VBE is available.
+You may experience problems running QWCL on some systems, because driver
+and operating-system support for game functionality are not yet mature
+under Win32, and many bugs and incompatibilities remain in those
+components.  If you encounter what seems to be a bug, first please
+check through the list of known problems, below.  For other info,
+check out http://www.quakeworld.net/
+
+The material accompanying Quake is the reference for all
+non-Windows-related matters concerning QuakeWorld; in terms of gameplay,
+QuakeWorld is the same as Quake.  This file contains Windows-related
+information only.
+
+The rest of this document is organized as follows:
+
+Installing and running QWCL
+Common problems and workarounds
+A bit about how QWCL video works
+Video command-line switches
+A bit about how QWCL sound works
+Sound command-line switches
+Notes on networking
+Notes on the mouse
+Log of changes to documentation
+Special thanks
+
+
+-----------------------------------
+| Installing and running QWCL     |
+-----------------------------------
+
+In order to run QWCL, you must first have Quake installed.
+Assuming Quake is installed in the standard directory, c:\quake,
+unzip the QWCL zip file into c:\quake.  The following files
+from the zip file must be present in order for QWCL to run:
+
+qwcl.exe
+pmpro16.dll
+pmpro32.dll
+wdir16.dll
+wdir32.dll
+wdirnop.com
+wdirnop.pif
+
+Then you can run QWCL by making c:\quake the current directory,
+typing "qwcl" and pressing the Enter key.  Alternatively, you can
+use qwc.bat to run QWCL.  The qwc batch file requires one parameter
+describing how to configure QWCL for performance; just type "qwc" to get
+a list of the six options.  The first of the six options is
+
+qwc fast
+
+This is the same as typing "qwcl"; this runs QWCL in an
+aggressive configuration that is likely to yield the best performance
+if it runs successfully on your system, but which has a risk of
+causing QWCL or even your system to crash if there are bugs or
+incompatibilities in your video or sound drivers.  Alternatively, you
+can use
+
+qwc safe
+
+to run QWCL in a conservative configuration, likely to run
+on almost all machines with no problems, but possibly with slower
+graphics, fewer high-resolution modes, and delayed sound.  Or you
+can run
+
+qwc verysafe
+
+to run QWCL in a very conservative configuration that is pretty
+much guaranteed to run, but will probably have slow performance, and
+will have no sound.  Two other options are
+
+qwc fastvid
+
+which has maximum video performance, but greater sound latency (delay
+until the sound is heard), and
+
+qwc fastsnd
+
+which uses more conservative video modes, but low-latency sound.
+
+(One odd note is that DirectSound has much lower-latency sound than
+wave sound, but is currently quite a bit slower overall.  Thus you
+may find that "qwc fastvid" is actually faster, by as much as 5-10%,
+than "qwc fast"; however, it may not feel faster, because the sound
+will lag.)
+
+Finally, you can use
+
+qwc max
+
+which is the same as qwc fast, but turns on DirectInput, which
+provides more responsive mouse control, but does not work properly
+on all systems.
+
+Note that DirectX is not required for QWCL to run, but QWCL will
+automatically take advantage of DirectSound and DirectDraw if they
+are present.  If DirectSound is not present, there will generally be
+considerable sound latency (sound will become audible several hundred
+milliseconds after the event that caused it).  Note also that there
+are currently no true DirectSound drivers for Windows NT, so QWCL will
+always run using wave output on NT, and will consequently have lagged
+sound.  See below for information about obtaining DirectX if you do
+not have it.
+
+Note that VESA VBE modes aren't required for QWCL to run, but QWCL will
+automatically make VESA modes available if they're present.  Your BIOS
+may already have VESA VBE 2.0 support built in, but most BIOSes
+don't. Worse, some BIOSes do have VESA VBE 2.0 built-in, but have
+buggy implementations, which may prevent you from being able to run
+the faster configurations of QWCL.  An easy way to get reliable VESA 2.0
+support is by obtaining SciTech Display Doctor; see below for
+further information. QWCL can also use VBE/AF 1.0 and greater modes;
+again, SciTech Display Doctor is the commonest way to get VBE/AF
+support.
+
+QWCL normally uses half the physical memory in your system for its
+heap, but not less than 8.5 Mb and not more than 16 Mb.  You can
+override this with "-heapsize n", where n is the amount of memory to
+allocate for the heap, in Kb.
+
+To use the joystick, you must bring down the console by pressing the
+tilde ('~') key, and type "joystick 1<enter>"; you can disable the
+joystick with "joystick 0<enter>" at any time.  The joystick setting
+remains in effect for subsequent QWCL sessions until changed, so
+you only need to do joystick 1 once to enable the joystick.  If the
+joystick somehow causes problems that keep you from being able to run
+QWCL at all, you can start QWCL -nojoy to complete disable the
+joystick for that session.
+
+
+-----------------------------------
+| Common problems and workarounds |
+-----------------------------------
+
+QWCL crashes or won't run
+-----------------------
+
+If QWCL refuses to run or crashes on your system, try running
+it using "qwc safe" or "qwc verysafe".  Or you can use command-line
+switches:
+
+qwcl -nodirectdraw -nowindirect -wavonly
+
+This will almost certainly solve your problem; however, it may result
+in  lagged sound (a long delay from action to hearing the sound), may
+result in fewer or slower high-res video modes, and the mouse may be
+somewhat less responsive.  If this does work, you can try removing
+each of the command-line switches until you identify the one that
+fixes the problem, thereby sacrificing as little functionality as
+possible.
+
+If the above command line does not fix your problems, try:
+
+qwcl -dibonly -nosound
+
+which forces QWCL into silent operation with bare-bones video support
+and no use of DirectInput for mouse input (the normal Windows mouse
+APIs are used instead).  Again, if this works, try removing switches
+until you identify the needed one.
+
+Both of the above command lines are quick fixes.  Often, the problem
+is caused by outdated or buggy DirectX drivers or code, and can
+frequently be completely fixed simply by installing the latest
+Microsoft-supplied version of DirectX, which you may be able to find
+on http://www.microsoft.com/mediadev/download/directx.exe, although
+the availability and location of the DirectX file changes
+periodically; note that at last check, this is a 3.4 Mb file.  (Be
+aware, though, that sometimes Microsoft's DirectX drivers don't
+support features that the manufacturers' drivers do support, such as
+display refresh rate control.)
+
+One known problem of this sort involves the current SB16 drivers from
+Creative Labs, which cause QWCL to crash on some machines.  The
+DirectSound drivers from Microsoft, available via the above-mentioned
+URL, fix this problem.
+
+It can also sometimes help to get the latest Windows drivers for your
+video adapter or sound card (although as the SB16 example indicates,
+this is not always a good idea), and for video boards that have flash
+BIOSes, it can sometimes help to get the latest BIOS upgrade.
+
+
+How do I select fullscreen or windowed QWCL operation?
+----------------------------------------------------
+Check out QWCL's new, spiffy Video menu, accessible from the Options
+menu.  There are now two types of modes listed, windowed and
+fullscreen.  You can make any of these modes the current and/or
+default mode, just as in DOS Quake.  If you make a windowed mode the
+default, QWCL will still briefly start up in fullscreen mode, then
+switch to windowed; if this is a problem, use the -startwindowed
+command-line switch.  More complete video control is available
+through the console, as described in the "A bit about how QWCL video
+works" section, below.
+
+
+Gee, I wish I could use a mouse to play QWCL with in a window
+-----------------------------------------------------------
+You can!  While in a windowed mode, go to the Options menu.  At the
+bottom, you'll find a new selection that lets you choose to have the
+mouse active when you're in a window.  Of course, if you do this,
+you'll have to use the keyboard (Alt-Tab, the Windows key, Ctrl-Esc,
+Alt-Esc, or Shift-Alt-Tab) to switch away from QWCL.
+
+
+Serial/modem menu is missing
+----------------------------
+QWCL currently does not support direct connect serial or modem play.
+
+
+DOS Quake reports unknown variables on startup after running QWCL
+---------------------------------------------------------------
+QWCL uses some console variables that do not exist in DOS Quake, and
+some of these are automatically archived in config.cfg when you exit
+QWCL.  If you then start DOS Quake, DOS Quake will complain that it
+doesn't recognize those variables.  You will also lose the settings
+of these variables when you return to QWCL.  Apart from losing the
+settings, this is harmless; ignore it.
+
+
+Problems running QWCL on NT 3.51
+------------------------------
+NT 3.51 isn't supported by QWCL.
+
+
+QWCL crashes while switching modes or Alt-Tabbing
+-----------------------------------------------
+So far, all cases of this seem to be tied to Creative Lab's SB16 sound
+drivers, and have been fixed by getting the latest DirectX drivers, as
+described above.  Alternatively, you should be able to fix this either
+by not switching modes or Alt-Tabbing, or by running -wavonly to
+disable DirectSound support.
+
+
+QWCL sometimes runs pretty slowly fullscreen
+------------------------------------------
+There are several possible reasons for this, starting with "You have a
+slow computer."  Assuming that's not the case, if you don't have
+either DirectDraw or SciTech Display Doctor installed (see the "A bit
+about how QWCL video works" section), it would probably be a good thing
+to install one or the other, because slow operation can be a result
+of slow copying or stretching of pixels to the screen by a Windows
+driver, something that's eliminated by both DirectDraw and Display
+Doctor.  You can also sometimes get a faster 320x200 mode on Win95 by
+doing vid_describemodes, then using vid_mode to select a non-VGA
+320x200 mode, as described in the "A bit about how QWCL video works"
+section.
+
+You can also try using a primary sound buffer on Win95 (this doesn't
+work on NT) by using the -primarysound command-line switch; this can
+improve performance by several percent, but does not work on all
+systems, and can result in odd sound effects on some systems when
+minimizing QWCL or switching the focus away from it.  If you use this
+switch, please don't report sound bugs; it's in there purely for you
+to use if it helps you, and we know it has problems on many systems.
+Finally, you can use -wavonly to select wave sound; this will increase
+your sound latency (sounds will be heard later than they should), but
+allows QWCL to run 5-10% faster on some systems.  That's about all you
+can do to speed up fullscreen QWCL on Win95, other than shrinking the
+active area of the screen with the screen size control in the Options
+menu.
+
+NT 4.0 comes with DirectX installed, but doesn't have any resolutions
+lower than 640x480.  In order to support a lower-resolution 320x240
+mode, QWCL has NT double each pixel in both directions to get enough
+pixels for 640x480.  The extra stretching costs some performance, the
+result being that NT can seem sluggish on all but high-end Pentiums
+and Pentium Pros.  (In fact, depending on the quality of your driver's
+stretching code, it can sometimes be faster to run QWCL at 640x480 than
+320x240-stretched on NT.)  One thing that can help on NT is switching
+to 640x480, then using the Options menu to shrink the active area of
+the screen.
+
+A common cause of slowness running in a window is having the desktop
+run in 16- or 32-bpp mode.  QWCL is an 8-bpp application, and it slows
+things down if pixels have to be translated from 8-bpp to 16- or
+32-bpp.  (Note that this is generally a problem only when running in a
+window; fullscreen apps rarely suffer from this.)
+
+
+Sound is sluggish on NT
+-----------------------
+NT doesn't have any real DirectSound drivers yet, so there's no way to
+do quick-response sound on NT.  When DirectSound drivers for NT
+appear, QWCL's sound should automatically be snappier.
+
+
+Sound breaks up or gets choppy, especially in menus
+---------------------------------------------------
+This is generally a sign that QWCL's frame rate is too low on your
+system.  Try reducing resolution or shrinking the active area of the
+screen.  In some circumstances, it may help to set the console
+variable _snd_mixahead to a larger value.
+
+
+The color black doesn't change with palette flashes sometimes
+-------------------------------------------------------------
+Normally, DirectDraw lets QWCL change all 256 colors, so when a palette
+flash happens, we can change all the colors, including black.
+However, on NT DirectDraw currently doesn't allow changing black;
+likewise, on both NT and Win95, black can't be changed in a window,
+either a normal window or fullscreen.  Consequently, in some modes and
+in a window, some parts of the QWCL screen (such as the sigils on the
+status bar and the spray where a shotgun blast hits) stay black when
+the palette flashes.  There is no workaround.
+
+
+Problems can result if Office shortcut bar is running
+-----------------------------------------------------
+Various odd behaviors, especially with sound, have been reported if
+the Office shortcut bar is running while QWCL is running.  If you
+experience odd problems, you might try shutting down the Office
+shortcut bar and see if that fixes anything.
+
+
+Other apps fail to play sound while QWCL is running
+-------------------------------------------------------
+The sound hardware is currently not a fully shareable resource on
+Win32.  Consequently, while QWCL is running, it always has the sound
+hardware allocated to itself, to make sure that sound is never lost to
+another app.  This means that normally (when QWCL is using DirectSound),
+apps that use wave sound (most non-game apps) will not be able to play
+sound while QWCL is running, even if QWCL is minimized or not the active
+app, although other DirectSound apps will be able to play sound when
+QWCL is not the active app.  If QWCL is using wave sound rather than
+DirectSound (either because -wavonly is used on the command line, or
+because there is no DirectSound driver, as is always the case on NT),
+then no other app will be able to play any sound while QWCL is running,
+period.
+
+
+QWCL doesn't have quite the right colors when it�s not the active app
+-------------------------------------------------------------------
+We're working on fixing this.  But QWCL puts everything back again as
+soon as it is reactivated, and anyway, when it�s not active, you can�t
+actually do anything in QWCL, so it doesn�t really matter anyway, right?
+
+
+Desktop is weird colors when QWCL runs windowed
+---------------------------------------------
+QWCL needs all 256 colors to look right and run fast, which causes it to
+have to change some of the 20 colors used to draw the desktop.
+
+
+Sometimes Permedia boards crash unless -nowindirect is used
+-----------------------------------------------------------
+It looks like this is probably a Permedia driver bug, so it might help
+if you get the most recent drivers.
+
+
+Right-click on QWCL button in task bar to close doesn�t work as expected
+----------------------------------------------------------------------
+In some modes, right-clicking on the QWCL task bar button doesn't work
+the way you'd expect.  We're trying to fix this, but if it's a
+problem, don't right-click.
+
+
+Screen saver never kicks in when running QWCL fullscreen
+------------------------------------------------------
+It does work windowed, but when QWCL is fullscreen, it completely
+owns the screen and doesn't share it with anyone, even the
+screensaver.  If you use Alt-Tab to minimize QWCL, the screensaver will
+then be enabled, so Alt-Tab away from QWCL if you're leaving your
+computer alone for a while and want the screensaver to be able to kick
+in.
+
+
+QWCL doesn't work in a window in 16-color mode
+--------------------------------------------
+That's 16 *colors*, not 16-bpp.  If you're still running a 16-color
+desktop, run QWCL fullscreen.
+
+
+Can't minimize window while mouse active
+----------------------------------------
+When running in a window with the mouse active as a QWCL input device,
+there is no easy way to minimize the window, because the system menu
+can't be brought up from the keyboard (because some of you use Alt
+and Spacebar for playing the game), and the mouse can't be used to
+manipulate the window because it's controlling QWCL.  To minimize, you
+can disable the mouse for QWCL and use it to minimize the window.  Or
+on Win95 you can Alt-Tab away from QWCL, then use the mouse to
+minimize (this doesn't work on NT, where clicking on the window
+controls just reactivates QWCL).  Or you can bind a key to the
+vid_minimize command, as in
+
+bind m "vid_minimize"
+
+and press that key to minimize the window.
+
+
+Window controls don't work on NT when mouse enabled
+---------------------------------------------------
+When running in a window on NT with the mouse enabled (so you can use
+the mouse to play QWCL), if you Alt-Tab away from QWCL, then use the mouse
+to click on the QWCL system menu control, or the minimize, maximize, or
+close controls, the controls are ignored and QWCL just reactivates.
+
+
+Mouse sometimes vanishes in system menu on Win95
+------------------------------------------------
+On Win95, if QWCL is running in a window with the mouse enabled (so you
+can use the mouse to play QWCL), if you Alt-Tab away, then click on the
+system menu, the menu comes up, but the mouse vanishes.  However, you
+can still use the keyboard to select system menu items, or to exit
+the system menu.
+
+
+QWCL behaves oddly if Scandisk starts defragmenting
+-------------------------------------------------
+If QWCL is running fullscreen on Win95 when Scandisk starts an automatic
+defragging, QWCL is forced to minimize, and when it is brought back up,
+may either be in a strange mode where it runs one frame for each
+keystroke (in which case Alt-Tab generally fixes things), or may hang
+the system.  We don't know what the problem is right now, but you may
+want to make sure you don't leave QWCL sitting there fullscreen
+overnight if you have automatic defragging.
+
+
+Hang reported with zero sound volume
+------------------------------------
+When sound is turned all the way down via the QWCL menus, hangs have
+been reported.
+
+
+Joystick worked fine with earlier versions of QWCL but not now
+------------------------------------------------------------------
+The joystick was enabled by default in earlier versions of
+QWCL, but quite a few people reported serious problems that
+forced them to disable the joystick--even some people who didn't
+have a joystick attached.  Since most people don't have joysticks,
+we've decided to disable the joystick by default, and let people
+who do want to use it set joystick 1 in the console (QWCL
+remembers this setting, so this only needs to be done once).
+
+
+QWCL runs very slowly when it has the focus under NT
+--------------------------------------------------
+In one case, QWCL ran very slowly when it had the focus, but fast when
+it didn't (obviously this is only visible in windowed modes).  The
+problem turned out to be that NT had a Sidewinder 3D Pro joystick
+driver installed; when the driver was removed, things were fine.
+If you see a similar problem, check whether QWCL is detecting that
+your system has a joystick when you don't think it should; if so,
+try doing "joystick 0", or -nojoy on the command line, and see if
+that fixes it.  If so, there's something flaky in your system
+joystick setup.
+
+
+Joystick doesn't seem calibrated properly
+-----------------------------------------
+QWCL relies on the information about your joystick stored in the
+system registry.  If the joystick seems miscalibrated, run the
+joystick applet and recalibrate and see if that fixes things.
+
+
+Playdemo fails across multiple levels
+-------------------------------------
+If "record" is used to record a client-side demo, bad things will
+happen on playback via playdemo if a level change is recorded.
+(Timedemo works fine.)  This is unfortunate, but QWCL
+internals make this not fixable without a good chance of
+breaking something more important, so it'll have to stay this way.
+
+
+Alt-Tab fullscreen only works sometimes
+---------------------------------------
+I know it seems that way, but actually the trick is that on Win95
+it only works if you let go of Tab before you let go of Alt.
+This is due to a Windows quirk involving what key sequences are
+passed along, so you'll have to work around it by remembering to
+let go of Tab first.
+
+
+MS-DOS windows get scrunched on Alt-Tab
+---------------------------------------
+This is a quirk of Windows; when you run QWCL in a low-res
+mode, sometimes when you exit QWCL or Alt-Tab back to the
+desktop, any open MS-DOS windows will be scrunched down to the
+size of the low-res mode.  There is no known workaround.
+
+
+Dprint in progs doesn't work
+----------------------------
+Dprint means "developer print," so it only works if the developer
+console variable is set to 1.  It was a bug in earlier versions that
+it worked even when developer was set to 0.
+
+
+Some DirectDraw modes flicker badly and look wrong
+--------------------------------------------------
+Page flipping doesn't work properly in some modes on some
+systems, particularly when using some DirectDraw modes.  You
+can work around this by setting the console variable
+vid_nopageflip to 1, then setting the desired mode (note
+that the vid_nopageflip setting does not take effect until
+the next mode set after the setting is changed).  Bear in
+mind, though, that the vid_nopageflip setting is remembered
+until it is explicitly changed again, meaning that once you
+change it, it thereafter applies to all modes, even if you
+exit and restart QWCL.
+
+
+The Windows key doesn't do anything fullscreen on Win95
+-------------------------------------------------------
+True.  This is a minor bug we haven't figured out how to fix yet.
+You'll have to use Ctrl-Esc, Alt-Tab, or Alt-Esc to switch away.
+
+
+My default mode is windowed, but QWCL goes fullscreen first
+---------------------------------------------------------
+For internal reasons, QWCL has to pick a single mode to always
+initialize when it starts up, before it sets whatever default you've
+selected.  We've chosen fullscreen mode, because that's the way most
+people will play.  If this is a problem for you, however, you can
+run QWCL with the -startwindowed command-line parameter.
+
+
+Some high-resolution video modes flicker or fail to initialize
+--------------------------------------------------------------
+We think these problems are all fixed, but if not, they have to
+do with triple-buffering in some modes on some DirectDraw drivers.
+If you encounter this problem, either don't use the problem modes
+or try using the -notriplebuf command-line parameter to turn off
+triple buffering.  Note, though, that turning off triple-buffering
+can reduce performance in some modes, so do this only if needed.
+
+
+Right-click doesn't work right on minimized QWCL
+----------------------------------------------------
+If you right-click on minimized QWCL on the task bar, the
+Close selection in the right-click menu doesn't work; you have
+to restore QWCL before you can exit it.  Also, the cursor vanishes
+over the right-click menu, although it still works.
+
+
+The screen briefly blanks when you exit QWCL
+------------------------------------------
+We're trying to fix this, but it's not harmful, just a mite ugly.
+
+
+MWAVE sound loses focus
+-----------------------
+We've had a report that on a ThinkPad with MWAVE sound, QWCL loses
+sound focus (and thus sound) every few seconds.
+
+
+Desktop doesn't reset to proper resolution on QWCL exit
+-----------------------------------------------------
+We've had a report that on exiting QWCL, the desktop didn't reset
+to the proper dimensions.  This may be a bug with the Matrox
+drivers, but we're not sure.  If it's a problem and newer
+drivers don't fix it, you can run -dibonly, which solves the
+problem but can cost some performance.
+
+
+Palette goes bad periodically on #9 Imagine card
+------------------------------------------------
+There's only one report of this, so maybe it's a flaky board,
+or maybe it's a driver bug.  Newer drivers might help.
+
+
+System with Packard Bell sound card III crashes on CapsLock
+-----------------------------------------------------------
+This appears to be the result of buggy DirectSound drivers;
+-wavonly makes the problem go away.
+
+
+Dvorak keyboard mapping ignored
+-------------------------------
+QWCL is hardwired for QWERTY.
+
+
+Cursor messed up after running QWCL
+---------------------------------
+This is a Windows driver bug; the driver isn't restoring the
+cursor properly on return from fullscreen QWCL to the desktop.
+Try newer drivers.
+
+
+Ctrl-Alt-Del on NT sometimes doesn't allow return to QWCL
+-------------------------------------------------------
+This happens on some machines while running QWCL fullscreen.
+If you experience this problem, the only workaround is not
+to press Ctrl-Alt-Del while fullscreen; Alt-Tab away first.
+
+
+Many fast Alt-Tabs on Win95 sometimes disable QWCL input
+------------------------------------------------------
+If you Alt-Tab fast lots of times on Win95 with QWCL running
+fullscreen, sometimes you end up in fullscreen QWCL, with the
+game not accepting any keyboard input (so there's no way to
+exit).  The only workaround is to not do lots of fast
+Alt-Tabs (why you'd want to, I'm not sure).
+
+
+
+----------------------------------
+| A bit about how QWCL video works |
+----------------------------------
+
+QWCL has the built-in ability to draw into windows (both normal, framed 
+desktop windows and fullscreen, borderless windows).  It also has
+built- in support for VGA 320x200 graphics, and supports DirectDraw,
+VESA VBE 2.0 and VESA VBE/AF (Accelerator Functions) graphics modes,
+if those are available.
+
+QWCL does not require DirectDraw, but in order for DirectDraw modes to
+be available, you must have DirectDraw installed; some systems come
+with it preinstalled, but if it's not on your system, you can download
+it from http://www.microsoft.com/mediadev/download/directx.exe (the
+exact URL may vary), and install it.
+
+QWCL does not require VESA VBE, but in order for VESA VBE modes to be
+available, your graphics card must be VESA VBE 2.0 or VBE/AF
+compliant; a VESA driver can either be built into the BIOS of your
+graphics card, or loadable via software.  If you don't have a VESA VBE
+driver, Scitech Display Doctor, available from Scitech Software, will
+update most graphics cards to VESA VBE 2.0 and VBE/AF.
+
+
+SciTech Display Doctor
+----------------------
+If you are having problems with your video drivers, or if you would
+like to take a shot at improving your video performance in QWCL, you may
+want to try out SciTech Display Doctor (SDD).  SDD works on just about
+any graphics card and it can do several things that can make QWCL run
+better on your system:
+
+1. It will update your graphics card to be compatible with VESA VBE
+2.0 and VESA VBE/AF (Accelerator Functions). These modes will usually
+give you the best performance in QWCL (which is often but not always
+faster than your current performance).
+
+2. It creates low-resolution modes on your graphics card.
+Low-resolution video modes (such as 320x240, 400x300 and 512x384)
+allow you to adjust the level of detail in QWCL so you can get the best
+balance between performance and image quality.
+
+The latest version of SciTech Display Doctor can be obtained from the
+following locations:
+
+www: http://www.scitechsoft.com
+ftp: ftp.scitechsoft.com
+CIS: GO SCITECH
+AOL: Keyword SciTech
+
+SciTech can be contacted at:
+
+email: info@scitechsoft.com
+
+SciTech Software, Inc.
+505 Wall Street
+Chico, CA  95926-1989
+916-894-8400
+916-894-9069 FAX
+
+
+Video modes supported in Win95
+------------------------------
+What all this means is that on Win95, QWCL will always be able to run in
+the following modes:
+
+1)  in a window
+2)  fullscreen 320x200 VGA mode 0x13
+3)  fullscreen high-resolution of some sort
+
+Category #3 can be any of several configurations.  On Win95, if either
+DirectDraw or VESA VBE modes are available, then all the DirectDraw
+and VESA modes will be presented as high-res choices.  (320x200 will
+always default to VGA mode 0x13.)  In the case that a given resolution
+is supported by both DirectDraw and VESA, the VESA mode will be used.
+(However, the command-line switch -nowindirect can turn off VESA modes
+entirely.)  If neither DirectDraw nor VESA modes are available, then
+high-resolution modes will be provided by using fullscreen, borderless
+windows in whatever resolutions the Windows driver supports, usually
+starting at 640x480 and going up.
+
+
+Video Modes Supported in Windows NT
+-----------------------------------
+NT is similar but not identical, because neither VESA VBE modes nor
+VGA mode 0x13 are available.  On NT, QWCL will always be able to run in
+the following modes:
+
+1)  in a window
+2)  fullscreen high-resolution of some sort
+
+On NT, category #2 can be one of two configurations.  If DirectDraw
+modes are available, then those will be the high-res choices;
+otherwise, fullscreen, borderless windows will be used in whatever
+resolutions the driver supports, usually starting at 640x480 and going
+up.  Because there is normally no low-resolution mode such as 320x200
+or 320x240 on NT, a pseudo low-res mode is created by rendering at
+320x240, then stretching the image by doubling it in each direction
+while copying it to a 640x480 screen.  However, stretching performance
+depends on the driver, and can be slow, so sometimes 640x480 is
+actually faster than 320x240 on NT.
+
+The bottom line here is that you can generally just use the Video menu
+and pick one of the modes and be happy.  In some cases, though, you
+may need to use command-line switches (described next) to get the
+types of modes you want.  One useful tip is to go into the console and
+do vid_describemodes, which lists all the modes QWCL makes available on
+your machine given the command-line switches you've used.  Each mode
+is followed by the name of the internal QWCL driver that supports it, so
+you can tell which modes are DirectDraw, VESA, and so on, as follows:
+
+WINDOWED: QWCL runs in a normal window
+FULLSCREEN DIB: fullscreen borderless window
+FULLSCREEN VGA8.DRV: VGA 320x200 mode
+FULLSCREEN DDRAW8.DRV: DirectDraw mode
+FULLSCREEN LINEAR8.DRV: VESA VBE 2.0+ mode
+FULLSCREEN ACCEL8.DRV: VESA VBE/AF (Accelerator Functions) mode
+                       (note that QWCL does not take advantage of
+                       VBE/AF acceleration; so far as QWCL is
+                       concerned VBE/AF is the same as normal VBE)
+
+You can use vid_mode from the console to set any of these modes.  So,
+for example, if you see that there are two 320x200 modes (such as one
+VGA mode 0x13, normally mode 3, and one VESA mode, normally mode 4),
+you can choose the VESA mode, which will often be faster, with
+vid_mode 4.  (You can make it the default by setting
+_vid_default_mode_win to the mode number.)
+
+There's more to the windowed modes than you might think.  320x240 is
+just what you�d expect, but 640x480 is actually rendered at 320x240
+and stretched up to 640x480, because most machines can�t handle the
+performance demands of real 640x480 rendering.  Likewise, 800x600 is a
+stretched 400x300.  Actually, though, vid_mode 2 (the 800x600 mode) is
+a user-configurable mode.  By setting the following console variables,
+you can change the characteristics of vid_mode 2:
+
+vid_config_x: width of mode 2 window
+
+vid_config_y: height of mode 2 window
+
+vid_stretch_by_2: whether to render at half-resolution in each
+direction and stretch up to the specified size in mode 2, or render at
+full resolution.
+
+After setting these variables in the console, do a vid_forcemode 2,
+and you�ll have the window you specified.  Note that after making
+these changes, the new resolution will show up as the third windowed
+mode in the Video menu.
+
+If you don't have QWCL mouse play enabled in windowed mode, you can also
+go from windowed to fullscreen mode simply by clicking on the maximize
+button.  The mode switched to is controlled by the vid_fullscreen_mode
+console variable, and defaults to mode 3.
+
+Other video console commands include:
+
+vid_fullscreen: switch to the mode specified by the
+vid_fullscreen_mode console variable.
+
+vid_windowed: switch to the mode specified by the vid_windowed_mode
+console variable.
+
+Vid_fullscreen and vid_windowed can be bound to keys, so it's possible
+to flip between windowed and fullscreen with a single key press.
+
+Also, vid_minimize minimizes the QWCL window if and only if
+QWCL is running in a windowed mode.  You can bind a key to
+the commands "vid_windowed; wait; vid_minimize" to minimize QWCL
+regardless of whether you're running in windowed or fullscreen mode.
+
+You can turn off page flipping by setting the console variable
+vid_nopageflip to 1, then setting a new mode.  (Note that the
+vid_nopageflip setting does not take effect until the next mode set.)
+Some systems run faster with page flipping turned off; also, page
+flipping does not work properly on some adapters, and vid_nopageflip
+is a workaround for this.  Note that vid_nopageflip is a persistent
+variable; it retains its setting until it is explicitly changed again,
+even across multiple QWCL sessions.
+
+The vid_forcemode console command sets the specified mode, even if
+it's the same as the current mode (normally the mode set only happens
+if the new mode differs from the current mode).  This is generally
+useful only if you've modified the characteristics of video mode 2
+(the configurable window) while you're in mode 2, and want to force
+the new characteristics to take effect.
+
+Whenever you switch to running QWCL in a window, the window is
+placed at the same location it was in the last time QWCL ran
+in a window.  You can reset the window position to the upper left
+by using the -resetwinpos command-line switch.  The window position
+is stored in the vid_window_x and vid_window_y console variables.
+
+
+
+-------------------------------
+| Video command-line switches |
+-------------------------------
+
+The full list of video-related command-line switches is:
+
+-dibonly: QWCL will use only windows (both normal, framed windows on the
+desktop and fullscreen, borderless windows), not any direct hardware
+access modes such as DirectDraw or VESA modes, or even VGA 320x200
+mode.  This is the closest thing to a guaranteed-to-run fullscreen
+mode QWCL has.
+
+-nowindirect: QWCL will not try to use VESA VBE 2.0 modes, or VBE/AF
+1.0 or later modes.  Note that if there are both DirectDraw and VESA
+modes for a given resolution, QWCL will normally use the VESA mode;
+-nowindirect allows DirectDraw modes to be the preferred choice for
+all resolutions except 320x200.  This can be useful if QWCL is crashing
+because of a buggy VESA driver.
+
+-nodirectdraw: QWCL will not try to use DirectDraw modes.  This can be
+useful if QWCL is crashing because of a buggy DirectDraw driver.
+
+-novbeaf: QWCL will not try to use VBE/AF 1.0 or later modes.
+
+-startwindowed: QWCL will come up in a windowed mode, without going
+fullscreen even during initialization.
+
+-noforcevga: normally, QWCL uses VGA mode 0x13 for the default 320x200
+mode, even if a DirectDraw or VESA 320x200 mode exists.  However,
+DirectDraw and VESA modes can be considerably faster than mode 0x13,
+because they can set up a linear framebuffer with higher memory
+bandwidth.  If you specify -noforcevga, the default 320x200 mode in
+the menu will be a DirectDraw or VESA mode if one exists.  This has no
+effect on modes selected via the console variable vid_mode, and if
+320x200 is already your video mode, -noforcevga doesn't do anything
+until you use the menu to select another mode, then select 320x200
+again.  (So if your default mode is 320x200 and you then specify
+-noforcevga, switch away to some other mode and then back to 320x200
+to get the potentially faster 320x200 mode.)  The downside to this
+switch is that DirectDraw and VESA modes can cause problems in some
+systems, due to driver bugs or hardware incompatibilities; if you
+experience problems with this switch, don't use it.
+
+-noautostretch: don't stretch windowed modes selected with
+-startwindowed to double resolution.
+
+-nofulldib: don't use fullscreen, borderless windows, even if there
+are no DirectDraw or VESA modes available.
+
+-allow360: allow listing of 360-wide modes in the video mode menu.
+These are normally filtered out to make sure the menu doesn't get too
+full, which could cause high-res modes not to be displayed.
+
+-notriplebuf: prevent triple-buffered page flipping (rather than double-
+buffered).  This may result in slower performance, but is a workaround
+if you encounter problems with flicker or initialization failure, which
+could possibly happen in some modes with some DirectDraw drivers.
+
+
+
+----------------------------------
+| A bit about how QWCL sound works |
+----------------------------------
+
+QWCL can use either DirectSound or Windows wave output to generate
+sound.  If DirectSound is available, it is used; if not, if wave sound
+is available it is used; and if neither is available, there is no
+sound.  DirectSound results in the best sound quality, and also the
+lowest-latency sound; use it if you can, because you will be happier
+with the results.  (Note, though, that no NT sound drivers yet support
+DirectSound.)  Wave sound will often have high latency, lagging the
+events that generate sound by hundreds of milliseconds on some
+machines.
+
+You can tell what kind of sound QWCL uses on your system by looking at
+the startup portion of the console; you will see either "DirectSound
+initialized" or "Wave sound initialized" (neither message is printed
+if there's no sound).  Any sound failure messages will also be printed
+in the startup portion of the console.
+
+Note that QWCL generates sound only when it is the active app, the one
+with the input focus.
+
+
+
+-------------------------------
+| Sound command-line switches |
+-------------------------------
+
+The full list of sound-related command-line switches is:
+
+-wavonly: don�t use DirectSound, but use wave sound if available.
+Note that wave sound is generally faster than DirectSound, but has
+considerably greater latency.  This switch is redundant on NT, because
+all sound output on current NT drivers is wave sound.
+
+-nosound: don�t output any sound.
+
+-primarysound: use DirectSound primary buffer output.  This is
+generally faster than normal secondary buffer output, but does not
+work in some systems, and produces odd sound glitches on minimization
+and focus switching in other systems.  Use it at your own risk, and
+please do not report sound bugs if you're using this switch.
+
+-snoforceformat: QWCL will not try to force the sound hardware to 11
+KHz, 16 bits per sample.  This may be useful if DirectSound is failing
+for no apparent reason, but generally QWCL will produce better sound and
+better performance if this switch is not used.
+
+
+
+-----------------------
+| Notes on networking |
+-----------------------
+
+The winsock TCP/IP driver will not cause a dial-up internet connection
+to automatically start up when Quake is started.  If you start Quake
+with it inactive, the connection will be activated when you either try
+to connect to a server or search for local servers.
+
+The local IP address will not always be known at startup.  If it is
+currently unknown the menu will display "INADDR_ANY".  This will be
+replaced with the real address when it is known.  The IP address will
+become known when you try to connect to a server, you search for local
+servers, or you start a server.
+
+For multi-homed machines (machines with more than one network adapter
+and IP adress), you can force QWCL to bind to a specific IP
+address.  There is a command line option "-ip" that takes an IP
+address as its parameter.
+
+
+
+----------------------
+| Notes on the mouse |
+----------------------
+
+If DirectInput is installed and functioning, QWCL can use it for
+mouse input, but does not do so automatically because DirectInput does
+not work properly on all systems.  DirectInput can be enabled via the
+command-line switch -dinput.  If DirectInput is not available or is
+not enabled, QWCL uses the normal Windows mouse APIs instead.
+DirectInput provides slightly smoother motion; also, it tends to be
+more responsive to fast spinning motions, and we recommend that you use
+it if it works properly on your system.  You can determine if QWCL uses
+DirectInput on your system when you use -dinput by checking for
+"DirectInput initialized" in the startup console text.  If not, you
+might try installing DirectX 3 (note, though, that as I write this
+there is no released DirectInput support for Windows NT, only Win95).
+
--- /dev/null
+++ b/QW/docs/readme.qwcl
@@ -1,0 +1,217 @@
+README for Linux QWCL
+---------------------
+
+Please refer to
+
+http://www.quakeworld.net/
+
+for documentation on the client that is not operating system specific.
+
+This README covers all versions of QWCL for Linux:
+
+Requirements for SVGALib qwcl:
+
+- SVGALib 1.20 or later (/lib/libvga.so.1.2.10)
+- libc 5.2.18 or later (5.0.9 will not work, /lib/libc.so.5.2.18)
+- CD-ROM for CDAudio
+- Soundcard capable of mmap'd buffers.  USSLite 3.5.4 was used to build squake
+  with.  Works fine on SoundBlaster 16.
+- SVGALib supported mouse (usually if it works with X, it'll work with
+  squake).
+- Kernel 2.0.24 or later
+  - untested with 2.1 kernels, your mileage may vary
+
+Requirements for glqwcl:
+
+- 3DFX based card for the GLQuake version, VooDoo, VooDoo Rush or VooDoo2
+at this writing.  In order to use 3DFX hardware, you must have 3DFX's
+GLIDE drivers installed.  RPMs for these drivers are available at:
+http://glide.xxedgexx.com/3DfxRPMS.html
+- For the glX version, an OpenGL implementation that includes hardware
+glX support.
+- CD-ROM for CDAudio
+- Soundcard capable of mmap'd buffers.  USSLite 3.5.4 was used to build squake
+  with.  Works fine on SoundBlaster 16 and Gravis Ultrasound MAX.
+- SVGALib compatible mouse for glquake or X11 for glquake.glx
+- Kernel 2.0.24 or later
+  - untested with 2.1 kernels, your mileage may vary
+
+Requirements for X11 qwcl:
+
+- X11R5 later, only tested with XFree86, should work with most X Servers
+- libc 5.2.18 or later (5.0.9 will not work, /lib/libc.so.5.2.18)
+  or glibc (libc6) for the glibc version
+- CD-ROM for CDAudio
+- Soundcard capable of mmap'd buffers.  USSLite 3.5.4 was used to build squake
+  with.  Works fine on SoundBlaster 16 and Gravis Ultrasound MAX.
+- SVGALib supported mouse (usually if it works with X, it'll work with
+  squake).
+- Kernel 2.0.24 or later
+  - untested with 2.1 kernels, your mileage may vary
+
+Skins Note
+----------
+
+After you get the skin files from ftp.idsoftware.com (currently, 
+qw_skins.zip, qws_9652.zip and qws_9706.zip) and install them in
+qw/skins, you should run the shell script 'fixskins.sh' that you can find in
+the qw/skins directly distributed with this archive.
+
+Linux qwcl will always look for lowercase file names first.
+
+Additional notes for SVGALib QWCL
+---------------------------------
+
+Linux qwcl supports 320x200x256, the various modeX modes (320x400, 360x400, 
+etc) as well as high res modes if your card is supported by SVGALib.  Use 
+the Quake console command vid_describemodes to list supported modes and 
+the command vid_mode <number> to change modes.
+
+Full sound support is included.  The default sound rate is 16-bit stereo,
+11KHz.  You can change this in the options section below.
+
+Mouse works great, but SVGALib may not detect a 3-button mouse properly (it
+will only use two buttons).  Check your /etc/libvga.config (or
+/etc/vga/libvga.config for SlackWare users).
+
+Additional notes for glqwcl
+---------------------------
+
+There are three different ways to execute glqwcl:
+
+1. The binary "glqwcl" requires Mesa 3-D 2.5 or later installed and compiled
+with 3DFX support (fxMesa..() function interface).  It also requires
+svgalib 1.3.0 or later for keyboard/mouse input.  This binary is a console
+application.  Mesa 3-D requires GLIDE to be installed.
+
+2. The shell script "glqwcl.3dfxgl" runs the "glqwcl" binary after
+preloading the lib3dfxgl.so library.  This is a port of 3DFX's Win32
+OpenGL MCD (Mini Client Driver) to Linux.  It is faster than Mesa 3-D
+since it was written specifically with supporting GLQuake in mind.
+lib3dfxgl.so requires that GLIDE be installed.
+
+3. The binary "glqwcl.glx" is linked against standard OpenGL libraries.
+It should run on many different hardward OpenGL implementations under
+Linux and X11.  This binary is an X11 application and must be run under
+X11.  It will work with Mesa 3-D as a standard glX based OpenGL 
+applications.  If the Mesa 3-D library is compiled with 3DFX support,
+you can have Mesa 3-D support 3DFX hardware under X11 by setting the
+enviroment variable "MESA_GLX_FX" to "fullscreen" for fullscreen mode
+and "window" for windowed mode, eg. "export MESA_GLX_FX=fullscreen" for sh 
+or "setenv MESA_GLX_FX fullscreen" for csh.
+
+For glqwcl, you must also have SVGALib or later installed (1.3.0 or later
+prefered).  glqwcl uses SVGALib for mouse and keyboard handling.
+
+If you have gpm and/or selection running, you will have to terminate them
+before running glqwcl since they will not give up the mouse when glqwcl
+attempts to run.  You can kill gpm by typing 'killall gpm' as root.
+
+You must run glqwcl as root or setuid root since it needs to access things 
+such as sound, keyboard, mouse and the 3DFX video.  Future versions may not 
+require root permissions.
+
+Additional notes for X11 qwcl
+-----------------------------
+
+This is a windowed version that is generic for X11.  It runs in a window
+and can be resized.  You can specify a starting window size with:
+	-width <width>
+	-height <height>
+	-winsize <width> <height>
+Default is 320x200. It works in 16bit modes, but it's slower (twice as many
+bytes to copy).
+
+No other video modes are supported (just runs windowed).  Mouse is read, but
+not "grabbed" by default.  Go to the Options menu and turn on Use Mouse to grab
+the mouse and use it in the game (or type "_windowed_mouse 1" at the console).
+
+New Command Line Options for Linux Quake
+----------------------------------------
+
+-mem <mb>
+Specify memory in megabytes to allocate (default is 8MB, which should be fine
+for most needs).
+
+-nostdout
+Don't do any output to stdout
+
+-mdev <device>
+Mouse device, default is /dev/mouse
+
+-mrate <speed>
+Mouse baud rate, default is 1200
+
+-cddev <device>
+CD device, default is /dev/cdrom
+
+-mode <modenum>
+Use indicated video mode
+
+-nokdb
+Don't initialize keyboard
+
+-sndbits <8 or 16>
+Set sound bit sample size.  Default is 16 if supported.
+
+-sndspeed <speed>
+Set sound speed.  Usual values are 8000, 11025, 22051 and 44100.
+Default is 11025.
+
+-sndmono
+Set mono sound
+
+-sndstereo
+Set stereo sound (default if supported)
+
+Installation
+------------
+
+Boot DOS (I know, but you need it to run the Quake install program) and
+install Quake from your Quake CD to a DOS parition.
+
+Boot Linux and make a directory for Quake.  Copy everything from the DOS Quake
+directory into it.  i.e.:
+	(cd /dos/quake; tar cf - .) | (cd ~/quake; tar xf -)
+
+Place qwcl into your Quake directory.  You must make it setuid root (since
+Quake access stuff like direct video writes, the raw keyboard mode, CD, etc).
+Quake will setuid back to the normal user as soon as it opens these files.
+Make Quake suid root as follows:
+	chown root qwcl
+	chmod 4755 qwcl
+
+Run qwcl.  I don't recommend running it as root, since all the saved
+config.cfg files will be then owned as root.  Use your normal account, unless
+you do everything as root, then your mileage will vary.
+
+qwcl may segfault if it tries to initialize your sound card and their isn't
+one.  Same with the CDROM.  If it dies, try it with -nosound and/or
+-nocdaudio.  If you have a sound card it died on and you know it is
+supported by USSLite (the driver that comes with the Linux kernel), let me
+know and I'll take a look at it.
+
+It should work with SCSI CDROMs, but is untested.
+
+End Notes
+---------
+
+Linux QuakeWorld is *NOT* an officially supported product.  Mail about it
+will be deleted.  Do not email id about this product.  If you are having
+technical difficultly, you can email me, but make sure you have the correct
+kernel, libc, svgalib and other software versions before you email me.
+
+/// Dave 'Zoid' Kirsch
+zoid@idsoftware.com
+Official Quake Unix Port Administrator
+
+Acks
+----
+
+Greg Alexander <galexand@sietch.bloomington.in.us> for initial work in SVGALib
+support.
+Dave Taylor <ddt@crack.com> for basic Linux support.
+id Software for Quake and making me port it. :)
+
+Lots of people on #linux, #quake for testing.
+
--- /dev/null
+++ b/QW/docs/readme.qwsv
@@ -1,0 +1,13 @@
+QWSV Notes (May.05.1998 Release)
+--------------------------------
+ 
+ Please refer to
+
+ http://www.quakeworld.net/
+
+ for documentation.
+
+ Server operators wishing to link to our master server at id, please use;
+
+ qwsv +setmaster 192.246.40.37.
+
--- /dev/null
+++ b/QW/dxsdk/sdk/inc/d3d.h
@@ -1,0 +1,392 @@
+/*==========================================================================;
+ *
+ *  Copyright (C) 1995-1996 Microsoft Corporation.  All Rights Reserved.
+ *
+ *  File:       d3d.h
+ *  Content:    Direct3D include file
+ *
+ ***************************************************************************/
+
+#ifndef _D3D_H_
+#define _D3D_H_
+
+#include <stdlib.h>
+
+#ifdef _WIN32
+#define COM_NO_WINDOWS_H
+#include <objbase.h>
+#else
+#include "d3dcom.h"
+#endif
+
+#ifdef _WIN32
+#define D3DAPI WINAPI
+#else
+#define D3DAPI
+#endif
+
+/*
+ * Interface IID's
+ */
+#if defined( _WIN32 ) && !defined( _NO_COM)
+DEFINE_GUID( IID_IDirect3D,             0x3BBA0080,0x2421,0x11CF,0xA3,0x1A,0x00,0xAA,0x00,0xB9,0x33,0x56 );
+DEFINE_GUID( IID_IDirect3DTexture,      0x2CDCD9E0,0x25A0,0x11CF,0xA3,0x1A,0x00,0xAA,0x00,0xB9,0x33,0x56 );
+DEFINE_GUID( IID_IDirect3DLight,        0x4417C142,0x33AD,0x11CF,0x81,0x6F,0x00,0x00,0xC0,0x20,0x15,0x6E );
+DEFINE_GUID( IID_IDirect3DMaterial,     0x4417C144,0x33AD,0x11CF,0x81,0x6F,0x00,0x00,0xC0,0x20,0x15,0x6E );
+DEFINE_GUID( IID_IDirect3DExecuteBuffer,0x4417C145,0x33AD,0x11CF,0x81,0x6F,0x00,0x00,0xC0,0x20,0x15,0x6E );
+DEFINE_GUID( IID_IDirect3DViewport,     0x4417C146,0x33AD,0x11CF,0x81,0x6F,0x00,0x00,0xC0,0x20,0x15,0x6E );
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Data structures
+ */
+#ifdef __cplusplus
+
+/* 'struct' not 'class' per the way DECLARE_INTERFACE_ is defined */
+struct IDirect3D;
+struct IDirect3DDevice;
+struct IDirect3DExecuteBuffer;
+struct IDirect3DLight;
+struct IDirect3DMaterial;
+struct IDirect3DTexture;
+struct IDirect3DViewport;
+typedef struct IDirect3D                *LPDIRECT3D;
+typedef struct IDirect3DDevice          *LPDIRECT3DDEVICE;
+typedef struct IDirect3DExecuteBuffer   *LPDIRECT3DEXECUTEBUFFER;
+typedef struct IDirect3DLight           *LPDIRECT3DLIGHT;
+typedef struct IDirect3DMaterial        *LPDIRECT3DMATERIAL;
+typedef struct IDirect3DTexture         *LPDIRECT3DTEXTURE;
+typedef struct IDirect3DViewport        *LPDIRECT3DVIEWPORT;
+
+#else
+
+typedef struct IDirect3D                *LPDIRECT3D;
+typedef struct IDirect3DDevice          *LPDIRECT3DDEVICE;
+typedef struct IDirect3DExecuteBuffer   *LPDIRECT3DEXECUTEBUFFER;
+typedef struct IDirect3DLight           *LPDIRECT3DLIGHT;
+typedef struct IDirect3DMaterial        *LPDIRECT3DMATERIAL;
+typedef struct IDirect3DTexture         *LPDIRECT3DTEXTURE;
+typedef struct IDirect3DViewport        *LPDIRECT3DVIEWPORT;
+
+#endif
+
+#include "d3dtypes.h"
+#include "d3dcaps.h"
+
+/*
+ * IDirect3D
+ */
+#undef INTERFACE
+#define INTERFACE IDirect3D
+DECLARE_INTERFACE_(IDirect3D, IUnknown)
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID* ppvObj) PURE;
+    STDMETHOD_(ULONG, AddRef) (THIS) PURE;
+    STDMETHOD_(ULONG, Release) (THIS) PURE;
+    /*** IDirect3D methods ***/
+    STDMETHOD(Initialize) (THIS_ REFIID) PURE;
+    STDMETHOD(EnumDevices)(THIS_ LPD3DENUMDEVICESCALLBACK, LPVOID) PURE;
+    STDMETHOD(CreateLight) (THIS_ LPDIRECT3DLIGHT*, IUnknown*) PURE;
+    STDMETHOD(CreateMaterial) (THIS_ LPDIRECT3DMATERIAL*, IUnknown*) PURE;
+    STDMETHOD(CreateViewport) (THIS_ LPDIRECT3DVIEWPORT*, IUnknown*) PURE;
+    STDMETHOD(FindDevice)(THIS_ LPD3DFINDDEVICESEARCH, LPD3DFINDDEVICERESULT) PURE;
+};
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirect3D_QueryInterface(p, a, b)         (p)->lpVtbl->QueryInterface(p, a, b)
+#define IDirect3D_AddRef(p)                       (p)->lpVtbl->AddRef(p)
+#define IDirect3D_Release(p)                      (p)->lpVtbl->Release(p)
+#define IDirect3D_Initialize(p, a)                (p)->lpVtbl->Initialize(p, a)
+#define IDirect3D_EnumDevices(p, a, b)            (p)->lpVtbl->EnumDevices(p, a, b)
+#define IDirect3D_CreateLight(p, a, b)            (p)->lpVtbl->CreateLight(p, a, b)
+#define IDirect3D_CreateMaterial(p, a, b)         (p)->lpVtbl->CreateMaterial(p, a, b)
+#define IDirect3D_CreateViewport(p, a, b)         (p)->lpVtbl->CreateViewport(p, a, b)
+#define IDirect3D_FindDevice(p, a, b)             (p)->lpVtbl->FindDevice(p, a, b)
+#endif
+
+/*
+ * IDirect3DDevice
+ */
+#undef INTERFACE
+#define INTERFACE IDirect3DDevice
+DECLARE_INTERFACE_(IDirect3DDevice, IUnknown)
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID* ppvObj) PURE;
+    STDMETHOD_(ULONG, AddRef) (THIS) PURE;
+    STDMETHOD_(ULONG, Release) (THIS) PURE;
+    /*** IDirect3DDevice methods ***/
+    STDMETHOD(Initialize) (THIS_ LPDIRECT3D, LPGUID, LPD3DDEVICEDESC) PURE;
+    STDMETHOD(GetCaps) (THIS_ LPD3DDEVICEDESC, LPD3DDEVICEDESC) PURE;
+    STDMETHOD(SwapTextureHandles) (THIS_ LPDIRECT3DTEXTURE, LPDIRECT3DTEXTURE) PURE;
+    STDMETHOD(CreateExecuteBuffer) (THIS_ LPD3DEXECUTEBUFFERDESC, LPDIRECT3DEXECUTEBUFFER*, IUnknown*) PURE;
+    STDMETHOD(GetStats) (THIS_ LPD3DSTATS) PURE;
+    STDMETHOD(Execute) (THIS_ LPDIRECT3DEXECUTEBUFFER, LPDIRECT3DVIEWPORT, DWORD) PURE;
+    STDMETHOD(AddViewport) (THIS_ LPDIRECT3DVIEWPORT) PURE;
+    STDMETHOD(DeleteViewport) (THIS_ LPDIRECT3DVIEWPORT) PURE;
+    STDMETHOD(NextViewport) (THIS_ LPDIRECT3DVIEWPORT, LPDIRECT3DVIEWPORT*, DWORD) PURE;
+    STDMETHOD(Pick) (THIS_ LPDIRECT3DEXECUTEBUFFER, LPDIRECT3DVIEWPORT, DWORD, LPD3DRECT) PURE;
+    STDMETHOD(GetPickRecords)(THIS_ LPDWORD, LPD3DPICKRECORD) PURE;
+    STDMETHOD(EnumTextureFormats) (THIS_ LPD3DENUMTEXTUREFORMATSCALLBACK, LPVOID) PURE;
+    STDMETHOD(CreateMatrix) (THIS_ LPD3DMATRIXHANDLE) PURE;
+    STDMETHOD(SetMatrix) (THIS_ D3DMATRIXHANDLE, LPD3DMATRIX) PURE;
+    STDMETHOD(GetMatrix) (THIS_ D3DMATRIXHANDLE, LPD3DMATRIX) PURE;
+    STDMETHOD(DeleteMatrix) (THIS_ D3DMATRIXHANDLE) PURE;
+    STDMETHOD_(HRESULT, BeginScene) (THIS) PURE;
+    STDMETHOD_(HRESULT, EndScene) (THIS) PURE;
+    STDMETHOD(GetDirect3D) (THIS_ LPDIRECT3D*) PURE;
+};
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirect3DDevice_QueryInterface(p, a, b)         (p)->lpVtbl->QueryInterface(p, a, b)
+#define IDirect3DDevice_AddRef(p)                       (p)->lpVtbl->AddRef(p)
+#define IDirect3DDevice_Release(p)                      (p)->lpVtbl->Release(p)
+#define IDirect3DDevice_Initialize(p, a, b, c)          (p)->lpVtbl->Initialize(p, a, b, c)
+#define IDirect3DDevice_GetCaps(p, a, b)                (p)->lpVtbl->GetCaps(p, a, b)
+#define IDirect3DDevice_SwapTextureHandles(p, a, b)     (p)->lpVtbl->SwapTextureHandles(p, a, b)
+#define IDirect3DDevice_CreateExecuteBuffer(p, a, b, c) (p)->lpVtbl->ExecuteBuffer(p, a, b, c)
+#define IDirect3DDevice_GetStats(p, a)                  (p)->lpVtbl->CreateViewport(p, a)
+#define IDirect3DDevice_Execute(p, a, b, c)             (p)->lpVtbl->Execute(p, a, b, c)
+#define IDirect3DDevice_AddViewport(p, a)               (p)->lpVtbl->AddViewport(p, a)
+#define IDirect3DDevice_DeleteViewport(p, a)            (p)->lpVtbl->DeleteViewport(p, a)
+#define IDirect3DDevice_NextViewport(p, a, b)           (p)->lpVtbl->NextViewport(p, a, b)
+#define IDirect3DDevice_Pick(p, a, b, c, d)             (p)->lpVtbl->Pick(p, a, b, c, d)
+#define IDirect3DDevice_GetPickRecords(p, a, b)         (p)->lpVtbl->GetPickRecords(p, a, b)
+#define IDirect3DDevice_EnumTextureFormats(p, a, b)     (p)->lpVtbl->EnumTextureFormats(p, a, b)
+#define IDirect3DDevice_CreateMatrix(p, a)              (p)->lpVtbl->CreateMatrix(p, a)
+#define IDirect3DDevice_SetMatrix(p, a, b)              (p)->lpVtbl->SetMatrix(p, a, b)
+#define IDirect3DDevice_GetMatrix(p, a, b)              (p)->lpVtbl->GetMatrix(p, a, b)
+#define IDirect3DDevice_DeleteMatrix(p, a)              (p)->lpVtbl->DeleteMatrix(p, a)
+#define IDirect3DDevice_BeginScene(p)                   (p)->lpVtbl->BeginScene(p)
+#define IDirect3DDevice_EndScene(p)                     (p)->lpVtbl->EndScene(p)
+#define IDirect3DDevice_GetDirect3D(p, a)               (p)->lpVtbl->GetDirect3D(p, a)
+#endif
+
+/*
+ * IDirect3DExecuteBuffer
+ */
+#undef INTERFACE
+#define INTERFACE IDirect3DExecuteBuffer
+DECLARE_INTERFACE_(IDirect3DExecuteBuffer, IUnknown)
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID* ppvObj) PURE;
+    STDMETHOD_(ULONG, AddRef) (THIS) PURE;
+    STDMETHOD_(ULONG, Release) (THIS) PURE;
+    /*** IDirect3DExecuteBuffer methods ***/
+    STDMETHOD(Initialize) (THIS_ LPDIRECT3DDEVICE, LPD3DEXECUTEBUFFERDESC) PURE;
+    STDMETHOD(Lock) (THIS_ LPD3DEXECUTEBUFFERDESC) PURE;
+    STDMETHOD_(HRESULT, Unlock) (THIS) PURE;
+    STDMETHOD(SetExecuteData) (THIS_ LPD3DEXECUTEDATA) PURE;
+    STDMETHOD(GetExecuteData) (THIS_ LPD3DEXECUTEDATA) PURE;
+    STDMETHOD(Validate) (THIS_ LPDWORD, LPD3DVALIDATECALLBACK, LPVOID, DWORD) PURE;
+    STDMETHOD(Optimize) (THIS_ DWORD) PURE;
+};
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirect3DExecuteBuffer_QueryInterface(p, a, b) (p)->lpVtbl->QueryInterface(p, a, b)
+#define IDirect3DExecuteBuffer_AddRef(p)               (p)->lpVtbl->AddRef(p)
+#define IDirect3DExecuteBuffer_Release(p)              (p)->lpVtbl->Release(p)
+#define IDirect3DExecuteBuffer_Initialize(p, a, b)     (p)->lpVtbl->Initialize(p, a, b)
+#define IDirect3DExecuteBuffer_Lock(p, a)              (p)->lpVtbl->Lock(p, a)
+#define IDirect3DExecuteBuffer_Unlock(p, a)            (p)->lpVtbl->Unlock(p)
+#define IDirect3DExecuteBuffer_SetExecuteData(p, a)    (p)->lpVtbl->SetExecuteData(p, a)
+#define IDirect3DExecuteBuffer_Validate(p, a, b, c, d) (p)->lpVtbl->Validata(p, a, b, c, d)
+#endif
+
+/*
+ * Flags for execute buffer calls
+ */
+#define D3DNEXT_NEXT    0x00000001l
+#define D3DNEXT_HEAD    0x00000002l
+#define D3DNEXT_TAIL    0x00000004l
+
+/*
+ * IDirect3DLight
+ */
+#undef INTERFACE
+#define INTERFACE IDirect3DLight
+DECLARE_INTERFACE_(IDirect3DLight, IUnknown)
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID* ppvObj) PURE;
+    STDMETHOD_(ULONG, AddRef) (THIS) PURE;
+    STDMETHOD_(ULONG, Release) (THIS) PURE;
+    /*** IDirect3DLight methods ***/
+    STDMETHOD(Initialize) (THIS_ LPDIRECT3D) PURE;
+    STDMETHOD(SetLight) (THIS_ LPD3DLIGHT) PURE;
+    STDMETHOD(GetLight) (THIS_ LPD3DLIGHT) PURE;
+};
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirect3DLight_QueryInterface(p, a, b) (p)->lpVtbl->QueryInterface(p, a, b)
+#define IDirect3DLight_AddRef(p)               (p)->lpVtbl->AddRef(p)
+#define IDirect3DLight_Release(p)              (p)->lpVtbl->Release(p)
+#define IDirect3DLight_Initialize(p, a)        (p)->lpVtbl->Initialize(p, a)
+#define IDirect3DLight_SetLight(p, a)          (p)->lpVtbl->SetLight(p, a)
+#define IDirect3DLight_GetLight(p, a)          (p)->lpVtbl->GetLight(p, a)
+#endif
+
+/*
+ * IDirect3DMaterial
+ */
+#undef INTERFACE
+#define INTERFACE IDirect3DMaterial
+DECLARE_INTERFACE_(IDirect3DMaterial, IUnknown)
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID* ppvObj) PURE;
+    STDMETHOD_(ULONG, AddRef) (THIS) PURE;
+    STDMETHOD_(ULONG, Release) (THIS) PURE;
+    /*** IDirect3DMaterial methods ***/
+    STDMETHOD(Initialize) (THIS_ LPDIRECT3D) PURE;
+    STDMETHOD(SetMaterial) (THIS_ LPD3DMATERIAL) PURE;
+    STDMETHOD(GetMaterial) (THIS_ LPD3DMATERIAL) PURE;
+    STDMETHOD(GetHandle) (THIS_ LPDIRECT3DDEVICE, LPD3DMATERIALHANDLE) PURE;
+    STDMETHOD_(HRESULT, Reserve) (THIS) PURE;
+    STDMETHOD_(HRESULT, Unreserve) (THIS) PURE;
+};
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirect3DMaterial_QueryInterface(p, a, b) (p)->lpVtbl->QueryInterface(p, a, b)
+#define IDirect3DMaterial_AddRef(p)               (p)->lpVtbl->AddRef(p)
+#define IDirect3DMaterial_Release(p)              (p)->lpVtbl->Release(p)
+#define IDirect3DMaterial_Initialize(p, a)        (p)->lpVtbl->Initialize(p, a)
+#define IDirect3DMaterial_SetMaterial(p, a)       (p)->lpVtbl->SetLight(p, a)
+#define IDirect3DMaterial_GetMaterial(p, a)       (p)->lpVtbl->GetLight(p, a)
+#define IDirect3DMaterial_GetHandle(p, a, b)      (p)->lpVtbl->GetHandle(p, a, b)
+#define IDirect3DMaterial_Reserve(p)              (p)->lpVtbl->Reserve(p)
+#define IDirect3DMaterial_Unreserve(p)            (p)->lpVtbl->Unreserve(p)
+#endif
+
+/*
+ * IDirect3DTexture
+ */
+#undef INTERFACE
+#define INTERFACE IDirect3DTexture
+DECLARE_INTERFACE_(IDirect3DTexture, IUnknown)
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID* ppvObj) PURE;
+    STDMETHOD_(ULONG, AddRef) (THIS) PURE;
+    STDMETHOD_(ULONG, Release) (THIS) PURE;
+    /*** IDirect3DTexture methods ***/
+    STDMETHOD(Initialize) (THIS_ LPDIRECT3DDEVICE, LPDIRECTDRAWSURFACE) PURE;
+    STDMETHOD(GetHandle) (THIS_ LPDIRECT3DDEVICE, LPD3DTEXTUREHANDLE) PURE;
+    STDMETHOD(PaletteChanged) (THIS_ DWORD, DWORD) PURE;
+    STDMETHOD(Load) (THIS_ LPDIRECT3DTEXTURE) PURE;
+    STDMETHOD_(HRESULT, Unload) (THIS) PURE;
+};
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirect3DTexture_QueryInterface(p, a, b) (p)->lpVtbl->QueryInterface(p, a, b)
+#define IDirect3DTexture_AddRef(p)               (p)->lpVtbl->AddRef(p)
+#define IDirect3DTexture_Release(p)              (p)->lpVtbl->Release(p)
+#define IDirect3DTexture_Initialize(p, a, b)     (p)->lpVtbl->Initialize(p, a, b)
+#define IDirect3DTexture_GetHandle(p, a, b)      (p)->lpVtbl->GetHandle(p, a, b)
+#define IDirect3DTexture_PaletteChanged(p, a, b) (p)->lpVtbl->PaletteChanged(p, a, b)
+#define IDirect3DTexture_Load(p, a)              (p)->lpVtbl->Load(p, a)
+#define IDirect3DTexture_Unload(p)               (p)->lpVtbl->Unload(p)
+#endif
+
+/*
+ * IDirect3DViewport
+ */
+#undef INTERFACE
+#define INTERFACE IDirect3DViewport
+DECLARE_INTERFACE_(IDirect3DViewport, IUnknown)
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID* ppvObj) PURE;
+    STDMETHOD_(ULONG, AddRef) (THIS) PURE;
+    STDMETHOD_(ULONG, Release) (THIS) PURE;
+    /*** IDirect3DViewport methods ***/
+    STDMETHOD(Initialize) (THIS_ LPDIRECT3D) PURE;
+    STDMETHOD(GetViewport) (THIS_ LPD3DVIEWPORT) PURE;
+    STDMETHOD(SetViewport) (THIS_ LPD3DVIEWPORT) PURE;
+    STDMETHOD(TransformVertices) (THIS_ DWORD, LPD3DTRANSFORMDATA, DWORD, LPDWORD) PURE;
+    STDMETHOD(LightElements) (THIS_ DWORD, LPD3DLIGHTDATA) PURE;
+    STDMETHOD(SetBackground) (THIS_ D3DMATERIALHANDLE) PURE;
+    STDMETHOD(GetBackground) (THIS_ LPD3DMATERIALHANDLE, LPBOOL) PURE;
+    STDMETHOD(SetBackgroundDepth) (THIS_ LPDIRECTDRAWSURFACE) PURE;
+    STDMETHOD(GetBackgroundDepth) (THIS_ LPDIRECTDRAWSURFACE*, LPBOOL) PURE;
+    STDMETHOD(Clear) (THIS_ DWORD, LPD3DRECT, DWORD) PURE;
+    STDMETHOD(AddLight) (THIS_ LPDIRECT3DLIGHT) PURE;
+    STDMETHOD(DeleteLight) (THIS_ LPDIRECT3DLIGHT) PURE;
+    STDMETHOD(NextLight) (THIS_ LPDIRECT3DLIGHT, LPDIRECT3DLIGHT*, DWORD) PURE;
+};
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirect3DViewport_QueryInterface(p, a, b)          (p)->lpVtbl->QueryInterface(p, a, b)
+#define IDirect3DViewport_AddRef(p)                        (p)->lpVtbl->AddRef(p)
+#define IDirect3DViewport_Release(p)                       (p)->lpVtbl->Release(p)
+#define IDirect3DViewport_Initialize(p, a)                 (p)->lpVtbl->Initialize(p, a)
+#define IDirect3DViewport_GetViewport(p, a)                (p)->lpVtbl->GetViewport(p, a)
+#define IDirect3DViewport_SetViewport(p, a)                (p)->lpVtbl->SetViewport(p, a)
+#define IDirect3DViewport_TransformVertices(p, a, b, c, d) (p)->lpVtbl->TransformVertices(p, a, b, c, d)
+#define IDirect3DViewport_LightElements(p, a, b)           (p)->lpVtbl->LightElements(p, a, b)
+#define IDirect3DViewport_SetBackground(p, a)              (p)->lpVtbl->SetBackground(p, a)
+#define IDirect3DViewport_GetBackground(p, a, b)           (p)->lpVtbl->GetBackground(p, a, b)
+#define IDirect3DViewport_Clear(p, a, b, c)                (p)->lpVtbl->Clear(p, a, b, c)
+#define IDirect3DViewport_AddLight(p, a)                   (p)->lpVtbl->AddLight(p, a)
+#define IDirect3DViewport_DeleteLight(p, a)                (p)->lpVtbl->DeleteLight(p, a)
+#define IDirect3DViewport_NextLight(p, a, b, c)            (p)->lpVtbl->NextLight(p, a, b, c)
+#endif
+
+/*
+ * Direct3D Errors
+ * DirectDraw error codes are used when errors not specified here.
+ */
+#define D3D_OK                          DD_OK
+#define D3DERR_BADMAJORVERSION          MAKE_DDHRESULT(700)
+#define D3DERR_BADMINORVERSION          MAKE_DDHRESULT(701)
+
+#define D3DERR_EXECUTE_CREATE_FAILED    MAKE_DDHRESULT(710)
+#define D3DERR_EXECUTE_DESTROY_FAILED   MAKE_DDHRESULT(711)
+#define D3DERR_EXECUTE_LOCK_FAILED      MAKE_DDHRESULT(712)
+#define D3DERR_EXECUTE_UNLOCK_FAILED    MAKE_DDHRESULT(713)
+#define D3DERR_EXECUTE_LOCKED           MAKE_DDHRESULT(714)
+#define D3DERR_EXECUTE_NOT_LOCKED       MAKE_DDHRESULT(715)
+
+#define D3DERR_EXECUTE_FAILED           MAKE_DDHRESULT(716)
+#define D3DERR_EXECUTE_CLIPPED_FAILED   MAKE_DDHRESULT(717)
+
+#define D3DERR_TEXTURE_NO_SUPPORT       MAKE_DDHRESULT(720)
+#define D3DERR_TEXTURE_CREATE_FAILED    MAKE_DDHRESULT(721)
+#define D3DERR_TEXTURE_DESTROY_FAILED   MAKE_DDHRESULT(722)
+#define D3DERR_TEXTURE_LOCK_FAILED      MAKE_DDHRESULT(723)
+#define D3DERR_TEXTURE_UNLOCK_FAILED    MAKE_DDHRESULT(724)
+#define D3DERR_TEXTURE_LOAD_FAILED      MAKE_DDHRESULT(725)
+#define D3DERR_TEXTURE_SWAP_FAILED      MAKE_DDHRESULT(726)
+#define D3DERR_TEXTURE_LOCKED           MAKE_DDHRESULT(727)
+#define D3DERR_TEXTURE_NOT_LOCKED       MAKE_DDHRESULT(728)
+#define D3DERR_TEXTURE_GETSURF_FAILED   MAKE_DDHRESULT(729)
+
+#define D3DERR_MATRIX_CREATE_FAILED     MAKE_DDHRESULT(730)
+#define D3DERR_MATRIX_DESTROY_FAILED    MAKE_DDHRESULT(731)
+#define D3DERR_MATRIX_SETDATA_FAILED    MAKE_DDHRESULT(732)
+#define D3DERR_MATRIX_GETDATA_FAILED    MAKE_DDHRESULT(733)
+#define D3DERR_SETVIEWPORTDATA_FAILED   MAKE_DDHRESULT(734)
+
+#define D3DERR_MATERIAL_CREATE_FAILED   MAKE_DDHRESULT(740)
+#define D3DERR_MATERIAL_DESTROY_FAILED  MAKE_DDHRESULT(741)
+#define D3DERR_MATERIAL_SETDATA_FAILED  MAKE_DDHRESULT(742)
+#define D3DERR_MATERIAL_GETDATA_FAILED  MAKE_DDHRESULT(743)
+
+#define D3DERR_LIGHT_SET_FAILED         MAKE_DDHRESULT(750)
+
+#define D3DERR_SCENE_IN_SCENE           MAKE_DDHRESULT(760)
+#define D3DERR_SCENE_NOT_IN_SCENE       MAKE_DDHRESULT(761)
+#define D3DERR_SCENE_BEGIN_FAILED       MAKE_DDHRESULT(762)
+#define D3DERR_SCENE_END_FAILED         MAKE_DDHRESULT(763)
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif /* _D3D_H_ */
--- /dev/null
+++ b/QW/dxsdk/sdk/inc/d3dcaps.h
@@ -1,0 +1,290 @@
+/*==========================================================================;
+ *
+ *  Copyright (C) 1995-1996 Microsoft Corporation.  All Rights Reserved.
+ *
+ *  File:       d3dcaps.h
+ *  Content:    Direct3D capabilities include file
+ *
+ ***************************************************************************/
+
+#ifndef _D3DCAPS_H
+#define _D3DCAPS_H
+
+/* 
+ *  Pull in DirectDraw include file automatically:
+ */
+#include <ddraw.h>
+
+#pragma pack(4)
+
+/* Description of capabilities of transform */
+
+typedef struct _D3DTRANSFORMCAPS {
+    DWORD dwSize;
+    DWORD dwCaps;
+} D3DTRANSFORMCAPS, *LPD3DTRANSFORMCAPS;
+
+#define D3DTRANSFORMCAPS_CLIP           0x00000001L /* Will clip whilst transforming */
+
+/* Description of capabilities of lighting */
+
+typedef struct _D3DLIGHTINGCAPS {
+    DWORD dwSize;
+    DWORD dwCaps;                   /* Lighting caps */
+    DWORD dwLightingModel;          /* Lighting model - RGB or mono */
+    DWORD dwNumLights;              /* Number of lights that can be handled */
+} D3DLIGHTINGCAPS, *LPD3DLIGHTINGCAPS;
+
+#define D3DLIGHTINGMODEL_RGB            0x00000001L
+#define D3DLIGHTINGMODEL_MONO           0x00000002L
+
+#define D3DLIGHTCAPS_POINT              0x00000001L /* Point lights supported */
+#define D3DLIGHTCAPS_SPOT               0x00000002L /* Spot lights supported */
+#define D3DLIGHTCAPS_DIRECTIONAL        0x00000004L /* Directional lights supported */
+#define D3DLIGHTCAPS_PARALLELPOINT      0x00000008L /* Parallel point lights supported */
+#define D3DLIGHTCAPS_GLSPOT             0x00000010L /* GL syle spot lights supported */
+
+/* Description of capabilities for each primitive type */
+
+typedef struct _D3DPrimCaps {
+    DWORD dwSize;
+    DWORD dwMiscCaps;                 /* Capability flags */
+    DWORD dwRasterCaps;
+    DWORD dwZCmpCaps;
+    DWORD dwSrcBlendCaps;
+    DWORD dwDestBlendCaps;
+    DWORD dwAlphaCmpCaps;
+    DWORD dwShadeCaps;
+    DWORD dwTextureCaps;
+    DWORD dwTextureFilterCaps;
+    DWORD dwTextureBlendCaps;
+    DWORD dwTextureAddressCaps;
+    DWORD dwStippleWidth;             /* maximum width and height of */
+    DWORD dwStippleHeight;            /* of supported stipple (up to 32x32) */
+} D3DPRIMCAPS, *LPD3DPRIMCAPS;
+
+/* D3DPRIMCAPS dwMiscCaps */
+
+#define D3DPMISCCAPS_MASKPLANES         0x00000001L
+#define D3DPMISCCAPS_MASKZ              0x00000002L
+#define D3DPMISCCAPS_LINEPATTERNREP     0x00000004L
+#define D3DPMISCCAPS_CONFORMANT         0x00000008L
+#define D3DPMISCCAPS_CULLNONE           0x00000010L
+#define D3DPMISCCAPS_CULLCW             0x00000020L
+#define D3DPMISCCAPS_CULLCCW            0x00000040L
+
+/* D3DPRIMCAPS dwRasterCaps */
+
+#define D3DPRASTERCAPS_DITHER           0x00000001L
+#define D3DPRASTERCAPS_ROP2             0x00000002L
+#define D3DPRASTERCAPS_XOR              0x00000004L
+#define D3DPRASTERCAPS_PAT              0x00000008L
+#define D3DPRASTERCAPS_ZTEST            0x00000010L
+#define D3DPRASTERCAPS_SUBPIXEL         0x00000020L
+#define D3DPRASTERCAPS_SUBPIXELX        0x00000040L
+#define D3DPRASTERCAPS_FOGVERTEX        0x00000080L
+#define D3DPRASTERCAPS_FOGTABLE         0x00000100L
+#define D3DPRASTERCAPS_STIPPLE          0x00000200L
+
+/* D3DPRIMCAPS dwZCmpCaps, dwAlphaCmpCaps */
+
+#define D3DPCMPCAPS_NEVER               0x00000001L
+#define D3DPCMPCAPS_LESS                0x00000002L
+#define D3DPCMPCAPS_EQUAL               0x00000004L
+#define D3DPCMPCAPS_LESSEQUAL           0x00000008L
+#define D3DPCMPCAPS_GREATER             0x00000010L
+#define D3DPCMPCAPS_NOTEQUAL            0x00000020L
+#define D3DPCMPCAPS_GREATEREQUAL        0x00000040L
+#define D3DPCMPCAPS_ALWAYS              0x00000080L
+
+/* D3DPRIMCAPS dwSourceBlendCaps, dwDestBlendCaps */
+
+#define D3DPBLENDCAPS_ZERO              0x00000001L
+#define D3DPBLENDCAPS_ONE               0x00000002L
+#define D3DPBLENDCAPS_SRCCOLOR          0x00000004L
+#define D3DPBLENDCAPS_INVSRCCOLOR       0x00000008L
+#define D3DPBLENDCAPS_SRCALPHA          0x00000010L
+#define D3DPBLENDCAPS_INVSRCALPHA       0x00000020L
+#define D3DPBLENDCAPS_DESTALPHA         0x00000040L
+#define D3DPBLENDCAPS_INVDESTALPHA      0x00000080L
+#define D3DPBLENDCAPS_DESTCOLOR         0x00000100L
+#define D3DPBLENDCAPS_INVDESTCOLOR      0x00000200L
+#define D3DPBLENDCAPS_SRCALPHASAT       0x00000400L
+#define D3DPBLENDCAPS_BOTHSRCALPHA      0x00000800L
+#define D3DPBLENDCAPS_BOTHINVSRCALPHA   0x00001000L
+
+/* D3DPRIMCAPS dwShadeCaps */
+
+#define D3DPSHADECAPS_COLORFLATMONO             0x00000001L
+#define D3DPSHADECAPS_COLORFLATRGB              0x00000002L
+#define D3DPSHADECAPS_COLORGOURAUDMONO          0x00000004L
+#define D3DPSHADECAPS_COLORGOURAUDRGB           0x00000008L
+#define D3DPSHADECAPS_COLORPHONGMONO            0x00000010L
+#define D3DPSHADECAPS_COLORPHONGRGB             0x00000020L
+
+#define D3DPSHADECAPS_SPECULARFLATMONO          0x00000040L
+#define D3DPSHADECAPS_SPECULARFLATRGB           0x00000080L
+#define D3DPSHADECAPS_SPECULARGOURAUDMONO       0x00000100L
+#define D3DPSHADECAPS_SPECULARGOURAUDRGB        0x00000200L
+#define D3DPSHADECAPS_SPECULARPHONGMONO         0x00000400L
+#define D3DPSHADECAPS_SPECULARPHONGRGB          0x00000800L
+
+#define D3DPSHADECAPS_ALPHAFLATBLEND            0x00001000L
+#define D3DPSHADECAPS_ALPHAFLATSTIPPLED         0x00002000L
+#define D3DPSHADECAPS_ALPHAGOURAUDBLEND         0x00004000L
+#define D3DPSHADECAPS_ALPHAGOURAUDSTIPPLED      0x00008000L
+#define D3DPSHADECAPS_ALPHAPHONGBLEND           0x00010000L
+#define D3DPSHADECAPS_ALPHAPHONGSTIPPLED        0x00020000L
+
+#define D3DPSHADECAPS_FOGFLAT                   0x00040000L
+#define D3DPSHADECAPS_FOGGOURAUD                0x00080000L
+#define D3DPSHADECAPS_FOGPHONG                  0x00100000L
+
+/* D3DPRIMCAPS dwTextureCaps */
+
+#define D3DPTEXTURECAPS_PERSPECTIVE     0x00000001L
+#define D3DPTEXTURECAPS_POW2            0x00000002L
+#define D3DPTEXTURECAPS_ALPHA           0x00000004L
+#define D3DPTEXTURECAPS_TRANSPARENCY    0x00000008L
+#define D3DPTEXTURECAPS_BORDER          0x00000010L
+#define D3DPTEXTURECAPS_SQUAREONLY      0x00000020L
+
+/* D3DPRIMCAPS dwTextureFilterCaps */
+
+#define D3DPTFILTERCAPS_NEAREST         0x00000001L
+#define D3DPTFILTERCAPS_LINEAR          0x00000002L
+#define D3DPTFILTERCAPS_MIPNEAREST      0x00000004L
+#define D3DPTFILTERCAPS_MIPLINEAR       0x00000008L
+#define D3DPTFILTERCAPS_LINEARMIPNEAREST 0x00000010L
+#define D3DPTFILTERCAPS_LINEARMIPLINEAR 0x00000020L
+
+/* D3DPRIMCAPS dwTextureBlendCaps */
+
+#define D3DPTBLENDCAPS_DECAL            0x00000001L
+#define D3DPTBLENDCAPS_MODULATE         0x00000002L
+#define D3DPTBLENDCAPS_DECALALPHA       0x00000004L
+#define D3DPTBLENDCAPS_MODULATEALPHA    0x00000008L
+#define D3DPTBLENDCAPS_DECALMASK        0x00000010L
+#define D3DPTBLENDCAPS_MODULATEMASK     0x00000020L
+#define D3DPTBLENDCAPS_COPY             0x00000040L
+
+/* D3DPRIMCAPS dwTextureAddressCaps */
+#define D3DPTADDRESSCAPS_WRAP           0x00000001L
+#define D3DPTADDRESSCAPS_MIRROR         0x00000002L
+#define D3DPTADDRESSCAPS_CLAMP          0x00000004L
+
+/*
+ * Description for a device.
+ * This is used to describe a device that is to be created or to query
+ * the current device.
+ */
+typedef struct _D3DDeviceDesc {
+    DWORD            dwSize;                 /* Size of D3DDEVICEDESC structure */
+    DWORD            dwFlags;                /* Indicates which fields have valid data */
+    D3DCOLORMODEL    dcmColorModel;          /* Color model of device */
+    DWORD            dwDevCaps;              /* Capabilities of device */
+    D3DTRANSFORMCAPS dtcTransformCaps;       /* Capabilities of transform */
+    BOOL             bClipping;              /* Device can do 3D clipping */
+    D3DLIGHTINGCAPS  dlcLightingCaps;        /* Capabilities of lighting */
+    D3DPRIMCAPS      dpcLineCaps;
+    D3DPRIMCAPS      dpcTriCaps;
+    DWORD            dwDeviceRenderBitDepth; /* One of DDBB_8, 16, etc.. */
+    DWORD            dwDeviceZBufferBitDepth;/* One of DDBD_16, 32, etc.. */
+    DWORD            dwMaxBufferSize;        /* Maximum execute buffer size */
+    DWORD            dwMaxVertexCount;       /* Maximum vertex count */
+} D3DDEVICEDESC, *LPD3DDEVICEDESC;
+
+typedef HRESULT (FAR PASCAL * LPD3DENUMDEVICESCALLBACK)(LPGUID lpGuid, LPSTR lpDeviceDescription, LPSTR lpDeviceName, LPD3DDEVICEDESC, LPD3DDEVICEDESC, LPVOID);
+
+/* D3DDEVICEDESC dwFlags indicating valid fields */
+
+#define D3DDD_COLORMODEL            0x00000001L /* dcmColorModel is valid */
+#define D3DDD_DEVCAPS               0x00000002L /* dwDevCaps is valid */
+#define D3DDD_TRANSFORMCAPS         0x00000004L /* dtcTransformCaps is valid */
+#define D3DDD_LIGHTINGCAPS          0x00000008L /* dlcLightingCaps is valid */
+#define D3DDD_BCLIPPING             0x00000010L /* bClipping is valid */
+#define D3DDD_LINECAPS              0x00000020L /* dpcLineCaps is valid */
+#define D3DDD_TRICAPS               0x00000040L /* dpcTriCaps is valid */
+#define D3DDD_DEVICERENDERBITDEPTH  0x00000080L /* dwDeviceRenderBitDepth is valid */
+#define D3DDD_DEVICEZBUFFERBITDEPTH 0x00000100L /* dwDeviceZBufferBitDepth is valid */
+#define D3DDD_MAXBUFFERSIZE         0x00000200L /* dwMaxBufferSize is valid */
+#define D3DDD_MAXVERTEXCOUNT        0x00000400L /* dwMaxVertexCount is valid */
+
+/* D3DDEVICEDESC dwDevCaps flags */
+
+#define D3DDEVCAPS_FLOATTLVERTEX        0x00000001L /* Device accepts floating point */
+                                                    /* for post-transform vertex data */
+#define D3DDEVCAPS_SORTINCREASINGZ      0x00000002L /* Device needs data sorted for increasing Z*/
+#define D3DDEVCAPS_SORTDECREASINGZ      0X00000004L /* Device needs data sorted for decreasing Z*/
+#define D3DDEVCAPS_SORTEXACT            0x00000008L /* Device needs data sorted exactly */
+
+#define D3DDEVCAPS_EXECUTESYSTEMMEMORY  0x00000010L /* Device can use execute buffers from system memory */
+#define D3DDEVCAPS_EXECUTEVIDEOMEMORY   0x00000020L /* Device can use execute buffers from video memory */
+#define D3DDEVCAPS_TLVERTEXSYSTEMMEMORY 0x00000040L /* Device can use TL buffers from system memory */
+#define D3DDEVCAPS_TLVERTEXVIDEOMEMORY  0x00000080L /* Device can use TL buffers from video memory */
+#define D3DDEVCAPS_TEXTURESYSTEMMEMORY  0x00000100L /* Device can texture from system memory */
+#define D3DDEVCAPS_TEXTUREVIDEOMEMORY   0x00000200L /* Device can texture from device memory */
+
+#define D3DFDS_COLORMODEL        0x00000001L /* Match color model */
+#define D3DFDS_GUID              0x00000002L /* Match guid */
+#define D3DFDS_HARDWARE          0x00000004L /* Match hardware/software */
+#define D3DFDS_TRIANGLES         0x00000008L /* Match in triCaps */
+#define D3DFDS_LINES             0x00000010L /* Match in lineCaps  */
+#define D3DFDS_MISCCAPS          0x00000020L /* Match primCaps.dwMiscCaps */
+#define D3DFDS_RASTERCAPS        0x00000040L /* Match primCaps.dwRasterCaps */
+#define D3DFDS_ZCMPCAPS          0x00000080L /* Match primCaps.dwZCmpCaps */
+#define D3DFDS_ALPHACMPCAPS      0x00000100L /* Match primCaps.dwAlphaCmpCaps */
+#define D3DFDS_SRCBLENDCAPS      0x00000200L /* Match primCaps.dwSourceBlendCaps */
+#define D3DFDS_DSTBLENDCAPS      0x00000400L /* Match primCaps.dwDestBlendCaps */
+#define D3DFDS_SHADECAPS         0x00000800L /* Match primCaps.dwShadeCaps */
+#define D3DFDS_TEXTURECAPS       0x00001000L /* Match primCaps.dwTextureCaps */
+#define D3DFDS_TEXTUREFILTERCAPS 0x00002000L /* Match primCaps.dwTextureFilterCaps */
+#define D3DFDS_TEXTUREBLENDCAPS  0x00004000L /* Match primCaps.dwTextureBlendCaps */
+#define D3DFDS_TEXTUREADDRESSCAPS  0x00008000L /* Match primCaps.dwTextureBlendCaps */
+
+/*
+ * FindDevice arguments
+ */
+typedef struct _D3DFINDDEVICESEARCH {
+    DWORD               dwSize;
+    DWORD               dwFlags;
+    BOOL                bHardware;
+    D3DCOLORMODEL       dcmColorModel;
+    GUID                guid;
+    DWORD               dwCaps;
+    D3DPRIMCAPS         dpcPrimCaps;
+} D3DFINDDEVICESEARCH, *LPD3DFINDDEVICESEARCH;
+
+typedef struct _D3DFINDDEVICERESULT {
+    DWORD               dwSize;
+    GUID                guid;           /* guid which matched */
+    D3DDEVICEDESC       ddHwDesc;               /* hardware D3DDEVICEDESC */
+    D3DDEVICEDESC       ddSwDesc;       /* software D3DDEVICEDESC */
+} D3DFINDDEVICERESULT, *LPD3DFINDDEVICERESULT;
+
+/*
+ * Description of execute buffer.
+ */
+typedef struct _D3DExecuteBufferDesc {
+    DWORD               dwSize;         /* size of this structure */
+    DWORD               dwFlags;        /* flags indicating which fields are valid */
+    DWORD               dwCaps;         /* capabilities of execute buffer */
+    DWORD               dwBufferSize;   /* size of execute buffer data */
+    LPVOID              lpData;         /* pointer to actual data */
+} D3DEXECUTEBUFFERDESC, *LPD3DEXECUTEBUFFERDESC;
+
+/* D3DEXECUTEBUFFER dwFlags indicating valid fields */
+
+#define D3DDEB_BUFSIZE          0x00000001l     /* buffer size valid */
+#define D3DDEB_CAPS             0x00000002l     /* caps valid */
+#define D3DDEB_LPDATA           0x00000004l     /* lpData valid */
+
+/* D3DEXECUTEBUFFER dwCaps */
+
+#define D3DDEBCAPS_SYSTEMMEMORY 0x00000001l     /* buffer in system memory */
+#define D3DDEBCAPS_VIDEOMEMORY  0x00000002l     /* buffer in device memory */
+#define D3DDEBCAPS_MEM (D3DDEBCAPS_SYSTEMMEMORY|D3DDEBCAPS_VIDEOMEMORY)
+
+#pragma pack()
+
+#endif /* _D3DCAPS_H_ */
--- /dev/null
+++ b/QW/dxsdk/sdk/inc/d3drm.h
@@ -1,0 +1,134 @@
+/*==========================================================================;
+ *
+ *  Copyright (C) 1995-1996 Microsoft Corporation.  All Rights Reserved.
+ *
+ *  File:       d3drm.h
+ *  Content:    Direct3DRM include file
+ *
+ ***************************************************************************/
+
+#ifndef __D3DRM_H__
+#define __D3DRM_H__
+
+#include "d3drmobj.h"
+
+#ifdef __cplusplus
+extern "C" {
+struct IDirect3DRM;
+#endif
+
+
+typedef void (*D3DRMDEVICEPALETTECALLBACK)
+    (LPDIRECT3DRMDEVICE lpDirect3DRMDev, LPVOID lpArg, DWORD dwIndex, LONG red, LONG green, LONG blue);
+
+DEFINE_GUID(IID_IDirect3DRM,    0x2bc49361, 0x8327, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+WIN_TYPES(IDirect3DRM, DIRECT3DRM);
+
+
+/* Create a Direct3DRM API */
+STDAPI Direct3DRMCreate(LPDIRECT3DRM FAR *lplpDirect3DRM);
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRM
+
+DECLARE_INTERFACE_(IDirect3DRM, IUnknown)
+{
+    IUNKNOWN_METHODS(PURE);
+
+    STDMETHOD(CreateObject)
+        (THIS_ REFCLSID rclsid, LPUNKNOWN pUnkOuter, REFIID riid, LPVOID FAR* ppv) PURE;
+    STDMETHOD(CreateFrame)      (THIS_ LPDIRECT3DRMFRAME, LPDIRECT3DRMFRAME *) PURE;
+    STDMETHOD(CreateMesh)       (THIS_ LPDIRECT3DRMMESH *) PURE;
+    STDMETHOD(CreateMeshBuilder)(THIS_ LPDIRECT3DRMMESHBUILDER *) PURE;
+    STDMETHOD(CreateFace)       (THIS_ LPDIRECT3DRMFACE *) PURE;
+    STDMETHOD(CreateAnimation)  (THIS_ LPDIRECT3DRMANIMATION *) PURE;
+    STDMETHOD(CreateAnimationSet)(THIS_ LPDIRECT3DRMANIMATIONSET *) PURE;
+    STDMETHOD(CreateTexture)    (THIS_ LPD3DRMIMAGE, LPDIRECT3DRMTEXTURE *) PURE;
+    STDMETHOD(CreateLight)      (THIS_ D3DRMLIGHTTYPE, D3DCOLOR, LPDIRECT3DRMLIGHT *) PURE;
+    STDMETHOD(CreateLightRGB)
+        (THIS_ D3DRMLIGHTTYPE, D3DVALUE, D3DVALUE, D3DVALUE, LPDIRECT3DRMLIGHT *) PURE;
+    STDMETHOD(CreateMaterial)   (THIS_ D3DVALUE, LPDIRECT3DRMMATERIAL *) PURE;
+    STDMETHOD(CreateDevice)     (THIS_ DWORD, DWORD, LPDIRECT3DRMDEVICE *) PURE;
+
+    /* Create a Windows Device using DirectDraw surfaces */
+    STDMETHOD(CreateDeviceFromSurface)
+    (   THIS_ LPGUID lpGUID, LPDIRECTDRAW lpDD,
+        LPDIRECTDRAWSURFACE lpDDSBack, LPDIRECT3DRMDEVICE *
+    ) PURE;
+
+    /* Create a Windows Device using D3D objects */
+    STDMETHOD(CreateDeviceFromD3D)
+    (   THIS_ LPDIRECT3D lpD3D, LPDIRECT3DDEVICE lpD3DDev,
+        LPDIRECT3DRMDEVICE *
+    ) PURE;
+
+    STDMETHOD(CreateDeviceFromClipper)
+    (   THIS_ LPDIRECTDRAWCLIPPER lpDDClipper, LPGUID lpGUID,
+        int width, int height, LPDIRECT3DRMDEVICE *) PURE;
+
+    STDMETHOD(CreateTextureFromSurface)(THIS_ LPDIRECTDRAWSURFACE lpDDS, LPDIRECT3DRMTEXTURE *) PURE;
+   
+    STDMETHOD(CreateShadow)
+    (   THIS_ LPDIRECT3DRMVISUAL, LPDIRECT3DRMLIGHT,
+        D3DVALUE px, D3DVALUE py, D3DVALUE pz,
+        D3DVALUE nx, D3DVALUE ny, D3DVALUE nz,
+        LPDIRECT3DRMVISUAL *
+    ) PURE;
+    STDMETHOD(CreateViewport)
+    (   THIS_ LPDIRECT3DRMDEVICE, LPDIRECT3DRMFRAME, DWORD, DWORD,
+        DWORD, DWORD, LPDIRECT3DRMVIEWPORT *
+    ) PURE;
+    STDMETHOD(CreateWrap)
+    (   THIS_ D3DRMWRAPTYPE, LPDIRECT3DRMFRAME,
+        D3DVALUE ox, D3DVALUE oy, D3DVALUE oz,
+        D3DVALUE dx, D3DVALUE dy, D3DVALUE dz,
+        D3DVALUE ux, D3DVALUE uy, D3DVALUE uz,
+        D3DVALUE ou, D3DVALUE ov,
+        D3DVALUE su, D3DVALUE sv,
+        LPDIRECT3DRMWRAP *
+    ) PURE;
+    STDMETHOD(CreateUserVisual) (THIS_ D3DRMUSERVISUALCALLBACK, LPVOID lPArg, LPDIRECT3DRMUSERVISUAL *) PURE;
+    STDMETHOD(LoadTexture)      (THIS_ const char *, LPDIRECT3DRMTEXTURE *) PURE;
+    STDMETHOD(LoadTextureFromResource)  (THIS_ HRSRC rs, LPDIRECT3DRMTEXTURE *) PURE;
+   
+    STDMETHOD(SetSearchPath)    (THIS_ LPCSTR) PURE;
+    STDMETHOD(AddSearchPath)    (THIS_ LPCSTR) PURE;
+    STDMETHOD(GetSearchPath)    (THIS_ DWORD *size_return, LPSTR path_return);
+    //STDMETHOD(GetSearchPath)  (THIS_ int *return_count, char ***return_path) PURE;
+    STDMETHOD(SetDefaultTextureColors)(THIS_ DWORD) PURE;
+    STDMETHOD(SetDefaultTextureShades)(THIS_ DWORD) PURE;
+   
+    STDMETHOD(GetDevices)       (THIS_ LPDIRECT3DRMDEVICEARRAY *) PURE;
+    STDMETHOD(GetNamedObject)   (THIS_ const char *, LPDIRECT3DRMOBJECT *) PURE;
+   
+    STDMETHOD(EnumerateObjects) (THIS_ D3DRMOBJECTCALLBACK, LPVOID) PURE;
+   
+    STDMETHOD(Load)             
+    (   THIS_ LPVOID, LPVOID, LPIID *, DWORD, D3DRMLOADOPTIONS,
+        D3DRMLOADCALLBACK, LPVOID, D3DRMLOADTEXTURECALLBACK, LPVOID,
+        LPDIRECT3DRMFRAME
+    ) PURE;
+    STDMETHOD(Tick)             (THIS_ D3DVALUE) PURE;
+};
+
+#define D3DRM_OK                        DD_OK
+#define D3DRMERR_BADOBJECT              MAKE_DDHRESULT(781)
+#define D3DRMERR_BADTYPE                MAKE_DDHRESULT(782)
+#define D3DRMERR_BADALLOC               MAKE_DDHRESULT(783)
+#define D3DRMERR_FACEUSED               MAKE_DDHRESULT(784)
+#define D3DRMERR_NOTFOUND               MAKE_DDHRESULT(785)
+#define D3DRMERR_NOTDONEYET             MAKE_DDHRESULT(786)
+#define D3DRMERR_FILENOTFOUND           MAKE_DDHRESULT(787)
+#define D3DRMERR_BADFILE                MAKE_DDHRESULT(788)
+#define D3DRMERR_BADDEVICE              MAKE_DDHRESULT(789)
+#define D3DRMERR_BADVALUE               MAKE_DDHRESULT(790)
+#define D3DRMERR_BADMAJORVERSION        MAKE_DDHRESULT(791)
+#define D3DRMERR_BADMINORVERSION        MAKE_DDHRESULT(792)
+#define D3DRMERR_UNABLETOEXECUTE        MAKE_DDHRESULT(793)
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif /* _D3DRMAPI_H_ */
+
--- /dev/null
+++ b/QW/dxsdk/sdk/inc/d3drmdef.h
@@ -1,0 +1,402 @@
+/*==========================================================================;
+ *
+ *  Copyright (C) 1995-1996 Microsoft Corporation.  All Rights Reserved.
+ *
+ *  File:       d3drm.h
+ *  Content:    Direct3DRM include file
+ *
+ ***************************************************************************/
+
+#ifndef __D3DRMDEFS_H__
+#define __D3DRMDEFS_H__
+
+#include <stddef.h>
+#include "d3dtypes.h"
+
+#ifdef WIN32
+#define D3DRMAPI  __stdcall
+#else
+#define D3DRMAPI
+#endif
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#ifndef TRUE
+#define FALSE 0
+#define TRUE 1
+#endif
+
+typedef struct _D3DRMVECTOR4D
+{   D3DVALUE x, y, z, w;
+} D3DRMVECTOR4D, *LPD3DRMVECTOR4D;
+
+typedef D3DVALUE D3DRMMATRIX4D[4][4];
+
+typedef struct _D3DRMQUATERNION
+{   D3DVALUE s;
+    D3DVECTOR v;
+} D3DRMQUATERNION, *LPD3DRMQUATERNION;
+
+typedef struct _D3DRMBOX
+{   D3DVECTOR min, max;
+} D3DRMBOX, *LPD3DRMBOX;
+
+typedef void (*D3DRMWRAPCALLBACK)
+    (LPD3DVECTOR, int* u, int* v, LPD3DVECTOR a, LPD3DVECTOR b, LPVOID);
+
+typedef enum _D3DRMLIGHTTYPE
+{   D3DRMLIGHT_AMBIENT,
+    D3DRMLIGHT_POINT,
+    D3DRMLIGHT_SPOT,
+    D3DRMLIGHT_DIRECTIONAL,
+    D3DRMLIGHT_PARALLELPOINT
+} D3DRMLIGHTTYPE, *LPD3DRMLIGHTTYPE;
+
+typedef enum _D3DRMSHADEMODE {
+    D3DRMSHADE_FLAT     = 0,
+    D3DRMSHADE_GOURAUD  = 1,
+    D3DRMSHADE_PHONG    = 2,
+
+    D3DRMSHADE_MASK     = 7,
+    D3DRMSHADE_MAX      = 8
+} D3DRMSHADEMODE, *LPD3DRMSHADEMODE;
+
+typedef enum _D3DRMLIGHTMODE {
+    D3DRMLIGHT_OFF      = 0 * D3DRMSHADE_MAX,
+    D3DRMLIGHT_ON       = 1 * D3DRMSHADE_MAX,
+
+    D3DRMLIGHT_MASK     = 7 * D3DRMSHADE_MAX,
+    D3DRMLIGHT_MAX      = 8 * D3DRMSHADE_MAX
+} D3DRMLIGHTMODE, *LPD3DRMLIGHTMODE;
+
+typedef enum _D3DRMFILLMODE {
+    D3DRMFILL_POINTS    = 0 * D3DRMLIGHT_MAX,
+    D3DRMFILL_WIREFRAME = 1 * D3DRMLIGHT_MAX,
+    D3DRMFILL_SOLID     = 2 * D3DRMLIGHT_MAX,
+
+    D3DRMFILL_MASK      = 7 * D3DRMLIGHT_MAX,
+    D3DRMFILL_MAX       = 8 * D3DRMLIGHT_MAX
+} D3DRMFILLMODE, *LPD3DRMFILLMODE;
+
+typedef DWORD D3DRMRENDERQUALITY, *LPD3DRMRENDERQUALITY;
+
+#define D3DRMRENDER_WIREFRAME   (D3DRMSHADE_FLAT+D3DRMLIGHT_OFF+D3DRMFILL_WIREFRAME)
+#define D3DRMRENDER_UNLITFLAT   (D3DRMSHADE_FLAT+D3DRMLIGHT_OFF+D3DRMFILL_SOLID)
+#define D3DRMRENDER_FLAT        (D3DRMSHADE_FLAT+D3DRMLIGHT_ON+D3DRMFILL_SOLID)
+#define D3DRMRENDER_GOURAUD     (D3DRMSHADE_GOURAUD+D3DRMLIGHT_ON+D3DRMFILL_SOLID)
+#define D3DRMRENDER_PHONG       (D3DRMSHADE_PHONG+D3DRMLIGHT_ON+D3DRMFILL_SOLID)
+
+typedef enum _D3DRMTEXTUREQUALITY
+{   D3DRMTEXTURE_NEAREST,               /* choose nearest texel */
+    D3DRMTEXTURE_LINEAR,                /* interpolate 4 texels */
+    D3DRMTEXTURE_MIPNEAREST,            /* nearest texel in nearest mipmap  */
+    D3DRMTEXTURE_MIPLINEAR,             /* interpolate 2 texels from 2 mipmaps */
+    D3DRMTEXTURE_LINEARMIPNEAREST,      /* interpolate 4 texels in nearest mipmap */
+    D3DRMTEXTURE_LINEARMIPLINEAR        /* interpolate 8 texels from 2 mipmaps */
+} D3DRMTEXTUREQUALITY, *LPD3DRMTEXTUREQUALITY;
+
+typedef enum _D3DRMCOMBINETYPE
+{   D3DRMCOMBINE_REPLACE,
+    D3DRMCOMBINE_BEFORE,
+    D3DRMCOMBINE_AFTER
+} D3DRMCOMBINETYPE, *LPD3DRMCOMBINETYPE;
+
+typedef D3DCOLORMODEL D3DRMCOLORMODEL, *LPD3DRMCOLORMODEL;
+
+typedef enum _D3DRMPALETTEFLAGS
+{   D3DRMPALETTE_FREE,                  /* renderer may use this entry freely */
+    D3DRMPALETTE_READONLY,              /* fixed but may be used by renderer */
+    D3DRMPALETTE_RESERVED               /* may not be used by renderer */
+} D3DRMPALETTEFLAGS, *LPD3DRMPALETTEFLAGS;
+
+typedef struct _D3DRMPALETTEENTRY
+{   unsigned char red;          /* 0 .. 255 */
+    unsigned char green;        /* 0 .. 255 */
+    unsigned char blue;         /* 0 .. 255 */
+    unsigned char flags;        /* one of D3DRMPALETTEFLAGS */
+} D3DRMPALETTEENTRY, *LPD3DRMPALETTEENTRY;
+
+typedef struct _D3DRMIMAGE
+{   int width, height;          /* width and height in pixels */
+    int aspectx, aspecty;       /* aspect ratio for non-square pixels */
+    int depth;                  /* bits per pixel */
+    int rgb;                    /* if false, pixels are indices into a
+                                   palette otherwise, pixels encode
+                                   RGB values. */
+    int bytes_per_line;         /* number of bytes of memory for a
+                                   scanline. This must be a multiple
+                                   of 4. */
+    void* buffer1;              /* memory to render into (first buffer). */
+    void* buffer2;              /* second rendering buffer for double
+                                   buffering, set to NULL for single
+                                   buffering. */
+    unsigned long red_mask;
+    unsigned long green_mask;
+    unsigned long blue_mask;
+    unsigned long alpha_mask;   /* if rgb is true, these are masks for
+                                   the red, green and blue parts of a
+                                   pixel.  Otherwise, these are masks
+                                   for the significant bits of the
+                                   red, green and blue elements in the
+                                   palette.  For instance, most SVGA
+                                   displays use 64 intensities of red,
+                                   green and blue, so the masks should
+                                   all be set to 0xfc. */
+    int palette_size;           /* number of entries in palette */
+    D3DRMPALETTEENTRY* palette; /* description of the palette (only if
+                                   rgb is false).  Must be (1<<depth)
+                                   elements. */
+} D3DRMIMAGE, *LPD3DRMIMAGE;
+
+typedef enum _D3DRMWRAPTYPE
+{   D3DRMWRAP_FLAT,
+    D3DRMWRAP_CYLINDER,
+    D3DRMWRAP_SPHERE,
+    D3DRMWRAP_CHROME
+} D3DRMWRAPTYPE, *LPD3DRMWRAPTYPE;
+
+#define D3DRMWIREFRAME_CULL             1 /* cull backfaces */
+#define D3DRMWIREFRAME_HIDDENLINE       2 /* lines are obscured by closer objects */
+
+typedef enum _D3DRMPROJECTIONTYPE
+{   D3DRMPROJECT_PERSPECTIVE,
+    D3DRMPROJECT_ORTHOGRAPHIC
+} D3DRMPROJECTIONTYPE, *LPD3DRMPROJECTIONTYPE;
+
+typedef enum _D3DRMXOFFORMAT
+{   D3DRMXOF_BINARY,
+    D3DRMXOF_COMPRESSED,
+    D3DRMXOF_TEXT
+} D3DRMXOFFORMAT, *LPD3DRMXOFFORMAT;
+
+typedef DWORD D3DRMSAVEOPTIONS;
+#define D3DRMXOFSAVE_NORMALS 1
+#define D3DRMXOFSAVE_TEXTURECOORDINATES 2
+#define D3DRMXOFSAVE_MATERIALS 4
+#define D3DRMXOFSAVE_TEXTURENAMES 8
+#define D3DRMXOFSAVE_ALL 15
+
+typedef enum _D3DRMCOLORSOURCE
+{   D3DRMCOLOR_FROMFACE,
+    D3DRMCOLOR_FROMVERTEX
+} D3DRMCOLORSOURCE, *LPD3DRMCOLORSOURCE;
+
+typedef enum _D3DRMFRAMECONSTRAINT
+{   D3DRMCONSTRAIN_Z,           /* use only X and Y rotations */
+    D3DRMCONSTRAIN_Y,           /* use only X and Z rotations */
+    D3DRMCONSTRAIN_X            /* use only Y and Z rotations */
+} D3DRMFRAMECONSTRAINT, *LPD3DRMFRAMECONSTRAINT;
+
+typedef enum _D3DRMMATERIALMODE
+{   D3DRMMATERIAL_FROMMESH,
+    D3DRMMATERIAL_FROMPARENT,
+    D3DRMMATERIAL_FROMFRAME
+} D3DRMMATERIALMODE, *LPD3DRMMATERIALMODE;
+
+typedef enum _D3DRMFOGMODE
+{   D3DRMFOG_LINEAR,            /* linear between start and end */
+    D3DRMFOG_EXPONENTIAL,       /* density * exp(-distance) */
+    D3DRMFOG_EXPONENTIALSQUARED /* density * exp(-distance*distance) */
+} D3DRMFOGMODE, *LPD3DRMFOGMODE;
+
+typedef enum _D3DRMZBUFFERMODE {
+    D3DRMZBUFFER_FROMPARENT,    /* default */
+    D3DRMZBUFFER_ENABLE,        /* enable zbuffering */
+    D3DRMZBUFFER_DISABLE        /* disable zbuffering */
+} D3DRMZBUFFERMODE, *LPD3DRMZBUFFERMODE;
+
+typedef enum _D3DRMSORTMODE {
+    D3DRMSORT_FROMPARENT,       /* default */
+    D3DRMSORT_NONE,             /* don't sort child frames */
+    D3DRMSORT_FRONTTOBACK,      /* sort child frames front-to-back */
+    D3DRMSORT_BACKTOFRONT       /* sort child frames back-to-front */
+} D3DRMSORTMODE, *LPD3DRMSORTMODE;
+
+typedef DWORD D3DRMANIMATIONOPTIONS;
+#define D3DRMANIMATION_OPEN 0x01L
+#define D3DRMANIMATION_CLOSED 0x02L
+#define D3DRMANIMATION_LINEARPOSITION 0x04L
+#define D3DRMANIMATION_SPLINEPOSITION 0x08L
+#define D3DRMANIMATION_SCALEANDROTATION 0x00000010L
+#define D3DRMANIMATION_POSITION 0x00000020L
+
+typedef DWORD D3DRMLOADOPTIONS;
+
+#define D3DRMLOAD_FROMFILE  0x00L
+#define D3DRMLOAD_FROMRESOURCE 0x01L
+#define D3DRMLOAD_FROMMEMORY 0x02L
+#define D3DRMLOAD_FROMSTREAM 0x04L
+
+#define D3DRMLOAD_BYNAME 0x10L
+#define D3DRMLOAD_BYPOSITION 0x20L
+#define D3DRMLOAD_BYGUID 0x40L
+#define D3DRMLOAD_FIRST 0x80L
+
+#define D3DRMLOAD_INSTANCEBYREFERENCE 0x100L
+#define D3DRMLOAD_INSTANCEBYCOPYING 0x200L
+
+typedef struct _D3DRMLOADRESOURCE {
+  HMODULE hModule;
+  LPCTSTR lpName;
+  LPCTSTR lpType;
+} D3DRMLOADRESOURCE, *LPD3DRMLOADRESOURCE;
+
+typedef struct _D3DRMLOADMEMORY {
+  LPVOID lpMemory;
+  DWORD dSize;
+} D3DRMLOADMEMORY, *LPD3DRMLOADMEMORY;
+
+typedef enum _D3DRMUSERVISUALREASON {
+    D3DRMUSERVISUAL_CANSEE,
+    D3DRMUSERVISUAL_RENDER
+} D3DRMUSERVISUALREASON, *LPD3DRMUSERVISUALREASON;
+
+
+typedef DWORD D3DRMMAPPING, D3DRMMAPPINGFLAG, *LPD3DRMMAPPING;
+static const D3DRMMAPPINGFLAG D3DRMMAP_WRAPU = 1;
+static const D3DRMMAPPINGFLAG D3DRMMAP_WRAPV = 2;
+static const D3DRMMAPPINGFLAG D3DRMMAP_PERSPCORRECT = 4;
+
+typedef struct _D3DRMVERTEX
+{   D3DVECTOR       position;
+    D3DVECTOR       normal;
+    D3DVALUE        tu, tv;
+    D3DCOLOR        color;
+} D3DRMVERTEX, *LPD3DRMVERTEX;
+
+typedef LONG D3DRMGROUPINDEX; /* group indexes begin a 0 */
+static const D3DRMGROUPINDEX D3DRMGROUP_ALLGROUPS = -1;
+
+/*
+ * Create a color from three components in the range 0-1 inclusive.
+ */
+extern D3DCOLOR D3DRMAPI        D3DRMCreateColorRGB(D3DVALUE red,
+                                          D3DVALUE green,
+                                          D3DVALUE blue);
+
+/*
+ * Create a color from four components in the range 0-1 inclusive.
+ */
+extern D3DCOLOR D3DRMAPI        D3DRMCreateColorRGBA(D3DVALUE red,
+                                                 D3DVALUE green,
+                                                 D3DVALUE blue,
+                                                 D3DVALUE alpha);
+
+/*
+ * Get the red component of a color.
+ */
+extern D3DVALUE                 D3DRMAPI D3DRMColorGetRed(D3DCOLOR);
+
+/*
+ * Get the green component of a color.
+ */
+extern D3DVALUE                 D3DRMAPI D3DRMColorGetGreen(D3DCOLOR);
+
+/*
+ * Get the blue component of a color.
+ */
+extern D3DVALUE                 D3DRMAPI D3DRMColorGetBlue(D3DCOLOR);
+
+/*
+ * Get the alpha component of a color.
+ */
+extern D3DVALUE                 D3DRMAPI D3DRMColorGetAlpha(D3DCOLOR);
+
+/*
+ * Add two vectors.  Returns its first argument.
+ */
+extern LPD3DVECTOR      D3DRMAPI D3DRMVectorAdd(LPD3DVECTOR d,
+                                          LPD3DVECTOR s1,
+                                          LPD3DVECTOR s2);
+
+/*
+ * Subtract two vectors.  Returns its first argument.
+ */
+extern LPD3DVECTOR      D3DRMAPI D3DRMVectorSubtract(LPD3DVECTOR d,
+                                               LPD3DVECTOR s1,
+                                               LPD3DVECTOR s2);
+/*
+ * Reflect a ray about a given normal.  Returns its first argument.
+ */
+extern LPD3DVECTOR      D3DRMAPI D3DRMVectorReflect(LPD3DVECTOR d,
+                                              LPD3DVECTOR ray,
+                                              LPD3DVECTOR norm);
+
+/*
+ * Calculate the vector cross product.  Returns its first argument.
+ */
+extern LPD3DVECTOR      D3DRMAPI D3DRMVectorCrossProduct(LPD3DVECTOR d,
+                                                   LPD3DVECTOR s1,
+                                                   LPD3DVECTOR s2);
+/*
+ * Return the vector dot product.
+ */
+extern D3DVALUE                 D3DRMAPI D3DRMVectorDotProduct(LPD3DVECTOR s1,
+                                                 LPD3DVECTOR s2);
+
+/*
+ * Scale a vector so that its modulus is 1.  Returns its argument or
+ * NULL if there was an error (e.g. a zero vector was passed).
+ */
+extern LPD3DVECTOR      D3DRMAPI D3DRMVectorNormalize(LPD3DVECTOR);
+#define D3DRMVectorNormalise D3DRMVectorNormalize
+
+/*
+ * Return the length of a vector (e.g. sqrt(x*x + y*y + z*z)).
+ */
+extern D3DVALUE                 D3DRMAPI D3DRMVectorModulus(LPD3DVECTOR v);
+
+/*
+ * Set the rotation part of a matrix to be a rotation of theta radians
+ * around the given axis.
+ */
+
+extern LPD3DVECTOR      D3DRMAPI D3DRMVectorRotate(LPD3DVECTOR r, LPD3DVECTOR v, LPD3DVECTOR axis, D3DVALUE theta);
+
+/*
+ * Scale a vector uniformly in all three axes
+ */
+extern LPD3DVECTOR      D3DRMAPI D3DRMVectorScale(LPD3DVECTOR d, LPD3DVECTOR s, D3DVALUE factor);
+
+/*
+ * Return a random unit vector
+ */
+extern LPD3DVECTOR      D3DRMAPI D3DRMVectorRandom(LPD3DVECTOR d);
+
+/*
+ * Returns a unit quaternion that represents a rotation of theta radians
+ * around the given axis.
+ */
+
+extern LPD3DRMQUATERNION D3DRMAPI D3DRMQuaternionFromRotation(LPD3DRMQUATERNION quat,
+                                                              LPD3DVECTOR v,
+                                                              D3DVALUE theta);
+
+/*
+ * Calculate the product of two quaternions
+ */
+extern LPD3DRMQUATERNION D3DRMAPI D3DRMQuaternionMultiply(LPD3DRMQUATERNION q,
+                                                          LPD3DRMQUATERNION a,
+                                                          LPD3DRMQUATERNION b);
+
+/*
+ * Interpolate between two quaternions
+ */
+extern LPD3DRMQUATERNION D3DRMAPI D3DRMQuaternionSlerp(LPD3DRMQUATERNION q,
+                                                       LPD3DRMQUATERNION a,
+                                                       LPD3DRMQUATERNION b,
+                                                       D3DVALUE alpha);
+
+/*
+ * Calculate the matrix for the rotation that a unit quaternion represents
+ */
+extern void             D3DRMAPI D3DRMMatrixFromQuaternion(D3DRMMATRIX4D dmMat, LPD3DRMQUATERNION lpDqQuat);
+
+
+#if defined(__cplusplus)
+};
+#endif
+
+#endif
--- /dev/null
+++ b/QW/dxsdk/sdk/inc/d3drmobj.h
@@ -1,0 +1,727 @@
+/*==========================================================================;
+ *
+ *  Copyright (C) 1995-1996 Microsoft Corporation.  All Rights Reserved.
+ *
+ *  File:       d3drm.h
+ *  Content:    Direct3DRM include file
+ *
+ ***************************************************************************/
+
+#ifndef _D3DRMOBJ_H_
+#define _D3DRMOBJ_H_
+
+#include <objbase.h> /* Use Windows header files */
+#define VIRTUAL
+
+#include "d3drmdef.h"
+#include "d3d.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * The methods for IUnknown
+ */
+#define IUNKNOWN_METHODS(kind) \
+    STDMETHOD(QueryInterface)           (THIS_ REFIID riid, LPVOID *ppvObj) kind; \
+    STDMETHOD_(ULONG, AddRef)           (THIS) kind; \
+    STDMETHOD_(ULONG, Release)          (THIS) kind
+
+/*
+ * The methods for IDirect3DRMObject
+ */
+#define IDIRECT3DRMOBJECT_METHODS(kind) \
+    STDMETHOD(Clone)                    (THIS_ LPUNKNOWN pUnkOuter, REFIID riid, LPVOID *ppvObj) kind; \
+    STDMETHOD(AddDestroyCallback)       (THIS_ D3DRMOBJECTCALLBACK, LPVOID argument) kind; \
+    STDMETHOD(DeleteDestroyCallback)    (THIS_ D3DRMOBJECTCALLBACK, LPVOID argument) kind; \
+    STDMETHOD(SetAppData)               (THIS_ DWORD data) kind; \
+    STDMETHOD_(DWORD, GetAppData)       (THIS) kind; \
+    STDMETHOD(SetName)                  (THIS_ LPCSTR) kind; \
+    STDMETHOD(GetName)                  (THIS_ LPDWORD lpdwSize, LPSTR lpName) kind; \
+    STDMETHOD(GetClassName)             (THIS_ LPDWORD lpdwSize, LPSTR lpName) kind
+
+
+#define WIN_TYPES(itype, ptype) \
+    typedef interface itype FAR *LP##ptype, FAR **LPLP##ptype
+
+WIN_TYPES(IDirect3DRMObject, DIRECT3DRMOBJECT);
+WIN_TYPES(IDirect3DRMDevice, DIRECT3DRMDEVICE);
+WIN_TYPES(IDirect3DRMViewport, DIRECT3DRMVIEWPORT);
+WIN_TYPES(IDirect3DRMFrame, DIRECT3DRMFRAME);
+WIN_TYPES(IDirect3DRMVisual, DIRECT3DRMVISUAL);
+WIN_TYPES(IDirect3DRMMesh, DIRECT3DRMMESH);
+WIN_TYPES(IDirect3DRMMeshBuilder, DIRECT3DRMMESHBUILDER);
+WIN_TYPES(IDirect3DRMFace, DIRECT3DRMFACE);
+WIN_TYPES(IDirect3DRMLight, DIRECT3DRMLIGHT);
+WIN_TYPES(IDirect3DRMTexture, DIRECT3DRMTEXTURE);
+WIN_TYPES(IDirect3DRMWrap, DIRECT3DRMWRAP);
+WIN_TYPES(IDirect3DRMMaterial, DIRECT3DRMMATERIAL);
+WIN_TYPES(IDirect3DRMAnimation, DIRECT3DRMANIMATION);
+WIN_TYPES(IDirect3DRMAnimationSet, DIRECT3DRMANIMATIONSET);
+WIN_TYPES(IDirect3DRMUserVisual, DIRECT3DRMUSERVISUAL);
+WIN_TYPES(IDirect3DRMShadow, DIRECT3DRMSHADOW);
+WIN_TYPES(IDirect3DRMArray, DIRECT3DRMOBJECTARRAY);
+WIN_TYPES(IDirect3DRMDeviceArray, DIRECT3DRMDEVICEARRAY);
+WIN_TYPES(IDirect3DRMFaceArray, DIRECT3DRMFACEARRAY);
+WIN_TYPES(IDirect3DRMViewportArray, DIRECT3DRMVIEWPORTARRAY);
+WIN_TYPES(IDirect3DRMFrameArray, DIRECT3DRMFRAMEARRAY);
+WIN_TYPES(IDirect3DRMVisualArray, DIRECT3DRMVISUALARRAY);
+WIN_TYPES(IDirect3DRMPickedArray, DIRECT3DRMPICKEDARRAY);
+WIN_TYPES(IDirect3DRMLightArray, DIRECT3DRMLIGHTARRAY);
+
+/*
+ * Direct3DRM Object classes
+ */
+DEFINE_GUID(CLSID_CDirect3DRMDevice,        0x4fa3568e, 0x623f, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(CLSID_CDirect3DRMViewport,      0x4fa3568f, 0x623f, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(CLSID_CDirect3DRMFrame,         0x4fa35690, 0x623f, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(CLSID_CDirect3DRMMesh,          0x4fa35691, 0x623f, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(CLSID_CDirect3DRMMeshBuilder,   0x4fa35692, 0x623f, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(CLSID_CDirect3DRMFace,          0x4fa35693, 0x623f, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(CLSID_CDirect3DRMLight,         0x4fa35694, 0x623f, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(CLSID_CDirect3DRMTexture,       0x4fa35695, 0x623f, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(CLSID_CDirect3DRMWrap,          0x4fa35696, 0x623f, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(CLSID_CDirect3DRMMaterial,      0x4fa35697, 0x623f, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(CLSID_CDirect3DRMAnimation,     0x4fa35698, 0x623f, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(CLSID_CDirect3DRMAnimationSet,  0x4fa35699, 0x623f, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(CLSID_CDirect3DRMUserVisual,    0x4fa3569a, 0x623f, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(CLSID_CDirect3DRMShadow,        0x4fa3569b, 0x623f, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+
+/*
+ * Direct3DRM Object interfaces
+ */
+DEFINE_GUID(IID_IDirect3DRMObject,          0xeb16cb00, 0xd271, 0x11ce, 0xac, 0x48, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(IID_IDirect3DRMDevice,          0xe9e19280, 0x6e05, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(IID_IDirect3DRMViewport,        0xeb16cb02, 0xd271, 0x11ce, 0xac, 0x48, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(IID_IDirect3DRMFrame,           0xeb16cb03, 0xd271, 0x11ce, 0xac, 0x48, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(IID_IDirect3DRMVisual,          0xeb16cb04, 0xd271, 0x11ce, 0xac, 0x48, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(IID_IDirect3DRMMesh,            0xa3a80d01, 0x6e12, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(IID_IDirect3DRMMeshBuilder,     0xa3a80d02, 0x6e12, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(IID_IDirect3DRMFace,            0xeb16cb07, 0xd271, 0x11ce, 0xac, 0x48, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(IID_IDirect3DRMLight,           0xeb16cb08, 0xd271, 0x11ce, 0xac, 0x48, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(IID_IDirect3DRMTexture,         0xeb16cb09, 0xd271, 0x11ce, 0xac, 0x48, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(IID_IDirect3DRMWrap,            0xeb16cb0a, 0xd271, 0x11ce, 0xac, 0x48, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(IID_IDirect3DRMMaterial,        0xeb16cb0b, 0xd271, 0x11ce, 0xac, 0x48, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(IID_IDirect3DRMAnimation,       0xeb16cb0d, 0xd271, 0x11ce, 0xac, 0x48, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(IID_IDirect3DRMAnimationSet,    0xeb16cb0e, 0xd271, 0x11ce, 0xac, 0x48, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(IID_IDirect3DRMDeviceArray,     0xeb16cb10, 0xd271, 0x11ce, 0xac, 0x48, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(IID_IDirect3DRMViewportArray,   0xeb16cb11, 0xd271, 0x11ce, 0xac, 0x48, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(IID_IDirect3DRMFrameArray,      0xeb16cb12, 0xd271, 0x11ce, 0xac, 0x48, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(IID_IDirect3DRMVisualArray,     0xeb16cb13, 0xd271, 0x11ce, 0xac, 0x48, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(IID_IDirect3DRMLightArray,      0xeb16cb14, 0xd271, 0x11ce, 0xac, 0x48, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(IID_IDirect3DRMPickedArray,     0xeb16cb16, 0xd271, 0x11ce, 0xac, 0x48, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(IID_IDirect3DRMFaceArray,       0xeb16cb17, 0xd271, 0x11ce, 0xac, 0x48, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(IID_IDirect3DRMUserVisual,      0x59163de0, 0x6d43, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(IID_IDirect3DRMShadow,          0xaf359780, 0x6ba3, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+
+typedef void (*D3DRMOBJECTCALLBACK)(LPDIRECT3DRMOBJECT obj, LPVOID arg);
+typedef void (*D3DRMFRAMEMOVECALLBACK)(LPDIRECT3DRMFRAME obj, LPVOID arg, D3DVALUE delta);
+typedef void (*D3DRMUPDATECALLBACK)(LPDIRECT3DRMDEVICE obj, LPVOID arg, int, LPD3DRECT);
+typedef int (*D3DRMUSERVISUALCALLBACK)(LPDIRECT3DRMUSERVISUAL obj, LPVOID arg,
+                                    D3DRMUSERVISUALREASON reason,
+                                    LPDIRECT3DRMDEVICE dev,
+                                    LPDIRECT3DRMVIEWPORT view);
+typedef HRESULT (*D3DRMLOADTEXTURECALLBACK)
+    (char *tex_name, void *arg, LPDIRECT3DRMTEXTURE *);
+typedef void (*D3DRMLOADCALLBACK)
+     (LPDIRECT3DRMOBJECT object, REFIID objectguid, LPVOID arg);
+
+
+
+typedef struct _D3DRMPICKDESC
+{
+    ULONG       ulFaceIdx;
+    LONG        lGroupIdx;
+    D3DVECTOR   vPosition;
+
+} D3DRMPICKDESC, *LPD3DRMPICKDESC;
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRMObject
+
+/*
+ * Base class
+ */
+DECLARE_INTERFACE_(IDirect3DRMObject, IUnknown)
+{
+    IUNKNOWN_METHODS(PURE);
+    IDIRECT3DRMOBJECT_METHODS(PURE);
+};
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRMVisual
+
+DECLARE_INTERFACE_(IDirect3DRMVisual, IDirect3DRMObject)
+{
+    IUNKNOWN_METHODS(PURE);
+    IDIRECT3DRMOBJECT_METHODS(PURE);
+};
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRMDevice
+
+DECLARE_INTERFACE_(IDirect3DRMDevice, IDirect3DRMObject)
+{
+    IUNKNOWN_METHODS(PURE);
+    IDIRECT3DRMOBJECT_METHODS(PURE);
+
+    /*
+     * IDirect3DRMDevice methods
+     */
+    STDMETHOD(Init)(THIS_ ULONG width, ULONG height) PURE;
+    STDMETHOD(InitFromD3D)(THIS_ LPDIRECT3D lpD3D, LPDIRECT3DDEVICE lpD3DDev) PURE;
+    STDMETHOD(InitFromClipper)(THIS_ LPDIRECTDRAWCLIPPER lpDDClipper, LPGUID lpGUID, int width, int height) PURE;
+
+    STDMETHOD(Update)(THIS) PURE;
+    STDMETHOD(AddUpdateCallback)(THIS_ D3DRMUPDATECALLBACK, LPVOID arg) PURE;
+    STDMETHOD(DeleteUpdateCallback)(THIS_ D3DRMUPDATECALLBACK, LPVOID arg) PURE;
+    STDMETHOD(SetBufferCount)(THIS_ DWORD) PURE;
+    STDMETHOD_(DWORD, GetBufferCount)(THIS) PURE;
+
+    STDMETHOD(SetDither)(THIS_ BOOL) PURE;
+    STDMETHOD(SetShades)(THIS_ DWORD) PURE;
+    STDMETHOD(SetQuality)(THIS_ D3DRMRENDERQUALITY) PURE;
+    STDMETHOD(SetTextureQuality)(THIS_ D3DRMTEXTUREQUALITY) PURE;
+
+    STDMETHOD(GetViewports)(THIS_ LPDIRECT3DRMVIEWPORTARRAY *return_views) PURE;
+
+    STDMETHOD_(BOOL, GetDither)(THIS) PURE;
+    STDMETHOD_(DWORD, GetShades)(THIS) PURE;
+    STDMETHOD_(DWORD, GetHeight)(THIS) PURE;
+    STDMETHOD_(DWORD, GetWidth)(THIS) PURE;
+    STDMETHOD_(DWORD, GetTrianglesDrawn)(THIS) PURE;
+    STDMETHOD_(DWORD, GetWireframeOptions)(THIS) PURE;
+    STDMETHOD_(D3DRMRENDERQUALITY, GetQuality)(THIS) PURE;
+    STDMETHOD_(D3DCOLORMODEL, GetColorModel)(THIS) PURE;
+    STDMETHOD_(D3DRMTEXTUREQUALITY, GetTextureQuality)(THIS) PURE;
+    STDMETHOD(GetDirect3DDevice)(THIS_ LPDIRECT3DDEVICE *) PURE;
+};
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRMViewport
+
+DECLARE_INTERFACE_(IDirect3DRMViewport, IDirect3DRMObject)
+{
+    IUNKNOWN_METHODS(PURE);
+    IDIRECT3DRMOBJECT_METHODS(PURE);
+
+    /*
+     * IDirect3DRMViewport methods
+     */
+    STDMETHOD(Init)
+    (   THIS_ LPDIRECT3DRMDEVICE dev, LPDIRECT3DRMFRAME camera,
+        DWORD xpos, DWORD ypos, DWORD width, DWORD height
+    ) PURE;
+    STDMETHOD(Clear)(THIS) PURE;
+    STDMETHOD(Render)(THIS_ LPDIRECT3DRMFRAME) PURE;
+
+    STDMETHOD(SetFront)(THIS_ D3DVALUE) PURE;
+    STDMETHOD(SetBack)(THIS_ D3DVALUE) PURE;
+    STDMETHOD(SetField)(THIS_ D3DVALUE) PURE;
+    STDMETHOD(SetUniformScaling)(THIS_ BOOL) PURE;
+    STDMETHOD(SetCamera)(THIS_ LPDIRECT3DRMFRAME) PURE;
+    STDMETHOD(SetProjection)(THIS_ D3DRMPROJECTIONTYPE) PURE;
+    STDMETHOD(Transform)(THIS_ D3DRMVECTOR4D *d, D3DVECTOR *s) PURE;
+    STDMETHOD(InverseTransform)(THIS_ D3DVECTOR *d, D3DRMVECTOR4D *s) PURE;
+    STDMETHOD(Configure)(THIS_ LONG x, LONG y, DWORD width, DWORD height) PURE;
+    STDMETHOD(ForceUpdate)(THIS_ DWORD x1, DWORD y1, DWORD x2, DWORD y2) PURE;
+    STDMETHOD(SetPlane)(THIS_ D3DVALUE left, D3DVALUE right, D3DVALUE bottom, D3DVALUE top) PURE;
+
+    STDMETHOD(GetCamera)(THIS_ LPDIRECT3DRMFRAME *) PURE;
+    STDMETHOD(GetDevice)(THIS_ LPDIRECT3DRMDEVICE *) PURE;
+    STDMETHOD(GetPlane)(THIS_ D3DVALUE *left, D3DVALUE *right, D3DVALUE *bottom, D3DVALUE *top) PURE;
+    STDMETHOD(Pick)(THIS_ LONG x, LONG y, LPDIRECT3DRMPICKEDARRAY *return_visuals) PURE;
+
+    STDMETHOD_(BOOL, GetUniformScaling)(THIS) PURE;
+    STDMETHOD_(LONG, GetX)(THIS) PURE;
+    STDMETHOD_(LONG, GetY)(THIS) PURE;
+    STDMETHOD_(DWORD, GetWidth)(THIS) PURE;
+    STDMETHOD_(DWORD, GetHeight)(THIS) PURE;
+    STDMETHOD_(D3DVALUE, GetField)(THIS) PURE;
+    STDMETHOD_(D3DVALUE, GetBack)(THIS) PURE;
+    STDMETHOD_(D3DVALUE, GetFront)(THIS) PURE;
+    STDMETHOD_(D3DRMPROJECTIONTYPE, GetProjection)(THIS) PURE;
+    STDMETHOD(GetDirect3DViewport)(THIS_ LPDIRECT3DVIEWPORT *) PURE;
+};
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRMFrame
+
+DECLARE_INTERFACE_(IDirect3DRMFrame, IDirect3DRMVisual)
+{
+    IUNKNOWN_METHODS(PURE);
+    IDIRECT3DRMOBJECT_METHODS(PURE);
+
+    /*
+     * IDirect3DRMFrame methods
+     */
+    STDMETHOD(AddChild)(THIS_ LPDIRECT3DRMFRAME child) PURE;
+    STDMETHOD(AddLight)(THIS_ LPDIRECT3DRMLIGHT) PURE;
+    STDMETHOD(AddMoveCallback)(THIS_ D3DRMFRAMEMOVECALLBACK, VOID *arg) PURE;
+    STDMETHOD(AddTransform)(THIS_ D3DRMCOMBINETYPE, D3DRMMATRIX4D) PURE;
+    STDMETHOD(AddTranslation)(THIS_ D3DRMCOMBINETYPE, D3DVALUE x, D3DVALUE y, D3DVALUE z) PURE;
+    STDMETHOD(AddScale)(THIS_ D3DRMCOMBINETYPE, D3DVALUE sx, D3DVALUE sy, D3DVALUE sz) PURE;
+    STDMETHOD(AddRotation)(THIS_ D3DRMCOMBINETYPE, D3DVALUE x, D3DVALUE y, D3DVALUE z, D3DVALUE theta) PURE;
+    STDMETHOD(AddVisual)(THIS_ LPDIRECT3DRMVISUAL) PURE;
+    STDMETHOD(GetChildren)(THIS_ LPDIRECT3DRMFRAMEARRAY *children) PURE;
+    STDMETHOD_(D3DCOLOR, GetColor)(THIS) PURE;
+    STDMETHOD(GetLights)(THIS_ LPDIRECT3DRMLIGHTARRAY *lights) PURE;
+    STDMETHOD_(D3DRMMATERIALMODE, GetMaterialMode)(THIS) PURE;
+    STDMETHOD(GetParent)(THIS_ LPDIRECT3DRMFRAME *) PURE;
+    STDMETHOD(GetPosition)(THIS_ LPDIRECT3DRMFRAME reference, LPD3DVECTOR return_position) PURE;
+    STDMETHOD(GetRotation)(THIS_ LPDIRECT3DRMFRAME reference, LPD3DVECTOR axis, LPD3DVALUE return_theta) PURE;
+    STDMETHOD(GetScene)(THIS_ LPDIRECT3DRMFRAME *) PURE;
+    STDMETHOD_(D3DRMSORTMODE, GetSortMode)(THIS) PURE;
+    STDMETHOD(GetTexture)(THIS_ LPDIRECT3DRMTEXTURE *) PURE;
+    STDMETHOD(GetTransform)(THIS_ D3DRMMATRIX4D return_matrix) PURE;
+    STDMETHOD(GetVelocity)(THIS_ LPDIRECT3DRMFRAME reference, LPD3DVECTOR return_velocity, BOOL with_rotation) PURE;
+    STDMETHOD(GetOrientation)(THIS_ LPDIRECT3DRMFRAME reference, LPD3DVECTOR dir, LPD3DVECTOR up) PURE;
+    STDMETHOD(GetVisuals)(THIS_ LPDIRECT3DRMVISUALARRAY *visuals) PURE;
+    STDMETHOD(GetTextureTopology)(THIS_ BOOL *wrap_u, BOOL *wrap_v) PURE;
+    STDMETHOD(InverseTransform)(THIS_ D3DVECTOR *d, D3DVECTOR *s) PURE;
+    STDMETHOD(Load)(THIS_ LPVOID filename, LPVOID name, D3DRMLOADOPTIONS loadflags, D3DRMLOADTEXTURECALLBACK, LPVOID lpArg)PURE;
+    STDMETHOD(LookAt)(THIS_ LPDIRECT3DRMFRAME target, LPDIRECT3DRMFRAME reference, D3DRMFRAMECONSTRAINT) PURE;
+    STDMETHOD(Move)(THIS_ D3DVALUE delta) PURE;
+    STDMETHOD(DeleteChild)(THIS_ LPDIRECT3DRMFRAME) PURE;
+    STDMETHOD(DeleteLight)(THIS_ LPDIRECT3DRMLIGHT) PURE;
+    STDMETHOD(DeleteMoveCallback)(THIS_ D3DRMFRAMEMOVECALLBACK, VOID *arg) PURE;
+    STDMETHOD(DeleteVisual)(THIS_ LPDIRECT3DRMVISUAL) PURE;
+    STDMETHOD_(D3DCOLOR, GetSceneBackground)(THIS) PURE;
+    STDMETHOD(GetSceneBackgroundDepth)(THIS_ LPDIRECTDRAWSURFACE *) PURE;
+    STDMETHOD_(D3DCOLOR, GetSceneFogColor)(THIS) PURE;
+    STDMETHOD_(BOOL, GetSceneFogEnable)(THIS) PURE;
+    STDMETHOD_(D3DRMFOGMODE, GetSceneFogMode)(THIS) PURE;
+    STDMETHOD(GetSceneFogParams)(THIS_ D3DVALUE *return_start, D3DVALUE *return_end, D3DVALUE *return_density) PURE;
+    STDMETHOD(SetSceneBackground)(THIS_ D3DCOLOR) PURE;
+    STDMETHOD(SetSceneBackgroundRGB)(THIS_ D3DVALUE red, D3DVALUE green, D3DVALUE blue) PURE;
+    STDMETHOD(SetSceneBackgroundDepth)(THIS_ LPDIRECTDRAWSURFACE) PURE;
+    STDMETHOD(SetSceneBackgroundImage)(THIS_ LPDIRECT3DRMTEXTURE) PURE;
+    STDMETHOD(SetSceneFogEnable)(THIS_ BOOL) PURE;
+    STDMETHOD(SetSceneFogColor)(THIS_ D3DCOLOR) PURE;
+    STDMETHOD(SetSceneFogMode)(THIS_ D3DRMFOGMODE) PURE;
+    STDMETHOD(SetSceneFogParams)(THIS_ D3DVALUE start, D3DVALUE end, D3DVALUE density) PURE;
+    STDMETHOD(SetColor)(THIS_ D3DCOLOR) PURE;
+    STDMETHOD(SetColorRGB)(THIS_ D3DVALUE red, D3DVALUE green, D3DVALUE blue) PURE;
+    STDMETHOD_(D3DRMZBUFFERMODE, GetZbufferMode)(THIS) PURE;
+    STDMETHOD(SetMaterialMode)(THIS_ D3DRMMATERIALMODE) PURE;
+    STDMETHOD(SetOrientation)
+    (   THIS_ LPDIRECT3DRMFRAME reference,
+        D3DVALUE dx, D3DVALUE dy, D3DVALUE dz,
+        D3DVALUE ux, D3DVALUE uy, D3DVALUE uz
+    ) PURE;
+    STDMETHOD(SetPosition)(THIS_ LPDIRECT3DRMFRAME reference, D3DVALUE x, D3DVALUE y, D3DVALUE z) PURE;
+    STDMETHOD(SetRotation)(THIS_ LPDIRECT3DRMFRAME reference, D3DVALUE x, D3DVALUE y, D3DVALUE z, D3DVALUE theta) PURE;
+    STDMETHOD(SetSortMode)(THIS_ D3DRMSORTMODE) PURE;
+    STDMETHOD(SetTexture)(THIS_ LPDIRECT3DRMTEXTURE) PURE;
+    STDMETHOD(SetTextureTopology)(THIS_ BOOL wrap_u, BOOL wrap_v) PURE;
+    STDMETHOD(SetVelocity)(THIS_ LPDIRECT3DRMFRAME reference, D3DVALUE x, D3DVALUE y, D3DVALUE z, BOOL with_rotation) PURE;
+    STDMETHOD(SetZbufferMode)(THIS_ D3DRMZBUFFERMODE) PURE;
+    STDMETHOD(Transform)(THIS_ D3DVECTOR *d, D3DVECTOR *s) PURE;
+};
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRMMesh
+
+DECLARE_INTERFACE_(IDirect3DRMMesh, IDirect3DRMVisual)
+{
+    IUNKNOWN_METHODS(PURE);
+    IDIRECT3DRMOBJECT_METHODS(PURE);
+
+    /*
+     * IDirect3DRMMesh methods
+     */
+    STDMETHOD(Scale)(THIS_ D3DVALUE sx, D3DVALUE sy, D3DVALUE sz) PURE;
+    STDMETHOD(Translate)(THIS_ D3DVALUE tx, D3DVALUE ty, D3DVALUE tz) PURE;
+    STDMETHOD(GetBox)(THIS_ D3DRMBOX *) PURE;
+    STDMETHOD(AddGroup)(THIS_ unsigned vCount, unsigned fCount, unsigned vPerFace, unsigned *fData, D3DRMGROUPINDEX *returnId) PURE;
+    STDMETHOD(SetVertices)(THIS_ D3DRMGROUPINDEX id, unsigned index, unsigned count, D3DRMVERTEX *values) PURE;
+    STDMETHOD(SetGroupColor)(THIS_ D3DRMGROUPINDEX id, D3DCOLOR value) PURE;
+    STDMETHOD(SetGroupColorRGB)(THIS_ D3DRMGROUPINDEX id, D3DVALUE red, D3DVALUE green, D3DVALUE blue) PURE;
+    STDMETHOD(SetGroupMapping)(THIS_ D3DRMGROUPINDEX id, D3DRMMAPPING value) PURE;
+    STDMETHOD(SetGroupQuality)(THIS_ D3DRMGROUPINDEX id, D3DRMRENDERQUALITY value) PURE;
+    STDMETHOD(SetGroupMaterial)(THIS_ D3DRMGROUPINDEX id, LPDIRECT3DRMMATERIAL value) PURE;
+    STDMETHOD(SetGroupTexture)(THIS_ D3DRMGROUPINDEX id, LPDIRECT3DRMTEXTURE value) PURE;
+
+    STDMETHOD_(unsigned, GetGroupCount)(THIS) PURE;
+    STDMETHOD(GetGroup)(THIS_ D3DRMGROUPINDEX id, unsigned *vCount, unsigned *fCount, unsigned *vPerFace, DWORD *fDataSize, unsigned *fData) PURE;
+    STDMETHOD(GetVertices)(THIS_ D3DRMGROUPINDEX id, DWORD index, DWORD count, D3DRMVERTEX *returnPtr) PURE;
+    STDMETHOD_(D3DCOLOR, GetGroupColor)(THIS_ D3DRMGROUPINDEX id) PURE;
+    STDMETHOD_(D3DRMMAPPING, GetGroupMapping)(THIS_ D3DRMGROUPINDEX id) PURE;
+    STDMETHOD_(D3DRMRENDERQUALITY, GetGroupQuality)(THIS_ D3DRMGROUPINDEX id) PURE;
+    STDMETHOD(GetGroupMaterial)(THIS_ D3DRMGROUPINDEX id, LPDIRECT3DRMMATERIAL *returnPtr) PURE;
+    STDMETHOD(GetGroupTexture)(THIS_ D3DRMGROUPINDEX id, LPDIRECT3DRMTEXTURE *returnPtr) PURE;
+};
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRMShadow
+
+DECLARE_INTERFACE_(IDirect3DRMShadow, IDirect3DRMVisual)
+{
+    IUNKNOWN_METHODS(PURE);
+    IDIRECT3DRMOBJECT_METHODS(PURE);
+
+    /*
+     * IDirect3DRMShadow methods
+     */
+    STDMETHOD(Init)
+    (   THIS_ LPDIRECT3DRMVISUAL visual, LPDIRECT3DRMLIGHT light,
+        D3DVALUE px, D3DVALUE py, D3DVALUE pz,
+        D3DVALUE nx, D3DVALUE ny, D3DVALUE nz
+    ) PURE;
+};
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRMFace
+
+DECLARE_INTERFACE_(IDirect3DRMFace, IDirect3DRMObject)
+{
+    IUNKNOWN_METHODS(PURE);
+    IDIRECT3DRMOBJECT_METHODS(PURE);
+
+    /*
+     * IDirect3DRMFace methods
+     */
+     STDMETHOD(AddVertex)(THIS_ D3DVALUE x, D3DVALUE y, D3DVALUE z) PURE;
+     STDMETHOD(AddVertexAndNormalIndexed)(THIS_ DWORD vertex, DWORD normal) PURE;
+     STDMETHOD(SetColorRGB)(THIS_ D3DVALUE, D3DVALUE, D3DVALUE) PURE;
+     STDMETHOD(SetColor)(THIS_ D3DCOLOR) PURE;
+     STDMETHOD(SetTexture)(THIS_ LPDIRECT3DRMTEXTURE) PURE;
+     STDMETHOD(SetTextureCoordinates)(THIS_ DWORD vertex, D3DVALUE u, D3DVALUE v) PURE;
+     STDMETHOD(SetMaterial)(THIS_ LPDIRECT3DRMMATERIAL) PURE;
+     STDMETHOD(SetTextureTopology)(THIS_ BOOL wrap_u, BOOL wrap_v) PURE;
+
+     STDMETHOD(GetVertex)(THIS_ DWORD index, D3DVECTOR *vertex, D3DVECTOR *normal) PURE;
+     STDMETHOD(GetVertices)(THIS_ DWORD *vertex_count, D3DVECTOR *coords, D3DVECTOR *normals);
+     STDMETHOD(GetTextureCoordinates)(THIS_ DWORD vertex, D3DVALUE *u, D3DVALUE *v) PURE;
+     STDMETHOD(GetTextureTopology)(THIS_ BOOL *wrap_u, BOOL *wrap_v) PURE;
+     STDMETHOD(GetNormal)(THIS_ D3DVECTOR *) PURE;
+     STDMETHOD(GetTexture)(THIS_ LPDIRECT3DRMTEXTURE *) PURE;
+     STDMETHOD(GetMaterial)(THIS_ LPDIRECT3DRMMATERIAL *) PURE;
+
+     STDMETHOD_(int, GetVertexCount)(THIS) PURE;
+     STDMETHOD_(int, GetVertexIndex)(THIS_ DWORD which) PURE;
+     STDMETHOD_(int, GetTextureCoordinateIndex)(THIS_ DWORD which) PURE;
+     STDMETHOD_(D3DCOLOR, GetColor)(THIS) PURE;
+};
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRMMeshBuilder
+
+DECLARE_INTERFACE_(IDirect3DRMMeshBuilder, IDirect3DRMVisual)
+{
+    IUNKNOWN_METHODS(PURE);
+    IDIRECT3DRMOBJECT_METHODS(PURE);
+
+    /*
+     * IDirect3DRMMeshBuilder methods
+     */
+    STDMETHOD(Load)(THIS_ LPVOID filename, LPVOID name, D3DRMLOADOPTIONS loadflags, D3DRMLOADTEXTURECALLBACK, LPVOID lpArg) PURE;
+    STDMETHOD(Save)(THIS_ const char *filename, D3DRMXOFFORMAT, D3DRMSAVEOPTIONS save) PURE;
+    STDMETHOD(Scale)(THIS_ D3DVALUE sx, D3DVALUE sy, D3DVALUE sz) PURE;
+    STDMETHOD(Translate)(THIS_ D3DVALUE tx, D3DVALUE ty, D3DVALUE tz) PURE;
+    STDMETHOD(SetColorSource)(THIS_ D3DRMCOLORSOURCE) PURE;
+    STDMETHOD(GetBox)(THIS_ D3DRMBOX *) PURE;
+    STDMETHOD(GenerateNormals)(THIS) PURE;
+    STDMETHOD_(D3DRMCOLORSOURCE, GetColorSource)(THIS) PURE;
+
+    STDMETHOD(AddMesh)(THIS_ LPDIRECT3DRMMESH) PURE;
+    STDMETHOD(AddMeshBuilder)(THIS_ LPDIRECT3DRMMESHBUILDER) PURE;
+    STDMETHOD(AddFrame)(THIS_ LPDIRECT3DRMFRAME) PURE;
+    STDMETHOD(AddFace)(THIS_ LPDIRECT3DRMFACE) PURE;
+    STDMETHOD(AddFaces)
+    (   THIS_ DWORD vcount, D3DVECTOR *vertices, DWORD ncount, D3DVECTOR *normals,
+        DWORD *data, LPDIRECT3DRMFACEARRAY*
+    ) PURE;
+    STDMETHOD(ReserveSpace)(THIS_ DWORD vertex_Count, DWORD normal_count, DWORD face_count) PURE;
+    STDMETHOD(SetColorRGB)(THIS_ D3DVALUE red, D3DVALUE green, D3DVALUE blue) PURE;
+    STDMETHOD(SetColor)(THIS_ D3DCOLOR) PURE;
+    STDMETHOD(SetTexture)(THIS_ LPDIRECT3DRMTEXTURE) PURE;
+    STDMETHOD(SetMaterial)(THIS_ LPDIRECT3DRMMATERIAL) PURE;
+    STDMETHOD(SetTextureTopology)(THIS_ BOOL wrap_u, BOOL wrap_v) PURE;
+    STDMETHOD(SetQuality)(THIS_ D3DRMRENDERQUALITY) PURE;
+    STDMETHOD(SetPerspective)(THIS_ BOOL) PURE;
+    STDMETHOD(SetVertex)(THIS_ DWORD index, D3DVALUE x, D3DVALUE y, D3DVALUE z) PURE;
+    STDMETHOD(SetNormal)(THIS_ DWORD index, D3DVALUE x, D3DVALUE y, D3DVALUE z) PURE;
+    STDMETHOD(SetTextureCoordinates)(THIS_ DWORD index, D3DVALUE u, D3DVALUE v) PURE;
+    STDMETHOD(SetVertexColor)(THIS_ DWORD index, D3DCOLOR) PURE;
+    STDMETHOD(SetVertexColorRGB)(THIS_ DWORD index, D3DVALUE red, D3DVALUE green, D3DVALUE blue) PURE;
+
+    STDMETHOD(GetFaces)(THIS_ LPDIRECT3DRMFACEARRAY*) PURE;
+    STDMETHOD(GetVertices)
+    (   THIS_ DWORD *vcount, D3DVECTOR *vertices, DWORD *ncount, D3DVECTOR *normals, DWORD *face_data_size, DWORD *face_data
+    ) PURE;
+    STDMETHOD(GetTextureCoordinates)(THIS_ DWORD index, D3DVALUE *u, D3DVALUE *v) PURE;
+
+    STDMETHOD_(int, AddVertex)(THIS_ D3DVALUE x, D3DVALUE y, D3DVALUE z) PURE;
+    STDMETHOD_(int, AddNormal)(THIS_ D3DVALUE x, D3DVALUE y, D3DVALUE z) PURE;
+    STDMETHOD(CreateFace)(THIS_ LPDIRECT3DRMFACE*) PURE;
+    STDMETHOD_(D3DRMRENDERQUALITY, GetQuality)(THIS) PURE;
+    STDMETHOD_(BOOL, GetPerspective)(THIS) PURE;
+    STDMETHOD_(int, GetFaceCount)(THIS) PURE;
+    STDMETHOD_(int, GetVertexCount)(THIS) PURE;
+    STDMETHOD_(D3DCOLOR, GetVertexColor)(THIS_ DWORD index) PURE;
+
+    STDMETHOD(CreateMesh)(THIS_ LPDIRECT3DRMMESH*) PURE;
+};
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRMLight
+
+DECLARE_INTERFACE_(IDirect3DRMLight, IDirect3DRMObject)
+{
+    IUNKNOWN_METHODS(PURE);
+    IDIRECT3DRMOBJECT_METHODS(PURE);
+
+    /*
+     * IDirect3DRMLight methods
+     */
+    STDMETHOD(SetType)(THIS_ D3DRMLIGHTTYPE) PURE;
+    STDMETHOD(SetColor)(THIS_ D3DCOLOR) PURE;
+    STDMETHOD(SetColorRGB)(THIS_ D3DVALUE red, D3DVALUE green, D3DVALUE blue) PURE;
+    STDMETHOD(SetRange)(THIS_ D3DVALUE) PURE;
+    STDMETHOD(SetUmbra)(THIS_ D3DVALUE) PURE;
+    STDMETHOD(SetPenumbra)(THIS_ D3DVALUE) PURE;
+    STDMETHOD(SetConstantAttenuation)(THIS_ D3DVALUE) PURE;
+    STDMETHOD(SetLinearAttenuation)(THIS_ D3DVALUE) PURE;
+    STDMETHOD(SetQuadraticAttenuation)(THIS_ D3DVALUE) PURE;
+
+    STDMETHOD_(D3DVALUE, GetRange)(THIS) PURE;
+    STDMETHOD_(D3DVALUE, GetUmbra)(THIS) PURE;
+    STDMETHOD_(D3DVALUE, GetPenumbra)(THIS) PURE;
+    STDMETHOD_(D3DVALUE, GetConstantAttenuation)(THIS) PURE;
+    STDMETHOD_(D3DVALUE, GetLinearAttenuation)(THIS) PURE;
+    STDMETHOD_(D3DVALUE, GetQuadraticAttenuation)(THIS) PURE;
+    STDMETHOD_(D3DCOLOR, GetColor)(THIS) PURE;
+    STDMETHOD_(D3DRMLIGHTTYPE, GetType)(THIS) PURE;
+
+    STDMETHOD(SetEnableFrame)(THIS_ LPDIRECT3DRMFRAME) PURE;
+    STDMETHOD(GetEnableFrame)(THIS_ LPDIRECT3DRMFRAME*) PURE;
+};
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRMTexture
+
+DECLARE_INTERFACE_(IDirect3DRMTexture, IDirect3DRMVisual)
+{
+    IUNKNOWN_METHODS(PURE);
+    IDIRECT3DRMOBJECT_METHODS(PURE);
+
+    /*
+     * IDirect3DRMTexture methods
+     */
+    STDMETHOD(InitFromFile)(THIS_ const char *filename) PURE;
+    STDMETHOD(InitFromSurface)(THIS_ LPDIRECTDRAWSURFACE lpDDS) PURE;
+    STDMETHOD(InitFromResource)(THIS_ HRSRC) PURE;
+    STDMETHOD(Changed)(THIS_ BOOL pixels, BOOL palette) PURE;
+
+    STDMETHOD(SetColors)(THIS_ DWORD) PURE;
+    STDMETHOD(SetShades)(THIS_ DWORD) PURE;
+    STDMETHOD(SetDecalSize)(THIS_ D3DVALUE width, D3DVALUE height) PURE;
+    STDMETHOD(SetDecalOrigin)(THIS_ LONG x, LONG y) PURE;
+    STDMETHOD(SetDecalScale)(THIS_ DWORD) PURE;
+    STDMETHOD(SetDecalTransparency)(THIS_ BOOL) PURE;
+    STDMETHOD(SetDecalTransparentColor)(THIS_ D3DCOLOR) PURE;
+
+    STDMETHOD(GetDecalSize)(THIS_ D3DVALUE *width_return, D3DVALUE *height_return) PURE;
+    STDMETHOD(GetDecalOrigin)(THIS_ LONG *x_return, LONG *y_return) PURE;
+
+    STDMETHOD_(D3DRMIMAGE *, GetImage)(THIS) PURE;
+    STDMETHOD_(DWORD, GetShades)(THIS) PURE;
+    STDMETHOD_(DWORD, GetColors)(THIS) PURE;
+    STDMETHOD_(DWORD, GetDecalScale)(THIS) PURE;
+    STDMETHOD_(BOOL, GetDecalTransparency)(THIS) PURE;
+    STDMETHOD_(D3DCOLOR, GetDecalTransparentColor)(THIS) PURE;
+};
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRMWrap
+
+DECLARE_INTERFACE_(IDirect3DRMWrap, IDirect3DRMObject)
+{
+    IUNKNOWN_METHODS(PURE);
+    IDIRECT3DRMOBJECT_METHODS(PURE);
+
+    /*
+     * IDirect3DRMWrap methods
+     */
+    STDMETHOD(Init)
+    (   THIS_ D3DRMWRAPTYPE, LPDIRECT3DRMFRAME ref,
+        D3DVALUE ox, D3DVALUE oy, D3DVALUE oz,
+        D3DVALUE dx, D3DVALUE dy, D3DVALUE dz,
+        D3DVALUE ux, D3DVALUE uy, D3DVALUE uz,
+        D3DVALUE ou, D3DVALUE ov,
+        D3DVALUE su, D3DVALUE sv
+    ) PURE;
+    STDMETHOD(Apply)(THIS_ LPDIRECT3DRMOBJECT) PURE;
+    STDMETHOD(ApplyRelative)(THIS_ LPDIRECT3DRMFRAME frame, LPDIRECT3DRMOBJECT) PURE;
+};
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRMMaterial
+
+DECLARE_INTERFACE_(IDirect3DRMMaterial, IDirect3DRMObject)
+{
+    IUNKNOWN_METHODS(PURE);
+    IDIRECT3DRMOBJECT_METHODS(PURE);
+
+    /*
+     * IDirect3DRMMaterial methods
+     */
+    STDMETHOD(SetPower)(THIS_ D3DVALUE power) PURE;
+    STDMETHOD(SetSpecular)(THIS_ D3DVALUE r, D3DVALUE g, D3DVALUE b) PURE;
+    STDMETHOD(SetEmissive)(THIS_ D3DVALUE r, D3DVALUE g, D3DVALUE b) PURE;
+
+    STDMETHOD_(D3DVALUE, GetPower)(THIS) PURE;
+    STDMETHOD(GetSpecular)(THIS_ D3DVALUE* r, D3DVALUE* g, D3DVALUE* b) PURE;
+    STDMETHOD(GetEmissive)(THIS_ D3DVALUE* r, D3DVALUE* g, D3DVALUE* b) PURE;
+};
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRMAnimation
+
+DECLARE_INTERFACE_(IDirect3DRMAnimation, IDirect3DRMObject)
+{
+    IUNKNOWN_METHODS(PURE);
+    IDIRECT3DRMOBJECT_METHODS(PURE);
+
+    /*
+     * IDirect3DRMAnimation methods
+     */
+    STDMETHOD(SetOptions)(THIS_ D3DRMANIMATIONOPTIONS flags) PURE;
+    STDMETHOD(AddRotateKey)(THIS_ D3DVALUE time, D3DRMQUATERNION *q) PURE;
+    STDMETHOD(AddPositionKey)(THIS_ D3DVALUE time, D3DVALUE x, D3DVALUE y, D3DVALUE z) PURE;
+    STDMETHOD(AddScaleKey)(THIS_ D3DVALUE time, D3DVALUE x, D3DVALUE y, D3DVALUE z) PURE;
+    STDMETHOD(DeleteKey)(THIS_ D3DVALUE time) PURE;
+    STDMETHOD(SetFrame)(THIS_ LPDIRECT3DRMFRAME frame) PURE;
+    STDMETHOD(SetTime)(THIS_ D3DVALUE time) PURE;
+
+    STDMETHOD_(D3DRMANIMATIONOPTIONS, GetOptions)(THIS) PURE;
+};
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRMAnimationSet
+
+DECLARE_INTERFACE_(IDirect3DRMAnimationSet, IDirect3DRMObject)
+{
+    IUNKNOWN_METHODS(PURE);
+    IDIRECT3DRMOBJECT_METHODS(PURE);
+
+    /*
+     * IDirect3DRMAnimationSet methods
+     */
+    STDMETHOD(AddAnimation)(THIS_ LPDIRECT3DRMANIMATION aid) PURE;
+    STDMETHOD(Load)(THIS_ LPVOID filename, LPVOID name, D3DRMLOADOPTIONS loadflags, D3DRMLOADTEXTURECALLBACK, LPVOID lpArg, LPDIRECT3DRMFRAME parent)PURE;
+    STDMETHOD(DeleteAnimation)(THIS_ LPDIRECT3DRMANIMATION aid) PURE;
+    STDMETHOD(SetTime)(THIS_ D3DVALUE time) PURE;
+};
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRMUserVisual
+
+DECLARE_INTERFACE_(IDirect3DRMUserVisual, IDirect3DRMVisual)
+{
+    IUNKNOWN_METHODS(PURE);
+    IDIRECT3DRMOBJECT_METHODS(PURE);
+
+    /*
+     * IDirect3DRMUserVisual methods
+     */
+    STDMETHOD(Init)(THIS_ D3DRMUSERVISUALCALLBACK fn, void *arg) PURE;
+};
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRMArray
+
+DECLARE_INTERFACE_(IDirect3DRMArray, IUnknown)
+{
+    IUNKNOWN_METHODS(PURE);
+
+    STDMETHOD_(DWORD, GetSize)(THIS) PURE;
+    /* No GetElement method as it would get overloaded
+     * in derived classes, and overloading is
+     * a no-no in COM
+     */
+};
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRMDeviceArray
+
+DECLARE_INTERFACE_(IDirect3DRMDeviceArray, IDirect3DRMArray)
+{
+    IUNKNOWN_METHODS(PURE);
+
+    STDMETHOD_(DWORD, GetSize)(THIS) PURE;
+    STDMETHOD(GetElement)(THIS_ DWORD index, LPDIRECT3DRMDEVICE *) PURE;
+};
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRMFrameArray
+
+DECLARE_INTERFACE_(IDirect3DRMFrameArray, IDirect3DRMArray)
+{
+    IUNKNOWN_METHODS(PURE);
+
+    STDMETHOD_(DWORD, GetSize)(THIS) PURE;
+    STDMETHOD(GetElement)(THIS_ DWORD index, LPDIRECT3DRMFRAME *) PURE;
+};
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRMViewportArray
+
+DECLARE_INTERFACE_(IDirect3DRMViewportArray, IDirect3DRMArray)
+{
+    IUNKNOWN_METHODS(PURE);
+
+    STDMETHOD_(DWORD, GetSize)(THIS) PURE;
+    STDMETHOD(GetElement)(THIS_ DWORD index, LPDIRECT3DRMVIEWPORT *) PURE;
+};
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRMVisualArray
+
+DECLARE_INTERFACE_(IDirect3DRMVisualArray, IDirect3DRMArray)
+{
+    IUNKNOWN_METHODS(PURE);
+
+    STDMETHOD_(DWORD, GetSize)(THIS) PURE;
+    STDMETHOD(GetElement)(THIS_ DWORD index, LPDIRECT3DRMVISUAL *) PURE;
+};
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRMPickedArray
+
+DECLARE_INTERFACE_(IDirect3DRMPickedArray, IDirect3DRMArray)
+{
+    IUNKNOWN_METHODS(PURE);
+
+    STDMETHOD_(DWORD, GetSize)(THIS) PURE;
+    STDMETHOD(GetPick)(THIS_ DWORD index, LPDIRECT3DRMVISUAL *, LPDIRECT3DRMFRAMEARRAY *, LPD3DRMPICKDESC) PURE;
+};
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRMLightArray
+
+DECLARE_INTERFACE_(IDirect3DRMLightArray, IDirect3DRMArray)
+{
+    IUNKNOWN_METHODS(PURE);
+
+    STDMETHOD_(DWORD, GetSize)(THIS) PURE;
+    STDMETHOD(GetElement)(THIS_ DWORD index, LPDIRECT3DRMLIGHT *) PURE;
+};
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRMFaceArray
+
+DECLARE_INTERFACE_(IDirect3DRMFaceArray, IDirect3DRMArray)
+{
+    IUNKNOWN_METHODS(PURE);
+
+    STDMETHOD_(DWORD, GetSize)(THIS) PURE;
+    STDMETHOD(GetElement)(THIS_ DWORD index, LPDIRECT3DRMFACE *) PURE;
+};
+
+#ifdef __cplusplus
+};
+#endif
+#endif /* _D3DRMOBJ_H_ */
--- /dev/null
+++ b/QW/dxsdk/sdk/inc/d3drmwin.h
@@ -1,0 +1,48 @@
+/*==========================================================================;
+ *
+ *  Copyright (C) 1995-1996 Microsoft Corporation.  All Rights Reserved.
+ *
+ *  File:       d3drm.h
+ *  Content:    Direct3DRM include file
+ *
+ ***************************************************************************/
+
+#ifndef __D3DRMWIN_H__
+#define __D3DRMWIN_H__
+
+#ifndef WIN32
+#define WIN32
+#endif
+
+#include "d3drm.h"
+#include "ddraw.h"
+#include "d3d.h"
+
+/*
+ * GUIDS used by Direct3DRM Windows interface
+ */
+DEFINE_GUID(IID_IDirect3DRMWinDevice,   0xc5016cc0, 0xd273, 0x11ce, 0xac, 0x48, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+
+WIN_TYPES(IDirect3DRMWinDevice, DIRECT3DRMWINDEVICE);
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRMWinDevice
+
+DECLARE_INTERFACE_(IDirect3DRMWinDevice, IDirect3DRMObject)
+{
+    IUNKNOWN_METHODS(PURE);
+    IDIRECT3DRMOBJECT_METHODS(PURE);
+
+    /*
+     * IDirect3DRMWinDevice methods
+     */
+
+    /* Repaint the window with the last frame which was rendered. */
+    STDMETHOD(HandlePaint)(THIS_ HDC hdc) PURE;
+
+    /* Respond to a WM_ACTIVATE message. */
+    STDMETHOD(HandleActivate)(THIS_ WORD wparam) PURE;
+};
+
+
+#endif
--- /dev/null
+++ b/QW/dxsdk/sdk/inc/d3dtypes.h
@@ -1,0 +1,956 @@
+/*==========================================================================;
+ *
+ *  Copyright (C) 1995-1996 Microsoft Corporation.  All Rights Reserved.
+ *
+ *  File:       d3dtypes.h
+ *  Content:    Direct3D types include file
+ *
+ ***************************************************************************/
+
+#ifndef _D3DTYPES_H_
+#define _D3DTYPES_H_
+
+#ifndef WIN32
+#include "subwtype.h"
+#else
+#include <windows.h>
+#endif
+
+#include <ddraw.h>
+
+#pragma pack(4)
+
+#if defined(__cplusplus)
+extern "C"
+{
+#endif
+
+/* D3DVALUE is the fundamental Direct3D fractional data type */
+
+#define D3DVALP(val, prec) ((float)(val))
+#define D3DVAL(val) ((float)(val))
+typedef float D3DVALUE, *LPD3DVALUE;
+#define D3DDivide(a, b)    (float)((double) (a) / (double) (b))
+#define D3DMultiply(a, b)    ((a) * (b))
+
+typedef LONG D3DFIXED;
+
+#ifndef RGB_MAKE
+/*
+ * Format of CI colors is
+ *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *  |    alpha      |         color index           |   fraction    |
+ *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+#define CI_GETALPHA(ci)    ((ci) >> 24)
+#define CI_GETINDEX(ci)    (((ci) >> 8) & 0xffff)
+#define CI_GETFRACTION(ci) ((ci) & 0xff)
+#define CI_ROUNDINDEX(ci)  CI_GETINDEX((ci) + 0x80)
+#define CI_MASKALPHA(ci)   ((ci) & 0xffffff)
+#define CI_MAKE(a, i, f)    (((a) << 24) | ((i) << 8) | (f))
+
+/*
+ * Format of RGBA colors is
+ *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *  |    alpha      |      red      |     green     |     blue      |
+ *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+#define RGBA_GETALPHA(rgb)      ((rgb) >> 24)
+#define RGBA_GETRED(rgb)        (((rgb) >> 16) & 0xff)
+#define RGBA_GETGREEN(rgb)      (((rgb) >> 8) & 0xff)
+#define RGBA_GETBLUE(rgb)       ((rgb) & 0xff)
+#define RGBA_MAKE(r, g, b, a)   ((D3DCOLOR) (((a) << 24) | ((r) << 16) | ((g) << 8) | (b)))
+
+/* D3DRGB and D3DRGBA may be used as initialisers for D3DCOLORs
+ * The float values must be in the range 0..1
+ */
+#define D3DRGB(r, g, b) \
+    (0xff000000L | ( ((long)((r) * 255)) << 16) | (((long)((g) * 255)) << 8) | (long)((b) * 255))
+#define D3DRGBA(r, g, b, a) \
+    (   (((long)((a) * 255)) << 24) | (((long)((r) * 255)) << 16) \
+    |   (((long)((g) * 255)) << 8) | (long)((b) * 255) \
+    )
+
+/*
+ * Format of RGB colors is
+ *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *  |    ignored    |      red      |     green     |     blue      |
+ *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+#define RGB_GETRED(rgb)         (((rgb) >> 16) & 0xff)
+#define RGB_GETGREEN(rgb)       (((rgb) >> 8) & 0xff)
+#define RGB_GETBLUE(rgb)        ((rgb) & 0xff)
+#define RGBA_SETALPHA(rgba, x) (((x) << 24) | ((rgba) & 0x00ffffff))
+#define RGB_MAKE(r, g, b)       ((D3DCOLOR) (((r) << 16) | ((g) << 8) | (b)))
+#define RGBA_TORGB(rgba)       ((D3DCOLOR) ((rgba) & 0xffffff))
+#define RGB_TORGBA(rgb)        ((D3DCOLOR) ((rgb) | 0xff000000))
+
+#endif
+
+/*
+ * Flags for Enumerate functions
+ */
+
+/*
+ * Stop the enumeration
+ */
+#define D3DENUMRET_CANCEL                        DDENUMRET_CANCEL
+
+/*
+ * Continue the enumeration
+ */
+#define D3DENUMRET_OK                            DDENUMRET_OK
+
+typedef HRESULT (WINAPI* LPD3DVALIDATECALLBACK)(LPVOID lpUserArg, DWORD dwOffset);
+typedef HRESULT (WINAPI* LPD3DENUMTEXTUREFORMATSCALLBACK)(LPDDSURFACEDESC lpDdsd, LPVOID lpContext);
+
+typedef DWORD D3DCOLOR, D3DCOLOR, *LPD3DCOLOR;
+
+typedef DWORD D3DMATERIALHANDLE, *LPD3DMATERIALHANDLE;
+typedef DWORD D3DTEXTUREHANDLE, *LPD3DTEXTUREHANDLE;
+typedef DWORD D3DMATRIXHANDLE, *LPD3DMATRIXHANDLE;
+
+typedef struct _D3DCOLORVALUE {
+    union {
+        D3DVALUE r;
+        D3DVALUE dvR;
+    };
+    union {
+        D3DVALUE g;
+        D3DVALUE dvG;
+    };
+    union {
+        D3DVALUE b;
+        D3DVALUE dvB;
+    };
+    union {
+        D3DVALUE a;
+        D3DVALUE dvA;
+    };
+} D3DCOLORVALUE;
+
+typedef struct _D3DRECT {
+    union {
+        LONG x1;
+        LONG lX1;
+    };
+    union {
+        LONG y1;
+        LONG lY1;
+    };
+    union {
+        LONG x2;
+        LONG lX2;
+    };
+    union {
+        LONG y2;
+        LONG lY2;
+    };
+} D3DRECT, *LPD3DRECT;
+
+typedef struct _D3DVECTOR {
+    union {
+        D3DVALUE x;
+        D3DVALUE dvX;
+    };
+    union {
+        D3DVALUE y;
+        D3DVALUE dvY;
+    };
+    union {
+        D3DVALUE z;
+        D3DVALUE dvZ;
+    };
+} D3DVECTOR, *LPD3DVECTOR;
+
+
+/*
+ * Vertex data types supported in an ExecuteBuffer.
+ */
+
+/*
+ * Homogeneous vertices
+ */
+
+typedef struct _D3DHVERTEX {
+    DWORD           dwFlags;        /* Homogeneous clipping flags */
+    union {
+        D3DVALUE    hx;
+        D3DVALUE    dvHX;
+    };
+    union {
+        D3DVALUE    hy;
+        D3DVALUE    dvHY;
+    };
+    union {
+        D3DVALUE    hz;
+        D3DVALUE    dvHZ;
+    };
+} D3DHVERTEX, *LPD3DHVERTEX;
+
+/*
+ * Transformed/lit vertices
+ */
+typedef struct _D3DTLVERTEX {
+    union {
+        D3DVALUE    sx;             /* Screen coordinates */
+        D3DVALUE    dvSX;
+    };
+    union {
+        D3DVALUE    sy;
+        D3DVALUE    dvSY;
+    };
+    union {
+        D3DVALUE    sz;
+        D3DVALUE    dvSZ;
+    };
+    union {
+        D3DVALUE    rhw;            /* Reciprocal of homogeneous w */
+        D3DVALUE    dvRHW;
+    };
+    union {
+        D3DCOLOR    color;          /* Vertex color */
+        D3DCOLOR    dcColor;
+    };
+    union {
+        D3DCOLOR    specular;       /* Specular component of vertex */
+        D3DCOLOR    dcSpecular;
+    };
+    union {
+        D3DVALUE    tu;             /* Texture coordinates */
+        D3DVALUE    dvTU;
+    };
+    union {
+        D3DVALUE    tv;
+        D3DVALUE    dvTV;
+    };
+} D3DTLVERTEX, *LPD3DTLVERTEX;
+
+/*
+ * Untransformed/lit vertices
+ */
+typedef struct _D3DLVERTEX {
+    union {
+        D3DVALUE     x;             /* Homogeneous coordinates */
+        D3DVALUE     dvX;
+    };
+    union {
+        D3DVALUE     y;
+        D3DVALUE     dvY;
+    };
+    union {
+        D3DVALUE     z;
+        D3DVALUE     dvZ;
+    };
+    DWORD            dwReserved;
+    union {
+        D3DCOLOR     color;         /* Vertex color */
+        D3DCOLOR     dcColor;
+    };
+    union {
+        D3DCOLOR     specular;      /* Specular component of vertex */
+        D3DCOLOR     dcSpecular;
+    };
+    union {
+        D3DVALUE     tu;            /* Texture coordinates */
+        D3DVALUE     dvTU;
+    };
+    union {
+        D3DVALUE     tv;
+        D3DVALUE     dvTV;
+    };
+} D3DLVERTEX, *LPD3DLVERTEX;
+
+/*
+ * Untransformed/unlit vertices
+ */
+
+typedef struct _D3DVERTEX {
+    union {
+        D3DVALUE     x;             /* Homogeneous coordinates */
+        D3DVALUE     dvX;
+    };
+    union {
+        D3DVALUE     y;
+        D3DVALUE     dvY;
+    };
+    union {
+        D3DVALUE     z;
+        D3DVALUE     dvZ;
+    };
+    union {
+        D3DVALUE     nx;            /* Normal */
+        D3DVALUE     dvNX;
+    };
+    union {
+        D3DVALUE     ny;
+        D3DVALUE     dvNY;
+    };
+    union {
+        D3DVALUE     nz;
+        D3DVALUE     dvNZ;
+    };
+    union {
+        D3DVALUE     tu;            /* Texture coordinates */
+        D3DVALUE     dvTU;
+    };
+    union {
+        D3DVALUE     tv;
+        D3DVALUE     dvTV;
+    };
+} D3DVERTEX, *LPD3DVERTEX;
+
+/*
+ * Matrix, viewport, and tranformation structures and definitions.
+ */
+
+typedef struct _D3DMATRIX {
+    D3DVALUE        _11, _12, _13, _14;
+    D3DVALUE        _21, _22, _23, _24;
+    D3DVALUE        _31, _32, _33, _34;
+    D3DVALUE        _41, _42, _43, _44;
+} D3DMATRIX, *LPD3DMATRIX;
+
+typedef struct _D3DVIEWPORT {
+    DWORD       dwSize;
+    DWORD       dwX;
+    DWORD       dwY;            /* Top left */
+    DWORD       dwWidth;
+    DWORD       dwHeight;       /* Dimensions */
+    D3DVALUE    dvScaleX;       /* Scale homogeneous to screen */
+    D3DVALUE    dvScaleY;       /* Scale homogeneous to screen */
+    D3DVALUE    dvMaxX;         /* Min/max homogeneous x coord */
+    D3DVALUE    dvMaxY;         /* Min/max homogeneous y coord */
+    D3DVALUE    dvMinZ;
+    D3DVALUE    dvMaxZ;         /* Min/max homogeneous z coord */
+} D3DVIEWPORT, *LPD3DVIEWPORT;
+
+/*
+ * Values for clip fields.
+ */
+#define D3DCLIP_LEFT                            0x00000001L
+#define D3DCLIP_RIGHT                           0x00000002L
+#define D3DCLIP_TOP                             0x00000004L
+#define D3DCLIP_BOTTOM                          0x00000008L
+#define D3DCLIP_FRONT                           0x00000010L
+#define D3DCLIP_BACK                            0x00000020L
+#define D3DCLIP_GEN0                            0x00000040L
+#define D3DCLIP_GEN1                            0x00000080L
+#define D3DCLIP_GEN2                            0x00000100L
+#define D3DCLIP_GEN3                            0x00000200L
+#define D3DCLIP_GEN4                            0x00000400L
+#define D3DCLIP_GEN5                            0x00000800L
+
+/*
+ * Values for d3d status.
+ */
+#define D3DSTATUS_CLIPUNIONLEFT                 D3DCLIP_LEFT
+#define D3DSTATUS_CLIPUNIONRIGHT                D3DCLIP_RIGHT
+#define D3DSTATUS_CLIPUNIONTOP                  D3DCLIP_TOP
+#define D3DSTATUS_CLIPUNIONBOTTOM               D3DCLIP_BOTTOM
+#define D3DSTATUS_CLIPUNIONFRONT                D3DCLIP_FRONT
+#define D3DSTATUS_CLIPUNIONBACK                 D3DCLIP_BACK
+#define D3DSTATUS_CLIPUNIONGEN0                 D3DCLIP_GEN0
+#define D3DSTATUS_CLIPUNIONGEN1                 D3DCLIP_GEN1
+#define D3DSTATUS_CLIPUNIONGEN2                 D3DCLIP_GEN2
+#define D3DSTATUS_CLIPUNIONGEN3                 D3DCLIP_GEN3
+#define D3DSTATUS_CLIPUNIONGEN4                 D3DCLIP_GEN4
+#define D3DSTATUS_CLIPUNIONGEN5                 D3DCLIP_GEN5
+
+#define D3DSTATUS_CLIPINTERSECTIONLEFT          0x00001000L
+#define D3DSTATUS_CLIPINTERSECTIONRIGHT         0x00002000L
+#define D3DSTATUS_CLIPINTERSECTIONTOP           0x00004000L
+#define D3DSTATUS_CLIPINTERSECTIONBOTTOM        0x00008000L
+#define D3DSTATUS_CLIPINTERSECTIONFRONT         0x00010000L
+#define D3DSTATUS_CLIPINTERSECTIONBACK          0x00020000L
+#define D3DSTATUS_CLIPINTERSECTIONGEN0          0x00040000L
+#define D3DSTATUS_CLIPINTERSECTIONGEN1          0x00080000L
+#define D3DSTATUS_CLIPINTERSECTIONGEN2          0x00100000L
+#define D3DSTATUS_CLIPINTERSECTIONGEN3          0x00200000L
+#define D3DSTATUS_CLIPINTERSECTIONGEN4          0x00400000L
+#define D3DSTATUS_CLIPINTERSECTIONGEN5          0x00800000L
+#define D3DSTATUS_ZNOTVISIBLE                   0x01000000L
+
+#define D3DSTATUS_CLIPUNIONALL  (               \
+            D3DSTATUS_CLIPUNIONLEFT     |       \
+            D3DSTATUS_CLIPUNIONRIGHT    |       \
+            D3DSTATUS_CLIPUNIONTOP      |       \
+            D3DSTATUS_CLIPUNIONBOTTOM   |       \
+            D3DSTATUS_CLIPUNIONFRONT    |       \
+            D3DSTATUS_CLIPUNIONBACK     |       \
+            D3DSTATUS_CLIPUNIONGEN0     |       \
+            D3DSTATUS_CLIPUNIONGEN1     |       \
+            D3DSTATUS_CLIPUNIONGEN2     |       \
+            D3DSTATUS_CLIPUNIONGEN3     |       \
+            D3DSTATUS_CLIPUNIONGEN4     |       \
+            D3DSTATUS_CLIPUNIONGEN5             \
+            )
+
+#define D3DSTATUS_CLIPINTERSECTIONALL   (               \
+            D3DSTATUS_CLIPINTERSECTIONLEFT      |       \
+            D3DSTATUS_CLIPINTERSECTIONRIGHT     |       \
+            D3DSTATUS_CLIPINTERSECTIONTOP       |       \
+            D3DSTATUS_CLIPINTERSECTIONBOTTOM    |       \
+            D3DSTATUS_CLIPINTERSECTIONFRONT     |       \
+            D3DSTATUS_CLIPINTERSECTIONBACK      |       \
+            D3DSTATUS_CLIPINTERSECTIONGEN0      |       \
+            D3DSTATUS_CLIPINTERSECTIONGEN1      |       \
+            D3DSTATUS_CLIPINTERSECTIONGEN2      |       \
+            D3DSTATUS_CLIPINTERSECTIONGEN3      |       \
+            D3DSTATUS_CLIPINTERSECTIONGEN4      |       \
+            D3DSTATUS_CLIPINTERSECTIONGEN5              \
+            )
+
+#define D3DSTATUS_DEFAULT       (                       \
+            D3DSTATUS_CLIPINTERSECTIONALL       |       \
+            D3DSTATUS_ZNOTVISIBLE)
+
+
+/*
+ * Options for direct transform calls
+ */
+#define D3DTRANSFORM_CLIPPED       0x00000001l
+#define D3DTRANSFORM_UNCLIPPED     0x00000002l
+
+typedef struct _D3DTRANSFORMDATA {
+    DWORD           dwSize;
+    LPVOID          lpIn;           /* Input vertices */
+    DWORD           dwInSize;       /* Stride of input vertices */
+    LPVOID          lpOut;          /* Output vertices */
+    DWORD           dwOutSize;      /* Stride of output vertices */
+    LPD3DHVERTEX    lpHOut;         /* Output homogeneous vertices */
+    DWORD           dwClip;         /* Clipping hint */
+    DWORD           dwClipIntersection;
+    DWORD           dwClipUnion;    /* Union of all clip flags */
+    D3DRECT         drExtent;       /* Extent of transformed vertices */
+} D3DTRANSFORMDATA, *LPD3DTRANSFORMDATA;
+
+/*
+ * Structure defining position and direction properties for lighting.
+ */
+typedef struct _D3DLIGHTINGELEMENT {
+    D3DVECTOR dvPosition;           /* Lightable point in model space */
+    D3DVECTOR dvNormal;             /* Normalised unit vector */
+} D3DLIGHTINGELEMENT, *LPD3DLIGHTINGELEMENT;
+
+/*
+ * Structure defining material properties for lighting.
+ */
+typedef struct _D3DMATERIAL {
+    DWORD               dwSize;
+    union {
+        D3DCOLORVALUE   diffuse;        /* Diffuse color RGBA */
+        D3DCOLORVALUE   dcvDiffuse;
+    };
+    union {
+        D3DCOLORVALUE   ambient;        /* Ambient color RGB */
+        D3DCOLORVALUE   dcvAmbient;
+    };
+    union {
+        D3DCOLORVALUE   specular;       /* Specular 'shininess' */
+        D3DCOLORVALUE   dcvSpecular;
+    };
+    union {
+        D3DCOLORVALUE   emissive;       /* Emissive color RGB */
+        D3DCOLORVALUE   dcvEmissive;
+    };
+    union {
+        D3DVALUE        power;          /* Sharpness if specular highlight */
+        D3DVALUE        dvPower;
+    };
+    D3DTEXTUREHANDLE    hTexture;       /* Handle to texture map */
+    DWORD               dwRampSize;
+} D3DMATERIAL, *LPD3DMATERIAL;
+
+typedef enum _D3DLIGHTTYPE {
+    D3DLIGHT_POINT          = 1,
+    D3DLIGHT_SPOT           = 2,
+    D3DLIGHT_DIRECTIONAL    = 3,
+    D3DLIGHT_PARALLELPOINT  = 4,
+    D3DLIGHT_GLSPOT         = 5,
+} D3DLIGHTTYPE;
+
+/*
+ * Structure defining a light source and its properties.
+ */
+typedef struct _D3DLIGHT {
+    DWORD           dwSize;
+    D3DLIGHTTYPE    dltType;            /* Type of light source */
+    D3DCOLORVALUE   dcvColor;           /* Color of light */
+    D3DVECTOR       dvPosition;         /* Position in world space */
+    D3DVECTOR       dvDirection;        /* Direction in world space */
+    D3DVALUE        dvRange;            /* Cutoff range */
+    D3DVALUE        dvFalloff;          /* Falloff */
+    D3DVALUE        dvAttenuation0;     /* Constant attenuation */
+    D3DVALUE        dvAttenuation1;     /* Linear attenuation */
+    D3DVALUE        dvAttenuation2;     /* Quadratic attenuation */
+    D3DVALUE        dvTheta;            /* Inner angle of spotlight cone */
+    D3DVALUE        dvPhi;              /* Outer angle of spotlight cone */
+} D3DLIGHT, *LPD3DLIGHT;
+
+typedef struct _D3DLIGHTDATA {
+    DWORD                dwSize;
+    LPD3DLIGHTINGELEMENT lpIn;          /* Input positions and normals */
+    DWORD                dwInSize;      /* Stride of input elements */
+    LPD3DTLVERTEX        lpOut;         /* Output colors */
+    DWORD                dwOutSize;     /* Stride of output colors */
+} D3DLIGHTDATA, *LPD3DLIGHTDATA;
+
+typedef enum _D3DCOLORMODEL {
+    D3DCOLOR_MONO           = 1,
+    D3DCOLOR_RGB            = 2,
+} D3DCOLORMODEL;
+
+/*
+ * Options for clearing
+ */
+#define D3DCLEAR_TARGET            0x00000001l /* Clear target surface */
+#define D3DCLEAR_ZBUFFER           0x00000002l /* Clear target z buffer */
+
+/*
+ * Execute buffers are allocated via Direct3D.  These buffers may then
+ * be filled by the application with instructions to execute along with
+ * vertex data.
+ */
+
+/*
+ * Supported op codes for execute instructions.
+ */
+typedef enum _D3DOPCODE {
+    D3DOP_POINT                 = 1,
+    D3DOP_LINE                  = 2,
+    D3DOP_TRIANGLE              = 3,
+    D3DOP_MATRIXLOAD            = 4,
+    D3DOP_MATRIXMULTIPLY        = 5,
+    D3DOP_STATETRANSFORM        = 6,
+    D3DOP_STATELIGHT            = 7,
+    D3DOP_STATERENDER           = 8,
+    D3DOP_PROCESSVERTICES       = 9,
+    D3DOP_TEXTURELOAD           = 10,
+    D3DOP_EXIT                  = 11,
+    D3DOP_BRANCHFORWARD         = 12,
+    D3DOP_SPAN                  = 13,
+    D3DOP_SETSTATUS             = 14,
+} D3DOPCODE;
+
+typedef struct _D3DINSTRUCTION {
+    BYTE bOpcode;   /* Instruction opcode */
+    BYTE bSize;     /* Size of each instruction data unit */
+    WORD wCount;    /* Count of instruction data units to follow */
+} D3DINSTRUCTION, *LPD3DINSTRUCTION;
+
+/*
+ * Structure for texture loads
+ */
+typedef struct _D3DTEXTURELOAD {
+    D3DTEXTUREHANDLE hDestTexture;
+    D3DTEXTUREHANDLE hSrcTexture;
+} D3DTEXTURELOAD, *LPD3DTEXTURELOAD;
+
+/*
+ * Structure for picking
+ */
+typedef struct _D3DPICKRECORD {
+    BYTE     bOpcode;
+    BYTE     bPad;
+    DWORD    dwOffset;
+    D3DVALUE dvZ;
+} D3DPICKRECORD, *LPD3DPICKRECORD;
+
+/*
+ * The following defines the rendering states which can be set in the
+ * execute buffer.
+ */
+
+typedef enum _D3DSHADEMODE {
+    D3DSHADE_FLAT              = 1,
+    D3DSHADE_GOURAUD           = 2,
+    D3DSHADE_PHONG             = 3,
+} D3DSHADEMODE;
+
+typedef enum _D3DFILLMODE {
+    D3DFILL_POINT              = 1,
+    D3DFILL_WIREFRAME          = 2,
+    D3DFILL_SOLID              = 3,
+} D3DFILLMODE;
+
+typedef struct _D3DLINEPATTERN {
+    WORD        wRepeatFactor;
+    WORD        wLinePattern;
+} D3DLINEPATTERN;
+
+typedef enum _D3DTEXTUREFILTER {
+    D3DFILTER_NEAREST          = 1,
+    D3DFILTER_LINEAR           = 2,
+    D3DFILTER_MIPNEAREST       = 3,
+    D3DFILTER_MIPLINEAR        = 4,
+    D3DFILTER_LINEARMIPNEAREST = 5,
+    D3DFILTER_LINEARMIPLINEAR  = 6,
+} D3DTEXTUREFILTER;
+
+typedef enum _D3DBLEND {
+    D3DBLEND_ZERO              = 1,
+    D3DBLEND_ONE               = 2,
+    D3DBLEND_SRCCOLOR          = 3,
+    D3DBLEND_INVSRCCOLOR       = 4,
+    D3DBLEND_SRCALPHA          = 5,
+    D3DBLEND_INVSRCALPHA       = 6,
+    D3DBLEND_DESTALPHA         = 7,
+    D3DBLEND_INVDESTALPHA      = 8,
+    D3DBLEND_DESTCOLOR         = 9,
+    D3DBLEND_INVDESTCOLOR      = 10,
+    D3DBLEND_SRCALPHASAT       = 11,
+    D3DBLEND_BOTHSRCALPHA      = 12,
+    D3DBLEND_BOTHINVSRCALPHA   = 13,
+} D3DBLEND;
+
+typedef enum _D3DTEXTUREBLEND {
+    D3DTBLEND_DECAL            = 1,
+    D3DTBLEND_MODULATE         = 2,
+    D3DTBLEND_DECALALPHA       = 3,
+    D3DTBLEND_MODULATEALPHA    = 4,
+    D3DTBLEND_DECALMASK        = 5,
+    D3DTBLEND_MODULATEMASK     = 6,
+    D3DTBLEND_COPY             = 7,
+} D3DTEXTUREBLEND;
+
+typedef enum _D3DTEXTUREADDRESS {
+    D3DTADDRESS_WRAP           = 1,
+    D3DTADDRESS_MIRROR         = 2,
+    D3DTADDRESS_CLAMP          = 3,
+} D3DTEXTUREADDRESS;
+
+typedef enum _D3DCULL {
+    D3DCULL_NONE               = 1,
+    D3DCULL_CW                 = 2,
+    D3DCULL_CCW                = 3,
+} D3DCULL;
+
+typedef enum _D3DCMPFUNC {
+    D3DCMP_NEVER               = 1,
+    D3DCMP_LESS                = 2,
+    D3DCMP_EQUAL               = 3,
+    D3DCMP_LESSEQUAL           = 4,
+    D3DCMP_GREATER             = 5,
+    D3DCMP_NOTEQUAL            = 6,
+    D3DCMP_GREATEREQUAL        = 7,
+    D3DCMP_ALWAYS              = 8,
+} D3DCMPFUNC;
+
+typedef enum _D3DFOGMODE {
+    D3DFOG_NONE                = 0,
+    D3DFOG_EXP                 = 1,
+    D3DFOG_EXP2                = 2,
+    D3DFOG_LINEAR              = 3
+} D3DFOGMODE;
+
+/*
+ * Amount to add to a state to generate the override for that state.
+ */
+#define D3DSTATE_OVERRIDE_BIAS          256
+
+/*
+ * A state which sets the override flag for the specified state type.
+ */
+#define D3DSTATE_OVERRIDE(type) ((DWORD) (type) + D3DSTATE_OVERRIDE_BIAS)
+
+typedef enum _D3DTRANSFORMSTATETYPE {
+    D3DTRANSFORMSTATE_WORLD           = 1,
+    D3DTRANSFORMSTATE_VIEW            = 2,
+    D3DTRANSFORMSTATE_PROJECTION      = 3,
+} D3DTRANSFORMSTATETYPE;
+
+typedef enum _D3DLIGHTSTATETYPE {
+    D3DLIGHTSTATE_MATERIAL            = 1,
+    D3DLIGHTSTATE_AMBIENT             = 2,
+    D3DLIGHTSTATE_COLORMODEL          = 3,
+    D3DLIGHTSTATE_FOGMODE             = 4,
+    D3DLIGHTSTATE_FOGSTART            = 5,
+    D3DLIGHTSTATE_FOGEND              = 6,
+    D3DLIGHTSTATE_FOGDENSITY          = 7,
+} D3DLIGHTSTATETYPE;
+
+typedef enum _D3DRENDERSTATETYPE {
+    D3DRENDERSTATE_TEXTUREHANDLE      = 1,    /* Texture handle */
+    D3DRENDERSTATE_ANTIALIAS          = 2,    /* Antialiasing prim edges */
+    D3DRENDERSTATE_TEXTUREADDRESS     = 3,    /* D3DTEXTUREADDRESS      */
+    D3DRENDERSTATE_TEXTUREPERSPECTIVE = 4,    /* TRUE for perspective correction */
+    D3DRENDERSTATE_WRAPU              = 5,    /* TRUE for wrapping in u */
+    D3DRENDERSTATE_WRAPV              = 6,    /* TRUE for wrapping in v */
+    D3DRENDERSTATE_ZENABLE            = 7,    /* TRUE to enable z test */
+    D3DRENDERSTATE_FILLMODE           = 8,    /* D3DFILL_MODE            */
+    D3DRENDERSTATE_SHADEMODE          = 9,    /* D3DSHADEMODE */
+    D3DRENDERSTATE_LINEPATTERN        = 10,   /* D3DLINEPATTERN */
+    D3DRENDERSTATE_MONOENABLE         = 11,   /* TRUE to enable mono rasterization */
+    D3DRENDERSTATE_ROP2               = 12,   /* ROP2 */
+    D3DRENDERSTATE_PLANEMASK          = 13,   /* DWORD physical plane mask */
+    D3DRENDERSTATE_ZWRITEENABLE       = 14,   /* TRUE to enable z writes */
+    D3DRENDERSTATE_ALPHATESTENABLE    = 15,   /* TRUE to enable alpha tests */
+    D3DRENDERSTATE_LASTPIXEL          = 16,   /* TRUE for last-pixel on lines */
+    D3DRENDERSTATE_TEXTUREMAG         = 17,   /* D3DTEXTUREFILTER */
+    D3DRENDERSTATE_TEXTUREMIN         = 18,   /* D3DTEXTUREFILTER */
+    D3DRENDERSTATE_SRCBLEND           = 19,   /* D3DBLEND */
+    D3DRENDERSTATE_DESTBLEND          = 20,   /* D3DBLEND */
+    D3DRENDERSTATE_TEXTUREMAPBLEND    = 21,   /* D3DTEXTUREBLEND */
+    D3DRENDERSTATE_CULLMODE           = 22,   /* D3DCULL */
+    D3DRENDERSTATE_ZFUNC              = 23,   /* D3DCMPFUNC */
+    D3DRENDERSTATE_ALPHAREF           = 24,   /* D3DFIXED */
+    D3DRENDERSTATE_ALPHAFUNC          = 25,   /* D3DCMPFUNC */
+    D3DRENDERSTATE_DITHERENABLE       = 26,   /* TRUE to enable dithering */
+    D3DRENDERSTATE_BLENDENABLE        = 27,   /* TRUE to enable alpha blending */
+    D3DRENDERSTATE_FOGENABLE          = 28,   /* TRUE to enable fog */
+    D3DRENDERSTATE_SPECULARENABLE     = 29,   /* TRUE to enable specular */
+    D3DRENDERSTATE_ZVISIBLE           = 30,   /* TRUE to enable z checking */
+    D3DRENDERSTATE_SUBPIXEL           = 31,   /* TRUE to enable subpixel correction */
+    D3DRENDERSTATE_SUBPIXELX          = 32,   /* TRUE to enable correction in X only */
+    D3DRENDERSTATE_STIPPLEDALPHA      = 33,   /* TRUE to enable stippled alpha */
+    D3DRENDERSTATE_FOGCOLOR           = 34,   /* D3DCOLOR */
+    D3DRENDERSTATE_FOGTABLEMODE       = 35,   /* D3DFOGMODE */
+    D3DRENDERSTATE_FOGTABLESTART      = 36,   /* Fog table start        */
+    D3DRENDERSTATE_FOGTABLEEND        = 37,   /* Fog table end          */
+    D3DRENDERSTATE_FOGTABLEDENSITY    = 38,   /* Fog table density      */
+    D3DRENDERSTATE_STIPPLEENABLE      = 39,   /* TRUE to enable stippling */
+    D3DRENDERSTATE_STIPPLEPATTERN00   = 64,   /* Stipple pattern 01...  */      
+    D3DRENDERSTATE_STIPPLEPATTERN01   = 65,
+    D3DRENDERSTATE_STIPPLEPATTERN02   = 66,
+    D3DRENDERSTATE_STIPPLEPATTERN03   = 67,
+    D3DRENDERSTATE_STIPPLEPATTERN04   = 68,
+    D3DRENDERSTATE_STIPPLEPATTERN05   = 69,
+    D3DRENDERSTATE_STIPPLEPATTERN06   = 70,
+    D3DRENDERSTATE_STIPPLEPATTERN07   = 71,
+    D3DRENDERSTATE_STIPPLEPATTERN08   = 72,
+    D3DRENDERSTATE_STIPPLEPATTERN09   = 73,
+    D3DRENDERSTATE_STIPPLEPATTERN10   = 74,
+    D3DRENDERSTATE_STIPPLEPATTERN11   = 75,
+    D3DRENDERSTATE_STIPPLEPATTERN12   = 76,
+    D3DRENDERSTATE_STIPPLEPATTERN13   = 77,
+    D3DRENDERSTATE_STIPPLEPATTERN14   = 78,
+    D3DRENDERSTATE_STIPPLEPATTERN15   = 79,
+    D3DRENDERSTATE_STIPPLEPATTERN16   = 80,
+    D3DRENDERSTATE_STIPPLEPATTERN17   = 81,
+    D3DRENDERSTATE_STIPPLEPATTERN18   = 82,
+    D3DRENDERSTATE_STIPPLEPATTERN19   = 83,
+    D3DRENDERSTATE_STIPPLEPATTERN20   = 84,
+    D3DRENDERSTATE_STIPPLEPATTERN21   = 85,
+    D3DRENDERSTATE_STIPPLEPATTERN22   = 86,
+    D3DRENDERSTATE_STIPPLEPATTERN23   = 87,
+    D3DRENDERSTATE_STIPPLEPATTERN24   = 88,
+    D3DRENDERSTATE_STIPPLEPATTERN25   = 89,
+    D3DRENDERSTATE_STIPPLEPATTERN26   = 90,
+    D3DRENDERSTATE_STIPPLEPATTERN27   = 91,
+    D3DRENDERSTATE_STIPPLEPATTERN28   = 92,
+    D3DRENDERSTATE_STIPPLEPATTERN29   = 93,
+    D3DRENDERSTATE_STIPPLEPATTERN30   = 94,
+    D3DRENDERSTATE_STIPPLEPATTERN31   = 95,
+} D3DRENDERSTATETYPE;
+
+#define D3DRENDERSTATE_STIPPLEPATTERN(y) (D3DRENDERSTATE_STIPPLEPATTERN00 + (y))
+
+typedef struct _D3DSTATE {
+    union {
+        D3DTRANSFORMSTATETYPE   dtstTransformStateType;
+        D3DLIGHTSTATETYPE       dlstLightStateType;
+        D3DRENDERSTATETYPE      drstRenderStateType;
+    };
+    union {
+        DWORD                   dwArg[1];
+        D3DVALUE                dvArg[1];
+    };
+} D3DSTATE, *LPD3DSTATE;
+
+/*
+ * Operation used to load matrices
+ * hDstMat = hSrcMat
+ */
+typedef struct _D3DMATRIXLOAD {
+    D3DMATRIXHANDLE hDestMatrix;   /* Destination matrix */
+    D3DMATRIXHANDLE hSrcMatrix;   /* Source matrix */
+} D3DMATRIXLOAD, *LPD3DMATRIXLOAD;
+
+/*
+ * Operation used to multiply matrices
+ * hDstMat = hSrcMat1 * hSrcMat2
+ */
+typedef struct _D3DMATRIXMULTIPLY {
+    D3DMATRIXHANDLE hDestMatrix;   /* Destination matrix */
+    D3DMATRIXHANDLE hSrcMatrix1;  /* First source matrix */
+    D3DMATRIXHANDLE hSrcMatrix2;  /* Second source matrix */
+} D3DMATRIXMULTIPLY, *LPD3DMATRIXMULTIPLY;
+
+/*
+ * Operation used to transform and light vertices.
+ */
+typedef struct _D3DPROCESSVERTICES {
+    DWORD        dwFlags;    /* Do we transform or light or just copy? */
+    WORD         wStart;     /* Index to first vertex in source */
+    WORD         wDest;      /* Index to first vertex in local buffer */
+    DWORD        dwCount;    /* Number of vertices to be processed */
+    DWORD        dwReserved; /* Must be zero */
+} D3DPROCESSVERTICES, *LPD3DPROCESSVERTICES;
+
+#define D3DPROCESSVERTICES_TRANSFORMLIGHT       0x00000000L
+#define D3DPROCESSVERTICES_TRANSFORM            0x00000001L
+#define D3DPROCESSVERTICES_COPY                 0x00000002L
+#define D3DPROCESSVERTICES_OPMASK               0x00000007L
+
+#define D3DPROCESSVERTICES_UPDATEEXTENTS        0x00000008L
+#define D3DPROCESSVERTICES_NOCOLOR              0x00000010L
+
+
+/*
+ * Triangle flags
+ */
+ 
+/*
+ * Tri strip and fan flags.
+ * START loads all three vertices
+ * EVEN and ODD load just v3 with even or odd culling
+ * START_FLAT contains a count from 0 to 29 that allows the
+ * whole strip or fan to be culled in one hit.
+ * e.g. for a quad len = 1
+ */
+#define D3DTRIFLAG_START                        0x00000000L
+#define D3DTRIFLAG_STARTFLAT(len) (len)         /* 0 < len < 30 */
+#define D3DTRIFLAG_ODD                          0x0000001eL
+#define D3DTRIFLAG_EVEN                         0x0000001fL
+
+/*
+ * Triangle edge flags
+ * enable edges for wireframe or antialiasing
+ */
+#define D3DTRIFLAG_EDGEENABLE1                  0x00000100L /* v0-v1 edge */
+#define D3DTRIFLAG_EDGEENABLE2                  0x00000200L /* v1-v2 edge */
+#define D3DTRIFLAG_EDGEENABLE3                  0x00000400L /* v2-v0 edge */
+#define D3DTRIFLAG_EDGEENABLETRIANGLE \
+        (D3DTRIFLAG_EDGEENABLE1 | D3DTRIFLAG_EDGEENABLE2 | D3DTRIFLAG_EDGEENABLE3)
+        
+/*
+ * Primitive structures and related defines.  Vertex offsets are to types
+ * D3DVERTEX, D3DLVERTEX, or D3DTLVERTEX.
+ */
+
+/*
+ * Triangle list primitive structure
+ */
+typedef struct _D3DTRIANGLE {
+    union {
+        WORD    v1;            /* Vertex indices */
+        WORD    wV1;
+    };
+    union {
+        WORD    v2;
+        WORD    wV2;
+    };
+    union {
+        WORD    v3;
+        WORD    wV3;
+    };
+    WORD        wFlags;       /* Edge (and other) flags */
+} D3DTRIANGLE, *LPD3DTRIANGLE;
+
+/*
+ * Line strip structure.
+ * The instruction count - 1 defines the number of line segments.
+ */
+typedef struct _D3DLINE {
+    union {
+        WORD    v1;            /* Vertex indices */
+        WORD    wV1;
+    };
+    union {
+        WORD    v2;
+        WORD    wV2;
+    };
+} D3DLINE, *LPD3DLINE;
+
+/*
+ * Span structure
+ * Spans join a list of points with the same y value.
+ * If the y value changes, a new span is started.
+ */
+typedef struct _D3DSPAN {
+    WORD        wCount; /* Number of spans */
+    WORD        wFirst; /* Index to first vertex */
+} D3DSPAN, *LPD3DSPAN;
+
+/*
+ * Point structure
+ */
+typedef struct _D3DPOINT {
+    WORD        wCount;         /* number of points         */
+    WORD        wFirst;         /* index to first vertex    */
+} D3DPOINT, *LPD3DPOINT;
+
+
+/*
+ * Forward branch structure.
+ * Mask is logically anded with the driver status mask
+ * if the result equals 'value', the branch is taken.
+ */
+typedef struct _D3DBRANCH {
+    DWORD       dwMask;         /* Bitmask against D3D status */
+    DWORD       dwValue;
+    BOOL        bNegate;        /* TRUE to negate comparison */
+    DWORD       dwOffset;       /* How far to branch forward (0 for exit)*/
+} D3DBRANCH, *LPD3DBRANCH;
+
+/*
+ * Status used for set status instruction.
+ * The D3D status is initialised on device creation
+ * and is modified by all execute calls.
+ */
+typedef struct _D3DSTATUS {
+    DWORD       dwFlags;        /* Do we set extents or status */
+    DWORD       dwStatus;       /* D3D status */
+    D3DRECT     drExtent;
+} D3DSTATUS, *LPD3DSTATUS;
+
+#define D3DSETSTATUS_STATUS             0x00000001L
+#define D3DSETSTATUS_EXTENTS            0x00000002L
+#define D3DSETSTATUS_ALL        (D3DSETSTATUS_STATUS | D3DSETSTATUS_EXTENTS)
+
+/*
+ * Statistics structure
+ */
+typedef struct _D3DSTATS {
+    DWORD        dwSize;
+    DWORD        dwTrianglesDrawn;
+    DWORD        dwLinesDrawn;
+    DWORD        dwPointsDrawn;
+    DWORD        dwSpansDrawn;
+    DWORD        dwVerticesProcessed;
+} D3DSTATS, *LPD3DSTATS;
+
+/*
+ * Execute options.
+ * When calling using D3DEXECUTE_UNCLIPPED all the primitives 
+ * inside the buffer must be contained within the viewport.
+ */
+#define D3DEXECUTE_CLIPPED       0x00000001l
+#define D3DEXECUTE_UNCLIPPED     0x00000002l
+
+typedef struct _D3DEXECUTEDATA {
+    DWORD       dwSize;
+    DWORD       dwVertexOffset;
+    DWORD       dwVertexCount;
+    DWORD       dwInstructionOffset;
+    DWORD       dwInstructionLength;
+    DWORD       dwHVertexOffset;
+    D3DSTATUS   dsStatus;       /* Status after execute */
+} D3DEXECUTEDATA, *LPD3DEXECUTEDATA;
+
+/*
+ * Palette flags.
+ * This are or'ed with the peFlags in the PALETTEENTRYs passed to DirectDraw.
+ */
+#define D3DPAL_FREE     0x00    /* Renderer may use this entry freely */
+#define D3DPAL_READONLY 0x40    /* Renderer may not set this entry */
+#define D3DPAL_RESERVED 0x80    /* Renderer may not use this entry */
+
+#if defined(__cplusplus)
+};
+#endif
+
+#pragma pack()
+
+#endif /* _D3DTYPES_H_ */
--- /dev/null
+++ b/QW/dxsdk/sdk/inc/ddraw.h
@@ -1,0 +1,3102 @@
+/*==========================================================================;
+ *
+ *  Copyright (C) 1994-1996 Microsoft Corporation.  All Rights Reserved.
+ *
+ *  File:       ddraw.h
+ *  Content:    DirectDraw include file
+ *
+ ***************************************************************************/
+
+#ifndef __DDRAW_INCLUDED__
+#define __DDRAW_INCLUDED__
+#if defined( _WIN32 )  && !defined( _NO_COM )
+#define COM_NO_WINDOWS_H
+#include <objbase.h>
+#else
+#define IUnknown            void
+#define CO_E_NOTINITIALIZED 0x800401F0L
+#endif
+
+#define _FACDD  0x876
+#define MAKE_DDHRESULT( code )  MAKE_HRESULT( 1, _FACDD, code )
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * GUIDS used by DirectDraw objects
+ */
+#if defined( _WIN32 ) && !defined( _NO_COM )
+DEFINE_GUID( CLSID_DirectDraw,                  0xD7B70EE0,0x4340,0x11CF,0xB0,0x63,0x00,0x20,0xAF,0xC2,0xCD,0x35 );
+DEFINE_GUID( CLSID_DirectDrawClipper,           0x593817A0,0x7DB3,0x11CF,0xA2,0xDE,0x00,0xAA,0x00,0xb9,0x33,0x56 );
+DEFINE_GUID( IID_IDirectDraw,                   0x6C14DB80,0xA733,0x11CE,0xA5,0x21,0x00,0x20,0xAF,0x0B,0xE5,0x60 );
+DEFINE_GUID( IID_IDirectDraw2,                  0xB3A6F3E0,0x2B43,0x11CF,0xA2,0xDE,0x00,0xAA,0x00,0xB9,0x33,0x56 );
+DEFINE_GUID( IID_IDirectDrawSurface,            0x6C14DB81,0xA733,0x11CE,0xA5,0x21,0x00,0x20,0xAF,0x0B,0xE5,0x60 );
+DEFINE_GUID( IID_IDirectDrawSurface2,           0x57805885,0x6eec,0x11cf,0x94,0x41,0xa8,0x23,0x03,0xc1,0x0e,0x27 );
+
+DEFINE_GUID( IID_IDirectDrawPalette,            0x6C14DB84,0xA733,0x11CE,0xA5,0x21,0x00,0x20,0xAF,0x0B,0xE5,0x60 );
+DEFINE_GUID( IID_IDirectDrawClipper,            0x6C14DB85,0xA733,0x11CE,0xA5,0x21,0x00,0x20,0xAF,0x0B,0xE5,0x60 );
+                 
+#endif
+
+/*============================================================================
+ *
+ * DirectDraw Structures
+ *
+ * Various structures used to invoke DirectDraw.
+ *
+ *==========================================================================*/
+
+struct IDirectDraw;
+struct IDirectDrawSurface;
+struct IDirectDrawPalette;
+struct IDirectDrawClipper;
+
+typedef struct IDirectDraw                      FAR *LPDIRECTDRAW;
+typedef struct IDirectDraw2                     FAR *LPDIRECTDRAW2;
+typedef struct IDirectDrawSurface               FAR *LPDIRECTDRAWSURFACE;
+typedef struct IDirectDrawSurface2              FAR *LPDIRECTDRAWSURFACE2;
+
+typedef struct IDirectDrawPalette               FAR *LPDIRECTDRAWPALETTE;
+typedef struct IDirectDrawClipper               FAR *LPDIRECTDRAWCLIPPER;
+
+typedef struct _DDFXROP                 FAR *LPDDFXROP;
+typedef struct _DDSURFACEDESC           FAR *LPDDSURFACEDESC;
+
+/*
+ * API's
+ */
+#if (defined (WIN32) || defined( _WIN32 ) ) && !defined( _NO_COM )
+//#if defined( _WIN32 ) && !defined( _NO_ENUM )
+    typedef BOOL (FAR PASCAL * LPDDENUMCALLBACKA)(GUID FAR *, LPSTR, LPSTR, LPVOID);
+    typedef BOOL (FAR PASCAL * LPDDENUMCALLBACKW)(GUID FAR *, LPWSTR, LPWSTR, LPVOID);
+    extern HRESULT WINAPI DirectDrawEnumerateW( LPDDENUMCALLBACKW lpCallback, LPVOID lpContext );
+    extern HRESULT WINAPI DirectDrawEnumerateA( LPDDENUMCALLBACKA lpCallback, LPVOID lpContext );
+    #ifdef UNICODE
+        typedef LPDDENUMCALLBACKW       LPDDENUMCALLBACK;
+        #define DirectDrawEnumerate     DirectDrawEnumerateW
+    #else
+        typedef LPDDENUMCALLBACKA       LPDDENUMCALLBACK;
+        #define DirectDrawEnumerate     DirectDrawEnumerateA
+    #endif
+    extern HRESULT WINAPI DirectDrawCreate( GUID FAR *lpGUID, LPDIRECTDRAW FAR *lplpDD, IUnknown FAR *pUnkOuter );
+    extern HRESULT WINAPI DirectDrawCreateClipper( DWORD dwFlags, LPDIRECTDRAWCLIPPER FAR *lplpDDClipper, IUnknown FAR *pUnkOuter );
+    #ifdef WINNT
+        //This is the user-mode entry stub to the kernel mode procedure.
+        extern HRESULT NtDirectDrawCreate( GUID FAR *lpGUID, HANDLE *lplpDD, IUnknown FAR *pUnkOuter );
+    #endif
+#endif
+
+#define REGSTR_KEY_DDHW_DESCRIPTION     "Description"
+#define REGSTR_KEY_DDHW_DRIVERNAME      "DriverName"
+#define REGSTR_PATH_DDHW                "Hardware\\DirectDrawDrivers"
+
+#define DDCREATE_HARDWAREONLY           0x00000001l
+#define DDCREATE_EMULATIONONLY          0x00000002l
+
+#ifdef WINNT
+typedef long HRESULT;
+#endif
+
+//#ifndef WINNT
+typedef HRESULT (FAR PASCAL * LPDDENUMMODESCALLBACK)(LPDDSURFACEDESC, LPVOID);
+typedef HRESULT (FAR PASCAL * LPDDENUMSURFACESCALLBACK)(LPDIRECTDRAWSURFACE, LPDDSURFACEDESC, LPVOID);
+//#endif
+/*
+ * DDCOLORKEY
+ */
+typedef struct _DDCOLORKEY
+{
+    DWORD       dwColorSpaceLowValue;   // low boundary of color space that is to 
+                                        // be treated as Color Key, inclusive
+    DWORD       dwColorSpaceHighValue;  // high boundary of color space that is 
+                                        // to be treated as Color Key, inclusive
+} DDCOLORKEY;
+
+typedef DDCOLORKEY FAR* LPDDCOLORKEY;
+
+/*
+ * DDBLTFX
+ * Used to pass override information to the DIRECTDRAWSURFACE callback Blt.
+ */
+typedef struct _DDBLTFX
+{
+    DWORD       dwSize;                         // size of structure
+    DWORD       dwDDFX;                         // FX operations
+    DWORD       dwROP;                          // Win32 raster operations
+    DWORD       dwDDROP;                        // Raster operations new for DirectDraw
+    DWORD       dwRotationAngle;                // Rotation angle for blt
+    DWORD       dwZBufferOpCode;                // ZBuffer compares
+    DWORD       dwZBufferLow;                   // Low limit of Z buffer
+    DWORD       dwZBufferHigh;                  // High limit of Z buffer
+    DWORD       dwZBufferBaseDest;              // Destination base value
+    DWORD       dwZDestConstBitDepth;           // Bit depth used to specify Z constant for destination
+    union
+    {
+        DWORD   dwZDestConst;                   // Constant to use as Z buffer for dest
+        LPDIRECTDRAWSURFACE lpDDSZBufferDest;   // Surface to use as Z buffer for dest
+    };
+    DWORD       dwZSrcConstBitDepth;            // Bit depth used to specify Z constant for source
+    union
+    {
+        DWORD   dwZSrcConst;                    // Constant to use as Z buffer for src
+        LPDIRECTDRAWSURFACE lpDDSZBufferSrc;    // Surface to use as Z buffer for src
+    };
+    DWORD       dwAlphaEdgeBlendBitDepth;       // Bit depth used to specify constant for alpha edge blend
+    DWORD       dwAlphaEdgeBlend;               // Alpha for edge blending
+    DWORD       dwReserved;
+    DWORD       dwAlphaDestConstBitDepth;       // Bit depth used to specify alpha constant for destination
+    union
+    {
+        DWORD   dwAlphaDestConst;               // Constant to use as Alpha Channel
+        LPDIRECTDRAWSURFACE lpDDSAlphaDest;     // Surface to use as Alpha Channel
+    };
+    DWORD       dwAlphaSrcConstBitDepth;        // Bit depth used to specify alpha constant for source
+    union
+    {
+        DWORD   dwAlphaSrcConst;                // Constant to use as Alpha Channel
+        LPDIRECTDRAWSURFACE lpDDSAlphaSrc;      // Surface to use as Alpha Channel
+    };
+    union
+    {
+        DWORD   dwFillColor;                    // color in RGB or Palettized
+        DWORD   dwFillDepth;                    // depth value for z-buffer
+        LPDIRECTDRAWSURFACE lpDDSPattern;       // Surface to use as pattern
+    };
+    DDCOLORKEY  ddckDestColorkey;               // DestColorkey override
+    DDCOLORKEY  ddckSrcColorkey;                // SrcColorkey override
+} DDBLTFX;
+
+typedef DDBLTFX FAR* LPDDBLTFX;
+
+
+/*
+ * DDSCAPS
+ */
+typedef struct _DDSCAPS
+{
+    DWORD       dwCaps;         // capabilities of surface wanted
+} DDSCAPS;
+
+typedef DDSCAPS FAR* LPDDSCAPS; 
+
+/*
+ * DDCAPS
+ */
+#define DD_ROP_SPACE            (256/32)        // space required to store ROP array
+
+typedef struct _DDCAPS
+{
+    DWORD       dwSize;                 // size of the DDDRIVERCAPS structure
+    DWORD       dwCaps;                 // driver specific capabilities
+    DWORD       dwCaps2;                // more driver specific capabilites
+    DWORD       dwCKeyCaps;             // color key capabilities of the surface
+    DWORD       dwFXCaps;               // driver specific stretching and effects capabilites
+    DWORD       dwFXAlphaCaps;          // alpha driver specific capabilities
+    DWORD       dwPalCaps;              // palette capabilities
+    DWORD       dwSVCaps;               // stereo vision capabilities
+    DWORD       dwAlphaBltConstBitDepths;       // DDBD_2,4,8
+    DWORD       dwAlphaBltPixelBitDepths;       // DDBD_1,2,4,8
+    DWORD       dwAlphaBltSurfaceBitDepths;     // DDBD_1,2,4,8
+    DWORD       dwAlphaOverlayConstBitDepths;   // DDBD_2,4,8
+    DWORD       dwAlphaOverlayPixelBitDepths;   // DDBD_1,2,4,8
+    DWORD       dwAlphaOverlaySurfaceBitDepths; // DDBD_1,2,4,8
+    DWORD       dwZBufferBitDepths;             // DDBD_8,16,24,32
+    DWORD       dwVidMemTotal;          // total amount of video memory
+    DWORD       dwVidMemFree;           // amount of free video memory
+    DWORD       dwMaxVisibleOverlays;   // maximum number of visible overlays
+    DWORD       dwCurrVisibleOverlays;  // current number of visible overlays
+    DWORD       dwNumFourCCCodes;       // number of four cc codes
+    DWORD       dwAlignBoundarySrc;     // source rectangle alignment
+    DWORD       dwAlignSizeSrc;         // source rectangle byte size
+    DWORD       dwAlignBoundaryDest;    // dest rectangle alignment
+    DWORD       dwAlignSizeDest;        // dest rectangle byte size
+    DWORD       dwAlignStrideAlign;     // stride alignment
+    DWORD       dwRops[DD_ROP_SPACE];   // ROPS supported
+    DDSCAPS     ddsCaps;                // DDSCAPS structure has all the general capabilities
+    DWORD       dwMinOverlayStretch;    // minimum overlay stretch factor multiplied by 1000, eg 1000 == 1.0, 1300 == 1.3
+    DWORD       dwMaxOverlayStretch;    // maximum overlay stretch factor multiplied by 1000, eg 1000 == 1.0, 1300 == 1.3
+    DWORD       dwMinLiveVideoStretch;  // minimum live video stretch factor multiplied by 1000, eg 1000 == 1.0, 1300 == 1.3
+    DWORD       dwMaxLiveVideoStretch;  // maximum live video stretch factor multiplied by 1000, eg 1000 == 1.0, 1300 == 1.3
+    DWORD       dwMinHwCodecStretch;    // minimum hardware codec stretch factor multiplied by 1000, eg 1000 == 1.0, 1300 == 1.3
+    DWORD       dwMaxHwCodecStretch;    // maximum hardware codec stretch factor multiplied by 1000, eg 1000 == 1.0, 1300 == 1.3
+    DWORD       dwReserved1;            // reserved
+    DWORD       dwReserved2;            // reserved
+    DWORD       dwReserved3;            // reserved
+    DWORD       dwSVBCaps;              // driver specific capabilities for System->Vmem blts
+    DWORD       dwSVBCKeyCaps;          // driver color key capabilities for System->Vmem blts
+    DWORD       dwSVBFXCaps;            // driver FX capabilities for System->Vmem blts
+    DWORD       dwSVBRops[DD_ROP_SPACE];// ROPS supported for System->Vmem blts
+    DWORD       dwVSBCaps;              // driver specific capabilities for Vmem->System blts
+    DWORD       dwVSBCKeyCaps;          // driver color key capabilities for Vmem->System blts
+    DWORD       dwVSBFXCaps;            // driver FX capabilities for Vmem->System blts
+    DWORD       dwVSBRops[DD_ROP_SPACE];// ROPS supported for Vmem->System blts
+    DWORD       dwSSBCaps;              // driver specific capabilities for System->System blts
+    DWORD       dwSSBCKeyCaps;          // driver color key capabilities for System->System blts
+    DWORD       dwSSBFXCaps;            // driver FX capabilities for System->System blts
+    DWORD       dwSSBRops[DD_ROP_SPACE];// ROPS supported for System->System blts
+    DWORD       dwReserved4;            // reserved
+    DWORD       dwReserved5;            // reserved
+    DWORD       dwReserved6;            // reserved
+} DDCAPS;
+
+typedef DDCAPS FAR* LPDDCAPS;
+
+
+
+/*
+ * DDPIXELFORMAT
+ */
+typedef struct _DDPIXELFORMAT
+{
+    DWORD       dwSize;                 // size of structure
+    DWORD       dwFlags;                // pixel format flags
+    DWORD       dwFourCC;               // (FOURCC code)
+    union
+    {
+        DWORD   dwRGBBitCount;          // how many bits per pixel (BD_4,8,16,24,32)
+        DWORD   dwYUVBitCount;          // how many bits per pixel (BD_4,8,16,24,32)
+        DWORD   dwZBufferBitDepth;      // how many bits for z buffers (BD_8,16,24,32)
+        DWORD   dwAlphaBitDepth;        // how many bits for alpha channels (BD_1,2,4,8)
+    };
+    union
+    {
+        DWORD   dwRBitMask;             // mask for red bit
+        DWORD   dwYBitMask;             // mask for Y bits
+    };
+    union
+    {
+        DWORD   dwGBitMask;             // mask for green bits
+        DWORD   dwUBitMask;             // mask for U bits
+    };
+    union
+    {
+        DWORD   dwBBitMask;             // mask for blue bits
+        DWORD   dwVBitMask;             // mask for V bits
+    };
+    union
+    {
+        DWORD   dwRGBAlphaBitMask;      // mask for alpha channel
+        DWORD   dwYUVAlphaBitMask;      // mask for alpha channel
+    };
+} DDPIXELFORMAT;
+
+typedef DDPIXELFORMAT FAR* LPDDPIXELFORMAT;
+
+/*
+ * DDOVERLAYFX
+ */
+typedef struct _DDOVERLAYFX
+{
+    DWORD       dwSize;                         // size of structure
+    DWORD       dwAlphaEdgeBlendBitDepth;       // Bit depth used to specify constant for alpha edge blend
+    DWORD       dwAlphaEdgeBlend;               // Constant to use as alpha for edge blend
+    DWORD       dwReserved;
+    DWORD       dwAlphaDestConstBitDepth;       // Bit depth used to specify alpha constant for destination
+    union
+    {
+        DWORD   dwAlphaDestConst;               // Constant to use as alpha channel for dest
+        LPDIRECTDRAWSURFACE lpDDSAlphaDest;     // Surface to use as alpha channel for dest
+    };
+    DWORD       dwAlphaSrcConstBitDepth;        // Bit depth used to specify alpha constant for source
+    union
+    {
+        DWORD   dwAlphaSrcConst;                // Constant to use as alpha channel for src
+        LPDIRECTDRAWSURFACE lpDDSAlphaSrc;      // Surface to use as alpha channel for src
+    };
+    DDCOLORKEY  dckDestColorkey;                // DestColorkey override
+    DDCOLORKEY  dckSrcColorkey;                 // DestColorkey override
+    DWORD       dwDDFX;                         // Overlay FX
+    DWORD       dwFlags;                        // flags
+} DDOVERLAYFX;
+
+typedef DDOVERLAYFX FAR *LPDDOVERLAYFX;
+
+/*
+ * DDBLTBATCH: BltBatch entry structure
+ */
+typedef struct _DDBLTBATCH
+{
+    LPRECT              lprDest;
+    LPDIRECTDRAWSURFACE lpDDSSrc;
+    LPRECT              lprSrc;
+    DWORD               dwFlags;
+    LPDDBLTFX           lpDDBltFx;
+} DDBLTBATCH;
+
+typedef DDBLTBATCH FAR * LPDDBLTBATCH;
+
+/*
+ * callbacks
+ */
+typedef DWORD   (FAR PASCAL *LPCLIPPERCALLBACK)(LPDIRECTDRAWCLIPPER lpDDClipper, HWND hWnd, DWORD code, LPVOID lpContext );
+#ifdef STREAMING
+typedef DWORD   (FAR PASCAL *LPSURFACESTREAMINGCALLBACK)(DWORD);
+#endif
+
+
+/*
+ * INTERACES FOLLOW:
+ *      IDirectDraw
+ *      IDirectDrawClipper
+ *      IDirectDrawPalette
+ *      IDirectDrawSurface
+ */
+
+/*
+ * IDirectDraw 
+ */
+#if defined( _WIN32 ) && !defined( _NO_COM )
+#undef INTERFACE
+#define INTERFACE IDirectDraw
+DECLARE_INTERFACE_( IDirectDraw, IUnknown )
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef) (THIS)  PURE;
+    STDMETHOD_(ULONG,Release) (THIS) PURE;
+    /*** IDirectDraw methods ***/
+    STDMETHOD(Compact)(THIS) PURE;
+    STDMETHOD(CreateClipper)(THIS_ DWORD, LPDIRECTDRAWCLIPPER FAR*, IUnknown FAR * ) PURE;
+    STDMETHOD(CreatePalette)(THIS_ DWORD, LPPALETTEENTRY, LPDIRECTDRAWPALETTE FAR*, IUnknown FAR * ) PURE;
+    STDMETHOD(CreateSurface)(THIS_  LPDDSURFACEDESC, LPDIRECTDRAWSURFACE FAR *, IUnknown FAR *) PURE;
+    STDMETHOD(DuplicateSurface)( THIS_ LPDIRECTDRAWSURFACE, LPDIRECTDRAWSURFACE FAR * ) PURE;
+    STDMETHOD(EnumDisplayModes)( THIS_ DWORD, LPDDSURFACEDESC, LPVOID, LPDDENUMMODESCALLBACK ) PURE;
+    STDMETHOD(EnumSurfaces)(THIS_ DWORD, LPDDSURFACEDESC, LPVOID,LPDDENUMSURFACESCALLBACK ) PURE;
+    STDMETHOD(FlipToGDISurface)(THIS) PURE;
+    STDMETHOD(GetCaps)( THIS_ LPDDCAPS, LPDDCAPS) PURE;
+    STDMETHOD(GetDisplayMode)( THIS_ LPDDSURFACEDESC) PURE;
+    STDMETHOD(GetFourCCCodes)(THIS_  LPDWORD, LPDWORD ) PURE;
+    STDMETHOD(GetGDISurface)(THIS_ LPDIRECTDRAWSURFACE FAR *) PURE;
+    STDMETHOD(GetMonitorFrequency)(THIS_ LPDWORD) PURE;
+    STDMETHOD(GetScanLine)(THIS_ LPDWORD) PURE;
+    STDMETHOD(GetVerticalBlankStatus)(THIS_ LPBOOL ) PURE;
+    STDMETHOD(Initialize)(THIS_ GUID FAR *) PURE;
+    STDMETHOD(RestoreDisplayMode)(THIS) PURE;
+    STDMETHOD(SetCooperativeLevel)(THIS_ HWND, DWORD) PURE;
+    STDMETHOD(SetDisplayMode)(THIS_ DWORD, DWORD,DWORD) PURE;
+    STDMETHOD(WaitForVerticalBlank)(THIS_ DWORD, HANDLE ) PURE;
+};
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirectDraw_QueryInterface(p, a, b)         (p)->lpVtbl->QueryInterface(p, a, b)
+#define IDirectDraw_AddRef(p)                       (p)->lpVtbl->AddRef(p)
+#define IDirectDraw_Release(p)                      (p)->lpVtbl->Release(p)
+#define IDirectDraw_Compact(p)                      (p)->lpVtbl->Compact(p)
+#define IDirectDraw_CreateClipper(p, a, b, c)       (p)->lpVtbl->CreateClipper(p, a, b, c)
+#define IDirectDraw_CreatePalette(p, a, b, c, d)    (p)->lpVtbl->CreatePalette(p, a, b, c, d)
+#define IDirectDraw_CreateSurface(p, a, b, c)       (p)->lpVtbl->CreateSurface(p, a, b, c)
+#define IDirectDraw_DuplicateSurface(p, a, b)       (p)->lpVtbl->DuplicateSurface(p, a, b)
+#define IDirectDraw_EnumDisplayModes(p, a, b, c, d) (p)->lpVtbl->EnumDisplayModes(p, a, b, c, d)
+#define IDirectDraw_EnumSurfaces(p, a, b, c, d)     (p)->lpVtbl->EnumSurfaces(p, a, b, c, d)
+#define IDirectDraw_FlipToGDISurface(p)             (p)->lpVtbl->FlipToGDISurface(p)
+#define IDirectDraw_GetCaps(p, a, b)                (p)->lpVtbl->GetCaps(p, a, b)
+#define IDirectDraw_GetDisplayMode(p, a)            (p)->lpVtbl->GetDisplayMode(p, a)
+#define IDirectDraw_GetFourCCCodes(p, a, b)         (p)->lpVtbl->GetFourCCCodes(p, a, b)
+#define IDirectDraw_GetGDISurface(p, a)             (p)->lpVtbl->GetGDISurface(p, a)
+#define IDirectDraw_GetMonitorFrequency(p, a)       (p)->lpVtbl->GetMonitorFrequency(p, a)
+#define IDirectDraw_GetScanLine(p, a)               (p)->lpVtbl->GetScanLine(p, a)
+#define IDirectDraw_GetVerticalBlankStatus(p, a)    (p)->lpVtbl->GetVerticalBlankStatus(p, a)
+#define IDirectDraw_Initialize(p, a)                (p)->lpVtbl->Initialize(p, a)
+#define IDirectDraw_RestoreDisplayMode(p)           (p)->lpVtbl->RestoreDisplayMode(p)
+#define IDirectDraw_SetCooperativeLevel(p, a, b)    (p)->lpVtbl->SetCooperativeLevel(p, a, b)
+#define IDirectDraw_SetDisplayMode(p, a, b, c)      (p)->lpVtbl->SetDisplayMode(p, a, b, c)
+#define IDirectDraw_WaitForVerticalBlank(p, a, b)   (p)->lpVtbl->WaitForVerticalBlank(p, a, b)
+#endif
+
+#endif
+
+#if defined( _WIN32 ) && !defined( _NO_COM )
+#undef INTERFACE
+#define INTERFACE IDirectDraw2
+DECLARE_INTERFACE_( IDirectDraw2, IUnknown )
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef) (THIS)  PURE;
+    STDMETHOD_(ULONG,Release) (THIS) PURE;
+    /*** IDirectDraw methods ***/
+    STDMETHOD(Compact)(THIS) PURE;
+    STDMETHOD(CreateClipper)(THIS_ DWORD, LPDIRECTDRAWCLIPPER FAR*, IUnknown FAR * ) PURE;
+    STDMETHOD(CreatePalette)(THIS_ DWORD, LPPALETTEENTRY, LPDIRECTDRAWPALETTE FAR*, IUnknown FAR * ) PURE;
+    STDMETHOD(CreateSurface)(THIS_  LPDDSURFACEDESC, LPDIRECTDRAWSURFACE FAR *, IUnknown FAR *) PURE;
+    STDMETHOD(DuplicateSurface)( THIS_ LPDIRECTDRAWSURFACE, LPDIRECTDRAWSURFACE FAR * ) PURE;
+    STDMETHOD(EnumDisplayModes)( THIS_ DWORD, LPDDSURFACEDESC, LPVOID, LPDDENUMMODESCALLBACK ) PURE;
+    STDMETHOD(EnumSurfaces)(THIS_ DWORD, LPDDSURFACEDESC, LPVOID,LPDDENUMSURFACESCALLBACK ) PURE;
+    STDMETHOD(FlipToGDISurface)(THIS) PURE;
+    STDMETHOD(GetCaps)( THIS_ LPDDCAPS, LPDDCAPS) PURE;
+    STDMETHOD(GetDisplayMode)( THIS_ LPDDSURFACEDESC) PURE;
+    STDMETHOD(GetFourCCCodes)(THIS_  LPDWORD, LPDWORD ) PURE;
+    STDMETHOD(GetGDISurface)(THIS_ LPDIRECTDRAWSURFACE FAR *) PURE;
+    STDMETHOD(GetMonitorFrequency)(THIS_ LPDWORD) PURE;
+    STDMETHOD(GetScanLine)(THIS_ LPDWORD) PURE;
+    STDMETHOD(GetVerticalBlankStatus)(THIS_ LPBOOL ) PURE;
+    STDMETHOD(Initialize)(THIS_ GUID FAR *) PURE;
+    STDMETHOD(RestoreDisplayMode)(THIS) PURE;
+    STDMETHOD(SetCooperativeLevel)(THIS_ HWND, DWORD) PURE;
+    STDMETHOD(SetDisplayMode)(THIS_ DWORD, DWORD,DWORD, DWORD, DWORD) PURE;
+    STDMETHOD(WaitForVerticalBlank)(THIS_ DWORD, HANDLE ) PURE;
+    /*** Added in the v2 interface ***/
+    STDMETHOD(GetAvailableVidMem)(THIS_ LPDDSCAPS, LPDWORD, LPDWORD) PURE;
+};
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirectDraw2_QueryInterface(p, a, b)         (p)->lpVtbl->QueryInterface(p, a, b)
+#define IDirectDraw2_AddRef(p)                       (p)->lpVtbl->AddRef(p)
+#define IDirectDraw2_Release(p)                      (p)->lpVtbl->Release(p)
+#define IDirectDraw2_Compact(p)                      (p)->lpVtbl->Compact(p)
+#define IDirectDraw2_CreateClipper(p, a, b, c)       (p)->lpVtbl->CreateClipper(p, a, b, c)
+#define IDirectDraw2_CreatePalette(p, a, b, c, d)    (p)->lpVtbl->CreatePalette(p, a, b, c, d)
+#define IDirectDraw2_CreateSurface(p, a, b, c)       (p)->lpVtbl->CreateSurface(p, a, b, c)
+#define IDirectDraw2_DuplicateSurface(p, a, b)       (p)->lpVtbl->DuplicateSurface(p, a, b)
+#define IDirectDraw2_EnumDisplayModes(p, a, b, c, d) (p)->lpVtbl->EnumDisplayModes(p, a, b, c, d)
+#define IDirectDraw2_EnumSurfaces(p, a, b, c, d)     (p)->lpVtbl->EnumSurfaces(p, a, b, c, d)
+#define IDirectDraw2_FlipToGDISurface(p)             (p)->lpVtbl->FlipToGDISurface(p)
+#define IDirectDraw2_GetCaps(p, a, b)                (p)->lpVtbl->GetCaps(p, a, b)
+#define IDirectDraw2_GetDisplayMode(p, a)            (p)->lpVtbl->GetDisplayMode(p, a)
+#define IDirectDraw2_GetFourCCCodes(p, a, b)         (p)->lpVtbl->GetFourCCCodes(p, a, b)
+#define IDirectDraw2_GetGDISurface(p, a)             (p)->lpVtbl->GetGDISurface(p, a)
+#define IDirectDraw2_GetMonitorFrequency(p, a)       (p)->lpVtbl->GetMonitorFrequency(p, a)
+#define IDirectDraw2_GetScanLine(p, a)               (p)->lpVtbl->GetScanLine(p, a)
+#define IDirectDraw2_GetVerticalBlankStatus(p, a)    (p)->lpVtbl->GetVerticalBlankStatus(p, a)
+#define IDirectDraw2_Initialize(p, a)                (p)->lpVtbl->Initialize(p, a)
+#define IDirectDraw2_RestoreDisplayMode(p)           (p)->lpVtbl->RestoreDisplayMode(p)
+#define IDirectDraw2_SetCooperativeLevel(p, a, b)    (p)->lpVtbl->SetCooperativeLevel(p, a, b)
+#define IDirectDraw2_SetDisplayMode(p, a, b, c, d)   (p)->lpVtbl->SetDisplayMode(p, a, b, c, d)
+#define IDirectDraw2_WaitForVerticalBlank(p, a, b)   (p)->lpVtbl->WaitForVerticalBlank(p, a, b)
+#define IDirectDraw2_GetAvailableVidMem(p, a, b, c)  (p)->lpVtbl->GetAvailableVidMem(p, a, b, c)
+#endif
+
+#endif
+
+/*
+ * IDirectDrawPalette
+ */
+#if defined( _WIN32 ) && !defined( _NO_COM )
+#undef INTERFACE
+#define INTERFACE IDirectDrawPalette
+DECLARE_INTERFACE_( IDirectDrawPalette, IUnknown )
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef) (THIS)  PURE;
+    STDMETHOD_(ULONG,Release) (THIS) PURE;
+    /*** IDirectDrawPalette methods ***/
+    STDMETHOD(GetCaps)(THIS_ LPDWORD) PURE;
+    STDMETHOD(GetEntries)(THIS_ DWORD,DWORD,DWORD,LPPALETTEENTRY) PURE;
+    STDMETHOD(Initialize)(THIS_ LPDIRECTDRAW, DWORD, LPPALETTEENTRY) PURE;
+    STDMETHOD(SetEntries)(THIS_ DWORD,DWORD,DWORD,LPPALETTEENTRY) PURE;
+};
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirectDrawPalette_QueryInterface(p, a, b)      (p)->lpVtbl->QueryInterface(p, a, b)
+#define IDirectDrawPalette_AddRef(p)                    (p)->lpVtbl->AddRef(p)
+#define IDirectDrawPalette_Release(p)                   (p)->lpVtbl->Release(p)
+#define IDirectDrawPalette_GetCaps(p, a)                (p)->lpVtbl->GetCaps(p, a)
+#define IDirectDrawPalette_GetEntries(p, a, b, c, d)    (p)->lpVtbl->GetEntries(p, a, b, c, d)
+#define IDirectDrawPalette_Initialize(p, a, b, c)       (p)->lpVtbl->Initialize(p, a, b, c)
+#define IDirectDrawPalette_SetEntries(p, a, b, c, d)    (p)->lpVtbl->SetEntries(p, a, b, c, d)
+#endif
+
+#endif
+
+/*
+ * IDirectDrawClipper
+ */
+#if defined( _WIN32 ) && !defined( _NO_COM )
+#undef INTERFACE
+#define INTERFACE IDirectDrawClipper
+DECLARE_INTERFACE_( IDirectDrawClipper, IUnknown )
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef) (THIS)  PURE;
+    STDMETHOD_(ULONG,Release) (THIS) PURE;
+    /*** IDirectDrawClipper methods ***/
+    STDMETHOD(GetClipList)(THIS_ LPRECT, LPRGNDATA, LPDWORD) PURE;
+    STDMETHOD(GetHWnd)(THIS_ HWND FAR *) PURE;
+    STDMETHOD(Initialize)(THIS_ LPDIRECTDRAW, DWORD) PURE;
+    STDMETHOD(IsClipListChanged)(THIS_ BOOL FAR *) PURE;
+    STDMETHOD(SetClipList)(THIS_ LPRGNDATA,DWORD) PURE;
+    STDMETHOD(SetHWnd)(THIS_ DWORD, HWND ) PURE;
+};
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirectDrawClipper_QueryInterface(p, a, b)  (p)->lpVtbl->QueryInterface(p, a, b)
+#define IDirectDrawClipper_AddRef(p)                (p)->lpVtbl->AddRef(p)
+#define IDirectDrawClipper_Release(p)               (p)->lpVtbl->Release(p)
+#define IDirectDrawClipper_GetClipList(p, a, b, c)  (p)->lpVtbl->GetClipList(p, a, b, c)
+#define IDirectDrawClipper_GetHWnd(p, a)            (p)->lpVtbl->GetHWnd(p, a)
+#define IDirectDrawClipper_Initialize(p, a, b)      (p)->lpVtbl->Initialize(p, a, b)
+#define IDirectDrawClipper_IsClipListChanged(p, a)  (p)->lpVtbl->IsClipListChanged(p, a)
+#define IDirectDrawClipper_SetClipList(p, a, b)     (p)->lpVtbl->SetClipList(p, a, b)
+#define IDirectDrawClipper_SetHWnd(p, a, b)         (p)->lpVtbl->SetHWnd(p, a, b)
+#endif
+
+#endif
+
+/*
+ * IDirectDrawSurface and related interfaces
+ */
+#if defined( _WIN32 ) && !defined( _NO_COM )
+#undef INTERFACE
+#define INTERFACE IDirectDrawSurface
+DECLARE_INTERFACE_( IDirectDrawSurface, IUnknown )
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef) (THIS)  PURE;
+    STDMETHOD_(ULONG,Release) (THIS) PURE;
+    /*** IDirectDrawSurface methods ***/
+    STDMETHOD(AddAttachedSurface)(THIS_ LPDIRECTDRAWSURFACE) PURE;
+    STDMETHOD(AddOverlayDirtyRect)(THIS_ LPRECT) PURE;
+    STDMETHOD(Blt)(THIS_ LPRECT,LPDIRECTDRAWSURFACE, LPRECT,DWORD, LPDDBLTFX) PURE;
+    STDMETHOD(BltBatch)(THIS_ LPDDBLTBATCH, DWORD, DWORD ) PURE;
+    STDMETHOD(BltFast)(THIS_ DWORD,DWORD,LPDIRECTDRAWSURFACE, LPRECT,DWORD) PURE;
+    STDMETHOD(DeleteAttachedSurface)(THIS_ DWORD,LPDIRECTDRAWSURFACE) PURE;
+    STDMETHOD(EnumAttachedSurfaces)(THIS_ LPVOID,LPDDENUMSURFACESCALLBACK) PURE;
+    STDMETHOD(EnumOverlayZOrders)(THIS_ DWORD,LPVOID,LPDDENUMSURFACESCALLBACK) PURE;
+    STDMETHOD(Flip)(THIS_ LPDIRECTDRAWSURFACE, DWORD) PURE;
+    STDMETHOD(GetAttachedSurface)(THIS_ LPDDSCAPS, LPDIRECTDRAWSURFACE FAR *) PURE;
+    STDMETHOD(GetBltStatus)(THIS_ DWORD) PURE;
+    STDMETHOD(GetCaps)(THIS_ LPDDSCAPS) PURE;
+    STDMETHOD(GetClipper)(THIS_ LPDIRECTDRAWCLIPPER FAR*) PURE;
+    STDMETHOD(GetColorKey)(THIS_ DWORD, LPDDCOLORKEY) PURE;
+    STDMETHOD(GetDC)(THIS_ HDC FAR *) PURE;
+    STDMETHOD(GetFlipStatus)(THIS_ DWORD) PURE;
+    STDMETHOD(GetOverlayPosition)(THIS_ LPLONG, LPLONG ) PURE;
+    STDMETHOD(GetPalette)(THIS_ LPDIRECTDRAWPALETTE FAR*) PURE;
+    STDMETHOD(GetPixelFormat)(THIS_ LPDDPIXELFORMAT) PURE;
+    STDMETHOD(GetSurfaceDesc)(THIS_ LPDDSURFACEDESC) PURE;
+    STDMETHOD(Initialize)(THIS_ LPDIRECTDRAW, LPDDSURFACEDESC) PURE;
+    STDMETHOD(IsLost)(THIS) PURE;
+    STDMETHOD(Lock)(THIS_ LPRECT,LPDDSURFACEDESC,DWORD,HANDLE) PURE;
+    STDMETHOD(ReleaseDC)(THIS_ HDC) PURE;
+    STDMETHOD(Restore)(THIS) PURE;
+    STDMETHOD(SetClipper)(THIS_ LPDIRECTDRAWCLIPPER) PURE;
+    STDMETHOD(SetColorKey)(THIS_ DWORD, LPDDCOLORKEY) PURE;
+    STDMETHOD(SetOverlayPosition)(THIS_ LONG, LONG ) PURE;
+    STDMETHOD(SetPalette)(THIS_ LPDIRECTDRAWPALETTE) PURE;
+    STDMETHOD(Unlock)(THIS_ LPVOID) PURE;
+    STDMETHOD(UpdateOverlay)(THIS_ LPRECT, LPDIRECTDRAWSURFACE,LPRECT,DWORD, LPDDOVERLAYFX) PURE;
+    STDMETHOD(UpdateOverlayDisplay)(THIS_ DWORD) PURE;
+    STDMETHOD(UpdateOverlayZOrder)(THIS_ DWORD, LPDIRECTDRAWSURFACE) PURE;
+};
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirectDrawSurface_QueryInterface(p,a,b)        (p)->lpVtbl->QueryInterface(p,a,b)
+#define IDirectDrawSurface_AddRef(p)                    (p)->lpVtbl->AddRef(p)
+#define IDirectDrawSurface_Release(p)                   (p)->lpVtbl->Release(p)
+#define IDirectDrawSurface_AddAttachedSurface(p,a)      (p)->lpVtbl->AddAttachedSurface(p,a)
+#define IDirectDrawSurface_AddOverlayDirtyRect(p,a)     (p)->lpVtbl->AddOverlayDirtyRect(p,a)
+#define IDirectDrawSurface_Blt(p,a,b,c,d,e)             (p)->lpVtbl->Blt(p,a,b,c,d,e)
+#define IDirectDrawSurface_BltBatch(p,a,b,c)            (p)->lpVtbl->BltBatch(p,a,b,c)
+#define IDirectDrawSurface_BltFast(p,a,b,c,d,e)         (p)->lpVtbl->BltFast(p,a,b,c,d,e)
+#define IDirectDrawSurface_DeleteAttachedSurface(p,a,b) (p)->lpVtbl->DeleteAttachedSurface(p,a,b)
+#define IDirectDrawSurface_EnumAttachedSurfaces(p,a,b)  (p)->lpVtbl->EnumAttachedSurfaces(p,a,b)
+#define IDirectDrawSurface_EnumOverlayZOrders(p,a,b,c)  (p)->lpVtbl->EnumOverlayZOrders(p,a,b,c)
+#define IDirectDrawSurface_Flip(p,a,b)                  (p)->lpVtbl->Flip(p,a,b)
+#define IDirectDrawSurface_GetAttachedSurface(p,a,b)    (p)->lpVtbl->GetAttachedSurface(p,a,b)
+#define IDirectDrawSurface_GetBltStatus(p,a)            (p)->lpVtbl->GetBltStatus(p,a)
+#define IDirectDrawSurface_GetCaps(p,b)                 (p)->lpVtbl->GetCaps(p,b)
+#define IDirectDrawSurface_GetClipper(p,a)              (p)->lpVtbl->GetClipper(p,a)
+#define IDirectDrawSurface_GetColorKey(p,a,b)           (p)->lpVtbl->GetColorKey(p,a,b)
+#define IDirectDrawSurface_GetDC(p,a)                   (p)->lpVtbl->GetDC(p,a)
+#define IDirectDrawSurface_GetFlipStatus(p,a)           (p)->lpVtbl->GetFlipStatus(p,a)
+#define IDirectDrawSurface_GetOverlayPosition(p,a,b)    (p)->lpVtbl->GetOverlayPosition(p,a,b)
+#define IDirectDrawSurface_GetPalette(p,a)              (p)->lpVtbl->GetPalette(p,a)
+#define IDirectDrawSurface_GetPixelFormat(p,a)          (p)->lpVtbl->GetPixelFormat(p,a)
+#define IDirectDrawSurface_GetSurfaceDesc(p,a)          (p)->lpVtbl->GetSurfaceDesc(p,a)
+#define IDirectDrawSurface_Initialize(p,a,b)            (p)->lpVtbl->Initialize(p,a,b)
+#define IDirectDrawSurface_IsLost(p)                    (p)->lpVtbl->IsLost(p)
+#define IDirectDrawSurface_Lock(p,a,b,c,d)              (p)->lpVtbl->Lock(p,a,b,c,d)
+#define IDirectDrawSurface_ReleaseDC(p,a)               (p)->lpVtbl->ReleaseDC(p,a)
+#define IDirectDrawSurface_Restore(p)                   (p)->lpVtbl->Restore(p)
+#define IDirectDrawSurface_SetClipper(p,a)              (p)->lpVtbl->SetClipper(p,a)
+#define IDirectDrawSurface_SetColorKey(p,a,b)           (p)->lpVtbl->SetColorKey(p,a,b)
+#define IDirectDrawSurface_SetOverlayPosition(p,a,b)    (p)->lpVtbl->SetOverlayPosition(p,a,b)
+#define IDirectDrawSurface_SetPalette(p,a)              (p)->lpVtbl->SetPalette(p,a)
+#define IDirectDrawSurface_Unlock(p,b)                  (p)->lpVtbl->Unlock(p,b)
+#define IDirectDrawSurface_UpdateOverlay(p,a,b,c,d,e)   (p)->lpVtbl->UpdateOverlay(p,a,b,c,d,e)
+#define IDirectDrawSurface_UpdateOverlayDisplay(p,a)    (p)->lpVtbl->UpdateOverlayDisplay(p,a)
+#define IDirectDrawSurface_UpdateOverlayZOrder(p,a,b)   (p)->lpVtbl->UpdateOverlayZOrder(p,a,b)
+#endif
+
+/*
+ * IDirectDrawSurface2 and related interfaces
+ */
+#undef INTERFACE
+#define INTERFACE IDirectDrawSurface2
+DECLARE_INTERFACE_( IDirectDrawSurface2, IUnknown )
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef) (THIS)  PURE;
+    STDMETHOD_(ULONG,Release) (THIS) PURE;
+    /*** IDirectDrawSurface methods ***/
+    STDMETHOD(AddAttachedSurface)(THIS_ LPDIRECTDRAWSURFACE2) PURE;
+    STDMETHOD(AddOverlayDirtyRect)(THIS_ LPRECT) PURE;
+    STDMETHOD(Blt)(THIS_ LPRECT,LPDIRECTDRAWSURFACE2, LPRECT,DWORD, LPDDBLTFX) PURE;
+    STDMETHOD(BltBatch)(THIS_ LPDDBLTBATCH, DWORD, DWORD ) PURE;
+    STDMETHOD(BltFast)(THIS_ DWORD,DWORD,LPDIRECTDRAWSURFACE2, LPRECT,DWORD) PURE;
+    STDMETHOD(DeleteAttachedSurface)(THIS_ DWORD,LPDIRECTDRAWSURFACE2) PURE;
+    STDMETHOD(EnumAttachedSurfaces)(THIS_ LPVOID,LPDDENUMSURFACESCALLBACK) PURE;
+    STDMETHOD(EnumOverlayZOrders)(THIS_ DWORD,LPVOID,LPDDENUMSURFACESCALLBACK) PURE;
+    STDMETHOD(Flip)(THIS_ LPDIRECTDRAWSURFACE2, DWORD) PURE;
+    STDMETHOD(GetAttachedSurface)(THIS_ LPDDSCAPS, LPDIRECTDRAWSURFACE2 FAR *) PURE;
+    STDMETHOD(GetBltStatus)(THIS_ DWORD) PURE;
+    STDMETHOD(GetCaps)(THIS_ LPDDSCAPS) PURE;
+    STDMETHOD(GetClipper)(THIS_ LPDIRECTDRAWCLIPPER FAR*) PURE;
+    STDMETHOD(GetColorKey)(THIS_ DWORD, LPDDCOLORKEY) PURE;
+    STDMETHOD(GetDC)(THIS_ HDC FAR *) PURE;
+    STDMETHOD(GetFlipStatus)(THIS_ DWORD) PURE;
+    STDMETHOD(GetOverlayPosition)(THIS_ LPLONG, LPLONG ) PURE;
+    STDMETHOD(GetPalette)(THIS_ LPDIRECTDRAWPALETTE FAR*) PURE;
+    STDMETHOD(GetPixelFormat)(THIS_ LPDDPIXELFORMAT) PURE;
+    STDMETHOD(GetSurfaceDesc)(THIS_ LPDDSURFACEDESC) PURE;
+    STDMETHOD(Initialize)(THIS_ LPDIRECTDRAW, LPDDSURFACEDESC) PURE;
+    STDMETHOD(IsLost)(THIS) PURE;
+    STDMETHOD(Lock)(THIS_ LPRECT,LPDDSURFACEDESC,DWORD,HANDLE) PURE;
+    STDMETHOD(ReleaseDC)(THIS_ HDC) PURE;
+    STDMETHOD(Restore)(THIS) PURE;
+    STDMETHOD(SetClipper)(THIS_ LPDIRECTDRAWCLIPPER) PURE;
+    STDMETHOD(SetColorKey)(THIS_ DWORD, LPDDCOLORKEY) PURE;
+    STDMETHOD(SetOverlayPosition)(THIS_ LONG, LONG ) PURE;
+    STDMETHOD(SetPalette)(THIS_ LPDIRECTDRAWPALETTE) PURE;
+    STDMETHOD(Unlock)(THIS_ LPVOID) PURE;
+    STDMETHOD(UpdateOverlay)(THIS_ LPRECT, LPDIRECTDRAWSURFACE2,LPRECT,DWORD, LPDDOVERLAYFX) PURE;
+    STDMETHOD(UpdateOverlayDisplay)(THIS_ DWORD) PURE;
+    STDMETHOD(UpdateOverlayZOrder)(THIS_ DWORD, LPDIRECTDRAWSURFACE2) PURE;
+    /*** Added in the v2 interface ***/
+    STDMETHOD(GetDDInterface)(THIS_ LPVOID FAR *) PURE;
+    STDMETHOD(PageLock)(THIS_ DWORD) PURE;
+    STDMETHOD(PageUnlock)(THIS_ DWORD) PURE;
+};
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirectDrawSurface2_QueryInterface(p,a,b)        (p)->lpVtbl->QueryInterface(p,a,b)
+#define IDirectDrawSurface2_AddRef(p)                    (p)->lpVtbl->AddRef(p)
+#define IDirectDrawSurface2_Release(p)                   (p)->lpVtbl->Release(p)
+#define IDirectDrawSurface2_AddAttachedSurface(p,a)      (p)->lpVtbl->AddAttachedSurface(p,a)
+#define IDirectDrawSurface2_AddOverlayDirtyRect(p,a)     (p)->lpVtbl->AddOverlayDirtyRect(p,a)
+#define IDirectDrawSurface2_Blt(p,a,b,c,d,e)             (p)->lpVtbl->Blt(p,a,b,c,d,e)
+#define IDirectDrawSurface2_BltBatch(p,a,b,c)            (p)->lpVtbl->BltBatch(p,a,b,c)
+#define IDirectDrawSurface2_BltFast(p,a,b,c,d,e)         (p)->lpVtbl->BltFast(p,a,b,c,d,e)
+#define IDirectDrawSurface2_DeleteAttachedSurface(p,a,b) (p)->lpVtbl->DeleteAttachedSurface(p,a,b)
+#define IDirectDrawSurface2_EnumAttachedSurfaces(p,a,b)  (p)->lpVtbl->EnumAttachedSurfaces(p,a,b)
+#define IDirectDrawSurface2_EnumOverlayZOrders(p,a,b,c)  (p)->lpVtbl->EnumOverlayZOrders(p,a,b,c)
+#define IDirectDrawSurface2_Flip(p,a,b)                  (p)->lpVtbl->Flip(p,a,b)
+#define IDirectDrawSurface2_GetAttachedSurface(p,a,b)    (p)->lpVtbl->GetAttachedSurface(p,a,b)
+#define IDirectDrawSurface2_GetBltStatus(p,a)            (p)->lpVtbl->GetBltStatus(p,a)
+#define IDirectDrawSurface2_GetCaps(p,b)                 (p)->lpVtbl->GetCaps(p,b)
+#define IDirectDrawSurface2_GetClipper(p,a)              (p)->lpVtbl->GetClipper(p,a)
+#define IDirectDrawSurface2_GetColorKey(p,a,b)           (p)->lpVtbl->GetColorKey(p,a,b)
+#define IDirectDrawSurface2_GetDC(p,a)                   (p)->lpVtbl->GetDC(p,a)
+#define IDirectDrawSurface2_GetFlipStatus(p,a)           (p)->lpVtbl->GetFlipStatus(p,a)
+#define IDirectDrawSurface2_GetOverlayPosition(p,a,b)    (p)->lpVtbl->GetOverlayPosition(p,a,b)
+#define IDirectDrawSurface2_GetPalette(p,a)              (p)->lpVtbl->GetPalette(p,a)
+#define IDirectDrawSurface2_GetPixelFormat(p,a)          (p)->lpVtbl->GetPixelFormat(p,a)
+#define IDirectDrawSurface2_GetSurfaceDesc(p,a)          (p)->lpVtbl->GetSurfaceDesc(p,a)
+#define IDirectDrawSurface2_Initialize(p,a,b)            (p)->lpVtbl->Initialize(p,a,b)
+#define IDirectDrawSurface2_IsLost(p)                    (p)->lpVtbl->IsLost(p)
+#define IDirectDrawSurface2_Lock(p,a,b,c,d)              (p)->lpVtbl->Lock(p,a,b,c,d)
+#define IDirectDrawSurface2_ReleaseDC(p,a)               (p)->lpVtbl->ReleaseDC(p,a)
+#define IDirectDrawSurface2_Restore(p)                   (p)->lpVtbl->Restore(p)
+#define IDirectDrawSurface2_SetClipper(p,a)              (p)->lpVtbl->SetClipper(p,a)
+#define IDirectDrawSurface2_SetColorKey(p,a,b)           (p)->lpVtbl->SetColorKey(p,a,b)
+#define IDirectDrawSurface2_SetOverlayPosition(p,a,b)    (p)->lpVtbl->SetOverlayPosition(p,a,b)
+#define IDirectDrawSurface2_SetPalette(p,a)              (p)->lpVtbl->SetPalette(p,a)
+#define IDirectDrawSurface2_Unlock(p,b)                  (p)->lpVtbl->Unlock(p,b)
+#define IDirectDrawSurface2_UpdateOverlay(p,a,b,c,d,e)   (p)->lpVtbl->UpdateOverlay(p,a,b,c,d,e)
+#define IDirectDrawSurface2_UpdateOverlayDisplay(p,a)    (p)->lpVtbl->UpdateOverlayDisplay(p,a)
+#define IDirectDrawSurface2_UpdateOverlayZOrder(p,a,b)   (p)->lpVtbl->UpdateOverlayZOrder(p,a,b)
+#define IDirectDrawSurface2_GetDDInterface(p,a)          (p)->lpVtbl->GetDDInterface(p,a)
+#define IDirectDrawSurface2_PageLock(p,a)                (p)->lpVtbl->PageLock(p,a)
+#define IDirectDrawSurface2_PageUnlock(p,a)              (p)->lpVtbl->PageUnlock(p,a)
+#endif
+
+
+#endif
+
+
+/*
+ * DDSURFACEDESC
+ */
+typedef struct _DDSURFACEDESC
+{
+    DWORD               dwSize;                 // size of the DDSURFACEDESC structure
+    DWORD               dwFlags;                // determines what fields are valid
+    DWORD               dwHeight;               // height of surface to be created
+    DWORD               dwWidth;                // width of input surface
+    LONG                lPitch;                 // distance to start of next line (return value only)
+    DWORD               dwBackBufferCount;      // number of back buffers requested
+    union
+    {
+        DWORD           dwMipMapCount;          // number of mip-map levels requested
+        DWORD           dwZBufferBitDepth;      // depth of Z buffer requested
+        DWORD           dwRefreshRate;          // refresh rate (used when display mode is described)
+    };
+    DWORD               dwAlphaBitDepth;        // depth of alpha buffer requested
+    DWORD               dwReserved;             // reserved
+    LPVOID              lpSurface;              // pointer to the associated surface memory
+    DDCOLORKEY          ddckCKDestOverlay;      // color key for destination overlay use
+    DDCOLORKEY          ddckCKDestBlt;          // color key for destination blt use
+    DDCOLORKEY          ddckCKSrcOverlay;       // color key for source overlay use
+    DDCOLORKEY          ddckCKSrcBlt;           // color key for source blt use
+    DDPIXELFORMAT       ddpfPixelFormat;        // pixel format description of the surface
+    DDSCAPS             ddsCaps;                // direct draw surface capabilities
+} DDSURFACEDESC;
+
+/*
+ * ddsCaps field is valid.
+ */
+#define DDSD_CAPS               0x00000001l     // default
+
+/*
+ * dwHeight field is valid.
+ */
+#define DDSD_HEIGHT             0x00000002l
+
+/*
+ * dwWidth field is valid.
+ */
+#define DDSD_WIDTH              0x00000004l
+
+/*
+ * lPitch is valid.
+ */
+#define DDSD_PITCH              0x00000008l
+
+/*
+ * dwBackBufferCount is valid.
+ */
+#define DDSD_BACKBUFFERCOUNT    0x00000020l
+
+/*
+ * dwZBufferBitDepth is valid.
+ */
+#define DDSD_ZBUFFERBITDEPTH    0x00000040l
+
+/*
+ * dwAlphaBitDepth is valid.
+ */
+#define DDSD_ALPHABITDEPTH      0x00000080l
+
+
+
+/*
+ * ddpfPixelFormat is valid.
+ */
+#define DDSD_PIXELFORMAT        0x00001000l
+
+/*
+ * ddckCKDestOverlay is valid.
+ */
+#define DDSD_CKDESTOVERLAY      0x00002000l
+
+/*
+ * ddckCKDestBlt is valid.
+ */
+#define DDSD_CKDESTBLT          0x00004000l
+
+/*
+ * ddckCKSrcOverlay is valid.
+ */
+#define DDSD_CKSRCOVERLAY       0x00008000l
+
+/*
+ * ddckCKSrcBlt is valid.
+ */
+#define DDSD_CKSRCBLT           0x00010000l
+
+/*
+ * dwMipMapCount is valid.
+ */
+#define DDSD_MIPMAPCOUNT        0x00020000l
+
+ /*
+  * dwRefreshRate is valid
+  */
+#define DDSD_REFRESHRATE        0x00040000l
+
+
+/*
+ * All input fields are valid. 
+ */
+#define DDSD_ALL                0x0007f9eel
+
+
+/*============================================================================
+ *
+ * Direct Draw Capability Flags
+ *
+ * These flags are used to describe the capabilities of a given Surface.
+ * All flags are bit flags. 
+ *
+ *==========================================================================*/
+
+/****************************************************************************
+ *
+ * DIRECTDRAWSURFACE CAPABILITY FLAGS
+ *
+ ****************************************************************************/
+/*
+ * This bit currently has no meaning.
+ */
+#define DDSCAPS_3D                              0x00000001l
+
+/*
+ * Indicates that this surface contains alpha information.  The pixel
+ * format must be interrogated to determine whether this surface
+ * contains only alpha information or alpha information interlaced
+ * with pixel color data (e.g. RGBA or YUVA).
+ */
+#define DDSCAPS_ALPHA                           0x00000002l
+
+/*
+ * Indicates that this surface is a backbuffer.  It is generally
+ * set by CreateSurface when the DDSCAPS_FLIP capability bit is set.
+ * It indicates that this surface is THE back buffer of a surface
+ * flipping structure.  DirectDraw supports N surfaces in a
+ * surface flipping structure.  Only the surface that immediately
+ * precedeces the DDSCAPS_FRONTBUFFER has this capability bit set.
+ * The other surfaces are identified as back buffers by the presence
+ * of the DDSCAPS_FLIP capability, their attachment order, and the
+ * absence of the DDSCAPS_FRONTBUFFER and DDSCAPS_BACKBUFFER
+ * capabilities.  The bit is sent to CreateSurface when a standalone
+ * back buffer is being created.  This surface could be attached to
+ * a front buffer and/or back buffers to form a flipping surface
+ * structure after the CreateSurface call.  See AddAttachments for
+ * a detailed description of the behaviors in this case.
+ */
+#define DDSCAPS_BACKBUFFER                      0x00000004l
+
+/*
+ * Indicates a complex surface structure is being described.  A
+ * complex surface structure results in the creation of more than
+ * one surface.  The additional surfaces are attached to the root
+ * surface.  The complex structure can only be destroyed by
+ * destroying the root.
+ */
+#define DDSCAPS_COMPLEX                         0x00000008l
+
+/*
+ * Indicates that this surface is a part of a surface flipping structure.
+ * When it is passed to CreateSurface the DDSCAPS_FRONTBUFFER and
+ * DDSCAP_BACKBUFFER bits are not set.  They are set by CreateSurface
+ * on the resulting creations.  The dwBackBufferCount field in the
+ * DDSURFACEDESC structure must be set to at least 1 in order for
+ * the CreateSurface call to succeed.  The DDSCAPS_COMPLEX capability
+ * must always be set with creating multiple surfaces through CreateSurface.
+ */
+#define DDSCAPS_FLIP                            0x00000010l
+
+/*
+ * Indicates that this surface is THE front buffer of a surface flipping
+ * structure.  It is generally set by CreateSurface when the DDSCAPS_FLIP
+ * capability bit is set.
+ * If this capability is sent to CreateSurface then a standalonw front buffer
+ * is created.  This surface will not have the DDSCAPS_FLIP capability.
+ * It can be attached to other back buffers to form a flipping structure.
+ * See AddAttachments for a detailed description of the behaviors in this
+ * case.
+ */
+#define DDSCAPS_FRONTBUFFER                     0x00000020l
+
+/*
+ * Indicates that this surface is any offscreen surface that is not an overlay,
+ * texture, zbuffer, front buffer, back buffer, or alpha surface.  It is used
+ * to identify plain vanilla surfaces.
+ */
+#define DDSCAPS_OFFSCREENPLAIN                  0x00000040l
+
+/*
+ * Indicates that this surface is an overlay.  It may or may not be directly visible
+ * depending on whether or not it is currently being overlayed onto the primary 
+ * surface.  DDSCAPS_VISIBLE can be used to determine whether or not it is being 
+ * overlayed at the moment. 
+ */
+#define DDSCAPS_OVERLAY                         0x00000080l
+
+/*
+ * Indicates that unique DirectDrawPalette objects can be created and
+ * attached to this surface.
+ */
+#define DDSCAPS_PALETTE                         0x00000100l
+
+/*
+ * Indicates that this surface is the primary surface.  The primary
+ * surface represents what the user is seeing at the moment.
+ */
+#define DDSCAPS_PRIMARYSURFACE                  0x00000200l
+
+/*
+ * Indicates that this surface is the primary surface for the left eye.
+ * The primary surface for the left eye represents what the user is seeing
+ * at the moment with the users left eye.  When this surface is created the
+ * DDSCAPS_PRIMARYSURFACE represents what the user is seeing with the users
+ * right eye.
+ */
+#define DDSCAPS_PRIMARYSURFACELEFT              0x00000400l
+
+/*
+ * Indicates that this surface memory was allocated in system memory
+ */
+#define DDSCAPS_SYSTEMMEMORY                    0x00000800l
+
+/*
+ * Indicates that this surface can be used as a 3D texture.  It does not
+ * indicate whether or not the surface is being used for that purpose.
+ */
+#define DDSCAPS_TEXTURE                         0x00001000l
+
+/*
+ * Indicates that a surface may be a destination for 3D rendering.  This
+ * bit must be set in order to query for a Direct3D Device Interface 
+ * from this surface.
+ */
+#define DDSCAPS_3DDEVICE                        0x00002000l
+
+/*
+ * Indicates that this surface exists in video memory.
+ */
+#define DDSCAPS_VIDEOMEMORY                     0x00004000l
+
+/*
+ * Indicates that changes made to this surface are immediately visible.  
+ * It is always set for the primary surface and is set for overlays while
+ * they are being overlayed and texture maps while they are being textured.
+ */
+#define DDSCAPS_VISIBLE                         0x00008000l
+
+/*
+ * Indicates that only writes are permitted to the surface.  Read accesses 
+ * from the surface may or may not generate a protection fault, but the 
+ * results of a read from this surface will not be meaningful.  READ ONLY.
+ */
+#define DDSCAPS_WRITEONLY                       0x00010000l
+
+/*
+ * Indicates that this surface is a z buffer. A z buffer does not contain
+ * displayable information.  Instead it contains bit depth information that is
+ * used to determine which pixels are visible and which are obscured. 
+ */
+#define DDSCAPS_ZBUFFER                         0x00020000l
+
+/*
+ * Indicates surface will have a DC associated long term
+ */
+#define DDSCAPS_OWNDC                           0x00040000l
+
+/*
+ * Indicates surface should be able to receive live video
+ */
+#define DDSCAPS_LIVEVIDEO                       0x00080000l
+
+/*
+ * Indicates surface should be able to have a stream decompressed
+ * to it by the hardware.
+ */
+#define DDSCAPS_HWCODEC                         0x00100000l
+
+/*
+ * Surface is a 320x200 or 320x240 ModeX surface
+ */
+#define DDSCAPS_MODEX                           0x00200000l
+
+/*
+ * Indicates surface is one level of a mip-map. This surface will
+ * be attached to other DDSCAPS_MIPMAP surfaces to form the mip-map.
+ * This can be done explicitly, by creating a number of surfaces and
+ * attaching them with AddAttachedSurface or by implicitly by CreateSurface.
+ * If this bit is set then DDSCAPS_TEXTURE must also be set.
+ */
+#define DDSCAPS_MIPMAP                          0x00400000l
+
+
+
+/*
+ * Indicates that memory for the surface is not allocated until the surface
+ * is loaded (via the Direct3D texture Load() function).
+ */
+#define DDSCAPS_ALLOCONLOAD                     0x04000000l
+
+
+
+ /****************************************************************************
+ *
+ * DIRECTDRAW DRIVER CAPABILITY FLAGS
+ *
+ ****************************************************************************/
+
+/*
+ * Display hardware has 3D acceleration.
+ */
+#define DDCAPS_3D                       0x00000001l
+
+/*
+ * Indicates that DirectDraw will support only dest rectangles that are aligned
+ * on DIRECTDRAWCAPS.dwAlignBoundaryDest boundaries of the surface, respectively.
+ * READ ONLY.
+ */
+#define DDCAPS_ALIGNBOUNDARYDEST        0x00000002l
+
+/*
+ * Indicates that DirectDraw will support only source rectangles  whose sizes in 
+ * BYTEs are DIRECTDRAWCAPS.dwAlignSizeDest multiples, respectively.  READ ONLY.
+ */
+#define DDCAPS_ALIGNSIZEDEST            0x00000004l
+/*
+ * Indicates that DirectDraw will support only source rectangles that are aligned
+ * on DIRECTDRAWCAPS.dwAlignBoundarySrc boundaries of the surface, respectively.
+ * READ ONLY.
+ */
+#define DDCAPS_ALIGNBOUNDARYSRC         0x00000008l
+
+/*
+ * Indicates that DirectDraw will support only source rectangles  whose sizes in 
+ * BYTEs are DIRECTDRAWCAPS.dwAlignSizeSrc multiples, respectively.  READ ONLY.
+ */
+#define DDCAPS_ALIGNSIZESRC             0x00000010l
+
+/*
+ * Indicates that DirectDraw will create video memory surfaces that have a stride 
+ * alignment equal to DIRECTDRAWCAPS.dwAlignStride.  READ ONLY.
+ */
+#define DDCAPS_ALIGNSTRIDE              0x00000020l
+
+/*
+ * Display hardware is capable of blt operations.
+ */
+#define DDCAPS_BLT                      0x00000040l
+
+/*
+ * Display hardware is capable of asynchronous blt operations.
+ */
+#define DDCAPS_BLTQUEUE                 0x00000080l
+
+/*
+ * Display hardware is capable of color space conversions during the blt operation.
+ */
+#define DDCAPS_BLTFOURCC                0x00000100l
+
+/*
+ * Display hardware is capable of stretching during blt operations.
+ */
+#define DDCAPS_BLTSTRETCH               0x00000200l
+
+/*
+ * Display hardware is shared with GDI.
+ */
+#define DDCAPS_GDI                      0x00000400l
+
+/*
+ * Display hardware can overlay.
+ */
+#define DDCAPS_OVERLAY                  0x00000800l
+
+/*
+ * Set if display hardware supports overlays but can not clip them.
+ */
+#define DDCAPS_OVERLAYCANTCLIP          0x00001000l
+
+/*
+ * Indicates that overlay hardware is capable of color space conversions during
+ * the overlay operation.
+ */
+#define DDCAPS_OVERLAYFOURCC            0x00002000l
+
+/*
+ * Indicates that stretching can be done by the overlay hardware.
+ */
+#define DDCAPS_OVERLAYSTRETCH           0x00004000l
+
+/*
+ * Indicates that unique DirectDrawPalettes can be created for DirectDrawSurfaces
+ * other than the primary surface.
+ */
+#define DDCAPS_PALETTE                  0x00008000l
+
+/*
+ * Indicates that palette changes can be syncd with the veritcal refresh.
+ */
+#define DDCAPS_PALETTEVSYNC             0x00010000l
+
+/*
+ * Display hardware can return the current scan line.
+ */
+#define DDCAPS_READSCANLINE             0x00020000l
+
+/*
+ * Display hardware has stereo vision capabilities.  DDSCAPS_PRIMARYSURFACELEFT 
+ * can be created.
+ */
+#define DDCAPS_STEREOVIEW               0x00040000l
+
+/*
+ * Display hardware is capable of generating a vertical blank interrupt.
+ */
+#define DDCAPS_VBI                      0x00080000l
+
+/*
+ * Supports the use of z buffers with blt operations.
+ */
+#define DDCAPS_ZBLTS                    0x00100000l
+
+/*
+ * Supports Z Ordering of overlays.
+ */
+#define DDCAPS_ZOVERLAYS                0x00200000l
+
+/*
+ * Supports color key
+ */
+#define DDCAPS_COLORKEY                 0x00400000l
+
+/*
+ * Supports alpha surfaces
+ */
+#define DDCAPS_ALPHA                    0x00800000l
+
+/*
+ * colorkey is hardware assisted(DDCAPS_COLORKEY will also be set)
+ */
+#define DDCAPS_COLORKEYHWASSIST         0x01000000l
+
+/*
+ * no hardware support at all
+ */
+#define DDCAPS_NOHARDWARE               0x02000000l
+
+/*
+ * Display hardware is capable of color fill with bltter
+ */
+#define DDCAPS_BLTCOLORFILL             0x04000000l
+
+/*
+ * Display hardware is bank switched, and potentially very slow at
+ * random access to VRAM.
+ */
+#define DDCAPS_BANKSWITCHED             0x08000000l
+
+/*
+ * Display hardware is capable of depth filling Z-buffers with bltter
+ */
+#define DDCAPS_BLTDEPTHFILL             0x10000000l
+
+/*
+ * Display hardware is capable of clipping while bltting.
+ */
+#define DDCAPS_CANCLIP                  0x20000000l
+
+/*
+ * Display hardware is capable of clipping while stretch bltting.
+ */
+#define DDCAPS_CANCLIPSTRETCHED         0x40000000l
+
+/*
+ * Display hardware is capable of bltting to or from system memory
+ */
+#define DDCAPS_CANBLTSYSMEM             0x80000000l
+
+
+ /****************************************************************************
+ *
+ * MORE DIRECTDRAW DRIVER CAPABILITY FLAGS (dwCaps2)
+ *
+ ****************************************************************************/
+
+/*
+ * Display hardware is certified
+ */
+#define DDCAPS2_CERTIFIED               0x00000001l
+
+/*
+ * Driver cannot interleave 2D operations (lock and blt) to surfaces with
+ * Direct3D rendering operations between calls to BeginScene() and EndScene()
+ */
+#define DDCAPS2_NO2DDURING3DSCENE       0x00000002l
+
+/****************************************************************************
+ *
+ * DIRECTDRAW FX ALPHA CAPABILITY FLAGS
+ *
+ ****************************************************************************/
+
+/*
+ * Supports alpha blending around the edge of a source color keyed surface.
+ * For Blt.
+ */
+#define DDFXALPHACAPS_BLTALPHAEDGEBLEND         0x00000001l
+
+/*
+ * Supports alpha information in the pixel format.  The bit depth of alpha 
+ * information in the pixel format can be 1,2,4, or 8.  The alpha value becomes
+ * more opaque as the alpha value increases.  (0 is transparent.)
+ * For Blt.
+ */
+#define DDFXALPHACAPS_BLTALPHAPIXELS            0x00000002l
+
+/*
+ * Supports alpha information in the pixel format.  The bit depth of alpha 
+ * information in the pixel format can be 1,2,4, or 8.  The alpha value 
+ * becomes more transparent as the alpha value increases.  (0 is opaque.) 
+ * This flag can only be set if DDCAPS_ALPHA is set.
+ * For Blt.
+ */
+#define DDFXALPHACAPS_BLTALPHAPIXELSNEG         0x00000004l
+
+/*
+ * Supports alpha only surfaces.  The bit depth of an alpha only surface can be
+ * 1,2,4, or 8.  The alpha value becomes more opaque as the alpha value increases.
+ * (0 is transparent.)
+ * For Blt.
+ */
+#define DDFXALPHACAPS_BLTALPHASURFACES          0x00000008l
+
+/*
+ * The depth of the alpha channel data can range can be 1,2,4, or 8.  
+ * The NEG suffix indicates that this alpha channel becomes more transparent
+ * as the alpha value increases. (0 is opaque.)  This flag can only be set if
+ * DDCAPS_ALPHA is set.
+ * For Blt.
+ */
+#define DDFXALPHACAPS_BLTALPHASURFACESNEG       0x00000010l
+
+/*
+ * Supports alpha blending around the edge of a source color keyed surface.
+ * For Overlays.
+ */
+#define DDFXALPHACAPS_OVERLAYALPHAEDGEBLEND     0x00000020l
+
+/*
+ * Supports alpha information in the pixel format.  The bit depth of alpha 
+ * information in the pixel format can be 1,2,4, or 8.  The alpha value becomes
+ * more opaque as the alpha value increases.  (0 is transparent.)
+ * For Overlays.
+ */
+#define DDFXALPHACAPS_OVERLAYALPHAPIXELS        0x00000040l
+
+/*
+ * Supports alpha information in the pixel format.  The bit depth of alpha 
+ * information in the pixel format can be 1,2,4, or 8.  The alpha value 
+ * becomes more transparent as the alpha value increases.  (0 is opaque.) 
+ * This flag can only be set if DDCAPS_ALPHA is set.
+ * For Overlays.
+ */
+#define DDFXALPHACAPS_OVERLAYALPHAPIXELSNEG     0x00000080l
+
+/*
+ * Supports alpha only surfaces.  The bit depth of an alpha only surface can be
+ * 1,2,4, or 8.  The alpha value becomes more opaque as the alpha value increases.
+ * (0 is transparent.)
+ * For Overlays.
+ */
+#define DDFXALPHACAPS_OVERLAYALPHASURFACES      0x00000100l
+
+/*
+ * The depth of the alpha channel data can range can be 1,2,4, or 8.  
+ * The NEG suffix indicates that this alpha channel becomes more transparent
+ * as the alpha value increases. (0 is opaque.)  This flag can only be set if
+ * DDCAPS_ALPHA is set.
+ * For Overlays.
+ */
+#define DDFXALPHACAPS_OVERLAYALPHASURFACESNEG   0x00000200l
+
+/****************************************************************************
+ *
+ * DIRECTDRAW FX CAPABILITY FLAGS
+ *
+ ****************************************************************************/
+
+/*
+ * Uses arithmetic operations to stretch and shrink surfaces during blt
+ * rather than pixel doubling techniques.  Along the Y axis.
+ */
+#define DDFXCAPS_BLTARITHSTRETCHY       0x00000020l
+
+/*
+ * Uses arithmetic operations to stretch during blt
+ * rather than pixel doubling techniques.  Along the Y axis. Only
+ * works for x1, x2, etc.
+ */
+#define DDFXCAPS_BLTARITHSTRETCHYN      0x00000010l
+
+/*
+ * Supports mirroring left to right in blt.
+ */
+#define DDFXCAPS_BLTMIRRORLEFTRIGHT     0x00000040l
+
+/*
+ * Supports mirroring top to bottom in blt.
+ */
+#define DDFXCAPS_BLTMIRRORUPDOWN        0x00000080l
+
+/*
+ * Supports arbitrary rotation for blts.
+ */
+#define DDFXCAPS_BLTROTATION            0x00000100l
+
+/*
+ * Supports 90 degree rotations for blts.
+ */
+#define DDFXCAPS_BLTROTATION90          0x00000200l
+
+/*
+ * DirectDraw supports arbitrary shrinking of a surface along the
+ * x axis (horizontal direction) for blts.
+ */
+#define DDFXCAPS_BLTSHRINKX             0x00000400l
+
+/*
+ * DirectDraw supports integer shrinking (1x,2x,) of a surface
+ * along the x axis (horizontal direction) for blts.
+ */
+#define DDFXCAPS_BLTSHRINKXN            0x00000800l
+
+/*
+ * DirectDraw supports arbitrary shrinking of a surface along the
+ * y axis (horizontal direction) for blts.  
+ */
+#define DDFXCAPS_BLTSHRINKY             0x00001000l
+
+/*
+ * DirectDraw supports integer shrinking (1x,2x,) of a surface
+ * along the y axis (vertical direction) for blts.  
+ */
+#define DDFXCAPS_BLTSHRINKYN            0x00002000l
+
+/*
+ * DirectDraw supports arbitrary stretching of a surface along the
+ * x axis (horizontal direction) for blts.
+ */
+#define DDFXCAPS_BLTSTRETCHX            0x00004000l
+
+/*
+ * DirectDraw supports integer stretching (1x,2x,) of a surface
+ * along the x axis (horizontal direction) for blts.
+ */
+#define DDFXCAPS_BLTSTRETCHXN           0x00008000l
+
+/*
+ * DirectDraw supports arbitrary stretching of a surface along the
+ * y axis (horizontal direction) for blts.  
+ */
+#define DDFXCAPS_BLTSTRETCHY            0x00010000l
+
+/*
+ * DirectDraw supports integer stretching (1x,2x,) of a surface
+ * along the y axis (vertical direction) for blts.  
+ */
+#define DDFXCAPS_BLTSTRETCHYN           0x00020000l
+
+/*
+ * Uses arithmetic operations to stretch and shrink surfaces during 
+ * overlay rather than pixel doubling techniques.  Along the Y axis 
+ * for overlays.
+ */
+#define DDFXCAPS_OVERLAYARITHSTRETCHY   0x00040000l
+
+/*
+ * Uses arithmetic operations to stretch surfaces during 
+ * overlay rather than pixel doubling techniques.  Along the Y axis 
+ * for overlays. Only works for x1, x2, etc.
+ */
+#define DDFXCAPS_OVERLAYARITHSTRETCHYN  0x00000008l
+
+/*
+ * DirectDraw supports arbitrary shrinking of a surface along the
+ * x axis (horizontal direction) for overlays.
+ */
+#define DDFXCAPS_OVERLAYSHRINKX         0x00080000l
+
+/*
+ * DirectDraw supports integer shrinking (1x,2x,) of a surface
+ * along the x axis (horizontal direction) for overlays.
+ */
+#define DDFXCAPS_OVERLAYSHRINKXN        0x00100000l
+
+/*
+ * DirectDraw supports arbitrary shrinking of a surface along the
+ * y axis (horizontal direction) for overlays.  
+ */
+#define DDFXCAPS_OVERLAYSHRINKY         0x00200000l
+
+/*
+ * DirectDraw supports integer shrinking (1x,2x,) of a surface
+ * along the y axis (vertical direction) for overlays.  
+ */
+#define DDFXCAPS_OVERLAYSHRINKYN        0x00400000l
+
+/*
+ * DirectDraw supports arbitrary stretching of a surface along the
+ * x axis (horizontal direction) for overlays.
+ */
+#define DDFXCAPS_OVERLAYSTRETCHX        0x00800000l
+
+/*
+ * DirectDraw supports integer stretching (1x,2x,) of a surface
+ * along the x axis (horizontal direction) for overlays.
+ */
+#define DDFXCAPS_OVERLAYSTRETCHXN       0x01000000l
+
+/*
+ * DirectDraw supports arbitrary stretching of a surface along the
+ * y axis (horizontal direction) for overlays.  
+ */
+#define DDFXCAPS_OVERLAYSTRETCHY        0x02000000l
+
+/*
+ * DirectDraw supports integer stretching (1x,2x,) of a surface
+ * along the y axis (vertical direction) for overlays.  
+ */
+#define DDFXCAPS_OVERLAYSTRETCHYN       0x04000000l
+
+/*
+ * DirectDraw supports mirroring of overlays across the vertical axis
+ */
+#define DDFXCAPS_OVERLAYMIRRORLEFTRIGHT 0x08000000l
+
+/*
+ * DirectDraw supports mirroring of overlays across the horizontal axis
+ */
+#define DDFXCAPS_OVERLAYMIRRORUPDOWN    0x10000000l
+
+/****************************************************************************
+ *
+ * DIRECTDRAW STEREO VIEW CAPABILITIES
+ *
+ ****************************************************************************/
+
+/*
+ * The stereo view is accomplished via enigma encoding.
+ */
+#define DDSVCAPS_ENIGMA                 0x00000001l
+
+/*
+ * The stereo view is accomplished via high frequency flickering.
+ */
+#define DDSVCAPS_FLICKER                0x00000002l
+
+/*
+ * The stereo view is accomplished via red and blue filters applied
+ * to the left and right eyes.  All images must adapt their colorspaces
+ * for this process.
+ */
+#define DDSVCAPS_REDBLUE                0x00000004l
+
+/*
+ * The stereo view is accomplished with split screen technology.
+ */
+#define DDSVCAPS_SPLIT                  0x00000008l
+
+/****************************************************************************
+ *
+ * DIRECTDRAWPALETTE CAPABILITIES
+ *
+ ****************************************************************************/
+
+/*
+ * Index is 4 bits.  There are sixteen color entries in the palette table.
+ */
+#define DDPCAPS_4BIT                    0x00000001l
+
+/*
+ * Index is onto a 8 bit color index.  This field is only valid with the
+ * DDPCAPS_1BIT, DDPCAPS_2BIT or DDPCAPS_4BIT capability and the target
+ * surface is in 8bpp. Each color entry is one byte long and is an index
+ * into destination surface's 8bpp palette.
+ */
+#define DDPCAPS_8BITENTRIES             0x00000002l
+
+/*
+ * Index is 8 bits.  There are 256 color entries in the palette table.
+ */
+#define DDPCAPS_8BIT                    0x00000004l
+
+/*
+ * Indicates that this DIRECTDRAWPALETTE should use the palette color array
+ * passed into the lpDDColorArray parameter to initialize the DIRECTDRAWPALETTE
+ * object.
+ */
+#define DDPCAPS_INITIALIZE              0x00000008l
+
+/*
+ * This palette is the one attached to the primary surface.  Changing this
+ * table has immediate effect on the display unless DDPSETPAL_VSYNC is specified
+ * and supported.
+ */
+#define DDPCAPS_PRIMARYSURFACE          0x00000010l
+
+/*
+ * This palette is the one attached to the primary surface left.  Changing
+ * this table has immediate effect on the display for the left eye unless
+ * DDPSETPAL_VSYNC is specified and supported.
+ */
+#define DDPCAPS_PRIMARYSURFACELEFT      0x00000020l
+
+/*
+ * This palette can have all 256 entries defined
+ */
+#define DDPCAPS_ALLOW256                0x00000040l
+
+/*
+ * This palette can have modifications to it synced with the monitors
+ * refresh rate.
+ */
+#define DDPCAPS_VSYNC                   0x00000080l
+
+/*
+ * Index is 1 bit.  There are two color entries in the palette table.
+ */
+#define DDPCAPS_1BIT                    0x00000100l
+
+/*
+ * Index is 2 bit.  There are four color entries in the palette table.
+ */
+#define DDPCAPS_2BIT                    0x00000200l
+
+
+/****************************************************************************
+ *
+ * DIRECTDRAWPALETTE SETENTRY CONSTANTS
+ *
+ ****************************************************************************/
+
+
+/****************************************************************************
+ *
+ * DIRECTDRAWPALETTE GETENTRY CONSTANTS
+ *
+ ****************************************************************************/
+
+/* 0 is the only legal value */
+
+/****************************************************************************
+ *
+ * DIRECTDRAWSURFACE SETPALETTE CONSTANTS
+ *
+ ****************************************************************************/
+
+
+/****************************************************************************
+ *
+ * DIRECTDRAW BITDEPTH CONSTANTS
+ *
+ * NOTE:  These are only used to indicate supported bit depths.   These
+ * are flags only, they are not to be used as an actual bit depth.   The
+ * absolute numbers 1, 2, 4, 8, 16, 24 and 32 are used to indicate actual
+ * bit depths in a surface or for changing the display mode.
+ *
+ ****************************************************************************/
+
+/*
+ * 1 bit per pixel.
+ */
+#define DDBD_1                  0x00004000l
+
+/*
+ * 2 bits per pixel.
+ */
+#define DDBD_2                  0x00002000l
+
+/*
+ * 4 bits per pixel.
+ */
+#define DDBD_4                  0x00001000l
+
+/*
+ * 8 bits per pixel.
+ */
+#define DDBD_8                  0x00000800l
+
+/*
+ * 16 bits per pixel.
+ */
+#define DDBD_16                 0x00000400l
+
+/*
+ * 24 bits per pixel.
+ */
+#define DDBD_24                 0X00000200l
+
+/*
+ * 32 bits per pixel.
+ */
+#define DDBD_32                 0x00000100l
+
+/****************************************************************************
+ *
+ * DIRECTDRAWSURFACE SET/GET COLOR KEY FLAGS
+ *
+ ****************************************************************************/
+
+/*
+ * Set if the structure contains a color space.  Not set if the structure
+ * contains a single color key.
+ */
+#define DDCKEY_COLORSPACE       0x00000001l
+
+/*
+ * Set if the structure specifies a color key or color space which is to be
+ * used as a destination color key for blt operations.
+ */
+#define DDCKEY_DESTBLT          0x00000002l
+
+/*
+ * Set if the structure specifies a color key or color space which is to be
+ * used as a destination color key for overlay operations.
+ */
+#define DDCKEY_DESTOVERLAY      0x00000004l
+
+/*
+ * Set if the structure specifies a color key or color space which is to be
+ * used as a source color key for blt operations.
+ */
+#define DDCKEY_SRCBLT           0x00000008l
+
+/*
+ * Set if the structure specifies a color key or color space which is to be
+ * used as a source color key for overlay operations.
+ */
+#define DDCKEY_SRCOVERLAY       0x00000010l
+
+
+/****************************************************************************
+ *
+ * DIRECTDRAW COLOR KEY CAPABILITY FLAGS
+ *
+ ****************************************************************************/
+
+/*
+ * Supports transparent blting using a color key to identify the replaceable 
+ * bits of the destination surface for RGB colors.
+ */
+#define DDCKEYCAPS_DESTBLT                      0x00000001l
+
+/*
+ * Supports transparent blting using a color space to identify the replaceable
+ * bits of the destination surface for RGB colors.
+ */
+#define DDCKEYCAPS_DESTBLTCLRSPACE              0x00000002l
+
+/*
+ * Supports transparent blting using a color space to identify the replaceable
+ * bits of the destination surface for YUV colors.
+ */
+#define DDCKEYCAPS_DESTBLTCLRSPACEYUV           0x00000004l
+
+/*
+ * Supports transparent blting using a color key to identify the replaceable 
+ * bits of the destination surface for YUV colors.
+ */
+#define DDCKEYCAPS_DESTBLTYUV                   0x00000008l
+
+/*
+ * Supports overlaying using colorkeying of the replaceable bits of the surface
+ * being overlayed for RGB colors.
+ */
+#define DDCKEYCAPS_DESTOVERLAY                  0x00000010l
+
+/*
+ * Supports a color space as the color key for the destination for RGB colors.
+ */
+#define DDCKEYCAPS_DESTOVERLAYCLRSPACE          0x00000020l
+
+/*
+ * Supports a color space as the color key for the destination for YUV colors.
+ */
+#define DDCKEYCAPS_DESTOVERLAYCLRSPACEYUV       0x00000040l
+
+/*
+ * Supports only one active destination color key value for visible overlay
+ * surfaces.
+ */
+#define DDCKEYCAPS_DESTOVERLAYONEACTIVE         0x00000080l
+
+/*
+ * Supports overlaying using colorkeying of the replaceable bits of the 
+ * surface being overlayed for YUV colors.
+ */
+#define DDCKEYCAPS_DESTOVERLAYYUV               0x00000100l
+
+/*
+ * Supports transparent blting using the color key for the source with
+ * this surface for RGB colors.
+ */
+#define DDCKEYCAPS_SRCBLT                       0x00000200l
+
+/*
+ * Supports transparent blting using a color space for the source with
+ * this surface for RGB colors.
+ */
+#define DDCKEYCAPS_SRCBLTCLRSPACE               0x00000400l
+
+/*
+ * Supports transparent blting using a color space for the source with
+ * this surface for YUV colors.
+ */
+#define DDCKEYCAPS_SRCBLTCLRSPACEYUV            0x00000800l
+
+/*
+ * Supports transparent blting using the color key for the source with
+ * this surface for YUV colors.
+ */
+#define DDCKEYCAPS_SRCBLTYUV                    0x00001000l
+
+/*
+ * Supports overlays using the color key for the source with this
+ * overlay surface for RGB colors.
+ */
+#define DDCKEYCAPS_SRCOVERLAY                   0x00002000l
+
+/*
+ * Supports overlays using a color space as the source color key for
+ * the overlay surface for RGB colors.
+ */
+#define DDCKEYCAPS_SRCOVERLAYCLRSPACE           0x00004000l
+
+/*
+ * Supports overlays using a color space as the source color key for
+ * the overlay surface for YUV colors.
+ */
+#define DDCKEYCAPS_SRCOVERLAYCLRSPACEYUV        0x00008000l
+
+/*
+ * Supports only one active source color key value for visible
+ * overlay surfaces.
+ */
+#define DDCKEYCAPS_SRCOVERLAYONEACTIVE          0x00010000l
+
+/*
+ * Supports overlays using the color key for the source with this
+ * overlay surface for YUV colors.
+ */
+#define DDCKEYCAPS_SRCOVERLAYYUV                0x00020000l
+
+/*
+ * there are no bandwidth trade-offs for using colorkey with an overlay
+ */
+#define DDCKEYCAPS_NOCOSTOVERLAY                0x00040000l
+
+
+/****************************************************************************
+ *
+ * DIRECTDRAW PIXELFORMAT FLAGS
+ *
+ ****************************************************************************/
+
+/*
+ * The surface has alpha channel information in the pixel format.
+ */
+#define DDPF_ALPHAPIXELS                        0x00000001l
+
+/*
+ * The pixel format contains alpha only information
+ */
+#define DDPF_ALPHA                              0x00000002l
+
+/*
+ * The FourCC code is valid.
+ */
+#define DDPF_FOURCC                             0x00000004l
+
+/*
+ * The surface is 4-bit color indexed.
+ */
+#define DDPF_PALETTEINDEXED4                    0x00000008l
+
+/*
+ * The surface is indexed into a palette which stores indices
+ * into the destination surface's 8-bit palette.
+ */
+#define DDPF_PALETTEINDEXEDTO8                  0x00000010l
+
+/*
+ * The surface is 8-bit color indexed.
+ */
+#define DDPF_PALETTEINDEXED8                    0x00000020l
+
+/*
+ * The RGB data in the pixel format structure is valid.
+ */
+#define DDPF_RGB                                0x00000040l
+
+/*
+ * The surface will accept pixel data in the format specified
+ * and compress it during the write.
+ */
+#define DDPF_COMPRESSED                         0x00000080l
+
+/*
+ * The surface will accept RGB data and translate it during
+ * the write to YUV data.  The format of the data to be written
+ * will be contained in the pixel format structure.  The DDPF_RGB
+ * flag will be set. 
+ */
+#define DDPF_RGBTOYUV                           0x00000100l
+
+/*
+ * pixel format is YUV - YUV data in pixel format struct is valid
+ */
+#define DDPF_YUV                                0x00000200l
+
+/*
+ * pixel format is a z buffer only surface
+ */
+#define DDPF_ZBUFFER                            0x00000400l
+
+/*
+ * The surface is 1-bit color indexed.
+ */
+#define DDPF_PALETTEINDEXED1                    0x00000800l
+
+/*
+ * The surface is 2-bit color indexed.
+ */
+#define DDPF_PALETTEINDEXED2                    0x00001000l
+
+/*===========================================================================
+ *
+ *
+ * DIRECTDRAW CALLBACK FLAGS
+ *
+ *
+ *==========================================================================*/
+
+/****************************************************************************
+ *
+ * DIRECTDRAW ENUMSURFACES FLAGS
+ *
+ ****************************************************************************/
+
+/*
+ * Enumerate all of the surfaces that meet the search criterion.
+ */
+#define DDENUMSURFACES_ALL                      0x00000001l
+
+/*
+ * A search hit is a surface that matches the surface description.
+ */
+#define DDENUMSURFACES_MATCH                    0x00000002l
+
+/*
+ * A search hit is a surface that does not match the surface description.
+ */
+#define DDENUMSURFACES_NOMATCH                  0x00000004l
+
+/*
+ * Enumerate the first surface that can be created which meets the search criterion.
+ */
+#define DDENUMSURFACES_CANBECREATED             0x00000008l
+
+/*
+ * Enumerate the surfaces that already exist that meet the search criterion.
+ */
+#define DDENUMSURFACES_DOESEXIST                0x00000010l
+
+
+/****************************************************************************
+ *
+ * DIRECTDRAW ENUMDISPLAYMODES FLAGS
+ *
+ ****************************************************************************/
+
+/*
+ * Enumerate Modes with different refresh rates.  EnumDisplayModes guarantees
+ * that a particular mode will be enumerated only once.  This flag specifies whether
+ * the refresh rate is taken into account when determining if a mode is unique.
+ */
+#define DDEDM_REFRESHRATES                      0x00000001l
+
+
+/****************************************************************************
+ *
+ * DIRECTDRAW SETCOOPERATIVELEVEL FLAGS
+ *
+ ****************************************************************************/
+
+/*
+ * Exclusive mode owner will be responsible for the entire primary surface.
+ * GDI can be ignored. used with DD
+ */
+#define DDSCL_FULLSCREEN                        0x00000001l
+
+/*
+ * allow CTRL_ALT_DEL to work while in fullscreen exclusive mode 
+ */
+#define DDSCL_ALLOWREBOOT                       0x00000002l
+
+/*
+ * prevents DDRAW from modifying the application window.
+ * prevents DDRAW from minimize/restore the application window on activation.
+ */
+#define DDSCL_NOWINDOWCHANGES                   0x00000004l
+
+/*
+ * app wants to work as a regular Windows application
+ */
+#define DDSCL_NORMAL                            0x00000008l
+
+/*
+ * app wants exclusive access
+ */
+#define DDSCL_EXCLUSIVE                         0x00000010l
+
+
+/*
+ * app can deal with non-windows display modes
+ */
+#define DDSCL_ALLOWMODEX                        0x00000040l
+
+
+/****************************************************************************
+ *
+ * DIRECTDRAW BLT FLAGS
+ *
+ ****************************************************************************/
+
+/*
+ * Use the alpha information in the pixel format or the alpha channel surface
+ * attached to the destination surface as the alpha channel for this blt.
+ */
+#define DDBLT_ALPHADEST                         0x00000001l
+
+/*
+ * Use the dwConstAlphaDest field in the DDBLTFX structure as the alpha channel
+ * for the destination surface for this blt.
+ */
+#define DDBLT_ALPHADESTCONSTOVERRIDE            0x00000002l
+
+/*
+ * The NEG suffix indicates that the destination surface becomes more
+ * transparent as the alpha value increases. (0 is opaque)
+ */
+#define DDBLT_ALPHADESTNEG                      0x00000004l
+
+/*
+ * Use the lpDDSAlphaDest field in the DDBLTFX structure as the alpha
+ * channel for the destination for this blt.
+ */
+#define DDBLT_ALPHADESTSURFACEOVERRIDE          0x00000008l
+
+/*
+ * Use the dwAlphaEdgeBlend field in the DDBLTFX structure as the alpha channel
+ * for the edges of the image that border the color key colors.
+ */
+#define DDBLT_ALPHAEDGEBLEND                    0x00000010l
+
+/*
+ * Use the alpha information in the pixel format or the alpha channel surface
+ * attached to the source surface as the alpha channel for this blt.
+ */
+#define DDBLT_ALPHASRC                          0x00000020l
+
+/*
+ * Use the dwConstAlphaSrc field in the DDBLTFX structure as the alpha channel
+ * for the source for this blt.
+ */
+#define DDBLT_ALPHASRCCONSTOVERRIDE             0x00000040l
+
+/*
+ * The NEG suffix indicates that the source surface becomes more transparent
+ * as the alpha value increases. (0 is opaque)
+ */
+#define DDBLT_ALPHASRCNEG                       0x00000080l
+
+/*
+ * Use the lpDDSAlphaSrc field in the DDBLTFX structure as the alpha channel
+ * for the source for this blt. 
+ */
+#define DDBLT_ALPHASRCSURFACEOVERRIDE           0x00000100l
+
+/*
+ * Do this blt asynchronously through the FIFO in the order received.  If
+ * there is no room in the hardware FIFO fail the call.
+ */
+#define DDBLT_ASYNC                             0x00000200l
+
+/*
+ * Uses the dwFillColor field in the DDBLTFX structure as the RGB color
+ * to fill the destination rectangle on the destination surface with.
+ */
+#define DDBLT_COLORFILL                         0x00000400l
+
+/*
+ * Uses the dwDDFX field in the DDBLTFX structure to specify the effects
+ * to use for the blt.
+ */
+#define DDBLT_DDFX                              0x00000800l
+
+/*
+ * Uses the dwDDROPS field in the DDBLTFX structure to specify the ROPS
+ * that are not part of the Win32 API.
+ */
+#define DDBLT_DDROPS                            0x00001000l
+
+/*
+ * Use the color key associated with the destination surface.
+ */
+#define DDBLT_KEYDEST                           0x00002000l
+
+/*
+ * Use the dckDestColorkey field in the DDBLTFX structure as the color key
+ * for the destination surface.
+ */
+#define DDBLT_KEYDESTOVERRIDE                   0x00004000l
+
+/*
+ * Use the color key associated with the source surface.
+ */
+#define DDBLT_KEYSRC                            0x00008000l
+
+/*
+ * Use the dckSrcColorkey field in the DDBLTFX structure as the color key
+ * for the source surface.
+ */
+#define DDBLT_KEYSRCOVERRIDE                    0x00010000l
+
+/*
+ * Use the dwROP field in the DDBLTFX structure for the raster operation
+ * for this blt.  These ROPs are the same as the ones defined in the Win32 API.
+ */
+#define DDBLT_ROP                               0x00020000l
+
+/*
+ * Use the dwRotationAngle field in the DDBLTFX structure as the angle
+ * (specified in 1/100th of a degree) to rotate the surface.
+ */
+#define DDBLT_ROTATIONANGLE                     0x00040000l
+
+/*
+ * Z-buffered blt using the z-buffers attached to the source and destination
+ * surfaces and the dwZBufferOpCode field in the DDBLTFX structure as the
+ * z-buffer opcode.
+ */
+#define DDBLT_ZBUFFER                           0x00080000l
+
+/*
+ * Z-buffered blt using the dwConstDest Zfield and the dwZBufferOpCode field
+ * in the DDBLTFX structure as the z-buffer and z-buffer opcode respectively
+ * for the destination.
+ */
+#define DDBLT_ZBUFFERDESTCONSTOVERRIDE          0x00100000l
+
+/*
+ * Z-buffered blt using the lpDDSDestZBuffer field and the dwZBufferOpCode
+ * field in the DDBLTFX structure as the z-buffer and z-buffer opcode
+ * respectively for the destination.
+ */
+#define DDBLT_ZBUFFERDESTOVERRIDE               0x00200000l
+
+/*
+ * Z-buffered blt using the dwConstSrcZ field and the dwZBufferOpCode field
+ * in the DDBLTFX structure as the z-buffer and z-buffer opcode respectively
+ * for the source.
+ */
+#define DDBLT_ZBUFFERSRCCONSTOVERRIDE           0x00400000l
+
+/*
+ * Z-buffered blt using the lpDDSSrcZBuffer field and the dwZBufferOpCode
+ * field in the DDBLTFX structure as the z-buffer and z-buffer opcode
+ * respectively for the source.
+ */
+#define DDBLT_ZBUFFERSRCOVERRIDE                0x00800000l
+
+/*
+ * wait until the device is ready to handle the blt
+ * this will cause blt to not return DDERR_WASSTILLDRAWING
+ */
+#define DDBLT_WAIT                              0x01000000l
+
+/*
+ * Uses the dwFillDepth field in the DDBLTFX structure as the depth value
+ * to fill the destination rectangle on the destination Z-buffer surface
+ * with.
+ */
+#define DDBLT_DEPTHFILL                         0x02000000l
+
+
+/****************************************************************************
+ *
+ * BLTFAST FLAGS
+ *
+ ****************************************************************************/
+
+#define DDBLTFAST_NOCOLORKEY                    0x00000000
+#define DDBLTFAST_SRCCOLORKEY                   0x00000001
+#define DDBLTFAST_DESTCOLORKEY                  0x00000002
+#define DDBLTFAST_WAIT                          0x00000010
+
+/****************************************************************************
+ *
+ * FLIP FLAGS
+ *
+ ****************************************************************************/
+
+#define DDFLIP_WAIT                          0x00000001l
+
+
+/****************************************************************************
+ *
+ * DIRECTDRAW SURFACE OVERLAY FLAGS
+ *
+ ****************************************************************************/
+
+/*
+ * Use the alpha information in the pixel format or the alpha channel surface
+ * attached to the destination surface as the alpha channel for the
+ * destination overlay.
+ */
+#define DDOVER_ALPHADEST                        0x00000001l
+
+/*
+ * Use the dwConstAlphaDest field in the DDOVERLAYFX structure as the
+ * destination alpha channel for this overlay.
+ */
+#define DDOVER_ALPHADESTCONSTOVERRIDE           0x00000002l
+
+/*
+ * The NEG suffix indicates that the destination surface becomes more
+ * transparent as the alpha value increases. 
+ */
+#define DDOVER_ALPHADESTNEG                     0x00000004l
+
+/*
+ * Use the lpDDSAlphaDest field in the DDOVERLAYFX structure as the alpha
+ * channel destination for this overlay.
+ */
+#define DDOVER_ALPHADESTSURFACEOVERRIDE         0x00000008l
+
+/*
+ * Use the dwAlphaEdgeBlend field in the DDOVERLAYFX structure as the alpha
+ * channel for the edges of the image that border the color key colors.
+ */
+#define DDOVER_ALPHAEDGEBLEND                   0x00000010l
+
+/*
+ * Use the alpha information in the pixel format or the alpha channel surface
+ * attached to the source surface as the source alpha channel for this overlay.
+ */
+#define DDOVER_ALPHASRC                         0x00000020l
+
+/*
+ * Use the dwConstAlphaSrc field in the DDOVERLAYFX structure as the source
+ * alpha channel for this overlay.
+ */
+#define DDOVER_ALPHASRCCONSTOVERRIDE            0x00000040l
+
+/*
+ * The NEG suffix indicates that the source surface becomes more transparent
+ * as the alpha value increases.
+ */
+#define DDOVER_ALPHASRCNEG                      0x00000080l
+
+/*
+ * Use the lpDDSAlphaSrc field in the DDOVERLAYFX structure as the alpha channel
+ * source for this overlay.
+ */
+#define DDOVER_ALPHASRCSURFACEOVERRIDE          0x00000100l
+
+/*
+ * Turn this overlay off.
+ */
+#define DDOVER_HIDE                             0x00000200l
+
+/*
+ * Use the color key associated with the destination surface.
+ */
+#define DDOVER_KEYDEST                          0x00000400l
+
+/*
+ * Use the dckDestColorkey field in the DDOVERLAYFX structure as the color key
+ * for the destination surface
+ */
+#define DDOVER_KEYDESTOVERRIDE                  0x00000800l
+
+/*
+ * Use the color key associated with the source surface.
+ */
+#define DDOVER_KEYSRC                           0x00001000l
+
+/*
+ * Use the dckSrcColorkey field in the DDOVERLAYFX structure as the color key
+ * for the source surface.
+ */
+#define DDOVER_KEYSRCOVERRIDE                   0x00002000l
+
+/*
+ * Turn this overlay on.
+ */
+#define DDOVER_SHOW                             0x00004000l
+
+/*
+ * Add a dirty rect to an emulated overlayed surface.
+ */
+#define DDOVER_ADDDIRTYRECT                     0x00008000l
+
+/*
+ * Redraw all dirty rects on an emulated overlayed surface.
+ */
+#define DDOVER_REFRESHDIRTYRECTS                0x00010000l
+
+/*
+ * Redraw the entire surface on an emulated overlayed surface.
+ */
+#define DDOVER_REFRESHALL                      0x00020000l
+
+
+/*
+ * Use the overlay FX flags to define special overlay FX
+ */
+#define DDOVER_DDFX                             0x00080000l
+
+
+/****************************************************************************
+ *
+ * DIRECTDRAWSURFACE LOCK FLAGS
+ *
+ ****************************************************************************/
+
+/*
+ * The default.  Set to indicate that Lock should return a valid memory pointer
+ * to the top of the specified rectangle.  If no rectangle is specified then a
+ * pointer to the top of the surface is returned.
+ */
+#define DDLOCK_SURFACEMEMORYPTR                 0x00000000L     // default
+
+/*
+ * Set to indicate that Lock should wait until it can obtain a valid memory
+ * pointer before returning.  If this bit is set, Lock will never return 
+ * DDERR_WASSTILLDRAWING.
+ */
+#define DDLOCK_WAIT                             0x00000001L
+
+/*
+ * Set if an event handle is being passed to Lock.  Lock will trigger the event
+ * when it can return the surface memory pointer requested.
+ */
+#define DDLOCK_EVENT                            0x00000002L
+
+/*
+ * Indicates that the surface being locked will only be read from.
+ */
+#define DDLOCK_READONLY                         0x00000010L
+
+/*
+ * Indicates that the surface being locked will only be written to
+ */
+#define DDLOCK_WRITEONLY                        0x00000020L
+
+
+/****************************************************************************
+ *
+ * DIRECTDRAWSURFACE PAGELOCK FLAGS
+ *
+ ****************************************************************************/
+
+/*
+ * No flags defined at present
+ */
+
+
+/****************************************************************************
+ *
+ * DIRECTDRAWSURFACE PAGEUNLOCK FLAGS
+ *
+ ****************************************************************************/
+
+/*
+ * No flags defined at present
+ */
+
+
+/****************************************************************************
+ *
+ * DIRECTDRAWSURFACE BLT FX FLAGS
+ *
+ ****************************************************************************/
+
+/*
+ * If stretching, use arithmetic stretching along the Y axis for this blt.
+ */
+#define DDBLTFX_ARITHSTRETCHY                   0x00000001l
+
+/*
+ * Do this blt mirroring the surface left to right.  Spin the
+ * surface around its y-axis.
+ */
+#define DDBLTFX_MIRRORLEFTRIGHT                 0x00000002l
+
+/*
+ * Do this blt mirroring the surface up and down.  Spin the surface
+ * around its x-axis.
+ */
+#define DDBLTFX_MIRRORUPDOWN                    0x00000004l
+
+/*
+ * Schedule this blt to avoid tearing.
+ */
+#define DDBLTFX_NOTEARING                       0x00000008l
+
+/*
+ * Do this blt rotating the surface one hundred and eighty degrees.
+ */
+#define DDBLTFX_ROTATE180                       0x00000010l
+
+/*
+ * Do this blt rotating the surface two hundred and seventy degrees.
+ */
+#define DDBLTFX_ROTATE270                       0x00000020l
+
+/*
+ * Do this blt rotating the surface ninety degrees.
+ */
+#define DDBLTFX_ROTATE90                        0x00000040l
+
+/*
+ * Do this z blt using dwZBufferLow and dwZBufferHigh as  range values
+ * specified to limit the bits copied from the source surface.
+ */
+#define DDBLTFX_ZBUFFERRANGE                    0x00000080l
+
+/*
+ * Do this z blt adding the dwZBufferBaseDest to each of the sources z values
+ * before comparing it with the desting z values.
+ */
+#define DDBLTFX_ZBUFFERBASEDEST                 0x00000100l
+
+/****************************************************************************
+ *
+ * DIRECTDRAWSURFACE OVERLAY FX FLAGS
+ *
+ ****************************************************************************/
+
+/*
+ * If stretching, use arithmetic stretching along the Y axis for this overlay.
+ */
+#define DDOVERFX_ARITHSTRETCHY                  0x00000001l
+
+/*
+ * Mirror the overlay across the vertical axis
+ */
+#define DDOVERFX_MIRRORLEFTRIGHT                0x00000002l
+
+/*
+ * Mirror the overlay across the horizontal axis
+ */
+#define DDOVERFX_MIRRORUPDOWN                   0x00000004l
+
+/****************************************************************************
+ *
+ * DIRECTDRAW WAITFORVERTICALBLANK FLAGS
+ *
+ ****************************************************************************/
+
+/*
+ * return when the vertical blank interval begins
+ */
+#define DDWAITVB_BLOCKBEGIN                     0x00000001l
+
+/*
+ * set up an event to trigger when the vertical blank begins
+ */
+#define DDWAITVB_BLOCKBEGINEVENT                0x00000002l
+
+/*
+ * return when the vertical blank interval ends and display begins
+ */
+#define DDWAITVB_BLOCKEND                       0x00000004l
+
+/****************************************************************************
+ *
+ * DIRECTDRAW GETFLIPSTATUS FLAGS
+ *
+ ****************************************************************************/
+
+/*
+ * is it OK to flip now?
+ */
+#define DDGFS_CANFLIP                   0x00000001l
+
+/*
+ * is the last flip finished?
+ */
+#define DDGFS_ISFLIPDONE                0x00000002l
+
+/****************************************************************************
+ *
+ * DIRECTDRAW GETBLTSTATUS FLAGS
+ *
+ ****************************************************************************/
+
+/*
+ * is it OK to blt now?
+ */
+#define DDGBS_CANBLT                    0x00000001l
+
+/*
+ * is the blt to the surface finished?
+ */
+#define DDGBS_ISBLTDONE                 0x00000002l
+
+
+/****************************************************************************
+ *
+ * DIRECTDRAW ENUMOVERLAYZORDER FLAGS
+ *
+ ****************************************************************************/
+
+/*
+ * Enumerate overlays back to front.
+ */
+#define DDENUMOVERLAYZ_BACKTOFRONT      0x00000000l
+
+/*
+ * Enumerate overlays front to back
+ */
+#define DDENUMOVERLAYZ_FRONTTOBACK      0x00000001l
+
+/****************************************************************************
+ *
+ * DIRECTDRAW UPDATEOVERLAYZORDER FLAGS
+ *
+ ****************************************************************************/
+
+/*
+ * Send overlay to front
+ */
+#define DDOVERZ_SENDTOFRONT             0x00000000l
+
+/*
+ * Send overlay to back
+ */
+#define DDOVERZ_SENDTOBACK              0x00000001l
+
+/*
+ * Move Overlay forward
+ */
+#define DDOVERZ_MOVEFORWARD             0x00000002l
+
+/*
+ * Move Overlay backward
+ */
+#define DDOVERZ_MOVEBACKWARD            0x00000003l
+
+/*
+ * Move Overlay in front of relative surface
+ */
+#define DDOVERZ_INSERTINFRONTOF         0x00000004l
+
+/*
+ * Move Overlay in back of relative surface
+ */
+#define DDOVERZ_INSERTINBACKOF          0x00000005l
+
+/*===========================================================================
+ *
+ *
+ * DIRECTDRAW RETURN CODES
+ *
+ * The return values from DirectDraw Commands and Surface that return an HRESULT
+ * are codes from DirectDraw concerning the results of the action
+ * requested by DirectDraw.
+ *
+ *==========================================================================*/
+
+/*
+ * Status is OK
+ *
+ * Issued by: DirectDraw Commands and all callbacks
+ */
+#define DD_OK                                   0
+
+/****************************************************************************
+ *
+ * DIRECTDRAW ENUMCALLBACK RETURN VALUES
+ *
+ * EnumCallback returns are used to control the flow of the DIRECTDRAW and
+ * DIRECTDRAWSURFACE object enumerations.   They can only be returned by
+ * enumeration callback routines.
+ *
+ ****************************************************************************/
+
+/*
+ * stop the enumeration
+ */
+#define DDENUMRET_CANCEL                        0
+
+/*
+ * continue the enumeration
+ */
+#define DDENUMRET_OK                            1
+
+/****************************************************************************
+ *
+ * DIRECTDRAW ERRORS
+ *
+ * Errors are represented by negative values and cannot be combined.
+ *
+ ****************************************************************************/
+
+/*
+ * This object is already initialized
+ */
+#define DDERR_ALREADYINITIALIZED                MAKE_DDHRESULT( 5 )
+
+/*
+ * This surface can not be attached to the requested surface.
+ */
+#define DDERR_CANNOTATTACHSURFACE               MAKE_DDHRESULT( 10 )
+
+/*
+ * This surface can not be detached from the requested surface.
+ */
+#define DDERR_CANNOTDETACHSURFACE               MAKE_DDHRESULT( 20 )
+
+/*
+ * Support is currently not available.
+ */
+#define DDERR_CURRENTLYNOTAVAIL                 MAKE_DDHRESULT( 40 )
+
+/*
+ * An exception was encountered while performing the requested operation
+ */
+#define DDERR_EXCEPTION                         MAKE_DDHRESULT( 55 )
+
+/*
+ * Generic failure.
+ */
+#define DDERR_GENERIC                           E_FAIL
+
+/*
+ * Height of rectangle provided is not a multiple of reqd alignment
+ */
+#define DDERR_HEIGHTALIGN                       MAKE_DDHRESULT( 90 )
+
+/*
+ * Unable to match primary surface creation request with existing 
+ * primary surface.
+ */
+#define DDERR_INCOMPATIBLEPRIMARY               MAKE_DDHRESULT( 95 )
+
+/*
+ * One or more of the caps bits passed to the callback are incorrect.
+ */
+#define DDERR_INVALIDCAPS                       MAKE_DDHRESULT( 100 )
+
+/*
+ * DirectDraw does not support provided Cliplist.
+ */
+#define DDERR_INVALIDCLIPLIST                   MAKE_DDHRESULT( 110 )
+
+/*
+ * DirectDraw does not support the requested mode
+ */
+#define DDERR_INVALIDMODE                       MAKE_DDHRESULT( 120 )
+
+/*
+ * DirectDraw received a pointer that was an invalid DIRECTDRAW object.
+ */
+#define DDERR_INVALIDOBJECT                     MAKE_DDHRESULT( 130 )
+
+/*
+ * One or more of the parameters passed to the callback function are
+ * incorrect.
+ */
+#define DDERR_INVALIDPARAMS                     E_INVALIDARG
+
+/*
+ * pixel format was invalid as specified
+ */
+#define DDERR_INVALIDPIXELFORMAT                MAKE_DDHRESULT( 145 )
+
+/*
+ * Rectangle provided was invalid.
+ */
+#define DDERR_INVALIDRECT                       MAKE_DDHRESULT( 150 )
+
+/*
+ * Operation could not be carried out because one or more surfaces are locked
+ */
+#define DDERR_LOCKEDSURFACES                    MAKE_DDHRESULT( 160 )
+
+/*
+ * There is no 3D present.
+ */
+#define DDERR_NO3D                              MAKE_DDHRESULT( 170 )
+
+/*
+ * Operation could not be carried out because there is no alpha accleration
+ * hardware present or available.
+ */
+#define DDERR_NOALPHAHW                         MAKE_DDHRESULT( 180 )
+
+
+/*
+ * no clip list available
+ */
+#define DDERR_NOCLIPLIST                        MAKE_DDHRESULT( 205 )
+
+/*
+ * Operation could not be carried out because there is no color conversion
+ * hardware present or available.
+ */
+#define DDERR_NOCOLORCONVHW                     MAKE_DDHRESULT( 210 )
+
+/*
+ * Create function called without DirectDraw object method SetCooperativeLevel
+ * being called.
+ */
+#define DDERR_NOCOOPERATIVELEVELSET             MAKE_DDHRESULT( 212 )
+
+/*
+ * Surface doesn't currently have a color key
+ */
+#define DDERR_NOCOLORKEY                        MAKE_DDHRESULT( 215 )
+
+/*
+ * Operation could not be carried out because there is no hardware support
+ * of the dest color key.
+ */
+#define DDERR_NOCOLORKEYHW                      MAKE_DDHRESULT( 220 )
+
+/*
+ * No DirectDraw support possible with current display driver
+ */
+#define DDERR_NODIRECTDRAWSUPPORT               MAKE_DDHRESULT( 222 )
+
+/*
+ * Operation requires the application to have exclusive mode but the
+ * application does not have exclusive mode.
+ */
+#define DDERR_NOEXCLUSIVEMODE                   MAKE_DDHRESULT( 225 )
+
+/*
+ * Flipping visible surfaces is not supported.
+ */
+#define DDERR_NOFLIPHW                          MAKE_DDHRESULT( 230 )
+
+/*
+ * There is no GDI present.
+ */
+#define DDERR_NOGDI                             MAKE_DDHRESULT( 240 )
+
+/*
+ * Operation could not be carried out because there is no hardware present
+ * or available.
+ */
+#define DDERR_NOMIRRORHW                        MAKE_DDHRESULT( 250 )
+
+/*
+ * Requested item was not found
+ */
+#define DDERR_NOTFOUND                          MAKE_DDHRESULT( 255 )
+
+/*
+ * Operation could not be carried out because there is no overlay hardware
+ * present or available.
+ */
+#define DDERR_NOOVERLAYHW                       MAKE_DDHRESULT( 260 )
+
+/*
+ * Operation could not be carried out because there is no appropriate raster
+ * op hardware present or available.
+ */
+#define DDERR_NORASTEROPHW                      MAKE_DDHRESULT( 280 )
+
+/*
+ * Operation could not be carried out because there is no rotation hardware
+ * present or available.
+ */
+#define DDERR_NOROTATIONHW                      MAKE_DDHRESULT( 290 )
+
+/*
+ * Operation could not be carried out because there is no hardware support
+ * for stretching
+ */
+#define DDERR_NOSTRETCHHW                       MAKE_DDHRESULT( 310 )
+
+/*
+ * DirectDrawSurface is not in 4 bit color palette and the requested operation
+ * requires 4 bit color palette.
+ */
+#define DDERR_NOT4BITCOLOR                      MAKE_DDHRESULT( 316 )
+
+/*
+ * DirectDrawSurface is not in 4 bit color index palette and the requested
+ * operation requires 4 bit color index palette.
+ */
+#define DDERR_NOT4BITCOLORINDEX                 MAKE_DDHRESULT( 317 )
+
+/*
+ * DirectDraw Surface is not in 8 bit color mode and the requested operation
+ * requires 8 bit color.
+ */
+#define DDERR_NOT8BITCOLOR                      MAKE_DDHRESULT( 320 )
+
+/*
+ * Operation could not be carried out because there is no texture mapping
+ * hardware present or available.
+ */
+#define DDERR_NOTEXTUREHW                       MAKE_DDHRESULT( 330 )
+
+/*
+ * Operation could not be carried out because there is no hardware support
+ * for vertical blank synchronized operations.
+ */
+#define DDERR_NOVSYNCHW                         MAKE_DDHRESULT( 335 )
+
+/*
+ * Operation could not be carried out because there is no hardware support
+ * for zbuffer blting.
+ */
+#define DDERR_NOZBUFFERHW                       MAKE_DDHRESULT( 340 )
+
+/*
+ * Overlay surfaces could not be z layered based on their BltOrder because
+ * the hardware does not support z layering of overlays.
+ */
+#define DDERR_NOZOVERLAYHW                      MAKE_DDHRESULT( 350 )
+
+/*
+ * The hardware needed for the requested operation has already been
+ * allocated.
+ */
+#define DDERR_OUTOFCAPS                         MAKE_DDHRESULT( 360 )
+
+/*
+ * DirectDraw does not have enough memory to perform the operation.
+ */
+#define DDERR_OUTOFMEMORY                       E_OUTOFMEMORY
+
+/*
+ * DirectDraw does not have enough memory to perform the operation.
+ */
+#define DDERR_OUTOFVIDEOMEMORY                  MAKE_DDHRESULT( 380 )
+
+/*
+ * hardware does not support clipped overlays
+ */
+#define DDERR_OVERLAYCANTCLIP                   MAKE_DDHRESULT( 382 )
+
+/*
+ * Can only have ony color key active at one time for overlays
+ */
+#define DDERR_OVERLAYCOLORKEYONLYONEACTIVE      MAKE_DDHRESULT( 384 )
+
+/*
+ * Access to this palette is being refused because the palette is already
+ * locked by another thread.
+ */
+#define DDERR_PALETTEBUSY                       MAKE_DDHRESULT( 387 )
+
+/*
+ * No src color key specified for this operation.
+ */
+#define DDERR_COLORKEYNOTSET                    MAKE_DDHRESULT( 400 )
+
+/*
+ * This surface is already attached to the surface it is being attached to.
+ */
+#define DDERR_SURFACEALREADYATTACHED            MAKE_DDHRESULT( 410 )
+
+/*
+ * This surface is already a dependency of the surface it is being made a
+ * dependency of.
+ */
+#define DDERR_SURFACEALREADYDEPENDENT           MAKE_DDHRESULT( 420 )
+
+/*
+ * Access to this surface is being refused because the surface is already
+ * locked by another thread.
+ */
+#define DDERR_SURFACEBUSY                       MAKE_DDHRESULT( 430 )
+
+/*
+ * Access to this surface is being refused because no driver exists
+ * which can supply a pointer to the surface.
+ * This is most likely to happen when attempting to lock the primary
+ * surface when no DCI provider is present.
+ */
+#define DDERR_CANTLOCKSURFACE                   MAKE_DDHRESULT( 435 )
+
+/*
+ * Access to Surface refused because Surface is obscured.
+ */
+#define DDERR_SURFACEISOBSCURED                 MAKE_DDHRESULT( 440 )
+
+/*
+ * Access to this surface is being refused because the surface is gone.
+ * The DIRECTDRAWSURFACE object representing this surface should 
+ * have Restore called on it.
+ */
+#define DDERR_SURFACELOST                       MAKE_DDHRESULT( 450 )
+
+/*
+ * The requested surface is not attached.
+ */
+#define DDERR_SURFACENOTATTACHED                MAKE_DDHRESULT( 460 )
+
+/*
+ * Height requested by DirectDraw is too large.
+ */
+#define DDERR_TOOBIGHEIGHT                      MAKE_DDHRESULT( 470 )
+
+/*
+ * Size requested by DirectDraw is too large --  The individual height and
+ * width are OK.
+ */
+#define DDERR_TOOBIGSIZE                        MAKE_DDHRESULT( 480 )
+
+/*
+ * Width requested by DirectDraw is too large.
+ */
+#define DDERR_TOOBIGWIDTH                       MAKE_DDHRESULT( 490 )
+
+/*
+ * Action not supported.
+ */
+#define DDERR_UNSUPPORTED                       E_NOTIMPL
+
+/*
+ * FOURCC format requested is unsupported by DirectDraw
+ */
+#define DDERR_UNSUPPORTEDFORMAT                 MAKE_DDHRESULT( 510 )
+
+/*
+ * Bitmask in the pixel format requested is unsupported by DirectDraw
+ */
+#define DDERR_UNSUPPORTEDMASK                   MAKE_DDHRESULT( 520 )
+
+/*
+ * vertical blank is in progress
+ */
+#define DDERR_VERTICALBLANKINPROGRESS           MAKE_DDHRESULT( 537 )
+
+/*
+ * Informs DirectDraw that the previous Blt which is transfering information
+ * to or from this Surface is incomplete.
+ */
+#define DDERR_WASSTILLDRAWING                   MAKE_DDHRESULT( 540 )
+
+/*
+ * Rectangle provided was not horizontally aligned on reqd. boundary
+ */
+#define DDERR_XALIGN                            MAKE_DDHRESULT( 560 )
+
+/*
+ * The GUID passed to DirectDrawCreate is not a valid DirectDraw driver
+ * identifier.
+ */
+#define DDERR_INVALIDDIRECTDRAWGUID             MAKE_DDHRESULT( 561 )
+
+/*
+ * A DirectDraw object representing this driver has already been created
+ * for this process.
+ */
+#define DDERR_DIRECTDRAWALREADYCREATED          MAKE_DDHRESULT( 562 )
+
+/*
+ * A hardware only DirectDraw object creation was attempted but the driver
+ * did not support any hardware.
+ */
+#define DDERR_NODIRECTDRAWHW                    MAKE_DDHRESULT( 563 )
+
+/*
+ * this process already has created a primary surface
+ */
+#define DDERR_PRIMARYSURFACEALREADYEXISTS       MAKE_DDHRESULT( 564 )
+
+/*
+ * software emulation not available.
+ */
+#define DDERR_NOEMULATION                       MAKE_DDHRESULT( 565 )
+
+/*
+ * region passed to Clipper::GetClipList is too small.
+ */
+#define DDERR_REGIONTOOSMALL                    MAKE_DDHRESULT( 566 )
+
+/*
+ * an attempt was made to set a clip list for a clipper objec that
+ * is already monitoring an hwnd.
+ */
+#define DDERR_CLIPPERISUSINGHWND                MAKE_DDHRESULT( 567 )
+
+/*
+ * No clipper object attached to surface object
+ */
+#define DDERR_NOCLIPPERATTACHED                 MAKE_DDHRESULT( 568 )
+
+/*
+ * Clipper notification requires an HWND or
+ * no HWND has previously been set as the CooperativeLevel HWND.
+ */
+#define DDERR_NOHWND                            MAKE_DDHRESULT( 569 )
+
+/*
+ * HWND used by DirectDraw CooperativeLevel has been subclassed,
+ * this prevents DirectDraw from restoring state.
+ */
+#define DDERR_HWNDSUBCLASSED                    MAKE_DDHRESULT( 570 )
+
+/*
+ * The CooperativeLevel HWND has already been set.
+ * It can not be reset while the process has surfaces or palettes created.
+ */
+#define DDERR_HWNDALREADYSET                    MAKE_DDHRESULT( 571 )
+
+/*
+ * No palette object attached to this surface.
+ */
+#define DDERR_NOPALETTEATTACHED                 MAKE_DDHRESULT( 572 )
+
+/*
+ * No hardware support for 16 or 256 color palettes.
+ */
+#define DDERR_NOPALETTEHW                       MAKE_DDHRESULT( 573 )
+
+/*
+ * If a clipper object is attached to the source surface passed into a
+ * BltFast call.
+ */
+#define DDERR_BLTFASTCANTCLIP                   MAKE_DDHRESULT( 574 )
+
+/*
+ * No blter.
+ */
+#define DDERR_NOBLTHW                           MAKE_DDHRESULT( 575 )
+
+/*
+ * No DirectDraw ROP hardware.
+ */
+#define DDERR_NODDROPSHW                        MAKE_DDHRESULT( 576 )
+
+/*
+ * returned when GetOverlayPosition is called on a hidden overlay
+ */
+#define DDERR_OVERLAYNOTVISIBLE                 MAKE_DDHRESULT( 577 )
+
+/*
+ * returned when GetOverlayPosition is called on a overlay that UpdateOverlay
+ * has never been called on to establish a destionation.
+ */
+#define DDERR_NOOVERLAYDEST                     MAKE_DDHRESULT( 578 )
+
+/*
+ * returned when the position of the overlay on the destionation is no longer
+ * legal for that destionation.
+ */
+#define DDERR_INVALIDPOSITION                   MAKE_DDHRESULT( 579 )
+
+/*
+ * returned when an overlay member is called for a non-overlay surface
+ */
+#define DDERR_NOTAOVERLAYSURFACE                MAKE_DDHRESULT( 580 )
+ 
+/*
+ * An attempt was made to set the cooperative level when it was already
+ * set to exclusive.
+ */
+#define DDERR_EXCLUSIVEMODEALREADYSET           MAKE_DDHRESULT( 581 )
+
+/*
+ * An attempt has been made to flip a surface that is not flippable.
+ */
+#define DDERR_NOTFLIPPABLE                      MAKE_DDHRESULT( 582 )
+
+/*
+ * Can't duplicate primary & 3D surfaces, or surfaces that are implicitly
+ * created.
+ */
+#define DDERR_CANTDUPLICATE                     MAKE_DDHRESULT( 583 )
+
+/*
+ * Surface was not locked.  An attempt to unlock a surface that was not
+ * locked at all, or by this process, has been attempted.
+ */
+#define DDERR_NOTLOCKED                         MAKE_DDHRESULT( 584 )
+
+/*
+ * Windows can not create any more DCs
+ */
+#define DDERR_CANTCREATEDC                      MAKE_DDHRESULT( 585 )
+
+/*
+ * No DC was ever created for this surface.
+ */
+#define DDERR_NODC                              MAKE_DDHRESULT( 586 )
+
+/*
+ * This surface can not be restored because it was created in a different
+ * mode.
+ */
+#define DDERR_WRONGMODE                         MAKE_DDHRESULT( 587 )
+
+/*
+ * This surface can not be restored because it is an implicitly created
+ * surface.
+ */
+#define DDERR_IMPLICITLYCREATED                 MAKE_DDHRESULT( 588 )
+
+/*
+ * The surface being used is not a palette-based surface
+ */
+#define DDERR_NOTPALETTIZED                     MAKE_DDHRESULT( 589 )
+
+
+/*
+ * The display is currently in an unsupported mode
+ */
+#define DDERR_UNSUPPORTEDMODE                   MAKE_DDHRESULT( 590 )
+
+/*
+ * Operation could not be carried out because there is no mip-map
+ * texture mapping hardware present or available.
+ */
+#define DDERR_NOMIPMAPHW                        MAKE_DDHRESULT( 591 )
+
+/*
+ * The requested action could not be performed because the surface was of
+ * the wrong type.
+ */
+#define DDERR_INVALIDSURFACETYPE                MAKE_DDHRESULT( 592 )
+
+
+
+/*
+ * A DC has already been returned for this surface. Only one DC can be 
+ * retrieved per surface.
+ */
+#define DDERR_DCALREADYCREATED                  MAKE_DDHRESULT( 620 )
+
+/*
+ * The attempt to page lock a surface failed.
+ */
+#define DDERR_CANTPAGELOCK                      MAKE_DDHRESULT( 640 )
+
+/*
+ * The attempt to page unlock a surface failed.
+ */
+#define DDERR_CANTPAGEUNLOCK                    MAKE_DDHRESULT( 660 )
+
+/*
+ * An attempt was made to page unlock a surface with no outstanding page locks.
+ */
+#define DDERR_NOTPAGELOCKED                     MAKE_DDHRESULT( 680 )
+
+/*
+ * An attempt was made to invoke an interface member of a DirectDraw object
+ * created by CoCreateInstance() before it was initialized.
+ */
+#define DDERR_NOTINITIALIZED                    CO_E_NOTINITIALIZED
+
+/* Alpha bit depth constants */
+
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif
--- /dev/null
+++ b/QW/dxsdk/sdk/inc/dinput.h
@@ -1,0 +1,873 @@
+/****************************************************************************
+ *
+ *  Copyright (C) 1996 Microsoft Corporation.  All Rights Reserved.
+ *
+ *  File:       dinput.h
+ *  Content:    DirectInput include file
+ *
+ ****************************************************************************/
+
+#ifndef __DINPUT_INCLUDED__
+#define __DINPUT_INCLUDED__
+
+#ifdef _WIN32
+#define COM_NO_WINDOWS_H
+#include <objbase.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define DIRECTINPUT_VERSION         0x0300
+
+/****************************************************************************
+ *
+ *      Class IDs
+ *
+ ****************************************************************************/
+
+DEFINE_GUID(CLSID_DirectInput,      0x25E609E0,0xB259,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00);
+DEFINE_GUID(CLSID_DirectInputDevice,0x25E609E1,0xB259,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00);
+
+/****************************************************************************
+ *
+ *      Interfaces
+ *
+ ****************************************************************************/
+
+DEFINE_GUID(IID_IDirectInputA,     0x89521360,0xAA8A,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00);
+DEFINE_GUID(IID_IDirectInputW,     0x89521361,0xAA8A,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00);
+
+DEFINE_GUID(IID_IDirectInputDeviceA,0x5944E680,0xC92E,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00);
+DEFINE_GUID(IID_IDirectInputDeviceW,0x5944E681,0xC92E,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00);
+
+/****************************************************************************
+ *
+ *      Predefined object types
+ *
+ ****************************************************************************/
+
+DEFINE_GUID(GUID_XAxis,   0xA36D02E0,0xC9F3,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00);
+DEFINE_GUID(GUID_YAxis,   0xA36D02E1,0xC9F3,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00);
+DEFINE_GUID(GUID_ZAxis,   0xA36D02E2,0xC9F3,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00);
+DEFINE_GUID(GUID_RAxis,   0xA36D02E3,0xC9F3,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00);
+DEFINE_GUID(GUID_UAxis,   0xA36D02E4,0xC9F3,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00);
+DEFINE_GUID(GUID_VAxis,   0xA36D02E5,0xC9F3,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00);
+
+DEFINE_GUID(GUID_Button,  0xA36D02F0,0xC9F3,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00);
+DEFINE_GUID(GUID_Key,     0x55728220,0xD33C,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00);
+
+DEFINE_GUID(GUID_POV,     0xA36D02F2,0xC9F3,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00);
+
+/****************************************************************************
+ *
+ *      Predefined product GUIDs
+ *
+ ****************************************************************************/
+
+DEFINE_GUID(GUID_SysMouse,   0x6F1D2B60,0xD5A0,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00);
+DEFINE_GUID(GUID_SysKeyboard,0x6F1D2B61,0xD5A0,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00);
+
+/****************************************************************************
+ *
+ *      Interfaces and Structures...
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ *
+ *      IDirectInputDevice
+ *
+ ****************************************************************************/
+
+#define DIDEVTYPE_DEVICE    1
+#define DIDEVTYPE_MOUSE     2
+#define DIDEVTYPE_KEYBOARD  3
+#define DIDEVTYPE_JOYSTICK  4
+
+#define DIDEVTYPEMOUSE_UNKNOWN          1
+#define DIDEVTYPEMOUSE_TRADITIONAL      2
+#define DIDEVTYPEMOUSE_FINGERSTICK      3
+#define DIDEVTYPEMOUSE_TOUCHPAD         4
+#define DIDEVTYPEMOUSE_TRACKBALL        5
+
+#define DIDEVTYPEKEYBOARD_PCXT          1
+#define DIDEVTYPEKEYBOARD_OLIVETTI      2
+#define DIDEVTYPEKEYBOARD_PCAT          3
+#define DIDEVTYPEKEYBOARD_PCENH         4
+#define DIDEVTYPEKEYBOARD_NOKIA1050     5
+#define DIDEVTYPEKEYBOARD_NOKIA9140     6
+#define DIDEVTYPEKEYBOARD_NEC98         7
+#define DIDEVTYPEKEYBOARD_NEC98LAPTOP   8
+#define DIDEVTYPEKEYBOARD_NEC98106      9
+#define DIDEVTYPEKEYBOARD_JAPAN106     10
+#define DIDEVTYPEKEYBOARD_JAPANAX      11
+#define DIDEVTYPEKEYBOARD_J3100        12
+
+#define GET_DIDEVICE_TYPE(dwDevType)    LOBYTE(dwDevType)
+#define GET_DIDEVICE_SUBTYPE(dwDevType) HIBYTE(dwDevType)
+
+typedef struct _DIDEVCAPS {
+    DWORD   dwSize;
+    DWORD   dwFlags;
+    DWORD   dwDevType;
+    DWORD   dwAxes;
+    DWORD   dwButtons;
+    DWORD   dwPOVs;
+} DIDEVCAPS, *LPDIDEVCAPS;
+
+#define DIDC_ATTACHED           0x00000001
+#define DIDC_POLLEDDEVICE       0x00000002
+
+#define DIDFT_ALL           0x00000000
+
+#define DIDFT_RELAXIS       0x00000001
+#define DIDFT_ABSAXIS       0x00000002
+#define DIDFT_AXIS          0x00000003
+
+#define DIDFT_PSHBUTTON     0x00000004
+#define DIDFT_TGLBUTTON     0x00000008
+#define DIDFT_BUTTON        0x0000000C
+
+#define DIDFT_POV           0x00000010
+
+#define DIDFT_ANYINSTANCE   0x0000FF00
+#define DIDFT_MAKEINSTANCE(n) ((BYTE)(n) << 8)
+#define DIDFT_GETTYPE(n)     LOBYTE(n)
+#define DIDFT_GETINSTANCE(n) HIBYTE(n)
+
+typedef struct _DIOBJECTDATAFORMAT {
+    const GUID *pguid;
+    DWORD   dwOfs;
+    DWORD   dwType;
+    DWORD   dwFlags;
+} DIOBJECTDATAFORMAT, *LPDIOBJECTDATAFORMAT;
+typedef const DIOBJECTDATAFORMAT *LPCDIOBJECTDATAFORMAT;
+
+typedef struct _DIDATAFORMAT {
+    DWORD   dwSize;
+    DWORD   dwObjSize;
+    DWORD   dwFlags;
+    DWORD   dwDataSize;
+    DWORD   dwNumObjs;
+    LPDIOBJECTDATAFORMAT rgodf;
+} DIDATAFORMAT, *LPDIDATAFORMAT;
+typedef const DIDATAFORMAT *LPCDIDATAFORMAT;
+
+#define DIDF_ABSAXIS            0x00000001
+#define DIDF_RELAXIS            0x00000002
+
+extern const DIDATAFORMAT c_dfDIMouse;
+extern const DIDATAFORMAT c_dfDIKeyboard;
+
+typedef struct DIDEVICEOBJECTINSTANCEA {
+    DWORD   dwSize;
+    GUID    guidType;
+    DWORD   dwOfs;
+    DWORD   dwType;
+    DWORD   dwFlags;
+    CHAR    tszName[MAX_PATH];
+} DIDEVICEOBJECTINSTANCEA, *LPDIDEVICEOBJECTINSTANCEA;
+typedef struct DIDEVICEOBJECTINSTANCEW {
+    DWORD   dwSize;
+    GUID    guidType;
+    DWORD   dwOfs;
+    DWORD   dwType;
+    DWORD   dwFlags;
+    WCHAR   tszName[MAX_PATH];
+} DIDEVICEOBJECTINSTANCEW, *LPDIDEVICEOBJECTINSTANCEW;
+#ifdef UNICODE
+typedef DIDEVICEOBJECTINSTANCEW DIDEVICEOBJECTINSTANCE;
+typedef LPDIDEVICEOBJECTINSTANCEW LPDIDEVICEOBJECTINSTANCE;
+#else
+typedef DIDEVICEOBJECTINSTANCEA DIDEVICEOBJECTINSTANCE;
+typedef LPDIDEVICEOBJECTINSTANCEA LPDIDEVICEOBJECTINSTANCE;
+#endif // UNICODE
+typedef const DIDEVICEOBJECTINSTANCEA *LPCDIDEVICEOBJECTINSTANCEA;
+typedef const DIDEVICEOBJECTINSTANCEW *LPCDIDEVICEOBJECTINSTANCEW;
+typedef const DIDEVICEOBJECTINSTANCE  *LPCDIDEVICEOBJECTINSTANCE;
+
+typedef BOOL (FAR PASCAL * LPDIENUMDEVICEOBJECTSCALLBACKA)(LPCDIDEVICEOBJECTINSTANCEA, LPVOID);
+typedef BOOL (FAR PASCAL * LPDIENUMDEVICEOBJECTSCALLBACKW)(LPCDIDEVICEOBJECTINSTANCEW, LPVOID);
+#ifdef UNICODE
+#define LPDIENUMDEVICEOBJECTSCALLBACK  LPDIENUMDEVICEOBJECTSCALLBACKW
+#else
+#define LPDIENUMDEVICEOBJECTSCALLBACK  LPDIENUMDEVICEOBJECTSCALLBACKA
+#endif // !UNICODE
+
+typedef struct DIPROPHEADER {
+    DWORD   dwSize;
+    DWORD   dwHeaderSize;
+    DWORD   dwObj;
+    DWORD   dwHow;
+} DIPROPHEADER, *LPDIPROPHEADER;
+typedef const DIPROPHEADER *LPCDIPROPHEADER;
+
+#define DIPH_DEVICE             0
+#define DIPH_BYOFFSET           1
+#define DIPH_BYID               2
+
+typedef struct DIPROPDWORD {
+    DIPROPHEADER diph;
+    DWORD   dwData;
+} DIPROPDWORD, *LPDIPROPDWORD;
+typedef const DIPROPDWORD *LPCDIPROPDWORD;
+
+typedef struct DIPROPRANGE {
+    DIPROPHEADER diph;
+    LONG    lMin;
+    LONG    lMax;
+} DIPROPRANGE, *LPDIPROPRANGE;
+typedef const DIPROPRANGE *LPCDIPROPRANGE;
+
+#define DIPROPRANGE_NOMIN       ((LONG)0x80000000)
+#define DIPROPRANGE_NOMAX       ((LONG)0x7FFFFFFF)
+
+#ifdef __cplusplus
+#define MAKEDIPROP(prop)    (*(const GUID *)(prop))
+#else
+#define MAKEDIPROP(prop)    ((REFGUID)(prop))
+#endif
+
+#define DIPROP_BUFFERSIZE       MAKEDIPROP(1)
+
+#define DIPROP_AXISMODE         MAKEDIPROP(2)
+
+#define DIPROPAXISMODE_ABS      0
+#define DIPROPAXISMODE_REL      1
+
+#define DIPROP_GRANULARITY      MAKEDIPROP(3)
+
+#define DIPROP_RANGE            MAKEDIPROP(4)
+
+typedef struct DIDEVICEOBJECTDATA {
+    DWORD   dwOfs;
+    DWORD   dwData;
+    DWORD   dwTimeStamp;
+    DWORD   dwSequence;
+} DIDEVICEOBJECTDATA, *LPDIDEVICEOBJECTDATA;
+
+#define DIGDD_PEEK          0x00000001
+
+#define DISEQUENCE_COMPARE(dwSequence1, cmp, dwSequence2) \
+                        ((int)((dwSequence1) - (dwSequence2)) cmp 0)
+
+#define DISCL_EXCLUSIVE     0x00000001
+#define DISCL_NONEXCLUSIVE  0x00000002
+#define DISCL_FOREGROUND    0x00000004
+#define DISCL_BACKGROUND    0x00000008
+
+typedef struct DIDEVICEINSTANCEA {
+    DWORD   dwSize;
+    GUID    guidInstance;
+    GUID    guidProduct;
+    DWORD   dwDevType;
+    CHAR    tszInstanceName[MAX_PATH];
+    CHAR    tszProductName[MAX_PATH];
+} DIDEVICEINSTANCEA, *LPDIDEVICEINSTANCEA;
+typedef struct DIDEVICEINSTANCEW {
+    DWORD   dwSize;
+    GUID    guidInstance;
+    GUID    guidProduct;
+    DWORD   dwDevType;
+    WCHAR   tszInstanceName[MAX_PATH];
+    WCHAR   tszProductName[MAX_PATH];
+} DIDEVICEINSTANCEW, *LPDIDEVICEINSTANCEW;
+#ifdef UNICODE
+typedef DIDEVICEINSTANCEW DIDEVICEINSTANCE;
+typedef LPDIDEVICEINSTANCEW LPDIDEVICEINSTANCE;
+#else
+typedef DIDEVICEINSTANCEA DIDEVICEINSTANCE;
+typedef LPDIDEVICEINSTANCEA LPDIDEVICEINSTANCE;
+#endif // UNICODE
+typedef const DIDEVICEINSTANCEA *LPCDIDEVICEINSTANCEA;
+typedef const DIDEVICEINSTANCEW *LPCDIDEVICEINSTANCEW;
+typedef const DIDEVICEINSTANCE  *LPCDIDEVICEINSTANCE;
+
+#undef INTERFACE
+#define INTERFACE IDirectInputDeviceW
+
+DECLARE_INTERFACE_(IDirectInputDeviceW, IUnknown)
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;
+
+    /*** IDirectInputDeviceW methods ***/
+    STDMETHOD(GetCapabilities)(THIS_ LPDIDEVCAPS) PURE;
+    STDMETHOD(EnumObjects)(THIS_ LPDIENUMDEVICEOBJECTSCALLBACKW,LPVOID,DWORD) PURE;
+    STDMETHOD(GetProperty)(THIS_ REFGUID,LPDIPROPHEADER) PURE;
+    STDMETHOD(SetProperty)(THIS_ REFGUID,LPCDIPROPHEADER) PURE;
+    STDMETHOD(Acquire)(THIS) PURE;
+    STDMETHOD(Unacquire)(THIS) PURE;
+    STDMETHOD(GetDeviceState)(THIS_ DWORD,LPVOID) PURE;
+    STDMETHOD(GetDeviceData)(THIS_ DWORD,LPDIDEVICEOBJECTDATA,LPDWORD,DWORD) PURE;
+    STDMETHOD(SetDataFormat)(THIS_ LPCDIDATAFORMAT) PURE;
+    STDMETHOD(SetEventNotification)(THIS_ HANDLE) PURE;
+    STDMETHOD(SetCooperativeLevel)(THIS_ HWND,DWORD) PURE;
+    STDMETHOD(GetObjectInfo)(THIS_ LPDIDEVICEOBJECTINSTANCEW,DWORD,DWORD) PURE;
+    STDMETHOD(GetDeviceInfo)(THIS_ LPDIDEVICEINSTANCEW) PURE;
+    STDMETHOD(RunControlPanel)(THIS_ HWND,DWORD) PURE;
+    STDMETHOD(Initialize)(THIS_ HINSTANCE,DWORD,REFGUID) PURE;
+};
+
+typedef struct IDirectInputDeviceW *LPDIRECTINPUTDEVICEW;
+
+#undef INTERFACE
+#define INTERFACE IDirectInputDeviceA
+
+DECLARE_INTERFACE_(IDirectInputDeviceA, IUnknown)
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;
+
+    /*** IDirectInputDeviceA methods ***/
+    STDMETHOD(GetCapabilities)(THIS_ LPDIDEVCAPS) PURE;
+    STDMETHOD(EnumObjects)(THIS_ LPDIENUMDEVICEOBJECTSCALLBACKA,LPVOID,DWORD) PURE;
+    STDMETHOD(GetProperty)(THIS_ REFGUID,LPDIPROPHEADER) PURE;
+    STDMETHOD(SetProperty)(THIS_ REFGUID,LPCDIPROPHEADER) PURE;
+    STDMETHOD(Acquire)(THIS) PURE;
+    STDMETHOD(Unacquire)(THIS) PURE;
+    STDMETHOD(GetDeviceState)(THIS_ DWORD,LPVOID) PURE;
+    STDMETHOD(GetDeviceData)(THIS_ DWORD,LPDIDEVICEOBJECTDATA,LPDWORD,DWORD) PURE;
+    STDMETHOD(SetDataFormat)(THIS_ LPCDIDATAFORMAT) PURE;
+    STDMETHOD(SetEventNotification)(THIS_ HANDLE) PURE;
+    STDMETHOD(SetCooperativeLevel)(THIS_ HWND,DWORD) PURE;
+    STDMETHOD(GetObjectInfo)(THIS_ LPDIDEVICEOBJECTINSTANCEA,DWORD,DWORD) PURE;
+    STDMETHOD(GetDeviceInfo)(THIS_ LPDIDEVICEINSTANCEA) PURE;
+    STDMETHOD(RunControlPanel)(THIS_ HWND,DWORD) PURE;
+    STDMETHOD(Initialize)(THIS_ HINSTANCE,DWORD,REFGUID) PURE;
+};
+
+typedef struct IDirectInputDeviceA *LPDIRECTINPUTDEVICEA;
+
+#ifdef UNICODE
+#define IID_IDirectInputDevice IID_IDirectInputDeviceW
+#define IDirectInputDevice IDirectInputDeviceW
+#define IDirectInputDeviceVtbl IDirectInputDeviceWVtbl
+#else
+#define IID_IDirectInputDevice IID_IDirectInputDeviceA
+#define IDirectInputDevice IDirectInputDeviceA
+#define IDirectInputDeviceVtbl IDirectInputDeviceAVtbl
+#endif
+typedef struct IDirectInputDevice *LPDIRECTINPUTDEVICE;
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirectInputDevice_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b)
+#define IDirectInputDevice_AddRef(p) (p)->lpVtbl->AddRef(p)
+#define IDirectInputDevice_Release(p) (p)->lpVtbl->Release(p)
+#define IDirectInputDevice_GetCapabilities(p,a) (p)->lpVtbl->GetCapabilities(p,a)
+#define IDirectInputDevice_EnumObjects(p,a,b,c) (p)->lpVtbl->EnumObjects(p,a,b,c)
+#define IDirectInputDevice_GetProperty(p,a,b) (p)->lpVtbl->GetProperty(p,a,b)
+#define IDirectInputDevice_SetProperty(p,a,b) (p)->lpVtbl->SetProperty(p,a,b)
+#define IDirectInputDevice_Acquire(p) (p)->lpVtbl->Acquire(p)
+#define IDirectInputDevice_Unacquire(p) (p)->lpVtbl->Unacquire(p)
+#define IDirectInputDevice_GetDeviceState(p,a,b) (p)->lpVtbl->GetDeviceState(p,a,b)
+#define IDirectInputDevice_GetDeviceData(p,a,b,c,d) (p)->lpVtbl->GetDeviceData(p,a,b,c,d)
+#define IDirectInputDevice_SetDataFormat(p,a) (p)->lpVtbl->SetDataFormat(p,a)
+#define IDirectInputDevice_SetEventNotification(p,a) (p)->lpVtbl->SetEventNotification(p,a)
+#define IDirectInputDevice_SetCooperativeLevel(p,a,b) (p)->lpVtbl->SetCooperativeLevel(p,a,b)
+#define IDirectInputDevice_GetObjectInfo(p,a,b,c) (p)->lpVtbl->GetObjectInfo(p,a,b,c)
+#define IDirectInputDevice_GetDeviceInfo(p,a) (p)->lpVtbl->GetDeviceInfo(p,a)
+#define IDirectInputDevice_RunControlPanel(p,a,b) (p)->lpVtbl->RunControlPanel(p,a,b)
+#define IDirectInputDevice_Initialize(p,a,b,c) (p)->lpVtbl->Initialize(p,a,b,c)
+#endif
+
+/****************************************************************************
+ *
+ *      Mouse
+ *
+ ****************************************************************************/
+
+typedef struct _DIMOUSESTATE {
+    LONG    lX;
+    LONG    lY;
+    LONG    lZ;
+    BYTE    rgbButtons[4];
+} DIMOUSESTATE, *LPDIMOUSESTATE;
+
+#define DIMOFS_X        FIELD_OFFSET(DIMOUSESTATE, lX)
+#define DIMOFS_Y        FIELD_OFFSET(DIMOUSESTATE, lY)
+#define DIMOFS_Z        FIELD_OFFSET(DIMOUSESTATE, lZ)
+#define DIMOFS_BUTTON0 (FIELD_OFFSET(DIMOUSESTATE, rgbButtons) + 0)
+#define DIMOFS_BUTTON1 (FIELD_OFFSET(DIMOUSESTATE, rgbButtons) + 1)
+#define DIMOFS_BUTTON2 (FIELD_OFFSET(DIMOUSESTATE, rgbButtons) + 2)
+#define DIMOFS_BUTTON3 (FIELD_OFFSET(DIMOUSESTATE, rgbButtons) + 3)
+
+/****************************************************************************
+ *
+ *      Keyboard
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ *
+ *      DirectInput keyboard scan codes
+ *
+ ****************************************************************************/
+
+#define DIK_ESCAPE          0x01
+#define DIK_1               0x02
+#define DIK_2               0x03
+#define DIK_3               0x04
+#define DIK_4               0x05
+#define DIK_5               0x06
+#define DIK_6               0x07
+#define DIK_7               0x08
+#define DIK_8               0x09
+#define DIK_9               0x0A
+#define DIK_0               0x0B
+#define DIK_MINUS           0x0C    /* - on main keyboard */
+#define DIK_EQUALS          0x0D
+#define DIK_BACK            0x0E    /* backspace */
+#define DIK_TAB             0x0F
+#define DIK_Q               0x10
+#define DIK_W               0x11
+#define DIK_E               0x12
+#define DIK_R               0x13
+#define DIK_T               0x14
+#define DIK_Y               0x15
+#define DIK_U               0x16
+#define DIK_I               0x17
+#define DIK_O               0x18
+#define DIK_P               0x19
+#define DIK_LBRACKET        0x1A
+#define DIK_RBRACKET        0x1B
+#define DIK_RETURN          0x1C    /* Enter on main keyboard */
+#define DIK_LCONTROL        0x1D
+#define DIK_A               0x1E
+#define DIK_S               0x1F
+#define DIK_D               0x20
+#define DIK_F               0x21
+#define DIK_G               0x22
+#define DIK_H               0x23
+#define DIK_J               0x24
+#define DIK_K               0x25
+#define DIK_L               0x26
+#define DIK_SEMICOLON       0x27
+#define DIK_APOSTROPHE      0x28
+#define DIK_GRAVE           0x29    /* accent grave */
+#define DIK_LSHIFT          0x2A
+#define DIK_BACKSLASH       0x2B
+#define DIK_Z               0x2C
+#define DIK_X               0x2D
+#define DIK_C               0x2E
+#define DIK_V               0x2F
+#define DIK_B               0x30
+#define DIK_N               0x31
+#define DIK_M               0x32
+#define DIK_COMMA           0x33
+#define DIK_PERIOD          0x34    /* . on main keyboard */
+#define DIK_SLASH           0x35    /* / on main keyboard */
+#define DIK_RSHIFT          0x36
+#define DIK_MULTIPLY        0x37    /* * on numeric keypad */
+#define DIK_LMENU           0x38    /* left Alt */
+#define DIK_SPACE           0x39
+#define DIK_CAPITAL         0x3A
+#define DIK_F1              0x3B
+#define DIK_F2              0x3C
+#define DIK_F3              0x3D
+#define DIK_F4              0x3E
+#define DIK_F5              0x3F
+#define DIK_F6              0x40
+#define DIK_F7              0x41
+#define DIK_F8              0x42
+#define DIK_F9              0x43
+#define DIK_F10             0x44
+#define DIK_NUMLOCK         0x45
+#define DIK_SCROLL          0x46    /* Scroll Lock */
+#define DIK_NUMPAD7         0x47
+#define DIK_NUMPAD8         0x48
+#define DIK_NUMPAD9         0x49
+#define DIK_SUBTRACT        0x4A    /* - on numeric keypad */
+#define DIK_NUMPAD4         0x4B
+#define DIK_NUMPAD5         0x4C
+#define DIK_NUMPAD6         0x4D
+#define DIK_ADD             0x4E    /* + on numeric keypad */
+#define DIK_NUMPAD1         0x4F
+#define DIK_NUMPAD2         0x50
+#define DIK_NUMPAD3         0x51
+#define DIK_NUMPAD0         0x52
+#define DIK_DECIMAL         0x53    /* . on numeric keypad */
+#define DIK_F11             0x57
+#define DIK_F12             0x58
+
+#define DIK_F13             0x64    /*                     (NEC PC98) */
+#define DIK_F14             0x65    /*                     (NEC PC98) */
+#define DIK_F15             0x66    /*                     (NEC PC98) */
+
+#define DIK_KANA            0x70    /* (Japanese keyboard)            */
+#define DIK_CONVERT         0x79    /* (Japanese keyboard)            */
+#define DIK_NOCONVERT       0x7B    /* (Japanese keyboard)            */
+#define DIK_YEN             0x7D    /* (Japanese keyboard)            */
+#define DIK_NUMPADEQUALS    0x8D    /* = on numeric keypad (NEC PC98) */
+#define DIK_CIRCUMFLEX      0x90    /* (Japanese keyboard)            */
+#define DIK_AT              0x91    /*                     (NEC PC98) */
+#define DIK_COLON           0x92    /*                     (NEC PC98) */
+#define DIK_UNDERLINE       0x93    /*                     (NEC PC98) */
+#define DIK_KANJI           0x94    /* (Japanese keyboard)            */
+#define DIK_STOP            0x95    /*                     (NEC PC98) */
+#define DIK_AX              0x96    /*                     (Japan AX) */
+#define DIK_UNLABELED       0x97    /*                        (J3100) */
+#define DIK_NUMPADENTER     0x9C    /* Enter on numeric keypad */
+#define DIK_RCONTROL        0x9D
+#define DIK_NUMPADCOMMA     0xB3    /* , on numeric keypad (NEC PC98) */
+#define DIK_DIVIDE          0xB5    /* / on numeric keypad */
+#define DIK_SYSRQ           0xB7
+#define DIK_RMENU           0xB8    /* right Alt */
+#define DIK_HOME            0xC7    /* Home on arrow keypad */
+#define DIK_UP              0xC8    /* UpArrow on arrow keypad */
+#define DIK_PRIOR           0xC9    /* PgUp on arrow keypad */
+#define DIK_LEFT            0xCB    /* LeftArrow on arrow keypad */
+#define DIK_RIGHT           0xCD    /* RightArrow on arrow keypad */
+#define DIK_END             0xCF    /* End on arrow keypad */
+#define DIK_DOWN            0xD0    /* DownArrow on arrow keypad */
+#define DIK_NEXT            0xD1    /* PgDn on arrow keypad */
+#define DIK_INSERT          0xD2    /* Insert on arrow keypad */
+#define DIK_DELETE          0xD3    /* Delete on arrow keypad */
+#define DIK_LWIN            0xDB    /* Left Windows key */
+#define DIK_RWIN            0xDC    /* Right Windows key */
+#define DIK_APPS            0xDD    /* AppMenu key */
+
+/*
+ *  Alternate names for keys, to facilitate transition from DOS.
+ */
+#define DIK_BACKSPACE       DIK_BACK            /* backspace */
+#define DIK_NUMPADSTAR      DIK_MULTIPLY        /* * on numeric keypad */
+#define DIK_LALT            DIK_LMENU           /* left Alt */
+#define DIK_CAPSLOCK        DIK_CAPITAL         /* CapsLock */
+#define DIK_NUMPADMINUS     DIK_SUBTRACT        /* - on numeric keypad */
+#define DIK_NUMPADPLUS      DIK_ADD             /* + on numeric keypad */
+#define DIK_NUMPADPERIOD    DIK_DECIMAL         /* . on numeric keypad */
+#define DIK_NUMPADSLASH     DIK_DIVIDE          /* / on numeric keypad */
+#define DIK_RALT            DIK_RMENU           /* right Alt */
+#define DIK_UPARROW         DIK_UP              /* UpArrow on arrow keypad */
+#define DIK_PGUP            DIK_PRIOR           /* PgUp on arrow keypad */
+#define DIK_LEFTARROW       DIK_LEFT            /* LeftArrow on arrow keypad */
+#define DIK_RIGHTARROW      DIK_RIGHT           /* RightArrow on arrow keypad */
+#define DIK_DOWNARROW       DIK_DOWN            /* DownArrow on arrow keypad */
+#define DIK_PGDN            DIK_NEXT            /* PgDn on arrow keypad */
+
+/****************************************************************************
+ *
+ *  IDirectInput
+ *
+ ****************************************************************************/
+
+#define DIENUM_STOP             0
+#define DIENUM_CONTINUE         1
+
+typedef BOOL (FAR PASCAL * LPDIENUMDEVICESCALLBACKA)(LPCDIDEVICEINSTANCEA, LPVOID);
+typedef BOOL (FAR PASCAL * LPDIENUMDEVICESCALLBACKW)(LPCDIDEVICEINSTANCEW, LPVOID);
+#ifdef UNICODE
+#define LPDIENUMDEVICESCALLBACK  LPDIENUMDEVICESCALLBACKW
+#else
+#define LPDIENUMDEVICESCALLBACK  LPDIENUMDEVICESCALLBACKA
+#endif // !UNICODE
+
+#define DIEDFL_ALLDEVICES       0x00000000
+#define DIEDFL_ATTACHEDONLY     0x00000001
+
+#undef INTERFACE
+#define INTERFACE IDirectInputW
+
+DECLARE_INTERFACE_(IDirectInputW, IUnknown)
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;
+
+    /*** IDirectInputW methods ***/
+    STDMETHOD(CreateDevice)(THIS_ REFGUID,LPDIRECTINPUTDEVICEW *,LPUNKNOWN) PURE;
+    STDMETHOD(EnumDevices)(THIS_ DWORD,LPDIENUMDEVICESCALLBACKW,LPVOID,DWORD) PURE;
+    STDMETHOD(GetDeviceStatus)(THIS_ REFGUID) PURE;
+    STDMETHOD(RunControlPanel)(THIS_ HWND,DWORD) PURE;
+    STDMETHOD(Initialize)(THIS_ HINSTANCE,DWORD) PURE;
+};
+
+typedef struct IDirectInputW *LPDIRECTINPUTW;
+
+#undef INTERFACE
+#define INTERFACE IDirectInputA
+
+DECLARE_INTERFACE_(IDirectInputA, IUnknown)
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;
+
+    /*** IDirectInputA methods ***/
+    STDMETHOD(CreateDevice)(THIS_ REFGUID,LPDIRECTINPUTDEVICEA *,LPUNKNOWN) PURE;
+    STDMETHOD(EnumDevices)(THIS_ DWORD,LPDIENUMDEVICESCALLBACKA,LPVOID,DWORD) PURE;
+    STDMETHOD(GetDeviceStatus)(THIS_ REFGUID) PURE;
+    STDMETHOD(RunControlPanel)(THIS_ HWND,DWORD) PURE;
+    STDMETHOD(Initialize)(THIS_ HINSTANCE,DWORD) PURE;
+};
+
+typedef struct IDirectInputA *LPDIRECTINPUTA;
+
+#ifdef UNICODE
+#define IID_IDirectInput IID_IDirectInputW
+#define IDirectInput IDirectInputW
+#define IDirectInputVtbl IDirectInputWVtbl
+#else
+#define IID_IDirectInput IID_IDirectInputA
+#define IDirectInput IDirectInputA
+#define IDirectInputVtbl IDirectInputAVtbl
+#endif
+typedef struct IDirectInput *LPDIRECTINPUT;
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirectInput_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b)
+#define IDirectInput_AddRef(p) (p)->lpVtbl->AddRef(p)
+#define IDirectInput_Release(p) (p)->lpVtbl->Release(p)
+#define IDirectInput_CreateDevice(p,a,b,c) (p)->lpVtbl->CreateDevice(p,a,b,c)
+#define IDirectInput_EnumDevices(p,a,b,c,d) (p)->lpVtbl->EnumDevices(p,a,b,c,d)
+#define IDirectInput_GetDeviceStatus(p,a) (p)->lpVtbl->GetDeviceStatus(p,a)
+#define IDirectInput_RunControlPanel(p,a,b) (p)->lpVtbl->RunControlPanel(p,a,b)
+#define IDirectInput_Initialize(p,a,b) (p)->lpVtbl->Initialize(p,a,b)
+#endif
+
+extern HRESULT WINAPI DirectInputCreateA(HINSTANCE hinst, DWORD dwVersion, LPDIRECTINPUTA *ppDI, LPUNKNOWN punkOuter);
+extern HRESULT WINAPI DirectInputCreateW(HINSTANCE hinst, DWORD dwVersion, LPDIRECTINPUTW *ppDI, LPUNKNOWN punkOuter);
+#ifdef UNICODE
+#define DirectInputCreate  DirectInputCreateW
+#else
+#define DirectInputCreate  DirectInputCreateA
+#endif // !UNICODE
+
+/****************************************************************************
+ *
+ *  Return Codes
+ *
+ ****************************************************************************/
+
+/*
+ *  The operation completed successfully.
+ */
+#define DI_OK                           S_OK
+
+/*
+ *  The device exists but is not currently attached.
+ */
+#define DI_NOTATTACHED                  S_FALSE
+
+/*
+ *  The device buffer overflowed; some input was lost.
+ */
+#define DI_BUFFEROVERFLOW               S_FALSE
+
+/*
+ *  The change in device properties had no effect.
+ */
+#define DI_PROPNOEFFECT                 S_FALSE
+
+/*
+ *  The device is a polled device.  As a result, device buffering
+ *  will not collect any data and event notifications will not be
+ *  signalled until GetDeviceState is called.
+ */
+#define DI_POLLEDDEVICE                 ((HRESULT)0x00000002L)
+
+/*
+ *  The application requires a newer version of DirectInput.
+ */
+#define DIERR_OLDDIRECTINPUTVERSION     \
+    MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_OLD_WIN_VERSION)
+
+/*
+ *  The application was written for an unsupported prerelease version
+ *  of DirectInput.
+ */
+#define DIERR_BETADIRECTINPUTVERSION    \
+    MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_RMODE_APP)
+
+/*
+ *  The object could not be created due to an incompatible driver version
+ *  or mismatched or incomplete driver components.
+ */
+#define DIERR_BADDRIVERVER              \
+    MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_BAD_DRIVER_LEVEL)
+
+/*
+ * The device or device instance is not registered with DirectInput.
+ */
+#define DIERR_DEVICENOTREG              REGDB_E_CLASSNOTREG
+
+/*
+ * The requested object does not exist.
+ */
+#define DIERR_OBJECTNOTFOUND            \
+    MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_FILE_NOT_FOUND)
+
+/*
+ * An invalid parameter was passed to the returning function,
+ * or the object was not in a state that admitted the function
+ * to be called.
+ */
+#define DIERR_INVALIDPARAM              E_INVALIDARG
+
+/*
+ * The specified interface is not supported by the object
+ */
+#define DIERR_NOINTERFACE               E_NOINTERFACE
+
+/*
+ * An undetermined error occured inside the DInput subsystem
+ */
+#define DIERR_GENERIC                   E_FAIL
+
+/*
+ * The DInput subsystem couldn't allocate sufficient memory to complete the
+ * caller's request.
+ */
+#define DIERR_OUTOFMEMORY               E_OUTOFMEMORY
+
+/*
+ * The function called is not supported at this time
+ */
+#define DIERR_UNSUPPORTED               E_NOTIMPL
+
+/*
+ * This object has not been initialized
+ */
+#define DIERR_NOTINITIALIZED            \
+    MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_NOT_READY)
+
+/*
+ * This object is already initialized
+ */
+#define DIERR_ALREADYINITIALIZED        \
+    MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_ALREADY_INITIALIZED)
+
+/*
+ * This object does not support aggregation
+ */
+#define DIERR_NOAGGREGATION             CLASS_E_NOAGGREGATION
+
+/*
+ * Another app has a higher priority level, preventing this call from
+ * succeeding.
+ */
+#define DIERR_OTHERAPPHASPRIO           E_ACCESSDENIED
+
+/*
+ * Access to the input device has been lost.  It must be re-acquired.
+ */
+#define DIERR_INPUTLOST                 \
+    MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_READ_FAULT)
+
+/*
+ * The operation cannot be performed while the device is acquired.
+ */
+#define DIERR_ACQUIRED                  \
+    MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_BUSY)
+
+/*
+ * The operation cannot be performed unless the device is acquired.
+ */
+#define DIERR_NOTACQUIRED               \
+    MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_INVALID_ACCESS)
+
+/*
+ * The specified property cannot be changed.
+ */
+#define DIERR_READONLY                  E_ACCESSDENIED
+
+/*
+ * The device already has an event notification associated with it.
+ */
+#define DIERR_HANDLEEXISTS              E_ACCESSDENIED
+
+/*
+ * Data is not yet available.
+ */
+#ifndef E_PENDING
+#define E_PENDING                       0x80070007L
+#endif
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif  /* __DINPUT_INCLUDED__ */
+
+/****************************************************************************
+ *
+ *  Definitions for non-IDirectInput (VJoyD) features defined more recently
+ *  than the current sdk files
+ *
+ ****************************************************************************/
+
+#ifdef _INC_MMSYSTEM
+#ifndef MMNOJOY
+
+#ifndef __VJOYDX_INCLUDED__
+#define __VJOYDX_INCLUDED__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Flag to indicate that the dwReserved2 field of the JOYINFOEX structure
+ * contains mini-driver specific data to be passed by VJoyD to the mini-
+ * driver instead of doing a poll.
+ */
+#define JOY_PASSDRIVERDATA          0x10000000l
+
+/*
+ * Informs the joystick driver that the configuration has been changed
+ * and should be reloaded from the registery.
+ * dwFlags is reserved and should be set to zero
+ */
+WINMMAPI MMRESULT WINAPI joyConfigChanged( DWORD dwFlags );
+
+/*
+ * Hardware Setting indicating that the device is a headtracker
+ */
+#define JOY_HWS_ISHEADTRACKER       0x02000000l
+
+/*
+ * Hardware Setting indicating that the VxD is used to replace
+ * the standard analog polling
+ */
+#define JOY_HWS_ISGAMEPORTDRIVER    0x04000000l
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif  /* __VJOYDX_INCLUDED__ */
+
+#endif  /* not MMNOJOY */
+#endif  /* _INC_MMSYSTEM */
+
+/****************************************************************************
+ *
+ *  Definitions for non-IDirectInput (VJoyD) features defined more recently
+ *  than the current ddk files
+ *
+ ****************************************************************************/
+
+#ifdef _INC_MMDDK
+#ifndef MMNOJOYDEV
+
+#ifndef __VJOYDXD_INCLUDED__
+#define __VJOYDXD_INCLUDED__
+/*
+ * Poll type in which the do_other field of the JOYOEMPOLLDATA
+ * structure contains mini-driver specific data passed from an app.
+ */
+#define JOY_OEMPOLL_PASSDRIVERDATA  7
+
+#endif  /* __VJOYDXD_INCLUDED__ */
+
+#endif  /* not MMNOJOYDEV */
+#endif  /* _INC_MMDDK */
--- /dev/null
+++ b/QW/dxsdk/sdk/inc/dplay.h
@@ -1,0 +1,308 @@
+/*==========================================================================;
+ *
+ *  Copyright (C) 1994-1995 Microsoft Corporation.  All Rights Reserved.
+ *
+ *  File:       dplay.h
+ *  Content:    DirectPlay include file
+ *
+ ***************************************************************************/
+
+#ifndef __DPLAY_INCLUDED__
+#define __DPLAY_INCLUDED__
+#ifdef _WIN32
+/* for DECLARE_INTERFACE and HRESULT. */
+#include <ole2.h>
+#endif
+
+#define _FACDP  0x877
+#define MAKE_DPHRESULT( code )    MAKE_HRESULT( 1, _FACDP, code )
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#pragma pack(push, 1)
+
+
+/*============================================================================
+ *
+ * DirectPlay Structures
+ *
+ * Various structures used to invoke DirectPlay.
+ *
+ *==========================================================================*/
+
+#ifdef __cplusplus
+/* 'struct' not 'class' per the way DECLARE_INTERFACE_ is defined */
+struct IDirectPlay;
+typedef struct IDirectPlay        FAR *LPDIRECTPLAY;
+#else                  
+typedef struct IDirectPlay        FAR *LPDIRECTPLAY;
+#endif
+
+typedef DWORD DPID, FAR *LPDPID;
+
+typedef struct _DPCAPS
+{
+    DWORD   dwSize;
+    DWORD   dwFlags;
+    DWORD   dwMaxBufferSize;
+    DWORD   dwMaxQueueSize;             // Function of DPlay, not SP.
+    DWORD   dwMaxPlayers;
+    DWORD   dwHundredBaud;              // 24 is 2400, 96 is 9600, etc.
+    DWORD   dwLatency;
+} DPCAPS;
+
+typedef DPCAPS        FAR *LPDPCAPS;
+
+#define DPLONGNAMELEN           52
+#define DPSHORTNAMELEN          20
+#define DPSESSIONNAMELEN        32
+#define DPPASSWORDLEN           16
+#define DPUSERRESERVED          16
+
+typedef struct
+{
+    DWORD   dwSize;
+    GUID    guidSession;                  // Id for Game.  Null is all games.
+    DWORD   dwSession;                    // session identifier
+    DWORD   dwMaxPlayers;                 // Maximum players allowed in game.
+    DWORD   dwCurrentPlayers;             // Current  players in Game.
+    DWORD   dwFlags;                      // DPOPEN_* flags
+    char    szSessionName[DPSESSIONNAMELEN];// Human readable name for Game
+    char    szUserField[DPUSERRESERVED];
+    DWORD   dwReserved1;                  // Reserved for future MS use.
+    char    szPassword[DPPASSWORDLEN];    // Password to be allowed into game.
+    DWORD   dwReserved2;                  // Reserved for future MS use. 
+    DWORD   dwUser1;
+    DWORD   dwUser2;
+    DWORD   dwUser3;
+    DWORD   dwUser4;
+} DPSESSIONDESC;
+typedef DPSESSIONDESC FAR *LPDPSESSIONDESC;
+
+
+/*
+ * Create API
+ */
+typedef BOOL (FAR PASCAL * LPDPENUMDPCALLBACK)(
+    LPGUID              lpSPGuid,
+    LPSTR               lpFriendlyName,
+    DWORD               dwMajorVersion,
+    DWORD               dwMinorVersion,
+    LPVOID              lpContext);
+
+typedef BOOL (FAR PASCAL * LPDPENUMSESSIONSCALLBACK)(
+    LPDPSESSIONDESC     lpDPSGameDesc,
+    LPVOID              lpContext,
+    LPDWORD             lpdwTimeOut,
+    DWORD               dwFlags);
+
+
+
+extern HRESULT WINAPI DirectPlayCreate( LPGUID lpGUID, LPDIRECTPLAY FAR *lplpDP, IUnknown FAR *pUnk);
+extern HRESULT WINAPI DirectPlayEnumerate( LPDPENUMDPCALLBACK, LPVOID );
+
+
+/* Player enumeration callback prototype */
+typedef BOOL (FAR PASCAL *LPDPENUMPLAYERSCALLBACK)(
+    DPID    dpId,
+    LPSTR   lpFriendlyName,
+    LPSTR   lpFormalName,
+    DWORD   dwFlags,
+    LPVOID  lpContext );
+
+/*
+ * IDirectPlay
+ */
+#undef INTERFACE
+#define INTERFACE IDirectPlay
+#ifdef _WIN32
+DECLARE_INTERFACE_( IDirectPlay, IUnknown )
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface)       (THIS_ REFIID riid, LPVOID * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef)        (THIS)  PURE;
+    STDMETHOD_(ULONG,Release)       (THIS) PURE;
+    /*** IDirectPlay methods ***/
+    STDMETHOD(AddPlayerToGroup)     (THIS_ DPID, DPID) PURE;
+    STDMETHOD(Close)                (THIS) PURE;
+    STDMETHOD(CreatePlayer)         (THIS_ LPDPID,LPSTR,LPSTR,LPHANDLE) PURE;
+    STDMETHOD(CreateGroup)          (THIS_ LPDPID,LPSTR,LPSTR) PURE;
+    STDMETHOD(DeletePlayerFromGroup)(THIS_ DPID,DPID) PURE;
+    STDMETHOD(DestroyPlayer)        (THIS_ DPID) PURE;
+    STDMETHOD(DestroyGroup)         (THIS_ DPID) PURE;
+    STDMETHOD(EnableNewPlayers)     (THIS_ BOOL) PURE;
+    STDMETHOD(EnumGroupPlayers)     (THIS_ DPID, LPDPENUMPLAYERSCALLBACK,LPVOID,DWORD) PURE;
+    STDMETHOD(EnumGroups)           (THIS_ DWORD, LPDPENUMPLAYERSCALLBACK,LPVOID,DWORD) PURE;
+    STDMETHOD(EnumPlayers)          (THIS_ DWORD, LPDPENUMPLAYERSCALLBACK,LPVOID,DWORD) PURE;
+    STDMETHOD(EnumSessions)         (THIS_ LPDPSESSIONDESC,DWORD,LPDPENUMSESSIONSCALLBACK,LPVOID,DWORD) PURE;
+    STDMETHOD(GetCaps)              (THIS_ LPDPCAPS) PURE;
+    STDMETHOD(GetMessageCount)      (THIS_ DPID, LPDWORD) PURE;
+    STDMETHOD(GetPlayerCaps)        (THIS_ DPID, LPDPCAPS) PURE;
+    STDMETHOD(GetPlayerName)        (THIS_ DPID,LPSTR,LPDWORD,LPSTR,LPDWORD) PURE;
+    STDMETHOD(Initialize)           (THIS_ LPGUID) PURE;
+    STDMETHOD(Open)                 (THIS_ LPDPSESSIONDESC) PURE;
+    STDMETHOD(Receive)              (THIS_ LPDPID,LPDPID,DWORD,LPVOID,LPDWORD) PURE;
+    STDMETHOD(SaveSession)          (THIS_ LPSTR) PURE;
+    STDMETHOD(Send)                 (THIS_ DPID, DPID, DWORD, LPVOID, DWORD) PURE;
+    STDMETHOD(SetPlayerName)        (THIS_ DPID,LPSTR,LPSTR) PURE;
+};
+#endif
+
+
+
+
+/****************************************************************************
+ *
+ * DIRECTPLAY ERRORS
+ *
+ * Errors are represented by negative values and cannot be combined.
+ *
+ ****************************************************************************/
+#define DP_OK                           0
+#define DPERR_ALREADYINITIALIZED        MAKE_DPHRESULT(   5 )
+#define DPERR_ACCESSDENIED              MAKE_DPHRESULT(  10 )
+#define DPERR_ACTIVEPLAYERS             MAKE_DPHRESULT(  20 )
+#define DPERR_BUFFERTOOSMALL            MAKE_DPHRESULT(  30 )
+#define DPERR_CANTADDPLAYER             MAKE_DPHRESULT(  40 )
+#define DPERR_CANTCREATEGROUP           MAKE_DPHRESULT(  50 )
+#define DPERR_CANTCREATEPLAYER          MAKE_DPHRESULT(  60 )
+#define DPERR_CANTCREATESESSION         MAKE_DPHRESULT(  70 )
+#define DPERR_CAPSNOTAVAILABLEYET       MAKE_DPHRESULT(  80 )
+#define DPERR_EXCEPTION                 MAKE_DPHRESULT(  90 )
+#define DPERR_GENERIC                   E_FAIL
+
+#define DPERR_INVALIDFLAGS              MAKE_DPHRESULT( 120 )
+#define DPERR_INVALIDOBJECT             MAKE_DPHRESULT( 130 )
+#define DPERR_INVALIDPARAM              E_INVALIDARG
+#define DPERR_INVALIDPARAMS             DPERR_INVALIDPARAM
+#define DPERR_INVALIDPLAYER             MAKE_DPHRESULT( 150 )
+#define DPERR_NOCAPS                    MAKE_DPHRESULT( 160 )
+#define DPERR_NOCONNECTION              MAKE_DPHRESULT( 170 )
+#define DPERR_NOMEMORY                  E_OUTOFMEMORY
+#define DPERR_OUTOFMEMORY               DPERR_NOMEMORY
+#define DPERR_NOMESSAGES                MAKE_DPHRESULT( 190 )
+#define DPERR_NONAMESERVERFOUND         MAKE_DPHRESULT( 200 )
+#define DPERR_NOPLAYERS                 MAKE_DPHRESULT( 210 )
+#define DPERR_NOSESSIONS                MAKE_DPHRESULT( 220 )
+#define DPERR_SENDTOOBIG                MAKE_DPHRESULT( 230 )
+#define DPERR_TIMEOUT                   MAKE_DPHRESULT( 240 )
+#define DPERR_UNAVAILABLE               MAKE_DPHRESULT( 250 )
+#define DPERR_UNSUPPORTED               E_NOTIMPL
+#define DPERR_BUSY                      MAKE_DPHRESULT( 270 )
+#define DPERR_USERCANCEL                MAKE_DPHRESULT( 280 ) 
+
+
+#define DPOPEN_OPENSESSION          0x00000001
+#define DPOPEN_CREATESESSION        0x00000002
+
+#define DPSEND_GUARANTEE            0x00000001
+#define DPSEND_HIGHPRIORITY         0x00000002
+#define DPSEND_TRYONCE              0x00000004
+
+#define DPRECEIVE_ALL               0x00000001
+#define DPRECEIVE_TOPLAYER          0x00000002
+#define DPRECEIVE_FROMPLAYER        0x00000004
+#define DPRECEIVE_PEEK              0x00000008
+
+#define DPCAPS_NAMESERVICE          0x00000001 // A name server is supported.
+#define DPCAPS_NAMESERVER           0x00000002 // You are the name server.
+#define DPCAPS_GUARANTEED           0x00000004 // SP's don't have to implement guarantees.
+
+#define DPENUMSESSIONS_AVAILABLE    0x00000001 // All games that match password (if given)
+                                               // and have openings.
+#define DPENUMSESSIONS_ALL          0x00000002
+#define DPENUMSESSIONS_PREVIOUS     0x00000004
+
+#define DPENUMPLAYERS_ALL           0x00000000
+#define DPENUMPLAYERS_PREVIOUS      0x00000004
+#define DPENUMPLAYERS_LOCAL         0x00000008
+#define DPENUMPLAYERS_REMOTE        0x00000010
+#define DPENUMPLAYERS_GROUP         0x00000020
+#define DPENUMPLAYERS_SESSION       0x00000080
+
+//
+// This flag is set on the enumsessions callback when the time out has occured.
+// This means that there is no session data for this callback.
+// If lpdwTimeOut is set to a non-zero value and the EnumSessionsCallback returns
+// TRUE then EnumSessions will continue until the next timeout occurs.
+// Timeouts are in milliseconds.
+ 
+#define DPESC_TIMEDOUT              0x00000001
+
+
+//
+// System message structures and types.
+//
+// System messages have a leading 4 byte type code to identify the message.
+// an app knows it is a system message because it is addressed 'To' player 0.
+//
+
+                                    
+#define DPSYS_ADDPLAYER               0x0003  // DPMSG_ADDPLAYER
+#define DPSYS_DELETEPLAYER            0x0005  // DPMSG_DELETEPLAYER
+
+#define DPSYS_ADDPLAYERTOGROUP        0x0007  // DPMSG_GROUPADD
+
+#define DPSYS_INVITE                  0x000e  // DPMSG_INVITE, Net only.
+
+#define DPSYS_DELETEGROUP             0x0020  // DPMSG_DELETEPLAYER
+#define DPSYS_DELETEPLAYERFROMGRP     0x0021  // DPMSG_GROUPDELETE
+#define DPSYS_SESSIONLOST             0x0031
+
+#define DPSYS_CONNECT                 0x484b  // DPMSG_GENERIC
+
+
+
+typedef struct
+{
+    DWORD       dwType;
+    DWORD       dwPlayerType;
+    DPID        dpId;
+    char        szLongName[DPLONGNAMELEN];
+    char        szShortName[DPSHORTNAMELEN];
+    DWORD       dwCurrentPlayers;
+}   DPMSG_ADDPLAYER;
+
+typedef DPMSG_ADDPLAYER DPMSG_ADDGROUP;
+
+typedef struct
+{
+    DWORD       dwType;
+    DPID        dpIdGroup;
+    DPID        dpIdPlayer;
+} DPMSG_GROUPADD;
+
+typedef DPMSG_GROUPADD DPMSG_GROUPDELETE;
+typedef struct
+{
+    DWORD       dwType;
+    DPID        dpId;
+} DPMSG_DELETEPLAYER;
+
+typedef struct
+{
+    DWORD           dwType;
+    DPSESSIONDESC   dpsDesc;
+} DPMSG_INVITE;
+
+
+
+typedef struct
+{
+    DWORD           dwType;
+} DPMSG_GENERIC;
+
+#pragma pack(pop)
+
+
+DEFINE_GUID( IID_IDirectPlay, 0x5454e9a0, 0xdb65, 0x11ce, 0x92, 0x1c, 0x00, 0xaa, 0x00, 0x6c, 0x49, 0x72);
+
+
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif
--- /dev/null
+++ b/QW/dxsdk/sdk/inc/dsetup.h
@@ -1,0 +1,66 @@
+/*==========================================================================
+ *
+ *  Copyright (C) 1995-1996 Microsoft Corporation.  All Rights Reserved.
+ *
+ *  File:       dsetup.h
+ *  Content:    DirectXSetup, error codes and flags
+ ***************************************************************************/
+
+#ifndef __DSETUP_H__
+#define __DSETUP_H__
+
+#ifdef _WIN32
+#define COM_NO_WINDOWS_H
+#include <objbase.h>
+#else
+#define GUID void
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define DSETUPERR_BADWINDOWSVERSION     -1
+#define DSETUPERR_SOURCEFILENOTFOUND    -2
+#define DSETUPERR_BADSOURCESIZE         -3
+#define DSETUPERR_BADSOURCETIME         -4
+#define DSETUPERR_NOCOPY                -5
+#define DSETUPERR_OUTOFDISKSPACE        -6
+#define DSETUPERR_CANTFINDINF           -7
+#define DSETUPERR_CANTFINDDIR           -8
+#define DSETUPERR_INTERNAL              -9
+#define DSETUPERR_NTWITHNO3D            -10
+
+
+#define MAX_INFLINE             (16*1024)
+#define MAX_DESCRIPTION         256
+
+#define DSETUP_DDRAW            0x00000001      /* install DirectDraw           */
+#define DSETUP_DSOUND           0x00000002      /* install DirectSound          */
+#define DSETUP_DPLAY            0x00000004      /* install DirectPlay           */
+#define DSETUP_DDRAWDRV         0x00000008      /* install DirectDraw Drivers   */
+#define DSETUP_DSOUNDDRV        0x00000010      /* install DirectSound Drivers  */
+#define DSETUP_DPLAYSP          0x00000020      /* install DirectPlay Providers */
+#define DSETUP_DVIDEO           0x00000040      /* install DirectVideo          */
+#define DSETUP_REINSTALL        0x00000080      /* install DirectX even if existing components have the same version    */
+#define DSETUP_DRVINFONLY       0x00000100      /* install DirectX inf files but not drivers                            */
+#define DSETUP_D3D              0x00000200      /* install Direct3D                                                     */
+#define DSETUP_REQUIRESD3D      0x00000400 | DSETUP_D3D /* install Direct3D, pop up dialog box on NT, if no D3D present         */
+
+#define DSETUP_DIRECTX          (DSETUP_D3D | DSETUP_DDRAW | DSETUP_DSOUND | DSETUP_DPLAY | DSETUP_DDRAWDRV | DSETUP_DSOUNDDRV | DSETUP_DPLAYSP)
+
+int WINAPI DirectXSetup( HWND hwnd, LPSTR root_path, DWORD flags );
+int WINAPI DirectXDeviceDriverSetup( HWND hwnd, LPSTR driver_class, LPSTR inf_path, LPSTR driver_path, DWORD flags );
+int WINAPI DirectXSetupIsJapan( void );
+int WINAPI DirectXSetupIsJapanNec( void );
+
+typedef int (WINAPI * LPDIRECTXSETUP)( HWND, LPSTR, DWORD );
+typedef int (WINAPI * LPDIRECTXDEVICEDRIVERSETUP)( HWND, LPSTR, LPSTR, LPSTR, DWORD );
+typedef int (WINAPI * LPDIRECTXSETUPISJAPAN)( void );
+typedef int (WINAPI * LPDIRECTXSETUPISJAPANNEC)( void );
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif
--- /dev/null
+++ b/QW/dxsdk/sdk/inc/dsound.h
@@ -1,0 +1,366 @@
+/*==========================================================================;
+ *
+ *  Copyright (C) 1995,1996 Microsoft Corporation.  All Rights Reserved.
+ *
+ *  File:       dsound.h
+ *  Content:    DirectSound include file
+ *
+ ***************************************************************************/
+
+#ifndef __DSOUND_INCLUDED__
+#define __DSOUND_INCLUDED__
+
+#ifdef _WIN32
+#define COM_NO_WINDOWS_H
+#include <objbase.h>
+#endif
+
+#define _FACDS  0x878
+#define MAKE_DSHRESULT( code )  MAKE_HRESULT( 1, _FACDS, code )
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Direct Sound Component GUID    {47D4D946-62E8-11cf-93BC-444553540000}
+DEFINE_GUID(CLSID_DirectSound,
+0x47d4d946, 0x62e8, 0x11cf, 0x93, 0xbc, 0x44, 0x45, 0x53, 0x54, 0x0, 0x0);
+
+// DirectSound 279afa83-4981-11ce-a521-0020af0be560
+DEFINE_GUID(IID_IDirectSound,0x279AFA83,0x4981,0x11CE,0xA5,0x21,0x00,0x20,0xAF,0x0B,0xE5,0x60);
+// DirectSoundBuffer 279afa85-4981-11ce-a521-0020af0be560
+DEFINE_GUID(IID_IDirectSoundBuffer,0x279AFA85,0x4981,0x11CE,0xA5,0x21,0x00,0x20,0xAF,0x0B,0xE5,0x60);
+
+
+
+//==========================================================================;
+//
+//                            Structures...
+//
+//==========================================================================;
+#ifdef __cplusplus
+/* 'struct' not 'class' per the way DECLARE_INTERFACE_ is defined */
+struct IDirectSound;
+struct IDirectSoundBuffer;
+#endif
+
+typedef struct IDirectSound           *LPDIRECTSOUND;        
+typedef struct IDirectSoundBuffer     *LPDIRECTSOUNDBUFFER;  
+typedef struct IDirectSoundBuffer    **LPLPDIRECTSOUNDBUFFER;  
+
+
+typedef struct _DSCAPS
+{
+    DWORD       dwSize;
+    DWORD       dwFlags;
+    DWORD       dwMinSecondarySampleRate;
+    DWORD       dwMaxSecondarySampleRate;
+    DWORD       dwPrimaryBuffers;
+    DWORD       dwMaxHwMixingAllBuffers;
+    DWORD       dwMaxHwMixingStaticBuffers;
+    DWORD       dwMaxHwMixingStreamingBuffers;
+    DWORD       dwFreeHwMixingAllBuffers;
+    DWORD       dwFreeHwMixingStaticBuffers;
+    DWORD       dwFreeHwMixingStreamingBuffers;
+    DWORD       dwMaxHw3DAllBuffers;
+    DWORD       dwMaxHw3DStaticBuffers;
+    DWORD       dwMaxHw3DStreamingBuffers;
+    DWORD       dwFreeHw3DAllBuffers;
+    DWORD       dwFreeHw3DStaticBuffers;
+    DWORD       dwFreeHw3DStreamingBuffers;
+    DWORD       dwTotalHwMemBytes;
+    DWORD       dwFreeHwMemBytes;
+    DWORD       dwMaxContigFreeHwMemBytes;
+    DWORD       dwUnlockTransferRateHwBuffers;
+    DWORD       dwPlayCpuOverheadSwBuffers;
+    DWORD       dwReserved1;
+    DWORD       dwReserved2;
+} DSCAPS, *LPDSCAPS;
+
+typedef struct _DSBCAPS
+{
+    
+    DWORD       dwSize;
+    DWORD       dwFlags;
+    DWORD       dwBufferBytes;
+    DWORD       dwUnlockTransferRate;
+    DWORD       dwPlayCpuOverhead;
+} DSBCAPS, *LPDSBCAPS;
+
+typedef struct _DSBUFFERDESC
+{
+    DWORD                   dwSize;
+    DWORD                   dwFlags;
+    DWORD                   dwBufferBytes;
+    DWORD                   dwReserved;
+    LPWAVEFORMATEX          lpwfxFormat;
+} DSBUFFERDESC, *LPDSBUFFERDESC;
+
+
+
+typedef LPVOID* LPLPVOID;
+
+
+typedef BOOL (FAR PASCAL * LPDSENUMCALLBACKW)(GUID FAR *, LPWSTR, LPWSTR, LPVOID);
+typedef BOOL (FAR PASCAL * LPDSENUMCALLBACKA)(GUID FAR *, LPSTR, LPSTR, LPVOID);
+
+extern HRESULT WINAPI DirectSoundCreate(GUID FAR * lpGUID, LPDIRECTSOUND * ppDS, IUnknown FAR *pUnkOuter );
+extern HRESULT WINAPI DirectSoundEnumerateW(LPDSENUMCALLBACKW lpCallback, LPVOID lpContext );
+extern HRESULT WINAPI DirectSoundEnumerateA(LPDSENUMCALLBACKA lpCallback, LPVOID lpContext );
+
+#ifdef UNICODE
+#define LPDSENUMCALLBACK        LPDSENUMCALLBACKW
+#define DirectSoundEnumerate    DirectSoundEnumerateW
+#else
+#define LPDSENUMCALLBACK        LPDSENUMCALLBACKA
+#define DirectSoundEnumerate    DirectSoundEnumerateA
+#endif
+
+//
+// IDirectSound
+//
+#undef INTERFACE
+#define INTERFACE IDirectSound
+#ifdef _WIN32
+DECLARE_INTERFACE_( IDirectSound, IUnknown )
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef) (THIS)  PURE;
+    STDMETHOD_(ULONG,Release) (THIS) PURE;
+    /*** IDirectSound methods ***/
+
+    STDMETHOD( CreateSoundBuffer)(THIS_ LPDSBUFFERDESC, LPLPDIRECTSOUNDBUFFER, IUnknown FAR *) PURE;
+    STDMETHOD( GetCaps)(THIS_ LPDSCAPS ) PURE;
+    STDMETHOD( DuplicateSoundBuffer)(THIS_ LPDIRECTSOUNDBUFFER, LPLPDIRECTSOUNDBUFFER ) PURE;
+    STDMETHOD( SetCooperativeLevel)(THIS_ HWND, DWORD ) PURE;
+    STDMETHOD( Compact)(THIS ) PURE;
+    STDMETHOD( GetSpeakerConfig)(THIS_ LPDWORD ) PURE;
+    STDMETHOD( SetSpeakerConfig)(THIS_ DWORD ) PURE;
+    STDMETHOD( Initialize)(THIS_ GUID FAR * ) PURE;
+};
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirectSound_QueryInterface(p,a,b)       (p)->lpVtbl->QueryInterface(p,a,b)
+#define IDirectSound_AddRef(p)                   (p)->lpVtbl->AddRef(p)
+#define IDirectSound_Release(p)                  (p)->lpVtbl->Release(p)
+#define IDirectSound_CreateSoundBuffer(p,a,b,c)  (p)->lpVtbl->CreateSoundBuffer(p,a,b,c)
+#define IDirectSound_GetCaps(p,a)                (p)->lpVtbl->GetCaps(p,a)
+#define IDirectSound_DuplicateSoundBuffer(p,a,b) (p)->lpVtbl->DuplicateSoundBuffer(p,a,b)
+#define IDirectSound_SetCooperativeLevel(p,a,b)  (p)->lpVtbl->SetCooperativeLevel(p,a,b)
+#define IDirectSound_Compact(p)                  (p)->lpVtbl->Compact(p)
+#define IDirectSound_GetSpeakerConfig(p,a)       (p)->lpVtbl->GetSpeakerConfig(p,a)
+#define IDirectSound_SetSpeakerConfig(p,b)       (p)->lpVtbl->SetSpeakerConfig(p,b)
+#define IDirectSound_Initialize(p,a)             (p)->lpVtbl->Initialize(p,a)
+#endif
+
+#endif
+
+//
+// IDirectSoundBuffer
+//
+#undef INTERFACE
+#define INTERFACE IDirectSoundBuffer
+#ifdef _WIN32
+DECLARE_INTERFACE_( IDirectSoundBuffer, IUnknown )
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef) (THIS)  PURE;
+    STDMETHOD_(ULONG,Release) (THIS) PURE;
+    /*** IDirectSoundBuffer methods ***/
+
+    STDMETHOD(           GetCaps)(THIS_ LPDSBCAPS ) PURE;
+    STDMETHOD(GetCurrentPosition)(THIS_ LPDWORD,LPDWORD ) PURE;
+    STDMETHOD(         GetFormat)(THIS_ LPWAVEFORMATEX, DWORD, LPDWORD ) PURE;
+    STDMETHOD(         GetVolume)(THIS_ LPLONG ) PURE;
+    STDMETHOD(            GetPan)(THIS_ LPLONG ) PURE;
+    STDMETHOD(      GetFrequency)(THIS_ LPDWORD ) PURE;
+    STDMETHOD(         GetStatus)(THIS_ LPDWORD ) PURE;
+    STDMETHOD(        Initialize)(THIS_ LPDIRECTSOUND, LPDSBUFFERDESC ) PURE;
+    STDMETHOD(              Lock)(THIS_ DWORD,DWORD,LPVOID,LPDWORD,LPVOID,LPDWORD,DWORD ) PURE;
+    STDMETHOD(              Play)(THIS_ DWORD,DWORD,DWORD ) PURE;
+    STDMETHOD(SetCurrentPosition)(THIS_ DWORD ) PURE;
+    STDMETHOD(         SetFormat)(THIS_ LPWAVEFORMATEX ) PURE;
+    STDMETHOD(         SetVolume)(THIS_ LONG ) PURE;
+    STDMETHOD(            SetPan)(THIS_ LONG ) PURE;
+    STDMETHOD(      SetFrequency)(THIS_ DWORD ) PURE;
+    STDMETHOD(              Stop)(THIS  ) PURE;
+    STDMETHOD(            Unlock)(THIS_ LPVOID,DWORD,LPVOID,DWORD ) PURE;
+    STDMETHOD(           Restore)(THIS  ) PURE;
+};
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirectSoundBuffer_QueryInterface(p,a,b)        (p)->lpVtbl->QueryInterface(p,a,b)
+#define IDirectSoundBuffer_AddRef(p)                    (p)->lpVtbl->AddRef(p)
+#define IDirectSoundBuffer_Release(p)                   (p)->lpVtbl->Release(p)
+#define IDirectSoundBuffer_GetCaps(p,a)                 (p)->lpVtbl->GetCaps(p,a)
+#define IDirectSoundBuffer_GetCurrentPosition(p,a,b)    (p)->lpVtbl->GetCurrentPosition(p,a,b)
+#define IDirectSoundBuffer_GetFormat(p,a,b,c)           (p)->lpVtbl->GetFormat(p,a,b,c)
+#define IDirectSoundBuffer_GetVolume(p,a)               (p)->lpVtbl->GetVolume(p,a)
+#define IDirectSoundBuffer_GetPan(p,a)                  (p)->lpVtbl->GetPan(p,a)
+#define IDirectSoundBuffer_GetFrequency(p,a)            (p)->lpVtbl->GetFrequency(p,a)
+#define IDirectSoundBuffer_GetStatus(p,a)               (p)->lpVtbl->GetStatus(p,a)
+#define IDirectSoundBuffer_Initialize(p,a,b)            (p)->lpVtbl->Initialize(p,a,b)
+#define IDirectSoundBuffer_Lock(p,a,b,c,d,e,f,g)        (p)->lpVtbl->Lock(p,a,b,c,d,e,f,g)
+#define IDirectSoundBuffer_Play(p,a,b,c)                (p)->lpVtbl->Play(p,a,b,c)
+#define IDirectSoundBuffer_SetCurrentPosition(p,a)      (p)->lpVtbl->SetCurrentPosition(p,a)
+#define IDirectSoundBuffer_SetFormat(p,a)               (p)->lpVtbl->SetFormat(p,a)
+#define IDirectSoundBuffer_SetVolume(p,a)               (p)->lpVtbl->SetVolume(p,a)
+#define IDirectSoundBuffer_SetPan(p,a)                  (p)->lpVtbl->SetPan(p,a)
+#define IDirectSoundBuffer_SetFrequency(p,a)            (p)->lpVtbl->SetFrequency(p,a)
+#define IDirectSoundBuffer_Stop(p)                      (p)->lpVtbl->Stop(p)
+#define IDirectSoundBuffer_Unlock(p,a,b,c,d)            (p)->lpVtbl->Unlock(p,a,b,c,d)
+#define IDirectSoundBuffer_Restore(p)                   (p)->lpVtbl->Restore(p)
+#endif
+
+#endif
+
+
+
+/*
+ * Return Codes
+ */
+
+#define DS_OK                           0
+
+/*
+ * The call failed because resources (such as a priority level)
+ *  were already being used by another caller.
+ */
+#define DSERR_ALLOCATED                 MAKE_DSHRESULT( 10 )
+/*
+ * The control (vol,pan,etc.) requested by the caller is not available.
+ */
+#define DSERR_CONTROLUNAVAIL            MAKE_DSHRESULT( 30 )
+/*
+ * An invalid parameter was passed to the returning function
+ */
+#define DSERR_INVALIDPARAM              E_INVALIDARG
+/*
+ * This call is not valid for the current state of this object
+ */
+#define DSERR_INVALIDCALL               MAKE_DSHRESULT( 50 )
+/*
+ * An undetermined error occured inside the DSound subsystem
+ */
+#define DSERR_GENERIC                   E_FAIL
+/*
+ * The caller does not have the priority level required for the function to
+ * succeed.
+ */
+#define DSERR_PRIOLEVELNEEDED           MAKE_DSHRESULT( 70 )
+/*
+ * The DSound subsystem couldn't allocate sufficient memory to complete the
+ * caller's request.
+ */
+#define DSERR_OUTOFMEMORY               E_OUTOFMEMORY
+/*
+ * The specified WAVE format is not supported
+ */
+#define DSERR_BADFORMAT                 MAKE_DSHRESULT( 100 )
+/*
+ * The function called is not supported at this time
+ */
+#define DSERR_UNSUPPORTED               E_NOTIMPL
+/*
+ * No sound driver is available for use
+ */
+#define DSERR_NODRIVER                  MAKE_DSHRESULT( 120 )
+/*
+ * This object is already initialized
+ */
+#define DSERR_ALREADYINITIALIZED        MAKE_DSHRESULT( 130 )
+/*
+ * This object does not support aggregation
+ */
+#define DSERR_NOAGGREGATION             CLASS_E_NOAGGREGATION
+/*
+ * The buffer memory has been lost, and must be Restored.
+ */
+#define DSERR_BUFFERLOST                MAKE_DSHRESULT( 150 )
+/*
+ * Another app has a higher priority level, preventing this call from
+ * succeeding.
+ */
+#define DSERR_OTHERAPPHASPRIO           MAKE_DSHRESULT( 160 )
+/*
+ * The Initialize() member on the Direct Sound Object has not been
+ * called or called successfully before calls to other members.
+ */
+#define DSERR_UNINITIALIZED             MAKE_DSHRESULT( 170 )
+
+
+
+
+//==========================================================================;
+//
+//                               Flags...
+//
+//==========================================================================;
+
+#define DSCAPS_PRIMARYMONO          0x00000001
+#define DSCAPS_PRIMARYSTEREO        0x00000002
+#define DSCAPS_PRIMARY8BIT          0x00000004
+#define DSCAPS_PRIMARY16BIT         0x00000008
+#define DSCAPS_CONTINUOUSRATE       0x00000010
+#define DSCAPS_EMULDRIVER           0x00000020
+#define DSCAPS_CERTIFIED            0x00000040
+#define DSCAPS_SECONDARYMONO        0x00000100
+#define DSCAPS_SECONDARYSTEREO      0x00000200
+#define DSCAPS_SECONDARY8BIT        0x00000400
+#define DSCAPS_SECONDARY16BIT       0x00000800
+
+
+
+#define DSBPLAY_LOOPING         0x00000001
+
+
+          
+#define DSBSTATUS_PLAYING           0x00000001
+#define DSBSTATUS_BUFFERLOST        0x00000002
+#define DSBSTATUS_LOOPING           0x00000004
+         
+
+#define DSBLOCK_FROMWRITECURSOR         0x00000001
+
+
+
+#define DSSCL_NORMAL                1
+#define DSSCL_PRIORITY              2
+#define DSSCL_EXCLUSIVE             3
+#define DSSCL_WRITEPRIMARY          4
+
+
+
+#define DSBCAPS_PRIMARYBUFFER       0x00000001
+#define DSBCAPS_STATIC              0x00000002
+#define DSBCAPS_LOCHARDWARE         0x00000004
+#define DSBCAPS_LOCSOFTWARE         0x00000008
+#define DSBCAPS_CTRLFREQUENCY       0x00000020
+#define DSBCAPS_CTRLPAN             0x00000040
+#define DSBCAPS_CTRLVOLUME          0x00000080
+#define DSBCAPS_CTRLDEFAULT         0x000000E0  // Pan + volume + frequency.
+#define DSBCAPS_CTRLALL             0x000000E0  // All control capabilities
+#define DSBCAPS_STICKYFOCUS         0x00004000
+#define DSBCAPS_GETCURRENTPOSITION2 0x00010000  // More accurate play cursor under emulation
+
+
+
+
+#define DSSPEAKER_HEADPHONE     1
+#define DSSPEAKER_MONO          2
+#define DSSPEAKER_QUAD          3
+#define DSSPEAKER_STEREO        4
+#define DSSPEAKER_SURROUND      5
+
+
+
+
+
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif  /* __DSOUND_INCLUDED__ */
--- /dev/null
+++ b/QW/dxsdk/sdk/inc/fastfile.h
@@ -1,0 +1,24 @@
+/*==========================================================================
+ *
+ *  Copyright (C) 1995-1996 Microsoft Corporation.  All Rights Reserved.
+ *
+ *  File:       fastfile.h
+ *  Content:    Definitions for fastfile access.
+ *
+ * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
+ * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
+ * WARRANTIES OF MERCHANTBILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ ***************************************************************************/
+
+typedef LPVOID  HFASTFILE;
+
+extern BOOL FastFileInit( LPSTR fname, int max_handles );
+extern void FastFileFini( void );
+extern HFASTFILE FastFileOpen( LPSTR name );
+extern BOOL FastFileClose( HFASTFILE pfe );
+extern BOOL FastFileRead( HFASTFILE pfh, LPVOID ptr, int size );
+extern BOOL FastFileSeek( HFASTFILE pfe, int off, int how );
+extern long FastFileTell( HFASTFILE pfe );
+extern LPVOID FastFileLock( HFASTFILE pfe, int off, int len );
+extern BOOL FastFileUnlock( HFASTFILE pfe, int off, int len );
binary files /dev/null b/QW/dxsdk/sdk/lib/dinput.lib differ
binary files /dev/null b/QW/dxsdk/sdk/lib/dxguid.lib differ
--- /dev/null
+++ b/QW/fixskins.sh
@@ -1,0 +1,8 @@
+#!/bin/sh
+for x in *; do
+	y=`echo $x | tr '[A-Z]' '[a-z]'`
+	if [ $x != $y ]; then
+		mv $x $y
+	fi
+done
+	
--- /dev/null
+++ b/QW/gas2masm/gas2masm.001
@@ -1,0 +1,102 @@
+# Microsoft Developer Studio Project File - Name="gas2masm" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 5.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=gas2masm - Win32 Release
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "gas2masm.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "gas2masm.mak" CFG="gas2masm - Win32 Release"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "gas2masm - Win32 Release" (based on\
+ "Win32 (x86) Console Application")
+!MESSAGE "gas2masm - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE 
+
+# Begin Project
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "gas2masm - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir ".\Release"
+# PROP BASE Intermediate_Dir ".\Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir ".\Release"
+# PROP Intermediate_Dir ".\Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /c
+# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+
+!ELSEIF  "$(CFG)" == "gas2masm - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir ".\Debug"
+# PROP BASE Intermediate_Dir ".\Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir ".\Debug"
+# PROP Intermediate_Dir ".\Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /YX /c
+# ADD CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386
+
+!ENDIF 
+
+# Begin Target
+
+# Name "gas2masm - Win32 Release"
+# Name "gas2masm - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;hpj;bat;for;f90"
+# Begin Source File
+
+SOURCE=.\gas2masm.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
--- /dev/null
+++ b/QW/gas2masm/gas2masm.c
@@ -1,0 +1,1056 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+//
+// gas to MASM source code converter
+//
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define MAX_TOKENS			100
+#define MAX_TOKEN_LENGTH	1024
+#define LF					0x0A
+
+typedef enum {NOT_WHITESPACE, WHITESPACE, TOKEN_AVAILABLE, LINE_DONE, FILE_DONE, PARSED_OKAY} tokenstat;
+typedef enum {NOSEG, DATASEG, TEXTSEG} segtype;
+
+int		tokennum;
+int		inline, outline;
+
+char	*token;
+char	tokens[MAX_TOKENS][MAX_TOKEN_LENGTH+1];
+
+segtype	currentseg = NOSEG;
+
+typedef struct {
+	char	*text;
+	char	*emit;
+	int		numtokens;
+	void	(*parsefunc) (void);
+} parsefield;
+
+
+void errorexit (void);
+
+
+//==============================================
+
+typedef struct {
+	char	*text;
+	char	*emit;
+	int		len;
+} regdesc;
+
+regdesc	reglist[] = {
+	{"%eax", "eax", 4},
+	{"%ebx", "ebx", 4},
+	{"%ecx", "ecx", 4},
+	{"%edx", "edx", 4},
+	{"%esi", "esi", 4},
+	{"%edi", "edi", 4},
+	{"%ebp", "ebp", 4},
+	{"%esp", "esp", 4},
+	{"%ax", "ax", 3},
+	{"%bx", "bx", 3},
+	{"%cx", "cx", 3},
+	{"%dx", "dx", 3},
+	{"%si", "si", 3},
+	{"%di", "di", 3},
+	{"%bp", "bp", 3},
+	{"%sp", "sp", 3},
+	{"%al", "al", 3},
+	{"%bl", "bl", 3},
+	{"%cl", "cl", 3},
+	{"%dl", "dl", 3},
+	{"%ah", "ah", 3},
+	{"%bh", "bh", 3},
+	{"%ch", "ch", 3},
+	{"%dh", "dh", 3},
+	{"%st(0)", "st(0)", 6},
+	{"%st(1)", "st(1)", 6},
+	{"%st(2)", "st(2)", 6},
+	{"%st(3)", "st(3)", 6},
+	{"%st(4)", "st(4)", 6},
+	{"%st(5)", "st(5)", 6},
+	{"%st(6)", "st(6)", 6},
+	{"%st(7)", "st(7)", 6},
+};
+
+int	numregs = sizeof (reglist) / sizeof (reglist[0]);
+
+//==============================================
+
+
+void emitanoperand (int tnum, char *type, int notdata)
+{
+	int		i, index, something_outside_parens, regfound;
+	int		parencount;
+	char	*pt;
+	char	temp[MAX_TOKEN_LENGTH+1];
+
+	pt = tokens[tnum];
+
+	if (pt[0] == '%')
+	{
+	// register
+		for (i=0 ; i<numregs ; i++)
+		{
+			if (!strcmpi (pt, reglist[i].text))
+			{
+				printf ("%s", reglist[i].emit);
+				return;
+			}
+		}
+
+		fprintf (stderr, "Error: bad register %s\n", pt);
+		errorexit ();
+	}
+	else if (pt[0] == '$')
+	{
+	// constant
+		if (pt[1] == '(')
+		{
+			if ((pt[2] > '9') || (pt[2] < '0'))
+			{
+				i = 2;
+				printf ("offset ");
+
+				parencount = 1;
+
+				while ((pt[i] != ')') || (parencount > 1))
+				{
+					if (!pt[i])
+					{
+						fprintf (stderr, "mismatched parens");
+						errorexit ();
+					}
+
+					if (pt[i] == ')')
+						parencount--;
+					else if (pt[i] == '(')
+						parencount++;
+
+					printf ("%c", pt[i]);
+					i++;
+				}
+			}
+			else
+			{
+				pt++;
+
+				parencount = 1;
+
+				for (i=1 ; (pt[i] != ')') || (parencount > 1) ; i++)
+				{
+					if (!pt[i])
+					{
+						fprintf (stderr, "mismatched parens");
+						errorexit ();
+					}
+
+					if (pt[i] == ')')
+						parencount--;
+					else if (pt[i] == '(')
+						parencount++;
+				}
+
+				pt[i] = 0;
+
+				if ((pt[1] == '0') && ((pt[2] == 'x') || (pt[2] == 'X')))
+				{
+					printf ("0%sh", &pt[3]);
+				}
+				else
+				{
+					printf ("%s", &pt[1]);
+				}
+ 			}
+		}
+		else if ((pt[1] == '0') && ((pt[2] == 'x') || (pt[2] == 'X')))
+		{
+			printf ("0%sh", &pt[3]);
+		}
+		else if ((pt[1] >= '0') && (pt[1] <= '9'))
+		{
+			printf ("%s", &pt[1]);
+		}
+		else
+		{
+			printf ("offset %s", &pt[1]);
+		}
+	}
+	else if (!notdata && ((pt[0] >= '0') && (pt[0] <= '9')))
+	{
+		pt--;
+
+		if ((pt[1] == '0') && ((pt[2] == 'x') || (pt[2] == 'X')))
+		{
+			printf ("0%sh", &pt[3]);
+		}
+		else
+		{
+			printf ("%s", &pt[1]);
+		}
+	}
+	else
+	{
+	// must be a memory location
+		strcpy (temp, type);
+		index = strlen (temp);
+
+		if (notdata)
+			temp[index++] = '[';
+
+		something_outside_parens = 0;
+
+		while (*pt)
+		{
+			if (index > (MAX_TOKEN_LENGTH - 10))
+			{
+				fprintf (stderr, "Error: operand too long %s\n",
+						 tokens[tnum]);
+				errorexit ();
+			}
+
+			if (*pt != ')')
+			{
+				if (*pt == '(')
+				{
+					if (something_outside_parens)
+						temp[index++] = '+';
+				}
+				else if (*pt == '%')
+				{
+					regfound = 0;
+
+					for (i=0 ; i<numregs ; i++)
+					{
+						if (!strnicmp (pt, reglist[i].text,
+							reglist[i].len))
+						{
+							strcpy (&temp[index], reglist[i].emit);
+							index += strlen (reglist[i].emit);
+							pt += strlen (reglist[i].text) - 1;
+							regfound = 1;
+							break;
+						}
+					}
+
+					if (!regfound)
+					{
+						fprintf (stderr, "Error: bad register %s\n", pt);
+						errorexit ();
+					}
+				}
+				else if (*pt == ',')
+				{
+					pt++;
+
+					if ((*pt >= '1') && (*pt <= '8'))
+					{
+						temp[index++] = '*';
+						temp[index++] = *pt;
+					}
+					else if (*pt != ')')
+					{
+						if (temp[index-1] != '+')
+							temp[index++] = '+';
+					}
+				}
+				else
+				{
+					something_outside_parens = 1;
+
+					// handle hexadecimal constants in addresses
+					if ((*pt == '0') &&
+						((*(pt+1) == 'x') || (*(pt+1) == 'X')))
+					{
+						pt += 2;
+
+						do
+						{
+							temp[index++] = *pt++;
+						} while (((*pt >= '0') && (*pt <= '9'))     ||
+								 ((*pt >= 'a') && (*pt <= 'f')) ||
+								 ((*pt >= 'A') && (*pt <= 'F')));
+
+						pt--;
+						temp[index++] = 'h';
+					}
+					else
+					{
+						temp[index++] = *pt;
+					}
+				}
+			}
+
+			pt++;
+		}
+
+		if (notdata)
+			temp[index++] = ']';
+
+		temp[index] = 0;
+		printf ("%s", temp);
+	}
+}
+
+
+void datasegstart (void)
+{
+	if (currentseg == DATASEG)
+		return;
+
+	if (currentseg == TEXTSEG)
+		printf ("_TEXT ENDS\n");
+
+	printf ("_DATA SEGMENT");
+
+	currentseg = DATASEG;
+}
+
+
+void textsegstart (void)
+{
+	if (currentseg == TEXTSEG)
+		return;
+
+	if (currentseg == DATASEG)
+		printf ("_DATA ENDS\n");
+
+	printf ("_TEXT SEGMENT");
+
+	currentseg = TEXTSEG;
+}
+
+
+void emitdata (void)
+{
+	int		i;
+
+	for (i=1 ; i<(tokennum-1) ; i++)
+		printf (" %s,", tokens[i]);
+
+	printf (" %s", tokens[tokennum-1]);
+}
+
+
+void emitonedata (void)
+{
+
+	printf (" %s", tokens[1]);
+}
+
+
+void emitonecalldata (void)
+{
+	int	i, isaddr, len;
+
+	if (tokens[1][0] == '*')
+	{
+		printf (" dword ptr[%s]", &tokens[1][1]);
+	}
+	else
+	{
+		isaddr = 0;
+		len = strlen(tokens[1]);
+
+		for (i=0 ; i<len ; i++)
+		{
+			if (tokens[1][i] == '(')
+			{
+				isaddr = 1;
+				break;
+			}
+		}
+
+		if (!isaddr)
+		{
+			printf (" near ptr %s", tokens[1]);
+		}
+		else
+		{
+			emitanoperand (1, " dword ptr", 1);
+		}
+	}
+}
+
+
+void emitonejumpdata (void)
+{
+	int	i, isaddr, len;
+
+	if (tokens[1][0] == '*')
+	{
+		printf (" dword ptr[%s]", &tokens[1][1]);
+	}
+	else
+	{
+		isaddr = 0;
+		len = strlen(tokens[1]);
+
+		for (i=0 ; i<len ; i++)
+		{
+			if (tokens[1][i] == '(')
+			{
+				isaddr = 1;
+				break;
+			}
+		}
+
+		if (!isaddr)
+		{
+			printf (" %s", tokens[1]);
+		}
+		else
+		{
+			emitanoperand (1, " dword ptr", 1);
+		}
+	}
+}
+
+
+void emitexterndef (void)
+{
+
+	printf (" %s:dword", tokens[1]);
+}
+
+
+void nooperands (void)
+{
+
+}
+
+
+void emitoneoperandl (void)
+{
+
+	printf (" ");
+	emitanoperand (1, "ds:dword ptr", 1);
+}
+
+
+void emitoneoperandb (void)
+{
+
+	printf (" ");
+	emitanoperand (1, "ds:byte ptr", 1);
+}
+
+
+void emitoneoperandw (void)
+{
+
+	printf (" ");
+	emitanoperand (1, "ds:word ptr", 1);
+}
+
+
+void emittwooperandsl (void)
+{
+
+	printf (" ");
+	emitanoperand (2, "ds:dword ptr", 1);
+	printf (",");
+	emitanoperand (1, "ds:dword ptr", 1);
+}
+
+
+void emittwooperandsb (void)
+{
+
+	printf (" ");
+	emitanoperand (2, "ds:byte ptr", 1);
+	printf (",");
+	emitanoperand (1, "ds:byte ptr", 1);
+}
+
+
+void emittwooperandsw (void)
+{
+
+	printf (" ");
+	emitanoperand (2, "ds:word ptr", 1);
+	printf (",");
+	emitanoperand (1, "ds:word ptr", 1);
+}
+
+
+void emit_0_or_1_operandsl (void)
+{
+
+	if (tokennum == 2)
+	{
+		printf (" ");
+		emitanoperand (1, "ds:dword ptr", 1);
+	}
+}
+
+
+void emit_1_or_2_operandsl (void)
+{
+	int		j;
+
+	if (tokennum == 2)
+	{
+		printf (" ");
+		emitanoperand (1, "ds:dword ptr", 1);
+	}
+	else if (tokennum == 3)
+	{
+		printf (" ");
+		emitanoperand (2, "ds:dword ptr", 1);
+		printf (",");
+		emitanoperand (1, "ds:dword ptr", 1);
+	}
+	else
+	{
+
+		fprintf (stderr, "Error: too many operands\n");
+
+		for (j=0 ; j<tokennum ; j++)
+			fprintf (stderr, "%s\n", tokens[j]);
+
+		fprintf (stderr, "\n");
+		errorexit ();
+	}
+}
+
+
+void emit_1_or_2_operandsl_vartext (char *str0, char *str1)
+{
+	int		j;
+
+	if (tokennum == 2)
+	{
+		printf (" %s ", str0);
+		emitanoperand (1, "ds:dword ptr", 1);
+	}
+	else if (tokennum == 3)
+	{
+		if (!strcmpi (tokens[2], "%st(0)"))
+			printf (" %s ", str0);
+		else
+			printf (" %s ", str1);
+
+		emitanoperand (2, "ds:dword ptr", 1);
+		printf (",");
+		emitanoperand (1, "ds:dword ptr", 1);
+	}
+	else
+	{
+
+		fprintf (stderr, "Error: too many operands\n");
+
+		for (j=0 ; j<tokennum ; j++)
+			fprintf (stderr, "%s\n", tokens[j]);
+
+		fprintf (stderr, "\n");
+		errorexit ();
+	}
+}
+
+
+void special_fdivl (void)
+{
+
+	emit_1_or_2_operandsl_vartext ("fdiv", "fdivr");
+}
+
+
+void special_fdivpl (void)
+{
+
+	emit_1_or_2_operandsl_vartext ("fdivp", "fdivrp");
+}
+
+
+void special_fdivrl (void)
+{
+
+	emit_1_or_2_operandsl_vartext ("fdivr", "fdiv");
+}
+
+
+void special_fdivrpl (void)
+{
+
+	emit_1_or_2_operandsl_vartext ("fdivrp", "fdivp");
+}
+
+
+void special_fsubl (void)
+{
+
+	emit_1_or_2_operandsl_vartext ("fsub", "fsubr");
+}
+
+
+void special_fsubpl (void)
+{
+
+	emit_1_or_2_operandsl_vartext ("fsubp", "fsubrp");
+}
+
+
+void special_fsubrl (void)
+{
+
+	emit_1_or_2_operandsl_vartext ("fsubr", "fsub");
+}
+
+
+void special_fsubrpl (void)
+{
+
+	emit_1_or_2_operandsl_vartext ("fsubrp", "fsubp");
+}
+
+
+void emit_multiple_data (void)
+{
+	int		i;
+
+	printf (" ");
+
+	for (i=1 ; i<(tokennum-1) ; i++)
+	{
+		emitanoperand (i, "", 0);
+		printf (", ");
+	}
+
+	emitanoperand (i, "", 0);
+}
+
+
+//==============================================
+
+parsefield	parsedata[] = {
+	{".align", " align", 2, emitonedata},
+	{".byte",  " db", -2, emit_multiple_data},
+	{".data",  "", 1, datasegstart},
+	{".extern"," externdef", 2, emitexterndef},
+	{".globl", " public", -2, emit_multiple_data},
+	{".long",  " dd", -2, emit_multiple_data},
+	{".single"," dd", -2, emit_multiple_data},
+	{".text",  "", 1, textsegstart},
+	{"adcl",   " adc", 3, emittwooperandsl},
+	{"addb",   " add", 3, emittwooperandsb},
+	{"addl",   " add", 3, emittwooperandsl},
+	{"andb",   " and", 3, emittwooperandsb},
+	{"andl",   " and", 3, emittwooperandsl},
+	{"call",   " call", 2, emitonecalldata},
+	{"cmpb",   " cmp", 3, emittwooperandsb},
+	{"cmpl",   " cmp", 3, emittwooperandsl},
+	{"cmpw",   " cmp", 3, emittwooperandsw},
+	{"decl",   " dec", 2, emitoneoperandl},
+	{"decw",   " dec", 2, emitoneoperandw},
+	{"divl",   " div", 2, emitoneoperandl},
+	{"fadd",   " fadd", -2, emit_1_or_2_operandsl},
+	{"faddp",  " faddp", -2, emit_1_or_2_operandsl},
+	{"faddps", " faddp", -2, emit_1_or_2_operandsl},
+	{"fadds",  " fadd", -2, emit_1_or_2_operandsl},
+	{"fcom",   " fcom", 2, emitoneoperandl},
+	{"fcoms",  " fcom", 2, emitoneoperandl},
+	{"fcomp",  " fcomp", 2, emitoneoperandl},
+	{"fcomps", " fcomp", 2, emitoneoperandl},
+	{"fdiv",   "", -2, special_fdivl}, 
+	{"fdivp",  "", -2, special_fdivpl}, 
+	{"fdivr",  "", -2, special_fdivrl},
+	{"fdivrp", "", -2, special_fdivrpl},
+	{"fdivrs", "", -2, special_fdivrl},
+	{"fildl",  " fild", 2, emitoneoperandl},
+	{"fistl",  " fist", 2, emitoneoperandl},
+	{"fistpl", " fistp", 2, emitoneoperandl},
+	{"fld",    " fld", 2, emitoneoperandl},
+	{"fldcw",  " fldcw", 2, emitoneoperandw},
+	{"fldenv", " fldenv", 2, emitoneoperandl},
+	{"flds",   " fld", 2, emitoneoperandl},
+	{"fmul",   " fmul", -2, emit_1_or_2_operandsl},
+	{"fmulp",  " fmulp", -2, emit_1_or_2_operandsl},
+	{"fmulps", " fmulp", -2, emit_1_or_2_operandsl},
+	{"fmuls",  " fmul", -2, emit_1_or_2_operandsl},
+	{"fnstcw", " fnstcw", 2, emitoneoperandw},
+	{"fnstenv"," fnstenv", 2, emitoneoperandl},
+	{"fnstsw", " fnstsw", 2, emitoneoperandw},
+	{"fstp",   " fstp", 2, emitoneoperandl},
+	{"fstps",  " fstp", 2, emitoneoperandl},
+	{"fsts",   " fst", 2, emitoneoperandl},
+	{"fsubr",  "", -2, special_fsubrl},
+	{"fsubrp", "", -2, special_fsubrpl},
+	{"fsubrs", "", -2, special_fsubrl},
+	{"fsub",   "", -2, special_fsubl},
+	{"fsubp",  "", -2, special_fsubpl},
+	{"fsubps", "", -2, special_fsubpl},
+	{"fsubs",  "", -2, special_fsubl},
+	{"fxch",   " fxch", 2, emitoneoperandl},
+	{"imull",  " imul", -2, emit_1_or_2_operandsl},
+	{"incl",   " inc", 2, emitoneoperandl},
+	{"ja",     " ja", 2, emitonedata},
+	{"jae",    " jae", 2, emitonedata},
+	{"jb",     " jb", 2, emitonedata},
+	{"jbe",    " jbe", 2, emitonedata},
+	{"jc",     " jc", 2, emitonedata},
+	{"je",     " je", 2, emitonedata},
+	{"jg",     " jg", 2, emitonedata},
+	{"jge",    " jge", 2, emitonedata},
+	{"jl",     " jl", 2, emitonedata},
+	{"jle",    " jle", 2, emitonedata},
+	{"jmp",    " jmp", 2, emitonejumpdata},
+	{"jna",    " jna", 2, emitonedata},
+	{"jnae",   " jnae", 2, emitonedata},
+	{"jnb",    " jnb", 2, emitonedata},
+	{"jnbe",   " jnbe", 2, emitonedata},
+	{"jnc",    " jnc", 2, emitonedata},
+	{"jne",    " jne", 2, emitonedata},
+	{"jng",    " jng", 2, emitonedata},
+	{"jnge",   " jnge", 2, emitonedata},
+	{"jnl",    " jnl", 2, emitonedata},
+	{"jnle",   " jnle", 2, emitonedata},
+	{"jns",    " jns", 2, emitonedata},
+	{"jnz",    " jnz", 2, emitonedata},
+	{"js",     " js", 2, emitonedata},
+	{"jz",     " jz", 2, emitonedata},
+	{"leal",   " lea", 3, emittwooperandsl},
+	{"movb",   " mov", 3, emittwooperandsb},
+	{"movl",   " mov", 3, emittwooperandsl},
+	{"movw",   " mov", 3, emittwooperandsw},
+	{"negl",   " neg", 2, emitoneoperandl},
+	{"orb",    " or", 3, emittwooperandsb},
+	{"orl",    " or", 3, emittwooperandsl},
+	{"popl",   " pop", 2, emitoneoperandl},
+	{"pushl",  " push", 2, emitoneoperandl},
+	{"ret",    " ret", -1, emit_0_or_1_operandsl},
+	{"rorl",   " ror", 3, emittwooperandsl},
+	{"sarl",   " sar", 3, emittwooperandsl},
+	{"sbbl",   " sbb", 3, emittwooperandsl},
+	{"shll",   " shl", 3, emittwooperandsl},
+	{"shrl",   " shr", 3, emittwooperandsl},	
+	{"subl",   " sub", 3, emittwooperandsl},
+	{"testb",  " test", 3, emittwooperandsb},
+	{"testl",  " test", 3, emittwooperandsl},
+	{"xorb",   " xor", 3, emittwooperandsb},
+	{"xorl",   " xor", 3, emittwooperandsl},
+};
+
+int	numparse = sizeof (parsedata) / sizeof (parsedata[0]);
+
+//==============================================
+
+void errorexit (void)
+{
+	fprintf (stderr, "In line: %d, out line: %d\n", inline, outline);
+	exit (1);
+}
+
+
+tokenstat whitespace (char c)
+{
+	if (c == '\n')
+		return LINE_DONE;
+
+	if ((c <= ' ') ||
+		(c > 127) ||
+		(c == ','))
+	{
+		return WHITESPACE;
+	}
+
+	return NOT_WHITESPACE;
+}
+
+
+int gettoken (void)
+{
+	char		c;
+	int			count, parencount;
+	tokenstat	stat;
+
+	do
+	{
+		if ((c = getchar ()) == EOF)
+			return FILE_DONE;
+
+		if ((stat = whitespace (c)) == LINE_DONE)
+			return LINE_DONE;
+	} while (stat == WHITESPACE);
+
+	token[0] = c;
+	count = 1;
+
+	if (c == '~')
+	{
+		count--;
+		token[count++] = 'n';
+		token[count++] = 'o';
+		token[count++] = 't';
+		token[count++] = ' ';
+	}
+
+	if (c == '(')
+	{
+		do
+		{
+			if ((c = getchar ()) == EOF)
+			{
+				fprintf (stderr, "EOF in middle of parentheses\n");
+				errorexit ();
+			}
+
+			token[count++] = c;
+
+		} while (c != ')');
+	}
+	
+	for ( ;; )
+	{
+		if ((c = getchar ()) == EOF)
+		{
+			token[count] = 0;
+			return TOKEN_AVAILABLE;
+		}
+
+		if (whitespace (c) == LINE_DONE)
+		{
+			if (ungetc (c, stdin) == EOF)
+			{
+				fprintf (stderr, "Couldn't unget character\n");
+				errorexit ();
+			}
+
+			token[count] = 0;
+			return TOKEN_AVAILABLE;
+		}
+
+		if (whitespace (c) == WHITESPACE)
+		{
+			token[count] = 0;
+			return TOKEN_AVAILABLE;
+		}
+
+		if (count >= MAX_TOKEN_LENGTH)
+		{
+			fprintf (stderr, "Error: token too long\n");
+			errorexit ();
+		}
+
+		token[count++] = c;
+
+		if (c == '~')
+		{
+			count--;
+			token[count++] = 'n';
+			token[count++] = 'o';
+			token[count++] = 't';
+			token[count++] = ' ';
+		}
+		else if (c == '(')
+		{
+			parencount = 1;
+
+			do
+			{
+				if ((c = getchar ()) == EOF)
+				{
+					fprintf (stderr, "EOF in middle of parentheses\n");
+					errorexit ();
+				}
+
+				if (c == '(')
+					parencount++;
+				else if (c == ')')
+					parencount--;
+
+				if (c == '~')
+				{
+					token[count++] = 'n';
+					token[count++] = 'o';
+					token[count++] = 't';
+					token[count++] = ' ';
+				}
+				else
+				{
+					token[count++] = c;
+				}
+
+			} while ((c != ')') || (parencount > 0));
+		}
+	}
+}
+
+
+tokenstat parseline (void)
+{
+	tokenstat	stat;
+	int			i, j, firsttoken, labelfound;
+	int			mnemfound;
+
+	firsttoken = 1;
+	tokennum = 0;
+	labelfound = 0;
+
+	for ( ;; )
+	{
+		token = tokens[tokennum];
+		stat = gettoken ();
+
+		switch (stat)
+		{
+		case FILE_DONE:
+			return FILE_DONE;
+
+		case LINE_DONE:
+			if (!firsttoken && tokennum)
+			{
+				mnemfound = 0;
+
+				for (i=0 ; i<numparse; i++)
+				{
+					if (!strcmpi (tokens[0], parsedata[i].text))
+					{
+						if (((parsedata[i].numtokens > 0) &&
+							 (parsedata[i].numtokens != tokennum)) ||
+							((parsedata[i].numtokens < 0) &&
+							 (tokennum < -parsedata[i].numtokens)))
+						{
+							fprintf (stderr, "mismatched number of tokens\n");
+
+							for (j=0 ; j<tokennum ; j++)
+								fprintf (stderr, "%s\n", tokens[j]);
+
+							fprintf (stderr, "\n");
+							errorexit ();
+						}
+
+						printf ("%s", parsedata[i].emit);
+						(*parsedata[i].parsefunc) ();
+
+						mnemfound = 1;
+						break;
+					}
+				}
+
+				if (!mnemfound)
+				{
+					fprintf (stderr, "Error: unknown mnemonic\n");
+
+					for (j=0 ; j<tokennum ; j++)
+						fprintf (stderr, "%s\n", tokens[j]);
+
+					fprintf (stderr, "\n");
+					errorexit ();
+				}
+			}
+
+			if (!firsttoken)
+			{
+				if ((currentseg == DATASEG) && labelfound && !tokennum)
+					printf (":\n");
+				else
+					printf ("\n");
+
+				outline++;
+			}
+			return PARSED_OKAY;
+
+		case TOKEN_AVAILABLE:
+			if (firsttoken)
+			{
+				if (token[strlen(token) - 1] == ':')
+				{
+					labelfound = 1;
+
+					if (currentseg == DATASEG)
+					{
+						token[strlen(token) - 1] = 0;
+						printf ("%s", token);
+					}
+					else if (currentseg == TEXTSEG)
+					{
+						printf ("%s", token);
+					}
+					else
+					{
+						fprintf (stderr, "Error: not in segment block\n");
+						errorexit ();
+					}
+
+					firsttoken = 0;
+					break;
+				}
+			}
+
+			firsttoken = 0;
+
+			if (tokennum >= MAX_TOKENS)
+			{
+				fprintf (stderr, "Error: too many tokens\n");
+				exit (0);
+			}
+
+			tokennum++;
+
+			break;
+
+		default:
+			fprintf (stderr, "Error: unknown tokenstat %d\n", stat);
+			exit (0);
+		}
+	}
+}
+
+
+void main (int argc, char **argv)
+{
+	tokenstat	stat;
+
+	printf (" .386P\n"
+            " .model FLAT\n");
+	inline = 1;
+	outline = 3;
+
+	for ( ;; )
+	{
+		stat = parseline ();
+		inline++;
+
+		switch (stat)
+		{
+		case FILE_DONE:
+			if (currentseg == TEXTSEG)
+				printf ("_TEXT ENDS\n");
+			else if (currentseg == DATASEG)
+				printf ("_DATA ENDS\n");
+
+			printf (" END\n");
+			exit (0);
+		
+		case PARSED_OKAY:
+			break;
+
+		default:
+			fprintf (stderr, "Error: unknown tokenstat %d\n", stat);
+			exit (0);
+		}
+	}
+}
+
--- /dev/null
+++ b/QW/gas2masm/gas2masm.dsp
@@ -1,0 +1,102 @@
+# Microsoft Developer Studio Project File - Name="gas2masm" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=gas2masm - Win32 Release
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "gas2masm.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "gas2masm.mak" CFG="gas2masm - Win32 Release"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "gas2masm - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "gas2masm - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE 
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "gas2masm - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir ".\Release"
+# PROP BASE Intermediate_Dir ".\Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir ".\Release"
+# PROP Intermediate_Dir ".\Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /c
+# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+
+!ELSEIF  "$(CFG)" == "gas2masm - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir ".\Debug"
+# PROP BASE Intermediate_Dir ".\Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir ".\Debug"
+# PROP Intermediate_Dir ".\Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /YX /c
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386
+
+!ENDIF 
+
+# Begin Target
+
+# Name "gas2masm - Win32 Release"
+# Name "gas2masm - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;hpj;bat;for;f90"
+# Begin Source File
+
+SOURCE=.\gas2masm.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
--- /dev/null
+++ b/QW/gas2masm/gas2masm.mak
@@ -1,0 +1,193 @@
+# Microsoft Developer Studio Generated NMAKE File, Format Version 4.20
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+!IF "$(CFG)" == ""
+CFG=gas2masm - Win32 Debug
+!MESSAGE No configuration specified.  Defaulting to gas2masm - Win32 Debug.
+!ENDIF 
+
+!IF "$(CFG)" != "gas2masm - Win32 Release" && "$(CFG)" !=\
+ "gas2masm - Win32 Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE on this makefile
+!MESSAGE by defining the macro CFG on the command line.  For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "gas2masm.mak" CFG="gas2masm - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "gas2masm - Win32 Release" (based on\
+ "Win32 (x86) Console Application")
+!MESSAGE "gas2masm - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE 
+!ERROR An invalid configuration is specified.
+!ENDIF 
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE 
+NULL=nul
+!ENDIF 
+################################################################################
+# Begin Project
+# PROP Target_Last_Scanned "gas2masm - Win32 Debug"
+RSC=rc.exe
+CPP=cl.exe
+
+!IF  "$(CFG)" == "gas2masm - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Target_Dir ""
+OUTDIR=.\Release
+INTDIR=.\Release
+
+ALL : "$(OUTDIR)\gas2masm.exe"
+
+CLEAN : 
+	-@erase "$(INTDIR)\gas2masm.obj"
+	-@erase "$(OUTDIR)\gas2masm.exe"
+
+"$(OUTDIR)" :
+    if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /c
+# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /c
+CPP_PROJ=/nologo /ML /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE"\
+ /Fp"$(INTDIR)/gas2masm.pch" /YX /Fo"$(INTDIR)/" /c 
+CPP_OBJS=.\Release/
+CPP_SBRS=.\.
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+BSC32_FLAGS=/nologo /o"$(OUTDIR)/gas2masm.bsc" 
+BSC32_SBRS= \
+	
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\
+ advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib\
+ odbccp32.lib /nologo /subsystem:console /incremental:no\
+ /pdb:"$(OUTDIR)/gas2masm.pdb" /machine:I386 /out:"$(OUTDIR)/gas2masm.exe" 
+LINK32_OBJS= \
+	"$(INTDIR)\gas2masm.obj"
+
+"$(OUTDIR)\gas2masm.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+    $(LINK32) @<<
+  $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ELSEIF  "$(CFG)" == "gas2masm - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Target_Dir ""
+OUTDIR=.\Debug
+INTDIR=.\Debug
+
+ALL : "$(OUTDIR)\gas2masm.exe"
+
+CLEAN : 
+	-@erase "$(INTDIR)\gas2masm.obj"
+	-@erase "$(INTDIR)\vc40.idb"
+	-@erase "$(INTDIR)\vc40.pdb"
+	-@erase "$(OUTDIR)\gas2masm.exe"
+	-@erase "$(OUTDIR)\gas2masm.ilk"
+	-@erase "$(OUTDIR)\gas2masm.pdb"
+
+"$(OUTDIR)" :
+    if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /YX /c
+# ADD CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /YX /c
+CPP_PROJ=/nologo /MLd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE"\
+ /Fp"$(INTDIR)/gas2masm.pch" /YX /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c 
+CPP_OBJS=.\Debug/
+CPP_SBRS=.\.
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+BSC32_FLAGS=/nologo /o"$(OUTDIR)/gas2masm.bsc" 
+BSC32_SBRS= \
+	
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386
+LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\
+ advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib\
+ odbccp32.lib /nologo /subsystem:console /incremental:yes\
+ /pdb:"$(OUTDIR)/gas2masm.pdb" /debug /machine:I386\
+ /out:"$(OUTDIR)/gas2masm.exe" 
+LINK32_OBJS= \
+	"$(INTDIR)\gas2masm.obj"
+
+"$(OUTDIR)\gas2masm.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+    $(LINK32) @<<
+  $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ENDIF 
+
+.c{$(CPP_OBJS)}.obj:
+   $(CPP) $(CPP_PROJ) $<  
+
+.cpp{$(CPP_OBJS)}.obj:
+   $(CPP) $(CPP_PROJ) $<  
+
+.cxx{$(CPP_OBJS)}.obj:
+   $(CPP) $(CPP_PROJ) $<  
+
+.c{$(CPP_SBRS)}.sbr:
+   $(CPP) $(CPP_PROJ) $<  
+
+.cpp{$(CPP_SBRS)}.sbr:
+   $(CPP) $(CPP_PROJ) $<  
+
+.cxx{$(CPP_SBRS)}.sbr:
+   $(CPP) $(CPP_PROJ) $<  
+
+################################################################################
+# Begin Target
+
+# Name "gas2masm - Win32 Release"
+# Name "gas2masm - Win32 Debug"
+
+!IF  "$(CFG)" == "gas2masm - Win32 Release"
+
+!ELSEIF  "$(CFG)" == "gas2masm - Win32 Debug"
+
+!ENDIF 
+
+################################################################################
+# Begin Source File
+
+SOURCE=.\gas2masm.c
+
+"$(INTDIR)\gas2masm.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+# End Target
+# End Project
+################################################################################
binary files /dev/null b/QW/gas2masm/gas2masm.mdp differ
--- /dev/null
+++ b/QW/gas2masm/gas2masm.plg
@@ -1,0 +1,32 @@
+<html>
+<body>
+<pre>
+<h1>Build Log</h1>
+<h3>
+--------------------Configuration: gas2masm - Win32 Debug--------------------
+</h3>
+<h3>Command Lines</h3>
+Creating temporary file "C:\TEMP\RSP712.tmp" with contents
+[
+/nologo /MLd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /Fp".\Debug/gas2masm.pch" /YX /Fo".\Debug/" /Fd".\Debug/" /FD /c 
+"D:\Work\quake source\QW\gas2masm\gas2masm.c"
+]
+Creating command line "cl.exe @C:\TEMP\RSP712.tmp" 
+Creating temporary file "C:\TEMP\RSP713.tmp" with contents
+[
+kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /incremental:yes /pdb:".\Debug/gas2masm.pdb" /debug /machine:I386 /out:".\Debug/gas2masm.exe" 
+".\Debug\gas2masm.obj"
+]
+Creating command line "link.exe @C:\TEMP\RSP713.tmp"
+<h3>Output Window</h3>
+Compiling...
+gas2masm.c
+Linking...
+
+
+
+<h3>Results</h3>
+gas2masm.exe - 0 error(s), 0 warning(s)
+</pre>
+</body>
+</html>
--- /dev/null
+++ b/QW/glqwcl.3dfxgl
@@ -1,0 +1,9 @@
+#!/bin/sh
+
+# This script preloads the lib3dfxgl.so library which overrides the functions
+# present in libMesaGL.so.  This allows glquake to run using 3DFX's miniport
+# and without Mesa 3-D.  Glide and X11 libraries have to be installed tho, 
+# even tho GLQuake doesn't use X11, it's linked against it because Mesa 3-D
+# requires them.
+
+LD_PRELOAD=./lib3dfxgl.so ./glqwcl $*
--- /dev/null
+++ b/QW/glqwcl.spec.sh
@@ -1,0 +1,45 @@
+#!/bin/sh
+# Generate qwcl.spec
+# $1 is version
+# $2 is release
+# $3 is install dir (assumed to be in /var/tmp)
+cat <<EOF
+%define name glqwcl
+%define version ${1}
+%define release ${2}
+%define builddir \$RPM_BUILD_DIR/%{name}-%{version}
+Name:		%{name}
+Version:	%{version}
+Release:	%{release}
+Vendor:		id Software
+Packager:	Dave "Zoid" Kirsch <zoid@idsoftware.com>
+URL:		http://www.idsoftware.com/
+Source:		glqwcl-%{version}.tar.gz
+Group:		Games
+Copyright:	Restricted
+Icon:		quake.gif
+BuildRoot:	/var/tmp/%{name}-%{version}
+Summary:	OpenGL QuakeWorld Client
+
+%description
+"Quake is the biggest, baddest, and bloodiest 3-D action game ever 
+conceived" - PC GAMER
+
+"The most important PC game ever" - PC ZONE
+
+""Quake": Bloody Amazing" - USA TODAY
+
+"The Vanguard of a terrifying new level of immersive interactivity" - 
+COMPUTER GAMING WORLD
+
+%install
+
+%files
+%attr(644,root,root) ${3}/readme.glqwcl
+%attr(4755,root,root) ${3}/glqwcl
+%attr(4755,root,root) ${3}/glqwcl.glx
+%attr(755,root,root) ${3}/glqwcl.3dfxgl
+%attr(755,root,root) ${3}/lib3dfxgl.so
+EOF
+
+
binary files /dev/null b/QW/makezip differ
--- /dev/null
+++ b/QW/makezip.bat
@@ -1,0 +1,1 @@
+zip -9 -r -D -X qw client server docs dxsdk gas2masm progs scitech -x *.obj *.sbr *.pch *.pdb *.idb *.bsc *.dll *.exp *.exe  *.lib *.map *.ilk
--- /dev/null
+++ b/QW/progs/buttons.qc
@@ -1,0 +1,141 @@
+// button and multiple button
+
+void() button_wait;
+void() button_return;
+
+void() button_wait =
+{
+	self.state = STATE_TOP;
+	self.nextthink = self.ltime + self.wait;
+	self.think = button_return;
+	activator = self.enemy;
+	SUB_UseTargets();
+	self.frame = 1;			// use alternate textures
+};
+
+void() button_done =
+{
+	self.state = STATE_BOTTOM;
+};
+
+void() button_return =
+{
+	self.state = STATE_DOWN;
+	SUB_CalcMove (self.pos1, self.speed, button_done);
+	self.frame = 0;			// use normal textures
+	if (self.health)
+		self.takedamage = DAMAGE_YES;	// can be shot again
+};
+
+
+void() button_blocked =
+{	// do nothing, just don't ome all the way back out
+};
+
+
+void() button_fire =
+{
+	if (self.state == STATE_UP || self.state == STATE_TOP)
+		return;
+
+	sound (self, CHAN_VOICE, self.noise, 1, ATTN_NORM);
+
+	self.state = STATE_UP;
+	SUB_CalcMove (self.pos2, self.speed, button_wait);
+};
+
+
+void() button_use =
+{
+	self.enemy = activator;
+	button_fire ();
+};
+
+void() button_touch =
+{
+	if (other.classname != "player")
+		return;
+	self.enemy = other;
+	button_fire ();
+};
+
+void() button_killed =
+{
+	self.enemy = damage_attacker;
+	self.health = self.max_health;
+	self.takedamage = DAMAGE_NO;	// wil be reset upon return
+	button_fire ();
+};
+
+
+/*QUAKED func_button (0 .5 .8) ?
+When a button is touched, it moves some distance in the direction of it's angle, triggers all of it's targets, waits some time, then returns to it's original position where it can be triggered again.
+
+"angle"		determines the opening direction
+"target"	all entities with a matching targetname will be used
+"speed"		override the default 40 speed
+"wait"		override the default 1 second wait (-1 = never return)
+"lip"		override the default 4 pixel lip remaining at end of move
+"health"	if set, the button must be killed instead of touched
+"sounds"
+0) steam metal
+1) wooden clunk
+2) metallic click
+3) in-out
+*/
+void() func_button =
+{
+local float		gtemp, ftemp;
+
+	if (self.sounds == 0)
+	{
+		precache_sound ("buttons/airbut1.wav");
+		self.noise = "buttons/airbut1.wav";
+	}
+	if (self.sounds == 1)
+	{
+		precache_sound ("buttons/switch21.wav");
+		self.noise = "buttons/switch21.wav";
+	}
+	if (self.sounds == 2)
+	{
+		precache_sound ("buttons/switch02.wav");
+		self.noise = "buttons/switch02.wav";
+	}
+	if (self.sounds == 3)
+	{
+		precache_sound ("buttons/switch04.wav");
+		self.noise = "buttons/switch04.wav";
+	}
+	
+	SetMovedir ();
+
+	self.movetype = MOVETYPE_PUSH;
+	self.solid = SOLID_BSP;
+	setmodel (self, self.model);
+
+	self.blocked = button_blocked;
+	self.use = button_use;
+
+	if (self.health)
+	{
+		self.max_health = self.health;
+		self.th_die = button_killed;
+		self.takedamage = DAMAGE_YES;
+	}
+	else
+		self.touch = button_touch;
+
+	if (!self.speed)
+		self.speed = 40;
+	if (!self.wait)
+		self.wait = 1;
+	if (!self.lip)
+		self.lip = 4;
+
+	self.state = STATE_BOTTOM;
+
+	self.pos1 = self.origin;
+	self.pos2 = self.pos1 + self.movedir*(fabs(self.movedir*self.size) - self.lip);
+};
+
--- /dev/null
+++ b/QW/progs/client.qc
@@ -1,0 +1,1498 @@
+
+// prototypes
+void () W_WeaponFrame;
+void() W_SetCurrentAmmo;
+void() player_pain;
+void() player_stand1;
+void (vector org) spawn_tfog;
+void (vector org, entity death_owner) spawn_tdeath;
+
+float   modelindex_eyes, modelindex_player;
+
+/*
+=============================================================================
+
+				LEVEL CHANGING / INTERMISSION
+
+=============================================================================
+*/
+
+string nextmap;
+
+float   intermission_running;
+float   intermission_exittime;
+
+/*QUAKED info_intermission (1 0.5 0.5) (-16 -16 -16) (16 16 16)
+This is the camera point for the intermission.
+Use mangle instead of angle, so you can set pitch or roll as well as yaw.  'pitch roll yaw'
+*/
+void() info_intermission =
+{
+	self.angles = self.mangle;      // so C can get at it
+};
+
+
+
+void() SetChangeParms =
+{
+	if (self.health <= 0)
+	{
+		SetNewParms ();
+		return;
+	}
+ 
+// remove items
+	self.items = self.items - (self.items & 
+	(IT_KEY1 | IT_KEY2 | IT_INVISIBILITY | IT_INVULNERABILITY | IT_SUIT | IT_QUAD) );
+	
+// cap super health
+	if (self.health > 100)
+		self.health = 100;
+	if (self.health < 50)
+		self.health = 50;
+	parm1 = self.items;
+	parm2 = self.health;
+	parm3 = self.armorvalue;
+	if (self.ammo_shells < 25)
+		parm4 = 25;
+	else
+		parm4 = self.ammo_shells;
+	parm5 = self.ammo_nails;
+	parm6 = self.ammo_rockets;
+	parm7 = self.ammo_cells;
+	parm8 = self.weapon;
+	parm9 = self.armortype * 100;
+};
+
+void() SetNewParms =
+{
+	parm1 = IT_SHOTGUN | IT_AXE;
+	parm2 = 100;
+	parm3 = 0;
+	parm4 = 25;
+	parm5 = 0;
+	parm6 = 0;
+	parm7 = 0;
+	parm8 = 1;
+	parm9 = 0;
+};
+
+void() DecodeLevelParms =
+{
+	if (serverflags)
+	{
+		if (world.model == "maps/start.bsp")
+			SetNewParms ();         // take away all stuff on starting new episode
+	}
+	
+	self.items = parm1;
+	self.health = parm2;
+	self.armorvalue = parm3;
+	self.ammo_shells = parm4;
+	self.ammo_nails = parm5;
+	self.ammo_rockets = parm6;
+	self.ammo_cells = parm7;
+	self.weapon = parm8;
+	self.armortype = parm9 * 0.01;
+};
+
+/*
+============
+FindIntermission
+
+Returns the entity to view from
+============
+*/
+entity() FindIntermission =
+{
+	local   entity spot;
+	local   float cyc;
+
+// look for info_intermission first
+	spot = find (world, classname, "info_intermission");
+	if (spot)
+	{       // pick a random one
+		cyc = random() * 4;
+		while (cyc > 1)
+		{
+			spot = find (spot, classname, "info_intermission");
+			if (!spot)
+				spot = find (spot, classname, "info_intermission");
+			cyc = cyc - 1;
+		}
+		return spot;
+	}
+
+// then look for the start position
+	spot = find (world, classname, "info_player_start");
+	if (spot)
+		return spot;
+	
+	objerror ("FindIntermission: no spot");
+};
+
+
+void() GotoNextMap =
+{
+	local string newmap;
+
+//ZOID: 12-13-96, samelevel is overloaded, only 1 works for same level
+
+	if (cvar("samelevel") == 1)     // if samelevel is set, stay on same level
+		changelevel (mapname);
+	else {
+		// configurable map lists, see if the current map exists as a
+		// serverinfo/localinfo var
+		newmap = infokey(world, mapname);
+		if (newmap != "")
+			changelevel (newmap);
+		else
+			changelevel (nextmap);
+	}
+};
+
+
+
+/*
+============
+IntermissionThink
+
+When the player presses attack or jump, change to the next level
+============
+*/
+void() IntermissionThink =
+{
+	if (time < intermission_exittime)
+		return;
+
+	if (!self.button0 && !self.button1 && !self.button2)
+		return;
+	
+	GotoNextMap ();
+};
+
+/*
+============
+execute_changelevel
+
+The global "nextmap" has been set previously.
+Take the players to the intermission spot
+============
+*/
+void() execute_changelevel =
+{
+	local entity    pos;
+
+	intermission_running = 1;
+	
+// enforce a wait time before allowing changelevel
+	intermission_exittime = time + 5;
+
+	pos = FindIntermission ();
+
+// play intermission music
+	WriteByte (MSG_ALL, SVC_CDTRACK);
+	WriteByte (MSG_ALL, 3);
+
+	WriteByte (MSG_ALL, SVC_INTERMISSION);
+	WriteCoord (MSG_ALL, pos.origin_x);
+	WriteCoord (MSG_ALL, pos.origin_y);
+	WriteCoord (MSG_ALL, pos.origin_z);
+	WriteAngle (MSG_ALL, pos.mangle_x);
+	WriteAngle (MSG_ALL, pos.mangle_y);
+	WriteAngle (MSG_ALL, pos.mangle_z);
+	
+	other = find (world, classname, "player");
+	while (other != world)
+	{
+		other.takedamage = DAMAGE_NO;
+		other.solid = SOLID_NOT;
+		other.movetype = MOVETYPE_NONE;
+		other.modelindex = 0;
+		other = find (other, classname, "player");
+	}       
+
+};
+
+
+void() changelevel_touch =
+{
+	local entity    pos;
+
+	if (other.classname != "player")
+		return;
+
+// if "noexit" is set, blow up the player trying to leave
+//ZOID, 12-13-96, noexit isn't supported in QW.  Overload samelevel
+//      if ((cvar("noexit") == 1) || ((cvar("noexit") == 2) && (mapname != "start")))
+	if ((cvar("samelevel") == 2) || ((cvar("samelevel") == 3) && (mapname != "start")))
+	{
+		T_Damage (other, self, self, 50000);
+		return;
+	}
+
+	bprint (PRINT_HIGH, other.netname);
+	bprint (PRINT_HIGH," exited the level\n");
+	
+	nextmap = self.map;
+
+	SUB_UseTargets ();
+
+	self.touch = SUB_Null;
+
+// we can't move people right now, because touch functions are called
+// in the middle of C movement code, so set a think time to do it
+	self.think = execute_changelevel;
+	self.nextthink = time + 0.1;
+};
+
+/*QUAKED trigger_changelevel (0.5 0.5 0.5) ? NO_INTERMISSION
+When the player touches this, he gets sent to the map listed in the "map" variable.  Unless the NO_INTERMISSION flag is set, the view will go to the info_intermission spot and display stats.
+*/
+void() trigger_changelevel =
+{
+	if (!self.map)
+		objerror ("chagnelevel trigger doesn't have map");
+	
+	InitTrigger ();
+	self.touch = changelevel_touch;
+};
+
+
+/*
+=============================================================================
+
+				PLAYER GAME EDGE FUNCTIONS
+
+=============================================================================
+*/
+
+void() set_suicide_frame;
+
+// called by ClientKill and DeadThink
+void() respawn =
+{
+	// make a copy of the dead body for appearances sake
+	CopyToBodyQue (self);
+	// set default spawn parms
+	SetNewParms ();
+	// respawn              
+	PutClientInServer ();
+};
+
+
+/*
+============
+ClientKill
+
+Player entered the suicide command
+============
+*/
+void() ClientKill =
+{
+	bprint (PRINT_MEDIUM, self.netname);
+	bprint (PRINT_MEDIUM, " suicides\n");
+	set_suicide_frame ();
+	self.modelindex = modelindex_player;
+	logfrag (self, self);
+	self.frags = self.frags - 2;    // extra penalty
+	respawn ();
+};
+
+float(vector v) CheckSpawnPoint =
+{
+	return FALSE;
+};
+
+/*
+============
+SelectSpawnPoint
+
+Returns the entity to spawn at
+============
+*/
+entity() SelectSpawnPoint =
+{
+	local   entity spot, newspot, thing;
+	local   float   numspots, totalspots;
+	local   float   rnum, pcount;
+	local   float   rs;
+	local entity spots;
+
+	numspots = 0;
+	totalspots = 0;
+
+// testinfo_player_start is only found in regioned levels
+	spot = find (world, classname, "testplayerstart");
+	if (spot)
+		return spot;
+		
+// choose a info_player_deathmatch point
+
+// ok, find all spots that don't have players nearby
+
+	spots = world;
+	spot = find (world, classname, "info_player_deathmatch");       
+	while (spot)
+	{
+		totalspots = totalspots + 1;
+
+		thing=findradius(spot.origin, 84);
+		pcount=0;               
+		while (thing)
+		{
+			if (thing.classname == "player")
+				pcount=pcount + 1;                      
+			thing=thing.chain;      
+		}
+		if (pcount == 0) {
+			spot.goalentity = spots;
+			spots = spot;
+			numspots = numspots + 1;
+		}
+
+		// Get the next spot in the chain
+		spot = find (spot, classname, "info_player_deathmatch");                
+	}
+	totalspots=totalspots - 1;
+	if (!numspots) {
+		// ack, they are all full, just pick one at random
+//		bprint (PRINT_HIGH, "Ackk! All spots are full. Selecting random spawn spot\n");
+		totalspots = rint((random() * totalspots));
+		spot = find (world, classname, "info_player_deathmatch");       
+		while (totalspots > 0) {
+			totalspots = totalspots - 1;
+			spot = find (spot, classname, "info_player_deathmatch");
+		}
+		return spot;
+	}
+		
+// We now have the number of spots available on the map in numspots
+
+	// Generate a random number between 1 and numspots
+
+	numspots = numspots - 1;
+	
+	numspots = rint((random() * numspots ) );
+
+	spot = spots;
+	while (numspots > 0) {
+		spot = spot.goalentity;
+		numspots = numspots - 1;
+	}
+	return spot;
+
+};
+void() DecodeLevelParms;
+void() PlayerDie;
+
+/*
+===========
+ValidateUser
+
+
+============
+*/
+float(entity e) ValidateUser =
+{
+/*
+	local string    s;
+	local string    userclan;
+	local float     rank, rankmin, rankmax;
+
+//
+// if the server has set "clan1" and "clan2", then it
+// is a clan match that will allow only those two clans in
+//
+	s = serverinfo("clan1");
+	if (s)
+	{
+		userclan = masterinfo(e,"clan");
+		if (s == userclan)
+			return true;
+		s = serverinfo("clan2");
+		if (s == userclan)
+			return true;
+		return false;
+	}
+
+//
+// if the server has set "rankmin" and/or "rankmax" then
+// the users rank must be between those two values
+//
+	s = masterinfo (e, "rank");
+	rank = stof (s);
+
+	s = serverinfo("rankmin");
+	if (s)
+	{
+		rankmin = stof (s);
+		if (rank < rankmin)
+			return false;
+	}
+	s = serverinfo("rankmax");
+	if (s)
+	{
+		rankmax = stof (s);
+		if (rankmax < rank)
+			return false;
+	}
+
+	return true;
+*/
+};
+
+
+/*
+===========
+PutClientInServer
+
+called each time a player enters a new level
+============
+*/
+void() PutClientInServer =
+{
+	local   entity spot;
+	local 	string	s;
+
+	self.classname = "player";
+	self.health = 100;
+	self.takedamage = DAMAGE_AIM;
+	self.solid = SOLID_SLIDEBOX;
+	self.movetype = MOVETYPE_WALK;
+	self.show_hostile = 0;
+	self.max_health = 100;
+	self.flags = FL_CLIENT;
+	self.air_finished = time + 12;
+	self.dmg = 2;                   // initial water damage
+	self.super_damage_finished = 0;
+	self.radsuit_finished = 0;
+	self.invisible_finished = 0;
+	self.invincible_finished = 0;
+	self.effects = 0;
+	self.invincible_time = 0;
+
+	DecodeLevelParms ();
+	
+	W_SetCurrentAmmo ();
+
+	self.attack_finished = time;
+	self.th_pain = player_pain;
+	self.th_die = PlayerDie;
+	
+	self.deadflag = DEAD_NO;
+// paustime is set by teleporters to keep the player from moving a while
+	self.pausetime = 0;
+	
+	spot = SelectSpawnPoint ();
+
+	self.origin = spot.origin + '0 0 1';
+	self.angles = spot.angles;
+	self.fixangle = TRUE;           // turn this way immediately
+
+// oh, this is a hack!
+	setmodel (self, "progs/eyes.mdl");
+	modelindex_eyes = self.modelindex;
+
+	setmodel (self, "progs/player.mdl");
+	modelindex_player = self.modelindex;
+
+	setsize (self, VEC_HULL_MIN, VEC_HULL_MAX);
+	
+	self.view_ofs = '0 0 22';
+
+// Mod - Xian (May.20.97)
+// Bug where player would have velocity from their last kill
+
+	self.velocity = '0 0 0';
+
+	player_stand1 ();
+	
+	makevectors(self.angles);
+	spawn_tfog (self.origin + v_forward*20);
+
+	spawn_tdeath (self.origin, self);
+
+	// Set Rocket Jump Modifiers
+	if (stof(infokey(world, "rj")) != 0)
+	{                
+		rj = stof(infokey(world, "rj"));
+	}
+
+	if (deathmatch == 4)
+	{
+		self.ammo_shells = 0;
+		if (stof(infokey(world, "axe")) == 0)
+		{
+			self.ammo_nails = 255;
+			self.ammo_shells = 255;
+			self.ammo_rockets = 255;
+			self.ammo_cells = 255;
+			self.items = self.items | IT_NAILGUN;
+			self.items = self.items | IT_SUPER_NAILGUN;
+			self.items = self.items | IT_SUPER_SHOTGUN;
+			self.items = self.items | IT_ROCKET_LAUNCHER;
+//		self.items = self.items | IT_GRENADE_LAUNCHER;
+			self.items = self.items | IT_LIGHTNING;
+		}
+		self.items = self.items - (self.items & (IT_ARMOR1 | IT_ARMOR2 | IT_ARMOR3)) + IT_ARMOR3;
+		self.armorvalue = 200;
+		self.armortype = 0.8;
+		self.health = 250;
+		self.items = self.items | IT_INVULNERABILITY;
+		self.invincible_time = 1;
+		self.invincible_finished = time + 3;
+	}
+
+	if (deathmatch == 5)
+	{
+		self.ammo_nails = 80;
+		self.ammo_shells = 30;
+		self.ammo_rockets = 10;
+		self.ammo_cells = 30;
+		self.items = self.items | IT_NAILGUN;
+		self.items = self.items | IT_SUPER_NAILGUN;
+		self.items = self.items | IT_SUPER_SHOTGUN;
+		self.items = self.items | IT_ROCKET_LAUNCHER;
+		self.items = self.items | IT_GRENADE_LAUNCHER;
+		self.items = self.items | IT_LIGHTNING;
+		self.items = self.items - (self.items & (IT_ARMOR1 | IT_ARMOR2 | IT_ARMOR3)) + IT_ARMOR3;
+		self.armorvalue = 200;
+		self.armortype = 0.8;
+		self.health = 200;
+		self.items = self.items | IT_INVULNERABILITY;
+		self.invincible_time = 1;
+		self.invincible_finished = time + 3;
+	}
+
+
+};
+
+
+/*
+=============================================================================
+
+				QUAKED FUNCTIONS
+
+=============================================================================
+*/
+
+
+/*QUAKED info_player_start (1 0 0) (-16 -16 -24) (16 16 24)
+The normal starting point for a level.
+*/
+void() info_player_start =
+{
+};
+
+
+/*QUAKED info_player_start2 (1 0 0) (-16 -16 -24) (16 16 24)
+Only used on start map for the return point from an episode.
+*/
+void() info_player_start2 =
+{
+};
+
+/*QUAKED info_player_deathmatch (1 0 1) (-16 -16 -24) (16 16 24)
+potential spawning position for deathmatch games
+*/
+void() info_player_deathmatch =
+{
+};
+
+/*QUAKED info_player_coop (1 0 1) (-16 -16 -24) (16 16 24)
+potential spawning position for coop games
+*/
+void() info_player_coop =
+{
+};
+
+/*
+===============================================================================
+
+RULES
+
+===============================================================================
+*/
+
+/*
+go to the next level for deathmatch
+*/
+void() NextLevel =
+{
+	local entity o;
+	local string newmap;
+
+	if (nextmap != "")
+		return; // already done
+
+	if (mapname == "start")
+	{
+		if (!cvar("registered"))
+		{
+			mapname = "e1m1";
+		}
+		else if (!(serverflags & 1))
+		{
+			mapname = "e1m1";
+			serverflags = serverflags | 1;
+		}
+		else if (!(serverflags & 2))
+		{
+			mapname = "e2m1";
+			serverflags = serverflags | 2;
+		}
+		else if (!(serverflags & 4))
+		{
+			mapname = "e3m1";
+			serverflags = serverflags | 4;
+		}
+		else if (!(serverflags & 8))
+		{
+			mapname = "e4m1";
+			serverflags = serverflags - 7;
+		}
+ 
+		o = spawn();
+		o.map = mapname;
+	}
+	else
+	{
+		// find a trigger changelevel
+		o = find(world, classname, "trigger_changelevel");
+		if (!o || mapname == "start")
+		{       // go back to same map if no trigger_changelevel
+			o = spawn();
+			o.map = mapname;
+		}
+	}
+
+	nextmap = o.map;
+
+	if (o.nextthink < time)
+	{
+		o.think = execute_changelevel;
+		o.nextthink = time + 0.1;
+	}
+};
+
+/*
+============
+CheckRules
+
+Exit deathmatch games upon conditions
+============
+*/
+void() CheckRules =
+{       
+	if (timelimit && time >= timelimit)
+		NextLevel ();
+	
+	if (fraglimit && self.frags >= fraglimit)
+		NextLevel ();
+};
+
+//============================================================================
+
+void() PlayerDeathThink =
+{
+	local entity    old_self;
+	local float             forward;
+
+	if ((self.flags & FL_ONGROUND))
+	{
+		forward = vlen (self.velocity);
+		forward = forward - 20;
+		if (forward <= 0)
+			self.velocity = '0 0 0';
+		else    
+			self.velocity = forward * normalize(self.velocity);
+	}
+
+// wait for all buttons released
+	if (self.deadflag == DEAD_DEAD)
+	{
+		if (self.button2 || self.button1 || self.button0)
+			return;
+		self.deadflag = DEAD_RESPAWNABLE;
+		return;
+	}
+
+// wait for any button down
+	if (!self.button2 && !self.button1 && !self.button0)
+		return;
+
+	self.button0 = 0;
+	self.button1 = 0;
+	self.button2 = 0;
+	respawn();
+};
+
+
+void() PlayerJump =
+{
+	local vector start, end;
+
+	if (self.flags & FL_WATERJUMP)
+		return;
+	
+	if (self.waterlevel >= 2)
+	{
+// play swiming sound
+		if (self.swim_flag < time)
+		{
+			self.swim_flag = time + 1;
+			if (random() < 0.5)
+				sound (self, CHAN_BODY, "misc/water1.wav", 1, ATTN_NORM);
+			else
+				sound (self, CHAN_BODY, "misc/water2.wav", 1, ATTN_NORM);
+		}
+
+		return;
+	}
+
+	if (!(self.flags & FL_ONGROUND))
+		return;
+
+	if ( !(self.flags & FL_JUMPRELEASED) )
+		return;         // don't pogo stick
+
+	self.flags = self.flags - (self.flags & FL_JUMPRELEASED);       
+	self.button2 = 0;
+
+// player jumping sound
+	sound (self, CHAN_BODY, "player/plyrjmp8.wav", 1, ATTN_NORM);
+};
+
+
+/*
+===========
+WaterMove
+
+============
+*/
+.float  dmgtime;
+
+void() WaterMove =
+{
+//dprint (ftos(self.waterlevel));
+	if (self.movetype == MOVETYPE_NOCLIP)
+		return;
+	if (self.health < 0)
+		return;
+
+	if (self.waterlevel != 3)
+	{
+		if (self.air_finished < time)
+			sound (self, CHAN_VOICE, "player/gasp2.wav", 1, ATTN_NORM);
+		else if (self.air_finished < time + 9)
+			sound (self, CHAN_VOICE, "player/gasp1.wav", 1, ATTN_NORM);
+		self.air_finished = time + 12;
+		self.dmg = 2;
+	}
+	else if (self.air_finished < time)
+	{       // drown!
+		if (self.pain_finished < time)
+		{
+			self.dmg = self.dmg + 2;
+			if (self.dmg > 15)
+				self.dmg = 10;
+			T_Damage (self, world, world, self.dmg);
+			self.pain_finished = time + 1;
+		}
+	}
+	
+	if (!self.waterlevel)
+	{
+		if (self.flags & FL_INWATER)
+		{       
+			// play leave water sound
+			sound (self, CHAN_BODY, "misc/outwater.wav", 1, ATTN_NORM);
+			self.flags = self.flags - FL_INWATER;
+		}
+		return;
+	}
+
+	if (self.watertype == CONTENT_LAVA)
+	{       // do damage
+		if (self.dmgtime < time)
+		{
+			if (self.radsuit_finished > time)
+				self.dmgtime = time + 1;
+			else
+				self.dmgtime = time + 0.2;
+
+			T_Damage (self, world, world, 10*self.waterlevel);
+		}
+	}
+	else if (self.watertype == CONTENT_SLIME)
+	{       // do damage
+		if (self.dmgtime < time && self.radsuit_finished < time)
+		{
+			self.dmgtime = time + 1;
+			T_Damage (self, world, world, 4*self.waterlevel);
+		}
+	}
+	
+	if ( !(self.flags & FL_INWATER) )
+	{       
+
+// player enter water sound
+
+		if (self.watertype == CONTENT_LAVA)
+			sound (self, CHAN_BODY, "player/inlava.wav", 1, ATTN_NORM);
+		if (self.watertype == CONTENT_WATER)
+			sound (self, CHAN_BODY, "player/inh2o.wav", 1, ATTN_NORM);
+		if (self.watertype == CONTENT_SLIME)
+			sound (self, CHAN_BODY, "player/slimbrn2.wav", 1, ATTN_NORM);
+
+		self.flags = self.flags + FL_INWATER;
+		self.dmgtime = 0;
+	}       
+};
+
+void() CheckWaterJump =
+{
+	local vector start, end;
+
+// check for a jump-out-of-water
+	makevectors (self.angles);
+	start = self.origin;
+	start_z = start_z + 8; 
+	v_forward_z = 0;
+	normalize(v_forward);
+	end = start + v_forward*24;
+	traceline (start, end, TRUE, self);
+	if (trace_fraction < 1)
+	{       // solid at waist
+		start_z = start_z + self.maxs_z - 8;
+		end = start + v_forward*24;
+		self.movedir = trace_plane_normal * -50;
+		traceline (start, end, TRUE, self);
+		if (trace_fraction == 1)
+		{       // open at eye level
+			self.flags = self.flags | FL_WATERJUMP;
+			self.velocity_z = 225;
+			self.flags = self.flags - (self.flags & FL_JUMPRELEASED);
+			self.teleport_time = time + 2;  // safety net
+			return;
+		}
+	}
+};
+
+/*
+================
+PlayerPreThink
+
+Called every frame before physics are run
+================
+*/
+void() PlayerPreThink =
+{
+	local   float   mspeed, aspeed;
+	local   float   r;
+
+	if (intermission_running)
+	{
+		IntermissionThink ();   // otherwise a button could be missed between
+		return;                                 // the think tics
+	}
+
+	if (self.view_ofs == '0 0 0')
+		return;         // intermission or finale
+
+	makevectors (self.v_angle);             // is this still used
+
+        self.deathtype = "";
+
+	CheckRules ();
+	WaterMove ();
+/*
+	if (self.waterlevel == 2)
+		CheckWaterJump ();
+*/
+
+	if (self.deadflag >= DEAD_DEAD)
+	{
+		PlayerDeathThink ();
+		return;
+	}
+	
+	if (self.deadflag == DEAD_DYING)
+		return; // dying, so do nothing
+
+	if (self.button2)
+	{
+		PlayerJump ();
+	}
+	else
+		self.flags = self.flags | FL_JUMPRELEASED;
+
+// teleporters can force a non-moving pause time        
+	if (time < self.pausetime)
+		self.velocity = '0 0 0';
+
+	if(time > self.attack_finished && self.currentammo == 0 && self.weapon != IT_AXE)
+	{
+		self.weapon = W_BestWeapon ();
+		W_SetCurrentAmmo ();
+	}
+};
+	
+/*
+================
+CheckPowerups
+
+Check for turning off powerups
+================
+*/
+void() CheckPowerups =
+{
+	if (self.health <= 0)
+		return;
+
+// invisibility
+	if (self.invisible_finished)
+	{
+// sound and screen flash when items starts to run out
+		if (self.invisible_sound < time)
+		{
+			sound (self, CHAN_AUTO, "items/inv3.wav", 0.5, ATTN_IDLE);
+			self.invisible_sound = time + ((random() * 3) + 1);
+		}
+
+
+		if (self.invisible_finished < time + 3)
+		{
+			if (self.invisible_time == 1)
+			{
+				sprint (self, PRINT_HIGH, "Ring of Shadows magic is fading\n");
+				stuffcmd (self, "bf\n");
+				sound (self, CHAN_AUTO, "items/inv2.wav", 1, ATTN_NORM);
+				self.invisible_time = time + 1;
+			}
+			
+			if (self.invisible_time < time)
+			{
+				self.invisible_time = time + 1;
+				stuffcmd (self, "bf\n");
+			}
+		}
+
+		if (self.invisible_finished < time)
+		{       // just stopped
+			self.items = self.items - IT_INVISIBILITY;
+			self.invisible_finished = 0;
+			self.invisible_time = 0;
+		}
+		
+	// use the eyes
+		self.frame = 0;
+		self.modelindex = modelindex_eyes;
+	}
+	else
+		self.modelindex = modelindex_player;    // don't use eyes
+
+// invincibility
+	if (self.invincible_finished)
+	{
+// sound and screen flash when items starts to run out
+		if (self.invincible_finished < time + 3)
+		{
+			if (self.invincible_time == 1)
+			{
+				sprint (self, PRINT_HIGH, "Protection is almost burned out\n");
+				stuffcmd (self, "bf\n");
+				sound (self, CHAN_AUTO, "items/protect2.wav", 1, ATTN_NORM);
+				self.invincible_time = time + 1;
+			}
+			
+			if (self.invincible_time < time)
+			{
+				self.invincible_time = time + 1;
+				stuffcmd (self, "bf\n");
+			}
+		}
+		
+		if (self.invincible_finished < time)
+		{       // just stopped
+			self.items = self.items - IT_INVULNERABILITY;
+			self.invincible_time = 0;
+			self.invincible_finished = 0;
+		}
+		if (self.invincible_finished > time)
+		{
+			self.effects = self.effects | EF_DIMLIGHT;
+			self.effects = self.effects | EF_RED;
+		}
+		else
+		{
+			self.effects = self.effects - (self.effects & EF_DIMLIGHT);
+			self.effects = self.effects - (self.effects & EF_RED);
+		}
+	}
+
+// super damage
+	if (self.super_damage_finished)
+	{
+
+// sound and screen flash when items starts to run out
+
+		if (self.super_damage_finished < time + 3)
+		{
+			if (self.super_time == 1)
+			{
+				if (deathmatch == 4)
+					sprint (self, PRINT_HIGH, "OctaPower is wearing off\n");
+				else
+					sprint (self, PRINT_HIGH, "Quad Damage is wearing off\n");
+				stuffcmd (self, "bf\n");
+				sound (self, CHAN_AUTO, "items/damage2.wav", 1, ATTN_NORM);
+				self.super_time = time + 1;
+			}         
+			
+			if (self.super_time < time)
+			{
+				self.super_time = time + 1;
+				stuffcmd (self, "bf\n");
+			}
+		}
+
+		if (self.super_damage_finished < time)
+		{       // just stopped
+			self.items = self.items - IT_QUAD;
+			if (deathmatch == 4)
+			{
+				self.ammo_cells = 255;
+				self.armorvalue = 1;
+				self.armortype = 0.8;
+				self.health = 100;
+			}
+			self.super_damage_finished = 0;
+			self.super_time = 0;
+		}
+		if (self.super_damage_finished > time)
+		{
+			self.effects = self.effects | EF_DIMLIGHT;
+			self.effects = self.effects | EF_BLUE;
+		}
+		else
+		{
+			self.effects = self.effects - (self.effects & EF_DIMLIGHT);
+			self.effects = self.effects - (self.effects & EF_BLUE);
+		}
+	}       
+
+// suit 
+	if (self.radsuit_finished)
+	{
+		self.air_finished = time + 12;          // don't drown
+
+// sound and screen flash when items starts to run out
+		if (self.radsuit_finished < time + 3)
+		{
+			if (self.rad_time == 1)
+			{
+				sprint (self, PRINT_HIGH, "Air supply in Biosuit expiring\n");
+				stuffcmd (self, "bf\n");
+				sound (self, CHAN_AUTO, "items/suit2.wav", 1, ATTN_NORM);
+				self.rad_time = time + 1;
+			}
+			
+			if (self.rad_time < time)
+			{
+				self.rad_time = time + 1;
+				stuffcmd (self, "bf\n");
+			}
+		}
+
+		if (self.radsuit_finished < time)
+		{       // just stopped
+			self.items = self.items - IT_SUIT;
+			self.rad_time = 0;
+			self.radsuit_finished = 0;
+		}
+	}       
+
+};
+
+
+/*
+================
+PlayerPostThink
+
+Called every frame after physics are run
+================
+*/
+void() PlayerPostThink =
+{
+	local   float   mspeed, aspeed;
+	local   float   r;
+
+//dprint ("post think\n");
+	if (self.view_ofs == '0 0 0')
+		return;         // intermission or finale
+	if (self.deadflag)
+		return;
+
+// check to see if player landed and play landing sound 
+	if ((self.jump_flag < -300) && (self.flags & FL_ONGROUND) )
+	{
+		if (self.watertype == CONTENT_WATER)
+			sound (self, CHAN_BODY, "player/h2ojump.wav", 1, ATTN_NORM);
+		else if (self.jump_flag < -650)
+		{
+			self.deathtype = "falling";
+			T_Damage (self, world, world, 5); 
+			sound (self, CHAN_VOICE, "player/land2.wav", 1, ATTN_NORM);
+		}
+		else
+			sound (self, CHAN_VOICE, "player/land.wav", 1, ATTN_NORM);
+	}
+
+	self.jump_flag = self.velocity_z;
+
+	CheckPowerups ();
+
+	W_WeaponFrame ();
+
+};
+
+
+/*
+===========
+ClientConnect
+
+called when a player connects to a server
+============
+*/
+void() ClientConnect =
+{
+	bprint (PRINT_HIGH, self.netname);
+	bprint (PRINT_HIGH, " entered the game\n");
+	
+// a client connecting during an intermission can cause problems
+	if (intermission_running)
+		GotoNextMap ();
+};
+
+
+/*
+===========
+ClientDisconnect
+
+called when a player disconnects from a server
+============
+*/
+void() ClientDisconnect =
+{
+	// let everyone else know
+	bprint (PRINT_HIGH, self.netname);
+		bprint (PRINT_HIGH, " left the game with ");
+		bprint (PRINT_HIGH, ftos(self.frags));
+		bprint (PRINT_HIGH, " frags\n");
+	sound (self, CHAN_BODY, "player/tornoff2.wav", 1, ATTN_NONE);
+	set_suicide_frame ();
+};
+
+/*
+===========
+ClientObituary
+
+called when a player dies
+============
+*/
+
+void(entity targ, entity attacker) ClientObituary =
+{
+	local   float rnum;
+	local   string deathstring, deathstring2;
+	local   string s;
+	local   string  attackerteam, targteam;
+
+	rnum = random();
+	//ZOID 12-13-96: self.team doesn't work in QW.  Use keys
+	attackerteam = infokey(attacker, "team");
+	targteam = infokey(targ, "team");
+
+	if (targ.classname == "player")
+	{
+
+		if (deathmatch > 3)	
+		{
+			if (targ.deathtype == "selfwater")
+			{
+				bprint (PRINT_MEDIUM, targ.netname);
+				bprint (PRINT_MEDIUM," electrocutes himself.\n ");
+				targ.frags = targ.frags - 1;
+				return;
+			}
+		}
+
+		if (attacker.classname == "teledeath")
+		{
+			bprint (PRINT_MEDIUM,targ.netname);
+			bprint (PRINT_MEDIUM," was telefragged by ");
+			bprint (PRINT_MEDIUM,attacker.owner.netname);
+			bprint (PRINT_MEDIUM,"\n");
+			logfrag (attacker.owner, targ);
+
+			attacker.owner.frags = attacker.owner.frags + 1;
+			return;
+		}
+
+		if (attacker.classname == "teledeath2")
+		{
+			bprint (PRINT_MEDIUM,"Satan's power deflects ");
+			bprint (PRINT_MEDIUM,targ.netname);
+			bprint (PRINT_MEDIUM,"'s telefrag\n");
+
+			targ.frags = targ.frags - 1;
+			logfrag (targ, targ);
+			return;
+		}
+
+		// double 666 telefrag (can happen often in deathmatch 4)
+		if (attacker.classname == "teledeath3") 
+		{
+			bprint (PRINT_MEDIUM,targ.netname);
+			bprint (PRINT_MEDIUM," was telefragged by ");
+			bprint (PRINT_MEDIUM,attacker.owner.netname);
+			bprint (PRINT_MEDIUM, "'s Satan's power\n");
+			targ.frags = targ.frags - 1;
+			logfrag (targ, targ);
+			return;
+		}
+	
+
+		if (targ.deathtype == "squish")
+		{
+			if (teamplay && targteam == attackerteam && attackerteam != "" && targ != attacker)
+			{
+				logfrag (attacker, attacker);
+				attacker.frags = attacker.frags - 1; 
+				bprint (PRINT_MEDIUM,attacker.netname);
+				bprint (PRINT_MEDIUM," squished a teammate\n");
+				return;
+			}
+			else if (attacker.classname == "player" && attacker != targ)
+			{
+				bprint (PRINT_MEDIUM, attacker.netname);
+				bprint (PRINT_MEDIUM," squishes ");
+				bprint (PRINT_MEDIUM,targ.netname);
+				bprint (PRINT_MEDIUM,"\n");
+				logfrag (attacker, targ);
+				attacker.frags = attacker.frags + 1;
+				return;
+			}
+			else
+			{
+				logfrag (targ, targ);
+				targ.frags = targ.frags - 1;            // killed self
+				bprint (PRINT_MEDIUM,targ.netname);
+				bprint (PRINT_MEDIUM," was squished\n");
+				return;
+			}
+		}
+
+		if (attacker.classname == "player")
+		{
+			if (targ == attacker)
+			{
+				// killed self
+				logfrag (attacker, attacker);
+				attacker.frags = attacker.frags - 1;
+				bprint (PRINT_MEDIUM,targ.netname);
+				if (targ.deathtype == "grenade")
+					bprint (PRINT_MEDIUM," tries to put the pin back in\n");
+				else if (targ.deathtype == "rocket")
+					bprint (PRINT_MEDIUM," becomes bored with life\n");
+				else if (targ.weapon == 64 && targ.waterlevel > 1)
+				{
+					if (targ.watertype == CONTENT_SLIME)
+						bprint (PRINT_MEDIUM," discharges into the slime\n");
+					else if (targ.watertype == CONTENT_LAVA)
+						bprint (PRINT_MEDIUM," discharges into the lava\n");
+					else
+						bprint (PRINT_MEDIUM," discharges into the water.\n");
+				}
+				else
+					bprint (PRINT_MEDIUM," becomes bored with life\n");
+				return;
+			}
+			else if ( (teamplay == 2) && (targteam == attackerteam) &&
+				(attackerteam != "") )
+			{
+				if (rnum < 0.25)
+					deathstring = " mows down a teammate\n";
+				else if (rnum < 0.50)
+					deathstring = " checks his glasses\n";
+				else if (rnum < 0.75)
+					deathstring = " gets a frag for the other team\n";
+				else
+					deathstring = " loses another friend\n";
+				bprint (PRINT_MEDIUM, attacker.netname);
+				bprint (PRINT_MEDIUM, deathstring);
+				attacker.frags = attacker.frags - 1;
+				//ZOID 12-13-96:  killing a teammate logs as suicide
+				logfrag (attacker, attacker);
+				return;
+			}
+			else
+			{
+				logfrag (attacker, targ);
+				attacker.frags = attacker.frags + 1;
+
+				rnum = attacker.weapon;
+				if (targ.deathtype == "nail")
+				{
+					deathstring = " was nailed by ";
+					deathstring2 = "\n";
+				}
+				else if (targ.deathtype == "supernail")
+				{
+					deathstring = " was punctured by ";
+					deathstring2 = "\n";
+				}
+				else if (targ.deathtype == "grenade")
+				{
+					deathstring = " eats ";
+					deathstring2 = "'s pineapple\n";
+					if (targ.health < -40)
+					{
+						deathstring = " was gibbed by ";
+						deathstring2 = "'s grenade\n";
+					}
+				}
+				else if (targ.deathtype == "rocket")
+				{
+					if (attacker.super_damage_finished > 0 && targ.health < -40)
+					{
+						rnum = random();
+						if (rnum < 0.3)
+							deathstring = " was brutalized by ";
+						else if (rnum < 0.6)
+							deathstring = " was smeared by ";
+						else
+						{
+							bprint (PRINT_MEDIUM, attacker.netname);
+							bprint (PRINT_MEDIUM, " rips ");
+							bprint (PRINT_MEDIUM, targ.netname);
+							bprint (PRINT_MEDIUM, " a new one\n");
+							return;
+						}
+						deathstring2 = "'s quad rocket\n";
+					}
+					else
+					{
+						deathstring = " rides ";
+						deathstring2 = "'s rocket\n";
+						if (targ.health < -40)
+						{
+							deathstring = " was gibbed by ";
+							deathstring2 = "'s rocket\n" ;
+						}
+					}
+				}
+				else if (rnum == IT_AXE)
+				{
+					deathstring = " was ax-murdered by ";
+					deathstring2 = "\n";
+				}
+				else if (rnum == IT_SHOTGUN)
+				{
+					deathstring = " chewed on ";
+					deathstring2 = "'s boomstick\n";
+				}
+				else if (rnum == IT_SUPER_SHOTGUN)
+				{
+					deathstring = " ate 2 loads of ";
+					deathstring2 = "'s buckshot\n";
+				}
+				else if (rnum == IT_LIGHTNING)
+				{
+					deathstring = " accepts ";
+					if (attacker.waterlevel > 1)
+						deathstring2 = "'s discharge\n";
+					else
+						deathstring2 = "'s shaft\n";
+				}
+				bprint (PRINT_MEDIUM,targ.netname);
+				bprint (PRINT_MEDIUM,deathstring);
+				bprint (PRINT_MEDIUM,attacker.netname);
+				bprint (PRINT_MEDIUM,deathstring2);
+			}
+			return;
+		}
+		else
+		{
+			logfrag (targ, targ);
+			targ.frags = targ.frags - 1;            // killed self
+			rnum = targ.watertype;
+
+			bprint (PRINT_MEDIUM,targ.netname);
+			if (rnum == -3)
+			{
+				if (random() < 0.5)
+					bprint (PRINT_MEDIUM," sleeps with the fishes\n");
+				else
+					bprint (PRINT_MEDIUM," sucks it down\n");
+				return;
+			}
+			else if (rnum == -4)
+			{
+				if (random() < 0.5)
+					bprint (PRINT_MEDIUM," gulped a load of slime\n");
+				else
+					bprint (PRINT_MEDIUM," can't exist on slime alone\n");
+				return;
+			}
+			else if (rnum == -5)
+			{
+				if (targ.health < -15)
+				{
+					bprint (PRINT_MEDIUM," burst into flames\n");
+					return;
+				}
+				if (random() < 0.5)
+					bprint (PRINT_MEDIUM," turned into hot slag\n");
+				else
+					bprint (PRINT_MEDIUM," visits the Volcano God\n");
+				return;
+			}
+
+			if (attacker.classname == "explo_box")
+			{
+				bprint (PRINT_MEDIUM," blew up\n");
+				return;
+			}
+			if (targ.deathtype == "falling")
+			{
+				bprint (PRINT_MEDIUM," fell to his death\n");
+				return;
+			}
+			if (targ.deathtype == "nail" || targ.deathtype == "supernail")
+			{
+				bprint (PRINT_MEDIUM," was spiked\n");
+				return;
+			}
+			if (targ.deathtype == "laser")
+			{
+				bprint (PRINT_MEDIUM," was zapped\n");
+				return;
+			}
+			if (attacker.classname == "fireball")
+			{
+				bprint (PRINT_MEDIUM," ate a lavaball\n");
+				return;
+			}
+			if (attacker.classname == "trigger_changelevel")
+			{
+				bprint (PRINT_MEDIUM," tried to leave\n");
+				return;
+			}
+
+			bprint (PRINT_MEDIUM," died\n");
+		}
+	}
+};
--- /dev/null
+++ b/QW/progs/combat.qc
@@ -1,0 +1,324 @@
+
+void() T_MissileTouch;
+void() info_player_start;
+void(entity targ, entity attacker) ClientObituary;
+void(entity inflictor, entity attacker, float damage, entity ignore, string dtype) T_RadiusDamage;
+
+/*SERVER
+void() monster_death_use;
+*/
+
+//============================================================================
+
+/*
+============
+CanDamage
+
+Returns true if the inflictor can directly damage the target.  Used for
+explosions and melee attacks.
+============
+*/
+float(entity targ, entity inflictor) CanDamage =
+{
+// bmodels need special checking because their origin is 0,0,0
+	if (targ.movetype == MOVETYPE_PUSH)
+	{
+		traceline(inflictor.origin, 0.5 * (targ.absmin + targ.absmax), TRUE, self);
+		if (trace_fraction == 1)
+			return TRUE;
+		if (trace_ent == targ)
+			return TRUE;
+		return FALSE;
+	}
+	
+	traceline(inflictor.origin, targ.origin, TRUE, self);
+	if (trace_fraction == 1)
+		return TRUE;
+	traceline(inflictor.origin, targ.origin + '15 15 0', TRUE, self);
+	if (trace_fraction == 1)
+		return TRUE;
+	traceline(inflictor.origin, targ.origin + '-15 -15 0', TRUE, self);
+	if (trace_fraction == 1)
+		return TRUE;
+	traceline(inflictor.origin, targ.origin + '-15 15 0', TRUE, self);
+	if (trace_fraction == 1)
+		return TRUE;
+	traceline(inflictor.origin, targ.origin + '15 -15 0', TRUE, self);
+	if (trace_fraction == 1)
+		return TRUE;
+
+	return FALSE;
+};
+
+
+/*
+============
+Killed
+============
+*/
+void(entity targ, entity attacker) Killed =
+{
+	local entity oself;
+
+	oself = self;
+	self = targ;
+	
+	if (self.health < -99)
+		self.health = -99;              // don't let sbar look bad if a player
+
+	if (self.movetype == MOVETYPE_PUSH || self.movetype == MOVETYPE_NONE)
+	{       // doors, triggers, etc
+		self.th_die ();
+		self = oself;
+		return;
+	}
+
+	self.enemy = attacker;
+
+// bump the monster counter
+	if (self.flags & FL_MONSTER)
+	{
+		killed_monsters = killed_monsters + 1;
+		WriteByte (MSG_ALL, SVC_KILLEDMONSTER);
+	}
+
+	ClientObituary(self, attacker);
+	
+	self.takedamage = DAMAGE_NO;
+	self.touch = SUB_Null;
+	self.effects = 0;
+
+/*SERVER
+	monster_death_use();
+*/
+	self.th_die ();
+	
+	self = oself;
+};
+
+
+/*
+============
+T_Damage
+
+The damage is coming from inflictor, but get mad at attacker
+This should be the only function that ever reduces health.
+============
+*/
+void(entity targ, entity inflictor, entity attacker, float damage) T_Damage=
+{
+	local   vector  dir;
+	local   entity  oldself;
+	local   float   save;
+	local   float   take;
+	local   string  s;
+	local   string  attackerteam, targteam;
+
+
+	if (!targ.takedamage)
+		return;
+
+// used by buttons and triggers to set activator for target firing
+	damage_attacker = attacker;
+
+
+// check for quad damage powerup on the attacker
+	if (attacker.super_damage_finished > time && inflictor.classname != "door")
+	if (deathmatch == 4)
+		damage = damage * 8;
+	else
+		damage = damage * 4;
+
+// save damage based on the target's armor level
+
+	save = ceil(targ.armortype*damage);
+	if (save >= targ.armorvalue)
+	{
+		save = targ.armorvalue;
+		targ.armortype = 0;     // lost all armor
+		targ.items = targ.items - (targ.items & (IT_ARMOR1 | IT_ARMOR2 | IT_ARMOR3));
+	}
+	
+	targ.armorvalue = targ.armorvalue - save;
+	take = ceil(damage-save);
+
+// add to the damage total for clients, which will be sent as a single
+// message at the end of the frame
+// FIXME: remove after combining shotgun blasts?
+	if (targ.flags & FL_CLIENT)
+	{
+		targ.dmg_take = targ.dmg_take + take;
+		targ.dmg_save = targ.dmg_save + save;
+		targ.dmg_inflictor = inflictor;
+	}
+
+	damage_inflictor = inflictor;        
+
+
+// figure momentum add
+	if ( (inflictor != world) && (targ.movetype == MOVETYPE_WALK) )
+	{
+		dir = targ.origin - (inflictor.absmin + inflictor.absmax) * 0.5;
+		dir = normalize(dir);
+		// Set kickback for smaller weapons
+//Zoid -- use normal NQ kickback
+//		// Read: only if it's not yourself doing the damage
+//		if ( (damage < 60) & ((attacker.classname == "player") & (targ.classname == "player")) & ( attacker.netname != targ.netname)) 
+//			targ.velocity = targ.velocity + dir * damage * 11;
+//		else                        
+		// Otherwise, these rules apply to rockets and grenades                        
+		// for blast velocity
+			targ.velocity = targ.velocity + dir * damage * 8;
+		
+		// Rocket Jump modifiers
+		if ( (rj > 1) & ((attacker.classname == "player") & (targ.classname == "player")) & ( attacker.netname == targ.netname)) 
+			targ.velocity = targ.velocity + dir * damage * rj;
+
+	}
+
+
+
+// check for godmode or invincibility
+	if (targ.flags & FL_GODMODE)
+		return;
+	if (targ.invincible_finished >= time)
+	{
+		if (self.invincible_sound < time)
+		{
+			sound (targ, CHAN_ITEM, "items/protect3.wav", 1, ATTN_NORM);
+			self.invincible_sound = time + 2;
+		}
+		return;
+	}
+
+// team play damage avoidance
+//ZOID 12-13-96: self.team doesn't work in QW.  Use keys
+	attackerteam = infokey(attacker, "team");
+	targteam = infokey(targ, "team");
+
+	if ((teamplay == 1) && (targteam == attackerteam) &&
+		(attacker.classname == "player") && (attackerteam != "") &&
+		inflictor.classname !="door")
+		return;
+
+	if ((teamplay == 3) && (targteam == attackerteam) &&
+		(attacker.classname == "player") && (attackerteam != "") &&
+		(targ != attacker)&& inflictor.classname !="door")
+		return;
+		
+// do the damage
+	targ.health = targ.health - take;
+
+	if (targ.health <= 0)
+	{
+		Killed (targ, attacker);
+		return;
+	}
+
+// react to the damage
+	oldself = self;
+	self = targ;
+
+/*SERVER
+	if ( (self.flags & FL_MONSTER) && attacker != world)
+	{
+	// get mad unless of the same class (except for soldiers)
+		if (self != attacker && attacker != self.enemy)
+		{
+			if ( (self.classname != attacker.classname) 
+			|| (self.classname == "monster_army" ) )
+			{
+				if (self.enemy.classname == "player")
+					self.oldenemy = self.enemy;
+				self.enemy = attacker;
+				FoundTarget ();
+			}
+		}
+	}
+*/
+	if (self.th_pain)
+	{
+		self.th_pain (attacker, take);
+	}
+
+	self = oldself;
+};
+
+/*
+============
+T_RadiusDamage
+============
+*/
+void(entity inflictor, entity attacker, float damage, entity ignore, string dtype) T_RadiusDamage =
+{
+	local   float   points;
+	local   entity  head;
+	local   vector  org;
+
+	head = findradius(inflictor.origin, damage+40);
+	
+	while (head)
+	{
+		//bprint (PRINT_HIGH, head.classname);
+		//bprint (PRINT_HIGH, " | ");
+		//bprint (PRINT_HIGH, head.netname);
+		//bprint (PRINT_HIGH, "\n");
+	
+		if (head != ignore)
+		{
+			if (head.takedamage)
+			{
+				org = head.origin + (head.mins + head.maxs)*0.5;
+				points = 0.5*vlen (inflictor.origin - org);
+				if (points < 0)
+					points = 0;
+				points = damage - points;
+				
+				if (head == attacker)
+					points = points * 0.5;
+				if (points > 0)
+				{
+					if (CanDamage (head, inflictor))
+					{
+						head.deathtype = dtype;
+						T_Damage (head, inflictor, attacker, points);
+					}
+				}
+			}
+		}
+		head = head.chain;
+	}
+};
+
+/*
+============
+T_BeamDamage
+============
+*/
+void(entity attacker, float damage) T_BeamDamage =
+{
+	local   float   points;
+	local   entity  head;
+	
+	head = findradius(attacker.origin, damage+40);
+	
+	while (head)
+	{
+		if (head.takedamage)
+		{
+			points = 0.5*vlen (attacker.origin - head.origin);
+			if (points < 0)
+				points = 0;
+			points = damage - points;
+			if (head == attacker)
+				points = points * 0.5;
+			if (points > 0)
+			{
+				if (CanDamage (head, attacker))
+					T_Damage (head, attacker, attacker, points);
+			}
+		}
+		head = head.chain;
+	}
+};
+
--- /dev/null
+++ b/QW/progs/defs.qc
@@ -1,0 +1,728 @@
+
+/*
+==============================================================================
+
+			SOURCE FOR GLOBALVARS_T C STRUCTURE
+
+==============================================================================
+*/
+
+//
+// system globals
+//
+entity          self;
+entity          other;
+entity          world;
+float           time;
+float           frametime;
+
+entity          newmis;                         // if this is set, the entity that just
+								// run created a new missile that should
+								// be simulated immediately
+
+
+float           force_retouch;          // force all entities to touch triggers
+								// next frame.  this is needed because
+								// non-moving things don't normally scan
+								// for triggers, and when a trigger is
+								// created (like a teleport trigger), it
+								// needs to catch everything.
+								// decremented each frame, so set to 2
+								// to guarantee everything is touched
+string          mapname;
+
+float           serverflags;            // propagated from level to level, used to
+								// keep track of completed episodes
+
+float           total_secrets;
+float           total_monsters;
+
+float           found_secrets;          // number of secrets found
+float           killed_monsters;        // number of monsters killed
+
+
+// spawnparms are used to encode information about clients across server
+// level changes
+float           parm1, parm2, parm3, parm4, parm5, parm6, parm7, parm8, parm9, parm10, parm11, parm12, parm13, parm14, parm15, parm16;
+
+//
+// global variables set by built in functions
+//      
+vector          v_forward, v_up, v_right;       // set by makevectors()
+	
+// set by traceline / tracebox
+float           trace_allsolid;
+float           trace_startsolid;
+float           trace_fraction;
+vector          trace_endpos;
+vector          trace_plane_normal;
+float           trace_plane_dist;
+entity          trace_ent;
+float           trace_inopen;
+float           trace_inwater;
+
+entity          msg_entity;                             // destination of single entity writes
+
+//
+// required prog functions
+//
+void()          main;                                           // only for testing
+
+void()          StartFrame;
+
+void()          PlayerPreThink;
+void()          PlayerPostThink;
+
+void()          ClientKill;
+void()          ClientConnect;
+void()          PutClientInServer;              // call after setting the parm1... parms
+void()          ClientDisconnect;
+
+void()          SetNewParms;                    // called when a client first connects to
+									// a server. sets parms so they can be
+									// saved off for restarts
+
+void()          SetChangeParms;                 // call to set parms for self so they can
+									// be saved for a level transition
+
+
+//================================================
+void            end_sys_globals;                // flag for structure dumping
+//================================================
+
+/*
+==============================================================================
+
+			SOURCE FOR ENTVARS_T C STRUCTURE
+
+==============================================================================
+*/
+
+//
+// system fields (*** = do not set in prog code, maintained by C code)
+//
+.float          modelindex;             // *** model index in the precached list
+.vector         absmin, absmax; // *** origin + mins / maxs
+
+.float          ltime;                  // local time for entity
+.float          lastruntime;    // *** to allow entities to run out of sequence
+
+.float          movetype;
+.float          solid;
+
+.vector         origin;                 // ***
+.vector         oldorigin;              // ***
+.vector         velocity;
+.vector         angles;
+.vector         avelocity;
+
+.string         classname;              // spawn function
+.string         model;
+.float          frame;
+.float          skin;
+.float          effects;
+
+.vector         mins, maxs;             // bounding box extents reletive to origin
+.vector         size;                   // maxs - mins
+
+.void()         touch;
+.void()         use;
+.void()         think;
+.void()         blocked;                // for doors or plats, called when can't push other
+
+.float          nextthink;
+.entity         groundentity;
+
+
+
+// stats
+.float          health;
+.float          frags;
+.float          weapon;                 // one of the IT_SHOTGUN, etc flags
+.string         weaponmodel;
+.float          weaponframe;
+.float          currentammo;
+.float          ammo_shells, ammo_nails, ammo_rockets, ammo_cells;
+
+.float          items;                  // bit flags
+
+.float          takedamage;
+.entity         chain;
+.float          deadflag;
+
+.vector         view_ofs;                       // add to origin to get eye point
+
+
+.float          button0;                // fire
+.float          button1;                // use
+.float          button2;                // jump
+
+.float          impulse;                // weapon changes
+
+.float          fixangle;
+.vector         v_angle;                // view / targeting angle for players
+
+.string         netname;
+
+.entity         enemy;
+
+.float          flags;
+
+.float          colormap;
+.float          team;
+
+.float          max_health;             // players maximum health is stored here
+
+.float          teleport_time;  // don't back up
+
+.float          armortype;              // save this fraction of incoming damage
+.float          armorvalue;
+
+.float          waterlevel;             // 0 = not in, 1 = feet, 2 = wast, 3 = eyes
+.float          watertype;              // a contents value
+
+.float          ideal_yaw;
+.float          yaw_speed;
+
+.entity         aiment;
+
+.entity         goalentity;             // a movetarget or an enemy
+
+.float          spawnflags;
+
+.string         target;
+.string         targetname;
+
+// damage is accumulated through a frame. and sent as one single
+// message, so the super shotgun doesn't generate huge messages
+.float          dmg_take;
+.float          dmg_save;
+.entity         dmg_inflictor;
+
+.entity         owner;          // who launched a missile
+.vector         movedir;        // mostly for doors, but also used for waterjump
+
+.string         message;                // trigger messages
+
+.float          sounds;         // either a cd track number or sound number
+
+.string         noise, noise1, noise2, noise3;  // contains names of wavs to play
+
+//================================================
+void            end_sys_fields;                 // flag for structure dumping
+//================================================
+
+/*
+==============================================================================
+
+				VARS NOT REFERENCED BY C CODE
+
+==============================================================================
+*/
+
+
+//
+// constants
+//
+
+float   FALSE                                   = 0;
+float   TRUE                                    = 1;
+
+// edict.flags
+float   FL_FLY                                  = 1;
+float   FL_SWIM                                 = 2;
+float   FL_CLIENT                               = 8;    // set for all client edicts
+float   FL_INWATER                              = 16;   // for enter / leave water splash
+float   FL_MONSTER                              = 32;
+float   FL_GODMODE                              = 64;   // player cheat
+float   FL_NOTARGET                             = 128;  // player cheat
+float   FL_ITEM                                 = 256;  // extra wide size for bonus items
+float   FL_ONGROUND                             = 512;  // standing on something
+float   FL_PARTIALGROUND                = 1024; // not all corners are valid
+float   FL_WATERJUMP                    = 2048; // player jumping out of water
+float   FL_JUMPRELEASED                 = 4096; // for jump debouncing
+
+// edict.movetype values
+float   MOVETYPE_NONE                   = 0;    // never moves
+//float MOVETYPE_ANGLENOCLIP    = 1;
+//float MOVETYPE_ANGLECLIP              = 2;
+float   MOVETYPE_WALK                   = 3;    // players only
+float   MOVETYPE_STEP                   = 4;    // discrete, not real time unless fall
+float   MOVETYPE_FLY                    = 5;
+float   MOVETYPE_TOSS                   = 6;    // gravity
+float   MOVETYPE_PUSH                   = 7;    // no clip to world, push and crush
+float   MOVETYPE_NOCLIP                 = 8;
+float   MOVETYPE_FLYMISSILE             = 9;    // fly with extra size against monsters
+float   MOVETYPE_BOUNCE                 = 10;
+float   MOVETYPE_BOUNCEMISSILE  = 11;   // bounce with extra size
+
+// edict.solid values
+float   SOLID_NOT                               = 0;    // no interaction with other objects
+float   SOLID_TRIGGER                   = 1;    // touch on edge, but not blocking
+float   SOLID_BBOX                              = 2;    // touch on edge, block
+float   SOLID_SLIDEBOX                  = 3;    // touch on edge, but not an onground
+float   SOLID_BSP                               = 4;    // bsp clip, touch on edge, block
+
+// range values
+float   RANGE_MELEE                             = 0;
+float   RANGE_NEAR                              = 1;
+float   RANGE_MID                               = 2;
+float   RANGE_FAR                               = 3;
+
+// deadflag values
+
+float   DEAD_NO                                 = 0;
+float   DEAD_DYING                              = 1;
+float   DEAD_DEAD                               = 2;
+float   DEAD_RESPAWNABLE                = 3;
+
+// takedamage values
+
+float   DAMAGE_NO                               = 0;
+float   DAMAGE_YES                              = 1;
+float   DAMAGE_AIM                              = 2;
+
+// items
+float   IT_AXE                                  = 4096;
+float   IT_SHOTGUN                              = 1;
+float   IT_SUPER_SHOTGUN                = 2;
+float   IT_NAILGUN                              = 4;
+float   IT_SUPER_NAILGUN                = 8;
+float   IT_GRENADE_LAUNCHER             = 16;
+float   IT_ROCKET_LAUNCHER              = 32;
+float   IT_LIGHTNING                    = 64;
+float   IT_EXTRA_WEAPON                 = 128;
+
+float   IT_SHELLS                               = 256;
+float   IT_NAILS                                = 512;
+float   IT_ROCKETS                              = 1024;
+float   IT_CELLS                                = 2048;
+
+float   IT_ARMOR1                               = 8192;
+float   IT_ARMOR2                               = 16384;
+float   IT_ARMOR3                               = 32768;
+float   IT_SUPERHEALTH                  = 65536;
+
+float   IT_KEY1                                 = 131072;
+float   IT_KEY2                                 = 262144;
+
+float   IT_INVISIBILITY                 = 524288;
+float   IT_INVULNERABILITY              = 1048576;
+float   IT_SUIT                                 = 2097152;
+float   IT_QUAD                                 = 4194304;
+
+// point content values
+
+float   CONTENT_EMPTY                   = -1;
+float   CONTENT_SOLID                   = -2;
+float   CONTENT_WATER                   = -3;
+float   CONTENT_SLIME                   = -4;
+float   CONTENT_LAVA                    = -5;
+float   CONTENT_SKY                             = -6;
+
+float   STATE_TOP               = 0;
+float   STATE_BOTTOM    = 1;
+float   STATE_UP                = 2;
+float   STATE_DOWN              = 3;
+
+vector  VEC_ORIGIN = '0 0 0';
+vector  VEC_HULL_MIN = '-16 -16 -24';
+vector  VEC_HULL_MAX = '16 16 32';
+
+vector  VEC_HULL2_MIN = '-32 -32 -24';
+vector  VEC_HULL2_MAX = '32 32 64';
+
+// protocol bytes
+float   SVC_TEMPENTITY          = 23;
+float   SVC_KILLEDMONSTER       = 27;
+float   SVC_FOUNDSECRET         = 28;
+float   SVC_INTERMISSION        = 30;
+float   SVC_FINALE                      = 31;
+float   SVC_CDTRACK                     = 32;
+float   SVC_SELLSCREEN          = 33;
+float   SVC_SMALLKICK           = 34;
+float   SVC_BIGKICK                     = 35;
+float   SVC_MUZZLEFLASH         = 39;
+
+
+float   TE_SPIKE                = 0;
+float   TE_SUPERSPIKE   = 1;
+float   TE_GUNSHOT              = 2;
+float   TE_EXPLOSION    = 3;
+float   TE_TAREXPLOSION = 4;
+float   TE_LIGHTNING1   = 5;
+float   TE_LIGHTNING2   = 6;
+float   TE_WIZSPIKE             = 7;
+float   TE_KNIGHTSPIKE  = 8;
+float   TE_LIGHTNING3   = 9;
+float   TE_LAVASPLASH   = 10;
+float   TE_TELEPORT             = 11;
+float   TE_BLOOD                = 12;
+float   TE_LIGHTNINGBLOOD = 13;
+
+// sound channels
+// channel 0 never willingly overrides
+// other channels (1-7) allways override a playing sound on that channel
+float   CHAN_AUTO               = 0;
+float   CHAN_WEAPON             = 1;
+float   CHAN_VOICE              = 2;
+float   CHAN_ITEM               = 3;
+float   CHAN_BODY               = 4;
+float   CHAN_NO_PHS_ADD = 8;    // ie: CHAN_BODY+CHAN_NO_PHS_ADD
+
+float   ATTN_NONE               = 0;
+float   ATTN_NORM               = 1;
+float   ATTN_IDLE               = 2;
+float   ATTN_STATIC             = 3;
+
+// update types
+
+float   UPDATE_GENERAL  = 0;
+float   UPDATE_STATIC   = 1;
+float   UPDATE_BINARY   = 2;
+float   UPDATE_TEMP             = 3;
+
+// entity effects
+
+//float EF_BRIGHTFIELD  = 1;
+//float EF_MUZZLEFLASH  = 2;
+float   EF_BRIGHTLIGHT  = 4;
+float   EF_DIMLIGHT     = 8;
+float   EF_FLAG1                = 16;
+float   EF_FLAG2                = 32;
+// GLQuakeWorld Stuff
+float 	EF_BLUE		=	64;	// Blue Globe effect for Quad
+float	EF_RED		=	128;	// Red Globe effect for Pentagram
+// messages
+float   MSG_BROADCAST   = 0;            // unreliable to all
+float   MSG_ONE                 = 1;            // reliable to one (msg_entity)
+float   MSG_ALL                 = 2;            // reliable to all
+float   MSG_INIT                = 3;            // write to the init string
+float   MSG_MULTICAST   = 4;            // for multicast() call
+
+// message levels
+float   PRINT_LOW               = 0;            // pickup messages
+float   PRINT_MEDIUM    	= 1;            // death messages
+float   PRINT_HIGH              = 2;            // critical messages
+float   PRINT_CHAT              = 3;            // also goes to chat console
+
+// multicast sets
+float   MULTICAST_ALL   = 0;            // every client
+float   MULTICAST_PHS   = 1;            // within hearing
+float   MULTICAST_PVS   = 2;            // within sight
+float   MULTICAST_ALL_R = 3;            // every client, reliable
+float   MULTICAST_PHS_R = 4;            // within hearing, reliable
+float   MULTICAST_PVS_R = 5;            // within sight, reliable
+
+
+
+
+//================================================
+
+//
+// globals
+//
+float   movedist;
+
+string  string_null;    // null string, nothing should be held here
+float   empty_float;
+
+entity  activator;              // the entity that activated a trigger or brush
+
+entity  damage_attacker;        // set by T_Damage
+entity  damage_inflictor;
+float   framecount;
+
+//
+// cvars checked each frame
+//
+float           teamplay;
+float           timelimit;
+float           fraglimit;
+float           deathmatch;
+float           rj                      =       1;
+
+//================================================
+
+//
+// world fields (FIXME: make globals)
+//
+.string         wad;
+.string         map;
+.float          worldtype;      // 0=medieval 1=metal 2=base
+
+//================================================
+
+.string         killtarget;
+
+//
+// quakeed fields
+//
+.float          light_lev;              // not used by game, but parsed by light util
+.float          style;
+
+
+//
+// monster ai
+//
+.void()         th_stand;
+.void()         th_walk;
+.void()         th_run;
+.void()         th_missile;
+.void()         th_melee;
+.void(entity attacker, float damage)            th_pain;
+.void()         th_die;
+
+.entity         oldenemy;               // mad at this player before taking damage
+
+.float          speed;
+
+.float  lefty;
+
+.float  search_time;
+.float  attack_state;
+
+float   AS_STRAIGHT             = 1;
+float   AS_SLIDING              = 2;
+float   AS_MELEE                = 3;
+float   AS_MISSILE              = 4;
+
+//
+// player only fields
+//
+.float          voided;
+.float          walkframe;
+
+// Zoid Additions
+.float		maxspeed;		// Used to set Maxspeed on a player
+.float		gravity;		// Gravity Multiplier (0 to 1.0)
+
+
+
+.float          attack_finished;
+.float          pain_finished;
+
+.float          invincible_finished;
+.float          invisible_finished;
+.float          super_damage_finished;
+.float          radsuit_finished;
+
+.float          invincible_time, invincible_sound;
+.float          invisible_time, invisible_sound;
+.float          super_time, super_sound;
+.float          rad_time;
+.float          fly_sound;
+
+.float          axhitme;
+
+.float          show_hostile;   // set to time+0.2 whenever a client fires a
+							// weapon or takes damage.  Used to alert
+							// monsters that otherwise would let the player go
+.float          jump_flag;              // player jump flag
+.float          swim_flag;              // player swimming sound flag
+.float          air_finished;   // when time > air_finished, start drowning
+.float          bubble_count;   // keeps track of the number of bubbles
+.string         deathtype;              // keeps track of how the player died
+
+//
+// object stuff
+//
+.string         mdl;
+.vector         mangle;                 // angle at start
+
+.vector         oldorigin;              // only used by secret door
+
+.float          t_length, t_width;
+
+
+//
+// doors, etc
+//
+.vector         dest, dest1, dest2;
+.float          wait;                   // time from firing to restarting
+.float          delay;                  // time from activation to firing
+.entity         trigger_field;  // door's trigger entity
+.string         noise4;
+
+//
+// monsters
+//
+.float          pausetime;
+.entity         movetarget;
+
+
+//
+// doors
+//
+.float          aflag;
+.float          dmg;                    // damage done by door when hit
+	
+//
+// misc
+//
+.float          cnt;                    // misc flag
+	
+//
+// subs
+//
+.void()         think1;
+.vector         finaldest, finalangle;
+
+//
+// triggers
+//
+.float          count;                  // for counting triggers
+
+
+//
+// plats / doors / buttons
+//
+.float          lip;
+.float          state;
+.vector         pos1, pos2;             // top and bottom positions
+.float          height;
+
+//
+// sounds
+//
+.float          waitmin, waitmax;
+.float          distance;
+.float          volume;
+
+
+
+
+//===========================================================================
+	
+
+//
+// builtin functions
+//
+
+void(vector ang)        makevectors             = #1;           // sets v_forward, etc globals
+void(entity e, vector o) setorigin      = #2;
+void(entity e, string m) setmodel       = #3;           // set movetype and solid first
+void(entity e, vector min, vector max) setsize = #4;
+// #5 was removed
+void() break                                            = #6;
+float() random                                          = #7;           // returns 0 - 1
+void(entity e, float chan, string samp, float vol, float atten) sound = #8;
+vector(vector v) normalize                      = #9;
+void(string e) error                            = #10;
+void(string e) objerror                         = #11;
+float(vector v) vlen                            = #12;
+float(vector v) vectoyaw                        = #13;
+entity() spawn                                          = #14;
+void(entity e) remove                           = #15;
+
+// sets trace_* globals
+// nomonsters can be:
+// An entity will also be ignored for testing if forent == test,
+// forent->owner == test, or test->owner == forent
+// a forent of world is ignored
+void(vector v1, vector v2, float nomonsters, entity forent) traceline = #16;    
+
+entity() checkclient                            = #17;  // returns a client to look for
+entity(entity start, .string fld, string match) find = #18;
+string(string s) precache_sound         = #19;
+string(string s) precache_model         = #20;
+void(entity client, string s)stuffcmd = #21;
+entity(vector org, float rad) findradius = #22;
+void(float level, string s) bprint                              = #23;
+void(entity client, float level, string s) sprint = #24;
+void(string s) dprint                           = #25;
+string(float f) ftos                            = #26;
+string(vector v) vtos                           = #27;
+void() coredump                                         = #28;          // prints all edicts
+void() traceon                                          = #29;          // turns statment trace on
+void() traceoff                                         = #30;
+void(entity e) eprint                           = #31;          // prints an entire edict
+float(float yaw, float dist) walkmove   = #32;  // returns TRUE or FALSE
+// #33 was removed
+float(float yaw, float dist) droptofloor= #34;  // TRUE if landed on floor
+void(float style, string value) lightstyle = #35;
+float(float v) rint                                     = #36;          // round to nearest int
+float(float v) floor                            = #37;          // largest integer <= v
+float(float v) ceil                                     = #38;          // smallest integer >= v
+// #39 was removed
+float(entity e) checkbottom                     = #40;          // true if self is on ground
+float(vector v) pointcontents           = #41;          // returns a CONTENT_*
+// #42 was removed
+float(float f) fabs = #43;
+vector(entity e, float speed) aim = #44;                // returns the shooting vector
+float(string s) cvar = #45;                                             // return cvar.value
+void(string s) localcmd = #46;                                  // put string into local que
+entity(entity e) nextent = #47;                                 // for looping through all ents
+// #48 was removed
+void() ChangeYaw = #49;                                         // turn towards self.ideal_yaw
+											// at self.yaw_speed
+// #50 was removed
+vector(vector v) vectoangles                    = #51;
+
+//
+// direct client message generation
+//
+void(float to, float f) WriteByte               = #52;
+void(float to, float f) WriteChar               = #53;
+void(float to, float f) WriteShort              = #54;
+void(float to, float f) WriteLong               = #55;
+void(float to, float f) WriteCoord              = #56;
+void(float to, float f) WriteAngle              = #57;
+void(float to, string s) WriteString    = #58;
+void(float to, entity s) WriteEntity    = #59;
+
+// several removed
+
+void(float step) movetogoal                             = #67;
+
+string(string s) precache_file          = #68;  // no effect except for -copy
+void(entity e) makestatic               = #69;
+void(string s) changelevel = #70;
+
+//#71 was removed
+
+void(string var, string val) cvar_set = #72;    // sets cvar.value
+
+void(entity client, string s) centerprint = #73;        // sprint, but in middle
+
+void(vector pos, string samp, float vol, float atten) ambientsound = #74;
+
+string(string s) precache_model2        = #75;          // registered version only
+string(string s) precache_sound2        = #76;          // registered version only
+string(string s) precache_file2         = #77;          // registered version only
+
+void(entity e) setspawnparms            = #78;          // set parm1... to the
+												// values at level start
+												// for coop respawn
+void(entity killer, entity killee) logfrag = #79;       // add to stats
+
+string(entity e, string key) infokey    = #80;  // get a key value (world = serverinfo)
+float(string s) stof                            = #81;          // convert string to float
+void(vector where, float set) multicast = #82;  // sends the temp message to a set
+												// of clients, possibly in PVS or PHS
+
+//============================================================================
+
+//
+// subs.qc
+//
+void(vector tdest, float tspeed, void() func) SUB_CalcMove;
+void(entity ent, vector tdest, float tspeed, void() func) SUB_CalcMoveEnt;
+void(vector destangle, float tspeed, void() func) SUB_CalcAngleMove;
+void()  SUB_CalcMoveDone;
+void() SUB_CalcAngleMoveDone;
+void() SUB_Null;
+void() SUB_UseTargets;
+void() SUB_Remove;
+
+//
+//      combat.qc
+//
+void(entity targ, entity inflictor, entity attacker, float damage) T_Damage;
+
+
+float (entity e, float healamount, float ignore) T_Heal; // health function
+
+float(entity targ, entity inflictor) CanDamage;
+
+
--- /dev/null
+++ b/QW/progs/doors.qc
@@ -1,0 +1,783 @@
+
+float DOOR_START_OPEN = 1;
+float DOOR_DONT_LINK = 4;
+float DOOR_GOLD_KEY = 8;
+float DOOR_SILVER_KEY = 16;
+float DOOR_TOGGLE = 32;
+
+/*
+
+Doors are similar to buttons, but can spawn a fat trigger field around them
+to open without a touch, and they link together to form simultanious
+double/quad doors.
+ 
+Door.owner is the master door.  If there is only one door, it points to itself.
+If multiple doors, all will point to a single one.
+
+Door.enemy chains from the master door through all doors linked in the chain.
+
+*/
+
+/*
+=============================================================================
+
+THINK FUNCTIONS
+
+=============================================================================
+*/
+
+void() door_go_down;
+void() door_go_up;
+
+void() door_blocked =
+{
+	other.deathtype = "squish";
+	T_Damage (other, self, self.goalentity, self.dmg);
+
+// if a door has a negative wait, it would never come back if blocked,
+// so let it just squash the object to death real fast
+	if (self.wait >= 0)
+	{
+		if (self.state == STATE_DOWN)
+			door_go_up ();
+		else
+			door_go_down ();
+	}
+};
+
+
+void() door_hit_top =
+{
+	sound (self, CHAN_NO_PHS_ADD+CHAN_VOICE, self.noise1, 1, ATTN_NORM);
+	self.state = STATE_TOP;
+	if (self.spawnflags & DOOR_TOGGLE)
+		return;         // don't come down automatically
+	self.think = door_go_down;
+	self.nextthink = self.ltime + self.wait;
+};
+
+void() door_hit_bottom =
+{
+	sound (self, CHAN_NO_PHS_ADD+CHAN_VOICE, self.noise1, 1, ATTN_NORM);
+	self.state = STATE_BOTTOM;
+};
+
+void() door_go_down =
+{
+	sound (self, CHAN_VOICE, self.noise2, 1, ATTN_NORM);
+	if (self.max_health)
+	{
+		self.takedamage = DAMAGE_YES;
+		self.health = self.max_health;
+	}
+	
+	self.state = STATE_DOWN;
+	SUB_CalcMove (self.pos1, self.speed, door_hit_bottom);
+};
+
+void() door_go_up =
+{
+	if (self.state == STATE_UP)
+		return;         // allready going up
+
+	if (self.state == STATE_TOP)
+	{       // reset top wait time
+		self.nextthink = self.ltime + self.wait;
+		return;
+	}
+	
+	sound (self, CHAN_VOICE, self.noise2, 1, ATTN_NORM);
+	self.state = STATE_UP;
+	SUB_CalcMove (self.pos2, self.speed, door_hit_top);
+
+	SUB_UseTargets();
+};
+
+
+/*
+=============================================================================
+
+ACTIVATION FUNCTIONS
+
+=============================================================================
+*/
+
+void() door_fire =
+{
+	local entity    oself;
+	local entity    starte;
+
+	if (self.owner != self)
+		objerror ("door_fire: self.owner != self");
+
+// play use key sound
+
+	if (self.items)
+		sound (self, CHAN_VOICE, self.noise4, 1, ATTN_NORM);
+
+	self.message = string_null;             // no more message
+	oself = self;
+
+	if (self.spawnflags & DOOR_TOGGLE)
+	{
+		if (self.state == STATE_UP || self.state == STATE_TOP)
+		{
+			starte = self;
+			do
+			{
+				door_go_down ();
+				self = self.enemy;
+			} while ( (self != starte) && (self != world) );
+			self = oself;
+			return;
+		}
+	}
+	
+// trigger all paired doors
+	starte = self;
+	
+	do
+	{
+		self.goalentity = activator;		// Who fired us
+		door_go_up ();
+		self = self.enemy;
+	} while ( (self != starte) && (self != world) );
+	self = oself;
+};
+
+
+void() door_use =
+{
+	local entity oself;
+
+	self.message = "";                      // door message are for touch only
+	self.owner.message = "";        
+	self.enemy.message = "";
+
+	oself = self;
+	self = self.owner;
+	door_fire ();
+	self = oself;
+};
+
+
+void() door_trigger_touch =
+{
+	if (other.health <= 0)
+		return;
+
+	if (time < self.attack_finished)
+		return;
+	self.attack_finished = time + 1;
+
+	activator = other;
+
+	self = self.owner;
+	door_use ();
+};
+
+
+void() door_killed =
+{
+	local entity oself;
+	
+	oself = self;
+	self = self.owner;
+	self.health = self.max_health;
+	self.takedamage = DAMAGE_NO;    // wil be reset upon return
+	door_use ();
+	self = oself;
+};
+
+
+/*
+================
+door_touch
+
+Prints messages and opens key doors
+================
+*/
+void() door_touch =
+{
+	if (other.classname != "player")
+		return;
+	if (self.owner.attack_finished > time)
+		return;
+
+	self.owner.attack_finished = time + 2;
+
+	if (self.owner.message != "")
+	{
+		centerprint (other, self.owner.message);
+		sound (other, CHAN_VOICE, "misc/talk.wav", 1, ATTN_NORM);
+	}
+	
+// key door stuff
+	if (!self.items)
+		return;
+
+// FIXME: blink key on player's status bar
+	if ( (self.items & other.items) != self.items )
+	{
+		if (self.owner.items == IT_KEY1)
+		{
+			if (world.worldtype == 2)
+			{
+				centerprint (other, "You need the silver keycard");
+				sound (self, CHAN_VOICE, self.noise3, 1, ATTN_NORM);
+			}
+			else if (world.worldtype == 1)
+			{
+				centerprint (other, "You need the silver runekey");
+				sound (self, CHAN_VOICE, self.noise3, 1, ATTN_NORM);
+			}
+			else if (world.worldtype == 0)
+			{
+				centerprint (other, "You need the silver key");
+				sound (self, CHAN_VOICE, self.noise3, 1, ATTN_NORM);
+			}
+		}
+		else
+		{
+			if (world.worldtype == 2)
+			{
+				centerprint (other, "You need the gold keycard");
+				sound (self, CHAN_VOICE, self.noise3, 1, ATTN_NORM);
+			}
+			else if (world.worldtype == 1)
+			{
+				centerprint (other, "You need the gold runekey");
+				sound (self, CHAN_VOICE, self.noise3, 1, ATTN_NORM);                    
+			}
+			else if (world.worldtype == 0)
+			{
+				centerprint (other, "You need the gold key");
+				sound (self, CHAN_VOICE, self.noise3, 1, ATTN_NORM);
+			}
+		}
+		return;
+	}
+
+	other.items = other.items - self.items;
+	self.touch = SUB_Null;
+	if (self.enemy)
+		self.enemy.touch = SUB_Null;    // get paired door
+	door_use ();
+};
+
+/*
+=============================================================================
+
+SPAWNING FUNCTIONS
+
+=============================================================================
+*/
+
+
+entity(vector fmins, vector fmaxs) spawn_field =
+{
+	local entity    trigger;
+	local   vector  t1, t2;
+
+	trigger = spawn();
+	trigger.movetype = MOVETYPE_NONE;
+	trigger.solid = SOLID_TRIGGER;
+	trigger.owner = self;
+	trigger.touch = door_trigger_touch;
+
+	t1 = fmins;
+	t2 = fmaxs;
+	setsize (trigger, t1 - '60 60 8', t2 + '60 60 8');
+	return (trigger);
+};
+
+
+float (entity e1, entity e2) EntitiesTouching =
+{
+	if (e1.mins_x > e2.maxs_x)
+		return FALSE;
+	if (e1.mins_y > e2.maxs_y)
+		return FALSE;
+	if (e1.mins_z > e2.maxs_z)
+		return FALSE;
+	if (e1.maxs_x < e2.mins_x)
+		return FALSE;
+	if (e1.maxs_y < e2.mins_y)
+		return FALSE;
+	if (e1.maxs_z < e2.mins_z)
+		return FALSE;
+	return TRUE;
+};
+
+
+/*
+=============
+LinkDoors
+
+
+=============
+*/
+void() LinkDoors =
+{
+	local entity    t, starte;
+	local vector    cmins, cmaxs;
+
+	if (self.enemy)
+		return;         // already linked by another door
+	if (self.spawnflags & 4)
+	{
+		self.owner = self.enemy = self;
+		return;         // don't want to link this door
+	}
+
+	cmins = self.mins;
+	cmaxs = self.maxs;
+	
+	starte = self;
+	t = self;
+	
+	do
+	{
+		self.owner = starte;                    // master door
+
+		if (self.health)
+			starte.health = self.health;
+		if (self.targetname)
+			starte.targetname = self.targetname;
+		if (self.message != "")
+			starte.message = self.message;
+
+		t = find (t, classname, self.classname);        
+		if (!t)
+		{
+			self.enemy = starte;            // make the chain a loop
+
+		// shootable, fired, or key doors just needed the owner/enemy links,
+		// they don't spawn a field
+	
+			self = self.owner;
+
+			if (self.health)
+				return;
+			if (self.targetname)
+				return;
+			if (self.items)
+				return;
+
+			self.owner.trigger_field = spawn_field(cmins, cmaxs);
+
+			return;
+		}
+
+		if (EntitiesTouching(self,t))
+		{
+			if (t.enemy)
+				objerror ("cross connected doors");
+			
+			self.enemy = t;
+			self = t;
+
+			if (t.mins_x < cmins_x)
+				cmins_x = t.mins_x;
+			if (t.mins_y < cmins_y)
+				cmins_y = t.mins_y;
+			if (t.mins_z < cmins_z)
+				cmins_z = t.mins_z;
+			if (t.maxs_x > cmaxs_x)
+				cmaxs_x = t.maxs_x;
+			if (t.maxs_y > cmaxs_y)
+				cmaxs_y = t.maxs_y;
+			if (t.maxs_z > cmaxs_z)
+				cmaxs_z = t.maxs_z;
+		}
+	} while (1 );
+
+};
+
+
+/*QUAKED func_door (0 .5 .8) ? START_OPEN x DOOR_DONT_LINK GOLD_KEY SILVER_KEY TOGGLE
+if two doors touch, they are assumed to be connected and operate as a unit.
+
+TOGGLE causes the door to wait in both the start and end states for a trigger event.
+
+START_OPEN causes the door to move to its destination when spawned, and operate in reverse.  It is used to temporarily or permanently close off an area when triggered (not usefull for touch or takedamage doors).
+
+Key doors are allways wait -1.
+
+"message"       is printed when the door is touched if it is a trigger door and it hasn't been fired yet
+"angle"         determines the opening direction
+"targetname" if set, no touch field will be spawned and a remote button or trigger field activates the door.
+"health"        if set, door must be shot open
+"speed"         movement speed (100 default)
+"wait"          wait before returning (3 default, -1 = never return)
+"lip"           lip remaining at end of move (8 default)
+"dmg"           damage to inflict when blocked (2 default)
+"sounds"
+0)      no sound
+1)      stone
+2)      base
+3)      stone chain
+4)      screechy metal
+*/
+
+void() func_door =
+
+{
+
+	if (world.worldtype == 0)
+	{
+		precache_sound ("doors/medtry.wav");
+		precache_sound ("doors/meduse.wav");
+		self.noise3 = "doors/medtry.wav";
+		self.noise4 = "doors/meduse.wav";
+	}
+	else if (world.worldtype == 1)
+	{
+		precache_sound ("doors/runetry.wav");
+		precache_sound ("doors/runeuse.wav");
+		self.noise3 = "doors/runetry.wav";
+		self.noise4 = "doors/runeuse.wav";
+	}
+	else if (world.worldtype == 2)
+	{
+		precache_sound ("doors/basetry.wav");
+		precache_sound ("doors/baseuse.wav");
+		self.noise3 = "doors/basetry.wav";
+		self.noise4 = "doors/baseuse.wav";
+	}
+	else
+	{
+		dprint ("no worldtype set!\n");
+	}
+	if (self.sounds == 0)
+	{
+		precache_sound ("misc/null.wav");
+		precache_sound ("misc/null.wav");
+		self.noise1 = "misc/null.wav";
+		self.noise2 = "misc/null.wav";
+	}
+	if (self.sounds == 1)
+	{
+		precache_sound ("doors/drclos4.wav");
+		precache_sound ("doors/doormv1.wav");
+		self.noise1 = "doors/drclos4.wav";
+		self.noise2 = "doors/doormv1.wav";
+	}
+	if (self.sounds == 2)
+	{
+		precache_sound ("doors/hydro1.wav");
+		precache_sound ("doors/hydro2.wav");
+		self.noise2 = "doors/hydro1.wav";
+		self.noise1 = "doors/hydro2.wav";
+	}
+	if (self.sounds == 3)
+	{
+		precache_sound ("doors/stndr1.wav");
+		precache_sound ("doors/stndr2.wav");
+		self.noise2 = "doors/stndr1.wav";
+		self.noise1 = "doors/stndr2.wav";
+	}
+	if (self.sounds == 4)
+	{
+		precache_sound ("doors/ddoor1.wav");
+		precache_sound ("doors/ddoor2.wav");
+		self.noise1 = "doors/ddoor2.wav";
+		self.noise2 = "doors/ddoor1.wav";
+	}
+
+
+	SetMovedir ();
+
+	self.max_health = self.health;
+	self.solid = SOLID_BSP;
+	self.movetype = MOVETYPE_PUSH;
+	setorigin (self, self.origin);  
+	setmodel (self, self.model);
+	self.classname = "door";
+
+	self.blocked = door_blocked;
+	self.use = door_use;
+	
+	if (self.spawnflags & DOOR_SILVER_KEY)
+		self.items = IT_KEY1;
+	if (self.spawnflags & DOOR_GOLD_KEY)
+		self.items = IT_KEY2;
+	
+	if (!self.speed)
+		self.speed = 100;
+	if (!self.wait)
+		self.wait = 3;
+	if (!self.lip)
+		self.lip = 8;
+	if (!self.dmg)
+		self.dmg = 2;
+
+	self.pos1 = self.origin;
+	self.pos2 = self.pos1 + self.movedir*(fabs(self.movedir*self.size) - self.lip);
+
+// DOOR_START_OPEN is to allow an entity to be lighted in the closed position
+// but spawn in the open position
+	if (self.spawnflags & DOOR_START_OPEN)
+	{
+		setorigin (self, self.pos2);
+		self.pos2 = self.pos1;
+		self.pos1 = self.origin;
+	}
+
+	self.state = STATE_BOTTOM;
+
+	if (self.health)
+	{
+		self.takedamage = DAMAGE_YES;
+		self.th_die = door_killed;
+	}
+	
+	if (self.items)
+		self.wait = -1;
+		
+	self.touch = door_touch;
+
+// LinkDoors can't be done until all of the doors have been spawned, so
+// the sizes can be detected properly.
+	self.think = LinkDoors;
+	self.nextthink = self.ltime + 0.1;
+};
+
+/*
+=============================================================================
+
+SECRET DOORS
+
+=============================================================================
+*/
+
+void() fd_secret_move1;
+void() fd_secret_move2;
+void() fd_secret_move3;
+void() fd_secret_move4;
+void() fd_secret_move5;
+void() fd_secret_move6;
+void() fd_secret_done;
+
+float SECRET_OPEN_ONCE = 1;             // stays open
+float SECRET_1ST_LEFT = 2;              // 1st move is left of arrow
+float SECRET_1ST_DOWN = 4;              // 1st move is down from arrow
+float SECRET_NO_SHOOT = 8;              // only opened by trigger
+float SECRET_YES_SHOOT = 16;    // shootable even if targeted
+
+
+void () fd_secret_use =
+{
+	local float temp;
+	
+	self.health = 10000;
+
+	// exit if still moving around...
+	if (self.origin != self.oldorigin)
+		return;
+	
+	self.message = string_null;             // no more message
+
+	SUB_UseTargets();                               // fire all targets / killtargets
+	
+	if (!(self.spawnflags & SECRET_NO_SHOOT))
+	{
+		self.th_pain = SUB_Null;
+		self.takedamage = DAMAGE_NO;
+	}
+	self.velocity = '0 0 0';
+
+	// Make a sound, wait a little...
+	
+	sound(self, CHAN_VOICE, self.noise1, 1, ATTN_NORM);
+	self.nextthink = self.ltime + 0.1;
+
+	temp = 1 - (self.spawnflags & SECRET_1ST_LEFT); // 1 or -1
+	makevectors(self.mangle);
+	
+	if (!self.t_width)
+	{
+		if (self.spawnflags & SECRET_1ST_DOWN)
+			self. t_width = fabs(v_up * self.size);
+		else
+			self. t_width = fabs(v_right * self.size);
+	}
+		
+	if (!self.t_length)
+		self. t_length = fabs(v_forward * self.size);
+
+	if (self.spawnflags & SECRET_1ST_DOWN)
+		self.dest1 = self.origin - v_up * self.t_width;
+	else
+		self.dest1 = self.origin + v_right * (self.t_width * temp);
+		
+	self.dest2 = self.dest1 + v_forward * self.t_length;
+	SUB_CalcMove(self.dest1, self.speed, fd_secret_move1);
+	sound(self, CHAN_VOICE, self.noise2, 1, ATTN_NORM);
+};
+
+// Wait after first movement...
+void () fd_secret_move1 = 
+{
+	self.nextthink = self.ltime + 1.0;
+	self.think = fd_secret_move2;
+	sound(self, CHAN_VOICE, self.noise3, 1, ATTN_NORM);
+};
+
+// Start moving sideways w/sound...
+void () fd_secret_move2 =
+{
+	sound(self, CHAN_VOICE, self.noise2, 1, ATTN_NORM);
+	SUB_CalcMove(self.dest2, self.speed, fd_secret_move3);
+};
+
+// Wait here until time to go back...
+void () fd_secret_move3 =
+{
+	sound(self, CHAN_VOICE, self.noise3, 1, ATTN_NORM);
+	if (!(self.spawnflags & SECRET_OPEN_ONCE))
+	{
+		self.nextthink = self.ltime + self.wait;
+		self.think = fd_secret_move4;
+	}
+};
+
+// Move backward...
+void () fd_secret_move4 =
+{
+	sound(self, CHAN_VOICE, self.noise2, 1, ATTN_NORM);
+	SUB_CalcMove(self.dest1, self.speed, fd_secret_move5);          
+};
+
+// Wait 1 second...
+void () fd_secret_move5 = 
+{
+	self.nextthink = self.ltime + 1.0;
+	self.think = fd_secret_move6;
+	sound(self, CHAN_VOICE, self.noise3, 1, ATTN_NORM);
+};
+
+void () fd_secret_move6 =
+{
+	sound(self, CHAN_VOICE, self.noise2, 1, ATTN_NORM);
+	SUB_CalcMove(self.oldorigin, self.speed, fd_secret_done);
+};
+
+void () fd_secret_done =
+{
+	if (!self.targetname || self.spawnflags&SECRET_YES_SHOOT)
+	{
+		self.health = 10000;
+		self.takedamage = DAMAGE_YES;
+		self.th_pain = fd_secret_use;   
+		self.th_die = fd_secret_use;
+	}
+	sound(self, CHAN_NO_PHS_ADD+CHAN_VOICE, self.noise3, 1, ATTN_NORM);
+};
+
+void () secret_blocked =
+{
+	if (time < self.attack_finished)
+		return;
+	self.attack_finished = time + 0.5;
+	other.deathtype = "squish";
+	T_Damage (other, self, self, self.dmg);
+};
+
+/*
+================
+secret_touch
+
+Prints messages
+================
+*/
+void() secret_touch =
+{
+	if (other.classname != "player")
+		return;
+	if (self.attack_finished > time)
+		return;
+
+	self.attack_finished = time + 2;
+	
+	if (self.message)
+	{
+		centerprint (other, self.message);
+		sound (other, CHAN_BODY, "misc/talk.wav", 1, ATTN_NORM);
+	}
+};
+
+
+/*QUAKED func_door_secret (0 .5 .8) ? open_once 1st_left 1st_down no_shoot always_shoot
+Basic secret door. Slides back, then to the side. Angle determines direction.
+wait  = # of seconds before coming back
+1st_left = 1st move is left of arrow
+1st_down = 1st move is down from arrow
+always_shoot = even if targeted, keep shootable
+t_width = override WIDTH to move back (or height if going down)
+t_length = override LENGTH to move sideways
+"dmg"           damage to inflict when blocked (2 default)
+
+If a secret door has a targetname, it will only be opened by it's botton or trigger, not by damage.
+"sounds"
+1) medieval
+2) metal
+3) base
+*/
+
+void () func_door_secret =
+{
+	if (self.sounds == 0)
+		self.sounds = 3;
+	if (self.sounds == 1)
+	{
+		precache_sound ("doors/latch2.wav");
+		precache_sound ("doors/winch2.wav");
+		precache_sound ("doors/drclos4.wav");
+		self.noise1 = "doors/latch2.wav";
+		self.noise2 = "doors/winch2.wav";
+		self.noise3 = "doors/drclos4.wav";
+	}
+	if (self.sounds == 2)
+	{
+		precache_sound ("doors/airdoor1.wav");
+		precache_sound ("doors/airdoor2.wav");
+		self.noise2 = "doors/airdoor1.wav";
+		self.noise1 = "doors/airdoor2.wav";
+		self.noise3 = "doors/airdoor2.wav";
+	}
+	if (self.sounds == 3)
+	{
+		precache_sound ("doors/basesec1.wav");
+		precache_sound ("doors/basesec2.wav");
+		self.noise2 = "doors/basesec1.wav";
+		self.noise1 = "doors/basesec2.wav";
+		self.noise3 = "doors/basesec2.wav";
+	}
+
+	if (!self.dmg)
+		self.dmg = 2;
+		
+	// Magic formula...
+	self.mangle = self.angles;
+	self.angles = '0 0 0';
+	self.solid = SOLID_BSP;
+	self.movetype = MOVETYPE_PUSH;
+	self.classname = "door";
+	setmodel (self, self.model);
+	setorigin (self, self.origin);  
+	
+	self.touch = secret_touch;
+	self.blocked = secret_blocked;
+	self.speed = 50;
+	self.use = fd_secret_use;
+	if ( !self.targetname || self.spawnflags&SECRET_YES_SHOOT)
+	{
+		self.health = 10000;
+		self.takedamage = DAMAGE_YES;
+		self.th_pain = fd_secret_use;
+	}
+	self.oldorigin = self.origin;
+	if (!self.wait)
+		self.wait = 5;          // 5 seconds before closing
+};
--- /dev/null
+++ b/QW/progs/files.dat
@@ -1,0 +1,312 @@
+140
+1 items/r_item1.wav
+1 items/r_item2.wav
+1 items/health1.wav
+1 misc/medkey.wav
+1 misc/runekey.wav
+2 misc/basekey.wav
+1 items/protect.wav
+1 items/protect2.wav
+1 items/protect3.wav
+1 items/suit.wav
+1 items/suit2.wav
+1 items/inv1.wav
+1 items/inv2.wav
+1 items/inv3.wav
+1 items/damage.wav
+1 items/damage2.wav
+1 items/damage3.wav
+1 weapons/r_exp3.wav
+1 weapons/rocket1i.wav
+1 weapons/sgun1.wav
+1 weapons/guncock.wav
+1 weapons/ric1.wav
+1 weapons/ric2.wav
+1 weapons/ric3.wav
+1 weapons/spike2.wav
+1 weapons/tink1.wav
+1 weapons/grenade.wav
+1 weapons/bounce.wav
+1 weapons/shotgn2.wav
+1 misc/menu1.wav
+1 misc/menu2.wav
+1 misc/menu3.wav
+1 ambience/water1.wav
+1 ambience/wind2.wav
+1 demon/dland2.wav
+1 misc/h2ohit1.wav
+1 items/itembk2.wav
+1 player/plyrjmp8.wav
+1 player/land.wav
+1 player/land2.wav
+1 player/drown1.wav
+1 player/drown2.wav
+1 player/gasp1.wav
+1 player/gasp2.wav
+1 player/h2odeath.wav
+1 misc/talk.wav
+1 player/teledth1.wav
+1 misc/r_tele1.wav
+1 misc/r_tele2.wav
+1 misc/r_tele3.wav
+1 misc/r_tele4.wav
+1 misc/r_tele5.wav
+1 weapons/lock4.wav
+1 weapons/pkup.wav
+1 items/armor1.wav
+1 weapons/lhit.wav
+1 weapons/lstart.wav
+1 misc/power.wav
+1 player/gib.wav
+1 player/udeath.wav
+1 player/tornoff2.wav
+1 player/pain1.wav
+1 player/pain2.wav
+1 player/pain3.wav
+1 player/pain4.wav
+1 player/pain5.wav
+1 player/pain6.wav
+1 player/death1.wav
+1 player/death2.wav
+1 player/death3.wav
+1 player/death4.wav
+1 player/death5.wav
+1 boss1/sight1.wav
+1 weapons/ax1.wav
+1 player/axhit1.wav
+1 player/axhit2.wav
+1 player/h2ojump.wav
+1 player/slimbrn2.wav
+1 player/inh2o.wav
+1 player/inlava.wav
+1 misc/outwater.wav
+1 player/lburn1.wav
+1 player/lburn2.wav
+1 misc/water1.wav
+1 misc/water2.wav
+1 doors/medtry.wav
+1 doors/meduse.wav
+1 doors/runetry.wav
+1 doors/runeuse.wav
+1 doors/basetry.wav
+1 doors/baseuse.wav
+1 misc/null.wav
+1 doors/drclos4.wav
+1 doors/doormv1.wav
+1 doors/hydro1.wav
+1 doors/hydro2.wav
+1 doors/stndr1.wav
+1 doors/stndr2.wav
+1 doors/ddoor1.wav
+1 doors/ddoor2.wav
+1 doors/latch2.wav
+1 doors/winch2.wav
+1 doors/airdoor1.wav
+1 doors/airdoor2.wav
+1 doors/basesec1.wav
+1 doors/basesec2.wav
+1 buttons/airbut1.wav
+1 buttons/switch21.wav
+1 buttons/switch02.wav
+1 buttons/switch04.wav
+1 misc/secret.wav
+1 misc/trigger1.wav
+1 ambience/hum1.wav
+1 ambience/windfly.wav
+1 plats/plat1.wav
+1 plats/plat2.wav
+1 plats/medplat1.wav
+1 plats/medplat2.wav
+1 plats/train2.wav
+1 plats/train1.wav
+1 ambience/fl_hum1.wav
+1 ambience/buzz1.wav
+1 ambience/fire1.wav
+2 enforcer/enfire.wav
+2 enforcer/enfstop.wav
+1 ambience/suck1.wav
+1 ambience/drone6.wav
+1 ambience/drip1.wav
+1 ambience/comp1.wav
+1 ambience/thunder1.wav
+1 ambience/swamp1.wav
+1 ambience/swamp2.wav
+2 enforcer/sight1.wav
+2 enforcer/sight2.wav
+2 enforcer/sight3.wav
+2 enforcer/sight4.wav
+2 enforcer/pain1.wav
+2 enforcer/pain2.wav
+2 enforcer/death1.wav
+2 enforcer/idle1.wav
+65
+1 maps/b_bh10.bsp
+1 maps/b_bh100.bsp
+1 maps/b_bh25.bsp
+1 progs/armor.mdl
+1 progs/g_shot.mdl
+1 progs/g_nail.mdl
+1 progs/g_nail2.mdl
+1 progs/g_rock.mdl
+1 progs/g_rock2.mdl
+1 progs/g_light.mdl
+1 maps/b_shell1.bsp
+1 maps/b_shell0.bsp
+1 maps/b_nail1.bsp
+1 maps/b_nail0.bsp
+1 maps/b_rock1.bsp
+1 maps/b_rock0.bsp
+1 maps/b_batt1.bsp
+1 maps/b_batt0.bsp
+1 progs/w_s_key.mdl
+1 progs/m_s_key.mdl
+2 progs/b_s_key.mdl
+1 progs/w_g_key.mdl
+1 progs/m_g_key.mdl
+2 progs/b_g_key.mdl
+1 progs/end1.mdl
+2 progs/end2.mdl
+2 progs/end3.mdl
+2 progs/end4.mdl
+1 progs/invulner.mdl
+1 progs/suit.mdl
+1 progs/invisibl.mdl
+1 progs/quaddama.mdl
+1 progs/player.mdl
+1 progs/eyes.mdl
+1 progs/h_player.mdl
+1 progs/gib1.mdl
+1 progs/gib2.mdl
+1 progs/gib3.mdl
+1 progs/s_bubble.spr
+1 progs/s_explod.spr
+1 progs/v_axe.mdl
+1 progs/v_shot.mdl
+1 progs/v_nail.mdl
+1 progs/v_rock.mdl
+1 progs/v_shot2.mdl
+1 progs/v_nail2.mdl
+1 progs/v_rock2.mdl
+1 progs/bolt.mdl
+1 progs/bolt2.mdl
+1 progs/bolt3.mdl
+1 progs/lavaball.mdl
+1 progs/missile.mdl
+1 progs/grenade.mdl
+1 progs/spike.mdl
+1 progs/s_spike.mdl
+1 progs/backpack.mdl
+1 progs/zom_gib.mdl
+1 progs/v_light.mdl
+2 progs/teleport.mdl
+1 progs/s_light.spr
+1 progs/flame.mdl
+1 progs/flame2.mdl
+1 maps/b_explob.bsp
+2 maps/b_exbox2.bsp
+2 progs/laser.mdl
+104
+1 progs.dat
+1 gfx.wad
+1 quake.rc
+1 default.cfg
+1 end1.bin
+2 end2.bin
+1 demo1.dem
+1 demo2.dem
+1 demo3.dem
+1 gfx/palette.lmp
+1 gfx/colormap.lmp
+2 gfx/pop.lmp
+1 gfx/complete.lmp
+1 gfx/inter.lmp
+1 gfx/ranking.lmp
+1 gfx/vidmodes.lmp
+1 gfx/finale.lmp
+1 gfx/conback.lmp
+1 gfx/qplaque.lmp
+1 gfx/menudot1.lmp
+1 gfx/menudot2.lmp
+1 gfx/menudot3.lmp
+1 gfx/menudot4.lmp
+1 gfx/menudot5.lmp
+1 gfx/menudot6.lmp
+1 gfx/menuplyr.lmp
+1 gfx/bigbox.lmp
+1 gfx/dim_modm.lmp
+1 gfx/dim_drct.lmp
+1 gfx/dim_ipx.lmp
+1 gfx/dim_tcp.lmp
+1 gfx/dim_mult.lmp
+1 gfx/mainmenu.lmp
+1 gfx/box_tl.lmp
+1 gfx/box_tm.lmp
+1 gfx/box_tr.lmp
+1 gfx/box_ml.lmp
+1 gfx/box_mm.lmp
+1 gfx/box_mm2.lmp
+1 gfx/box_mr.lmp
+1 gfx/box_bl.lmp
+1 gfx/box_bm.lmp
+1 gfx/box_br.lmp
+1 gfx/sp_menu.lmp
+1 gfx/ttl_sgl.lmp
+1 gfx/ttl_main.lmp
+1 gfx/ttl_cstm.lmp
+1 gfx/mp_menu.lmp
+1 gfx/netmen1.lmp
+1 gfx/netmen2.lmp
+1 gfx/netmen3.lmp
+1 gfx/netmen4.lmp
+1 gfx/netmen5.lmp
+1 gfx/sell.lmp
+1 gfx/help0.lmp
+1 gfx/help1.lmp
+1 gfx/help2.lmp
+1 gfx/help3.lmp
+1 gfx/help4.lmp
+1 gfx/help5.lmp
+1 gfx/pause.lmp
+1 gfx/loading.lmp
+1 gfx/p_option.lmp
+1 gfx/p_load.lmp
+1 gfx/p_save.lmp
+1 gfx/p_multi.lmp
+1 maps/start.bsp
+1 maps/e1m1.bsp
+1 maps/e1m2.bsp
+1 maps/e1m3.bsp
+1 maps/e1m4.bsp
+1 maps/e1m5.bsp
+1 maps/e1m6.bsp
+1 maps/e1m7.bsp
+1 maps/e1m8.bsp
+2 maps/e2m1.bsp
+2 maps/e2m2.bsp
+2 maps/e2m3.bsp
+2 maps/e2m4.bsp
+2 maps/e2m5.bsp
+2 maps/e2m6.bsp
+2 maps/e2m7.bsp
+2 maps/e3m1.bsp
+2 maps/e3m2.bsp
+2 maps/e3m3.bsp
+2 maps/e3m4.bsp
+2 maps/e3m5.bsp
+2 maps/e3m6.bsp
+2 maps/e3m7.bsp
+2 maps/e4m1.bsp
+2 maps/e4m2.bsp
+2 maps/e4m3.bsp
+2 maps/e4m4.bsp
+2 maps/e4m5.bsp
+2 maps/e4m6.bsp
+2 maps/e4m7.bsp
+2 maps/e4m8.bsp
+2 maps/end.bsp
+2 maps/dm1.bsp
+2 maps/dm2.bsp
+2 maps/dm3.bsp
+2 maps/dm4.bsp
+2 maps/dm5.bsp
+2 maps/dm6.bsp
--- /dev/null
+++ b/QW/progs/items.qc
@@ -1,0 +1,1660 @@
+void() W_SetCurrentAmmo;
+/* ALL LIGHTS SHOULD BE 0 1 0 IN COLOR ALL OTHER ITEMS SHOULD
+BE .8 .3 .4 IN COLOR */
+
+
+void() SUB_regen =
+{
+	self.model = self.mdl;          // restore original model
+	self.solid = SOLID_TRIGGER;     // allow it to be touched again
+	sound (self, CHAN_VOICE, "items/itembk2.wav", 1, ATTN_NORM);    // play respawn sound
+	setorigin (self, self.origin);
+};
+
+
+
+/*QUAKED noclass (0 0 0) (-8 -8 -8) (8 8 8)
+prints a warning message when spawned
+*/
+void() noclass =
+{
+	dprint ("noclass spawned at");
+	dprint (vtos(self.origin));
+	dprint ("\n");
+	remove (self);
+};
+
+void() q_touch;
+
+void() q_touch =
+{
+local entity    stemp;
+local float     best;
+local string    s;
+
+	if (other.classname != "player")
+		return;
+	if (other.health <= 0)
+		return;
+
+	self.mdl = self.model;
+
+	sound (other, CHAN_VOICE, self.noise, 1, ATTN_NORM);
+	stuffcmd (other, "bf\n");
+	self.solid = SOLID_NOT;
+	other.items = other.items | IT_QUAD;
+	self.model = string_null;
+		if (deathmatch == 4)
+		{
+			other.armortype = 0;
+			other.armorvalue = 0 * 0.01;
+			other.ammo_cells = 0;
+		}
+
+// do the apropriate action
+	other.super_time = 1;
+	other.super_damage_finished = self.cnt;
+
+	s=ftos(rint(other.super_damage_finished - time));
+
+	bprint (PRINT_LOW, other.netname);
+	if (deathmatch == 4)
+		bprint (PRINT_LOW, " recovered an OctaPower with ");
+	else 
+		bprint (PRINT_LOW, " recovered a Quad with ");
+	bprint (PRINT_LOW, s);
+	bprint (PRINT_LOW, " seconds remaining!\n");
+
+	activator = other;
+	SUB_UseTargets();                               // fire all targets / killtargets
+};
+
+
+void(float timeleft) DropQuad =
+{
+	local entity    item;
+
+	item = spawn();
+	item.origin = self.origin;
+	
+	item.velocity_z = 300;
+	item.velocity_x = -100 + (random() * 200);
+	item.velocity_y = -100 + (random() * 200);
+	
+	item.flags = FL_ITEM;
+	item.solid = SOLID_TRIGGER;
+	item.movetype = MOVETYPE_TOSS;
+	item.noise = "items/damage.wav";
+	setmodel (item, "progs/quaddama.mdl");
+	setsize (item, '-16 -16 -24', '16 16 32');
+	item.cnt = time + timeleft;
+	item.touch = q_touch;
+	item.nextthink = time + timeleft;    // remove it with the time left on it
+	item.think = SUB_Remove;
+};
+
+
+void() r_touch;
+
+void() r_touch =
+{
+local entity    stemp;
+local float     best;
+local string    s;
+
+	if (other.classname != "player")
+		return;
+	if (other.health <= 0)
+		return;
+
+	self.mdl = self.model;
+
+	sound (other, CHAN_VOICE, self.noise, 1, ATTN_NORM);
+	stuffcmd (other, "bf\n");
+	self.solid = SOLID_NOT;
+	other.items = other.items | IT_INVISIBILITY;
+	self.model = string_null;
+
+// do the apropriate action
+	other.invisible_time = 1;
+	other.invisible_finished = self.cnt;
+	s=ftos(rint(other.invisible_finished - time));
+	bprint (PRINT_LOW, other.netname);
+	bprint (PRINT_LOW, " recovered a Ring with ");
+	bprint (PRINT_LOW, s);
+	bprint (PRINT_LOW, " seconds remaining!\n");
+      
+
+	activator = other;
+	SUB_UseTargets();                               // fire all targets / killtargets
+};
+
+
+void(float timeleft) DropRing =
+{
+	local entity    item;
+
+	item = spawn();
+	item.origin = self.origin;
+	
+	item.velocity_z = 300;
+	item.velocity_x = -100 + (random() * 200);
+	item.velocity_y = -100 + (random() * 200);
+	
+	item.flags = FL_ITEM;
+	item.solid = SOLID_TRIGGER;
+	item.movetype = MOVETYPE_TOSS;
+	item.noise = "items/inv1.wav";
+	setmodel (item, "progs/invisibl.mdl");
+	setsize (item, '-16 -16 -24', '16 16 32');
+	item.cnt = time + timeleft;
+	item.touch = r_touch;
+	item.nextthink = time + timeleft;    // remove after 30 seconds
+	item.think = SUB_Remove;
+};
+
+/*
+============
+PlaceItem
+
+plants the object on the floor
+============
+*/
+void() PlaceItem =
+{
+	local float     oldz;
+
+	self.mdl = self.model;          // so it can be restored on respawn
+	self.flags = FL_ITEM;           // make extra wide
+	self.solid = SOLID_TRIGGER;
+	self.movetype = MOVETYPE_TOSS;  
+	self.velocity = '0 0 0';
+	self.origin_z = self.origin_z + 6;
+	oldz = self.origin_z;
+	if (!droptofloor())
+	{
+		dprint ("Bonus item fell out of level at ");
+		dprint (vtos(self.origin));
+		dprint ("\n");
+		remove(self);
+		return;
+	}
+};
+
+/*
+============
+StartItem
+
+Sets the clipping size and plants the object on the floor
+============
+*/
+void() StartItem =
+{
+	self.nextthink = time + 0.2;    // items start after other solids
+	self.think = PlaceItem;
+};
+
+/*
+=========================================================================
+
+HEALTH BOX
+
+=========================================================================
+*/
+//
+// T_Heal: add health to an entity, limiting health to max_health
+// "ignore" will ignore max_health limit
+//
+float (entity e, float healamount, float ignore) T_Heal =
+{
+	if (e.health <= 0)
+		return 0;
+	if ((!ignore) && (e.health >= other.max_health))
+		return 0;
+	healamount = ceil(healamount);
+
+	e.health = e.health + healamount;
+	if ((!ignore) && (e.health >= other.max_health))
+		e.health = other.max_health;
+		
+	if (e.health > 250)
+		e.health = 250;
+	return 1;
+};
+
+/*QUAKED item_health (.3 .3 1) (0 0 0) (32 32 32) rotten megahealth
+Health box. Normally gives 25 points.
+Rotten box heals 5-10 points,
+megahealth will add 100 health, then 
+rot you down to your maximum health limit, 
+one point per second.
+*/
+
+float   H_ROTTEN = 1;
+float   H_MEGA = 2;
+.float  healamount, healtype;
+void() health_touch;
+void() item_megahealth_rot;
+
+void() item_health =
+{       
+	self.touch = health_touch;
+
+	if (self.spawnflags & H_ROTTEN)
+	{
+		precache_model("maps/b_bh10.bsp");
+
+		precache_sound("items/r_item1.wav");
+		setmodel(self, "maps/b_bh10.bsp");
+		self.noise = "items/r_item1.wav";
+		self.healamount = 15;
+		self.healtype = 0;
+	}
+	else
+	if (self.spawnflags & H_MEGA)
+	{
+		precache_model("maps/b_bh100.bsp");
+		precache_sound("items/r_item2.wav");
+		setmodel(self, "maps/b_bh100.bsp");
+		self.noise = "items/r_item2.wav";
+		self.healamount = 100;
+		self.healtype = 2;
+	}
+	else
+	{
+		precache_model("maps/b_bh25.bsp");
+		precache_sound("items/health1.wav");
+		setmodel(self, "maps/b_bh25.bsp");
+		self.noise = "items/health1.wav";
+		self.healamount = 25;
+		self.healtype = 1;
+	}
+	setsize (self, '0 0 0', '32 32 56');
+	StartItem ();
+};
+
+
+void() health_touch =
+{
+	local   float amount;
+	local   string  s;
+	
+	if (deathmatch == 4)
+		if (other.invincible_time > 0)
+			return;
+
+	if (other.classname != "player")
+		return;
+	
+	if (self.healtype == 2) // Megahealth?  Ignore max_health...
+	{
+		if (other.health >= 250)
+			return;
+		if (!T_Heal(other, self.healamount, 1))
+			return;
+	}
+	else
+	{
+		if (!T_Heal(other, self.healamount, 0))
+			return;
+	}
+	
+	sprint(other, PRINT_LOW, "You receive ");
+	s = ftos(self.healamount);
+	sprint(other, PRINT_LOW, s);
+	sprint(other, PRINT_LOW, " health\n");
+	
+// health touch sound
+	sound(other, CHAN_ITEM, self.noise, 1, ATTN_NORM);
+
+	stuffcmd (other, "bf\n");
+	
+	self.model = string_null;
+	self.solid = SOLID_NOT;
+
+	// Megahealth = rot down the player's super health
+	if (self.healtype == 2)
+	{
+		other.items = other.items | IT_SUPERHEALTH;
+		if (deathmatch != 4)
+		{
+			self.nextthink = time + 5;
+			self.think = item_megahealth_rot;
+		}
+		self.owner = other;
+	}
+	else
+	{
+		if (deathmatch != 2)            // deathmatch 2 is the silly old rules
+		{
+			self.nextthink = time + 20;
+			self.think = SUB_regen;
+		}
+	}
+	
+	activator = other;
+	SUB_UseTargets();                               // fire all targets / killtargets
+};      
+
+void() item_megahealth_rot =
+{
+	other = self.owner;
+	
+	if (other.health > other.max_health)
+	{
+		other.health = other.health - 1;
+		self.nextthink = time + 1;
+		return;
+	}
+
+// it is possible for a player to die and respawn between rots, so don't
+// just blindly subtract the flag off
+	other.items = other.items - (other.items & IT_SUPERHEALTH);
+	
+	if (deathmatch != 2)    // deathmatch 2 is silly old rules
+	{
+		self.nextthink = time + 20;
+		self.think = SUB_regen;
+	}
+};
+
+/*
+===============================================================================
+
+ARMOR
+
+===============================================================================
+*/
+
+void() armor_touch;
+
+void() armor_touch =
+{
+	local   float   type, value, bit;
+	
+	if (other.health <= 0)
+		return;
+	if (other.classname != "player")
+		return;
+
+	if (deathmatch == 4)
+		if (other.invincible_time > 0)
+			return;
+
+	if (self.classname == "item_armor1")
+	{
+		type = 0.3;
+		value = 100;
+		bit = IT_ARMOR1;
+	}
+	if (self.classname == "item_armor2")
+	{
+		type = 0.6;
+		value = 150;
+		bit = IT_ARMOR2;
+	}
+	if (self.classname == "item_armorInv")
+	{
+		type = 0.8;
+		value = 200;
+		bit = IT_ARMOR3;
+	}
+	if (other.armortype*other.armorvalue >= type*value)
+		return;
+		
+	other.armortype = type;
+	other.armorvalue = value;
+	other.items = other.items - (other.items & (IT_ARMOR1 | IT_ARMOR2 | IT_ARMOR3)) + bit;
+
+	self.solid = SOLID_NOT;
+	self.model = string_null;
+	if (deathmatch != 2)
+		self.nextthink = time + 20;
+	self.think = SUB_regen;
+
+	sprint(other, PRINT_LOW, "You got armor\n");
+// armor touch sound
+	sound(other, CHAN_ITEM, "items/armor1.wav", 1, ATTN_NORM);
+	stuffcmd (other, "bf\n");
+	
+	activator = other;
+	SUB_UseTargets();                               // fire all targets / killtargets
+};
+
+
+/*QUAKED item_armor1 (0 .5 .8) (-16 -16 0) (16 16 32)
+*/
+
+void() item_armor1 =
+{
+	self.touch = armor_touch;
+	precache_model ("progs/armor.mdl");
+	setmodel (self, "progs/armor.mdl");
+	self.skin = 0;
+	setsize (self, '-16 -16 0', '16 16 56');
+	StartItem ();
+};
+
+/*QUAKED item_armor2 (0 .5 .8) (-16 -16 0) (16 16 32)
+*/
+
+void() item_armor2 =
+{
+	self.touch = armor_touch;
+	precache_model ("progs/armor.mdl");
+	setmodel (self, "progs/armor.mdl");
+	self.skin = 1;
+	setsize (self, '-16 -16 0', '16 16 56');
+	StartItem ();
+};
+
+/*QUAKED item_armorInv (0 .5 .8) (-16 -16 0) (16 16 32)
+*/
+
+void() item_armorInv =
+{
+	self.touch = armor_touch;
+	precache_model ("progs/armor.mdl");
+	setmodel (self, "progs/armor.mdl");
+	self.skin = 2;
+	setsize (self, '-16 -16 0', '16 16 56');
+	StartItem ();
+};
+
+/*
+===============================================================================
+
+WEAPONS
+
+===============================================================================
+*/
+
+void() bound_other_ammo =
+{
+	if (other.ammo_shells > 100)
+		other.ammo_shells = 100;
+	if (other.ammo_nails > 200)
+		other.ammo_nails = 200;
+	if (other.ammo_rockets > 100)
+		other.ammo_rockets = 100;               
+	if (other.ammo_cells > 100)
+		other.ammo_cells = 100;         
+};
+
+
+float(float w) RankForWeapon =
+{
+	if (w == IT_LIGHTNING)
+		return 1;
+	if (w == IT_ROCKET_LAUNCHER)
+		return 2;
+	if (w == IT_SUPER_NAILGUN)
+		return 3;
+	if (w == IT_GRENADE_LAUNCHER)
+		return 4;
+	if (w == IT_SUPER_SHOTGUN)
+		return 5;
+	if (w == IT_NAILGUN)
+		return 6;
+	return 7;
+};
+
+float (float w) WeaponCode =
+{
+	if (w == IT_SUPER_SHOTGUN)
+		return 3;
+	if (w == IT_NAILGUN)
+		return 4;
+	if (w == IT_SUPER_NAILGUN)
+		return 5;
+	if (w == IT_GRENADE_LAUNCHER)
+		return 6;
+	if (w == IT_ROCKET_LAUNCHER)
+		return 7;
+	if (w == IT_LIGHTNING)
+		return 8;
+	return 1;
+};
+
+/*
+=============
+Deathmatch_Weapon
+
+Deathmatch weapon change rules for picking up a weapon
+
+.float          ammo_shells, ammo_nails, ammo_rockets, ammo_cells;
+=============
+*/
+void(float old, float new) Deathmatch_Weapon =
+{
+	local float or, nr;
+
+// change self.weapon if desired
+	or = RankForWeapon (self.weapon);
+	nr = RankForWeapon (new);
+	if ( nr < or )
+		self.weapon = new;
+};
+
+/*
+=============
+weapon_touch
+=============
+*/
+float() W_BestWeapon;
+
+void() weapon_touch =
+{
+	local   float   hadammo, best, new, old;
+	local   entity  stemp;
+	local   float   leave;
+
+	// For client weapon_switch
+	local   float   w_switch;
+
+	if (!(other.flags & FL_CLIENT))
+		return;
+
+	if ((stof(infokey(other,"w_switch"))) == 0)
+		w_switch = 8;
+	else
+		w_switch = stof(infokey(other,"w_switch"));
+	
+// if the player was using his best weapon, change up to the new one if better          
+	stemp = self;
+	self = other;
+	best = W_BestWeapon();
+	self = stemp;
+
+	if (deathmatch == 2 || deathmatch == 3 || deathmatch == 5)
+		leave = 1;
+	else
+		leave = 0;
+	
+	if (self.classname == "weapon_nailgun")
+	{
+		if (leave && (other.items & IT_NAILGUN) )
+			return;
+		hadammo = other.ammo_nails;                     
+		new = IT_NAILGUN;
+		other.ammo_nails = other.ammo_nails + 30;
+	}
+	else if (self.classname == "weapon_supernailgun")
+	{
+		if (leave && (other.items & IT_SUPER_NAILGUN) )
+			return;
+		hadammo = other.ammo_rockets;                   
+		new = IT_SUPER_NAILGUN;
+		other.ammo_nails = other.ammo_nails + 30;
+	}
+	else if (self.classname == "weapon_supershotgun")
+	{
+		if (leave && (other.items & IT_SUPER_SHOTGUN) )
+			return;
+		hadammo = other.ammo_rockets;                   
+		new = IT_SUPER_SHOTGUN;
+		other.ammo_shells = other.ammo_shells + 5;
+	}
+	else if (self.classname == "weapon_rocketlauncher")
+	{
+		if (leave && (other.items & IT_ROCKET_LAUNCHER) )
+			return;
+		hadammo = other.ammo_rockets;                   
+		new = IT_ROCKET_LAUNCHER;
+		other.ammo_rockets = other.ammo_rockets + 5;
+	}
+	else if (self.classname == "weapon_grenadelauncher")
+	{
+		if (leave && (other.items & IT_GRENADE_LAUNCHER) )
+			return;
+		hadammo = other.ammo_rockets;                   
+		new = IT_GRENADE_LAUNCHER;
+		other.ammo_rockets = other.ammo_rockets + 5;
+	}
+	else if (self.classname == "weapon_lightning")
+	{
+		if (leave && (other.items & IT_LIGHTNING))
+			return;
+		hadammo = other.ammo_rockets;                   
+		new = IT_LIGHTNING;
+		other.ammo_cells = other.ammo_cells + 15;
+	}
+	else
+		objerror ("weapon_touch: unknown classname");
+
+	sprint (other, PRINT_LOW, "You got the ");
+	sprint (other, PRINT_LOW, self.netname);
+	sprint (other, PRINT_LOW, "\n");
+// weapon touch sound
+	sound (other, CHAN_ITEM, "weapons/pkup.wav", 1, ATTN_NORM);
+	stuffcmd (other, "bf\n");
+
+	bound_other_ammo ();
+
+// change to the weapon
+	old = other.items;
+	other.items = other.items | new;
+	
+	stemp = self;
+	self = other;
+
+	if ( WeaponCode(new) <= w_switch )
+	{
+		if (self.flags & FL_INWATER)
+		{
+			if (new != IT_LIGHTNING)
+			{
+				Deathmatch_Weapon (old, new);
+			}
+		}
+		else
+		{                
+			Deathmatch_Weapon (old, new);
+		}
+	}
+
+	W_SetCurrentAmmo();
+
+	self = stemp;
+
+	if (leave)
+		return;
+
+	if (deathmatch!=3 || deathmatch !=5)
+	{
+	// remove it in single player, or setup for respawning in deathmatch
+		self.model = string_null;
+		self.solid = SOLID_NOT;
+		if (deathmatch != 2)
+			self.nextthink = time + 30;
+		self.think = SUB_regen;
+	}
+	activator = other;
+	SUB_UseTargets();                               // fire all targets / killtargets
+};
+
+
+/*QUAKED weapon_supershotgun (0 .5 .8) (-16 -16 0) (16 16 32)
+*/
+
+void() weapon_supershotgun =
+{
+if (deathmatch <= 3)
+{
+	precache_model ("progs/g_shot.mdl");
+	setmodel (self, "progs/g_shot.mdl");
+	self.weapon = IT_SUPER_SHOTGUN;
+	self.netname = "Double-barrelled Shotgun";
+	self.touch = weapon_touch;
+	setsize (self, '-16 -16 0', '16 16 56');
+	StartItem ();
+}
+};
+
+/*QUAKED weapon_nailgun (0 .5 .8) (-16 -16 0) (16 16 32)
+*/
+
+void() weapon_nailgun =
+{
+if (deathmatch <= 3)
+{
+	precache_model ("progs/g_nail.mdl");
+	setmodel (self, "progs/g_nail.mdl");
+	self.weapon = IT_NAILGUN;
+	self.netname = "nailgun";
+	self.touch = weapon_touch;
+	setsize (self, '-16 -16 0', '16 16 56');
+	StartItem ();
+}
+};
+
+/*QUAKED weapon_supernailgun (0 .5 .8) (-16 -16 0) (16 16 32)
+*/
+
+void() weapon_supernailgun =
+{
+if (deathmatch <= 3)
+{
+	precache_model ("progs/g_nail2.mdl");
+	setmodel (self, "progs/g_nail2.mdl");
+	self.weapon = IT_SUPER_NAILGUN;
+	self.netname = "Super Nailgun";
+	self.touch = weapon_touch;
+	setsize (self, '-16 -16 0', '16 16 56');
+	StartItem ();
+}
+};
+
+/*QUAKED weapon_grenadelauncher (0 .5 .8) (-16 -16 0) (16 16 32)
+*/
+
+void() weapon_grenadelauncher =
+{
+if (deathmatch <= 3)
+{
+	precache_model ("progs/g_rock.mdl");
+	setmodel (self, "progs/g_rock.mdl");
+	self.weapon = 3;
+	self.netname = "Grenade Launcher";
+	self.touch = weapon_touch;
+	setsize (self, '-16 -16 0', '16 16 56');
+	StartItem ();
+}
+};
+
+/*QUAKED weapon_rocketlauncher (0 .5 .8) (-16 -16 0) (16 16 32)
+*/
+
+void() weapon_rocketlauncher =
+{
+if (deathmatch <= 3)
+{
+	precache_model ("progs/g_rock2.mdl");
+	setmodel (self, "progs/g_rock2.mdl");
+	self.weapon = 3;
+	self.netname = "Rocket Launcher";
+	self.touch = weapon_touch;
+	setsize (self, '-16 -16 0', '16 16 56');
+	StartItem ();
+}
+};
+
+
+/*QUAKED weapon_lightning (0 .5 .8) (-16 -16 0) (16 16 32)
+*/
+
+void() weapon_lightning =
+{
+if (deathmatch <= 3)
+{
+	precache_model ("progs/g_light.mdl");
+	setmodel (self, "progs/g_light.mdl");
+	self.weapon = 3;
+	self.netname = "Thunderbolt";
+	self.touch = weapon_touch;
+	setsize (self, '-16 -16 0', '16 16 56');
+	StartItem ();
+}
+};
+
+
+/*
+===============================================================================
+
+AMMO
+
+===============================================================================
+*/
+
+void() ammo_touch =
+{
+local entity    stemp;
+local float             best;
+
+	if (other.classname != "player")
+		return;
+	if (other.health <= 0)
+		return;
+
+// if the player was using his best weapon, change up to the new one if better          
+	stemp = self;
+	self = other;
+	best = W_BestWeapon();
+	self = stemp;
+
+
+// shotgun
+	if (self.weapon == 1)
+	{
+		if (other.ammo_shells >= 100)
+			return;
+		other.ammo_shells = other.ammo_shells + self.aflag;
+	}
+
+// spikes
+	if (self.weapon == 2)
+	{
+		if (other.ammo_nails >= 200)
+			return;
+		other.ammo_nails = other.ammo_nails + self.aflag;
+	}
+
+//      rockets
+	if (self.weapon == 3)
+	{
+		if (other.ammo_rockets >= 100)
+			return;
+		other.ammo_rockets = other.ammo_rockets + self.aflag;
+	}
+
+//      cells
+	if (self.weapon == 4)
+	{
+		if (other.ammo_cells >= 100)
+			return;
+		other.ammo_cells = other.ammo_cells + self.aflag;
+	}
+
+	bound_other_ammo ();
+	
+	sprint (other, PRINT_LOW, "You got the ");
+	sprint (other, PRINT_LOW, self.netname);
+	sprint (other, PRINT_LOW, "\n");
+// ammo touch sound
+	sound (other, CHAN_ITEM, "weapons/lock4.wav", 1, ATTN_NORM);
+	stuffcmd (other, "bf\n");
+
+// change to a better weapon if appropriate
+
+	if ( other.weapon == best )
+	{
+		stemp = self;
+		self = other;
+		self.weapon = W_BestWeapon();
+		W_SetCurrentAmmo ();
+		self = stemp;
+	}
+
+// if changed current ammo, update it
+	stemp = self;
+	self = other;
+	W_SetCurrentAmmo();
+	self = stemp;
+
+// remove it in single player, or setup for respawning in deathmatch
+	self.model = string_null;
+	self.solid = SOLID_NOT;
+	if (deathmatch != 2)
+		self.nextthink = time + 30;
+
+// Xian -- If playing in DM 3.0 mode, halve the time ammo respawns        
+
+	if (deathmatch == 3 || deathmatch == 5)        
+		self.nextthink = time + 15;
+
+	self.think = SUB_regen;
+
+	activator = other;
+	SUB_UseTargets();                               // fire all targets / killtargets
+};
+
+
+
+
+float WEAPON_BIG2 = 1;
+
+/*QUAKED item_shells (0 .5 .8) (0 0 0) (32 32 32) big
+*/
+
+void() item_shells =
+{
+	if (deathmatch == 4)
+		return;
+
+	self.touch = ammo_touch;
+
+	if (self.spawnflags & WEAPON_BIG2)
+	{
+		precache_model ("maps/b_shell1.bsp");
+		setmodel (self, "maps/b_shell1.bsp");
+		self.aflag = 40;
+	}
+	else
+	{
+		precache_model ("maps/b_shell0.bsp");
+		setmodel (self, "maps/b_shell0.bsp");
+		self.aflag = 20;
+	}
+	self.weapon = 1;
+	self.netname = "shells";
+	setsize (self, '0 0 0', '32 32 56');
+	StartItem ();
+};
+
+/*QUAKED item_spikes (0 .5 .8) (0 0 0) (32 32 32) big
+*/
+
+void() item_spikes =
+{
+	if (deathmatch == 4)
+		return;
+
+	self.touch = ammo_touch;
+
+	if (self.spawnflags & WEAPON_BIG2)
+	{
+		precache_model ("maps/b_nail1.bsp");
+		setmodel (self, "maps/b_nail1.bsp");
+		self.aflag = 50;
+	}
+	else
+	{
+		precache_model ("maps/b_nail0.bsp");
+		setmodel (self, "maps/b_nail0.bsp");
+		self.aflag = 25;
+	}
+	self.weapon = 2;
+	self.netname = "nails";
+	setsize (self, '0 0 0', '32 32 56');
+	StartItem ();
+
+};
+
+/*QUAKED item_rockets (0 .5 .8) (0 0 0) (32 32 32) big
+*/
+
+void() item_rockets =
+{
+	if (deathmatch == 4)
+		return;
+
+	self.touch = ammo_touch;
+
+	if (self.spawnflags & WEAPON_BIG2)
+	{
+		precache_model ("maps/b_rock1.bsp");
+		setmodel (self, "maps/b_rock1.bsp");
+		self.aflag = 10;
+	}
+	else
+	{
+		precache_model ("maps/b_rock0.bsp");
+		setmodel (self, "maps/b_rock0.bsp");
+		self.aflag = 5;
+	}
+	self.weapon = 3;
+	self.netname = "rockets";
+	setsize (self, '0 0 0', '32 32 56');
+	StartItem ();
+
+};
+
+
+/*QUAKED item_cells (0 .5 .8) (0 0 0) (32 32 32) big
+*/
+
+void() item_cells =
+{
+	if (deathmatch == 4)
+		return;
+
+	self.touch = ammo_touch;
+
+	if (self.spawnflags & WEAPON_BIG2)
+	{
+		precache_model ("maps/b_batt1.bsp");
+		setmodel (self, "maps/b_batt1.bsp");
+		self.aflag = 12;
+	}
+	else
+	{
+		precache_model ("maps/b_batt0.bsp");
+		setmodel (self, "maps/b_batt0.bsp");
+		self.aflag = 6;
+	}
+	self.weapon = 4;
+	self.netname = "cells";
+	setsize (self, '0 0 0', '32 32 56');
+	StartItem ();
+
+};
+
+
+/*QUAKED item_weapon (0 .5 .8) (0 0 0) (32 32 32) shotgun rocket spikes big
+DO NOT USE THIS!!!! IT WILL BE REMOVED!
+*/
+
+float WEAPON_SHOTGUN = 1;
+float WEAPON_ROCKET = 2;
+float WEAPON_SPIKES = 4;
+float WEAPON_BIG = 8;
+void() item_weapon =
+{
+	self.touch = ammo_touch;
+
+	if (self.spawnflags & WEAPON_SHOTGUN)
+	{
+		if (self.spawnflags & WEAPON_BIG)
+		{
+			precache_model ("maps/b_shell1.bsp");
+			setmodel (self, "maps/b_shell1.bsp");
+			self.aflag = 40;
+		}
+		else
+		{
+			precache_model ("maps/b_shell0.bsp");
+			setmodel (self, "maps/b_shell0.bsp");
+			self.aflag = 20;
+		}
+		self.weapon = 1;
+		self.netname = "shells";
+	}
+
+	if (self.spawnflags & WEAPON_SPIKES)
+	{
+		if (self.spawnflags & WEAPON_BIG)
+		{
+			precache_model ("maps/b_nail1.bsp");
+			setmodel (self, "maps/b_nail1.bsp");
+			self.aflag = 40;
+		}
+		else
+		{
+			precache_model ("maps/b_nail0.bsp");
+			setmodel (self, "maps/b_nail0.bsp");
+			self.aflag = 20;
+		}
+		self.weapon = 2;
+		self.netname = "spikes";
+	}
+
+	if (self.spawnflags & WEAPON_ROCKET)
+	{
+		if (self.spawnflags & WEAPON_BIG)
+		{
+			precache_model ("maps/b_rock1.bsp");
+			setmodel (self, "maps/b_rock1.bsp");
+			self.aflag = 10;
+		}
+		else
+		{
+			precache_model ("maps/b_rock0.bsp");
+			setmodel (self, "maps/b_rock0.bsp");
+			self.aflag = 5;
+		}
+		self.weapon = 3;
+		self.netname = "rockets";
+	}
+	
+	setsize (self, '0 0 0', '32 32 56');
+	StartItem ();
+};
+
+
+/*
+===============================================================================
+
+KEYS
+
+===============================================================================
+*/
+
+void() key_touch =
+{
+local entity    stemp;
+local float             best;
+
+	if (other.classname != "player")
+		return;
+	if (other.health <= 0)
+		return;
+	if (other.items & self.items)
+		return;
+
+	sprint (other, PRINT_LOW, "You got the ");
+	sprint (other, PRINT_LOW, self.netname);
+	sprint (other,PRINT_LOW, "\n");
+
+	sound (other, CHAN_ITEM, self.noise, 1, ATTN_NORM);
+	stuffcmd (other, "bf\n");
+	other.items = other.items | self.items;
+
+	self.solid = SOLID_NOT;
+	self.model = string_null;
+
+	activator = other;
+	SUB_UseTargets();                               // fire all targets / killtargets
+};
+
+
+void() key_setsounds =
+{
+	if (world.worldtype == 0)
+	{
+		precache_sound ("misc/medkey.wav");
+		self.noise = "misc/medkey.wav";
+	}
+	if (world.worldtype == 1)
+	{
+		precache_sound ("misc/runekey.wav");
+		self.noise = "misc/runekey.wav";
+	}
+	if (world.worldtype == 2)
+	{
+		precache_sound2 ("misc/basekey.wav");
+		self.noise = "misc/basekey.wav";
+	}
+};
+
+/*QUAKED item_key1 (0 .5 .8) (-16 -16 -24) (16 16 32)
+SILVER key
+In order for keys to work
+you MUST set your maps
+worldtype to one of the
+following:
+0: medieval
+1: metal
+2: base
+*/
+
+void() item_key1 =
+{
+	if (world.worldtype == 0)
+	{
+		precache_model ("progs/w_s_key.mdl");
+		setmodel (self, "progs/w_s_key.mdl");
+		self.netname = "silver key";
+	}
+	else if (world.worldtype == 1)
+	{
+		precache_model ("progs/m_s_key.mdl");
+		setmodel (self, "progs/m_s_key.mdl");
+		self.netname = "silver runekey";
+	}
+	else if (world.worldtype == 2)
+	{
+		precache_model2 ("progs/b_s_key.mdl");
+		setmodel (self, "progs/b_s_key.mdl");
+		self.netname = "silver keycard";
+	}
+	key_setsounds();
+	self.touch = key_touch;
+	self.items = IT_KEY1;
+	setsize (self, '-16 -16 -24', '16 16 32');
+	StartItem ();
+};
+
+/*QUAKED item_key2 (0 .5 .8) (-16 -16 -24) (16 16 32)
+GOLD key
+In order for keys to work
+you MUST set your maps
+worldtype to one of the
+following:
+0: medieval
+1: metal
+2: base
+*/
+
+void() item_key2 =
+{
+	if (world.worldtype == 0)
+	{
+		precache_model ("progs/w_g_key.mdl");
+		setmodel (self, "progs/w_g_key.mdl");
+		self.netname = "gold key";
+	}
+	if (world.worldtype == 1)
+	{
+		precache_model ("progs/m_g_key.mdl");
+		setmodel (self, "progs/m_g_key.mdl");
+		self.netname = "gold runekey";
+	}
+	if (world.worldtype == 2)
+	{
+		precache_model2 ("progs/b_g_key.mdl");
+		setmodel (self, "progs/b_g_key.mdl");
+		self.netname = "gold keycard";
+	}
+	key_setsounds();
+	self.touch = key_touch;
+	self.items = IT_KEY2;
+	setsize (self, '-16 -16 -24', '16 16 32');
+	StartItem ();
+};
+
+
+
+/*
+===============================================================================
+
+END OF LEVEL RUNES
+
+===============================================================================
+*/
+
+void() sigil_touch =
+{
+local entity    stemp;
+local float             best;
+
+	if (other.classname != "player")
+		return;
+	if (other.health <= 0)
+		return;
+
+	centerprint (other, "You got the rune!");
+
+	sound (other, CHAN_ITEM, self.noise, 1, ATTN_NORM);
+	stuffcmd (other, "bf\n");
+	self.solid = SOLID_NOT;
+	self.model = string_null;
+	serverflags = serverflags | (self.spawnflags & 15);
+	self.classname = "";            // so rune doors won't find it
+	
+	activator = other;
+	SUB_UseTargets();                               // fire all targets / killtargets
+};
+
+
+/*QUAKED item_sigil (0 .5 .8) (-16 -16 -24) (16 16 32) E1 E2 E3 E4
+End of level sigil, pick up to end episode and return to jrstart.
+*/
+
+void() item_sigil =
+{
+	if (!self.spawnflags)
+		objerror ("no spawnflags");
+
+	precache_sound ("misc/runekey.wav");
+	self.noise = "misc/runekey.wav";
+
+	if (self.spawnflags & 1)
+	{
+		precache_model ("progs/end1.mdl");
+		setmodel (self, "progs/end1.mdl");
+	}
+	if (self.spawnflags & 2)
+	{
+		precache_model2 ("progs/end2.mdl");
+		setmodel (self, "progs/end2.mdl");
+	}
+	if (self.spawnflags & 4)
+	{
+		precache_model2 ("progs/end3.mdl");
+		setmodel (self, "progs/end3.mdl");
+	}
+	if (self.spawnflags & 8)
+	{
+		precache_model2 ("progs/end4.mdl");
+		setmodel (self, "progs/end4.mdl");
+	}
+	
+	self.touch = sigil_touch;
+	setsize (self, '-16 -16 -24', '16 16 32');
+	StartItem ();
+};
+
+/*
+===============================================================================
+
+POWERUPS
+
+===============================================================================
+*/
+
+void() powerup_touch;
+
+
+void() powerup_touch =
+{
+local entity    stemp;
+local float             best;
+
+	if (other.classname != "player")
+		return;
+	if (other.health <= 0)
+		return;
+
+	sprint (other, PRINT_LOW, "You got the ");
+	sprint (other,PRINT_LOW,  self.netname);
+	sprint (other,PRINT_LOW, "\n");
+
+	self.mdl = self.model;
+	
+	if ((self.classname == "item_artifact_invulnerability") ||
+		(self.classname == "item_artifact_invisibility"))
+		self.nextthink = time + 60*5;
+	else
+		self.nextthink = time + 60;
+	
+	self.think = SUB_regen;
+
+	sound (other, CHAN_VOICE, self.noise, 1, ATTN_NORM);
+	stuffcmd (other, "bf\n");
+	self.solid = SOLID_NOT;
+	other.items = other.items | self.items;
+	self.model = string_null;
+
+// do the apropriate action
+	if (self.classname == "item_artifact_envirosuit")
+	{
+		other.rad_time = 1;
+		other.radsuit_finished = time + 30;
+	}
+	
+	if (self.classname == "item_artifact_invulnerability")
+	{
+		other.invincible_time = 1;
+		other.invincible_finished = time + 30;
+	}
+	
+	if (self.classname == "item_artifact_invisibility")
+	{
+		other.invisible_time = 1;
+		other.invisible_finished = time + 30;
+	}
+
+	if (self.classname == "item_artifact_super_damage")
+	{
+		if (deathmatch == 4)
+		{
+			other.armortype = 0;
+			other.armorvalue = 0 * 0.01;
+			other.ammo_cells = 0;
+		}
+		other.super_time = 1;
+		other.super_damage_finished = time + 30;
+	}       
+
+	activator = other;
+	SUB_UseTargets();                               // fire all targets / killtargets
+};
+
+
+
+/*QUAKED item_artifact_invulnerability (0 .5 .8) (-16 -16 -24) (16 16 32)
+Player is invulnerable for 30 seconds
+*/
+void() item_artifact_invulnerability =
+{
+	self.touch = powerup_touch;
+
+	precache_model ("progs/invulner.mdl");
+	precache_sound ("items/protect.wav");
+	precache_sound ("items/protect2.wav");
+	precache_sound ("items/protect3.wav");
+	self.noise = "items/protect.wav";
+	setmodel (self, "progs/invulner.mdl");
+	self.netname = "Pentagram of Protection";
+	self.effects = self.effects | EF_RED;
+	self.items = IT_INVULNERABILITY;
+	setsize (self, '-16 -16 -24', '16 16 32');
+	StartItem ();
+};
+
+/*QUAKED item_artifact_envirosuit (0 .5 .8) (-16 -16 -24) (16 16 32)
+Player takes no damage from water or slime for 30 seconds
+*/
+void() item_artifact_envirosuit =
+{
+	self.touch = powerup_touch;
+
+	precache_model ("progs/suit.mdl");
+	precache_sound ("items/suit.wav");
+	precache_sound ("items/suit2.wav");
+	self.noise = "items/suit.wav";
+	setmodel (self, "progs/suit.mdl");
+	self.netname = "Biosuit";
+	self.items = IT_SUIT;
+	setsize (self, '-16 -16 -24', '16 16 32');
+	StartItem ();
+};
+
+
+/*QUAKED item_artifact_invisibility (0 .5 .8) (-16 -16 -24) (16 16 32)
+Player is invisible for 30 seconds
+*/
+void() item_artifact_invisibility =
+{
+	self.touch = powerup_touch;
+
+	precache_model ("progs/invisibl.mdl");
+	precache_sound ("items/inv1.wav");
+	precache_sound ("items/inv2.wav");
+	precache_sound ("items/inv3.wav");
+	self.noise = "items/inv1.wav";
+	setmodel (self, "progs/invisibl.mdl");
+	self.netname = "Ring of Shadows";
+	self.items = IT_INVISIBILITY;
+	setsize (self, '-16 -16 -24', '16 16 32');
+	StartItem ();
+};
+
+
+/*QUAKED item_artifact_super_damage (0 .5 .8) (-16 -16 -24) (16 16 32)
+The next attack from the player will do 4x damage
+*/
+void() item_artifact_super_damage =
+{
+	self.touch = powerup_touch;
+
+	precache_model ("progs/quaddama.mdl");
+	precache_sound ("items/damage.wav");
+	precache_sound ("items/damage2.wav");
+	precache_sound ("items/damage3.wav");
+	self.noise = "items/damage.wav";
+	setmodel (self, "progs/quaddama.mdl");
+	if (deathmatch == 4)
+		self.netname = "OctaPower";	
+	else
+		self.netname = "Quad Damage";
+	self.items = IT_QUAD;
+	self.effects = self.effects | EF_BLUE;
+	setsize (self, '-16 -16 -24', '16 16 32');
+	StartItem ();
+};
+
+
+
+/*
+===============================================================================
+
+PLAYER BACKPACKS
+
+===============================================================================
+*/
+
+void() BackpackTouch =
+{
+	local string    s;
+	local   float   best, old, new;
+	local           entity  stemp;
+	local   float   acount;
+	local   float   b_switch;
+
+	if (deathmatch == 4)
+		if (other.invincible_time > 0)
+			return;
+
+	if ((stof(infokey(other,"b_switch"))) == 0)
+		b_switch = 8;
+	else
+		b_switch = stof(infokey(other,"b_switch"));
+	
+
+	if (other.classname != "player")
+		return;
+	if (other.health <= 0)
+		return;
+		
+	acount = 0;
+	sprint (other, PRINT_LOW, "You get ");
+ 
+	if (deathmatch == 4)
+	{       
+		other.health = other.health + 10;
+		sprint (other, PRINT_LOW, "10 additional health\n");
+		if ((other.health > 250) && (other.health < 300))
+			sound (other, CHAN_ITEM, "items/protect3.wav", 1, ATTN_NORM);
+		else
+			sound (other, CHAN_ITEM, "weapons/lock4.wav", 1, ATTN_NORM);
+		stuffcmd (other, "bf\n");
+		remove(self);
+
+		if (other.health >299)
+		{               
+			if (other.invincible_time != 1)
+			{                       
+				other.invincible_time = 1;
+				other.invincible_finished = time + 30;
+				other.items = other.items | IT_INVULNERABILITY;
+				
+				other.super_time = 1;
+				other.super_damage_finished = time + 30;
+				other.items = other.items | IT_QUAD;
+
+				other.ammo_cells = 0;		
+		
+	
+				sound (other, CHAN_VOICE, "boss1/sight1.wav", 1, ATTN_NORM);
+				stuffcmd (other, "bf\n");               
+				bprint (PRINT_HIGH, other.netname);
+				bprint (PRINT_HIGH, " attains bonus powers!!!\n");
+			}
+		}
+		self = other;
+		return;
+	}
+	if (self.items)
+		if ((other.items & self.items) == 0)
+		{
+			acount = 1;
+			sprint (other, PRINT_LOW, "the ");
+			sprint (other, PRINT_LOW, self.netname);
+		}
+ 
+// if the player was using his best weapon, change up to the new one if better          
+	stemp = self;
+	self = other;
+	best = W_BestWeapon();
+	self = stemp;
+
+// change weapons
+	other.ammo_shells = other.ammo_shells + self.ammo_shells;
+	other.ammo_nails = other.ammo_nails + self.ammo_nails;
+	other.ammo_rockets = other.ammo_rockets + self.ammo_rockets;
+	other.ammo_cells = other.ammo_cells + self.ammo_cells;
+
+	new = self.items;
+	if (!new)
+		new = other.weapon;
+	old = other.items;
+	other.items = other.items | self.items;
+	
+	bound_other_ammo ();
+
+	if (self.ammo_shells)
+	{
+		if (acount)
+			sprint(other, PRINT_LOW, ", ");
+		acount = 1;
+		s = ftos(self.ammo_shells);
+		sprint (other, PRINT_LOW, s);
+		sprint (other, PRINT_LOW, " shells");
+	}
+	if (self.ammo_nails)
+	{
+		if (acount)
+			sprint(other, PRINT_LOW, ", ");
+		acount = 1;
+		s = ftos(self.ammo_nails);
+		sprint (other, PRINT_LOW, s);
+		sprint (other, PRINT_LOW, " nails");
+	}
+	if (self.ammo_rockets)
+	{
+		if (acount)
+			sprint(other, PRINT_LOW, ", ");
+		acount = 1;
+		s = ftos(self.ammo_rockets);
+		sprint (other, PRINT_LOW, s);
+		sprint (other, PRINT_LOW, " rockets");
+	}
+	if (self.ammo_cells)
+	{
+		if (acount)
+			sprint(other, PRINT_LOW, ", ");
+		acount = 1;
+		s = ftos(self.ammo_cells);
+		sprint (other, PRINT_LOW, s);
+		sprint (other,PRINT_LOW, " cells");
+	}
+	
+	if ( (deathmatch==3 || deathmatch == 5) & ( (WeaponCode(new)==6) || (WeaponCode(new)==7) ) & (other.ammo_rockets < 5) )
+		other.ammo_rockets = 5;
+
+	sprint (other, PRINT_LOW, "\n");
+// backpack touch sound
+	sound (other, CHAN_ITEM, "weapons/lock4.wav", 1, ATTN_NORM);
+	stuffcmd (other, "bf\n");
+
+	remove(self);
+	self = other;
+	
+// change to the weapon
+	
+	
+	if ( WeaponCode(new) <= b_switch )
+	{
+		if (self.flags & FL_INWATER)
+		{
+			if (new != IT_LIGHTNING)
+			{
+				Deathmatch_Weapon (old, new);
+			}
+		}
+		else
+		{                
+			Deathmatch_Weapon (old, new);
+		}
+	}
+
+	W_SetCurrentAmmo ();
+};
+
+/*
+===============
+DropBackpack
+===============
+*/
+void() DropBackpack =
+{
+	local entity    item;
+
+	if (!(self.ammo_shells + self.ammo_nails + self.ammo_rockets + self.ammo_cells))
+		return; // nothing in it
+
+	item = spawn();
+	item.origin = self.origin - '0 0 24';
+	
+	item.items = self.weapon;
+	if (item.items == IT_AXE)
+		item.netname = "Axe";
+	else if (item.items == IT_SHOTGUN)
+		item.netname = "Shotgun";
+	else if (item.items == IT_SUPER_SHOTGUN)
+		item.netname = "Double-barrelled Shotgun";
+	else if (item.items == IT_NAILGUN)
+		item.netname = "Nailgun";
+	else if (item.items == IT_SUPER_NAILGUN)
+		item.netname = "Super Nailgun";
+	else if (item.items == IT_GRENADE_LAUNCHER)
+		item.netname = "Grenade Launcher";
+	else if (item.items == IT_ROCKET_LAUNCHER)
+		item.netname = "Rocket Launcher";
+	else if (item.items == IT_LIGHTNING)
+		item.netname = "Thunderbolt";
+	else
+		item.netname = "";
+
+	item.ammo_shells = self.ammo_shells;
+	item.ammo_nails = self.ammo_nails;
+	item.ammo_rockets = self.ammo_rockets;
+	item.ammo_cells = self.ammo_cells;
+
+	item.velocity_z = 300;
+	item.velocity_x = -100 + (random() * 200);
+	item.velocity_y = -100 + (random() * 200);
+	
+	item.flags = FL_ITEM;
+	item.solid = SOLID_TRIGGER;
+	item.movetype = MOVETYPE_TOSS;
+	setmodel (item, "progs/backpack.mdl");
+	setsize (item, '-16 -16 0', '16 16 56');
+	item.touch = BackpackTouch;
+	
+	item.nextthink = time + 120;    // remove after 2 minutes
+	item.think = SUB_Remove;
+};
+
+
--- /dev/null
+++ b/QW/progs/misc.qc
@@ -1,0 +1,730 @@
+
+/*QUAKED info_null (0 0.5 0) (-4 -4 -4) (4 4 4)
+Used as a positional target for spotlights, etc.
+*/
+void() info_null =
+{
+	remove(self);
+};
+
+/*QUAKED info_notnull (0 0.5 0) (-4 -4 -4) (4 4 4)
+Used as a positional target for lightning.
+*/
+void() info_notnull =
+{
+};
+
+//============================================================================
+
+float START_OFF = 1;
+
+void() light_use =
+{
+	if (self.spawnflags & START_OFF)
+	{
+		lightstyle(self.style, "m");
+		self.spawnflags = self.spawnflags - START_OFF;
+	}
+	else
+	{
+		lightstyle(self.style, "a");
+		self.spawnflags = self.spawnflags + START_OFF;
+	}
+};
+
+/*QUAKED light (0 1 0) (-8 -8 -8) (8 8 8) START_OFF
+Non-displayed light.
+Default light value is 300
+Default style is 0
+If targeted, it will toggle between on or off.
+*/
+void() light =
+{
+	if (!self.targetname)
+	{       // inert light
+		remove(self);
+		return;
+	}
+	
+	if (self.style >= 32)
+	{
+		self.use = light_use;
+		if (self.spawnflags & START_OFF)
+			lightstyle(self.style, "a");
+		else
+			lightstyle(self.style, "m");
+	}
+};
+
+/*QUAKED light_fluoro (0 1 0) (-8 -8 -8) (8 8 8) START_OFF
+Non-displayed light.
+Default light value is 300
+Default style is 0
+If targeted, it will toggle between on or off.
+Makes steady fluorescent humming sound
+*/
+void() light_fluoro =
+{
+	if (self.style >= 32)
+	{
+		self.use = light_use;
+		if (self.spawnflags & START_OFF)
+			lightstyle(self.style, "a");
+		else
+			lightstyle(self.style, "m");
+	}
+	
+	precache_sound ("ambience/fl_hum1.wav");
+	ambientsound (self.origin, "ambience/fl_hum1.wav", 0.5, ATTN_STATIC);
+};
+
+/*QUAKED light_fluorospark (0 1 0) (-8 -8 -8) (8 8 8)
+Non-displayed light.
+Default light value is 300
+Default style is 10
+Makes sparking, broken fluorescent sound
+*/
+void() light_fluorospark =
+{
+	if (!self.style)
+		self.style = 10;
+
+	precache_sound ("ambience/buzz1.wav");
+	ambientsound (self.origin, "ambience/buzz1.wav", 0.5, ATTN_STATIC);
+};
+
+/*QUAKED light_globe (0 1 0) (-8 -8 -8) (8 8 8)
+Sphere globe light.
+Default light value is 300
+Default style is 0
+*/
+void() light_globe =
+{
+	precache_model ("progs/s_light.spr");
+	setmodel (self, "progs/s_light.spr");
+	makestatic (self);
+};
+
+void() FireAmbient =
+{
+	precache_sound ("ambience/fire1.wav");
+// attenuate fast
+	ambientsound (self.origin, "ambience/fire1.wav", 0.5, ATTN_STATIC);
+};
+
+/*QUAKED light_torch_small_walltorch (0 .5 0) (-10 -10 -20) (10 10 20)
+Short wall torch
+Default light value is 200
+Default style is 0
+*/
+void() light_torch_small_walltorch =
+{
+	precache_model ("progs/flame.mdl");
+	setmodel (self, "progs/flame.mdl");
+	FireAmbient ();
+	makestatic (self);
+};
+
+/*QUAKED light_flame_large_yellow (0 1 0) (-10 -10 -12) (12 12 18)
+Large yellow flame ball
+*/
+void() light_flame_large_yellow =
+{
+	precache_model ("progs/flame2.mdl");
+	setmodel (self, "progs/flame2.mdl");
+	self.frame = 1;
+	FireAmbient ();
+	makestatic (self);
+};
+
+/*QUAKED light_flame_small_yellow (0 1 0) (-8 -8 -8) (8 8 8) START_OFF
+Small yellow flame ball
+*/
+void() light_flame_small_yellow =
+{
+	precache_model ("progs/flame2.mdl");
+	setmodel (self, "progs/flame2.mdl");
+	FireAmbient ();
+	makestatic (self);
+};
+
+/*QUAKED light_flame_small_white (0 1 0) (-10 -10 -40) (10 10 40) START_OFF
+Small white flame ball
+*/
+void() light_flame_small_white =
+{
+	precache_model ("progs/flame2.mdl");
+	setmodel (self, "progs/flame2.mdl");
+	FireAmbient ();
+	makestatic (self);
+};
+
+//============================================================================
+
+
+/*QUAKED misc_fireball (0 .5 .8) (-8 -8 -8) (8 8 8)
+Lava Balls
+*/
+
+void() fire_fly;
+void() fire_touch;
+void() misc_fireball =
+{
+	
+	precache_model ("progs/lavaball.mdl");
+	self.classname = "fireball";
+	self.nextthink = time + (random() * 5);
+	self.think = fire_fly;
+	if (!self.speed)
+		self.speed == 1000;
+};
+
+void() fire_fly =
+{
+local entity    fireball;
+
+	fireball = spawn();
+	fireball.solid = SOLID_TRIGGER;
+	fireball.movetype = MOVETYPE_TOSS;
+	fireball.velocity = '0 0 1000';
+	fireball.velocity_x = (random() * 100) - 50;
+	fireball.velocity_y = (random() * 100) - 50;
+	fireball.velocity_z = self.speed + (random() * 200);
+	fireball.classname = "fireball";
+	setmodel (fireball, "progs/lavaball.mdl");
+	setsize (fireball, '0 0 0', '0 0 0');
+	setorigin (fireball, self.origin);
+	fireball.nextthink = time + 5;
+	fireball.think = SUB_Remove;
+	fireball.touch = fire_touch;
+	
+	self.nextthink = time + (random() * 5) + 3;
+	self.think = fire_fly;
+};
+
+
+void() fire_touch =
+{
+	T_Damage (other, self, self, 20);
+	remove(self);
+};
+
+//============================================================================
+
+
+void() barrel_explode =
+{
+	self.takedamage = DAMAGE_NO;
+	self.classname = "explo_box";
+	// did say self.owner
+	T_RadiusDamage (self, self, 160, world, "");
+	WriteByte (MSG_MULTICAST, SVC_TEMPENTITY);
+	WriteByte (MSG_MULTICAST, TE_EXPLOSION);
+	WriteCoord (MSG_MULTICAST, self.origin_x);
+	WriteCoord (MSG_MULTICAST, self.origin_y);
+	WriteCoord (MSG_MULTICAST, self.origin_z+32);
+	multicast (self.origin, MULTICAST_PHS);
+	remove (self);
+};
+
+
+
+/*QUAKED misc_explobox (0 .5 .8) (0 0 0) (32 32 64)
+TESTING THING
+*/
+
+void() misc_explobox =
+{
+	local float     oldz;
+	
+	self.solid = SOLID_BBOX;
+	self.movetype = MOVETYPE_NONE;
+	precache_model ("maps/b_explob.bsp");
+	setmodel (self, "maps/b_explob.bsp");
+	setsize (self, '0 0 0', '32 32 64');
+	precache_sound ("weapons/r_exp3.wav");
+	self.health = 20;
+	self.th_die = barrel_explode;
+	self.takedamage = DAMAGE_AIM;
+
+	self.origin_z = self.origin_z + 2;
+	oldz = self.origin_z;
+	droptofloor();
+	if (oldz - self.origin_z > 250)
+	{
+		dprint ("item fell out of level at ");
+		dprint (vtos(self.origin));
+		dprint ("\n");
+		remove(self);
+	}
+};
+
+
+
+
+/*QUAKED misc_explobox2 (0 .5 .8) (0 0 0) (32 32 64)
+Smaller exploding box, REGISTERED ONLY
+*/
+
+void() misc_explobox2 =
+{
+	local float     oldz;
+	
+	self.solid = SOLID_BBOX;
+	self.movetype = MOVETYPE_NONE;
+	precache_model2 ("maps/b_exbox2.bsp");
+	setmodel (self, "maps/b_exbox2.bsp");
+	setsize (self, '0 0 0', '32 32 32');
+	precache_sound ("weapons/r_exp3.wav");
+	self.health = 20;
+	self.th_die = barrel_explode;
+	self.takedamage = DAMAGE_AIM;
+
+	self.origin_z = self.origin_z + 2;
+	oldz = self.origin_z;
+	droptofloor();
+	if (oldz - self.origin_z > 250)
+	{
+		dprint ("item fell out of level at ");
+		dprint (vtos(self.origin));
+		dprint ("\n");
+		remove(self);
+	}
+};
+
+//============================================================================
+
+float SPAWNFLAG_SUPERSPIKE      = 1;
+float SPAWNFLAG_LASER = 2;
+
+void() Laser_Touch =
+{
+	local vector org;
+	
+	if (other == self.owner)
+		return;         // don't explode on owner
+
+	if (pointcontents(self.origin) == CONTENT_SKY)
+	{
+		remove(self);
+		return;
+	}
+	
+	sound (self, CHAN_WEAPON, "enforcer/enfstop.wav", 1, ATTN_STATIC);
+	org = self.origin - 8*normalize(self.velocity);
+
+	if (other.health)
+	{
+		SpawnBlood (org, 15);
+		other.deathtype = "laser";
+		T_Damage (other, self, self.owner, 15);
+	}
+	else
+	{
+		WriteByte (MSG_MULTICAST, SVC_TEMPENTITY);
+		WriteByte (MSG_MULTICAST, TE_GUNSHOT);
+		WriteByte (MSG_MULTICAST, 5);
+		WriteCoord (MSG_MULTICAST, org_x);
+		WriteCoord (MSG_MULTICAST, org_y);
+		WriteCoord (MSG_MULTICAST, org_z);
+		multicast (org, MULTICAST_PVS);
+	}
+	
+	remove(self);   
+};
+
+void(vector org, vector vec) LaunchLaser =
+{
+	local   vector  vec;
+		
+	if (self.classname == "monster_enforcer")
+		sound (self, CHAN_WEAPON, "enforcer/enfire.wav", 1, ATTN_NORM);
+
+	vec = normalize(vec);
+	
+	newmis = spawn();
+	newmis.owner = self;
+	newmis.movetype = MOVETYPE_FLY;
+	newmis.solid = SOLID_BBOX;
+	newmis.effects = EF_DIMLIGHT;
+
+	setmodel (newmis, "progs/laser.mdl");
+	setsize (newmis, '0 0 0', '0 0 0');             
+
+	setorigin (newmis, org);
+
+	newmis.velocity = vec * 600;
+	newmis.angles = vectoangles(newmis.velocity);
+
+	newmis.nextthink = time + 5;
+	newmis.think = SUB_Remove;
+	newmis.touch = Laser_Touch;
+};
+
+void() spikeshooter_use =
+{
+	if (self.spawnflags & SPAWNFLAG_LASER)
+	{
+		sound (self, CHAN_VOICE, "enforcer/enfire.wav", 1, ATTN_NORM);
+		LaunchLaser (self.origin, self.movedir);
+	}
+	else
+	{
+		sound (self, CHAN_VOICE, "weapons/spike2.wav", 1, ATTN_NORM);
+		launch_spike (self.origin, self.movedir);
+		newmis.velocity = self.movedir * 500;
+		if (self.spawnflags & SPAWNFLAG_SUPERSPIKE)
+			newmis.touch = superspike_touch;
+	}
+};
+
+void() shooter_think =
+{
+	spikeshooter_use ();
+	self.nextthink = time + self.wait;
+	newmis.velocity = self.movedir * 500;
+};
+
+
+/*QUAKED trap_spikeshooter (0 .5 .8) (-8 -8 -8) (8 8 8) superspike laser
+When triggered, fires a spike in the direction set in QuakeEd.
+Laser is only for REGISTERED.
+*/
+
+void() trap_spikeshooter =
+{
+	SetMovedir ();
+	self.use = spikeshooter_use;
+	if (self.spawnflags & SPAWNFLAG_LASER)
+	{
+		precache_model2 ("progs/laser.mdl");
+		
+		precache_sound2 ("enforcer/enfire.wav");
+		precache_sound2 ("enforcer/enfstop.wav");
+	}
+	else
+		precache_sound ("weapons/spike2.wav");
+};
+
+
+/*QUAKED trap_shooter (0 .5 .8) (-8 -8 -8) (8 8 8) superspike laser
+Continuously fires spikes.
+"wait" time between spike (1.0 default)
+"nextthink" delay before firing first spike, so multiple shooters can be stagered.
+*/
+void() trap_shooter =
+{
+	trap_spikeshooter ();
+	
+	if (self.wait == 0)
+		self.wait = 1;
+	self.nextthink = self.nextthink + self.wait + self.ltime;
+	self.think = shooter_think;
+};
+
+
+
+/*
+===============================================================================
+
+
+===============================================================================
+*/
+
+
+void() make_bubbles;
+void() bubble_remove;
+void() bubble_bob;
+
+/*QUAKED air_bubbles (0 .5 .8) (-8 -8 -8) (8 8 8)
+
+testing air bubbles
+*/
+
+void() air_bubbles =
+{
+	remove (self);
+};
+
+void() make_bubbles =
+{
+local entity    bubble;
+
+	bubble = spawn();
+	setmodel (bubble, "progs/s_bubble.spr");
+	setorigin (bubble, self.origin);
+	bubble.movetype = MOVETYPE_NOCLIP;
+	bubble.solid = SOLID_NOT;
+	bubble.velocity = '0 0 15';
+	bubble.nextthink = time + 0.5;
+	bubble.think = bubble_bob;
+	bubble.touch = bubble_remove;
+	bubble.classname = "bubble";
+	bubble.frame = 0;
+	bubble.cnt = 0;
+	setsize (bubble, '-8 -8 -8', '8 8 8');
+	self.nextthink = time + random() + 0.5;
+	self.think = make_bubbles;
+};
+
+void() bubble_split =
+{
+local entity    bubble;
+	bubble = spawn();
+	setmodel (bubble, "progs/s_bubble.spr");
+	setorigin (bubble, self.origin);
+	bubble.movetype = MOVETYPE_NOCLIP;
+	bubble.solid = SOLID_NOT;
+	bubble.velocity = self.velocity;
+	bubble.nextthink = time + 0.5;
+	bubble.think = bubble_bob;
+	bubble.touch = bubble_remove;
+	bubble.classname = "bubble";
+	bubble.frame = 1;
+	bubble.cnt = 10;
+	setsize (bubble, '-8 -8 -8', '8 8 8');
+	self.frame = 1;
+	self.cnt = 10;
+	if (self.waterlevel != 3)
+		remove (self);
+};
+
+void() bubble_remove =
+{
+	if (other.classname == self.classname)
+	{
+//              dprint ("bump");
+		return;
+	}
+	remove(self);
+};
+
+void() bubble_bob =
+{
+local float             rnd1, rnd2, rnd3;
+local vector    vtmp1, modi;
+
+	self.cnt = self.cnt + 1;
+	if (self.cnt == 4)
+		bubble_split();
+	if (self.cnt == 20)
+		remove(self);
+
+	rnd1 = self.velocity_x + (-10 + (random() * 20));
+	rnd2 = self.velocity_y + (-10 + (random() * 20));
+	rnd3 = self.velocity_z + 10 + random() * 10;
+
+	if (rnd1 > 10)
+		rnd1 = 5;
+	if (rnd1 < -10)
+		rnd1 = -5;
+		
+	if (rnd2 > 10)
+		rnd2 = 5;
+	if (rnd2 < -10)
+		rnd2 = -5;
+		
+	if (rnd3 < 10)
+		rnd3 = 15;
+	if (rnd3 > 30)
+		rnd3 = 25;
+	
+	self.velocity_x = rnd1;
+	self.velocity_y = rnd2;
+	self.velocity_z = rnd3;
+		
+	self.nextthink = time + 0.5;
+	self.think = bubble_bob;
+};
+
+/*~>~<~>~<~>~<~>~<~>~<~>~<~>~<~>~<~>~<~>~<~>~<~>~<~>~<~>~<~>~<~>~<~>~<~>
+~>~<~>~<~>~<~>~<~>~<~>~<~>~<~>~<~>~<~>~<~>~<~>~<~>~<~>~<~>~<~>~<~>~<~>~*/
+
+/*QUAKED viewthing (0 .5 .8) (-8 -8 -8) (8 8 8)
+
+Just for the debugging level.  Don't use
+*/
+
+void() viewthing =
+
+{
+	self.movetype = MOVETYPE_NONE;
+	self.solid = SOLID_NOT;
+	precache_model ("progs/player.mdl");
+	setmodel (self, "progs/player.mdl");
+};
+
+
+/*
+==============================================================================
+
+SIMPLE BMODELS
+
+==============================================================================
+*/
+
+void() func_wall_use =
+{       // change to alternate textures
+	self.frame = 1 - self.frame;
+};
+
+/*QUAKED func_wall (0 .5 .8) ?
+This is just a solid wall if not inhibitted
+*/
+void() func_wall =
+{
+	self.angles = '0 0 0';
+	self.movetype = MOVETYPE_PUSH;  // so it doesn't get pushed by anything
+	self.solid = SOLID_BSP;
+	self.use = func_wall_use;
+	setmodel (self, self.model);
+};
+
+
+/*QUAKED func_illusionary (0 .5 .8) ?
+A simple entity that looks solid but lets you walk through it.
+*/
+void() func_illusionary =
+
+{
+	self.angles = '0 0 0';
+	self.movetype = MOVETYPE_NONE;
+	self.solid = SOLID_NOT;
+	setmodel (self, self.model);
+	makestatic ();
+};
+
+/*QUAKED func_episodegate (0 .5 .8) ? E1 E2 E3 E4
+This bmodel will appear if the episode has allready been completed, so players can't reenter it.
+*/
+void() func_episodegate =
+
+{
+	if (!(serverflags & self.spawnflags))
+		return;                 // can still enter episode
+
+	self.angles = '0 0 0';
+	self.movetype = MOVETYPE_PUSH;  // so it doesn't get pushed by anything
+	self.solid = SOLID_BSP;
+	self.use = func_wall_use;
+	setmodel (self, self.model);
+};
+
+/*QUAKED func_bossgate (0 .5 .8) ?
+This bmodel appears unless players have all of the episode sigils.
+*/
+void() func_bossgate =
+
+{
+	if ( (serverflags & 15) == 15)
+		return;         // all episodes completed
+	self.angles = '0 0 0';
+	self.movetype = MOVETYPE_PUSH;  // so it doesn't get pushed by anything
+	self.solid = SOLID_BSP;
+	self.use = func_wall_use;
+	setmodel (self, self.model);
+};
+
+//============================================================================
+/*QUAKED ambient_suck_wind (0.3 0.1 0.6) (-10 -10 -8) (10 10 8)
+*/
+void() ambient_suck_wind =
+{
+	precache_sound ("ambience/suck1.wav");
+	ambientsound (self.origin, "ambience/suck1.wav", 1, ATTN_STATIC);
+};
+
+/*QUAKED ambient_drone (0.3 0.1 0.6) (-10 -10 -8) (10 10 8)
+*/
+void() ambient_drone =
+{
+	precache_sound ("ambience/drone6.wav");
+	ambientsound (self.origin, "ambience/drone6.wav", 0.5, ATTN_STATIC);
+};
+
+/*QUAKED ambient_flouro_buzz (0.3 0.1 0.6) (-10 -10 -8) (10 10 8)
+*/
+void() ambient_flouro_buzz =
+{
+	precache_sound ("ambience/buzz1.wav");
+	ambientsound (self.origin, "ambience/buzz1.wav", 1, ATTN_STATIC);
+};
+/*QUAKED ambient_drip (0.3 0.1 0.6) (-10 -10 -8) (10 10 8)
+*/
+void() ambient_drip =
+{
+	precache_sound ("ambience/drip1.wav");
+	ambientsound (self.origin, "ambience/drip1.wav", 0.5, ATTN_STATIC);
+};
+/*QUAKED ambient_comp_hum (0.3 0.1 0.6) (-10 -10 -8) (10 10 8)
+*/
+void() ambient_comp_hum =
+{
+	precache_sound ("ambience/comp1.wav");
+	ambientsound (self.origin, "ambience/comp1.wav", 1, ATTN_STATIC);
+};
+/*QUAKED ambient_thunder (0.3 0.1 0.6) (-10 -10 -8) (10 10 8)
+*/
+void() ambient_thunder =
+{
+	precache_sound ("ambience/thunder1.wav");
+	ambientsound (self.origin, "ambience/thunder1.wav", 0.5, ATTN_STATIC);
+};
+/*QUAKED ambient_light_buzz (0.3 0.1 0.6) (-10 -10 -8) (10 10 8)
+*/
+void() ambient_light_buzz =
+{
+	precache_sound ("ambience/fl_hum1.wav");
+	ambientsound (self.origin, "ambience/fl_hum1.wav", 0.5, ATTN_STATIC);
+};
+/*QUAKED ambient_swamp1 (0.3 0.1 0.6) (-10 -10 -8) (10 10 8)
+*/
+void() ambient_swamp1 =
+{
+	precache_sound ("ambience/swamp1.wav");
+	ambientsound (self.origin, "ambience/swamp1.wav", 0.5, ATTN_STATIC);
+};
+/*QUAKED ambient_swamp2 (0.3 0.1 0.6) (-10 -10 -8) (10 10 8)
+*/
+void() ambient_swamp2 =
+{
+	precache_sound ("ambience/swamp2.wav");
+	ambientsound (self.origin, "ambience/swamp2.wav", 0.5, ATTN_STATIC);
+};
+
+//============================================================================
+
+void() noise_think =
+{
+	self.nextthink = time + 0.5;
+	sound (self, 1, "enforcer/enfire.wav", 1, ATTN_NORM);
+	sound (self, 2, "enforcer/enfstop.wav", 1, ATTN_NORM);
+	sound (self, 3, "enforcer/sight1.wav", 1, ATTN_NORM);
+	sound (self, 4, "enforcer/sight2.wav", 1, ATTN_NORM);
+	sound (self, 5, "enforcer/sight3.wav", 1, ATTN_NORM);
+	sound (self, 6, "enforcer/sight4.wav", 1, ATTN_NORM);
+	sound (self, 7, "enforcer/pain1.wav", 1, ATTN_NORM);
+};
+
+/*QUAKED misc_noisemaker (1 0.5 0) (-10 -10 -10) (10 10 10)
+
+For optimzation testing, starts a lot of sounds.
+*/
+
+void() misc_noisemaker =
+
+{
+	precache_sound2 ("enforcer/enfire.wav");
+	precache_sound2 ("enforcer/enfstop.wav");
+	precache_sound2 ("enforcer/sight1.wav");
+	precache_sound2 ("enforcer/sight2.wav");
+	precache_sound2 ("enforcer/sight3.wav");
+	precache_sound2 ("enforcer/sight4.wav");
+	precache_sound2 ("enforcer/pain1.wav");
+	precache_sound2 ("enforcer/pain2.wav");
+	precache_sound2 ("enforcer/death1.wav");
+	precache_sound2 ("enforcer/idle1.wav");
+
+	self.nextthink = time + 0.1 + random();
+	self.think = noise_think;
+};
--- /dev/null
+++ b/QW/progs/models.qc
@@ -1,0 +1,585 @@
+
+/*
+===============================================================================
+
+WORLD WEAPONS
+
+===============================================================================
+*/
+
+$modelname g_shot
+$cd /raid/quake/id1/models/g_shot
+$origin 0 0 -24
+$flags 8		// client side rotate
+$base base
+$skin skin
+$frame shot1
+
+
+$modelname g_nail
+$cd /raid/quake/id1/models/g_nail
+$flags 8		// client side rotate
+$origin 0 0 -24
+$base base
+$skin skin
+$frame shot1
+
+
+$modelname g_nail2
+$cd /raid/quake/id1/models/g_nail2
+$flags 8		// client side rotate
+$origin 0 0 -24
+$base base
+$skin skin
+$frame shot2
+
+
+$modelname g_rock
+$cd /raid/quake/id1/models/g_rock
+$flags 8		// client side rotate
+$origin 0 0 -24
+$base base
+$skin skin
+$frame shot1
+
+
+$modelname g_rock2
+$cd /raid/quake/id1/models/g_rock2
+$flags 8		// client side rotate
+$origin 0 0 -24
+$base base
+$skin skin
+$frame shot1
+
+$modelname g_light
+$cd /raid/quake/id1/models/g_light
+$flags 8		// client side rotate
+$origin 0 0 -24
+$base base
+$skin skin
+$frame shot1
+
+/*
+===============================================================================
+
+VIEW WEAPONS
+
+===============================================================================
+*/
+
+$modelname v_axe
+$cd /raid/quake/id1/models/v_axe
+$origin 0 5 54
+$base base
+$skin skin
+$frame frame1 frame2 frame3 frame4 frame5 frame6 frame7 frame8 frame9
+
+
+$modelname v_shot
+$cd /raid/quake/id1/models/v_shot
+$origin 0 0 54
+$base base
+$skin skin
+$frame shot1 shot2 shot3 shot4 shot5 shot6 shot7
+
+
+$modelname v_shot2
+$cd /raid/quake/id1/models/v_shot2
+$origin 0 0 56
+$base base
+$skin skin
+$frame shot1 shot2 shot3 shot4 shot5 shot6 shot7
+
+
+$modelname v_rock2
+$cd /raid/quake/id1/models/v_rock2
+$origin 0 0 54
+$base base
+$skin skin
+$frame shot1 shot2 shot3 shot4 shot5 shot6 shot6
+
+
+$modelname v_rock
+$cd /raid/quake/id1/models/v_rock
+$origin 0 0 54
+$base base
+$skin skin
+$frame shot1 shot2 shot3 shot4 shot5 shot6 shot7
+
+
+$modelname v_nail2
+$cd /raid/quake/id1/models/v_nail2
+$origin 0 0 54
+$base base
+$skin skin
+$frame shot1 shot2 shot3 shot4 shot5 shot6 shot7 shot8 shot9
+
+
+$modelname v_nail
+$cd /raid/quake/id1/models/v_nail
+$origin 0 0 54
+$base base
+$skin skin
+$frame shot1 shot2 shot3 shot4 shot5 shot6 shot7 shot8 shot9
+
+$modelname v_light
+$cd /raid/quake/id1/models/v_light
+$origin 0 0 54
+$base base
+$skin skin
+$frame shot1 shot2 shot3 shot4 shot5
+
+
+/*
+===============================================================================
+
+ITEMS
+
+===============================================================================
+*/
+
+$modelname w_g_key
+$cd /raid/quake/id1/models/w_g_key
+$flags 8		// client side rotate
+$base base
+$skin skin
+$frame frame1
+
+$modelname w_s_key
+$cd /raid/quake/id1/models/w_s_key
+$flags 8		// client side rotate
+$base base
+$skin skin
+$frame frame1
+
+$modelname m_g_key
+$cd /raid/quake/id1/models/m_g_key
+$flags 8		// client side rotate
+$base base
+$skin skin
+$frame frame1
+
+$modelname m_s_key
+$cd /raid/quake/id1/models/m_s_key
+$flags 8		// client side rotate
+$base base
+$skin skin
+$frame frame1
+
+$modelname b_g_key
+$cd /raid/quake/id1/models/b_g_key
+$flags 8		// client side rotate
+$base base
+$skin skin
+$frame frame1
+
+$modelname b_s_key
+$cd /raid/quake/id1/models/b_s_key
+$flags 8		// client side rotate
+$base base
+$skin skin
+$frame frame1
+
+
+$modelname quaddama
+$cd /raid/quake/id1/models/quaddama
+$flags 8		// client side rotate
+$base base
+$skin skin
+$frame frame1
+
+$modelname invisibl
+$cd /raid/quake/id1/models/invisibl
+$flags 8		// client side rotate
+$base base
+$skin skin
+$frame frame1
+
+$modelname invulner
+$flags 8		// client side rotate
+$cd /raid/quake/id1/models/invulner
+$base base
+$skin skin
+$frame frame1
+
+//modelname jetpack
+//cd /raid/quake/id1/models/jetpack
+//flags 8		// client side rotate
+//base base
+//skin skin
+//frame frame1
+
+$modelname cube
+$cd /raid/quake/id1/models/cube
+$flags 8		// client side rotate
+$base base
+$skin skin
+$frame frame1
+
+$modelname suit
+$cd /raid/quake/id1/models/suit
+$flags 8		// client side rotate
+$base base
+$skin skin
+$frame frame1
+
+$modelname boots
+$cd /raid/quake/id1/models/boots
+$flags 8		// client side rotate
+$base base
+$skin skin
+$frame frame1
+
+$modelname end1
+$cd /raid/quake/id1/models/end1
+$flags 8		// client side rotate
+$base base
+$skin skin
+$frame frame1
+
+$modelname end2
+$cd /raid/quake/id1/models/end2
+$flags 8		// client side rotate
+$base base
+$skin skin
+$frame frame1
+
+$modelname end3
+$cd /raid/quake/id1/models/end3
+$flags 8		// client side rotate
+$base base
+$skin skin
+$frame frame1
+
+$modelname end4
+$cd /raid/quake/id1/models/end4
+$flags 8		// client side rotate
+$base base
+$skin skin
+$frame frame1
+
+
+/*
+===============================================================================
+
+GIBS
+
+===============================================================================
+*/
+
+$modelname gib1
+$cd /raid/quake/id1/models/gib1
+$flags 4		// EF_GIB
+$origin 0 0 0
+$base base
+$skin skin
+$frame frame1
+
+
+// torso
+$modelname gib2
+$cd /raid/quake/id1/models/gib2
+$flags 4		// EF_GIB
+$origin 0 0 0
+$base base
+$skin skin
+$frame frame1
+
+$modelname gib3
+$cd /raid/quake/id1/models/gib3
+$flags 4		// EF_GIB
+$origin 0 0 0
+$base base
+$skin skin
+$frame frame1
+
+
+// heads
+
+$modelname h_player
+$cd /raid/quake/id1/models/h_player
+$flags 4		// EF_GIB
+$origin 0 0 0
+$base base
+$skin skin
+$frame frame1
+
+$modelname h_dog
+$cd /raid/quake/id1/models/h_dog
+$flags 4		// EF_GIB
+$origin 0 0 0
+$base base
+$skin skin
+$frame frame1
+
+$modelname h_mega
+$cd /raid/quake/id1/models/h_mega
+$flags 4		// EF_GIB
+$origin 0 0 0
+$base base
+$skin skin
+$frame frame1
+
+$modelname h_guard
+$cd /raid/quake/id1/models/h_guard
+$flags 4		// EF_GIB
+$origin 0 0 0
+$base base
+$skin skin
+$frame frame1
+
+$modelname h_wizard
+$cd /raid/quake/id1/models/h_wizard
+$flags 4		// EF_GIB
+$origin 0 0 0
+$base base
+$skin skin
+$frame frame1
+
+$modelname h_knight
+$cd /raid/quake/id1/models/h_knight
+$flags 4		// EF_GIB
+$origin 0 0 0
+$base base
+$skin skin
+$frame frame1
+
+$modelname h_hellkn
+$cd /raid/quake/id1/models/h_hellkn
+$flags 4		// EF_GIB
+$origin 0 0 0
+$base base
+$skin skin
+$frame frame1
+
+$modelname h_zombie
+$cd /raid/quake/id1/models/h_zombie
+$flags 4		// EF_GIB
+$origin 0 0 0
+$base base
+$skin skin
+$frame frame1
+
+$modelname h_shams
+$cd /raid/quake/id1/models/h_shams
+$flags 4		// EF_GIB
+$origin 0 0 0
+$base base
+$skin skin
+$frame frame1
+
+$modelname h_shal
+$cd /raid/quake/id1/models/h_shal
+$flags 4		// EF_GIB
+$origin 0 0 0
+$base base
+$skin skin
+$frame frame1
+
+$modelname h_ogre
+$cd /raid/quake/id1/models/h_ogre
+$flags 4		// EF_GIB
+$origin 0 0 0
+$base base
+$skin skin
+$frame frame1
+
+$modelname h_demon
+$cd /raid/quake/id1/models/h_demon
+$flags 4		// EF_GIB
+$origin 0 0 0
+$base base
+$skin skin
+$frame frame1
+
+/*
+===============================================================================
+
+MISC
+
+===============================================================================
+*/
+
+$modelname armor
+$cd /raid/quake/id1/models/armor
+$flags 8		// client side rotate
+$origin 0 0 -8
+$base base
+$skin skin
+$skin skin2
+$skin skin3
+$frame armor
+
+$modelname s_light			// shambler lightning ready
+$cd /raid/quake/id1/models/s_light
+$origin 0 0 24
+$base base
+$skin skin
+$frame	frame1 frame2 frame3
+
+$modelname bolt3			// lightning towar bolts
+$cd /raid/quake/id1/models/bolt2
+$origin 0 0 0
+$base base
+$scale 4
+$skin skin
+$frame	light
+
+$modelname bolt2
+$cd /raid/quake/id1/models/bolt2
+$origin 0 0 0
+$base base
+$skin skin
+$frame	light
+
+$modelname bolt
+$cd /raid/quake/id1/models/bolt
+$origin 0 0 0
+$base light
+$skin light
+$frame	light
+
+$modelname laser
+$cd /raid/quake/id1/models/laser
+$base base
+$skin skin
+$scale 2
+$frame frame1
+
+$modelname flame		// with torch
+$cd /raid/quake/id1/models/flame
+$origin 0 0 12
+$base base
+$skin skin
+$framegroupstart
+$frame flame1	0.1
+$frame flame2	0.1
+$frame flame3	0.1
+$frame flame4	0.1
+$frame flame5	0.1
+$frame flame6	0.1
+$framegroupend
+
+$modelname flame2		// standing flame, no torch
+$cd /raid/quake/id1/models/flame2
+$origin 0 0 12
+$base base
+$skin skin
+$framegroupstart
+$frame flame1	0.1
+$frame flame2	0.1
+$frame flame3	0.1
+$frame flame4	0.1
+$frame flame5	0.1
+$frame flame6	0.1
+$framegroupend
+$framegroupstart
+$frame flameb1
+$frame flameb2
+$frame flameb3
+$frame flameb4
+$frame flameb5
+$frame flameb6
+$frame flameb7
+$frame flameb8
+$frame flameb9
+$frame flameb10
+$frame flameb11
+$framegroupend
+
+$modelname zom_gib
+$cd /raid/quake/id1/models/zom_gib
+$flags 32		// EF_ZOMGIB
+$base base
+$skin skin
+$frame frame1
+
+$modelname eyes
+$cd /raid/quake/id1/models/eyes
+$origin 0 0 -24
+$base base
+$skin skin
+$frame frame1
+
+$modelname spike
+$cd /raid/quake/id1/models/spike
+$origin 0 0 0
+$base spike
+$skin skin
+$frame spike
+
+$modelname s_spike
+$cd /raid/quake/id1/models/s_spike
+$origin 0 0 0
+$base spike
+$skin skin
+$frame spike
+
+$modelname v_spike
+$cd /raid/quake/id1/models/v_spike
+$flags 128		// EF_TRACER3
+$origin 0 0 0
+$base base
+$skin skin
+$frame frame1
+
+$modelname w_spike
+$cd /raid/quake/id1/models/w_spike
+$flags 16		// EF_TRACER
+$origin 0 0 0
+$base base
+$skin skin
+$framegroupstart
+$frame frame1	0.1
+$frame frame2	0.1
+$frame frame3	0.1
+$frame frame4	0.1
+$framegroupend
+
+$modelname k_spike
+$cd /raid/quake/id1/models/k_spike
+$flags 64		// EF_TRACER2
+$origin 0 0 0
+$base base
+$skin skin
+$frame frame1
+
+$modelname backpack
+$cd /raid/quake/id1/models/backpack
+$flags 8		// EF_ROTATE
+$origin 0 0 0
+$base base
+$skin skin
+$frame frame1
+
+$modelname grenade
+$cd /raid/quake/id1/models/grenade2
+$flags 2		// EF_GRENADE
+$origin 0 0 0
+$base base
+$skin skin
+$frame grenade
+
+$modelname missile
+$cd /raid/quake/id1/models/missile
+$flags	1			// EF_ROCKET
+$origin 0 0 0
+$base base
+$skin skin
+$frame missile
+
+$modelname lavaball
+$cd /raid/quake/id1/models/lavaball
+$flags	1			// EF_ROCKET
+$origin 0 0 0
+$base base
+$skin skin
+$frame frame1
+
+$modelname teleport
+$cd /raid/quake/id1/models/teleport
+$origin 0 0 24
+$base base
+$skin skin
+$frame frame1
+
--- /dev/null
+++ b/QW/progs/plats.qc
@@ -1,0 +1,367 @@
+
+
+void() plat_center_touch;
+void() plat_outside_touch;
+void() plat_trigger_use;
+void() plat_go_up;
+void() plat_go_down;
+void() plat_crush;
+float PLAT_LOW_TRIGGER = 1;
+
+void() plat_spawn_inside_trigger =
+{
+	local entity	trigger;
+	local vector	tmin, tmax;
+
+//
+// middle trigger
+//	
+	trigger = spawn();
+	trigger.touch = plat_center_touch;
+	trigger.movetype = MOVETYPE_NONE;
+	trigger.solid = SOLID_TRIGGER;
+	trigger.enemy = self;
+	
+	tmin = self.mins + '25 25 0';
+	tmax = self.maxs - '25 25 -8';
+	tmin_z = tmax_z - (self.pos1_z - self.pos2_z + 8);
+	if (self.spawnflags & PLAT_LOW_TRIGGER)
+		tmax_z = tmin_z + 8;
+	
+	if (self.size_x <= 50)
+	{
+		tmin_x = (self.mins_x + self.maxs_x) / 2;
+		tmax_x = tmin_x + 1;
+	}
+	if (self.size_y <= 50)
+	{
+		tmin_y = (self.mins_y + self.maxs_y) / 2;
+		tmax_y = tmin_y + 1;
+	}
+	
+	setsize (trigger, tmin, tmax);
+};
+
+void() plat_hit_top =
+{
+	sound (self, CHAN_NO_PHS_ADD+CHAN_VOICE, self.noise1, 1, ATTN_NORM);
+	self.state = STATE_TOP;
+	self.think = plat_go_down;
+	self.nextthink = self.ltime + 3;
+};
+
+void() plat_hit_bottom =
+{
+	sound (self, CHAN_NO_PHS_ADD+CHAN_VOICE, self.noise1, 1, ATTN_NORM);
+	self.state = STATE_BOTTOM;
+};
+
+void() plat_go_down =
+{
+	sound (self, CHAN_VOICE, self.noise, 1, ATTN_NORM);
+	self.state = STATE_DOWN;
+	SUB_CalcMove (self.pos2, self.speed, plat_hit_bottom);
+};
+
+void() plat_go_up =
+{
+	sound (self, CHAN_VOICE, self.noise, 1, ATTN_NORM);
+	self.state = STATE_UP;
+	SUB_CalcMove (self.pos1, self.speed, plat_hit_top);
+};
+
+void() plat_center_touch =
+{
+	if (other.classname != "player")
+		return;
+		
+	if (other.health <= 0)
+		return;
+
+	self = self.enemy;
+	if (self.state == STATE_BOTTOM)
+		plat_go_up ();
+	else if (self.state == STATE_TOP)
+		self.nextthink = self.ltime + 1;	// delay going down
+};
+
+void() plat_outside_touch =
+{
+	if (other.classname != "player")
+		return;
+
+	if (other.health <= 0)
+		return;
+		
+//dprint ("plat_outside_touch\n");
+	self = self.enemy;
+	if (self.state == STATE_TOP)
+		plat_go_down ();
+};
+
+void() plat_trigger_use =
+{
+	if (self.think)
+		return;		// allready activated
+	plat_go_down();
+};
+
+
+void() plat_crush =
+{
+//dprint ("plat_crush\n");
+
+	other.deathtype = "squish";
+	T_Damage (other, self, self, 1);
+	
+	if (self.state == STATE_UP)
+		plat_go_down ();
+	else if (self.state == STATE_DOWN)
+		plat_go_up ();
+	else
+		objerror ("plat_crush: bad self.state\n");
+};
+
+void() plat_use =
+{
+	self.use = SUB_Null;
+	if (self.state != STATE_UP)
+		objerror ("plat_use: not in up state");
+	plat_go_down();
+};
+
+
+/*QUAKED func_plat (0 .5 .8) ? PLAT_LOW_TRIGGER
+speed	default 150
+
+Plats are always drawn in the extended position, so they will light correctly.
+
+If the plat is the target of another trigger or button, it will start out disabled in the extended position until it is trigger, when it will lower and become a normal plat.
+
+If the "height" key is set, that will determine the amount the plat moves, instead of being implicitly determined by the model's height.
+Set "sounds" to one of the following:
+1) base fast
+2) chain slow
+*/
+
+
+void() func_plat =
+
+{
+local entity t;
+
+	if (!self.t_length)
+		self.t_length = 80;
+	if (!self.t_width)
+		self.t_width = 10;
+
+	if (self.sounds == 0)
+		self.sounds = 2;
+// FIX THIS TO LOAD A GENERIC PLAT SOUND
+
+	if (self.sounds == 1)
+	{
+		precache_sound ("plats/plat1.wav");
+		precache_sound ("plats/plat2.wav");
+		self.noise = "plats/plat1.wav";
+		self.noise1 = "plats/plat2.wav";
+	}
+
+	if (self.sounds == 2)
+	{
+		precache_sound ("plats/medplat1.wav");
+		precache_sound ("plats/medplat2.wav");
+		self.noise = "plats/medplat1.wav";
+		self.noise1 = "plats/medplat2.wav";
+	}
+
+
+	self.mangle = self.angles;
+	self.angles = '0 0 0';
+
+	self.classname = "plat";
+	self.solid = SOLID_BSP;
+	self.movetype = MOVETYPE_PUSH;
+	setorigin (self, self.origin);	
+	setmodel (self, self.model);
+	setsize (self, self.mins , self.maxs);
+
+	self.blocked = plat_crush;
+	if (!self.speed)
+		self.speed = 150;
+
+// pos1 is the top position, pos2 is the bottom
+	self.pos1 = self.origin;
+	self.pos2 = self.origin;
+	if (self.height)
+		self.pos2_z = self.origin_z - self.height;
+	else
+		self.pos2_z = self.origin_z - self.size_z + 8;
+
+	self.use = plat_trigger_use;
+
+	plat_spawn_inside_trigger ();	// the "start moving" trigger	
+
+	if (self.targetname)
+	{
+		self.state = STATE_UP;
+		self.use = plat_use;
+	}
+	else
+	{
+		setorigin (self, self.pos2);
+		self.state = STATE_BOTTOM;
+	}
+};
+
+//============================================================================
+
+void() train_next;
+void() func_train_find;
+
+void() train_blocked =
+{
+	if (time < self.attack_finished)
+		return;
+	self.attack_finished = time + 0.5;
+	other.deathtype = "squish";
+	T_Damage (other, self, self, self.dmg);
+};
+
+void() train_use =
+{
+	if (self.think != func_train_find)
+		return;		// already activated
+	train_next();
+};
+
+void() train_wait =
+{
+	if (self.wait)
+	{
+		self.nextthink = self.ltime + self.wait;
+		sound (self, CHAN_NO_PHS_ADD+CHAN_VOICE, self.noise, 1, ATTN_NORM);
+	}
+	else
+		self.nextthink = self.ltime + 0.1;
+	
+	self.think = train_next;
+};
+
+void() train_next =
+{
+	local entity	targ;
+
+	targ = find (world, targetname, self.target);
+	self.target = targ.target;
+	if (!self.target)
+		objerror ("train_next: no next target");
+	if (targ.wait)
+		self.wait = targ.wait;
+	else
+		self.wait = 0;
+	sound (self, CHAN_VOICE, self.noise1, 1, ATTN_NORM);
+	SUB_CalcMove (targ.origin - self.mins, self.speed, train_wait);
+};
+
+void() func_train_find =
+
+{
+	local entity	targ;
+
+	targ = find (world, targetname, self.target);
+	self.target = targ.target;
+	setorigin (self, targ.origin - self.mins);
+	if (!self.targetname)
+	{	// not triggered, so start immediately
+		self.nextthink = self.ltime + 0.1;
+		self.think = train_next;
+	}
+};
+
+/*QUAKED func_train (0 .5 .8) ?
+Trains are moving platforms that players can ride.
+The targets origin specifies the min point of the train at each corner.
+The train spawns at the first target it is pointing at.
+If the train is the target of a button or trigger, it will not begin moving until activated.
+speed	default 100
+dmg		default	2
+sounds
+1) ratchet metal
+
+*/
+void() func_train =
+{	
+	if (!self.speed)
+		self.speed = 100;
+	if (!self.target)
+		objerror ("func_train without a target");
+	if (!self.dmg)
+		self.dmg = 2;
+
+	if (self.sounds == 0)
+	{
+		self.noise = ("misc/null.wav");
+		precache_sound ("misc/null.wav");
+		self.noise1 = ("misc/null.wav");
+		precache_sound ("misc/null.wav");
+	}
+
+	if (self.sounds == 1)
+	{
+		self.noise = ("plats/train2.wav");
+		precache_sound ("plats/train2.wav");
+		self.noise1 = ("plats/train1.wav");
+		precache_sound ("plats/train1.wav");
+	}
+
+	self.cnt = 1;
+	self.solid = SOLID_BSP;
+	self.movetype = MOVETYPE_PUSH;
+	self.blocked = train_blocked;
+	self.use = train_use;
+	self.classname = "train";
+
+	setmodel (self, self.model);
+	setsize (self, self.mins , self.maxs);
+	setorigin (self, self.origin);
+
+// start trains on the second frame, to make sure their targets have had
+// a chance to spawn
+	self.nextthink = self.ltime + 0.1;
+	self.think = func_train_find;
+};
+
+/*QUAKED misc_teleporttrain (0 .5 .8) (-8 -8 -8) (8 8 8)
+This is used for the final bos
+*/
+void() misc_teleporttrain =
+{	
+	if (!self.speed)
+		self.speed = 100;
+	if (!self.target)
+		objerror ("func_train without a target");
+
+	self.cnt = 1;
+	self.solid = SOLID_NOT;
+	self.movetype = MOVETYPE_PUSH;
+	self.blocked = train_blocked;
+	self.use = train_use;
+	self.avelocity = '100 200 300';
+
+	self.noise = ("misc/null.wav");
+	precache_sound ("misc/null.wav");
+	self.noise1 = ("misc/null.wav");
+	precache_sound ("misc/null.wav");
+
+	precache_model2 ("progs/teleport.mdl");
+	setmodel (self, "progs/teleport.mdl");
+	setsize (self, self.mins , self.maxs);
+	setorigin (self, self.origin);
+
+// start trains on the second frame, to make sure their targets have had
+// a chance to spawn
+	self.nextthink = self.ltime + 0.1;
+	self.think = func_train_find;
+};
+
--- /dev/null
+++ b/QW/progs/player.qc
@@ -1,0 +1,710 @@
+
+void() bubble_bob;
+
+/*
+==============================================================================
+
+PLAYER
+
+==============================================================================
+*/
+
+$cd /raid/quake/id1/models/player_4
+$origin 0 -6 24
+$base base              
+$skin skin
+
+//
+// running
+//
+$frame axrun1 axrun2 axrun3 axrun4 axrun5 axrun6
+
+$frame rockrun1 rockrun2 rockrun3 rockrun4 rockrun5 rockrun6
+
+//
+// standing
+//
+$frame stand1 stand2 stand3 stand4 stand5
+
+$frame axstnd1 axstnd2 axstnd3 axstnd4 axstnd5 axstnd6
+$frame axstnd7 axstnd8 axstnd9 axstnd10 axstnd11 axstnd12
+
+
+//
+// pain
+//
+$frame axpain1 axpain2 axpain3 axpain4 axpain5 axpain6
+
+$frame pain1 pain2 pain3 pain4 pain5 pain6
+
+
+//
+// death
+//
+
+$frame axdeth1 axdeth2 axdeth3 axdeth4 axdeth5 axdeth6
+$frame axdeth7 axdeth8 axdeth9
+
+$frame deatha1 deatha2 deatha3 deatha4 deatha5 deatha6 deatha7 deatha8
+$frame deatha9 deatha10 deatha11
+
+$frame deathb1 deathb2 deathb3 deathb4 deathb5 deathb6 deathb7 deathb8
+$frame deathb9
+
+$frame deathc1 deathc2 deathc3 deathc4 deathc5 deathc6 deathc7 deathc8
+$frame deathc9 deathc10 deathc11 deathc12 deathc13 deathc14 deathc15
+
+$frame deathd1 deathd2 deathd3 deathd4 deathd5 deathd6 deathd7
+$frame deathd8 deathd9
+
+$frame deathe1 deathe2 deathe3 deathe4 deathe5 deathe6 deathe7
+$frame deathe8 deathe9
+
+//
+// attacks
+//
+$frame nailatt1 nailatt2
+
+$frame light1 light2
+
+$frame rockatt1 rockatt2 rockatt3 rockatt4 rockatt5 rockatt6
+
+$frame shotatt1 shotatt2 shotatt3 shotatt4 shotatt5 shotatt6
+
+$frame axatt1 axatt2 axatt3 axatt4 axatt5 axatt6
+
+$frame axattb1 axattb2 axattb3 axattb4 axattb5 axattb6
+
+$frame axattc1 axattc2 axattc3 axattc4 axattc5 axattc6
+
+$frame axattd1 axattd2 axattd3 axattd4 axattd5 axattd6
+
+
+/*
+==============================================================================
+PLAYER
+==============================================================================
+*/
+
+void() player_run;
+
+void()  player_stand1 =[        $axstnd1,       player_stand1   ]
+{
+	self.weaponframe=0;
+	if (self.velocity_x || self.velocity_y)
+	{
+		self.walkframe=0;
+		player_run();
+		return;
+	}
+
+	if (self.weapon == IT_AXE)
+	{
+		if (self.walkframe >= 12)
+			self.walkframe = 0;
+		self.frame = $axstnd1 + self.walkframe;
+	}
+	else
+	{
+		if (self.walkframe >= 5)
+			self.walkframe = 0;
+		self.frame = $stand1 + self.walkframe;
+	}
+	self.walkframe = self.walkframe + 1;    
+};
+
+void()  player_run =[   $rockrun1,      player_run      ]
+{
+	self.weaponframe=0;
+	if (!self.velocity_x && !self.velocity_y)
+	{
+		self.walkframe=0;
+		player_stand1();
+		return;
+	}
+
+	if (self.weapon == IT_AXE)
+	{
+		if (self.walkframe == 6)
+			self.walkframe = 0;
+		self.frame = $axrun1 + self.walkframe;
+	}
+	else
+	{
+		if (self.walkframe == 6)
+			self.walkframe = 0;
+		self.frame = self.frame + self.walkframe;
+	}
+	self.walkframe = self.walkframe + 1;
+};
+
+void()muzzleflash =
+{
+	WriteByte (MSG_MULTICAST, SVC_MUZZLEFLASH);
+	WriteEntity (MSG_MULTICAST, self);
+	multicast (self.origin, MULTICAST_PVS);
+};
+
+
+void()  player_shot1 =  [$shotatt1, player_shot2        ] {self.weaponframe=1;muzzleflash();};
+void()  player_shot2 =  [$shotatt2, player_shot3        ] {self.weaponframe=2;};
+void()  player_shot3 =  [$shotatt3, player_shot4        ] {self.weaponframe=3;};
+void()  player_shot4 =  [$shotatt4, player_shot5        ] {self.weaponframe=4;};
+void()  player_shot5 =  [$shotatt5, player_shot6        ] {self.weaponframe=5;};
+void()  player_shot6 =  [$shotatt6, player_run  ] {self.weaponframe=6;};
+
+void()  player_axe1 =   [$axatt1, player_axe2   ] {self.weaponframe=1;};
+void()  player_axe2 =   [$axatt2, player_axe3   ] {self.weaponframe=2;};
+void()  player_axe3 =   [$axatt3, player_axe4   ] {self.weaponframe=3;W_FireAxe();};
+void()  player_axe4 =   [$axatt4, player_run    ] {self.weaponframe=4;};
+
+void()  player_axeb1 =  [$axattb1, player_axeb2 ] {self.weaponframe=5;};
+void()  player_axeb2 =  [$axattb2, player_axeb3 ] {self.weaponframe=6;};
+void()  player_axeb3 =  [$axattb3, player_axeb4 ] {self.weaponframe=7;W_FireAxe();};
+void()  player_axeb4 =  [$axattb4, player_run   ] {self.weaponframe=8;};
+
+void()  player_axec1 =  [$axattc1, player_axec2 ] {self.weaponframe=1;};
+void()  player_axec2 =  [$axattc2, player_axec3 ] {self.weaponframe=2;};
+void()  player_axec3 =  [$axattc3, player_axec4 ] {self.weaponframe=3;W_FireAxe();};
+void()  player_axec4 =  [$axattc4, player_run   ] {self.weaponframe=4;};
+
+void()  player_axed1 =  [$axattd1, player_axed2 ] {self.weaponframe=5;};
+void()  player_axed2 =  [$axattd2, player_axed3 ] {self.weaponframe=6;};
+void()  player_axed3 =  [$axattd3, player_axed4 ] {self.weaponframe=7;W_FireAxe();};
+void()  player_axed4 =  [$axattd4, player_run   ] {self.weaponframe=8;};
+
+
+//============================================================================
+
+void() player_nail1   =[$nailatt1, player_nail2  ] 
+{
+	muzzleflash();
+
+	if (!self.button0 || intermission_running || self.impulse)
+		{player_run ();return;}
+	self.weaponframe = self.weaponframe + 1;
+	if (self.weaponframe == 9)
+		self.weaponframe = 1;
+	SuperDamageSound();
+	W_FireSpikes (4);
+	self.attack_finished = time + 0.2;
+};
+void() player_nail2   =[$nailatt2, player_nail1  ]
+{
+	muzzleflash();
+
+	if (!self.button0 || intermission_running || self.impulse)
+		{player_run ();return;}
+	self.weaponframe = self.weaponframe + 1;
+	if (self.weaponframe == 9)
+		self.weaponframe = 1;
+	SuperDamageSound();
+	W_FireSpikes (-4);
+	self.attack_finished = time + 0.2;
+};
+
+//============================================================================
+
+void() player_light1   =[$light1, player_light2  ] 
+{
+	muzzleflash();
+
+	if (!self.button0 || intermission_running)
+		{player_run ();return;}
+	self.weaponframe = self.weaponframe + 1;
+	if (self.weaponframe == 5)
+		self.weaponframe = 1;
+	SuperDamageSound();
+	W_FireLightning();
+	self.attack_finished = time + 0.2;
+};
+void() player_light2   =[$light2, player_light1  ]
+{
+	muzzleflash();
+
+	if (!self.button0 || intermission_running)
+		{player_run ();return;}
+	self.weaponframe = self.weaponframe + 1;
+	if (self.weaponframe == 5)
+		self.weaponframe = 1;
+	SuperDamageSound();
+	W_FireLightning();
+	self.attack_finished = time + 0.2;
+};
+
+//============================================================================
+
+
+void() player_rocket1   =[$rockatt1, player_rocket2  ] {self.weaponframe=1;
+	muzzleflash();};
+void() player_rocket2   =[$rockatt2, player_rocket3  ] {self.weaponframe=2;};
+void() player_rocket3   =[$rockatt3, player_rocket4  ] {self.weaponframe=3;};
+void() player_rocket4   =[$rockatt4, player_rocket5  ] {self.weaponframe=4;};
+void() player_rocket5   =[$rockatt5, player_rocket6  ] {self.weaponframe=5;};
+void() player_rocket6   =[$rockatt6, player_run  ] {self.weaponframe=6;};
+void(float num_bubbles) DeathBubbles;
+
+void() PainSound =
+{
+local float             rs;
+
+	if (self.health < 0)
+		return;
+
+	if (damage_attacker.classname == "teledeath")
+	{
+		sound (self, CHAN_VOICE, "player/teledth1.wav", 1, ATTN_NONE);
+		return;
+	}
+
+// water pain sounds
+	if (self.watertype == CONTENT_WATER && self.waterlevel == 3)
+	{
+		DeathBubbles(1);
+		if (random() > 0.5)
+			sound (self, CHAN_VOICE, "player/drown1.wav", 1, ATTN_NORM);
+		else
+			sound (self, CHAN_VOICE, "player/drown2.wav", 1, ATTN_NORM);
+		return;
+	}
+
+// slime pain sounds
+	if (self.watertype == CONTENT_SLIME)
+	{
+// FIX ME       put in some steam here
+		if (random() > 0.5)
+			sound (self, CHAN_VOICE, "player/lburn1.wav", 1, ATTN_NORM);
+		else
+			sound (self, CHAN_VOICE, "player/lburn2.wav", 1, ATTN_NORM);
+		return;
+	}
+
+	if (self.watertype == CONTENT_LAVA)
+	{
+		if (random() > 0.5)
+			sound (self, CHAN_VOICE, "player/lburn1.wav", 1, ATTN_NORM);
+		else
+			sound (self, CHAN_VOICE, "player/lburn2.wav", 1, ATTN_NORM);
+		return;
+	}
+
+	if (self.pain_finished > time)
+	{
+		self.axhitme = 0;
+		return;
+	}
+	self.pain_finished = time + 0.5;
+
+// don't make multiple pain sounds right after each other
+
+// ax pain sound
+	if (self.axhitme == 1)
+	{
+		self.axhitme = 0;
+		sound (self, CHAN_VOICE, "player/axhit1.wav", 1, ATTN_NORM);
+		return;
+	}
+	
+
+	rs = rint((random() * 5) + 1);
+
+	self.noise = "";
+	if (rs == 1)
+		self.noise = "player/pain1.wav";
+	else if (rs == 2)
+		self.noise = "player/pain2.wav";
+	else if (rs == 3)
+		self.noise = "player/pain3.wav";
+	else if (rs == 4)
+		self.noise = "player/pain4.wav";
+	else if (rs == 5)
+		self.noise = "player/pain5.wav";
+	else
+		self.noise = "player/pain6.wav";
+
+	sound (self, CHAN_VOICE, self.noise, 1, ATTN_NORM);
+	return;
+};
+
+void()  player_pain1 =  [       $pain1, player_pain2    ] {PainSound();self.weaponframe=0;};
+void()  player_pain2 =  [       $pain2, player_pain3    ] {};
+void()  player_pain3 =  [       $pain3, player_pain4    ] {};
+void()  player_pain4 =  [       $pain4, player_pain5    ] {};
+void()  player_pain5 =  [       $pain5, player_pain6    ] {};
+void()  player_pain6 =  [       $pain6, player_run      ] {};
+
+void()  player_axpain1 =        [       $axpain1,       player_axpain2  ] {PainSound();self.weaponframe=0;};
+void()  player_axpain2 =        [       $axpain2,       player_axpain3  ] {};
+void()  player_axpain3 =        [       $axpain3,       player_axpain4  ] {};
+void()  player_axpain4 =        [       $axpain4,       player_axpain5  ] {};
+void()  player_axpain5 =        [       $axpain5,       player_axpain6  ] {};
+void()  player_axpain6 =        [       $axpain6,       player_run      ] {};
+
+void() player_pain =
+{
+	if (self.weaponframe)
+		return;
+
+	if (self.invisible_finished > time)
+		return;         // eyes don't have pain frames
+
+	if (self.weapon == IT_AXE)
+		player_axpain1 ();
+	else
+		player_pain1 ();
+};
+
+void() player_diea1;
+void() player_dieb1;
+void() player_diec1;
+void() player_died1;
+void() player_diee1;
+void() player_die_ax1;
+
+void() DeathBubblesSpawn =
+{
+local entity    bubble;
+	if (self.owner.waterlevel != 3)
+		return;
+	bubble = spawn();
+	setmodel (bubble, "progs/s_bubble.spr");
+	setorigin (bubble, self.owner.origin + '0 0 24');
+	bubble.movetype = MOVETYPE_NOCLIP;
+	bubble.solid = SOLID_NOT;
+	bubble.velocity = '0 0 15';
+	bubble.nextthink = time + 0.5;
+	bubble.think = bubble_bob;
+	bubble.classname = "bubble";
+	bubble.frame = 0;
+	bubble.cnt = 0;
+	setsize (bubble, '-8 -8 -8', '8 8 8');
+	self.nextthink = time + 0.1;
+	self.think = DeathBubblesSpawn;
+	self.air_finished = self.air_finished + 1;
+	if (self.air_finished >= self.bubble_count)
+		remove(self);
+};
+
+void(float num_bubbles) DeathBubbles =
+{
+local entity    bubble_spawner;
+	
+	bubble_spawner = spawn();
+	setorigin (bubble_spawner, self.origin);
+	bubble_spawner.movetype = MOVETYPE_NONE;
+	bubble_spawner.solid = SOLID_NOT;
+	bubble_spawner.nextthink = time + 0.1;
+	bubble_spawner.think = DeathBubblesSpawn;
+	bubble_spawner.air_finished = 0;
+	bubble_spawner.owner = self;
+	bubble_spawner.bubble_count = num_bubbles;
+	return;
+};
+
+
+void() DeathSound =
+{
+local float             rs;
+
+	// water death sounds
+	if (self.waterlevel == 3)
+	{
+		DeathBubbles(5);
+		sound (self, CHAN_VOICE, "player/h2odeath.wav", 1, ATTN_NONE);
+		return;
+	}
+	
+	rs = rint ((random() * 4) + 1);
+	if (rs == 1)
+		self.noise = "player/death1.wav";
+	if (rs == 2)
+		self.noise = "player/death2.wav";
+	if (rs == 3)
+		self.noise = "player/death3.wav";
+	if (rs == 4)
+		self.noise = "player/death4.wav";
+	if (rs == 5)
+		self.noise = "player/death5.wav";
+
+	sound (self, CHAN_VOICE, self.noise, 1, ATTN_NONE);
+	return;
+};
+
+
+void() PlayerDead =
+{
+	self.nextthink = -1;
+// allow respawn after a certain time
+	self.deadflag = DEAD_DEAD;
+};
+
+vector(float dm) VelocityForDamage =
+{
+	local vector v;
+
+	if (vlen(damage_inflictor.velocity)>0)
+	{
+		v = 0.5 * damage_inflictor.velocity;
+		v = v + (25 * normalize(self.origin-damage_inflictor.origin));
+		v_z = 100 + 240 * random();
+		v_x = v_x + (200 * crandom());
+		v_y = v_y + (200 * crandom());
+		//dprint ("Velocity gib\n");                
+	}
+	else
+	{
+		v_x = 100 * crandom();
+		v_y = 100 * crandom();
+		v_z = 200 + 100 * random();
+	}
+
+	//v_x = 100 * crandom();
+	//v_y = 100 * crandom();
+	//v_z = 200 + 100 * random();
+
+	if (dm > -50)
+	{
+	//      dprint ("level 1\n");
+		v = v * 0.7;
+	}
+	else if (dm > -200)
+	{
+	//      dprint ("level 3\n");
+		v = v * 2;
+	}
+	else
+		v = v * 10;
+
+	return v;
+};
+
+void(string gibname, float dm) ThrowGib =
+{
+	local   entity new;
+
+	new = spawn();
+	new.origin = self.origin;
+	setmodel (new, gibname);
+	setsize (new, '0 0 0', '0 0 0');
+	new.velocity = VelocityForDamage (dm);
+	new.movetype = MOVETYPE_BOUNCE;
+	new.solid = SOLID_NOT;
+	new.avelocity_x = random()*600;
+	new.avelocity_y = random()*600;
+	new.avelocity_z = random()*600;
+	new.think = SUB_Remove;
+	new.ltime = time;
+	new.nextthink = time + 10 + random()*10;
+	new.frame = 0;
+	new.flags = 0;
+};
+
+void(string gibname, float dm) ThrowHead =
+{
+	setmodel (self, gibname);
+	self.frame = 0;
+	self.nextthink = -1;
+	self.movetype = MOVETYPE_BOUNCE;
+	self.takedamage = DAMAGE_NO;
+	self.solid = SOLID_NOT;
+	self.view_ofs = '0 0 8';
+	setsize (self, '-16 -16 0', '16 16 56');
+	self.velocity = VelocityForDamage (dm);
+	self.origin_z = self.origin_z - 24;
+	self.flags = self.flags - (self.flags & FL_ONGROUND);
+	self.avelocity = crandom() * '0 600 0';
+};
+
+
+void() GibPlayer =
+{
+	ThrowHead ("progs/h_player.mdl", self.health);
+	ThrowGib ("progs/gib1.mdl", self.health);
+	ThrowGib ("progs/gib2.mdl", self.health);
+	ThrowGib ("progs/gib3.mdl", self.health);
+
+	self.deadflag = DEAD_DEAD;
+
+	if (damage_attacker.classname == "teledeath")
+	{
+		sound (self, CHAN_VOICE, "player/teledth1.wav", 1, ATTN_NONE);
+		return;
+	}
+
+	if (damage_attacker.classname == "teledeath2")
+	{
+		sound (self, CHAN_VOICE, "player/teledth1.wav", 1, ATTN_NONE);
+		return;
+	}
+		
+	if (random() < 0.5)
+		sound (self, CHAN_VOICE, "player/gib.wav", 1, ATTN_NONE);
+	else
+		sound (self, CHAN_VOICE, "player/udeath.wav", 1, ATTN_NONE);
+};
+
+void() PlayerDie =
+{
+	local   float   i;
+	local	string	s;	
+	self.items = self.items - (self.items & IT_INVISIBILITY);
+
+	if ((stof(infokey(world,"dq"))) != 0)
+	{
+		if (self.super_damage_finished > 0)
+		{
+			DropQuad (self.super_damage_finished - time);
+			bprint (PRINT_LOW, self.netname);
+			if (deathmatch == 4)
+				bprint (PRINT_LOW, " lost an OctaPower with ");
+			else
+				bprint (PRINT_LOW, " lost a quad with ");
+			s = ftos(rint(self.super_damage_finished - time));
+			bprint (PRINT_LOW, s);
+			bprint (PRINT_LOW, " seconds remaining\n");
+		}
+	}
+
+	if ((stof(infokey(world,"dr"))) != 0)
+	{
+		if (self.invisible_finished > 0)
+		{
+			bprint (PRINT_LOW, self.netname);
+			bprint (PRINT_LOW, " lost a ring with ");
+			s = ftos(rint(self.invisible_finished - time));
+			bprint (PRINT_LOW, s);
+			bprint (PRINT_LOW, " seconds remaining\n");
+			DropRing (self.invisible_finished - time);
+		}
+	}
+
+	self.invisible_finished = 0;    // don't die as eyes
+	self.invincible_finished = 0;
+	self.super_damage_finished = 0;
+	self.radsuit_finished = 0;
+	self.modelindex = modelindex_player;    // don't use eyes
+
+	DropBackpack();
+	
+	self.weaponmodel="";
+	self.view_ofs = '0 0 -8';
+	self.deadflag = DEAD_DYING;
+	self.solid = SOLID_NOT;
+	self.flags = self.flags - (self.flags & FL_ONGROUND);
+	self.movetype = MOVETYPE_TOSS;
+	if (self.velocity_z < 10)
+		self.velocity_z = self.velocity_z + random()*300;
+
+	if (self.health < -40)
+	{
+		GibPlayer ();
+		return;
+	}
+
+	DeathSound();
+	
+	self.angles_x = 0;
+	self.angles_z = 0;
+	
+	if (self.weapon == IT_AXE)
+	{
+		player_die_ax1 ();
+		return;
+	}
+	
+	i = cvar("temp1");
+	if (!i)
+		i = 1 + floor(random()*6);
+	
+	if (i == 1)
+		player_diea1();
+	else if (i == 2)
+		player_dieb1();
+	else if (i == 3)
+		player_diec1();
+	else if (i == 4)
+		player_died1();
+	else
+		player_diee1();
+
+};
+
+void() set_suicide_frame =
+{       // used by klill command and diconnect command
+	if (self.model != "progs/player.mdl")
+		return; // allready gibbed
+	self.frame = $deatha11;
+	self.solid = SOLID_NOT;
+	self.movetype = MOVETYPE_TOSS;
+	self.deadflag = DEAD_DEAD;
+	self.nextthink = -1;
+};
+
+
+void()  player_diea1    =       [       $deatha1,       player_diea2    ] {};
+void()  player_diea2    =       [       $deatha2,       player_diea3    ] {};
+void()  player_diea3    =       [       $deatha3,       player_diea4    ] {};
+void()  player_diea4    =       [       $deatha4,       player_diea5    ] {};
+void()  player_diea5    =       [       $deatha5,       player_diea6    ] {};
+void()  player_diea6    =       [       $deatha6,       player_diea7    ] {};
+void()  player_diea7    =       [       $deatha7,       player_diea8    ] {};
+void()  player_diea8    =       [       $deatha8,       player_diea9    ] {};
+void()  player_diea9    =       [       $deatha9,       player_diea10   ] {};
+void()  player_diea10   =       [       $deatha10,      player_diea11   ] {};
+void()  player_diea11   =       [       $deatha11,      player_diea11 ] {PlayerDead();};
+
+void()  player_dieb1    =       [       $deathb1,       player_dieb2    ] {};
+void()  player_dieb2    =       [       $deathb2,       player_dieb3    ] {};
+void()  player_dieb3    =       [       $deathb3,       player_dieb4    ] {};
+void()  player_dieb4    =       [       $deathb4,       player_dieb5    ] {};
+void()  player_dieb5    =       [       $deathb5,       player_dieb6    ] {};
+void()  player_dieb6    =       [       $deathb6,       player_dieb7    ] {};
+void()  player_dieb7    =       [       $deathb7,       player_dieb8    ] {};
+void()  player_dieb8    =       [       $deathb8,       player_dieb9    ] {};
+void()  player_dieb9    =       [       $deathb9,       player_dieb9    ] {PlayerDead();};
+
+void()  player_diec1    =       [       $deathc1,       player_diec2    ] {};
+void()  player_diec2    =       [       $deathc2,       player_diec3    ] {};
+void()  player_diec3    =       [       $deathc3,       player_diec4    ] {};
+void()  player_diec4    =       [       $deathc4,       player_diec5    ] {};
+void()  player_diec5    =       [       $deathc5,       player_diec6    ] {};
+void()  player_diec6    =       [       $deathc6,       player_diec7    ] {};
+void()  player_diec7    =       [       $deathc7,       player_diec8    ] {};
+void()  player_diec8    =       [       $deathc8,       player_diec9    ] {};
+void()  player_diec9    =       [       $deathc9,       player_diec10   ] {};
+void()  player_diec10   =       [       $deathc10,      player_diec11   ] {};
+void()  player_diec11   =       [       $deathc11,      player_diec12   ] {};
+void()  player_diec12   =       [       $deathc12,      player_diec13   ] {};
+void()  player_diec13   =       [       $deathc13,      player_diec14   ] {};
+void()  player_diec14   =       [       $deathc14,      player_diec15   ] {};
+void()  player_diec15   =       [       $deathc15,      player_diec15 ] {PlayerDead();};
+
+void()  player_died1    =       [       $deathd1,       player_died2    ] {};
+void()  player_died2    =       [       $deathd2,       player_died3    ] {};
+void()  player_died3    =       [       $deathd3,       player_died4    ] {};
+void()  player_died4    =       [       $deathd4,       player_died5    ] {};
+void()  player_died5    =       [       $deathd5,       player_died6    ] {};
+void()  player_died6    =       [       $deathd6,       player_died7    ] {};
+void()  player_died7    =       [       $deathd7,       player_died8    ] {};
+void()  player_died8    =       [       $deathd8,       player_died9    ] {};
+void()  player_died9    =       [       $deathd9,       player_died9    ] {PlayerDead();};
+
+void()  player_diee1    =       [       $deathe1,       player_diee2    ] {};
+void()  player_diee2    =       [       $deathe2,       player_diee3    ] {};
+void()  player_diee3    =       [       $deathe3,       player_diee4    ] {};
+void()  player_diee4    =       [       $deathe4,       player_diee5    ] {};
+void()  player_diee5    =       [       $deathe5,       player_diee6    ] {};
+void()  player_diee6    =       [       $deathe6,       player_diee7    ] {};
+void()  player_diee7    =       [       $deathe7,       player_diee8    ] {};
+void()  player_diee8    =       [       $deathe8,       player_diee9    ] {};
+void()  player_diee9    =       [       $deathe9,       player_diee9    ] {PlayerDead();};
+
+void()  player_die_ax1  =       [       $axdeth1,       player_die_ax2  ] {};
+void()  player_die_ax2  =       [       $axdeth2,       player_die_ax3  ] {};
+void()  player_die_ax3  =       [       $axdeth3,       player_die_ax4  ] {};
+void()  player_die_ax4  =       [       $axdeth4,       player_die_ax5  ] {};
+void()  player_die_ax5  =       [       $axdeth5,       player_die_ax6  ] {};
+void()  player_die_ax6  =       [       $axdeth6,       player_die_ax7  ] {};
+void()  player_die_ax7  =       [       $axdeth7,       player_die_ax8  ] {};
+void()  player_die_ax8  =       [       $axdeth8,       player_die_ax9  ] {};
+void()  player_die_ax9  =       [       $axdeth9,       player_die_ax9  ] {PlayerDead();};
--- /dev/null
+++ b/QW/progs/progdefs.h
@@ -1,0 +1,140 @@
+
+/* file generated by qcc, do not modify */
+
+typedef struct
+{	int	pad[28];
+	int	self;
+	int	other;
+	int	world;
+	float	time;
+	float	frametime;
+	int	newmis;
+	float	force_retouch;
+	string_t	mapname;
+	float	serverflags;
+	float	total_secrets;
+	float	total_monsters;
+	float	found_secrets;
+	float	killed_monsters;
+	float	parm1;
+	float	parm2;
+	float	parm3;
+	float	parm4;
+	float	parm5;
+	float	parm6;
+	float	parm7;
+	float	parm8;
+	float	parm9;
+	float	parm10;
+	float	parm11;
+	float	parm12;
+	float	parm13;
+	float	parm14;
+	float	parm15;
+	float	parm16;
+	vec3_t	v_forward;
+	vec3_t	v_up;
+	vec3_t	v_right;
+	float	trace_allsolid;
+	float	trace_startsolid;
+	float	trace_fraction;
+	vec3_t	trace_endpos;
+	vec3_t	trace_plane_normal;
+	float	trace_plane_dist;
+	int	trace_ent;
+	float	trace_inopen;
+	float	trace_inwater;
+	int	msg_entity;
+	func_t	main;
+	func_t	StartFrame;
+	func_t	PlayerPreThink;
+	func_t	PlayerPostThink;
+	func_t	ClientKill;
+	func_t	ClientConnect;
+	func_t	PutClientInServer;
+	func_t	ClientDisconnect;
+	func_t	SetNewParms;
+	func_t	SetChangeParms;
+} globalvars_t;
+
+typedef struct
+{
+	float	modelindex;
+	vec3_t	absmin;
+	vec3_t	absmax;
+	float	ltime;
+	float	lastruntime;
+	float	movetype;
+	float	solid;
+	vec3_t	origin;
+	vec3_t	oldorigin;
+	vec3_t	velocity;
+	vec3_t	angles;
+	vec3_t	avelocity;
+	string_t	classname;
+	string_t	model;
+	float	frame;
+	float	skin;
+	float	effects;
+	vec3_t	mins;
+	vec3_t	maxs;
+	vec3_t	size;
+	func_t	touch;
+	func_t	use;
+	func_t	think;
+	func_t	blocked;
+	float	nextthink;
+	int	groundentity;
+	float	health;
+	float	frags;
+	float	weapon;
+	string_t	weaponmodel;
+	float	weaponframe;
+	float	currentammo;
+	float	ammo_shells;
+	float	ammo_nails;
+	float	ammo_rockets;
+	float	ammo_cells;
+	float	items;
+	float	takedamage;
+	int	chain;
+	float	deadflag;
+	vec3_t	view_ofs;
+	float	button0;
+	float	button1;
+	float	button2;
+	float	impulse;
+	float	fixangle;
+	vec3_t	v_angle;
+	string_t	netname;
+	int	enemy;
+	float	flags;
+	float	colormap;
+	float	team;
+	float	max_health;
+	float	teleport_time;
+	float	armortype;
+	float	armorvalue;
+	float	waterlevel;
+	float	watertype;
+	float	ideal_yaw;
+	float	yaw_speed;
+	int	aiment;
+	int	goalentity;
+	float	spawnflags;
+	string_t	target;
+	string_t	targetname;
+	float	dmg_take;
+	float	dmg_save;
+	int	dmg_inflictor;
+	int	owner;
+	vec3_t	movedir;
+	string_t	message;
+	float	sounds;
+	string_t	noise;
+	string_t	noise1;
+	string_t	noise2;
+	string_t	noise3;
+} entvars_t;
+
+#define PROGHEADER_CRC 54730
--- /dev/null
+++ b/QW/progs/progs.src
@@ -1,0 +1,18 @@
+./qwprogs.dat
+
+defs.qc
+subs.qc
+combat.qc
+items.qc
+weapons.qc
+world.qc
+client.qc
+spectate.qc
+player.qc
+doors.qc
+buttons.qc
+triggers.qc
+plats.qc
+misc.qc
+
+server.qc
binary files /dev/null b/QW/progs/qwprogs.dat differ
--- /dev/null
+++ b/QW/progs/server.qc
@@ -1,0 +1,97 @@
+
+void() monster_ogre = {remove(self);};
+void() monster_demon1 = {remove(self);};
+void() monster_shambler = {remove(self);};
+void() monster_knight = {remove(self);};
+void() monster_army = {remove(self);};
+void() monster_wizard = {remove(self);};
+void() monster_dog = {remove(self);};
+void() monster_zombie = {remove(self);};
+void() monster_boss = {remove(self);};
+void() monster_tarbaby = {remove(self);};
+void() monster_hell_knight = {remove(self);};
+void() monster_fish = {remove(self);};
+void() monster_shalrath = {remove(self);};
+void() monster_enforcer = {remove(self);};
+void() monster_oldone = {remove(self);};
+void() event_lightning = {remove(self);};
+
+/*
+==============================================================================
+
+MOVETARGET CODE
+
+The angle of the movetarget effects standing and bowing direction, but has no effect on movement, which allways heads to the next target.
+
+targetname
+must be present.  The name of this movetarget.
+
+target
+the next spot to move to.  If not present, stop here for good.
+
+pausetime
+The number of seconds to spend standing or bowing for path_stand or path_bow
+
+==============================================================================
+*/
+
+/*
+=============
+t_movetarget
+
+Something has bumped into a movetarget.  If it is a monster
+moving towards it, change the next destination and continue.
+==============
+*/
+void() t_movetarget =
+{
+local entity    temp;
+
+	if (other.movetarget != self)
+		return;
+	
+	if (other.enemy)
+		return;         // fighting, not following a path
+
+	temp = self;
+	self = other;
+	other = temp;
+
+	if (self.classname == "monster_ogre")
+		sound (self, CHAN_VOICE, "ogre/ogdrag.wav", 1, ATTN_IDLE);// play chainsaw drag sound
+
+//dprint ("t_movetarget\n");
+	self.goalentity = self.movetarget = find (world, targetname, other.target);
+	self.ideal_yaw = vectoyaw(self.goalentity.origin - self.origin);
+	if (!self.movetarget)
+	{
+		self.pausetime = time + 999999;
+		self.th_stand ();
+		return;
+	}
+};
+
+
+
+void() movetarget_f =
+{
+	if (!self.targetname)
+		objerror ("monster_movetarget: no targetname");
+		
+	self.solid = SOLID_TRIGGER;
+	self.touch = t_movetarget;
+	setsize (self, '-8 -8 -8', '8 8 8');
+	
+};
+
+/*QUAKED path_corner (0.5 0.3 0) (-8 -8 -8) (8 8 8)
+Monsters will continue walking towards the next target corner.
+*/
+void() path_corner =
+{
+	movetarget_f ();
+};
+
+
+
+//============================================================================
--- /dev/null
+++ b/QW/progs/spectate.qc
@@ -1,0 +1,84 @@
+// Spectator functions
+// Added Aug11'97 by Zoid <zoid@idsoftware.com>
+//
+// These functions are called from the server if they exist.
+// Note that Spectators only have one think since they movement code doesn't
+// track them much.  Impulse commands work as usual, but don't call
+// the regular ImpulseCommand handler in weapons.qc since Spectators don't
+// have any weapons and things can explode.
+//
+//   --- Zoid.
+
+/*
+===========
+SpectatorConnect
+
+called when a spectator connects to a server
+============
+*/
+void() SpectatorConnect =
+{
+	bprint (PRINT_MEDIUM, "Spectator ");
+	bprint (PRINT_MEDIUM, self.netname);
+	bprint (PRINT_MEDIUM, " entered the game\n");
+
+	self.goalentity = world; // used for impulse 1 below
+};
+
+/*
+===========
+SpectatorDisconnect
+
+called when a spectator disconnects from a server
+============
+*/
+void() SpectatorDisconnect =
+{
+	bprint (PRINT_MEDIUM, "Spectator ");
+	bprint (PRINT_MEDIUM, self.netname);
+	bprint (PRINT_MEDIUM, " left the game\n");
+};
+
+/*
+================
+SpectatorImpulseCommand
+
+Called by SpectatorThink if the spectator entered an impulse
+================
+*/
+void() SpectatorImpulseCommand =
+{
+	if (self.impulse == 1) {
+		// teleport the spectator to the next spawn point
+		// note that if the spectator is tracking, this doesn't do
+		// much
+		self.goalentity = find(self.goalentity, classname, "info_player_deathmatch");
+		if (self.goalentity == world)
+			self.goalentity = find(self.goalentity, classname, "info_player_deathmatch");
+		if (self.goalentity != world) {
+			setorigin(self, self.goalentity.origin);
+			self.angles = self.goalentity.angles;
+			self.fixangle = TRUE;           // turn this way immediately
+		}
+	}
+
+	self.impulse = 0;
+};
+
+/*
+================
+SpectatorThink
+
+Called every frame after physics are run
+================
+*/
+void() SpectatorThink =
+{
+	// self.origin, etc contains spectator position, so you could
+	// do some neat stuff here
+
+	if (self.impulse)
+		SpectatorImpulseCommand();
+};
+
+
--- /dev/null
+++ b/QW/progs/sprites.qc
@@ -1,0 +1,26 @@
+
+// these are the only sprites still in the game...
+
+$spritename s_explod
+$type vp_parallel
+$load /raid/quake/id1/gfx/sprites/explod03.lbm
+$frame	24	24	56	56
+$frame	120	24	56	56
+$frame	216	24	56	56
+$frame	24	88	56	56
+$frame	120	88	56	56
+$frame	216	88	56	56
+
+
+$spritename s_bubble
+$type vp_parallel
+$load /raid/quake/id1/gfx/sprites/bubble.lbm
+$frame	16	16	16	16
+$frame	40	16	16	16
+
+
+$spritename s_light
+$type vp_parallel
+$load /raid/quake/id1/gfx/sprites/light.lbm
+$frame	104	32	32	32
+
--- /dev/null
+++ b/QW/progs/subs.qc
@@ -1,0 +1,284 @@
+
+
+void() SUB_Null = {};
+
+void() SUB_Remove = {remove(self);};
+
+
+/*
+QuakeEd only writes a single float for angles (bad idea), so up and down are
+just constant angles.
+*/
+vector() SetMovedir =
+{
+	if (self.angles == '0 -1 0')
+		self.movedir = '0 0 1';
+	else if (self.angles == '0 -2 0')
+		self.movedir = '0 0 -1';
+	else
+	{
+		makevectors (self.angles);
+		self.movedir = v_forward;
+	}
+	
+	self.angles = '0 0 0';
+};
+
+/*
+================
+InitTrigger
+================
+*/
+void() InitTrigger =
+{
+// trigger angles are used for one-way touches.  An angle of 0 is assumed
+// to mean no restrictions, so use a yaw of 360 instead.
+	if (self.angles != '0 0 0')
+		SetMovedir ();
+	self.solid = SOLID_TRIGGER;
+	setmodel (self, self.model);	// set size and link into world
+	self.movetype = MOVETYPE_NONE;
+	self.modelindex = 0;
+	self.model = "";
+};
+
+/*
+=============
+SUB_CalcMove
+
+calculate self.velocity and self.nextthink to reach dest from
+self.origin traveling at speed
+===============
+*/
+void(entity ent, vector tdest, float tspeed, void() func) SUB_CalcMoveEnt =
+{
+local entity	stemp;
+	stemp = self;
+	self = ent;
+
+	SUB_CalcMove (tdest, tspeed, func);
+	self = stemp;
+};
+
+void(vector tdest, float tspeed, void() func) SUB_CalcMove =
+{
+local vector	vdestdelta;
+local float		len, traveltime;
+
+	if (!tspeed)
+		objerror("No speed is defined!");
+
+	self.think1 = func;
+	self.finaldest = tdest;
+	self.think = SUB_CalcMoveDone;
+
+	if (tdest == self.origin)
+	{
+		self.velocity = '0 0 0';
+		self.nextthink = self.ltime + 0.1;
+		return;
+	}
+		
+// set destdelta to the vector needed to move
+	vdestdelta = tdest - self.origin;
+	
+// calculate length of vector
+	len = vlen (vdestdelta);
+	
+// divide by speed to get time to reach dest
+	traveltime = len / tspeed;
+
+	if (traveltime < 0.03)
+		traveltime = 0.03;
+	
+// set nextthink to trigger a think when dest is reached
+	self.nextthink = self.ltime + traveltime;
+
+// scale the destdelta vector by the time spent traveling to get velocity
+	self.velocity = vdestdelta * (1/traveltime);	// qcc won't take vec/float	
+};
+
+/*
+============
+After moving, set origin to exact final destination
+============
+*/
+void()  SUB_CalcMoveDone =
+{
+	setorigin(self, self.finaldest);
+	self.velocity = '0 0 0';
+	self.nextthink = -1;
+	if (self.think1)
+		self.think1();
+};
+
+
+/*
+=============
+SUB_CalcAngleMove
+
+calculate self.avelocity and self.nextthink to reach destangle from
+self.angles rotating 
+
+The calling function should make sure self.think is valid
+===============
+*/
+void(entity ent, vector destangle, float tspeed, void() func) SUB_CalcAngleMoveEnt =
+{
+local entity		stemp;
+	stemp = self;
+	self = ent;
+	SUB_CalcAngleMove (destangle, tspeed, func);
+	self = stemp;
+};
+
+void(vector destangle, float tspeed, void() func) SUB_CalcAngleMove =
+{
+local vector	destdelta;
+local float		len, traveltime;
+
+	if (!tspeed)
+		objerror("No speed is defined!");
+		
+// set destdelta to the vector needed to move
+	destdelta = destangle - self.angles;
+	
+// calculate length of vector
+	len = vlen (destdelta);
+	
+// divide by speed to get time to reach dest
+	traveltime = len / tspeed;
+
+// set nextthink to trigger a think when dest is reached
+	self.nextthink = self.ltime + traveltime;
+
+// scale the destdelta vector by the time spent traveling to get velocity
+	self.avelocity = destdelta * (1 / traveltime);
+	
+	self.think1 = func;
+	self.finalangle = destangle;
+	self.think = SUB_CalcAngleMoveDone;
+};
+
+/*
+============
+After rotating, set angle to exact final angle
+============
+*/
+void() SUB_CalcAngleMoveDone =
+{
+	self.angles = self.finalangle;
+	self.avelocity = '0 0 0';
+	self.nextthink = -1;
+	if (self.think1)
+		self.think1();
+};
+
+
+//=============================================================================
+
+void() DelayThink =
+{
+	activator = self.enemy;
+	SUB_UseTargets ();
+	remove(self);
+};
+
+/*
+==============================
+SUB_UseTargets
+
+the global "activator" should be set to the entity that initiated the firing.
+
+If self.delay is set, a DelayedUse entity will be created that will actually
+do the SUB_UseTargets after that many seconds have passed.
+
+Centerprints any self.message to the activator.
+
+Removes all entities with a targetname that match self.killtarget,
+and removes them, so some events can remove other triggers.
+
+Search for (string)targetname in all entities that
+match (string)self.target and call their .use function
+
+==============================
+*/
+void() SUB_UseTargets =
+{
+	local entity t, stemp, otemp, act;
+
+//
+// check for a delay
+//
+	if (self.delay)
+	{
+	// create a temp object to fire at a later time
+		t = spawn();
+		t.classname = "DelayedUse";
+		t.nextthink = time + self.delay;
+		t.think = DelayThink;
+		t.enemy = activator;
+		t.message = self.message;
+		t.killtarget = self.killtarget;
+		t.target = self.target;
+		return;
+	}
+	
+	
+//
+// print the message
+//
+	if (activator.classname == "player" && self.message != "")
+	{
+		centerprint (activator, self.message);
+		if (!self.noise)
+			sound (activator, CHAN_VOICE, "misc/talk.wav", 1, ATTN_NORM);
+	}
+
+//
+// kill the killtagets
+//
+	if (self.killtarget)
+	{
+		t = world;
+		do
+		{
+			t = find (t, targetname, self.killtarget);
+			if (!t)
+				return;
+			remove (t);
+		} while ( 1 );
+	}
+	
+//
+// fire targets
+//
+	if (self.target)
+	{
+		act = activator;
+		t = world;
+		do
+		{
+			t = find (t, targetname, self.target);
+			if (!t)
+			{
+				return;
+			}
+			stemp = self;
+			otemp = other;
+			self = t;
+			other = stemp;
+			if (self.use != SUB_Null)
+			{
+				if (self.use)
+					self.use ();
+			}
+			self = stemp;
+			other = otemp;
+			activator = act;
+		} while ( 1 );
+	}
+	
+
+};
+
--- /dev/null
+++ b/QW/progs/triggers.qc
@@ -1,0 +1,646 @@
+
+entity stemp, otemp, s, old;
+
+
+void() trigger_reactivate =
+{
+	self.solid = SOLID_TRIGGER;
+};
+
+//=============================================================================
+
+float	SPAWNFLAG_NOMESSAGE = 1;
+float	SPAWNFLAG_NOTOUCH = 1;
+
+// the wait time has passed, so set back up for another activation
+void() multi_wait =
+{
+	if (self.max_health)
+	{
+		self.health = self.max_health;
+		self.takedamage = DAMAGE_YES;
+		self.solid = SOLID_BBOX;
+	}
+};
+
+
+// the trigger was just touched/killed/used
+// self.enemy should be set to the activator so it can be held through a delay
+// so wait for the delay time before firing
+void() multi_trigger =
+{
+	if (self.nextthink > time)
+	{
+		return;		// allready been triggered
+	}
+
+	if (self.classname == "trigger_secret")
+	{
+		if (self.enemy.classname != "player")
+			return;
+		found_secrets = found_secrets + 1;
+		WriteByte (MSG_ALL, SVC_FOUNDSECRET);
+	}
+
+	if (self.noise)
+		sound (self, CHAN_VOICE, self.noise, 1, ATTN_NORM);
+
+// don't trigger again until reset
+	self.takedamage = DAMAGE_NO;
+
+	activator = self.enemy;
+	
+	SUB_UseTargets();
+
+	if (self.wait > 0)	
+	{
+		self.think = multi_wait;
+		self.nextthink = time + self.wait;
+	}
+	else
+	{	// we can't just remove (self) here, because this is a touch function
+		// called wheil C code is looping through area links...
+		self.touch = SUB_Null;
+		self.nextthink = time + 0.1;
+		self.think = SUB_Remove;
+	}
+};
+
+void() multi_killed =
+{
+	self.enemy = damage_attacker;
+	multi_trigger();
+};
+
+void() multi_use =
+{
+	self.enemy = activator;
+	multi_trigger();
+};
+
+void() multi_touch =
+{
+	if (other.classname != "player")
+		return;
+	
+// if the trigger has an angles field, check player's facing direction
+	if (self.movedir != '0 0 0')
+	{
+		makevectors (other.angles);
+		if (v_forward * self.movedir < 0)
+			return;		// not facing the right way
+	}
+	
+	self.enemy = other;
+	multi_trigger ();
+};
+
+/*QUAKED trigger_multiple (.5 .5 .5) ? notouch
+Variable sized repeatable trigger.  Must be targeted at one or more entities.  If "health" is set, the trigger must be killed to activate each time.
+If "delay" is set, the trigger waits some time after activating before firing.
+"wait" : Seconds between triggerings. (.2 default)
+If notouch is set, the trigger is only fired by other entities, not by touching.
+NOTOUCH has been obsoleted by trigger_relay!
+sounds
+1)	secret
+2)	beep beep
+3)	large switch
+4)
+set "message" to text string
+*/
+void() trigger_multiple =
+{
+	if (self.sounds == 1)
+	{
+		precache_sound ("misc/secret.wav");
+		self.noise = "misc/secret.wav";
+	}
+	else if (self.sounds == 2)
+	{
+		precache_sound ("misc/talk.wav");
+		self.noise = "misc/talk.wav";
+	}
+	else if (self.sounds == 3)
+	{
+		precache_sound ("misc/trigger1.wav");
+		self.noise = "misc/trigger1.wav";
+	}
+	
+	if (!self.wait)
+		self.wait = 0.2;
+	self.use = multi_use;
+
+	InitTrigger ();
+
+	if (self.health)
+	{
+		if (self.spawnflags & SPAWNFLAG_NOTOUCH)
+			objerror ("health and notouch don't make sense\n");
+		self.max_health = self.health;
+		self.th_die = multi_killed;
+		self.takedamage = DAMAGE_YES;
+		self.solid = SOLID_BBOX;
+		setorigin (self, self.origin);	// make sure it links into the world
+	}
+	else
+	{
+		if ( !(self.spawnflags & SPAWNFLAG_NOTOUCH) )
+		{
+			self.touch = multi_touch;
+		}
+	}
+};
+
+
+/*QUAKED trigger_once (.5 .5 .5) ? notouch
+Variable sized trigger. Triggers once, then removes itself.  You must set the key "target" to the name of another object in the level that has a matching
+"targetname".  If "health" is set, the trigger must be killed to activate.
+If notouch is set, the trigger is only fired by other entities, not by touching.
+if "killtarget" is set, any objects that have a matching "target" will be removed when the trigger is fired.
+if "angle" is set, the trigger will only fire when someone is facing the direction of the angle.  Use "360" for an angle of 0.
+sounds
+1)	secret
+2)	beep beep
+3)	large switch
+4)
+set "message" to text string
+*/
+void() trigger_once =
+{
+	self.wait = -1;
+	trigger_multiple();
+};
+
+//=============================================================================
+
+/*QUAKED trigger_relay (.5 .5 .5) (-8 -8 -8) (8 8 8)
+This fixed size trigger cannot be touched, it can only be fired by other events.  It can contain killtargets, targets, delays, and messages.
+*/
+void() trigger_relay =
+{
+	self.use = SUB_UseTargets;
+};
+
+
+//=============================================================================
+
+/*QUAKED trigger_secret (.5 .5 .5) ?
+secret counter trigger
+sounds
+1)	secret
+2)	beep beep
+3)
+4)
+set "message" to text string
+*/
+void() trigger_secret =
+{
+	total_secrets = total_secrets + 1;
+	self.wait = -1;
+	if (!self.message)
+		self.message = "You found a secret area!";
+	if (!self.sounds)
+		self.sounds = 1;
+	
+	if (self.sounds == 1)
+	{
+		precache_sound ("misc/secret.wav");
+		self.noise = "misc/secret.wav";
+	}
+	else if (self.sounds == 2)
+	{
+		precache_sound ("misc/talk.wav");
+		self.noise = "misc/talk.wav";
+	}
+
+	trigger_multiple ();
+};
+
+//=============================================================================
+
+
+void() counter_use =
+{
+	local string junk;
+
+	self.count = self.count - 1;
+	if (self.count < 0)
+		return;
+	
+	if (self.count != 0)
+	{
+		if (activator.classname == "player"
+		&& (self.spawnflags & SPAWNFLAG_NOMESSAGE) == 0)
+		{
+			if (self.count >= 4)
+				centerprint (activator, "There are more to go...");
+			else if (self.count == 3)
+				centerprint (activator, "Only 3 more to go...");
+			else if (self.count == 2)
+				centerprint (activator, "Only 2 more to go...");
+			else
+				centerprint (activator, "Only 1 more to go...");
+		}
+		return;
+	}
+	
+	if (activator.classname == "player"
+	&& (self.spawnflags & SPAWNFLAG_NOMESSAGE) == 0)
+		centerprint(activator, "Sequence completed!");
+	self.enemy = activator;
+	multi_trigger ();
+};
+
+/*QUAKED trigger_counter (.5 .5 .5) ? nomessage
+Acts as an intermediary for an action that takes multiple inputs.
+
+If nomessage is not set, t will print "1 more.. " etc when triggered and "sequence complete" when finished.
+
+After the counter has been triggered "count" times (default 2), it will fire all of it's targets and remove itself.
+*/
+void() trigger_counter =
+{
+	self.wait = -1;
+	if (!self.count)
+		self.count = 2;
+
+	self.use = counter_use;
+};
+
+
+/*
+==============================================================================
+
+TELEPORT TRIGGERS
+
+==============================================================================
+*/
+
+float	PLAYER_ONLY	= 1;
+float	SILENT = 2;
+
+void() play_teleport =
+{
+	local	float v;
+	local	string tmpstr;
+
+	v = random() * 5;
+	if (v < 1)
+		tmpstr = "misc/r_tele1.wav";
+	else if (v < 2)
+		tmpstr = "misc/r_tele2.wav";
+	else if (v < 3)
+		tmpstr = "misc/r_tele3.wav";
+	else if (v < 4)
+		tmpstr = "misc/r_tele4.wav";
+	else
+		tmpstr = "misc/r_tele5.wav";
+
+	sound (self, CHAN_VOICE, tmpstr, 1, ATTN_NORM);
+	remove (self);
+};
+
+void(vector org) spawn_tfog =
+{
+	s = spawn ();
+	s.origin = org;
+	s.nextthink = time + 0.2;
+	s.think = play_teleport;
+
+	WriteByte (MSG_MULTICAST, SVC_TEMPENTITY);
+	WriteByte (MSG_MULTICAST, TE_TELEPORT);
+	WriteCoord (MSG_MULTICAST, org_x);
+	WriteCoord (MSG_MULTICAST, org_y);
+	WriteCoord (MSG_MULTICAST, org_z);
+	multicast (org, MULTICAST_PHS);
+};
+
+
+void() tdeath_touch =
+{
+	local entity other2;
+
+	if (other == self.owner)
+		return;
+
+// frag anyone who teleports in on top of an invincible player
+	if (other.classname == "player")
+	{
+		if (other.invincible_finished > time &&
+			self.owner.invincible_finished > time) {
+			self.classname = "teledeath3";
+			other.invincible_finished = 0;
+			self.owner.invincible_finished = 0;
+			T_Damage (other, self, self, 50000);
+			other2 = self.owner;
+			self.owner = other;
+			T_Damage (other2, self, self, 50000);
+		}
+			
+		if (other.invincible_finished > time)
+		{
+			self.classname = "teledeath2";
+			T_Damage (self.owner, self, self, 50000);
+			return;
+		}
+		
+	}
+
+	if (other.health)
+	{
+		T_Damage (other, self, self, 50000);
+	}
+};
+
+
+void(vector org, entity death_owner) spawn_tdeath =
+{
+local entity	death;
+
+	death = spawn();
+	death.classname = "teledeath";
+	death.movetype = MOVETYPE_NONE;
+	death.solid = SOLID_TRIGGER;
+	death.angles = '0 0 0';
+	setsize (death, death_owner.mins - '1 1 1', death_owner.maxs + '1 1 1');
+	setorigin (death, org);
+	death.touch = tdeath_touch;
+	death.nextthink = time + 0.2;
+	death.think = SUB_Remove;
+	death.owner = death_owner;
+	
+	force_retouch = 2;		// make sure even still objects get hit
+};
+
+void() teleport_touch =
+{
+local entity	t;
+local vector	org;
+
+	if (self.targetname)
+	{
+		if (self.nextthink < time)
+		{
+			return;		// not fired yet
+		}
+	}
+
+	if (self.spawnflags & PLAYER_ONLY)
+	{
+		if (other.classname != "player")
+			return;
+	}
+
+// only teleport living creatures
+	if (other.health <= 0 || other.solid != SOLID_SLIDEBOX)
+		return;
+
+	SUB_UseTargets ();
+
+// put a tfog where the player was
+	spawn_tfog (other.origin);
+
+	t = find (world, targetname, self.target);
+	if (!t)
+		objerror ("couldn't find target");
+		
+// spawn a tfog flash in front of the destination
+	makevectors (t.mangle);
+	org = t.origin + 32 * v_forward;
+
+	spawn_tfog (org);
+	spawn_tdeath(t.origin, other);
+
+// move the player and lock him down for a little while
+	if (!other.health)
+	{
+		other.origin = t.origin;
+		other.velocity = (v_forward * other.velocity_x) + (v_forward * other.velocity_y);
+		return;
+	}
+
+	setorigin (other, t.origin);
+	other.angles = t.mangle;
+	if (other.classname == "player")
+	{
+		other.fixangle = 1;		// turn this way immediately
+		other.teleport_time = time + 0.7;
+		if (other.flags & FL_ONGROUND)
+			other.flags = other.flags - FL_ONGROUND;
+		other.velocity = v_forward * 300;
+	}
+	other.flags = other.flags - other.flags & FL_ONGROUND;
+};
+
+/*QUAKED info_teleport_destination (.5 .5 .5) (-8 -8 -8) (8 8 32)
+This is the destination marker for a teleporter.  It should have a "targetname" field with the same value as a teleporter's "target" field.
+*/
+void() info_teleport_destination =
+{
+// this does nothing, just serves as a target spot
+	self.mangle = self.angles;
+	self.angles = '0 0 0';
+	self.model = "";
+	self.origin = self.origin + '0 0 27';
+	if (!self.targetname)
+		objerror ("no targetname");
+};
+
+void() teleport_use =
+{
+	self.nextthink = time + 0.2;
+	force_retouch = 2;		// make sure even still objects get hit
+	self.think = SUB_Null;
+};
+
+/*QUAKED trigger_teleport (.5 .5 .5) ? PLAYER_ONLY SILENT
+Any object touching this will be transported to the corresponding info_teleport_destination entity. You must set the "target" field, and create an object with a "targetname" field that matches.
+
+If the trigger_teleport has a targetname, it will only teleport entities when it has been fired.
+*/
+void() trigger_teleport =
+{
+	local vector o;
+
+	InitTrigger ();
+	self.touch = teleport_touch;
+	// find the destination 
+	if (!self.target)
+		objerror ("no target");
+	self.use = teleport_use;
+
+	if (!(self.spawnflags & SILENT))
+	{
+		precache_sound ("ambience/hum1.wav");
+		o = (self.mins + self.maxs)*0.5;
+		ambientsound (o, "ambience/hum1.wav",0.5 , ATTN_STATIC);
+	}
+};
+
+/*
+==============================================================================
+
+trigger_setskill
+
+==============================================================================
+*/
+
+/*QUAKED trigger_setskill (.5 .5 .5) ?
+sets skill level to the value of "message".
+Only used on start map.
+*/
+void() trigger_setskill =
+{
+	remove (self);
+};
+
+
+/*
+==============================================================================
+
+ONLY REGISTERED TRIGGERS
+
+==============================================================================
+*/
+
+void() trigger_onlyregistered_touch =
+{
+	if (other.classname != "player")
+		return;
+	if (self.attack_finished > time)
+		return;
+
+	self.attack_finished = time + 2;
+	if (cvar("registered"))
+	{
+		self.message = "";
+		SUB_UseTargets ();
+		remove (self);
+	}
+	else
+	{
+		if (self.message != "")
+		{
+			centerprint (other, self.message);
+			sound (other, CHAN_BODY, "misc/talk.wav", 1, ATTN_NORM);
+		}
+	}
+};
+
+/*QUAKED trigger_onlyregistered (.5 .5 .5) ?
+Only fires if playing the registered version, otherwise prints the message
+*/
+void() trigger_onlyregistered =
+{
+	precache_sound ("misc/talk.wav");
+	InitTrigger ();
+	self.touch = trigger_onlyregistered_touch;
+};
+
+//============================================================================
+
+void() hurt_on =
+{
+	self.solid = SOLID_TRIGGER;
+	self.nextthink = -1;
+};
+
+void() hurt_touch =
+{
+	if (other.takedamage)
+	{
+		self.solid = SOLID_NOT;
+		T_Damage (other, self, self, self.dmg);
+		self.think = hurt_on;
+		self.nextthink = time + 1;
+	}
+
+	return;
+};
+
+/*QUAKED trigger_hurt (.5 .5 .5) ?
+Any object touching this will be hurt
+set dmg to damage amount
+defalt dmg = 5
+*/
+void() trigger_hurt =
+{
+	InitTrigger ();
+	self.touch = hurt_touch;
+	if (!self.dmg)
+		self.dmg = 5;
+};
+
+//============================================================================
+
+float PUSH_ONCE = 1;
+
+void() trigger_push_touch =
+{
+	if (other.classname == "grenade")
+		other.velocity = self.speed * self.movedir * 10;
+	else if (other.health > 0)
+	{
+		other.velocity = self.speed * self.movedir * 10;
+		if (other.classname == "player")
+		{
+			if (other.fly_sound < time)
+			{
+				other.fly_sound = time + 1.5;
+				sound (other, CHAN_AUTO, "ambience/windfly.wav", 1, ATTN_NORM);
+			}
+		}
+	}
+	if (self.spawnflags & PUSH_ONCE)
+		remove(self);
+};
+
+
+/*QUAKED trigger_push (.5 .5 .5) ? PUSH_ONCE
+Pushes the player
+*/
+void() trigger_push =
+{
+	InitTrigger ();
+	precache_sound ("ambience/windfly.wav");
+	self.touch = trigger_push_touch;
+	if (!self.speed)
+		self.speed = 1000;
+};
+
+//============================================================================
+
+void() trigger_monsterjump_touch =
+{
+	if ( other.flags & (FL_MONSTER | FL_FLY | FL_SWIM) != FL_MONSTER )
+		return;
+
+// set XY even if not on ground, so the jump will clear lips
+	other.velocity_x = self.movedir_x * self.speed;
+	other.velocity_y = self.movedir_y * self.speed;
+	
+	if ( !(other.flags & FL_ONGROUND) )
+		return;
+	
+	other.flags = other.flags - FL_ONGROUND;
+
+	other.velocity_z = self.height;
+};
+
+/*QUAKED trigger_monsterjump (.5 .5 .5) ?
+Walking monsters that touch this will jump in the direction of the trigger's angle
+"speed" default to 200, the speed thrown forward
+"height" default to 200, the speed thrown upwards
+*/
+void() trigger_monsterjump =
+{
+	if (!self.speed)
+		self.speed = 200;
+	if (!self.height)
+		self.height = 200;
+	if (self.angles == '0 0 0')
+		self.angles = '0 360 0';
+	InitTrigger ();
+	self.touch = trigger_monsterjump_touch;
+};
+
--- /dev/null
+++ b/QW/progs/weapons.qc
@@ -1,0 +1,1402 @@
+/*
+*/
+void (entity targ, entity inflictor, entity attacker, float damage) T_Damage;
+void () player_run;
+void(entity bomb, entity attacker, float rad, entity ignore, string dtype) T_RadiusDamage;
+void(vector org, float damage) SpawnBlood;
+void() SuperDamageSound;
+
+
+// called by worldspawn
+void() W_Precache =
+{
+	precache_sound ("weapons/r_exp3.wav");  // new rocket explosion
+	precache_sound ("weapons/rocket1i.wav");        // spike gun
+	precache_sound ("weapons/sgun1.wav");
+	precache_sound ("weapons/guncock.wav"); // player shotgun
+	precache_sound ("weapons/ric1.wav");    // ricochet (used in c code)
+	precache_sound ("weapons/ric2.wav");    // ricochet (used in c code)
+	precache_sound ("weapons/ric3.wav");    // ricochet (used in c code)
+	precache_sound ("weapons/spike2.wav");  // super spikes
+	precache_sound ("weapons/tink1.wav");   // spikes tink (used in c code)
+	precache_sound ("weapons/grenade.wav"); // grenade launcher
+	precache_sound ("weapons/bounce.wav");          // grenade bounce
+	precache_sound ("weapons/shotgn2.wav"); // super shotgun
+};
+
+float() crandom =
+{
+	return 2*(random() - 0.5);
+};
+
+/*
+================
+W_FireAxe
+================
+*/
+void() W_FireAxe =
+{
+	local   vector  source;
+	local   vector  org;
+
+	makevectors (self.v_angle);
+	source = self.origin + '0 0 16';
+	traceline (source, source + v_forward*64, FALSE, self);
+	if (trace_fraction == 1.0)
+		return;
+	
+	org = trace_endpos - v_forward*4;
+
+	if (trace_ent.takedamage)
+	{
+		trace_ent.axhitme = 1;
+		SpawnBlood (org, 20);
+		if (deathmatch > 3)
+			T_Damage (trace_ent, self, self, 75);
+		else
+			T_Damage (trace_ent, self, self, 20);
+	}
+	else
+	{       // hit wall
+		sound (self, CHAN_WEAPON, "player/axhit2.wav", 1, ATTN_NORM);
+
+		WriteByte (MSG_MULTICAST, SVC_TEMPENTITY);
+		WriteByte (MSG_MULTICAST, TE_GUNSHOT);
+		WriteByte (MSG_MULTICAST, 3);
+		WriteCoord (MSG_MULTICAST, org_x);
+		WriteCoord (MSG_MULTICAST, org_y);
+		WriteCoord (MSG_MULTICAST, org_z);
+		multicast (org, MULTICAST_PVS);
+	}
+};
+
+
+//============================================================================
+
+
+vector() wall_velocity =
+{
+	local vector    vel;
+	
+	vel = normalize (self.velocity);
+	vel = normalize(vel + v_up*(random()- 0.5) + v_right*(random()- 0.5));
+	vel = vel + 2*trace_plane_normal;
+	vel = vel * 200;
+	
+	return vel;
+};
+
+
+/*
+================
+SpawnMeatSpray
+================
+*/
+void(vector org, vector vel) SpawnMeatSpray =
+{
+	local   entity missile;
+	local   vector  org;
+
+	missile = spawn ();
+	missile.owner = self;
+	missile.movetype = MOVETYPE_BOUNCE;
+	missile.solid = SOLID_NOT;
+
+	makevectors (self.angles);
+
+	missile.velocity = vel;
+	missile.velocity_z = missile.velocity_z + 250 + 50*random();
+
+	missile.avelocity = '3000 1000 2000';
+	
+// set missile duration
+	missile.nextthink = time + 1;
+	missile.think = SUB_Remove;
+
+	setmodel (missile, "progs/zom_gib.mdl");
+	setsize (missile, '0 0 0', '0 0 0');            
+	setorigin (missile, org);
+};
+
+/*
+================
+SpawnBlood
+================
+*/
+void(vector org, float damage) SpawnBlood =
+{
+	WriteByte (MSG_MULTICAST, SVC_TEMPENTITY);
+	WriteByte (MSG_MULTICAST, TE_BLOOD);
+	WriteByte (MSG_MULTICAST, 1);
+	WriteCoord (MSG_MULTICAST, org_x);
+	WriteCoord (MSG_MULTICAST, org_y);
+	WriteCoord (MSG_MULTICAST, org_z);
+	multicast (org, MULTICAST_PVS);
+};
+
+/*
+================
+spawn_touchblood
+================
+*/
+void(float damage) spawn_touchblood =
+{
+	local vector    vel;
+
+	vel = wall_velocity () * 0.2;
+	SpawnBlood (self.origin + vel*0.01, damage);
+};
+
+/*
+==============================================================================
+
+MULTI-DAMAGE
+
+Collects multiple small damages into a single damage
+
+==============================================================================
+*/
+
+entity  multi_ent;
+float   multi_damage;
+
+vector  blood_org;
+float   blood_count;
+
+vector  puff_org;
+float   puff_count;
+
+void() ClearMultiDamage =
+{
+	multi_ent = world;
+	multi_damage = 0;
+	blood_count = 0;
+	puff_count = 0;
+};
+
+void() ApplyMultiDamage =
+{
+	if (!multi_ent)
+		return;
+	T_Damage (multi_ent, self, self, multi_damage);
+};
+
+void(entity hit, float damage) AddMultiDamage =
+{
+	if (!hit)
+		return;
+	
+	if (hit != multi_ent)
+	{
+		ApplyMultiDamage ();
+		multi_damage = damage;
+		multi_ent = hit;
+	}
+	else
+		multi_damage = multi_damage + damage;
+};
+
+void() Multi_Finish =
+{
+	if (puff_count)
+	{
+		WriteByte (MSG_MULTICAST, SVC_TEMPENTITY);
+		WriteByte (MSG_MULTICAST, TE_GUNSHOT);
+		WriteByte (MSG_MULTICAST, puff_count);
+		WriteCoord (MSG_MULTICAST, puff_org_x);
+		WriteCoord (MSG_MULTICAST, puff_org_y);
+		WriteCoord (MSG_MULTICAST, puff_org_z);
+		multicast (puff_org, MULTICAST_PVS);
+	}
+
+	if (blood_count)
+	{
+		WriteByte (MSG_MULTICAST, SVC_TEMPENTITY);
+		WriteByte (MSG_MULTICAST, TE_BLOOD);
+		WriteByte (MSG_MULTICAST, blood_count);
+		WriteCoord (MSG_MULTICAST, blood_org_x);
+		WriteCoord (MSG_MULTICAST, blood_org_y);
+		WriteCoord (MSG_MULTICAST, blood_org_z);
+		multicast (puff_org, MULTICAST_PVS);
+	}
+};
+
+/*
+==============================================================================
+BULLETS
+==============================================================================
+*/
+
+/*
+================
+TraceAttack
+================
+*/
+void(float damage, vector dir) TraceAttack =
+{
+	local   vector  vel, org;
+	
+	vel = normalize(dir + v_up*crandom() + v_right*crandom());
+	vel = vel + 2*trace_plane_normal;
+	vel = vel * 200;
+
+	org = trace_endpos - dir*4;
+
+	if (trace_ent.takedamage)
+	{
+		blood_count = blood_count + 1;
+		blood_org = org;
+		AddMultiDamage (trace_ent, damage);
+	}
+	else
+	{
+		puff_count = puff_count + 1;
+	}
+};
+
+/*
+================
+FireBullets
+
+Used by shotgun, super shotgun, and enemy soldier firing
+Go to the trouble of combining multiple pellets into a single damage call.
+================
+*/
+void(float shotcount, vector dir, vector spread) FireBullets =
+{
+	local   vector direction;
+	local   vector  src;
+	
+	makevectors(self.v_angle);
+
+	src = self.origin + v_forward*10;
+	src_z = self.absmin_z + self.size_z * 0.7;
+
+	ClearMultiDamage ();
+
+	traceline (src, src + dir*2048, FALSE, self);
+	puff_org = trace_endpos - dir*4;
+
+	while (shotcount > 0)
+	{
+		direction = dir + crandom()*spread_x*v_right + crandom()*spread_y*v_up;
+		traceline (src, src + direction*2048, FALSE, self);
+		if (trace_fraction != 1.0)
+			TraceAttack (4, direction);
+
+		shotcount = shotcount - 1;
+	}
+	ApplyMultiDamage ();
+	Multi_Finish ();
+};
+
+/*
+================
+W_FireShotgun
+================
+*/
+void() W_FireShotgun =
+{
+	local vector dir;
+
+	sound (self, CHAN_WEAPON, "weapons/guncock.wav", 1, ATTN_NORM); 
+
+	msg_entity = self;
+	WriteByte (MSG_ONE, SVC_SMALLKICK);
+	
+	if (deathmatch != 4 )
+		self.currentammo = self.ammo_shells = self.ammo_shells - 1;
+
+	dir = aim (self, 100000);
+	FireBullets (6, dir, '0.04 0.04 0');
+};
+
+
+/*
+================
+W_FireSuperShotgun
+================
+*/
+void() W_FireSuperShotgun =
+{
+	local vector dir;
+
+	if (self.currentammo == 1)
+	{
+		W_FireShotgun ();
+		return;
+	}
+		
+	sound (self ,CHAN_WEAPON, "weapons/shotgn2.wav", 1, ATTN_NORM); 
+
+	msg_entity = self;
+	WriteByte (MSG_ONE, SVC_BIGKICK);
+	
+	if (deathmatch != 4)
+		self.currentammo = self.ammo_shells = self.ammo_shells - 2;
+	dir = aim (self, 100000);
+	FireBullets (14, dir, '0.14 0.08 0');
+};
+
+
+/*
+==============================================================================
+
+ROCKETS
+
+==============================================================================
+*/
+
+void() T_MissileTouch =
+{
+	local float     damg;
+
+//	if (deathmatch == 4)
+//	{
+//	if ( ((other.weapon == 32) || (other.weapon == 16)))
+//		{	
+//			if (random() < 0.1)
+//			{
+//				if (other != world)
+//				{
+//	//				bprint (PRINT_HIGH, "Got here\n");
+//					other.deathtype = "blaze";
+//					T_Damage (other, self, self.owner, 1000 );
+//					T_RadiusDamage (self, self.owner, 1000, other);
+//				}
+//			}
+//		}	
+//	}
+
+	if (other == self.owner)
+		return;         // don't explode on owner
+
+	if (self.voided) {
+		return;
+	}
+	self.voided = 1;
+
+	if (pointcontents(self.origin) == CONTENT_SKY)
+	{
+		remove(self);
+		return;
+	}
+
+	damg = 100 + random()*20;
+	
+	if (other.health)
+	{
+		other.deathtype = "rocket";
+		T_Damage (other, self, self.owner, damg );
+	}
+
+	// don't do radius damage to the other, because all the damage
+	// was done in the impact
+
+
+	T_RadiusDamage (self, self.owner, 120, other, "rocket");
+
+//  sound (self, CHAN_WEAPON, "weapons/r_exp3.wav", 1, ATTN_NORM);
+	self.origin = self.origin - 8 * normalize(self.velocity);
+
+	WriteByte (MSG_MULTICAST, SVC_TEMPENTITY);
+	WriteByte (MSG_MULTICAST, TE_EXPLOSION);
+	WriteCoord (MSG_MULTICAST, self.origin_x);
+	WriteCoord (MSG_MULTICAST, self.origin_y);
+	WriteCoord (MSG_MULTICAST, self.origin_z);
+	multicast (self.origin, MULTICAST_PHS);
+
+	remove(self);
+};
+
+
+
+/*
+================
+W_FireRocket
+================
+*/
+void() W_FireRocket =
+{
+	if (deathmatch != 4)
+		self.currentammo = self.ammo_rockets = self.ammo_rockets - 1;
+	
+	sound (self, CHAN_WEAPON, "weapons/sgun1.wav", 1, ATTN_NORM);
+
+	msg_entity = self;
+	WriteByte (MSG_ONE, SVC_SMALLKICK);
+
+	newmis = spawn ();
+	newmis.owner = self;
+	newmis.movetype = MOVETYPE_FLYMISSILE;
+	newmis.solid = SOLID_BBOX;
+		
+// set newmis speed     
+
+	makevectors (self.v_angle);
+	newmis.velocity = aim(self, 1000);
+	newmis.velocity = newmis.velocity * 1000;
+	newmis.angles = vectoangles(newmis.velocity);
+	
+	newmis.touch = T_MissileTouch;
+	newmis.voided = 0;
+	
+// set newmis duration
+	newmis.nextthink = time + 5;
+	newmis.think = SUB_Remove;
+	newmis.classname = "rocket";
+
+	setmodel (newmis, "progs/missile.mdl");
+	setsize (newmis, '0 0 0', '0 0 0');             
+	setorigin (newmis, self.origin + v_forward*8 + '0 0 16');
+};
+
+/*
+===============================================================================
+LIGHTNING
+===============================================================================
+*/
+
+void(entity from, float damage) LightningHit =
+{
+	WriteByte (MSG_MULTICAST, SVC_TEMPENTITY);
+	WriteByte (MSG_MULTICAST, TE_LIGHTNINGBLOOD);
+	WriteCoord (MSG_MULTICAST, trace_endpos_x);
+	WriteCoord (MSG_MULTICAST, trace_endpos_y);
+	WriteCoord (MSG_MULTICAST, trace_endpos_z);
+	multicast (trace_endpos, MULTICAST_PVS);
+
+	T_Damage (trace_ent, from, from, damage);
+};
+
+/*
+=================
+LightningDamage
+=================
+*/
+void(vector p1, vector p2, entity from, float damage) LightningDamage =
+{
+	local entity            e1, e2;
+	local vector            f;
+	
+	f = p2 - p1;
+	normalize (f);
+	f_x = 0 - f_y;
+	f_y = f_x;
+	f_z = 0;
+	f = f*16;
+
+	e1 = e2 = world;
+
+	traceline (p1, p2, FALSE, self);
+
+	if (trace_ent.takedamage)
+	{
+		LightningHit (from, damage);
+		if (self.classname == "player")
+		{
+			if (other.classname == "player")
+				trace_ent.velocity_z = trace_ent.velocity_z + 400;
+		}
+	}
+	e1 = trace_ent;
+
+	traceline (p1 + f, p2 + f, FALSE, self);
+	if (trace_ent != e1 && trace_ent.takedamage)
+	{
+		LightningHit (from, damage);
+	}
+	e2 = trace_ent;
+
+	traceline (p1 - f, p2 - f, FALSE, self);
+	if (trace_ent != e1 && trace_ent != e2 && trace_ent.takedamage)
+	{
+		LightningHit (from, damage);
+	}
+};
+
+
+void() W_FireLightning =
+{
+	local   vector          org;
+	local   float           cells;
+
+	if (self.ammo_cells < 1)
+	{
+		self.weapon = W_BestWeapon ();
+		W_SetCurrentAmmo ();
+		return;
+	}
+
+// explode if under water
+	if (self.waterlevel > 1)
+	{
+		if (deathmatch > 3)
+		{
+			if (random() <= 0.5)
+			{
+				self.deathtype = "selfwater";
+				T_Damage (self, self, self.owner, 4000 );
+			}
+			else
+			{
+				cells = self.ammo_cells;
+				self.ammo_cells = 0;
+				W_SetCurrentAmmo ();
+				T_RadiusDamage (self, self, 35*cells, world, "");
+				return;
+			}
+		}
+		else
+		{
+			cells = self.ammo_cells;
+			self.ammo_cells = 0;
+			W_SetCurrentAmmo ();
+			T_RadiusDamage (self, self, 35*cells, world,"");
+			return;
+		}
+	}
+
+	if (self.t_width < time)
+	{
+		sound (self, CHAN_WEAPON, "weapons/lhit.wav", 1, ATTN_NORM);
+		self.t_width = time + 0.6;
+	}
+	msg_entity = self;
+	WriteByte (MSG_ONE, SVC_SMALLKICK);
+
+	if (deathmatch != 4)
+		self.currentammo = self.ammo_cells = self.ammo_cells - 1;
+
+	org = self.origin + '0 0 16';
+	
+	traceline (org, org + v_forward*600, TRUE, self);
+
+	WriteByte (MSG_MULTICAST, SVC_TEMPENTITY);
+	WriteByte (MSG_MULTICAST, TE_LIGHTNING2);
+	WriteEntity (MSG_MULTICAST, self);
+	WriteCoord (MSG_MULTICAST, org_x);
+	WriteCoord (MSG_MULTICAST, org_y);
+	WriteCoord (MSG_MULTICAST, org_z);
+	WriteCoord (MSG_MULTICAST, trace_endpos_x);
+	WriteCoord (MSG_MULTICAST, trace_endpos_y);
+	WriteCoord (MSG_MULTICAST, trace_endpos_z);
+	multicast (org, MULTICAST_PHS);
+
+	LightningDamage (self.origin, trace_endpos + v_forward*4, self, 30);
+};
+
+
+//=============================================================================
+
+
+void() GrenadeExplode =
+{
+	if (self.voided) {
+		return;
+	}
+	self.voided = 1;
+
+	T_RadiusDamage (self, self.owner, 120, world, "grenade");
+
+	WriteByte (MSG_MULTICAST, SVC_TEMPENTITY);
+	WriteByte (MSG_MULTICAST, TE_EXPLOSION);
+	WriteCoord (MSG_MULTICAST, self.origin_x);
+	WriteCoord (MSG_MULTICAST, self.origin_y);
+	WriteCoord (MSG_MULTICAST, self.origin_z);
+	multicast (self.origin, MULTICAST_PHS);
+
+	remove (self);
+};
+
+void() GrenadeTouch =
+{
+	if (other == self.owner)
+		return;         // don't explode on owner
+	if (other.takedamage == DAMAGE_AIM)
+	{
+		GrenadeExplode();
+		return;
+	}
+	sound (self, CHAN_WEAPON, "weapons/bounce.wav", 1, ATTN_NORM);  // bounce sound
+	if (self.velocity == '0 0 0')
+		self.avelocity = '0 0 0';
+};
+
+/*
+================
+W_FireGrenade
+================
+*/
+void() W_FireGrenade =
+{       
+	if (deathmatch != 4)
+		self.currentammo = self.ammo_rockets = self.ammo_rockets - 1;
+	
+	sound (self, CHAN_WEAPON, "weapons/grenade.wav", 1, ATTN_NORM);
+
+	msg_entity = self;
+	WriteByte (MSG_ONE, SVC_SMALLKICK);
+
+	newmis = spawn ();
+	newmis.voided=0;
+	newmis.owner = self;
+	newmis.movetype = MOVETYPE_BOUNCE;
+	newmis.solid = SOLID_BBOX;
+	newmis.classname = "grenade";
+		
+// set newmis speed     
+
+	makevectors (self.v_angle);
+
+	if (self.v_angle_x)
+		newmis.velocity = v_forward*600 + v_up * 200 + crandom()*v_right*10 + crandom()*v_up*10;
+	else
+	{
+		newmis.velocity = aim(self, 10000);
+		newmis.velocity = newmis.velocity * 600;
+		newmis.velocity_z = 200;
+	}
+
+	newmis.avelocity = '300 300 300';
+
+	newmis.angles = vectoangles(newmis.velocity);
+	
+	newmis.touch = GrenadeTouch;
+	
+// set newmis duration
+	if (deathmatch == 4)
+	{
+		newmis.nextthink = time + 2.5;		
+		self.attack_finished = time + 1.1;
+//		self.health = self.health - 1;
+		T_Damage (self, self, self.owner, 10 );
+	}
+	else
+		newmis.nextthink = time + 2.5;
+
+	newmis.think = GrenadeExplode;
+
+	setmodel (newmis, "progs/grenade.mdl");
+	setsize (newmis, '0 0 0', '0 0 0');             
+	setorigin (newmis, self.origin);
+};
+
+
+//=============================================================================
+
+void() spike_touch;
+void() superspike_touch;
+
+
+/*
+===============
+launch_spike
+
+Used for both the player and the ogre
+===============
+*/
+void(vector org, vector dir) launch_spike =
+{
+	newmis = spawn ();
+	newmis.voided=0;
+	newmis.owner = self;
+	newmis.movetype = MOVETYPE_FLYMISSILE;
+	newmis.solid = SOLID_BBOX;
+
+	newmis.angles = vectoangles(dir);
+	
+	newmis.touch = spike_touch;
+	newmis.classname = "spike";
+	newmis.think = SUB_Remove;
+	newmis.nextthink = time + 6;
+	setmodel (newmis, "progs/spike.mdl");
+	setsize (newmis, VEC_ORIGIN, VEC_ORIGIN);               
+	setorigin (newmis, org);
+
+	newmis.velocity = dir * 1000;
+};
+
+void() W_FireSuperSpikes =
+{
+	local vector    dir;
+	local entity    old;
+	
+	sound (self, CHAN_WEAPON, "weapons/spike2.wav", 1, ATTN_NORM);
+	self.attack_finished = time + 0.2;
+	if (deathmatch != 4) 
+		self.currentammo = self.ammo_nails = self.ammo_nails - 2;
+	dir = aim (self, 1000);
+	launch_spike (self.origin + '0 0 16', dir);
+	newmis.touch = superspike_touch;
+	setmodel (newmis, "progs/s_spike.mdl");
+	setsize (newmis, VEC_ORIGIN, VEC_ORIGIN);               
+	msg_entity = self;
+	WriteByte (MSG_ONE, SVC_SMALLKICK);
+};
+
+void(float ox) W_FireSpikes =
+{
+	local vector    dir;
+	local entity    old;
+	
+	makevectors (self.v_angle);
+	
+	if (self.ammo_nails >= 2 && self.weapon == IT_SUPER_NAILGUN)
+	{
+		W_FireSuperSpikes ();
+		return;
+	}
+
+	if (self.ammo_nails < 1)
+	{
+		self.weapon = W_BestWeapon ();
+		W_SetCurrentAmmo ();
+		return;
+	}
+
+	sound (self, CHAN_WEAPON, "weapons/rocket1i.wav", 1, ATTN_NORM);
+	self.attack_finished = time + 0.2;
+	if (deathmatch != 4)
+		self.currentammo = self.ammo_nails = self.ammo_nails - 1;
+	dir = aim (self, 1000);
+	launch_spike (self.origin + '0 0 16' + v_right*ox, dir);
+
+	msg_entity = self;
+	WriteByte (MSG_ONE, SVC_SMALLKICK);
+};
+
+
+
+.float hit_z;
+void() spike_touch =
+{
+local float rand;
+	if (other == self.owner)
+		return;
+
+	if (self.voided) {
+		return;
+	}
+	self.voided = 1;
+
+	if (other.solid == SOLID_TRIGGER)
+		return; // trigger field, do nothing
+
+	if (pointcontents(self.origin) == CONTENT_SKY)
+	{
+		remove(self);
+		return;
+	}
+	
+// hit something that bleeds
+	if (other.takedamage)
+	{
+		spawn_touchblood (9);
+		other.deathtype = "nail";
+		T_Damage (other, self, self.owner, 9);
+	}
+	else
+	{
+		WriteByte (MSG_MULTICAST, SVC_TEMPENTITY);
+		if (self.classname == "wizspike")
+			WriteByte (MSG_MULTICAST, TE_WIZSPIKE);
+		else if (self.classname == "knightspike")
+			WriteByte (MSG_MULTICAST, TE_KNIGHTSPIKE);
+		else
+			WriteByte (MSG_MULTICAST, TE_SPIKE);
+		WriteCoord (MSG_MULTICAST, self.origin_x);
+		WriteCoord (MSG_MULTICAST, self.origin_y);
+		WriteCoord (MSG_MULTICAST, self.origin_z);
+		multicast (self.origin, MULTICAST_PHS);
+	}
+
+	remove(self);
+
+};
+
+void() superspike_touch =
+{
+local float rand;
+	if (other == self.owner)
+		return;
+
+	if (self.voided) {
+		return;
+	}
+	self.voided = 1;
+
+
+	if (other.solid == SOLID_TRIGGER)
+		return; // trigger field, do nothing
+
+	if (pointcontents(self.origin) == CONTENT_SKY)
+	{
+		remove(self);
+		return;
+	}
+	
+// hit something that bleeds
+	if (other.takedamage)
+	{
+		spawn_touchblood (18);
+		other.deathtype = "supernail";
+		T_Damage (other, self, self.owner, 18);
+	}
+	else
+	{
+		WriteByte (MSG_MULTICAST, SVC_TEMPENTITY);
+		WriteByte (MSG_MULTICAST, TE_SUPERSPIKE);
+		WriteCoord (MSG_MULTICAST, self.origin_x);
+		WriteCoord (MSG_MULTICAST, self.origin_y);
+		WriteCoord (MSG_MULTICAST, self.origin_z);
+		multicast (self.origin, MULTICAST_PHS);
+	}
+
+	remove(self);
+
+};
+
+
+/*
+===============================================================================
+
+PLAYER WEAPON USE
+
+===============================================================================
+*/
+
+void() W_SetCurrentAmmo =
+{
+	player_run ();          // get out of any weapon firing states
+
+	self.items = self.items - ( self.items & (IT_SHELLS | IT_NAILS | IT_ROCKETS | IT_CELLS) );
+	
+	if (self.weapon == IT_AXE)
+	{
+		self.currentammo = 0;
+		self.weaponmodel = "progs/v_axe.mdl";
+		self.weaponframe = 0;
+	}
+	else if (self.weapon == IT_SHOTGUN)
+	{
+		self.currentammo = self.ammo_shells;
+		self.weaponmodel = "progs/v_shot.mdl";
+		self.weaponframe = 0;
+		self.items = self.items | IT_SHELLS;
+	}
+	else if (self.weapon == IT_SUPER_SHOTGUN)
+	{
+		self.currentammo = self.ammo_shells;
+		self.weaponmodel = "progs/v_shot2.mdl";
+		self.weaponframe = 0;
+		self.items = self.items | IT_SHELLS;
+	}
+	else if (self.weapon == IT_NAILGUN)
+	{
+		self.currentammo = self.ammo_nails;
+		self.weaponmodel = "progs/v_nail.mdl";
+		self.weaponframe = 0;
+		self.items = self.items | IT_NAILS;
+	}
+	else if (self.weapon == IT_SUPER_NAILGUN)
+	{
+		self.currentammo = self.ammo_nails;
+		self.weaponmodel = "progs/v_nail2.mdl";
+		self.weaponframe = 0;
+		self.items = self.items | IT_NAILS;
+	}
+	else if (self.weapon == IT_GRENADE_LAUNCHER)
+	{
+		self.currentammo = self.ammo_rockets;
+		self.weaponmodel = "progs/v_rock.mdl";
+		self.weaponframe = 0;
+		self.items = self.items | IT_ROCKETS;
+	}
+	else if (self.weapon == IT_ROCKET_LAUNCHER)
+	{
+		self.currentammo = self.ammo_rockets;
+		self.weaponmodel = "progs/v_rock2.mdl";
+		self.weaponframe = 0;
+		self.items = self.items | IT_ROCKETS;
+	}
+	else if (self.weapon == IT_LIGHTNING)
+	{
+		self.currentammo = self.ammo_cells;
+		self.weaponmodel = "progs/v_light.mdl";
+		self.weaponframe = 0;
+		self.items = self.items | IT_CELLS;
+	}
+	else
+	{
+		self.currentammo = 0;
+		self.weaponmodel = "";
+		self.weaponframe = 0;
+	}
+};
+
+float() W_BestWeapon =
+{
+	local   float   it;
+	
+	it = self.items;
+
+	if (self.waterlevel <= 1 && self.ammo_cells >= 1 && (it & IT_LIGHTNING) )
+		return IT_LIGHTNING;
+	else if(self.ammo_nails >= 2 && (it & IT_SUPER_NAILGUN) )
+		return IT_SUPER_NAILGUN;
+	else if(self.ammo_shells >= 2 && (it & IT_SUPER_SHOTGUN) )
+		return IT_SUPER_SHOTGUN;
+	else if(self.ammo_nails >= 1 && (it & IT_NAILGUN) )
+		return IT_NAILGUN;
+	else if(self.ammo_shells >= 1 && (it & IT_SHOTGUN)  )
+		return IT_SHOTGUN;
+		
+/*
+	if(self.ammo_rockets >= 1 && (it & IT_ROCKET_LAUNCHER) )
+		return IT_ROCKET_LAUNCHER;
+	else if(self.ammo_rockets >= 1 && (it & IT_GRENADE_LAUNCHER) )
+		return IT_GRENADE_LAUNCHER;
+
+*/
+
+	return IT_AXE;
+};
+
+float() W_CheckNoAmmo =
+{
+	if (self.currentammo > 0)
+		return TRUE;
+
+	if (self.weapon == IT_AXE)
+		return TRUE;
+	
+	self.weapon = W_BestWeapon ();
+
+	W_SetCurrentAmmo ();
+	
+// drop the weapon down
+	return FALSE;
+};
+
+/*
+============
+W_Attack
+
+An attack impulse can be triggered now
+============
+*/
+void()  player_axe1;
+void()  player_axeb1;
+void()  player_axec1;
+void()  player_axed1;
+void()  player_shot1;
+void()  player_nail1;
+void()  player_light1;
+void()  player_rocket1;
+
+void() W_Attack =
+{
+	local   float   r;
+
+	if (!W_CheckNoAmmo ())
+		return;
+
+	makevectors     (self.v_angle);                 // calculate forward angle for velocity
+	self.show_hostile = time + 1;   // wake monsters up
+
+	if (self.weapon == IT_AXE)
+	{
+		self.attack_finished = time + 0.5;
+		sound (self, CHAN_WEAPON, "weapons/ax1.wav", 1, ATTN_NORM);
+		r = random();
+		if (r < 0.25)
+			player_axe1 ();
+		else if (r<0.5)
+			player_axeb1 ();
+		else if (r<0.75)
+			player_axec1 ();
+		else
+			player_axed1 ();
+	}
+	else if (self.weapon == IT_SHOTGUN)
+	{
+		player_shot1 ();
+		self.attack_finished = time + 0.5;
+		W_FireShotgun ();
+	}
+	else if (self.weapon == IT_SUPER_SHOTGUN)
+	{
+		player_shot1 ();
+		self.attack_finished = time + 0.7;
+		W_FireSuperShotgun ();
+	}
+	else if (self.weapon == IT_NAILGUN)
+	{
+		player_nail1 ();
+	}
+	else if (self.weapon == IT_SUPER_NAILGUN)
+	{
+		player_nail1 ();
+	}
+	else if (self.weapon == IT_GRENADE_LAUNCHER)
+	{
+		player_rocket1();
+		self.attack_finished = time + 0.6;
+		W_FireGrenade();
+	}
+	else if (self.weapon == IT_ROCKET_LAUNCHER)
+	{
+		player_rocket1();
+		self.attack_finished = time + 0.8;
+		W_FireRocket();
+	}
+	else if (self.weapon == IT_LIGHTNING)
+	{
+		self.attack_finished = time + 0.1;
+		sound (self, CHAN_AUTO, "weapons/lstart.wav", 1, ATTN_NORM);
+		player_light1();
+	}
+};
+
+/*
+============
+W_ChangeWeapon
+
+============
+*/
+void() W_ChangeWeapon =
+{
+	local   float   it, am, fl;
+	
+	it = self.items;
+	am = 0;
+	
+	if (self.impulse == 1)
+	{
+		fl = IT_AXE;
+	}
+	else if (self.impulse == 2)
+	{
+		fl = IT_SHOTGUN;
+		if (self.ammo_shells < 1)
+			am = 1;
+	}
+	else if (self.impulse == 3)
+	{
+		fl = IT_SUPER_SHOTGUN;
+		if (self.ammo_shells < 2)
+			am = 1;
+	}               
+	else if (self.impulse == 4)
+	{
+		fl = IT_NAILGUN;
+		if (self.ammo_nails < 1)
+			am = 1;
+	}
+	else if (self.impulse == 5)
+	{
+		fl = IT_SUPER_NAILGUN;
+		if (self.ammo_nails < 2)
+			am = 1;
+	}
+	else if (self.impulse == 6)
+	{
+		fl = IT_GRENADE_LAUNCHER;
+		if (self.ammo_rockets < 1)
+			am = 1;
+	}
+	else if (self.impulse == 7)
+	{
+		fl = IT_ROCKET_LAUNCHER;
+		if (self.ammo_rockets < 1)
+			am = 1;
+	}
+	else if (self.impulse == 8)
+	{
+		fl = IT_LIGHTNING;
+		if (self.ammo_cells < 1)
+			am = 1;
+	}
+
+	self.impulse = 0;
+	
+	if (!(self.items & fl))
+	{       // don't have the weapon or the ammo
+		sprint (self, PRINT_HIGH, "no weapon.\n");
+		return;
+	}
+	
+	if (am)
+	{       // don't have the ammo
+		sprint (self, PRINT_HIGH, "not enough ammo.\n");
+		return;
+	}
+
+//
+// set weapon, set ammo
+//
+	self.weapon = fl;               
+	W_SetCurrentAmmo ();
+};
+
+/*
+============
+CheatCommand
+============
+*/
+void() CheatCommand =
+{
+//      if (deathmatch || coop)
+		return;
+
+	self.ammo_rockets = 100;
+	self.ammo_nails = 200;
+	self.ammo_shells = 100;
+	self.items = self.items | 
+		IT_AXE |
+		IT_SHOTGUN |
+		IT_SUPER_SHOTGUN |
+		IT_NAILGUN |
+		IT_SUPER_NAILGUN |
+		IT_GRENADE_LAUNCHER |
+		IT_ROCKET_LAUNCHER |
+		IT_KEY1 | IT_KEY2;
+
+	self.ammo_cells = 200;
+	self.items = self.items | IT_LIGHTNING;
+
+	self.weapon = IT_ROCKET_LAUNCHER;
+	self.impulse = 0;
+	W_SetCurrentAmmo ();
+};
+
+/*
+============
+CycleWeaponCommand
+
+Go to the next weapon with ammo
+============
+*/
+void() CycleWeaponCommand =
+{
+	local   float   it, am;
+	
+	it = self.items;
+	self.impulse = 0;
+
+	while (1)
+	{
+		am = 0;
+
+		if (self.weapon == IT_LIGHTNING)
+		{
+			self.weapon = IT_AXE;
+		}
+		else if (self.weapon == IT_AXE)
+		{
+			self.weapon = IT_SHOTGUN;
+			if (self.ammo_shells < 1)
+				am = 1;
+		}
+		else if (self.weapon == IT_SHOTGUN)
+		{
+			self.weapon = IT_SUPER_SHOTGUN;
+			if (self.ammo_shells < 2)
+				am = 1;
+		}               
+		else if (self.weapon == IT_SUPER_SHOTGUN)
+		{
+			self.weapon = IT_NAILGUN;
+			if (self.ammo_nails < 1)
+				am = 1;
+		}
+		else if (self.weapon == IT_NAILGUN)
+		{
+			self.weapon = IT_SUPER_NAILGUN;
+			if (self.ammo_nails < 2)
+				am = 1;
+		}
+		else if (self.weapon == IT_SUPER_NAILGUN)
+		{
+			self.weapon = IT_GRENADE_LAUNCHER;
+			if (self.ammo_rockets < 1)
+				am = 1;
+		}
+		else if (self.weapon == IT_GRENADE_LAUNCHER)
+		{
+			self.weapon = IT_ROCKET_LAUNCHER;
+			if (self.ammo_rockets < 1)
+				am = 1;
+		}
+		else if (self.weapon == IT_ROCKET_LAUNCHER)
+		{
+			self.weapon = IT_LIGHTNING;
+			if (self.ammo_cells < 1)
+				am = 1;
+		}
+	
+		if ( (self.items & self.weapon) && am == 0)
+		{
+			W_SetCurrentAmmo ();
+			return;
+		}
+	}
+
+};
+
+
+/*
+============
+CycleWeaponReverseCommand
+
+Go to the prev weapon with ammo
+============
+*/
+void() CycleWeaponReverseCommand =
+{
+	local   float   it, am;
+	
+	it = self.items;
+	self.impulse = 0;
+
+	while (1)
+	{
+		am = 0;
+
+		if (self.weapon == IT_LIGHTNING)
+		{
+			self.weapon = IT_ROCKET_LAUNCHER;
+			if (self.ammo_rockets < 1)
+				am = 1;
+		}
+		else if (self.weapon == IT_ROCKET_LAUNCHER)
+		{
+			self.weapon = IT_GRENADE_LAUNCHER;
+			if (self.ammo_rockets < 1)
+				am = 1;
+		}
+		else if (self.weapon == IT_GRENADE_LAUNCHER)
+		{
+			self.weapon = IT_SUPER_NAILGUN;
+			if (self.ammo_nails < 2)
+				am = 1;
+		}
+		else if (self.weapon == IT_SUPER_NAILGUN)
+		{
+			self.weapon = IT_NAILGUN;
+			if (self.ammo_nails < 1)
+				am = 1;
+		}
+		else if (self.weapon == IT_NAILGUN)
+		{
+			self.weapon = IT_SUPER_SHOTGUN;
+			if (self.ammo_shells < 2)
+				am = 1;
+		}               
+		else if (self.weapon == IT_SUPER_SHOTGUN)
+		{
+			self.weapon = IT_SHOTGUN;
+			if (self.ammo_shells < 1)
+				am = 1;
+		}
+		else if (self.weapon == IT_SHOTGUN)
+		{
+			self.weapon = IT_AXE;
+		}
+		else if (self.weapon == IT_AXE)
+		{
+			self.weapon = IT_LIGHTNING;
+			if (self.ammo_cells < 1)
+				am = 1;
+		}
+	
+		if ( (it & self.weapon) && am == 0)
+		{
+			W_SetCurrentAmmo ();
+			return;
+		}
+	}
+
+};
+
+
+/*
+============
+ServerflagsCommand
+
+Just for development
+============
+*/
+void() ServerflagsCommand =
+{
+	serverflags = serverflags * 2 + 1;
+};
+
+
+/*
+============
+ImpulseCommands
+
+============
+*/
+void() ImpulseCommands =
+{
+	if (self.impulse >= 1 && self.impulse <= 8)
+		W_ChangeWeapon ();
+
+	if (self.impulse == 9)
+		CheatCommand ();
+	if (self.impulse == 10)
+		CycleWeaponCommand ();
+	if (self.impulse == 11)
+		ServerflagsCommand ();
+	if (self.impulse == 12)
+		CycleWeaponReverseCommand ();
+
+	self.impulse = 0;
+};
+
+/*
+============
+W_WeaponFrame
+
+Called every frame so impulse events can be handled as well as possible
+============
+*/
+void() W_WeaponFrame =
+{
+	if (time < self.attack_finished)
+		return;
+
+	ImpulseCommands ();
+	
+// check for attack
+	if (self.button0)
+	{
+		SuperDamageSound ();
+		W_Attack ();
+	}
+};
+
+/*
+========
+SuperDamageSound
+
+Plays sound if needed
+========
+*/
+void() SuperDamageSound =
+{
+	if (self.super_damage_finished > time)
+	{
+		if (self.super_sound < time)
+		{
+			self.super_sound = time + 1;
+			sound (self, CHAN_BODY, "items/damage3.wav", 1, ATTN_NORM);
+		}
+	}
+	return;
+};
+
+
--- /dev/null
+++ b/QW/progs/world.qc
@@ -1,0 +1,406 @@
+
+void() InitBodyQue;
+
+
+void() main =
+{
+	dprint ("main function\n");
+	
+// these are just commands the the prog compiler to copy these files
+
+	precache_file ("progs.dat");
+	precache_file ("gfx.wad");
+	precache_file ("quake.rc");
+	precache_file ("default.cfg");
+
+	precache_file ("end1.bin");
+	precache_file2 ("end2.bin");
+
+	precache_file ("demo1.dem");
+	precache_file ("demo2.dem");
+	precache_file ("demo3.dem");
+
+//
+// these are all of the lumps from the cached.ls files
+//
+	precache_file ("gfx/palette.lmp");
+	precache_file ("gfx/colormap.lmp");
+
+	precache_file2 ("gfx/pop.lmp");
+
+	precache_file ("gfx/complete.lmp");
+	precache_file ("gfx/inter.lmp");
+
+	precache_file ("gfx/ranking.lmp");
+	precache_file ("gfx/vidmodes.lmp");
+	precache_file ("gfx/finale.lmp");
+	precache_file ("gfx/conback.lmp");
+	precache_file ("gfx/qplaque.lmp");
+
+	precache_file ("gfx/menudot1.lmp");
+	precache_file ("gfx/menudot2.lmp");
+	precache_file ("gfx/menudot3.lmp");
+	precache_file ("gfx/menudot4.lmp");
+	precache_file ("gfx/menudot5.lmp");
+	precache_file ("gfx/menudot6.lmp");
+
+	precache_file ("gfx/menuplyr.lmp");
+	precache_file ("gfx/bigbox.lmp");
+	precache_file ("gfx/dim_modm.lmp");
+	precache_file ("gfx/dim_drct.lmp");
+	precache_file ("gfx/dim_ipx.lmp");
+	precache_file ("gfx/dim_tcp.lmp");
+	precache_file ("gfx/dim_mult.lmp");
+	precache_file ("gfx/mainmenu.lmp");
+	
+	precache_file ("gfx/box_tl.lmp");
+	precache_file ("gfx/box_tm.lmp");
+	precache_file ("gfx/box_tr.lmp");
+	
+	precache_file ("gfx/box_ml.lmp");
+	precache_file ("gfx/box_mm.lmp");
+	precache_file ("gfx/box_mm2.lmp");
+	precache_file ("gfx/box_mr.lmp");
+	
+	precache_file ("gfx/box_bl.lmp");
+	precache_file ("gfx/box_bm.lmp");
+	precache_file ("gfx/box_br.lmp");
+	
+	precache_file ("gfx/sp_menu.lmp");
+	precache_file ("gfx/ttl_sgl.lmp");
+	precache_file ("gfx/ttl_main.lmp");
+	precache_file ("gfx/ttl_cstm.lmp");
+	
+	precache_file ("gfx/mp_menu.lmp");
+	
+	precache_file ("gfx/netmen1.lmp");
+	precache_file ("gfx/netmen2.lmp");
+	precache_file ("gfx/netmen3.lmp");
+	precache_file ("gfx/netmen4.lmp");
+	precache_file ("gfx/netmen5.lmp");
+	
+	precache_file ("gfx/sell.lmp");
+	
+	precache_file ("gfx/help0.lmp");
+	precache_file ("gfx/help1.lmp");
+	precache_file ("gfx/help2.lmp");
+	precache_file ("gfx/help3.lmp");
+	precache_file ("gfx/help4.lmp");
+	precache_file ("gfx/help5.lmp");
+
+	precache_file ("gfx/pause.lmp");
+	precache_file ("gfx/loading.lmp");
+
+	precache_file ("gfx/p_option.lmp");
+	precache_file ("gfx/p_load.lmp");
+	precache_file ("gfx/p_save.lmp");
+	precache_file ("gfx/p_multi.lmp");
+
+// sounds loaded by C code
+	precache_sound ("misc/menu1.wav");
+	precache_sound ("misc/menu2.wav");
+	precache_sound ("misc/menu3.wav");
+
+	precache_sound ("ambience/water1.wav");
+	precache_sound ("ambience/wind2.wav");
+
+// shareware
+	precache_file ("maps/start.bsp");
+
+	precache_file ("maps/e1m1.bsp");
+	precache_file ("maps/e1m2.bsp");
+	precache_file ("maps/e1m3.bsp");
+	precache_file ("maps/e1m4.bsp");
+	precache_file ("maps/e1m5.bsp");
+	precache_file ("maps/e1m6.bsp");
+	precache_file ("maps/e1m7.bsp");
+	precache_file ("maps/e1m8.bsp");
+
+// registered
+	precache_file2 ("gfx/pop.lmp");
+
+	precache_file2 ("maps/e2m1.bsp");
+	precache_file2 ("maps/e2m2.bsp");
+	precache_file2 ("maps/e2m3.bsp");
+	precache_file2 ("maps/e2m4.bsp");
+	precache_file2 ("maps/e2m5.bsp");
+	precache_file2 ("maps/e2m6.bsp");
+	precache_file2 ("maps/e2m7.bsp");
+
+	precache_file2 ("maps/e3m1.bsp");
+	precache_file2 ("maps/e3m2.bsp");
+	precache_file2 ("maps/e3m3.bsp");
+	precache_file2 ("maps/e3m4.bsp");
+	precache_file2 ("maps/e3m5.bsp");
+	precache_file2 ("maps/e3m6.bsp");
+	precache_file2 ("maps/e3m7.bsp");
+
+	precache_file2 ("maps/e4m1.bsp");
+	precache_file2 ("maps/e4m2.bsp");
+	precache_file2 ("maps/e4m3.bsp");
+	precache_file2 ("maps/e4m4.bsp");
+	precache_file2 ("maps/e4m5.bsp");
+	precache_file2 ("maps/e4m6.bsp");
+	precache_file2 ("maps/e4m7.bsp");
+	precache_file2 ("maps/e4m8.bsp");
+
+	precache_file2 ("maps/end.bsp");
+
+	precache_file2 ("maps/dm1.bsp");
+	precache_file2 ("maps/dm2.bsp");
+	precache_file2 ("maps/dm3.bsp");
+	precache_file2 ("maps/dm4.bsp");
+	precache_file2 ("maps/dm5.bsp");
+	precache_file2 ("maps/dm6.bsp");
+};
+
+
+entity  lastspawn;
+
+//=======================
+/*QUAKED worldspawn (0 0 0) ?
+Only used for the world entity.
+Set message to the level name.
+Set sounds to the cd track to play.
+
+World Types:
+0: medieval
+1: metal
+2: base
+*/
+//=======================
+void() worldspawn =
+{
+	lastspawn = world;
+	InitBodyQue ();
+
+// custom map attributes
+
+	if (self.model == "maps/e1m8.bsp")
+		cvar_set ("sv_gravity", "100");
+	else
+		cvar_set ("sv_gravity", "800");
+
+
+// the area based ambient sounds MUST be the first precache_sounds
+
+// player precaches     
+	W_Precache ();                  // get weapon precaches
+
+// sounds used from C physics code
+	precache_sound ("demon/dland2.wav");            // landing thud
+	precache_sound ("misc/h2ohit1.wav");            // landing splash
+
+// setup precaches allways needed
+	precache_sound ("items/itembk2.wav");           // item respawn sound
+	precache_sound ("player/plyrjmp8.wav");         // player jump
+	precache_sound ("player/land.wav");                     // player landing
+	precache_sound ("player/land2.wav");            // player hurt landing
+	precache_sound ("player/drown1.wav");           // drowning pain
+	precache_sound ("player/drown2.wav");           // drowning pain
+	precache_sound ("player/gasp1.wav");            // gasping for air
+	precache_sound ("player/gasp2.wav");            // taking breath
+	precache_sound ("player/h2odeath.wav");         // drowning death
+
+	precache_sound ("misc/talk.wav");                       // talk
+	precache_sound ("player/teledth1.wav");         // telefrag
+	precache_sound ("misc/r_tele1.wav");            // teleport sounds
+	precache_sound ("misc/r_tele2.wav");
+	precache_sound ("misc/r_tele3.wav");
+	precache_sound ("misc/r_tele4.wav");
+	precache_sound ("misc/r_tele5.wav");
+	precache_sound ("weapons/lock4.wav");           // ammo pick up
+	precache_sound ("weapons/pkup.wav");            // weapon up
+	precache_sound ("items/armor1.wav");            // armor up
+	precache_sound ("weapons/lhit.wav");            //lightning
+	precache_sound ("weapons/lstart.wav");          //lightning start
+	precache_sound ("items/damage3.wav");
+
+	precache_sound ("misc/power.wav");                      //lightning for boss
+
+// player gib sounds
+	precache_sound ("player/gib.wav");                      // player gib sound
+	precache_sound ("player/udeath.wav");           // player gib sound
+	precache_sound ("player/tornoff2.wav");         // gib sound
+
+// player pain sounds
+
+	precache_sound ("player/pain1.wav");
+	precache_sound ("player/pain2.wav");
+	precache_sound ("player/pain3.wav");
+	precache_sound ("player/pain4.wav");
+	precache_sound ("player/pain5.wav");
+	precache_sound ("player/pain6.wav");
+
+// player death sounds
+	precache_sound ("player/death1.wav");
+	precache_sound ("player/death2.wav");
+	precache_sound ("player/death3.wav");
+	precache_sound ("player/death4.wav");
+	precache_sound ("player/death5.wav");
+
+	precache_sound ("boss1/sight1.wav");
+
+// ax sounds    
+	precache_sound ("weapons/ax1.wav");                     // ax swoosh
+	precache_sound ("player/axhit1.wav");           // ax hit meat
+	precache_sound ("player/axhit2.wav");           // ax hit world
+
+	precache_sound ("player/h2ojump.wav");          // player jumping into water
+	precache_sound ("player/slimbrn2.wav");         // player enter slime
+	precache_sound ("player/inh2o.wav");            // player enter water
+	precache_sound ("player/inlava.wav");           // player enter lava
+	precache_sound ("misc/outwater.wav");           // leaving water sound
+
+	precache_sound ("player/lburn1.wav");           // lava burn
+	precache_sound ("player/lburn2.wav");           // lava burn
+
+	precache_sound ("misc/water1.wav");                     // swimming
+	precache_sound ("misc/water2.wav");                     // swimming
+
+// Invulnerability sounds
+	precache_sound ("items/protect.wav");
+	precache_sound ("items/protect2.wav");
+	precache_sound ("items/protect3.wav");
+
+
+	precache_model ("progs/player.mdl");
+	precache_model ("progs/eyes.mdl");
+	precache_model ("progs/h_player.mdl");
+	precache_model ("progs/gib1.mdl");
+	precache_model ("progs/gib2.mdl");
+	precache_model ("progs/gib3.mdl");
+
+	precache_model ("progs/s_bubble.spr");  // drowning bubbles
+	precache_model ("progs/s_explod.spr");  // sprite explosion
+
+	precache_model ("progs/v_axe.mdl");
+	precache_model ("progs/v_shot.mdl");
+	precache_model ("progs/v_nail.mdl");
+	precache_model ("progs/v_rock.mdl");
+	precache_model ("progs/v_shot2.mdl");
+	precache_model ("progs/v_nail2.mdl");
+	precache_model ("progs/v_rock2.mdl");
+
+	precache_model ("progs/bolt.mdl");              // for lightning gun
+	precache_model ("progs/bolt2.mdl");             // for lightning gun
+	precache_model ("progs/bolt3.mdl");             // for boss shock
+	precache_model ("progs/lavaball.mdl");  // for testing
+	
+	precache_model ("progs/missile.mdl");
+	precache_model ("progs/grenade.mdl");
+	precache_model ("progs/spike.mdl");
+	precache_model ("progs/s_spike.mdl");
+
+	precache_model ("progs/backpack.mdl");
+
+	precache_model ("progs/zom_gib.mdl");
+
+	precache_model ("progs/v_light.mdl");
+	
+
+//
+// Setup light animation tables. 'a' is total darkness, 'z' is maxbright.
+//
+
+	// 0 normal
+	lightstyle(0, "m");
+	
+	// 1 FLICKER (first variety)
+	lightstyle(1, "mmnmmommommnonmmonqnmmo");
+	
+	// 2 SLOW STRONG PULSE
+	lightstyle(2, "abcdefghijklmnopqrstuvwxyzyxwvutsrqponmlkjihgfedcba");
+	
+	// 3 CANDLE (first variety)
+	lightstyle(3, "mmmmmaaaaammmmmaaaaaabcdefgabcdefg");
+	
+	// 4 FAST STROBE
+	lightstyle(4, "mamamamamama");
+	
+	// 5 GENTLE PULSE 1
+	lightstyle(5,"jklmnopqrstuvwxyzyxwvutsrqponmlkj");
+	
+	// 6 FLICKER (second variety)
+	lightstyle(6, "nmonqnmomnmomomno");
+	
+	// 7 CANDLE (second variety)
+	lightstyle(7, "mmmaaaabcdefgmmmmaaaammmaamm");
+	
+	// 8 CANDLE (third variety)
+	lightstyle(8, "mmmaaammmaaammmabcdefaaaammmmabcdefmmmaaaa");
+	
+	// 9 SLOW STROBE (fourth variety)
+	lightstyle(9, "aaaaaaaazzzzzzzz");
+	
+	// 10 FLUORESCENT FLICKER
+	lightstyle(10, "mmamammmmammamamaaamammma");
+
+	// 11 SLOW PULSE NOT FADE TO BLACK
+	lightstyle(11, "abcdefghijklmnopqrrqponmlkjihgfedcba");
+	
+	// styles 32-62 are assigned by the light program for switchable lights
+
+	// 63 testing
+	lightstyle(63, "a");
+};
+
+void() StartFrame =
+{
+	timelimit = cvar("timelimit") * 60;
+	fraglimit = cvar("fraglimit");
+	teamplay = cvar("teamplay");
+	deathmatch = cvar("deathmatch");
+	
+	framecount = framecount + 1;
+};
+
+/*
+==============================================================================
+
+BODY QUE
+
+==============================================================================
+*/
+
+entity  bodyque_head;
+
+void() bodyque =
+{       // just here so spawn functions don't complain after the world
+	// creates bodyques
+};
+
+void() InitBodyQue =
+{
+	local entity    e;
+	
+	bodyque_head = spawn();
+	bodyque_head.classname = "bodyque";
+	bodyque_head.owner = spawn();
+	bodyque_head.owner.classname = "bodyque";
+	bodyque_head.owner.owner = spawn();
+	bodyque_head.owner.owner.classname = "bodyque";
+	bodyque_head.owner.owner.owner = spawn();
+	bodyque_head.owner.owner.owner.classname = "bodyque";
+	bodyque_head.owner.owner.owner.owner = bodyque_head;
+};
+
+
+// make a body que entry for the given ent so the ent can be
+// respawned elsewhere
+void(entity ent) CopyToBodyQue =
+{
+	bodyque_head.angles = ent.angles;
+	bodyque_head.model = ent.model;
+	bodyque_head.modelindex = ent.modelindex;
+	bodyque_head.frame = ent.frame;
+	bodyque_head.colormap = ent.colormap;
+	bodyque_head.movetype = ent.movetype;
+	bodyque_head.velocity = ent.velocity;
+	bodyque_head.flags = 0;
+	setorigin (bodyque_head, ent.origin);
+	setsize (bodyque_head, ent.mins, ent.maxs);
+	bodyque_head = bodyque_head.owner;
+};
+
+
binary files /dev/null b/QW/quake.gif differ
binary files /dev/null b/QW/quakeworld.bmp differ
--- /dev/null
+++ b/QW/qw.dsw
@@ -1,0 +1,68 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "QWFwd"=.\qwfwd\qwfwd.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "gas2masm"=.\gas2masm\gas2masm.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "qwcl"=.\client\qwcl.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+    Begin Project Dependency
+    Project_Dep_Name gas2masm
+    End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "qwsv"=.\server\qwsv.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
binary files /dev/null b/QW/qw.ncb differ
binary files /dev/null b/QW/qw.opt differ
--- /dev/null
+++ b/QW/qw2do.txt
@@ -1,0 +1,106 @@
+QW 2.3 2do
+
+- don't broadcast name changes unless cs_connected
+  fix up the name changes stuff.  Right now second changes aren't broadcast.  Make it count as floodprot (and
+  don't change if flood prot succeeds)
+- winquake bug, keys bound to +/- aliases don't work when console is down
+- spectator name changes don't broadcast
+- cl_crosshaircolor
+- add gl_cshiftpercent (ala glq098)
+x- restore 2.1 movement code, but use new gravity application from 2.2, friction is still 4
+  check the step near quad on e1m5
+  stairs on ctf4
+x- look over stuffbuf again, possible clean up?  extend stuffbuf to generic backbuffer for 
+  reliable data?  change blocks to WriteClientMSG(client, byte, estimiatedsize), which will
+  auto rotate buffers if needed?  Change all reliable writes to WriteClientReliable_TYPE()?
+  NO MORE OVERFLOWS
+x- delta compress usercmds (ala Q2?), reduces client to server bandwidth
+x- fix player drift in initialsnapposition
+x- localid works first shot, before server connection
+x- double size of eyes in gl
+x- new spectator camera.  cl_chasecam 1 now gives a 'through the eyes' camera.  This is broken in demo playback.
+
+
+
+- packet loss display for clients?
+
+- m_filter in linux qwcl?
+- some sort of fastforward on .qwds?  host_framerate?  "Press [ATTACK] to Fast Forward"?
+- don't draw crosshair while showing scores
+- skin of '.' is invalid (causes hang?)
+- fix it so that screenshots try to write to gamedir and if it doesn't
+  exist go to qw dir
+- profile qwsv and see if it can be made less cpu intensive
+- client up the checksum crap, replace random table
+- r_lightmap 1?
+
+x- clamp topcolor/bottomcolor (crashes glqwcl with high bogus values)
+x- work on pmodel/emodel stuff, gl probs?
+x- heapsize b0rked in win32 qwsv
+x- server challenge
+x- internal port number (like john did to Q2)
+x- add rerecord
+x- increase edicts to 1024
+x- check that -zone is used
+x- change EF_DIMLIGHT to EF_BLUE for Quad effect in QWQC
+x- rewrite the server player cmd to remove double touch
+x- exec frontend.cfg after execing config.cfg during gamedir change
+x- add percentage loss on r_netgraph
+x- add r_netgraph to gl version
+x- stuff cl_warncmd before and after execing gamedir configs on gamedir change
+x- check to see that high fps doesn't overflow network and increase ping
+x- add a localinfo to server (complements serverinfo).  Same as serverinfo,
+  but is local to the server and can only be accessed by the QC and the
+  console.  64K limit?
+  Save localinfo automatically during map changes.
+  sv_localfile specifics localinfo file name
+  saves in current gamedir
+  accessed as serverinfo, i.e. infokey(world, "blah")
+  localinfo overrides serverinfo
+x- should water leafs pass sounds (i.e., fully hearable in PHS)
+x- allow 'password none' and 'spectator_password none' to clear passwords
+x- remove "password" field from userinfo data upon connect
+x- average ping for the team on +showteamscores, low/avg/high
+x- check that prediction of other players clips against self
+  - early implementation works well, but causes movement jerk in close
+    quarters due to prediction problems.  try a few other things
+x- check that fixangle from the server is reliable (after teleporters)
+x- add new msg level, PRINT_SELF
+x- add kill-flood filters.  Possible maxlines/time value setting.
+x- add /ignore for llamas
+x- move sound effects to reliable data stream
+x- check directinput support on qwcl
+x- model rendering is slow in gl, see if we can speed it up
+x- colored lighting in GL version 
+  - extend "style" key for lights
+- check demo playback timing in an attempt to make it smoother
+x- think about storing the current push value in the demo
+x- colored lighting for powerups (blue for quad, red for 666, etc.)
+x- ability to set 'password none' or 'spectator_password none' on a server
+x- do we want to look at adding real string support to QC?
+x- spectator QC calls:  SpectatorConnect, SpectatorThink, SpectatorDisconnect
+x- change the lava effect when outside of map in spectator mode
+x- change autocam to fixed, not float
+- new art for console background/status bar?  release a new pak file?
+  qw/pak0.pak
+  <morbid> And just fresher, a little bit brighter graphics.
+- Change status bar?  some sort of heads up display
+  the tools "float" independantly on the bottom.
+- McTaggart's "fun water" effect.
+- Update QPlug to provide more QSpy interaction.
+- skin master server which QSpy talks to in order to get skins
+  client still retains the ability to d/l skins from current server, put
+  QSpy do a precheck before game launch.
+  Download of skins should probably be compressed
+- skins should expire both on the client and on the skin master.
+  have qwcl touch (change modify date) on a skin every time its loaded
+  QSpy can then just delete skins more than a month or so old
+- id will host the skin master
+x- check out ph00k's comments about jumping
+x- change hunk_alloc error msgs, to say "16384" instead of "1600"?
+x- remove console scaling in GL version
+- Dis would like to continue work on the progs (QC)
+
+191, g_light.mdl, 0x0171b2c8
+
+
\ No newline at end of file
--- /dev/null
+++ b/QW/qwchangelog.txt
@@ -1,0 +1,243 @@
+
+2.1
+release build
+
+2.02
+client
+- fixed prediction bug in spectator/camera view, camera will no longer
+  try to view under plats and stuff
+- new crosshair, enabled with "crosshair 2"
+
+server
+- another security hole
+
+2.01
+server
+- added SpectatorConnect, SpectatorThink and SpectatorDisconnect Quake-C
+  functions.  They are empty shells for now (a example of moving spectators
+  from point to point is included with impulse 1) but can be used in lots
+  of ways.
+- fixed the crash bug with spectators
+- changed the death msgs in the Quake-C to fix the old bug of incorrect msgs
+  when your weapon changed.  Minor things like if two guys with pentagrams
+  telefrag, they both die (happens in deathmatch 4).  Thanks to Nolan 'Radix'
+  Pflug <nolan@fyi.net> for diffs of the progs changes to get this worked out.
+- fixed the mipmapping color errors in the GL version
+
+client
+
+
+1.82
+
+server
+- default floodprot, 4 lines in 8 secs, wait for 10 on activation
+- sv_friction defaults to 6 now (server op can change it to 4 if they want)
+
+client
+- put support back in for -zone option
+- added rerecord <filename> to cause a reconnect with demo recording on the
+  same server
+
+1.81
+
+server
+- Added floodprots to the server
+- Using localinfo, you can now configure a series of maps to run without
+  editing the quake-c.  usage:  localinfo <from-map> <to-map>.  For example,
+  to run a server that loops through e1m2, dm2, dm4 and dm6, try this:
+        localinfo e1m2 dm2
+        localinfo dm2 dm4
+        localinfo dm4 dm6
+        localinfo dm6 e1m2
+  Note that the last one should loop back to the first, otherwise normal
+  level changing applies.  Put the localinfo commands in the server.cfg
+
+client
+- new lightmap code (requires new opengl32.dll miniport)
+- Added EF_BLUE and EF_RED for new GL light bubbles
+- Made rocket trails fade out in GL
+- Added NOSKINS 2 to use but not download skins
+- Using TexSubImage2D to upload partial lightmaps (GL)
+- Precalculate light bubble
+- Translucent console (GL)
+
+1.80
+
+server
+- added localinfo.  32k of key=value storage.  Values are stored with the
+  localinfo console command on the server, i.e.
+      localinfo e1m1 e1m2
+  localinfo is persistant from the life of the server (between maps)
+  progs can access localinfo using infokey(world, "key") and set it using
+      localcmd("localinfo ");
+      localcmd(key);
+	  localcmd(" ");
+	  localcmd(value);
+	  localcmd("\n");
+  values with spaces should be quoted
+  If the same key exists in serverinfo and localinfo, serverinfo will override
+  localinfo is not visible 'outside' the server
+- protocol has changed, old clients will no longer work.  changable move
+  vars such as gravity, maxspeed, etc. are supported again
+- full server controlled localized client maxspeed and gravity is in
+  Create to new fields in the QC, .float gravity and .float maxspeed.  .maxspeed
+  defaults to sv_maxspeed (320), .gravity defaults to 1.0 (full gravity).
+  Change them at will in the QC, but don't change them too often as every change
+  is noted and the clients are updated with the change so that their prediction
+  works correctly.  The per-client maxspeed should be very handy for the TF
+  guys.
+- fixed 'download ./server.cfg' security bug.
+
+client
+- 8bit 3DFX texture support.  reduces texture thrashing due to way less 
+  texture memory used.
+- will work on pre 1.8 servers, but can cause minor movement errors due to
+  differences in movement prediction
+- support for server controlled maxspeed and gravity multiplier.
+
+1.69
+
+server
+- fixed up ramp movement (on ground stuff)
+
+1.68
+
+client
+- fixed resized console in gl version, had some dead space, so put a mini
+  frag list on the bottom
+- changed lightning in gl version so in default of gl_flashblend 1 you don't
+  see you own light, so having the quad doesn't obscure your vision
+
+server
+- hopefully finally fixed the acceleration up ramps
+
+1.67
+
+client
+- added low/avg/high ping values to the showteamscores so an
+  average team ping is calculated
+- fixed dynamic lightning of alias models in gl version (players and what
+  not were not lit up by dynamic lights)
+
+server
+- removed password from userinfo after player connect so that other
+  players and spectators can't use the 'user' command to see the
+  passwd
+- setting password or spectator_password to 'none' is the same as
+  clearing it
+
+
+1.66
+
+client
+- Added startup graphic banner
+- exiting the world in spectator mode is no longer lava red, but
+  slime green.
+
+server
+- change player move physics to support ramp accel, there was a bug in
+  stair stepping that prevented proper movement.  With this bug, you can't
+  jump into the RL room on dm6, or hit the secret light on e4m1.
+- added support for 'namefun' (high bit characters).  On by default, server
+  operators can turn it off with sv_highchars 0
+
+1.65
+
+client
+- fixed the z-angle on entities (for example, the flag was rotated wrong)
+  in GL version.
+- worked on the spectator camera, going to change it from a free float
+  to a locked camera that tracks
+- add other player clip hulls to player prediction and local prediction
+  this removes the problem of walking through other players and makes
+  close combat a lot nicer.
+1.64
+
+server
+- fixed bug in serverinfo strings (memory overwrite and length problem)
+- added new allow_download vars:
+	allow_download_skins, allow_download_models,
+	allow_download_sounds, allow_download_maps
+- map files are permitted to be downloaded if they aren't in a pak file
+  (unless allow_download or allow_download_maps isn't set)
+- fixed annoying NET_GetPacket: Connection Refused msgs
+- new command, sv_gamedir, which sets the visible gamedir to clients.  this
+  allows servers to have a different physical game directories, handing for
+  machines with multiple servers that don't support symbolic links.  for
+  example:
+  		gamedir ctf4.1
+		sv_gamedir ctf
+  causes qwsv to use the physical directory of 'ctf4.1', but report the
+  directory to clients (players) as 'ctf' for their files.
+- fixed annoying water jump bug where you would immedately hop back out of 
+  water just after you jumped in
+- added a few client to server commands for autocamera support
+- fixed air velocity movement so that it is like regular Quake, 
+  players have more control over their air movement and can cut
+  velocity as needed just like in Quake.  This gives more control
+  to the player and rewards skill.
+- spectators no longer can send or receive say_team msgs (possible
+  cheating could happen)
+- adding new server cvar, sv_spectalk (defaults to 1, or on) that controls
+  whether spectators can talk to players.  If disabled, spectators can
+  only talk to each other
+- stopped reporting spectators as players when front-ends request info
+- fixed up air movement that broke a bit in 1.61
+- fixed bug that disallowed 9's in ip address for filtering
+- spectators can now send say_team msgs, but only to other spectators
+- no duplicate names allowed now (will rename people who do it)
+- a client can not name themselves console
+
+client
+- adjust console input a bit to allow room for download percent bar (moved up
+	six pixels)
+- added download percentage bar.  Displays filename and a bar indicating
+  visual completeness of download and a percentage.  Overwrites
+  any text at the bottom
+- if a model file isn't found (couldn't be download) a msg is displayed
+  telling the user they may need to download or purchase an addon pak
+- added +showteamscores.  In team games, the intermission displays team
+  totals, unless you hit tab to display frag scores
+  bind a key to +showteamscores will give you the team score display
+- added client side demo support and playback [wow, one line for three days
+  of work. :) ]
+  usage:  record <file> <server>
+  Autodownload is disabled when recording.
+- added auto-tracking camera for spectator mode.  It's mostly a novelty, but
+  its fun.
+- made all skin downloads go into QW
+- allowed Ctrl-V (paste) at console
+- fixed water jump bug where you hop immediately back out in narrow entrances
+- added copyright dialog on exit (press y to quit) with credits and version
+  number
+- new cvar, cl_warncmd, defaults to zero and disables the 'unknown command'
+  msg.  qwcl stuffs 'cl_warncmd 1' to itself after quake.rc loads. This gets
+  rid of unknown command messages (like unknown command 'startdemos') from the
+  default exec files, as well as hiding "execing" messages.
+- new command, windows, which will pop a user in fullscreen mode back to Windows
+  (obviously not in Linux versions)
+- add cl_hightrack cvar for spectator mode, causes it to always
+  select camera view on player with the highest frags
+- turned off bobbing in spectator mode
+- added text to the "single player" and "multiplayer" menu options
+- now execs the config.cfg in a gamedir upon receiving a new gamedir from
+  the server (saves the current config into the current gamedir before
+  switching to the new one)
+- reconnect command will now reconnect to the server it's is currently connected
+  to, or last one it was connected to.
+- fixed it so entering 'record blah server' while connected disconnects before
+  starting recording
+- uh, added gl support (love these one liners for two days of work)
+- fixed scoreboard while dead in gl version
+- made it so players are never completely black in the gl version
+- changed some console load up msgs in gl
+- fixed it so exec files without a trailing new line still work
+- changed effects in gl to not be as striking (hard to see)
+- fixed it so a 'glquake' dir is created in other gamedirs for model
+  meshes in gl version
+- fixed tolerance on corrupt skin files
+- fov setting implemented in gl version
+- fixed 'skins' command in gl version
+
+
+                                                               
--- /dev/null
+++ b/QW/qwcl.spec.sh
@@ -1,0 +1,62 @@
+#!/bin/sh
+# Generate qwcl.spec
+# $1 is version
+# $2 is release
+# $3 is install dir (assumed to be in /var/tmp)
+cat <<EOF
+%define name qwcl
+%define version ${1}
+%define release ${2}
+%define builddir \$RPM_BUILD_DIR/%{name}-%{version}
+Name:		%{name}
+Version:	%{version}
+Release:	%{release}
+Vendor:		id Software
+Packager:	Dave "Zoid" Kirsch <zoid@idsoftware.com>
+URL:		http://www.idsoftware.com/
+Source:		qwcl-%{version}.tar.gz
+Group:		Games
+Copyright:	Restricted
+Icon:		quake.gif
+BuildRoot:	/var/tmp/%{name}-%{version}
+Summary:	QuakeWorld Client
+
+%description
+QuakeWorld is an Internet multi-player specific version of Quake. While the 
+original version of Quake can be played over the Internet, many users modem 
+users - the majority of players, had less than satisfactory play. Symptoms 
+like excessive lag - actions actually happening much later than you did them; 
+packet loss - the game would freeze and resume several seconds later; and 
+various other difficulties plagued users.
+
+After realizing how many people played Quake on the internet, and how many 
+wanted to, but couldn't due to the play being unsatisfactory, John Carmack 
+of id Software decided to create a version of Quake that was optimized for 
+the average modem Internet player. This Internet specific version does only 
+one thing, play deathmatch games over a TCP/IP network such as the Internet. 
+It has no support for solo play, and you can't do anything with out connecting 
+to a special server.
+
+Now in it's second generation, QuakeWorld has been sculpted by countless 
+hours of user feedback and tweaking to provide the best multi-player 
+experience that can be had from the equipment the average gamer will have. 
+All that is required to use QuakeWorld is registered Quake.
+
+%install
+
+%files
+%attr(644,root,root) ${3}/README.qwcl
+%attr(4755,root,root) ${3}/qwcl
+%attr(4755,root,root) ${3}/glqwcl
+%attr(4755,root,root) ${3}/glqwcl.glx
+%attr(755,root,root) ${3}/glqwcl.3dfxgl
+%attr(755,root,root) ${3}/lib3dfxgl.so
+%attr(755,root,root) ${3}/libMesaGL.so.2.6
+%attr(755,root,root) ${3}/libMesaGL.so.2
+%attr(755,root,root) ${3}/libMesaGL.so
+%attr(755,root,root) ${3}/libGL.so
+%attr(755,root,root) ${3}/qwcl.x11
+%attr(755,root,root) ${3}/qw/skins/fixskins.sh
+EOF
+
+
--- /dev/null
+++ b/QW/qwcl.x11.spec.sh
@@ -1,0 +1,42 @@
+#!/bin/sh
+# Generate qwcl.x11.spec
+# $1 is version
+# $2 is release
+# $3 is install dir (assumed to be in /var/tmp)
+cat <<EOF
+%define name qwcl.x11
+%define version ${1}
+%define release ${2}
+%define builddir \$RPM_BUILD_DIR/%{name}-%{version}
+Name:		%{name}
+Version:	%{version}
+Release:	%{release}
+Vendor:		id Software
+Packager:	Dave "Zoid" Kirsch <zoid@idsoftware.com>
+URL:		http://www.idsoftware.com/
+Source:		qwcl.x11-%{version}.tar.gz
+Group:		Games
+Copyright:	Restricted
+Icon:		quake.gif
+BuildRoot:	/var/tmp/%{name}-%{version}
+Summary:	X11 QuakeWorld Client
+
+%description
+"Quake is the biggest, baddest, and bloodiest 3-D action game ever 
+conceived" - PC GAMER
+
+"The most important PC game ever" - PC ZONE
+
+""Quake": Bloody Amazing" - USA TODAY
+
+"The Vanguard of a terrifying new level of immersive interactivity" - 
+COMPUTER GAMING WORLD
+
+%install
+
+%files
+%attr(644,root,root) ${3}/readme.qwcl.x11
+%attr(755,root,root) ${3}/qwcl.x11
+EOF
+
+
--- /dev/null
+++ b/QW/qwfwd/misc.c
@@ -1,0 +1,452 @@
+#include "master.h"
+
+int		com_argc;
+char	**com_argv;
+
+/*
+================
+COM_CheckParm
+
+Returns the position (1 to argc-1) in the program's argument list
+where the given parameter apears, or 0 if not present
+================
+*/
+int COM_CheckParm (char *parm)
+{
+	int		i;
+	
+	for (i=1 ; i<com_argc ; i++)
+	{
+		if (!com_argv[i])
+			continue;		// NEXTSTEP sometimes clears appkit vars.
+		if (!strcmp (parm,com_argv[i]))
+			return i;
+	}
+		
+	return 0;
+}
+
+char	*AdrToString (netadr_t a)
+{
+	static	char	s[64];
+	
+	sprintf (s, "%i.%i.%i.%i:%i",
+		a.sin_addr.S_un.S_un_b.s_b1,
+		a.sin_addr.S_un.S_un_b.s_b2,
+		a.sin_addr.S_un.S_un_b.s_b3,
+		a.sin_addr.S_un.S_un_b.s_b4,
+		ntohs(a.sin_port));
+
+	return s;
+}
+
+netadr_t	StringToAdr (char *s)
+{
+	netadr_t		a;
+	int			b1, b2, b3, b4, p;
+	
+	b1 = b2 = b3 = b4 = p = 0;
+	sscanf (s, "%i.%i.%i.%i:%i", &b1, &b2, &b3, &b4, &p);
+	
+	a.sin_addr.S_un.S_un_b.s_b1 = b1;
+	a.sin_addr.S_un.S_un_b.s_b2 = b2;
+	a.sin_addr.S_un.S_un_b.s_b3 = b3;
+	a.sin_addr.S_un.S_un_b.s_b4 = b4;
+	a.sin_port = ntohs(p);
+
+	return a;
+}
+
+qboolean	CompareAdr (netadr_t a, netadr_t b)
+{
+	if (a.sin_addr.s_addr == b.sin_addr.s_addr 
+	&& a.sin_port == b.sin_port)
+		return true;
+	return false;
+}
+
+
+void	mprintf (char *msg, ...)
+{
+	va_list	argptr;
+	
+	va_start (argptr, msg);
+	vprintf (msg, argptr);
+	vfprintf (logfile, msg, argptr);
+	va_end (argptr);
+		
+}
+
+int	msg_readcount;
+char	*MSG_ReadString (void)
+{
+	char	*start;
+	
+	start = packet_data + msg_readcount;
+	
+	for ( ; msg_readcount < packet_length ; msg_readcount++)
+		if (packet_data[msg_readcount] == '\n'
+		|| packet_data[msg_readcount] == 0)
+			break;
+	
+	packet_data[msg_readcount] = 0;
+	msg_readcount++;
+	
+	return start;
+}
+
+/*
+=====================================================================
+
+  COMMAND LINES
+
+=====================================================================
+*/
+
+#define	MAX_ARGS	32
+#define	MAX_ARG_LENGTH	1024
+int		cmd_argc;
+char	cmd_argv[MAX_ARGS][MAX_ARG_LENGTH];
+
+char		com_token[1024];
+/*
+==============
+COM_Parse
+
+Parse a token out of a string
+==============
+*/
+char *COM_Parse (char *data)
+{
+	int		c;
+	int		len;
+	
+	len = 0;
+	com_token[0] = 0;
+	
+	if (!data)
+		return NULL;
+		
+// skip whitespace
+skipwhite:
+	while ( (c = *data) <= ' ')
+	{
+		if (c == 0)
+			return NULL;			// end of file;
+		data++;
+	}
+	
+// skip // comments
+	if (c=='/' && data[1] == '/')
+	{
+		while (*data && *data != '\n')
+			data++;
+		goto skipwhite;
+	}
+	
+
+// handle quoted strings specially
+	if (c == '\"')
+	{
+		data++;
+		while (1)
+		{
+			c = *data++;
+			if (c=='\"' || !c)
+			{
+				com_token[len] = 0;
+				return data;
+			}
+			com_token[len] = c;
+			len++;
+		}
+	}
+
+// parse a regular word
+	do
+	{
+		com_token[len] = c;
+		data++;
+		len++;
+		c = *data;
+	} while (c>32);
+	
+	com_token[len] = 0;
+	return data;
+}
+
+/*
+============
+Cmd_Argc
+============
+*/
+int		Cmd_Argc (void)
+{
+	return cmd_argc;
+}
+
+/*
+============
+Cmd_Argv
+============
+*/
+char	*Cmd_Argv (int arg)
+{
+	if ( (unsigned)arg >= cmd_argc )
+		return "";
+	return cmd_argv[arg];	
+}
+
+/*
+============
+Cmd_TokenizeString
+
+Parses the given string into command line tokens.
+============
+*/
+void Cmd_TokenizeString (char *text)
+{	
+	cmd_argc = 0;
+	
+	while (1)
+	{
+// skip whitespace up to a /n
+		while (*text && *text <= ' ')
+		{
+			text++;
+		}
+		
+		if (!*text)
+			return;
+	
+		text = COM_Parse (text);
+		if (!text)
+			return;
+
+		if (cmd_argc < MAX_ARGS)
+		{
+			strcpy (cmd_argv[cmd_argc], com_token);
+			cmd_argc++;
+		}
+	}
+	
+}
+
+
+/*
+=====================================================================
+
+  INFO STRINGS
+
+=====================================================================
+*/
+
+/*
+===============
+Info_ValueForKey
+
+Searches the string (userinfo or masterinfo) for the given
+key and returns the associated value, or an empty string.
+===============
+*/
+char *Info_ValueForKey (char *s, char *key)
+{
+	char	pkey[512];
+	static	char value[512];
+	char	*o;
+	
+	if (*s == '\\')
+		s++;
+	while (1)
+	{
+		o = pkey;
+		while (*s != '\\')
+		{
+			if (!*s)
+				return "";
+			*o++ = *s++;
+		}
+		*o = 0;
+		s++;
+
+		o = value;
+		while (*s != '\\' && *s)
+		{
+			if (!*s)
+				return "";
+			*o++ = *s++;
+		}
+		*o = 0;
+
+		if (!strcmp (key, pkey) )
+			return value;
+
+		if (!*s)
+			return "";
+		s++;
+	}
+}
+
+void Info_RemoveKey (char *s, char *key)
+{
+	char	*start;
+	char	pkey[512];
+	char	value[512];
+	char	*o;
+
+	if (strstr (key, "\\"))
+	{
+		printf ("Can't use a key with a \\\n");
+		return;
+	}
+
+	while (1)
+	{
+		start = s;
+		if (*s == '\\')
+			s++;
+		o = pkey;
+		while (*s != '\\')
+		{
+			if (!*s)
+				return;
+			*o++ = *s++;
+		}
+		*o = 0;
+		s++;
+
+		o = value;
+		while (*s != '\\' && *s)
+		{
+			if (!*s)
+				return;
+			*o++ = *s++;
+		}
+		*o = 0;
+
+		if (!strcmp (key, pkey) )
+		{
+			strcpy (start, s);	// remove this part
+			return;
+		}
+
+		if (!*s)
+			return;
+	}
+
+}
+
+void Info_RemovePrefixedKeys (char *start, char prefix)
+{
+	char	*s;
+	char	pkey[512];
+	char	value[512];
+	char	*o;
+
+	s = start;

+	while (1)
+	{
+		if (*s == '\\')
+			s++;
+		o = pkey;
+		while (*s != '\\')
+		{
+			if (!*s)
+				return;
+			*o++ = *s++;
+		}
+		*o = 0;
+		s++;
+
+		o = value;
+		while (*s != '\\' && *s)
+		{
+			if (!*s)
+				return;
+			*o++ = *s++;
+		}
+		*o = 0;
+
+		if (pkey[0] == prefix)
+		{
+			Info_RemoveKey (start, pkey);
+			s = start;
+		}
+
+		if (!*s)
+			return;
+	}
+
+}
+
+void Info_SetValueForKey (char *s, char *key, char *value)
+{
+	char	new[512];
+
+	if (strstr (key, "\\") || strstr (value, "\\") )
+	{
+		printf ("Can't use keys or values with a \\\n");
+		return;
+	}
+	if (strstr (key, "\"") || strstr (value, "\"") )
+	{
+		printf ("Can't use keys or values with a \\\n");
+		return;
+	}
+
+	Info_RemoveKey (s, key);
+	if (!value || !strlen(value))
+		return;
+
+	sprintf (new, "\\%s\\%s", key, value);
+
+	if (strlen(new) + strlen(s) > MAX_INFO_STRING)
+	{
+		printf ("Info string length exceeded\n");
+		return;
+	}
+	strcat (s, new);
+}
+
+void Info_Print (char *s)
+{
+	char	key[512];
+	char	value[512];
+	char	*o;
+	int		l;
+
+	if (*s == '\\')
+		s++;
+	while (*s)
+	{
+		o = key;
+		while (*s && *s != '\\')
+			*o++ = *s++;
+
+		l = o - key;
+		if (l < 20)
+		{
+			memset (o, ' ', 20-l);
+			key[20] = 0;
+		}
+		else
+			*o = 0;
+		printf ("%s", key);
+
+		if (!*s)
+		{
+			printf ("MISSING VALUE\n");
+			return;
+		}
+
+		o = value;
+		s++;
+		while (*s && *s != '\\')
+			*o++ = *s++;
+		*o = 0;
+
+		if (*s)
+			s++;
+		printf ("%s\n", value);
+	}
+}
--- /dev/null
+++ b/QW/qwfwd/qwfwd.001
@@ -1,0 +1,89 @@
+# Microsoft Developer Studio Project File - Name="QWFwd" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 5.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=QWFwd - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "QWFwd.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "QWFwd.mak" CFG="QWFwd - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "QWFwd - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "QWFwd - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE 
+
+# Begin Project
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "QWFwd - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+
+!ELSEIF  "$(CFG)" == "QWFwd - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+
+!ENDIF 
+
+# Begin Target
+
+# Name "QWFwd - Win32 Release"
+# Name "QWFwd - Win32 Debug"
+# Begin Source File
+
+SOURCE=.\qwfwd.c
+# End Source File
+# End Target
+# End Project
--- /dev/null
+++ b/QW/qwfwd/qwfwd.c
@@ -1,0 +1,269 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+
+
+/*
+ * udpred - a inetd launched udp port redirector
+ *
+ * Version:	@(#)udpred.c 0.01   01/15/97
+ *
+ * Author:	Chris Faherty <chrisf@america.com>
+ *
+ * syntax:
+ *
+ * udpred toip toport
+ *
+ * sample inetd.conf entry:
+ *
+ * 7000	dgram	udp	wait	root	/usr/sbin/tcpd	/usr/sbin/udpred 192.168.100.16 7000
+ *
+ *
+ *	This program is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU General Public License
+ *	as published by the Free Software Foundation; either version
+ *	2 of the License, or (at your option) any later version.
+ *
+ */
+#include <stdio.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <time.h>
+
+#ifdef _WIN32
+#include <winsock.h>
+#else
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <sys/wait.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <unistd.h>
+#include <syslog.h>
+
+#endif
+
+int host_port; // port we are listening on
+
+typedef struct peer {
+	time_t last;
+	struct sockaddr_in sin;
+	struct sockaddr_in dest;
+	int s; // connected socket to remote
+	struct peer *next;
+} peer_t;
+
+peer_t *peers;
+
+/*
+====================
+NET_Init
+====================
+*/
+void NET_Init (void)
+{
+#ifdef _WIN32
+	static WSADATA          winsockdata;
+//    WORD    wVersionRequested;
+    int             r;
+
+//    wVersionRequested = MAKEWORD(1, 1);
+
+    r = WSAStartup (MAKEWORD(2, 1), &winsockdata);
+
+    if (r) {
+		fprintf(stderr, "Winsock initialization failed.");
+		exit(1);
+	}
+
+    printf("Winsock Initialized\n");
+#endif
+}
+
+
+
+int connectsock(char *host, char *service, char *protocol)
+{
+	struct hostent *phe;
+	struct servent *pse;
+	struct protoent *ppe;
+	struct sockaddr_in sin;
+	int s, type;
+
+	memset(&sin, 0, sizeof(sin));
+	sin.sin_family = AF_INET;
+
+/* Map service name to port number */
+	if(pse = getservbyname(service, protocol))
+		sin.sin_port = pse->s_port;
+	else if((sin.sin_port = htons((u_short)atoi(service))) == 0)
+	{
+		fprintf(stderr, "udpred: can't get \"%s\" service entry\n", service);
+		exit(2);
+	}
+
+/* Map host name to IP address, allowing for dotted decimal */
+	if(phe = gethostbyname(host))
+		memcpy((char *)&sin.sin_addr, phe->h_addr, phe->h_length);
+	else if((sin.sin_addr.s_addr = inet_addr(host)) == INADDR_NONE)
+	{
+		fprintf(stderr, "udpred: can't get \"%s\" host entry\n", host);
+		exit(2);
+	}
+
+/* Map protocol name to protocol number */
+	if((ppe = getprotobyname(protocol)) == 0)
+	{
+		fprintf(stderr, "udpred: can't get \"%s\" protocol entry\n", protocol);
+		exit(2);
+	}
+
+/* Use protocol to choose a socket type */
+	if(strcmp(protocol, "udp") == 0)
+		type = SOCK_DGRAM;
+	else
+		type = SOCK_STREAM;
+
+/* Allocate a socket */
+	s = socket(PF_INET, type, ppe->p_proto);
+	if(s < 0)
+	{
+		fprintf(stderr, "udpred: can't create socket: %s\n", sys_errlist[errno]);
+		exit(2);
+	}
+
+/* Connect the socket */
+	if(connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0)
+	{
+		fprintf(stderr, "udpred: can't connect to %s.%s: %s\n", host, service, sys_errlist[errno]);
+		exit(2);
+	}
+	return s;
+}
+
+int main(int argc, char *argv[])
+{
+	fd_set rfds;
+	struct timeval tv;
+	int retval;
+	int i1;
+	char buffer[4095];
+	struct sockaddr_in fsin;
+	int alen;
+	peer_t *p;
+	int s;
+	struct sockaddr_in	address;
+
+	if (argc < 3) {
+		printf("Usage:  %s <port> <remote server> <remote server port>\n", argv[0]);
+		return 1;
+	}
+
+	NET_Init();
+
+	if ((s = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) {
+		perror("socket");
+		return 1;
+	}
+
+	address.sin_family = AF_INET;
+	address.sin_addr.s_addr = INADDR_ANY;
+	address.sin_port = htons((unsigned short)atoi(argv[1]));
+	if (bind (s, (void *)&address, sizeof(address)) == -1)
+		perror("bind");
+
+	while(1)
+	{
+		FD_ZERO(&rfds);
+		FD_SET(s, &rfds);
+		i1 = s;
+		for (p = peers; p; p = p->next) {
+			FD_SET(p->s, &rfds);
+			if (p->s >= i1)
+				i1 = p->s + 1;
+		}
+		/* Wait up to two minutes. */
+		tv.tv_sec = 2;
+		tv.tv_usec = 0;
+		retval = select(i1, &rfds, (fd_set *)0, (fd_set *)0, &tv);
+		if(retval > 0)
+		{
+			if(FD_ISSET(s, &rfds))
+			{
+				alen = sizeof(fsin);
+				i1 = recvfrom(s, buffer, 4096, 0, (struct sockaddr *) &fsin, &alen);
+				if(i1 > 0) {
+					for (p = peers; p; p = p->next)
+						if (memcmp(&p->sin.sin_addr, &fsin.sin_addr, sizeof(p->sin.sin_addr)) == 0 &&
+							memcmp(&p->sin.sin_port, &fsin.sin_port, sizeof(p->sin.sin_port)) == 0) 
+						{
+							send(p->s, buffer, i1, 0);
+							time(&p->last);
+							break;
+						}
+					if (p == NULL) { // new peer
+						printf("peer %s:%d added", inet_ntoa(fsin.sin_addr), (int)ntohs(fsin.sin_port));
+						p = malloc(sizeof *p);
+						p->sin = fsin;
+						p->s = connectsock(argv[2], argv[3], "udp");
+						p->next = peers;
+						peers = p;
+						send(p->s, buffer, i1, 0);
+						time(&p->last);
+					}
+				}
+			}
+			for (p = peers; p; p = p->next)
+				if(FD_ISSET(p->s, &rfds))
+				{
+					i1 = recv(p->s, buffer, 4096, 0);
+					if(i1 > 0) {
+						time(&p->last);
+						sendto(s, buffer, i1, 0, (struct sockaddr *) &p->sin, 
+							sizeof(p->sin)); 
+					}
+				}
+		} else {
+			peer_t *pp;
+
+			pp = NULL;
+			p = peers; 
+			while (p) {
+				if (time(NULL) - p->last > 300) {
+					if (!pp && !p->next) {
+						printf("peer %s:%d removed (timeout)", inet_ntoa(p->sin.sin_addr), (int)ntohs(p->sin.sin_port));
+						free(p);
+						p = pp = NULL;
+						continue;
+					}
+					pp->next = p->next;
+					printf ("peer %s:%d removed (timeout)", inet_ntoa(p->sin.sin_addr), (int)ntohs(p->sin.sin_port));
+					free(p);
+					p = pp->next;
+				} else {
+					pp = p;
+					p = p->next;
+				}
+			}
+		}
+	}
+}
--- /dev/null
+++ b/QW/qwfwd/qwfwd.dsp
@@ -1,0 +1,90 @@
+# Microsoft Developer Studio Project File - Name="QWFwd" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=QWFwd - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "qwfwd.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "qwfwd.mak" CFG="QWFwd - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "QWFwd - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "QWFwd - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE 
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "QWFwd - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+
+!ELSEIF  "$(CFG)" == "QWFwd - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+
+!ENDIF 
+
+# Begin Target
+
+# Name "QWFwd - Win32 Release"
+# Name "QWFwd - Win32 Debug"
+# Begin Source File
+
+SOURCE=.\qwfwd.c
+# End Source File
+# End Target
+# End Project
--- /dev/null
+++ b/QW/qwfwd/qwfwd.dsw
@@ -1,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 5.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "QWFwd"=.\QWFwd.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
--- /dev/null
+++ b/QW/qwfwd/qwfwd.plg
@@ -1,0 +1,32 @@
+<html>
+<body>
+<pre>
+<h1>Build Log</h1>
+<h3>
+--------------------Configuration: QWFwd - Win32 Release--------------------
+</h3>
+<h3>Command Lines</h3>
+Creating temporary file "C:\TEMP\RSP775.tmp" with contents
+[
+/nologo /ML /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Fp"Release/qwfwd.pch" /YX /Fo"Release/" /Fd"Release/" /FD /c 
+"D:\Work\quake source\QW\qwfwd\qwfwd.c"
+]
+Creating command line "cl.exe @C:\TEMP\RSP775.tmp" 
+Creating temporary file "C:\TEMP\RSP776.tmp" with contents
+[
+wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /incremental:no /pdb:"Release/qwfwd.pdb" /machine:I386 /out:"Release/qwfwd.exe" 
+".\Release\qwfwd.obj"
+]
+Creating command line "link.exe @C:\TEMP\RSP776.tmp"
+<h3>Output Window</h3>
+Compiling...
+qwfwd.c
+Linking...
+
+
+
+<h3>Results</h3>
+qwfwd.exe - 0 error(s), 0 warning(s)
+</pre>
+</body>
+</html>
--- /dev/null
+++ b/QW/qwrlnote.txt
@@ -1,0 +1,362 @@
+           ----------------------------------------------
+            QuakeWorld v2.30 Release Notes (Aug 26,1998)
+           ----------------------------------------------
+              Copyright id Software 1996, 1997, 1998
+                   
+                     Programmers:
+                  Dave 'Zoid' Kirsch 
+                http://www.quakeworld.net/
+                  zoid@idsoftware.com
+                
+                 Jack 'Morbid' Mathews
+                 http://www.gamespy.com 
+                   jack@gamespy.com
+
+2.30 Changes to QuakeWorld Server
+---------------------------------
+
+- Fixed many of the overflow problems found in 2.2x
+- Minor fixes to player movement code
+- sv_mapcheck defautls to on
+
+2.30 Chanes to QuakeWorld Client
+--------------------------------
+
+- "crosshaircolor" controls the color for the crosshair in "crosshair 2"
+  Values are 0 through 255 and represent a color in the palette.
+- "cl_chasecam 1" while in spectator mode gives a through-the-eyes view
+  of the player.
+- gl_cshiftpercent controls the blend precentage in GLQWCL (default 100).
+- Packet loss meter added to player scoreboard, "PL" is the column title.
+  This indicates the amount of packet loss the player is receiving.
+
+2.21 Changes to QuakeWorld Server
+---------------------------------
+
+New:
+- infokey(self, "ip") and infokey(self, "ping") return expected values as 
+strings (use stof for ping).
+- sv_mapcheck controls map checksumming.  Vis data is not included in the 
+checksum with 2.21 clients.
+
+Fixed/Changed:
+- Proxy checksumming code changed to less CPU intensive algorithm.
+- Fixed lots of overflow bugs (TF2.6 now works)
+- Optimized some of the server code
+- Server can accept 2.20 clients
+- Movement bug on maps such as ctf4 and the lip by the outside 100health on 
+dm3 fixed.
+
+2.21 Changes to QuakeWorld Client
+---------------------------------
+
+New:
+- CVar cl_maxfps added that controls the max fps rate independant of rate (it 
+defaults to zero, which means rate controlled).  PLEASE NOTE:  Setting 
+cl_maxfps to high values on a modem will OVERRUN YOUR MODEM and lag you since a 
+packet is sent every frame, resulting in your sending more data than your modem 
+can handle.  This is why fps was tied to rate in the first place.
+
+Fixed/Changed:
+- Demo recording lock ups fixed
+- Map checks don't include vis data (only works on 2.21 servers)
+- Client works on 2.20 and 2.21 servers
+- Movement bug on maps such as ctf4 and the lip by the outside 100health on 
+dm3 fixed.
+- Small bug in fov changes in glqwcl fixed (calculated fov span at wrong 
+point)
+- Linux client was hard locked at 30fps, fixed
+
+2.20 Changes to QuakeWorld Server
+---------------------------------
+
+New:
+- Map checksumming.  Client map must match server.
+
+Fixed/Changed:
+- Packets are now restricted to 1500 bytes for broken routers.
+- Server signon sequence changed to multipart due to new packet size 
+  limitations
+- Challenge/response system to stop spoofing
+- New internal port handling to route through broken NAT routers.
+- Client userinfo spamming reduced
+- Name changes are broadcast
+- Player physics tuned to be more like original Quake
+- Autoaim is off by default in the server (sv_aim 2)
+- Serverinfo watervis controls whether clients with GLQWCL can enable 
+  r_wateralpha
+
+2.20 Changes to QuakeWorld Client
+---------------------------------
+
+Fixed/Changed:
+- Signon sequence changed to correspond to new server protocol
+- Demos can now be initiated during a server connection
+
+2.11 Changes to QuakeWorld Client
+---------------------------------
+New:
+- You can now specify the size of the console in the GL version.  For example,
+  if you want a 320x200 console, put "-conwidth 320" on the command line.
+  -conheight is also supported, but if unspecified it will automatically use
+  a 4:3 aspect.  I.e., -conwidth 512 defaults to -conheight 384.  In high
+  resolution modes such as 800x600 and 1024x768, the console defaults to
+  640x480, otherwise the font and status bar become too small to read.  If
+  you do want a higher resolution console in those modes, specify it as well:
+  glqwcl -width 800 -height 600 -conwidth 800
+  Note that not all cards support modes higher than 640x480.
+- GL_SGIS_multitexture is now supported.  This allows some hardware that can
+  blend textures together to render the world in one pass instead of two
+  (world textures for one pass, lightmaps for the second).  You need a card
+  such as a 3DFX VooDoo with two TMU units in order to take advantage of
+  this.  If you have the required hardware, you will get a 60 to 100%
+  improvement in rendering speed.
+
+Fixed/Changed:
+- GL Sprite bug fixed
+
+2.11 Changes to QuakeWorld Server
+---------------------------------
+- Win32 -heapsize <kb>/-mem <mb> options were broken
+
+2.10 Changes to QuakeWorld Client
+---------------------------------
+New:
+- Added alternate crosshair.  Enabled with "crosshair 2".
+
+Fixed/Changed:
+- Fixed prediction bug in spectator/camera view.  Camera will no longer try
+  to view under platforms.  Water still confuses it.
+- Fixed random crash/exit problem present in 2.0
+
+2.10 Changes to QuakeWorld Server
+---------------------------------
+- Spectators are now indicated with a (s) on server console "status" command
+- Fixed minor security hole
+
+2.01 Changes to QuakeWorld Server
+---------------------------------
+New:
+- Added SpectatorConnect, SpectatorThink and SpectatorDisconnect Quake-C
+  functions.  They are empty shells for now (a example of moving spectators
+  from point to point is included with impulse 1) but can be used in lots
+  of ways.
+
+Fixed/Changed:
+- Fixed the crash bug with spectators
+- Changed the death msgs in the Quake-C to fix the old bug of incorrect msgs
+  when your weapon changed.  Minor things like if two guys with pentagrams
+  telefrag, they both die (happens in deathmatch 4).  Thanks to Nolan 'Radix'
+  Pflug <nolan@fyi.net> for diffs of the progs changes to get this worked out.
+- Fixed the mipmapping color errors in the GL version
+
+2.00 Changes to QuakeWorld Client
+---------------------------------
+        
+New:
+- Put support back in for -zone option
+- Added rerecord <filename> to cause a reconnect with demo recording on the
+  same server
+- Added EF_BLUE and EF_RED for new GL light bubbles
+- Made rocket trails fade out in GL
+- Added NOSKINS 2 to use but not download skins
+- Precalculate light bubble
+- Translucent console (GL)
+- 8bit 3DFX texture support.  reduces texture thrashing due to way less 
+  texture memory used.
+- will work on pre 2.0 servers, but can cause minor movement errors due to
+  differences in movement prediction
+- support for server controlled maxspeed and gravity multiplier.
+- added low/avg/high ping values to the showteamscores so an
+  average team ping is calculated
+- Added startup graphic banner
+- add other player clip hulls to player prediction and local prediction
+  this removes the problem of walking through other players and makes
+  close combat a lot nicer.
+
+Fixed/Changed:
+- Using TexSubImage2D to upload partial lightmaps (GL)
+- fixed resized console in gl version, had some dead space, so put a mini
+  frag list on the bottom
+- changed lightning in gl version so in default of gl_flashblend 1 you don't
+  see your own light, so having the quad doesn't obscure your vision
+- fixed dynamic lightning of alias models in gl version (players and what
+  not were not lit up by dynamic lights)
+- exiting the world in spectator mode is no longer lava red, but
+  slime green.
+- fixed the z-angle on entities (for example, the flag was rotated wrong)
+  in GL version.
+- Spectator camera changed from a free float to a locked camera that tracks
+
+2.00 Changes to QuakeWorld Server
+---------------------------------
+
+New:
+- Added flood procection to the server
+  default is 4 lines in 8 secs, wait for 10 on activation
+  Command to change is:  floodprot <lines> <time> <wait-time>
+- Added localinfo.  32k of key=value storage.  Values are stored with the
+  localinfo console command on the server, i.e.
+      localinfo e1m1 e1m2
+  localinfo is persistant from the life of the server (between maps)
+  progs can access localinfo using infokey(world, "key") and set it using
+      localcmd("localinfo ");
+      localcmd(key);
+      localcmd(" ");
+      localcmd(value);
+      localcmd("\n");
+  values with spaces should be quoted
+  If the same key exists in serverinfo and localinfo, serverinfo will override
+  localinfo is not visible 'outside' the server
+- Using localinfo, you can now configure a series of maps to run without
+  editing the quake-c.  usage:  localinfo <from-map> <to-map>.  For example,
+  to run a server that loops through e1m2, dm2, dm4 and dm6, try this:
+        localinfo e1m2 dm2
+        localinfo dm2 dm4
+        localinfo dm4 dm6
+        localinfo dm6 e1m2
+  Note that the last one should loop back to the first, otherwise normal
+  level changing applies.  Put the localinfo commands in the server.cfg
+- Protocol has changed, old clients will no longer work.  changable move
+  vars such as gravity, maxspeed, etc. are supported again
+- Full server controlled localized client maxspeed and gravity is in
+  Create to new fields in the QC, .float gravity and .float maxspeed.  
+  .maxspeed defaults to sv_maxspeed (320), .gravity defaults to 1.0 
+  (full gravity).
+  Change them at will in the QC, but don't change them too often as every 
+  change is noted and the clients are updated with the change so that 
+  their prediction works correctly.  The per-client maxspeed should be 
+  very handy for the TF guys.
+- added support for 'namefun' (high bit characters).  On by default, server
+  operators can turn it off with sv_highchars 0
+
+Fixed/Changed:
+- sv_friction defaults to 6 as in previous QuakeWorld release.  Regular Quake
+  uses a default friction of 4, so if the server op wants Regular Quake
+  behavior, he can change it to 4.
+- fixed 'download ./server.cfg' security bug.
+- fixed up ramp movement (on ground stuff)
+- removed password from userinfo after player connect so that other
+  players and spectators can't use the 'user' command to see the
+  passwd
+- setting password or spectator_password to 'none' is the same as
+  clearing it
+- change player move physics to support ramp accel, there was a bug in
+  stair stepping that prevented proper movement.  With this bug, you can't
+  jump into the RL room on dm6, or hit the secret light on e4m1.
+
+1.64 Changes to QuakeWorld Client
+---------------------------------
+New:
+- Added download percentage bar.  Displays filename and a bar indicating        
+  visual completeness of download and a percentage.  Overwrites
+  any text at the bottom.
+- Added auto-tracking camera for spectator mode.  It's mostly a novelty, but
+  its fun.
+- Added +showteamscores.  In team games, the intermission displays team
+  totals, unless you hit TAB to display frag scores
+  bind a key to +showteamscores will give you the team score display.
+- Added client side DEMO support and playback
+  usage:  record <file> <server>
+  Autodownload is disabled when recording.
+  playback: playdemo <file>
+  File uses the .qwd extension and is incompatible with regular Quake and its 
+  demos.
+- Adjust console input a bit to allow room for download percent bar (moved up
+  six pixels).
+- Add cl_hightrack cvar for spectator mode, causes it to always
+  select camera view on player with the highest frags.  cl_hightrack 1 turns
+  it on, cl_hightrack 0 turns it off (default)
+- Added text to the "Single player" and "Multiplayer" menu options.
+- Allowed Ctrl-V (paste) at console.
+- Added GL support.
+- Added FOV setting in GL version.
+
+Fixed/Changed:
+- If a model file isn't found (couldn't be download) a msg is displayed
+  telling the user they may need to download or purchase an addon pak.
+- Made all skin downloads go into QW directory.
+- Fixed water jump bug where you hop immediately back out in narrow entrances.
+- Added copyright dialog on exit (press y to quit) with credits and version
+  number.
+- New cvar, cl_warncmd, defaults to zero and disables the 'unknown command'
+  msg.  qwcl stuffs 'cl_warncmd 1' to itself after quake.rc loads. This gets
+  rid of unknown command messages (like unknown command 'startdemos') from 
+  the default exec files, as well as hiding "execing" messages.
+- New command, windows, which will pop a user in fullscreen mode back to     
+  Windows (not GL or Linux versions).
+- Turned off bobbing in spectator mode.
+- Now execs the config.cfg in a gamedir upon receiving a new gamedir from
+  the server (saves the current config into the current gamedir before
+  switching to the new one).
+- Reconnect command will now reconnect to the server it is currently   
+  connected to, or last one it was connected to.
+- Fixed it so entering 'record <file> <server>' while connected disconnects 
+  before starting recording.
+- Fixed scoreboard while dead in GL version.
+- Made it so players are never completely black in the GL version.
+- Changed some console load up msgs in GL.
+- Fixed it so exec files without a trailing new line still work.
+- changed effects in gl to not be as striking (hard to see).
+- Fixed it so a 'glquake' directory is created in other gamedirs for model
+  meshes in GL version.
+- Fixed tolerance on corrupt skin files.
+
+1.64 Changes to QuakeWorld Server
+---------------------------------
+New:
+- Added new allow_download vars:
+    allow_download_skins, allow_download_models,
+    allow_download_sounds, allow_download_maps
+- Added a few client to server commands for auto-camera support.
+- Adding new server cvar, sv_spectalk (defaults to 1, or on) that controls
+  whether spectators can talk to players.  If disabled, spectators can
+  only talk to each other.
+- New command, sv_gamedir, which sets the visible gamedir to clients.  this
+  allows servers to have a different physical game directories, handing for
+  machines with multiple servers that don't support symbolic links.  for
+  example:
+          gamedir ctf4.1
+        sv_gamedir ctf
+  causes qwsv to use the physical directory of 'ctf4.1', but report the
+  directory to clients (players) as 'ctf' for their files.
+
+Fixed/Changed:
+- Fixed bug in serverinfo strings (memory overwrite and length problem).
+- Map files are permitted to be downloaded if they aren't in a pak file
+  (unless allow_download or allow_download_maps isn't set).
+- Fixed annoying NET_GetPacket: Connection Refused msgs.
+- Fixed annoying water jump bug where you would immedately hop back out of 
+  water just after you jumped in.
+- Fixed air velocity movement so that it is like regular Quake, 
+  players have more control over their air movement and can cut
+  velocity as needed just like in Quake.  This gives more control
+  to the player and rewards skill.
+- Spectators no longer can send or receive say_team msgs (possible
+  cheating could happen).
+- Stopped reporting spectators as players when front-ends request info.
+- Fixed bug that disallowed 9's in ip address for filtering.
+- Spectators can now send say_team msgs, but only to other spectators.
+- No duplicate names allowed now (will rename people who do it).
+- A client can not name themselves 'console'.
+
+
+WorkArounds:
+------------
+
+-If you get the message 'GLIDE.DLL not found' OR QSpy reports error 1157, 
+you need to get and install the latest Glide drivers from 
+http://www.3dfx.com (currently v2.31).
+
+------------------------------
+2.00 Release Notes written by:
+------------------------------
+Dave 'Zoid' Kirsch - zoid@idsoftware.com
+
+------------------------------
+1.64 Release Notes written by:
+------------------------------
+Sean 'Redwood' Martin
+Redwood's Quake Page - http://redwood.stomped.com
+
+Special Thanks: All of the beta testers.
--- /dev/null
+++ b/QW/qwsv.spec.sh
@@ -1,0 +1,73 @@
+#!/bin/sh
+# Generate qwsv.spec
+# $1 is version
+# $2 is release
+# $3 is install dir (assumed to be in /var/tmp)
+cat <<EOF
+%define name qwsv
+%define version ${1}
+%define release ${2}
+%define builddir \$RPM_BUILD_DIR/%{name}-%{version}
+Name:		%{name}
+Version:	%{version}
+Release:	%{release}
+Vendor:		id Software
+Packager:	Dave "Zoid" Kirsch <zoid@idsoftware.com>
+URL:		http://www.idsoftware.com/
+Source:		qwsv-%{version}.tar.gz
+Group:		Games
+Copyright:	Restricted
+Icon:		quake.gif
+BuildRoot:	/var/tmp/%{name}-%{version}
+Summary:	QuakeWorld Server
+
+%description
+QuakeWorld is an Internet multi-player specific version of Quake. While the 
+original version of Quake can be played over the Internet, many users modem 
+users - the majority of players, had less than satisfactory play. Symptoms 
+like excessive lag - actions actually happening much later than you did them; 
+packet loss - the game would freeze and resume several seconds later; and 
+various other difficulties plagued users.
+
+After realizing how many people played Quake on the internet, and how many 
+wanted to, but couldn't due to the play being unsatisfactory, John Carmack 
+of id Software decided to create a version of Quake that was optimized for 
+the average modem Internet player. This Internet specific version does only 
+one thing, play deathmatch games over a TCP/IP network such as the Internet. 
+It has no support for solo play, and you can't do anything with out connecting 
+to a special server.
+
+Now in it's second generation, QuakeWorld has been sculpted by countless 
+hours of user feedback and tweaking to provide the best multi-player 
+experience that can be had from the equipment the average gamer will have. 
+All that is required to use QuakeWorld is registered Quake.
+
+%install
+
+%files
+%attr(644,root,root) ${3}/README.qwsv
+%attr(755,root,root) ${3}/qwsv
+%attr(644,root,root) ${3}/qw/buttons.qc 
+%attr(644,root,root) ${3}/qw/client.qc 
+%attr(644,root,root) ${3}/qw/combat.qc 
+%attr(644,root,root) ${3}/qw/defs.qc 
+%attr(644,root,root) ${3}/qw/doors.qc 
+%attr(644,root,root) ${3}/qw/items.qc 
+%attr(644,root,root) ${3}/qw/misc.qc 
+%attr(644,root,root) ${3}/qw/models.qc 
+%attr(644,root,root) ${3}/qw/plats.qc 
+%attr(644,root,root) ${3}/qw/player.qc 
+%attr(644,root,root) ${3}/qw/progdefs.h 
+%attr(644,root,root) ${3}/qw/progs.src 
+%attr(644,root,root) ${3}/qw/qwprogs.dat 
+%attr(644,root,root) ${3}/qw/server.qc 
+%attr(644,root,root) ${3}/qw/spectate.qc 
+%attr(644,root,root) ${3}/qw/sprites.qc 
+%attr(644,root,root) ${3}/qw/subs.qc 
+%attr(644,root,root) ${3}/qw/triggers.qc 
+%attr(644,root,root) ${3}/qw/weapons.qc 
+%attr(644,root,root) ${3}/qw/world.qc
+%attr(644,root,root) ${3}/qw/skins/fixskins.sh
+EOF
+
+
--- /dev/null
+++ b/QW/release233_notes.txt
@@ -1,0 +1,42 @@
+
+QuakeWorld 2.33 Test Release
+----------------------------
+
+QuakeWorld 2.33 is a test release to address several issues that have
+come to light in the QuakeWorld community.  Several different DoS
+(Denial Of Service) attacks have surfaced that need addressed.
+
+This test release contains both a new client and server to address these
+problems.  This release is currently compatible with 2.30 servers and clients,
+but this will not be true once the test period has completed.  The next
+release of QuakeWorld with be 2.4 and will be changed so previous versions
+will no longer function.  This is necessary in order to fully combat all
+the denial of service attacks currently present and to facility some changes
+in the prevention of cheating.
+
+The QuakeWorld 2.33 client has the follow changes and issues addressed:
+
+- Bug where client would crash during a level change if a skin name longer 
+than 16 characters on the server has been fixed.
+- The client now ignores foreign connection requests while connected to a
+server.
+- A foreign message packet with C-style format strings no longer cause a 
+client crash.
+- Large packets sent to the client could cause it to exit with a fatal error
+- Timing issues with later versions of Windows 95 and Windows 98 that would
+cause clients to mistime their frame times and result in a player that could 
+run faster/slower on a server has been changed and fixed.
+- When the client is running in a window, going to the menu or the console
+automatically frees up the mouse cursor.
+
+QuakeWorld 2.33 server changes:
+
+- Server now unpauses when all clients disconnect.
+- A possible server crash with large userinfo data has been fixed
+- A minor buffering error in network data was fixed
+
+Feedback for the release should be directed to Zoid at zoid@idsoftware.com
+
+
+
+
--- /dev/null
+++ b/QW/scitech/include/debug.h
@@ -1,0 +1,290 @@
+/****************************************************************************
+*
+*                   Copyright (C) 1996 SciTech Software
+*                           All rights reserved.
+*
+* Filename:     $Workfile:   debug.h  $
+* Version:      $Revision:   1.17  $
+*
+* Language:     ANSI C
+* Environment:  any
+*
+* Description:  General header file for operating system portable code.
+*
+* $Date:   04 Mar 1997 11:34:08  $ $Author:   KendallB  $
+*
+****************************************************************************/
+
+#ifndef __DEBUG_H
+#define __DEBUG_H
+
+/* We have the following defines to identify the compilation environment:
+ *
+ *	__16BIT__		Compiling for 16 bit code (any environment)
+ *  __32BIT__       Compiling for 32 bit code (any environment)
+ *	__MSDOS__		Compiling for MS-DOS (includes __WINDOWS16__, __WIN386__)
+ *  __REALDOS__     Compiling for MS-DOS (excludes __WINDOWS16__)
+ *  __MSDOS16__ 	Compiling for 16 bit MS-DOS
+ *  __MSDOS32__ 	Compiling for 32 bit MS-DOS
+ *  __WINDOWS__ 	Compiling for Windows
+ *	__WINDOWS16__	Compiling for 16 bit Windows (__MSDOS__ also defined)
+ *	__WINDOWS32__	Compiling for 32 bit Windows
+ *  __WIN386__      Compiling for Watcom C++ Win386 extended Windows
+ *  __OS2__     	Compiling for OS/2
+ *  __OS2_16__  	Compiling for 16 bit OS/2
+ *  __OS2_32__ 		Compiling for 32 bit OS/2
+ *  __UNIX__   		Compiling for Unix
+ *
+ */
+
+#ifdef	__SC__
+#if		__INTSIZE == 4
+#define __SC386__
+#endif
+#endif
+
+#ifdef	__GNUC__
+#define	__cdecl			/* GCC doesn't know about __cdecl modifiers		*/
+#define	__FLAT__		/* GCC is always 32 bit flat model				*/
+#define	__HAS_BOOL__	/* Latest GNU C++ has bool type					*/
+#endif
+
+#ifdef	__BORLANDC__
+#if	(__BORLANDC__ >= 0x500) || defined(CLASSLIB_DEFS_H)
+#define	__HAS_BOOL__	/* Borland C++ 5.0 and later define bool type	*/
+#endif
+#endif
+
+/* For the Metaware High C/C++ compiler, there is no _cdecl calling
+ * convention. The conventions can be changed, but it is a complicated
+ * process involving #pragmas, and all externally referenced functions
+ * will use stack based calling conventions. We also need to change the
+ * global aliasing conventions to use underscores for external function
+ * and variables names, so that our assembler routines will link
+ * correctly (except of course the main function - man what a PAIN!).
+ */
+
+#ifdef	__HIGHC__
+#define	__cdecl
+#define	__FLAT__	/* High C is always 32 bit flat model				*/
+#pragma Global_aliasing_convention("_%r")
+extern main();
+#pragma Alias(main,"main")
+#endif
+
+#if     defined(__MSDOS__) || defined(__DOS__) || defined(__DPMI32__) || (defined(M_I86) && !defined(__SC386__))
+#ifndef __MSDOS__
+#define __MSDOS__
+#endif
+#if     defined(__386__) || defined(__FLAT__) || defined(__NT__) || defined(__SC386__)
+#ifndef	__MSDOS32__
+#define __MSDOS32__
+#endif
+#ifndef	__32BIT__
+#define __32BIT__
+#endif
+#ifndef __REALDOS__
+#define __REALDOS__
+#endif
+#elif   (defined(_Windows) || defined(_WINDOWS)) && !defined(__DPMI16__)
+#ifndef	__16BIT__
+#define	__16BIT__
+#endif
+#ifndef __WINDOWS16__
+#define	__WINDOWS16__
+#endif
+#ifndef __WINDOWS__
+#define __WINDOWS__
+#endif
+#ifndef	__MSDOS__
+#define	__MSDOS__
+#endif
+#else
+#ifndef	__16BIT__
+#define	__16BIT__
+#endif
+#ifndef __MSDOS16__
+#define __MSDOS16__
+#endif
+#ifndef __REALDOS__
+#define __REALDOS__
+#endif
+#endif
+#elif   defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)
+#ifndef	__32BIT__
+#define __32BIT__
+#endif
+#ifndef	__WINDOWS32__
+#define	__WINDOWS32__
+#endif
+#ifndef	_WIN32
+#define	_WIN32					/* Microsoft Win32 SDK headers use _WIN32 */
+#endif
+#ifndef	WIN32
+#define	WIN32					/* OpenGL headers use WIN32 */
+#endif
+#ifndef __WINDOWS__
+#define __WINDOWS__
+#endif
+#elif   defined(__WINDOWS_386__)
+#ifndef	__32BIT__
+#define __32BIT__
+#endif
+#ifndef __WIN386__
+#define __WIN386__
+#endif
+#ifndef __WINDOWS__
+#define __WINDOWS__
+#endif
+#ifndef	__MSDOS__
+#define	__MSDOS__
+#endif
+#elif   defined(__OS2__)
+#ifndef __OS2__                 /* TODO: to be completed */
+#define __OS2__
+#define	__OS2_32__				/* Default to 32 bit OS/2 */
+#endif
+#else
+#define __UNIX__				/* TODO: to be completed */
+#endif
+
+/* We have the following defines to define the calling conventions for
+ * publicly accesible functions:
+ *
+ *  _PUBAPI - Compiler default calling conventions for all public 'C' functions
+ *  _ASMAPI - Calling conventions for all public assembler functions
+ *  _DLLAPI - Calling conventions for all DLL exported functions
+ *  _DLLVAR - Modifier to export/import globals in 32 bit DLL's
+ *  _EXPORT - Expands to _export when compiling a DLL
+ *  _VARAPI - Modifiers for variables; Watcom C++ mangles C++ globals
+ */
+
+#define _PUBAPI	
+#define _ASMAPI __cdecl
+
+#if defined(_MSC_VER) && defined(_WIN32) && !defined(__SC__)
+#define __PASCAL    __stdcall
+#define __export
+#define	__import
+#else
+#define __PASCAL    __pascal
+#endif
+
+#if defined(__WATCOMC__)
+#define	_VARAPI		__cdecl
+#else
+#define	_VARAPI
+#endif
+
+#if     defined(__WINDOWS__)
+#ifdef  BUILD_DLL
+#define _DLLASM __export __cdecl
+#define _EXPORT __export
+#ifdef  __WINDOWS32__
+#define _DLLAPI __export __PASCAL
+#define _DLLVAR __export
+#else
+#define _DLLAPI  __export __far __pascal
+#define _DLLVAR
+#endif
+#else
+#define _DLLASM __cdecl
+#define	_EXPORT
+#ifdef  __WINDOWS32__
+#define _DLLAPI __PASCAL
+#define _DLLVAR __import
+#else
+#define _DLLAPI __far __pascal
+#define _DLLVAR
+#endif
+#endif
+#else
+#define _EXPORT
+#define _DLLAPI
+#define _DLLVAR
+#endif
+
+/* Useful macros */
+
+#define PRIVATE static
+#define PUBLIC
+
+#ifdef  DEBUG
+#       define DBG(x) x
+#else
+#       define DBG(x)
+#endif
+
+#ifndef NULL
+#       define NULL 0L
+#endif
+
+#ifndef MAX
+#       define MAX(a,b) ( ((a) > (b)) ? (a) : (b))
+#endif
+#ifndef MIN
+#       define MIN(a,b) ( ((a) < (b)) ? (a) : (b))
+#endif
+#ifndef ABS
+#       define ABS(a)   ((a) >= 0 ? (a) : -(a))
+#endif
+#ifndef	SIGN
+#		define SIGN(a)	((a) > 0 ? 1 : -1)
+#endif
+
+/* General typedefs */
+
+#ifndef __GENDEFS
+#define __GENDEFS
+typedef unsigned char   uchar;
+typedef unsigned short  ushort;
+typedef unsigned int    uint;
+typedef unsigned long   ulong;
+typedef int             ibool;		/* Integer boolean type			*/
+#ifndef	__cplusplus
+#define	bool			ibool		/* Standard C					*/
+#else
+#ifndef	__HAS_BOOL__
+#define	bool			ibool		/* Older C++ compilers			*/
+#endif
+#endif	/* __cplusplus */
+#endif  /* __GENDEFS */
+
+/* Includes Windows headers, as they define TRUE and FALSE */
+
+#ifdef	__WINDOWS__
+#ifndef _WINDOWS_                   /* Dont include if already included */
+#ifndef __WIN386__
+#define STRICT
+#define	WIN32_LEAN_AND_MEAN
+#endif
+#include <windows.h>
+#endif
+#endif
+
+/* Boolean truth values */
+
+#undef	false
+#undef	true
+#undef	NO
+#undef	YES
+#undef	FALSE
+#undef	TRUE
+
+#ifdef	__cplusplus					/* Cast to bool's for C++ code		*/
+#define false       ((bool)0)
+#define true        ((bool)1)
+#define NO          ((bool)0)
+#define YES         ((bool)1)
+#define FALSE       ((bool)0)
+#define TRUE        ((bool)1)
+#else								/* Define to 0 and 1 for C code		*/
+#define false       0
+#define true        1
+#define NO          0
+#define YES         1
+#define FALSE       0
+#define TRUE        1
+#endif
+
+#endif  /* __DEBUG_H */
--- /dev/null
+++ b/QW/scitech/include/mgldos.h
@@ -1,0 +1,83 @@
+/****************************************************************************
+*
+*						MegaGraph Graphics Library
+*
+*                   Copyright (C) 1996 SciTech Software.
+*							All rights reserved.
+*
+* Filename:		$Workfile:   mgldos.h  $
+* Version:		$Revision:   1.9  $
+*
+* Language:		ANSI C
+* Environment:	IBM PC (MS DOS)
+*
+* Description:	Header file for the MGLDOS binding for the MSDOS environment.
+*
+* $Date:   30 Jan 1997 17:31:58  $ $Author:   KendallB  $
+*
+****************************************************************************/
+
+#ifndef	__MGLDOS_H
+#define	__MGLDOS_H
+
+#ifndef MGLDOS
+#define	MGLDOS
+#endif
+
+/*---------------------- Macros and type definitions ----------------------*/
+
+typedef void	*MGL_HWND;
+
+/*------------------------- Function Prototypes ---------------------------*/
+
+#ifdef	__cplusplus
+extern "C" {			/* Use "C" linkage when in C++ mode	*/
+#endif
+
+/* Initialise the MGL for fullscreen output */
+
+bool	MGLAPI MGL_init(m_int *driver,m_int *mode,const char *mglpath);
+
+/* Change the active display mode. You must destroy all display device
+ * contexts before calling this function, and re-create them again with
+ * the new display mode. Does not affect any event handling hooks.
+ */
+
+bool	MGLAPI MGL_changeDisplayMode(m_int mode);
+
+/* Disable/enable event handling (call before calling MGL_init */
+
+void 	MGLAPI MGL_useEvents(bool use);
+
+/* Device context management */
+
+MGLDC	* MGLAPI MGL_createDisplayDC(m_int numBuffers);
+MGLDC	* MGLAPI MGL_createScrollingDC(m_int virtualX,m_int virtualY,m_int numBuffers);
+MGLDC	* MGLAPI MGL_createOffscreenDC(void);
+MGLDC	* MGLAPI MGL_createLinearOffscreenDC(void);
+MGLDC 	* MGLAPI MGL_createMemoryDC(m_int xSize,m_int ySize,m_int bitsPerPixel,pixel_format_t *pf);
+bool	MGLAPI MGL_destroyDC(MGLDC *dc);
+
+/* Generic helper functions */
+
+ulong	MGLAPI MGL_getTicks(void);
+ulong	MGLAPI MGL_getTickResolution(void);
+void	MGLAPI MGL_delay(m_int millseconds);
+void	MGLAPI MGL_beep(m_int freq,m_int milliseconds);
+void	MGLAPI MGL_suspend(void);
+void	MGLAPI MGL_resume(void);
+
+/* Fullscreen specific routines */
+
+void	MGLAPI MGL_setPaletteSnowLevel(MGLDC *dc,m_int level);
+m_int	MGLAPI MGL_getPaletteSnowLevel(MGLDC *dc);
+
+/* Determine if a specific scancode'ed key is held down (PC specific) */
+
+bool	MGLAPI EVT_isKeyDown(uchar scanCode);
+
+#ifdef	__cplusplus
+}						/* End of "C" linkage for C++	*/
+#endif
+
+#endif	/* __MGLDOS_H */
--- /dev/null
+++ b/QW/scitech/include/mglwin.h
@@ -1,0 +1,152 @@
+/****************************************************************************
+*
+*						MegaGraph Graphics Library
+*
+*                   Copyright (C) 1996 SciTech Software.
+*							All rights reserved.
+*
+* Filename:		$Workfile:   mglwin.h  $
+* Version:		$Revision:   1.14  $
+*
+* Language:		ANSI C
+* Environment:	IBM PC (MS DOS)
+*
+* Description:	Header file for the MGLWIN bindings for MS Windows using
+*				WinG in a window and WinDirect for full screen. The MGLWIN
+*				binding only targets Win32 applications, so cannot be used
+*				for 16 bit Windows development.
+*
+* $Date:   14 Mar 1997 16:09:34  $ $Author:   KendallB  $
+*
+****************************************************************************/
+
+#ifndef	__MGLWIN_H
+#define	__MGLWIN_H
+
+#ifndef MGLWIN
+#define	MGLWIN
+#endif
+
+/*---------------------- Macros and type definitions ----------------------*/
+
+typedef HWND		MGL_HWND;
+typedef	HDC			MGL_HDC;
+typedef	HINSTANCE	MGL_HINSTANCE;
+
+/*------------------------- Function Prototypes ---------------------------*/
+
+#ifdef	__cplusplus
+extern "C" {			/* Use "C" linkage when in C++ mode	*/
+#endif
+
+/* Initialise the MGL for fullscreen output */
+
+bool	MGLAPI MGL_init(m_int *driver,m_int *mode,const char *mglpath);
+
+/* Initialise the MGL just for Windowed output, not full screen */
+
+bool	MGLAPI MGL_initWindowed(const char *mglpath);
+
+/* Function to register a fullscreen window with the MGL. If you wish
+ * for the MGL to use your own window for fullscreen modes, you can
+ * register it with this function. Note that when the MGL goes into
+ * fullscreen modes, the attributes, size and position of the window are
+ * modified to make it into a fullscreen Window necessary to cover the
+ * entire desktop, and the state of the window will be restore to the original
+ * format on return to normal GDI mode.
+ *
+ * Note that if you are using a common window for Windowed mode and fullscreen
+ * modes of your application, you will need to ensure that certain messages
+ * that you window normally handles in windowed modes are ignored when in
+ * fullscreen modes.
+ */
+
+void 	MGLAPI MGL_registerFullScreenWindow(HWND hwndFullScreen);
+
+/* Function to register a fullscreen event handling window procedure.
+ * If you wish to do your own event handling, you can register your window
+ * procedure with the MGL using this function and it will be called
+ * when there are messages to be handled. You can still call the MGL_event()
+ * functions even if you have registered an event handling procedure.
+ */
+
+void 	MGLAPI MGL_registerEventProc(WNDPROC userWndProc);
+
+/* Change the active display mode. You must destroy all display device
+ * contexts before calling this function, and re-create them again with
+ * the new display mode. Does not affect any event handling hooks.
+ */
+
+bool	MGLAPI MGL_changeDisplayMode(m_int mode);
+
+/* Obtain the handle to the MGL fullscreen window when in fullscreen modes */
+
+MGL_HWND MGLAPI MGL_getFullScreenWindow(void);
+
+/* Tell the MGL what your applications main window is */
+
+void	MGLAPI MGL_setMainWindow(MGL_HWND hwnd);
+
+/* Tell the MGL your applications instance handle (call before all funcs!) */
+
+void	MGLAPI MGL_setAppInstance(MGL_HINSTANCE hInstApp);
+
+/* Device context management */
+
+MGLDC	* MGLAPI MGL_createDisplayDC(m_int numBuffers);
+MGLDC	* MGLAPI MGL_createSrollingDC(m_int virtualX,m_int virtualY,m_int numBuffers);
+MGLDC	* MGLAPI MGL_createOffscreenDC(void);
+MGLDC	* MGLAPI MGL_createLinearOffscreenDC(void);
+MGLDC	* MGLAPI MGL_createWindowedDC(MGL_HWND hwnd);
+MGLDC 	* MGLAPI MGL_createMemoryDC(m_int xSize,m_int ySize,m_int bitsPerPixel,pixel_format_t *pf);
+bool	MGLAPI MGL_destroyDC(MGLDC *dc);
+
+/* Get a Windows HDC for the MGL device context. You can use this returned
+ * HDC to get GDI to draw to the device context surface, such as rendering
+ * and using TrueType fonts with the MGL. If a Windows compatible HDC is not
+ * available, this function will return NULL.
+ */
+
+HDC		MGLAPI MGL_getWinDC(MGLDC *dc);
+
+/* Associate a Window manager DC with the MGLDC for painting */
+
+bool	MGLAPI MGL_setWinDC(MGLDC *dc,MGL_HDC hdc);
+
+/* Activate the WindowDC's palette */
+
+bool	MGLAPI MGL_activatePalette(MGLDC *dc,bool unrealize);
+
+/* Let the MGL know when your application is being activated or deactivated.
+ * This function only needs to be called when running in Windowed modes and
+ * you have set the system palette to SYSPAL_NOSTATIC mode, to ensure
+ * that the MGL can properly re-map your application palette when your
+ * app is not active and allow Windows to re-map your bitmap colors on the
+ * fly. This function should be passed a pointer to the currently active
+ * MGL Windowed DC and a flag to indicate whether the app is in the background
+ * or not.   
+ */
+
+void	MGLAPI MGL_appActivate(MGLDC *winDC,bool active);
+
+/* Generic helper functions */
+
+ulong	MGLAPI MGL_getTicks(void);
+ulong	MGLAPI MGL_getTickResolution(void);
+void	MGLAPI MGL_delay(m_int millseconds);
+void	MGLAPI MGL_beep(m_int freq,m_int milliseconds);
+
+/* Fullscreen specific routines */
+
+void	MGLAPI MGL_setPaletteSnowLevel(MGLDC *dc,m_int level);
+m_int	MGLAPI MGL_getPaletteSnowLevel(MGLDC *dc);
+
+/* Determine if a specific scancode'ed key is held down (PC specific) */
+
+bool	MGLAPI EVT_isKeyDown(uchar scanCode);
+
+#ifdef	__cplusplus
+}						/* End of "C" linkage for C++	*/
+#endif
+
+#endif	/* __MGLWIN_H */
--- /dev/null
+++ b/QW/scitech/include/mgraph.h
@@ -1,0 +1,1951 @@
+/****************************************************************************
+*
+*						MegaGraph Graphics Library
+*
+*                   Copyright (C) 1996 SciTech Software.
+*							All rights reserved.
+*
+* Filename:		$Workfile:   mgraph.h  $
+* Version:		$Revision:   1.29  $
+*
+* Language:		ANSI C
+* Environment:	IBM PC (MS DOS)
+*
+* Description:	Header file for the MegaGraph Graphics Library. You can
+*				defined one of the following to specify which MGL API you
+*				wish to use.
+*
+*					MGL_LITE	- Compile for the MGL/Lite API
+*					MGL_PRO		- Compile for the MGL/Pro API
+*					MGL_FIX3D	- Compile for the MGL/3D API (fixed point)
+*					MGL_FLT3D	- Compile for the MGL/3D API (floating point)
+*
+*				If you do not define any of these, MGL_FIX3D will be defined
+*				automatically for compatibility with older versions of the
+*				MGL.
+*
+* $Date:   11 Mar 1997 16:46:42  $ $Author:   KendallB  $
+*
+****************************************************************************/
+
+#ifndef	__MGRAPH_H
+#define	__MGRAPH_H
+
+#include <stdio.h>
+
+#ifndef	__DEBUG_H
+#include "debug.h"
+#endif
+
+#if	!defined(MGL_LITE) && !defined(MGL_PRO) && !defined(MGL_FIX3D) \
+	&& !defined(MGL_FLT3D)
+#define	MGL_FIX3D
+#endif
+
+#if	defined(MGL_FIX3D) || defined(MGL_FLT3D)
+#define	MGL_3D
+#endif
+
+/*---------------------- Macros and type definitions ----------------------*/
+
+#pragma pack(1)				/* Pack structures to byte granularity		*/
+
+/* Define the version number for the MGL release */
+
+#define MGL_VERSION_STR     "3.1"
+
+/* Define the calling conventions for all public MGL functions. If we
+ * are compiling the MGL as a DLL, then all public functions are compiled
+ * and exported with standard C calling conventions, otherwise we use
+ * the default calling conventions provided by the compiler.
+ *
+ * Note that because Watcom C++ uses register based parameter passing
+ * by default we also provide special DLL's for watcom that are compiled
+ * with register parameter passing. This is necessary to work with all
+ * the extra libraries provided as they are all compiled to call MGL
+ * functions with arguments in registers whenever possible. You can still
+ * use the standard DLL but if you do you will need to re-compile all
+ * of the extra libraries with the MGL_DLL #define to change the calling
+ * conventions for the MGL functions.
+ */
+
+#if		defined(MGL_DLL)
+#define	MGLAPI	_EXPORT __cdecl
+#else
+#define	MGLAPI	_EXPORT _PUBAPI
+#endif
+#define	ASMAPI	_EXPORT __cdecl
+
+/* Define a type for integers used in the library. For most environments
+ * we simply define it as a normal integer (16 or 32 bits), however for
+ * 16 bit Windows it is defined as a 32 bit integer as all the real code
+ * lives in a 32 bit DLL that uses 32 bit integers.
+ */
+
+#ifndef	__M_INT_DEFINED
+#if	defined(__WINDOWS16__)
+typedef	long			m_int;
+typedef unsigned long	m_uint;
+#else
+typedef int				m_int;
+typedef	unsigned int	m_uint;
+#endif
+#define	__M_INT_DEFINED
+#endif
+
+/* Define the graphics subsystems available	*/
+
+typedef enum {
+	grDETECT		= -1,	/* Auto detect the graphics subsystem		*/
+	grNONE			= 0,	/* No graphics hardware detected			*/
+	grVGA,					/* Standard VGA								*/
+	grVESA,					/* VESA VBE compliant SuperVGA				*/
+	grSVGA,					/* Unaccelerated SuperVGA					*/
+	grACCEL,				/* Accelerated SuperVGA						*/
+	grDDRAW,				/* Unaccelerated DirectDraw					*/
+	grDDRAWACCEL,			/* Accelerated DirectDraw 					*/
+	grDDRAW3D,				/* 3D Accelerated DirectDraw 				*/
+	grMAXDRIVER,			/* Maximum driver number					*/
+	} MGL_driverType;
+
+/* Graphics modes supported	- the only video modes supported by this
+ * graphics library are those that support at least 16 colors per pixel.
+ */
+
+typedef enum {
+	/* 16 color VGA video modes */
+
+	grVGA_320x200x16,
+	grVGA_640x200x16,
+	grVGA_640x350x16,
+	grVGA_640x400x16,
+	grVGA_640x480x16,
+	grSVGA_800x600x16,
+
+	/* 256 color VGA ModeX video modes */
+
+	grVGAX_320x200x256,
+	grVGAX_320x240x256,
+	grVGAX_320x400x256,
+	grVGAX_320x480x256,
+
+	/* 256 color VGA video modes */
+
+	grVGA_320x200x256,
+
+	/* 256 color VGA/SuperVGA video modes */
+
+	grSVGA_320x200x256,
+	grSVGA_320x240x256,
+	grSVGA_320x400x256,
+	grSVGA_320x480x256,
+	grSVGA_400x300x256,
+	grSVGA_512x384x256,
+	grSVGA_640x350x256,
+	grSVGA_640x400x256,
+	grSVGA_640x480x256,
+	grSVGA_800x600x256,
+	grSVGA_1024x768x256,
+	grSVGA_1152x864x256,
+	grSVGA_1280x960x256,
+	grSVGA_1280x1024x256,
+	grSVGA_1600x1200x256,
+
+	/* 32,768 color Super VGA video modes */
+
+    grSVGA_320x200x32k,
+	grSVGA_320x240x32k,
+	grSVGA_320x400x32k,
+	grSVGA_320x480x32k,
+	grSVGA_400x300x32k,
+	grSVGA_512x384x32k,
+	grSVGA_640x350x32k,
+    grSVGA_640x400x32k,
+    grSVGA_640x480x32k,
+    grSVGA_800x600x32k,
+    grSVGA_1024x768x32k,
+	grSVGA_1152x864x32k,
+	grSVGA_1280x960x32k,
+	grSVGA_1280x1024x32k,
+    grSVGA_1600x1200x32k,
+
+	/* 65,536 color Super VGA video modes */
+
+    grSVGA_320x200x64k,
+	grSVGA_320x240x64k,
+	grSVGA_320x400x64k,
+	grSVGA_320x480x64k,
+	grSVGA_400x300x64k,
+	grSVGA_512x384x64k,
+	grSVGA_640x350x64k,
+	grSVGA_640x400x64k,
+	grSVGA_640x480x64k,
+	grSVGA_800x600x64k,
+	grSVGA_1024x768x64k,
+	grSVGA_1152x864x64k,
+	grSVGA_1280x960x64k,
+	grSVGA_1280x1024x64k,
+	grSVGA_1600x1200x64k,
+
+	/* 16 million color, 24 bits per pixel Super VGA video modes */
+
+	grSVGA_320x200x16m,
+	grSVGA_320x240x16m,
+	grSVGA_320x400x16m,
+	grSVGA_320x480x16m,
+	grSVGA_400x300x16m,
+	grSVGA_512x384x16m,
+	grSVGA_640x350x16m,
+	grSVGA_640x400x16m,
+	grSVGA_640x480x16m,
+	grSVGA_800x600x16m,
+	grSVGA_1024x768x16m,
+	grSVGA_1152x864x16m,
+	grSVGA_1280x960x16m,
+	grSVGA_1280x1024x16m,
+	grSVGA_1600x1200x16m,
+
+	/* 16 million color, 32 bits per pixel Super VGA video modes */
+
+	grSVGA_320x200x4G,
+	grSVGA_320x240x4G,
+	grSVGA_320x400x4G,
+	grSVGA_320x480x4G,
+	grSVGA_400x300x4G,
+	grSVGA_512x384x4G,
+	grSVGA_640x350x4G,
+	grSVGA_640x400x4G,
+	grSVGA_640x480x4G,
+	grSVGA_800x600x4G,
+	grSVGA_1024x768x4G,
+	grSVGA_1152x864x4G,
+	grSVGA_1280x960x4G,
+	grSVGA_1280x1024x4G,
+	grSVGA_1600x1200x4G,
+
+	/* Render into Windowing System DC (Windows, OS/2 PM, X11) */
+
+	grWINDOWED,
+
+	grMAXMODE,					/* Maximum mode number					*/
+	} MGL_modeType;
+
+/* MGL_result() error codes	*/
+
+typedef enum {
+	grOK			= 0,	/* No error									*/
+	grNoInit		= -1,	/* Graphics driver has not been installed	*/
+	grNotDetected	= -2,	/* Graphics hardware was not detected		*/
+	grDriverNotFound= -3,	/* Graphics driver file not found			*/
+	grBadDriver		= -4,	/* File loaded was not a graphics driver	*/
+	grLoadMem		= -5,	/* Not enough memory to load graphics driver*/
+	grInvalidMode	= -6,	/* Invalid graphics mode for selected driver*/
+	grError			= -8,	/* General graphics error					*/
+	grInvalidName	= -9,	/* Invalid driver name						*/
+	grNoMem			= -10,	/* Not enough memory to perform operation	*/
+	grNoModeSupport	= -11,	/* Select video mode not supported by hard.	*/
+	grInvalidFont	= -12,	/* Invalid font data						*/
+	grBadFontFile	= -13,	/* File loaded was not a font file			*/
+	grFontNotFound	= -14,	/* Font file was not found					*/
+	grOldDriver     = -15,	/* Driver file is an old version			*/
+	grInvalidDevice	= -16,	/* Invalid device for selected operation	*/
+	grInvalidDC		= -17,	/* Invalid device context					*/
+	grInvalidCursor	= -18,	/* Invalid cursor file						*/
+	grCursorNotFound= -19,	/* Cursor file was not found				*/
+	grInvalidIcon	= -20,	/* Invalid icon file						*/
+	grIconNotFound	= -21,	/* Icon file was not found					*/
+	grInvalidBitmap = -22,	/* Invalid bitmap file						*/
+	grBitmapNotFound= -23,	/* Bitmap file was not found				*/
+	grZbufferTooBig	= -24,	/* Zbuffer allocation is too large			*/
+	grNewFontFile	= -25,	/* Only Windows 2.x font files supported	*/
+	grNoDoubleBuff  = -26,	/* Double buffering is not available		*/
+	grNoHardwareBlt	= -28,	/* No hardware bitBlt for OffscreenDC		*/
+	grNoOffscreenMem= -29,	/* No available offscreen memory			*/
+	grInvalidPF		= -30,	/* Invalid pixel format for memory DC		*/
+
+	grLastError		= -31,	/* Last error number in list				*/
+	} MGL_errorType;
+
+#define	MGL_CLIPON		true
+#define	MGL_CLIPOFF		false
+
+/* Color mapped modes */
+
+typedef enum {
+	MGL_CMAP_MODE,					/* Normal Color mapped mode 	*/
+	MGL_DITHER_RGB_MODE,			/* 24 bit RGB halftone dithered	*/
+	} MGL_colorModes;
+
+/* Standard colors - this is the standard set of colors for the IBM PC. The
+ * default palette will have been programmed to contain these values when a
+ * graphics modes is started. If the palette has been changed, they will
+ * not correspond to the actual colors on the screen. Under a Windowing
+ * manage environment these colors will also not be setup by default.
+ */
+
+enum MGL_COLORS {
+	MGL_BLACK,						/* dark colors	*/
+	MGL_BLUE,
+	MGL_GREEN,
+	MGL_CYAN,
+	MGL_RED,
+	MGL_MAGENTA,
+	MGL_BROWN,
+	MGL_LIGHTGRAY,
+	MGL_DARKGRAY,					/* light colors	*/
+	MGL_LIGHTBLUE,
+	MGL_LIGHTGREEN,
+	MGL_LIGHTCYAN,
+	MGL_LIGHTRED,
+	MGL_LIGHTMAGENTA,
+	MGL_YELLOW,
+	MGL_WHITE,
+	};
+
+/* Windows standard color indices for 256 color bitmaps. 8,9,246,247 are
+ * reserved and you should not count on these colors always being the
+ * same. For 16 color bitmaps, colors 248-255 map to colors 8-15.
+ */
+
+enum MGL_WIN_COLORS {
+	MGL_WIN_BLACK 			= 0,
+	MGL_WIN_DARKRED			= 1,
+	MGL_WIN_DARKGREEN		= 2,
+	MGL_WIN_DARKYELLOW		= 3,
+	MGL_WIN_DARKBLUE		= 4,
+	MGL_WIN_DARKMAGENTA		= 5,
+	MGL_WIN_DARKCYAN		= 6,
+	MGL_WIN_LIGHTGRAY		= 7,
+	MGL_WIN_TURQUOISE		= 8,		/* Reserved; dont count on this	*/
+	MGL_WIN_SKYBLUE			= 9,		/* Reserved; dont count on this	*/
+	MGL_WIN_CREAM			= 246,		/* Reserved; dont count on this	*/
+	MGL_WIN_MEDIUMGRAY		= 247,		/* Reserved; dont count on this	*/
+	MGL_WIN_DARKGRAY		= 248,
+	MGL_WIN_LIGHTRED		= 249,
+	MGL_WIN_LIGHTGREEN		= 250,
+	MGL_WIN_LIGHTYELLOW		= 251,
+	MGL_WIN_LIGHTBLUE		= 252,
+	MGL_WIN_LIGHTMAGENTA	= 253,
+    MGL_WIN_LIGHTCYAN		= 254,
+	MGL_WIN_WHITE 			= 255,
+	};
+
+typedef enum {
+	MGL_MARKER_SQUARE,
+	MGL_MARKER_CIRCLE,
+	MGL_MARKER_X,
+	} MGL_markerStyleType;
+
+typedef enum {						/* Write mode operators				*/
+	MGL_REPLACE_MODE,				/* Replace mode						*/
+	MGL_AND_MODE,					/* AND mode							*/
+	MGL_OR_MODE,					/* OR mode							*/
+	MGL_XOR_MODE,					/* XOR mode							*/
+	} MGL_writeModeType;
+
+typedef enum {
+	MGL_BITMAP_SOLID,
+	MGL_BITMAP_OPAQUE,
+	MGL_BITMAP_TRANSPARENT,
+	MGL_PIXMAP,
+	} MGL_fillStyleType;
+
+typedef enum {
+	MGL_LINE_PENSTYLE,				/* Line drawn in current pen style	*/
+	MGL_LINE_STIPPLE,				/* Line drawn with current stipple	*/
+	} MGL_lineStyleType;
+
+typedef enum {
+	MGL_CONVEX_POLYGON,				/* Monotone vertical polygon		*/
+	MGL_COMPLEX_POLYGON,			/* Non-Simple polygons				*/
+	MGL_AUTO_POLYGON,				/* Auto detect the polygon type		*/
+	} MGL_polygonType;
+
+/* Text manipulation defines */
+
+typedef enum {
+	MGL_LEFT_TEXT		=	0,		/* Justify from left				*/
+	MGL_TOP_TEXT		=	0,		/* Justify from top					*/
+	MGL_CENTER_TEXT		=	1,		/* Center the text					*/
+	MGL_RIGHT_TEXT		=	2,		/* Justify from right				*/
+	MGL_BOTTOM_TEXT		=	2,		/* Justify from bottom				*/
+	MGL_BASELINE_TEXT	=	3,		/* Justify from the baseline		*/
+	} MGL_textJustType;
+
+typedef enum {
+	MGL_LEFT_DIR		=	0,		/* Text goes to left				*/
+	MGL_UP_DIR			=	1,		/* Text goes up						*/
+	MGL_RIGHT_DIR		=	2,		/* Text goes right					*/
+	MGL_DOWN_DIR		=	3,		/* Text goes down					*/
+	} MGL_textDirType;
+
+/* Font types */
+
+typedef enum {
+	MGL_VECTORFONT = 1,				/* Vector font						*/
+	MGL_FIXEDFONT,					/* Fixed width bitmap font			*/
+	MGL_PROPFONT,					/* Proportional width bitmap font	*/
+	} MGL_fontType;
+
+/* Palette rotation directions */
+
+typedef enum {
+	MGL_ROTATE_UP,					/* Rotate the palette values up		*/
+	MGL_ROTATE_DOWN,				/* Rotate the palette values down	*/
+	} MGL_palRotateType;
+
+/* Border drawing routine styles */
+
+typedef enum {
+	MGL_BDR_INSET,					/* Interior is inset into screen	*/
+	MGL_BDR_OUTSET,					/* Interior is outset from screen	*/
+	MGL_BDR_OUTLINE,				/* Border is 3d outline				*/
+	} MGL_bdrStyleType;
+
+/* Standard display driver names 	*/
+
+#define	MGL_VGA4NAME		"VGA4.DRV"		/* Standard VGA drivers			*/
+#define	MGL_VGA8NAME		"VGA8.DRV"
+#define	MGL_VGAXNAME		"VGAX.DRV"
+
+#define	MGL_SVGA4NAME		"SVGA4.DRV"		/* Generic SuperVGA drivers		*/
+#define	MGL_SVGA8NAME		"SVGA8.DRV"
+#define	MGL_SVGA16NAME		"SVGA16.DRV"
+#define	MGL_SVGA24NAME		"SVGA24.DRV"
+#define	MGL_SVGA32NAME		"SVGA32.DRV"
+
+#define	MGL_LINEAR8NAME		"LINEAR8.DRV"	/* Linear framebuffer drivers	*/
+#define	MGL_LINEAR16NAME	"LINEAR16.DRV"
+#define	MGL_LINEAR24NAME	"LINEAR24.DRV"
+#define	MGL_LINEAR32NAME	"LINEAR32.DRV"
+
+#define	MGL_ACCEL8NAME		"ACCEL8.DRV"	/* VBE/AF Accelerated drivers	*/
+#define	MGL_ACCEL16NAME		"ACCEL16.DRV"
+#define	MGL_ACCEL24NAME		"ACCEL24.DRV"
+#define	MGL_ACCEL32NAME		"ACCEL32.DRV"
+
+#define	MGL_DDRAW8NAME		"DDRAW8.DRV"	/* DirectDraw drivers			*/
+#define	MGL_DDRAW16NAME		"DDRAW16.DRV"
+#define	MGL_DDRAW24NAME		"DDRAW24.DRV"
+#define	MGL_DDRAW32NAME		"DDRAW32.DRV"
+
+/* Standard memory driver names 	*/
+
+#define	MGL_PACKED1NAME		"PACK1.DRV"
+#define	MGL_PACKED4NAME		"PACK4.DRV"
+#define	MGL_PACKED8NAME		"PACK8.DRV"
+#define	MGL_PACKED16NAME	"PACK16.DRV"
+#define	MGL_PACKED24NAME	"PACK24.DRV"
+#define	MGL_PACKED32NAME	"PACK32.DRV"
+
+/* Standard bitmap names	*/
+
+#define	MGL_EMPTY_FILL	_MGL_getEmptyPat()
+#define	MGL_GRAY_FILL	_MGL_getGrayPat()
+#define	MGL_SOLID_FILL	_MGL_getSolidPat()
+
+/* Event message masks for keyDown events */
+
+#define	EVT_ASCIIMASK	0x00FF	/* Ascii code of key pressed			*/
+#define	EVT_SCANMASK	0xFF00	/* Scan code of key pressed				*/
+#define	EVT_COUNTMASK	0x7FFF0000L		/* Count for KEYREPEAT's		*/
+
+#define	EVT_asciiCode(m)	( (uchar) (m & EVT_ASCIIMASK) )
+#define	EVT_scanCode(m)		( (uchar) ( (m & EVT_SCANMASK) >> 8 ) )
+#define	EVT_repeatCount(m)	( (short) ( (m & EVT_COUNTMASK) >> 16 ) )
+
+/* Event message masks for mouse events */
+
+#define	EVT_LEFTBMASK	0x0001	/* Left button is bit 0					*/
+#define	EVT_RIGHTBMASK	0x0004	/* Right button is bit 1				*/
+#define	EVT_BOTHBMASK	0x0005	/* Both left and right together			*/
+#define	EVT_ALLBMASK	0x0005	/* All buttons pressed					*/
+
+/* Modifier masks */
+
+#define	EVT_LEFTBUT		0x0001	/* Set if left button was down			*/
+#define	EVT_RIGHTBUT	0x0002	/* Set if right button was down			*/
+#define	EVT_RIGHTSHIFT	0x0008	/* Set if right shift down				*/
+#define	EVT_LEFTSHIFT	0x0010	/* Set if left shift down				*/
+#define	EVT_CTRLSTATE	0x0020	/* Set if ctrl key down					*/
+#define	EVT_ALTSTATE	0x0040	/* Set if alt key down					*/
+#define	EVT_LEFTCTRL	0x0080	/* Set if left ctrl key down			*/
+#define	EVT_LEFTALT		0x0100	/* Set if left alt key down				*/
+#define	EVT_SHIFTKEY	0x0018	/* Any shift key						*/
+
+/* Event codes */
+
+#define	EVT_NULLEVT		0x0000	/* A null event							*/
+#define	EVT_KEYDOWN		0x0001	/* Key down event						*/
+#define	EVT_KEYREPEAT	0x0002	/* Key repeat event						*/
+#define	EVT_KEYUP		0x0004	/* Key up event							*/
+#define	EVT_MOUSEDOWN	0x0008	/* Mouse down event						*/
+#define	EVT_MOUSEUP		0x0010	/* Mouse up event						*/
+#define	EVT_MOUSEMOVE	0x0020	/* Mouse movement event					*/
+#define	EVT_TIMERTICK	0x0040	/* Timer tick event						*/
+#define	EVT_USEREVT		0x0080	/* First user event						*/
+
+/* Event code masks */
+
+#define	EVT_KEYEVT		(EVT_KEYDOWN | EVT_KEYREPEAT | EVT_KEYUP)
+#define	EVT_MOUSEEVT	(EVT_MOUSEDOWN | EVT_MOUSEUP | EVT_MOUSEMOVE)
+#define	EVT_MOUSECLICK	(EVT_MOUSEDOWN | EVT_MOUSEUP)
+#define	EVT_EVERYEVT	0xFFFF
+
+/* Suspend Application callback type codes. This callback is called
+ * when the user presses one of the corresponding keys indicating that
+ * they wish to change the active application. The MGL will catch these
+ * events and if you have registered a callback, will call the callback to
+ * save the state of the application so that it can be properly restored
+ * when the user switches back to your application. The MGL takes care of
+ * all the details about saving and restoring the state of the hardware,
+ * and all your application needs to do is save its own state so that you can
+ * re-draw the application screen upon re-activation.
+ *
+ * NOTE: Your application suspend callback may get called twice with the
+ *		 MGL_DEACTIVATE flag in order to test whether the switch should
+ *		 occur (under both DirectDraw and WinDirect fullscreen modes).
+ *
+ * NOTE: When your callback is called with the MGL_DEACTIVATE flag, you
+ *		 cannot assume that you have access to the display memory surfaces
+ *		 as they may have been lost by the time your callback has been called. 
+ */
+
+#define	MGL_DEACTIVATE	0x0001	/* Application losing active focus		*/
+#define	MGL_REACTIVATE	0x0002	/* Application regaining active focus	*/
+
+/* Return codes from the suspend application callback. The normal value
+ * to be returned is MGL_SUSPEND_APP and this will cause the app to be
+ * suspended while back in GDI mode until the app is re-activated again
+ * by the user.
+ *
+ * MGL_NO_DEACTIVATE signals to WinDirect that the application does not want
+ * to allow switching to occur, and the switch request will be ignored and
+ * the app will remain in fullscreen mode.
+ *
+ * MGL_NO_SUSPEND_APP can be used to tell WinDirect to switch back to the
+ * desktop, but not to suspend the application. This must be used with
+ * care as the suspend application callback is then responsible for setting
+ * a flag in the application that will stop the application from doing any
+ * rendering to the framebuffer while the application is in GDI mode. This
+ * return value is useful for games that need to maintain network
+ * connectivity while the user has temporarily switched back to GDI mode.
+ */
+
+#define	MGL_NO_DEACTIVATE	0	/* Dont allow app to be deactivated 	*/
+#define	MGL_SUSPEND_APP		1	/* Suspend application until restored	*/
+#define	MGL_NO_SUSPEND_APP	2	/* Dont suspend, but allow switch		*/
+
+/* Here we define the structures used to represent points and rectangles */
+
+typedef struct {
+	m_int	x,y;
+	} point_t;
+
+typedef	struct {
+	m_int	left;
+	m_int	top;
+	m_int	right;
+	m_int	bottom;
+	} rect_t;
+
+/* All colors are represented as longs by the library. This allows
+ * code to work correctly with up to 24 bit color device drivers. The
+ * device drivers themselves expect the color to be a color index if in
+ * a color mapped mode, or a 15/16/24 bit RGB tuple in a hicolor or truecolor
+ * mode. You can use the appropriate routines to pack and unpack
+ * colors into the color_t format.
+ */
+
+typedef	ulong		color_t;
+
+/* Define the value used to clear the software ZBuffer. The MGL always uses
+ * a > operator for the z compare, and the smallest value is 0.
+ */
+
+#define	MGL_ZCLEARVAL	0
+
+/* Structures for passing vertex information to polygon rendering routines.
+ * All fixed point coordinates are passed in 16.16 signed fixed point
+ * format, while zbuffer coordinates are passed in 4.28 signed fixed point
+ * format. The sign bit is used purely for overflow and arithmetic
+ * internally, and all user passed zbuffer values should be greater than
+ * 0. All shaded rendering routines either take a color index in 8.16 fixed
+ * point format (range 0-255.9) or separate RGB components in 8.16 fixed
+ * point format (range 0-255.9).
+ */
+
+#ifdef	__FX_FIXED_H
+#define	fix32_t			FXFixed
+#else
+typedef	long			fix32_t;
+#endif
+typedef	fix32_t			fxcolor_t;
+typedef	long			zfix32_t;
+
+typedef	struct {
+	fix32_t x,y;
+	} fxpoint_t;
+
+typedef	struct {
+	fxcolor_t	r,g,b;
+	} fxrgb_t;
+
+typedef struct {
+	fix32_t		w,s,t;
+	} fxtex_t;
+
+typedef	struct {
+	fxcolor_t	c;
+	fxpoint_t   p;
+	} fxpointc_t;
+
+typedef	struct {
+	fxrgb_t		c;
+	fxpoint_t	p;
+	} fxpointrgb_t;
+
+typedef	struct {
+	fxpoint_t	p;
+	zfix32_t	z;
+	} fxpointz_t;
+
+typedef	struct {
+	fxcolor_t	c;
+	fxpoint_t	p;
+	zfix32_t	z;
+	} fxpointcz_t;
+
+typedef	struct {
+	fxrgb_t		c;
+	fxpoint_t	p;
+	zfix32_t	z;
+	} fxpointrgbz_t;
+
+/* Macros to convert between integer and 32 bit fixed point format */
+
+#define	MGL_FIX_1			0x10000L
+#define	MGL_FIX_2			0x20000L
+#define	MGL_FIX_HALF		0x08000L
+#define	MGL_TOFIX(i)		((long)(i) << 16)
+#define MGL_FIXTOINT(f)		((m_int)((f) >> 16))
+#define	MGL_FIXROUND(f) 	((m_int)(((f) + MGL_FIX_HALF) >> 16))
+
+#define	MGL_ZFIX_1			0x10000000L
+#define	MGL_ZFIX_HALF		0x08000000L
+#define MGL_FIXTOZ(i)		((i) << 12)
+#define	MGL_ZTOFIX(i)		((i) >> 12)
+#define	MGL_TOZFIX(i)		((long)(i) << 28)
+#define MGL_ZFIXTOINT(f)	((m_int)((f) >> 28))
+#define	MGL_ZFIXROUND(f) 	((m_int)(((f) + MGL_ZFIX_HALF) >> 28))
+
+/* Region structure */
+
+#ifdef	BUILD_MGL
+struct _span_t;
+typedef	struct _span_t	span_t;
+#else
+typedef void		span_t;
+#endif
+
+typedef struct {
+	rect_t      rect;			/* Bounding rectangle for region		*/
+	span_t		*spans;			/* Start of span list for region		*/
+	} region_t;
+
+/* Palette entry structure	*/
+
+typedef struct {
+	uchar	blue;				/* Blue component of color				*/
+	uchar	green;				/* Green component of color				*/
+	uchar	red;				/* Blue component of color				*/
+	uchar	alpha;				/* Alpha or alignment byte				*/
+	} palette_t;
+
+/* Maximum value for each palette entry component */
+
+#define	PALMAX		255				/* Max value for palette components	*/
+
+/* Pixel format structure */
+
+typedef struct {
+	uchar	redMask,greenMask;		/* Mask values for pixels			*/
+	uchar	blueMask,rsvdMask;
+	m_int	redPos,redAdjust;		/* Red position and adjustment		*/
+	m_int	greenPos,greenAdjust;	/* Green position and adjustment	*/
+	m_int	bluePos,blueAdjust;		/* Blue position and adjustment		*/
+	m_int	rsvdPos,rsvdAdjust;		/* Reserved position and adjustment */
+	} pixel_format_t;
+
+/* Structure to hold arc coordinate information */
+
+typedef struct {
+	m_int	x,y;					/* Centre point of the arc			*/
+	m_int	startX,startY;			/* Starting point on arc			*/
+	m_int	endX,endY;				/* Ending point on arc				*/
+	} arc_coords_t;
+
+/* Mouse cursor structure */
+
+typedef	struct {
+	ulong		xorMask[32];
+	ulong		andMask[32];
+	m_int		xHotSpot;
+	m_int		yHotSpot;
+	} cursor_t;
+
+/* Bitmap structure - always packed pixel DIB format */
+
+typedef struct {
+	m_int		width;				/* Width of bitmap in pixels		*/
+	m_int		height;				/* Height of bitmap in pixels		*/
+	m_int		bitsPerPixel;		/* Pixel width						*/
+	m_int		bytesPerLine;		/* Bytes per line value for surface */
+	uchar		*surface;			/* Pointer to bitmap surface		*/
+	palette_t	*pal;				/* Palette (NULL if not loaded)		*/
+	pixel_format_t *pf;				/* Pixel format (NULL if none)		*/
+
+	/* ... palette, pixel format and bitmap data are store contiguously */
+	} bitmap_t;
+
+/* Icon structure - can be 32x23, 64x64 or in fact any size */
+
+typedef struct {
+	m_int		byteWidth;			/* Byte with for AND mask			*/
+	uchar		*andMask;			/* Hold punch mask for icon			*/
+	bitmap_t	xorMask;			/* XOR mask for the icon			*/
+
+	/* ... AND mask and bitmap structure are stored contiguously */
+	} icon_t;
+
+/* Default cursor name */
+
+#define	MGL_DEF_CURSOR		_MGL_getDefCursor()
+
+/* Generic Font structure */
+
+#define	_MGL_FNAMESIZE		58
+
+typedef struct {
+	char			name[_MGL_FNAMESIZE];/* Name of the font			*/
+	short			fontType;		/* Type of font						*/
+	short			maxWidth;		/* Maximum character width			*/
+	short			maxKern;		/* Maximum character kern			*/
+	short			fontWidth;		/* Font width						*/
+	short			fontHeight;		/* Font height						*/
+	short			ascent;			/* Font ascent value				*/
+	short			descent;		/* Font descent value				*/
+	short			leading;		/* Font leading value				*/
+	} font_t;
+
+/* Character and font metrics structure */
+
+typedef struct {
+	m_int			width;			/* Width of character or font		*/
+	m_int			fontWidth;		/* Character width (tightest fit)	*/
+	m_int			fontHeight;		/* Height of the font				*/
+	m_int			ascent;			/* Ascent value						*/
+	m_int			descent;		/* Descent value					*/
+	m_int			leading;		/* Leading value					*/
+	m_int			kern;			/* Kern value						*/
+	} metrics_t;
+
+/* Text settings structure */
+
+typedef struct {
+	m_int			horizJust;		/* Horizontal justfication			*/
+	m_int			vertJust;		/* Vertical justification			*/
+	m_int			dir;			/* Text drawing direction			*/
+	m_int 			szNumerx;		/* Text x size numerator			*/
+	m_int 			szNumery;		/* Text y size numerator			*/
+	m_int			szDenomx;		/* Text x size denominator			*/
+	m_int			szDenomy;		/* Text y size denominator			*/
+	m_int			spaceExtra;		/* Space extra term					*/
+	font_t 			*font;			/* Currently selected font			*/
+	} text_settings_t;
+
+/* Macros to access the (left,top) and (right,bottom) points of a
+ * rectangle.
+ */
+
+#define	MGL_leftTop(r)		(((point_t *) &(r))[0])
+#define	MGL_rightBottom(r)	(((point_t *) &(r))[1])
+
+typedef uchar	pattern_t[8];
+typedef color_t	pixpattern_t[8][8];
+
+/* Attributes structure */
+
+typedef struct {
+	color_t			color;			/* Foreground color					*/
+	color_t			backColor;		/* Background color					*/
+	m_int			colorMode;		/* Current color mode				*/
+	m_int			markerSize;		/* Size of markers in pixels		*/
+	m_int			markerStyle;	/* Style of markers					*/
+	color_t			markerColor;	/* Color to draw markers in			*/
+	color_t			bdrBright;		/* Border bright color				*/
+	color_t			bdrDark;		/* Border dark color				*/
+	point_t			CP;				/* Graphics pen position			*/
+	m_int			writeMode;		/* Scan conversion write mode op.	*/
+	m_int			penStyle;		/* Pen style						*/
+	m_int			penHeight;		/* Height of pen					*/
+	m_int			penWidth;		/* Width of pen						*/
+	pattern_t		penPat;			/* Pattern for pen					*/
+	pixpattern_t	penPixPat;		/* Pixmap pattern for pen			*/
+	m_int			lineStyle;		/* Line style						*/
+	ushort			lineStipple;	/* Line stipple						*/
+	m_uint			stippleCount;	/* Current line stipple count		*/
+	rect_t			viewPort;		/* Viewport dimensions				*/
+	point_t			viewPortOrg;	/* Logical viewport origin			*/
+	rect_t			clipRect;		/* Clipping rectangle dimensions	*/
+	m_int			clip;			/* Is clipping on?					*/
+	m_int			polyType;		/* Polygon drawing type				*/
+	text_settings_t	ts;				/* Text drawing attributes			*/
+	} attributes_t;
+
+/* Mode specific format information. This structrure can be used by
+ * the device driver to build tables of values for all supported modes
+ */
+
+typedef struct {
+	m_int	xRes;			/* Device x resolution - 1					*/
+	m_int	yRes;			/* Device y resolution - 1					*/
+	m_int	bitsPerPixel;	/* Number of bits per pixel					*/
+	m_int	numberOfPlanes;	/* Number of planes in image				*/
+	color_t	maxColor;		/* Maximum number of colors - 1				*/
+	m_int	maxPage;		/* Maximum number of video pages - 1		*/
+	m_int	bytesPerLine;	/* Number of bytes in a line				*/
+	m_int	aspectRatio;	/* Mode aspect ratio (horiz/vert * 1000)	*/
+	long	pageSize;		/* Number of bytes in a page				*/
+	m_int	scratch1;		/* Scratch pad value 1						*/
+	m_int	scratch2;		/* Scratch pad value 2						*/
+	char    redMaskSize;            /* Size of direct color red mask    */
+	char    redFieldPosition;       /* Bit posn of lsb of red mask      */
+	char    greenMaskSize;          /* Size of direct color green mask  */
+	char    greenFieldPosition;     /* Bit posn of lsb of green mask    */
+	char    blueMaskSize;           /* Size of direct color blue mask   */
+	char    blueFieldPosition;      /* Bit posn of lsb of blue mask     */
+	char	rsvdMaskSize;			/* Size of reserved mask			*/
+	char	rsvdFieldPosition;		/* Bit posn of reserved mask		*/
+	} gmode_t;
+
+/* Public Device Context Structure. The 'surface' member along with the
+ * gmode_t information block, provides direct access to the active
+ * display surface for user applications. The MGL virtualises the surface
+ * in SuperVGA modes that dont have a real linear framebuffer.
+ */
+
+typedef struct {
+	attributes_t a;			/* Active device attributes					*/
+	void	*surface;		/* Pointer to active device surface			*/
+	void	*zbuffer;		/* Pointer to Z-buffer if allocated			*/
+	m_int	zbits;			/* Bits per zbuffer element					*/
+	m_int   zwidth;			/* Width of the zbuffer in pixels			*/
+	gmode_t	mi;				/* Mode specific information block			*/
+	pixel_format_t pf;		/* Current pixel format for device context	*/
+	color_t	*colorTab;		/* Color lookup table cache					*/
+	color_t	*shadeTab;		/* Currently active shade table				*/
+	m_int	bankOffset;		/* Offset of starting bank number			*/
+
+	/* Remainder of Device Context structure is private and internal	*/
+	} publicDevCtx_t;
+
+#ifndef	BUILD_MGL
+typedef publicDevCtx_t			MGLDC;
+#else
+struct internalDevCtx_t;
+typedef struct internalDevCtx_t	MGLDC;
+#endif
+
+typedef	struct {
+	ulong		which;			/* Which window for window manager code	*/
+	m_uint		what;			/* Event code							*/
+	ulong		when;			/* Clock ticks since midnight			*/
+	m_int		where_x;		/* Mouse location 						*/
+	m_int		where_y;
+	ulong		message;		/* Event specific message				*/
+	ulong		modifiers;		/* Modifier flags						*/
+	m_int		next;   		/* Next event in queue					*/
+	m_int		prev;			/* Previous event in queue				*/
+	} event_t;
+
+/* Structure containing file I/O functions allowing the user application to
+ * completely replace the MGL's file I/O functions with their own. This
+ * allows the app to store all MGL related files in a single large file,
+ * with encryption or compression is desired. By default normal file I/O
+ * functions will be used.
+ */
+
+typedef struct {
+	FILE *	(*fopen)(const char *filename,const char *mode);
+	int 	(*fclose)(FILE *f);
+	int 	(*fseek)(FILE *f,long offset,int whence);
+	long 	(*ftell)(FILE *f);
+	size_t	(*fread)(void *ptr,size_t size,size_t n,FILE *f);
+	size_t	(*fwrite)(const void *ptr,size_t size,size_t n,FILE *f);
+	} fileio_t;
+
+/* Define the flags for the types of direct surface access provided */
+
+#define	MGL_NO_ACCESS		0x0		/* Surface cannot be accessed		*/
+#define	MGL_VIRTUAL_ACCESS	0x1		/* Surface is virtualised 			*/
+#define	MGL_LINEAR_ACCESS	0x2		/* Surface can be linearly accessed	*/
+#define	MGL_SURFACE_FLAGS	0x3
+
+/* Define the flags for the types of direct zbuffer access provided */
+
+#define	MGL_NO_ZACCESS		0x0		/* Zbuffer cannot be accessed		*/
+#define	MGL_VIRTUAL_ZACCESS	0x4		/* Zbuffer is virtualised in 		*/
+#define	MGL_LINEAR_ZACCESS	0x8		/* Zbuffer can be linearly accessed	*/
+#define	MGL_ZBUFFER_FLAGS	0xC
+
+/* Define the flags for the types of hardware acceleration supported by
+ * the device context. This will allow the application to tailor the use of
+ * MGL functions depending upon whether specific hardware support is
+ * available. Hence applications can use specialised software rendering
+ * support if the desired hardware support is not available.
+ *
+ * NOTE: If the hardware flags are not MGL_HW_NONE, you *must* call
+ *		 the MGL_beginDirectAccess() and MGL_endDirectAccess() functions
+ *		 before and after any custom code that does direct framebuffer
+ *		 rendering!!
+ *
+ *		 This is not necessary for non-accelerated device context, so you
+ *		 might want to optimise these calls out if there is no hardware
+ *		 acceleration support.
+ */
+
+#define	MGL_HW_NONE			0x0000	/* No hardware acceleration			*/
+#define	MGL_HW_LINE			0x0010	/* Hardware line drawing			*/
+#define	MGL_HW_STIPPLE_LINE	0x0020	/* Hardware stippled line drawing	*/
+#define	MGL_HW_POLY			0x0040	/* Hardware polygon filling			*/
+#define	MGL_HW_RECT			0x0080	/* Hardware rectangle fill			*/
+#define	MGL_HW_PATT_RECT	0x0100	/* Hardware pattern rectangle fill	*/
+#define	MGL_HW_CLRPATT_RECT	0x0200	/* Hardware color pattern fill		*/
+#define	MGL_HW_SCR_BLT		0x0400	/* Hardware screen/screen bitBlt	*/
+#define	MGL_HW_SRCTRANS_BLT	0x0800	/* Hardware source transparent blt	*/
+#define	MGL_HW_DSTTRANS_BLT	0x1000	/* Hardware dest. transparent blt	*/
+#define	MGL_HW_MONO_BLT		0x2000	/* Hardware monochrome blt			*/
+#define	MGL_HW_CLIP			0x4000	/* Hardware clipping				*/
+#define	MGL_HW_FLAGS		0xFFF0
+
+#ifdef	__cplusplus
+extern "C" {			/* Use "C" linkage when in C++ mode	*/
+#endif
+
+/*------------------------- Function Prototypes ---------------------------*/
+
+/*---------------------------------------------------------------------------
+ * Routines bound to a specific device context. These routines all take
+ * an MGLDC as a parmeter for the context to work with and hence dont work
+ * with the current context. If however the context passed is the currently
+ * active context, all changes to that context are reflected in the
+ * currently active context as well.
+ *-------------------------------------------------------------------------*/
+
+/* Environment detection and initialisation */
+
+m_int 	MGLAPI MGL_registerDriver(const char *name,void *driver);
+void	MGLAPI MGL_unregisterAllDrivers(void);
+void	MGLAPI MGL_registerAllDispDrivers(bool useLinear,bool useDirectDraw,bool useWinDirect);
+void	MGLAPI MGL_registerAllMemDrivers(void);
+void 	MGLAPI MGL_detectGraph(m_int *driver,m_int *mode);
+uchar *	MGLAPI MGL_availableModes(void);
+m_int	MGLAPI MGL_availablePages(m_int mode);
+m_int	MGLAPI MGL_modeResolution(m_int mode,m_int *xRes,m_int *yRes,m_int *bitsPerPixel);
+bool	MGLAPI MGL_isDisplayDC(MGLDC *dc);
+bool	MGLAPI MGL_isWindowedDC(MGLDC *dc);
+bool	MGLAPI MGL_isMemoryDC(MGLDC *dc);
+void 	MGLAPI MGL_exit(void);
+void 	MGLAPI MGL_setBufSize(unsigned size);
+void	MGLAPI MGL_fatalError(const char *msg);
+m_int 	MGLAPI MGL_result(void);
+void	MGLAPI MGL_setResult(m_int result);
+const char * MGLAPI MGL_errorMsg(m_int err);
+const char * MGLAPI MGL_modeName(m_int mode);
+const char * MGLAPI MGL_modeDriverName(m_int mode);
+const char * MGLAPI MGL_driverName(m_int driver);
+m_int	MGLAPI MGL_getDriver(MGLDC *dc);
+m_int	MGLAPI MGL_getMode(MGLDC *dc);
+m_int	MGLAPI MGL_surfaceAccessType(MGLDC *dc);
+m_int	MGLAPI MGL_zbufferAccessType(MGLDC *dc);
+long	MGLAPI MGL_getHardwareFlags(MGLDC *dc);
+void 	MGLAPI MGL_defaultAttributes(MGLDC *dc);
+void 	MGLAPI MGL_makeSubDC(MGLDC *dc,m_int left,m_int top,m_int right,m_int bottom);
+
+/* Viewport and clip rectangle manipulation bound to a specific DC */
+
+void 	MGLAPI MGL_setViewportDC(MGLDC *dc,rect_t view);
+void	MGLAPI MGL_setRelViewportDC(MGLDC *dc,rect_t view);
+void 	MGLAPI MGL_getViewportDC(MGLDC *dc,rect_t *view);
+void 	MGLAPI MGL_setViewportOrgDC(MGLDC *dc,point_t org);
+void	MGLAPI MGL_getViewportOrgDC(MGLDC *dc,point_t *org);
+void	MGLAPI MGL_globalToLocalDC(MGLDC *dc,point_t *p);
+void	MGLAPI MGL_localToGlobalDC(MGLDC *dc,point_t *p);
+m_int 	MGLAPI MGL_maxxDC(MGLDC *dc);
+m_int 	MGLAPI MGL_maxyDC(MGLDC *dc);
+void 	MGLAPI MGL_setClipRectDC(MGLDC *dc,rect_t clip);
+void 	MGLAPI MGL_getClipRectDC(MGLDC *dc,rect_t *clip);
+void 	MGLAPI MGL_setClipModeDC(MGLDC *dc,bool mode);
+bool 	MGLAPI MGL_getClipModeDC(MGLDC *dc);
+
+/* Color and palette manipulation */
+
+color_t	MGLAPI MGL_realColor(MGLDC *dc,m_int color);
+color_t	MGLAPI MGL_rgbColor(MGLDC *dc,uchar R,uchar G,uchar B);
+void 	MGLAPI MGL_setPaletteEntry(MGLDC *dc,m_int entry,uchar red,uchar green,uchar blue);
+void 	MGLAPI MGL_getPaletteEntry(MGLDC *dc,m_int entry,uchar *red,uchar *green,uchar *blue);
+void 	MGLAPI MGL_setPalette(MGLDC *dc,palette_t *pal,m_int numColors,m_int startIndex);
+void 	MGLAPI MGL_getPalette(MGLDC *dc,palette_t *pal,m_int numColors,m_int startIndex);
+void	ASMAPI MGL_rotatePalette(MGLDC *dc,m_int numColors,m_int startIndex,m_int direction);
+bool	ASMAPI MGL_fadePalette(MGLDC *dc,palette_t *fullIntensity,m_int numColors,m_int startIndex,uchar intensity);
+void	MGLAPI MGL_realizePalette(MGLDC *dc,m_int numColors,m_int startIndex,m_int waitVRT);
+m_int	MGLAPI MGL_getPaletteSize(MGLDC *dc);
+void	MGLAPI MGL_getDefaultPalette(MGLDC *dc,palette_t *pal);
+void 	MGLAPI MGL_setDefaultPalette(MGLDC *dc);
+#ifndef	MGL_LITE
+bool	MGLAPI MGL_checkIdentityPalette(bool enable);
+void	MGLAPI MGL_mapToPalette(MGLDC *dc,palette_t *pal);
+#endif
+
+/* Generic device context information and manipulation */
+
+bool 	MGLAPI MGL_haveWidePalette(MGLDC *dc);
+m_int	MGLAPI MGL_getBitsPerPixel(MGLDC *dc);
+color_t	MGLAPI MGL_maxColor(MGLDC *dc);
+m_int	MGLAPI MGL_maxPage(MGLDC *dc);
+m_int 	MGLAPI MGL_sizex(MGLDC *dc);
+m_int 	MGLAPI MGL_sizey(MGLDC *dc);
+void 	MGLAPI MGL_getPixelFormat(MGLDC *dc,pixel_format_t *pf);
+void	* MGLAPI MGL_computePixelAddr(MGLDC *dc,int x,int y);
+
+/* Double buffering support */
+
+void	MGLAPI MGL_setActivePage(MGLDC *dc,m_int page);
+m_int	MGLAPI MGL_getActivePage(MGLDC *dc);
+void	MGLAPI MGL_setVisualPage(MGLDC *dc,m_int page,m_int waitVRT);
+m_int	MGLAPI MGL_getVisualPage(MGLDC *dc);
+void	MGLAPI MGL_setDisplayStart(MGLDC *dc,m_int x,m_int y,m_int waitFlag);
+void	MGLAPI MGL_getDisplayStart(MGLDC *dc,m_int *x,m_int *y);
+void	MGLAPI MGL_vSync(MGLDC *dc);
+bool	MGLAPI MGL_doubleBuffer(MGLDC *dc);
+void	MGLAPI MGL_singleBuffer(MGLDC *dc);
+void	MGLAPI MGL_swapBuffers(MGLDC *dc,m_int waitVRT);
+
+/* Zbuffering support */
+
+#ifdef	MGL_3D
+m_int	MGLAPI MGL_getHardwareZBufferDepth(MGLDC *dc);
+bool    ASMAPI MGL_zBegin(MGLDC *dc,m_int zbits);
+bool	MGLAPI MGL_zShareZBuffer(MGLDC *dc,MGLDC *dcShared,m_int zbits);
+#endif
+
+/* Event handling support */
+
+bool 	MGLAPI EVT_getNext(event_t *evt,m_uint mask);
+bool	MGLAPI EVT_peekNext(event_t *evt,m_uint mask);
+bool	MGLAPI EVT_post(ulong which,m_uint what,ulong message,ulong modifiers);
+void	MGLAPI EVT_flush(m_uint mask);
+void 	MGLAPI EVT_halt(event_t *evt,m_uint mask);
+m_int	MGLAPI EVT_setTimerTick(m_int ticks);
+
+/*---------------------------------------------------------------------------
+ * Routines bound to the currently active context. All these routines work
+ * with the currently active context and do not reflect any changes made
+ * to the global context to the original user supplied context (because it
+ * may be cached). The cached DC is automatically flushed back to the
+ * original DC when a new context is enabled with MGL_makeCurrentDC().
+ *
+ * Before destroying a DC that is current, make sure you call
+ * MGL_makeCurrentDC(NULL) first!
+ *-------------------------------------------------------------------------*/
+
+/* Routines to change the active global device context */
+
+MGLDC *	MGLAPI MGL_makeCurrentDC(MGLDC *dc);
+bool	MGLAPI MGL_isCurrentDC(MGLDC *dc);
+
+/* Current device context information and manipulation */
+
+m_int 	MGLAPI MGL_getAspectRatio(void);
+void 	MGLAPI MGL_setAspectRatio(m_int aspectRatio);
+void 	ASMAPI MGL_setColor(color_t color);
+void	MGLAPI MGL_setColorRGB(uchar R,uchar G,uchar B);
+void	MGLAPI MGL_setColorCI(m_int index);
+color_t MGLAPI MGL_getColor(void);
+void 	ASMAPI MGL_setBackColor(color_t color);
+color_t MGLAPI MGL_getBackColor(void);
+color_t	ASMAPI MGL_packColor(pixel_format_t *pf,uchar R,uchar G,uchar B);
+void	MGLAPI MGL_unpackColor(pixel_format_t *pf,color_t color,uchar *R,uchar *G,uchar *B);
+color_t	ASMAPI MGL_packColorRGB(uchar R,uchar G,uchar B);
+void	MGLAPI MGL_unpackColorRGB(color_t color,uchar *R,uchar *G,uchar *B);
+color_t	MGLAPI MGL_defaultColor(void);
+#ifndef	MGL_LITE
+void	MGLAPI MGL_setMarkerSize(m_int size);
+m_int	MGLAPI MGL_getMarkerSize(void);
+void	MGLAPI MGL_setMarkerStyle(m_int style);
+m_int	MGLAPI MGL_getMarkerStyle(void);
+void	MGLAPI MGL_setMarkerColor(color_t color);
+color_t	MGLAPI MGL_getMarkerColor(void);
+void	MGLAPI MGL_setBorderColors(color_t bright,color_t dark);
+void	MGLAPI MGL_getBorderColors(color_t *bright,color_t *dark);
+void 	ASMAPI MGL_setWriteMode(m_int mode);
+m_int 	MGLAPI MGL_getWriteMode(void);
+void 	ASMAPI MGL_setPenStyle(m_int style);
+m_int 	MGLAPI MGL_getPenStyle(void);
+void 	MGLAPI MGL_setLineStyle(m_int style);
+m_int 	MGLAPI MGL_getLineStyle(void);
+void 	ASMAPI MGL_setLineStipple(ushort stipple);
+ushort	MGLAPI MGL_getLineStipple(void);
+void 	ASMAPI MGL_setLineStippleCount(m_uint stippleCount);
+m_uint	MGLAPI MGL_getLineStippleCount(void);
+void 	ASMAPI MGL_setPenBitmapPattern(const pattern_t *pat);
+void 	MGLAPI MGL_getPenBitmapPattern(pattern_t *pat);
+void 	ASMAPI MGL_setPenPixmapPattern(const pixpattern_t *pat);
+void 	MGLAPI MGL_getPenPixmapPattern(pixpattern_t *pat);
+void	MGLAPI MGL_setPenSize(m_int height,m_int width);
+void 	MGLAPI MGL_getPenSize(m_int *height,m_int *width);
+#ifndef	MGL_LITE
+void 	MGLAPI MGL_setColorMapMode(m_int mode);
+m_int	MGLAPI MGL_getColorMapMode(void);
+#endif
+void	MGLAPI MGL_setPolygonType(m_int type);
+m_int	MGLAPI MGL_getPolygonType(void);
+#endif
+void 	MGLAPI MGL_getAttributes(attributes_t *attr);
+void 	MGLAPI MGL_restoreAttributes(attributes_t *attr);
+
+/* Device clearing */
+
+void	ASMAPI MGL_clearDevice(void);
+void 	MGLAPI MGL_clearViewport(void);
+
+/* Viewport and clip rectangle manipulation */
+
+void 	MGLAPI MGL_setViewport(rect_t view);
+void	MGLAPI MGL_setRelViewport(rect_t view);
+void 	MGLAPI MGL_getViewport(rect_t *view);
+void 	MGLAPI MGL_setViewportOrg(point_t org);
+void	MGLAPI MGL_getViewportOrg(point_t *org);
+void	MGLAPI MGL_globalToLocal(point_t *p);
+void	MGLAPI MGL_localToGlobal(point_t *p);
+m_int 	MGLAPI MGL_maxx(void);
+m_int 	MGLAPI MGL_maxy(void);
+void 	MGLAPI MGL_setClipRect(rect_t clip);
+void 	MGLAPI MGL_getClipRect(rect_t *clip);
+void 	MGLAPI MGL_setClipMode(bool mode);
+bool 	MGLAPI MGL_getClipMode(void);
+
+/* Pixel plotting */
+
+void 	MGLAPI MGL_pixelCoord(m_int x,m_int y);
+color_t	MGLAPI MGL_getPixelCoord(m_int x,m_int y);
+void	ASMAPI MGL_beginPixel(void);
+void 	MGLAPI MGL_pixelCoordFast(m_int x,m_int y);
+color_t	MGLAPI MGL_getPixelCoordFast(m_int x,m_int y);
+void	ASMAPI MGL_endPixel(void);
+
+/* Line drawing and clipping */
+
+void 	MGLAPI MGL_moveToCoord(m_int x,m_int y);
+void 	MGLAPI MGL_moveRelCoord(m_int dx,m_int dy);
+void 	MGLAPI MGL_lineToCoord(m_int x,m_int y);
+void 	MGLAPI MGL_lineRelCoord(m_int dx,m_int dy);
+m_int 	MGLAPI MGL_getX(void);
+m_int 	MGLAPI MGL_getY(void);
+void	MGLAPI MGL_getCP(point_t* CP);
+void 	MGLAPI MGL_lineCoord(m_int x1,m_int y1,m_int x2,m_int y2);
+void 	MGLAPI MGL_lineCoordFX(fix32_t x1,fix32_t y1,fix32_t x2,fix32_t y2);
+void	MGLAPI MGL_lineCoordFast(m_int x1,m_int y1,m_int x2,m_int y2);
+void	MGLAPI MGL_lineCoordFastFX(fix32_t x1,fix32_t y1,fix32_t x2,fix32_t y2);
+void    MGLAPI MGL_lineEngine(fix32_t x1,fix32_t y1,fix32_t x2,fix32_t y2,void (ASMAPI *plotPoint)(m_int x,m_int y));
+bool	MGLAPI MGL_clipLineFX(fix32_t *x1,fix32_t *y1,fix32_t *x2,fix32_t *y2,fix32_t left,fix32_t top,fix32_t right,fix32_t bottom);
+#ifndef	MGL_LITE
+void 	ASMAPI MGL_scanLine(m_int y,m_int x1,m_int x2);
+#endif
+
+/* Routines to perform bank switching for banked framebuffers for custom
+ * rendering code. The first version is callable only from assembler and
+ * requires the new bank value to be passed in the DL register. The second
+ * version is callable directly from C. DO NOT CALL THESE FUNCTIONS WHEN
+ * RUNNING WITH A LINEAR FRAMEBUFFER!!!
+ */
+
+void	_ASMAPI SVGA_setBank(void);
+void	_ASMAPI SVGA_setBankC(int bank);
+
+/* Routines to begin/end direct framebuffer access. You must call these
+ * functions is you wish to render directly to a hardware accelerated
+ * device surface.
+ */
+
+void 	ASMAPI MGL_beginDirectAccess(void);
+void 	ASMAPI MGL_endDirectAccess(void);
+
+/* Routines to begin/end fast rendering of flat shaded lines, scanlines
+ * and polygons.
+ */
+
+void 	ASMAPI MGL_beginDrawing(void);
+void 	ASMAPI MGL_endDrawing(void);
+
+/* Routines to begin/end fast rendering of smooth shaded lines, scanlines
+ * and polygons.
+ */
+
+#ifdef	MGL_3D
+void 	ASMAPI MGL_beginShadedDrawing(void);
+void 	ASMAPI MGL_endShadedDrawing(void);
+#endif
+
+/* Routines to begin/end fast rendering of flat shaded, zbuffered lines and
+ * polygons.
+ */
+
+#ifdef	MGL_3D
+void 	ASMAPI MGL_beginZDrawing(void);
+void 	ASMAPI MGL_endZDrawing(void);
+#endif
+
+/* Routines to begin/end fast rendering of smooth shaded, zbuffered lines and
+ * polygons.
+ */
+
+#ifdef	MGL_3D
+void 	ASMAPI MGL_beginZShadedDrawing(void);
+void 	ASMAPI MGL_endZShadedDrawing(void);
+#endif
+
+/* Polygon drawing: Note that the following fast polygon routines
+ * only work with convex polygons. The integer coordinate versions are
+ * provided for compatibility only, and convert the coordinates to fixed
+ * point and call the appropriate fixed point routines below.
+ */
+
+#ifndef	MGL_LITE
+void	MGLAPI MGL_fillPolygon(m_int count,point_t *vArray,m_int xOffset,m_int yOffset);
+void	MGLAPI MGL_fillPolygonFast(m_int count,point_t *vArray,m_int xOffset,m_int yOffset);
+void    ASMAPI MGL_fillPolygonFX(m_int count,fxpoint_t *vArray,m_int vinc,fix32_t xOffset,fix32_t yOffset);
+void    ASMAPI MGL_fillPolygonFastFX(m_int count,fxpoint_t *vArray,m_int vinc,fix32_t xOffset,fix32_t yOffset);
+#endif
+
+/* 3D rasterization routines */
+
+#ifdef	MGL_3D
+void    MGLAPI MGL_zClearCoord(m_int left,m_int top,m_int right,m_int bottom,zfix32_t clearVal);
+#endif
+
+#ifdef	MGL_FIX3D
+void	ASMAPI MGL_cLineCoordFast(fix32_t x1,fix32_t y1,fix32_t c1,fix32_t x2,fix32_t y2,fix32_t c2);
+void	ASMAPI MGL_rgbLineCoordFast(fix32_t x1,fix32_t y1,fix32_t r1,fix32_t g1,fix32_t b1,fix32_t x2,fix32_t y2,fix32_t r2,fix32_t g2,fix32_t b2);
+void	ASMAPI MGL_zLineCoordFast(fix32_t x1,fix32_t y1,zfix32_t z1,fix32_t x2,fix32_t y2,zfix32_t z2);
+void	ASMAPI MGL_czLineCoordFast(fix32_t x1,fix32_t y1,zfix32_t z1,fix32_t c1,fix32_t x2,fix32_t y2,zfix32_t z2,fix32_t c2);
+void	ASMAPI MGL_rgbzLineCoordFast(fix32_t x1,fix32_t y1,zfix32_t z1,fix32_t r1,fix32_t g1,fix32_t b1,fix32_t x2,fix32_t y2,zfix32_t z2,fix32_t r2,fix32_t g2,fix32_t b2);
+
+void	ASMAPI MGL_triFast(fxpoint_t *v1,fxpoint_t *v2,fxpoint_t *v3,fix32_t xOffset,fix32_t yOffset);
+void	ASMAPI MGL_cTriFast(fxpointc_t *v1,fxpointc_t *v2,fxpointc_t *v3,fix32_t xOffset,fix32_t yOffset);
+void	ASMAPI MGL_rgbTriFast(fxpointrgb_t *v1,fxpointrgb_t *v2,fxpointrgb_t *v3,fix32_t xOffset,fix32_t yOffset);
+void	ASMAPI MGL_zTriFast(fxpointz_t *v1,fxpointz_t *v2,fxpointz_t *v3,fix32_t xOffset,fix32_t yOffset,zfix32_t zOffset);
+void	ASMAPI MGL_czTriFast(fxpointcz_t *v1,fxpointcz_t *v2,fxpointcz_t *v3,fix32_t xOffset,fix32_t yOffset,zfix32_t zOffset);
+void	ASMAPI MGL_rgbzTriFast(fxpointrgbz_t *v1,fxpointrgbz_t *v2,fxpointrgbz_t *v3,fix32_t xOffset,fix32_t yOffset,zfix32_t zOffset);
+
+void	ASMAPI MGL_quadFast(fxpoint_t *v1,fxpoint_t *v2,fxpoint_t *v3,fxpoint_t *v4,fix32_t xOffset,fix32_t yOffset);
+void	ASMAPI MGL_cQuadFast(fxpointc_t *v1,fxpointc_t *v2,fxpointc_t *v3,fxpointc_t *v4,fix32_t xOffset,fix32_t yOffset);
+void	ASMAPI MGL_rgbQuadFast(fxpointrgb_t *v1,fxpointrgb_t *v2,fxpointrgb_t *v3,fxpointrgb_t *v4,fix32_t xOffset,fix32_t yOffset);
+void	ASMAPI MGL_zQuadFast(fxpointz_t *v1,fxpointz_t *v2,fxpointz_t *v3,fxpointz_t *v4,fix32_t xOffset,fix32_t yOffset,zfix32_t zOffset);
+void	ASMAPI MGL_czQuadFast(fxpointcz_t *v1,fxpointcz_t *v2,fxpointcz_t *v3,fxpointcz_t *v4,fix32_t xOffset,fix32_t yOffset,zfix32_t zOffset);
+void	ASMAPI MGL_rgbzQuadFast(fxpointrgbz_t *v1,fxpointrgbz_t *v2,fxpointrgbz_t *v3,fxpointrgbz_t *v4,fix32_t xOffset,fix32_t yOffset,zfix32_t zOffset);
+#endif
+
+/* Routine to set the currently active shade table. In HiColor and TrueColor
+ * video modes, you must set a valid shadeTable before you call any of the
+ * color index shaded rendering routines (MGL_cTri() etc). These routines
+ * will interpolate an index into the current shade table rather than
+ * each of the RGB color channels, and the appropriate full RGB color is
+ * extracted directly from the shade table. The shade table can be any size,
+ * but the application must ensure that the indices passed in are within
+ * the range of the current shade table.
+ */
+
+#ifdef	MGL_3D
+void	MGLAPI MGL_setShadeTable(color_t *shadeTab);
+#endif
+
+/* Polyline drawing */
+
+#ifndef	MGL_LITE
+void 	MGLAPI MGL_marker(point_t p);
+void	MGLAPI MGL_polyPoint(m_int count,point_t *vArray);
+void 	MGLAPI MGL_polyMarker(m_int count,point_t *vArray);
+void 	MGLAPI MGL_polyLine(m_int count,point_t *vArray);
+#endif
+
+/* Rectangle drawing */
+
+#ifndef	MGL_LITE
+void 	MGLAPI MGL_rectCoord(m_int left,m_int top,m_int right,m_int bottom);
+void 	MGLAPI MGL_fillRectCoord(m_int left,m_int top,m_int right,m_int bottom);
+#endif
+
+/* Scanline color scanning. Thee routines are primitive, and do not perform
+ * any clipping or viewport mapping, so can be used to build you own
+ * high performance floodfilling routines (see the example file ffill.c
+ * for pre-built high speed floodfill routines).
+ */
+
+#ifndef	MGL_LITE
+m_int	ASMAPI MGL_scanRightForColor(m_int x,m_int y,color_t color);
+m_int	ASMAPI MGL_scanLeftForColor(m_int x,m_int y,color_t color);
+m_int 	ASMAPI MGL_scanRightWhileColor(m_int x,m_int y,color_t color);
+m_int	ASMAPI MGL_scanLeftWhileColor(m_int x,m_int y,color_t color);
+#endif
+
+/* Psuedo 3D border drawing */
+
+#ifndef	MGL_LITE
+void	MGLAPI MGL_drawBorderCoord(m_int left,m_int top,m_int right,m_int bottom,m_int style,m_int thickness);
+void 	MGLAPI MGL_drawHDivider(m_int y,m_int x1,m_int x2);
+void 	MGLAPI MGL_drawVDivider(m_int x,m_int y1,m_int y2);
+#endif
+
+/* Ellipse drawing */
+
+#ifndef	MGL_LITE
+void	MGLAPI MGL_ellipseArc(rect_t extentRect,m_int startAngle,m_int endAngle);
+void	MGLAPI MGL_ellipseArcCoord(m_int x,m_int y,m_int xradius,m_int yradius,m_int startAngle,m_int endAngle);
+void	ASMAPI MGL_getArcCoords(arc_coords_t *coords);
+void	MGLAPI MGL_ellipse(rect_t extentRect);
+void	MGLAPI MGL_ellipseCoord(m_int x,m_int y,m_int xradius,m_int yradius);
+void	MGLAPI MGL_fillEllipseArc(rect_t extentRect,m_int startAngle,m_int endAngle);
+void	MGLAPI MGL_fillEllipseArcCoord(m_int x,m_int y,m_int xradius,m_int yradius,m_int startAngle,m_int endAngle);
+void	MGLAPI MGL_fillEllipse(rect_t extentRect);
+void	MGLAPI MGL_fillEllipseCoord(m_int x,m_int y,m_int xradius,m_int yradius);
+void	MGLAPI MGL_ellipseEngine(rect_t extentRect,void (ASMAPI *setup)(m_int topY,m_int botY,m_int left,m_int right),void (ASMAPI *set4pixels)(bool inc_x,bool inc_y,bool region1),void (ASMAPI *finished)(void));
+void 	MGLAPI MGL_ellipseArcEngine(rect_t extentRect,m_int startAngle,m_int endAngle,arc_coords_t *ac,void (ASMAPI *plotPoint)(m_int x,m_int y));
+#endif
+
+/* Text attribute manipulation */
+
+#ifndef	MGL_LITE
+void 	MGLAPI MGL_setTextJustify(m_int horiz,m_int vert);
+void 	MGLAPI MGL_getTextJustify(m_int *horiz,m_int *vert);
+void 	MGLAPI MGL_setTextDirection(m_int direction);
+m_int   MGLAPI MGL_getTextDirection(void);
+void	MGLAPI MGL_setTextSize(m_int numerx,m_int denomx,m_int numery,m_int denomy);
+void	MGLAPI MGL_getTextSize(m_int *numerx,m_int *denomx,m_int *numery,m_int *denomy);
+void	MGLAPI MGL_setSpaceExtra(m_int extra);
+m_int	MGLAPI MGL_getSpaceExtra(void);
+void	MGLAPI MGL_setTextSettings(text_settings_t *settings);
+void	MGLAPI MGL_getTextSettings(text_settings_t *settings);
+m_int 	MGLAPI MGL_textHeight(void);
+m_int 	MGLAPI MGL_textWidth(const char *str);
+void	MGLAPI MGL_textBounds(m_int x,m_int y,const char *str,rect_t *bounds);
+m_int	MGLAPI MGL_charWidth(char ch);
+void	MGLAPI MGL_getFontMetrics(metrics_t *metrics);
+void	MGLAPI MGL_getCharMetrics(char ch,metrics_t *metrics);
+m_int	MGLAPI MGL_maxCharWidth(void);
+void	MGLAPI MGL_underScoreLocation(m_int *x,m_int *y,const char *str);
+#endif
+
+/* Text drawing */
+
+#ifndef	MGL_LITE
+void 	MGLAPI MGL_drawStr(const char *str);
+void	MGLAPI MGL_drawStrXY(m_int x,m_int y,const char *str);
+bool	MGLAPI MGL_useFont(font_t *font);
+font_t 	* MGLAPI MGL_getFont(void);
+bool	MGLAPI MGL_vecFontEngine(m_int x,m_int y,const char *str,void (ASMAPI *move)(m_int x,m_int y),void (ASMAPI *draw)(m_int x,m_int y));
+#endif
+
+/* BitBlt support */
+
+void 	MGLAPI MGL_bitBltCoord(MGLDC *dst,MGLDC *src,m_int left,m_int top,m_int right,m_int bottom,m_int dstLeft,m_int dstTop,m_int op);
+void 	MGLAPI MGL_stretchBltCoord(MGLDC *dst,MGLDC *src,m_int left,m_int top,m_int right,m_int bottom,m_int dstLeft,m_int dstTop,m_int dstRight,m_int dstBottom);
+#ifndef	MGL_LITE
+void 	MGLAPI MGL_getDivotCoord(MGLDC *dc,m_int left,m_int top,m_int right,m_int bottom,void *divot);
+void 	MGLAPI MGL_putDivot(MGLDC *dc,void *divot);
+long 	MGLAPI MGL_divotSizeCoord(MGLDC *dc,m_int left,m_int top,m_int right,m_int bottom);
+void 	MGLAPI MGL_putMonoImage(MGLDC *dc,m_int x,m_int y,m_int byteWidth,m_int height,void *image);
+void	MGLAPI MGL_putBitmap(MGLDC *dc,m_int x,m_int y,const bitmap_t *bitmap,m_int op);
+void	MGLAPI MGL_putBitmapSection(MGLDC *dc,m_int left,m_int top,m_int right,m_int bottom,m_int dstLeft,m_int dstTop,const bitmap_t *bitmap,m_int op);
+void	MGLAPI MGL_putBitmapTransparent(MGLDC *dc,m_int x,m_int y,const bitmap_t *bitmap,color_t transparent,bool sourceTrans);
+void	MGLAPI MGL_putBitmapTransparentSection(MGLDC *dc,m_int left,m_int top,m_int right,m_int bottom,m_int dstLeft,m_int dstTop,const bitmap_t *bitmap,color_t transparent,bool sourceTrans);
+void	MGLAPI MGL_putBitmapMask(MGLDC *dc,m_int x,m_int y,const bitmap_t *mask,color_t color);
+void	MGLAPI MGL_stretchBitmap(MGLDC *dc,m_int left,m_int top,m_int right,m_int bottom,const bitmap_t *bitmap);
+void	MGLAPI MGL_putIcon(MGLDC *dc,m_int x,m_int y,const icon_t *icon);
+void 	MGLAPI MGL_transBltCoord(MGLDC *dst,MGLDC *src,m_int left,m_int top,m_int right,m_int bottom,m_int dstLeft,m_int dstTop,color_t transparent,bool sourceTrans);
+#endif
+
+/* Linear offscreen DC BitBlt support */
+
+#ifndef	MGL_LITE
+void 	MGLAPI MGL_bitBltLinCoord(MGLDC *dst,MGLDC *src,ulong srcOfs,m_int dstLeft,m_int dstTop,m_int dstRight,m_int dstBottom,m_int op);
+void 	MGLAPI MGL_transBltLinCoord(MGLDC *dst,MGLDC *src,ulong srcOfs,m_int dstLeft,m_int dstTop,m_int dstRight,m_int dstBottom,color_t transparent,bool sourceTrans);
+#endif
+
+/* Monochrome bitmap manipulation */
+
+#ifndef	MGL_LITE
+void	MGLAPI MGL_drawGlyph(font_t *g,m_int x,m_int y,uchar glyph);
+m_int	MGLAPI MGL_getGlyphWidth(font_t *font,uchar glyph);
+m_int	MGLAPI MGL_getGlyphHeight(font_t *font);
+void 	MGLAPI MGL_rotateGlyph(uchar *dst,uchar *src,m_int *byteWidth,m_int *height,m_int rotation);
+void 	MGLAPI MGL_mirrorGlyph(uchar *dst,uchar *src,m_int byteWidth,m_int height);
+#endif
+
+/* Region management */
+
+#ifndef	MGL_LITE
+region_t * MGLAPI MGL_newRegion(void);
+region_t * MGLAPI MGL_copyRegion(const region_t *s);
+void	MGLAPI MGL_clearRegion(region_t *r);
+void 	MGLAPI MGL_freeRegion(region_t *r);
+void 	MGLAPI MGL_drawRegion(m_int x,m_int y,const region_t *r);
+#endif
+
+/* Region generation primitives */
+
+#ifndef	MGL_LITE
+region_t * MGLAPI MGL_rgnLineCoord(m_int x1,m_int y1,m_int x2,m_int y2,const region_t *pen);
+region_t * MGLAPI MGL_rgnLineCoordFX(fix32_t x1,fix32_t y1,fix32_t x2,fix32_t y2,const region_t *pen);
+/*region_t * MGLAPI MGL_rgnPolygon(m_int count,point_t *vArray);*/
+/*region_t * MGLAPI MGL_rgnPolygonFast(m_int count,point_t *vArray);*/
+region_t * MGLAPI MGL_rgnSolidRectCoord(m_int left,m_int top,m_int right,m_int bottom);
+region_t * MGLAPI MGL_rgnEllipse(rect_t extentRect,const region_t *pen);
+region_t * MGLAPI MGL_rgnEllipseArc(rect_t extentRect,m_int startAngle,m_int endAngle,const region_t *pen);
+void	MGLAPI MGL_rgnGetArcCoords(arc_coords_t *coords);
+region_t * MGLAPI MGL_rgnSolidEllipse(rect_t extentRect);
+region_t * MGLAPI MGL_rgnSolidEllipseArc(rect_t extentRect,m_int startAngle,m_int endAngle);
+#endif
+
+/* Region alegbra */
+
+#ifndef	MGL_LITE
+region_t * MGLAPI MGL_sectRegion(const region_t *r1,const region_t *r2);
+region_t * MGLAPI MGL_sectRegionRect(const region_t *r1,const rect_t *r2);
+bool	MGLAPI MGL_unionRegion(region_t *r1,const region_t *r2);
+bool	MGLAPI MGL_unionRegionRect(region_t *r1,const rect_t *r2);
+bool 	MGLAPI MGL_unionRegionOfs(region_t *r1,const region_t *r2,m_int xOffset,m_int yOffset);
+bool	MGLAPI MGL_diffRegion(region_t *r1,const region_t *r2);
+bool	MGLAPI MGL_diffRegionRect(region_t *r1,const rect_t *r2);
+void	MGLAPI MGL_optimizeRegion(region_t *r);
+void 	MGLAPI MGL_offsetRegion(region_t *r,m_int dx,m_int dy);
+bool	MGLAPI MGL_emptyRegion(const region_t *r);
+bool	MGLAPI MGL_equalRegion(const region_t *r1,const region_t *r2);
+bool	MGLAPI MGL_ptInRegionCoord(m_int x,m_int y,const region_t *r);
+#endif
+
+/* Region traversal */
+
+#ifndef	MGL_LITE
+typedef void (ASMAPI *rgncallback_t)(const rect_t *r);
+
+void 	MGLAPI MGL_traverseRegion(region_t *rgn,rgncallback_t doRect);
+#endif
+
+/* RGB to 8 bit halftone dithering routines */
+
+#ifndef	MGL_LITE
+void 	MGLAPI MGL_getHalfTonePalette(palette_t *pal);
+uchar	MGLAPI MGL_halfTonePixel(m_int x,m_int y,uchar R,uchar G,uchar B);
+#endif
+
+/* Resource loading/unloading */
+
+font_t * MGLAPI MGL_loadFont(const char *fontname);
+bool	MGLAPI MGL_availableFont(const char *fontname);
+void	MGLAPI MGL_unloadFont(font_t *font);
+cursor_t * MGLAPI MGL_loadCursor(const char *cursorName);
+bool	MGLAPI MGL_availableCursor(const char *cursorName);
+void 	MGLAPI MGL_unloadCursor(cursor_t *cursor);
+#ifndef	MGL_LITE
+icon_t * MGLAPI MGL_loadIcon(const char *iconName,bool loadPalette);
+bool	MGLAPI MGL_availableIcon(const char *iconName);
+void	MGLAPI MGL_unloadIcon(icon_t *icon);
+#endif
+
+/* Windows BMP bitmap loading/unloading/saving */
+
+#ifndef	MGL_LITE
+bitmap_t * MGLAPI MGL_loadBitmap(const char *bitmapName,bool loadPalette);
+bool	MGLAPI MGL_availableBitmap(const char *bitmapName);
+void	MGLAPI MGL_unloadBitmap(bitmap_t *bitmap);
+bool	MGLAPI MGL_getBitmapSize(const char *bitmapName,m_int *width,m_int *height,m_int *bitsPerPixel,pixel_format_t *pf);
+bool	MGLAPI MGL_loadBitmapIntoDC(MGLDC *dc,const char *bitmapName,m_int dstLeft,m_int dstTop,bool loadPalette);
+bool	MGLAPI MGL_saveBitmapFromDC(MGLDC *dc,const char *bitmapName,m_int left,m_int top,m_int right,m_int bottom);
+bitmap_t * MGLAPI MGL_getBitmapFromDC(MGLDC *dc,m_int left,m_int top,m_int right,m_int bottom,bool savePalette);
+bitmap_t * MGLAPI MGL_buildMonoMask(bitmap_t *bitmap,color_t transparent);
+#endif
+
+/* PCX bitmap loading/unloading/saving (1/4/8 bpp only) */
+
+#ifndef	MGL_LITE
+bitmap_t * MGLAPI MGL_loadPCX(const char *bitmapName,bool loadPalette);
+bool	MGLAPI MGL_availablePCX(const char *bitmapName);
+bool	MGLAPI MGL_getPCXSize(const char *bitmapName,m_int *width,m_int *height,m_int *bitsPerPixel);
+bool	MGLAPI MGL_loadPCXIntoDC(MGLDC *dc,const char *bitmapName,m_int dstLeft,m_int dstTop,bool loadPalette);
+bool	MGLAPI MGL_savePCXFromDC(MGLDC *dc,const char *bitmapName,m_int left,m_int top,m_int right,m_int bottom);
+#endif
+
+/* Random number generation routines for shorts and longs with full range */
+
+void    ASMAPI MGL_srand(m_uint seed);
+ushort	ASMAPI MGL_random(ushort max);
+ulong	ASMAPI MGL_randoml(ulong max);
+
+/* Mouse support */
+
+bool	MGLAPI MS_available(void);
+void	MGLAPI MS_show(void);
+void	MGLAPI MS_hide(void);
+void	MGLAPI MS_obscure(void);
+void	MGLAPI MS_setCursor(cursor_t *curs);
+void	MGLAPI MS_setCursorColor(color_t color);
+void 	MGLAPI MS_moveTo(m_int x,m_int y);
+void	MGLAPI MS_getPos(m_int *x,m_int *y);
+void	MGLAPI MS_drawCursor(void);
+
+/* Rectangle and Point manipulation */
+
+rect_t 	MGLAPI MGL_defRect(m_int left,m_int top,m_int right,m_int bottom);
+rect_t 	MGLAPI MGL_defRectPt(point_t leftTop,point_t rightBottom);
+bool 	MGLAPI MGL_sectRect(rect_t s1,rect_t s2,rect_t *d);
+bool 	MGLAPI MGL_sectRectCoord(m_int left1,m_int top1,m_int right1,m_int bottom1,m_int left2,m_int top2,m_int right2,m_int bottom2,rect_t *d);
+void 	MGLAPI MGL_unionRect(rect_t s1,rect_t s2,rect_t *d);
+void 	MGLAPI MGL_unionRectCoord(m_int left1,m_int top1,m_int right1,m_int bottom1,m_int left2,m_int top2,m_int right2,m_int bottom2,rect_t *d);
+
+/* Built-in patterns and mouse cursor */
+
+#ifndef	MGL_LITE
+pattern_t	* MGLAPI _MGL_getEmptyPat(void);
+pattern_t   * MGLAPI _MGL_getGrayPat(void);
+pattern_t   * MGLAPI _MGL_getSolidPat(void);
+#endif
+cursor_t    * MGLAPI _MGL_getDefCursor(void);
+
+/* Fixed point multiplication/divide routines */
+
+#if defined(__WATCOMC__) && defined(__386__)
+
+/* For Watcom C++ we can use special inline assembler code that is much
+ * faster than calling the 386 assembler functions. Currently this is the
+ * the only compiler that will allow inline assembler to be expanded
+ * directly as inline functions.
+ */
+
+fix32_t	MGL_FixMul(fix32_t a,fix32_t b);
+#pragma aux MGL_FixMul =			\
+	"imul	edx"					\
+	"add	eax,8000h"				\
+	"adc	edx,0"					\
+	"shrd	eax,edx,16"				\
+	parm [eax] [edx]				\
+	value [eax]						\
+	modify exact [eax edx];
+
+fix32_t	MGL_FixDiv(fix32_t a,fix32_t b);
+#pragma aux MGL_FixDiv =			\
+	"xor	eax,eax"				\
+	"shrd	eax,edx,16"				\
+	"sar	edx,16"					\
+	"idiv	ebx"              		\
+	parm [edx] [ebx] 				\
+	value [eax]             		\
+	modify exact [eax edx];
+
+fix32_t	MGL_FixMulDiv(fix32_t a,fix32_t b,fix32_t c);
+#pragma aux MGL_FixMulDiv =			\
+	"imul	ebx"					\
+	"idiv	ecx"              		\
+	parm [eax] [ebx] [ecx] 			\
+	value [eax]             		\
+	modify exact [eax edx];
+
+m_int	MGL_backfacing(fix32_t dx1,fix32_t dy1,fix32_t dx2,fix32_t dy2);
+#pragma aux MGL_backfacing =		\
+	"imul	ebx"					\
+	"mov	ebx,eax"				\
+	"mov	ecx,edx"				\
+	"mov	eax,esi"				\
+	"imul	edi"					\
+	"sub	eax,ebx"				\
+	"mov	eax,1"					\
+	"sbb	edx,ecx"				\
+	"jns	@@Backfacing"			\
+	"xor	eax,eax"				\
+	"@@Backfacing:"					\
+	parm [eax] [esi] [edi] [ebx]	\
+	value [eax]             		\
+	modify exact [eax ecx edx];
+
+void MGL_memcpy(void *dst,void *src,m_int n);
+#pragma aux MGL_memcpy =            \
+	"mov	eax,ecx"				\
+	"shr    ecx,2"                  \
+	"rep    movsd"                  \
+	"mov	cl,al"					\
+	"and	cl,3"					\
+	"rep	movsb"					\
+	parm [edi] [esi] [ecx]			\
+	modify exact [eax ecx esi edi];
+
+#else
+
+fix32_t	ASMAPI MGL_FixMul(fix32_t a,fix32_t b);
+fix32_t	ASMAPI MGL_FixDiv(fix32_t a,fix32_t b);
+fix32_t	ASMAPI MGL_FixMulDiv(fix32_t a,fix32_t b,fix32_t c);
+m_int	ASMAPI MGL_backfacing(fix32_t dx1,fix32_t dy1,fix32_t dx2,fix32_t dy2);
+void 	ASMAPI MGL_memcpy(void *dst,void *src,m_int n);
+
+#endif
+
+/* The following are special memcpy routines that properly handler reading
+ * and writing to virtual linear buffer memory by forcing the proper
+ * alignment. Note that the copy is extended to use a DWORD copy of speed.
+ */
+
+void 	ASMAPI MGL_memcpyVIRTSRC(void *dst,void *src,m_int n);
+void 	ASMAPI MGL_memcpyVIRTDST(void *dst,void *src,m_int n);
+
+/* Function to find an MGL system file's full pathname */
+
+bool	MGLAPI _MGL_findFile(char *validpath,const char *dir, const char *filename, const char *mode);
+
+/* Override the internal MGL file I/O functions */
+
+void	MGLAPI MGL_setFileIO(fileio_t *fio);
+
+/* The following dummy symbols are used to link in driver files to be used. A
+ * driver is not active until it is linked in with the MGL_registerDriver
+ * call. Because we dont export globals in DLLs, we provide functions to
+ * get the address of the drivers. However for a static link library we
+ * need to use globals so that if the driver data is unreferenced, it will
+ * not be linked in with the code. 
+ */
+
+#ifndef	BUILD_MGL
+#if	defined(MGL_DLL) && !defined(BUILD_MGLDLL)
+void * MGLAPI VGA4_getDriverAddr(void);
+void * MGLAPI VGAX_getDriverAddr(void);
+void * MGLAPI SVGA4_getDriverAddr(void);
+void * MGLAPI SVGA8_getDriverAddr(void);
+void * MGLAPI SVGA16_getDriverAddr(void);
+void * MGLAPI SVGA24_getDriverAddr(void);
+void * MGLAPI SVGA32_getDriverAddr(void);
+#if !defined(__16BIT__)
+void * MGLAPI VGA8_getDriverAddr(void);
+void * MGLAPI LINEAR8_getDriverAddr(void);
+void * MGLAPI LINEAR16_getDriverAddr(void);
+void * MGLAPI LINEAR24_getDriverAddr(void);
+void * MGLAPI LINEAR32_getDriverAddr(void);
+void * MGLAPI ACCEL8_getDriverAddr(void);
+void * MGLAPI ACCEL16_getDriverAddr(void);
+void * MGLAPI ACCEL24_getDriverAddr(void);
+void * MGLAPI ACCEL32_getDriverAddr(void);
+#if defined(MGLWIN) || defined(__WINDOWS__)
+void * MGLAPI DDRAW8_getDriverAddr(void);
+void * MGLAPI DDRAW16_getDriverAddr(void);
+void * MGLAPI DDRAW24_getDriverAddr(void);
+void * MGLAPI DDRAW32_getDriverAddr(void);
+#endif
+#endif
+void * MGLAPI PACKED1_getDriverAddr(void);
+void * MGLAPI PACKED4_getDriverAddr(void);
+void * MGLAPI PACKED8_getDriverAddr(void);
+void * MGLAPI PACKED16_getDriverAddr(void);
+void * MGLAPI PACKED24_getDriverAddr(void);
+void * MGLAPI PACKED32_getDriverAddr(void);
+#define VGA4_driver			VGA4_getDriverAddr()
+#define VGAX_driver			VGAX_getDriverAddr()
+#define SVGA4_driver		SVGA4_getDriverAddr()
+#define SVGA8_driver		SVGA8_getDriverAddr()
+#define SVGA16_driver		SVGA16_getDriverAddr()
+#define SVGA24_driver		SVGA24_getDriverAddr()
+#define SVGA32_driver		SVGA32_getDriverAddr()
+#if !defined(__16BIT__)
+#define VGA8_driver			VGA8_getDriverAddr()
+#define LINEAR8_driver		LINEAR8_getDriverAddr()
+#define LINEAR16_driver		LINEAR16_getDriverAddr()
+#define LINEAR24_driver     LINEAR24_getDriverAddr()
+#define LINEAR32_driver     LINEAR32_getDriverAddr()
+#define ACCEL8_driver       ACCEL8_getDriverAddr()
+#define ACCEL16_driver      ACCEL16_getDriverAddr()
+#define ACCEL24_driver      ACCEL24_getDriverAddr()
+#define ACCEL32_driver      ACCEL32_getDriverAddr()
+#if defined(MGLWIN) || defined(__WINDOWS__)
+#define DDRAW8_driver       DDRAW8_getDriverAddr()
+#define DDRAW16_driver      DDRAW16_getDriverAddr()
+#define DDRAW24_driver      DDRAW24_getDriverAddr()
+#define DDRAW32_driver      DDRAW32_getDriverAddr()
+#endif
+#endif
+#define PACKED1_driver      PACKED1_getDriverAddr()
+#define PACKED4_driver      PACKED4_getDriverAddr()
+#define PACKED8_driver      PACKED8_getDriverAddr()
+#define PACKED16_driver     PACKED16_getDriverAddr()
+#define PACKED24_driver     PACKED24_getDriverAddr()
+#define PACKED32_driver		PACKED32_getDriverAddr()
+#else
+extern m_int _VARAPI VGA4_driver[];
+extern m_int _VARAPI VGAX_driver[];
+extern m_int _VARAPI SVGA4_driver[];
+extern m_int _VARAPI SVGA8_driver[];
+extern m_int _VARAPI SVGA16_driver[];
+extern m_int _VARAPI SVGA24_driver[];
+extern m_int _VARAPI SVGA32_driver[];
+#if !defined(__16BIT__)
+extern m_int _VARAPI VGA8_driver[];
+extern m_int _VARAPI LINEAR8_driver[];
+extern m_int _VARAPI LINEAR16_driver[];
+extern m_int _VARAPI LINEAR24_driver[];
+extern m_int _VARAPI LINEAR32_driver[];
+extern m_int _VARAPI ACCEL8_driver[];
+extern m_int _VARAPI ACCEL16_driver[];
+extern m_int _VARAPI ACCEL24_driver[];
+extern m_int _VARAPI ACCEL32_driver[];
+#if defined(MGLWIN) || defined(__WINDOWS__)
+extern m_int _VARAPI DDRAW8_driver[];
+extern m_int _VARAPI DDRAW16_driver[];
+extern m_int _VARAPI DDRAW24_driver[];
+extern m_int _VARAPI DDRAW32_driver[];
+#endif
+#endif
+extern m_int _VARAPI PACKED1_driver[];
+extern m_int _VARAPI PACKED4_driver[];
+extern m_int _VARAPI PACKED8_driver[];
+extern m_int _VARAPI PACKED16_driver[];
+extern m_int _VARAPI PACKED24_driver[];
+extern m_int _VARAPI PACKED32_driver[];
+#endif
+#endif
+
+/*---------------------------------------------------------------------------
+ * Memory allocation and utility functions.
+ *-------------------------------------------------------------------------*/
+
+#ifndef	__16BIT__
+#define	_HUGE
+#else
+#define	_HUGE	_huge
+#endif
+
+void MGL_availableMemory(ulong *physical,ulong *total);
+void MGL_useLocalMalloc(void _HUGE * (*malloc)(long size),void (*free)(void _HUGE *p));
+void * MGLAPI MGL_malloc(long size);
+void * MGLAPI MGL_calloc(long size,long n);
+void MGLAPI MGL_free(void _HUGE *p);
+void MGLAPI MGL_memset(void _HUGE *s,m_int c,long n);
+void MGLAPI MGL_memsetw(void _HUGE *s,m_int c,long n);
+void MGLAPI MGL_memsetl(void _HUGE *s,long c,long n);
+
+/*---------------------------------------------------------------------------
+ * Set a fullscreen suspend application callback function. This is used in
+ * fullscreen video modes to allow switching back to the normal operating
+ * system graphical shell (such as Windows GDI, OS/2 PM etc).
+ *-------------------------------------------------------------------------*/
+
+typedef m_int (ASMAPI *MGL_suspend_cb_t)(MGLDC *dc,m_int flags);
+void	MGLAPI MGL_setSuspendAppCallback(MGL_suspend_cb_t staveState);
+
+/*---------------------------------------------------------------------------
+ * Tell the MGL to use a pre-loaded ACCEL.DRV driver file. This allows
+ * you to link with the SciTech WinDirect/Pro and WinDirect/Ultra device
+ * support libraries and tell the MGL to use the device support drivers.
+ * If the user has a real ACCEL.DRV driver file in the standard location
+ * on their machine, this driver file will still be used.
+ *-------------------------------------------------------------------------*/
+
+void	MGLAPI MGL_setACCELDriver(void *driver);
+
+/*---------------------- Inline functions as Macros -----------------------*/
+
+#define	MGL_equalPoint(p1,p2)	((p1).x == (p2).x && (p1).y == (p2).y)
+
+#define	MGL_equalRect(r1,r2)	((r1).left == (r2).left &&			\
+								 (r1).top == (r2).top &&			\
+								 (r1).right == (r2).right &&		\
+								 (r1).bottom == (r2).bottom)
+
+#define	MGL_emptyRect(r)		((r).bottom <= (r).top || 			\
+								 (r).right <= (r).left)
+
+#define	MGL_disjointRect(r1,r2)	((r1).right <= (r2).left ||			\
+								 (r1).left >= (r2).right ||			\
+								 (r1).bottom <= (r2).top ||			\
+								 (r1).top >= (r2).bottom)
+
+#define	MGL_sectRect(s1,s2,d)										\
+   ((d)->left = MAX((s1).left,(s2).left),                           \
+	(d)->right = MIN((s1).right,(s2).right),                        \
+	(d)->top = MAX((s1).top,(s2).top),                              \
+	(d)->bottom = MIN((s1).bottom,(s2).bottom),                     \
+	!MGL_emptyRect(*d))
+
+#define	MGL_sectRectFast(s1,s2,d)									\
+	(d)->left = MAX((s1).left,(s2).left);                           \
+	(d)->right = MIN((s1).right,(s2).right);                        \
+	(d)->top = MAX((s1).top,(s2).top);                              \
+	(d)->bottom = MIN((s1).bottom,(s2).bottom)
+
+#define	MGL_sectRectCoord(l1,t1,r1,b1,l2,t2,r2,b2,d)				\
+   ((d)->left = MAX(l1,l2),											\
+	(d)->right = MIN(r1,r2),										\
+	(d)->top = MAX(t1,t2),											\
+	(d)->bottom = MIN(b1,b2),										\
+	!MGL_emptyRect(*d))
+
+#define	MGL_sectRectFastCoord(l1,t1,r1,b1,l2,t2,r2,b2,d)			\
+	(d)->left = MAX(l1,l2);											\
+	(d)->right = MIN(r1,r2);										\
+	(d)->top = MAX(t1,t2);											\
+	(d)->bottom = MIN(b1,b2)
+
+#define	MGL_unionRect(s1,s2,d)										\
+	(d)->left = MIN((s1).left,(s2).left);                           \
+	(d)->right = MAX((s1).right,(s2).right);                        \
+	(d)->top = MIN((s1).top,(s2).top);                              \
+	(d)->bottom = MAX((s1).bottom,(s2).bottom)
+
+#define MGL_unionRectCoord(l1,t1,r1,b1,l2,t2,r2,b2,d)				\
+	(d)->left = MIN(l1,l2);                                 		\
+	(d)->right = MAX(r1,r2);                              			\
+	(d)->top = MIN(t1,t2);                                    		\
+	(d)->bottom = MAX(b1,b2)
+
+#define	MGL_offsetRect(r,dx,dy)										\
+	{	(r).left += dx; (r).right += dx;							\
+		(r).top += dy; (r).bottom += dy; }
+
+#define	MGL_insetRect(r,dx,dy)										\
+	{	(r).left += dx; (r).right -= dx;							\
+		(r).top += dy; (r).bottom -= dy;							\
+		if (MGL_emptyRect(r))										\
+			(r).left = (r).right = (r).top = (r).bottom = 0; }
+
+#define	MGL_ptInRect(p,r)		((p).x >= (r).left &&				\
+								 (p).x < (r).right &&				\
+								 (p).y >= (r).top &&				\
+								 (p).y < (r).bottom)
+
+#define	MGL_ptInRectCoord(x,y,r)	((x) >= (r).left &&				\
+									 (x) < (r).right &&				\
+									 (y) >= (r).top &&				\
+									 (y) < (r).bottom)
+
+#define	MGL_ptInRegion(p,r)		MGL_ptInRegionCoord((p).x,(p).y,r)
+
+#define	MGL_pixel(p)			MGL_pixelCoord((p).x,(p).y)
+#define	MGL_getPixel(p)			MGL_getPixelCoord((p).x,(p).y)
+#define	MGL_pixelFast(p)		MGL_pixelCoordFast((p).x,(p).y)
+#define	MGL_getPixelFast(p)		MGL_getPixelCoordFast((p).x,(p).y)
+#define	MGL_moveTo(p)			MGL_moveToCoord((p).x,(p).y)
+#define MGL_moveRel(p)			MGL_moveRelCoord((p).x,(p).y)
+#define	MGL_line(p1,p2)			MGL_lineCoord((p1).x,(p1).y,(p2).x,(p2).y)
+#define	MGL_lineFast(p1,p2)		MGL_lineCoordFast((p1).x,(p1).y,(p2).x,(p2).y)
+#define	MGL_lineFX(p1,p2)		MGL_lineCoordFX((p1).x,(p1).y,(p2).x,(p2).y)
+#define	MGL_lineFastFX(p1,p2)	MGL_lineCoordFastFX((p1).x,(p1).y,(p2).x,(p2).y)
+#define	MGL_cLineFast(p1,p2)	MGL_cLineCoordFast((p1).p.x,(p1).p.y,(p1).c,(p2).p.x,(p2).p.y,(p2).c)
+#define	MGL_rgbLineFast(p1,p2)	MGL_rgbLineCoordFast((p1).p.x,(p1).p.y,(p1).c.r,(p1).c.g,(p1).c.b,(p2).p.x,(p2).p.y,(p2).c.r,(p2).c.g,(p2).c.b)
+#define	MGL_zLineFast(p1,p2)	MGL_zLineCoordFast((p1).p.x,(p1).p.y,(p1).z,(p2).p.x,(p2).p.y,(p2).z)
+#define	MGL_czLineFast(p1,p2)	MGL_czLineCoordFast((p1).p.x,(p1).p.y,(p1).z,(p1).c,(p2).p.x,(p2).p.y,(p2).z,(p2).c)
+#define	MGL_rgbzLineFast(p1,p2)	MGL_rgbzLineCoordFast((p1).p.x,(p1).p.y,(p1).z,(p1).c.r,(p1).c.g,(p1).c.b,(p2).p.x,(p2).p.y,(p2).z,(p2).c.r,(p2).c.g,(p2).c.b)
+
+#define	MGL_zClearPt(lt,rb,z)	MGL_zClearCoord((lt).x,(lt).y,	\
+									(rb).x,(rb).y,z)
+#define	MGL_zClear(r,z)			MGL_zClearCoord((r).left,(r).top,	\
+									(r).right,(r).bottom,z)
+#define	MGL_lineTo(p)			MGL_lineToCoord((p).x,(p).y)
+#define	MGL_lineRel(p)			MGL_lineRelCoord((p).x,(p).y);
+#define	MGL_rectPt(lt,rb)		MGL_rectCoord((lt).x,(lt).y,(rb).x,(rb).y)
+#define	MGL_rect(r)				MGL_rectCoord((r).left,(r).top,			\
+									(r).right,(r).bottom)
+#define	MGL_drawBorder(r,s,t)	MGL_drawBorderCoord((r).left,(r).top,	\
+									(r).right,(r).bottom,(s),(t))
+#define	MGL_fillRectPt(lt,rb)	MGL_fillRectCoord((lt).x,(lt).y,	\
+									(rb).x,(rb).y)
+#define	MGL_fillRect(r)			MGL_fillRectCoord((r).left,(r).top,	\
+									(r).right,(r).bottom)
+#define	MGL_bitBlt(d,s,r,dl,dt,op) 	MGL_bitBltCoord((d),(s),(r).left,		\
+									(r).top,(r).right,(r).bottom,dl,dt,op)
+#define	MGL_bitBltLin(d,s,so,r,op) MGL_bitBltLinCoord((d),(s),so,			\
+									(r).left,(r).top,(r).right,(r).bottom,op)
+#define	MGL_stretchBlt(d,s,sr,dr) 	MGL_stretchBltCoord((d),(s),(sr).left,		\
+									(sr).top,(sr).right,(sr).bottom,	\
+									(dr).left,(dr).top,(dr).right,(dr).bottom)
+#define	MGL_transBlt(d,s,r,dl,dt,c,st)	MGL_transBltCoord((d),(s),(r).left,		\
+									(r).top,(r).right,(r).bottom,dl,dt,c,st)
+#define	MGL_transBltLin(d,s,so,r,c,st) MGL_transBltLinCoord((d),(s),so,	\
+									(r).left,(r).top,(r).right,(r).bottom,c,st)
+#define	MGL_getDivot(dc,r,divot) MGL_getDivotCoord(dc,(r).left,(r).top,	\
+									(r).right,(r).bottom,divot)
+#define	MGL_divotSize(dc,r)		MGL_divotSizeCoord(dc,(r).left,(r).top,\
+									(r).right,(r).bottom)
+#define	MGL_isSimpleRegion(r)	(((region_t*)(r))->spans == NULL)
+#define	MGL_rgnLine(p1,p2,p)	MGL_rgnLineCoord((p1).x,(p1).y,(p2).x,(p2).y,p)
+#define	MGL_rgnLineFX(p1,p2,p)	MGL_rgnLineCoordFX((p1).x,(p1).y,(p2).x,(p2).y,p)
+#define	MGL_rgnSolidRectPt(lt,rb)	MGL_rgnSolidRectCoord((lt).x,(lt).y,	\
+									(rb).x,(rb).y)
+#define	MGL_rgnSolidRect(r)			MGL_rgnSolidRectCoord((r).left,(r).top,	\
+									(r).right,(r).bottom)
+
+/* Fast color packing/unpacking routines implemented as macros */
+
+#define	MGL_packColorFast(pf,R,G,B)													\
+ ((ulong)(((uchar)(R) >> (pf)->redAdjust) & (pf)->redMask) << (pf)->redPos)			\
+ | ((ulong)(((uchar)(G) >> (pf)->greenAdjust) & (pf)->greenMask) << (pf)->greenPos)	\
+ | ((ulong)(((uchar)(B) >> (pf)->blueAdjust) & (pf)->blueMask) << (pf)->bluePos)
+
+#define	MGL_unpackColorFast(pf,c,R,G,B)												\
+{																					\
+ (R) = (uchar)((((ulong)(c) >> (pf)->redPos) & (pf)->redMask) << (pf)->redAdjust);		\
+ (G) = (uchar)((((ulong)(c) >> (pf)->greenPos) & (pf)->greenMask) << (pf)->greenAdjust);\
+ (B) = (uchar)((((ulong)(c) >> (pf)->bluePos) & (pf)->blueMask) << (pf)->blueAdjust);	\
+}
+
+/* Macros to access the RGB components in a packed 24 bit RGB tuple */
+
+#define	MGL_rgbRed(c)	(((uchar*)&(c))[2])
+#define	MGL_rgbGreen(c)	(((uchar*)&(c))[1])
+#define	MGL_rgbBlue(c)	(((uchar*)&(c))[0])
+
+/* Fast 24 bit color packing/unpacking routines implemented as macros */
+
+#define	MGL_packColorRGBFast(R,G,B)											\
+ (((ulong)((uchar)(R)) << 16) | ((ulong)((uchar)(G)) << 8) | (uchar)(B))
+
+#define	MGL_packColorRGBFast2(c,R,G,B)										\
+{																			\
+ MGL_rgbRed(c) = (uchar)(R);												\
+ MGL_rgbGreen(c) = (uchar)(G);												\
+ MGL_rgbBlue(c) = (uchar)(B);												\
+}
+
+#define	MGL_unpackColorRGBFast(c,R,G,B)										\
+{																			\
+ (R) = MGL_rgbRed(c);														\
+ (G) = MGL_rgbGreen(c);														\
+ (B) = MGL_rgbBlue(c);														\
+}
+
+#ifdef	__cplusplus
+}						/* End of "C" linkage for C++	*/
+
+#include "mglrect.hpp"	/* Include C++ point/rectangle classes			*/
+
+#endif	/* __cplusplus */
+
+/* Include appropriate platform specific bindings */
+
+#if defined(MGLWIN) || defined(__WINDOWS__)
+#include "mglwin.h"
+#elif defined(MGLPM) || defined(__OS2__)
+/*#include "mglpm.h"*/
+#elif defined(MGLX) || defined(__UNIX__)
+/*#include "mglx.h"*/
+#else
+#include "mgldos.h"
+#endif
+
+#pragma pack()				/* Return to default packing				*/
+
+#endif	/* __MGRAPH_H */
binary files /dev/null b/QW/scitech/lib/win32/vc/mgllt.lib differ
--- /dev/null
+++ b/QW/server/asm_i386.h
@@ -1,0 +1,97 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+
+#ifndef __ASM_I386__
+#define __ASM_I386__
+
+#ifdef ELF
+#define C(label) label
+#else
+#define C(label) _##label
+#endif
+
+//
+// !!! note that this file must match the corresponding C structures at all
+// times !!!
+//
+
+// plane_t structure
+// !!! if this is changed, it must be changed in model.h too !!!
+// !!! if the size of this is changed, the array lookup in SV_HullPointContents
+//     must be changed too !!!
+#define pl_normal	0
+#define pl_dist		12
+#define pl_type		16
+#define pl_signbits	17
+#define pl_pad		18
+#define pl_size		20
+
+// hull_t structure
+// !!! if this is changed, it must be changed in model.h too !!!
+#define	hu_clipnodes		0
+#define	hu_planes			4
+#define	hu_firstclipnode	8
+#define	hu_lastclipnode		12
+#define	hu_clip_mins		16
+#define	hu_clip_maxs		28
+#define hu_size  			40
+
+// dnode_t structure
+// !!! if this is changed, it must be changed in bspfile.h too !!!
+#define	nd_planenum		0
+#define	nd_children		4
+#define	nd_mins			8
+#define	nd_maxs			20
+#define	nd_firstface	32
+#define	nd_numfaces		36
+#define nd_size			40
+
+// sfxcache_t structure
+// !!! if this is changed, it much be changed in sound.h too !!!
+#define sfxc_length		0
+#define sfxc_loopstart	4
+#define sfxc_speed		8
+#define sfxc_width		12
+#define sfxc_stereo		16
+#define sfxc_data		20
+
+// channel_t structure
+// !!! if this is changed, it much be changed in sound.h too !!!
+#define ch_sfx			0
+#define ch_leftvol		4
+#define ch_rightvol		8
+#define ch_end			12
+#define ch_pos			16
+#define ch_looping		20
+#define ch_entnum		24
+#define ch_entchannel	28
+#define ch_origin		32
+#define ch_dist_mult	44
+#define ch_master_vol	48
+#define ch_size			52
+
+// portable_samplepair_t structure
+// !!! if this is changed, it much be changed in sound.h too !!!
+#define psp_left		0
+#define psp_right		4
+#define psp_size		8
+
+#endif
+
--- /dev/null
+++ b/QW/server/makefile
@@ -1,0 +1,52 @@
+
+#CFLAGS = -g -Wall -DDEBUG -I../client -I. -DSERVERONLY
+#CFLAGS = -mpentium -O6 -Wall -I../client -I. -DSERVERONLY -fomit-frame-pointer -fno-strength-reduce
+#CFLAGS = -mpentium -O2 -Wall -I../client -I. -DSERVERONLY -fomit-frame-pointer -fno-strength-reduce
+CFLAGS=-DSERVERONLY -I../client -V2.7.2.1 -bi486-linux/ -O6 -Wall -fomit-frame-pointer -fno-strength-reduce
+
+EXE = qwsv
+
+OFILES =\
+         pr_cmds.o \
+		 pr_edict.o \
+		 pr_exec.o \
+		 sv_init.o \
+		 sv_main.o \
+		 sv_ents.o \
+		 sv_send.o \
+		 sv_move.o \
+		 sv_phys.o \
+		 sv_user.o \
+		 sv_ccmds.o \
+		 world.o \
+         sys_unix.o \
+		 model.o \
+		 cmd.o \
+		 common.o \
+		 crc.o \
+		 cvar.o \
+		 mathlib.o \
+		 zone.o \
+		 pmove.o \
+		 pmovetst.o \
+		 net_chan.o \
+		 net_udp.o 
+
+LDFLAGS = -lm
+
+$(EXE) : $(OFILES)
+	cc $(CFLAGS) -o $(EXE) $(OFILES) $(LDFLAGS) 
+
+clean:
+	rm -f $(OFILES) $(EXE)
+
+app:
+	make "CFLAGS = -O4 -g -Wall  -I../client  -DSERVERONLY"
+
+profile:
+	make "CFLAGS = -g -pg -O -Wall -I../client -DPROFILE"
+	cp $(EXE) /LocalApps
+
+.c.o: ; cc -c $(CFLAGS) -o $@ $*.c
+.s.o: ; cc -c $(CFLAGS) -o $@ $*.s
+
--- /dev/null
+++ b/QW/server/math.s
@@ -1,0 +1,331 @@
+//
+// math.s
+// x86 assembly-language math routines.
+
+#include "asm_i386.h"
+#include "quakeasm.h"
+
+
+#if id386
+
+	.data
+
+	.align	4
+Ljmptab:	.long	Lcase0, Lcase1, Lcase2, Lcase3
+			.long	Lcase4, Lcase5, Lcase6, Lcase7
+
+	.text
+
+
+#define EMINS	4+4
+#define EMAXS	4+8
+#define P		4+12
+
+	.align 2
+.globl C(BoxOnPlaneSide)
+C(BoxOnPlaneSide):
+	pushl	%ebx
+
+	movl	P(%esp),%edx
+	movl	EMINS(%esp),%ecx
+	xorl	%eax,%eax
+	movl	EMAXS(%esp),%ebx
+	movb	pl_signbits(%edx),%al
+	cmpl	$8,%al
+	jge		Lerror
+	flds	pl_normal(%edx)		// p->normal[0]
+	fld		%st(0)				// p->normal[0] | p->normal[0]
+	jmp		*Ljmptab(,%eax,4)
+
+
+//dist1= p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
+//dist2= p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
+Lcase0:
+	fmuls	(%ebx)				// p->normal[0]*emaxs[0] | p->normal[0]
+	flds	pl_normal+4(%edx)	// p->normal[1] | p->normal[0]*emaxs[0] |
+								//  p->normal[0]
+	fxch	%st(2)				// p->normal[0] | p->normal[0]*emaxs[0] |
+								//  p->normal[1]
+	fmuls	(%ecx)				// p->normal[0]*emins[0] |
+								//  p->normal[0]*emaxs[0] | p->normal[1]
+	fxch	%st(2)				// p->normal[1] | p->normal[0]*emaxs[0] |
+								//  p->normal[0]*emins[0]
+	fld		%st(0)				// p->normal[1] | p->normal[1] |
+								//  p->normal[0]*emaxs[0] |
+								//  p->normal[0]*emins[0]
+	fmuls	4(%ebx)				// p->normal[1]*emaxs[1] | p->normal[1] |
+								//  p->normal[0]*emaxs[0] |
+								//  p->normal[0]*emins[0]
+	flds	pl_normal+8(%edx)	// p->normal[2] | p->normal[1]*emaxs[1] |
+								//  p->normal[1] | p->normal[0]*emaxs[0] |
+								//  p->normal[0]*emins[0]
+	fxch	%st(2)				// p->normal[1] | p->normal[1]*emaxs[1] |
+								//  p->normal[2] | p->normal[0]*emaxs[0] |
+								//  p->normal[0]*emins[0]
+	fmuls	4(%ecx)				// p->normal[1]*emins[1] |
+								//  p->normal[1]*emaxs[1] |
+								//  p->normal[2] | p->normal[0]*emaxs[0] |
+								//  p->normal[0]*emins[0]
+	fxch	%st(2)				// p->normal[2] | p->normal[1]*emaxs[1] |
+								//  p->normal[1]*emins[1] |
+								//  p->normal[0]*emaxs[0] |
+								//  p->normal[0]*emins[0]
+	fld		%st(0)				// p->normal[2] | p->normal[2] |
+								//  p->normal[1]*emaxs[1] |
+								//  p->normal[1]*emins[1] |
+								//  p->normal[0]*emaxs[0] |
+								//  p->normal[0]*emins[0]
+	fmuls	8(%ebx)				// p->normal[2]*emaxs[2] |
+								//  p->normal[2] |
+								//  p->normal[1]*emaxs[1] |
+								//  p->normal[1]*emins[1] |
+								//  p->normal[0]*emaxs[0] |
+								//  p->normal[0]*emins[0]
+	fxch	%st(5)				// p->normal[0]*emins[0] |
+								//  p->normal[2] |
+								//  p->normal[1]*emaxs[1] |
+								//  p->normal[1]*emins[1] |
+								//  p->normal[0]*emaxs[0] |
+								//  p->normal[2]*emaxs[2]
+	faddp	%st(0),%st(3)		//p->normal[2] |
+								// p->normal[1]*emaxs[1] |
+								// p->normal[1]*emins[1]+p->normal[0]*emins[0]|
+								// p->normal[0]*emaxs[0] |
+								// p->normal[2]*emaxs[2]
+	fmuls	8(%ecx)				//p->normal[2]*emins[2] |
+								// p->normal[1]*emaxs[1] |
+								// p->normal[1]*emins[1]+p->normal[0]*emins[0]|
+								// p->normal[0]*emaxs[0] |
+								// p->normal[2]*emaxs[2]
+	fxch	%st(1)				//p->normal[1]*emaxs[1] |
+								// p->normal[2]*emins[2] |
+								// p->normal[1]*emins[1]+p->normal[0]*emins[0]|
+								// p->normal[0]*emaxs[0] |
+								// p->normal[2]*emaxs[2]
+	faddp	%st(0),%st(3)		//p->normal[2]*emins[2] |
+								// p->normal[1]*emins[1]+p->normal[0]*emins[0]|
+								// p->normal[0]*emaxs[0]+p->normal[1]*emaxs[1]|
+								// p->normal[2]*emaxs[2]
+	fxch	%st(3)				//p->normal[2]*emaxs[2] +
+								// p->normal[1]*emins[1]+p->normal[0]*emins[0]|
+								// p->normal[0]*emaxs[0]+p->normal[1]*emaxs[1]|
+								// p->normal[2]*emins[2]
+	faddp	%st(0),%st(2)		//p->normal[1]*emins[1]+p->normal[0]*emins[0]|
+								// dist1 | p->normal[2]*emins[2]
+
+	jmp		LSetSides
+
+//dist1= p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
+//dist2= p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
+Lcase1:
+	fmuls	(%ecx)				// emins[0]
+	flds	pl_normal+4(%edx)
+	fxch	%st(2)
+	fmuls	(%ebx)				// emaxs[0]
+	fxch	%st(2)
+	fld		%st(0)
+	fmuls	4(%ebx)				// emaxs[1]
+	flds	pl_normal+8(%edx)
+	fxch	%st(2)
+	fmuls	4(%ecx)				// emins[1]
+	fxch	%st(2)
+	fld		%st(0)
+	fmuls	8(%ebx)				// emaxs[2]
+	fxch	%st(5)
+	faddp	%st(0),%st(3)
+	fmuls	8(%ecx)				// emins[2]
+	fxch	%st(1)
+	faddp	%st(0),%st(3)
+	fxch	%st(3)
+	faddp	%st(0),%st(2)
+
+	jmp		LSetSides
+
+//dist1= p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
+//dist2= p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
+Lcase2:
+	fmuls	(%ebx)				// emaxs[0]
+	flds	pl_normal+4(%edx)
+	fxch	%st(2)
+	fmuls	(%ecx)				// emins[0]
+	fxch	%st(2)
+	fld		%st(0)
+	fmuls	4(%ecx)				// emins[1]
+	flds	pl_normal+8(%edx)
+	fxch	%st(2)
+	fmuls	4(%ebx)				// emaxs[1]
+	fxch	%st(2)
+	fld		%st(0)
+	fmuls	8(%ebx)				// emaxs[2]
+	fxch	%st(5)
+	faddp	%st(0),%st(3)
+	fmuls	8(%ecx)				// emins[2]
+	fxch	%st(1)
+	faddp	%st(0),%st(3)
+	fxch	%st(3)
+	faddp	%st(0),%st(2)
+
+	jmp		LSetSides
+
+//dist1= p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
+//dist2= p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
+Lcase3:
+	fmuls	(%ecx)				// emins[0]
+	flds	pl_normal+4(%edx)
+	fxch	%st(2)
+	fmuls	(%ebx)				// emaxs[0]
+	fxch	%st(2)
+	fld		%st(0)
+	fmuls	4(%ecx)				// emins[1]
+	flds	pl_normal+8(%edx)
+	fxch	%st(2)
+	fmuls	4(%ebx)				// emaxs[1]
+	fxch	%st(2)
+	fld		%st(0)
+	fmuls	8(%ebx)				// emaxs[2]
+	fxch	%st(5)
+	faddp	%st(0),%st(3)
+	fmuls	8(%ecx)				// emins[2]
+	fxch	%st(1)
+	faddp	%st(0),%st(3)
+	fxch	%st(3)
+	faddp	%st(0),%st(2)
+
+	jmp		LSetSides
+
+//dist1= p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
+//dist2= p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
+Lcase4:
+	fmuls	(%ebx)				// emaxs[0]
+	flds	pl_normal+4(%edx)
+	fxch	%st(2)
+	fmuls	(%ecx)				// emins[0]
+	fxch	%st(2)
+	fld		%st(0)
+	fmuls	4(%ebx)				// emaxs[1]
+	flds	pl_normal+8(%edx)
+	fxch	%st(2)
+	fmuls	4(%ecx)				// emins[1]
+	fxch	%st(2)
+	fld		%st(0)
+	fmuls	8(%ecx)				// emins[2]
+	fxch	%st(5)
+	faddp	%st(0),%st(3)
+	fmuls	8(%ebx)				// emaxs[2]
+	fxch	%st(1)
+	faddp	%st(0),%st(3)
+	fxch	%st(3)
+	faddp	%st(0),%st(2)
+
+	jmp		LSetSides
+
+//dist1= p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
+//dist2= p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
+Lcase5:
+	fmuls	(%ecx)				// emins[0]
+	flds	pl_normal+4(%edx)
+	fxch	%st(2)
+	fmuls	(%ebx)				// emaxs[0]
+	fxch	%st(2)
+	fld		%st(0)
+	fmuls	4(%ebx)				// emaxs[1]
+	flds	pl_normal+8(%edx)
+	fxch	%st(2)
+	fmuls	4(%ecx)				// emins[1]
+	fxch	%st(2)
+	fld		%st(0)
+	fmuls	8(%ecx)				// emins[2]
+	fxch	%st(5)
+	faddp	%st(0),%st(3)
+	fmuls	8(%ebx)				// emaxs[2]
+	fxch	%st(1)
+	faddp	%st(0),%st(3)
+	fxch	%st(3)
+	faddp	%st(0),%st(2)
+
+	jmp		LSetSides
+
+//dist1= p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
+//dist2= p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
+Lcase6:
+	fmuls	(%ebx)				// emaxs[0]
+	flds	pl_normal+4(%edx)
+	fxch	%st(2)
+	fmuls	(%ecx)				// emins[0]
+	fxch	%st(2)
+	fld		%st(0)
+	fmuls	4(%ecx)				// emins[1]
+	flds	pl_normal+8(%edx)
+	fxch	%st(2)
+	fmuls	4(%ebx)				// emaxs[1]
+	fxch	%st(2)
+	fld		%st(0)
+	fmuls	8(%ecx)				// emins[2]
+	fxch	%st(5)
+	faddp	%st(0),%st(3)
+	fmuls	8(%ebx)				// emaxs[2]
+	fxch	%st(1)
+	faddp	%st(0),%st(3)
+	fxch	%st(3)
+	faddp	%st(0),%st(2)
+
+	jmp		LSetSides
+
+//dist1= p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
+//dist2= p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
+Lcase7:
+	fmuls	(%ecx)				// emins[0]
+	flds	pl_normal+4(%edx)
+	fxch	%st(2)
+	fmuls	(%ebx)				// emaxs[0]
+	fxch	%st(2)
+	fld		%st(0)
+	fmuls	4(%ecx)				// emins[1]
+	flds	pl_normal+8(%edx)
+	fxch	%st(2)
+	fmuls	4(%ebx)				// emaxs[1]
+	fxch	%st(2)
+	fld		%st(0)
+	fmuls	8(%ecx)				// emins[2]
+	fxch	%st(5)
+	faddp	%st(0),%st(3)
+	fmuls	8(%ebx)				// emaxs[2]
+	fxch	%st(1)
+	faddp	%st(0),%st(3)
+	fxch	%st(3)
+	faddp	%st(0),%st(2)
+
+LSetSides:
+
+//	sides = 0;
+//	if (dist1 >= p->dist)
+//		sides = 1;
+//	if (dist2 < p->dist)
+//		sides |= 2;
+
+	faddp	%st(0),%st(2)		// dist1 | dist2
+	fcomps	pl_dist(%edx)
+	xorl	%ecx,%ecx
+	fnstsw	%ax
+	fcomps	pl_dist(%edx)
+	andb	$1,%ah
+	xorb	$1,%ah
+	addb	%ah,%cl
+
+	fnstsw	%ax
+	andb	$1,%ah
+	addb	%ah,%ah
+	addb	%ah,%cl
+
+//	return sides;
+
+	popl	%ebx
+	movl	%ecx,%eax	// return status
+
+	ret
+
+
+Lerror:
+	call	C(BOPS_Error)
+
+#endif	// id386
--- /dev/null
+++ b/QW/server/model.c
@@ -1,0 +1,1137 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// models.c -- model loading and caching
+
+// models are the only shared resource between a client and server running
+// on the same machine.
+
+#include "qwsvdef.h"
+
+model_t	*loadmodel;
+char	loadname[32];	// for hunk tags
+
+void Mod_LoadSpriteModel (model_t *mod, void *buffer);
+void Mod_LoadBrushModel (model_t *mod, void *buffer);
+void Mod_LoadAliasModel (model_t *mod, void *buffer);
+model_t *Mod_LoadModel (model_t *mod, qboolean crash);
+
+byte	mod_novis[MAX_MAP_LEAFS/8];
+
+#define	MAX_MOD_KNOWN	256
+model_t	mod_known[MAX_MOD_KNOWN];
+int		mod_numknown;
+
+texture_t	r_notexture_mip;
+
+unsigned *model_checksum;
+
+/*
+===============
+Mod_Init
+===============
+*/
+void Mod_Init (void)
+{
+	memset (mod_novis, 0xff, sizeof(mod_novis));
+}
+
+/*
+===============
+Mod_PointInLeaf
+===============
+*/
+mleaf_t *Mod_PointInLeaf (vec3_t p, model_t *model)
+{
+	mnode_t		*node;
+	float		d;
+	mplane_t	*plane;
+	
+	if (!model || !model->nodes)
+		SV_Error ("Mod_PointInLeaf: bad model");
+
+	node = model->nodes;
+	while (1)
+	{
+		if (node->contents < 0)
+			return (mleaf_t *)node;
+		plane = node->plane;
+		d = DotProduct (p,plane->normal) - plane->dist;
+		if (d > 0)
+			node = node->children[0];
+		else
+			node = node->children[1];
+	}
+	
+	return NULL;	// never reached
+}
+
+
+/*
+===================
+Mod_DecompressVis
+===================
+*/
+byte *Mod_DecompressVis (byte *in, model_t *model)
+{
+	static byte	decompressed[MAX_MAP_LEAFS/8];
+	int		c;
+	byte	*out;
+	int		row;
+
+	row = (model->numleafs+7)>>3;	
+	out = decompressed;
+
+#if 0
+	memcpy (out, in, row);
+#else
+	if (!in)
+	{	// no vis info, so make all visible
+		while (row)
+		{
+			*out++ = 0xff;
+			row--;
+		}
+		return decompressed;		
+	}
+
+	do
+	{
+		if (*in)
+		{
+			*out++ = *in++;
+			continue;
+		}
+	
+		c = in[1];
+		in += 2;
+		while (c)
+		{
+			*out++ = 0;
+			c--;
+		}
+	} while (out - decompressed < row);
+#endif
+	
+	return decompressed;
+}
+
+byte *Mod_LeafPVS (mleaf_t *leaf, model_t *model)
+{
+	if (leaf == model->leafs)
+		return mod_novis;
+	return Mod_DecompressVis (leaf->compressed_vis, model);
+}
+
+/*
+===================
+Mod_ClearAll
+===================
+*/
+void Mod_ClearAll (void)
+{
+	int		i;
+	model_t	*mod;
+	
+	for (i=0 , mod=mod_known ; i<mod_numknown ; i++, mod++)
+		if (mod->type != mod_alias)
+			mod->needload = true;
+}
+
+/*
+==================
+Mod_FindName
+
+==================
+*/
+model_t *Mod_FindName (char *name)
+{
+	int		i;
+	model_t	*mod;
+	
+	if (!name[0])
+		SV_Error ("Mod_ForName: NULL name");
+		
+//
+// search the currently loaded models
+//
+	for (i=0 , mod=mod_known ; i<mod_numknown ; i++, mod++)
+		if (!strcmp (mod->name, name) )
+			break;
+			
+	if (i == mod_numknown)
+	{
+		if (mod_numknown == MAX_MOD_KNOWN)
+			SV_Error ("mod_numknown == MAX_MOD_KNOWN");
+		strcpy (mod->name, name);
+		mod->needload = true;
+		mod_numknown++;
+	}
+
+	return mod;
+}
+
+
+/*
+==================
+Mod_LoadModel
+
+Loads a model into the cache
+==================
+*/
+model_t *Mod_LoadModel (model_t *mod, qboolean crash)
+{
+	void	*d;
+	unsigned *buf;
+	byte	stackbuf[1024];		// avoid dirtying the cache heap
+
+	if (!mod->needload)
+	{
+		if (mod->type == mod_alias)
+		{
+			d = Cache_Check (&mod->cache);
+			if (d)
+				return mod;
+		}
+		else
+			return mod;		// not cached at all
+	}
+	
+//
+// load the file
+//
+	buf = (unsigned *)COM_LoadStackFile (mod->name, stackbuf, sizeof(stackbuf));
+	if (!buf)
+	{
+		if (crash)
+			SV_Error ("Mod_NumForName: %s not found", mod->name);
+		return NULL;
+	}
+	
+//
+// allocate a new model
+//
+	COM_FileBase (mod->name, loadname);
+	
+	loadmodel = mod;
+
+//
+// fill it in
+//
+
+// call the apropriate loader
+	mod->needload = false;
+	
+	Mod_LoadBrushModel (mod, buf);
+
+	return mod;
+}
+
+/*
+==================
+Mod_ForName
+
+Loads in a model for the given name
+==================
+*/
+model_t *Mod_ForName (char *name, qboolean crash)
+{
+	model_t	*mod;
+	
+	mod = Mod_FindName (name);
+	
+	return Mod_LoadModel (mod, crash);
+}
+
+
+/*
+===============================================================================
+
+					BRUSHMODEL LOADING
+
+===============================================================================
+*/
+
+byte	*mod_base;
+
+
+/*
+=================
+Mod_LoadTextures
+=================
+*/
+void Mod_LoadTextures (lump_t *l)
+{
+	int		i, j, pixels, num, max, altmax;
+	miptex_t	*mt;
+	texture_t	*tx, *tx2;
+	texture_t	*anims[10];
+	texture_t	*altanims[10];
+	dmiptexlump_t *m;
+
+	if (!l->filelen)
+	{
+		loadmodel->textures = NULL;
+		return;
+	}
+	m = (dmiptexlump_t *)(mod_base + l->fileofs);
+	
+	m->nummiptex = LittleLong (m->nummiptex);
+	
+	loadmodel->numtextures = m->nummiptex;
+	loadmodel->textures = Hunk_AllocName (m->nummiptex * sizeof(*loadmodel->textures) , loadname);
+
+	for (i=0 ; i<m->nummiptex ; i++)
+	{
+		m->dataofs[i] = LittleLong(m->dataofs[i]);
+		if (m->dataofs[i] == -1)
+			continue;
+		mt = (miptex_t *)((byte *)m + m->dataofs[i]);
+		mt->width = LittleLong (mt->width);
+		mt->height = LittleLong (mt->height);
+		for (j=0 ; j<MIPLEVELS ; j++)
+			mt->offsets[j] = LittleLong (mt->offsets[j]);
+		
+		if ( (mt->width & 15) || (mt->height & 15) )
+			SV_Error ("Texture %s is not 16 aligned", mt->name);
+		pixels = mt->width*mt->height/64*85;
+		tx = Hunk_AllocName (sizeof(texture_t) +pixels, loadname );
+		loadmodel->textures[i] = tx;
+
+		memcpy (tx->name, mt->name, sizeof(tx->name));
+		tx->width = mt->width;
+		tx->height = mt->height;
+		for (j=0 ; j<MIPLEVELS ; j++)
+			tx->offsets[j] = mt->offsets[j] + sizeof(texture_t) - sizeof(miptex_t);
+		// the pixels immediately follow the structures
+		memcpy ( tx+1, mt+1, pixels);
+	}
+
+//
+// sequence the animations
+//
+	for (i=0 ; i<m->nummiptex ; i++)
+	{
+		tx = loadmodel->textures[i];
+		if (!tx || tx->name[0] != '+')
+			continue;
+		if (tx->anim_next)
+			continue;	// allready sequenced
+
+	// find the number of frames in the animation
+		memset (anims, 0, sizeof(anims));
+		memset (altanims, 0, sizeof(altanims));
+
+		max = tx->name[1];
+		altmax = 0;
+		if (max >= 'a' && max <= 'z')
+			max -= 'a' - 'A';
+		if (max >= '0' && max <= '9')
+		{
+			max -= '0';
+			altmax = 0;
+			anims[max] = tx;
+			max++;
+		}
+		else if (max >= 'A' && max <= 'J')
+		{
+			altmax = max - 'A';
+			max = 0;
+			altanims[altmax] = tx;
+			altmax++;
+		}
+		else
+			SV_Error ("Bad animating texture %s", tx->name);
+
+		for (j=i+1 ; j<m->nummiptex ; j++)
+		{
+			tx2 = loadmodel->textures[j];
+			if (!tx2 || tx2->name[0] != '+')
+				continue;
+			if (strcmp (tx2->name+2, tx->name+2))
+				continue;
+
+			num = tx2->name[1];
+			if (num >= 'a' && num <= 'z')
+				num -= 'a' - 'A';
+			if (num >= '0' && num <= '9')
+			{
+				num -= '0';
+				anims[num] = tx2;
+				if (num+1 > max)
+					max = num + 1;
+			}
+			else if (num >= 'A' && num <= 'J')
+			{
+				num = num - 'A';
+				altanims[num] = tx2;
+				if (num+1 > altmax)
+					altmax = num+1;
+			}
+			else
+				SV_Error ("Bad animating texture %s", tx->name);
+		}
+		
+#define	ANIM_CYCLE	2
+	// link them all together
+		for (j=0 ; j<max ; j++)
+		{
+			tx2 = anims[j];
+			if (!tx2)
+				SV_Error ("Missing frame %i of %s",j, tx->name);
+			tx2->anim_total = max * ANIM_CYCLE;
+			tx2->anim_min = j * ANIM_CYCLE;
+			tx2->anim_max = (j+1) * ANIM_CYCLE;
+			tx2->anim_next = anims[ (j+1)%max ];
+			if (altmax)
+				tx2->alternate_anims = altanims[0];
+		}
+		for (j=0 ; j<altmax ; j++)
+		{
+			tx2 = altanims[j];
+			if (!tx2)
+				SV_Error ("Missing frame %i of %s",j, tx->name);
+			tx2->anim_total = altmax * ANIM_CYCLE;
+			tx2->anim_min = j * ANIM_CYCLE;
+			tx2->anim_max = (j+1) * ANIM_CYCLE;
+			tx2->anim_next = altanims[ (j+1)%altmax ];
+			if (max)
+				tx2->alternate_anims = anims[0];
+		}
+	}
+}
+
+/*
+=================
+Mod_LoadLighting
+=================
+*/
+void Mod_LoadLighting (lump_t *l)
+{
+	if (!l->filelen)
+	{
+		loadmodel->lightdata = NULL;
+		return;
+	}
+	loadmodel->lightdata = Hunk_AllocName ( l->filelen, loadname);	
+	memcpy (loadmodel->lightdata, mod_base + l->fileofs, l->filelen);
+}
+
+
+/*
+=================
+Mod_LoadVisibility
+=================
+*/
+void Mod_LoadVisibility (lump_t *l)
+{
+	if (!l->filelen)
+	{
+		loadmodel->visdata = NULL;
+		return;
+	}
+	loadmodel->visdata = Hunk_AllocName ( l->filelen, loadname);	
+	memcpy (loadmodel->visdata, mod_base + l->fileofs, l->filelen);
+}
+
+
+/*
+=================
+Mod_LoadEntities
+=================
+*/
+void Mod_LoadEntities (lump_t *l)
+{
+	if (!l->filelen)
+	{
+		loadmodel->entities = NULL;
+		return;
+	}
+	loadmodel->entities = Hunk_AllocName ( l->filelen, loadname);	
+	memcpy (loadmodel->entities, mod_base + l->fileofs, l->filelen);
+}
+
+
+/*
+=================
+Mod_LoadVertexes
+=================
+*/
+void Mod_LoadVertexes (lump_t *l)
+{
+	dvertex_t	*in;
+	mvertex_t	*out;
+	int			i, count;
+
+	in = (void *)(mod_base + l->fileofs);
+	if (l->filelen % sizeof(*in))
+		SV_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
+	count = l->filelen / sizeof(*in);
+	out = Hunk_AllocName ( count*sizeof(*out), loadname);	
+
+	loadmodel->vertexes = out;
+	loadmodel->numvertexes = count;
+
+	for ( i=0 ; i<count ; i++, in++, out++)
+	{
+		out->position[0] = LittleFloat (in->point[0]);
+		out->position[1] = LittleFloat (in->point[1]);
+		out->position[2] = LittleFloat (in->point[2]);
+	}
+}
+
+/*
+=================
+Mod_LoadSubmodels
+=================
+*/
+void Mod_LoadSubmodels (lump_t *l)
+{
+	dmodel_t	*in;
+	dmodel_t	*out;
+	int			i, j, count;
+
+	in = (void *)(mod_base + l->fileofs);
+	if (l->filelen % sizeof(*in))
+		SV_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
+	count = l->filelen / sizeof(*in);
+	out = Hunk_AllocName ( count*sizeof(*out), loadname);	
+
+	loadmodel->submodels = out;
+	loadmodel->numsubmodels = count;
+
+	for ( i=0 ; i<count ; i++, in++, out++)
+	{
+		for (j=0 ; j<3 ; j++)
+		{	// spread the mins / maxs by a pixel
+			out->mins[j] = LittleFloat (in->mins[j]) - 1;
+			out->maxs[j] = LittleFloat (in->maxs[j]) + 1;
+			out->origin[j] = LittleFloat (in->origin[j]);
+		}
+		for (j=0 ; j<MAX_MAP_HULLS ; j++)
+			out->headnode[j] = LittleLong (in->headnode[j]);
+		out->visleafs = LittleLong (in->visleafs);
+		out->firstface = LittleLong (in->firstface);
+		out->numfaces = LittleLong (in->numfaces);
+	}
+}
+
+/*
+=================
+Mod_LoadEdges
+=================
+*/
+void Mod_LoadEdges (lump_t *l)
+{
+	dedge_t *in;
+	medge_t *out;
+	int 	i, count;
+
+	in = (void *)(mod_base + l->fileofs);
+	if (l->filelen % sizeof(*in))
+		SV_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
+	count = l->filelen / sizeof(*in);
+	out = Hunk_AllocName ( (count + 1) * sizeof(*out), loadname);	
+
+	loadmodel->edges = out;
+	loadmodel->numedges = count;
+
+	for ( i=0 ; i<count ; i++, in++, out++)
+	{
+		out->v[0] = (unsigned short)LittleShort(in->v[0]);
+		out->v[1] = (unsigned short)LittleShort(in->v[1]);
+	}
+}
+
+/*
+=================
+Mod_LoadTexinfo
+=================
+*/
+void Mod_LoadTexinfo (lump_t *l)
+{
+	texinfo_t *in;
+	mtexinfo_t *out;
+	int 	i, j, count;
+	int		miptex;
+	float	len1, len2;
+
+	in = (void *)(mod_base + l->fileofs);
+	if (l->filelen % sizeof(*in))
+		SV_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
+	count = l->filelen / sizeof(*in);
+	out = Hunk_AllocName ( count*sizeof(*out), loadname);	
+
+	loadmodel->texinfo = out;
+	loadmodel->numtexinfo = count;
+
+	for ( i=0 ; i<count ; i++, in++, out++)
+	{
+#if 0
+		for (j=0 ; j<8 ; j++)
+			out->vecs[0][j] = LittleFloat (in->vecs[0][j]);
+		len1 = Length (in->vecs[0]);
+		len2 = Length (in->vecs[1]);
+#else
+		for (j=0 ; j<4 ; j++) {
+			out->vecs[0][j] = LittleFloat (in->vecs[0][j]);
+			out->vecs[1][j] = LittleFloat (in->vecs[1][j]);
+		}
+		len1 = Length (out->vecs[0]);
+		len2 = Length (out->vecs[1]);
+#endif
+		if (len1 + len2 < 2 /*0.001*/)
+			out->mipadjust = 1;
+		else
+			out->mipadjust = 1 / floor( (len1+len2)/2 );
+
+		miptex = LittleLong (in->miptex);
+		out->flags = LittleLong (in->flags);
+	
+		if (!loadmodel->textures)
+		{
+			out->texture = &r_notexture_mip;	// checkerboard texture
+			out->flags = 0;
+		}
+		else
+		{
+			if (miptex >= loadmodel->numtextures)
+				SV_Error ("miptex >= loadmodel->numtextures");
+			out->texture = loadmodel->textures[miptex];
+			if (!out->texture)
+			{
+				out->texture = &r_notexture_mip; // texture not found
+				out->flags = 0;
+			}
+		}
+	}
+}
+
+/*
+================
+CalcSurfaceExtents
+
+Fills in s->texturemins[] and s->extents[]
+================
+*/
+void CalcSurfaceExtents (msurface_t *s)
+{
+	float	mins[2], maxs[2], val;
+	int		i,j, e;
+	mvertex_t	*v;
+	mtexinfo_t	*tex;
+	int		bmins[2], bmaxs[2];
+
+	mins[0] = mins[1] = 999999;
+	maxs[0] = maxs[1] = -99999;
+
+	tex = s->texinfo;
+	
+	for (i=0 ; i<s->numedges ; i++)
+	{
+		e = loadmodel->surfedges[s->firstedge+i];
+		if (e >= 0)
+			v = &loadmodel->vertexes[loadmodel->edges[e].v[0]];
+		else
+			v = &loadmodel->vertexes[loadmodel->edges[-e].v[1]];
+		
+		for (j=0 ; j<2 ; j++)
+		{
+			val = v->position[0] * tex->vecs[j][0] + 
+				v->position[1] * tex->vecs[j][1] +
+				v->position[2] * tex->vecs[j][2] +
+				tex->vecs[j][3];
+			if (val < mins[j])
+				mins[j] = val;
+			if (val > maxs[j])
+				maxs[j] = val;
+		}
+	}
+
+	for (i=0 ; i<2 ; i++)
+	{	
+		bmins[i] = floor(mins[i]/16);
+		bmaxs[i] = ceil(maxs[i]/16);
+
+		s->texturemins[i] = bmins[i] * 16;
+		s->extents[i] = (bmaxs[i] - bmins[i]) * 16;
+		if ( !(tex->flags & TEX_SPECIAL) && s->extents[i] > 256)
+			SV_Error ("Bad surface extents");
+	}
+}
+
+
+/*
+=================
+Mod_LoadFaces
+=================
+*/
+void Mod_LoadFaces (lump_t *l)
+{
+	dface_t		*in;
+	msurface_t 	*out;
+	int			i, count, surfnum;
+	int			planenum, side;
+
+	in = (void *)(mod_base + l->fileofs);
+	if (l->filelen % sizeof(*in))
+		SV_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
+	count = l->filelen / sizeof(*in);
+	out = Hunk_AllocName ( count*sizeof(*out), loadname);	
+
+	loadmodel->surfaces = out;
+	loadmodel->numsurfaces = count;
+
+	for ( surfnum=0 ; surfnum<count ; surfnum++, in++, out++)
+	{
+		out->firstedge = LittleLong(in->firstedge);
+		out->numedges = LittleShort(in->numedges);		
+		out->flags = 0;
+
+		planenum = LittleShort(in->planenum);
+		side = LittleShort(in->side);
+		if (side)
+			out->flags |= SURF_PLANEBACK;			
+
+		out->plane = loadmodel->planes + planenum;
+
+		out->texinfo = loadmodel->texinfo + LittleShort (in->texinfo);
+
+		CalcSurfaceExtents (out);
+				
+	// lighting info
+
+		for (i=0 ; i<MAXLIGHTMAPS ; i++)
+			out->styles[i] = in->styles[i];
+		i = LittleLong(in->lightofs);
+		if (i == -1)
+			out->samples = NULL;
+		else
+			out->samples = loadmodel->lightdata + i;
+		
+	// set the drawing flags flag
+		
+		if (!Q_strncmp(out->texinfo->texture->name,"sky",3))	// sky
+		{
+			out->flags |= (SURF_DRAWSKY | SURF_DRAWTILED);
+			continue;
+		}
+		
+		if (!Q_strncmp(out->texinfo->texture->name,"*",1))		// turbulent
+		{
+			out->flags |= (SURF_DRAWTURB | SURF_DRAWTILED);
+			for (i=0 ; i<2 ; i++)
+			{
+				out->extents[i] = 16384;
+				out->texturemins[i] = -8192;
+			}
+			continue;
+		}
+	}
+}
+
+
+/*
+=================
+Mod_SetParent
+=================
+*/
+void Mod_SetParent (mnode_t *node, mnode_t *parent)
+{
+	node->parent = parent;
+	if (node->contents < 0)
+		return;
+	Mod_SetParent (node->children[0], node);
+	Mod_SetParent (node->children[1], node);
+}
+
+/*
+=================
+Mod_LoadNodes
+=================
+*/
+void Mod_LoadNodes (lump_t *l)
+{
+	int			i, j, count, p;
+	dnode_t		*in;
+	mnode_t 	*out;
+
+	in = (void *)(mod_base + l->fileofs);
+	if (l->filelen % sizeof(*in))
+		SV_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
+	count = l->filelen / sizeof(*in);
+	out = Hunk_AllocName ( count*sizeof(*out), loadname);	
+
+	loadmodel->nodes = out;
+	loadmodel->numnodes = count;
+
+	for ( i=0 ; i<count ; i++, in++, out++)
+	{
+		for (j=0 ; j<3 ; j++)
+		{
+			out->minmaxs[j] = LittleShort (in->mins[j]);
+			out->minmaxs[3+j] = LittleShort (in->maxs[j]);
+		}
+	
+		p = LittleLong(in->planenum);
+		out->plane = loadmodel->planes + p;
+
+		out->firstsurface = LittleShort (in->firstface);
+		out->numsurfaces = LittleShort (in->numfaces);
+		
+		for (j=0 ; j<2 ; j++)
+		{
+			p = LittleShort (in->children[j]);
+			if (p >= 0)
+				out->children[j] = loadmodel->nodes + p;
+			else
+				out->children[j] = (mnode_t *)(loadmodel->leafs + (-1 - p));
+		}
+	}
+	
+	Mod_SetParent (loadmodel->nodes, NULL);	// sets nodes and leafs
+}
+
+/*
+=================
+Mod_LoadLeafs
+=================
+*/
+void Mod_LoadLeafs (lump_t *l)
+{
+	dleaf_t 	*in;
+	mleaf_t 	*out;
+	int			i, j, count, p;
+
+	in = (void *)(mod_base + l->fileofs);
+	if (l->filelen % sizeof(*in))
+		SV_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
+	count = l->filelen / sizeof(*in);
+	out = Hunk_AllocName ( count*sizeof(*out), loadname);	
+
+	loadmodel->leafs = out;
+	loadmodel->numleafs = count;
+
+	for ( i=0 ; i<count ; i++, in++, out++)
+	{
+		for (j=0 ; j<3 ; j++)
+		{
+			out->minmaxs[j] = LittleShort (in->mins[j]);
+			out->minmaxs[3+j] = LittleShort (in->maxs[j]);
+		}
+
+		p = LittleLong(in->contents);
+		out->contents = p;
+
+		out->firstmarksurface = loadmodel->marksurfaces +
+			LittleShort(in->firstmarksurface);
+		out->nummarksurfaces = LittleShort(in->nummarksurfaces);
+		
+		p = LittleLong(in->visofs);
+		if (p == -1)
+			out->compressed_vis = NULL;
+		else
+			out->compressed_vis = loadmodel->visdata + p;
+		out->efrags = NULL;
+		
+		for (j=0 ; j<4 ; j++)
+			out->ambient_sound_level[j] = in->ambient_level[j];
+	}	
+}
+
+/*
+=================
+Mod_LoadClipnodes
+=================
+*/
+void Mod_LoadClipnodes (lump_t *l)
+{
+	dclipnode_t *in, *out;
+	int			i, count;
+	hull_t		*hull;
+
+	in = (void *)(mod_base + l->fileofs);
+	if (l->filelen % sizeof(*in))
+		SV_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
+	count = l->filelen / sizeof(*in);
+	out = Hunk_AllocName ( count*sizeof(*out), loadname);	
+
+	loadmodel->clipnodes = out;
+	loadmodel->numclipnodes = count;
+
+	hull = &loadmodel->hulls[1];
+	hull->clipnodes = out;
+	hull->firstclipnode = 0;
+	hull->lastclipnode = count-1;
+	hull->planes = loadmodel->planes;
+	hull->clip_mins[0] = -16;
+	hull->clip_mins[1] = -16;
+	hull->clip_mins[2] = -24;
+	hull->clip_maxs[0] = 16;
+	hull->clip_maxs[1] = 16;
+	hull->clip_maxs[2] = 32;
+
+	hull = &loadmodel->hulls[2];
+	hull->clipnodes = out;
+	hull->firstclipnode = 0;
+	hull->lastclipnode = count-1;
+	hull->planes = loadmodel->planes;
+	hull->clip_mins[0] = -32;
+	hull->clip_mins[1] = -32;
+	hull->clip_mins[2] = -24;
+	hull->clip_maxs[0] = 32;
+	hull->clip_maxs[1] = 32;
+	hull->clip_maxs[2] = 64;
+
+	for (i=0 ; i<count ; i++, out++, in++)
+	{
+		out->planenum = LittleLong(in->planenum);
+		out->children[0] = LittleShort(in->children[0]);
+		out->children[1] = LittleShort(in->children[1]);
+	}
+}
+
+/*
+=================
+Mod_MakeHull0
+
+Deplicate the drawing hull structure as a clipping hull
+=================
+*/
+void Mod_MakeHull0 (void)
+{
+	mnode_t		*in, *child;
+	dclipnode_t *out;
+	int			i, j, count;
+	hull_t		*hull;
+	
+	hull = &loadmodel->hulls[0];	
+	
+	in = loadmodel->nodes;
+	count = loadmodel->numnodes;
+	out = Hunk_AllocName ( count*sizeof(*out), loadname);	
+
+	hull->clipnodes = out;
+	hull->firstclipnode = 0;
+	hull->lastclipnode = count-1;
+	hull->planes = loadmodel->planes;
+
+	for (i=0 ; i<count ; i++, out++, in++)
+	{
+		out->planenum = in->plane - loadmodel->planes;
+		for (j=0 ; j<2 ; j++)
+		{
+			child = in->children[j];
+			if (child->contents < 0)
+				out->children[j] = child->contents;
+			else
+				out->children[j] = child - loadmodel->nodes;
+		}
+	}
+}
+
+/*
+=================
+Mod_LoadMarksurfaces
+=================
+*/
+void Mod_LoadMarksurfaces (lump_t *l)
+{	
+	int		i, j, count;
+	short		*in;
+	msurface_t **out;
+	
+	in = (void *)(mod_base + l->fileofs);
+	if (l->filelen % sizeof(*in))
+		SV_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
+	count = l->filelen / sizeof(*in);
+	out = Hunk_AllocName ( count*sizeof(*out), loadname);	
+
+	loadmodel->marksurfaces = out;
+	loadmodel->nummarksurfaces = count;
+
+	for ( i=0 ; i<count ; i++)
+	{
+		j = LittleShort(in[i]);
+		if (j >= loadmodel->numsurfaces)
+			SV_Error ("Mod_ParseMarksurfaces: bad surface number");
+		out[i] = loadmodel->surfaces + j;
+	}
+}
+
+/*
+=================
+Mod_LoadSurfedges
+=================
+*/
+void Mod_LoadSurfedges (lump_t *l)
+{	
+	int		i, count;
+	int		*in, *out;
+	
+	in = (void *)(mod_base + l->fileofs);
+	if (l->filelen % sizeof(*in))
+		SV_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
+	count = l->filelen / sizeof(*in);
+	out = Hunk_AllocName ( count*sizeof(*out), loadname);	
+
+	loadmodel->surfedges = out;
+	loadmodel->numsurfedges = count;
+
+	for ( i=0 ; i<count ; i++)
+		out[i] = LittleLong (in[i]);
+}
+
+/*
+=================
+Mod_LoadPlanes
+=================
+*/
+void Mod_LoadPlanes (lump_t *l)
+{
+	int			i, j;
+	mplane_t	*out;
+	dplane_t 	*in;
+	int			count;
+	int			bits;
+	
+	in = (void *)(mod_base + l->fileofs);
+	if (l->filelen % sizeof(*in))
+		SV_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
+	count = l->filelen / sizeof(*in);
+	out = Hunk_AllocName ( count*2*sizeof(*out), loadname);	
+	
+	loadmodel->planes = out;
+	loadmodel->numplanes = count;
+
+	for ( i=0 ; i<count ; i++, in++, out++)
+	{
+		bits = 0;
+		for (j=0 ; j<3 ; j++)
+		{
+			out->normal[j] = LittleFloat (in->normal[j]);
+			if (out->normal[j] < 0)
+				bits |= 1<<j;
+		}
+
+		out->dist = LittleFloat (in->dist);
+		out->type = LittleLong (in->type);
+		out->signbits = bits;
+	}
+}
+
+
+/*
+=================
+Mod_LoadBrushModel
+=================
+*/
+void Mod_LoadBrushModel (model_t *mod, void *buffer)
+{
+	int			i, j;
+	dheader_t	*header;
+	dmodel_t 	*bm;
+	
+	loadmodel->type = mod_brush;
+	
+	header = (dheader_t *)buffer;
+
+	i = LittleLong (header->version);
+	if (i != BSPVERSION)
+		SV_Error ("Mod_LoadBrushModel: %s has wrong version number (%i should be %i)", mod->name, i, BSPVERSION);
+
+// swap all the lumps
+	mod_base = (byte *)header;
+
+	for (i=0 ; i<sizeof(dheader_t)/4 ; i++)
+		((int *)header)[i] = LittleLong ( ((int *)header)[i]);
+
+// load into heap
+
+	mod->checksum = 0;
+	mod->checksum2 = 0;
+
+	// checksum all of the map, except for entities
+	for (i = 0; i < HEADER_LUMPS; i++) {
+		if (i == LUMP_ENTITIES)
+			continue;
+		mod->checksum ^= LittleLong(Com_BlockChecksum(mod_base + header->lumps[i].fileofs, 
+			header->lumps[i].filelen));
+
+		if (i == LUMP_VISIBILITY || i == LUMP_LEAFS || i == LUMP_NODES)
+			continue;
+		mod->checksum2 ^= LittleLong(Com_BlockChecksum(mod_base + header->lumps[i].fileofs, 
+			header->lumps[i].filelen));
+	}
+
+	Mod_LoadVertexes (&header->lumps[LUMP_VERTEXES]);
+	Mod_LoadEdges (&header->lumps[LUMP_EDGES]);
+	Mod_LoadSurfedges (&header->lumps[LUMP_SURFEDGES]);
+	Mod_LoadTextures (&header->lumps[LUMP_TEXTURES]);
+	Mod_LoadLighting (&header->lumps[LUMP_LIGHTING]);
+	Mod_LoadPlanes (&header->lumps[LUMP_PLANES]);
+	Mod_LoadTexinfo (&header->lumps[LUMP_TEXINFO]);
+	Mod_LoadFaces (&header->lumps[LUMP_FACES]);
+	Mod_LoadMarksurfaces (&header->lumps[LUMP_MARKSURFACES]);
+	Mod_LoadVisibility (&header->lumps[LUMP_VISIBILITY]);
+	Mod_LoadLeafs (&header->lumps[LUMP_LEAFS]);
+	Mod_LoadNodes (&header->lumps[LUMP_NODES]);
+	Mod_LoadClipnodes (&header->lumps[LUMP_CLIPNODES]);
+	Mod_LoadEntities (&header->lumps[LUMP_ENTITIES]);
+	Mod_LoadSubmodels (&header->lumps[LUMP_MODELS]);
+
+	Mod_MakeHull0 ();
+	
+	mod->numframes = 2;		// regular and alternate animation
+	
+//
+// set up the submodels (FIXME: this is confusing)
+//
+	for (i=0 ; i<mod->numsubmodels ; i++)
+	{
+		bm = &mod->submodels[i];
+
+		mod->hulls[0].firstclipnode = bm->headnode[0];
+		for (j=1 ; j<MAX_MAP_HULLS ; j++)
+		{
+			mod->hulls[j].firstclipnode = bm->headnode[j];
+			mod->hulls[j].lastclipnode = mod->numclipnodes-1;
+		}
+		
+		mod->firstmodelsurface = bm->firstface;
+		mod->nummodelsurfaces = bm->numfaces;
+		
+		VectorCopy (bm->maxs, mod->maxs);
+		VectorCopy (bm->mins, mod->mins);
+	
+		mod->numleafs = bm->visleafs;
+
+		if (i < mod->numsubmodels-1)
+		{	// duplicate the basic information
+			char	name[10];
+
+			sprintf (name, "*%i", i+1);
+			loadmodel = Mod_FindName (name);
+			*loadmodel = *mod;
+			strcpy (loadmodel->name, name);
+			mod = loadmodel;
+		}
+	}
+}
+
--- /dev/null
+++ b/QW/server/move.txt
@@ -1,0 +1,39 @@
+
+dead state flag for no user input
+
+
+floor = under feet test
+	onground?
+	
+feet = wading test
+
+waist = swimming test
+
+head = submerged test
+
+
+if ( floor == solid)
+	if (head == water)
+		friction = 0.8;
+	else if (waist == water)
+		friction =
+	else if (feet == water)
+		friction =
+	else
+		friction = 
+	walk code
+	return;
+	
+if (floor == water)
+	if (head == water)
+		total underwater
+	if (waist == water)
+		treading water
+	drifting down
+	
+if (floor == air)
+	falling
+
+
+
+	
\ No newline at end of file
--- /dev/null
+++ b/QW/server/newnet.txt
@@ -1,0 +1,121 @@
+registered clients will auto-kick unregistered clients
+
+central clearingghouse for active servers
+
+server logon messages
+
+problem with reconnect to same server out of order packets
+
+acknowledge all command line parameters
+
+annoying pause on intermission screen
+
+seperate accept/reject list for server packets and client packets
+
+server compile time should be part of connect message and status
+
+allocate new cvars during file parse
+
+remote console should be able to do cvar setting/reading
+
+make punchangle a client side operation
+
+remove sys_printf
+remove host_client
+
+packet filter list
+client move by test final pos and test 1/16 down
+simulate world first, then clients, clients explicitly sim weapon projectiles
+allow remote locations to subscribe to console output
+
+
+
+client zombie state?
+seperate command ques for client and server?
+worry about partial connection during level change
+worry about zombie state for if(!state) constructs
+
+make sound/ and models/ implicit in data types
+
+int		sequence
+int		reliable_sequence;
+bit		reliable_payload;
+
+consumption
+renewable resources
+depletable resources
+rate of extraction
+
+
+how can you influence other characters
+how can you communicate
+
+
+login
+logoff
+disconnection
+
+client to server
+----------------
+last good received server time
+milliseconds since last move frame
+angles
+movement
+buttonstates
+impulse
+
+
+server to client
+----------------
+last movemessage received
+origin
+velocity
+
+
+build movement
+send movement packet to server
+set player position to last known good
+execute all unaknowledged movement packets
+
+
+needs to know all things that can effect movement
+
+movement context
+----------------
+origin
+velocity
+size
+
+run move command (context, move)
+
+
+
+#define	MAX_MOVEMESSAGES	64
+
+typedef struct
+{
+	double	time;		// client time when sent
+	byte	milliseconds;
+} movemessage_t;
+
+int		ack_movemessage;
+int		current_movemessage;
+
+movemessage_t	movemessages[MAX_MOVEMESSAGES];
+
+void CL_Frame (void)
+{
+	get all pending server messages
+	
+	latency = cl.time - movemessage[last].time;
+
+	movetime = cl.time - cl.oldtime;
+	get movemessage
+	
+	send packet to server
+}
+
+
+
+
+does not adress interpolating other object's movement
--- /dev/null
+++ b/QW/server/notes.txt
@@ -1,0 +1,7 @@
+
+new server auth design;
+- server includes 32bit random token S
+- master sees new server, request auth with MD5(M|S).  m is 32bit master key
+- server sends register MD5( MD5(M|S) | S )
+- master validates registration with server
+- M value changes for each server randomly
--- /dev/null
+++ b/QW/server/pr_cmds.c
@@ -1,0 +1,1722 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+
+#include "qwsvdef.h"
+
+#define	RETURN_EDICT(e) (((int *)pr_globals)[OFS_RETURN] = EDICT_TO_PROG(e))
+#define	RETURN_STRING(s) (((int *)pr_globals)[OFS_RETURN] = PR_SetString(s))
+
+/*
+===============================================================================
+
+						BUILT-IN FUNCTIONS
+
+===============================================================================
+*/
+
+char *PF_VarString (int	first)
+{
+	int		i;
+	static char out[256];
+	
+	out[0] = 0;
+	for (i=first ; i<pr_argc ; i++)
+	{
+		strcat (out, G_STRING((OFS_PARM0+i*3)));
+	}
+	return out;
+}
+
+
+/*
+=================
+PF_errror
+
+This is a TERMINAL error, which will kill off the entire server.
+Dumps self.
+
+error(value)
+=================
+*/
+void PF_error (void)
+{
+	char	*s;
+	edict_t	*ed;
+	
+	s = PF_VarString(0);
+	Con_Printf ("======SERVER ERROR in %s:\n%s\n", PR_GetString(pr_xfunction->s_name) ,s);
+	ed = PROG_TO_EDICT(pr_global_struct->self);
+	ED_Print (ed);
+
+	SV_Error ("Program error");
+}
+
+/*
+=================
+PF_objerror
+
+Dumps out self, then an error message.  The program is aborted and self is
+removed, but the level can continue.
+
+objerror(value)
+=================
+*/
+void PF_objerror (void)
+{
+	char	*s;
+	edict_t	*ed;
+	
+	s = PF_VarString(0);
+	Con_Printf ("======OBJECT ERROR in %s:\n%s\n", PR_GetString(pr_xfunction->s_name),s);
+	ed = PROG_TO_EDICT(pr_global_struct->self);
+	ED_Print (ed);
+	ED_Free (ed);
+	
+	SV_Error ("Program error");
+}
+
+
+
+/*
+==============
+PF_makevectors
+
+Writes new values for v_forward, v_up, and v_right based on angles
+makevectors(vector)
+==============
+*/
+void PF_makevectors (void)
+{
+	AngleVectors (G_VECTOR(OFS_PARM0), pr_global_struct->v_forward, pr_global_struct->v_right, pr_global_struct->v_up);
+}
+
+/*
+=================
+PF_setorigin
+
+This is the only valid way to move an object without using the physics of the world (setting velocity and waiting).  Directly changing origin will not set internal links correctly, so clipping would be messed up.  This should be called when an object is spawned, and then only if it is teleported.
+
+setorigin (entity, origin)
+=================
+*/
+void PF_setorigin (void)
+{
+	edict_t	*e;
+	float	*org;
+	
+	e = G_EDICT(OFS_PARM0);
+	org = G_VECTOR(OFS_PARM1);
+	VectorCopy (org, e->v.origin);
+	SV_LinkEdict (e, false);
+}
+
+
+/*
+=================
+PF_setsize
+
+the size box is rotated by the current angle
+
+setsize (entity, minvector, maxvector)
+=================
+*/
+void PF_setsize (void)
+{
+	edict_t	*e;
+	float	*min, *max;
+	
+	e = G_EDICT(OFS_PARM0);
+	min = G_VECTOR(OFS_PARM1);
+	max = G_VECTOR(OFS_PARM2);
+	VectorCopy (min, e->v.mins);
+	VectorCopy (max, e->v.maxs);
+	VectorSubtract (max, min, e->v.size);
+	SV_LinkEdict (e, false);
+}
+
+
+/*
+=================
+PF_setmodel
+
+setmodel(entity, model)
+Also sets size, mins, and maxs for inline bmodels
+=================
+*/
+void PF_setmodel (void)
+{
+	edict_t	*e;
+	char	*m, **check;
+	int		i;
+	model_t	*mod;
+
+	e = G_EDICT(OFS_PARM0);
+	m = G_STRING(OFS_PARM1);
+
+// check to see if model was properly precached
+	for (i=0, check = sv.model_precache ; *check ; i++, check++)
+		if (!strcmp(*check, m))
+			break;
+
+	if (!*check)
+		PR_RunError ("no precache: %s\n", m);
+		
+	e->v.model = PR_SetString(m);
+	e->v.modelindex = i;
+
+// if it is an inline model, get the size information for it
+	if (m[0] == '*')
+	{
+		mod = Mod_ForName (m, true);
+		VectorCopy (mod->mins, e->v.mins);
+		VectorCopy (mod->maxs, e->v.maxs);
+		VectorSubtract (mod->maxs, mod->mins, e->v.size);
+		SV_LinkEdict (e, false);
+	}
+
+}
+
+/*
+=================
+PF_bprint
+
+broadcast print to everyone on server
+
+bprint(value)
+=================
+*/
+void PF_bprint (void)
+{
+	char		*s;
+	int			level;
+	
+	level = G_FLOAT(OFS_PARM0);
+
+	s = PF_VarString(1);
+	SV_BroadcastPrintf (level, "%s", s);
+}
+
+/*
+=================
+PF_sprint
+
+single print to a specific client
+
+sprint(clientent, value)
+=================
+*/
+void PF_sprint (void)
+{
+	char		*s;
+	client_t	*client;
+	int			entnum;
+	int			level;
+	
+	entnum = G_EDICTNUM(OFS_PARM0);
+	level = G_FLOAT(OFS_PARM1);
+
+	s = PF_VarString(2);
+	
+	if (entnum < 1 || entnum > MAX_CLIENTS)
+	{
+		Con_Printf ("tried to sprint to a non-client\n");
+		return;
+	}
+		
+	client = &svs.clients[entnum-1];
+	
+	SV_ClientPrintf (client, level, "%s", s);
+}
+
+
+/*
+=================
+PF_centerprint
+
+single print to a specific client
+
+centerprint(clientent, value)
+=================
+*/
+void PF_centerprint (void)
+{
+	char		*s;
+	int			entnum;
+	client_t	*cl;
+	
+	entnum = G_EDICTNUM(OFS_PARM0);
+	s = PF_VarString(1);
+	
+	if (entnum < 1 || entnum > MAX_CLIENTS)
+	{
+		Con_Printf ("tried to sprint to a non-client\n");
+		return;
+	}
+		
+	cl = &svs.clients[entnum-1];
+
+	ClientReliableWrite_Begin (cl, svc_centerprint, 2 + strlen(s));
+	ClientReliableWrite_String (cl, s);
+}
+
+
+/*
+=================
+PF_normalize
+
+vector normalize(vector)
+=================
+*/
+void PF_normalize (void)
+{
+	float	*value1;
+	vec3_t	newvalue;
+	float	new;
+	
+	value1 = G_VECTOR(OFS_PARM0);
+
+	new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2];
+	new = sqrt(new);
+	
+	if (new == 0)
+		newvalue[0] = newvalue[1] = newvalue[2] = 0;
+	else
+	{
+		new = 1/new;
+		newvalue[0] = value1[0] * new;
+		newvalue[1] = value1[1] * new;
+		newvalue[2] = value1[2] * new;
+	}
+	
+	VectorCopy (newvalue, G_VECTOR(OFS_RETURN));	
+}
+
+/*
+=================
+PF_vlen
+
+scalar vlen(vector)
+=================
+*/
+void PF_vlen (void)
+{
+	float	*value1;
+	float	new;
+	
+	value1 = G_VECTOR(OFS_PARM0);
+
+	new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2];
+	new = sqrt(new);
+	
+	G_FLOAT(OFS_RETURN) = new;
+}
+
+/*
+=================
+PF_vectoyaw
+
+float vectoyaw(vector)
+=================
+*/
+void PF_vectoyaw (void)
+{
+	float	*value1;
+	float	yaw;
+	
+	value1 = G_VECTOR(OFS_PARM0);
+
+	if (value1[1] == 0 && value1[0] == 0)
+		yaw = 0;
+	else
+	{
+		yaw = (int) (atan2(value1[1], value1[0]) * 180 / M_PI);
+		if (yaw < 0)
+			yaw += 360;
+	}
+
+	G_FLOAT(OFS_RETURN) = yaw;
+}
+
+
+/*
+=================
+PF_vectoangles
+
+vector vectoangles(vector)
+=================
+*/
+void PF_vectoangles (void)
+{
+	float	*value1;
+	float	forward;
+	float	yaw, pitch;
+	
+	value1 = G_VECTOR(OFS_PARM0);
+
+	if (value1[1] == 0 && value1[0] == 0)
+	{
+		yaw = 0;
+		if (value1[2] > 0)
+			pitch = 90;
+		else
+			pitch = 270;
+	}
+	else
+	{
+		yaw = (int) (atan2(value1[1], value1[0]) * 180 / M_PI);
+		if (yaw < 0)
+			yaw += 360;
+
+		forward = sqrt (value1[0]*value1[0] + value1[1]*value1[1]);
+		pitch = (int) (atan2(value1[2], forward) * 180 / M_PI);
+		if (pitch < 0)
+			pitch += 360;
+	}
+
+	G_FLOAT(OFS_RETURN+0) = pitch;
+	G_FLOAT(OFS_RETURN+1) = yaw;
+	G_FLOAT(OFS_RETURN+2) = 0;
+}
+
+/*
+=================
+PF_Random
+
+Returns a number from 0<= num < 1
+
+random()
+=================
+*/
+void PF_random (void)
+{
+	float		num;
+		
+	num = (rand ()&0x7fff) / ((float)0x7fff);
+	
+	G_FLOAT(OFS_RETURN) = num;
+}
+
+
+/*
+=================
+PF_ambientsound
+
+=================
+*/
+void PF_ambientsound (void)
+{
+	char		**check;
+	char		*samp;
+	float		*pos;
+	float 		vol, attenuation;
+	int			i, soundnum;
+
+	pos = G_VECTOR (OFS_PARM0);			
+	samp = G_STRING(OFS_PARM1);
+	vol = G_FLOAT(OFS_PARM2);
+	attenuation = G_FLOAT(OFS_PARM3);
+	
+// check to see if samp was properly precached
+	for (soundnum=0, check = sv.sound_precache ; *check ; check++, soundnum++)
+		if (!strcmp(*check,samp))
+			break;
+			
+	if (!*check)
+	{
+		Con_Printf ("no precache: %s\n", samp);
+		return;
+	}
+
+// add an svc_spawnambient command to the level signon packet
+
+	MSG_WriteByte (&sv.signon,svc_spawnstaticsound);
+	for (i=0 ; i<3 ; i++)
+		MSG_WriteCoord(&sv.signon, pos[i]);
+
+	MSG_WriteByte (&sv.signon, soundnum);
+
+	MSG_WriteByte (&sv.signon, vol*255);
+	MSG_WriteByte (&sv.signon, attenuation*64);
+
+}
+
+/*
+=================
+PF_sound
+
+Each entity can have eight independant sound sources, like voice,
+weapon, feet, etc.
+
+Channel 0 is an auto-allocate channel, the others override anything
+allready running on that entity/channel pair.
+
+An attenuation of 0 will play full volume everywhere in the level.
+Larger attenuations will drop off.
+
+=================
+*/
+void PF_sound (void)
+{
+	char		*sample;
+	int			channel;
+	edict_t		*entity;
+	int 		volume;
+	float attenuation;
+		
+	entity = G_EDICT(OFS_PARM0);
+	channel = G_FLOAT(OFS_PARM1);
+	sample = G_STRING(OFS_PARM2);
+	volume = G_FLOAT(OFS_PARM3) * 255;
+	attenuation = G_FLOAT(OFS_PARM4);
+	
+	SV_StartSound (entity, channel, sample, volume, attenuation);
+}
+
+/*
+=================
+PF_break
+
+break()
+=================
+*/
+void PF_break (void)
+{
+Con_Printf ("break statement\n");
+*(int *)-4 = 0;	// dump to debugger
+//	PR_RunError ("break statement");
+}
+
+/*
+=================
+PF_traceline
+
+Used for use tracing and shot targeting
+Traces are blocked by bbox and exact bsp entityes, and also slide box entities
+if the tryents flag is set.
+
+traceline (vector1, vector2, tryents)
+=================
+*/
+void PF_traceline (void)
+{
+	float	*v1, *v2;
+	trace_t	trace;
+	int		nomonsters;
+	edict_t	*ent;
+
+	v1 = G_VECTOR(OFS_PARM0);
+	v2 = G_VECTOR(OFS_PARM1);
+	nomonsters = G_FLOAT(OFS_PARM2);
+	ent = G_EDICT(OFS_PARM3);
+
+	trace = SV_Move (v1, vec3_origin, vec3_origin, v2, nomonsters, ent);
+
+	pr_global_struct->trace_allsolid = trace.allsolid;
+	pr_global_struct->trace_startsolid = trace.startsolid;
+	pr_global_struct->trace_fraction = trace.fraction;
+	pr_global_struct->trace_inwater = trace.inwater;
+	pr_global_struct->trace_inopen = trace.inopen;
+	VectorCopy (trace.endpos, pr_global_struct->trace_endpos);
+	VectorCopy (trace.plane.normal, pr_global_struct->trace_plane_normal);
+	pr_global_struct->trace_plane_dist =  trace.plane.dist;	
+	if (trace.ent)
+		pr_global_struct->trace_ent = EDICT_TO_PROG(trace.ent);
+	else
+		pr_global_struct->trace_ent = EDICT_TO_PROG(sv.edicts);
+}
+
+/*
+=================
+PF_checkpos
+
+Returns true if the given entity can move to the given position from it's
+current position by walking or rolling.
+FIXME: make work...
+scalar checkpos (entity, vector)
+=================
+*/
+void PF_checkpos (void)
+{
+}
+
+//============================================================================
+
+byte	checkpvs[MAX_MAP_LEAFS/8];
+
+int PF_newcheckclient (int check)
+{
+	int		i;
+	byte	*pvs;
+	edict_t	*ent;
+	mleaf_t	*leaf;
+	vec3_t	org;
+
+// cycle to the next one
+
+	if (check < 1)
+		check = 1;
+	if (check > MAX_CLIENTS)
+		check = MAX_CLIENTS;
+
+	if (check == MAX_CLIENTS)
+		i = 1;
+	else
+		i = check + 1;
+
+	for ( ;  ; i++)
+	{
+		if (i == MAX_CLIENTS+1)
+			i = 1;
+
+		ent = EDICT_NUM(i);
+
+		if (i == check)
+			break;	// didn't find anything else
+
+		if (ent->free)
+			continue;
+		if (ent->v.health <= 0)
+			continue;
+		if ((int)ent->v.flags & FL_NOTARGET)
+			continue;
+
+	// anything that is a client, or has a client as an enemy
+		break;
+	}
+
+// get the PVS for the entity
+	VectorAdd (ent->v.origin, ent->v.view_ofs, org);
+	leaf = Mod_PointInLeaf (org, sv.worldmodel);
+	pvs = Mod_LeafPVS (leaf, sv.worldmodel);
+	memcpy (checkpvs, pvs, (sv.worldmodel->numleafs+7)>>3 );
+
+	return i;
+}
+
+/*
+=================
+PF_checkclient
+
+Returns a client (or object that has a client enemy) that would be a
+valid target.
+
+If there are more than one valid options, they are cycled each frame
+
+If (self.origin + self.viewofs) is not in the PVS of the current target,
+it is not returned at all.
+
+name checkclient ()
+=================
+*/
+#define	MAX_CHECK	16
+int c_invis, c_notvis;
+void PF_checkclient (void)
+{
+	edict_t	*ent, *self;
+	mleaf_t	*leaf;
+	int		l;
+	vec3_t	view;
+	
+// find a new check if on a new frame
+	if (sv.time - sv.lastchecktime >= 0.1)
+	{
+		sv.lastcheck = PF_newcheckclient (sv.lastcheck);
+		sv.lastchecktime = sv.time;
+	}
+
+// return check if it might be visible	
+	ent = EDICT_NUM(sv.lastcheck);
+	if (ent->free || ent->v.health <= 0)
+	{
+		RETURN_EDICT(sv.edicts);
+		return;
+	}
+
+// if current entity can't possibly see the check entity, return 0
+	self = PROG_TO_EDICT(pr_global_struct->self);
+	VectorAdd (self->v.origin, self->v.view_ofs, view);
+	leaf = Mod_PointInLeaf (view, sv.worldmodel);
+	l = (leaf - sv.worldmodel->leafs) - 1;
+	if ( (l<0) || !(checkpvs[l>>3] & (1<<(l&7)) ) )
+	{
+c_notvis++;
+		RETURN_EDICT(sv.edicts);
+		return;
+	}
+
+// might be able to see it
+c_invis++;
+	RETURN_EDICT(ent);
+}
+
+//============================================================================
+
+
+/*
+=================
+PF_stuffcmd
+
+Sends text over to the client's execution buffer
+
+stuffcmd (clientent, value)
+=================
+*/
+void PF_stuffcmd (void)
+{
+	int		entnum;
+	char	*str;
+	client_t	*cl;
+	
+	entnum = G_EDICTNUM(OFS_PARM0);
+	if (entnum < 1 || entnum > MAX_CLIENTS)
+		PR_RunError ("Parm 0 not a client");
+	str = G_STRING(OFS_PARM1);	
+	
+	cl = &svs.clients[entnum-1];
+
+	if (strcmp(str, "disconnect\n") == 0) {
+		// so long and thanks for all the fish
+		cl->drop = true;
+		return;
+	}
+
+	ClientReliableWrite_Begin (cl, svc_stufftext, 2+strlen(str));
+	ClientReliableWrite_String (cl, str);
+}
+
+/*
+=================
+PF_localcmd
+
+Sends text over to the client's execution buffer
+
+localcmd (string)
+=================
+*/
+void PF_localcmd (void)
+{
+	char	*str;
+	
+	str = G_STRING(OFS_PARM0);	
+	Cbuf_AddText (str);
+}
+
+/*
+=================
+PF_cvar
+
+float cvar (string)
+=================
+*/
+void PF_cvar (void)
+{
+	char	*str;
+	
+	str = G_STRING(OFS_PARM0);
+	
+	G_FLOAT(OFS_RETURN) = Cvar_VariableValue (str);
+}
+
+/*
+=================
+PF_cvar_set
+
+float cvar (string)
+=================
+*/
+void PF_cvar_set (void)
+{
+	char	*var, *val;
+	
+	var = G_STRING(OFS_PARM0);
+	val = G_STRING(OFS_PARM1);
+	
+	Cvar_Set (var, val);
+}
+
+/*
+=================
+PF_findradius
+
+Returns a chain of entities that have origins within a spherical area
+
+findradius (origin, radius)
+=================
+*/
+void PF_findradius (void)
+{
+	edict_t	*ent, *chain;
+	float	rad;
+	float	*org;
+	vec3_t	eorg;
+	int		i, j;
+
+	chain = (edict_t *)sv.edicts;
+	
+	org = G_VECTOR(OFS_PARM0);
+	rad = G_FLOAT(OFS_PARM1);
+
+	ent = NEXT_EDICT(sv.edicts);
+	for (i=1 ; i<sv.num_edicts ; i++, ent = NEXT_EDICT(ent))
+	{
+		if (ent->free)
+			continue;
+		if (ent->v.solid == SOLID_NOT)
+			continue;
+		for (j=0 ; j<3 ; j++)
+			eorg[j] = org[j] - (ent->v.origin[j] + (ent->v.mins[j] + ent->v.maxs[j])*0.5);			
+		if (Length(eorg) > rad)
+			continue;
+			
+		ent->v.chain = EDICT_TO_PROG(chain);
+		chain = ent;
+	}
+
+	RETURN_EDICT(chain);
+}
+
+
+/*
+=========
+PF_dprint
+=========
+*/
+void PF_dprint (void)
+{
+	Con_Printf ("%s",PF_VarString(0));
+}
+
+char	pr_string_temp[128];
+
+void PF_ftos (void)
+{
+	float	v;
+	v = G_FLOAT(OFS_PARM0);
+	
+	if (v == (int)v)
+		sprintf (pr_string_temp, "%d",(int)v);
+	else
+		sprintf (pr_string_temp, "%5.1f",v);
+	G_INT(OFS_RETURN) = PR_SetString(pr_string_temp);
+}
+
+void PF_fabs (void)
+{
+	float	v;
+	v = G_FLOAT(OFS_PARM0);
+	G_FLOAT(OFS_RETURN) = fabs(v);
+}
+
+void PF_vtos (void)
+{
+	sprintf (pr_string_temp, "'%5.1f %5.1f %5.1f'", G_VECTOR(OFS_PARM0)[0], G_VECTOR(OFS_PARM0)[1], G_VECTOR(OFS_PARM0)[2]);
+	G_INT(OFS_RETURN) = PR_SetString(pr_string_temp);
+}
+
+void PF_Spawn (void)
+{
+	edict_t	*ed;
+	ed = ED_Alloc();
+	RETURN_EDICT(ed);
+}
+
+void PF_Remove (void)
+{
+	edict_t	*ed;
+	
+	ed = G_EDICT(OFS_PARM0);
+	ED_Free (ed);
+}
+
+
+// entity (entity start, .string field, string match) find = #5;
+void PF_Find (void)
+{
+	int		e;	
+	int		f;
+	char	*s, *t;
+	edict_t	*ed;
+	
+	e = G_EDICTNUM(OFS_PARM0);
+	f = G_INT(OFS_PARM1);
+	s = G_STRING(OFS_PARM2);
+	if (!s)
+		PR_RunError ("PF_Find: bad search string");
+		
+	for (e++ ; e < sv.num_edicts ; e++)
+	{
+		ed = EDICT_NUM(e);
+		if (ed->free)
+			continue;
+		t = E_STRING(ed,f);
+		if (!t)
+			continue;
+		if (!strcmp(t,s))
+		{
+			RETURN_EDICT(ed);
+			return;
+		}
+	}
+	
+	RETURN_EDICT(sv.edicts);
+}
+
+void PR_CheckEmptyString (char *s)
+{
+	if (s[0] <= ' ')
+		PR_RunError ("Bad string");
+}
+
+void PF_precache_file (void)
+{	// precache_file is only used to copy files with qcc, it does nothing
+	G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
+}
+
+void PF_precache_sound (void)
+{
+	char	*s;
+	int		i;
+	
+	if (sv.state != ss_loading)
+		PR_RunError ("PF_Precache_*: Precache can only be done in spawn functions");
+		
+	s = G_STRING(OFS_PARM0);
+	G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
+	PR_CheckEmptyString (s);
+	
+	for (i=0 ; i<MAX_SOUNDS ; i++)
+	{
+		if (!sv.sound_precache[i])
+		{
+			sv.sound_precache[i] = s;
+			return;
+		}
+		if (!strcmp(sv.sound_precache[i], s))
+			return;
+	}
+	PR_RunError ("PF_precache_sound: overflow");
+}
+
+void PF_precache_model (void)
+{
+	char	*s;
+	int		i;
+	
+	if (sv.state != ss_loading)
+		PR_RunError ("PF_Precache_*: Precache can only be done in spawn functions");
+		
+	s = G_STRING(OFS_PARM0);
+	G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
+	PR_CheckEmptyString (s);
+
+	for (i=0 ; i<MAX_MODELS ; i++)
+	{
+		if (!sv.model_precache[i])
+		{
+			sv.model_precache[i] = s;
+			return;
+		}
+		if (!strcmp(sv.model_precache[i], s))
+			return;
+	}
+	PR_RunError ("PF_precache_model: overflow");
+}
+
+
+void PF_coredump (void)
+{
+	ED_PrintEdicts ();
+}
+
+void PF_traceon (void)
+{
+	pr_trace = true;
+}
+
+void PF_traceoff (void)
+{
+	pr_trace = false;
+}
+
+void PF_eprint (void)
+{
+	ED_PrintNum (G_EDICTNUM(OFS_PARM0));
+}
+
+/*
+===============
+PF_walkmove
+
+float(float yaw, float dist) walkmove
+===============
+*/
+void PF_walkmove (void)
+{
+	edict_t	*ent;
+	float	yaw, dist;
+	vec3_t	move;
+	dfunction_t	*oldf;
+	int 	oldself;
+	
+	ent = PROG_TO_EDICT(pr_global_struct->self);
+	yaw = G_FLOAT(OFS_PARM0);
+	dist = G_FLOAT(OFS_PARM1);
+	
+	if ( !( (int)ent->v.flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
+	{
+		G_FLOAT(OFS_RETURN) = 0;
+		return;
+	}
+
+	yaw = yaw*M_PI*2 / 360;
+	
+	move[0] = cos(yaw)*dist;
+	move[1] = sin(yaw)*dist;
+	move[2] = 0;
+
+// save program state, because SV_movestep may call other progs
+	oldf = pr_xfunction;
+	oldself = pr_global_struct->self;
+	
+	G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true);
+	
+	
+// restore program state
+	pr_xfunction = oldf;
+	pr_global_struct->self = oldself;
+}
+
+/*
+===============
+PF_droptofloor
+
+void() droptofloor
+===============
+*/
+void PF_droptofloor (void)
+{
+	edict_t		*ent;
+	vec3_t		end;
+	trace_t		trace;
+	
+	ent = PROG_TO_EDICT(pr_global_struct->self);
+
+	VectorCopy (ent->v.origin, end);
+	end[2] -= 256;
+	
+	trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, end, false, ent);
+
+	if (trace.fraction == 1 || trace.allsolid)
+		G_FLOAT(OFS_RETURN) = 0;
+	else
+	{
+		VectorCopy (trace.endpos, ent->v.origin);
+		SV_LinkEdict (ent, false);
+		ent->v.flags = (int)ent->v.flags | FL_ONGROUND;
+		ent->v.groundentity = EDICT_TO_PROG(trace.ent);
+		G_FLOAT(OFS_RETURN) = 1;
+	}
+}
+
+/*
+===============
+PF_lightstyle
+
+void(float style, string value) lightstyle
+===============
+*/
+void PF_lightstyle (void)
+{
+	int		style;
+	char	*val;
+	client_t	*client;
+	int			j;
+	
+	style = G_FLOAT(OFS_PARM0);
+	val = G_STRING(OFS_PARM1);
+
+// change the string in sv
+	sv.lightstyles[style] = val;
+	
+// send message to all clients on this server
+	if (sv.state != ss_active)
+		return;
+	
+	for (j=0, client = svs.clients ; j<MAX_CLIENTS ; j++, client++)
+		if ( client->state == cs_spawned )
+		{
+			ClientReliableWrite_Begin (client, svc_lightstyle, strlen(val)+3);
+			ClientReliableWrite_Char (client, style);
+			ClientReliableWrite_String (client, val);
+		}
+}
+
+void PF_rint (void)
+{
+	float	f;
+	f = G_FLOAT(OFS_PARM0);
+	if (f > 0)
+		G_FLOAT(OFS_RETURN) = (int)(f + 0.5);
+	else
+		G_FLOAT(OFS_RETURN) = (int)(f - 0.5);
+}
+void PF_floor (void)
+{
+	G_FLOAT(OFS_RETURN) = floor(G_FLOAT(OFS_PARM0));
+}
+void PF_ceil (void)
+{
+	G_FLOAT(OFS_RETURN) = ceil(G_FLOAT(OFS_PARM0));
+}
+
+
+/*
+=============
+PF_checkbottom
+=============
+*/
+void PF_checkbottom (void)
+{
+	edict_t	*ent;
+	
+	ent = G_EDICT(OFS_PARM0);
+
+	G_FLOAT(OFS_RETURN) = SV_CheckBottom (ent);
+}
+
+/*
+=============
+PF_pointcontents
+=============
+*/
+void PF_pointcontents (void)
+{
+	float	*v;
+	
+	v = G_VECTOR(OFS_PARM0);
+
+	G_FLOAT(OFS_RETURN) = SV_PointContents (v);	
+}
+
+/*
+=============
+PF_nextent
+
+entity nextent(entity)
+=============
+*/
+void PF_nextent (void)
+{
+	int		i;
+	edict_t	*ent;
+	
+	i = G_EDICTNUM(OFS_PARM0);
+	while (1)
+	{
+		i++;
+		if (i == sv.num_edicts)
+		{
+			RETURN_EDICT(sv.edicts);
+			return;
+		}
+		ent = EDICT_NUM(i);
+		if (!ent->free)
+		{
+			RETURN_EDICT(ent);
+			return;
+		}
+	}
+}
+
+/*
+=============
+PF_aim
+
+Pick a vector for the player to shoot along
+vector aim(entity, missilespeed)
+=============
+*/
+//cvar_t	sv_aim = {"sv_aim", "0.93"};
+cvar_t	sv_aim = {"sv_aim", "2"};
+void PF_aim (void)
+{
+	edict_t	*ent, *check, *bestent;
+	vec3_t	start, dir, end, bestdir;
+	int		i, j;
+	trace_t	tr;
+	float	dist, bestdist;
+	float	speed;
+	char	*noaim;
+
+	ent = G_EDICT(OFS_PARM0);
+	speed = G_FLOAT(OFS_PARM1);
+
+	VectorCopy (ent->v.origin, start);
+	start[2] += 20;
+
+// noaim option
+	i = NUM_FOR_EDICT(ent);
+	if (i>0 && i<MAX_CLIENTS)
+	{
+		noaim = Info_ValueForKey (svs.clients[i-1].userinfo, "noaim");
+		if (atoi(noaim) > 0)
+		{
+			VectorCopy (pr_global_struct->v_forward, G_VECTOR(OFS_RETURN));
+			return;
+		}
+	}
+
+// try sending a trace straight
+	VectorCopy (pr_global_struct->v_forward, dir);
+	VectorMA (start, 2048, dir, end);
+	tr = SV_Move (start, vec3_origin, vec3_origin, end, false, ent);
+	if (tr.ent && tr.ent->v.takedamage == DAMAGE_AIM
+	&& (!teamplay.value || ent->v.team <=0 || ent->v.team != tr.ent->v.team) )
+	{
+		VectorCopy (pr_global_struct->v_forward, G_VECTOR(OFS_RETURN));
+		return;
+	}
+
+
+// try all possible entities
+	VectorCopy (dir, bestdir);
+	bestdist = sv_aim.value;
+	bestent = NULL;
+	
+	check = NEXT_EDICT(sv.edicts);
+	for (i=1 ; i<sv.num_edicts ; i++, check = NEXT_EDICT(check) )
+	{
+		if (check->v.takedamage != DAMAGE_AIM)
+			continue;
+		if (check == ent)
+			continue;
+		if (teamplay.value && ent->v.team > 0 && ent->v.team == check->v.team)
+			continue;	// don't aim at teammate
+		for (j=0 ; j<3 ; j++)
+			end[j] = check->v.origin[j]
+			+ 0.5*(check->v.mins[j] + check->v.maxs[j]);
+		VectorSubtract (end, start, dir);
+		VectorNormalize (dir);
+		dist = DotProduct (dir, pr_global_struct->v_forward);
+		if (dist < bestdist)
+			continue;	// to far to turn
+		tr = SV_Move (start, vec3_origin, vec3_origin, end, false, ent);
+		if (tr.ent == check)
+		{	// can shoot at this one
+			bestdist = dist;
+			bestent = check;
+		}
+	}
+	
+	if (bestent)
+	{
+		VectorSubtract (bestent->v.origin, ent->v.origin, dir);
+		dist = DotProduct (dir, pr_global_struct->v_forward);
+		VectorScale (pr_global_struct->v_forward, dist, end);
+		end[2] = dir[2];
+		VectorNormalize (end);
+		VectorCopy (end, G_VECTOR(OFS_RETURN));	
+	}
+	else
+	{
+		VectorCopy (bestdir, G_VECTOR(OFS_RETURN));
+	}
+}
+
+/*
+==============
+PF_changeyaw
+
+This was a major timewaster in progs, so it was converted to C
+==============
+*/
+void PF_changeyaw (void)
+{
+	edict_t		*ent;
+	float		ideal, current, move, speed;
+	
+	ent = PROG_TO_EDICT(pr_global_struct->self);
+	current = anglemod( ent->v.angles[1] );
+	ideal = ent->v.ideal_yaw;
+	speed = ent->v.yaw_speed;
+	
+	if (current == ideal)
+		return;
+	move = ideal - current;
+	if (ideal > current)
+	{
+		if (move >= 180)
+			move = move - 360;
+	}
+	else
+	{
+		if (move <= -180)
+			move = move + 360;
+	}
+	if (move > 0)
+	{
+		if (move > speed)
+			move = speed;
+	}
+	else
+	{
+		if (move < -speed)
+			move = -speed;
+	}
+	
+	ent->v.angles[1] = anglemod (current + move);
+}
+
+/*
+===============================================================================
+
+MESSAGE WRITING
+
+===============================================================================
+*/
+
+#define	MSG_BROADCAST	0		// unreliable to all
+#define	MSG_ONE			1		// reliable to one (msg_entity)
+#define	MSG_ALL			2		// reliable to all
+#define	MSG_INIT		3		// write to the init string
+#define	MSG_MULTICAST	4		// for multicast()
+
+sizebuf_t *WriteDest (void)
+{
+	int		entnum;
+	int		dest;
+	edict_t	*ent;
+
+	dest = G_FLOAT(OFS_PARM0);
+	switch (dest)
+	{
+	case MSG_BROADCAST:
+		return &sv.datagram;
+	
+	case MSG_ONE:
+		SV_Error("Shouldn't be at MSG_ONE");
+#if 0
+		ent = PROG_TO_EDICT(pr_global_struct->msg_entity);
+		entnum = NUM_FOR_EDICT(ent);
+		if (entnum < 1 || entnum > MAX_CLIENTS)
+			PR_RunError ("WriteDest: not a client");
+		return &svs.clients[entnum-1].netchan.message;
+#endif
+		
+	case MSG_ALL:
+		return &sv.reliable_datagram;
+	
+	case MSG_INIT:
+		if (sv.state != ss_loading)
+			PR_RunError ("PF_Write_*: MSG_INIT can only be written in spawn functions");
+		return &sv.signon;
+
+	case MSG_MULTICAST:
+		return &sv.multicast;
+
+	default:
+		PR_RunError ("WriteDest: bad destination");
+		break;
+	}
+	
+	return NULL;
+}
+
+static client_t *Write_GetClient(void)
+{
+	int		entnum;
+	edict_t	*ent;
+
+	ent = PROG_TO_EDICT(pr_global_struct->msg_entity);
+	entnum = NUM_FOR_EDICT(ent);
+	if (entnum < 1 || entnum > MAX_CLIENTS)
+		PR_RunError ("WriteDest: not a client");
+	return &svs.clients[entnum-1];
+}
+
+
+void PF_WriteByte (void)
+{
+	if (G_FLOAT(OFS_PARM0) == MSG_ONE) {
+		client_t *cl = Write_GetClient();
+		ClientReliableCheckBlock(cl, 1);
+		ClientReliableWrite_Byte(cl, G_FLOAT(OFS_PARM1));
+	} else
+		MSG_WriteByte (WriteDest(), G_FLOAT(OFS_PARM1));
+}
+
+void PF_WriteChar (void)
+{
+	if (G_FLOAT(OFS_PARM0) == MSG_ONE) {
+		client_t *cl = Write_GetClient();
+		ClientReliableCheckBlock(cl, 1);
+		ClientReliableWrite_Char(cl, G_FLOAT(OFS_PARM1));
+	} else
+		MSG_WriteChar (WriteDest(), G_FLOAT(OFS_PARM1));
+}
+
+void PF_WriteShort (void)
+{
+	if (G_FLOAT(OFS_PARM0) == MSG_ONE) {
+		client_t *cl = Write_GetClient();
+		ClientReliableCheckBlock(cl, 2);
+		ClientReliableWrite_Short(cl, G_FLOAT(OFS_PARM1));
+	} else
+		MSG_WriteShort (WriteDest(), G_FLOAT(OFS_PARM1));
+}
+
+void PF_WriteLong (void)
+{
+	if (G_FLOAT(OFS_PARM0) == MSG_ONE) {
+		client_t *cl = Write_GetClient();
+		ClientReliableCheckBlock(cl, 4);
+		ClientReliableWrite_Long(cl, G_FLOAT(OFS_PARM1));
+	} else
+		MSG_WriteLong (WriteDest(), G_FLOAT(OFS_PARM1));
+}
+
+void PF_WriteAngle (void)
+{
+	if (G_FLOAT(OFS_PARM0) == MSG_ONE) {
+		client_t *cl = Write_GetClient();
+		ClientReliableCheckBlock(cl, 1);
+		ClientReliableWrite_Angle(cl, G_FLOAT(OFS_PARM1));
+	} else
+		MSG_WriteAngle (WriteDest(), G_FLOAT(OFS_PARM1));
+}
+
+void PF_WriteCoord (void)
+{
+	if (G_FLOAT(OFS_PARM0) == MSG_ONE) {
+		client_t *cl = Write_GetClient();
+		ClientReliableCheckBlock(cl, 2);
+		ClientReliableWrite_Coord(cl, G_FLOAT(OFS_PARM1));
+	} else
+		MSG_WriteCoord (WriteDest(), G_FLOAT(OFS_PARM1));
+}
+
+void PF_WriteString (void)
+{
+	if (G_FLOAT(OFS_PARM0) == MSG_ONE) {
+		client_t *cl = Write_GetClient();
+		ClientReliableCheckBlock(cl, 1+strlen(G_STRING(OFS_PARM1)));
+		ClientReliableWrite_String(cl, G_STRING(OFS_PARM1));
+	} else
+		MSG_WriteString (WriteDest(), G_STRING(OFS_PARM1));
+}
+
+
+void PF_WriteEntity (void)
+{
+	if (G_FLOAT(OFS_PARM0) == MSG_ONE) {
+		client_t *cl = Write_GetClient();
+		ClientReliableCheckBlock(cl, 2);
+		ClientReliableWrite_Short(cl, G_EDICTNUM(OFS_PARM1));
+	} else
+		MSG_WriteShort (WriteDest(), G_EDICTNUM(OFS_PARM1));
+}
+
+//=============================================================================
+
+int SV_ModelIndex (char *name);
+
+void PF_makestatic (void)
+{
+	edict_t	*ent;
+	int		i;
+	
+	ent = G_EDICT(OFS_PARM0);
+
+	MSG_WriteByte (&sv.signon,svc_spawnstatic);
+
+	MSG_WriteByte (&sv.signon, SV_ModelIndex(PR_GetString(ent->v.model)));
+
+	MSG_WriteByte (&sv.signon, ent->v.frame);
+	MSG_WriteByte (&sv.signon, ent->v.colormap);
+	MSG_WriteByte (&sv.signon, ent->v.skin);
+	for (i=0 ; i<3 ; i++)
+	{
+		MSG_WriteCoord(&sv.signon, ent->v.origin[i]);
+		MSG_WriteAngle(&sv.signon, ent->v.angles[i]);
+	}
+
+// throw the entity away now
+	ED_Free (ent);
+}
+
+//=============================================================================
+
+/*
+==============
+PF_setspawnparms
+==============
+*/
+void PF_setspawnparms (void)
+{
+	edict_t	*ent;
+	int		i;
+	client_t	*client;
+
+	ent = G_EDICT(OFS_PARM0);
+	i = NUM_FOR_EDICT(ent);
+	if (i < 1 || i > MAX_CLIENTS)
+		PR_RunError ("Entity is not a client");
+
+	// copy spawn parms out of the client_t
+	client = svs.clients + (i-1);
+
+	for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
+		(&pr_global_struct->parm1)[i] = client->spawn_parms[i];
+}
+
+/*
+==============
+PF_changelevel
+==============
+*/
+void PF_changelevel (void)
+{
+	char	*s;
+	static	int	last_spawncount;
+
+// make sure we don't issue two changelevels
+	if (svs.spawncount == last_spawncount)
+		return;
+	last_spawncount = svs.spawncount;
+	
+	s = G_STRING(OFS_PARM0);
+	Cbuf_AddText (va("map %s\n",s));
+}
+
+
+/*
+==============
+PF_logfrag
+
+logfrag (killer, killee)
+==============
+*/
+void PF_logfrag (void)
+{
+	edict_t	*ent1, *ent2;
+	int		e1, e2;
+	char	*s;
+
+	ent1 = G_EDICT(OFS_PARM0);
+	ent2 = G_EDICT(OFS_PARM1);
+
+	e1 = NUM_FOR_EDICT(ent1);
+	e2 = NUM_FOR_EDICT(ent2);
+	
+	if (e1 < 1 || e1 > MAX_CLIENTS
+	|| e2 < 1 || e2 > MAX_CLIENTS)
+		return;
+	
+	s = va("\\%s\\%s\\\n",svs.clients[e1-1].name, svs.clients[e2-1].name);
+
+	SZ_Print (&svs.log[svs.logsequence&1], s);
+	if (sv_fraglogfile) {
+		fprintf (sv_fraglogfile, s);
+		fflush (sv_fraglogfile);
+	}
+}
+
+
+/*
+==============
+PF_infokey
+
+string(entity e, string key) infokey
+==============
+*/
+void PF_infokey (void)
+{
+	edict_t	*e;
+	int		e1;
+	char	*value;
+	char	*key;
+	static	char ov[256];
+
+	e = G_EDICT(OFS_PARM0);
+	e1 = NUM_FOR_EDICT(e);
+	key = G_STRING(OFS_PARM1);
+
+	if (e1 == 0) {
+		if ((value = Info_ValueForKey (svs.info, key)) == NULL ||
+			!*value)
+			value = Info_ValueForKey(localinfo, key);
+	} else if (e1 <= MAX_CLIENTS) {
+		if (!strcmp(key, "ip"))
+			value = strcpy(ov, NET_BaseAdrToString (svs.clients[e1-1].netchan.remote_address));
+		else if (!strcmp(key, "ping")) {
+			int ping = SV_CalcPing (&svs.clients[e1-1]);
+			sprintf(ov, "%d", ping);
+			value = ov;
+		} else
+			value = Info_ValueForKey (svs.clients[e1-1].userinfo, key);
+	} else
+		value = "";
+
+	RETURN_STRING(value);
+}
+
+/*
+==============
+PF_stof
+
+float(string s) stof
+==============
+*/
+void PF_stof (void)
+{
+	char	*s;
+
+	s = G_STRING(OFS_PARM0);
+
+	G_FLOAT(OFS_RETURN) = atof(s);
+}
+
+
+/*
+==============
+PF_multicast
+
+void(vector where, float set) multicast
+==============
+*/
+void PF_multicast (void)
+{
+	float	*o;
+	int		to;
+
+	o = G_VECTOR(OFS_PARM0);
+	to = G_FLOAT(OFS_PARM1);
+
+	SV_Multicast (o, to);
+}
+
+
+void PF_Fixme (void)
+{
+	PR_RunError ("unimplemented bulitin");
+}
+
+
+
+builtin_t pr_builtin[] =
+{
+	PF_Fixme,
+PF_makevectors,	// void(entity e)	makevectors 		= #1;
+PF_setorigin,	// void(entity e, vector o) setorigin	= #2;
+PF_setmodel,	// void(entity e, string m) setmodel	= #3;
+PF_setsize,	// void(entity e, vector min, vector max) setsize = #4;
+PF_Fixme,	// void(entity e, vector min, vector max) setabssize = #5;
+PF_break,	// void() break						= #6;
+PF_random,	// float() random						= #7;
+PF_sound,	// void(entity e, float chan, string samp) sound = #8;
+PF_normalize,	// vector(vector v) normalize			= #9;
+PF_error,	// void(string e) error				= #10;
+PF_objerror,	// void(string e) objerror				= #11;
+PF_vlen,	// float(vector v) vlen				= #12;
+PF_vectoyaw,	// float(vector v) vectoyaw		= #13;
+PF_Spawn,	// entity() spawn						= #14;
+PF_Remove,	// void(entity e) remove				= #15;
+PF_traceline,	// float(vector v1, vector v2, float tryents) traceline = #16;
+PF_checkclient,	// entity() clientlist					= #17;
+PF_Find,	// entity(entity start, .string fld, string match) find = #18;
+PF_precache_sound,	// void(string s) precache_sound		= #19;
+PF_precache_model,	// void(string s) precache_model		= #20;
+PF_stuffcmd,	// void(entity client, string s)stuffcmd = #21;
+PF_findradius,	// entity(vector org, float rad) findradius = #22;
+PF_bprint,	// void(string s) bprint				= #23;
+PF_sprint,	// void(entity client, string s) sprint = #24;
+PF_dprint,	// void(string s) dprint				= #25;
+PF_ftos,	// void(string s) ftos				= #26;
+PF_vtos,	// void(string s) vtos				= #27;
+PF_coredump,
+PF_traceon,
+PF_traceoff,
+PF_eprint,	// void(entity e) debug print an entire entity
+PF_walkmove, // float(float yaw, float dist) walkmove
+PF_Fixme, // float(float yaw, float dist) walkmove
+PF_droptofloor,
+PF_lightstyle,
+PF_rint,
+PF_floor,
+PF_ceil,
+PF_Fixme,
+PF_checkbottom,
+PF_pointcontents,
+PF_Fixme,
+PF_fabs,
+PF_aim,
+PF_cvar,
+PF_localcmd,
+PF_nextent,
+PF_Fixme,
+PF_changeyaw,
+PF_Fixme,
+PF_vectoangles,
+
+PF_WriteByte,
+PF_WriteChar,
+PF_WriteShort,
+PF_WriteLong,
+PF_WriteCoord,
+PF_WriteAngle,
+PF_WriteString,
+PF_WriteEntity,
+
+PF_Fixme,
+PF_Fixme,
+PF_Fixme,
+PF_Fixme,
+PF_Fixme,
+PF_Fixme,
+PF_Fixme,
+
+SV_MoveToGoal,
+PF_precache_file,
+PF_makestatic,
+
+PF_changelevel,
+PF_Fixme,
+
+PF_cvar_set,
+PF_centerprint,
+
+PF_ambientsound,
+
+PF_precache_model,
+PF_precache_sound,		// precache_sound2 is different only for qcc
+PF_precache_file,
+
+PF_setspawnparms,
+
+PF_logfrag,
+
+PF_infokey,
+PF_stof,
+PF_multicast
+};
+
+builtin_t *pr_builtins = pr_builtin;
+int pr_numbuiltins = sizeof(pr_builtin)/sizeof(pr_builtin[0]);
+
--- /dev/null
+++ b/QW/server/pr_comp.h
@@ -1,0 +1,180 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+
+// this file is shared by quake and qcc
+
+typedef int	func_t;
+typedef int	string_t;
+
+typedef enum {ev_void, ev_string, ev_float, ev_vector, ev_entity, ev_field, ev_function, ev_pointer} etype_t;
+
+
+#define	OFS_NULL		0
+#define	OFS_RETURN		1
+#define	OFS_PARM0		4		// leave 3 ofs for each parm to hold vectors
+#define	OFS_PARM1		7
+#define	OFS_PARM2		10
+#define	OFS_PARM3		13
+#define	OFS_PARM4		16
+#define	OFS_PARM5		19
+#define	OFS_PARM6		22
+#define	OFS_PARM7		25
+#define	RESERVED_OFS	28
+
+
+enum {
+	OP_DONE,
+	OP_MUL_F,
+	OP_MUL_V,
+	OP_MUL_FV,
+	OP_MUL_VF,
+	OP_DIV_F,
+	OP_ADD_F,
+	OP_ADD_V,
+	OP_SUB_F,
+	OP_SUB_V,
+	
+	OP_EQ_F,
+	OP_EQ_V,
+	OP_EQ_S,
+	OP_EQ_E,
+	OP_EQ_FNC,
+	
+	OP_NE_F,
+	OP_NE_V,
+	OP_NE_S,
+	OP_NE_E,
+	OP_NE_FNC,
+	
+	OP_LE,
+	OP_GE,
+	OP_LT,
+	OP_GT,
+
+	OP_LOAD_F,
+	OP_LOAD_V,
+	OP_LOAD_S,
+	OP_LOAD_ENT,
+	OP_LOAD_FLD,
+	OP_LOAD_FNC,
+
+	OP_ADDRESS,
+
+	OP_STORE_F,
+	OP_STORE_V,
+	OP_STORE_S,
+	OP_STORE_ENT,
+	OP_STORE_FLD,
+	OP_STORE_FNC,
+
+	OP_STOREP_F,
+	OP_STOREP_V,
+	OP_STOREP_S,
+	OP_STOREP_ENT,
+	OP_STOREP_FLD,
+	OP_STOREP_FNC,
+
+	OP_RETURN,
+	OP_NOT_F,
+	OP_NOT_V,
+	OP_NOT_S,
+	OP_NOT_ENT,
+	OP_NOT_FNC,
+	OP_IF,
+	OP_IFNOT,
+	OP_CALL0,
+	OP_CALL1,
+	OP_CALL2,
+	OP_CALL3,
+	OP_CALL4,
+	OP_CALL5,
+	OP_CALL6,
+	OP_CALL7,
+	OP_CALL8,
+	OP_STATE,
+	OP_GOTO,
+	OP_AND,
+	OP_OR,
+	
+	OP_BITAND,
+	OP_BITOR
+};
+
+
+typedef struct statement_s
+{
+	unsigned short	op;
+	short	a,b,c;
+} dstatement_t;
+
+typedef struct
+{
+	unsigned short	type;		// if DEF_SAVEGLOBGAL bit is set
+								// the variable needs to be saved in savegames
+	unsigned short	ofs;
+	int			s_name;
+} ddef_t;
+#define	DEF_SAVEGLOBAL	(1<<15)
+
+#define	MAX_PARMS	8
+
+typedef struct
+{
+	int		first_statement;	// negative numbers are builtins
+	int		parm_start;
+	int		locals;				// total ints of parms + locals
+	
+	int		profile;		// runtime
+	
+	int		s_name;
+	int		s_file;			// source file defined in
+	
+	int		numparms;
+	byte	parm_size[MAX_PARMS];
+} dfunction_t;
+
+
+#define	PROG_VERSION	6
+typedef struct
+{
+	int		version;
+	int		crc;			// check of header file
+	
+	int		ofs_statements;
+	int		numstatements;	// statement 0 is an error
+
+	int		ofs_globaldefs;
+	int		numglobaldefs;
+	
+	int		ofs_fielddefs;
+	int		numfielddefs;
+	
+	int		ofs_functions;
+	int		numfunctions;	// function 0 is an empty
+	
+	int		ofs_strings;
+	int		numstrings;		// first string is a null string
+
+	int		ofs_globals;
+	int		numglobals;
+	
+	int		entityfields;
+} dprograms_t;
+
--- /dev/null
+++ b/QW/server/pr_edict.c
@@ -1,0 +1,1085 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// sv_edict.c -- entity dictionary
+
+#include "qwsvdef.h"
+
+dprograms_t		*progs;
+dfunction_t		*pr_functions;
+char			*pr_strings;
+ddef_t			*pr_fielddefs;
+ddef_t			*pr_globaldefs;
+dstatement_t	*pr_statements;
+globalvars_t	*pr_global_struct;
+float			*pr_globals;			// same as pr_global_struct
+int				pr_edict_size;	// in bytes
+
+int		type_size[8] = {1,sizeof(void *)/4,1,3,1,1,sizeof(void *)/4,sizeof(void *)/4};
+
+ddef_t *ED_FieldAtOfs (int ofs);
+qboolean	ED_ParseEpair (void *base, ddef_t *key, char *s);
+
+#define	MAX_FIELD_LEN	64
+#define GEFV_CACHESIZE	2
+
+typedef struct {
+	ddef_t	*pcache;
+	char	field[MAX_FIELD_LEN];
+} gefv_cache;
+
+static gefv_cache	gefvCache[GEFV_CACHESIZE] = {{NULL, ""}, {NULL, ""}};
+
+func_t SpectatorConnect;
+func_t SpectatorThink;
+func_t SpectatorDisconnect;
+
+
+/*
+=================
+ED_ClearEdict
+
+Sets everything to NULL
+=================
+*/
+void ED_ClearEdict (edict_t *e)
+{
+	memset (&e->v, 0, progs->entityfields * 4);
+	e->free = false;
+}
+
+/*
+=================
+ED_Alloc
+
+Either finds a free edict, or allocates a new one.
+Try to avoid reusing an entity that was recently freed, because it
+can cause the client to think the entity morphed into something else
+instead of being removed and recreated, which can cause interpolated
+angles and bad trails.
+=================
+*/
+edict_t *ED_Alloc (void)
+{
+	int			i;
+	edict_t		*e;
+
+	for ( i=MAX_CLIENTS+1 ; i<sv.num_edicts ; i++)
+	{
+		e = EDICT_NUM(i);
+		// the first couple seconds of server time can involve a lot of
+		// freeing and allocating, so relax the replacement policy
+		if (e->free && ( e->freetime < 2 || sv.time - e->freetime > 0.5 ) )
+		{
+			ED_ClearEdict (e);
+			return e;
+		}
+	}
+	
+	if (i == MAX_EDICTS)
+	{
+		Con_Printf ("WARNING: ED_Alloc: no free edicts\n");
+		i--;	// step on whatever is the last edict
+		e = EDICT_NUM(i);
+		SV_UnlinkEdict(e);
+	}
+	else
+		sv.num_edicts++;
+	e = EDICT_NUM(i);
+	ED_ClearEdict (e);
+
+	return e;
+}
+
+/*
+=================
+ED_Free
+
+Marks the edict as free
+FIXME: walk all entities and NULL out references to this entity
+=================
+*/
+void ED_Free (edict_t *ed)
+{
+	SV_UnlinkEdict (ed);		// unlink from world bsp
+
+	ed->free = true;
+	ed->v.model = 0;
+	ed->v.takedamage = 0;
+	ed->v.modelindex = 0;
+	ed->v.colormap = 0;
+	ed->v.skin = 0;
+	ed->v.frame = 0;
+	VectorCopy (vec3_origin, ed->v.origin);
+	VectorCopy (vec3_origin, ed->v.angles);
+	ed->v.nextthink = -1;
+	ed->v.solid = 0;
+	
+	ed->freetime = sv.time;
+}
+
+//===========================================================================
+
+/*
+============
+ED_GlobalAtOfs
+============
+*/
+ddef_t *ED_GlobalAtOfs (int ofs)
+{
+	ddef_t		*def;
+	int			i;
+	
+	for (i=0 ; i<progs->numglobaldefs ; i++)
+	{
+		def = &pr_globaldefs[i];
+		if (def->ofs == ofs)
+			return def;
+	}
+	return NULL;
+}
+
+/*
+============
+ED_FieldAtOfs
+============
+*/
+ddef_t *ED_FieldAtOfs (int ofs)
+{
+	ddef_t		*def;
+	int			i;
+	
+	for (i=0 ; i<progs->numfielddefs ; i++)
+	{
+		def = &pr_fielddefs[i];
+		if (def->ofs == ofs)
+			return def;
+	}
+	return NULL;
+}
+
+/*
+============
+ED_FindField
+============
+*/
+ddef_t *ED_FindField (char *name)
+{
+	ddef_t		*def;
+	int			i;
+	
+	for (i=0 ; i<progs->numfielddefs ; i++)
+	{
+		def = &pr_fielddefs[i];
+		if (!strcmp(PR_GetString(def->s_name),name) )
+			return def;
+	}
+	return NULL;
+}
+
+
+/*
+============
+ED_FindGlobal
+============
+*/
+ddef_t *ED_FindGlobal (char *name)
+{
+	ddef_t		*def;
+	int			i;
+	
+	for (i=0 ; i<progs->numglobaldefs ; i++)
+	{
+		def = &pr_globaldefs[i];
+		if (!strcmp(PR_GetString(def->s_name),name) )
+			return def;
+	}
+	return NULL;
+}
+
+
+/*
+============
+ED_FindFunction
+============
+*/
+dfunction_t *ED_FindFunction (char *name)
+{
+	dfunction_t		*func;
+	int				i;
+	
+	for (i=0 ; i<progs->numfunctions ; i++)
+	{
+		func = &pr_functions[i];
+		if (!strcmp(PR_GetString(func->s_name),name) )
+			return func;
+	}
+	return NULL;
+}
+
+eval_t *GetEdictFieldValue(edict_t *ed, char *field)
+{
+	ddef_t			*def = NULL;
+	int				i;
+	static int		rep = 0;
+
+	for (i=0 ; i<GEFV_CACHESIZE ; i++)
+	{
+		if (!strcmp(field, gefvCache[i].field))
+		{
+			def = gefvCache[i].pcache;
+			goto Done;
+		}
+	}
+
+	def = ED_FindField (field);
+
+	if (strlen(field) < MAX_FIELD_LEN)
+	{
+		gefvCache[rep].pcache = def;
+		strcpy (gefvCache[rep].field, field);
+		rep ^= 1;
+	}
+
+Done:
+	if (!def)
+		return NULL;
+
+	return (eval_t *)((char *)&ed->v + def->ofs*4);
+}
+
+/*
+============
+PR_ValueString
+
+Returns a string describing *data in a type specific manner
+=============
+*/
+char *PR_ValueString (etype_t type, eval_t *val)
+{
+	static char	line[256];
+	ddef_t		*def;
+	dfunction_t	*f;
+	
+	type &= ~DEF_SAVEGLOBAL;
+
+	switch (type)
+	{
+	case ev_string:
+		sprintf (line, "%s", PR_GetString(val->string));
+		break;
+	case ev_entity:	
+		sprintf (line, "entity %i", NUM_FOR_EDICT(PROG_TO_EDICT(val->edict)) );
+		break;
+	case ev_function:
+		f = pr_functions + val->function;
+		sprintf (line, "%s()", PR_GetString(f->s_name));
+		break;
+	case ev_field:
+		def = ED_FieldAtOfs ( val->_int );
+		sprintf (line, ".%s", PR_GetString(def->s_name));
+		break;
+	case ev_void:
+		sprintf (line, "void");
+		break;
+	case ev_float:
+		sprintf (line, "%5.1f", val->_float);
+		break;
+	case ev_vector:
+		sprintf (line, "'%5.1f %5.1f %5.1f'", val->vector[0], val->vector[1], val->vector[2]);
+		break;
+	case ev_pointer:
+		sprintf (line, "pointer");
+		break;
+	default:
+		sprintf (line, "bad type %i", type);
+		break;
+	}
+	
+	return line;
+}
+
+/*
+============
+PR_UglyValueString
+
+Returns a string describing *data in a type specific manner
+Easier to parse than PR_ValueString
+=============
+*/
+char *PR_UglyValueString (etype_t type, eval_t *val)
+{
+	static char	line[256];
+	ddef_t		*def;
+	dfunction_t	*f;
+	
+	type &= ~DEF_SAVEGLOBAL;
+
+	switch (type)
+	{
+	case ev_string:
+		sprintf (line, "%s", PR_GetString(val->string));
+		break;
+	case ev_entity:	
+		sprintf (line, "%i", NUM_FOR_EDICT(PROG_TO_EDICT(val->edict)));
+		break;
+	case ev_function:
+		f = pr_functions + val->function;
+		sprintf (line, "%s", PR_GetString(f->s_name));
+		break;
+	case ev_field:
+		def = ED_FieldAtOfs ( val->_int );
+		sprintf (line, "%s", PR_GetString(def->s_name));
+		break;
+	case ev_void:
+		sprintf (line, "void");
+		break;
+	case ev_float:
+		sprintf (line, "%f", val->_float);
+		break;
+	case ev_vector:
+		sprintf (line, "%f %f %f", val->vector[0], val->vector[1], val->vector[2]);
+		break;
+	default:
+		sprintf (line, "bad type %i", type);
+		break;
+	}
+	
+	return line;
+}
+
+/*
+============
+PR_GlobalString
+
+Returns a string with a description and the contents of a global,
+padded to 20 field width
+============
+*/
+char *PR_GlobalString (int ofs)
+{
+	char	*s;
+	int		i;
+	ddef_t	*def;
+	void	*val;
+	static char	line[128];
+	
+	val = (void *)&pr_globals[ofs];
+	def = ED_GlobalAtOfs(ofs);
+	if (!def)
+		sprintf (line,"%i(???)", ofs);
+	else
+	{
+		s = PR_ValueString (def->type, val);
+		sprintf (line,"%i(%s)%s", ofs, PR_GetString(def->s_name), s);
+	}
+	
+	i = strlen(line);
+	for ( ; i<20 ; i++)
+		strcat (line," ");
+	strcat (line," ");
+		
+	return line;
+}
+
+char *PR_GlobalStringNoContents (int ofs)
+{
+	int		i;
+	ddef_t	*def;
+	static char	line[128];
+	
+	def = ED_GlobalAtOfs(ofs);
+	if (!def)
+		sprintf (line,"%i(???)", ofs);
+	else
+		sprintf (line,"%i(%s)", ofs, PR_GetString(def->s_name));
+	
+	i = strlen(line);
+	for ( ; i<20 ; i++)
+		strcat (line," ");
+	strcat (line," ");
+		
+	return line;
+}
+
+
+/*
+=============
+ED_Print
+
+For debugging
+=============
+*/
+void ED_Print (edict_t *ed)
+{
+	int		l;
+	ddef_t	*d;
+	int		*v;
+	int		i, j;
+	char	*name;
+	int		type;
+
+	if (ed->free)
+	{
+		Con_Printf ("FREE\n");
+		return;
+	}
+	
+	for (i=1 ; i<progs->numfielddefs ; i++)
+	{
+		d = &pr_fielddefs[i];
+		name = PR_GetString(d->s_name);
+		if (name[strlen(name)-2] == '_')
+			continue;	// skip _x, _y, _z vars
+			
+		v = (int *)((char *)&ed->v + d->ofs*4);
+
+	// if the value is still all 0, skip the field
+		type = d->type & ~DEF_SAVEGLOBAL;
+		
+		for (j=0 ; j<type_size[type] ; j++)
+			if (v[j])
+				break;
+		if (j == type_size[type])
+			continue;
+	
+		Con_Printf ("%s",name);
+		l = strlen (name);
+		while (l++ < 15)
+			Con_Printf (" ");
+
+		Con_Printf ("%s\n", PR_ValueString(d->type, (eval_t *)v));		
+	}
+}
+
+/*
+=============
+ED_Write
+
+For savegames
+=============
+*/
+void ED_Write (FILE *f, edict_t *ed)
+{
+	ddef_t	*d;
+	int		*v;
+	int		i, j;
+	char	*name;
+	int		type;
+
+	fprintf (f, "{\n");
+
+	if (ed->free)
+	{
+		fprintf (f, "}\n");
+		return;
+	}
+	
+	for (i=1 ; i<progs->numfielddefs ; i++)
+	{
+		d = &pr_fielddefs[i];
+		name = PR_GetString(d->s_name);
+		if (name[strlen(name)-2] == '_')
+			continue;	// skip _x, _y, _z vars
+			
+		v = (int *)((char *)&ed->v + d->ofs*4);
+
+	// if the value is still all 0, skip the field
+		type = d->type & ~DEF_SAVEGLOBAL;
+		for (j=0 ; j<type_size[type] ; j++)
+			if (v[j])
+				break;
+		if (j == type_size[type])
+			continue;
+	
+		fprintf (f,"\"%s\" ",name);
+		fprintf (f,"\"%s\"\n", PR_UglyValueString(d->type, (eval_t *)v));		
+	}
+
+	fprintf (f, "}\n");
+}
+
+void ED_PrintNum (int ent)
+{
+	ED_Print (EDICT_NUM(ent));
+}
+
+/*
+=============
+ED_PrintEdicts
+
+For debugging, prints all the entities in the current server
+=============
+*/
+void ED_PrintEdicts (void)
+{
+	int		i;
+	
+	Con_Printf ("%i entities\n", sv.num_edicts);
+	for (i=0 ; i<sv.num_edicts ; i++)
+	{
+		Con_Printf ("\nEDICT %i:\n",i);
+		ED_PrintNum (i);
+	}
+}
+
+/*
+=============
+ED_PrintEdict_f
+
+For debugging, prints a single edicy
+=============
+*/
+void ED_PrintEdict_f (void)
+{
+	int		i;
+	
+	i = Q_atoi (Cmd_Argv(1));
+	Con_Printf ("\n EDICT %i:\n",i);
+	ED_PrintNum (i);
+}
+
+/*
+=============
+ED_Count
+
+For debugging
+=============
+*/
+void ED_Count (void)
+{
+	int		i;
+	edict_t	*ent;
+	int		active, models, solid, step;
+
+	active = models = solid = step = 0;
+	for (i=0 ; i<sv.num_edicts ; i++)
+	{
+		ent = EDICT_NUM(i);
+		if (ent->free)
+			continue;
+		active++;
+		if (ent->v.solid)
+			solid++;
+		if (ent->v.model)
+			models++;
+		if (ent->v.movetype == MOVETYPE_STEP)
+			step++;
+	}
+
+	Con_Printf ("num_edicts:%3i\n", sv.num_edicts);
+	Con_Printf ("active    :%3i\n", active);
+	Con_Printf ("view      :%3i\n", models);
+	Con_Printf ("touch     :%3i\n", solid);
+	Con_Printf ("step      :%3i\n", step);
+
+}
+
+/*
+==============================================================================
+
+					ARCHIVING GLOBALS
+
+FIXME: need to tag constants, doesn't really work
+==============================================================================
+*/
+
+/*
+=============
+ED_WriteGlobals
+=============
+*/
+void ED_WriteGlobals (FILE *f)
+{
+	ddef_t		*def;
+	int			i;
+	char		*name;
+	int			type;
+
+	fprintf (f,"{\n");
+	for (i=0 ; i<progs->numglobaldefs ; i++)
+	{
+		def = &pr_globaldefs[i];
+		type = def->type;
+		if ( !(def->type & DEF_SAVEGLOBAL) )
+			continue;
+		type &= ~DEF_SAVEGLOBAL;
+
+		if (type != ev_string
+		&& type != ev_float
+		&& type != ev_entity)
+			continue;
+
+		name = PR_GetString(def->s_name);
+		fprintf (f,"\"%s\" ", name);
+		fprintf (f,"\"%s\"\n", PR_UglyValueString(type, (eval_t *)&pr_globals[def->ofs]));		
+	}
+	fprintf (f,"}\n");
+}
+
+/*
+=============
+ED_ParseGlobals
+=============
+*/
+void ED_ParseGlobals (char *data)
+{
+	char	keyname[64];
+	ddef_t	*key;
+
+	while (1)
+	{	
+	// parse key
+		data = COM_Parse (data);
+		if (com_token[0] == '}')
+			break;
+		if (!data)
+			SV_Error ("ED_ParseEntity: EOF without closing brace");
+
+		strcpy (keyname, com_token);
+
+	// parse value	
+		data = COM_Parse (data);
+		if (!data)
+			SV_Error ("ED_ParseEntity: EOF without closing brace");
+
+		if (com_token[0] == '}')
+			SV_Error ("ED_ParseEntity: closing brace without data");
+
+		key = ED_FindGlobal (keyname);
+		if (!key)
+		{
+			Con_Printf ("%s is not a global\n", keyname);
+			continue;
+		}
+
+		if (!ED_ParseEpair ((void *)pr_globals, key, com_token))
+			SV_Error ("ED_ParseGlobals: parse error");
+	}
+}
+
+//============================================================================
+
+
+/*
+=============
+ED_NewString
+=============
+*/
+char *ED_NewString (char *string)
+{
+	char	*new, *new_p;
+	int		i,l;
+	
+	l = strlen(string) + 1;
+	new = Hunk_Alloc (l);
+	new_p = new;
+
+	for (i=0 ; i< l ; i++)
+	{
+		if (string[i] == '\\' && i < l-1)
+		{
+			i++;
+			if (string[i] == 'n')
+				*new_p++ = '\n';
+			else
+				*new_p++ = '\\';
+		}
+		else
+			*new_p++ = string[i];
+	}
+	
+	return new;
+}
+
+
+/*
+=============
+ED_ParseEval
+
+Can parse either fields or globals
+returns false if error
+=============
+*/
+qboolean	ED_ParseEpair (void *base, ddef_t *key, char *s)
+{
+	int		i;
+	char	string[128];
+	ddef_t	*def;
+	char	*v, *w;
+	void	*d;
+	dfunction_t	*func;
+	
+	d = (void *)((int *)base + key->ofs);
+	
+	switch (key->type & ~DEF_SAVEGLOBAL)
+	{
+	case ev_string:
+		*(string_t *)d = PR_SetString(ED_NewString (s));
+		break;
+		
+	case ev_float:
+		*(float *)d = atof (s);
+		break;
+		
+	case ev_vector:
+		strcpy (string, s);
+		v = string;
+		w = string;
+		for (i=0 ; i<3 ; i++)
+		{
+			while (*v && *v != ' ')
+				v++;
+			*v = 0;
+			((float *)d)[i] = atof (w);
+			w = v = v+1;
+		}
+		break;
+		
+	case ev_entity:
+		*(int *)d = EDICT_TO_PROG(EDICT_NUM(atoi (s)));
+		break;
+		
+	case ev_field:
+		def = ED_FindField (s);
+		if (!def)
+		{
+			Con_Printf ("Can't find field %s\n", s);
+			return false;
+		}
+		*(int *)d = G_INT(def->ofs);
+		break;
+	
+	case ev_function:
+		func = ED_FindFunction (s);
+		if (!func)
+		{
+			Con_Printf ("Can't find function %s\n", s);
+			return false;
+		}
+		*(func_t *)d = func - pr_functions;
+		break;
+		
+	default:
+		break;
+	}
+	return true;
+}
+
+/*
+====================
+ED_ParseEdict
+
+Parses an edict out of the given string, returning the new position
+ed should be a properly initialized empty edict.
+Used for initial level load and for savegames.
+====================
+*/
+char *ED_ParseEdict (char *data, edict_t *ent)
+{
+	ddef_t		*key;
+	qboolean	anglehack;
+	qboolean	init;
+	char		keyname[256];
+
+	init = false;
+
+// clear it
+	if (ent != sv.edicts)	// hack
+		memset (&ent->v, 0, progs->entityfields * 4);
+
+// go through all the dictionary pairs
+	while (1)
+	{	
+	// parse key
+		data = COM_Parse (data);
+		if (com_token[0] == '}')
+			break;
+		if (!data)
+			SV_Error ("ED_ParseEntity: EOF without closing brace");
+		
+// anglehack is to allow QuakeEd to write single scalar angles
+// and allow them to be turned into vectors. (FIXME...)
+if (!strcmp(com_token, "angle"))
+{
+	strcpy (com_token, "angles");
+	anglehack = true;
+}
+else
+	anglehack = false;
+
+// FIXME: change light to _light to get rid of this hack
+if (!strcmp(com_token, "light"))
+	strcpy (com_token, "light_lev");	// hack for single light def
+
+		strcpy (keyname, com_token);
+		
+	// parse value	
+		data = COM_Parse (data);
+		if (!data)
+			SV_Error ("ED_ParseEntity: EOF without closing brace");
+
+		if (com_token[0] == '}')
+			SV_Error ("ED_ParseEntity: closing brace without data");
+
+		init = true;	
+
+// keynames with a leading underscore are used for utility comments,
+// and are immediately discarded by quake
+		if (keyname[0] == '_')
+			continue;
+		
+		key = ED_FindField (keyname);
+		if (!key)
+		{
+			Con_Printf ("%s is not a field\n", keyname);
+			continue;
+		}
+
+if (anglehack)
+{
+char	temp[32];
+strcpy (temp, com_token);
+sprintf (com_token, "0 %s 0", temp);
+}
+
+		if (!ED_ParseEpair ((void *)&ent->v, key, com_token))
+			SV_Error ("ED_ParseEdict: parse error");
+	}
+
+	if (!init)
+		ent->free = true;
+
+	return data;
+}
+
+
+/*
+================
+ED_LoadFromFile
+
+The entities are directly placed in the array, rather than allocated with
+ED_Alloc, because otherwise an error loading the map would have entity
+number references out of order.
+
+Creates a server's entity / program execution context by
+parsing textual entity definitions out of an ent file.
+
+Used for both fresh maps and savegame loads.  A fresh map would also need
+to call ED_CallSpawnFunctions () to let the objects initialize themselves.
+================
+*/
+void ED_LoadFromFile (char *data)
+{	
+	edict_t		*ent;
+	int			inhibit;
+	dfunction_t	*func;
+	
+	ent = NULL;
+	inhibit = 0;
+	pr_global_struct->time = sv.time;
+	
+// parse ents
+	while (1)
+	{
+// parse the opening brace	
+		data = COM_Parse (data);
+		if (!data)
+			break;
+		if (com_token[0] != '{')
+			SV_Error ("ED_LoadFromFile: found %s when expecting {",com_token);
+
+		if (!ent)
+			ent = EDICT_NUM(0);
+		else
+			ent = ED_Alloc ();
+		data = ED_ParseEdict (data, ent);
+		
+// remove things from different skill levels or deathmatch
+		if (((int)ent->v.spawnflags & SPAWNFLAG_NOT_DEATHMATCH))
+		{
+			ED_Free (ent);	
+			inhibit++;
+			continue;
+		}
+
+//
+// immediately call spawn function
+//
+		if (!ent->v.classname)
+		{
+			Con_Printf ("No classname for:\n");
+			ED_Print (ent);
+			ED_Free (ent);
+			continue;
+		}
+		
+	// look for the spawn function
+		func = ED_FindFunction ( PR_GetString(ent->v.classname) );
+
+		if (!func)
+		{
+			Con_Printf ("No spawn function for:\n");
+			ED_Print (ent);
+			ED_Free (ent);
+			continue;
+		}
+
+		pr_global_struct->self = EDICT_TO_PROG(ent);
+		PR_ExecuteProgram (func - pr_functions);
+		SV_FlushSignon();
+	}	
+
+	Con_DPrintf ("%i entities inhibited\n", inhibit);
+}
+
+
+/*
+===============
+PR_LoadProgs
+===============
+*/
+void PR_LoadProgs (void)
+{
+	int		i;
+	char	num[32];
+	dfunction_t *f;
+
+// flush the non-C variable lookup cache
+	for (i=0 ; i<GEFV_CACHESIZE ; i++)
+		gefvCache[i].field[0] = 0;
+
+	progs = (dprograms_t *)COM_LoadHunkFile ("qwprogs.dat");
+	if (!progs)
+		progs = (dprograms_t *)COM_LoadHunkFile ("progs.dat");
+	if (!progs)
+		SV_Error ("PR_LoadProgs: couldn't load progs.dat");
+	Con_DPrintf ("Programs occupy %iK.\n", com_filesize/1024);
+
+// add prog crc to the serverinfo
+	sprintf (num, "%i", CRC_Block ((byte *)progs, com_filesize));
+	Info_SetValueForStarKey (svs.info, "*progs", num, MAX_SERVERINFO_STRING);
+
+// byte swap the header
+	for (i=0 ; i<sizeof(*progs)/4 ; i++)
+		((int *)progs)[i] = LittleLong ( ((int *)progs)[i] );		
+
+	if (progs->version != PROG_VERSION)
+		SV_Error ("progs.dat has wrong version number (%i should be %i)", progs->version, PROG_VERSION);
+	if (progs->crc != PROGHEADER_CRC)
+		SV_Error ("You must have the progs.dat from QuakeWorld installed");
+
+	pr_functions = (dfunction_t *)((byte *)progs + progs->ofs_functions);
+	pr_strings = (char *)progs + progs->ofs_strings;
+	pr_globaldefs = (ddef_t *)((byte *)progs + progs->ofs_globaldefs);
+	pr_fielddefs = (ddef_t *)((byte *)progs + progs->ofs_fielddefs);
+	pr_statements = (dstatement_t *)((byte *)progs + progs->ofs_statements);
+
+	num_prstr = 0;
+
+	pr_global_struct = (globalvars_t *)((byte *)progs + progs->ofs_globals);
+	pr_globals = (float *)pr_global_struct;
+	
+	pr_edict_size = progs->entityfields * 4 + sizeof (edict_t) - sizeof(entvars_t);
+	
+// byte swap the lumps
+	for (i=0 ; i<progs->numstatements ; i++)
+	{
+		pr_statements[i].op = LittleShort(pr_statements[i].op);
+		pr_statements[i].a = LittleShort(pr_statements[i].a);
+		pr_statements[i].b = LittleShort(pr_statements[i].b);
+		pr_statements[i].c = LittleShort(pr_statements[i].c);
+	}
+
+	for (i=0 ; i<progs->numfunctions; i++)
+	{
+	pr_functions[i].first_statement = LittleLong (pr_functions[i].first_statement);
+	pr_functions[i].parm_start = LittleLong (pr_functions[i].parm_start);
+	pr_functions[i].s_name = LittleLong (pr_functions[i].s_name);
+	pr_functions[i].s_file = LittleLong (pr_functions[i].s_file);
+	pr_functions[i].numparms = LittleLong (pr_functions[i].numparms);
+	pr_functions[i].locals = LittleLong (pr_functions[i].locals);
+	}	
+
+	for (i=0 ; i<progs->numglobaldefs ; i++)
+	{
+		pr_globaldefs[i].type = LittleShort (pr_globaldefs[i].type);
+		pr_globaldefs[i].ofs = LittleShort (pr_globaldefs[i].ofs);
+		pr_globaldefs[i].s_name = LittleLong (pr_globaldefs[i].s_name);
+	}
+
+	for (i=0 ; i<progs->numfielddefs ; i++)
+	{
+		pr_fielddefs[i].type = LittleShort (pr_fielddefs[i].type);
+		if (pr_fielddefs[i].type & DEF_SAVEGLOBAL)
+			SV_Error ("PR_LoadProgs: pr_fielddefs[i].type & DEF_SAVEGLOBAL");
+		pr_fielddefs[i].ofs = LittleShort (pr_fielddefs[i].ofs);
+		pr_fielddefs[i].s_name = LittleLong (pr_fielddefs[i].s_name);
+	}
+
+	for (i=0 ; i<progs->numglobals ; i++)
+		((int *)pr_globals)[i] = LittleLong (((int *)pr_globals)[i]);
+
+	// Zoid, find the spectator functions
+	SpectatorConnect = SpectatorThink = SpectatorDisconnect = 0;
+
+	if ((f = ED_FindFunction ("SpectatorConnect")) != NULL)
+		SpectatorConnect = (func_t)(f - pr_functions);
+	if ((f = ED_FindFunction ("SpectatorThink")) != NULL)
+		SpectatorThink = (func_t)(f - pr_functions);
+	if ((f = ED_FindFunction ("SpectatorDisconnect")) != NULL)
+		SpectatorDisconnect = (func_t)(f - pr_functions);
+}
+
+
+/*
+===============
+PR_Init
+===============
+*/
+void PR_Init (void)
+{
+	Cmd_AddCommand ("edict", ED_PrintEdict_f);
+	Cmd_AddCommand ("edicts", ED_PrintEdicts);
+	Cmd_AddCommand ("edictcount", ED_Count);
+	Cmd_AddCommand ("profile", PR_Profile_f);
+}
+
+
+
+edict_t *EDICT_NUM(int n)
+{
+	if (n < 0 || n >= MAX_EDICTS)
+		SV_Error ("EDICT_NUM: bad number %i", n);
+	return (edict_t *)((byte *)sv.edicts+ (n)*pr_edict_size);
+}
+
+int NUM_FOR_EDICT(edict_t *e)
+{
+	int		b;
+	
+	b = (byte *)e - (byte *)sv.edicts;
+	b = b / pr_edict_size;
+	
+	if (b < 0 || b >= sv.num_edicts)
+		SV_Error ("NUM_FOR_EDICT: bad pointer");
+	return b;
+}
+
+
--- /dev/null
+++ b/QW/server/pr_exec.c
@@ -1,0 +1,699 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+
+#include "qwsvdef.h"
+
+
+/*
+
+*/
+
+typedef struct
+{
+	int				s;
+	dfunction_t		*f;
+} prstack_t;
+
+#define	MAX_STACK_DEPTH		32
+prstack_t	pr_stack[MAX_STACK_DEPTH];
+int			pr_depth;
+
+#define	LOCALSTACK_SIZE		2048
+int			localstack[LOCALSTACK_SIZE];
+int			localstack_used;
+
+
+qboolean	pr_trace;
+dfunction_t	*pr_xfunction;
+int			pr_xstatement;
+
+
+int		pr_argc;
+
+char *pr_opnames[] =
+{
+"DONE",
+
+"MUL_F",
+"MUL_V", 
+"MUL_FV",
+"MUL_VF",
+ 
+"DIV",
+
+"ADD_F",
+"ADD_V", 
+  
+"SUB_F",
+"SUB_V",
+
+"EQ_F",
+"EQ_V",
+"EQ_S", 
+"EQ_E",
+"EQ_FNC",
+ 
+"NE_F",
+"NE_V", 
+"NE_S",
+"NE_E", 
+"NE_FNC",
+ 
+"LE",
+"GE",
+"LT",
+"GT", 
+
+"INDIRECT",
+"INDIRECT",
+"INDIRECT", 
+"INDIRECT", 
+"INDIRECT",
+"INDIRECT", 
+
+"ADDRESS", 
+
+"STORE_F",
+"STORE_V",
+"STORE_S",
+"STORE_ENT",
+"STORE_FLD",
+"STORE_FNC",
+
+"STOREP_F",
+"STOREP_V",
+"STOREP_S",
+"STOREP_ENT",
+"STOREP_FLD",
+"STOREP_FNC",
+
+"RETURN",
+  
+"NOT_F",
+"NOT_V",
+"NOT_S", 
+"NOT_ENT", 
+"NOT_FNC", 
+  
+"IF",
+"IFNOT",
+  
+"CALL0",
+"CALL1",
+"CALL2",
+"CALL3",
+"CALL4",
+"CALL5",
+"CALL6",
+"CALL7",
+"CALL8",
+  
+"STATE",
+  
+"GOTO", 
+  
+"AND",
+"OR", 
+
+"BITAND",
+"BITOR"
+};
+
+char *PR_GlobalString (int ofs);
+char *PR_GlobalStringNoContents (int ofs);
+
+
+//=============================================================================
+
+/*
+=================
+PR_PrintStatement
+=================
+*/
+void PR_PrintStatement (dstatement_t *s)
+{
+	int		i;
+	
+	if ( (unsigned)s->op < sizeof(pr_opnames)/sizeof(pr_opnames[0]))
+	{
+		Con_Printf ("%s ",  pr_opnames[s->op]);
+		i = strlen(pr_opnames[s->op]);
+		for ( ; i<10 ; i++)
+			Con_Printf (" ");
+	}
+		
+	if (s->op == OP_IF || s->op == OP_IFNOT)
+		Con_Printf ("%sbranch %i",PR_GlobalString(s->a),s->b);
+	else if (s->op == OP_GOTO)
+	{
+		Con_Printf ("branch %i",s->a);
+	}
+	else if ( (unsigned)(s->op - OP_STORE_F) < 6)
+	{
+		Con_Printf ("%s",PR_GlobalString(s->a));
+		Con_Printf ("%s", PR_GlobalStringNoContents(s->b));
+	}
+	else
+	{
+		if (s->a)
+			Con_Printf ("%s",PR_GlobalString(s->a));
+		if (s->b)
+			Con_Printf ("%s",PR_GlobalString(s->b));
+		if (s->c)
+			Con_Printf ("%s", PR_GlobalStringNoContents(s->c));
+	}
+	Con_Printf ("\n");
+}
+
+/*
+============
+PR_StackTrace
+============
+*/
+void PR_StackTrace (void)
+{
+	dfunction_t	*f;
+	int			i;
+	
+	if (pr_depth == 0)
+	{
+		Con_Printf ("<NO STACK>\n");
+		return;
+	}
+	
+	pr_stack[pr_depth].f = pr_xfunction;
+	for (i=pr_depth ; i>=0 ; i--)
+	{
+		f = pr_stack[i].f;
+		
+		if (!f)
+		{
+			Con_Printf ("<NO FUNCTION>\n");
+		}
+		else
+			Con_Printf ("%12s : %s\n", PR_GetString(f->s_file), PR_GetString(f->s_name));		
+	}
+}
+
+
+/*
+============
+PR_Profile_f
+
+============
+*/
+void PR_Profile_f (void)
+{
+	dfunction_t	*f, *best;
+	int			max;
+	int			num;
+	int			i;
+	
+	num = 0;	
+	do
+	{
+		max = 0;
+		best = NULL;
+		for (i=0 ; i<progs->numfunctions ; i++)
+		{
+			f = &pr_functions[i];
+			if (f->profile > max)
+			{
+				max = f->profile;
+				best = f;
+			}
+		}
+		if (best)
+		{
+			if (num < 10)
+				Con_Printf ("%7i %s\n", best->profile, PR_GetString(best->s_name));
+			num++;
+			best->profile = 0;
+		}
+	} while (best);
+}
+
+
+/*
+============
+PR_RunError
+
+Aborts the currently executing function
+============
+*/
+void PR_RunError (char *error, ...)
+{
+	va_list		argptr;
+	char		string[1024];
+
+	va_start (argptr,error);
+	vsprintf (string,error,argptr);
+	va_end (argptr);
+
+	PR_PrintStatement (pr_statements + pr_xstatement);
+	PR_StackTrace ();
+	Con_Printf ("%s\n", string);
+	
+	pr_depth = 0;		// dump the stack so SV_Error can shutdown functions
+
+	SV_Error ("Program error");
+}
+
+/*
+============================================================================
+PR_ExecuteProgram
+
+The interpretation main loop
+============================================================================
+*/
+
+/*
+====================
+PR_EnterFunction
+
+Returns the new program statement counter
+====================
+*/
+int PR_EnterFunction (dfunction_t *f)
+{
+	int		i, j, c, o;
+
+	pr_stack[pr_depth].s = pr_xstatement;
+	pr_stack[pr_depth].f = pr_xfunction;	
+	pr_depth++;
+	if (pr_depth >= MAX_STACK_DEPTH)
+		PR_RunError ("stack overflow");
+
+// save off any locals that the new function steps on
+	c = f->locals;
+	if (localstack_used + c > LOCALSTACK_SIZE)
+		PR_RunError ("PR_ExecuteProgram: locals stack overflow\n");
+
+	for (i=0 ; i < c ; i++)
+		localstack[localstack_used+i] = ((int *)pr_globals)[f->parm_start + i];
+	localstack_used += c;
+
+// copy parameters
+	o = f->parm_start;
+	for (i=0 ; i<f->numparms ; i++)
+	{
+		for (j=0 ; j<f->parm_size[i] ; j++)
+		{
+			((int *)pr_globals)[o] = ((int *)pr_globals)[OFS_PARM0+i*3+j];
+			o++;
+		}
+	}
+
+	pr_xfunction = f;
+	return f->first_statement - 1;	// offset the s++
+}
+
+/*
+====================
+PR_LeaveFunction
+====================
+*/
+int PR_LeaveFunction (void)
+{
+	int		i, c;
+
+	if (pr_depth <= 0)
+		SV_Error ("prog stack underflow");
+
+// restore locals from the stack
+	c = pr_xfunction->locals;
+	localstack_used -= c;
+	if (localstack_used < 0)
+		PR_RunError ("PR_ExecuteProgram: locals stack underflow\n");
+
+	for (i=0 ; i < c ; i++)
+		((int *)pr_globals)[pr_xfunction->parm_start + i] = localstack[localstack_used+i];
+
+// up stack
+	pr_depth--;
+	pr_xfunction = pr_stack[pr_depth].f;
+	return pr_stack[pr_depth].s;
+}
+
+
+/*
+====================
+PR_ExecuteProgram
+====================
+*/
+void PR_ExecuteProgram (func_t fnum)
+{
+	eval_t	*a, *b, *c;
+	int			s;
+	dstatement_t	*st;
+	dfunction_t	*f, *newf;
+	int		runaway;
+	int		i;
+	edict_t	*ed;
+	int		exitdepth;
+	eval_t	*ptr;
+
+	if (!fnum || fnum >= progs->numfunctions)
+	{
+		if (pr_global_struct->self)
+			ED_Print (PROG_TO_EDICT(pr_global_struct->self));
+		SV_Error ("PR_ExecuteProgram: NULL function");
+	}
+	
+	f = &pr_functions[fnum];
+
+	runaway = 100000;
+	pr_trace = false;
+
+// make a stack frame
+	exitdepth = pr_depth;
+
+	s = PR_EnterFunction (f);
+	
+while (1)
+{
+	s++;	// next statement
+
+	st = &pr_statements[s];
+	a = (eval_t *)&pr_globals[st->a];
+	b = (eval_t *)&pr_globals[st->b];
+	c = (eval_t *)&pr_globals[st->c];
+	
+	if (--runaway == 0)
+		PR_RunError ("runaway loop error");
+		
+	pr_xfunction->profile++;
+	pr_xstatement = s;
+	
+	if (pr_trace)
+		PR_PrintStatement (st);
+		
+	switch (st->op)
+	{
+	case OP_ADD_F:
+		c->_float = a->_float + b->_float;
+		break;
+	case OP_ADD_V:
+		c->vector[0] = a->vector[0] + b->vector[0];
+		c->vector[1] = a->vector[1] + b->vector[1];
+		c->vector[2] = a->vector[2] + b->vector[2];
+		break;
+		
+	case OP_SUB_F:
+		c->_float = a->_float - b->_float;
+		break;
+	case OP_SUB_V:
+		c->vector[0] = a->vector[0] - b->vector[0];
+		c->vector[1] = a->vector[1] - b->vector[1];
+		c->vector[2] = a->vector[2] - b->vector[2];
+		break;
+
+	case OP_MUL_F:
+		c->_float = a->_float * b->_float;
+		break;
+	case OP_MUL_V:
+		c->_float = a->vector[0]*b->vector[0]
+				+ a->vector[1]*b->vector[1]
+				+ a->vector[2]*b->vector[2];
+		break;
+	case OP_MUL_FV:
+		c->vector[0] = a->_float * b->vector[0];
+		c->vector[1] = a->_float * b->vector[1];
+		c->vector[2] = a->_float * b->vector[2];
+		break;
+	case OP_MUL_VF:
+		c->vector[0] = b->_float * a->vector[0];
+		c->vector[1] = b->_float * a->vector[1];
+		c->vector[2] = b->_float * a->vector[2];
+		break;
+
+	case OP_DIV_F:
+		c->_float = a->_float / b->_float;
+		break;
+	
+	case OP_BITAND:
+		c->_float = (int)a->_float & (int)b->_float;
+		break;
+	
+	case OP_BITOR:
+		c->_float = (int)a->_float | (int)b->_float;
+		break;
+	
+		
+	case OP_GE:
+		c->_float = a->_float >= b->_float;
+		break;
+	case OP_LE:
+		c->_float = a->_float <= b->_float;
+		break;
+	case OP_GT:
+		c->_float = a->_float > b->_float;
+		break;
+	case OP_LT:
+		c->_float = a->_float < b->_float;
+		break;
+	case OP_AND:
+		c->_float = a->_float && b->_float;
+		break;
+	case OP_OR:
+		c->_float = a->_float || b->_float;
+		break;
+		
+	case OP_NOT_F:
+		c->_float = !a->_float;
+		break;
+	case OP_NOT_V:
+		c->_float = !a->vector[0] && !a->vector[1] && !a->vector[2];
+		break;
+	case OP_NOT_S:
+		c->_float = !a->string || !*PR_GetString(a->string);
+		break;
+	case OP_NOT_FNC:
+		c->_float = !a->function;
+		break;
+	case OP_NOT_ENT:
+		c->_float = (PROG_TO_EDICT(a->edict) == sv.edicts);
+		break;
+
+	case OP_EQ_F:
+		c->_float = a->_float == b->_float;
+		break;
+	case OP_EQ_V:
+		c->_float = (a->vector[0] == b->vector[0]) &&
+					(a->vector[1] == b->vector[1]) &&
+					(a->vector[2] == b->vector[2]);
+		break;
+	case OP_EQ_S:
+		c->_float = !strcmp(PR_GetString(a->string), PR_GetString(b->string));
+		break;
+	case OP_EQ_E:
+		c->_float = a->_int == b->_int;
+		break;
+	case OP_EQ_FNC:
+		c->_float = a->function == b->function;
+		break;
+
+
+	case OP_NE_F:
+		c->_float = a->_float != b->_float;
+		break;
+	case OP_NE_V:
+		c->_float = (a->vector[0] != b->vector[0]) ||
+					(a->vector[1] != b->vector[1]) ||
+					(a->vector[2] != b->vector[2]);
+		break;
+	case OP_NE_S:
+		c->_float = strcmp(PR_GetString(a->string), PR_GetString(b->string));
+		break;
+	case OP_NE_E:
+		c->_float = a->_int != b->_int;
+		break;
+	case OP_NE_FNC:
+		c->_float = a->function != b->function;
+		break;
+
+//==================
+	case OP_STORE_F:
+	case OP_STORE_ENT:
+	case OP_STORE_FLD:		// integers
+	case OP_STORE_S:
+	case OP_STORE_FNC:		// pointers
+		b->_int = a->_int;
+		break;
+	case OP_STORE_V:
+		b->vector[0] = a->vector[0];
+		b->vector[1] = a->vector[1];
+		b->vector[2] = a->vector[2];
+		break;
+		
+	case OP_STOREP_F:
+	case OP_STOREP_ENT:
+	case OP_STOREP_FLD:		// integers
+	case OP_STOREP_S:
+	case OP_STOREP_FNC:		// pointers
+		ptr = (eval_t *)((byte *)sv.edicts + b->_int);
+		ptr->_int = a->_int;
+		break;
+	case OP_STOREP_V:
+		ptr = (eval_t *)((byte *)sv.edicts + b->_int);
+		ptr->vector[0] = a->vector[0];
+		ptr->vector[1] = a->vector[1];
+		ptr->vector[2] = a->vector[2];
+		break;
+		
+	case OP_ADDRESS:
+		ed = PROG_TO_EDICT(a->edict);
+#ifdef PARANOID
+		NUM_FOR_EDICT(ed);		// make sure it's in range
+#endif
+		if (ed == (edict_t *)sv.edicts && sv.state == ss_active)
+			PR_RunError ("assignment to world entity");
+		c->_int = (byte *)((int *)&ed->v + b->_int) - (byte *)sv.edicts;
+		break;
+		
+	case OP_LOAD_F:
+	case OP_LOAD_FLD:
+	case OP_LOAD_ENT:
+	case OP_LOAD_S:
+	case OP_LOAD_FNC:
+		ed = PROG_TO_EDICT(a->edict);
+#ifdef PARANOID
+		NUM_FOR_EDICT(ed);		// make sure it's in range
+#endif
+		a = (eval_t *)((int *)&ed->v + b->_int);
+		c->_int = a->_int;
+		break;
+
+	case OP_LOAD_V:
+		ed = PROG_TO_EDICT(a->edict);
+#ifdef PARANOID
+		NUM_FOR_EDICT(ed);		// make sure it's in range
+#endif
+		a = (eval_t *)((int *)&ed->v + b->_int);
+		c->vector[0] = a->vector[0];
+		c->vector[1] = a->vector[1];
+		c->vector[2] = a->vector[2];
+		break;
+		
+//==================
+
+	case OP_IFNOT:
+		if (!a->_int)
+			s += st->b - 1;	// offset the s++
+		break;
+		
+	case OP_IF:
+		if (a->_int)
+			s += st->b - 1;	// offset the s++
+		break;
+		
+	case OP_GOTO:
+		s += st->a - 1;	// offset the s++
+		break;
+		
+	case OP_CALL0:
+	case OP_CALL1:
+	case OP_CALL2:
+	case OP_CALL3:
+	case OP_CALL4:
+	case OP_CALL5:
+	case OP_CALL6:
+	case OP_CALL7:
+	case OP_CALL8:
+		pr_argc = st->op - OP_CALL0;
+		if (!a->function)
+			PR_RunError ("NULL function");
+
+		newf = &pr_functions[a->function];
+
+		if (newf->first_statement < 0)
+		{	// negative statements are built in functions
+			i = -newf->first_statement;
+			if (i >= pr_numbuiltins)
+				PR_RunError ("Bad builtin call number");
+			pr_builtins[i] ();
+			break;
+		}
+
+		s = PR_EnterFunction (newf);
+		break;
+
+	case OP_DONE:
+	case OP_RETURN:
+		pr_globals[OFS_RETURN] = pr_globals[st->a];
+		pr_globals[OFS_RETURN+1] = pr_globals[st->a+1];
+		pr_globals[OFS_RETURN+2] = pr_globals[st->a+2];
+	
+		s = PR_LeaveFunction ();
+		if (pr_depth == exitdepth)
+			return;		// all done
+		break;
+		
+	case OP_STATE:
+		ed = PROG_TO_EDICT(pr_global_struct->self);
+		ed->v.nextthink = pr_global_struct->time + 0.1;
+		if (a->_float != ed->v.frame)
+		{
+			ed->v.frame = a->_float;
+		}
+		ed->v.think = b->function;
+		break;
+		
+	default:
+		PR_RunError ("Bad opcode %i", st->op);
+	}
+}
+
+}
+
+/*----------------------*/
+
+char *pr_strtbl[MAX_PRSTR];
+int num_prstr;
+
+char *PR_GetString(int num)
+{
+	if (num < 0) {
+//Con_DPrintf("GET:%d == %s\n", num, pr_strtbl[-num]);
+		return pr_strtbl[-num];
+	}
+	return pr_strings + num;
+}
+
+int PR_SetString(char *s)
+{
+	int i;
+
+	if (s - pr_strings < 0) {
+		for (i = 0; i <= num_prstr; i++)
+			if (pr_strtbl[i] == s)
+				break;
+		if (i < num_prstr)
+			return -i;
+		if (num_prstr == MAX_PRSTR - 1)
+			Sys_Error("MAX_PRSTR");
+		num_prstr++;
+		pr_strtbl[num_prstr] = s;
+//Con_DPrintf("SET:%d == %s\n", -num_prstr, s);
+		return -num_prstr;
+	}
+	return (int)(s - pr_strings);
+}
+
--- /dev/null
+++ b/QW/server/profile.txt
@@ -1,0 +1,41 @@
+  25840.596  39.6    65204.788 100.0        1 _main (sys_win.obj)
+    6449.591   9.9     6850.383  10.5        5 _COM_LoadFile (common.obj)
+    3813.669   5.8     3813.669   5.8    41293 _AddEntsToPmove (sv_user.obj)
+    3538.778   5.4     3671.834   5.6        2 _SV_CalcPHS (sv_init.obj)
+    2832.023   4.3     3860.142   5.9   108369 _PR_ExecuteProgram (pr_exec.obj)
+    2024.012   3.1     2535.985   3.9  3101158 _PM_RecursiveHullCheck (pmovetst.obj)
+    1703.335   2.6     1713.442   2.6  2906788 _SV_RecursiveHullCheck (world.obj)
+    1679.222   2.6     1694.639   2.6    42208 _NET_GetPacket (net_wins.obj)
+    1311.947   2.0     2442.941   3.7     9423 _SV_WriteEntitiesToClient (sv_send.obj)
+     995.298   1.5     1001.797   1.5     9751 _NET_SendPacket (net_wins.obj)
+     957.416   1.5      957.416   1.5   122264 _AngleVectors (mathlib.obj)
+     800.625   1.2      885.897   1.4  1446092 _SV_FindTouchedLeafs (world.obj)
+     776.868   1.2      776.868   1.2     4583 _Sys_ConsoleInput (sys_win.obj)
+     678.630   1.0     4809.817   7.4  1011039 _SV_RunEntity (sv_phys.obj)
+     619.906   1.0      619.906   1.0    95170 _PM_PointContents (pmovetst.obj)
+     512.033   0.8     3063.593   4.7   123219 _PM_PlayerMove (pmovetst.obj)
+     511.973   0.8      511.973   0.8   183507 _PM_HullPointContents (pmovetst.obj)
+     478.937   0.7      498.020   0.8   776129 _SV_ClipToLinks (world.obj)
+     427.858   0.7      427.858   0.7    15333 _Mod_DecompressVis (model.obj)
+     403.567   0.6      745.403   1.1    11587 _SV_AddToFatPVS (sv_send.obj)
+     375.905   0.6      498.825   0.8   256663 _SV_TouchLinks (world.obj)
+     324.689   0.5      361.897   0.6        4 _COM_LoadPackFile (common.obj)
+     315.352   0.5      532.091   0.8   445925 _SV_Physics_Toss (sv_phys.obj)
+     312.962   0.5    13855.472  21.2    45555 _SV_RunCmd (sv_user.obj)
+     286.925   0.4     3259.854   5.0     1014 _SV_Push (sv_phys.obj)
+     274.811   0.4      391.274   0.6   901924 _SV_RunThink (sv_phys.obj)
+     269.635   0.4      269.635   0.4       19 _Sys_FileTime (sys_win.obj)
+     249.745   0.4     2904.674   4.5   153853 _SV_Move (world.obj)
+     233.801   0.4      233.801   0.4    13724 _Sys_DoubleTime (sys_win.obj)
+     228.801   0.4     5602.910   8.6     4579 _SV_Physics (sv_phys.obj)
+     203.463   0.3      203.463   0.3     8931 _SV_ModelIndex (sv_init.obj)
+     193.181   0.3      193.181   0.3   315189 _PR_EnterFunction (pr_exec.obj)
+     183.088   0.3     1623.544   2.5    60223 _SV_LinkEdict (world.obj)
+     172.218   0.3      172.609   0.3   156480 _SV_HullForEntity (world.obj)
+     171.956   0.3      171.956   0.3      242 _Sys_Printf (sys_win.obj)
+     169.198   0.3      176.432   0.3        1 _Memory_Init (zone.obj)
+     166.687   0.3     2052.738   3.1   156480 _SV_ClipMoveToEntity (world.obj)
+     164.941   0.3      164.941   0.3    17116 _CalcSurfaceExtents (model.obj)
+     161.209   0.2      161.209   0.2   118953 _VectorNormalize (mathlib.obj)
+     142.722   0.2      142.722   0.2        7 _COM_filelength (common.obj)
+ 
\ No newline at end of file
--- /dev/null
+++ b/QW/server/progdefs.h
@@ -1,0 +1,159 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+
+/* file generated by qcc, do not modify */
+
+typedef struct
+{	int	pad[28];
+	int	self;
+	int	other;
+	int	world;
+	float	time;
+	float	frametime;
+	int	newmis;
+	float	force_retouch;
+	string_t	mapname;
+	float	serverflags;
+	float	total_secrets;
+	float	total_monsters;
+	float	found_secrets;
+	float	killed_monsters;
+	float	parm1;
+	float	parm2;
+	float	parm3;
+	float	parm4;
+	float	parm5;
+	float	parm6;
+	float	parm7;
+	float	parm8;
+	float	parm9;
+	float	parm10;
+	float	parm11;
+	float	parm12;
+	float	parm13;
+	float	parm14;
+	float	parm15;
+	float	parm16;
+	vec3_t	v_forward;
+	vec3_t	v_up;
+	vec3_t	v_right;
+	float	trace_allsolid;
+	float	trace_startsolid;
+	float	trace_fraction;
+	vec3_t	trace_endpos;
+	vec3_t	trace_plane_normal;
+	float	trace_plane_dist;
+	int	trace_ent;
+	float	trace_inopen;
+	float	trace_inwater;
+	int	msg_entity;
+	func_t	main;
+	func_t	StartFrame;
+	func_t	PlayerPreThink;
+	func_t	PlayerPostThink;
+	func_t	ClientKill;
+	func_t	ClientConnect;
+	func_t	PutClientInServer;
+	func_t	ClientDisconnect;
+	func_t	SetNewParms;
+	func_t	SetChangeParms;
+} globalvars_t;
+
+typedef struct
+{
+	float	modelindex;
+	vec3_t	absmin;
+	vec3_t	absmax;
+	float	ltime;
+	float	lastruntime;
+	float	movetype;
+	float	solid;
+	vec3_t	origin;
+	vec3_t	oldorigin;
+	vec3_t	velocity;
+	vec3_t	angles;
+	vec3_t	avelocity;
+	string_t	classname;
+	string_t	model;
+	float	frame;
+	float	skin;
+	float	effects;
+	vec3_t	mins;
+	vec3_t	maxs;
+	vec3_t	size;
+	func_t	touch;
+	func_t	use;
+	func_t	think;
+	func_t	blocked;
+	float	nextthink;
+	int	groundentity;
+	float	health;
+	float	frags;
+	float	weapon;
+	string_t	weaponmodel;
+	float	weaponframe;
+	float	currentammo;
+	float	ammo_shells;
+	float	ammo_nails;
+	float	ammo_rockets;
+	float	ammo_cells;
+	float	items;
+	float	takedamage;
+	int	chain;
+	float	deadflag;
+	vec3_t	view_ofs;
+	float	button0;
+	float	button1;
+	float	button2;
+	float	impulse;
+	float	fixangle;
+	vec3_t	v_angle;
+	string_t	netname;
+	int	enemy;
+	float	flags;
+	float	colormap;
+	float	team;
+	float	max_health;
+	float	teleport_time;
+	float	armortype;
+	float	armorvalue;
+	float	waterlevel;
+	float	watertype;
+	float	ideal_yaw;
+	float	yaw_speed;
+	int	aiment;
+	int	goalentity;
+	float	spawnflags;
+	string_t	target;
+	string_t	targetname;
+	float	dmg_take;
+	float	dmg_save;
+	int	dmg_inflictor;
+	int	owner;
+	vec3_t	movedir;
+	string_t	message;
+	float	sounds;
+	string_t	noise;
+	string_t	noise1;
+	string_t	noise2;
+	string_t	noise3;
+} entvars_t;
+
+#define PROGHEADER_CRC 54730
--- /dev/null
+++ b/QW/server/progs.h
@@ -1,0 +1,147 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+
+#include "pr_comp.h"			// defs shared with qcc
+#include "progdefs.h"			// generated by program cdefs
+
+typedef union eval_s
+{
+	string_t		string;
+	float			_float;
+	float			vector[3];
+	func_t			function;
+	int				_int;
+	int				edict;
+} eval_t;	
+
+#define	MAX_ENT_LEAFS	16
+typedef struct edict_s
+{
+	qboolean	free;
+	link_t		area;				// linked to a division node or leaf
+	
+	int			num_leafs;
+	short		leafnums[MAX_ENT_LEAFS];
+
+	entity_state_t	baseline;
+	
+	float		freetime;			// sv.time when the object was freed
+	entvars_t	v;					// C exported fields from progs
+// other fields from progs come immediately after
+} edict_t;
+#define	EDICT_FROM_AREA(l) STRUCT_FROM_LINK(l,edict_t,area)
+
+//============================================================================
+
+extern	dprograms_t		*progs;
+extern	dfunction_t		*pr_functions;
+extern	char			*pr_strings;
+extern	ddef_t			*pr_globaldefs;
+extern	ddef_t			*pr_fielddefs;
+extern	dstatement_t	*pr_statements;
+extern	globalvars_t	*pr_global_struct;
+extern	float			*pr_globals;			// same as pr_global_struct
+
+extern	int				pr_edict_size;	// in bytes
+
+//============================================================================
+
+void PR_Init (void);
+
+void PR_ExecuteProgram (func_t fnum);
+void PR_LoadProgs (void);
+
+void PR_Profile_f (void);
+
+edict_t *ED_Alloc (void);
+void ED_Free (edict_t *ed);
+
+char	*ED_NewString (char *string);
+// returns a copy of the string allocated from the server's string heap
+
+void ED_Print (edict_t *ed);
+void ED_Write (FILE *f, edict_t *ed);
+char *ED_ParseEdict (char *data, edict_t *ent);
+
+void ED_WriteGlobals (FILE *f);
+void ED_ParseGlobals (char *data);
+
+void ED_LoadFromFile (char *data);
+
+//define EDICT_NUM(n) ((edict_t *)(sv.edicts+ (n)*pr_edict_size))
+//define NUM_FOR_EDICT(e) (((byte *)(e) - sv.edicts)/pr_edict_size)
+
+edict_t *EDICT_NUM(int n);
+int NUM_FOR_EDICT(edict_t *e);
+
+#define	NEXT_EDICT(e) ((edict_t *)( (byte *)e + pr_edict_size))
+
+#define	EDICT_TO_PROG(e) ((byte *)e - (byte *)sv.edicts)
+#define PROG_TO_EDICT(e) ((edict_t *)((byte *)sv.edicts + e))
+
+//============================================================================
+
+#define	G_FLOAT(o) (pr_globals[o])
+#define	G_INT(o) (*(int *)&pr_globals[o])
+#define	G_EDICT(o) ((edict_t *)((byte *)sv.edicts+ *(int *)&pr_globals[o]))
+#define G_EDICTNUM(o) NUM_FOR_EDICT(G_EDICT(o))
+#define	G_VECTOR(o) (&pr_globals[o])
+#define	G_STRING(o) (PR_GetString(*(string_t *)&pr_globals[o]))
+#define	G_FUNCTION(o) (*(func_t *)&pr_globals[o])
+
+#define	E_FLOAT(e,o) (((float*)&e->v)[o])
+#define	E_INT(e,o) (*(int *)&((float*)&e->v)[o])
+#define	E_VECTOR(e,o) (&((float*)&e->v)[o])
+#define	E_STRING(e,o) (PR_GetString(*(string_t *)&((float*)&e->v)[o]))
+
+extern	int		type_size[8];
+
+typedef void (*builtin_t) (void);
+extern	builtin_t *pr_builtins;
+extern int pr_numbuiltins;
+
+extern int		pr_argc;
+
+extern	qboolean	pr_trace;
+extern	dfunction_t	*pr_xfunction;
+extern	int			pr_xstatement;
+
+extern func_t SpectatorConnect;
+extern func_t SpectatorThink;
+extern func_t SpectatorDisconnect;
+
+void PR_RunError (char *error, ...);
+
+void ED_PrintEdicts (void);
+void ED_PrintNum (int ent);
+
+eval_t *GetEdictFieldValue(edict_t *ed, char *field);
+
+//
+// PR STrings stuff
+//
+#define MAX_PRSTR 1024
+
+extern char *pr_strtbl[MAX_PRSTR];
+extern int num_prstr;
+
+char *PR_GetString(int num);
+int PR_SetString(char *s);
+
--- /dev/null
+++ b/QW/server/quakeasm.h
@@ -1,0 +1,32 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+//
+// quakeasm.h: general asm header file
+//
+
+#if __i386__
+#define id386	1
+#else
+#define id386	0
+#endif
+
+// !!! must be kept the same as in d_iface.h !!!
+#define TRANSPARENT_COLOR	255
+
--- /dev/null
+++ b/QW/server/qwsv.dsp
@@ -1,0 +1,364 @@
+# Microsoft Developer Studio Project File - Name="qwsv" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=qwsv - Win32 Release
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "qwsv.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "qwsv.mak" CFG="qwsv - Win32 Release"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "qwsv - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "qwsv - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE 
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "qwsv - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir ".\Release"
+# PROP BASE Intermediate_Dir ".\Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir ".\Release"
+# PROP Intermediate_Dir ".\Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /c
+# ADD CPP /nologo /GX /O2 /I "." /I "..\client" /D "NDEBUG" /D "SERVERONLY" /D "WIN32" /D "_CONSOLE" /FR /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib winmm.lib /nologo /subsystem:console /machine:I386
+# SUBTRACT LINK32 /profile
+
+!ELSEIF  "$(CFG)" == "qwsv - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir ".\Debug"
+# PROP BASE Intermediate_Dir ".\Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir ".\Debug"
+# PROP Intermediate_Dir ".\Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /YX /c
+# ADD CPP /nologo /GX /ZI /Od /I "." /I "..\client" /D "_DEBUG" /D "SERVERONLY" /D "WIN32" /D "_CONSOLE" /FR /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386
+# ADD LINK32 wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib winmm.lib /nologo /subsystem:console /map /debug /machine:I386
+# SUBTRACT LINK32 /profile
+
+!ENDIF 
+
+# Begin Target
+
+# Name "qwsv - Win32 Release"
+# Name "qwsv - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;hpj;bat;for;f90"
+# Begin Source File
+
+SOURCE=..\client\cmd.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\client\common.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\client\crc.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\client\cvar.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\client\mathlib.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\client\md4.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\model.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\quake\v2\client\net.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\client\net_chan.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\client\net_wins.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\client\pmove.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\client\pmovetst.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\pr_cmds.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\pr_edict.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\pr_exec.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\sv_ccmds.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\sv_ents.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\sv_init.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\sv_main.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\sv_move.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\sv_nchan.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\sv_phys.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\sv_send.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\sv_user.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\sys_win.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\world.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\client\zone.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd"
+# Begin Source File
+
+SOURCE=..\client\bothdefs.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\client\bspfile.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\client\cdaudio.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\client\client.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\client\cmd.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\client\common.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\client\console.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\client\crc.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\client\cvar.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\client\d_iface.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\client\draw.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\client\input.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\client\keys.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\client\mathlib.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\client\menu.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\client\model.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\client\modelgen.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\client\net.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\client\pmove.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\pr_comp.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\progdefs.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\progs.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\client\protocol.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\client\quakedef.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\qwsvdef.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\client\render.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\client\sbar.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\client\screen.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\server.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\client\sound.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\client\spritegn.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\client\sys.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\sys.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\client\vid.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\client\view.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\client\wad.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\client\winquake.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\world.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\client\zone.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
--- /dev/null
+++ b/QW/server/qwsv.dsw
@@ -1,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 5.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "qwsv"=.\qwsv.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
--- /dev/null
+++ b/QW/server/qwsv.mak
@@ -1,0 +1,2207 @@
+# Microsoft Developer Studio Generated NMAKE File, Format Version 4.20
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+!IF "$(CFG)" == ""
+CFG=qwsv - Win32 Debug
+!MESSAGE No configuration specified.  Defaulting to qwsv - Win32 Debug.
+!ENDIF 
+
+!IF "$(CFG)" != "qwsv - Win32 Release" && "$(CFG)" != "qwsv - Win32 Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE on this makefile
+!MESSAGE by defining the macro CFG on the command line.  For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "qwsv.mak" CFG="qwsv - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "qwsv - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "qwsv - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE 
+!ERROR An invalid configuration is specified.
+!ENDIF 
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE 
+NULL=nul
+!ENDIF 
+################################################################################
+# Begin Project
+# PROP Target_Last_Scanned "qwsv - Win32 Debug"
+RSC=rc.exe
+CPP=cl.exe
+
+!IF  "$(CFG)" == "qwsv - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Target_Dir ""
+OUTDIR=.\Release
+INTDIR=.\Release
+
+ALL : "$(OUTDIR)\qwsv.exe"
+
+CLEAN : 
+	-@erase "$(INTDIR)\cmd.obj"
+	-@erase "$(INTDIR)\common.obj"
+	-@erase "$(INTDIR)\crc.obj"
+	-@erase "$(INTDIR)\cvar.obj"
+	-@erase "$(INTDIR)\mathlib.obj"
+	-@erase "$(INTDIR)\model.obj"
+	-@erase "$(INTDIR)\net_chan.obj"
+	-@erase "$(INTDIR)\net_wins.obj"
+	-@erase "$(INTDIR)\pmove.obj"
+	-@erase "$(INTDIR)\pmovetst.obj"
+	-@erase "$(INTDIR)\pr_cmds.obj"
+	-@erase "$(INTDIR)\pr_edict.obj"
+	-@erase "$(INTDIR)\pr_exec.obj"
+	-@erase "$(INTDIR)\sv_ccmds.obj"
+	-@erase "$(INTDIR)\sv_ents.obj"
+	-@erase "$(INTDIR)\sv_init.obj"
+	-@erase "$(INTDIR)\sv_main.obj"
+	-@erase "$(INTDIR)\sv_move.obj"
+	-@erase "$(INTDIR)\sv_phys.obj"
+	-@erase "$(INTDIR)\sv_send.obj"
+	-@erase "$(INTDIR)\sv_user.obj"
+	-@erase "$(INTDIR)\sys_win.obj"
+	-@erase "$(INTDIR)\world.obj"
+	-@erase "$(INTDIR)\zone.obj"
+	-@erase "$(OUTDIR)\qwsv.exe"
+
+"$(OUTDIR)" :
+    if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /c
+# ADD CPP /nologo /GX /O2 /I "." /I "../client" /D "NDEBUG" /D "SERVERONLY" /D "WIN32" /D "_CONSOLE" /YX /c
+# SUBTRACT CPP /Fr
+CPP_PROJ=/nologo /ML /GX /O2 /I "." /I "../client" /D "NDEBUG" /D "SERVERONLY"\
+ /D "WIN32" /D "_CONSOLE" /Fp"$(INTDIR)/qwsv.pch" /YX /Fo"$(INTDIR)/" /c 
+CPP_OBJS=.\Release/
+CPP_SBRS=.\.
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+BSC32_FLAGS=/nologo /o"$(OUTDIR)/qwsv.bsc" 
+BSC32_SBRS= \
+	
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /profile /machine:I386
+LINK32_FLAGS=wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib\
+ comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib\
+ odbc32.lib odbccp32.lib /nologo /subsystem:console /profile /machine:I386\
+ /out:"$(OUTDIR)/qwsv.exe" 
+LINK32_OBJS= \
+	"$(INTDIR)\cmd.obj" \
+	"$(INTDIR)\common.obj" \
+	"$(INTDIR)\crc.obj" \
+	"$(INTDIR)\cvar.obj" \
+	"$(INTDIR)\mathlib.obj" \
+	"$(INTDIR)\model.obj" \
+	"$(INTDIR)\net_chan.obj" \
+	"$(INTDIR)\net_wins.obj" \
+	"$(INTDIR)\pmove.obj" \
+	"$(INTDIR)\pmovetst.obj" \
+	"$(INTDIR)\pr_cmds.obj" \
+	"$(INTDIR)\pr_edict.obj" \
+	"$(INTDIR)\pr_exec.obj" \
+	"$(INTDIR)\sv_ccmds.obj" \
+	"$(INTDIR)\sv_ents.obj" \
+	"$(INTDIR)\sv_init.obj" \
+	"$(INTDIR)\sv_main.obj" \
+	"$(INTDIR)\sv_move.obj" \
+	"$(INTDIR)\sv_phys.obj" \
+	"$(INTDIR)\sv_send.obj" \
+	"$(INTDIR)\sv_user.obj" \
+	"$(INTDIR)\sys_win.obj" \
+	"$(INTDIR)\world.obj" \
+	"$(INTDIR)\zone.obj"
+
+"$(OUTDIR)\qwsv.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+    $(LINK32) @<<
+  $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ELSEIF  "$(CFG)" == "qwsv - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Target_Dir ""
+OUTDIR=.\Debug
+INTDIR=.\Debug
+
+ALL : "$(OUTDIR)\qwsv.exe" "$(OUTDIR)\qwsv.bsc"
+
+CLEAN : 
+	-@erase "$(INTDIR)\cmd.obj"
+	-@erase "$(INTDIR)\cmd.sbr"
+	-@erase "$(INTDIR)\common.obj"
+	-@erase "$(INTDIR)\common.sbr"
+	-@erase "$(INTDIR)\crc.obj"
+	-@erase "$(INTDIR)\crc.sbr"
+	-@erase "$(INTDIR)\cvar.obj"
+	-@erase "$(INTDIR)\cvar.sbr"
+	-@erase "$(INTDIR)\mathlib.obj"
+	-@erase "$(INTDIR)\mathlib.sbr"
+	-@erase "$(INTDIR)\model.obj"
+	-@erase "$(INTDIR)\model.sbr"
+	-@erase "$(INTDIR)\net_chan.obj"
+	-@erase "$(INTDIR)\net_chan.sbr"
+	-@erase "$(INTDIR)\net_wins.obj"
+	-@erase "$(INTDIR)\net_wins.sbr"
+	-@erase "$(INTDIR)\pmove.obj"
+	-@erase "$(INTDIR)\pmove.sbr"
+	-@erase "$(INTDIR)\pmovetst.obj"
+	-@erase "$(INTDIR)\pmovetst.sbr"
+	-@erase "$(INTDIR)\pr_cmds.obj"
+	-@erase "$(INTDIR)\pr_cmds.sbr"
+	-@erase "$(INTDIR)\pr_edict.obj"
+	-@erase "$(INTDIR)\pr_edict.sbr"
+	-@erase "$(INTDIR)\pr_exec.obj"
+	-@erase "$(INTDIR)\pr_exec.sbr"
+	-@erase "$(INTDIR)\sv_ccmds.obj"
+	-@erase "$(INTDIR)\sv_ccmds.sbr"
+	-@erase "$(INTDIR)\sv_ents.obj"
+	-@erase "$(INTDIR)\sv_ents.sbr"
+	-@erase "$(INTDIR)\sv_init.obj"
+	-@erase "$(INTDIR)\sv_init.sbr"
+	-@erase "$(INTDIR)\sv_main.obj"
+	-@erase "$(INTDIR)\sv_main.sbr"
+	-@erase "$(INTDIR)\sv_move.obj"
+	-@erase "$(INTDIR)\sv_move.sbr"
+	-@erase "$(INTDIR)\sv_phys.obj"
+	-@erase "$(INTDIR)\sv_phys.sbr"
+	-@erase "$(INTDIR)\sv_send.obj"
+	-@erase "$(INTDIR)\sv_send.sbr"
+	-@erase "$(INTDIR)\sv_user.obj"
+	-@erase "$(INTDIR)\sv_user.sbr"
+	-@erase "$(INTDIR)\sys_win.obj"
+	-@erase "$(INTDIR)\sys_win.sbr"
+	-@erase "$(INTDIR)\vc40.idb"
+	-@erase "$(INTDIR)\vc40.pdb"
+	-@erase "$(INTDIR)\world.obj"
+	-@erase "$(INTDIR)\world.sbr"
+	-@erase "$(INTDIR)\zone.obj"
+	-@erase "$(INTDIR)\zone.sbr"
+	-@erase "$(OUTDIR)\qwsv.bsc"
+	-@erase "$(OUTDIR)\qwsv.exe"
+	-@erase "$(OUTDIR)\qwsv.map"
+
+"$(OUTDIR)" :
+    if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /YX /c
+# ADD CPP /nologo /Gm /GX /Zi /Od /I "." /I "../client" /D "_DEBUG" /D "SERVERONLY" /D "WIN32" /D "_CONSOLE" /FR /YX /c
+CPP_PROJ=/nologo /MLd /Gm /GX /Zi /Od /I "." /I "../client" /D "_DEBUG" /D\
+ "SERVERONLY" /D "WIN32" /D "_CONSOLE" /FR"$(INTDIR)/" /Fp"$(INTDIR)/qwsv.pch"\
+ /YX /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c 
+CPP_OBJS=.\Debug/
+CPP_SBRS=.\Debug/
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+BSC32_FLAGS=/nologo /o"$(OUTDIR)/qwsv.bsc" 
+BSC32_SBRS= \
+	"$(INTDIR)\cmd.sbr" \
+	"$(INTDIR)\common.sbr" \
+	"$(INTDIR)\crc.sbr" \
+	"$(INTDIR)\cvar.sbr" \
+	"$(INTDIR)\mathlib.sbr" \
+	"$(INTDIR)\model.sbr" \
+	"$(INTDIR)\net_chan.sbr" \
+	"$(INTDIR)\net_wins.sbr" \
+	"$(INTDIR)\pmove.sbr" \
+	"$(INTDIR)\pmovetst.sbr" \
+	"$(INTDIR)\pr_cmds.sbr" \
+	"$(INTDIR)\pr_edict.sbr" \
+	"$(INTDIR)\pr_exec.sbr" \
+	"$(INTDIR)\sv_ccmds.sbr" \
+	"$(INTDIR)\sv_ents.sbr" \
+	"$(INTDIR)\sv_init.sbr" \
+	"$(INTDIR)\sv_main.sbr" \
+	"$(INTDIR)\sv_move.sbr" \
+	"$(INTDIR)\sv_phys.sbr" \
+	"$(INTDIR)\sv_send.sbr" \
+	"$(INTDIR)\sv_user.sbr" \
+	"$(INTDIR)\sys_win.sbr" \
+	"$(INTDIR)\world.sbr" \
+	"$(INTDIR)\zone.sbr"
+
+"$(OUTDIR)\qwsv.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
+    $(BSC32) @<<
+  $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386
+# ADD LINK32 wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /profile /map /debug /machine:I386
+LINK32_FLAGS=wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib\
+ comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib\
+ odbc32.lib odbccp32.lib /nologo /subsystem:console /profile\
+ /map:"$(INTDIR)/qwsv.map" /debug /machine:I386 /out:"$(OUTDIR)/qwsv.exe" 
+LINK32_OBJS= \
+	"$(INTDIR)\cmd.obj" \
+	"$(INTDIR)\common.obj" \
+	"$(INTDIR)\crc.obj" \
+	"$(INTDIR)\cvar.obj" \
+	"$(INTDIR)\mathlib.obj" \
+	"$(INTDIR)\model.obj" \
+	"$(INTDIR)\net_chan.obj" \
+	"$(INTDIR)\net_wins.obj" \
+	"$(INTDIR)\pmove.obj" \
+	"$(INTDIR)\pmovetst.obj" \
+	"$(INTDIR)\pr_cmds.obj" \
+	"$(INTDIR)\pr_edict.obj" \
+	"$(INTDIR)\pr_exec.obj" \
+	"$(INTDIR)\sv_ccmds.obj" \
+	"$(INTDIR)\sv_ents.obj" \
+	"$(INTDIR)\sv_init.obj" \
+	"$(INTDIR)\sv_main.obj" \
+	"$(INTDIR)\sv_move.obj" \
+	"$(INTDIR)\sv_phys.obj" \
+	"$(INTDIR)\sv_send.obj" \
+	"$(INTDIR)\sv_user.obj" \
+	"$(INTDIR)\sys_win.obj" \
+	"$(INTDIR)\world.obj" \
+	"$(INTDIR)\zone.obj"
+
+"$(OUTDIR)\qwsv.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+    $(LINK32) @<<
+  $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ENDIF 
+
+.c{$(CPP_OBJS)}.obj:
+   $(CPP) $(CPP_PROJ) $<  
+
+.cpp{$(CPP_OBJS)}.obj:
+   $(CPP) $(CPP_PROJ) $<  
+
+.cxx{$(CPP_OBJS)}.obj:
+   $(CPP) $(CPP_PROJ) $<  
+
+.c{$(CPP_SBRS)}.sbr:
+   $(CPP) $(CPP_PROJ) $<  
+
+.cpp{$(CPP_SBRS)}.sbr:
+   $(CPP) $(CPP_PROJ) $<  
+
+.cxx{$(CPP_SBRS)}.sbr:
+   $(CPP) $(CPP_PROJ) $<  
+
+################################################################################
+# Begin Target
+
+# Name "qwsv - Win32 Release"
+# Name "qwsv - Win32 Debug"
+
+!IF  "$(CFG)" == "qwsv - Win32 Release"
+
+!ELSEIF  "$(CFG)" == "qwsv - Win32 Debug"
+
+!ENDIF 
+
+################################################################################
+# Begin Source File
+
+SOURCE=.\model.c
+
+!IF  "$(CFG)" == "qwsv - Win32 Release"
+
+DEP_CPP_MODEL=\
+	"..\client\spritegn.h"\
+	".\../client\bothdefs.h"\
+	".\../client\bspfile.h"\
+	".\../client\cmd.h"\
+	".\../client\common.h"\
+	".\../client\crc.h"\
+	".\../client\cvar.h"\
+	".\../client\mathlib.h"\
+	".\../client\model.h"\
+	".\../client\net.h"\
+	".\../client\pmove.h"\
+	".\../client\protocol.h"\
+	".\../client\zone.h"\
+	".\..\client\modelgen.h"\
+	".\pr_comp.h"\
+	".\progdefs.h"\
+	".\progs.h"\
+	".\qwsvdef.h"\
+	".\server.h"\
+	".\sys.h"\
+	".\world.h"\
+	
+NODEP_CPP_MODEL=\
+	"..\client\cmdlib.h"\
+	"..\client\dictlib.h"\
+	"..\client\lbmlib.h"\
+	"..\client\scriplib.h"\
+	"..\client\trilib.h"\
+	
+
+"$(INTDIR)\model.obj" : $(SOURCE) $(DEP_CPP_MODEL) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwsv - Win32 Debug"
+
+DEP_CPP_MODEL=\
+	"..\client\spritegn.h"\
+	".\../client\bothdefs.h"\
+	".\../client\bspfile.h"\
+	".\../client\cmd.h"\
+	".\../client\common.h"\
+	".\../client\crc.h"\
+	".\../client\cvar.h"\
+	".\../client\mathlib.h"\
+	".\../client\model.h"\
+	".\../client\net.h"\
+	".\../client\pmove.h"\
+	".\../client\protocol.h"\
+	".\../client\zone.h"\
+	".\..\client\modelgen.h"\
+	".\pr_comp.h"\
+	".\progdefs.h"\
+	".\progs.h"\
+	".\qwsvdef.h"\
+	".\server.h"\
+	".\sys.h"\
+	".\world.h"\
+	
+NODEP_CPP_MODEL=\
+	"..\client\cmdlib.h"\
+	"..\client\dictlib.h"\
+	"..\client\lbmlib.h"\
+	"..\client\scriplib.h"\
+	"..\client\trilib.h"\
+	
+
+"$(INTDIR)\model.obj" : $(SOURCE) $(DEP_CPP_MODEL) "$(INTDIR)"
+
+"$(INTDIR)\model.sbr" : $(SOURCE) $(DEP_CPP_MODEL) "$(INTDIR)"
+
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\pr_cmds.c
+
+!IF  "$(CFG)" == "qwsv - Win32 Release"
+
+DEP_CPP_PR_CM=\
+	"..\client\spritegn.h"\
+	".\../client\bothdefs.h"\
+	".\../client\bspfile.h"\
+	".\../client\cmd.h"\
+	".\../client\common.h"\
+	".\../client\crc.h"\
+	".\../client\cvar.h"\
+	".\../client\mathlib.h"\
+	".\../client\model.h"\
+	".\../client\net.h"\
+	".\../client\pmove.h"\
+	".\../client\protocol.h"\
+	".\../client\zone.h"\
+	".\..\client\modelgen.h"\
+	".\pr_comp.h"\
+	".\progdefs.h"\
+	".\progs.h"\
+	".\qwsvdef.h"\
+	".\server.h"\
+	".\sys.h"\
+	".\world.h"\
+	
+NODEP_CPP_PR_CM=\
+	"..\client\cmdlib.h"\
+	"..\client\dictlib.h"\
+	"..\client\lbmlib.h"\
+	"..\client\scriplib.h"\
+	"..\client\trilib.h"\
+	
+
+"$(INTDIR)\pr_cmds.obj" : $(SOURCE) $(DEP_CPP_PR_CM) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwsv - Win32 Debug"
+
+DEP_CPP_PR_CM=\
+	"..\client\spritegn.h"\
+	".\../client\bothdefs.h"\
+	".\../client\bspfile.h"\
+	".\../client\cmd.h"\
+	".\../client\common.h"\
+	".\../client\crc.h"\
+	".\../client\cvar.h"\
+	".\../client\mathlib.h"\
+	".\../client\model.h"\
+	".\../client\net.h"\
+	".\../client\pmove.h"\
+	".\../client\protocol.h"\
+	".\../client\zone.h"\
+	".\..\client\modelgen.h"\
+	".\pr_comp.h"\
+	".\progdefs.h"\
+	".\progs.h"\
+	".\qwsvdef.h"\
+	".\server.h"\
+	".\sys.h"\
+	".\world.h"\
+	
+NODEP_CPP_PR_CM=\
+	"..\client\cmdlib.h"\
+	"..\client\dictlib.h"\
+	"..\client\lbmlib.h"\
+	"..\client\scriplib.h"\
+	"..\client\trilib.h"\
+	
+
+"$(INTDIR)\pr_cmds.obj" : $(SOURCE) $(DEP_CPP_PR_CM) "$(INTDIR)"
+
+"$(INTDIR)\pr_cmds.sbr" : $(SOURCE) $(DEP_CPP_PR_CM) "$(INTDIR)"
+
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\pr_edict.c
+
+!IF  "$(CFG)" == "qwsv - Win32 Release"
+
+DEP_CPP_PR_ED=\
+	"..\client\spritegn.h"\
+	".\../client\bothdefs.h"\
+	".\../client\bspfile.h"\
+	".\../client\cmd.h"\
+	".\../client\common.h"\
+	".\../client\crc.h"\
+	".\../client\cvar.h"\
+	".\../client\mathlib.h"\
+	".\../client\model.h"\
+	".\../client\net.h"\
+	".\../client\pmove.h"\
+	".\../client\protocol.h"\
+	".\../client\zone.h"\
+	".\..\client\modelgen.h"\
+	".\pr_comp.h"\
+	".\progdefs.h"\
+	".\progs.h"\
+	".\qwsvdef.h"\
+	".\server.h"\
+	".\sys.h"\
+	".\world.h"\
+	
+NODEP_CPP_PR_ED=\
+	"..\client\cmdlib.h"\
+	"..\client\dictlib.h"\
+	"..\client\lbmlib.h"\
+	"..\client\scriplib.h"\
+	"..\client\trilib.h"\
+	
+
+"$(INTDIR)\pr_edict.obj" : $(SOURCE) $(DEP_CPP_PR_ED) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwsv - Win32 Debug"
+
+DEP_CPP_PR_ED=\
+	"..\client\spritegn.h"\
+	".\../client\bothdefs.h"\
+	".\../client\bspfile.h"\
+	".\../client\cmd.h"\
+	".\../client\common.h"\
+	".\../client\crc.h"\
+	".\../client\cvar.h"\
+	".\../client\mathlib.h"\
+	".\../client\model.h"\
+	".\../client\net.h"\
+	".\../client\pmove.h"\
+	".\../client\protocol.h"\
+	".\../client\zone.h"\
+	".\..\client\modelgen.h"\
+	".\pr_comp.h"\
+	".\progdefs.h"\
+	".\progs.h"\
+	".\qwsvdef.h"\
+	".\server.h"\
+	".\sys.h"\
+	".\world.h"\
+	
+NODEP_CPP_PR_ED=\
+	"..\client\cmdlib.h"\
+	"..\client\dictlib.h"\
+	"..\client\lbmlib.h"\
+	"..\client\scriplib.h"\
+	"..\client\trilib.h"\
+	
+
+"$(INTDIR)\pr_edict.obj" : $(SOURCE) $(DEP_CPP_PR_ED) "$(INTDIR)"
+
+"$(INTDIR)\pr_edict.sbr" : $(SOURCE) $(DEP_CPP_PR_ED) "$(INTDIR)"
+
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\pr_exec.c
+
+!IF  "$(CFG)" == "qwsv - Win32 Release"
+
+DEP_CPP_PR_EX=\
+	"..\client\spritegn.h"\
+	".\../client\bothdefs.h"\
+	".\../client\bspfile.h"\
+	".\../client\cmd.h"\
+	".\../client\common.h"\
+	".\../client\crc.h"\
+	".\../client\cvar.h"\
+	".\../client\mathlib.h"\
+	".\../client\model.h"\
+	".\../client\net.h"\
+	".\../client\pmove.h"\
+	".\../client\protocol.h"\
+	".\../client\zone.h"\
+	".\..\client\modelgen.h"\
+	".\pr_comp.h"\
+	".\progdefs.h"\
+	".\progs.h"\
+	".\qwsvdef.h"\
+	".\server.h"\
+	".\sys.h"\
+	".\world.h"\
+	
+NODEP_CPP_PR_EX=\
+	"..\client\cmdlib.h"\
+	"..\client\dictlib.h"\
+	"..\client\lbmlib.h"\
+	"..\client\scriplib.h"\
+	"..\client\trilib.h"\
+	
+
+"$(INTDIR)\pr_exec.obj" : $(SOURCE) $(DEP_CPP_PR_EX) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwsv - Win32 Debug"
+
+DEP_CPP_PR_EX=\
+	"..\client\spritegn.h"\
+	".\../client\bothdefs.h"\
+	".\../client\bspfile.h"\
+	".\../client\cmd.h"\
+	".\../client\common.h"\
+	".\../client\crc.h"\
+	".\../client\cvar.h"\
+	".\../client\mathlib.h"\
+	".\../client\model.h"\
+	".\../client\net.h"\
+	".\../client\pmove.h"\
+	".\../client\protocol.h"\
+	".\../client\zone.h"\
+	".\..\client\modelgen.h"\
+	".\pr_comp.h"\
+	".\progdefs.h"\
+	".\progs.h"\
+	".\qwsvdef.h"\
+	".\server.h"\
+	".\sys.h"\
+	".\world.h"\
+	
+NODEP_CPP_PR_EX=\
+	"..\client\cmdlib.h"\
+	"..\client\dictlib.h"\
+	"..\client\lbmlib.h"\
+	"..\client\scriplib.h"\
+	"..\client\trilib.h"\
+	
+
+"$(INTDIR)\pr_exec.obj" : $(SOURCE) $(DEP_CPP_PR_EX) "$(INTDIR)"
+
+"$(INTDIR)\pr_exec.sbr" : $(SOURCE) $(DEP_CPP_PR_EX) "$(INTDIR)"
+
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\sv_ccmds.c
+
+!IF  "$(CFG)" == "qwsv - Win32 Release"
+
+DEP_CPP_SV_CC=\
+	"..\client\spritegn.h"\
+	".\../client\bothdefs.h"\
+	".\../client\bspfile.h"\
+	".\../client\cmd.h"\
+	".\../client\common.h"\
+	".\../client\crc.h"\
+	".\../client\cvar.h"\
+	".\../client\mathlib.h"\
+	".\../client\model.h"\
+	".\../client\net.h"\
+	".\../client\pmove.h"\
+	".\../client\protocol.h"\
+	".\../client\zone.h"\
+	".\..\client\modelgen.h"\
+	".\pr_comp.h"\
+	".\progdefs.h"\
+	".\progs.h"\
+	".\qwsvdef.h"\
+	".\server.h"\
+	".\sys.h"\
+	".\world.h"\
+	
+NODEP_CPP_SV_CC=\
+	"..\client\cmdlib.h"\
+	"..\client\dictlib.h"\
+	"..\client\lbmlib.h"\
+	"..\client\scriplib.h"\
+	"..\client\trilib.h"\
+	
+
+"$(INTDIR)\sv_ccmds.obj" : $(SOURCE) $(DEP_CPP_SV_CC) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwsv - Win32 Debug"
+
+DEP_CPP_SV_CC=\
+	"..\client\spritegn.h"\
+	".\../client\bothdefs.h"\
+	".\../client\bspfile.h"\
+	".\../client\cmd.h"\
+	".\../client\common.h"\
+	".\../client\crc.h"\
+	".\../client\cvar.h"\
+	".\../client\mathlib.h"\
+	".\../client\model.h"\
+	".\../client\net.h"\
+	".\../client\pmove.h"\
+	".\../client\protocol.h"\
+	".\../client\zone.h"\
+	".\..\client\modelgen.h"\
+	".\pr_comp.h"\
+	".\progdefs.h"\
+	".\progs.h"\
+	".\qwsvdef.h"\
+	".\server.h"\
+	".\sys.h"\
+	".\world.h"\
+	
+NODEP_CPP_SV_CC=\
+	"..\client\cmdlib.h"\
+	"..\client\dictlib.h"\
+	"..\client\lbmlib.h"\
+	"..\client\scriplib.h"\
+	"..\client\trilib.h"\
+	
+
+"$(INTDIR)\sv_ccmds.obj" : $(SOURCE) $(DEP_CPP_SV_CC) "$(INTDIR)"
+
+"$(INTDIR)\sv_ccmds.sbr" : $(SOURCE) $(DEP_CPP_SV_CC) "$(INTDIR)"
+
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\sv_init.c
+
+!IF  "$(CFG)" == "qwsv - Win32 Release"
+
+DEP_CPP_SV_IN=\
+	"..\client\spritegn.h"\
+	".\../client\bothdefs.h"\
+	".\../client\bspfile.h"\
+	".\../client\cmd.h"\
+	".\../client\common.h"\
+	".\../client\crc.h"\
+	".\../client\cvar.h"\
+	".\../client\mathlib.h"\
+	".\../client\model.h"\
+	".\../client\net.h"\
+	".\../client\pmove.h"\
+	".\../client\protocol.h"\
+	".\../client\zone.h"\
+	".\..\client\modelgen.h"\
+	".\pr_comp.h"\
+	".\progdefs.h"\
+	".\progs.h"\
+	".\qwsvdef.h"\
+	".\server.h"\
+	".\sys.h"\
+	".\world.h"\
+	
+NODEP_CPP_SV_IN=\
+	"..\client\cmdlib.h"\
+	"..\client\dictlib.h"\
+	"..\client\lbmlib.h"\
+	"..\client\scriplib.h"\
+	"..\client\trilib.h"\
+	
+
+"$(INTDIR)\sv_init.obj" : $(SOURCE) $(DEP_CPP_SV_IN) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwsv - Win32 Debug"
+
+DEP_CPP_SV_IN=\
+	"..\client\spritegn.h"\
+	".\../client\bothdefs.h"\
+	".\../client\bspfile.h"\
+	".\../client\cmd.h"\
+	".\../client\common.h"\
+	".\../client\crc.h"\
+	".\../client\cvar.h"\
+	".\../client\mathlib.h"\
+	".\../client\model.h"\
+	".\../client\net.h"\
+	".\../client\pmove.h"\
+	".\../client\protocol.h"\
+	".\../client\zone.h"\
+	".\..\client\modelgen.h"\
+	".\pr_comp.h"\
+	".\progdefs.h"\
+	".\progs.h"\
+	".\qwsvdef.h"\
+	".\server.h"\
+	".\sys.h"\
+	".\world.h"\
+	
+NODEP_CPP_SV_IN=\
+	"..\client\cmdlib.h"\
+	"..\client\dictlib.h"\
+	"..\client\lbmlib.h"\
+	"..\client\scriplib.h"\
+	"..\client\trilib.h"\
+	
+
+"$(INTDIR)\sv_init.obj" : $(SOURCE) $(DEP_CPP_SV_IN) "$(INTDIR)"
+
+"$(INTDIR)\sv_init.sbr" : $(SOURCE) $(DEP_CPP_SV_IN) "$(INTDIR)"
+
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\sv_main.c
+
+!IF  "$(CFG)" == "qwsv - Win32 Release"
+
+DEP_CPP_SV_MA=\
+	"..\client\spritegn.h"\
+	".\../client\bothdefs.h"\
+	".\../client\bspfile.h"\
+	".\../client\cmd.h"\
+	".\../client\common.h"\
+	".\../client\crc.h"\
+	".\../client\cvar.h"\
+	".\../client\mathlib.h"\
+	".\../client\model.h"\
+	".\../client\net.h"\
+	".\../client\pmove.h"\
+	".\../client\protocol.h"\
+	".\../client\zone.h"\
+	".\..\client\modelgen.h"\
+	".\pr_comp.h"\
+	".\progdefs.h"\
+	".\progs.h"\
+	".\qwsvdef.h"\
+	".\server.h"\
+	".\sys.h"\
+	".\world.h"\
+	
+NODEP_CPP_SV_MA=\
+	"..\client\cmdlib.h"\
+	"..\client\dictlib.h"\
+	"..\client\lbmlib.h"\
+	"..\client\scriplib.h"\
+	"..\client\trilib.h"\
+	
+
+"$(INTDIR)\sv_main.obj" : $(SOURCE) $(DEP_CPP_SV_MA) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwsv - Win32 Debug"
+
+DEP_CPP_SV_MA=\
+	"..\client\spritegn.h"\
+	".\../client\bothdefs.h"\
+	".\../client\bspfile.h"\
+	".\../client\cmd.h"\
+	".\../client\common.h"\
+	".\../client\crc.h"\
+	".\../client\cvar.h"\
+	".\../client\mathlib.h"\
+	".\../client\model.h"\
+	".\../client\net.h"\
+	".\../client\pmove.h"\
+	".\../client\protocol.h"\
+	".\../client\zone.h"\
+	".\..\client\modelgen.h"\
+	".\pr_comp.h"\
+	".\progdefs.h"\
+	".\progs.h"\
+	".\qwsvdef.h"\
+	".\server.h"\
+	".\sys.h"\
+	".\world.h"\
+	
+NODEP_CPP_SV_MA=\
+	"..\client\cmdlib.h"\
+	"..\client\dictlib.h"\
+	"..\client\lbmlib.h"\
+	"..\client\scriplib.h"\
+	"..\client\trilib.h"\
+	
+
+"$(INTDIR)\sv_main.obj" : $(SOURCE) $(DEP_CPP_SV_MA) "$(INTDIR)"
+
+"$(INTDIR)\sv_main.sbr" : $(SOURCE) $(DEP_CPP_SV_MA) "$(INTDIR)"
+
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\sv_move.c
+
+!IF  "$(CFG)" == "qwsv - Win32 Release"
+
+DEP_CPP_SV_MO=\
+	"..\client\spritegn.h"\
+	".\../client\bothdefs.h"\
+	".\../client\bspfile.h"\
+	".\../client\cmd.h"\
+	".\../client\common.h"\
+	".\../client\crc.h"\
+	".\../client\cvar.h"\
+	".\../client\mathlib.h"\
+	".\../client\model.h"\
+	".\../client\net.h"\
+	".\../client\pmove.h"\
+	".\../client\protocol.h"\
+	".\../client\zone.h"\
+	".\..\client\modelgen.h"\
+	".\pr_comp.h"\
+	".\progdefs.h"\
+	".\progs.h"\
+	".\qwsvdef.h"\
+	".\server.h"\
+	".\sys.h"\
+	".\world.h"\
+	
+NODEP_CPP_SV_MO=\
+	"..\client\cmdlib.h"\
+	"..\client\dictlib.h"\
+	"..\client\lbmlib.h"\
+	"..\client\scriplib.h"\
+	"..\client\trilib.h"\
+	
+
+"$(INTDIR)\sv_move.obj" : $(SOURCE) $(DEP_CPP_SV_MO) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwsv - Win32 Debug"
+
+DEP_CPP_SV_MO=\
+	"..\client\spritegn.h"\
+	".\../client\bothdefs.h"\
+	".\../client\bspfile.h"\
+	".\../client\cmd.h"\
+	".\../client\common.h"\
+	".\../client\crc.h"\
+	".\../client\cvar.h"\
+	".\../client\mathlib.h"\
+	".\../client\model.h"\
+	".\../client\net.h"\
+	".\../client\pmove.h"\
+	".\../client\protocol.h"\
+	".\../client\zone.h"\
+	".\..\client\modelgen.h"\
+	".\pr_comp.h"\
+	".\progdefs.h"\
+	".\progs.h"\
+	".\qwsvdef.h"\
+	".\server.h"\
+	".\sys.h"\
+	".\world.h"\
+	
+NODEP_CPP_SV_MO=\
+	"..\client\cmdlib.h"\
+	"..\client\dictlib.h"\
+	"..\client\lbmlib.h"\
+	"..\client\scriplib.h"\
+	"..\client\trilib.h"\
+	
+
+"$(INTDIR)\sv_move.obj" : $(SOURCE) $(DEP_CPP_SV_MO) "$(INTDIR)"
+
+"$(INTDIR)\sv_move.sbr" : $(SOURCE) $(DEP_CPP_SV_MO) "$(INTDIR)"
+
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\sv_phys.c
+
+!IF  "$(CFG)" == "qwsv - Win32 Release"
+
+DEP_CPP_SV_PH=\
+	"..\client\spritegn.h"\
+	".\../client\bothdefs.h"\
+	".\../client\bspfile.h"\
+	".\../client\cmd.h"\
+	".\../client\common.h"\
+	".\../client\crc.h"\
+	".\../client\cvar.h"\
+	".\../client\mathlib.h"\
+	".\../client\model.h"\
+	".\../client\net.h"\
+	".\../client\pmove.h"\
+	".\../client\protocol.h"\
+	".\../client\zone.h"\
+	".\..\client\modelgen.h"\
+	".\pr_comp.h"\
+	".\progdefs.h"\
+	".\progs.h"\
+	".\qwsvdef.h"\
+	".\server.h"\
+	".\sys.h"\
+	".\world.h"\
+	
+NODEP_CPP_SV_PH=\
+	"..\client\cmdlib.h"\
+	"..\client\dictlib.h"\
+	"..\client\lbmlib.h"\
+	"..\client\scriplib.h"\
+	"..\client\trilib.h"\
+	
+
+"$(INTDIR)\sv_phys.obj" : $(SOURCE) $(DEP_CPP_SV_PH) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwsv - Win32 Debug"
+
+DEP_CPP_SV_PH=\
+	"..\client\spritegn.h"\
+	".\../client\bothdefs.h"\
+	".\../client\bspfile.h"\
+	".\../client\cmd.h"\
+	".\../client\common.h"\
+	".\../client\crc.h"\
+	".\../client\cvar.h"\
+	".\../client\mathlib.h"\
+	".\../client\model.h"\
+	".\../client\net.h"\
+	".\../client\pmove.h"\
+	".\../client\protocol.h"\
+	".\../client\zone.h"\
+	".\..\client\modelgen.h"\
+	".\pr_comp.h"\
+	".\progdefs.h"\
+	".\progs.h"\
+	".\qwsvdef.h"\
+	".\server.h"\
+	".\sys.h"\
+	".\world.h"\
+	
+NODEP_CPP_SV_PH=\
+	"..\client\cmdlib.h"\
+	"..\client\dictlib.h"\
+	"..\client\lbmlib.h"\
+	"..\client\scriplib.h"\
+	"..\client\trilib.h"\
+	
+
+"$(INTDIR)\sv_phys.obj" : $(SOURCE) $(DEP_CPP_SV_PH) "$(INTDIR)"
+
+"$(INTDIR)\sv_phys.sbr" : $(SOURCE) $(DEP_CPP_SV_PH) "$(INTDIR)"
+
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\sv_send.c
+
+!IF  "$(CFG)" == "qwsv - Win32 Release"
+
+DEP_CPP_SV_SE=\
+	"..\client\spritegn.h"\
+	".\../client\bothdefs.h"\
+	".\../client\bspfile.h"\
+	".\../client\cmd.h"\
+	".\../client\common.h"\
+	".\../client\crc.h"\
+	".\../client\cvar.h"\
+	".\../client\mathlib.h"\
+	".\../client\model.h"\
+	".\../client\net.h"\
+	".\../client\pmove.h"\
+	".\../client\protocol.h"\
+	".\../client\zone.h"\
+	".\..\client\modelgen.h"\
+	".\pr_comp.h"\
+	".\progdefs.h"\
+	".\progs.h"\
+	".\qwsvdef.h"\
+	".\server.h"\
+	".\sys.h"\
+	".\world.h"\
+	
+NODEP_CPP_SV_SE=\
+	"..\client\cmdlib.h"\
+	"..\client\dictlib.h"\
+	"..\client\lbmlib.h"\
+	"..\client\scriplib.h"\
+	"..\client\trilib.h"\
+	
+
+"$(INTDIR)\sv_send.obj" : $(SOURCE) $(DEP_CPP_SV_SE) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwsv - Win32 Debug"
+
+DEP_CPP_SV_SE=\
+	"..\client\spritegn.h"\
+	".\../client\bothdefs.h"\
+	".\../client\bspfile.h"\
+	".\../client\cmd.h"\
+	".\../client\common.h"\
+	".\../client\crc.h"\
+	".\../client\cvar.h"\
+	".\../client\mathlib.h"\
+	".\../client\model.h"\
+	".\../client\net.h"\
+	".\../client\pmove.h"\
+	".\../client\protocol.h"\
+	".\../client\zone.h"\
+	".\..\client\modelgen.h"\
+	".\pr_comp.h"\
+	".\progdefs.h"\
+	".\progs.h"\
+	".\qwsvdef.h"\
+	".\server.h"\
+	".\sys.h"\
+	".\world.h"\
+	
+NODEP_CPP_SV_SE=\
+	"..\client\cmdlib.h"\
+	"..\client\dictlib.h"\
+	"..\client\lbmlib.h"\
+	"..\client\scriplib.h"\
+	"..\client\trilib.h"\
+	
+
+"$(INTDIR)\sv_send.obj" : $(SOURCE) $(DEP_CPP_SV_SE) "$(INTDIR)"
+
+"$(INTDIR)\sv_send.sbr" : $(SOURCE) $(DEP_CPP_SV_SE) "$(INTDIR)"
+
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\sv_user.c
+
+!IF  "$(CFG)" == "qwsv - Win32 Release"
+
+DEP_CPP_SV_US=\
+	"..\client\spritegn.h"\
+	".\../client\bothdefs.h"\
+	".\../client\bspfile.h"\
+	".\../client\cmd.h"\
+	".\../client\common.h"\
+	".\../client\crc.h"\
+	".\../client\cvar.h"\
+	".\../client\mathlib.h"\
+	".\../client\model.h"\
+	".\../client\net.h"\
+	".\../client\pmove.h"\
+	".\../client\protocol.h"\
+	".\../client\zone.h"\
+	".\..\client\modelgen.h"\
+	".\pr_comp.h"\
+	".\progdefs.h"\
+	".\progs.h"\
+	".\qwsvdef.h"\
+	".\server.h"\
+	".\sys.h"\
+	".\world.h"\
+	
+NODEP_CPP_SV_US=\
+	"..\client\cmdlib.h"\
+	"..\client\dictlib.h"\
+	"..\client\lbmlib.h"\
+	"..\client\scriplib.h"\
+	"..\client\trilib.h"\
+	
+
+"$(INTDIR)\sv_user.obj" : $(SOURCE) $(DEP_CPP_SV_US) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwsv - Win32 Debug"
+
+DEP_CPP_SV_US=\
+	"..\client\spritegn.h"\
+	".\../client\bothdefs.h"\
+	".\../client\bspfile.h"\
+	".\../client\cmd.h"\
+	".\../client\common.h"\
+	".\../client\crc.h"\
+	".\../client\cvar.h"\
+	".\../client\mathlib.h"\
+	".\../client\model.h"\
+	".\../client\net.h"\
+	".\../client\pmove.h"\
+	".\../client\protocol.h"\
+	".\../client\zone.h"\
+	".\..\client\modelgen.h"\
+	".\pr_comp.h"\
+	".\progdefs.h"\
+	".\progs.h"\
+	".\qwsvdef.h"\
+	".\server.h"\
+	".\sys.h"\
+	".\world.h"\
+	
+NODEP_CPP_SV_US=\
+	"..\client\cmdlib.h"\
+	"..\client\dictlib.h"\
+	"..\client\lbmlib.h"\
+	"..\client\scriplib.h"\
+	"..\client\trilib.h"\
+	
+
+"$(INTDIR)\sv_user.obj" : $(SOURCE) $(DEP_CPP_SV_US) "$(INTDIR)"
+
+"$(INTDIR)\sv_user.sbr" : $(SOURCE) $(DEP_CPP_SV_US) "$(INTDIR)"
+
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\world.c
+
+!IF  "$(CFG)" == "qwsv - Win32 Release"
+
+DEP_CPP_WORLD=\
+	"..\client\spritegn.h"\
+	".\../client\bothdefs.h"\
+	".\../client\bspfile.h"\
+	".\../client\cmd.h"\
+	".\../client\common.h"\
+	".\../client\crc.h"\
+	".\../client\cvar.h"\
+	".\../client\mathlib.h"\
+	".\../client\model.h"\
+	".\../client\net.h"\
+	".\../client\pmove.h"\
+	".\../client\protocol.h"\
+	".\../client\zone.h"\
+	".\..\client\modelgen.h"\
+	".\pr_comp.h"\
+	".\progdefs.h"\
+	".\progs.h"\
+	".\qwsvdef.h"\
+	".\server.h"\
+	".\sys.h"\
+	".\world.h"\
+	
+NODEP_CPP_WORLD=\
+	"..\client\cmdlib.h"\
+	"..\client\dictlib.h"\
+	"..\client\lbmlib.h"\
+	"..\client\scriplib.h"\
+	"..\client\trilib.h"\
+	
+
+"$(INTDIR)\world.obj" : $(SOURCE) $(DEP_CPP_WORLD) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwsv - Win32 Debug"
+
+DEP_CPP_WORLD=\
+	"..\client\spritegn.h"\
+	".\../client\bothdefs.h"\
+	".\../client\bspfile.h"\
+	".\../client\cmd.h"\
+	".\../client\common.h"\
+	".\../client\crc.h"\
+	".\../client\cvar.h"\
+	".\../client\mathlib.h"\
+	".\../client\model.h"\
+	".\../client\net.h"\
+	".\../client\pmove.h"\
+	".\../client\protocol.h"\
+	".\../client\zone.h"\
+	".\..\client\modelgen.h"\
+	".\pr_comp.h"\
+	".\progdefs.h"\
+	".\progs.h"\
+	".\qwsvdef.h"\
+	".\server.h"\
+	".\sys.h"\
+	".\world.h"\
+	
+NODEP_CPP_WORLD=\
+	"..\client\cmdlib.h"\
+	"..\client\dictlib.h"\
+	"..\client\lbmlib.h"\
+	"..\client\scriplib.h"\
+	"..\client\trilib.h"\
+	
+
+"$(INTDIR)\world.obj" : $(SOURCE) $(DEP_CPP_WORLD) "$(INTDIR)"
+
+"$(INTDIR)\world.sbr" : $(SOURCE) $(DEP_CPP_WORLD) "$(INTDIR)"
+
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\sys_win.c
+
+!IF  "$(CFG)" == "qwsv - Win32 Release"
+
+DEP_CPP_SYS_W=\
+	"..\client\spritegn.h"\
+	".\../client\bothdefs.h"\
+	".\../client\bspfile.h"\
+	".\../client\cmd.h"\
+	".\../client\common.h"\
+	".\../client\crc.h"\
+	".\../client\cvar.h"\
+	".\../client\mathlib.h"\
+	".\../client\model.h"\
+	".\../client\net.h"\
+	".\../client\pmove.h"\
+	".\../client\protocol.h"\
+	".\../client\zone.h"\
+	".\..\client\modelgen.h"\
+	".\pr_comp.h"\
+	".\progdefs.h"\
+	".\progs.h"\
+	".\qwsvdef.h"\
+	".\server.h"\
+	".\sys.h"\
+	".\world.h"\
+	{$(INCLUDE)}"\sys\TIMEB.H"\
+	{$(INCLUDE)}"\sys\TYPES.H"\
+	
+NODEP_CPP_SYS_W=\
+	"..\client\cmdlib.h"\
+	"..\client\dictlib.h"\
+	"..\client\lbmlib.h"\
+	"..\client\scriplib.h"\
+	"..\client\trilib.h"\
+	
+
+"$(INTDIR)\sys_win.obj" : $(SOURCE) $(DEP_CPP_SYS_W) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwsv - Win32 Debug"
+
+DEP_CPP_SYS_W=\
+	"..\client\spritegn.h"\
+	".\../client\bothdefs.h"\
+	".\../client\bspfile.h"\
+	".\../client\cmd.h"\
+	".\../client\common.h"\
+	".\../client\crc.h"\
+	".\../client\cvar.h"\
+	".\../client\mathlib.h"\
+	".\../client\model.h"\
+	".\../client\net.h"\
+	".\../client\pmove.h"\
+	".\../client\protocol.h"\
+	".\../client\zone.h"\
+	".\..\client\modelgen.h"\
+	".\pr_comp.h"\
+	".\progdefs.h"\
+	".\progs.h"\
+	".\qwsvdef.h"\
+	".\server.h"\
+	".\sys.h"\
+	".\world.h"\
+	{$(INCLUDE)}"\sys\TIMEB.H"\
+	{$(INCLUDE)}"\sys\TYPES.H"\
+	
+NODEP_CPP_SYS_W=\
+	"..\client\cmdlib.h"\
+	"..\client\dictlib.h"\
+	"..\client\lbmlib.h"\
+	"..\client\scriplib.h"\
+	"..\client\trilib.h"\
+	
+
+"$(INTDIR)\sys_win.obj" : $(SOURCE) $(DEP_CPP_SYS_W) "$(INTDIR)"
+
+"$(INTDIR)\sys_win.sbr" : $(SOURCE) $(DEP_CPP_SYS_W) "$(INTDIR)"
+
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\server.h
+
+!IF  "$(CFG)" == "qwsv - Win32 Release"
+
+!ELSEIF  "$(CFG)" == "qwsv - Win32 Debug"
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=\quake\v2\client\net.h
+
+!IF  "$(CFG)" == "qwsv - Win32 Release"
+
+!ELSEIF  "$(CFG)" == "qwsv - Win32 Debug"
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\sv_ents.c
+
+!IF  "$(CFG)" == "qwsv - Win32 Release"
+
+DEP_CPP_SV_EN=\
+	"..\client\spritegn.h"\
+	".\../client\bothdefs.h"\
+	".\../client\bspfile.h"\
+	".\../client\cmd.h"\
+	".\../client\common.h"\
+	".\../client\crc.h"\
+	".\../client\cvar.h"\
+	".\../client\mathlib.h"\
+	".\../client\model.h"\
+	".\../client\net.h"\
+	".\../client\pmove.h"\
+	".\../client\protocol.h"\
+	".\../client\zone.h"\
+	".\..\client\modelgen.h"\
+	".\pr_comp.h"\
+	".\progdefs.h"\
+	".\progs.h"\
+	".\qwsvdef.h"\
+	".\server.h"\
+	".\sys.h"\
+	".\world.h"\
+	
+NODEP_CPP_SV_EN=\
+	"..\client\cmdlib.h"\
+	"..\client\dictlib.h"\
+	"..\client\lbmlib.h"\
+	"..\client\scriplib.h"\
+	"..\client\trilib.h"\
+	
+
+"$(INTDIR)\sv_ents.obj" : $(SOURCE) $(DEP_CPP_SV_EN) "$(INTDIR)"
+
+
+!ELSEIF  "$(CFG)" == "qwsv - Win32 Debug"
+
+DEP_CPP_SV_EN=\
+	"..\client\spritegn.h"\
+	".\../client\bothdefs.h"\
+	".\../client\bspfile.h"\
+	".\../client\cmd.h"\
+	".\../client\common.h"\
+	".\../client\crc.h"\
+	".\../client\cvar.h"\
+	".\../client\mathlib.h"\
+	".\../client\model.h"\
+	".\../client\net.h"\
+	".\../client\pmove.h"\
+	".\../client\protocol.h"\
+	".\../client\zone.h"\
+	".\..\client\modelgen.h"\
+	".\pr_comp.h"\
+	".\progdefs.h"\
+	".\progs.h"\
+	".\qwsvdef.h"\
+	".\server.h"\
+	".\sys.h"\
+	".\world.h"\
+	
+NODEP_CPP_SV_EN=\
+	"..\client\cmdlib.h"\
+	"..\client\dictlib.h"\
+	"..\client\lbmlib.h"\
+	"..\client\scriplib.h"\
+	"..\client\trilib.h"\
+	
+
+"$(INTDIR)\sv_ents.obj" : $(SOURCE) $(DEP_CPP_SV_EN) "$(INTDIR)"
+
+"$(INTDIR)\sv_ents.sbr" : $(SOURCE) $(DEP_CPP_SV_EN) "$(INTDIR)"
+
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=\Projects\QW\client\mathlib.c
+DEP_CPP_MATHL=\
+	"..\client\cdaudio.h"\
+	"..\client\client.h"\
+	"..\client\console.h"\
+	"..\client\d_iface.h"\
+	"..\client\draw.h"\
+	"..\client\gl_model.h"\
+	"..\client\glquake.h"\
+	"..\client\input.h"\
+	"..\client\keys.h"\
+	"..\client\menu.h"\
+	"..\client\render.h"\
+	"..\client\sbar.h"\
+	"..\client\screen.h"\
+	"..\client\sound.h"\
+	"..\client\spritegn.h"\
+	"..\client\sys.h"\
+	"..\client\vid.h"\
+	"..\client\view.h"\
+	"..\client\wad.h"\
+	".\../client\bothdefs.h"\
+	".\../client\bspfile.h"\
+	".\../client\cmd.h"\
+	".\../client\common.h"\
+	".\../client\crc.h"\
+	".\../client\cvar.h"\
+	".\../client\mathlib.h"\
+	".\../client\model.h"\
+	".\../client\net.h"\
+	".\../client\pmove.h"\
+	".\../client\protocol.h"\
+	".\../client\zone.h"\
+	".\..\client\modelgen.h"\
+	".\..\client\quakedef.h"\
+	
+NODEP_CPP_MATHL=\
+	"..\client\cmdlib.h"\
+	"..\client\dictlib.h"\
+	"..\client\lbmlib.h"\
+	"..\client\scriplib.h"\
+	"..\client\trilib.h"\
+	
+
+!IF  "$(CFG)" == "qwsv - Win32 Release"
+
+
+"$(INTDIR)\mathlib.obj" : $(SOURCE) $(DEP_CPP_MATHL) "$(INTDIR)"
+   $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF  "$(CFG)" == "qwsv - Win32 Debug"
+
+
+BuildCmds= \
+	$(CPP) $(CPP_PROJ) $(SOURCE) \
+	
+
+"$(INTDIR)\mathlib.obj" : $(SOURCE) $(DEP_CPP_MATHL) "$(INTDIR)"
+   $(BuildCmds)
+
+"$(INTDIR)\mathlib.sbr" : $(SOURCE) $(DEP_CPP_MATHL) "$(INTDIR)"
+   $(BuildCmds)
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=\Projects\QW\client\net_chan.c
+DEP_CPP_NET_C=\
+	"..\client\cdaudio.h"\
+	"..\client\client.h"\
+	"..\client\console.h"\
+	"..\client\d_iface.h"\
+	"..\client\draw.h"\
+	"..\client\gl_model.h"\
+	"..\client\glquake.h"\
+	"..\client\input.h"\
+	"..\client\keys.h"\
+	"..\client\menu.h"\
+	"..\client\render.h"\
+	"..\client\sbar.h"\
+	"..\client\screen.h"\
+	"..\client\sound.h"\
+	"..\client\spritegn.h"\
+	"..\client\sys.h"\
+	"..\client\vid.h"\
+	"..\client\view.h"\
+	"..\client\wad.h"\
+	".\../client\bothdefs.h"\
+	".\../client\bspfile.h"\
+	".\../client\cmd.h"\
+	".\../client\common.h"\
+	".\../client\crc.h"\
+	".\../client\cvar.h"\
+	".\../client\mathlib.h"\
+	".\../client\model.h"\
+	".\../client\net.h"\
+	".\../client\pmove.h"\
+	".\../client\protocol.h"\
+	".\../client\zone.h"\
+	".\..\client\modelgen.h"\
+	".\..\client\quakedef.h"\
+	
+NODEP_CPP_NET_C=\
+	"..\client\cmdlib.h"\
+	"..\client\dictlib.h"\
+	"..\client\lbmlib.h"\
+	"..\client\scriplib.h"\
+	"..\client\trilib.h"\
+	
+
+!IF  "$(CFG)" == "qwsv - Win32 Release"
+
+
+"$(INTDIR)\net_chan.obj" : $(SOURCE) $(DEP_CPP_NET_C) "$(INTDIR)"
+   $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF  "$(CFG)" == "qwsv - Win32 Debug"
+
+
+BuildCmds= \
+	$(CPP) $(CPP_PROJ) $(SOURCE) \
+	
+
+"$(INTDIR)\net_chan.obj" : $(SOURCE) $(DEP_CPP_NET_C) "$(INTDIR)"
+   $(BuildCmds)
+
+"$(INTDIR)\net_chan.sbr" : $(SOURCE) $(DEP_CPP_NET_C) "$(INTDIR)"
+   $(BuildCmds)
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=\Projects\QW\client\common.c
+DEP_CPP_COMMO=\
+	"..\client\cdaudio.h"\
+	"..\client\client.h"\
+	"..\client\console.h"\
+	"..\client\d_iface.h"\
+	"..\client\draw.h"\
+	"..\client\gl_model.h"\
+	"..\client\glquake.h"\
+	"..\client\input.h"\
+	"..\client\keys.h"\
+	"..\client\menu.h"\
+	"..\client\render.h"\
+	"..\client\sbar.h"\
+	"..\client\screen.h"\
+	"..\client\sound.h"\
+	"..\client\spritegn.h"\
+	"..\client\sys.h"\
+	"..\client\vid.h"\
+	"..\client\view.h"\
+	"..\client\wad.h"\
+	".\../client\bothdefs.h"\
+	".\../client\bspfile.h"\
+	".\../client\cmd.h"\
+	".\../client\common.h"\
+	".\../client\crc.h"\
+	".\../client\cvar.h"\
+	".\../client\mathlib.h"\
+	".\../client\model.h"\
+	".\../client\net.h"\
+	".\../client\pmove.h"\
+	".\../client\protocol.h"\
+	".\../client\zone.h"\
+	".\..\client\modelgen.h"\
+	".\..\client\quakedef.h"\
+	
+NODEP_CPP_COMMO=\
+	"..\client\cmdlib.h"\
+	"..\client\dictlib.h"\
+	"..\client\lbmlib.h"\
+	"..\client\qwsvdef.h"\
+	"..\client\scriplib.h"\
+	"..\client\trilib.h"\
+	
+
+!IF  "$(CFG)" == "qwsv - Win32 Release"
+
+
+"$(INTDIR)\common.obj" : $(SOURCE) $(DEP_CPP_COMMO) "$(INTDIR)"
+   $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF  "$(CFG)" == "qwsv - Win32 Debug"
+
+
+BuildCmds= \
+	$(CPP) $(CPP_PROJ) $(SOURCE) \
+	
+
+"$(INTDIR)\common.obj" : $(SOURCE) $(DEP_CPP_COMMO) "$(INTDIR)"
+   $(BuildCmds)
+
+"$(INTDIR)\common.sbr" : $(SOURCE) $(DEP_CPP_COMMO) "$(INTDIR)"
+   $(BuildCmds)
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=\Projects\QW\client\pmovetst.c
+DEP_CPP_PMOVE=\
+	"..\client\cdaudio.h"\
+	"..\client\client.h"\
+	"..\client\console.h"\
+	"..\client\d_iface.h"\
+	"..\client\draw.h"\
+	"..\client\gl_model.h"\
+	"..\client\glquake.h"\
+	"..\client\input.h"\
+	"..\client\keys.h"\
+	"..\client\menu.h"\
+	"..\client\render.h"\
+	"..\client\sbar.h"\
+	"..\client\screen.h"\
+	"..\client\sound.h"\
+	"..\client\spritegn.h"\
+	"..\client\sys.h"\
+	"..\client\vid.h"\
+	"..\client\view.h"\
+	"..\client\wad.h"\
+	".\../client\bothdefs.h"\
+	".\../client\bspfile.h"\
+	".\../client\cmd.h"\
+	".\../client\common.h"\
+	".\../client\crc.h"\
+	".\../client\cvar.h"\
+	".\../client\mathlib.h"\
+	".\../client\model.h"\
+	".\../client\net.h"\
+	".\../client\pmove.h"\
+	".\../client\protocol.h"\
+	".\../client\zone.h"\
+	".\..\client\modelgen.h"\
+	".\..\client\quakedef.h"\
+	
+NODEP_CPP_PMOVE=\
+	"..\client\cmdlib.h"\
+	"..\client\dictlib.h"\
+	"..\client\lbmlib.h"\
+	"..\client\scriplib.h"\
+	"..\client\trilib.h"\
+	
+
+!IF  "$(CFG)" == "qwsv - Win32 Release"
+
+
+"$(INTDIR)\pmovetst.obj" : $(SOURCE) $(DEP_CPP_PMOVE) "$(INTDIR)"
+   $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF  "$(CFG)" == "qwsv - Win32 Debug"
+
+
+BuildCmds= \
+	$(CPP) $(CPP_PROJ) $(SOURCE) \
+	
+
+"$(INTDIR)\pmovetst.obj" : $(SOURCE) $(DEP_CPP_PMOVE) "$(INTDIR)"
+   $(BuildCmds)
+
+"$(INTDIR)\pmovetst.sbr" : $(SOURCE) $(DEP_CPP_PMOVE) "$(INTDIR)"
+   $(BuildCmds)
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=\Projects\QW\client\pmove.c
+DEP_CPP_PMOVE_=\
+	"..\client\cdaudio.h"\
+	"..\client\client.h"\
+	"..\client\console.h"\
+	"..\client\d_iface.h"\
+	"..\client\draw.h"\
+	"..\client\gl_model.h"\
+	"..\client\glquake.h"\
+	"..\client\input.h"\
+	"..\client\keys.h"\
+	"..\client\menu.h"\
+	"..\client\render.h"\
+	"..\client\sbar.h"\
+	"..\client\screen.h"\
+	"..\client\sound.h"\
+	"..\client\spritegn.h"\
+	"..\client\sys.h"\
+	"..\client\vid.h"\
+	"..\client\view.h"\
+	"..\client\wad.h"\
+	".\../client\bothdefs.h"\
+	".\../client\bspfile.h"\
+	".\../client\cmd.h"\
+	".\../client\common.h"\
+	".\../client\crc.h"\
+	".\../client\cvar.h"\
+	".\../client\mathlib.h"\
+	".\../client\model.h"\
+	".\../client\net.h"\
+	".\../client\pmove.h"\
+	".\../client\protocol.h"\
+	".\../client\zone.h"\
+	".\..\client\modelgen.h"\
+	".\..\client\quakedef.h"\
+	
+NODEP_CPP_PMOVE_=\
+	"..\client\cmdlib.h"\
+	"..\client\dictlib.h"\
+	"..\client\lbmlib.h"\
+	"..\client\scriplib.h"\
+	"..\client\trilib.h"\
+	
+
+!IF  "$(CFG)" == "qwsv - Win32 Release"
+
+
+"$(INTDIR)\pmove.obj" : $(SOURCE) $(DEP_CPP_PMOVE_) "$(INTDIR)"
+   $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF  "$(CFG)" == "qwsv - Win32 Debug"
+
+
+BuildCmds= \
+	$(CPP) $(CPP_PROJ) $(SOURCE) \
+	
+
+"$(INTDIR)\pmove.obj" : $(SOURCE) $(DEP_CPP_PMOVE_) "$(INTDIR)"
+   $(BuildCmds)
+
+"$(INTDIR)\pmove.sbr" : $(SOURCE) $(DEP_CPP_PMOVE_) "$(INTDIR)"
+   $(BuildCmds)
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=\Projects\QW\client\cvar.c
+DEP_CPP_CVAR_=\
+	"..\client\cdaudio.h"\
+	"..\client\client.h"\
+	"..\client\console.h"\
+	"..\client\d_iface.h"\
+	"..\client\draw.h"\
+	"..\client\gl_model.h"\
+	"..\client\glquake.h"\
+	"..\client\input.h"\
+	"..\client\keys.h"\
+	"..\client\menu.h"\
+	"..\client\render.h"\
+	"..\client\sbar.h"\
+	"..\client\screen.h"\
+	"..\client\sound.h"\
+	"..\client\spritegn.h"\
+	"..\client\sys.h"\
+	"..\client\vid.h"\
+	"..\client\view.h"\
+	"..\client\wad.h"\
+	".\../client\bothdefs.h"\
+	".\../client\bspfile.h"\
+	".\../client\cmd.h"\
+	".\../client\common.h"\
+	".\../client\crc.h"\
+	".\../client\cvar.h"\
+	".\../client\mathlib.h"\
+	".\../client\model.h"\
+	".\../client\net.h"\
+	".\../client\pmove.h"\
+	".\../client\protocol.h"\
+	".\../client\zone.h"\
+	".\..\client\modelgen.h"\
+	".\..\client\quakedef.h"\
+	
+NODEP_CPP_CVAR_=\
+	"..\client\cmdlib.h"\
+	"..\client\dictlib.h"\
+	"..\client\lbmlib.h"\
+	"..\client\qwsvdef.h"\
+	"..\client\scriplib.h"\
+	"..\client\trilib.h"\
+	
+
+!IF  "$(CFG)" == "qwsv - Win32 Release"
+
+
+"$(INTDIR)\cvar.obj" : $(SOURCE) $(DEP_CPP_CVAR_) "$(INTDIR)"
+   $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF  "$(CFG)" == "qwsv - Win32 Debug"
+
+
+BuildCmds= \
+	$(CPP) $(CPP_PROJ) $(SOURCE) \
+	
+
+"$(INTDIR)\cvar.obj" : $(SOURCE) $(DEP_CPP_CVAR_) "$(INTDIR)"
+   $(BuildCmds)
+
+"$(INTDIR)\cvar.sbr" : $(SOURCE) $(DEP_CPP_CVAR_) "$(INTDIR)"
+   $(BuildCmds)
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=\Projects\QW\client\crc.c
+DEP_CPP_CRC_C=\
+	"..\client\cdaudio.h"\
+	"..\client\client.h"\
+	"..\client\console.h"\
+	"..\client\d_iface.h"\
+	"..\client\draw.h"\
+	"..\client\gl_model.h"\
+	"..\client\glquake.h"\
+	"..\client\input.h"\
+	"..\client\keys.h"\
+	"..\client\menu.h"\
+	"..\client\render.h"\
+	"..\client\sbar.h"\
+	"..\client\screen.h"\
+	"..\client\sound.h"\
+	"..\client\spritegn.h"\
+	"..\client\sys.h"\
+	"..\client\vid.h"\
+	"..\client\view.h"\
+	"..\client\wad.h"\
+	".\../client\bothdefs.h"\
+	".\../client\bspfile.h"\
+	".\../client\cmd.h"\
+	".\../client\common.h"\
+	".\../client\crc.h"\
+	".\../client\cvar.h"\
+	".\../client\mathlib.h"\
+	".\../client\model.h"\
+	".\../client\net.h"\
+	".\../client\pmove.h"\
+	".\../client\protocol.h"\
+	".\../client\zone.h"\
+	".\..\client\modelgen.h"\
+	".\..\client\quakedef.h"\
+	
+NODEP_CPP_CRC_C=\
+	"..\client\cmdlib.h"\
+	"..\client\dictlib.h"\
+	"..\client\lbmlib.h"\
+	"..\client\scriplib.h"\
+	"..\client\trilib.h"\
+	
+
+!IF  "$(CFG)" == "qwsv - Win32 Release"
+
+
+"$(INTDIR)\crc.obj" : $(SOURCE) $(DEP_CPP_CRC_C) "$(INTDIR)"
+   $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF  "$(CFG)" == "qwsv - Win32 Debug"
+
+
+BuildCmds= \
+	$(CPP) $(CPP_PROJ) $(SOURCE) \
+	
+
+"$(INTDIR)\crc.obj" : $(SOURCE) $(DEP_CPP_CRC_C) "$(INTDIR)"
+   $(BuildCmds)
+
+"$(INTDIR)\crc.sbr" : $(SOURCE) $(DEP_CPP_CRC_C) "$(INTDIR)"
+   $(BuildCmds)
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=\Projects\QW\client\net_wins.c
+DEP_CPP_NET_W=\
+	"..\client\cdaudio.h"\
+	"..\client\client.h"\
+	"..\client\console.h"\
+	"..\client\d_iface.h"\
+	"..\client\draw.h"\
+	"..\client\gl_model.h"\
+	"..\client\glquake.h"\
+	"..\client\input.h"\
+	"..\client\keys.h"\
+	"..\client\menu.h"\
+	"..\client\render.h"\
+	"..\client\sbar.h"\
+	"..\client\screen.h"\
+	"..\client\sound.h"\
+	"..\client\spritegn.h"\
+	"..\client\sys.h"\
+	"..\client\vid.h"\
+	"..\client\view.h"\
+	"..\client\wad.h"\
+	".\../client\bothdefs.h"\
+	".\../client\bspfile.h"\
+	".\../client\cmd.h"\
+	".\../client\common.h"\
+	".\../client\crc.h"\
+	".\../client\cvar.h"\
+	".\../client\mathlib.h"\
+	".\../client\model.h"\
+	".\../client\net.h"\
+	".\../client\pmove.h"\
+	".\../client\protocol.h"\
+	".\../client\zone.h"\
+	".\..\client\modelgen.h"\
+	".\..\client\quakedef.h"\
+	".\..\client\winquake.h"\
+	
+NODEP_CPP_NET_W=\
+	"..\client\cmdlib.h"\
+	"..\client\dictlib.h"\
+	"..\client\lbmlib.h"\
+	"..\client\scriplib.h"\
+	"..\client\trilib.h"\
+	
+
+!IF  "$(CFG)" == "qwsv - Win32 Release"
+
+
+"$(INTDIR)\net_wins.obj" : $(SOURCE) $(DEP_CPP_NET_W) "$(INTDIR)"
+   $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF  "$(CFG)" == "qwsv - Win32 Debug"
+
+
+BuildCmds= \
+	$(CPP) $(CPP_PROJ) $(SOURCE) \
+	
+
+"$(INTDIR)\net_wins.obj" : $(SOURCE) $(DEP_CPP_NET_W) "$(INTDIR)"
+   $(BuildCmds)
+
+"$(INTDIR)\net_wins.sbr" : $(SOURCE) $(DEP_CPP_NET_W) "$(INTDIR)"
+   $(BuildCmds)
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=\Projects\QW\client\zone.c
+DEP_CPP_ZONE_=\
+	"..\client\cdaudio.h"\
+	"..\client\client.h"\
+	"..\client\console.h"\
+	"..\client\d_iface.h"\
+	"..\client\draw.h"\
+	"..\client\gl_model.h"\
+	"..\client\glquake.h"\
+	"..\client\input.h"\
+	"..\client\keys.h"\
+	"..\client\menu.h"\
+	"..\client\render.h"\
+	"..\client\sbar.h"\
+	"..\client\screen.h"\
+	"..\client\sound.h"\
+	"..\client\spritegn.h"\
+	"..\client\sys.h"\
+	"..\client\vid.h"\
+	"..\client\view.h"\
+	"..\client\wad.h"\
+	".\../client\bothdefs.h"\
+	".\../client\bspfile.h"\
+	".\../client\cmd.h"\
+	".\../client\common.h"\
+	".\../client\crc.h"\
+	".\../client\cvar.h"\
+	".\../client\mathlib.h"\
+	".\../client\model.h"\
+	".\../client\net.h"\
+	".\../client\pmove.h"\
+	".\../client\protocol.h"\
+	".\../client\zone.h"\
+	".\..\client\modelgen.h"\
+	".\..\client\quakedef.h"\
+	
+NODEP_CPP_ZONE_=\
+	"..\client\cmdlib.h"\
+	"..\client\dictlib.h"\
+	"..\client\lbmlib.h"\
+	"..\client\scriplib.h"\
+	"..\client\trilib.h"\
+	
+
+!IF  "$(CFG)" == "qwsv - Win32 Release"
+
+
+"$(INTDIR)\zone.obj" : $(SOURCE) $(DEP_CPP_ZONE_) "$(INTDIR)"
+   $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF  "$(CFG)" == "qwsv - Win32 Debug"
+
+
+BuildCmds= \
+	$(CPP) $(CPP_PROJ) $(SOURCE) \
+	
+
+"$(INTDIR)\zone.obj" : $(SOURCE) $(DEP_CPP_ZONE_) "$(INTDIR)"
+   $(BuildCmds)
+
+"$(INTDIR)\zone.sbr" : $(SOURCE) $(DEP_CPP_ZONE_) "$(INTDIR)"
+   $(BuildCmds)
+
+!ENDIF 
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=\Projects\QW\client\cmd.c
+DEP_CPP_CMD_C=\
+	"..\client\cdaudio.h"\
+	"..\client\client.h"\
+	"..\client\console.h"\
+	"..\client\d_iface.h"\
+	"..\client\draw.h"\
+	"..\client\gl_model.h"\
+	"..\client\glquake.h"\
+	"..\client\input.h"\
+	"..\client\keys.h"\
+	"..\client\menu.h"\
+	"..\client\render.h"\
+	"..\client\sbar.h"\
+	"..\client\screen.h"\
+	"..\client\sound.h"\
+	"..\client\spritegn.h"\
+	"..\client\sys.h"\
+	"..\client\vid.h"\
+	"..\client\view.h"\
+	"..\client\wad.h"\
+	".\../client\bothdefs.h"\
+	".\../client\bspfile.h"\
+	".\../client\cmd.h"\
+	".\../client\common.h"\
+	".\../client\crc.h"\
+	".\../client\cvar.h"\
+	".\../client\mathlib.h"\
+	".\../client\model.h"\
+	".\../client\net.h"\
+	".\../client\pmove.h"\
+	".\../client\protocol.h"\
+	".\../client\zone.h"\
+	".\..\client\modelgen.h"\
+	".\..\client\quakedef.h"\
+	
+NODEP_CPP_CMD_C=\
+	"..\client\cmdlib.h"\
+	"..\client\dictlib.h"\
+	"..\client\lbmlib.h"\
+	"..\client\scriplib.h"\
+	"..\client\trilib.h"\
+	
+
+!IF  "$(CFG)" == "qwsv - Win32 Release"
+
+
+"$(INTDIR)\cmd.obj" : $(SOURCE) $(DEP_CPP_CMD_C) "$(INTDIR)"
+   $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF  "$(CFG)" == "qwsv - Win32 Debug"
+
+
+BuildCmds= \
+	$(CPP) $(CPP_PROJ) $(SOURCE) \
+	
+
+"$(INTDIR)\cmd.obj" : $(SOURCE) $(DEP_CPP_CMD_C) "$(INTDIR)"
+   $(BuildCmds)
+
+"$(INTDIR)\cmd.sbr" : $(SOURCE) $(DEP_CPP_CMD_C) "$(INTDIR)"
+   $(BuildCmds)
+
+!ENDIF 
+
+# End Source File
+# End Target
+# End Project
+################################################################################
binary files /dev/null b/QW/server/qwsv.mdp differ
--- /dev/null
+++ b/QW/server/qwsv.plg
@@ -1,0 +1,107 @@
+<html>
+<body>
+<pre>
+<h1>Build Log</h1>
+<h3>
+--------------------Configuration: qwsv - Win32 Release--------------------
+</h3>
+<h3>Command Lines</h3>
+Creating temporary file "C:\TEMP\RSP778.tmp" with contents
+[
+/nologo /ML /GX /O2 /I "." /I "..\client" /D "NDEBUG" /D "SERVERONLY" /D "WIN32" /D "_CONSOLE" /FR".\Release/" /Fp".\Release/qwsv.pch" /YX /Fo".\Release/" /Fd".\Release/" /FD /c 
+"D:\Work\quake source\QW\client\cmd.c"
+"D:\Work\quake source\QW\client\common.c"
+"D:\Work\quake source\QW\client\crc.c"
+"D:\Work\quake source\QW\client\cvar.c"
+"D:\Work\quake source\QW\client\mathlib.c"
+"D:\Work\quake source\QW\client\md4.c"
+"D:\Work\quake source\QW\server\model.c"
+"D:\Work\quake source\QW\client\net_chan.c"
+"D:\Work\quake source\QW\client\net_wins.c"
+"D:\Work\quake source\QW\client\pmove.c"
+"D:\Work\quake source\QW\client\pmovetst.c"
+"D:\Work\quake source\QW\server\pr_cmds.c"
+"D:\Work\quake source\QW\server\pr_edict.c"
+"D:\Work\quake source\QW\server\pr_exec.c"
+"D:\Work\quake source\QW\server\sv_ccmds.c"
+"D:\Work\quake source\QW\server\sv_ents.c"
+"D:\Work\quake source\QW\server\sv_init.c"
+"D:\Work\quake source\QW\server\sv_main.c"
+"D:\Work\quake source\QW\server\sv_move.c"
+"D:\Work\quake source\QW\server\sv_nchan.c"
+"D:\Work\quake source\QW\server\sv_phys.c"
+"D:\Work\quake source\QW\server\sv_send.c"
+"D:\Work\quake source\QW\server\sv_user.c"
+"D:\Work\quake source\QW\server\sys_win.c"
+"D:\Work\quake source\QW\server\world.c"
+"D:\Work\quake source\QW\client\zone.c"
+]
+Creating command line "cl.exe @C:\TEMP\RSP778.tmp" 
+Creating temporary file "C:\TEMP\RSP779.tmp" with contents
+[
+wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib winmm.lib /nologo /subsystem:console /incremental:no /pdb:".\Release/qwsv.pdb" /machine:I386 /out:".\Release/qwsv.exe" 
+".\Release\cmd.obj"
+".\Release\common.obj"
+".\Release\crc.obj"
+".\Release\cvar.obj"
+".\Release\mathlib.obj"
+".\Release\md4.obj"
+".\Release\model.obj"
+".\Release\net_chan.obj"
+".\Release\net_wins.obj"
+".\Release\pmove.obj"
+".\Release\pmovetst.obj"
+".\Release\pr_cmds.obj"
+".\Release\pr_edict.obj"
+".\Release\pr_exec.obj"
+".\Release\sv_ccmds.obj"
+".\Release\sv_ents.obj"
+".\Release\sv_init.obj"
+".\Release\sv_main.obj"
+".\Release\sv_move.obj"
+".\Release\sv_nchan.obj"
+".\Release\sv_phys.obj"
+".\Release\sv_send.obj"
+".\Release\sv_user.obj"
+".\Release\sys_win.obj"
+".\Release\world.obj"
+".\Release\zone.obj"
+]
+Creating command line "link.exe @C:\TEMP\RSP779.tmp"
+<h3>Output Window</h3>
+Compiling...
+cmd.c
+common.c
+crc.c
+cvar.c
+mathlib.c
+md4.c
+model.c
+net_chan.c
+net_wins.c
+pmove.c
+pmovetst.c
+pr_cmds.c
+pr_edict.c
+pr_exec.c
+sv_ccmds.c
+sv_ents.c
+sv_init.c
+sv_main.c
+sv_move.c
+sv_nchan.c
+sv_phys.c
+sv_send.c
+sv_user.c
+sys_win.c
+world.c
+zone.c
+Linking...
+
+
+
+<h3>Results</h3>
+qwsv.exe - 0 error(s), 0 warning(s)
+</pre>
+</body>
+</html>
--- /dev/null
+++ b/QW/server/qwsvdef.h
@@ -1,0 +1,95 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// quakedef.h -- primary header for server
+
+#define	QUAKE_GAME			// as opposed to utilities
+
+//define	PARANOID			// speed sapping error checking
+
+#ifdef _WIN32
+#pragma warning( disable : 4244 4127 4201 4214 4514 4305 4115 4018)
+#endif
+
+#include <math.h>
+#include <string.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <setjmp.h>
+#include <ctype.h>
+
+#include "bothdefs.h"
+
+#include "common.h"
+#include "bspfile.h"
+#include "sys.h"
+#include "zone.h"
+#include "mathlib.h"
+
+#include "cvar.h"
+#include "net.h"
+#include "protocol.h"
+#include "cmd.h"
+#include "model.h"
+#include "crc.h"
+#include "progs.h"
+
+#include "server.h"
+#include "world.h"
+#include "pmove.h"
+
+//=============================================================================
+
+// the host system specifies the base of the directory tree, the
+// command line parms passed to the program, and the amount of memory
+// available for the program to use
+
+typedef struct
+{
+	char	*basedir;
+	char	*cachedir;		// for development over ISDN lines
+	int		argc;
+	char	**argv;
+	void	*membase;
+	int		memsize;
+} quakeparms_t;
+
+
+//=============================================================================
+
+//
+// host
+//
+extern	quakeparms_t host_parms;
+
+extern	cvar_t		sys_nostdout;
+extern	cvar_t		developer;
+
+extern	qboolean	host_initialized;		// true if into command execution
+extern	double		host_frametime;
+extern	double		realtime;			// not bounded in any way, changed at
+										// start of every frame, never reset
+
+void SV_Error (char *error, ...);
+void SV_Init (quakeparms_t *parms);
+
+void Con_Printf (char *fmt, ...);
+void Con_DPrintf (char *fmt, ...);
+
--- /dev/null
+++ b/QW/server/server.h
@@ -1,0 +1,456 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// server.h
+
+#define	QW_SERVER
+
+#define	MAX_MASTERS	8				// max recipients for heartbeat packets
+
+#define	MAX_SIGNON_BUFFERS	8
+
+typedef enum {
+	ss_dead,			// no map loaded
+	ss_loading,			// spawning level edicts
+	ss_active			// actively running
+} server_state_t;
+// some qc commands are only valid before the server has finished
+// initializing (precache commands, static sounds / objects, etc)
+
+typedef struct
+{
+	qboolean	active;				// false when server is going down
+	server_state_t	state;			// precache commands are only valid during load
+
+	double		time;
+	
+	int			lastcheck;			// used by PF_checkclient
+	double		lastchecktime;		// for monster ai 
+
+	qboolean	paused;				// are we paused?
+
+	//check player/eyes models for hacks
+	unsigned	model_player_checksum;
+	unsigned	eyes_player_checksum;
+	
+	char		name[64];			// map name
+	char		modelname[MAX_QPATH];		// maps/<name>.bsp, for model_precache[0]
+	struct model_s 	*worldmodel;
+	char		*model_precache[MAX_MODELS];	// NULL terminated
+	char		*sound_precache[MAX_SOUNDS];	// NULL terminated
+	char		*lightstyles[MAX_LIGHTSTYLES];
+	struct model_s		*models[MAX_MODELS];
+
+	int			num_edicts;			// increases towards MAX_EDICTS
+	edict_t		*edicts;			// can NOT be array indexed, because
+									// edict_t is variable sized, but can
+									// be used to reference the world ent
+
+	byte		*pvs, *phs;			// fully expanded and decompressed
+
+	// added to every client's unreliable buffer each frame, then cleared
+	sizebuf_t	datagram;
+	byte		datagram_buf[MAX_DATAGRAM];
+
+	// added to every client's reliable buffer each frame, then cleared
+	sizebuf_t	reliable_datagram;
+	byte		reliable_datagram_buf[MAX_MSGLEN];
+
+	// the multicast buffer is used to send a message to a set of clients
+	sizebuf_t	multicast;
+	byte		multicast_buf[MAX_MSGLEN];
+
+	// the master buffer is used for building log packets
+	sizebuf_t	master;
+	byte		master_buf[MAX_DATAGRAM];
+
+	// the signon buffer will be sent to each client as they connect
+	// includes the entity baselines, the static entities, etc
+	// large levels will have >MAX_DATAGRAM sized signons, so 
+	// multiple signon messages are kept
+	sizebuf_t	signon;
+	int			num_signon_buffers;
+	int			signon_buffer_size[MAX_SIGNON_BUFFERS];
+	byte		signon_buffers[MAX_SIGNON_BUFFERS][MAX_DATAGRAM];
+} server_t;
+
+
+#define	NUM_SPAWN_PARMS			16
+
+typedef enum
+{
+	cs_free,		// can be reused for a new connection
+	cs_zombie,		// client has been disconnected, but don't reuse
+					// connection for a couple seconds
+	cs_connected,	// has been assigned to a client_t, but not in game yet
+	cs_spawned		// client is fully in game
+} client_state_t;
+
+typedef struct
+{
+	// received from client
+
+	// reply
+	double				senttime;
+	float				ping_time;
+	packet_entities_t	entities;
+} client_frame_t;
+
+#define MAX_BACK_BUFFERS 4
+
+typedef struct client_s
+{
+	client_state_t	state;
+
+	int				spectator;			// non-interactive
+
+	qboolean		sendinfo;			// at end of frame, send info to all
+										// this prevents malicious multiple broadcasts
+	float			lastnametime;		// time of last name change
+	int				lastnamecount;		// time of last name change
+	unsigned		checksum;			// checksum for calcs
+	qboolean		drop;				// lose this guy next opportunity
+	int				lossage;			// loss percentage
+
+	int				userid;							// identifying number
+	char			userinfo[MAX_INFO_STRING];		// infostring
+
+	usercmd_t		lastcmd;			// for filling in big drops and partial predictions
+	double			localtime;			// of last message
+	int				oldbuttons;
+
+	float			maxspeed;			// localized maxspeed
+	float			entgravity;			// localized ent gravity
+
+	edict_t			*edict;				// EDICT_NUM(clientnum+1)
+	char			name[32];			// for printing to other people
+										// extracted from userinfo
+	int				messagelevel;		// for filtering printed messages
+
+	// the datagram is written to after every frame, but only cleared
+	// when it is sent out to the client.  overflow is tolerated.
+	sizebuf_t		datagram;
+	byte			datagram_buf[MAX_DATAGRAM];
+
+	// back buffers for client reliable data
+	sizebuf_t	backbuf;
+	int			num_backbuf;
+	int			backbuf_size[MAX_BACK_BUFFERS];
+	byte		backbuf_data[MAX_BACK_BUFFERS][MAX_MSGLEN];
+
+	double			connection_started;	// or time of disconnect for zombies
+	qboolean		send_message;		// set on frames a datagram arived on
+
+// spawn parms are carried from level to level
+	float			spawn_parms[NUM_SPAWN_PARMS];
+
+// client known data for deltas	
+	int				old_frags;
+	
+	int				stats[MAX_CL_STATS];
+
+
+	client_frame_t	frames[UPDATE_BACKUP];	// updates can be deltad from here
+
+	FILE			*download;			// file being downloaded
+	int				downloadsize;		// total bytes
+	int				downloadcount;		// bytes sent
+
+	int				spec_track;			// entnum of player tracking
+
+	double			whensaid[10];       // JACK: For floodprots
+ 	int			whensaidhead;       // Head value for floodprots
+ 	double			lockedtill;
+
+	qboolean		upgradewarn;		// did we warn him?
+
+	FILE			*upload;
+	char			uploadfn[MAX_QPATH];
+	netadr_t		snap_from;
+	qboolean		remote_snap;
+ 
+//===== NETWORK ============
+	int				chokecount;
+	int				delta_sequence;		// -1 = no compression
+	netchan_t		netchan;
+} client_t;
+
+// a client can leave the server in one of four ways:
+// dropping properly by quiting or disconnecting
+// timing out if no valid messages are received for timeout.value seconds
+// getting kicked off by the server operator
+// a program error, like an overflowed reliable buffer
+
+//=============================================================================
+
+
+#define	STATFRAMES	100
+typedef struct
+{
+	double	active;
+	double	idle;
+	int		count;
+	int		packets;
+
+	double	latched_active;
+	double	latched_idle;
+	int		latched_packets;
+} svstats_t;
+
+// MAX_CHALLENGES is made large to prevent a denial
+// of service attack that could cycle all of them
+// out before legitimate users connected
+#define	MAX_CHALLENGES	1024
+
+typedef struct
+{
+	netadr_t	adr;
+	int			challenge;
+	int			time;
+} challenge_t;
+
+typedef struct
+{
+	int			spawncount;			// number of servers spawned since start,
+									// used to check late spawns
+	client_t	clients[MAX_CLIENTS];
+	int			serverflags;		// episode completion information
+	
+	double		last_heartbeat;
+	int			heartbeat_sequence;
+	svstats_t	stats;
+
+	char		info[MAX_SERVERINFO_STRING];
+
+	// log messages are used so that fraglog processes can get stats
+	int			logsequence;	// the message currently being filled
+	double		logtime;		// time of last swap
+	sizebuf_t	log[2];
+	byte		log_buf[2][MAX_DATAGRAM];
+
+	challenge_t	challenges[MAX_CHALLENGES];	// to prevent invalid IPs from connecting
+} server_static_t;
+
+//=============================================================================
+
+// edict->movetype values
+#define	MOVETYPE_NONE			0		// never moves
+#define	MOVETYPE_ANGLENOCLIP	1
+#define	MOVETYPE_ANGLECLIP		2
+#define	MOVETYPE_WALK			3		// gravity
+#define	MOVETYPE_STEP			4		// gravity, special edge handling
+#define	MOVETYPE_FLY			5
+#define	MOVETYPE_TOSS			6		// gravity
+#define	MOVETYPE_PUSH			7		// no clip to world, push and crush
+#define	MOVETYPE_NOCLIP			8
+#define	MOVETYPE_FLYMISSILE		9		// extra size to monsters
+#define	MOVETYPE_BOUNCE			10
+
+// edict->solid values
+#define	SOLID_NOT				0		// no interaction with other objects
+#define	SOLID_TRIGGER			1		// touch on edge, but not blocking
+#define	SOLID_BBOX				2		// touch on edge, block
+#define	SOLID_SLIDEBOX			3		// touch on edge, but not an onground
+#define	SOLID_BSP				4		// bsp clip, touch on edge, block
+
+// edict->deadflag values
+#define	DEAD_NO					0
+#define	DEAD_DYING				1
+#define	DEAD_DEAD				2
+
+#define	DAMAGE_NO				0
+#define	DAMAGE_YES				1
+#define	DAMAGE_AIM				2
+
+// edict->flags
+#define	FL_FLY					1
+#define	FL_SWIM					2
+#define	FL_GLIMPSE				4
+#define	FL_CLIENT				8
+#define	FL_INWATER				16
+#define	FL_MONSTER				32
+#define	FL_GODMODE				64
+#define	FL_NOTARGET				128
+#define	FL_ITEM					256
+#define	FL_ONGROUND				512
+#define	FL_PARTIALGROUND		1024	// not all corners are valid
+#define	FL_WATERJUMP			2048	// player jumping out of water
+
+// entity effects
+
+//define	EF_BRIGHTFIELD			1
+//define	EF_MUZZLEFLASH 			2
+#define	EF_BRIGHTLIGHT 			4
+#define	EF_DIMLIGHT 			8
+
+
+#define	SPAWNFLAG_NOT_EASY			256
+#define	SPAWNFLAG_NOT_MEDIUM		512
+#define	SPAWNFLAG_NOT_HARD			1024
+#define	SPAWNFLAG_NOT_DEATHMATCH	2048
+
+#define	MULTICAST_ALL			0
+#define	MULTICAST_PHS			1
+#define	MULTICAST_PVS			2
+
+#define	MULTICAST_ALL_R			3
+#define	MULTICAST_PHS_R			4
+#define	MULTICAST_PVS_R			5
+
+//============================================================================
+
+extern	cvar_t	sv_mintic, sv_maxtic;
+extern	cvar_t	sv_maxspeed;
+
+extern	netadr_t	master_adr[MAX_MASTERS];	// address of the master server
+
+extern	cvar_t	spawn;
+extern	cvar_t	teamplay;
+extern	cvar_t	deathmatch;
+extern	cvar_t	fraglimit;
+extern	cvar_t	timelimit;
+
+extern	server_static_t	svs;				// persistant server info
+extern	server_t		sv;					// local server
+
+extern	client_t	*host_client;
+
+extern	edict_t		*sv_player;
+
+extern	char		localmodels[MAX_MODELS][5];	// inline model names for precache
+
+extern	char		localinfo[MAX_LOCALINFO_STRING+1];
+
+extern	int			host_hunklevel;
+extern	FILE		*sv_logfile;
+extern	FILE		*sv_fraglogfile;
+
+//===========================================================
+
+//
+// sv_main.c
+//
+void SV_Shutdown (void);
+void SV_Frame (float time);
+void SV_FinalMessage (char *message);
+void SV_DropClient (client_t *drop);
+
+int SV_CalcPing (client_t *cl);
+void SV_FullClientUpdate (client_t *client, sizebuf_t *buf);
+
+int SV_ModelIndex (char *name);
+
+qboolean SV_CheckBottom (edict_t *ent);
+qboolean SV_movestep (edict_t *ent, vec3_t move, qboolean relink);
+
+void SV_WriteClientdataToMessage (client_t *client, sizebuf_t *msg);
+
+void SV_MoveToGoal (void);
+
+void SV_SaveSpawnparms (void);
+
+void SV_Physics_Client (edict_t	*ent);
+
+void SV_ExecuteUserCommand (char *s);
+void SV_InitOperatorCommands (void);
+
+void SV_SendServerinfo (client_t *client);
+void SV_ExtractFromUserinfo (client_t *cl);
+
+
+void Master_Heartbeat (void);
+void Master_Packet (void);
+
+//
+// sv_init.c
+//
+void SV_SpawnServer (char *server);
+void SV_FlushSignon (void);
+
+
+//
+// sv_phys.c
+//
+void SV_ProgStartFrame (void);
+void SV_Physics (void);
+void SV_CheckVelocity (edict_t *ent);
+void SV_AddGravity (edict_t *ent, float scale);
+qboolean SV_RunThink (edict_t *ent);
+void SV_Physics_Toss (edict_t *ent);
+void SV_RunNewmis (void);
+void SV_Impact (edict_t *e1, edict_t *e2);
+void SV_SetMoveVars(void);
+
+//
+// sv_send.c
+//
+void SV_SendClientMessages (void);
+
+void SV_Multicast (vec3_t origin, int to);
+void SV_StartSound (edict_t *entity, int channel, char *sample, int volume,
+    float attenuation);
+void SV_ClientPrintf (client_t *cl, int level, char *fmt, ...);
+void SV_BroadcastPrintf (int level, char *fmt, ...);
+void SV_BroadcastCommand (char *fmt, ...);
+void SV_SendMessagesToAll (void);
+void SV_FindModelNumbers (void);
+
+//
+// sv_user.c
+//
+void SV_ExecuteClientMessage (client_t *cl);
+void SV_UserInit (void);
+void SV_TogglePause (const char *msg);
+
+
+//
+// svonly.c
+//
+typedef enum {RD_NONE, RD_CLIENT, RD_PACKET} redirect_t;
+void SV_BeginRedirect (redirect_t rd);
+void SV_EndRedirect (void);
+
+//
+// sv_ccmds.c
+//
+void SV_Status_f (void);
+
+//
+// sv_ents.c
+//
+void SV_WriteEntitiesToClient (client_t *client, sizebuf_t *msg);
+
+//
+// sv_nchan.c
+//
+
+void ClientReliableCheckBlock(client_t *cl, int maxsize);
+void ClientReliable_FinishWrite(client_t *cl);
+void ClientReliableWrite_Begin(client_t *cl, int c, int maxsize);
+void ClientReliableWrite_Angle(client_t *cl, float f);
+void ClientReliableWrite_Angle16(client_t *cl, float f);
+void ClientReliableWrite_Byte(client_t *cl, int c);
+void ClientReliableWrite_Char(client_t *cl, int c);
+void ClientReliableWrite_Float(client_t *cl, float f);
+void ClientReliableWrite_Coord(client_t *cl, float f);
+void ClientReliableWrite_Long(client_t *cl, int c);
+void ClientReliableWrite_Short(client_t *cl, int c);
+void ClientReliableWrite_String(client_t *cl, char *s);
+void ClientReliableWrite_SZ(client_t *cl, void *data, int len);
+
--- /dev/null
+++ b/QW/server/sv_ccmds.c
@@ -1,0 +1,900 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+
+#include "qwsvdef.h"
+
+qboolean	sv_allow_cheats;
+
+int fp_messages=4, fp_persecond=4, fp_secondsdead=10;
+char fp_msg[255] = { 0 };
+extern cvar_t cl_warncmd;
+	extern		redirect_t	sv_redirected;
+
+
+/*
+===============================================================================
+
+OPERATOR CONSOLE ONLY COMMANDS
+
+These commands can only be entered from stdin or by a remote operator datagram
+===============================================================================
+*/
+
+/*
+====================
+SV_SetMaster_f
+
+Make a master server current
+====================
+*/
+void SV_SetMaster_f (void)
+{
+	char	data[2];
+	int		i;
+
+	memset (&master_adr, 0, sizeof(master_adr));
+
+	for (i=1 ; i<Cmd_Argc() ; i++)
+	{
+		if (!strcmp(Cmd_Argv(i), "none") || !NET_StringToAdr (Cmd_Argv(i), &master_adr[i-1]))
+		{
+			Con_Printf ("Setting nomaster mode.\n");
+			return;
+		}
+		if (master_adr[i-1].port == 0)
+			master_adr[i-1].port = BigShort (27000);
+
+		Con_Printf ("Master server at %s\n", NET_AdrToString (master_adr[i-1]));
+
+		Con_Printf ("Sending a ping.\n");
+
+		data[0] = A2A_PING;
+		data[1] = 0;
+		NET_SendPacket (2, data, master_adr[i-1]);
+	}
+
+	svs.last_heartbeat = -99999;
+}
+
+
+/*
+==================
+SV_Quit_f
+==================
+*/
+void SV_Quit_f (void)
+{
+	SV_FinalMessage ("server shutdown\n");
+	Con_Printf ("Shutting down.\n");
+	SV_Shutdown ();
+	Sys_Quit ();
+}
+
+/*
+============
+SV_Logfile_f
+============
+*/
+void SV_Logfile_f (void)
+{
+	char	name[MAX_OSPATH];
+
+	if (sv_logfile)
+	{
+		Con_Printf ("File logging off.\n");
+		fclose (sv_logfile);
+		sv_logfile = NULL;
+		return;
+	}
+
+	sprintf (name, "%s/qconsole.log", com_gamedir);
+	Con_Printf ("Logging text to %s.\n", name);
+	sv_logfile = fopen (name, "w");
+	if (!sv_logfile)
+		Con_Printf ("failed.\n");
+}
+
+
+/*
+============
+SV_Fraglogfile_f
+============
+*/
+void SV_Fraglogfile_f (void)
+{
+	char	name[MAX_OSPATH];
+	int		i;
+
+	if (sv_fraglogfile)
+	{
+		Con_Printf ("Frag file logging off.\n");
+		fclose (sv_fraglogfile);
+		sv_fraglogfile = NULL;
+		return;
+	}
+
+	// find an unused name
+	for (i=0 ; i<1000 ; i++)
+	{
+		sprintf (name, "%s/frag_%i.log", com_gamedir, i);
+		sv_fraglogfile = fopen (name, "r");
+		if (!sv_fraglogfile)
+		{	// can't read it, so create this one
+			sv_fraglogfile = fopen (name, "w");
+			if (!sv_fraglogfile)
+				i=1000;	// give error
+			break;
+		}
+		fclose (sv_fraglogfile);
+	}
+	if (i==1000)
+	{
+		Con_Printf ("Can't open any logfiles.\n");
+		sv_fraglogfile = NULL;
+		return;
+	}
+
+	Con_Printf ("Logging frags to %s.\n", name);
+}
+
+
+/*
+==================
+SV_SetPlayer
+
+Sets host_client and sv_player to the player with idnum Cmd_Argv(1)
+==================
+*/
+qboolean SV_SetPlayer (void)
+{
+	client_t	*cl;
+	int			i;
+	int			idnum;
+
+	idnum = atoi(Cmd_Argv(1));
+
+	for (i=0,cl=svs.clients ; i<MAX_CLIENTS ; i++,cl++)
+	{
+		if (!cl->state)
+			continue;
+		if (cl->userid == idnum)
+		{
+			host_client = cl;
+			sv_player = host_client->edict;
+			return true;
+		}
+	}
+	Con_Printf ("Userid %i is not on the server\n", idnum);
+	return false;
+}
+
+
+/*
+==================
+SV_God_f
+
+Sets client to godmode
+==================
+*/
+void SV_God_f (void)
+{
+	if (!sv_allow_cheats)
+	{
+		Con_Printf ("You must run the server with -cheats to enable this command.\n");
+		return;
+	}
+
+	if (!SV_SetPlayer ())
+		return;
+
+	sv_player->v.flags = (int)sv_player->v.flags ^ FL_GODMODE;
+	if (!((int)sv_player->v.flags & FL_GODMODE) )
+		SV_ClientPrintf (host_client, PRINT_HIGH, "godmode OFF\n");
+	else
+		SV_ClientPrintf (host_client, PRINT_HIGH, "godmode ON\n");
+}
+
+
+void SV_Noclip_f (void)
+{
+	if (!sv_allow_cheats)
+	{
+		Con_Printf ("You must run the server with -cheats to enable this command.\n");
+		return;
+	}
+
+	if (!SV_SetPlayer ())
+		return;
+
+	if (sv_player->v.movetype != MOVETYPE_NOCLIP)
+	{
+		sv_player->v.movetype = MOVETYPE_NOCLIP;
+		SV_ClientPrintf (host_client, PRINT_HIGH, "noclip ON\n");
+	}
+	else
+	{
+		sv_player->v.movetype = MOVETYPE_WALK;
+		SV_ClientPrintf (host_client, PRINT_HIGH, "noclip OFF\n");
+	}
+}
+
+
+/*
+==================
+SV_Give_f
+==================
+*/
+void SV_Give_f (void)
+{
+	char	*t;
+	int		v;
+	
+	if (!sv_allow_cheats)
+	{
+		Con_Printf ("You must run the server with -cheats to enable this command.\n");
+		return;
+	}
+	
+	if (!SV_SetPlayer ())
+		return;
+
+	t = Cmd_Argv(2);
+	v = atoi (Cmd_Argv(3));
+	
+	switch (t[0])
+	{
+	case '2':
+	case '3':
+	case '4':
+	case '5':
+	case '6':
+	case '7':
+	case '8':
+	case '9':
+		sv_player->v.items = (int)sv_player->v.items | IT_SHOTGUN<< (t[0] - '2');
+		break;
+	
+	case 's':
+		sv_player->v.ammo_shells = v;
+		break;		
+	case 'n':
+		sv_player->v.ammo_nails = v;
+		break;		
+	case 'r':
+		sv_player->v.ammo_rockets = v;
+		break;		
+	case 'h':
+		sv_player->v.health = v;
+		break;		
+	case 'c':
+		sv_player->v.ammo_cells = v;
+		break;		
+	}
+}
+
+
+/*
+======================
+SV_Map_f
+
+handle a 
+map <mapname>
+command from the console or progs.
+======================
+*/
+void SV_Map_f (void)
+{
+	char	level[MAX_QPATH];
+	char	expanded[MAX_QPATH];
+	FILE	*f;
+
+	if (Cmd_Argc() != 2)
+	{
+		Con_Printf ("map <levelname> : continue game on a new level\n");
+		return;
+	}
+	strcpy (level, Cmd_Argv(1));
+
+#if 0
+	if (!strcmp (level, "e1m8"))
+	{	// QuakeWorld can't go to e1m8
+		SV_BroadcastPrintf (PRINT_HIGH, "can't go to low grav level in QuakeWorld...\n");
+		strcpy (level, "e1m5");
+	}
+#endif
+
+	// check to make sure the level exists
+	sprintf (expanded, "maps/%s.bsp", level);
+	COM_FOpenFile (expanded, &f);
+	if (!f)
+	{
+		Con_Printf ("Can't find %s\n", expanded);
+		return;
+	}
+	fclose (f);
+
+	SV_BroadcastCommand ("changing\n");
+	SV_SendMessagesToAll ();
+
+	SV_SpawnServer (level);
+
+	SV_BroadcastCommand ("reconnect\n");
+}
+
+
+/*
+==================
+SV_Kick_f
+
+Kick a user off of the server
+==================
+*/
+void SV_Kick_f (void)
+{
+	int			i;
+	client_t	*cl;
+	int			uid;
+
+	uid = atoi(Cmd_Argv(1));
+	
+	for (i = 0, cl = svs.clients; i < MAX_CLIENTS; i++, cl++)
+	{
+		if (!cl->state)
+			continue;
+		if (cl->userid == uid)
+		{
+			SV_BroadcastPrintf (PRINT_HIGH, "%s was kicked\n", cl->name);
+			// print directly, because the dropped client won't get the
+			// SV_BroadcastPrintf message
+			SV_ClientPrintf (cl, PRINT_HIGH, "You were kicked from the game\n");
+			SV_DropClient (cl); 
+			return;
+		}
+	}
+
+	Con_Printf ("Couldn't find user number %i\n", uid);
+}
+
+
+/*
+================
+SV_Status_f
+================
+*/
+void SV_Status_f (void)
+{
+	int			i, j, l;
+	client_t	*cl;
+	float		cpu, avg, pak;
+	char		*s;
+
+
+	cpu = (svs.stats.latched_active+svs.stats.latched_idle);
+	if (cpu)
+		cpu = 100*svs.stats.latched_active/cpu;
+	avg = 1000*svs.stats.latched_active / STATFRAMES;
+	pak = (float)svs.stats.latched_packets/ STATFRAMES;
+
+	Con_Printf ("net address      : %s\n",NET_AdrToString (net_local_adr));
+	Con_Printf ("cpu utilization  : %3i%%\n",(int)cpu);
+	Con_Printf ("avg response time: %i ms\n",(int)avg);
+	Con_Printf ("packets/frame    : %5.2f (%d)\n", pak, num_prstr);
+	
+// min fps lat drp
+	if (sv_redirected != RD_NONE) {
+		// most remote clients are 40 columns
+		//           0123456789012345678901234567890123456789
+		Con_Printf ("name               userid frags\n");
+        Con_Printf ("  address          rate ping drop\n");
+		Con_Printf ("  ---------------- ---- ---- -----\n");
+		for (i=0,cl=svs.clients ; i<MAX_CLIENTS ; i++,cl++)
+		{
+			if (!cl->state)
+				continue;
+
+			Con_Printf ("%-16.16s  ", cl->name);
+
+			Con_Printf ("%6i %5i", cl->userid, (int)cl->edict->v.frags);
+			if (cl->spectator)
+				Con_Printf(" (s)\n");
+			else			
+				Con_Printf("\n");
+
+			s = NET_BaseAdrToString ( cl->netchan.remote_address);
+			Con_Printf ("  %-16.16s", s);
+			if (cl->state == cs_connected)
+			{
+				Con_Printf ("CONNECTING\n");
+				continue;
+			}
+			if (cl->state == cs_zombie)
+			{
+				Con_Printf ("ZOMBIE\n");
+				continue;
+			}
+			Con_Printf ("%4i %4i %5.2f\n"
+				, (int)(1000*cl->netchan.frame_rate)
+				, (int)SV_CalcPing (cl)
+				, 100.0*cl->netchan.drop_count / cl->netchan.incoming_sequence);
+		}
+	} else {
+		Con_Printf ("frags userid address         name            rate ping drop  qport\n");
+		Con_Printf ("----- ------ --------------- --------------- ---- ---- ----- -----\n");
+		for (i=0,cl=svs.clients ; i<MAX_CLIENTS ; i++,cl++)
+		{
+			if (!cl->state)
+				continue;
+			Con_Printf ("%5i %6i ", (int)cl->edict->v.frags,  cl->userid);
+
+			s = NET_BaseAdrToString ( cl->netchan.remote_address);
+			Con_Printf ("%s", s);
+			l = 16 - strlen(s);
+			for (j=0 ; j<l ; j++)
+				Con_Printf (" ");
+			
+			Con_Printf ("%s", cl->name);
+			l = 16 - strlen(cl->name);
+			for (j=0 ; j<l ; j++)
+				Con_Printf (" ");
+			if (cl->state == cs_connected)
+			{
+				Con_Printf ("CONNECTING\n");
+				continue;
+			}
+			if (cl->state == cs_zombie)
+			{
+				Con_Printf ("ZOMBIE\n");
+				continue;
+			}
+			Con_Printf ("%4i %4i %3.1f %4i"
+				, (int)(1000*cl->netchan.frame_rate)
+				, (int)SV_CalcPing (cl)
+				, 100.0*cl->netchan.drop_count / cl->netchan.incoming_sequence
+				, cl->netchan.qport);
+			if (cl->spectator)
+				Con_Printf(" (s)\n");
+			else			
+				Con_Printf("\n");
+
+				
+		}
+	}
+	Con_Printf ("\n");
+}
+
+/*
+==================
+SV_ConSay_f
+==================
+*/
+void SV_ConSay_f(void)
+{
+	client_t *client;
+	int		j;
+	char	*p;
+	char	text[1024];
+
+	if (Cmd_Argc () < 2)
+		return;
+
+	Q_strcpy (text, "console: ");
+	p = Cmd_Args();
+
+	if (*p == '"')
+	{
+		p++;
+		p[Q_strlen(p)-1] = 0;
+	}
+
+	Q_strcat(text, p);
+
+	for (j = 0, client = svs.clients; j < MAX_CLIENTS; j++, client++)
+	{
+		if (client->state != cs_spawned)
+			continue;
+		SV_ClientPrintf(client, PRINT_CHAT, "%s\n", text);
+	}
+}
+
+
+/*
+==================
+SV_Heartbeat_f
+==================
+*/
+void SV_Heartbeat_f (void)
+{
+	svs.last_heartbeat = -9999;
+}
+
+void SV_SendServerInfoChange(char *key, char *value)
+{
+	if (!sv.state)
+		return;
+
+	MSG_WriteByte (&sv.reliable_datagram, svc_serverinfo);
+	MSG_WriteString (&sv.reliable_datagram, key);
+	MSG_WriteString (&sv.reliable_datagram, value);
+}
+
+/*
+===========
+SV_Serverinfo_f
+
+  Examine or change the serverinfo string
+===========
+*/
+char *CopyString(char *s);
+void SV_Serverinfo_f (void)
+{
+	cvar_t	*var;
+
+	if (Cmd_Argc() == 1)
+	{
+		Con_Printf ("Server info settings:\n");
+		Info_Print (svs.info);
+		return;
+	}
+
+	if (Cmd_Argc() != 3)
+	{
+		Con_Printf ("usage: serverinfo [ <key> <value> ]\n");
+		return;
+	}
+
+	if (Cmd_Argv(1)[0] == '*')
+	{
+		Con_Printf ("Star variables cannot be changed.\n");
+		return;
+	}
+	Info_SetValueForKey (svs.info, Cmd_Argv(1), Cmd_Argv(2), MAX_SERVERINFO_STRING);
+
+	// if this is a cvar, change it too	
+	var = Cvar_FindVar (Cmd_Argv(1));
+	if (var)
+	{
+		Z_Free (var->string);	// free the old value string	
+		var->string = CopyString (Cmd_Argv(2));
+		var->value = Q_atof (var->string);
+	}
+
+	SV_SendServerInfoChange(Cmd_Argv(1), Cmd_Argv(2));
+}
+
+
+/*
+===========
+SV_Serverinfo_f
+
+  Examine or change the serverinfo string
+===========
+*/
+char *CopyString(char *s);
+void SV_Localinfo_f (void)
+{
+	if (Cmd_Argc() == 1)
+	{
+		Con_Printf ("Local info settings:\n");
+		Info_Print (localinfo);
+		return;
+	}
+
+	if (Cmd_Argc() != 3)
+	{
+		Con_Printf ("usage: localinfo [ <key> <value> ]\n");
+		return;
+	}
+
+	if (Cmd_Argv(1)[0] == '*')
+	{
+		Con_Printf ("Star variables cannot be changed.\n");
+		return;
+	}
+	Info_SetValueForKey (localinfo, Cmd_Argv(1), Cmd_Argv(2), MAX_LOCALINFO_STRING);
+}
+
+
+/*
+===========
+SV_User_f
+
+Examine a users info strings
+===========
+*/
+void SV_User_f (void)
+{
+	if (Cmd_Argc() != 2)
+	{
+		Con_Printf ("Usage: info <userid>\n");
+		return;
+	}
+
+	if (!SV_SetPlayer ())
+		return;
+
+	Info_Print (host_client->userinfo);
+}
+
+/*
+================
+SV_Gamedir
+
+Sets the fake *gamedir to a different directory.
+================
+*/
+void SV_Gamedir (void)
+{
+	char			*dir;
+
+	if (Cmd_Argc() == 1)
+	{
+		Con_Printf ("Current *gamedir: %s\n", Info_ValueForKey (svs.info, "*gamedir"));
+		return;
+	}
+
+	if (Cmd_Argc() != 2)
+	{
+		Con_Printf ("Usage: sv_gamedir <newgamedir>\n");
+		return;
+	}
+
+	dir = Cmd_Argv(1);
+
+	if (strstr(dir, "..") || strstr(dir, "/")
+		|| strstr(dir, "\\") || strstr(dir, ":") )
+	{
+		Con_Printf ("*Gamedir should be a single filename, not a path\n");
+		return;
+	}
+
+	Info_SetValueForStarKey (svs.info, "*gamedir", dir, MAX_SERVERINFO_STRING);
+}
+
+/*
+================
+SV_Floodport_f
+
+Sets the gamedir and path to a different directory.
+================
+*/
+
+void SV_Floodprot_f (void)
+{
+	int arg1, arg2, arg3;
+	
+	if (Cmd_Argc() == 1)
+	{
+		if (fp_messages) {
+			Con_Printf ("Current floodprot settings: \nAfter %d msgs per %d seconds, silence for %d seconds\n", 
+				fp_messages, fp_persecond, fp_secondsdead);
+			return;
+		} else
+			Con_Printf ("No floodprots enabled.\n");
+	}
+
+	if (Cmd_Argc() != 4)
+	{
+		Con_Printf ("Usage: floodprot <# of messages> <per # of seconds> <seconds to silence>\n");
+		Con_Printf ("Use floodprotmsg to set a custom message to say to the flooder.\n");
+		return;
+	}
+
+	arg1 = atoi(Cmd_Argv(1));
+	arg2 = atoi(Cmd_Argv(2));
+	arg3 = atoi(Cmd_Argv(3));
+
+	if (arg1<=0 || arg2 <= 0 || arg3<=0) {
+		Con_Printf ("All values must be positive numbers\n");
+		return;
+	}
+	
+	if (arg1 > 10) {
+		Con_Printf ("Can only track up to 10 messages.\n");
+		return;
+	}
+
+	fp_messages	= arg1;
+	fp_persecond = arg2;
+	fp_secondsdead = arg3;
+}
+
+void SV_Floodprotmsg_f (void)
+{
+	if (Cmd_Argc() == 1) {
+		Con_Printf("Current msg: %s\n", fp_msg);
+		return;
+	} else if (Cmd_Argc() != 2) {
+		Con_Printf("Usage: floodprotmsg \"<message>\"\n");
+		return;
+	}
+	sprintf(fp_msg, "%s", Cmd_Argv(1));
+}
+  
+/*
+================
+SV_Gamedir_f
+
+Sets the gamedir and path to a different directory.
+================
+*/
+char	gamedirfile[MAX_OSPATH];
+void SV_Gamedir_f (void)
+{
+	char			*dir;
+
+	if (Cmd_Argc() == 1)
+	{
+		Con_Printf ("Current gamedir: %s\n", com_gamedir);
+		return;
+	}
+
+	if (Cmd_Argc() != 2)
+	{
+		Con_Printf ("Usage: gamedir <newdir>\n");
+		return;
+	}
+
+	dir = Cmd_Argv(1);
+
+	if (strstr(dir, "..") || strstr(dir, "/")
+		|| strstr(dir, "\\") || strstr(dir, ":") )
+	{
+		Con_Printf ("Gamedir should be a single filename, not a path\n");
+		return;
+	}
+
+	COM_Gamedir (dir);
+	Info_SetValueForStarKey (svs.info, "*gamedir", dir, MAX_SERVERINFO_STRING);
+}
+
+/*
+================
+SV_Snap
+================
+*/
+void SV_Snap (int uid)
+{
+	client_t *cl;
+	char		pcxname[80]; 
+	char		checkname[MAX_OSPATH];
+	int			i;
+
+	for (i = 0, cl = svs.clients; i < MAX_CLIENTS; i++, cl++)
+	{
+		if (!cl->state)
+			continue;
+		if (cl->userid == uid)
+			break;
+	}
+	if (i >= MAX_CLIENTS) {
+		Con_Printf ("userid not found\n");
+		return;
+	}
+
+	sprintf(pcxname, "%d-00.pcx", uid);
+
+	sprintf(checkname, "%s/snap", gamedirfile);
+	Sys_mkdir(gamedirfile);
+	Sys_mkdir(checkname);
+		
+	for (i=0 ; i<=99 ; i++) 
+	{ 
+		pcxname[strlen(pcxname) - 6] = i/10 + '0'; 
+		pcxname[strlen(pcxname) - 5] = i%10 + '0'; 
+		sprintf (checkname, "%s/snap/%s", gamedirfile, pcxname);
+		if (Sys_FileTime(checkname) == -1)
+			break;	// file doesn't exist
+	} 
+	if (i==100) 
+	{
+		Con_Printf ("Snap: Couldn't create a file, clean some out.\n"); 
+		return;
+	}
+	strcpy(cl->uploadfn, checkname);
+
+	memcpy(&cl->snap_from, &net_from, sizeof(net_from));
+	if (sv_redirected != RD_NONE)
+		cl->remote_snap = true;
+	else
+		cl->remote_snap = false;
+
+	ClientReliableWrite_Begin (cl, svc_stufftext, 24);
+	ClientReliableWrite_String (cl, "cmd snap");
+	Con_Printf ("Requesting snap from user %d...\n", uid);
+}
+
+/*
+================
+SV_Snap_f
+================
+*/
+void SV_Snap_f (void)
+{
+	int			uid;
+
+	if (Cmd_Argc() != 2)
+	{
+		Con_Printf ("Usage:  snap <userid>\n");
+		return;
+	}
+
+	uid = atoi(Cmd_Argv(1));
+
+	SV_Snap(uid);
+}
+
+/*
+================
+SV_Snap
+================
+*/
+void SV_SnapAll_f (void)
+{
+	client_t *cl;
+	int			i;
+
+	for (i = 0, cl = svs.clients; i < MAX_CLIENTS; i++, cl++)
+	{
+		if (cl->state < cs_connected || cl->spectator)
+			continue;
+		SV_Snap(cl->userid);
+	}
+}
+
+/*
+==================
+SV_InitOperatorCommands
+==================
+*/
+void SV_InitOperatorCommands (void)
+{
+	if (COM_CheckParm ("-cheats"))
+	{
+		sv_allow_cheats = true;
+		Info_SetValueForStarKey (svs.info, "*cheats", "ON", MAX_SERVERINFO_STRING);
+	}
+
+	Cmd_AddCommand ("logfile", SV_Logfile_f);
+	Cmd_AddCommand ("fraglogfile", SV_Fraglogfile_f);
+
+	Cmd_AddCommand ("snap", SV_Snap_f);
+	Cmd_AddCommand ("snapall", SV_SnapAll_f);
+	Cmd_AddCommand ("kick", SV_Kick_f);
+	Cmd_AddCommand ("status", SV_Status_f);
+
+	Cmd_AddCommand ("map", SV_Map_f);
+	Cmd_AddCommand ("setmaster", SV_SetMaster_f);
+
+	Cmd_AddCommand ("say", SV_ConSay_f);
+	Cmd_AddCommand ("heartbeat", SV_Heartbeat_f);
+	Cmd_AddCommand ("quit", SV_Quit_f);
+	Cmd_AddCommand ("god", SV_God_f);
+	Cmd_AddCommand ("give", SV_Give_f);
+	Cmd_AddCommand ("noclip", SV_Noclip_f);
+	Cmd_AddCommand ("serverinfo", SV_Serverinfo_f);
+	Cmd_AddCommand ("localinfo", SV_Localinfo_f);
+	Cmd_AddCommand ("user", SV_User_f);
+	Cmd_AddCommand ("gamedir", SV_Gamedir_f);
+	Cmd_AddCommand ("sv_gamedir", SV_Gamedir);
+	Cmd_AddCommand ("floodprot", SV_Floodprot_f);
+	Cmd_AddCommand ("floodprotmsg", SV_Floodprotmsg_f);
+
+	cl_warncmd.value = 1;
+}
--- /dev/null
+++ b/QW/server/sv_ents.c
@@ -1,0 +1,517 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+
+#include "qwsvdef.h"
+
+/*
+=============================================================================
+
+The PVS must include a small area around the client to allow head bobbing
+or other small motion on the client side.  Otherwise, a bob might cause an
+entity that should be visible to not show up, especially when the bob
+crosses a waterline.
+
+=============================================================================
+*/
+
+int		fatbytes;
+byte	fatpvs[MAX_MAP_LEAFS/8];
+
+void SV_AddToFatPVS (vec3_t org, mnode_t *node)
+{
+	int		i;
+	byte	*pvs;
+	mplane_t	*plane;
+	float	d;
+
+	while (1)
+	{
+	// if this is a leaf, accumulate the pvs bits
+		if (node->contents < 0)
+		{
+			if (node->contents != CONTENTS_SOLID)
+			{
+				pvs = Mod_LeafPVS ( (mleaf_t *)node, sv.worldmodel);
+				for (i=0 ; i<fatbytes ; i++)
+					fatpvs[i] |= pvs[i];
+			}
+			return;
+		}
+	
+		plane = node->plane;
+		d = DotProduct (org, plane->normal) - plane->dist;
+		if (d > 8)
+			node = node->children[0];
+		else if (d < -8)
+			node = node->children[1];
+		else
+		{	// go down both
+			SV_AddToFatPVS (org, node->children[0]);
+			node = node->children[1];
+		}
+	}
+}
+
+/*
+=============
+SV_FatPVS
+
+Calculates a PVS that is the inclusive or of all leafs within 8 pixels of the
+given point.
+=============
+*/
+byte *SV_FatPVS (vec3_t org)
+{
+	fatbytes = (sv.worldmodel->numleafs+31)>>3;
+	Q_memset (fatpvs, 0, fatbytes);
+	SV_AddToFatPVS (org, sv.worldmodel->nodes);
+	return fatpvs;
+}
+
+//=============================================================================
+
+// because there can be a lot of nails, there is a special
+// network protocol for them
+#define	MAX_NAILS	32
+edict_t	*nails[MAX_NAILS];
+int		numnails;
+
+extern	int	sv_nailmodel, sv_supernailmodel, sv_playermodel;
+
+qboolean SV_AddNailUpdate (edict_t *ent)
+{
+	if (ent->v.modelindex != sv_nailmodel
+		&& ent->v.modelindex != sv_supernailmodel)
+		return false;
+	if (numnails == MAX_NAILS)
+		return true;
+	nails[numnails] = ent;
+	numnails++;
+	return true;
+}
+
+void SV_EmitNailUpdate (sizebuf_t *msg)
+{
+	byte	bits[6];	// [48 bits] xyzpy 12 12 12 4 8 
+	int		n, i;
+	edict_t	*ent;
+	int		x, y, z, p, yaw;
+
+	if (!numnails)
+		return;
+
+	MSG_WriteByte (msg, svc_nails);
+	MSG_WriteByte (msg, numnails);
+
+	for (n=0 ; n<numnails ; n++)
+	{
+		ent = nails[n];
+		x = (int)(ent->v.origin[0]+4096)>>1;
+		y = (int)(ent->v.origin[1]+4096)>>1;
+		z = (int)(ent->v.origin[2]+4096)>>1;
+		p = (int)(16*ent->v.angles[0]/360)&15;
+		yaw = (int)(256*ent->v.angles[1]/360)&255;
+
+		bits[0] = x;
+		bits[1] = (x>>8) | (y<<4);
+		bits[2] = (y>>4);
+		bits[3] = z;
+		bits[4] = (z>>8) | (p<<4);
+		bits[5] = yaw;
+
+		for (i=0 ; i<6 ; i++)
+			MSG_WriteByte (msg, bits[i]);
+	}
+}
+
+//=============================================================================
+
+
+/*
+==================
+SV_WriteDelta
+
+Writes part of a packetentities message.
+Can delta from either a baseline or a previous packet_entity
+==================
+*/
+void SV_WriteDelta (entity_state_t *from, entity_state_t *to, sizebuf_t *msg, qboolean force)
+{
+	int		bits;
+	int		i;
+	float	miss;
+
+// send an update
+	bits = 0;
+	
+	for (i=0 ; i<3 ; i++)
+	{
+		miss = to->origin[i] - from->origin[i];
+		if ( miss < -0.1 || miss > 0.1 )
+			bits |= U_ORIGIN1<<i;
+	}
+
+	if ( to->angles[0] != from->angles[0] )
+		bits |= U_ANGLE1;
+		
+	if ( to->angles[1] != from->angles[1] )
+		bits |= U_ANGLE2;
+		
+	if ( to->angles[2] != from->angles[2] )
+		bits |= U_ANGLE3;
+		
+	if ( to->colormap != from->colormap )
+		bits |= U_COLORMAP;
+		
+	if ( to->skinnum != from->skinnum )
+		bits |= U_SKIN;
+		
+	if ( to->frame != from->frame )
+		bits |= U_FRAME;
+	
+	if ( to->effects != from->effects )
+		bits |= U_EFFECTS;
+	
+	if ( to->modelindex != from->modelindex )
+		bits |= U_MODEL;
+
+	if (bits & 511)
+		bits |= U_MOREBITS;
+
+	if (to->flags & U_SOLID)
+		bits |= U_SOLID;
+
+	//
+	// write the message
+	//
+	if (!to->number)
+		SV_Error ("Unset entity number");
+	if (to->number >= 512)
+		SV_Error ("Entity number >= 512");
+
+	if (!bits && !force)
+		return;		// nothing to send!
+	i = to->number | (bits&~511);
+	if (i & U_REMOVE)
+		Sys_Error ("U_REMOVE");
+	MSG_WriteShort (msg, i);
+	
+	if (bits & U_MOREBITS)
+		MSG_WriteByte (msg, bits&255);
+	if (bits & U_MODEL)
+		MSG_WriteByte (msg,	to->modelindex);
+	if (bits & U_FRAME)
+		MSG_WriteByte (msg, to->frame);
+	if (bits & U_COLORMAP)
+		MSG_WriteByte (msg, to->colormap);
+	if (bits & U_SKIN)
+		MSG_WriteByte (msg, to->skinnum);
+	if (bits & U_EFFECTS)
+		MSG_WriteByte (msg, to->effects);
+	if (bits & U_ORIGIN1)
+		MSG_WriteCoord (msg, to->origin[0]);		
+	if (bits & U_ANGLE1)
+		MSG_WriteAngle(msg, to->angles[0]);
+	if (bits & U_ORIGIN2)
+		MSG_WriteCoord (msg, to->origin[1]);
+	if (bits & U_ANGLE2)
+		MSG_WriteAngle(msg, to->angles[1]);
+	if (bits & U_ORIGIN3)
+		MSG_WriteCoord (msg, to->origin[2]);
+	if (bits & U_ANGLE3)
+		MSG_WriteAngle(msg, to->angles[2]);
+}
+
+/*
+=============
+SV_EmitPacketEntities
+
+Writes a delta update of a packet_entities_t to the message.
+
+=============
+*/
+void SV_EmitPacketEntities (client_t *client, packet_entities_t *to, sizebuf_t *msg)
+{
+	edict_t	*ent;
+	client_frame_t	*fromframe;
+	packet_entities_t *from;
+	int		oldindex, newindex;
+	int		oldnum, newnum;
+	int		oldmax;
+
+	// this is the frame that we are going to delta update from
+	if (client->delta_sequence != -1)
+	{
+		fromframe = &client->frames[client->delta_sequence & UPDATE_MASK];
+		from = &fromframe->entities;
+		oldmax = from->num_entities;
+
+		MSG_WriteByte (msg, svc_deltapacketentities);
+		MSG_WriteByte (msg, client->delta_sequence);
+	}
+	else
+	{
+		oldmax = 0;	// no delta update
+		from = NULL;
+
+		MSG_WriteByte (msg, svc_packetentities);
+	}
+
+	newindex = 0;
+	oldindex = 0;
+//Con_Printf ("---%i to %i ----\n", client->delta_sequence & UPDATE_MASK
+//			, client->netchan.outgoing_sequence & UPDATE_MASK);
+	while (newindex < to->num_entities || oldindex < oldmax)
+	{
+		newnum = newindex >= to->num_entities ? 9999 : to->entities[newindex].number;
+		oldnum = oldindex >= oldmax ? 9999 : from->entities[oldindex].number;
+
+		if (newnum == oldnum)
+		{	// delta update from old position
+//Con_Printf ("delta %i\n", newnum);
+			SV_WriteDelta (&from->entities[oldindex], &to->entities[newindex], msg, false);
+			oldindex++;
+			newindex++;
+			continue;
+		}
+
+		if (newnum < oldnum)
+		{	// this is a new entity, send it from the baseline
+			ent = EDICT_NUM(newnum);
+//Con_Printf ("baseline %i\n", newnum);
+			SV_WriteDelta (&ent->baseline, &to->entities[newindex], msg, true);
+			newindex++;
+			continue;
+		}
+
+		if (newnum > oldnum)
+		{	// the old entity isn't present in the new message
+//Con_Printf ("remove %i\n", oldnum);
+			MSG_WriteShort (msg, oldnum | U_REMOVE);
+			oldindex++;
+			continue;
+		}
+	}
+
+	MSG_WriteShort (msg, 0);	// end of packetentities
+}
+
+/*
+=============
+SV_WritePlayersToClient
+
+=============
+*/
+void SV_WritePlayersToClient (client_t *client, edict_t *clent, byte *pvs, sizebuf_t *msg)
+{
+	int			i, j;
+	client_t	*cl;
+	edict_t		*ent;
+	int			msec;
+	usercmd_t	cmd;
+	int			pflags;
+
+	for (j=0,cl=svs.clients ; j<MAX_CLIENTS ; j++,cl++)
+	{
+		if (cl->state != cs_spawned)
+			continue;
+
+		ent = cl->edict;
+
+		// ZOID visibility tracking
+		if (ent != clent &&
+			!(client->spec_track && client->spec_track - 1 == j)) 
+		{
+			if (cl->spectator)
+				continue;
+
+			// ignore if not touching a PV leaf
+			for (i=0 ; i < ent->num_leafs ; i++)
+				if (pvs[ent->leafnums[i] >> 3] & (1 << (ent->leafnums[i]&7) ))
+					break;
+			if (i == ent->num_leafs)
+				continue;		// not visible
+		}
+		
+		pflags = PF_MSEC | PF_COMMAND;
+		
+		if (ent->v.modelindex != sv_playermodel)
+			pflags |= PF_MODEL;
+		for (i=0 ; i<3 ; i++)
+			if (ent->v.velocity[i])
+				pflags |= PF_VELOCITY1<<i;
+		if (ent->v.effects)
+			pflags |= PF_EFFECTS;
+		if (ent->v.skin)
+			pflags |= PF_SKINNUM;
+		if (ent->v.health <= 0)
+			pflags |= PF_DEAD;
+		if (ent->v.mins[2] != -24)
+			pflags |= PF_GIB;
+
+		if (cl->spectator)
+		{	// only sent origin and velocity to spectators
+			pflags &= PF_VELOCITY1 | PF_VELOCITY2 | PF_VELOCITY3;
+		}
+		else if (ent == clent)
+		{	// don't send a lot of data on personal entity
+			pflags &= ~(PF_MSEC|PF_COMMAND);
+			if (ent->v.weaponframe)
+				pflags |= PF_WEAPONFRAME;
+		}
+
+		if (client->spec_track && client->spec_track - 1 == j &&
+			ent->v.weaponframe) 
+			pflags |= PF_WEAPONFRAME;
+
+		MSG_WriteByte (msg, svc_playerinfo);
+		MSG_WriteByte (msg, j);
+		MSG_WriteShort (msg, pflags);
+
+		for (i=0 ; i<3 ; i++)
+			MSG_WriteCoord (msg, ent->v.origin[i]);
+		
+		MSG_WriteByte (msg, ent->v.frame);
+
+		if (pflags & PF_MSEC)
+		{
+			msec = 1000*(sv.time - cl->localtime);
+			if (msec > 255)
+				msec = 255;
+			MSG_WriteByte (msg, msec);
+		}
+		
+		if (pflags & PF_COMMAND)
+		{
+			cmd = cl->lastcmd;
+
+			if (ent->v.health <= 0)
+			{	// don't show the corpse looking around...
+				cmd.angles[0] = 0;
+				cmd.angles[1] = ent->v.angles[1];
+				cmd.angles[0] = 0;
+			}
+
+			cmd.buttons = 0;	// never send buttons
+			cmd.impulse = 0;	// never send impulses
+
+			MSG_WriteDeltaUsercmd (msg, &nullcmd, &cmd);
+		}
+
+		for (i=0 ; i<3 ; i++)
+			if (pflags & (PF_VELOCITY1<<i) )
+				MSG_WriteShort (msg, ent->v.velocity[i]);
+
+		if (pflags & PF_MODEL)
+			MSG_WriteByte (msg, ent->v.modelindex);
+
+		if (pflags & PF_SKINNUM)
+			MSG_WriteByte (msg, ent->v.skin);
+
+		if (pflags & PF_EFFECTS)
+			MSG_WriteByte (msg, ent->v.effects);
+
+		if (pflags & PF_WEAPONFRAME)
+			MSG_WriteByte (msg, ent->v.weaponframe);
+	}
+}
+
+
+/*
+=============
+SV_WriteEntitiesToClient
+
+Encodes the current state of the world as
+a svc_packetentities messages and possibly
+a svc_nails message and
+svc_playerinfo messages
+=============
+*/
+void SV_WriteEntitiesToClient (client_t *client, sizebuf_t *msg)
+{
+	int		e, i;
+	byte	*pvs;
+	vec3_t	org;
+	edict_t	*ent;
+	packet_entities_t	*pack;
+	edict_t	*clent;
+	client_frame_t	*frame;
+	entity_state_t	*state;
+
+	// this is the frame we are creating
+	frame = &client->frames[client->netchan.incoming_sequence & UPDATE_MASK];
+
+	// find the client's PVS
+	clent = client->edict;
+	VectorAdd (clent->v.origin, clent->v.view_ofs, org);
+	pvs = SV_FatPVS (org);
+
+	// send over the players in the PVS
+	SV_WritePlayersToClient (client, clent, pvs, msg);
+	
+	// put other visible entities into either a packet_entities or a nails message
+	pack = &frame->entities;
+	pack->num_entities = 0;
+
+	numnails = 0;
+
+	for (e=MAX_CLIENTS+1, ent=EDICT_NUM(e) ; e<sv.num_edicts ; e++, ent = NEXT_EDICT(ent))
+	{
+		// ignore ents without visible models
+		if (!ent->v.modelindex || !*PR_GetString(ent->v.model))
+			continue;
+
+		// ignore if not touching a PV leaf
+		for (i=0 ; i < ent->num_leafs ; i++)
+			if (pvs[ent->leafnums[i] >> 3] & (1 << (ent->leafnums[i]&7) ))
+				break;
+			
+		if (i == ent->num_leafs)
+			continue;		// not visible
+
+		if (SV_AddNailUpdate (ent))
+			continue;	// added to the special update list
+
+		// add to the packetentities
+		if (pack->num_entities == MAX_PACKET_ENTITIES)
+			continue;	// all full
+
+		state = &pack->entities[pack->num_entities];
+		pack->num_entities++;
+
+		state->number = e;
+		state->flags = 0;
+		VectorCopy (ent->v.origin, state->origin);
+		VectorCopy (ent->v.angles, state->angles);
+		state->modelindex = ent->v.modelindex;
+		state->frame = ent->v.frame;
+		state->colormap = ent->v.colormap;
+		state->skinnum = ent->v.skin;
+		state->effects = ent->v.effects;
+	}
+
+	// encode the packet entities as a delta from the
+	// last packetentities acknowledged by the client
+
+	SV_EmitPacketEntities (client, pack, msg);
+
+	// now add the specialized nail update
+	SV_EmitNailUpdate (msg);
+}
--- /dev/null
+++ b/QW/server/sv_init.c
@@ -1,0 +1,411 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+
+#include "qwsvdef.h"
+
+server_static_t	svs;				// persistant server info
+server_t		sv;					// local server
+
+char	localmodels[MAX_MODELS][5];	// inline model names for precache
+
+char localinfo[MAX_LOCALINFO_STRING+1]; // local game info
+
+/*
+================
+SV_ModelIndex
+
+================
+*/
+int SV_ModelIndex (char *name)
+{
+	int		i;
+	
+	if (!name || !name[0])
+		return 0;
+
+	for (i=0 ; i<MAX_MODELS && sv.model_precache[i] ; i++)
+		if (!strcmp(sv.model_precache[i], name))
+			return i;
+	if (i==MAX_MODELS || !sv.model_precache[i])
+		SV_Error ("SV_ModelIndex: model %s not precached", name);
+	return i;
+}
+
+/*
+================
+SV_FlushSignon
+
+Moves to the next signon buffer if needed
+================
+*/
+void SV_FlushSignon (void)
+{
+	if (sv.signon.cursize < sv.signon.maxsize - 512)
+		return;
+
+	if (sv.num_signon_buffers == MAX_SIGNON_BUFFERS-1)
+		SV_Error ("sv.num_signon_buffers == MAX_SIGNON_BUFFERS-1");
+
+	sv.signon_buffer_size[sv.num_signon_buffers-1] = sv.signon.cursize;
+	sv.signon.data = sv.signon_buffers[sv.num_signon_buffers];
+	sv.num_signon_buffers++;
+	sv.signon.cursize = 0;
+}
+
+/*
+================
+SV_CreateBaseline
+
+Entity baselines are used to compress the update messages
+to the clients -- only the fields that differ from the
+baseline will be transmitted
+================
+*/
+void SV_CreateBaseline (void)
+{
+	int			i;
+	edict_t			*svent;
+	int				entnum;	
+		
+	for (entnum = 0; entnum < sv.num_edicts ; entnum++)
+	{
+		svent = EDICT_NUM(entnum);
+		if (svent->free)
+			continue;
+		// create baselines for all player slots,
+		// and any other edict that has a visible model
+		if (entnum > MAX_CLIENTS && !svent->v.modelindex)
+			continue;
+
+	//
+	// create entity baseline
+	//
+		VectorCopy (svent->v.origin, svent->baseline.origin);
+		VectorCopy (svent->v.angles, svent->baseline.angles);
+		svent->baseline.frame = svent->v.frame;
+		svent->baseline.skinnum = svent->v.skin;
+		if (entnum > 0 && entnum <= MAX_CLIENTS)
+		{
+			svent->baseline.colormap = entnum;
+			svent->baseline.modelindex = SV_ModelIndex("progs/player.mdl");
+		}
+		else
+		{
+			svent->baseline.colormap = 0;
+			svent->baseline.modelindex =
+				SV_ModelIndex(PR_GetString(svent->v.model));
+		}
+
+		//
+		// flush the signon message out to a seperate buffer if
+		// nearly full
+		//
+		SV_FlushSignon ();
+
+		//
+		// add to the message
+		//
+		MSG_WriteByte (&sv.signon,svc_spawnbaseline);		
+		MSG_WriteShort (&sv.signon,entnum);
+
+		MSG_WriteByte (&sv.signon, svent->baseline.modelindex);
+		MSG_WriteByte (&sv.signon, svent->baseline.frame);
+		MSG_WriteByte (&sv.signon, svent->baseline.colormap);
+		MSG_WriteByte (&sv.signon, svent->baseline.skinnum);
+		for (i=0 ; i<3 ; i++)
+		{
+			MSG_WriteCoord(&sv.signon, svent->baseline.origin[i]);
+			MSG_WriteAngle(&sv.signon, svent->baseline.angles[i]);
+		}
+	}
+}
+
+
+/*
+================
+SV_SaveSpawnparms
+
+Grabs the current state of the progs serverinfo flags 
+and each client for saving across the
+transition to another level
+================
+*/
+void SV_SaveSpawnparms (void)
+{
+	int		i, j;
+
+	if (!sv.state)
+		return;		// no progs loaded yet
+
+	// serverflags is the only game related thing maintained
+	svs.serverflags = pr_global_struct->serverflags;
+
+	for (i=0, host_client = svs.clients ; i<MAX_CLIENTS ; i++, host_client++)
+	{
+		if (host_client->state != cs_spawned)
+			continue;
+
+		// needs to reconnect
+		host_client->state = cs_connected;
+
+		// call the progs to get default spawn parms for the new client
+		pr_global_struct->self = EDICT_TO_PROG(host_client->edict);
+		PR_ExecuteProgram (pr_global_struct->SetChangeParms);
+		for (j=0 ; j<NUM_SPAWN_PARMS ; j++)
+			host_client->spawn_parms[j] = (&pr_global_struct->parm1)[j];
+	}
+}
+
+/*
+================
+SV_CalcPHS
+
+Expands the PVS and calculates the PHS
+(Potentially Hearable Set)
+================
+*/
+void SV_CalcPHS (void)
+{
+	int		rowbytes, rowwords;
+	int		i, j, k, l, index, num;
+	int		bitbyte;
+	unsigned	*dest, *src;
+	byte	*scan;
+	int		count, vcount;
+
+	Con_Printf ("Building PHS...\n");
+
+	num = sv.worldmodel->numleafs;
+	rowwords = (num+31)>>5;
+	rowbytes = rowwords*4;
+
+	sv.pvs = Hunk_Alloc (rowbytes*num);
+	scan = sv.pvs;
+	vcount = 0;
+	for (i=0 ; i<num ; i++, scan+=rowbytes)
+	{
+		memcpy (scan, Mod_LeafPVS(sv.worldmodel->leafs+i, sv.worldmodel),
+			rowbytes);
+		if (i == 0)
+			continue;
+		for (j=0 ; j<num ; j++)
+		{
+			if ( scan[j>>3] & (1<<(j&7)) )
+			{
+				vcount++;
+			}
+		}
+	}
+
+
+	sv.phs = Hunk_Alloc (rowbytes*num);
+	count = 0;
+	scan = sv.pvs;
+	dest = (unsigned *)sv.phs;
+	for (i=0 ; i<num ; i++, dest += rowwords, scan += rowbytes)
+	{
+		memcpy (dest, scan, rowbytes);
+		for (j=0 ; j<rowbytes ; j++)
+		{
+			bitbyte = scan[j];
+			if (!bitbyte)
+				continue;
+			for (k=0 ; k<8 ; k++)
+			{
+				if (! (bitbyte & (1<<k)) )
+					continue;
+				// or this pvs row into the phs
+				// +1 because pvs is 1 based
+				index = ((j<<3)+k+1);
+				if (index >= num)
+					continue;
+				src = (unsigned *)sv.pvs + index*rowwords;
+				for (l=0 ; l<rowwords ; l++)
+					dest[l] |= src[l];
+			}
+		}
+
+		if (i == 0)
+			continue;
+		for (j=0 ; j<num ; j++)
+			if ( ((byte *)dest)[j>>3] & (1<<(j&7)) )
+				count++;
+	}
+
+	Con_Printf ("Average leafs visible / hearable / total: %i / %i / %i\n"
+		, vcount/num, count/num, num);
+}
+
+unsigned SV_CheckModel(char *mdl)
+{
+	byte	stackbuf[1024];		// avoid dirtying the cache heap
+	byte *buf;
+	unsigned short crc;
+//	int len;
+
+	buf = (byte *)COM_LoadStackFile (mdl, stackbuf, sizeof(stackbuf));
+	crc = CRC_Block(buf, com_filesize);
+//	for (len = com_filesize; len; len--, buf++)
+//		CRC_ProcessByte(&crc, *buf);
+
+	return crc;
+}
+
+/*
+================
+SV_SpawnServer
+
+Change the server to a new map, taking all connected
+clients along with it.
+
+This is only called from the SV_Map_f() function.
+================
+*/
+void SV_SpawnServer (char *server)
+{
+	edict_t		*ent;
+	int			i;
+
+	Con_DPrintf ("SpawnServer: %s\n",server);
+	
+	SV_SaveSpawnparms ();
+
+	svs.spawncount++;		// any partially connected client will be
+							// restarted
+
+	sv.state = ss_dead;
+
+	Mod_ClearAll ();
+	Hunk_FreeToLowMark (host_hunklevel);
+
+	// wipe the entire per-level structure
+	memset (&sv, 0, sizeof(sv));
+
+	sv.datagram.maxsize = sizeof(sv.datagram_buf);
+	sv.datagram.data = sv.datagram_buf;
+	sv.datagram.allowoverflow = true;
+
+	sv.reliable_datagram.maxsize = sizeof(sv.reliable_datagram_buf);
+	sv.reliable_datagram.data = sv.reliable_datagram_buf;
+	
+	sv.multicast.maxsize = sizeof(sv.multicast_buf);
+	sv.multicast.data = sv.multicast_buf;
+	
+	sv.master.maxsize = sizeof(sv.master_buf);
+	sv.master.data = sv.master_buf;
+	
+	sv.signon.maxsize = sizeof(sv.signon_buffers[0]);
+	sv.signon.data = sv.signon_buffers[0];
+	sv.num_signon_buffers = 1;
+
+	strcpy (sv.name, server);
+
+	// load progs to get entity field count
+	// which determines how big each edict is
+	PR_LoadProgs ();
+
+	// allocate edicts
+	sv.edicts = Hunk_AllocName (MAX_EDICTS*pr_edict_size, "edicts");
+	
+	// leave slots at start for clients only
+	sv.num_edicts = MAX_CLIENTS+1;
+	for (i=0 ; i<MAX_CLIENTS ; i++)
+	{
+		ent = EDICT_NUM(i+1);
+		svs.clients[i].edict = ent;
+//ZOID - make sure we update frags right
+		svs.clients[i].old_frags = 0;
+	}
+
+	sv.time = 1.0;
+	
+	strcpy (sv.name, server);
+	sprintf (sv.modelname,"maps/%s.bsp", server);
+	sv.worldmodel = Mod_ForName (sv.modelname, true);
+	SV_CalcPHS ();
+
+	//
+	// clear physics interaction links
+	//
+	SV_ClearWorld ();
+	
+	sv.sound_precache[0] = pr_strings;
+
+	sv.model_precache[0] = pr_strings;
+	sv.model_precache[1] = sv.modelname;
+	sv.models[1] = sv.worldmodel;
+	for (i=1 ; i<sv.worldmodel->numsubmodels ; i++)
+	{
+		sv.model_precache[1+i] = localmodels[i];
+		sv.models[i+1] = Mod_ForName (localmodels[i], false);
+	}
+
+	//check player/eyes models for hacks
+	sv.model_player_checksum = SV_CheckModel("progs/player.mdl");
+	sv.eyes_player_checksum = SV_CheckModel("progs/eyes.mdl");
+
+	//
+	// spawn the rest of the entities on the map
+	//	
+
+	// precache and static commands can be issued during
+	// map initialization
+	sv.state = ss_loading;
+
+	ent = EDICT_NUM(0);
+	ent->free = false;
+	ent->v.model = PR_SetString(sv.worldmodel->name);
+	ent->v.modelindex = 1;		// world model
+	ent->v.solid = SOLID_BSP;
+	ent->v.movetype = MOVETYPE_PUSH;
+
+	pr_global_struct->mapname = PR_SetString(sv.name);
+	// serverflags are for cross level information (sigils)
+	pr_global_struct->serverflags = svs.serverflags;
+	
+	// run the frame start qc function to let progs check cvars
+	SV_ProgStartFrame ();
+
+	// load and spawn all other entities
+	ED_LoadFromFile (sv.worldmodel->entities);
+
+	// look up some model indexes for specialized message compression
+	SV_FindModelNumbers ();
+
+	// all spawning is completed, any further precache statements
+	// or prog writes to the signon message are errors
+	sv.state = ss_active;
+	
+	// run two frames to allow everything to settle
+	host_frametime = 0.1;
+	SV_Physics ();
+	SV_Physics ();
+
+	// save movement vars
+	SV_SetMoveVars();
+
+	// create a baseline for more efficient communications
+	SV_CreateBaseline ();
+	sv.signon_buffer_size[sv.num_signon_buffers-1] = sv.signon.cursize;
+
+	Info_SetValueForKey (svs.info, "map", sv.name, MAX_SERVERINFO_STRING);
+	Con_DPrintf ("Server spawned.\n");
+}
+
--- /dev/null
+++ b/QW/server/sv_main.c
@@ -1,0 +1,1658 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+
+#include "qwsvdef.h"
+
+quakeparms_t host_parms;
+
+qboolean	host_initialized;		// true if into command execution (compatability)
+
+double		host_frametime;
+double		realtime;				// without any filtering or bounding
+
+int			host_hunklevel;
+
+netadr_t	master_adr[MAX_MASTERS];	// address of group servers
+
+client_t	*host_client;			// current client
+
+cvar_t	sv_mintic = {"sv_mintic","0.03"};	// bound the size of the
+cvar_t	sv_maxtic = {"sv_maxtic","0.1"};	// physics time tic 
+
+cvar_t	developer = {"developer","0"};		// show extra messages
+
+cvar_t	timeout = {"timeout","65"};		// seconds without any message
+cvar_t	zombietime = {"zombietime", "2"};	// seconds to sink messages
+											// after disconnect
+
+cvar_t	rcon_password = {"rcon_password", ""};	// password for remote server commands
+cvar_t	password = {"password", ""};	// password for entering the game
+cvar_t	spectator_password = {"spectator_password", ""};	// password for entering as a sepctator
+
+cvar_t	allow_download = {"allow_download", "1"};
+cvar_t	allow_download_skins = {"allow_download_skins", "1"};
+cvar_t	allow_download_models = {"allow_download_models", "1"};
+cvar_t	allow_download_sounds = {"allow_download_sounds", "1"};
+cvar_t	allow_download_maps = {"allow_download_maps", "1"};
+
+cvar_t sv_highchars = {"sv_highchars", "1"};
+
+cvar_t sv_phs = {"sv_phs", "1"};
+
+cvar_t pausable	= {"pausable", "1"};
+
+
+//
+// game rules mirrored in svs.info
+//
+cvar_t	fraglimit = {"fraglimit","0",false,true};
+cvar_t	timelimit = {"timelimit","0",false,true};
+cvar_t	teamplay = {"teamplay","0",false,true};
+cvar_t	samelevel = {"samelevel","0", false, true};
+cvar_t	maxclients = {"maxclients","8", false, true};
+cvar_t	maxspectators = {"maxspectators","8", false, true};
+cvar_t	deathmatch = {"deathmatch","1", false, true};			// 0, 1, or 2
+cvar_t	spawn = {"spawn","0", false, true};
+cvar_t	watervis = {"watervis", "0", false, true};
+
+cvar_t	hostname = {"hostname","unnamed", false, true};
+
+FILE	*sv_logfile;
+FILE	*sv_fraglogfile;
+
+void SV_AcceptClient (netadr_t adr, int userid, char *userinfo);
+void Master_Shutdown (void);
+
+//============================================================================
+
+qboolean ServerPaused(void)
+{
+	return sv.paused;
+}
+
+/*
+================
+SV_Shutdown
+
+Quake calls this before calling Sys_Quit or Sys_Error
+================
+*/
+void SV_Shutdown (void)
+{
+	Master_Shutdown ();
+	if (sv_logfile)
+	{
+		fclose (sv_logfile);
+		sv_logfile = NULL;
+	}
+	if (sv_fraglogfile)
+	{
+		fclose (sv_fraglogfile);
+		sv_logfile = NULL;
+	}
+	NET_Shutdown ();
+}
+
+/*
+================
+SV_Error
+
+Sends a datagram to all the clients informing them of the server crash,
+then exits
+================
+*/
+void SV_Error (char *error, ...)
+{
+	va_list		argptr;
+	static	char		string[1024];
+	static	qboolean inerror = false;
+
+	if (inerror)
+		Sys_Error ("SV_Error: recursively entered (%s)", string);
+
+	inerror = true;
+
+	va_start (argptr,error);
+	vsprintf (string,error,argptr);
+	va_end (argptr);
+
+	Con_Printf ("SV_Error: %s\n",string);
+
+	SV_FinalMessage (va("server crashed: %s\n", string));
+		
+	SV_Shutdown ();
+
+	Sys_Error ("SV_Error: %s\n",string);
+}
+
+/*
+==================
+SV_FinalMessage
+
+Used by SV_Error and SV_Quit_f to send a final message to all connected
+clients before the server goes down.  The messages are sent immediately,
+not just stuck on the outgoing message list, because the server is going
+to totally exit after returning from this function.
+==================
+*/
+void SV_FinalMessage (char *message)
+{
+	int			i;
+	client_t	*cl;
+	
+	SZ_Clear (&net_message);
+	MSG_WriteByte (&net_message, svc_print);
+	MSG_WriteByte (&net_message, PRINT_HIGH);
+	MSG_WriteString (&net_message, message);
+	MSG_WriteByte (&net_message, svc_disconnect);
+
+	for (i=0, cl = svs.clients ; i<MAX_CLIENTS ; i++, cl++)
+		if (cl->state >= cs_spawned)
+			Netchan_Transmit (&cl->netchan, net_message.cursize
+			, net_message.data);
+}
+
+
+
+/*
+=====================
+SV_DropClient
+
+Called when the player is totally leaving the server, either willingly
+or unwillingly.  This is NOT called if the entire server is quiting
+or crashing.
+=====================
+*/
+void SV_DropClient (client_t *drop)
+{
+	// add the disconnect
+	MSG_WriteByte (&drop->netchan.message, svc_disconnect);
+
+	if (drop->state == cs_spawned)
+		if (!drop->spectator)
+		{
+			// call the prog function for removing a client
+			// this will set the body to a dead frame, among other things
+			pr_global_struct->self = EDICT_TO_PROG(drop->edict);
+			PR_ExecuteProgram (pr_global_struct->ClientDisconnect);
+		}
+		else if (SpectatorDisconnect)
+		{
+			// call the prog function for removing a client
+			// this will set the body to a dead frame, among other things
+			pr_global_struct->self = EDICT_TO_PROG(drop->edict);
+			PR_ExecuteProgram (SpectatorDisconnect);
+		}
+
+	if (drop->spectator)
+		Con_Printf ("Spectator %s removed\n",drop->name);
+	else
+		Con_Printf ("Client %s removed\n",drop->name);
+
+	if (drop->download)
+	{
+		fclose (drop->download);
+		drop->download = NULL;
+	}
+	if (drop->upload)
+	{
+		fclose (drop->upload);
+		drop->upload = NULL;
+	}
+	*drop->uploadfn = 0;
+
+	drop->state = cs_zombie;		// become free in a few seconds
+	drop->connection_started = realtime;	// for zombie timeout
+
+	drop->old_frags = 0;
+	drop->edict->v.frags = 0;
+	drop->name[0] = 0;
+	memset (drop->userinfo, 0, sizeof(drop->userinfo));
+
+// send notification to all remaining clients
+	SV_FullClientUpdate (drop, &sv.reliable_datagram);
+}
+
+
+//====================================================================
+
+/*
+===================
+SV_CalcPing
+
+===================
+*/
+int SV_CalcPing (client_t *cl)
+{
+	float		ping;
+	int			i;
+	int			count;
+	register	client_frame_t *frame;
+
+	ping = 0;
+	count = 0;
+	for (frame = cl->frames, i=0 ; i<UPDATE_BACKUP ; i++, frame++)
+	{
+		if (frame->ping_time > 0)
+		{
+			ping += frame->ping_time;
+			count++;
+		}
+	}
+	if (!count)
+		return 9999;
+	ping /= count;
+
+	return ping*1000;
+}
+
+/*
+===================
+SV_FullClientUpdate
+
+Writes all update values to a sizebuf
+===================
+*/
+void SV_FullClientUpdate (client_t *client, sizebuf_t *buf)
+{
+	int		i;
+	char	info[MAX_INFO_STRING];
+
+	i = client - svs.clients;
+
+//Sys_Printf("SV_FullClientUpdate:  Updated frags for client %d\n", i);
+
+	MSG_WriteByte (buf, svc_updatefrags);
+	MSG_WriteByte (buf, i);
+	MSG_WriteShort (buf, client->old_frags);
+	
+	MSG_WriteByte (buf, svc_updateping);
+	MSG_WriteByte (buf, i);
+	MSG_WriteShort (buf, SV_CalcPing (client));
+	
+	MSG_WriteByte (buf, svc_updatepl);
+	MSG_WriteByte (buf, i);
+	MSG_WriteByte (buf, client->lossage);
+	
+	MSG_WriteByte (buf, svc_updateentertime);
+	MSG_WriteByte (buf, i);
+	MSG_WriteFloat (buf, realtime - client->connection_started);
+
+	strcpy (info, client->userinfo);
+	Info_RemovePrefixedKeys (info, '_');	// server passwords, etc
+
+	MSG_WriteByte (buf, svc_updateuserinfo);
+	MSG_WriteByte (buf, i);
+	MSG_WriteLong (buf, client->userid);
+	MSG_WriteString (buf, info);
+}
+
+/*
+===================
+SV_FullClientUpdateToClient
+
+Writes all update values to a client's reliable stream
+===================
+*/
+void SV_FullClientUpdateToClient (client_t *client, client_t *cl)
+{
+	ClientReliableCheckBlock(cl, 24 + strlen(client->userinfo));
+	if (cl->num_backbuf) {
+		SV_FullClientUpdate (client, &cl->backbuf);
+		ClientReliable_FinishWrite(cl);
+	} else
+		SV_FullClientUpdate (client, &cl->netchan.message);
+}
+
+
+/*
+==============================================================================
+
+CONNECTIONLESS COMMANDS
+
+==============================================================================
+*/
+
+/*
+================
+SVC_Status
+
+Responds with all the info that qplug or qspy can see
+This message can be up to around 5k with worst case string lengths.
+================
+*/
+void SVC_Status (void)
+{
+	int		i;
+	client_t	*cl;
+	int		ping;
+	int		top, bottom;
+
+	Cmd_TokenizeString ("status");
+	SV_BeginRedirect (RD_PACKET);
+	Con_Printf ("%s\n", svs.info);
+	for (i=0 ; i<MAX_CLIENTS ; i++)
+	{
+		cl = &svs.clients[i];
+		if ((cl->state == cs_connected || cl->state == cs_spawned ) && !cl->spectator)
+		{
+			top = atoi(Info_ValueForKey (cl->userinfo, "topcolor"));
+			bottom = atoi(Info_ValueForKey (cl->userinfo, "bottomcolor"));
+			top = (top < 0) ? 0 : ((top > 13) ? 13 : top);
+			bottom = (bottom < 0) ? 0 : ((bottom > 13) ? 13 : bottom);
+			ping = SV_CalcPing (cl);
+			Con_Printf ("%i %i %i %i \"%s\" \"%s\" %i %i\n", cl->userid, 
+				cl->old_frags, (int)(realtime - cl->connection_started)/60,
+				ping, cl->name, Info_ValueForKey (cl->userinfo, "skin"), top, bottom);
+		}
+	}
+	SV_EndRedirect ();
+}
+
+/*
+===================
+SV_CheckLog
+
+===================
+*/
+#define	LOG_HIGHWATER	4096
+#define	LOG_FLUSH		10*60
+void SV_CheckLog (void)
+{
+	sizebuf_t	*sz;
+
+	sz = &svs.log[svs.logsequence&1];
+
+	// bump sequence if allmost full, or ten minutes have passed and
+	// there is something still sitting there
+	if (sz->cursize > LOG_HIGHWATER
+	|| (realtime - svs.logtime > LOG_FLUSH && sz->cursize) )
+	{
+		// swap buffers and bump sequence
+		svs.logtime = realtime;
+		svs.logsequence++;
+		sz = &svs.log[svs.logsequence&1];
+		sz->cursize = 0;
+		Con_Printf ("beginning fraglog sequence %i\n", svs.logsequence);
+	}
+
+}
+
+/*
+================
+SVC_Log
+
+Responds with all the logged frags for ranking programs.
+If a sequence number is passed as a parameter and it is
+the same as the current sequence, an A2A_NACK will be returned
+instead of the data.
+================
+*/
+void SVC_Log (void)
+{
+	int		seq;
+	char	data[MAX_DATAGRAM+64];
+
+	if (Cmd_Argc() == 2)
+		seq = atoi(Cmd_Argv(1));
+	else
+		seq = -1;
+
+	if (seq == svs.logsequence-1 || !sv_fraglogfile)
+	{	// they allready have this data, or we aren't logging frags
+		data[0] = A2A_NACK;
+		NET_SendPacket (1, data, net_from);
+		return;
+	}
+
+	Con_DPrintf ("sending log %i to %s\n", svs.logsequence-1, NET_AdrToString(net_from));
+
+	sprintf (data, "stdlog %i\n", svs.logsequence-1);
+	strcat (data, (char *)svs.log_buf[((svs.logsequence-1)&1)]);
+
+	NET_SendPacket (strlen(data)+1, data, net_from);
+}
+
+/*
+================
+SVC_Ping
+
+Just responds with an acknowledgement
+================
+*/
+void SVC_Ping (void)
+{
+	char	data;
+
+	data = A2A_ACK;
+
+	NET_SendPacket (1, &data, net_from);
+}
+
+/*
+=================
+SVC_GetChallenge
+
+Returns a challenge number that can be used
+in a subsequent client_connect command.
+We do this to prevent denial of service attacks that
+flood the server with invalid connection IPs.  With a
+challenge, they must give a valid IP address.
+=================
+*/
+void SVC_GetChallenge (void)
+{
+	int		i;
+	int		oldest;
+	int		oldestTime;
+
+	oldest = 0;
+	oldestTime = 0x7fffffff;
+
+	// see if we already have a challenge for this ip
+	for (i = 0 ; i < MAX_CHALLENGES ; i++)
+	{
+		if (NET_CompareBaseAdr (net_from, svs.challenges[i].adr))
+			break;
+		if (svs.challenges[i].time < oldestTime)
+		{
+			oldestTime = svs.challenges[i].time;
+			oldest = i;
+		}
+	}
+
+	if (i == MAX_CHALLENGES)
+	{
+		// overwrite the oldest
+		svs.challenges[oldest].challenge = (rand() << 16) ^ rand();
+		svs.challenges[oldest].adr = net_from;
+		svs.challenges[oldest].time = realtime;
+		i = oldest;
+	}
+
+	// send it back
+	Netchan_OutOfBandPrint (net_from, "%c%i", S2C_CHALLENGE, 
+			svs.challenges[i].challenge);
+}
+
+/*
+==================
+SVC_DirectConnect
+
+A connection request that did not come from the master
+==================
+*/
+void SVC_DirectConnect (void)
+{
+	char		userinfo[1024];
+	static		int	userid;
+	netadr_t	adr;
+	int			i;
+	client_t	*cl, *newcl;
+	client_t	temp;
+	edict_t		*ent;
+	int			edictnum;
+	char		*s;
+	int			clients, spectators;
+	qboolean	spectator;
+	int			qport;
+	int			version;
+	int			challenge;
+
+	version = atoi(Cmd_Argv(1));
+	if (version != PROTOCOL_VERSION)
+	{
+		Netchan_OutOfBandPrint (net_from, "%c\nServer is version %4.2f.\n", A2C_PRINT, VERSION);
+		Con_Printf ("* rejected connect from version %i\n", version);
+		return;
+	}
+
+	qport = atoi(Cmd_Argv(2));
+
+	challenge = atoi(Cmd_Argv(3));
+
+	// note an extra byte is needed to replace spectator key
+	strncpy (userinfo, Cmd_Argv(4), sizeof(userinfo)-2);
+	userinfo[sizeof(userinfo) - 2] = 0;
+
+	// see if the challenge is valid
+	for (i=0 ; i<MAX_CHALLENGES ; i++)
+	{
+		if (NET_CompareBaseAdr (net_from, svs.challenges[i].adr))
+		{
+			if (challenge == svs.challenges[i].challenge)
+				break;		// good
+			Netchan_OutOfBandPrint (net_from, "%c\nBad challenge.\n", A2C_PRINT);
+			return;
+		}
+	}
+	if (i == MAX_CHALLENGES)
+	{
+		Netchan_OutOfBandPrint (net_from, "%c\nNo challenge for address.\n", A2C_PRINT);
+		return;
+	}
+
+	// check for password or spectator_password
+	s = Info_ValueForKey (userinfo, "spectator");
+	if (s[0] && strcmp(s, "0"))
+	{
+		if (spectator_password.string[0] && 
+			stricmp(spectator_password.string, "none") &&
+			strcmp(spectator_password.string, s) )
+		{	// failed
+			Con_Printf ("%s:spectator password failed\n", NET_AdrToString (net_from));
+			Netchan_OutOfBandPrint (net_from, "%c\nrequires a spectator password\n\n", A2C_PRINT);
+			return;
+		}
+		Info_RemoveKey (userinfo, "spectator"); // remove passwd
+		Info_SetValueForStarKey (userinfo, "*spectator", "1", MAX_INFO_STRING);
+		spectator = true;
+	}
+	else
+	{
+		s = Info_ValueForKey (userinfo, "password");
+		if (password.string[0] && 
+			stricmp(password.string, "none") &&
+			strcmp(password.string, s) )
+		{
+			Con_Printf ("%s:password failed\n", NET_AdrToString (net_from));
+			Netchan_OutOfBandPrint (net_from, "%c\nserver requires a password\n\n", A2C_PRINT);
+			return;
+		}
+		spectator = false;
+		Info_RemoveKey (userinfo, "password"); // remove passwd
+	}
+
+	adr = net_from;
+	userid++;	// so every client gets a unique id
+
+	newcl = &temp;
+	memset (newcl, 0, sizeof(client_t));
+
+	newcl->userid = userid;
+
+	// works properly
+	if (!sv_highchars.value) {
+		byte *p, *q;
+
+		for (p = (byte *)newcl->userinfo, q = (byte *)userinfo; 
+			*q && p < (byte *)newcl->userinfo + sizeof(newcl->userinfo)-1; q++)
+			if (*q > 31 && *q <= 127)
+				*p++ = *q;
+	} else
+		strncpy (newcl->userinfo, userinfo, sizeof(newcl->userinfo)-1);
+
+	// if there is allready a slot for this ip, drop it
+	for (i=0,cl=svs.clients ; i<MAX_CLIENTS ; i++,cl++)
+	{
+		if (cl->state == cs_free)
+			continue;
+		if (NET_CompareBaseAdr (adr, cl->netchan.remote_address)
+			&& ( cl->netchan.qport == qport 
+			|| adr.port == cl->netchan.remote_address.port ))
+		{
+			if (cl->state == cs_connected) {
+				Con_Printf("%s:dup connect\n", NET_AdrToString (adr));
+				userid--;
+				return;
+			}
+
+			Con_Printf ("%s:reconnect\n", NET_AdrToString (adr));
+			SV_DropClient (cl);
+			break;
+		}
+	}
+
+	// count up the clients and spectators
+	clients = 0;
+	spectators = 0;
+	for (i=0,cl=svs.clients ; i<MAX_CLIENTS ; i++,cl++)
+	{
+		if (cl->state == cs_free)
+			continue;
+		if (cl->spectator)
+			spectators++;
+		else
+			clients++;
+	}
+
+	// if at server limits, refuse connection
+	if ( maxclients.value > MAX_CLIENTS )
+		Cvar_SetValue ("maxclients", MAX_CLIENTS);
+	if (maxspectators.value > MAX_CLIENTS)
+		Cvar_SetValue ("maxspectators", MAX_CLIENTS);
+	if (maxspectators.value + maxclients.value > MAX_CLIENTS)
+		Cvar_SetValue ("maxspectators", MAX_CLIENTS - maxspectators.value + maxclients.value);
+	if ( (spectator && spectators >= (int)maxspectators.value)
+		|| (!spectator && clients >= (int)maxclients.value) )
+	{
+		Con_Printf ("%s:full connect\n", NET_AdrToString (adr));
+		Netchan_OutOfBandPrint (adr, "%c\nserver is full\n\n", A2C_PRINT);
+		return;
+	}
+
+	// find a client slot
+	newcl = NULL;
+	for (i=0,cl=svs.clients ; i<MAX_CLIENTS ; i++,cl++)
+	{
+		if (cl->state == cs_free)
+		{
+			newcl = cl;
+			break;
+		}
+	}
+	if (!newcl)
+	{
+		Con_Printf ("WARNING: miscounted available clients\n");
+		return;
+	}
+
+	
+	// build a new connection
+	// accept the new client
+	// this is the only place a client_t is ever initialized
+	*newcl = temp;
+
+	Netchan_OutOfBandPrint (adr, "%c", S2C_CONNECTION );
+
+	edictnum = (newcl-svs.clients)+1;
+	
+	Netchan_Setup (&newcl->netchan , adr, qport);
+
+	newcl->state = cs_connected;
+
+	newcl->datagram.allowoverflow = true;
+	newcl->datagram.data = newcl->datagram_buf;
+	newcl->datagram.maxsize = sizeof(newcl->datagram_buf);
+
+	// spectator mode can ONLY be set at join time
+	newcl->spectator = spectator;
+
+	ent = EDICT_NUM(edictnum);	
+	newcl->edict = ent;
+	
+	// parse some info from the info strings
+	SV_ExtractFromUserinfo (newcl);
+
+	// JACK: Init the floodprot stuff.
+	for (i=0; i<10; i++)
+		newcl->whensaid[i] = 0.0;
+	newcl->whensaidhead = 0;
+	newcl->lockedtill = 0;
+
+	// call the progs to get default spawn parms for the new client
+	PR_ExecuteProgram (pr_global_struct->SetNewParms);
+	for (i=0 ; i<NUM_SPAWN_PARMS ; i++)
+		newcl->spawn_parms[i] = (&pr_global_struct->parm1)[i];
+
+	if (newcl->spectator)
+		Con_Printf ("Spectator %s connected\n", newcl->name);
+	else
+		Con_DPrintf ("Client %s connected\n", newcl->name);
+	newcl->sendinfo = true;
+}
+
+int Rcon_Validate (void)
+{
+	if (!strlen (rcon_password.string))
+		return 0;
+
+	if (strcmp (Cmd_Argv(1), rcon_password.string) )
+		return 0;
+
+	return 1;
+}
+
+/*
+===============
+SVC_RemoteCommand
+
+A client issued an rcon command.
+Shift down the remaining args
+Redirect all printfs
+===============
+*/
+void SVC_RemoteCommand (void)
+{
+	int		i;
+	char	remaining[1024];
+
+
+	if (!Rcon_Validate ()) {
+		Con_Printf ("Bad rcon from %s:\n%s\n"
+			, NET_AdrToString (net_from), net_message.data+4);
+
+		SV_BeginRedirect (RD_PACKET);
+
+		Con_Printf ("Bad rcon_password.\n");
+
+	} else {
+
+		Con_Printf ("Rcon from %s:\n%s\n"
+			, NET_AdrToString (net_from), net_message.data+4);
+
+		SV_BeginRedirect (RD_PACKET);
+
+		remaining[0] = 0;
+
+		for (i=2 ; i<Cmd_Argc() ; i++)
+		{
+			strcat (remaining, Cmd_Argv(i) );
+			strcat (remaining, " ");
+		}
+
+		Cmd_ExecuteString (remaining);
+
+	}
+
+	SV_EndRedirect ();
+}
+
+
+/*
+=================
+SV_ConnectionlessPacket
+
+A connectionless packet has four leading 0xff
+characters to distinguish it from a game channel.
+Clients that are in the game can still send
+connectionless packets.
+=================
+*/
+void SV_ConnectionlessPacket (void)
+{
+	char	*s;
+	char	*c;
+
+	MSG_BeginReading ();
+	MSG_ReadLong ();		// skip the -1 marker
+
+	s = MSG_ReadStringLine ();
+
+	Cmd_TokenizeString (s);
+
+	c = Cmd_Argv(0);
+
+	if (!strcmp(c, "ping") || ( c[0] == A2A_PING && (c[1] == 0 || c[1] == '\n')) )
+	{
+		SVC_Ping ();
+		return;
+	}
+	if (c[0] == A2A_ACK && (c[1] == 0 || c[1] == '\n') )
+	{
+		Con_Printf ("A2A_ACK from %s\n", NET_AdrToString (net_from));
+		return;
+	}
+	else if (!strcmp(c,"status"))
+	{
+		SVC_Status ();
+		return;
+	}
+	else if (!strcmp(c,"log"))
+	{
+		SVC_Log ();
+		return;
+	}
+	else if (!strcmp(c,"connect"))
+	{
+		SVC_DirectConnect ();
+		return;
+	}
+	else if (!strcmp(c,"getchallenge"))
+	{
+		SVC_GetChallenge ();
+		return;
+	}
+	else if (!strcmp(c, "rcon"))
+		SVC_RemoteCommand ();
+	else
+		Con_Printf ("bad connectionless packet from %s:\n%s\n"
+		, NET_AdrToString (net_from), s);
+}
+
+/*
+==============================================================================
+
+PACKET FILTERING
+ 
+
+You can add or remove addresses from the filter list with:
+
+addip <ip>
+removeip <ip>
+
+The ip address is specified in dot format, and any unspecified digits will match any value, so you can specify an entire class C network with "addip 192.246.40".
+
+Removeip will only remove an address specified exactly the same way.  You cannot addip a subnet, then removeip a single host.
+
+listip
+Prints the current list of filters.
+
+writeip
+Dumps "addip <ip>" commands to listip.cfg so it can be execed at a later date.  The filter lists are not saved and restored by default, because I beleive it would cause too much confusion.
+
+filterban <0 or 1>
+
+If 1 (the default), then ip addresses matching the current list will be prohibited from entering the game.  This is the default setting.
+
+If 0, then only addresses matching the list will be allowed.  This lets you easily set up a private game, or a game that only allows players from your local network.
+
+
+==============================================================================
+*/
+
+
+typedef struct
+{
+	unsigned	mask;
+	unsigned	compare;
+} ipfilter_t;
+
+#define	MAX_IPFILTERS	1024
+
+ipfilter_t	ipfilters[MAX_IPFILTERS];
+int			numipfilters;
+
+cvar_t	filterban = {"filterban", "1"};
+
+/*
+=================
+StringToFilter
+=================
+*/
+qboolean StringToFilter (char *s, ipfilter_t *f)
+{
+	char	num[128];
+	int		i, j;
+	byte	b[4];
+	byte	m[4];
+	
+	for (i=0 ; i<4 ; i++)
+	{
+		b[i] = 0;
+		m[i] = 0;
+	}
+	
+	for (i=0 ; i<4 ; i++)
+	{
+		if (*s < '0' || *s > '9')
+		{
+			Con_Printf ("Bad filter address: %s\n", s);
+			return false;
+		}
+		
+		j = 0;
+		while (*s >= '0' && *s <= '9')
+		{
+			num[j++] = *s++;
+		}
+		num[j] = 0;
+		b[i] = atoi(num);
+		if (b[i] != 0)
+			m[i] = 255;
+
+		if (!*s)
+			break;
+		s++;
+	}
+	
+	f->mask = *(unsigned *)m;
+	f->compare = *(unsigned *)b;
+	
+	return true;
+}
+
+/*
+=================
+SV_AddIP_f
+=================
+*/
+void SV_AddIP_f (void)
+{
+	int		i;
+	
+	for (i=0 ; i<numipfilters ; i++)
+		if (ipfilters[i].compare == 0xffffffff)
+			break;		// free spot
+	if (i == numipfilters)
+	{
+		if (numipfilters == MAX_IPFILTERS)
+		{
+			Con_Printf ("IP filter list is full\n");
+			return;
+		}
+		numipfilters++;
+	}
+	
+	if (!StringToFilter (Cmd_Argv(1), &ipfilters[i]))
+		ipfilters[i].compare = 0xffffffff;
+}
+
+/*
+=================
+SV_RemoveIP_f
+=================
+*/
+void SV_RemoveIP_f (void)
+{
+	ipfilter_t	f;
+	int			i, j;
+
+	if (!StringToFilter (Cmd_Argv(1), &f))
+		return;
+	for (i=0 ; i<numipfilters ; i++)
+		if (ipfilters[i].mask == f.mask
+		&& ipfilters[i].compare == f.compare)
+		{
+			for (j=i+1 ; j<numipfilters ; j++)
+				ipfilters[j-1] = ipfilters[j];
+			numipfilters--;
+			Con_Printf ("Removed.\n");
+			return;
+		}
+	Con_Printf ("Didn't find %s.\n", Cmd_Argv(1));
+}
+
+/*
+=================
+SV_ListIP_f
+=================
+*/
+void SV_ListIP_f (void)
+{
+	int		i;
+	byte	b[4];
+
+	Con_Printf ("Filter list:\n");
+	for (i=0 ; i<numipfilters ; i++)
+	{
+		*(unsigned *)b = ipfilters[i].compare;
+		Con_Printf ("%3i.%3i.%3i.%3i\n", b[0], b[1], b[2], b[3]);
+	}
+}
+
+/*
+=================
+SV_WriteIP_f
+=================
+*/
+void SV_WriteIP_f (void)
+{
+	FILE	*f;
+	char	name[MAX_OSPATH];
+	byte	b[4];
+	int		i;
+
+	sprintf (name, "%s/listip.cfg", com_gamedir);
+
+	Con_Printf ("Writing %s.\n", name);
+
+	f = fopen (name, "wb");
+	if (!f)
+	{
+		Con_Printf ("Couldn't open %s\n", name);
+		return;
+	}
+	
+	for (i=0 ; i<numipfilters ; i++)
+	{
+		*(unsigned *)b = ipfilters[i].compare;
+		fprintf (f, "addip %i.%i.%i.%i\n", b[0], b[1], b[2], b[3]);
+	}
+	
+	fclose (f);
+}
+
+/*
+=================
+SV_SendBan
+=================
+*/
+void SV_SendBan (void)
+{
+	char		data[128];
+
+	data[0] = data[1] = data[2] = data[3] = 0xff;
+	data[4] = A2C_PRINT;
+	data[5] = 0;
+	strcat (data, "\nbanned.\n");
+	
+	NET_SendPacket (strlen(data), data, net_from);
+}
+
+/*
+=================
+SV_FilterPacket
+=================
+*/
+qboolean SV_FilterPacket (void)
+{
+	int		i;
+	unsigned	in;
+	
+	in = *(unsigned *)net_from.ip;
+
+	for (i=0 ; i<numipfilters ; i++)
+		if ( (in & ipfilters[i].mask) == ipfilters[i].compare)
+			return filterban.value;
+
+	return !filterban.value;
+}
+
+//============================================================================
+
+/*
+=================
+SV_ReadPackets
+=================
+*/
+void SV_ReadPackets (void)
+{
+	int			i;
+	client_t	*cl;
+	qboolean	good;
+	int			qport;
+
+	good = false;
+	while (NET_GetPacket ())
+	{
+		if (SV_FilterPacket ())
+		{
+			SV_SendBan ();	// tell them we aren't listening...
+			continue;
+		}
+
+		// check for connectionless packet (0xffffffff) first
+		if (*(int *)net_message.data == -1)
+		{
+			SV_ConnectionlessPacket ();
+			continue;
+		}
+		
+		// read the qport out of the message so we can fix up
+		// stupid address translating routers
+		MSG_BeginReading ();
+		MSG_ReadLong ();		// sequence number
+		MSG_ReadLong ();		// sequence number
+		qport = MSG_ReadShort () & 0xffff;
+
+		// check for packets from connected clients
+		for (i=0, cl=svs.clients ; i<MAX_CLIENTS ; i++,cl++)
+		{
+			if (cl->state == cs_free)
+				continue;
+			if (!NET_CompareBaseAdr (net_from, cl->netchan.remote_address))
+				continue;
+			if (cl->netchan.qport != qport)
+				continue;
+			if (cl->netchan.remote_address.port != net_from.port)
+			{
+				Con_DPrintf ("SV_ReadPackets: fixing up a translated port\n");
+				cl->netchan.remote_address.port = net_from.port;
+			}
+			if (Netchan_Process(&cl->netchan))
+			{	// this is a valid, sequenced packet, so process it
+				svs.stats.packets++;
+				good = true;
+				cl->send_message = true;	// reply at end of frame
+				if (cl->state != cs_zombie)
+					SV_ExecuteClientMessage (cl);
+			}
+			break;
+		}
+		
+		if (i != MAX_CLIENTS)
+			continue;
+	
+		// packet is not from a known client
+		//	Con_Printf ("%s:sequenced packet without connection\n"
+		// ,NET_AdrToString(net_from));
+	}
+}
+
+/*
+==================
+SV_CheckTimeouts
+
+If a packet has not been received from a client in timeout.value
+seconds, drop the conneciton.
+
+When a client is normally dropped, the client_t goes into a zombie state
+for a few seconds to make sure any final reliable message gets resent
+if necessary
+==================
+*/
+void SV_CheckTimeouts (void)
+{
+	int		i;
+	client_t	*cl;
+	float	droptime;
+	int	nclients;
+	
+	droptime = realtime - timeout.value;
+	nclients = 0;
+
+	for (i=0,cl=svs.clients ; i<MAX_CLIENTS ; i++,cl++)
+	{
+		if (cl->state == cs_connected || cl->state == cs_spawned) {
+			if (!cl->spectator)
+				nclients++;
+			if (cl->netchan.last_received < droptime) {
+				SV_BroadcastPrintf (PRINT_HIGH, "%s timed out\n", cl->name);
+				SV_DropClient (cl); 
+				cl->state = cs_free;	// don't bother with zombie state
+			}
+		}
+		if (cl->state == cs_zombie && 
+			realtime - cl->connection_started > zombietime.value)
+		{
+			cl->state = cs_free;	// can now be reused
+		}
+	}
+	if (sv.paused && !nclients) {
+		// nobody left, unpause the server
+		SV_TogglePause("Pause released since no players are left.\n");
+	}
+}
+
+/*
+===================
+SV_GetConsoleCommands
+
+Add them exactly as if they had been typed at the console
+===================
+*/
+void SV_GetConsoleCommands (void)
+{
+	char	*cmd;
+
+	while (1)
+	{
+		cmd = Sys_ConsoleInput ();
+		if (!cmd)
+			break;
+		Cbuf_AddText (cmd);
+	}
+}
+
+/*
+===================
+SV_CheckVars
+
+===================
+*/
+void SV_CheckVars (void)
+{
+	static char *pw, *spw;
+	int			v;
+
+	if (password.string == pw && spectator_password.string == spw)
+		return;
+	pw = password.string;
+	spw = spectator_password.string;
+
+	v = 0;
+	if (pw && pw[0] && strcmp(pw, "none"))
+		v |= 1;
+	if (spw && spw[0] && strcmp(spw, "none"))
+		v |= 2;
+
+	Con_Printf ("Updated needpass.\n");
+	if (!v)
+		Info_SetValueForKey (svs.info, "needpass", "", MAX_SERVERINFO_STRING);
+	else
+		Info_SetValueForKey (svs.info, "needpass", va("%i",v), MAX_SERVERINFO_STRING);
+}
+
+/*
+==================
+SV_Frame
+
+==================
+*/
+void SV_Frame (float time)
+{
+	static double	start, end;
+	
+	start = Sys_DoubleTime ();
+	svs.stats.idle += start - end;
+	
+// keep the random time dependent
+	rand ();
+
+// decide the simulation time
+	if (!sv.paused) {
+		realtime += time;
+		sv.time += time;
+	}
+
+// check timeouts
+	SV_CheckTimeouts ();
+
+// toggle the log buffer if full
+	SV_CheckLog ();
+
+// move autonomous things around if enough time has passed
+	if (!sv.paused)
+		SV_Physics ();
+
+// get packets
+	SV_ReadPackets ();
+
+// check for commands typed to the host
+	SV_GetConsoleCommands ();
+	
+// process console commands
+	Cbuf_Execute ();
+
+	SV_CheckVars ();
+
+// send messages back to the clients that had packets read this frame
+	SV_SendClientMessages ();
+
+// send a heartbeat to the master if needed
+	Master_Heartbeat ();
+
+// collect timing statistics
+	end = Sys_DoubleTime ();
+	svs.stats.active += end-start;
+	if (++svs.stats.count == STATFRAMES)
+	{
+		svs.stats.latched_active = svs.stats.active;
+		svs.stats.latched_idle = svs.stats.idle;
+		svs.stats.latched_packets = svs.stats.packets;
+		svs.stats.active = 0;
+		svs.stats.idle = 0;
+		svs.stats.packets = 0;
+		svs.stats.count = 0;
+	}
+}
+
+/*
+===============
+SV_InitLocal
+===============
+*/
+void SV_InitLocal (void)
+{
+	int		i;
+	extern	cvar_t	sv_maxvelocity;
+	extern	cvar_t	sv_gravity;
+	extern	cvar_t	sv_aim;
+	extern	cvar_t	sv_stopspeed;
+	extern	cvar_t	sv_spectatormaxspeed;
+	extern	cvar_t	sv_accelerate;
+	extern	cvar_t	sv_airaccelerate;
+	extern	cvar_t	sv_wateraccelerate;
+	extern	cvar_t	sv_friction;
+	extern	cvar_t	sv_waterfriction;
+
+	SV_InitOperatorCommands	();
+	SV_UserInit ();
+	
+	Cvar_RegisterVariable (&rcon_password);
+	Cvar_RegisterVariable (&password);
+	Cvar_RegisterVariable (&spectator_password);
+
+	Cvar_RegisterVariable (&sv_mintic);
+	Cvar_RegisterVariable (&sv_maxtic);
+
+	Cvar_RegisterVariable (&fraglimit);
+	Cvar_RegisterVariable (&timelimit);
+	Cvar_RegisterVariable (&teamplay);
+	Cvar_RegisterVariable (&samelevel);
+	Cvar_RegisterVariable (&maxclients);
+	Cvar_RegisterVariable (&maxspectators);
+	Cvar_RegisterVariable (&hostname);
+	Cvar_RegisterVariable (&deathmatch);
+	Cvar_RegisterVariable (&spawn);
+	Cvar_RegisterVariable (&watervis);
+
+	Cvar_RegisterVariable (&developer);
+
+	Cvar_RegisterVariable (&timeout);
+	Cvar_RegisterVariable (&zombietime);
+
+	Cvar_RegisterVariable (&sv_maxvelocity);
+	Cvar_RegisterVariable (&sv_gravity);
+	Cvar_RegisterVariable (&sv_stopspeed);
+	Cvar_RegisterVariable (&sv_maxspeed);
+	Cvar_RegisterVariable (&sv_spectatormaxspeed);
+	Cvar_RegisterVariable (&sv_accelerate);
+	Cvar_RegisterVariable (&sv_airaccelerate);
+	Cvar_RegisterVariable (&sv_wateraccelerate);
+	Cvar_RegisterVariable (&sv_friction);
+	Cvar_RegisterVariable (&sv_waterfriction);
+
+	Cvar_RegisterVariable (&sv_aim);
+
+	Cvar_RegisterVariable (&filterban);
+	
+	Cvar_RegisterVariable (&allow_download);
+	Cvar_RegisterVariable (&allow_download_skins);
+	Cvar_RegisterVariable (&allow_download_models);
+	Cvar_RegisterVariable (&allow_download_sounds);
+	Cvar_RegisterVariable (&allow_download_maps);
+
+	Cvar_RegisterVariable (&sv_highchars);
+
+	Cvar_RegisterVariable (&sv_phs);
+
+	Cvar_RegisterVariable (&pausable);
+
+	Cmd_AddCommand ("addip", SV_AddIP_f);
+	Cmd_AddCommand ("removeip", SV_RemoveIP_f);
+	Cmd_AddCommand ("listip", SV_ListIP_f);
+	Cmd_AddCommand ("writeip", SV_WriteIP_f);
+
+	for (i=0 ; i<MAX_MODELS ; i++)
+		sprintf (localmodels[i], "*%i", i);
+
+	Info_SetValueForStarKey (svs.info, "*version", va("%4.2f", VERSION), MAX_SERVERINFO_STRING);
+
+	// init fraglog stuff
+	svs.logsequence = 1;
+	svs.logtime = realtime;
+	svs.log[0].data = svs.log_buf[0];
+	svs.log[0].maxsize = sizeof(svs.log_buf[0]);
+	svs.log[0].cursize = 0;
+	svs.log[0].allowoverflow = true;
+	svs.log[1].data = svs.log_buf[1];
+	svs.log[1].maxsize = sizeof(svs.log_buf[1]);
+	svs.log[1].cursize = 0;
+	svs.log[1].allowoverflow = true;
+}
+
+
+//============================================================================
+
+/*
+================
+Master_Heartbeat
+
+Send a message to the master every few minutes to
+let it know we are alive, and log information
+================
+*/
+#define	HEARTBEAT_SECONDS	300
+void Master_Heartbeat (void)
+{
+	char		string[2048];
+	int			active;
+	int			i;
+
+	if (realtime - svs.last_heartbeat < HEARTBEAT_SECONDS)
+		return;		// not time to send yet
+
+	svs.last_heartbeat = realtime;
+
+	//
+	// count active users
+	//
+	active = 0;
+	for (i=0 ; i<MAX_CLIENTS ; i++)
+		if (svs.clients[i].state == cs_connected ||
+		svs.clients[i].state == cs_spawned )
+			active++;
+
+	svs.heartbeat_sequence++;
+	sprintf (string, "%c\n%i\n%i\n", S2M_HEARTBEAT,
+		svs.heartbeat_sequence, active);
+
+
+	// send to group master
+	for (i=0 ; i<MAX_MASTERS ; i++)
+		if (master_adr[i].port)
+		{
+			Con_Printf ("Sending heartbeat to %s\n", NET_AdrToString (master_adr[i]));
+			NET_SendPacket (strlen(string), string, master_adr[i]);
+		}
+}
+
+/*
+=================
+Master_Shutdown
+
+Informs all masters that this server is going down
+=================
+*/
+void Master_Shutdown (void)
+{
+	char		string[2048];
+	int			i;
+
+	sprintf (string, "%c\n", S2M_SHUTDOWN);
+
+	// send to group master
+	for (i=0 ; i<MAX_MASTERS ; i++)
+		if (master_adr[i].port)
+		{
+			Con_Printf ("Sending heartbeat to %s\n", NET_AdrToString (master_adr[i]));
+			NET_SendPacket (strlen(string), string, master_adr[i]);
+		}
+}
+
+/*
+=================
+SV_ExtractFromUserinfo
+
+Pull specific info from a newly changed userinfo string
+into a more C freindly form.
+=================
+*/
+void SV_ExtractFromUserinfo (client_t *cl)
+{
+	char	*val, *p, *q;
+	int		i;
+	client_t	*client;
+	int		dupc = 1;
+	char	newname[80];
+
+
+	// name for C code
+	val = Info_ValueForKey (cl->userinfo, "name");
+
+	// trim user name
+	strncpy(newname, val, sizeof(newname) - 1);
+	newname[sizeof(newname) - 1] = 0;
+
+	for (p = newname; (*p == ' ' || *p == '\r' || *p == '\n') && *p; p++)
+		;
+
+	if (p != newname && !*p) {
+		//white space only
+		strcpy(newname, "unnamed");
+		p = newname;
+	}
+
+	if (p != newname && *p) {
+		for (q = newname; *p; *q++ = *p++)
+			;
+		*q = 0;
+	}
+	for (p = newname + strlen(newname) - 1; p != newname && (*p == ' ' || *p == '\r' || *p == '\n') ; p--)
+		;
+	p[1] = 0;
+
+	if (strcmp(val, newname)) {
+		Info_SetValueForKey (cl->userinfo, "name", newname, MAX_INFO_STRING);
+		val = Info_ValueForKey (cl->userinfo, "name");
+	}
+
+	if (!val[0] || !stricmp(val, "console")) {
+		Info_SetValueForKey (cl->userinfo, "name", "unnamed", MAX_INFO_STRING);
+		val = Info_ValueForKey (cl->userinfo, "name");
+	}
+
+	// check to see if another user by the same name exists
+	while (1) {
+		for (i=0, client = svs.clients ; i<MAX_CLIENTS ; i++, client++) {
+			if (client->state != cs_spawned || client == cl)
+				continue;
+			if (!stricmp(client->name, val))
+				break;
+		}
+		if (i != MAX_CLIENTS) { // dup name
+			if (strlen(val) > sizeof(cl->name) - 1)
+				val[sizeof(cl->name) - 4] = 0;
+			p = val;
+
+			if (val[0] == '(')
+				if (val[2] == ')')
+					p = val + 3;
+				else if (val[3] == ')')
+					p = val + 4;
+
+			sprintf(newname, "(%d)%-.40s", dupc++, p);
+			Info_SetValueForKey (cl->userinfo, "name", newname, MAX_INFO_STRING);
+			val = Info_ValueForKey (cl->userinfo, "name");
+		} else
+			break;
+	}
+	
+	if (strncmp(val, cl->name, strlen(cl->name))) {
+		if (!sv.paused) {
+			if (!cl->lastnametime || realtime - cl->lastnametime > 5) {
+				cl->lastnamecount = 0;
+				cl->lastnametime = realtime;
+			} else if (cl->lastnamecount++ > 4) {
+				SV_BroadcastPrintf (PRINT_HIGH, "%s was kicked for name spam\n", cl->name);
+				SV_ClientPrintf (cl, PRINT_HIGH, "You were kicked from the game for name spamming\n");
+				SV_DropClient (cl); 
+				return;
+			}
+		}
+				
+		if (cl->state >= cs_spawned && !cl->spectator)
+			SV_BroadcastPrintf (PRINT_HIGH, "%s changed name to %s\n", cl->name, val);
+	}
+
+
+	strncpy (cl->name, val, sizeof(cl->name)-1);	
+
+	// rate command
+	val = Info_ValueForKey (cl->userinfo, "rate");
+	if (strlen(val))
+	{
+		i = atoi(val);
+		if (i < 500)
+			i = 500;
+		if (i > 10000)
+			i = 10000;
+		cl->netchan.rate = 1.0/i;
+	}
+
+	// msg command
+	val = Info_ValueForKey (cl->userinfo, "msg");
+	if (strlen(val))
+	{
+		cl->messagelevel = atoi(val);
+	}
+
+}
+
+
+//============================================================================
+
+/*
+====================
+SV_InitNet
+====================
+*/
+void SV_InitNet (void)
+{
+	int	port;
+	int	p;
+
+	port = PORT_SERVER;
+	p = COM_CheckParm ("-port");
+	if (p && p < com_argc)
+	{
+		port = atoi(com_argv[p+1]);
+		Con_Printf ("Port: %i\n", port);
+	}
+	NET_Init (port);
+
+	Netchan_Init ();
+
+	// heartbeats will allways be sent to the id master
+	svs.last_heartbeat = -99999;		// send immediately
+//	NET_StringToAdr ("192.246.40.70:27000", &idmaster_adr);
+}
+
+
+/*
+====================
+SV_Init
+====================
+*/
+void SV_Init (quakeparms_t *parms)
+{
+	COM_InitArgv (parms->argc, parms->argv);
+	COM_AddParm ("-game");
+	COM_AddParm ("qw");
+
+	if (COM_CheckParm ("-minmemory"))
+		parms->memsize = MINIMUM_MEMORY;
+
+	host_parms = *parms;
+
+	if (parms->memsize < MINIMUM_MEMORY)
+		SV_Error ("Only %4.1f megs of memory reported, can't execute game", parms->memsize / (float)0x100000);
+
+	Memory_Init (parms->membase, parms->memsize);
+	Cbuf_Init ();
+	Cmd_Init ();	
+
+	COM_Init ();
+	
+	PR_Init ();
+	Mod_Init ();
+
+	SV_InitNet ();
+
+	SV_InitLocal ();
+	Sys_Init ();
+	Pmove_Init ();
+
+	Hunk_AllocName (0, "-HOST_HUNKLEVEL-");
+	host_hunklevel = Hunk_LowMark ();
+
+	Cbuf_InsertText ("exec server.cfg\n");
+
+	host_initialized = true;
+	
+	Con_Printf ("Exe: "__TIME__" "__DATE__"\n");
+	Con_Printf ("%4.1f megabyte heap\n",parms->memsize/ (1024*1024.0));	
+
+	Con_Printf ("\nServer Version %4.2f (Build %04d)\n\n", VERSION, build_number());
+
+	Con_Printf ("======== QuakeWorld Initialized ========\n");
+	
+// process command line arguments
+	Cmd_StuffCmds_f ();
+	Cbuf_Execute ();
+
+// if a map wasn't specified on the command line, spawn start.map
+	if (sv.state == ss_dead)
+		Cmd_ExecuteString ("map start");
+	if (sv.state == ss_dead)
+		SV_Error ("Couldn't spawn a server");
+}
--- /dev/null
+++ b/QW/server/sv_move.c
@@ -1,0 +1,419 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// sv_move.c -- monster movement
+
+#include "qwsvdef.h"
+
+#define	STEPSIZE	18
+
+/*
+=============
+SV_CheckBottom
+
+Returns false if any part of the bottom of the entity is off an edge that
+is not a staircase.
+
+=============
+*/
+int c_yes, c_no;
+
+qboolean SV_CheckBottom (edict_t *ent)
+{
+	vec3_t	mins, maxs, start, stop;
+	trace_t	trace;
+	int		x, y;
+	float	mid, bottom;
+	
+	VectorAdd (ent->v.origin, ent->v.mins, mins);
+	VectorAdd (ent->v.origin, ent->v.maxs, maxs);
+
+// if all of the points under the corners are solid world, don't bother
+// with the tougher checks
+// the corners must be within 16 of the midpoint
+	start[2] = mins[2] - 1;
+	for	(x=0 ; x<=1 ; x++)
+		for	(y=0 ; y<=1 ; y++)
+		{
+			start[0] = x ? maxs[0] : mins[0];
+			start[1] = y ? maxs[1] : mins[1];
+			if (SV_PointContents (start) != CONTENTS_SOLID)
+				goto realcheck;
+		}
+
+	c_yes++;
+	return true;		// we got out easy
+
+realcheck:
+	c_no++;
+//
+// check it for real...
+//
+	start[2] = mins[2];
+	
+// the midpoint must be within 16 of the bottom
+	start[0] = stop[0] = (mins[0] + maxs[0])*0.5;
+	start[1] = stop[1] = (mins[1] + maxs[1])*0.5;
+	stop[2] = start[2] - 2*STEPSIZE;
+	trace = SV_Move (start, vec3_origin, vec3_origin, stop, true, ent);
+
+	if (trace.fraction == 1.0)
+		return false;
+	mid = bottom = trace.endpos[2];
+	
+// the corners must be within 16 of the midpoint	
+	for	(x=0 ; x<=1 ; x++)
+		for	(y=0 ; y<=1 ; y++)
+		{
+			start[0] = stop[0] = x ? maxs[0] : mins[0];
+			start[1] = stop[1] = y ? maxs[1] : mins[1];
+			
+			trace = SV_Move (start, vec3_origin, vec3_origin, stop, true, ent);
+			
+			if (trace.fraction != 1.0 && trace.endpos[2] > bottom)
+				bottom = trace.endpos[2];
+			if (trace.fraction == 1.0 || mid - trace.endpos[2] > STEPSIZE)
+				return false;
+		}
+
+	c_yes++;
+	return true;
+}
+
+
+/*
+=============
+SV_movestep
+
+Called by monster program code.
+The move will be adjusted for slopes and stairs, but if the move isn't
+possible, no move is done, false is returned, and
+pr_global_struct->trace_normal is set to the normal of the blocking wall
+=============
+*/
+qboolean SV_movestep (edict_t *ent, vec3_t move, qboolean relink)
+{
+	float		dz;
+	vec3_t		oldorg, neworg, end;
+	trace_t		trace;
+	int			i;
+	edict_t		*enemy;
+
+// try the move	
+	VectorCopy (ent->v.origin, oldorg);
+	VectorAdd (ent->v.origin, move, neworg);
+
+// flying monsters don't step up
+	if ( (int)ent->v.flags & (FL_SWIM | FL_FLY) )
+	{
+	// try one move with vertical motion, then one without
+		for (i=0 ; i<2 ; i++)
+		{
+			VectorAdd (ent->v.origin, move, neworg);
+			enemy = PROG_TO_EDICT(ent->v.enemy);
+			if (i == 0 && enemy != sv.edicts)
+			{
+				dz = ent->v.origin[2] - PROG_TO_EDICT(ent->v.enemy)->v.origin[2];
+				if (dz > 40)
+					neworg[2] -= 8;
+				if (dz < 30)
+					neworg[2] += 8;
+			}
+			trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, neworg, false, ent);
+	
+			if (trace.fraction == 1)
+			{
+				if ( ((int)ent->v.flags & FL_SWIM) && SV_PointContents(trace.endpos) == CONTENTS_EMPTY )
+					return false;	// swim monster left water
+	
+				VectorCopy (trace.endpos, ent->v.origin);
+				if (relink)
+					SV_LinkEdict (ent, true);
+				return true;
+			}
+			
+			if (enemy == sv.edicts)
+				break;
+		}
+		
+		return false;
+	}
+
+// push down from a step height above the wished position
+	neworg[2] += STEPSIZE;
+	VectorCopy (neworg, end);
+	end[2] -= STEPSIZE*2;
+
+	trace = SV_Move (neworg, ent->v.mins, ent->v.maxs, end, false, ent);
+
+	if (trace.allsolid)
+		return false;
+
+	if (trace.startsolid)
+	{
+		neworg[2] -= STEPSIZE;
+		trace = SV_Move (neworg, ent->v.mins, ent->v.maxs, end, false, ent);
+		if (trace.allsolid || trace.startsolid)
+			return false;
+	}
+	if (trace.fraction == 1)
+	{
+	// if monster had the ground pulled out, go ahead and fall
+		if ( (int)ent->v.flags & FL_PARTIALGROUND )
+		{
+			VectorAdd (ent->v.origin, move, ent->v.origin);
+			if (relink)
+				SV_LinkEdict (ent, true);
+			ent->v.flags = (int)ent->v.flags & ~FL_ONGROUND;
+//	Con_Printf ("fall down\n"); 
+			return true;
+		}
+	
+		return false;		// walked off an edge
+	}
+
+// check point traces down for dangling corners
+	VectorCopy (trace.endpos, ent->v.origin);
+	
+	if (!SV_CheckBottom (ent))
+	{
+		if ( (int)ent->v.flags & FL_PARTIALGROUND )
+		{	// entity had floor mostly pulled out from underneath it
+			// and is trying to correct
+			if (relink)
+				SV_LinkEdict (ent, true);
+			return true;
+		}
+		VectorCopy (oldorg, ent->v.origin);
+		return false;
+	}
+
+	if ( (int)ent->v.flags & FL_PARTIALGROUND )
+	{
+//		Con_Printf ("back on ground\n"); 
+		ent->v.flags = (int)ent->v.flags & ~FL_PARTIALGROUND;
+	}
+	ent->v.groundentity = EDICT_TO_PROG(trace.ent);
+
+// the move is ok
+	if (relink)
+		SV_LinkEdict (ent, true);
+	return true;
+}
+
+
+//============================================================================
+
+/*
+======================
+SV_StepDirection
+
+Turns to the movement direction, and walks the current distance if
+facing it.
+
+======================
+*/
+void PF_changeyaw (void);
+qboolean SV_StepDirection (edict_t *ent, float yaw, float dist)
+{
+	vec3_t		move, oldorigin;
+	float		delta;
+	
+	ent->v.ideal_yaw = yaw;
+	PF_changeyaw();
+	
+	yaw = yaw*M_PI*2 / 360;
+	move[0] = cos(yaw)*dist;
+	move[1] = sin(yaw)*dist;
+	move[2] = 0;
+
+	VectorCopy (ent->v.origin, oldorigin);
+	if (SV_movestep (ent, move, false))
+	{
+		delta = ent->v.angles[YAW] - ent->v.ideal_yaw;
+		if (delta > 45 && delta < 315)
+		{		// not turned far enough, so don't take the step
+			VectorCopy (oldorigin, ent->v.origin);
+		}
+		SV_LinkEdict (ent, true);
+		return true;
+	}
+	SV_LinkEdict (ent, true);
+		
+	return false;
+}
+
+/*
+======================
+SV_FixCheckBottom
+
+======================
+*/
+void SV_FixCheckBottom (edict_t *ent)
+{
+//	Con_Printf ("SV_FixCheckBottom\n");
+	
+	ent->v.flags = (int)ent->v.flags | FL_PARTIALGROUND;
+}
+
+
+
+/*
+================
+SV_NewChaseDir
+
+================
+*/
+#define	DI_NODIR	-1
+void SV_NewChaseDir (edict_t *actor, edict_t *enemy, float dist)
+{
+	float		deltax,deltay;
+	float			d[3];
+	float		tdir, olddir, turnaround;
+
+	olddir = anglemod( (int)(actor->v.ideal_yaw/45)*45 );
+	turnaround = anglemod(olddir - 180);
+
+	deltax = enemy->v.origin[0] - actor->v.origin[0];
+	deltay = enemy->v.origin[1] - actor->v.origin[1];
+	if (deltax>10)
+		d[1]= 0;
+	else if (deltax<-10)
+		d[1]= 180;
+	else
+		d[1]= DI_NODIR;
+	if (deltay<-10)
+		d[2]= 270;
+	else if (deltay>10)
+		d[2]= 90;
+	else
+		d[2]= DI_NODIR;
+
+// try direct route
+	if (d[1] != DI_NODIR && d[2] != DI_NODIR)
+	{
+		if (d[1] == 0)
+			tdir = d[2] == 90 ? 45 : 315;
+		else
+			tdir = d[2] == 90 ? 135 : 215;
+			
+		if (tdir != turnaround && SV_StepDirection(actor, tdir, dist))
+			return;
+	}
+
+// try other directions
+	if ( ((rand()&3) & 1) ||  abs(deltay)>abs(deltax))
+	{
+		tdir=d[1];
+		d[1]=d[2];
+		d[2]=tdir;
+	}
+
+	if (d[1]!=DI_NODIR && d[1]!=turnaround 
+	&& SV_StepDirection(actor, d[1], dist))
+			return;
+
+	if (d[2]!=DI_NODIR && d[2]!=turnaround
+	&& SV_StepDirection(actor, d[2], dist))
+			return;
+
+/* there is no direct path to the player, so pick another direction */
+
+	if (olddir!=DI_NODIR && SV_StepDirection(actor, olddir, dist))
+			return;
+
+	if (rand()&1) 	/*randomly determine direction of search*/
+	{
+		for (tdir=0 ; tdir<=315 ; tdir += 45)
+			if (tdir!=turnaround && SV_StepDirection(actor, tdir, dist) )
+					return;
+	}
+	else
+	{
+		for (tdir=315 ; tdir >=0 ; tdir -= 45)
+			if (tdir!=turnaround && SV_StepDirection(actor, tdir, dist) )
+					return;
+	}
+
+	if (turnaround != DI_NODIR && SV_StepDirection(actor, turnaround, dist) )
+			return;
+
+	actor->v.ideal_yaw = olddir;		// can't move
+
+// if a bridge was pulled out from underneath a monster, it may not have
+// a valid standing position at all
+
+	if (!SV_CheckBottom (actor))
+		SV_FixCheckBottom (actor);
+
+}
+
+/*
+======================
+SV_CloseEnough
+
+======================
+*/
+qboolean SV_CloseEnough (edict_t *ent, edict_t *goal, float dist)
+{
+	int		i;
+	
+	for (i=0 ; i<3 ; i++)
+	{
+		if (goal->v.absmin[i] > ent->v.absmax[i] + dist)
+			return false;
+		if (goal->v.absmax[i] < ent->v.absmin[i] - dist)
+			return false;
+	}
+	return true;
+}
+
+/*
+======================
+SV_MoveToGoal
+
+======================
+*/
+void SV_MoveToGoal (void)
+{
+	edict_t		*ent, *goal;
+	float		dist;
+	
+	ent = PROG_TO_EDICT(pr_global_struct->self);
+	goal = PROG_TO_EDICT(ent->v.goalentity);
+	dist = G_FLOAT(OFS_PARM0);
+
+	if ( !( (int)ent->v.flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
+	{
+		G_FLOAT(OFS_RETURN) = 0;
+		return;
+	}
+
+// if the next step hits the enemy, return immediately
+	if ( PROG_TO_EDICT(ent->v.enemy) != sv.edicts &&  SV_CloseEnough (ent, goal, dist) )
+		return;
+
+// bump around...
+	if ( (rand()&3)==1 ||
+	!SV_StepDirection (ent, ent->v.ideal_yaw, dist))
+	{
+		SV_NewChaseDir (ent, goal, dist);
+	}
+}
+
--- /dev/null
+++ b/QW/server/sv_nchan.c
@@ -1,0 +1,165 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// sv_nchan.c, user reliable data stream writes
+
+#include "qwsvdef.h"
+
+// check to see if client block will fit, if not, rotate buffers
+void ClientReliableCheckBlock(client_t *cl, int maxsize)
+{
+	if (cl->num_backbuf ||
+		cl->netchan.message.cursize > 
+		cl->netchan.message.maxsize - maxsize - 1) {
+		// we would probably overflow the buffer, save it for next
+		if (!cl->num_backbuf) {
+			memset(&cl->backbuf, 0, sizeof(cl->backbuf));
+			cl->backbuf.allowoverflow = true;
+			cl->backbuf.data = cl->backbuf_data[0];
+			cl->backbuf.maxsize = sizeof(cl->backbuf_data[0]);
+			cl->backbuf_size[0] = 0;
+			cl->num_backbuf++;
+		}
+
+		if (cl->backbuf.cursize > cl->backbuf.maxsize - maxsize - 1) {
+			if (cl->num_backbuf == MAX_BACK_BUFFERS) {
+				Con_Printf ("WARNING: MAX_BACK_BUFFERS for %s\n", cl->name);
+				cl->backbuf.cursize = 0; // don't overflow without allowoverflow set
+				cl->netchan.message.overflowed = true; // this will drop the client
+				return;
+			}
+			memset(&cl->backbuf, 0, sizeof(cl->backbuf));
+			cl->backbuf.allowoverflow = true;
+			cl->backbuf.data = cl->backbuf_data[cl->num_backbuf];
+			cl->backbuf.maxsize = sizeof(cl->backbuf_data[cl->num_backbuf]);
+			cl->backbuf_size[cl->num_backbuf] = 0;
+			cl->num_backbuf++;
+		}
+	}
+}
+
+// begin a client block, estimated maximum size
+void ClientReliableWrite_Begin(client_t *cl, int c, int maxsize)
+{
+	ClientReliableCheckBlock(cl, maxsize);
+	ClientReliableWrite_Byte(cl, c);
+}
+
+void ClientReliable_FinishWrite(client_t *cl)
+{
+	if (cl->num_backbuf) {
+		cl->backbuf_size[cl->num_backbuf - 1] = cl->backbuf.cursize;
+
+		if (cl->backbuf.overflowed) {
+			Con_Printf ("WARNING: backbuf [%d] reliable overflow for %s\n",cl->num_backbuf,cl->name);
+			cl->netchan.message.overflowed = true; // this will drop the client
+		}
+	}
+}
+
+void ClientReliableWrite_Angle(client_t *cl, float f)
+{
+	if (cl->num_backbuf) {
+		MSG_WriteAngle(&cl->backbuf, f);
+		ClientReliable_FinishWrite(cl);
+	} else
+		MSG_WriteAngle(&cl->netchan.message, f);
+}
+
+void ClientReliableWrite_Angle16(client_t *cl, float f)
+{
+	if (cl->num_backbuf) {
+		MSG_WriteAngle16(&cl->backbuf, f);
+		ClientReliable_FinishWrite(cl);
+	} else
+		MSG_WriteAngle16(&cl->netchan.message, f);
+}
+
+void ClientReliableWrite_Byte(client_t *cl, int c)
+{
+	if (cl->num_backbuf) {
+		MSG_WriteByte(&cl->backbuf, c);
+		ClientReliable_FinishWrite(cl);
+	} else
+		MSG_WriteByte(&cl->netchan.message, c);
+}
+
+void ClientReliableWrite_Char(client_t *cl, int c)
+{
+	if (cl->num_backbuf) {
+		MSG_WriteChar(&cl->backbuf, c);
+		ClientReliable_FinishWrite(cl);
+	} else
+		MSG_WriteChar(&cl->netchan.message, c);
+}
+
+void ClientReliableWrite_Float(client_t *cl, float f)
+{
+	if (cl->num_backbuf) {
+		MSG_WriteFloat(&cl->backbuf, f);
+		ClientReliable_FinishWrite(cl);
+	} else
+		MSG_WriteFloat(&cl->netchan.message, f);
+}
+
+void ClientReliableWrite_Coord(client_t *cl, float f)
+{
+	if (cl->num_backbuf) {
+		MSG_WriteCoord(&cl->backbuf, f);
+		ClientReliable_FinishWrite(cl);
+	} else
+		MSG_WriteCoord(&cl->netchan.message, f);
+}
+
+void ClientReliableWrite_Long(client_t *cl, int c)
+{
+	if (cl->num_backbuf) {
+		MSG_WriteLong(&cl->backbuf, c);
+		ClientReliable_FinishWrite(cl);
+	} else
+		MSG_WriteLong(&cl->netchan.message, c);
+}
+
+void ClientReliableWrite_Short(client_t *cl, int c)
+{
+	if (cl->num_backbuf) {
+		MSG_WriteShort(&cl->backbuf, c);
+		ClientReliable_FinishWrite(cl);
+	} else
+		MSG_WriteShort(&cl->netchan.message, c);
+}
+
+void ClientReliableWrite_String(client_t *cl, char *s)
+{
+	if (cl->num_backbuf) {
+		MSG_WriteString(&cl->backbuf, s);
+		ClientReliable_FinishWrite(cl);
+	} else
+		MSG_WriteString(&cl->netchan.message, s);
+}
+
+void ClientReliableWrite_SZ(client_t *cl, void *data, int len)
+{
+	if (cl->num_backbuf) {
+		SZ_Write(&cl->backbuf, data, len);
+		ClientReliable_FinishWrite(cl);
+	} else
+		SZ_Write(&cl->netchan.message, data, len);
+}
+
--- /dev/null
+++ b/QW/server/sv_phys.c
@@ -1,0 +1,947 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// sv_phys.c
+
+#include "qwsvdef.h"
+
+/*
+
+
+pushmove objects do not obey gravity, and do not interact with each other or trigger fields, but block normal movement and push normal objects when they move.
+
+onground is set for toss objects when they come to a complete rest.  it is set for steping or walking objects 
+
+doors, plats, etc are SOLID_BSP, and MOVETYPE_PUSH
+bonus items are SOLID_TRIGGER touch, and MOVETYPE_TOSS
+corpses are SOLID_NOT and MOVETYPE_TOSS
+crates are SOLID_BBOX and MOVETYPE_TOSS
+walking monsters are SOLID_SLIDEBOX and MOVETYPE_STEP
+flying/floating monsters are SOLID_SLIDEBOX and MOVETYPE_FLY
+
+solid_edge items only clip against bsp models.
+
+*/
+
+cvar_t	sv_maxvelocity = {"sv_maxvelocity","2000"}; 
+
+cvar_t	sv_gravity			 = { "sv_gravity", "800"};    
+cvar_t	sv_stopspeed		 = { "sv_stopspeed", "100"};    
+cvar_t	sv_maxspeed			 = { "sv_maxspeed", "320"};    
+cvar_t	sv_spectatormaxspeed = { "sv_spectatormaxspeed", "500"};
+cvar_t	sv_accelerate		 = { "sv_accelerate", "10"};     
+cvar_t	sv_airaccelerate	 = { "sv_airaccelerate", "0.7"};    
+cvar_t	sv_wateraccelerate	 = { "sv_wateraccelerate", "10"};     
+cvar_t	sv_friction			 = { "sv_friction", "4"};      
+cvar_t	sv_waterfriction	 = { "sv_waterfriction", "4"};      
+
+
+#define	MOVE_EPSILON	0.01
+
+void SV_Physics_Toss (edict_t *ent);
+
+/*
+================
+SV_CheckAllEnts
+================
+*/
+void SV_CheckAllEnts (void)
+{
+	int			e;
+	edict_t		*check;
+
+// see if any solid entities are inside the final position
+	check = NEXT_EDICT(sv.edicts);
+	for (e=1 ; e<sv.num_edicts ; e++, check = NEXT_EDICT(check))
+	{
+		if (check->free)
+			continue;
+		if (check->v.movetype == MOVETYPE_PUSH
+		|| check->v.movetype == MOVETYPE_NONE
+		|| check->v.movetype == MOVETYPE_NOCLIP)
+			continue;
+
+		if (SV_TestEntityPosition (check))
+			Con_Printf ("entity in invalid position\n");
+	}
+}
+
+/*
+================
+SV_CheckVelocity
+================
+*/
+void SV_CheckVelocity (edict_t *ent)
+{
+	int		i;
+
+//
+// bound velocity
+//
+	for (i=0 ; i<3 ; i++)
+	{
+		if (IS_NAN(ent->v.velocity[i]))
+		{
+			Con_Printf ("Got a NaN velocity on %s\n", PR_GetString(ent->v.classname));
+			ent->v.velocity[i] = 0;
+		}
+		if (IS_NAN(ent->v.origin[i]))
+		{
+			Con_Printf ("Got a NaN origin on %s\n", PR_GetString(ent->v.classname));
+			ent->v.origin[i] = 0;
+		}
+		if (ent->v.velocity[i] > sv_maxvelocity.value)
+			ent->v.velocity[i] = sv_maxvelocity.value;
+		else if (ent->v.velocity[i] < -sv_maxvelocity.value)
+			ent->v.velocity[i] = -sv_maxvelocity.value;
+	}
+}
+
+/*
+=============
+SV_RunThink
+
+Runs thinking code if time.  There is some play in the exact time the think
+function will be called, because it is called before any movement is done
+in a frame.  Not used for pushmove objects, because they must be exact.
+Returns false if the entity removed itself.
+=============
+*/
+qboolean SV_RunThink (edict_t *ent)
+{
+	float	thinktime;
+
+	do
+	{
+		thinktime = ent->v.nextthink;
+		if (thinktime <= 0)
+			return true;
+		if (thinktime > sv.time + host_frametime)
+			return true;
+		
+		if (thinktime < sv.time)
+			thinktime = sv.time;	// don't let things stay in the past.
+									// it is possible to start that way
+									// by a trigger with a local time.
+		ent->v.nextthink = 0;
+		pr_global_struct->time = thinktime;
+		pr_global_struct->self = EDICT_TO_PROG(ent);
+		pr_global_struct->other = EDICT_TO_PROG(sv.edicts);
+		PR_ExecuteProgram (ent->v.think);
+
+		if (ent->free)
+			return false;
+	} while (1);
+
+	return true;
+}
+
+/*
+==================
+SV_Impact
+
+Two entities have touched, so run their touch functions
+==================
+*/
+void SV_Impact (edict_t *e1, edict_t *e2)
+{
+	int		old_self, old_other;
+	
+	old_self = pr_global_struct->self;
+	old_other = pr_global_struct->other;
+	
+	pr_global_struct->time = sv.time;
+	if (e1->v.touch && e1->v.solid != SOLID_NOT)
+	{
+		pr_global_struct->self = EDICT_TO_PROG(e1);
+		pr_global_struct->other = EDICT_TO_PROG(e2);
+		PR_ExecuteProgram (e1->v.touch);
+	}
+	
+	if (e2->v.touch && e2->v.solid != SOLID_NOT)
+	{
+		pr_global_struct->self = EDICT_TO_PROG(e2);
+		pr_global_struct->other = EDICT_TO_PROG(e1);
+		PR_ExecuteProgram (e2->v.touch);
+	}
+
+	pr_global_struct->self = old_self;
+	pr_global_struct->other = old_other;
+}
+
+
+/*
+==================
+ClipVelocity
+
+Slide off of the impacting object
+returns the blocked flags (1 = floor, 2 = step / wall)
+==================
+*/
+#define	STOP_EPSILON	0.1
+
+int ClipVelocity (vec3_t in, vec3_t normal, vec3_t out, float overbounce)
+{
+	float	backoff;
+	float	change;
+	int		i, blocked;
+	
+	blocked = 0;
+	if (normal[2] > 0)
+		blocked |= 1;		// floor
+	if (!normal[2])
+		blocked |= 2;		// step
+	
+	backoff = DotProduct (in, normal) * overbounce;
+
+	for (i=0 ; i<3 ; i++)
+	{
+		change = normal[i]*backoff;
+		out[i] = in[i] - change;
+		if (out[i] > -STOP_EPSILON && out[i] < STOP_EPSILON)
+			out[i] = 0;
+	}
+	
+	return blocked;
+}
+
+
+/*
+============
+SV_FlyMove
+
+The basic solid body movement clip that slides along multiple planes
+Returns the clipflags if the velocity was modified (hit something solid)
+1 = floor
+2 = wall / step
+4 = dead stop
+If steptrace is not NULL, the trace of any vertical wall hit will be stored
+============
+*/
+#define	MAX_CLIP_PLANES	5
+int SV_FlyMove (edict_t *ent, float time, trace_t *steptrace)
+{
+	int			bumpcount, numbumps;
+	vec3_t		dir;
+	float		d;
+	int			numplanes;
+	vec3_t		planes[MAX_CLIP_PLANES];
+	vec3_t		primal_velocity, original_velocity, new_velocity;
+	int			i, j;
+	trace_t		trace;
+	vec3_t		end;
+	float		time_left;
+	int			blocked;
+	
+	numbumps = 4;
+	
+	blocked = 0;
+	VectorCopy (ent->v.velocity, original_velocity);
+	VectorCopy (ent->v.velocity, primal_velocity);
+	numplanes = 0;
+	
+	time_left = time;
+
+	for (bumpcount=0 ; bumpcount<numbumps ; bumpcount++)
+	{
+		for (i=0 ; i<3 ; i++)
+			end[i] = ent->v.origin[i] + time_left * ent->v.velocity[i];
+
+		trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, end, false, ent);
+
+		if (trace.allsolid)
+		{	// entity is trapped in another solid
+			VectorCopy (vec3_origin, ent->v.velocity);
+			return 3;
+		}
+
+		if (trace.fraction > 0)
+		{	// actually covered some distance
+			VectorCopy (trace.endpos, ent->v.origin);
+			VectorCopy (ent->v.velocity, original_velocity);
+			numplanes = 0;
+		}
+
+		if (trace.fraction == 1)
+			 break;		// moved the entire distance
+
+		if (!trace.ent)
+			SV_Error ("SV_FlyMove: !trace.ent");
+
+		if (trace.plane.normal[2] > 0.7)
+		{
+			blocked |= 1;		// floor
+			if (trace.ent->v.solid == SOLID_BSP)
+			{
+				ent->v.flags =	(int)ent->v.flags | FL_ONGROUND;
+				ent->v.groundentity = EDICT_TO_PROG(trace.ent);
+			}
+		}
+		if (!trace.plane.normal[2])
+		{
+			blocked |= 2;		// step
+			if (steptrace)
+				*steptrace = trace;	// save for player extrafriction
+		}
+
+//
+// run the impact function
+//
+		SV_Impact (ent, trace.ent);
+		if (ent->free)
+			break;		// removed by the impact function
+
+		
+		time_left -= time_left * trace.fraction;
+		
+	// cliped to another plane
+		if (numplanes >= MAX_CLIP_PLANES)
+		{	// this shouldn't really happen
+			VectorCopy (vec3_origin, ent->v.velocity);
+			return 3;
+		}
+
+		VectorCopy (trace.plane.normal, planes[numplanes]);
+		numplanes++;
+
+//
+// modify original_velocity so it parallels all of the clip planes
+//
+		for (i=0 ; i<numplanes ; i++)
+		{
+			ClipVelocity (original_velocity, planes[i], new_velocity, 1);
+			for (j=0 ; j<numplanes ; j++)
+				if (j != i)
+				{
+					if (DotProduct (new_velocity, planes[j]) < 0)
+						break;	// not ok
+				}
+			if (j == numplanes)
+				break;
+		}
+		
+		if (i != numplanes)
+		{	// go along this plane
+			VectorCopy (new_velocity, ent->v.velocity);
+		}
+		else
+		{	// go along the crease
+			if (numplanes != 2)
+			{
+//				Con_Printf ("clip velocity, numplanes == %i\n",numplanes);
+				VectorCopy (vec3_origin, ent->v.velocity);
+				return 7;
+			}
+			CrossProduct (planes[0], planes[1], dir);
+			d = DotProduct (dir, ent->v.velocity);
+			VectorScale (dir, d, ent->v.velocity);
+		}
+
+//
+// if original velocity is against the original velocity, stop dead
+// to avoid tiny occilations in sloping corners
+//
+		if (DotProduct (ent->v.velocity, primal_velocity) <= 0)
+		{
+			VectorCopy (vec3_origin, ent->v.velocity);
+			return blocked;
+		}
+	}
+
+	return blocked;
+}
+
+
+/*
+============
+SV_AddGravity
+
+============
+*/
+void SV_AddGravity (edict_t *ent, float scale)
+{
+	ent->v.velocity[2] -= scale * movevars.gravity * host_frametime;
+}
+
+/*
+===============================================================================
+
+PUSHMOVE
+
+===============================================================================
+*/
+
+/*
+============
+SV_PushEntity
+
+Does not change the entities velocity at all
+============
+*/
+trace_t SV_PushEntity (edict_t *ent, vec3_t push)
+{
+	trace_t	trace;
+	vec3_t	end;
+		
+	VectorAdd (ent->v.origin, push, end);
+
+	if (ent->v.movetype == MOVETYPE_FLYMISSILE)
+		trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, end, MOVE_MISSILE, ent);
+	else if (ent->v.solid == SOLID_TRIGGER || ent->v.solid == SOLID_NOT)
+	// only clip against bmodels
+		trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, end, MOVE_NOMONSTERS, ent);
+	else
+		trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, end, MOVE_NORMAL, ent);
+	
+	VectorCopy (trace.endpos, ent->v.origin);
+	SV_LinkEdict (ent, true);
+
+	if (trace.ent)
+		SV_Impact (ent, trace.ent);		
+
+	return trace;
+}					
+
+
+/*
+============
+SV_Push
+
+============
+*/
+qboolean SV_Push (edict_t *pusher, vec3_t move)
+{
+	int			i, e;
+	edict_t		*check, *block;
+	vec3_t		mins, maxs;
+	vec3_t		pushorig;
+	int			num_moved;
+	edict_t		*moved_edict[MAX_EDICTS];
+	vec3_t		moved_from[MAX_EDICTS];
+
+	for (i=0 ; i<3 ; i++)
+	{
+		mins[i] = pusher->v.absmin[i] + move[i];
+		maxs[i] = pusher->v.absmax[i] + move[i];
+	}
+
+	VectorCopy (pusher->v.origin, pushorig);
+	
+// move the pusher to it's final position
+
+	VectorAdd (pusher->v.origin, move, pusher->v.origin);
+	SV_LinkEdict (pusher, false);
+
+// see if any solid entities are inside the final position
+	num_moved = 0;
+	check = NEXT_EDICT(sv.edicts);
+	for (e=1 ; e<sv.num_edicts ; e++, check = NEXT_EDICT(check))
+	{
+		if (check->free)
+			continue;
+		if (check->v.movetype == MOVETYPE_PUSH
+		|| check->v.movetype == MOVETYPE_NONE
+		|| check->v.movetype == MOVETYPE_NOCLIP)
+			continue;
+
+		pusher->v.solid = SOLID_NOT;
+		block = SV_TestEntityPosition (check);
+		pusher->v.solid = SOLID_BSP;
+		if (block)
+			continue;
+
+	// if the entity is standing on the pusher, it will definately be moved
+		if ( ! ( ((int)check->v.flags & FL_ONGROUND)
+		&& PROG_TO_EDICT(check->v.groundentity) == pusher) )
+		{
+			if ( check->v.absmin[0] >= maxs[0]
+			|| check->v.absmin[1] >= maxs[1]
+			|| check->v.absmin[2] >= maxs[2]
+			|| check->v.absmax[0] <= mins[0]
+			|| check->v.absmax[1] <= mins[1]
+			|| check->v.absmax[2] <= mins[2] )
+				continue;
+
+		// see if the ent's bbox is inside the pusher's final position
+			if (!SV_TestEntityPosition (check))
+				continue;
+		}
+
+		VectorCopy (check->v.origin, moved_from[num_moved]);
+		moved_edict[num_moved] = check;
+		num_moved++;
+
+		// try moving the contacted entity 
+		VectorAdd (check->v.origin, move, check->v.origin);
+		block = SV_TestEntityPosition (check);
+		if (!block)
+		{	// pushed ok
+			SV_LinkEdict (check, false);
+			continue;
+		}
+
+		// if it is ok to leave in the old position, do it
+		VectorSubtract (check->v.origin, move, check->v.origin);
+		block = SV_TestEntityPosition (check);
+		if (!block)
+		{
+			num_moved--;
+			continue;
+		}
+
+	// if it is still inside the pusher, block
+		if (check->v.mins[0] == check->v.maxs[0])
+		{
+			SV_LinkEdict (check, false);
+			continue;
+		}
+		if (check->v.solid == SOLID_NOT || check->v.solid == SOLID_TRIGGER)
+		{	// corpse
+			check->v.mins[0] = check->v.mins[1] = 0;
+			VectorCopy (check->v.mins, check->v.maxs);
+			SV_LinkEdict (check, false);
+			continue;
+		}
+		
+		VectorCopy (pushorig, pusher->v.origin);
+		SV_LinkEdict (pusher, false);
+
+		// if the pusher has a "blocked" function, call it
+		// otherwise, just stay in place until the obstacle is gone
+		if (pusher->v.blocked)
+		{
+			pr_global_struct->self = EDICT_TO_PROG(pusher);
+			pr_global_struct->other = EDICT_TO_PROG(check);
+			PR_ExecuteProgram (pusher->v.blocked);
+		}
+		
+	// move back any entities we already moved
+		for (i=0 ; i<num_moved ; i++)
+		{
+			VectorCopy (moved_from[i], moved_edict[i]->v.origin);
+			SV_LinkEdict (moved_edict[i], false);
+		}
+		return false;
+	}
+
+	return true;
+}
+
+/*
+============
+SV_PushMove
+
+============
+*/
+void SV_PushMove (edict_t *pusher, float movetime)
+{
+	int			i;
+	vec3_t		move;
+
+	if (!pusher->v.velocity[0] && !pusher->v.velocity[1] && !pusher->v.velocity[2])
+	{
+		pusher->v.ltime += movetime;
+		return;
+	}
+
+	for (i=0 ; i<3 ; i++)
+		move[i] = pusher->v.velocity[i] * movetime;
+
+	if (SV_Push (pusher, move))
+		pusher->v.ltime += movetime;
+}
+
+
+/*
+================
+SV_Physics_Pusher
+
+================
+*/
+void SV_Physics_Pusher (edict_t *ent)
+{
+	float	thinktime;
+	float	oldltime;
+	float	movetime;
+vec3_t oldorg, move;
+float	l;
+
+	oldltime = ent->v.ltime;
+	
+	thinktime = ent->v.nextthink;
+	if (thinktime < ent->v.ltime + host_frametime)
+	{
+		movetime = thinktime - ent->v.ltime;
+		if (movetime < 0)
+			movetime = 0;
+	}
+	else
+		movetime = host_frametime;
+
+	if (movetime)
+	{
+		SV_PushMove (ent, movetime);	// advances ent->v.ltime if not blocked
+	}
+		
+	if (thinktime > oldltime && thinktime <= ent->v.ltime)
+	{
+VectorCopy (ent->v.origin, oldorg);
+		ent->v.nextthink = 0;
+		pr_global_struct->time = sv.time;
+		pr_global_struct->self = EDICT_TO_PROG(ent);
+		pr_global_struct->other = EDICT_TO_PROG(sv.edicts);
+		PR_ExecuteProgram (ent->v.think);
+		if (ent->free)
+			return;
+VectorSubtract (ent->v.origin, oldorg, move);
+
+l = Length(move);
+if (l > 1.0/64)
+{
+//	Con_Printf ("**** snap: %f\n", Length (l));
+	VectorCopy (oldorg, ent->v.origin);
+	SV_Push (ent, move);
+}
+
+	}
+
+}
+
+
+/*
+=============
+SV_Physics_None
+
+Non moving objects can only think
+=============
+*/
+void SV_Physics_None (edict_t *ent)
+{
+// regular thinking
+	SV_RunThink (ent);
+}
+
+/*
+=============
+SV_Physics_Noclip
+
+A moving object that doesn't obey physics
+=============
+*/
+void SV_Physics_Noclip (edict_t *ent)
+{
+// regular thinking
+	if (!SV_RunThink (ent))
+		return;
+	
+	VectorMA (ent->v.angles, host_frametime, ent->v.avelocity, ent->v.angles);
+	VectorMA (ent->v.origin, host_frametime, ent->v.velocity, ent->v.origin);
+
+	SV_LinkEdict (ent, false);
+}
+
+/*
+==============================================================================
+
+TOSS / BOUNCE
+
+==============================================================================
+*/
+
+/*
+=============
+SV_CheckWaterTransition
+
+=============
+*/
+void SV_CheckWaterTransition (edict_t *ent)
+{
+	int		cont;
+
+	cont = SV_PointContents (ent->v.origin);
+	if (!ent->v.watertype)
+	{	// just spawned here
+		ent->v.watertype = cont;
+		ent->v.waterlevel = 1;
+		return;
+	}
+	
+	if (cont <= CONTENTS_WATER)
+	{
+		if (ent->v.watertype == CONTENTS_EMPTY)
+		{	// just crossed into water
+			SV_StartSound (ent, 0, "misc/h2ohit1.wav", 255, 1);
+		}		
+		ent->v.watertype = cont;
+		ent->v.waterlevel = 1;
+	}
+	else
+	{
+		if (ent->v.watertype != CONTENTS_EMPTY)
+		{	// just crossed into water
+			SV_StartSound (ent, 0, "misc/h2ohit1.wav", 255, 1);
+		}		
+		ent->v.watertype = CONTENTS_EMPTY;
+		ent->v.waterlevel = cont;
+	}
+}
+
+/*
+=============
+SV_Physics_Toss
+
+Toss, bounce, and fly movement.  When onground, do nothing.
+=============
+*/
+void SV_Physics_Toss (edict_t *ent)
+{
+	trace_t	trace;
+	vec3_t	move;
+	float	backoff;
+
+// regular thinking
+	if (!SV_RunThink (ent))
+		return;
+
+	if (ent->v.velocity[2] > 0)
+		ent->v.flags = (int)ent->v.flags & ~FL_ONGROUND;
+
+// if onground, return without moving
+	if ( ((int)ent->v.flags & FL_ONGROUND) )
+		return;
+
+	SV_CheckVelocity (ent);
+
+// add gravity
+	if (ent->v.movetype != MOVETYPE_FLY
+	&& ent->v.movetype != MOVETYPE_FLYMISSILE)
+		SV_AddGravity (ent, 1.0);
+
+// move angles
+	VectorMA (ent->v.angles, host_frametime, ent->v.avelocity, ent->v.angles);
+
+// move origin
+	VectorScale (ent->v.velocity, host_frametime, move);
+	trace = SV_PushEntity (ent, move);
+	if (trace.fraction == 1)
+		return;
+	if (ent->free)
+		return;
+	
+	if (ent->v.movetype == MOVETYPE_BOUNCE)
+		backoff = 1.5;
+	else
+		backoff = 1;
+
+	ClipVelocity (ent->v.velocity, trace.plane.normal, ent->v.velocity, backoff);
+
+// stop if on ground
+	if (trace.plane.normal[2] > 0.7)
+	{		
+		if (ent->v.velocity[2] < 60 || ent->v.movetype != MOVETYPE_BOUNCE )
+		{
+			ent->v.flags = (int)ent->v.flags | FL_ONGROUND;
+			ent->v.groundentity = EDICT_TO_PROG(trace.ent);
+			VectorCopy (vec3_origin, ent->v.velocity);
+			VectorCopy (vec3_origin, ent->v.avelocity);
+		}
+	}
+	
+// check for in water
+	SV_CheckWaterTransition (ent);
+}
+
+/*
+===============================================================================
+
+STEPPING MOVEMENT
+
+===============================================================================
+*/
+
+/*
+=============
+SV_Physics_Step
+
+Monsters freefall when they don't have a ground entity, otherwise
+all movement is done with discrete steps.
+
+This is also used for objects that have become still on the ground, but
+will fall if the floor is pulled out from under them.
+FIXME: is this true?
+=============
+*/
+void SV_Physics_Step (edict_t *ent)
+{
+	qboolean	hitsound;
+
+// frefall if not onground
+	if ( ! ((int)ent->v.flags & (FL_ONGROUND | FL_FLY | FL_SWIM) ) )
+	{
+		if (ent->v.velocity[2] < movevars.gravity*-0.1)
+			hitsound = true;
+		else
+			hitsound = false;
+
+		SV_AddGravity (ent, 1.0);
+		SV_CheckVelocity (ent);
+		SV_FlyMove (ent, host_frametime, NULL);
+		SV_LinkEdict (ent, true);
+
+		if ( (int)ent->v.flags & FL_ONGROUND )	// just hit ground
+		{
+			if (hitsound)
+				SV_StartSound (ent, 0, "demon/dland2.wav", 255, 1);
+		}
+	}
+
+// regular thinking
+	SV_RunThink (ent);
+	
+	SV_CheckWaterTransition (ent);
+}
+
+//============================================================================
+
+void SV_ProgStartFrame (void)
+{
+// let the progs know that a new frame has started
+	pr_global_struct->self = EDICT_TO_PROG(sv.edicts);
+	pr_global_struct->other = EDICT_TO_PROG(sv.edicts);
+	pr_global_struct->time = sv.time;
+	PR_ExecuteProgram (pr_global_struct->StartFrame);
+}
+
+/*
+================
+SV_RunEntity
+
+================
+*/
+void SV_RunEntity (edict_t *ent)
+{
+	if (ent->v.lastruntime == (float)realtime)
+		return;
+	ent->v.lastruntime = (float)realtime;
+
+	switch ( (int)ent->v.movetype)
+	{
+	case MOVETYPE_PUSH:
+		SV_Physics_Pusher (ent);
+		break;
+	case MOVETYPE_NONE:
+		SV_Physics_None (ent);
+		break;
+	case MOVETYPE_NOCLIP:
+		SV_Physics_Noclip (ent);
+		break;
+	case MOVETYPE_STEP:
+		SV_Physics_Step (ent);
+		break;
+	case MOVETYPE_TOSS:
+	case MOVETYPE_BOUNCE:
+	case MOVETYPE_FLY:
+	case MOVETYPE_FLYMISSILE:
+		SV_Physics_Toss (ent);
+		break;
+	default:
+		SV_Error ("SV_Physics: bad movetype %i", (int)ent->v.movetype);			
+	}
+}
+
+/*
+================
+SV_RunNewmis
+
+================
+*/
+void SV_RunNewmis (void)
+{
+	edict_t	*ent;
+
+	if (!pr_global_struct->newmis)
+		return;
+	ent = PROG_TO_EDICT(pr_global_struct->newmis);
+	host_frametime = 0.05;
+	pr_global_struct->newmis = 0;
+	
+	SV_RunEntity (ent);		
+}
+
+/*
+================
+SV_Physics
+
+================
+*/
+void SV_Physics (void)
+{
+	int		i;
+	edict_t	*ent;
+	static double	old_time;
+
+// don't bother running a frame if sys_ticrate seconds haven't passed
+	host_frametime = realtime - old_time;
+	if (host_frametime < sv_mintic.value)
+		return;
+	if (host_frametime > sv_maxtic.value)
+		host_frametime = sv_maxtic.value;
+	old_time = realtime;
+
+	pr_global_struct->frametime = host_frametime;
+
+	SV_ProgStartFrame ();
+
+//
+// treat each object in turn
+// even the world gets a chance to think
+//
+	ent = sv.edicts;
+	for (i=0 ; i<sv.num_edicts ; i++, ent = NEXT_EDICT(ent))
+	{
+		if (ent->free)
+			continue;
+
+		if (pr_global_struct->force_retouch)
+			SV_LinkEdict (ent, true);	// force retouch even for stationary
+
+		if (i > 0 && i <= MAX_CLIENTS)
+			continue;		// clients are run directly from packets
+
+		SV_RunEntity (ent);
+		SV_RunNewmis ();
+	}
+	
+	if (pr_global_struct->force_retouch)
+		pr_global_struct->force_retouch--;	
+}
+
+void SV_SetMoveVars(void)
+{
+	movevars.gravity			= sv_gravity.value; 
+	movevars.stopspeed		    = sv_stopspeed.value;		 
+	movevars.maxspeed			= sv_maxspeed.value;			 
+	movevars.spectatormaxspeed  = sv_spectatormaxspeed.value; 
+	movevars.accelerate		    = sv_accelerate.value;		 
+	movevars.airaccelerate	    = sv_airaccelerate.value;	 
+	movevars.wateraccelerate	= sv_wateraccelerate.value;	   
+	movevars.friction			= sv_friction.value;			 
+	movevars.waterfriction	    = sv_waterfriction.value;	 
+	movevars.entgravity			= 1.0;
+}
--- /dev/null
+++ b/QW/server/sv_send.c
@@ -1,0 +1,806 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// sv_main.c -- server main program
+
+#include "qwsvdef.h"
+
+#define CHAN_AUTO   0
+#define CHAN_WEAPON 1
+#define CHAN_VOICE  2
+#define CHAN_ITEM   3
+#define CHAN_BODY   4
+
+/*
+=============================================================================
+
+Con_Printf redirection
+
+=============================================================================
+*/
+
+char	outputbuf[8000];
+
+redirect_t	sv_redirected;
+
+extern cvar_t sv_phs;
+
+/*
+==================
+SV_FlushRedirect
+==================
+*/
+void SV_FlushRedirect (void)
+{
+	char	send[8000+6];
+
+	if (sv_redirected == RD_PACKET)
+	{
+		send[0] = 0xff;
+		send[1] = 0xff;
+		send[2] = 0xff;
+		send[3] = 0xff;
+		send[4] = A2C_PRINT;
+		memcpy (send+5, outputbuf, strlen(outputbuf)+1);
+
+		NET_SendPacket (strlen(send)+1, send, net_from);
+	}
+	else if (sv_redirected == RD_CLIENT)
+	{
+		ClientReliableWrite_Begin (host_client, svc_print, strlen(outputbuf)+3);
+		ClientReliableWrite_Byte (host_client, PRINT_HIGH);
+		ClientReliableWrite_String (host_client, outputbuf);
+	}
+
+	// clear it
+	outputbuf[0] = 0;
+}
+
+
+/*
+==================
+SV_BeginRedirect
+
+  Send Con_Printf data to the remote client
+  instead of the console
+==================
+*/
+void SV_BeginRedirect (redirect_t rd)
+{
+	sv_redirected = rd;
+	outputbuf[0] = 0;
+}
+
+void SV_EndRedirect (void)
+{
+	SV_FlushRedirect ();
+	sv_redirected = RD_NONE;
+}
+
+
+/*
+================
+Con_Printf
+
+Handles cursor positioning, line wrapping, etc
+================
+*/
+#define	MAXPRINTMSG	4096
+// FIXME: make a buffer size safe vsprintf?
+void Con_Printf (char *fmt, ...)
+{
+	va_list		argptr;
+	char		msg[MAXPRINTMSG];
+	
+	va_start (argptr,fmt);
+	vsprintf (msg,fmt,argptr);
+	va_end (argptr);
+
+	// add to redirected message
+	if (sv_redirected)
+	{
+		if (strlen (msg) + strlen(outputbuf) > sizeof(outputbuf) - 1)
+			SV_FlushRedirect ();
+		strcat (outputbuf, msg);
+		return;
+	}
+
+	Sys_Printf ("%s", msg);	// also echo to debugging console
+	if (sv_logfile)
+		fprintf (sv_logfile, "%s", msg);
+}
+
+/*
+================
+Con_DPrintf
+
+A Con_Printf that only shows up if the "developer" cvar is set
+================
+*/
+void Con_DPrintf (char *fmt, ...)
+{
+	va_list		argptr;
+	char		msg[MAXPRINTMSG];
+
+	if (!developer.value)
+		return;
+
+	va_start (argptr,fmt);
+	vsprintf (msg,fmt,argptr);
+	va_end (argptr);
+	
+	Con_Printf ("%s", msg);
+}
+
+/*
+=============================================================================
+
+EVENT MESSAGES
+
+=============================================================================
+*/
+
+static void SV_PrintToClient(client_t *cl, int level, char *string)
+{
+	ClientReliableWrite_Begin (cl, svc_print, strlen(string)+3);
+	ClientReliableWrite_Byte (cl, level);
+	ClientReliableWrite_String (cl, string);
+}
+
+
+/*
+=================
+SV_ClientPrintf
+
+Sends text across to be displayed if the level passes
+=================
+*/
+void SV_ClientPrintf (client_t *cl, int level, char *fmt, ...)
+{
+	va_list		argptr;
+	char		string[1024];
+	
+	if (level < cl->messagelevel)
+		return;
+	
+	va_start (argptr,fmt);
+	vsprintf (string, fmt,argptr);
+	va_end (argptr);
+
+	SV_PrintToClient(cl, level, string);
+}
+
+/*
+=================
+SV_BroadcastPrintf
+
+Sends text to all active clients
+=================
+*/
+void SV_BroadcastPrintf (int level, char *fmt, ...)
+{
+	va_list		argptr;
+	char		string[1024];
+	client_t	*cl;
+	int			i;
+
+	va_start (argptr,fmt);
+	vsprintf (string, fmt,argptr);
+	va_end (argptr);
+	
+	Sys_Printf ("%s", string);	// print to the console
+
+	for (i=0, cl = svs.clients ; i<MAX_CLIENTS ; i++, cl++)
+	{
+		if (level < cl->messagelevel)
+			continue;
+		if (!cl->state)
+			continue;
+
+		SV_PrintToClient(cl, level, string);
+	}
+}
+
+/*
+=================
+SV_BroadcastCommand
+
+Sends text to all active clients
+=================
+*/
+void SV_BroadcastCommand (char *fmt, ...)
+{
+	va_list		argptr;
+	char		string[1024];
+	
+	if (!sv.state)
+		return;
+	va_start (argptr,fmt);
+	vsprintf (string, fmt,argptr);
+	va_end (argptr);
+
+	MSG_WriteByte (&sv.reliable_datagram, svc_stufftext);
+	MSG_WriteString (&sv.reliable_datagram, string);
+}
+
+
+/*
+=================
+SV_Multicast
+
+Sends the contents of sv.multicast to a subset of the clients,
+then clears sv.multicast.
+
+MULTICAST_ALL	same as broadcast
+MULTICAST_PVS	send to clients potentially visible from org
+MULTICAST_PHS	send to clients potentially hearable from org
+=================
+*/
+void SV_Multicast (vec3_t origin, int to)
+{
+	client_t	*client;
+	byte		*mask;
+	mleaf_t		*leaf;
+	int			leafnum;
+	int			j;
+	qboolean	reliable;
+
+	leaf = Mod_PointInLeaf (origin, sv.worldmodel);
+	if (!leaf)
+		leafnum = 0;
+	else
+		leafnum = leaf - sv.worldmodel->leafs;
+
+	reliable = false;
+
+	switch (to)
+	{
+	case MULTICAST_ALL_R:
+		reliable = true;	// intentional fallthrough
+	case MULTICAST_ALL:
+		mask = sv.pvs;		// leaf 0 is everything;
+		break;
+
+	case MULTICAST_PHS_R:
+		reliable = true;	// intentional fallthrough
+	case MULTICAST_PHS:
+		mask = sv.phs + leafnum * 4*((sv.worldmodel->numleafs+31)>>5);
+		break;
+
+	case MULTICAST_PVS_R:
+		reliable = true;	// intentional fallthrough
+	case MULTICAST_PVS:
+		mask = sv.pvs + leafnum * 4*((sv.worldmodel->numleafs+31)>>5);
+		break;
+
+	default:
+		mask = NULL;
+		SV_Error ("SV_Multicast: bad to:%i", to);
+	}
+
+	// send the data to all relevent clients
+	for (j = 0, client = svs.clients; j < MAX_CLIENTS; j++, client++)
+	{
+		if (client->state != cs_spawned)
+			continue;
+
+		if (to == MULTICAST_PHS_R || to == MULTICAST_PHS) {
+			vec3_t delta;
+			VectorSubtract(origin, client->edict->v.origin, delta);
+			if (Length(delta) <= 1024)
+				goto inrange;
+		}
+
+		leaf = Mod_PointInLeaf (client->edict->v.origin, sv.worldmodel);
+		if (leaf)
+		{
+			// -1 is because pvs rows are 1 based, not 0 based like leafs
+			leafnum = leaf - sv.worldmodel->leafs - 1;
+			if ( !(mask[leafnum>>3] & (1<<(leafnum&7)) ) )
+			{
+//				Con_Printf ("supressed multicast\n");
+				continue;
+			}
+		}
+
+inrange:
+		if (reliable) {
+			ClientReliableCheckBlock(client, sv.multicast.cursize);
+			ClientReliableWrite_SZ(client, sv.multicast.data, sv.multicast.cursize);
+		} else
+			SZ_Write (&client->datagram, sv.multicast.data, sv.multicast.cursize);
+	}
+
+	SZ_Clear (&sv.multicast);
+}
+
+
+/*  
+==================
+SV_StartSound
+
+Each entity can have eight independant sound sources, like voice,
+weapon, feet, etc.
+
+Channel 0 is an auto-allocate channel, the others override anything
+allready running on that entity/channel pair.
+
+An attenuation of 0 will play full volume everywhere in the level.
+Larger attenuations will drop off.  (max 4 attenuation)
+
+==================
+*/  
+void SV_StartSound (edict_t *entity, int channel, char *sample, int volume,
+    float attenuation)
+{       
+    int         sound_num;
+    int			field_mask;
+    int			i;
+	int			ent;
+	vec3_t		origin;
+	qboolean	use_phs;
+	qboolean	reliable = false;
+
+	if (volume < 0 || volume > 255)
+		SV_Error ("SV_StartSound: volume = %i", volume);
+
+	if (attenuation < 0 || attenuation > 4)
+		SV_Error ("SV_StartSound: attenuation = %f", attenuation);
+
+	if (channel < 0 || channel > 15)
+		SV_Error ("SV_StartSound: channel = %i", channel);
+
+// find precache number for sound
+    for (sound_num=1 ; sound_num<MAX_SOUNDS
+        && sv.sound_precache[sound_num] ; sound_num++)
+        if (!strcmp(sample, sv.sound_precache[sound_num]))
+            break;
+    
+    if ( sound_num == MAX_SOUNDS || !sv.sound_precache[sound_num] )
+    {
+        Con_Printf ("SV_StartSound: %s not precacheed\n", sample);
+        return;
+    }
+    
+	ent = NUM_FOR_EDICT(entity);
+
+	if ((channel & 8) || !sv_phs.value)	// no PHS flag
+	{
+		if (channel & 8)
+			reliable = true; // sounds that break the phs are reliable
+		use_phs = false;
+		channel &= 7;
+	}
+	else
+		use_phs = true;
+
+//	if (channel == CHAN_BODY || channel == CHAN_VOICE)
+//		reliable = true;
+
+	channel = (ent<<3) | channel;
+
+	field_mask = 0;
+	if (volume != DEFAULT_SOUND_PACKET_VOLUME)
+		channel |= SND_VOLUME;
+	if (attenuation != DEFAULT_SOUND_PACKET_ATTENUATION)
+		channel |= SND_ATTENUATION;
+
+	// use the entity origin unless it is a bmodel
+	if (entity->v.solid == SOLID_BSP)
+	{
+		for (i=0 ; i<3 ; i++)
+			origin[i] = entity->v.origin[i]+0.5*(entity->v.mins[i]+entity->v.maxs[i]);
+	}
+	else
+	{
+		VectorCopy (entity->v.origin, origin);
+	}
+
+	MSG_WriteByte (&sv.multicast, svc_sound);
+	MSG_WriteShort (&sv.multicast, channel);
+	if (channel & SND_VOLUME)
+		MSG_WriteByte (&sv.multicast, volume);
+	if (channel & SND_ATTENUATION)
+		MSG_WriteByte (&sv.multicast, attenuation*64);
+	MSG_WriteByte (&sv.multicast, sound_num);
+	for (i=0 ; i<3 ; i++)
+		MSG_WriteCoord (&sv.multicast, origin[i]);
+
+	if (use_phs)
+		SV_Multicast (origin, reliable ? MULTICAST_PHS_R : MULTICAST_PHS);
+	else
+		SV_Multicast (origin, reliable ? MULTICAST_ALL_R : MULTICAST_ALL);
+}           
+
+
+/*
+===============================================================================
+
+FRAME UPDATES
+
+===============================================================================
+*/
+
+int		sv_nailmodel, sv_supernailmodel, sv_playermodel;
+
+void SV_FindModelNumbers (void)
+{
+	int		i;
+
+	sv_nailmodel = -1;
+	sv_supernailmodel = -1;
+	sv_playermodel = -1;
+
+	for (i=0 ; i<MAX_MODELS ; i++)
+	{
+		if (!sv.model_precache[i])
+			break;
+		if (!strcmp(sv.model_precache[i],"progs/spike.mdl"))
+			sv_nailmodel = i;
+		if (!strcmp(sv.model_precache[i],"progs/s_spike.mdl"))
+			sv_supernailmodel = i;
+		if (!strcmp(sv.model_precache[i],"progs/player.mdl"))
+			sv_playermodel = i;
+	}
+}
+
+
+/*
+==================
+SV_WriteClientdataToMessage
+
+==================
+*/
+void SV_WriteClientdataToMessage (client_t *client, sizebuf_t *msg)
+{
+	int		i;
+	edict_t	*other;
+	edict_t	*ent;
+
+	ent = client->edict;
+
+	// send the chokecount for r_netgraph
+	if (client->chokecount)
+	{
+		MSG_WriteByte (msg, svc_chokecount);
+		MSG_WriteByte (msg, client->chokecount);
+		client->chokecount = 0;
+	}
+
+	// send a damage message if the player got hit this frame
+	if (ent->v.dmg_take || ent->v.dmg_save)
+	{
+		other = PROG_TO_EDICT(ent->v.dmg_inflictor);
+		MSG_WriteByte (msg, svc_damage);
+		MSG_WriteByte (msg, ent->v.dmg_save);
+		MSG_WriteByte (msg, ent->v.dmg_take);
+		for (i=0 ; i<3 ; i++)
+			MSG_WriteCoord (msg, other->v.origin[i] + 0.5*(other->v.mins[i] + other->v.maxs[i]));
+	
+		ent->v.dmg_take = 0;
+		ent->v.dmg_save = 0;
+	}
+
+	// a fixangle might get lost in a dropped packet.  Oh well.
+	if ( ent->v.fixangle )
+	{
+		MSG_WriteByte (msg, svc_setangle);
+		for (i=0 ; i < 3 ; i++)
+			MSG_WriteAngle (msg, ent->v.angles[i] );
+		ent->v.fixangle = 0;
+	}
+}
+
+/*
+=======================
+SV_UpdateClientStats
+
+Performs a delta update of the stats array.  This should only be performed
+when a reliable message can be delivered this frame.
+=======================
+*/
+void SV_UpdateClientStats (client_t *client)
+{
+	edict_t	*ent;
+	int		stats[MAX_CL_STATS];
+	int		i;
+	
+	ent = client->edict;
+	memset (stats, 0, sizeof(stats));
+	
+	// if we are a spectator and we are tracking a player, we get his stats
+	// so our status bar reflects his
+	if (client->spectator && client->spec_track > 0)
+		ent = svs.clients[client->spec_track - 1].edict;
+
+	stats[STAT_HEALTH] = ent->v.health;
+	stats[STAT_WEAPON] = SV_ModelIndex(PR_GetString(ent->v.weaponmodel));
+	stats[STAT_AMMO] = ent->v.currentammo;
+	stats[STAT_ARMOR] = ent->v.armorvalue;
+	stats[STAT_SHELLS] = ent->v.ammo_shells;
+	stats[STAT_NAILS] = ent->v.ammo_nails;
+	stats[STAT_ROCKETS] = ent->v.ammo_rockets;
+	stats[STAT_CELLS] = ent->v.ammo_cells;
+	if (!client->spectator)
+		stats[STAT_ACTIVEWEAPON] = ent->v.weapon;
+	// stuff the sigil bits into the high bits of items for sbar
+	stats[STAT_ITEMS] = (int)ent->v.items | ((int)pr_global_struct->serverflags << 28);
+
+	for (i=0 ; i<MAX_CL_STATS ; i++)
+		if (stats[i] != client->stats[i])
+		{
+			client->stats[i] = stats[i];
+			if (stats[i] >=0 && stats[i] <= 255)
+			{
+				ClientReliableWrite_Begin(client, svc_updatestat, 3);
+				ClientReliableWrite_Byte(client, i);
+				ClientReliableWrite_Byte(client, stats[i]);
+			}
+			else
+			{
+				ClientReliableWrite_Begin(client, svc_updatestatlong, 6);
+				ClientReliableWrite_Byte(client, i);
+				ClientReliableWrite_Long(client, stats[i]);
+			}
+		}
+}
+
+/*
+=======================
+SV_SendClientDatagram
+=======================
+*/
+qboolean SV_SendClientDatagram (client_t *client)
+{
+	byte		buf[MAX_DATAGRAM];
+	sizebuf_t	msg;
+
+	msg.data = buf;
+	msg.maxsize = sizeof(buf);
+	msg.cursize = 0;
+	msg.allowoverflow = true;
+	msg.overflowed = false;
+
+	// add the client specific data to the datagram
+	SV_WriteClientdataToMessage (client, &msg);
+
+	// send over all the objects that are in the PVS
+	// this will include clients, a packetentities, and
+	// possibly a nails update
+	SV_WriteEntitiesToClient (client, &msg);
+
+	// copy the accumulated multicast datagram
+	// for this client out to the message
+	if (client->datagram.overflowed)
+		Con_Printf ("WARNING: datagram overflowed for %s\n", client->name);
+	else
+		SZ_Write (&msg, client->datagram.data, client->datagram.cursize);
+	SZ_Clear (&client->datagram);
+
+	// send deltas over reliable stream
+	if (Netchan_CanReliable (&client->netchan))
+		SV_UpdateClientStats (client);
+
+	if (msg.overflowed)
+	{
+		Con_Printf ("WARNING: msg overflowed for %s\n", client->name);
+		SZ_Clear (&msg);
+	}
+
+	// send the datagram
+	Netchan_Transmit (&client->netchan, msg.cursize, buf);
+
+	return true;
+}
+
+/*
+=======================
+SV_UpdateToReliableMessages
+=======================
+*/
+void SV_UpdateToReliableMessages (void)
+{
+	int			i, j;
+	client_t *client;
+	eval_t *val;
+	edict_t *ent;
+
+// check for changes to be sent over the reliable streams to all clients
+	for (i=0, host_client = svs.clients ; i<MAX_CLIENTS ; i++, host_client++)
+	{
+		if (host_client->state != cs_spawned)
+			continue;
+		if (host_client->sendinfo)
+		{
+			host_client->sendinfo = false;
+			SV_FullClientUpdate (host_client, &sv.reliable_datagram);
+		}
+		if (host_client->old_frags != host_client->edict->v.frags)
+		{
+			for (j=0, client = svs.clients ; j<MAX_CLIENTS ; j++, client++)
+			{
+				if (client->state < cs_connected)
+					continue;
+				ClientReliableWrite_Begin(client, svc_updatefrags, 4);
+				ClientReliableWrite_Byte(client, i);
+				ClientReliableWrite_Short(client, host_client->edict->v.frags);
+			}
+
+			host_client->old_frags = host_client->edict->v.frags;
+		}
+
+		// maxspeed/entgravity changes
+		ent = host_client->edict;
+
+		val = GetEdictFieldValue(ent, "gravity");
+		if (val && host_client->entgravity != val->_float) {
+			host_client->entgravity = val->_float;
+			ClientReliableWrite_Begin(host_client, svc_entgravity, 5);
+			ClientReliableWrite_Float(host_client, host_client->entgravity);
+		}
+		val = GetEdictFieldValue(ent, "maxspeed");
+		if (val && host_client->maxspeed != val->_float) {
+			host_client->maxspeed = val->_float;
+			ClientReliableWrite_Begin(host_client, svc_maxspeed, 5);
+			ClientReliableWrite_Float(host_client, host_client->maxspeed);
+		}
+
+	}
+
+	if (sv.datagram.overflowed)
+		SZ_Clear (&sv.datagram);
+
+	// append the broadcast messages to each client messages
+	for (j=0, client = svs.clients ; j<MAX_CLIENTS ; j++, client++)
+	{
+		if (client->state < cs_connected)
+			continue;	// reliables go to all connected or spawned
+
+		ClientReliableCheckBlock(client, sv.reliable_datagram.cursize);
+		ClientReliableWrite_SZ(client, sv.reliable_datagram.data, sv.reliable_datagram.cursize);
+
+		if (client->state != cs_spawned)
+			continue;	// datagrams only go to spawned
+		SZ_Write (&client->datagram
+			, sv.datagram.data
+			, sv.datagram.cursize);
+	}
+
+	SZ_Clear (&sv.reliable_datagram);
+	SZ_Clear (&sv.datagram);
+}
+
+#ifdef _WIN32
+#pragma optimize( "", off )
+#endif
+
+
+
+/*
+=======================
+SV_SendClientMessages
+=======================
+*/
+void SV_SendClientMessages (void)
+{
+	int			i, j;
+	client_t	*c;
+
+// update frags, names, etc
+	SV_UpdateToReliableMessages ();
+
+// build individual updates
+	for (i=0, c = svs.clients ; i<MAX_CLIENTS ; i++, c++)
+	{
+		if (!c->state)
+			continue;
+
+		if (c->drop) {
+			SV_DropClient(c);
+			c->drop = false;
+			continue;
+		}
+
+		// check to see if we have a backbuf to stick in the reliable
+		if (c->num_backbuf) {
+			// will it fit?
+			if (c->netchan.message.cursize + c->backbuf_size[0] <
+				c->netchan.message.maxsize) {
+
+				Con_DPrintf("%s: backbuf %d bytes\n",
+					c->name, c->backbuf_size[0]);
+
+				// it'll fit
+				SZ_Write(&c->netchan.message, c->backbuf_data[0],
+					c->backbuf_size[0]);
+				
+				//move along, move along
+				for (j = 1; j < c->num_backbuf; j++) {
+					memcpy(c->backbuf_data[j - 1], c->backbuf_data[j],
+						c->backbuf_size[j]);
+					c->backbuf_size[j - 1] = c->backbuf_size[j];
+				}
+
+				c->num_backbuf--;
+				if (c->num_backbuf) {
+					memset(&c->backbuf, 0, sizeof(c->backbuf));
+					c->backbuf.data = c->backbuf_data[c->num_backbuf - 1];
+					c->backbuf.cursize = c->backbuf_size[c->num_backbuf - 1];
+					c->backbuf.maxsize = sizeof(c->backbuf_data[c->num_backbuf - 1]);
+				}
+			}
+		}
+
+		// if the reliable message overflowed,
+		// drop the client
+		if (c->netchan.message.overflowed)
+		{
+			SZ_Clear (&c->netchan.message);
+			SZ_Clear (&c->datagram);
+			SV_BroadcastPrintf (PRINT_HIGH, "%s overflowed\n", c->name);
+			Con_Printf ("WARNING: reliable overflow for %s\n",c->name);
+			SV_DropClient (c);
+			c->send_message = true;
+			c->netchan.cleartime = 0;	// don't choke this message
+		}
+
+		// only send messages if the client has sent one
+		// and the bandwidth is not choked
+		if (!c->send_message)
+			continue;
+		c->send_message = false;	// try putting this after choke?
+		if (!sv.paused && !Netchan_CanPacket (&c->netchan))
+		{
+			c->chokecount++;
+			continue;		// bandwidth choke
+		}
+
+		if (c->state == cs_spawned)
+			SV_SendClientDatagram (c);
+		else
+			Netchan_Transmit (&c->netchan, 0, NULL);	// just update reliable
+			
+	}
+}
+
+#ifdef _WIN32
+#pragma optimize( "", on )
+#endif
+
+
+
+/*
+=======================
+SV_SendMessagesToAll
+
+FIXME: does this sequence right?
+=======================
+*/
+void SV_SendMessagesToAll (void)
+{
+	int			i;
+	client_t	*c;
+
+	for (i=0, c = svs.clients ; i<MAX_CLIENTS ; i++, c++)
+		if (c->state)		// FIXME: should this only send to active?
+			c->send_message = true;
+	
+	SV_SendClientMessages ();
+}
+
--- /dev/null
+++ b/QW/server/sv_user.c
@@ -1,0 +1,1702 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// sv_user.c -- server code for moving users
+
+#include "qwsvdef.h"
+
+edict_t	*sv_player;
+
+usercmd_t	cmd;
+
+cvar_t	cl_rollspeed = {"cl_rollspeed", "200"};
+cvar_t	cl_rollangle = {"cl_rollangle", "2.0"};
+cvar_t	sv_spectalk = {"sv_spectalk", "1"};
+
+cvar_t	sv_mapcheck	= {"sv_mapcheck", "1"};
+
+extern	vec3_t	player_mins;
+
+extern int fp_messages, fp_persecond, fp_secondsdead;
+extern char fp_msg[];
+extern cvar_t pausable;
+
+/*
+============================================================
+
+USER STRINGCMD EXECUTION
+
+host_client and sv_player will be valid.
+============================================================
+*/
+
+/*
+================
+SV_New_f
+
+Sends the first message from the server to a connected client.
+This will be sent on the initial connection and upon each server load.
+================
+*/
+void SV_New_f (void)
+{
+	char		*gamedir;
+	int			playernum;
+
+	if (host_client->state == cs_spawned)
+		return;
+
+	host_client->state = cs_connected;
+	host_client->connection_started = realtime;
+
+	// send the info about the new client to all connected clients
+//	SV_FullClientUpdate (host_client, &sv.reliable_datagram);
+//	host_client->sendinfo = true;
+
+	gamedir = Info_ValueForKey (svs.info, "*gamedir");
+	if (!gamedir[0])
+		gamedir = "qw";
+
+//NOTE:  This doesn't go through ClientReliableWrite since it's before the user
+//spawns.  These functions are written to not overflow
+	if (host_client->num_backbuf) {
+		Con_Printf("WARNING %s: [SV_New] Back buffered (%d0, clearing", host_client->name, host_client->netchan.message.cursize); 
+		host_client->num_backbuf = 0;
+		SZ_Clear(&host_client->netchan.message);
+	}
+
+	// send the serverdata
+	MSG_WriteByte (&host_client->netchan.message, svc_serverdata);
+	MSG_WriteLong (&host_client->netchan.message, PROTOCOL_VERSION);
+	MSG_WriteLong (&host_client->netchan.message, svs.spawncount);
+	MSG_WriteString (&host_client->netchan.message, gamedir);
+
+	playernum = NUM_FOR_EDICT(host_client->edict)-1;
+	if (host_client->spectator)
+		playernum |= 128;
+	MSG_WriteByte (&host_client->netchan.message, playernum);
+
+	// send full levelname
+	MSG_WriteString (&host_client->netchan.message, PR_GetString(sv.edicts->v.message));
+
+	// send the movevars
+	MSG_WriteFloat(&host_client->netchan.message, movevars.gravity);
+	MSG_WriteFloat(&host_client->netchan.message, movevars.stopspeed);
+	MSG_WriteFloat(&host_client->netchan.message, movevars.maxspeed);
+	MSG_WriteFloat(&host_client->netchan.message, movevars.spectatormaxspeed);
+	MSG_WriteFloat(&host_client->netchan.message, movevars.accelerate);
+	MSG_WriteFloat(&host_client->netchan.message, movevars.airaccelerate);
+	MSG_WriteFloat(&host_client->netchan.message, movevars.wateraccelerate);
+	MSG_WriteFloat(&host_client->netchan.message, movevars.friction);
+	MSG_WriteFloat(&host_client->netchan.message, movevars.waterfriction);
+	MSG_WriteFloat(&host_client->netchan.message, movevars.entgravity);
+
+	// send music
+	MSG_WriteByte (&host_client->netchan.message, svc_cdtrack);
+	MSG_WriteByte (&host_client->netchan.message, sv.edicts->v.sounds);
+
+	// send server info string
+	MSG_WriteByte (&host_client->netchan.message, svc_stufftext);
+	MSG_WriteString (&host_client->netchan.message, va("fullserverinfo \"%s\"\n", svs.info) );
+}
+
+/*
+==================
+SV_Soundlist_f
+==================
+*/
+void SV_Soundlist_f (void)
+{
+	char		**s;
+	int			n;
+
+	if (host_client->state != cs_connected)
+	{
+		Con_Printf ("soundlist not valid -- allready spawned\n");
+		return;
+	}
+
+	// handle the case of a level changing while a client was connecting
+	if ( atoi(Cmd_Argv(1)) != svs.spawncount )
+	{
+		Con_Printf ("SV_Soundlist_f from different level\n");
+		SV_New_f ();
+		return;
+	}
+
+	n = atoi(Cmd_Argv(2));
+	
+//NOTE:  This doesn't go through ClientReliableWrite since it's before the user
+//spawns.  These functions are written to not overflow
+	if (host_client->num_backbuf) {
+		Con_Printf("WARNING %s: [SV_Soundlist] Back buffered (%d0, clearing", host_client->name, host_client->netchan.message.cursize); 
+		host_client->num_backbuf = 0;
+		SZ_Clear(&host_client->netchan.message);
+	}
+
+	MSG_WriteByte (&host_client->netchan.message, svc_soundlist);
+	MSG_WriteByte (&host_client->netchan.message, n);
+	for (s = sv.sound_precache+1 + n ; 
+		*s && host_client->netchan.message.cursize < (MAX_MSGLEN/2); 
+		s++, n++)
+		MSG_WriteString (&host_client->netchan.message, *s);
+
+	MSG_WriteByte (&host_client->netchan.message, 0);
+
+	// next msg
+	if (*s)
+		MSG_WriteByte (&host_client->netchan.message, n);
+	else
+		MSG_WriteByte (&host_client->netchan.message, 0);
+}
+
+/*
+==================
+SV_Modellist_f
+==================
+*/
+void SV_Modellist_f (void)
+{
+	char		**s;
+	int			n;
+
+	if (host_client->state != cs_connected)
+	{
+		Con_Printf ("modellist not valid -- allready spawned\n");
+		return;
+	}
+	
+	// handle the case of a level changing while a client was connecting
+	if ( atoi(Cmd_Argv(1)) != svs.spawncount )
+	{
+		Con_Printf ("SV_Modellist_f from different level\n");
+		SV_New_f ();
+		return;
+	}
+
+	n = atoi(Cmd_Argv(2));
+
+//NOTE:  This doesn't go through ClientReliableWrite since it's before the user
+//spawns.  These functions are written to not overflow
+	if (host_client->num_backbuf) {
+		Con_Printf("WARNING %s: [SV_Modellist] Back buffered (%d0, clearing", host_client->name, host_client->netchan.message.cursize); 
+		host_client->num_backbuf = 0;
+		SZ_Clear(&host_client->netchan.message);
+	}
+
+	MSG_WriteByte (&host_client->netchan.message, svc_modellist);
+	MSG_WriteByte (&host_client->netchan.message, n);
+	for (s = sv.model_precache+1+n ; 
+		*s && host_client->netchan.message.cursize < (MAX_MSGLEN/2); 
+		s++, n++)
+		MSG_WriteString (&host_client->netchan.message, *s);
+	MSG_WriteByte (&host_client->netchan.message, 0);
+
+	// next msg
+	if (*s)
+		MSG_WriteByte (&host_client->netchan.message, n);
+	else
+		MSG_WriteByte (&host_client->netchan.message, 0);
+}
+
+/*
+==================
+SV_PreSpawn_f
+==================
+*/
+void SV_PreSpawn_f (void)
+{
+	unsigned	buf;
+	unsigned	check;
+
+	if (host_client->state != cs_connected)
+	{
+		Con_Printf ("prespawn not valid -- allready spawned\n");
+		return;
+	}
+	
+	// handle the case of a level changing while a client was connecting
+	if ( atoi(Cmd_Argv(1)) != svs.spawncount )
+	{
+		Con_Printf ("SV_PreSpawn_f from different level\n");
+		SV_New_f ();
+		return;
+	}
+	
+	buf = atoi(Cmd_Argv(2));
+	if (buf >= sv.num_signon_buffers)
+		buf = 0;
+
+	if (!buf) {
+		// should be three numbers following containing checksums
+		check = atoi(Cmd_Argv(3));
+
+//		Con_DPrintf("Client check = %d\n", check);
+
+		if (sv_mapcheck.value && check != sv.worldmodel->checksum &&
+			check != sv.worldmodel->checksum2) {
+			SV_ClientPrintf (host_client, PRINT_HIGH, 
+				"Map model file does not match (%s), %i != %i/%i.\n"
+				"You may need a new version of the map, or the proper install files.\n",
+				sv.modelname, check, sv.worldmodel->checksum, sv.worldmodel->checksum2);
+			SV_DropClient (host_client); 
+			return;
+		}
+		host_client->checksum = check;
+	}
+
+//NOTE:  This doesn't go through ClientReliableWrite since it's before the user
+//spawns.  These functions are written to not overflow
+	if (host_client->num_backbuf) {
+		Con_Printf("WARNING %s: [SV_PreSpawn] Back buffered (%d0, clearing", host_client->name, host_client->netchan.message.cursize); 
+		host_client->num_backbuf = 0;
+		SZ_Clear(&host_client->netchan.message);
+	}
+
+	SZ_Write (&host_client->netchan.message, 
+		sv.signon_buffers[buf],
+		sv.signon_buffer_size[buf]);
+
+	buf++;
+	if (buf == sv.num_signon_buffers)
+	{	// all done prespawning
+		MSG_WriteByte (&host_client->netchan.message, svc_stufftext);
+		MSG_WriteString (&host_client->netchan.message, va("cmd spawn %i 0\n",svs.spawncount) );
+	}
+	else
+	{	// need to prespawn more
+		MSG_WriteByte (&host_client->netchan.message, svc_stufftext);
+		MSG_WriteString (&host_client->netchan.message, 
+			va("cmd prespawn %i %i\n", svs.spawncount, buf) );
+	}
+}
+
+/*
+==================
+SV_Spawn_f
+==================
+*/
+void SV_Spawn_f (void)
+{
+	int		i;
+	client_t	*client;
+	edict_t	*ent;
+	eval_t *val;
+	int n;
+
+	if (host_client->state != cs_connected)
+	{
+		Con_Printf ("Spawn not valid -- allready spawned\n");
+		return;
+	}
+
+// handle the case of a level changing while a client was connecting
+	if ( atoi(Cmd_Argv(1)) != svs.spawncount )
+	{
+		Con_Printf ("SV_Spawn_f from different level\n");
+		SV_New_f ();
+		return;
+	}
+
+	n = atoi(Cmd_Argv(2));
+
+	// make sure n is valid
+	if ( n < 0 || n > MAX_CLIENTS )
+	{
+		Con_Printf ("SV_Spawn_f invalid client start\n");
+		SV_New_f ();
+		return;
+	}
+
+
+	
+// send all current names, colors, and frag counts
+	// FIXME: is this a good thing?
+	SZ_Clear (&host_client->netchan.message);
+
+// send current status of all other players
+
+	// normally this could overflow, but no need to check due to backbuf
+	for (i=n, client = svs.clients + n ; i<MAX_CLIENTS ; i++, client++)
+		SV_FullClientUpdateToClient (client, host_client);
+	
+// send all current light styles
+	for (i=0 ; i<MAX_LIGHTSTYLES ; i++)
+	{
+		ClientReliableWrite_Begin (host_client, svc_lightstyle, 
+			3 + (sv.lightstyles[i] ? strlen(sv.lightstyles[i]) : 1));
+		ClientReliableWrite_Byte (host_client, (char)i);
+		ClientReliableWrite_String (host_client, sv.lightstyles[i]);
+	}
+
+	// set up the edict
+	ent = host_client->edict;
+
+	memset (&ent->v, 0, progs->entityfields * 4);
+	ent->v.colormap = NUM_FOR_EDICT(ent);
+	ent->v.team = 0;	// FIXME
+	ent->v.netname = PR_SetString(host_client->name);
+
+	host_client->entgravity = 1.0;
+	val = GetEdictFieldValue(ent, "gravity");
+	if (val)
+		val->_float = 1.0;
+	host_client->maxspeed = sv_maxspeed.value;
+	val = GetEdictFieldValue(ent, "maxspeed");
+	if (val)
+		val->_float = sv_maxspeed.value;
+
+//
+// force stats to be updated
+//
+	memset (host_client->stats, 0, sizeof(host_client->stats));
+
+	ClientReliableWrite_Begin (host_client, svc_updatestatlong, 6);
+	ClientReliableWrite_Byte (host_client, STAT_TOTALSECRETS);
+	ClientReliableWrite_Long (host_client, pr_global_struct->total_secrets);
+
+	ClientReliableWrite_Begin (host_client, svc_updatestatlong, 6);
+	ClientReliableWrite_Byte (host_client, STAT_TOTALMONSTERS);
+	ClientReliableWrite_Long (host_client, pr_global_struct->total_monsters);
+
+	ClientReliableWrite_Begin (host_client, svc_updatestatlong, 6);
+	ClientReliableWrite_Byte (host_client, STAT_SECRETS);
+	ClientReliableWrite_Long (host_client, pr_global_struct->found_secrets);
+
+	ClientReliableWrite_Begin (host_client, svc_updatestatlong, 6);
+	ClientReliableWrite_Byte (host_client, STAT_MONSTERS);
+	ClientReliableWrite_Long (host_client, pr_global_struct->killed_monsters);
+
+	// get the client to check and download skins
+	// when that is completed, a begin command will be issued
+	ClientReliableWrite_Begin (host_client, svc_stufftext, 8);
+	ClientReliableWrite_String (host_client, "skins\n" );
+
+}
+
+/*
+==================
+SV_SpawnSpectator
+==================
+*/
+void SV_SpawnSpectator (void)
+{
+	int		i;
+	edict_t	*e;
+
+	VectorCopy (vec3_origin, sv_player->v.origin);
+	VectorCopy (vec3_origin, sv_player->v.view_ofs);
+	sv_player->v.view_ofs[2] = 22;
+
+	// search for an info_playerstart to spawn the spectator at
+	for (i=MAX_CLIENTS-1 ; i<sv.num_edicts ; i++)
+	{
+		e = EDICT_NUM(i);
+		if (!strcmp(PR_GetString(e->v.classname), "info_player_start"))
+		{
+			VectorCopy (e->v.origin, sv_player->v.origin);
+			return;
+		}
+	}
+
+}
+
+/*
+==================
+SV_Begin_f
+==================
+*/
+void SV_Begin_f (void)
+{
+	unsigned pmodel = 0, emodel = 0;
+	int		i;
+
+	if (host_client->state == cs_spawned)
+		return; // don't begin again
+
+	host_client->state = cs_spawned;
+	
+	// handle the case of a level changing while a client was connecting
+	if ( atoi(Cmd_Argv(1)) != svs.spawncount )
+	{
+		Con_Printf ("SV_Begin_f from different level\n");
+		SV_New_f ();
+		return;
+	}
+
+	if (host_client->spectator)
+	{
+		SV_SpawnSpectator ();
+
+		if (SpectatorConnect) {
+			// copy spawn parms out of the client_t
+			for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
+				(&pr_global_struct->parm1)[i] = host_client->spawn_parms[i];
+	
+			// call the spawn function
+			pr_global_struct->time = sv.time;
+			pr_global_struct->self = EDICT_TO_PROG(sv_player);
+			PR_ExecuteProgram (SpectatorConnect);
+		}
+	}
+	else
+	{
+		// copy spawn parms out of the client_t
+		for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
+			(&pr_global_struct->parm1)[i] = host_client->spawn_parms[i];
+
+		// call the spawn function
+		pr_global_struct->time = sv.time;
+		pr_global_struct->self = EDICT_TO_PROG(sv_player);
+		PR_ExecuteProgram (pr_global_struct->ClientConnect);
+
+		// actually spawn the player
+		pr_global_struct->time = sv.time;
+		pr_global_struct->self = EDICT_TO_PROG(sv_player);
+		PR_ExecuteProgram (pr_global_struct->PutClientInServer);	
+	}
+
+	// clear the net statistics, because connecting gives a bogus picture
+	host_client->netchan.frame_latency = 0;
+	host_client->netchan.frame_rate = 0;
+	host_client->netchan.drop_count = 0;
+	host_client->netchan.good_count = 0;
+
+	//check he's not cheating
+
+	pmodel = atoi(Info_ValueForKey (host_client->userinfo, "pmodel"));
+	emodel = atoi(Info_ValueForKey (host_client->userinfo, "emodel"));
+
+	if (pmodel != sv.model_player_checksum ||
+		emodel != sv.eyes_player_checksum)
+		SV_BroadcastPrintf (PRINT_HIGH, "%s WARNING: non standard player/eyes model detected\n", host_client->name);
+
+	// if we are paused, tell the client
+	if (sv.paused) {
+		ClientReliableWrite_Begin (host_client, svc_setpause, 2);
+		ClientReliableWrite_Byte (host_client, sv.paused);
+		SV_ClientPrintf(host_client, PRINT_HIGH, "Server is paused.\n");
+	}
+
+#if 0
+//
+// send a fixangle over the reliable channel to make sure it gets there
+// Never send a roll angle, because savegames can catch the server
+// in a state where it is expecting the client to correct the angle
+// and it won't happen if the game was just loaded, so you wind up
+// with a permanent head tilt
+	ent = EDICT_NUM( 1 + (host_client - svs.clients) );
+	MSG_WriteByte (&host_client->netchan.message, svc_setangle);
+	for (i=0 ; i < 2 ; i++)
+		MSG_WriteAngle (&host_client->netchan.message, ent->v.angles[i] );
+	MSG_WriteAngle (&host_client->netchan.message, 0 );
+#endif
+}
+
+//=============================================================================
+
+/*
+==================
+SV_NextDownload_f
+==================
+*/
+void SV_NextDownload_f (void)
+{
+	byte	buffer[1024];
+	int		r;
+	int		percent;
+	int		size;
+
+	if (!host_client->download)
+		return;
+
+	r = host_client->downloadsize - host_client->downloadcount;
+	if (r > 768)
+		r = 768;
+	r = fread (buffer, 1, r, host_client->download);
+	ClientReliableWrite_Begin (host_client, svc_download, 6+r);
+	ClientReliableWrite_Short (host_client, r);
+
+	host_client->downloadcount += r;
+	size = host_client->downloadsize;
+	if (!size)
+		size = 1;
+	percent = host_client->downloadcount*100/size;
+	ClientReliableWrite_Byte (host_client, percent);
+	ClientReliableWrite_SZ (host_client, buffer, r);
+
+	if (host_client->downloadcount != host_client->downloadsize)
+		return;
+
+	fclose (host_client->download);
+	host_client->download = NULL;
+
+}
+
+void OutofBandPrintf(netadr_t where, char *fmt, ...)
+{
+	va_list		argptr;
+	char	send[1024];
+	
+	send[0] = 0xff;
+	send[1] = 0xff;
+	send[2] = 0xff;
+	send[3] = 0xff;
+	send[4] = A2C_PRINT;
+	va_start (argptr, fmt);
+	vsprintf (send+5, fmt, argptr);
+	va_end (argptr);
+
+	NET_SendPacket (strlen(send)+1, send, where);
+}
+
+/*
+==================
+SV_NextUpload
+==================
+*/
+void SV_NextUpload (void)
+{
+	byte	buffer[1024];
+	int		r;
+	int		percent;
+	int		size;
+	client_t *client;
+
+	if (!*host_client->uploadfn) {
+		SV_ClientPrintf(host_client, PRINT_HIGH, "Upload denied\n");
+		ClientReliableWrite_Begin (host_client, svc_stufftext, 8);
+		ClientReliableWrite_String (host_client, "stopul");
+
+		// suck out rest of packet
+		size = MSG_ReadShort ();	MSG_ReadByte ();
+		msg_readcount += size;
+		return;
+	}
+
+	size = MSG_ReadShort ();
+	percent = MSG_ReadByte ();
+
+	if (!host_client->upload)
+	{
+		host_client->upload = fopen(host_client->uploadfn, "wb");
+		if (!host_client->upload) {
+			Sys_Printf("Can't create %s\n", host_client->uploadfn);
+			ClientReliableWrite_Begin (host_client, svc_stufftext, 8);
+			ClientReliableWrite_String (host_client, "stopul");
+			*host_client->uploadfn = 0;
+			return;
+		}
+		Sys_Printf("Receiving %s from %d...\n", host_client->uploadfn, host_client->userid);
+		if (host_client->remote_snap)
+			OutofBandPrintf(host_client->snap_from, "Server receiving %s from %d...\n", host_client->uploadfn, host_client->userid);
+	}
+
+	fwrite (net_message.data + msg_readcount, 1, size, host_client->upload);
+	msg_readcount += size;
+
+Con_DPrintf ("UPLOAD: %d received\n", size);
+
+	if (percent != 100) {
+		ClientReliableWrite_Begin (host_client, svc_stufftext, 8);
+		ClientReliableWrite_String (host_client, "nextul\n");
+	} else {
+		fclose (host_client->upload);
+		host_client->upload = NULL;
+
+		Sys_Printf("%s upload completed.\n", host_client->uploadfn);
+
+		if (host_client->remote_snap) {
+			char *p;
+
+			if ((p = strchr(host_client->uploadfn, '/')) != NULL)
+				p++;
+			else
+				p = host_client->uploadfn;
+			OutofBandPrintf(host_client->snap_from, "%s upload completed.\nTo download, enter:\ndownload %s\n", 
+				host_client->uploadfn, p);
+		}
+	}
+
+}
+
+/*
+==================
+SV_BeginDownload_f
+==================
+*/
+void SV_BeginDownload_f(void)
+{
+	char	*name;
+	extern	cvar_t	allow_download;
+	extern	cvar_t	allow_download_skins;
+	extern	cvar_t	allow_download_models;
+	extern	cvar_t	allow_download_sounds;
+	extern	cvar_t	allow_download_maps;
+	extern	int		file_from_pak; // ZOID did file come from pak?
+
+	name = Cmd_Argv(1);
+// hacked by zoid to allow more conrol over download
+		// first off, no .. or global allow check
+	if (strstr (name, "..") || !allow_download.value
+		// leading dot is no good
+		|| *name == '.' 
+		// leading slash bad as well, must be in subdir
+		|| *name == '/'
+		// next up, skin check
+		|| (strncmp(name, "skins/", 6) == 0 && !allow_download_skins.value)
+		// now models
+		|| (strncmp(name, "progs/", 6) == 0 && !allow_download_models.value)
+		// now sounds
+		|| (strncmp(name, "sound/", 6) == 0 && !allow_download_sounds.value)
+		// now maps (note special case for maps, must not be in pak)
+		|| (strncmp(name, "maps/", 6) == 0 && !allow_download_maps.value)
+		// MUST be in a subdirectory	
+		|| !strstr (name, "/") )	
+	{	// don't allow anything with .. path
+		ClientReliableWrite_Begin (host_client, svc_download, 4);
+		ClientReliableWrite_Short (host_client, -1);
+		ClientReliableWrite_Byte (host_client, 0);
+		return;
+	}
+
+	if (host_client->download) {
+		fclose (host_client->download);
+		host_client->download = NULL;
+	}
+
+	// lowercase name (needed for casesen file systems)
+	{
+		char *p;
+
+		for (p = name; *p; p++)
+			*p = (char)tolower(*p);
+	}
+
+
+	host_client->downloadsize = COM_FOpenFile (name, &host_client->download);
+	host_client->downloadcount = 0;
+
+	if (!host_client->download
+		// special check for maps, if it came from a pak file, don't allow
+		// download  ZOID
+		|| (strncmp(name, "maps/", 5) == 0 && file_from_pak))
+	{
+		if (host_client->download) {
+			fclose(host_client->download);
+			host_client->download = NULL;
+		}
+
+		Sys_Printf ("Couldn't download %s to %s\n", name, host_client->name);
+		ClientReliableWrite_Begin (host_client, svc_download, 4);
+		ClientReliableWrite_Short (host_client, -1);
+		ClientReliableWrite_Byte (host_client, 0);
+		return;
+	}
+
+	SV_NextDownload_f ();
+	Sys_Printf ("Downloading %s to %s\n", name, host_client->name);
+}
+
+//=============================================================================
+
+/*
+==================
+SV_Say
+==================
+*/
+void SV_Say (qboolean team)
+{
+	client_t *client;
+	int		j, tmp;
+	char	*p;
+	char	text[2048];
+	char	t1[32], *t2;
+
+	if (Cmd_Argc () < 2)
+		return;
+
+	if (team)
+	{
+		strncpy (t1, Info_ValueForKey (host_client->userinfo, "team"), 31);
+		t1[31] = 0;
+	}
+
+	if (host_client->spectator && (!sv_spectalk.value || team))
+		sprintf (text, "[SPEC] %s: ", host_client->name);
+	else if (team)
+		sprintf (text, "(%s): ", host_client->name);
+	else {
+		sprintf (text, "%s: ", host_client->name);
+	}
+
+	if (fp_messages) {
+		if (!sv.paused && realtime<host_client->lockedtill) {
+			SV_ClientPrintf(host_client, PRINT_CHAT,
+				"You can't talk for %d more seconds\n", 
+					(int) (host_client->lockedtill - realtime));
+			return;
+		}
+		tmp = host_client->whensaidhead - fp_messages + 1;
+		if (tmp < 0)
+			tmp = 10+tmp;
+		if (!sv.paused &&
+			host_client->whensaid[tmp] && (realtime-host_client->whensaid[tmp] < fp_persecond)) {
+			host_client->lockedtill = realtime + fp_secondsdead;
+			if (fp_msg[0])
+				SV_ClientPrintf(host_client, PRINT_CHAT,
+					"FloodProt: %s\n", fp_msg);
+			else
+				SV_ClientPrintf(host_client, PRINT_CHAT,
+					"FloodProt: You can't talk for %d seconds.\n", fp_secondsdead);
+			return;
+		}
+		host_client->whensaidhead++;
+		if (host_client->whensaidhead > 9)
+			host_client->whensaidhead = 0;
+		host_client->whensaid[host_client->whensaidhead] = realtime;
+	}
+
+	p = Cmd_Args();
+
+	if (*p == '"')
+	{
+		p++;
+		p[Q_strlen(p)-1] = 0;
+	}
+
+	Q_strcat(text, p);
+	Q_strcat(text, "\n");
+
+	Sys_Printf ("%s", text);
+
+	for (j = 0, client = svs.clients; j < MAX_CLIENTS; j++, client++)
+	{
+		if (client->state != cs_spawned)
+			continue;
+		if (host_client->spectator && !sv_spectalk.value)
+			if (!client->spectator)
+				continue;
+
+		if (team)
+		{
+			// the spectator team
+			if (host_client->spectator) {
+				if (!client->spectator)
+					continue;
+			} else {
+				t2 = Info_ValueForKey (client->userinfo, "team");
+				if (strcmp(t1, t2) || client->spectator)
+					continue;	// on different teams
+			}
+		}
+		SV_ClientPrintf(client, PRINT_CHAT, "%s", text);
+	}
+}
+
+
+/*
+==================
+SV_Say_f
+==================
+*/
+void SV_Say_f(void)
+{
+	SV_Say (false);
+}
+/*
+==================
+SV_Say_Team_f
+==================
+*/
+void SV_Say_Team_f(void)
+{
+	SV_Say (true);
+}
+
+
+
+//============================================================================
+
+/*
+=================
+SV_Pings_f
+
+The client is showing the scoreboard, so send new ping times for all
+clients
+=================
+*/
+void SV_Pings_f (void)
+{
+	client_t *client;
+	int		j;
+
+	for (j = 0, client = svs.clients; j < MAX_CLIENTS; j++, client++)
+	{
+		if (client->state != cs_spawned)
+			continue;
+
+		ClientReliableWrite_Begin (host_client, svc_updateping, 4);
+		ClientReliableWrite_Byte (host_client, j);
+		ClientReliableWrite_Short (host_client, SV_CalcPing(client));
+		ClientReliableWrite_Begin (host_client, svc_updatepl, 4);
+		ClientReliableWrite_Byte (host_client, j);
+		ClientReliableWrite_Byte (host_client, client->lossage);
+	}
+}
+
+
+
+/*
+==================
+SV_Kill_f
+==================
+*/
+void SV_Kill_f (void)
+{
+	if (sv_player->v.health <= 0)
+	{
+		SV_ClientPrintf (host_client, PRINT_HIGH, "Can't suicide -- allready dead!\n");
+		return;
+	}
+	
+	pr_global_struct->time = sv.time;
+	pr_global_struct->self = EDICT_TO_PROG(sv_player);
+	PR_ExecuteProgram (pr_global_struct->ClientKill);
+}
+
+/*
+==================
+SV_TogglePause
+==================
+*/
+void SV_TogglePause (const char *msg)
+{
+	int i;
+	client_t *cl;
+
+	sv.paused ^= 1;
+
+	if (msg)
+		SV_BroadcastPrintf (PRINT_HIGH, "%s", msg);
+
+	// send notification to all clients
+	for (i=0, cl = svs.clients ; i<MAX_CLIENTS ; i++, cl++)
+	{
+		if (!cl->state)
+			continue;
+		ClientReliableWrite_Begin (cl, svc_setpause, 2);
+		ClientReliableWrite_Byte (cl, sv.paused);
+	}
+}
+
+
+/*
+==================
+SV_Pause_f
+==================
+*/
+void SV_Pause_f (void)
+{
+	int i;
+	client_t *cl;
+	char st[sizeof(host_client->name) + 32];
+
+	if (!pausable.value) {
+		SV_ClientPrintf (host_client, PRINT_HIGH, "Pause not allowed.\n");
+		return;
+	}
+
+	if (host_client->spectator) {
+		SV_ClientPrintf (host_client, PRINT_HIGH, "Spectators can not pause.\n");
+		return;
+	}
+
+	if (sv.paused)
+		sprintf (st, "%s paused the game\n", host_client->name);
+	else
+		sprintf (st, "%s unpaused the game\n", host_client->name);
+
+	SV_TogglePause(st);
+}
+
+
+/*
+=================
+SV_Drop_f
+
+The client is going to disconnect, so remove the connection immediately
+=================
+*/
+void SV_Drop_f (void)
+{
+	SV_EndRedirect ();
+	if (!host_client->spectator)
+		SV_BroadcastPrintf (PRINT_HIGH, "%s dropped\n", host_client->name);
+	SV_DropClient (host_client);	
+}
+
+/*
+=================
+SV_PTrack_f
+
+Change the bandwidth estimate for a client
+=================
+*/
+void SV_PTrack_f (void)
+{
+	int		i;
+	edict_t *ent, *tent;
+	
+	if (!host_client->spectator)
+		return;
+
+	if (Cmd_Argc() != 2)
+	{
+		// turn off tracking
+		host_client->spec_track = 0;
+		ent = EDICT_NUM(host_client - svs.clients + 1);
+		tent = EDICT_NUM(0);
+		ent->v.goalentity = EDICT_TO_PROG(tent);
+		return;
+	}
+	
+	i = atoi(Cmd_Argv(1));
+	if (i < 0 || i >= MAX_CLIENTS || svs.clients[i].state != cs_spawned ||
+		svs.clients[i].spectator) {
+		SV_ClientPrintf (host_client, PRINT_HIGH, "Invalid client to track\n");
+		host_client->spec_track = 0;
+		ent = EDICT_NUM(host_client - svs.clients + 1);
+		tent = EDICT_NUM(0);
+		ent->v.goalentity = EDICT_TO_PROG(tent);
+		return;
+	}
+	host_client->spec_track = i + 1; // now tracking
+
+	ent = EDICT_NUM(host_client - svs.clients + 1);
+	tent = EDICT_NUM(i + 1);
+	ent->v.goalentity = EDICT_TO_PROG(tent);
+}
+
+
+/*
+=================
+SV_Rate_f
+
+Change the bandwidth estimate for a client
+=================
+*/
+void SV_Rate_f (void)
+{
+	int		rate;
+	
+	if (Cmd_Argc() != 2)
+	{
+		SV_ClientPrintf (host_client, PRINT_HIGH, "Current rate is %i\n",
+			(int)(1.0/host_client->netchan.rate + 0.5));
+		return;
+	}
+	
+	rate = atoi(Cmd_Argv(1));
+	if (rate < 500)
+		rate = 500;
+	if (rate > 10000)
+		rate = 10000;
+
+	SV_ClientPrintf (host_client, PRINT_HIGH, "Net rate set to %i\n", rate);
+	host_client->netchan.rate = 1.0/rate;
+}
+
+
+/*
+=================
+SV_Msg_f
+
+Change the message level for a client
+=================
+*/
+void SV_Msg_f (void)
+{	
+	if (Cmd_Argc() != 2)
+	{
+		SV_ClientPrintf (host_client, PRINT_HIGH, "Current msg level is %i\n",
+			host_client->messagelevel);
+		return;
+	}
+	
+	host_client->messagelevel = atoi(Cmd_Argv(1));
+
+	SV_ClientPrintf (host_client, PRINT_HIGH, "Msg level set to %i\n", host_client->messagelevel);
+}
+
+/*
+==================
+SV_SetInfo_f
+
+Allow clients to change userinfo
+==================
+*/
+void SV_SetInfo_f (void)
+{
+	int i;
+	char oldval[MAX_INFO_STRING];
+
+
+	if (Cmd_Argc() == 1)
+	{
+		Con_Printf ("User info settings:\n");
+		Info_Print (host_client->userinfo);
+		return;
+	}
+
+	if (Cmd_Argc() != 3)
+	{
+		Con_Printf ("usage: setinfo [ <key> <value> ]\n");
+		return;
+	}
+
+	if (Cmd_Argv(1)[0] == '*')
+		return;		// don't set priveledged values
+
+	strcpy(oldval, Info_ValueForKey(host_client->userinfo, Cmd_Argv(1)));
+
+	Info_SetValueForKey (host_client->userinfo, Cmd_Argv(1), Cmd_Argv(2), MAX_INFO_STRING);
+// name is extracted below in ExtractFromUserInfo
+//	strncpy (host_client->name, Info_ValueForKey (host_client->userinfo, "name")
+//		, sizeof(host_client->name)-1);	
+//	SV_FullClientUpdate (host_client, &sv.reliable_datagram);
+//	host_client->sendinfo = true;
+
+	if (!strcmp(Info_ValueForKey(host_client->userinfo, Cmd_Argv(1)), oldval))
+		return; // key hasn't changed
+
+	// process any changed values
+	SV_ExtractFromUserinfo (host_client);
+
+	i = host_client - svs.clients;
+	MSG_WriteByte (&sv.reliable_datagram, svc_setinfo);
+	MSG_WriteByte (&sv.reliable_datagram, i);
+	MSG_WriteString (&sv.reliable_datagram, Cmd_Argv(1));
+	MSG_WriteString (&sv.reliable_datagram, Info_ValueForKey(host_client->userinfo, Cmd_Argv(1)));
+}
+
+/*
+==================
+SV_ShowServerinfo_f
+
+Dumps the serverinfo info string
+==================
+*/
+void SV_ShowServerinfo_f (void)
+{
+	Info_Print (svs.info);
+}
+
+void SV_NoSnap_f(void)
+{
+	if (*host_client->uploadfn) {
+		*host_client->uploadfn = 0;
+		SV_BroadcastPrintf (PRINT_HIGH, "%s refused remote screenshot\n", host_client->name);
+	}
+}
+
+typedef struct
+{
+	char	*name;
+	void	(*func) (void);
+} ucmd_t;
+
+ucmd_t ucmds[] =
+{
+	{"new", SV_New_f},
+	{"modellist", SV_Modellist_f},
+	{"soundlist", SV_Soundlist_f},
+	{"prespawn", SV_PreSpawn_f},
+	{"spawn", SV_Spawn_f},
+	{"begin", SV_Begin_f},
+
+	{"drop", SV_Drop_f},
+	{"pings", SV_Pings_f},
+
+// issued by hand at client consoles	
+	{"rate", SV_Rate_f},
+	{"kill", SV_Kill_f},
+	{"pause", SV_Pause_f},
+	{"msg", SV_Msg_f},
+
+	{"say", SV_Say_f},
+	{"say_team", SV_Say_Team_f},
+
+	{"setinfo", SV_SetInfo_f},
+
+	{"serverinfo", SV_ShowServerinfo_f},
+
+	{"download", SV_BeginDownload_f},
+	{"nextdl", SV_NextDownload_f},
+
+	{"ptrack", SV_PTrack_f}, //ZOID - used with autocam
+
+	{"snap", SV_NoSnap_f},
+	
+	{NULL, NULL}
+};
+
+/*
+==================
+SV_ExecuteUserCommand
+==================
+*/
+void SV_ExecuteUserCommand (char *s)
+{
+	ucmd_t	*u;
+	
+	Cmd_TokenizeString (s);
+	sv_player = host_client->edict;
+
+	SV_BeginRedirect (RD_CLIENT);
+
+	for (u=ucmds ; u->name ; u++)
+		if (!strcmp (Cmd_Argv(0), u->name) )
+		{
+			u->func ();
+			break;
+		}
+
+	if (!u->name)
+		Con_Printf ("Bad user command: %s\n", Cmd_Argv(0));
+
+	SV_EndRedirect ();
+}
+
+/*
+===========================================================================
+
+USER CMD EXECUTION
+
+===========================================================================
+*/
+
+/*
+===============
+V_CalcRoll
+
+Used by view and sv_user
+===============
+*/
+float V_CalcRoll (vec3_t angles, vec3_t velocity)
+{
+	vec3_t	forward, right, up;
+	float	sign;
+	float	side;
+	float	value;
+	
+	AngleVectors (angles, forward, right, up);
+	side = DotProduct (velocity, right);
+	sign = side < 0 ? -1 : 1;
+	side = fabs(side);
+	
+	value = cl_rollangle.value;
+
+	if (side < cl_rollspeed.value)
+		side = side * value / cl_rollspeed.value;
+	else
+		side = value;
+	
+	return side*sign;
+	
+}
+
+
+
+
+//============================================================================
+
+vec3_t	pmove_mins, pmove_maxs;
+
+/*
+====================
+AddLinksToPmove
+
+====================
+*/
+void AddLinksToPmove ( areanode_t *node )
+{
+	link_t		*l, *next;
+	edict_t		*check;
+	int			pl;
+	int			i;
+	physent_t	*pe;
+
+	pl = EDICT_TO_PROG(sv_player);
+
+	// touch linked edicts
+	for (l = node->solid_edicts.next ; l != &node->solid_edicts ; l = next)
+	{
+		next = l->next;
+		check = EDICT_FROM_AREA(l);
+
+		if (check->v.owner == pl)
+			continue;		// player's own missile
+		if (check->v.solid == SOLID_BSP 
+			|| check->v.solid == SOLID_BBOX 
+			|| check->v.solid == SOLID_SLIDEBOX)
+		{
+			if (check == sv_player)
+				continue;
+
+			for (i=0 ; i<3 ; i++)
+				if (check->v.absmin[i] > pmove_maxs[i]
+				|| check->v.absmax[i] < pmove_mins[i])
+					break;
+			if (i != 3)
+				continue;
+			if (pmove.numphysent == MAX_PHYSENTS)
+				return;
+			pe = &pmove.physents[pmove.numphysent];
+			pmove.numphysent++;
+
+			VectorCopy (check->v.origin, pe->origin);
+			pe->info = NUM_FOR_EDICT(check);
+			if (check->v.solid == SOLID_BSP)
+				pe->model = sv.models[(int)(check->v.modelindex)];
+			else
+			{
+				pe->model = NULL;
+				VectorCopy (check->v.mins, pe->mins);
+				VectorCopy (check->v.maxs, pe->maxs);
+			}
+		}
+	}
+	
+// recurse down both sides
+	if (node->axis == -1)
+		return;
+
+	if ( pmove_maxs[node->axis] > node->dist )
+		AddLinksToPmove ( node->children[0] );
+	if ( pmove_mins[node->axis] < node->dist )
+		AddLinksToPmove ( node->children[1] );
+}
+
+
+/*
+================
+AddAllEntsToPmove
+
+For debugging
+================
+*/
+void AddAllEntsToPmove (void)
+{
+	int			e;
+	edict_t		*check;
+	int			i;
+	physent_t	*pe;
+	int			pl;
+
+	pl = EDICT_TO_PROG(sv_player);
+	check = NEXT_EDICT(sv.edicts);
+	for (e=1 ; e<sv.num_edicts ; e++, check = NEXT_EDICT(check))
+	{
+		if (check->free)
+			continue;
+		if (check->v.owner == pl)
+			continue;
+		if (check->v.solid == SOLID_BSP 
+			|| check->v.solid == SOLID_BBOX 
+			|| check->v.solid == SOLID_SLIDEBOX)
+		{
+			if (check == sv_player)
+				continue;
+
+			for (i=0 ; i<3 ; i++)
+				if (check->v.absmin[i] > pmove_maxs[i]
+				|| check->v.absmax[i] < pmove_mins[i])
+					break;
+			if (i != 3)
+				continue;
+			pe = &pmove.physents[pmove.numphysent];
+
+			VectorCopy (check->v.origin, pe->origin);
+			pmove.physents[pmove.numphysent].info = e;
+			if (check->v.solid == SOLID_BSP)
+				pe->model = sv.models[(int)(check->v.modelindex)];
+			else
+			{
+				pe->model = NULL;
+				VectorCopy (check->v.mins, pe->mins);
+				VectorCopy (check->v.maxs, pe->maxs);
+			}
+
+			if (++pmove.numphysent == MAX_PHYSENTS)
+				break;
+		}
+	}
+}
+
+/*
+===========
+SV_PreRunCmd
+===========
+Done before running a player command.  Clears the touch array
+*/
+byte playertouch[(MAX_EDICTS+7)/8];
+
+void SV_PreRunCmd(void)
+{
+	memset(playertouch, 0, sizeof(playertouch));
+}
+
+/*
+===========
+SV_RunCmd
+===========
+*/
+void SV_RunCmd (usercmd_t *ucmd)
+{
+	edict_t		*ent;
+	int			i, n;
+	int			oldmsec;
+
+	cmd = *ucmd;
+
+	// chop up very long commands
+	if (cmd.msec > 50)
+	{
+		oldmsec = ucmd->msec;
+		cmd.msec = oldmsec/2;
+		SV_RunCmd (&cmd);
+		cmd.msec = oldmsec/2;
+		cmd.impulse = 0;
+		SV_RunCmd (&cmd);
+		return;
+	}
+
+	if (!sv_player->v.fixangle)
+		VectorCopy (ucmd->angles, sv_player->v.v_angle);
+
+	sv_player->v.button0 = ucmd->buttons & 1;
+	sv_player->v.button2 = (ucmd->buttons & 2)>>1;
+	if (ucmd->impulse)
+		sv_player->v.impulse = ucmd->impulse;
+
+//
+// angles
+// show 1/3 the pitch angle and all the roll angle	
+	if (sv_player->v.health > 0)
+	{
+		if (!sv_player->v.fixangle)
+		{
+			sv_player->v.angles[PITCH] = -sv_player->v.v_angle[PITCH]/3;
+			sv_player->v.angles[YAW] = sv_player->v.v_angle[YAW];
+		}
+		sv_player->v.angles[ROLL] = 
+			V_CalcRoll (sv_player->v.angles, sv_player->v.velocity)*4;
+	}
+
+	host_frametime = ucmd->msec * 0.001;
+	if (host_frametime > 0.1)
+		host_frametime = 0.1;
+
+	if (!host_client->spectator)
+	{
+		pr_global_struct->frametime = host_frametime;
+
+		pr_global_struct->time = sv.time;
+		pr_global_struct->self = EDICT_TO_PROG(sv_player);
+		PR_ExecuteProgram (pr_global_struct->PlayerPreThink);
+
+		SV_RunThink (sv_player);
+	}
+
+	for (i=0 ; i<3 ; i++)
+		pmove.origin[i] = sv_player->v.origin[i] + (sv_player->v.mins[i] - player_mins[i]);
+	VectorCopy (sv_player->v.velocity, pmove.velocity);
+	VectorCopy (sv_player->v.v_angle, pmove.angles);
+
+	pmove.spectator = host_client->spectator;
+	pmove.waterjumptime = sv_player->v.teleport_time;
+	pmove.numphysent = 1;
+	pmove.physents[0].model = sv.worldmodel;
+	pmove.cmd = *ucmd;
+	pmove.dead = sv_player->v.health <= 0;
+	pmove.oldbuttons = host_client->oldbuttons;
+
+	movevars.entgravity = host_client->entgravity;
+	movevars.maxspeed = host_client->maxspeed;
+
+	for (i=0 ; i<3 ; i++)
+	{
+		pmove_mins[i] = pmove.origin[i] - 256;
+		pmove_maxs[i] = pmove.origin[i] + 256;
+	}
+#if 1
+	AddLinksToPmove ( sv_areanodes );
+#else
+	AddAllEntsToPmove ();
+#endif
+
+#if 0
+{
+	int before, after;
+
+before = PM_TestPlayerPosition (pmove.origin);
+	PlayerMove ();
+after = PM_TestPlayerPosition (pmove.origin);
+
+if (sv_player->v.health > 0 && before && !after )
+	Con_Printf ("player %s got stuck in playermove!!!!\n", host_client->name);
+}
+#else
+	PlayerMove ();
+#endif
+
+	host_client->oldbuttons = pmove.oldbuttons;
+	sv_player->v.teleport_time = pmove.waterjumptime;
+	sv_player->v.waterlevel = waterlevel;
+	sv_player->v.watertype = watertype;
+	if (onground != -1)
+	{
+		sv_player->v.flags = (int)sv_player->v.flags | FL_ONGROUND;
+		sv_player->v.groundentity = EDICT_TO_PROG(EDICT_NUM(pmove.physents[onground].info));
+	}
+	else
+		sv_player->v.flags = (int)sv_player->v.flags & ~FL_ONGROUND;
+	for (i=0 ; i<3 ; i++)
+		sv_player->v.origin[i] = pmove.origin[i] - (sv_player->v.mins[i] - player_mins[i]);
+
+#if 0
+	// truncate velocity the same way the net protocol will
+	for (i=0 ; i<3 ; i++)
+		sv_player->v.velocity[i] = (int)pmove.velocity[i];
+#else
+	VectorCopy (pmove.velocity, sv_player->v.velocity);
+#endif
+
+	VectorCopy (pmove.angles, sv_player->v.v_angle);
+
+	if (!host_client->spectator)
+	{
+		// link into place and touch triggers
+		SV_LinkEdict (sv_player, true);
+
+		// touch other objects
+		for (i=0 ; i<pmove.numtouch ; i++)
+		{
+			n = pmove.physents[pmove.touchindex[i]].info;
+			ent = EDICT_NUM(n);
+			if (!ent->v.touch || (playertouch[n/8]&(1<<(n%8))))
+				continue;
+			pr_global_struct->self = EDICT_TO_PROG(ent);
+			pr_global_struct->other = EDICT_TO_PROG(sv_player);
+			PR_ExecuteProgram (ent->v.touch);
+			playertouch[n/8] |= 1 << (n%8);
+		}
+	}
+}
+
+/*
+===========
+SV_PostRunCmd
+===========
+Done after running a player command.
+*/
+void SV_PostRunCmd(void)
+{
+	// run post-think
+
+	if (!host_client->spectator) {
+		pr_global_struct->time = sv.time;
+		pr_global_struct->self = EDICT_TO_PROG(sv_player);
+		PR_ExecuteProgram (pr_global_struct->PlayerPostThink);
+		SV_RunNewmis ();
+	} else if (SpectatorThink) {
+		pr_global_struct->time = sv.time;
+		pr_global_struct->self = EDICT_TO_PROG(sv_player);
+		PR_ExecuteProgram (SpectatorThink);
+	}
+}
+
+
+/*
+===================
+SV_ExecuteClientMessage
+
+The current net_message is parsed for the given client
+===================
+*/
+void SV_ExecuteClientMessage (client_t *cl)
+{
+	int		c;
+	char	*s;
+	usercmd_t	oldest, oldcmd, newcmd;
+	client_frame_t	*frame;
+	vec3_t o;
+	qboolean	move_issued = false; //only allow one move command
+	int		checksumIndex;
+	byte	checksum, calculatedChecksum;
+	int		seq_hash;
+
+	// calc ping time
+	frame = &cl->frames[cl->netchan.incoming_acknowledged & UPDATE_MASK];
+	frame->ping_time = realtime - frame->senttime;
+
+	// make sure the reply sequence number matches the incoming
+	// sequence number 
+	if (cl->netchan.incoming_sequence >= cl->netchan.outgoing_sequence)
+		cl->netchan.outgoing_sequence = cl->netchan.incoming_sequence;
+	else
+		cl->send_message = false;	// don't reply, sequences have slipped		
+
+	// save time for ping calculations
+	cl->frames[cl->netchan.outgoing_sequence & UPDATE_MASK].senttime = realtime;
+	cl->frames[cl->netchan.outgoing_sequence & UPDATE_MASK].ping_time = -1;
+
+	host_client = cl;
+	sv_player = host_client->edict;
+
+//	seq_hash = (cl->netchan.incoming_sequence & 0xffff) ; // ^ QW_CHECK_HASH;
+	seq_hash = cl->netchan.incoming_sequence;
+	
+	// mark time so clients will know how much to predict
+	// other players
+ 	cl->localtime = sv.time;
+	cl->delta_sequence = -1;	// no delta unless requested
+	while (1)
+	{
+		if (msg_badread)
+		{
+			Con_Printf ("SV_ReadClientMessage: badread\n");
+			SV_DropClient (cl);
+			return;
+		}	
+
+		c = MSG_ReadByte ();
+		if (c == -1)
+			break;
+				
+		switch (c)
+		{
+		default:
+			Con_Printf ("SV_ReadClientMessage: unknown command char\n");
+			SV_DropClient (cl);
+			return;
+						
+		case clc_nop:
+			break;
+
+		case clc_delta:
+			cl->delta_sequence = MSG_ReadByte ();
+			break;
+
+		case clc_move:
+			if (move_issued)
+				return;		// someone is trying to cheat...
+
+			move_issued = true;
+
+			checksumIndex = MSG_GetReadCount();
+			checksum = (byte)MSG_ReadByte ();
+
+			// read loss percentage
+			cl->lossage = MSG_ReadByte();
+
+			MSG_ReadDeltaUsercmd (&nullcmd, &oldest);
+			MSG_ReadDeltaUsercmd (&oldest, &oldcmd);
+			MSG_ReadDeltaUsercmd (&oldcmd, &newcmd);
+
+			if ( cl->state != cs_spawned )
+				break;
+
+			// if the checksum fails, ignore the rest of the packet
+			calculatedChecksum = COM_BlockSequenceCRCByte(
+				net_message.data + checksumIndex + 1,
+				MSG_GetReadCount() - checksumIndex - 1,
+				seq_hash);
+
+			if (calculatedChecksum != checksum)
+			{
+				Con_DPrintf ("Failed command checksum for %s(%d) (%d != %d)\n", 
+					cl->name, cl->netchan.incoming_sequence, checksum, calculatedChecksum);
+				return;
+			}
+
+			if (!sv.paused) {
+				SV_PreRunCmd();
+
+				if (net_drop < 20)
+				{
+					while (net_drop > 2)
+					{
+						SV_RunCmd (&cl->lastcmd);
+						net_drop--;
+					}
+					if (net_drop > 1)
+						SV_RunCmd (&oldest);
+					if (net_drop > 0)
+						SV_RunCmd (&oldcmd);
+				}
+				SV_RunCmd (&newcmd);
+
+				SV_PostRunCmd();
+			}
+
+			cl->lastcmd = newcmd;
+			cl->lastcmd.buttons = 0; // avoid multiple fires on lag
+			break;
+
+
+		case clc_stringcmd:	
+			s = MSG_ReadString ();
+			SV_ExecuteUserCommand (s);
+			break;
+
+		case clc_tmove:
+			o[0] = MSG_ReadCoord();
+			o[1] = MSG_ReadCoord();
+			o[2] = MSG_ReadCoord();
+			// only allowed by spectators
+			if (host_client->spectator) {
+				VectorCopy(o, sv_player->v.origin);
+				SV_LinkEdict(sv_player, false);
+			}
+			break;
+
+		case clc_upload:
+			SV_NextUpload();
+			break;
+
+		}
+	}
+}
+
+/*
+==============
+SV_UserInit
+==============
+*/
+void SV_UserInit (void)
+{
+	Cvar_RegisterVariable (&cl_rollspeed);
+	Cvar_RegisterVariable (&cl_rollangle);
+	Cvar_RegisterVariable (&sv_spectalk);
+	Cvar_RegisterVariable (&sv_mapcheck);
+}
+
+
--- /dev/null
+++ b/QW/server/sys.h
@@ -1,0 +1,35 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// sys.h -- non-portable functions
+
+int	Sys_FileTime (char *path);
+
+void Sys_mkdir (char *path);
+
+void Sys_Error (char *error, ...);
+// an error will cause the entire program to exit
+
+void Sys_Printf (char *fmt, ...);
+// send text to the console
+
+void Sys_Quit (void);
+double Sys_DoubleTime (void);
+char *Sys_ConsoleInput (void);
+void Sys_Init (void);
--- /dev/null
+++ b/QW/server/sys_unix.c
@@ -1,0 +1,283 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+#include <sys/types.h>
+#include "qwsvdef.h"
+
+#ifdef NeXT
+#include <libc.h>
+#endif
+
+#if defined(__linux__) || defined(sun)
+#include <sys/stat.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <errno.h>
+#else
+#include <sys/dir.h>
+#endif
+
+cvar_t	sys_nostdout = {"sys_nostdout","0"};
+cvar_t	sys_extrasleep = {"sys_extrasleep","0"};
+
+qboolean	stdin_ready;
+
+/*
+===============================================================================
+
+				REQUIRED SYS FUNCTIONS
+
+===============================================================================
+*/
+
+/*
+============
+Sys_FileTime
+
+returns -1 if not present
+============
+*/
+int	Sys_FileTime (char *path)
+{
+	struct	stat	buf;
+	
+	if (stat (path,&buf) == -1)
+		return -1;
+	
+	return buf.st_mtime;
+}
+
+
+/*
+============
+Sys_mkdir
+
+============
+*/
+void Sys_mkdir (char *path)
+{
+	if (mkdir (path, 0777) != -1)
+		return;
+	if (errno != EEXIST)
+		Sys_Error ("mkdir %s: %s",path, strerror(errno)); 
+}
+
+
+/*
+================
+Sys_DoubleTime
+================
+*/
+double Sys_DoubleTime (void)
+{
+	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;
+}
+
+/*
+================
+Sys_Error
+================
+*/
+void Sys_Error (char *error, ...)
+{
+	va_list		argptr;
+	char		string[1024];
+	
+	va_start (argptr,error);
+	vsprintf (string,error,argptr);
+	va_end (argptr);
+	printf ("Fatal error: %s\n",string);
+	
+	exit (1);
+}
+
+/*
+================
+Sys_Printf
+================
+*/
+void Sys_Printf (char *fmt, ...)
+{
+	va_list		argptr;
+	static char		text[2048];
+	unsigned char		*p;
+
+	va_start (argptr,fmt);
+	vsprintf (text,fmt,argptr);
+	va_end (argptr);
+
+	if (strlen(text) > sizeof(text))
+		Sys_Error("memory overwrite in Sys_Printf");
+
+    if (sys_nostdout.value)
+        return;
+
+	for (p = (unsigned char *)text; *p; p++) {
+		*p &= 0x7f;
+		if ((*p > 128 || *p < 32) && *p != 10 && *p != 13 && *p != 9)
+			printf("[%02x]", *p);
+		else
+			putc(*p, stdout);
+	}
+	fflush(stdout);
+}
+
+
+/*
+================
+Sys_Quit
+================
+*/
+void Sys_Quit (void)
+{
+	exit (0);		// appkit isn't running
+}
+
+static int do_stdin = 1;
+
+/*
+================
+Sys_ConsoleInput
+
+Checks for a complete line of text typed in at the console, then forwards
+it to the host command processor
+================
+*/
+char *Sys_ConsoleInput (void)
+{
+	static char	text[256];
+	int		len;
+
+	if (!stdin_ready || !do_stdin)
+		return NULL;		// the select didn't say it was ready
+	stdin_ready = false;
+
+	len = read (0, text, sizeof(text));
+	if (len == 0) {
+		// end of file
+		do_stdin = 0;
+		return NULL;
+	}
+	if (len < 1)
+		return NULL;
+	text[len-1] = 0;	// rip off the /n and terminate
+	
+	return text;
+}
+
+/*
+=============
+Sys_Init
+
+Quake calls this so the system can register variables before host_hunklevel
+is marked
+=============
+*/
+void Sys_Init (void)
+{
+	Cvar_RegisterVariable (&sys_nostdout);
+	Cvar_RegisterVariable (&sys_extrasleep);
+}
+
+/*
+=============
+main
+=============
+*/
+void main(int argc, char *argv[])
+{
+	double			time, oldtime, newtime;
+	quakeparms_t	parms;
+	fd_set	fdset;
+	extern	int		net_socket;
+    struct timeval timeout;
+	int j;
+
+	memset (&parms, 0, sizeof(parms));
+
+	COM_InitArgv (argc, argv);	
+	parms.argc = com_argc;
+	parms.argv = com_argv;
+
+	parms.memsize = 16*1024*1024;
+
+	j = COM_CheckParm("-mem");
+	if (j)
+		parms.memsize = (int) (Q_atof(com_argv[j+1]) * 1024 * 1024);
+	if ((parms.membase = malloc (parms.memsize)) == NULL)
+		Sys_Error("Can't allocate %ld\n", parms.memsize);
+
+	parms.basedir = ".";
+
+/*
+	if (Sys_FileTime ("id1/pak0.pak") != -1)
+	else
+		parms.basedir = "/raid/quake/v2";
+*/
+
+	SV_Init (&parms);
+
+// run one frame immediately for first heartbeat
+	SV_Frame (0.1);		
+
+//
+// main loop
+//
+	oldtime = Sys_DoubleTime () - 0.1;
+	while (1)
+	{
+	// select on the net socket and stdin
+	// the only reason we have a timeout at all is so that if the last
+	// connected client times out, the message would not otherwise
+	// be printed until the next event.
+		FD_ZERO(&fdset);
+		if (do_stdin)
+			FD_SET(0, &fdset);
+		FD_SET(net_socket, &fdset);
+		timeout.tv_sec = 1;
+		timeout.tv_usec = 0;
+		if (select (net_socket+1, &fdset, NULL, NULL, &timeout) == -1)
+			continue;
+		stdin_ready = FD_ISSET(0, &fdset);
+
+	// find time passed since last cycle
+		newtime = Sys_DoubleTime ();
+		time = newtime - oldtime;
+		oldtime = newtime;
+		
+		SV_Frame (time);		
+		
+	// extrasleep is just a way to generate a fucked up connection on purpose
+		if (sys_extrasleep.value)
+			usleep (sys_extrasleep.value);
+	}	
+}
+
--- /dev/null
+++ b/QW/server/sys_win.c
@@ -1,0 +1,260 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+#include <sys/types.h>
+#include <sys/timeb.h>
+#include "qwsvdef.h"
+#include <winsock.h>
+#include <conio.h>
+
+
+cvar_t	sys_nostdout = {"sys_nostdout","0"};
+
+/*
+================
+Sys_FileTime
+================
+*/
+int	Sys_FileTime (char *path)
+{
+	FILE	*f;
+	
+	f = fopen(path, "rb");
+	if (f)
+	{
+		fclose(f);
+		return 1;
+	}
+	
+	return -1;
+}
+
+/*
+================
+Sys_mkdir
+================
+*/
+void Sys_mkdir (char *path)
+{
+	_mkdir(path);
+}
+
+
+/*
+================
+Sys_Error
+================
+*/
+void Sys_Error (char *error, ...)
+{
+	va_list		argptr;
+	char		text[1024];
+
+	va_start (argptr,error);
+	vsprintf (text, error,argptr);
+	va_end (argptr);
+
+//    MessageBox(NULL, text, "Error", 0 /* MB_OK */ );
+	printf ("ERROR: %s\n", text);
+
+	exit (1);
+}
+
+
+/*
+================
+Sys_DoubleTime
+================
+*/
+double Sys_DoubleTime (void)
+{
+	double t;
+    struct _timeb tstruct;
+	static int	starttime;
+
+	_ftime( &tstruct );
+ 
+	if (!starttime)
+		starttime = tstruct.time;
+	t = (tstruct.time-starttime) + tstruct.millitm*0.001;
+	
+	return t;
+}
+
+
+/*
+================
+Sys_ConsoleInput
+================
+*/
+char *Sys_ConsoleInput (void)
+{
+	static char	text[256];
+	static int		len;
+	int		c;
+
+	// read a line out
+	while (_kbhit())
+	{
+		c = _getch();
+		putch (c);
+		if (c == '\r')
+		{
+			text[len] = 0;
+			putch ('\n');
+			len = 0;
+			return text;
+		}
+		if (c == 8)
+		{
+			if (len)
+			{
+				putch (' ');
+				putch (c);
+				len--;
+				text[len] = 0;
+			}
+			continue;
+		}
+		text[len] = c;
+		len++;
+		text[len] = 0;
+		if (len == sizeof(text))
+			len = 0;
+	}
+
+	return NULL;
+}
+
+
+/*
+================
+Sys_Printf
+================
+*/
+void Sys_Printf (char *fmt, ...)
+{
+	va_list		argptr;
+	
+	if (sys_nostdout.value)
+		return;
+		
+	va_start (argptr,fmt);
+	vprintf (fmt,argptr);
+	va_end (argptr);
+}
+
+/*
+================
+Sys_Quit
+================
+*/
+void Sys_Quit (void)
+{
+	exit (0);
+}
+
+
+/*
+=============
+Sys_Init
+
+Quake calls this so the system can register variables before host_hunklevel
+is marked
+=============
+*/
+void Sys_Init (void)
+{
+	Cvar_RegisterVariable (&sys_nostdout);
+}
+
+/*
+==================
+main
+
+==================
+*/
+char	*newargv[256];
+
+int main (int argc, char **argv)
+{
+	quakeparms_t	parms;
+	double			newtime, time, oldtime;
+	static	char	cwd[1024];
+	struct timeval	timeout;
+	fd_set			fdset;
+	int				t;
+
+	COM_InitArgv (argc, argv);
+	
+	parms.argc = com_argc;
+	parms.argv = com_argv;
+
+	parms.memsize = 16*1024*1024;
+
+	if ((t = COM_CheckParm ("-heapsize")) != 0 &&
+		t + 1 < com_argc)
+		parms.memsize = Q_atoi (com_argv[t + 1]) * 1024;
+
+	if ((t = COM_CheckParm ("-mem")) != 0 &&
+		t + 1 < com_argc)
+		parms.memsize = Q_atoi (com_argv[t + 1]) * 1024 * 1024;
+
+	parms.membase = malloc (parms.memsize);
+
+	if (!parms.membase)
+		Sys_Error("Insufficient memory.\n");
+
+	parms.basedir = ".";
+	parms.cachedir = NULL;
+
+	SV_Init (&parms);
+
+// run one frame immediately for first heartbeat
+	SV_Frame (0.1);		
+
+//
+// main loop
+//
+	oldtime = Sys_DoubleTime () - 0.1;
+	while (1)
+	{
+	// select on the net socket and stdin
+	// the only reason we have a timeout at all is so that if the last
+	// connected client times out, the message would not otherwise
+	// be printed until the next event.
+		FD_ZERO(&fdset);
+		FD_SET(net_socket, &fdset);
+		timeout.tv_sec = 0;
+		timeout.tv_usec = 100;
+		if (select (net_socket+1, &fdset, NULL, NULL, &timeout) == -1)
+			continue;
+
+	// find time passed since last cycle
+		newtime = Sys_DoubleTime ();
+		time = newtime - oldtime;
+		oldtime = newtime;
+		
+		SV_Frame (time);				
+	}	
+
+	return true;
+}
+
+
--- /dev/null
+++ b/QW/server/world.c
@@ -1,0 +1,924 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// world.c -- world query functions
+
+#include "qwsvdef.h"
+
+/*
+
+entities never clip against themselves, or their owner
+
+line of sight checks trace->crosscontent, but bullets don't
+
+*/
+
+
+typedef struct
+{
+	vec3_t		boxmins, boxmaxs;// enclose the test object along entire move
+	float		*mins, *maxs;	// size of the moving object
+	vec3_t		mins2, maxs2;	// size when clipping against mosnters
+	float		*start, *end;
+	trace_t		trace;
+	int			type;
+	edict_t		*passedict;
+} moveclip_t;
+
+
+int SV_HullPointContents (hull_t *hull, int num, vec3_t p);
+
+/*
+===============================================================================
+
+HULL BOXES
+
+===============================================================================
+*/
+
+
+static	hull_t		box_hull;
+static	dclipnode_t	box_clipnodes[6];
+static	mplane_t	box_planes[6];
+
+/*
+===================
+SV_InitBoxHull
+
+Set up the planes and clipnodes so that the six floats of a bounding box
+can just be stored out and get a proper hull_t structure.
+===================
+*/
+void SV_InitBoxHull (void)
+{
+	int		i;
+	int		side;
+
+	box_hull.clipnodes = box_clipnodes;
+	box_hull.planes = box_planes;
+	box_hull.firstclipnode = 0;
+	box_hull.lastclipnode = 5;
+
+	for (i=0 ; i<6 ; i++)
+	{
+		box_clipnodes[i].planenum = i;
+		
+		side = i&1;
+		
+		box_clipnodes[i].children[side] = CONTENTS_EMPTY;
+		if (i != 5)
+			box_clipnodes[i].children[side^1] = i + 1;
+		else
+			box_clipnodes[i].children[side^1] = CONTENTS_SOLID;
+		
+		box_planes[i].type = i>>1;
+		box_planes[i].normal[i>>1] = 1;
+	}
+	
+}
+
+
+/*
+===================
+SV_HullForBox
+
+To keep everything totally uniform, bounding boxes are turned into small
+BSP trees instead of being compared directly.
+===================
+*/
+hull_t	*SV_HullForBox (vec3_t mins, vec3_t maxs)
+{
+	box_planes[0].dist = maxs[0];
+	box_planes[1].dist = mins[0];
+	box_planes[2].dist = maxs[1];
+	box_planes[3].dist = mins[1];
+	box_planes[4].dist = maxs[2];
+	box_planes[5].dist = mins[2];
+
+	return &box_hull;
+}
+
+
+
+/*
+================
+SV_HullForEntity
+
+Returns a hull that can be used for testing or clipping an object of mins/maxs
+size.
+Offset is filled in to contain the adjustment that must be added to the
+testing object's origin to get a point to use with the returned hull.
+================
+*/
+hull_t *SV_HullForEntity (edict_t *ent, vec3_t mins, vec3_t maxs, vec3_t offset)
+{
+	model_t		*model;
+	vec3_t		size;
+	vec3_t		hullmins, hullmaxs;
+	hull_t		*hull;
+
+// decide which clipping hull to use, based on the size
+	if (ent->v.solid == SOLID_BSP)
+	{	// explicit hulls in the BSP model
+		if (ent->v.movetype != MOVETYPE_PUSH)
+			SV_Error ("SOLID_BSP without MOVETYPE_PUSH");
+
+		model = sv.models[ (int)ent->v.modelindex ];
+
+		if (!model || model->type != mod_brush)
+			SV_Error ("MOVETYPE_PUSH with a non bsp model");
+
+		VectorSubtract (maxs, mins, size);
+		if (size[0] < 3)
+			hull = &model->hulls[0];
+		else if (size[0] <= 32)
+			hull = &model->hulls[1];
+		else
+			hull = &model->hulls[2];
+
+// calculate an offset value to center the origin
+		VectorSubtract (hull->clip_mins, mins, offset);
+		VectorAdd (offset, ent->v.origin, offset);
+	}
+	else
+	{	// create a temp hull from bounding box sizes
+
+		VectorSubtract (ent->v.mins, maxs, hullmins);
+		VectorSubtract (ent->v.maxs, mins, hullmaxs);
+		hull = SV_HullForBox (hullmins, hullmaxs);
+		
+		VectorCopy (ent->v.origin, offset);
+	}
+
+
+	return hull;
+}
+
+/*
+===============================================================================
+
+ENTITY AREA CHECKING
+
+===============================================================================
+*/
+
+
+areanode_t	sv_areanodes[AREA_NODES];
+int			sv_numareanodes;
+
+/*
+===============
+SV_CreateAreaNode
+
+===============
+*/
+areanode_t *SV_CreateAreaNode (int depth, vec3_t mins, vec3_t maxs)
+{
+	areanode_t	*anode;
+	vec3_t		size;
+	vec3_t		mins1, maxs1, mins2, maxs2;
+
+	anode = &sv_areanodes[sv_numareanodes];
+	sv_numareanodes++;
+
+	ClearLink (&anode->trigger_edicts);
+	ClearLink (&anode->solid_edicts);
+	
+	if (depth == AREA_DEPTH)
+	{
+		anode->axis = -1;
+		anode->children[0] = anode->children[1] = NULL;
+		return anode;
+	}
+	
+	VectorSubtract (maxs, mins, size);
+	if (size[0] > size[1])
+		anode->axis = 0;
+	else
+		anode->axis = 1;
+	
+	anode->dist = 0.5 * (maxs[anode->axis] + mins[anode->axis]);
+	VectorCopy (mins, mins1);	
+	VectorCopy (mins, mins2);	
+	VectorCopy (maxs, maxs1);	
+	VectorCopy (maxs, maxs2);	
+	
+	maxs1[anode->axis] = mins2[anode->axis] = anode->dist;
+	
+	anode->children[0] = SV_CreateAreaNode (depth+1, mins2, maxs2);
+	anode->children[1] = SV_CreateAreaNode (depth+1, mins1, maxs1);
+
+	return anode;
+}
+
+/*
+===============
+SV_ClearWorld
+
+===============
+*/
+void SV_ClearWorld (void)
+{
+	SV_InitBoxHull ();
+	
+	memset (sv_areanodes, 0, sizeof(sv_areanodes));
+	sv_numareanodes = 0;
+	SV_CreateAreaNode (0, sv.worldmodel->mins, sv.worldmodel->maxs);
+}
+
+
+/*
+===============
+SV_UnlinkEdict
+
+===============
+*/
+void SV_UnlinkEdict (edict_t *ent)
+{
+	if (!ent->area.prev)
+		return;		// not linked in anywhere
+	RemoveLink (&ent->area);
+	ent->area.prev = ent->area.next = NULL;
+}
+
+
+/*
+====================
+SV_TouchLinks
+====================
+*/
+void SV_TouchLinks ( edict_t *ent, areanode_t *node )
+{
+	link_t		*l, *next;
+	edict_t		*touch;
+	int			old_self, old_other;
+
+// touch linked edicts
+	for (l = node->trigger_edicts.next ; l != &node->trigger_edicts ; l = next)
+	{
+		next = l->next;
+		touch = EDICT_FROM_AREA(l);
+		if (touch == ent)
+			continue;
+		if (!touch->v.touch || touch->v.solid != SOLID_TRIGGER)
+			continue;
+		if (ent->v.absmin[0] > touch->v.absmax[0]
+		|| ent->v.absmin[1] > touch->v.absmax[1]
+		|| ent->v.absmin[2] > touch->v.absmax[2]
+		|| ent->v.absmax[0] < touch->v.absmin[0]
+		|| ent->v.absmax[1] < touch->v.absmin[1]
+		|| ent->v.absmax[2] < touch->v.absmin[2] )
+			continue;
+			
+		old_self = pr_global_struct->self;
+		old_other = pr_global_struct->other;
+
+		pr_global_struct->self = EDICT_TO_PROG(touch);
+		pr_global_struct->other = EDICT_TO_PROG(ent);
+		pr_global_struct->time = sv.time;
+		PR_ExecuteProgram (touch->v.touch);
+
+		pr_global_struct->self = old_self;
+		pr_global_struct->other = old_other;
+	}
+	
+// recurse down both sides
+	if (node->axis == -1)
+		return;
+	
+	if ( ent->v.absmax[node->axis] > node->dist )
+		SV_TouchLinks ( ent, node->children[0] );
+	if ( ent->v.absmin[node->axis] < node->dist )
+		SV_TouchLinks ( ent, node->children[1] );
+}
+
+
+/*
+===============
+SV_FindTouchedLeafs
+
+===============
+*/
+void SV_FindTouchedLeafs (edict_t *ent, mnode_t *node)
+{
+	mplane_t	*splitplane;
+	mleaf_t		*leaf;
+	int			sides;
+	int			leafnum;
+
+	if (node->contents == CONTENTS_SOLID)
+		return;
+	
+// add an efrag if the node is a leaf
+
+	if ( node->contents < 0)
+	{
+		if (ent->num_leafs == MAX_ENT_LEAFS)
+			return;
+
+		leaf = (mleaf_t *)node;
+		leafnum = leaf - sv.worldmodel->leafs - 1;
+
+		ent->leafnums[ent->num_leafs] = leafnum;
+		ent->num_leafs++;			
+		return;
+	}
+	
+// NODE_MIXED
+
+	splitplane = node->plane;
+	sides = BOX_ON_PLANE_SIDE(ent->v.absmin, ent->v.absmax, splitplane);
+	
+// recurse down the contacted sides
+	if (sides & 1)
+		SV_FindTouchedLeafs (ent, node->children[0]);
+		
+	if (sides & 2)
+		SV_FindTouchedLeafs (ent, node->children[1]);
+}
+
+/*
+===============
+SV_LinkEdict
+
+===============
+*/
+void SV_LinkEdict (edict_t *ent, qboolean touch_triggers)
+{
+	areanode_t	*node;
+	
+	if (ent->area.prev)
+		SV_UnlinkEdict (ent);	// unlink from old position
+		
+	if (ent == sv.edicts)
+		return;		// don't add the world
+
+	if (ent->free)
+		return;
+
+// set the abs box
+	VectorAdd (ent->v.origin, ent->v.mins, ent->v.absmin);	
+	VectorAdd (ent->v.origin, ent->v.maxs, ent->v.absmax);
+
+//
+// to make items easier to pick up and allow them to be grabbed off
+// of shelves, the abs sizes are expanded
+//
+	if ((int)ent->v.flags & FL_ITEM)
+	{
+		ent->v.absmin[0] -= 15;
+		ent->v.absmin[1] -= 15;
+		ent->v.absmax[0] += 15;
+		ent->v.absmax[1] += 15;
+	}
+	else
+	{	// because movement is clipped an epsilon away from an actual edge,
+		// we must fully check even when bounding boxes don't quite touch
+		ent->v.absmin[0] -= 1;
+		ent->v.absmin[1] -= 1;
+		ent->v.absmin[2] -= 1;
+		ent->v.absmax[0] += 1;
+		ent->v.absmax[1] += 1;
+		ent->v.absmax[2] += 1;
+	}
+	
+// link to PVS leafs
+	ent->num_leafs = 0;
+	if (ent->v.modelindex)
+		SV_FindTouchedLeafs (ent, sv.worldmodel->nodes);
+
+	if (ent->v.solid == SOLID_NOT)
+		return;
+
+// find the first node that the ent's box crosses
+	node = sv_areanodes;
+	while (1)
+	{
+		if (node->axis == -1)
+			break;
+		if (ent->v.absmin[node->axis] > node->dist)
+			node = node->children[0];
+		else if (ent->v.absmax[node->axis] < node->dist)
+			node = node->children[1];
+		else
+			break;		// crosses the node
+	}
+	
+// link it in	
+
+	if (ent->v.solid == SOLID_TRIGGER)
+		InsertLinkBefore (&ent->area, &node->trigger_edicts);
+	else
+		InsertLinkBefore (&ent->area, &node->solid_edicts);
+	
+// if touch_triggers, touch all entities at this node and decend for more
+	if (touch_triggers)
+		SV_TouchLinks ( ent, sv_areanodes );
+}
+
+
+
+/*
+===============================================================================
+
+POINT TESTING IN HULLS
+
+===============================================================================
+*/
+
+#if	!id386
+
+/*
+==================
+SV_HullPointContents
+
+==================
+*/
+int SV_HullPointContents (hull_t *hull, int num, vec3_t p)
+{
+	float		d;
+	dclipnode_t	*node;
+	mplane_t	*plane;
+
+	while (num >= 0)
+	{
+		if (num < hull->firstclipnode || num > hull->lastclipnode)
+			SV_Error ("SV_HullPointContents: bad node number");
+	
+		node = hull->clipnodes + num;
+		plane = hull->planes + node->planenum;
+		
+		if (plane->type < 3)
+			d = p[plane->type] - plane->dist;
+		else
+			d = DotProduct (plane->normal, p) - plane->dist;
+		if (d < 0)
+			num = node->children[1];
+		else
+			num = node->children[0];
+	}
+	
+	return num;
+}
+
+#endif	// !id386
+
+
+/*
+==================
+SV_PointContents
+
+==================
+*/
+int SV_PointContents (vec3_t p)
+{
+	return SV_HullPointContents (&sv.worldmodel->hulls[0], 0, p);
+}
+
+//===========================================================================
+
+/*
+============
+SV_TestEntityPosition
+
+A small wrapper around SV_BoxInSolidEntity that never clips against the
+supplied entity.
+============
+*/
+edict_t	*SV_TestEntityPosition (edict_t *ent)
+{
+	trace_t	trace;
+
+	trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, ent->v.origin, 0, ent);
+	
+	if (trace.startsolid)
+		return sv.edicts;
+		
+	return NULL;
+}
+
+/*
+===============================================================================
+
+LINE TESTING IN HULLS
+
+===============================================================================
+*/
+
+// 1/32 epsilon to keep floating point happy
+#define	DIST_EPSILON	(0.03125)
+
+/*
+==================
+SV_RecursiveHullCheck
+
+==================
+*/
+qboolean SV_RecursiveHullCheck (hull_t *hull, int num, float p1f, float p2f, vec3_t p1, vec3_t p2, trace_t *trace)
+{
+	dclipnode_t	*node;
+	mplane_t	*plane;
+	float		t1, t2;
+	float		frac;
+	int			i;
+	vec3_t		mid;
+	int			side;
+	float		midf;
+
+// check for empty
+	if (num < 0)
+	{
+		if (num != CONTENTS_SOLID)
+		{
+			trace->allsolid = false;
+			if (num == CONTENTS_EMPTY)
+				trace->inopen = true;
+			else
+				trace->inwater = true;
+		}
+		else
+			trace->startsolid = true;
+		return true;		// empty
+	}
+
+	if (num < hull->firstclipnode || num > hull->lastclipnode)
+		SV_Error ("SV_RecursiveHullCheck: bad node number");
+
+//
+// find the point distances
+//
+	node = hull->clipnodes + num;
+	plane = hull->planes + node->planenum;
+
+	if (plane->type < 3)
+	{
+		t1 = p1[plane->type] - plane->dist;
+		t2 = p2[plane->type] - plane->dist;
+	}
+	else
+	{
+		t1 = DotProduct (plane->normal, p1) - plane->dist;
+		t2 = DotProduct (plane->normal, p2) - plane->dist;
+	}
+	
+#if 1
+	if (t1 >= 0 && t2 >= 0)
+		return SV_RecursiveHullCheck (hull, node->children[0], p1f, p2f, p1, p2, trace);
+	if (t1 < 0 && t2 < 0)
+		return SV_RecursiveHullCheck (hull, node->children[1], p1f, p2f, p1, p2, trace);
+#else
+	if ( (t1 >= DIST_EPSILON && t2 >= DIST_EPSILON) || (t2 > t1 && t1 >= 0) )
+		return SV_RecursiveHullCheck (hull, node->children[0], p1f, p2f, p1, p2, trace);
+	if ( (t1 <= -DIST_EPSILON && t2 <= -DIST_EPSILON) || (t2 < t1 && t1 <= 0) )
+		return SV_RecursiveHullCheck (hull, node->children[1], p1f, p2f, p1, p2, trace);
+#endif
+
+// put the crosspoint DIST_EPSILON pixels on the near side
+	if (t1 < 0)
+		frac = (t1 + DIST_EPSILON)/(t1-t2);
+	else
+		frac = (t1 - DIST_EPSILON)/(t1-t2);
+	if (frac < 0)
+		frac = 0;
+	if (frac > 1)
+		frac = 1;
+		
+	midf = p1f + (p2f - p1f)*frac;
+	for (i=0 ; i<3 ; i++)
+		mid[i] = p1[i] + frac*(p2[i] - p1[i]);
+
+	side = (t1 < 0);
+
+// move up to the node
+	if (!SV_RecursiveHullCheck (hull, node->children[side], p1f, midf, p1, mid, trace) )
+		return false;
+
+#ifdef PARANOID
+	if (SV_HullPointContents (sv_hullmodel, mid, node->children[side])
+	== CONTENTS_SOLID)
+	{
+		Con_Printf ("mid PointInHullSolid\n");
+		return false;
+	}
+#endif
+	
+	if (SV_HullPointContents (hull, node->children[side^1], mid)
+	!= CONTENTS_SOLID)
+// go past the node
+		return SV_RecursiveHullCheck (hull, node->children[side^1], midf, p2f, mid, p2, trace);
+	
+	if (trace->allsolid)
+		return false;		// never got out of the solid area
+		
+//==================
+// the other side of the node is solid, this is the impact point
+//==================
+	if (!side)
+	{
+		VectorCopy (plane->normal, trace->plane.normal);
+		trace->plane.dist = plane->dist;
+	}
+	else
+	{
+		VectorSubtract (vec3_origin, plane->normal, trace->plane.normal);
+		trace->plane.dist = -plane->dist;
+	}
+
+	while (SV_HullPointContents (hull, hull->firstclipnode, mid)
+	== CONTENTS_SOLID)
+	{ // shouldn't really happen, but does occasionally
+		frac -= 0.1;
+		if (frac < 0)
+		{
+			trace->fraction = midf;
+			VectorCopy (mid, trace->endpos);
+			Con_Printf ("backup past 0\n");
+			return false;
+		}
+		midf = p1f + (p2f - p1f)*frac;
+		for (i=0 ; i<3 ; i++)
+			mid[i] = p1[i] + frac*(p2[i] - p1[i]);
+	}
+
+	trace->fraction = midf;
+	VectorCopy (mid, trace->endpos);
+
+	return false;
+}
+
+
+/*
+==================
+SV_ClipMoveToEntity
+
+Handles selection or creation of a clipping hull, and offseting (and
+eventually rotation) of the end points
+==================
+*/
+trace_t SV_ClipMoveToEntity (edict_t *ent, vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end)
+{
+	trace_t		trace;
+	vec3_t		offset;
+	vec3_t		start_l, end_l;
+	hull_t		*hull;
+
+// fill in a default trace
+	memset (&trace, 0, sizeof(trace_t));
+	trace.fraction = 1;
+	trace.allsolid = true;
+	VectorCopy (end, trace.endpos);
+
+// get the clipping hull
+	hull = SV_HullForEntity (ent, mins, maxs, offset);
+
+	VectorSubtract (start, offset, start_l);
+	VectorSubtract (end, offset, end_l);
+
+// trace a line through the apropriate clipping hull
+	SV_RecursiveHullCheck (hull, hull->firstclipnode, 0, 1, start_l, end_l, &trace);
+
+// fix trace up by the offset
+	if (trace.fraction != 1)
+		VectorAdd (trace.endpos, offset, trace.endpos);
+
+// did we clip the move?
+	if (trace.fraction < 1 || trace.startsolid  )
+		trace.ent = ent;
+
+	return trace;
+}
+
+//===========================================================================
+
+/*
+====================
+SV_ClipToLinks
+
+Mins and maxs enclose the entire area swept by the move
+====================
+*/
+void SV_ClipToLinks ( areanode_t *node, moveclip_t *clip )
+{
+	link_t		*l, *next;
+	edict_t		*touch;
+	trace_t		trace;
+
+// touch linked edicts
+	for (l = node->solid_edicts.next ; l != &node->solid_edicts ; l = next)
+	{
+		next = l->next;
+		touch = EDICT_FROM_AREA(l);
+		if (touch->v.solid == SOLID_NOT)
+			continue;
+		if (touch == clip->passedict)
+			continue;
+		if (touch->v.solid == SOLID_TRIGGER)
+			SV_Error ("Trigger in clipping list");
+
+		if (clip->type == MOVE_NOMONSTERS && touch->v.solid != SOLID_BSP)
+			continue;
+
+		if (clip->boxmins[0] > touch->v.absmax[0]
+		|| clip->boxmins[1] > touch->v.absmax[1]
+		|| clip->boxmins[2] > touch->v.absmax[2]
+		|| clip->boxmaxs[0] < touch->v.absmin[0]
+		|| clip->boxmaxs[1] < touch->v.absmin[1]
+		|| clip->boxmaxs[2] < touch->v.absmin[2] )
+			continue;
+
+		if (clip->passedict && clip->passedict->v.size[0] && !touch->v.size[0])
+			continue;	// points never interact
+
+	// might intersect, so do an exact clip
+		if (clip->trace.allsolid)
+			return;
+		if (clip->passedict)
+		{
+		 	if (PROG_TO_EDICT(touch->v.owner) == clip->passedict)
+				continue;	// don't clip against own missiles
+			if (PROG_TO_EDICT(clip->passedict->v.owner) == touch)
+				continue;	// don't clip against owner
+		}
+
+		if ((int)touch->v.flags & FL_MONSTER)
+			trace = SV_ClipMoveToEntity (touch, clip->start, clip->mins2, clip->maxs2, clip->end);
+		else
+			trace = SV_ClipMoveToEntity (touch, clip->start, clip->mins, clip->maxs, clip->end);
+		if (trace.allsolid || trace.startsolid ||
+		trace.fraction < clip->trace.fraction)
+		{
+			trace.ent = touch;
+		 	if (clip->trace.startsolid)
+			{
+				clip->trace = trace;
+				clip->trace.startsolid = true;
+			}
+			else
+				clip->trace = trace;
+		}
+		else if (trace.startsolid)
+			clip->trace.startsolid = true;
+	}
+	
+// recurse down both sides
+	if (node->axis == -1)
+		return;
+
+	if ( clip->boxmaxs[node->axis] > node->dist )
+		SV_ClipToLinks ( node->children[0], clip );
+	if ( clip->boxmins[node->axis] < node->dist )
+		SV_ClipToLinks ( node->children[1], clip );
+}
+
+
+/*
+==================
+SV_MoveBounds
+==================
+*/
+void SV_MoveBounds (vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, vec3_t boxmins, vec3_t boxmaxs)
+{
+#if 0
+// debug to test against everything
+boxmins[0] = boxmins[1] = boxmins[2] = -9999;
+boxmaxs[0] = boxmaxs[1] = boxmaxs[2] = 9999;
+#else
+	int		i;
+	
+	for (i=0 ; i<3 ; i++)
+	{
+		if (end[i] > start[i])
+		{
+			boxmins[i] = start[i] + mins[i] - 1;
+			boxmaxs[i] = end[i] + maxs[i] + 1;
+		}
+		else
+		{
+			boxmins[i] = end[i] + mins[i] - 1;
+			boxmaxs[i] = start[i] + maxs[i] + 1;
+		}
+	}
+#endif
+}
+
+/*
+==================
+SV_Move
+==================
+*/
+trace_t SV_Move (vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, int type, edict_t *passedict)
+{
+	moveclip_t	clip;
+	int			i;
+
+	memset ( &clip, 0, sizeof ( moveclip_t ) );
+
+// clip to world
+	clip.trace = SV_ClipMoveToEntity ( sv.edicts, start, mins, maxs, end );
+
+	clip.start = start;
+	clip.end = end;
+	clip.mins = mins;
+	clip.maxs = maxs;
+	clip.type = type;
+	clip.passedict = passedict;
+
+	if (type == MOVE_MISSILE)
+	{
+		for (i=0 ; i<3 ; i++)
+		{
+			clip.mins2[i] = -15;
+			clip.maxs2[i] = 15;
+		}
+	}
+	else
+	{
+		VectorCopy (mins, clip.mins2);
+		VectorCopy (maxs, clip.maxs2);
+	}
+	
+// create the bounding box of the entire move
+	SV_MoveBounds ( start, clip.mins2, clip.maxs2, end, clip.boxmins, clip.boxmaxs );
+
+// clip to entities
+	SV_ClipToLinks ( sv_areanodes, &clip );
+
+	return clip.trace;
+}
+
+//=============================================================================
+
+/*
+============
+SV_TestPlayerPosition
+
+============
+*/
+edict_t	*SV_TestPlayerPosition (edict_t *ent, vec3_t origin)
+{
+	hull_t	*hull;
+	edict_t	*check;
+	vec3_t	boxmins, boxmaxs;
+	vec3_t	offset;
+	int		e;
+	
+// check world first
+	hull = &sv.worldmodel->hulls[1];
+	if ( SV_HullPointContents (hull, hull->firstclipnode, origin) != CONTENTS_EMPTY )
+		return sv.edicts;
+
+// check all entities
+	VectorAdd (origin, ent->v.mins, boxmins);
+	VectorAdd (origin, ent->v.maxs, boxmaxs);
+	
+	check = NEXT_EDICT(sv.edicts);
+	for (e=1 ; e<sv.num_edicts ; e++, check = NEXT_EDICT(check))
+	{
+		if (check->free)
+			continue;
+		if (check->v.solid != SOLID_BSP &&
+			check->v.solid != SOLID_BBOX &&
+			check->v.solid != SOLID_SLIDEBOX)
+			continue;
+
+		if (boxmins[0] > check->v.absmax[0]
+		|| boxmins[1] > check->v.absmax[1]
+		|| boxmins[2] > check->v.absmax[2]
+		|| boxmaxs[0] < check->v.absmin[0]
+		|| boxmaxs[1] < check->v.absmin[1]
+		|| boxmaxs[2] < check->v.absmin[2] )
+			continue;
+
+		if (check == ent)
+			continue;
+
+	// get the clipping hull
+		hull = SV_HullForEntity (check, ent->v.mins, ent->v.maxs, offset);
+	
+		VectorSubtract (origin, offset, offset);
+	
+	// test the point
+		if ( SV_HullPointContents (hull, hull->firstclipnode, offset) != CONTENTS_EMPTY )
+			return check;
+	}
+
+	return NULL;
+}
+
+
--- /dev/null
+++ b/QW/server/world.h
@@ -1,0 +1,93 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// world.h
+
+typedef struct
+{
+	vec3_t	normal;
+	float	dist;
+} plane_t;
+
+typedef struct
+{
+	qboolean	allsolid;	// if true, plane is not valid
+	qboolean	startsolid;	// if true, the initial point was in a solid area
+	qboolean	inopen, inwater;
+	float	fraction;		// time completed, 1.0 = didn't hit anything
+	vec3_t	endpos;			// final position
+	plane_t	plane;			// surface normal at impact
+	edict_t	*ent;			// entity the surface is on
+} trace_t;
+
+
+#define	MOVE_NORMAL		0
+#define	MOVE_NOMONSTERS	1
+#define	MOVE_MISSILE	2
+
+typedef struct areanode_s
+{
+	int		axis;		// -1 = leaf node
+	float	dist;
+	struct areanode_s	*children[2];
+	link_t	trigger_edicts;
+	link_t	solid_edicts;
+} areanode_t;
+
+#define	AREA_DEPTH	4
+#define	AREA_NODES	32
+
+extern	areanode_t	sv_areanodes[AREA_NODES];
+
+
+void SV_ClearWorld (void);
+// called after the world model has been loaded, before linking any entities
+
+void SV_UnlinkEdict (edict_t *ent);
+// call before removing an entity, and before trying to move one,
+// so it doesn't clip against itself
+// flags ent->v.modified
+
+void SV_LinkEdict (edict_t *ent, qboolean touch_triggers);
+// Needs to be called any time an entity changes origin, mins, maxs, or solid
+// flags ent->v.modified
+// sets ent->v.absmin and ent->v.absmax
+// if touchtriggers, calls prog functions for the intersected triggers
+
+int SV_PointContents (vec3_t p);
+// returns the CONTENTS_* value from the world at the given point.
+// does not check any entities at all
+
+edict_t	*SV_TestEntityPosition (edict_t *ent);
+
+trace_t SV_Move (vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, int type, edict_t *passedict);
+// mins and maxs are reletive
+
+// if the entire move stays in a solid volume, trace.allsolid will be set
+
+// if the starting point is in a solid, it will be allowed to move out
+// to an open area
+
+// nomonsters is used for line of sight or edge testing, where mosnters
+// shouldn't be considered solid objects
+
+// passedict is explicitly excluded from clipping checks (normally NULL)
+
+
+edict_t	*SV_TestPlayerPosition (edict_t *ent, vec3_t origin);
--- /dev/null
+++ b/QW/server/worlda.s
@@ -1,0 +1,124 @@
+//
+// worlda.s
+// x86 assembly-language server testing stuff
+//
+
+#include "asm_i386.h"
+#include "quakeasm.h"
+//include "d_ifacea.h"
+
+#if id386
+
+	.data
+
+Ltemp:	.long	0
+
+	.text
+
+//----------------------------------------------------------------------
+// hull-point test
+//----------------------------------------------------------------------
+
+#define hull	4+8				// because only partially pushed
+#define	num		8+4				// because only partially pushed
+#define p		12+12			// because only partially pushed
+
+	.align 4
+.globl C(SV_HullPointContents)
+C(SV_HullPointContents):
+	pushl	%edi				// preserve register variables
+	movl	num(%esp),%eax
+	testl	%eax,%eax
+	js		Lhquickout
+
+//	float		d;
+//	dclipnode_t	*node;
+//	mplane_t	*plane;
+
+	pushl	%ebx
+	movl	hull(%esp),%ebx
+
+	pushl	%ebp
+	movl	p(%esp),%edx
+
+	movl	hu_clipnodes(%ebx),%edi
+	movl	hu_planes(%ebx),%ebp
+
+	subl	%ebx,%ebx
+	pushl	%esi
+
+// %ebx: 0
+// %eax: num
+// %edx: p
+// %edi: hull->clipnodes
+// %ebp: hull->planes
+
+//	while (num >= 0)
+//	{
+
+Lhloop:
+
+//		node = hull->clipnodes + num;
+//		plane = hull->planes + node->planenum;
+// !!! if the size of dclipnode_t changes, the scaling of %eax needs to be
+//     changed !!!
+	movl	nd_planenum(%edi,%eax,8),%ecx
+	movl	nd_children(%edi,%eax,8),%eax
+	movl	%eax,%esi
+	rorl	$16,%eax
+	leal	(%ecx,%ecx,4),%ecx
+
+//		if (plane->type < 3)
+//			d = p[plane->type] - plane->dist;
+	movl	pl_type(%ebp,%ecx,4),%bl
+	cmpb	$3,%bl
+	jb		Lnodot
+
+//		else
+//			d = DotProduct (plane->normal, p) - plane->dist;
+	flds	pl_normal(%ebp,%ecx,4)
+	fmuls	0(%edx)
+	flds	pl_normal+4(%ebp,%ecx,4)
+	fmuls	4(%edx)
+	flds	pl_normal+8(%ebp,%ecx,4)
+	fmuls	8(%edx)
+	fxch	%st(1)
+	faddp	%st(0),%st(2)
+	faddp	%st(0),%st(1)
+	fsubs	pl_dist(%ebp,%ecx,4)
+	jmp		Lsub
+
+Lnodot:
+	flds	pl_dist(%ebp,%ecx,4)
+	fsubrs	(%edx,%ebx,4)
+
+Lsub:
+	sarl	$16,%eax
+	sarl	$16,%esi
+
+//		if (d < 0)
+//			num = node->children[1];
+//		else
+//			num = node->children[0];
+	fstps	Ltemp
+	movl	Ltemp,%ecx
+	sarl	$31,%ecx
+	andl	%ecx,%esi
+	xorl	$0xFFFFFFFF,%ecx
+	andl	%ecx,%eax
+	orl		%esi,%eax
+	jns		Lhloop
+
+//	return num;
+Lhdone:
+	popl	%esi
+	popl	%ebp
+	popl	%ebx				// restore register variables
+
+Lhquickout:
+	popl	%edi
+
+	ret
+
+#endif	// id386
+
--- /dev/null
+++ b/WinQuake/3dfx.txt
@@ -1,0 +1,69 @@
+GLQuake Drivers
+
+Graphics Subsystem: Voodoo Graphics or Voodoo Rush
+
+Copyright ( 1997 3Dfx Interactive, Inc. )
+All Rights Reserved
+
+3Dfx Interactive, Inc.
+www: www.3dfx.com
+news: news.3dfx.com  
+
+-----------------------------------------------------------------------
+NOTE: GLQuake requires DirectX support DirectSound.  DirectX can be 
+installed from the media provided with your Voodoo Based 3D Accelerator.
+
+Glide 2.31 or HIGHER runtime drivers *MUST* be installed to use this
+GLQuake driver.  Please download these drivers from your board
+manufacturer OR unsupported drivers from http://www.3dfx.com
+-----------------------------------------------------------------------
+
+Release Notes for GLQuake's mini-GL driver
+
+What's in the distribution?
+---------------------------
+
+This distribution contains GLQuake Drivers for Voodoo Based 3D
+Accelerators.  These drivers were tested on the following boards: 
+
+Voodoo Graphics:
+- Quantum 3D Obsidian 
+- Diamond Monster 3D
+- Orchid Righteous 3D
+- Deltron Realvision Flash 3D
+- Guillemot MaxiGamer 
+- Skywell Magic 3D
+
+Voodoo Rush:
+- Hercules Stringray 128-3D
+- Intergraph Intense 3D Voodoo
+- Jazz Multimedia Adrenaline Rush
+
+NOTE:  The enclosed drivers are not meant to replace any Direct3D or 
+Glide drivers provided by your Voodoo Graphics card manufacturer. 
+Please obtain supported drivers from your board manufacturer.
+
+OEMSR2 and NT users: Do NOT replace OPENGL32.DLL located in your
+Windows\SYSTEM directory.
+
+Requirements
+------------
+
+- Voodoo Graphics or Voodoo Rush Based 3D Accelerator
+- Windows 95 (Windows NT is supported for Voodoo Rush)
+- A PC with a Pentium 90 or higher CPU
+- 16MB of RAM
+- 2D Video card set at 16 bit color
+
+Support and Frequently Asked Questions
+--------------------------------------
+
+GLQuake is currently unsupported.  You may however find answers to 
+questions on various Quake dedicated websites.  3Dfx provides a GLQuake
+newsgroup on news.3dfx.com (Newsgroup name is 3dfx.games.glquake ) to
+discuss GLQuake with other users.  3Dfx also provides a regularly
+updated GLQuake FAQ at: http://www.3dfx.com/game_dev/quake_faq.html
+
+
+Voodoo Graphics and Voodoo Rush are trademarks of 3Dfx Interactive, Inc.  
+All other trademarks are the property of their respective owners.
\ No newline at end of file
--- /dev/null
+++ b/WinQuake/Makefile.Solaris
@@ -1,0 +1,483 @@
+#
+# Quake Makefile for Solaris
+#
+# Nov '97 by Zoid <zoid@idsoftware.com>
+#
+# ELF only
+#
+
+VERSION=1.09
+
+ifneq (,$(findstring i86pc,$(shell uname -m)))
+ARCH=i386
+else
+ARCH=sparc
+endif
+
+MOUNT_DIR=/grog/Projects/WinQuake
+
+BUILD_DEBUG_DIR=debug$(ARCH)
+BUILD_RELEASE_DIR=release$(ARCH)
+
+CC=gcc
+BASE_CFLAGS=-I/usr/openwin/include
+
+RELEASE_CFLAGS=$(BASE_CFLAGS) -O6 -ffast-math -funroll-loops -fomit-frame-pointer -fexpensive-optimizations
+DEBUG_CFLAGS=$(BASE_CFLAGS) -g
+LDFLAGS=-R /usr/openwin/lib -L /usr/openwin/lib -lm -lX11 -lXext -lsocket -lnsl -lthread -ldl 
+XIL_LDFLAGS=-L /opt/SUNWits/Graphics-sw/xil/lib -R /opt/SUNWits/Graphics-sw/xil/lib:/usr/openwin/lib -L /usr/openwin/lib -lm -lxil -lX11 -lXext -lsocket -lnsl -lthread -ldl 
+
+DO_CC=$(CC) $(CFLAGS) -o $@ -c $<
+DO_AS=$(CC) $(CFLAGS) -DELF -x assembler-with-cpp -o $@ -c $<
+
+#############################################################################
+# SETUP AND BUILD
+#############################################################################
+
+TARGETS=$(BUILDDIR)/quake.sw $(BUILDDIR)/quake.xil
+
+build_debug:
+	@-mkdir $(BUILD_DEBUG_DIR)
+	$(MAKE) targets BUILDDIR=$(BUILD_DEBUG_DIR) CFLAGS="$(DEBUG_CFLAGS)"
+
+build_release:
+	@-mkdir $(BUILD_RELEASE_DIR)
+	$(MAKE) targets BUILDDIR=$(BUILD_RELEASE_DIR) CFLAGS="$(RELEASE_CFLAGS)"
+
+all: build_debug build_release
+
+targets: $(TARGETS)
+
+#############################################################################
+# CLIENT/SERVER
+#############################################################################
+
+QUAKE_OBJS= \
+	$(BUILDDIR)/chase.o \
+	$(BUILDDIR)/cl_demo.o \
+	$(BUILDDIR)/cl_input.o \
+	$(BUILDDIR)/cl_main.o \
+	$(BUILDDIR)/cl_parse.o \
+	$(BUILDDIR)/cl_tent.o \
+	$(BUILDDIR)/cmd.o \
+	$(BUILDDIR)/common.o \
+	$(BUILDDIR)/console.o \
+	$(BUILDDIR)/crc.o \
+	$(BUILDDIR)/cvar.o \
+	$(BUILDDIR)/draw.o \
+	$(BUILDDIR)/d_edge.o \
+	$(BUILDDIR)/d_fill.o \
+	$(BUILDDIR)/d_init.o \
+	$(BUILDDIR)/d_modech.o \
+	$(BUILDDIR)/d_part.o \
+	$(BUILDDIR)/d_polyse.o \
+	$(BUILDDIR)/d_scan.o \
+	$(BUILDDIR)/d_sky.o \
+	$(BUILDDIR)/d_sprite.o \
+	$(BUILDDIR)/d_surf.o \
+	$(BUILDDIR)/d_vars.o \
+	$(BUILDDIR)/d_zpoint.o \
+	$(BUILDDIR)/host.o \
+	$(BUILDDIR)/host_cmd.o \
+	$(BUILDDIR)/keys.o \
+	$(BUILDDIR)/menu.o \
+	$(BUILDDIR)/mathlib.o \
+	$(BUILDDIR)/model.o \
+	$(BUILDDIR)/nonintel.o \
+	$(BUILDDIR)/pr_cmds.o \
+	$(BUILDDIR)/pr_edict.o \
+	$(BUILDDIR)/pr_exec.o \
+	$(BUILDDIR)/r_aclip.o \
+	$(BUILDDIR)/r_alias.o \
+	$(BUILDDIR)/r_bsp.o \
+	$(BUILDDIR)/r_light.o \
+	$(BUILDDIR)/r_draw.o \
+	$(BUILDDIR)/r_efrag.o \
+	$(BUILDDIR)/r_edge.o \
+	$(BUILDDIR)/r_misc.o \
+	$(BUILDDIR)/r_main.o \
+	$(BUILDDIR)/r_sky.o \
+	$(BUILDDIR)/r_sprite.o \
+	$(BUILDDIR)/r_surf.o \
+	$(BUILDDIR)/r_part.o \
+	$(BUILDDIR)/r_vars.o \
+	$(BUILDDIR)/screen.o \
+	$(BUILDDIR)/sbar.o \
+	$(BUILDDIR)/sv_main.o \
+	$(BUILDDIR)/sv_phys.o \
+	$(BUILDDIR)/sv_move.o \
+	$(BUILDDIR)/sv_user.o \
+	$(BUILDDIR)/zone.o	\
+	$(BUILDDIR)/view.o	\
+	$(BUILDDIR)/wad.o \
+	$(BUILDDIR)/world.o \
+	$(BUILDDIR)/cd_null.o \
+	$(BUILDDIR)/snd_dma.o \
+	$(BUILDDIR)/snd_mix.o \
+	$(BUILDDIR)/snd_mem.o \
+	$(BUILDDIR)/net_dgrm.o \
+	$(BUILDDIR)/net_loop.o \
+	$(BUILDDIR)/net_main.o \
+	$(BUILDDIR)/net_vcr.o \
+	$(BUILDDIR)/net_udp.o \
+	$(BUILDDIR)/net_bsd.o \
+	$(BUILDDIR)/sys_sun.o \
+	$(BUILDDIR)/snd_sun.o 
+
+QUAKE_AS_OBJS= \
+	$(BUILDDIR)/d_copy.o \
+	$(BUILDDIR)/d_draw.o \
+	$(BUILDDIR)/d_draw16.o \
+	$(BUILDDIR)/d_parta.o \
+	$(BUILDDIR)/d_polysa.o \
+	$(BUILDDIR)/d_scana.o \
+	$(BUILDDIR)/d_spr8.o \
+	$(BUILDDIR)/d_varsa.o \
+	$(BUILDDIR)/math.o \
+	$(BUILDDIR)/r_aliasa.o \
+	$(BUILDDIR)/r_drawa.o \
+	$(BUILDDIR)/r_edgea.o \
+	$(BUILDDIR)/r_varsa.o \
+	$(BUILDDIR)/surf16.o \
+	$(BUILDDIR)/surf8.o \
+	$(BUILDDIR)/worlda.o \
+	$(BUILDDIR)/r_aclipa.o \
+	$(BUILDDIR)/snd_mixa.o \
+	$(BUILDDIR)/sys_dosa.o
+
+QUAKE_X_OBJS = $(BUILDDIR)/vid_sunx.o
+
+QUAKE_XIL_OBJS = $(BUILDDIR)/vid_sunxil.o
+
+ifeq ($(ARCH),i386)
+$(BUILDDIR)/quake.sw : $(QUAKE_OBJS) $(QUAKE_AS_OBJS) $(QUAKE_X_OBJS)
+	$(CC) -o $(@) $(QUAKE_OBJS) $(QUAKE_AS_OBJS) $(QUAKE_X_OBJS) $(LDFLAGS)
+
+$(BUILDDIR)/quake.xil: $(QUAKE_OBJS) $(QUAKE_AS_OBJS) $(QUAKE_XIL_OBJS)
+	$(CC) -o $(@) $(QUAKE_OBJS) $(QUAKE_AS_OBJS) $(QUAKE_XIL_OBJS) $(XIL_LDFLAGS)
+else
+$(BUILDDIR)/quake.sw : $(QUAKE_OBJS) $(QUAKE_X_OBJS)
+	$(CC) -o $(@) $(QUAKE_OBJS) $(QUAKE_X_OBJS) $(LDFLAGS)
+
+$(BUILDDIR)/quake.xil: $(QUAKE_OBJS) $(QUAKE_XIL_OBJS)
+	$(CC) -o $(@) $(QUAKE_OBJS) $(QUAKE_XIL_OBJS) $(XIL_LDFLAGS)
+endif
+
+##
+
+$(BUILDDIR)/chase.o :				$(MOUNT_DIR)/chase.c
+	$(DO_CC)
+
+$(BUILDDIR)/cl_demo.o :             $(MOUNT_DIR)/cl_demo.c
+	$(DO_CC)
+
+$(BUILDDIR)/cl_input.o :            $(MOUNT_DIR)/cl_input.c
+	$(DO_CC)
+
+$(BUILDDIR)/cl_main.o :             $(MOUNT_DIR)/cl_main.c
+	$(DO_CC)
+
+$(BUILDDIR)/cl_parse.o :            $(MOUNT_DIR)/cl_parse.c
+	$(DO_CC)
+
+$(BUILDDIR)/cl_tent.o :             $(MOUNT_DIR)/cl_tent.c
+	$(DO_CC)
+
+$(BUILDDIR)/cmd.o :                 $(MOUNT_DIR)/cmd.c
+	$(DO_CC)
+
+$(BUILDDIR)/common.o :              $(MOUNT_DIR)/common.c
+	$(DO_CC)
+
+$(BUILDDIR)/console.o :             $(MOUNT_DIR)/console.c
+	$(DO_CC)
+
+$(BUILDDIR)/crc.o :                 $(MOUNT_DIR)/crc.c
+	$(DO_CC)
+
+$(BUILDDIR)/cvar.o :                $(MOUNT_DIR)/cvar.c
+	$(DO_CC)
+
+$(BUILDDIR)/draw.o :                $(MOUNT_DIR)/draw.c
+	$(DO_CC)
+
+$(BUILDDIR)/d_edge.o :              $(MOUNT_DIR)/d_edge.c
+	$(DO_CC)
+
+$(BUILDDIR)/d_fill.o :              $(MOUNT_DIR)/d_fill.c
+	$(DO_CC)
+
+$(BUILDDIR)/d_init.o :              $(MOUNT_DIR)/d_init.c
+	$(DO_CC)
+
+$(BUILDDIR)/d_modech.o :            $(MOUNT_DIR)/d_modech.c
+	$(DO_CC)
+
+$(BUILDDIR)/d_part.o :              $(MOUNT_DIR)/d_part.c
+	$(DO_CC)
+
+$(BUILDDIR)/d_polyse.o :            $(MOUNT_DIR)/d_polyse.c
+	$(DO_CC)
+
+$(BUILDDIR)/d_scan.o :              $(MOUNT_DIR)/d_scan.c
+	$(DO_CC)
+
+$(BUILDDIR)/d_sky.o :               $(MOUNT_DIR)/d_sky.c
+	$(DO_CC)
+
+$(BUILDDIR)/d_sprite.o :            $(MOUNT_DIR)/d_sprite.c
+	$(DO_CC)
+
+$(BUILDDIR)/d_surf.o :              $(MOUNT_DIR)/d_surf.c
+	$(DO_CC)
+
+$(BUILDDIR)/d_vars.o :              $(MOUNT_DIR)/d_vars.c
+	$(DO_CC)
+
+$(BUILDDIR)/d_zpoint.o :            $(MOUNT_DIR)/d_zpoint.c
+	$(DO_CC)
+
+$(BUILDDIR)/host.o :                $(MOUNT_DIR)/host.c
+	$(DO_CC)
+
+$(BUILDDIR)/host_cmd.o :            $(MOUNT_DIR)/host_cmd.c
+	$(DO_CC)
+
+$(BUILDDIR)/keys.o :                $(MOUNT_DIR)/keys.c
+	$(DO_CC)
+
+$(BUILDDIR)/menu.o :                $(MOUNT_DIR)/menu.c
+	$(DO_CC)
+
+$(BUILDDIR)/mathlib.o :             $(MOUNT_DIR)/mathlib.c
+	$(DO_CC)
+
+$(BUILDDIR)/model.o :               $(MOUNT_DIR)/model.c
+	$(DO_CC)
+
+$(BUILDDIR)/nonintel.o :            $(MOUNT_DIR)/nonintel.c
+	$(DO_CC)
+
+$(BUILDDIR)/pr_cmds.o :             $(MOUNT_DIR)/pr_cmds.c
+	$(DO_CC)
+
+$(BUILDDIR)/pr_edict.o :            $(MOUNT_DIR)/pr_edict.c
+	$(DO_CC)
+
+$(BUILDDIR)/pr_exec.o :             $(MOUNT_DIR)/pr_exec.c
+	$(DO_CC)
+
+$(BUILDDIR)/r_aclip.o :             $(MOUNT_DIR)/r_aclip.c
+	$(DO_CC)
+
+$(BUILDDIR)/r_alias.o :             $(MOUNT_DIR)/r_alias.c
+	$(DO_CC)
+
+$(BUILDDIR)/r_bsp.o :               $(MOUNT_DIR)/r_bsp.c
+	$(DO_CC)
+
+$(BUILDDIR)/r_light.o :             $(MOUNT_DIR)/r_light.c
+	$(DO_CC)
+
+$(BUILDDIR)/r_draw.o :              $(MOUNT_DIR)/r_draw.c
+	$(DO_CC)
+
+$(BUILDDIR)/r_efrag.o :             $(MOUNT_DIR)/r_efrag.c
+	$(DO_CC)
+
+$(BUILDDIR)/r_edge.o :              $(MOUNT_DIR)/r_edge.c
+	$(DO_CC)
+
+$(BUILDDIR)/r_misc.o :              $(MOUNT_DIR)/r_misc.c
+	$(DO_CC)
+
+$(BUILDDIR)/r_main.o :              $(MOUNT_DIR)/r_main.c
+	$(DO_CC)
+
+$(BUILDDIR)/r_sky.o :               $(MOUNT_DIR)/r_sky.c
+	$(DO_CC)
+
+$(BUILDDIR)/r_sprite.o :            $(MOUNT_DIR)/r_sprite.c
+	$(DO_CC)
+
+$(BUILDDIR)/r_surf.o :              $(MOUNT_DIR)/r_surf.c
+	$(DO_CC)
+
+$(BUILDDIR)/r_part.o :              $(MOUNT_DIR)/r_part.c
+	$(DO_CC)
+
+$(BUILDDIR)/r_vars.o :              $(MOUNT_DIR)/r_vars.c
+	$(DO_CC)
+
+$(BUILDDIR)/screen.o :              $(MOUNT_DIR)/screen.c
+	$(DO_CC)
+
+$(BUILDDIR)/sbar.o :                $(MOUNT_DIR)/sbar.c
+	$(DO_CC)
+
+$(BUILDDIR)/sv_main.o :             $(MOUNT_DIR)/sv_main.c
+	$(DO_CC)
+
+$(BUILDDIR)/sv_phys.o :             $(MOUNT_DIR)/sv_phys.c
+	$(DO_CC)
+
+$(BUILDDIR)/sv_move.o :             $(MOUNT_DIR)/sv_move.c
+	$(DO_CC)
+
+$(BUILDDIR)/sv_user.o :             $(MOUNT_DIR)/sv_user.c
+	$(DO_CC)
+
+$(BUILDDIR)/zone.o	:               $(MOUNT_DIR)/zone.c
+	$(DO_CC)
+
+$(BUILDDIR)/view.o	:               $(MOUNT_DIR)/view.c
+	$(DO_CC)
+
+$(BUILDDIR)/wad.o :                 $(MOUNT_DIR)/wad.c
+	$(DO_CC)
+
+$(BUILDDIR)/world.o :               $(MOUNT_DIR)/world.c
+	$(DO_CC)
+
+$(BUILDDIR)/cd_null.o :             $(MOUNT_DIR)/cd_null.c
+	$(DO_CC)
+
+$(BUILDDIR)/snd_dma.o :             $(MOUNT_DIR)/snd_dma.c
+	$(DO_CC)
+
+$(BUILDDIR)/snd_mix.o :             $(MOUNT_DIR)/snd_mix.c
+	$(DO_CC)
+
+$(BUILDDIR)/snd_mem.o :             $(MOUNT_DIR)/snd_mem.c
+	$(DO_CC)
+
+$(BUILDDIR)/net_dgrm.o :            $(MOUNT_DIR)/net_dgrm.c
+	$(DO_CC)
+
+$(BUILDDIR)/net_loop.o :            $(MOUNT_DIR)/net_loop.c
+	$(DO_CC)
+
+$(BUILDDIR)/net_main.o :            $(MOUNT_DIR)/net_main.c
+	$(DO_CC)
+
+$(BUILDDIR)/net_vcr.o :             $(MOUNT_DIR)/net_vcr.c
+	$(DO_CC)
+
+$(BUILDDIR)/net_udp.o :             $(MOUNT_DIR)/net_udp.c
+	$(DO_CC)
+
+$(BUILDDIR)/net_bsd.o :             $(MOUNT_DIR)/net_bsd.c
+	$(DO_CC)
+
+$(BUILDDIR)/sys_sun.o :             $(MOUNT_DIR)/sys_sun.c
+	$(DO_CC)
+
+$(BUILDDIR)/snd_sun.o :             $(MOUNT_DIR)/snd_sun.c
+	$(DO_CC)
+
+$(BUILDDIR)/in_sun.o :             $(MOUNT_DIR)/in_sun.c
+	$(DO_CC)
+
+$(BUILDDIR)/vid_sunx.o :             $(MOUNT_DIR)/vid_sunx.c
+	$(DO_CC)
+
+$(BUILDDIR)/vid_sunxil.o :             $(MOUNT_DIR)/vid_sunxil.c
+	$(DO_CC)
+
+#####
+
+$(BUILDDIR)/d_copy.o :   $(MOUNT_DIR)/d_copy.s
+	$(DO_AS)
+
+$(BUILDDIR)/d_draw.o :   $(MOUNT_DIR)/d_draw.s
+	$(DO_AS)
+
+$(BUILDDIR)/d_draw16.o : $(MOUNT_DIR)/d_draw16.s
+	$(DO_AS)
+
+$(BUILDDIR)/d_parta.o :  $(MOUNT_DIR)/d_parta.s
+	$(DO_AS)
+
+$(BUILDDIR)/d_polysa.o : $(MOUNT_DIR)/d_polysa.s
+	$(DO_AS)
+
+$(BUILDDIR)/d_scana.o :  $(MOUNT_DIR)/d_scana.s
+	$(DO_AS)
+
+$(BUILDDIR)/d_spr8.o :   $(MOUNT_DIR)/d_spr8.s
+	$(DO_AS)
+
+$(BUILDDIR)/d_varsa.o :  $(MOUNT_DIR)/d_varsa.s
+	$(DO_AS)
+
+$(BUILDDIR)/math.o :     $(MOUNT_DIR)/math.s
+	$(DO_AS)
+
+$(BUILDDIR)/r_aliasa.o : $(MOUNT_DIR)/r_aliasa.s
+	$(DO_AS)
+
+$(BUILDDIR)/r_drawa.o :  $(MOUNT_DIR)/r_drawa.s
+	$(DO_AS)
+
+$(BUILDDIR)/r_edgea.o :  $(MOUNT_DIR)/r_edgea.s
+	$(DO_AS)
+
+$(BUILDDIR)/r_varsa.o :  $(MOUNT_DIR)/r_varsa.s
+	$(DO_AS)
+
+$(BUILDDIR)/surf16.o :   $(MOUNT_DIR)/surf16.s
+	$(DO_AS)
+
+$(BUILDDIR)/surf8.o :    $(MOUNT_DIR)/surf8.s
+	$(DO_AS)
+
+$(BUILDDIR)/worlda.o :   $(MOUNT_DIR)/worlda.s
+	$(DO_AS)
+
+$(BUILDDIR)/r_aclipa.o : $(MOUNT_DIR)/r_aclipa.s
+	$(DO_AS)
+
+$(BUILDDIR)/snd_mixa.o : $(MOUNT_DIR)/snd_mixa.s
+	$(DO_AS)
+
+$(BUILDDIR)/sys_dosa.o : $(MOUNT_DIR)/sys_dosa.s
+	$(DO_AS)
+
+#############################################################################
+# TAR
+#############################################################################
+
+# Make RPMs.  You need to be root to make this work
+RPMDIR = /var/tmp/quake-$(VERSION)
+
+tar:
+	if [ ! -d archives ];then mkdir archives;fi
+	$(MAKE) copyfiles COPYDIR=$(RPMDIR)
+	cd $(RPMDIR); tar cvf q2ded-$(VERSION)-$(ARCH)-sun-solaris2.5.1.tar *
+	cd $(RPMDIR); compress q2ded-$(VERSION)-$(ARCH)-sun-solaris2.5.1.tar
+	mv $(RPMDIR)/*.tar.Z archives/.
+	rm -rf $(RPMDIR)
+
+copyfiles:
+	-mkdirhier $(COPYDIR)
+	cp $(BUILD_RELEASE_DIR)/quake.sw $(COPYDIR)
+	cp $(BUILD_RELEASE_DIR)/quake.xil $(COPYDIR)
+	strip $(COPYDIR)/quake
+	strip $(COPYDIR)/quake.xil
+	cp $(MOUNT_DIR)/README.Solaris $(COPYDIR)/README.Solaris
+
+#############################################################################
+# MISC
+#############################################################################
+
+clean: clean-debug clean-release
+
+clean-debug:
+	$(MAKE) clean2 BUILDDIR=$(BUILD_DEBUG_DIR) CFLAGS="$(DEBUG_CFLAGS)"
+
+clean-release:
+	$(MAKE) clean2 BUILDDIR=$(BUILD_RELEASE_DIR) CFLAGS="$(DEBUG_CFLAGS)"
+
+clean2:
+	-rm -f $(QUAKE_OBJS) $(QUAKE_X_OBJS) $(QUAKE_XIL_OBJS)
+
--- /dev/null
+++ b/WinQuake/Makefile.linuxi386
@@ -1,0 +1,1240 @@
+#
+# Quake Makefile for Linux 2.0
+#
+# Aug '98 by Zoid <zoid@idsoftware.com>
+#
+# ELF only
+#
+
+BASEVERSION=1.09
+VERSION=$(BASEVERSION)$(GLIBC)
+
+# RPM release number
+RPM_RELEASE=5
+
+ifneq (,$(findstring libc6,$(shell if [ -e /lib/libc.so.6 ];then echo libc6;fi)))
+GLIBC=-glibc
+else
+GLIBC=
+endif
+
+ifneq (,$(findstring alpha,$(shell uname -m)))
+ARCH=axp
+else
+ARCH=i386
+endif
+NOARCH=noarch
+
+MOUNT_DIR=/grog/Projects/WinQuake
+MASTER_DIR=/grog/Projects/QuakeMaster
+MESA_DIR=/usr/local/src/Mesa-2.6
+TDFXGL_DIR = /home/zoid/3dfxgl
+
+BUILD_DEBUG_DIR=debug$(ARCH)$(GLIBC)
+BUILD_RELEASE_DIR=release$(ARCH)$(GLIBC)
+
+EGCS=/usr/local/egcs-1.1.2/bin/gcc
+CC=$(EGCS)
+
+BASE_CFLAGS=-Dstricmp=strcasecmp
+RELEASE_CFLAGS=$(BASE_CFLAGS) -g -mpentiumpro -O6 -ffast-math -funroll-loops \
+	-fomit-frame-pointer -fexpensive-optimizations
+DEBUG_CFLAGS=$(BASE_CFLAGS) -g
+LDFLAGS=-lm
+SVGALDFLAGS=-lvga
+XLDFLAGS=-L/usr/X11R6/lib -lX11 -lXext -lXxf86dga
+XCFLAGS=-DX11
+
+MESAGLLDFLAGS=-L/usr/X11/lib -L/usr/local/lib -L$(MESA_DIR)/lib -lMesaGL -lglide2x -lX11 -lXext -ldl
+TDFXGLLDFLAGS=-L$(TDFXGL_DIR)/release$(ARCH)$(GLIBC) -l3dfxgl -lglide2x -ldl
+GLLDFLAGS=-L/usr/X11/lib -L/usr/local/lib -lGL -lX11 -lXext -ldl -lXxf86dga -lXxf86vm -lm
+GLCFLAGS=-DGLQUAKE -I$(MESA_DIR)/include -I/usr/include/glide
+
+DO_CC=$(CC) $(CFLAGS) -o $@ -c $<
+DO_DEBUG_CC=$(CC) $(DEBUG_CFLAGS) -o $@ -c $<
+DO_GL_CC=$(CC) $(CFLAGS) $(GLCFLAGS) -o $@ -c $<
+DO_GL_DEBUG_CC=$(CC) $(DEBUG_CFLAGS) $(GLCFLAGS) -o $@ -c $<
+DO_X11_CC=$(CC) $(CFLAGS) $(XCFLAGS) -o $@ -c $<
+DO_X11_DEBUG_CC=$(CC) $(DEBUG_CFLAGS) $(XCFLAGS) -o $@ -c $<
+DO_O_CC=$(CC) -O $(CFLAGS) -o $@ -c $<
+DO_AS=$(CC) $(CFLAGS) -DELF -x assembler-with-cpp -o $@ -c $<
+DO_GL_AS=$(CC) $(CFLAGS) $(GLCFLAGS) -DELF -x assembler-with-cpp -o $@ -c $<
+
+#############################################################################
+# SETUP AND BUILD
+#############################################################################
+
+TARGETS=$(BUILDDIR)/bin/squake \
+	$(BUILDDIR)/bin/glquake \
+	$(BUILDDIR)/bin/glquake.glx \
+	$(BUILDDIR)/bin/glquake.3dfxgl \
+	$(BUILDDIR)/bin/quake.x11
+	# $(BUILDDIR)/bin/unixded
+
+build_debug:
+	@-mkdir $(BUILD_DEBUG_DIR) \
+		$(BUILD_DEBUG_DIR)/bin \
+		$(BUILD_DEBUG_DIR)/glquake \
+		$(BUILD_DEBUG_DIR)/squake \
+		$(BUILD_DEBUG_DIR)/unixded \
+		$(BUILD_DEBUG_DIR)/x11
+	$(MAKE) targets BUILDDIR=$(BUILD_DEBUG_DIR) CFLAGS="$(DEBUG_CFLAGS)"
+
+build_release:
+	@-mkdir $(BUILD_RELEASE_DIR) \
+		$(BUILD_RELEASE_DIR)/bin \
+		$(BUILD_RELEASE_DIR)/glquake \
+		$(BUILD_RELEASE_DIR)/squake \
+		$(BUILD_RELEASE_DIR)/unixded \
+		$(BUILD_RELEASE_DIR)/x11
+	$(MAKE) targets BUILDDIR=$(BUILD_RELEASE_DIR) CFLAGS="$(RELEASE_CFLAGS)"
+
+all: build_debug build_release
+
+targets: $(TARGETS)
+
+#############################################################################
+# SVGALIB Quake
+#############################################################################
+
+SQUAKE_OBJS = \
+	$(BUILDDIR)/squake/cl_demo.o \
+	$(BUILDDIR)/squake/cl_input.o \
+	$(BUILDDIR)/squake/cl_main.o \
+	$(BUILDDIR)/squake/cl_parse.o \
+	$(BUILDDIR)/squake/cl_tent.o \
+	$(BUILDDIR)/squake/chase.o \
+	$(BUILDDIR)/squake/cmd.o \
+	$(BUILDDIR)/squake/common.o \
+	$(BUILDDIR)/squake/console.o \
+	$(BUILDDIR)/squake/crc.o \
+	$(BUILDDIR)/squake/cvar.o \
+	$(BUILDDIR)/squake/draw.o \
+	$(BUILDDIR)/squake/d_edge.o \
+	$(BUILDDIR)/squake/d_fill.o \
+	$(BUILDDIR)/squake/d_init.o \
+	$(BUILDDIR)/squake/d_modech.o \
+	$(BUILDDIR)/squake/d_part.o \
+	$(BUILDDIR)/squake/d_polyse.o \
+	$(BUILDDIR)/squake/d_scan.o \
+	$(BUILDDIR)/squake/d_sky.o \
+	$(BUILDDIR)/squake/d_sprite.o \
+	$(BUILDDIR)/squake/d_surf.o \
+	$(BUILDDIR)/squake/d_vars.o \
+	$(BUILDDIR)/squake/d_zpoint.o \
+	$(BUILDDIR)/squake/host.o \
+	$(BUILDDIR)/squake/host_cmd.o \
+	$(BUILDDIR)/squake/keys.o \
+	$(BUILDDIR)/squake/menu.o \
+	$(BUILDDIR)/squake/mathlib.o \
+	$(BUILDDIR)/squake/model.o \
+	$(BUILDDIR)/squake/net_dgrm.o \
+	$(BUILDDIR)/squake/net_loop.o \
+	$(BUILDDIR)/squake/net_main.o \
+	$(BUILDDIR)/squake/net_vcr.o \
+	$(BUILDDIR)/squake/net_udp.o \
+	$(BUILDDIR)/squake/net_bsd.o \
+	$(BUILDDIR)/squake/nonintel.o \
+	$(BUILDDIR)/squake/pr_cmds.o \
+	$(BUILDDIR)/squake/pr_edict.o \
+	$(BUILDDIR)/squake/pr_exec.o \
+	$(BUILDDIR)/squake/r_aclip.o \
+	$(BUILDDIR)/squake/r_alias.o \
+	$(BUILDDIR)/squake/r_bsp.o \
+	$(BUILDDIR)/squake/r_light.o \
+	$(BUILDDIR)/squake/r_draw.o \
+	$(BUILDDIR)/squake/r_efrag.o \
+	$(BUILDDIR)/squake/r_edge.o \
+	$(BUILDDIR)/squake/r_misc.o \
+	$(BUILDDIR)/squake/r_main.o \
+	$(BUILDDIR)/squake/r_sky.o \
+	$(BUILDDIR)/squake/r_sprite.o \
+	$(BUILDDIR)/squake/r_surf.o \
+	$(BUILDDIR)/squake/r_part.o \
+	$(BUILDDIR)/squake/r_vars.o \
+	$(BUILDDIR)/squake/screen.o \
+	$(BUILDDIR)/squake/sbar.o \
+	$(BUILDDIR)/squake/sv_main.o \
+	$(BUILDDIR)/squake/sv_phys.o \
+	$(BUILDDIR)/squake/sv_move.o \
+	$(BUILDDIR)/squake/sv_user.o \
+	$(BUILDDIR)/squake/zone.o	\
+	$(BUILDDIR)/squake/view.o	\
+	$(BUILDDIR)/squake/wad.o \
+	$(BUILDDIR)/squake/world.o \
+	$(BUILDDIR)/squake/cd_linux.o \
+	$(BUILDDIR)/squake/sys_linux.o \
+	$(BUILDDIR)/squake/vid_svgalib.o \
+	$(BUILDDIR)/squake/snd_dma.o \
+	$(BUILDDIR)/squake/snd_mem.o \
+	$(BUILDDIR)/squake/snd_mix.o \
+	$(BUILDDIR)/squake/snd_linux.o \
+	\
+	$(BUILDDIR)/squake/d_copy.o \
+	$(BUILDDIR)/squake/d_draw.o \
+	$(BUILDDIR)/squake/d_draw16.o \
+	$(BUILDDIR)/squake/d_parta.o \
+	$(BUILDDIR)/squake/d_polysa.o \
+	$(BUILDDIR)/squake/d_scana.o \
+	$(BUILDDIR)/squake/d_spr8.o \
+	$(BUILDDIR)/squake/d_varsa.o \
+	$(BUILDDIR)/squake/math.o \
+	$(BUILDDIR)/squake/r_aliasa.o \
+	$(BUILDDIR)/squake/r_drawa.o \
+	$(BUILDDIR)/squake/r_edgea.o \
+	$(BUILDDIR)/squake/r_varsa.o \
+	$(BUILDDIR)/squake/surf16.o \
+	$(BUILDDIR)/squake/surf8.o \
+	$(BUILDDIR)/squake/worlda.o \
+	$(BUILDDIR)/squake/r_aclipa.o \
+	$(BUILDDIR)/squake/snd_mixa.o \
+	$(BUILDDIR)/squake/sys_dosa.o
+
+$(BUILDDIR)/bin/squake : $(SQUAKE_OBJS)
+	$(CC) $(CFLAGS) -o $@ $(SQUAKE_OBJS) $(SVGALDFLAGS) $(LDFLAGS)
+
+####
+
+$(BUILDDIR)/squake/cl_demo.o :  $(MOUNT_DIR)/cl_demo.c
+	$(DO_CC)
+
+$(BUILDDIR)/squake/cl_input.o : $(MOUNT_DIR)/cl_input.c
+	$(DO_CC)
+
+$(BUILDDIR)/squake/cl_main.o :  $(MOUNT_DIR)/cl_main.c
+	$(DO_CC)
+
+$(BUILDDIR)/squake/cl_parse.o : $(MOUNT_DIR)/cl_parse.c
+	$(DO_CC)
+
+$(BUILDDIR)/squake/cl_tent.o :  $(MOUNT_DIR)/cl_tent.c
+	$(DO_CC)
+
+$(BUILDDIR)/squake/chase.o :    $(MOUNT_DIR)/chase.c
+	$(DO_CC)
+
+$(BUILDDIR)/squake/cmd.o :      $(MOUNT_DIR)/cmd.c
+	$(DO_CC)
+
+$(BUILDDIR)/squake/common.o :   $(MOUNT_DIR)/common.c
+	$(DO_DEBUG_CC)
+
+$(BUILDDIR)/squake/console.o :  $(MOUNT_DIR)/console.c
+	$(DO_CC)
+
+$(BUILDDIR)/squake/crc.o :      $(MOUNT_DIR)/crc.c
+	$(DO_CC)
+
+$(BUILDDIR)/squake/cvar.o :     $(MOUNT_DIR)/cvar.c
+	$(DO_CC)
+
+$(BUILDDIR)/squake/draw.o :     $(MOUNT_DIR)/draw.c
+	$(DO_CC)
+
+$(BUILDDIR)/squake/d_edge.o :   $(MOUNT_DIR)/d_edge.c
+	$(DO_CC)
+
+$(BUILDDIR)/squake/d_fill.o :   $(MOUNT_DIR)/d_fill.c
+	$(DO_CC)
+
+$(BUILDDIR)/squake/d_init.o :   $(MOUNT_DIR)/d_init.c
+	$(DO_CC)
+
+$(BUILDDIR)/squake/d_modech.o : $(MOUNT_DIR)/d_modech.c
+	$(DO_CC)
+
+$(BUILDDIR)/squake/d_part.o :   $(MOUNT_DIR)/d_part.c
+	$(DO_CC)
+
+$(BUILDDIR)/squake/d_polyse.o : $(MOUNT_DIR)/d_polyse.c
+	$(DO_CC)
+
+$(BUILDDIR)/squake/d_scan.o :   $(MOUNT_DIR)/d_scan.c
+	$(DO_CC)
+
+$(BUILDDIR)/squake/d_sky.o :    $(MOUNT_DIR)/d_sky.c
+	$(DO_CC)
+
+$(BUILDDIR)/squake/d_sprite.o : $(MOUNT_DIR)/d_sprite.c
+	$(DO_CC)
+
+$(BUILDDIR)/squake/d_surf.o :   $(MOUNT_DIR)/d_surf.c
+	$(DO_CC)
+
+$(BUILDDIR)/squake/d_vars.o :   $(MOUNT_DIR)/d_vars.c
+	$(DO_CC)
+
+$(BUILDDIR)/squake/d_zpoint.o : $(MOUNT_DIR)/d_zpoint.c
+	$(DO_CC)
+
+$(BUILDDIR)/squake/host.o :     $(MOUNT_DIR)/host.c
+	$(DO_CC)
+
+$(BUILDDIR)/squake/host_cmd.o : $(MOUNT_DIR)/host_cmd.c
+	$(DO_CC)
+
+$(BUILDDIR)/squake/keys.o :     $(MOUNT_DIR)/keys.c
+	$(DO_CC)
+
+$(BUILDDIR)/squake/menu.o :     $(MOUNT_DIR)/menu.c
+	$(DO_CC)
+
+$(BUILDDIR)/squake/mathlib.o :  $(MOUNT_DIR)/mathlib.c
+	$(DO_CC)
+
+$(BUILDDIR)/squake/model.o :    $(MOUNT_DIR)/model.c
+	$(DO_CC)
+
+$(BUILDDIR)/squake/net_dgrm.o : $(MOUNT_DIR)/net_dgrm.c
+	$(DO_CC)
+
+$(BUILDDIR)/squake/net_loop.o : $(MOUNT_DIR)/net_loop.c
+	$(DO_CC)
+
+$(BUILDDIR)/squake/net_main.o : $(MOUNT_DIR)/net_main.c
+	$(DO_CC)
+
+$(BUILDDIR)/squake/net_vcr.o :  $(MOUNT_DIR)/net_vcr.c
+	$(DO_CC)
+
+$(BUILDDIR)/squake/net_udp.o :  $(MOUNT_DIR)/net_udp.c
+	$(DO_CC)
+
+$(BUILDDIR)/squake/net_bsd.o :  $(MOUNT_DIR)/net_bsd.c
+	$(DO_CC)
+
+$(BUILDDIR)/squake/nonintel.o : $(MOUNT_DIR)/nonintel.c
+	$(DO_CC)
+
+$(BUILDDIR)/squake/pr_cmds.o :  $(MOUNT_DIR)/pr_cmds.c
+	$(DO_CC)
+
+$(BUILDDIR)/squake/pr_edict.o : $(MOUNT_DIR)/pr_edict.c
+	$(DO_CC)
+
+$(BUILDDIR)/squake/pr_exec.o :  $(MOUNT_DIR)/pr_exec.c
+	$(DO_CC)
+
+$(BUILDDIR)/squake/r_aclip.o :  $(MOUNT_DIR)/r_aclip.c
+	$(DO_CC)
+
+$(BUILDDIR)/squake/r_alias.o :  $(MOUNT_DIR)/r_alias.c
+	$(DO_CC)
+
+$(BUILDDIR)/squake/r_bsp.o :    $(MOUNT_DIR)/r_bsp.c
+	$(DO_CC)
+
+$(BUILDDIR)/squake/r_light.o :  $(MOUNT_DIR)/r_light.c
+	$(DO_CC)
+
+$(BUILDDIR)/squake/r_draw.o :   $(MOUNT_DIR)/r_draw.c
+	$(DO_CC)
+
+$(BUILDDIR)/squake/r_efrag.o :  $(MOUNT_DIR)/r_efrag.c
+	$(DO_CC)
+
+$(BUILDDIR)/squake/r_edge.o :   $(MOUNT_DIR)/r_edge.c
+	$(DO_CC)
+
+$(BUILDDIR)/squake/r_misc.o :   $(MOUNT_DIR)/r_misc.c
+	$(DO_CC)
+
+$(BUILDDIR)/squake/r_main.o :   $(MOUNT_DIR)/r_main.c
+	$(DO_CC)
+
+$(BUILDDIR)/squake/r_sky.o :    $(MOUNT_DIR)/r_sky.c
+	$(DO_CC)
+
+$(BUILDDIR)/squake/r_sprite.o : $(MOUNT_DIR)/r_sprite.c
+	$(DO_CC)
+
+$(BUILDDIR)/squake/r_surf.o :   $(MOUNT_DIR)/r_surf.c
+	$(DO_CC)
+
+$(BUILDDIR)/squake/r_part.o :   $(MOUNT_DIR)/r_part.c
+	$(DO_CC)
+
+$(BUILDDIR)/squake/r_vars.o :   $(MOUNT_DIR)/r_vars.c
+	$(DO_CC)
+
+$(BUILDDIR)/squake/screen.o :   $(MOUNT_DIR)/screen.c
+	$(DO_CC)
+
+$(BUILDDIR)/squake/sbar.o :     $(MOUNT_DIR)/sbar.c
+	$(DO_CC)
+
+$(BUILDDIR)/squake/sv_main.o :  $(MOUNT_DIR)/sv_main.c
+	$(DO_CC)
+
+$(BUILDDIR)/squake/sv_phys.o :  $(MOUNT_DIR)/sv_phys.c
+	$(DO_CC)
+
+$(BUILDDIR)/squake/sv_move.o :  $(MOUNT_DIR)/sv_move.c
+	$(DO_CC)
+
+$(BUILDDIR)/squake/sv_user.o :  $(MOUNT_DIR)/sv_user.c
+	$(DO_CC)
+
+$(BUILDDIR)/squake/zone.o	:   $(MOUNT_DIR)/zone.c
+	$(DO_CC)
+
+$(BUILDDIR)/squake/view.o	:   $(MOUNT_DIR)/view.c
+	$(DO_CC)
+
+$(BUILDDIR)/squake/wad.o :      $(MOUNT_DIR)/wad.c
+	$(DO_CC)
+
+$(BUILDDIR)/squake/world.o :    $(MOUNT_DIR)/world.c
+	$(DO_CC)
+
+$(BUILDDIR)/squake/cd_linux.o : $(MOUNT_DIR)/cd_linux.c
+	$(DO_CC)
+
+$(BUILDDIR)/squake/sys_linux.o :$(MOUNT_DIR)/sys_linux.c
+	$(DO_CC)
+
+$(BUILDDIR)/squake/vid_svgalib.o:$(MOUNT_DIR)/vid_svgalib.c
+	$(DO_O_CC)
+
+$(BUILDDIR)/squake/snd_dma.o :  $(MOUNT_DIR)/snd_dma.c
+	$(DO_CC)
+
+$(BUILDDIR)/squake/snd_mem.o :  $(MOUNT_DIR)/snd_mem.c
+	$(DO_CC)
+
+$(BUILDDIR)/squake/snd_mix.o :  $(MOUNT_DIR)/snd_mix.c
+	$(DO_CC)
+
+$(BUILDDIR)/squake/snd_linux.o :$(MOUNT_DIR)/snd_linux.c
+	$(DO_CC)
+
+#####
+
+$(BUILDDIR)/squake/d_copy.o :   $(MOUNT_DIR)/d_copy.s
+	$(DO_AS)
+
+$(BUILDDIR)/squake/d_draw.o :   $(MOUNT_DIR)/d_draw.s
+	$(DO_AS)
+
+$(BUILDDIR)/squake/d_draw16.o : $(MOUNT_DIR)/d_draw16.s
+	$(DO_AS)
+
+$(BUILDDIR)/squake/d_parta.o :  $(MOUNT_DIR)/d_parta.s
+	$(DO_AS)
+
+$(BUILDDIR)/squake/d_polysa.o : $(MOUNT_DIR)/d_polysa.s
+	$(DO_AS)
+
+$(BUILDDIR)/squake/d_scana.o :  $(MOUNT_DIR)/d_scana.s
+	$(DO_AS)
+
+$(BUILDDIR)/squake/d_spr8.o :   $(MOUNT_DIR)/d_spr8.s
+	$(DO_AS)
+
+$(BUILDDIR)/squake/d_varsa.o :  $(MOUNT_DIR)/d_varsa.s
+	$(DO_AS)
+
+$(BUILDDIR)/squake/math.o :     $(MOUNT_DIR)/math.s
+	$(DO_AS)
+
+$(BUILDDIR)/squake/r_aliasa.o : $(MOUNT_DIR)/r_aliasa.s
+	$(DO_AS)
+
+$(BUILDDIR)/squake/r_drawa.o :  $(MOUNT_DIR)/r_drawa.s
+	$(DO_AS)
+
+$(BUILDDIR)/squake/r_edgea.o :  $(MOUNT_DIR)/r_edgea.s
+	$(DO_AS)
+
+$(BUILDDIR)/squake/r_varsa.o :  $(MOUNT_DIR)/r_varsa.s
+	$(DO_AS)
+
+$(BUILDDIR)/squake/surf16.o :   $(MOUNT_DIR)/surf16.s
+	$(DO_AS)
+
+$(BUILDDIR)/squake/surf8.o :    $(MOUNT_DIR)/surf8.s
+	$(DO_AS)
+
+$(BUILDDIR)/squake/worlda.o :   $(MOUNT_DIR)/worlda.s
+	$(DO_AS)
+
+$(BUILDDIR)/squake/r_aclipa.o : $(MOUNT_DIR)/r_aclipa.s
+	$(DO_AS)
+
+$(BUILDDIR)/squake/snd_mixa.o : $(MOUNT_DIR)/snd_mixa.s
+	$(DO_AS)
+
+$(BUILDDIR)/squake/sys_dosa.o : $(MOUNT_DIR)/sys_dosa.s
+	$(DO_AS)
+
+#############################################################################
+# X11 Quake
+#############################################################################
+
+X11_OBJS = \
+	$(BUILDDIR)/x11/cl_demo.o \
+	$(BUILDDIR)/x11/cl_input.o \
+	$(BUILDDIR)/x11/cl_main.o \
+	$(BUILDDIR)/x11/cl_parse.o \
+	$(BUILDDIR)/x11/cl_tent.o \
+	$(BUILDDIR)/x11/chase.o \
+	$(BUILDDIR)/x11/cmd.o \
+	$(BUILDDIR)/x11/common.o \
+	$(BUILDDIR)/x11/console.o \
+	$(BUILDDIR)/x11/crc.o \
+	$(BUILDDIR)/x11/cvar.o \
+	$(BUILDDIR)/x11/draw.o \
+	$(BUILDDIR)/x11/d_edge.o \
+	$(BUILDDIR)/x11/d_fill.o \
+	$(BUILDDIR)/x11/d_init.o \
+	$(BUILDDIR)/x11/d_modech.o \
+	$(BUILDDIR)/x11/d_part.o \
+	$(BUILDDIR)/x11/d_polyse.o \
+	$(BUILDDIR)/x11/d_scan.o \
+	$(BUILDDIR)/x11/d_sky.o \
+	$(BUILDDIR)/x11/d_sprite.o \
+	$(BUILDDIR)/x11/d_surf.o \
+	$(BUILDDIR)/x11/d_vars.o \
+	$(BUILDDIR)/x11/d_zpoint.o \
+	$(BUILDDIR)/x11/host.o \
+	$(BUILDDIR)/x11/host_cmd.o \
+	$(BUILDDIR)/x11/keys.o \
+	$(BUILDDIR)/x11/menu.o \
+	$(BUILDDIR)/x11/mathlib.o \
+	$(BUILDDIR)/x11/model.o \
+	$(BUILDDIR)/x11/net_dgrm.o \
+	$(BUILDDIR)/x11/net_loop.o \
+	$(BUILDDIR)/x11/net_main.o \
+	$(BUILDDIR)/x11/net_vcr.o \
+	$(BUILDDIR)/x11/net_udp.o \
+	$(BUILDDIR)/x11/net_bsd.o \
+	$(BUILDDIR)/x11/nonintel.o \
+	$(BUILDDIR)/x11/pr_cmds.o \
+	$(BUILDDIR)/x11/pr_edict.o \
+	$(BUILDDIR)/x11/pr_exec.o \
+	$(BUILDDIR)/x11/r_aclip.o \
+	$(BUILDDIR)/x11/r_alias.o \
+	$(BUILDDIR)/x11/r_bsp.o \
+	$(BUILDDIR)/x11/r_light.o \
+	$(BUILDDIR)/x11/r_draw.o \
+	$(BUILDDIR)/x11/r_efrag.o \
+	$(BUILDDIR)/x11/r_edge.o \
+	$(BUILDDIR)/x11/r_misc.o \
+	$(BUILDDIR)/x11/r_main.o \
+	$(BUILDDIR)/x11/r_sky.o \
+	$(BUILDDIR)/x11/r_sprite.o \
+	$(BUILDDIR)/x11/r_surf.o \
+	$(BUILDDIR)/x11/r_part.o \
+	$(BUILDDIR)/x11/r_vars.o \
+	$(BUILDDIR)/x11/screen.o \
+	$(BUILDDIR)/x11/sbar.o \
+	$(BUILDDIR)/x11/sv_main.o \
+	$(BUILDDIR)/x11/sv_phys.o \
+	$(BUILDDIR)/x11/sv_move.o \
+	$(BUILDDIR)/x11/sv_user.o \
+	$(BUILDDIR)/x11/zone.o	\
+	$(BUILDDIR)/x11/view.o	\
+	$(BUILDDIR)/x11/wad.o \
+	$(BUILDDIR)/x11/world.o \
+	$(BUILDDIR)/x11/cd_linux.o \
+	$(BUILDDIR)/x11/sys_linux.o \
+	$(BUILDDIR)/x11/vid_x.o \
+	$(BUILDDIR)/x11/snd_dma.o \
+	$(BUILDDIR)/x11/snd_mem.o \
+	$(BUILDDIR)/x11/snd_mix.o \
+	$(BUILDDIR)/x11/snd_linux.o \
+	\
+	$(BUILDDIR)/x11/d_draw.o \
+	$(BUILDDIR)/x11/d_draw16.o \
+	$(BUILDDIR)/x11/d_parta.o \
+	$(BUILDDIR)/x11/d_polysa.o \
+	$(BUILDDIR)/x11/d_scana.o \
+	$(BUILDDIR)/x11/d_spr8.o \
+	$(BUILDDIR)/x11/d_varsa.o \
+	$(BUILDDIR)/x11/math.o \
+	$(BUILDDIR)/x11/r_aliasa.o \
+	$(BUILDDIR)/x11/r_drawa.o \
+	$(BUILDDIR)/x11/r_edgea.o \
+	$(BUILDDIR)/x11/r_varsa.o \
+	$(BUILDDIR)/x11/surf16.o \
+	$(BUILDDIR)/x11/surf8.o \
+	$(BUILDDIR)/x11/worlda.o \
+	$(BUILDDIR)/x11/r_aclipa.o \
+	$(BUILDDIR)/x11/snd_mixa.o \
+	$(BUILDDIR)/x11/sys_dosa.o
+
+$(BUILDDIR)/bin/quake.x11 : $(X11_OBJS)
+	$(CC) $(CFLAGS) -o $@ $(X11_OBJS) $(XLDFLAGS) $(LDFLAGS)
+
+####
+
+$(BUILDDIR)/x11/cl_demo.o :  $(MOUNT_DIR)/cl_demo.c
+	$(DO_X11_CC)
+
+$(BUILDDIR)/x11/cl_input.o : $(MOUNT_DIR)/cl_input.c
+	$(DO_X11_CC)
+
+$(BUILDDIR)/x11/cl_main.o :  $(MOUNT_DIR)/cl_main.c
+	$(DO_X11_CC)
+
+$(BUILDDIR)/x11/cl_parse.o : $(MOUNT_DIR)/cl_parse.c
+	$(DO_X11_CC)
+
+$(BUILDDIR)/x11/cl_tent.o :  $(MOUNT_DIR)/cl_tent.c
+	$(DO_X11_CC)
+
+$(BUILDDIR)/x11/chase.o :    $(MOUNT_DIR)/chase.c
+	$(DO_X11_CC)
+
+$(BUILDDIR)/x11/cmd.o :      $(MOUNT_DIR)/cmd.c
+	$(DO_X11_CC)
+
+$(BUILDDIR)/x11/common.o :   $(MOUNT_DIR)/common.c
+	$(DO_X11_DEBUG_CC)
+
+$(BUILDDIR)/x11/console.o :  $(MOUNT_DIR)/console.c
+	$(DO_X11_CC)
+
+$(BUILDDIR)/x11/crc.o :      $(MOUNT_DIR)/crc.c
+	$(DO_X11_CC)
+
+$(BUILDDIR)/x11/cvar.o :     $(MOUNT_DIR)/cvar.c
+	$(DO_X11_CC)
+
+$(BUILDDIR)/x11/draw.o :     $(MOUNT_DIR)/draw.c
+	$(DO_X11_CC)
+
+$(BUILDDIR)/x11/d_edge.o :   $(MOUNT_DIR)/d_edge.c
+	$(DO_X11_CC)
+
+$(BUILDDIR)/x11/d_fill.o :   $(MOUNT_DIR)/d_fill.c
+	$(DO_X11_CC)
+
+$(BUILDDIR)/x11/d_init.o :   $(MOUNT_DIR)/d_init.c
+	$(DO_X11_CC)
+
+$(BUILDDIR)/x11/d_modech.o : $(MOUNT_DIR)/d_modech.c
+	$(DO_X11_CC)
+
+$(BUILDDIR)/x11/d_part.o :   $(MOUNT_DIR)/d_part.c
+	$(DO_X11_CC)
+
+$(BUILDDIR)/x11/d_polyse.o : $(MOUNT_DIR)/d_polyse.c
+	$(DO_X11_CC)
+
+$(BUILDDIR)/x11/d_scan.o :   $(MOUNT_DIR)/d_scan.c
+	$(DO_X11_CC)
+
+$(BUILDDIR)/x11/d_sky.o :    $(MOUNT_DIR)/d_sky.c
+	$(DO_X11_CC)
+
+$(BUILDDIR)/x11/d_sprite.o : $(MOUNT_DIR)/d_sprite.c
+	$(DO_X11_CC)
+
+$(BUILDDIR)/x11/d_surf.o :   $(MOUNT_DIR)/d_surf.c
+	$(DO_X11_CC)
+
+$(BUILDDIR)/x11/d_vars.o :   $(MOUNT_DIR)/d_vars.c
+	$(DO_X11_CC)
+
+$(BUILDDIR)/x11/d_zpoint.o : $(MOUNT_DIR)/d_zpoint.c
+	$(DO_X11_CC)
+
+$(BUILDDIR)/x11/host.o :     $(MOUNT_DIR)/host.c
+	$(DO_X11_CC)
+
+$(BUILDDIR)/x11/host_cmd.o : $(MOUNT_DIR)/host_cmd.c
+	$(DO_X11_CC)
+
+$(BUILDDIR)/x11/keys.o :     $(MOUNT_DIR)/keys.c
+	$(DO_X11_CC)
+
+$(BUILDDIR)/x11/menu.o :     $(MOUNT_DIR)/menu.c
+	$(DO_X11_CC)
+
+$(BUILDDIR)/x11/mathlib.o :  $(MOUNT_DIR)/mathlib.c
+	$(DO_X11_CC)
+
+$(BUILDDIR)/x11/model.o :    $(MOUNT_DIR)/model.c
+	$(DO_X11_CC)
+
+$(BUILDDIR)/x11/net_dgrm.o : $(MOUNT_DIR)/net_dgrm.c
+	$(DO_X11_CC)
+
+$(BUILDDIR)/x11/net_loop.o : $(MOUNT_DIR)/net_loop.c
+	$(DO_X11_CC)
+
+$(BUILDDIR)/x11/net_main.o : $(MOUNT_DIR)/net_main.c
+	$(DO_X11_CC)
+
+$(BUILDDIR)/x11/net_vcr.o :  $(MOUNT_DIR)/net_vcr.c
+	$(DO_X11_CC)
+
+$(BUILDDIR)/x11/net_udp.o :  $(MOUNT_DIR)/net_udp.c
+	$(DO_X11_CC)
+
+$(BUILDDIR)/x11/net_bsd.o :  $(MOUNT_DIR)/net_bsd.c
+	$(DO_X11_CC)
+
+$(BUILDDIR)/x11/nonintel.o : $(MOUNT_DIR)/nonintel.c
+	$(DO_X11_CC)
+
+$(BUILDDIR)/x11/pr_cmds.o :  $(MOUNT_DIR)/pr_cmds.c
+	$(DO_X11_CC)
+
+$(BUILDDIR)/x11/pr_edict.o : $(MOUNT_DIR)/pr_edict.c
+	$(DO_X11_CC)
+
+$(BUILDDIR)/x11/pr_exec.o :  $(MOUNT_DIR)/pr_exec.c
+	$(DO_X11_CC)
+
+$(BUILDDIR)/x11/r_aclip.o :  $(MOUNT_DIR)/r_aclip.c
+	$(DO_X11_CC)
+
+$(BUILDDIR)/x11/r_alias.o :  $(MOUNT_DIR)/r_alias.c
+	$(DO_X11_CC)
+
+$(BUILDDIR)/x11/r_bsp.o :    $(MOUNT_DIR)/r_bsp.c
+	$(DO_X11_CC)
+
+$(BUILDDIR)/x11/r_light.o :  $(MOUNT_DIR)/r_light.c
+	$(DO_X11_CC)
+
+$(BUILDDIR)/x11/r_draw.o :   $(MOUNT_DIR)/r_draw.c
+	$(DO_X11_CC)
+
+$(BUILDDIR)/x11/r_efrag.o :  $(MOUNT_DIR)/r_efrag.c
+	$(DO_X11_CC)
+
+$(BUILDDIR)/x11/r_edge.o :   $(MOUNT_DIR)/r_edge.c
+	$(DO_X11_CC)
+
+$(BUILDDIR)/x11/r_misc.o :   $(MOUNT_DIR)/r_misc.c
+	$(DO_X11_CC)
+
+$(BUILDDIR)/x11/r_main.o :   $(MOUNT_DIR)/r_main.c
+	$(DO_X11_CC)
+
+$(BUILDDIR)/x11/r_sky.o :    $(MOUNT_DIR)/r_sky.c
+	$(DO_X11_CC)
+
+$(BUILDDIR)/x11/r_sprite.o : $(MOUNT_DIR)/r_sprite.c
+	$(DO_X11_CC)
+
+$(BUILDDIR)/x11/r_surf.o :   $(MOUNT_DIR)/r_surf.c
+	$(DO_X11_CC)
+
+$(BUILDDIR)/x11/r_part.o :   $(MOUNT_DIR)/r_part.c
+	$(DO_X11_CC)
+
+$(BUILDDIR)/x11/r_vars.o :   $(MOUNT_DIR)/r_vars.c
+	$(DO_X11_CC)
+
+$(BUILDDIR)/x11/screen.o :   $(MOUNT_DIR)/screen.c
+	$(DO_X11_CC)
+
+$(BUILDDIR)/x11/sbar.o :     $(MOUNT_DIR)/sbar.c
+	$(DO_X11_CC)
+
+$(BUILDDIR)/x11/sv_main.o :  $(MOUNT_DIR)/sv_main.c
+	$(DO_X11_CC)
+
+$(BUILDDIR)/x11/sv_phys.o :  $(MOUNT_DIR)/sv_phys.c
+	$(DO_X11_CC)
+
+$(BUILDDIR)/x11/sv_move.o :  $(MOUNT_DIR)/sv_move.c
+	$(DO_X11_CC)
+
+$(BUILDDIR)/x11/sv_user.o :  $(MOUNT_DIR)/sv_user.c
+	$(DO_X11_CC)
+
+$(BUILDDIR)/x11/zone.o	:   $(MOUNT_DIR)/zone.c
+	$(DO_X11_CC)
+
+$(BUILDDIR)/x11/view.o	:   $(MOUNT_DIR)/view.c
+	$(DO_X11_CC)
+
+$(BUILDDIR)/x11/wad.o :      $(MOUNT_DIR)/wad.c
+	$(DO_X11_CC)
+
+$(BUILDDIR)/x11/world.o :    $(MOUNT_DIR)/world.c
+	$(DO_X11_CC)
+
+$(BUILDDIR)/x11/cd_linux.o : $(MOUNT_DIR)/cd_linux.c
+	$(DO_X11_CC)
+
+$(BUILDDIR)/x11/sys_linux.o :$(MOUNT_DIR)/sys_linux.c
+	$(DO_X11_CC)
+
+$(BUILDDIR)/x11/vid_x.o: $(MOUNT_DIR)/vid_x.c
+	$(DO_O_CC)
+
+$(BUILDDIR)/x11/snd_dma.o :  $(MOUNT_DIR)/snd_dma.c
+	$(DO_X11_CC)
+
+$(BUILDDIR)/x11/snd_mem.o :  $(MOUNT_DIR)/snd_mem.c
+	$(DO_X11_CC)
+
+$(BUILDDIR)/x11/snd_mix.o :  $(MOUNT_DIR)/snd_mix.c
+	$(DO_X11_CC)
+
+$(BUILDDIR)/x11/snd_linux.o :$(MOUNT_DIR)/snd_linux.c
+	$(DO_X11_CC)
+
+#####
+
+$(BUILDDIR)/x11/d_copy.o :   $(MOUNT_DIR)/d_copy.s
+	$(DO_AS)
+
+$(BUILDDIR)/x11/d_draw.o :   $(MOUNT_DIR)/d_draw.s
+	$(DO_AS)
+
+$(BUILDDIR)/x11/d_draw16.o : $(MOUNT_DIR)/d_draw16.s
+	$(DO_AS)
+
+$(BUILDDIR)/x11/d_parta.o :  $(MOUNT_DIR)/d_parta.s
+	$(DO_AS)
+
+$(BUILDDIR)/x11/d_polysa.o : $(MOUNT_DIR)/d_polysa.s
+	$(DO_AS)
+
+$(BUILDDIR)/x11/d_scana.o :  $(MOUNT_DIR)/d_scana.s
+	$(DO_AS)
+
+$(BUILDDIR)/x11/d_spr8.o :   $(MOUNT_DIR)/d_spr8.s
+	$(DO_AS)
+
+$(BUILDDIR)/x11/d_varsa.o :  $(MOUNT_DIR)/d_varsa.s
+	$(DO_AS)
+
+$(BUILDDIR)/x11/math.o :     $(MOUNT_DIR)/math.s
+	$(DO_AS)
+
+$(BUILDDIR)/x11/r_aliasa.o : $(MOUNT_DIR)/r_aliasa.s
+	$(DO_AS)
+
+$(BUILDDIR)/x11/r_drawa.o :  $(MOUNT_DIR)/r_drawa.s
+	$(DO_AS)
+
+$(BUILDDIR)/x11/r_edgea.o :  $(MOUNT_DIR)/r_edgea.s
+	$(DO_AS)
+
+$(BUILDDIR)/x11/r_varsa.o :  $(MOUNT_DIR)/r_varsa.s
+	$(DO_AS)
+
+$(BUILDDIR)/x11/surf16.o :   $(MOUNT_DIR)/surf16.s
+	$(DO_AS)
+
+$(BUILDDIR)/x11/surf8.o :    $(MOUNT_DIR)/surf8.s
+	$(DO_AS)
+
+$(BUILDDIR)/x11/worlda.o :   $(MOUNT_DIR)/worlda.s
+	$(DO_AS)
+
+$(BUILDDIR)/x11/r_aclipa.o : $(MOUNT_DIR)/r_aclipa.s
+	$(DO_AS)
+
+$(BUILDDIR)/x11/snd_mixa.o : $(MOUNT_DIR)/snd_mixa.s
+	$(DO_AS)
+
+$(BUILDDIR)/x11/sys_dosa.o : $(MOUNT_DIR)/sys_dosa.s
+	$(DO_AS)
+
+#############################################################################
+# GLQuake
+#############################################################################
+
+GLQUAKE_OBJS= \
+	$(BUILDDIR)/glquake/cl_demo.o \
+	$(BUILDDIR)/glquake/cl_input.o \
+	$(BUILDDIR)/glquake/cl_main.o \
+	$(BUILDDIR)/glquake/cl_parse.o \
+	$(BUILDDIR)/glquake/cl_tent.o \
+	$(BUILDDIR)/glquake/chase.o \
+	$(BUILDDIR)/glquake/cmd.o \
+	$(BUILDDIR)/glquake/common.o \
+	$(BUILDDIR)/glquake/console.o \
+	$(BUILDDIR)/glquake/crc.o \
+	$(BUILDDIR)/glquake/cvar.o \
+	\
+	$(BUILDDIR)/glquake/gl_draw.o \
+	$(BUILDDIR)/glquake/gl_mesh.o \
+	$(BUILDDIR)/glquake/gl_model.o \
+	$(BUILDDIR)/glquake/gl_refrag.o \
+	$(BUILDDIR)/glquake/gl_rlight.o \
+	$(BUILDDIR)/glquake/gl_rmain.o \
+	$(BUILDDIR)/glquake/gl_rmisc.o \
+	$(BUILDDIR)/glquake/gl_rsurf.o \
+	$(BUILDDIR)/glquake/gl_screen.o \
+	$(BUILDDIR)/glquake/gl_test.o \
+	$(BUILDDIR)/glquake/gl_warp.o \
+	\
+	$(BUILDDIR)/glquake/host.o \
+	$(BUILDDIR)/glquake/host_cmd.o \
+	$(BUILDDIR)/glquake/keys.o \
+	$(BUILDDIR)/glquake/menu.o \
+	$(BUILDDIR)/glquake/mathlib.o \
+	$(BUILDDIR)/glquake/net_dgrm.o \
+	$(BUILDDIR)/glquake/net_loop.o \
+	$(BUILDDIR)/glquake/net_main.o \
+	$(BUILDDIR)/glquake/net_vcr.o \
+	$(BUILDDIR)/glquake/net_udp.o \
+	$(BUILDDIR)/glquake/net_bsd.o \
+	$(BUILDDIR)/glquake/pr_cmds.o \
+	$(BUILDDIR)/glquake/pr_edict.o \
+	$(BUILDDIR)/glquake/pr_exec.o \
+	$(BUILDDIR)/glquake/r_part.o \
+	$(BUILDDIR)/glquake/sbar.o \
+	$(BUILDDIR)/glquake/sv_main.o \
+	$(BUILDDIR)/glquake/sv_phys.o \
+	$(BUILDDIR)/glquake/sv_move.o \
+	$(BUILDDIR)/glquake/sv_user.o \
+	$(BUILDDIR)/glquake/zone.o	\
+	$(BUILDDIR)/glquake/view.o	\
+	$(BUILDDIR)/glquake/wad.o \
+	$(BUILDDIR)/glquake/world.o \
+	$(BUILDDIR)/glquake/cd_linux.o \
+	$(BUILDDIR)/glquake/sys_linux.o \
+	$(BUILDDIR)/glquake/snd_dma.o \
+	$(BUILDDIR)/glquake/snd_mem.o \
+	$(BUILDDIR)/glquake/snd_mix.o \
+	$(BUILDDIR)/glquake/snd_linux.o \
+	\
+	$(BUILDDIR)/glquake/math.o \
+	$(BUILDDIR)/glquake/worlda.o \
+	$(BUILDDIR)/glquake/snd_mixa.o \
+	$(BUILDDIR)/glquake/sys_dosa.o
+
+GLSVGA_OBJS=$(BUILDDIR)/glquake/gl_vidlinux.o
+
+GLX_OBJS=$(BUILDDIR)/glquake/gl_vidlinuxglx.o
+
+$(BUILDDIR)/bin/glquake : $(GLQUAKE_OBJS) $(GLSVGA_OBJS)
+	$(CC) $(CFLAGS) -o $@ $(GLQUAKE_OBJS) $(GLSVGA_OBJS) $(MESAGLLDFLAGS) $(SVGALDFLAGS) $(LDFLAGS)
+
+$(BUILDDIR)/bin/glquake.glx : $(GLQUAKE_OBJS) $(GLX_OBJS)
+	$(CC) $(CFLAGS) -o $@ $(GLQUAKE_OBJS) $(GLX_OBJS) $(GLLDFLAGS) $(LDFLAGS)
+
+$(BUILDDIR)/bin/glquake.3dfxgl : $(GLQUAKE_OBJS) $(GLSVGA_OBJS)
+	$(CC) $(CFLAGS) -o $@ $(GLQUAKE_OBJS) $(GLSVGA_OBJS) $(TDFXGLLDFLAGS) $(SVGALDFLAGS) $(LDFLAGS)
+
+$(BUILDDIR)/glquake/cl_demo.o :      $(MOUNT_DIR)/cl_demo.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glquake/cl_input.o :     $(MOUNT_DIR)/cl_input.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glquake/cl_main.o :      $(MOUNT_DIR)/cl_main.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glquake/cl_parse.o :     $(MOUNT_DIR)/cl_parse.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glquake/cl_tent.o :      $(MOUNT_DIR)/cl_tent.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glquake/chase.o :        $(MOUNT_DIR)/chase.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glquake/cmd.o :          $(MOUNT_DIR)/cmd.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glquake/common.o :       $(MOUNT_DIR)/common.c
+	$(DO_GL_DEBUG_CC)
+
+$(BUILDDIR)/glquake/console.o :      $(MOUNT_DIR)/console.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glquake/crc.o :          $(MOUNT_DIR)/crc.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glquake/cvar.o :         $(MOUNT_DIR)/cvar.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glquake/gl_draw.o :      $(MOUNT_DIR)/gl_draw.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glquake/gl_mesh.o :      $(MOUNT_DIR)/gl_mesh.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glquake/gl_model.o :     $(MOUNT_DIR)/gl_model.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glquake/gl_refrag.o :    $(MOUNT_DIR)/gl_refrag.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glquake/gl_rlight.o :    $(MOUNT_DIR)/gl_rlight.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glquake/gl_rmain.o :     $(MOUNT_DIR)/gl_rmain.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glquake/gl_rmisc.o :     $(MOUNT_DIR)/gl_rmisc.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glquake/gl_rsurf.o :     $(MOUNT_DIR)/gl_rsurf.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glquake/gl_screen.o :    $(MOUNT_DIR)/gl_screen.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glquake/gl_test.o :      $(MOUNT_DIR)/gl_test.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glquake/gl_vidlinux.o :  $(MOUNT_DIR)/gl_vidlinux.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glquake/gl_vidlinuxglx.o :  $(MOUNT_DIR)/gl_vidlinuxglx.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glquake/gl_warp.o :      $(MOUNT_DIR)/gl_warp.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glquake/host.o :         $(MOUNT_DIR)/host.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glquake/host_cmd.o :     $(MOUNT_DIR)/host_cmd.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glquake/keys.o :         $(MOUNT_DIR)/keys.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glquake/menu.o :         $(MOUNT_DIR)/menu.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glquake/mathlib.o :      $(MOUNT_DIR)/mathlib.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glquake/net_dgrm.o :     $(MOUNT_DIR)/net_dgrm.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glquake/net_loop.o :     $(MOUNT_DIR)/net_loop.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glquake/net_main.o :     $(MOUNT_DIR)/net_main.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glquake/net_vcr.o :      $(MOUNT_DIR)/net_vcr.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glquake/net_udp.o :      $(MOUNT_DIR)/net_udp.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glquake/net_bsd.o :      $(MOUNT_DIR)/net_bsd.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glquake/pr_cmds.o :      $(MOUNT_DIR)/pr_cmds.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glquake/pr_edict.o :     $(MOUNT_DIR)/pr_edict.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glquake/pr_exec.o :      $(MOUNT_DIR)/pr_exec.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glquake/r_part.o :       $(MOUNT_DIR)/r_part.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glquake/sbar.o :         $(MOUNT_DIR)/sbar.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glquake/sv_main.o :      $(MOUNT_DIR)/sv_main.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glquake/sv_phys.o :      $(MOUNT_DIR)/sv_phys.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glquake/sv_move.o :      $(MOUNT_DIR)/sv_move.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glquake/sv_user.o :      $(MOUNT_DIR)/sv_user.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glquake/zone.o	:        $(MOUNT_DIR)/zone.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glquake/view.o	:        $(MOUNT_DIR)/view.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glquake/wad.o :          $(MOUNT_DIR)/wad.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glquake/world.o :        $(MOUNT_DIR)/world.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glquake/cd_linux.o :     $(MOUNT_DIR)/cd_linux.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glquake/sys_linux.o :    $(MOUNT_DIR)/sys_linux.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glquake/snd_dma.o :      $(MOUNT_DIR)/snd_dma.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glquake/snd_mem.o :      $(MOUNT_DIR)/snd_mem.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glquake/snd_mix.o :      $(MOUNT_DIR)/snd_mix.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glquake/snd_linux.o :    $(MOUNT_DIR)/snd_linux.c
+	$(DO_GL_CC)
+
+$(BUILDDIR)/glquake/math.o :         $(MOUNT_DIR)/math.s
+	$(DO_GL_AS)
+
+$(BUILDDIR)/glquake/worlda.o :       $(MOUNT_DIR)/worlda.s
+	$(DO_GL_AS)
+
+$(BUILDDIR)/glquake/snd_mixa.o :     $(MOUNT_DIR)/snd_mixa.s
+	$(DO_GL_AS)
+
+$(BUILDDIR)/glquake/sys_dosa.o :     $(MOUNT_DIR)/sys_dosa.s
+	$(DO_GL_AS)
+
+#############################################################################
+# RPM
+#############################################################################
+
+# Make RPMs.  You need to be root to make this work
+RPMROOT=/usr/src/redhat
+RPM = rpm
+RPMFLAGS = -bb
+INSTALLDIR = /usr/local/games/quake
+TMPDIR = /var/tmp
+RPMDIR = $(TMPDIR)/quake-$(VERSION)
+BASERPMDIR = $(TMPDIR)/quake-$(BASEVERSION)
+
+rpm: rpm-quake rpm-quake-data rpm-hipnotic rpm-rogue
+
+rpm-quake: quake.spec \
+		$(BUILD_RELEASE_DIR)/bin/squake \
+		$(BUILD_RELEASE_DIR)/bin/quake.x11 \
+		$(BUILD_RELEASE_DIR)/bin/glquake \
+		$(BUILD_RELEASE_DIR)/bin/glquake.glx \
+		$(BUILD_RELEASE_DIR)/bin/glquake.3dfxgl
+	touch $(RPMROOT)/SOURCES/quake-$(VERSION).tar.gz
+	if [ ! -d RPMS ];then mkdir RPMS;fi
+	cp $(MOUNT_DIR)/quake.gif $(RPMROOT)/SOURCES/quake.gif
+
+	# basic binaries rpm
+	-mkdirhier $(RPMDIR)/$(INSTALLDIR)
+	cp $(MOUNT_DIR)/docs/README $(RPMDIR)/$(INSTALLDIR)/.
+	cp $(BUILD_RELEASE_DIR)/bin/squake $(RPMDIR)/$(INSTALLDIR)/squake
+	strip $(RPMDIR)/$(INSTALLDIR)/squake
+	cp $(BUILD_RELEASE_DIR)/bin/quake.x11 $(RPMDIR)/$(INSTALLDIR)/quake.x11
+	strip $(RPMDIR)/$(INSTALLDIR)/quake.x11
+	cp $(BUILD_RELEASE_DIR)/bin/glquake $(RPMDIR)/$(INSTALLDIR)/glquake
+	strip $(RPMDIR)/$(INSTALLDIR)/glquake
+	cp $(BUILD_RELEASE_DIR)/bin/glquake.glx $(RPMDIR)/$(INSTALLDIR)/glquake.glx
+	strip $(RPMDIR)/$(INSTALLDIR)/glquake.glx
+	cp $(BUILD_RELEASE_DIR)/bin/glquake.3dfxgl $(RPMDIR)/$(INSTALLDIR)/glquake.3dfxgl
+	strip $(RPMDIR)/$(INSTALLDIR)/glquake.3dfxgl
+	-mkdirhier $(RPMDIR)/usr/lib
+	cp $(TDFXGL_DIR)/release$(ARCH)$(GLIBC)/lib3dfxgl.so $(RPMDIR)/usr/lib/lib3dfxgl.so
+	cp $(MESA_DIR)/lib/libMesaGL.so.2.6 $(RPMDIR)/usr/lib/libMesaGL.so.2.6
+
+	cp quake.spec $(RPMROOT)/SPECS/.
+	cd $(RPMROOT)/SPECS; $(RPM) $(RPMFLAGS) quake.spec
+	rm -rf $(RPMDIR)
+	rm -f $(RPMROOT)/SOURCES/quake-$(VERSION).tar.gz
+
+	mv $(RPMROOT)/RPMS/$(ARCH)/quake-$(VERSION)-$(RPM_RELEASE).$(ARCH).rpm RPMS/.
+
+QUAKEDATADIR=$(TMPDIR)/quake-data-$(BASEVERSION)
+rpm-quake-data: quake-data.spec
+	# data rpm
+	touch $(RPMROOT)/SOURCES/quake-$(BASEVERSION)-data.tar.gz
+
+	-mkdirhier $(QUAKEDATADIR)/$(INSTALLDIR)/id1
+	cp $(MASTER_DIR)/id1/pak0.pak $(QUAKEDATADIR)/$(INSTALLDIR)/id1/.
+	cp $(MASTER_DIR)/id1/pak1.pak $(QUAKEDATADIR)/$(INSTALLDIR)/id1/.
+	cp $(MOUNT_DIR)/docs/README $(QUAKEDATADIR)/$(INSTALLDIR)/.
+	cp $(MOUNT_DIR)/data/comexp.txt $(QUAKEDATADIR)/$(INSTALLDIR)/.
+	cp $(MOUNT_DIR)/data/help.txt $(QUAKEDATADIR)/$(INSTALLDIR)/.
+	cp $(MOUNT_DIR)/data/licinfo.txt $(QUAKEDATADIR)/$(INSTALLDIR)/.
+	cp $(MOUNT_DIR)/data/manual.txt $(QUAKEDATADIR)/$(INSTALLDIR)/.
+	cp $(MOUNT_DIR)/data/readme.txt $(QUAKEDATADIR)/$(INSTALLDIR)/.
+	cp $(MOUNT_DIR)/data/rlicnse.txt $(QUAKEDATADIR)/$(INSTALLDIR)/.
+	cp $(MOUNT_DIR)/data/slicnse.txt $(QUAKEDATADIR)/$(INSTALLDIR)/.
+	cp $(MOUNT_DIR)/data/techinfo.txt $(QUAKEDATADIR)/$(INSTALLDIR)/.
+	cp quake-data.spec $(RPMROOT)/SPECS/.
+	cd $(RPMROOT)/SPECS; $(RPM) $(RPMFLAGS) quake-data.spec
+	rm -rf $(QUAKEDATADIR)
+	rm -f $(RPMROOT)/SOURCES/quake-$(BASEVERSION)-data.tar.gz
+
+	mv $(RPMROOT)/RPMS/$(NOARCH)/quake-data-$(BASEVERSION)-$(RPM_RELEASE).$(NOARCH).rpm RPMS/.
+
+RPMHIPNOTICDIR=$(TMPDIR)/quake-hipnotic-$(BASEVERSION)
+rpm-hipnotic: quake-hipnotic.spec
+	touch $(RPMROOT)/SOURCES/quake-hipnotic-$(BASEVERSION).tar.gz
+	if [ ! -d RPMS ];then mkdir RPMS;fi
+	cp $(MOUNT_DIR)/quake.gif $(RPMROOT)/SOURCES/quake.gif
+	-mkdirhier $(RPMHIPNOTICDIR)/$(INSTALLDIR)/hipnotic/docs
+	cp $(MASTER_DIR)/hipnotic/pak0.pak $(RPMHIPNOTICDIR)/$(INSTALLDIR)/hipnotic/.
+	cp $(MASTER_DIR)/hipnotic/config.cfg $(RPMHIPNOTICDIR)/$(INSTALLDIR)/hipnotic/.
+	cp $(MASTER_DIR)/hipnotic/docs/manual.doc $(RPMHIPNOTICDIR)/$(INSTALLDIR)/hipnotic/docs/.
+	cp $(MASTER_DIR)/hipnotic/docs/manual.htm $(RPMHIPNOTICDIR)/$(INSTALLDIR)/hipnotic/docs/.
+	cp $(MASTER_DIR)/hipnotic/docs/manual.txt $(RPMHIPNOTICDIR)/$(INSTALLDIR)/hipnotic/docs/.
+	cp $(MASTER_DIR)/hipnotic/docs/readme.doc $(RPMHIPNOTICDIR)/$(INSTALLDIR)/hipnotic/docs/.
+	cp $(MASTER_DIR)/hipnotic/docs/readme.htm $(RPMHIPNOTICDIR)/$(INSTALLDIR)/hipnotic/docs/.
+	cp $(MASTER_DIR)/hipnotic/docs/readme.txt $(RPMHIPNOTICDIR)/$(INSTALLDIR)/hipnotic/docs/.
+	cp quake-hipnotic.spec $(RPMROOT)/SPECS/.
+	cd $(RPMROOT)/SPECS; $(RPM) $(RPMFLAGS) quake-hipnotic.spec
+	rm -rf $(RPMHIPNOTICDIR)
+	rm -f $(RPMROOT)/SOURCES/quake-hipnotic-$(BASEVERSION).tar.gz
+
+	mv $(RPMROOT)/RPMS/$(NOARCH)/quake-hipnotic-$(BASEVERSION)-$(RPM_RELEASE).$(NOARCH).rpm RPMS/.
+
+RPMROGUEDIR=$(TMPDIR)/quake-rogue-$(BASEVERSION)
+rpm-rogue: quake-rogue.spec
+	touch $(RPMROOT)/SOURCES/quake-rogue-$(BASEVERSION).tar.gz
+	if [ ! -d RPMS ];then mkdir RPMS;fi
+	cp $(MOUNT_DIR)/quake.gif $(RPMROOT)/SOURCES/quake.gif
+	-mkdirhier $(RPMROGUEDIR)/$(INSTALLDIR)/rogue/docs
+	cp $(MASTER_DIR)/rogue/pak0.pak $(RPMROGUEDIR)/$(INSTALLDIR)/rogue/.
+	cp $(MASTER_DIR)/rogue/docs/manual.doc $(RPMROGUEDIR)/$(INSTALLDIR)/rogue/docs/.
+	cp $(MASTER_DIR)/rogue/docs/manual.htm $(RPMROGUEDIR)/$(INSTALLDIR)/rogue/docs/.
+	cp $(MASTER_DIR)/rogue/docs/manual.txt $(RPMROGUEDIR)/$(INSTALLDIR)/rogue/docs/.
+	cp $(MASTER_DIR)/rogue/docs/readme.doc $(RPMROGUEDIR)/$(INSTALLDIR)/rogue/docs/.
+	cp $(MASTER_DIR)/rogue/docs/readme.htm $(RPMROGUEDIR)/$(INSTALLDIR)/rogue/docs/.
+	cp $(MASTER_DIR)/rogue/docs/readme.txt $(RPMROGUEDIR)/$(INSTALLDIR)/rogue/docs/.
+	cp $(MASTER_DIR)/rogue/docs/ctf.doc $(RPMROGUEDIR)/$(INSTALLDIR)/rogue/docs/.
+	cp $(MASTER_DIR)/rogue/docs/ctf.htm $(RPMROGUEDIR)/$(INSTALLDIR)/rogue/docs/.
+	cp $(MASTER_DIR)/rogue/docs/ctf.txt $(RPMROGUEDIR)/$(INSTALLDIR)/rogue/docs/.
+	cp quake-rogue.spec $(RPMROOT)/SPECS/.
+	cd $(RPMROOT)/SPECS; $(RPM) $(RPMFLAGS) quake-rogue.spec
+	rm -rf $(RPMROGUEDIR)
+	rm -f $(RPMROOT)/SOURCES/quake-rogue-$(BASEVERSION).tar.gz
+
+	mv $(RPMROOT)/RPMS/$(NOARCH)/quake-rogue-$(BASEVERSION)-$(RPM_RELEASE).$(NOARCH).rpm RPMS/.
+
+quake.spec : $(MOUNT_DIR)/quake.spec.sh
+	sh $< $(VERSION) $(RPM_RELEASE) $(INSTALLDIR) > $@
+
+quake-data.spec : $(MOUNT_DIR)/quake-data.spec.sh
+	sh $< $(BASEVERSION) $(RPM_RELEASE) $(INSTALLDIR) > $@
+
+quake-hipnotic.spec : $(MOUNT_DIR)/quake-hipnotic.spec.sh
+	sh $< $(BASEVERSION) $(RPM_RELEASE) $(INSTALLDIR) > $@
+
+quake-rogue.spec : $(MOUNT_DIR)/quake-rogue.spec.sh
+	sh $< $(BASEVERSION) $(RPM_RELEASE) $(INSTALLDIR) > $@
+
+#############################################################################
+# MISC
+#############################################################################
+
+clean: clean-debug clean-release
+	rm -f squake.spec glquake.spec quake.x11.spec
+
+clean-debug:
+	$(MAKE) clean2 BUILDDIR=$(BUILD_DEBUG_DIR) CFLAGS="$(DEBUG_CFLAGS)"
+
+clean-release:
+	$(MAKE) clean2 BUILDDIR=$(BUILD_RELEASE_DIR) CFLAGS="$(DEBUG_CFLAGS)"
+
+clean2:
+	-rm -f $(SQUAKE_OBJS) $(X11_OBJS) $(GLQUAKE_OBJS) $(GLSVGA_OBJS) \
+		$(GLX_OBJS)
+
--- /dev/null
+++ b/WinQuake/README.Solaris
@@ -1,0 +1,98 @@
+Solaris 2 Quake / QuakeWorld
+----------------------------
+
+	This is an UNSUPPORTED version of Quake and QuakeWorld.  Don't
+	bother id software about it.  Bug reports will be ignored.
+	
+PORT DETAILS
+------------
+
+	There are a few major difference between this port and the
+	vanilla Quake/QuakeWorld available on the internet.  For
+	optimum performance, you should copy everything to a directory
+	on your local system before starting play so that you are
+	not mounting files from a remote filesystem.
+
+	In order to use this program, you need the files pak0.pak 
+	and pak1.pak in the id1 directory found on a registered copy of
+	Quake.  You can ftp them to your Solaris host from a Windows95
+	machine for example.  The files must be in an id1 subdirectory from
+	the directory you install Quake/QuakeWorld, and all file names must
+	be lowercase.  Add on packages such as ThreeWave CTF work fine as
+	well, just place such addon packages in their own directory as you
+	would on a Windows95 installation.  But again, make sure all files
+	are lowercase.
+			
+	COMMAND LINE FLAGS:
+	
+	+pixel_multiply 
+	
+		You can magnify the screen by using this flag:
+		
+		Ex: % quake +pixel_multiply 2
+		
+		You can also use this command (without the dash)
+		from the Quake console.  pixel_multiply is a Quake
+		cvar and is saved from session to session in the
+		config.cfg file.
+
+	-winsize <width> <height>
+
+		Set the size of the window when you start
+
+	-count_frames
+
+		See how many frames per second you're getting
+
+	GAME SETTINGS
+
+	mouse binding
+
+		You can bind and unbind the mouse to the Quake window
+		by using the Use Mouse selection in the Options menu,
+		or with the "_windowed_mouse" command in the console,
+		ex "_windowed_mouse 1" Now, moving the mouse will move
+		your player.  Use "_windowed_mouse 0" to unbind.  You
+		can bind or alias this to a key.  
+
+	Example command:
+
+		% quake.xil +pixel_multiply 2 -winsize 400 300
+
+WHAT IS "QUAKEWORLD" AND HOW DO I USE IT?
+-----------------------------------------
+
+	In a nutshell, QuakeWorld is an extension of Quake that is
+	much more user friendly.  It allows the user to dynamically
+	download changes from the server, such as new maps and new
+	weapons while inside the Quake client.  It is not directly
+	compatible with Quake (ie, you can't connect to a Quake server
+	from a QuakeWorld client) but in general it is superior to
+	Quake.  QuakeWorld also offers much smoother play over the 
+	Internet by using client prediction.  For more information,
+	check out http://www.quakeworld.net/.
+
+	In order to use it, you must make a copy of the "qw"
+	directory.  Any new stuff that is downloaded from a QuakeWorld
+	server will be stored in this directory.  All regular Quake
+	flags apply so you can use the same command line as before.
+
+	Example command:
+
+		% qwcl.xil +pixel_multiply 2 -winsize 400 300
+
+WHERE CAN I FIND OUT ABOUT...
+-----------------------------
+
+	If you've got questions about Quake, rest assured that there
+	are answers out there.  Try checking out these web sites:
+
+		http://www.planetquake.com/
+		http://www.stomped.com/
+		http://www.quakeworld.net/
+	
+	If all else fails use a search engine.
+
+Happy fragging,
+the Quake/Solaris team
+	
--- /dev/null
+++ b/WinQuake/WinQuake.dsp
@@ -1,0 +1,2240 @@
+# Microsoft Developer Studio Project File - Name="winquake" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+
+CFG=winquake - Win32 Release
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "WinQuake.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "WinQuake.mak" CFG="winquake - Win32 Release"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "winquake - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "winquake - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE "winquake - Win32 GL Debug" (based on "Win32 (x86) Application")
+!MESSAGE "winquake - Win32 GL Release" (based on "Win32 (x86) Application")
+!MESSAGE 
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "winquake - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir ".\Release"
+# PROP BASE Intermediate_Dir ".\Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir ".\Release"
+# PROP Intermediate_Dir ".\Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c
+# ADD CPP /nologo /G5 /GX /Ox /Ot /Ow /I ".\scitech\include" /I ".\dxsdk\sdk\inc" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FR /YX /FD /c
+# SUBTRACT CPP /Oa /Og
+# ADD BASE MTL /nologo /D "NDEBUG" /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
+# ADD LINK32 .\dxsdk\sdk\lib\dxguid.lib .\scitech\lib\win32\vc\mgllt.lib winmm.lib wsock32.lib opengl32.lib glu32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /profile /machine:I386
+# SUBTRACT LINK32 /map /debug
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir ".\Debug"
+# PROP BASE Intermediate_Dir ".\Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir ".\Debug"
+# PROP Intermediate_Dir ".\Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c
+# ADD CPP /nologo /G5 /ML /GX /ZI /Od /I ".\scitech\include" /I ".\dxsdk\sdk\inc" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /YX /FD /c
+# ADD BASE MTL /nologo /D "_DEBUG" /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386
+# ADD LINK32 .\dxsdk\sdk\lib\dxguid.lib .\scitech\lib\win32\vc\mgllt.lib winmm.lib wsock32.lib opengl32.lib glu32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386
+# SUBTRACT LINK32 /nodefaultlib
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir ".\winquake"
+# PROP BASE Intermediate_Dir ".\winquake"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir ".\debug_gl"
+# PROP Intermediate_Dir ".\debug_gl"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /G5 /ML /GX /Zi /Od /I ".\scitech\include" /I ".\dxsdk\sdk\inc" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c
+# ADD CPP /nologo /G5 /ML /GX /ZI /Od /I ".\dxsdk\sdk\inc" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "GLQUAKE" /FR /YX /FD /c
+# ADD BASE MTL /nologo /D "_DEBUG" /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 winmm.lib wsock32.lib opengl32.lib glu32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib .\scitech\lib\win32\vc\mgllt.lib /nologo /subsystem:windows /debug /machine:I386
+# SUBTRACT BASE LINK32 /nodefaultlib
+# ADD LINK32 .\dxsdk\sdk\lib\dxguid.lib comctl32.lib winmm.lib wsock32.lib opengl32.lib glu32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /out:".\debug_gl\glquake.exe"
+# SUBTRACT LINK32 /nodefaultlib
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir ".\winquak0"
+# PROP BASE Intermediate_Dir ".\winquak0"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir ".\release_gl"
+# PROP Intermediate_Dir ".\release_gl"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /G5 /GX /Ox /Ot /Ow /I ".\scitech\include" /I ".\dxsdk\sdk\inc" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c
+# SUBTRACT BASE CPP /Oa /Og
+# ADD CPP /nologo /G5 /GX /Ot /Ow /I ".\dxsdk\sdk\inc" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "GLQUAKE" /FR /YX /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 winmm.lib wsock32.lib opengl32.lib glu32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib .\scitech\lib\win32\vc\mgllt.lib /nologo /subsystem:windows /profile /machine:I386
+# SUBTRACT BASE LINK32 /map /debug
+# ADD LINK32 .\dxsdk\sdk\lib\dxguid.lib comctl32.lib winmm.lib wsock32.lib opengl32.lib glu32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /profile /machine:I386 /out:".\release_gl\glquake.exe"
+# SUBTRACT LINK32 /map /debug
+
+!ENDIF 
+
+# Begin Target
+
+# Name "winquake - Win32 Release"
+# Name "winquake - Win32 Debug"
+# Name "winquake - Win32 GL Debug"
+# Name "winquake - Win32 GL Release"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;hpj;bat;for;f90"
+# Begin Source File
+
+SOURCE=.\cd_win.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\chase.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\cl_demo.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\cl_input.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\cl_main.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\cl_parse.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\cl_tent.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\cmd.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\common.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\conproc.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\console.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\crc.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\cvar.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\d_draw.s
+
+!IF  "$(CFG)" == "winquake - Win32 Release"
+
+# Begin Custom Build - mycoolbuild
+OutDir=.\Release
+InputPath=.\d_draw.s
+InputName=d_draw
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) 
+	gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp >                                                                                                                                                                                                    $(OUTDIR)\$(InputName).asm 
+	ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi                                                                                                                                                                                                    $(OUTDIR)\$(InputName).asm 
+	del $(OUTDIR)\$(InputName).spp 
+	
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 Debug"
+
+# Begin Custom Build - mycoolbuild
+OutDir=.\Debug
+InputPath=.\d_draw.s
+InputName=d_draw
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) 
+	gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp >                                                                                                                                                                                                    $(OUTDIR)\$(InputName).asm 
+	ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi                                                                                                                                                                                                    $(OUTDIR)\$(InputName).asm 
+	del $(OUTDIR)\$(InputName).spp 
+	
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Release"
+
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\d_draw16.s
+
+!IF  "$(CFG)" == "winquake - Win32 Release"
+
+# Begin Custom Build - mycoolbuild
+OutDir=.\Release
+InputPath=.\d_draw16.s
+InputName=d_draw16
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) 
+	gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp >                                                                                                                                                                                                    $(OUTDIR)\$(InputName).asm 
+	ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi                                                                                                                                                                                                    $(OUTDIR)\$(InputName).asm 
+	del $(OUTDIR)\$(InputName).spp 
+	
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 Debug"
+
+# Begin Custom Build - mycoolbuild
+OutDir=.\Debug
+InputPath=.\d_draw16.s
+InputName=d_draw16
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) 
+	gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp >                                                                                                                                                                                                    $(OUTDIR)\$(InputName).asm 
+	ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi                                                                                                                                                                                                    $(OUTDIR)\$(InputName).asm 
+	del $(OUTDIR)\$(InputName).spp 
+	
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Release"
+
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\d_edge.c
+
+!IF  "$(CFG)" == "winquake - Win32 Release"
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 Debug"
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Release"
+
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\d_fill.c
+
+!IF  "$(CFG)" == "winquake - Win32 Release"
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 Debug"
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Release"
+
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\d_init.c
+
+!IF  "$(CFG)" == "winquake - Win32 Release"
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 Debug"
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Release"
+
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\d_modech.c
+
+!IF  "$(CFG)" == "winquake - Win32 Release"
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 Debug"
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Release"
+
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\d_part.c
+
+!IF  "$(CFG)" == "winquake - Win32 Release"
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 Debug"
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Release"
+
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\d_parta.s
+
+!IF  "$(CFG)" == "winquake - Win32 Release"
+
+# Begin Custom Build - mycoolbuild
+OutDir=.\Release
+InputPath=.\d_parta.s
+InputName=d_parta
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) 
+	gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp >                                                                                                                                                                                                    $(OUTDIR)\$(InputName).asm 
+	ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi                                                                                                                                                                                                    $(OUTDIR)\$(InputName).asm 
+	del $(OUTDIR)\$(InputName).spp 
+	
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 Debug"
+
+# Begin Custom Build - mycoolbuild
+OutDir=.\Debug
+InputPath=.\d_parta.s
+InputName=d_parta
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) 
+	gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp >                                                                                                                                                                                                    $(OUTDIR)\$(InputName).asm 
+	ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi                                                                                                                                                                                                    $(OUTDIR)\$(InputName).asm 
+	del $(OUTDIR)\$(InputName).spp 
+	
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Release"
+
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\d_polysa.s
+
+!IF  "$(CFG)" == "winquake - Win32 Release"
+
+# Begin Custom Build - mycoolbuild
+OutDir=.\Release
+InputPath=.\d_polysa.s
+InputName=d_polysa
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) 
+	gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp >                                                                                                                                                                                                    $(OUTDIR)\$(InputName).asm 
+	ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi                                                                                                                                                                                                    $(OUTDIR)\$(InputName).asm 
+	del $(OUTDIR)\$(InputName).spp 
+	
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 Debug"
+
+# Begin Custom Build - mycoolbuild
+OutDir=.\Debug
+InputPath=.\d_polysa.s
+InputName=d_polysa
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) 
+	gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp >                                                                                                                                                                                                    $(OUTDIR)\$(InputName).asm 
+	ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi                                                                                                                                                                                                    $(OUTDIR)\$(InputName).asm 
+	del $(OUTDIR)\$(InputName).spp 
+	
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Release"
+
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\d_polyse.c
+
+!IF  "$(CFG)" == "winquake - Win32 Release"
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 Debug"
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Release"
+
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\d_scan.c
+
+!IF  "$(CFG)" == "winquake - Win32 Release"
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 Debug"
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Release"
+
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\d_scana.s
+
+!IF  "$(CFG)" == "winquake - Win32 Release"
+
+# Begin Custom Build - mycoolbuild
+OutDir=.\Release
+InputPath=.\d_scana.s
+InputName=d_scana
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) 
+	gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp >                                                                                                                                                                                                    $(OUTDIR)\$(InputName).asm 
+	ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi                                                                                                                                                                                                    $(OUTDIR)\$(InputName).asm 
+	del $(OUTDIR)\$(InputName).spp 
+	
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 Debug"
+
+# Begin Custom Build - mycoolbuild
+OutDir=.\Debug
+InputPath=.\d_scana.s
+InputName=d_scana
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) 
+	gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp >                                                                                                                                                                                                    $(OUTDIR)\$(InputName).asm 
+	ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi                                                                                                                                                                                                    $(OUTDIR)\$(InputName).asm 
+	del $(OUTDIR)\$(InputName).spp 
+	
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Release"
+
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\d_sky.c
+
+!IF  "$(CFG)" == "winquake - Win32 Release"
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 Debug"
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Release"
+
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\d_spr8.s
+
+!IF  "$(CFG)" == "winquake - Win32 Release"
+
+# Begin Custom Build - mycoolbuild
+OutDir=.\Release
+InputPath=.\d_spr8.s
+InputName=d_spr8
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) 
+	gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp >                                                                                                                                                                                                    $(OUTDIR)\$(InputName).asm 
+	ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi                                                                                                                                                                                                    $(OUTDIR)\$(InputName).asm 
+	del $(OUTDIR)\$(InputName).spp 
+	
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 Debug"
+
+# Begin Custom Build - mycoolbuild
+OutDir=.\Debug
+InputPath=.\d_spr8.s
+InputName=d_spr8
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) 
+	gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp >                                                                                                                                                                                                    $(OUTDIR)\$(InputName).asm 
+	ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi                                                                                                                                                                                                    $(OUTDIR)\$(InputName).asm 
+	del $(OUTDIR)\$(InputName).spp 
+	
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Release"
+
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\d_sprite.c
+
+!IF  "$(CFG)" == "winquake - Win32 Release"
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 Debug"
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Release"
+
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\d_surf.c
+
+!IF  "$(CFG)" == "winquake - Win32 Release"
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 Debug"
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Release"
+
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\d_vars.c
+
+!IF  "$(CFG)" == "winquake - Win32 Release"
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 Debug"
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Release"
+
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\d_varsa.s
+
+!IF  "$(CFG)" == "winquake - Win32 Release"
+
+# Begin Custom Build - mycoolbuild
+OutDir=.\Release
+InputPath=.\d_varsa.s
+InputName=d_varsa
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) 
+	gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp >                                                                                                                                                                                                    $(OUTDIR)\$(InputName).asm 
+	ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi                                                                                                                                                                                                    $(OUTDIR)\$(InputName).asm 
+	del $(OUTDIR)\$(InputName).spp 
+	
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 Debug"
+
+# Begin Custom Build - mycoolbuild
+OutDir=.\Debug
+InputPath=.\d_varsa.s
+InputName=d_varsa
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) 
+	gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp >                                                                                                                                                                                                    $(OUTDIR)\$(InputName).asm 
+	ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi                                                                                                                                                                                                    $(OUTDIR)\$(InputName).asm 
+	del $(OUTDIR)\$(InputName).spp 
+	
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Release"
+
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\d_zpoint.c
+
+!IF  "$(CFG)" == "winquake - Win32 Release"
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 Debug"
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Release"
+
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\draw.c
+
+!IF  "$(CFG)" == "winquake - Win32 Release"
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 Debug"
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Release"
+
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\gl_draw.c
+
+!IF  "$(CFG)" == "winquake - Win32 Release"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Debug"
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Release"
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\gl_mesh.c
+
+!IF  "$(CFG)" == "winquake - Win32 Release"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Debug"
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Release"
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\gl_model.c
+
+!IF  "$(CFG)" == "winquake - Win32 Release"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Debug"
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Release"
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\gl_refrag.c
+
+!IF  "$(CFG)" == "winquake - Win32 Release"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Debug"
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Release"
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\gl_rlight.c
+
+!IF  "$(CFG)" == "winquake - Win32 Release"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Debug"
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Release"
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\gl_rmain.c
+
+!IF  "$(CFG)" == "winquake - Win32 Release"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Debug"
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Release"
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\gl_rmisc.c
+
+!IF  "$(CFG)" == "winquake - Win32 Release"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Debug"
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Release"
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\gl_rsurf.c
+
+!IF  "$(CFG)" == "winquake - Win32 Release"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Debug"
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Release"
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\gl_screen.c
+
+!IF  "$(CFG)" == "winquake - Win32 Release"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Debug"
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Release"
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\gl_test.c
+
+!IF  "$(CFG)" == "winquake - Win32 Release"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Debug"
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Release"
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\gl_vidnt.c
+
+!IF  "$(CFG)" == "winquake - Win32 Release"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Debug"
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Release"
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\gl_warp.c
+
+!IF  "$(CFG)" == "winquake - Win32 Release"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Debug"
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Release"
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\host.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\host_cmd.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\in_win.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\keys.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\math.s
+
+!IF  "$(CFG)" == "winquake - Win32 Release"
+
+# Begin Custom Build - mycoolbuild
+OutDir=.\Release
+InputPath=.\math.s
+InputName=math
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) 
+	gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp >                                                                                                                                                                                                    $(OUTDIR)\$(InputName).asm 
+	ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi                                                                                                                                                                                                    $(OUTDIR)\$(InputName).asm 
+	del $(OUTDIR)\$(InputName).spp 
+	
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 Debug"
+
+# Begin Custom Build - mycoolbuild
+OutDir=.\Debug
+InputPath=.\math.s
+InputName=math
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) 
+	gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp >                                                                                                                                                                                                    $(OUTDIR)\$(InputName).asm 
+	ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi                                                                                                                                                                                                    $(OUTDIR)\$(InputName).asm 
+	del $(OUTDIR)\$(InputName).spp 
+	
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Debug"
+
+# Begin Custom Build - mycoolbuild
+OutDir=.\debug_gl
+InputPath=.\math.s
+InputName=math
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	cl /EP /DGLQUAKE > $(OUTDIR)\$(InputName).spp $(InputPath) 
+	gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp >                                                                                                                                                                                                    $(OUTDIR)\$(InputName).asm 
+	ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi                                                                                                                                                                                                    $(OUTDIR)\$(InputName).asm 
+	del $(OUTDIR)\$(InputName).spp 
+	
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Release"
+
+# Begin Custom Build - mycoolbuild
+OutDir=.\release_gl
+InputPath=.\math.s
+InputName=math
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) 
+	gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp >                                                                                                                                                                                                    $(OUTDIR)\$(InputName).asm 
+	ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi                                                                                                                                                                                                    $(OUTDIR)\$(InputName).asm 
+	del $(OUTDIR)\$(InputName).spp 
+	
+# End Custom Build
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\mathlib.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\menu.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\model.c
+
+!IF  "$(CFG)" == "winquake - Win32 Release"
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 Debug"
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Release"
+
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\net_dgrm.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\net_loop.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\net_main.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\net_vcr.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\net_win.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\net_wins.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\net_wipx.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\pr_cmds.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\pr_edict.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\pr_exec.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\r_aclip.c
+
+!IF  "$(CFG)" == "winquake - Win32 Release"
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 Debug"
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Release"
+
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\r_aclipa.s
+
+!IF  "$(CFG)" == "winquake - Win32 Release"
+
+# Begin Custom Build - mycoolbuild
+OutDir=.\Release
+InputPath=.\r_aclipa.s
+InputName=r_aclipa
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) 
+	gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp >                                                                                                                                                                                                    $(OUTDIR)\$(InputName).asm 
+	ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi                                                                                                                                                                                                    $(OUTDIR)\$(InputName).asm 
+	del $(OUTDIR)\$(InputName).spp 
+	
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 Debug"
+
+# Begin Custom Build - mycoolbuild
+OutDir=.\Debug
+InputPath=.\r_aclipa.s
+InputName=r_aclipa
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) 
+	gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp >                                                                                                                                                                                                    $(OUTDIR)\$(InputName).asm 
+	ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi                                                                                                                                                                                                    $(OUTDIR)\$(InputName).asm 
+	del $(OUTDIR)\$(InputName).spp 
+	
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Release"
+
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\r_alias.c
+
+!IF  "$(CFG)" == "winquake - Win32 Release"
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 Debug"
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Release"
+
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\r_aliasa.s
+
+!IF  "$(CFG)" == "winquake - Win32 Release"
+
+# Begin Custom Build - mycoolbuild
+OutDir=.\Release
+InputPath=.\r_aliasa.s
+InputName=r_aliasa
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) 
+	gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp >                                                                                                                                                                                                    $(OUTDIR)\$(InputName).asm 
+	ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi                                                                                                                                                                                                    $(OUTDIR)\$(InputName).asm 
+	del $(OUTDIR)\$(InputName).spp 
+	
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 Debug"
+
+# Begin Custom Build - mycoolbuild
+OutDir=.\Debug
+InputPath=.\r_aliasa.s
+InputName=r_aliasa
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) 
+	gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp >                                                                                                                                                                                                    $(OUTDIR)\$(InputName).asm 
+	ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi                                                                                                                                                                                                    $(OUTDIR)\$(InputName).asm 
+	del $(OUTDIR)\$(InputName).spp 
+	
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Release"
+
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\r_bsp.c
+
+!IF  "$(CFG)" == "winquake - Win32 Release"
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 Debug"
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Release"
+
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\r_draw.c
+
+!IF  "$(CFG)" == "winquake - Win32 Release"
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 Debug"
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Release"
+
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\r_drawa.s
+
+!IF  "$(CFG)" == "winquake - Win32 Release"
+
+# Begin Custom Build - mycoolbuild
+OutDir=.\Release
+InputPath=.\r_drawa.s
+InputName=r_drawa
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) 
+	gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp >                                                                                                                                                                                                    $(OUTDIR)\$(InputName).asm 
+	ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi                                                                                                                                                                                                    $(OUTDIR)\$(InputName).asm 
+	del $(OUTDIR)\$(InputName).spp 
+	
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 Debug"
+
+# Begin Custom Build - mycoolbuild
+OutDir=.\Debug
+InputPath=.\r_drawa.s
+InputName=r_drawa
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) 
+	gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp >                                                                                                                                                                                                    $(OUTDIR)\$(InputName).asm 
+	ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi                                                                                                                                                                                                    $(OUTDIR)\$(InputName).asm 
+	del $(OUTDIR)\$(InputName).spp 
+	
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Release"
+
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\r_edge.c
+
+!IF  "$(CFG)" == "winquake - Win32 Release"
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 Debug"
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Release"
+
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\r_edgea.s
+
+!IF  "$(CFG)" == "winquake - Win32 Release"
+
+# Begin Custom Build - mycoolbuild
+OutDir=.\Release
+InputPath=.\r_edgea.s
+InputName=r_edgea
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) 
+	gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp >                                                                                                                                                                                                    $(OUTDIR)\$(InputName).asm 
+	ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi                                                                                                                                                                                                    $(OUTDIR)\$(InputName).asm 
+	del $(OUTDIR)\$(InputName).spp 
+	
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 Debug"
+
+# Begin Custom Build - mycoolbuild
+OutDir=.\Debug
+InputPath=.\r_edgea.s
+InputName=r_edgea
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) 
+	gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp >                                                                                                                                                                                                    $(OUTDIR)\$(InputName).asm 
+	ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi                                                                                                                                                                                                    $(OUTDIR)\$(InputName).asm 
+	del $(OUTDIR)\$(InputName).spp 
+	
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Release"
+
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\r_efrag.c
+
+!IF  "$(CFG)" == "winquake - Win32 Release"
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 Debug"
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Release"
+
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\r_light.c
+
+!IF  "$(CFG)" == "winquake - Win32 Release"
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 Debug"
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Release"
+
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\r_main.c
+
+!IF  "$(CFG)" == "winquake - Win32 Release"
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 Debug"
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Release"
+
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\r_misc.c
+
+!IF  "$(CFG)" == "winquake - Win32 Release"
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 Debug"
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Release"
+
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\r_part.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\r_sky.c
+
+!IF  "$(CFG)" == "winquake - Win32 Release"
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 Debug"
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Release"
+
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\r_sprite.c
+
+!IF  "$(CFG)" == "winquake - Win32 Release"
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 Debug"
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Release"
+
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\r_surf.c
+
+!IF  "$(CFG)" == "winquake - Win32 Release"
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 Debug"
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Release"
+
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\r_vars.c
+
+!IF  "$(CFG)" == "winquake - Win32 Release"
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 Debug"
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Release"
+
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\r_varsa.s
+
+!IF  "$(CFG)" == "winquake - Win32 Release"
+
+# Begin Custom Build - mycoolbuild
+OutDir=.\Release
+InputPath=.\r_varsa.s
+InputName=r_varsa
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) 
+	gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp >                                                                                                                                                                                                    $(OUTDIR)\$(InputName).asm 
+	ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi                                                                                                                                                                                                    $(OUTDIR)\$(InputName).asm 
+	del $(OUTDIR)\$(InputName).spp 
+	
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 Debug"
+
+# Begin Custom Build - mycoolbuild
+OutDir=.\Debug
+InputPath=.\r_varsa.s
+InputName=r_varsa
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) 
+	gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp >                                                                                                                                                                                                    $(OUTDIR)\$(InputName).asm 
+	ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi                                                                                                                                                                                                    $(OUTDIR)\$(InputName).asm 
+	del $(OUTDIR)\$(InputName).spp 
+	
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Release"
+
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\sbar.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\screen.c
+
+!IF  "$(CFG)" == "winquake - Win32 Release"
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 Debug"
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Release"
+
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\snd_dma.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\snd_mem.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\snd_mix.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\snd_mixa.s
+
+!IF  "$(CFG)" == "winquake - Win32 Release"
+
+# Begin Custom Build - mycoolbuild
+OutDir=.\Release
+InputPath=.\snd_mixa.s
+InputName=snd_mixa
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) 
+	gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp >                                                                                                                                                                                                    $(OUTDIR)\$(InputName).asm 
+	ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi                                                                                                                                                                                                    $(OUTDIR)\$(InputName).asm 
+	del $(OUTDIR)\$(InputName).spp 
+	
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 Debug"
+
+# Begin Custom Build - mycoolbuild
+OutDir=.\Debug
+InputPath=.\snd_mixa.s
+InputName=snd_mixa
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) 
+	gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp >                                                                                                                                                                                                    $(OUTDIR)\$(InputName).asm 
+	ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi                                                                                                                                                                                                    $(OUTDIR)\$(InputName).asm 
+	del $(OUTDIR)\$(InputName).spp 
+	
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Debug"
+
+# Begin Custom Build - mycoolbuild
+OutDir=.\debug_gl
+InputPath=.\snd_mixa.s
+InputName=snd_mixa
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	cl /EP /DGLQUAKE > $(OUTDIR)\$(InputName).spp $(InputPath) 
+	gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp >                                                                                                                                                                                                    $(OUTDIR)\$(InputName).asm 
+	ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi                                                                                                                                                                                                    $(OUTDIR)\$(InputName).asm 
+	del $(OUTDIR)\$(InputName).spp 
+	
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Release"
+
+# Begin Custom Build - mycoolbuild
+OutDir=.\release_gl
+InputPath=.\snd_mixa.s
+InputName=snd_mixa
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	cl /EP /DGLQUAKE > $(OUTDIR)\$(InputName).spp $(InputPath) 
+	gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp >                                                                                                                                                                                                    $(OUTDIR)\$(InputName).asm 
+	ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi                                                                                                                                                                                                    $(OUTDIR)\$(InputName).asm 
+	del $(OUTDIR)\$(InputName).spp 
+	
+# End Custom Build
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\snd_win.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\surf16.s
+
+!IF  "$(CFG)" == "winquake - Win32 Release"
+
+# Begin Custom Build - mycoolbuild
+OutDir=.\Release
+InputPath=.\surf16.s
+InputName=surf16
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) 
+	gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp >                                                                                                                                                                                                    $(OUTDIR)\$(InputName).asm 
+	ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi                                                                                                                                                                                                    $(OUTDIR)\$(InputName).asm 
+	del $(OUTDIR)\$(InputName).spp 
+	
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 Debug"
+
+# Begin Custom Build - mycoolbuild
+OutDir=.\Debug
+InputPath=.\surf16.s
+InputName=surf16
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) 
+	gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp >                                                                                                                                                                                                    $(OUTDIR)\$(InputName).asm 
+	ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi                                                                                                                                                                                                    $(OUTDIR)\$(InputName).asm 
+	del $(OUTDIR)\$(InputName).spp 
+	
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Release"
+
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\surf8.s
+
+!IF  "$(CFG)" == "winquake - Win32 Release"
+
+# Begin Custom Build - mycoolbuild
+OutDir=.\Release
+InputPath=.\surf8.s
+InputName=surf8
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) 
+	gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp >                                                                                                                                                                                                    $(OUTDIR)\$(InputName).asm 
+	ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi                                                                                                                                                                                                    $(OUTDIR)\$(InputName).asm 
+	del $(OUTDIR)\$(InputName).spp 
+	
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 Debug"
+
+# Begin Custom Build - mycoolbuild
+OutDir=.\Debug
+InputPath=.\surf8.s
+InputName=surf8
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) 
+	gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp >                                                                                                                                                                                                    $(OUTDIR)\$(InputName).asm 
+	ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi                                                                                                                                                                                                    $(OUTDIR)\$(InputName).asm 
+	del $(OUTDIR)\$(InputName).spp 
+	
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Release"
+
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\sv_main.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\sv_move.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\sv_phys.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\sv_user.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\sys_win.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\sys_wina.s
+
+!IF  "$(CFG)" == "winquake - Win32 Release"
+
+# Begin Custom Build - mycoolbuild
+OutDir=.\Release
+InputPath=.\sys_wina.s
+InputName=sys_wina
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) 
+	gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp >                                                                                                                                                                                                    $(OUTDIR)\$(InputName).asm 
+	ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi                                                                                                                                                                                                    $(OUTDIR)\$(InputName).asm 
+	del $(OUTDIR)\$(InputName).spp 
+	
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 Debug"
+
+# Begin Custom Build - mycoolbuild
+OutDir=.\Debug
+InputPath=.\sys_wina.s
+InputName=sys_wina
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) 
+	gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp >                                                                                                                                                                                                    $(OUTDIR)\$(InputName).asm 
+	ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi                                                                                                                                                                                                    $(OUTDIR)\$(InputName).asm 
+	del $(OUTDIR)\$(InputName).spp 
+	
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Debug"
+
+# Begin Custom Build - mycoolbuild
+OutDir=.\debug_gl
+InputPath=.\sys_wina.s
+InputName=sys_wina
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	cl /EP /DGLQUAKE > $(OUTDIR)\$(InputName).spp $(InputPath) 
+	gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp >                                                                                                                                                                                                    $(OUTDIR)\$(InputName).asm 
+	ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi                                                                                                                                                                                                    $(OUTDIR)\$(InputName).asm 
+	del $(OUTDIR)\$(InputName).spp 
+	
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Release"
+
+# Begin Custom Build - mycoolbuild
+OutDir=.\release_gl
+InputPath=.\sys_wina.s
+InputName=sys_wina
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	cl /EP /DGLQUAKE > $(OUTDIR)\$(InputName).spp $(InputPath) 
+	gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp >                                                                                                                                                                                                    $(OUTDIR)\$(InputName).asm 
+	ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi                                                                                                                                                                                                    $(OUTDIR)\$(InputName).asm 
+	del $(OUTDIR)\$(InputName).spp 
+	
+# End Custom Build
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\vid_win.c
+
+!IF  "$(CFG)" == "winquake - Win32 Release"
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 Debug"
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Release"
+
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\view.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\wad.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\winquake.rc
+# End Source File
+# Begin Source File
+
+SOURCE=.\world.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\worlda.s
+
+!IF  "$(CFG)" == "winquake - Win32 Release"
+
+# Begin Custom Build - mycoolbuild
+OutDir=.\Release
+InputPath=.\worlda.s
+InputName=worlda
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) 
+	gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp >                                                                                                                                                                                                    $(OUTDIR)\$(InputName).asm 
+	ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi                                                                                                                                                                                                    $(OUTDIR)\$(InputName).asm 
+	del $(OUTDIR)\$(InputName).spp 
+	
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 Debug"
+
+# Begin Custom Build - mycoolbuild
+OutDir=.\Debug
+InputPath=.\worlda.s
+InputName=worlda
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) 
+	gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp >                                                                                                                                                                                                    $(OUTDIR)\$(InputName).asm 
+	ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi                                                                                                                                                                                                    $(OUTDIR)\$(InputName).asm 
+	del $(OUTDIR)\$(InputName).spp 
+	
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Debug"
+
+# Begin Custom Build - mycoolbuild
+OutDir=.\debug_gl
+InputPath=.\worlda.s
+InputName=worlda
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	cl /EP /DGLQUAKE > $(OUTDIR)\$(InputName).spp $(InputPath) 
+	gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp >                                                                                                                                                                                                    $(OUTDIR)\$(InputName).asm 
+	ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi                                                                                                                                                                                                    $(OUTDIR)\$(InputName).asm 
+	del $(OUTDIR)\$(InputName).spp 
+	
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "winquake - Win32 GL Release"
+
+# Begin Custom Build - mycoolbuild
+OutDir=.\release_gl
+InputPath=.\worlda.s
+InputName=worlda
+
+"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	cl /EP /DGLQUAKE > $(OUTDIR)\$(InputName).spp $(InputPath) 
+	gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp >                                                                                                                                                                                                    $(OUTDIR)\$(InputName).asm 
+	ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi                                                                                                                                                                                                    $(OUTDIR)\$(InputName).asm 
+	del $(OUTDIR)\$(InputName).spp 
+	
+# End Custom Build
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\zone.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd"
+# Begin Source File
+
+SOURCE=.\anorm_dots.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\anorms.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\bspfile.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\cdaudio.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\client.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\cmd.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\common.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\conproc.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\console.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\crc.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\cvar.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\d_iface.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\dosisms.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\draw.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\gl_model.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\gl_warp_sin.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\glquake.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\input.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\keys.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\mathlib.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\menu.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\model.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\modelgen.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\net.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\net_dgrm.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\net_loop.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\net_ser.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\net_vcr.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\net_wins.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\net_wipx.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\pr_comp.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\progdefs.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\progs.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\protocol.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\quakedef.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\r_local.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\r_shared.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\render.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\sbar.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\screen.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\server.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\sound.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\spritegn.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\sys.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\vid.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\view.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\wad.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\winquake.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\world.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\zone.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe"
+# Begin Source File
+
+SOURCE=.\qe3.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\quake.ico
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=.\progdefs.q1
+# End Source File
+# Begin Source File
+
+SOURCE=.\progdefs.q2
+# End Source File
+# End Target
+# End Project
--- /dev/null
+++ b/WinQuake/WinQuake.dsw
@@ -1,0 +1,44 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "gas2masm"=.\gas2masm\gas2masm.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "winquake"=.\WinQuake.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+    Begin Project Dependency
+    Project_Dep_Name gas2masm
+    End Project Dependency
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
binary files /dev/null b/WinQuake/WinQuake.mdp differ
binary files /dev/null b/WinQuake/WinQuake.ncb differ
binary files /dev/null b/WinQuake/WinQuake.opt differ
--- /dev/null
+++ b/WinQuake/WinQuake.plg
@@ -1,0 +1,595 @@
+<html>
+<body>
+<pre>
+<h1>Build Log</h1>
+<h3>
+--------------------Configuration: winquake - Win32 Release--------------------
+</h3>
+<h3>Command Lines</h3>
+Creating temporary file "C:\TEMP\RSP74A.bat" with contents
+[
+@echo off
+cl /EP > .\Release\worlda.spp .\worlda.s
+gas2masm\debug\gas2masm < .\Release\worlda.spp >                                                                                                                                                                                                    .\Release\worlda.asm
+ml /c /Cp /coff /Fo.\Release\worlda.obj /Zm /Zi                                                                                                                                                                                                    .\Release\worlda.asm
+del .\Release\worlda.spp
+]
+Creating command line "C:\TEMP\RSP74A.bat"
+Creating temporary file "C:\TEMP\RSP74B.bat" with contents
+[
+@echo off
+cl /EP > .\Release\sys_wina.spp .\sys_wina.s
+gas2masm\debug\gas2masm < .\Release\sys_wina.spp >                                                                                                                                                                                                    .\Release\sys_wina.asm
+ml /c /Cp /coff /Fo.\Release\sys_wina.obj /Zm /Zi                                                                                                                                                                                                    .\Release\sys_wina.asm
+del .\Release\sys_wina.spp
+]
+Creating command line "C:\TEMP\RSP74B.bat"
+Creating temporary file "C:\TEMP\RSP74C.bat" with contents
+[
+@echo off
+cl /EP > .\Release\surf8.spp .\surf8.s
+gas2masm\debug\gas2masm < .\Release\surf8.spp >                                                                                                                                                                                                    .\Release\surf8.asm
+ml /c /Cp /coff /Fo.\Release\surf8.obj /Zm /Zi                                                                                                                                                                                                    .\Release\surf8.asm
+del .\Release\surf8.spp
+]
+Creating command line "C:\TEMP\RSP74C.bat"
+Creating temporary file "C:\TEMP\RSP74D.bat" with contents
+[
+@echo off
+cl /EP > .\Release\surf16.spp .\surf16.s
+gas2masm\debug\gas2masm < .\Release\surf16.spp >                                                                                                                                                                                                    .\Release\surf16.asm
+ml /c /Cp /coff /Fo.\Release\surf16.obj /Zm /Zi                                                                                                                                                                                                    .\Release\surf16.asm
+del .\Release\surf16.spp
+]
+Creating command line "C:\TEMP\RSP74D.bat"
+Creating temporary file "C:\TEMP\RSP74E.bat" with contents
+[
+@echo off
+cl /EP > .\Release\snd_mixa.spp .\snd_mixa.s
+gas2masm\debug\gas2masm < .\Release\snd_mixa.spp >                                                                                                                                                                                                    .\Release\snd_mixa.asm
+ml /c /Cp /coff /Fo.\Release\snd_mixa.obj /Zm /Zi                                                                                                                                                                                                    .\Release\snd_mixa.asm
+del .\Release\snd_mixa.spp
+]
+Creating command line "C:\TEMP\RSP74E.bat"
+Creating temporary file "C:\TEMP\RSP74F.bat" with contents
+[
+@echo off
+cl /EP > .\Release\r_varsa.spp .\r_varsa.s
+gas2masm\debug\gas2masm < .\Release\r_varsa.spp >                                                                                                                                                                                                    .\Release\r_varsa.asm
+ml /c /Cp /coff /Fo.\Release\r_varsa.obj /Zm /Zi                                                                                                                                                                                                    .\Release\r_varsa.asm
+del .\Release\r_varsa.spp
+]
+Creating command line "C:\TEMP\RSP74F.bat"
+Creating temporary file "C:\TEMP\RSP750.bat" with contents
+[
+@echo off
+cl /EP > .\Release\r_edgea.spp .\r_edgea.s
+gas2masm\debug\gas2masm < .\Release\r_edgea.spp >                                                                                                                                                                                                    .\Release\r_edgea.asm
+ml /c /Cp /coff /Fo.\Release\r_edgea.obj /Zm /Zi                                                                                                                                                                                                    .\Release\r_edgea.asm
+del .\Release\r_edgea.spp
+]
+Creating command line "C:\TEMP\RSP750.bat"
+Creating temporary file "C:\TEMP\RSP751.bat" with contents
+[
+@echo off
+cl /EP > .\Release\r_drawa.spp .\r_drawa.s
+gas2masm\debug\gas2masm < .\Release\r_drawa.spp >                                                                                                                                                                                                    .\Release\r_drawa.asm
+ml /c /Cp /coff /Fo.\Release\r_drawa.obj /Zm /Zi                                                                                                                                                                                                    .\Release\r_drawa.asm
+del .\Release\r_drawa.spp
+]
+Creating command line "C:\TEMP\RSP751.bat"
+Creating temporary file "C:\TEMP\RSP752.bat" with contents
+[
+@echo off
+cl /EP > .\Release\r_aliasa.spp .\r_aliasa.s
+gas2masm\debug\gas2masm < .\Release\r_aliasa.spp >                                                                                                                                                                                                    .\Release\r_aliasa.asm
+ml /c /Cp /coff /Fo.\Release\r_aliasa.obj /Zm /Zi                                                                                                                                                                                                    .\Release\r_aliasa.asm
+del .\Release\r_aliasa.spp
+]
+Creating command line "C:\TEMP\RSP752.bat"
+Creating temporary file "C:\TEMP\RSP753.bat" with contents
+[
+@echo off
+cl /EP > .\Release\r_aclipa.spp .\r_aclipa.s
+gas2masm\debug\gas2masm < .\Release\r_aclipa.spp >                                                                                                                                                                                                    .\Release\r_aclipa.asm
+ml /c /Cp /coff /Fo.\Release\r_aclipa.obj /Zm /Zi                                                                                                                                                                                                    .\Release\r_aclipa.asm
+del .\Release\r_aclipa.spp
+]
+Creating command line "C:\TEMP\RSP753.bat"
+Creating temporary file "C:\TEMP\RSP754.bat" with contents
+[
+@echo off
+cl /EP > .\Release\math.spp .\math.s
+gas2masm\debug\gas2masm < .\Release\math.spp >                                                                                                                                                                                                    .\Release\math.asm
+ml /c /Cp /coff /Fo.\Release\math.obj /Zm /Zi                                                                                                                                                                                                    .\Release\math.asm
+del .\Release\math.spp
+]
+Creating command line "C:\TEMP\RSP754.bat"
+Creating temporary file "C:\TEMP\RSP755.bat" with contents
+[
+@echo off
+cl /EP > .\Release\d_varsa.spp .\d_varsa.s
+gas2masm\debug\gas2masm < .\Release\d_varsa.spp >                                                                                                                                                                                                    .\Release\d_varsa.asm
+ml /c /Cp /coff /Fo.\Release\d_varsa.obj /Zm /Zi                                                                                                                                                                                                    .\Release\d_varsa.asm
+del .\Release\d_varsa.spp
+]
+Creating command line "C:\TEMP\RSP755.bat"
+Creating temporary file "C:\TEMP\RSP756.bat" with contents
+[
+@echo off
+cl /EP > .\Release\d_spr8.spp .\d_spr8.s
+gas2masm\debug\gas2masm < .\Release\d_spr8.spp >                                                                                                                                                                                                    .\Release\d_spr8.asm
+ml /c /Cp /coff /Fo.\Release\d_spr8.obj /Zm /Zi                                                                                                                                                                                                    .\Release\d_spr8.asm
+del .\Release\d_spr8.spp
+]
+Creating command line "C:\TEMP\RSP756.bat"
+Creating temporary file "C:\TEMP\RSP757.bat" with contents
+[
+@echo off
+cl /EP > .\Release\d_scana.spp .\d_scana.s
+gas2masm\debug\gas2masm < .\Release\d_scana.spp >                                                                                                                                                                                                    .\Release\d_scana.asm
+ml /c /Cp /coff /Fo.\Release\d_scana.obj /Zm /Zi                                                                                                                                                                                                    .\Release\d_scana.asm
+del .\Release\d_scana.spp
+]
+Creating command line "C:\TEMP\RSP757.bat"
+Creating temporary file "C:\TEMP\RSP758.bat" with contents
+[
+@echo off
+cl /EP > .\Release\d_polysa.spp .\d_polysa.s
+gas2masm\debug\gas2masm < .\Release\d_polysa.spp >                                                                                                                                                                                                    .\Release\d_polysa.asm
+ml /c /Cp /coff /Fo.\Release\d_polysa.obj /Zm /Zi                                                                                                                                                                                                    .\Release\d_polysa.asm
+del .\Release\d_polysa.spp
+]
+Creating command line "C:\TEMP\RSP758.bat"
+Creating temporary file "C:\TEMP\RSP759.bat" with contents
+[
+@echo off
+cl /EP > .\Release\d_parta.spp .\d_parta.s
+gas2masm\debug\gas2masm < .\Release\d_parta.spp >                                                                                                                                                                                                    .\Release\d_parta.asm
+ml /c /Cp /coff /Fo.\Release\d_parta.obj /Zm /Zi                                                                                                                                                                                                    .\Release\d_parta.asm
+del .\Release\d_parta.spp
+]
+Creating command line "C:\TEMP\RSP759.bat"
+Creating temporary file "C:\TEMP\RSP75A.bat" with contents
+[
+@echo off
+cl /EP > .\Release\d_draw16.spp .\d_draw16.s
+gas2masm\debug\gas2masm < .\Release\d_draw16.spp >                                                                                                                                                                                                    .\Release\d_draw16.asm
+ml /c /Cp /coff /Fo.\Release\d_draw16.obj /Zm /Zi                                                                                                                                                                                                    .\Release\d_draw16.asm
+del .\Release\d_draw16.spp
+]
+Creating command line "C:\TEMP\RSP75A.bat"
+Creating temporary file "C:\TEMP\RSP75B.bat" with contents
+[
+@echo off
+cl /EP > .\Release\d_draw.spp .\d_draw.s
+gas2masm\debug\gas2masm < .\Release\d_draw.spp >                                                                                                                                                                                                    .\Release\d_draw.asm
+ml /c /Cp /coff /Fo.\Release\d_draw.obj /Zm /Zi                                                                                                                                                                                                    .\Release\d_draw.asm
+del .\Release\d_draw.spp
+]
+Creating command line "C:\TEMP\RSP75B.bat"
+Creating command line "rc.exe /l 0x409 /fo".\Release/winquake.res" /d "NDEBUG" "D:\Work\quake source\WinQuake\winquake.rc"" 
+mycoolbuild
+Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for 80x86
+Copyright (C) Microsoft Corp 1984-1998. All rights reserved.
+
+worlda.s
+Microsoft (R) Macro Assembler Version 6.11
+Copyright (C) Microsoft Corp 1981-1993.  All rights reserved.
+
+ Assembling: .\Release\worlda.asm
+mycoolbuild
+Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for 80x86
+Copyright (C) Microsoft Corp 1984-1998. All rights reserved.
+
+sys_wina.s
+Microsoft (R) Macro Assembler Version 6.11
+Copyright (C) Microsoft Corp 1981-1993.  All rights reserved.
+
+ Assembling: .\Release\sys_wina.asm
+mycoolbuild
+Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for 80x86
+Copyright (C) Microsoft Corp 1984-1998. All rights reserved.
+
+surf8.s
+Microsoft (R) Macro Assembler Version 6.11
+Copyright (C) Microsoft Corp 1981-1993.  All rights reserved.
+
+ Assembling: .\Release\surf8.asm
+mycoolbuild
+Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for 80x86
+Copyright (C) Microsoft Corp 1984-1998. All rights reserved.
+
+surf16.s
+Microsoft (R) Macro Assembler Version 6.11
+Copyright (C) Microsoft Corp 1981-1993.  All rights reserved.
+
+ Assembling: .\Release\surf16.asm
+mycoolbuild
+Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for 80x86
+Copyright (C) Microsoft Corp 1984-1998. All rights reserved.
+
+snd_mixa.s
+Microsoft (R) Macro Assembler Version 6.11
+Copyright (C) Microsoft Corp 1981-1993.  All rights reserved.
+
+ Assembling: .\Release\snd_mixa.asm
+mycoolbuild
+Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for 80x86
+Copyright (C) Microsoft Corp 1984-1998. All rights reserved.
+
+r_varsa.s
+Microsoft (R) Macro Assembler Version 6.11
+Copyright (C) Microsoft Corp 1981-1993.  All rights reserved.
+
+ Assembling: .\Release\r_varsa.asm
+mycoolbuild
+Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for 80x86
+Copyright (C) Microsoft Corp 1984-1998. All rights reserved.
+
+r_edgea.s
+Microsoft (R) Macro Assembler Version 6.11
+Copyright (C) Microsoft Corp 1981-1993.  All rights reserved.
+
+ Assembling: .\Release\r_edgea.asm
+mycoolbuild
+Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for 80x86
+Copyright (C) Microsoft Corp 1984-1998. All rights reserved.
+
+r_drawa.s
+Microsoft (R) Macro Assembler Version 6.11
+Copyright (C) Microsoft Corp 1981-1993.  All rights reserved.
+
+ Assembling: .\Release\r_drawa.asm
+mycoolbuild
+Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for 80x86
+Copyright (C) Microsoft Corp 1984-1998. All rights reserved.
+
+r_aliasa.s
+Microsoft (R) Macro Assembler Version 6.11
+Copyright (C) Microsoft Corp 1981-1993.  All rights reserved.
+
+ Assembling: .\Release\r_aliasa.asm
+mycoolbuild
+Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for 80x86
+Copyright (C) Microsoft Corp 1984-1998. All rights reserved.
+
+r_aclipa.s
+Microsoft (R) Macro Assembler Version 6.11
+Copyright (C) Microsoft Corp 1981-1993.  All rights reserved.
+
+ Assembling: .\Release\r_aclipa.asm
+mycoolbuild
+Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for 80x86
+Copyright (C) Microsoft Corp 1984-1998. All rights reserved.
+
+math.s
+Microsoft (R) Macro Assembler Version 6.11
+Copyright (C) Microsoft Corp 1981-1993.  All rights reserved.
+
+ Assembling: .\Release\math.asm
+mycoolbuild
+Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for 80x86
+Copyright (C) Microsoft Corp 1984-1998. All rights reserved.
+
+d_varsa.s
+Microsoft (R) Macro Assembler Version 6.11
+Copyright (C) Microsoft Corp 1981-1993.  All rights reserved.
+
+ Assembling: .\Release\d_varsa.asm
+mycoolbuild
+Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for 80x86
+Copyright (C) Microsoft Corp 1984-1998. All rights reserved.
+
+d_spr8.s
+Microsoft (R) Macro Assembler Version 6.11
+Copyright (C) Microsoft Corp 1981-1993.  All rights reserved.
+
+ Assembling: .\Release\d_spr8.asm
+mycoolbuild
+Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for 80x86
+Copyright (C) Microsoft Corp 1984-1998. All rights reserved.
+
+d_scana.s
+Microsoft (R) Macro Assembler Version 6.11
+Copyright (C) Microsoft Corp 1981-1993.  All rights reserved.
+
+ Assembling: .\Release\d_scana.asm
+mycoolbuild
+Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for 80x86
+Copyright (C) Microsoft Corp 1984-1998. All rights reserved.
+
+d_polysa.s
+Microsoft (R) Macro Assembler Version 6.11
+Copyright (C) Microsoft Corp 1981-1993.  All rights reserved.
+
+ Assembling: .\Release\d_polysa.asm
+mycoolbuild
+Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for 80x86
+Copyright (C) Microsoft Corp 1984-1998. All rights reserved.
+
+d_parta.s
+Microsoft (R) Macro Assembler Version 6.11
+Copyright (C) Microsoft Corp 1981-1993.  All rights reserved.
+
+ Assembling: .\Release\d_parta.asm
+mycoolbuild
+Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for 80x86
+Copyright (C) Microsoft Corp 1984-1998. All rights reserved.
+
+d_draw16.s
+Microsoft (R) Macro Assembler Version 6.11
+Copyright (C) Microsoft Corp 1981-1993.  All rights reserved.
+
+ Assembling: .\Release\d_draw16.asm
+mycoolbuild
+Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for 80x86
+Copyright (C) Microsoft Corp 1984-1998. All rights reserved.
+
+d_draw.s
+Microsoft (R) Macro Assembler Version 6.11
+Copyright (C) Microsoft Corp 1981-1993.  All rights reserved.
+
+ Assembling: .\Release\d_draw.asm
+Creating temporary file "C:\TEMP\RSP75C.tmp" with contents
+[
+/nologo /G5 /ML /GX /Ox /Ot /Ow /I ".\scitech\include" /I ".\dxsdk\sdk\inc" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FR".\Release/" /Fp".\Release/WinQuake.pch" /YX /Fo".\Release/" /Fd".\Release/" /FD /c 
+"D:\Work\quake source\WinQuake\cd_win.c"
+"D:\Work\quake source\WinQuake\chase.c"
+"D:\Work\quake source\WinQuake\cl_demo.c"
+"D:\Work\quake source\WinQuake\cl_input.c"
+"D:\Work\quake source\WinQuake\cl_main.c"
+"D:\Work\quake source\WinQuake\cl_parse.c"
+"D:\Work\quake source\WinQuake\cl_tent.c"
+"D:\Work\quake source\WinQuake\cmd.c"
+"D:\Work\quake source\WinQuake\common.c"
+"D:\Work\quake source\WinQuake\conproc.c"
+"D:\Work\quake source\WinQuake\console.c"
+"D:\Work\quake source\WinQuake\crc.c"
+"D:\Work\quake source\WinQuake\cvar.c"
+"D:\Work\quake source\WinQuake\d_edge.c"
+"D:\Work\quake source\WinQuake\d_fill.c"
+"D:\Work\quake source\WinQuake\d_init.c"
+"D:\Work\quake source\WinQuake\d_modech.c"
+"D:\Work\quake source\WinQuake\d_part.c"
+"D:\Work\quake source\WinQuake\d_polyse.c"
+"D:\Work\quake source\WinQuake\d_scan.c"
+"D:\Work\quake source\WinQuake\d_sky.c"
+"D:\Work\quake source\WinQuake\d_sprite.c"
+"D:\Work\quake source\WinQuake\d_surf.c"
+"D:\Work\quake source\WinQuake\d_vars.c"
+"D:\Work\quake source\WinQuake\d_zpoint.c"
+"D:\Work\quake source\WinQuake\draw.c"
+"D:\Work\quake source\WinQuake\host.c"
+"D:\Work\quake source\WinQuake\host_cmd.c"
+"D:\Work\quake source\WinQuake\in_win.c"
+"D:\Work\quake source\WinQuake\keys.c"
+"D:\Work\quake source\WinQuake\mathlib.c"
+"D:\Work\quake source\WinQuake\menu.c"
+"D:\Work\quake source\WinQuake\model.c"
+"D:\Work\quake source\WinQuake\net_dgrm.c"
+"D:\Work\quake source\WinQuake\net_loop.c"
+"D:\Work\quake source\WinQuake\net_main.c"
+"D:\Work\quake source\WinQuake\net_vcr.c"
+"D:\Work\quake source\WinQuake\net_win.c"
+"D:\Work\quake source\WinQuake\net_wins.c"
+"D:\Work\quake source\WinQuake\net_wipx.c"
+"D:\Work\quake source\WinQuake\pr_cmds.c"
+"D:\Work\quake source\WinQuake\pr_edict.c"
+"D:\Work\quake source\WinQuake\pr_exec.c"
+"D:\Work\quake source\WinQuake\r_aclip.c"
+"D:\Work\quake source\WinQuake\r_alias.c"
+"D:\Work\quake source\WinQuake\r_bsp.c"
+"D:\Work\quake source\WinQuake\r_draw.c"
+"D:\Work\quake source\WinQuake\r_edge.c"
+"D:\Work\quake source\WinQuake\r_efrag.c"
+"D:\Work\quake source\WinQuake\r_light.c"
+"D:\Work\quake source\WinQuake\r_main.c"
+"D:\Work\quake source\WinQuake\r_misc.c"
+"D:\Work\quake source\WinQuake\r_part.c"
+"D:\Work\quake source\WinQuake\r_sky.c"
+"D:\Work\quake source\WinQuake\r_sprite.c"
+"D:\Work\quake source\WinQuake\r_surf.c"
+"D:\Work\quake source\WinQuake\r_vars.c"
+"D:\Work\quake source\WinQuake\sbar.c"
+"D:\Work\quake source\WinQuake\screen.c"
+"D:\Work\quake source\WinQuake\snd_dma.c"
+"D:\Work\quake source\WinQuake\snd_mem.c"
+"D:\Work\quake source\WinQuake\snd_mix.c"
+"D:\Work\quake source\WinQuake\snd_win.c"
+"D:\Work\quake source\WinQuake\sv_main.c"
+"D:\Work\quake source\WinQuake\sv_move.c"
+"D:\Work\quake source\WinQuake\sv_phys.c"
+"D:\Work\quake source\WinQuake\sv_user.c"
+"D:\Work\quake source\WinQuake\sys_win.c"
+"D:\Work\quake source\WinQuake\vid_win.c"
+"D:\Work\quake source\WinQuake\view.c"
+"D:\Work\quake source\WinQuake\wad.c"
+"D:\Work\quake source\WinQuake\world.c"
+"D:\Work\quake source\WinQuake\zone.c"
+]
+Creating command line "cl.exe @C:\TEMP\RSP75C.tmp" 
+Creating temporary file "C:\TEMP\RSP75D.tmp" with contents
+[
+.\dxsdk\sdk\lib\dxguid.lib .\scitech\lib\win32\vc\mgllt.lib winmm.lib wsock32.lib opengl32.lib glu32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /profile /machine:I386 /out:".\Release/WinQuake.exe" 
+".\Release\cd_win.obj"
+".\Release\chase.obj"
+".\Release\cl_demo.obj"
+".\Release\cl_input.obj"
+".\Release\cl_main.obj"
+".\Release\cl_parse.obj"
+".\Release\cl_tent.obj"
+".\Release\cmd.obj"
+".\Release\common.obj"
+".\Release\conproc.obj"
+".\Release\console.obj"
+".\Release\crc.obj"
+".\Release\cvar.obj"
+".\Release\d_edge.obj"
+".\Release\d_fill.obj"
+".\Release\d_init.obj"
+".\Release\d_modech.obj"
+".\Release\d_part.obj"
+".\Release\d_polyse.obj"
+".\Release\d_scan.obj"
+".\Release\d_sky.obj"
+".\Release\d_sprite.obj"
+".\Release\d_surf.obj"
+".\Release\d_vars.obj"
+".\Release\d_zpoint.obj"
+".\Release\draw.obj"
+".\Release\host.obj"
+".\Release\host_cmd.obj"
+".\Release\in_win.obj"
+".\Release\keys.obj"
+".\Release\mathlib.obj"
+".\Release\menu.obj"
+".\Release\model.obj"
+".\Release\net_dgrm.obj"
+".\Release\net_loop.obj"
+".\Release\net_main.obj"
+".\Release\net_vcr.obj"
+".\Release\net_win.obj"
+".\Release\net_wins.obj"
+".\Release\net_wipx.obj"
+".\Release\pr_cmds.obj"
+".\Release\pr_edict.obj"
+".\Release\pr_exec.obj"
+".\Release\r_aclip.obj"
+".\Release\r_alias.obj"
+".\Release\r_bsp.obj"
+".\Release\r_draw.obj"
+".\Release\r_edge.obj"
+".\Release\r_efrag.obj"
+".\Release\r_light.obj"
+".\Release\r_main.obj"
+".\Release\r_misc.obj"
+".\Release\r_part.obj"
+".\Release\r_sky.obj"
+".\Release\r_sprite.obj"
+".\Release\r_surf.obj"
+".\Release\r_vars.obj"
+".\Release\sbar.obj"
+".\Release\screen.obj"
+".\Release\snd_dma.obj"
+".\Release\snd_mem.obj"
+".\Release\snd_mix.obj"
+".\Release\snd_win.obj"
+".\Release\sv_main.obj"
+".\Release\sv_move.obj"
+".\Release\sv_phys.obj"
+".\Release\sv_user.obj"
+".\Release\sys_win.obj"
+".\Release\vid_win.obj"
+".\Release\view.obj"
+".\Release\wad.obj"
+".\Release\world.obj"
+".\Release\zone.obj"
+".\Release\winquake.res"
+".\Release\d_draw.obj"
+".\Release\d_draw16.obj"
+".\Release\d_parta.obj"
+".\Release\d_polysa.obj"
+".\Release\d_scana.obj"
+".\Release\d_spr8.obj"
+".\Release\d_varsa.obj"
+".\Release\math.obj"
+".\Release\r_aclipa.obj"
+".\Release\r_aliasa.obj"
+".\Release\r_drawa.obj"
+".\Release\r_edgea.obj"
+".\Release\r_varsa.obj"
+".\Release\snd_mixa.obj"
+".\Release\surf16.obj"
+".\Release\surf8.obj"
+".\Release\sys_wina.obj"
+".\Release\worlda.obj"
+]
+Creating command line "link.exe @C:\TEMP\RSP75D.tmp"
+<h3>Output Window</h3>
+Compiling resources...
+Compiling...
+cd_win.c
+chase.c
+cl_demo.c
+cl_input.c
+cl_main.c
+cl_parse.c
+cl_tent.c
+cmd.c
+common.c
+conproc.c
+console.c
+crc.c
+cvar.c
+d_edge.c
+d_fill.c
+d_init.c
+d_modech.c
+d_part.c
+d_polyse.c
+d_scan.c
+d_sky.c
+d_sprite.c
+d_surf.c
+d_vars.c
+d_zpoint.c
+draw.c
+host.c
+host_cmd.c
+in_win.c
+keys.c
+D:\Work\quake source\WinQuake\in_win.c(883) : warning C4715: 'RawValuePointer' : not all control paths return a value
+mathlib.c
+menu.c
+model.c
+net_dgrm.c
+net_loop.c
+net_main.c
+net_vcr.c
+net_win.c
+net_wins.c
+net_wipx.c
+pr_cmds.c
+pr_edict.c
+pr_exec.c
+r_aclip.c
+r_alias.c
+r_bsp.c
+r_draw.c
+r_edge.c
+r_efrag.c
+r_light.c
+r_main.c
+r_misc.c
+r_part.c
+r_sky.c
+r_sprite.c
+r_surf.c
+r_vars.c
+sbar.c
+screen.c
+snd_dma.c
+snd_mem.c
+snd_mix.c
+snd_win.c
+sv_main.c
+sv_move.c
+sv_phys.c
+sv_user.c
+sys_win.c
+vid_win.c
+view.c
+D:\Work\quake source\WinQuake\vid_win.c(348) : warning C4715: 'VID_Suspend' : not all control paths return a value
+wad.c
+world.c
+zone.c
+Linking...
+
+
+
+<h3>Results</h3>
+WinQuake.exe - 0 error(s), 2 warning(s)
+</pre>
+</body>
+</html>
--- /dev/null
+++ b/WinQuake/adivtab.h
@@ -1,0 +1,1077 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// table of quotients and remainders for [-15...16] / [-15...16]
+
+// numerator = -15
+{1, 0},
+{1, -1},
+{1, -2},
+{1, -3},
+{1, -4},
+{1, -5},
+{1, -6},
+{1, -7},
+{2, -1},
+{2, -3},
+{3, 0},
+{3, -3},
+{5, 0},
+{7, -1},
+{15, 0},
+{0, 0},
+{-15, 0},
+{-8, 1},
+{-5, 0},
+{-4, 1},
+{-3, 0},
+{-3, 3},
+{-3, 6},
+{-2, 1},
+{-2, 3},
+{-2, 5},
+{-2, 7},
+{-2, 9},
+{-2, 11},
+{-2, 13},
+{-1, 0},
+{-1, 1},
+// numerator = -14
+{0, -14},
+{1, 0},
+{1, -1},
+{1, -2},
+{1, -3},
+{1, -4},
+{1, -5},
+{1, -6},
+{2, 0},
+{2, -2},
+{2, -4},
+{3, -2},
+{4, -2},
+{7, 0},
+{14, 0},
+{0, 0},
+{-14, 0},
+{-7, 0},
+{-5, 1},
+{-4, 2},
+{-3, 1},
+{-3, 4},
+{-2, 0},
+{-2, 2},
+{-2, 4},
+{-2, 6},
+{-2, 8},
+{-2, 10},
+{-2, 12},
+{-1, 0},
+{-1, 1},
+{-1, 2},
+// numerator = -13
+{0, -13},
+{0, -13},
+{1, 0},
+{1, -1},
+{1, -2},
+{1, -3},
+{1, -4},
+{1, -5},
+{1, -6},
+{2, -1},
+{2, -3},
+{3, -1},
+{4, -1},
+{6, -1},
+{13, 0},
+{0, 0},
+{-13, 0},
+{-7, 1},
+{-5, 2},
+{-4, 3},
+{-3, 2},
+{-3, 5},
+{-2, 1},
+{-2, 3},
+{-2, 5},
+{-2, 7},
+{-2, 9},
+{-2, 11},
+{-1, 0},
+{-1, 1},
+{-1, 2},
+{-1, 3},
+// numerator = -12
+{0, -12},
+{0, -12},
+{0, -12},
+{1, 0},
+{1, -1},
+{1, -2},
+{1, -3},
+{1, -4},
+{1, -5},
+{2, 0},
+{2, -2},
+{3, 0},
+{4, 0},
+{6, 0},
+{12, 0},
+{0, 0},
+{-12, 0},
+{-6, 0},
+{-4, 0},
+{-3, 0},
+{-3, 3},
+{-2, 0},
+{-2, 2},
+{-2, 4},
+{-2, 6},
+{-2, 8},
+{-2, 10},
+{-1, 0},
+{-1, 1},
+{-1, 2},
+{-1, 3},
+{-1, 4},
+// numerator = -11
+{0, -11},
+{0, -11},
+{0, -11},
+{0, -11},
+{1, 0},
+{1, -1},
+{1, -2},
+{1, -3},
+{1, -4},
+{1, -5},
+{2, -1},
+{2, -3},
+{3, -2},
+{5, -1},
+{11, 0},
+{0, 0},
+{-11, 0},
+{-6, 1},
+{-4, 1},
+{-3, 1},
+{-3, 4},
+{-2, 1},
+{-2, 3},
+{-2, 5},
+{-2, 7},
+{-2, 9},
+{-1, 0},
+{-1, 1},
+{-1, 2},
+{-1, 3},
+{-1, 4},
+{-1, 5},
+// numerator = -10
+{0, -10},
+{0, -10},
+{0, -10},
+{0, -10},
+{0, -10},
+{1, 0},
+{1, -1},
+{1, -2},
+{1, -3},
+{1, -4},
+{2, 0},
+{2, -2},
+{3, -1},
+{5, 0},
+{10, 0},
+{0, 0},
+{-10, 0},
+{-5, 0},
+{-4, 2},
+{-3, 2},
+{-2, 0},
+{-2, 2},
+{-2, 4},
+{-2, 6},
+{-2, 8},
+{-1, 0},
+{-1, 1},
+{-1, 2},
+{-1, 3},
+{-1, 4},
+{-1, 5},
+{-1, 6},
+// numerator = -9
+{0, -9},
+{0, -9},
+{0, -9},
+{0, -9},
+{0, -9},
+{0, -9},
+{1, 0},
+{1, -1},
+{1, -2},
+{1, -3},
+{1, -4},
+{2, -1},
+{3, 0},
+{4, -1},
+{9, 0},
+{0, 0},
+{-9, 0},
+{-5, 1},
+{-3, 0},
+{-3, 3},
+{-2, 1},
+{-2, 3},
+{-2, 5},
+{-2, 7},
+{-1, 0},
+{-1, 1},
+{-1, 2},
+{-1, 3},
+{-1, 4},
+{-1, 5},
+{-1, 6},
+{-1, 7},
+// numerator = -8
+{0, -8},
+{0, -8},
+{0, -8},
+{0, -8},
+{0, -8},
+{0, -8},
+{0, -8},
+{1, 0},
+{1, -1},
+{1, -2},
+{1, -3},
+{2, 0},
+{2, -2},
+{4, 0},
+{8, 0},
+{0, 0},
+{-8, 0},
+{-4, 0},
+{-3, 1},
+{-2, 0},
+{-2, 2},
+{-2, 4},
+{-2, 6},
+{-1, 0},
+{-1, 1},
+{-1, 2},
+{-1, 3},
+{-1, 4},
+{-1, 5},
+{-1, 6},
+{-1, 7},
+{-1, 8},
+// numerator = -7
+{0, -7},
+{0, -7},
+{0, -7},
+{0, -7},
+{0, -7},
+{0, -7},
+{0, -7},
+{0, -7},
+{1, 0},
+{1, -1},
+{1, -2},
+{1, -3},
+{2, -1},
+{3, -1},
+{7, 0},
+{0, 0},
+{-7, 0},
+{-4, 1},
+{-3, 2},
+{-2, 1},
+{-2, 3},
+{-2, 5},
+{-1, 0},
+{-1, 1},
+{-1, 2},
+{-1, 3},
+{-1, 4},
+{-1, 5},
+{-1, 6},
+{-1, 7},
+{-1, 8},
+{-1, 9},
+// numerator = -6
+{0, -6},
+{0, -6},
+{0, -6},
+{0, -6},
+{0, -6},
+{0, -6},
+{0, -6},
+{0, -6},
+{0, -6},
+{1, 0},
+{1, -1},
+{1, -2},
+{2, 0},
+{3, 0},
+{6, 0},
+{0, 0},
+{-6, 0},
+{-3, 0},
+{-2, 0},
+{-2, 2},
+{-2, 4},
+{-1, 0},
+{-1, 1},
+{-1, 2},
+{-1, 3},
+{-1, 4},
+{-1, 5},
+{-1, 6},
+{-1, 7},
+{-1, 8},
+{-1, 9},
+{-1, 10},
+// numerator = -5
+{0, -5},
+{0, -5},
+{0, -5},
+{0, -5},
+{0, -5},
+{0, -5},
+{0, -5},
+{0, -5},
+{0, -5},
+{0, -5},
+{1, 0},
+{1, -1},
+{1, -2},
+{2, -1},
+{5, 0},
+{0, 0},
+{-5, 0},
+{-3, 1},
+{-2, 1},
+{-2, 3},
+{-1, 0},
+{-1, 1},
+{-1, 2},
+{-1, 3},
+{-1, 4},
+{-1, 5},
+{-1, 6},
+{-1, 7},
+{-1, 8},
+{-1, 9},
+{-1, 10},
+{-1, 11},
+// numerator = -4
+{0, -4},
+{0, -4},
+{0, -4},
+{0, -4},
+{0, -4},
+{0, -4},
+{0, -4},
+{0, -4},
+{0, -4},
+{0, -4},
+{0, -4},
+{1, 0},
+{1, -1},
+{2, 0},
+{4, 0},
+{0, 0},
+{-4, 0},
+{-2, 0},
+{-2, 2},
+{-1, 0},
+{-1, 1},
+{-1, 2},
+{-1, 3},
+{-1, 4},
+{-1, 5},
+{-1, 6},
+{-1, 7},
+{-1, 8},
+{-1, 9},
+{-1, 10},
+{-1, 11},
+{-1, 12},
+// numerator = -3
+{0, -3},
+{0, -3},
+{0, -3},
+{0, -3},
+{0, -3},
+{0, -3},
+{0, -3},
+{0, -3},
+{0, -3},
+{0, -3},
+{0, -3},
+{0, -3},
+{1, 0},
+{1, -1},
+{3, 0},
+{0, 0},
+{-3, 0},
+{-2, 1},
+{-1, 0},
+{-1, 1},
+{-1, 2},
+{-1, 3},
+{-1, 4},
+{-1, 5},
+{-1, 6},
+{-1, 7},
+{-1, 8},
+{-1, 9},
+{-1, 10},
+{-1, 11},
+{-1, 12},
+{-1, 13},
+// numerator = -2
+{0, -2},
+{0, -2},
+{0, -2},
+{0, -2},
+{0, -2},
+{0, -2},
+{0, -2},
+{0, -2},
+{0, -2},
+{0, -2},
+{0, -2},
+{0, -2},
+{0, -2},
+{1, 0},
+{2, 0},
+{0, 0},
+{-2, 0},
+{-1, 0},
+{-1, 1},
+{-1, 2},
+{-1, 3},
+{-1, 4},
+{-1, 5},
+{-1, 6},
+{-1, 7},
+{-1, 8},
+{-1, 9},
+{-1, 10},
+{-1, 11},
+{-1, 12},
+{-1, 13},
+{-1, 14},
+// numerator = -1
+{0, -1},
+{0, -1},
+{0, -1},
+{0, -1},
+{0, -1},
+{0, -1},
+{0, -1},
+{0, -1},
+{0, -1},
+{0, -1},
+{0, -1},
+{0, -1},
+{0, -1},
+{0, -1},
+{1, 0},
+{0, 0},
+{-1, 0},
+{-1, 1},
+{-1, 2},
+{-1, 3},
+{-1, 4},
+{-1, 5},
+{-1, 6},
+{-1, 7},
+{-1, 8},
+{-1, 9},
+{-1, 10},
+{-1, 11},
+{-1, 12},
+{-1, 13},
+{-1, 14},
+{-1, 15},
+// numerator = 0
+{0, 0},
+{0, 0},
+{0, 0},
+{0, 0},
+{0, 0},
+{0, 0},
+{0, 0},
+{0, 0},
+{0, 0},
+{0, 0},
+{0, 0},
+{0, 0},
+{0, 0},
+{0, 0},
+{0, 0},
+{0, 0},
+{0, 0},
+{0, 0},
+{0, 0},
+{0, 0},
+{0, 0},
+{0, 0},
+{0, 0},
+{0, 0},
+{0, 0},
+{0, 0},
+{0, 0},
+{0, 0},
+{0, 0},
+{0, 0},
+{0, 0},
+{0, 0},
+// numerator = 1
+{-1, -14},
+{-1, -13},
+{-1, -12},
+{-1, -11},
+{-1, -10},
+{-1, -9},
+{-1, -8},
+{-1, -7},
+{-1, -6},
+{-1, -5},
+{-1, -4},
+{-1, -3},
+{-1, -2},
+{-1, -1},
+{-1, 0},
+{0, 0},
+{1, 0},
+{0, 1},
+{0, 1},
+{0, 1},
+{0, 1},
+{0, 1},
+{0, 1},
+{0, 1},
+{0, 1},
+{0, 1},
+{0, 1},
+{0, 1},
+{0, 1},
+{0, 1},
+{0, 1},
+{0, 1},
+// numerator = 2
+{-1, -13},
+{-1, -12},
+{-1, -11},
+{-1, -10},
+{-1, -9},
+{-1, -8},
+{-1, -7},
+{-1, -6},
+{-1, -5},
+{-1, -4},
+{-1, -3},
+{-1, -2},
+{-1, -1},
+{-1, 0},
+{-2, 0},
+{0, 0},
+{2, 0},
+{1, 0},
+{0, 2},
+{0, 2},
+{0, 2},
+{0, 2},
+{0, 2},
+{0, 2},
+{0, 2},
+{0, 2},
+{0, 2},
+{0, 2},
+{0, 2},
+{0, 2},
+{0, 2},
+{0, 2},
+// numerator = 3
+{-1, -12},
+{-1, -11},
+{-1, -10},
+{-1, -9},
+{-1, -8},
+{-1, -7},
+{-1, -6},
+{-1, -5},
+{-1, -4},
+{-1, -3},
+{-1, -2},
+{-1, -1},
+{-1, 0},
+{-2, -1},
+{-3, 0},
+{0, 0},
+{3, 0},
+{1, 1},
+{1, 0},
+{0, 3},
+{0, 3},
+{0, 3},
+{0, 3},
+{0, 3},
+{0, 3},
+{0, 3},
+{0, 3},
+{0, 3},
+{0, 3},
+{0, 3},
+{0, 3},
+{0, 3},
+// numerator = 4
+{-1, -11},
+{-1, -10},
+{-1, -9},
+{-1, -8},
+{-1, -7},
+{-1, -6},
+{-1, -5},
+{-1, -4},
+{-1, -3},
+{-1, -2},
+{-1, -1},
+{-1, 0},
+{-2, -2},
+{-2, 0},
+{-4, 0},
+{0, 0},
+{4, 0},
+{2, 0},
+{1, 1},
+{1, 0},
+{0, 4},
+{0, 4},
+{0, 4},
+{0, 4},
+{0, 4},
+{0, 4},
+{0, 4},
+{0, 4},
+{0, 4},
+{0, 4},
+{0, 4},
+{0, 4},
+// numerator = 5
+{-1, -10},
+{-1, -9},
+{-1, -8},
+{-1, -7},
+{-1, -6},
+{-1, -5},
+{-1, -4},
+{-1, -3},
+{-1, -2},
+{-1, -1},
+{-1, 0},
+{-2, -3},
+{-2, -1},
+{-3, -1},
+{-5, 0},
+{0, 0},
+{5, 0},
+{2, 1},
+{1, 2},
+{1, 1},
+{1, 0},
+{0, 5},
+{0, 5},
+{0, 5},
+{0, 5},
+{0, 5},
+{0, 5},
+{0, 5},
+{0, 5},
+{0, 5},
+{0, 5},
+{0, 5},
+// numerator = 6
+{-1, -9},
+{-1, -8},
+{-1, -7},
+{-1, -6},
+{-1, -5},
+{-1, -4},
+{-1, -3},
+{-1, -2},
+{-1, -1},
+{-1, 0},
+{-2, -4},
+{-2, -2},
+{-2, 0},
+{-3, 0},
+{-6, 0},
+{0, 0},
+{6, 0},
+{3, 0},
+{2, 0},
+{1, 2},
+{1, 1},
+{1, 0},
+{0, 6},
+{0, 6},
+{0, 6},
+{0, 6},
+{0, 6},
+{0, 6},
+{0, 6},
+{0, 6},
+{0, 6},
+{0, 6},
+// numerator = 7
+{-1, -8},
+{-1, -7},
+{-1, -6},
+{-1, -5},
+{-1, -4},
+{-1, -3},
+{-1, -2},
+{-1, -1},
+{-1, 0},
+{-2, -5},
+{-2, -3},
+{-2, -1},
+{-3, -2},
+{-4, -1},
+{-7, 0},
+{0, 0},
+{7, 0},
+{3, 1},
+{2, 1},
+{1, 3},
+{1, 2},
+{1, 1},
+{1, 0},
+{0, 7},
+{0, 7},
+{0, 7},
+{0, 7},
+{0, 7},
+{0, 7},
+{0, 7},
+{0, 7},
+{0, 7},
+// numerator = 8
+{-1, -7},
+{-1, -6},
+{-1, -5},
+{-1, -4},
+{-1, -3},
+{-1, -2},
+{-1, -1},
+{-1, 0},
+{-2, -6},
+{-2, -4},
+{-2, -2},
+{-2, 0},
+{-3, -1},
+{-4, 0},
+{-8, 0},
+{0, 0},
+{8, 0},
+{4, 0},
+{2, 2},
+{2, 0},
+{1, 3},
+{1, 2},
+{1, 1},
+{1, 0},
+{0, 8},
+{0, 8},
+{0, 8},
+{0, 8},
+{0, 8},
+{0, 8},
+{0, 8},
+{0, 8},
+// numerator = 9
+{-1, -6},
+{-1, -5},
+{-1, -4},
+{-1, -3},
+{-1, -2},
+{-1, -1},
+{-1, 0},
+{-2, -7},
+{-2, -5},
+{-2, -3},
+{-2, -1},
+{-3, -3},
+{-3, 0},
+{-5, -1},
+{-9, 0},
+{0, 0},
+{9, 0},
+{4, 1},
+{3, 0},
+{2, 1},
+{1, 4},
+{1, 3},
+{1, 2},
+{1, 1},
+{1, 0},
+{0, 9},
+{0, 9},
+{0, 9},
+{0, 9},
+{0, 9},
+{0, 9},
+{0, 9},
+// numerator = 10
+{-1, -5},
+{-1, -4},
+{-1, -3},
+{-1, -2},
+{-1, -1},
+{-1, 0},
+{-2, -8},
+{-2, -6},
+{-2, -4},
+{-2, -2},
+{-2, 0},
+{-3, -2},
+{-4, -2},
+{-5, 0},
+{-10, 0},
+{0, 0},
+{10, 0},
+{5, 0},
+{3, 1},
+{2, 2},
+{2, 0},
+{1, 4},
+{1, 3},
+{1, 2},
+{1, 1},
+{1, 0},
+{0, 10},
+{0, 10},
+{0, 10},
+{0, 10},
+{0, 10},
+{0, 10},
+// numerator = 11
+{-1, -4},
+{-1, -3},
+{-1, -2},
+{-1, -1},
+{-1, 0},
+{-2, -9},
+{-2, -7},
+{-2, -5},
+{-2, -3},
+{-2, -1},
+{-3, -4},
+{-3, -1},
+{-4, -1},
+{-6, -1},
+{-11, 0},
+{0, 0},
+{11, 0},
+{5, 1},
+{3, 2},
+{2, 3},
+{2, 1},
+{1, 5},
+{1, 4},
+{1, 3},
+{1, 2},
+{1, 1},
+{1, 0},
+{0, 11},
+{0, 11},
+{0, 11},
+{0, 11},
+{0, 11},
+// numerator = 12
+{-1, -3},
+{-1, -2},
+{-1, -1},
+{-1, 0},
+{-2, -10},
+{-2, -8},
+{-2, -6},
+{-2, -4},
+{-2, -2},
+{-2, 0},
+{-3, -3},
+{-3, 0},
+{-4, 0},
+{-6, 0},
+{-12, 0},
+{0, 0},
+{12, 0},
+{6, 0},
+{4, 0},
+{3, 0},
+{2, 2},
+{2, 0},
+{1, 5},
+{1, 4},
+{1, 3},
+{1, 2},
+{1, 1},
+{1, 0},
+{0, 12},
+{0, 12},
+{0, 12},
+{0, 12},
+// numerator = 13
+{-1, -2},
+{-1, -1},
+{-1, 0},
+{-2, -11},
+{-2, -9},
+{-2, -7},
+{-2, -5},
+{-2, -3},
+{-2, -1},
+{-3, -5},
+{-3, -2},
+{-4, -3},
+{-5, -2},
+{-7, -1},
+{-13, 0},
+{0, 0},
+{13, 0},
+{6, 1},
+{4, 1},
+{3, 1},
+{2, 3},
+{2, 1},
+{1, 6},
+{1, 5},
+{1, 4},
+{1, 3},
+{1, 2},
+{1, 1},
+{1, 0},
+{0, 13},
+{0, 13},
+{0, 13},
+// numerator = 14
+{-1, -1},
+{-1, 0},
+{-2, -12},
+{-2, -10},
+{-2, -8},
+{-2, -6},
+{-2, -4},
+{-2, -2},
+{-2, 0},
+{-3, -4},
+{-3, -1},
+{-4, -2},
+{-5, -1},
+{-7, 0},
+{-14, 0},
+{0, 0},
+{14, 0},
+{7, 0},
+{4, 2},
+{3, 2},
+{2, 4},
+{2, 2},
+{2, 0},
+{1, 6},
+{1, 5},
+{1, 4},
+{1, 3},
+{1, 2},
+{1, 1},
+{1, 0},
+{0, 14},
+{0, 14},
+// numerator = 15
+{-1, 0},
+{-2, -13},
+{-2, -11},
+{-2, -9},
+{-2, -7},
+{-2, -5},
+{-2, -3},
+{-2, -1},
+{-3, -6},
+{-3, -3},
+{-3, 0},
+{-4, -1},
+{-5, 0},
+{-8, -1},
+{-15, 0},
+{0, 0},
+{15, 0},
+{7, 1},
+{5, 0},
+{3, 3},
+{3, 0},
+{2, 3},
+{2, 1},
+{1, 7},
+{1, 6},
+{1, 5},
+{1, 4},
+{1, 3},
+{1, 2},
+{1, 1},
+{1, 0},
+{0, 15},
+// numerator = 16
+{-2, -14},
+{-2, -12},
+{-2, -10},
+{-2, -8},
+{-2, -6},
+{-2, -4},
+{-2, -2},
+{-2, 0},
+{-3, -5},
+{-3, -2},
+{-4, -4},
+{-4, 0},
+{-6, -2},
+{-8, 0},
+{-16, 0},
+{0, 0},
+{16, 0},
+{8, 0},
+{5, 1},
+{4, 0},
+{3, 1},
+{2, 4},
+{2, 2},
+{2, 0},
+{1, 7},
+{1, 6},
+{1, 5},
+{1, 4},
+{1, 3},
+{1, 2},
+{1, 1},
+{1, 0},
--- /dev/null
+++ b/WinQuake/anorm_dots.h
@@ -1,0 +1,37 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+{
+{1.23,1.30,1.47,1.35,1.56,1.71,1.37,1.38,1.59,1.60,1.79,1.97,1.88,1.92,1.79,1.02,0.93,1.07,0.82,0.87,0.88,0.94,0.96,1.14,1.11,0.82,0.83,0.89,0.89,0.86,0.94,0.91,1.00,1.21,0.98,1.48,1.30,1.57,0.96,1.07,1.14,1.60,1.61,1.40,1.37,1.72,1.78,1.79,1.93,1.99,1.90,1.68,1.71,1.86,1.60,1.68,1.78,1.86,1.93,1.99,1.97,1.44,1.22,1.49,0.93,0.99,0.99,1.23,1.22,1.44,1.49,0.89,0.89,0.97,0.91,0.98,1.19,0.82,0.76,0.82,0.71,0.72,0.73,0.76,0.79,0.86,0.83,0.72,0.76,0.76,0.89,0.82,0.89,0.82,0.89,0.91,0.83,0.96,1.14,0.97,1.40,1.19,0.98,0.94,1.00,1.07,1.37,1.21,1.48,1.30,1.57,1.61,1.37,0.86,0.83,0.91,0.82,0.82,0.88,0.89,0.96,1.14,0.98,0.87,0.93,0.94,1.02,1.30,1.07,1.35,1.38,1.11,1.56,1.92,1.79,1.79,1.59,1.60,1.72,1.90,1.79,0.80,0.85,0.79,0.93,0.80,0.85,0.77,0.74,0.72,0.77,0.74,0.72,0.70,0.70,0.71,0.76,0.73,0.79,0.79,0.73,0.76,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00},
+{1.26,1.26,1.48,1.23,1.50,1.71,1.14,1.19,1.38,1.46,1.64,1.94,1.87,1.84,1.71,1.02,0.92,1.00,0.79,0.85,0.84,0.91,0.90,0.98,0.99,0.77,0.77,0.83,0.82,0.79,0.86,0.84,0.92,0.99,0.91,1.24,1.03,1.33,0.88,0.94,0.97,1.41,1.39,1.18,1.11,1.51,1.61,1.59,1.80,1.91,1.76,1.54,1.65,1.76,1.70,1.70,1.85,1.85,1.97,1.99,1.93,1.28,1.09,1.39,0.92,0.97,0.99,1.18,1.26,1.52,1.48,0.83,0.85,0.90,0.88,0.93,1.00,0.77,0.73,0.78,0.72,0.71,0.74,0.75,0.79,0.86,0.81,0.75,0.81,0.79,0.96,0.88,0.94,0.86,0.93,0.92,0.85,1.08,1.33,1.05,1.55,1.31,1.01,1.05,1.27,1.31,1.60,1.47,1.70,1.54,1.76,1.76,1.57,0.93,0.90,0.99,0.88,0.88,0.95,0.97,1.11,1.39,1.20,0.92,0.97,1.01,1.10,1.39,1.22,1.51,1.58,1.32,1.64,1.97,1.85,1.91,1.77,1.74,1.88,1.99,1.91,0.79,0.86,0.80,0.94,0.84,0.88,0.74,0.74,0.71,0.82,0.77,0.76,0.70,0.73,0.72,0.73,0.70,0.74,0.85,0.77,0.82,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00},
+{1.34,1.27,1.53,1.17,1.46,1.71,0.98,1.05,1.20,1.34,1.48,1.86,1.82,1.71,1.62,1.09,0.94,0.99,0.79,0.85,0.82,0.90,0.87,0.93,0.96,0.76,0.74,0.79,0.76,0.74,0.79,0.78,0.85,0.92,0.85,1.00,0.93,1.06,0.81,0.86,0.89,1.16,1.12,0.97,0.95,1.28,1.38,1.35,1.60,1.77,1.57,1.33,1.50,1.58,1.69,1.63,1.82,1.74,1.91,1.92,1.80,1.04,0.97,1.21,0.90,0.93,0.97,1.05,1.21,1.48,1.37,0.77,0.80,0.84,0.85,0.88,0.92,0.73,0.71,0.74,0.74,0.71,0.75,0.73,0.79,0.84,0.78,0.79,0.86,0.81,1.05,0.94,0.99,0.90,0.95,0.92,0.86,1.24,1.44,1.14,1.59,1.34,1.02,1.27,1.50,1.49,1.80,1.69,1.86,1.72,1.87,1.80,1.69,1.00,0.98,1.23,0.95,0.96,1.09,1.16,1.37,1.63,1.46,0.99,1.10,1.25,1.24,1.51,1.41,1.67,1.77,1.55,1.72,1.95,1.89,1.98,1.91,1.86,1.97,1.99,1.94,0.81,0.89,0.85,0.98,0.90,0.94,0.75,0.78,0.73,0.89,0.83,0.82,0.72,0.77,0.76,0.72,0.70,0.71,0.91,0.83,0.89,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00},
+{1.46,1.34,1.60,1.16,1.46,1.71,0.94,0.99,1.05,1.26,1.33,1.74,1.76,1.57,1.54,1.23,0.98,1.05,0.83,0.89,0.84,0.92,0.87,0.91,0.96,0.78,0.74,0.79,0.72,0.72,0.75,0.76,0.80,0.88,0.83,0.94,0.87,0.95,0.76,0.80,0.82,0.97,0.96,0.89,0.88,1.08,1.11,1.10,1.37,1.59,1.37,1.07,1.27,1.34,1.57,1.45,1.69,1.55,1.77,1.79,1.60,0.93,0.90,0.99,0.86,0.87,0.93,0.96,1.07,1.35,1.18,0.73,0.76,0.77,0.81,0.82,0.85,0.70,0.71,0.72,0.78,0.73,0.77,0.73,0.79,0.82,0.76,0.83,0.90,0.84,1.18,0.98,1.03,0.92,0.95,0.90,0.86,1.32,1.45,1.15,1.53,1.27,0.99,1.42,1.65,1.58,1.93,1.83,1.94,1.81,1.88,1.74,1.70,1.19,1.17,1.44,1.11,1.15,1.36,1.41,1.61,1.81,1.67,1.22,1.34,1.50,1.42,1.65,1.61,1.82,1.91,1.75,1.80,1.89,1.89,1.98,1.99,1.94,1.98,1.92,1.87,0.86,0.95,0.92,1.14,0.98,1.03,0.79,0.84,0.77,0.97,0.90,0.89,0.76,0.82,0.82,0.74,0.72,0.71,0.98,0.89,0.97,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00},
+{1.60,1.44,1.68,1.22,1.49,1.71,0.93,0.99,0.99,1.23,1.22,1.60,1.68,1.44,1.49,1.40,1.14,1.19,0.89,0.96,0.89,0.97,0.89,0.91,0.98,0.82,0.76,0.82,0.71,0.72,0.73,0.76,0.79,0.86,0.83,0.91,0.83,0.89,0.72,0.76,0.76,0.89,0.89,0.82,0.82,0.98,0.96,0.97,1.14,1.40,1.19,0.94,1.00,1.07,1.37,1.21,1.48,1.30,1.57,1.61,1.37,0.86,0.83,0.91,0.82,0.82,0.88,0.89,0.96,1.14,0.98,0.70,0.72,0.73,0.77,0.76,0.79,0.70,0.72,0.71,0.82,0.77,0.80,0.74,0.79,0.80,0.74,0.87,0.93,0.85,1.23,1.02,1.02,0.93,0.93,0.87,0.85,1.30,1.35,1.07,1.38,1.11,0.94,1.47,1.71,1.56,1.97,1.88,1.92,1.79,1.79,1.59,1.60,1.30,1.35,1.56,1.37,1.38,1.59,1.60,1.79,1.92,1.79,1.48,1.57,1.72,1.61,1.78,1.79,1.93,1.99,1.90,1.86,1.78,1.86,1.93,1.99,1.97,1.90,1.79,1.72,0.94,1.07,1.00,1.37,1.21,1.30,0.86,0.91,0.83,1.14,0.98,0.96,0.82,0.88,0.89,0.79,0.76,0.73,1.07,0.94,1.11,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00},
+{1.74,1.57,1.76,1.33,1.54,1.71,0.94,1.05,0.99,1.26,1.16,1.46,1.60,1.34,1.46,1.59,1.37,1.37,0.97,1.11,0.96,1.10,0.95,0.94,1.08,0.89,0.82,0.88,0.72,0.76,0.75,0.80,0.80,0.88,0.87,0.91,0.83,0.87,0.72,0.76,0.74,0.83,0.84,0.78,0.79,0.96,0.89,0.92,0.98,1.23,1.05,0.86,0.92,0.95,1.11,0.98,1.22,1.03,1.34,1.42,1.14,0.79,0.77,0.84,0.78,0.76,0.82,0.82,0.89,0.97,0.90,0.70,0.71,0.71,0.73,0.72,0.74,0.73,0.76,0.72,0.86,0.81,0.82,0.76,0.79,0.77,0.73,0.90,0.95,0.86,1.18,1.03,0.98,0.92,0.90,0.83,0.84,1.19,1.17,0.98,1.15,0.97,0.89,1.42,1.65,1.44,1.93,1.83,1.81,1.67,1.61,1.36,1.41,1.32,1.45,1.58,1.57,1.53,1.74,1.70,1.88,1.94,1.81,1.69,1.77,1.87,1.79,1.89,1.92,1.98,1.99,1.98,1.89,1.65,1.80,1.82,1.91,1.94,1.75,1.61,1.50,1.07,1.34,1.27,1.60,1.45,1.55,0.93,0.99,0.90,1.35,1.18,1.07,0.87,0.93,0.96,0.85,0.82,0.77,1.15,0.99,1.27,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00},
+{1.86,1.71,1.82,1.48,1.62,1.71,0.98,1.20,1.05,1.34,1.17,1.34,1.53,1.27,1.46,1.77,1.60,1.57,1.16,1.38,1.12,1.35,1.06,1.00,1.28,0.97,0.89,0.95,0.76,0.81,0.79,0.86,0.85,0.92,0.93,0.93,0.85,0.87,0.74,0.78,0.74,0.79,0.82,0.76,0.79,0.96,0.85,0.90,0.94,1.09,0.99,0.81,0.85,0.89,0.95,0.90,0.99,0.94,1.10,1.24,0.98,0.75,0.73,0.78,0.74,0.72,0.77,0.76,0.82,0.89,0.83,0.73,0.71,0.71,0.71,0.70,0.72,0.77,0.80,0.74,0.90,0.85,0.84,0.78,0.79,0.75,0.73,0.92,0.95,0.86,1.05,0.99,0.94,0.90,0.86,0.79,0.81,1.00,0.98,0.91,0.96,0.89,0.83,1.27,1.50,1.23,1.80,1.69,1.63,1.46,1.37,1.09,1.16,1.24,1.44,1.49,1.69,1.59,1.80,1.69,1.87,1.86,1.72,1.82,1.91,1.94,1.92,1.95,1.99,1.98,1.91,1.97,1.89,1.51,1.72,1.67,1.77,1.86,1.55,1.41,1.25,1.33,1.58,1.50,1.80,1.63,1.74,1.04,1.21,0.97,1.48,1.37,1.21,0.93,0.97,1.05,0.92,0.88,0.84,1.14,1.02,1.34,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00},
+{1.94,1.84,1.87,1.64,1.71,1.71,1.14,1.38,1.19,1.46,1.23,1.26,1.48,1.26,1.50,1.91,1.80,1.76,1.41,1.61,1.39,1.59,1.33,1.24,1.51,1.18,0.97,1.11,0.82,0.88,0.86,0.94,0.92,0.99,1.03,0.98,0.91,0.90,0.79,0.84,0.77,0.79,0.84,0.77,0.83,0.99,0.85,0.91,0.92,1.02,1.00,0.79,0.80,0.86,0.88,0.84,0.92,0.88,0.97,1.10,0.94,0.74,0.71,0.74,0.72,0.70,0.73,0.72,0.76,0.82,0.77,0.77,0.73,0.74,0.71,0.70,0.73,0.83,0.85,0.78,0.92,0.88,0.86,0.81,0.79,0.74,0.75,0.92,0.93,0.85,0.96,0.94,0.88,0.86,0.81,0.75,0.79,0.93,0.90,0.85,0.88,0.82,0.77,1.05,1.27,0.99,1.60,1.47,1.39,1.20,1.11,0.95,0.97,1.08,1.33,1.31,1.70,1.55,1.76,1.57,1.76,1.70,1.54,1.85,1.97,1.91,1.99,1.97,1.99,1.91,1.77,1.88,1.85,1.39,1.64,1.51,1.58,1.74,1.32,1.22,1.01,1.54,1.76,1.65,1.93,1.70,1.85,1.28,1.39,1.09,1.52,1.48,1.26,0.97,0.99,1.18,1.00,0.93,0.90,1.05,1.01,1.31,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00},
+{1.97,1.92,1.88,1.79,1.79,1.71,1.37,1.59,1.38,1.60,1.35,1.23,1.47,1.30,1.56,1.99,1.93,1.90,1.60,1.78,1.61,1.79,1.57,1.48,1.72,1.40,1.14,1.37,0.89,0.96,0.94,1.07,1.00,1.21,1.30,1.14,0.98,0.96,0.86,0.91,0.83,0.82,0.88,0.82,0.89,1.11,0.87,0.94,0.93,1.02,1.07,0.80,0.79,0.85,0.82,0.80,0.87,0.85,0.93,1.02,0.93,0.77,0.72,0.74,0.71,0.70,0.70,0.71,0.72,0.77,0.74,0.82,0.76,0.79,0.72,0.73,0.76,0.89,0.89,0.82,0.93,0.91,0.86,0.83,0.79,0.73,0.76,0.91,0.89,0.83,0.89,0.89,0.82,0.82,0.76,0.72,0.76,0.86,0.83,0.79,0.82,0.76,0.73,0.94,1.00,0.91,1.37,1.21,1.14,0.98,0.96,0.88,0.89,0.96,1.14,1.07,1.60,1.40,1.61,1.37,1.57,1.48,1.30,1.78,1.93,1.79,1.99,1.92,1.90,1.79,1.59,1.72,1.79,1.30,1.56,1.35,1.38,1.60,1.11,1.07,0.94,1.68,1.86,1.71,1.97,1.68,1.86,1.44,1.49,1.22,1.44,1.49,1.22,0.99,0.99,1.23,1.19,0.98,0.97,0.97,0.98,1.19,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00},
+{1.94,1.97,1.87,1.91,1.85,1.71,1.60,1.77,1.58,1.74,1.51,1.26,1.48,1.39,1.64,1.99,1.97,1.99,1.70,1.85,1.76,1.91,1.76,1.70,1.88,1.55,1.33,1.57,0.96,1.08,1.05,1.31,1.27,1.47,1.54,1.39,1.20,1.11,0.93,0.99,0.90,0.88,0.95,0.88,0.97,1.32,0.92,1.01,0.97,1.10,1.22,0.84,0.80,0.88,0.79,0.79,0.85,0.86,0.92,1.02,0.94,0.82,0.76,0.77,0.72,0.73,0.70,0.72,0.71,0.74,0.74,0.88,0.81,0.85,0.75,0.77,0.82,0.94,0.93,0.86,0.92,0.92,0.86,0.85,0.79,0.74,0.79,0.88,0.85,0.81,0.82,0.83,0.77,0.78,0.73,0.71,0.75,0.79,0.77,0.74,0.77,0.73,0.70,0.86,0.92,0.84,1.14,0.99,0.98,0.91,0.90,0.84,0.83,0.88,0.97,0.94,1.41,1.18,1.39,1.11,1.33,1.24,1.03,1.61,1.80,1.59,1.91,1.84,1.76,1.64,1.38,1.51,1.71,1.26,1.50,1.23,1.19,1.46,0.99,1.00,0.91,1.70,1.85,1.65,1.93,1.54,1.76,1.52,1.48,1.26,1.28,1.39,1.09,0.99,0.97,1.18,1.31,1.01,1.05,0.90,0.93,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00},
+{1.86,1.95,1.82,1.98,1.89,1.71,1.80,1.91,1.77,1.86,1.67,1.34,1.53,1.51,1.72,1.92,1.91,1.99,1.69,1.82,1.80,1.94,1.87,1.86,1.97,1.59,1.44,1.69,1.05,1.24,1.27,1.49,1.50,1.69,1.72,1.63,1.46,1.37,1.00,1.23,0.98,0.95,1.09,0.96,1.16,1.55,0.99,1.25,1.10,1.24,1.41,0.90,0.85,0.94,0.79,0.81,0.85,0.89,0.94,1.09,0.98,0.89,0.82,0.83,0.74,0.77,0.72,0.76,0.73,0.75,0.78,0.94,0.86,0.91,0.79,0.83,0.89,0.99,0.95,0.90,0.90,0.92,0.84,0.86,0.79,0.75,0.81,0.85,0.80,0.78,0.76,0.77,0.73,0.74,0.71,0.71,0.73,0.74,0.74,0.71,0.76,0.72,0.70,0.79,0.85,0.78,0.98,0.92,0.93,0.85,0.87,0.82,0.79,0.81,0.89,0.86,1.16,0.97,1.12,0.95,1.06,1.00,0.93,1.38,1.60,1.35,1.77,1.71,1.57,1.48,1.20,1.28,1.62,1.27,1.46,1.17,1.05,1.34,0.96,0.99,0.90,1.63,1.74,1.50,1.80,1.33,1.58,1.48,1.37,1.21,1.04,1.21,0.97,0.97,0.93,1.05,1.34,1.02,1.14,0.84,0.88,0.92,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00},
+{1.74,1.89,1.76,1.98,1.89,1.71,1.93,1.99,1.91,1.94,1.82,1.46,1.60,1.65,1.80,1.79,1.77,1.92,1.57,1.69,1.74,1.87,1.88,1.94,1.98,1.53,1.45,1.70,1.18,1.32,1.42,1.58,1.65,1.83,1.81,1.81,1.67,1.61,1.19,1.44,1.17,1.11,1.36,1.15,1.41,1.75,1.22,1.50,1.34,1.42,1.61,0.98,0.92,1.03,0.83,0.86,0.89,0.95,0.98,1.23,1.14,0.97,0.89,0.90,0.78,0.82,0.76,0.82,0.77,0.79,0.84,0.98,0.90,0.98,0.83,0.89,0.97,1.03,0.95,0.92,0.86,0.90,0.82,0.86,0.79,0.77,0.84,0.81,0.76,0.76,0.72,0.73,0.70,0.72,0.71,0.73,0.73,0.72,0.74,0.71,0.78,0.74,0.72,0.75,0.80,0.76,0.94,0.88,0.91,0.83,0.87,0.84,0.79,0.76,0.82,0.80,0.97,0.89,0.96,0.88,0.95,0.94,0.87,1.11,1.37,1.10,1.59,1.57,1.37,1.33,1.05,1.08,1.54,1.34,1.46,1.16,0.99,1.26,0.96,1.05,0.92,1.45,1.55,1.27,1.60,1.07,1.34,1.35,1.18,1.07,0.93,0.99,0.90,0.93,0.87,0.96,1.27,0.99,1.15,0.77,0.82,0.85,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00},
+{1.60,1.78,1.68,1.93,1.86,1.71,1.97,1.99,1.99,1.97,1.93,1.60,1.68,1.78,1.86,1.61,1.57,1.79,1.37,1.48,1.59,1.72,1.79,1.92,1.90,1.38,1.35,1.60,1.23,1.30,1.47,1.56,1.71,1.88,1.79,1.92,1.79,1.79,1.30,1.56,1.35,1.37,1.59,1.38,1.60,1.90,1.48,1.72,1.57,1.61,1.79,1.21,1.00,1.30,0.89,0.94,0.96,1.07,1.14,1.40,1.37,1.14,0.96,0.98,0.82,0.88,0.82,0.89,0.83,0.86,0.91,1.02,0.93,1.07,0.87,0.94,1.11,1.02,0.93,0.93,0.82,0.87,0.80,0.85,0.79,0.80,0.85,0.77,0.72,0.74,0.71,0.70,0.70,0.71,0.72,0.77,0.74,0.72,0.76,0.73,0.82,0.79,0.76,0.73,0.79,0.76,0.93,0.86,0.91,0.83,0.89,0.89,0.82,0.72,0.76,0.76,0.89,0.82,0.89,0.82,0.89,0.91,0.83,0.96,1.14,0.97,1.40,1.44,1.19,1.22,0.99,0.98,1.49,1.44,1.49,1.22,0.99,1.23,0.98,1.19,0.97,1.21,1.30,1.00,1.37,0.94,1.07,1.14,0.98,0.96,0.86,0.91,0.83,0.88,0.82,0.89,1.11,0.94,1.07,0.73,0.76,0.79,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00},
+{1.46,1.65,1.60,1.82,1.80,1.71,1.93,1.91,1.99,1.94,1.98,1.74,1.76,1.89,1.89,1.42,1.34,1.61,1.11,1.22,1.36,1.50,1.61,1.81,1.75,1.15,1.17,1.41,1.18,1.19,1.42,1.44,1.65,1.83,1.67,1.94,1.81,1.88,1.32,1.58,1.45,1.57,1.74,1.53,1.70,1.98,1.69,1.87,1.77,1.79,1.92,1.45,1.27,1.55,0.97,1.07,1.11,1.34,1.37,1.59,1.60,1.35,1.07,1.18,0.86,0.93,0.87,0.96,0.90,0.93,0.99,1.03,0.95,1.15,0.90,0.99,1.27,0.98,0.90,0.92,0.78,0.83,0.77,0.84,0.79,0.82,0.86,0.73,0.71,0.73,0.72,0.70,0.73,0.72,0.76,0.81,0.76,0.76,0.82,0.77,0.89,0.85,0.82,0.75,0.80,0.80,0.94,0.88,0.94,0.87,0.95,0.96,0.88,0.72,0.74,0.76,0.83,0.78,0.84,0.79,0.87,0.91,0.83,0.89,0.98,0.92,1.23,1.34,1.05,1.16,0.99,0.96,1.46,1.57,1.54,1.33,1.05,1.26,1.08,1.37,1.10,0.98,1.03,0.92,1.14,0.86,0.95,0.97,0.90,0.89,0.79,0.84,0.77,0.82,0.76,0.82,0.97,0.89,0.98,0.71,0.72,0.74,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00},
+{1.34,1.51,1.53,1.67,1.72,1.71,1.80,1.77,1.91,1.86,1.98,1.86,1.82,1.95,1.89,1.24,1.10,1.41,0.95,0.99,1.09,1.25,1.37,1.63,1.55,0.96,0.98,1.16,1.05,1.00,1.27,1.23,1.50,1.69,1.46,1.86,1.72,1.87,1.24,1.49,1.44,1.69,1.80,1.59,1.69,1.97,1.82,1.94,1.91,1.92,1.99,1.63,1.50,1.74,1.16,1.33,1.38,1.58,1.60,1.77,1.80,1.48,1.21,1.37,0.90,0.97,0.93,1.05,0.97,1.04,1.21,0.99,0.95,1.14,0.92,1.02,1.34,0.94,0.86,0.90,0.74,0.79,0.75,0.81,0.79,0.84,0.86,0.71,0.71,0.73,0.76,0.73,0.77,0.74,0.80,0.85,0.78,0.81,0.89,0.84,0.97,0.92,0.88,0.79,0.85,0.86,0.98,0.92,1.00,0.93,1.06,1.12,0.95,0.74,0.74,0.78,0.79,0.76,0.82,0.79,0.87,0.93,0.85,0.85,0.94,0.90,1.09,1.27,0.99,1.17,1.05,0.96,1.46,1.71,1.62,1.48,1.20,1.34,1.28,1.57,1.35,0.90,0.94,0.85,0.98,0.81,0.89,0.89,0.83,0.82,0.75,0.78,0.73,0.77,0.72,0.76,0.89,0.83,0.91,0.71,0.70,0.72,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00},
+{1.26,1.39,1.48,1.51,1.64,1.71,1.60,1.58,1.77,1.74,1.91,1.94,1.87,1.97,1.85,1.10,0.97,1.22,0.88,0.92,0.95,1.01,1.11,1.39,1.32,0.88,0.90,0.97,0.96,0.93,1.05,0.99,1.27,1.47,1.20,1.70,1.54,1.76,1.08,1.31,1.33,1.70,1.76,1.55,1.57,1.88,1.85,1.91,1.97,1.99,1.99,1.70,1.65,1.85,1.41,1.54,1.61,1.76,1.80,1.91,1.93,1.52,1.26,1.48,0.92,0.99,0.97,1.18,1.09,1.28,1.39,0.94,0.93,1.05,0.92,1.01,1.31,0.88,0.81,0.86,0.72,0.75,0.74,0.79,0.79,0.86,0.85,0.71,0.73,0.75,0.82,0.77,0.83,0.78,0.85,0.88,0.81,0.88,0.97,0.90,1.18,1.00,0.93,0.86,0.92,0.94,1.14,0.99,1.24,1.03,1.33,1.39,1.11,0.79,0.77,0.84,0.79,0.77,0.84,0.83,0.90,0.98,0.91,0.85,0.92,0.91,1.02,1.26,1.00,1.23,1.19,0.99,1.50,1.84,1.71,1.64,1.38,1.46,1.51,1.76,1.59,0.84,0.88,0.80,0.94,0.79,0.86,0.82,0.77,0.76,0.74,0.74,0.71,0.73,0.70,0.72,0.82,0.77,0.85,0.74,0.70,0.73,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00}
+}
--- /dev/null
+++ b/WinQuake/anorms.h
@@ -1,0 +1,181 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+{-0.525731, 0.000000, 0.850651}, 
+{-0.442863, 0.238856, 0.864188}, 
+{-0.295242, 0.000000, 0.955423}, 
+{-0.309017, 0.500000, 0.809017}, 
+{-0.162460, 0.262866, 0.951056}, 
+{0.000000, 0.000000, 1.000000}, 
+{0.000000, 0.850651, 0.525731}, 
+{-0.147621, 0.716567, 0.681718}, 
+{0.147621, 0.716567, 0.681718}, 
+{0.000000, 0.525731, 0.850651}, 
+{0.309017, 0.500000, 0.809017}, 
+{0.525731, 0.000000, 0.850651}, 
+{0.295242, 0.000000, 0.955423}, 
+{0.442863, 0.238856, 0.864188}, 
+{0.162460, 0.262866, 0.951056}, 
+{-0.681718, 0.147621, 0.716567}, 
+{-0.809017, 0.309017, 0.500000}, 
+{-0.587785, 0.425325, 0.688191}, 
+{-0.850651, 0.525731, 0.000000}, 
+{-0.864188, 0.442863, 0.238856}, 
+{-0.716567, 0.681718, 0.147621}, 
+{-0.688191, 0.587785, 0.425325}, 
+{-0.500000, 0.809017, 0.309017}, 
+{-0.238856, 0.864188, 0.442863}, 
+{-0.425325, 0.688191, 0.587785}, 
+{-0.716567, 0.681718, -0.147621}, 
+{-0.500000, 0.809017, -0.309017}, 
+{-0.525731, 0.850651, 0.000000}, 
+{0.000000, 0.850651, -0.525731}, 
+{-0.238856, 0.864188, -0.442863}, 
+{0.000000, 0.955423, -0.295242}, 
+{-0.262866, 0.951056, -0.162460}, 
+{0.000000, 1.000000, 0.000000}, 
+{0.000000, 0.955423, 0.295242}, 
+{-0.262866, 0.951056, 0.162460}, 
+{0.238856, 0.864188, 0.442863}, 
+{0.262866, 0.951056, 0.162460}, 
+{0.500000, 0.809017, 0.309017}, 
+{0.238856, 0.864188, -0.442863}, 
+{0.262866, 0.951056, -0.162460}, 
+{0.500000, 0.809017, -0.309017}, 
+{0.850651, 0.525731, 0.000000}, 
+{0.716567, 0.681718, 0.147621}, 
+{0.716567, 0.681718, -0.147621}, 
+{0.525731, 0.850651, 0.000000}, 
+{0.425325, 0.688191, 0.587785}, 
+{0.864188, 0.442863, 0.238856}, 
+{0.688191, 0.587785, 0.425325}, 
+{0.809017, 0.309017, 0.500000}, 
+{0.681718, 0.147621, 0.716567}, 
+{0.587785, 0.425325, 0.688191}, 
+{0.955423, 0.295242, 0.000000}, 
+{1.000000, 0.000000, 0.000000}, 
+{0.951056, 0.162460, 0.262866}, 
+{0.850651, -0.525731, 0.000000}, 
+{0.955423, -0.295242, 0.000000}, 
+{0.864188, -0.442863, 0.238856}, 
+{0.951056, -0.162460, 0.262866}, 
+{0.809017, -0.309017, 0.500000}, 
+{0.681718, -0.147621, 0.716567}, 
+{0.850651, 0.000000, 0.525731}, 
+{0.864188, 0.442863, -0.238856}, 
+{0.809017, 0.309017, -0.500000}, 
+{0.951056, 0.162460, -0.262866}, 
+{0.525731, 0.000000, -0.850651}, 
+{0.681718, 0.147621, -0.716567}, 
+{0.681718, -0.147621, -0.716567}, 
+{0.850651, 0.000000, -0.525731}, 
+{0.809017, -0.309017, -0.500000}, 
+{0.864188, -0.442863, -0.238856}, 
+{0.951056, -0.162460, -0.262866}, 
+{0.147621, 0.716567, -0.681718}, 
+{0.309017, 0.500000, -0.809017}, 
+{0.425325, 0.688191, -0.587785}, 
+{0.442863, 0.238856, -0.864188}, 
+{0.587785, 0.425325, -0.688191}, 
+{0.688191, 0.587785, -0.425325}, 
+{-0.147621, 0.716567, -0.681718}, 
+{-0.309017, 0.500000, -0.809017}, 
+{0.000000, 0.525731, -0.850651}, 
+{-0.525731, 0.000000, -0.850651}, 
+{-0.442863, 0.238856, -0.864188}, 
+{-0.295242, 0.000000, -0.955423}, 
+{-0.162460, 0.262866, -0.951056}, 
+{0.000000, 0.000000, -1.000000}, 
+{0.295242, 0.000000, -0.955423}, 
+{0.162460, 0.262866, -0.951056}, 
+{-0.442863, -0.238856, -0.864188}, 
+{-0.309017, -0.500000, -0.809017}, 
+{-0.162460, -0.262866, -0.951056}, 
+{0.000000, -0.850651, -0.525731}, 
+{-0.147621, -0.716567, -0.681718}, 
+{0.147621, -0.716567, -0.681718}, 
+{0.000000, -0.525731, -0.850651}, 
+{0.309017, -0.500000, -0.809017}, 
+{0.442863, -0.238856, -0.864188}, 
+{0.162460, -0.262866, -0.951056}, 
+{0.238856, -0.864188, -0.442863}, 
+{0.500000, -0.809017, -0.309017}, 
+{0.425325, -0.688191, -0.587785}, 
+{0.716567, -0.681718, -0.147621}, 
+{0.688191, -0.587785, -0.425325}, 
+{0.587785, -0.425325, -0.688191}, 
+{0.000000, -0.955423, -0.295242}, 
+{0.000000, -1.000000, 0.000000}, 
+{0.262866, -0.951056, -0.162460}, 
+{0.000000, -0.850651, 0.525731}, 
+{0.000000, -0.955423, 0.295242}, 
+{0.238856, -0.864188, 0.442863}, 
+{0.262866, -0.951056, 0.162460}, 
+{0.500000, -0.809017, 0.309017}, 
+{0.716567, -0.681718, 0.147621}, 
+{0.525731, -0.850651, 0.000000}, 
+{-0.238856, -0.864188, -0.442863}, 
+{-0.500000, -0.809017, -0.309017}, 
+{-0.262866, -0.951056, -0.162460}, 
+{-0.850651, -0.525731, 0.000000}, 
+{-0.716567, -0.681718, -0.147621}, 
+{-0.716567, -0.681718, 0.147621}, 
+{-0.525731, -0.850651, 0.000000}, 
+{-0.500000, -0.809017, 0.309017}, 
+{-0.238856, -0.864188, 0.442863}, 
+{-0.262866, -0.951056, 0.162460}, 
+{-0.864188, -0.442863, 0.238856}, 
+{-0.809017, -0.309017, 0.500000}, 
+{-0.688191, -0.587785, 0.425325}, 
+{-0.681718, -0.147621, 0.716567}, 
+{-0.442863, -0.238856, 0.864188}, 
+{-0.587785, -0.425325, 0.688191}, 
+{-0.309017, -0.500000, 0.809017}, 
+{-0.147621, -0.716567, 0.681718}, 
+{-0.425325, -0.688191, 0.587785}, 
+{-0.162460, -0.262866, 0.951056}, 
+{0.442863, -0.238856, 0.864188}, 
+{0.162460, -0.262866, 0.951056}, 
+{0.309017, -0.500000, 0.809017}, 
+{0.147621, -0.716567, 0.681718}, 
+{0.000000, -0.525731, 0.850651}, 
+{0.425325, -0.688191, 0.587785}, 
+{0.587785, -0.425325, 0.688191}, 
+{0.688191, -0.587785, 0.425325}, 
+{-0.955423, 0.295242, 0.000000}, 
+{-0.951056, 0.162460, 0.262866}, 
+{-1.000000, 0.000000, 0.000000}, 
+{-0.850651, 0.000000, 0.525731}, 
+{-0.955423, -0.295242, 0.000000}, 
+{-0.951056, -0.162460, 0.262866}, 
+{-0.864188, 0.442863, -0.238856}, 
+{-0.951056, 0.162460, -0.262866}, 
+{-0.809017, 0.309017, -0.500000}, 
+{-0.864188, -0.442863, -0.238856}, 
+{-0.951056, -0.162460, -0.262866}, 
+{-0.809017, -0.309017, -0.500000}, 
+{-0.681718, 0.147621, -0.716567}, 
+{-0.681718, -0.147621, -0.716567}, 
+{-0.850651, 0.000000, -0.525731}, 
+{-0.688191, 0.587785, -0.425325}, 
+{-0.587785, 0.425325, -0.688191}, 
+{-0.425325, 0.688191, -0.587785}, 
+{-0.425325, -0.688191, -0.587785}, 
+{-0.587785, -0.425325, -0.688191}, 
+{-0.688191, -0.587785, -0.425325}, 
--- /dev/null
+++ b/WinQuake/asm_draw.h
@@ -1,0 +1,151 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+//
+// asm_draw.h
+//
+// Include file for asm drawing routines.
+//
+
+//
+// !!! note that this file must match the corresponding C structures at all
+// times !!!
+//
+
+// !!! if this is changed, it must be changed in r_local.h too !!!
+#define	NEAR_CLIP	0.01
+
+// !!! if this is changed, it must be changed in r_local.h too !!!
+#define	CYCLE	128
+
+// espan_t structure
+// !!! if this is changed, it must be changed in r_shared.h too !!!
+#define espan_t_u    	0
+#define espan_t_v	    4
+#define espan_t_count   8
+#define espan_t_pnext	12
+#define espan_t_size    16
+
+// sspan_t structure
+// !!! if this is changed, it must be changed in d_local.h too !!!
+#define sspan_t_u    	0
+#define sspan_t_v	    4
+#define sspan_t_count   8
+#define sspan_t_size    12
+
+// spanpackage_t structure
+// !!! if this is changed, it must be changed in d_polyset.c too !!!
+#define spanpackage_t_pdest				0
+#define spanpackage_t_pz				4
+#define spanpackage_t_count				8
+#define spanpackage_t_ptex				12
+#define spanpackage_t_sfrac				16
+#define spanpackage_t_tfrac				20
+#define spanpackage_t_light				24
+#define spanpackage_t_zi				28
+#define spanpackage_t_size				32 
+
+// edge_t structure
+// !!! if this is changed, it must be changed in r_shared.h too !!!
+#define et_u			0
+#define et_u_step		4
+#define et_prev			8
+#define et_next			12
+#define et_surfs		16
+#define et_nextremove	20
+#define et_nearzi		24
+#define et_owner		28
+#define et_size			32
+
+// surf_t structure
+// !!! if this is changed, it must be changed in r_shared.h too !!!
+#define SURF_T_SHIFT	6
+#define st_next			0
+#define st_prev			4
+#define st_spans		8
+#define st_key			12
+#define st_last_u		16
+#define st_spanstate	20
+#define st_flags		24
+#define st_data			28
+#define st_entity		32
+#define st_nearzi		36
+#define st_insubmodel	40
+#define st_d_ziorigin	44
+#define st_d_zistepu	48
+#define st_d_zistepv	52
+#define st_pad			56
+#define st_size			64
+
+// clipplane_t structure
+// !!! if this is changed, it must be changed in r_local.h too !!!
+#define cp_normal		0
+#define cp_dist			12
+#define cp_next			16
+#define cp_leftedge		20
+#define cp_rightedge	21
+#define cp_reserved		22
+#define cp_size			24
+
+// medge_t structure
+// !!! if this is changed, it must be changed in model.h too !!!
+#define me_v				0
+#define me_cachededgeoffset	4
+#define me_size				8
+
+// mvertex_t structure
+// !!! if this is changed, it must be changed in model.h too !!!
+#define mv_position		0
+#define mv_size			12
+
+// refdef_t structure
+// !!! if this is changed, it must be changed in render.h too !!!
+#define rd_vrect					0
+#define rd_aliasvrect				20
+#define rd_vrectright				40
+#define rd_vrectbottom				44
+#define rd_aliasvrectright			48
+#define rd_aliasvrectbottom			52
+#define rd_vrectrightedge			56
+#define rd_fvrectx					60
+#define rd_fvrecty					64
+#define rd_fvrectx_adj				68
+#define rd_fvrecty_adj				72
+#define rd_vrect_x_adj_shift20		76
+#define rd_vrectright_adj_shift20	80
+#define rd_fvrectright_adj			84
+#define rd_fvrectbottom_adj			88
+#define rd_fvrectright				92
+#define rd_fvrectbottom				96
+#define rd_horizontalFieldOfView	100
+#define rd_xOrigin					104
+#define rd_yOrigin					108
+#define rd_vieworg					112
+#define rd_viewangles				124
+#define rd_ambientlight				136
+#define rd_size						140
+
+// mtriangle_t structure
+// !!! if this is changed, it must be changed in model.h too !!!
+#define mtri_facesfront		0
+#define mtri_vertindex		4
+#define mtri_size			16	// !!! if this changes, array indexing in !!!
+								// !!! d_polysa.s must be changed to match !!!
+#define mtri_shift			4
+
--- /dev/null
+++ b/WinQuake/asm_i386.h
@@ -1,0 +1,97 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+
+#ifndef __ASM_I386__
+#define __ASM_I386__
+
+#ifdef ELF
+#define C(label) label
+#else
+#define C(label) _##label
+#endif
+
+//
+// !!! note that this file must match the corresponding C structures at all
+// times !!!
+//
+
+// plane_t structure
+// !!! if this is changed, it must be changed in model.h too !!!
+// !!! if the size of this is changed, the array lookup in SV_HullPointContents
+//     must be changed too !!!
+#define pl_normal	0
+#define pl_dist		12
+#define pl_type		16
+#define pl_signbits	17
+#define pl_pad		18
+#define pl_size		20
+
+// hull_t structure
+// !!! if this is changed, it must be changed in model.h too !!!
+#define	hu_clipnodes		0
+#define	hu_planes			4
+#define	hu_firstclipnode	8
+#define	hu_lastclipnode		12
+#define	hu_clip_mins		16
+#define	hu_clip_maxs		28
+#define hu_size  			40
+
+// dnode_t structure
+// !!! if this is changed, it must be changed in bspfile.h too !!!
+#define	nd_planenum		0
+#define	nd_children		4
+#define	nd_mins			8
+#define	nd_maxs			20
+#define	nd_firstface	32
+#define	nd_numfaces		36
+#define nd_size			40
+
+// sfxcache_t structure
+// !!! if this is changed, it much be changed in sound.h too !!!
+#define sfxc_length		0
+#define sfxc_loopstart	4
+#define sfxc_speed		8
+#define sfxc_width		12
+#define sfxc_stereo		16
+#define sfxc_data		20
+
+// channel_t structure
+// !!! if this is changed, it much be changed in sound.h too !!!
+#define ch_sfx			0
+#define ch_leftvol		4
+#define ch_rightvol		8
+#define ch_end			12
+#define ch_pos			16
+#define ch_looping		20
+#define ch_entnum		24
+#define ch_entchannel	28
+#define ch_origin		32
+#define ch_dist_mult	44
+#define ch_master_vol	48
+#define ch_size			52
+
+// portable_samplepair_t structure
+// !!! if this is changed, it much be changed in sound.h too !!!
+#define psp_left		0
+#define psp_right		4
+#define psp_size		8
+
+#endif
+
--- /dev/null
+++ b/WinQuake/block16.h
@@ -1,0 +1,142 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+LEnter16_16:
+	movb	(%esi),%al
+	movb	(%esi,%ebx,),%cl
+	movb	%dh,%ah
+	addl	%ebp,%edx
+	movb	%dh,%ch
+	leal	(%esi,%ebx,2),%esi
+	movw	0x12345678(,%eax,2),%ax
+LBPatch0:
+	addl	%ebp,%edx
+	movw	%ax,(%edi)
+	movw	0x12345678(,%ecx,2),%cx
+LBPatch1:
+	movw	%cx,2(%edi)
+	addl	$0x4,%edi
+
+	movb	(%esi),%al
+	movb	(%esi,%ebx,),%cl
+	movb	%dh,%ah
+	addl	%ebp,%edx
+	movb	%dh,%ch
+	leal	(%esi,%ebx,2),%esi
+	movw	0x12345678(,%eax,2),%ax
+LBPatch2:
+	addl	%ebp,%edx
+	movw	%ax,(%edi)
+	movw	0x12345678(,%ecx,2),%cx
+LBPatch3:
+	movw	%cx,2(%edi)
+	addl	$0x4,%edi
+
+	movb	(%esi),%al
+	movb	(%esi,%ebx,),%cl
+	movb	%dh,%ah
+	addl	%ebp,%edx
+	movb	%dh,%ch
+	leal	(%esi,%ebx,2),%esi
+	movw	0x12345678(,%eax,2),%ax
+LBPatch4:
+	addl	%ebp,%edx
+	movw	%ax,(%edi)
+	movw	0x12345678(,%ecx,2),%cx
+LBPatch5:
+	movw	%cx,2(%edi)
+	addl	$0x4,%edi
+
+	movb	(%esi),%al
+	movb	(%esi,%ebx,),%cl
+	movb	%dh,%ah
+	addl	%ebp,%edx
+	movb	%dh,%ch
+	leal	(%esi,%ebx,2),%esi
+	movw	0x12345678(,%eax,2),%ax
+LBPatch6:
+	addl	%ebp,%edx
+	movw	%ax,(%edi)
+	movw	0x12345678(,%ecx,2),%cx
+LBPatch7:
+	movw	%cx,2(%edi)
+	addl	$0x4,%edi
+
+LEnter8_16:
+	movb	(%esi),%al
+	movb	(%esi,%ebx,),%cl
+	movb	%dh,%ah
+	addl	%ebp,%edx
+	movb	%dh,%ch
+	leal	(%esi,%ebx,2),%esi
+	movw	0x12345678(,%eax,2),%ax
+LBPatch8:
+	addl	%ebp,%edx
+	movw	%ax,(%edi)
+	movw	0x12345678(,%ecx,2),%cx
+LBPatch9:
+	movw	%cx,2(%edi)
+	addl	$0x4,%edi
+
+	movb	(%esi),%al
+	movb	(%esi,%ebx,),%cl
+	movb	%dh,%ah
+	addl	%ebp,%edx
+	movb	%dh,%ch
+	leal	(%esi,%ebx,2),%esi
+	movw	0x12345678(,%eax,2),%ax
+LBPatch10:
+	addl	%ebp,%edx
+	movw	%ax,(%edi)
+	movw	0x12345678(,%ecx,2),%cx
+LBPatch11:
+	movw	%cx,2(%edi)
+	addl	$0x4,%edi
+
+LEnter4_16:
+	movb	(%esi),%al
+	movb	(%esi,%ebx,),%cl
+	movb	%dh,%ah
+	addl	%ebp,%edx
+	movb	%dh,%ch
+	leal	(%esi,%ebx,2),%esi
+	movw	0x12345678(,%eax,2),%ax
+LBPatch12:
+	addl	%ebp,%edx
+	movw	%ax,(%edi)
+	movw	0x12345678(,%ecx,2),%cx
+LBPatch13:
+	movw	%cx,2(%edi)
+	addl	$0x4,%edi
+
+LEnter2_16:
+	movb	(%esi),%al
+	movb	(%esi,%ebx,),%cl
+	movb	%dh,%ah
+	addl	%ebp,%edx
+	movb	%dh,%ch
+	leal	(%esi,%ebx,2),%esi
+	movw	0x12345678(,%eax,2),%ax
+LBPatch14:
+	addl	%ebp,%edx
+	movw	%ax,(%edi)
+	movw	0x12345678(,%ecx,2),%cx
+LBPatch15:
+	movw	%cx,2(%edi)
+	addl	$0x4,%edi
--- /dev/null
+++ b/WinQuake/block8.h
@@ -1,0 +1,143 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+LEnter16_8:
+	movb	(%esi),%al
+	movb	(%esi,%ebx,),%cl
+	movb	%dh,%ah
+	addl	%ebp,%edx
+	movb	%dh,%ch
+	leal	(%esi,%ebx,2),%esi
+	movb	0x12345678(%eax),%al
+LBPatch0:
+	addl	%ebp,%edx
+	movb	%al,(%edi)
+	movb	0x12345678(%ecx),%cl
+LBPatch1:
+	movb	%cl,1(%edi)
+	addl	$0x2,%edi
+
+	movb	(%esi),%al
+	movb	(%esi,%ebx,),%cl
+	movb	%dh,%ah
+	addl	%ebp,%edx
+	movb	%dh,%ch
+	leal	(%esi,%ebx,2),%esi
+	movb	0x12345678(%eax),%al
+LBPatch2:
+	addl	%ebp,%edx
+	movb	%al,(%edi)
+	movb	0x12345678(%ecx),%cl
+LBPatch3:
+	movb	%cl,1(%edi)
+	addl	$0x2,%edi
+
+	movb	(%esi),%al
+	movb	(%esi,%ebx,),%cl
+	movb	%dh,%ah
+	addl	%ebp,%edx
+	movb	%dh,%ch
+	leal	(%esi,%ebx,2),%esi
+	movb	0x12345678(%eax),%al
+LBPatch4:
+	addl	%ebp,%edx
+	movb	%al,(%edi)
+	movb	0x12345678(%ecx),%cl
+LBPatch5:
+	movb	%cl,1(%edi)
+	addl	$0x2,%edi
+
+	movb	(%esi),%al
+	movb	(%esi,%ebx,),%cl
+	movb	%dh,%ah
+	addl	%ebp,%edx
+	movb	%dh,%ch
+	leal	(%esi,%ebx,2),%esi
+	movb	0x12345678(%eax),%al
+LBPatch6:
+	addl	%ebp,%edx
+	movb	%al,(%edi)
+	movb	0x12345678(%ecx),%cl
+LBPatch7:
+	movb	%cl,1(%edi)
+	addl	$0x2,%edi
+
+LEnter8_8:
+	movb	(%esi),%al
+	movb	(%esi,%ebx,),%cl
+	movb	%dh,%ah
+	addl	%ebp,%edx
+	movb	%dh,%ch
+	leal	(%esi,%ebx,2),%esi
+	movb	0x12345678(%eax),%al
+LBPatch8:
+	addl	%ebp,%edx
+	movb	%al,(%edi)
+	movb	0x12345678(%ecx),%cl
+LBPatch9:
+	movb	%cl,1(%edi)
+	addl	$0x2,%edi
+
+	movb	(%esi),%al
+	movb	(%esi,%ebx,),%cl
+	movb	%dh,%ah
+	addl	%ebp,%edx
+	movb	%dh,%ch
+	leal	(%esi,%ebx,2),%esi
+	movb	0x12345678(%eax),%al
+LBPatch10:
+	addl	%ebp,%edx
+	movb	%al,(%edi)
+	movb	0x12345678(%ecx),%cl
+LBPatch11:
+	movb	%cl,1(%edi)
+	addl	$0x2,%edi
+
+LEnter4_8:
+	movb	(%esi),%al
+	movb	(%esi,%ebx,),%cl
+	movb	%dh,%ah
+	addl	%ebp,%edx
+	movb	%dh,%ch
+	leal	(%esi,%ebx,2),%esi
+	movb	0x12345678(%eax),%al
+LBPatch12:
+	addl	%ebp,%edx
+	movb	%al,(%edi)
+	movb	0x12345678(%ecx),%cl
+LBPatch13:
+	movb	%cl,1(%edi)
+	addl	$0x2,%edi
+
+LEnter2_8:
+	movb	(%esi),%al
+	movb	(%esi,%ebx,),%cl
+	movb	%dh,%ah
+	addl	%ebp,%edx
+	movb	%dh,%ch
+	leal	(%esi,%ebx,2),%esi
+	movb	0x12345678(%eax),%al
+LBPatch14:
+	addl	%ebp,%edx
+	movb	%al,(%edi)
+	movb	0x12345678(%ecx),%cl
+LBPatch15:
+	movb	%cl,1(%edi)
+	addl	$0x2,%edi
+
--- /dev/null
+++ b/WinQuake/bspfile.h
@@ -1,0 +1,324 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+
+
+// upper design bounds
+
+#define	MAX_MAP_HULLS		4
+
+#define	MAX_MAP_MODELS		256
+#define	MAX_MAP_BRUSHES		4096
+#define	MAX_MAP_ENTITIES	1024
+#define	MAX_MAP_ENTSTRING	65536
+
+#define	MAX_MAP_PLANES		32767
+#define	MAX_MAP_NODES		32767		// because negative shorts are contents
+#define	MAX_MAP_CLIPNODES	32767		//
+#define	MAX_MAP_LEAFS		8192
+#define	MAX_MAP_VERTS		65535
+#define	MAX_MAP_FACES		65535
+#define	MAX_MAP_MARKSURFACES 65535
+#define	MAX_MAP_TEXINFO		4096
+#define	MAX_MAP_EDGES		256000
+#define	MAX_MAP_SURFEDGES	512000
+#define	MAX_MAP_TEXTURES	512
+#define	MAX_MAP_MIPTEX		0x200000
+#define	MAX_MAP_LIGHTING	0x100000
+#define	MAX_MAP_VISIBILITY	0x100000
+
+#define	MAX_MAP_PORTALS		65536
+
+// key / value pair sizes
+
+#define	MAX_KEY		32
+#define	MAX_VALUE	1024
+
+//=============================================================================
+
+
+#define BSPVERSION	29
+#define	TOOLVERSION	2
+
+typedef struct
+{
+	int		fileofs, filelen;
+} lump_t;
+
+#define	LUMP_ENTITIES	0
+#define	LUMP_PLANES		1
+#define	LUMP_TEXTURES	2
+#define	LUMP_VERTEXES	3
+#define	LUMP_VISIBILITY	4
+#define	LUMP_NODES		5
+#define	LUMP_TEXINFO	6
+#define	LUMP_FACES		7
+#define	LUMP_LIGHTING	8
+#define	LUMP_CLIPNODES	9
+#define	LUMP_LEAFS		10
+#define	LUMP_MARKSURFACES 11
+#define	LUMP_EDGES		12
+#define	LUMP_SURFEDGES	13
+#define	LUMP_MODELS		14
+
+#define	HEADER_LUMPS	15
+
+typedef struct
+{
+	float		mins[3], maxs[3];
+	float		origin[3];
+	int			headnode[MAX_MAP_HULLS];
+	int			visleafs;		// not including the solid leaf 0
+	int			firstface, numfaces;
+} dmodel_t;
+
+typedef struct
+{
+	int			version;	
+	lump_t		lumps[HEADER_LUMPS];
+} dheader_t;
+
+typedef struct
+{
+	int			nummiptex;
+	int			dataofs[4];		// [nummiptex]
+} dmiptexlump_t;
+
+#define	MIPLEVELS	4
+typedef struct miptex_s
+{
+	char		name[16];
+	unsigned	width, height;
+	unsigned	offsets[MIPLEVELS];		// four mip maps stored
+} miptex_t;
+
+
+typedef struct
+{
+	float	point[3];
+} dvertex_t;
+
+
+// 0-2 are axial planes
+#define	PLANE_X			0
+#define	PLANE_Y			1
+#define	PLANE_Z			2
+
+// 3-5 are non-axial planes snapped to the nearest
+#define	PLANE_ANYX		3
+#define	PLANE_ANYY		4
+#define	PLANE_ANYZ		5
+
+typedef struct
+{
+	float	normal[3];
+	float	dist;
+	int		type;		// PLANE_X - PLANE_ANYZ ?remove? trivial to regenerate
+} dplane_t;
+
+
+
+#define	CONTENTS_EMPTY		-1
+#define	CONTENTS_SOLID		-2
+#define	CONTENTS_WATER		-3
+#define	CONTENTS_SLIME		-4
+#define	CONTENTS_LAVA		-5
+#define	CONTENTS_SKY		-6
+#define	CONTENTS_ORIGIN		-7		// removed at csg time
+#define	CONTENTS_CLIP		-8		// changed to contents_solid
+
+#define	CONTENTS_CURRENT_0		-9
+#define	CONTENTS_CURRENT_90		-10
+#define	CONTENTS_CURRENT_180	-11
+#define	CONTENTS_CURRENT_270	-12
+#define	CONTENTS_CURRENT_UP		-13
+#define	CONTENTS_CURRENT_DOWN	-14
+
+
+// !!! if this is changed, it must be changed in asm_i386.h too !!!
+typedef struct
+{
+	int			planenum;
+	short		children[2];	// negative numbers are -(leafs+1), not nodes
+	short		mins[3];		// for sphere culling
+	short		maxs[3];
+	unsigned short	firstface;
+	unsigned short	numfaces;	// counting both sides
+} dnode_t;
+
+typedef struct
+{
+	int			planenum;
+	short		children[2];	// negative numbers are contents
+} dclipnode_t;
+
+
+typedef struct texinfo_s
+{
+	float		vecs[2][4];		// [s/t][xyz offset]
+	int			miptex;
+	int			flags;
+} texinfo_t;
+#define	TEX_SPECIAL		1		// sky or slime, no lightmap or 256 subdivision
+
+// note that edge 0 is never used, because negative edge nums are used for
+// counterclockwise use of the edge in a face
+typedef struct
+{
+	unsigned short	v[2];		// vertex numbers
+} dedge_t;
+
+#define	MAXLIGHTMAPS	4
+typedef struct
+{
+	short		planenum;
+	short		side;
+
+	int			firstedge;		// we must support > 64k edges
+	short		numedges;	
+	short		texinfo;
+
+// lighting info
+	byte		styles[MAXLIGHTMAPS];
+	int			lightofs;		// start of [numstyles*surfsize] samples
+} dface_t;
+
+
+
+#define	AMBIENT_WATER	0
+#define	AMBIENT_SKY		1
+#define	AMBIENT_SLIME	2
+#define	AMBIENT_LAVA	3
+
+#define	NUM_AMBIENTS			4		// automatic ambient sounds
+
+// leaf 0 is the generic CONTENTS_SOLID leaf, used for all solid areas
+// all other leafs need visibility info
+typedef struct
+{
+	int			contents;
+	int			visofs;				// -1 = no visibility info
+
+	short		mins[3];			// for frustum culling
+	short		maxs[3];
+
+	unsigned short		firstmarksurface;
+	unsigned short		nummarksurfaces;
+
+	byte		ambient_level[NUM_AMBIENTS];
+} dleaf_t;
+
+
+//============================================================================
+
+#ifndef QUAKE_GAME
+
+#define	ANGLE_UP	-1
+#define	ANGLE_DOWN	-2
+
+
+// the utilities get to be lazy and just use large static arrays
+
+extern	int			nummodels;
+extern	dmodel_t	dmodels[MAX_MAP_MODELS];
+
+extern	int			visdatasize;
+extern	byte		dvisdata[MAX_MAP_VISIBILITY];
+
+extern	int			lightdatasize;
+extern	byte		dlightdata[MAX_MAP_LIGHTING];
+
+extern	int			texdatasize;
+extern	byte		dtexdata[MAX_MAP_MIPTEX]; // (dmiptexlump_t)
+
+extern	int			entdatasize;
+extern	char		dentdata[MAX_MAP_ENTSTRING];
+
+extern	int			numleafs;
+extern	dleaf_t		dleafs[MAX_MAP_LEAFS];
+
+extern	int			numplanes;
+extern	dplane_t	dplanes[MAX_MAP_PLANES];
+
+extern	int			numvertexes;
+extern	dvertex_t	dvertexes[MAX_MAP_VERTS];
+
+extern	int			numnodes;
+extern	dnode_t		dnodes[MAX_MAP_NODES];
+
+extern	int			numtexinfo;
+extern	texinfo_t	texinfo[MAX_MAP_TEXINFO];
+
+extern	int			numfaces;
+extern	dface_t		dfaces[MAX_MAP_FACES];
+
+extern	int			numclipnodes;
+extern	dclipnode_t	dclipnodes[MAX_MAP_CLIPNODES];
+
+extern	int			numedges;
+extern	dedge_t		dedges[MAX_MAP_EDGES];
+
+extern	int			nummarksurfaces;
+extern	unsigned short	dmarksurfaces[MAX_MAP_MARKSURFACES];
+
+extern	int			numsurfedges;
+extern	int			dsurfedges[MAX_MAP_SURFEDGES];
+
+
+void DecompressVis (byte *in, byte *decompressed);
+int CompressVis (byte *vis, byte *dest);
+
+void	LoadBSPFile (char *filename);
+void	WriteBSPFile (char *filename);
+void	PrintBSPFileSizes (void);
+
+//===============
+
+
+typedef struct epair_s
+{
+	struct epair_s	*next;
+	char	*key;
+	char	*value;
+} epair_t;
+
+typedef struct
+{
+	vec3_t		origin;
+	int			firstbrush;
+	int			numbrushes;
+	epair_t		*epairs;
+} entity_t;
+
+extern	int			num_entities;
+extern	entity_t	entities[MAX_MAP_ENTITIES];
+
+void	ParseEntities (void);
+void	UnparseEntities (void);
+
+void 	SetKeyValue (entity_t *ent, char *key, char *value);
+char 	*ValueForKey (entity_t *ent, char *key);
+// will return "" if not present
+
+vec_t	FloatForKey (entity_t *ent, char *key);
+void 	GetVectorForKey (entity_t *ent, char *key, vec3_t vec);
+
+epair_t *ParseEpair (void);
+
+#endif
--- /dev/null
+++ b/WinQuake/cd_audio.c
@@ -1,0 +1,886 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// Quake is a trademark of Id Software, Inc., (c) 1996 Id Software, Inc. All
+// rights reserved.
+
+#include <dpmi.h>
+#include "quakedef.h"
+#include "dosisms.h"
+
+extern	cvar_t	bgmvolume;
+
+#define ADDRESS_MODE_HSG		0
+#define ADDRESS_MODE_RED_BOOK	1
+
+#define STATUS_ERROR_BIT	0x8000
+#define STATUS_BUSY_BIT		0x0200
+#define STATUS_DONE_BIT		0x0100
+#define STATUS_ERROR_MASK	0x00ff
+
+#define ERROR_WRITE_PROTECT		0
+#define ERROR_UNKNOWN_UNIT		1
+#define ERROR_DRIVE_NOT_READY	2
+#define ERROR_UNKNOWN_COMMAND	3
+#define ERROR_CRC_ERROR			4
+#define ERROR_BAD_REQUEST_LEN	5
+#define ERROR_SEEK_ERROR		6
+#define ERROR_UNKNOWN_MEDIA		7
+#define ERROR_SECTOR_NOT_FOUND	8
+#define ERROR_OUT_OF_PAPER		9
+#define ERROR_WRITE_FAULT		10
+#define ERROR_READ_FAULT		11
+#define ERROR_GENERAL_FAILURE	12
+#define ERROR_RESERVED_13		13
+#define ERROR_RESERVED_14		14
+#define ERROR_BAD_DISK_CHANGE	15
+
+#define COMMAND_READ			3
+#define COMMAND_WRITE			12
+#define COMMAND_PLAY_AUDIO		132
+#define COMMAND_STOP_AUDIO		133
+#define COMMAND_RESUME_AUDIO	136
+
+#define READ_REQUEST_AUDIO_CHANNEL_INFO		4
+#define READ_REQUEST_DEVICE_STATUS			6
+#define READ_REQUEST_MEDIA_CHANGE			9
+#define READ_REQUEST_AUDIO_DISK_INFO		10
+#define READ_REQUEST_AUDIO_TRACK_INFO		11
+#define READ_REQUEST_AUDIO_STATUS			15
+
+#define WRITE_REQUEST_EJECT					0
+#define WRITE_REQUEST_RESET					2
+#define WRITE_REQUEST_AUDIO_CHANNEL_INFO	3
+
+#define STATUS_DOOR_OPEN					0x00000001
+#define STATUS_DOOR_UNLOCKED				0x00000002
+#define STATUS_RAW_SUPPORT					0x00000004
+#define STATUS_READ_WRITE					0x00000008
+#define STATUS_AUDIO_SUPPORT				0x00000010
+#define STATUS_INTERLEAVE_SUPPORT			0x00000020
+#define STATUS_BIT_6_RESERVED				0x00000040
+#define STATUS_PREFETCH_SUPPORT				0x00000080
+#define STATUS_AUDIO_MANIPLUATION_SUPPORT	0x00000100
+#define STATUS_RED_BOOK_ADDRESS_SUPPORT		0x00000200
+
+#define MEDIA_NOT_CHANGED		1
+#define MEDIA_STATUS_UNKNOWN	0
+#define MEDIA_CHANGED			-1
+
+#define AUDIO_CONTROL_MASK				0xd0
+#define AUDIO_CONTROL_DATA_TRACK		0x40
+#define AUDIO_CONTROL_AUDIO_2_TRACK		0x00
+#define AUDIO_CONTROL_AUDIO_2P_TRACK	0x10
+#define AUDIO_CONTROL_AUDIO_4_TRACK		0x80
+#define AUDIO_CONTROL_AUDIO_4P_TRACK	0x90
+
+#define AUDIO_STATUS_PAUSED				0x0001
+
+#pragma pack(1)
+
+struct playAudioRequest
+{
+	char	addressingMode;
+	int		startLocation;
+	int		sectors;
+};
+
+struct readRequest
+{
+	char	mediaDescriptor;
+	short	bufferOffset;
+	short	bufferSegment;
+	short	length;
+	short	startSector;
+	int		volumeID;
+};
+
+struct writeRequest
+{
+	char	mediaDescriptor;
+	short	bufferOffset;
+	short	bufferSegment;
+	short	length;
+	short	startSector;
+	int		volumeID;
+};
+
+struct cd_request
+{
+	char	headerLength;
+	char	unit;
+	char	command;
+	short	status;
+	char	reserved[8];
+	union
+	{
+		struct	playAudioRequest	playAudio;
+		struct	readRequest			read;
+		struct	writeRequest		write;
+	} x;
+};
+
+
+struct audioChannelInfo_s
+{
+	char	code;
+	char	channel0input;
+	char	channel0volume;
+	char	channel1input;
+	char	channel1volume;
+	char	channel2input;
+	char	channel2volume;
+	char	channel3input;
+	char	channel3volume;
+};
+
+struct deviceStatus_s
+{
+	char	code;
+	int		status;
+};
+
+struct mediaChange_s
+{
+	char	code;
+	char	status;
+};
+
+struct audioDiskInfo_s
+{
+	char	code;
+	char	lowTrack;
+	char	highTrack;
+	int		leadOutStart;
+};
+
+struct audioTrackInfo_s
+{
+	char	code;
+	char	track;
+	int		start;
+	char	control;
+};
+
+struct audioStatus_s
+{
+	char	code;
+	short	status;
+	int		PRstartLocation;
+	int		PRendLocation;
+};
+
+struct reset_s
+{
+	char	code;
+};
+
+union readInfo_u
+{
+	struct audioChannelInfo_s	audioChannelInfo;
+	struct deviceStatus_s		deviceStatus;
+	struct mediaChange_s		mediaChange;
+	struct audioDiskInfo_s		audioDiskInfo;
+	struct audioTrackInfo_s		audioTrackInfo;
+	struct audioStatus_s		audioStatus;
+	struct reset_s				reset;
+};
+
+#pragma pack()
+
+#define MAXIMUM_TRACKS			100
+
+typedef struct
+{
+	int			start;
+	int			length;
+	qboolean	isData;
+} track_info;
+
+typedef struct
+{
+	qboolean	valid;
+	int			leadOutAddress;
+	track_info	track[MAXIMUM_TRACKS];
+	byte		lowTrack;
+	byte		highTrack;
+} cd_info;
+
+static struct cd_request	*cdRequest;
+static union readInfo_u		*readInfo;
+static cd_info				cd;
+
+static qboolean	playing = false;
+static qboolean	wasPlaying = false;
+static qboolean	mediaCheck = false;
+static qboolean	initialized = false;
+static qboolean	enabled = true;
+static qboolean playLooping = false;
+static short	cdRequestSegment;
+static short	cdRequestOffset;
+static short	readInfoSegment;
+static short	readInfoOffset;
+static byte 	remap[256];
+static byte		cdrom;
+static byte		playTrack;
+static byte		cdvolume;
+
+
+static int RedBookToSector(int rb)
+{
+	byte	minute;
+	byte	second;
+	byte	frame;
+
+	minute = (rb >> 16) & 0xff;
+	second = (rb >> 8) & 0xff;
+	frame = rb & 0xff;
+	return minute * 60 * 75 + second * 75 + frame;
+}
+
+
+static void CDAudio_Reset(void)
+{
+	cdRequest->headerLength = 13;
+	cdRequest->unit = 0;
+	cdRequest->command = COMMAND_WRITE;
+	cdRequest->status = 0;
+
+	cdRequest->x.write.mediaDescriptor = 0;
+	cdRequest->x.write.bufferOffset = readInfoOffset;
+	cdRequest->x.write.bufferSegment = readInfoSegment;
+	cdRequest->x.write.length = sizeof(struct reset_s);
+	cdRequest->x.write.startSector = 0;
+	cdRequest->x.write.volumeID = 0;
+
+	readInfo->reset.code = WRITE_REQUEST_RESET;
+
+	regs.x.ax = 0x1510;
+	regs.x.cx = cdrom;
+	regs.x.es = cdRequestSegment;
+	regs.x.bx = cdRequestOffset;
+	dos_int86 (0x2f);
+}
+
+
+static void CDAudio_Eject(void)
+{
+	cdRequest->headerLength = 13;
+	cdRequest->unit = 0;
+	cdRequest->command = COMMAND_WRITE;
+	cdRequest->status = 0;
+
+	cdRequest->x.write.mediaDescriptor = 0;
+	cdRequest->x.write.bufferOffset = readInfoOffset;
+	cdRequest->x.write.bufferSegment = readInfoSegment;
+	cdRequest->x.write.length = sizeof(struct reset_s);
+	cdRequest->x.write.startSector = 0;
+	cdRequest->x.write.volumeID = 0;
+
+	readInfo->reset.code = WRITE_REQUEST_EJECT;
+
+	regs.x.ax = 0x1510;
+	regs.x.cx = cdrom;
+	regs.x.es = cdRequestSegment;
+	regs.x.bx = cdRequestOffset;
+	dos_int86 (0x2f);
+}
+
+
+static int CDAudio_GetAudioTrackInfo(byte track, int *start)
+{
+	byte	control;
+
+	cdRequest->headerLength = 13;
+	cdRequest->unit = 0;
+	cdRequest->command = COMMAND_READ;
+	cdRequest->status = 0;
+
+	cdRequest->x.read.mediaDescriptor = 0;
+	cdRequest->x.read.bufferOffset = readInfoOffset;
+	cdRequest->x.read.bufferSegment = readInfoSegment;
+	cdRequest->x.read.length = sizeof(struct audioTrackInfo_s);
+	cdRequest->x.read.startSector = 0;
+	cdRequest->x.read.volumeID = 0;
+
+	readInfo->audioTrackInfo.code = READ_REQUEST_AUDIO_TRACK_INFO;
+	readInfo->audioTrackInfo.track = track;
+
+	regs.x.ax = 0x1510;
+	regs.x.cx = cdrom;
+	regs.x.es = cdRequestSegment;
+	regs.x.bx = cdRequestOffset;
+	dos_int86 (0x2f);
+
+	if (cdRequest->status & STATUS_ERROR_BIT)
+	{
+		Con_DPrintf("CDAudio_GetAudioTrackInfo %04x\n", cdRequest->status & 	0xffff);
+		return -1;
+	}
+
+	*start = readInfo->audioTrackInfo.start;
+	control = readInfo->audioTrackInfo.control & AUDIO_CONTROL_MASK;
+	return (control & AUDIO_CONTROL_DATA_TRACK);
+}
+
+
+static int CDAudio_GetAudioDiskInfo(void)
+{
+	int n;
+
+	cdRequest->headerLength = 13;
+	cdRequest->unit = 0;
+	cdRequest->command = COMMAND_READ;
+	cdRequest->status = 0;
+
+	cdRequest->x.read.mediaDescriptor = 0;
+	cdRequest->x.read.bufferOffset = readInfoOffset;
+	cdRequest->x.read.bufferSegment = readInfoSegment;
+	cdRequest->x.read.length = sizeof(struct audioDiskInfo_s);
+	cdRequest->x.read.startSector = 0;
+	cdRequest->x.read.volumeID = 0;
+
+	readInfo->audioDiskInfo.code = READ_REQUEST_AUDIO_DISK_INFO;
+
+	regs.x.ax = 0x1510;
+	regs.x.cx = cdrom;
+	regs.x.es = cdRequestSegment;
+	regs.x.bx = cdRequestOffset;
+	dos_int86 (0x2f);
+
+	if (cdRequest->status & STATUS_ERROR_BIT)
+	{
+		Con_DPrintf("CDAudio_GetAudioDiskInfo %04x\n", cdRequest->status & 	0xffff);
+		return -1;
+	}
+
+	cd.valid = true;
+	cd.lowTrack = readInfo->audioDiskInfo.lowTrack;
+	cd.highTrack = readInfo->audioDiskInfo.highTrack;
+	cd.leadOutAddress = readInfo->audioDiskInfo.leadOutStart;
+
+	for (n = cd.lowTrack; n <= cd.highTrack; n++)
+	{
+		cd.track[n].isData = CDAudio_GetAudioTrackInfo (n, &cd.track[n].start);
+		if (n > cd.lowTrack)
+		{
+			cd.track[n-1].length = RedBookToSector(cd.track[n].start) - RedBookToSector(cd.track[n-1].start);
+			if (n == cd.highTrack)
+				cd.track[n].length = RedBookToSector(cd.leadOutAddress) - RedBookToSector(cd.track[n].start);
+		}
+	}
+
+	return 0;
+}
+
+
+static int CDAudio_GetAudioStatus(void)
+{
+	cdRequest->headerLength = 13;
+	cdRequest->unit = 0;
+	cdRequest->command = COMMAND_READ;
+	cdRequest->status = 0;
+
+	cdRequest->x.read.mediaDescriptor = 0;
+	cdRequest->x.read.bufferOffset = readInfoOffset;
+	cdRequest->x.read.bufferSegment = readInfoSegment;
+	cdRequest->x.read.length = sizeof(struct audioStatus_s);
+	cdRequest->x.read.startSector = 0;
+	cdRequest->x.read.volumeID = 0;
+
+	readInfo->audioDiskInfo.code = READ_REQUEST_AUDIO_STATUS;
+
+	regs.x.ax = 0x1510;
+	regs.x.cx = cdrom;
+	regs.x.es = cdRequestSegment;
+	regs.x.bx = cdRequestOffset;
+	dos_int86 (0x2f);
+
+	if (cdRequest->status & STATUS_ERROR_BIT)
+		return -1;
+	return 0;
+}
+
+
+static int CDAudio_MediaChange(void)
+{
+	cdRequest->headerLength = 13;
+	cdRequest->unit = 0;
+	cdRequest->command = COMMAND_READ;
+	cdRequest->status = 0;
+
+	cdRequest->x.read.mediaDescriptor = 0;
+	cdRequest->x.read.bufferOffset = readInfoOffset;
+	cdRequest->x.read.bufferSegment = readInfoSegment;
+	cdRequest->x.read.length = sizeof(struct mediaChange_s);
+	cdRequest->x.read.startSector = 0;
+	cdRequest->x.read.volumeID = 0;
+
+	readInfo->mediaChange.code = READ_REQUEST_MEDIA_CHANGE;
+
+	regs.x.ax = 0x1510;
+	regs.x.cx = cdrom;
+	regs.x.es = cdRequestSegment;
+	regs.x.bx = cdRequestOffset;
+	dos_int86 (0x2f);
+
+	return readInfo->mediaChange.status;
+}
+
+
+// we set the volume to 0 first and then to the desired volume
+// some cd-rom drivers seem to need it done this way
+void CDAudio_SetVolume (byte volume)
+{
+	if (!initialized || !enabled)
+		return;
+
+	cdRequest->headerLength = 13;
+	cdRequest->unit = 0;
+	cdRequest->command = COMMAND_WRITE;
+	cdRequest->status = 0;
+
+	cdRequest->x.read.mediaDescriptor = 0;
+	cdRequest->x.read.bufferOffset = readInfoOffset;
+	cdRequest->x.read.bufferSegment = readInfoSegment;
+	cdRequest->x.read.length = sizeof(struct audioChannelInfo_s);
+	cdRequest->x.read.startSector = 0;
+	cdRequest->x.read.volumeID = 0;
+
+	readInfo->audioChannelInfo.code = WRITE_REQUEST_AUDIO_CHANNEL_INFO;
+	readInfo->audioChannelInfo.channel0input = 0;
+	readInfo->audioChannelInfo.channel0volume = 0;
+	readInfo->audioChannelInfo.channel1input = 1;
+	readInfo->audioChannelInfo.channel1volume = 0;
+	readInfo->audioChannelInfo.channel2input = 2;
+	readInfo->audioChannelInfo.channel2volume = 0;
+	readInfo->audioChannelInfo.channel3input = 3;
+	readInfo->audioChannelInfo.channel3volume = 0;
+
+	regs.x.ax = 0x1510;
+	regs.x.cx = cdrom;
+	regs.x.es = cdRequestSegment;
+	regs.x.bx = cdRequestOffset;
+	dos_int86 (0x2f);
+
+	readInfo->audioChannelInfo.channel0volume = volume;
+	readInfo->audioChannelInfo.channel1volume = volume;
+
+	regs.x.ax = 0x1510;
+	regs.x.cx = cdrom;
+	regs.x.es = cdRequestSegment;
+	regs.x.bx = cdRequestOffset;
+	dos_int86 (0x2f);
+
+	cdvolume = volume;
+}
+
+
+void CDAudio_Play(byte track, qboolean looping)
+{
+	int		volume;
+
+	if (!initialized || !enabled)
+		return;
+	
+	if (!cd.valid)
+		return;
+
+	track = remap[track];
+
+	if (playing)
+	{
+		if (playTrack == track)
+			return;
+		CDAudio_Stop();
+	}
+
+	playLooping = looping;
+
+	if (track < cd.lowTrack || track > cd.highTrack)
+	{
+		Con_DPrintf("CDAudio_Play: Bad track number %u.\n", track);
+		return;
+	}
+
+	playTrack = track;
+
+	if (cd.track[track].isData)
+	{
+		Con_DPrintf("CDAudio_Play: Can not play data.\n");
+		return;
+	}
+
+	volume = (int)(bgmvolume.value * 255.0);
+	if (volume < 0)
+	{
+		Cvar_SetValue ("bgmvolume", 0.0);
+		volume = 0;
+	}
+	else if (volume > 255)
+	{
+		Cvar_SetValue ("bgmvolume", 1.0);
+		volume = 255;
+	}
+	CDAudio_SetVolume (volume);
+
+	cdRequest->headerLength = 13;
+	cdRequest->unit = 0;
+	cdRequest->command = COMMAND_PLAY_AUDIO;
+	cdRequest->status = 0;
+
+	cdRequest->x.playAudio.addressingMode = ADDRESS_MODE_RED_BOOK;
+	cdRequest->x.playAudio.startLocation = cd.track[track].start;
+	cdRequest->x.playAudio.sectors = cd.track[track].length;
+
+	regs.x.ax = 0x1510;
+	regs.x.cx = cdrom;
+	regs.x.es = cdRequestSegment;
+	regs.x.bx = cdRequestOffset;
+	dos_int86 (0x2f);
+
+	if (cdRequest->status & STATUS_ERROR_BIT)
+	{
+		Con_DPrintf("CDAudio_Play: track %u failed\n", track);
+		cd.valid = false;
+		playing = false;
+		return;
+	}
+
+	playing = true;
+}
+
+
+void CDAudio_Stop(void)
+{
+	if (!initialized || !enabled)
+		return;
+	
+	cdRequest->headerLength = 13;
+	cdRequest->unit = 0;
+	cdRequest->command = COMMAND_STOP_AUDIO;
+	cdRequest->status = 0;
+
+	regs.x.ax = 0x1510;
+	regs.x.cx = cdrom;
+	regs.x.es = cdRequestSegment;
+	regs.x.bx = cdRequestOffset;
+	dos_int86 (0x2f);
+
+	wasPlaying = playing;
+	playing = false;
+}
+
+
+void CDAudio_Pause(void)
+{
+	CDAudio_Stop();
+}
+
+
+void CDAudio_Resume(void)
+{
+	if (!initialized || !enabled)
+		return;
+	
+	if (!cd.valid)
+		return;
+
+	if (!wasPlaying)
+		return;
+	
+	cdRequest->headerLength = 13;
+	cdRequest->unit = 0;
+	cdRequest->command = COMMAND_RESUME_AUDIO;
+	cdRequest->status = 0;
+
+	regs.x.ax = 0x1510;
+	regs.x.cx = cdrom;
+	regs.x.es = cdRequestSegment;
+	regs.x.bx = cdRequestOffset;
+	dos_int86 (0x2f);
+
+	playing = true;
+}
+
+
+static void CD_f (void)
+{
+	char	*command;
+	int		ret;
+	int		n;
+	int		startAddress;
+
+	if (Cmd_Argc() < 2)
+		return;
+
+	command = Cmd_Argv (1);
+
+	if (Q_strcasecmp(command, "on") == 0)
+	{
+		enabled = true;
+		return;
+	}
+
+	if (Q_strcasecmp(command, "off") == 0)
+	{
+		if (playing)
+			CDAudio_Stop();
+		enabled = false;
+		return;
+	}
+
+	if (Q_strcasecmp(command, "reset") == 0)
+	{
+		enabled = true;
+		if (playing)
+			CDAudio_Stop();
+		for (n = 0; n < 256; n++)
+			remap[n] = n;
+		CDAudio_Reset();
+		CDAudio_GetAudioDiskInfo();
+		return;
+	}
+
+	if (Q_strcasecmp(command, "remap") == 0)
+	{
+		ret = Cmd_Argc() - 2;
+		if (ret <= 0)
+		{
+			for (n = 1; n < 256; n++)
+				if (remap[n] != n)
+					Con_Printf("  %u -> %u\n", n, remap[n]);
+			return;
+		}
+		for (n = 1; n <= ret; n++)
+			remap[n] = Q_atoi(Cmd_Argv (n+1));
+		return;
+	}
+
+	if (!cd.valid)
+	{
+		Con_Printf("No CD in player.\n");
+		return;
+	}
+
+	if (Q_strcasecmp(command, "play") == 0)
+	{
+		CDAudio_Play(Q_atoi(Cmd_Argv (2)), false);
+		return;
+	}
+
+	if (Q_strcasecmp(command, "loop") == 0)
+	{
+		CDAudio_Play(Q_atoi(Cmd_Argv (2)), true);
+		return;
+	}
+
+	if (Q_strcasecmp(command, "stop") == 0)
+	{
+		CDAudio_Stop();
+		return;
+	}
+
+	if (Q_strcasecmp(command, "pause") == 0)
+	{
+		CDAudio_Pause();
+		return;
+	}
+
+	if (Q_strcasecmp(command, "resume") == 0)
+	{
+		CDAudio_Resume();
+		return;
+	}
+
+	if (Q_strcasecmp(command, "eject") == 0)
+	{
+		if (playing)
+			CDAudio_Stop();
+		CDAudio_Eject();
+		cd.valid = false;
+		return;
+	}
+
+	if (Q_strcasecmp(command, "info") == 0)
+	{
+		Con_Printf("%u tracks\n", cd.highTrack - cd.lowTrack + 1);
+		for (n = cd.lowTrack; n <= cd.highTrack; n++)
+		{
+			ret = CDAudio_GetAudioTrackInfo (n, &startAddress);
+			Con_Printf("Track %2u: %s at %2u:%02u\n", n, ret ? "data " : "music", (startAddress >> 16) & 0xff, (startAddress >> 8) & 0xff);
+		}
+		if (playing)
+			Con_Printf("Currently %s track %u\n", playLooping ? "looping" : "playing", playTrack);
+		Con_Printf("Volume is %u\n", cdvolume);
+		CDAudio_MediaChange();
+		Con_Printf("Status %04x\n", cdRequest->status & 0xffff);
+		return;
+	}
+}
+
+
+void CDAudio_Update(void)
+{
+	int		ret;
+	int		newVolume;
+	static	double lastUpdate;
+
+	if (!initialized || !enabled)
+		return;
+
+	if ((realtime - lastUpdate) < 0.25)
+		return;
+	lastUpdate = realtime;
+
+	if (mediaCheck)
+	{
+		static	double lastCheck;
+
+		if ((realtime - lastCheck) < 5.0)
+			return;
+		lastCheck = realtime;
+
+		ret = CDAudio_MediaChange();
+		if (ret == MEDIA_CHANGED)
+		{
+			Con_DPrintf("CDAudio: media changed\n");
+			playing = false;
+			wasPlaying = false;
+			cd.valid = false;
+			CDAudio_GetAudioDiskInfo();
+			return;
+		}
+	}
+
+	newVolume = (int)(bgmvolume.value * 255.0);
+	if (newVolume != cdvolume)
+	{
+		if (newVolume < 0)
+		{
+			Cvar_SetValue ("bgmvolume", 0.0);
+			newVolume = 0;
+		}
+		else if (newVolume > 255)
+		{
+			Cvar_SetValue ("bgmvolume", 1.0);
+			newVolume = 255;
+		}
+		CDAudio_SetVolume (newVolume);
+	}
+
+	if (playing)
+	{
+		CDAudio_GetAudioStatus();
+		if ((cdRequest->status & STATUS_BUSY_BIT) == 0)
+		{
+			playing = false;
+			if (playLooping)
+				CDAudio_Play(playTrack, true);
+		}
+	}
+}
+
+
+int CDAudio_Init(void)
+{
+	char	*memory;
+	int		n;
+
+	if (cls.state == ca_dedicated)
+		return -1;
+
+	if (COM_CheckParm("-nocdaudio"))
+		return -1;
+
+	if (COM_CheckParm("-cdmediacheck"))
+		mediaCheck = true;
+
+	regs.x.ax = 0x1500;
+	regs.x.bx = 0;
+	dos_int86 (0x2f);
+	if (regs.x.bx == 0)
+	{
+		Con_NotifyBox (
+			"MSCDEX not loaded, music is\n"
+			"disabled.  Use \"-nocdaudio\" if you\n"
+			"wish to avoid this message in the\n"
+			"future.  See README.TXT for help.\n"
+			);			
+		return -1;
+	}
+	if (regs.x.bx > 1)
+		Con_DPrintf("CDAudio_Init: First CD-ROM drive will be used\n");
+	cdrom = regs.x.cx;
+
+	regs.x.ax = 0x150c;
+	regs.x.bx = 0;
+	dos_int86 (0x2f);
+	if (regs.x.bx == 0)
+	{
+		Con_NotifyBox (
+			"MSCDEX version 2.00 or later\n"
+			"required for music. See README.TXT\n"
+			"for help.\n"
+			);			
+		Con_DPrintf("CDAudio_Init: MSCDEX version 2.00 or later required.\n");
+		return -1;
+	}
+
+	memory = dos_getmemory(sizeof(struct cd_request
+) + sizeof(union readInfo_u));
+	if (memory == NULL)
+	{
+		Con_DPrintf("CDAudio_Init: Unable to allocate low memory.\n");
+		return -1;
+	}
+
+	cdRequest = (struct cd_request *)memory;
+	cdRequestSegment = ptr2real(cdRequest) >> 4;
+	cdRequestOffset = ptr2real(cdRequest) & 0xf;
+
+	readInfo = (union readInfo_u *)(memory + sizeof(struct cd_request));
+	readInfoSegment = ptr2real(readInfo) >> 4;
+	readInfoOffset = ptr2real(readInfo) & 0xf;
+
+	for (n = 0; n < 256; n++)
+		remap[n] = n;
+	initialized = true;
+
+	CDAudio_SetVolume (255);
+	if (CDAudio_GetAudioDiskInfo())
+	{
+		Con_Printf("CDAudio_Init: No CD in player.\n");
+		enabled = false;
+	}
+
+	Cmd_AddCommand ("cd", CD_f);
+
+	Con_Printf("CD Audio Initialized\n");
+
+	return 0;
+}
+
+
+void CDAudio_Shutdown(void)
+{
+	if (!initialized)
+		return;
+	CDAudio_Stop();
+}
--- /dev/null
+++ b/WinQuake/cd_linux.c
@@ -1,0 +1,416 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// Quake is a trademark of Id Software, Inc., (c) 1996 Id Software, Inc. All
+// rights reserved.
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/ioctl.h>
+#include <sys/file.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <string.h>
+#include <time.h>
+#include <errno.h>
+
+#include <linux/cdrom.h>
+
+#include "quakedef.h"
+
+static qboolean cdValid = false;
+static qboolean	playing = false;
+static qboolean	wasPlaying = false;
+static qboolean	initialized = false;
+static qboolean	enabled = true;
+static qboolean playLooping = false;
+static float	cdvolume;
+static byte 	remap[100];
+static byte		playTrack;
+static byte		maxTrack;
+
+static int cdfile = -1;
+static char cd_dev[64] = "/dev/cdrom";
+
+static void CDAudio_Eject(void)
+{
+	if (cdfile == -1 || !enabled)
+		return; // no cd init'd
+
+	if ( ioctl(cdfile, CDROMEJECT) == -1 ) 
+		Con_DPrintf("ioctl cdromeject failed\n");
+}
+
+
+static void CDAudio_CloseDoor(void)
+{
+	if (cdfile == -1 || !enabled)
+		return; // no cd init'd
+
+	if ( ioctl(cdfile, CDROMCLOSETRAY) == -1 ) 
+		Con_DPrintf("ioctl cdromclosetray failed\n");
+}
+
+static int CDAudio_GetAudioDiskInfo(void)
+{
+	struct cdrom_tochdr tochdr;
+
+	cdValid = false;
+
+	if ( ioctl(cdfile, CDROMREADTOCHDR, &tochdr) == -1 ) 
+    {
+      Con_DPrintf("ioctl cdromreadtochdr failed\n");
+	  return -1;
+    }
+
+	if (tochdr.cdth_trk0 < 1)
+	{
+		Con_DPrintf("CDAudio: no music tracks\n");
+		return -1;
+	}
+
+	cdValid = true;
+	maxTrack = tochdr.cdth_trk1;
+
+	return 0;
+}
+
+
+void CDAudio_Play(byte track, qboolean looping)
+{
+	struct cdrom_tocentry entry;
+	struct cdrom_ti ti;
+
+	if (cdfile == -1 || !enabled)
+		return;
+	
+	if (!cdValid)
+	{
+		CDAudio_GetAudioDiskInfo();
+		if (!cdValid)
+			return;
+	}
+
+	track = remap[track];
+
+	if (track < 1 || track > maxTrack)
+	{
+		Con_DPrintf("CDAudio: Bad track number %u.\n", track);
+		return;
+	}
+
+	// don't try to play a non-audio track
+	entry.cdte_track = track;
+	entry.cdte_format = CDROM_MSF;
+    if ( ioctl(cdfile, CDROMREADTOCENTRY, &entry) == -1 )
+	{
+		Con_DPrintf("ioctl cdromreadtocentry failed\n");
+		return;
+	}
+	if (entry.cdte_ctrl == CDROM_DATA_TRACK)
+	{
+		Con_Printf("CDAudio: track %i is not audio\n", track);
+		return;
+	}
+
+	if (playing)
+	{
+		if (playTrack == track)
+			return;
+		CDAudio_Stop();
+	}
+
+	ti.cdti_trk0 = track;
+	ti.cdti_trk1 = track;
+	ti.cdti_ind0 = 1;
+	ti.cdti_ind1 = 99;
+
+	if ( ioctl(cdfile, CDROMPLAYTRKIND, &ti) == -1 ) 
+    {
+		Con_DPrintf("ioctl cdromplaytrkind failed\n");
+		return;
+    }
+
+	if ( ioctl(cdfile, CDROMRESUME) == -1 ) 
+		Con_DPrintf("ioctl cdromresume failed\n");
+
+	playLooping = looping;
+	playTrack = track;
+	playing = true;
+
+	if (cdvolume == 0.0)
+		CDAudio_Pause ();
+}
+
+
+void CDAudio_Stop(void)
+{
+	if (cdfile == -1 || !enabled)
+		return;
+	
+	if (!playing)
+		return;
+
+	if ( ioctl(cdfile, CDROMSTOP) == -1 )
+		Con_DPrintf("ioctl cdromstop failed (%d)\n", errno);
+
+	wasPlaying = false;
+	playing = false;
+}
+
+void CDAudio_Pause(void)
+{
+	if (cdfile == -1 || !enabled)
+		return;
+
+	if (!playing)
+		return;
+
+	if ( ioctl(cdfile, CDROMPAUSE) == -1 ) 
+		Con_DPrintf("ioctl cdrompause failed\n");
+
+	wasPlaying = playing;
+	playing = false;
+}
+
+
+void CDAudio_Resume(void)
+{
+	if (cdfile == -1 || !enabled)
+		return;
+	
+	if (!cdValid)
+		return;
+
+	if (!wasPlaying)
+		return;
+	
+	if ( ioctl(cdfile, CDROMRESUME) == -1 ) 
+		Con_DPrintf("ioctl cdromresume failed\n");
+	playing = true;
+}
+
+static void CD_f (void)
+{
+	char	*command;
+	int		ret;
+	int		n;
+
+	if (Cmd_Argc() < 2)
+		return;
+
+	command = Cmd_Argv (1);
+
+	if (Q_strcasecmp(command, "on") == 0)
+	{
+		enabled = true;
+		return;
+	}
+
+	if (Q_strcasecmp(command, "off") == 0)
+	{
+		if (playing)
+			CDAudio_Stop();
+		enabled = false;
+		return;
+	}
+
+	if (Q_strcasecmp(command, "reset") == 0)
+	{
+		enabled = true;
+		if (playing)
+			CDAudio_Stop();
+		for (n = 0; n < 100; n++)
+			remap[n] = n;
+		CDAudio_GetAudioDiskInfo();
+		return;
+	}
+
+	if (Q_strcasecmp(command, "remap") == 0)
+	{
+		ret = Cmd_Argc() - 2;
+		if (ret <= 0)
+		{
+			for (n = 1; n < 100; n++)
+				if (remap[n] != n)
+					Con_Printf("  %u -> %u\n", n, remap[n]);
+			return;
+		}
+		for (n = 1; n <= ret; n++)
+			remap[n] = Q_atoi(Cmd_Argv (n+1));
+		return;
+	}
+
+	if (Q_strcasecmp(command, "close") == 0)
+	{
+		CDAudio_CloseDoor();
+		return;
+	}
+
+	if (!cdValid)
+	{
+		CDAudio_GetAudioDiskInfo();
+		if (!cdValid)
+		{
+			Con_Printf("No CD in player.\n");
+			return;
+		}
+	}
+
+	if (Q_strcasecmp(command, "play") == 0)
+	{
+		CDAudio_Play((byte)Q_atoi(Cmd_Argv (2)), false);
+		return;
+	}
+
+	if (Q_strcasecmp(command, "loop") == 0)
+	{
+		CDAudio_Play((byte)Q_atoi(Cmd_Argv (2)), true);
+		return;
+	}
+
+	if (Q_strcasecmp(command, "stop") == 0)
+	{
+		CDAudio_Stop();
+		return;
+	}
+
+	if (Q_strcasecmp(command, "pause") == 0)
+	{
+		CDAudio_Pause();
+		return;
+	}
+
+	if (Q_strcasecmp(command, "resume") == 0)
+	{
+		CDAudio_Resume();
+		return;
+	}
+
+	if (Q_strcasecmp(command, "eject") == 0)
+	{
+		if (playing)
+			CDAudio_Stop();
+		CDAudio_Eject();
+		cdValid = false;
+		return;
+	}
+
+	if (Q_strcasecmp(command, "info") == 0)
+	{
+		Con_Printf("%u tracks\n", maxTrack);
+		if (playing)
+			Con_Printf("Currently %s track %u\n", playLooping ? "looping" : "playing", playTrack);
+		else if (wasPlaying)
+			Con_Printf("Paused %s track %u\n", playLooping ? "looping" : "playing", playTrack);
+		Con_Printf("Volume is %f\n", cdvolume);
+		return;
+	}
+}
+
+void CDAudio_Update(void)
+{
+	struct cdrom_subchnl subchnl;
+	static time_t lastchk;
+
+	if (!enabled)
+		return;
+
+	if (bgmvolume.value != cdvolume)
+	{
+		if (cdvolume)
+		{
+			Cvar_SetValue ("bgmvolume", 0.0);
+			cdvolume = bgmvolume.value;
+			CDAudio_Pause ();
+		}
+		else
+		{
+			Cvar_SetValue ("bgmvolume", 1.0);
+			cdvolume = bgmvolume.value;
+			CDAudio_Resume ();
+		}
+	}
+
+	if (playing && lastchk < time(NULL)) {
+		lastchk = time(NULL) + 2; //two seconds between chks
+		subchnl.cdsc_format = CDROM_MSF;
+		if (ioctl(cdfile, CDROMSUBCHNL, &subchnl) == -1 ) {
+			Con_DPrintf("ioctl cdromsubchnl failed\n");
+			playing = false;
+			return;
+		}
+		if (subchnl.cdsc_audiostatus != CDROM_AUDIO_PLAY &&
+			subchnl.cdsc_audiostatus != CDROM_AUDIO_PAUSED) {
+			playing = false;
+			if (playLooping)
+				CDAudio_Play(playTrack, true);
+		}
+	}
+}
+
+int CDAudio_Init(void)
+{
+	int i;
+
+	if (cls.state == ca_dedicated)
+		return -1;
+
+	if (COM_CheckParm("-nocdaudio"))
+		return -1;
+
+	if ((i = COM_CheckParm("-cddev")) != 0 && i < com_argc - 1) {
+		strncpy(cd_dev, com_argv[i + 1], sizeof(cd_dev));
+		cd_dev[sizeof(cd_dev) - 1] = 0;
+	}
+
+	if ((cdfile = open(cd_dev, O_RDONLY)) == -1) {
+		Con_Printf("CDAudio_Init: open of \"%s\" failed (%i)\n", cd_dev, errno);
+		cdfile = -1;
+		return -1;
+	}
+
+	for (i = 0; i < 100; i++)
+		remap[i] = i;
+	initialized = true;
+	enabled = true;
+
+	if (CDAudio_GetAudioDiskInfo())
+	{
+		Con_Printf("CDAudio_Init: No CD in player.\n");
+		cdValid = false;
+	}
+
+	Cmd_AddCommand ("cd", CD_f);
+
+	Con_Printf("CD Audio Initialized\n");
+
+	return 0;
+}
+
+
+void CDAudio_Shutdown(void)
+{
+	if (!initialized)
+		return;
+	CDAudio_Stop();
+	close(cdfile);
+	cdfile = -1;
+}
--- /dev/null
+++ b/WinQuake/cd_null.c
@@ -1,0 +1,55 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+#include "quakedef.h"
+
+void CDAudio_Play(byte track, qboolean looping)
+{
+}
+
+
+void CDAudio_Stop(void)
+{
+}
+
+
+void CDAudio_Pause(void)
+{
+}
+
+
+void CDAudio_Resume(void)
+{
+}
+
+
+void CDAudio_Update(void)
+{
+}
+
+
+int CDAudio_Init(void)
+{
+	return 0;
+}
+
+
+void CDAudio_Shutdown(void)
+{
+}
\ No newline at end of file
--- /dev/null
+++ b/WinQuake/cd_win.c
@@ -1,0 +1,477 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// Quake is a trademark of Id Software, Inc., (c) 1996 Id Software, Inc. All
+// rights reserved.
+
+#include <windows.h>
+#include "quakedef.h"
+
+extern	HWND	mainwindow;
+extern	cvar_t	bgmvolume;
+
+static qboolean cdValid = false;
+static qboolean	playing = false;
+static qboolean	wasPlaying = false;
+static qboolean	initialized = false;
+static qboolean	enabled = false;
+static qboolean playLooping = false;
+static float	cdvolume;
+static byte 	remap[100];
+static byte		cdrom;
+static byte		playTrack;
+static byte		maxTrack;
+
+UINT	wDeviceID;
+
+
+static void CDAudio_Eject(void)
+{
+	DWORD	dwReturn;
+
+    if (dwReturn = mciSendCommand(wDeviceID, MCI_SET, MCI_SET_DOOR_OPEN, (DWORD)NULL))
+		Con_DPrintf("MCI_SET_DOOR_OPEN failed (%i)\n", dwReturn);
+}
+
+
+static void CDAudio_CloseDoor(void)
+{
+	DWORD	dwReturn;
+
+    if (dwReturn = mciSendCommand(wDeviceID, MCI_SET, MCI_SET_DOOR_CLOSED, (DWORD)NULL))
+		Con_DPrintf("MCI_SET_DOOR_CLOSED failed (%i)\n", dwReturn);
+}
+
+
+static int CDAudio_GetAudioDiskInfo(void)
+{
+	DWORD				dwReturn;
+	MCI_STATUS_PARMS	mciStatusParms;
+
+
+	cdValid = false;
+
+	mciStatusParms.dwItem = MCI_STATUS_READY;
+    dwReturn = mciSendCommand(wDeviceID, MCI_STATUS, MCI_STATUS_ITEM | MCI_WAIT, (DWORD) (LPVOID) &mciStatusParms);
+	if (dwReturn)
+	{
+		Con_DPrintf("CDAudio: drive ready test - get status failed\n");
+		return -1;
+	}
+	if (!mciStatusParms.dwReturn)
+	{
+		Con_DPrintf("CDAudio: drive not ready\n");
+		return -1;
+	}
+
+	mciStatusParms.dwItem = MCI_STATUS_NUMBER_OF_TRACKS;
+    dwReturn = mciSendCommand(wDeviceID, MCI_STATUS, MCI_STATUS_ITEM | MCI_WAIT, (DWORD) (LPVOID) &mciStatusParms);
+	if (dwReturn)
+	{
+		Con_DPrintf("CDAudio: get tracks - status failed\n");
+		return -1;
+	}
+	if (mciStatusParms.dwReturn < 1)
+	{
+		Con_DPrintf("CDAudio: no music tracks\n");
+		return -1;
+	}
+
+	cdValid = true;
+	maxTrack = mciStatusParms.dwReturn;
+
+	return 0;
+}
+
+
+void CDAudio_Play(byte track, qboolean looping)
+{
+	DWORD				dwReturn;
+    MCI_PLAY_PARMS		mciPlayParms;
+	MCI_STATUS_PARMS	mciStatusParms;
+
+	if (!enabled)
+		return;
+	
+	if (!cdValid)
+	{
+		CDAudio_GetAudioDiskInfo();
+		if (!cdValid)
+			return;
+	}
+
+	track = remap[track];
+
+	if (track < 1 || track > maxTrack)
+	{
+		Con_DPrintf("CDAudio: Bad track number %u.\n", track);
+		return;
+	}
+
+	// don't try to play a non-audio track
+	mciStatusParms.dwItem = MCI_CDA_STATUS_TYPE_TRACK;
+	mciStatusParms.dwTrack = track;
+    dwReturn = mciSendCommand(wDeviceID, MCI_STATUS, MCI_STATUS_ITEM | MCI_TRACK | MCI_WAIT, (DWORD) (LPVOID) &mciStatusParms);
+	if (dwReturn)
+	{
+		Con_DPrintf("MCI_STATUS failed (%i)\n", dwReturn);
+		return;
+	}
+	if (mciStatusParms.dwReturn != MCI_CDA_TRACK_AUDIO)
+	{
+		Con_Printf("CDAudio: track %i is not audio\n", track);
+		return;
+	}
+
+	// get the length of the track to be played
+	mciStatusParms.dwItem = MCI_STATUS_LENGTH;
+	mciStatusParms.dwTrack = track;
+    dwReturn = mciSendCommand(wDeviceID, MCI_STATUS, MCI_STATUS_ITEM | MCI_TRACK | MCI_WAIT, (DWORD) (LPVOID) &mciStatusParms);
+	if (dwReturn)
+	{
+		Con_DPrintf("MCI_STATUS failed (%i)\n", dwReturn);
+		return;
+	}
+
+	if (playing)
+	{
+		if (playTrack == track)
+			return;
+		CDAudio_Stop();
+	}
+
+    mciPlayParms.dwFrom = MCI_MAKE_TMSF(track, 0, 0, 0);
+	mciPlayParms.dwTo = (mciStatusParms.dwReturn << 8) | track;
+    mciPlayParms.dwCallback = (DWORD)mainwindow;
+    dwReturn = mciSendCommand(wDeviceID, MCI_PLAY, MCI_NOTIFY | MCI_FROM | MCI_TO, (DWORD)(LPVOID) &mciPlayParms);
+	if (dwReturn)
+	{
+		Con_DPrintf("CDAudio: MCI_PLAY failed (%i)\n", dwReturn);
+		return;
+	}
+
+	playLooping = looping;
+	playTrack = track;
+	playing = true;
+
+	if (cdvolume == 0.0)
+		CDAudio_Pause ();
+}
+
+
+void CDAudio_Stop(void)
+{
+	DWORD	dwReturn;
+
+	if (!enabled)
+		return;
+	
+	if (!playing)
+		return;
+
+    if (dwReturn = mciSendCommand(wDeviceID, MCI_STOP, 0, (DWORD)NULL))
+		Con_DPrintf("MCI_STOP failed (%i)", dwReturn);
+
+	wasPlaying = false;
+	playing = false;
+}
+
+
+void CDAudio_Pause(void)
+{
+	DWORD				dwReturn;
+	MCI_GENERIC_PARMS	mciGenericParms;
+
+	if (!enabled)
+		return;
+
+	if (!playing)
+		return;
+
+	mciGenericParms.dwCallback = (DWORD)mainwindow;
+    if (dwReturn = mciSendCommand(wDeviceID, MCI_PAUSE, 0, (DWORD)(LPVOID) &mciGenericParms))
+		Con_DPrintf("MCI_PAUSE failed (%i)", dwReturn);
+
+	wasPlaying = playing;
+	playing = false;
+}
+
+
+void CDAudio_Resume(void)
+{
+	DWORD			dwReturn;
+    MCI_PLAY_PARMS	mciPlayParms;
+
+	if (!enabled)
+		return;
+	
+	if (!cdValid)
+		return;
+
+	if (!wasPlaying)
+		return;
+	
+    mciPlayParms.dwFrom = MCI_MAKE_TMSF(playTrack, 0, 0, 0);
+    mciPlayParms.dwTo = MCI_MAKE_TMSF(playTrack + 1, 0, 0, 0);
+    mciPlayParms.dwCallback = (DWORD)mainwindow;
+    dwReturn = mciSendCommand(wDeviceID, MCI_PLAY, MCI_TO | MCI_NOTIFY, (DWORD)(LPVOID) &mciPlayParms);
+	if (dwReturn)
+	{
+		Con_DPrintf("CDAudio: MCI_PLAY failed (%i)\n", dwReturn);
+		return;
+	}
+	playing = true;
+}
+
+
+static void CD_f (void)
+{
+	char	*command;
+	int		ret;
+	int		n;
+	int		startAddress;
+
+	if (Cmd_Argc() < 2)
+		return;
+
+	command = Cmd_Argv (1);
+
+	if (Q_strcasecmp(command, "on") == 0)
+	{
+		enabled = true;
+		return;
+	}
+
+	if (Q_strcasecmp(command, "off") == 0)
+	{
+		if (playing)
+			CDAudio_Stop();
+		enabled = false;
+		return;
+	}
+
+	if (Q_strcasecmp(command, "reset") == 0)
+	{
+		enabled = true;
+		if (playing)
+			CDAudio_Stop();
+		for (n = 0; n < 100; n++)
+			remap[n] = n;
+		CDAudio_GetAudioDiskInfo();
+		return;
+	}
+
+	if (Q_strcasecmp(command, "remap") == 0)
+	{
+		ret = Cmd_Argc() - 2;
+		if (ret <= 0)
+		{
+			for (n = 1; n < 100; n++)
+				if (remap[n] != n)
+					Con_Printf("  %u -> %u\n", n, remap[n]);
+			return;
+		}
+		for (n = 1; n <= ret; n++)
+			remap[n] = Q_atoi(Cmd_Argv (n+1));
+		return;
+	}
+
+	if (Q_strcasecmp(command, "close") == 0)
+	{
+		CDAudio_CloseDoor();
+		return;
+	}
+
+	if (!cdValid)
+	{
+		CDAudio_GetAudioDiskInfo();
+		if (!cdValid)
+		{
+			Con_Printf("No CD in player.\n");
+			return;
+		}
+	}
+
+	if (Q_strcasecmp(command, "play") == 0)
+	{
+		CDAudio_Play((byte)Q_atoi(Cmd_Argv (2)), false);
+		return;
+	}
+
+	if (Q_strcasecmp(command, "loop") == 0)
+	{
+		CDAudio_Play((byte)Q_atoi(Cmd_Argv (2)), true);
+		return;
+	}
+
+	if (Q_strcasecmp(command, "stop") == 0)
+	{
+		CDAudio_Stop();
+		return;
+	}
+
+	if (Q_strcasecmp(command, "pause") == 0)
+	{
+		CDAudio_Pause();
+		return;
+	}
+
+	if (Q_strcasecmp(command, "resume") == 0)
+	{
+		CDAudio_Resume();
+		return;
+	}
+
+	if (Q_strcasecmp(command, "eject") == 0)
+	{
+		if (playing)
+			CDAudio_Stop();
+		CDAudio_Eject();
+		cdValid = false;
+		return;
+	}
+
+	if (Q_strcasecmp(command, "info") == 0)
+	{
+		Con_Printf("%u tracks\n", maxTrack);
+		if (playing)
+			Con_Printf("Currently %s track %u\n", playLooping ? "looping" : "playing", playTrack);
+		else if (wasPlaying)
+			Con_Printf("Paused %s track %u\n", playLooping ? "looping" : "playing", playTrack);
+		Con_Printf("Volume is %f\n", cdvolume);
+		return;
+	}
+}
+
+
+LONG CDAudio_MessageHandler(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+	if (lParam != wDeviceID)
+		return 1;
+
+	switch (wParam)
+	{
+		case MCI_NOTIFY_SUCCESSFUL:
+			if (playing)
+			{
+				playing = false;
+				if (playLooping)
+					CDAudio_Play(playTrack, true);
+			}
+			break;
+
+		case MCI_NOTIFY_ABORTED:
+		case MCI_NOTIFY_SUPERSEDED:
+			break;
+
+		case MCI_NOTIFY_FAILURE:
+			Con_DPrintf("MCI_NOTIFY_FAILURE\n");
+			CDAudio_Stop ();
+			cdValid = false;
+			break;
+
+		default:
+			Con_DPrintf("Unexpected MM_MCINOTIFY type (%i)\n", wParam);
+			return 1;
+	}
+
+	return 0;
+}
+
+
+void CDAudio_Update(void)
+{
+	if (!enabled)
+		return;
+
+	if (bgmvolume.value != cdvolume)
+	{
+		if (cdvolume)
+		{
+			Cvar_SetValue ("bgmvolume", 0.0);
+			cdvolume = bgmvolume.value;
+			CDAudio_Pause ();
+		}
+		else
+		{
+			Cvar_SetValue ("bgmvolume", 1.0);
+			cdvolume = bgmvolume.value;
+			CDAudio_Resume ();
+		}
+	}
+}
+
+
+int CDAudio_Init(void)
+{
+	DWORD	dwReturn;
+	MCI_OPEN_PARMS	mciOpenParms;
+    MCI_SET_PARMS	mciSetParms;
+	int				n;
+
+	if (cls.state == ca_dedicated)
+		return -1;
+
+	if (COM_CheckParm("-nocdaudio"))
+		return -1;
+
+	mciOpenParms.lpstrDeviceType = "cdaudio";
+	if (dwReturn = mciSendCommand(0, MCI_OPEN, MCI_OPEN_TYPE | MCI_OPEN_SHAREABLE, (DWORD) (LPVOID) &mciOpenParms))
+	{
+		Con_Printf("CDAudio_Init: MCI_OPEN failed (%i)\n", dwReturn);
+		return -1;
+	}
+	wDeviceID = mciOpenParms.wDeviceID;
+
+    // Set the time format to track/minute/second/frame (TMSF).
+    mciSetParms.dwTimeFormat = MCI_FORMAT_TMSF;
+    if (dwReturn = mciSendCommand(wDeviceID, MCI_SET, MCI_SET_TIME_FORMAT, (DWORD)(LPVOID) &mciSetParms))
+    {
+		Con_Printf("MCI_SET_TIME_FORMAT failed (%i)\n", dwReturn);
+        mciSendCommand(wDeviceID, MCI_CLOSE, 0, (DWORD)NULL);
+		return -1;
+    }
+
+	for (n = 0; n < 100; n++)
+		remap[n] = n;
+	initialized = true;
+	enabled = true;
+
+	if (CDAudio_GetAudioDiskInfo())
+	{
+		Con_Printf("CDAudio_Init: No CD in player.\n");
+		cdValid = false;
+	}
+
+	Cmd_AddCommand ("cd", CD_f);
+
+	Con_Printf("CD Audio Initialized\n");
+
+	return 0;
+}
+
+
+void CDAudio_Shutdown(void)
+{
+	if (!initialized)
+		return;
+	CDAudio_Stop();
+	if (mciSendCommand(wDeviceID, MCI_CLOSE, MCI_WAIT, (DWORD)NULL))
+		Con_DPrintf("CDAudio_Shutdown: MCI_CLOSE failed\n");
+}
--- /dev/null
+++ b/WinQuake/cdaudio.h
@@ -1,0 +1,27 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+
+int CDAudio_Init(void);
+void CDAudio_Play(byte track, qboolean looping);
+void CDAudio_Stop(void);
+void CDAudio_Pause(void);
+void CDAudio_Resume(void);
+void CDAudio_Shutdown(void);
+void CDAudio_Update(void);
--- /dev/null
+++ b/WinQuake/chase.c
@@ -1,0 +1,92 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// chase.c -- chase camera code
+
+#include "quakedef.h"
+
+cvar_t	chase_back = {"chase_back", "100"};
+cvar_t	chase_up = {"chase_up", "16"};
+cvar_t	chase_right = {"chase_right", "0"};
+cvar_t	chase_active = {"chase_active", "0"};
+
+vec3_t	chase_pos;
+vec3_t	chase_angles;
+
+vec3_t	chase_dest;
+vec3_t	chase_dest_angles;
+
+
+void Chase_Init (void)
+{
+	Cvar_RegisterVariable (&chase_back);
+	Cvar_RegisterVariable (&chase_up);
+	Cvar_RegisterVariable (&chase_right);
+	Cvar_RegisterVariable (&chase_active);
+}
+
+void Chase_Reset (void)
+{
+	// for respawning and teleporting
+//	start position 12 units behind head
+}
+
+void TraceLine (vec3_t start, vec3_t end, vec3_t impact)
+{
+	trace_t	trace;
+
+	memset (&trace, 0, sizeof(trace));
+	SV_RecursiveHullCheck (cl.worldmodel->hulls, 0, 0, 1, start, end, &trace);
+
+	VectorCopy (trace.endpos, impact);
+}
+
+void Chase_Update (void)
+{
+	int		i;
+	float	dist;
+	vec3_t	forward, up, right;
+	vec3_t	dest, stop;
+
+
+	// if can't see player, reset
+	AngleVectors (cl.viewangles, forward, right, up);
+
+	// calc exact destination
+	for (i=0 ; i<3 ; i++)
+		chase_dest[i] = r_refdef.vieworg[i] 
+		- forward[i]*chase_back.value
+		- right[i]*chase_right.value;
+	chase_dest[2] = r_refdef.vieworg[2] + chase_up.value;
+
+	// find the spot the player is looking at
+	VectorMA (r_refdef.vieworg, 4096, forward, dest);
+	TraceLine (r_refdef.vieworg, dest, stop);
+
+	// calculate pitch to look at the same spot from camera
+	VectorSubtract (stop, r_refdef.vieworg, stop);
+	dist = DotProduct (stop, forward);
+	if (dist < 1)
+		dist = 1;
+	r_refdef.viewangles[PITCH] = -atan(stop[2] / dist) / M_PI * 180;
+
+	// move towards destination
+	VectorCopy (chase_dest, r_refdef.vieworg);
+}
+
--- /dev/null
+++ b/WinQuake/cl_demo.c
@@ -1,0 +1,367 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+
+#include "quakedef.h"
+
+void CL_FinishTimeDemo (void);
+
+/*
+==============================================================================
+
+DEMO CODE
+
+When a demo is playing back, all NET_SendMessages are skipped, and
+NET_GetMessages are read from the demo file.
+
+Whenever cl.time gets past the last received message, another message is
+read from the demo file.
+==============================================================================
+*/
+
+/*
+==============
+CL_StopPlayback
+
+Called when a demo file runs out, or the user starts a game
+==============
+*/
+void CL_StopPlayback (void)
+{
+	if (!cls.demoplayback)
+		return;
+
+	fclose (cls.demofile);
+	cls.demoplayback = false;
+	cls.demofile = NULL;
+	cls.state = ca_disconnected;
+
+	if (cls.timedemo)
+		CL_FinishTimeDemo ();
+}
+
+/*
+====================
+CL_WriteDemoMessage
+
+Dumps the current net message, prefixed by the length and view angles
+====================
+*/
+void CL_WriteDemoMessage (void)
+{
+	int		len;
+	int		i;
+	float	f;
+
+	len = LittleLong (net_message.cursize);
+	fwrite (&len, 4, 1, cls.demofile);
+	for (i=0 ; i<3 ; i++)
+	{
+		f = LittleFloat (cl.viewangles[i]);
+		fwrite (&f, 4, 1, cls.demofile);
+	}
+	fwrite (net_message.data, net_message.cursize, 1, cls.demofile);
+	fflush (cls.demofile);
+}
+
+/*
+====================
+CL_GetMessage
+
+Handles recording and playback of demos, on top of NET_ code
+====================
+*/
+int CL_GetMessage (void)
+{
+	int		r, i;
+	float	f;
+	
+	if	(cls.demoplayback)
+	{
+	// decide if it is time to grab the next message		
+		if (cls.signon == SIGNONS)	// allways grab until fully connected
+		{
+			if (cls.timedemo)
+			{
+				if (host_framecount == cls.td_lastframe)
+					return 0;		// allready read this frame's message
+				cls.td_lastframe = host_framecount;
+			// if this is the second frame, grab the real td_starttime
+			// so the bogus time on the first frame doesn't count
+				if (host_framecount == cls.td_startframe + 1)
+					cls.td_starttime = realtime;
+			}
+			else if ( /* cl.time > 0 && */ cl.time <= cl.mtime[0])
+			{
+					return 0;		// don't need another message yet
+			}
+		}
+		
+	// get the next message
+		fread (&net_message.cursize, 4, 1, cls.demofile);
+		VectorCopy (cl.mviewangles[0], cl.mviewangles[1]);
+		for (i=0 ; i<3 ; i++)
+		{
+			r = fread (&f, 4, 1, cls.demofile);
+			cl.mviewangles[0][i] = LittleFloat (f);
+		}
+		
+		net_message.cursize = LittleLong (net_message.cursize);
+		if (net_message.cursize > MAX_MSGLEN)
+			Sys_Error ("Demo message > MAX_MSGLEN");
+		r = fread (net_message.data, net_message.cursize, 1, cls.demofile);
+		if (r != 1)
+		{
+			CL_StopPlayback ();
+			return 0;
+		}
+	
+		return 1;
+	}
+
+	while (1)
+	{
+		r = NET_GetMessage (cls.netcon);
+		
+		if (r != 1 && r != 2)
+			return r;
+	
+	// discard nop keepalive message
+		if (net_message.cursize == 1 && net_message.data[0] == svc_nop)
+			Con_Printf ("<-- server to client keepalive\n");
+		else
+			break;
+	}
+
+	if (cls.demorecording)
+		CL_WriteDemoMessage ();
+	
+	return r;
+}
+
+
+/*
+====================
+CL_Stop_f
+
+stop recording a demo
+====================
+*/
+void CL_Stop_f (void)
+{
+	if (cmd_source != src_command)
+		return;
+
+	if (!cls.demorecording)
+	{
+		Con_Printf ("Not recording a demo.\n");
+		return;
+	}
+
+// write a disconnect message to the demo file
+	SZ_Clear (&net_message);
+	MSG_WriteByte (&net_message, svc_disconnect);
+	CL_WriteDemoMessage ();
+
+// finish up
+	fclose (cls.demofile);
+	cls.demofile = NULL;
+	cls.demorecording = false;
+	Con_Printf ("Completed demo\n");
+}
+
+/*
+====================
+CL_Record_f
+
+record <demoname> <map> [cd track]
+====================
+*/
+void CL_Record_f (void)
+{
+	int		c;
+	char	name[MAX_OSPATH];
+	int		track;
+
+	if (cmd_source != src_command)
+		return;
+
+	c = Cmd_Argc();
+	if (c != 2 && c != 3 && c != 4)
+	{
+		Con_Printf ("record <demoname> [<map> [cd track]]\n");
+		return;
+	}
+
+	if (strstr(Cmd_Argv(1), ".."))
+	{
+		Con_Printf ("Relative pathnames are not allowed.\n");
+		return;
+	}
+
+	if (c == 2 && cls.state == ca_connected)
+	{
+		Con_Printf("Can not record - already connected to server\nClient demo recording must be started before connecting\n");
+		return;
+	}
+
+// write the forced cd track number, or -1
+	if (c == 4)
+	{
+		track = atoi(Cmd_Argv(3));
+		Con_Printf ("Forcing CD track to %i\n", cls.forcetrack);
+	}
+	else
+		track = -1;	
+
+	sprintf (name, "%s/%s", com_gamedir, Cmd_Argv(1));
+	
+//
+// start the map up
+//
+	if (c > 2)
+		Cmd_ExecuteString ( va("map %s", Cmd_Argv(2)), src_command);
+	
+//
+// open the demo file
+//
+	COM_DefaultExtension (name, ".dem");
+
+	Con_Printf ("recording to %s.\n", name);
+	cls.demofile = fopen (name, "wb");
+	if (!cls.demofile)
+	{
+		Con_Printf ("ERROR: couldn't open.\n");
+		return;
+	}
+
+	cls.forcetrack = track;
+	fprintf (cls.demofile, "%i\n", cls.forcetrack);
+	
+	cls.demorecording = true;
+}
+
+
+/*
+====================
+CL_PlayDemo_f
+
+play [demoname]
+====================
+*/
+void CL_PlayDemo_f (void)
+{
+	char	name[256];
+	int c;
+	qboolean neg = false;
+
+	if (cmd_source != src_command)
+		return;
+
+	if (Cmd_Argc() != 2)
+	{
+		Con_Printf ("play <demoname> : plays a demo\n");
+		return;
+	}
+
+//
+// disconnect from server
+//
+	CL_Disconnect ();
+	
+//
+// open the demo file
+//
+	strcpy (name, Cmd_Argv(1));
+	COM_DefaultExtension (name, ".dem");
+
+	Con_Printf ("Playing demo from %s.\n", name);
+	COM_FOpenFile (name, &cls.demofile);
+	if (!cls.demofile)
+	{
+		Con_Printf ("ERROR: couldn't open.\n");
+		cls.demonum = -1;		// stop demo loop
+		return;
+	}
+
+	cls.demoplayback = true;
+	cls.state = ca_connected;
+	cls.forcetrack = 0;
+
+	while ((c = getc(cls.demofile)) != '\n')
+		if (c == '-')
+			neg = true;
+		else
+			cls.forcetrack = cls.forcetrack * 10 + (c - '0');
+
+	if (neg)
+		cls.forcetrack = -cls.forcetrack;
+// ZOID, fscanf is evil
+//	fscanf (cls.demofile, "%i\n", &cls.forcetrack);
+}
+
+/*
+====================
+CL_FinishTimeDemo
+
+====================
+*/
+void CL_FinishTimeDemo (void)
+{
+	int		frames;
+	float	time;
+	
+	cls.timedemo = false;
+	
+// the first frame didn't count
+	frames = (host_framecount - cls.td_startframe) - 1;
+	time = realtime - cls.td_starttime;
+	if (!time)
+		time = 1;
+	Con_Printf ("%i frames %5.1f seconds %5.1f fps\n", frames, time, frames/time);
+}
+
+/*
+====================
+CL_TimeDemo_f
+
+timedemo [demoname]
+====================
+*/
+void CL_TimeDemo_f (void)
+{
+	if (cmd_source != src_command)
+		return;
+
+	if (Cmd_Argc() != 2)
+	{
+		Con_Printf ("timedemo <demoname> : gets demo speeds\n");
+		return;
+	}
+
+	CL_PlayDemo_f ();
+	
+// cls.td_starttime will be grabbed at the second frame of the demo, so
+// all the loading time doesn't get counted
+	
+	cls.timedemo = true;
+	cls.td_startframe = host_framecount;
+	cls.td_lastframe = -1;		// get a new message this frame
+}
+
--- /dev/null
+++ b/WinQuake/cl_input.c
@@ -1,0 +1,448 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// cl.input.c  -- builds an intended movement command to send to the server
+
+// Quake is a trademark of Id Software, Inc., (c) 1996 Id Software, Inc. All
+// rights reserved.
+
+#include "quakedef.h"
+
+/*
+===============================================================================
+
+KEY BUTTONS
+
+Continuous button event tracking is complicated by the fact that two different
+input sources (say, mouse button 1 and the control key) can both press the
+same button, but the button should only be released when both of the
+pressing key have been released.
+
+When a key event issues a button command (+forward, +attack, etc), it appends
+its key number as a parameter to the command so it can be matched up with
+the release.
+
+state bit 0 is the current state of the key
+state bit 1 is edge triggered on the up to down transition
+state bit 2 is edge triggered on the down to up transition
+
+===============================================================================
+*/
+
+
+kbutton_t	in_mlook, in_klook;
+kbutton_t	in_left, in_right, in_forward, in_back;
+kbutton_t	in_lookup, in_lookdown, in_moveleft, in_moveright;
+kbutton_t	in_strafe, in_speed, in_use, in_jump, in_attack;
+kbutton_t	in_up, in_down;
+
+int			in_impulse;
+
+
+void KeyDown (kbutton_t *b)
+{
+	int		k;
+	char	*c;
+
+	c = Cmd_Argv(1);
+	if (c[0])
+		k = atoi(c);
+	else
+		k = -1;		// typed manually at the console for continuous down
+
+	if (k == b->down[0] || k == b->down[1])
+		return;		// repeating key
+	
+	if (!b->down[0])
+		b->down[0] = k;
+	else if (!b->down[1])
+		b->down[1] = k;
+	else
+	{
+		Con_Printf ("Three keys down for a button!\n");
+		return;
+	}
+	
+	if (b->state & 1)
+		return;		// still down
+	b->state |= 1 + 2;	// down + impulse down
+}
+
+void KeyUp (kbutton_t *b)
+{
+	int		k;
+	char	*c;
+	
+	c = Cmd_Argv(1);
+	if (c[0])
+		k = atoi(c);
+	else
+	{ // typed manually at the console, assume for unsticking, so clear all
+		b->down[0] = b->down[1] = 0;
+		b->state = 4;	// impulse up
+		return;
+	}
+
+	if (b->down[0] == k)
+		b->down[0] = 0;
+	else if (b->down[1] == k)
+		b->down[1] = 0;
+	else
+		return;		// key up without coresponding down (menu pass through)
+	if (b->down[0] || b->down[1])
+		return;		// some other key is still holding it down
+
+	if (!(b->state & 1))
+		return;		// still up (this should not happen)
+	b->state &= ~1;		// now up
+	b->state |= 4; 		// impulse up
+}
+
+void IN_KLookDown (void) {KeyDown(&in_klook);}
+void IN_KLookUp (void) {KeyUp(&in_klook);}
+void IN_MLookDown (void) {KeyDown(&in_mlook);}
+void IN_MLookUp (void) {
+KeyUp(&in_mlook);
+if ( !(in_mlook.state&1) &&  lookspring.value)
+	V_StartPitchDrift();
+}
+void IN_UpDown(void) {KeyDown(&in_up);}
+void IN_UpUp(void) {KeyUp(&in_up);}
+void IN_DownDown(void) {KeyDown(&in_down);}
+void IN_DownUp(void) {KeyUp(&in_down);}
+void IN_LeftDown(void) {KeyDown(&in_left);}
+void IN_LeftUp(void) {KeyUp(&in_left);}
+void IN_RightDown(void) {KeyDown(&in_right);}
+void IN_RightUp(void) {KeyUp(&in_right);}
+void IN_ForwardDown(void) {KeyDown(&in_forward);}
+void IN_ForwardUp(void) {KeyUp(&in_forward);}
+void IN_BackDown(void) {KeyDown(&in_back);}
+void IN_BackUp(void) {KeyUp(&in_back);}
+void IN_LookupDown(void) {KeyDown(&in_lookup);}
+void IN_LookupUp(void) {KeyUp(&in_lookup);}
+void IN_LookdownDown(void) {KeyDown(&in_lookdown);}
+void IN_LookdownUp(void) {KeyUp(&in_lookdown);}
+void IN_MoveleftDown(void) {KeyDown(&in_moveleft);}
+void IN_MoveleftUp(void) {KeyUp(&in_moveleft);}
+void IN_MoverightDown(void) {KeyDown(&in_moveright);}
+void IN_MoverightUp(void) {KeyUp(&in_moveright);}
+
+void IN_SpeedDown(void) {KeyDown(&in_speed);}
+void IN_SpeedUp(void) {KeyUp(&in_speed);}
+void IN_StrafeDown(void) {KeyDown(&in_strafe);}
+void IN_StrafeUp(void) {KeyUp(&in_strafe);}
+
+void IN_AttackDown(void) {KeyDown(&in_attack);}
+void IN_AttackUp(void) {KeyUp(&in_attack);}
+
+void IN_UseDown (void) {KeyDown(&in_use);}
+void IN_UseUp (void) {KeyUp(&in_use);}
+void IN_JumpDown (void) {KeyDown(&in_jump);}
+void IN_JumpUp (void) {KeyUp(&in_jump);}
+
+void IN_Impulse (void) {in_impulse=Q_atoi(Cmd_Argv(1));}
+
+/*
+===============
+CL_KeyState
+
+Returns 0.25 if a key was pressed and released during the frame,
+0.5 if it was pressed and held
+0 if held then released, and
+1.0 if held for the entire time
+===============
+*/
+float CL_KeyState (kbutton_t *key)
+{
+	float		val;
+	qboolean	impulsedown, impulseup, down;
+	
+	impulsedown = key->state & 2;
+	impulseup = key->state & 4;
+	down = key->state & 1;
+	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
+
+	key->state &= 1;		// clear impulses
+	
+	return val;
+}
+
+
+
+
+//==========================================================================
+
+cvar_t	cl_upspeed = {"cl_upspeed","200"};
+cvar_t	cl_forwardspeed = {"cl_forwardspeed","200", true};
+cvar_t	cl_backspeed = {"cl_backspeed","200", true};
+cvar_t	cl_sidespeed = {"cl_sidespeed","350"};
+
+cvar_t	cl_movespeedkey = {"cl_movespeedkey","2.0"};
+
+cvar_t	cl_yawspeed = {"cl_yawspeed","140"};
+cvar_t	cl_pitchspeed = {"cl_pitchspeed","150"};
+
+cvar_t	cl_anglespeedkey = {"cl_anglespeedkey","1.5"};
+
+
+/*
+================
+CL_AdjustAngles
+
+Moves the local angle positions
+================
+*/
+void CL_AdjustAngles (void)
+{
+	float	speed;
+	float	up, down;
+	
+	if (in_speed.state & 1)
+		speed = host_frametime * cl_anglespeedkey.value;
+	else
+		speed = host_frametime;
+
+	if (!(in_strafe.state & 1))
+	{
+		cl.viewangles[YAW] -= speed*cl_yawspeed.value*CL_KeyState (&in_right);
+		cl.viewangles[YAW] += speed*cl_yawspeed.value*CL_KeyState (&in_left);
+		cl.viewangles[YAW] = anglemod(cl.viewangles[YAW]);
+	}
+	if (in_klook.state & 1)
+	{
+		V_StopPitchDrift ();
+		cl.viewangles[PITCH] -= speed*cl_pitchspeed.value * CL_KeyState (&in_forward);
+		cl.viewangles[PITCH] += speed*cl_pitchspeed.value * CL_KeyState (&in_back);
+	}
+	
+	up = CL_KeyState (&in_lookup);
+	down = CL_KeyState(&in_lookdown);
+	
+	cl.viewangles[PITCH] -= speed*cl_pitchspeed.value * up;
+	cl.viewangles[PITCH] += speed*cl_pitchspeed.value * down;
+
+	if (up || down)
+		V_StopPitchDrift ();
+		
+	if (cl.viewangles[PITCH] > 80)
+		cl.viewangles[PITCH] = 80;
+	if (cl.viewangles[PITCH] < -70)
+		cl.viewangles[PITCH] = -70;
+
+	if (cl.viewangles[ROLL] > 50)
+		cl.viewangles[ROLL] = 50;
+	if (cl.viewangles[ROLL] < -50)
+		cl.viewangles[ROLL] = -50;
+		
+}
+
+/*
+================
+CL_BaseMove
+
+Send the intended movement message to the server
+================
+*/
+void CL_BaseMove (usercmd_t *cmd)
+{	
+	if (cls.signon != SIGNONS)
+		return;
+			
+	CL_AdjustAngles ();
+	
+	Q_memset (cmd, 0, sizeof(*cmd));
+	
+	if (in_strafe.state & 1)
+	{
+		cmd->sidemove += cl_sidespeed.value * CL_KeyState (&in_right);
+		cmd->sidemove -= cl_sidespeed.value * CL_KeyState (&in_left);
+	}
+
+	cmd->sidemove += cl_sidespeed.value * CL_KeyState (&in_moveright);
+	cmd->sidemove -= cl_sidespeed.value * CL_KeyState (&in_moveleft);
+
+	cmd->upmove += cl_upspeed.value * CL_KeyState (&in_up);
+	cmd->upmove -= cl_upspeed.value * CL_KeyState (&in_down);
+
+	if (! (in_klook.state & 1) )
+	{	
+		cmd->forwardmove += cl_forwardspeed.value * CL_KeyState (&in_forward);
+		cmd->forwardmove -= cl_backspeed.value * CL_KeyState (&in_back);
+	}	
+
+//
+// adjust for speed key
+//
+	if (in_speed.state & 1)
+	{
+		cmd->forwardmove *= cl_movespeedkey.value;
+		cmd->sidemove *= cl_movespeedkey.value;
+		cmd->upmove *= cl_movespeedkey.value;
+	}
+
+#ifdef QUAKE2
+	cmd->lightlevel = cl.light_level;
+#endif
+}
+
+
+
+/*
+==============
+CL_SendMove
+==============
+*/
+void CL_SendMove (usercmd_t *cmd)
+{
+	int		i;
+	int		bits;
+	sizebuf_t	buf;
+	byte	data[128];
+	
+	buf.maxsize = 128;
+	buf.cursize = 0;
+	buf.data = data;
+	
+	cl.cmd = *cmd;
+
+//
+// send the movement message
+//
+    MSG_WriteByte (&buf, clc_move);
+
+	MSG_WriteFloat (&buf, cl.mtime[0]);	// so server can get ping times
+
+	for (i=0 ; i<3 ; i++)
+		MSG_WriteAngle (&buf, cl.viewangles[i]);
+	
+    MSG_WriteShort (&buf, cmd->forwardmove);
+    MSG_WriteShort (&buf, cmd->sidemove);
+    MSG_WriteShort (&buf, cmd->upmove);
+
+//
+// send button bits
+//
+	bits = 0;
+	
+	if ( in_attack.state & 3 )
+		bits |= 1;
+	in_attack.state &= ~2;
+	
+	if (in_jump.state & 3)
+		bits |= 2;
+	in_jump.state &= ~2;
+	
+    MSG_WriteByte (&buf, bits);
+
+    MSG_WriteByte (&buf, in_impulse);
+	in_impulse = 0;
+
+#ifdef QUAKE2
+//
+// light level
+//
+	MSG_WriteByte (&buf, cmd->lightlevel);
+#endif
+
+//
+// deliver the message
+//
+	if (cls.demoplayback)
+		return;
+
+//
+// allways dump the first two message, because it may contain leftover inputs
+// from the last level
+//
+	if (++cl.movemessages <= 2)
+		return;
+	
+	if (NET_SendUnreliableMessage (cls.netcon, &buf) == -1)
+	{
+		Con_Printf ("CL_SendMove: lost server connection\n");
+		CL_Disconnect ();
+	}
+}
+
+/*
+============
+CL_InitInput
+============
+*/
+void CL_InitInput (void)
+{
+	Cmd_AddCommand ("+moveup",IN_UpDown);
+	Cmd_AddCommand ("-moveup",IN_UpUp);
+	Cmd_AddCommand ("+movedown",IN_DownDown);
+	Cmd_AddCommand ("-movedown",IN_DownUp);
+	Cmd_AddCommand ("+left",IN_LeftDown);
+	Cmd_AddCommand ("-left",IN_LeftUp);
+	Cmd_AddCommand ("+right",IN_RightDown);
+	Cmd_AddCommand ("-right",IN_RightUp);
+	Cmd_AddCommand ("+forward",IN_ForwardDown);
+	Cmd_AddCommand ("-forward",IN_ForwardUp);
+	Cmd_AddCommand ("+back",IN_BackDown);
+	Cmd_AddCommand ("-back",IN_BackUp);
+	Cmd_AddCommand ("+lookup", IN_LookupDown);
+	Cmd_AddCommand ("-lookup", IN_LookupUp);
+	Cmd_AddCommand ("+lookdown", IN_LookdownDown);
+	Cmd_AddCommand ("-lookdown", IN_LookdownUp);
+	Cmd_AddCommand ("+strafe", IN_StrafeDown);
+	Cmd_AddCommand ("-strafe", IN_StrafeUp);
+	Cmd_AddCommand ("+moveleft", IN_MoveleftDown);
+	Cmd_AddCommand ("-moveleft", IN_MoveleftUp);
+	Cmd_AddCommand ("+moveright", IN_MoverightDown);
+	Cmd_AddCommand ("-moveright", IN_MoverightUp);
+	Cmd_AddCommand ("+speed", IN_SpeedDown);
+	Cmd_AddCommand ("-speed", IN_SpeedUp);
+	Cmd_AddCommand ("+attack", IN_AttackDown);
+	Cmd_AddCommand ("-attack", IN_AttackUp);
+	Cmd_AddCommand ("+use", IN_UseDown);
+	Cmd_AddCommand ("-use", IN_UseUp);
+	Cmd_AddCommand ("+jump", IN_JumpDown);
+	Cmd_AddCommand ("-jump", IN_JumpUp);
+	Cmd_AddCommand ("impulse", IN_Impulse);
+	Cmd_AddCommand ("+klook", IN_KLookDown);
+	Cmd_AddCommand ("-klook", IN_KLookUp);
+	Cmd_AddCommand ("+mlook", IN_MLookDown);
+	Cmd_AddCommand ("-mlook", IN_MLookUp);
+
+}
+
--- /dev/null
+++ b/WinQuake/cl_main.c
@@ -1,0 +1,757 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// cl_main.c  -- client main loop
+
+#include "quakedef.h"
+
+// we need to declare some mouse variables here, because the menu system
+// references them even when on a unix system.
+
+// these two are not intended to be set directly
+cvar_t	cl_name = {"_cl_name", "player", true};
+cvar_t	cl_color = {"_cl_color", "0", true};
+
+cvar_t	cl_shownet = {"cl_shownet","0"};	// can be 0, 1, or 2
+cvar_t	cl_nolerp = {"cl_nolerp","0"};
+
+cvar_t	lookspring = {"lookspring","0", true};
+cvar_t	lookstrafe = {"lookstrafe","0", true};
+cvar_t	sensitivity = {"sensitivity","3", true};
+
+cvar_t	m_pitch = {"m_pitch","0.022", true};
+cvar_t	m_yaw = {"m_yaw","0.022", true};
+cvar_t	m_forward = {"m_forward","1", true};
+cvar_t	m_side = {"m_side","0.8", true};
+
+
+client_static_t	cls;
+client_state_t	cl;
+// FIXME: put these on hunk?
+efrag_t			cl_efrags[MAX_EFRAGS];
+entity_t		cl_entities[MAX_EDICTS];
+entity_t		cl_static_entities[MAX_STATIC_ENTITIES];
+lightstyle_t	cl_lightstyle[MAX_LIGHTSTYLES];
+dlight_t		cl_dlights[MAX_DLIGHTS];
+
+int				cl_numvisedicts;
+entity_t		*cl_visedicts[MAX_VISEDICTS];
+
+/*
+=====================
+CL_ClearState
+
+=====================
+*/
+void CL_ClearState (void)
+{
+	int			i;
+
+	if (!sv.active)
+		Host_ClearMemory ();
+
+// wipe the entire cl structure
+	memset (&cl, 0, sizeof(cl));
+
+	SZ_Clear (&cls.message);
+
+// clear other arrays	
+	memset (cl_efrags, 0, sizeof(cl_efrags));
+	memset (cl_entities, 0, sizeof(cl_entities));
+	memset (cl_dlights, 0, sizeof(cl_dlights));
+	memset (cl_lightstyle, 0, sizeof(cl_lightstyle));
+	memset (cl_temp_entities, 0, sizeof(cl_temp_entities));
+	memset (cl_beams, 0, sizeof(cl_beams));
+
+//
+// allocate the efrags and chain together into a free list
+//
+	cl.free_efrags = cl_efrags;
+	for (i=0 ; i<MAX_EFRAGS-1 ; i++)
+		cl.free_efrags[i].entnext = &cl.free_efrags[i+1];
+	cl.free_efrags[i].entnext = NULL;
+}
+
+/*
+=====================
+CL_Disconnect
+
+Sends a disconnect message to the server
+This is also called on Host_Error, so it shouldn't cause any errors
+=====================
+*/
+void CL_Disconnect (void)
+{
+// stop sounds (especially looping!)
+	S_StopAllSounds (true);
+	
+// bring the console down and fade the colors back to normal
+//	SCR_BringDownConsole ();
+
+// if running a local server, shut it down
+	if (cls.demoplayback)
+		CL_StopPlayback ();
+	else if (cls.state == ca_connected)
+	{
+		if (cls.demorecording)
+			CL_Stop_f ();
+
+		Con_DPrintf ("Sending clc_disconnect\n");
+		SZ_Clear (&cls.message);
+		MSG_WriteByte (&cls.message, clc_disconnect);
+		NET_SendUnreliableMessage (cls.netcon, &cls.message);
+		SZ_Clear (&cls.message);
+		NET_Close (cls.netcon);
+
+		cls.state = ca_disconnected;
+		if (sv.active)
+			Host_ShutdownServer(false);
+	}
+
+	cls.demoplayback = cls.timedemo = false;
+	cls.signon = 0;
+}
+
+void CL_Disconnect_f (void)
+{
+	CL_Disconnect ();
+	if (sv.active)
+		Host_ShutdownServer (false);
+}
+
+
+
+
+/*
+=====================
+CL_EstablishConnection
+
+Host should be either "local" or a net address to be passed on
+=====================
+*/
+void CL_EstablishConnection (char *host)
+{
+	if (cls.state == ca_dedicated)
+		return;
+
+	if (cls.demoplayback)
+		return;
+
+	CL_Disconnect ();
+
+	cls.netcon = NET_Connect (host);
+	if (!cls.netcon)
+		Host_Error ("CL_Connect: connect failed\n");
+	Con_DPrintf ("CL_EstablishConnection: connected to %s\n", host);
+	
+	cls.demonum = -1;			// not in the demo loop now
+	cls.state = ca_connected;
+	cls.signon = 0;				// need all the signon messages before playing
+}
+
+/*
+=====================
+CL_SignonReply
+
+An svc_signonnum has been received, perform a client side setup
+=====================
+*/
+void CL_SignonReply (void)
+{
+	char 	str[8192];
+
+Con_DPrintf ("CL_SignonReply: %i\n", cls.signon);
+
+	switch (cls.signon)
+	{
+	case 1:
+		MSG_WriteByte (&cls.message, clc_stringcmd);
+		MSG_WriteString (&cls.message, "prespawn");
+		break;
+		
+	case 2:		
+		MSG_WriteByte (&cls.message, clc_stringcmd);
+		MSG_WriteString (&cls.message, va("name \"%s\"\n", cl_name.string));
+	
+		MSG_WriteByte (&cls.message, clc_stringcmd);
+		MSG_WriteString (&cls.message, va("color %i %i\n", ((int)cl_color.value)>>4, ((int)cl_color.value)&15));
+	
+		MSG_WriteByte (&cls.message, clc_stringcmd);
+		sprintf (str, "spawn %s", cls.spawnparms);
+		MSG_WriteString (&cls.message, str);
+		break;
+		
+	case 3:	
+		MSG_WriteByte (&cls.message, clc_stringcmd);
+		MSG_WriteString (&cls.message, "begin");
+		Cache_Report ();		// print remaining memory
+		break;
+		
+	case 4:
+		SCR_EndLoadingPlaque ();		// allow normal screen updates
+		break;
+	}
+}
+
+/*
+=====================
+CL_NextDemo
+
+Called to play the next demo in the demo loop
+=====================
+*/
+void CL_NextDemo (void)
+{
+	char	str[1024];
+
+	if (cls.demonum == -1)
+		return;		// don't play demos
+
+	SCR_BeginLoadingPlaque ();
+
+	if (!cls.demos[cls.demonum][0] || cls.demonum == MAX_DEMOS)
+	{
+		cls.demonum = 0;
+		if (!cls.demos[cls.demonum][0])
+		{
+			Con_Printf ("No demos listed with startdemos\n");
+			cls.demonum = -1;
+			return;
+		}
+	}
+
+	sprintf (str,"playdemo %s\n", cls.demos[cls.demonum]);
+	Cbuf_InsertText (str);
+	cls.demonum++;
+}
+
+/*
+==============
+CL_PrintEntities_f
+==============
+*/
+void CL_PrintEntities_f (void)
+{
+	entity_t	*ent;
+	int			i;
+	
+	for (i=0,ent=cl_entities ; i<cl.num_entities ; i++,ent++)
+	{
+		Con_Printf ("%3i:",i);
+		if (!ent->model)
+		{
+			Con_Printf ("EMPTY\n");
+			continue;
+		}
+		Con_Printf ("%s:%2i  (%5.1f,%5.1f,%5.1f) [%5.1f %5.1f %5.1f]\n"
+		,ent->model->name,ent->frame, ent->origin[0], ent->origin[1], ent->origin[2], ent->angles[0], ent->angles[1], ent->angles[2]);
+	}
+}
+
+
+/*
+===============
+SetPal
+
+Debugging tool, just flashes the screen
+===============
+*/
+void SetPal (int i)
+{
+#if 0
+	static int old;
+	byte	pal[768];
+	int		c;
+	
+	if (i == old)
+		return;
+	old = i;
+
+	if (i==0)
+		VID_SetPalette (host_basepal);
+	else if (i==1)
+	{
+		for (c=0 ; c<768 ; c+=3)
+		{
+			pal[c] = 0;
+			pal[c+1] = 255;
+			pal[c+2] = 0;
+		}
+		VID_SetPalette (pal);
+	}
+	else
+	{
+		for (c=0 ; c<768 ; c+=3)
+		{
+			pal[c] = 0;
+			pal[c+1] = 0;
+			pal[c+2] = 255;
+		}
+		VID_SetPalette (pal);
+	}
+#endif
+}
+
+/*
+===============
+CL_AllocDlight
+
+===============
+*/
+dlight_t *CL_AllocDlight (int key)
+{
+	int		i;
+	dlight_t	*dl;
+
+// first look for an exact key match
+	if (key)
+	{
+		dl = cl_dlights;
+		for (i=0 ; i<MAX_DLIGHTS ; i++, dl++)
+		{
+			if (dl->key == key)
+			{
+				memset (dl, 0, sizeof(*dl));
+				dl->key = key;
+				return dl;
+			}
+		}
+	}
+
+// then look for anything else
+	dl = cl_dlights;
+	for (i=0 ; i<MAX_DLIGHTS ; i++, dl++)
+	{
+		if (dl->die < cl.time)
+		{
+			memset (dl, 0, sizeof(*dl));
+			dl->key = key;
+			return dl;
+		}
+	}
+
+	dl = &cl_dlights[0];
+	memset (dl, 0, sizeof(*dl));
+	dl->key = key;
+	return dl;
+}
+
+
+/*
+===============
+CL_DecayLights
+
+===============
+*/
+void CL_DecayLights (void)
+{
+	int			i;
+	dlight_t	*dl;
+	float		time;
+	
+	time = cl.time - cl.oldtime;
+
+	dl = cl_dlights;
+	for (i=0 ; i<MAX_DLIGHTS ; i++, dl++)
+	{
+		if (dl->die < cl.time || !dl->radius)
+			continue;
+		
+		dl->radius -= time*dl->decay;
+		if (dl->radius < 0)
+			dl->radius = 0;
+	}
+}
+
+
+/*
+===============
+CL_LerpPoint
+
+Determines the fraction between the last two messages that the objects
+should be put at.
+===============
+*/
+float	CL_LerpPoint (void)
+{
+	float	f, frac;
+
+	f = cl.mtime[0] - cl.mtime[1];
+	
+	if (!f || cl_nolerp.value || cls.timedemo || sv.active)
+	{
+		cl.time = cl.mtime[0];
+		return 1;
+	}
+		
+	if (f > 0.1)
+	{	// dropped packet, or start of demo
+		cl.mtime[1] = cl.mtime[0] - 0.1;
+		f = 0.1;
+	}
+	frac = (cl.time - cl.mtime[1]) / f;
+//Con_Printf ("frac: %f\n",frac);
+	if (frac < 0)
+	{
+		if (frac < -0.01)
+		{
+SetPal(1);
+			cl.time = cl.mtime[1];
+//				Con_Printf ("low frac\n");
+		}
+		frac = 0;
+	}
+	else if (frac > 1)
+	{
+		if (frac > 1.01)
+		{
+SetPal(2);
+			cl.time = cl.mtime[0];
+//				Con_Printf ("high frac\n");
+		}
+		frac = 1;
+	}
+	else
+		SetPal(0);
+		
+	return frac;
+}
+
+
+/*
+===============
+CL_RelinkEntities
+===============
+*/
+void CL_RelinkEntities (void)
+{
+	entity_t	*ent;
+	int			i, j;
+	float		frac, f, d;
+	vec3_t		delta;
+	float		bobjrotate;
+	vec3_t		oldorg;
+	dlight_t	*dl;
+
+// determine partial update time	
+	frac = CL_LerpPoint ();
+
+	cl_numvisedicts = 0;
+
+//
+// interpolate player info
+//
+	for (i=0 ; i<3 ; i++)
+		cl.velocity[i] = cl.mvelocity[1][i] + 
+			frac * (cl.mvelocity[0][i] - cl.mvelocity[1][i]);
+
+	if (cls.demoplayback)
+	{
+	// interpolate the angles	
+		for (j=0 ; j<3 ; j++)
+		{
+			d = cl.mviewangles[0][j] - cl.mviewangles[1][j];
+			if (d > 180)
+				d -= 360;
+			else if (d < -180)
+				d += 360;
+			cl.viewangles[j] = cl.mviewangles[1][j] + frac*d;
+		}
+	}
+	
+	bobjrotate = anglemod(100*cl.time);
+	
+// start on the entity after the world
+	for (i=1,ent=cl_entities+1 ; i<cl.num_entities ; i++,ent++)
+	{
+		if (!ent->model)
+		{	// empty slot
+			if (ent->forcelink)
+				R_RemoveEfrags (ent);	// just became empty
+			continue;
+		}
+
+// if the object wasn't included in the last packet, remove it
+		if (ent->msgtime != cl.mtime[0])
+		{
+			ent->model = NULL;
+			continue;
+		}
+
+		VectorCopy (ent->origin, oldorg);
+
+		if (ent->forcelink)
+		{	// the entity was not updated in the last message
+			// so move to the final spot
+			VectorCopy (ent->msg_origins[0], ent->origin);
+			VectorCopy (ent->msg_angles[0], ent->angles);
+		}
+		else
+		{	// if the delta is large, assume a teleport and don't lerp
+			f = frac;
+			for (j=0 ; j<3 ; j++)
+			{
+				delta[j] = ent->msg_origins[0][j] - ent->msg_origins[1][j];
+				if (delta[j] > 100 || delta[j] < -100)
+					f = 1;		// assume a teleportation, not a motion
+			}
+
+		// interpolate the origin and angles
+			for (j=0 ; j<3 ; j++)
+			{
+				ent->origin[j] = ent->msg_origins[1][j] + f*delta[j];
+
+				d = ent->msg_angles[0][j] - ent->msg_angles[1][j];
+				if (d > 180)
+					d -= 360;
+				else if (d < -180)
+					d += 360;
+				ent->angles[j] = ent->msg_angles[1][j] + f*d;
+			}
+			
+		}
+
+// rotate binary objects locally
+		if (ent->model->flags & EF_ROTATE)
+			ent->angles[1] = bobjrotate;
+
+		if (ent->effects & EF_BRIGHTFIELD)
+			R_EntityParticles (ent);
+#ifdef QUAKE2
+		if (ent->effects & EF_DARKFIELD)
+			R_DarkFieldParticles (ent);
+#endif
+		if (ent->effects & EF_MUZZLEFLASH)
+		{
+			vec3_t		fv, rv, uv;
+
+			dl = CL_AllocDlight (i);
+			VectorCopy (ent->origin,  dl->origin);
+			dl->origin[2] += 16;
+			AngleVectors (ent->angles, fv, rv, uv);
+			 
+			VectorMA (dl->origin, 18, fv, dl->origin);
+			dl->radius = 200 + (rand()&31);
+			dl->minlight = 32;
+			dl->die = cl.time + 0.1;
+		}
+		if (ent->effects & EF_BRIGHTLIGHT)
+		{			
+			dl = CL_AllocDlight (i);
+			VectorCopy (ent->origin,  dl->origin);
+			dl->origin[2] += 16;
+			dl->radius = 400 + (rand()&31);
+			dl->die = cl.time + 0.001;
+		}
+		if (ent->effects & EF_DIMLIGHT)
+		{			
+			dl = CL_AllocDlight (i);
+			VectorCopy (ent->origin,  dl->origin);
+			dl->radius = 200 + (rand()&31);
+			dl->die = cl.time + 0.001;
+		}
+#ifdef QUAKE2
+		if (ent->effects & EF_DARKLIGHT)
+		{			
+			dl = CL_AllocDlight (i);
+			VectorCopy (ent->origin,  dl->origin);
+			dl->radius = 200.0 + (rand()&31);
+			dl->die = cl.time + 0.001;
+			dl->dark = true;
+		}
+		if (ent->effects & EF_LIGHT)
+		{			
+			dl = CL_AllocDlight (i);
+			VectorCopy (ent->origin,  dl->origin);
+			dl->radius = 200;
+			dl->die = cl.time + 0.001;
+		}
+#endif
+
+		if (ent->model->flags & EF_GIB)
+			R_RocketTrail (oldorg, ent->origin, 2);
+		else if (ent->model->flags & EF_ZOMGIB)
+			R_RocketTrail (oldorg, ent->origin, 4);
+		else if (ent->model->flags & EF_TRACER)
+			R_RocketTrail (oldorg, ent->origin, 3);
+		else if (ent->model->flags & EF_TRACER2)
+			R_RocketTrail (oldorg, ent->origin, 5);
+		else if (ent->model->flags & EF_ROCKET)
+		{
+			R_RocketTrail (oldorg, ent->origin, 0);
+			dl = CL_AllocDlight (i);
+			VectorCopy (ent->origin, dl->origin);
+			dl->radius = 200;
+			dl->die = cl.time + 0.01;
+		}
+		else if (ent->model->flags & EF_GRENADE)
+			R_RocketTrail (oldorg, ent->origin, 1);
+		else if (ent->model->flags & EF_TRACER3)
+			R_RocketTrail (oldorg, ent->origin, 6);
+
+		ent->forcelink = false;
+
+		if (i == cl.viewentity && !chase_active.value)
+			continue;
+
+#ifdef QUAKE2
+		if ( ent->effects & EF_NODRAW )
+			continue;
+#endif
+		if (cl_numvisedicts < MAX_VISEDICTS)
+		{
+			cl_visedicts[cl_numvisedicts] = ent;
+			cl_numvisedicts++;
+		}
+	}
+
+}
+
+
+/*
+===============
+CL_ReadFromServer
+
+Read all incoming data from the server
+===============
+*/
+int CL_ReadFromServer (void)
+{
+	int		ret;
+
+	cl.oldtime = cl.time;
+	cl.time += host_frametime;
+	
+	do
+	{
+		ret = CL_GetMessage ();
+		if (ret == -1)
+			Host_Error ("CL_ReadFromServer: lost server connection");
+		if (!ret)
+			break;
+		
+		cl.last_received_message = realtime;
+		CL_ParseServerMessage ();
+	} while (ret && cls.state == ca_connected);
+	
+	if (cl_shownet.value)
+		Con_Printf ("\n");
+
+	CL_RelinkEntities ();
+	CL_UpdateTEnts ();
+
+//
+// bring the links up to date
+//
+	return 0;
+}
+
+/*
+=================
+CL_SendCmd
+=================
+*/
+void CL_SendCmd (void)
+{
+	usercmd_t		cmd;
+
+	if (cls.state != ca_connected)
+		return;
+
+	if (cls.signon == SIGNONS)
+	{
+	// get basic movement from keyboard
+		CL_BaseMove (&cmd);
+	
+	// allow mice or other external controllers to add to the move
+		IN_Move (&cmd);
+	
+	// send the unreliable message
+		CL_SendMove (&cmd);
+	
+	}
+
+	if (cls.demoplayback)
+	{
+		SZ_Clear (&cls.message);
+		return;
+	}
+	
+// send the reliable message
+	if (!cls.message.cursize)
+		return;		// no message at all
+	
+	if (!NET_CanSendMessage (cls.netcon))
+	{
+		Con_DPrintf ("CL_WriteToServer: can't send\n");
+		return;
+	}
+
+	if (NET_SendMessage (cls.netcon, &cls.message) == -1)
+		Host_Error ("CL_WriteToServer: lost server connection");
+
+	SZ_Clear (&cls.message);
+}
+
+/*
+=================
+CL_Init
+=================
+*/
+void CL_Init (void)
+{	
+	SZ_Alloc (&cls.message, 1024);
+
+	CL_InitInput ();
+	CL_InitTEnts ();
+	
+//
+// register our commands
+//
+	Cvar_RegisterVariable (&cl_name);
+	Cvar_RegisterVariable (&cl_color);
+	Cvar_RegisterVariable (&cl_upspeed);
+	Cvar_RegisterVariable (&cl_forwardspeed);
+	Cvar_RegisterVariable (&cl_backspeed);
+	Cvar_RegisterVariable (&cl_sidespeed);
+	Cvar_RegisterVariable (&cl_movespeedkey);
+	Cvar_RegisterVariable (&cl_yawspeed);
+	Cvar_RegisterVariable (&cl_pitchspeed);
+	Cvar_RegisterVariable (&cl_anglespeedkey);
+	Cvar_RegisterVariable (&cl_shownet);
+	Cvar_RegisterVariable (&cl_nolerp);
+	Cvar_RegisterVariable (&lookspring);
+	Cvar_RegisterVariable (&lookstrafe);
+	Cvar_RegisterVariable (&sensitivity);
+
+	Cvar_RegisterVariable (&m_pitch);
+	Cvar_RegisterVariable (&m_yaw);
+	Cvar_RegisterVariable (&m_forward);
+	Cvar_RegisterVariable (&m_side);
+
+//	Cvar_RegisterVariable (&cl_autofire);
+	
+	Cmd_AddCommand ("entities", CL_PrintEntities_f);
+	Cmd_AddCommand ("disconnect", CL_Disconnect_f);
+	Cmd_AddCommand ("record", CL_Record_f);
+	Cmd_AddCommand ("stop", CL_Stop_f);
+	Cmd_AddCommand ("playdemo", CL_PlayDemo_f);
+	Cmd_AddCommand ("timedemo", CL_TimeDemo_f);
+}
+
--- /dev/null
+++ b/WinQuake/cl_parse.c
@@ -1,0 +1,963 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// cl_parse.c  -- parse a message received from the server
+
+#include "quakedef.h"
+
+char *svc_strings[] =
+{
+	"svc_bad",
+	"svc_nop",
+	"svc_disconnect",
+	"svc_updatestat",
+	"svc_version",		// [long] server version
+	"svc_setview",		// [short] entity number
+	"svc_sound",			// <see code>
+	"svc_time",			// [float] server time
+	"svc_print",			// [string] null terminated string
+	"svc_stufftext",		// [string] stuffed into client's console buffer
+						// the string should be \n terminated
+	"svc_setangle",		// [vec3] set the view angle to this absolute value
+	
+	"svc_serverinfo",		// [long] version
+						// [string] signon string
+						// [string]..[0]model cache [string]...[0]sounds cache
+						// [string]..[0]item cache
+	"svc_lightstyle",		// [byte] [string]
+	"svc_updatename",		// [byte] [string]
+	"svc_updatefrags",	// [byte] [short]
+	"svc_clientdata",		// <shortbits + data>
+	"svc_stopsound",		// <see code>
+	"svc_updatecolors",	// [byte] [byte]
+	"svc_particle",		// [vec3] <variable>
+	"svc_damage",			// [byte] impact [byte] blood [vec3] from
+	
+	"svc_spawnstatic",
+	"OBSOLETE svc_spawnbinary",
+	"svc_spawnbaseline",
+	
+	"svc_temp_entity",		// <variable>
+	"svc_setpause",
+	"svc_signonnum",
+	"svc_centerprint",
+	"svc_killedmonster",
+	"svc_foundsecret",
+	"svc_spawnstaticsound",
+	"svc_intermission",
+	"svc_finale",			// [string] music [string] text
+	"svc_cdtrack",			// [byte] track [byte] looptrack
+	"svc_sellscreen",
+	"svc_cutscene"
+};
+
+//=============================================================================
+
+/*
+===============
+CL_EntityNum
+
+This error checks and tracks the total number of entities
+===============
+*/
+entity_t	*CL_EntityNum (int num)
+{
+	if (num >= cl.num_entities)
+	{
+		if (num >= MAX_EDICTS)
+			Host_Error ("CL_EntityNum: %i is an invalid number",num);
+		while (cl.num_entities<=num)
+		{
+			cl_entities[cl.num_entities].colormap = vid.colormap;
+			cl.num_entities++;
+		}
+	}
+		
+	return &cl_entities[num];
+}
+
+
+/*
+==================
+CL_ParseStartSoundPacket
+==================
+*/
+void CL_ParseStartSoundPacket(void)
+{
+    vec3_t  pos;
+    int 	channel, ent;
+    int 	sound_num;
+    int 	volume;
+    int 	field_mask;
+    float 	attenuation;  
+ 	int		i;
+	           
+    field_mask = MSG_ReadByte(); 
+
+    if (field_mask & SND_VOLUME)
+		volume = MSG_ReadByte ();
+	else
+		volume = DEFAULT_SOUND_PACKET_VOLUME;
+	
+    if (field_mask & SND_ATTENUATION)
+		attenuation = MSG_ReadByte () / 64.0;
+	else
+		attenuation = DEFAULT_SOUND_PACKET_ATTENUATION;
+	
+	channel = MSG_ReadShort ();
+	sound_num = MSG_ReadByte ();
+
+	ent = channel >> 3;
+	channel &= 7;
+
+	if (ent > MAX_EDICTS)
+		Host_Error ("CL_ParseStartSoundPacket: ent = %i", ent);
+	
+	for (i=0 ; i<3 ; i++)
+		pos[i] = MSG_ReadCoord ();
+ 
+    S_StartSound (ent, channel, cl.sound_precache[sound_num], pos, volume/255.0, attenuation);
+}       
+
+/*
+==================
+CL_KeepaliveMessage
+
+When the client is taking a long time to load stuff, send keepalive messages
+so the server doesn't disconnect.
+==================
+*/
+void CL_KeepaliveMessage (void)
+{
+	float	time;
+	static float lastmsg;
+	int		ret;
+	sizebuf_t	old;
+	byte		olddata[8192];
+	
+	if (sv.active)
+		return;		// no need if server is local
+	if (cls.demoplayback)
+		return;
+
+// read messages from server, should just be nops
+	old = net_message;
+	memcpy (olddata, net_message.data, net_message.cursize);
+	
+	do
+	{
+		ret = CL_GetMessage ();
+		switch (ret)
+		{
+		default:
+			Host_Error ("CL_KeepaliveMessage: CL_GetMessage failed");		
+		case 0:
+			break;	// nothing waiting
+		case 1:
+			Host_Error ("CL_KeepaliveMessage: received a message");
+			break;
+		case 2:
+			if (MSG_ReadByte() != svc_nop)
+				Host_Error ("CL_KeepaliveMessage: datagram wasn't a nop");
+			break;
+		}
+	} while (ret);
+
+	net_message = old;
+	memcpy (net_message.data, olddata, net_message.cursize);
+
+// check time
+	time = Sys_FloatTime ();
+	if (time - lastmsg < 5)
+		return;
+	lastmsg = time;
+
+// write out a nop
+	Con_Printf ("--> client to server keepalive\n");
+
+	MSG_WriteByte (&cls.message, clc_nop);
+	NET_SendMessage (cls.netcon, &cls.message);
+	SZ_Clear (&cls.message);
+}
+
+/*
+==================
+CL_ParseServerInfo
+==================
+*/
+void CL_ParseServerInfo (void)
+{
+	char	*str;
+	int		i;
+	int		nummodels, numsounds;
+	char	model_precache[MAX_MODELS][MAX_QPATH];
+	char	sound_precache[MAX_SOUNDS][MAX_QPATH];
+	
+	Con_DPrintf ("Serverinfo packet received.\n");
+//
+// wipe the client_state_t struct
+//
+	CL_ClearState ();
+
+// parse protocol version number
+	i = MSG_ReadLong ();
+	if (i != PROTOCOL_VERSION)
+	{
+		Con_Printf ("Server returned version %i, not %i", i, PROTOCOL_VERSION);
+		return;
+	}
+
+// parse maxclients
+	cl.maxclients = MSG_ReadByte ();
+	if (cl.maxclients < 1 || cl.maxclients > MAX_SCOREBOARD)
+	{
+		Con_Printf("Bad maxclients (%u) from server\n", cl.maxclients);
+		return;
+	}
+	cl.scores = Hunk_AllocName (cl.maxclients*sizeof(*cl.scores), "scores");
+
+// parse gametype
+	cl.gametype = MSG_ReadByte ();
+
+// parse signon message
+	str = MSG_ReadString ();
+	strncpy (cl.levelname, str, sizeof(cl.levelname)-1);
+
+// seperate the printfs so the server message can have a color
+	Con_Printf("\n\n\35\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\37\n\n");
+	Con_Printf ("%c%s\n", 2, str);
+
+//
+// first we go through and touch all of the precache data that still
+// happens to be in the cache, so precaching something else doesn't
+// needlessly purge it
+//
+
+// precache models
+	memset (cl.model_precache, 0, sizeof(cl.model_precache));
+	for (nummodels=1 ; ; nummodels++)
+	{
+		str = MSG_ReadString ();
+		if (!str[0])
+			break;
+		if (nummodels==MAX_MODELS)
+		{
+			Con_Printf ("Server sent too many model precaches\n");
+			return;
+		}
+		strcpy (model_precache[nummodels], str);
+		Mod_TouchModel (str);
+	}
+
+// precache sounds
+	memset (cl.sound_precache, 0, sizeof(cl.sound_precache));
+	for (numsounds=1 ; ; numsounds++)
+	{
+		str = MSG_ReadString ();
+		if (!str[0])
+			break;
+		if (numsounds==MAX_SOUNDS)
+		{
+			Con_Printf ("Server sent too many sound precaches\n");
+			return;
+		}
+		strcpy (sound_precache[numsounds], str);
+		S_TouchSound (str);
+	}
+
+//
+// now we try to load everything else until a cache allocation fails
+//
+
+	for (i=1 ; i<nummodels ; i++)
+	{
+		cl.model_precache[i] = Mod_ForName (model_precache[i], false);
+		if (cl.model_precache[i] == NULL)
+		{
+			Con_Printf("Model %s not found\n", model_precache[i]);
+			return;
+		}
+		CL_KeepaliveMessage ();
+	}
+
+	S_BeginPrecaching ();
+	for (i=1 ; i<numsounds ; i++)
+	{
+		cl.sound_precache[i] = S_PrecacheSound (sound_precache[i]);
+		CL_KeepaliveMessage ();
+	}
+	S_EndPrecaching ();
+
+
+// local state
+	cl_entities[0].model = cl.worldmodel = cl.model_precache[1];
+	
+	R_NewMap ();
+
+	Hunk_Check ();		// make sure nothing is hurt
+	
+	noclip_anglehack = false;		// noclip is turned off at start	
+}
+
+
+/*
+==================
+CL_ParseUpdate
+
+Parse an entity update message from the server
+If an entities model or origin changes from frame to frame, it must be
+relinked.  Other attributes can change without relinking.
+==================
+*/
+int	bitcounts[16];
+
+void CL_ParseUpdate (int bits)
+{
+	int			i;
+	model_t		*model;
+	int			modnum;
+	qboolean	forcelink;
+	entity_t	*ent;
+	int			num;
+	int			skin;
+
+	if (cls.signon == SIGNONS - 1)
+	{	// first update is the final signon stage
+		cls.signon = SIGNONS;
+		CL_SignonReply ();
+	}
+
+	if (bits & U_MOREBITS)
+	{
+		i = MSG_ReadByte ();
+		bits |= (i<<8);
+	}
+
+	if (bits & U_LONGENTITY)	
+		num = MSG_ReadShort ();
+	else
+		num = MSG_ReadByte ();
+
+	ent = CL_EntityNum (num);
+
+for (i=0 ; i<16 ; i++)
+if (bits&(1<<i))
+	bitcounts[i]++;
+
+	if (ent->msgtime != cl.mtime[1])
+		forcelink = true;	// no previous frame to lerp from
+	else
+		forcelink = false;
+
+	ent->msgtime = cl.mtime[0];
+	
+	if (bits & U_MODEL)
+	{
+		modnum = MSG_ReadByte ();
+		if (modnum >= MAX_MODELS)
+			Host_Error ("CL_ParseModel: bad modnum");
+	}
+	else
+		modnum = ent->baseline.modelindex;
+		
+	model = cl.model_precache[modnum];
+	if (model != ent->model)
+	{
+		ent->model = model;
+	// automatic animation (torches, etc) can be either all together
+	// or randomized
+		if (model)
+		{
+			if (model->synctype == ST_RAND)
+				ent->syncbase = (float)(rand()&0x7fff) / 0x7fff;
+			else
+				ent->syncbase = 0.0;
+		}
+		else
+			forcelink = true;	// hack to make null model players work
+#ifdef GLQUAKE
+		if (num > 0 && num <= cl.maxclients)
+			R_TranslatePlayerSkin (num - 1);
+#endif
+	}
+	
+	if (bits & U_FRAME)
+		ent->frame = MSG_ReadByte ();
+	else
+		ent->frame = ent->baseline.frame;
+
+	if (bits & U_COLORMAP)
+		i = MSG_ReadByte();
+	else
+		i = ent->baseline.colormap;
+	if (!i)
+		ent->colormap = vid.colormap;
+	else
+	{
+		if (i > cl.maxclients)
+			Sys_Error ("i >= cl.maxclients");
+		ent->colormap = cl.scores[i-1].translations;
+	}
+
+#ifdef GLQUAKE
+	if (bits & U_SKIN)
+		skin = MSG_ReadByte();
+	else
+		skin = ent->baseline.skin;
+	if (skin != ent->skinnum) {
+		ent->skinnum = skin;
+		if (num > 0 && num <= cl.maxclients)
+			R_TranslatePlayerSkin (num - 1);
+	}
+
+#else
+
+	if (bits & U_SKIN)
+		ent->skinnum = MSG_ReadByte();
+	else
+		ent->skinnum = ent->baseline.skin;
+#endif
+
+	if (bits & U_EFFECTS)
+		ent->effects = MSG_ReadByte();
+	else
+		ent->effects = ent->baseline.effects;
+
+// shift the known values for interpolation
+	VectorCopy (ent->msg_origins[0], ent->msg_origins[1]);
+	VectorCopy (ent->msg_angles[0], ent->msg_angles[1]);
+
+	if (bits & U_ORIGIN1)
+		ent->msg_origins[0][0] = MSG_ReadCoord ();
+	else
+		ent->msg_origins[0][0] = ent->baseline.origin[0];
+	if (bits & U_ANGLE1)
+		ent->msg_angles[0][0] = MSG_ReadAngle();
+	else
+		ent->msg_angles[0][0] = ent->baseline.angles[0];
+
+	if (bits & U_ORIGIN2)
+		ent->msg_origins[0][1] = MSG_ReadCoord ();
+	else
+		ent->msg_origins[0][1] = ent->baseline.origin[1];
+	if (bits & U_ANGLE2)
+		ent->msg_angles[0][1] = MSG_ReadAngle();
+	else
+		ent->msg_angles[0][1] = ent->baseline.angles[1];
+
+	if (bits & U_ORIGIN3)
+		ent->msg_origins[0][2] = MSG_ReadCoord ();
+	else
+		ent->msg_origins[0][2] = ent->baseline.origin[2];
+	if (bits & U_ANGLE3)
+		ent->msg_angles[0][2] = MSG_ReadAngle();
+	else
+		ent->msg_angles[0][2] = ent->baseline.angles[2];
+
+	if ( bits & U_NOLERP )
+		ent->forcelink = true;
+
+	if ( forcelink )
+	{	// didn't have an update last message
+		VectorCopy (ent->msg_origins[0], ent->msg_origins[1]);
+		VectorCopy (ent->msg_origins[0], ent->origin);
+		VectorCopy (ent->msg_angles[0], ent->msg_angles[1]);
+		VectorCopy (ent->msg_angles[0], ent->angles);
+		ent->forcelink = true;
+	}
+}
+
+/*
+==================
+CL_ParseBaseline
+==================
+*/
+void CL_ParseBaseline (entity_t *ent)
+{
+	int			i;
+	
+	ent->baseline.modelindex = MSG_ReadByte ();
+	ent->baseline.frame = MSG_ReadByte ();
+	ent->baseline.colormap = MSG_ReadByte();
+	ent->baseline.skin = MSG_ReadByte();
+	for (i=0 ; i<3 ; i++)
+	{
+		ent->baseline.origin[i] = MSG_ReadCoord ();
+		ent->baseline.angles[i] = MSG_ReadAngle ();
+	}
+}
+
+
+/*
+==================
+CL_ParseClientdata
+
+Server information pertaining to this client only
+==================
+*/
+void CL_ParseClientdata (int bits)
+{
+	int		i, j;
+	
+	if (bits & SU_VIEWHEIGHT)
+		cl.viewheight = MSG_ReadChar ();
+	else
+		cl.viewheight = DEFAULT_VIEWHEIGHT;
+
+	if (bits & SU_IDEALPITCH)
+		cl.idealpitch = MSG_ReadChar ();
+	else
+		cl.idealpitch = 0;
+	
+	VectorCopy (cl.mvelocity[0], cl.mvelocity[1]);
+	for (i=0 ; i<3 ; i++)
+	{
+		if (bits & (SU_PUNCH1<<i) )
+			cl.punchangle[i] = MSG_ReadChar();
+		else
+			cl.punchangle[i] = 0;
+		if (bits & (SU_VELOCITY1<<i) )
+			cl.mvelocity[0][i] = MSG_ReadChar()*16;
+		else
+			cl.mvelocity[0][i] = 0;
+	}
+
+// [always sent]	if (bits & SU_ITEMS)
+		i = MSG_ReadLong ();
+
+	if (cl.items != i)
+	{	// set flash times
+		Sbar_Changed ();
+		for (j=0 ; j<32 ; j++)
+			if ( (i & (1<<j)) && !(cl.items & (1<<j)))
+				cl.item_gettime[j] = cl.time;
+		cl.items = i;
+	}
+		
+	cl.onground = (bits & SU_ONGROUND) != 0;
+	cl.inwater = (bits & SU_INWATER) != 0;
+
+	if (bits & SU_WEAPONFRAME)
+		cl.stats[STAT_WEAPONFRAME] = MSG_ReadByte ();
+	else
+		cl.stats[STAT_WEAPONFRAME] = 0;
+
+	if (bits & SU_ARMOR)
+		i = MSG_ReadByte ();
+	else
+		i = 0;
+	if (cl.stats[STAT_ARMOR] != i)
+	{
+		cl.stats[STAT_ARMOR] = i;
+		Sbar_Changed ();
+	}
+
+	if (bits & SU_WEAPON)
+		i = MSG_ReadByte ();
+	else
+		i = 0;
+	if (cl.stats[STAT_WEAPON] != i)
+	{
+		cl.stats[STAT_WEAPON] = i;
+		Sbar_Changed ();
+	}
+	
+	i = MSG_ReadShort ();
+	if (cl.stats[STAT_HEALTH] != i)
+	{
+		cl.stats[STAT_HEALTH] = i;
+		Sbar_Changed ();
+	}
+
+	i = MSG_ReadByte ();
+	if (cl.stats[STAT_AMMO] != i)
+	{
+		cl.stats[STAT_AMMO] = i;
+		Sbar_Changed ();
+	}
+
+	for (i=0 ; i<4 ; i++)
+	{
+		j = MSG_ReadByte ();
+		if (cl.stats[STAT_SHELLS+i] != j)
+		{
+			cl.stats[STAT_SHELLS+i] = j;
+			Sbar_Changed ();
+		}
+	}
+
+	i = MSG_ReadByte ();
+
+	if (standard_quake)
+	{
+		if (cl.stats[STAT_ACTIVEWEAPON] != i)
+		{
+			cl.stats[STAT_ACTIVEWEAPON] = i;
+			Sbar_Changed ();
+		}
+	}
+	else
+	{
+		if (cl.stats[STAT_ACTIVEWEAPON] != (1<<i))
+		{
+			cl.stats[STAT_ACTIVEWEAPON] = (1<<i);
+			Sbar_Changed ();
+		}
+	}
+}
+
+/*
+=====================
+CL_NewTranslation
+=====================
+*/
+void CL_NewTranslation (int slot)
+{
+	int		i, j;
+	int		top, bottom;
+	byte	*dest, *source;
+	
+	if (slot > cl.maxclients)
+		Sys_Error ("CL_NewTranslation: slot > cl.maxclients");
+	dest = cl.scores[slot].translations;
+	source = vid.colormap;
+	memcpy (dest, vid.colormap, sizeof(cl.scores[slot].translations));
+	top = cl.scores[slot].colors & 0xf0;
+	bottom = (cl.scores[slot].colors &15)<<4;
+#ifdef GLQUAKE
+	R_TranslatePlayerSkin (slot);
+#endif
+
+	for (i=0 ; i<VID_GRADES ; i++, dest += 256, source+=256)
+	{
+		if (top < 128)	// the artists made some backwards ranges.  sigh.
+			memcpy (dest + TOP_RANGE, source + top, 16);
+		else
+			for (j=0 ; j<16 ; j++)
+				dest[TOP_RANGE+j] = source[top+15-j];
+				
+		if (bottom < 128)
+			memcpy (dest + BOTTOM_RANGE, source + bottom, 16);
+		else
+			for (j=0 ; j<16 ; j++)
+				dest[BOTTOM_RANGE+j] = source[bottom+15-j];		
+	}
+}
+
+/*
+=====================
+CL_ParseStatic
+=====================
+*/
+void CL_ParseStatic (void)
+{
+	entity_t *ent;
+	int		i;
+		
+	i = cl.num_statics;
+	if (i >= MAX_STATIC_ENTITIES)
+		Host_Error ("Too many static entities");
+	ent = &cl_static_entities[i];
+	cl.num_statics++;
+	CL_ParseBaseline (ent);
+
+// copy it to the current state
+	ent->model = cl.model_precache[ent->baseline.modelindex];
+	ent->frame = ent->baseline.frame;
+	ent->colormap = vid.colormap;
+	ent->skinnum = ent->baseline.skin;
+	ent->effects = ent->baseline.effects;
+
+	VectorCopy (ent->baseline.origin, ent->origin);
+	VectorCopy (ent->baseline.angles, ent->angles);	
+	R_AddEfrags (ent);
+}
+
+/*
+===================
+CL_ParseStaticSound
+===================
+*/
+void CL_ParseStaticSound (void)
+{
+	vec3_t		org;
+	int			sound_num, vol, atten;
+	int			i;
+	
+	for (i=0 ; i<3 ; i++)
+		org[i] = MSG_ReadCoord ();
+	sound_num = MSG_ReadByte ();
+	vol = MSG_ReadByte ();
+	atten = MSG_ReadByte ();
+	
+	S_StaticSound (cl.sound_precache[sound_num], org, vol, atten);
+}
+
+
+#define SHOWNET(x) if(cl_shownet.value==2)Con_Printf ("%3i:%s\n", msg_readcount-1, x);
+
+/*
+=====================
+CL_ParseServerMessage
+=====================
+*/
+void CL_ParseServerMessage (void)
+{
+	int			cmd;
+	int			i;
+	
+//
+// if recording demos, copy the message out
+//
+	if (cl_shownet.value == 1)
+		Con_Printf ("%i ",net_message.cursize);
+	else if (cl_shownet.value == 2)
+		Con_Printf ("------------------\n");
+	
+	cl.onground = false;	// unless the server says otherwise	
+//
+// parse the message
+//
+	MSG_BeginReading ();
+	
+	while (1)
+	{
+		if (msg_badread)
+			Host_Error ("CL_ParseServerMessage: Bad server message");
+
+		cmd = MSG_ReadByte ();
+
+		if (cmd == -1)
+		{
+			SHOWNET("END OF MESSAGE");
+			return;		// end of message
+		}
+
+	// if the high bit of the command byte is set, it is a fast update
+		if (cmd & 128)
+		{
+			SHOWNET("fast update");
+			CL_ParseUpdate (cmd&127);
+			continue;
+		}
+
+		SHOWNET(svc_strings[cmd]);
+	
+	// other commands
+		switch (cmd)
+		{
+		default:
+			Host_Error ("CL_ParseServerMessage: Illegible server message\n");
+			break;
+			
+		case svc_nop:
+//			Con_Printf ("svc_nop\n");
+			break;
+			
+		case svc_time:
+			cl.mtime[1] = cl.mtime[0];
+			cl.mtime[0] = MSG_ReadFloat ();			
+			break;
+			
+		case svc_clientdata:
+			i = MSG_ReadShort ();
+			CL_ParseClientdata (i);
+			break;
+		
+		case svc_version:
+			i = MSG_ReadLong ();
+			if (i != PROTOCOL_VERSION)
+				Host_Error ("CL_ParseServerMessage: Server is protocol %i instead of %i\n", i, PROTOCOL_VERSION);
+			break;
+			
+		case svc_disconnect:
+			Host_EndGame ("Server disconnected\n");
+
+		case svc_print:
+			Con_Printf ("%s", MSG_ReadString ());
+			break;
+			
+		case svc_centerprint:
+			SCR_CenterPrint (MSG_ReadString ());
+			break;
+			
+		case svc_stufftext:
+			Cbuf_AddText (MSG_ReadString ());
+			break;
+			
+		case svc_damage:
+			V_ParseDamage ();
+			break;
+			
+		case svc_serverinfo:
+			CL_ParseServerInfo ();
+			vid.recalc_refdef = true;	// leave intermission full screen
+			break;
+			
+		case svc_setangle:
+			for (i=0 ; i<3 ; i++)
+				cl.viewangles[i] = MSG_ReadAngle ();
+			break;
+			
+		case svc_setview:
+			cl.viewentity = MSG_ReadShort ();
+			break;
+					
+		case svc_lightstyle:
+			i = MSG_ReadByte ();
+			if (i >= MAX_LIGHTSTYLES)
+				Sys_Error ("svc_lightstyle > MAX_LIGHTSTYLES");
+			Q_strcpy (cl_lightstyle[i].map,  MSG_ReadString());
+			cl_lightstyle[i].length = Q_strlen(cl_lightstyle[i].map);
+			break;
+			
+		case svc_sound:
+			CL_ParseStartSoundPacket();
+			break;
+			
+		case svc_stopsound:
+			i = MSG_ReadShort();
+			S_StopSound(i>>3, i&7);
+			break;
+		
+		case svc_updatename:
+			Sbar_Changed ();
+			i = MSG_ReadByte ();
+			if (i >= cl.maxclients)
+				Host_Error ("CL_ParseServerMessage: svc_updatename > MAX_SCOREBOARD");
+			strcpy (cl.scores[i].name, MSG_ReadString ());
+			break;
+			
+		case svc_updatefrags:
+			Sbar_Changed ();
+			i = MSG_ReadByte ();
+			if (i >= cl.maxclients)
+				Host_Error ("CL_ParseServerMessage: svc_updatefrags > MAX_SCOREBOARD");
+			cl.scores[i].frags = MSG_ReadShort ();
+			break;			
+
+		case svc_updatecolors:
+			Sbar_Changed ();
+			i = MSG_ReadByte ();
+			if (i >= cl.maxclients)
+				Host_Error ("CL_ParseServerMessage: svc_updatecolors > MAX_SCOREBOARD");
+			cl.scores[i].colors = MSG_ReadByte ();
+			CL_NewTranslation (i);
+			break;
+			
+		case svc_particle:
+			R_ParseParticleEffect ();
+			break;
+
+		case svc_spawnbaseline:
+			i = MSG_ReadShort ();
+			// must use CL_EntityNum() to force cl.num_entities up
+			CL_ParseBaseline (CL_EntityNum(i));
+			break;
+		case svc_spawnstatic:
+			CL_ParseStatic ();
+			break;			
+		case svc_temp_entity:
+			CL_ParseTEnt ();
+			break;
+
+		case svc_setpause:
+			{
+				cl.paused = MSG_ReadByte ();
+
+				if (cl.paused)
+				{
+					CDAudio_Pause ();
+#ifdef _WIN32
+					VID_HandlePause (true);
+#endif
+				}
+				else
+				{
+					CDAudio_Resume ();
+#ifdef _WIN32
+					VID_HandlePause (false);
+#endif
+				}
+			}
+			break;
+			
+		case svc_signonnum:
+			i = MSG_ReadByte ();
+			if (i <= cls.signon)
+				Host_Error ("Received signon %i when at %i", i, cls.signon);
+			cls.signon = i;
+			CL_SignonReply ();
+			break;
+
+		case svc_killedmonster:
+			cl.stats[STAT_MONSTERS]++;
+			break;
+
+		case svc_foundsecret:
+			cl.stats[STAT_SECRETS]++;
+			break;
+
+		case svc_updatestat:
+			i = MSG_ReadByte ();
+			if (i < 0 || i >= MAX_CL_STATS)
+				Sys_Error ("svc_updatestat: %i is invalid", i);
+			cl.stats[i] = MSG_ReadLong ();;
+			break;
+			
+		case svc_spawnstaticsound:
+			CL_ParseStaticSound ();
+			break;
+
+		case svc_cdtrack:
+			cl.cdtrack = MSG_ReadByte ();
+			cl.looptrack = MSG_ReadByte ();
+			if ( (cls.demoplayback || cls.demorecording) && (cls.forcetrack != -1) )
+				CDAudio_Play ((byte)cls.forcetrack, true);
+			else
+				CDAudio_Play ((byte)cl.cdtrack, true);
+			break;
+
+		case svc_intermission:
+			cl.intermission = 1;
+			cl.completed_time = cl.time;
+			vid.recalc_refdef = true;	// go to full screen
+			break;
+
+		case svc_finale:
+			cl.intermission = 2;
+			cl.completed_time = cl.time;
+			vid.recalc_refdef = true;	// go to full screen
+			SCR_CenterPrint (MSG_ReadString ());			
+			break;
+
+		case svc_cutscene:
+			cl.intermission = 3;
+			cl.completed_time = cl.time;
+			vid.recalc_refdef = true;	// go to full screen
+			SCR_CenterPrint (MSG_ReadString ());			
+			break;
+
+		case svc_sellscreen:
+			Cmd_ExecuteString ("help", src_command);
+			break;
+		}
+	}
+}
+
--- /dev/null
+++ b/WinQuake/cl_tent.c
@@ -1,0 +1,394 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// cl_tent.c -- client side temporary entities
+
+#include "quakedef.h"
+
+int			num_temp_entities;
+entity_t	cl_temp_entities[MAX_TEMP_ENTITIES];
+beam_t		cl_beams[MAX_BEAMS];
+
+sfx_t			*cl_sfx_wizhit;
+sfx_t			*cl_sfx_knighthit;
+sfx_t			*cl_sfx_tink1;
+sfx_t			*cl_sfx_ric1;
+sfx_t			*cl_sfx_ric2;
+sfx_t			*cl_sfx_ric3;
+sfx_t			*cl_sfx_r_exp3;
+#ifdef QUAKE2
+sfx_t			*cl_sfx_imp;
+sfx_t			*cl_sfx_rail;
+#endif
+
+/*
+=================
+CL_ParseTEnt
+=================
+*/
+void CL_InitTEnts (void)
+{
+	cl_sfx_wizhit = S_PrecacheSound ("wizard/hit.wav");
+	cl_sfx_knighthit = S_PrecacheSound ("hknight/hit.wav");
+	cl_sfx_tink1 = S_PrecacheSound ("weapons/tink1.wav");
+	cl_sfx_ric1 = S_PrecacheSound ("weapons/ric1.wav");
+	cl_sfx_ric2 = S_PrecacheSound ("weapons/ric2.wav");
+	cl_sfx_ric3 = S_PrecacheSound ("weapons/ric3.wav");
+	cl_sfx_r_exp3 = S_PrecacheSound ("weapons/r_exp3.wav");
+#ifdef QUAKE2
+	cl_sfx_imp = S_PrecacheSound ("shambler/sattck1.wav");
+	cl_sfx_rail = S_PrecacheSound ("weapons/lstart.wav");
+#endif
+}
+
+/*
+=================
+CL_ParseBeam
+=================
+*/
+void CL_ParseBeam (model_t *m)
+{
+	int		ent;
+	vec3_t	start, end;
+	beam_t	*b;
+	int		i;
+	
+	ent = MSG_ReadShort ();
+	
+	start[0] = MSG_ReadCoord ();
+	start[1] = MSG_ReadCoord ();
+	start[2] = MSG_ReadCoord ();
+	
+	end[0] = MSG_ReadCoord ();
+	end[1] = MSG_ReadCoord ();
+	end[2] = MSG_ReadCoord ();
+
+// override any beam with the same entity
+	for (i=0, b=cl_beams ; i< MAX_BEAMS ; i++, b++)
+		if (b->entity == ent)
+		{
+			b->entity = ent;
+			b->model = m;
+			b->endtime = cl.time + 0.2;
+			VectorCopy (start, b->start);
+			VectorCopy (end, b->end);
+			return;
+		}
+
+// find a free beam
+	for (i=0, b=cl_beams ; i< MAX_BEAMS ; i++, b++)
+	{
+		if (!b->model || b->endtime < cl.time)
+		{
+			b->entity = ent;
+			b->model = m;
+			b->endtime = cl.time + 0.2;
+			VectorCopy (start, b->start);
+			VectorCopy (end, b->end);
+			return;
+		}
+	}
+	Con_Printf ("beam list overflow!\n");	
+}
+
+/*
+=================
+CL_ParseTEnt
+=================
+*/
+void CL_ParseTEnt (void)
+{
+	int		type;
+	vec3_t	pos;
+#ifdef QUAKE2
+	vec3_t	endpos;
+#endif
+	dlight_t	*dl;
+	int		rnd;
+	int		colorStart, colorLength;
+
+	type = MSG_ReadByte ();
+	switch (type)
+	{
+	case TE_WIZSPIKE:			// spike hitting wall
+		pos[0] = MSG_ReadCoord ();
+		pos[1] = MSG_ReadCoord ();
+		pos[2] = MSG_ReadCoord ();
+		R_RunParticleEffect (pos, vec3_origin, 20, 30);
+		S_StartSound (-1, 0, cl_sfx_wizhit, pos, 1, 1);
+		break;
+		
+	case TE_KNIGHTSPIKE:			// spike hitting wall
+		pos[0] = MSG_ReadCoord ();
+		pos[1] = MSG_ReadCoord ();
+		pos[2] = MSG_ReadCoord ();
+		R_RunParticleEffect (pos, vec3_origin, 226, 20);
+		S_StartSound (-1, 0, cl_sfx_knighthit, pos, 1, 1);
+		break;
+		
+	case TE_SPIKE:			// spike hitting wall
+		pos[0] = MSG_ReadCoord ();
+		pos[1] = MSG_ReadCoord ();
+		pos[2] = MSG_ReadCoord ();
+#ifdef GLTEST
+		Test_Spawn (pos);
+#else
+		R_RunParticleEffect (pos, vec3_origin, 0, 10);
+#endif
+		if ( rand() % 5 )
+			S_StartSound (-1, 0, cl_sfx_tink1, pos, 1, 1);
+		else
+		{
+			rnd = rand() & 3;
+			if (rnd == 1)
+				S_StartSound (-1, 0, cl_sfx_ric1, pos, 1, 1);
+			else if (rnd == 2)
+				S_StartSound (-1, 0, cl_sfx_ric2, pos, 1, 1);
+			else
+				S_StartSound (-1, 0, cl_sfx_ric3, pos, 1, 1);
+		}
+		break;
+	case TE_SUPERSPIKE:			// super spike hitting wall
+		pos[0] = MSG_ReadCoord ();
+		pos[1] = MSG_ReadCoord ();
+		pos[2] = MSG_ReadCoord ();
+		R_RunParticleEffect (pos, vec3_origin, 0, 20);
+
+		if ( rand() % 5 )
+			S_StartSound (-1, 0, cl_sfx_tink1, pos, 1, 1);
+		else
+		{
+			rnd = rand() & 3;
+			if (rnd == 1)
+				S_StartSound (-1, 0, cl_sfx_ric1, pos, 1, 1);
+			else if (rnd == 2)
+				S_StartSound (-1, 0, cl_sfx_ric2, pos, 1, 1);
+			else
+				S_StartSound (-1, 0, cl_sfx_ric3, pos, 1, 1);
+		}
+		break;
+		
+	case TE_GUNSHOT:			// bullet hitting wall
+		pos[0] = MSG_ReadCoord ();
+		pos[1] = MSG_ReadCoord ();
+		pos[2] = MSG_ReadCoord ();
+		R_RunParticleEffect (pos, vec3_origin, 0, 20);
+		break;
+		
+	case TE_EXPLOSION:			// rocket explosion
+		pos[0] = MSG_ReadCoord ();
+		pos[1] = MSG_ReadCoord ();
+		pos[2] = MSG_ReadCoord ();
+		R_ParticleExplosion (pos);
+		dl = CL_AllocDlight (0);
+		VectorCopy (pos, dl->origin);
+		dl->radius = 350;
+		dl->die = cl.time + 0.5;
+		dl->decay = 300;
+		S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
+		break;
+		
+	case TE_TAREXPLOSION:			// tarbaby explosion
+		pos[0] = MSG_ReadCoord ();
+		pos[1] = MSG_ReadCoord ();
+		pos[2] = MSG_ReadCoord ();
+		R_BlobExplosion (pos);
+
+		S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
+		break;
+
+	case TE_LIGHTNING1:				// lightning bolts
+		CL_ParseBeam (Mod_ForName("progs/bolt.mdl", true));
+		break;
+	
+	case TE_LIGHTNING2:				// lightning bolts
+		CL_ParseBeam (Mod_ForName("progs/bolt2.mdl", true));
+		break;
+	
+	case TE_LIGHTNING3:				// lightning bolts
+		CL_ParseBeam (Mod_ForName("progs/bolt3.mdl", true));
+		break;
+	
+// PGM 01/21/97 
+	case TE_BEAM:				// grappling hook beam
+		CL_ParseBeam (Mod_ForName("progs/beam.mdl", true));
+		break;
+// PGM 01/21/97
+
+	case TE_LAVASPLASH:	
+		pos[0] = MSG_ReadCoord ();
+		pos[1] = MSG_ReadCoord ();
+		pos[2] = MSG_ReadCoord ();
+		R_LavaSplash (pos);
+		break;
+	
+	case TE_TELEPORT:
+		pos[0] = MSG_ReadCoord ();
+		pos[1] = MSG_ReadCoord ();
+		pos[2] = MSG_ReadCoord ();
+		R_TeleportSplash (pos);
+		break;
+		
+	case TE_EXPLOSION2:				// color mapped explosion
+		pos[0] = MSG_ReadCoord ();
+		pos[1] = MSG_ReadCoord ();
+		pos[2] = MSG_ReadCoord ();
+		colorStart = MSG_ReadByte ();
+		colorLength = MSG_ReadByte ();
+		R_ParticleExplosion2 (pos, colorStart, colorLength);
+		dl = CL_AllocDlight (0);
+		VectorCopy (pos, dl->origin);
+		dl->radius = 350;
+		dl->die = cl.time + 0.5;
+		dl->decay = 300;
+		S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
+		break;
+		
+#ifdef QUAKE2
+	case TE_IMPLOSION:
+		pos[0] = MSG_ReadCoord ();
+		pos[1] = MSG_ReadCoord ();
+		pos[2] = MSG_ReadCoord ();
+		S_StartSound (-1, 0, cl_sfx_imp, pos, 1, 1);
+		break;
+
+	case TE_RAILTRAIL:
+		pos[0] = MSG_ReadCoord ();
+		pos[1] = MSG_ReadCoord ();
+		pos[2] = MSG_ReadCoord ();
+		endpos[0] = MSG_ReadCoord ();
+		endpos[1] = MSG_ReadCoord ();
+		endpos[2] = MSG_ReadCoord ();
+		S_StartSound (-1, 0, cl_sfx_rail, pos, 1, 1);
+		S_StartSound (-1, 1, cl_sfx_r_exp3, endpos, 1, 1);
+		R_RocketTrail (pos, endpos, 0+128);
+		R_ParticleExplosion (endpos);
+		dl = CL_AllocDlight (-1);
+		VectorCopy (endpos, dl->origin);
+		dl->radius = 350;
+		dl->die = cl.time + 0.5;
+		dl->decay = 300;
+		break;
+#endif
+
+	default:
+		Sys_Error ("CL_ParseTEnt: bad type");
+	}
+}
+
+
+/*
+=================
+CL_NewTempEntity
+=================
+*/
+entity_t *CL_NewTempEntity (void)
+{
+	entity_t	*ent;
+
+	if (cl_numvisedicts == MAX_VISEDICTS)
+		return NULL;
+	if (num_temp_entities == MAX_TEMP_ENTITIES)
+		return NULL;
+	ent = &cl_temp_entities[num_temp_entities];
+	memset (ent, 0, sizeof(*ent));
+	num_temp_entities++;
+	cl_visedicts[cl_numvisedicts] = ent;
+	cl_numvisedicts++;
+
+	ent->colormap = vid.colormap;
+	return ent;
+}
+
+
+/*
+=================
+CL_UpdateTEnts
+=================
+*/
+void CL_UpdateTEnts (void)
+{
+	int			i;
+	beam_t		*b;
+	vec3_t		dist, org;
+	float		d;
+	entity_t	*ent;
+	float		yaw, pitch;
+	float		forward;
+
+	num_temp_entities = 0;
+
+// update lightning
+	for (i=0, b=cl_beams ; i< MAX_BEAMS ; i++, b++)
+	{
+		if (!b->model || b->endtime < cl.time)
+			continue;
+
+	// if coming from the player, update the start position
+		if (b->entity == cl.viewentity)
+		{
+			VectorCopy (cl_entities[cl.viewentity].origin, b->start);
+		}
+
+	// calculate pitch and yaw
+		VectorSubtract (b->end, b->start, dist);
+
+		if (dist[1] == 0 && dist[0] == 0)
+		{
+			yaw = 0;
+			if (dist[2] > 0)
+				pitch = 90;
+			else
+				pitch = 270;
+		}
+		else
+		{
+			yaw = (int) (atan2(dist[1], dist[0]) * 180 / M_PI);
+			if (yaw < 0)
+				yaw += 360;
+	
+			forward = sqrt (dist[0]*dist[0] + dist[1]*dist[1]);
+			pitch = (int) (atan2(dist[2], forward) * 180 / M_PI);
+			if (pitch < 0)
+				pitch += 360;
+		}
+
+	// add new entities for the lightning
+		VectorCopy (b->start, org);
+		d = VectorNormalize(dist);
+		while (d > 0)
+		{
+			ent = CL_NewTempEntity ();
+			if (!ent)
+				return;
+			VectorCopy (org, ent->origin);
+			ent->model = b->model;
+			ent->angles[0] = pitch;
+			ent->angles[1] = yaw;
+			ent->angles[2] = rand()%360;
+
+			for (i=0 ; i<3 ; i++)
+				org[i] += dist[i]*30;
+			d -= 30;
+		}
+	}
+	
+}
+
+
--- /dev/null
+++ b/WinQuake/clean.bat
@@ -1,0 +1,18 @@
+rmdir /s /q debug
+rmdir /s /q release
+rmdir /s /q debug_gl
+rmdir /s /q release_gl
+
+rmdir /s /q gas2masm\debug
+rmdir /s /q gas2masm\release
+
+del gas2masm\gas2masm.opt
+del gas2masm\gas2masm.plg
+del gas2masm\gas2masm.ncb
+del gas2masm\gas2masm.stt
+
+del WinQuake.opt
+del WinQuake.plg
+del WinQuake.ncb
+del WinQuake.stt
+
--- /dev/null
+++ b/WinQuake/client.h
@@ -1,0 +1,375 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// client.h
+
+typedef struct
+{
+	vec3_t	viewangles;
+
+// intended velocities
+	float	forwardmove;
+	float	sidemove;
+	float	upmove;
+#ifdef QUAKE2
+	byte	lightlevel;
+#endif
+} usercmd_t;
+
+typedef struct
+{
+	int		length;
+	char	map[MAX_STYLESTRING];
+} lightstyle_t;
+
+typedef struct
+{
+	char	name[MAX_SCOREBOARDNAME];
+	float	entertime;
+	int		frags;
+	int		colors;			// two 4 bit fields
+	byte	translations[VID_GRADES*256];
+} scoreboard_t;
+
+typedef struct
+{
+	int		destcolor[3];
+	int		percent;		// 0-256
+} cshift_t;
+
+#define	CSHIFT_CONTENTS	0
+#define	CSHIFT_DAMAGE	1
+#define	CSHIFT_BONUS	2
+#define	CSHIFT_POWERUP	3
+#define	NUM_CSHIFTS		4
+
+#define	NAME_LENGTH	64
+
+
+//
+// client_state_t should hold all pieces of the client state
+//
+
+#define	SIGNONS		4			// signon messages to receive before connected
+
+#define	MAX_DLIGHTS		32
+typedef struct
+{
+	vec3_t	origin;
+	float	radius;
+	float	die;				// stop lighting after this time
+	float	decay;				// drop this each second
+	float	minlight;			// don't add when contributing less
+	int		key;
+#ifdef QUAKE2
+	qboolean	dark;			// subtracts light instead of adding
+#endif
+} dlight_t;
+
+
+#define	MAX_BEAMS	24
+typedef struct
+{
+	int		entity;
+	struct model_s	*model;
+	float	endtime;
+	vec3_t	start, end;
+} beam_t;
+
+#define	MAX_EFRAGS		640
+
+#define	MAX_MAPSTRING	2048
+#define	MAX_DEMOS		8
+#define	MAX_DEMONAME	16
+
+typedef enum {
+ca_dedicated, 		// a dedicated server with no ability to start a client
+ca_disconnected, 	// full screen console with no connection
+ca_connected		// valid netcon, talking to a server
+} cactive_t;
+
+//
+// the client_static_t structure is persistant through an arbitrary number
+// of server connections
+//
+typedef struct
+{
+	cactive_t	state;
+
+// personalization data sent to server	
+	char		mapstring[MAX_QPATH];
+	char		spawnparms[MAX_MAPSTRING];	// to restart a level
+
+// demo loop control
+	int			demonum;		// -1 = don't play demos
+	char		demos[MAX_DEMOS][MAX_DEMONAME];		// when not playing
+
+// demo recording info must be here, because record is started before
+// entering a map (and clearing client_state_t)
+	qboolean	demorecording;
+	qboolean	demoplayback;
+	qboolean	timedemo;
+	int			forcetrack;			// -1 = use normal cd track
+	FILE		*demofile;
+	int			td_lastframe;		// to meter out one message a frame
+	int			td_startframe;		// host_framecount at start
+	float		td_starttime;		// realtime at second frame of timedemo
+
+
+// connection information
+	int			signon;			// 0 to SIGNONS
+	struct qsocket_s	*netcon;
+	sizebuf_t	message;		// writing buffer to send to server
+	
+} client_static_t;
+
+extern client_static_t	cls;
+
+//
+// the client_state_t structure is wiped completely at every
+// server signon
+//
+typedef struct
+{
+	int			movemessages;	// since connecting to this server
+								// throw out the first couple, so the player
+								// doesn't accidentally do something the 
+								// first frame
+	usercmd_t	cmd;			// last command sent to the server
+
+// information for local display
+	int			stats[MAX_CL_STATS];	// health, etc
+	int			items;			// inventory bit flags
+	float	item_gettime[32];	// cl.time of aquiring item, for blinking
+	float		faceanimtime;	// use anim frame if cl.time < this
+
+	cshift_t	cshifts[NUM_CSHIFTS];	// color shifts for damage, powerups
+	cshift_t	prev_cshifts[NUM_CSHIFTS];	// and content types
+
+// the client maintains its own idea of view angles, which are
+// sent to the server each frame.  The server sets punchangle when
+// the view is temporarliy offset, and an angle reset commands at the start
+// of each level and after teleporting.
+	vec3_t		mviewangles[2];	// during demo playback viewangles is lerped
+								// between these
+	vec3_t		viewangles;
+	
+	vec3_t		mvelocity[2];	// update by server, used for lean+bob
+								// (0 is newest)
+	vec3_t		velocity;		// lerped between mvelocity[0] and [1]
+
+	vec3_t		punchangle;		// temporary offset
+	
+// pitch drifting vars
+	float		idealpitch;
+	float		pitchvel;
+	qboolean	nodrift;
+	float		driftmove;
+	double		laststop;
+
+	float		viewheight;
+	float		crouch;			// local amount for smoothing stepups
+
+	qboolean	paused;			// send over by server
+	qboolean	onground;
+	qboolean	inwater;
+	
+	int			intermission;	// don't change view angle, full screen, etc
+	int			completed_time;	// latched at intermission start
+	
+	double		mtime[2];		// the timestamp of last two messages	
+	double		time;			// clients view of time, should be between
+								// servertime and oldservertime to generate
+								// a lerp point for other data
+	double		oldtime;		// previous cl.time, time-oldtime is used
+								// to decay light values and smooth step ups
+	
+
+	float		last_received_message;	// (realtime) for net trouble icon
+
+//
+// information that is static for the entire time connected to a server
+//
+	struct model_s		*model_precache[MAX_MODELS];
+	struct sfx_s		*sound_precache[MAX_SOUNDS];
+
+	char		levelname[40];	// for display on solo scoreboard
+	int			viewentity;		// cl_entitites[cl.viewentity] = player
+	int			maxclients;
+	int			gametype;
+
+// refresh related state
+	struct model_s	*worldmodel;	// cl_entitites[0].model
+	struct efrag_s	*free_efrags;
+	int			num_entities;	// held in cl_entities array
+	int			num_statics;	// held in cl_staticentities array
+	entity_t	viewent;			// the gun model
+
+	int			cdtrack, looptrack;	// cd audio
+
+// frag scoreboard
+	scoreboard_t	*scores;		// [cl.maxclients]
+
+#ifdef QUAKE2
+// light level at player's position including dlights
+// this is sent back to the server each frame
+// architectually ugly but it works
+	int			light_level;
+#endif
+} client_state_t;
+
+
+//
+// cvars
+//
+extern	cvar_t	cl_name;
+extern	cvar_t	cl_color;
+
+extern	cvar_t	cl_upspeed;
+extern	cvar_t	cl_forwardspeed;
+extern	cvar_t	cl_backspeed;
+extern	cvar_t	cl_sidespeed;
+
+extern	cvar_t	cl_movespeedkey;
+
+extern	cvar_t	cl_yawspeed;
+extern	cvar_t	cl_pitchspeed;
+
+extern	cvar_t	cl_anglespeedkey;
+
+extern	cvar_t	cl_autofire;
+
+extern	cvar_t	cl_shownet;
+extern	cvar_t	cl_nolerp;
+
+extern	cvar_t	cl_pitchdriftspeed;
+extern	cvar_t	lookspring;
+extern	cvar_t	lookstrafe;
+extern	cvar_t	sensitivity;
+
+extern	cvar_t	m_pitch;
+extern	cvar_t	m_yaw;
+extern	cvar_t	m_forward;
+extern	cvar_t	m_side;
+
+
+#define	MAX_TEMP_ENTITIES	64			// lightning bolts, etc
+#define	MAX_STATIC_ENTITIES	128			// torches, etc
+
+extern	client_state_t	cl;
+
+// FIXME, allocate dynamically
+extern	efrag_t			cl_efrags[MAX_EFRAGS];
+extern	entity_t		cl_entities[MAX_EDICTS];
+extern	entity_t		cl_static_entities[MAX_STATIC_ENTITIES];
+extern	lightstyle_t	cl_lightstyle[MAX_LIGHTSTYLES];
+extern	dlight_t		cl_dlights[MAX_DLIGHTS];
+extern	entity_t		cl_temp_entities[MAX_TEMP_ENTITIES];
+extern	beam_t			cl_beams[MAX_BEAMS];
+
+//=============================================================================
+
+//
+// cl_main
+//
+dlight_t *CL_AllocDlight (int key);
+void	CL_DecayLights (void);
+
+void CL_Init (void);
+
+void CL_EstablishConnection (char *host);
+void CL_Signon1 (void);
+void CL_Signon2 (void);
+void CL_Signon3 (void);
+void CL_Signon4 (void);
+
+void CL_Disconnect (void);
+void CL_Disconnect_f (void);
+void CL_NextDemo (void);
+
+#define			MAX_VISEDICTS	256
+extern	int				cl_numvisedicts;
+extern	entity_t		*cl_visedicts[MAX_VISEDICTS];
+
+//
+// cl_input
+//
+typedef struct
+{
+	int		down[2];		// key nums holding it down
+	int		state;			// low bit is down state
+} kbutton_t;
+
+extern	kbutton_t	in_mlook, in_klook;
+extern 	kbutton_t 	in_strafe;
+extern 	kbutton_t 	in_speed;
+
+void CL_InitInput (void);
+void CL_SendCmd (void);
+void CL_SendMove (usercmd_t *cmd);
+
+void CL_ParseTEnt (void);
+void CL_UpdateTEnts (void);
+
+void CL_ClearState (void);
+
+
+int  CL_ReadFromServer (void);
+void CL_WriteToServer (usercmd_t *cmd);
+void CL_BaseMove (usercmd_t *cmd);
+
+
+float CL_KeyState (kbutton_t *key);
+char *Key_KeynumToString (int keynum);
+
+//
+// cl_demo.c
+//
+void CL_StopPlayback (void);
+int CL_GetMessage (void);
+
+void CL_Stop_f (void);
+void CL_Record_f (void);
+void CL_PlayDemo_f (void);
+void CL_TimeDemo_f (void);
+
+//
+// cl_parse.c
+//
+void CL_ParseServerMessage (void);
+void CL_NewTranslation (int slot);
+
+//
+// view
+//
+void V_StartPitchDrift (void);
+void V_StopPitchDrift (void);
+
+void V_RenderView (void);
+void V_UpdatePalette (void);
+void V_Register (void);
+void V_ParseDamage (void);
+void V_SetContentsColor (int contents);
+
+
+//
+// cl_tent
+//
+void CL_InitTEnts (void);
+void CL_SignonReply (void);
--- /dev/null
+++ b/WinQuake/cmd.c
@@ -1,0 +1,705 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// cmd.c -- Quake script command processing module
+
+#include "quakedef.h"
+
+void Cmd_ForwardToServer (void);
+
+#define	MAX_ALIAS_NAME	32
+
+typedef struct cmdalias_s
+{
+	struct cmdalias_s	*next;
+	char	name[MAX_ALIAS_NAME];
+	char	*value;
+} cmdalias_t;
+
+cmdalias_t	*cmd_alias;
+
+int trashtest;
+int *trashspot;
+
+qboolean	cmd_wait;
+
+//=============================================================================
+
+/*
+============
+Cmd_Wait_f
+
+Causes execution of the remainder of the command buffer to be delayed until
+next frame.  This allows commands like:
+bind g "impulse 5 ; +attack ; wait ; -attack ; impulse 2"
+============
+*/
+void Cmd_Wait_f (void)
+{
+	cmd_wait = true;
+}
+
+/*
+=============================================================================
+
+						COMMAND BUFFER
+
+=============================================================================
+*/
+
+sizebuf_t	cmd_text;
+
+/*
+============
+Cbuf_Init
+============
+*/
+void Cbuf_Init (void)
+{
+	SZ_Alloc (&cmd_text, 8192);		// space for commands and script files
+}
+
+
+/*
+============
+Cbuf_AddText
+
+Adds command text at the end of the buffer
+============
+*/
+void Cbuf_AddText (char *text)
+{
+	int		l;
+	
+	l = Q_strlen (text);
+
+	if (cmd_text.cursize + l >= cmd_text.maxsize)
+	{
+		Con_Printf ("Cbuf_AddText: overflow\n");
+		return;
+	}
+
+	SZ_Write (&cmd_text, text, Q_strlen (text));
+}
+
+
+/*
+============
+Cbuf_InsertText
+
+Adds command text immediately after the current command
+Adds a \n to the text
+FIXME: actually change the command buffer to do less copying
+============
+*/
+void Cbuf_InsertText (char *text)
+{
+	char	*temp;
+	int		templen;
+
+// copy off any commands still remaining in the exec buffer
+	templen = cmd_text.cursize;
+	if (templen)
+	{
+		temp = Z_Malloc (templen);
+		Q_memcpy (temp, cmd_text.data, templen);
+		SZ_Clear (&cmd_text);
+	}
+	else
+		temp = NULL;	// shut up compiler
+		
+// add the entire text of the file
+	Cbuf_AddText (text);
+	
+// add the copied off data
+	if (templen)
+	{
+		SZ_Write (&cmd_text, temp, templen);
+		Z_Free (temp);
+	}
+}
+
+/*
+============
+Cbuf_Execute
+============
+*/
+void Cbuf_Execute (void)
+{
+	int		i;
+	char	*text;
+	char	line[1024];
+	int		quotes;
+	
+	while (cmd_text.cursize)
+	{
+// find a \n or ; line break
+		text = (char *)cmd_text.data;
+
+		quotes = 0;
+		for (i=0 ; i< cmd_text.cursize ; i++)
+		{
+			if (text[i] == '"')
+				quotes++;
+			if ( !(quotes&1) &&  text[i] == ';')
+				break;	// don't break if inside a quoted string
+			if (text[i] == '\n')
+				break;
+		}
+			
+				
+		memcpy (line, text, i);
+		line[i] = 0;
+		
+// delete the text from the command buffer and move remaining commands down
+// this is necessary because commands (exec, alias) can insert data at the
+// beginning of the text buffer
+
+		if (i == cmd_text.cursize)
+			cmd_text.cursize = 0;
+		else
+		{
+			i++;
+			cmd_text.cursize -= i;
+			Q_memcpy (text, text+i, cmd_text.cursize);
+		}
+
+// execute the command line
+		Cmd_ExecuteString (line, src_command);
+		
+		if (cmd_wait)
+		{	// skip out while text still remains in buffer, leaving it
+			// for next frame
+			cmd_wait = false;
+			break;
+		}
+	}
+}
+
+/*
+==============================================================================
+
+						SCRIPT COMMANDS
+
+==============================================================================
+*/
+
+/*
+===============
+Cmd_StuffCmds_f
+
+Adds command line parameters as script statements
+Commands lead with a +, and continue until a - or another +
+quake +prog jctest.qp +cmd amlev1
+quake -nosound +cmd amlev1
+===============
+*/
+void Cmd_StuffCmds_f (void)
+{
+	int		i, j;
+	int		s;
+	char	*text, *build, c;
+		
+	if (Cmd_Argc () != 1)
+	{
+		Con_Printf ("stuffcmds : execute command line parameters\n");
+		return;
+	}
+
+// build the combined string to parse from
+	s = 0;
+	for (i=1 ; i<com_argc ; i++)
+	{
+		if (!com_argv[i])
+			continue;		// NEXTSTEP nulls out -NXHost
+		s += Q_strlen (com_argv[i]) + 1;
+	}
+	if (!s)
+		return;
+		
+	text = Z_Malloc (s+1);
+	text[0] = 0;
+	for (i=1 ; i<com_argc ; i++)
+	{
+		if (!com_argv[i])
+			continue;		// NEXTSTEP nulls out -NXHost
+		Q_strcat (text,com_argv[i]);
+		if (i != com_argc-1)
+			Q_strcat (text, " ");
+	}
+	
+// pull out the commands
+	build = Z_Malloc (s+1);
+	build[0] = 0;
+	
+	for (i=0 ; i<s-1 ; i++)
+	{
+		if (text[i] == '+')
+		{
+			i++;
+
+			for (j=i ; (text[j] != '+') && (text[j] != '-') && (text[j] != 0) ; j++)
+				;
+
+			c = text[j];
+			text[j] = 0;
+			
+			Q_strcat (build, text+i);
+			Q_strcat (build, "\n");
+			text[j] = c;
+			i = j-1;
+		}
+	}
+	
+	if (build[0])
+		Cbuf_InsertText (build);
+	
+	Z_Free (text);
+	Z_Free (build);
+}
+
+
+/*
+===============
+Cmd_Exec_f
+===============
+*/
+void Cmd_Exec_f (void)
+{
+	char	*f;
+	int		mark;
+
+	if (Cmd_Argc () != 2)
+	{
+		Con_Printf ("exec <filename> : execute a script file\n");
+		return;
+	}
+
+	mark = Hunk_LowMark ();
+	f = (char *)COM_LoadHunkFile (Cmd_Argv(1));
+	if (!f)
+	{
+		Con_Printf ("couldn't exec %s\n",Cmd_Argv(1));
+		return;
+	}
+	Con_Printf ("execing %s\n",Cmd_Argv(1));
+	
+	Cbuf_InsertText (f);
+	Hunk_FreeToLowMark (mark);
+}
+
+
+/*
+===============
+Cmd_Echo_f
+
+Just prints the rest of the line to the console
+===============
+*/
+void Cmd_Echo_f (void)
+{
+	int		i;
+	
+	for (i=1 ; i<Cmd_Argc() ; i++)
+		Con_Printf ("%s ",Cmd_Argv(i));
+	Con_Printf ("\n");
+}
+
+/*
+===============
+Cmd_Alias_f
+
+Creates a new command that executes a command string (possibly ; seperated)
+===============
+*/
+
+char *CopyString (char *in)
+{
+	char	*out;
+	
+	out = Z_Malloc (strlen(in)+1);
+	strcpy (out, in);
+	return out;
+}
+
+void Cmd_Alias_f (void)
+{
+	cmdalias_t	*a;
+	char		cmd[1024];
+	int			i, c;
+	char		*s;
+
+	if (Cmd_Argc() == 1)
+	{
+		Con_Printf ("Current alias commands:\n");
+		for (a = cmd_alias ; a ; a=a->next)
+			Con_Printf ("%s : %s\n", a->name, a->value);
+		return;
+	}
+
+	s = Cmd_Argv(1);
+	if (strlen(s) >= MAX_ALIAS_NAME)
+	{
+		Con_Printf ("Alias name is too long\n");
+		return;
+	}
+
+	// if the alias allready exists, reuse it
+	for (a = cmd_alias ; a ; a=a->next)
+	{
+		if (!strcmp(s, a->name))
+		{
+			Z_Free (a->value);
+			break;
+		}
+	}
+
+	if (!a)
+	{
+		a = Z_Malloc (sizeof(cmdalias_t));
+		a->next = cmd_alias;
+		cmd_alias = a;
+	}
+	strcpy (a->name, s);	
+
+// copy the rest of the command line
+	cmd[0] = 0;		// start out with a null string
+	c = Cmd_Argc();
+	for (i=2 ; i< c ; i++)
+	{
+		strcat (cmd, Cmd_Argv(i));
+		if (i != c)
+			strcat (cmd, " ");
+	}
+	strcat (cmd, "\n");
+	
+	a->value = CopyString (cmd);
+}
+
+/*
+=============================================================================
+
+					COMMAND EXECUTION
+
+=============================================================================
+*/
+
+typedef struct cmd_function_s
+{
+	struct cmd_function_s	*next;
+	char					*name;
+	xcommand_t				function;
+} cmd_function_t;
+
+
+#define	MAX_ARGS		80
+
+static	int			cmd_argc;
+static	char		*cmd_argv[MAX_ARGS];
+static	char		*cmd_null_string = "";
+static	char		*cmd_args = NULL;
+
+cmd_source_t	cmd_source;
+
+
+static	cmd_function_t	*cmd_functions;		// possible commands to execute
+
+/*
+============
+Cmd_Init
+============
+*/
+void Cmd_Init (void)
+{
+//
+// register our commands
+//
+	Cmd_AddCommand ("stuffcmds",Cmd_StuffCmds_f);
+	Cmd_AddCommand ("exec",Cmd_Exec_f);
+	Cmd_AddCommand ("echo",Cmd_Echo_f);
+	Cmd_AddCommand ("alias",Cmd_Alias_f);
+	Cmd_AddCommand ("cmd", Cmd_ForwardToServer);
+	Cmd_AddCommand ("wait", Cmd_Wait_f);
+}
+
+/*
+============
+Cmd_Argc
+============
+*/
+int		Cmd_Argc (void)
+{
+	return cmd_argc;
+}
+
+/*
+============
+Cmd_Argv
+============
+*/
+char	*Cmd_Argv (int arg)
+{
+	if ( (unsigned)arg >= cmd_argc )
+		return cmd_null_string;
+	return cmd_argv[arg];	
+}
+
+/*
+============
+Cmd_Args
+============
+*/
+char		*Cmd_Args (void)
+{
+	return cmd_args;
+}
+
+
+/*
+============
+Cmd_TokenizeString
+
+Parses the given string into command line tokens.
+============
+*/
+void Cmd_TokenizeString (char *text)
+{
+	int		i;
+	
+// clear the args from the last string
+	for (i=0 ; i<cmd_argc ; i++)
+		Z_Free (cmd_argv[i]);
+		
+	cmd_argc = 0;
+	cmd_args = NULL;
+	
+	while (1)
+	{
+// skip whitespace up to a /n
+		while (*text && *text <= ' ' && *text != '\n')
+		{
+			text++;
+		}
+		
+		if (*text == '\n')
+		{	// a newline seperates commands in the buffer
+			text++;
+			break;
+		}
+
+		if (!*text)
+			return;
+	
+		if (cmd_argc == 1)
+			 cmd_args = text;
+			
+		text = COM_Parse (text);
+		if (!text)
+			return;
+
+		if (cmd_argc < MAX_ARGS)
+		{
+			cmd_argv[cmd_argc] = Z_Malloc (Q_strlen(com_token)+1);
+			Q_strcpy (cmd_argv[cmd_argc], com_token);
+			cmd_argc++;
+		}
+	}
+	
+}
+
+
+/*
+============
+Cmd_AddCommand
+============
+*/
+void	Cmd_AddCommand (char *cmd_name, xcommand_t function)
+{
+	cmd_function_t	*cmd;
+	
+	if (host_initialized)	// because hunk allocation would get stomped
+		Sys_Error ("Cmd_AddCommand after host_initialized");
+		
+// fail if the command is a variable name
+	if (Cvar_VariableString(cmd_name)[0])
+	{
+		Con_Printf ("Cmd_AddCommand: %s already defined as a var\n", cmd_name);
+		return;
+	}
+	
+// fail if the command already exists
+	for (cmd=cmd_functions ; cmd ; cmd=cmd->next)
+	{
+		if (!Q_strcmp (cmd_name, cmd->name))
+		{
+			Con_Printf ("Cmd_AddCommand: %s already defined\n", cmd_name);
+			return;
+		}
+	}
+
+	cmd = Hunk_Alloc (sizeof(cmd_function_t));
+	cmd->name = cmd_name;
+	cmd->function = function;
+	cmd->next = cmd_functions;
+	cmd_functions = cmd;
+}
+
+/*
+============
+Cmd_Exists
+============
+*/
+qboolean	Cmd_Exists (char *cmd_name)
+{
+	cmd_function_t	*cmd;
+
+	for (cmd=cmd_functions ; cmd ; cmd=cmd->next)
+	{
+		if (!Q_strcmp (cmd_name,cmd->name))
+			return true;
+	}
+
+	return false;
+}
+
+
+
+/*
+============
+Cmd_CompleteCommand
+============
+*/
+char *Cmd_CompleteCommand (char *partial)
+{
+	cmd_function_t	*cmd;
+	int				len;
+	
+	len = Q_strlen(partial);
+	
+	if (!len)
+		return NULL;
+		
+// check functions
+	for (cmd=cmd_functions ; cmd ; cmd=cmd->next)
+		if (!Q_strncmp (partial,cmd->name, len))
+			return cmd->name;
+
+	return NULL;
+}
+
+/*
+============
+Cmd_ExecuteString
+
+A complete command line has been parsed, so try to execute it
+FIXME: lookupnoadd the token to speed search?
+============
+*/
+void	Cmd_ExecuteString (char *text, cmd_source_t src)
+{	
+	cmd_function_t	*cmd;
+	cmdalias_t		*a;
+
+	cmd_source = src;
+	Cmd_TokenizeString (text);
+			
+// execute the command line
+	if (!Cmd_Argc())
+		return;		// no tokens
+
+// check functions
+	for (cmd=cmd_functions ; cmd ; cmd=cmd->next)
+	{
+		if (!Q_strcasecmp (cmd_argv[0],cmd->name))
+		{
+			cmd->function ();
+			return;
+		}
+	}
+
+// check alias
+	for (a=cmd_alias ; a ; a=a->next)
+	{
+		if (!Q_strcasecmp (cmd_argv[0], a->name))
+		{
+			Cbuf_InsertText (a->value);
+			return;
+		}
+	}
+	
+// check cvars
+	if (!Cvar_Command ())
+		Con_Printf ("Unknown command \"%s\"\n", Cmd_Argv(0));
+	
+}
+
+
+/*
+===================
+Cmd_ForwardToServer
+
+Sends the entire command line over to the server
+===================
+*/
+void Cmd_ForwardToServer (void)
+{
+	if (cls.state != ca_connected)
+	{
+		Con_Printf ("Can't \"%s\", not connected\n", Cmd_Argv(0));
+		return;
+	}
+	
+	if (cls.demoplayback)
+		return;		// not really connected
+
+	MSG_WriteByte (&cls.message, clc_stringcmd);
+	if (Q_strcasecmp(Cmd_Argv(0), "cmd") != 0)
+	{
+		SZ_Print (&cls.message, Cmd_Argv(0));
+		SZ_Print (&cls.message, " ");
+	}
+	if (Cmd_Argc() > 1)
+		SZ_Print (&cls.message, Cmd_Args());
+	else
+		SZ_Print (&cls.message, "\n");
+}
+
+
+/*
+================
+Cmd_CheckParm
+
+Returns the position (1 to argc-1) in the command's argument list
+where the given parameter apears, or 0 if not present
+================
+*/
+
+int Cmd_CheckParm (char *parm)
+{
+	int i;
+	
+	if (!parm)
+		Sys_Error ("Cmd_CheckParm: NULL");
+
+	for (i = 1; i < Cmd_Argc (); i++)
+		if (! Q_strcasecmp (parm, Cmd_Argv (i)))
+			return i;
+			
+	return 0;
+}
--- /dev/null
+++ b/WinQuake/cmd.h
@@ -1,0 +1,121 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+
+// cmd.h -- Command buffer and command execution
+
+//===========================================================================
+
+/*
+
+Any number of commands can be added in a frame, from several different sources.
+Most commands come from either keybindings or console line input, but remote
+servers can also send across commands and entire text files can be execed.
+
+The + command line options are also added to the command buffer.
+
+The game starts with a Cbuf_AddText ("exec quake.rc\n"); Cbuf_Execute ();
+
+*/
+
+
+void Cbuf_Init (void);
+// allocates an initial text buffer that will grow as needed
+
+void Cbuf_AddText (char *text);
+// as new commands are generated from the console or keybindings,
+// the text is added to the end of the command buffer.
+
+void Cbuf_InsertText (char *text);
+// when a command wants to issue other commands immediately, the text is
+// inserted at the beginning of the buffer, before any remaining unexecuted
+// commands.
+
+void Cbuf_Execute (void);
+// Pulls off \n terminated lines of text from the command buffer and sends
+// them through Cmd_ExecuteString.  Stops when the buffer is empty.
+// Normally called once per frame, but may be explicitly invoked.
+// Do not call inside a command function!
+
+//===========================================================================
+
+/*
+
+Command execution takes a null terminated string, breaks it into tokens,
+then searches for a command or variable that matches the first token.
+
+Commands can come from three sources, but the handler functions may choose
+to dissallow the action or forward it to a remote server if the source is
+not apropriate.
+
+*/
+
+typedef void (*xcommand_t) (void);
+
+typedef enum
+{
+	src_client,		// came in over a net connection as a clc_stringcmd
+					// host_client will be valid during this state.
+	src_command		// from the command buffer
+} cmd_source_t;
+
+extern	cmd_source_t	cmd_source;
+
+void	Cmd_Init (void);
+
+void	Cmd_AddCommand (char *cmd_name, xcommand_t function);
+// called by the init functions of other parts of the program to
+// register commands and functions to call for them.
+// The cmd_name is referenced later, so it should not be in temp memory
+
+qboolean Cmd_Exists (char *cmd_name);
+// used by the cvar code to check for cvar / command name overlap
+
+char 	*Cmd_CompleteCommand (char *partial);
+// attempts to match a partial command for automatic command line completion
+// returns NULL if nothing fits
+
+int		Cmd_Argc (void);
+char	*Cmd_Argv (int arg);
+char	*Cmd_Args (void);
+// The functions that execute commands get their parameters with these
+// functions. Cmd_Argv () will return an empty string, not a NULL
+// if arg > argc, so string operations are allways safe.
+
+int Cmd_CheckParm (char *parm);
+// Returns the position (1 to argc-1) in the command's argument list
+// where the given parameter apears, or 0 if not present
+
+void Cmd_TokenizeString (char *text);
+// Takes a null terminated string.  Does not need to be /n terminated.
+// breaks the string up into arg tokens.
+
+void	Cmd_ExecuteString (char *text, cmd_source_t src);
+// Parses a single line of text into arguments and tries to execute it.
+// The text can come from the command buffer, a remote client, or stdin.
+
+void	Cmd_ForwardToServer (void);
+// adds the current command line as a clc_stringcmd to the client message.
+// things like godmode, noclip, etc, are commands directed to the server,
+// so when they are typed in at the console, they will need to be forwarded.
+
+void	Cmd_Print (char *text);
+// used by command functions to send output to either the graphics console or
+// passed as a print message to the client
+
--- /dev/null
+++ b/WinQuake/common.c
@@ -1,0 +1,1827 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// common.c -- misc functions used in client and server
+
+#include "quakedef.h"
+
+#define NUM_SAFE_ARGVS  7
+
+static char     *largv[MAX_NUM_ARGVS + NUM_SAFE_ARGVS + 1];
+static char     *argvdummy = " ";
+
+static char     *safeargvs[NUM_SAFE_ARGVS] =
+	{"-stdvid", "-nolan", "-nosound", "-nocdaudio", "-nojoy", "-nomouse", "-dibonly"};
+
+cvar_t  registered = {"registered","0"};
+cvar_t  cmdline = {"cmdline","0", false, true};
+
+qboolean        com_modified;   // set true if using non-id files
+
+qboolean		proghack;
+
+int             static_registered = 1;  // only for startup check, then set
+
+qboolean		msg_suppress_1 = 0;
+
+void COM_InitFilesystem (void);
+
+// if a packfile directory differs from this, it is assumed to be hacked
+#define PAK0_COUNT              339
+#define PAK0_CRC                32981
+
+char	com_token[1024];
+int		com_argc;
+char	**com_argv;
+
+#define CMDLINE_LENGTH	256
+char	com_cmdline[CMDLINE_LENGTH];
+
+qboolean		standard_quake = true, rogue, hipnotic;
+
+// this graphic needs to be in the pak file to use registered features
+unsigned short 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
+};
+
+/*
+
+
+All of Quake's data access is through a hierchal file system, but the contents of the file system can be transparently merged from several sources.
+
+The "base directory" is the path to the directory holding the quake.exe and all game directories.  The sys_* files pass this to host_init in quakeparms_t->basedir.  This can be overridden with the "-basedir" command line parm to allow code debugging in a different directory.  The base directory is
+only used during filesystem initialization.
+
+The "game directory" is the first tree on the search path and directory that all generated files (savegames, screenshots, demos, config files) will be saved to.  This can be overridden with the "-game" command line parameter.  The game directory can never be changed while quake is executing.  This is a precacution against having a malicious server instruct clients to write files over areas they shouldn't.
+
+The "cache directory" is only used during development to save network bandwidth, especially over ISDN / T1 lines.  If there is a cache directory
+specified, when a file is found by the normal search path, it will be mirrored
+into the cache directory, then opened there.
+
+
+
+FIXME:
+The file "parms.txt" will be read out of the game directory and appended to the current command line arguments to allow different games to initialize startup parms differently.  This could be used to add a "-sspeed 22050" for the high quality sound edition.  Because they are added at the end, they will not override an explicit setting on the original command line.
+	
+*/
+
+//============================================================================
+
+
+// ClearLink is used for new headnodes
+void ClearLink (link_t *l)
+{
+	l->prev = l->next = l;
+}
+
+void RemoveLink (link_t *l)
+{
+	l->next->prev = l->prev;
+	l->prev->next = l->next;
+}
+
+void InsertLinkBefore (link_t *l, link_t *before)
+{
+	l->next = before;
+	l->prev = before->prev;
+	l->prev->next = l;
+	l->next->prev = l;
+}
+void InsertLinkAfter (link_t *l, link_t *after)
+{
+	l->next = after->next;
+	l->prev = after;
+	l->prev->next = l;
+	l->next->prev = l;
+}
+
+/*
+============================================================================
+
+					LIBRARY REPLACEMENT FUNCTIONS
+
+============================================================================
+*/
+
+void Q_memset (void *dest, int fill, int count)
+{
+	int             i;
+	
+	if ( (((long)dest | count) & 3) == 0)
+	{
+		count >>= 2;
+		fill = fill | (fill<<8) | (fill<<16) | (fill<<24);
+		for (i=0 ; i<count ; i++)
+			((int *)dest)[i] = fill;
+	}
+	else
+		for (i=0 ; i<count ; i++)
+			((byte *)dest)[i] = fill;
+}
+
+void Q_memcpy (void *dest, void *src, int count)
+{
+	int             i;
+	
+	if (( ( (long)dest | (long)src | count) & 3) == 0 )
+	{
+		count>>=2;
+		for (i=0 ; i<count ; i++)
+			((int *)dest)[i] = ((int *)src)[i];
+	}
+	else
+		for (i=0 ; i<count ; i++)
+			((byte *)dest)[i] = ((byte *)src)[i];
+}
+
+int Q_memcmp (void *m1, void *m2, int count)
+{
+	while(count)
+	{
+		count--;
+		if (((byte *)m1)[count] != ((byte *)m2)[count])
+			return -1;
+	}
+	return 0;
+}
+
+void Q_strcpy (char *dest, char *src)
+{
+	while (*src)
+	{
+		*dest++ = *src++;
+	}
+	*dest++ = 0;
+}
+
+void Q_strncpy (char *dest, char *src, int count)
+{
+	while (*src && count--)
+	{
+		*dest++ = *src++;
+	}
+	if (count)
+		*dest++ = 0;
+}
+
+int Q_strlen (char *str)
+{
+	int             count;
+	
+	count = 0;
+	while (str[count])
+		count++;
+
+	return count;
+}
+
+char *Q_strrchr(char *s, char c)
+{
+    int len = Q_strlen(s);
+    s += len;
+    while (len--)
+	if (*--s == c) return s;
+    return 0;
+}
+
+void Q_strcat (char *dest, char *src)
+{
+	dest += Q_strlen(dest);
+	Q_strcpy (dest, src);
+}
+
+int Q_strcmp (char *s1, char *s2)
+{
+	while (1)
+	{
+		if (*s1 != *s2)
+			return -1;              // strings not equal    
+		if (!*s1)
+			return 0;               // strings are equal
+		s1++;
+		s2++;
+	}
+	
+	return -1;
+}
+
+int Q_strncmp (char *s1, char *s2, int count)
+{
+	while (1)
+	{
+		if (!count--)
+			return 0;
+		if (*s1 != *s2)
+			return -1;              // strings not equal    
+		if (!*s1)
+			return 0;               // strings are equal
+		s1++;
+		s2++;
+	}
+	
+	return -1;
+}
+
+int Q_strncasecmp (char *s1, char *s2, int n)
+{
+	int             c1, c2;
+	
+	while (1)
+	{
+		c1 = *s1++;
+		c2 = *s2++;
+
+		if (!n--)
+			return 0;               // strings are equal until end point
+		
+		if (c1 != c2)
+		{
+			if (c1 >= 'a' && c1 <= 'z')
+				c1 -= ('a' - 'A');
+			if (c2 >= 'a' && c2 <= 'z')
+				c2 -= ('a' - 'A');
+			if (c1 != c2)
+				return -1;              // strings not equal
+		}
+		if (!c1)
+			return 0;               // strings are equal
+//              s1++;
+//              s2++;
+	}
+	
+	return -1;
+}
+
+int Q_strcasecmp (char *s1, char *s2)
+{
+	return Q_strncasecmp (s1, s2, 99999);
+}
+
+int Q_atoi (char *str)
+{
+	int             val;
+	int             sign;
+	int             c;
+	
+	if (*str == '-')
+	{
+		sign = -1;
+		str++;
+	}
+	else
+		sign = 1;
+		
+	val = 0;
+
+//
+// check for hex
+//
+	if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X') )
+	{
+		str += 2;
+		while (1)
+		{
+			c = *str++;
+			if (c >= '0' && c <= '9')
+				val = (val<<4) + c - '0';
+			else if (c >= 'a' && c <= 'f')
+				val = (val<<4) + c - 'a' + 10;
+			else if (c >= 'A' && c <= 'F')
+				val = (val<<4) + c - 'A' + 10;
+			else
+				return val*sign;
+		}
+	}
+	
+//
+// check for character
+//
+	if (str[0] == '\'')
+	{
+		return sign * str[1];
+	}
+	
+//
+// assume decimal
+//
+	while (1)
+	{
+		c = *str++;
+		if (c <'0' || c > '9')
+			return val*sign;
+		val = val*10 + c - '0';
+	}
+	
+	return 0;
+}
+
+
+float Q_atof (char *str)
+{
+	double			val;
+	int             sign;
+	int             c;
+	int             decimal, total;
+	
+	if (*str == '-')
+	{
+		sign = -1;
+		str++;
+	}
+	else
+		sign = 1;
+		
+	val = 0;
+
+//
+// check for hex
+//
+	if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X') )
+	{
+		str += 2;
+		while (1)
+		{
+			c = *str++;
+			if (c >= '0' && c <= '9')
+				val = (val*16) + c - '0';
+			else if (c >= 'a' && c <= 'f')
+				val = (val*16) + c - 'a' + 10;
+			else if (c >= 'A' && c <= 'F')
+				val = (val*16) + c - 'A' + 10;
+			else
+				return val*sign;
+		}
+	}
+	
+//
+// check for character
+//
+	if (str[0] == '\'')
+	{
+		return sign * str[1];
+	}
+	
+//
+// assume decimal
+//
+	decimal = -1;
+	total = 0;
+	while (1)
+	{
+		c = *str++;
+		if (c == '.')
+		{
+			decimal = total;
+			continue;
+		}
+		if (c <'0' || c > '9')
+			break;
+		val = val*10 + c - '0';
+		total++;
+	}
+
+	if (decimal == -1)
+		return val*sign;
+	while (total > decimal)
+	{
+		val /= 10;
+		total--;
+	}
+	
+	return val*sign;
+}
+
+/*
+============================================================================
+
+					BYTE ORDER FUNCTIONS
+
+============================================================================
+*/
+
+qboolean        bigendien;
+
+short   (*BigShort) (short l);
+short   (*LittleShort) (short l);
+int     (*BigLong) (int l);
+int     (*LittleLong) (int l);
+float   (*BigFloat) (float l);
+float   (*LittleFloat) (float l);
+
+short   ShortSwap (short l)
+{
+	byte    b1,b2;
+
+	b1 = l&255;
+	b2 = (l>>8)&255;
+
+	return (b1<<8) + b2;
+}
+
+short   ShortNoSwap (short l)
+{
+	return l;
+}
+
+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;
+}
+
+int     LongNoSwap (int l)
+{
+	return l;
+}
+
+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;
+}
+
+float FloatNoSwap (float f)
+{
+	return f;
+}
+
+/*
+==============================================================================
+
+			MESSAGE IO FUNCTIONS
+
+Handles byte ordering and avoids alignment errors
+==============================================================================
+*/
+
+//
+// writing functions
+//
+
+void MSG_WriteChar (sizebuf_t *sb, int c)
+{
+	byte    *buf;
+	
+#ifdef PARANOID
+	if (c < -128 || c > 127)
+		Sys_Error ("MSG_WriteChar: range error");
+#endif
+
+	buf = SZ_GetSpace (sb, 1);
+	buf[0] = c;
+}
+
+void MSG_WriteByte (sizebuf_t *sb, int c)
+{
+	byte    *buf;
+	
+#ifdef PARANOID
+	if (c < 0 || c > 255)
+		Sys_Error ("MSG_WriteByte: range error");
+#endif
+
+	buf = SZ_GetSpace (sb, 1);
+	buf[0] = c;
+}
+
+void MSG_WriteShort (sizebuf_t *sb, int c)
+{
+	byte    *buf;
+	
+#ifdef PARANOID
+	if (c < ((short)0x8000) || c > (short)0x7fff)
+		Sys_Error ("MSG_WriteShort: range error");
+#endif
+
+	buf = SZ_GetSpace (sb, 2);
+	buf[0] = c&0xff;
+	buf[1] = c>>8;
+}
+
+void MSG_WriteLong (sizebuf_t *sb, int c)
+{
+	byte    *buf;
+	
+	buf = SZ_GetSpace (sb, 4);
+	buf[0] = c&0xff;
+	buf[1] = (c>>8)&0xff;
+	buf[2] = (c>>16)&0xff;
+	buf[3] = c>>24;
+}
+
+void MSG_WriteFloat (sizebuf_t *sb, float f)
+{
+	union
+	{
+		float   f;
+		int     l;
+	} dat;
+	
+	
+	dat.f = f;
+	dat.l = LittleLong (dat.l);
+	
+	SZ_Write (sb, &dat.l, 4);
+}
+
+void MSG_WriteString (sizebuf_t *sb, char *s)
+{
+	if (!s)
+		SZ_Write (sb, "", 1);
+	else
+		SZ_Write (sb, s, Q_strlen(s)+1);
+}
+
+void MSG_WriteCoord (sizebuf_t *sb, float f)
+{
+	MSG_WriteShort (sb, (int)(f*8));
+}
+
+void MSG_WriteAngle (sizebuf_t *sb, float f)
+{
+	MSG_WriteByte (sb, ((int)f*256/360) & 255);
+}
+
+//
+// reading functions
+//
+int                     msg_readcount;
+qboolean        msg_badread;
+
+void MSG_BeginReading (void)
+{
+	msg_readcount = 0;
+	msg_badread = false;
+}
+
+// returns -1 and sets msg_badread if no more characters are available
+int MSG_ReadChar (void)
+{
+	int     c;
+	
+	if (msg_readcount+1 > net_message.cursize)
+	{
+		msg_badread = true;
+		return -1;
+	}
+		
+	c = (signed char)net_message.data[msg_readcount];
+	msg_readcount++;
+	
+	return c;
+}
+
+int MSG_ReadByte (void)
+{
+	int     c;
+	
+	if (msg_readcount+1 > net_message.cursize)
+	{
+		msg_badread = true;
+		return -1;
+	}
+		
+	c = (unsigned char)net_message.data[msg_readcount];
+	msg_readcount++;
+	
+	return c;
+}
+
+int MSG_ReadShort (void)
+{
+	int     c;
+	
+	if (msg_readcount+2 > net_message.cursize)
+	{
+		msg_badread = true;
+		return -1;
+	}
+		
+	c = (short)(net_message.data[msg_readcount]
+	+ (net_message.data[msg_readcount+1]<<8));
+	
+	msg_readcount += 2;
+	
+	return c;
+}
+
+int MSG_ReadLong (void)
+{
+	int     c;
+	
+	if (msg_readcount+4 > net_message.cursize)
+	{
+		msg_badread = true;
+		return -1;
+	}
+		
+	c = net_message.data[msg_readcount]
+	+ (net_message.data[msg_readcount+1]<<8)
+	+ (net_message.data[msg_readcount+2]<<16)
+	+ (net_message.data[msg_readcount+3]<<24);
+	
+	msg_readcount += 4;
+	
+	return c;
+}
+
+float MSG_ReadFloat (void)
+{
+	union
+	{
+		byte    b[4];
+		float   f;
+		int     l;
+	} dat;
+	
+	dat.b[0] =      net_message.data[msg_readcount];
+	dat.b[1] =      net_message.data[msg_readcount+1];
+	dat.b[2] =      net_message.data[msg_readcount+2];
+	dat.b[3] =      net_message.data[msg_readcount+3];
+	msg_readcount += 4;
+	
+	dat.l = LittleLong (dat.l);
+
+	return dat.f;   
+}
+
+char *MSG_ReadString (void)
+{
+	static char     string[2048];
+	int             l,c;
+	
+	l = 0;
+	do
+	{
+		c = MSG_ReadChar ();
+		if (c == -1 || c == 0)
+			break;
+		string[l] = c;
+		l++;
+	} while (l < sizeof(string)-1);
+	
+	string[l] = 0;
+	
+	return string;
+}
+
+float MSG_ReadCoord (void)
+{
+	return MSG_ReadShort() * (1.0/8);
+}
+
+float MSG_ReadAngle (void)
+{
+	return MSG_ReadChar() * (360.0/256);
+}
+
+
+
+//===========================================================================
+
+void SZ_Alloc (sizebuf_t *buf, int startsize)
+{
+	if (startsize < 256)
+		startsize = 256;
+	buf->data = Hunk_AllocName (startsize, "sizebuf");
+	buf->maxsize = startsize;
+	buf->cursize = 0;
+}
+
+
+void SZ_Free (sizebuf_t *buf)
+{
+//      Z_Free (buf->data);
+//      buf->data = NULL;
+//      buf->maxsize = 0;
+	buf->cursize = 0;
+}
+
+void SZ_Clear (sizebuf_t *buf)
+{
+	buf->cursize = 0;
+}
+
+void *SZ_GetSpace (sizebuf_t *buf, int length)
+{
+	void    *data;
+	
+	if (buf->cursize + length > buf->maxsize)
+	{
+		if (!buf->allowoverflow)
+			Sys_Error ("SZ_GetSpace: overflow without allowoverflow set");
+		
+		if (length > buf->maxsize)
+			Sys_Error ("SZ_GetSpace: %i is > full buffer size", length);
+			
+		buf->overflowed = true;
+		Con_Printf ("SZ_GetSpace: overflow");
+		SZ_Clear (buf); 
+	}
+
+	data = buf->data + buf->cursize;
+	buf->cursize += length;
+	
+	return data;
+}
+
+void SZ_Write (sizebuf_t *buf, void *data, int length)
+{
+	Q_memcpy (SZ_GetSpace(buf,length),data,length);         
+}
+
+void SZ_Print (sizebuf_t *buf, char *data)
+{
+	int             len;
+	
+	len = Q_strlen(data)+1;
+
+// byte * cast to keep VC++ happy
+	if (buf->data[buf->cursize-1])
+		Q_memcpy ((byte *)SZ_GetSpace(buf, len),data,len); // no trailing 0
+	else
+		Q_memcpy ((byte *)SZ_GetSpace(buf, len-1)-1,data,len); // write over trailing 0
+}
+
+
+//============================================================================
+
+
+/*
+============
+COM_SkipPath
+============
+*/
+char *COM_SkipPath (char *pathname)
+{
+	char    *last;
+	
+	last = pathname;
+	while (*pathname)
+	{
+		if (*pathname=='/')
+			last = pathname+1;
+		pathname++;
+	}
+	return last;
+}
+
+/*
+============
+COM_StripExtension
+============
+*/
+void COM_StripExtension (char *in, char *out)
+{
+	while (*in && *in != '.')
+		*out++ = *in++;
+	*out = 0;
+}
+
+/*
+============
+COM_FileExtension
+============
+*/
+char *COM_FileExtension (char *in)
+{
+	static char exten[8];
+	int             i;
+
+	while (*in && *in != '.')
+		in++;
+	if (!*in)
+		return "";
+	in++;
+	for (i=0 ; i<7 && *in ; i++,in++)
+		exten[i] = *in;
+	exten[i] = 0;
+	return exten;
+}
+
+/*
+============
+COM_FileBase
+============
+*/
+void COM_FileBase (char *in, char *out)
+{
+	char *s, *s2;
+	
+	s = in + strlen(in) - 1;
+	
+	while (s != in && *s != '.')
+		s--;
+	
+	for (s2 = s ; *s2 && *s2 != '/' ; s2--)
+	;
+	
+	if (s-s2 < 2)
+		strcpy (out,"?model?");
+	else
+	{
+		s--;
+		strncpy (out,s2+1, s-s2);
+		out[s-s2] = 0;
+	}
+}
+
+
+/*
+==================
+COM_DefaultExtension
+==================
+*/
+void COM_DefaultExtension (char *path, char *extension)
+{
+	char    *src;
+//
+// if path doesn't have a .EXT, append extension
+// (extension should include the .)
+//
+	src = path + strlen(path) - 1;
+
+	while (*src != '/' && src != path)
+	{
+		if (*src == '.')
+			return;                 // it has an extension
+		src--;
+	}
+
+	strcat (path, extension);
+}
+
+
+/*
+==============
+COM_Parse
+
+Parse a token out of a string
+==============
+*/
+char *COM_Parse (char *data)
+{
+	int             c;
+	int             len;
+	
+	len = 0;
+	com_token[0] = 0;
+	
+	if (!data)
+		return NULL;
+		
+// skip whitespace
+skipwhite:
+	while ( (c = *data) <= ' ')
+	{
+		if (c == 0)
+			return NULL;                    // end of file;
+		data++;
+	}
+	
+// skip // comments
+	if (c=='/' && data[1] == '/')
+	{
+		while (*data && *data != '\n')
+			data++;
+		goto skipwhite;
+	}
+	
+
+// handle quoted strings specially
+	if (c == '\"')
+	{
+		data++;
+		while (1)
+		{
+			c = *data++;
+			if (c=='\"' || !c)
+			{
+				com_token[len] = 0;
+				return data;
+			}
+			com_token[len] = c;
+			len++;
+		}
+	}
+
+// parse single characters
+	if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c==':')
+	{
+		com_token[len] = c;
+		len++;
+		com_token[len] = 0;
+		return data+1;
+	}
+
+// parse a regular word
+	do
+	{
+		com_token[len] = c;
+		data++;
+		len++;
+		c = *data;
+	if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c==':')
+			break;
+	} while (c>32);
+	
+	com_token[len] = 0;
+	return data;
+}
+
+
+/*
+================
+COM_CheckParm
+
+Returns the position (1 to argc-1) in the program's argument list
+where the given parameter apears, or 0 if not present
+================
+*/
+int COM_CheckParm (char *parm)
+{
+	int             i;
+	
+	for (i=1 ; i<com_argc ; i++)
+	{
+		if (!com_argv[i])
+			continue;               // NEXTSTEP sometimes clears appkit vars.
+		if (!Q_strcmp (parm,com_argv[i]))
+			return i;
+	}
+		
+	return 0;
+}
+
+/*
+================
+COM_CheckRegistered
+
+Looks for the pop.txt file and verifies it.
+Sets the "registered" cvar.
+Immediately exits out if an alternate game was attempted to be started without
+being registered.
+================
+*/
+void COM_CheckRegistered (void)
+{
+	int             h;
+	unsigned short  check[128];
+	int                     i;
+
+	COM_OpenFile("gfx/pop.lmp", &h);
+	static_registered = 0;
+
+	if (h == -1)
+	{
+#if WINDED
+	Sys_Error ("This dedicated server requires a full registered copy of Quake");
+#endif
+		Con_Printf ("Playing shareware version.\n");
+		if (com_modified)
+			Sys_Error ("You must have the registered version to use modified games");
+		return;
+	}
+
+	Sys_FileRead (h, check, sizeof(check));
+	COM_CloseFile (h);
+	
+	for (i=0 ; i<128 ; i++)
+		if (pop[i] != (unsigned short)BigShort (check[i]))
+			Sys_Error ("Corrupted data file.");
+	
+	Cvar_Set ("cmdline", com_cmdline);
+	Cvar_Set ("registered", "1");
+	static_registered = 1;
+	Con_Printf ("Playing registered version.\n");
+}
+
+
+void COM_Path_f (void);
+
+
+/*
+================
+COM_InitArgv
+================
+*/
+void COM_InitArgv (int argc, char **argv)
+{
+	qboolean        safe;
+	int             i, j, n;
+
+// reconstitute the command line for the cmdline externally visible cvar
+	n = 0;
+
+	for (j=0 ; (j<MAX_NUM_ARGVS) && (j< argc) ; j++)
+	{
+		i = 0;
+
+		while ((n < (CMDLINE_LENGTH - 1)) && argv[j][i])
+		{
+			com_cmdline[n++] = argv[j][i++];
+		}
+
+		if (n < (CMDLINE_LENGTH - 1))
+			com_cmdline[n++] = ' ';
+		else
+			break;
+	}
+
+	com_cmdline[n] = 0;
+
+	safe = false;
+
+	for (com_argc=0 ; (com_argc<MAX_NUM_ARGVS) && (com_argc < argc) ;
+		 com_argc++)
+	{
+		largv[com_argc] = argv[com_argc];
+		if (!Q_strcmp ("-safe", argv[com_argc]))
+			safe = true;
+	}
+
+	if (safe)
+	{
+	// force all the safe-mode switches. Note that we reserved extra space in
+	// case we need to add these, so we don't need an overflow check
+		for (i=0 ; i<NUM_SAFE_ARGVS ; i++)
+		{
+			largv[com_argc] = safeargvs[i];
+			com_argc++;
+		}
+	}
+
+	largv[com_argc] = argvdummy;
+	com_argv = largv;
+
+	if (COM_CheckParm ("-rogue"))
+	{
+		rogue = true;
+		standard_quake = false;
+	}
+
+	if (COM_CheckParm ("-hipnotic"))
+	{
+		hipnotic = true;
+		standard_quake = false;
+	}
+}
+
+
+/*
+================
+COM_Init
+================
+*/
+void COM_Init (char *basedir)
+{
+	byte    swaptest[2] = {1,0};
+
+// set the byte swapping variables in a portable manner 
+	if ( *(short *)swaptest == 1)
+	{
+		bigendien = false;
+		BigShort = ShortSwap;
+		LittleShort = ShortNoSwap;
+		BigLong = LongSwap;
+		LittleLong = LongNoSwap;
+		BigFloat = FloatSwap;
+		LittleFloat = FloatNoSwap;
+	}
+	else
+	{
+		bigendien = true;
+		BigShort = ShortNoSwap;
+		LittleShort = ShortSwap;
+		BigLong = LongNoSwap;
+		LittleLong = LongSwap;
+		BigFloat = FloatNoSwap;
+		LittleFloat = FloatSwap;
+	}
+
+	Cvar_RegisterVariable (&registered);
+	Cvar_RegisterVariable (&cmdline);
+	Cmd_AddCommand ("path", COM_Path_f);
+
+	COM_InitFilesystem ();
+	COM_CheckRegistered ();
+}
+
+
+/*
+============
+va
+
+does a varargs printf into a temp buffer, so I don't need to have
+varargs versions of all text functions.
+FIXME: make this buffer size safe someday
+============
+*/
+char    *va(char *format, ...)
+{
+	va_list         argptr;
+	static char             string[1024];
+	
+	va_start (argptr, format);
+	vsprintf (string, format,argptr);
+	va_end (argptr);
+
+	return string;  
+}
+
+
+/// just for debugging
+int     memsearch (byte *start, int count, int search)
+{
+	int             i;
+	
+	for (i=0 ; i<count ; i++)
+		if (start[i] == search)
+			return i;
+	return -1;
+}
+
+/*
+=============================================================================
+
+QUAKE FILESYSTEM
+
+=============================================================================
+*/
+
+int     com_filesize;
+
+
+//
+// in memory
+//
+
+typedef struct
+{
+	char    name[MAX_QPATH];
+	int             filepos, filelen;
+} packfile_t;
+
+typedef struct pack_s
+{
+	char    filename[MAX_OSPATH];
+	int             handle;
+	int             numfiles;
+	packfile_t      *files;
+} pack_t;
+
+//
+// on disk
+//
+typedef struct
+{
+	char    name[56];
+	int             filepos, filelen;
+} dpackfile_t;
+
+typedef struct
+{
+	char    id[4];
+	int             dirofs;
+	int             dirlen;
+} dpackheader_t;
+
+#define MAX_FILES_IN_PACK       2048
+
+char    com_cachedir[MAX_OSPATH];
+char    com_gamedir[MAX_OSPATH];
+
+typedef struct searchpath_s
+{
+	char    filename[MAX_OSPATH];
+	pack_t  *pack;          // only one of filename / pack will be used
+	struct searchpath_s *next;
+} searchpath_t;
+
+searchpath_t    *com_searchpaths;
+
+/*
+============
+COM_Path_f
+
+============
+*/
+void COM_Path_f (void)
+{
+	searchpath_t    *s;
+	
+	Con_Printf ("Current search path:\n");
+	for (s=com_searchpaths ; s ; s=s->next)
+	{
+		if (s->pack)
+		{
+			Con_Printf ("%s (%i files)\n", s->pack->filename, s->pack->numfiles);
+		}
+		else
+			Con_Printf ("%s\n", s->filename);
+	}
+}
+
+/*
+============
+COM_WriteFile
+
+The filename will be prefixed by the current game directory
+============
+*/
+void COM_WriteFile (char *filename, void *data, int len)
+{
+	int             handle;
+	char    name[MAX_OSPATH];
+	
+	sprintf (name, "%s/%s", com_gamedir, filename);
+
+	handle = Sys_FileOpenWrite (name);
+	if (handle == -1)
+	{
+		Sys_Printf ("COM_WriteFile: failed on %s\n", name);
+		return;
+	}
+	
+	Sys_Printf ("COM_WriteFile: %s\n", name);
+	Sys_FileWrite (handle, data, len);
+	Sys_FileClose (handle);
+}
+
+
+/*
+============
+COM_CreatePath
+
+Only used for CopyFile
+============
+*/
+void    COM_CreatePath (char *path)
+{
+	char    *ofs;
+	
+	for (ofs = path+1 ; *ofs ; ofs++)
+	{
+		if (*ofs == '/')
+		{       // create the directory
+			*ofs = 0;
+			Sys_mkdir (path);
+			*ofs = '/';
+		}
+	}
+}
+
+
+/*
+===========
+COM_CopyFile
+
+Copies a file over from the net to the local cache, creating any directories
+needed.  This is for the convenience of developers using ISDN from home.
+===========
+*/
+void COM_CopyFile (char *netpath, char *cachepath)
+{
+	int             in, out;
+	int             remaining, count;
+	char    buf[4096];
+	
+	remaining = Sys_FileOpenRead (netpath, &in);            
+	COM_CreatePath (cachepath);     // create directories up to the cache file
+	out = Sys_FileOpenWrite (cachepath);
+	
+	while (remaining)
+	{
+		if (remaining < sizeof(buf))
+			count = remaining;
+		else
+			count = sizeof(buf);
+		Sys_FileRead (in, buf, count);
+		Sys_FileWrite (out, buf, count);
+		remaining -= count;
+	}
+
+	Sys_FileClose (in);
+	Sys_FileClose (out);    
+}
+
+/*
+===========
+COM_FindFile
+
+Finds the file in the search path.
+Sets com_filesize and one of handle or file
+===========
+*/
+int COM_FindFile (char *filename, int *handle, FILE **file)
+{
+	searchpath_t    *search;
+	char            netpath[MAX_OSPATH];
+	char            cachepath[MAX_OSPATH];
+	pack_t          *pak;
+	int                     i;
+	int                     findtime, cachetime;
+
+	if (file && handle)
+		Sys_Error ("COM_FindFile: both handle and file set");
+	if (!file && !handle)
+		Sys_Error ("COM_FindFile: neither handle or file set");
+		
+//
+// search through the path, one element at a time
+//
+	search = com_searchpaths;
+	if (proghack)
+	{	// gross hack to use quake 1 progs with quake 2 maps
+		if (!strcmp(filename, "progs.dat"))
+			search = search->next;
+	}
+
+	for ( ; search ; search = search->next)
+	{
+	// is the element a pak file?
+		if (search->pack)
+		{
+		// look through all the pak file elements
+			pak = search->pack;
+			for (i=0 ; i<pak->numfiles ; i++)
+				if (!strcmp (pak->files[i].name, filename))
+				{       // found it!
+					Sys_Printf ("PackFile: %s : %s\n",pak->filename, filename);
+					if (handle)
+					{
+						*handle = pak->handle;
+						Sys_FileSeek (pak->handle, pak->files[i].filepos);
+					}
+					else
+					{       // open a new file on the pakfile
+						*file = fopen (pak->filename, "rb");
+						if (*file)
+							fseek (*file, pak->files[i].filepos, SEEK_SET);
+					}
+					com_filesize = pak->files[i].filelen;
+					return com_filesize;
+				}
+		}
+		else
+		{               
+	// check a file in the directory tree
+			if (!static_registered)
+			{       // if not a registered version, don't ever go beyond base
+				if ( strchr (filename, '/') || strchr (filename,'\\'))
+					continue;
+			}
+			
+			sprintf (netpath, "%s/%s",search->filename, filename);
+			
+			findtime = Sys_FileTime (netpath);
+			if (findtime == -1)
+				continue;
+				
+		// see if the file needs to be updated in the cache
+			if (!com_cachedir[0])
+				strcpy (cachepath, netpath);
+			else
+			{	
+#if defined(_WIN32)
+				if ((strlen(netpath) < 2) || (netpath[1] != ':'))
+					sprintf (cachepath,"%s%s", com_cachedir, netpath);
+				else
+					sprintf (cachepath,"%s%s", com_cachedir, netpath+2);
+#else
+				sprintf (cachepath,"%s%s", com_cachedir, netpath);
+#endif
+
+				cachetime = Sys_FileTime (cachepath);
+			
+				if (cachetime < findtime)
+					COM_CopyFile (netpath, cachepath);
+				strcpy (netpath, cachepath);
+			}	
+
+			Sys_Printf ("FindFile: %s\n",netpath);
+			com_filesize = Sys_FileOpenRead (netpath, &i);
+			if (handle)
+				*handle = i;
+			else
+			{
+				Sys_FileClose (i);
+				*file = fopen (netpath, "rb");
+			}
+			return com_filesize;
+		}
+		
+	}
+	
+	Sys_Printf ("FindFile: can't find %s\n", filename);
+	
+	if (handle)
+		*handle = -1;
+	else
+		*file = NULL;
+	com_filesize = -1;
+	return -1;
+}
+
+
+/*
+===========
+COM_OpenFile
+
+filename never has a leading slash, but may contain directory walks
+returns a handle and a length
+it may actually be inside a pak file
+===========
+*/
+int COM_OpenFile (char *filename, int *handle)
+{
+	return COM_FindFile (filename, handle, NULL);
+}
+
+/*
+===========
+COM_FOpenFile
+
+If the requested file is inside a packfile, a new FILE * will be opened
+into the file.
+===========
+*/
+int COM_FOpenFile (char *filename, FILE **file)
+{
+	return COM_FindFile (filename, NULL, file);
+}
+
+/*
+============
+COM_CloseFile
+
+If it is a pak file handle, don't really close it
+============
+*/
+void COM_CloseFile (int h)
+{
+	searchpath_t    *s;
+	
+	for (s = com_searchpaths ; s ; s=s->next)
+		if (s->pack && s->pack->handle == h)
+			return;
+			
+	Sys_FileClose (h);
+}
+
+
+/*
+============
+COM_LoadFile
+
+Filename are reletive to the quake directory.
+Allways appends a 0 byte.
+============
+*/
+cache_user_t *loadcache;
+byte    *loadbuf;
+int             loadsize;
+byte *COM_LoadFile (char *path, int usehunk)
+{
+	int             h;
+	byte    *buf;
+	char    base[32];
+	int             len;
+
+	buf = NULL;     // quiet compiler warning
+
+// look for it in the filesystem or pack files
+	len = COM_OpenFile (path, &h);
+	if (h == -1)
+		return NULL;
+	
+// extract the filename base name for hunk tag
+	COM_FileBase (path, base);
+	
+	if (usehunk == 1)
+		buf = Hunk_AllocName (len+1, base);
+	else if (usehunk == 2)
+		buf = Hunk_TempAlloc (len+1);
+	else if (usehunk == 0)
+		buf = Z_Malloc (len+1);
+	else if (usehunk == 3)
+		buf = Cache_Alloc (loadcache, len+1, base);
+	else if (usehunk == 4)
+	{
+		if (len+1 > loadsize)
+			buf = Hunk_TempAlloc (len+1);
+		else
+			buf = loadbuf;
+	}
+	else
+		Sys_Error ("COM_LoadFile: bad usehunk");
+
+	if (!buf)
+		Sys_Error ("COM_LoadFile: not enough space for %s", path);
+		
+	((byte *)buf)[len] = 0;
+
+	Draw_BeginDisc ();
+	Sys_FileRead (h, buf, len);                     
+	COM_CloseFile (h);
+	Draw_EndDisc ();
+
+	return buf;
+}
+
+byte *COM_LoadHunkFile (char *path)
+{
+	return COM_LoadFile (path, 1);
+}
+
+byte *COM_LoadTempFile (char *path)
+{
+	return COM_LoadFile (path, 2);
+}
+
+void COM_LoadCacheFile (char *path, struct cache_user_s *cu)
+{
+	loadcache = cu;
+	COM_LoadFile (path, 3);
+}
+
+// uses temp hunk if larger than bufsize
+byte *COM_LoadStackFile (char *path, void *buffer, int bufsize)
+{
+	byte    *buf;
+	
+	loadbuf = (byte *)buffer;
+	loadsize = bufsize;
+	buf = COM_LoadFile (path, 4);
+	
+	return buf;
+}
+
+/*
+=================
+COM_LoadPackFile
+
+Takes an explicit (not game tree related) path to a pak file.
+
+Loads the header and directory, adding the files at the beginning
+of the list so they override previous pack files.
+=================
+*/
+pack_t *COM_LoadPackFile (char *packfile)
+{
+	dpackheader_t   header;
+	int                             i;
+	packfile_t              *newfiles;
+	int                             numpackfiles;
+	pack_t                  *pack;
+	int                             packhandle;
+	dpackfile_t             info[MAX_FILES_IN_PACK];
+	unsigned short          crc;
+
+	if (Sys_FileOpenRead (packfile, &packhandle) == -1)
+	{
+//              Con_Printf ("Couldn't open %s\n", packfile);
+		return NULL;
+	}
+	Sys_FileRead (packhandle, (void *)&header, sizeof(header));
+	if (header.id[0] != 'P' || header.id[1] != 'A'
+	|| header.id[2] != 'C' || header.id[3] != 'K')
+		Sys_Error ("%s is not a packfile", packfile);
+	header.dirofs = LittleLong (header.dirofs);
+	header.dirlen = LittleLong (header.dirlen);
+
+	numpackfiles = header.dirlen / sizeof(dpackfile_t);
+
+	if (numpackfiles > MAX_FILES_IN_PACK)
+		Sys_Error ("%s has %i files", packfile, numpackfiles);
+
+	if (numpackfiles != PAK0_COUNT)
+		com_modified = true;    // not the original file
+
+	newfiles = Hunk_AllocName (numpackfiles * sizeof(packfile_t), "packfile");
+
+	Sys_FileSeek (packhandle, header.dirofs);
+	Sys_FileRead (packhandle, (void *)info, header.dirlen);
+
+// crc the directory to check for modifications
+	CRC_Init (&crc);
+	for (i=0 ; i<header.dirlen ; i++)
+		CRC_ProcessByte (&crc, ((byte *)info)[i]);
+	if (crc != PAK0_CRC)
+		com_modified = true;
+
+// parse the directory
+	for (i=0 ; i<numpackfiles ; i++)
+	{
+		strcpy (newfiles[i].name, info[i].name);
+		newfiles[i].filepos = LittleLong(info[i].filepos);
+		newfiles[i].filelen = LittleLong(info[i].filelen);
+	}
+
+	pack = Hunk_Alloc (sizeof (pack_t));
+	strcpy (pack->filename, packfile);
+	pack->handle = packhandle;
+	pack->numfiles = numpackfiles;
+	pack->files = newfiles;
+	
+	Con_Printf ("Added packfile %s (%i files)\n", packfile, numpackfiles);
+	return pack;
+}
+
+
+/*
+================
+COM_AddGameDirectory
+
+Sets com_gamedir, adds the directory to the head of the path,
+then loads and adds pak1.pak pak2.pak ... 
+================
+*/
+void COM_AddGameDirectory (char *dir)
+{
+	int                             i;
+	searchpath_t    *search;
+	pack_t                  *pak;
+	char                    pakfile[MAX_OSPATH];
+
+	strcpy (com_gamedir, dir);
+
+//
+// add the directory to the search path
+//
+	search = Hunk_Alloc (sizeof(searchpath_t));
+	strcpy (search->filename, dir);
+	search->next = com_searchpaths;
+	com_searchpaths = search;
+
+//
+// add any pak files in the format pak0.pak pak1.pak, ...
+//
+	for (i=0 ; ; i++)
+	{
+		sprintf (pakfile, "%s/pak%i.pak", dir, i);
+		pak = COM_LoadPackFile (pakfile);
+		if (!pak)
+			break;
+		search = Hunk_Alloc (sizeof(searchpath_t));
+		search->pack = pak;
+		search->next = com_searchpaths;
+		com_searchpaths = search;               
+	}
+
+//
+// add the contents of the parms.txt file to the end of the command line
+//
+
+}
+
+/*
+================
+COM_InitFilesystem
+================
+*/
+void COM_InitFilesystem (void)
+{
+	int             i, j;
+	char    basedir[MAX_OSPATH];
+	searchpath_t    *search;
+
+//
+// -basedir <path>
+// Overrides the system supplied base directory (under GAMENAME)
+//
+	i = COM_CheckParm ("-basedir");
+	if (i && i < com_argc-1)
+		strcpy (basedir, com_argv[i+1]);
+	else
+		strcpy (basedir, host_parms.basedir);
+
+	j = strlen (basedir);
+
+	if (j > 0)
+	{
+		if ((basedir[j-1] == '\\') || (basedir[j-1] == '/'))
+			basedir[j-1] = 0;
+	}
+
+//
+// -cachedir <path>
+// Overrides the system supplied cache directory (NULL or /qcache)
+// -cachedir - will disable caching.
+//
+	i = COM_CheckParm ("-cachedir");
+	if (i && i < com_argc-1)
+	{
+		if (com_argv[i+1][0] == '-')
+			com_cachedir[0] = 0;
+		else
+			strcpy (com_cachedir, com_argv[i+1]);
+	}
+	else if (host_parms.cachedir)
+		strcpy (com_cachedir, host_parms.cachedir);
+	else
+		com_cachedir[0] = 0;
+
+//
+// start up with GAMENAME by default (id1)
+//
+	COM_AddGameDirectory (va("%s/"GAMENAME, basedir) );
+
+	if (COM_CheckParm ("-rogue"))
+		COM_AddGameDirectory (va("%s/rogue", basedir) );
+	if (COM_CheckParm ("-hipnotic"))
+		COM_AddGameDirectory (va("%s/hipnotic", basedir) );
+
+//
+// -game <gamedir>
+// Adds basedir/gamedir as an override game
+//
+	i = COM_CheckParm ("-game");
+	if (i && i < com_argc-1)
+	{
+		com_modified = true;
+		COM_AddGameDirectory (va("%s/%s", basedir, com_argv[i+1]));
+	}
+
+//
+// -path <dir or packfile> [<dir or packfile>] ...
+// Fully specifies the exact serach path, overriding the generated one
+//
+	i = COM_CheckParm ("-path");
+	if (i)
+	{
+		com_modified = true;
+		com_searchpaths = NULL;
+		while (++i < com_argc)
+		{
+			if (!com_argv[i] || com_argv[i][0] == '+' || com_argv[i][0] == '-')
+				break;
+			
+			search = Hunk_Alloc (sizeof(searchpath_t));
+			if ( !strcmp(COM_FileExtension(com_argv[i]), "pak") )
+			{
+				search->pack = COM_LoadPackFile (com_argv[i]);
+				if (!search->pack)
+					Sys_Error ("Couldn't load packfile: %s", com_argv[i]);
+			}
+			else
+				strcpy (search->filename, com_argv[i]);
+			search->next = com_searchpaths;
+			com_searchpaths = search;
+		}
+	}
+
+	if (COM_CheckParm ("-proghack"))
+		proghack = true;
+}
+
+
--- /dev/null
+++ b/WinQuake/common.h
@@ -1,0 +1,183 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// comndef.h  -- general definitions
+
+#if !defined BYTE_DEFINED
+typedef unsigned char 		byte;
+#define BYTE_DEFINED 1
+#endif
+
+#undef true
+#undef false
+
+typedef enum {false, true}	qboolean;
+
+//============================================================================
+
+typedef struct sizebuf_s
+{
+	qboolean	allowoverflow;	// if false, do a Sys_Error
+	qboolean	overflowed;		// set to true if the buffer size failed
+	byte	*data;
+	int		maxsize;
+	int		cursize;
+} sizebuf_t;
+
+void SZ_Alloc (sizebuf_t *buf, int startsize);
+void SZ_Free (sizebuf_t *buf);
+void SZ_Clear (sizebuf_t *buf);
+void *SZ_GetSpace (sizebuf_t *buf, int length);
+void SZ_Write (sizebuf_t *buf, void *data, int length);
+void SZ_Print (sizebuf_t *buf, char *data);	// strcats onto the sizebuf
+
+//============================================================================
+
+typedef struct link_s
+{
+	struct link_s	*prev, *next;
+} link_t;
+
+
+void ClearLink (link_t *l);
+void RemoveLink (link_t *l);
+void InsertLinkBefore (link_t *l, link_t *before);
+void InsertLinkAfter (link_t *l, link_t *after);
+
+// (type *)STRUCT_FROM_LINK(link_t *link, type, member)
+// ent = STRUCT_FROM_LINK(link,entity_t,order)
+// FIXME: remove this mess!
+#define	STRUCT_FROM_LINK(l,t,m) ((t *)((byte *)l - (int)&(((t *)0)->m)))
+
+//============================================================================
+
+#ifndef NULL
+#define NULL ((void *)0)
+#endif
+
+#define Q_MAXCHAR ((char)0x7f)
+#define Q_MAXSHORT ((short)0x7fff)
+#define Q_MAXINT	((int)0x7fffffff)
+#define Q_MAXLONG ((int)0x7fffffff)
+#define Q_MAXFLOAT ((int)0x7fffffff)
+
+#define Q_MINCHAR ((char)0x80)
+#define Q_MINSHORT ((short)0x8000)
+#define Q_MININT 	((int)0x80000000)
+#define Q_MINLONG ((int)0x80000000)
+#define Q_MINFLOAT ((int)0x7fffffff)
+
+//============================================================================
+
+extern	qboolean		bigendien;
+
+extern	short	(*BigShort) (short l);
+extern	short	(*LittleShort) (short l);
+extern	int	(*BigLong) (int l);
+extern	int	(*LittleLong) (int l);
+extern	float	(*BigFloat) (float l);
+extern	float	(*LittleFloat) (float l);
+
+//============================================================================
+
+void MSG_WriteChar (sizebuf_t *sb, int c);
+void MSG_WriteByte (sizebuf_t *sb, int c);
+void MSG_WriteShort (sizebuf_t *sb, int c);
+void MSG_WriteLong (sizebuf_t *sb, int c);
+void MSG_WriteFloat (sizebuf_t *sb, float f);
+void MSG_WriteString (sizebuf_t *sb, char *s);
+void MSG_WriteCoord (sizebuf_t *sb, float f);
+void MSG_WriteAngle (sizebuf_t *sb, float f);
+
+extern	int			msg_readcount;
+extern	qboolean	msg_badread;		// set if a read goes beyond end of message
+
+void MSG_BeginReading (void);
+int MSG_ReadChar (void);
+int MSG_ReadByte (void);
+int MSG_ReadShort (void);
+int MSG_ReadLong (void);
+float MSG_ReadFloat (void);
+char *MSG_ReadString (void);
+
+float MSG_ReadCoord (void);
+float MSG_ReadAngle (void);
+
+//============================================================================
+
+void Q_memset (void *dest, int fill, int count);
+void Q_memcpy (void *dest, void *src, int count);
+int Q_memcmp (void *m1, void *m2, int count);
+void Q_strcpy (char *dest, char *src);
+void Q_strncpy (char *dest, char *src, int count);
+int Q_strlen (char *str);
+char *Q_strrchr (char *s, char c);
+void Q_strcat (char *dest, char *src);
+int Q_strcmp (char *s1, char *s2);
+int Q_strncmp (char *s1, char *s2, int count);
+int Q_strcasecmp (char *s1, char *s2);
+int Q_strncasecmp (char *s1, char *s2, int n);
+int	Q_atoi (char *str);
+float Q_atof (char *str);
+
+//============================================================================
+
+extern	char		com_token[1024];
+extern	qboolean	com_eof;
+
+char *COM_Parse (char *data);
+
+
+extern	int		com_argc;
+extern	char	**com_argv;
+
+int COM_CheckParm (char *parm);
+void COM_Init (char *path);
+void COM_InitArgv (int argc, char **argv);
+
+char *COM_SkipPath (char *pathname);
+void COM_StripExtension (char *in, char *out);
+void COM_FileBase (char *in, char *out);
+void COM_DefaultExtension (char *path, char *extension);
+
+char	*va(char *format, ...);
+// does a varargs printf into a temp buffer
+
+
+//============================================================================
+
+extern int com_filesize;
+struct cache_user_s;
+
+extern	char	com_gamedir[MAX_OSPATH];
+
+void COM_WriteFile (char *filename, void *data, int len);
+int COM_OpenFile (char *filename, int *hndl);
+int COM_FOpenFile (char *filename, FILE **file);
+void COM_CloseFile (int h);
+
+byte *COM_LoadStackFile (char *path, void *buffer, int bufsize);
+byte *COM_LoadTempFile (char *path);
+byte *COM_LoadHunkFile (char *path);
+void COM_LoadCacheFile (char *path, struct cache_user_s *cu);
+
+
+extern	struct cvar_s	registered;
+
+extern qboolean		standard_quake, rogue, hipnotic;
--- /dev/null
+++ b/WinQuake/conproc.c
@@ -1,0 +1,365 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// conproc.c
+
+#include <windows.h>
+#include "conproc.h"
+#include "quakedef.h"
+
+HANDLE	heventDone;
+HANDLE	hfileBuffer;
+HANDLE	heventChildSend;
+HANDLE	heventParentSend;
+HANDLE	hStdout;
+HANDLE	hStdin;
+
+DWORD RequestProc (DWORD dwNichts);
+LPVOID GetMappedBuffer (HANDLE hfileBuffer);
+void ReleaseMappedBuffer (LPVOID pBuffer);
+BOOL GetScreenBufferLines (int *piLines);
+BOOL SetScreenBufferLines (int iLines);
+BOOL ReadText (LPTSTR pszText, int iBeginLine, int iEndLine);
+BOOL WriteText (LPCTSTR szText);
+int CharToCode (char c);
+BOOL SetConsoleCXCY(HANDLE hStdout, int cx, int cy);
+
+
+void InitConProc (HANDLE hFile, HANDLE heventParent, HANDLE heventChild)
+{
+	DWORD	dwID;
+	CONSOLE_SCREEN_BUFFER_INFO	info;
+	int		wheight, wwidth;
+
+// ignore if we don't have all the events.
+	if (!hFile || !heventParent || !heventChild)
+		return;
+
+	hfileBuffer = hFile;
+	heventParentSend = heventParent;
+	heventChildSend = heventChild;
+
+// so we'll know when to go away.
+	heventDone = CreateEvent (NULL, FALSE, FALSE, NULL);
+
+	if (!heventDone)
+	{
+		Con_SafePrintf ("Couldn't create heventDone\n");
+		return;
+	}
+
+	if (!CreateThread (NULL,
+					   0,
+					   (LPTHREAD_START_ROUTINE) RequestProc,
+					   0,
+					   0,
+					   &dwID))
+	{
+		CloseHandle (heventDone);
+		Con_SafePrintf ("Couldn't create QHOST thread\n");
+		return;
+	}
+
+// save off the input/output handles.
+	hStdout = GetStdHandle (STD_OUTPUT_HANDLE);
+	hStdin = GetStdHandle (STD_INPUT_HANDLE);
+
+// force 80 character width, at least 25 character height
+	SetConsoleCXCY (hStdout, 80, 25);
+}
+
+
+void DeinitConProc (void)
+{
+	if (heventDone)
+		SetEvent (heventDone);
+}
+
+
+DWORD RequestProc (DWORD dwNichts)
+{
+	int		*pBuffer;
+	DWORD	dwRet;
+	HANDLE	heventWait[2];
+	int		iBeginLine, iEndLine;
+	
+	heventWait[0] = heventParentSend;
+	heventWait[1] = heventDone;
+
+	while (1)
+	{
+		dwRet = WaitForMultipleObjects (2, heventWait, FALSE, INFINITE);
+
+	// heventDone fired, so we're exiting.
+		if (dwRet == WAIT_OBJECT_0 + 1)	
+			break;
+
+		pBuffer = (int *) GetMappedBuffer (hfileBuffer);
+		
+	// hfileBuffer is invalid.  Just leave.
+		if (!pBuffer)
+		{
+			Con_SafePrintf ("Invalid hfileBuffer\n");
+			break;
+		}
+
+		switch (pBuffer[0])
+		{
+			case CCOM_WRITE_TEXT:
+			// Param1 : Text
+				pBuffer[0] = WriteText ((LPCTSTR) (pBuffer + 1));
+				break;
+
+			case CCOM_GET_TEXT:
+			// Param1 : Begin line
+			// Param2 : End line
+				iBeginLine = pBuffer[1];
+				iEndLine = pBuffer[2];
+				pBuffer[0] = ReadText ((LPTSTR) (pBuffer + 1), iBeginLine, 
+									   iEndLine);
+				break;
+
+			case CCOM_GET_SCR_LINES:
+			// No params
+				pBuffer[0] = GetScreenBufferLines (&pBuffer[1]);
+				break;
+
+			case CCOM_SET_SCR_LINES:
+			// Param1 : Number of lines
+				pBuffer[0] = SetScreenBufferLines (pBuffer[1]);
+				break;
+		}
+
+		ReleaseMappedBuffer (pBuffer);
+		SetEvent (heventChildSend);
+	}
+
+	return 0;
+}
+
+
+LPVOID GetMappedBuffer (HANDLE hfileBuffer)
+{
+	LPVOID pBuffer;
+
+	pBuffer = MapViewOfFile (hfileBuffer,
+							FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
+
+	return pBuffer;
+}
+
+
+void ReleaseMappedBuffer (LPVOID pBuffer)
+{
+	UnmapViewOfFile (pBuffer);
+}
+
+
+BOOL GetScreenBufferLines (int *piLines)
+{
+	CONSOLE_SCREEN_BUFFER_INFO	info;							  
+	BOOL						bRet;
+
+	bRet = GetConsoleScreenBufferInfo (hStdout, &info);
+		
+	if (bRet)
+		*piLines = info.dwSize.Y;
+
+	return bRet;
+}
+
+
+BOOL SetScreenBufferLines (int iLines)
+{
+
+	return SetConsoleCXCY (hStdout, 80, iLines);
+}
+
+
+BOOL ReadText (LPTSTR pszText, int iBeginLine, int iEndLine)
+{
+	COORD	coord;
+	DWORD	dwRead;
+	BOOL	bRet;
+
+	coord.X = 0;
+	coord.Y = iBeginLine;
+
+	bRet = ReadConsoleOutputCharacter(
+		hStdout,
+		pszText,
+		80 * (iEndLine - iBeginLine + 1),
+		coord,
+		&dwRead);
+
+	// Make sure it's null terminated.
+	if (bRet)
+		pszText[dwRead] = '\0';
+
+	return bRet;
+}
+
+
+BOOL WriteText (LPCTSTR szText)
+{
+	DWORD			dwWritten;
+	INPUT_RECORD	rec;
+	char			upper, *sz;
+
+	sz = (LPTSTR) szText;
+
+	while (*sz)
+	{
+	// 13 is the code for a carriage return (\n) instead of 10.
+		if (*sz == 10)
+			*sz = 13;
+
+		upper = toupper(*sz);
+
+		rec.EventType = KEY_EVENT;
+		rec.Event.KeyEvent.bKeyDown = TRUE;
+		rec.Event.KeyEvent.wRepeatCount = 1;
+		rec.Event.KeyEvent.wVirtualKeyCode = upper;
+		rec.Event.KeyEvent.wVirtualScanCode = CharToCode (*sz);
+		rec.Event.KeyEvent.uChar.AsciiChar = *sz;
+		rec.Event.KeyEvent.uChar.UnicodeChar = *sz;
+		rec.Event.KeyEvent.dwControlKeyState = isupper(*sz) ? 0x80 : 0x0; 
+
+		WriteConsoleInput(
+			hStdin,
+			&rec,
+			1,
+			&dwWritten);
+
+		rec.Event.KeyEvent.bKeyDown = FALSE;
+
+		WriteConsoleInput(
+			hStdin,
+			&rec,
+			1,
+			&dwWritten);
+
+		sz++;
+	}
+
+	return TRUE;
+}
+
+
+int CharToCode (char c)
+{
+	char upper;
+		
+	upper = toupper(c);
+
+	switch (c)
+	{
+		case 13:
+			return 28;
+
+		default:
+			break;
+	}
+
+	if (isalpha(c))
+		return (30 + upper - 65); 
+
+	if (isdigit(c))
+		return (1 + upper - 47);
+
+	return c;
+}
+
+
+BOOL SetConsoleCXCY(HANDLE hStdout, int cx, int cy)
+{
+	CONSOLE_SCREEN_BUFFER_INFO	info;
+	COORD						coordMax;
+ 
+	coordMax = GetLargestConsoleWindowSize(hStdout);
+
+	if (cy > coordMax.Y)
+		cy = coordMax.Y;
+
+	if (cx > coordMax.X)
+		cx = coordMax.X;
+ 
+	if (!GetConsoleScreenBufferInfo(hStdout, &info))
+		return FALSE;
+ 
+// height
+    info.srWindow.Left = 0;         
+    info.srWindow.Right = info.dwSize.X - 1;                
+    info.srWindow.Top = 0;
+    info.srWindow.Bottom = cy - 1;          
+ 
+	if (cy < info.dwSize.Y)
+	{
+		if (!SetConsoleWindowInfo(hStdout, TRUE, &info.srWindow))
+			return FALSE;
+ 
+		info.dwSize.Y = cy;
+ 
+		if (!SetConsoleScreenBufferSize(hStdout, info.dwSize))
+			return FALSE;
+    }
+    else if (cy > info.dwSize.Y)
+    {
+		info.dwSize.Y = cy;
+ 
+		if (!SetConsoleScreenBufferSize(hStdout, info.dwSize))
+			return FALSE;
+ 
+		if (!SetConsoleWindowInfo(hStdout, TRUE, &info.srWindow))
+			return FALSE;
+    }
+ 
+	if (!GetConsoleScreenBufferInfo(hStdout, &info))
+		return FALSE;
+ 
+// width
+	info.srWindow.Left = 0;         
+	info.srWindow.Right = cx - 1;
+	info.srWindow.Top = 0;
+	info.srWindow.Bottom = info.dwSize.Y - 1;               
+ 
+	if (cx < info.dwSize.X)
+	{
+		if (!SetConsoleWindowInfo(hStdout, TRUE, &info.srWindow))
+			return FALSE;
+ 
+		info.dwSize.X = cx;
+    
+		if (!SetConsoleScreenBufferSize(hStdout, info.dwSize))
+			return FALSE;
+	}
+	else if (cx > info.dwSize.X)
+	{
+		info.dwSize.X = cx;
+ 
+		if (!SetConsoleScreenBufferSize(hStdout, info.dwSize))
+			return FALSE;
+ 
+		if (!SetConsoleWindowInfo(hStdout, TRUE, &info.srWindow))
+			return FALSE;
+	}
+ 
+	return TRUE;
+}
+     
--- /dev/null
+++ b/WinQuake/conproc.h
@@ -1,0 +1,37 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// conproc.h
+
+#define CCOM_WRITE_TEXT		0x2
+// Param1 : Text
+
+#define CCOM_GET_TEXT		0x3
+// Param1 : Begin line
+// Param2 : End line
+
+#define CCOM_GET_SCR_LINES	0x4
+// No params
+
+#define CCOM_SET_SCR_LINES	0x5
+// Param1 : Number of lines
+
+void InitConProc (HANDLE hFile, HANDLE heventParent, HANDLE heventChild);
+void DeinitConProc (void);
+
--- /dev/null
+++ b/WinQuake/console.c
@@ -1,0 +1,649 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// console.c
+
+#ifdef NeXT
+#include <libc.h>
+#endif
+#ifndef _MSC_VER
+#include <unistd.h>
+#endif
+#include <fcntl.h>
+#include "quakedef.h"
+
+int 		con_linewidth;
+
+float		con_cursorspeed = 4;
+
+#define		CON_TEXTSIZE	16384
+
+qboolean 	con_forcedup;		// because no entities to refresh
+
+int			con_totallines;		// total lines in console scrollback
+int			con_backscroll;		// lines up from bottom to display
+int			con_current;		// where next message will be printed
+int			con_x;				// offset in current line for next print
+char		*con_text=0;
+
+cvar_t		con_notifytime = {"con_notifytime","3"};		//seconds
+
+#define	NUM_CON_TIMES 4
+float		con_times[NUM_CON_TIMES];	// realtime time the line was generated
+								// for transparent notify lines
+
+int			con_vislines;
+
+qboolean	con_debuglog;
+
+#define		MAXCMDLINE	256
+extern	char	key_lines[32][MAXCMDLINE];
+extern	int		edit_line;
+extern	int		key_linepos;
+		
+
+qboolean	con_initialized;
+
+int			con_notifylines;		// scan lines to clear for notify lines
+
+extern void M_Menu_Main_f (void);
+
+/*
+================
+Con_ToggleConsole_f
+================
+*/
+void Con_ToggleConsole_f (void)
+{
+	if (key_dest == key_console)
+	{
+		if (cls.state == ca_connected)
+		{
+			key_dest = key_game;
+			key_lines[edit_line][1] = 0;	// clear any typing
+			key_linepos = 1;
+		}
+		else
+		{
+			M_Menu_Main_f ();
+		}
+	}
+	else
+		key_dest = key_console;
+	
+	SCR_EndLoadingPlaque ();
+	memset (con_times, 0, sizeof(con_times));
+}
+
+/*
+================
+Con_Clear_f
+================
+*/
+void Con_Clear_f (void)
+{
+	if (con_text)
+		Q_memset (con_text, ' ', CON_TEXTSIZE);
+}
+
+						
+/*
+================
+Con_ClearNotify
+================
+*/
+void Con_ClearNotify (void)
+{
+	int		i;
+	
+	for (i=0 ; i<NUM_CON_TIMES ; i++)
+		con_times[i] = 0;
+}
+
+						
+/*
+================
+Con_MessageMode_f
+================
+*/
+extern qboolean team_message;
+
+void Con_MessageMode_f (void)
+{
+	key_dest = key_message;
+	team_message = false;
+}
+
+						
+/*
+================
+Con_MessageMode2_f
+================
+*/
+void Con_MessageMode2_f (void)
+{
+	key_dest = key_message;
+	team_message = true;
+}
+
+						
+/*
+================
+Con_CheckResize
+
+If the line width has changed, reformat the buffer.
+================
+*/
+void Con_CheckResize (void)
+{
+	int		i, j, width, oldwidth, oldtotallines, numlines, numchars;
+	char	tbuf[CON_TEXTSIZE];
+
+	width = (vid.width >> 3) - 2;
+
+	if (width == con_linewidth)
+		return;
+
+	if (width < 1)			// video hasn't been initialized yet
+	{
+		width = 38;
+		con_linewidth = width;
+		con_totallines = CON_TEXTSIZE / con_linewidth;
+		Q_memset (con_text, ' ', CON_TEXTSIZE);
+	}
+	else
+	{
+		oldwidth = con_linewidth;
+		con_linewidth = width;
+		oldtotallines = con_totallines;
+		con_totallines = CON_TEXTSIZE / con_linewidth;
+		numlines = oldtotallines;
+
+		if (con_totallines < numlines)
+			numlines = con_totallines;
+
+		numchars = oldwidth;
+	
+		if (con_linewidth < numchars)
+			numchars = con_linewidth;
+
+		Q_memcpy (tbuf, con_text, CON_TEXTSIZE);
+		Q_memset (con_text, ' ', CON_TEXTSIZE);
+
+		for (i=0 ; i<numlines ; i++)
+		{
+			for (j=0 ; j<numchars ; j++)
+			{
+				con_text[(con_totallines - 1 - i) * con_linewidth + j] =
+						tbuf[((con_current - i + oldtotallines) %
+							  oldtotallines) * oldwidth + j];
+			}
+		}
+
+		Con_ClearNotify ();
+	}
+
+	con_backscroll = 0;
+	con_current = con_totallines - 1;
+}
+
+
+/*
+================
+Con_Init
+================
+*/
+void Con_Init (void)
+{
+#define MAXGAMEDIRLEN	1000
+	char	temp[MAXGAMEDIRLEN+1];
+	char	*t2 = "/qconsole.log";
+
+	con_debuglog = COM_CheckParm("-condebug");
+
+	if (con_debuglog)
+	{
+		if (strlen (com_gamedir) < (MAXGAMEDIRLEN - strlen (t2)))
+		{
+			sprintf (temp, "%s%s", com_gamedir, t2);
+			unlink (temp);
+		}
+	}
+
+	con_text = Hunk_AllocName (CON_TEXTSIZE, "context");
+	Q_memset (con_text, ' ', CON_TEXTSIZE);
+	con_linewidth = -1;
+	Con_CheckResize ();
+	
+	Con_Printf ("Console initialized.\n");
+
+//
+// register our commands
+//
+	Cvar_RegisterVariable (&con_notifytime);
+
+	Cmd_AddCommand ("toggleconsole", Con_ToggleConsole_f);
+	Cmd_AddCommand ("messagemode", Con_MessageMode_f);
+	Cmd_AddCommand ("messagemode2", Con_MessageMode2_f);
+	Cmd_AddCommand ("clear", Con_Clear_f);
+	con_initialized = true;
+}
+
+
+/*
+===============
+Con_Linefeed
+===============
+*/
+void Con_Linefeed (void)
+{
+	con_x = 0;
+	con_current++;
+	Q_memset (&con_text[(con_current%con_totallines)*con_linewidth]
+	, ' ', con_linewidth);
+}
+
+/*
+================
+Con_Print
+
+Handles cursor positioning, line wrapping, etc
+All console printing must go through this in order to be logged to disk
+If no console is visible, the notify window will pop up.
+================
+*/
+void Con_Print (char *txt)
+{
+	int		y;
+	int		c, l;
+	static int	cr;
+	int		mask;
+	
+	con_backscroll = 0;
+
+	if (txt[0] == 1)
+	{
+		mask = 128;		// go to colored text
+		S_LocalSound ("misc/talk.wav");
+	// play talk wav
+		txt++;
+	}
+	else if (txt[0] == 2)
+	{
+		mask = 128;		// go to colored text
+		txt++;
+	}
+	else
+		mask = 0;
+
+
+	while ( (c = *txt) )
+	{
+	// count word length
+		for (l=0 ; l< con_linewidth ; l++)
+			if ( txt[l] <= ' ')
+				break;
+
+	// word wrap
+		if (l != con_linewidth && (con_x + l > con_linewidth) )
+			con_x = 0;
+
+		txt++;
+
+		if (cr)
+		{
+			con_current--;
+			cr = false;
+		}
+
+		
+		if (!con_x)
+		{
+			Con_Linefeed ();
+		// mark time for transparent overlay
+			if (con_current >= 0)
+				con_times[con_current % NUM_CON_TIMES] = realtime;
+		}
+
+		switch (c)
+		{
+		case '\n':
+			con_x = 0;
+			break;
+
+		case '\r':
+			con_x = 0;
+			cr = 1;
+			break;
+
+		default:	// display character and advance
+			y = con_current % con_totallines;
+			con_text[y*con_linewidth+con_x] = c | mask;
+			con_x++;
+			if (con_x >= con_linewidth)
+				con_x = 0;
+			break;
+		}
+		
+	}
+}
+
+
+/*
+================
+Con_DebugLog
+================
+*/
+void Con_DebugLog(char *file, char *fmt, ...)
+{
+    va_list argptr; 
+    static char data[1024];
+    int fd;
+    
+    va_start(argptr, fmt);
+    vsprintf(data, fmt, argptr);
+    va_end(argptr);
+    fd = open(file, O_WRONLY | O_CREAT | O_APPEND, 0666);
+    write(fd, data, strlen(data));
+    close(fd);
+}
+
+
+/*
+================
+Con_Printf
+
+Handles cursor positioning, line wrapping, etc
+================
+*/
+#define	MAXPRINTMSG	4096
+// FIXME: make a buffer size safe vsprintf?
+void Con_Printf (char *fmt, ...)
+{
+	va_list		argptr;
+	char		msg[MAXPRINTMSG];
+	static qboolean	inupdate;
+	
+	va_start (argptr,fmt);
+	vsprintf (msg,fmt,argptr);
+	va_end (argptr);
+	
+// also echo to debugging console
+	Sys_Printf ("%s", msg);	// also echo to debugging console
+
+// log all messages to file
+	if (con_debuglog)
+		Con_DebugLog(va("%s/qconsole.log",com_gamedir), "%s", msg);
+
+	if (!con_initialized)
+		return;
+		
+	if (cls.state == ca_dedicated)
+		return;		// no graphics mode
+
+// write it to the scrollable buffer
+	Con_Print (msg);
+	
+// update the screen if the console is displayed
+	if (cls.signon != SIGNONS && !scr_disabled_for_loading )
+	{
+	// protect against infinite loop if something in SCR_UpdateScreen calls
+	// Con_Printd
+		if (!inupdate)
+		{
+			inupdate = true;
+			SCR_UpdateScreen ();
+			inupdate = false;
+		}
+	}
+}
+
+/*
+================
+Con_DPrintf
+
+A Con_Printf that only shows up if the "developer" cvar is set
+================
+*/
+void Con_DPrintf (char *fmt, ...)
+{
+	va_list		argptr;
+	char		msg[MAXPRINTMSG];
+		
+	if (!developer.value)
+		return;			// don't confuse non-developers with techie stuff...
+
+	va_start (argptr,fmt);
+	vsprintf (msg,fmt,argptr);
+	va_end (argptr);
+	
+	Con_Printf ("%s", msg);
+}
+
+
+/*
+==================
+Con_SafePrintf
+
+Okay to call even when the screen can't be updated
+==================
+*/
+void Con_SafePrintf (char *fmt, ...)
+{
+	va_list		argptr;
+	char		msg[1024];
+	int			temp;
+		
+	va_start (argptr,fmt);
+	vsprintf (msg,fmt,argptr);
+	va_end (argptr);
+
+	temp = scr_disabled_for_loading;
+	scr_disabled_for_loading = true;
+	Con_Printf ("%s", msg);
+	scr_disabled_for_loading = temp;
+}
+
+
+/*
+==============================================================================
+
+DRAWING
+
+==============================================================================
+*/
+
+
+/*
+================
+Con_DrawInput
+
+The input line scrolls horizontally if typing goes beyond the right edge
+================
+*/
+void Con_DrawInput (void)
+{
+	int		y;
+	int		i;
+	char	*text;
+
+	if (key_dest != key_console && !con_forcedup)
+		return;		// don't draw anything
+
+	text = key_lines[edit_line];
+	
+// add the cursor frame
+	text[key_linepos] = 10+((int)(realtime*con_cursorspeed)&1);
+	
+// fill out remainder with spaces
+	for (i=key_linepos+1 ; i< con_linewidth ; i++)
+		text[i] = ' ';
+		
+//	prestep if horizontally scrolling
+	if (key_linepos >= con_linewidth)
+		text += 1 + key_linepos - con_linewidth;
+		
+// draw it
+	y = con_vislines-16;
+
+	for (i=0 ; i<con_linewidth ; i++)
+		Draw_Character ( (i+1)<<3, con_vislines - 16, text[i]);
+
+// remove cursor
+	key_lines[edit_line][key_linepos] = 0;
+}
+
+
+/*
+================
+Con_DrawNotify
+
+Draws the last few lines of output transparently over the game top
+================
+*/
+void Con_DrawNotify (void)
+{
+	int		x, v;
+	char	*text;
+	int		i;
+	float	time;
+	extern char chat_buffer[];
+
+	v = 0;
+	for (i= con_current-NUM_CON_TIMES+1 ; i<=con_current ; i++)
+	{
+		if (i < 0)
+			continue;
+		time = con_times[i % NUM_CON_TIMES];
+		if (time == 0)
+			continue;
+		time = realtime - time;
+		if (time > con_notifytime.value)
+			continue;
+		text = con_text + (i % con_totallines)*con_linewidth;
+		
+		clearnotify = 0;
+		scr_copytop = 1;
+
+		for (x = 0 ; x < con_linewidth ; x++)
+			Draw_Character ( (x+1)<<3, v, text[x]);
+
+		v += 8;
+	}
+
+
+	if (key_dest == key_message)
+	{
+		clearnotify = 0;
+		scr_copytop = 1;
+	
+		x = 0;
+		
+		Draw_String (8, v, "say:");
+		while(chat_buffer[x])
+		{
+			Draw_Character ( (x+5)<<3, v, chat_buffer[x]);
+			x++;
+		}
+		Draw_Character ( (x+5)<<3, v, 10+((int)(realtime*con_cursorspeed)&1));
+		v += 8;
+	}
+	
+	if (v > con_notifylines)
+		con_notifylines = v;
+}
+
+/*
+================
+Con_DrawConsole
+
+Draws the console with the solid background
+The typing input line at the bottom should only be drawn if typing is allowed
+================
+*/
+void Con_DrawConsole (int lines, qboolean drawinput)
+{
+	int				i, x, y;
+	int				rows;
+	char			*text;
+	int				j;
+	
+	if (lines <= 0)
+		return;
+
+// draw the background
+	Draw_ConsoleBackground (lines);
+
+// draw the text
+	con_vislines = lines;
+
+	rows = (lines-16)>>3;		// rows of text to draw
+	y = lines - 16 - (rows<<3);	// may start slightly negative
+
+	for (i= con_current - rows + 1 ; i<=con_current ; i++, y+=8 )
+	{
+		j = i - con_backscroll;
+		if (j<0)
+			j = 0;
+		text = con_text + (j % con_totallines)*con_linewidth;
+
+		for (x=0 ; x<con_linewidth ; x++)
+			Draw_Character ( (x+1)<<3, y, text[x]);
+	}
+
+// draw the input prompt, user text, and cursor if desired
+	if (drawinput)
+		Con_DrawInput ();
+}
+
+
+/*
+==================
+Con_NotifyBox
+==================
+*/
+void Con_NotifyBox (char *text)
+{
+	double		t1, t2;
+
+// during startup for sound / cd warnings
+	Con_Printf("\n\n\35\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\37\n");
+
+	Con_Printf (text);
+
+	Con_Printf ("Press a key.\n");
+	Con_Printf("\35\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\37\n");
+
+	key_count = -2;		// wait for a key down and up
+	key_dest = key_console;
+
+	do
+	{
+		t1 = Sys_FloatTime ();
+		SCR_UpdateScreen ();
+		Sys_SendKeyEvents ();
+		t2 = Sys_FloatTime ();
+		realtime += t2-t1;		// make the cursor blink
+	} while (key_count < 0);
+
+	Con_Printf ("\n");
+	key_dest = key_game;
+	realtime = 0;				// put the cursor back to invisible
+}
+
--- /dev/null
+++ b/WinQuake/console.h
@@ -1,0 +1,46 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+
+//
+// console
+//
+extern int con_totallines;
+extern int con_backscroll;
+extern	qboolean con_forcedup;	// because no entities to refresh
+extern qboolean con_initialized;
+extern byte *con_chars;
+extern	int	con_notifylines;		// scan lines to clear for notify lines
+
+void Con_DrawCharacter (int cx, int line, int num);
+
+void Con_CheckResize (void);
+void Con_Init (void);
+void Con_DrawConsole (int lines, qboolean drawinput);
+void Con_Print (char *txt);
+void Con_Printf (char *fmt, ...);
+void Con_DPrintf (char *fmt, ...);
+void Con_SafePrintf (char *fmt, ...);
+void Con_Clear_f (void);
+void Con_DrawNotify (void);
+void Con_ClearNotify (void);
+void Con_ToggleConsole_f (void);
+
+void Con_NotifyBox (char *text);	// during startup for sound / cd warnings
+
--- /dev/null
+++ b/WinQuake/crc.c
@@ -1,0 +1,81 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+/* crc.c */
+
+#include "quakedef.h"
+#include "crc.h"
+
+// 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
+
+#define CRC_INIT_VALUE	0xffff
+#define CRC_XOR_VALUE	0x0000
+
+static unsigned short crctable[256] =
+{
+	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
+};
+
+void CRC_Init(unsigned short *crcvalue)
+{
+	*crcvalue = CRC_INIT_VALUE;
+}
+
+void CRC_ProcessByte(unsigned short *crcvalue, byte data)
+{
+	*crcvalue = (*crcvalue << 8) ^ crctable[(*crcvalue >> 8) ^ data];
+}
+
+unsigned short CRC_Value(unsigned short crcvalue)
+{
+	return crcvalue ^ CRC_XOR_VALUE;
+}
\ No newline at end of file
--- /dev/null
+++ b/WinQuake/crc.h
@@ -1,0 +1,24 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+/* crc.h */
+
+void CRC_Init(unsigned short *crcvalue);
+void CRC_ProcessByte(unsigned short *crcvalue, byte data);
+unsigned short CRC_Value(unsigned short crcvalue);
--- /dev/null
+++ b/WinQuake/cvar.c
@@ -1,0 +1,224 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// cvar.c -- dynamic variable tracking
+
+#include "quakedef.h"
+
+cvar_t	*cvar_vars;
+char	*cvar_null_string = "";
+
+/*
+============
+Cvar_FindVar
+============
+*/
+cvar_t *Cvar_FindVar (char *var_name)
+{
+	cvar_t	*var;
+	
+	for (var=cvar_vars ; var ; var=var->next)
+		if (!Q_strcmp (var_name, var->name))
+			return var;
+
+	return NULL;
+}
+
+/*
+============
+Cvar_VariableValue
+============
+*/
+float	Cvar_VariableValue (char *var_name)
+{
+	cvar_t	*var;
+	
+	var = Cvar_FindVar (var_name);
+	if (!var)
+		return 0;
+	return Q_atof (var->string);
+}
+
+
+/*
+============
+Cvar_VariableString
+============
+*/
+char *Cvar_VariableString (char *var_name)
+{
+	cvar_t *var;
+	
+	var = Cvar_FindVar (var_name);
+	if (!var)
+		return cvar_null_string;
+	return var->string;
+}
+
+
+/*
+============
+Cvar_CompleteVariable
+============
+*/
+char *Cvar_CompleteVariable (char *partial)
+{
+	cvar_t		*cvar;
+	int			len;
+	
+	len = Q_strlen(partial);
+	
+	if (!len)
+		return NULL;
+		
+// check functions
+	for (cvar=cvar_vars ; cvar ; cvar=cvar->next)
+		if (!Q_strncmp (partial,cvar->name, len))
+			return cvar->name;
+
+	return NULL;
+}
+
+
+/*
+============
+Cvar_Set
+============
+*/
+void Cvar_Set (char *var_name, char *value)
+{
+	cvar_t	*var;
+	qboolean changed;
+	
+	var = Cvar_FindVar (var_name);
+	if (!var)
+	{	// there is an error in C code if this happens
+		Con_Printf ("Cvar_Set: variable %s not found\n", var_name);
+		return;
+	}
+
+	changed = Q_strcmp(var->string, value);
+	
+	Z_Free (var->string);	// free the old value string
+	
+	var->string = Z_Malloc (Q_strlen(value)+1);
+	Q_strcpy (var->string, value);
+	var->value = Q_atof (var->string);
+	if (var->server && changed)
+	{
+		if (sv.active)
+			SV_BroadcastPrintf ("\"%s\" changed to \"%s\"\n", var->name, var->string);
+	}
+}
+
+/*
+============
+Cvar_SetValue
+============
+*/
+void Cvar_SetValue (char *var_name, float value)
+{
+	char	val[32];
+	
+	sprintf (val, "%f",value);
+	Cvar_Set (var_name, val);
+}
+
+
+/*
+============
+Cvar_RegisterVariable
+
+Adds a freestanding variable to the variable list.
+============
+*/
+void Cvar_RegisterVariable (cvar_t *variable)
+{
+	char	*oldstr;
+	
+// first check to see if it has allready been defined
+	if (Cvar_FindVar (variable->name))
+	{
+		Con_Printf ("Can't register variable %s, allready defined\n", variable->name);
+		return;
+	}
+	
+// check for overlap with a command
+	if (Cmd_Exists (variable->name))
+	{
+		Con_Printf ("Cvar_RegisterVariable: %s is a command\n", variable->name);
+		return;
+	}
+		
+// copy the value off, because future sets will Z_Free it
+	oldstr = variable->string;
+	variable->string = Z_Malloc (Q_strlen(variable->string)+1);	
+	Q_strcpy (variable->string, oldstr);
+	variable->value = Q_atof (variable->string);
+	
+// link the variable in
+	variable->next = cvar_vars;
+	cvar_vars = variable;
+}
+
+/*
+============
+Cvar_Command
+
+Handles variable inspection and changing from the console
+============
+*/
+qboolean	Cvar_Command (void)
+{
+	cvar_t			*v;
+
+// check variables
+	v = Cvar_FindVar (Cmd_Argv(0));
+	if (!v)
+		return false;
+		
+// perform a variable print or set
+	if (Cmd_Argc() == 1)
+	{
+		Con_Printf ("\"%s\" is \"%s\"\n", v->name, v->string);
+		return true;
+	}
+
+	Cvar_Set (v->name, Cmd_Argv(1));
+	return true;
+}
+
+
+/*
+============
+Cvar_WriteVariables
+
+Writes lines containing "set variable value" for all variables
+with the archive flag set to true.
+============
+*/
+void Cvar_WriteVariables (FILE *f)
+{
+	cvar_t	*var;
+	
+	for (var = cvar_vars ; var ; var = var->next)
+		if (var->archive)
+			fprintf (f, "%s \"%s\"\n", var->name, var->string);
+}
+
--- /dev/null
+++ b/WinQuake/cvar.h
@@ -1,0 +1,97 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// cvar.h
+
+/*
+
+cvar_t variables are used to hold scalar or string variables that can be changed or displayed at the console or prog code as well as accessed directly
+in C code.
+
+it is sufficient to initialize a cvar_t with just the first two fields, or
+you can add a ,true flag for variables that you want saved to the configuration
+file when the game is quit:
+
+cvar_t	r_draworder = {"r_draworder","1"};
+cvar_t	scr_screensize = {"screensize","1",true};
+
+Cvars must be registered before use, or they will have a 0 value instead of the float interpretation of the string.  Generally, all cvar_t declarations should be registered in the apropriate init function before any console commands are executed:
+Cvar_RegisterVariable (&host_framerate);
+
+
+C code usually just references a cvar in place:
+if ( r_draworder.value )
+
+It could optionally ask for the value to be looked up for a string name:
+if (Cvar_VariableValue ("r_draworder"))
+
+Interpreted prog code can access cvars with the cvar(name) or
+cvar_set (name, value) internal functions:
+teamplay = cvar("teamplay");
+cvar_set ("registered", "1");
+
+The user can access cvars from the console in two ways:
+r_draworder			prints the current value
+r_draworder 0		sets the current value to 0
+Cvars are restricted from having the same names as commands to keep this
+interface from being ambiguous.
+*/
+
+typedef struct cvar_s
+{
+	char	*name;
+	char	*string;
+	qboolean archive;		// set to true to cause it to be saved to vars.rc
+	qboolean server;		// notifies players when changed
+	float	value;
+	struct cvar_s *next;
+} cvar_t;
+
+void 	Cvar_RegisterVariable (cvar_t *variable);
+// registers a cvar that allready has the name, string, and optionally the
+// archive elements set.
+
+void 	Cvar_Set (char *var_name, char *value);
+// equivelant to "<name> <variable>" typed at the console
+
+void	Cvar_SetValue (char *var_name, float value);
+// expands value to a string and calls Cvar_Set
+
+float	Cvar_VariableValue (char *var_name);
+// returns 0 if not defined or non numeric
+
+char	*Cvar_VariableString (char *var_name);
+// returns an empty string if not defined
+
+char 	*Cvar_CompleteVariable (char *partial);
+// attempts to match a partial variable name for command line completion
+// returns NULL if nothing fits
+
+qboolean Cvar_Command (void);
+// called by Cmd_ExecuteString when Cmd_Argv(0) doesn't match a known
+// command.  Returns true if the command was a variable reference that
+// was handled. (print or change)
+
+void 	Cvar_WriteVariables (FILE *f);
+// Writes lines containing "set variable value" for all variables
+// with the archive flag set to true.
+
+cvar_t *Cvar_FindVar (char *var_name);
+
+extern cvar_t	*cvar_vars;
binary files /dev/null b/WinQuake/cwsdpmi.exe differ
--- /dev/null
+++ b/WinQuake/d_copy.s
@@ -1,0 +1,149 @@
+//
+// d_copy.s
+// x86 assembly-language screen copying code.
+//
+
+#include "asm_i386.h"
+#include "quakeasm.h"
+#include "asm_draw.h"
+
+	.data
+
+LCopyWidth:		.long	0
+LBlockSrcStep:	.long	0
+LBlockDestStep:	.long	0
+LSrcDelta:		.long	0
+LDestDelta:		.long	0
+
+#define bufptr	4+16
+
+// copies 16 rows per plane at a pop; idea is that 16*512 = 8k, and since
+// no Mode X mode is wider than 360, all the data should fit in the cache for
+// the passes for the next 3 planes
+
+	.text
+
+.globl C(VGA_UpdatePlanarScreen)
+C(VGA_UpdatePlanarScreen):
+	pushl	%ebp				// preserve caller's stack frame
+	pushl	%edi
+	pushl	%esi				// preserve register variables
+	pushl	%ebx
+
+	movl	C(VGA_bufferrowbytes),%eax
+	shll	$1,%eax
+	movl	%eax,LBlockSrcStep
+	movl	C(VGA_rowbytes),%eax
+	shll	$1,%eax
+	movl	%eax,LBlockDestStep
+
+	movl	$0x3C4,%edx
+	movb	$2,%al
+	outb	%al,%dx		// point the SC to the Map Mask
+	incl	%edx
+
+	movl	bufptr(%esp),%esi
+	movl	C(VGA_pagebase),%edi
+	movl	C(VGA_height),%ebp
+	shrl	$1,%ebp
+
+	movl	C(VGA_width),%ecx
+	movl	C(VGA_bufferrowbytes),%eax
+	subl	%ecx,%eax
+	movl	%eax,LSrcDelta
+	movl	C(VGA_rowbytes),%eax
+	shll	$2,%eax
+	subl	%ecx,%eax
+	movl	%eax,LDestDelta
+	shrl	$4,%ecx
+	movl	%ecx,LCopyWidth
+
+LRowLoop:
+	movb	$1,%al
+
+LPlaneLoop:
+	outb	%al,%dx
+	movb	$2,%ah
+
+	pushl	%esi
+	pushl	%edi
+LRowSetLoop:
+	movl	LCopyWidth,%ecx
+LColumnLoop:
+	movb	12(%esi),%bh
+	movb	8(%esi),%bl
+	shll	$16,%ebx
+	movb	4(%esi),%bh
+	movb	(%esi),%bl
+	movl	%ebx,(%edi)
+	addl	$16,%esi
+	addl	$4,%edi
+	decl	%ecx
+	jnz		LColumnLoop
+
+	addl	LDestDelta,%edi
+	addl	LSrcDelta,%esi
+	decb	%ah
+	jnz		LRowSetLoop
+
+	popl	%edi
+	popl	%esi
+	incl	%esi
+
+	shlb	$1,%al
+	cmpb	$16,%al
+	jnz		LPlaneLoop
+
+	subl	$4,%esi
+	addl	LBlockSrcStep,%esi
+	addl	LBlockDestStep,%edi
+	decl	%ebp
+	jnz		LRowLoop
+
+	popl	%ebx				// restore register variables
+	popl	%esi
+	popl	%edi
+	popl	%ebp				// restore the caller's stack frame
+
+	ret
+
+
+#define srcptr			4+16
+#define destptr			8+16
+#define width			12+16
+#define height			16+16
+#define srcrowbytes		20+16
+#define destrowbytes	24+16
+
+.globl C(VGA_UpdateLinearScreen)
+C(VGA_UpdateLinearScreen):
+	pushl	%ebp				// preserve caller's stack frame
+	pushl	%edi
+	pushl	%esi				// preserve register variables
+	pushl	%ebx
+
+	cld
+	movl	srcptr(%esp),%esi
+	movl	destptr(%esp),%edi
+	movl	width(%esp),%ebx
+	movl	srcrowbytes(%esp),%eax
+	subl	%ebx,%eax
+	movl	destrowbytes(%esp),%edx
+	subl	%ebx,%edx
+	shrl	$2,%ebx
+	movl	height(%esp),%ebp
+LLRowLoop:
+	movl	%ebx,%ecx
+	rep/movsl	(%esi),(%edi)
+	addl	%eax,%esi
+	addl	%edx,%edi
+	decl	%ebp
+	jnz		LLRowLoop
+
+	popl	%ebx				// restore register variables
+	popl	%esi
+	popl	%edi
+	popl	%ebp				// restore the caller's stack frame
+
+	ret
+
--- /dev/null
+++ b/WinQuake/d_draw.s
@@ -1,0 +1,1037 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+//
+// d_draw.s
+// x86 assembly-language horizontal 8-bpp span-drawing code.
+//
+
+#include "asm_i386.h"
+#include "quakeasm.h"
+#include "asm_draw.h"
+#include "d_ifacea.h"
+
+#if	id386
+
+//----------------------------------------------------------------------
+// 8-bpp horizontal span drawing code for polygons, with no transparency.
+//
+// Assumes there is at least one span in pspans, and that every span
+// contains at least one pixel
+//----------------------------------------------------------------------
+
+	.text
+
+// out-of-line, rarely-needed clamping code
+
+LClampHigh0:
+	movl	C(bbextents),%esi
+	jmp		LClampReentry0
+LClampHighOrLow0:
+	jg		LClampHigh0
+	xorl	%esi,%esi
+	jmp		LClampReentry0
+
+LClampHigh1:
+	movl	C(bbextentt),%edx
+	jmp		LClampReentry1
+LClampHighOrLow1:
+	jg		LClampHigh1
+	xorl	%edx,%edx
+	jmp		LClampReentry1
+
+LClampLow2:
+	movl	$2048,%ebp
+	jmp		LClampReentry2
+LClampHigh2:
+	movl	C(bbextents),%ebp
+	jmp		LClampReentry2
+
+LClampLow3:
+	movl	$2048,%ecx
+	jmp		LClampReentry3
+LClampHigh3:
+	movl	C(bbextentt),%ecx
+	jmp		LClampReentry3
+
+LClampLow4:
+	movl	$2048,%eax
+	jmp		LClampReentry4
+LClampHigh4:
+	movl	C(bbextents),%eax
+	jmp		LClampReentry4
+
+LClampLow5:
+	movl	$2048,%ebx
+	jmp		LClampReentry5
+LClampHigh5:
+	movl	C(bbextentt),%ebx
+	jmp		LClampReentry5
+
+
+#define pspans	4+16
+
+	.align 4
+.globl C(D_DrawSpans8)
+C(D_DrawSpans8):
+	pushl	%ebp				// preserve caller's stack frame
+	pushl	%edi
+	pushl	%esi				// preserve register variables
+	pushl	%ebx
+
+//
+// set up scaled-by-8 steps, for 8-long segments; also set up cacheblock
+// and span list pointers
+//
+// TODO: any overlap from rearranging?
+	flds	C(d_sdivzstepu)
+	fmuls	fp_8
+	movl	C(cacheblock),%edx
+	flds	C(d_tdivzstepu)
+	fmuls	fp_8
+	movl	pspans(%esp),%ebx	// point to the first span descriptor
+	flds	C(d_zistepu)
+	fmuls	fp_8
+	movl	%edx,pbase			// pbase = cacheblock
+	fstps	zi8stepu
+	fstps	tdivz8stepu
+	fstps	sdivz8stepu
+
+LSpanLoop:
+//
+// set up the initial s/z, t/z, and 1/z on the FP stack, and generate the
+// initial s and t values
+//
+// FIXME: pipeline FILD?
+	fildl	espan_t_v(%ebx)
+	fildl	espan_t_u(%ebx)
+
+	fld		%st(1)			// dv | du | dv
+	fmuls	C(d_sdivzstepv)	// dv*d_sdivzstepv | du | dv
+	fld		%st(1)			// du | dv*d_sdivzstepv | du | dv
+	fmuls	C(d_sdivzstepu)	// du*d_sdivzstepu | dv*d_sdivzstepv | du | dv
+	fld		%st(2)			// du | du*d_sdivzstepu | dv*d_sdivzstepv | du | dv
+	fmuls	C(d_tdivzstepu)	// du*d_tdivzstepu | du*d_sdivzstepu |
+							//  dv*d_sdivzstepv | du | dv
+	fxch	%st(1)			// du*d_sdivzstepu | du*d_tdivzstepu |
+							//  dv*d_sdivzstepv | du | dv
+	faddp	%st(0),%st(2)	// du*d_tdivzstepu |
+							//  du*d_sdivzstepu + dv*d_sdivzstepv | du | dv
+	fxch	%st(1)			// du*d_sdivzstepu + dv*d_sdivzstepv |
+							//  du*d_tdivzstepu | du | dv
+	fld		%st(3)			// dv | du*d_sdivzstepu + dv*d_sdivzstepv |
+							//  du*d_tdivzstepu | du | dv
+	fmuls	C(d_tdivzstepv)	// dv*d_tdivzstepv |
+							//  du*d_sdivzstepu + dv*d_sdivzstepv |
+							//  du*d_tdivzstepu | du | dv
+	fxch	%st(1)			// du*d_sdivzstepu + dv*d_sdivzstepv |
+							//  dv*d_tdivzstepv | du*d_tdivzstepu | du | dv
+	fadds	C(d_sdivzorigin)	// sdivz = d_sdivzorigin + dv*d_sdivzstepv +
+							//  du*d_sdivzstepu; stays in %st(2) at end
+	fxch	%st(4)			// dv | dv*d_tdivzstepv | du*d_tdivzstepu | du |
+							//  s/z
+	fmuls	C(d_zistepv)		// dv*d_zistepv | dv*d_tdivzstepv |
+							//  du*d_tdivzstepu | du | s/z
+	fxch	%st(1)			// dv*d_tdivzstepv |  dv*d_zistepv |
+							//  du*d_tdivzstepu | du | s/z
+	faddp	%st(0),%st(2)	// dv*d_zistepv |
+							//  dv*d_tdivzstepv + du*d_tdivzstepu | du | s/z
+	fxch	%st(2)			// du | dv*d_tdivzstepv + du*d_tdivzstepu |
+							//  dv*d_zistepv | s/z
+	fmuls	C(d_zistepu)		// du*d_zistepu |
+							//  dv*d_tdivzstepv + du*d_tdivzstepu |
+							//  dv*d_zistepv | s/z
+	fxch	%st(1)			// dv*d_tdivzstepv + du*d_tdivzstepu |
+							//  du*d_zistepu | dv*d_zistepv | s/z
+	fadds	C(d_tdivzorigin)	// tdivz = d_tdivzorigin + dv*d_tdivzstepv +
+							//  du*d_tdivzstepu; stays in %st(1) at end
+	fxch	%st(2)			// dv*d_zistepv | du*d_zistepu | t/z | s/z
+	faddp	%st(0),%st(1)	// dv*d_zistepv + du*d_zistepu | t/z | s/z
+
+	flds	fp_64k			// fp_64k | dv*d_zistepv + du*d_zistepu | t/z | s/z
+	fxch	%st(1)			// dv*d_zistepv + du*d_zistepu | fp_64k | t/z | s/z
+	fadds	C(d_ziorigin)		// zi = d_ziorigin + dv*d_zistepv +
+							//  du*d_zistepu; stays in %st(0) at end
+							// 1/z | fp_64k | t/z | s/z
+//
+// calculate and clamp s & t
+//
+	fdivr	%st(0),%st(1)	// 1/z | z*64k | t/z | s/z
+
+//
+// point %edi to the first pixel in the span
+//
+	movl	C(d_viewbuffer),%ecx
+	movl	espan_t_v(%ebx),%eax
+	movl	%ebx,pspantemp	// preserve spans pointer
+
+	movl	C(tadjust),%edx
+	movl	C(sadjust),%esi
+	movl	C(d_scantable)(,%eax,4),%edi	// v * screenwidth
+	addl	%ecx,%edi
+	movl	espan_t_u(%ebx),%ecx
+	addl	%ecx,%edi				// pdest = &pdestspan[scans->u];
+	movl	espan_t_count(%ebx),%ecx
+
+//
+// now start the FDIV for the end of the span
+//
+	cmpl	$8,%ecx
+	ja		LSetupNotLast1
+
+	decl	%ecx
+	jz		LCleanup1		// if only one pixel, no need to start an FDIV
+	movl	%ecx,spancountminus1
+
+// finish up the s and t calcs
+	fxch	%st(1)			// z*64k | 1/z | t/z | s/z
+
+	fld		%st(0)			// z*64k | z*64k | 1/z | t/z | s/z
+	fmul	%st(4),%st(0)	// s | z*64k | 1/z | t/z | s/z
+	fxch	%st(1)			// z*64k | s | 1/z | t/z | s/z
+	fmul	%st(3),%st(0)	// t | s | 1/z | t/z | s/z
+	fxch	%st(1)			// s | t | 1/z | t/z | s/z
+	fistpl	s				// 1/z | t | t/z | s/z
+	fistpl	t				// 1/z | t/z | s/z
+
+	fildl	spancountminus1
+
+	flds	C(d_tdivzstepu)	// C(d_tdivzstepu) | spancountminus1
+	flds	C(d_zistepu)		// C(d_zistepu) | C(d_tdivzstepu) | spancountminus1
+	fmul	%st(2),%st(0)	// C(d_zistepu)*scm1 | C(d_tdivzstepu) | scm1
+	fxch	%st(1)			// C(d_tdivzstepu) | C(d_zistepu)*scm1 | scm1
+	fmul	%st(2),%st(0)	// C(d_tdivzstepu)*scm1 | C(d_zistepu)*scm1 | scm1
+	fxch	%st(2)			// scm1 | C(d_zistepu)*scm1 | C(d_tdivzstepu)*scm1
+	fmuls	C(d_sdivzstepu)	// C(d_sdivzstepu)*scm1 | C(d_zistepu)*scm1 |
+							//  C(d_tdivzstepu)*scm1
+	fxch	%st(1)			// C(d_zistepu)*scm1 | C(d_sdivzstepu)*scm1 |
+							//  C(d_tdivzstepu)*scm1
+	faddp	%st(0),%st(3)	// C(d_sdivzstepu)*scm1 | C(d_tdivzstepu)*scm1
+	fxch	%st(1)			// C(d_tdivzstepu)*scm1 | C(d_sdivzstepu)*scm1
+	faddp	%st(0),%st(3)	// C(d_sdivzstepu)*scm1
+	faddp	%st(0),%st(3)
+
+	flds	fp_64k
+	fdiv	%st(1),%st(0)	// this is what we've gone to all this trouble to
+							//  overlap
+	jmp		LFDIVInFlight1
+
+LCleanup1:
+// finish up the s and t calcs
+	fxch	%st(1)			// z*64k | 1/z | t/z | s/z
+
+	fld		%st(0)			// z*64k | z*64k | 1/z | t/z | s/z
+	fmul	%st(4),%st(0)	// s | z*64k | 1/z | t/z | s/z
+	fxch	%st(1)			// z*64k | s | 1/z | t/z | s/z
+	fmul	%st(3),%st(0)	// t | s | 1/z | t/z | s/z
+	fxch	%st(1)			// s | t | 1/z | t/z | s/z
+	fistpl	s				// 1/z | t | t/z | s/z
+	fistpl	t				// 1/z | t/z | s/z
+	jmp		LFDIVInFlight1
+
+	.align	4
+LSetupNotLast1:
+// finish up the s and t calcs
+	fxch	%st(1)			// z*64k | 1/z | t/z | s/z
+
+	fld		%st(0)			// z*64k | z*64k | 1/z | t/z | s/z
+	fmul	%st(4),%st(0)	// s | z*64k | 1/z | t/z | s/z
+	fxch	%st(1)			// z*64k | s | 1/z | t/z | s/z
+	fmul	%st(3),%st(0)	// t | s | 1/z | t/z | s/z
+	fxch	%st(1)			// s | t | 1/z | t/z | s/z
+	fistpl	s				// 1/z | t | t/z | s/z
+	fistpl	t				// 1/z | t/z | s/z
+
+	fadds	zi8stepu
+	fxch	%st(2)
+	fadds	sdivz8stepu
+	fxch	%st(2)
+	flds	tdivz8stepu
+	faddp	%st(0),%st(2)
+	flds	fp_64k
+	fdiv	%st(1),%st(0)	// z = 1/1/z
+							// this is what we've gone to all this trouble to
+							//  overlap
+LFDIVInFlight1:
+
+	addl	s,%esi
+	addl	t,%edx
+	movl	C(bbextents),%ebx
+	movl	C(bbextentt),%ebp
+	cmpl	%ebx,%esi
+	ja		LClampHighOrLow0
+LClampReentry0:
+	movl	%esi,s
+	movl	pbase,%ebx
+	shll	$16,%esi
+	cmpl	%ebp,%edx
+	movl	%esi,sfracf
+	ja		LClampHighOrLow1
+LClampReentry1:
+	movl	%edx,t
+	movl	s,%esi					// sfrac = scans->sfrac;
+	shll	$16,%edx
+	movl	t,%eax					// tfrac = scans->tfrac;
+	sarl	$16,%esi
+	movl	%edx,tfracf
+
+//
+// calculate the texture starting address
+//
+	sarl	$16,%eax
+	movl	C(cachewidth),%edx
+	imull	%edx,%eax				// (tfrac >> 16) * cachewidth
+	addl	%ebx,%esi
+	addl	%eax,%esi				// psource = pbase + (sfrac >> 16) +
+									//           ((tfrac >> 16) * cachewidth);
+
+//
+// determine whether last span or not
+//
+	cmpl	$8,%ecx
+	jna		LLastSegment
+
+//
+// not the last segment; do full 8-wide segment
+//
+LNotLastSegment:
+
+//
+// advance s/z, t/z, and 1/z, and calculate s & t at end of span and steps to
+// get there
+//
+
+// pick up after the FDIV that was left in flight previously
+
+	fld		%st(0)			// duplicate it
+	fmul	%st(4),%st(0)	// s = s/z * z
+	fxch	%st(1)
+	fmul	%st(3),%st(0)	// t = t/z * z
+	fxch	%st(1)
+	fistpl	snext
+	fistpl	tnext
+	movl	snext,%eax
+	movl	tnext,%edx
+
+	movb	(%esi),%bl	// get first source texel
+	subl	$8,%ecx		// count off this segments' pixels
+	movl	C(sadjust),%ebp
+	movl	%ecx,counttemp	// remember count of remaining pixels
+
+	movl	C(tadjust),%ecx
+	movb	%bl,(%edi)	// store first dest pixel
+
+	addl	%eax,%ebp
+	addl	%edx,%ecx
+
+	movl	C(bbextents),%eax
+	movl	C(bbextentt),%edx
+
+	cmpl	$2048,%ebp
+	jl		LClampLow2
+	cmpl	%eax,%ebp
+	ja		LClampHigh2
+LClampReentry2:
+
+	cmpl	$2048,%ecx
+	jl		LClampLow3
+	cmpl	%edx,%ecx
+	ja		LClampHigh3
+LClampReentry3:
+
+	movl	%ebp,snext
+	movl	%ecx,tnext
+
+	subl	s,%ebp
+	subl	t,%ecx
+	
+//
+// set up advancetable
+//
+	movl	%ecx,%eax
+	movl	%ebp,%edx
+	sarl	$19,%eax			// tstep >>= 16;
+	jz		LZero
+	sarl	$19,%edx			// sstep >>= 16;
+	movl	C(cachewidth),%ebx
+	imull	%ebx,%eax
+	jmp		LSetUp1
+
+LZero:
+	sarl	$19,%edx			// sstep >>= 16;
+	movl	C(cachewidth),%ebx
+
+LSetUp1:
+
+	addl	%edx,%eax			// add in sstep
+								// (tstep >> 16) * cachewidth + (sstep >> 16);
+	movl	tfracf,%edx
+	movl	%eax,advancetable+4	// advance base in t
+	addl	%ebx,%eax			// ((tstep >> 16) + 1) * cachewidth +
+								//  (sstep >> 16);
+	shll	$13,%ebp			// left-justify sstep fractional part
+	movl	sfracf,%ebx
+	shll	$13,%ecx			// left-justify tstep fractional part
+	movl	%eax,advancetable	// advance extra in t
+
+	movl	%ecx,tstep
+	addl	%ecx,%edx			// advance tfrac fractional part by tstep frac
+
+	sbbl	%ecx,%ecx			// turn tstep carry into -1 (0 if none)
+	addl	%ebp,%ebx			// advance sfrac fractional part by sstep frac
+	adcl	advancetable+4(,%ecx,4),%esi	// point to next source texel
+
+	addl	tstep,%edx
+	sbbl	%ecx,%ecx
+	movb	(%esi),%al
+	addl	%ebp,%ebx
+	movb	%al,1(%edi)
+	adcl	advancetable+4(,%ecx,4),%esi
+
+	addl	tstep,%edx
+	sbbl	%ecx,%ecx
+	addl	%ebp,%ebx
+	movb	(%esi),%al
+	adcl	advancetable+4(,%ecx,4),%esi
+
+	addl	tstep,%edx
+	sbbl	%ecx,%ecx
+	movb	%al,2(%edi)
+	addl	%ebp,%ebx
+	movb	(%esi),%al
+	adcl	advancetable+4(,%ecx,4),%esi
+
+	addl	tstep,%edx
+	sbbl	%ecx,%ecx
+	movb	%al,3(%edi)
+	addl	%ebp,%ebx
+	movb	(%esi),%al
+	adcl	advancetable+4(,%ecx,4),%esi
+
+
+//
+// start FDIV for end of next segment in flight, so it can overlap
+//
+	movl	counttemp,%ecx
+	cmpl	$8,%ecx			// more than one segment after this?
+	ja		LSetupNotLast2	// yes
+
+	decl	%ecx
+	jz		LFDIVInFlight2	// if only one pixel, no need to start an FDIV
+	movl	%ecx,spancountminus1
+	fildl	spancountminus1
+
+	flds	C(d_zistepu)		// C(d_zistepu) | spancountminus1
+	fmul	%st(1),%st(0)	// C(d_zistepu)*scm1 | scm1
+	flds	C(d_tdivzstepu)	// C(d_tdivzstepu) | C(d_zistepu)*scm1 | scm1
+	fmul	%st(2),%st(0)	// C(d_tdivzstepu)*scm1 | C(d_zistepu)*scm1 | scm1
+	fxch	%st(1)			// C(d_zistepu)*scm1 | C(d_tdivzstepu)*scm1 | scm1
+	faddp	%st(0),%st(3)	// C(d_tdivzstepu)*scm1 | scm1
+	fxch	%st(1)			// scm1 | C(d_tdivzstepu)*scm1
+	fmuls	C(d_sdivzstepu)	// C(d_sdivzstepu)*scm1 | C(d_tdivzstepu)*scm1
+	fxch	%st(1)			// C(d_tdivzstepu)*scm1 | C(d_sdivzstepu)*scm1
+	faddp	%st(0),%st(3)	// C(d_sdivzstepu)*scm1
+	flds	fp_64k			// 64k | C(d_sdivzstepu)*scm1
+	fxch	%st(1)			// C(d_sdivzstepu)*scm1 | 64k
+	faddp	%st(0),%st(4)	// 64k
+
+	fdiv	%st(1),%st(0)	// this is what we've gone to all this trouble to
+							//  overlap
+	jmp		LFDIVInFlight2
+
+	.align	4
+LSetupNotLast2:
+	fadds	zi8stepu
+	fxch	%st(2)
+	fadds	sdivz8stepu
+	fxch	%st(2)
+	flds	tdivz8stepu
+	faddp	%st(0),%st(2)
+	flds	fp_64k
+	fdiv	%st(1),%st(0)	// z = 1/1/z
+							// this is what we've gone to all this trouble to
+							//  overlap
+LFDIVInFlight2:
+	movl	%ecx,counttemp
+
+	addl	tstep,%edx
+	sbbl	%ecx,%ecx
+	movb	%al,4(%edi)
+	addl	%ebp,%ebx
+	movb	(%esi),%al
+	adcl	advancetable+4(,%ecx,4),%esi
+
+	addl	tstep,%edx
+	sbbl	%ecx,%ecx
+	movb	%al,5(%edi)
+	addl	%ebp,%ebx
+	movb	(%esi),%al
+	adcl	advancetable+4(,%ecx,4),%esi
+
+	addl	tstep,%edx
+	sbbl	%ecx,%ecx
+	movb	%al,6(%edi)
+	addl	%ebp,%ebx
+	movb	(%esi),%al
+	adcl	advancetable+4(,%ecx,4),%esi
+
+	addl	$8,%edi
+	movl	%edx,tfracf
+	movl	snext,%edx
+	movl	%ebx,sfracf
+	movl	tnext,%ebx
+	movl	%edx,s
+	movl	%ebx,t
+
+	movl	counttemp,%ecx		// retrieve count
+
+//
+// determine whether last span or not
+//
+	cmpl	$8,%ecx				// are there multiple segments remaining?
+	movb	%al,-1(%edi)
+	ja		LNotLastSegment		// yes
+
+//
+// last segment of scan
+//
+LLastSegment:
+
+//
+// advance s/z, t/z, and 1/z, and calculate s & t at end of span and steps to
+// get there. The number of pixels left is variable, and we want to land on the
+// last pixel, not step one past it, so we can't run into arithmetic problems
+//
+	testl	%ecx,%ecx
+	jz		LNoSteps		// just draw the last pixel and we're done
+
+// pick up after the FDIV that was left in flight previously
+
+
+	fld		%st(0)			// duplicate it
+	fmul	%st(4),%st(0)	// s = s/z * z
+	fxch	%st(1)
+	fmul	%st(3),%st(0)	// t = t/z * z
+	fxch	%st(1)
+	fistpl	snext
+	fistpl	tnext
+
+	movb	(%esi),%al		// load first texel in segment
+	movl	C(tadjust),%ebx
+	movb	%al,(%edi)		// store first pixel in segment
+	movl	C(sadjust),%eax
+
+	addl	snext,%eax
+	addl	tnext,%ebx
+
+	movl	C(bbextents),%ebp
+	movl	C(bbextentt),%edx
+
+	cmpl	$2048,%eax
+	jl		LClampLow4
+	cmpl	%ebp,%eax
+	ja		LClampHigh4
+LClampReentry4:
+	movl	%eax,snext
+
+	cmpl	$2048,%ebx
+	jl		LClampLow5
+	cmpl	%edx,%ebx
+	ja		LClampHigh5
+LClampReentry5:
+
+	cmpl	$1,%ecx			// don't bother 
+	je		LOnlyOneStep	// if two pixels in segment, there's only one step,
+							//  of the segment length
+	subl	s,%eax
+	subl	t,%ebx
+
+	addl	%eax,%eax		// convert to 15.17 format so multiply by 1.31
+	addl	%ebx,%ebx		//  reciprocal yields 16.48
+
+	imull	reciprocal_table-8(,%ecx,4) // sstep = (snext - s) / (spancount-1)
+	movl	%edx,%ebp
+
+	movl	%ebx,%eax
+	imull	reciprocal_table-8(,%ecx,4) // tstep = (tnext - t) / (spancount-1)
+
+LSetEntryvec:
+//
+// set up advancetable
+//
+	movl	entryvec_table(,%ecx,4),%ebx
+	movl	%edx,%eax
+	movl	%ebx,jumptemp		// entry point into code for RET later
+	movl	%ebp,%ecx
+	sarl	$16,%edx			// tstep >>= 16;
+	movl	C(cachewidth),%ebx
+	sarl	$16,%ecx			// sstep >>= 16;
+	imull	%ebx,%edx
+
+	addl	%ecx,%edx			// add in sstep
+								// (tstep >> 16) * cachewidth + (sstep >> 16);
+	movl	tfracf,%ecx
+	movl	%edx,advancetable+4	// advance base in t
+	addl	%ebx,%edx			// ((tstep >> 16) + 1) * cachewidth +
+								//  (sstep >> 16);
+	shll	$16,%ebp			// left-justify sstep fractional part
+	movl	sfracf,%ebx
+	shll	$16,%eax			// left-justify tstep fractional part
+	movl	%edx,advancetable	// advance extra in t
+
+	movl	%eax,tstep
+	movl	%ecx,%edx
+	addl	%eax,%edx
+	sbbl	%ecx,%ecx
+	addl	%ebp,%ebx
+	adcl	advancetable+4(,%ecx,4),%esi
+
+	jmp		*jumptemp			// jump to the number-of-pixels handler
+
+//----------------------------------------
+
+LNoSteps:
+	movb	(%esi),%al		// load first texel in segment
+	subl	$7,%edi			// adjust for hardwired offset
+	jmp		LEndSpan
+
+
+LOnlyOneStep:
+	subl	s,%eax
+	subl	t,%ebx
+	movl	%eax,%ebp
+	movl	%ebx,%edx
+	jmp		LSetEntryvec
+
+//----------------------------------------
+
+.globl	Entry2_8
+Entry2_8:
+	subl	$6,%edi		// adjust for hardwired offsets
+	movb	(%esi),%al
+	jmp		LLEntry2_8
+
+//----------------------------------------
+
+.globl	Entry3_8
+Entry3_8:
+	subl	$5,%edi		// adjust for hardwired offsets
+	addl	%eax,%edx
+	movb	(%esi),%al
+	sbbl	%ecx,%ecx
+	addl	%ebp,%ebx
+	adcl	advancetable+4(,%ecx,4),%esi
+	jmp		LLEntry3_8
+
+//----------------------------------------
+
+.globl	Entry4_8
+Entry4_8:
+	subl	$4,%edi		// adjust for hardwired offsets
+	addl	%eax,%edx
+	movb	(%esi),%al
+	sbbl	%ecx,%ecx
+	addl	%ebp,%ebx
+	adcl	advancetable+4(,%ecx,4),%esi
+	addl	tstep,%edx
+	jmp		LLEntry4_8
+
+//----------------------------------------
+
+.globl	Entry5_8
+Entry5_8:
+	subl	$3,%edi		// adjust for hardwired offsets
+	addl	%eax,%edx
+	movb	(%esi),%al
+	sbbl	%ecx,%ecx
+	addl	%ebp,%ebx
+	adcl	advancetable+4(,%ecx,4),%esi
+	addl	tstep,%edx
+	jmp		LLEntry5_8
+
+//----------------------------------------
+
+.globl	Entry6_8
+Entry6_8:
+	subl	$2,%edi		// adjust for hardwired offsets
+	addl	%eax,%edx
+	movb	(%esi),%al
+	sbbl	%ecx,%ecx
+	addl	%ebp,%ebx
+	adcl	advancetable+4(,%ecx,4),%esi
+	addl	tstep,%edx
+	jmp		LLEntry6_8
+
+//----------------------------------------
+
+.globl	Entry7_8
+Entry7_8:
+	decl	%edi		// adjust for hardwired offsets
+	addl	%eax,%edx
+	movb	(%esi),%al
+	sbbl	%ecx,%ecx
+	addl	%ebp,%ebx
+	adcl	advancetable+4(,%ecx,4),%esi
+	addl	tstep,%edx
+	jmp		LLEntry7_8
+
+//----------------------------------------
+
+.globl	Entry8_8
+Entry8_8:
+	addl	%eax,%edx
+	movb	(%esi),%al
+	sbbl	%ecx,%ecx
+	addl	%ebp,%ebx
+	adcl	advancetable+4(,%ecx,4),%esi
+
+	addl	tstep,%edx
+	sbbl	%ecx,%ecx
+	movb	%al,1(%edi)
+	addl	%ebp,%ebx
+	movb	(%esi),%al
+	adcl	advancetable+4(,%ecx,4),%esi
+	addl	tstep,%edx
+LLEntry7_8:
+	sbbl	%ecx,%ecx
+	movb	%al,2(%edi)
+	addl	%ebp,%ebx
+	movb	(%esi),%al
+	adcl	advancetable+4(,%ecx,4),%esi
+	addl	tstep,%edx
+LLEntry6_8:
+	sbbl	%ecx,%ecx
+	movb	%al,3(%edi)
+	addl	%ebp,%ebx
+	movb	(%esi),%al
+	adcl	advancetable+4(,%ecx,4),%esi
+	addl	tstep,%edx
+LLEntry5_8:
+	sbbl	%ecx,%ecx
+	movb	%al,4(%edi)
+	addl	%ebp,%ebx
+	movb	(%esi),%al
+	adcl	advancetable+4(,%ecx,4),%esi
+	addl	tstep,%edx
+LLEntry4_8:
+	sbbl	%ecx,%ecx
+	movb	%al,5(%edi)
+	addl	%ebp,%ebx
+	movb	(%esi),%al
+	adcl	advancetable+4(,%ecx,4),%esi
+LLEntry3_8:
+	movb	%al,6(%edi)
+	movb	(%esi),%al
+LLEntry2_8:
+
+LEndSpan:
+
+//
+// clear s/z, t/z, 1/z from FP stack
+//
+	fstp %st(0)
+	fstp %st(0)
+	fstp %st(0)
+
+	movl	pspantemp,%ebx				// restore spans pointer
+	movl	espan_t_pnext(%ebx),%ebx	// point to next span
+	testl	%ebx,%ebx			// any more spans?
+	movb	%al,7(%edi)
+	jnz		LSpanLoop			// more spans
+
+	popl	%ebx				// restore register variables
+	popl	%esi
+	popl	%edi
+	popl	%ebp				// restore the caller's stack frame
+	ret
+
+//----------------------------------------------------------------------
+// 8-bpp horizontal span z drawing codefor polygons, with no transparency.
+//
+// Assumes there is at least one span in pzspans, and that every span
+// contains at least one pixel
+//----------------------------------------------------------------------
+
+	.text
+
+// z-clamp on a non-negative gradient span
+LClamp:
+	movl	$0x40000000,%edx
+	xorl	%ebx,%ebx
+	fstp	%st(0)
+	jmp		LZDraw
+
+// z-clamp on a negative gradient span
+LClampNeg:
+	movl	$0x40000000,%edx
+	xorl	%ebx,%ebx
+	fstp	%st(0)
+	jmp		LZDrawNeg
+
+
+#define pzspans	4+16
+
+.globl C(D_DrawZSpans)
+C(D_DrawZSpans):
+	pushl	%ebp				// preserve caller's stack frame
+	pushl	%edi
+	pushl	%esi				// preserve register variables
+	pushl	%ebx
+
+	flds	C(d_zistepu)
+	movl	C(d_zistepu),%eax
+	movl	pzspans(%esp),%esi
+	testl	%eax,%eax
+	jz		LFNegSpan
+
+	fmuls	Float2ToThe31nd
+	fistpl	izistep		// note: we are relying on FP exceptions being turned
+						// off here to avoid range problems
+	movl	izistep,%ebx	// remains loaded for all spans
+
+LFSpanLoop:
+// set up the initial 1/z value
+	fildl	espan_t_v(%esi)
+	fildl	espan_t_u(%esi)
+	movl	espan_t_v(%esi),%ecx
+	movl	C(d_pzbuffer),%edi
+	fmuls	C(d_zistepu)
+	fxch	%st(1)
+	fmuls	C(d_zistepv)
+	fxch	%st(1)
+	fadds	C(d_ziorigin)
+	imull	C(d_zrowbytes),%ecx
+	faddp	%st(0),%st(1)
+
+// clamp if z is nearer than 2 (1/z > 0.5)
+	fcoms	float_point5
+	addl	%ecx,%edi
+	movl	espan_t_u(%esi),%edx
+	addl	%edx,%edx				// word count
+	movl	espan_t_count(%esi),%ecx
+	addl	%edx,%edi				// pdest = &pdestspan[scans->u];
+	pushl	%esi		// preserve spans pointer
+	fnstsw	%ax
+	testb	$0x45,%ah
+	jz		LClamp
+
+	fmuls	Float2ToThe31nd
+	fistpl	izi			// note: we are relying on FP exceptions being turned
+						// off here to avoid problems when the span is closer
+						// than 1/(2**31)
+	movl	izi,%edx
+
+// at this point:
+// %ebx = izistep
+// %ecx = count
+// %edx = izi
+// %edi = pdest
+
+LZDraw:
+
+// do a single pixel up front, if necessary to dword align the destination
+	testl	$2,%edi
+	jz		LFMiddle
+	movl	%edx,%eax
+	addl	%ebx,%edx
+	shrl	$16,%eax
+	decl	%ecx
+	movw	%ax,(%edi)
+	addl	$2,%edi
+
+// do middle a pair of aligned dwords at a time
+LFMiddle:
+	pushl	%ecx
+	shrl	$1,%ecx				// count / 2
+	jz		LFLast				// no aligned dwords to do
+	shrl	$1,%ecx				// (count / 2) / 2
+	jnc		LFMiddleLoop		// even number of aligned dwords to do
+
+	movl	%edx,%eax
+	addl	%ebx,%edx
+	shrl	$16,%eax
+	movl	%edx,%esi
+	addl	%ebx,%edx
+	andl	$0xFFFF0000,%esi
+	orl		%esi,%eax
+	movl	%eax,(%edi)
+	addl	$4,%edi
+	andl	%ecx,%ecx
+	jz		LFLast
+
+LFMiddleLoop:
+	movl	%edx,%eax
+	addl	%ebx,%edx
+	shrl	$16,%eax
+	movl	%edx,%esi
+	addl	%ebx,%edx
+	andl	$0xFFFF0000,%esi
+	orl		%esi,%eax
+	movl	%edx,%ebp
+	movl	%eax,(%edi)
+	addl	%ebx,%edx
+	shrl	$16,%ebp
+	movl	%edx,%esi
+	addl	%ebx,%edx
+	andl	$0xFFFF0000,%esi
+	orl		%esi,%ebp
+	movl	%ebp,4(%edi)	// FIXME: eliminate register contention
+	addl	$8,%edi
+
+	decl	%ecx
+	jnz		LFMiddleLoop
+
+LFLast:
+	popl	%ecx			// retrieve count
+	popl	%esi			// retrieve span pointer
+
+// do the last, unaligned pixel, if there is one
+	andl	$1,%ecx			// is there an odd pixel left to do?
+	jz		LFSpanDone		// no
+	shrl	$16,%edx
+	movw	%dx,(%edi)		// do the final pixel's z
+
+LFSpanDone:
+	movl	espan_t_pnext(%esi),%esi
+	testl	%esi,%esi
+	jnz		LFSpanLoop
+
+	jmp		LFDone
+
+LFNegSpan:
+	fmuls	FloatMinus2ToThe31nd
+	fistpl	izistep		// note: we are relying on FP exceptions being turned
+						// off here to avoid range problems
+	movl	izistep,%ebx	// remains loaded for all spans
+
+LFNegSpanLoop:
+// set up the initial 1/z value
+	fildl	espan_t_v(%esi)
+	fildl	espan_t_u(%esi)
+	movl	espan_t_v(%esi),%ecx
+	movl	C(d_pzbuffer),%edi
+	fmuls	C(d_zistepu)
+	fxch	%st(1)
+	fmuls	C(d_zistepv)
+	fxch	%st(1)
+	fadds	C(d_ziorigin)
+	imull	C(d_zrowbytes),%ecx
+	faddp	%st(0),%st(1)
+
+// clamp if z is nearer than 2 (1/z > 0.5)
+	fcoms	float_point5
+	addl	%ecx,%edi
+	movl	espan_t_u(%esi),%edx
+	addl	%edx,%edx				// word count
+	movl	espan_t_count(%esi),%ecx
+	addl	%edx,%edi				// pdest = &pdestspan[scans->u];
+	pushl	%esi		// preserve spans pointer
+	fnstsw	%ax
+	testb	$0x45,%ah
+	jz		LClampNeg
+
+	fmuls	Float2ToThe31nd
+	fistpl	izi			// note: we are relying on FP exceptions being turned
+						// off here to avoid problems when the span is closer
+						// than 1/(2**31)
+	movl	izi,%edx
+
+// at this point:
+// %ebx = izistep
+// %ecx = count
+// %edx = izi
+// %edi = pdest
+
+LZDrawNeg:
+
+// do a single pixel up front, if necessary to dword align the destination
+	testl	$2,%edi
+	jz		LFNegMiddle
+	movl	%edx,%eax
+	subl	%ebx,%edx
+	shrl	$16,%eax
+	decl	%ecx
+	movw	%ax,(%edi)
+	addl	$2,%edi
+
+// do middle a pair of aligned dwords at a time
+LFNegMiddle:
+	pushl	%ecx
+	shrl	$1,%ecx				// count / 2
+	jz		LFNegLast			// no aligned dwords to do
+	shrl	$1,%ecx				// (count / 2) / 2
+	jnc		LFNegMiddleLoop		// even number of aligned dwords to do
+
+	movl	%edx,%eax
+	subl	%ebx,%edx
+	shrl	$16,%eax
+	movl	%edx,%esi
+	subl	%ebx,%edx
+	andl	$0xFFFF0000,%esi
+	orl		%esi,%eax
+	movl	%eax,(%edi)
+	addl	$4,%edi
+	andl	%ecx,%ecx
+	jz		LFNegLast
+
+LFNegMiddleLoop:
+	movl	%edx,%eax
+	subl	%ebx,%edx
+	shrl	$16,%eax
+	movl	%edx,%esi
+	subl	%ebx,%edx
+	andl	$0xFFFF0000,%esi
+	orl		%esi,%eax
+	movl	%edx,%ebp
+	movl	%eax,(%edi)
+	subl	%ebx,%edx
+	shrl	$16,%ebp
+	movl	%edx,%esi
+	subl	%ebx,%edx
+	andl	$0xFFFF0000,%esi
+	orl		%esi,%ebp
+	movl	%ebp,4(%edi)	// FIXME: eliminate register contention
+	addl	$8,%edi
+
+	decl	%ecx
+	jnz		LFNegMiddleLoop
+
+LFNegLast:
+	popl	%ecx			// retrieve count
+	popl	%esi			// retrieve span pointer
+
+// do the last, unaligned pixel, if there is one
+	andl	$1,%ecx			// is there an odd pixel left to do?
+	jz		LFNegSpanDone	// no
+	shrl	$16,%edx
+	movw	%dx,(%edi)		// do the final pixel's z
+
+LFNegSpanDone:
+	movl	espan_t_pnext(%esi),%esi
+	testl	%esi,%esi
+	jnz		LFNegSpanLoop
+
+LFDone:
+	popl	%ebx				// restore register variables
+	popl	%esi
+	popl	%edi
+	popl	%ebp				// restore the caller's stack frame
+	ret
+
+#endif	// id386
--- /dev/null
+++ b/WinQuake/d_draw16.s
@@ -1,0 +1,974 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+//
+// d_draw16.s
+// x86 assembly-language horizontal 8-bpp span-drawing code, with 16-pixel
+// subdivision.
+//
+
+#include "asm_i386.h"
+#include "quakeasm.h"
+#include "asm_draw.h"
+#include "d_ifacea.h"
+
+#if	id386
+
+//----------------------------------------------------------------------
+// 8-bpp horizontal span drawing code for polygons, with no transparency and
+// 16-pixel subdivision.
+//
+// Assumes there is at least one span in pspans, and that every span
+// contains at least one pixel
+//----------------------------------------------------------------------
+
+	.data
+
+	.text
+
+// out-of-line, rarely-needed clamping code
+
+LClampHigh0:
+	movl	C(bbextents),%esi
+	jmp		LClampReentry0
+LClampHighOrLow0:
+	jg		LClampHigh0
+	xorl	%esi,%esi
+	jmp		LClampReentry0
+
+LClampHigh1:
+	movl	C(bbextentt),%edx
+	jmp		LClampReentry1
+LClampHighOrLow1:
+	jg		LClampHigh1
+	xorl	%edx,%edx
+	jmp		LClampReentry1
+
+LClampLow2:
+	movl	$4096,%ebp
+	jmp		LClampReentry2
+LClampHigh2:
+	movl	C(bbextents),%ebp
+	jmp		LClampReentry2
+
+LClampLow3:
+	movl	$4096,%ecx
+	jmp		LClampReentry3
+LClampHigh3:
+	movl	C(bbextentt),%ecx
+	jmp		LClampReentry3
+
+LClampLow4:
+	movl	$4096,%eax
+	jmp		LClampReentry4
+LClampHigh4:
+	movl	C(bbextents),%eax
+	jmp		LClampReentry4
+
+LClampLow5:
+	movl	$4096,%ebx
+	jmp		LClampReentry5
+LClampHigh5:
+	movl	C(bbextentt),%ebx
+	jmp		LClampReentry5
+
+
+#define pspans	4+16
+
+	.align 4
+.globl C(D_DrawSpans16)
+C(D_DrawSpans16):
+	pushl	%ebp				// preserve caller's stack frame
+	pushl	%edi
+	pushl	%esi				// preserve register variables
+	pushl	%ebx
+
+//
+// set up scaled-by-16 steps, for 16-long segments; also set up cacheblock
+// and span list pointers
+//
+// TODO: any overlap from rearranging?
+	flds	C(d_sdivzstepu)
+	fmuls	fp_16
+	movl	C(cacheblock),%edx
+	flds	C(d_tdivzstepu)
+	fmuls	fp_16
+	movl	pspans(%esp),%ebx	// point to the first span descriptor
+	flds	C(d_zistepu)
+	fmuls	fp_16
+	movl	%edx,pbase			// pbase = cacheblock
+	fstps	zi16stepu
+	fstps	tdivz16stepu
+	fstps	sdivz16stepu
+
+LSpanLoop:
+//
+// set up the initial s/z, t/z, and 1/z on the FP stack, and generate the
+// initial s and t values
+//
+// FIXME: pipeline FILD?
+	fildl	espan_t_v(%ebx)
+	fildl	espan_t_u(%ebx)
+
+	fld		%st(1)			// dv | du | dv
+	fmuls	C(d_sdivzstepv)	// dv*d_sdivzstepv | du | dv
+	fld		%st(1)			// du | dv*d_sdivzstepv | du | dv
+	fmuls	C(d_sdivzstepu)	// du*d_sdivzstepu | dv*d_sdivzstepv | du | dv
+	fld		%st(2)			// du | du*d_sdivzstepu | dv*d_sdivzstepv | du | dv
+	fmuls	C(d_tdivzstepu)	// du*d_tdivzstepu | du*d_sdivzstepu |
+							//  dv*d_sdivzstepv | du | dv
+	fxch	%st(1)			// du*d_sdivzstepu | du*d_tdivzstepu |
+							//  dv*d_sdivzstepv | du | dv
+	faddp	%st(0),%st(2)	// du*d_tdivzstepu |
+							//  du*d_sdivzstepu + dv*d_sdivzstepv | du | dv
+	fxch	%st(1)			// du*d_sdivzstepu + dv*d_sdivzstepv |
+							//  du*d_tdivzstepu | du | dv
+	fld		%st(3)			// dv | du*d_sdivzstepu + dv*d_sdivzstepv |
+							//  du*d_tdivzstepu | du | dv
+	fmuls	C(d_tdivzstepv)	// dv*d_tdivzstepv |
+							//  du*d_sdivzstepu + dv*d_sdivzstepv |
+							//  du*d_tdivzstepu | du | dv
+	fxch	%st(1)			// du*d_sdivzstepu + dv*d_sdivzstepv |
+							//  dv*d_tdivzstepv | du*d_tdivzstepu | du | dv
+	fadds	C(d_sdivzorigin)	// sdivz = d_sdivzorigin + dv*d_sdivzstepv +
+							//  du*d_sdivzstepu; stays in %st(2) at end
+	fxch	%st(4)			// dv | dv*d_tdivzstepv | du*d_tdivzstepu | du |
+							//  s/z
+	fmuls	C(d_zistepv)		// dv*d_zistepv | dv*d_tdivzstepv |
+							//  du*d_tdivzstepu | du | s/z
+	fxch	%st(1)			// dv*d_tdivzstepv |  dv*d_zistepv |
+							//  du*d_tdivzstepu | du | s/z
+	faddp	%st(0),%st(2)	// dv*d_zistepv |
+							//  dv*d_tdivzstepv + du*d_tdivzstepu | du | s/z
+	fxch	%st(2)			// du | dv*d_tdivzstepv + du*d_tdivzstepu |
+							//  dv*d_zistepv | s/z
+	fmuls	C(d_zistepu)		// du*d_zistepu |
+							//  dv*d_tdivzstepv + du*d_tdivzstepu |
+							//  dv*d_zistepv | s/z
+	fxch	%st(1)			// dv*d_tdivzstepv + du*d_tdivzstepu |
+							//  du*d_zistepu | dv*d_zistepv | s/z
+	fadds	C(d_tdivzorigin)	// tdivz = d_tdivzorigin + dv*d_tdivzstepv +
+							//  du*d_tdivzstepu; stays in %st(1) at end
+	fxch	%st(2)			// dv*d_zistepv | du*d_zistepu | t/z | s/z
+	faddp	%st(0),%st(1)	// dv*d_zistepv + du*d_zistepu | t/z | s/z
+
+	flds	fp_64k			// fp_64k | dv*d_zistepv + du*d_zistepu | t/z | s/z
+	fxch	%st(1)			// dv*d_zistepv + du*d_zistepu | fp_64k | t/z | s/z
+	fadds	C(d_ziorigin)		// zi = d_ziorigin + dv*d_zistepv +
+							//  du*d_zistepu; stays in %st(0) at end
+							// 1/z | fp_64k | t/z | s/z
+//
+// calculate and clamp s & t
+//
+	fdivr	%st(0),%st(1)	// 1/z | z*64k | t/z | s/z
+
+//
+// point %edi to the first pixel in the span
+//
+	movl	C(d_viewbuffer),%ecx
+	movl	espan_t_v(%ebx),%eax
+	movl	%ebx,pspantemp	// preserve spans pointer
+
+	movl	C(tadjust),%edx
+	movl	C(sadjust),%esi
+	movl	C(d_scantable)(,%eax,4),%edi	// v * screenwidth
+	addl	%ecx,%edi
+	movl	espan_t_u(%ebx),%ecx
+	addl	%ecx,%edi				// pdest = &pdestspan[scans->u];
+	movl	espan_t_count(%ebx),%ecx
+
+//
+// now start the FDIV for the end of the span
+//
+	cmpl	$16,%ecx
+	ja		LSetupNotLast1
+
+	decl	%ecx
+	jz		LCleanup1		// if only one pixel, no need to start an FDIV
+	movl	%ecx,spancountminus1
+
+// finish up the s and t calcs
+	fxch	%st(1)			// z*64k | 1/z | t/z | s/z
+
+	fld		%st(0)			// z*64k | z*64k | 1/z | t/z | s/z
+	fmul	%st(4),%st(0)	// s | z*64k | 1/z | t/z | s/z
+	fxch	%st(1)			// z*64k | s | 1/z | t/z | s/z
+	fmul	%st(3),%st(0)	// t | s | 1/z | t/z | s/z
+	fxch	%st(1)			// s | t | 1/z | t/z | s/z
+	fistpl	s				// 1/z | t | t/z | s/z
+	fistpl	t				// 1/z | t/z | s/z
+
+	fildl	spancountminus1
+
+	flds	C(d_tdivzstepu)	// C(d_tdivzstepu) | spancountminus1
+	flds	C(d_zistepu)		// C(d_zistepu) | C(d_tdivzstepu) | spancountminus1
+	fmul	%st(2),%st(0)	// C(d_zistepu)*scm1 | C(d_tdivzstepu) | scm1
+	fxch	%st(1)			// C(d_tdivzstepu) | C(d_zistepu)*scm1 | scm1
+	fmul	%st(2),%st(0)	// C(d_tdivzstepu)*scm1 | C(d_zistepu)*scm1 | scm1
+	fxch	%st(2)			// scm1 | C(d_zistepu)*scm1 | C(d_tdivzstepu)*scm1
+	fmuls	C(d_sdivzstepu)	// C(d_sdivzstepu)*scm1 | C(d_zistepu)*scm1 |
+							//  C(d_tdivzstepu)*scm1
+	fxch	%st(1)			// C(d_zistepu)*scm1 | C(d_sdivzstepu)*scm1 |
+							//  C(d_tdivzstepu)*scm1
+	faddp	%st(0),%st(3)	// C(d_sdivzstepu)*scm1 | C(d_tdivzstepu)*scm1
+	fxch	%st(1)			// C(d_tdivzstepu)*scm1 | C(d_sdivzstepu)*scm1
+	faddp	%st(0),%st(3)	// C(d_sdivzstepu)*scm1
+	faddp	%st(0),%st(3)
+
+	flds	fp_64k
+	fdiv	%st(1),%st(0)	// this is what we've gone to all this trouble to
+							//  overlap
+	jmp		LFDIVInFlight1
+
+LCleanup1:
+// finish up the s and t calcs
+	fxch	%st(1)			// z*64k | 1/z | t/z | s/z
+
+	fld		%st(0)			// z*64k | z*64k | 1/z | t/z | s/z
+	fmul	%st(4),%st(0)	// s | z*64k | 1/z | t/z | s/z
+	fxch	%st(1)			// z*64k | s | 1/z | t/z | s/z
+	fmul	%st(3),%st(0)	// t | s | 1/z | t/z | s/z
+	fxch	%st(1)			// s | t | 1/z | t/z | s/z
+	fistpl	s				// 1/z | t | t/z | s/z
+	fistpl	t				// 1/z | t/z | s/z
+	jmp		LFDIVInFlight1
+
+	.align	4
+LSetupNotLast1:
+// finish up the s and t calcs
+	fxch	%st(1)			// z*64k | 1/z | t/z | s/z
+
+	fld		%st(0)			// z*64k | z*64k | 1/z | t/z | s/z
+	fmul	%st(4),%st(0)	// s | z*64k | 1/z | t/z | s/z
+	fxch	%st(1)			// z*64k | s | 1/z | t/z | s/z
+	fmul	%st(3),%st(0)	// t | s | 1/z | t/z | s/z
+	fxch	%st(1)			// s | t | 1/z | t/z | s/z
+	fistpl	s				// 1/z | t | t/z | s/z
+	fistpl	t				// 1/z | t/z | s/z
+
+	fadds	zi16stepu
+	fxch	%st(2)
+	fadds	sdivz16stepu
+	fxch	%st(2)
+	flds	tdivz16stepu
+	faddp	%st(0),%st(2)
+	flds	fp_64k
+	fdiv	%st(1),%st(0)	// z = 1/1/z
+							// this is what we've gone to all this trouble to
+							//  overlap
+LFDIVInFlight1:
+
+	addl	s,%esi
+	addl	t,%edx
+	movl	C(bbextents),%ebx
+	movl	C(bbextentt),%ebp
+	cmpl	%ebx,%esi
+	ja		LClampHighOrLow0
+LClampReentry0:
+	movl	%esi,s
+	movl	pbase,%ebx
+	shll	$16,%esi
+	cmpl	%ebp,%edx
+	movl	%esi,sfracf
+	ja		LClampHighOrLow1
+LClampReentry1:
+	movl	%edx,t
+	movl	s,%esi					// sfrac = scans->sfrac;
+	shll	$16,%edx
+	movl	t,%eax					// tfrac = scans->tfrac;
+	sarl	$16,%esi
+	movl	%edx,tfracf
+
+//
+// calculate the texture starting address
+//
+	sarl	$16,%eax
+	movl	C(cachewidth),%edx
+	imull	%edx,%eax				// (tfrac >> 16) * cachewidth
+	addl	%ebx,%esi
+	addl	%eax,%esi				// psource = pbase + (sfrac >> 16) +
+									//           ((tfrac >> 16) * cachewidth);
+//
+// determine whether last span or not
+//
+	cmpl	$16,%ecx
+	jna		LLastSegment
+
+//
+// not the last segment; do full 16-wide segment
+//
+LNotLastSegment:
+
+//
+// advance s/z, t/z, and 1/z, and calculate s & t at end of span and steps to
+// get there
+//
+
+// pick up after the FDIV that was left in flight previously
+
+	fld		%st(0)			// duplicate it
+	fmul	%st(4),%st(0)	// s = s/z * z
+	fxch	%st(1)
+	fmul	%st(3),%st(0)	// t = t/z * z
+	fxch	%st(1)
+	fistpl	snext
+	fistpl	tnext
+	movl	snext,%eax
+	movl	tnext,%edx
+
+	movb	(%esi),%bl	// get first source texel
+	subl	$16,%ecx		// count off this segments' pixels
+	movl	C(sadjust),%ebp
+	movl	%ecx,counttemp	// remember count of remaining pixels
+
+	movl	C(tadjust),%ecx
+	movb	%bl,(%edi)	// store first dest pixel
+
+	addl	%eax,%ebp
+	addl	%edx,%ecx
+
+	movl	C(bbextents),%eax
+	movl	C(bbextentt),%edx
+
+	cmpl	$4096,%ebp
+	jl		LClampLow2
+	cmpl	%eax,%ebp
+	ja		LClampHigh2
+LClampReentry2:
+
+	cmpl	$4096,%ecx
+	jl		LClampLow3
+	cmpl	%edx,%ecx
+	ja		LClampHigh3
+LClampReentry3:
+
+	movl	%ebp,snext
+	movl	%ecx,tnext
+
+	subl	s,%ebp
+	subl	t,%ecx
+	
+//
+// set up advancetable
+//
+	movl	%ecx,%eax
+	movl	%ebp,%edx
+	sarl	$20,%eax			// tstep >>= 16;
+	jz		LZero
+	sarl	$20,%edx			// sstep >>= 16;
+	movl	C(cachewidth),%ebx
+	imull	%ebx,%eax
+	jmp		LSetUp1
+
+LZero:
+	sarl	$20,%edx			// sstep >>= 16;
+	movl	C(cachewidth),%ebx
+
+LSetUp1:
+
+	addl	%edx,%eax			// add in sstep
+								// (tstep >> 16) * cachewidth + (sstep >> 16);
+	movl	tfracf,%edx
+	movl	%eax,advancetable+4	// advance base in t
+	addl	%ebx,%eax			// ((tstep >> 16) + 1) * cachewidth +
+								//  (sstep >> 16);
+	shll	$12,%ebp			// left-justify sstep fractional part
+	movl	sfracf,%ebx
+	shll	$12,%ecx			// left-justify tstep fractional part
+	movl	%eax,advancetable	// advance extra in t
+
+	movl	%ecx,tstep
+	addl	%ecx,%edx			// advance tfrac fractional part by tstep frac
+
+	sbbl	%ecx,%ecx			// turn tstep carry into -1 (0 if none)
+	addl	%ebp,%ebx			// advance sfrac fractional part by sstep frac
+	adcl	advancetable+4(,%ecx,4),%esi	// point to next source texel
+
+	addl	tstep,%edx
+	sbbl	%ecx,%ecx
+	movb	(%esi),%al
+	addl	%ebp,%ebx
+	movb	%al,1(%edi)
+	adcl	advancetable+4(,%ecx,4),%esi
+
+	addl	tstep,%edx
+	sbbl	%ecx,%ecx
+	addl	%ebp,%ebx
+	movb	(%esi),%al
+	adcl	advancetable+4(,%ecx,4),%esi
+
+	addl	tstep,%edx
+	sbbl	%ecx,%ecx
+	movb	%al,2(%edi)
+	addl	%ebp,%ebx
+	movb	(%esi),%al
+	adcl	advancetable+4(,%ecx,4),%esi
+
+	addl	tstep,%edx
+	sbbl	%ecx,%ecx
+	movb	%al,3(%edi)
+	addl	%ebp,%ebx
+	movb	(%esi),%al
+	adcl	advancetable+4(,%ecx,4),%esi
+
+	addl	tstep,%edx
+	sbbl	%ecx,%ecx
+	movb	%al,4(%edi)
+	addl	%ebp,%ebx
+	movb	(%esi),%al
+	adcl	advancetable+4(,%ecx,4),%esi
+
+	addl	tstep,%edx
+	sbbl	%ecx,%ecx
+	movb	%al,5(%edi)
+	addl	%ebp,%ebx
+	movb	(%esi),%al
+	adcl	advancetable+4(,%ecx,4),%esi
+
+	addl	tstep,%edx
+	sbbl	%ecx,%ecx
+	movb	%al,6(%edi)
+	addl	%ebp,%ebx
+	movb	(%esi),%al
+	adcl	advancetable+4(,%ecx,4),%esi
+
+	addl	tstep,%edx
+	sbbl	%ecx,%ecx
+	movb	%al,7(%edi)
+	addl	%ebp,%ebx
+	movb	(%esi),%al
+	adcl	advancetable+4(,%ecx,4),%esi
+
+
+//
+// start FDIV for end of next segment in flight, so it can overlap
+//
+	movl	counttemp,%ecx
+	cmpl	$16,%ecx			// more than one segment after this?
+	ja		LSetupNotLast2	// yes
+
+	decl	%ecx
+	jz		LFDIVInFlight2	// if only one pixel, no need to start an FDIV
+	movl	%ecx,spancountminus1
+	fildl	spancountminus1
+
+	flds	C(d_zistepu)		// C(d_zistepu) | spancountminus1
+	fmul	%st(1),%st(0)	// C(d_zistepu)*scm1 | scm1
+	flds	C(d_tdivzstepu)	// C(d_tdivzstepu) | C(d_zistepu)*scm1 | scm1
+	fmul	%st(2),%st(0)	// C(d_tdivzstepu)*scm1 | C(d_zistepu)*scm1 | scm1
+	fxch	%st(1)			// C(d_zistepu)*scm1 | C(d_tdivzstepu)*scm1 | scm1
+	faddp	%st(0),%st(3)	// C(d_tdivzstepu)*scm1 | scm1
+	fxch	%st(1)			// scm1 | C(d_tdivzstepu)*scm1
+	fmuls	C(d_sdivzstepu)	// C(d_sdivzstepu)*scm1 | C(d_tdivzstepu)*scm1
+	fxch	%st(1)			// C(d_tdivzstepu)*scm1 | C(d_sdivzstepu)*scm1
+	faddp	%st(0),%st(3)	// C(d_sdivzstepu)*scm1
+	flds	fp_64k			// 64k | C(d_sdivzstepu)*scm1
+	fxch	%st(1)			// C(d_sdivzstepu)*scm1 | 64k
+	faddp	%st(0),%st(4)	// 64k
+
+	fdiv	%st(1),%st(0)	// this is what we've gone to all this trouble to
+							//  overlap
+	jmp		LFDIVInFlight2
+
+	.align	4
+LSetupNotLast2:
+	fadds	zi16stepu
+	fxch	%st(2)
+	fadds	sdivz16stepu
+	fxch	%st(2)
+	flds	tdivz16stepu
+	faddp	%st(0),%st(2)
+	flds	fp_64k
+	fdiv	%st(1),%st(0)	// z = 1/1/z
+							// this is what we've gone to all this trouble to
+							//  overlap
+LFDIVInFlight2:
+	movl	%ecx,counttemp
+
+	addl	tstep,%edx
+	sbbl	%ecx,%ecx
+	movb	%al,8(%edi)
+	addl	%ebp,%ebx
+	movb	(%esi),%al
+	adcl	advancetable+4(,%ecx,4),%esi
+
+	addl	tstep,%edx
+	sbbl	%ecx,%ecx
+	movb	%al,9(%edi)
+	addl	%ebp,%ebx
+	movb	(%esi),%al
+	adcl	advancetable+4(,%ecx,4),%esi
+
+	addl	tstep,%edx
+	sbbl	%ecx,%ecx
+	movb	%al,10(%edi)
+	addl	%ebp,%ebx
+	movb	(%esi),%al
+	adcl	advancetable+4(,%ecx,4),%esi
+
+	addl	tstep,%edx
+	sbbl	%ecx,%ecx
+	movb	%al,11(%edi)
+	addl	%ebp,%ebx
+	movb	(%esi),%al
+	adcl	advancetable+4(,%ecx,4),%esi
+
+	addl	tstep,%edx
+	sbbl	%ecx,%ecx
+	movb	%al,12(%edi)
+	addl	%ebp,%ebx
+	movb	(%esi),%al
+	adcl	advancetable+4(,%ecx,4),%esi
+
+	addl	tstep,%edx
+	sbbl	%ecx,%ecx
+	movb	%al,13(%edi)
+	addl	%ebp,%ebx
+	movb	(%esi),%al
+	adcl	advancetable+4(,%ecx,4),%esi
+
+	addl	tstep,%edx
+	sbbl	%ecx,%ecx
+	movb	%al,14(%edi)
+	addl	%ebp,%ebx
+	movb	(%esi),%al
+	adcl	advancetable+4(,%ecx,4),%esi
+
+	addl	$16,%edi
+	movl	%edx,tfracf
+	movl	snext,%edx
+	movl	%ebx,sfracf
+	movl	tnext,%ebx
+	movl	%edx,s
+	movl	%ebx,t
+
+	movl	counttemp,%ecx		// retrieve count
+
+//
+// determine whether last span or not
+//
+	cmpl	$16,%ecx				// are there multiple segments remaining?
+	movb	%al,-1(%edi)
+	ja		LNotLastSegment		// yes
+
+//
+// last segment of scan
+//
+LLastSegment:
+
+//
+// advance s/z, t/z, and 1/z, and calculate s & t at end of span and steps to
+// get there. The number of pixels left is variable, and we want to land on the
+// last pixel, not step one past it, so we can't run into arithmetic problems
+//
+	testl	%ecx,%ecx
+	jz		LNoSteps		// just draw the last pixel and we're done
+
+// pick up after the FDIV that was left in flight previously
+
+
+	fld		%st(0)			// duplicate it
+	fmul	%st(4),%st(0)	// s = s/z * z
+	fxch	%st(1)
+	fmul	%st(3),%st(0)	// t = t/z * z
+	fxch	%st(1)
+	fistpl	snext
+	fistpl	tnext
+
+	movb	(%esi),%al		// load first texel in segment
+	movl	C(tadjust),%ebx
+	movb	%al,(%edi)		// store first pixel in segment
+	movl	C(sadjust),%eax
+
+	addl	snext,%eax
+	addl	tnext,%ebx
+
+	movl	C(bbextents),%ebp
+	movl	C(bbextentt),%edx
+
+	cmpl	$4096,%eax
+	jl		LClampLow4
+	cmpl	%ebp,%eax
+	ja		LClampHigh4
+LClampReentry4:
+	movl	%eax,snext
+
+	cmpl	$4096,%ebx
+	jl		LClampLow5
+	cmpl	%edx,%ebx
+	ja		LClampHigh5
+LClampReentry5:
+
+	cmpl	$1,%ecx			// don't bother 
+	je		LOnlyOneStep	// if two pixels in segment, there's only one step,
+							//  of the segment length
+	subl	s,%eax
+	subl	t,%ebx
+
+	addl	%eax,%eax		// convert to 15.17 format so multiply by 1.31
+	addl	%ebx,%ebx		//  reciprocal yields 16.48
+
+	imull	reciprocal_table_16-8(,%ecx,4)	// sstep = (snext - s) /
+											//  (spancount-1)
+	movl	%edx,%ebp
+
+	movl	%ebx,%eax
+	imull	reciprocal_table_16-8(,%ecx,4)	// tstep = (tnext - t) /
+											//  (spancount-1)
+LSetEntryvec:
+//
+// set up advancetable
+//
+	movl	entryvec_table_16(,%ecx,4),%ebx
+	movl	%edx,%eax
+	movl	%ebx,jumptemp		// entry point into code for RET later
+	movl	%ebp,%ecx
+	sarl	$16,%edx			// tstep >>= 16;
+	movl	C(cachewidth),%ebx
+	sarl	$16,%ecx			// sstep >>= 16;
+	imull	%ebx,%edx
+
+	addl	%ecx,%edx			// add in sstep
+								// (tstep >> 16) * cachewidth + (sstep >> 16);
+	movl	tfracf,%ecx
+	movl	%edx,advancetable+4	// advance base in t
+	addl	%ebx,%edx			// ((tstep >> 16) + 1) * cachewidth +
+								//  (sstep >> 16);
+	shll	$16,%ebp			// left-justify sstep fractional part
+	movl	sfracf,%ebx
+	shll	$16,%eax			// left-justify tstep fractional part
+	movl	%edx,advancetable	// advance extra in t
+
+	movl	%eax,tstep
+	movl	%ecx,%edx
+	addl	%eax,%edx
+	sbbl	%ecx,%ecx
+	addl	%ebp,%ebx
+	adcl	advancetable+4(,%ecx,4),%esi
+
+	jmp		*jumptemp			// jump to the number-of-pixels handler
+
+//----------------------------------------
+
+LNoSteps:
+	movb	(%esi),%al		// load first texel in segment
+	subl	$15,%edi			// adjust for hardwired offset
+	jmp		LEndSpan
+
+
+LOnlyOneStep:
+	subl	s,%eax
+	subl	t,%ebx
+	movl	%eax,%ebp
+	movl	%ebx,%edx
+	jmp		LSetEntryvec
+
+//----------------------------------------
+
+.globl	Entry2_16, Entry3_16, Entry4_16, Entry5_16
+.globl	Entry6_16, Entry7_16, Entry8_16, Entry9_16
+.globl	Entry10_16, Entry11_16, Entry12_16, Entry13_16
+.globl	Entry14_16, Entry15_16, Entry16_16
+
+Entry2_16:
+	subl	$14,%edi		// adjust for hardwired offsets
+	movb	(%esi),%al
+	jmp		LEntry2_16
+
+//----------------------------------------
+
+Entry3_16:
+	subl	$13,%edi		// adjust for hardwired offsets
+	addl	%eax,%edx
+	movb	(%esi),%al
+	sbbl	%ecx,%ecx
+	addl	%ebp,%ebx
+	adcl	advancetable+4(,%ecx,4),%esi
+	jmp		LEntry3_16
+
+//----------------------------------------
+
+Entry4_16:
+	subl	$12,%edi		// adjust for hardwired offsets
+	addl	%eax,%edx
+	movb	(%esi),%al
+	sbbl	%ecx,%ecx
+	addl	%ebp,%ebx
+	adcl	advancetable+4(,%ecx,4),%esi
+	addl	tstep,%edx
+	jmp		LEntry4_16
+
+//----------------------------------------
+
+Entry5_16:
+	subl	$11,%edi		// adjust for hardwired offsets
+	addl	%eax,%edx
+	movb	(%esi),%al
+	sbbl	%ecx,%ecx
+	addl	%ebp,%ebx
+	adcl	advancetable+4(,%ecx,4),%esi
+	addl	tstep,%edx
+	jmp		LEntry5_16
+
+//----------------------------------------
+
+Entry6_16:
+	subl	$10,%edi		// adjust for hardwired offsets
+	addl	%eax,%edx
+	movb	(%esi),%al
+	sbbl	%ecx,%ecx
+	addl	%ebp,%ebx
+	adcl	advancetable+4(,%ecx,4),%esi
+	addl	tstep,%edx
+	jmp		LEntry6_16
+
+//----------------------------------------
+
+Entry7_16:
+	subl	$9,%edi		// adjust for hardwired offsets
+	addl	%eax,%edx
+	movb	(%esi),%al
+	sbbl	%ecx,%ecx
+	addl	%ebp,%ebx
+	adcl	advancetable+4(,%ecx,4),%esi
+	addl	tstep,%edx
+	jmp		LEntry7_16
+
+//----------------------------------------
+
+Entry8_16:
+	subl	$8,%edi		// adjust for hardwired offsets
+	addl	%eax,%edx
+	movb	(%esi),%al
+	sbbl	%ecx,%ecx
+	addl	%ebp,%ebx
+	adcl	advancetable+4(,%ecx,4),%esi
+	addl	tstep,%edx
+	jmp		LEntry8_16
+
+//----------------------------------------
+
+Entry9_16:
+	subl	$7,%edi		// adjust for hardwired offsets
+	addl	%eax,%edx
+	movb	(%esi),%al
+	sbbl	%ecx,%ecx
+	addl	%ebp,%ebx
+	adcl	advancetable+4(,%ecx,4),%esi
+	addl	tstep,%edx
+	jmp		LEntry9_16
+
+//----------------------------------------
+
+Entry10_16:
+	subl	$6,%edi		// adjust for hardwired offsets
+	addl	%eax,%edx
+	movb	(%esi),%al
+	sbbl	%ecx,%ecx
+	addl	%ebp,%ebx
+	adcl	advancetable+4(,%ecx,4),%esi
+	addl	tstep,%edx
+	jmp		LEntry10_16
+
+//----------------------------------------
+
+Entry11_16:
+	subl	$5,%edi		// adjust for hardwired offsets
+	addl	%eax,%edx
+	movb	(%esi),%al
+	sbbl	%ecx,%ecx
+	addl	%ebp,%ebx
+	adcl	advancetable+4(,%ecx,4),%esi
+	addl	tstep,%edx
+	jmp		LEntry11_16
+
+//----------------------------------------
+
+Entry12_16:
+	subl	$4,%edi		// adjust for hardwired offsets
+	addl	%eax,%edx
+	movb	(%esi),%al
+	sbbl	%ecx,%ecx
+	addl	%ebp,%ebx
+	adcl	advancetable+4(,%ecx,4),%esi
+	addl	tstep,%edx
+	jmp		LEntry12_16
+
+//----------------------------------------
+
+Entry13_16:
+	subl	$3,%edi		// adjust for hardwired offsets
+	addl	%eax,%edx
+	movb	(%esi),%al
+	sbbl	%ecx,%ecx
+	addl	%ebp,%ebx
+	adcl	advancetable+4(,%ecx,4),%esi
+	addl	tstep,%edx
+	jmp		LEntry13_16
+
+//----------------------------------------
+
+Entry14_16:
+	subl	$2,%edi		// adjust for hardwired offsets
+	addl	%eax,%edx
+	movb	(%esi),%al
+	sbbl	%ecx,%ecx
+	addl	%ebp,%ebx
+	adcl	advancetable+4(,%ecx,4),%esi
+	addl	tstep,%edx
+	jmp		LEntry14_16
+
+//----------------------------------------
+
+Entry15_16:
+	decl	%edi		// adjust for hardwired offsets
+	addl	%eax,%edx
+	movb	(%esi),%al
+	sbbl	%ecx,%ecx
+	addl	%ebp,%ebx
+	adcl	advancetable+4(,%ecx,4),%esi
+	addl	tstep,%edx
+	jmp		LEntry15_16
+
+//----------------------------------------
+
+Entry16_16:
+	addl	%eax,%edx
+	movb	(%esi),%al
+	sbbl	%ecx,%ecx
+	addl	%ebp,%ebx
+	adcl	advancetable+4(,%ecx,4),%esi
+
+	addl	tstep,%edx
+	sbbl	%ecx,%ecx
+	movb	%al,1(%edi)
+	addl	%ebp,%ebx
+	movb	(%esi),%al
+	adcl	advancetable+4(,%ecx,4),%esi
+	addl	tstep,%edx
+LEntry15_16:
+	sbbl	%ecx,%ecx
+	movb	%al,2(%edi)
+	addl	%ebp,%ebx
+	movb	(%esi),%al
+	adcl	advancetable+4(,%ecx,4),%esi
+	addl	tstep,%edx
+LEntry14_16:
+	sbbl	%ecx,%ecx
+	movb	%al,3(%edi)
+	addl	%ebp,%ebx
+	movb	(%esi),%al
+	adcl	advancetable+4(,%ecx,4),%esi
+	addl	tstep,%edx
+LEntry13_16:
+	sbbl	%ecx,%ecx
+	movb	%al,4(%edi)
+	addl	%ebp,%ebx
+	movb	(%esi),%al
+	adcl	advancetable+4(,%ecx,4),%esi
+	addl	tstep,%edx
+LEntry12_16:
+	sbbl	%ecx,%ecx
+	movb	%al,5(%edi)
+	addl	%ebp,%ebx
+	movb	(%esi),%al
+	adcl	advancetable+4(,%ecx,4),%esi
+	addl	tstep,%edx
+LEntry11_16:
+	sbbl	%ecx,%ecx
+	movb	%al,6(%edi)
+	addl	%ebp,%ebx
+	movb	(%esi),%al
+	adcl	advancetable+4(,%ecx,4),%esi
+	addl	tstep,%edx
+LEntry10_16:
+	sbbl	%ecx,%ecx
+	movb	%al,7(%edi)
+	addl	%ebp,%ebx
+	movb	(%esi),%al
+	adcl	advancetable+4(,%ecx,4),%esi
+	addl	tstep,%edx
+LEntry9_16:
+	sbbl	%ecx,%ecx
+	movb	%al,8(%edi)
+	addl	%ebp,%ebx
+	movb	(%esi),%al
+	adcl	advancetable+4(,%ecx,4),%esi
+	addl	tstep,%edx
+LEntry8_16:
+	sbbl	%ecx,%ecx
+	movb	%al,9(%edi)
+	addl	%ebp,%ebx
+	movb	(%esi),%al
+	adcl	advancetable+4(,%ecx,4),%esi
+	addl	tstep,%edx
+LEntry7_16:
+	sbbl	%ecx,%ecx
+	movb	%al,10(%edi)
+	addl	%ebp,%ebx
+	movb	(%esi),%al
+	adcl	advancetable+4(,%ecx,4),%esi
+	addl	tstep,%edx
+LEntry6_16:
+	sbbl	%ecx,%ecx
+	movb	%al,11(%edi)
+	addl	%ebp,%ebx
+	movb	(%esi),%al
+	adcl	advancetable+4(,%ecx,4),%esi
+	addl	tstep,%edx
+LEntry5_16:
+	sbbl	%ecx,%ecx
+	movb	%al,12(%edi)
+	addl	%ebp,%ebx
+	movb	(%esi),%al
+	adcl	advancetable+4(,%ecx,4),%esi
+	addl	tstep,%edx
+LEntry4_16:
+	sbbl	%ecx,%ecx
+	movb	%al,13(%edi)
+	addl	%ebp,%ebx
+	movb	(%esi),%al
+	adcl	advancetable+4(,%ecx,4),%esi
+LEntry3_16:
+	movb	%al,14(%edi)
+	movb	(%esi),%al
+LEntry2_16:
+
+LEndSpan:
+
+//
+// clear s/z, t/z, 1/z from FP stack
+//
+	fstp %st(0)
+	fstp %st(0)
+	fstp %st(0)
+
+	movl	pspantemp,%ebx				// restore spans pointer
+	movl	espan_t_pnext(%ebx),%ebx	// point to next span
+	testl	%ebx,%ebx			// any more spans?
+	movb	%al,15(%edi)
+	jnz		LSpanLoop			// more spans
+
+	popl	%ebx				// restore register variables
+	popl	%esi
+	popl	%edi
+	popl	%ebp				// restore the caller's stack frame
+	ret
+
+#endif	// id386
--- /dev/null
+++ b/WinQuake/d_edge.c
@@ -1,0 +1,331 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// d_edge.c
+
+#include "quakedef.h"
+#include "d_local.h"
+
+static int	miplevel;
+
+float		scale_for_mip;
+int			screenwidth;
+int			ubasestep, errorterm, erroradjustup, erroradjustdown;
+int			vstartscan;
+
+// FIXME: should go away
+extern void			R_RotateBmodel (void);
+extern void			R_TransformFrustum (void);
+
+vec3_t		transformed_modelorg;
+
+/*
+==============
+D_DrawPoly
+
+==============
+*/
+void D_DrawPoly (void)
+{
+// this driver takes spans, not polygons
+}
+
+
+/*
+=============
+D_MipLevelForScale
+=============
+*/
+int D_MipLevelForScale (float scale)
+{
+	int		lmiplevel;
+
+	if (scale >= d_scalemip[0] )
+		lmiplevel = 0;
+	else if (scale >= d_scalemip[1] )
+		lmiplevel = 1;
+	else if (scale >= d_scalemip[2] )
+		lmiplevel = 2;
+	else
+		lmiplevel = 3;
+
+	if (lmiplevel < d_minmip)
+		lmiplevel = d_minmip;
+
+	return lmiplevel;
+}
+
+
+/*
+==============
+D_DrawSolidSurface
+==============
+*/
+
+// FIXME: clean this up
+
+void D_DrawSolidSurface (surf_t *surf, int color)
+{
+	espan_t	*span;
+	byte	*pdest;
+	int		u, u2, pix;
+	
+	pix = (color<<24) | (color<<16) | (color<<8) | color;
+	for (span=surf->spans ; span ; span=span->pnext)
+	{
+		pdest = (byte *)d_viewbuffer + screenwidth*span->v;
+		u = span->u;
+		u2 = span->u + span->count - 1;
+		((byte *)pdest)[u] = pix;
+
+		if (u2 - u < 8)
+		{
+			for (u++ ; u <= u2 ; u++)
+				((byte *)pdest)[u] = pix;
+		}
+		else
+		{
+			for (u++ ; u & 3 ; u++)
+				((byte *)pdest)[u] = pix;
+
+			u2 -= 4;
+			for ( ; u <= u2 ; u+=4)
+				*(int *)((byte *)pdest + u) = pix;
+			u2 += 4;
+			for ( ; u <= u2 ; u++)
+				((byte *)pdest)[u] = pix;
+		}
+	}
+}
+
+
+/*
+==============
+D_CalcGradients
+==============
+*/
+void D_CalcGradients (msurface_t *pface)
+{
+	mplane_t	*pplane;
+	float		mipscale;
+	vec3_t		p_temp1;
+	vec3_t		p_saxis, p_taxis;
+	float		t;
+
+	pplane = pface->plane;
+
+	mipscale = 1.0 / (float)(1 << miplevel);
+
+	TransformVector (pface->texinfo->vecs[0], p_saxis);
+	TransformVector (pface->texinfo->vecs[1], p_taxis);
+
+	t = xscaleinv * mipscale;
+	d_sdivzstepu = p_saxis[0] * t;
+	d_tdivzstepu = p_taxis[0] * t;
+
+	t = yscaleinv * mipscale;
+	d_sdivzstepv = -p_saxis[1] * t;
+	d_tdivzstepv = -p_taxis[1] * t;
+
+	d_sdivzorigin = p_saxis[2] * mipscale - xcenter * d_sdivzstepu -
+			ycenter * d_sdivzstepv;
+	d_tdivzorigin = p_taxis[2] * mipscale - xcenter * d_tdivzstepu -
+			ycenter * d_tdivzstepv;
+
+	VectorScale (transformed_modelorg, mipscale, p_temp1);
+
+	t = 0x10000*mipscale;
+	sadjust = ((fixed16_t)(DotProduct (p_temp1, p_saxis) * 0x10000 + 0.5)) -
+			((pface->texturemins[0] << 16) >> miplevel)
+			+ pface->texinfo->vecs[0][3]*t;
+	tadjust = ((fixed16_t)(DotProduct (p_temp1, p_taxis) * 0x10000 + 0.5)) -
+			((pface->texturemins[1] << 16) >> miplevel)
+			+ pface->texinfo->vecs[1][3]*t;
+
+//
+// -1 (-epsilon) so we never wander off the edge of the texture
+//
+	bbextents = ((pface->extents[0] << 16) >> miplevel) - 1;
+	bbextentt = ((pface->extents[1] << 16) >> miplevel) - 1;
+}
+
+
+/*
+==============
+D_DrawSurfaces
+==============
+*/
+void D_DrawSurfaces (void)
+{
+	surf_t			*s;
+	msurface_t		*pface;
+	surfcache_t		*pcurrentcache;
+	vec3_t			world_transformed_modelorg;
+	vec3_t			local_modelorg;
+
+	currententity = &cl_entities[0];
+	TransformVector (modelorg, transformed_modelorg);
+	VectorCopy (transformed_modelorg, world_transformed_modelorg);
+
+// TODO: could preset a lot of this at mode set time
+	if (r_drawflat.value)
+	{
+		for (s = &surfaces[1] ; s<surface_p ; s++)
+		{
+			if (!s->spans)
+				continue;
+
+			d_zistepu = s->d_zistepu;
+			d_zistepv = s->d_zistepv;
+			d_ziorigin = s->d_ziorigin;
+
+			D_DrawSolidSurface (s, (int)s->data & 0xFF);
+			D_DrawZSpans (s->spans);
+		}
+	}
+	else
+	{
+		for (s = &surfaces[1] ; s<surface_p ; s++)
+		{
+			if (!s->spans)
+				continue;
+
+			r_drawnpolycount++;
+
+			d_zistepu = s->d_zistepu;
+			d_zistepv = s->d_zistepv;
+			d_ziorigin = s->d_ziorigin;
+
+			if (s->flags & SURF_DRAWSKY)
+			{
+				if (!r_skymade)
+				{
+					R_MakeSky ();
+				}
+
+				D_DrawSkyScans8 (s->spans);
+				D_DrawZSpans (s->spans);
+			}
+			else if (s->flags & SURF_DRAWBACKGROUND)
+			{
+			// set up a gradient for the background surface that places it
+			// effectively at infinity distance from the viewpoint
+				d_zistepu = 0;
+				d_zistepv = 0;
+				d_ziorigin = -0.9;
+
+				D_DrawSolidSurface (s, (int)r_clearcolor.value & 0xFF);
+				D_DrawZSpans (s->spans);
+			}
+			else if (s->flags & SURF_DRAWTURB)
+			{
+				pface = s->data;
+				miplevel = 0;
+				cacheblock = (pixel_t *)
+						((byte *)pface->texinfo->texture +
+						pface->texinfo->texture->offsets[0]);
+				cachewidth = 64;
+
+				if (s->insubmodel)
+				{
+				// FIXME: we don't want to do all this for every polygon!
+				// TODO: store once at start of frame
+					currententity = s->entity;	//FIXME: make this passed in to
+												// R_RotateBmodel ()
+					VectorSubtract (r_origin, currententity->origin,
+							local_modelorg);
+					TransformVector (local_modelorg, transformed_modelorg);
+
+					R_RotateBmodel ();	// FIXME: don't mess with the frustum,
+										// make entity passed in
+				}
+
+				D_CalcGradients (pface);
+				Turbulent8 (s->spans);
+				D_DrawZSpans (s->spans);
+
+				if (s->insubmodel)
+				{
+				//
+				// restore the old drawing state
+				// FIXME: we don't want to do this every time!
+				// TODO: speed up
+				//
+					currententity = &cl_entities[0];
+					VectorCopy (world_transformed_modelorg,
+								transformed_modelorg);
+					VectorCopy (base_vpn, vpn);
+					VectorCopy (base_vup, vup);
+					VectorCopy (base_vright, vright);
+					VectorCopy (base_modelorg, modelorg);
+					R_TransformFrustum ();
+				}
+			}
+			else
+			{
+				if (s->insubmodel)
+				{
+				// FIXME: we don't want to do all this for every polygon!
+				// TODO: store once at start of frame
+					currententity = s->entity;	//FIXME: make this passed in to
+												// R_RotateBmodel ()
+					VectorSubtract (r_origin, currententity->origin, local_modelorg);
+					TransformVector (local_modelorg, transformed_modelorg);
+
+					R_RotateBmodel ();	// FIXME: don't mess with the frustum,
+										// make entity passed in
+				}
+
+				pface = s->data;
+				miplevel = D_MipLevelForScale (s->nearzi * scale_for_mip
+				* pface->texinfo->mipadjust);
+
+			// FIXME: make this passed in to D_CacheSurface
+				pcurrentcache = D_CacheSurface (pface, miplevel);
+
+				cacheblock = (pixel_t *)pcurrentcache->data;
+				cachewidth = pcurrentcache->width;
+
+				D_CalcGradients (pface);
+
+				(*d_drawspans) (s->spans);
+
+				D_DrawZSpans (s->spans);
+
+				if (s->insubmodel)
+				{
+				//
+				// restore the old drawing state
+				// FIXME: we don't want to do this every time!
+				// TODO: speed up
+				//
+					currententity = &cl_entities[0];
+					VectorCopy (world_transformed_modelorg,
+								transformed_modelorg);
+					VectorCopy (base_vpn, vpn);
+					VectorCopy (base_vup, vup);
+					VectorCopy (base_vright, vright);
+					VectorCopy (base_modelorg, modelorg);
+					R_TransformFrustum ();
+				}
+			}
+		}
+	}
+}
+
--- /dev/null
+++ b/WinQuake/d_fill.c
@@ -1,0 +1,88 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// d_clear: clears a specified rectangle to the specified color
+
+#include "quakedef.h"
+
+
+/*
+================
+D_FillRect
+================
+*/
+void D_FillRect (vrect_t *rect, int color)
+{
+	int				rx, ry, rwidth, rheight;
+	unsigned char	*dest;
+	unsigned		*ldest;
+
+	rx = rect->x;
+	ry = rect->y;
+	rwidth = rect->width;
+	rheight = rect->height;
+
+	if (rx < 0)
+	{
+		rwidth += rx;
+		rx = 0;
+	}
+	if (ry < 0)
+	{
+		rheight += ry;
+		ry = 0;
+	}
+	if (rx+rwidth > vid.width)
+		rwidth = vid.width - rx;
+	if (ry+rheight > vid.height)
+		rheight = vid.height - rx;
+		
+	if (rwidth < 1 || rheight < 1)
+		return;
+
+	dest = ((byte *)vid.buffer + ry*vid.rowbytes + rx);
+
+	if (((rwidth & 0x03) == 0) && (((long)dest & 0x03) == 0))
+	{
+	// faster aligned dword clear
+		ldest = (unsigned *)dest;
+		color += color << 16;
+
+		rwidth >>= 2;
+		color += color << 8;
+
+		for (ry=0 ; ry<rheight ; ry++)
+		{
+			for (rx=0 ; rx<rwidth ; rx++)
+				ldest[rx] = color;
+			ldest = (unsigned *)((byte*)ldest + vid.rowbytes);
+		}
+	}
+	else
+	{
+	// slower byte-by-byte clear for unaligned cases
+		for (ry=0 ; ry<rheight ; ry++)
+		{
+			for (rx=0 ; rx<rwidth ; rx++)
+				dest[rx] = color;
+			dest += vid.rowbytes;
+		}
+	}
+}
+
--- /dev/null
+++ b/WinQuake/d_iface.h
@@ -1,0 +1,229 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// d_iface.h: interface header file for rasterization driver modules
+
+#define WARP_WIDTH		320
+#define WARP_HEIGHT		200
+
+#define MAX_LBM_HEIGHT	480
+
+typedef struct
+{
+	float	u, v;
+	float	s, t;
+	float	zi;
+} emitpoint_t;
+
+typedef enum {
+	pt_static, pt_grav, pt_slowgrav, pt_fire, pt_explode, pt_explode2, pt_blob, pt_blob2
+} ptype_t;
+
+// !!! if this is changed, it must be changed in d_ifacea.h too !!!
+typedef struct particle_s
+{
+// driver-usable fields
+	vec3_t		org;
+	float		color;
+// drivers never touch the following fields
+	struct particle_s	*next;
+	vec3_t		vel;
+	float		ramp;
+	float		die;
+	ptype_t		type;
+} particle_t;
+
+#define PARTICLE_Z_CLIP	8.0
+
+typedef struct polyvert_s {
+	float	u, v, zi, s, t;
+} polyvert_t;
+
+typedef struct polydesc_s {
+	int			numverts;
+	float		nearzi;
+	msurface_t	*pcurrentface;
+	polyvert_t	*pverts;
+} polydesc_t;
+
+// !!! if this is changed, it must be changed in d_ifacea.h too !!!
+typedef struct finalvert_s {
+	int		v[6];		// u, v, s, t, l, 1/z
+	int		flags;
+	float	reserved;
+} finalvert_t;
+
+// !!! if this is changed, it must be changed in d_ifacea.h too !!!
+typedef struct
+{
+	void				*pskin;
+	maliasskindesc_t	*pskindesc;
+	int					skinwidth;
+	int					skinheight;
+	mtriangle_t			*ptriangles;
+	finalvert_t			*pfinalverts;
+	int					numtriangles;
+	int					drawtype;
+	int					seamfixupX16;
+} affinetridesc_t;
+
+// !!! if this is changed, it must be changed in d_ifacea.h too !!!
+typedef struct {
+	float	u, v, zi, color;
+} screenpart_t;
+
+typedef struct
+{
+	int			nump;
+	emitpoint_t	*pverts;	// there's room for an extra element at [nump], 
+							//  if the driver wants to duplicate element [0] at
+							//  element [nump] to avoid dealing with wrapping
+	mspriteframe_t	*pspriteframe;
+	vec3_t			vup, vright, vpn;	// in worldspace
+	float			nearzi;
+} spritedesc_t;
+
+typedef struct
+{
+	int		u, v;
+	float	zi;
+	int		color;
+} zpointdesc_t;
+
+extern cvar_t	r_drawflat;
+extern int		d_spanpixcount;
+extern int		r_framecount;		// sequence # of current frame since Quake
+									//  started
+extern qboolean	r_drawpolys;		// 1 if driver wants clipped polygons
+									//  rather than a span list
+extern qboolean	r_drawculledpolys;	// 1 if driver wants clipped polygons that
+									//  have been culled by the edge list
+extern qboolean	r_worldpolysbacktofront;	// 1 if driver wants polygons
+											//  delivered back to front rather
+											//  than front to back
+extern qboolean	r_recursiveaffinetriangles;	// true if a driver wants to use
+											//  recursive triangular subdivison
+											//  and vertex drawing via
+											//  D_PolysetDrawFinalVerts() past
+											//  a certain distance (normally 
+											//  only used by the software
+											//  driver)
+extern float	r_aliasuvscale;		// scale-up factor for screen u and v
+									//  on Alias vertices passed to driver
+extern int		r_pixbytes;
+extern qboolean	r_dowarp;
+
+extern affinetridesc_t	r_affinetridesc;
+extern spritedesc_t		r_spritedesc;
+extern zpointdesc_t		r_zpointdesc;
+extern polydesc_t		r_polydesc;
+
+extern int		d_con_indirect;	// if 0, Quake will draw console directly
+								//  to vid.buffer; if 1, Quake will
+								//  draw console via D_DrawRect. Must be
+								//  defined by driver
+
+extern vec3_t	r_pright, r_pup, r_ppn;
+
+
+void D_Aff8Patch (void *pcolormap);
+void D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height);
+void D_DisableBackBufferAccess (void);
+void D_EndDirectRect (int x, int y, int width, int height);
+void D_PolysetDraw (void);
+void D_PolysetDrawFinalVerts (finalvert_t *fv, int numverts);
+void D_DrawParticle (particle_t *pparticle);
+void D_DrawPoly (void);
+void D_DrawSprite (void);
+void D_DrawSurfaces (void);
+void D_DrawZPoint (void);
+void D_EnableBackBufferAccess (void);
+void D_EndParticles (void);
+void D_Init (void);
+void D_ViewChanged (void);
+void D_SetupFrame (void);
+void D_StartParticles (void);
+void D_TurnZOn (void);
+void D_WarpScreen (void);
+
+void D_FillRect (vrect_t *vrect, int color);
+void D_DrawRect (void);
+void D_UpdateRects (vrect_t *prect);
+
+// currently for internal use only, and should be a do-nothing function in
+// hardware drivers
+// FIXME: this should go away
+void D_PolysetUpdateTables (void);
+
+// these are currently for internal use only, and should not be used by drivers
+extern int				r_skydirect;
+extern byte				*r_skysource;
+
+// transparency types for D_DrawRect ()
+#define DR_SOLID		0
+#define DR_TRANSPARENT	1
+
+// !!! must be kept the same as in quakeasm.h !!!
+#define TRANSPARENT_COLOR	0xFF
+
+extern void *acolormap;	// FIXME: should go away
+
+//=======================================================================//
+
+// callbacks to Quake
+
+typedef struct
+{
+	pixel_t		*surfdat;	// destination for generated surface
+	int			rowbytes;	// destination logical width in bytes
+	msurface_t	*surf;		// description for surface to generate
+	fixed8_t	lightadj[MAXLIGHTMAPS];
+							// adjust for lightmap levels for dynamic lighting
+	texture_t	*texture;	// corrected for animating textures
+	int			surfmip;	// mipmapped ratio of surface texels / world pixels
+	int			surfwidth;	// in mipmapped texels
+	int			surfheight;	// in mipmapped texels
+} drawsurf_t;
+
+extern drawsurf_t	r_drawsurf;
+
+void R_DrawSurface (void);
+void R_GenTile (msurface_t *psurf, void *pdest);
+
+
+// !!! if this is changed, it must be changed in d_ifacea.h too !!!
+#define TURB_TEX_SIZE	64		// base turbulent texture size
+
+// !!! if this is changed, it must be changed in d_ifacea.h too !!!
+#define	CYCLE			128		// turbulent cycle size
+
+#define TILE_SIZE		128		// size of textures generated by R_GenTiledSurf
+
+#define SKYSHIFT		7
+#define	SKYSIZE			(1 << SKYSHIFT)
+#define SKYMASK			(SKYSIZE - 1)
+
+extern float	skyspeed, skyspeed2;
+extern float	skytime;
+
+extern int		c_surf;
+extern vrect_t	scr_vrect;
+
+extern byte		*r_warpbuffer;
+
--- /dev/null
+++ b/WinQuake/d_ifacea.h
@@ -1,0 +1,98 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+//
+// d_ifacea.h
+//
+// Include file for asm driver interface.
+//
+
+//
+// !!! note that this file must match the corresponding C structures in
+// d_iface.h at all times !!!
+//
+
+// !!! if this is changed, it must be changed in r_shared.h too !!!
+#define ALIAS_ONSEAM				0x0020
+
+// !!! if this is changed, it must be changed in d_iface.h too !!!
+#define TURB_TEX_SIZE	64		// base turbulent texture size
+
+// !!! if this is changed, it must be changed in d_iface.h too !!!
+#define	CYCLE	128
+
+// !!! if this is changed, it must be changed in r_shared.h too !!!
+#define	MAXHEIGHT	1024
+
+// !!! if this is changed, it must be changed in quakedef.h too !!!
+#define CACHE_SIZE	32		// used to align key data structures
+
+// particle_t structure
+// !!! if this is changed, it must be changed in d_iface.h too !!!
+// driver-usable fields
+#define pt_org				0
+#define pt_color			12
+// drivers never touch the following fields
+#define pt_next				16
+#define pt_vel				20
+#define pt_ramp				32
+#define pt_die				36
+#define pt_type				40
+#define pt_size				44
+
+#define PARTICLE_Z_CLIP	8.0
+
+// finalvert_t structure
+// !!! if this is changed, it must be changed in d_iface.h too !!!
+#define fv_v				0	// !!! if this is moved, cases where the !!!
+								// !!! address of this field is pushed in !!!
+								// !!! d_polysa.s must be changed !!!
+#define fv_flags			24
+#define fv_reserved			28
+#define fv_size				32
+#define fv_shift			5
+
+
+// stvert_t structure
+// !!! if this is changed, it must be changed in modelgen.h too !!!
+#define stv_onseam	0
+#define stv_s		4
+#define stv_t		8
+#define stv_size	12
+
+
+// trivertx_t structure
+// !!! if this is changed, it must be changed in modelgen.h too !!!
+#define tv_v				0
+#define tv_lightnormalindex	3
+#define tv_size				4
+
+// affinetridesc_t structure
+// !!! if this is changed, it must be changed in d_iface.h too !!!
+#define atd_pskin			0
+#define atd_pskindesc		4
+#define atd_skinwidth		8
+#define atd_skinheight		12
+#define atd_ptriangles		16
+#define atd_pfinalverts		20
+#define atd_numtriangles	24
+#define atd_drawtype		28
+#define atd_seamfixupX16	32
+#define atd_size			36
+
--- /dev/null
+++ b/WinQuake/d_init.c
@@ -1,0 +1,173 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// d_init.c: rasterization driver initialization
+
+#include "quakedef.h"
+#include "d_local.h"
+
+#define NUM_MIPS	4
+
+cvar_t	d_subdiv16 = {"d_subdiv16", "1"};
+cvar_t	d_mipcap = {"d_mipcap", "0"};
+cvar_t	d_mipscale = {"d_mipscale", "1"};
+
+surfcache_t		*d_initial_rover;
+qboolean		d_roverwrapped;
+int				d_minmip;
+float			d_scalemip[NUM_MIPS-1];
+
+static float	basemip[NUM_MIPS-1] = {1.0, 0.5*0.8, 0.25*0.8};
+
+extern int			d_aflatcolor;
+
+void (*d_drawspans) (espan_t *pspan);
+
+
+/*
+===============
+D_Init
+===============
+*/
+void D_Init (void)
+{
+
+	r_skydirect = 1;
+
+	Cvar_RegisterVariable (&d_subdiv16);
+	Cvar_RegisterVariable (&d_mipcap);
+	Cvar_RegisterVariable (&d_mipscale);
+
+	r_drawpolys = false;
+	r_worldpolysbacktofront = false;
+	r_recursiveaffinetriangles = true;
+	r_pixbytes = 1;
+	r_aliasuvscale = 1.0;
+}
+
+
+/*
+===============
+D_CopyRects
+===============
+*/
+void D_CopyRects (vrect_t *prects, int transparent)
+{
+
+// this function is only required if the CPU doesn't have direct access to the
+// back buffer, and there's some driver interface function that the driver
+// doesn't support and requires Quake to do in software (such as drawing the
+// console); Quake will then draw into wherever the driver points vid.buffer
+// and will call this function before swapping buffers
+
+	UNUSED(prects);
+	UNUSED(transparent);
+}
+
+
+/*
+===============
+D_EnableBackBufferAccess
+===============
+*/
+void D_EnableBackBufferAccess (void)
+{
+	VID_LockBuffer ();
+}
+
+
+/*
+===============
+D_TurnZOn
+===============
+*/
+void D_TurnZOn (void)
+{
+// not needed for software version
+}
+
+
+/*
+===============
+D_DisableBackBufferAccess
+===============
+*/
+void D_DisableBackBufferAccess (void)
+{
+	VID_UnlockBuffer ();
+}
+
+
+/*
+===============
+D_SetupFrame
+===============
+*/
+void D_SetupFrame (void)
+{
+	int		i;
+
+	if (r_dowarp)
+		d_viewbuffer = r_warpbuffer;
+	else
+		d_viewbuffer = (void *)(byte *)vid.buffer;
+
+	if (r_dowarp)
+		screenwidth = WARP_WIDTH;
+	else
+		screenwidth = vid.rowbytes;
+
+	d_roverwrapped = false;
+	d_initial_rover = sc_rover;
+
+	d_minmip = d_mipcap.value;
+	if (d_minmip > 3)
+		d_minmip = 3;
+	else if (d_minmip < 0)
+		d_minmip = 0;
+
+	for (i=0 ; i<(NUM_MIPS-1) ; i++)
+		d_scalemip[i] = basemip[i] * d_mipscale.value;
+
+#if	id386
+				if (d_subdiv16.value)
+					d_drawspans = D_DrawSpans16;
+				else
+					d_drawspans = D_DrawSpans8;
+#else
+				d_drawspans = D_DrawSpans8;
+#endif
+
+	d_aflatcolor = 0;
+}
+
+
+/*
+===============
+D_UpdateRects
+===============
+*/
+void D_UpdateRects (vrect_t *prect)
+{
+
+// the software driver draws these directly to the vid buffer
+
+	UNUSED(prect);
+}
+
--- /dev/null
+++ b/WinQuake/d_local.h
@@ -1,0 +1,111 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// d_local.h:  private rasterization driver defs
+
+#include "r_shared.h"
+
+//
+// TODO: fine-tune this; it's based on providing some overage even if there
+// is a 2k-wide scan, with subdivision every 8, for 256 spans of 12 bytes each
+//
+#define SCANBUFFERPAD		0x1000
+
+#define R_SKY_SMASK	0x007F0000
+#define R_SKY_TMASK	0x007F0000
+
+#define DS_SPAN_LIST_END	-128
+
+#define SURFCACHE_SIZE_AT_320X200	600*1024
+
+typedef struct surfcache_s
+{
+	struct surfcache_s	*next;
+	struct surfcache_s 	**owner;		// NULL is an empty chunk of memory
+	int					lightadj[MAXLIGHTMAPS]; // checked for strobe flush
+	int					dlight;
+	int					size;		// including header
+	unsigned			width;
+	unsigned			height;		// DEBUG only needed for debug
+	float				mipscale;
+	struct texture_s	*texture;	// checked for animating textures
+	byte				data[4];	// width*height elements
+} surfcache_t;
+
+// !!! if this is changed, it must be changed in asm_draw.h too !!!
+typedef struct sspan_s
+{
+	int				u, v, count;
+} sspan_t;
+
+extern cvar_t	d_subdiv16;
+
+extern float	scale_for_mip;
+
+extern qboolean		d_roverwrapped;
+extern surfcache_t	*sc_rover;
+extern surfcache_t	*d_initial_rover;
+
+extern float	d_sdivzstepu, d_tdivzstepu, d_zistepu;
+extern float	d_sdivzstepv, d_tdivzstepv, d_zistepv;
+extern float	d_sdivzorigin, d_tdivzorigin, d_ziorigin;
+
+fixed16_t	sadjust, tadjust;
+fixed16_t	bbextents, bbextentt;
+
+
+void D_DrawSpans8 (espan_t *pspans);
+void D_DrawSpans16 (espan_t *pspans);
+void D_DrawZSpans (espan_t *pspans);
+void Turbulent8 (espan_t *pspan);
+void D_SpriteDrawSpans (sspan_t *pspan);
+
+void D_DrawSkyScans8 (espan_t *pspan);
+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);
+
+#if id386
+extern void D_PolysetAff8Start (void);
+extern void D_PolysetAff8End (void);
+#endif
+
+extern short *d_pzbuffer;
+extern unsigned int d_zrowbytes, d_zwidth;
+
+extern int	*d_pscantable;
+extern int	d_scantable[MAXHEIGHT];
+
+extern int	d_vrectx, d_vrecty, d_vrectright_particle, d_vrectbottom_particle;
+
+extern int	d_y_aspect_shift, d_pix_min, d_pix_max, d_pix_shift;
+
+extern pixel_t	*d_viewbuffer;
+
+extern short	*zspantable[MAXHEIGHT];
+
+extern int		d_minmip;
+extern float	d_scalemip[3];
+
+extern void (*d_drawspans) (espan_t *pspan);
+
--- /dev/null
+++ b/WinQuake/d_modech.c
@@ -1,0 +1,107 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// d_modech.c: called when mode has just changed
+
+#include "quakedef.h"
+#include "d_local.h"
+
+int	d_vrectx, d_vrecty, d_vrectright_particle, d_vrectbottom_particle;
+
+int	d_y_aspect_shift, d_pix_min, d_pix_max, d_pix_shift;
+
+int		d_scantable[MAXHEIGHT];
+short	*zspantable[MAXHEIGHT]; 
+
+/*
+================
+D_Patch
+================
+*/
+void D_Patch (void)
+{
+#if id386
+
+	static qboolean protectset8 = false;
+
+	if (!protectset8)
+	{
+		Sys_MakeCodeWriteable ((int)D_PolysetAff8Start,
+						     (int)D_PolysetAff8End - (int)D_PolysetAff8Start);
+		protectset8 = true;
+	}
+
+#endif	// id386
+}
+
+
+/*
+================
+D_ViewChanged
+================
+*/
+void D_ViewChanged (void)
+{
+	int rowbytes;
+
+	if (r_dowarp)
+		rowbytes = WARP_WIDTH;
+	else
+		rowbytes = vid.rowbytes;
+
+	scale_for_mip = xscale;
+	if (yscale > xscale)
+		scale_for_mip = yscale;
+
+	d_zrowbytes = vid.width * 2;
+	d_zwidth = vid.width;
+
+	d_pix_min = r_refdef.vrect.width / 320;
+	if (d_pix_min < 1)
+		d_pix_min = 1;
+
+	d_pix_max = (int)((float)r_refdef.vrect.width / (320.0 / 4.0) + 0.5);
+	d_pix_shift = 8 - (int)((float)r_refdef.vrect.width / 320.0 + 0.5);
+	if (d_pix_max < 1)
+		d_pix_max = 1;
+
+	if (pixelAspect > 1.4)
+		d_y_aspect_shift = 1;
+	else
+		d_y_aspect_shift = 0;
+
+	d_vrectx = r_refdef.vrect.x;
+	d_vrecty = r_refdef.vrect.y;
+	d_vrectright_particle = r_refdef.vrectright - d_pix_max;
+	d_vrectbottom_particle =
+			r_refdef.vrectbottom - (d_pix_max << d_y_aspect_shift);
+
+	{
+		int		i;
+
+		for (i=0 ; i<vid.height; i++)
+		{
+			d_scantable[i] = i*rowbytes;
+			zspantable[i] = d_pzbuffer + i*d_zwidth;
+		}
+	}
+
+	D_Patch ();
+}
+
--- /dev/null
+++ b/WinQuake/d_part.c
@@ -1,0 +1,207 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// d_part.c: software driver module for drawing particles
+
+#include "quakedef.h"
+#include "d_local.h"
+
+
+/*
+==============
+D_EndParticles
+==============
+*/
+void D_EndParticles (void)
+{
+// not used by software driver
+}
+
+
+/*
+==============
+D_StartParticles
+==============
+*/
+void D_StartParticles (void)
+{
+// not used by software driver
+}
+
+
+#if	!id386
+
+/*
+==============
+D_DrawParticle
+==============
+*/
+void D_DrawParticle (particle_t *pparticle)
+{
+	vec3_t	local, transformed;
+	float	zi;
+	byte	*pdest;
+	short	*pz;
+	int		i, izi, pix, count, u, v;
+
+// transform point
+	VectorSubtract (pparticle->org, r_origin, local);
+
+	transformed[0] = DotProduct(local, r_pright);
+	transformed[1] = DotProduct(local, r_pup);
+	transformed[2] = DotProduct(local, r_ppn);		
+
+	if (transformed[2] < PARTICLE_Z_CLIP)
+		return;
+
+// project the point
+// FIXME: preadjust xcenter and ycenter
+	zi = 1.0 / transformed[2];
+	u = (int)(xcenter + zi * transformed[0] + 0.5);
+	v = (int)(ycenter - zi * transformed[1] + 0.5);
+
+	if ((v > d_vrectbottom_particle) || 
+		(u > d_vrectright_particle) ||
+		(v < d_vrecty) ||
+		(u < d_vrectx))
+	{
+		return;
+	}
+
+	pz = d_pzbuffer + (d_zwidth * v) + u;
+	pdest = d_viewbuffer + d_scantable[v] + u;
+	izi = (int)(zi * 0x8000);
+
+	pix = izi >> d_pix_shift;
+
+	if (pix < d_pix_min)
+		pix = d_pix_min;
+	else if (pix > d_pix_max)
+		pix = d_pix_max;
+
+	switch (pix)
+	{
+	case 1:
+		count = 1 << d_y_aspect_shift;
+
+		for ( ; count ; count--, pz += d_zwidth, pdest += screenwidth)
+		{
+			if (pz[0] <= izi)
+			{
+				pz[0] = izi;
+				pdest[0] = pparticle->color;
+			}
+		}
+		break;
+
+	case 2:
+		count = 2 << d_y_aspect_shift;
+
+		for ( ; count ; count--, pz += d_zwidth, pdest += screenwidth)
+		{
+			if (pz[0] <= izi)
+			{
+				pz[0] = izi;
+				pdest[0] = pparticle->color;
+			}
+
+			if (pz[1] <= izi)
+			{
+				pz[1] = izi;
+				pdest[1] = pparticle->color;
+			}
+		}
+		break;
+
+	case 3:
+		count = 3 << d_y_aspect_shift;
+
+		for ( ; count ; count--, pz += d_zwidth, pdest += screenwidth)
+		{
+			if (pz[0] <= izi)
+			{
+				pz[0] = izi;
+				pdest[0] = pparticle->color;
+			}
+
+			if (pz[1] <= izi)
+			{
+				pz[1] = izi;
+				pdest[1] = pparticle->color;
+			}
+
+			if (pz[2] <= izi)
+			{
+				pz[2] = izi;
+				pdest[2] = pparticle->color;
+			}
+		}
+		break;
+
+	case 4:
+		count = 4 << d_y_aspect_shift;
+
+		for ( ; count ; count--, pz += d_zwidth, pdest += screenwidth)
+		{
+			if (pz[0] <= izi)
+			{
+				pz[0] = izi;
+				pdest[0] = pparticle->color;
+			}
+
+			if (pz[1] <= izi)
+			{
+				pz[1] = izi;
+				pdest[1] = pparticle->color;
+			}
+
+			if (pz[2] <= izi)
+			{
+				pz[2] = izi;
+				pdest[2] = pparticle->color;
+			}
+
+			if (pz[3] <= izi)
+			{
+				pz[3] = izi;
+				pdest[3] = pparticle->color;
+			}
+		}
+		break;
+
+	default:
+		count = pix << d_y_aspect_shift;
+
+		for ( ; count ; count--, pz += d_zwidth, pdest += screenwidth)
+		{
+			for (i=0 ; i<pix ; i++)
+			{
+				if (pz[i] <= izi)
+				{
+					pz[i] = izi;
+					pdest[i] = pparticle->color;
+				}
+			}
+		}
+		break;
+	}
+}
+
+#endif	// !id386
+
--- /dev/null
+++ b/WinQuake/d_parta.s
@@ -1,0 +1,477 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+//
+// d_parta.s
+// x86 assembly-language 8-bpp particle-drawing code.
+//
+
+#include "asm_i386.h"
+#include "quakeasm.h"
+#include "d_ifacea.h"
+#include "asm_draw.h"
+
+#if	id386
+
+//----------------------------------------------------------------------
+// 8-bpp particle drawing code.
+//----------------------------------------------------------------------
+
+//FIXME: comments, full optimization
+
+//----------------------------------------------------------------------
+// 8-bpp particle queueing code.
+//----------------------------------------------------------------------
+
+	.text
+
+#define P	12+4
+
+	.align 4
+.globl C(D_DrawParticle)
+C(D_DrawParticle):
+	pushl	%ebp				// preserve caller's stack frame
+	pushl	%edi				// preserve register variables
+	pushl	%ebx
+
+	movl	P(%esp),%edi
+
+// FIXME: better FP overlap in general here
+
+// transform point
+//	VectorSubtract (p->org, r_origin, local);
+	flds	C(r_origin)
+	fsubrs	pt_org(%edi)
+	flds	pt_org+4(%edi)
+	fsubs	C(r_origin)+4
+	flds	pt_org+8(%edi)
+	fsubs	C(r_origin)+8
+	fxch	%st(2)			// local[0] | local[1] | local[2]
+
+//	transformed[2] = DotProduct(local, r_ppn);		
+	flds	C(r_ppn)		// r_ppn[0] | local[0] | local[1] | local[2]
+	fmul	%st(1),%st(0)	// dot0 | local[0] | local[1] | local[2]
+	flds	C(r_ppn)+4	// r_ppn[1] | dot0 | local[0] | local[1] | local[2]
+	fmul	%st(3),%st(0)	// dot1 | dot0 | local[0] | local[1] | local[2]
+	flds	C(r_ppn)+8	// r_ppn[2] | dot1 | dot0 | local[0] |
+						//  local[1] | local[2]
+	fmul	%st(5),%st(0)	// dot2 | dot1 | dot0 | local[0] | local[1] | local[2]
+	fxch	%st(2)		// dot0 | dot1 | dot2 | local[0] | local[1] | local[2]
+	faddp	%st(0),%st(1) // dot0 + dot1 | dot2 | local[0] | local[1] |
+						  //  local[2]
+	faddp	%st(0),%st(1) // z | local[0] | local[1] | local[2]
+	fld		%st(0)		// z | z | local[0] | local[1] |
+						//  local[2]
+	fdivrs	float_1		// 1/z | z | local[0] | local[1] | local[2]
+	fxch	%st(1)		// z | 1/z | local[0] | local[1] | local[2]
+
+//	if (transformed[2] < PARTICLE_Z_CLIP)
+//		return;
+	fcomps	float_particle_z_clip	// 1/z | local[0] | local[1] | local[2]
+	fxch	%st(3)					// local[2] | local[0] | local[1] | 1/z
+
+	flds	C(r_pup)	// r_pup[0] | local[2] | local[0] | local[1] | 1/z
+	fmul	%st(2),%st(0)	// dot0 | local[2] | local[0] | local[1] | 1/z 
+	flds	C(r_pup)+4	// r_pup[1] | dot0 | local[2] | local[0] |
+						//  local[1] | 1/z 
+
+	fnstsw	%ax
+	testb	$1,%ah
+	jnz		LPop6AndDone
+
+//	transformed[1] = DotProduct(local, r_pup);
+	fmul	%st(4),%st(0)	// dot1 | dot0 | local[2] | local[0] | local[1] | 1/z 
+	flds	C(r_pup)+8	// r_pup[2] | dot1 | dot0 | local[2] |
+						//  local[0] | local[1] | 1/z 
+	fmul	%st(3),%st(0)	// dot2 | dot1 | dot0 | local[2] | local[0] |
+						//  local[1] | 1/z 
+	fxch	%st(2)		// dot0 | dot1 | dot2 | local[2] | local[0] |
+						//  local[1] | 1/z 
+	faddp	%st(0),%st(1) // dot0 + dot1 | dot2 | local[2] | local[0] |
+						//  local[1] | 1/z 
+	faddp	%st(0),%st(1) // y | local[2] | local[0] | local[1] | 1/z 
+	fxch	%st(3)		// local[1] | local[2] | local[0] | y | 1/z 
+
+//	transformed[0] = DotProduct(local, r_pright);
+	fmuls	C(r_pright)+4	// dot1 | local[2] | local[0] | y | 1/z
+	fxch	%st(2)		// local[0] | local[2] | dot1 | y | 1/z
+	fmuls	C(r_pright)	// dot0 | local[2] | dot1 | y | 1/z
+	fxch	%st(1)		// local[2] | dot0 | dot1 | y | 1/z
+	fmuls	C(r_pright)+8	// dot2 | dot0 | dot1 | y | 1/z
+	fxch	%st(2)		// dot1 | dot0 | dot2 | y | 1/z
+	faddp	%st(0),%st(1) // dot1 + dot0 | dot2 | y | 1/z
+
+	faddp	%st(0),%st(1)	// x | y | 1/z
+	fxch	%st(1)			// y | x | 1/z
+
+// project the point
+	fmul	%st(2),%st(0)	// y/z | x | 1/z
+	fxch	%st(1)			// x | y/z | 1/z
+	fmul	%st(2),%st(0)	// x/z | y/z | 1/z
+	fxch	%st(1)			// y/z | x/z | 1/z
+	fsubrs	C(ycenter)		// v | x/z | 1/z
+	fxch	%st(1)			// x/z | v | 1/z
+	fadds	C(xcenter)		// u | v | 1/z
+// FIXME: preadjust xcenter and ycenter
+	fxch	%st(1)			// v | u | 1/z
+	fadds	float_point5	// v | u | 1/z
+	fxch	%st(1)			// u | v | 1/z
+	fadds	float_point5	// u | v | 1/z
+	fxch	%st(2)			// 1/z | v | u
+	fmuls	DP_32768		// 1/z * 0x8000 | v | u
+	fxch	%st(2)			// u | v | 1/z * 0x8000
+
+// FIXME: use Terje's fp->int trick here?
+// FIXME: check we're getting proper rounding here
+	fistpl	DP_u			// v | 1/z * 0x8000
+	fistpl	DP_v			// 1/z * 0x8000
+
+	movl	DP_u,%eax
+	movl	DP_v,%edx
+
+// if ((v > d_vrectbottom_particle) || 
+// 	(u > d_vrectright_particle) ||
+// 	(v < d_vrecty) ||
+// 	(u < d_vrectx))
+// {
+// 	continue;
+// }
+
+	movl	C(d_vrectbottom_particle),%ebx
+	movl	C(d_vrectright_particle),%ecx
+	cmpl	%ebx,%edx
+	jg		LPop1AndDone
+	cmpl	%ecx,%eax
+	jg		LPop1AndDone
+	movl	C(d_vrecty),%ebx
+	movl	C(d_vrectx),%ecx
+	cmpl	%ebx,%edx
+	jl		LPop1AndDone
+
+	cmpl	%ecx,%eax
+	jl		LPop1AndDone
+
+	flds	pt_color(%edi)	// color | 1/z * 0x8000
+// FIXME: use Terje's fast fp->int trick?
+	fistpl	DP_Color		// 1/z * 0x8000
+
+	movl	C(d_viewbuffer),%ebx
+
+	addl	%eax,%ebx
+	movl	C(d_scantable)(,%edx,4),%edi		// point to the pixel
+
+	imull	C(d_zrowbytes),%edx		// point to the z pixel
+
+	leal	(%edx,%eax,2),%edx
+	movl	C(d_pzbuffer),%eax
+
+	fistpl	izi
+
+	addl	%ebx,%edi
+	addl	%eax,%edx
+
+// pix = izi >> d_pix_shift;
+
+	movl	izi,%eax
+	movl	C(d_pix_shift),%ecx
+	shrl	%cl,%eax
+	movl	izi,%ebp
+
+// if (pix < d_pix_min)
+// 		pix = d_pix_min;
+// else if (pix > d_pix_max)
+//  	pix = d_pix_max;
+
+	movl	C(d_pix_min),%ebx
+	movl	C(d_pix_max),%ecx
+	cmpl	%ebx,%eax
+	jnl		LTestPixMax
+	movl	%ebx,%eax
+	jmp		LTestDone
+
+LTestPixMax:
+	cmpl	%ecx,%eax
+	jng		LTestDone
+	movl	%ecx,%eax
+LTestDone:
+
+	movb	DP_Color,%ch
+
+	movl	C(d_y_aspect_shift),%ebx
+	testl	%ebx,%ebx
+	jnz		LDefault
+
+	cmpl	$4,%eax
+	ja		LDefault
+
+	jmp		DP_EntryTable-4(,%eax,4)
+
+// 1x1
+.globl	DP_1x1
+DP_1x1:
+	cmpw	%bp,(%edx)		// just one pixel to do
+	jg		LDone
+	movw	%bp,(%edx)
+	movb	%ch,(%edi)
+	jmp		LDone
+
+// 2x2
+.globl	DP_2x2
+DP_2x2:
+	pushl	%esi
+	movl	C(screenwidth),%ebx
+	movl	C(d_zrowbytes),%esi
+
+	cmpw	%bp,(%edx)
+	jg		L2x2_1
+	movw	%bp,(%edx)
+	movb	%ch,(%edi)
+L2x2_1:
+	cmpw	%bp,2(%edx)
+	jg		L2x2_2
+	movw	%bp,2(%edx)
+	movb	%ch,1(%edi)
+L2x2_2:
+	cmpw	%bp,(%edx,%esi,1)
+	jg		L2x2_3
+	movw	%bp,(%edx,%esi,1)
+	movb	%ch,(%edi,%ebx,1)
+L2x2_3:
+	cmpw	%bp,2(%edx,%esi,1)
+	jg		L2x2_4
+	movw	%bp,2(%edx,%esi,1)
+	movb	%ch,1(%edi,%ebx,1)
+L2x2_4:
+
+	popl	%esi
+	jmp		LDone
+
+// 3x3
+.globl	DP_3x3
+DP_3x3:
+	pushl	%esi
+	movl	C(screenwidth),%ebx
+	movl	C(d_zrowbytes),%esi
+
+	cmpw	%bp,(%edx)
+	jg		L3x3_1
+	movw	%bp,(%edx)
+	movb	%ch,(%edi)
+L3x3_1:
+	cmpw	%bp,2(%edx)
+	jg		L3x3_2
+	movw	%bp,2(%edx)
+	movb	%ch,1(%edi)
+L3x3_2:
+	cmpw	%bp,4(%edx)
+	jg		L3x3_3
+	movw	%bp,4(%edx)
+	movb	%ch,2(%edi)
+L3x3_3:
+
+	cmpw	%bp,(%edx,%esi,1)
+	jg		L3x3_4
+	movw	%bp,(%edx,%esi,1)
+	movb	%ch,(%edi,%ebx,1)
+L3x3_4:
+	cmpw	%bp,2(%edx,%esi,1)
+	jg		L3x3_5
+	movw	%bp,2(%edx,%esi,1)
+	movb	%ch,1(%edi,%ebx,1)
+L3x3_5:
+	cmpw	%bp,4(%edx,%esi,1)
+	jg		L3x3_6
+	movw	%bp,4(%edx,%esi,1)
+	movb	%ch,2(%edi,%ebx,1)
+L3x3_6:
+
+	cmpw	%bp,(%edx,%esi,2)
+	jg		L3x3_7
+	movw	%bp,(%edx,%esi,2)
+	movb	%ch,(%edi,%ebx,2)
+L3x3_7:
+	cmpw	%bp,2(%edx,%esi,2)
+	jg		L3x3_8
+	movw	%bp,2(%edx,%esi,2)
+	movb	%ch,1(%edi,%ebx,2)
+L3x3_8:
+	cmpw	%bp,4(%edx,%esi,2)
+	jg		L3x3_9
+	movw	%bp,4(%edx,%esi,2)
+	movb	%ch,2(%edi,%ebx,2)
+L3x3_9:
+
+	popl	%esi
+	jmp		LDone
+
+
+// 4x4
+.globl	DP_4x4
+DP_4x4:
+	pushl	%esi
+	movl	C(screenwidth),%ebx
+	movl	C(d_zrowbytes),%esi
+
+	cmpw	%bp,(%edx)
+	jg		L4x4_1
+	movw	%bp,(%edx)
+	movb	%ch,(%edi)
+L4x4_1:
+	cmpw	%bp,2(%edx)
+	jg		L4x4_2
+	movw	%bp,2(%edx)
+	movb	%ch,1(%edi)
+L4x4_2:
+	cmpw	%bp,4(%edx)
+	jg		L4x4_3
+	movw	%bp,4(%edx)
+	movb	%ch,2(%edi)
+L4x4_3:
+	cmpw	%bp,6(%edx)
+	jg		L4x4_4
+	movw	%bp,6(%edx)
+	movb	%ch,3(%edi)
+L4x4_4:
+
+	cmpw	%bp,(%edx,%esi,1)
+	jg		L4x4_5
+	movw	%bp,(%edx,%esi,1)
+	movb	%ch,(%edi,%ebx,1)
+L4x4_5:
+	cmpw	%bp,2(%edx,%esi,1)
+	jg		L4x4_6
+	movw	%bp,2(%edx,%esi,1)
+	movb	%ch,1(%edi,%ebx,1)
+L4x4_6:
+	cmpw	%bp,4(%edx,%esi,1)
+	jg		L4x4_7
+	movw	%bp,4(%edx,%esi,1)
+	movb	%ch,2(%edi,%ebx,1)
+L4x4_7:
+	cmpw	%bp,6(%edx,%esi,1)
+	jg		L4x4_8
+	movw	%bp,6(%edx,%esi,1)
+	movb	%ch,3(%edi,%ebx,1)
+L4x4_8:
+
+	leal	(%edx,%esi,2),%edx
+	leal	(%edi,%ebx,2),%edi
+
+	cmpw	%bp,(%edx)
+	jg		L4x4_9
+	movw	%bp,(%edx)
+	movb	%ch,(%edi)
+L4x4_9:
+	cmpw	%bp,2(%edx)
+	jg		L4x4_10
+	movw	%bp,2(%edx)
+	movb	%ch,1(%edi)
+L4x4_10:
+	cmpw	%bp,4(%edx)
+	jg		L4x4_11
+	movw	%bp,4(%edx)
+	movb	%ch,2(%edi)
+L4x4_11:
+	cmpw	%bp,6(%edx)
+	jg		L4x4_12
+	movw	%bp,6(%edx)
+	movb	%ch,3(%edi)
+L4x4_12:
+
+	cmpw	%bp,(%edx,%esi,1)
+	jg		L4x4_13
+	movw	%bp,(%edx,%esi,1)
+	movb	%ch,(%edi,%ebx,1)
+L4x4_13:
+	cmpw	%bp,2(%edx,%esi,1)
+	jg		L4x4_14
+	movw	%bp,2(%edx,%esi,1)
+	movb	%ch,1(%edi,%ebx,1)
+L4x4_14:
+	cmpw	%bp,4(%edx,%esi,1)
+	jg		L4x4_15
+	movw	%bp,4(%edx,%esi,1)
+	movb	%ch,2(%edi,%ebx,1)
+L4x4_15:
+	cmpw	%bp,6(%edx,%esi,1)
+	jg		L4x4_16
+	movw	%bp,6(%edx,%esi,1)
+	movb	%ch,3(%edi,%ebx,1)
+L4x4_16:
+
+	popl	%esi
+	jmp		LDone
+
+// default case, handling any size particle
+LDefault:
+
+// count = pix << d_y_aspect_shift;
+
+	movl	%eax,%ebx
+	movl	%eax,DP_Pix
+	movb	C(d_y_aspect_shift),%cl
+	shll	%cl,%ebx
+
+// for ( ; count ; count--, pz += d_zwidth, pdest += screenwidth)
+// {
+// 	for (i=0 ; i<pix ; i++)
+// 	{
+// 		if (pz[i] <= izi)
+// 		{
+// 			pz[i] = izi;
+// 			pdest[i] = color;
+// 		}
+// 	}
+// }
+
+LGenRowLoop:
+	movl	DP_Pix,%eax
+
+LGenColLoop:
+	cmpw	%bp,-2(%edx,%eax,2)
+	jg		LGSkip
+	movw	%bp,-2(%edx,%eax,2)
+	movb	%ch,-1(%edi,%eax,1)
+LGSkip:
+	decl	%eax			// --pix
+	jnz		LGenColLoop
+
+	addl	C(d_zrowbytes),%edx
+	addl	C(screenwidth),%edi
+
+	decl	%ebx			// --count
+	jnz		LGenRowLoop
+
+LDone:
+	popl	%ebx				// restore register variables
+	popl	%edi
+	popl	%ebp				// restore the caller's stack frame
+	ret
+
+LPop6AndDone:
+	fstp	%st(0)
+	fstp	%st(0)
+	fstp	%st(0)
+	fstp	%st(0)
+	fstp	%st(0)
+LPop1AndDone:
+	fstp	%st(0)
+	jmp		LDone
+
+#endif	// id386
--- /dev/null
+++ b/WinQuake/d_polysa.s
@@ -1,0 +1,1744 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+//
+// d_polysa.s
+// x86 assembly-language polygon model drawing code
+//
+
+#include "asm_i386.h"
+#include "quakeasm.h"
+#include "asm_draw.h"
+#include "d_ifacea.h"
+
+#if	id386
+
+// !!! if this is changed, it must be changed in d_polyse.c too !!!
+#define DPS_MAXSPANS			MAXHEIGHT+1	
+									// 1 extra for spanpackage that marks end
+
+//#define	SPAN_SIZE	(((DPS_MAXSPANS + 1 + ((CACHE_SIZE - 1) / spanpackage_t_size)) + 1) * spanpackage_t_size)
+#define SPAN_SIZE (1024+1+1+1)*32
+
+
+	.data
+
+	.align	4
+p10_minus_p20:	.single		0
+p01_minus_p21:	.single		0
+temp0:			.single		0
+temp1:			.single		0
+Ltemp:			.single		0
+
+aff8entryvec_table:	.long	LDraw8, LDraw7, LDraw6, LDraw5
+				.long	LDraw4, LDraw3, LDraw2, LDraw1
+
+lzistepx:		.long	0
+
+
+	.text
+
+#ifndef NeXT
+	.extern C(D_PolysetSetEdgeTable)
+	.extern C(D_RasterizeAliasPolySmooth)
+#endif
+
+//----------------------------------------------------------------------
+// affine triangle gradient calculation code
+//----------------------------------------------------------------------
+
+#define skinwidth	4+0
+
+.globl C(D_PolysetCalcGradients)
+C(D_PolysetCalcGradients):
+
+//	p00_minus_p20 = r_p0[0] - r_p2[0];
+//	p01_minus_p21 = r_p0[1] - r_p2[1];
+//	p10_minus_p20 = r_p1[0] - r_p2[0];
+//	p11_minus_p21 = r_p1[1] - r_p2[1];
+//
+//	xstepdenominv = 1.0 / (p10_minus_p20 * p01_minus_p21 -
+//			     p00_minus_p20 * p11_minus_p21);
+//
+//	ystepdenominv = -xstepdenominv;
+
+	fildl	C(r_p0)+0		// r_p0[0]
+	fildl	C(r_p2)+0		// r_p2[0] | r_p0[0]
+	fildl	C(r_p0)+4		// r_p0[1] | r_p2[0] | r_p0[0]
+	fildl	C(r_p2)+4		// r_p2[1] | r_p0[1] | r_p2[0] | r_p0[0]
+	fildl	C(r_p1)+0		// r_p1[0] | r_p2[1] | r_p0[1] | r_p2[0] | r_p0[0]
+	fildl	C(r_p1)+4		// r_p1[1] | r_p1[0] | r_p2[1] | r_p0[1] |
+							//  r_p2[0] | r_p0[0]
+	fxch	%st(3)			// r_p0[1] | r_p1[0] | r_p2[1] | r_p1[1] |
+							//  r_p2[0] | r_p0[0]
+	fsub	%st(2),%st(0)	// p01_minus_p21 | r_p1[0] | r_p2[1] | r_p1[1] |
+							//  r_p2[0] | r_p0[0]
+	fxch	%st(1)			// r_p1[0] | p01_minus_p21 | r_p2[1] | r_p1[1] |
+							//  r_p2[0] | r_p0[0]
+	fsub	%st(4),%st(0)	// p10_minus_p20 | p01_minus_p21 | r_p2[1] |
+							//  r_p1[1] | r_p2[0] | r_p0[0]
+	fxch	%st(5)			// r_p0[0] | p01_minus_p21 | r_p2[1] |
+							//  r_p1[1] | r_p2[0] | p10_minus_p20
+	fsubp	%st(0),%st(4)	// p01_minus_p21 | r_p2[1] | r_p1[1] |
+							//  p00_minus_p20 | p10_minus_p20
+	fxch	%st(2)			// r_p1[1] | r_p2[1] | p01_minus_p21 |
+							//  p00_minus_p20 | p10_minus_p20
+	fsubp	%st(0),%st(1)	// p11_minus_p21 | p01_minus_p21 |
+							//  p00_minus_p20 | p10_minus_p20
+	fxch	%st(1)			// p01_minus_p21 | p11_minus_p21 |
+							//  p00_minus_p20 | p10_minus_p20
+	flds	C(d_xdenom)		// d_xdenom | p01_minus_p21 | p11_minus_p21 |
+							//  p00_minus_p20 | p10_minus_p20
+	fxch	%st(4)			// p10_minus_p20 | p01_minus_p21 | p11_minus_p21 |
+							//  p00_minus_p20 | d_xdenom
+	fstps	p10_minus_p20	// p01_minus_p21 | p11_minus_p21 |
+							//  p00_minus_p20 | d_xdenom
+	fstps	p01_minus_p21	// p11_minus_p21 | p00_minus_p20 | xstepdenominv
+	fxch	%st(2)			// xstepdenominv | p00_minus_p20 | p11_minus_p21
+
+//// ceil () for light so positive steps are exaggerated, negative steps
+//// diminished,  pushing us away from underflow toward overflow. Underflow is
+//// very visible, overflow is very unlikely, because of ambient lighting
+//	t0 = r_p0[4] - r_p2[4];
+//	t1 = r_p1[4] - r_p2[4];
+
+	fildl	C(r_p2)+16		// r_p2[4] | xstepdenominv | p00_minus_p20 |
+							//  p11_minus_p21
+	fildl	C(r_p0)+16		// r_p0[4] | r_p2[4] | xstepdenominv |
+							//  p00_minus_p20 | p11_minus_p21
+	fildl	C(r_p1)+16		// r_p1[4] | r_p0[4] | r_p2[4] | xstepdenominv |
+							//  p00_minus_p20 | p11_minus_p21
+	fxch	%st(2)			// r_p2[4] | r_p0[4] | r_p1[4] | xstepdenominv |
+							//  p00_minus_p20 | p11_minus_p21
+	fld		%st(0)			// r_p2[4] | r_p2[4] | r_p0[4] | r_p1[4] |
+							//  xstepdenominv | p00_minus_p20 | p11_minus_p21
+	fsubrp	%st(0),%st(2)	// r_p2[4] | t0 | r_p1[4] | xstepdenominv |
+							//  p00_minus_p20 | p11_minus_p21
+	fsubrp	%st(0),%st(2)	// t0 | t1 | xstepdenominv | p00_minus_p20 |
+							//  p11_minus_p21
+
+//	r_lstepx = (int)
+//			ceil((t1 * p01_minus_p21 - t0 * p11_minus_p21) * xstepdenominv);
+//	r_lstepy = (int)
+//			ceil((t1 * p00_minus_p20 - t0 * p10_minus_p20) * ystepdenominv);
+
+	fld		%st(0)			// t0 | t0 | t1 | xstepdenominv | p00_minus_p20 |
+							//  p11_minus_p21
+	fmul	%st(5),%st(0)	// t0*p11_minus_p21 | t0 | t1 | xstepdenominv |
+							//  p00_minus_p20 | p11_minus_p21
+	fxch	%st(2)			// t1 | t0 | t0*p11_minus_p21 | xstepdenominv |
+							//  p00_minus_p20 | p11_minus_p21
+	fld		%st(0)			// t1 | t1 | t0 | t0*p11_minus_p21 |
+							//  xstepdenominv | p00_minus_p20 | p11_minus_p21
+	fmuls	p01_minus_p21	// t1*p01_minus_p21 | t1 | t0 | t0*p11_minus_p21 |
+							//  xstepdenominv | p00_minus_p20 | p11_minus_p21
+	fxch	%st(2)			// t0 | t1 | t1*p01_minus_p21 | t0*p11_minus_p21 |
+							//  xstepdenominv | p00_minus_p20 | p11_minus_p21
+	fmuls	p10_minus_p20	// t0*p10_minus_p20 | t1 | t1*p01_minus_p21 |
+							//  t0*p11_minus_p21 | xstepdenominv |
+							//  p00_minus_p20 | p11_minus_p21
+	fxch	%st(1)			// t1 | t0*p10_minus_p20 | t1*p01_minus_p21 |
+							//  t0*p11_minus_p21 | xstepdenominv |
+							//  p00_minus_p20 | p11_minus_p21
+	fmul	%st(5),%st(0)	// t1*p00_minus_p20 | t0*p10_minus_p20 |
+							//  t1*p01_minus_p21 | t0*p11_minus_p21 |
+							//  xstepdenominv | p00_minus_p20 | p11_minus_p21
+	fxch	%st(2)			// t1*p01_minus_p21 | t0*p10_minus_p20 |
+							//  t1*p00_minus_p20 | t0*p11_minus_p21 |
+							//  xstepdenominv | p00_minus_p20 | p11_minus_p21
+	fsubp	%st(0),%st(3)	// t0*p10_minus_p20 | t1*p00_minus_p20 |
+							//  t1*p01_minus_p21 - t0*p11_minus_p21 |
+							//  xstepdenominv | p00_minus_p20 | p11_minus_p21
+	fsubrp	%st(0),%st(1)	// t1*p00_minus_p20 - t0*p10_minus_p20 |
+							//  t1*p01_minus_p21 - t0*p11_minus_p21 |
+							//  xstepdenominv | p00_minus_p20 | p11_minus_p21
+	fld		%st(2)			// xstepdenominv |
+							//  t1*p00_minus_p20 - t0*p10_minus_p20 |
+							//  t1*p01_minus_p21 - t0*p11_minus_p21 |
+							//  xstepdenominv | p00_minus_p20 | p11_minus_p21
+	fmuls	float_minus_1	// ystepdenominv |
+							//  t1*p00_minus_p20 - t0*p10_minus_p20 |
+							//  t1*p01_minus_p21 - t0*p11_minus_p21 |
+							//  xstepdenominv | p00_minus_p20 | p11_minus_p21
+	fxch	%st(2)			// t1*p01_minus_p21 - t0*p11_minus_p21 |
+							//  t1*p00_minus_p20 - t0*p10_minus_p20 |
+							//  ystepdenominv | xstepdenominv | p00_minus_p20 |
+							//  p11_minus_p21
+	fmul	%st(3),%st(0)	// (t1*p01_minus_p21 - t0*p11_minus_p21)*
+							//   xstepdenominv |
+							//  t1*p00_minus_p20 - t0*p10_minus_p20 |
+							//   | ystepdenominv | xstepdenominv |
+							//   p00_minus_p20 | p11_minus_p21
+	fxch	%st(1)			// t1*p00_minus_p20 - t0*p10_minus_p20 |
+							//  (t1*p01_minus_p21 - t0*p11_minus_p21)*
+							//   xstepdenominv | ystepdenominv |
+							//   xstepdenominv | p00_minus_p20 | p11_minus_p21
+	fmul	%st(2),%st(0)	// (t1*p00_minus_p20 - t0*p10_minus_p20)*
+							//  ystepdenominv |
+							//  (t1*p01_minus_p21 - t0*p11_minus_p21)*
+							//  xstepdenominv | ystepdenominv |
+							//  xstepdenominv | p00_minus_p20 | p11_minus_p21
+	fldcw	ceil_cw
+	fistpl	C(r_lstepy)		// r_lstepx | ystepdenominv | xstepdenominv |
+							//  p00_minus_p20 | p11_minus_p21
+	fistpl	C(r_lstepx)		// ystepdenominv | xstepdenominv | p00_minus_p20 |
+							//  p11_minus_p21
+	fldcw	single_cw
+
+//	t0 = r_p0[2] - r_p2[2];
+//	t1 = r_p1[2] - r_p2[2];
+
+	fildl	C(r_p2)+8		// r_p2[2] | ystepdenominv | xstepdenominv |
+							//  p00_minus_p20 | p11_minus_p21
+	fildl	C(r_p0)+8		// r_p0[2] | r_p2[2] | ystepdenominv |
+							//   xstepdenominv | p00_minus_p20 | p11_minus_p21
+	fildl	C(r_p1)+8		// r_p1[2] | r_p0[2] | r_p2[2] | ystepdenominv |
+							//  xstepdenominv | p00_minus_p20 | p11_minus_p21
+	fxch	%st(2)			// r_p2[2] | r_p0[2] | r_p1[2] | ystepdenominv |
+							//  xstepdenominv | p00_minus_p20 | p11_minus_p21
+	fld		%st(0)			// r_p2[2] | r_p2[2] | r_p0[2] | r_p1[2] |
+							//  ystepdenominv | xstepdenominv | p00_minus_p20 |
+							//  p11_minus_p21
+	fsubrp	%st(0),%st(2)	// r_p2[2] | t0 | r_p1[2] | ystepdenominv |
+							//  xstepdenominv | p00_minus_p20 | p11_minus_p21
+	fsubrp	%st(0),%st(2)	// t0 | t1 | ystepdenominv | xstepdenominv |
+							//  p00_minus_p20 | p11_minus_p21
+
+//	r_sstepx = (int)((t1 * p01_minus_p21 - t0 * p11_minus_p21) *
+//			xstepdenominv);
+//	r_sstepy = (int)((t1 * p00_minus_p20 - t0 * p10_minus_p20) *
+//			ystepdenominv);
+
+	fld		%st(0)			// t0 | t0 | t1 | ystepdenominv | xstepdenominv
+	fmul	%st(6),%st(0)	// t0*p11_minus_p21 | t0 | t1 | ystepdenominv |
+							//  xstepdenominv | p00_minus_p20 | p11_minus_p21
+	fxch	%st(2)			// t1 | t0 | t0*p11_minus_p21 | ystepdenominv |
+							//  xstepdenominv | p00_minus_p20 | p11_minus_p21
+	fld		%st(0)			// t1 | t1 | t0 | t0*p11_minus_p21 |
+							//  ystepdenominv | xstepdenominv | p00_minus_p20 |
+							//  p11_minus_p21
+	fmuls	p01_minus_p21	// t1*p01_minus_p21 | t1 | t0 | t0*p11_minus_p21 |
+							//  ystepdenominv | xstepdenominv | p00_minus_p20 |
+							//  p11_minus_p21
+	fxch	%st(2)			// t0 | t1 | t1*p01_minus_p21 | t0*p11_minus_p21 |
+							//  ystepdenominv | xstepdenominv | p00_minus_p20 |
+							//  p11_minus_p21
+	fmuls	p10_minus_p20	// t0*p10_minus_p20 | t1 | t1*p01_minus_p21 |
+							//  t0*p11_minus_p21 | ystepdenominv |
+							//  xstepdenominv | p00_minus_p20 | p11_minus_p21
+	fxch	%st(1)			// t1 | t0*p10_minus_p20 | t1*p01_minus_p21 |
+							//  t0*p11_minus_p21 | ystepdenominv |
+							//  xstepdenominv | p00_minus_p20 | p11_minus_p21
+	fmul	%st(6),%st(0)	// t1*p00_minus_p20 | t0*p10_minus_p20 |
+							//  t1*p01_minus_p21 | t0*p11_minus_p21 |
+							//  ystepdenominv | xstepdenominv | p00_minus_p20 |
+							//  p11_minus_p21
+	fxch	%st(2)			// t1*p01_minus_p21 | t0*p10_minus_p20 |
+							//  t1*p00_minus_p20 | t0*p11_minus_p21 |
+							//  ystepdenominv | xstepdenominv | p00_minus_p20 |
+							//  p11_minus_p21
+	fsubp	%st(0),%st(3)	// t0*p10_minus_p20 | t1*p00_minus_p20 |
+							//  t1*p01_minus_p21 - t0*p11_minus_p21 |
+							//  ystepdenominv | xstepdenominv | p00_minus_p20 |
+							//  p11_minus_p21
+	fsubrp	%st(0),%st(1)	// t1*p00_minus_p20 - t0*p10_minus_p20 |
+							//  t1*p01_minus_p21 - t0*p11_minus_p21 |
+							//  ystepdenominv | xstepdenominv | p00_minus_p20 |
+							//  p11_minus_p21
+	fmul	%st(2),%st(0)	// (t1*p00_minus_p20 - t0*p10_minus_p20)*
+							//   ystepdenominv |
+							//  t1*p01_minus_p21 - t0*p11_minus_p21 |
+							//  ystepdenominv | xstepdenominv | p00_minus_p20 |
+							//  p11_minus_p21
+	fxch	%st(1)			// t1*p01_minus_p21 - t0*p11_minus_p21 |
+							//  (t1*p00_minus_p20 - t0*p10_minus_p20)*
+							//   ystepdenominv | ystepdenominv |
+							//  xstepdenominv | p00_minus_p20 | p11_minus_p21
+	fmul	%st(3),%st(0)	// (t1*p01_minus_p21 - t0*p11_minus_p21)*
+							//  xstepdenominv |
+							//  (t1*p00_minus_p20 - t0*p10_minus_p20)*
+							//  ystepdenominv | ystepdenominv |
+							//  xstepdenominv | p00_minus_p20 | p11_minus_p21
+	fxch	%st(1)			// (t1*p00_minus_p20 - t0*p10_minus_p20)*
+							//  ystepdenominv |
+							//  (t1*p01_minus_p21 - t0*p11_minus_p21)*
+							//  xstepdenominv | ystepdenominv |
+							//  xstepdenominv | p00_minus_p20 | p11_minus_p21
+	fistpl	C(r_sstepy)		// r_sstepx | ystepdenominv | xstepdenominv |
+							//  p00_minus_p20 | p11_minus_p21
+	fistpl	C(r_sstepx)		// ystepdenominv | xstepdenominv | p00_minus_p20 |
+							//  p11_minus_p21
+
+//	t0 = r_p0[3] - r_p2[3];
+//	t1 = r_p1[3] - r_p2[3];
+
+	fildl	C(r_p2)+12		// r_p2[3] | ystepdenominv | xstepdenominv |
+							//  p00_minus_p20 | p11_minus_p21
+	fildl	C(r_p0)+12		// r_p0[3] | r_p2[3] | ystepdenominv |
+							//  xstepdenominv | p00_minus_p20 | p11_minus_p21
+	fildl	C(r_p1)+12		// r_p1[3] | r_p0[3] | r_p2[3] | ystepdenominv |
+							//  xstepdenominv | p00_minus_p20 | p11_minus_p21
+	fxch	%st(2)			// r_p2[3] | r_p0[3] | r_p1[3] | ystepdenominv |
+							//  xstepdenominv | p00_minus_p20 | p11_minus_p21
+	fld		%st(0)			// r_p2[3] | r_p2[3] | r_p0[3] | r_p1[3] |
+							//  ystepdenominv | xstepdenominv | p00_minus_p20 |
+							//  p11_minus_p21
+	fsubrp	%st(0),%st(2)	// r_p2[3] | t0 | r_p1[3] | ystepdenominv |
+							//  xstepdenominv | p00_minus_p20 | p11_minus_p21
+	fsubrp	%st(0),%st(2)	// t0 | t1 | ystepdenominv | xstepdenominv |
+							//  p00_minus_p20 | p11_minus_p21
+
+//	r_tstepx = (int)((t1 * p01_minus_p21 - t0 * p11_minus_p21) *
+//			xstepdenominv);
+//	r_tstepy = (int)((t1 * p00_minus_p20 - t0 * p10_minus_p20) *
+//			ystepdenominv);
+
+	fld		%st(0)			// t0 | t0 | t1 | ystepdenominv | xstepdenominv |
+							//  p00_minus_p20 | p11_minus_p21
+	fmul	%st(6),%st(0)	// t0*p11_minus_p21 | t0 | t1 | ystepdenominv |
+							//  xstepdenominv | p00_minus_p20 | p11_minus_p21
+	fxch	%st(2)			// t1 | t0 | t0*p11_minus_p21 | ystepdenominv |
+							//  xstepdenominv | p00_minus_p20 | p11_minus_p21
+	fld		%st(0)			// t1 | t1 | t0 | t0*p11_minus_p21 |
+							//  ystepdenominv | xstepdenominv | p00_minus_p20 |
+							//  p11_minus_p21
+	fmuls	p01_minus_p21	// t1*p01_minus_p21 | t1 | t0 | t0*p11_minus_p21 |
+							//  ystepdenominv | xstepdenominv | p00_minus_p20 |
+							//  p11_minus_p21
+	fxch	%st(2)			// t0 | t1 | t1*p01_minus_p21 | t0*p11_minus_p21 |
+							//  ystepdenominv | xstepdenominv | p00_minus_p20 |
+							//  p11_minus_p21
+	fmuls	p10_minus_p20	// t0*p10_minus_p20 | t1 | t1*p01_minus_p21 |
+							//  t0*p11_minus_p21 | ystepdenominv |
+							//  xstepdenominv | p00_minus_p20 | p11_minus_p21
+	fxch	%st(1)			// t1 | t0*p10_minus_p20 | t1*p01_minus_p21 |
+							//  t0*p11_minus_p21 | ystepdenominv |
+							//  xstepdenominv | p00_minus_p20 | p11_minus_p21
+	fmul	%st(6),%st(0)	// t1*p00_minus_p20 | t0*p10_minus_p20 |
+							//  t1*p01_minus_p21 | t0*p11_minus_p21 |
+							//  ystepdenominv | xstepdenominv | p00_minus_p20 |
+							//  p11_minus_p21
+	fxch	%st(2)			// t1*p01_minus_p21 | t0*p10_minus_p20 |
+							//  t1*p00_minus_p20 | t0*p11_minus_p21 |
+							//  ystepdenominv | xstepdenominv | p00_minus_p20 |
+							//  p11_minus_p21
+	fsubp	%st(0),%st(3)	// t0*p10_minus_p20 | t1*p00_minus_p20 |
+							//  t1*p01_minus_p21 - t0*p11_minus_p21 |
+							//  ystepdenominv | xstepdenominv | p00_minus_p20 |
+							//  p11_minus_p21
+	fsubrp	%st(0),%st(1)	// t1*p00_minus_p20 - t0*p10_minus_p20 |
+							//  t1*p01_minus_p21 - t0*p11_minus_p21 |
+							//  ystepdenominv | xstepdenominv | p00_minus_p20 |
+							//  p11_minus_p21
+	fmul	%st(2),%st(0)	// (t1*p00_minus_p20 - t0*p10_minus_p20)*
+							//   ystepdenominv |
+							//  t1*p01_minus_p21 - t0*p11_minus_p21 |
+							//  ystepdenominv | xstepdenominv | p00_minus_p20 |
+							//  p11_minus_p21
+	fxch	%st(1)			// t1*p01_minus_p21 - t0*p11_minus_p21 |
+							//  (t1*p00_minus_p20 - t0*p10_minus_p20)*
+							//  ystepdenominv | ystepdenominv |
+							//  xstepdenominv | p00_minus_p20 | p11_minus_p21
+	fmul	%st(3),%st(0)	// (t1*p01_minus_p21 - t0*p11_minus_p21)*
+							//  xstepdenominv |
+							//  (t1*p00_minus_p20 - t0*p10_minus_p20)*
+							//  ystepdenominv | ystepdenominv |
+							//  xstepdenominv | p00_minus_p20 | p11_minus_p21
+	fxch	%st(1)			// (t1*p00_minus_p20 - t0*p10_minus_p20)*
+							//  ystepdenominv |
+							//  (t1*p01_minus_p21 - t0*p11_minus_p21)*
+							//  xstepdenominv | ystepdenominv |
+							//  xstepdenominv | p00_minus_p20 | p11_minus_p21
+	fistpl	C(r_tstepy)		// r_tstepx | ystepdenominv | xstepdenominv |
+							//  p00_minus_p20 | p11_minus_p21
+	fistpl	C(r_tstepx)		// ystepdenominv | xstepdenominv | p00_minus_p20 |
+							//  p11_minus_p21
+
+//	t0 = r_p0[5] - r_p2[5];
+//	t1 = r_p1[5] - r_p2[5];
+
+	fildl	C(r_p2)+20		// r_p2[5] | ystepdenominv | xstepdenominv |
+							//  p00_minus_p20 | p11_minus_p21
+	fildl	C(r_p0)+20		// r_p0[5] | r_p2[5] | ystepdenominv |
+							//  xstepdenominv | p00_minus_p20 | p11_minus_p21
+	fildl	C(r_p1)+20		// r_p1[5] | r_p0[5] | r_p2[5] | ystepdenominv |
+							//  xstepdenominv | p00_minus_p20 | p11_minus_p21
+	fxch	%st(2)			// r_p2[5] | r_p0[5] | r_p1[5] | ystepdenominv |
+							//  xstepdenominv | p00_minus_p20 | p11_minus_p21
+	fld		%st(0)			// r_p2[5] | r_p2[5] | r_p0[5] | r_p1[5] |
+							//  ystepdenominv | xstepdenominv | p00_minus_p20 |
+							//  p11_minus_p21
+	fsubrp	%st(0),%st(2)	// r_p2[5] | t0 | r_p1[5] | ystepdenominv |
+							//  xstepdenominv | p00_minus_p20 | p11_minus_p21
+	fsubrp	%st(0),%st(2)	// t0 | t1 | ystepdenominv | xstepdenominv |
+							//  p00_minus_p20 | p11_minus_p21
+
+//	r_zistepx = (int)((t1 * p01_minus_p21 - t0 * p11_minus_p21) *
+//			xstepdenominv);
+//	r_zistepy = (int)((t1 * p00_minus_p20 - t0 * p10_minus_p20) *
+//			ystepdenominv);
+
+	fld		%st(0)			// t0 | t0 | t1 | ystepdenominv | xstepdenominv |
+							//  p00_minus_p20 | p11_minus_p21
+	fmulp	%st(0),%st(6)	// t0 | t1 | ystepdenominv | xstepdenominv |
+							//  p00_minus_p20 | t0*p11_minus_p21
+	fxch	%st(1)			// t1 | t0 | ystepdenominv | xstepdenominv |
+							//  p00_minus_p20 | t0*p11_minus_p21
+	fld		%st(0)			// t1 | t1 | t0 | ystepdenominv | xstepdenominv |
+							//  p00_minus_p20 | t0*p11_minus_p21
+	fmuls	p01_minus_p21	// t1*p01_minus_p21 | t1 | t0 | ystepdenominv |
+							//  xstepdenominv | p00_minus_p20 |
+							//  t0*p11_minus_p21
+	fxch	%st(2)			// t0 | t1 | t1*p01_minus_p21 | ystepdenominv |
+							//  xstepdenominv | p00_minus_p20 |
+							//  t0*p11_minus_p21
+	fmuls	p10_minus_p20	// t0*p10_minus_p20 | t1 | t1*p01_minus_p21 |
+							//  ystepdenominv | xstepdenominv | p00_minus_p20 |
+							//  t0*p11_minus_p21
+	fxch	%st(1)			// t1 | t0*p10_minus_p20 | t1*p01_minus_p21 |
+							//  ystepdenominv | xstepdenominv | p00_minus_p20 |
+							//  t0*p11_minus_p21
+	fmulp	%st(0),%st(5)	// t0*p10_minus_p20 | t1*p01_minus_p21 |
+							//  ystepdenominv | xstepdenominv |
+							//  t1*p00_minus_p20 | t0*p11_minus_p21
+	fxch	%st(5)			// t0*p11_minus_p21 | t1*p01_minus_p21 |
+							//  ystepdenominv | xstepdenominv |
+							//  t1*p00_minus_p20 | t0*p10_minus_p20
+	fsubrp	%st(0),%st(1)	// t1*p01_minus_p21 - t0*p11_minus_p21 |
+							//  ystepdenominv | xstepdenominv |
+							//  t1*p00_minus_p20 | t0*p10_minus_p20
+	fxch	%st(3)			// t1*p00_minus_p20 | ystepdenominv |
+							//  xstepdenominv |
+							//  t1*p01_minus_p21 - t0*p11_minus_p21 |
+							//  t0*p10_minus_p20
+	fsubp	%st(0),%st(4)	// ystepdenominv | xstepdenominv |
+							//  t1*p01_minus_p21 - t0*p11_minus_p21 |
+							//  t1*p00_minus_p20 - t0*p10_minus_p20
+	fxch	%st(1)			// xstepdenominv | ystepdenominv |
+							//  t1*p01_minus_p21 - t0*p11_minus_p21 |
+							//  t1*p00_minus_p20 - t0*p10_minus_p20
+	fmulp	%st(0),%st(2)	// ystepdenominv |
+							//  (t1*p01_minus_p21 - t0*p11_minus_p21) *
+							//  xstepdenominv |
+							//  t1*p00_minus_p20 - t0*p10_minus_p20
+	fmulp	%st(0),%st(2)	// (t1*p01_minus_p21 - t0*p11_minus_p21) *
+							//  xstepdenominv |
+							//  (t1*p00_minus_p20 - t0*p10_minus_p20) *
+							//  ystepdenominv
+	fistpl	C(r_zistepx)	// (t1*p00_minus_p20 - t0*p10_minus_p20) *
+							//  ystepdenominv
+	fistpl	C(r_zistepy)
+
+//	a_sstepxfrac = r_sstepx << 16;
+//	a_tstepxfrac = r_tstepx << 16;
+//
+//	a_ststepxwhole = r_affinetridesc.skinwidth * (r_tstepx >> 16) +
+//			(r_sstepx >> 16);
+
+	movl	C(r_sstepx),%eax
+	movl	C(r_tstepx),%edx
+	shll	$16,%eax
+	shll	$16,%edx
+	movl	%eax,C(a_sstepxfrac)
+	movl	%edx,C(a_tstepxfrac)
+
+	movl	C(r_sstepx),%ecx
+	movl	C(r_tstepx),%eax
+	sarl	$16,%ecx
+	sarl	$16,%eax
+	imull	skinwidth(%esp)
+	addl	%ecx,%eax
+	movl	%eax,C(a_ststepxwhole)
+
+	ret
+
+
+//----------------------------------------------------------------------
+// recursive subdivision affine triangle drawing code
+//
+// not C-callable because of stdcall return
+//----------------------------------------------------------------------
+
+#define lp1	4+16
+#define lp2	8+16
+#define lp3	12+16
+
+.globl C(D_PolysetRecursiveTriangle)
+C(D_PolysetRecursiveTriangle):
+	pushl	%ebp				// preserve caller stack frame pointer
+	pushl	%esi				// preserve register variables
+	pushl	%edi
+	pushl	%ebx
+
+//	int		*temp;
+//	int		d;
+//	int		new[6];
+//	int		i;
+//	int		z;
+//	short	*zbuf;
+	movl	lp2(%esp),%esi
+	movl	lp1(%esp),%ebx
+	movl	lp3(%esp),%edi
+
+//	d = lp2[0] - lp1[0];
+//	if (d < -1 || d > 1)
+//		goto split;
+	movl	0(%esi),%eax
+
+	movl	0(%ebx),%edx
+	movl	4(%esi),%ebp
+
+	subl	%edx,%eax
+	movl	4(%ebx),%ecx
+
+	subl	%ecx,%ebp
+	incl	%eax
+
+	cmpl	$2,%eax
+	ja		LSplit
+
+//	d = lp2[1] - lp1[1];
+//	if (d < -1 || d > 1)
+//		goto split;
+	movl	0(%edi),%eax
+	incl	%ebp
+
+	cmpl	$2,%ebp
+	ja		LSplit
+
+//	d = lp3[0] - lp2[0];
+//	if (d < -1 || d > 1)
+//		goto split2;
+	movl	0(%esi),%edx
+	movl	4(%edi),%ebp
+
+	subl	%edx,%eax
+	movl	4(%esi),%ecx
+
+	subl	%ecx,%ebp
+	incl	%eax
+
+	cmpl	$2,%eax
+	ja		LSplit2
+
+//	d = lp3[1] - lp2[1];
+//	if (d < -1 || d > 1)
+//		goto split2;
+	movl	0(%ebx),%eax
+	incl	%ebp
+
+	cmpl	$2,%ebp
+	ja		LSplit2
+
+//	d = lp1[0] - lp3[0];
+//	if (d < -1 || d > 1)
+//		goto split3;
+	movl	0(%edi),%edx
+	movl	4(%ebx),%ebp
+
+	subl	%edx,%eax
+	movl	4(%edi),%ecx
+
+	subl	%ecx,%ebp
+	incl	%eax
+
+	incl	%ebp
+	movl	%ebx,%edx
+
+	cmpl	$2,%eax
+	ja		LSplit3
+
+//	d = lp1[1] - lp3[1];
+//	if (d < -1 || d > 1)
+//	{
+//split3:
+//		temp = lp1;
+//		lp3 = lp2;
+//		lp1 = lp3;
+//		lp2 = temp;
+//		goto split;
+//	}
+//
+//	return;			// entire tri is filled
+//
+	cmpl	$2,%ebp
+	jna		LDone
+
+LSplit3:
+	movl	%edi,%ebx
+	movl	%esi,%edi
+	movl	%edx,%esi
+	jmp		LSplit
+
+//split2:
+LSplit2:
+
+//	temp = lp1;
+//	lp1 = lp2;
+//	lp2 = lp3;
+//	lp3 = temp;
+	movl	%ebx,%eax
+	movl	%esi,%ebx
+	movl	%edi,%esi
+	movl	%eax,%edi
+
+//split:
+LSplit:
+
+	subl	$24,%esp		// allocate space for a new vertex
+
+//// split this edge
+//	new[0] = (lp1[0] + lp2[0]) >> 1;
+//	new[1] = (lp1[1] + lp2[1]) >> 1;
+//	new[2] = (lp1[2] + lp2[2]) >> 1;
+//	new[3] = (lp1[3] + lp2[3]) >> 1;
+//	new[5] = (lp1[5] + lp2[5]) >> 1;
+	movl	8(%ebx),%eax
+
+	movl	8(%esi),%edx
+	movl	12(%ebx),%ecx
+
+	addl	%edx,%eax
+	movl	12(%esi),%edx
+
+	sarl	$1,%eax
+	addl	%edx,%ecx
+
+	movl	%eax,8(%esp)
+	movl	20(%ebx),%eax
+
+	sarl	$1,%ecx
+	movl	20(%esi),%edx
+
+	movl	%ecx,12(%esp)
+	addl	%edx,%eax
+
+	movl	0(%ebx),%ecx
+	movl	0(%esi),%edx
+
+	sarl	$1,%eax
+	addl	%ecx,%edx
+
+	movl	%eax,20(%esp)
+	movl	4(%ebx),%eax
+
+	sarl	$1,%edx
+	movl	4(%esi),%ebp
+
+	movl	%edx,0(%esp)
+	addl	%eax,%ebp
+
+	sarl	$1,%ebp
+	movl	%ebp,4(%esp)
+
+//// draw the point if splitting a leading edge
+//	if (lp2[1] > lp1[1])
+//		goto nodraw;
+	cmpl	%eax,4(%esi)
+	jg		LNoDraw
+
+//	if ((lp2[1] == lp1[1]) && (lp2[0] < lp1[0]))
+//		goto nodraw;
+	movl	0(%esi),%edx
+	jnz		LDraw
+
+	cmpl	%ecx,%edx
+	jl		LNoDraw
+
+LDraw:
+
+// z = new[5] >> 16;
+	movl	20(%esp),%edx
+	movl	4(%esp),%ecx
+
+	sarl	$16,%edx
+	movl	0(%esp),%ebp
+
+//	zbuf = zspantable[new[1]] + new[0];
+	movl	C(zspantable)(,%ecx,4),%eax
+
+//	if (z >= *zbuf)
+//	{
+	cmpw	(%eax,%ebp,2),%dx
+	jnge	LNoDraw
+
+//		int		pix;
+//		
+//		*zbuf = z;
+	movw	%dx,(%eax,%ebp,2)
+
+//		pix = d_pcolormap[skintable[new[3]>>16][new[2]>>16]];
+	movl	12(%esp),%eax
+
+	sarl	$16,%eax
+	movl	8(%esp),%edx
+
+	sarl	$16,%edx
+	subl	%ecx,%ecx
+
+	movl	C(skintable)(,%eax,4),%eax
+	movl	4(%esp),%ebp
+
+	movb	(%eax,%edx,),%cl
+	movl	C(d_pcolormap),%edx
+
+	movb	(%edx,%ecx,),%dl
+	movl	0(%esp),%ecx
+
+//		d_viewbuffer[d_scantable[new[1]] + new[0]] = pix;
+	movl	C(d_scantable)(,%ebp,4),%eax
+	addl	%eax,%ecx
+	movl	C(d_viewbuffer),%eax
+	movb	%dl,(%eax,%ecx,1)
+
+//	}
+//
+//nodraw:
+LNoDraw:
+
+//// recursively continue
+//	D_PolysetRecursiveTriangle (lp3, lp1, new);
+	pushl	%esp
+	pushl	%ebx
+	pushl	%edi
+	call	C(D_PolysetRecursiveTriangle)
+
+//	D_PolysetRecursiveTriangle (lp3, new, lp2);
+	movl	%esp,%ebx
+	pushl	%esi
+	pushl	%ebx
+	pushl	%edi
+	call	C(D_PolysetRecursiveTriangle)
+	addl	$24,%esp
+
+LDone:
+	popl	%ebx				// restore register variables
+	popl	%edi
+	popl	%esi
+	popl	%ebp				// restore caller stack frame pointer
+	ret		$12
+
+
+//----------------------------------------------------------------------
+// 8-bpp horizontal span drawing code for affine polygons, with smooth
+// shading and no transparency
+//----------------------------------------------------------------------
+
+#define pspans	4+8
+
+.globl C(D_PolysetAff8Start)
+C(D_PolysetAff8Start):
+
+.globl C(D_PolysetDrawSpans8)
+C(D_PolysetDrawSpans8):
+	pushl	%esi				// preserve register variables
+	pushl	%ebx
+
+	movl	pspans(%esp),%esi	// point to the first span descriptor
+	movl	C(r_zistepx),%ecx
+
+	pushl	%ebp				// preserve caller's stack frame
+	pushl	%edi
+
+	rorl	$16,%ecx			// put high 16 bits of 1/z step in low word
+	movl	spanpackage_t_count(%esi),%edx
+
+	movl	%ecx,lzistepx
+
+LSpanLoop:
+
+//		lcount = d_aspancount - pspanpackage->count;
+//
+//		errorterm += erroradjustup;
+//		if (errorterm >= 0)
+//		{
+//			d_aspancount += d_countextrastep;
+//			errorterm -= erroradjustdown;
+//		}
+//		else
+//		{
+//			d_aspancount += ubasestep;
+//		}
+	movl	C(d_aspancount),%eax
+	subl	%edx,%eax
+
+	movl	C(erroradjustup),%edx
+	movl	C(errorterm),%ebx
+	addl	%edx,%ebx
+	js		LNoTurnover
+
+	movl	C(erroradjustdown),%edx
+	movl	C(d_countextrastep),%edi
+	subl	%edx,%ebx
+	movl	C(d_aspancount),%ebp
+	movl	%ebx,C(errorterm)
+	addl	%edi,%ebp
+	movl	%ebp,C(d_aspancount)
+	jmp		LRightEdgeStepped
+
+LNoTurnover:
+	movl	C(d_aspancount),%edi
+	movl	C(ubasestep),%edx
+	movl	%ebx,C(errorterm)
+	addl	%edx,%edi
+	movl	%edi,C(d_aspancount)
+
+LRightEdgeStepped:
+	cmpl	$1,%eax
+
+	jl		LNextSpan
+	jz		LExactlyOneLong
+
+//
+// set up advancetable
+//
+	movl	C(a_ststepxwhole),%ecx
+	movl	C(r_affinetridesc)+atd_skinwidth,%edx
+
+	movl	%ecx,advancetable+4	// advance base in t
+	addl	%edx,%ecx
+
+	movl	%ecx,advancetable	// advance extra in t
+	movl	C(a_tstepxfrac),%ecx
+
+	movw	C(r_lstepx),%cx
+	movl	%eax,%edx			// count
+
+	movl	%ecx,tstep
+	addl	$7,%edx
+
+	shrl	$3,%edx				// count of full and partial loops
+	movl	spanpackage_t_sfrac(%esi),%ebx
+
+	movw	%dx,%bx
+	movl	spanpackage_t_pz(%esi),%ecx
+
+	negl	%eax
+
+	movl	spanpackage_t_pdest(%esi),%edi
+	andl	$7,%eax		// 0->0, 1->7, 2->6, ... , 7->1
+
+	subl	%eax,%edi	// compensate for hardwired offsets
+	subl	%eax,%ecx
+
+	subl	%eax,%ecx
+	movl	spanpackage_t_tfrac(%esi),%edx
+
+	movw	spanpackage_t_light(%esi),%dx
+	movl	spanpackage_t_zi(%esi),%ebp
+
+	rorl	$16,%ebp	// put high 16 bits of 1/z in low word
+	pushl	%esi
+
+	movl	spanpackage_t_ptex(%esi),%esi
+	jmp		aff8entryvec_table(,%eax,4)
+
+// %bx = count of full and partial loops
+// %ebx high word = sfrac
+// %ecx = pz
+// %dx = light
+// %edx high word = tfrac
+// %esi = ptex
+// %edi = pdest
+// %ebp = 1/z
+// tstep low word = C(r_lstepx)
+// tstep high word = C(a_tstepxfrac)
+// C(a_sstepxfrac) low word = 0
+// C(a_sstepxfrac) high word = C(a_sstepxfrac)
+
+LDrawLoop:
+
+// FIXME: do we need to clamp light? We may need at least a buffer bit to
+// keep it from poking into tfrac and causing problems
+
+LDraw8:
+	cmpw	(%ecx),%bp
+	jl		Lp1
+	xorl	%eax,%eax
+	movb	%dh,%ah
+	movb	(%esi),%al
+	movw	%bp,(%ecx)
+	movb	0x12345678(%eax),%al
+LPatch8:
+	movb	%al,(%edi)
+Lp1:
+	addl	tstep,%edx
+	sbbl	%eax,%eax
+	addl	lzistepx,%ebp
+	adcl	$0,%ebp
+	addl	C(a_sstepxfrac),%ebx
+	adcl	advancetable+4(,%eax,4),%esi
+
+LDraw7:
+	cmpw	2(%ecx),%bp
+	jl		Lp2
+	xorl	%eax,%eax
+	movb	%dh,%ah
+	movb	(%esi),%al
+	movw	%bp,2(%ecx)
+	movb	0x12345678(%eax),%al
+LPatch7:
+	movb	%al,1(%edi)
+Lp2:
+	addl	tstep,%edx
+	sbbl	%eax,%eax
+	addl	lzistepx,%ebp
+	adcl	$0,%ebp
+	addl	C(a_sstepxfrac),%ebx
+	adcl	advancetable+4(,%eax,4),%esi
+
+LDraw6:
+	cmpw	4(%ecx),%bp
+	jl		Lp3
+	xorl	%eax,%eax
+	movb	%dh,%ah
+	movb	(%esi),%al
+	movw	%bp,4(%ecx)
+	movb	0x12345678(%eax),%al
+LPatch6:
+	movb	%al,2(%edi)
+Lp3:
+	addl	tstep,%edx
+	sbbl	%eax,%eax
+	addl	lzistepx,%ebp
+	adcl	$0,%ebp
+	addl	C(a_sstepxfrac),%ebx
+	adcl	advancetable+4(,%eax,4),%esi
+
+LDraw5:
+	cmpw	6(%ecx),%bp
+	jl		Lp4
+	xorl	%eax,%eax
+	movb	%dh,%ah
+	movb	(%esi),%al
+	movw	%bp,6(%ecx)
+	movb	0x12345678(%eax),%al
+LPatch5:
+	movb	%al,3(%edi)
+Lp4:
+	addl	tstep,%edx
+	sbbl	%eax,%eax
+	addl	lzistepx,%ebp
+	adcl	$0,%ebp
+	addl	C(a_sstepxfrac),%ebx
+	adcl	advancetable+4(,%eax,4),%esi
+
+LDraw4:
+	cmpw	8(%ecx),%bp
+	jl		Lp5
+	xorl	%eax,%eax
+	movb	%dh,%ah
+	movb	(%esi),%al
+	movw	%bp,8(%ecx)
+	movb	0x12345678(%eax),%al
+LPatch4:
+	movb	%al,4(%edi)
+Lp5:
+	addl	tstep,%edx
+	sbbl	%eax,%eax
+	addl	lzistepx,%ebp
+	adcl	$0,%ebp
+	addl	C(a_sstepxfrac),%ebx
+	adcl	advancetable+4(,%eax,4),%esi
+
+LDraw3:
+	cmpw	10(%ecx),%bp
+	jl		Lp6
+	xorl	%eax,%eax
+	movb	%dh,%ah
+	movb	(%esi),%al
+	movw	%bp,10(%ecx)
+	movb	0x12345678(%eax),%al
+LPatch3:
+	movb	%al,5(%edi)
+Lp6:
+	addl	tstep,%edx
+	sbbl	%eax,%eax
+	addl	lzistepx,%ebp
+	adcl	$0,%ebp
+	addl	C(a_sstepxfrac),%ebx
+	adcl	advancetable+4(,%eax,4),%esi
+
+LDraw2:
+	cmpw	12(%ecx),%bp
+	jl		Lp7
+	xorl	%eax,%eax
+	movb	%dh,%ah
+	movb	(%esi),%al
+	movw	%bp,12(%ecx)
+	movb	0x12345678(%eax),%al
+LPatch2:
+	movb	%al,6(%edi)
+Lp7:
+	addl	tstep,%edx
+	sbbl	%eax,%eax
+	addl	lzistepx,%ebp
+	adcl	$0,%ebp
+	addl	C(a_sstepxfrac),%ebx
+	adcl	advancetable+4(,%eax,4),%esi
+
+LDraw1:
+	cmpw	14(%ecx),%bp
+	jl		Lp8
+	xorl	%eax,%eax
+	movb	%dh,%ah
+	movb	(%esi),%al
+	movw	%bp,14(%ecx)
+	movb	0x12345678(%eax),%al
+LPatch1:
+	movb	%al,7(%edi)
+Lp8:
+	addl	tstep,%edx
+	sbbl	%eax,%eax
+	addl	lzistepx,%ebp
+	adcl	$0,%ebp
+	addl	C(a_sstepxfrac),%ebx
+	adcl	advancetable+4(,%eax,4),%esi
+
+	addl	$8,%edi
+	addl	$16,%ecx
+
+	decw	%bx
+	jnz		LDrawLoop
+
+	popl	%esi				// restore spans pointer
+LNextSpan:
+	addl	$(spanpackage_t_size),%esi	// point to next span
+LNextSpanESISet:
+	movl	spanpackage_t_count(%esi),%edx
+	cmpl	$-999999,%edx		// any more spans?
+	jnz		LSpanLoop			// yes
+
+	popl	%edi
+	popl	%ebp				// restore the caller's stack frame
+	popl	%ebx				// restore register variables
+	popl	%esi
+	ret
+
+
+// draw a one-long span
+
+LExactlyOneLong:
+
+	movl	spanpackage_t_pz(%esi),%ecx
+	movl	spanpackage_t_zi(%esi),%ebp
+
+	rorl	$16,%ebp	// put high 16 bits of 1/z in low word
+	movl	spanpackage_t_ptex(%esi),%ebx
+
+	cmpw	(%ecx),%bp
+	jl		LNextSpan
+	xorl	%eax,%eax
+	movl	spanpackage_t_pdest(%esi),%edi
+	movb	spanpackage_t_light+1(%esi),%ah
+	addl	$(spanpackage_t_size),%esi	// point to next span
+	movb	(%ebx),%al
+	movw	%bp,(%ecx)
+	movb	0x12345678(%eax),%al
+LPatch9:
+	movb	%al,(%edi)
+
+	jmp		LNextSpanESISet
+
+.globl C(D_PolysetAff8End)
+C(D_PolysetAff8End):
+
+
+#define pcolormap		4
+
+.globl C(D_Aff8Patch)
+C(D_Aff8Patch):
+	movl	pcolormap(%esp),%eax
+	movl	%eax,LPatch1-4
+	movl	%eax,LPatch2-4
+	movl	%eax,LPatch3-4
+	movl	%eax,LPatch4-4
+	movl	%eax,LPatch5-4
+	movl	%eax,LPatch6-4
+	movl	%eax,LPatch7-4
+	movl	%eax,LPatch8-4
+	movl	%eax,LPatch9-4
+
+	ret
+
+
+//----------------------------------------------------------------------
+// Alias model polygon dispatching code, combined with subdivided affine
+// triangle drawing code
+//----------------------------------------------------------------------
+
+.globl C(D_PolysetDraw)
+C(D_PolysetDraw):
+
+//	spanpackage_t	spans[DPS_MAXSPANS + 1 +
+//			((CACHE_SIZE - 1) / sizeof(spanpackage_t)) + 1];
+//						// one extra because of cache line pretouching
+//
+//	a_spans = (spanpackage_t *)
+//			(((long)&spans[0] + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1));
+	subl	$(SPAN_SIZE),%esp
+	movl	%esp,%eax
+	addl	$(CACHE_SIZE - 1),%eax
+	andl	$(~(CACHE_SIZE - 1)),%eax
+	movl	%eax,C(a_spans)
+
+//	if (r_affinetridesc.drawtype)
+//		D_DrawSubdiv ();
+//	else
+//		D_DrawNonSubdiv ();
+	movl	C(r_affinetridesc)+atd_drawtype,%eax
+	testl	%eax,%eax
+	jz		C(D_DrawNonSubdiv)
+
+	pushl	%ebp				// preserve caller stack frame pointer
+
+//	lnumtriangles = r_affinetridesc.numtriangles;
+	movl	C(r_affinetridesc)+atd_numtriangles,%ebp
+
+	pushl	%esi				// preserve register variables
+	shll	$4,%ebp
+
+	pushl	%ebx
+//	ptri = r_affinetridesc.ptriangles;
+	movl	C(r_affinetridesc)+atd_ptriangles,%ebx
+
+	pushl	%edi
+
+//	mtriangle_t		*ptri;
+//	finalvert_t		*pfv, *index0, *index1, *index2;
+//	int				i;
+//	int				lnumtriangles;
+//	int				s0, s1, s2;
+
+//	pfv = r_affinetridesc.pfinalverts;
+	movl	C(r_affinetridesc)+atd_pfinalverts,%edi
+
+//	for (i=0 ; i<lnumtriangles ; i++)
+//	{
+
+Llooptop:
+
+//		index0 = pfv + ptri[i].vertindex[0];
+//		index1 = pfv + ptri[i].vertindex[1];
+//		index2 = pfv + ptri[i].vertindex[2];
+	movl	mtri_vertindex-16+0(%ebx,%ebp,),%ecx
+	movl	mtri_vertindex-16+4(%ebx,%ebp,),%esi
+
+	shll	$(fv_shift),%ecx
+	movl	mtri_vertindex-16+8(%ebx,%ebp,),%edx
+
+	shll	$(fv_shift),%esi
+	addl	%edi,%ecx
+
+	shll	$(fv_shift),%edx
+	addl	%edi,%esi
+
+	addl	%edi,%edx
+
+//		if (((index0->v[1]-index1->v[1]) *
+//				(index0->v[0]-index2->v[0]) -
+//				(index0->v[0]-index1->v[0])*(index0->v[1]-index2->v[1])) >= 0)
+//		{
+//			continue;
+//		}
+//
+//		d_pcolormap = &((byte *)acolormap)[index0->v[4] & 0xFF00];
+	fildl	fv_v+4(%ecx)	// i0v1
+	fildl	fv_v+4(%esi)	// i1v1 | i0v1
+	fildl	fv_v+0(%ecx)	// i0v0 | i1v1 | i0v1
+	fildl	fv_v+0(%edx)	// i2v0 | i0v0 | i1v1 | i0v1
+	fxch	%st(2)			// i1v1 | i0v0 | i2v0 | i0v1
+	fsubr	%st(3),%st(0)	// i0v1-i1v1 | i0v0 | i2v0 | i0v1
+	fildl	fv_v+0(%esi)	// i1v0 | i0v1-i1v1 | i0v0 | i2v0 | i0v1
+	fxch	%st(2)			// i0v0 | i0v1-i1v1 | i1v0 | i2v0 | i0v1
+	fsub	%st(0),%st(3)	// i0v0 | i0v1-i1v1 | i1v0 | i0v0-i2v0 | i0v1
+	fildl	fv_v+4(%edx)	// i2v1 | i0v0 | i0v1-i1v1 | i1v0 | i0v0-i2v0| i0v1
+	fxch	%st(1)			// i0v0 | i2v1 | i0v1-i1v1 | i1v0 | i0v0-i2v0| i0v1
+	fsubp	%st(0),%st(3)	// i2v1 | i0v1-i1v1 | i0v0-i1v0 | i0v0-i2v0 | i0v1
+	fxch	%st(1)			// i0v1-i1v1 | i2v1 | i0v0-i1v0 | i0v0-i2v0 | i0v1
+	fmulp	%st(0),%st(3)	// i2v1 | i0v0-i1v0 | i0v1-i1v1*i0v0-i2v0 | i0v1
+	fsubrp	%st(0),%st(3)	// i0v0-i1v0 | i0v1-i1v1*i0v0-i2v0 | i0v1-i2v1
+	movl	fv_v+16(%ecx),%eax
+	andl	$0xFF00,%eax
+	fmulp	%st(0),%st(2)	// i0v1-i1v1*i0v0-i2v0 | i0v0-i1v0*i0v1-i2v1
+	addl	C(acolormap),%eax
+	fsubp	%st(0),%st(1)	// (i0v1-i1v1)*(i0v0-i2v0)-(i0v0-i1v0)*(i0v1-i2v1)
+	movl	%eax,C(d_pcolormap)
+	fstps	Ltemp
+	movl	Ltemp,%eax
+	subl	$0x80000001,%eax
+	jc		Lskip
+
+//		if (ptri[i].facesfront)
+//		{
+//			D_PolysetRecursiveTriangle(index0->v, index1->v, index2->v);
+	movl	mtri_facesfront-16(%ebx,%ebp,),%eax
+	testl	%eax,%eax
+	jz		Lfacesback
+
+	pushl	%edx
+	pushl	%esi
+	pushl	%ecx
+	call	C(D_PolysetRecursiveTriangle)
+
+	subl	$16,%ebp
+	jnz		Llooptop
+	jmp		Ldone2
+
+//		}
+//		else
+//		{
+Lfacesback:
+
+//			s0 = index0->v[2];
+//			s1 = index1->v[2];
+//			s2 = index2->v[2];
+	movl	fv_v+8(%ecx),%eax
+	pushl	%eax
+	movl	fv_v+8(%esi),%eax
+	pushl	%eax
+	movl	fv_v+8(%edx),%eax
+	pushl	%eax
+	pushl	%ecx
+	pushl	%edx
+
+//			if (index0->flags & ALIAS_ONSEAM)
+//				index0->v[2] += r_affinetridesc.seamfixupX16;
+	movl	C(r_affinetridesc)+atd_seamfixupX16,%eax
+	testl	$(ALIAS_ONSEAM),fv_flags(%ecx)
+	jz		Lp11
+	addl	%eax,fv_v+8(%ecx)
+Lp11:
+
+//			if (index1->flags & ALIAS_ONSEAM)
+//				index1->v[2] += r_affinetridesc.seamfixupX16;
+	testl	$(ALIAS_ONSEAM),fv_flags(%esi)
+	jz		Lp12
+	addl	%eax,fv_v+8(%esi)
+Lp12:
+
+//			if (index2->flags & ALIAS_ONSEAM)
+//				index2->v[2] += r_affinetridesc.seamfixupX16;
+	testl	$(ALIAS_ONSEAM),fv_flags(%edx)
+	jz		Lp13
+	addl	%eax,fv_v+8(%edx)
+Lp13:
+
+//			D_PolysetRecursiveTriangle(index0->v, index1->v, index2->v);
+	pushl	%edx
+	pushl	%esi
+	pushl	%ecx
+	call	C(D_PolysetRecursiveTriangle)
+
+//			index0->v[2] = s0;
+//			index1->v[2] = s1;
+//			index2->v[2] = s2;
+	popl	%edx
+	popl	%ecx
+	popl	%eax
+	movl	%eax,fv_v+8(%edx)
+	popl	%eax
+	movl	%eax,fv_v+8(%esi)
+	popl	%eax
+	movl	%eax,fv_v+8(%ecx)
+
+//		}
+//	}
+Lskip:
+	subl	$16,%ebp
+	jnz		Llooptop
+
+Ldone2:
+	popl	%edi				// restore the caller's stack frame
+	popl	%ebx
+	popl	%esi				// restore register variables
+	popl	%ebp
+
+	addl	$(SPAN_SIZE),%esp
+
+	ret
+
+
+//----------------------------------------------------------------------
+// Alias model triangle left-edge scanning code
+//----------------------------------------------------------------------
+
+#define height	4+16
+
+.globl C(D_PolysetScanLeftEdge)
+C(D_PolysetScanLeftEdge):
+	pushl	%ebp				// preserve caller stack frame pointer
+	pushl	%esi				// preserve register variables
+	pushl	%edi
+	pushl	%ebx
+
+	movl	height(%esp),%eax
+	movl	C(d_sfrac),%ecx
+	andl	$0xFFFF,%eax
+	movl	C(d_ptex),%ebx
+	orl		%eax,%ecx
+	movl	C(d_pedgespanpackage),%esi
+	movl	C(d_tfrac),%edx
+	movl	C(d_light),%edi
+	movl	C(d_zi),%ebp
+
+// %eax: scratch
+// %ebx: d_ptex
+// %ecx: d_sfrac in high word, count in low word
+// %edx: d_tfrac
+// %esi: d_pedgespanpackage, errorterm, scratch alternately
+// %edi: d_light
+// %ebp: d_zi
+
+//	do
+//	{
+
+LScanLoop:
+
+//		d_pedgespanpackage->ptex = ptex;
+//		d_pedgespanpackage->pdest = d_pdest;
+//		d_pedgespanpackage->pz = d_pz;
+//		d_pedgespanpackage->count = d_aspancount;
+//		d_pedgespanpackage->light = d_light;
+//		d_pedgespanpackage->zi = d_zi;
+//		d_pedgespanpackage->sfrac = d_sfrac << 16;
+//		d_pedgespanpackage->tfrac = d_tfrac << 16;
+	movl	%ebx,spanpackage_t_ptex(%esi)
+	movl	C(d_pdest),%eax
+	movl	%eax,spanpackage_t_pdest(%esi)
+	movl	C(d_pz),%eax
+	movl	%eax,spanpackage_t_pz(%esi)
+	movl	C(d_aspancount),%eax
+	movl	%eax,spanpackage_t_count(%esi)
+	movl	%edi,spanpackage_t_light(%esi)
+	movl	%ebp,spanpackage_t_zi(%esi)
+	movl	%ecx,spanpackage_t_sfrac(%esi)
+	movl	%edx,spanpackage_t_tfrac(%esi)
+
+// pretouch the next cache line
+	movb	spanpackage_t_size(%esi),%al
+
+//		d_pedgespanpackage++;
+	addl	$(spanpackage_t_size),%esi
+	movl	C(erroradjustup),%eax
+	movl	%esi,C(d_pedgespanpackage)
+
+//		errorterm += erroradjustup;
+	movl	C(errorterm),%esi
+	addl	%eax,%esi
+	movl	C(d_pdest),%eax
+
+//		if (errorterm >= 0)
+//		{
+	js		LNoLeftEdgeTurnover
+
+//			errorterm -= erroradjustdown;
+//			d_pdest += d_pdestextrastep;
+	subl	C(erroradjustdown),%esi
+	addl	C(d_pdestextrastep),%eax
+	movl	%esi,C(errorterm)
+	movl	%eax,C(d_pdest)
+
+//			d_pz += d_pzextrastep;
+//			d_aspancount += d_countextrastep;
+//			d_ptex += d_ptexextrastep;
+//			d_sfrac += d_sfracextrastep;
+//			d_ptex += d_sfrac >> 16;
+//			d_sfrac &= 0xFFFF;
+//			d_tfrac += d_tfracextrastep;
+	movl	C(d_pz),%eax
+	movl	C(d_aspancount),%esi
+	addl	C(d_pzextrastep),%eax
+	addl	C(d_sfracextrastep),%ecx
+	adcl	C(d_ptexextrastep),%ebx
+	addl	C(d_countextrastep),%esi
+	movl	%eax,C(d_pz)
+	movl	C(d_tfracextrastep),%eax
+	movl	%esi,C(d_aspancount)
+	addl	%eax,%edx
+
+//			if (d_tfrac & 0x10000)
+//			{
+	jnc		LSkip1
+
+//				d_ptex += r_affinetridesc.skinwidth;
+//				d_tfrac &= 0xFFFF;
+	addl	C(r_affinetridesc)+atd_skinwidth,%ebx
+
+//			}
+
+LSkip1:
+
+//			d_light += d_lightextrastep;
+//			d_zi += d_ziextrastep;
+	addl	C(d_lightextrastep),%edi
+	addl	C(d_ziextrastep),%ebp
+
+//		}
+	movl	C(d_pedgespanpackage),%esi
+	decl	%ecx
+	testl	$0xFFFF,%ecx
+	jnz		LScanLoop
+
+	popl	%ebx
+	popl	%edi
+	popl	%esi
+	popl	%ebp
+	ret
+
+//		else
+//		{
+
+LNoLeftEdgeTurnover:
+	movl	%esi,C(errorterm)
+
+//			d_pdest += d_pdestbasestep;
+	addl	C(d_pdestbasestep),%eax
+	movl	%eax,C(d_pdest)
+
+//			d_pz += d_pzbasestep;
+//			d_aspancount += ubasestep;
+//			d_ptex += d_ptexbasestep;
+//			d_sfrac += d_sfracbasestep;
+//			d_ptex += d_sfrac >> 16;
+//			d_sfrac &= 0xFFFF;
+	movl	C(d_pz),%eax
+	movl	C(d_aspancount),%esi
+	addl	C(d_pzbasestep),%eax
+	addl	C(d_sfracbasestep),%ecx
+	adcl	C(d_ptexbasestep),%ebx
+	addl	C(ubasestep),%esi
+	movl	%eax,C(d_pz)
+	movl	%esi,C(d_aspancount)
+
+//			d_tfrac += d_tfracbasestep;
+	movl	C(d_tfracbasestep),%esi
+	addl	%esi,%edx
+
+//			if (d_tfrac & 0x10000)
+//			{
+	jnc		LSkip2
+
+//				d_ptex += r_affinetridesc.skinwidth;
+//				d_tfrac &= 0xFFFF;
+	addl	C(r_affinetridesc)+atd_skinwidth,%ebx
+
+//			}
+
+LSkip2:
+
+//			d_light += d_lightbasestep;
+//			d_zi += d_zibasestep;
+	addl	C(d_lightbasestep),%edi
+	addl	C(d_zibasestep),%ebp
+
+//		}
+//	} while (--height);
+	movl	C(d_pedgespanpackage),%esi
+	decl	%ecx
+	testl	$0xFFFF,%ecx
+	jnz		LScanLoop
+
+	popl	%ebx
+	popl	%edi
+	popl	%esi
+	popl	%ebp
+	ret
+
+
+//----------------------------------------------------------------------
+// Alias model vertex drawing code
+//----------------------------------------------------------------------
+
+#define fv			4+8
+#define	numverts	8+8
+
+.globl C(D_PolysetDrawFinalVerts)
+C(D_PolysetDrawFinalVerts):
+	pushl	%ebp				// preserve caller stack frame pointer
+	pushl	%ebx
+
+//	int		i, z;
+//	short	*zbuf;
+
+	movl	numverts(%esp),%ecx
+	movl	fv(%esp),%ebx
+
+	pushl	%esi				// preserve register variables
+	pushl	%edi
+
+LFVLoop:
+
+//	for (i=0 ; i<numverts ; i++, fv++)
+//	{
+//	// valid triangle coordinates for filling can include the bottom and
+//	// right clip edges, due to the fill rule; these shouldn't be drawn
+//		if ((fv->v[0] < r_refdef.vrectright) &&
+//			(fv->v[1] < r_refdef.vrectbottom))
+//		{
+	movl	fv_v+0(%ebx),%eax
+	movl	C(r_refdef)+rd_vrectright,%edx
+	cmpl	%edx,%eax
+	jge		LNextVert
+	movl	fv_v+4(%ebx),%esi
+	movl	C(r_refdef)+rd_vrectbottom,%edx
+	cmpl	%edx,%esi
+	jge		LNextVert
+
+//			zbuf = zspantable[fv->v[1]] + fv->v[0];
+	movl	C(zspantable)(,%esi,4),%edi
+
+//			z = fv->v[5]>>16;
+	movl	fv_v+20(%ebx),%edx
+	shrl	$16,%edx
+
+//			if (z >= *zbuf)
+//			{
+//				int		pix;
+	cmpw	(%edi,%eax,2),%dx
+	jl		LNextVert
+
+//				*zbuf = z;
+	movw	%dx,(%edi,%eax,2)
+
+//				pix = skintable[fv->v[3]>>16][fv->v[2]>>16];
+	movl	fv_v+12(%ebx),%edi
+	shrl	$16,%edi
+	movl	C(skintable)(,%edi,4),%edi
+	movl	fv_v+8(%ebx),%edx
+	shrl	$16,%edx
+	movb	(%edi,%edx),%dl
+
+//				pix = ((byte *)acolormap)[pix + (fv->v[4] & 0xFF00)];
+	movl	fv_v+16(%ebx),%edi
+	andl	$0xFF00,%edi
+	andl	$0x00FF,%edx
+	addl	%edx,%edi
+	movl	C(acolormap),%edx
+	movb	(%edx,%edi,1),%dl
+
+//				d_viewbuffer[d_scantable[fv->v[1]] + fv->v[0]] = pix;
+	movl	C(d_scantable)(,%esi,4),%edi
+	movl	C(d_viewbuffer),%esi
+	addl	%eax,%edi
+	movb	%dl,(%esi,%edi)
+
+//			}
+//		}
+//	}
+LNextVert:
+	addl	$(fv_size),%ebx
+	decl	%ecx
+	jnz		LFVLoop
+
+	popl	%edi
+	popl	%esi
+	popl	%ebx
+	popl	%ebp
+	ret
+
+
+//----------------------------------------------------------------------
+// Alias model non-subdivided polygon dispatching code
+//
+// not C-callable because of stack buffer cleanup
+//----------------------------------------------------------------------
+
+.globl C(D_DrawNonSubdiv)
+C(D_DrawNonSubdiv):
+	pushl	%ebp				// preserve caller stack frame pointer
+	movl	C(r_affinetridesc)+atd_numtriangles,%ebp
+	pushl	%ebx
+	shll	$(mtri_shift),%ebp
+	pushl	%esi				// preserve register variables
+	movl	C(r_affinetridesc)+atd_ptriangles,%esi
+	pushl	%edi
+
+//	mtriangle_t		*ptri;
+//	finalvert_t		*pfv, *index0, *index1, *index2;
+//	int				i;
+//	int				lnumtriangles;
+
+//	pfv = r_affinetridesc.pfinalverts;
+//	ptri = r_affinetridesc.ptriangles;
+//	lnumtriangles = r_affinetridesc.numtriangles;
+
+LNDLoop:
+
+//	for (i=0 ; i<lnumtriangles ; i++, ptri++)
+//	{
+//		index0 = pfv + ptri->vertindex[0];
+//		index1 = pfv + ptri->vertindex[1];
+//		index2 = pfv + ptri->vertindex[2];
+	movl	C(r_affinetridesc)+atd_pfinalverts,%edi
+	movl	mtri_vertindex+0-mtri_size(%esi,%ebp,1),%ecx
+	shll	$(fv_shift),%ecx
+	movl	mtri_vertindex+4-mtri_size(%esi,%ebp,1),%edx
+	shll	$(fv_shift),%edx
+	movl	mtri_vertindex+8-mtri_size(%esi,%ebp,1),%ebx
+	shll	$(fv_shift),%ebx
+	addl	%edi,%ecx
+	addl	%edi,%edx
+	addl	%edi,%ebx
+
+//		d_xdenom = (index0->v[1]-index1->v[1]) *
+//				(index0->v[0]-index2->v[0]) -
+//				(index0->v[0]-index1->v[0])*(index0->v[1]-index2->v[1]);
+	movl	fv_v+4(%ecx),%eax
+	movl	fv_v+0(%ecx),%esi
+	subl	fv_v+4(%edx),%eax
+	subl	fv_v+0(%ebx),%esi
+	imull	%esi,%eax
+	movl	fv_v+0(%ecx),%esi
+	movl	fv_v+4(%ecx),%edi
+	subl	fv_v+0(%edx),%esi
+	subl	fv_v+4(%ebx),%edi
+	imull	%esi,%edi
+	subl	%edi,%eax
+
+//		if (d_xdenom >= 0)
+//		{
+//			continue;
+	jns		LNextTri
+
+//		}
+
+	movl	%eax,C(d_xdenom)
+	fildl	C(d_xdenom)
+
+//		r_p0[0] = index0->v[0];		// u
+//		r_p0[1] = index0->v[1];		// v
+//		r_p0[2] = index0->v[2];		// s
+//		r_p0[3] = index0->v[3];		// t
+//		r_p0[4] = index0->v[4];		// light
+//		r_p0[5] = index0->v[5];		// iz
+	movl	fv_v+0(%ecx),%eax
+	movl	fv_v+4(%ecx),%esi
+	movl	%eax,C(r_p0)+0
+	movl	%esi,C(r_p0)+4
+	movl	fv_v+8(%ecx),%eax
+	movl	fv_v+12(%ecx),%esi
+	movl	%eax,C(r_p0)+8
+	movl	%esi,C(r_p0)+12
+	movl	fv_v+16(%ecx),%eax
+	movl	fv_v+20(%ecx),%esi
+	movl	%eax,C(r_p0)+16
+	movl	%esi,C(r_p0)+20
+
+	fdivrs	float_1
+
+//		r_p1[0] = index1->v[0];
+//		r_p1[1] = index1->v[1];
+//		r_p1[2] = index1->v[2];
+//		r_p1[3] = index1->v[3];
+//		r_p1[4] = index1->v[4];
+//		r_p1[5] = index1->v[5];
+	movl	fv_v+0(%edx),%eax
+	movl	fv_v+4(%edx),%esi
+	movl	%eax,C(r_p1)+0
+	movl	%esi,C(r_p1)+4
+	movl	fv_v+8(%edx),%eax
+	movl	fv_v+12(%edx),%esi
+	movl	%eax,C(r_p1)+8
+	movl	%esi,C(r_p1)+12
+	movl	fv_v+16(%edx),%eax
+	movl	fv_v+20(%edx),%esi
+	movl	%eax,C(r_p1)+16
+	movl	%esi,C(r_p1)+20
+
+//		r_p2[0] = index2->v[0];
+//		r_p2[1] = index2->v[1];
+//		r_p2[2] = index2->v[2];
+//		r_p2[3] = index2->v[3];
+//		r_p2[4] = index2->v[4];
+//		r_p2[5] = index2->v[5];
+	movl	fv_v+0(%ebx),%eax
+	movl	fv_v+4(%ebx),%esi
+	movl	%eax,C(r_p2)+0
+	movl	%esi,C(r_p2)+4
+	movl	fv_v+8(%ebx),%eax
+	movl	fv_v+12(%ebx),%esi
+	movl	%eax,C(r_p2)+8
+	movl	%esi,C(r_p2)+12
+	movl	fv_v+16(%ebx),%eax
+	movl	fv_v+20(%ebx),%esi
+	movl	%eax,C(r_p2)+16
+	movl	C(r_affinetridesc)+atd_ptriangles,%edi
+	movl	%esi,C(r_p2)+20
+	movl	mtri_facesfront-mtri_size(%edi,%ebp,1),%eax
+
+//		if (!ptri->facesfront)
+//		{
+	testl	%eax,%eax
+	jnz		LFacesFront
+
+//			if (index0->flags & ALIAS_ONSEAM)
+//				r_p0[2] += r_affinetridesc.seamfixupX16;
+	movl	fv_flags(%ecx),%eax
+	movl	fv_flags(%edx),%esi
+	movl	fv_flags(%ebx),%edi
+	testl	$(ALIAS_ONSEAM),%eax
+	movl	C(r_affinetridesc)+atd_seamfixupX16,%eax
+	jz		LOnseamDone0
+	addl	%eax,C(r_p0)+8
+LOnseamDone0:
+
+//			if (index1->flags & ALIAS_ONSEAM)
+// 				r_p1[2] += r_affinetridesc.seamfixupX16;
+	testl	$(ALIAS_ONSEAM),%esi
+	jz		LOnseamDone1
+	addl	%eax,C(r_p1)+8
+LOnseamDone1:
+
+//			if (index2->flags & ALIAS_ONSEAM)
+//				r_p2[2] += r_affinetridesc.seamfixupX16;
+	testl	$(ALIAS_ONSEAM),%edi
+	jz		LOnseamDone2
+	addl	%eax,C(r_p2)+8
+LOnseamDone2:
+
+//		}
+
+LFacesFront:
+
+	fstps	C(d_xdenom)
+
+//		D_PolysetSetEdgeTable ();
+//		D_RasterizeAliasPolySmooth ();
+		call	C(D_PolysetSetEdgeTable)
+		call	C(D_RasterizeAliasPolySmooth)
+
+LNextTri:
+		movl	C(r_affinetridesc)+atd_ptriangles,%esi
+		subl	$16,%ebp
+		jnz		LNDLoop
+//	}
+
+	popl	%edi
+	popl	%esi
+	popl	%ebx
+	popl	%ebp
+
+	addl	$(SPAN_SIZE),%esp
+
+	ret
+
+
+#endif	// id386
+
--- /dev/null
+++ b/WinQuake/d_polyse.c
@@ -1,0 +1,1111 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// d_polyset.c: routines for drawing sets of polygons sharing the same
+// texture (used for Alias models)
+
+#include "quakedef.h"
+#include "r_local.h"
+#include "d_local.h"
+
+// TODO: put in span spilling to shrink list size
+// !!! if this is changed, it must be changed in d_polysa.s too !!!
+#define DPS_MAXSPANS			MAXHEIGHT+1	
+									// 1 extra for spanpackage that marks end
+
+// !!! if this is changed, it must be changed in asm_draw.h too !!!
+typedef struct {
+	void			*pdest;
+	short			*pz;
+	int				count;
+	byte			*ptex;
+	int				sfrac, tfrac, light, zi;
+} spanpackage_t;
+
+typedef struct {
+	int		isflattop;
+	int		numleftedges;
+	int		*pleftedgevert0;
+	int		*pleftedgevert1;
+	int		*pleftedgevert2;
+	int		numrightedges;
+	int		*prightedgevert0;
+	int		*prightedgevert1;
+	int		*prightedgevert2;
+} edgetable;
+
+int	r_p0[6], r_p1[6], r_p2[6];
+
+byte		*d_pcolormap;
+
+int			d_aflatcolor;
+int			d_xdenom;
+
+edgetable	*pedgetable;
+
+edgetable	edgetables[12] = {
+	{0, 1, r_p0, r_p2, NULL, 2, r_p0, r_p1, r_p2 },
+	{0, 2, r_p1, r_p0, r_p2,   1, r_p1, r_p2, NULL},
+	{1, 1, r_p0, r_p2, NULL, 1, r_p1, r_p2, NULL},
+	{0, 1, r_p1, r_p0, NULL, 2, r_p1, r_p2, r_p0 },
+	{0, 2, r_p0, r_p2, r_p1,   1, r_p0, r_p1, NULL},
+	{0, 1, r_p2, r_p1, NULL, 1, r_p2, r_p0, NULL},
+	{0, 1, r_p2, r_p1, NULL, 2, r_p2, r_p0, r_p1 },
+	{0, 2, r_p2, r_p1, r_p0,   1, r_p2, r_p0, NULL},
+	{0, 1, r_p1, r_p0, NULL, 1, r_p1, r_p2, NULL},
+	{1, 1, r_p2, r_p1, NULL, 1, r_p0, r_p1, NULL},
+	{1, 1, r_p1, r_p0, NULL, 1, r_p2, r_p0, NULL},
+	{0, 1, r_p0, r_p2, NULL, 1, r_p0, r_p1, NULL},
+};
+
+// FIXME: some of these can become statics
+int				a_sstepxfrac, a_tstepxfrac, r_lstepx, a_ststepxwhole;
+int				r_sstepx, r_tstepx, r_lstepy, r_sstepy, r_tstepy;
+int				r_zistepx, r_zistepy;
+int				d_aspancount, d_countextrastep;
+
+spanpackage_t			*a_spans;
+spanpackage_t			*d_pedgespanpackage;
+static int				ystart;
+byte					*d_pdest, *d_ptex;
+short					*d_pz;
+int						d_sfrac, d_tfrac, d_light, d_zi;
+int						d_ptexextrastep, d_sfracextrastep;
+int						d_tfracextrastep, d_lightextrastep, d_pdestextrastep;
+int						d_lightbasestep, d_pdestbasestep, d_ptexbasestep;
+int						d_sfracbasestep, d_tfracbasestep;
+int						d_ziextrastep, d_zibasestep;
+int						d_pzextrastep, d_pzbasestep;
+
+typedef struct {
+	int		quotient;
+	int		remainder;
+} adivtab_t;
+
+static adivtab_t	adivtab[32*32] = {
+#include "adivtab.h"
+};
+
+byte	*skintable[MAX_LBM_HEIGHT];
+int		skinwidth;
+byte	*skinstart;
+
+void D_PolysetDrawSpans8 (spanpackage_t *pspanpackage);
+void D_PolysetCalcGradients (int skinwidth);
+void D_DrawSubdiv (void);
+void D_DrawNonSubdiv (void);
+void D_PolysetRecursiveTriangle (int *p1, int *p2, int *p3);
+void D_PolysetSetEdgeTable (void);
+void D_RasterizeAliasPolySmooth (void);
+void D_PolysetScanLeftEdge (int height);
+
+#if	!id386
+
+/*
+================
+D_PolysetDraw
+================
+*/
+void D_PolysetDraw (void)
+{
+	spanpackage_t	spans[DPS_MAXSPANS + 1 +
+			((CACHE_SIZE - 1) / sizeof(spanpackage_t)) + 1];
+						// one extra because of cache line pretouching
+
+	a_spans = (spanpackage_t *)
+			(((long)&spans[0] + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1));
+
+	if (r_affinetridesc.drawtype)
+	{
+		D_DrawSubdiv ();
+	}
+	else
+	{
+		D_DrawNonSubdiv ();
+	}
+}
+
+
+/*
+================
+D_PolysetDrawFinalVerts
+================
+*/
+void D_PolysetDrawFinalVerts (finalvert_t *fv, int numverts)
+{
+	int		i, z;
+	short	*zbuf;
+
+	for (i=0 ; i<numverts ; i++, fv++)
+	{
+	// valid triangle coordinates for filling can include the bottom and
+	// right clip edges, due to the fill rule; these shouldn't be drawn
+		if ((fv->v[0] < r_refdef.vrectright) &&
+			(fv->v[1] < r_refdef.vrectbottom))
+		{
+			z = fv->v[5]>>16;
+			zbuf = zspantable[fv->v[1]] + fv->v[0];
+			if (z >= *zbuf)
+			{
+				int		pix;
+				
+				*zbuf = z;
+				pix = skintable[fv->v[3]>>16][fv->v[2]>>16];
+				pix = ((byte *)acolormap)[pix + (fv->v[4] & 0xFF00) ];
+				d_viewbuffer[d_scantable[fv->v[1]] + fv->v[0]] = pix;
+			}
+		}
+	}
+}
+
+
+/*
+================
+D_DrawSubdiv
+================
+*/
+void D_DrawSubdiv (void)
+{
+	mtriangle_t		*ptri;
+	finalvert_t		*pfv, *index0, *index1, *index2;
+	int				i;
+	int				lnumtriangles;
+
+	pfv = r_affinetridesc.pfinalverts;
+	ptri = r_affinetridesc.ptriangles;
+	lnumtriangles = r_affinetridesc.numtriangles;
+
+	for (i=0 ; i<lnumtriangles ; i++)
+	{
+		index0 = pfv + ptri[i].vertindex[0];
+		index1 = pfv + ptri[i].vertindex[1];
+		index2 = pfv + ptri[i].vertindex[2];
+
+		if (((index0->v[1]-index1->v[1]) *
+			 (index0->v[0]-index2->v[0]) -
+			 (index0->v[0]-index1->v[0]) * 
+			 (index0->v[1]-index2->v[1])) >= 0)
+		{
+			continue;
+		}
+
+		d_pcolormap = &((byte *)acolormap)[index0->v[4] & 0xFF00];
+
+		if (ptri[i].facesfront)
+		{
+			D_PolysetRecursiveTriangle(index0->v, index1->v, index2->v);
+		}
+		else
+		{
+			int		s0, s1, s2;
+
+			s0 = index0->v[2];
+			s1 = index1->v[2];
+			s2 = index2->v[2];
+
+			if (index0->flags & ALIAS_ONSEAM)
+				index0->v[2] += r_affinetridesc.seamfixupX16;
+			if (index1->flags & ALIAS_ONSEAM)
+				index1->v[2] += r_affinetridesc.seamfixupX16;
+			if (index2->flags & ALIAS_ONSEAM)
+				index2->v[2] += r_affinetridesc.seamfixupX16;
+
+			D_PolysetRecursiveTriangle(index0->v, index1->v, index2->v);
+
+			index0->v[2] = s0;
+			index1->v[2] = s1;
+			index2->v[2] = s2;
+		}
+	}
+}
+
+
+/*
+================
+D_DrawNonSubdiv
+================
+*/
+void D_DrawNonSubdiv (void)
+{
+	mtriangle_t		*ptri;
+	finalvert_t		*pfv, *index0, *index1, *index2;
+	int				i;
+	int				lnumtriangles;
+
+	pfv = r_affinetridesc.pfinalverts;
+	ptri = r_affinetridesc.ptriangles;
+	lnumtriangles = r_affinetridesc.numtriangles;
+
+	for (i=0 ; i<lnumtriangles ; i++, ptri++)
+	{
+		index0 = pfv + ptri->vertindex[0];
+		index1 = pfv + ptri->vertindex[1];
+		index2 = pfv + ptri->vertindex[2];
+
+		d_xdenom = (index0->v[1]-index1->v[1]) *
+				(index0->v[0]-index2->v[0]) -
+				(index0->v[0]-index1->v[0])*(index0->v[1]-index2->v[1]);
+
+		if (d_xdenom >= 0)
+		{
+			continue;
+		}
+
+		r_p0[0] = index0->v[0];		// u
+		r_p0[1] = index0->v[1];		// v
+		r_p0[2] = index0->v[2];		// s
+		r_p0[3] = index0->v[3];		// t
+		r_p0[4] = index0->v[4];		// light
+		r_p0[5] = index0->v[5];		// iz
+
+		r_p1[0] = index1->v[0];
+		r_p1[1] = index1->v[1];
+		r_p1[2] = index1->v[2];
+		r_p1[3] = index1->v[3];
+		r_p1[4] = index1->v[4];
+		r_p1[5] = index1->v[5];
+
+		r_p2[0] = index2->v[0];
+		r_p2[1] = index2->v[1];
+		r_p2[2] = index2->v[2];
+		r_p2[3] = index2->v[3];
+		r_p2[4] = index2->v[4];
+		r_p2[5] = index2->v[5];
+
+		if (!ptri->facesfront)
+		{
+			if (index0->flags & ALIAS_ONSEAM)
+				r_p0[2] += r_affinetridesc.seamfixupX16;
+			if (index1->flags & ALIAS_ONSEAM)
+				r_p1[2] += r_affinetridesc.seamfixupX16;
+			if (index2->flags & ALIAS_ONSEAM)
+				r_p2[2] += r_affinetridesc.seamfixupX16;
+		}
+
+		D_PolysetSetEdgeTable ();
+		D_RasterizeAliasPolySmooth ();
+	}
+}
+
+
+/*
+================
+D_PolysetRecursiveTriangle
+================
+*/
+void D_PolysetRecursiveTriangle (int *lp1, int *lp2, int *lp3)
+{
+	int		*temp;
+	int		d;
+	int		new[6];
+	int		z;
+	short	*zbuf;
+
+	d = lp2[0] - lp1[0];
+	if (d < -1 || d > 1)
+		goto split;
+	d = lp2[1] - lp1[1];
+	if (d < -1 || d > 1)
+		goto split;
+
+	d = lp3[0] - lp2[0];
+	if (d < -1 || d > 1)
+		goto split2;
+	d = lp3[1] - lp2[1];
+	if (d < -1 || d > 1)
+		goto split2;
+
+	d = lp1[0] - lp3[0];
+	if (d < -1 || d > 1)
+		goto split3;
+	d = lp1[1] - lp3[1];
+	if (d < -1 || d > 1)
+	{
+split3:
+		temp = lp1;
+		lp1 = lp3;
+		lp3 = lp2;
+		lp2 = temp;
+
+		goto split;
+	}
+
+	return;			// entire tri is filled
+
+split2:
+	temp = lp1;
+	lp1 = lp2;
+	lp2 = lp3;
+	lp3 = temp;
+
+split:
+// split this edge
+	new[0] = (lp1[0] + lp2[0]) >> 1;
+	new[1] = (lp1[1] + lp2[1]) >> 1;
+	new[2] = (lp1[2] + lp2[2]) >> 1;
+	new[3] = (lp1[3] + lp2[3]) >> 1;
+	new[5] = (lp1[5] + lp2[5]) >> 1;
+
+// draw the point if splitting a leading edge
+	if (lp2[1] > lp1[1])
+		goto nodraw;
+	if ((lp2[1] == lp1[1]) && (lp2[0] < lp1[0]))
+		goto nodraw;
+
+
+	z = new[5]>>16;
+	zbuf = zspantable[new[1]] + new[0];
+	if (z >= *zbuf)
+	{
+		int		pix;
+		
+		*zbuf = z;
+		pix = d_pcolormap[skintable[new[3]>>16][new[2]>>16]];
+		d_viewbuffer[d_scantable[new[1]] + new[0]] = pix;
+	}
+
+nodraw:
+// recursively continue
+	D_PolysetRecursiveTriangle (lp3, lp1, new);
+	D_PolysetRecursiveTriangle (lp3, new, lp2);
+}
+
+#endif	// !id386
+
+
+/*
+================
+D_PolysetUpdateTables
+================
+*/
+void D_PolysetUpdateTables (void)
+{
+	int		i;
+	byte	*s;
+	
+	if (r_affinetridesc.skinwidth != skinwidth ||
+		r_affinetridesc.pskin != skinstart)
+	{
+		skinwidth = r_affinetridesc.skinwidth;
+		skinstart = r_affinetridesc.pskin;
+		s = skinstart;
+		for (i=0 ; i<MAX_LBM_HEIGHT ; i++, s+=skinwidth)
+			skintable[i] = s;
+	}
+}
+
+
+#if	!id386
+
+/*
+===================
+D_PolysetScanLeftEdge
+====================
+*/
+void D_PolysetScanLeftEdge (int height)
+{
+
+	do
+	{
+		d_pedgespanpackage->pdest = d_pdest;
+		d_pedgespanpackage->pz = d_pz;
+		d_pedgespanpackage->count = d_aspancount;
+		d_pedgespanpackage->ptex = d_ptex;
+
+		d_pedgespanpackage->sfrac = d_sfrac;
+		d_pedgespanpackage->tfrac = d_tfrac;
+
+	// FIXME: need to clamp l, s, t, at both ends?
+		d_pedgespanpackage->light = d_light;
+		d_pedgespanpackage->zi = d_zi;
+
+		d_pedgespanpackage++;
+
+		errorterm += erroradjustup;
+		if (errorterm >= 0)
+		{
+			d_pdest += d_pdestextrastep;
+			d_pz += d_pzextrastep;
+			d_aspancount += d_countextrastep;
+			d_ptex += d_ptexextrastep;
+			d_sfrac += d_sfracextrastep;
+			d_ptex += d_sfrac >> 16;
+
+			d_sfrac &= 0xFFFF;
+			d_tfrac += d_tfracextrastep;
+			if (d_tfrac & 0x10000)
+			{
+				d_ptex += r_affinetridesc.skinwidth;
+				d_tfrac &= 0xFFFF;
+			}
+			d_light += d_lightextrastep;
+			d_zi += d_ziextrastep;
+			errorterm -= erroradjustdown;
+		}
+		else
+		{
+			d_pdest += d_pdestbasestep;
+			d_pz += d_pzbasestep;
+			d_aspancount += ubasestep;
+			d_ptex += d_ptexbasestep;
+			d_sfrac += d_sfracbasestep;
+			d_ptex += d_sfrac >> 16;
+			d_sfrac &= 0xFFFF;
+			d_tfrac += d_tfracbasestep;
+			if (d_tfrac & 0x10000)
+			{
+				d_ptex += r_affinetridesc.skinwidth;
+				d_tfrac &= 0xFFFF;
+			}
+			d_light += d_lightbasestep;
+			d_zi += d_zibasestep;
+		}
+	} while (--height);
+}
+
+#endif	// !id386
+
+
+/*
+===================
+D_PolysetSetUpForLineScan
+====================
+*/
+void D_PolysetSetUpForLineScan(fixed8_t startvertu, fixed8_t startvertv,
+		fixed8_t endvertu, fixed8_t endvertv)
+{
+	double		dm, dn;
+	int			tm, tn;
+	adivtab_t	*ptemp;
+
+// TODO: implement x86 version
+
+	errorterm = -1;
+
+	tm = endvertu - startvertu;
+	tn = endvertv - startvertv;
+
+	if (((tm <= 16) && (tm >= -15)) &&
+		((tn <= 16) && (tn >= -15)))
+	{
+		ptemp = &adivtab[((tm+15) << 5) + (tn+15)];
+		ubasestep = ptemp->quotient;
+		erroradjustup = ptemp->remainder;
+		erroradjustdown = tn;
+	}
+	else
+	{
+		dm = (double)tm;
+		dn = (double)tn;
+
+		FloorDivMod (dm, dn, &ubasestep, &erroradjustup);
+
+		erroradjustdown = dn;
+	}
+}
+
+
+#if	!id386
+
+/*
+================
+D_PolysetCalcGradients
+================
+*/
+void D_PolysetCalcGradients (int skinwidth)
+{
+	float	xstepdenominv, ystepdenominv, t0, t1;
+	float	p01_minus_p21, p11_minus_p21, p00_minus_p20, p10_minus_p20;
+
+	p00_minus_p20 = r_p0[0] - r_p2[0];
+	p01_minus_p21 = r_p0[1] - r_p2[1];
+	p10_minus_p20 = r_p1[0] - r_p2[0];
+	p11_minus_p21 = r_p1[1] - r_p2[1];
+
+	xstepdenominv = 1.0 / (float)d_xdenom;
+
+	ystepdenominv = -xstepdenominv;
+
+// ceil () for light so positive steps are exaggerated, negative steps
+// diminished,  pushing us away from underflow toward overflow. Underflow is
+// very visible, overflow is very unlikely, because of ambient lighting
+	t0 = r_p0[4] - r_p2[4];
+	t1 = r_p1[4] - r_p2[4];
+	r_lstepx = (int)
+			ceil((t1 * p01_minus_p21 - t0 * p11_minus_p21) * xstepdenominv);
+	r_lstepy = (int)
+			ceil((t1 * p00_minus_p20 - t0 * p10_minus_p20) * ystepdenominv);
+
+	t0 = r_p0[2] - r_p2[2];
+	t1 = r_p1[2] - r_p2[2];
+	r_sstepx = (int)((t1 * p01_minus_p21 - t0 * p11_minus_p21) *
+			xstepdenominv);
+	r_sstepy = (int)((t1 * p00_minus_p20 - t0* p10_minus_p20) *
+			ystepdenominv);
+
+	t0 = r_p0[3] - r_p2[3];
+	t1 = r_p1[3] - r_p2[3];
+	r_tstepx = (int)((t1 * p01_minus_p21 - t0 * p11_minus_p21) *
+			xstepdenominv);
+	r_tstepy = (int)((t1 * p00_minus_p20 - t0 * p10_minus_p20) *
+			ystepdenominv);
+
+	t0 = r_p0[5] - r_p2[5];
+	t1 = r_p1[5] - r_p2[5];
+	r_zistepx = (int)((t1 * p01_minus_p21 - t0 * p11_minus_p21) *
+			xstepdenominv);
+	r_zistepy = (int)((t1 * p00_minus_p20 - t0 * p10_minus_p20) *
+			ystepdenominv);
+
+#if	id386
+	a_sstepxfrac = r_sstepx << 16;
+	a_tstepxfrac = r_tstepx << 16;
+#else
+	a_sstepxfrac = r_sstepx & 0xFFFF;
+	a_tstepxfrac = r_tstepx & 0xFFFF;
+#endif
+
+	a_ststepxwhole = skinwidth * (r_tstepx >> 16) + (r_sstepx >> 16);
+}
+
+#endif	// !id386
+
+
+#if 0
+byte gelmap[256];
+void InitGel (byte *palette)
+{
+	int		i;
+	int		r;
+
+	for (i=0 ; i<256 ; i++)
+	{
+//		r = (palette[i*3]>>4);
+		r = (palette[i*3] + palette[i*3+1] + palette[i*3+2])/(16*3);
+		gelmap[i] = /* 64 */ 0 + r;
+	}
+}
+#endif
+
+
+#if	!id386
+
+/*
+================
+D_PolysetDrawSpans8
+================
+*/
+void D_PolysetDrawSpans8 (spanpackage_t *pspanpackage)
+{
+	int		lcount;
+	byte	*lpdest;
+	byte	*lptex;
+	int		lsfrac, ltfrac;
+	int		llight;
+	int		lzi;
+	short	*lpz;
+
+	do
+	{
+		lcount = d_aspancount - pspanpackage->count;
+
+		errorterm += erroradjustup;
+		if (errorterm >= 0)
+		{
+			d_aspancount += d_countextrastep;
+			errorterm -= erroradjustdown;
+		}
+		else
+		{
+			d_aspancount += ubasestep;
+		}
+
+		if (lcount)
+		{
+			lpdest = pspanpackage->pdest;
+			lptex = pspanpackage->ptex;
+			lpz = pspanpackage->pz;
+			lsfrac = pspanpackage->sfrac;
+			ltfrac = pspanpackage->tfrac;
+			llight = pspanpackage->light;
+			lzi = pspanpackage->zi;
+
+			do
+			{
+				if ((lzi >> 16) >= *lpz)
+				{
+					*lpdest = ((byte *)acolormap)[*lptex + (llight & 0xFF00)];
+// gel mapping					*lpdest = gelmap[*lpdest];
+					*lpz = lzi >> 16;
+				}
+				lpdest++;
+				lzi += r_zistepx;
+				lpz++;
+				llight += r_lstepx;
+				lptex += a_ststepxwhole;
+				lsfrac += a_sstepxfrac;
+				lptex += lsfrac >> 16;
+				lsfrac &= 0xFFFF;
+				ltfrac += a_tstepxfrac;
+				if (ltfrac & 0x10000)
+				{
+					lptex += r_affinetridesc.skinwidth;
+					ltfrac &= 0xFFFF;
+				}
+			} while (--lcount);
+		}
+
+		pspanpackage++;
+	} while (pspanpackage->count != -999999);
+}
+#endif	// !id386
+
+
+/*
+================
+D_PolysetFillSpans8
+================
+*/
+void D_PolysetFillSpans8 (spanpackage_t *pspanpackage)
+{
+	int				color;
+
+// FIXME: do z buffering
+
+	color = d_aflatcolor++;
+
+	while (1)
+	{
+		int		lcount;
+		byte	*lpdest;
+
+		lcount = pspanpackage->count;
+
+		if (lcount == -1)
+			return;
+
+		if (lcount)
+		{
+			lpdest = pspanpackage->pdest;
+
+			do
+			{
+				*lpdest++ = color;
+			} while (--lcount);
+		}
+
+		pspanpackage++;
+	}
+}
+
+/*
+================
+D_RasterizeAliasPolySmooth
+================
+*/
+void D_RasterizeAliasPolySmooth (void)
+{
+	int				initialleftheight, initialrightheight;
+	int				*plefttop, *prighttop, *pleftbottom, *prightbottom;
+	int				working_lstepx, originalcount;
+
+	plefttop = pedgetable->pleftedgevert0;
+	prighttop = pedgetable->prightedgevert0;
+
+	pleftbottom = pedgetable->pleftedgevert1;
+	prightbottom = pedgetable->prightedgevert1;
+
+	initialleftheight = pleftbottom[1] - plefttop[1];
+	initialrightheight = prightbottom[1] - prighttop[1];
+
+//
+// set the s, t, and light gradients, which are consistent across the triangle
+// because being a triangle, things are affine
+//
+	D_PolysetCalcGradients (r_affinetridesc.skinwidth);
+
+//
+// rasterize the polygon
+//
+
+//
+// scan out the top (and possibly only) part of the left edge
+//
+	d_pedgespanpackage = a_spans;
+
+	ystart = plefttop[1];
+	d_aspancount = plefttop[0] - prighttop[0];
+
+	d_ptex = (byte *)r_affinetridesc.pskin + (plefttop[2] >> 16) +
+			(plefttop[3] >> 16) * r_affinetridesc.skinwidth;
+#if	id386
+	d_sfrac = (plefttop[2] & 0xFFFF) << 16;
+	d_tfrac = (plefttop[3] & 0xFFFF) << 16;
+#else
+	d_sfrac = plefttop[2] & 0xFFFF;
+	d_tfrac = plefttop[3] & 0xFFFF;
+#endif
+	d_light = plefttop[4];
+	d_zi = plefttop[5];
+
+	d_pdest = (byte *)d_viewbuffer +
+			ystart * screenwidth + plefttop[0];
+	d_pz = d_pzbuffer + ystart * d_zwidth + plefttop[0];
+
+	if (initialleftheight == 1)
+	{
+		d_pedgespanpackage->pdest = d_pdest;
+		d_pedgespanpackage->pz = d_pz;
+		d_pedgespanpackage->count = d_aspancount;
+		d_pedgespanpackage->ptex = d_ptex;
+
+		d_pedgespanpackage->sfrac = d_sfrac;
+		d_pedgespanpackage->tfrac = d_tfrac;
+
+	// FIXME: need to clamp l, s, t, at both ends?
+		d_pedgespanpackage->light = d_light;
+		d_pedgespanpackage->zi = d_zi;
+
+		d_pedgespanpackage++;
+	}
+	else
+	{
+		D_PolysetSetUpForLineScan(plefttop[0], plefttop[1],
+							  pleftbottom[0], pleftbottom[1]);
+
+	#if	id386
+		d_pzbasestep = (d_zwidth + ubasestep) << 1;
+		d_pzextrastep = d_pzbasestep + 2;
+	#else
+		d_pzbasestep = d_zwidth + ubasestep;
+		d_pzextrastep = d_pzbasestep + 1;
+	#endif
+
+		d_pdestbasestep = screenwidth + ubasestep;
+		d_pdestextrastep = d_pdestbasestep + 1;
+
+	// TODO: can reuse partial expressions here
+
+	// for negative steps in x along left edge, bias toward overflow rather than
+	// underflow (sort of turning the floor () we did in the gradient calcs into
+	// ceil (), but plus a little bit)
+		if (ubasestep < 0)
+			working_lstepx = r_lstepx - 1;
+		else
+			working_lstepx = r_lstepx;
+
+		d_countextrastep = ubasestep + 1;
+		d_ptexbasestep = ((r_sstepy + r_sstepx * ubasestep) >> 16) +
+				((r_tstepy + r_tstepx * ubasestep) >> 16) *
+				r_affinetridesc.skinwidth;
+	#if	id386
+		d_sfracbasestep = (r_sstepy + r_sstepx * ubasestep) << 16;
+		d_tfracbasestep = (r_tstepy + r_tstepx * ubasestep) << 16;
+	#else
+		d_sfracbasestep = (r_sstepy + r_sstepx * ubasestep) & 0xFFFF;
+		d_tfracbasestep = (r_tstepy + r_tstepx * ubasestep) & 0xFFFF;
+	#endif
+		d_lightbasestep = r_lstepy + working_lstepx * ubasestep;
+		d_zibasestep = r_zistepy + r_zistepx * ubasestep;
+
+		d_ptexextrastep = ((r_sstepy + r_sstepx * d_countextrastep) >> 16) +
+				((r_tstepy + r_tstepx * d_countextrastep) >> 16) *
+				r_affinetridesc.skinwidth;
+	#if	id386
+		d_sfracextrastep = (r_sstepy + r_sstepx*d_countextrastep) << 16;
+		d_tfracextrastep = (r_tstepy + r_tstepx*d_countextrastep) << 16;
+	#else
+		d_sfracextrastep = (r_sstepy + r_sstepx*d_countextrastep) & 0xFFFF;
+		d_tfracextrastep = (r_tstepy + r_tstepx*d_countextrastep) & 0xFFFF;
+	#endif
+		d_lightextrastep = d_lightbasestep + working_lstepx;
+		d_ziextrastep = d_zibasestep + r_zistepx;
+
+		D_PolysetScanLeftEdge (initialleftheight);
+	}
+
+//
+// scan out the bottom part of the left edge, if it exists
+//
+	if (pedgetable->numleftedges == 2)
+	{
+		int		height;
+
+		plefttop = pleftbottom;
+		pleftbottom = pedgetable->pleftedgevert2;
+
+		height = pleftbottom[1] - plefttop[1];
+
+// TODO: make this a function; modularize this function in general
+
+		ystart = plefttop[1];
+		d_aspancount = plefttop[0] - prighttop[0];
+		d_ptex = (byte *)r_affinetridesc.pskin + (plefttop[2] >> 16) +
+				(plefttop[3] >> 16) * r_affinetridesc.skinwidth;
+		d_sfrac = 0;
+		d_tfrac = 0;
+		d_light = plefttop[4];
+		d_zi = plefttop[5];
+
+		d_pdest = (byte *)d_viewbuffer + ystart * screenwidth + plefttop[0];
+		d_pz = d_pzbuffer + ystart * d_zwidth + plefttop[0];
+
+		if (height == 1)
+		{
+			d_pedgespanpackage->pdest = d_pdest;
+			d_pedgespanpackage->pz = d_pz;
+			d_pedgespanpackage->count = d_aspancount;
+			d_pedgespanpackage->ptex = d_ptex;
+
+			d_pedgespanpackage->sfrac = d_sfrac;
+			d_pedgespanpackage->tfrac = d_tfrac;
+
+		// FIXME: need to clamp l, s, t, at both ends?
+			d_pedgespanpackage->light = d_light;
+			d_pedgespanpackage->zi = d_zi;
+
+			d_pedgespanpackage++;
+		}
+		else
+		{
+			D_PolysetSetUpForLineScan(plefttop[0], plefttop[1],
+								  pleftbottom[0], pleftbottom[1]);
+
+			d_pdestbasestep = screenwidth + ubasestep;
+			d_pdestextrastep = d_pdestbasestep + 1;
+
+	#if	id386
+			d_pzbasestep = (d_zwidth + ubasestep) << 1;
+			d_pzextrastep = d_pzbasestep + 2;
+	#else
+			d_pzbasestep = d_zwidth + ubasestep;
+			d_pzextrastep = d_pzbasestep + 1;
+	#endif
+
+			if (ubasestep < 0)
+				working_lstepx = r_lstepx - 1;
+			else
+				working_lstepx = r_lstepx;
+
+			d_countextrastep = ubasestep + 1;
+			d_ptexbasestep = ((r_sstepy + r_sstepx * ubasestep) >> 16) +
+					((r_tstepy + r_tstepx * ubasestep) >> 16) *
+					r_affinetridesc.skinwidth;
+	#if	id386
+			d_sfracbasestep = (r_sstepy + r_sstepx * ubasestep) << 16;
+			d_tfracbasestep = (r_tstepy + r_tstepx * ubasestep) << 16;
+	#else
+			d_sfracbasestep = (r_sstepy + r_sstepx * ubasestep) & 0xFFFF;
+			d_tfracbasestep = (r_tstepy + r_tstepx * ubasestep) & 0xFFFF;
+	#endif
+			d_lightbasestep = r_lstepy + working_lstepx * ubasestep;
+			d_zibasestep = r_zistepy + r_zistepx * ubasestep;
+
+			d_ptexextrastep = ((r_sstepy + r_sstepx * d_countextrastep) >> 16) +
+					((r_tstepy + r_tstepx * d_countextrastep) >> 16) *
+					r_affinetridesc.skinwidth;
+	#if	id386
+			d_sfracextrastep = ((r_sstepy+r_sstepx*d_countextrastep) & 0xFFFF)<<16;
+			d_tfracextrastep = ((r_tstepy+r_tstepx*d_countextrastep) & 0xFFFF)<<16;
+	#else
+			d_sfracextrastep = (r_sstepy+r_sstepx*d_countextrastep) & 0xFFFF;
+			d_tfracextrastep = (r_tstepy+r_tstepx*d_countextrastep) & 0xFFFF;
+	#endif
+			d_lightextrastep = d_lightbasestep + working_lstepx;
+			d_ziextrastep = d_zibasestep + r_zistepx;
+
+			D_PolysetScanLeftEdge (height);
+		}
+	}
+
+// scan out the top (and possibly only) part of the right edge, updating the
+// count field
+	d_pedgespanpackage = a_spans;
+
+	D_PolysetSetUpForLineScan(prighttop[0], prighttop[1],
+						  prightbottom[0], prightbottom[1]);
+	d_aspancount = 0;
+	d_countextrastep = ubasestep + 1;
+	originalcount = a_spans[initialrightheight].count;
+	a_spans[initialrightheight].count = -999999; // mark end of the spanpackages
+	D_PolysetDrawSpans8 (a_spans);
+
+// scan out the bottom part of the right edge, if it exists
+	if (pedgetable->numrightedges == 2)
+	{
+		int				height;
+		spanpackage_t	*pstart;
+
+		pstart = a_spans + initialrightheight;
+		pstart->count = originalcount;
+
+		d_aspancount = prightbottom[0] - prighttop[0];
+
+		prighttop = prightbottom;
+		prightbottom = pedgetable->prightedgevert2;
+
+		height = prightbottom[1] - prighttop[1];
+
+		D_PolysetSetUpForLineScan(prighttop[0], prighttop[1],
+							  prightbottom[0], prightbottom[1]);
+
+		d_countextrastep = ubasestep + 1;
+		a_spans[initialrightheight + height].count = -999999;
+											// mark end of the spanpackages
+		D_PolysetDrawSpans8 (pstart);
+	}
+}
+
+
+/*
+================
+D_PolysetSetEdgeTable
+================
+*/
+void D_PolysetSetEdgeTable (void)
+{
+	int			edgetableindex;
+
+	edgetableindex = 0;	// assume the vertices are already in
+						//  top to bottom order
+
+//
+// determine which edges are right & left, and the order in which
+// to rasterize them
+//
+	if (r_p0[1] >= r_p1[1])
+	{
+		if (r_p0[1] == r_p1[1])
+		{
+			if (r_p0[1] < r_p2[1])
+				pedgetable = &edgetables[2];
+			else
+				pedgetable = &edgetables[5];
+
+			return;
+		}
+		else
+		{
+			edgetableindex = 1;
+		}
+	}
+
+	if (r_p0[1] == r_p2[1])
+	{
+		if (edgetableindex)
+			pedgetable = &edgetables[8];
+		else
+			pedgetable = &edgetables[9];
+
+		return;
+	}
+	else if (r_p1[1] == r_p2[1])
+	{
+		if (edgetableindex)
+			pedgetable = &edgetables[10];
+		else
+			pedgetable = &edgetables[11];
+
+		return;
+	}
+
+	if (r_p0[1] > r_p2[1])
+		edgetableindex += 2;
+
+	if (r_p1[1] > r_p2[1])
+		edgetableindex += 4;
+
+	pedgetable = &edgetables[edgetableindex];
+}
+
+
+#if 0
+
+void D_PolysetRecursiveDrawLine (int *lp1, int *lp2)
+{
+	int		d;
+	int		new[6];
+	int 	ofs;
+	
+	d = lp2[0] - lp1[0];
+	if (d < -1 || d > 1)
+		goto split;
+	d = lp2[1] - lp1[1];
+	if (d < -1 || d > 1)
+		goto split;
+
+	return;	// line is completed
+
+split:
+// split this edge
+	new[0] = (lp1[0] + lp2[0]) >> 1;
+	new[1] = (lp1[1] + lp2[1]) >> 1;
+	new[5] = (lp1[5] + lp2[5]) >> 1;
+	new[2] = (lp1[2] + lp2[2]) >> 1;
+	new[3] = (lp1[3] + lp2[3]) >> 1;
+	new[4] = (lp1[4] + lp2[4]) >> 1;
+
+// draw the point
+	ofs = d_scantable[new[1]] + new[0];
+	if (new[5] > d_pzbuffer[ofs])
+	{
+		int		pix;
+		
+		d_pzbuffer[ofs] = new[5];
+		pix = skintable[new[3]>>16][new[2]>>16];
+//		pix = ((byte *)acolormap)[pix + (new[4] & 0xFF00)];
+		d_viewbuffer[ofs] = pix;
+	}
+
+// recursively continue
+	D_PolysetRecursiveDrawLine (lp1, new);
+	D_PolysetRecursiveDrawLine (new, lp2);
+}
+
+void D_PolysetRecursiveTriangle2 (int *lp1, int *lp2, int *lp3)
+{
+	int		d;
+	int		new[4];
+	
+	d = lp2[0] - lp1[0];
+	if (d < -1 || d > 1)
+		goto split;
+	d = lp2[1] - lp1[1];
+	if (d < -1 || d > 1)
+		goto split;
+	return;
+
+split:
+// split this edge
+	new[0] = (lp1[0] + lp2[0]) >> 1;
+	new[1] = (lp1[1] + lp2[1]) >> 1;
+	new[5] = (lp1[5] + lp2[5]) >> 1;
+	new[2] = (lp1[2] + lp2[2]) >> 1;
+	new[3] = (lp1[3] + lp2[3]) >> 1;
+	new[4] = (lp1[4] + lp2[4]) >> 1;
+
+	D_PolysetRecursiveDrawLine (new, lp3);
+
+// recursively continue
+	D_PolysetRecursiveTriangle (lp1, new, lp3);
+	D_PolysetRecursiveTriangle (new, lp2, lp3);
+}
+
+#endif
+
--- /dev/null
+++ b/WinQuake/d_scan.c
@@ -1,0 +1,449 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// d_scan.c
+//
+// Portable C scan-level rasterization code, all pixel depths.
+
+#include "quakedef.h"
+#include "r_local.h"
+#include "d_local.h"
+
+unsigned char	*r_turb_pbase, *r_turb_pdest;
+fixed16_t		r_turb_s, r_turb_t, r_turb_sstep, r_turb_tstep;
+int				*r_turb_turb;
+int				r_turb_spancount;
+
+void D_DrawTurbulent8Span (void);
+
+
+/*
+=============
+D_WarpScreen
+
+// this performs a slight compression of the screen at the same time as
+// the sine warp, to keep the edges from wrapping
+=============
+*/
+void D_WarpScreen (void)
+{
+	int		w, h;
+	int		u,v;
+	byte	*dest;
+	int		*turb;
+	int		*col;
+	byte	**row;
+	byte	*rowptr[MAXHEIGHT+(AMP2*2)];
+	int		column[MAXWIDTH+(AMP2*2)];
+	float	wratio, hratio;
+
+	w = r_refdef.vrect.width;
+	h = r_refdef.vrect.height;
+
+	wratio = w / (float)scr_vrect.width;
+	hratio = h / (float)scr_vrect.height;
+
+	for (v=0 ; v<scr_vrect.height+AMP2*2 ; v++)
+	{
+		rowptr[v] = d_viewbuffer + (r_refdef.vrect.y * screenwidth) +
+				 (screenwidth * (int)((float)v * hratio * h / (h + AMP2 * 2)));
+	}
+
+	for (u=0 ; u<scr_vrect.width+AMP2*2 ; u++)
+	{
+		column[u] = r_refdef.vrect.x +
+				(int)((float)u * wratio * w / (w + AMP2 * 2));
+	}
+
+	turb = intsintable + ((int)(cl.time*SPEED)&(CYCLE-1));
+	dest = vid.buffer + scr_vrect.y * vid.rowbytes + scr_vrect.x;
+
+	for (v=0 ; v<scr_vrect.height ; v++, dest += vid.rowbytes)
+	{
+		col = &column[turb[v]];
+		row = &rowptr[v];
+
+		for (u=0 ; u<scr_vrect.width ; u+=4)
+		{
+			dest[u+0] = row[turb[u+0]][col[u+0]];
+			dest[u+1] = row[turb[u+1]][col[u+1]];
+			dest[u+2] = row[turb[u+2]][col[u+2]];
+			dest[u+3] = row[turb[u+3]][col[u+3]];
+		}
+	}
+}
+
+
+#if	!id386
+
+/*
+=============
+D_DrawTurbulent8Span
+=============
+*/
+void D_DrawTurbulent8Span (void)
+{
+	int		sturb, tturb;
+
+	do
+	{
+		sturb = ((r_turb_s + r_turb_turb[(r_turb_t>>16)&(CYCLE-1)])>>16)&63;
+		tturb = ((r_turb_t + r_turb_turb[(r_turb_s>>16)&(CYCLE-1)])>>16)&63;
+		*r_turb_pdest++ = *(r_turb_pbase + (tturb<<6) + sturb);
+		r_turb_s += r_turb_sstep;
+		r_turb_t += r_turb_tstep;
+	} while (--r_turb_spancount > 0);
+}
+
+#endif	// !id386
+
+
+/*
+=============
+Turbulent8
+=============
+*/
+void Turbulent8 (espan_t *pspan)
+{
+	int				count;
+	fixed16_t		snext, tnext;
+	float			sdivz, tdivz, zi, z, du, dv, spancountminus1;
+	float			sdivz16stepu, tdivz16stepu, zi16stepu;
+	
+	r_turb_turb = sintable + ((int)(cl.time*SPEED)&(CYCLE-1));
+
+	r_turb_sstep = 0;	// keep compiler happy
+	r_turb_tstep = 0;	// ditto
+
+	r_turb_pbase = (unsigned char *)cacheblock;
+
+	sdivz16stepu = d_sdivzstepu * 16;
+	tdivz16stepu = d_tdivzstepu * 16;
+	zi16stepu = d_zistepu * 16;
+
+	do
+	{
+		r_turb_pdest = (unsigned char *)((byte *)d_viewbuffer +
+				(screenwidth * pspan->v) + pspan->u);
+
+		count = pspan->count;
+
+	// calculate the initial s/z, t/z, 1/z, s, and t and clamp
+		du = (float)pspan->u;
+		dv = (float)pspan->v;
+
+		sdivz = d_sdivzorigin + dv*d_sdivzstepv + du*d_sdivzstepu;
+		tdivz = d_tdivzorigin + dv*d_tdivzstepv + du*d_tdivzstepu;
+		zi = d_ziorigin + dv*d_zistepv + du*d_zistepu;
+		z = (float)0x10000 / zi;	// prescale to 16.16 fixed-point
+
+		r_turb_s = (int)(sdivz * z) + sadjust;
+		if (r_turb_s > bbextents)
+			r_turb_s = bbextents;
+		else if (r_turb_s < 0)
+			r_turb_s = 0;
+
+		r_turb_t = (int)(tdivz * z) + tadjust;
+		if (r_turb_t > bbextentt)
+			r_turb_t = bbextentt;
+		else if (r_turb_t < 0)
+			r_turb_t = 0;
+
+		do
+		{
+		// calculate s and t at the far end of the span
+			if (count >= 16)
+				r_turb_spancount = 16;
+			else
+				r_turb_spancount = count;
+
+			count -= r_turb_spancount;
+
+			if (count)
+			{
+			// calculate s/z, t/z, zi->fixed s and t at far end of span,
+			// calculate s and t steps across span by shifting
+				sdivz += sdivz16stepu;
+				tdivz += tdivz16stepu;
+				zi += zi16stepu;
+				z = (float)0x10000 / zi;	// prescale to 16.16 fixed-point
+
+				snext = (int)(sdivz * z) + sadjust;
+				if (snext > bbextents)
+					snext = bbextents;
+				else if (snext < 16)
+					snext = 16;	// prevent round-off error on <0 steps from
+								//  from causing overstepping & running off the
+								//  edge of the texture
+
+				tnext = (int)(tdivz * z) + tadjust;
+				if (tnext > bbextentt)
+					tnext = bbextentt;
+				else if (tnext < 16)
+					tnext = 16;	// guard against round-off error on <0 steps
+
+				r_turb_sstep = (snext - r_turb_s) >> 4;
+				r_turb_tstep = (tnext - r_turb_t) >> 4;
+			}
+			else
+			{
+			// calculate s/z, t/z, zi->fixed s and t at last pixel in span (so
+			// can't step off polygon), clamp, calculate s and t steps across
+			// span by division, biasing steps low so we don't run off the
+			// texture
+				spancountminus1 = (float)(r_turb_spancount - 1);
+				sdivz += d_sdivzstepu * spancountminus1;
+				tdivz += d_tdivzstepu * spancountminus1;
+				zi += d_zistepu * spancountminus1;
+				z = (float)0x10000 / zi;	// prescale to 16.16 fixed-point
+				snext = (int)(sdivz * z) + sadjust;
+				if (snext > bbextents)
+					snext = bbextents;
+				else if (snext < 16)
+					snext = 16;	// prevent round-off error on <0 steps from
+								//  from causing overstepping & running off the
+								//  edge of the texture
+
+				tnext = (int)(tdivz * z) + tadjust;
+				if (tnext > bbextentt)
+					tnext = bbextentt;
+				else if (tnext < 16)
+					tnext = 16;	// guard against round-off error on <0 steps
+
+				if (r_turb_spancount > 1)
+				{
+					r_turb_sstep = (snext - r_turb_s) / (r_turb_spancount - 1);
+					r_turb_tstep = (tnext - r_turb_t) / (r_turb_spancount - 1);
+				}
+			}
+
+			r_turb_s = r_turb_s & ((CYCLE<<16)-1);
+			r_turb_t = r_turb_t & ((CYCLE<<16)-1);
+
+			D_DrawTurbulent8Span ();
+
+			r_turb_s = snext;
+			r_turb_t = tnext;
+
+		} while (count > 0);
+
+	} while ((pspan = pspan->pnext) != NULL);
+}
+
+
+#if	!id386
+
+/*
+=============
+D_DrawSpans8
+=============
+*/
+void D_DrawSpans8 (espan_t *pspan)
+{
+	int				count, spancount;
+	unsigned char	*pbase, *pdest;
+	fixed16_t		s, t, snext, tnext, sstep, tstep;
+	float			sdivz, tdivz, zi, z, du, dv, spancountminus1;
+	float			sdivz8stepu, tdivz8stepu, zi8stepu;
+
+	sstep = 0;	// keep compiler happy
+	tstep = 0;	// ditto
+
+	pbase = (unsigned char *)cacheblock;
+
+	sdivz8stepu = d_sdivzstepu * 8;
+	tdivz8stepu = d_tdivzstepu * 8;
+	zi8stepu = d_zistepu * 8;
+
+	do
+	{
+		pdest = (unsigned char *)((byte *)d_viewbuffer +
+				(screenwidth * pspan->v) + pspan->u);
+
+		count = pspan->count;
+
+	// calculate the initial s/z, t/z, 1/z, s, and t and clamp
+		du = (float)pspan->u;
+		dv = (float)pspan->v;
+
+		sdivz = d_sdivzorigin + dv*d_sdivzstepv + du*d_sdivzstepu;
+		tdivz = d_tdivzorigin + dv*d_tdivzstepv + du*d_tdivzstepu;
+		zi = d_ziorigin + dv*d_zistepv + du*d_zistepu;
+		z = (float)0x10000 / zi;	// prescale to 16.16 fixed-point
+
+		s = (int)(sdivz * z) + sadjust;
+		if (s > bbextents)
+			s = bbextents;
+		else if (s < 0)
+			s = 0;
+
+		t = (int)(tdivz * z) + tadjust;
+		if (t > bbextentt)
+			t = bbextentt;
+		else if (t < 0)
+			t = 0;
+
+		do
+		{
+		// calculate s and t at the far end of the span
+			if (count >= 8)
+				spancount = 8;
+			else
+				spancount = count;
+
+			count -= spancount;
+
+			if (count)
+			{
+			// calculate s/z, t/z, zi->fixed s and t at far end of span,
+			// calculate s and t steps across span by shifting
+				sdivz += sdivz8stepu;
+				tdivz += tdivz8stepu;
+				zi += zi8stepu;
+				z = (float)0x10000 / zi;	// prescale to 16.16 fixed-point
+
+				snext = (int)(sdivz * z) + sadjust;
+				if (snext > bbextents)
+					snext = bbextents;
+				else if (snext < 8)
+					snext = 8;	// prevent round-off error on <0 steps from
+								//  from causing overstepping & running off the
+								//  edge of the texture
+
+				tnext = (int)(tdivz * z) + tadjust;
+				if (tnext > bbextentt)
+					tnext = bbextentt;
+				else if (tnext < 8)
+					tnext = 8;	// guard against round-off error on <0 steps
+
+				sstep = (snext - s) >> 3;
+				tstep = (tnext - t) >> 3;
+			}
+			else
+			{
+			// calculate s/z, t/z, zi->fixed s and t at last pixel in span (so
+			// can't step off polygon), clamp, calculate s and t steps across
+			// span by division, biasing steps low so we don't run off the
+			// texture
+				spancountminus1 = (float)(spancount - 1);
+				sdivz += d_sdivzstepu * spancountminus1;
+				tdivz += d_tdivzstepu * spancountminus1;
+				zi += d_zistepu * spancountminus1;
+				z = (float)0x10000 / zi;	// prescale to 16.16 fixed-point
+				snext = (int)(sdivz * z) + sadjust;
+				if (snext > bbextents)
+					snext = bbextents;
+				else if (snext < 8)
+					snext = 8;	// prevent round-off error on <0 steps from
+								//  from causing overstepping & running off the
+								//  edge of the texture
+
+				tnext = (int)(tdivz * z) + tadjust;
+				if (tnext > bbextentt)
+					tnext = bbextentt;
+				else if (tnext < 8)
+					tnext = 8;	// guard against round-off error on <0 steps
+
+				if (spancount > 1)
+				{
+					sstep = (snext - s) / (spancount - 1);
+					tstep = (tnext - t) / (spancount - 1);
+				}
+			}
+
+			do
+			{
+				*pdest++ = *(pbase + (s >> 16) + (t >> 16) * cachewidth);
+				s += sstep;
+				t += tstep;
+			} while (--spancount > 0);
+
+			s = snext;
+			t = tnext;
+
+		} while (count > 0);
+
+	} while ((pspan = pspan->pnext) != NULL);
+}
+
+#endif
+
+
+#if	!id386
+
+/*
+=============
+D_DrawZSpans
+=============
+*/
+void D_DrawZSpans (espan_t *pspan)
+{
+	int				count, doublecount, izistep;
+	int				izi;
+	short			*pdest;
+	unsigned		ltemp;
+	double			zi;
+	float			du, dv;
+
+// FIXME: check for clamping/range problems
+// we count on FP exceptions being turned off to avoid range problems
+	izistep = (int)(d_zistepu * 0x8000 * 0x10000);
+
+	do
+	{
+		pdest = d_pzbuffer + (d_zwidth * pspan->v) + pspan->u;
+
+		count = pspan->count;
+
+	// calculate the initial 1/z
+		du = (float)pspan->u;
+		dv = (float)pspan->v;
+
+		zi = d_ziorigin + dv*d_zistepv + du*d_zistepu;
+	// we count on FP exceptions being turned off to avoid range problems
+		izi = (int)(zi * 0x8000 * 0x10000);
+
+		if ((long)pdest & 0x02)
+		{
+			*pdest++ = (short)(izi >> 16);
+			izi += izistep;
+			count--;
+		}
+
+		if ((doublecount = count >> 1) > 0)
+		{
+			do
+			{
+				ltemp = izi >> 16;
+				izi += izistep;
+				ltemp |= izi & 0xFFFF0000;
+				izi += izistep;
+				*(int *)pdest = ltemp;
+				pdest += 2;
+			} while (--doublecount > 0);
+		}
+
+		if (count & 1)
+			*pdest = (short)(izi >> 16);
+
+	} while ((pspan = pspan->pnext) != NULL);
+}
+
+#endif
+
--- /dev/null
+++ b/WinQuake/d_scana.s
@@ -1,0 +1,89 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+//
+// d_scana.s
+// x86 assembly-language turbulent texture mapping code
+//
+
+#include "asm_i386.h"
+#include "quakeasm.h"
+#include "asm_draw.h"
+#include "d_ifacea.h"
+
+#if id386
+
+	.data
+
+	.text
+
+//----------------------------------------------------------------------
+// turbulent texture mapping code
+//----------------------------------------------------------------------
+
+	.align 4
+.globl C(D_DrawTurbulent8Span)
+C(D_DrawTurbulent8Span):
+	pushl	%ebp				// preserve caller's stack frame pointer
+	pushl	%esi				// preserve register variables
+	pushl	%edi
+	pushl	%ebx
+
+	movl	C(r_turb_s),%esi
+	movl	C(r_turb_t),%ecx
+	movl	C(r_turb_pdest),%edi
+	movl	C(r_turb_spancount),%ebx
+
+Llp:
+	movl	%ecx,%eax
+	movl	%esi,%edx
+	sarl	$16,%eax
+	movl	C(r_turb_turb),%ebp
+	sarl	$16,%edx
+	andl	$(CYCLE-1),%eax
+	andl	$(CYCLE-1),%edx
+	movl	(%ebp,%eax,4),%eax
+	movl	(%ebp,%edx,4),%edx
+	addl	%esi,%eax
+	sarl	$16,%eax
+	addl	%ecx,%edx
+	sarl	$16,%edx
+	andl	$(TURB_TEX_SIZE-1),%eax
+	andl	$(TURB_TEX_SIZE-1),%edx
+	shll	$6,%edx
+	movl	C(r_turb_pbase),%ebp
+	addl	%eax,%edx
+	incl	%edi
+	addl	C(r_turb_sstep),%esi
+	addl	C(r_turb_tstep),%ecx
+	movb	(%ebp,%edx,1),%dl
+	decl	%ebx
+	movb	%dl,-1(%edi)
+	jnz		Llp
+
+	movl	%edi,C(r_turb_pdest)
+
+	popl	%ebx				// restore register variables
+	popl	%edi
+	popl	%esi
+	popl	%ebp				// restore caller's stack frame pointer
+	ret
+
+#endif	// id386
+
--- /dev/null
+++ b/WinQuake/d_sky.c
@@ -1,0 +1,138 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// d_sky.c
+
+#include "quakedef.h"
+#include "r_local.h"
+#include "d_local.h"
+
+#define SKY_SPAN_SHIFT	5
+#define SKY_SPAN_MAX	(1 << SKY_SPAN_SHIFT)
+
+
+/*
+=================
+D_Sky_uv_To_st
+=================
+*/
+void D_Sky_uv_To_st (int u, int v, fixed16_t *s, fixed16_t *t)
+{
+	float	wu, wv, temp;
+	vec3_t	end;
+
+	if (r_refdef.vrect.width >= r_refdef.vrect.height)
+		temp = (float)r_refdef.vrect.width;
+	else
+		temp = (float)r_refdef.vrect.height;
+
+	wu = 8192.0 * (float)(u-((int)vid.width>>1)) / temp;
+	wv = 8192.0 * (float)(((int)vid.height>>1)-v) / temp;
+
+	end[0] = 4096*vpn[0] + wu*vright[0] + wv*vup[0];
+	end[1] = 4096*vpn[1] + wu*vright[1] + wv*vup[1];
+	end[2] = 4096*vpn[2] + wu*vright[2] + wv*vup[2];
+	end[2] *= 3;
+	VectorNormalize (end);
+
+	temp = skytime*skyspeed;	// TODO: add D_SetupFrame & set this there
+	*s = (int)((temp + 6*(SKYSIZE/2-1)*end[0]) * 0x10000);
+	*t = (int)((temp + 6*(SKYSIZE/2-1)*end[1]) * 0x10000);
+}
+
+
+/*
+=================
+D_DrawSkyScans8
+=================
+*/
+void D_DrawSkyScans8 (espan_t *pspan)
+{
+	int				count, spancount, u, v;
+	unsigned char	*pdest;
+	fixed16_t		s, t, snext, tnext, sstep, tstep;
+	int				spancountminus1;
+
+	sstep = 0;	// keep compiler happy
+	tstep = 0;	// ditto
+
+	do
+	{
+		pdest = (unsigned char *)((byte *)d_viewbuffer +
+				(screenwidth * pspan->v) + pspan->u);
+
+		count = pspan->count;
+
+	// calculate the initial s & t
+		u = pspan->u;
+		v = pspan->v;
+		D_Sky_uv_To_st (u, v, &s, &t);
+
+		do
+		{
+			if (count >= SKY_SPAN_MAX)
+				spancount = SKY_SPAN_MAX;
+			else
+				spancount = count;
+
+			count -= spancount;
+
+			if (count)
+			{
+				u += spancount;
+
+			// calculate s and t at far end of span,
+			// calculate s and t steps across span by shifting
+				D_Sky_uv_To_st (u, v, &snext, &tnext);
+
+				sstep = (snext - s) >> SKY_SPAN_SHIFT;
+				tstep = (tnext - t) >> SKY_SPAN_SHIFT;
+			}
+			else
+			{
+			// calculate s and t at last pixel in span,
+			// calculate s and t steps across span by division
+				spancountminus1 = (float)(spancount - 1);
+
+				if (spancountminus1 > 0)
+				{
+					u += spancountminus1;
+					D_Sky_uv_To_st (u, v, &snext, &tnext);
+
+					sstep = (snext - s) / spancountminus1;
+					tstep = (tnext - t) / spancountminus1;
+				}
+			}
+
+			do
+			{
+				*pdest++ = r_skysource[((t & R_SKY_TMASK) >> 8) +
+						((s & R_SKY_SMASK) >> 16)];
+				s += sstep;
+				t += tstep;
+			} while (--spancount > 0);
+
+			s = snext;
+			t = tnext;
+
+		} while (count > 0);
+
+	} while ((pspan = pspan->pnext) != NULL);
+}
+
--- /dev/null
+++ b/WinQuake/d_spr8.s
@@ -1,0 +1,900 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+//
+// d_spr8.s
+// x86 assembly-language horizontal 8-bpp transparent span-drawing code.
+//
+
+#include "asm_i386.h"
+#include "quakeasm.h"
+#include "asm_draw.h"
+
+#if id386
+
+//----------------------------------------------------------------------
+// 8-bpp horizontal span drawing code for polygons, with transparency.
+//----------------------------------------------------------------------
+
+	.text
+
+// out-of-line, rarely-needed clamping code
+
+LClampHigh0:
+	movl	C(bbextents),%esi
+	jmp		LClampReentry0
+LClampHighOrLow0:
+	jg		LClampHigh0
+	xorl	%esi,%esi
+	jmp		LClampReentry0
+
+LClampHigh1:
+	movl	C(bbextentt),%edx
+	jmp		LClampReentry1
+LClampHighOrLow1:
+	jg		LClampHigh1
+	xorl	%edx,%edx
+	jmp		LClampReentry1
+
+LClampLow2:
+	movl	$2048,%ebp
+	jmp		LClampReentry2
+LClampHigh2:
+	movl	C(bbextents),%ebp
+	jmp		LClampReentry2
+
+LClampLow3:
+	movl	$2048,%ecx
+	jmp		LClampReentry3
+LClampHigh3:
+	movl	C(bbextentt),%ecx
+	jmp		LClampReentry3
+
+LClampLow4:
+	movl	$2048,%eax
+	jmp		LClampReentry4
+LClampHigh4:
+	movl	C(bbextents),%eax
+	jmp		LClampReentry4
+
+LClampLow5:
+	movl	$2048,%ebx
+	jmp		LClampReentry5
+LClampHigh5:
+	movl	C(bbextentt),%ebx
+	jmp		LClampReentry5
+
+
+#define pspans	4+16
+
+	.align 4
+.globl C(D_SpriteDrawSpans)
+C(D_SpriteDrawSpans):
+	pushl	%ebp				// preserve caller's stack frame
+	pushl	%edi
+	pushl	%esi				// preserve register variables
+	pushl	%ebx
+
+//
+// set up scaled-by-8 steps, for 8-long segments; also set up cacheblock
+// and span list pointers, and 1/z step in 0.32 fixed-point
+//
+// FIXME: any overlap from rearranging?
+	flds	C(d_sdivzstepu)
+	fmuls	fp_8
+	movl	C(cacheblock),%edx
+	flds	C(d_tdivzstepu)
+	fmuls	fp_8
+	movl	pspans(%esp),%ebx	// point to the first span descriptor
+	flds	C(d_zistepu)
+	fmuls	fp_8
+	movl	%edx,pbase			// pbase = cacheblock
+	flds	C(d_zistepu)
+	fmuls	fp_64kx64k
+	fxch	%st(3)
+	fstps	sdivz8stepu
+	fstps	zi8stepu
+	fstps	tdivz8stepu
+	fistpl	izistep
+	movl	izistep,%eax
+	rorl	$16,%eax		// put upper 16 bits in low word
+	movl	sspan_t_count(%ebx),%ecx
+	movl	%eax,izistep
+
+	cmpl	$0,%ecx
+	jle		LNextSpan
+
+LSpanLoop:
+
+//
+// set up the initial s/z, t/z, and 1/z on the FP stack, and generate the
+// initial s and t values
+//
+// FIXME: pipeline FILD?
+	fildl	sspan_t_v(%ebx)
+	fildl	sspan_t_u(%ebx)
+
+	fld		%st(1)			// dv | du | dv
+	fmuls	C(d_sdivzstepv)	// dv*d_sdivzstepv | du | dv
+	fld		%st(1)			// du | dv*d_sdivzstepv | du | dv
+	fmuls	C(d_sdivzstepu)	// du*d_sdivzstepu | dv*d_sdivzstepv | du | dv
+	fld		%st(2)			// du | du*d_sdivzstepu | dv*d_sdivzstepv | du | dv
+	fmuls	C(d_tdivzstepu)	// du*d_tdivzstepu | du*d_sdivzstepu |
+							//  dv*d_sdivzstepv | du | dv
+	fxch	%st(1)			// du*d_sdivzstepu | du*d_tdivzstepu |
+							//  dv*d_sdivzstepv | du | dv
+	faddp	%st(0),%st(2)	// du*d_tdivzstepu |
+							//  du*d_sdivzstepu + dv*d_sdivzstepv | du | dv
+	fxch	%st(1)			// du*d_sdivzstepu + dv*d_sdivzstepv |
+							//  du*d_tdivzstepu | du | dv
+	fld		%st(3)			// dv | du*d_sdivzstepu + dv*d_sdivzstepv |
+							//  du*d_tdivzstepu | du | dv
+	fmuls	C(d_tdivzstepv)	// dv*d_tdivzstepv |
+							//  du*d_sdivzstepu + dv*d_sdivzstepv |
+							//  du*d_tdivzstepu | du | dv
+	fxch	%st(1)			// du*d_sdivzstepu + dv*d_sdivzstepv |
+							//  dv*d_tdivzstepv | du*d_tdivzstepu | du | dv
+	fadds	C(d_sdivzorigin) // sdivz = d_sdivzorigin + dv*d_sdivzstepv +
+							//  du*d_sdivzstepu; stays in %st(2) at end
+	fxch	%st(4)			// dv | dv*d_tdivzstepv | du*d_tdivzstepu | du |
+							//  s/z
+	fmuls	C(d_zistepv)		// dv*d_zistepv | dv*d_tdivzstepv |
+							//  du*d_tdivzstepu | du | s/z
+	fxch	%st(1)			// dv*d_tdivzstepv |  dv*d_zistepv |
+							//  du*d_tdivzstepu | du | s/z
+	faddp	%st(0),%st(2)	// dv*d_zistepv |
+							//  dv*d_tdivzstepv + du*d_tdivzstepu | du | s/z
+	fxch	%st(2)			// du | dv*d_tdivzstepv + du*d_tdivzstepu |
+							//  dv*d_zistepv | s/z
+	fmuls	C(d_zistepu)		// du*d_zistepu |
+							//  dv*d_tdivzstepv + du*d_tdivzstepu |
+							//  dv*d_zistepv | s/z
+	fxch	%st(1)			// dv*d_tdivzstepv + du*d_tdivzstepu |
+							//  du*d_zistepu | dv*d_zistepv | s/z
+	fadds	C(d_tdivzorigin)	// tdivz = d_tdivzorigin + dv*d_tdivzstepv +
+							//  du*d_tdivzstepu; stays in %st(1) at end
+	fxch	%st(2)			// dv*d_zistepv | du*d_zistepu | t/z | s/z
+	faddp	%st(0),%st(1)	// dv*d_zistepv + du*d_zistepu | t/z | s/z
+
+	flds	fp_64k			// fp_64k | dv*d_zistepv + du*d_zistepu | t/z | s/z
+	fxch	%st(1)			// dv*d_zistepv + du*d_zistepu | fp_64k | t/z | s/z
+	fadds	C(d_ziorigin)		// zi = d_ziorigin + dv*d_zistepv +
+							//  du*d_zistepu; stays in %st(0) at end
+							// 1/z | fp_64k | t/z | s/z
+
+	fld		%st(0)			// FIXME: get rid of stall on FMUL?
+	fmuls	fp_64kx64k
+	fxch	%st(1)
+
+//
+// calculate and clamp s & t
+//
+	fdivr	%st(0),%st(2)	// 1/z | z*64k | t/z | s/z
+	fxch	%st(1)
+
+	fistpl	izi				// 0.32 fixed-point 1/z
+	movl	izi,%ebp
+
+//
+// set pz to point to the first z-buffer pixel in the span
+//
+	rorl	$16,%ebp		// put upper 16 bits in low word
+	movl	sspan_t_v(%ebx),%eax
+	movl	%ebp,izi
+	movl	sspan_t_u(%ebx),%ebp
+	imull	C(d_zrowbytes)
+	shll	$1,%ebp					// a word per pixel
+	addl	C(d_pzbuffer),%eax
+	addl	%ebp,%eax
+	movl	%eax,pz
+
+//
+// point %edi to the first pixel in the span
+//
+	movl	C(d_viewbuffer),%ebp
+	movl	sspan_t_v(%ebx),%eax
+	pushl	%ebx		// preserve spans pointer
+	movl	C(tadjust),%edx
+	movl	C(sadjust),%esi
+	movl	C(d_scantable)(,%eax,4),%edi	// v * screenwidth
+	addl	%ebp,%edi
+	movl	sspan_t_u(%ebx),%ebp
+	addl	%ebp,%edi				// pdest = &pdestspan[scans->u];
+
+//
+// now start the FDIV for the end of the span
+//
+	cmpl	$8,%ecx
+	ja		LSetupNotLast1
+
+	decl	%ecx
+	jz		LCleanup1		// if only one pixel, no need to start an FDIV
+	movl	%ecx,spancountminus1
+
+// finish up the s and t calcs
+	fxch	%st(1)			// z*64k | 1/z | t/z | s/z
+
+	fld		%st(0)			// z*64k | z*64k | 1/z | t/z | s/z
+	fmul	%st(4),%st(0)	// s | z*64k | 1/z | t/z | s/z
+	fxch	%st(1)			// z*64k | s | 1/z | t/z | s/z
+	fmul	%st(3),%st(0)	// t | s | 1/z | t/z | s/z
+	fxch	%st(1)			// s | t | 1/z | t/z | s/z
+	fistpl	s				// 1/z | t | t/z | s/z
+	fistpl	t				// 1/z | t/z | s/z
+
+	fildl	spancountminus1
+
+	flds	C(d_tdivzstepu)	// _d_tdivzstepu | spancountminus1
+	flds	C(d_zistepu)	// _d_zistepu | _d_tdivzstepu | spancountminus1
+	fmul	%st(2),%st(0)	// _d_zistepu*scm1 | _d_tdivzstepu | scm1
+	fxch	%st(1)			// _d_tdivzstepu | _d_zistepu*scm1 | scm1
+	fmul	%st(2),%st(0)	// _d_tdivzstepu*scm1 | _d_zistepu*scm1 | scm1
+	fxch	%st(2)			// scm1 | _d_zistepu*scm1 | _d_tdivzstepu*scm1
+	fmuls	C(d_sdivzstepu)	// _d_sdivzstepu*scm1 | _d_zistepu*scm1 |
+							//  _d_tdivzstepu*scm1
+	fxch	%st(1)			// _d_zistepu*scm1 | _d_sdivzstepu*scm1 |
+							//  _d_tdivzstepu*scm1
+	faddp	%st(0),%st(3)	// _d_sdivzstepu*scm1 | _d_tdivzstepu*scm1
+	fxch	%st(1)			// _d_tdivzstepu*scm1 | _d_sdivzstepu*scm1
+	faddp	%st(0),%st(3)	// _d_sdivzstepu*scm1
+	faddp	%st(0),%st(3)
+
+	flds	fp_64k
+	fdiv	%st(1),%st(0)	// this is what we've gone to all this trouble to
+							//  overlap
+	jmp		LFDIVInFlight1
+
+LCleanup1:
+// finish up the s and t calcs
+	fxch	%st(1)			// z*64k | 1/z | t/z | s/z
+
+	fld		%st(0)			// z*64k | z*64k | 1/z | t/z | s/z
+	fmul	%st(4),%st(0)	// s | z*64k | 1/z | t/z | s/z
+	fxch	%st(1)			// z*64k | s | 1/z | t/z | s/z
+	fmul	%st(3),%st(0)	// t | s | 1/z | t/z | s/z
+	fxch	%st(1)			// s | t | 1/z | t/z | s/z
+	fistpl	s				// 1/z | t | t/z | s/z
+	fistpl	t				// 1/z | t/z | s/z
+	jmp		LFDIVInFlight1
+
+	.align	4
+LSetupNotLast1:
+// finish up the s and t calcs
+	fxch	%st(1)			// z*64k | 1/z | t/z | s/z
+
+	fld		%st(0)			// z*64k | z*64k | 1/z | t/z | s/z
+	fmul	%st(4),%st(0)	// s | z*64k | 1/z | t/z | s/z
+	fxch	%st(1)			// z*64k | s | 1/z | t/z | s/z
+	fmul	%st(3),%st(0)	// t | s | 1/z | t/z | s/z
+	fxch	%st(1)			// s | t | 1/z | t/z | s/z
+	fistpl	s				// 1/z | t | t/z | s/z
+	fistpl	t				// 1/z | t/z | s/z
+
+	fadds	zi8stepu
+	fxch	%st(2)
+	fadds	sdivz8stepu
+	fxch	%st(2)
+	flds	tdivz8stepu
+	faddp	%st(0),%st(2)
+	flds	fp_64k
+	fdiv	%st(1),%st(0)	// z = 1/1/z
+							// this is what we've gone to all this trouble to
+							//  overlap
+LFDIVInFlight1:
+
+	addl	s,%esi
+	addl	t,%edx
+	movl	C(bbextents),%ebx
+	movl	C(bbextentt),%ebp
+	cmpl	%ebx,%esi
+	ja		LClampHighOrLow0
+LClampReentry0:
+	movl	%esi,s
+	movl	pbase,%ebx
+	shll	$16,%esi
+	cmpl	%ebp,%edx
+	movl	%esi,sfracf
+	ja		LClampHighOrLow1
+LClampReentry1:
+	movl	%edx,t
+	movl	s,%esi					// sfrac = scans->sfrac;
+	shll	$16,%edx
+	movl	t,%eax					// tfrac = scans->tfrac;
+	sarl	$16,%esi
+	movl	%edx,tfracf
+
+//
+// calculate the texture starting address
+//
+	sarl	$16,%eax
+	addl	%ebx,%esi
+	imull	C(cachewidth),%eax		// (tfrac >> 16) * cachewidth
+	addl	%eax,%esi				// psource = pbase + (sfrac >> 16) +
+									//           ((tfrac >> 16) * cachewidth);
+
+//
+// determine whether last span or not
+//
+	cmpl	$8,%ecx
+	jna		LLastSegment
+
+//
+// not the last segment; do full 8-wide segment
+//
+LNotLastSegment:
+
+//
+// advance s/z, t/z, and 1/z, and calculate s & t at end of span and steps to
+// get there
+//
+
+// pick up after the FDIV that was left in flight previously
+
+	fld		%st(0)			// duplicate it
+	fmul	%st(4),%st(0)	// s = s/z * z
+	fxch	%st(1)
+	fmul	%st(3),%st(0)	// t = t/z * z
+	fxch	%st(1)
+	fistpl	snext
+	fistpl	tnext
+	movl	snext,%eax
+	movl	tnext,%edx
+
+	subl	$8,%ecx		// count off this segments' pixels
+	movl	C(sadjust),%ebp
+	pushl	%ecx		// remember count of remaining pixels
+	movl	C(tadjust),%ecx
+
+	addl	%eax,%ebp
+	addl	%edx,%ecx
+
+	movl	C(bbextents),%eax
+	movl	C(bbextentt),%edx
+
+	cmpl	$2048,%ebp
+	jl		LClampLow2
+	cmpl	%eax,%ebp
+	ja		LClampHigh2
+LClampReentry2:
+
+	cmpl	$2048,%ecx
+	jl		LClampLow3
+	cmpl	%edx,%ecx
+	ja		LClampHigh3
+LClampReentry3:
+
+	movl	%ebp,snext
+	movl	%ecx,tnext
+
+	subl	s,%ebp
+	subl	t,%ecx
+	
+//
+// set up advancetable
+//
+	movl	%ecx,%eax
+	movl	%ebp,%edx
+	sarl	$19,%edx			// sstep >>= 16;
+	movl	C(cachewidth),%ebx
+	sarl	$19,%eax			// tstep >>= 16;
+	jz		LIsZero
+	imull	%ebx,%eax			// (tstep >> 16) * cachewidth;
+LIsZero:
+	addl	%edx,%eax			// add in sstep
+								// (tstep >> 16) * cachewidth + (sstep >> 16);
+	movl	tfracf,%edx
+	movl	%eax,advancetable+4	// advance base in t
+	addl	%ebx,%eax			// ((tstep >> 16) + 1) * cachewidth +
+								//  (sstep >> 16);
+	shll	$13,%ebp			// left-justify sstep fractional part
+	movl	%ebp,sstep
+	movl	sfracf,%ebx
+	shll	$13,%ecx			// left-justify tstep fractional part
+	movl	%eax,advancetable	// advance extra in t
+	movl	%ecx,tstep
+
+	movl	pz,%ecx
+	movl	izi,%ebp
+
+	cmpw	(%ecx),%bp
+	jl		Lp1
+	movb	(%esi),%al			// get first source texel
+	cmpb	$(TRANSPARENT_COLOR),%al
+	jz		Lp1
+	movw	%bp,(%ecx)
+	movb	%al,(%edi)			// store first dest pixel
+Lp1:
+	addl	izistep,%ebp
+	adcl	$0,%ebp
+	addl	tstep,%edx			// advance tfrac fractional part by tstep frac
+
+	sbbl	%eax,%eax			// turn tstep carry into -1 (0 if none)
+	addl	sstep,%ebx			// advance sfrac fractional part by sstep frac
+	adcl	advancetable+4(,%eax,4),%esi	// point to next source texel
+
+	cmpw	2(%ecx),%bp
+	jl		Lp2
+	movb	(%esi),%al
+	cmpb	$(TRANSPARENT_COLOR),%al
+	jz		Lp2
+	movw	%bp,2(%ecx)
+	movb	%al,1(%edi)
+Lp2:
+	addl	izistep,%ebp
+	adcl	$0,%ebp
+	addl	tstep,%edx
+	sbbl	%eax,%eax
+	addl	sstep,%ebx
+	adcl	advancetable+4(,%eax,4),%esi
+
+	cmpw	4(%ecx),%bp
+	jl		Lp3
+	movb	(%esi),%al
+	cmpb	$(TRANSPARENT_COLOR),%al
+	jz		Lp3
+	movw	%bp,4(%ecx)
+	movb	%al,2(%edi)
+Lp3:
+	addl	izistep,%ebp
+	adcl	$0,%ebp
+	addl	tstep,%edx
+	sbbl	%eax,%eax
+	addl	sstep,%ebx
+	adcl	advancetable+4(,%eax,4),%esi
+
+	cmpw	6(%ecx),%bp
+	jl		Lp4
+	movb	(%esi),%al
+	cmpb	$(TRANSPARENT_COLOR),%al
+	jz		Lp4
+	movw	%bp,6(%ecx)
+	movb	%al,3(%edi)
+Lp4:
+	addl	izistep,%ebp
+	adcl	$0,%ebp
+	addl	tstep,%edx
+	sbbl	%eax,%eax
+	addl	sstep,%ebx
+	adcl	advancetable+4(,%eax,4),%esi
+
+	cmpw	8(%ecx),%bp
+	jl		Lp5
+	movb	(%esi),%al
+	cmpb	$(TRANSPARENT_COLOR),%al
+	jz		Lp5
+	movw	%bp,8(%ecx)
+	movb	%al,4(%edi)
+Lp5:
+	addl	izistep,%ebp
+	adcl	$0,%ebp
+	addl	tstep,%edx
+	sbbl	%eax,%eax
+	addl	sstep,%ebx
+	adcl	advancetable+4(,%eax,4),%esi
+
+//
+// start FDIV for end of next segment in flight, so it can overlap
+//
+	popl	%eax
+	cmpl	$8,%eax			// more than one segment after this?
+	ja		LSetupNotLast2	// yes
+
+	decl	%eax
+	jz		LFDIVInFlight2	// if only one pixel, no need to start an FDIV
+	movl	%eax,spancountminus1
+	fildl	spancountminus1
+
+	flds	C(d_zistepu)		// _d_zistepu | spancountminus1
+	fmul	%st(1),%st(0)	// _d_zistepu*scm1 | scm1
+	flds	C(d_tdivzstepu)	// _d_tdivzstepu | _d_zistepu*scm1 | scm1
+	fmul	%st(2),%st(0)	// _d_tdivzstepu*scm1 | _d_zistepu*scm1 | scm1
+	fxch	%st(1)			// _d_zistepu*scm1 | _d_tdivzstepu*scm1 | scm1
+	faddp	%st(0),%st(3)	// _d_tdivzstepu*scm1 | scm1
+	fxch	%st(1)			// scm1 | _d_tdivzstepu*scm1
+	fmuls	C(d_sdivzstepu)	// _d_sdivzstepu*scm1 | _d_tdivzstepu*scm1
+	fxch	%st(1)			// _d_tdivzstepu*scm1 | _d_sdivzstepu*scm1
+	faddp	%st(0),%st(3)	// _d_sdivzstepu*scm1
+	flds	fp_64k			// 64k | _d_sdivzstepu*scm1
+	fxch	%st(1)			// _d_sdivzstepu*scm1 | 64k
+	faddp	%st(0),%st(4)	// 64k
+
+	fdiv	%st(1),%st(0)	// this is what we've gone to all this trouble to
+							//  overlap
+	jmp		LFDIVInFlight2
+
+	.align	4
+LSetupNotLast2:
+	fadds	zi8stepu
+	fxch	%st(2)
+	fadds	sdivz8stepu
+	fxch	%st(2)
+	flds	tdivz8stepu
+	faddp	%st(0),%st(2)
+	flds	fp_64k
+	fdiv	%st(1),%st(0)	// z = 1/1/z
+							// this is what we've gone to all this trouble to
+							//  overlap
+LFDIVInFlight2:
+	pushl	%eax
+
+	cmpw	10(%ecx),%bp
+	jl		Lp6
+	movb	(%esi),%al
+	cmpb	$(TRANSPARENT_COLOR),%al
+	jz		Lp6
+	movw	%bp,10(%ecx)
+	movb	%al,5(%edi)
+Lp6:
+	addl	izistep,%ebp
+	adcl	$0,%ebp
+	addl	tstep,%edx
+	sbbl	%eax,%eax
+	addl	sstep,%ebx
+	adcl	advancetable+4(,%eax,4),%esi
+
+	cmpw	12(%ecx),%bp
+	jl		Lp7
+	movb	(%esi),%al
+	cmpb	$(TRANSPARENT_COLOR),%al
+	jz		Lp7
+	movw	%bp,12(%ecx)
+	movb	%al,6(%edi)
+Lp7:
+	addl	izistep,%ebp
+	adcl	$0,%ebp
+	addl	tstep,%edx
+	sbbl	%eax,%eax
+	addl	sstep,%ebx
+	adcl	advancetable+4(,%eax,4),%esi
+
+	cmpw	14(%ecx),%bp
+	jl		Lp8
+	movb	(%esi),%al
+	cmpb	$(TRANSPARENT_COLOR),%al
+	jz		Lp8
+	movw	%bp,14(%ecx)
+	movb	%al,7(%edi)
+Lp8:
+	addl	izistep,%ebp
+	adcl	$0,%ebp
+	addl	tstep,%edx
+	sbbl	%eax,%eax
+	addl	sstep,%ebx
+	adcl	advancetable+4(,%eax,4),%esi
+
+	addl	$8,%edi
+	addl	$16,%ecx
+	movl	%edx,tfracf
+	movl	snext,%edx
+	movl	%ebx,sfracf
+	movl	tnext,%ebx
+	movl	%edx,s
+	movl	%ebx,t
+
+	movl	%ecx,pz
+	movl	%ebp,izi
+
+	popl	%ecx				// retrieve count
+
+//
+// determine whether last span or not
+//
+	cmpl	$8,%ecx				// are there multiple segments remaining?
+	ja		LNotLastSegment		// yes
+
+//
+// last segment of scan
+//
+LLastSegment:
+
+//
+// advance s/z, t/z, and 1/z, and calculate s & t at end of span and steps to
+// get there. The number of pixels left is variable, and we want to land on the
+// last pixel, not step one past it, so we can't run into arithmetic problems
+//
+	testl	%ecx,%ecx
+	jz		LNoSteps		// just draw the last pixel and we're done
+
+// pick up after the FDIV that was left in flight previously
+
+
+	fld		%st(0)			// duplicate it
+	fmul	%st(4),%st(0)	// s = s/z * z
+	fxch	%st(1)
+	fmul	%st(3),%st(0)	// t = t/z * z
+	fxch	%st(1)
+	fistpl	snext
+	fistpl	tnext
+
+	movl	C(tadjust),%ebx
+	movl	C(sadjust),%eax
+
+	addl	snext,%eax
+	addl	tnext,%ebx
+
+	movl	C(bbextents),%ebp
+	movl	C(bbextentt),%edx
+
+	cmpl	$2048,%eax
+	jl		LClampLow4
+	cmpl	%ebp,%eax
+	ja		LClampHigh4
+LClampReentry4:
+	movl	%eax,snext
+
+	cmpl	$2048,%ebx
+	jl		LClampLow5
+	cmpl	%edx,%ebx
+	ja		LClampHigh5
+LClampReentry5:
+
+	cmpl	$1,%ecx			// don't bother 
+	je		LOnlyOneStep	// if two pixels in segment, there's only one step,
+							//  of the segment length
+	subl	s,%eax
+	subl	t,%ebx
+
+	addl	%eax,%eax		// convert to 15.17 format so multiply by 1.31
+	addl	%ebx,%ebx		//  reciprocal yields 16.48
+	imull	reciprocal_table-8(,%ecx,4) // sstep = (snext - s) / (spancount-1)
+	movl	%edx,%ebp
+
+	movl	%ebx,%eax
+	imull	reciprocal_table-8(,%ecx,4) // tstep = (tnext - t) / (spancount-1)
+
+LSetEntryvec:
+//
+// set up advancetable
+//
+	movl	spr8entryvec_table(,%ecx,4),%ebx
+	movl	%edx,%eax
+	pushl	%ebx				// entry point into code for RET later
+	movl	%ebp,%ecx
+	sarl	$16,%ecx			// sstep >>= 16;
+	movl	C(cachewidth),%ebx
+	sarl	$16,%edx			// tstep >>= 16;
+	jz		LIsZeroLast
+	imull	%ebx,%edx			// (tstep >> 16) * cachewidth;
+LIsZeroLast:
+	addl	%ecx,%edx			// add in sstep
+								// (tstep >> 16) * cachewidth + (sstep >> 16);
+	movl	tfracf,%ecx
+	movl	%edx,advancetable+4	// advance base in t
+	addl	%ebx,%edx			// ((tstep >> 16) + 1) * cachewidth +
+								//  (sstep >> 16);
+	shll	$16,%ebp			// left-justify sstep fractional part
+	movl	sfracf,%ebx
+	shll	$16,%eax			// left-justify tstep fractional part
+	movl	%edx,advancetable	// advance extra in t
+
+	movl	%eax,tstep
+	movl	%ebp,sstep
+	movl	%ecx,%edx
+
+	movl	pz,%ecx
+	movl	izi,%ebp
+
+	ret							// jump to the number-of-pixels handler
+
+//----------------------------------------
+
+LNoSteps:
+	movl	pz,%ecx
+	subl	$7,%edi			// adjust for hardwired offset
+	subl	$14,%ecx
+	jmp		LEndSpan
+
+
+LOnlyOneStep:
+	subl	s,%eax
+	subl	t,%ebx
+	movl	%eax,%ebp
+	movl	%ebx,%edx
+	jmp		LSetEntryvec
+
+//----------------------------------------
+
+.globl	Spr8Entry2_8
+Spr8Entry2_8:
+	subl	$6,%edi		// adjust for hardwired offsets
+	subl	$12,%ecx
+	movb	(%esi),%al
+	jmp		LLEntry2_8
+
+//----------------------------------------
+
+.globl	Spr8Entry3_8
+Spr8Entry3_8:
+	subl	$5,%edi		// adjust for hardwired offsets
+	subl	$10,%ecx
+	jmp		LLEntry3_8
+
+//----------------------------------------
+
+.globl	Spr8Entry4_8
+Spr8Entry4_8:
+	subl	$4,%edi		// adjust for hardwired offsets
+	subl	$8,%ecx
+	jmp		LLEntry4_8
+
+//----------------------------------------
+
+.globl	Spr8Entry5_8
+Spr8Entry5_8:
+	subl	$3,%edi		// adjust for hardwired offsets
+	subl	$6,%ecx
+	jmp		LLEntry5_8
+
+//----------------------------------------
+
+.globl	Spr8Entry6_8
+Spr8Entry6_8:
+	subl	$2,%edi		// adjust for hardwired offsets
+	subl	$4,%ecx
+	jmp		LLEntry6_8
+
+//----------------------------------------
+
+.globl	Spr8Entry7_8
+Spr8Entry7_8:
+	decl	%edi		// adjust for hardwired offsets
+	subl	$2,%ecx
+	jmp		LLEntry7_8
+
+//----------------------------------------
+
+.globl	Spr8Entry8_8
+Spr8Entry8_8:
+	cmpw	(%ecx),%bp
+	jl		Lp9
+	movb	(%esi),%al
+	cmpb	$(TRANSPARENT_COLOR),%al
+	jz		Lp9
+	movw	%bp,(%ecx)
+	movb	%al,(%edi)
+Lp9:
+	addl	izistep,%ebp
+	adcl	$0,%ebp
+	addl	tstep,%edx
+	sbbl	%eax,%eax
+	addl	sstep,%ebx
+	adcl	advancetable+4(,%eax,4),%esi
+LLEntry7_8:
+	cmpw	2(%ecx),%bp
+	jl		Lp10
+	movb	(%esi),%al
+	cmpb	$(TRANSPARENT_COLOR),%al
+	jz		Lp10
+	movw	%bp,2(%ecx)
+	movb	%al,1(%edi)
+Lp10:
+	addl	izistep,%ebp
+	adcl	$0,%ebp
+	addl	tstep,%edx
+	sbbl	%eax,%eax
+	addl	sstep,%ebx
+	adcl	advancetable+4(,%eax,4),%esi
+LLEntry6_8:
+	cmpw	4(%ecx),%bp
+	jl		Lp11
+	movb	(%esi),%al
+	cmpb	$(TRANSPARENT_COLOR),%al
+	jz		Lp11
+	movw	%bp,4(%ecx)
+	movb	%al,2(%edi)
+Lp11:
+	addl	izistep,%ebp
+	adcl	$0,%ebp
+	addl	tstep,%edx
+	sbbl	%eax,%eax
+	addl	sstep,%ebx
+	adcl	advancetable+4(,%eax,4),%esi
+LLEntry5_8:
+	cmpw	6(%ecx),%bp
+	jl		Lp12
+	movb	(%esi),%al
+	cmpb	$(TRANSPARENT_COLOR),%al
+	jz		Lp12
+	movw	%bp,6(%ecx)
+	movb	%al,3(%edi)
+Lp12:
+	addl	izistep,%ebp
+	adcl	$0,%ebp
+	addl	tstep,%edx
+	sbbl	%eax,%eax
+	addl	sstep,%ebx
+	adcl	advancetable+4(,%eax,4),%esi
+LLEntry4_8:
+	cmpw	8(%ecx),%bp
+	jl		Lp13
+	movb	(%esi),%al
+	cmpb	$(TRANSPARENT_COLOR),%al
+	jz		Lp13
+	movw	%bp,8(%ecx)
+	movb	%al,4(%edi)
+Lp13:
+	addl	izistep,%ebp
+	adcl	$0,%ebp
+	addl	tstep,%edx
+	sbbl	%eax,%eax
+	addl	sstep,%ebx
+	adcl	advancetable+4(,%eax,4),%esi
+LLEntry3_8:
+	cmpw	10(%ecx),%bp
+	jl		Lp14
+	movb	(%esi),%al
+	cmpb	$(TRANSPARENT_COLOR),%al
+	jz		Lp14
+	movw	%bp,10(%ecx)
+	movb	%al,5(%edi)
+Lp14:
+	addl	izistep,%ebp
+	adcl	$0,%ebp
+	addl	tstep,%edx
+	sbbl	%eax,%eax
+	addl	sstep,%ebx
+	adcl	advancetable+4(,%eax,4),%esi
+LLEntry2_8:
+	cmpw	12(%ecx),%bp
+	jl		Lp15
+	movb	(%esi),%al
+	cmpb	$(TRANSPARENT_COLOR),%al
+	jz		Lp15
+	movw	%bp,12(%ecx)
+	movb	%al,6(%edi)
+Lp15:
+	addl	izistep,%ebp
+	adcl	$0,%ebp
+	addl	tstep,%edx
+	sbbl	%eax,%eax
+	addl	sstep,%ebx
+	adcl	advancetable+4(,%eax,4),%esi
+
+LEndSpan:
+	cmpw	14(%ecx),%bp
+	jl		Lp16
+	movb	(%esi),%al		// load first texel in segment
+	cmpb	$(TRANSPARENT_COLOR),%al
+	jz		Lp16
+	movw	%bp,14(%ecx)
+	movb	%al,7(%edi)
+Lp16:
+
+//
+// clear s/z, t/z, 1/z from FP stack
+//
+	fstp %st(0)
+	fstp %st(0)
+	fstp %st(0)
+
+	popl	%ebx				// restore spans pointer
+LNextSpan:
+	addl	$(sspan_t_size),%ebx // point to next span
+	movl	sspan_t_count(%ebx),%ecx
+	cmpl	$0,%ecx				// any more spans?
+	jg		LSpanLoop			// yes
+	jz		LNextSpan			// yes, but this one's empty
+
+	popl	%ebx				// restore register variables
+	popl	%esi
+	popl	%edi
+	popl	%ebp				// restore the caller's stack frame
+	ret
+
+#endif	// id386
--- /dev/null
+++ b/WinQuake/d_sprite.c
@@ -1,0 +1,442 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// d_sprite.c: software top-level rasterization driver module for drawing
+// sprites
+
+#include "quakedef.h"
+#include "d_local.h"
+
+static int		sprite_height;
+static int		minindex, maxindex;
+static sspan_t	*sprite_spans;
+
+#if	!id386
+
+/*
+=====================
+D_SpriteDrawSpans
+=====================
+*/
+void D_SpriteDrawSpans (sspan_t *pspan)
+{
+	int			count, spancount, izistep;
+	int			izi;
+	byte		*pbase, *pdest;
+	fixed16_t	s, t, snext, tnext, sstep, tstep;
+	float		sdivz, tdivz, zi, z, du, dv, spancountminus1;
+	float		sdivz8stepu, tdivz8stepu, zi8stepu;
+	byte		btemp;
+	short		*pz;
+
+	sstep = 0;	// keep compiler happy
+	tstep = 0;	// ditto
+
+	pbase = cacheblock;
+
+	sdivz8stepu = d_sdivzstepu * 8;
+	tdivz8stepu = d_tdivzstepu * 8;
+	zi8stepu = d_zistepu * 8;
+
+// we count on FP exceptions being turned off to avoid range problems
+	izistep = (int)(d_zistepu * 0x8000 * 0x10000);
+
+	do
+	{
+		pdest = (byte *)d_viewbuffer + (screenwidth * pspan->v) + pspan->u;
+		pz = d_pzbuffer + (d_zwidth * pspan->v) + pspan->u;
+
+		count = pspan->count;
+
+		if (count <= 0)
+			goto NextSpan;
+
+	// calculate the initial s/z, t/z, 1/z, s, and t and clamp
+		du = (float)pspan->u;
+		dv = (float)pspan->v;
+
+		sdivz = d_sdivzorigin + dv*d_sdivzstepv + du*d_sdivzstepu;
+		tdivz = d_tdivzorigin + dv*d_tdivzstepv + du*d_tdivzstepu;
+		zi = d_ziorigin + dv*d_zistepv + du*d_zistepu;
+		z = (float)0x10000 / zi;	// prescale to 16.16 fixed-point
+	// we count on FP exceptions being turned off to avoid range problems
+		izi = (int)(zi * 0x8000 * 0x10000);
+
+		s = (int)(sdivz * z) + sadjust;
+		if (s > bbextents)
+			s = bbextents;
+		else if (s < 0)
+			s = 0;
+
+		t = (int)(tdivz * z) + tadjust;
+		if (t > bbextentt)
+			t = bbextentt;
+		else if (t < 0)
+			t = 0;
+
+		do
+		{
+		// calculate s and t at the far end of the span
+			if (count >= 8)
+				spancount = 8;
+			else
+				spancount = count;
+
+			count -= spancount;
+
+			if (count)
+			{
+			// calculate s/z, t/z, zi->fixed s and t at far end of span,
+			// calculate s and t steps across span by shifting
+				sdivz += sdivz8stepu;
+				tdivz += tdivz8stepu;
+				zi += zi8stepu;
+				z = (float)0x10000 / zi;	// prescale to 16.16 fixed-point
+
+				snext = (int)(sdivz * z) + sadjust;
+				if (snext > bbextents)
+					snext = bbextents;
+				else if (snext < 8)
+					snext = 8;	// prevent round-off error on <0 steps from
+								//  from causing overstepping & running off the
+								//  edge of the texture
+
+				tnext = (int)(tdivz * z) + tadjust;
+				if (tnext > bbextentt)
+					tnext = bbextentt;
+				else if (tnext < 8)
+					tnext = 8;	// guard against round-off error on <0 steps
+
+				sstep = (snext - s) >> 3;
+				tstep = (tnext - t) >> 3;
+			}
+			else
+			{
+			// calculate s/z, t/z, zi->fixed s and t at last pixel in span (so
+			// can't step off polygon), clamp, calculate s and t steps across
+			// span by division, biasing steps low so we don't run off the
+			// texture
+				spancountminus1 = (float)(spancount - 1);
+				sdivz += d_sdivzstepu * spancountminus1;
+				tdivz += d_tdivzstepu * spancountminus1;
+				zi += d_zistepu * spancountminus1;
+				z = (float)0x10000 / zi;	// prescale to 16.16 fixed-point
+				snext = (int)(sdivz * z) + sadjust;
+				if (snext > bbextents)
+					snext = bbextents;
+				else if (snext < 8)
+					snext = 8;	// prevent round-off error on <0 steps from
+								//  from causing overstepping & running off the
+								//  edge of the texture
+
+				tnext = (int)(tdivz * z) + tadjust;
+				if (tnext > bbextentt)
+					tnext = bbextentt;
+				else if (tnext < 8)
+					tnext = 8;	// guard against round-off error on <0 steps
+
+				if (spancount > 1)
+				{
+					sstep = (snext - s) / (spancount - 1);
+					tstep = (tnext - t) / (spancount - 1);
+				}
+			}
+
+			do
+			{
+				btemp = *(pbase + (s >> 16) + (t >> 16) * cachewidth);
+				if (btemp != 255)
+				{
+					if (*pz <= (izi >> 16))
+					{
+						*pz = izi >> 16;
+						*pdest = btemp;
+					}
+				}
+
+				izi += izistep;
+				pdest++;
+				pz++;
+				s += sstep;
+				t += tstep;
+			} while (--spancount > 0);
+
+			s = snext;
+			t = tnext;
+
+		} while (count > 0);
+
+NextSpan:
+		pspan++;
+
+	} while (pspan->count != DS_SPAN_LIST_END);
+}
+
+#endif
+
+
+/*
+=====================
+D_SpriteScanLeftEdge
+=====================
+*/
+void D_SpriteScanLeftEdge (void)
+{
+	int			i, v, itop, ibottom, lmaxindex;
+	emitpoint_t	*pvert, *pnext;
+	sspan_t		*pspan;
+	float		du, dv, vtop, vbottom, slope;
+	fixed16_t	u, u_step;
+
+	pspan = sprite_spans;
+	i = minindex;
+	if (i == 0)
+		i = r_spritedesc.nump;
+
+	lmaxindex = maxindex;
+	if (lmaxindex == 0)
+		lmaxindex = r_spritedesc.nump;
+
+	vtop = ceil (r_spritedesc.pverts[i].v);
+
+	do
+	{
+		pvert = &r_spritedesc.pverts[i];
+		pnext = pvert - 1;
+
+		vbottom = ceil (pnext->v);
+
+		if (vtop < vbottom)
+		{
+			du = pnext->u - pvert->u;
+			dv = pnext->v - pvert->v;
+			slope = du / dv;
+			u_step = (int)(slope * 0x10000);
+		// adjust u to ceil the integer portion
+			u = (int)((pvert->u + (slope * (vtop - pvert->v))) * 0x10000) +
+					(0x10000 - 1);
+			itop = (int)vtop;
+			ibottom = (int)vbottom;
+
+			for (v=itop ; v<ibottom ; v++)
+			{
+				pspan->u = u >> 16;
+				pspan->v = v;
+				u += u_step;
+				pspan++;
+			}
+		}
+
+		vtop = vbottom;
+
+		i--;
+		if (i == 0)
+			i = r_spritedesc.nump;
+
+	} while (i != lmaxindex);
+}
+
+
+/*
+=====================
+D_SpriteScanRightEdge
+=====================
+*/
+void D_SpriteScanRightEdge (void)
+{
+	int			i, v, itop, ibottom;
+	emitpoint_t	*pvert, *pnext;
+	sspan_t		*pspan;
+	float		du, dv, vtop, vbottom, slope, uvert, unext, vvert, vnext;
+	fixed16_t	u, u_step;
+
+	pspan = sprite_spans;
+	i = minindex;
+
+	vvert = r_spritedesc.pverts[i].v;
+	if (vvert < r_refdef.fvrecty_adj)
+		vvert = r_refdef.fvrecty_adj;
+	if (vvert > r_refdef.fvrectbottom_adj)
+		vvert = r_refdef.fvrectbottom_adj;
+
+	vtop = ceil (vvert);
+
+	do
+	{
+		pvert = &r_spritedesc.pverts[i];
+		pnext = pvert + 1;
+
+		vnext = pnext->v;
+		if (vnext < r_refdef.fvrecty_adj)
+			vnext = r_refdef.fvrecty_adj;
+		if (vnext > r_refdef.fvrectbottom_adj)
+			vnext = r_refdef.fvrectbottom_adj;
+
+		vbottom = ceil (vnext);
+
+		if (vtop < vbottom)
+		{
+			uvert = pvert->u;
+			if (uvert < r_refdef.fvrectx_adj)
+				uvert = r_refdef.fvrectx_adj;
+			if (uvert > r_refdef.fvrectright_adj)
+				uvert = r_refdef.fvrectright_adj;
+
+			unext = pnext->u;
+			if (unext < r_refdef.fvrectx_adj)
+				unext = r_refdef.fvrectx_adj;
+			if (unext > r_refdef.fvrectright_adj)
+				unext = r_refdef.fvrectright_adj;
+
+			du = unext - uvert;
+			dv = vnext - vvert;
+			slope = du / dv;
+			u_step = (int)(slope * 0x10000);
+		// adjust u to ceil the integer portion
+			u = (int)((uvert + (slope * (vtop - vvert))) * 0x10000) +
+					(0x10000 - 1);
+			itop = (int)vtop;
+			ibottom = (int)vbottom;
+
+			for (v=itop ; v<ibottom ; v++)
+			{
+				pspan->count = (u >> 16) - pspan->u;
+				u += u_step;
+				pspan++;
+			}
+		}
+
+		vtop = vbottom;
+		vvert = vnext;
+
+		i++;
+		if (i == r_spritedesc.nump)
+			i = 0;
+
+	} while (i != maxindex);
+
+	pspan->count = DS_SPAN_LIST_END;	// mark the end of the span list 
+}
+
+
+/*
+=====================
+D_SpriteCalculateGradients
+=====================
+*/
+void D_SpriteCalculateGradients (void)
+{
+	vec3_t		p_normal, p_saxis, p_taxis, p_temp1;
+	float		distinv;
+
+	TransformVector (r_spritedesc.vpn, p_normal);
+	TransformVector (r_spritedesc.vright, p_saxis);
+	TransformVector (r_spritedesc.vup, p_taxis);
+	VectorInverse (p_taxis);
+
+	distinv = 1.0 / (-DotProduct (modelorg, r_spritedesc.vpn));
+
+	d_sdivzstepu = p_saxis[0] * xscaleinv;
+	d_tdivzstepu = p_taxis[0] * xscaleinv;
+
+	d_sdivzstepv = -p_saxis[1] * yscaleinv;
+	d_tdivzstepv = -p_taxis[1] * yscaleinv;
+
+	d_zistepu = p_normal[0] * xscaleinv * distinv;
+	d_zistepv = -p_normal[1] * yscaleinv * distinv;
+
+	d_sdivzorigin = p_saxis[2] - xcenter * d_sdivzstepu -
+			ycenter * d_sdivzstepv;
+	d_tdivzorigin = p_taxis[2] - xcenter * d_tdivzstepu -
+			ycenter * d_tdivzstepv;
+	d_ziorigin = p_normal[2] * distinv - xcenter * d_zistepu -
+			ycenter * d_zistepv;
+
+	TransformVector (modelorg, p_temp1);
+
+	sadjust = ((fixed16_t)(DotProduct (p_temp1, p_saxis) * 0x10000 + 0.5)) -
+			(-(cachewidth >> 1) << 16);
+	tadjust = ((fixed16_t)(DotProduct (p_temp1, p_taxis) * 0x10000 + 0.5)) -
+			(-(sprite_height >> 1) << 16);
+
+// -1 (-epsilon) so we never wander off the edge of the texture
+	bbextents = (cachewidth << 16) - 1;
+	bbextentt = (sprite_height << 16) - 1;
+}
+
+
+/*
+=====================
+D_DrawSprite
+=====================
+*/
+void D_DrawSprite (void)
+{
+	int			i, nump;
+	float		ymin, ymax;
+	emitpoint_t	*pverts;
+	sspan_t		spans[MAXHEIGHT+1];
+
+	sprite_spans = spans;
+
+// find the top and bottom vertices, and make sure there's at least one scan to
+// draw
+	ymin = 999999.9;
+	ymax = -999999.9;
+	pverts = r_spritedesc.pverts;
+
+	for (i=0 ; i<r_spritedesc.nump ; i++)
+	{
+		if (pverts->v < ymin)
+		{
+			ymin = pverts->v;
+			minindex = i;
+		}
+
+		if (pverts->v > ymax)
+		{
+			ymax = pverts->v;
+			maxindex = i;
+		}
+
+		pverts++;
+	}
+
+	ymin = ceil (ymin);
+	ymax = ceil (ymax);
+
+	if (ymin >= ymax)
+		return;		// doesn't cross any scans at all
+
+	cachewidth = r_spritedesc.pspriteframe->width;
+	sprite_height = r_spritedesc.pspriteframe->height;
+	cacheblock = (byte *)&r_spritedesc.pspriteframe->pixels[0];
+
+// copy the first vertex to the last vertex, so we don't have to deal with
+// wrapping
+	nump = r_spritedesc.nump;
+	pverts = r_spritedesc.pverts;
+	pverts[nump] = pverts[0];
+
+	D_SpriteCalculateGradients ();
+	D_SpriteScanLeftEdge ();
+	D_SpriteScanRightEdge ();
+	D_SpriteDrawSpans (sprite_spans);
+}
+
--- /dev/null
+++ b/WinQuake/d_surf.c
@@ -1,0 +1,335 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// d_surf.c: rasterization driver surface heap manager
+
+#include "quakedef.h"
+#include "d_local.h"
+#include "r_local.h"
+
+float           surfscale;
+qboolean        r_cache_thrash;         // set if surface cache is thrashing
+
+int                                     sc_size;
+surfcache_t                     *sc_rover, *sc_base;
+
+#define GUARDSIZE       4
+
+
+int     D_SurfaceCacheForRes (int width, int height)
+{
+	int             size, pix;
+
+	if (COM_CheckParm ("-surfcachesize"))
+	{
+		size = Q_atoi(com_argv[COM_CheckParm("-surfcachesize")+1]) * 1024;
+		return size;
+	}
+	
+	size = SURFCACHE_SIZE_AT_320X200;
+
+	pix = width*height;
+	if (pix > 64000)
+		size += (pix-64000)*3;
+		
+
+	return size;
+}
+
+void D_CheckCacheGuard (void)
+{
+	byte    *s;
+	int             i;
+
+	s = (byte *)sc_base + sc_size;
+	for (i=0 ; i<GUARDSIZE ; i++)
+		if (s[i] != (byte)i)
+			Sys_Error ("D_CheckCacheGuard: failed");
+}
+
+void D_ClearCacheGuard (void)
+{
+	byte    *s;
+	int             i;
+	
+	s = (byte *)sc_base + sc_size;
+	for (i=0 ; i<GUARDSIZE ; i++)
+		s[i] = (byte)i;
+}
+
+
+/*
+================
+D_InitCaches
+
+================
+*/
+void D_InitCaches (void *buffer, int size)
+{
+
+	if (!msg_suppress_1)
+		Con_Printf ("%ik surface cache\n", size/1024);
+
+	sc_size = size - GUARDSIZE;
+	sc_base = (surfcache_t *)buffer;
+	sc_rover = sc_base;
+	
+	sc_base->next = NULL;
+	sc_base->owner = NULL;
+	sc_base->size = sc_size;
+	
+	D_ClearCacheGuard ();
+}
+
+
+/*
+==================
+D_FlushCaches
+==================
+*/
+void D_FlushCaches (void)
+{
+	surfcache_t     *c;
+	
+	if (!sc_base)
+		return;
+
+	for (c = sc_base ; c ; c = c->next)
+	{
+		if (c->owner)
+			*c->owner = NULL;
+	}
+	
+	sc_rover = sc_base;
+	sc_base->next = NULL;
+	sc_base->owner = NULL;
+	sc_base->size = sc_size;
+}
+
+/*
+=================
+D_SCAlloc
+=================
+*/
+surfcache_t     *D_SCAlloc (int width, int size)
+{
+	surfcache_t             *new;
+	qboolean                wrapped_this_time;
+
+	if ((width < 0) || (width > 256))
+		Sys_Error ("D_SCAlloc: bad cache width %d\n", width);
+
+	if ((size <= 0) || (size > 0x10000))
+		Sys_Error ("D_SCAlloc: bad cache size %d\n", size);
+	
+	size = (int)&((surfcache_t *)0)->data[size];
+	size = (size + 3) & ~3;
+	if (size > sc_size)
+		Sys_Error ("D_SCAlloc: %i > cache size",size);
+
+// if there is not size bytes after the rover, reset to the start
+	wrapped_this_time = false;
+
+	if ( !sc_rover || (byte *)sc_rover - (byte *)sc_base > sc_size - size)
+	{
+		if (sc_rover)
+		{
+			wrapped_this_time = true;
+		}
+		sc_rover = sc_base;
+	}
+		
+// colect and free surfcache_t blocks until the rover block is large enough
+	new = sc_rover;
+	if (sc_rover->owner)
+		*sc_rover->owner = NULL;
+	
+	while (new->size < size)
+	{
+	// free another
+		sc_rover = sc_rover->next;
+		if (!sc_rover)
+			Sys_Error ("D_SCAlloc: hit the end of memory");
+		if (sc_rover->owner)
+			*sc_rover->owner = NULL;
+			
+		new->size += sc_rover->size;
+		new->next = sc_rover->next;
+	}
+
+// create a fragment out of any leftovers
+	if (new->size - size > 256)
+	{
+		sc_rover = (surfcache_t *)( (byte *)new + size);
+		sc_rover->size = new->size - size;
+		sc_rover->next = new->next;
+		sc_rover->width = 0;
+		sc_rover->owner = NULL;
+		new->next = sc_rover;
+		new->size = size;
+	}
+	else
+		sc_rover = new->next;
+	
+	new->width = width;
+// DEBUG
+	if (width > 0)
+		new->height = (size - sizeof(*new) + sizeof(new->data)) / width;
+
+	new->owner = NULL;              // should be set properly after return
+
+	if (d_roverwrapped)
+	{
+		if (wrapped_this_time || (sc_rover >= d_initial_rover))
+			r_cache_thrash = true;
+	}
+	else if (wrapped_this_time)
+	{       
+		d_roverwrapped = true;
+	}
+
+D_CheckCacheGuard ();   // DEBUG
+	return new;
+}
+
+
+/*
+=================
+D_SCDump
+=================
+*/
+void D_SCDump (void)
+{
+	surfcache_t             *test;
+
+	for (test = sc_base ; test ; test = test->next)
+	{
+		if (test == sc_rover)
+			Sys_Printf ("ROVER:\n");
+		printf ("%p : %i bytes     %i width\n",test, test->size, test->width);
+	}
+}
+
+//=============================================================================
+
+// if the num is not a power of 2, assume it will not repeat
+
+int     MaskForNum (int num)
+{
+	if (num==128)
+		return 127;
+	if (num==64)
+		return 63;
+	if (num==32)
+		return 31;
+	if (num==16)
+		return 15;
+	return 255;
+}
+
+int D_log2 (int num)
+{
+	int     c;
+	
+	c = 0;
+	
+	while (num>>=1)
+		c++;
+	return c;
+}
+
+//=============================================================================
+
+/*
+================
+D_CacheSurface
+================
+*/
+surfcache_t *D_CacheSurface (msurface_t *surface, int miplevel)
+{
+	surfcache_t     *cache;
+
+//
+// if the surface is animating or flashing, flush the cache
+//
+	r_drawsurf.texture = R_TextureAnimation (surface->texinfo->texture);
+	r_drawsurf.lightadj[0] = d_lightstylevalue[surface->styles[0]];
+	r_drawsurf.lightadj[1] = d_lightstylevalue[surface->styles[1]];
+	r_drawsurf.lightadj[2] = d_lightstylevalue[surface->styles[2]];
+	r_drawsurf.lightadj[3] = d_lightstylevalue[surface->styles[3]];
+	
+//
+// see if the cache holds apropriate data
+//
+	cache = surface->cachespots[miplevel];
+
+	if (cache && !cache->dlight && surface->dlightframe != r_framecount
+			&& cache->texture == r_drawsurf.texture
+			&& cache->lightadj[0] == r_drawsurf.lightadj[0]
+			&& cache->lightadj[1] == r_drawsurf.lightadj[1]
+			&& cache->lightadj[2] == r_drawsurf.lightadj[2]
+			&& cache->lightadj[3] == r_drawsurf.lightadj[3] )
+		return cache;
+
+//
+// determine shape of surface
+//
+	surfscale = 1.0 / (1<<miplevel);
+	r_drawsurf.surfmip = miplevel;
+	r_drawsurf.surfwidth = surface->extents[0] >> miplevel;
+	r_drawsurf.rowbytes = r_drawsurf.surfwidth;
+	r_drawsurf.surfheight = surface->extents[1] >> miplevel;
+	
+//
+// allocate memory if needed
+//
+	if (!cache)     // if a texture just animated, don't reallocate it
+	{
+		cache = D_SCAlloc (r_drawsurf.surfwidth,
+						   r_drawsurf.surfwidth * r_drawsurf.surfheight);
+		surface->cachespots[miplevel] = cache;
+		cache->owner = &surface->cachespots[miplevel];
+		cache->mipscale = surfscale;
+	}
+	
+	if (surface->dlightframe == r_framecount)
+		cache->dlight = 1;
+	else
+		cache->dlight = 0;
+
+	r_drawsurf.surfdat = (pixel_t *)cache->data;
+	
+	cache->texture = r_drawsurf.texture;
+	cache->lightadj[0] = r_drawsurf.lightadj[0];
+	cache->lightadj[1] = r_drawsurf.lightadj[1];
+	cache->lightadj[2] = r_drawsurf.lightadj[2];
+	cache->lightadj[3] = r_drawsurf.lightadj[3];
+
+//
+// draw and light the surface texture
+//
+	r_drawsurf.surf = surface;
+
+	c_surf++;
+	R_DrawSurface ();
+
+	return surface->cachespots[miplevel];
+}
+
+
--- /dev/null
+++ b/WinQuake/d_vars.c
@@ -1,0 +1,50 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// r_vars.c: global refresh variables
+
+#if	!id386
+
+#include	"quakedef.h"
+
+// all global and static refresh variables are collected in a contiguous block
+// to avoid cache conflicts.
+
+//-------------------------------------------------------
+// global refresh variables
+//-------------------------------------------------------
+
+// FIXME: make into one big structure, like cl or sv
+// FIXME: do separately for refresh engine and driver
+
+float	d_sdivzstepu, d_tdivzstepu, d_zistepu;
+float	d_sdivzstepv, d_tdivzstepv, d_zistepv;
+float	d_sdivzorigin, d_tdivzorigin, d_ziorigin;
+
+fixed16_t	sadjust, tadjust, bbextents, bbextentt;
+
+pixel_t			*cacheblock;
+int				cachewidth;
+pixel_t			*d_viewbuffer;
+short			*d_pzbuffer;
+unsigned int	d_zrowbytes;
+unsigned int	d_zwidth;
+
+#endif	// !id386
+
--- /dev/null
+++ b/WinQuake/d_varsa.s
@@ -1,0 +1,213 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+//
+// d_varsa.s
+//
+
+#include "asm_i386.h"
+#include "quakeasm.h"
+#include "asm_draw.h"
+#include "d_ifacea.h"
+
+#if	id386
+
+	.data
+
+//-------------------------------------------------------
+// global refresh variables
+//-------------------------------------------------------
+
+// FIXME: put all refresh variables into one contiguous block. Make into one
+// big structure, like cl or sv?
+
+	.align	4
+.globl	C(d_sdivzstepu)
+.globl	C(d_tdivzstepu)
+.globl	C(d_zistepu)
+.globl	C(d_sdivzstepv)
+.globl	C(d_tdivzstepv)
+.globl	C(d_zistepv)
+.globl	C(d_sdivzorigin)
+.globl	C(d_tdivzorigin)
+.globl	C(d_ziorigin)
+C(d_sdivzstepu):	.single	0
+C(d_tdivzstepu):	.single	0
+C(d_zistepu):		.single	0
+C(d_sdivzstepv):	.single	0
+C(d_tdivzstepv):	.single	0
+C(d_zistepv):		.single	0
+C(d_sdivzorigin):	.single	0
+C(d_tdivzorigin):	.single	0
+C(d_ziorigin):		.single	0
+
+.globl	C(sadjust)
+.globl	C(tadjust)
+.globl	C(bbextents)
+.globl	C(bbextentt)
+C(sadjust):			.long	0
+C(tadjust):			.long	0
+C(bbextents):		.long	0
+C(bbextentt):		.long	0
+
+.globl	C(cacheblock)
+.globl	C(d_viewbuffer)
+.globl	C(cachewidth)
+.globl	C(d_pzbuffer)
+.globl	C(d_zrowbytes)
+.globl	C(d_zwidth)
+C(cacheblock):		.long	0
+C(cachewidth):		.long	0
+C(d_viewbuffer):	.long	0
+C(d_pzbuffer):		.long	0
+C(d_zrowbytes):		.long	0
+C(d_zwidth):		.long	0
+
+
+//-------------------------------------------------------
+// ASM-only variables
+//-------------------------------------------------------
+.globl	izi
+izi:			.long	0
+
+.globl	pbase, s, t, sfracf, tfracf, snext, tnext
+.globl	spancountminus1, zi16stepu, sdivz16stepu, tdivz16stepu
+.globl	zi8stepu, sdivz8stepu, tdivz8stepu, pz
+s:				.long	0
+t:				.long	0
+snext:			.long	0
+tnext:			.long	0
+sfracf:			.long	0
+tfracf:			.long	0
+pbase:			.long	0
+zi8stepu:		.long	0
+sdivz8stepu:	.long	0
+tdivz8stepu:	.long	0
+zi16stepu:		.long	0
+sdivz16stepu:	.long	0
+tdivz16stepu:	.long	0
+spancountminus1: .long	0
+pz:				.long	0
+
+.globl	izistep
+izistep:				.long	0
+
+//-------------------------------------------------------
+// local variables for d_draw16.s
+//-------------------------------------------------------
+
+.globl	reciprocal_table_16, entryvec_table_16
+// 1/2, 1/3, 1/4, 1/5, 1/6, 1/7, 1/8, 1/9, 1/10, 1/11, 1/12, 1/13,
+// 1/14, and 1/15 in 0.32 form
+reciprocal_table_16:	.long	0x40000000, 0x2aaaaaaa, 0x20000000
+						.long	0x19999999, 0x15555555, 0x12492492
+						.long	0x10000000, 0xe38e38e, 0xccccccc, 0xba2e8ba
+						.long	0xaaaaaaa, 0x9d89d89, 0x9249249, 0x8888888
+
+#ifndef NeXT
+	.extern Entry2_16
+	.extern Entry3_16
+	.extern Entry4_16
+	.extern Entry5_16
+	.extern Entry6_16
+	.extern Entry7_16
+	.extern Entry8_16
+	.extern Entry9_16
+	.extern Entry10_16
+	.extern Entry11_16
+	.extern Entry12_16
+	.extern Entry13_16
+	.extern Entry14_16
+	.extern Entry15_16
+	.extern Entry16_16
+#endif
+
+entryvec_table_16:	.long	0, Entry2_16, Entry3_16, Entry4_16
+					.long	Entry5_16, Entry6_16, Entry7_16, Entry8_16
+					.long	Entry9_16, Entry10_16, Entry11_16, Entry12_16
+					.long	Entry13_16, Entry14_16, Entry15_16, Entry16_16
+
+//-------------------------------------------------------
+// local variables for d_parta.s
+//-------------------------------------------------------
+.globl	DP_Count, DP_u, DP_v, DP_32768, DP_Color, DP_Pix, DP_EntryTable
+DP_Count:		.long	0
+DP_u:			.long	0
+DP_v:			.long	0
+DP_32768:		.single	32768.0
+DP_Color:		.long	0
+DP_Pix:			.long	0
+
+
+#ifndef NeXT
+	.extern DP_1x1
+	.extern DP_2x2
+	.extern DP_3x3
+	.extern DP_4x4
+#endif
+
+DP_EntryTable:	.long	DP_1x1, DP_2x2, DP_3x3, DP_4x4
+
+//
+// advancetable is 8 bytes, but points to the middle of that range so negative
+// offsets will work
+//
+.globl	advancetable, sstep, tstep, pspantemp, counttemp, jumptemp
+advancetable:	.long	0, 0
+sstep:			.long	0
+tstep:			.long	0
+
+pspantemp:		.long	0
+counttemp:		.long	0
+jumptemp:		.long	0
+
+// 1/2, 1/3, 1/4, 1/5, 1/6, and 1/7 in 0.32 form
+.globl	reciprocal_table, entryvec_table
+reciprocal_table:	.long	0x40000000, 0x2aaaaaaa, 0x20000000
+					.long	0x19999999, 0x15555555, 0x12492492
+
+#ifndef NeXT
+	.extern Entry2_8
+	.extern Entry3_8
+	.extern Entry4_8
+	.extern Entry5_8
+	.extern Entry6_8
+	.extern Entry7_8
+	.extern Entry8_8
+#endif
+
+entryvec_table:	.long	0, Entry2_8, Entry3_8, Entry4_8
+				.long	Entry5_8, Entry6_8, Entry7_8, Entry8_8
+
+#ifndef NeXT
+	.extern Spr8Entry2_8
+	.extern Spr8Entry3_8
+	.extern Spr8Entry4_8
+	.extern Spr8Entry5_8
+	.extern Spr8Entry6_8
+	.extern Spr8Entry7_8
+	.extern Spr8Entry8_8
+#endif
+	
+.globl spr8entryvec_table
+spr8entryvec_table:	.long	0, Spr8Entry2_8, Spr8Entry3_8, Spr8Entry4_8
+					.long	Spr8Entry5_8, Spr8Entry6_8, Spr8Entry7_8, Spr8Entry8_8
+
+#endif	// id386
+
--- /dev/null
+++ b/WinQuake/d_zpoint.c
@@ -1,0 +1,47 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// d_zpoint.c: software driver module for drawing z-buffered points
+
+#include "quakedef.h"
+#include "d_local.h"
+
+
+/*
+=====================
+D_DrawZPoint
+=====================
+*/
+void D_DrawZPoint (void)
+{
+	byte	*pdest;
+	short	*pz;
+	int		izi;
+	
+	pz = d_pzbuffer + (d_zwidth * r_zpointdesc.v) + r_zpointdesc.u;
+	pdest = d_viewbuffer + d_scantable[r_zpointdesc.v] + r_zpointdesc.u;
+	izi = (int)(r_zpointdesc.zi * 0x8000);
+
+	if (*pz <= izi)
+	{
+		*pz = izi;
+		*pdest = r_zpointdesc.color;
+	}
+}
+
--- /dev/null
+++ b/WinQuake/data/COMEXP.TXT
@@ -1,0 +1,487 @@
+        COMMERCIAL EXPLOITATION LICENSE AGREEMENT FOR QUAKE
+
+        This Commercial Exploitation License Agreement for QUAKE
+(the "Agreement") is between Id Software, Inc., a Texas
+Corporation, (hereinafter "Id Software") and Licensee (as described
+on the signature page hereof) and is made effective beginning on
+the date of last signature hereto (the "Effective Date"). 
+
+        R E C I T A L S
+
+        WHEREAS, Id Software is the owner and developer of the
+computer software game entitled QUAKE;
+
+        WHEREAS, Id Software desires to license certain
+non-exclusive rights regarding QUAKE to Licensee; and
+
+        WHEREAS, Licensee desires to receive a license for such
+rights. 
+
+        T E R M S    A N D    C O N D I T I O N S
+ 
+        NOW, THEREFORE, for and in consideration of the mutual
+premises contained herein and for other good and valuable
+consideration, the receipt and sufficiency of which is hereby
+acknowledged, the undersigned parties do hereby agree as follows: 
+
+        1.      DEFINITIONS.  As used in this Agreement, the parties
+hereto agree the words set forth below shall have the specified
+meanings: 
+
+        a.      "Authorized Copy" shall mean one (1) copy of the
+                Subject Game actually purchased by Licensee from an
+                Id Software approved retailer; and 
+
+        b.      "Subject Game" shall mean the full registered
+                version of QUAKE on a CD-ROM and shall not mean the
+                shareware or any other version. 
+
+        2.      GRANT OF RIGHTS.  Id Software hereby grants to
+Licensee and Licensee hereby accepts, subject to the provisions and
+conditions hereof, a world-wide (except as otherwise provided
+herein), non-exclusive, non-transferable, and non-assignable
+license to: 
+
+        a.      publicly display an Authorized Copy in exchange for
+                rental payment; 
+
+        b.      run the Authorized Copy so that it will accept
+                network/modem connections in exchange for payments
+                from end-users who also must have actually purchased
+                an Authorized Copy; and 
+
+        c.      otherwise commercially exploit an Authorized Copy,
+                except that Licensee shall not copy, reproduce,
+                manufacture or distribute the Authorized Copy. 
+
+        3.      RESERVATION OF RIGHTS AND PROHIBITIONS.  Id Software
+expressly reserves all rights not granted herein.  Under no
+circumstances shall Licensee copy, reproduce, manufacture or
+distribute (free of charge or otherwise) the Authorized Copy or the
+Subject Game.  Licensee shall not reverse engineer, decompile,
+disassemble, modify or alter the Authorized Copy.  Licensee is not
+receiving any rights hereunder regarding the Trademark or any
+artwork, sound, music or other element of the Subject Game. 
+
+        4.      OWNERSHIP.  Title to and all ownership rights in and
+to the Subject Game, and the QUAKE Trademark (the "Trademark") and
+the copyrights, trademarks, patents and other intellectual property
+rights related thereto shall remain with Id Software which shall have
+the exclusive right to protect the same  by copyright or otherwise.
+Licensee shall have no ownership rights in or to the Subject Game or
+the Trademark and Licensee shall not own any intellectual property
+rights regarding the Authorized Copy, including, without limitation,
+the copyright regarding the Authorized Copy. Licensee acknowledges
+that it only has a limited license to use the Authorized Copy, as
+specified in that certain QUAKE Enduser License contained within the
+Authorized Copy and as specified in this Agreement.
+
+        5.      TERM AND TERMINATION.  
+
+        a.      The term of this Agreement and the license granted
+herein begins on the Effective Date and shall expire on a date one
+(1) calendar year from the Effective Date. 
+
+        b.      Either party may terminate this Agreement, for any
+reason or no reason, on thirty (30) days written notice to the
+other party.  Termination will be effective on the thirtieth (30th)
+day following delivery of the described notice.  Notwithstanding
+anything to the contrary herein, this Agreement shall immediately
+terminate, without the requirement of any notice from Id Software
+to Licensee, upon the occurrence of any of the following:  (a) if
+Licensee shall file a petition in bankruptcy or make an assignment
+for the benefit of creditors, or if any bankruptcy proceeding or
+assignment for benefit of creditors, shall be commenced against
+Licensee and not be dismissed within sixty (60) days after the date
+of its commencement; (b) the insolvency of Licensee; (c) the
+cessation by Licensee of its business; or (d) the cessation by
+Licensee, without the prior written consent of Id Software of the
+distribution, manufacture, and sale responsibilities embodied
+herein.  Further, Id Software may elect to terminate this Agreement
+upon the occurrence of any of the following:  (1) if Licensee's
+business operations are interrupted for forty (40) consecutive
+calendar days; or (2) if each of two Id Software audit inspections
+during any eighteen (18) month period demonstrates an
+understatement by Licensee of Royalty payments due Id Software for
+the six (6) month period immediately preceding each such inspection
+of five percent (5%) or more.  Upon the occurrence of such
+terminating event, and the election of Id Software, if necessary,
+to cause such termination, this Agreement and any and all rights
+thereunder shall terminate without prejudice to any rights or
+claims Id Software may have, and all rights hereunder shall
+thereupon terminate, revert to and be vested in Id Software. 
+
+        6.      EFFECT OF TERMINATION OR EXPIRATION.  Termination or
+expiration of this Agreement, either by Id Software or
+automatically, shall not create any liability against Id Software.
+Upon expiration or earlier termination of this Agreement, Licensee
+shall have no further right to exercise the rights licensed
+hereunder or otherwise acquired in relation to this Agreement. 
+
+        7.      INDEMNIFICATION.  Licensee hereby agrees to
+indemnify, hold harmless and defend Id Software and Id Software's
+predecessors, successors, assigns, officers, directors,
+shareholders, employees, agents, representatives, licensees,
+sublicensees, distributors, attorneys and accountants
+(collectively, the "Id Related Parties") from and against any and
+all damages, claims, losses, causes of action, liabilities,
+lawsuits, judgments and expenses (including, without limitation,
+reasonable attorneys' fees and expenses) arising from, relating to
+or in connection with a breach of this Agreement by Licensee and
+arising from, relating to or in connection with the Licensee's use
+or non-use of the Authorized Copy (collectively, the "Claims").  Id
+Software agrees to notify Licensee of any such Claims within a
+reasonable time after Id Software learns of same.  Licensee, at its
+own expense, shall defend Id Software and the Id Related Parties
+from any and all Claims.  Id Software and the Id Related Parties
+reserve the right to participate in any defense of the Claims with
+counsel of their choice, and at their own expense.  In the event
+Licensee fails to provide a defense, then Licensee shall be
+responsible for paying the attorneys' fees and expenses incurred by
+Id Software and the Id Related Parties regarding the defense of the
+Claims.  Id Software and the Id Related Parties, as applicable,
+agree to reasonably assist in the defense of the Claims.  No
+settlement by Licensee of any Claims shall be valid unless Licensee
+receives the prior written consent of Id Software and the Id
+Related Parties, as applicable, to any such settlement. 
+
+        8.      CONFIDENTIALITY.  It is understood and agreed that
+any proprietary information of Id Software that may from time to
+time be made available or become known to Licensee is to be treated
+as confidential, is to be used solely in connection with Licensee's
+performance under this Agreement, and is to be disclosed only to
+employees of Licensee who have a need for access.  Such proprietary
+information shall include, but not be limited to, trade secrets,
+release information, financial information, personnel information,
+and the like.  Reasonable measures shall be taken by Licensee to
+protect the confidentiality of Id Software's proprietary
+information and any memoranda or papers containing proprietary
+information of Id Software's that Licensee may receive are to be
+returned to Id Software upon request.  Licensee's obligations and
+duties under this paragraph shall survive expiration or earlier
+termination of this Agreement.  Licensee shall obtain from its
+employees an undertaking in a form which may be supplied by Id
+Software, and which is subject to Id Software's prior written
+approval, not to use or disclose to any third party any information
+or knowledge concerning the business of Id Software which may be
+communicated to such employees. 
+
+        9.      LIMITATION OF LIABILITY.  ID SOFTWARE EXPRESSLY
+DISCLAIMS ALL WARRANTIES NOT PROVIDED BY ID SOFTWARE HEREUNDER. 
+UNDER NO CIRCUMSTANCES SHALL ID SOFTWARE BE LIABLE TO LICENSEE FOR
+ACTUAL, SPECIAL, INCIDENTAL, CONSEQUENTIAL OR PUNITIVE DAMAGES OR
+ANY OTHER DAMAGES, WHETHER OR NOT ID SOFTWARE RECEIVES NOTICE OF
+ANY SUCH DAMAGES. 
+
+        10.     COMPLIANCE WITH APPLICABLE LAWS.  In performing
+under this Agreement, Licensee agrees to comply with all applicable
+laws, [including, without limitation, 22 U.S.C., 2778 and 22
+U.S.C. C.F.R. Parts 120-130 (1995)] regulations, ordinances and
+statutes, including, but not limited to, the import/export laws and
+regulations of the United States and its governmental and
+regulatory agencies (including, without limitation, the Bureau of
+Export Administration and the U.S. Department of Commerce) and all
+applicable international treaties and laws.  Further, Licensee
+shall defend, indemnify and hold harmless Id Software from any and
+all sales tax, tariffs and/or duties in connection with Licensee's
+performance hereunder. 
+
+        11.     SPECIFIC UNDERTAKINGS BY LICENSEE.  In addition to
+the obligations of Licensee otherwise set forth in this Agreement,
+during the term of this Agreement, and thereafter where specified,
+Licensee agrees that: 
+
+        a.      It will not attack the title of Id Software to the
+Subject Game or the Trademark and any copyright, patent or
+trademark or other intellectual property right related thereto and
+it will not attack the validity of the license granted hereunder
+during the term hereof or thereafter; and 
+
+        b.      It will promptly inform Id Software of any
+unauthorized use of the Authorized Copy, the Subject Game and the
+Trademark and any portions thereof and reasonably assist Id
+Software in the enforcement of any rights Id Software may have
+against such unauthorized users. 
+
+        12.     FINANCIAL OBLIGATIONS AND ACCOUNTING.
+
+        a.      Payment of Royalties.  Licensee agrees to pay Id
+Software a royalty ("Royalty") at the rate of twelve and one-half
+percent (12.5%) of Net Income.  The term "Net Income" shall mean
+all revenue received by Licensee from the commercial use of the
+Authorized Copy, less only Licensee's actual, documented costs
+relating directly to such use.  A Royalty shall only be due for
+those months in which Licensee's gross revenue from QUAKE
+distribution exceeds U.S. Five Thousand Dollars ($5,000.00) and in
+such months Licensee shall pay a full Royalty on all revenue
+received. 
+
+        b.      Rendition of Statements.  Licensee shall account to
+Id Software with regard to transactions hereunder within forty-five
+(45) days following the conclusion of each calendar quarter. 
+Licensee hereby represents and warrants that such statements of
+account to be prepared shall be true and correct.  The accounts
+shall show in summary form the appropriate calculations relating to
+the computation of Royalties, if any.  The statements shall also
+show the gross revenue received by Licensee per month.  The
+Royalties payable to Id Software hereunder shall be remitted with
+the particular statement indicating such amount to be due.  All
+statements hereunder shall be deemed rendered when deposited,
+postage prepaid, in the United States mail, addressed to Id
+Software at Id Software's address set forth on the signature page
+hereof. 
+
+        c.      Books of Account and Audits.  Licensee shall keep
+books of account relating to the commercial use of the Authorized
+Copy on the basis of generally accepted accounting principles and
+shall maintain such books of account for a period of at least two
+(2) years after the expiration or earlier termination of this
+Agreement; provided, however, that Licensee shall not be required
+to keep such records longer than seven (7) years from their date of
+origination.  Id Software may, upon reasonable notice and at its
+own expense, audit the applicable records at Licensee's office, in
+order to verify statements rendered hereunder.  Any such audit
+shall take place during reasonable business hours and in such
+manner so as not to interfere with Licensee's normal business
+activities.  Id Software agrees that such information inspected
+and/or copied on behalf of Id Software hereunder shall be used only
+for the purpose of determining the accuracy of the statements, and
+shall be revealed only to such officers, directors, employees,
+agents and/or representatives of Id Software as necessary to verify
+the accuracy of the statements.  If in an audit of Licensee's books
+and records it is determined that there is a short fall of ten
+percent (10%) or more in Royalties reported for any calendar
+quarter, in addition to payment of such short fall and interest as
+may be due, as provided herein, Licensee shall reimburse Id
+Software for the full out-of-pocket costs of the audit including
+reasonable travel costs and expenses; provided, however, that the
+amount of reimbursement paid by Licensee shall not exceed U.S.
+Fifteen Thousand Dollars ($15,000.00) for any audit. 
+
+        d.      Payment of the Royalty.  Licensee assumes all risks
+associated with fluctuations in foreign currency exchange rates. 
+Licensee shall pay and agrees to pay all sums due Id Software in
+United States Dollars.  With respect to Royalties due for
+commercial use outside the United States, other currencies shall be
+exchanged at the expense of Licensee into United States Dollars
+using the bid price quoted at the Citibank, N.A. of New York, New
+York, for the purchase of United States Dollars at the close of
+business on the last day of the calendar quarter during which any
+amounts accrue. Payment of the Royalties shall be made in Dallas
+County, Texas. 
+
+        e.      Interest.  If Id Software does not receive the
+applicable Royalty payment on or before the due date of such
+payment, Licensee agrees to pay and shall pay interest on Royalties
+owed to Id Software from such date as specified in the following
+sentence at a rate per annum equal to the Index Rate.  For purposes
+of clarification, the interest will begin to accrue on the first
+(1st) day following the due date of the Royalty payment, unless the
+Royalty payment is paid timely.  The "Index Rate" shall be the
+prime rate as published in The Wall Street Journal's "Money Rates"
+table.  If multiple prime rates are quoted in the table, then the
+highest prime rate will be the Index Rate.  In the event that the
+prime rate is no longer published in the "Money Rates" table, then
+Id Software will choose a substitute Index Rate which is based upon
+comparable information.  The applicable interest rate will be
+determined and take effect on the first day of each month. 
+
+        NOTHING HEREIN SHALL BE CONSTRUED AS A REQUEST OR DEMAND BY
+ID SOFTWARE OF INTEREST AT A RATE HIGHER THAN ALLOWED BY APPLICABLE
+LAW.  IT IS THE INTENT OF THE PARTIES HERETO THAT NO INTEREST BE
+CHARGED HEREUNDER WHICH EXCEEDS THE MAXIMUM RATE ALLOWED BY
+APPLICABLE LAW.  IF THE RATE REFERENCED ABOVE EXCEEDS THE MAXIMUM
+RATE ALLOWED BY APPLICABLE LAW, THEN THE INTEREST RATE MADE
+APPLICABLE HEREIN SHALL BE THE MAXIMUM RATE ALLOWED BY APPLICABLE
+LAW. 
+
+        13.     SUBLICENSE.  Licensee shall not be entitled to
+sublicense any of its rights under this Agreement.   
+
+        14.     GOODWILL.  Licensee recognizes the great value of
+the goodwill associated with the Subject Game and the Trademark,
+and acknowledges that such goodwill, now existing and hereafter
+created, exclusively belongs to Id Software and that the Trademark
+has acquired a secondary meaning in the mind of the public. 
+
+        15.     REMEDIES.  In the event of a breach of this
+Agreement by Id Software, Licensee's sole remedy shall be to
+terminate this Agreement.  In the event of a breach by Licensee of
+this Agreement, Id Software may pursue the remedies to which it is
+entitled under applicable law, including, but not limited to,
+termination of this Agreement.  Licensee agrees that its failure to
+comply with the terms of this Agreement upon expiration or earlier
+termination hereof or Licensee's unauthorized use of the Authorized
+Copy may result in immediate and irreparable damage to Id Software
+for which there is no adequate remedy at law, and in the event of
+such failure by Licensee, Id Software shall be entitled to
+injunctive relief.  Pursuit of any remedy by Id Software shall not
+constitute a waiver of any other right or remedy of Id Software
+under this Agreement or under applicable law.  Termination of this
+Agreement shall not be a pre-condition to Id Software pursuing its
+other remedies for breach. 
+
+        16.     LICENSEE'S WARRANTIES.  Licensee warrants and
+represents that it has full legal rights to enter into this
+Agreement and to perform its obligations hereunder and that it will
+comply, at all times during the terms of this Agreement, with all
+applicable laws, as set forth hereinabove. 
+
+        17.     BANKRUPTCY.  If Licensee's liabilities exceed its
+assets, or if Licensee becomes unable to pay its debts as they
+become due or if Licensee files for voluntary bankruptcy, or is
+placed in bankruptcy which is not dissolved or dismissed after
+thirty (30) days from the petition filing date, or if Licensee
+becomes insolvent, or makes an assignment for the benefit of its
+creditors or an arrangement pursuant to any bankruptcy laws or if
+Licensee discontinues its business or if a receiver is appointed
+for its business, this Agreement shall automatically terminate,
+without notice, and become null and void; provided, however, all
+duties of Licensee upon termination or expiration of this Agreement
+shall continue in full force and effect. 
+
+        18.     ENTIRE AGREEMENT AND ASSIGNMENT.  This Agreement
+constitutes the entire understanding between Licensee and Id
+Software regarding the Subject Game.  Each and every clause of this
+Agreement is severable from the whole and shall survive unless the
+entire Agreement is declared unenforceable.  No prior or present
+agreements or representations shall be binding upon any of the
+parties hereto unless incorporated in this Agreement.  No
+modification or change in this Agreement shall be valid or binding
+upon the parties unless in writing, executed by the parties to be
+bound thereby.  This Agreement shall bind and inure to the benefit
+of Id Software, its successors and assigns, and Id Software may
+assign its rights hereunder, in Id Software's sole discretion. 
+This Agreement is personal to Licensee, and Licensee shall not
+sublicense, assign, transfer, convey nor franchise its rights
+granted hereunder. 
+
+        19.     CHOICE OF LAW, VENUE AND SERVICE OF PROCESS.  This
+Agreement shall be construed in accordance with the laws of the
+State of Texas and applicable U.S. federal law and all claims
+and/or lawsuits in connection with this Agreement must be brought
+in Dallas County, Texas. Licensee hereby agrees that service of
+process by certified mail to the address set forth below, with
+return receipt requested, shall constitute valid service of process
+upon Licensee.  If for any reason Licensee has moved or cannot be
+validly served, then Licensee appoints the Secretary of State of
+the state of Texas to accept service of process on Licensee's 
+behalf. 
+
+        20.     EXCUSED PERFORMANCE.  Neither party shall be deemed
+to be in default of any provision of this Agreement nor be liable
+for any delay, failure in performance or interruption of service,
+resulting directly or indirectly from acts of God, civil or
+military authority, civil disturbance, military action, war,
+strikes, other catastrophes or any other similar cause beyond its
+reasonable control. Written notice to the non-affected party of any
+such condition shall be given by the affected party within ten (10)
+days of the event. 
+
+        21.     DELIVERY OF NOTICES, AND DELIVERY OF PAYMENTS. 
+Unless otherwise directed in writing by the parties, all notices
+given hereunder and all payments made hereunder shall be sent to
+the addresses set forth on the signature page hereof.   All
+notices, requests, consents and other communications under this
+Agreement shall be in writing and shall be deemed to have been
+delivered on the date personally delivered or on the date deposited
+in the United States Postal Service, postage prepaid, by certified
+mail, return receipt requested, or telegraphed and confirmed, or
+delivered by electronic facsimile and confirmed.  Any notice to Id
+Software shall also be sent to its counsel: D. Wade Cloud, Jr.,
+Hiersche, Martens, Hayward, Drakeley & Urbach, P.C., 15303 Dallas
+Parkway, Suite 700, LB 17, Dallas, Texas  75248. 
+
+        22.     NO PARTNERSHIP, ETC.  This Agreement does not
+constitute and shall not be construed as constituting a partnership
+or joint venture between Id Software and Licensee.  Neither party
+shall have any right to obligate or bind the other party in any
+manner whatsoever, and nothing herein contained shall give, or is
+intended to give, any rights of any kind to any third persons. 
+
+        23.     COUNTERPARTS.  This Agreement may be executed in
+several counterparts, each of which will be deemed to be an
+original, and each of which alone and all of which together, shall
+constitute one and the same instrument, but in making proof of this
+Agreement it shall not be necessary to produce or account for each
+copy of any counterpart other than the counterpart signed by the
+party against whom this Agreement is to be enforced.  This
+Agreement may be transmitted by facsimile, and it is the intent of
+the parties for the facsimile of any autograph printed by a
+receiving facsimile machine to be an original signature and for the
+facsimile and any complete photocopy of the Agreement to be deemed
+an original counterpart. 
+
+        24.     MEDIATION.  If a dispute arises out of or relates to
+this Agreement, or a breach of this Agreement, and if the dispute
+cannot be settled through direct discussion, then the parties agree
+to endeavor to settle the dispute in an amicable manner by
+mediation, under the applicable provisions of Section 154.00 et
+seq., Texas Civil Practices and Remedies Code, as supplemented by
+the rules of the Association of Attorney Mediators. 
+
+        25.     SURVIVAL.  The following provisions shall survive
+the expiration or earlier termination of this Agreement: 
+paragraphs 4., 7., 8., and the audit rights of Id Software in
+paragraph 12.c. 
+
+        26.     MISCELLANEOUS.  
+
+        a.      All captions in this Agreement are intended solely
+for the convenience of the parties, and none shall effect the
+meaning or construction of any provision. 
+
+        b.      The terms and conditions of this Agreement have been
+negotiated fully and freely among the parties.  Accordingly, the
+preparation of this Agreement by counsel for a given party will not
+be material to the construction hereof, and the terms of this
+Agreement shall not be strictly construed against such party. 
+
+        By signing in the spaces provided below, the parties have
+agreed to all of the terms and conditions set forth in this
+Agreement. 
+
+
+AGREED:
+
+LICENSEE:       
+
+
+Signed:_______________________________
+Printed Name:_________________________
+Title:________________________________
+Address:______________________________
+______________________________________
+______________________________________
+Telephone #: _________________________
+Fax #:________________________________
+E-Mail Address:_______________________
+Date: ________________________________
+
+
+AGREED:
+
+ID SOFTWARE, INC.
+
+
+Signed:_______________________________
+Printed Name:_________________________
+Title:________________________________
+Address:______________________________
+______________________________________
+______________________________________
+Telephone #: _________________________
+Fax #:________________________________
+E-Mail Address:_______________________
+Date: ________________________________
+
+
+
+June 10, 1996
+
+
+
+COMMERCIAL EXPLOITATION LICENSE AGREEMENT FOR QUAKE
+(DWC:dw:3406.0299:dwc\doc:5017)
+
+
--- /dev/null
+++ b/WinQuake/data/HELP.TXT
@@ -1,0 +1,119 @@
+TECH SUPPORT
+Any of the information listed below could change. Check the id software
+Web Site, at www.idsoftware.com, for updates.
+
+A. Tech Support Options
+id Software does charge for technical support, but we strive to offer
+this service at the lowest cost possible. Because volume on the support
+lines dictate costs, we periodically adjust our rates for Voice Tech
+Support. Check our web site for current pricing.
+
+Paying for Voice or Automated Support
+1 -- You can get Voice Support using a major credit card for a one-time
+shot.  The system asks for your credit card number and expiration date,
+then pre-authorizes your credit card for the tech support call. You will
+only be billed for the number of minutes actually used.
+
+2 -- You can assign yourself a rechargeable PIN account. The system prompts
+you for your credit card information, and assigns you a PIN account number.
+You can use the PIN to access Voice Support, Automated Support and the
+Game Hints Line. Once your account runs out, you can charge it up again.
+
+3 -- You may also charge up a PIN account using the number 1 (900) call-2-id.
+Then call back at 1(800)ID-GAMES (1(800)434-3627), and use your new PIN to
+receive all the support and hints you wish.
+
+4 -- id Software's Game Hints Line is accessible either using a PIN account
+via 1 (800) ID-GAMES (see above), or by calling 1 (900) CALL2-ID, which
+places the call on your phone bill.
+
+	1. Voice Support
+		Telephone -- 1 (800) id-games
+
+		Lines Open from 12 noon to 10pm Central Time, 7 Days a
+                week ($1.75 per minute). Closed some holidays
+
+                Please have the following information handy.
+			1.  Game title and version number. (The version
+                            number can be found on the end text screen.)
+			2.  Your operating system, processor, processor
+                            speed and amount of RAM.
+			3.  If you are having a sound, video or modem
+                            problem, we need to know the device brand name
+                            and model.
+
+	2. Automated Support
+		Telephone -- 1 (800) id-games 
+
+                Lines Open 24 hours a day, 365 days a year, or 366 days
+                in Leap years ($0.25 per minute)
+
+                Please have pencil and paper handy.
+
+	3. E-mail Support
+		Just send your e-mail to support@idsoftware.com
+
+                We will do our best to respond within 48 hours after
+                receiving your e-mail.
+
+                When sending e-mail, cut and paste the following into your
+                e-mail message and fill in the blanks:
+
+Date:  
+Name:  
+Phone number:  
+E-mail address:  (please include this, we redirect tons of mail)
+Game Title:  
+Version #:  
+Operating system (eg., DOS 6.0 or Windows 95):
+Computer type:  
+Processor type:  
+Processor speed:  
+Video card brand and model:  (only if video problem)
+Audio card brand and model:  (only if audio problem)
+Modem brand and model:  (only if modem problem)
+Network card brand and model:  (only if netgame problem)
+Network configuration (eg., NET.CFG file):  (only if netgame problem)
+Drivers, protocol stacks, and versions:  (eg., lsl v2.14, exp16odi
+v2.33, and ipxodi v3.01)  (only if netgame problem)
+If there were any error messages or fault information, report them
+here:
+Please state the problem you encountered:
+Please state how to reproduce the problem:
+
+	4. Web Support
+		Found at www.idsoftware.com
+
+		Our web support pages provide the same information that's
+                available via Automated Support, except it's free!
+
+	5. News Sites
+		For information, FAQ, or announcements:
+			rec.games.computer.quake.announce 
+		For editing and hecking Quake-related files:
+			rec.games.computer.quake.editing
+		For general Quake discussion:
+			 rec.games.computer.quake.misc
+
+	6. Game Hints Line
+		Telephone -- 1 (800) id-games or 1 (900) call-2-id
+
+                Lines Open 24 hours a day, 365 days a year, or 366 days
+                in Leap years ($0.85 per minute)
+                You must be 18 years of age or have parental permission
+                to call 1 (900) call-2-id.
+
+B. In Europe
+        The help lines in Europe are open 7:30am - 5:00pm GMT,
+        Monday - Friday.
+
+English:	+44 01923 209145
+German:		+44 (0)1923 209151
+French:		+44 (0)1923 209148
+
+C. Problems
+	If you have an unfavorable experience using our services, please
+        send e-mail to 911@idsoftware.com.  We would also like to hear
+        from you if you have something positive to share with us.  Kindly
+        include your full name, address, phone number, and the problem
+        encountered or information you'd like to tell us about.
--- /dev/null
+++ b/WinQuake/data/LICINFO.TXT
@@ -1,0 +1,97 @@
+Here is a brief explanation  of all the legal mumbo jumbo contained in the
+various license agreements that may or may not be part of this package.
+
+(This document was designed to be a quick overview of our license terms.
+You must refer to the full text of the license for a complete listing of 
+terms and conditions.)
+
+QUAKE SHAREWARE END USER LICENSE (slicnse.txt) or
+What You Can and Cannot Do With the Shareware Version of Quake.
+
+CAN DO:
+-- Play & Enjoy the single player game 
+-- Setup a shareware version based server on a not-for-profit basis
+
+CANNOT DO:
+-- Run the game with user developed levels.  
+-- You may not commercially exploit the shareware version in any way
+        This specifically excludes retail distribution of the shareware 
+        version. Do not call or e-mail to ask if you can be a retail 
+        distributor of the shareware version -- the answer is no! 
+-- Commercially exploit any id copyrighted and/or trademarked property. 
+        Example: Game names, logos, graphics, etc.
+
+
+QUAKE REGISTERED VERSION END USER LICENSE (rlicnse.txt) or
+What You Can and Cannot Do With the Registered Version of Quake.
+
+CAN DO:
+-- Play & Enjoy the single player game
+-- Setup a registered version based server on a not-for-profit basis
+-- Develop new levels and/or level creation utilities.  
+-- Play the game and/or setup a Registered Version based server using
+   a user-developed level.
+
+CANNOT DO:
+-- Commercially exploit the Registered  Version of Quake in any way;
+   see commercially exploitation license info below.
+-- Commercially exploit any id copyrighted and/or trademarked
+   property. 
+        Example: Game names, logos, game graphics, etc. 
+-- Sell user-developed levels and/or tools
+
+COMMERCIAL EXPLOITATION LICENSE (comexp.txt -- accompanies Quake
+                                 registered version only)
+
+If you are interested in trying to make money using the registered version
+of Quake (this sort of thing is not allowed using the shareware version) you
+must sign our easy-to-digest Commercial Exploitation License.
+
+This is a royalty free license that allows you to run Quake for a profit
+through a certain monthly gross profit range. If your Quake-related business
+becomes successful the agreement brings id into the revenue stream.
+
+Basic terms of the commercial exploitation license:
+
+-- License grants a royalty free commercial exploitation right for the
+   registered version of Quake as a whole so long as Quake's monthly gross
+   revenue is below $5,000.00
+
+-- License provides for a 12.5% royalty to be paid to id Software in months
+   where the licensee's Quake related monthly gross revenue is above $5,000.00
+
+-- Royalty is based off net income.  Net income is defined as Quake-related
+   gross income less Quake-related expenses.
+
+-- License expressly prohibits commercial exploitation via the sale (retail
+   or otherwise) of the shareware or registered versions of Quake.
+
+-- License expressly prohibits advertising/marketing use of our copyrighted
+   and/or trademarked properties.
+
+To get into bed with us on this deal you must print two (2) copies of the
+document named comexp.txt. (You should find comexp.txt somewhere on the
+registered version CD.)  Sign/fill in the blanks of both copies where
+indicated and mail both to:
+
+		id Software
+		18601 LBJ #666
+		Mesquite, TX  75150
+		Attn: ComExp License
+
+We will then countersign the documents and mail one back to you.
+
+Two items worth noting here:
+
+1. It is VERY IMPORTANT that the information you enter in the signature
+block be legible. We prefer it if you enter the info into the blanks before
+printing your two copies. If we cannot read your information we will not be
+able to return the documents to you.
+
+2. The terms of this document are not subject to negotiation. If you cannot
+live with the terms spelled out in the agreement do not engage in any
+commercial exploitation of Quake and do not sign the document.
+
+
+ 
+
--- /dev/null
+++ b/WinQuake/data/MANUAL.TXT
@@ -1,0 +1,1030 @@
+Table of Contents
+        I. THE STORY
+                A. Background
+                B. Prelude to Destruction
+
+        II. INSTALLING QUAKE
+                A. Installation
+                B. README.TXT
+                C. MANUAL.TXT
+                D. TECHINFO.TXT
+
+        III. THE BASICS OF PLAY
+		A. Goal of the Game
+		B. Skill
+		C. Episode
+		D. Getting About 
+		E. Finding Things
+
+        IV. CONTROLS
+		A. Keyboard Commands
+		B. The Main Menu
+		C. Console
+		D. Command Line
+		E. Cheat Codes
+
+        V. THE GAME
+		A. The Screen
+		B. Messages 
+		C  Ending a Level
+		D. Ending a Dimension
+
+        VI. YOUR NEW ENVIRONMENT
+		A. Firepower
+		B. Ammo
+		C. Power-ups
+		D. Bad Guys
+		E. Environmental Hazards and Effects
+
+        VII. MULTIPLAYER ACTION 
+		A. Cooperative
+		B. Deathmatch	
+		C. Team Games 
+
+        VIII. COMMONLY ASKED QUESTIONS
+
+        IX. TECH SUPPORT
+		A. Tech Support Options
+		B. In Europe
+		C. Problems
+
+	X. LEVELS AND DESIGNERS
+
+	XI. LEGAL BOILERPLATE 
+****************
+I. THE STORY
+A. Background
+      You get the phone call at 4 a.m. By 5:30 you're in the secret
+   installation. The commander explains tersely, "It's about the Slipgate
+   device. Once we perfect these, we'll be able to use them to transport
+   people and cargo from one place to another instantly.
+
+      "An enemy codenamed Quake, is using his own slipgates to insert death
+   squads inside our bases to kill, steal, and kidnap..
+
+      "The hell of it is we have no idea where he's from. Our top scientists
+   think Quake's not from Earth, but another dimension. They say Quake's
+   preparing to unleash his real army, whatever that is.
+
+      "You're our best man. This is Operation Counterstrike and you're in
+   charge. Find Quake, and stop him ... or it ... You have full authority
+   to requisition anything you need. If the eggheads are right, all our
+   lives are expendable.."
+
+B. Prelude to Destruction
+      While scouting the neighborhood, you hear shots back at the base Damn,
+   that Quake bastard works fast! He heard about Operation Counterstrike,
+   and hit first. Racing back, you see the place is overrun. You are almost
+   certainly the only survivor. Operation Counterstrike is over. Except for
+   you.
+
+      You know that the heart of the installation holds a slipgate.
+   Since Quake's killers came through, it is still set to his dimension.
+   You can use it to get loose in his hometown. Maybe you can get to the
+   asshole personally. You pump a round into your shotgun, and get moving.
+      
+II. INSTALLING QUAKE
+A. Installation
+   You must install Quake before you can play it. It will not run off the
+   CD-ROM. Place the CD-ROM into your drive, log on to that drive, and type
+   'INSTALL'. If you have downloaded Quake via modem, simply go to the
+   directory you've placed Quake in, unzip it, and type 'INSTALL'.
+
+B. README.TXT
+   After you install Quake, you go right into the README.TXT file, which is
+   henceforth available in your Quake directory. This is a full listing of
+   Quake's technical parameters, and is constantly updated with new versions
+   of Quake. We strongly recommend that after you install Quake, you glance
+   through README.TXT.
+
+   You may wish to print this file out, so you can have a copy of it on hand
+   while playing Quake.
+
+C. MANUAL.TXT
+   Also available in your Quake directory is a file labeled MANUAL.TXT.
+   This is the file you are now reading.
+
+D. TECHINFO.TXT
+   For those who are more technically inclined, or to fill out a bug report,
+   check out TECHINFO.TXT. Information on filling out a bug report is located
+   at the end of TECHINFO.TXT.
+
+
+III. THE BASICS OF PLAY
+A. Goal of the Game
+	Quake has two basic goals. First, stay alive. Second, get out of the
+        place you're in. The first level of each episode ends in a slipgate -- 
+        these signify that
you're entering another dimension. When you complete 
+        an entire
dimension (this takes six to eight levels), you'll find a
+        Rune and another slipgate, which returns you to the start. 
+
+B. Skill
+	The start area has three short hallways. The one you go down selects
+        the Skill you wish to play at.
+	Easy -- This is meant for little kids and grandmas. 
+	Medium --  Most people should start Quake at Medium skill. 
+	Hard -- Here at id, we play Hard skill, and we think you should too,
+        once you're ready.
+	(Nightmare) -- This is so bad that the entry is hidden, so people
+        won't wander in by accident. If you find it, don't say we didn't warn
+        you.
+
+C. Episode
+	After the Skill halls, you're in a room with four exits. Each exit
+        leads to a different military complex, at the end of which is a
+        slipgate leading to a new dimension. If you have not registered, the 
+        first episode, Dimension of the Doomed, is the only place you can go. 
+        After registration, all four episodes are available. The other three 
+        episodes, in order from second to fourth, are Realm of Black Magic, 
+        Netherworld, and The Elder World.
+
+=============================================================================
+== TIP -- From episode 1 to episode 4, the dimensions become progressively ==
+== more difficult. We suggest you play the episodes in the proper order to ==
+== get the maximum fun out of Quake.                                       ==
+=============================================================================
+
+D. Getting About
+      The specific keys named below can be changed by using the Configure Keys
+      Menu. If you have renamed Run as the R key, for instance, then the Shift 
+      key will not double your speed. 
+   Walk
+      Use the arrow keys or the mouse. To walk steadily forward, hold down
+      the Forward key (up arrow or center mouse button). Turn left or right
+      with the left or right arrow keys or sliding your mouse to the left or 
+      right.
+   Run
+      Hold down Run (the Shift key) to double your speed.
+   Jumping
+      Tap the Jump key (the space bar or Enter key). You jump further if 
+      you're moving forward, and you jump higher if you're moving up a slope at 
+      the time. You'll be surprised at the spots you can reach in a jump. You 
+      can even avoid some attacks by jumping at the right time.
+   Swimming
+      When underwater, aim yourself in the direction you wish to go, and
+      move forward. You have full three-dimensional freedom. Unfortunately,
+      as in real life, you may lose your bearings while underwater. Use
+      jump (the space bar or Enter key) to kick straight up towards the
+      surface. Once on the surface, tread water by holding down jump.
+      To get out of the drink, swim towards the shore. Once there, use jump
+      to clamber up. If you're down a well or you can't get a grip, you may
+      not be able to climb out. There is always another way out, but you may
+      have to submerge to find it.
+   Shooting
+      Tap the Shoot key (the Ctrl key or left mousebutton) to fire. Hold it 
+      down to
keep firing.
+   Use
+      Quake has no "Use" function. To push a button or open a door, walk up
+      to it. To ride a platform up or down, step atop it. If a door won't open 
+      or a platform won't lower, you may need to do something special to 
+      activate it.
+   Picking up stuff
+      To pick up items, weapons, and power-ups, walk over them. If you can't
+      pick up something, it means you already have the maximum possible of 
+      that thing. If it is armor, it means the stuff you're trying to get is 
+      worse than what you now have.
+
+E. Finding Things
+   Buttons and Floorplates
+      Buttons activate with a touch, and floorplates must be stepped on.
+      If you see a distinctive-looking button in a spot you cannot reach,
+      it's probably a shootable button-- fire at it.
+   Doors
+      Most doors open at your approach. If one doesn't, seek a button,
+      floorplate, or key.
+   Secret Doors
+      Some doors are camouflaged. Almost all secret doors open when they are
+      shot or hit with an axe. The rest are opened by hidden pressure plates
+      or buttons.
+   Platforms
+      Most platforms only go up and down, while some follow tracks around
+      rooms or levels. When you step atop of a platform, it rises to its
+      full height, and usually only lowers when you step off. Some platforms
+      must be activated via button or pressure plate.
+   Pressure Plates & Motion Detectors
+      Invisible or visible sensors which open doors, unleash traps, warn
+      monsters, etc.
+   Uncovering Secrets
+      Secrets are hidden lots of ways. You might need to shoot a button, kill
+      a monster, walk through a secret motion detector, etc.
+   The Secret of Secrets
+      All secrets in Quake are indicated by clues. Don't waste your time
+      hacking at every wall. It's much more productive (and fun) to use your
+      brain and your eyes. Look up. An angled texture, a light shining under
+      a wall, a strange sound -- anything -- might be the clue. Something
+      prominent in a room might be decoration ... or it might be the clue.
+
+=============================================================================
+== TIP -- Bouncing a grenade off a shootable button or secret door won't   ==
+== open it, but if the grenade's explosion goes off nearby, this may       ==
+== activate such secrets.                                                  ==
+=============================================================================
+
+IV. CONTROLS
+A. Keyboard Commands
+   By using the key configuration option from the Main Menu, you can
+   customize the keyboard to suit your fancy, except for the Function keys,
+   the Escape key, and the ~ (tilde) key.
+
+FUNCTION KEYS
+Help				F1
+Save Game			F2
+Load Game			F3
+Options Menu			F4
+Multiplayer Menu		F5
+Quicksave			F6
+Quickload			F9
+Quit to operating system        F10
+Screenshot                      F12
+
+WEAPONS
+Axe				1
+Shotgun				2
+Double Barrelled Shotgun	3
+Nailgun				4
+Supernailgun			5
+Grenade Launcher		6
+Rocket Launcher			7
+Thunderbolt			8
+Change to next weapon		/
+
+MOVEMENT
+Move / Turn	arrow keys
+Jump / Swim	Space bar or Enter
+Run		Shift
+Sidestep Left	. or >
+Sidestep Right	, or <
+Strafe *	Alt
+Swim Up         D
+Swim Down       C
+
+OTHER CONTROLS
+Main Menu		Escape
+Console			~ (tilde)
+Look Up			A or PgDn
+Look Down		Z or Del
+Center View		X or End
+Mouse Look **		\ or center mouse button
+Keyboard Look ***	Ins
+
+  * Turning right or left sidesteps instead while the Strafe key is pressed.
+ ** Sliding your mouse forward and back looks up and down while the Mouse
+    Look key is pressed.
+*** The walk forward/backpedal arrows will look up and down while the
+    Keyboard Look key is pressed.
+
+B. The Main Menu
+   Tap the Escape key to pop  up the Main Menu. While you are in the menu,
+   the game is paused.
+      Use the arrow keys to move the Quake icon up and down the menu. Place 
+   the icon before the desired option, and tap the Enter key. To return to the
+   Main Menu, tap the Escape key again. To exit the menu and return to the
+   game, tap the Escape key when you are on the Main Menu.
+
+   NEW GAME
+      Discards the game you're playing, and starts anew.
+
+   MULTIPLAYER
+      Controls multiplayer game starting and details...
+      Name
+         Type your name or alias here, and all messages about you will use
+         this. So the computer says stuff like, "Josephine rides Bad Bill's
+         rocket."
+      Shirt Color
+         Lets you select your character's uniform color from 14 different
+         options (numbered 0-13).
+      Pants Color
+         As above, but your pants color also determines what team you're on,
+         if in team play. (After all, pants are more important than shirts.)
+      Communications Configuration
+         Takes you to a separate menu on which you can change communications
+         settings.
+         Com Port
+            Selects the COM Port to use for Communications. A null modem or 
+            modem must be connected to this port.
+         Baud Rate
+            Selects the COM port baud rate (9600-57600bps). This is NOT the
+            same as setting the modem speed. The COM port speed must be AT 
+            LEAST the same speed as the modem speed.
+         Device
+            Selects the type of connection, either direct (null-modem) or
+            modem.
+         Modem Init String
+            The Initialization string for the modem. 
+      
+      Start a Multiplayer Game
+         If you want your machine to be the host for a multiplayer game 
+         (Note: if you are starting a listen server, id Software strongly 
+         recommends that the fastest machine act as the host! If you are
+         playing a game with more than 4 players, we suggest using a 
+         dedicated server as the host!), select this option, and you'll get
+         the following menu  ...
+         Begin Game
+            Starts up the game. Now all your friends have to do is log on, 
+            using either "search for local network games" or "join a 
+            running game at..." Multiplayer options (see below). 
+         Maximum Players
+            You can have up to 16 players. You need at least 2, or it's not 
+            "multiplayer", right?
+         Game Type
+            Toggles between cooperative and deathmatch.
+         Team Color Rules
+            Toggles between "none" and "no friendly fire". In the latter mode, 
+            your shots won't injure someone wearing the exact same color 
+            pants as you. 
+         Skill
+            Chooses skill level. Only applicable in a cooperative game. 
+         Frag Limit
+            From none to 100, in ten-frag increments. When someone reaches 
+            the frag limit, by killing the 40th (or whatever) person, then 
+            the game ends immediately, and final scores are printed. If your 
+            frag limit is none, the game won't end till someone exits the 
+            level or the time limit expires. 
+         Time Limit
+            From none to 60 minutes, in 10 minute increments. When the time
+            limit is up, the game ends immediately, and final scores are 
+            printed. If your time limit is none, the game won't end till 
+            someone exits the level or the frag limit is reached. 
+         Start Map 
+            Lets you choose what map you'd like to play on. The top line 
+            gives you the episode name, and the lower line is the level's 
+            name. Note that all levels in Quake are fun to play, but the 
+            episode Deathmatch Arena is composed of special levels that are 
+            solely-designed for deathmatch play. Try them, you'll like them. 
+      Search For Local Network Games
+         Has your computer look through your network. It will list all the 
+         games it finds on the console, and you can choose to join one of 
+         them by typing connect <server>.
+      Join A Running Game At ... 
+         Lets you join a game either by typing its net address (for a net 
+         game) or your friend's modem phone number (for a modem game). 
+         If necessary, ensure your modem and network connections are operative 
+         by checking your Communications Configuration menu. 
+
+   SAVE
+      Brings up a list of saved games. Highlight the desired slot, and tap the 
     Enter key. Each saved game is identified by the level's name, plus the 
+      proportion of kills you have achieved so far. 
+   LOAD
+      Brings up a list of saved games. Highlight the desired slot, and tap the
+      Enter key. 
+   OPTIONS
+      Miscellaneous game options ...
+         Configure Keys
+            Permits you to customize Quake so every action is linked to the 
+            button or key that you prefer. 
+               First, move the cursor (via the arrow keys) to the action you 
+            wish to change. Then tap the Enter key. Now press the key or 
+            button you want to bind to that action. For instance, if you wish
+            to use the Alt key for Jump, move the cursor to Jump / Swim, tap 
+            the Enter key, then press the Alt key. 
+               Each action can have two different keys assigned to it. If you 
+            already have two keys in an entry, you cannot add more from this 
+            menu. 
+               To clear the keys bound to an action, move the cursor to that 
+            action and tap the Backspace or Delete key instead of the Enter 
+            key. This will clear the keys formerly bound to that action, 
+            leaving it blank.
+               You can bind any key to an action except Function keys, the 
+            Escape key, and the ~ (tilde) key. "Weird" keys such as Scroll 
+            Lock, Print Screen, etc. may or may not work, depending on your 
+            machine, but why bother?
+ 
+            Attack
+               Fires your weapon
+            Change Weapon
+               Switches to the weapon "above" the one you're now using. Wraps 
+               around to the axe.
+            Jump / Swim Up
+               If you're on land, jumps. If you're underwater, kicks you 
+               towards the surface. If you're right at the water's edge, pops
+               you up out of the water, if you combine it with forward 
+               movement. 
+            Walk Forward 
+            Backpedal 
+            Turn Left 
+            Turn Right 
+            Run
+               Press this while moving, and you move at double speed. 
+            Step Left
+               Sidesteps (strafes) left
+            Step Right
+               Sidesteps (strafes) right
+            Sidestep
+               Press this when using turn left or turn right and you sidestep
+              (strafe) instead.
+            Look Up
+               Lets you angle your view upwards. Your view returns to 
+               horizontal when you start walking forward. 
+             Look Down
+               Lets you angle your view upwards. Your view returns to 
+               horizontal when you start walking forward. 
+             Center View
+                If  you're looking up or down, returns your view to dead 
+                center. 
+             Mouse Look
+                Press this to allow your mouse to look up or down (by 
+                sliding it forward and back), and to remain looking up or 
+                down even if you move forward. 
+             Keyboard Look
+                Press this to use your movement keys to look up or down. 
+             Go To Console
+                Brings down the Console. Also possible by tapping the 
+                ~ (tilde) key. 
+             Reset To Defaults
+                Everything you've changed in the options menu is reset by 
+                this option. Consider it an "Oops" key. 
+             Screen Size
+                A slider which enlarges or shrinks your view area. All 
+                Quake's sliders use the right and left arrow keys. 
+             Brightness
+                Pretty much self-explanatory. Choose a brightness which 
+                doesn't strain your eyes. 
+             Mouse Speed
+                Adjusts mouse sensitivity. The further you set the slider 
+                to the right, the quicker your mouse reacts. 
+             Music Volume
+                Self-explanatory
+             Sound Effects Volume
+                Self-explanatory
+             Always Run
+                When this is selected, you do not need the Run key -- you 
+                are always at double speed.
+             Invert Mouse Up / Down
+                This gives your mouse "airplane-style" controls. This means 
+                that pushing the mouse forward "noses down", and pulling it 
+                back "noses up". Some people prefer this control technique. 
+              Lookspring
+                 Returns your view immediately to straight ahead when you 
+                 release the look up / down key. Otherwise, you must move 
+                 forward for a step or two before your view snaps back. 
+                 Lookspring does not work while you are underwater. 
+              Lookstrafe
+                 If you are using the look up / down key, then this option 
+                 causes you to sidestep instead of turn when you try to move 
+                 left or right.
+
+   HELP / ORDERING
+      Lists the default keyboard and mouse commands. Also contains the 
+      information you need to register Quake. 
+    QUIT
+      Exits Quake at once. 
+
+=============================================================================
+== TIP -- Quake saves your current key configuration when you quit, so     ==
+== next time you play, you have the same configuration.                    ==
+=============================================================================
+
+C. Console
+      Tap the ~ (tilde) key to bring down the console. As with the Main Menu, 
+   when the console is down, a singleplayer game is paused. A wide variety of
+   esoteric commands can be entered at the console. If your keyboard has no 
+   ~ (tilde), the Options Menu (inside the Main Menu) has a "Console" option. 
+
+D. Command Line
+   For special command line parameters, see README.TXT. 
+
+E. Cheat Codes
+   id Software, as in our previous games, has removed all cheat codes from 
+   Quake. 
+
+V. THE GAME
+A. The Screen
+      The large top part of the screen is the view area, in which you see 
+   monsters and architecture. Immediately below is the Inventory, beneath 
+   which is the Status Bar. You can enlarge the viewing area (tap the + key), 
+   so much that it engulfs first the Inventory Bar and then the Status Bar. 
+   The - key shrinks the view area. 
+
+   Inventory Bar
+      Lists ammo, weapons, deathmatch scores, and power-ups.
+         The active weapon is lit up. Each weapon has a number by it -- type 
+      the appropriate number key to switch to that weapon.
+         In addition, this gives the amount of ammo you have of each type, 
+      any keys you possess, and any power=ups currently active. Plus it shows 
+      how many and which of the four Runes you possess. 
+         In Deathmatch, it shows the top four scores in the game. 
+
+   Status Bar
+      A vital part of the screen. When your armor, hit points, or ammo get 
+      low, the number turns red. 
+         From left to right, the big numbers represent: Armor Points, Health, 
+      and Ammo (of the current weapon). Icons show the Armor Type (green,  
+      yellow, or red), your adorable face, and your Ammo Type). 
+
+   Score Bar
+      Hold down theTab key to replace the Status Bar with the Score Bar. 
+         This lists the proportion of monsters you've killed, secrets you've 
+      found, and time you've spent, along with the level name. 
+         In Deathmatch, the Score bar lists the top six scorers, along with 
+      their names. 
+
+B.  Messages 
+   Quake talks to you from time to time. Some messages appear at the top of 
+   the screen. These are non-critical, and tell you that you've picked up an 
+   object, or you've died in an interesting fashion. Ignore these messages if
+   you please. 
+      Certain messages appear inconveniently in the middle of your view. These 
+   are always important, and you do not want to ignore them!
+
+D Ending a Level
+   Once you finish a level, you'll find a slipgate or a distinctive archway 
+   leading to the next level. Pass through to emerge onto a new level. 
+      You start the new level with the same armor, weapons, and ammo you had at 
+   the end of the previous one. If a power-up was active at the end of the 
+   previous level, it is now, sadly, gone. Make the best of it. If your hit 
+   points were over 100 or under 50, they are altered to 100 or 50, 
+   respectively. Otherwise, your hit points are unchanged. 
+
+D. Ending a Dimension
+   Once you've finished all the levels in a particular dimension, you return 
+   to the starting hall. New dimensions are started from scratch -- you, your 
+   shotgun, and axe.
+
+VI. Your New Environment
+A. Firepower
+   You are blessed with eight different Means o' Mass Destruction. Each has 
+   its place in a balanced diet. 
+
+   Axe
+      The last resort. Face it  -- going toe-to-toe with the uglies in Quake
+      demonstrates all the good sense of a man parachuting into an alligator 
+      farm. 
+
+   Shotgun
+      The basic gun, to which all other guns compare favorably.
+
+   Double-barrelled Shotgun
+      A worthy weapon with three minor drawbacks: first, it uses up 2 shells 
+      per blast; second, it's slow; third, its shot pattern is very loose at 
+      long range. But in general, once you find this puppy, the other shotgun 
+      starts rusting from disuse. 
+
+   Nailgun
+      A two-barrel dingus that prickles bad guys with armor-piercing darts, 
+      technically termed "nails". 
+
+   Supernailgun 
+      The great equalizer. Four cyclic barrels that hose out spikes like 
+      crazy. Pro: foes drop like flies. Con: eats ammo like popcorn. 
+
+   Grenade Launcher
+      Thumps neat exploding bombs into the air. You can even bounce a grenade
+      off the wall or floor.. When a grenade hits someone, it explodes. 
+      If it misses, the bomb sits on the floor for a moment, then explodes. 
+      Even though I sometimes bounce grenades into myself, this gun's still 
+      my favorite. 
+
+   Rocket Launcher
+      For when a grenade positively, absolutely, has to be there on time. 
+
+   Thunderbolt  
+      Try it. You'll like it. Use the same technique as watering your 
+      rosebush.
+
+   Switching Between Weapons
+      If you are firing a weapon and run out of ammo, Quake automatically 
+      switches you to another weapon. It will never switch to the grenade 
+      launcher or rocket launcher, however, for reasons that ought to be 
+      obvious. So if you're firing away happily and suddenly switch to the 
+      axe, it doesn't mean you're out of all ammo -- you may still have 
+      grenades. But Quake requires you to select such dangerous 
+      explosives on your own. 
+
+=============================================================================
+== TIP -- If you shoot the Thunderbolt underwater, it discharges all its ==  
+== cells in every direction in a single gigantic KA-ZAP, with you at the   == 
+== center. Don't try this at home.                                         ==
+=============================================================================
+
+B. Ammo
+   The eight weapons use four types of ammo. Each ammo type comes in two 
+   flavors -- small and large. The large boxes carry twice as much as the 
+   small. 
+
+   Shells 
+      For shotguns and double-barrelled shotguns. A small box holds 20.
+
+   Flechettes 
+      For nailguns and supernailgunss. A small box holds 25. 
+
+   Grenades 
+      For grenade launchers and rocket launchers. A small crate holds 5.
+
+   Cells 
+      For Mr. Thunderbolt. A small battery has 6 charges, lasting a little 
+      over a second.
+
+C. Power-ups
+   All power-ups except armor burn out after a while, so smoke 'em while you 
+   got 'em. 
+
+   Armor 
+      Comes in three flavors; green, yellow, and red, from weakest to most 
+      powerful.
+
+   Megahealth
+      Gives you 100 additional hit points. After a few seconds, all hit points 
+      over 100 start slowing draining away, because it's too much for the human 
+      frame to hold. Still, it's nice while it lasts. 
+
+   Biosuit 
+      lets you breathe underwater and swim through slime without harm. Does 
+      not protect against lava. 
+
+   Ring of Shadows 
+      Renders you almost totally invisible. Only your eyes can be seen. 
+      Monsters don't detect you unless you do something stupid. Like shoot.
+
+   Pentagram of Protection 
+      Renders you invulnerable. 
+
+   Quad Damage 
+      Magnum upgrade! You now deliver four times the pain!
+
+=============================================================================
+== TIP -- When quad damage is activated, use the grenade or rocket         ==
+== launcher with care -- their bursts are four times as deadly to you, as  ==
+== well as your enemies.                                                   ==
+=============================================================================
+
+D. Bad Guys
+   Quake critters are extremely tough, but you have the firepower to vent 
+   your grievances on them anyway. Good hunting. 
+
+   Rottweiler
+      Bad, bad doggie! Play dead! -- blam! -- yipe! Good  dog!
+
+   Grunt 
+      Goons with probes inserted into their pleasure centers; wired up so 
+      when they kill someone, they get paroxysms of ecstasy. In essence, 
+      customized serial killers. Easy to kill, and they tote shotgun shells. 
+      It's like a little Christmas each time you blow a Grunt away!
+
+   Enforcer (registered only) 
+      Grunt, Mark Two. Recruits who are surlier and beefier than the rest get 
+      outfitted in combat armor and built-in blasters. 
+
+   Knight 
+      Canned meat. Open 'er up and see if it's still fresh. 
+
+   Death Knight (registered only) 
+      This particular canned meat tends to open you up instead. 
+
+   Rotfish (registered only) 
+      Disgusting little critters who dish it out, but can't take it.
+
+   Zombie
+      Thou canst not kill that which doth not live. But you can blast it 
+      into chunky kibbles. 
+
+   Scrag 
+      Floats like a butterfly, stings like a bee. Ugly as hell. They're not 
+      real tough, but like to bushwhack you. 
+
+   Ogre 
+      What's worse than a cannibal monster eight feet tall? One with a 
+      chainsaw. And a sack of grenades.
+
+   Spawn (registered) 
+      A merrily bouncing blob as dangerous to kill as to ignore. Blech.
+
+   Fiend 
+      In essence, organic buzzsaws, rife with pummeling power! 
+
+   Vore (registered) 
+      A spideresque hybrid horror. Keep your eye on the energy pod he hurls. 
+
+   Shambler 
+      Even other monsters fear him, so expect a clobbering. He shrugs off 
+      explosions. Good luck. 
+
+=============================================================================
+== TIP -- Some weapons are better vs. particular monsters than others. If  ==
+== a new monster seems real tough, switch weapons.                         ==
+=============================================================================
+
+E. Environmental Hazards and Effects
+
+   Explosions
+      Radioactive containers are in some military bases. Shooting these 
+      things unleashes a big boom, so be careful -- you may not want to 
+      stand too close in a firefight. 
+         Your own grenades and rockets cause explosions too, of course -- the 
+      blast can hurt you if you're too close. 
+
+   Water 
+      Safe enough unless you stay under so long you start to drown. Come up 
+      for air periodically to prevent this. 
+
+   Slime 
+      Hurts you instantly and keeps on hurting. Stay out of slime unless you 
+      have a very good reason to take a dip. 
+
+   Lava 
+      If you're quick and the lava's shallow, you might escape before you're 
+      burnt to a crisp,  but don't bet on it. 
+
+   Traps 
+      Quake has many different traps. Don't be paranoid, because traps aren't 
+      really very common, but be aware of their existence. Traps can't be 
+      classified because they come in many varieties -- monsters in ambush, 
+      spike shooters, crushing walls, trapdoors, etc. 
+
+    Teleporters 
+      These are distinctive in appearance and emit a unique sound. When you 
+      step into a teleporter, you're instantly transported to another 
+      teleporter, or atop a teleport pad. If you teleport directly right atop 
+      of somebody else, he or she is killed instantly. 
+
+=============================================================================
+== TIP -- Monsters are smart enough not to activate their own traps, but   ==
+== if you activate the traps, the monsters can get caught by them.         ==
+=============================================================================
+
+VII. Multiplayer Action 
+   Quake can be even more fun when you're playing with friends than when 
+   you're playing by yourself.
+      When you are using the console or Main Menu in multiplayer, the game does
+   not pause. Irresponsible players and monsters can freely shoot you, and
+   your only recourse is bloodthirsty vengeance. 
+     The Talk function is useful here. When you talk, the message appears at 
+   the top of all players' screens, preceded by the speaker's name.
+     To talk, press 'T' and start typing your message. Press ENTER to set
+   the message to everyone.
+     To set up, run, or join a multiplayer game, use the Main Menu Multiplayer
+   option. README.TXT contains details that may be useful if your network or 
+   modem need special configurations. 
+
+A. Cooperative
+   In a co-op game, you and your friends work together to finish the level. 
+   When one person exits, everyone else exits too, wherever they might be. If 
+   you are killed in co-op, you reappear at the start area, and have to catch 
+   up to your buddies. Use Talk to find out where they are. See the 
+   Multiplayer options on the Main Menu for more info.
+
+B. Deathmatch	
+   In a deathmatch, play is totally cutthroat. No monsters exist, and when 
+   you are killed, you reappear in a random spot. After you pick up an item, 
+   it respawns (i.e. pops back into existence) after a while. (Some items 
+   take longer to respawn than others.) Every time you kill someone, you get 
+   a Frag. The person with the most Frags wins, so wreak slaughter amongst 
+   your pals! 
+      If you kill yourself, whether intentionally or by accident, you lose a 
+   Frag. This includes drowning, getting crushed, and so forth. See the 
+   Multiplayer options on the Main Menu for more info.
+
+C. Team Games 
+   Team play is a cool combination of co-op and deathmatch. Each team picks 
+   a "uniform" and everyone on that team changes their color to the team 
+   color. The team with the most Frags wins. See README.TXT or the Main Menu 
+   for details. 
+
+=============================================================================
+== TIP -- if you have the Team Color Rules set to No Friendly Fire, your   ==
+== weapons won't hurt other players wearing the same color pants as you.   ==
+== (You can still have differently-colored shirts.) Your shots still wear  ==
+== down their armor, and your own grenade and rocket explosions still hurt ==
+== YOU, just not them.                                                     ==
+=============================================================================
+
+VIII. Commonly Asked Questions
+
+Q. I'm stuck. How do I get through the level?
+A. Take a stroll around and look for a place you haven't been yet. Sometimes 
+you have to kill a particular monster in order to progress, so exterminate 
+them all!
+
+Q. How can I find all the secrets? 
+A. Don't worry about it. You never have to find a secret to finish a level.. 
+Also, some secrets are intentionally hard to find. 
+
+Q. I've cleared out the whole level, but my monster kill score isn't 100%. 
+Where are they hiding?
+A. Some monsters hide inside secrets, or are released by them. You won't be 
+able to kill those monsters until you find their secrets. Also, some monsters 
+might  lurk underwater. Good fishing. 
+
+Q. Don't you worry that Quake teaches people that all problems can be solved 
+by the misuse of deadly force? 
+A. No. 
+
+Q. Did I really see two monsters fighting each other?
+A. Probably. Some monsters hate one another almost as much as they hate you. 
+You can use this to your advantage (exercise left up to the reader). 
+
+Q. How do I prevent motion sickness when watching Quake?
+A. If you're one of the unlucky sufferers from motion sickness in Quake, 
+we're sorry to say the answer seems to differs from person to person. Try 
+sitting closer to the screen, or further away. Dim the lights in your room, 
+or turn them up high. Adjust screen brightness up or down. Take a break from 
+Quake and rest your eyes every hour or so. One or more of these tricks, or a 
+combination, ought to work. 
+
+Q. Are you guys Satan-worshipers?
+A. No. 
+
+IX. Tech Support
+   Any of the information listed below could change. Check the id software Web
+Site, at www.idsoftware.com, for updates.
+
+A. Tech Support Options
+id Software does charge for technical support, but we strive to offer this 
+service at the lowest cost possible. Because volume on the support lines 
+dictates costs, we periodically adjust our rates for Voice Tech Support. 
+Check our web site for current pricing.
+
+Paying for Voice or Automated Support
+   1 -- You can get Voice Support using a major credit card for a one-time 
+   shot. The system asks for your credit card number and expiration date, then 
+   pre-authorizes your credit card for the tech support call. You will only be 
+   billed for the number of minutes actually used.
+
+   2 -- You can assign yourself a rechargeable PIN account. The system 
+   prompts you for your credit card information, and assigns you a PIN account
+   number. You can use the PIN to access Voice Support, Automated Support and 
+   the Game Hints Line. Once your account runs out, you can charge it up
+   again.
+
+   3 -- You may also charge up a PIN account using the number 
+   1 (900) call-2-id. Then call back at 1 (800) id-games, and use your
+   new PIN to receive all the support and hints you wish.
+
+Voice Support
+Telephone -- 1 (800) id-games
+   Lines Open from 12 noon to 10pm Central Time
+   7 Days a week ($1.75 per minute maximum as of this printing)
+   Closed some holidays
+Please have the following information handy.
+   1.  Game title and version number. (The version number can be found in the 
+   lower right-hand corner of the console.)
+   2.  Your operating system, processor, processor speed and amount of RAM.
+   3.  If you are having a sound, video or modem problem, we need to know the   
+   device brand name and model.
+
+Automated Support
+Telephone -- 1 (800) id-games 
+   Lines Open 24 hours a day, 365 days a year (366 in Leap year)
+   ($0.25 per minute)
+Please have pencil and paper handy
+
+E-mail Support
+   Just send your e-mail to support@idsoftware.com
+   We will respond within 48 hours after receiving your e-mail. When sending
+   e-mail, cut and paste the following into your e-mail message and fill
+   in the blanks --
+
+Date:  
+Name:  
+Phone number:  
+E-mail address:  (please include this, we redirect tons of mail)
+Game Title:  
+Version #:  
+Operating system (eg., DOS 6.0 or Windows 95):
+Computer type:  
+Processor type:  
+Processor speed:  
+Video card brand and model:  (only if video problem)
+Audio card brand and model:  (only if audio problem)
+Modem brand and model:  (only if modem problem)
+Network card brand and model:  (only if netgame problem)
+Network configuration (eg., NET.CFG file):  (only if netgame problem)
+Drivers, protocol stacks, and versions:  (eg., lsl v2.14, exp16odi
+v2.33, and ipxodi v3.01)  (only if netgame problem)
+If there were any error messages or fault information, report them
+here:
+Please state the problem you encountered:
+Please state how to reproduce the problem:
+
+Web Support
+   Found at www.idsoftware.com
+   Our web support pages provide the same information that's available via
+   Automated Support, except it's free!
+
+News Sites
+   For information, FAQ, or announcements, check out
+      rec.games.computer.quake.announce
+
+   For editing and hecking Quake-related files, check out
+      rec.games.computer.quake.editing
+
+   For general Quake discussion, check out
+      rec.games.computer.quake.misc
+
+Game Hints Line
+Telephone -- 1 (800) id-games or 1 (900) call-2-id
+   Lines Open 24 hours a day, 365 days a year (366 in Leap year)
+   ($0.85 per minute)
+
+B. In Europe
+   Our help lines in Europe are open 7:30am - 5:00pm GMT, Monday - Friday. 
+
+      English:  +44 01923 209145
+      German:   +44 (0)1923 209151
+      French:   +44 (0)1923 209148
+
+C. Problems
+   If you have an unfavorable experience using our services, please send
+   e-mail to support@idsoftware.com. Kindly include your full name,
+   address, phone number, and the problem encountered.
+
+X. LEVELS & DESIGNERS
+
+***************************************
+The Beginning
+start -- Welcome to Quake -- by John Romero
+***************************************
+Dimension of the Doomed (shareware episode)
+e1m1: Slipgate Complex -- by John Romero
+e1m2: Castle of the Damned -- by Tim Willits
+e1m3: The Necropolis -- by Tim Willits
+e1m4: The Grisly Grotto -- by Tim Willits
+e1m5: Gloom Keep -- by Tim Willits
+e1m6: The Door To Chthon -- by American McGee
+e1m7: The House of Chthon -- by American McGee
+***************************************
+Realm of Black Magic
+e2m1: The Installation -- by John Romero
+e2m2: Ogre Citadel -- by John Romero
+e2m3: Crypt of Decay -- by John Romero
+e2m4: The Ebon Fortress  -- by John Romero
+e2m5: The Wizard's Manse -- by John Romero
+e2m6: The Dismal Oubliette -- by John Romero
+***************************************
+Netherworld
+e3m1: Termination Central -- by John Romero
+e3m2: The Vaults of Zin -- by American McGee
+e3m3: The Tomb of Terror -- by American McGee
+e3m4: Satan's Dark Delight -- by American McGee
+e3m5: Wind Tunnels --by Tim Willits
+e3m6: Chambers of Torment -- by American McGee & Tim Willits
+***************************************
+The Elder World
+e4m1: The Sewage System -- by Tim Willits
+e4m2: The Tower of Despair --by Sandy Petersen
+e4m3: The Elder God Shrine --by Sandy Petersen
+e4m4: The Palace of Hate --by Sandy Petersen
+e4m5: Hell's Atrium --by Sandy Petersen
+e4m6: The Pain Maze --by Sandy Petersen
+e4m7: Azure Agony --by Sandy Petersen
+***************************************
+The End
+end: Shub-Niggurath's Pit --by John Romero
+***************************************
+The Deathmatch Arenas
+dm1: Place of Two Deaths --by Tim Willits
+dm2: Claustrophobopolis --by American McGee
+dm3: The Abandoned Base --by John Romero
+dm4: The Bad Place --by American McGee
+dm5: The Cistern --by Tim Willits
+dm6: The Dark Zone --by Tim Willits
+***************************************
+???
+Ziggurat Vertigo --by American McGee
+Underearth --by Tim Willits
+The Haunted Halls -- by American McGee
+The Nameless City -- by Sandy Petersen
+***************************************
+
+XI. Legal Boilerplate 
+   Quake (tm) (c) id Software, Inc. All rights reserved. All trademarks are
+   the property of their respective companies. For full information on the
+   legal issues of owning and using Quake, please refer to the files
+   LICINFO.TXT and ORDER.TXT.
+
+The program you've purchased was produced through the effort of many people.
+Don't make copies for others who have not paid for the right to the
+registered version of Quake. To report copyright violations to the Software
+Publishers Association, call 1 (800) 388-PIR8 or write:
+
+	Software Publishers Association
+	Suite 901
+	1101 Connecticut Avenue NW
+	Washington, DC  20036
+
+XII. MUSIC CREDITS
+
+Titles of Songs or Themes (C) 1996 TVT/Interscope Records.
+All Rights Reserved.
+Written by Trent Reznor (C) 1996 Leaving Hope/TVT Music.
+ASCAP All Rights Reserved.
+
+Note: music is ONLY available on CD. See your local software retailer
+or order Quake today at 1-800-idgames!
+
+XIII. Thanks
+
+id Software would like to give special thanks to:
+
+Sean Barrett
+Raymond Chen
+DJ Delorie
+Andy Glew
+Lance Hacking
+Chris Hecker
+Todd Laney
+Terje Mathisen
+Charles Sandmann
+Jon Vondrak
+Billy Zelsnack
+The GameTech crew
+Syntrillium Software for CoolEdit
--- /dev/null
+++ b/WinQuake/data/ORDER.TXT
@@ -1,0 +1,103 @@
+ORDERING INFO
+	To order the full version of Quake (or any other id Software 
+product) in North America, call our fulfillment center at 1-800-idgames
+(1-800-434-3627).  Except as noted by our operators, you can expect 
+Airborne Express afternoon delivery. The price for the full version 
+of Quake (available on PC CDROM only) is $45, plus $5 shipping, for a 
+total of $50. Our fulfillment center accepts Visa, Mastercard, and 
+American Express. You can also fax, mail, or email your order using 
+the attached forms. The fax number is (317) 361-3710 and the email 
+address is idsoftware@stream.com. To prepay and order with a check 
+by mail, send your check and the order form to:
+
+		id Software
+		P.O. Box 4500
+		Crawfordsville, IN  47933
+
+ To see an electronic catalog of our software, tshirts, hint books, and
+ other merchandise available, check out the Shopping Maul section of our
+ website at www.idsoftware.com.
+
+INTERNATIONAL ORDERS
+Quake is available worldwide as a full retail product. To find out 
+which local stores carry Quake and other id products, contact the 
+following international affiliates:
+
+Europe				Australia
+GT Interactive Software		Roadshow New Media
+1712 583791	(U.K.)		1 902 962000
+
+Taiwan				Singapore
+U.S. Summit Corporation		Summit Co. (Singapore) Pte. Ltd.
+706-0660			273-9988
+
+Malaysia			Honk Kong
+Summit Co. (Malaysia) Sdn Bhd	Tsun Tsun Trading Company
+757-2244			571-4231
+
+Thailand			Israel/Jordan/Lebanon/Egypt
+U.S. Summit Corp. (Overseas)	Mirage Mulimedia
+374-3956			972 3 510 5764
+
+If you are in a territory that cannot access 1(800)idgames, and you 
+wish to order our products directly, you must place your order in 
+writing to the fax, mail, or email addresses listed above under 
+ORDERING INFO.	
+
+International phone orders will NOT be accepted. Unfortunately, due 
+to international shipping costs, all international orders are sent 
+out via US Mail. This means we cannot guarantee timeliness of delivery 
+due to customs and other delays inherent to international shipping
+______________________________________________________________________
+ ORDER FORM --  USE THIS FORM TO FAX , MAIL OR EMAIL YOUR ORDER.
+
+id Software Order Center			Date ______________
+PO BOX  4500					Phone: 1800 id games
+Crawfordsville, IN  47933			Fax: (317) 361-3710
+						idsoftware@stream.com
+
+
+Product List and Prices in U.S. Currency:			(check items)
+
+Quake (CD ROM only)						$45	____
+The Ultimate DOOM (Mac version available � must specify) 	$25	____
+DOOM II (Mac version available � must specify)			$40	____	
+Master Levels for DOOM II (CD ROM only)				$25	____
+Final DOOM (CD ROM only)					$40	____
+DOOM Hint Book							$15	____
+Original DOOM Tshirt (S,M.L.XL)					$13	____
+The Ultimate DOOM Tshirt (XXL only)   				$13	____
+Final DOOM Tshirt						$13	____
+Heretic:Shadow of the Serpent Riders (CD ROM only)		$40	____
+Heretic Hint Book						$15	____
+Hexen:Beyond Heretic (Mac version available � must specify)	$40	____
+Hexen:Deathkings of the Dark Citadel (CD ROM only)		$25	____
+Hexen Hint Book							$15	____
+Hexen Tshirt (XXL only)						$13	____
+Wolfenstein 3D (PC CD only)					$20	____
+Commander Keen (3.5 disk only)					$15	____
+
+							Order total:   $______
+
+Name:						Age (optional):
+
+Form of payment (check, money order, or credit card):
+
+Credit card number:					Expiration Date:
+
+Exact mailing address:______________________________________
+			_______________________________________	
+			_______________________________________
+			_______________________________________
+
+Phone:				Fax:				Email:
+
+Shipping: US orders-$5.00 first product/$2.00 each additional 
+(allow 3-5 business days)
+
+International shipping for prepaid orders are via US Mail, and 
+we cannot guarantee the time it will take to arrive.
+
+*Prices subject to change
+
+
--- /dev/null
+++ b/WinQuake/data/README.TXT
@@ -1,0 +1,456 @@
+Welcome to Quake!
+
+This file details how to get Quake running on your system and what to do
+if you have problems.  We would like to thank Gandalf Technologies, Inc and
+MPath Interactive for the use of their technology.  We would also like to
+thank Trent Reznor and Nine Inch Nails for their tremendous contributions
+to Quake's entire audio portion.
+
+The NIN logo is a Registered Trademark licensed to Nothing Interactive, Inc.
+All Rights Reserved.
+
+Quake System Requirements
+-------------------------
+IBM PC and Compatibles
+Pentium processor or better
+VGA Compatible Display or better
+8MB RAM minimum, 16MB recommended (16 MB required for running under Win95)
+CD-ROM drive Required 
+MS-DOS 5.0 or better or Windows 95 (does NOT run under Windows NT)
+Hard Drive (30MB for Shareware, 80 MB for Registered)
+
+*** IMPORTANT!: Quake requires a floating point processor.
+Systems that do not have an FPU installed will not run Quake -- at all.
+
+*** IMPORTANT Video Adapter Note! ***
+On some ATI Mach32 cards, Quake can come up with a garbled video display.
+This is due to a problem with the card in which 320x200 mode isn't
+initialized correctly.  Workarounds include:
+
+1) If running from Windows, start Quake from an icon, or from a windowed
+(not fullscreen) MS-DOS prompt.  If Quake is already running and has
+the garbled screen, press Alt-Enter twice to switch to the desktop and
+back to fullscreen, and the screen will display properly.
+
+2) If running from DOS, either put the line
+
+vid_mode 1
+
+in id1\autoexec.cfg, or, typing blind, press tilde ('~') to bring down
+the console, type
+
+vid_mode 1<enter>
+
+and the screen will display properly.
+
+========================================================================
+Here are the text files included with the shareware release of Quake and
+what they are:
+
+README.TXT              This file
+TECHINFO.TXT            Technical information on Quake's subsystems and
+                        their advanced use.
+MANUAL.TXT              Text version of the printed game manual
+LICINFO.TXT             Info on the various license files included with Quake
+SLICNSE.TXT             Shareware Quake end-user license
+ORDER.TXT               How to order Quake
+HELP.TXT                How to get help with Quake
+
+Here are the text files included with the registered version of Quake and
+what they are:
+
+README.TXT              This file
+TECHINFO.TXT            Technical information on Quake's subsystems and
+                        their advanced use.
+MANUAL.TXT              Text version of the printed game manual
+LICINFO.TXT             Info on the various license files included with Quake
+RLICNSE.TXT             Registered Quake end-user license
+COMEXP.TXT              Commercial exploitation agreement
+ORDER.TXT               How to order Quake
+HELP.TXT                How to get help with Quake
+
+
+Running Quake
+-------------
+
+DOS:  To launch Quake from the DOS Prompt, go to the Quake directory and
+simply type "QUAKE" <ENTER>. (no quotes)
+
+Windows 95:  To launch Quake in single player mode, double click on the file
+QUAKE.EXE From Windows Explorer.  To run Quake in Multi-Player mode using
+the TCP/IP protocol, first check your network settings to ensure the
+protocol is installed, then double click on the Q95.BAT file to launch the
+game. In this version (v0.91) there is a minor bug that will cause the
+Q95.BAT file to exit the first time you run it, without running Quake.
+Merely double-click on that file again and it will work.
+
+Audio Setup
+-----------
+
+When using a Sound Card with Quake, there are a few setup steps which must
+be taken. First, the "BLASTER" environment variable setting must be in your
+autoexec.bat (or you can type it in manually from the MS-DOS command prompt).
+Running the Sound Blaster utility diagnose.exe will automatically configure
+your sound card and put this statement in your autoexec.bat file for you.
+A typical blaster setting looks like this (although yours may vary):
+
+SET BLASTER=A220 I5 D1 H5 P330 T6
+
+If you want to play the audio track from the CD-ROM while playing Quake,
+you must ensure that the audio cable from the CD-ROM is connected to the
+sound card.
+
+If you think your sound card is setup properly and it STILL doesn't work,
+check to make sure that your BLASTER environment variable contains the
+high DMA setting (H5 in the above example).
+
+If you don't get sound while trying to play the audio track, check to see
+if a small cable goes from the back of your CD-ROM player directly to your
+sound card.  If the CD-ROM audio cable is connected to your sound board (or
+the motherboard in some cases) and you STILL don't hear CD Audio coming from
+your speakers, make sure the MIXER program has the CD volume turned up.
+You will also need to run the CD-ROM driver MSCDEX.EXE. Here is an example
+of the files you should see (yours probably will vary) listed in your
+CONFIG.SYS and AUTOEXEC.BAT (explanation is in parentheses):
+
+CONFIG.SYS:
+
+DEVICE=C:\PROSCSI\CDROM.SYS /D:PROCD01 (CD-ROM driver)
+
+AUTOEXEC.BAT:
+
+SET BLASTER=A220 I5 D1 H5 P330 T6 (sound environment variable setting)
+C:\WINDOWS\COMMAND\MSCDEX.EXE  /D:PROCD01 /L:D (CD-ROM driver)
+
+===================================================
+UltraSound MAX and UltraSound PnP Support for Quake
+===================================================
+
+Before running Quake, make sure that your sound card works and your
+environment variables are set correctly.
+
+Other UltraSound Cards (ACE & Classic)
+--------------------------------------
+These drivers are not for the UltraSound ACE or UltraSound Classic
+sound cards. We have heard mixed reports that MegaEm or SBOS
+have a chance of working with the UltraSound Classic but there is a
+short sound F/X delay.
+
+UltraSound PnP and PnP Pro
+--------------------------
+You must make sure that you do NOT have IWSBOS or MegaEm loaded. 
+
+Setup
+-----
+Quake will automatically detect that the UltraSound Max or PnP
+are installed. It does this by looking at the SET INTERWAVE (PnP)
+and SET ULTRA16 (Max) environment variables.
+
+Quake will use the settings found on the SET ULTRASND/ULTRA16 (Max)
+and in the IW.INI (PnP) file to determine what port settings to use.
+
+Troubleshooting Windows 95 (DOS Box)
+------------------------------------
+We recommend that you restart your computer in MS-DOS Mode.  DOS Box 
+may or may not work, so use at your own risk.  
+
+CD Audio Input
+--------------
+If you have not already enabled CD audio output by default you will
+need to enable it. For the UltraSound MAX you can run "ULTRINIT -EC".
+For the UltraSound PnP you will need to enable the CD audio output
+in Win'95 and then restart your computer into MS-DOS.
+
+===================================================
+Mouse Setup
+-----------
+
+If you are going to use a mouse when playing Quake, you will need to load
+your mouse driver.  This should go in the AUTOEXEC.BAT file as well.  Here
+is an example:
+
+C:\LOGITECH\MOUSE\MOUSE.EXE (mouse driver)
+
+
+Booting Clean
+-------------
+
+If you are going to be running Quake with only 8 megabytes of RAM, it is best
+to boot clean .  You eliminate unwanted utilities or applications from taking
+up valuable memory, without having to alter your regular AUTOEXEC.BAT and
+CONFIG.SYS. Booting clean can be done in one of two ways. If you have
+MS-DOS version 6.xx, booting clean is as simple a pressing the shift key
+when you see the words "Starting MS-DOS". If you have MS-DOS ver 5.xx you
+will need to make a system disk.
+
+To make a boot disk, type the following from the MS-DOS command prompt:
+
+FORMAT A: /S
+
+1. Make sure that this is a disk you wish to erase.
+2. This disk absolutely HAS to be formatted in the A: drive.
+
+To use the system disk, place the disk in the A: drive and reset the
+computer.
+
+NOTE: If your sound card requires a driver to be loaded, or you will be
+using a mouse, or you will be using Quake's CD audio feature, the system
+disk will need to have a CONFIG.SYS and AUTOEXEC.BAT that load the
+appropriate drivers.
+
+Creating a Quake Shortcut
+
+As an alternative to making a Boot Disk, Windows 95 users can create a
+Quake Shortcut.  By double clicking onthis shortcut, Windows 95 will reboot
+in MS-DOS mode and install only the desired drivers, giving you the same
+results as using a Boot Disk.  To create a Quake Shortcut, do the following:
+
+1.  Using Explorer, right click and drag the file QUAKE.EXE, from the Quake
+    directory, to your desktop.  Windows 95 will make an MS-DOS Icon titled
+    "Shortcut to quake".
+2.  Right click on the new icon, and from the menu that pops up, choose
+    "Properties".  Then choose the "Program" tab at the top.
+3.  Now click on the "Advanced..." button near the bottom.  The "Advanced
+    Program Settings" window should appear.
+4.  Select the "MS-DOS mode" check box and the "Specify a new MS-DOS
+    configuration" option button.
+5.  Now simply fill in the "CONFIG.SYS for MS-DOS mode:" and "AUTOEXEC.BAT
+    for MS-DOS mode:" boxes with the same sound, CD-ROM and mouse settings as
+    mentioned above in the Boot Disks section.
+6.  Click on "OK" when you are finished.  If you wish, you can change your
+    Quake Shortcut Icon to something a little more exciting by clicking on
+    "Change Icon...".
+7.  To finish, click on "OK" again.
+    8.  You can rename your Quake Shortcut by right clicking on the shortcut
+    icon, choosing "Rename" and typing in the new name.
+
+
+======================================================
+==                  Known Problems                  ==
+======================================================
+
+Problem: Zombies sometime get stuck on the ground and connot get back up.
+(You can still hear them, but you cannot kill them. This bug makes it
+impossible to get 100% kills on whatever level it occurs on.)
+Solution: There is no workaround for this bug.
+
+Problem: It is sometimes possible for the player to get stuck in a room or
+in a wall.
+Solution: If you get stuck, use the 'kill' console command. It is a good
+idea to save your game often.
+
+Problem: View centering problems. Sometimes during a game, the view will not
+center properly.  The end result is the player view looking up torwards the
+ceiling while walking.
+Solution: Exit to the next level or use the 'kill' console command..
+
+
+======================================================
+==                 Troubleshooting                  ==
+======================================================
+
+If Quake fails to start up, or has problems not addressed elsewhere in the
+documentation, try the -safe command line switch, which disables a number
+of parts of Quake that can be problems if there are hardware or configuration
+problems.  The -safe command line switch is equivalent to -stdvid, -nosound,
+-nonet, and -nocdaudio together.  Those four switches do the following:
+
+-stdvid: disables VESA video modes.
+
+-nosound: disables sound card support.
+
+-nonet: disables network card support.
+
+-nocdaudio: disables CD audio support.
+
+If -safe makes the problem go away, try using each of the switches
+individually to isolate the area in which you're experiencing the problem,
+then either correct the configuration or hardware problem or play Quake with
+that functionality disabled.
+
+If you still have problems, try booting clean in conjunction with
+the -safe command line parameter.  For information on booting clean, refer
+to the "Booting Clean" section above.
+
+If you experience page faults while running Quarterdeck's QDPMI DPMI server,
+this is caused by a bug in QDPMI.  Workarounds:  Remove QDPMI from CONFIG.SYS,
+issue the command QDPMI OFF before running QUAKE, or get the update patch
+for QDPMI from Quarterdeck.  You may be running QDPMI without knowing it if
+you have QEMM installed, because it can be installed as part of the QEMM
+installation.
+
+
+Technical Support
+-----------------
+
+If you are having trouble installing or running Quake you can receive
+technical support by sending e-mailing to support@idsoftware.com.  You can
+also refer to our web page, www.idsoftware.com, or call 1-800-idgames.
+
+When sending support e-mail, cut and paste the following into your e-mail
+message and fill in the blanks:
+
+Date:  
+Name:  
+Phone number:  
+E-mail address:  (please include this, we redirect tons of mail)
+Game Title:  
+Version #:  
+Operating system (i.e., DOS 6.0 or Windows 95):
+Computer type:  
+BIOS date:
+BIOS version:
+Processor type:  
+Processor speed:  
+Do you program at school/work?
+Do you provide tech. support at school/work?
+Please state the problem you encountered:
+Please state how to reproduce the problem:
+
+If program crashed with nasty undecipherable techno-garbage, please
+look for the eight-digit hex number which comes after "eip="
+and write it down here:
+
+** NOTE:  If you are sending a bug report, PLEASE refer to the TECHINFO.TXT
+file for the correct form and procedures.
+
+
+======================================================
+==                 Version History                  ==
+======================================================
+v1.01 -- Bugs fixed
+------------------------------------------------------
+* Fixed modem code
+* Fixed fraglimit & timelimit
+* Added NOEXIT cvar (so no one can exit a level)
+------------------------------------------------------
+v1.00 -- Bugs fixed
+------------------------------------------------------
+* Gravis Ultrasound audio support (still has bugs)
+* More deathmatch start spots on E1M6 and END
+* Print server version and PROG CRC on connect
+* -dedicated starts start.map if nothing else specified
+* fixed lookspring function during net game
+* fixed rare crash during long running dedicated server
+------------------------------------------------------
+v0.94 -- Bugs fixed / Features added -- LIMITED BETA VERSION
+------------------------------------------------------
+* Totally rewritten menus
+* New lighting model with overbrighting
+* Parsed lowercase BLASTER parms
+* Better Sound Blaster shutdown code
+* Rewrote BLASTER initialization
+* Fixed DMA channel 0 bugs
+* Added SBPro 8 stereo setup
+* Fix delayed sound on 8 bit Sound Blasters
+* Fixed speed key affecting angle-turning from keyboard
+* Fixed "no such Alias frame" bugs
+* Fixed Zombie not getting up bug
+* Checked for very high joystick values, signalling a failed read
+* Unstuck jumping Fiends and Spawn
+* Fixed large BModels blinking out in complex areas
+* Fixed s_localsound with no sound started
+* Saved spawn parms in savegame
+* Fixed screenshot save location
+* Bind with no arguments no longer clears value
+* Allow console in intermission / finale
+* Fixed false gib messages
+* Full-screen TAB scoreboard in DeathMatch
+* Fixed "+playdemo <demo>" from command line
+* Trapped overflow in sizebuf messages
+* Moveup / movedown in water!
+* Fixed-up Talk command
+* Added unsupported crosshair option ("crosshair 1" from console)
+* Colored chat messages with notify sound
+* Fixed "connect during intermission" bug
+* Changelevel while demos running no longer crashes
+* Fixed changelevel with no map left up loading screen
+* Fixed long names entered from the console causing crash
+* Stopped demos changing while in the menus
+
+* Fixed modem initialization from menu
+* Fixed serial reliable stream getting stalled
+* Serial/modem code fixes
+	16550a lost transmit buffer empty interrupts
+	fixed sometimes processing interrupts from com1 when using com2
+	added com3/com4 support from menus
+	fixed first character of modem init not getting sent
+	saved serial/modem settings in config.cfg
+* Fixed name and colors not always sent to server at startup
+* Fixed "stopdemo" crashing the system when there wasn't a demo playing
+* Added server's TCP/IP and IPX addresses (if available) to status command
+
+* In 0.92, an additional check for a usable VESA video mode was added;
+the numpages field was verified to be greater than 0, and no mode was
+supported that had numpages set to 0 (which indicates that there's not
+enough video memory for that mode).  ATI's VESA driver, m64vbe,
+reports 0 for numpages, so VESA video modes that were available in 0.91
+were no longer available in 0.92.  This extra numpages check has
+been removed.
+
+-----------------------------------------------------------------------
+v0.93 -- Never officially released; internal testing only.
+-----------------------------------------------------------------------
+v0.92 -- Bugs fixed
+-----------------------------------------------------------------------
+Typing long strings in the hostname or modem init field in the menus caused
+crashes.
+
+Under Win95 IPX was detected but not functional, resulting in the game
+exiting to DOS.
+
+If -nosound, got "S_LocalSound: can't cache" on every keypress in the menu.
+
+When vid_nopageflip was set to 1 in VESA modes, going underwater resulted in
+only the upper left corner of the drawing area being updated.
+
+The single player scoreboard (tab) printed text incorrectly in all modes
+greater than 320 pixels wide.
+
+On network connections that dropped packets, the reliable message stream
+could get stopped up, resulting in frag counts and talk messages no longer
+being delivered, although game movement continued.
+
+The com port settings from the menu were getting saved & restored but
+not used.
+
+Direct serial connections did not work with slist.
+
+Quake now checks the vesa information for hardware incabable of page-flipping.
+
+Menu sound sometimes didn't play.
+
+Q95 (qlaunch.exe) frequently failed to execute on the first attempt.
+
+Q95 (quakeudp.dll) was running out of buffers when running a server.
+
+Teams were not being set according to pants colors.
+
+
+Joystick notes
+--------------
+Your joystick must be plugged in when Quake is launched.
+
+If you have a joystick plugged in, but don't want to use it in Quake
+(it slows the game down a few percent), or you have weird hardware that
+doesn't like being tested as a joystick add "-nojoy" to your Quake
+command line.
+
+You can turn off joystick reading during the game by typing "joystick 0" at
+the Quake command console.
+
+You MUST configure your buttons from the configure keys menu before they will
+work.  There is no default configuration. 
+
+If your joystick or interface card improperly sets the third or fourth
+joystick buttons, type "joybuttons 2" at the quake console or in your
+.CFG file.
+
+The "mlook" button command now lets the joystick as well as the mouse control
+pitch angles.
+
+The "sidestep" buttom command works on joysticks as with mice and keyboard
+movement.
+
+The "invert mouse up/down" menu option also inverts the joystick pitch
+direction.
--- /dev/null
+++ b/WinQuake/data/RLICNSE.TXT
@@ -1,0 +1,204 @@
+REGISTERED VERSION: QUAKE
+LIMITED USE SOFTWARE LICENSE AGREEMENT
+
+        This Limited Use Software License Agreement (the
+"Agreement") is a legal agreement between you, the end-user, and Id
+Software, Inc. ("ID").  By continuing the installation of this game
+program, by loading or running the game, or by placing or copying
+the game program onto your computer hard drive, you are agreeing to
+be bound by the terms of this Agreement.  If you do not agree to
+the terms of this Agreement, promptly return the game program and
+the accompanying items (including all written materials), along
+with your receipt to the place from where you obtained them for a
+full refund. 
+
+ID SOFTWARE LICENSE
+
+        1.      Grant of License.  ID grants to you the limited
+right to use one (1) copy of the enclosed or foregoing game program
+(the "Software") on a single computer.  You have no ownership or
+proprietary rights in or to the Software or the written materials
+accompanying the Software.  For purposes of this section, "use"
+means loading the Software into RAM, as well as installation on a
+hard disk or other storage device.  You may create a map editor,
+modify maps and make your own maps (collectively referenced as the
+"Permitted Derivative Works") for the Software.  Permitted
+Derivative Works may not be sold, whether by you or by any other
+person or entity, but you may exchange the Permitted Derivative
+Works at no charge amongst other end-users.  The Software, together
+with any archive copy thereof, shall be either returned to ID or
+destroyed when no longer used in accordance with this Agreement, or
+when the right to use the Software is terminated.  You agree that
+the Software will not be shipped, transferred or exported into any
+country in violation of the U.S. Export Administration Act (or any
+other law governing such matters) and that you will not utilize, in
+any other manner, the Software in violation of any applicable law. 
+
+        2.      Commercial Use is Prohibited.  Except as provided in
+paragraph 5. hereinbelow in regard to the Software, under no
+circumstances shall you, the end-user, be permitted, allowed or
+authorized to commercially exploit the Software, any data
+comprising the Software.  Neither you nor anyone at your direction
+shall do any of the following acts (any such acts shall be deemed
+void and a breach of this Agreement) with regard to the Software,
+or any portion thereof, such as a screen display or a screenshot: 
+
+        a.      Rent the Software;
+
+        b.      Sell the Software;
+
+        c.      Lease or lend the Software;
+
+        d.      Offer the Software on a pay-per-play basis;
+
+        e.      Distribute, by electronic means or otherwise, the
+                Software for money or any other consideration; or
+
+        f.      In any other manner and through any medium
+                whatsoever commercially exploit the Software or use
+                the Software for any commercial purpose. 
+        
+        3.      Additional Prohibited Uses.  Neither you nor anyone
+at your direction shall take the following action in regard to the
+Software, or any portion thereof, such as a screen display or a 
+screenshot: 
+
+        a.      Modify, disassemble, reverse engineer or decompile
+                the Software; 
+
+        b.      Translate the Software;
+
+        c.      Reproduce the Software;
+
+        d.      Publicly display the Software; 
+
+        e.      Prepare derivative works based upon the Software
+                (except Permitted Derivative Works); or
+
+        f.      Distribute, by electronic means or otherwise, the
+                Software. 
+
+	4.	Use of Other Material is Prohibited.  Use, in any manner, of 
+	the trademarks, such as Quake(tm) and the NIN(r) logo, logos, symbols, 
+	art work, images, screen displays or screenshots, sound effects, music, 
+	and other such material contained within, generated by or relating to 
+	the Software is prohibited.
+
+        5.      To Receive Permission to Commercially Exploit.  If
+you desire to commercially exploit the Software, you may execute
+the Commercial Exploitation License Agreement for QUAKE (the
+"License") contained within the QUAKE install package and forward
+the original License to Id Software at the address noted therein. 
+Please note that ID may refuse your request and not sign the
+License in ID's sole discretion. 
+
+        6.      Restrictions Apply to Third Parties.  The
+prohibitions and restrictions described herein apply to anyone in
+possession of the Software and/or Permitted Derivative Works. 
+
+        7.      Copyright.  The Software and all copyrights related
+thereto (including all characters and other images generated by the
+Software or depicted in the Software) is owned by ID and is protected
+by United States copyright laws and international treaty provisions.
+You must treat the Software like any other copyrighted material,
+except that you may either (a) make one copy of the Software solely
+for back-up or archival purposes, or (b) transfer the Software to a
+single hard disk provided you keep the original solely for back-up or
+archival purposes.  You may not otherwise reproduce, copy or disclose
+to others, in whole or in any part, the Software.  You may not copy
+the written materials accompanying the Software.  The same
+restrictions and prohibitions regarding your use of the Software as
+provided in this Agreement apply to your use of the written materials
+accompanying the Software.  The written materials are owned by ID and
+are protected by United States copyright laws and international
+treaties.  You agree to use your best efforts to see that any user of
+the Software licensed hereunder complies with this Agreement.
+
+        8.      Limited Warranty.  ID warrants that if properly
+installed and operated on a computer for which it is designed, the
+Software will perform substantially in accordance with the
+accompanying written materials for a period of ninety (90) days
+from the date of purchase of the Software.  ID's entire liability
+and your exclusive remedy shall be, at ID's option, either (a)
+return of the price paid or (b) repair or replacement of the
+Software that does not meet ID's Limited Warranty.  To make a
+warranty claim, return the Software to the point of purchase,
+accompanied by proof of purchase, your name, your address, and a
+statement of defect, or return the Software with the above
+information to ID.  This Limited Warranty is void if failure of the
+Software has resulted in whole or in part from accident, abuse,
+misapplication or violation of this Agreement.  Any replacement
+Software will be warranted for the remainder of the original
+warranty period or thirty (30) days from your receipt of the
+replacement software, whichever is longer.  This warranty allocates
+risks of product failure between Licensee and ID.  ID's product
+pricing reflects this allocation of risk and the limitations of
+liability contained in this warranty. 
+
+        9.      NO OTHER WARRANTIES.  ID DISCLAIMS ALL OTHER
+WARRANTIES, BOTH EXPRESS IMPLIED, INCLUDING BUT NOT LIMITED TO,
+IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR
+PURPOSE WITH RESPECT TO THE SOFTWARE AND THE ACCOMPANYING WRITTEN
+MATERIALS.  THIS LIMITED WARRANTY GIVES YOU SPECIFIC LEGAL RIGHTS. 
+YOU MAY HAVE OTHER RIGHTS WHICH VARY FROM JURISDICTION TO
+JURISDICTION.  ID DOES NOT WARRANT THAT THE OPERATION OF THE
+SOFTWARE WILL BE UNINTERRUPTED, ERROR FREE OR MEET LICENSEE'S
+SPECIFIC REQUIREMENTS.  THE WARRANTY SET FORTH ABOVE IS IN LIEU OF
+ALL OTHER EXPRESS WARRANTIES WHETHER ORAL OR WRITTEN.  THE AGENTS,
+EMPLOYEES, DISTRIBUTORS, AND DEALERS OF ID ARE NOT AUTHORIZED TO
+MAKE MODIFICATIONS TO THIS WARRANTY, OR ADDITIONAL WARRANTIES ON
+BEHALF OF ID.  ADDITIONAL STATEMENTS SUCH AS DEALER ADVERTISING OR
+PRESENTATIONS, WHETHER ORAL OR WRITTEN, DO NOT CONSTITUTE
+WARRANTIES BY ID AND SHOULD NOT BE RELIED UPON. 
+
+        10.     Exclusive Remedies.  You agree that your exclusive
+remedy against ID, its affiliates, contractors, suppliers, and
+agents for loss or damage caused by any defect or failure in the
+Software regardless of the form of action, whether in contract,
+tort, including negligence, strict liability or otherwise, shall be
+the return of the purchase price paid or replacement of the
+Software.  This Agreement shall be construed in accordance with and
+governed by the laws of the State of Texas. Copyright and other
+proprietary matters will be governed by United States laws and
+international treaties.  IN ANY CASE, ID SHALL NOT BE LIABLE FOR
+LOSS OF DATA, LOSS OF PROFITS, LOST SAVINGS, SPECIAL, INCIDENTAL,
+CONSEQUENTIAL, INDIRECT OR OTHER SIMILAR DAMAGES ARISING FROM
+BREACH OF WARRANTY, BREACH OF CONTRACT, NEGLIGENCE, OR OTHER LEGAL
+THEORY EVEN IF ID OR ITS AGENT HAS BEEN ADVISED OF THE POSSIBILITY
+OF SUCH DAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY.  Some
+jurisdictions do not allow the exclusion or limitation of
+incidental or consequential damages, so the above limitation or
+exclusion may not apply to you. 
+
+        11.     General Provisions.  Neither this Agreement nor any
+part or portion hereof shall be assigned, sublicensed or otherwise
+transferred by you.  Should any provision of this Agreement be held
+to be void, invalid, unenforceable or illegal by a court, the
+validity and enforceability of the other provisions shall not be
+affected thereby.  If any provision is determined to be
+unenforceable, you agree to a modification of such provision to
+provide for enforcement of the provision's intent, to the extent
+permitted by applicable law.  Failure of a party to enforce any
+provision of this Agreement shall not constitute or be construed as
+a waiver of such provision or of the right to enforce such
+provision.  If you fail to comply with any terms of this Agreement,
+YOUR LICENSE IS AUTOMATICALLY TERMINATED. 
+
+        YOU ACKNOWLEDGE THAT YOU HAVE READ THIS AGREEMENT, THAT YOU
+UNDERSTAND THIS AGREEMENT, AND UNDERSTAND THAT BY CONTINUING THE
+INSTALLATION OF THE SOFTWARE, BY LOADING OR RUNNING THE SOFTWARE, OR
+BY PLACING OR COPYING THE SOFTWARE ONTO YOUR COMPUTER HARD DRIVE, YOU
+AGREE TO BE BOUND BY THIS AGREEMENT'S TERMS AND CONDITIONS.  YOU
+FURTHER AGREE THAT, EXCEPT FOR WRITTEN SEPARATE AGREEMENTS BETWEEN ID
+AND YOU, THIS AGREEMENT IS A COMPLETE AND EXCLUSIVE STATEMENT OF THE
+RIGHTS AND LIABILITIES OF THE PARTIES.  THIS AGREEMENT SUPERSEDES ALL
+PRIOR ORAL AGREEMENTS, PROPOSALS OR UNDERSTANDINGS, AND ANY OTHER
+COMMUNICATIONS BETWEEN ID AND YOU RELATING TO THE SUBJECT MATTER OF
+THIS AGREEMENT. 
+
+June 21, 1996
+
+REGISTERED VERSION: QUAKE LIMITED USE SOFTWARE LICENSE AGREEMENT        Page 4
+(DWC:dw:3406.0024:DWC\doc:1164)
+
+
--- /dev/null
+++ b/WinQuake/data/SLICNSE.TXT
@@ -1,0 +1,175 @@
+SHAREWARE VERSION: QUAKE
+LIMITED USE SOFTWARE LICENSE AGREEMENT
+
+        This Limited Use Software License Agreement (the "Agreement") is a
+        legal agreement between you, the end-user, and id Software, Inc.
+        ("ID").  By continuing the installation of this game program, by
+        loading or running the game, or by placing or copying the game
+        program onto your computer hard drive, you are agreeing to be bound
+        by the terms of this Agreement.
+
+ID SOFTWARE LICENSE
+
+        1.      Grant of License.  ID grants to you the limited right to use
+        one (1) copy of the enclosed or foregoing Id Software game program
+        (the "Software"), which is the shareware version or episode one of
+        the game program.  For purposes of this section, "use" means loading
+        the Software into RAM, as well as installation on a hard disk or
+        other storage device. You agree that the Software will not be
+        shipped, transferred or exported into any country in violation of
+        the U.S. Export Administration Act (or any other law governing such
+        matters) and that you will not utilize, in any other manner, the
+        Software in violation of any applicable law.
+
+        2.      Commercial Use is Prohibited.  Under no circumstances shall
+        you, the end-user, be permitted, allowed or authorized to
+        commercially exploit the Software, or any portion thereof, such 
+	as a screen display or a screenshot.  Neither you nor anyone at your
+        direction shall do any of the following acts:
+
+        a.      Rent the Software;
+
+        b.      Sell the Software;
+
+        c.      Lease or lend the Software;
+
+        d.      Offer the Software on a pay-per-play basis;
+
+        e.      Distribute the Software for money or any other
+                consideration; or 
+
+        f.      In any other manner and through any medium
+                whatsoever commercially exploit the Software or use
+                the Software for any commercial purpose. 
+
+        3.      Additional Prohibited Uses.  Neither you, nor anyone at your
+        direction, shall take the following action in regard to the
+        Software, or any portion thereof, such as a screen display or 
+	a screenshot:
+
+        a.      Modify, disassemble, reverse engineer or decompile
+                the Software; 
+
+        b.      Translate the Software;
+
+        c.      Reproduce the Software;
+
+        d.      Publicly display the Software; or
+
+        e.      Prepare derivative works based upon the Software.
+
+	4.	Use of Other Material is Prohibited.  Use, in any manner, of 
+	the trademarks, such as Quake(tm) and the NIN(r) logo, logos, symbols, 
+	art work, images, screen displays or screenshots, sound effects, music, 
+	and other such material contained within, generated by or relating to 
+	the Software is prohibited.
+
+	5.      Restrictions Apply to Third Parties.  The prohibitions and
+        restrictions described herein apply to anyone in possession of 
+	the Software.
+
+        6.      Permitted Distribution. So long as this Agreement
+        accompanies the Software at all times, ID grants to Providers the
+        limited right to distribute, free of charge, except normal access
+        fees, and by electronic means only, the Software; provided, however,
+        the Software must be so electronically distributed only in a
+        compressed format. The term "Providers," as used in the foregoing
+        sentence, shall mean persons whose business it is to provide
+        services on the Internet, on commercial online networks, or on the
+        BBS. Anyone who receives the Software from a Provider shall be
+        limited to all the terms and conditions of this Agreement. Further,
+        ID grants to you, the end-user, the limited right to distribute,
+        free of charge only, the Software as a whole.
+
+        7.      Copyright. The Software is owned by ID and is protected by
+        United States copyright laws and international treaty provisions.
+        You must treat the Software like any other copyrighted material,
+        except that you may make copies of the Software to give to other
+        persons. You may not charge or receive any consideration from any
+        other person for the receipt or use of the Software. You agree to
+        use your best efforts to see that any user of the Software licensed
+        hereunder complies with this Agreement.
+
+        8.      Limited Warranty. ID warrants that if properly installed and
+        operated on a computer for which it is designed, the Software will
+        perform substantially in accordance with its designed purpose for a
+        period of ninety (90) days from the date the Software is first
+        obtained by an end-user. ID's entire liability and your exclusive
+        remedy shall be, at ID's option, either (a) return of the retail
+        price paid, if any, or (b) repair or replacement of the Software
+        that does not meet ID's Limited Warranty. To make a warranty claim,
+        return the Software to the point of purchase, accompanied by proof
+        of purchase, your name, your address, and a statement of defect, or
+        return the Software with the above information to ID.  This Limited
+        Warranty is void if failure of the Software has resulted in whole
+        or in part from accident, abuse, misapplication or violation of this
+        Agreement. Any replacement Software will be warranted for the
+        remainder of the original warranty period or thirty (30) days,
+        whichever is longer. This warranty allocates risks of product
+        failure between Licensee and ID. ID's product pricing reflects this
+        allocation of risk and the limitations of liability contained in
+        this warranty.
+
+        9.      NO OTHER WARRANTIES. ID DISCLAIMS ALL OTHER  WARRANTIES,
+        EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO, IMPLIED
+        WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A pARTICULAR PURPOSE
+        WITH RESPECT TO THE SOFTWARE AND THE ACCOMPANYING WRITTEN MATERIALS,
+        IF ANY. THIS LIMITED WARRANTY GIVES YOU SPECIFIC LEGAL RIGHTS. YOU
+        MAY HAVE OTHERS WHICH VARY FROM JURISDICTION TO JURISDICTION. ID
+        DOES NOT WARRANT THAT THE OPERATION OF THE SOFTWARE WILL BE
+        UNINTERRUPTED, ERROR FREE OR MEET LICENSEE'S SPECIFIC REQUIREMENTS.
+        THE WARRANTY SET FORTH ABOVE IS IN LIEU OF ALL OTHER EXPRESS
+        WARRANTIES WHETHER ORAL OR WRITTEN. THE AGENTS, EMPLOYEES,
+        DISTRIBUTORS, AND DEALERS OF ID ARE NOT AUTHORIZED TO MAKE
+        MODIFICATIONS TO THIS WARRANTY, OR ADDITIONAL WARRANTIES ON BEHALF
+        OF ID. ADDITIONAL STATEMENTS SUCH AS DEALER ADVERTISING OR
+        PRESENTATIONS, WHETHER ORAL OR WRITTEN, DO NOT CONSTITUTE WARRANTIES
+        BY ID AND SHOULD NOT BE RELIED UPON.
+
+        10.      Exclusive Remedies. You agree that your exclusive remedy
+        against ID, its affiliates, contractors, suppliers, and agents for
+        loss or damage caused by any defect or failure in the Software
+        regardless of the form of action, whether in contract,tort,
+        including negligence, strict liability or otherwise, shall be the
+        return of the retail purchase price paid, if any, or replacement of
+        the Software. This Agreement shall be construed in accordance with
+        and governed by the laws of the State of Texas. Copyright and other
+        proprietary matters will be governed by United States laws and
+        international treaties. IN ANY CASE, ID SHALL NOT BE LIABLE FOR LOSS
+        OF DATA, LOSS OF PROFITS, LOST SAVINGS, SPECIAL, INCIDENTAL,
+        CONSEQUENTIAL, INDIRECT OR OTHER SIMILAR DAMAGES ARISING FROM BREACH
+        OF WARRANTY, BREACH OF CONTRACT, NEGLIGENCE, OR OTHER LEGAL THEORY
+        EVEN IF ID OR ITS AGENT HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+        DAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY. Some jurisdictions do
+        not allow the exclusion or limitation of incidental or consequential
+        damages, so the above limitation or exclusion may not apply to you.
+
+        11.     General Provisions. Neither this Agreement nor any part or
+        portion hereof shall be assigned or sublicensed, except as described
+        herein. Should any provision of this Agreement be held to be void,
+        invalid, unenforceable or illegal by a court, the validity and
+        enforceability of the other provisions shall not be affected thereby. 
+	If any provision is determined to be unenforceable, you agree to a 
+	modification of such provision to provide for enforcement of the 
+	provision's intent, to the extent permitted by applicable law.  Failure 
+	of a party to enforce any provision of this Agreement shall not 
+	constitute or be construed as a waiver of such provision or of the 
+	right to enforce such provision. If you fail to comply with any terms 
+	of this Agreement, YOUR LICENSE IS AUTOMATICALLY TERMINATED.
+
+        YOU ACKNOWLEDGE THAT YOU HAVE READ THIS AGREEMENT, YOU UNDERSTAND
+        THIS AGREEMENT, AND UNDERSTAND THAT BY CONTINUING THE INSTALLATION
+        OF THE SOFTWARE, BY LOADING OR RUNNING THE SOFTWARE, OR BY PLACING
+        OR COPYING THE SOFTWARE ONTO YOUR COMPUTER HARD DRIVE, YOU AGREE TO
+        BE BOUND BY THIS AGREEMENT'S TERMS AND CONDITIONS. YOU FURTHER
+        AGREE THAT, EXCEPT FOR WRITTEN SEPARATE AGREEMENTS BETWEEN ID AND
+        YOU, THIS AGREEMENT IS A COMPLETE AND EXCLUSIVE STATEMENT OF THE
+        RIGHTS AND LIABILITIES OF THE PARTIES. THIS AGREEMENT SUPERSEDES
+        ALL PRIOR ORAL AGREEMENTS, PROPOSALS OR UNDERSTANDINGS, AND ANY
+        OTHER COMMUNICATIONS BETWEEN ID AND YOU RELATING TO THE SUBJECT
+        MATTER OF THIS AGREEMENT.
+
+June 21, 1996
+
+SHAREWARE VERSION: QUAKE LIMITED USE SOFTWARE LICENSE AGREEMENT
+(DWC:dw:3406.0024:DWC\doc:1163)
--- /dev/null
+++ b/WinQuake/data/TECHINFO.TXT
@@ -1,0 +1,1901 @@
+Welcome to the Quake Technical Information file!
+
+TABLE OF CONTENTS
+-----------------
+Introduction to the Console..............
+Video Subsystem Documentation............
+Sound Subsystem Documentation............
+CD Audio Subsystem Documentation.........
+Network Subsystem Documentation..........
+Modem Strings............................
+Win95 Documentation......................
+Key Binding and Aliases..................
+Quake Keys and Common Commands...........
+Making a Config File.....................
+Demos....................................
+Reporting Quake Bugs.....................
+
+
+==========================================
+==     Introduction to the Console      ==
+==========================================
+
+Throughout this document, examples of commands are given, all of which
+are typed in at the console. To bring up the console, press the tilde ('~')
+key or press ESC to bring up the menu, select Options, and select Console...
+from the options menu. To exit the console, press ESC.
+
+The console provides a way to change console variables and also accepts
+commands that change game settings such as movement keys, video mode, as
+well as providing an interface for key binding and command aliasing (more
+on that later).
+
+The console also has a command history with which you can browse through
+previous commands. Use the up and down arrows to navigate through the
+command history and press <enter> to re-issue a command.
+
+Partially typing a command and then pressing the TAB key will complete the
+currently typed text with the first matching console variable or command.
+(Yes, this is a good way to look for console commands.)
+
+To review previous actions by page, use the PGUP and PGDN keys.
+
+
+==========================================
+==    Video Subsystem Documentation     ==
+==========================================
+
+The Video Modes menu
+--------------------
+
+Video modes can most easily be selected from the the Video Modes menu, which
+is brought up by selecting the Video Options choice in the Options menu.
+All the resolutions that Quake can support on the current computer are
+displayed.
+
+Please note that higher-resolution modes require correspondingly more
+system memory in order for Quake to run, and that some high-resolution
+modes may not be available when running Quake on 8 Mb machines.  Such
+modes are not listed in the Video Modes menu.  Please do not report
+video modes that do not appear in the Video Modes menu as bugs; either
+those modes are not supported by your video adapter, or there is not
+enough system memory for Quake to support those modes.
+
+The video modes listed in the Video Modes menu can be tested, set, and made
+the default mode for Quake from the Video menu, as follows:
+
+* The arrow keys can be used to move the blinking indicator to any of the
+modes listed in the Video menu.
+
+* Pressing the 'T' key tests the mode the blinking indicator points to, by
+setting the mode, leaving it set for 5 seconds, and returning to the previous
+mode.  This lets you verify that your computer does in fact support that
+mode.  We highly recommend that you always test modes with 'T' before setting
+them
permanently by pressing the Enter key, in case some sort of hardware or
+software glitch causes a mode to function incorrectly and produce a garbled
+screen.  It is unlikely but possible that testing or setting a mode will
+cause your computer to hang or crash; if this happens, there is a serious
+hardware or software bug, and you should not attempt to select that mode
+again.
+
+* Pressing the Enter key sets the mode the blinking indicator points to,
+leaving it set so Quake will then run in that mode.  We suggest that you
+test a mode by pressing the 'T' key before setting it by pressing the Enter
+key.  Note that a selection made with the Enter key remains in effect only
+until Quake is exited (or a new mode is set).  You must explictly make a mode
+the default mode by pressing the 'D' key in order to automatically set that
+mode when you start Quake up in the future.
+
+* Pressing the 'D' key makes the current mode the default mode that Quake
+starts up with.  Note that the current mode is the mode that's displayed in
+white in the mode list, not necessarily the mode that the blinking indicator
+points to.  The current default mode is listed in the description of the 'D'
+key at the bottom of the Video Modes menu.
+
+* Pressing Esc exits the Video Modes menu.
+
+Please see "Bug Reporting," below, for information on how to report any
+problems you encounter.
+
+
+Video modes from the console:  Quick start
+------------------------------------------
+
+More comprehensive but more complex video control is available through the
+Quake console.  This section describes the commands necessary to perform
+basic mode setting through the console (this is similar to what can be
+accomplished through the Video Modes menu), and following sections describe
+console video control in detail.
+
+To see all the video modes that are available, bring up the console (either
+press tilde ('~'), or press Esc to bring up the menu, select Options, and
+select Console... from the Options menu).
+
+From the console, type vid_describemodes<enter> to see all available modes.
+Type vid_mode <mode #> to set a mode, where <mode #> is the mode number
+listed for the desired mode by vid_describemodes.  Higher-resolution modes
+generally require more extra system memory in order to run, and many are
+not available in 8 Mb systems; modes that are supported by the video
+adapter but are currently unavailable due to system  memory limitations
+will still show up in
the mode list from vid_describemodes, but will
+have "**" in place of a mode number.  (Such modes will not show up at
+all in the Video Modes menu.)  If you try to set a mode for which
+there is insufficient system memory, you will receive a message to that
+effect, and the video mode will remain unchanged.
+
+
+More detail
+-----------
+
+This version of Quake supports software drawing in a variety of
+video modes.  It does not support any 3-D hardware accelerators.
+Video modes that are built into Quake are:
+
+320x200, 360x200, 320x240, 360x240, 320x350, 360x350, 320x400,
+360x400, 320x480, 360x480
+
+However, the higher-resolution modes on this list require additional
+memory, and may not be available in 8 Mb systems.
+
+In addition, all VESA 2.0 256-color linear framebuffer modes
+supported by the video adapter are supported.  Further information
+about VESA 2.0 is provided below.
+
+
+Video mode reporting and selection
+----------------------------------
+
+Quake assigns each available video mode a mode number, which can
+then be used to query information about the mode or to select the
+mode.  The first 11 mode numbers are always as follows:
+
+0:  320x200
+1:  320x200
+2:  360x200
+3:  320x240
+4:  360x240
+5:  320x350
+6:  360x350
+7:  320x400
+8:  360x400
+9:  320x480
+10: 360x480
+
+You will notice that modes 0 and 1 are both 320x200; mode 1 is a
+Mode X-style version, which may someday allow support of page
+flipping for cleaner graphics, but right now it's just slower with
+no advantages, so use mode 0 for 320x200 resolution.  Modes 2-10
+are all higher resolution than mode 0, and look very nice, but are
+also all slower than mode 0.  Mode 0 is the fastest of the 11
+built-in modes.
+
+In addition to the built-in modes, Quake checks for the presence
+of a VESA version 2.0 driver.  If such a driver is detected, the
+driver is queried for all 8-bit-per-pixel linear framebuffer (LFB)
+modes that are supported; also, if no LFB 320x200 mode is available,
+a banked 320x200 VESA mode is queried for.  All such modes are added
+to the mode list starting at mode 11.  The available modes will vary
+depending on adapter, graphics chipset, amount of video memory, and VESA
+2.0
 driver.  The higher the resolution, the lower the performance, and
+the
higher-resolution modes will often be too slow for good gameplay
+on most machines.  (Also, higher-resolution modes often need more memory
+than is available in an 8 Mb system.)  The screen can be sized down to
+improve performance in higher-resolution modes, but then of course the
+effective resolution of Quake is reduced.
+
+At the same resolution, VESA LFB modes are often faster than the non-VESA
+modes 0-10, because adapters often have faster memory access in LFB modes.
+
+If a given VESA mode can support page flipping, then it defaults to page-
+flipped operation.  A VESA mode can be forced to non-page-flipped operation
+by setting the vid_nopageflip console variable to 1, then setting the mode
+
(note that vid_nopageflip takes operation on the next, not the current, mode
+set, and note that it then stays in effect permanently, even when Quake is
+exited and restarted, unless it is manually set back to 0).  If there is not
+enough memory for two pages in a VESA mode, or if the
+adapter doesn't support page flipping, then the mode will automatically
+be non-page-flipped.  Page flipping can have higher visual quality, but may
+be either faster or slower, depending on the graphics adapter and other
+hardware.  (See the discussion of the Pentium Pro, below, for a
+discussion of why page flipping can be faster but is sometimes much slower
+on that processor.)  Page-flipped modes use less system memory than non-
+page-flipped modes.
+
+Quake's VESA support, including VESA driver detection, can be disabled by
+using the -stdvid command-line switch, and can also be disabled, along with
+sound, network, and other hardware support, by the -safe command-line switch.
+
+The maximum resolution supported by Quake is 1280x1024.  Modes with higher
+resolutions will not be reported by vid_describemodes, and cannot be set.
+
+There is no support for any 3-D accelerator boards in this version of Quake.
+Coming soon.
+
+Quake always starts up in mode 0, and modes 0-10 are always available, given
+enough system memory.
+
+
+A note on modes reported in the Video Modes menu
+------------------------------------------------
+
+The vid_describemodes console command lists all modes with
+resolution less than or equal to 1280x1024 that are
+supported by the video adapter, although modes for which there
+is not enough system memory have "**" for the mode number.  VGA,
+Mode X-style, and VESA 2.0 modes are listed separately, so a
+single resolution can be listed as many as three times, once for
+each hardware mode that supports it.  For example, mode 0 is
+VGA mode 0x13, which supports 320x200 resolution, and mode 1 is
+320x200 Mode X-style mode.  Quake looks identical in both
+modes, although it usually runs faster in mode 0.
+
+The Video Modes menu is much simpler.  Only modes with resolution
+less than or equal to 1280x1024 that are both supported by the
+hardware and for which there is sufficient system memory are
+listed.  Further, a given resolution is listed only once.  If a
+given resolution is available in multiple hardware modes, then
+selecting that resolution will select the appropriate hardware mode
+as follows:
+
+If the mode is 320x200, then VGA mode 0x13 is selected, and
+equivalent Mode X and VESA modes are ignored;
+
+Otherwise, the VESA version of the mode is used.
+
+You can always see what video mode is selected from the console by typing
+the command:
+
+vid_mode<enter>
+
+command.
+
+None of this has any effect on selecting modes through the
+console, where all the different versions of each mode are
+listed, and the desired version can be selected by using the
+appropriate mode number.
+
+
+How to get VESA 2.0 support
+---------------------------
+
+Some video adapters have VESA 2.0 support in ROM.  Other video
+adapters come with loadable VESA 2.0 TSRs.  In the absence of either
+of these, UniVBE, a shareware product from SciTech, provides VESA 2.0
+support for most video adapters.  The latest version of UniVBE can be
+obtained from the following locations:
+
+www: http://www.scitechsoft.com
+ftp: ftp.scitechsoft.com
+CIS: GO SCITECH
+AOL: Keyword SciTech
+
+SciTech can be contacted at:
+
+email: sales@scitechsoft.com
+
+SciTech Software
+5 Governors Lane, Suite D
+Chico, CA
+95926-1989
+
+The current version at this writing is UniVBE 5.2.  This version
+supports many more adapters than previous versions, and adds
+a number of useful low- and medium-resolution modes, such as 400x300
+and 512x384.
+
+
+Video-related commands
+----------------------
+
+vid_describecurrentmode
+   lists the description for the current video mode.
+
+vid_describemode <mode #>
+   lists the description for the specified video mode, where <mode #> is as
+   reported by vid_describemodes.
+
+vid_describemodes
+   lists descriptions for all available video modes.
+
+vid_mode <mode #>
+   sets the display to the specified mode, where <mode #> is as reported by
+   vid_describemodes.
+
+vid_nopageflip <1|0>
+   when set to 1, VESA mode sets will always select non-page-flipped
+   operation.  When set to 0, VESA mode sets will select page-flipped
+   operation whenever possible.  All non-VESA modes are always
+   non-page-flipped.  The setting of vid_nopageflip is remembered
+   when Quake is exited (by being saved in config.cfg), and is reloaded
+   when Quake is restarted, so once vid_nopageflip is set to 1, all
+   VESA modes set in all Quake sessions after that point be will non-page-
+   flipped until vid_nopageflip is set to 0.  Note that setting this
+   variable doesn't affect whether the current video mode is page-flipped,
+   but rather whether page-flipping can be used by future mode sets.
+
+vid_nummodes
+   reports the total number of modes available.
+
+vid_testmode <mode #>
+   tries to switch Quake to the specified mode, then returns to the current
+   mode after 5 seconds.  This allows you to try an untested mode without
+   ending up with a black screen if, for example, the monitor can't display
+   the mode properly.  There may still be instances in which, due to VESA
+   driver or hardware bugs, the machine will hang in certain modes;
+   vid_testmode can't recover from these situations, but it can recover
+   from a blank or scrambled screen.
+
+vid_wait <wait type>
+  sets the type of waiting that the video adapter should do, as follows:
+  0: no waiting
+  1: wait for vertical sync active
+  2: wait for display enable active
+
+The default state of vid_wait depends on the video mode selected.
+(_vid_wait_override can force vid_wait to 1, wait for vertical
+sync; see the description of _vid_wait_override below.)
+In built-in modes 0-10, the default is always 0, no waiting.  You
+can set vid_wait to 1 (wait for vertical sync) to eliminate shear
+and tearing in these modes (so partially-completed frames are never
+drawn, resulting in a rock-solid image).  However, waiting for
+vertical sync can result in substantial performance loss.
+
+In VESA modes, if the adapter is VGA compatible and there's enough
+memory for three video pages, then triple-buffering is enabled and
+vid_wait is set to 2, wait for display enable.  There is little
+performance loss to this sort of waiting.  If the adapter is not
+VGA compatible, or if there's only enough memory for double-buffering,
+then vid_wait is set to 1 (wait for vertical sync).  This can cause
+significant loss of performance, but some sort of wait is generally
+necessary to avoid occasional glitching of the screen when
+page-flipping; we always choose the lowest-cost wait option that
+seems to be safe to use.  If there's only enough memory for one
+page, or if vid_nopageflip 1 is in effect, then vid_wait is set to 0
+(no wait).  As with modes 0-10, vid_wait 1 can be used to eliminate
+shear, but at a performance cost.
+
+We have encountered problems with a few adapters in VESA modes when
+vid_wait is set to 2 (wait for display enable).  Apparently some adapters
+just toggle display enable all the time, rather than only when pixels
+are being sent to the screen; this can cause occasional glitches in
+which the screen image jumps for one frame.  You can fix this by
+setting vid_wait to 1 (wait for vertical sync).  We would have made
+vid_wait 1 the default, but it's slower, and vid_wait 2 works on most
+machines.
+
+The default setting for vid_wait can be changed from the console
+at any time.  If you are in a VESA mode that waits for vertical
+sync and want to turn it off to get a speed-up, you can do so.
+However, changing a vid_wait 1 default in a VESA mode may result
+in problems.  If vid_wait defaults to 1 (wait for vertical sync)
+in a mode, and you force it to 2 (wait for display enable), the
+machine may hang, because some VGA-incompatible adapters, such as
+some ATI Mach64s, don't support the display enable status.  If you
+force vid_wait to 0 (no wait), then the screen may glitch periodically
+if the page flips at a time that results in a bad flip address,
+although some adapters work fine with no wait at all.
+
+If you force a new setting for vid_wait and encounter problems, DO
+NOT send us a bug report!
+
+_vid_wait_override <1|0>
+	can be used to force wait for vertical sync in all modes.  When
+    _vid_wait_override is set to 0, the type of waiting, if any, for
+    each video mode that's set thereafter is automatically set to
+    what appears to be the fastest safe state.  However, it is
+    possible in some cases that automatic setting may result in some
+	screen glitching, and it is also true that shear can be
+    eliminated by waiting for vertical sync (although at a cost in
+	performance), so it may be desirable in some cases to override
+    the automatic wait selection and always wait for vertical sync.
+    This can be done by setting _vid_wait_override to 1.  Once set,
+    this remains in effect through all succeeding mode sets, even
+    when Quake is exited and re-entered; the only way to keep Quake
+    from waiting for vertical sync once _vid_wait_override is set to
+    1 is to set _vid_wait_override to 0.  Note that changing
+    _vid_wait_override doesn't affect the current mode, but rather
+    takes effect on the next mode set.  _vid_wait_override is initially
+    set to 0.
+
+_vid_default_mode <mode #>
+    can be used to force Quake to start up in a particular mode.
+    The easiest way to select a default mode is by pressing the
+    'D' key in the Video Modes menu, but you can alternatively
+    use _vid_default_mode to specify the mode in which you want
+    Quake to start up in future Quake sessions.  _vid_default_mode
+    is initially set to 0.
+
+
+Higher-quality perspective texture mapping
+------------------------------------------
+
+For maximum speed, perspective correction is performed only every 16
+pixels.  This is normally fine, but it is possible to see texture ripples
+in surfaces that are viewed at sharp angles.  For more precise texture
+mapping, set the console variable d_subdiv16 to 0.  Doing this will result
+in somewhat slower performance, however, and the difference in visual
+quality will not normally be noticeable.
+
+
+Known video problems and workarounds
+------------------------------------
+
+If you think you've encountered a bug, see "Bug Reporting," below.
+As a general rule, go back to mode 0 if you have problems; mode 0
+should work properly in all cases.
+
+On some ATI Mach64 adapters, the palette is sometimes too dark in
+some VESA modes, and is tinted oddly (too red, for example) in other
+modes.  The workaround is to use different modes, or modes 0-10.
+
+In modes 0-10, shear and tearing can occur as partially finished
+frames are displayed.  Workaround:  set vid_wait to 1 (wait for
+vertical sync); this can result in a substantial performance loss,
+however.  An alternative is to use a page-flipped VESA mode.
+
+In page-flipped VESA modes, occasional glitched frames may occur with some
+VESA driver-hardware combinations.  Workaround:  set vid_wait to 1 (wait
+for vertical sync) (you can set _vid_wait_override to 1 to make waiting
+for vertical sync permanent for future Quake sessions), or use a different
+mode.
+
+The VESA video drivers that come with some video adapters don't
+support low-resolution modes such as 320x200; often,
+nothing lower than 640x400 is supported.  For example,
+this is the case with some ATI adapters.  There's nothing
+Quake can do to provide low-resolution VESA modes in these
+cases, because Quake simply supports whatever modes the VESA
+driver chooses to report as supported.  Unfortunately, 640x400
+is too high a resolution for really good performance unless you
+have a very fast Pentium or a Pentium Pro, so on machines with
+this sort of adapter, the VESA modes aren't very usable.
+Workaround:  Use UniVBE 5.2, which supports low-resolution modes
+on a wide variety of adapters.  Note that a few adapters simply can't
+support low-resolution modes, in which case you'll have to stick with
+the low-resolution VGA and Mode X modes that are built into Quake,
+which run fine but may be somewhat slower than VESA modes.
+
+A few video adapters are almost but not fully VGA compatible, because
+they don't support some unusual VGA video modes.  In particular, a few
+adapters don't support the 360-wide Mode X-style video modes that are
+build into Quake (modes 2, 4, 6, 8, and 10), and display garbage in those
+modes.  Workaround:  use different modes, such as 0, 3, 5, 7, 9, or any
+VESA modes that are available.
+
+Under Win 95, the palette occasionally gets messed up when switching from
+Quake to the desktop and back again.  You can restore the palette by
+bringing down the console (either press tilde ('~'), or press Esc to bring
+up the menu, select Options, and select Console... from the Options menu),
+and typing bf and pressing the enter key, to generate a background flash,
+which sets the palette.  Press Esc to exit the console.  Alternatively,
+setting the screen brightness, either from the Options menu or via the
+gamma console variable, sets the palette.
+
+Under Win 95, if the system key (the key with the Win 95 flag on it) is
+pressed while Quake is running fullscreen in a VESA mode, Win 95 may be
+unable to switch back from the desktop to Quake, in which case it will
+notify you of this, then terminate the Quake session.  This is a quirk
+of Win 95, and normally there is no workaround other than not to press
+that key or not to use VESA modes.  (Some people go so far as to remove
+the system key from their keyboard.)  However, you can
+disable the system key for Quake with the following utility:
+
+http://www.microsoft.com/windows/download/doswinky.exe
+
+Switching away from Quake with Alt-Enter, Ctrl-Esc, Alt-Tab, or
+Alt-Spacebar all work fine (except that if you disable the system key
+with doswinky.exe, Ctrl-Esc will also be disabled).
+
+
+Performance
+-----------
+
+Quake's graphics should be adequately fast in mode 0 (320x200) on all
+Pentium-class machines. If you feel Quake is running slowly, set the
+showturtle console variable to 1; you will then see a turtle icon
+appear in the upper left corner of the screen if the frame rate drops
+below 10 frame/second.  If you are getting the turtle, you are probably
+not getting great gameplay.  Performance can be improved in several ways:
+
+* size down the screen with the minus key
+
+* select a lower-resolution mode, if possible
+
+* use a VESA mode
+
+* if you're using a VESA mode and vid_wait is set to 1 (wait for
+vertical sync) by default (you can check by typing vid_wait<enter>
+in the console), you can try setting vid_wait to 0 or 2, as detailed
+in the discussion of the vid_wait command above.  Be aware that
+risks of screen glitching or hung machines are associated with
+overriding a default vid_wait 1 setting in VESA modes.
+
+To see how exactly fast Quake is running, bring up the console and type
+
+host_speeds 1<enter>
+
+You will see a display at the top indicating total frame time in
+milliseconds, and also server, graphics, and sound frame time in
+milliseconds.  (Note, though, that unless you also do
+
+snd_noextraupdate 1<enter>
+
+sound time will actually show up as graphics time.  However,
+snd_noextraupdate 1 can cause sound to get choppy, so it's not
+generally recommended.)
+
+Lower numbers are better.
+
+Type
+
+host_speeds 0<enter>
+
+to turn off the frame time display.
+
+
+Pentium Pro Performance
+-----------------------
+
+The Pentium Pro is a very fast Quake platform, but has one weak spot; it is
+by default very slow on writes to video memory.  This means that in default
+hardware configurations, you are usually much better off setting
+vid_nopageflip to 1 if you use VESA modes, so drawing is done to system
+memory instead of to video memory.  Remember that you must set the mode
+after setting vid_nopageflip to 1 in order to get vid_nopageflip to take
+effect.  (vid_nopageflip can sometimes be faster on a Pentium, too, but
+not by nearly as much in general, and it's often slower.)
+
+The Pentium Pro has some special features that are not turned on by default,
+but which can help Quake performance a LOT.  These features can be enabled
+by John Hinkley's program FASTVID, which can be obtained from
+ftp://members.aol.com/JHinkley/fastvid.zip.  Performance in 640x480
+mode on a Pentium Pro/150 nearly doubled after FASTVID was run; Quake
+was very playable (and looked great!) at this resolution.
+
+There's the usual caution with FASTVID:  It could conceivably make your
+system run goofily, or who knows what.  FASTVID is not a product of
+id Software, and id makes no guarantees regarding FASTVID. In other words,
+use FASTVID at your own risk.
+
+************************************************************************
+IMPORTANT NOTE: FASTVID works only on Pentium Pros!!!  Please do NOT
+contact either John Hinkley or id with problems concerning FASTVID on
+Pentium or 486 machines.
+************************************************************************
+
+
+Video Bug Reporting
+-------------------
+
+If you encounter a video-related bug, please fill out the form found at the
+end of this file and e-mail it to support@idsoftware.com.  There are several
+problems that are not bugs, and shouldn't be reported, including:
+
+* unavailability of some VESA modes; VESA modes are only supported by
+Quake if they are 8-bpp, are LFB modes (except for 320x200), and are
+no greater than 1280x1024 in resolution.  If you have a VESA mode
+that doesn't seem to be working properly, please contact the
+manufacturer; we just use the information that the VESA driver
+provides us with.
+
+* problems that occur when you change vid_wait from a default value
+of 1 (wait for vertical sync) in VESA modes
+
+* sluggish performance on 486s
+
+* the known palette problem on some Mach64s.
+
+* the known palette problems switching from fullscreen to the desktop and
+back under Win95.
+
+* the known problems switching back from the desktop in VESA modes after the
+system (Windows flag) key has switched from fullscreen to the desktop.
+
+* video modes that are not listed in the Video Modes menu, or that are not
+listed or are listed with "**" in the output from vid_describemodes; such
+modes are either not supported by your video adapter, or cannot be supported
+by Quake in the amount of memory your system has.  High-resolution modes will
+often not be available in 8 Mb systems.
+
+* 360-wide video modes that don't work although other resolutions do work
+
+* lack of low-resolution VESA modes; the availability of low-resolution modes
+is the responsibility of the VESA driver.  UniVBE 5.2 provides low-resolution
+modes on most adapters.
+
+Apart from these, we would very much like to hear about any video
+problems you encounter.
+
+
+==========================================
+==     Sound Subsystem Documentation    ==
+==========================================
+
+Quake's sound subsystem works only with Sound Blaster compatible sound
+cards.  For Quake to get the correct settings for DMA channel and PORT
+address, you must set your BLASTER environment variable (or have it set for
+you with the DIAGNOSE utility in your SB16 directory).  If you do not have
+the BLASTER environment variable set, your sound will not work.  If your
+sound card supports Sound Blaster compatibility, Windows 95 should set this
+variable for you.
+
+Note:  some sound cards do not have 100% Sound Blaster compatible
+hardware, but emulate the Sound Blaster interface.  Such cards may
+display some inconsistencies relative to an actual sound blaster.
+In particular, sound may be delayed on some cards.
+
+Note:  it is possible for sound to get choppy if the frame rate
+drops to a very low level, below 5 frames a second.  A frame rate
+that low will not provide a good gameplay experience, so if you
+do experience choppy sound, your machine is almost certainly not
+fast enough to run Quake satisfactorily in general.
+
+If (when) you see bugs, please use the form attached to the end
+of these docs to submit a bug report.
+
+Sound Card Command Line Options, Commands, and Variables
+==================================================================
+
+The commands and variables below work under any operating system.
+Command-Line options are typed on the command line in most any place
+but only in operating systems which support command line interfaces,
+like DOS's COMMAND.COM, or NEXTSTEP's or Linux's csh, sh, or bash.
+For example, under DOS, the NOSOUND option would be used like this:
+"C:> quake -nosound".
+
+Command-Line Options
+--------------------
+
+NOSOUND
+  Syntax: -nosound
+  Description: This will prevent *any* sound code from being executed.  If
+	you are having technical difficulty with the game and then try
+	running the game with this option and the problem goes away, then
+	the problem is probably somewhere in the sound code.
+
+SSPEED
+  Syntax: -sspeed <speed>
+  Description: This will ask the sound code to set the playback speed
+    within the constraints of the capabilities of the card.  This is
+	11025 Hz by default and usually from 8000 to 44100.  Making this
+	faster requires more CPU horsepower, and has no actual benefits,
+	because the sounds only contain 11 KHz data.  Making this slower
+	degrades sound quality, but improves performance and saves memory.
+
+Commands
+--------
+
+SOUNDINFO
+  Syntax: soundinfo
+  Description: This prints the "portable" information on your current
+        audio hardware setting in the game.  It specifies whether there is
+        stereo output (0 or 1), the number of samples in the DMA buffer, the
+        current sample position (changes each time you run SOUNDINFO and
+        ranges from 0 to the number of samples), the number of sample bits,
+	the submission chunk (1 in DOS or Linux w/ mmaped sound, larger in
+	Linux w/o mmaped sound), playback speed in Hz, the DMA buffer address
+	in hexadecimal (usually 8 digits after the 0x, starting with 0xf00..
+	in DOS, starting with 0x400.. in Linux, and less than 8 digits if the
+	hardware was not initialized successfully), and the number of
+        channels mixed in software (8 by default, changeable w/NUMCHANNELS
+        command).
+
+STOPSOUNDS
+  Syntax: stopsounds
+  Description: Stops any current looping sounds.
+
+
+Sound Blaster Sound Card Command-Line Options and Commands
+==========================================================
+
+The following applies to Sound Blaster cards or compatibles under DOS
+or a DOS box.
+
+Commands
+--------
+
+SBINFO
+  Syntax: sbinfo
+  Description: This will print information on the Sound Blaster card
+    in the system.  If the version is 4 or greater, then it is some
+	kind of Sound Blaster 16 or compatible.  Version 2 is an 8 bit mono
+	sound blaster, Version 3 is an 8 bit stereo sound blaster pro.
+	The port is the I/O port
sensed from the A variable in the BLASTER
+	environment variable.
The DMA is the DMA channel and is confirmed in
+	hardware if the
card is version 4 or higher.  The mixer port can be
+	ignored.
+
+
+==========================================
+==   CD Audio Subsystem Documentation   ==
+==========================================
+
+Overview
+========
+Quake is designed to play background music off of a CD-ROM.  The Quake CD has
+music tracks on it and each level has been assigned a track that will be
+played.
+
+Win95 Users:  Putting a CD other than the Quake CD into the drive when Quake
+is already running will sometimes cause another Windows application to start
+and switch you back to Windows with Quake running in the background.  You
+will probably want to stop whatever was started and switch back to Quake as
+quickly as possible... especially if you are playing deathmatch.
+
+
+Command Line Parameters
+=======================
+-nocdaudio
+   This will prevent the CD audio system from even attempting to initialize.
+   No CD commands or functions will be available.  The game will just run
+   with no music.
+
+-cdmediacheck
+   This causes the game to periodically check to see if the CD has been
+   removed and a new one placed in the player.  It is off by default since
+   this operation is very slow on some CD players and is not needed under
+   Win95.  There is normally no reason to enable this option; it would
+   only be useful if you were going to be changing the CD from within the
+   game on a regular basis.
+
+Commands
+========
+There is normally no reason you would need to use any of these commands.  If
+you are playing Quake with the Quake CD in your CD-ROM drive, the appropriate
+music track will be played automatically.
+
+cd on
+   Re-enables the CD audio system after a "cd off" command.
+
+cd off
+   Shuts down the CD audio system.  No more music will be played unless it
+   is re-enabled.
+
+cd reset
+   Causes the CD audio to re-initialize.  This is useful if you change
+   CDs or insert the CD after you've already run Quake.
+
+cd play <track number>
+   Plays the specified track one time.
+
+cd loop <track number>
+   Plays the specified track.  It will be repeated until either it is
+   manually stopped or another track is started.
+
+cd stop
+   Stops the currently playing track.
+
+cd resume
+   Will resume playback of a stopped track.
+
+cd eject
+   This is for CD players that do not have a manual eject button.
+
+cd remap <track1> <track2> <track3> ...
+   Allows you to switch what tracks are played.  This is especially useful
+   if you want to play music other than that on the Quake CD.  If the CD
+   audio system is told to play track 1, it will instead play the 1st
+   track you specified.  For example: assuming a CD with 1 data track and
+   8 music tracks, the command "cd remap 1 9 8 7 6 5 4 3 2" would leave
+   the data alone and play the audio tracks as if they had been placed on
+   the CD in the opposite order.
+
+cd info
+   Reports information such as the number and types of tracks on the current
+   CD, what track (if any) is currently playing, and the playback volume.
+
+
+Variables
+=========
+bgmvolume
+   The background music volume.  Valid values are 0.0 though 1.0.  Changes
+   will normally be made using the options menu.
+
+   Not all CD-ROM players support variable volume.  The 0.0 to 1.0 value
+   translated to a value from 0 to 255 before it is passed to MSCDEX.  How
+   this value is interpreted varies from drive to drive.  The only thing
+   required by the MSCDEX specification is that 0 is off and anything else
+   is on.  Some CD-ROM drives only have on and off so change to bgmvolume
+   will have have no effect on volume once it is on.
+
+
+Messages
+========
+CDAudio_Init: MSCDEX version 2.00 or later required.
+   MSCDEX was either not loaded, or is a version earlier than 2.00.
+
+CDAudio_Init: First CD-ROM drive will be used
+   MSCDEX reported that the system has more than one CD-ROM drive.
+   Quake will always use the first drive in this case.
+
+CDAudio_Init: Unable to allocate low memory.
+   We were unable to allocate the memory needed to communicate with MSCDEX.
+   Although the game can still run, this indicates a severe low memory
+   condition.
+
+CD Audio Initialized
+   Indicates that the CD audio system has successfully initialized.
+
+CDAudio_Play: Bad track number N.
+   We attempted to play a track number that that is outside the range of
+   tracks recorded on the CD currently in the CD-ROM drive.  Probable causes
+   are that a CD other than Quake is in the player, or a custom level has
+   specified an invalid track number.
+
+CDAudio_Play: Can not play data.
+   A valid track was requested to be played, but it was a not an audio track.
+   The probable causes are the same as for a bad track number.
+
+CDAudio_Play: track N failed
+   A valid audio track was going to be played, but the play command to MSCDEX
+   returned an error.
+
+CDAudio: media changed
+   This is simply a notification.  It can only occur if the "-cdmediacheck"
+   option was specified on the command line.
+
+CDAudio: Error - playback stopped N
+   An error occurred while the CD was playing audio.  Playback has been
+   stopped and no further automatic play will be attempted; the game will
+   proceed without music.
+
+CDAudio_Init: No CD in player.
+   MSCDEX reported an error while Quake was attempting to get information
+   about the current CD.  There is either no CD in the player, or it was
+   unable to get the track information.  No automatic CD play will be
+   attempted; the game will proceed without music.
+
+
+==========================================
+==    Network Subsystem Documentation   ==
+==========================================
+
+Overview
+========
+
+Quake is a client/server game.  You are always running over some type of
+network.  In a standalone game, you are using a loopback network; it just
+passes messages back and forth in memory buffers.  This readme is talking
+about real networks and multiplayer deathmatches.  There are three main
+sections: commands, LANs, and Serial.
+
+Most normal configuration can be done via the game menus.
+
+There are two types of Quake servers: dedicated and listen.  A listen server
+is a machine that is used to play the game and also hosts the game for other
+players.  A dedicated server only hosts the game; it runs in text mode and
+does not let anyone play on that machine.  A single player game is really 
+just a 1 player listen server that doesn't listen for network connections.
+
+Dedicated vs Listen.  I'll try to make this simple: it is always better to
+use a dedicated server.  Why? Fairness and playability.  With a listen
+server, the person on the server always has advantages.  They will always be
+the first person into a level, they will always have zero latency, and they
+will get a server update on each and every frame.  On a dedicated server
+everyone gets equal treatment.  Getting into the server is a first come,
+first served proposition; latency is determined by each player's connection;
+and everyone is sent the same number of updates.  It's about as fair as life
+gets.  By the way, a good 486 machine works nicely as dedicated server.
+
+Another suggestion.  Until there is a native Win95 version of Quake, IPX will
+usually provide better gameplay on a local area network.  This is due to the
+delicate balancing act that is required to let a DOS program use the Win95
+TCP/IP stack.
+
+To start a Dedicated Server, you invoke Quake with the "-dedicated"
+command-line parameter.  When the server starts, you can type any command
+that you would normally type in the Quake Console, such as "map e1m1" to
+start the server on a specific map.  This can be done from the command-
+line as well by typing "quake -dedicated +map e1m1".  If a value is entered
+after "-dedicated", that is the amount of players allowed to connect, up
+to a maximum of 16 players. A dedicated server will quit to the OS whenever
+a fraglimit or timelimit is reached.  Example: "quake -dedicated 16" will
+start a 16-player dedicated server.
+
+To start a Listen Server, you invoke Quake with the "-listen" command-
+line parameter, or use the Multiplayer menu in the game.  Starting a listen
+server from the command-line will allow you to handle more than 4 players,
+as 4 is the limit when starting a game from the Multiplayer menu.  If a
+value is used after the "-listen", that is the maximum amount of players
+allowed, up to 16 players.
+
+Command Line Parameters, Commands, and Variables
+================================================
+
+Command line parameters
+-----------------------
+-nolan
+   Disables IPX, TCP/IP, and serial support.
+
+-noudp
+   Disables support for TCP/IP.
+
+-udpport <port#>
+   Specifies a UDP port to be used other than the default of 26000.
+
+-noipx
+   Disables support for IPX.
+
+-ipxport <port#>
+   Specifies a IPX port to be used other than the default of 26000.
+
+-noserial
+   Disable serial support.
+
+-mpath
+   Enables support for code to use Win95's TCP/IP stack.  Do NOT use this
+   under DOS!
+
+-listen [n]
+	Starts Quake ready to be a non-dedicated server for up to <n>
+	players.  If you do not specify a number <n> after -listen it will
+	default to 8.  The maximum allowed value is 16.
+
+-dedicated [n]
+	Starts Quake ready to be a dedicated server for up to <n> players.
+	If you do not specify a number <n> after -listen it will default to 8.
+	The maximum allowed value is 16.  A dedicated Quake server stays in
+	text mode.  This is the Quake console with most commands still
+	available; those that make no sense (like vid_mode) are ommitted.
+
+Console Variables
+-----------------
+
+net_messagetimeout
+   Specifies how long Quake should wait for a message to arrive before
+   deciding the connection has died.  The default is 3 minutes.  For
+   reference, messages usually arrive at the rate of about 20 per second.
+
+hostname
+   This is the name for your server that will show up on an slist
+   (see below).  The default value is "unnamed".
+
+sys_ticrate
+   Only used by dedicated servers.  This determines the rate at which the
+   server will send out updates to the clients.  The default value is 0.05
+   (20 updatesper second).  For servers where bandwidth is limited, using
+   modems or the internet for example, it is advisable to lower this value
+   to 0.1 (10 updates per second).  This will have a very minor effect on
+   responsiveness, but will half to outbound bandwitdh required making the
+   modem players a lot happier.
+
+
+Console commands
+----------------
+
+net_stats
+   This is for debugging. It displays various network statistics.
+
+slist
+   Looks for Quake servers on a local LAN (or over a null modem
+   cable).  This will NOT go outside the local LAN (will not cross
+   routers).
+
+
+LANs
+====
+
+Here are the LANs that are supported by the Quake test
+release.  For each one, you'll be told how to connect to a server
+*if it is not on your local network*.  If it is, you can use the
+"slist" command and connect by hostname.  See the main readme for
+a discussion of the connect command.
+
+IPX
+---
+
+Quake has been run with Novell's ODI IPX stack under DOS, PDIPX with packet
+drivers under DOS, and the Microsoft IPX stack in a Win95 DOS box.  When
+connecting to a server using IPX, you specify its network:nodeaddress (like
+12345678:1234567890AB).  If you are on the same network, you can just specify
+the node address.  If you are doing a connect command from the console, a
+full IPX address must be enclosed in quotes.
+
+For example, the server's IPX address is "00FADE23:00aa00b9b5b2", you would
+enter: connect "00FADE23:00aa00b9b5b2"
+
+Win95 TCP/IP
+------------
+
+Please see the Win95 section of this file for details about playing using
+TCP/IP under Win95.
+
+Kali
+----
+
+To Quake, Kali appears to be IPX.  Once you've got Kali up and running, run
+Quake as if it was on an IPX network.
+
+Beame & Whiteside TCP/IP
+------------------------
+
+This is the only DOS TCP/IP stack supported in the test release.
+It is not shareware...it's what we use on our network (in case you
+were wondering why this particular stack).  This has been "tested"
+extensively over ethernet and you should encounter no problems
+with it.  Their SLIP and PPP have not been tested.  When connecting
+to a server using TCP/IP (UDP actually), you specifiy it's "dot notation"
+address (like 123.45.67.89).  You only need to specify the unique portion
+of the adress.  For example, if your IP address is 123.45.12.34
+and the server's is 123.45.56.78, you could use "connect 56.78".
+
+Playing over the Internet
+-------------------------
+Yes, you can play Quake over the Internet.  How many people can be in
+the game? That depends.  How smooth will the game be?  That depends.
+There are just too many variables (bandwidth, latency, current load,
+etc...) for us to make any kind of promises about Internet play.
+
+
+Serial/Modem
+============
+
+The Quake serial driver supports two COM ports.  Although they are referred
+to as COM1 and COM2, you can configure them to use any normal hardware
+COM port (1 thru 4 on most PCs).  The com ports are used with interrupts,
+so their IRQ may not be used for another purpose (such as a LAN adapter
+or sound card).  The IRQ may not be shared with another device either;
+not even another COM port.  A client can only be connected to one server
+at a time, so multiple ports are really only useful on a server.
+When using modems, the client must originate the call and the server
+must answer.  This holds true even for a two player, non-dedicated
+server configuration.
+
+In the Multiplayer menu, the default modem string is "ATZ".  If your modem
+games are too slow, you can change this string to the appropriate one for
+your modem as listed below in the "Modem Strings" section.
+
+
+The COMx commands
+-----------------
+
+Use the menus for serial play whenever possible.  The console
+interface is only for unusual configurations.  It is much more
+difficult to understand and use correctly.
+
+Those of you who do use the console commands for serial play need to
+know that the menus always use the first Quake COM line (COM1); yes,
+even for COM2.  The names COM1 and COM2 here mean the first and second
+serial ports, not necessarily the PC COM1 and COM2 ports (although those
+are the default configurations).
+
+There are two commands to support serial/modem play for Quake.  They
+are: COM1 and COM2. Entering one of these commands with no arguments
+will display the status of that serial port, similar to this:
+
+Settings for COM1
+enabled:   true
+connected: false
+uart:      16550
+port:      3f8
+irq:       4
+baud:      57600
+CTS:       ignored 
+DSR:       ignored 
+CD:        ignored
+clear:     ATZ
+startup:
+shutdown:  ATH
+
+When used with arguments, these commands change the settings and
+status of the COM ports.  The possible arguments are listed below;
+examples follow.
+
+enable | disable
+   "enable" means that your configuration is complete and you want to use
+   the COM port.  "disable" is used to turn off a COM port, usually to
+   change its settings.  The default (initial) state is disabled.
+
+
+modem | direct
+   Use one of these two to let Quake know if you are using a modem or a
+   direct connection (also called a null modem).  Quake uses this to know
+   if it needs to handles modem initialization strings, dialing sequences,
+   and hangup procedures.
+
+reset
+   This will reset the COM port to its default settings and state.
+
+
+port <n>
+irq <n>
+   These are used to set the I/O Port and IRQ that your serial port uses.
+   The default values are: port=3f8 irq=4 for COM1 and port=2f8 irq=3 for
+   COM2.  Note that the port number is displayed in hexadecimal; to enter
+   it you would use something like "COM2 port 0x2f8"; the "0x" preceding
+   the "2f8" indicates that you are giving the value in hexadecimal
+   otherwise decimal is assumed.
+
+
+baud <n>
+   Sets the baud rate.  Valid values for <n> are: 9600, 14400,
+   28800, 57600, and 115200.  57600 is the default.  Please note that
+   this is the baud rate used for the uart, not your modem.  It is
+   perfectly valid to use 57600 on a COM port that is connected to a
+   28.8 modem.
+
+8250 | 16550
+   Specifies the type of uart chip in your system. Normally this is
+   automatically detected, one of these need only be used if your chip
+   is incorrectly detected.
+
+clear
+startup
+shutdown
+   This allows you to specify the clear, startup, and shutdown strings
+   needed for
a modem for playing Quake.  If you've found values that
+   previously worked
with Doom, use them here.  If you are playing over
+   a null modem cable,
leave these blank.
+
+-cts | +cts
+-dsr | +dsr
+-cd  | +cd
+   These determine if certain serial control lines should be honored or
+   ignored. The "-" means you want that line ignored, the "+" means to honor
+   it. "cts" is an abbreviation for "clear to send", "dsr" for
+   "data set ready", and "cd" for "carrier detect".  Do not
change these
+   values unless you are absolutely positive you need to. The default is to
+   ignore all 3 lines.
+
+Quake always uses no parity, 8 data bits, and 1 stop bit; these
+values can not be changed.  The baud, port, irq, and uart type can
+not be changed on an enabled port, you must disable it first.
+
+
+Configuration examples
+----------------------
+Example1: You have a machine with two serial ports you are going
+to use as a Quake server.  COM1 will be using a null modem cable and
+COM2 will be connected to a 14.4 modem.  You would use commands similar
+(the startup string would almost certainly be different) to these:
+
+COM1 baud 57600 enable
+COM2 baud 14400 modem startup AT\N0%C0B8 enable
+
+
+Example2: You are going to use your machine to connect to a dial-up
+Quake server with your 28.8 modem connected to COM2.  You would
+use a command something like this:
+
+COM2 baud 57600 modem startup AT\N0%C0B8 enable
+
+Note the baud rate is not the same as the modem speed.  This allows
+the modem-to-uart communications to occur at a higher rate than
+the modem-to-modem communications.
+
+Connecting to a serial Quake server
+-----------------------------------
+
+Connecting to a Quake server over a serial/modem connection is done
+using the "connect" command.  The command "connect 5551212" would try to
+connect to a Quake server at the phone number 555-1212.  Note: your local
+phone company would probably appreciate it if you didn't try this number!
+
+If you are using a null modem cable, you can type "connect #".
+Quake will then attempt to connect to the server.
+
+
+Known problems / workarounds
+============================
+Packet drivers with PDIPX - there is a bug that stops a server running on
+this combination from responding to the slist command.  Use the patched
+version of PDIPX included with Quake to correct this problem.
+
+SLIST sees no servers - Some PCMCIA ethernet cards and PPP drivers will
+not do the UDP broadcasts needed for the SLIST command (search for local
+games from the menu) to function correctly.  In these cases you must
+connect to a Quake game using either its IP address or hostname
+(DNS resolvable hostname, not the hostname variable in Quake).
+
+"BW_OpenSocket failed: 5" - This error is specific to the Beame and
+Whitesdie TCP/IP stack.  This stack uses DOS file handles as it's
+socket handles.  This error occurs when DOS runs out of file handles.
+You need to increase the number specified by "FILES=" in the DOS
+config.sys file.
+
+Severe lag using TCP/IP under Win95:
+	- Occasionaly when you first connect in to a Quake game using Win95
+TCP/IP you will experience severe lag and not be able to control your
+player's actions.  This usually clears up in 10 to 15 seconds.  
+	- There is apparently a strange limbo state for Microsoft's File and
+Print sharing.  This has been seen when it was installed and then later
+removed, but it still appears on the menus.  For some unknown reason
+this causes severe lag for a Quake game.  You need to go back and make
+sure that it is either completely installed or removed.
+
+
+==========================================
+==            Modem Strings             ==
+==========================================
+
+Boca M1440i (internal):
+ATS48=0S37=9S46=136%C0%E0%M0&K0&Q0&R1&C1&D2\G0\N1N0
+
+Boca 14.4k (internal):
+AT&C0N0S37=9&K0W0&Q0S36=3S48=128%C0
+
+Boca 14.4 Fax/Modem
+AT S46=0 S37=9 N0 &Q0 &D2 &K4
+
+Boca 14.4k (external):
+AT &F S0=1 S36=0 &K0 &Q6N0S37=9 &D2
+
+Boca 14.4k:
+AT S46=0 S37=9 N0 &Q0 &D2 &K0 %C0
+
+Cardinal 14.4k v.32bis, v.42bis Fax/Modem:
+AT &F N0 S37=9 &Q0 &D2 \N1
+
+Digicom Systems (DSI) (softmodem):
+AT Z \N0 &D2 &K0 S48=48
+
+Digicom Systems Scout Plus:
+ATZ*E0*N3*M0*S0*F0&D2
+
+Gateway Telepath:
+AT &F S37=9 %C0 &K0 &Q6 \G0
+
+Gateway Telepath 14.4k:
+AT S46=0 S37=9 N0 &Q0 &D2 &K0 %C0
+
+Gateway Telepath I:
+AT S0=1 &N6 &K0 &M0
+
+Gateway Telepath II:
+AT S0=1 S37=9 %C0 &Q0 &K0
+
+Generic v.32bis 14.4k Fax/Modem:
+AT \N0 %C0 B8
+
+Generic 14.4k Fax/Modem:
+AT S46=0 S37=9 N0 &Q0 &D2 %C0 \G0 &K0
+
+GVC 14.4k (internal):
+AT &F B8 \Q0
+
+Hayes 28.8k V.FAST Modem:
+AT &Q6 &K S37=9 N %C0 \N0
+
+Infotel 144I:
+AT&Q0 S37=9 N0 &D2
+
+Infotel 14.4:
+&F0 \N1 &D2 S37=F8
+
+Intel 14.4k:
+AT \N0 %C0 \Q0 B8
+
+Intel 14.4k (internal):
+AT Z B8 Q1 \C0 \N1 %C0 \V "H
+
+Linelink 144e:
+AT &F &D1 &K0 &Q6 S36=3 S46=136 %C0
+19200
+
+Microcom AX:
+&F \N1 \Q0 &D2
+
+Microcom QX/4232bis:
+AT %C0 \N0
+
+Netcomm M7F:
+AT &E &K0 B0 \V0 X4 &D2 \N1 \Q0 #J0 #Q9 %C0
+
+Nokia ECM 4896M Trellis V.32:
+AT Z %C0 /N0
+
+Nuvotel IFX 14.4 (internal):
+&F \N1 &D2 
+
+Practical Peripherals 14400FX v.32bis:
+AT Z S46=0 &Q0 &D2
+
+Practical Peripherals 14400FX v.32bis:
+AT S46=0 &Q0 &K0 &D2
+
+Supra:
+AT &F0 S46=136 %C0
+
+Supra (external):
+AT &K &Q &D \N1
+
+Supra 14.4k v.32bis:
+AT &F S46=136 &Q0 &D2
+
+Supra 14.4k v.32bis:
+AT &K &Q &D \N1
+
+Supra Fax Modem 14.4K v.32 bis
+AT &F %C0 S48=7 Q0 V1 W1
+
+Telepath 14.4k:
+AT &F&M0&K0&N6&H0 S0=1
+
+Twincomm DFi 14.4:
+AT&F &Q0 %C0 S37=9 &D2
+
+UDS V.3223:
+&F \N1 \Q &D2
+
+UDS Fastalk 32BX:
+&F0 \N1 &D2
+
+USR Courier v.32bis:
+ATS0=1 S7=60 E1 Q0 V1 &C1 &D2 &H0 &K0 &M0 &N6 &A3
+
+USR Courier HST/DS 16.8k:
+First reset the modem in a communication program with AT&F&W
+AT X4 B0 &A0 &B0 &H2 &I0 &K0 &M0 &N6a
+
+USR DS v.32bis v.42bis (external):
+AT&m0&n6&a0&r1&h0&k0&i0&s0&b1x1
+
+USR Sporster 9600:
+AT&M0&K0&N6
+
+USR Sportster V.34 28.8 (note: works best at 19200 baud):
+AT &F &M0 &I0 &K0 &B0 &N0
+
+USR Sportster 14.4k Fax/Modem USING ERROR CORRECTION:
+AT S0=1 S7=60 E1 QO V1 &C1 &D2 &K0 &N6 &A3
+
+USR Sportster 14.4k Fax/Modem (internal):
+AT &F&M0&K0&N6&H0
+
+USR Sportster 14.4k (internal):
+AT &F &B1 &H0 &I0 &K0 &M0 &N6 &R1
+
+USR Sportster 14.4k:
+ATS0=1S7=60E1Q0V1&C1&D2&K0&N6&A3
+
+USR Sportster 14.4k:
+AT &F0 &K0 &M0 &N6 &H0 &I0 &B1 &R1
+
+USR Sportster 14,000 Fax Modem:
+AT S0=2 &N6 &K0 &M0 &I0 &H0 &R1 &A0 V1 X4
+
+USR 14.4k:
+AT &F&A0&K0&M0
+
+USR 14.4k
+AT &K0 &H0 &D0 &I0 &R1
+
+USR 14.4k Dual Standard
+ATB0&R1&B1&N6Q0X4&A0&D2&H0&I0&K0&M0M1
+
+USR (model?):
+&F E1 V1 X4 &C1 &D2 &N0             
+
+ViVa 14.4k:
+AT&F&Q6\N0%C0&D2N0S37=9
+
+ViVa modem (internal):
+&F&Q6\N0%C0&D2N0S37=9
+
+Zoltrix model 14/14 VE:
+AT S0=Q0 V1 &C1 &D2 W2 &Q0
+
+Zoom 14.4k VFX:
+AT&Q6S37=9N0%C\N0
+
+Zoom 14.4k VFX:
+AT&Q6S37=11N0%C&K0
+
+Zoom OEM Modem:
+AT&Q6S37=9N0&K0
+
+Zyxel U-1496E:
+AT Z &N4 &K0
+
+
+==========================================
+==         Win95 Documentation          ==
+==========================================
+
+Quake is a DOS application.  However, it runs fine from the MS-DOS prompt
+under Win95, so long as the Properties for the MS-DOS prompt are set up so
+that Quake can run.  (See "Set the MS-DOS Prompt Properties", below, for
+information about setting MS-DOS Prompt Properties.)  Quake will NOT run
+under Windows NT. Following are some steps that can help Quake run better
+under Win95.
+
+
+Have enough memory
+------------------
+
+Quake requires at least 16 Mb of installed memory in order to run under
+Win95.
+
+
+Set the MS-DOS Prompt Properties
+--------------------------------
+
+If Quake won't run, the MS-DOS Prompt Properties may not be set correctly.
+To set the Properties for the MS-DOS prompt, bring up a DOS session, and
+either click on the MS-DOS icon in the upper left corner or press
+Alt-Spacebar, then select Properties from the menu that comes up, and make
+sure the following settings are correct.
+
+In the Program sheet of MS-DOS Prompt Properties, make sure the "Suggest
+MS-DOS mode as necessary" is checked.
+
+In the Memory sheet of MS-DOS Prompt Properties, make sure all five fields
+are "Auto".
+
+In the Screen sheet of MS-DOS Prompt Properties, set "Usage" to Full-screen.
+
+In the Misc sheet of MS-DOS Prompt Properties, uncheck the "Allow screen
+saver" box, and check the "Always suspend" box.
+
+
+Make sure there's enough free disk space
+----------------------------------------
+
+If you get error messages like "can't lock memory" under Win 95, or if you
+get other weird, inexplicable errors, make sure you haven't run out of disk
+space; delete some files if necessary.  You can see how much disk space is
+free by bringing up "My Computer" and clicking on the disk icon; the free
+disk space will be shown at the bottom of the window.
+
+
+Run fullscreen
+--------------
+
+Quake can run in a window under Win95--but it will run very slowly.  You are
+unlikely to get satisfactory performance unless you run Quake fullscreen.
+Quake normally comes up fullscreen under Win95; if you have switched it back
+to windowed mode, you can get that window back to fullscreen by clicking on
+it and then pressing Alt-Enter.
+
+
+Shut down other applications
+----------------------------
+
+Many Win95 apps and DOS apps run even when they're not the foreground
+application.  Such applications contend for system resources such as memory,
+processor cycles, and sound hardware.  If Quake seems to be running choppily,
+if sound is garbled, or if the disk is going all the time, try shutting down
+whatever other applications you have running.  For example, some players
+have reported that Quake does not run as well when the Office shortcut bar
+is running.
+
+
+Restore the palette if it gets garbled
+--------------------------------------
+
+Under Win 95, the palette occasionally gets messed up when switching from
+Quake to the desktop and back again.  You can restore the palette by
+bringing down the console (either press tilde ('~'), or press Esc to bring
+up the menu, select Options, and select Console... from the Options menu),
+and typing bf and pressing the enter key, to generate a background flash,
+which sets the palette.  Press Esc to exit the console.  Alternatively,
+setting the screen brightness, either from the Options menu or via the
+gamma console command, sets the palette.
+
+
+Avoid the system key
+--------------------
+
+Under Win 95, if the system key (the key with the Win 95 flag on it) is
+pressed while Quake is running fullscreen in a VESA mode, Win 95 may be
+unable to switch back from the desktop to Quake, in which case it will
+notify you of this, then terminate the Quake session.  This is a quirk
+of Win 95, and there is no workaround other than not to press that key
+or not to use VESA modes.  (Some people go so far as to remove the system
+key from their keyboard.)  Switching away from Quake with Alt-Enter,
+Ctrl-Esc, Alt-Tab, or Alt-Spacebar all work fine.
+
+
+Give Quake more and/or locked memory
+------------------------------------
+
+By default, Quake tries to allocate 8 Mb of unlocked memory for heap space
+under Win 95.  More memory helps Quake run faster; you can allocate more
+memory for Quake under Win95 by setting the command-line switch
+
+-winmem x
+
+where x is the number of megabytes to allocate for Quake.  If there's enough
+memory in the system, the larger the number, up to about 16, the better the
+performance.  If, however, there isn't enough memory in the system, or many
+other applications are running, the larger number can just cause Quake to
+page to disk a lot, and can actually slow performance considerably.  Also,
+higher numbers can also cause Win 95 to take longer to start Quake and take
+longer to return to the desktop afterward.  If you have 32 Mb or more in your
+machine, -winmem 16 should provide the best performance for Quake.  If you
+have less than 32 Mb, or a lot of applications running, then you will have
+to experiment to find the best amount of memory to allocate for Quake.
+
+You may optionally instruct Quake to lock itself in memory by using the
+command-line switch
+
+-winlock
+
+so it won't get paged out by other applications.  This can avoid hitches when
+parts of Quake get paged into and out of memory, and thus provide a smoother
+playing experience.  On the other hand, it can cause Quake to take longer to
+start, and can make the return to the desktop take longer when Quake ends,
+because Quake has been hogging a lot of memory.  It is even possible, if most
+of the memory in the system is locked by Quake, that it will take many
+minutes to switch back to the desktop while Quake is running, so the system
+will effectively be nearly frozen.  Therefore, use -winlock with caution;
+Quake is not as well-behaved a Win95 citizen when -winlock is specified, and
+does not share resources particularly well.
+
+-winmem can be used in conjunction with -winlock; if -winmem specifies more
+memory than is available to be locked, then Quake will lock as much memory
+as possible.  Being too aggressive about how much memory is locked can
+actually slow Quake performance, because unlocked parts of the system like
+system CD and sound code and data can then be forced to page, so if you do
+lock memory, you will have to experiment to find the sweet spot, unless you
+have 32 Mb or more of memory.
+
+-winlockunlock can be specified as an alternative to -winlock, to tell Quake
+to lock its memory when it starts, then immediately unlock it.  The
+advantages of doing this are: 1) it forces all of Quake's pages into memory,
+so no pages should need to be brought in as Quake runs, making for smoother
+running at the start, and 2) it enables Quake to determine whether the
+specified amount of memory (if -winmem is also specified) is available in the
+machine, so you can be sure Quake won't try to allocate more heap space than
+the the amount of physical memory that's actually available.  Like -winlock,
+-winlockunlock causes Quake to take quite a bit longer to start up, but it
+has the advantage of making Quake a good Win95 citizen if you need to switch
+back to the desktop, or have other apps running.
+
+In general, Quake will run fine without any of the -winxxx switches, but you
+may find that one or more of them--particularly -winmem if you have more than
+16 Mb--helps Quake performance on your machine.
+
+None of this is an issue under DOS itself (as oppsed to a DOS box under
+Win95), because Quake just uses all the memory in the machine under DOS.
+
+By default, Quake tries to allocate 8 Mb of unlocked memory for heap space
+
+
+Watch out for limbo subsystems
+------------------------------
+Microsoft's File and Print sharing and IPX protocol stack have both been
+known to cause strange problems when they are in a limbo state.  The limbo
+state is seems to be an uninstall that did not complete succesfully.  Both
+of these cause poor network play performance. If you are experiencing
+severe lag, check the File and Print services.  If you the warning "IPX
+driver send failue: 04", check the IPX protocol stack.  They need to be
+either completely installed or removed; the problems only occur when they
+get into this strange semi-installed state.
+
+
+==========================================
+==        Key Binding and Aliases       ==
+==========================================
+
+Pressing the tilde key ("~") will bring down the console (pressing the
+tilde key or ESC while in the console will close the console). From the
+console you can adjust your player controls, this is done by "binding"
+keys to commands.  The format for binding keys is as follows:
+
+bind <key> <command>
+
+Where <key> is a valid key control and <command> is a valid quake command.
+
+Example:
+To bind the j key to the 'jump' command, you would type:
+bind j +jump			
+and press enter.
+
+Non-printable keys such as 'page up' and buttons from the mouse/joystick are
+bound in the same manner as printable characters. A list of bindable keys can
+be found at the end of this file.
+
+Example:
+To bind the page up key to the 'jump' command, you would type:
+bind pageup +jump
+and press enter.
+
+To bind the right mouse button to the attack command, you would type:
+bind mouse2 +attack
+and press enter.
+
+The alias command is used to create a reference to a command or list of
+commands.  When aliasing multiple commands, or commands that contain
+multiple words (such as "fraglimit 50"), you must enclose all the commands
+in quotation marks and separate each command with a semi-colon.
+
+Example of an alias that changes some Deathmatch server parameters:
+
+alias net_game "hostname my_server ; fraglimit 15 ; timelimit 15"
+bind INS net_game
+
+Once the server is spawned (you must be the one running the -listen server),
+you just push the Insert key to set the hostname, frag limit and time limit
+of the server. So now the first person to 15 frags, or with the one with the
+most frags in 15 minutes, wins.
+
+Another example would be to change to the Rocket Launcher, fire one rocket,
+and change back to the Double Barrel Shotgun, when you press the "," key:
+
+alias rl_dbsg "impulse 7 ; +attack ; wait ; -attack ; impulse 3"
+bind , rl_dbsg
+
+Aliasing is very powerful, allowing you great flexibility, so you should
+experiment by aliasing different commands in various ways.
+
+A list of common commands can be found in the next section.
+
+
+==========================================
+==    Quake Keys and Common Commands    ==
+==========================================
+
+The following keys can be bound:
+
+A-Z                     0-9
+*F1-F12                 *TAB
+ENTER                   SPACE
+BACKSPACE               UPARROW
+DOWNARROW               LEFTARROW
+RIGHTARROW              ALT
+CTRL                    SHIFT
+INS                     DEL
+PGDN                    PGUP
+HOME                    END
+PAUSE                   SEMICOLON
+
+MOUSE1 (mouse button 1)
+MOUSE2 (mouse button 2)
+MOUSE3 (mouse button 3)
+
+*~ (tilde)
+
+* Can only be bound on the command line or in a .cfg file.
+
+The ESC key cannot be bound. 
+
+
+==========================================
+==         Making a Config File         ==
+==========================================
+
+The commands (bindings and aliases) discussed above can be included into a
+file containing all of your personal configurations, known as a "config"
+file.  This file can then be loaded during game play to enable all your
+personal bindings and settings.
+
+To do this, use your favorite editor to create a new file, such as
+"fragmstr.cfg".  Your .cfg file MUST be located in the quake\id1 directory
+or quake won't find it.  Then after launching Quake, you would type "exec
+fragmstr.cfg" and press enter, from the console.  You can also exec you .cfg
+file from the DOS command prompt by typing "quake +exec fragmstr.cfg".
+When you exec a config file, it is the same as typing all the lines in your
+config file into the console, only Quake does it for you.  Here is an
+example config file (c:\quake\id1\bear.cfg) and the meaning of all the
+bindings, aliases and settings:
+
+-------------------------------cut here-------------------------------------
+name player1            // Sets player name to player1 (lets your opponent
+                        // know who fragged them)
+
+sensitivity 4           // Sets the mouse sensitivity to 4
+
+scr_conspeed 5000       // Sets the console raise/lower speed
+
+lookspring 0            // Sets Mouse Look Spring to 0 (0=keep looking,
+                        // 1=spring back, when mouse button is released)
+
+vid_mode 10             // Sets Video Mode to mode 10 (360X480 resolution)
+
+gamma .8                // Sets Gamma Correction to .8 (<1=Lighter, 1=normal
+                        // and >1=darker)
+
+viewsize 70             // Sets the Screen View size to 70 degrees
+
+bind mouse1 +forward    // Binds the left mouse button to Move Forward
+
+bind mouse3 +attack     // Binds the middle mouse button to Fire
+
+bind mouse2 +mlook      // Binds the right mouse button to Mouse Look
+
+bind HOME "save bear1"  // Binds the Home Key to quick save, saves to
+                        // bear1.sav
+
+bind ENTER +showscores  // Binds the Enter key to show Deathmatch Scores
+
+bind SHIFT +speed       // Binds the Shift key to Run
+
+bind CTRL +jump         // Binds the Control key to Jump
+
+bind ; +mlook           // Binds the ; key to Mouse Look also
+
+bind . +moveleft        // Binds the . key to Strafe Left
+
+bind / +moveright       // Binds the / key to Strafe Right
+
+color 3 4               // Makes Uniform Top green and Pants Red for Net play
+
+alias rl_dbsg "impulse 7 ; +attack ; wait ; -attack ; impulse 3"
+
+bind , rl_dbsg          // Aliases single rocket attack command and binds
+                        // it to the ',' key.
+-------------------------------cut here-------------------------------------
+
+
+==========================================
+==                Demos                 ==
+==========================================
+
+The standard Demos
+------------------
+
+Quake has 3 standard demos that start playing when you first run the game.
+It will cycle through these demos until you start or join a game.
+
+Recording a Demo
+----------------
+"record <demoname> <map> [track]"  This starts up level <map> and begins
+recording a demo into a file name <demoname>.dem.  You can specify the
+optional <track> to choose a background music from the CD, otherwise the
+default selection for that map will be played.
+
+Playing a Demo
+--------------
+"playdemo <demoname>"  This command will open the file <demoname>.dem and
+play the demo.
+
+How to not play the standard demos at startup
+---------------------------------------------
+
+So you've seen the Necropolis demo 10 billion times now and really don't
+ever want to see it again?  Here's how.
+
+The easy way is to start Quake with a "+map" command.  You could do
+"quake +map start" and you'll start on the single player start level.
+Or you could do "quake +map nonsense" and you'll wind up at the Quake
+console since there is no map named nonsense.  You can accomplish the
+same thing with a "+connect" too.   "+connect" by itself will look for
+Quake servers on the local network, "+connect 192.12.34.56" or
+"+connect host.timbuktu.edu" will try to connect the the specified
+Quake server.
+
+There is another way to not show the demos; one that also keeps your
+customizations in a seperate directory from the data files in the
+Quake distribution.
+
+Do this in the quake directory (the directory where you installed Quake;
+where you find "quake.exe" and "the id1" directory).  Create a file named
+"quake.rc".  Its contents should be:
+
+exec default.cfg
+exec config.cfg
+exec autoexec.cfg
+stuffcmds
+menu_main
+
+Create a batch file to run Quake in the quake directory.  "Q.BAT" is a good
+name. It's contents should be:
+
+quake -game . %1 %2 %3 %4 %5 %6 %7 %8 %9
+
+If you normally use the Q95 batch file, just add the "-game ." part to
+that file.
+
+Now you can run "q" and quake will start off with the main menu displayed
+instead of running the demos.
+
+You can also make a seperate subdirectory for this if you'd like.  For
+example, make a directory named "mine" in the quake directory.  Create
+the "quake.rc" file as specified above in this directory.  Use
+"-game mine" instead of "-game ." in your batch file.
+
+Important note:  The directory specified by "-game" is where Quake will
+look for config.cfg, load and save games, and record and play
+demos.
+
+
+==========================================
+==         Reporting Quake Bugs         ==
+==========================================
+
+How to use the bug report:
+
+Where to send bug reports:
+E-mail  : support@idsoftware.com
+FAX     : 214-686-9288
+
+There are two sections of information - primary and secondary.
+
+Primary information contains information such as date, your name, e-mail
+address, etc.  Secondary information is actual bug information. There are
+a few different sections depending on what type of bug you revieced
+(sound, video, etc). Only fill out and include information from the section
+related to the type of bug you received.
+
+If possible, start Quake with the "-condebug" command line parameter
+and try to reproduce the bug. Attach the "qconsole.log" file found in the
+"id1" directory to the end of the bug report. If the bug is sound related,
+while in Quake, execute the SOUNDINFO and SBINFO (DOS only) commands from
+the console.
+
+Please attach a copy of your CONFIG.SYS and AUTOEXEC.BAT file to the end of
+the report.
+
+Bugs submitted properly with this form will get attention.
+Unformatted ones sent to personal accounts will be ignored.
+If you see problems, please take the time to do this.
+
+If you do not have all of the information requested in the form,
+don't worry. Send what you do have.
+
+Please include the version #. THe version # for Quake can be found in the
+lower right hand corner of the console. To bring up the console, press the
+tilde ('~') key. Press tilde ('~') again or ESC to exit.
+
+-------------------------------cut here-------------------------------------
+
+
+============================================================================
+==              Quake Bug Report - Primary information                    ==   
+============================================================================
+
+Date:  
+Name:  
+Phone number:  
+E-mail address:  (please include this, we redirect tons of mail)
+Game Title:  
+Version #: 
+Operating system (i.e., DOS 6.0 or Windows 95):
+Computer type:  
+BIOS date:
+BIOS version:
+Processor type:  
+Processor speed:  
+Do you program at school/work?
+Do you provide tech. support at school/work?
+Please state the problem you encountered:
+Please state how to reproduce the problem:
+
+If program crashed with nasty undecipherable techno-garbage, please
+look for the eight-digit hex number which comes after "eip="
+and write it down here:
+
+
+============================================================================
+==              Quake Bug Report - Secondary information                  ==
+============================================================================
+
+------------------------------ Video Related ------------------------------ 
+
+Video Card Manufacturer:
+Video Card Model:
+Chipset Used:
+BIOS Date:
+(If using UniVBE, The above information can be found by running uvconfig)
+
+Did the problem occur while in a VESA mode?
+
+If so, what is the VESA driver and version?  (eg., UniVBE 5.1a,
+built into board BIOS, or manufacturer provided TSR)
+
+------------------------------ Sound Related ------------------------------
+
+Audio card brand and model:  
+
+If DOS or a DOS box, please run the command "set > set.txt" then
+attach "set.txt" to the end of the report.
+
+----------------------------- Network Related -----------------------------
+
+What type of network connection was established when the error occurred?
+(modem, nullmodem, or network)
+If modem, Modem brand and model:
+
+If network, Network card brand and model:
+            Network protocol/configuration:  
+
+---------------------------------------------------------------------------
+
+
+
+
+
+
+
+                                                                          
--- /dev/null
+++ b/WinQuake/docs/INSTALL
@@ -1,0 +1,177 @@
+INSTALL for Linux Quake
+-----------------------
+
+Quake for Linux provides several different binary executables to support
+different hardware and drivers.
+
+Included with Linux Quake are:
+	- SVGALib Quake (squake)
+	  This is a software renderer Quake that runs at the text console in Linux.
+	- GLQuake (glquake, glquake.glx and glquake.3dfxgl)
+	  This is a hardware renderer Quake that runs using hardware 3D
+	  acceleration.
+	- X11 Quake (quake.x11)
+	  Software rendering in a window under X11.
+
+Installation
+------------
+
+Mount the Quake CD as one would usually mount a CDROM, this can be 
+accomplished by using the command:
+
+		mount /dev/cdrom /mnt
+
+As root.  Once the CD is mounted, run the setup script on the CD as root.
+
+		$ su
+		Password:
+		# mount /dev/cdrom /mnt
+		# /bin/sh /mnt/setup
+
+The script will ask some questions about what options you want to install
+and automatically install the software into /usr/local/games/quake.
+
+Requirements
+------------
+
+Requirements for SVGALib Quake:
+
+- SVGALib 1.20 or later (/lib/libvga.so.1.2.10)
+- libc 5.2.18 or later (5.0.9 will not work, /lib/libc.so.5.2.18)
+  or glibc (libc6) for the glibc version
+- CD-ROM for CDAudio
+- Soundcard capable of mmap'd buffers.  USSLite 3.5.4 was used to build squake
+  with.  Works fine on SoundBlaster 16 and Gravis Ultrasound MAX.
+- SVGALib supported mouse (usually if it works with X, it'll work with
+  squake).
+- Kernel 2.0.24 or later
+  - untested with 2.1 kernels, your mileage may vary
+
+Requirements for GLQuake:
+
+- 3DFX based card for the GLQuake version, VooDoo, VooDoo Rush or VooDoo2
+at this writing.  In order to use 3DFX hardware, you must have 3DFX's
+GLIDE drivers installed.  RPMs for these drivers are available at:
+http://glide.xxedgexx.com/3DfxRPMS.html
+- For the glX version, an OpenGL implementation that includes hardware
+glX support.
+- CD-ROM for CDAudio
+- Soundcard capable of mmap'd buffers.  USSLite 3.5.4 was used to build squake
+  with.  Works fine on SoundBlaster 16 and Gravis Ultrasound MAX.
+- SVGALib compatible mouse for glquake or X11 for glquake.glx
+- Kernel 2.0.24 or later
+  - untested with 2.1 kernels, your mileage may vary
+
+Requirements for X11 Quake:
+
+- X11R5 later, only tested with XFree86, should work with most X Servers
+- libc 5.2.18 or later (5.0.9 will not work, /lib/libc.so.5.2.18)
+  or glibc (libc6) for the glibc version
+- CD-ROM for CDAudio
+- Soundcard capable of mmap'd buffers.  USSLite 3.5.4 was used to build squake
+  with.  Works fine on SoundBlaster 16 and Gravis Ultrasound MAX.
+- SVGALib supported mouse (usually if it works with X, it'll work with
+  squake).
+- Kernel 2.0.24 or later
+  - untested with 2.1 kernels, your mileage may vary
+
+Additional notes for SVGALib Quake
+----------------------------------
+
+SVGALib may not detect a 3-button mouse properly (it
+will only use two buttons).  Check your /etc/vga/libvga.config
+and set it up for your mouse type.
+
+Also, newer versions of SVGALib have an mouse_accel_type option.  Most
+users will want to set this to "off" in /etc/vga/libvga.config.
+
+Additional notes for GLQuake
+----------------------------
+
+There are three different ways to execute GLQuake:
+
+1. The binary "glquake" requires Mesa 3-D 2.5 or later installed and compiled
+with 3DFX support (fxMesa..() function interface).  It also requires
+svgalib 1.3.0 or later for keyboard/mouse input.  This binary is a console
+application.  Mesa 3-D requires GLIDE to be installed.
+
+2. The shell script "glquake.3dfxgl" runs the "glquake" binary after
+preloading the lib3dfxgl.so library.  This is a port of 3DFX's Win32
+OpenGL MCD (Mini Client Driver) to Linux.  It is faster than Mesa 3-D
+since it was written specifically with supporting GLQuake in mind.
+lib3dfxgl.so requires that GLIDE be installed.
+
+3. The binary "glquake.glx" is linked against standard OpenGL libraries.
+It should run on many different hardward OpenGL implementations under
+Linux and X11.  This binary is an X11 application and must be run under
+X11.  It will work with Mesa 3-D as a standard glX based OpenGL 
+applications.  If the Mesa 3-D library is compiled with 3DFX support,
+you can have Mesa 3-D support 3DFX hardware under X11 by setting the
+enviroment variable "MESA_GLX_FX" to "fullscreen" for fullscreen mode
+and "window" for windowed mode, eg. "export MESA_GLX_FX=fullscreen" for sh 
+or "setenv MESA_GLX_FX fullscreen" for csh.
+
+For glquake, you must also have SVGALib or later installed (1.3.0 or later
+prefered).  GLQuake uses SVGALib for mouse and keyboard handling.
+
+If you have gpm and/or selection running, you will have to terminate them
+before running GLQuake since they will not give up the mouse when GLQuake
+attempts to run.  You can kill gpm by typing 'killall gpm' as root.
+
+You must run GLQuake as root or setuid root since it needs to access things 
+such as sound, keyboard, mouse and the 3DFX video.  Future versions may not 
+require root permissions.
+
+Additional notes for X11 Quake
+------------------------------
+
+This is a windowed version that is generic for X11.  It runs in a window
+and can be resized.  You can specify a starting window size with:
+	-width <width>
+	-height <height>
+	-winsize <width> <height>
+Default is 320x200. It works in 16bit modes, but it's slower (twice as many
+bytes to copy).
+
+No other video modes are supported (just runs windowed).  Mouse is read, but
+not "grabbed" by default.  Go to the Options menu and turn on Use Mouse to grab
+the mouse and use it in the game (or type "_windowed_mouse 1" at the console).
+
+Command Line Options for Linux Quake
+------------------------------------
+
+-mem <mb>
+Specify memory in megabytes to allocate (default is 8MB, which should be fine
+for most needs).
+
+-nostdout
+Don't do any output to stdout
+
+-mdev <device> (SVGALib based versions only)
+Mouse device, default is /dev/mouse
+
+-mrate <speed> (SVGALib based versions only)
+Mouse baud rate, default is 1200
+
+-cddev <device>
+CD device, default is /dev/cdrom
+
+-mode <modenum>
+Use indicated video mode
+
+-nokdb
+Don't initialize keyboard
+
+-sndbits <8 or 16>
+Set sound bit sample size.  Default is 16 if supported.
+
+-sndspeed <speed>
+Set sound speed.  Usual values are 8000, 11025, 22051 and 44100.
+Default is 11025.
+
+-sndmono
+Set mono sound
+
+-sndstereo
+Set stereo sound (default if supported)
+
--- /dev/null
+++ b/WinQuake/docs/INSTALL.Q2Mission
@@ -1,0 +1,39 @@
+INSTALL for Linux Quake2 Mission Packs
+--------------------------------------
+
+Installation
+------------
+
+Mount the Quake2 Mission Pack CD as one would usually mount a CDROM, this can 
+be accomplished by using the command:
+
+		mount /dev/cdrom /mnt
+
+As root.  Once the CD is mounted, run the setup script on the CD as root.
+
+		$ su
+		Password:
+		# mount /dev/cdrom /mnt
+		# /bin/sh /mnt/setup
+
+The script will ask some questions about what options you want to install
+and automatically install the software into /usr/local/games/quake2.
+
+After Installation
+------------------
+
+To run Quake2 Mission Pack #1: The Reckoning add the following option when
+executing Quake2:
+
+	./quake2 +set game xatrix
+
+To run Quake2 Mission Pack #2: Ground Zero add the following:
+
+	./quake2 +set game rogue
+
+Requirements
+------------
+
+The Quake2 Mission Packs require a previous installation of Quake2.
+
+
--- /dev/null
+++ b/WinQuake/docs/INSTALL.Quake
@@ -1,0 +1,177 @@
+INSTALL for Linux Quake
+-----------------------
+
+Quake for Linux provides several different binary executables to support
+different hardware and drivers.
+
+Included with Linux Quake are:
+	- SVGALib Quake (squake)
+	  This is a software renderer Quake that runs at the text console in Linux.
+	- GLQuake (glquake, glquake.glx and glquake.3dfxgl)
+	  This is a hardware renderer Quake that runs using hardware 3D
+	  acceleration.
+	- X11 Quake (quake.x11)
+	  Software rendering in a window under X11.
+
+Installation
+------------
+
+Mount the Quake CD as one would usually mount a CDROM, this can be 
+accomplished by using the command:
+
+		mount /dev/cdrom /mnt
+
+As root.  Once the CD is mounted, run the setup script on the CD as root.
+
+		$ su
+		Password:
+		# mount /dev/cdrom /mnt
+		# /bin/sh /mnt/setup
+
+The script will ask some questions about what options you want to install
+and automatically install the software into /usr/local/games/quake.
+
+Requirements
+------------
+
+Requirements for SVGALib Quake:
+
+- SVGALib 1.20 or later (/lib/libvga.so.1.2.10)
+- libc 5.2.18 or later (5.0.9 will not work, /lib/libc.so.5.2.18)
+  or glibc (libc6) for the glibc version
+- CD-ROM for CDAudio
+- Soundcard capable of mmap'd buffers.  USSLite 3.5.4 was used to build squake
+  with.  Works fine on SoundBlaster 16 and Gravis Ultrasound MAX.
+- SVGALib supported mouse (usually if it works with X, it'll work with
+  squake).
+- Kernel 2.0.24 or later
+  - untested with 2.1 kernels, your mileage may vary
+
+Requirements for GLQuake:
+
+- 3DFX based card for the GLQuake version, VooDoo, VooDoo Rush or VooDoo2
+at this writing.  In order to use 3DFX hardware, you must have 3DFX's
+GLIDE drivers installed.  RPMs for these drivers are available at:
+http://glide.xxedgexx.com/3DfxRPMS.html
+- For the glX version, an OpenGL implementation that includes hardware
+glX support.
+- CD-ROM for CDAudio
+- Soundcard capable of mmap'd buffers.  USSLite 3.5.4 was used to build squake
+  with.  Works fine on SoundBlaster 16 and Gravis Ultrasound MAX.
+- SVGALib compatible mouse for glquake or X11 for glquake.glx
+- Kernel 2.0.24 or later
+  - untested with 2.1 kernels, your mileage may vary
+
+Requirements for X11 Quake:
+
+- X11R5 later, only tested with XFree86, should work with most X Servers
+- libc 5.2.18 or later (5.0.9 will not work, /lib/libc.so.5.2.18)
+  or glibc (libc6) for the glibc version
+- CD-ROM for CDAudio
+- Soundcard capable of mmap'd buffers.  USSLite 3.5.4 was used to build squake
+  with.  Works fine on SoundBlaster 16 and Gravis Ultrasound MAX.
+- SVGALib supported mouse (usually if it works with X, it'll work with
+  squake).
+- Kernel 2.0.24 or later
+  - untested with 2.1 kernels, your mileage may vary
+
+Additional notes for SVGALib Quake
+----------------------------------
+
+SVGALib may not detect a 3-button mouse properly (it
+will only use two buttons).  Check your /etc/vga/libvga.config
+and set it up for your mouse type.
+
+Also, newer versions of SVGALib have an mouse_accel_type option.  Most
+users will want to set this to "off" in /etc/vga/libvga.config.
+
+Additional notes for GLQuake
+----------------------------
+
+There are three different ways to execute GLQuake:
+
+1. The binary "glquake" requires Mesa 3-D 2.5 or later installed and compiled
+with 3DFX support (fxMesa..() function interface).  It also requires
+svgalib 1.3.0 or later for keyboard/mouse input.  This binary is a console
+application.  Mesa 3-D requires GLIDE to be installed.
+
+2. The shell script "glquake.3dfxgl" runs the "glquake" binary after
+preloading the lib3dfxgl.so library.  This is a port of 3DFX's Win32
+OpenGL MCD (Mini Client Driver) to Linux.  It is faster than Mesa 3-D
+since it was written specifically with supporting GLQuake in mind.
+lib3dfxgl.so requires that GLIDE be installed.
+
+3. The binary "glquake.glx" is linked against standard OpenGL libraries.
+It should run on many different hardward OpenGL implementations under
+Linux and X11.  This binary is an X11 application and must be run under
+X11.  It will work with Mesa 3-D as a standard glX based OpenGL 
+applications.  If the Mesa 3-D library is compiled with 3DFX support,
+you can have Mesa 3-D support 3DFX hardware under X11 by setting the
+enviroment variable "MESA_GLX_FX" to "fullscreen" for fullscreen mode
+and "window" for windowed mode, eg. "export MESA_GLX_FX=fullscreen" for sh 
+or "setenv MESA_GLX_FX fullscreen" for csh.
+
+For glquake, you must also have SVGALib or later installed (1.3.0 or later
+prefered).  GLQuake uses SVGALib for mouse and keyboard handling.
+
+If you have gpm and/or selection running, you will have to terminate them
+before running GLQuake since they will not give up the mouse when GLQuake
+attempts to run.  You can kill gpm by typing 'killall gpm' as root.
+
+You must run GLQuake as root or setuid root since it needs to access things 
+such as sound, keyboard, mouse and the 3DFX video.  Future versions may not 
+require root permissions.
+
+Additional notes for X11 Quake
+------------------------------
+
+This is a windowed version that is generic for X11.  It runs in a window
+and can be resized.  You can specify a starting window size with:
+	-width <width>
+	-height <height>
+	-winsize <width> <height>
+Default is 320x200. It works in 16bit modes, but it's slower (twice as many
+bytes to copy).
+
+No other video modes are supported (just runs windowed).  Mouse is read, but
+not "grabbed" by default.  Go to the Options menu and turn on Use Mouse to grab
+the mouse and use it in the game (or type "_windowed_mouse 1" at the console).
+
+Command Line Options for Linux Quake
+------------------------------------
+
+-mem <mb>
+Specify memory in megabytes to allocate (default is 8MB, which should be fine
+for most needs).
+
+-nostdout
+Don't do any output to stdout
+
+-mdev <device> (SVGALib based versions only)
+Mouse device, default is /dev/mouse
+
+-mrate <speed> (SVGALib based versions only)
+Mouse baud rate, default is 1200
+
+-cddev <device>
+CD device, default is /dev/cdrom
+
+-mode <modenum>
+Use indicated video mode
+
+-nokdb
+Don't initialize keyboard
+
+-sndbits <8 or 16>
+Set sound bit sample size.  Default is 16 if supported.
+
+-sndspeed <speed>
+Set sound speed.  Usual values are 8000, 11025, 22051 and 44100.
+Default is 11025.
+
+-sndmono
+Set mono sound
+
+-sndstereo
+Set stereo sound (default if supported)
+
--- /dev/null
+++ b/WinQuake/docs/INSTALL.Quake2
@@ -1,0 +1,218 @@
+INSTALL for Linux Quake2
+------------------------
+
+Quake2 for Linux supports the following video subsystems:
+
+- SVGALib Console Graphics (ref_soft.so)
+	- Requires SVGALib 1.2.0 or later
+- X11 Window Graphics (ref_softx.so)
+	- X11R5 or later, XShm shared memory extension supported
+- 3DFX fxMesa with Mesa 3-D or 3DFX Miniport (ref_gl.so)
+	- Mesa 3-D 2.6 or later, specifically compiled for 3DFX support
+	  Mesa 3-D 2.6 compiled with 3DFX support is provided with this archive.
+- Generic glX (X11) based OpenGL (ref_glx.so)
+	- Requires a glX based hardware accelerated OpenGL implementation.
+	  Mesa 3-D 2.6 supports this on 3DFX hardware.
+
+Also included is a specific 3DFX mini-OpenGL implementation for running Quake2
+on 3DFX hardware.
+
+Installation
+------------
+
+Mount the Quake2 CD as one would usually mount a CDROM, this can be 
+accomplished by using the command:
+
+		mount /dev/cdrom /mnt
+
+As root.  Once the CD is mounted, run the setup script on the CD as root.
+
+		$ su
+		Password:
+		# mount /dev/cdrom /mnt
+		# /bin/sh /mnt/setup
+
+The script will ask some questions about what options you want to install
+and automatically install the software into /usr/local/games/quake2.
+
+Make sure you have the appropirate hardware, drivers and libraries installed
+for the renderer you are going to play on.
+
+Quake2 for Linux supports the following renderers:
+
+- ref_soft
+  Software rendering under SVGALib (console only).  SVGALib 1.2.10 or later
+  is required.  Note that SVGALib 1.2.11 supports the ability to run a
+  SVGALib application under X11 as it will automatically allocate a new
+  console.  The default mode is 320x240 (ModeX) since that is the lowest
+  resolution supported by Quake2.  If SVGALib supports your video card, higher
+  resolution modes such as 640x480 and 800x600 are also supported.
+
+  Please note that you may need to configure your mouse for SVGALib in
+  /etc/vga/libvga.config (or /etc/libvga.config).
+
+- ref_softx
+  Software rendering under X11.  This uses the MITSHM Extension and should
+  work will virtually all Linux X Servers.  **NOTE: Do not resize the window
+  under X11.  You must use the Video menu to change resolution/window size.
+
+  By default, the mouse will not be 'tied' to the Quake2 window.  To cause
+  Quake2 to grab the mouse, select 'Windowed Mouse' from the video menu,
+  or type '_windowed_mouse 0' at the console.  Do the reverse to release it.
+  You can bind keys to grab and release the mouse in the console, like so:
+    bind i "_windowed_mouse 1"  
+    bind o "_windowed_mouse 0"  
+  Then "i" will grab the mouse and "o" will release it.
+
+- ref_gl
+  This render can be run with two different OpenGL drivers:  Mesa 3-D
+  ontop of Linux GLIDE, or 3DFX's mini-OpenGL Quake driver. 
+  For Mesa 3-D, the necessary libMesaGL.so.2.6 is included with this archive.  
+  You must copy it to /usr/lib or /usr/local/lib and run ldconfig (as root)
+  in order to use it.  You can do this as follows:
+    tar cf - lib*GL* | (cd /usr/lib; tar xf -)
+  You should use tar to keep the symlinks intact. Once you copy them over
+  run ldconfig.
+  You must also download and install the Linux GLIDE drivers at
+  http://www.3dfx.com/software/download_glidel.html
+  And install them as instructed.
+  RPMs for GLIDE are available at :
+     http://glide.xxedgexx.com/3DfxRPMS.html
+  With version 3.20, the GL library is entirely runtime loaded.  This means
+  you can specify what shared object to load for GL display.
+  To use Mesa 3-D GL (console), run quake with:
+  	 ./quake2 +set vid_ref gl +set gl_driver libMesaGL.so.2
+  To use the 3DFX OpenGL Miniport, run the included quake2.3dfxgl:
+     ./quake2 +set vid_ref gl +set gl_driver lib3dfxgl.so
+  The gl_driver cvar indicates the name of the library to load for GL
+  functions.  It can be in any directory listed in /etc/ld.so.conf
+  or in /etc/quake2.conf
+
+  **NOTE:  There is a problem on libc5 systems where a vid_restart (causing
+  a reload of the video system) will crash.  There doesn't seem to be a 
+  solution to this yet.  It looks to be some sort of ld.so dynamic loading
+  interaction with SVGALib and ref_gl.so.  A work around is to start in
+  software mode (./quake2 +set vid_ref soft), then use the menu to set your
+  mode and a vid_restart will work when going from software to GL.  Exit
+  out then and save your video mode settings.
+  This problem does not occur on libc6 (glibc) based systems; vid_restart
+  works fine on there.
+
+- ref_glx
+  ref_glx should run on many different hardward OpenGL implementations under
+  Linux and X11.  This binary is an X11 application and must be run under
+  X11.  It will work with Mesa 3-D as a standard glX based OpenGL 
+  applications.  If the Mesa 3-D library is compiled with 3DFX support,
+  you can have Mesa 3-D support 3DFX hardware under X11 by setting the
+  enviroment variable "MESA_GLX_FX" to "fullscreen" for fullscreen mode
+  and "window" for windowed mode, eg. "export MESA_GLX_FX=fullscreen" for sh 
+  or "setenv MESA_GLX_FX fullscreen" for csh.
+
+  As with ref_gl, the "gl_driver" cvar indicates the shared library to load
+  for OpenGL functions (the glX functions must provided in that library
+  as well).
+
+Permissions
+-----------
+
+Quake2 requires root permissions to use the software (SVGALib) and GL (MesaGL
+w/3dfx) renders.  In order to make this secure, some special considerations
+must be made.
+
+Quake2 should get setuid root:
+	chown root quake2
+	chmod 4711 quake2
+
+And the ref_soft.so and ref_gl.so files must owned by root.
+
+The file /etc/quake2.conf must be installed.  This file contains a single
+line with the path of where the ref shared libraries can be found.
+A sample one is included that lists /usr/games/quake2 as the default
+path.  The libraries are only loaded out of the directory listed in
+/etc/quake2.conf for security considerations.
+
+Special permissions are not required for the softx renderer, but quake2 may
+still need to be setuid root to open the sound device (quake2 will give up
+setuid root permissions before loading softx).
+
+NOTE:  If you use a setuid quake2 binary and run it as a normal user, it
+will NOT be able to switch renderers on the fly because root permissions
+are given up after the renderer is loaded.  You can switch renderers on the
+fly if you run quake2 as root (su or log in as root).
+
+NOTE:  When the quake2 binary is run in dedicated server mode
+(+set dedicated 1), no special permissions are required and 
+/etc/quake2.conf is not read since no renderer is loaded.
+
+----
+
+The first time you run Quake2, it will use ref_soft or ref_softx based
+on whether a DISPLAY environment variable exists.
+
+To force the loading of a specific renderer at load time, use the following
+command lines:
+
+	./quake2 +set vid_ref soft
+	./quake2 +set vid_ref softx
+	./quake2 +set vid_ref gl
+	./quake2 +set vid_ref glx
+
+Linux Specific Cvars
+--------------------
+
+To set this, use +set on the command line, i.e.:
+	./quake2 +set cd_dev /dev/hdc +set sndmono 1
+
+nocdaudio (defaults to 0)
+  Do not enable cd audio if not zero
+
+sndbits (defaults to 16)
+  Set sound bit sample size.
+
+sndspeed (defaults to 0)
+  Set sound speed.  Usual values are 8000, 11025, 22051 and 44100.
+  If set to zero, causes the sound driver to attempt speeds in the following
+  order:  11025, 22051, 44100, 8000.
+
+sndchannels (defaults to 2)
+  Indicates stereo or mono sound.  Defaults to 2 (stereo). Use 1 for mono.
+
+nostdout (defaults to 0)
+  Whether to output console msgs to standard out.  Non-zero is cease output.
+
+Dedicated server
+----------------
+
+To run Linux Quake2 as a dedicated server, just run it as follows:
+
+  ./quake2 +set dedicated 1
+
+You can also set dmflags, timelimit, etc. in a config file, like so:
+  set timelimit 20
+  set fraglimit 25
+  set dmflags 532
+  map fact3
+
+Then exec that config file on load, like so:
+
+  ./quake2 +set dedicated 1 +exec server.cfg
+
+If you use a config file, you must put a 'map' command in it or the
+server won't load a map.
+
+To run a dedicated server in the background, use this;
+
+	nohup ./quake2 +set dedicated 1 +exec server.cfg &
+
+A better way is to run Quake2 on a tty via screen.  screen can be found
+at ftp://prep.ai.mit.edu/pub/gnu/screen-3.7.4.tar.gz, but it comes with
+most modern Linux installations now.
+
+-----------------------------------------------------------------------------
+
+Linux Quake2 is an unsupported product.  Usage of this product is bound by 
+the legal notice found on the distribution Quake2 CDROM.
+
+/// Zoid
+zoid@idsoftware.com
+
--- /dev/null
+++ b/WinQuake/docs/README
@@ -1,0 +1,157 @@
+README for Linux Quake
+----------------------
+
+This README convers all versions of Quake for Linux:
+	- SVGALib Quake (squake)
+	- GLQuake (glquake, glquake.glx and glquake.3dfxgl)
+	- X11 Quake (quake.x11)
+
+Requirements for SVGALib Quake:
+
+- SVGALib 1.20 or later (/lib/libvga.so.1.2.10)
+- libc 5.2.18 or later (5.0.9 will not work, /lib/libc.so.5.2.18)
+  or glibc (libc6) for the glibc version
+- CD-ROM for CDAudio
+- Soundcard capable of mmap'd buffers.  USSLite 3.5.4 was used to build squake
+  with.  Works fine on SoundBlaster 16 and Gravis Ultrasound MAX.
+- SVGALib supported mouse (usually if it works with X, it'll work with
+  squake).
+- Kernel 2.0.24 or later
+  - untested with 2.1 kernels, your mileage may vary
+
+Requirements for GLQuake:
+
+- 3DFX based card for the GLQuake version, VooDoo, VooDoo Rush or VooDoo2
+at this writing.  In order to use 3DFX hardware, you must have 3DFX's
+GLIDE drivers installed.  RPMs for these drivers are available at:
+http://glide.xxedgexx.com/3DfxRPMS.html
+- For the glX version, an OpenGL implementation that includes hardware
+glX support.
+- CD-ROM for CDAudio
+- Soundcard capable of mmap'd buffers.  USSLite 3.5.4 was used to build squake
+  with.  Works fine on SoundBlaster 16 and Gravis Ultrasound MAX.
+- SVGALib compatible mouse for glquake or X11 for glquake.glx
+- Kernel 2.0.24 or later
+  - untested with 2.1 kernels, your mileage may vary
+
+Requirements for X11 Quake:
+
+- X11R5 later, only tested with XFree86, should work with most X Servers
+- libc 5.2.18 or later (5.0.9 will not work, /lib/libc.so.5.2.18)
+  or glibc (libc6) for the glibc version
+- CD-ROM for CDAudio
+- Soundcard capable of mmap'd buffers.  USSLite 3.5.4 was used to build squake
+  with.  Works fine on SoundBlaster 16 and Gravis Ultrasound MAX.
+- SVGALib supported mouse (usually if it works with X, it'll work with
+  squake).
+- Kernel 2.0.24 or later
+  - untested with 2.1 kernels, your mileage may vary
+
+Additional notes for SVGALib Quake
+----------------------------------
+
+SVGALib may not detect a 3-button mouse properly (it
+will only use two buttons).  Check your /etc/vga/libvga.config
+and set it up for your mouse type.
+
+Additional notes for GLQuake
+----------------------------
+
+There are three different ways to execute GLQuake:
+
+1. The binary "glquake" requires Mesa 3-D 2.5 or later installed and compiled
+with 3DFX support (fxMesa..() function interface).  It also requires
+svgalib 1.3.0 or later for keyboard/mouse input.  This binary is a console
+application.  Mesa 3-D requires GLIDE to be installed.
+
+2. The shell script "glquake.3dfxgl" runs the "glquake" binary after
+preloading the lib3dfxgl.so library.  This is a port of 3DFX's Win32
+OpenGL MCD (Mini Client Driver) to Linux.  It is faster than Mesa 3-D
+since it was written specifically with supporting GLQuake in mind.
+lib3dfxgl.so requires that GLIDE be installed.
+
+3. The binary "glquake.glx" is linked against standard OpenGL libraries.
+It should run on many different hardward OpenGL implementations under
+Linux and X11.  This binary is an X11 application and must be run under
+X11.  It will work with Mesa 3-D as a standard glX based OpenGL 
+applications.  If the Mesa 3-D library is compiled with 3DFX support,
+you can have Mesa 3-D support 3DFX hardware under X11 by setting the
+enviroment variable "MESA_GLX_FX" to "fullscreen" for fullscreen mode
+and "window" for windowed mode, eg. "export MESA_GLX_FX=fullscreen" for sh 
+or "setenv MESA_GLX_FX fullscreen" for csh.
+
+For glquake, you must also have SVGALib or later installed (1.3.0 or later
+prefered).  GLQuake uses SVGALib for mouse and keyboard handling.
+
+If you have gpm and/or selection running, you will have to terminate them
+before running GLQuake since they will not give up the mouse when GLQuake
+attempts to run.  You can kill gpm by typing 'killall gpm' as root.
+
+You must run GLQuake as root or setuid root since it needs to access things 
+such as sound, keyboard, mouse and the 3DFX video.  Future versions may not 
+require root permissions.
+
+Additional notes for X11 Quake
+------------------------------
+
+This is a windowed version that is generic for X11.  It runs in a window
+and can be resized.  You can specify a starting window size with:
+	-width <width>
+	-height <height>
+	-winsize <width> <height>
+Default is 320x200. It works in 16bit modes, but it's slower (twice as many
+bytes to copy).
+
+No other video modes are supported (just runs windowed).  Mouse is read, but
+not "grabbed" by default.  Go to the Options menu and turn on Use Mouse to grab
+the mouse and use it in the game (or type "_windowed_mouse 1" at the console).
+
+Command Line Options for Linux Quake
+------------------------------------
+
+-mem <mb>
+Specify memory in megabytes to allocate (default is 8MB, which should be fine
+for most needs).
+
+-nostdout
+Don't do any output to stdout
+
+-mdev <device> (SVGALib based versions only)
+Mouse device, default is /dev/mouse
+
+-mrate <speed> (SVGALib based versions only)
+Mouse baud rate, default is 1200
+
+-cddev <device>
+CD device, default is /dev/cdrom
+
+-mode <modenum>
+Use indicated video mode
+
+-nokdb
+Don't initialize keyboard
+
+-sndbits <8 or 16>
+Set sound bit sample size.  Default is 16 if supported.
+
+-sndspeed <speed>
+Set sound speed.  Usual values are 8000, 11025, 22051 and 44100.
+Default is 11025.
+
+-sndmono
+Set mono sound
+
+-sndstereo
+Set stereo sound (default if supported)
+
+End Notes
+---------
+
+Linux Quake is *NOT* an officially supported product.  Mail about it
+will be deleted.  Do not email id about this product.  If you are having
+technical difficultly, you can email me, but make sure you have the correct
+kernel, libc, svgalib and other software versions before you email me.
+
+Dave 'Zoid' Kirsch
+zoid@idsoftware.com
+Official Quake Unix Port Administrator
--- /dev/null
+++ b/WinQuake/docs/README.X11
@@ -1,0 +1,107 @@
+
+README for Linux SVGALib Quake
+------------------------------
+
+Requirements:
+
+- X11R5 later, only tested with XFree86, should work with most X Servers
+- libc 5.2.18 or later (5.0.9 will not work, /lib/libc.so.5.2.18)
+- CD-ROM for CDAudio
+- Soundcard capable of mmap'd buffers.  USSLite 3.5.4 was used to build squake
+  with.  Works fine on SoundBlaster 16 and Gravis Ultrasound MAX.
+- SVGALib supported mouse (usually if it works with X, it'll work with
+  squake).
+- Kernel 2.0.24 or later
+  - untested with 2.1 kernels, your mileage may vary
+
+This is a windowed version that is generic for X11.  It runs in a window
+and can be resized.  You can specify a starting window size with:
+	-width <width>
+	-height <height>
+	-winsize <width> <height>
+Default is 320x200. It works in 16bit modes, but it's slower (twice as many
+bytes to copy).
+
+No other video modes are supported (just runs windowed).  Mouse is read, but
+not "grabbed" by default.  Go to the Options menu and turn on Use Mouse to grab
+the mouse and use it in the game.  If you want to move the mouse out of
+QWCL, you have to turn Use Mouse off.
+
+Full sound support is included.  The default sound rate is 16-bit stereo,
+11KHz.  You can change this in the options section below.
+
+New Command Line Options for Linux SVGAlib Quake
+------------------------------------------------
+
+-mem <mb>
+Specify memory in megabytes to allocate (default is 8MB, which should be fine
+for most needs).
+
+-nostdout
+Don't do any output to stdout
+
+-cddev <device>
+CD device, default is /dev/cdrom
+
+-sndbits <8 or 16>
+Set sound bit sample size.  Default is 16 if supported.
+
+-sndspeed <speed>
+Set sound speed.  Usual values are 8000, 11025, 22051 and 44100.
+Default is 11025.
+
+-sndmono
+Set mono sound
+
+-sndstereo
+Set stereo sound (default if supported)
+
+Installation
+------------
+
+Boot DOS (I know, but you need it to run the Quake install program) and
+install Quake from your Quake CD to a DOS parition.
+
+Boot Linux and make a directory for Quake.  Copy everything from the DOS Quake
+directory into it.  i.e.:
+	(cd /dos/quake; tar cf - .) | (cd ~/quake; tar xf -)
+
+Quake for X11 does not need to be setuid root.  Sound can fail if /dev/dsp is
+not mode 666.
+
+Quake may segfault if it tries to initialize your sound card and their isn't
+one.  Same with the CDROM.  If it dies, try it with -nosound and/or
+-nocdaudio.  If you have a sound card it died on and you know it is
+supported by USSLite (the driver that comes with the Linux kernel), let me
+know and I'll take a look at it.
+
+It should work with SCSI CDROMs, but is untested.
+
+Full TCP/IP network support is in, including listen and dedicated server
+modes.
+
+All of the options described in TECHINFO.TXT and MANUAL.TXT from the Quake
+distribution will work, 'cept for stuff with vid modes and stuff.
+
+End Notes
+---------
+
+Linux Quake is *NOT* an officially supported product.  Mail about it
+will be deleted.  Do not email id about this product.  If you are having
+technical difficultly, you can email me, but make sure you have the correct
+kernel, libc, svgalib and other software versions before you email me.
+
+Dave 'Zoid' Kirsch
+zoid@idsoftware.com
+Official Quake Unix Port Administrator
+
+Acks
+----
+
+Greg Alexander <galexand@sietch.bloomington.in.us> for initial work in SVGALib
+support.
+Dave Taylor <ddt@crack.com> for basic Linux support.
+id Software for Quake and making me port it. :)
+
+Lots of people on #linux, #quake for testing.
+
--- /dev/null
+++ b/WinQuake/docs/readme.glquake
@@ -1,0 +1,162 @@
+Linux Glquake v0.98, Quake v1.09 release notes
+
+Requirements
+------------
+
+For 3DFX based hardware, you must download and install Linux GLIDE from 
+http://glide.xxedgexx.com/3DfxRPMS.html and install as per the
+instructions.
+
+Running GLQuake
+---------------
+
+There are three different ways to execute GLQuake:
+
+1. The binary "glquake" requires Mesa 3-D 2.5 or later installed and compiled
+with 3DFX support (fxMesa..() function interface).  It also requires
+svgalib 1.3.0 or later for keyboard/mouse input.  This binary is a console
+application.  Mesa 3-D requires GLIDE to be installed.
+
+2. The shell script "glquake.3dfxgl" runs the "glquake" binary after
+preloading the lib3dfxgl.so library.  This is a port of 3DFX's Win32
+OpenGL MCD (Mini Client Driver) to Linux.  It is faster than Mesa 3-D
+since it was written specifically with supporting GLQuake in mind.
+lib3dfxgl.so requires that GLIDE be installed.
+
+3. The binary "glquake.glx" is linked against standard OpenGL libraries.
+It should run on many different hardward OpenGL implementations under
+Linux and X11.  This binary is an X11 application and must be run under
+X11.  It will work with Mesa 3-D as a standard glX based OpenGL 
+applications.  If the Mesa 3-D library is compiled with 3DFX support,
+you can have Mesa 3-D support 3DFX hardware under X11 by setting the
+enviroment variable "MESA_GLX_FX" to "fullscreen" for fullscreen mode
+and "window" for windowed mode.
+
+You must also have SVGALib 1.3.0 or later installed.  GLQuake uses SVGALib
+for mouse and keyboard handling.
+
+If you have gpm and/or selection running, you will have to terminate them
+before running GLQuake since they will not give up the mouse when GLQuake
+attempts to run.  You can kill gpm by typing 'killall gpm' as root.
+
+You must run GLQuake as root or setuid root since it needs to access things 
+such as sound, keyboard, mouse and the 3DFX video.  Future versions may not 
+require root permissions.
+
+resolution options
+------------------
+glquake -width 512 -height 384
+Tries to run glquake at the specified resolution.  
+Only highend VooDoo cards support such high resolutions (most
+cards on the market right now do not).  Another popular and supported mode
+is 512x384 (-width 512 -height 384) which can offer a faster speed than
+the default 640x480.
+
+You can also specify the resolution of the console independant of the screen
+resolution.
+
+glquake -conwidth 320
+This will specify a console resolution of 320 by 240 (the height is
+automatically determined by the default 4:3 aspect ratio, you can also
+specify the height directly with -conheight).
+
+In higher resolution modes such as 800x600 and 1024x768, glquake will default
+to a 640x480 console, since the font becomes small enough at higher 
+resolutions to become unreadable.  If do you wish to have a higher resolution
+console and status bar, specify it as well, such as:
+glquake -width 800 -height 600 -conwidth 800
+
+texture options
+---------------
+The amount of textures used in the game can have a large impact on performance.  
+There are several options that let you trade off visual quality for better 
+performance.
+
+There is no way to flush already loaded textures, so it is best to change 
+these options on the command line, or they will only take effect on some of 
+the textures when you change levels.
+
+OpenGL only allows textures to repeat on power of two boundaries (32, 64, 
+128, etc), but software quake had a number of textures that repeated at 24 
+or 96 pixel boundaries.  These need to be either stretched out to the next 
+higher size, or shrunk down to the next lower.  By default, they are filtered 
+down to the smaller size, but you can cause it to use the larger size if you 
+really want by using: 
+
+glquake +gl_round_down 0
+This will generally run well on a normal 4 MB 3dfx card, but for other cards 
+that have either worse texture management or slower texture swapping speeds, 
+there are some additional settings that can drastically lower the amount of 
+textures to be managed.
+
+glquake +gl_picmip 1
+This causes all textures to have one half the dimensions they otherwise would.  
+This makes them blurry, but very small.  You can set this to 2 to make the 
+textures one quarter the resolution on each axis for REALLY blurry textures.
+
+glquake +gl_playermip 1
+This is similar to picmip, but is only used for other players in deathmatch.  
+Each player in a deathmatch requires an individual skin texture, so this can 
+be a serious problem for texture management.  It wouldn't be unreasonable to 
+set this to 2 or even 3 if you are playing competatively (and don't care if 
+the other guys have smudged skins).  If you change this during the game, it 
+will take effect as soon as a player changes their skin colors.
+
+run time options
+----------------
+At the console, you can set these values to effect drawing.
+
+gl_texturemode GL_NEAREST
+Sets texture mapping to point sampled, which may be faster on some GL systems 
+(not on 3dfx).
+
+gl_texturemode GL_LINEAR_MIPMAP
+This is the default texture mode.
+
+gl_texturemode GL_LINEAR_MIPMAP_LINEAR
+This is the highest quality texture mapping (trilinear), but only very high 
+end hardware (intergraph intense 3D / realizm) supports it.  Not that big of 
+a deal, actually.
+
+gl_finish 0
+This causes the game to not issue a glFinish() call each frame, which may make 
+some hardware run faster.  If this is cleared, the 3dfx will back up a number 
+of frames and not be very playable.
+
+gl_flashblend 0
+By default, glquake just draws a shaded ball around objects that are emiting 
+light.  Clearing this variable will cause it to properly relight the world 
+like normal quake, but it can be a significant speed hit on some systems.
+
+gl_ztrick 0
+Glquake uses a buffering method that avoids clearing the Z buffer, but some 
+hardware platforms don't like it.  If the status bar and console are flashing 
+every other frame, clear this variable.
+
+gl_keeptjunctions 0
+If you clear this, glquake will remove colinear vertexes when it reloads the 
+level.  This can give a few percent speedup, but it can leave a couple stray 
+blinking pixels on the screen.
+
+novelty features
+----------------
+These are some rendering tricks that were easy to do in glquake.  They aren't 
+very robust, but they are pretty cool to look at.
+
+r_shadows 1
+This causes every object to cast a shadow.
+
+r_wateralpha 0.7
+This sets the opacity of water textures, so you can see through it in properly 
+processed maps.  0.3 is very faint, almost like fog.  1 is completely solid 
+(the default).  Unfortunately, the standard quake maps don't contain any 
+visibility information for seeing past water surfaces, so you can't just play 
+quake with this turned on.  If you just want to see what it looks like, you 
+can set "r_novis 1", but that will make things go very slow.  When I get a 
+chance, I will probably release some maps that have been processed properly 
+for this.
+
+r_mirroralpha 0.3
+This changes one particular texture (the stained glass texture in the EASY 
+start hall) into a mirror.  The value is the opacity of the mirror surface.
+
--- /dev/null
+++ b/WinQuake/docs/readme.squake
@@ -1,0 +1,127 @@
+
+README for Linux SVGALib Quake
+------------------------------
+
+Requirements:
+
+- SVGALib 1.20 or later (/lib/libvga.so.1.2.10)
+- libc 5.2.18 or later (5.0.9 will not work, /lib/libc.so.5.2.18)
+- CD-ROM for CDAudio
+- Soundcard capable of mmap'd buffers.  USSLite 3.5.4 was used to build squake
+  with.  Works fine on SoundBlaster 16 and Gravis Ultrasound MAX.
+- SVGALib supported mouse (usually if it works with X, it'll work with
+  squake).
+- Kernel 2.0.24 or later
+  - untested with 2.1 kernels, your mileage may vary
+
+Here's the release you've been waiting for.  Linux squake supports
+320x200x256, the various modeX modes (320x400, 360x400, etc) as well as high
+res modes if your card is supported by SVGALib.  Use the Quake console command
+vid_describemodes to list supported modes and the command vid_mode <number> to
+change modes.
+
+Full sound support is included.  The default sound rate is 16-bit stereo,
+11KHz.  You can change this in the options section below.
+
+Mouse works great, but SVGALib may not detect a 3-button mouse properly (it
+will only use two buttons).  Check your /etc/libvga.config (or
+/etc/vga/libvga.config for SlackWare users).
+
+**Version 1.1 fixes some crash bugs with the mission packs.
+
+New Command Line Options for Linux SVGAlib Quake
+------------------------------------------------
+
+-mem <mb>
+Specify memory in megabytes to allocate (default is 8MB, which should be fine
+for most needs).
+
+-nostdout
+Don't do any output to stdout
+
+-mdev <device>
+Mouse device, default is /dev/mouse
+
+-mrate <speed>
+Mouse baud rate, default is 1200
+
+-cddev <device>
+CD device, default is /dev/cdrom
+
+-mode <modenum>
+Use indicated video mode
+
+-nokdb
+Don't initialize keyboard
+
+-sndbits <8 or 16>
+Set sound bit sample size.  Default is 16 if supported.
+
+-sndspeed <speed>
+Set sound speed.  Usual values are 8000, 11025, 22051 and 44100.
+Default is 11025.
+
+-sndmono
+Set mono sound
+
+-sndstereo
+Set stereo sound (default if supported)
+
+Installation
+------------
+
+Boot DOS (I know, but you need it to run the Quake install program) and
+install Quake from your Quake CD to a DOS parition.
+
+Boot Linux and make a directory for Quake.  Copy everything from the DOS Quake
+directory into it.  i.e.:
+	(cd /dos/quake; tar cf - .) | (cd ~/quake; tar xf -)
+
+Place squake into your Quake directory.  You must make it setuid root (since
+Quake access stuff like direct video writes, the raw keyboard mode, CD, etc).
+Quake will setuid back to the normal user as soon as it opens these files.
+Make Quake suid root as follows:
+	chown root squake
+	chmod 4755 squake
+
+Run squake.  I don't recommend running it as root, since all the saved
+config.cfg files will be then owned as root.  Use your normal account, unless
+you do everything as root, then your mileage will vary.
+
+squake may segfault if it tries to initialize your sound card and their isn't
+one.  Same with the CDROM.  If it dies, try it with -nosound and/or
+-nocdaudio.  If you have a sound card it died on and you know it is
+supported by USSLite (the driver that comes with the Linux kernel), let me
+know and I'll take a look at it.
+
+It should work with SCSI CDROMs, but is untested.
+
+Full TCP/IP network support is in, including listen and dedicated server
+modes.  squake makes a nice dedicated server as you don't need the X11
+libraries kicking around.
+
+All of the options described in TECHINFO.TXT and MANUAL.TXT from the Quake
+distribution will work, 'cept for stuff with vid modes and stuff.
+
+End Notes
+---------
+
+Linux SVGALib Quake is *NOT* an officially supported product.  Mail about it
+will be deleted.  Do not email id about this product.  If you are having
+technical difficultly, you can email me, but make sure you have the correct
+kernel, libc, svgalib and other software versions before you email me.
+
+Dave 'Zoid' Kirsch
+zoid@threewave.com
+Official Quake Unix Port Administrator
+
+Acks
+----
+
+Greg Alexander <galexand@sietch.bloomington.in.us> for initial work in SVGALib
+support.
+Dave Taylor <ddt@crack.com> for basic Linux support.
+id Software for Quake and making me port it. :)
+
+Lots of people on #linux, #quake for testing.
+
--- /dev/null
+++ b/WinQuake/dos_v2.c
@@ -1,0 +1,257 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+#include <sys/segments.h>
+#include <go32.h>
+#include <unistd.h>
+#include <sys/nearptr.h>
+#include <dos.h>
+#include <string.h>
+#include <dpmi.h>
+// #include <osfcn.h>
+#include <bios.h>
+
+#include "dosisms.h"
+
+_go32_dpmi_registers hmm;
+
+// globals
+regs_t regs;
+void (*dos_error_func)(char *msg, ...);
+
+static unsigned conventional_memory = -1;
+
+__dpmi_regs callback_regs;
+
+void map_in_conventional_memory(void)
+{
+	if (conventional_memory == -1)
+	{
+		if (__djgpp_nearptr_enable())
+		{
+			conventional_memory = __djgpp_conventional_base;
+		}
+	}
+}
+
+unsigned int ptr2real(void *ptr)
+{
+	map_in_conventional_memory();
+	return (int)ptr - conventional_memory;
+}
+
+void *real2ptr(unsigned int real)
+{
+	map_in_conventional_memory();
+	return (void *) (real + conventional_memory);
+}
+
+void *far2ptr(unsigned int farptr)
+{
+	return real2ptr(((farptr & ~0xffff) >>12) + (farptr&0xffff));
+}
+
+unsigned int ptr2far(void *ptr)
+{
+	return ((ptr2real(ptr)&~0xf) << 12) + (ptr2real(ptr) & 0xf);
+}
+
+int dos_inportb(int port)
+{
+	return inportb(port);
+}
+
+int dos_inportw(int port)
+{
+	return inportw(port);
+}
+
+void dos_outportb(int port, int val)
+{
+	outportb(port, val);
+}
+
+void dos_outportw(int port, int val)
+{
+	outportw(port, val);
+}
+
+void dos_irqenable(void)
+{
+	enable();
+}
+
+void dos_irqdisable(void)
+{
+	disable();
+}
+
+//
+// Returns 0 on success
+//
+
+int	dos_int86(int vec)
+{
+    int rc;
+    regs.x.ss = regs.x.sp = 0;
+    rc = _go32_dpmi_simulate_int(vec, (_go32_dpmi_registers *) &regs);
+    return rc || (regs.x.flags & 1);
+}
+
+int	dos_int386(int vec, regs_t *inregs, regs_t *outregs)
+{
+	int rc;
+	memcpy(outregs, inregs, sizeof(regs_t));
+	outregs->x.ss = outregs->x.sp = 0;
+	rc = _go32_dpmi_simulate_int(vec, (_go32_dpmi_registers *) outregs);
+	return rc || (outregs->x.flags & 1);
+}
+
+//
+// Because of a quirk in dj's alloc-dos-memory wrapper, you need to keep
+// the seginfo structure around for when you free the mem.
+//
+
+static _go32_dpmi_seginfo seginfo[10];
+
+void *dos_getmemory(int size)
+{
+
+	int rc;
+	_go32_dpmi_seginfo info;
+	static int firsttime=1;
+	int i;
+
+	if (firsttime)
+	{
+		memset(seginfo, 0, sizeof(seginfo));
+		firsttime = 0;
+	}
+
+	info.size = (size+15) / 16;
+	rc = _go32_dpmi_allocate_dos_memory(&info);
+	if (rc)
+		return 0;
+
+	for (i=0;i<10;i++)
+		if (!seginfo[i].rm_segment) break;
+	seginfo[i] = info;
+	return real2ptr((int) info.rm_segment << 4);
+
+}
+
+void dos_freememory(void *ptr)
+{
+
+	int i;
+	int segment;
+
+	segment = ptr2real(ptr) >> 4;
+	for (i=0 ; i<10 ; i++)
+		if (seginfo[i].rm_segment == segment)
+		{
+			_go32_dpmi_free_dos_memory(&seginfo[i]);
+			seginfo[i].rm_segment = 0;
+			break;
+		}
+
+}
+
+static struct handlerhistory_s
+{
+	int intr;
+	_go32_dpmi_seginfo pm_oldvec;
+} handlerhistory[4];
+
+static int handlercount=0;
+
+void	dos_registerintr(int intr, void (*handler)(void))
+{
+	_go32_dpmi_seginfo info;
+	struct handlerhistory_s *oldstuff;
+
+	oldstuff = &handlerhistory[handlercount];
+
+// remember old handler
+	_go32_dpmi_get_protected_mode_interrupt_vector(intr, &oldstuff->pm_oldvec);
+	oldstuff->intr = intr;
+
+	info.pm_offset = (int) handler;
+	_go32_dpmi_allocate_iret_wrapper(&info);
+
+// set new protected mode handler
+	_go32_dpmi_set_protected_mode_interrupt_vector(intr, &info);
+
+	handlercount++;
+
+}
+
+void	dos_restoreintr(int intr)
+{
+
+	int i;
+	struct handlerhistory_s *oldstuff;
+
+// find and reinstall previous interrupt
+	for (i=0 ; i<handlercount ; i++)
+	{
+		oldstuff = &handlerhistory[i];
+		if (oldstuff->intr == intr)
+		{
+			_go32_dpmi_set_protected_mode_interrupt_vector(intr,
+				&oldstuff->pm_oldvec);
+			oldstuff->intr = -1;
+			break;
+		}
+	}
+
+}
+
+void	dos_usleep(int usecs)
+{
+	usleep(usecs);
+}
+
+int dos_getheapsize(void)
+{
+	return _go32_dpmi_remaining_physical_memory();
+}
+
+int dos_lockmem(void *addr, int size)
+{
+	__dpmi_meminfo info;
+	info.address = (long) addr + __djgpp_base_address;
+	info.size = size;
+	if (__dpmi_lock_linear_region(&info))
+		return __dpmi_error;
+	else
+		return 0;
+}
+
+int dos_unlockmem(void *addr, int size)
+{
+	__dpmi_meminfo info;
+	info.address = (long) addr + __djgpp_base_address;
+	info.size = size;
+	if (__dpmi_unlock_linear_region(&info))
+		return __dpmi_error;
+	else
+		return 0;
+}
+
--- /dev/null
+++ b/WinQuake/dosasm.s
@@ -1,0 +1,77 @@
+#include "asm_i386.h"
+
+.data
+fpenv:	.long	0, 0, 0, 0, 0, 0, 0, 0
+
+.text
+.globl	C(StartMSRInterval)
+C(StartMSRInterval):
+	movl	$0x11,%ecx	// read the CESR
+	.byte	0x0F
+	.byte	0x32		// RDMSR
+
+	andl	$0xFE3FFE3F,%eax	// stop both counters
+	.byte	0x0F
+	.byte	0x30		// WRMSR
+
+	movl	4(%esp),%eax	// point counter 0 to desired event, with counters
+	andl	$0x3F,%eax		//  still stopped
+	movl	$0x11,%ecx
+	.byte	0x0F
+	.byte	0x30		// WRMSR
+
+	movl	$0x12,%ecx	// set counter 0 to the value 0
+	subl	%eax,%eax
+	subl	%edx,%edx
+	.byte	0x0F
+	.byte	0x30		// WRMSR
+	
+	movl	4(%esp),%eax // restart counter 0 with selected event
+	andl	$0x3F,%eax
+	subl	%edx,%edx
+	orl		$0xC0,%eax
+	movl	$0x11,%ecx	// control and event select
+	.byte	0x0F
+	.byte	0x30		// WRMSR
+
+	ret
+
+.globl	C(EndMSRInterval)
+C(EndMSRInterval):
+	movl	$0x12,%ecx	// counter 0
+	.byte	0x0F
+	.byte	0x32		// RDMSR
+
+	ret					// lower 32 bits of count in %eax
+
+#if 0
+	.data
+Lxxx:	.long	0
+
+	.text
+
+.globl C(setstackcheck)
+C(setstackcheck):
+
+	movl	%esp,%eax
+	subl	$0x38000,%eax
+	movl	$0x5A5A5A5A,(%eax)
+	movl	%eax,Lxxx
+
+	ret
+
+
+.globl C(dostackcheck)
+C(dostackcheck):
+
+	movl	Lxxx,%edx
+	movl	$0,%eax
+
+	cmpl	$0x5A5A5A5A,(%edx)
+	jz		qqq
+	incl	%eax
+qqq:
+
+	ret
+#endif
+
--- /dev/null
+++ b/WinQuake/dosisms.h
@@ -1,0 +1,100 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+
+//
+// dosisms.h: I'd call it dos.h, but the name's taken
+//
+
+#ifndef _DOSISMS_H_
+#define _DOSISMS_H_
+
+int dos_lockmem(void *addr, int size);
+int dos_unlockmem(void *addr, int size);
+
+typedef union {
+	struct {
+		unsigned long edi;
+		unsigned long esi;
+		unsigned long ebp;
+		unsigned long res;
+		unsigned long ebx;
+		unsigned long edx;
+		unsigned long ecx;
+		unsigned long eax;
+	} d;
+	struct {
+		unsigned short di, di_hi;
+		unsigned short si, si_hi;
+		unsigned short bp, bp_hi;
+		unsigned short res, res_hi;
+		unsigned short bx, bx_hi;
+		unsigned short dx, dx_hi;
+		unsigned short cx, cx_hi;
+		unsigned short ax, ax_hi;
+		unsigned short flags;
+		unsigned short es;
+		unsigned short ds;
+		unsigned short fs;
+		unsigned short gs;
+		unsigned short ip;
+		unsigned short cs;
+		unsigned short sp;
+		unsigned short ss;
+	} x;
+	struct {
+		unsigned char edi[4];
+		unsigned char esi[4];
+		unsigned char ebp[4];
+		unsigned char res[4];
+		unsigned char bl, bh, ebx_b2, ebx_b3;
+		unsigned char dl, dh, edx_b2, edx_b3;
+		unsigned char cl, ch, ecx_b2, ecx_b3;
+		unsigned char al, ah, eax_b2, eax_b3;
+	} h;
+} regs_t;
+
+unsigned int ptr2real(void *ptr);
+void *real2ptr(unsigned int real);
+void *far2ptr(unsigned int farptr);
+unsigned int ptr2far(void *ptr);
+
+int	dos_inportb(int port);
+int	dos_inportw(int port);
+void dos_outportb(int port, int val);
+void dos_outportw(int port, int val);
+
+void dos_irqenable(void);
+void dos_irqdisable(void);
+void dos_registerintr(int intr, void (*handler)(void));
+void dos_restoreintr(int intr);
+
+int	dos_int86(int vec);
+
+void *dos_getmemory(int size);
+void dos_freememory(void *ptr);
+
+void	dos_usleep(int usecs);
+
+int dos_getheapsize(void);
+
+extern regs_t regs;
+
+#endif	// _DOSISMS_H_
+
--- /dev/null
+++ b/WinQuake/draw.c
@@ -1,0 +1,902 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+
+// draw.c -- this is the only file outside the refresh that touches the
+// vid buffer
+
+#include "quakedef.h"
+
+typedef struct {
+	vrect_t	rect;
+	int		width;
+	int		height;
+	byte	*ptexbytes;
+	int		rowbytes;
+} rectdesc_t;
+
+static rectdesc_t	r_rectdesc;
+
+byte		*draw_chars;				// 8*8 graphic characters
+qpic_t		*draw_disc;
+qpic_t		*draw_backtile;
+
+//=============================================================================
+/* Support Routines */
+
+typedef struct cachepic_s
+{
+	char		name[MAX_QPATH];
+	cache_user_t	cache;
+} cachepic_t;
+
+#define	MAX_CACHED_PICS		128
+cachepic_t	menu_cachepics[MAX_CACHED_PICS];
+int			menu_numcachepics;
+
+
+qpic_t	*Draw_PicFromWad (char *name)
+{
+	return W_GetLumpName (name);
+}
+
+/*
+================
+Draw_CachePic
+================
+*/
+qpic_t	*Draw_CachePic (char *path)
+{
+	cachepic_t	*pic;
+	int			i;
+	qpic_t		*dat;
+	
+	for (pic=menu_cachepics, i=0 ; i<menu_numcachepics ; pic++, i++)
+		if (!strcmp (path, pic->name))
+			break;
+
+	if (i == menu_numcachepics)
+	{
+		if (menu_numcachepics == MAX_CACHED_PICS)
+			Sys_Error ("menu_numcachepics == MAX_CACHED_PICS");
+		menu_numcachepics++;
+		strcpy (pic->name, path);
+	}
+
+	dat = Cache_Check (&pic->cache);
+
+	if (dat)
+		return dat;
+
+//
+// load the pic from disk
+//
+	COM_LoadCacheFile (path, &pic->cache);
+	
+	dat = (qpic_t *)pic->cache.data;
+	if (!dat)
+	{
+		Sys_Error ("Draw_CachePic: failed to load %s", path);
+	}
+
+	SwapPic (dat);
+
+	return dat;
+}
+
+
+
+/*
+===============
+Draw_Init
+===============
+*/
+void Draw_Init (void)
+{
+	int		i;
+
+	draw_chars = W_GetLumpName ("conchars");
+	draw_disc = W_GetLumpName ("disc");
+	draw_backtile = W_GetLumpName ("backtile");
+
+	r_rectdesc.width = draw_backtile->width;
+	r_rectdesc.height = draw_backtile->height;
+	r_rectdesc.ptexbytes = draw_backtile->data;
+	r_rectdesc.rowbytes = draw_backtile->width;
+}
+
+
+
+/*
+================
+Draw_Character
+
+Draws one 8*8 graphics character with 0 being transparent.
+It can be clipped to the top of the screen to allow the console to be
+smoothly scrolled off.
+================
+*/
+void Draw_Character (int x, int y, int num)
+{
+	byte			*dest;
+	byte			*source;
+	unsigned short	*pusdest;
+	int				drawline;	
+	int				row, col;
+
+	num &= 255;
+	
+	if (y <= -8)
+		return;			// totally off screen
+
+#ifdef PARANOID
+	if (y > vid.height - 8 || x < 0 || x > vid.width - 8)
+		Sys_Error ("Con_DrawCharacter: (%i, %i)", x, y);
+	if (num < 0 || num > 255)
+		Sys_Error ("Con_DrawCharacter: char %i", num);
+#endif
+
+	row = num>>4;
+	col = num&15;
+	source = draw_chars + (row<<10) + (col<<3);
+
+	if (y < 0)
+	{	// clipped
+		drawline = 8 + y;
+		source -= 128*y;
+		y = 0;
+	}
+	else
+		drawline = 8;
+
+
+	if (r_pixbytes == 1)
+	{
+		dest = vid.conbuffer + y*vid.conrowbytes + x;
+	
+		while (drawline--)
+		{
+			if (source[0])
+				dest[0] = source[0];
+			if (source[1])
+				dest[1] = source[1];
+			if (source[2])
+				dest[2] = source[2];
+			if (source[3])
+				dest[3] = source[3];
+			if (source[4])
+				dest[4] = source[4];
+			if (source[5])
+				dest[5] = source[5];
+			if (source[6])
+				dest[6] = source[6];
+			if (source[7])
+				dest[7] = source[7];
+			source += 128;
+			dest += vid.conrowbytes;
+		}
+	}
+	else
+	{
+	// FIXME: pre-expand to native format?
+		pusdest = (unsigned short *)
+				((byte *)vid.conbuffer + y*vid.conrowbytes + (x<<1));
+
+		while (drawline--)
+		{
+			if (source[0])
+				pusdest[0] = d_8to16table[source[0]];
+			if (source[1])
+				pusdest[1] = d_8to16table[source[1]];
+			if (source[2])
+				pusdest[2] = d_8to16table[source[2]];
+			if (source[3])
+				pusdest[3] = d_8to16table[source[3]];
+			if (source[4])
+				pusdest[4] = d_8to16table[source[4]];
+			if (source[5])
+				pusdest[5] = d_8to16table[source[5]];
+			if (source[6])
+				pusdest[6] = d_8to16table[source[6]];
+			if (source[7])
+				pusdest[7] = d_8to16table[source[7]];
+
+			source += 128;
+			pusdest += (vid.conrowbytes >> 1);
+		}
+	}
+}
+
+/*
+================
+Draw_String
+================
+*/
+void Draw_String (int x, int y, char *str)
+{
+	while (*str)
+	{
+		Draw_Character (x, y, *str);
+		str++;
+		x += 8;
+	}
+}
+
+/*
+================
+Draw_DebugChar
+
+Draws a single character directly to the upper right corner of the screen.
+This is for debugging lockups by drawing different chars in different parts
+of the code.
+================
+*/
+void Draw_DebugChar (char num)
+{
+	byte			*dest;
+	byte			*source;
+	int				drawline;	
+	extern byte		*draw_chars;
+	int				row, col;
+
+	if (!vid.direct)
+		return;		// don't have direct FB access, so no debugchars...
+
+	drawline = 8;
+
+	row = num>>4;
+	col = num&15;
+	source = draw_chars + (row<<10) + (col<<3);
+
+	dest = vid.direct + 312;
+
+	while (drawline--)
+	{
+		dest[0] = source[0];
+		dest[1] = source[1];
+		dest[2] = source[2];
+		dest[3] = source[3];
+		dest[4] = source[4];
+		dest[5] = source[5];
+		dest[6] = source[6];
+		dest[7] = source[7];
+		source += 128;
+		dest += 320;
+	}
+}
+
+/*
+=============
+Draw_Pic
+=============
+*/
+void Draw_Pic (int x, int y, qpic_t *pic)
+{
+	byte			*dest, *source;
+	unsigned short	*pusdest;
+	int				v, u;
+
+	if ((x < 0) ||
+		(x + pic->width > vid.width) ||
+		(y < 0) ||
+		(y + pic->height > vid.height))
+	{
+		Sys_Error ("Draw_Pic: bad coordinates");
+	}
+
+	source = pic->data;
+
+	if (r_pixbytes == 1)
+	{
+		dest = vid.buffer + y * vid.rowbytes + x;
+
+		for (v=0 ; v<pic->height ; v++)
+		{
+			Q_memcpy (dest, source, pic->width);
+			dest += vid.rowbytes;
+			source += pic->width;
+		}
+	}
+	else
+	{
+	// FIXME: pretranslate at load time?
+		pusdest = (unsigned short *)vid.buffer + y * (vid.rowbytes >> 1) + x;
+
+		for (v=0 ; v<pic->height ; v++)
+		{
+			for (u=0 ; u<pic->width ; u++)
+			{
+				pusdest[u] = d_8to16table[source[u]];
+			}
+
+			pusdest += vid.rowbytes >> 1;
+			source += pic->width;
+		}
+	}
+}
+
+
+/*
+=============
+Draw_TransPic
+=============
+*/
+void Draw_TransPic (int x, int y, qpic_t *pic)
+{
+	byte	*dest, *source, tbyte;
+	unsigned short	*pusdest;
+	int				v, u;
+
+	if (x < 0 || (unsigned)(x + pic->width) > vid.width || y < 0 ||
+		 (unsigned)(y + pic->height) > vid.height)
+	{
+		Sys_Error ("Draw_TransPic: bad coordinates");
+	}
+		
+	source = pic->data;
+
+	if (r_pixbytes == 1)
+	{
+		dest = vid.buffer + y * vid.rowbytes + x;
+
+		if (pic->width & 7)
+		{	// general
+			for (v=0 ; v<pic->height ; v++)
+			{
+				for (u=0 ; u<pic->width ; u++)
+					if ( (tbyte=source[u]) != TRANSPARENT_COLOR)
+						dest[u] = tbyte;
+	
+				dest += vid.rowbytes;
+				source += pic->width;
+			}
+		}
+		else
+		{	// unwound
+			for (v=0 ; v<pic->height ; v++)
+			{
+				for (u=0 ; u<pic->width ; u+=8)
+				{
+					if ( (tbyte=source[u]) != TRANSPARENT_COLOR)
+						dest[u] = tbyte;
+					if ( (tbyte=source[u+1]) != TRANSPARENT_COLOR)
+						dest[u+1] = tbyte;
+					if ( (tbyte=source[u+2]) != TRANSPARENT_COLOR)
+						dest[u+2] = tbyte;
+					if ( (tbyte=source[u+3]) != TRANSPARENT_COLOR)
+						dest[u+3] = tbyte;
+					if ( (tbyte=source[u+4]) != TRANSPARENT_COLOR)
+						dest[u+4] = tbyte;
+					if ( (tbyte=source[u+5]) != TRANSPARENT_COLOR)
+						dest[u+5] = tbyte;
+					if ( (tbyte=source[u+6]) != TRANSPARENT_COLOR)
+						dest[u+6] = tbyte;
+					if ( (tbyte=source[u+7]) != TRANSPARENT_COLOR)
+						dest[u+7] = tbyte;
+				}
+				dest += vid.rowbytes;
+				source += pic->width;
+			}
+		}
+	}
+	else
+	{
+	// FIXME: pretranslate at load time?
+		pusdest = (unsigned short *)vid.buffer + y * (vid.rowbytes >> 1) + x;
+
+		for (v=0 ; v<pic->height ; v++)
+		{
+			for (u=0 ; u<pic->width ; u++)
+			{
+				tbyte = source[u];
+
+				if (tbyte != TRANSPARENT_COLOR)
+				{
+					pusdest[u] = d_8to16table[tbyte];
+				}
+			}
+
+			pusdest += vid.rowbytes >> 1;
+			source += pic->width;
+		}
+	}
+}
+
+
+/*
+=============
+Draw_TransPicTranslate
+=============
+*/
+void Draw_TransPicTranslate (int x, int y, qpic_t *pic, byte *translation)
+{
+	byte	*dest, *source, tbyte;
+	unsigned short	*pusdest;
+	int				v, u;
+
+	if (x < 0 || (unsigned)(x + pic->width) > vid.width || y < 0 ||
+		 (unsigned)(y + pic->height) > vid.height)
+	{
+		Sys_Error ("Draw_TransPic: bad coordinates");
+	}
+		
+	source = pic->data;
+
+	if (r_pixbytes == 1)
+	{
+		dest = vid.buffer + y * vid.rowbytes + x;
+
+		if (pic->width & 7)
+		{	// general
+			for (v=0 ; v<pic->height ; v++)
+			{
+				for (u=0 ; u<pic->width ; u++)
+					if ( (tbyte=source[u]) != TRANSPARENT_COLOR)
+						dest[u] = translation[tbyte];
+
+				dest += vid.rowbytes;
+				source += pic->width;
+			}
+		}
+		else
+		{	// unwound
+			for (v=0 ; v<pic->height ; v++)
+			{
+				for (u=0 ; u<pic->width ; u+=8)
+				{
+					if ( (tbyte=source[u]) != TRANSPARENT_COLOR)
+						dest[u] = translation[tbyte];
+					if ( (tbyte=source[u+1]) != TRANSPARENT_COLOR)
+						dest[u+1] = translation[tbyte];
+					if ( (tbyte=source[u+2]) != TRANSPARENT_COLOR)
+						dest[u+2] = translation[tbyte];
+					if ( (tbyte=source[u+3]) != TRANSPARENT_COLOR)
+						dest[u+3] = translation[tbyte];
+					if ( (tbyte=source[u+4]) != TRANSPARENT_COLOR)
+						dest[u+4] = translation[tbyte];
+					if ( (tbyte=source[u+5]) != TRANSPARENT_COLOR)
+						dest[u+5] = translation[tbyte];
+					if ( (tbyte=source[u+6]) != TRANSPARENT_COLOR)
+						dest[u+6] = translation[tbyte];
+					if ( (tbyte=source[u+7]) != TRANSPARENT_COLOR)
+						dest[u+7] = translation[tbyte];
+				}
+				dest += vid.rowbytes;
+				source += pic->width;
+			}
+		}
+	}
+	else
+	{
+	// FIXME: pretranslate at load time?
+		pusdest = (unsigned short *)vid.buffer + y * (vid.rowbytes >> 1) + x;
+
+		for (v=0 ; v<pic->height ; v++)
+		{
+			for (u=0 ; u<pic->width ; u++)
+			{
+				tbyte = source[u];
+
+				if (tbyte != TRANSPARENT_COLOR)
+				{
+					pusdest[u] = d_8to16table[tbyte];
+				}
+			}
+
+			pusdest += vid.rowbytes >> 1;
+			source += pic->width;
+		}
+	}
+}
+
+
+void Draw_CharToConback (int num, byte *dest)
+{
+	int		row, col;
+	byte	*source;
+	int		drawline;
+	int		x;
+
+	row = num>>4;
+	col = num&15;
+	source = draw_chars + (row<<10) + (col<<3);
+
+	drawline = 8;
+
+	while (drawline--)
+	{
+		for (x=0 ; x<8 ; x++)
+			if (source[x])
+				dest[x] = 0x60 + source[x];
+		source += 128;
+		dest += 320;
+	}
+
+}
+
+/*
+================
+Draw_ConsoleBackground
+
+================
+*/
+void Draw_ConsoleBackground (int lines)
+{
+	int				x, y, v;
+	byte			*src, *dest;
+	unsigned short	*pusdest;
+	int				f, fstep;
+	qpic_t			*conback;
+	char			ver[100];
+
+	conback = Draw_CachePic ("gfx/conback.lmp");
+
+// hack the version number directly into the pic
+#ifdef _WIN32
+	sprintf (ver, "(WinQuake) %4.2f", (float)VERSION);
+	dest = conback->data + 320*186 + 320 - 11 - 8*strlen(ver);
+#elif defined(X11)
+	sprintf (ver, "(X11 Quake %2.2f) %4.2f", (float)X11_VERSION, (float)VERSION);
+	dest = conback->data + 320*186 + 320 - 11 - 8*strlen(ver);
+#elif defined(__linux__)
+	sprintf (ver, "(Linux Quake %2.2f) %4.2f", (float)LINUX_VERSION, (float)VERSION);
+	dest = conback->data + 320*186 + 320 - 11 - 8*strlen(ver);
+#else
+	dest = conback->data + 320 - 43 + 320*186;
+	sprintf (ver, "%4.2f", VERSION);
+#endif
+
+	for (x=0 ; x<strlen(ver) ; x++)
+		Draw_CharToConback (ver[x], dest+(x<<3));
+	
+// draw the pic
+	if (r_pixbytes == 1)
+	{
+		dest = vid.conbuffer;
+
+		for (y=0 ; y<lines ; y++, dest += vid.conrowbytes)
+		{
+			v = (vid.conheight - lines + y)*200/vid.conheight;
+			src = conback->data + v*320;
+			if (vid.conwidth == 320)
+				memcpy (dest, src, vid.conwidth);
+			else
+			{
+				f = 0;
+				fstep = 320*0x10000/vid.conwidth;
+				for (x=0 ; x<vid.conwidth ; x+=4)
+				{
+					dest[x] = src[f>>16];
+					f += fstep;
+					dest[x+1] = src[f>>16];
+					f += fstep;
+					dest[x+2] = src[f>>16];
+					f += fstep;
+					dest[x+3] = src[f>>16];
+					f += fstep;
+				}
+			}
+		}
+	}
+	else
+	{
+		pusdest = (unsigned short *)vid.conbuffer;
+
+		for (y=0 ; y<lines ; y++, pusdest += (vid.conrowbytes >> 1))
+		{
+		// FIXME: pre-expand to native format?
+		// FIXME: does the endian switching go away in production?
+			v = (vid.conheight - lines + y)*200/vid.conheight;
+			src = conback->data + v*320;
+			f = 0;
+			fstep = 320*0x10000/vid.conwidth;
+			for (x=0 ; x<vid.conwidth ; x+=4)
+			{
+				pusdest[x] = d_8to16table[src[f>>16]];
+				f += fstep;
+				pusdest[x+1] = d_8to16table[src[f>>16]];
+				f += fstep;
+				pusdest[x+2] = d_8to16table[src[f>>16]];
+				f += fstep;
+				pusdest[x+3] = d_8to16table[src[f>>16]];
+				f += fstep;
+			}
+		}
+	}
+}
+
+
+/*
+==============
+R_DrawRect8
+==============
+*/
+void R_DrawRect8 (vrect_t *prect, int rowbytes, byte *psrc,
+	int transparent)
+{
+	byte	t;
+	int		i, j, srcdelta, destdelta;
+	byte	*pdest;
+
+	pdest = vid.buffer + (prect->y * vid.rowbytes) + prect->x;
+
+	srcdelta = rowbytes - prect->width;
+	destdelta = vid.rowbytes - prect->width;
+
+	if (transparent)
+	{
+		for (i=0 ; i<prect->height ; i++)
+		{
+			for (j=0 ; j<prect->width ; j++)
+			{
+				t = *psrc;
+				if (t != TRANSPARENT_COLOR)
+				{
+					*pdest = t;
+				}
+
+				psrc++;
+				pdest++;
+			}
+
+			psrc += srcdelta;
+			pdest += destdelta;
+		}
+	}
+	else
+	{
+		for (i=0 ; i<prect->height ; i++)
+		{
+			memcpy (pdest, psrc, prect->width);
+			psrc += rowbytes;
+			pdest += vid.rowbytes;
+		}
+	}
+}
+
+
+/*
+==============
+R_DrawRect16
+==============
+*/
+void R_DrawRect16 (vrect_t *prect, int rowbytes, byte *psrc,
+	int transparent)
+{
+	byte			t;
+	int				i, j, srcdelta, destdelta;
+	unsigned short	*pdest;
+
+// FIXME: would it be better to pre-expand native-format versions?
+
+	pdest = (unsigned short *)vid.buffer +
+			(prect->y * (vid.rowbytes >> 1)) + prect->x;
+
+	srcdelta = rowbytes - prect->width;
+	destdelta = (vid.rowbytes >> 1) - prect->width;
+
+	if (transparent)
+	{
+		for (i=0 ; i<prect->height ; i++)
+		{
+			for (j=0 ; j<prect->width ; j++)
+			{
+				t = *psrc;
+				if (t != TRANSPARENT_COLOR)
+				{
+					*pdest = d_8to16table[t];
+				}
+
+				psrc++;
+				pdest++;
+			}
+
+			psrc += srcdelta;
+			pdest += destdelta;
+		}
+	}
+	else
+	{
+		for (i=0 ; i<prect->height ; i++)
+		{
+			for (j=0 ; j<prect->width ; j++)
+			{
+				*pdest = d_8to16table[*psrc];
+				psrc++;
+				pdest++;
+			}
+
+			psrc += srcdelta;
+			pdest += destdelta;
+		}
+	}
+}
+
+
+/*
+=============
+Draw_TileClear
+
+This repeats a 64*64 tile graphic to fill the screen around a sized down
+refresh window.
+=============
+*/
+void Draw_TileClear (int x, int y, int w, int h)
+{
+	int				width, height, tileoffsetx, tileoffsety;
+	byte			*psrc;
+	vrect_t			vr;
+
+	r_rectdesc.rect.x = x;
+	r_rectdesc.rect.y = y;
+	r_rectdesc.rect.width = w;
+	r_rectdesc.rect.height = h;
+
+	vr.y = r_rectdesc.rect.y;
+	height = r_rectdesc.rect.height;
+
+	tileoffsety = vr.y % r_rectdesc.height;
+
+	while (height > 0)
+	{
+		vr.x = r_rectdesc.rect.x;
+		width = r_rectdesc.rect.width;
+
+		if (tileoffsety != 0)
+			vr.height = r_rectdesc.height - tileoffsety;
+		else
+			vr.height = r_rectdesc.height;
+
+		if (vr.height > height)
+			vr.height = height;
+
+		tileoffsetx = vr.x % r_rectdesc.width;
+
+		while (width > 0)
+		{
+			if (tileoffsetx != 0)
+				vr.width = r_rectdesc.width - tileoffsetx;
+			else
+				vr.width = r_rectdesc.width;
+
+			if (vr.width > width)
+				vr.width = width;
+
+			psrc = r_rectdesc.ptexbytes +
+					(tileoffsety * r_rectdesc.rowbytes) + tileoffsetx;
+
+			if (r_pixbytes == 1)
+			{
+				R_DrawRect8 (&vr, r_rectdesc.rowbytes, psrc, 0);
+			}
+			else
+			{
+				R_DrawRect16 (&vr, r_rectdesc.rowbytes, psrc, 0);
+			}
+
+			vr.x += vr.width;
+			width -= vr.width;
+			tileoffsetx = 0;	// only the left tile can be left-clipped
+		}
+
+		vr.y += vr.height;
+		height -= vr.height;
+		tileoffsety = 0;		// only the top tile can be top-clipped
+	}
+}
+
+
+/*
+=============
+Draw_Fill
+
+Fills a box of pixels with a single color
+=============
+*/
+void Draw_Fill (int x, int y, int w, int h, int c)
+{
+	byte			*dest;
+	unsigned short	*pusdest;
+	unsigned		uc;
+	int				u, v;
+
+	if (r_pixbytes == 1)
+	{
+		dest = vid.buffer + y*vid.rowbytes + x;
+		for (v=0 ; v<h ; v++, dest += vid.rowbytes)
+			for (u=0 ; u<w ; u++)
+				dest[u] = c;
+	}
+	else
+	{
+		uc = d_8to16table[c];
+
+		pusdest = (unsigned short *)vid.buffer + y * (vid.rowbytes >> 1) + x;
+		for (v=0 ; v<h ; v++, pusdest += (vid.rowbytes >> 1))
+			for (u=0 ; u<w ; u++)
+				pusdest[u] = uc;
+	}
+}
+//=============================================================================
+
+/*
+================
+Draw_FadeScreen
+
+================
+*/
+void Draw_FadeScreen (void)
+{
+	int			x,y;
+	byte		*pbuf;
+
+	VID_UnlockBuffer ();
+	S_ExtraUpdate ();
+	VID_LockBuffer ();
+
+	for (y=0 ; y<vid.height ; y++)
+	{
+		int	t;
+
+		pbuf = (byte *)(vid.buffer + vid.rowbytes*y);
+		t = (y & 1) << 1;
+
+		for (x=0 ; x<vid.width ; x++)
+		{
+			if ((x & 3) != t)
+				pbuf[x] = 0;
+		}
+	}
+
+	VID_UnlockBuffer ();
+	S_ExtraUpdate ();
+	VID_LockBuffer ();
+}
+
+//=============================================================================
+
+/*
+================
+Draw_BeginDisc
+
+Draws the little blue disc in the corner of the screen.
+Call before beginning any disc IO.
+================
+*/
+void Draw_BeginDisc (void)
+{
+
+	D_BeginDirectRect (vid.width - 24, 0, draw_disc->data, 24, 24);
+}
+
+
+/*
+================
+Draw_EndDisc
+
+Erases the disc icon.
+Call after completing any disc IO
+================
+*/
+void Draw_EndDisc (void)
+{
+
+	D_EndDirectRect (vid.width - 24, 0, 24, 24);
+}
+
--- /dev/null
+++ b/WinQuake/draw.h
@@ -1,0 +1,40 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+
+// draw.h -- these are the only functions outside the refresh allowed
+// to touch the vid buffer
+
+extern	qpic_t		*draw_disc;	// also used on sbar
+
+void Draw_Init (void);
+void Draw_Character (int x, int y, int num);
+void Draw_DebugChar (char num);
+void Draw_Pic (int x, int y, qpic_t *pic);
+void Draw_TransPic (int x, int y, qpic_t *pic);
+void Draw_TransPicTranslate (int x, int y, qpic_t *pic, byte *translation);
+void Draw_ConsoleBackground (int lines);
+void Draw_BeginDisc (void);
+void Draw_EndDisc (void);
+void Draw_TileClear (int x, int y, int w, int h);
+void Draw_Fill (int x, int y, int w, int h, int c);
+void Draw_FadeScreen (void);
+void Draw_String (int x, int y, char *str);
+qpic_t *Draw_PicFromWad (char *name);
+qpic_t *Draw_CachePic (char *path);
--- /dev/null
+++ b/WinQuake/dxsdk/SDK/INC/D3D.H
@@ -1,0 +1,392 @@
+/*==========================================================================;
+ *
+ *  Copyright (C) 1995-1996 Microsoft Corporation.  All Rights Reserved.
+ *
+ *  File:       d3d.h
+ *  Content:    Direct3D include file
+ *
+ ***************************************************************************/
+
+#ifndef _D3D_H_
+#define _D3D_H_
+
+#include <stdlib.h>
+
+#ifdef _WIN32
+#define COM_NO_WINDOWS_H
+#include <objbase.h>
+#else
+#include "d3dcom.h"
+#endif
+
+#ifdef _WIN32
+#define D3DAPI WINAPI
+#else
+#define D3DAPI
+#endif
+
+/*
+ * Interface IID's
+ */
+#if defined( _WIN32 ) && !defined( _NO_COM)
+DEFINE_GUID( IID_IDirect3D,             0x3BBA0080,0x2421,0x11CF,0xA3,0x1A,0x00,0xAA,0x00,0xB9,0x33,0x56 );
+DEFINE_GUID( IID_IDirect3DTexture,      0x2CDCD9E0,0x25A0,0x11CF,0xA3,0x1A,0x00,0xAA,0x00,0xB9,0x33,0x56 );
+DEFINE_GUID( IID_IDirect3DLight,        0x4417C142,0x33AD,0x11CF,0x81,0x6F,0x00,0x00,0xC0,0x20,0x15,0x6E );
+DEFINE_GUID( IID_IDirect3DMaterial,     0x4417C144,0x33AD,0x11CF,0x81,0x6F,0x00,0x00,0xC0,0x20,0x15,0x6E );
+DEFINE_GUID( IID_IDirect3DExecuteBuffer,0x4417C145,0x33AD,0x11CF,0x81,0x6F,0x00,0x00,0xC0,0x20,0x15,0x6E );
+DEFINE_GUID( IID_IDirect3DViewport,     0x4417C146,0x33AD,0x11CF,0x81,0x6F,0x00,0x00,0xC0,0x20,0x15,0x6E );
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Data structures
+ */
+#ifdef __cplusplus
+
+/* 'struct' not 'class' per the way DECLARE_INTERFACE_ is defined */
+struct IDirect3D;
+struct IDirect3DDevice;
+struct IDirect3DExecuteBuffer;
+struct IDirect3DLight;
+struct IDirect3DMaterial;
+struct IDirect3DTexture;
+struct IDirect3DViewport;
+typedef struct IDirect3D                *LPDIRECT3D;
+typedef struct IDirect3DDevice          *LPDIRECT3DDEVICE;
+typedef struct IDirect3DExecuteBuffer   *LPDIRECT3DEXECUTEBUFFER;
+typedef struct IDirect3DLight           *LPDIRECT3DLIGHT;
+typedef struct IDirect3DMaterial        *LPDIRECT3DMATERIAL;
+typedef struct IDirect3DTexture         *LPDIRECT3DTEXTURE;
+typedef struct IDirect3DViewport        *LPDIRECT3DVIEWPORT;
+
+#else
+
+typedef struct IDirect3D                *LPDIRECT3D;
+typedef struct IDirect3DDevice          *LPDIRECT3DDEVICE;
+typedef struct IDirect3DExecuteBuffer   *LPDIRECT3DEXECUTEBUFFER;
+typedef struct IDirect3DLight           *LPDIRECT3DLIGHT;
+typedef struct IDirect3DMaterial        *LPDIRECT3DMATERIAL;
+typedef struct IDirect3DTexture         *LPDIRECT3DTEXTURE;
+typedef struct IDirect3DViewport        *LPDIRECT3DVIEWPORT;
+
+#endif
+
+#include "d3dtypes.h"
+#include "d3dcaps.h"
+
+/*
+ * IDirect3D
+ */
+#undef INTERFACE
+#define INTERFACE IDirect3D
+DECLARE_INTERFACE_(IDirect3D, IUnknown)
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID* ppvObj) PURE;
+    STDMETHOD_(ULONG, AddRef) (THIS) PURE;
+    STDMETHOD_(ULONG, Release) (THIS) PURE;
+    /*** IDirect3D methods ***/
+    STDMETHOD(Initialize) (THIS_ REFIID) PURE;
+    STDMETHOD(EnumDevices)(THIS_ LPD3DENUMDEVICESCALLBACK, LPVOID) PURE;
+    STDMETHOD(CreateLight) (THIS_ LPDIRECT3DLIGHT*, IUnknown*) PURE;
+    STDMETHOD(CreateMaterial) (THIS_ LPDIRECT3DMATERIAL*, IUnknown*) PURE;
+    STDMETHOD(CreateViewport) (THIS_ LPDIRECT3DVIEWPORT*, IUnknown*) PURE;
+    STDMETHOD(FindDevice)(THIS_ LPD3DFINDDEVICESEARCH, LPD3DFINDDEVICERESULT) PURE;
+};
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirect3D_QueryInterface(p, a, b)         (p)->lpVtbl->QueryInterface(p, a, b)
+#define IDirect3D_AddRef(p)                       (p)->lpVtbl->AddRef(p)
+#define IDirect3D_Release(p)                      (p)->lpVtbl->Release(p)
+#define IDirect3D_Initialize(p, a)                (p)->lpVtbl->Initialize(p, a)
+#define IDirect3D_EnumDevices(p, a, b)            (p)->lpVtbl->EnumDevices(p, a, b)
+#define IDirect3D_CreateLight(p, a, b)            (p)->lpVtbl->CreateLight(p, a, b)
+#define IDirect3D_CreateMaterial(p, a, b)         (p)->lpVtbl->CreateMaterial(p, a, b)
+#define IDirect3D_CreateViewport(p, a, b)         (p)->lpVtbl->CreateViewport(p, a, b)
+#define IDirect3D_FindDevice(p, a, b)             (p)->lpVtbl->FindDevice(p, a, b)
+#endif
+
+/*
+ * IDirect3DDevice
+ */
+#undef INTERFACE
+#define INTERFACE IDirect3DDevice
+DECLARE_INTERFACE_(IDirect3DDevice, IUnknown)
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID* ppvObj) PURE;
+    STDMETHOD_(ULONG, AddRef) (THIS) PURE;
+    STDMETHOD_(ULONG, Release) (THIS) PURE;
+    /*** IDirect3DDevice methods ***/
+    STDMETHOD(Initialize) (THIS_ LPDIRECT3D, LPGUID, LPD3DDEVICEDESC) PURE;
+    STDMETHOD(GetCaps) (THIS_ LPD3DDEVICEDESC, LPD3DDEVICEDESC) PURE;
+    STDMETHOD(SwapTextureHandles) (THIS_ LPDIRECT3DTEXTURE, LPDIRECT3DTEXTURE) PURE;
+    STDMETHOD(CreateExecuteBuffer) (THIS_ LPD3DEXECUTEBUFFERDESC, LPDIRECT3DEXECUTEBUFFER*, IUnknown*) PURE;
+    STDMETHOD(GetStats) (THIS_ LPD3DSTATS) PURE;
+    STDMETHOD(Execute) (THIS_ LPDIRECT3DEXECUTEBUFFER, LPDIRECT3DVIEWPORT, DWORD) PURE;
+    STDMETHOD(AddViewport) (THIS_ LPDIRECT3DVIEWPORT) PURE;
+    STDMETHOD(DeleteViewport) (THIS_ LPDIRECT3DVIEWPORT) PURE;
+    STDMETHOD(NextViewport) (THIS_ LPDIRECT3DVIEWPORT, LPDIRECT3DVIEWPORT*, DWORD) PURE;
+    STDMETHOD(Pick) (THIS_ LPDIRECT3DEXECUTEBUFFER, LPDIRECT3DVIEWPORT, DWORD, LPD3DRECT) PURE;
+    STDMETHOD(GetPickRecords)(THIS_ LPDWORD, LPD3DPICKRECORD) PURE;
+    STDMETHOD(EnumTextureFormats) (THIS_ LPD3DENUMTEXTUREFORMATSCALLBACK, LPVOID) PURE;
+    STDMETHOD(CreateMatrix) (THIS_ LPD3DMATRIXHANDLE) PURE;
+    STDMETHOD(SetMatrix) (THIS_ D3DMATRIXHANDLE, LPD3DMATRIX) PURE;
+    STDMETHOD(GetMatrix) (THIS_ D3DMATRIXHANDLE, LPD3DMATRIX) PURE;
+    STDMETHOD(DeleteMatrix) (THIS_ D3DMATRIXHANDLE) PURE;
+    STDMETHOD_(HRESULT, BeginScene) (THIS) PURE;
+    STDMETHOD_(HRESULT, EndScene) (THIS) PURE;
+    STDMETHOD(GetDirect3D) (THIS_ LPDIRECT3D*) PURE;
+};
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirect3DDevice_QueryInterface(p, a, b)         (p)->lpVtbl->QueryInterface(p, a, b)
+#define IDirect3DDevice_AddRef(p)                       (p)->lpVtbl->AddRef(p)
+#define IDirect3DDevice_Release(p)                      (p)->lpVtbl->Release(p)
+#define IDirect3DDevice_Initialize(p, a, b, c)          (p)->lpVtbl->Initialize(p, a, b, c)
+#define IDirect3DDevice_GetCaps(p, a, b)                (p)->lpVtbl->GetCaps(p, a, b)
+#define IDirect3DDevice_SwapTextureHandles(p, a, b)     (p)->lpVtbl->SwapTextureHandles(p, a, b)
+#define IDirect3DDevice_CreateExecuteBuffer(p, a, b, c) (p)->lpVtbl->ExecuteBuffer(p, a, b, c)
+#define IDirect3DDevice_GetStats(p, a)                  (p)->lpVtbl->CreateViewport(p, a)
+#define IDirect3DDevice_Execute(p, a, b, c)             (p)->lpVtbl->Execute(p, a, b, c)
+#define IDirect3DDevice_AddViewport(p, a)               (p)->lpVtbl->AddViewport(p, a)
+#define IDirect3DDevice_DeleteViewport(p, a)            (p)->lpVtbl->DeleteViewport(p, a)
+#define IDirect3DDevice_NextViewport(p, a, b)           (p)->lpVtbl->NextViewport(p, a, b)
+#define IDirect3DDevice_Pick(p, a, b, c, d)             (p)->lpVtbl->Pick(p, a, b, c, d)
+#define IDirect3DDevice_GetPickRecords(p, a, b)         (p)->lpVtbl->GetPickRecords(p, a, b)
+#define IDirect3DDevice_EnumTextureFormats(p, a, b)     (p)->lpVtbl->EnumTextureFormats(p, a, b)
+#define IDirect3DDevice_CreateMatrix(p, a)              (p)->lpVtbl->CreateMatrix(p, a)
+#define IDirect3DDevice_SetMatrix(p, a, b)              (p)->lpVtbl->SetMatrix(p, a, b)
+#define IDirect3DDevice_GetMatrix(p, a, b)              (p)->lpVtbl->GetMatrix(p, a, b)
+#define IDirect3DDevice_DeleteMatrix(p, a)              (p)->lpVtbl->DeleteMatrix(p, a)
+#define IDirect3DDevice_BeginScene(p)                   (p)->lpVtbl->BeginScene(p)
+#define IDirect3DDevice_EndScene(p)                     (p)->lpVtbl->EndScene(p)
+#define IDirect3DDevice_GetDirect3D(p, a)               (p)->lpVtbl->GetDirect3D(p, a)
+#endif
+
+/*
+ * IDirect3DExecuteBuffer
+ */
+#undef INTERFACE
+#define INTERFACE IDirect3DExecuteBuffer
+DECLARE_INTERFACE_(IDirect3DExecuteBuffer, IUnknown)
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID* ppvObj) PURE;
+    STDMETHOD_(ULONG, AddRef) (THIS) PURE;
+    STDMETHOD_(ULONG, Release) (THIS) PURE;
+    /*** IDirect3DExecuteBuffer methods ***/
+    STDMETHOD(Initialize) (THIS_ LPDIRECT3DDEVICE, LPD3DEXECUTEBUFFERDESC) PURE;
+    STDMETHOD(Lock) (THIS_ LPD3DEXECUTEBUFFERDESC) PURE;
+    STDMETHOD_(HRESULT, Unlock) (THIS) PURE;
+    STDMETHOD(SetExecuteData) (THIS_ LPD3DEXECUTEDATA) PURE;
+    STDMETHOD(GetExecuteData) (THIS_ LPD3DEXECUTEDATA) PURE;
+    STDMETHOD(Validate) (THIS_ LPDWORD, LPD3DVALIDATECALLBACK, LPVOID, DWORD) PURE;
+    STDMETHOD(Optimize) (THIS_ DWORD) PURE;
+};
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirect3DExecuteBuffer_QueryInterface(p, a, b) (p)->lpVtbl->QueryInterface(p, a, b)
+#define IDirect3DExecuteBuffer_AddRef(p)               (p)->lpVtbl->AddRef(p)
+#define IDirect3DExecuteBuffer_Release(p)              (p)->lpVtbl->Release(p)
+#define IDirect3DExecuteBuffer_Initialize(p, a, b)     (p)->lpVtbl->Initialize(p, a, b)
+#define IDirect3DExecuteBuffer_Lock(p, a)              (p)->lpVtbl->Lock(p, a)
+#define IDirect3DExecuteBuffer_Unlock(p, a)            (p)->lpVtbl->Unlock(p)
+#define IDirect3DExecuteBuffer_SetExecuteData(p, a)    (p)->lpVtbl->SetExecuteData(p, a)
+#define IDirect3DExecuteBuffer_Validate(p, a, b, c, d) (p)->lpVtbl->Validata(p, a, b, c, d)
+#endif
+
+/*
+ * Flags for execute buffer calls
+ */
+#define D3DNEXT_NEXT    0x00000001l
+#define D3DNEXT_HEAD    0x00000002l
+#define D3DNEXT_TAIL    0x00000004l
+
+/*
+ * IDirect3DLight
+ */
+#undef INTERFACE
+#define INTERFACE IDirect3DLight
+DECLARE_INTERFACE_(IDirect3DLight, IUnknown)
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID* ppvObj) PURE;
+    STDMETHOD_(ULONG, AddRef) (THIS) PURE;
+    STDMETHOD_(ULONG, Release) (THIS) PURE;
+    /*** IDirect3DLight methods ***/
+    STDMETHOD(Initialize) (THIS_ LPDIRECT3D) PURE;
+    STDMETHOD(SetLight) (THIS_ LPD3DLIGHT) PURE;
+    STDMETHOD(GetLight) (THIS_ LPD3DLIGHT) PURE;
+};
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirect3DLight_QueryInterface(p, a, b) (p)->lpVtbl->QueryInterface(p, a, b)
+#define IDirect3DLight_AddRef(p)               (p)->lpVtbl->AddRef(p)
+#define IDirect3DLight_Release(p)              (p)->lpVtbl->Release(p)
+#define IDirect3DLight_Initialize(p, a)        (p)->lpVtbl->Initialize(p, a)
+#define IDirect3DLight_SetLight(p, a)          (p)->lpVtbl->SetLight(p, a)
+#define IDirect3DLight_GetLight(p, a)          (p)->lpVtbl->GetLight(p, a)
+#endif
+
+/*
+ * IDirect3DMaterial
+ */
+#undef INTERFACE
+#define INTERFACE IDirect3DMaterial
+DECLARE_INTERFACE_(IDirect3DMaterial, IUnknown)
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID* ppvObj) PURE;
+    STDMETHOD_(ULONG, AddRef) (THIS) PURE;
+    STDMETHOD_(ULONG, Release) (THIS) PURE;
+    /*** IDirect3DMaterial methods ***/
+    STDMETHOD(Initialize) (THIS_ LPDIRECT3D) PURE;
+    STDMETHOD(SetMaterial) (THIS_ LPD3DMATERIAL) PURE;
+    STDMETHOD(GetMaterial) (THIS_ LPD3DMATERIAL) PURE;
+    STDMETHOD(GetHandle) (THIS_ LPDIRECT3DDEVICE, LPD3DMATERIALHANDLE) PURE;
+    STDMETHOD_(HRESULT, Reserve) (THIS) PURE;
+    STDMETHOD_(HRESULT, Unreserve) (THIS) PURE;
+};
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirect3DMaterial_QueryInterface(p, a, b) (p)->lpVtbl->QueryInterface(p, a, b)
+#define IDirect3DMaterial_AddRef(p)               (p)->lpVtbl->AddRef(p)
+#define IDirect3DMaterial_Release(p)              (p)->lpVtbl->Release(p)
+#define IDirect3DMaterial_Initialize(p, a)        (p)->lpVtbl->Initialize(p, a)
+#define IDirect3DMaterial_SetMaterial(p, a)       (p)->lpVtbl->SetLight(p, a)
+#define IDirect3DMaterial_GetMaterial(p, a)       (p)->lpVtbl->GetLight(p, a)
+#define IDirect3DMaterial_GetHandle(p, a, b)      (p)->lpVtbl->GetHandle(p, a, b)
+#define IDirect3DMaterial_Reserve(p)              (p)->lpVtbl->Reserve(p)
+#define IDirect3DMaterial_Unreserve(p)            (p)->lpVtbl->Unreserve(p)
+#endif
+
+/*
+ * IDirect3DTexture
+ */
+#undef INTERFACE
+#define INTERFACE IDirect3DTexture
+DECLARE_INTERFACE_(IDirect3DTexture, IUnknown)
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID* ppvObj) PURE;
+    STDMETHOD_(ULONG, AddRef) (THIS) PURE;
+    STDMETHOD_(ULONG, Release) (THIS) PURE;
+    /*** IDirect3DTexture methods ***/
+    STDMETHOD(Initialize) (THIS_ LPDIRECT3DDEVICE, LPDIRECTDRAWSURFACE) PURE;
+    STDMETHOD(GetHandle) (THIS_ LPDIRECT3DDEVICE, LPD3DTEXTUREHANDLE) PURE;
+    STDMETHOD(PaletteChanged) (THIS_ DWORD, DWORD) PURE;
+    STDMETHOD(Load) (THIS_ LPDIRECT3DTEXTURE) PURE;
+    STDMETHOD_(HRESULT, Unload) (THIS) PURE;
+};
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirect3DTexture_QueryInterface(p, a, b) (p)->lpVtbl->QueryInterface(p, a, b)
+#define IDirect3DTexture_AddRef(p)               (p)->lpVtbl->AddRef(p)
+#define IDirect3DTexture_Release(p)              (p)->lpVtbl->Release(p)
+#define IDirect3DTexture_Initialize(p, a, b)     (p)->lpVtbl->Initialize(p, a, b)
+#define IDirect3DTexture_GetHandle(p, a, b)      (p)->lpVtbl->GetHandle(p, a, b)
+#define IDirect3DTexture_PaletteChanged(p, a, b) (p)->lpVtbl->PaletteChanged(p, a, b)
+#define IDirect3DTexture_Load(p, a)              (p)->lpVtbl->Load(p, a)
+#define IDirect3DTexture_Unload(p)               (p)->lpVtbl->Unload(p)
+#endif
+
+/*
+ * IDirect3DViewport
+ */
+#undef INTERFACE
+#define INTERFACE IDirect3DViewport
+DECLARE_INTERFACE_(IDirect3DViewport, IUnknown)
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID* ppvObj) PURE;
+    STDMETHOD_(ULONG, AddRef) (THIS) PURE;
+    STDMETHOD_(ULONG, Release) (THIS) PURE;
+    /*** IDirect3DViewport methods ***/
+    STDMETHOD(Initialize) (THIS_ LPDIRECT3D) PURE;
+    STDMETHOD(GetViewport) (THIS_ LPD3DVIEWPORT) PURE;
+    STDMETHOD(SetViewport) (THIS_ LPD3DVIEWPORT) PURE;
+    STDMETHOD(TransformVertices) (THIS_ DWORD, LPD3DTRANSFORMDATA, DWORD, LPDWORD) PURE;
+    STDMETHOD(LightElements) (THIS_ DWORD, LPD3DLIGHTDATA) PURE;
+    STDMETHOD(SetBackground) (THIS_ D3DMATERIALHANDLE) PURE;
+    STDMETHOD(GetBackground) (THIS_ LPD3DMATERIALHANDLE, LPBOOL) PURE;
+    STDMETHOD(SetBackgroundDepth) (THIS_ LPDIRECTDRAWSURFACE) PURE;
+    STDMETHOD(GetBackgroundDepth) (THIS_ LPDIRECTDRAWSURFACE*, LPBOOL) PURE;
+    STDMETHOD(Clear) (THIS_ DWORD, LPD3DRECT, DWORD) PURE;
+    STDMETHOD(AddLight) (THIS_ LPDIRECT3DLIGHT) PURE;
+    STDMETHOD(DeleteLight) (THIS_ LPDIRECT3DLIGHT) PURE;
+    STDMETHOD(NextLight) (THIS_ LPDIRECT3DLIGHT, LPDIRECT3DLIGHT*, DWORD) PURE;
+};
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirect3DViewport_QueryInterface(p, a, b)          (p)->lpVtbl->QueryInterface(p, a, b)
+#define IDirect3DViewport_AddRef(p)                        (p)->lpVtbl->AddRef(p)
+#define IDirect3DViewport_Release(p)                       (p)->lpVtbl->Release(p)
+#define IDirect3DViewport_Initialize(p, a)                 (p)->lpVtbl->Initialize(p, a)
+#define IDirect3DViewport_GetViewport(p, a)                (p)->lpVtbl->GetViewport(p, a)
+#define IDirect3DViewport_SetViewport(p, a)                (p)->lpVtbl->SetViewport(p, a)
+#define IDirect3DViewport_TransformVertices(p, a, b, c, d) (p)->lpVtbl->TransformVertices(p, a, b, c, d)
+#define IDirect3DViewport_LightElements(p, a, b)           (p)->lpVtbl->LightElements(p, a, b)
+#define IDirect3DViewport_SetBackground(p, a)              (p)->lpVtbl->SetBackground(p, a)
+#define IDirect3DViewport_GetBackground(p, a, b)           (p)->lpVtbl->GetBackground(p, a, b)
+#define IDirect3DViewport_Clear(p, a, b, c)                (p)->lpVtbl->Clear(p, a, b, c)
+#define IDirect3DViewport_AddLight(p, a)                   (p)->lpVtbl->AddLight(p, a)
+#define IDirect3DViewport_DeleteLight(p, a)                (p)->lpVtbl->DeleteLight(p, a)
+#define IDirect3DViewport_NextLight(p, a, b, c)            (p)->lpVtbl->NextLight(p, a, b, c)
+#endif
+
+/*
+ * Direct3D Errors
+ * DirectDraw error codes are used when errors not specified here.
+ */
+#define D3D_OK                          DD_OK
+#define D3DERR_BADMAJORVERSION          MAKE_DDHRESULT(700)
+#define D3DERR_BADMINORVERSION          MAKE_DDHRESULT(701)
+
+#define D3DERR_EXECUTE_CREATE_FAILED    MAKE_DDHRESULT(710)
+#define D3DERR_EXECUTE_DESTROY_FAILED   MAKE_DDHRESULT(711)
+#define D3DERR_EXECUTE_LOCK_FAILED      MAKE_DDHRESULT(712)
+#define D3DERR_EXECUTE_UNLOCK_FAILED    MAKE_DDHRESULT(713)
+#define D3DERR_EXECUTE_LOCKED           MAKE_DDHRESULT(714)
+#define D3DERR_EXECUTE_NOT_LOCKED       MAKE_DDHRESULT(715)
+
+#define D3DERR_EXECUTE_FAILED           MAKE_DDHRESULT(716)
+#define D3DERR_EXECUTE_CLIPPED_FAILED   MAKE_DDHRESULT(717)
+
+#define D3DERR_TEXTURE_NO_SUPPORT       MAKE_DDHRESULT(720)
+#define D3DERR_TEXTURE_CREATE_FAILED    MAKE_DDHRESULT(721)
+#define D3DERR_TEXTURE_DESTROY_FAILED   MAKE_DDHRESULT(722)
+#define D3DERR_TEXTURE_LOCK_FAILED      MAKE_DDHRESULT(723)
+#define D3DERR_TEXTURE_UNLOCK_FAILED    MAKE_DDHRESULT(724)
+#define D3DERR_TEXTURE_LOAD_FAILED      MAKE_DDHRESULT(725)
+#define D3DERR_TEXTURE_SWAP_FAILED      MAKE_DDHRESULT(726)
+#define D3DERR_TEXTURE_LOCKED           MAKE_DDHRESULT(727)
+#define D3DERR_TEXTURE_NOT_LOCKED       MAKE_DDHRESULT(728)
+#define D3DERR_TEXTURE_GETSURF_FAILED   MAKE_DDHRESULT(729)
+
+#define D3DERR_MATRIX_CREATE_FAILED     MAKE_DDHRESULT(730)
+#define D3DERR_MATRIX_DESTROY_FAILED    MAKE_DDHRESULT(731)
+#define D3DERR_MATRIX_SETDATA_FAILED    MAKE_DDHRESULT(732)
+#define D3DERR_MATRIX_GETDATA_FAILED    MAKE_DDHRESULT(733)
+#define D3DERR_SETVIEWPORTDATA_FAILED   MAKE_DDHRESULT(734)
+
+#define D3DERR_MATERIAL_CREATE_FAILED   MAKE_DDHRESULT(740)
+#define D3DERR_MATERIAL_DESTROY_FAILED  MAKE_DDHRESULT(741)
+#define D3DERR_MATERIAL_SETDATA_FAILED  MAKE_DDHRESULT(742)
+#define D3DERR_MATERIAL_GETDATA_FAILED  MAKE_DDHRESULT(743)
+
+#define D3DERR_LIGHT_SET_FAILED         MAKE_DDHRESULT(750)
+
+#define D3DERR_SCENE_IN_SCENE           MAKE_DDHRESULT(760)
+#define D3DERR_SCENE_NOT_IN_SCENE       MAKE_DDHRESULT(761)
+#define D3DERR_SCENE_BEGIN_FAILED       MAKE_DDHRESULT(762)
+#define D3DERR_SCENE_END_FAILED         MAKE_DDHRESULT(763)
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif /* _D3D_H_ */
--- /dev/null
+++ b/WinQuake/dxsdk/SDK/INC/D3DCAPS.H
@@ -1,0 +1,290 @@
+/*==========================================================================;
+ *
+ *  Copyright (C) 1995-1996 Microsoft Corporation.  All Rights Reserved.
+ *
+ *  File:       d3dcaps.h
+ *  Content:    Direct3D capabilities include file
+ *
+ ***************************************************************************/
+
+#ifndef _D3DCAPS_H
+#define _D3DCAPS_H
+
+/* 
+ *  Pull in DirectDraw include file automatically:
+ */
+#include <ddraw.h>
+
+#pragma pack(4)
+
+/* Description of capabilities of transform */
+
+typedef struct _D3DTRANSFORMCAPS {
+    DWORD dwSize;
+    DWORD dwCaps;
+} D3DTRANSFORMCAPS, *LPD3DTRANSFORMCAPS;
+
+#define D3DTRANSFORMCAPS_CLIP           0x00000001L /* Will clip whilst transforming */
+
+/* Description of capabilities of lighting */
+
+typedef struct _D3DLIGHTINGCAPS {
+    DWORD dwSize;
+    DWORD dwCaps;                   /* Lighting caps */
+    DWORD dwLightingModel;          /* Lighting model - RGB or mono */
+    DWORD dwNumLights;              /* Number of lights that can be handled */
+} D3DLIGHTINGCAPS, *LPD3DLIGHTINGCAPS;
+
+#define D3DLIGHTINGMODEL_RGB            0x00000001L
+#define D3DLIGHTINGMODEL_MONO           0x00000002L
+
+#define D3DLIGHTCAPS_POINT              0x00000001L /* Point lights supported */
+#define D3DLIGHTCAPS_SPOT               0x00000002L /* Spot lights supported */
+#define D3DLIGHTCAPS_DIRECTIONAL        0x00000004L /* Directional lights supported */
+#define D3DLIGHTCAPS_PARALLELPOINT      0x00000008L /* Parallel point lights supported */
+#define D3DLIGHTCAPS_GLSPOT             0x00000010L /* GL syle spot lights supported */
+
+/* Description of capabilities for each primitive type */
+
+typedef struct _D3DPrimCaps {
+    DWORD dwSize;
+    DWORD dwMiscCaps;                 /* Capability flags */
+    DWORD dwRasterCaps;
+    DWORD dwZCmpCaps;
+    DWORD dwSrcBlendCaps;
+    DWORD dwDestBlendCaps;
+    DWORD dwAlphaCmpCaps;
+    DWORD dwShadeCaps;
+    DWORD dwTextureCaps;
+    DWORD dwTextureFilterCaps;
+    DWORD dwTextureBlendCaps;
+    DWORD dwTextureAddressCaps;
+    DWORD dwStippleWidth;             /* maximum width and height of */
+    DWORD dwStippleHeight;            /* of supported stipple (up to 32x32) */
+} D3DPRIMCAPS, *LPD3DPRIMCAPS;
+
+/* D3DPRIMCAPS dwMiscCaps */
+
+#define D3DPMISCCAPS_MASKPLANES         0x00000001L
+#define D3DPMISCCAPS_MASKZ              0x00000002L
+#define D3DPMISCCAPS_LINEPATTERNREP     0x00000004L
+#define D3DPMISCCAPS_CONFORMANT         0x00000008L
+#define D3DPMISCCAPS_CULLNONE           0x00000010L
+#define D3DPMISCCAPS_CULLCW             0x00000020L
+#define D3DPMISCCAPS_CULLCCW            0x00000040L
+
+/* D3DPRIMCAPS dwRasterCaps */
+
+#define D3DPRASTERCAPS_DITHER           0x00000001L
+#define D3DPRASTERCAPS_ROP2             0x00000002L
+#define D3DPRASTERCAPS_XOR              0x00000004L
+#define D3DPRASTERCAPS_PAT              0x00000008L
+#define D3DPRASTERCAPS_ZTEST            0x00000010L
+#define D3DPRASTERCAPS_SUBPIXEL         0x00000020L
+#define D3DPRASTERCAPS_SUBPIXELX        0x00000040L
+#define D3DPRASTERCAPS_FOGVERTEX        0x00000080L
+#define D3DPRASTERCAPS_FOGTABLE         0x00000100L
+#define D3DPRASTERCAPS_STIPPLE          0x00000200L
+
+/* D3DPRIMCAPS dwZCmpCaps, dwAlphaCmpCaps */
+
+#define D3DPCMPCAPS_NEVER               0x00000001L
+#define D3DPCMPCAPS_LESS                0x00000002L
+#define D3DPCMPCAPS_EQUAL               0x00000004L
+#define D3DPCMPCAPS_LESSEQUAL           0x00000008L
+#define D3DPCMPCAPS_GREATER             0x00000010L
+#define D3DPCMPCAPS_NOTEQUAL            0x00000020L
+#define D3DPCMPCAPS_GREATEREQUAL        0x00000040L
+#define D3DPCMPCAPS_ALWAYS              0x00000080L
+
+/* D3DPRIMCAPS dwSourceBlendCaps, dwDestBlendCaps */
+
+#define D3DPBLENDCAPS_ZERO              0x00000001L
+#define D3DPBLENDCAPS_ONE               0x00000002L
+#define D3DPBLENDCAPS_SRCCOLOR          0x00000004L
+#define D3DPBLENDCAPS_INVSRCCOLOR       0x00000008L
+#define D3DPBLENDCAPS_SRCALPHA          0x00000010L
+#define D3DPBLENDCAPS_INVSRCALPHA       0x00000020L
+#define D3DPBLENDCAPS_DESTALPHA         0x00000040L
+#define D3DPBLENDCAPS_INVDESTALPHA      0x00000080L
+#define D3DPBLENDCAPS_DESTCOLOR         0x00000100L
+#define D3DPBLENDCAPS_INVDESTCOLOR      0x00000200L
+#define D3DPBLENDCAPS_SRCALPHASAT       0x00000400L
+#define D3DPBLENDCAPS_BOTHSRCALPHA      0x00000800L
+#define D3DPBLENDCAPS_BOTHINVSRCALPHA   0x00001000L
+
+/* D3DPRIMCAPS dwShadeCaps */
+
+#define D3DPSHADECAPS_COLORFLATMONO             0x00000001L
+#define D3DPSHADECAPS_COLORFLATRGB              0x00000002L
+#define D3DPSHADECAPS_COLORGOURAUDMONO          0x00000004L
+#define D3DPSHADECAPS_COLORGOURAUDRGB           0x00000008L
+#define D3DPSHADECAPS_COLORPHONGMONO            0x00000010L
+#define D3DPSHADECAPS_COLORPHONGRGB             0x00000020L
+
+#define D3DPSHADECAPS_SPECULARFLATMONO          0x00000040L
+#define D3DPSHADECAPS_SPECULARFLATRGB           0x00000080L
+#define D3DPSHADECAPS_SPECULARGOURAUDMONO       0x00000100L
+#define D3DPSHADECAPS_SPECULARGOURAUDRGB        0x00000200L
+#define D3DPSHADECAPS_SPECULARPHONGMONO         0x00000400L
+#define D3DPSHADECAPS_SPECULARPHONGRGB          0x00000800L
+
+#define D3DPSHADECAPS_ALPHAFLATBLEND            0x00001000L
+#define D3DPSHADECAPS_ALPHAFLATSTIPPLED         0x00002000L
+#define D3DPSHADECAPS_ALPHAGOURAUDBLEND         0x00004000L
+#define D3DPSHADECAPS_ALPHAGOURAUDSTIPPLED      0x00008000L
+#define D3DPSHADECAPS_ALPHAPHONGBLEND           0x00010000L
+#define D3DPSHADECAPS_ALPHAPHONGSTIPPLED        0x00020000L
+
+#define D3DPSHADECAPS_FOGFLAT                   0x00040000L
+#define D3DPSHADECAPS_FOGGOURAUD                0x00080000L
+#define D3DPSHADECAPS_FOGPHONG                  0x00100000L
+
+/* D3DPRIMCAPS dwTextureCaps */
+
+#define D3DPTEXTURECAPS_PERSPECTIVE     0x00000001L
+#define D3DPTEXTURECAPS_POW2            0x00000002L
+#define D3DPTEXTURECAPS_ALPHA           0x00000004L
+#define D3DPTEXTURECAPS_TRANSPARENCY    0x00000008L
+#define D3DPTEXTURECAPS_BORDER          0x00000010L
+#define D3DPTEXTURECAPS_SQUAREONLY      0x00000020L
+
+/* D3DPRIMCAPS dwTextureFilterCaps */
+
+#define D3DPTFILTERCAPS_NEAREST         0x00000001L
+#define D3DPTFILTERCAPS_LINEAR          0x00000002L
+#define D3DPTFILTERCAPS_MIPNEAREST      0x00000004L
+#define D3DPTFILTERCAPS_MIPLINEAR       0x00000008L
+#define D3DPTFILTERCAPS_LINEARMIPNEAREST 0x00000010L
+#define D3DPTFILTERCAPS_LINEARMIPLINEAR 0x00000020L
+
+/* D3DPRIMCAPS dwTextureBlendCaps */
+
+#define D3DPTBLENDCAPS_DECAL            0x00000001L
+#define D3DPTBLENDCAPS_MODULATE         0x00000002L
+#define D3DPTBLENDCAPS_DECALALPHA       0x00000004L
+#define D3DPTBLENDCAPS_MODULATEALPHA    0x00000008L
+#define D3DPTBLENDCAPS_DECALMASK        0x00000010L
+#define D3DPTBLENDCAPS_MODULATEMASK     0x00000020L
+#define D3DPTBLENDCAPS_COPY             0x00000040L
+
+/* D3DPRIMCAPS dwTextureAddressCaps */
+#define D3DPTADDRESSCAPS_WRAP           0x00000001L
+#define D3DPTADDRESSCAPS_MIRROR         0x00000002L
+#define D3DPTADDRESSCAPS_CLAMP          0x00000004L
+
+/*
+ * Description for a device.
+ * This is used to describe a device that is to be created or to query
+ * the current device.
+ */
+typedef struct _D3DDeviceDesc {
+    DWORD            dwSize;                 /* Size of D3DDEVICEDESC structure */
+    DWORD            dwFlags;                /* Indicates which fields have valid data */
+    D3DCOLORMODEL    dcmColorModel;          /* Color model of device */
+    DWORD            dwDevCaps;              /* Capabilities of device */
+    D3DTRANSFORMCAPS dtcTransformCaps;       /* Capabilities of transform */
+    BOOL             bClipping;              /* Device can do 3D clipping */
+    D3DLIGHTINGCAPS  dlcLightingCaps;        /* Capabilities of lighting */
+    D3DPRIMCAPS      dpcLineCaps;
+    D3DPRIMCAPS      dpcTriCaps;
+    DWORD            dwDeviceRenderBitDepth; /* One of DDBB_8, 16, etc.. */
+    DWORD            dwDeviceZBufferBitDepth;/* One of DDBD_16, 32, etc.. */
+    DWORD            dwMaxBufferSize;        /* Maximum execute buffer size */
+    DWORD            dwMaxVertexCount;       /* Maximum vertex count */
+} D3DDEVICEDESC, *LPD3DDEVICEDESC;
+
+typedef HRESULT (FAR PASCAL * LPD3DENUMDEVICESCALLBACK)(LPGUID lpGuid, LPSTR lpDeviceDescription, LPSTR lpDeviceName, LPD3DDEVICEDESC, LPD3DDEVICEDESC, LPVOID);
+
+/* D3DDEVICEDESC dwFlags indicating valid fields */
+
+#define D3DDD_COLORMODEL            0x00000001L /* dcmColorModel is valid */
+#define D3DDD_DEVCAPS               0x00000002L /* dwDevCaps is valid */
+#define D3DDD_TRANSFORMCAPS         0x00000004L /* dtcTransformCaps is valid */
+#define D3DDD_LIGHTINGCAPS          0x00000008L /* dlcLightingCaps is valid */
+#define D3DDD_BCLIPPING             0x00000010L /* bClipping is valid */
+#define D3DDD_LINECAPS              0x00000020L /* dpcLineCaps is valid */
+#define D3DDD_TRICAPS               0x00000040L /* dpcTriCaps is valid */
+#define D3DDD_DEVICERENDERBITDEPTH  0x00000080L /* dwDeviceRenderBitDepth is valid */
+#define D3DDD_DEVICEZBUFFERBITDEPTH 0x00000100L /* dwDeviceZBufferBitDepth is valid */
+#define D3DDD_MAXBUFFERSIZE         0x00000200L /* dwMaxBufferSize is valid */
+#define D3DDD_MAXVERTEXCOUNT        0x00000400L /* dwMaxVertexCount is valid */
+
+/* D3DDEVICEDESC dwDevCaps flags */
+
+#define D3DDEVCAPS_FLOATTLVERTEX        0x00000001L /* Device accepts floating point */
+                                                    /* for post-transform vertex data */
+#define D3DDEVCAPS_SORTINCREASINGZ      0x00000002L /* Device needs data sorted for increasing Z*/
+#define D3DDEVCAPS_SORTDECREASINGZ      0X00000004L /* Device needs data sorted for decreasing Z*/
+#define D3DDEVCAPS_SORTEXACT            0x00000008L /* Device needs data sorted exactly */
+
+#define D3DDEVCAPS_EXECUTESYSTEMMEMORY  0x00000010L /* Device can use execute buffers from system memory */
+#define D3DDEVCAPS_EXECUTEVIDEOMEMORY   0x00000020L /* Device can use execute buffers from video memory */
+#define D3DDEVCAPS_TLVERTEXSYSTEMMEMORY 0x00000040L /* Device can use TL buffers from system memory */
+#define D3DDEVCAPS_TLVERTEXVIDEOMEMORY  0x00000080L /* Device can use TL buffers from video memory */
+#define D3DDEVCAPS_TEXTURESYSTEMMEMORY  0x00000100L /* Device can texture from system memory */
+#define D3DDEVCAPS_TEXTUREVIDEOMEMORY   0x00000200L /* Device can texture from device memory */
+
+#define D3DFDS_COLORMODEL        0x00000001L /* Match color model */
+#define D3DFDS_GUID              0x00000002L /* Match guid */
+#define D3DFDS_HARDWARE          0x00000004L /* Match hardware/software */
+#define D3DFDS_TRIANGLES         0x00000008L /* Match in triCaps */
+#define D3DFDS_LINES             0x00000010L /* Match in lineCaps  */
+#define D3DFDS_MISCCAPS          0x00000020L /* Match primCaps.dwMiscCaps */
+#define D3DFDS_RASTERCAPS        0x00000040L /* Match primCaps.dwRasterCaps */
+#define D3DFDS_ZCMPCAPS          0x00000080L /* Match primCaps.dwZCmpCaps */
+#define D3DFDS_ALPHACMPCAPS      0x00000100L /* Match primCaps.dwAlphaCmpCaps */
+#define D3DFDS_SRCBLENDCAPS      0x00000200L /* Match primCaps.dwSourceBlendCaps */
+#define D3DFDS_DSTBLENDCAPS      0x00000400L /* Match primCaps.dwDestBlendCaps */
+#define D3DFDS_SHADECAPS         0x00000800L /* Match primCaps.dwShadeCaps */
+#define D3DFDS_TEXTURECAPS       0x00001000L /* Match primCaps.dwTextureCaps */
+#define D3DFDS_TEXTUREFILTERCAPS 0x00002000L /* Match primCaps.dwTextureFilterCaps */
+#define D3DFDS_TEXTUREBLENDCAPS  0x00004000L /* Match primCaps.dwTextureBlendCaps */
+#define D3DFDS_TEXTUREADDRESSCAPS  0x00008000L /* Match primCaps.dwTextureBlendCaps */
+
+/*
+ * FindDevice arguments
+ */
+typedef struct _D3DFINDDEVICESEARCH {
+    DWORD               dwSize;
+    DWORD               dwFlags;
+    BOOL                bHardware;
+    D3DCOLORMODEL       dcmColorModel;
+    GUID                guid;
+    DWORD               dwCaps;
+    D3DPRIMCAPS         dpcPrimCaps;
+} D3DFINDDEVICESEARCH, *LPD3DFINDDEVICESEARCH;
+
+typedef struct _D3DFINDDEVICERESULT {
+    DWORD               dwSize;
+    GUID                guid;           /* guid which matched */
+    D3DDEVICEDESC       ddHwDesc;               /* hardware D3DDEVICEDESC */
+    D3DDEVICEDESC       ddSwDesc;       /* software D3DDEVICEDESC */
+} D3DFINDDEVICERESULT, *LPD3DFINDDEVICERESULT;
+
+/*
+ * Description of execute buffer.
+ */
+typedef struct _D3DExecuteBufferDesc {
+    DWORD               dwSize;         /* size of this structure */
+    DWORD               dwFlags;        /* flags indicating which fields are valid */
+    DWORD               dwCaps;         /* capabilities of execute buffer */
+    DWORD               dwBufferSize;   /* size of execute buffer data */
+    LPVOID              lpData;         /* pointer to actual data */
+} D3DEXECUTEBUFFERDESC, *LPD3DEXECUTEBUFFERDESC;
+
+/* D3DEXECUTEBUFFER dwFlags indicating valid fields */
+
+#define D3DDEB_BUFSIZE          0x00000001l     /* buffer size valid */
+#define D3DDEB_CAPS             0x00000002l     /* caps valid */
+#define D3DDEB_LPDATA           0x00000004l     /* lpData valid */
+
+/* D3DEXECUTEBUFFER dwCaps */
+
+#define D3DDEBCAPS_SYSTEMMEMORY 0x00000001l     /* buffer in system memory */
+#define D3DDEBCAPS_VIDEOMEMORY  0x00000002l     /* buffer in device memory */
+#define D3DDEBCAPS_MEM (D3DDEBCAPS_SYSTEMMEMORY|D3DDEBCAPS_VIDEOMEMORY)
+
+#pragma pack()
+
+#endif /* _D3DCAPS_H_ */
--- /dev/null
+++ b/WinQuake/dxsdk/SDK/INC/D3DRM.H
@@ -1,0 +1,134 @@
+/*==========================================================================;
+ *
+ *  Copyright (C) 1995-1996 Microsoft Corporation.  All Rights Reserved.
+ *
+ *  File:       d3drm.h
+ *  Content:    Direct3DRM include file
+ *
+ ***************************************************************************/
+
+#ifndef __D3DRM_H__
+#define __D3DRM_H__
+
+#include "d3drmobj.h"
+
+#ifdef __cplusplus
+extern "C" {
+struct IDirect3DRM;
+#endif
+
+
+typedef void (*D3DRMDEVICEPALETTECALLBACK)
+    (LPDIRECT3DRMDEVICE lpDirect3DRMDev, LPVOID lpArg, DWORD dwIndex, LONG red, LONG green, LONG blue);
+
+DEFINE_GUID(IID_IDirect3DRM,    0x2bc49361, 0x8327, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+WIN_TYPES(IDirect3DRM, DIRECT3DRM);
+
+
+/* Create a Direct3DRM API */
+STDAPI Direct3DRMCreate(LPDIRECT3DRM FAR *lplpDirect3DRM);
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRM
+
+DECLARE_INTERFACE_(IDirect3DRM, IUnknown)
+{
+    IUNKNOWN_METHODS(PURE);
+
+    STDMETHOD(CreateObject)
+        (THIS_ REFCLSID rclsid, LPUNKNOWN pUnkOuter, REFIID riid, LPVOID FAR* ppv) PURE;
+    STDMETHOD(CreateFrame)      (THIS_ LPDIRECT3DRMFRAME, LPDIRECT3DRMFRAME *) PURE;
+    STDMETHOD(CreateMesh)       (THIS_ LPDIRECT3DRMMESH *) PURE;
+    STDMETHOD(CreateMeshBuilder)(THIS_ LPDIRECT3DRMMESHBUILDER *) PURE;
+    STDMETHOD(CreateFace)       (THIS_ LPDIRECT3DRMFACE *) PURE;
+    STDMETHOD(CreateAnimation)  (THIS_ LPDIRECT3DRMANIMATION *) PURE;
+    STDMETHOD(CreateAnimationSet)(THIS_ LPDIRECT3DRMANIMATIONSET *) PURE;
+    STDMETHOD(CreateTexture)    (THIS_ LPD3DRMIMAGE, LPDIRECT3DRMTEXTURE *) PURE;
+    STDMETHOD(CreateLight)      (THIS_ D3DRMLIGHTTYPE, D3DCOLOR, LPDIRECT3DRMLIGHT *) PURE;
+    STDMETHOD(CreateLightRGB)
+        (THIS_ D3DRMLIGHTTYPE, D3DVALUE, D3DVALUE, D3DVALUE, LPDIRECT3DRMLIGHT *) PURE;
+    STDMETHOD(CreateMaterial)   (THIS_ D3DVALUE, LPDIRECT3DRMMATERIAL *) PURE;
+    STDMETHOD(CreateDevice)     (THIS_ DWORD, DWORD, LPDIRECT3DRMDEVICE *) PURE;
+
+    /* Create a Windows Device using DirectDraw surfaces */
+    STDMETHOD(CreateDeviceFromSurface)
+    (   THIS_ LPGUID lpGUID, LPDIRECTDRAW lpDD,
+        LPDIRECTDRAWSURFACE lpDDSBack, LPDIRECT3DRMDEVICE *
+    ) PURE;
+
+    /* Create a Windows Device using D3D objects */
+    STDMETHOD(CreateDeviceFromD3D)
+    (   THIS_ LPDIRECT3D lpD3D, LPDIRECT3DDEVICE lpD3DDev,
+        LPDIRECT3DRMDEVICE *
+    ) PURE;
+
+    STDMETHOD(CreateDeviceFromClipper)
+    (   THIS_ LPDIRECTDRAWCLIPPER lpDDClipper, LPGUID lpGUID,
+        int width, int height, LPDIRECT3DRMDEVICE *) PURE;
+
+    STDMETHOD(CreateTextureFromSurface)(THIS_ LPDIRECTDRAWSURFACE lpDDS, LPDIRECT3DRMTEXTURE *) PURE;
+   
+    STDMETHOD(CreateShadow)
+    (   THIS_ LPDIRECT3DRMVISUAL, LPDIRECT3DRMLIGHT,
+        D3DVALUE px, D3DVALUE py, D3DVALUE pz,
+        D3DVALUE nx, D3DVALUE ny, D3DVALUE nz,
+        LPDIRECT3DRMVISUAL *
+    ) PURE;
+    STDMETHOD(CreateViewport)
+    (   THIS_ LPDIRECT3DRMDEVICE, LPDIRECT3DRMFRAME, DWORD, DWORD,
+        DWORD, DWORD, LPDIRECT3DRMVIEWPORT *
+    ) PURE;
+    STDMETHOD(CreateWrap)
+    (   THIS_ D3DRMWRAPTYPE, LPDIRECT3DRMFRAME,
+        D3DVALUE ox, D3DVALUE oy, D3DVALUE oz,
+        D3DVALUE dx, D3DVALUE dy, D3DVALUE dz,
+        D3DVALUE ux, D3DVALUE uy, D3DVALUE uz,
+        D3DVALUE ou, D3DVALUE ov,
+        D3DVALUE su, D3DVALUE sv,
+        LPDIRECT3DRMWRAP *
+    ) PURE;
+    STDMETHOD(CreateUserVisual) (THIS_ D3DRMUSERVISUALCALLBACK, LPVOID lPArg, LPDIRECT3DRMUSERVISUAL *) PURE;
+    STDMETHOD(LoadTexture)      (THIS_ const char *, LPDIRECT3DRMTEXTURE *) PURE;
+    STDMETHOD(LoadTextureFromResource)  (THIS_ HRSRC rs, LPDIRECT3DRMTEXTURE *) PURE;
+   
+    STDMETHOD(SetSearchPath)    (THIS_ LPCSTR) PURE;
+    STDMETHOD(AddSearchPath)    (THIS_ LPCSTR) PURE;
+    STDMETHOD(GetSearchPath)    (THIS_ DWORD *size_return, LPSTR path_return);
+    //STDMETHOD(GetSearchPath)  (THIS_ int *return_count, char ***return_path) PURE;
+    STDMETHOD(SetDefaultTextureColors)(THIS_ DWORD) PURE;
+    STDMETHOD(SetDefaultTextureShades)(THIS_ DWORD) PURE;
+   
+    STDMETHOD(GetDevices)       (THIS_ LPDIRECT3DRMDEVICEARRAY *) PURE;
+    STDMETHOD(GetNamedObject)   (THIS_ const char *, LPDIRECT3DRMOBJECT *) PURE;
+   
+    STDMETHOD(EnumerateObjects) (THIS_ D3DRMOBJECTCALLBACK, LPVOID) PURE;
+   
+    STDMETHOD(Load)             
+    (   THIS_ LPVOID, LPVOID, LPIID *, DWORD, D3DRMLOADOPTIONS,
+        D3DRMLOADCALLBACK, LPVOID, D3DRMLOADTEXTURECALLBACK, LPVOID,
+        LPDIRECT3DRMFRAME
+    ) PURE;
+    STDMETHOD(Tick)             (THIS_ D3DVALUE) PURE;
+};
+
+#define D3DRM_OK                        DD_OK
+#define D3DRMERR_BADOBJECT              MAKE_DDHRESULT(781)
+#define D3DRMERR_BADTYPE                MAKE_DDHRESULT(782)
+#define D3DRMERR_BADALLOC               MAKE_DDHRESULT(783)
+#define D3DRMERR_FACEUSED               MAKE_DDHRESULT(784)
+#define D3DRMERR_NOTFOUND               MAKE_DDHRESULT(785)
+#define D3DRMERR_NOTDONEYET             MAKE_DDHRESULT(786)
+#define D3DRMERR_FILENOTFOUND           MAKE_DDHRESULT(787)
+#define D3DRMERR_BADFILE                MAKE_DDHRESULT(788)
+#define D3DRMERR_BADDEVICE              MAKE_DDHRESULT(789)
+#define D3DRMERR_BADVALUE               MAKE_DDHRESULT(790)
+#define D3DRMERR_BADMAJORVERSION        MAKE_DDHRESULT(791)
+#define D3DRMERR_BADMINORVERSION        MAKE_DDHRESULT(792)
+#define D3DRMERR_UNABLETOEXECUTE        MAKE_DDHRESULT(793)
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif /* _D3DRMAPI_H_ */
+
--- /dev/null
+++ b/WinQuake/dxsdk/SDK/INC/D3DRMDEF.H
@@ -1,0 +1,402 @@
+/*==========================================================================;
+ *
+ *  Copyright (C) 1995-1996 Microsoft Corporation.  All Rights Reserved.
+ *
+ *  File:       d3drm.h
+ *  Content:    Direct3DRM include file
+ *
+ ***************************************************************************/
+
+#ifndef __D3DRMDEFS_H__
+#define __D3DRMDEFS_H__
+
+#include <stddef.h>
+#include "d3dtypes.h"
+
+#ifdef WIN32
+#define D3DRMAPI  __stdcall
+#else
+#define D3DRMAPI
+#endif
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#ifndef TRUE
+#define FALSE 0
+#define TRUE 1
+#endif
+
+typedef struct _D3DRMVECTOR4D
+{   D3DVALUE x, y, z, w;
+} D3DRMVECTOR4D, *LPD3DRMVECTOR4D;
+
+typedef D3DVALUE D3DRMMATRIX4D[4][4];
+
+typedef struct _D3DRMQUATERNION
+{   D3DVALUE s;
+    D3DVECTOR v;
+} D3DRMQUATERNION, *LPD3DRMQUATERNION;
+
+typedef struct _D3DRMBOX
+{   D3DVECTOR min, max;
+} D3DRMBOX, *LPD3DRMBOX;
+
+typedef void (*D3DRMWRAPCALLBACK)
+    (LPD3DVECTOR, int* u, int* v, LPD3DVECTOR a, LPD3DVECTOR b, LPVOID);
+
+typedef enum _D3DRMLIGHTTYPE
+{   D3DRMLIGHT_AMBIENT,
+    D3DRMLIGHT_POINT,
+    D3DRMLIGHT_SPOT,
+    D3DRMLIGHT_DIRECTIONAL,
+    D3DRMLIGHT_PARALLELPOINT
+} D3DRMLIGHTTYPE, *LPD3DRMLIGHTTYPE;
+
+typedef enum _D3DRMSHADEMODE {
+    D3DRMSHADE_FLAT     = 0,
+    D3DRMSHADE_GOURAUD  = 1,
+    D3DRMSHADE_PHONG    = 2,
+
+    D3DRMSHADE_MASK     = 7,
+    D3DRMSHADE_MAX      = 8
+} D3DRMSHADEMODE, *LPD3DRMSHADEMODE;
+
+typedef enum _D3DRMLIGHTMODE {
+    D3DRMLIGHT_OFF      = 0 * D3DRMSHADE_MAX,
+    D3DRMLIGHT_ON       = 1 * D3DRMSHADE_MAX,
+
+    D3DRMLIGHT_MASK     = 7 * D3DRMSHADE_MAX,
+    D3DRMLIGHT_MAX      = 8 * D3DRMSHADE_MAX
+} D3DRMLIGHTMODE, *LPD3DRMLIGHTMODE;
+
+typedef enum _D3DRMFILLMODE {
+    D3DRMFILL_POINTS    = 0 * D3DRMLIGHT_MAX,
+    D3DRMFILL_WIREFRAME = 1 * D3DRMLIGHT_MAX,
+    D3DRMFILL_SOLID     = 2 * D3DRMLIGHT_MAX,
+
+    D3DRMFILL_MASK      = 7 * D3DRMLIGHT_MAX,
+    D3DRMFILL_MAX       = 8 * D3DRMLIGHT_MAX
+} D3DRMFILLMODE, *LPD3DRMFILLMODE;
+
+typedef DWORD D3DRMRENDERQUALITY, *LPD3DRMRENDERQUALITY;
+
+#define D3DRMRENDER_WIREFRAME   (D3DRMSHADE_FLAT+D3DRMLIGHT_OFF+D3DRMFILL_WIREFRAME)
+#define D3DRMRENDER_UNLITFLAT   (D3DRMSHADE_FLAT+D3DRMLIGHT_OFF+D3DRMFILL_SOLID)
+#define D3DRMRENDER_FLAT        (D3DRMSHADE_FLAT+D3DRMLIGHT_ON+D3DRMFILL_SOLID)
+#define D3DRMRENDER_GOURAUD     (D3DRMSHADE_GOURAUD+D3DRMLIGHT_ON+D3DRMFILL_SOLID)
+#define D3DRMRENDER_PHONG       (D3DRMSHADE_PHONG+D3DRMLIGHT_ON+D3DRMFILL_SOLID)
+
+typedef enum _D3DRMTEXTUREQUALITY
+{   D3DRMTEXTURE_NEAREST,               /* choose nearest texel */
+    D3DRMTEXTURE_LINEAR,                /* interpolate 4 texels */
+    D3DRMTEXTURE_MIPNEAREST,            /* nearest texel in nearest mipmap  */
+    D3DRMTEXTURE_MIPLINEAR,             /* interpolate 2 texels from 2 mipmaps */
+    D3DRMTEXTURE_LINEARMIPNEAREST,      /* interpolate 4 texels in nearest mipmap */
+    D3DRMTEXTURE_LINEARMIPLINEAR        /* interpolate 8 texels from 2 mipmaps */
+} D3DRMTEXTUREQUALITY, *LPD3DRMTEXTUREQUALITY;
+
+typedef enum _D3DRMCOMBINETYPE
+{   D3DRMCOMBINE_REPLACE,
+    D3DRMCOMBINE_BEFORE,
+    D3DRMCOMBINE_AFTER
+} D3DRMCOMBINETYPE, *LPD3DRMCOMBINETYPE;
+
+typedef D3DCOLORMODEL D3DRMCOLORMODEL, *LPD3DRMCOLORMODEL;
+
+typedef enum _D3DRMPALETTEFLAGS
+{   D3DRMPALETTE_FREE,                  /* renderer may use this entry freely */
+    D3DRMPALETTE_READONLY,              /* fixed but may be used by renderer */
+    D3DRMPALETTE_RESERVED               /* may not be used by renderer */
+} D3DRMPALETTEFLAGS, *LPD3DRMPALETTEFLAGS;
+
+typedef struct _D3DRMPALETTEENTRY
+{   unsigned char red;          /* 0 .. 255 */
+    unsigned char green;        /* 0 .. 255 */
+    unsigned char blue;         /* 0 .. 255 */
+    unsigned char flags;        /* one of D3DRMPALETTEFLAGS */
+} D3DRMPALETTEENTRY, *LPD3DRMPALETTEENTRY;
+
+typedef struct _D3DRMIMAGE
+{   int width, height;          /* width and height in pixels */
+    int aspectx, aspecty;       /* aspect ratio for non-square pixels */
+    int depth;                  /* bits per pixel */
+    int rgb;                    /* if false, pixels are indices into a
+                                   palette otherwise, pixels encode
+                                   RGB values. */
+    int bytes_per_line;         /* number of bytes of memory for a
+                                   scanline. This must be a multiple
+                                   of 4. */
+    void* buffer1;              /* memory to render into (first buffer). */
+    void* buffer2;              /* second rendering buffer for double
+                                   buffering, set to NULL for single
+                                   buffering. */
+    unsigned long red_mask;
+    unsigned long green_mask;
+    unsigned long blue_mask;
+    unsigned long alpha_mask;   /* if rgb is true, these are masks for
+                                   the red, green and blue parts of a
+                                   pixel.  Otherwise, these are masks
+                                   for the significant bits of the
+                                   red, green and blue elements in the
+                                   palette.  For instance, most SVGA
+                                   displays use 64 intensities of red,
+                                   green and blue, so the masks should
+                                   all be set to 0xfc. */
+    int palette_size;           /* number of entries in palette */
+    D3DRMPALETTEENTRY* palette; /* description of the palette (only if
+                                   rgb is false).  Must be (1<<depth)
+                                   elements. */
+} D3DRMIMAGE, *LPD3DRMIMAGE;
+
+typedef enum _D3DRMWRAPTYPE
+{   D3DRMWRAP_FLAT,
+    D3DRMWRAP_CYLINDER,
+    D3DRMWRAP_SPHERE,
+    D3DRMWRAP_CHROME
+} D3DRMWRAPTYPE, *LPD3DRMWRAPTYPE;
+
+#define D3DRMWIREFRAME_CULL             1 /* cull backfaces */
+#define D3DRMWIREFRAME_HIDDENLINE       2 /* lines are obscured by closer objects */
+
+typedef enum _D3DRMPROJECTIONTYPE
+{   D3DRMPROJECT_PERSPECTIVE,
+    D3DRMPROJECT_ORTHOGRAPHIC
+} D3DRMPROJECTIONTYPE, *LPD3DRMPROJECTIONTYPE;
+
+typedef enum _D3DRMXOFFORMAT
+{   D3DRMXOF_BINARY,
+    D3DRMXOF_COMPRESSED,
+    D3DRMXOF_TEXT
+} D3DRMXOFFORMAT, *LPD3DRMXOFFORMAT;
+
+typedef DWORD D3DRMSAVEOPTIONS;
+#define D3DRMXOFSAVE_NORMALS 1
+#define D3DRMXOFSAVE_TEXTURECOORDINATES 2
+#define D3DRMXOFSAVE_MATERIALS 4
+#define D3DRMXOFSAVE_TEXTURENAMES 8
+#define D3DRMXOFSAVE_ALL 15
+
+typedef enum _D3DRMCOLORSOURCE
+{   D3DRMCOLOR_FROMFACE,
+    D3DRMCOLOR_FROMVERTEX
+} D3DRMCOLORSOURCE, *LPD3DRMCOLORSOURCE;
+
+typedef enum _D3DRMFRAMECONSTRAINT
+{   D3DRMCONSTRAIN_Z,           /* use only X and Y rotations */
+    D3DRMCONSTRAIN_Y,           /* use only X and Z rotations */
+    D3DRMCONSTRAIN_X            /* use only Y and Z rotations */
+} D3DRMFRAMECONSTRAINT, *LPD3DRMFRAMECONSTRAINT;
+
+typedef enum _D3DRMMATERIALMODE
+{   D3DRMMATERIAL_FROMMESH,
+    D3DRMMATERIAL_FROMPARENT,
+    D3DRMMATERIAL_FROMFRAME
+} D3DRMMATERIALMODE, *LPD3DRMMATERIALMODE;
+
+typedef enum _D3DRMFOGMODE
+{   D3DRMFOG_LINEAR,            /* linear between start and end */
+    D3DRMFOG_EXPONENTIAL,       /* density * exp(-distance) */
+    D3DRMFOG_EXPONENTIALSQUARED /* density * exp(-distance*distance) */
+} D3DRMFOGMODE, *LPD3DRMFOGMODE;
+
+typedef enum _D3DRMZBUFFERMODE {
+    D3DRMZBUFFER_FROMPARENT,    /* default */
+    D3DRMZBUFFER_ENABLE,        /* enable zbuffering */
+    D3DRMZBUFFER_DISABLE        /* disable zbuffering */
+} D3DRMZBUFFERMODE, *LPD3DRMZBUFFERMODE;
+
+typedef enum _D3DRMSORTMODE {
+    D3DRMSORT_FROMPARENT,       /* default */
+    D3DRMSORT_NONE,             /* don't sort child frames */
+    D3DRMSORT_FRONTTOBACK,      /* sort child frames front-to-back */
+    D3DRMSORT_BACKTOFRONT       /* sort child frames back-to-front */
+} D3DRMSORTMODE, *LPD3DRMSORTMODE;
+
+typedef DWORD D3DRMANIMATIONOPTIONS;
+#define D3DRMANIMATION_OPEN 0x01L
+#define D3DRMANIMATION_CLOSED 0x02L
+#define D3DRMANIMATION_LINEARPOSITION 0x04L
+#define D3DRMANIMATION_SPLINEPOSITION 0x08L
+#define D3DRMANIMATION_SCALEANDROTATION 0x00000010L
+#define D3DRMANIMATION_POSITION 0x00000020L
+
+typedef DWORD D3DRMLOADOPTIONS;
+
+#define D3DRMLOAD_FROMFILE  0x00L
+#define D3DRMLOAD_FROMRESOURCE 0x01L
+#define D3DRMLOAD_FROMMEMORY 0x02L
+#define D3DRMLOAD_FROMSTREAM 0x04L
+
+#define D3DRMLOAD_BYNAME 0x10L
+#define D3DRMLOAD_BYPOSITION 0x20L
+#define D3DRMLOAD_BYGUID 0x40L
+#define D3DRMLOAD_FIRST 0x80L
+
+#define D3DRMLOAD_INSTANCEBYREFERENCE 0x100L
+#define D3DRMLOAD_INSTANCEBYCOPYING 0x200L
+
+typedef struct _D3DRMLOADRESOURCE {
+  HMODULE hModule;
+  LPCTSTR lpName;
+  LPCTSTR lpType;
+} D3DRMLOADRESOURCE, *LPD3DRMLOADRESOURCE;
+
+typedef struct _D3DRMLOADMEMORY {
+  LPVOID lpMemory;
+  DWORD dSize;
+} D3DRMLOADMEMORY, *LPD3DRMLOADMEMORY;
+
+typedef enum _D3DRMUSERVISUALREASON {
+    D3DRMUSERVISUAL_CANSEE,
+    D3DRMUSERVISUAL_RENDER
+} D3DRMUSERVISUALREASON, *LPD3DRMUSERVISUALREASON;
+
+
+typedef DWORD D3DRMMAPPING, D3DRMMAPPINGFLAG, *LPD3DRMMAPPING;
+static const D3DRMMAPPINGFLAG D3DRMMAP_WRAPU = 1;
+static const D3DRMMAPPINGFLAG D3DRMMAP_WRAPV = 2;
+static const D3DRMMAPPINGFLAG D3DRMMAP_PERSPCORRECT = 4;
+
+typedef struct _D3DRMVERTEX
+{   D3DVECTOR       position;
+    D3DVECTOR       normal;
+    D3DVALUE        tu, tv;
+    D3DCOLOR        color;
+} D3DRMVERTEX, *LPD3DRMVERTEX;
+
+typedef LONG D3DRMGROUPINDEX; /* group indexes begin a 0 */
+static const D3DRMGROUPINDEX D3DRMGROUP_ALLGROUPS = -1;
+
+/*
+ * Create a color from three components in the range 0-1 inclusive.
+ */
+extern D3DCOLOR D3DRMAPI        D3DRMCreateColorRGB(D3DVALUE red,
+                                          D3DVALUE green,
+                                          D3DVALUE blue);
+
+/*
+ * Create a color from four components in the range 0-1 inclusive.
+ */
+extern D3DCOLOR D3DRMAPI        D3DRMCreateColorRGBA(D3DVALUE red,
+                                                 D3DVALUE green,
+                                                 D3DVALUE blue,
+                                                 D3DVALUE alpha);
+
+/*
+ * Get the red component of a color.
+ */
+extern D3DVALUE                 D3DRMAPI D3DRMColorGetRed(D3DCOLOR);
+
+/*
+ * Get the green component of a color.
+ */
+extern D3DVALUE                 D3DRMAPI D3DRMColorGetGreen(D3DCOLOR);
+
+/*
+ * Get the blue component of a color.
+ */
+extern D3DVALUE                 D3DRMAPI D3DRMColorGetBlue(D3DCOLOR);
+
+/*
+ * Get the alpha component of a color.
+ */
+extern D3DVALUE                 D3DRMAPI D3DRMColorGetAlpha(D3DCOLOR);
+
+/*
+ * Add two vectors.  Returns its first argument.
+ */
+extern LPD3DVECTOR      D3DRMAPI D3DRMVectorAdd(LPD3DVECTOR d,
+                                          LPD3DVECTOR s1,
+                                          LPD3DVECTOR s2);
+
+/*
+ * Subtract two vectors.  Returns its first argument.
+ */
+extern LPD3DVECTOR      D3DRMAPI D3DRMVectorSubtract(LPD3DVECTOR d,
+                                               LPD3DVECTOR s1,
+                                               LPD3DVECTOR s2);
+/*
+ * Reflect a ray about a given normal.  Returns its first argument.
+ */
+extern LPD3DVECTOR      D3DRMAPI D3DRMVectorReflect(LPD3DVECTOR d,
+                                              LPD3DVECTOR ray,
+                                              LPD3DVECTOR norm);
+
+/*
+ * Calculate the vector cross product.  Returns its first argument.
+ */
+extern LPD3DVECTOR      D3DRMAPI D3DRMVectorCrossProduct(LPD3DVECTOR d,
+                                                   LPD3DVECTOR s1,
+                                                   LPD3DVECTOR s2);
+/*
+ * Return the vector dot product.
+ */
+extern D3DVALUE                 D3DRMAPI D3DRMVectorDotProduct(LPD3DVECTOR s1,
+                                                 LPD3DVECTOR s2);
+
+/*
+ * Scale a vector so that its modulus is 1.  Returns its argument or
+ * NULL if there was an error (e.g. a zero vector was passed).
+ */
+extern LPD3DVECTOR      D3DRMAPI D3DRMVectorNormalize(LPD3DVECTOR);
+#define D3DRMVectorNormalise D3DRMVectorNormalize
+
+/*
+ * Return the length of a vector (e.g. sqrt(x*x + y*y + z*z)).
+ */
+extern D3DVALUE                 D3DRMAPI D3DRMVectorModulus(LPD3DVECTOR v);
+
+/*
+ * Set the rotation part of a matrix to be a rotation of theta radians
+ * around the given axis.
+ */
+
+extern LPD3DVECTOR      D3DRMAPI D3DRMVectorRotate(LPD3DVECTOR r, LPD3DVECTOR v, LPD3DVECTOR axis, D3DVALUE theta);
+
+/*
+ * Scale a vector uniformly in all three axes
+ */
+extern LPD3DVECTOR      D3DRMAPI D3DRMVectorScale(LPD3DVECTOR d, LPD3DVECTOR s, D3DVALUE factor);
+
+/*
+ * Return a random unit vector
+ */
+extern LPD3DVECTOR      D3DRMAPI D3DRMVectorRandom(LPD3DVECTOR d);
+
+/*
+ * Returns a unit quaternion that represents a rotation of theta radians
+ * around the given axis.
+ */
+
+extern LPD3DRMQUATERNION D3DRMAPI D3DRMQuaternionFromRotation(LPD3DRMQUATERNION quat,
+                                                              LPD3DVECTOR v,
+                                                              D3DVALUE theta);
+
+/*
+ * Calculate the product of two quaternions
+ */
+extern LPD3DRMQUATERNION D3DRMAPI D3DRMQuaternionMultiply(LPD3DRMQUATERNION q,
+                                                          LPD3DRMQUATERNION a,
+                                                          LPD3DRMQUATERNION b);
+
+/*
+ * Interpolate between two quaternions
+ */
+extern LPD3DRMQUATERNION D3DRMAPI D3DRMQuaternionSlerp(LPD3DRMQUATERNION q,
+                                                       LPD3DRMQUATERNION a,
+                                                       LPD3DRMQUATERNION b,
+                                                       D3DVALUE alpha);
+
+/*
+ * Calculate the matrix for the rotation that a unit quaternion represents
+ */
+extern void             D3DRMAPI D3DRMMatrixFromQuaternion(D3DRMMATRIX4D dmMat, LPD3DRMQUATERNION lpDqQuat);
+
+
+#if defined(__cplusplus)
+};
+#endif
+
+#endif
--- /dev/null
+++ b/WinQuake/dxsdk/SDK/INC/D3DRMOBJ.H
@@ -1,0 +1,727 @@
+/*==========================================================================;
+ *
+ *  Copyright (C) 1995-1996 Microsoft Corporation.  All Rights Reserved.
+ *
+ *  File:       d3drm.h
+ *  Content:    Direct3DRM include file
+ *
+ ***************************************************************************/
+
+#ifndef _D3DRMOBJ_H_
+#define _D3DRMOBJ_H_
+
+#include <objbase.h> /* Use Windows header files */
+#define VIRTUAL
+
+#include "d3drmdef.h"
+#include "d3d.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * The methods for IUnknown
+ */
+#define IUNKNOWN_METHODS(kind) \
+    STDMETHOD(QueryInterface)           (THIS_ REFIID riid, LPVOID *ppvObj) kind; \
+    STDMETHOD_(ULONG, AddRef)           (THIS) kind; \
+    STDMETHOD_(ULONG, Release)          (THIS) kind
+
+/*
+ * The methods for IDirect3DRMObject
+ */
+#define IDIRECT3DRMOBJECT_METHODS(kind) \
+    STDMETHOD(Clone)                    (THIS_ LPUNKNOWN pUnkOuter, REFIID riid, LPVOID *ppvObj) kind; \
+    STDMETHOD(AddDestroyCallback)       (THIS_ D3DRMOBJECTCALLBACK, LPVOID argument) kind; \
+    STDMETHOD(DeleteDestroyCallback)    (THIS_ D3DRMOBJECTCALLBACK, LPVOID argument) kind; \
+    STDMETHOD(SetAppData)               (THIS_ DWORD data) kind; \
+    STDMETHOD_(DWORD, GetAppData)       (THIS) kind; \
+    STDMETHOD(SetName)                  (THIS_ LPCSTR) kind; \
+    STDMETHOD(GetName)                  (THIS_ LPDWORD lpdwSize, LPSTR lpName) kind; \
+    STDMETHOD(GetClassName)             (THIS_ LPDWORD lpdwSize, LPSTR lpName) kind
+
+
+#define WIN_TYPES(itype, ptype) \
+    typedef interface itype FAR *LP##ptype, FAR **LPLP##ptype
+
+WIN_TYPES(IDirect3DRMObject, DIRECT3DRMOBJECT);
+WIN_TYPES(IDirect3DRMDevice, DIRECT3DRMDEVICE);
+WIN_TYPES(IDirect3DRMViewport, DIRECT3DRMVIEWPORT);
+WIN_TYPES(IDirect3DRMFrame, DIRECT3DRMFRAME);
+WIN_TYPES(IDirect3DRMVisual, DIRECT3DRMVISUAL);
+WIN_TYPES(IDirect3DRMMesh, DIRECT3DRMMESH);
+WIN_TYPES(IDirect3DRMMeshBuilder, DIRECT3DRMMESHBUILDER);
+WIN_TYPES(IDirect3DRMFace, DIRECT3DRMFACE);
+WIN_TYPES(IDirect3DRMLight, DIRECT3DRMLIGHT);
+WIN_TYPES(IDirect3DRMTexture, DIRECT3DRMTEXTURE);
+WIN_TYPES(IDirect3DRMWrap, DIRECT3DRMWRAP);
+WIN_TYPES(IDirect3DRMMaterial, DIRECT3DRMMATERIAL);
+WIN_TYPES(IDirect3DRMAnimation, DIRECT3DRMANIMATION);
+WIN_TYPES(IDirect3DRMAnimationSet, DIRECT3DRMANIMATIONSET);
+WIN_TYPES(IDirect3DRMUserVisual, DIRECT3DRMUSERVISUAL);
+WIN_TYPES(IDirect3DRMShadow, DIRECT3DRMSHADOW);
+WIN_TYPES(IDirect3DRMArray, DIRECT3DRMOBJECTARRAY);
+WIN_TYPES(IDirect3DRMDeviceArray, DIRECT3DRMDEVICEARRAY);
+WIN_TYPES(IDirect3DRMFaceArray, DIRECT3DRMFACEARRAY);
+WIN_TYPES(IDirect3DRMViewportArray, DIRECT3DRMVIEWPORTARRAY);
+WIN_TYPES(IDirect3DRMFrameArray, DIRECT3DRMFRAMEARRAY);
+WIN_TYPES(IDirect3DRMVisualArray, DIRECT3DRMVISUALARRAY);
+WIN_TYPES(IDirect3DRMPickedArray, DIRECT3DRMPICKEDARRAY);
+WIN_TYPES(IDirect3DRMLightArray, DIRECT3DRMLIGHTARRAY);
+
+/*
+ * Direct3DRM Object classes
+ */
+DEFINE_GUID(CLSID_CDirect3DRMDevice,        0x4fa3568e, 0x623f, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(CLSID_CDirect3DRMViewport,      0x4fa3568f, 0x623f, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(CLSID_CDirect3DRMFrame,         0x4fa35690, 0x623f, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(CLSID_CDirect3DRMMesh,          0x4fa35691, 0x623f, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(CLSID_CDirect3DRMMeshBuilder,   0x4fa35692, 0x623f, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(CLSID_CDirect3DRMFace,          0x4fa35693, 0x623f, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(CLSID_CDirect3DRMLight,         0x4fa35694, 0x623f, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(CLSID_CDirect3DRMTexture,       0x4fa35695, 0x623f, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(CLSID_CDirect3DRMWrap,          0x4fa35696, 0x623f, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(CLSID_CDirect3DRMMaterial,      0x4fa35697, 0x623f, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(CLSID_CDirect3DRMAnimation,     0x4fa35698, 0x623f, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(CLSID_CDirect3DRMAnimationSet,  0x4fa35699, 0x623f, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(CLSID_CDirect3DRMUserVisual,    0x4fa3569a, 0x623f, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(CLSID_CDirect3DRMShadow,        0x4fa3569b, 0x623f, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+
+/*
+ * Direct3DRM Object interfaces
+ */
+DEFINE_GUID(IID_IDirect3DRMObject,          0xeb16cb00, 0xd271, 0x11ce, 0xac, 0x48, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(IID_IDirect3DRMDevice,          0xe9e19280, 0x6e05, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(IID_IDirect3DRMViewport,        0xeb16cb02, 0xd271, 0x11ce, 0xac, 0x48, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(IID_IDirect3DRMFrame,           0xeb16cb03, 0xd271, 0x11ce, 0xac, 0x48, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(IID_IDirect3DRMVisual,          0xeb16cb04, 0xd271, 0x11ce, 0xac, 0x48, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(IID_IDirect3DRMMesh,            0xa3a80d01, 0x6e12, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(IID_IDirect3DRMMeshBuilder,     0xa3a80d02, 0x6e12, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(IID_IDirect3DRMFace,            0xeb16cb07, 0xd271, 0x11ce, 0xac, 0x48, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(IID_IDirect3DRMLight,           0xeb16cb08, 0xd271, 0x11ce, 0xac, 0x48, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(IID_IDirect3DRMTexture,         0xeb16cb09, 0xd271, 0x11ce, 0xac, 0x48, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(IID_IDirect3DRMWrap,            0xeb16cb0a, 0xd271, 0x11ce, 0xac, 0x48, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(IID_IDirect3DRMMaterial,        0xeb16cb0b, 0xd271, 0x11ce, 0xac, 0x48, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(IID_IDirect3DRMAnimation,       0xeb16cb0d, 0xd271, 0x11ce, 0xac, 0x48, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(IID_IDirect3DRMAnimationSet,    0xeb16cb0e, 0xd271, 0x11ce, 0xac, 0x48, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(IID_IDirect3DRMDeviceArray,     0xeb16cb10, 0xd271, 0x11ce, 0xac, 0x48, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(IID_IDirect3DRMViewportArray,   0xeb16cb11, 0xd271, 0x11ce, 0xac, 0x48, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(IID_IDirect3DRMFrameArray,      0xeb16cb12, 0xd271, 0x11ce, 0xac, 0x48, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(IID_IDirect3DRMVisualArray,     0xeb16cb13, 0xd271, 0x11ce, 0xac, 0x48, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(IID_IDirect3DRMLightArray,      0xeb16cb14, 0xd271, 0x11ce, 0xac, 0x48, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(IID_IDirect3DRMPickedArray,     0xeb16cb16, 0xd271, 0x11ce, 0xac, 0x48, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(IID_IDirect3DRMFaceArray,       0xeb16cb17, 0xd271, 0x11ce, 0xac, 0x48, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(IID_IDirect3DRMUserVisual,      0x59163de0, 0x6d43, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+DEFINE_GUID(IID_IDirect3DRMShadow,          0xaf359780, 0x6ba3, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+
+typedef void (*D3DRMOBJECTCALLBACK)(LPDIRECT3DRMOBJECT obj, LPVOID arg);
+typedef void (*D3DRMFRAMEMOVECALLBACK)(LPDIRECT3DRMFRAME obj, LPVOID arg, D3DVALUE delta);
+typedef void (*D3DRMUPDATECALLBACK)(LPDIRECT3DRMDEVICE obj, LPVOID arg, int, LPD3DRECT);
+typedef int (*D3DRMUSERVISUALCALLBACK)(LPDIRECT3DRMUSERVISUAL obj, LPVOID arg,
+                                    D3DRMUSERVISUALREASON reason,
+                                    LPDIRECT3DRMDEVICE dev,
+                                    LPDIRECT3DRMVIEWPORT view);
+typedef HRESULT (*D3DRMLOADTEXTURECALLBACK)
+    (char *tex_name, void *arg, LPDIRECT3DRMTEXTURE *);
+typedef void (*D3DRMLOADCALLBACK)
+     (LPDIRECT3DRMOBJECT object, REFIID objectguid, LPVOID arg);
+
+
+
+typedef struct _D3DRMPICKDESC
+{
+    ULONG       ulFaceIdx;
+    LONG        lGroupIdx;
+    D3DVECTOR   vPosition;
+
+} D3DRMPICKDESC, *LPD3DRMPICKDESC;
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRMObject
+
+/*
+ * Base class
+ */
+DECLARE_INTERFACE_(IDirect3DRMObject, IUnknown)
+{
+    IUNKNOWN_METHODS(PURE);
+    IDIRECT3DRMOBJECT_METHODS(PURE);
+};
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRMVisual
+
+DECLARE_INTERFACE_(IDirect3DRMVisual, IDirect3DRMObject)
+{
+    IUNKNOWN_METHODS(PURE);
+    IDIRECT3DRMOBJECT_METHODS(PURE);
+};
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRMDevice
+
+DECLARE_INTERFACE_(IDirect3DRMDevice, IDirect3DRMObject)
+{
+    IUNKNOWN_METHODS(PURE);
+    IDIRECT3DRMOBJECT_METHODS(PURE);
+
+    /*
+     * IDirect3DRMDevice methods
+     */
+    STDMETHOD(Init)(THIS_ ULONG width, ULONG height) PURE;
+    STDMETHOD(InitFromD3D)(THIS_ LPDIRECT3D lpD3D, LPDIRECT3DDEVICE lpD3DDev) PURE;
+    STDMETHOD(InitFromClipper)(THIS_ LPDIRECTDRAWCLIPPER lpDDClipper, LPGUID lpGUID, int width, int height) PURE;
+
+    STDMETHOD(Update)(THIS) PURE;
+    STDMETHOD(AddUpdateCallback)(THIS_ D3DRMUPDATECALLBACK, LPVOID arg) PURE;
+    STDMETHOD(DeleteUpdateCallback)(THIS_ D3DRMUPDATECALLBACK, LPVOID arg) PURE;
+    STDMETHOD(SetBufferCount)(THIS_ DWORD) PURE;
+    STDMETHOD_(DWORD, GetBufferCount)(THIS) PURE;
+
+    STDMETHOD(SetDither)(THIS_ BOOL) PURE;
+    STDMETHOD(SetShades)(THIS_ DWORD) PURE;
+    STDMETHOD(SetQuality)(THIS_ D3DRMRENDERQUALITY) PURE;
+    STDMETHOD(SetTextureQuality)(THIS_ D3DRMTEXTUREQUALITY) PURE;
+
+    STDMETHOD(GetViewports)(THIS_ LPDIRECT3DRMVIEWPORTARRAY *return_views) PURE;
+
+    STDMETHOD_(BOOL, GetDither)(THIS) PURE;
+    STDMETHOD_(DWORD, GetShades)(THIS) PURE;
+    STDMETHOD_(DWORD, GetHeight)(THIS) PURE;
+    STDMETHOD_(DWORD, GetWidth)(THIS) PURE;
+    STDMETHOD_(DWORD, GetTrianglesDrawn)(THIS) PURE;
+    STDMETHOD_(DWORD, GetWireframeOptions)(THIS) PURE;
+    STDMETHOD_(D3DRMRENDERQUALITY, GetQuality)(THIS) PURE;
+    STDMETHOD_(D3DCOLORMODEL, GetColorModel)(THIS) PURE;
+    STDMETHOD_(D3DRMTEXTUREQUALITY, GetTextureQuality)(THIS) PURE;
+    STDMETHOD(GetDirect3DDevice)(THIS_ LPDIRECT3DDEVICE *) PURE;
+};
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRMViewport
+
+DECLARE_INTERFACE_(IDirect3DRMViewport, IDirect3DRMObject)
+{
+    IUNKNOWN_METHODS(PURE);
+    IDIRECT3DRMOBJECT_METHODS(PURE);
+
+    /*
+     * IDirect3DRMViewport methods
+     */
+    STDMETHOD(Init)
+    (   THIS_ LPDIRECT3DRMDEVICE dev, LPDIRECT3DRMFRAME camera,
+        DWORD xpos, DWORD ypos, DWORD width, DWORD height
+    ) PURE;
+    STDMETHOD(Clear)(THIS) PURE;
+    STDMETHOD(Render)(THIS_ LPDIRECT3DRMFRAME) PURE;
+
+    STDMETHOD(SetFront)(THIS_ D3DVALUE) PURE;
+    STDMETHOD(SetBack)(THIS_ D3DVALUE) PURE;
+    STDMETHOD(SetField)(THIS_ D3DVALUE) PURE;
+    STDMETHOD(SetUniformScaling)(THIS_ BOOL) PURE;
+    STDMETHOD(SetCamera)(THIS_ LPDIRECT3DRMFRAME) PURE;
+    STDMETHOD(SetProjection)(THIS_ D3DRMPROJECTIONTYPE) PURE;
+    STDMETHOD(Transform)(THIS_ D3DRMVECTOR4D *d, D3DVECTOR *s) PURE;
+    STDMETHOD(InverseTransform)(THIS_ D3DVECTOR *d, D3DRMVECTOR4D *s) PURE;
+    STDMETHOD(Configure)(THIS_ LONG x, LONG y, DWORD width, DWORD height) PURE;
+    STDMETHOD(ForceUpdate)(THIS_ DWORD x1, DWORD y1, DWORD x2, DWORD y2) PURE;
+    STDMETHOD(SetPlane)(THIS_ D3DVALUE left, D3DVALUE right, D3DVALUE bottom, D3DVALUE top) PURE;
+
+    STDMETHOD(GetCamera)(THIS_ LPDIRECT3DRMFRAME *) PURE;
+    STDMETHOD(GetDevice)(THIS_ LPDIRECT3DRMDEVICE *) PURE;
+    STDMETHOD(GetPlane)(THIS_ D3DVALUE *left, D3DVALUE *right, D3DVALUE *bottom, D3DVALUE *top) PURE;
+    STDMETHOD(Pick)(THIS_ LONG x, LONG y, LPDIRECT3DRMPICKEDARRAY *return_visuals) PURE;
+
+    STDMETHOD_(BOOL, GetUniformScaling)(THIS) PURE;
+    STDMETHOD_(LONG, GetX)(THIS) PURE;
+    STDMETHOD_(LONG, GetY)(THIS) PURE;
+    STDMETHOD_(DWORD, GetWidth)(THIS) PURE;
+    STDMETHOD_(DWORD, GetHeight)(THIS) PURE;
+    STDMETHOD_(D3DVALUE, GetField)(THIS) PURE;
+    STDMETHOD_(D3DVALUE, GetBack)(THIS) PURE;
+    STDMETHOD_(D3DVALUE, GetFront)(THIS) PURE;
+    STDMETHOD_(D3DRMPROJECTIONTYPE, GetProjection)(THIS) PURE;
+    STDMETHOD(GetDirect3DViewport)(THIS_ LPDIRECT3DVIEWPORT *) PURE;
+};
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRMFrame
+
+DECLARE_INTERFACE_(IDirect3DRMFrame, IDirect3DRMVisual)
+{
+    IUNKNOWN_METHODS(PURE);
+    IDIRECT3DRMOBJECT_METHODS(PURE);
+
+    /*
+     * IDirect3DRMFrame methods
+     */
+    STDMETHOD(AddChild)(THIS_ LPDIRECT3DRMFRAME child) PURE;
+    STDMETHOD(AddLight)(THIS_ LPDIRECT3DRMLIGHT) PURE;
+    STDMETHOD(AddMoveCallback)(THIS_ D3DRMFRAMEMOVECALLBACK, VOID *arg) PURE;
+    STDMETHOD(AddTransform)(THIS_ D3DRMCOMBINETYPE, D3DRMMATRIX4D) PURE;
+    STDMETHOD(AddTranslation)(THIS_ D3DRMCOMBINETYPE, D3DVALUE x, D3DVALUE y, D3DVALUE z) PURE;
+    STDMETHOD(AddScale)(THIS_ D3DRMCOMBINETYPE, D3DVALUE sx, D3DVALUE sy, D3DVALUE sz) PURE;
+    STDMETHOD(AddRotation)(THIS_ D3DRMCOMBINETYPE, D3DVALUE x, D3DVALUE y, D3DVALUE z, D3DVALUE theta) PURE;
+    STDMETHOD(AddVisual)(THIS_ LPDIRECT3DRMVISUAL) PURE;
+    STDMETHOD(GetChildren)(THIS_ LPDIRECT3DRMFRAMEARRAY *children) PURE;
+    STDMETHOD_(D3DCOLOR, GetColor)(THIS) PURE;
+    STDMETHOD(GetLights)(THIS_ LPDIRECT3DRMLIGHTARRAY *lights) PURE;
+    STDMETHOD_(D3DRMMATERIALMODE, GetMaterialMode)(THIS) PURE;
+    STDMETHOD(GetParent)(THIS_ LPDIRECT3DRMFRAME *) PURE;
+    STDMETHOD(GetPosition)(THIS_ LPDIRECT3DRMFRAME reference, LPD3DVECTOR return_position) PURE;
+    STDMETHOD(GetRotation)(THIS_ LPDIRECT3DRMFRAME reference, LPD3DVECTOR axis, LPD3DVALUE return_theta) PURE;
+    STDMETHOD(GetScene)(THIS_ LPDIRECT3DRMFRAME *) PURE;
+    STDMETHOD_(D3DRMSORTMODE, GetSortMode)(THIS) PURE;
+    STDMETHOD(GetTexture)(THIS_ LPDIRECT3DRMTEXTURE *) PURE;
+    STDMETHOD(GetTransform)(THIS_ D3DRMMATRIX4D return_matrix) PURE;
+    STDMETHOD(GetVelocity)(THIS_ LPDIRECT3DRMFRAME reference, LPD3DVECTOR return_velocity, BOOL with_rotation) PURE;
+    STDMETHOD(GetOrientation)(THIS_ LPDIRECT3DRMFRAME reference, LPD3DVECTOR dir, LPD3DVECTOR up) PURE;
+    STDMETHOD(GetVisuals)(THIS_ LPDIRECT3DRMVISUALARRAY *visuals) PURE;
+    STDMETHOD(GetTextureTopology)(THIS_ BOOL *wrap_u, BOOL *wrap_v) PURE;
+    STDMETHOD(InverseTransform)(THIS_ D3DVECTOR *d, D3DVECTOR *s) PURE;
+    STDMETHOD(Load)(THIS_ LPVOID filename, LPVOID name, D3DRMLOADOPTIONS loadflags, D3DRMLOADTEXTURECALLBACK, LPVOID lpArg)PURE;
+    STDMETHOD(LookAt)(THIS_ LPDIRECT3DRMFRAME target, LPDIRECT3DRMFRAME reference, D3DRMFRAMECONSTRAINT) PURE;
+    STDMETHOD(Move)(THIS_ D3DVALUE delta) PURE;
+    STDMETHOD(DeleteChild)(THIS_ LPDIRECT3DRMFRAME) PURE;
+    STDMETHOD(DeleteLight)(THIS_ LPDIRECT3DRMLIGHT) PURE;
+    STDMETHOD(DeleteMoveCallback)(THIS_ D3DRMFRAMEMOVECALLBACK, VOID *arg) PURE;
+    STDMETHOD(DeleteVisual)(THIS_ LPDIRECT3DRMVISUAL) PURE;
+    STDMETHOD_(D3DCOLOR, GetSceneBackground)(THIS) PURE;
+    STDMETHOD(GetSceneBackgroundDepth)(THIS_ LPDIRECTDRAWSURFACE *) PURE;
+    STDMETHOD_(D3DCOLOR, GetSceneFogColor)(THIS) PURE;
+    STDMETHOD_(BOOL, GetSceneFogEnable)(THIS) PURE;
+    STDMETHOD_(D3DRMFOGMODE, GetSceneFogMode)(THIS) PURE;
+    STDMETHOD(GetSceneFogParams)(THIS_ D3DVALUE *return_start, D3DVALUE *return_end, D3DVALUE *return_density) PURE;
+    STDMETHOD(SetSceneBackground)(THIS_ D3DCOLOR) PURE;
+    STDMETHOD(SetSceneBackgroundRGB)(THIS_ D3DVALUE red, D3DVALUE green, D3DVALUE blue) PURE;
+    STDMETHOD(SetSceneBackgroundDepth)(THIS_ LPDIRECTDRAWSURFACE) PURE;
+    STDMETHOD(SetSceneBackgroundImage)(THIS_ LPDIRECT3DRMTEXTURE) PURE;
+    STDMETHOD(SetSceneFogEnable)(THIS_ BOOL) PURE;
+    STDMETHOD(SetSceneFogColor)(THIS_ D3DCOLOR) PURE;
+    STDMETHOD(SetSceneFogMode)(THIS_ D3DRMFOGMODE) PURE;
+    STDMETHOD(SetSceneFogParams)(THIS_ D3DVALUE start, D3DVALUE end, D3DVALUE density) PURE;
+    STDMETHOD(SetColor)(THIS_ D3DCOLOR) PURE;
+    STDMETHOD(SetColorRGB)(THIS_ D3DVALUE red, D3DVALUE green, D3DVALUE blue) PURE;
+    STDMETHOD_(D3DRMZBUFFERMODE, GetZbufferMode)(THIS) PURE;
+    STDMETHOD(SetMaterialMode)(THIS_ D3DRMMATERIALMODE) PURE;
+    STDMETHOD(SetOrientation)
+    (   THIS_ LPDIRECT3DRMFRAME reference,
+        D3DVALUE dx, D3DVALUE dy, D3DVALUE dz,
+        D3DVALUE ux, D3DVALUE uy, D3DVALUE uz
+    ) PURE;
+    STDMETHOD(SetPosition)(THIS_ LPDIRECT3DRMFRAME reference, D3DVALUE x, D3DVALUE y, D3DVALUE z) PURE;
+    STDMETHOD(SetRotation)(THIS_ LPDIRECT3DRMFRAME reference, D3DVALUE x, D3DVALUE y, D3DVALUE z, D3DVALUE theta) PURE;
+    STDMETHOD(SetSortMode)(THIS_ D3DRMSORTMODE) PURE;
+    STDMETHOD(SetTexture)(THIS_ LPDIRECT3DRMTEXTURE) PURE;
+    STDMETHOD(SetTextureTopology)(THIS_ BOOL wrap_u, BOOL wrap_v) PURE;
+    STDMETHOD(SetVelocity)(THIS_ LPDIRECT3DRMFRAME reference, D3DVALUE x, D3DVALUE y, D3DVALUE z, BOOL with_rotation) PURE;
+    STDMETHOD(SetZbufferMode)(THIS_ D3DRMZBUFFERMODE) PURE;
+    STDMETHOD(Transform)(THIS_ D3DVECTOR *d, D3DVECTOR *s) PURE;
+};
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRMMesh
+
+DECLARE_INTERFACE_(IDirect3DRMMesh, IDirect3DRMVisual)
+{
+    IUNKNOWN_METHODS(PURE);
+    IDIRECT3DRMOBJECT_METHODS(PURE);
+
+    /*
+     * IDirect3DRMMesh methods
+     */
+    STDMETHOD(Scale)(THIS_ D3DVALUE sx, D3DVALUE sy, D3DVALUE sz) PURE;
+    STDMETHOD(Translate)(THIS_ D3DVALUE tx, D3DVALUE ty, D3DVALUE tz) PURE;
+    STDMETHOD(GetBox)(THIS_ D3DRMBOX *) PURE;
+    STDMETHOD(AddGroup)(THIS_ unsigned vCount, unsigned fCount, unsigned vPerFace, unsigned *fData, D3DRMGROUPINDEX *returnId) PURE;
+    STDMETHOD(SetVertices)(THIS_ D3DRMGROUPINDEX id, unsigned index, unsigned count, D3DRMVERTEX *values) PURE;
+    STDMETHOD(SetGroupColor)(THIS_ D3DRMGROUPINDEX id, D3DCOLOR value) PURE;
+    STDMETHOD(SetGroupColorRGB)(THIS_ D3DRMGROUPINDEX id, D3DVALUE red, D3DVALUE green, D3DVALUE blue) PURE;
+    STDMETHOD(SetGroupMapping)(THIS_ D3DRMGROUPINDEX id, D3DRMMAPPING value) PURE;
+    STDMETHOD(SetGroupQuality)(THIS_ D3DRMGROUPINDEX id, D3DRMRENDERQUALITY value) PURE;
+    STDMETHOD(SetGroupMaterial)(THIS_ D3DRMGROUPINDEX id, LPDIRECT3DRMMATERIAL value) PURE;
+    STDMETHOD(SetGroupTexture)(THIS_ D3DRMGROUPINDEX id, LPDIRECT3DRMTEXTURE value) PURE;
+
+    STDMETHOD_(unsigned, GetGroupCount)(THIS) PURE;
+    STDMETHOD(GetGroup)(THIS_ D3DRMGROUPINDEX id, unsigned *vCount, unsigned *fCount, unsigned *vPerFace, DWORD *fDataSize, unsigned *fData) PURE;
+    STDMETHOD(GetVertices)(THIS_ D3DRMGROUPINDEX id, DWORD index, DWORD count, D3DRMVERTEX *returnPtr) PURE;
+    STDMETHOD_(D3DCOLOR, GetGroupColor)(THIS_ D3DRMGROUPINDEX id) PURE;
+    STDMETHOD_(D3DRMMAPPING, GetGroupMapping)(THIS_ D3DRMGROUPINDEX id) PURE;
+    STDMETHOD_(D3DRMRENDERQUALITY, GetGroupQuality)(THIS_ D3DRMGROUPINDEX id) PURE;
+    STDMETHOD(GetGroupMaterial)(THIS_ D3DRMGROUPINDEX id, LPDIRECT3DRMMATERIAL *returnPtr) PURE;
+    STDMETHOD(GetGroupTexture)(THIS_ D3DRMGROUPINDEX id, LPDIRECT3DRMTEXTURE *returnPtr) PURE;
+};
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRMShadow
+
+DECLARE_INTERFACE_(IDirect3DRMShadow, IDirect3DRMVisual)
+{
+    IUNKNOWN_METHODS(PURE);
+    IDIRECT3DRMOBJECT_METHODS(PURE);
+
+    /*
+     * IDirect3DRMShadow methods
+     */
+    STDMETHOD(Init)
+    (   THIS_ LPDIRECT3DRMVISUAL visual, LPDIRECT3DRMLIGHT light,
+        D3DVALUE px, D3DVALUE py, D3DVALUE pz,
+        D3DVALUE nx, D3DVALUE ny, D3DVALUE nz
+    ) PURE;
+};
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRMFace
+
+DECLARE_INTERFACE_(IDirect3DRMFace, IDirect3DRMObject)
+{
+    IUNKNOWN_METHODS(PURE);
+    IDIRECT3DRMOBJECT_METHODS(PURE);
+
+    /*
+     * IDirect3DRMFace methods
+     */
+     STDMETHOD(AddVertex)(THIS_ D3DVALUE x, D3DVALUE y, D3DVALUE z) PURE;
+     STDMETHOD(AddVertexAndNormalIndexed)(THIS_ DWORD vertex, DWORD normal) PURE;
+     STDMETHOD(SetColorRGB)(THIS_ D3DVALUE, D3DVALUE, D3DVALUE) PURE;
+     STDMETHOD(SetColor)(THIS_ D3DCOLOR) PURE;
+     STDMETHOD(SetTexture)(THIS_ LPDIRECT3DRMTEXTURE) PURE;
+     STDMETHOD(SetTextureCoordinates)(THIS_ DWORD vertex, D3DVALUE u, D3DVALUE v) PURE;
+     STDMETHOD(SetMaterial)(THIS_ LPDIRECT3DRMMATERIAL) PURE;
+     STDMETHOD(SetTextureTopology)(THIS_ BOOL wrap_u, BOOL wrap_v) PURE;
+
+     STDMETHOD(GetVertex)(THIS_ DWORD index, D3DVECTOR *vertex, D3DVECTOR *normal) PURE;
+     STDMETHOD(GetVertices)(THIS_ DWORD *vertex_count, D3DVECTOR *coords, D3DVECTOR *normals);
+     STDMETHOD(GetTextureCoordinates)(THIS_ DWORD vertex, D3DVALUE *u, D3DVALUE *v) PURE;
+     STDMETHOD(GetTextureTopology)(THIS_ BOOL *wrap_u, BOOL *wrap_v) PURE;
+     STDMETHOD(GetNormal)(THIS_ D3DVECTOR *) PURE;
+     STDMETHOD(GetTexture)(THIS_ LPDIRECT3DRMTEXTURE *) PURE;
+     STDMETHOD(GetMaterial)(THIS_ LPDIRECT3DRMMATERIAL *) PURE;
+
+     STDMETHOD_(int, GetVertexCount)(THIS) PURE;
+     STDMETHOD_(int, GetVertexIndex)(THIS_ DWORD which) PURE;
+     STDMETHOD_(int, GetTextureCoordinateIndex)(THIS_ DWORD which) PURE;
+     STDMETHOD_(D3DCOLOR, GetColor)(THIS) PURE;
+};
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRMMeshBuilder
+
+DECLARE_INTERFACE_(IDirect3DRMMeshBuilder, IDirect3DRMVisual)
+{
+    IUNKNOWN_METHODS(PURE);
+    IDIRECT3DRMOBJECT_METHODS(PURE);
+
+    /*
+     * IDirect3DRMMeshBuilder methods
+     */
+    STDMETHOD(Load)(THIS_ LPVOID filename, LPVOID name, D3DRMLOADOPTIONS loadflags, D3DRMLOADTEXTURECALLBACK, LPVOID lpArg) PURE;
+    STDMETHOD(Save)(THIS_ const char *filename, D3DRMXOFFORMAT, D3DRMSAVEOPTIONS save) PURE;
+    STDMETHOD(Scale)(THIS_ D3DVALUE sx, D3DVALUE sy, D3DVALUE sz) PURE;
+    STDMETHOD(Translate)(THIS_ D3DVALUE tx, D3DVALUE ty, D3DVALUE tz) PURE;
+    STDMETHOD(SetColorSource)(THIS_ D3DRMCOLORSOURCE) PURE;
+    STDMETHOD(GetBox)(THIS_ D3DRMBOX *) PURE;
+    STDMETHOD(GenerateNormals)(THIS) PURE;
+    STDMETHOD_(D3DRMCOLORSOURCE, GetColorSource)(THIS) PURE;
+
+    STDMETHOD(AddMesh)(THIS_ LPDIRECT3DRMMESH) PURE;
+    STDMETHOD(AddMeshBuilder)(THIS_ LPDIRECT3DRMMESHBUILDER) PURE;
+    STDMETHOD(AddFrame)(THIS_ LPDIRECT3DRMFRAME) PURE;
+    STDMETHOD(AddFace)(THIS_ LPDIRECT3DRMFACE) PURE;
+    STDMETHOD(AddFaces)
+    (   THIS_ DWORD vcount, D3DVECTOR *vertices, DWORD ncount, D3DVECTOR *normals,
+        DWORD *data, LPDIRECT3DRMFACEARRAY*
+    ) PURE;
+    STDMETHOD(ReserveSpace)(THIS_ DWORD vertex_Count, DWORD normal_count, DWORD face_count) PURE;
+    STDMETHOD(SetColorRGB)(THIS_ D3DVALUE red, D3DVALUE green, D3DVALUE blue) PURE;
+    STDMETHOD(SetColor)(THIS_ D3DCOLOR) PURE;
+    STDMETHOD(SetTexture)(THIS_ LPDIRECT3DRMTEXTURE) PURE;
+    STDMETHOD(SetMaterial)(THIS_ LPDIRECT3DRMMATERIAL) PURE;
+    STDMETHOD(SetTextureTopology)(THIS_ BOOL wrap_u, BOOL wrap_v) PURE;
+    STDMETHOD(SetQuality)(THIS_ D3DRMRENDERQUALITY) PURE;
+    STDMETHOD(SetPerspective)(THIS_ BOOL) PURE;
+    STDMETHOD(SetVertex)(THIS_ DWORD index, D3DVALUE x, D3DVALUE y, D3DVALUE z) PURE;
+    STDMETHOD(SetNormal)(THIS_ DWORD index, D3DVALUE x, D3DVALUE y, D3DVALUE z) PURE;
+    STDMETHOD(SetTextureCoordinates)(THIS_ DWORD index, D3DVALUE u, D3DVALUE v) PURE;
+    STDMETHOD(SetVertexColor)(THIS_ DWORD index, D3DCOLOR) PURE;
+    STDMETHOD(SetVertexColorRGB)(THIS_ DWORD index, D3DVALUE red, D3DVALUE green, D3DVALUE blue) PURE;
+
+    STDMETHOD(GetFaces)(THIS_ LPDIRECT3DRMFACEARRAY*) PURE;
+    STDMETHOD(GetVertices)
+    (   THIS_ DWORD *vcount, D3DVECTOR *vertices, DWORD *ncount, D3DVECTOR *normals, DWORD *face_data_size, DWORD *face_data
+    ) PURE;
+    STDMETHOD(GetTextureCoordinates)(THIS_ DWORD index, D3DVALUE *u, D3DVALUE *v) PURE;
+
+    STDMETHOD_(int, AddVertex)(THIS_ D3DVALUE x, D3DVALUE y, D3DVALUE z) PURE;
+    STDMETHOD_(int, AddNormal)(THIS_ D3DVALUE x, D3DVALUE y, D3DVALUE z) PURE;
+    STDMETHOD(CreateFace)(THIS_ LPDIRECT3DRMFACE*) PURE;
+    STDMETHOD_(D3DRMRENDERQUALITY, GetQuality)(THIS) PURE;
+    STDMETHOD_(BOOL, GetPerspective)(THIS) PURE;
+    STDMETHOD_(int, GetFaceCount)(THIS) PURE;
+    STDMETHOD_(int, GetVertexCount)(THIS) PURE;
+    STDMETHOD_(D3DCOLOR, GetVertexColor)(THIS_ DWORD index) PURE;
+
+    STDMETHOD(CreateMesh)(THIS_ LPDIRECT3DRMMESH*) PURE;
+};
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRMLight
+
+DECLARE_INTERFACE_(IDirect3DRMLight, IDirect3DRMObject)
+{
+    IUNKNOWN_METHODS(PURE);
+    IDIRECT3DRMOBJECT_METHODS(PURE);
+
+    /*
+     * IDirect3DRMLight methods
+     */
+    STDMETHOD(SetType)(THIS_ D3DRMLIGHTTYPE) PURE;
+    STDMETHOD(SetColor)(THIS_ D3DCOLOR) PURE;
+    STDMETHOD(SetColorRGB)(THIS_ D3DVALUE red, D3DVALUE green, D3DVALUE blue) PURE;
+    STDMETHOD(SetRange)(THIS_ D3DVALUE) PURE;
+    STDMETHOD(SetUmbra)(THIS_ D3DVALUE) PURE;
+    STDMETHOD(SetPenumbra)(THIS_ D3DVALUE) PURE;
+    STDMETHOD(SetConstantAttenuation)(THIS_ D3DVALUE) PURE;
+    STDMETHOD(SetLinearAttenuation)(THIS_ D3DVALUE) PURE;
+    STDMETHOD(SetQuadraticAttenuation)(THIS_ D3DVALUE) PURE;
+
+    STDMETHOD_(D3DVALUE, GetRange)(THIS) PURE;
+    STDMETHOD_(D3DVALUE, GetUmbra)(THIS) PURE;
+    STDMETHOD_(D3DVALUE, GetPenumbra)(THIS) PURE;
+    STDMETHOD_(D3DVALUE, GetConstantAttenuation)(THIS) PURE;
+    STDMETHOD_(D3DVALUE, GetLinearAttenuation)(THIS) PURE;
+    STDMETHOD_(D3DVALUE, GetQuadraticAttenuation)(THIS) PURE;
+    STDMETHOD_(D3DCOLOR, GetColor)(THIS) PURE;
+    STDMETHOD_(D3DRMLIGHTTYPE, GetType)(THIS) PURE;
+
+    STDMETHOD(SetEnableFrame)(THIS_ LPDIRECT3DRMFRAME) PURE;
+    STDMETHOD(GetEnableFrame)(THIS_ LPDIRECT3DRMFRAME*) PURE;
+};
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRMTexture
+
+DECLARE_INTERFACE_(IDirect3DRMTexture, IDirect3DRMVisual)
+{
+    IUNKNOWN_METHODS(PURE);
+    IDIRECT3DRMOBJECT_METHODS(PURE);
+
+    /*
+     * IDirect3DRMTexture methods
+     */
+    STDMETHOD(InitFromFile)(THIS_ const char *filename) PURE;
+    STDMETHOD(InitFromSurface)(THIS_ LPDIRECTDRAWSURFACE lpDDS) PURE;
+    STDMETHOD(InitFromResource)(THIS_ HRSRC) PURE;
+    STDMETHOD(Changed)(THIS_ BOOL pixels, BOOL palette) PURE;
+
+    STDMETHOD(SetColors)(THIS_ DWORD) PURE;
+    STDMETHOD(SetShades)(THIS_ DWORD) PURE;
+    STDMETHOD(SetDecalSize)(THIS_ D3DVALUE width, D3DVALUE height) PURE;
+    STDMETHOD(SetDecalOrigin)(THIS_ LONG x, LONG y) PURE;
+    STDMETHOD(SetDecalScale)(THIS_ DWORD) PURE;
+    STDMETHOD(SetDecalTransparency)(THIS_ BOOL) PURE;
+    STDMETHOD(SetDecalTransparentColor)(THIS_ D3DCOLOR) PURE;
+
+    STDMETHOD(GetDecalSize)(THIS_ D3DVALUE *width_return, D3DVALUE *height_return) PURE;
+    STDMETHOD(GetDecalOrigin)(THIS_ LONG *x_return, LONG *y_return) PURE;
+
+    STDMETHOD_(D3DRMIMAGE *, GetImage)(THIS) PURE;
+    STDMETHOD_(DWORD, GetShades)(THIS) PURE;
+    STDMETHOD_(DWORD, GetColors)(THIS) PURE;
+    STDMETHOD_(DWORD, GetDecalScale)(THIS) PURE;
+    STDMETHOD_(BOOL, GetDecalTransparency)(THIS) PURE;
+    STDMETHOD_(D3DCOLOR, GetDecalTransparentColor)(THIS) PURE;
+};
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRMWrap
+
+DECLARE_INTERFACE_(IDirect3DRMWrap, IDirect3DRMObject)
+{
+    IUNKNOWN_METHODS(PURE);
+    IDIRECT3DRMOBJECT_METHODS(PURE);
+
+    /*
+     * IDirect3DRMWrap methods
+     */
+    STDMETHOD(Init)
+    (   THIS_ D3DRMWRAPTYPE, LPDIRECT3DRMFRAME ref,
+        D3DVALUE ox, D3DVALUE oy, D3DVALUE oz,
+        D3DVALUE dx, D3DVALUE dy, D3DVALUE dz,
+        D3DVALUE ux, D3DVALUE uy, D3DVALUE uz,
+        D3DVALUE ou, D3DVALUE ov,
+        D3DVALUE su, D3DVALUE sv
+    ) PURE;
+    STDMETHOD(Apply)(THIS_ LPDIRECT3DRMOBJECT) PURE;
+    STDMETHOD(ApplyRelative)(THIS_ LPDIRECT3DRMFRAME frame, LPDIRECT3DRMOBJECT) PURE;
+};
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRMMaterial
+
+DECLARE_INTERFACE_(IDirect3DRMMaterial, IDirect3DRMObject)
+{
+    IUNKNOWN_METHODS(PURE);
+    IDIRECT3DRMOBJECT_METHODS(PURE);
+
+    /*
+     * IDirect3DRMMaterial methods
+     */
+    STDMETHOD(SetPower)(THIS_ D3DVALUE power) PURE;
+    STDMETHOD(SetSpecular)(THIS_ D3DVALUE r, D3DVALUE g, D3DVALUE b) PURE;
+    STDMETHOD(SetEmissive)(THIS_ D3DVALUE r, D3DVALUE g, D3DVALUE b) PURE;
+
+    STDMETHOD_(D3DVALUE, GetPower)(THIS) PURE;
+    STDMETHOD(GetSpecular)(THIS_ D3DVALUE* r, D3DVALUE* g, D3DVALUE* b) PURE;
+    STDMETHOD(GetEmissive)(THIS_ D3DVALUE* r, D3DVALUE* g, D3DVALUE* b) PURE;
+};
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRMAnimation
+
+DECLARE_INTERFACE_(IDirect3DRMAnimation, IDirect3DRMObject)
+{
+    IUNKNOWN_METHODS(PURE);
+    IDIRECT3DRMOBJECT_METHODS(PURE);
+
+    /*
+     * IDirect3DRMAnimation methods
+     */
+    STDMETHOD(SetOptions)(THIS_ D3DRMANIMATIONOPTIONS flags) PURE;
+    STDMETHOD(AddRotateKey)(THIS_ D3DVALUE time, D3DRMQUATERNION *q) PURE;
+    STDMETHOD(AddPositionKey)(THIS_ D3DVALUE time, D3DVALUE x, D3DVALUE y, D3DVALUE z) PURE;
+    STDMETHOD(AddScaleKey)(THIS_ D3DVALUE time, D3DVALUE x, D3DVALUE y, D3DVALUE z) PURE;
+    STDMETHOD(DeleteKey)(THIS_ D3DVALUE time) PURE;
+    STDMETHOD(SetFrame)(THIS_ LPDIRECT3DRMFRAME frame) PURE;
+    STDMETHOD(SetTime)(THIS_ D3DVALUE time) PURE;
+
+    STDMETHOD_(D3DRMANIMATIONOPTIONS, GetOptions)(THIS) PURE;
+};
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRMAnimationSet
+
+DECLARE_INTERFACE_(IDirect3DRMAnimationSet, IDirect3DRMObject)
+{
+    IUNKNOWN_METHODS(PURE);
+    IDIRECT3DRMOBJECT_METHODS(PURE);
+
+    /*
+     * IDirect3DRMAnimationSet methods
+     */
+    STDMETHOD(AddAnimation)(THIS_ LPDIRECT3DRMANIMATION aid) PURE;
+    STDMETHOD(Load)(THIS_ LPVOID filename, LPVOID name, D3DRMLOADOPTIONS loadflags, D3DRMLOADTEXTURECALLBACK, LPVOID lpArg, LPDIRECT3DRMFRAME parent)PURE;
+    STDMETHOD(DeleteAnimation)(THIS_ LPDIRECT3DRMANIMATION aid) PURE;
+    STDMETHOD(SetTime)(THIS_ D3DVALUE time) PURE;
+};
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRMUserVisual
+
+DECLARE_INTERFACE_(IDirect3DRMUserVisual, IDirect3DRMVisual)
+{
+    IUNKNOWN_METHODS(PURE);
+    IDIRECT3DRMOBJECT_METHODS(PURE);
+
+    /*
+     * IDirect3DRMUserVisual methods
+     */
+    STDMETHOD(Init)(THIS_ D3DRMUSERVISUALCALLBACK fn, void *arg) PURE;
+};
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRMArray
+
+DECLARE_INTERFACE_(IDirect3DRMArray, IUnknown)
+{
+    IUNKNOWN_METHODS(PURE);
+
+    STDMETHOD_(DWORD, GetSize)(THIS) PURE;
+    /* No GetElement method as it would get overloaded
+     * in derived classes, and overloading is
+     * a no-no in COM
+     */
+};
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRMDeviceArray
+
+DECLARE_INTERFACE_(IDirect3DRMDeviceArray, IDirect3DRMArray)
+{
+    IUNKNOWN_METHODS(PURE);
+
+    STDMETHOD_(DWORD, GetSize)(THIS) PURE;
+    STDMETHOD(GetElement)(THIS_ DWORD index, LPDIRECT3DRMDEVICE *) PURE;
+};
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRMFrameArray
+
+DECLARE_INTERFACE_(IDirect3DRMFrameArray, IDirect3DRMArray)
+{
+    IUNKNOWN_METHODS(PURE);
+
+    STDMETHOD_(DWORD, GetSize)(THIS) PURE;
+    STDMETHOD(GetElement)(THIS_ DWORD index, LPDIRECT3DRMFRAME *) PURE;
+};
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRMViewportArray
+
+DECLARE_INTERFACE_(IDirect3DRMViewportArray, IDirect3DRMArray)
+{
+    IUNKNOWN_METHODS(PURE);
+
+    STDMETHOD_(DWORD, GetSize)(THIS) PURE;
+    STDMETHOD(GetElement)(THIS_ DWORD index, LPDIRECT3DRMVIEWPORT *) PURE;
+};
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRMVisualArray
+
+DECLARE_INTERFACE_(IDirect3DRMVisualArray, IDirect3DRMArray)
+{
+    IUNKNOWN_METHODS(PURE);
+
+    STDMETHOD_(DWORD, GetSize)(THIS) PURE;
+    STDMETHOD(GetElement)(THIS_ DWORD index, LPDIRECT3DRMVISUAL *) PURE;
+};
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRMPickedArray
+
+DECLARE_INTERFACE_(IDirect3DRMPickedArray, IDirect3DRMArray)
+{
+    IUNKNOWN_METHODS(PURE);
+
+    STDMETHOD_(DWORD, GetSize)(THIS) PURE;
+    STDMETHOD(GetPick)(THIS_ DWORD index, LPDIRECT3DRMVISUAL *, LPDIRECT3DRMFRAMEARRAY *, LPD3DRMPICKDESC) PURE;
+};
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRMLightArray
+
+DECLARE_INTERFACE_(IDirect3DRMLightArray, IDirect3DRMArray)
+{
+    IUNKNOWN_METHODS(PURE);
+
+    STDMETHOD_(DWORD, GetSize)(THIS) PURE;
+    STDMETHOD(GetElement)(THIS_ DWORD index, LPDIRECT3DRMLIGHT *) PURE;
+};
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRMFaceArray
+
+DECLARE_INTERFACE_(IDirect3DRMFaceArray, IDirect3DRMArray)
+{
+    IUNKNOWN_METHODS(PURE);
+
+    STDMETHOD_(DWORD, GetSize)(THIS) PURE;
+    STDMETHOD(GetElement)(THIS_ DWORD index, LPDIRECT3DRMFACE *) PURE;
+};
+
+#ifdef __cplusplus
+};
+#endif
+#endif /* _D3DRMOBJ_H_ */
--- /dev/null
+++ b/WinQuake/dxsdk/SDK/INC/D3DRMWIN.H
@@ -1,0 +1,48 @@
+/*==========================================================================;
+ *
+ *  Copyright (C) 1995-1996 Microsoft Corporation.  All Rights Reserved.
+ *
+ *  File:       d3drm.h
+ *  Content:    Direct3DRM include file
+ *
+ ***************************************************************************/
+
+#ifndef __D3DRMWIN_H__
+#define __D3DRMWIN_H__
+
+#ifndef WIN32
+#define WIN32
+#endif
+
+#include "d3drm.h"
+#include "ddraw.h"
+#include "d3d.h"
+
+/*
+ * GUIDS used by Direct3DRM Windows interface
+ */
+DEFINE_GUID(IID_IDirect3DRMWinDevice,   0xc5016cc0, 0xd273, 0x11ce, 0xac, 0x48, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1);
+
+WIN_TYPES(IDirect3DRMWinDevice, DIRECT3DRMWINDEVICE);
+
+#undef INTERFACE
+#define INTERFACE IDirect3DRMWinDevice
+
+DECLARE_INTERFACE_(IDirect3DRMWinDevice, IDirect3DRMObject)
+{
+    IUNKNOWN_METHODS(PURE);
+    IDIRECT3DRMOBJECT_METHODS(PURE);
+
+    /*
+     * IDirect3DRMWinDevice methods
+     */
+
+    /* Repaint the window with the last frame which was rendered. */
+    STDMETHOD(HandlePaint)(THIS_ HDC hdc) PURE;
+
+    /* Respond to a WM_ACTIVATE message. */
+    STDMETHOD(HandleActivate)(THIS_ WORD wparam) PURE;
+};
+
+
+#endif
--- /dev/null
+++ b/WinQuake/dxsdk/SDK/INC/D3DTYPES.H
@@ -1,0 +1,956 @@
+/*==========================================================================;
+ *
+ *  Copyright (C) 1995-1996 Microsoft Corporation.  All Rights Reserved.
+ *
+ *  File:       d3dtypes.h
+ *  Content:    Direct3D types include file
+ *
+ ***************************************************************************/
+
+#ifndef _D3DTYPES_H_
+#define _D3DTYPES_H_
+
+#ifndef WIN32
+#include "subwtype.h"
+#else
+#include <windows.h>
+#endif
+
+#include <ddraw.h>
+
+#pragma pack(4)
+
+#if defined(__cplusplus)
+extern "C"
+{
+#endif
+
+/* D3DVALUE is the fundamental Direct3D fractional data type */
+
+#define D3DVALP(val, prec) ((float)(val))
+#define D3DVAL(val) ((float)(val))
+typedef float D3DVALUE, *LPD3DVALUE;
+#define D3DDivide(a, b)    (float)((double) (a) / (double) (b))
+#define D3DMultiply(a, b)    ((a) * (b))
+
+typedef LONG D3DFIXED;
+
+#ifndef RGB_MAKE
+/*
+ * Format of CI colors is
+ *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *  |    alpha      |         color index           |   fraction    |
+ *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+#define CI_GETALPHA(ci)    ((ci) >> 24)
+#define CI_GETINDEX(ci)    (((ci) >> 8) & 0xffff)
+#define CI_GETFRACTION(ci) ((ci) & 0xff)
+#define CI_ROUNDINDEX(ci)  CI_GETINDEX((ci) + 0x80)
+#define CI_MASKALPHA(ci)   ((ci) & 0xffffff)
+#define CI_MAKE(a, i, f)    (((a) << 24) | ((i) << 8) | (f))
+
+/*
+ * Format of RGBA colors is
+ *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *  |    alpha      |      red      |     green     |     blue      |
+ *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+#define RGBA_GETALPHA(rgb)      ((rgb) >> 24)
+#define RGBA_GETRED(rgb)        (((rgb) >> 16) & 0xff)
+#define RGBA_GETGREEN(rgb)      (((rgb) >> 8) & 0xff)
+#define RGBA_GETBLUE(rgb)       ((rgb) & 0xff)
+#define RGBA_MAKE(r, g, b, a)   ((D3DCOLOR) (((a) << 24) | ((r) << 16) | ((g) << 8) | (b)))
+
+/* D3DRGB and D3DRGBA may be used as initialisers for D3DCOLORs
+ * The float values must be in the range 0..1
+ */
+#define D3DRGB(r, g, b) \
+    (0xff000000L | ( ((long)((r) * 255)) << 16) | (((long)((g) * 255)) << 8) | (long)((b) * 255))
+#define D3DRGBA(r, g, b, a) \
+    (   (((long)((a) * 255)) << 24) | (((long)((r) * 255)) << 16) \
+    |   (((long)((g) * 255)) << 8) | (long)((b) * 255) \
+    )
+
+/*
+ * Format of RGB colors is
+ *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *  |    ignored    |      red      |     green     |     blue      |
+ *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+#define RGB_GETRED(rgb)         (((rgb) >> 16) & 0xff)
+#define RGB_GETGREEN(rgb)       (((rgb) >> 8) & 0xff)
+#define RGB_GETBLUE(rgb)        ((rgb) & 0xff)
+#define RGBA_SETALPHA(rgba, x) (((x) << 24) | ((rgba) & 0x00ffffff))
+#define RGB_MAKE(r, g, b)       ((D3DCOLOR) (((r) << 16) | ((g) << 8) | (b)))
+#define RGBA_TORGB(rgba)       ((D3DCOLOR) ((rgba) & 0xffffff))
+#define RGB_TORGBA(rgb)        ((D3DCOLOR) ((rgb) | 0xff000000))
+
+#endif
+
+/*
+ * Flags for Enumerate functions
+ */
+
+/*
+ * Stop the enumeration
+ */
+#define D3DENUMRET_CANCEL                        DDENUMRET_CANCEL
+
+/*
+ * Continue the enumeration
+ */
+#define D3DENUMRET_OK                            DDENUMRET_OK
+
+typedef HRESULT (WINAPI* LPD3DVALIDATECALLBACK)(LPVOID lpUserArg, DWORD dwOffset);
+typedef HRESULT (WINAPI* LPD3DENUMTEXTUREFORMATSCALLBACK)(LPDDSURFACEDESC lpDdsd, LPVOID lpContext);
+
+typedef DWORD D3DCOLOR, D3DCOLOR, *LPD3DCOLOR;
+
+typedef DWORD D3DMATERIALHANDLE, *LPD3DMATERIALHANDLE;
+typedef DWORD D3DTEXTUREHANDLE, *LPD3DTEXTUREHANDLE;
+typedef DWORD D3DMATRIXHANDLE, *LPD3DMATRIXHANDLE;
+
+typedef struct _D3DCOLORVALUE {
+    union {
+        D3DVALUE r;
+        D3DVALUE dvR;
+    };
+    union {
+        D3DVALUE g;
+        D3DVALUE dvG;
+    };
+    union {
+        D3DVALUE b;
+        D3DVALUE dvB;
+    };
+    union {
+        D3DVALUE a;
+        D3DVALUE dvA;
+    };
+} D3DCOLORVALUE;
+
+typedef struct _D3DRECT {
+    union {
+        LONG x1;
+        LONG lX1;
+    };
+    union {
+        LONG y1;
+        LONG lY1;
+    };
+    union {
+        LONG x2;
+        LONG lX2;
+    };
+    union {
+        LONG y2;
+        LONG lY2;
+    };
+} D3DRECT, *LPD3DRECT;
+
+typedef struct _D3DVECTOR {
+    union {
+        D3DVALUE x;
+        D3DVALUE dvX;
+    };
+    union {
+        D3DVALUE y;
+        D3DVALUE dvY;
+    };
+    union {
+        D3DVALUE z;
+        D3DVALUE dvZ;
+    };
+} D3DVECTOR, *LPD3DVECTOR;
+
+
+/*
+ * Vertex data types supported in an ExecuteBuffer.
+ */
+
+/*
+ * Homogeneous vertices
+ */
+
+typedef struct _D3DHVERTEX {
+    DWORD           dwFlags;        /* Homogeneous clipping flags */
+    union {
+        D3DVALUE    hx;
+        D3DVALUE    dvHX;
+    };
+    union {
+        D3DVALUE    hy;
+        D3DVALUE    dvHY;
+    };
+    union {
+        D3DVALUE    hz;
+        D3DVALUE    dvHZ;
+    };
+} D3DHVERTEX, *LPD3DHVERTEX;
+
+/*
+ * Transformed/lit vertices
+ */
+typedef struct _D3DTLVERTEX {
+    union {
+        D3DVALUE    sx;             /* Screen coordinates */
+        D3DVALUE    dvSX;
+    };
+    union {
+        D3DVALUE    sy;
+        D3DVALUE    dvSY;
+    };
+    union {
+        D3DVALUE    sz;
+        D3DVALUE    dvSZ;
+    };
+    union {
+        D3DVALUE    rhw;            /* Reciprocal of homogeneous w */
+        D3DVALUE    dvRHW;
+    };
+    union {
+        D3DCOLOR    color;          /* Vertex color */
+        D3DCOLOR    dcColor;
+    };
+    union {
+        D3DCOLOR    specular;       /* Specular component of vertex */
+        D3DCOLOR    dcSpecular;
+    };
+    union {
+        D3DVALUE    tu;             /* Texture coordinates */
+        D3DVALUE    dvTU;
+    };
+    union {
+        D3DVALUE    tv;
+        D3DVALUE    dvTV;
+    };
+} D3DTLVERTEX, *LPD3DTLVERTEX;
+
+/*
+ * Untransformed/lit vertices
+ */
+typedef struct _D3DLVERTEX {
+    union {
+        D3DVALUE     x;             /* Homogeneous coordinates */
+        D3DVALUE     dvX;
+    };
+    union {
+        D3DVALUE     y;
+        D3DVALUE     dvY;
+    };
+    union {
+        D3DVALUE     z;
+        D3DVALUE     dvZ;
+    };
+    DWORD            dwReserved;
+    union {
+        D3DCOLOR     color;         /* Vertex color */
+        D3DCOLOR     dcColor;
+    };
+    union {
+        D3DCOLOR     specular;      /* Specular component of vertex */
+        D3DCOLOR     dcSpecular;
+    };
+    union {
+        D3DVALUE     tu;            /* Texture coordinates */
+        D3DVALUE     dvTU;
+    };
+    union {
+        D3DVALUE     tv;
+        D3DVALUE     dvTV;
+    };
+} D3DLVERTEX, *LPD3DLVERTEX;
+
+/*
+ * Untransformed/unlit vertices
+ */
+
+typedef struct _D3DVERTEX {
+    union {
+        D3DVALUE     x;             /* Homogeneous coordinates */
+        D3DVALUE     dvX;
+    };
+    union {
+        D3DVALUE     y;
+        D3DVALUE     dvY;
+    };
+    union {
+        D3DVALUE     z;
+        D3DVALUE     dvZ;
+    };
+    union {
+        D3DVALUE     nx;            /* Normal */
+        D3DVALUE     dvNX;
+    };
+    union {
+        D3DVALUE     ny;
+        D3DVALUE     dvNY;
+    };
+    union {
+        D3DVALUE     nz;
+        D3DVALUE     dvNZ;
+    };
+    union {
+        D3DVALUE     tu;            /* Texture coordinates */
+        D3DVALUE     dvTU;
+    };
+    union {
+        D3DVALUE     tv;
+        D3DVALUE     dvTV;
+    };
+} D3DVERTEX, *LPD3DVERTEX;
+
+/*
+ * Matrix, viewport, and tranformation structures and definitions.
+ */
+
+typedef struct _D3DMATRIX {
+    D3DVALUE        _11, _12, _13, _14;
+    D3DVALUE        _21, _22, _23, _24;
+    D3DVALUE        _31, _32, _33, _34;
+    D3DVALUE        _41, _42, _43, _44;
+} D3DMATRIX, *LPD3DMATRIX;
+
+typedef struct _D3DVIEWPORT {
+    DWORD       dwSize;
+    DWORD       dwX;
+    DWORD       dwY;            /* Top left */
+    DWORD       dwWidth;
+    DWORD       dwHeight;       /* Dimensions */
+    D3DVALUE    dvScaleX;       /* Scale homogeneous to screen */
+    D3DVALUE    dvScaleY;       /* Scale homogeneous to screen */
+    D3DVALUE    dvMaxX;         /* Min/max homogeneous x coord */
+    D3DVALUE    dvMaxY;         /* Min/max homogeneous y coord */
+    D3DVALUE    dvMinZ;
+    D3DVALUE    dvMaxZ;         /* Min/max homogeneous z coord */
+} D3DVIEWPORT, *LPD3DVIEWPORT;
+
+/*
+ * Values for clip fields.
+ */
+#define D3DCLIP_LEFT                            0x00000001L
+#define D3DCLIP_RIGHT                           0x00000002L
+#define D3DCLIP_TOP                             0x00000004L
+#define D3DCLIP_BOTTOM                          0x00000008L
+#define D3DCLIP_FRONT                           0x00000010L
+#define D3DCLIP_BACK                            0x00000020L
+#define D3DCLIP_GEN0                            0x00000040L
+#define D3DCLIP_GEN1                            0x00000080L
+#define D3DCLIP_GEN2                            0x00000100L
+#define D3DCLIP_GEN3                            0x00000200L
+#define D3DCLIP_GEN4                            0x00000400L
+#define D3DCLIP_GEN5                            0x00000800L
+
+/*
+ * Values for d3d status.
+ */
+#define D3DSTATUS_CLIPUNIONLEFT                 D3DCLIP_LEFT
+#define D3DSTATUS_CLIPUNIONRIGHT                D3DCLIP_RIGHT
+#define D3DSTATUS_CLIPUNIONTOP                  D3DCLIP_TOP
+#define D3DSTATUS_CLIPUNIONBOTTOM               D3DCLIP_BOTTOM
+#define D3DSTATUS_CLIPUNIONFRONT                D3DCLIP_FRONT
+#define D3DSTATUS_CLIPUNIONBACK                 D3DCLIP_BACK
+#define D3DSTATUS_CLIPUNIONGEN0                 D3DCLIP_GEN0
+#define D3DSTATUS_CLIPUNIONGEN1                 D3DCLIP_GEN1
+#define D3DSTATUS_CLIPUNIONGEN2                 D3DCLIP_GEN2
+#define D3DSTATUS_CLIPUNIONGEN3                 D3DCLIP_GEN3
+#define D3DSTATUS_CLIPUNIONGEN4                 D3DCLIP_GEN4
+#define D3DSTATUS_CLIPUNIONGEN5                 D3DCLIP_GEN5
+
+#define D3DSTATUS_CLIPINTERSECTIONLEFT          0x00001000L
+#define D3DSTATUS_CLIPINTERSECTIONRIGHT         0x00002000L
+#define D3DSTATUS_CLIPINTERSECTIONTOP           0x00004000L
+#define D3DSTATUS_CLIPINTERSECTIONBOTTOM        0x00008000L
+#define D3DSTATUS_CLIPINTERSECTIONFRONT         0x00010000L
+#define D3DSTATUS_CLIPINTERSECTIONBACK          0x00020000L
+#define D3DSTATUS_CLIPINTERSECTIONGEN0          0x00040000L
+#define D3DSTATUS_CLIPINTERSECTIONGEN1          0x00080000L
+#define D3DSTATUS_CLIPINTERSECTIONGEN2          0x00100000L
+#define D3DSTATUS_CLIPINTERSECTIONGEN3          0x00200000L
+#define D3DSTATUS_CLIPINTERSECTIONGEN4          0x00400000L
+#define D3DSTATUS_CLIPINTERSECTIONGEN5          0x00800000L
+#define D3DSTATUS_ZNOTVISIBLE                   0x01000000L
+
+#define D3DSTATUS_CLIPUNIONALL  (               \
+            D3DSTATUS_CLIPUNIONLEFT     |       \
+            D3DSTATUS_CLIPUNIONRIGHT    |       \
+            D3DSTATUS_CLIPUNIONTOP      |       \
+            D3DSTATUS_CLIPUNIONBOTTOM   |       \
+            D3DSTATUS_CLIPUNIONFRONT    |       \
+            D3DSTATUS_CLIPUNIONBACK     |       \
+            D3DSTATUS_CLIPUNIONGEN0     |       \
+            D3DSTATUS_CLIPUNIONGEN1     |       \
+            D3DSTATUS_CLIPUNIONGEN2     |       \
+            D3DSTATUS_CLIPUNIONGEN3     |       \
+            D3DSTATUS_CLIPUNIONGEN4     |       \
+            D3DSTATUS_CLIPUNIONGEN5             \
+            )
+
+#define D3DSTATUS_CLIPINTERSECTIONALL   (               \
+            D3DSTATUS_CLIPINTERSECTIONLEFT      |       \
+            D3DSTATUS_CLIPINTERSECTIONRIGHT     |       \
+            D3DSTATUS_CLIPINTERSECTIONTOP       |       \
+            D3DSTATUS_CLIPINTERSECTIONBOTTOM    |       \
+            D3DSTATUS_CLIPINTERSECTIONFRONT     |       \
+            D3DSTATUS_CLIPINTERSECTIONBACK      |       \
+            D3DSTATUS_CLIPINTERSECTIONGEN0      |       \
+            D3DSTATUS_CLIPINTERSECTIONGEN1      |       \
+            D3DSTATUS_CLIPINTERSECTIONGEN2      |       \
+            D3DSTATUS_CLIPINTERSECTIONGEN3      |       \
+            D3DSTATUS_CLIPINTERSECTIONGEN4      |       \
+            D3DSTATUS_CLIPINTERSECTIONGEN5              \
+            )
+
+#define D3DSTATUS_DEFAULT       (                       \
+            D3DSTATUS_CLIPINTERSECTIONALL       |       \
+            D3DSTATUS_ZNOTVISIBLE)
+
+
+/*
+ * Options for direct transform calls
+ */
+#define D3DTRANSFORM_CLIPPED       0x00000001l
+#define D3DTRANSFORM_UNCLIPPED     0x00000002l
+
+typedef struct _D3DTRANSFORMDATA {
+    DWORD           dwSize;
+    LPVOID          lpIn;           /* Input vertices */
+    DWORD           dwInSize;       /* Stride of input vertices */
+    LPVOID          lpOut;          /* Output vertices */
+    DWORD           dwOutSize;      /* Stride of output vertices */
+    LPD3DHVERTEX    lpHOut;         /* Output homogeneous vertices */
+    DWORD           dwClip;         /* Clipping hint */
+    DWORD           dwClipIntersection;
+    DWORD           dwClipUnion;    /* Union of all clip flags */
+    D3DRECT         drExtent;       /* Extent of transformed vertices */
+} D3DTRANSFORMDATA, *LPD3DTRANSFORMDATA;
+
+/*
+ * Structure defining position and direction properties for lighting.
+ */
+typedef struct _D3DLIGHTINGELEMENT {
+    D3DVECTOR dvPosition;           /* Lightable point in model space */
+    D3DVECTOR dvNormal;             /* Normalised unit vector */
+} D3DLIGHTINGELEMENT, *LPD3DLIGHTINGELEMENT;
+
+/*
+ * Structure defining material properties for lighting.
+ */
+typedef struct _D3DMATERIAL {
+    DWORD               dwSize;
+    union {
+        D3DCOLORVALUE   diffuse;        /* Diffuse color RGBA */
+        D3DCOLORVALUE   dcvDiffuse;
+    };
+    union {
+        D3DCOLORVALUE   ambient;        /* Ambient color RGB */
+        D3DCOLORVALUE   dcvAmbient;
+    };
+    union {
+        D3DCOLORVALUE   specular;       /* Specular 'shininess' */
+        D3DCOLORVALUE   dcvSpecular;
+    };
+    union {
+        D3DCOLORVALUE   emissive;       /* Emissive color RGB */
+        D3DCOLORVALUE   dcvEmissive;
+    };
+    union {
+        D3DVALUE        power;          /* Sharpness if specular highlight */
+        D3DVALUE        dvPower;
+    };
+    D3DTEXTUREHANDLE    hTexture;       /* Handle to texture map */
+    DWORD               dwRampSize;
+} D3DMATERIAL, *LPD3DMATERIAL;
+
+typedef enum _D3DLIGHTTYPE {
+    D3DLIGHT_POINT          = 1,
+    D3DLIGHT_SPOT           = 2,
+    D3DLIGHT_DIRECTIONAL    = 3,
+    D3DLIGHT_PARALLELPOINT  = 4,
+    D3DLIGHT_GLSPOT         = 5,
+} D3DLIGHTTYPE;
+
+/*
+ * Structure defining a light source and its properties.
+ */
+typedef struct _D3DLIGHT {
+    DWORD           dwSize;
+    D3DLIGHTTYPE    dltType;            /* Type of light source */
+    D3DCOLORVALUE   dcvColor;           /* Color of light */
+    D3DVECTOR       dvPosition;         /* Position in world space */
+    D3DVECTOR       dvDirection;        /* Direction in world space */
+    D3DVALUE        dvRange;            /* Cutoff range */
+    D3DVALUE        dvFalloff;          /* Falloff */
+    D3DVALUE        dvAttenuation0;     /* Constant attenuation */
+    D3DVALUE        dvAttenuation1;     /* Linear attenuation */
+    D3DVALUE        dvAttenuation2;     /* Quadratic attenuation */
+    D3DVALUE        dvTheta;            /* Inner angle of spotlight cone */
+    D3DVALUE        dvPhi;              /* Outer angle of spotlight cone */
+} D3DLIGHT, *LPD3DLIGHT;
+
+typedef struct _D3DLIGHTDATA {
+    DWORD                dwSize;
+    LPD3DLIGHTINGELEMENT lpIn;          /* Input positions and normals */
+    DWORD                dwInSize;      /* Stride of input elements */
+    LPD3DTLVERTEX        lpOut;         /* Output colors */
+    DWORD                dwOutSize;     /* Stride of output colors */
+} D3DLIGHTDATA, *LPD3DLIGHTDATA;
+
+typedef enum _D3DCOLORMODEL {
+    D3DCOLOR_MONO           = 1,
+    D3DCOLOR_RGB            = 2,
+} D3DCOLORMODEL;
+
+/*
+ * Options for clearing
+ */
+#define D3DCLEAR_TARGET            0x00000001l /* Clear target surface */
+#define D3DCLEAR_ZBUFFER           0x00000002l /* Clear target z buffer */
+
+/*
+ * Execute buffers are allocated via Direct3D.  These buffers may then
+ * be filled by the application with instructions to execute along with
+ * vertex data.
+ */
+
+/*
+ * Supported op codes for execute instructions.
+ */
+typedef enum _D3DOPCODE {
+    D3DOP_POINT                 = 1,
+    D3DOP_LINE                  = 2,
+    D3DOP_TRIANGLE              = 3,
+    D3DOP_MATRIXLOAD            = 4,
+    D3DOP_MATRIXMULTIPLY        = 5,
+    D3DOP_STATETRANSFORM        = 6,
+    D3DOP_STATELIGHT            = 7,
+    D3DOP_STATERENDER           = 8,
+    D3DOP_PROCESSVERTICES       = 9,
+    D3DOP_TEXTURELOAD           = 10,
+    D3DOP_EXIT                  = 11,
+    D3DOP_BRANCHFORWARD         = 12,
+    D3DOP_SPAN                  = 13,
+    D3DOP_SETSTATUS             = 14,
+} D3DOPCODE;
+
+typedef struct _D3DINSTRUCTION {
+    BYTE bOpcode;   /* Instruction opcode */
+    BYTE bSize;     /* Size of each instruction data unit */
+    WORD wCount;    /* Count of instruction data units to follow */
+} D3DINSTRUCTION, *LPD3DINSTRUCTION;
+
+/*
+ * Structure for texture loads
+ */
+typedef struct _D3DTEXTURELOAD {
+    D3DTEXTUREHANDLE hDestTexture;
+    D3DTEXTUREHANDLE hSrcTexture;
+} D3DTEXTURELOAD, *LPD3DTEXTURELOAD;
+
+/*
+ * Structure for picking
+ */
+typedef struct _D3DPICKRECORD {
+    BYTE     bOpcode;
+    BYTE     bPad;
+    DWORD    dwOffset;
+    D3DVALUE dvZ;
+} D3DPICKRECORD, *LPD3DPICKRECORD;
+
+/*
+ * The following defines the rendering states which can be set in the
+ * execute buffer.
+ */
+
+typedef enum _D3DSHADEMODE {
+    D3DSHADE_FLAT              = 1,
+    D3DSHADE_GOURAUD           = 2,
+    D3DSHADE_PHONG             = 3,
+} D3DSHADEMODE;
+
+typedef enum _D3DFILLMODE {
+    D3DFILL_POINT              = 1,
+    D3DFILL_WIREFRAME          = 2,
+    D3DFILL_SOLID              = 3,
+} D3DFILLMODE;
+
+typedef struct _D3DLINEPATTERN {
+    WORD        wRepeatFactor;
+    WORD        wLinePattern;
+} D3DLINEPATTERN;
+
+typedef enum _D3DTEXTUREFILTER {
+    D3DFILTER_NEAREST          = 1,
+    D3DFILTER_LINEAR           = 2,
+    D3DFILTER_MIPNEAREST       = 3,
+    D3DFILTER_MIPLINEAR        = 4,
+    D3DFILTER_LINEARMIPNEAREST = 5,
+    D3DFILTER_LINEARMIPLINEAR  = 6,
+} D3DTEXTUREFILTER;
+
+typedef enum _D3DBLEND {
+    D3DBLEND_ZERO              = 1,
+    D3DBLEND_ONE               = 2,
+    D3DBLEND_SRCCOLOR          = 3,
+    D3DBLEND_INVSRCCOLOR       = 4,
+    D3DBLEND_SRCALPHA          = 5,
+    D3DBLEND_INVSRCALPHA       = 6,
+    D3DBLEND_DESTALPHA         = 7,
+    D3DBLEND_INVDESTALPHA      = 8,
+    D3DBLEND_DESTCOLOR         = 9,
+    D3DBLEND_INVDESTCOLOR      = 10,
+    D3DBLEND_SRCALPHASAT       = 11,
+    D3DBLEND_BOTHSRCALPHA      = 12,
+    D3DBLEND_BOTHINVSRCALPHA   = 13,
+} D3DBLEND;
+
+typedef enum _D3DTEXTUREBLEND {
+    D3DTBLEND_DECAL            = 1,
+    D3DTBLEND_MODULATE         = 2,
+    D3DTBLEND_DECALALPHA       = 3,
+    D3DTBLEND_MODULATEALPHA    = 4,
+    D3DTBLEND_DECALMASK        = 5,
+    D3DTBLEND_MODULATEMASK     = 6,
+    D3DTBLEND_COPY             = 7,
+} D3DTEXTUREBLEND;
+
+typedef enum _D3DTEXTUREADDRESS {
+    D3DTADDRESS_WRAP           = 1,
+    D3DTADDRESS_MIRROR         = 2,
+    D3DTADDRESS_CLAMP          = 3,
+} D3DTEXTUREADDRESS;
+
+typedef enum _D3DCULL {
+    D3DCULL_NONE               = 1,
+    D3DCULL_CW                 = 2,
+    D3DCULL_CCW                = 3,
+} D3DCULL;
+
+typedef enum _D3DCMPFUNC {
+    D3DCMP_NEVER               = 1,
+    D3DCMP_LESS                = 2,
+    D3DCMP_EQUAL               = 3,
+    D3DCMP_LESSEQUAL           = 4,
+    D3DCMP_GREATER             = 5,
+    D3DCMP_NOTEQUAL            = 6,
+    D3DCMP_GREATEREQUAL        = 7,
+    D3DCMP_ALWAYS              = 8,
+} D3DCMPFUNC;
+
+typedef enum _D3DFOGMODE {
+    D3DFOG_NONE                = 0,
+    D3DFOG_EXP                 = 1,
+    D3DFOG_EXP2                = 2,
+    D3DFOG_LINEAR              = 3
+} D3DFOGMODE;
+
+/*
+ * Amount to add to a state to generate the override for that state.
+ */
+#define D3DSTATE_OVERRIDE_BIAS          256
+
+/*
+ * A state which sets the override flag for the specified state type.
+ */
+#define D3DSTATE_OVERRIDE(type) ((DWORD) (type) + D3DSTATE_OVERRIDE_BIAS)
+
+typedef enum _D3DTRANSFORMSTATETYPE {
+    D3DTRANSFORMSTATE_WORLD           = 1,
+    D3DTRANSFORMSTATE_VIEW            = 2,
+    D3DTRANSFORMSTATE_PROJECTION      = 3,
+} D3DTRANSFORMSTATETYPE;
+
+typedef enum _D3DLIGHTSTATETYPE {
+    D3DLIGHTSTATE_MATERIAL            = 1,
+    D3DLIGHTSTATE_AMBIENT             = 2,
+    D3DLIGHTSTATE_COLORMODEL          = 3,
+    D3DLIGHTSTATE_FOGMODE             = 4,
+    D3DLIGHTSTATE_FOGSTART            = 5,
+    D3DLIGHTSTATE_FOGEND              = 6,
+    D3DLIGHTSTATE_FOGDENSITY          = 7,
+} D3DLIGHTSTATETYPE;
+
+typedef enum _D3DRENDERSTATETYPE {
+    D3DRENDERSTATE_TEXTUREHANDLE      = 1,    /* Texture handle */
+    D3DRENDERSTATE_ANTIALIAS          = 2,    /* Antialiasing prim edges */
+    D3DRENDERSTATE_TEXTUREADDRESS     = 3,    /* D3DTEXTUREADDRESS      */
+    D3DRENDERSTATE_TEXTUREPERSPECTIVE = 4,    /* TRUE for perspective correction */
+    D3DRENDERSTATE_WRAPU              = 5,    /* TRUE for wrapping in u */
+    D3DRENDERSTATE_WRAPV              = 6,    /* TRUE for wrapping in v */
+    D3DRENDERSTATE_ZENABLE            = 7,    /* TRUE to enable z test */
+    D3DRENDERSTATE_FILLMODE           = 8,    /* D3DFILL_MODE            */
+    D3DRENDERSTATE_SHADEMODE          = 9,    /* D3DSHADEMODE */
+    D3DRENDERSTATE_LINEPATTERN        = 10,   /* D3DLINEPATTERN */
+    D3DRENDERSTATE_MONOENABLE         = 11,   /* TRUE to enable mono rasterization */
+    D3DRENDERSTATE_ROP2               = 12,   /* ROP2 */
+    D3DRENDERSTATE_PLANEMASK          = 13,   /* DWORD physical plane mask */
+    D3DRENDERSTATE_ZWRITEENABLE       = 14,   /* TRUE to enable z writes */
+    D3DRENDERSTATE_ALPHATESTENABLE    = 15,   /* TRUE to enable alpha tests */
+    D3DRENDERSTATE_LASTPIXEL          = 16,   /* TRUE for last-pixel on lines */
+    D3DRENDERSTATE_TEXTUREMAG         = 17,   /* D3DTEXTUREFILTER */
+    D3DRENDERSTATE_TEXTUREMIN         = 18,   /* D3DTEXTUREFILTER */
+    D3DRENDERSTATE_SRCBLEND           = 19,   /* D3DBLEND */
+    D3DRENDERSTATE_DESTBLEND          = 20,   /* D3DBLEND */
+    D3DRENDERSTATE_TEXTUREMAPBLEND    = 21,   /* D3DTEXTUREBLEND */
+    D3DRENDERSTATE_CULLMODE           = 22,   /* D3DCULL */
+    D3DRENDERSTATE_ZFUNC              = 23,   /* D3DCMPFUNC */
+    D3DRENDERSTATE_ALPHAREF           = 24,   /* D3DFIXED */
+    D3DRENDERSTATE_ALPHAFUNC          = 25,   /* D3DCMPFUNC */
+    D3DRENDERSTATE_DITHERENABLE       = 26,   /* TRUE to enable dithering */
+    D3DRENDERSTATE_BLENDENABLE        = 27,   /* TRUE to enable alpha blending */
+    D3DRENDERSTATE_FOGENABLE          = 28,   /* TRUE to enable fog */
+    D3DRENDERSTATE_SPECULARENABLE     = 29,   /* TRUE to enable specular */
+    D3DRENDERSTATE_ZVISIBLE           = 30,   /* TRUE to enable z checking */
+    D3DRENDERSTATE_SUBPIXEL           = 31,   /* TRUE to enable subpixel correction */
+    D3DRENDERSTATE_SUBPIXELX          = 32,   /* TRUE to enable correction in X only */
+    D3DRENDERSTATE_STIPPLEDALPHA      = 33,   /* TRUE to enable stippled alpha */
+    D3DRENDERSTATE_FOGCOLOR           = 34,   /* D3DCOLOR */
+    D3DRENDERSTATE_FOGTABLEMODE       = 35,   /* D3DFOGMODE */
+    D3DRENDERSTATE_FOGTABLESTART      = 36,   /* Fog table start        */
+    D3DRENDERSTATE_FOGTABLEEND        = 37,   /* Fog table end          */
+    D3DRENDERSTATE_FOGTABLEDENSITY    = 38,   /* Fog table density      */
+    D3DRENDERSTATE_STIPPLEENABLE      = 39,   /* TRUE to enable stippling */
+    D3DRENDERSTATE_STIPPLEPATTERN00   = 64,   /* Stipple pattern 01...  */      
+    D3DRENDERSTATE_STIPPLEPATTERN01   = 65,
+    D3DRENDERSTATE_STIPPLEPATTERN02   = 66,
+    D3DRENDERSTATE_STIPPLEPATTERN03   = 67,
+    D3DRENDERSTATE_STIPPLEPATTERN04   = 68,
+    D3DRENDERSTATE_STIPPLEPATTERN05   = 69,
+    D3DRENDERSTATE_STIPPLEPATTERN06   = 70,
+    D3DRENDERSTATE_STIPPLEPATTERN07   = 71,
+    D3DRENDERSTATE_STIPPLEPATTERN08   = 72,
+    D3DRENDERSTATE_STIPPLEPATTERN09   = 73,
+    D3DRENDERSTATE_STIPPLEPATTERN10   = 74,
+    D3DRENDERSTATE_STIPPLEPATTERN11   = 75,
+    D3DRENDERSTATE_STIPPLEPATTERN12   = 76,
+    D3DRENDERSTATE_STIPPLEPATTERN13   = 77,
+    D3DRENDERSTATE_STIPPLEPATTERN14   = 78,
+    D3DRENDERSTATE_STIPPLEPATTERN15   = 79,
+    D3DRENDERSTATE_STIPPLEPATTERN16   = 80,
+    D3DRENDERSTATE_STIPPLEPATTERN17   = 81,
+    D3DRENDERSTATE_STIPPLEPATTERN18   = 82,
+    D3DRENDERSTATE_STIPPLEPATTERN19   = 83,
+    D3DRENDERSTATE_STIPPLEPATTERN20   = 84,
+    D3DRENDERSTATE_STIPPLEPATTERN21   = 85,
+    D3DRENDERSTATE_STIPPLEPATTERN22   = 86,
+    D3DRENDERSTATE_STIPPLEPATTERN23   = 87,
+    D3DRENDERSTATE_STIPPLEPATTERN24   = 88,
+    D3DRENDERSTATE_STIPPLEPATTERN25   = 89,
+    D3DRENDERSTATE_STIPPLEPATTERN26   = 90,
+    D3DRENDERSTATE_STIPPLEPATTERN27   = 91,
+    D3DRENDERSTATE_STIPPLEPATTERN28   = 92,
+    D3DRENDERSTATE_STIPPLEPATTERN29   = 93,
+    D3DRENDERSTATE_STIPPLEPATTERN30   = 94,
+    D3DRENDERSTATE_STIPPLEPATTERN31   = 95,
+} D3DRENDERSTATETYPE;
+
+#define D3DRENDERSTATE_STIPPLEPATTERN(y) (D3DRENDERSTATE_STIPPLEPATTERN00 + (y))
+
+typedef struct _D3DSTATE {
+    union {
+        D3DTRANSFORMSTATETYPE   dtstTransformStateType;
+        D3DLIGHTSTATETYPE       dlstLightStateType;
+        D3DRENDERSTATETYPE      drstRenderStateType;
+    };
+    union {
+        DWORD                   dwArg[1];
+        D3DVALUE                dvArg[1];
+    };
+} D3DSTATE, *LPD3DSTATE;
+
+/*
+ * Operation used to load matrices
+ * hDstMat = hSrcMat
+ */
+typedef struct _D3DMATRIXLOAD {
+    D3DMATRIXHANDLE hDestMatrix;   /* Destination matrix */
+    D3DMATRIXHANDLE hSrcMatrix;   /* Source matrix */
+} D3DMATRIXLOAD, *LPD3DMATRIXLOAD;
+
+/*
+ * Operation used to multiply matrices
+ * hDstMat = hSrcMat1 * hSrcMat2
+ */
+typedef struct _D3DMATRIXMULTIPLY {
+    D3DMATRIXHANDLE hDestMatrix;   /* Destination matrix */
+    D3DMATRIXHANDLE hSrcMatrix1;  /* First source matrix */
+    D3DMATRIXHANDLE hSrcMatrix2;  /* Second source matrix */
+} D3DMATRIXMULTIPLY, *LPD3DMATRIXMULTIPLY;
+
+/*
+ * Operation used to transform and light vertices.
+ */
+typedef struct _D3DPROCESSVERTICES {
+    DWORD        dwFlags;    /* Do we transform or light or just copy? */
+    WORD         wStart;     /* Index to first vertex in source */
+    WORD         wDest;      /* Index to first vertex in local buffer */
+    DWORD        dwCount;    /* Number of vertices to be processed */
+    DWORD        dwReserved; /* Must be zero */
+} D3DPROCESSVERTICES, *LPD3DPROCESSVERTICES;
+
+#define D3DPROCESSVERTICES_TRANSFORMLIGHT       0x00000000L
+#define D3DPROCESSVERTICES_TRANSFORM            0x00000001L
+#define D3DPROCESSVERTICES_COPY                 0x00000002L
+#define D3DPROCESSVERTICES_OPMASK               0x00000007L
+
+#define D3DPROCESSVERTICES_UPDATEEXTENTS        0x00000008L
+#define D3DPROCESSVERTICES_NOCOLOR              0x00000010L
+
+
+/*
+ * Triangle flags
+ */
+ 
+/*
+ * Tri strip and fan flags.
+ * START loads all three vertices
+ * EVEN and ODD load just v3 with even or odd culling
+ * START_FLAT contains a count from 0 to 29 that allows the
+ * whole strip or fan to be culled in one hit.
+ * e.g. for a quad len = 1
+ */
+#define D3DTRIFLAG_START                        0x00000000L
+#define D3DTRIFLAG_STARTFLAT(len) (len)         /* 0 < len < 30 */
+#define D3DTRIFLAG_ODD                          0x0000001eL
+#define D3DTRIFLAG_EVEN                         0x0000001fL
+
+/*
+ * Triangle edge flags
+ * enable edges for wireframe or antialiasing
+ */
+#define D3DTRIFLAG_EDGEENABLE1                  0x00000100L /* v0-v1 edge */
+#define D3DTRIFLAG_EDGEENABLE2                  0x00000200L /* v1-v2 edge */
+#define D3DTRIFLAG_EDGEENABLE3                  0x00000400L /* v2-v0 edge */
+#define D3DTRIFLAG_EDGEENABLETRIANGLE \
+        (D3DTRIFLAG_EDGEENABLE1 | D3DTRIFLAG_EDGEENABLE2 | D3DTRIFLAG_EDGEENABLE3)
+        
+/*
+ * Primitive structures and related defines.  Vertex offsets are to types
+ * D3DVERTEX, D3DLVERTEX, or D3DTLVERTEX.
+ */
+
+/*
+ * Triangle list primitive structure
+ */
+typedef struct _D3DTRIANGLE {
+    union {
+        WORD    v1;            /* Vertex indices */
+        WORD    wV1;
+    };
+    union {
+        WORD    v2;
+        WORD    wV2;
+    };
+    union {
+        WORD    v3;
+        WORD    wV3;
+    };
+    WORD        wFlags;       /* Edge (and other) flags */
+} D3DTRIANGLE, *LPD3DTRIANGLE;
+
+/*
+ * Line strip structure.
+ * The instruction count - 1 defines the number of line segments.
+ */
+typedef struct _D3DLINE {
+    union {
+        WORD    v1;            /* Vertex indices */
+        WORD    wV1;
+    };
+    union {
+        WORD    v2;
+        WORD    wV2;
+    };
+} D3DLINE, *LPD3DLINE;
+
+/*
+ * Span structure
+ * Spans join a list of points with the same y value.
+ * If the y value changes, a new span is started.
+ */
+typedef struct _D3DSPAN {
+    WORD        wCount; /* Number of spans */
+    WORD        wFirst; /* Index to first vertex */
+} D3DSPAN, *LPD3DSPAN;
+
+/*
+ * Point structure
+ */
+typedef struct _D3DPOINT {
+    WORD        wCount;         /* number of points         */
+    WORD        wFirst;         /* index to first vertex    */
+} D3DPOINT, *LPD3DPOINT;
+
+
+/*
+ * Forward branch structure.
+ * Mask is logically anded with the driver status mask
+ * if the result equals 'value', the branch is taken.
+ */
+typedef struct _D3DBRANCH {
+    DWORD       dwMask;         /* Bitmask against D3D status */
+    DWORD       dwValue;
+    BOOL        bNegate;        /* TRUE to negate comparison */
+    DWORD       dwOffset;       /* How far to branch forward (0 for exit)*/
+} D3DBRANCH, *LPD3DBRANCH;
+
+/*
+ * Status used for set status instruction.
+ * The D3D status is initialised on device creation
+ * and is modified by all execute calls.
+ */
+typedef struct _D3DSTATUS {
+    DWORD       dwFlags;        /* Do we set extents or status */
+    DWORD       dwStatus;       /* D3D status */
+    D3DRECT     drExtent;
+} D3DSTATUS, *LPD3DSTATUS;
+
+#define D3DSETSTATUS_STATUS             0x00000001L
+#define D3DSETSTATUS_EXTENTS            0x00000002L
+#define D3DSETSTATUS_ALL        (D3DSETSTATUS_STATUS | D3DSETSTATUS_EXTENTS)
+
+/*
+ * Statistics structure
+ */
+typedef struct _D3DSTATS {
+    DWORD        dwSize;
+    DWORD        dwTrianglesDrawn;
+    DWORD        dwLinesDrawn;
+    DWORD        dwPointsDrawn;
+    DWORD        dwSpansDrawn;
+    DWORD        dwVerticesProcessed;
+} D3DSTATS, *LPD3DSTATS;
+
+/*
+ * Execute options.
+ * When calling using D3DEXECUTE_UNCLIPPED all the primitives 
+ * inside the buffer must be contained within the viewport.
+ */
+#define D3DEXECUTE_CLIPPED       0x00000001l
+#define D3DEXECUTE_UNCLIPPED     0x00000002l
+
+typedef struct _D3DEXECUTEDATA {
+    DWORD       dwSize;
+    DWORD       dwVertexOffset;
+    DWORD       dwVertexCount;
+    DWORD       dwInstructionOffset;
+    DWORD       dwInstructionLength;
+    DWORD       dwHVertexOffset;
+    D3DSTATUS   dsStatus;       /* Status after execute */
+} D3DEXECUTEDATA, *LPD3DEXECUTEDATA;
+
+/*
+ * Palette flags.
+ * This are or'ed with the peFlags in the PALETTEENTRYs passed to DirectDraw.
+ */
+#define D3DPAL_FREE     0x00    /* Renderer may use this entry freely */
+#define D3DPAL_READONLY 0x40    /* Renderer may not set this entry */
+#define D3DPAL_RESERVED 0x80    /* Renderer may not use this entry */
+
+#if defined(__cplusplus)
+};
+#endif
+
+#pragma pack()
+
+#endif /* _D3DTYPES_H_ */
--- /dev/null
+++ b/WinQuake/dxsdk/SDK/INC/DDRAW.H
@@ -1,0 +1,3102 @@
+/*==========================================================================;
+ *
+ *  Copyright (C) 1994-1996 Microsoft Corporation.  All Rights Reserved.
+ *
+ *  File:       ddraw.h
+ *  Content:    DirectDraw include file
+ *
+ ***************************************************************************/
+
+#ifndef __DDRAW_INCLUDED__
+#define __DDRAW_INCLUDED__
+#if defined( _WIN32 )  && !defined( _NO_COM )
+#define COM_NO_WINDOWS_H
+#include <objbase.h>
+#else
+#define IUnknown            void
+#define CO_E_NOTINITIALIZED 0x800401F0L
+#endif
+
+#define _FACDD  0x876
+#define MAKE_DDHRESULT( code )  MAKE_HRESULT( 1, _FACDD, code )
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * GUIDS used by DirectDraw objects
+ */
+#if defined( _WIN32 ) && !defined( _NO_COM )
+DEFINE_GUID( CLSID_DirectDraw,                  0xD7B70EE0,0x4340,0x11CF,0xB0,0x63,0x00,0x20,0xAF,0xC2,0xCD,0x35 );
+DEFINE_GUID( CLSID_DirectDrawClipper,           0x593817A0,0x7DB3,0x11CF,0xA2,0xDE,0x00,0xAA,0x00,0xb9,0x33,0x56 );
+DEFINE_GUID( IID_IDirectDraw,                   0x6C14DB80,0xA733,0x11CE,0xA5,0x21,0x00,0x20,0xAF,0x0B,0xE5,0x60 );
+DEFINE_GUID( IID_IDirectDraw2,                  0xB3A6F3E0,0x2B43,0x11CF,0xA2,0xDE,0x00,0xAA,0x00,0xB9,0x33,0x56 );
+DEFINE_GUID( IID_IDirectDrawSurface,            0x6C14DB81,0xA733,0x11CE,0xA5,0x21,0x00,0x20,0xAF,0x0B,0xE5,0x60 );
+DEFINE_GUID( IID_IDirectDrawSurface2,           0x57805885,0x6eec,0x11cf,0x94,0x41,0xa8,0x23,0x03,0xc1,0x0e,0x27 );
+
+DEFINE_GUID( IID_IDirectDrawPalette,            0x6C14DB84,0xA733,0x11CE,0xA5,0x21,0x00,0x20,0xAF,0x0B,0xE5,0x60 );
+DEFINE_GUID( IID_IDirectDrawClipper,            0x6C14DB85,0xA733,0x11CE,0xA5,0x21,0x00,0x20,0xAF,0x0B,0xE5,0x60 );
+                 
+#endif
+
+/*============================================================================
+ *
+ * DirectDraw Structures
+ *
+ * Various structures used to invoke DirectDraw.
+ *
+ *==========================================================================*/
+
+struct IDirectDraw;
+struct IDirectDrawSurface;
+struct IDirectDrawPalette;
+struct IDirectDrawClipper;
+
+typedef struct IDirectDraw                      FAR *LPDIRECTDRAW;
+typedef struct IDirectDraw2                     FAR *LPDIRECTDRAW2;
+typedef struct IDirectDrawSurface               FAR *LPDIRECTDRAWSURFACE;
+typedef struct IDirectDrawSurface2              FAR *LPDIRECTDRAWSURFACE2;
+
+typedef struct IDirectDrawPalette               FAR *LPDIRECTDRAWPALETTE;
+typedef struct IDirectDrawClipper               FAR *LPDIRECTDRAWCLIPPER;
+
+typedef struct _DDFXROP                 FAR *LPDDFXROP;
+typedef struct _DDSURFACEDESC           FAR *LPDDSURFACEDESC;
+
+/*
+ * API's
+ */
+#if (defined (WIN32) || defined( _WIN32 ) ) && !defined( _NO_COM )
+//#if defined( _WIN32 ) && !defined( _NO_ENUM )
+    typedef BOOL (FAR PASCAL * LPDDENUMCALLBACKA)(GUID FAR *, LPSTR, LPSTR, LPVOID);
+    typedef BOOL (FAR PASCAL * LPDDENUMCALLBACKW)(GUID FAR *, LPWSTR, LPWSTR, LPVOID);
+    extern HRESULT WINAPI DirectDrawEnumerateW( LPDDENUMCALLBACKW lpCallback, LPVOID lpContext );
+    extern HRESULT WINAPI DirectDrawEnumerateA( LPDDENUMCALLBACKA lpCallback, LPVOID lpContext );
+    #ifdef UNICODE
+        typedef LPDDENUMCALLBACKW       LPDDENUMCALLBACK;
+        #define DirectDrawEnumerate     DirectDrawEnumerateW
+    #else
+        typedef LPDDENUMCALLBACKA       LPDDENUMCALLBACK;
+        #define DirectDrawEnumerate     DirectDrawEnumerateA
+    #endif
+    extern HRESULT WINAPI DirectDrawCreate( GUID FAR *lpGUID, LPDIRECTDRAW FAR *lplpDD, IUnknown FAR *pUnkOuter );
+    extern HRESULT WINAPI DirectDrawCreateClipper( DWORD dwFlags, LPDIRECTDRAWCLIPPER FAR *lplpDDClipper, IUnknown FAR *pUnkOuter );
+    #ifdef WINNT
+        //This is the user-mode entry stub to the kernel mode procedure.
+        extern HRESULT NtDirectDrawCreate( GUID FAR *lpGUID, HANDLE *lplpDD, IUnknown FAR *pUnkOuter );
+    #endif
+#endif
+
+#define REGSTR_KEY_DDHW_DESCRIPTION     "Description"
+#define REGSTR_KEY_DDHW_DRIVERNAME      "DriverName"
+#define REGSTR_PATH_DDHW                "Hardware\\DirectDrawDrivers"
+
+#define DDCREATE_HARDWAREONLY           0x00000001l
+#define DDCREATE_EMULATIONONLY          0x00000002l
+
+#ifdef WINNT
+typedef long HRESULT;
+#endif
+
+//#ifndef WINNT
+typedef HRESULT (FAR PASCAL * LPDDENUMMODESCALLBACK)(LPDDSURFACEDESC, LPVOID);
+typedef HRESULT (FAR PASCAL * LPDDENUMSURFACESCALLBACK)(LPDIRECTDRAWSURFACE, LPDDSURFACEDESC, LPVOID);
+//#endif
+/*
+ * DDCOLORKEY
+ */
+typedef struct _DDCOLORKEY
+{
+    DWORD       dwColorSpaceLowValue;   // low boundary of color space that is to 
+                                        // be treated as Color Key, inclusive
+    DWORD       dwColorSpaceHighValue;  // high boundary of color space that is 
+                                        // to be treated as Color Key, inclusive
+} DDCOLORKEY;
+
+typedef DDCOLORKEY FAR* LPDDCOLORKEY;
+
+/*
+ * DDBLTFX
+ * Used to pass override information to the DIRECTDRAWSURFACE callback Blt.
+ */
+typedef struct _DDBLTFX
+{
+    DWORD       dwSize;                         // size of structure
+    DWORD       dwDDFX;                         // FX operations
+    DWORD       dwROP;                          // Win32 raster operations
+    DWORD       dwDDROP;                        // Raster operations new for DirectDraw
+    DWORD       dwRotationAngle;                // Rotation angle for blt
+    DWORD       dwZBufferOpCode;                // ZBuffer compares
+    DWORD       dwZBufferLow;                   // Low limit of Z buffer
+    DWORD       dwZBufferHigh;                  // High limit of Z buffer
+    DWORD       dwZBufferBaseDest;              // Destination base value
+    DWORD       dwZDestConstBitDepth;           // Bit depth used to specify Z constant for destination
+    union
+    {
+        DWORD   dwZDestConst;                   // Constant to use as Z buffer for dest
+        LPDIRECTDRAWSURFACE lpDDSZBufferDest;   // Surface to use as Z buffer for dest
+    };
+    DWORD       dwZSrcConstBitDepth;            // Bit depth used to specify Z constant for source
+    union
+    {
+        DWORD   dwZSrcConst;                    // Constant to use as Z buffer for src
+        LPDIRECTDRAWSURFACE lpDDSZBufferSrc;    // Surface to use as Z buffer for src
+    };
+    DWORD       dwAlphaEdgeBlendBitDepth;       // Bit depth used to specify constant for alpha edge blend
+    DWORD       dwAlphaEdgeBlend;               // Alpha for edge blending
+    DWORD       dwReserved;
+    DWORD       dwAlphaDestConstBitDepth;       // Bit depth used to specify alpha constant for destination
+    union
+    {
+        DWORD   dwAlphaDestConst;               // Constant to use as Alpha Channel
+        LPDIRECTDRAWSURFACE lpDDSAlphaDest;     // Surface to use as Alpha Channel
+    };
+    DWORD       dwAlphaSrcConstBitDepth;        // Bit depth used to specify alpha constant for source
+    union
+    {
+        DWORD   dwAlphaSrcConst;                // Constant to use as Alpha Channel
+        LPDIRECTDRAWSURFACE lpDDSAlphaSrc;      // Surface to use as Alpha Channel
+    };
+    union
+    {
+        DWORD   dwFillColor;                    // color in RGB or Palettized
+        DWORD   dwFillDepth;                    // depth value for z-buffer
+        LPDIRECTDRAWSURFACE lpDDSPattern;       // Surface to use as pattern
+    };
+    DDCOLORKEY  ddckDestColorkey;               // DestColorkey override
+    DDCOLORKEY  ddckSrcColorkey;                // SrcColorkey override
+} DDBLTFX;
+
+typedef DDBLTFX FAR* LPDDBLTFX;
+
+
+/*
+ * DDSCAPS
+ */
+typedef struct _DDSCAPS
+{
+    DWORD       dwCaps;         // capabilities of surface wanted
+} DDSCAPS;
+
+typedef DDSCAPS FAR* LPDDSCAPS; 
+
+/*
+ * DDCAPS
+ */
+#define DD_ROP_SPACE            (256/32)        // space required to store ROP array
+
+typedef struct _DDCAPS
+{
+    DWORD       dwSize;                 // size of the DDDRIVERCAPS structure
+    DWORD       dwCaps;                 // driver specific capabilities
+    DWORD       dwCaps2;                // more driver specific capabilites
+    DWORD       dwCKeyCaps;             // color key capabilities of the surface
+    DWORD       dwFXCaps;               // driver specific stretching and effects capabilites
+    DWORD       dwFXAlphaCaps;          // alpha driver specific capabilities
+    DWORD       dwPalCaps;              // palette capabilities
+    DWORD       dwSVCaps;               // stereo vision capabilities
+    DWORD       dwAlphaBltConstBitDepths;       // DDBD_2,4,8
+    DWORD       dwAlphaBltPixelBitDepths;       // DDBD_1,2,4,8
+    DWORD       dwAlphaBltSurfaceBitDepths;     // DDBD_1,2,4,8
+    DWORD       dwAlphaOverlayConstBitDepths;   // DDBD_2,4,8
+    DWORD       dwAlphaOverlayPixelBitDepths;   // DDBD_1,2,4,8
+    DWORD       dwAlphaOverlaySurfaceBitDepths; // DDBD_1,2,4,8
+    DWORD       dwZBufferBitDepths;             // DDBD_8,16,24,32
+    DWORD       dwVidMemTotal;          // total amount of video memory
+    DWORD       dwVidMemFree;           // amount of free video memory
+    DWORD       dwMaxVisibleOverlays;   // maximum number of visible overlays
+    DWORD       dwCurrVisibleOverlays;  // current number of visible overlays
+    DWORD       dwNumFourCCCodes;       // number of four cc codes
+    DWORD       dwAlignBoundarySrc;     // source rectangle alignment
+    DWORD       dwAlignSizeSrc;         // source rectangle byte size
+    DWORD       dwAlignBoundaryDest;    // dest rectangle alignment
+    DWORD       dwAlignSizeDest;        // dest rectangle byte size
+    DWORD       dwAlignStrideAlign;     // stride alignment
+    DWORD       dwRops[DD_ROP_SPACE];   // ROPS supported
+    DDSCAPS     ddsCaps;                // DDSCAPS structure has all the general capabilities
+    DWORD       dwMinOverlayStretch;    // minimum overlay stretch factor multiplied by 1000, eg 1000 == 1.0, 1300 == 1.3
+    DWORD       dwMaxOverlayStretch;    // maximum overlay stretch factor multiplied by 1000, eg 1000 == 1.0, 1300 == 1.3
+    DWORD       dwMinLiveVideoStretch;  // minimum live video stretch factor multiplied by 1000, eg 1000 == 1.0, 1300 == 1.3
+    DWORD       dwMaxLiveVideoStretch;  // maximum live video stretch factor multiplied by 1000, eg 1000 == 1.0, 1300 == 1.3
+    DWORD       dwMinHwCodecStretch;    // minimum hardware codec stretch factor multiplied by 1000, eg 1000 == 1.0, 1300 == 1.3
+    DWORD       dwMaxHwCodecStretch;    // maximum hardware codec stretch factor multiplied by 1000, eg 1000 == 1.0, 1300 == 1.3
+    DWORD       dwReserved1;            // reserved
+    DWORD       dwReserved2;            // reserved
+    DWORD       dwReserved3;            // reserved
+    DWORD       dwSVBCaps;              // driver specific capabilities for System->Vmem blts
+    DWORD       dwSVBCKeyCaps;          // driver color key capabilities for System->Vmem blts
+    DWORD       dwSVBFXCaps;            // driver FX capabilities for System->Vmem blts
+    DWORD       dwSVBRops[DD_ROP_SPACE];// ROPS supported for System->Vmem blts
+    DWORD       dwVSBCaps;              // driver specific capabilities for Vmem->System blts
+    DWORD       dwVSBCKeyCaps;          // driver color key capabilities for Vmem->System blts
+    DWORD       dwVSBFXCaps;            // driver FX capabilities for Vmem->System blts
+    DWORD       dwVSBRops[DD_ROP_SPACE];// ROPS supported for Vmem->System blts
+    DWORD       dwSSBCaps;              // driver specific capabilities for System->System blts
+    DWORD       dwSSBCKeyCaps;          // driver color key capabilities for System->System blts
+    DWORD       dwSSBFXCaps;            // driver FX capabilities for System->System blts
+    DWORD       dwSSBRops[DD_ROP_SPACE];// ROPS supported for System->System blts
+    DWORD       dwReserved4;            // reserved
+    DWORD       dwReserved5;            // reserved
+    DWORD       dwReserved6;            // reserved
+} DDCAPS;
+
+typedef DDCAPS FAR* LPDDCAPS;
+
+
+
+/*
+ * DDPIXELFORMAT
+ */
+typedef struct _DDPIXELFORMAT
+{
+    DWORD       dwSize;                 // size of structure
+    DWORD       dwFlags;                // pixel format flags
+    DWORD       dwFourCC;               // (FOURCC code)
+    union
+    {
+        DWORD   dwRGBBitCount;          // how many bits per pixel (BD_4,8,16,24,32)
+        DWORD   dwYUVBitCount;          // how many bits per pixel (BD_4,8,16,24,32)
+        DWORD   dwZBufferBitDepth;      // how many bits for z buffers (BD_8,16,24,32)
+        DWORD   dwAlphaBitDepth;        // how many bits for alpha channels (BD_1,2,4,8)
+    };
+    union
+    {
+        DWORD   dwRBitMask;             // mask for red bit
+        DWORD   dwYBitMask;             // mask for Y bits
+    };
+    union
+    {
+        DWORD   dwGBitMask;             // mask for green bits
+        DWORD   dwUBitMask;             // mask for U bits
+    };
+    union
+    {
+        DWORD   dwBBitMask;             // mask for blue bits
+        DWORD   dwVBitMask;             // mask for V bits
+    };
+    union
+    {
+        DWORD   dwRGBAlphaBitMask;      // mask for alpha channel
+        DWORD   dwYUVAlphaBitMask;      // mask for alpha channel
+    };
+} DDPIXELFORMAT;
+
+typedef DDPIXELFORMAT FAR* LPDDPIXELFORMAT;
+
+/*
+ * DDOVERLAYFX
+ */
+typedef struct _DDOVERLAYFX
+{
+    DWORD       dwSize;                         // size of structure
+    DWORD       dwAlphaEdgeBlendBitDepth;       // Bit depth used to specify constant for alpha edge blend
+    DWORD       dwAlphaEdgeBlend;               // Constant to use as alpha for edge blend
+    DWORD       dwReserved;
+    DWORD       dwAlphaDestConstBitDepth;       // Bit depth used to specify alpha constant for destination
+    union
+    {
+        DWORD   dwAlphaDestConst;               // Constant to use as alpha channel for dest
+        LPDIRECTDRAWSURFACE lpDDSAlphaDest;     // Surface to use as alpha channel for dest
+    };
+    DWORD       dwAlphaSrcConstBitDepth;        // Bit depth used to specify alpha constant for source
+    union
+    {
+        DWORD   dwAlphaSrcConst;                // Constant to use as alpha channel for src
+        LPDIRECTDRAWSURFACE lpDDSAlphaSrc;      // Surface to use as alpha channel for src
+    };
+    DDCOLORKEY  dckDestColorkey;                // DestColorkey override
+    DDCOLORKEY  dckSrcColorkey;                 // DestColorkey override
+    DWORD       dwDDFX;                         // Overlay FX
+    DWORD       dwFlags;                        // flags
+} DDOVERLAYFX;
+
+typedef DDOVERLAYFX FAR *LPDDOVERLAYFX;
+
+/*
+ * DDBLTBATCH: BltBatch entry structure
+ */
+typedef struct _DDBLTBATCH
+{
+    LPRECT              lprDest;
+    LPDIRECTDRAWSURFACE lpDDSSrc;
+    LPRECT              lprSrc;
+    DWORD               dwFlags;
+    LPDDBLTFX           lpDDBltFx;
+} DDBLTBATCH;
+
+typedef DDBLTBATCH FAR * LPDDBLTBATCH;
+
+/*
+ * callbacks
+ */
+typedef DWORD   (FAR PASCAL *LPCLIPPERCALLBACK)(LPDIRECTDRAWCLIPPER lpDDClipper, HWND hWnd, DWORD code, LPVOID lpContext );
+#ifdef STREAMING
+typedef DWORD   (FAR PASCAL *LPSURFACESTREAMINGCALLBACK)(DWORD);
+#endif
+
+
+/*
+ * INTERACES FOLLOW:
+ *      IDirectDraw
+ *      IDirectDrawClipper
+ *      IDirectDrawPalette
+ *      IDirectDrawSurface
+ */
+
+/*
+ * IDirectDraw 
+ */
+#if defined( _WIN32 ) && !defined( _NO_COM )
+#undef INTERFACE
+#define INTERFACE IDirectDraw
+DECLARE_INTERFACE_( IDirectDraw, IUnknown )
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef) (THIS)  PURE;
+    STDMETHOD_(ULONG,Release) (THIS) PURE;
+    /*** IDirectDraw methods ***/
+    STDMETHOD(Compact)(THIS) PURE;
+    STDMETHOD(CreateClipper)(THIS_ DWORD, LPDIRECTDRAWCLIPPER FAR*, IUnknown FAR * ) PURE;
+    STDMETHOD(CreatePalette)(THIS_ DWORD, LPPALETTEENTRY, LPDIRECTDRAWPALETTE FAR*, IUnknown FAR * ) PURE;
+    STDMETHOD(CreateSurface)(THIS_  LPDDSURFACEDESC, LPDIRECTDRAWSURFACE FAR *, IUnknown FAR *) PURE;
+    STDMETHOD(DuplicateSurface)( THIS_ LPDIRECTDRAWSURFACE, LPDIRECTDRAWSURFACE FAR * ) PURE;
+    STDMETHOD(EnumDisplayModes)( THIS_ DWORD, LPDDSURFACEDESC, LPVOID, LPDDENUMMODESCALLBACK ) PURE;
+    STDMETHOD(EnumSurfaces)(THIS_ DWORD, LPDDSURFACEDESC, LPVOID,LPDDENUMSURFACESCALLBACK ) PURE;
+    STDMETHOD(FlipToGDISurface)(THIS) PURE;
+    STDMETHOD(GetCaps)( THIS_ LPDDCAPS, LPDDCAPS) PURE;
+    STDMETHOD(GetDisplayMode)( THIS_ LPDDSURFACEDESC) PURE;
+    STDMETHOD(GetFourCCCodes)(THIS_  LPDWORD, LPDWORD ) PURE;
+    STDMETHOD(GetGDISurface)(THIS_ LPDIRECTDRAWSURFACE FAR *) PURE;
+    STDMETHOD(GetMonitorFrequency)(THIS_ LPDWORD) PURE;
+    STDMETHOD(GetScanLine)(THIS_ LPDWORD) PURE;
+    STDMETHOD(GetVerticalBlankStatus)(THIS_ LPBOOL ) PURE;
+    STDMETHOD(Initialize)(THIS_ GUID FAR *) PURE;
+    STDMETHOD(RestoreDisplayMode)(THIS) PURE;
+    STDMETHOD(SetCooperativeLevel)(THIS_ HWND, DWORD) PURE;
+    STDMETHOD(SetDisplayMode)(THIS_ DWORD, DWORD,DWORD) PURE;
+    STDMETHOD(WaitForVerticalBlank)(THIS_ DWORD, HANDLE ) PURE;
+};
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirectDraw_QueryInterface(p, a, b)         (p)->lpVtbl->QueryInterface(p, a, b)
+#define IDirectDraw_AddRef(p)                       (p)->lpVtbl->AddRef(p)
+#define IDirectDraw_Release(p)                      (p)->lpVtbl->Release(p)
+#define IDirectDraw_Compact(p)                      (p)->lpVtbl->Compact(p)
+#define IDirectDraw_CreateClipper(p, a, b, c)       (p)->lpVtbl->CreateClipper(p, a, b, c)
+#define IDirectDraw_CreatePalette(p, a, b, c, d)    (p)->lpVtbl->CreatePalette(p, a, b, c, d)
+#define IDirectDraw_CreateSurface(p, a, b, c)       (p)->lpVtbl->CreateSurface(p, a, b, c)
+#define IDirectDraw_DuplicateSurface(p, a, b)       (p)->lpVtbl->DuplicateSurface(p, a, b)
+#define IDirectDraw_EnumDisplayModes(p, a, b, c, d) (p)->lpVtbl->EnumDisplayModes(p, a, b, c, d)
+#define IDirectDraw_EnumSurfaces(p, a, b, c, d)     (p)->lpVtbl->EnumSurfaces(p, a, b, c, d)
+#define IDirectDraw_FlipToGDISurface(p)             (p)->lpVtbl->FlipToGDISurface(p)
+#define IDirectDraw_GetCaps(p, a, b)                (p)->lpVtbl->GetCaps(p, a, b)
+#define IDirectDraw_GetDisplayMode(p, a)            (p)->lpVtbl->GetDisplayMode(p, a)
+#define IDirectDraw_GetFourCCCodes(p, a, b)         (p)->lpVtbl->GetFourCCCodes(p, a, b)
+#define IDirectDraw_GetGDISurface(p, a)             (p)->lpVtbl->GetGDISurface(p, a)
+#define IDirectDraw_GetMonitorFrequency(p, a)       (p)->lpVtbl->GetMonitorFrequency(p, a)
+#define IDirectDraw_GetScanLine(p, a)               (p)->lpVtbl->GetScanLine(p, a)
+#define IDirectDraw_GetVerticalBlankStatus(p, a)    (p)->lpVtbl->GetVerticalBlankStatus(p, a)
+#define IDirectDraw_Initialize(p, a)                (p)->lpVtbl->Initialize(p, a)
+#define IDirectDraw_RestoreDisplayMode(p)           (p)->lpVtbl->RestoreDisplayMode(p)
+#define IDirectDraw_SetCooperativeLevel(p, a, b)    (p)->lpVtbl->SetCooperativeLevel(p, a, b)
+#define IDirectDraw_SetDisplayMode(p, a, b, c)      (p)->lpVtbl->SetDisplayMode(p, a, b, c)
+#define IDirectDraw_WaitForVerticalBlank(p, a, b)   (p)->lpVtbl->WaitForVerticalBlank(p, a, b)
+#endif
+
+#endif
+
+#if defined( _WIN32 ) && !defined( _NO_COM )
+#undef INTERFACE
+#define INTERFACE IDirectDraw2
+DECLARE_INTERFACE_( IDirectDraw2, IUnknown )
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef) (THIS)  PURE;
+    STDMETHOD_(ULONG,Release) (THIS) PURE;
+    /*** IDirectDraw methods ***/
+    STDMETHOD(Compact)(THIS) PURE;
+    STDMETHOD(CreateClipper)(THIS_ DWORD, LPDIRECTDRAWCLIPPER FAR*, IUnknown FAR * ) PURE;
+    STDMETHOD(CreatePalette)(THIS_ DWORD, LPPALETTEENTRY, LPDIRECTDRAWPALETTE FAR*, IUnknown FAR * ) PURE;
+    STDMETHOD(CreateSurface)(THIS_  LPDDSURFACEDESC, LPDIRECTDRAWSURFACE FAR *, IUnknown FAR *) PURE;
+    STDMETHOD(DuplicateSurface)( THIS_ LPDIRECTDRAWSURFACE, LPDIRECTDRAWSURFACE FAR * ) PURE;
+    STDMETHOD(EnumDisplayModes)( THIS_ DWORD, LPDDSURFACEDESC, LPVOID, LPDDENUMMODESCALLBACK ) PURE;
+    STDMETHOD(EnumSurfaces)(THIS_ DWORD, LPDDSURFACEDESC, LPVOID,LPDDENUMSURFACESCALLBACK ) PURE;
+    STDMETHOD(FlipToGDISurface)(THIS) PURE;
+    STDMETHOD(GetCaps)( THIS_ LPDDCAPS, LPDDCAPS) PURE;
+    STDMETHOD(GetDisplayMode)( THIS_ LPDDSURFACEDESC) PURE;
+    STDMETHOD(GetFourCCCodes)(THIS_  LPDWORD, LPDWORD ) PURE;
+    STDMETHOD(GetGDISurface)(THIS_ LPDIRECTDRAWSURFACE FAR *) PURE;
+    STDMETHOD(GetMonitorFrequency)(THIS_ LPDWORD) PURE;
+    STDMETHOD(GetScanLine)(THIS_ LPDWORD) PURE;
+    STDMETHOD(GetVerticalBlankStatus)(THIS_ LPBOOL ) PURE;
+    STDMETHOD(Initialize)(THIS_ GUID FAR *) PURE;
+    STDMETHOD(RestoreDisplayMode)(THIS) PURE;
+    STDMETHOD(SetCooperativeLevel)(THIS_ HWND, DWORD) PURE;
+    STDMETHOD(SetDisplayMode)(THIS_ DWORD, DWORD,DWORD, DWORD, DWORD) PURE;
+    STDMETHOD(WaitForVerticalBlank)(THIS_ DWORD, HANDLE ) PURE;
+    /*** Added in the v2 interface ***/
+    STDMETHOD(GetAvailableVidMem)(THIS_ LPDDSCAPS, LPDWORD, LPDWORD) PURE;
+};
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirectDraw2_QueryInterface(p, a, b)         (p)->lpVtbl->QueryInterface(p, a, b)
+#define IDirectDraw2_AddRef(p)                       (p)->lpVtbl->AddRef(p)
+#define IDirectDraw2_Release(p)                      (p)->lpVtbl->Release(p)
+#define IDirectDraw2_Compact(p)                      (p)->lpVtbl->Compact(p)
+#define IDirectDraw2_CreateClipper(p, a, b, c)       (p)->lpVtbl->CreateClipper(p, a, b, c)
+#define IDirectDraw2_CreatePalette(p, a, b, c, d)    (p)->lpVtbl->CreatePalette(p, a, b, c, d)
+#define IDirectDraw2_CreateSurface(p, a, b, c)       (p)->lpVtbl->CreateSurface(p, a, b, c)
+#define IDirectDraw2_DuplicateSurface(p, a, b)       (p)->lpVtbl->DuplicateSurface(p, a, b)
+#define IDirectDraw2_EnumDisplayModes(p, a, b, c, d) (p)->lpVtbl->EnumDisplayModes(p, a, b, c, d)
+#define IDirectDraw2_EnumSurfaces(p, a, b, c, d)     (p)->lpVtbl->EnumSurfaces(p, a, b, c, d)
+#define IDirectDraw2_FlipToGDISurface(p)             (p)->lpVtbl->FlipToGDISurface(p)
+#define IDirectDraw2_GetCaps(p, a, b)                (p)->lpVtbl->GetCaps(p, a, b)
+#define IDirectDraw2_GetDisplayMode(p, a)            (p)->lpVtbl->GetDisplayMode(p, a)
+#define IDirectDraw2_GetFourCCCodes(p, a, b)         (p)->lpVtbl->GetFourCCCodes(p, a, b)
+#define IDirectDraw2_GetGDISurface(p, a)             (p)->lpVtbl->GetGDISurface(p, a)
+#define IDirectDraw2_GetMonitorFrequency(p, a)       (p)->lpVtbl->GetMonitorFrequency(p, a)
+#define IDirectDraw2_GetScanLine(p, a)               (p)->lpVtbl->GetScanLine(p, a)
+#define IDirectDraw2_GetVerticalBlankStatus(p, a)    (p)->lpVtbl->GetVerticalBlankStatus(p, a)
+#define IDirectDraw2_Initialize(p, a)                (p)->lpVtbl->Initialize(p, a)
+#define IDirectDraw2_RestoreDisplayMode(p)           (p)->lpVtbl->RestoreDisplayMode(p)
+#define IDirectDraw2_SetCooperativeLevel(p, a, b)    (p)->lpVtbl->SetCooperativeLevel(p, a, b)
+#define IDirectDraw2_SetDisplayMode(p, a, b, c, d)   (p)->lpVtbl->SetDisplayMode(p, a, b, c, d)
+#define IDirectDraw2_WaitForVerticalBlank(p, a, b)   (p)->lpVtbl->WaitForVerticalBlank(p, a, b)
+#define IDirectDraw2_GetAvailableVidMem(p, a, b, c)  (p)->lpVtbl->GetAvailableVidMem(p, a, b, c)
+#endif
+
+#endif
+
+/*
+ * IDirectDrawPalette
+ */
+#if defined( _WIN32 ) && !defined( _NO_COM )
+#undef INTERFACE
+#define INTERFACE IDirectDrawPalette
+DECLARE_INTERFACE_( IDirectDrawPalette, IUnknown )
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef) (THIS)  PURE;
+    STDMETHOD_(ULONG,Release) (THIS) PURE;
+    /*** IDirectDrawPalette methods ***/
+    STDMETHOD(GetCaps)(THIS_ LPDWORD) PURE;
+    STDMETHOD(GetEntries)(THIS_ DWORD,DWORD,DWORD,LPPALETTEENTRY) PURE;
+    STDMETHOD(Initialize)(THIS_ LPDIRECTDRAW, DWORD, LPPALETTEENTRY) PURE;
+    STDMETHOD(SetEntries)(THIS_ DWORD,DWORD,DWORD,LPPALETTEENTRY) PURE;
+};
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirectDrawPalette_QueryInterface(p, a, b)      (p)->lpVtbl->QueryInterface(p, a, b)
+#define IDirectDrawPalette_AddRef(p)                    (p)->lpVtbl->AddRef(p)
+#define IDirectDrawPalette_Release(p)                   (p)->lpVtbl->Release(p)
+#define IDirectDrawPalette_GetCaps(p, a)                (p)->lpVtbl->GetCaps(p, a)
+#define IDirectDrawPalette_GetEntries(p, a, b, c, d)    (p)->lpVtbl->GetEntries(p, a, b, c, d)
+#define IDirectDrawPalette_Initialize(p, a, b, c)       (p)->lpVtbl->Initialize(p, a, b, c)
+#define IDirectDrawPalette_SetEntries(p, a, b, c, d)    (p)->lpVtbl->SetEntries(p, a, b, c, d)
+#endif
+
+#endif
+
+/*
+ * IDirectDrawClipper
+ */
+#if defined( _WIN32 ) && !defined( _NO_COM )
+#undef INTERFACE
+#define INTERFACE IDirectDrawClipper
+DECLARE_INTERFACE_( IDirectDrawClipper, IUnknown )
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef) (THIS)  PURE;
+    STDMETHOD_(ULONG,Release) (THIS) PURE;
+    /*** IDirectDrawClipper methods ***/
+    STDMETHOD(GetClipList)(THIS_ LPRECT, LPRGNDATA, LPDWORD) PURE;
+    STDMETHOD(GetHWnd)(THIS_ HWND FAR *) PURE;
+    STDMETHOD(Initialize)(THIS_ LPDIRECTDRAW, DWORD) PURE;
+    STDMETHOD(IsClipListChanged)(THIS_ BOOL FAR *) PURE;
+    STDMETHOD(SetClipList)(THIS_ LPRGNDATA,DWORD) PURE;
+    STDMETHOD(SetHWnd)(THIS_ DWORD, HWND ) PURE;
+};
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirectDrawClipper_QueryInterface(p, a, b)  (p)->lpVtbl->QueryInterface(p, a, b)
+#define IDirectDrawClipper_AddRef(p)                (p)->lpVtbl->AddRef(p)
+#define IDirectDrawClipper_Release(p)               (p)->lpVtbl->Release(p)
+#define IDirectDrawClipper_GetClipList(p, a, b, c)  (p)->lpVtbl->GetClipList(p, a, b, c)
+#define IDirectDrawClipper_GetHWnd(p, a)            (p)->lpVtbl->GetHWnd(p, a)
+#define IDirectDrawClipper_Initialize(p, a, b)      (p)->lpVtbl->Initialize(p, a, b)
+#define IDirectDrawClipper_IsClipListChanged(p, a)  (p)->lpVtbl->IsClipListChanged(p, a)
+#define IDirectDrawClipper_SetClipList(p, a, b)     (p)->lpVtbl->SetClipList(p, a, b)
+#define IDirectDrawClipper_SetHWnd(p, a, b)         (p)->lpVtbl->SetHWnd(p, a, b)
+#endif
+
+#endif
+
+/*
+ * IDirectDrawSurface and related interfaces
+ */
+#if defined( _WIN32 ) && !defined( _NO_COM )
+#undef INTERFACE
+#define INTERFACE IDirectDrawSurface
+DECLARE_INTERFACE_( IDirectDrawSurface, IUnknown )
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef) (THIS)  PURE;
+    STDMETHOD_(ULONG,Release) (THIS) PURE;
+    /*** IDirectDrawSurface methods ***/
+    STDMETHOD(AddAttachedSurface)(THIS_ LPDIRECTDRAWSURFACE) PURE;
+    STDMETHOD(AddOverlayDirtyRect)(THIS_ LPRECT) PURE;
+    STDMETHOD(Blt)(THIS_ LPRECT,LPDIRECTDRAWSURFACE, LPRECT,DWORD, LPDDBLTFX) PURE;
+    STDMETHOD(BltBatch)(THIS_ LPDDBLTBATCH, DWORD, DWORD ) PURE;
+    STDMETHOD(BltFast)(THIS_ DWORD,DWORD,LPDIRECTDRAWSURFACE, LPRECT,DWORD) PURE;
+    STDMETHOD(DeleteAttachedSurface)(THIS_ DWORD,LPDIRECTDRAWSURFACE) PURE;
+    STDMETHOD(EnumAttachedSurfaces)(THIS_ LPVOID,LPDDENUMSURFACESCALLBACK) PURE;
+    STDMETHOD(EnumOverlayZOrders)(THIS_ DWORD,LPVOID,LPDDENUMSURFACESCALLBACK) PURE;
+    STDMETHOD(Flip)(THIS_ LPDIRECTDRAWSURFACE, DWORD) PURE;
+    STDMETHOD(GetAttachedSurface)(THIS_ LPDDSCAPS, LPDIRECTDRAWSURFACE FAR *) PURE;
+    STDMETHOD(GetBltStatus)(THIS_ DWORD) PURE;
+    STDMETHOD(GetCaps)(THIS_ LPDDSCAPS) PURE;
+    STDMETHOD(GetClipper)(THIS_ LPDIRECTDRAWCLIPPER FAR*) PURE;
+    STDMETHOD(GetColorKey)(THIS_ DWORD, LPDDCOLORKEY) PURE;
+    STDMETHOD(GetDC)(THIS_ HDC FAR *) PURE;
+    STDMETHOD(GetFlipStatus)(THIS_ DWORD) PURE;
+    STDMETHOD(GetOverlayPosition)(THIS_ LPLONG, LPLONG ) PURE;
+    STDMETHOD(GetPalette)(THIS_ LPDIRECTDRAWPALETTE FAR*) PURE;
+    STDMETHOD(GetPixelFormat)(THIS_ LPDDPIXELFORMAT) PURE;
+    STDMETHOD(GetSurfaceDesc)(THIS_ LPDDSURFACEDESC) PURE;
+    STDMETHOD(Initialize)(THIS_ LPDIRECTDRAW, LPDDSURFACEDESC) PURE;
+    STDMETHOD(IsLost)(THIS) PURE;
+    STDMETHOD(Lock)(THIS_ LPRECT,LPDDSURFACEDESC,DWORD,HANDLE) PURE;
+    STDMETHOD(ReleaseDC)(THIS_ HDC) PURE;
+    STDMETHOD(Restore)(THIS) PURE;
+    STDMETHOD(SetClipper)(THIS_ LPDIRECTDRAWCLIPPER) PURE;
+    STDMETHOD(SetColorKey)(THIS_ DWORD, LPDDCOLORKEY) PURE;
+    STDMETHOD(SetOverlayPosition)(THIS_ LONG, LONG ) PURE;
+    STDMETHOD(SetPalette)(THIS_ LPDIRECTDRAWPALETTE) PURE;
+    STDMETHOD(Unlock)(THIS_ LPVOID) PURE;
+    STDMETHOD(UpdateOverlay)(THIS_ LPRECT, LPDIRECTDRAWSURFACE,LPRECT,DWORD, LPDDOVERLAYFX) PURE;
+    STDMETHOD(UpdateOverlayDisplay)(THIS_ DWORD) PURE;
+    STDMETHOD(UpdateOverlayZOrder)(THIS_ DWORD, LPDIRECTDRAWSURFACE) PURE;
+};
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirectDrawSurface_QueryInterface(p,a,b)        (p)->lpVtbl->QueryInterface(p,a,b)
+#define IDirectDrawSurface_AddRef(p)                    (p)->lpVtbl->AddRef(p)
+#define IDirectDrawSurface_Release(p)                   (p)->lpVtbl->Release(p)
+#define IDirectDrawSurface_AddAttachedSurface(p,a)      (p)->lpVtbl->AddAttachedSurface(p,a)
+#define IDirectDrawSurface_AddOverlayDirtyRect(p,a)     (p)->lpVtbl->AddOverlayDirtyRect(p,a)
+#define IDirectDrawSurface_Blt(p,a,b,c,d,e)             (p)->lpVtbl->Blt(p,a,b,c,d,e)
+#define IDirectDrawSurface_BltBatch(p,a,b,c)            (p)->lpVtbl->BltBatch(p,a,b,c)
+#define IDirectDrawSurface_BltFast(p,a,b,c,d,e)         (p)->lpVtbl->BltFast(p,a,b,c,d,e)
+#define IDirectDrawSurface_DeleteAttachedSurface(p,a,b) (p)->lpVtbl->DeleteAttachedSurface(p,a,b)
+#define IDirectDrawSurface_EnumAttachedSurfaces(p,a,b)  (p)->lpVtbl->EnumAttachedSurfaces(p,a,b)
+#define IDirectDrawSurface_EnumOverlayZOrders(p,a,b,c)  (p)->lpVtbl->EnumOverlayZOrders(p,a,b,c)
+#define IDirectDrawSurface_Flip(p,a,b)                  (p)->lpVtbl->Flip(p,a,b)
+#define IDirectDrawSurface_GetAttachedSurface(p,a,b)    (p)->lpVtbl->GetAttachedSurface(p,a,b)
+#define IDirectDrawSurface_GetBltStatus(p,a)            (p)->lpVtbl->GetBltStatus(p,a)
+#define IDirectDrawSurface_GetCaps(p,b)                 (p)->lpVtbl->GetCaps(p,b)
+#define IDirectDrawSurface_GetClipper(p,a)              (p)->lpVtbl->GetClipper(p,a)
+#define IDirectDrawSurface_GetColorKey(p,a,b)           (p)->lpVtbl->GetColorKey(p,a,b)
+#define IDirectDrawSurface_GetDC(p,a)                   (p)->lpVtbl->GetDC(p,a)
+#define IDirectDrawSurface_GetFlipStatus(p,a)           (p)->lpVtbl->GetFlipStatus(p,a)
+#define IDirectDrawSurface_GetOverlayPosition(p,a,b)    (p)->lpVtbl->GetOverlayPosition(p,a,b)
+#define IDirectDrawSurface_GetPalette(p,a)              (p)->lpVtbl->GetPalette(p,a)
+#define IDirectDrawSurface_GetPixelFormat(p,a)          (p)->lpVtbl->GetPixelFormat(p,a)
+#define IDirectDrawSurface_GetSurfaceDesc(p,a)          (p)->lpVtbl->GetSurfaceDesc(p,a)
+#define IDirectDrawSurface_Initialize(p,a,b)            (p)->lpVtbl->Initialize(p,a,b)
+#define IDirectDrawSurface_IsLost(p)                    (p)->lpVtbl->IsLost(p)
+#define IDirectDrawSurface_Lock(p,a,b,c,d)              (p)->lpVtbl->Lock(p,a,b,c,d)
+#define IDirectDrawSurface_ReleaseDC(p,a)               (p)->lpVtbl->ReleaseDC(p,a)
+#define IDirectDrawSurface_Restore(p)                   (p)->lpVtbl->Restore(p)
+#define IDirectDrawSurface_SetClipper(p,a)              (p)->lpVtbl->SetClipper(p,a)
+#define IDirectDrawSurface_SetColorKey(p,a,b)           (p)->lpVtbl->SetColorKey(p,a,b)
+#define IDirectDrawSurface_SetOverlayPosition(p,a,b)    (p)->lpVtbl->SetOverlayPosition(p,a,b)
+#define IDirectDrawSurface_SetPalette(p,a)              (p)->lpVtbl->SetPalette(p,a)
+#define IDirectDrawSurface_Unlock(p,b)                  (p)->lpVtbl->Unlock(p,b)
+#define IDirectDrawSurface_UpdateOverlay(p,a,b,c,d,e)   (p)->lpVtbl->UpdateOverlay(p,a,b,c,d,e)
+#define IDirectDrawSurface_UpdateOverlayDisplay(p,a)    (p)->lpVtbl->UpdateOverlayDisplay(p,a)
+#define IDirectDrawSurface_UpdateOverlayZOrder(p,a,b)   (p)->lpVtbl->UpdateOverlayZOrder(p,a,b)
+#endif
+
+/*
+ * IDirectDrawSurface2 and related interfaces
+ */
+#undef INTERFACE
+#define INTERFACE IDirectDrawSurface2
+DECLARE_INTERFACE_( IDirectDrawSurface2, IUnknown )
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef) (THIS)  PURE;
+    STDMETHOD_(ULONG,Release) (THIS) PURE;
+    /*** IDirectDrawSurface methods ***/
+    STDMETHOD(AddAttachedSurface)(THIS_ LPDIRECTDRAWSURFACE2) PURE;
+    STDMETHOD(AddOverlayDirtyRect)(THIS_ LPRECT) PURE;
+    STDMETHOD(Blt)(THIS_ LPRECT,LPDIRECTDRAWSURFACE2, LPRECT,DWORD, LPDDBLTFX) PURE;
+    STDMETHOD(BltBatch)(THIS_ LPDDBLTBATCH, DWORD, DWORD ) PURE;
+    STDMETHOD(BltFast)(THIS_ DWORD,DWORD,LPDIRECTDRAWSURFACE2, LPRECT,DWORD) PURE;
+    STDMETHOD(DeleteAttachedSurface)(THIS_ DWORD,LPDIRECTDRAWSURFACE2) PURE;
+    STDMETHOD(EnumAttachedSurfaces)(THIS_ LPVOID,LPDDENUMSURFACESCALLBACK) PURE;
+    STDMETHOD(EnumOverlayZOrders)(THIS_ DWORD,LPVOID,LPDDENUMSURFACESCALLBACK) PURE;
+    STDMETHOD(Flip)(THIS_ LPDIRECTDRAWSURFACE2, DWORD) PURE;
+    STDMETHOD(GetAttachedSurface)(THIS_ LPDDSCAPS, LPDIRECTDRAWSURFACE2 FAR *) PURE;
+    STDMETHOD(GetBltStatus)(THIS_ DWORD) PURE;
+    STDMETHOD(GetCaps)(THIS_ LPDDSCAPS) PURE;
+    STDMETHOD(GetClipper)(THIS_ LPDIRECTDRAWCLIPPER FAR*) PURE;
+    STDMETHOD(GetColorKey)(THIS_ DWORD, LPDDCOLORKEY) PURE;
+    STDMETHOD(GetDC)(THIS_ HDC FAR *) PURE;
+    STDMETHOD(GetFlipStatus)(THIS_ DWORD) PURE;
+    STDMETHOD(GetOverlayPosition)(THIS_ LPLONG, LPLONG ) PURE;
+    STDMETHOD(GetPalette)(THIS_ LPDIRECTDRAWPALETTE FAR*) PURE;
+    STDMETHOD(GetPixelFormat)(THIS_ LPDDPIXELFORMAT) PURE;
+    STDMETHOD(GetSurfaceDesc)(THIS_ LPDDSURFACEDESC) PURE;
+    STDMETHOD(Initialize)(THIS_ LPDIRECTDRAW, LPDDSURFACEDESC) PURE;
+    STDMETHOD(IsLost)(THIS) PURE;
+    STDMETHOD(Lock)(THIS_ LPRECT,LPDDSURFACEDESC,DWORD,HANDLE) PURE;
+    STDMETHOD(ReleaseDC)(THIS_ HDC) PURE;
+    STDMETHOD(Restore)(THIS) PURE;
+    STDMETHOD(SetClipper)(THIS_ LPDIRECTDRAWCLIPPER) PURE;
+    STDMETHOD(SetColorKey)(THIS_ DWORD, LPDDCOLORKEY) PURE;
+    STDMETHOD(SetOverlayPosition)(THIS_ LONG, LONG ) PURE;
+    STDMETHOD(SetPalette)(THIS_ LPDIRECTDRAWPALETTE) PURE;
+    STDMETHOD(Unlock)(THIS_ LPVOID) PURE;
+    STDMETHOD(UpdateOverlay)(THIS_ LPRECT, LPDIRECTDRAWSURFACE2,LPRECT,DWORD, LPDDOVERLAYFX) PURE;
+    STDMETHOD(UpdateOverlayDisplay)(THIS_ DWORD) PURE;
+    STDMETHOD(UpdateOverlayZOrder)(THIS_ DWORD, LPDIRECTDRAWSURFACE2) PURE;
+    /*** Added in the v2 interface ***/
+    STDMETHOD(GetDDInterface)(THIS_ LPVOID FAR *) PURE;
+    STDMETHOD(PageLock)(THIS_ DWORD) PURE;
+    STDMETHOD(PageUnlock)(THIS_ DWORD) PURE;
+};
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirectDrawSurface2_QueryInterface(p,a,b)        (p)->lpVtbl->QueryInterface(p,a,b)
+#define IDirectDrawSurface2_AddRef(p)                    (p)->lpVtbl->AddRef(p)
+#define IDirectDrawSurface2_Release(p)                   (p)->lpVtbl->Release(p)
+#define IDirectDrawSurface2_AddAttachedSurface(p,a)      (p)->lpVtbl->AddAttachedSurface(p,a)
+#define IDirectDrawSurface2_AddOverlayDirtyRect(p,a)     (p)->lpVtbl->AddOverlayDirtyRect(p,a)
+#define IDirectDrawSurface2_Blt(p,a,b,c,d,e)             (p)->lpVtbl->Blt(p,a,b,c,d,e)
+#define IDirectDrawSurface2_BltBatch(p,a,b,c)            (p)->lpVtbl->BltBatch(p,a,b,c)
+#define IDirectDrawSurface2_BltFast(p,a,b,c,d,e)         (p)->lpVtbl->BltFast(p,a,b,c,d,e)
+#define IDirectDrawSurface2_DeleteAttachedSurface(p,a,b) (p)->lpVtbl->DeleteAttachedSurface(p,a,b)
+#define IDirectDrawSurface2_EnumAttachedSurfaces(p,a,b)  (p)->lpVtbl->EnumAttachedSurfaces(p,a,b)
+#define IDirectDrawSurface2_EnumOverlayZOrders(p,a,b,c)  (p)->lpVtbl->EnumOverlayZOrders(p,a,b,c)
+#define IDirectDrawSurface2_Flip(p,a,b)                  (p)->lpVtbl->Flip(p,a,b)
+#define IDirectDrawSurface2_GetAttachedSurface(p,a,b)    (p)->lpVtbl->GetAttachedSurface(p,a,b)
+#define IDirectDrawSurface2_GetBltStatus(p,a)            (p)->lpVtbl->GetBltStatus(p,a)
+#define IDirectDrawSurface2_GetCaps(p,b)                 (p)->lpVtbl->GetCaps(p,b)
+#define IDirectDrawSurface2_GetClipper(p,a)              (p)->lpVtbl->GetClipper(p,a)
+#define IDirectDrawSurface2_GetColorKey(p,a,b)           (p)->lpVtbl->GetColorKey(p,a,b)
+#define IDirectDrawSurface2_GetDC(p,a)                   (p)->lpVtbl->GetDC(p,a)
+#define IDirectDrawSurface2_GetFlipStatus(p,a)           (p)->lpVtbl->GetFlipStatus(p,a)
+#define IDirectDrawSurface2_GetOverlayPosition(p,a,b)    (p)->lpVtbl->GetOverlayPosition(p,a,b)
+#define IDirectDrawSurface2_GetPalette(p,a)              (p)->lpVtbl->GetPalette(p,a)
+#define IDirectDrawSurface2_GetPixelFormat(p,a)          (p)->lpVtbl->GetPixelFormat(p,a)
+#define IDirectDrawSurface2_GetSurfaceDesc(p,a)          (p)->lpVtbl->GetSurfaceDesc(p,a)
+#define IDirectDrawSurface2_Initialize(p,a,b)            (p)->lpVtbl->Initialize(p,a,b)
+#define IDirectDrawSurface2_IsLost(p)                    (p)->lpVtbl->IsLost(p)
+#define IDirectDrawSurface2_Lock(p,a,b,c,d)              (p)->lpVtbl->Lock(p,a,b,c,d)
+#define IDirectDrawSurface2_ReleaseDC(p,a)               (p)->lpVtbl->ReleaseDC(p,a)
+#define IDirectDrawSurface2_Restore(p)                   (p)->lpVtbl->Restore(p)
+#define IDirectDrawSurface2_SetClipper(p,a)              (p)->lpVtbl->SetClipper(p,a)
+#define IDirectDrawSurface2_SetColorKey(p,a,b)           (p)->lpVtbl->SetColorKey(p,a,b)
+#define IDirectDrawSurface2_SetOverlayPosition(p,a,b)    (p)->lpVtbl->SetOverlayPosition(p,a,b)
+#define IDirectDrawSurface2_SetPalette(p,a)              (p)->lpVtbl->SetPalette(p,a)
+#define IDirectDrawSurface2_Unlock(p,b)                  (p)->lpVtbl->Unlock(p,b)
+#define IDirectDrawSurface2_UpdateOverlay(p,a,b,c,d,e)   (p)->lpVtbl->UpdateOverlay(p,a,b,c,d,e)
+#define IDirectDrawSurface2_UpdateOverlayDisplay(p,a)    (p)->lpVtbl->UpdateOverlayDisplay(p,a)
+#define IDirectDrawSurface2_UpdateOverlayZOrder(p,a,b)   (p)->lpVtbl->UpdateOverlayZOrder(p,a,b)
+#define IDirectDrawSurface2_GetDDInterface(p,a)          (p)->lpVtbl->GetDDInterface(p,a)
+#define IDirectDrawSurface2_PageLock(p,a)                (p)->lpVtbl->PageLock(p,a)
+#define IDirectDrawSurface2_PageUnlock(p,a)              (p)->lpVtbl->PageUnlock(p,a)
+#endif
+
+
+#endif
+
+
+/*
+ * DDSURFACEDESC
+ */
+typedef struct _DDSURFACEDESC
+{
+    DWORD               dwSize;                 // size of the DDSURFACEDESC structure
+    DWORD               dwFlags;                // determines what fields are valid
+    DWORD               dwHeight;               // height of surface to be created
+    DWORD               dwWidth;                // width of input surface
+    LONG                lPitch;                 // distance to start of next line (return value only)
+    DWORD               dwBackBufferCount;      // number of back buffers requested
+    union
+    {
+        DWORD           dwMipMapCount;          // number of mip-map levels requested
+        DWORD           dwZBufferBitDepth;      // depth of Z buffer requested
+        DWORD           dwRefreshRate;          // refresh rate (used when display mode is described)
+    };
+    DWORD               dwAlphaBitDepth;        // depth of alpha buffer requested
+    DWORD               dwReserved;             // reserved
+    LPVOID              lpSurface;              // pointer to the associated surface memory
+    DDCOLORKEY          ddckCKDestOverlay;      // color key for destination overlay use
+    DDCOLORKEY          ddckCKDestBlt;          // color key for destination blt use
+    DDCOLORKEY          ddckCKSrcOverlay;       // color key for source overlay use
+    DDCOLORKEY          ddckCKSrcBlt;           // color key for source blt use
+    DDPIXELFORMAT       ddpfPixelFormat;        // pixel format description of the surface
+    DDSCAPS             ddsCaps;                // direct draw surface capabilities
+} DDSURFACEDESC;
+
+/*
+ * ddsCaps field is valid.
+ */
+#define DDSD_CAPS               0x00000001l     // default
+
+/*
+ * dwHeight field is valid.
+ */
+#define DDSD_HEIGHT             0x00000002l
+
+/*
+ * dwWidth field is valid.
+ */
+#define DDSD_WIDTH              0x00000004l
+
+/*
+ * lPitch is valid.
+ */
+#define DDSD_PITCH              0x00000008l
+
+/*
+ * dwBackBufferCount is valid.
+ */
+#define DDSD_BACKBUFFERCOUNT    0x00000020l
+
+/*
+ * dwZBufferBitDepth is valid.
+ */
+#define DDSD_ZBUFFERBITDEPTH    0x00000040l
+
+/*
+ * dwAlphaBitDepth is valid.
+ */
+#define DDSD_ALPHABITDEPTH      0x00000080l
+
+
+
+/*
+ * ddpfPixelFormat is valid.
+ */
+#define DDSD_PIXELFORMAT        0x00001000l
+
+/*
+ * ddckCKDestOverlay is valid.
+ */
+#define DDSD_CKDESTOVERLAY      0x00002000l
+
+/*
+ * ddckCKDestBlt is valid.
+ */
+#define DDSD_CKDESTBLT          0x00004000l
+
+/*
+ * ddckCKSrcOverlay is valid.
+ */
+#define DDSD_CKSRCOVERLAY       0x00008000l
+
+/*
+ * ddckCKSrcBlt is valid.
+ */
+#define DDSD_CKSRCBLT           0x00010000l
+
+/*
+ * dwMipMapCount is valid.
+ */
+#define DDSD_MIPMAPCOUNT        0x00020000l
+
+ /*
+  * dwRefreshRate is valid
+  */
+#define DDSD_REFRESHRATE        0x00040000l
+
+
+/*
+ * All input fields are valid. 
+ */
+#define DDSD_ALL                0x0007f9eel
+
+
+/*============================================================================
+ *
+ * Direct Draw Capability Flags
+ *
+ * These flags are used to describe the capabilities of a given Surface.
+ * All flags are bit flags. 
+ *
+ *==========================================================================*/
+
+/****************************************************************************
+ *
+ * DIRECTDRAWSURFACE CAPABILITY FLAGS
+ *
+ ****************************************************************************/
+/*
+ * This bit currently has no meaning.
+ */
+#define DDSCAPS_3D                              0x00000001l
+
+/*
+ * Indicates that this surface contains alpha information.  The pixel
+ * format must be interrogated to determine whether this surface
+ * contains only alpha information or alpha information interlaced
+ * with pixel color data (e.g. RGBA or YUVA).
+ */
+#define DDSCAPS_ALPHA                           0x00000002l
+
+/*
+ * Indicates that this surface is a backbuffer.  It is generally
+ * set by CreateSurface when the DDSCAPS_FLIP capability bit is set.
+ * It indicates that this surface is THE back buffer of a surface
+ * flipping structure.  DirectDraw supports N surfaces in a
+ * surface flipping structure.  Only the surface that immediately
+ * precedeces the DDSCAPS_FRONTBUFFER has this capability bit set.
+ * The other surfaces are identified as back buffers by the presence
+ * of the DDSCAPS_FLIP capability, their attachment order, and the
+ * absence of the DDSCAPS_FRONTBUFFER and DDSCAPS_BACKBUFFER
+ * capabilities.  The bit is sent to CreateSurface when a standalone
+ * back buffer is being created.  This surface could be attached to
+ * a front buffer and/or back buffers to form a flipping surface
+ * structure after the CreateSurface call.  See AddAttachments for
+ * a detailed description of the behaviors in this case.
+ */
+#define DDSCAPS_BACKBUFFER                      0x00000004l
+
+/*
+ * Indicates a complex surface structure is being described.  A
+ * complex surface structure results in the creation of more than
+ * one surface.  The additional surfaces are attached to the root
+ * surface.  The complex structure can only be destroyed by
+ * destroying the root.
+ */
+#define DDSCAPS_COMPLEX                         0x00000008l
+
+/*
+ * Indicates that this surface is a part of a surface flipping structure.
+ * When it is passed to CreateSurface the DDSCAPS_FRONTBUFFER and
+ * DDSCAP_BACKBUFFER bits are not set.  They are set by CreateSurface
+ * on the resulting creations.  The dwBackBufferCount field in the
+ * DDSURFACEDESC structure must be set to at least 1 in order for
+ * the CreateSurface call to succeed.  The DDSCAPS_COMPLEX capability
+ * must always be set with creating multiple surfaces through CreateSurface.
+ */
+#define DDSCAPS_FLIP                            0x00000010l
+
+/*
+ * Indicates that this surface is THE front buffer of a surface flipping
+ * structure.  It is generally set by CreateSurface when the DDSCAPS_FLIP
+ * capability bit is set.
+ * If this capability is sent to CreateSurface then a standalonw front buffer
+ * is created.  This surface will not have the DDSCAPS_FLIP capability.
+ * It can be attached to other back buffers to form a flipping structure.
+ * See AddAttachments for a detailed description of the behaviors in this
+ * case.
+ */
+#define DDSCAPS_FRONTBUFFER                     0x00000020l
+
+/*
+ * Indicates that this surface is any offscreen surface that is not an overlay,
+ * texture, zbuffer, front buffer, back buffer, or alpha surface.  It is used
+ * to identify plain vanilla surfaces.
+ */
+#define DDSCAPS_OFFSCREENPLAIN                  0x00000040l
+
+/*
+ * Indicates that this surface is an overlay.  It may or may not be directly visible
+ * depending on whether or not it is currently being overlayed onto the primary 
+ * surface.  DDSCAPS_VISIBLE can be used to determine whether or not it is being 
+ * overlayed at the moment. 
+ */
+#define DDSCAPS_OVERLAY                         0x00000080l
+
+/*
+ * Indicates that unique DirectDrawPalette objects can be created and
+ * attached to this surface.
+ */
+#define DDSCAPS_PALETTE                         0x00000100l
+
+/*
+ * Indicates that this surface is the primary surface.  The primary
+ * surface represents what the user is seeing at the moment.
+ */
+#define DDSCAPS_PRIMARYSURFACE                  0x00000200l
+
+/*
+ * Indicates that this surface is the primary surface for the left eye.
+ * The primary surface for the left eye represents what the user is seeing
+ * at the moment with the users left eye.  When this surface is created the
+ * DDSCAPS_PRIMARYSURFACE represents what the user is seeing with the users
+ * right eye.
+ */
+#define DDSCAPS_PRIMARYSURFACELEFT              0x00000400l
+
+/*
+ * Indicates that this surface memory was allocated in system memory
+ */
+#define DDSCAPS_SYSTEMMEMORY                    0x00000800l
+
+/*
+ * Indicates that this surface can be used as a 3D texture.  It does not
+ * indicate whether or not the surface is being used for that purpose.
+ */
+#define DDSCAPS_TEXTURE                         0x00001000l
+
+/*
+ * Indicates that a surface may be a destination for 3D rendering.  This
+ * bit must be set in order to query for a Direct3D Device Interface 
+ * from this surface.
+ */
+#define DDSCAPS_3DDEVICE                        0x00002000l
+
+/*
+ * Indicates that this surface exists in video memory.
+ */
+#define DDSCAPS_VIDEOMEMORY                     0x00004000l
+
+/*
+ * Indicates that changes made to this surface are immediately visible.  
+ * It is always set for the primary surface and is set for overlays while
+ * they are being overlayed and texture maps while they are being textured.
+ */
+#define DDSCAPS_VISIBLE                         0x00008000l
+
+/*
+ * Indicates that only writes are permitted to the surface.  Read accesses 
+ * from the surface may or may not generate a protection fault, but the 
+ * results of a read from this surface will not be meaningful.  READ ONLY.
+ */
+#define DDSCAPS_WRITEONLY                       0x00010000l
+
+/*
+ * Indicates that this surface is a z buffer. A z buffer does not contain
+ * displayable information.  Instead it contains bit depth information that is
+ * used to determine which pixels are visible and which are obscured. 
+ */
+#define DDSCAPS_ZBUFFER                         0x00020000l
+
+/*
+ * Indicates surface will have a DC associated long term
+ */
+#define DDSCAPS_OWNDC                           0x00040000l
+
+/*
+ * Indicates surface should be able to receive live video
+ */
+#define DDSCAPS_LIVEVIDEO                       0x00080000l
+
+/*
+ * Indicates surface should be able to have a stream decompressed
+ * to it by the hardware.
+ */
+#define DDSCAPS_HWCODEC                         0x00100000l
+
+/*
+ * Surface is a 320x200 or 320x240 ModeX surface
+ */
+#define DDSCAPS_MODEX                           0x00200000l
+
+/*
+ * Indicates surface is one level of a mip-map. This surface will
+ * be attached to other DDSCAPS_MIPMAP surfaces to form the mip-map.
+ * This can be done explicitly, by creating a number of surfaces and
+ * attaching them with AddAttachedSurface or by implicitly by CreateSurface.
+ * If this bit is set then DDSCAPS_TEXTURE must also be set.
+ */
+#define DDSCAPS_MIPMAP                          0x00400000l
+
+
+
+/*
+ * Indicates that memory for the surface is not allocated until the surface
+ * is loaded (via the Direct3D texture Load() function).
+ */
+#define DDSCAPS_ALLOCONLOAD                     0x04000000l
+
+
+
+ /****************************************************************************
+ *
+ * DIRECTDRAW DRIVER CAPABILITY FLAGS
+ *
+ ****************************************************************************/
+
+/*
+ * Display hardware has 3D acceleration.
+ */
+#define DDCAPS_3D                       0x00000001l
+
+/*
+ * Indicates that DirectDraw will support only dest rectangles that are aligned
+ * on DIRECTDRAWCAPS.dwAlignBoundaryDest boundaries of the surface, respectively.
+ * READ ONLY.
+ */
+#define DDCAPS_ALIGNBOUNDARYDEST        0x00000002l
+
+/*
+ * Indicates that DirectDraw will support only source rectangles  whose sizes in 
+ * BYTEs are DIRECTDRAWCAPS.dwAlignSizeDest multiples, respectively.  READ ONLY.
+ */
+#define DDCAPS_ALIGNSIZEDEST            0x00000004l
+/*
+ * Indicates that DirectDraw will support only source rectangles that are aligned
+ * on DIRECTDRAWCAPS.dwAlignBoundarySrc boundaries of the surface, respectively.
+ * READ ONLY.
+ */
+#define DDCAPS_ALIGNBOUNDARYSRC         0x00000008l
+
+/*
+ * Indicates that DirectDraw will support only source rectangles  whose sizes in 
+ * BYTEs are DIRECTDRAWCAPS.dwAlignSizeSrc multiples, respectively.  READ ONLY.
+ */
+#define DDCAPS_ALIGNSIZESRC             0x00000010l
+
+/*
+ * Indicates that DirectDraw will create video memory surfaces that have a stride 
+ * alignment equal to DIRECTDRAWCAPS.dwAlignStride.  READ ONLY.
+ */
+#define DDCAPS_ALIGNSTRIDE              0x00000020l
+
+/*
+ * Display hardware is capable of blt operations.
+ */
+#define DDCAPS_BLT                      0x00000040l
+
+/*
+ * Display hardware is capable of asynchronous blt operations.
+ */
+#define DDCAPS_BLTQUEUE                 0x00000080l
+
+/*
+ * Display hardware is capable of color space conversions during the blt operation.
+ */
+#define DDCAPS_BLTFOURCC                0x00000100l
+
+/*
+ * Display hardware is capable of stretching during blt operations.
+ */
+#define DDCAPS_BLTSTRETCH               0x00000200l
+
+/*
+ * Display hardware is shared with GDI.
+ */
+#define DDCAPS_GDI                      0x00000400l
+
+/*
+ * Display hardware can overlay.
+ */
+#define DDCAPS_OVERLAY                  0x00000800l
+
+/*
+ * Set if display hardware supports overlays but can not clip them.
+ */
+#define DDCAPS_OVERLAYCANTCLIP          0x00001000l
+
+/*
+ * Indicates that overlay hardware is capable of color space conversions during
+ * the overlay operation.
+ */
+#define DDCAPS_OVERLAYFOURCC            0x00002000l
+
+/*
+ * Indicates that stretching can be done by the overlay hardware.
+ */
+#define DDCAPS_OVERLAYSTRETCH           0x00004000l
+
+/*
+ * Indicates that unique DirectDrawPalettes can be created for DirectDrawSurfaces
+ * other than the primary surface.
+ */
+#define DDCAPS_PALETTE                  0x00008000l
+
+/*
+ * Indicates that palette changes can be syncd with the veritcal refresh.
+ */
+#define DDCAPS_PALETTEVSYNC             0x00010000l
+
+/*
+ * Display hardware can return the current scan line.
+ */
+#define DDCAPS_READSCANLINE             0x00020000l
+
+/*
+ * Display hardware has stereo vision capabilities.  DDSCAPS_PRIMARYSURFACELEFT 
+ * can be created.
+ */
+#define DDCAPS_STEREOVIEW               0x00040000l
+
+/*
+ * Display hardware is capable of generating a vertical blank interrupt.
+ */
+#define DDCAPS_VBI                      0x00080000l
+
+/*
+ * Supports the use of z buffers with blt operations.
+ */
+#define DDCAPS_ZBLTS                    0x00100000l
+
+/*
+ * Supports Z Ordering of overlays.
+ */
+#define DDCAPS_ZOVERLAYS                0x00200000l
+
+/*
+ * Supports color key
+ */
+#define DDCAPS_COLORKEY                 0x00400000l
+
+/*
+ * Supports alpha surfaces
+ */
+#define DDCAPS_ALPHA                    0x00800000l
+
+/*
+ * colorkey is hardware assisted(DDCAPS_COLORKEY will also be set)
+ */
+#define DDCAPS_COLORKEYHWASSIST         0x01000000l
+
+/*
+ * no hardware support at all
+ */
+#define DDCAPS_NOHARDWARE               0x02000000l
+
+/*
+ * Display hardware is capable of color fill with bltter
+ */
+#define DDCAPS_BLTCOLORFILL             0x04000000l
+
+/*
+ * Display hardware is bank switched, and potentially very slow at
+ * random access to VRAM.
+ */
+#define DDCAPS_BANKSWITCHED             0x08000000l
+
+/*
+ * Display hardware is capable of depth filling Z-buffers with bltter
+ */
+#define DDCAPS_BLTDEPTHFILL             0x10000000l
+
+/*
+ * Display hardware is capable of clipping while bltting.
+ */
+#define DDCAPS_CANCLIP                  0x20000000l
+
+/*
+ * Display hardware is capable of clipping while stretch bltting.
+ */
+#define DDCAPS_CANCLIPSTRETCHED         0x40000000l
+
+/*
+ * Display hardware is capable of bltting to or from system memory
+ */
+#define DDCAPS_CANBLTSYSMEM             0x80000000l
+
+
+ /****************************************************************************
+ *
+ * MORE DIRECTDRAW DRIVER CAPABILITY FLAGS (dwCaps2)
+ *
+ ****************************************************************************/
+
+/*
+ * Display hardware is certified
+ */
+#define DDCAPS2_CERTIFIED               0x00000001l
+
+/*
+ * Driver cannot interleave 2D operations (lock and blt) to surfaces with
+ * Direct3D rendering operations between calls to BeginScene() and EndScene()
+ */
+#define DDCAPS2_NO2DDURING3DSCENE       0x00000002l
+
+/****************************************************************************
+ *
+ * DIRECTDRAW FX ALPHA CAPABILITY FLAGS
+ *
+ ****************************************************************************/
+
+/*
+ * Supports alpha blending around the edge of a source color keyed surface.
+ * For Blt.
+ */
+#define DDFXALPHACAPS_BLTALPHAEDGEBLEND         0x00000001l
+
+/*
+ * Supports alpha information in the pixel format.  The bit depth of alpha 
+ * information in the pixel format can be 1,2,4, or 8.  The alpha value becomes
+ * more opaque as the alpha value increases.  (0 is transparent.)
+ * For Blt.
+ */
+#define DDFXALPHACAPS_BLTALPHAPIXELS            0x00000002l
+
+/*
+ * Supports alpha information in the pixel format.  The bit depth of alpha 
+ * information in the pixel format can be 1,2,4, or 8.  The alpha value 
+ * becomes more transparent as the alpha value increases.  (0 is opaque.) 
+ * This flag can only be set if DDCAPS_ALPHA is set.
+ * For Blt.
+ */
+#define DDFXALPHACAPS_BLTALPHAPIXELSNEG         0x00000004l
+
+/*
+ * Supports alpha only surfaces.  The bit depth of an alpha only surface can be
+ * 1,2,4, or 8.  The alpha value becomes more opaque as the alpha value increases.
+ * (0 is transparent.)
+ * For Blt.
+ */
+#define DDFXALPHACAPS_BLTALPHASURFACES          0x00000008l
+
+/*
+ * The depth of the alpha channel data can range can be 1,2,4, or 8.  
+ * The NEG suffix indicates that this alpha channel becomes more transparent
+ * as the alpha value increases. (0 is opaque.)  This flag can only be set if
+ * DDCAPS_ALPHA is set.
+ * For Blt.
+ */
+#define DDFXALPHACAPS_BLTALPHASURFACESNEG       0x00000010l
+
+/*
+ * Supports alpha blending around the edge of a source color keyed surface.
+ * For Overlays.
+ */
+#define DDFXALPHACAPS_OVERLAYALPHAEDGEBLEND     0x00000020l
+
+/*
+ * Supports alpha information in the pixel format.  The bit depth of alpha 
+ * information in the pixel format can be 1,2,4, or 8.  The alpha value becomes
+ * more opaque as the alpha value increases.  (0 is transparent.)
+ * For Overlays.
+ */
+#define DDFXALPHACAPS_OVERLAYALPHAPIXELS        0x00000040l
+
+/*
+ * Supports alpha information in the pixel format.  The bit depth of alpha 
+ * information in the pixel format can be 1,2,4, or 8.  The alpha value 
+ * becomes more transparent as the alpha value increases.  (0 is opaque.) 
+ * This flag can only be set if DDCAPS_ALPHA is set.
+ * For Overlays.
+ */
+#define DDFXALPHACAPS_OVERLAYALPHAPIXELSNEG     0x00000080l
+
+/*
+ * Supports alpha only surfaces.  The bit depth of an alpha only surface can be
+ * 1,2,4, or 8.  The alpha value becomes more opaque as the alpha value increases.
+ * (0 is transparent.)
+ * For Overlays.
+ */
+#define DDFXALPHACAPS_OVERLAYALPHASURFACES      0x00000100l
+
+/*
+ * The depth of the alpha channel data can range can be 1,2,4, or 8.  
+ * The NEG suffix indicates that this alpha channel becomes more transparent
+ * as the alpha value increases. (0 is opaque.)  This flag can only be set if
+ * DDCAPS_ALPHA is set.
+ * For Overlays.
+ */
+#define DDFXALPHACAPS_OVERLAYALPHASURFACESNEG   0x00000200l
+
+/****************************************************************************
+ *
+ * DIRECTDRAW FX CAPABILITY FLAGS
+ *
+ ****************************************************************************/
+
+/*
+ * Uses arithmetic operations to stretch and shrink surfaces during blt
+ * rather than pixel doubling techniques.  Along the Y axis.
+ */
+#define DDFXCAPS_BLTARITHSTRETCHY       0x00000020l
+
+/*
+ * Uses arithmetic operations to stretch during blt
+ * rather than pixel doubling techniques.  Along the Y axis. Only
+ * works for x1, x2, etc.
+ */
+#define DDFXCAPS_BLTARITHSTRETCHYN      0x00000010l
+
+/*
+ * Supports mirroring left to right in blt.
+ */
+#define DDFXCAPS_BLTMIRRORLEFTRIGHT     0x00000040l
+
+/*
+ * Supports mirroring top to bottom in blt.
+ */
+#define DDFXCAPS_BLTMIRRORUPDOWN        0x00000080l
+
+/*
+ * Supports arbitrary rotation for blts.
+ */
+#define DDFXCAPS_BLTROTATION            0x00000100l
+
+/*
+ * Supports 90 degree rotations for blts.
+ */
+#define DDFXCAPS_BLTROTATION90          0x00000200l
+
+/*
+ * DirectDraw supports arbitrary shrinking of a surface along the
+ * x axis (horizontal direction) for blts.
+ */
+#define DDFXCAPS_BLTSHRINKX             0x00000400l
+
+/*
+ * DirectDraw supports integer shrinking (1x,2x,) of a surface
+ * along the x axis (horizontal direction) for blts.
+ */
+#define DDFXCAPS_BLTSHRINKXN            0x00000800l
+
+/*
+ * DirectDraw supports arbitrary shrinking of a surface along the
+ * y axis (horizontal direction) for blts.  
+ */
+#define DDFXCAPS_BLTSHRINKY             0x00001000l
+
+/*
+ * DirectDraw supports integer shrinking (1x,2x,) of a surface
+ * along the y axis (vertical direction) for blts.  
+ */
+#define DDFXCAPS_BLTSHRINKYN            0x00002000l
+
+/*
+ * DirectDraw supports arbitrary stretching of a surface along the
+ * x axis (horizontal direction) for blts.
+ */
+#define DDFXCAPS_BLTSTRETCHX            0x00004000l
+
+/*
+ * DirectDraw supports integer stretching (1x,2x,) of a surface
+ * along the x axis (horizontal direction) for blts.
+ */
+#define DDFXCAPS_BLTSTRETCHXN           0x00008000l
+
+/*
+ * DirectDraw supports arbitrary stretching of a surface along the
+ * y axis (horizontal direction) for blts.  
+ */
+#define DDFXCAPS_BLTSTRETCHY            0x00010000l
+
+/*
+ * DirectDraw supports integer stretching (1x,2x,) of a surface
+ * along the y axis (vertical direction) for blts.  
+ */
+#define DDFXCAPS_BLTSTRETCHYN           0x00020000l
+
+/*
+ * Uses arithmetic operations to stretch and shrink surfaces during 
+ * overlay rather than pixel doubling techniques.  Along the Y axis 
+ * for overlays.
+ */
+#define DDFXCAPS_OVERLAYARITHSTRETCHY   0x00040000l
+
+/*
+ * Uses arithmetic operations to stretch surfaces during 
+ * overlay rather than pixel doubling techniques.  Along the Y axis 
+ * for overlays. Only works for x1, x2, etc.
+ */
+#define DDFXCAPS_OVERLAYARITHSTRETCHYN  0x00000008l
+
+/*
+ * DirectDraw supports arbitrary shrinking of a surface along the
+ * x axis (horizontal direction) for overlays.
+ */
+#define DDFXCAPS_OVERLAYSHRINKX         0x00080000l
+
+/*
+ * DirectDraw supports integer shrinking (1x,2x,) of a surface
+ * along the x axis (horizontal direction) for overlays.
+ */
+#define DDFXCAPS_OVERLAYSHRINKXN        0x00100000l
+
+/*
+ * DirectDraw supports arbitrary shrinking of a surface along the
+ * y axis (horizontal direction) for overlays.  
+ */
+#define DDFXCAPS_OVERLAYSHRINKY         0x00200000l
+
+/*
+ * DirectDraw supports integer shrinking (1x,2x,) of a surface
+ * along the y axis (vertical direction) for overlays.  
+ */
+#define DDFXCAPS_OVERLAYSHRINKYN        0x00400000l
+
+/*
+ * DirectDraw supports arbitrary stretching of a surface along the
+ * x axis (horizontal direction) for overlays.
+ */
+#define DDFXCAPS_OVERLAYSTRETCHX        0x00800000l
+
+/*
+ * DirectDraw supports integer stretching (1x,2x,) of a surface
+ * along the x axis (horizontal direction) for overlays.
+ */
+#define DDFXCAPS_OVERLAYSTRETCHXN       0x01000000l
+
+/*
+ * DirectDraw supports arbitrary stretching of a surface along the
+ * y axis (horizontal direction) for overlays.  
+ */
+#define DDFXCAPS_OVERLAYSTRETCHY        0x02000000l
+
+/*
+ * DirectDraw supports integer stretching (1x,2x,) of a surface
+ * along the y axis (vertical direction) for overlays.  
+ */
+#define DDFXCAPS_OVERLAYSTRETCHYN       0x04000000l
+
+/*
+ * DirectDraw supports mirroring of overlays across the vertical axis
+ */
+#define DDFXCAPS_OVERLAYMIRRORLEFTRIGHT 0x08000000l
+
+/*
+ * DirectDraw supports mirroring of overlays across the horizontal axis
+ */
+#define DDFXCAPS_OVERLAYMIRRORUPDOWN    0x10000000l
+
+/****************************************************************************
+ *
+ * DIRECTDRAW STEREO VIEW CAPABILITIES
+ *
+ ****************************************************************************/
+
+/*
+ * The stereo view is accomplished via enigma encoding.
+ */
+#define DDSVCAPS_ENIGMA                 0x00000001l
+
+/*
+ * The stereo view is accomplished via high frequency flickering.
+ */
+#define DDSVCAPS_FLICKER                0x00000002l
+
+/*
+ * The stereo view is accomplished via red and blue filters applied
+ * to the left and right eyes.  All images must adapt their colorspaces
+ * for this process.
+ */
+#define DDSVCAPS_REDBLUE                0x00000004l
+
+/*
+ * The stereo view is accomplished with split screen technology.
+ */
+#define DDSVCAPS_SPLIT                  0x00000008l
+
+/****************************************************************************
+ *
+ * DIRECTDRAWPALETTE CAPABILITIES
+ *
+ ****************************************************************************/
+
+/*
+ * Index is 4 bits.  There are sixteen color entries in the palette table.
+ */
+#define DDPCAPS_4BIT                    0x00000001l
+
+/*
+ * Index is onto a 8 bit color index.  This field is only valid with the
+ * DDPCAPS_1BIT, DDPCAPS_2BIT or DDPCAPS_4BIT capability and the target
+ * surface is in 8bpp. Each color entry is one byte long and is an index
+ * into destination surface's 8bpp palette.
+ */
+#define DDPCAPS_8BITENTRIES             0x00000002l
+
+/*
+ * Index is 8 bits.  There are 256 color entries in the palette table.
+ */
+#define DDPCAPS_8BIT                    0x00000004l
+
+/*
+ * Indicates that this DIRECTDRAWPALETTE should use the palette color array
+ * passed into the lpDDColorArray parameter to initialize the DIRECTDRAWPALETTE
+ * object.
+ */
+#define DDPCAPS_INITIALIZE              0x00000008l
+
+/*
+ * This palette is the one attached to the primary surface.  Changing this
+ * table has immediate effect on the display unless DDPSETPAL_VSYNC is specified
+ * and supported.
+ */
+#define DDPCAPS_PRIMARYSURFACE          0x00000010l
+
+/*
+ * This palette is the one attached to the primary surface left.  Changing
+ * this table has immediate effect on the display for the left eye unless
+ * DDPSETPAL_VSYNC is specified and supported.
+ */
+#define DDPCAPS_PRIMARYSURFACELEFT      0x00000020l
+
+/*
+ * This palette can have all 256 entries defined
+ */
+#define DDPCAPS_ALLOW256                0x00000040l
+
+/*
+ * This palette can have modifications to it synced with the monitors
+ * refresh rate.
+ */
+#define DDPCAPS_VSYNC                   0x00000080l
+
+/*
+ * Index is 1 bit.  There are two color entries in the palette table.
+ */
+#define DDPCAPS_1BIT                    0x00000100l
+
+/*
+ * Index is 2 bit.  There are four color entries in the palette table.
+ */
+#define DDPCAPS_2BIT                    0x00000200l
+
+
+/****************************************************************************
+ *
+ * DIRECTDRAWPALETTE SETENTRY CONSTANTS
+ *
+ ****************************************************************************/
+
+
+/****************************************************************************
+ *
+ * DIRECTDRAWPALETTE GETENTRY CONSTANTS
+ *
+ ****************************************************************************/
+
+/* 0 is the only legal value */
+
+/****************************************************************************
+ *
+ * DIRECTDRAWSURFACE SETPALETTE CONSTANTS
+ *
+ ****************************************************************************/
+
+
+/****************************************************************************
+ *
+ * DIRECTDRAW BITDEPTH CONSTANTS
+ *
+ * NOTE:  These are only used to indicate supported bit depths.   These
+ * are flags only, they are not to be used as an actual bit depth.   The
+ * absolute numbers 1, 2, 4, 8, 16, 24 and 32 are used to indicate actual
+ * bit depths in a surface or for changing the display mode.
+ *
+ ****************************************************************************/
+
+/*
+ * 1 bit per pixel.
+ */
+#define DDBD_1                  0x00004000l
+
+/*
+ * 2 bits per pixel.
+ */
+#define DDBD_2                  0x00002000l
+
+/*
+ * 4 bits per pixel.
+ */
+#define DDBD_4                  0x00001000l
+
+/*
+ * 8 bits per pixel.
+ */
+#define DDBD_8                  0x00000800l
+
+/*
+ * 16 bits per pixel.
+ */
+#define DDBD_16                 0x00000400l
+
+/*
+ * 24 bits per pixel.
+ */
+#define DDBD_24                 0X00000200l
+
+/*
+ * 32 bits per pixel.
+ */
+#define DDBD_32                 0x00000100l
+
+/****************************************************************************
+ *
+ * DIRECTDRAWSURFACE SET/GET COLOR KEY FLAGS
+ *
+ ****************************************************************************/
+
+/*
+ * Set if the structure contains a color space.  Not set if the structure
+ * contains a single color key.
+ */
+#define DDCKEY_COLORSPACE       0x00000001l
+
+/*
+ * Set if the structure specifies a color key or color space which is to be
+ * used as a destination color key for blt operations.
+ */
+#define DDCKEY_DESTBLT          0x00000002l
+
+/*
+ * Set if the structure specifies a color key or color space which is to be
+ * used as a destination color key for overlay operations.
+ */
+#define DDCKEY_DESTOVERLAY      0x00000004l
+
+/*
+ * Set if the structure specifies a color key or color space which is to be
+ * used as a source color key for blt operations.
+ */
+#define DDCKEY_SRCBLT           0x00000008l
+
+/*
+ * Set if the structure specifies a color key or color space which is to be
+ * used as a source color key for overlay operations.
+ */
+#define DDCKEY_SRCOVERLAY       0x00000010l
+
+
+/****************************************************************************
+ *
+ * DIRECTDRAW COLOR KEY CAPABILITY FLAGS
+ *
+ ****************************************************************************/
+
+/*
+ * Supports transparent blting using a color key to identify the replaceable 
+ * bits of the destination surface for RGB colors.
+ */
+#define DDCKEYCAPS_DESTBLT                      0x00000001l
+
+/*
+ * Supports transparent blting using a color space to identify the replaceable
+ * bits of the destination surface for RGB colors.
+ */
+#define DDCKEYCAPS_DESTBLTCLRSPACE              0x00000002l
+
+/*
+ * Supports transparent blting using a color space to identify the replaceable
+ * bits of the destination surface for YUV colors.
+ */
+#define DDCKEYCAPS_DESTBLTCLRSPACEYUV           0x00000004l
+
+/*
+ * Supports transparent blting using a color key to identify the replaceable 
+ * bits of the destination surface for YUV colors.
+ */
+#define DDCKEYCAPS_DESTBLTYUV                   0x00000008l
+
+/*
+ * Supports overlaying using colorkeying of the replaceable bits of the surface
+ * being overlayed for RGB colors.
+ */
+#define DDCKEYCAPS_DESTOVERLAY                  0x00000010l
+
+/*
+ * Supports a color space as the color key for the destination for RGB colors.
+ */
+#define DDCKEYCAPS_DESTOVERLAYCLRSPACE          0x00000020l
+
+/*
+ * Supports a color space as the color key for the destination for YUV colors.
+ */
+#define DDCKEYCAPS_DESTOVERLAYCLRSPACEYUV       0x00000040l
+
+/*
+ * Supports only one active destination color key value for visible overlay
+ * surfaces.
+ */
+#define DDCKEYCAPS_DESTOVERLAYONEACTIVE         0x00000080l
+
+/*
+ * Supports overlaying using colorkeying of the replaceable bits of the 
+ * surface being overlayed for YUV colors.
+ */
+#define DDCKEYCAPS_DESTOVERLAYYUV               0x00000100l
+
+/*
+ * Supports transparent blting using the color key for the source with
+ * this surface for RGB colors.
+ */
+#define DDCKEYCAPS_SRCBLT                       0x00000200l
+
+/*
+ * Supports transparent blting using a color space for the source with
+ * this surface for RGB colors.
+ */
+#define DDCKEYCAPS_SRCBLTCLRSPACE               0x00000400l
+
+/*
+ * Supports transparent blting using a color space for the source with
+ * this surface for YUV colors.
+ */
+#define DDCKEYCAPS_SRCBLTCLRSPACEYUV            0x00000800l
+
+/*
+ * Supports transparent blting using the color key for the source with
+ * this surface for YUV colors.
+ */
+#define DDCKEYCAPS_SRCBLTYUV                    0x00001000l
+
+/*
+ * Supports overlays using the color key for the source with this
+ * overlay surface for RGB colors.
+ */
+#define DDCKEYCAPS_SRCOVERLAY                   0x00002000l
+
+/*
+ * Supports overlays using a color space as the source color key for
+ * the overlay surface for RGB colors.
+ */
+#define DDCKEYCAPS_SRCOVERLAYCLRSPACE           0x00004000l
+
+/*
+ * Supports overlays using a color space as the source color key for
+ * the overlay surface for YUV colors.
+ */
+#define DDCKEYCAPS_SRCOVERLAYCLRSPACEYUV        0x00008000l
+
+/*
+ * Supports only one active source color key value for visible
+ * overlay surfaces.
+ */
+#define DDCKEYCAPS_SRCOVERLAYONEACTIVE          0x00010000l
+
+/*
+ * Supports overlays using the color key for the source with this
+ * overlay surface for YUV colors.
+ */
+#define DDCKEYCAPS_SRCOVERLAYYUV                0x00020000l
+
+/*
+ * there are no bandwidth trade-offs for using colorkey with an overlay
+ */
+#define DDCKEYCAPS_NOCOSTOVERLAY                0x00040000l
+
+
+/****************************************************************************
+ *
+ * DIRECTDRAW PIXELFORMAT FLAGS
+ *
+ ****************************************************************************/
+
+/*
+ * The surface has alpha channel information in the pixel format.
+ */
+#define DDPF_ALPHAPIXELS                        0x00000001l
+
+/*
+ * The pixel format contains alpha only information
+ */
+#define DDPF_ALPHA                              0x00000002l
+
+/*
+ * The FourCC code is valid.
+ */
+#define DDPF_FOURCC                             0x00000004l
+
+/*
+ * The surface is 4-bit color indexed.
+ */
+#define DDPF_PALETTEINDEXED4                    0x00000008l
+
+/*
+ * The surface is indexed into a palette which stores indices
+ * into the destination surface's 8-bit palette.
+ */
+#define DDPF_PALETTEINDEXEDTO8                  0x00000010l
+
+/*
+ * The surface is 8-bit color indexed.
+ */
+#define DDPF_PALETTEINDEXED8                    0x00000020l
+
+/*
+ * The RGB data in the pixel format structure is valid.
+ */
+#define DDPF_RGB                                0x00000040l
+
+/*
+ * The surface will accept pixel data in the format specified
+ * and compress it during the write.
+ */
+#define DDPF_COMPRESSED                         0x00000080l
+
+/*
+ * The surface will accept RGB data and translate it during
+ * the write to YUV data.  The format of the data to be written
+ * will be contained in the pixel format structure.  The DDPF_RGB
+ * flag will be set. 
+ */
+#define DDPF_RGBTOYUV                           0x00000100l
+
+/*
+ * pixel format is YUV - YUV data in pixel format struct is valid
+ */
+#define DDPF_YUV                                0x00000200l
+
+/*
+ * pixel format is a z buffer only surface
+ */
+#define DDPF_ZBUFFER                            0x00000400l
+
+/*
+ * The surface is 1-bit color indexed.
+ */
+#define DDPF_PALETTEINDEXED1                    0x00000800l
+
+/*
+ * The surface is 2-bit color indexed.
+ */
+#define DDPF_PALETTEINDEXED2                    0x00001000l
+
+/*===========================================================================
+ *
+ *
+ * DIRECTDRAW CALLBACK FLAGS
+ *
+ *
+ *==========================================================================*/
+
+/****************************************************************************
+ *
+ * DIRECTDRAW ENUMSURFACES FLAGS
+ *
+ ****************************************************************************/
+
+/*
+ * Enumerate all of the surfaces that meet the search criterion.
+ */
+#define DDENUMSURFACES_ALL                      0x00000001l
+
+/*
+ * A search hit is a surface that matches the surface description.
+ */
+#define DDENUMSURFACES_MATCH                    0x00000002l
+
+/*
+ * A search hit is a surface that does not match the surface description.
+ */
+#define DDENUMSURFACES_NOMATCH                  0x00000004l
+
+/*
+ * Enumerate the first surface that can be created which meets the search criterion.
+ */
+#define DDENUMSURFACES_CANBECREATED             0x00000008l
+
+/*
+ * Enumerate the surfaces that already exist that meet the search criterion.
+ */
+#define DDENUMSURFACES_DOESEXIST                0x00000010l
+
+
+/****************************************************************************
+ *
+ * DIRECTDRAW ENUMDISPLAYMODES FLAGS
+ *
+ ****************************************************************************/
+
+/*
+ * Enumerate Modes with different refresh rates.  EnumDisplayModes guarantees
+ * that a particular mode will be enumerated only once.  This flag specifies whether
+ * the refresh rate is taken into account when determining if a mode is unique.
+ */
+#define DDEDM_REFRESHRATES                      0x00000001l
+
+
+/****************************************************************************
+ *
+ * DIRECTDRAW SETCOOPERATIVELEVEL FLAGS
+ *
+ ****************************************************************************/
+
+/*
+ * Exclusive mode owner will be responsible for the entire primary surface.
+ * GDI can be ignored. used with DD
+ */
+#define DDSCL_FULLSCREEN                        0x00000001l
+
+/*
+ * allow CTRL_ALT_DEL to work while in fullscreen exclusive mode 
+ */
+#define DDSCL_ALLOWREBOOT                       0x00000002l
+
+/*
+ * prevents DDRAW from modifying the application window.
+ * prevents DDRAW from minimize/restore the application window on activation.
+ */
+#define DDSCL_NOWINDOWCHANGES                   0x00000004l
+
+/*
+ * app wants to work as a regular Windows application
+ */
+#define DDSCL_NORMAL                            0x00000008l
+
+/*
+ * app wants exclusive access
+ */
+#define DDSCL_EXCLUSIVE                         0x00000010l
+
+
+/*
+ * app can deal with non-windows display modes
+ */
+#define DDSCL_ALLOWMODEX                        0x00000040l
+
+
+/****************************************************************************
+ *
+ * DIRECTDRAW BLT FLAGS
+ *
+ ****************************************************************************/
+
+/*
+ * Use the alpha information in the pixel format or the alpha channel surface
+ * attached to the destination surface as the alpha channel for this blt.
+ */
+#define DDBLT_ALPHADEST                         0x00000001l
+
+/*
+ * Use the dwConstAlphaDest field in the DDBLTFX structure as the alpha channel
+ * for the destination surface for this blt.
+ */
+#define DDBLT_ALPHADESTCONSTOVERRIDE            0x00000002l
+
+/*
+ * The NEG suffix indicates that the destination surface becomes more
+ * transparent as the alpha value increases. (0 is opaque)
+ */
+#define DDBLT_ALPHADESTNEG                      0x00000004l
+
+/*
+ * Use the lpDDSAlphaDest field in the DDBLTFX structure as the alpha
+ * channel for the destination for this blt.
+ */
+#define DDBLT_ALPHADESTSURFACEOVERRIDE          0x00000008l
+
+/*
+ * Use the dwAlphaEdgeBlend field in the DDBLTFX structure as the alpha channel
+ * for the edges of the image that border the color key colors.
+ */
+#define DDBLT_ALPHAEDGEBLEND                    0x00000010l
+
+/*
+ * Use the alpha information in the pixel format or the alpha channel surface
+ * attached to the source surface as the alpha channel for this blt.
+ */
+#define DDBLT_ALPHASRC                          0x00000020l
+
+/*
+ * Use the dwConstAlphaSrc field in the DDBLTFX structure as the alpha channel
+ * for the source for this blt.
+ */
+#define DDBLT_ALPHASRCCONSTOVERRIDE             0x00000040l
+
+/*
+ * The NEG suffix indicates that the source surface becomes more transparent
+ * as the alpha value increases. (0 is opaque)
+ */
+#define DDBLT_ALPHASRCNEG                       0x00000080l
+
+/*
+ * Use the lpDDSAlphaSrc field in the DDBLTFX structure as the alpha channel
+ * for the source for this blt. 
+ */
+#define DDBLT_ALPHASRCSURFACEOVERRIDE           0x00000100l
+
+/*
+ * Do this blt asynchronously through the FIFO in the order received.  If
+ * there is no room in the hardware FIFO fail the call.
+ */
+#define DDBLT_ASYNC                             0x00000200l
+
+/*
+ * Uses the dwFillColor field in the DDBLTFX structure as the RGB color
+ * to fill the destination rectangle on the destination surface with.
+ */
+#define DDBLT_COLORFILL                         0x00000400l
+
+/*
+ * Uses the dwDDFX field in the DDBLTFX structure to specify the effects
+ * to use for the blt.
+ */
+#define DDBLT_DDFX                              0x00000800l
+
+/*
+ * Uses the dwDDROPS field in the DDBLTFX structure to specify the ROPS
+ * that are not part of the Win32 API.
+ */
+#define DDBLT_DDROPS                            0x00001000l
+
+/*
+ * Use the color key associated with the destination surface.
+ */
+#define DDBLT_KEYDEST                           0x00002000l
+
+/*
+ * Use the dckDestColorkey field in the DDBLTFX structure as the color key
+ * for the destination surface.
+ */
+#define DDBLT_KEYDESTOVERRIDE                   0x00004000l
+
+/*
+ * Use the color key associated with the source surface.
+ */
+#define DDBLT_KEYSRC                            0x00008000l
+
+/*
+ * Use the dckSrcColorkey field in the DDBLTFX structure as the color key
+ * for the source surface.
+ */
+#define DDBLT_KEYSRCOVERRIDE                    0x00010000l
+
+/*
+ * Use the dwROP field in the DDBLTFX structure for the raster operation
+ * for this blt.  These ROPs are the same as the ones defined in the Win32 API.
+ */
+#define DDBLT_ROP                               0x00020000l
+
+/*
+ * Use the dwRotationAngle field in the DDBLTFX structure as the angle
+ * (specified in 1/100th of a degree) to rotate the surface.
+ */
+#define DDBLT_ROTATIONANGLE                     0x00040000l
+
+/*
+ * Z-buffered blt using the z-buffers attached to the source and destination
+ * surfaces and the dwZBufferOpCode field in the DDBLTFX structure as the
+ * z-buffer opcode.
+ */
+#define DDBLT_ZBUFFER                           0x00080000l
+
+/*
+ * Z-buffered blt using the dwConstDest Zfield and the dwZBufferOpCode field
+ * in the DDBLTFX structure as the z-buffer and z-buffer opcode respectively
+ * for the destination.
+ */
+#define DDBLT_ZBUFFERDESTCONSTOVERRIDE          0x00100000l
+
+/*
+ * Z-buffered blt using the lpDDSDestZBuffer field and the dwZBufferOpCode
+ * field in the DDBLTFX structure as the z-buffer and z-buffer opcode
+ * respectively for the destination.
+ */
+#define DDBLT_ZBUFFERDESTOVERRIDE               0x00200000l
+
+/*
+ * Z-buffered blt using the dwConstSrcZ field and the dwZBufferOpCode field
+ * in the DDBLTFX structure as the z-buffer and z-buffer opcode respectively
+ * for the source.
+ */
+#define DDBLT_ZBUFFERSRCCONSTOVERRIDE           0x00400000l
+
+/*
+ * Z-buffered blt using the lpDDSSrcZBuffer field and the dwZBufferOpCode
+ * field in the DDBLTFX structure as the z-buffer and z-buffer opcode
+ * respectively for the source.
+ */
+#define DDBLT_ZBUFFERSRCOVERRIDE                0x00800000l
+
+/*
+ * wait until the device is ready to handle the blt
+ * this will cause blt to not return DDERR_WASSTILLDRAWING
+ */
+#define DDBLT_WAIT                              0x01000000l
+
+/*
+ * Uses the dwFillDepth field in the DDBLTFX structure as the depth value
+ * to fill the destination rectangle on the destination Z-buffer surface
+ * with.
+ */
+#define DDBLT_DEPTHFILL                         0x02000000l
+
+
+/****************************************************************************
+ *
+ * BLTFAST FLAGS
+ *
+ ****************************************************************************/
+
+#define DDBLTFAST_NOCOLORKEY                    0x00000000
+#define DDBLTFAST_SRCCOLORKEY                   0x00000001
+#define DDBLTFAST_DESTCOLORKEY                  0x00000002
+#define DDBLTFAST_WAIT                          0x00000010
+
+/****************************************************************************
+ *
+ * FLIP FLAGS
+ *
+ ****************************************************************************/
+
+#define DDFLIP_WAIT                          0x00000001l
+
+
+/****************************************************************************
+ *
+ * DIRECTDRAW SURFACE OVERLAY FLAGS
+ *
+ ****************************************************************************/
+
+/*
+ * Use the alpha information in the pixel format or the alpha channel surface
+ * attached to the destination surface as the alpha channel for the
+ * destination overlay.
+ */
+#define DDOVER_ALPHADEST                        0x00000001l
+
+/*
+ * Use the dwConstAlphaDest field in the DDOVERLAYFX structure as the
+ * destination alpha channel for this overlay.
+ */
+#define DDOVER_ALPHADESTCONSTOVERRIDE           0x00000002l
+
+/*
+ * The NEG suffix indicates that the destination surface becomes more
+ * transparent as the alpha value increases. 
+ */
+#define DDOVER_ALPHADESTNEG                     0x00000004l
+
+/*
+ * Use the lpDDSAlphaDest field in the DDOVERLAYFX structure as the alpha
+ * channel destination for this overlay.
+ */
+#define DDOVER_ALPHADESTSURFACEOVERRIDE         0x00000008l
+
+/*
+ * Use the dwAlphaEdgeBlend field in the DDOVERLAYFX structure as the alpha
+ * channel for the edges of the image that border the color key colors.
+ */
+#define DDOVER_ALPHAEDGEBLEND                   0x00000010l
+
+/*
+ * Use the alpha information in the pixel format or the alpha channel surface
+ * attached to the source surface as the source alpha channel for this overlay.
+ */
+#define DDOVER_ALPHASRC                         0x00000020l
+
+/*
+ * Use the dwConstAlphaSrc field in the DDOVERLAYFX structure as the source
+ * alpha channel for this overlay.
+ */
+#define DDOVER_ALPHASRCCONSTOVERRIDE            0x00000040l
+
+/*
+ * The NEG suffix indicates that the source surface becomes more transparent
+ * as the alpha value increases.
+ */
+#define DDOVER_ALPHASRCNEG                      0x00000080l
+
+/*
+ * Use the lpDDSAlphaSrc field in the DDOVERLAYFX structure as the alpha channel
+ * source for this overlay.
+ */
+#define DDOVER_ALPHASRCSURFACEOVERRIDE          0x00000100l
+
+/*
+ * Turn this overlay off.
+ */
+#define DDOVER_HIDE                             0x00000200l
+
+/*
+ * Use the color key associated with the destination surface.
+ */
+#define DDOVER_KEYDEST                          0x00000400l
+
+/*
+ * Use the dckDestColorkey field in the DDOVERLAYFX structure as the color key
+ * for the destination surface
+ */
+#define DDOVER_KEYDESTOVERRIDE                  0x00000800l
+
+/*
+ * Use the color key associated with the source surface.
+ */
+#define DDOVER_KEYSRC                           0x00001000l
+
+/*
+ * Use the dckSrcColorkey field in the DDOVERLAYFX structure as the color key
+ * for the source surface.
+ */
+#define DDOVER_KEYSRCOVERRIDE                   0x00002000l
+
+/*
+ * Turn this overlay on.
+ */
+#define DDOVER_SHOW                             0x00004000l
+
+/*
+ * Add a dirty rect to an emulated overlayed surface.
+ */
+#define DDOVER_ADDDIRTYRECT                     0x00008000l
+
+/*
+ * Redraw all dirty rects on an emulated overlayed surface.
+ */
+#define DDOVER_REFRESHDIRTYRECTS                0x00010000l
+
+/*
+ * Redraw the entire surface on an emulated overlayed surface.
+ */
+#define DDOVER_REFRESHALL                      0x00020000l
+
+
+/*
+ * Use the overlay FX flags to define special overlay FX
+ */
+#define DDOVER_DDFX                             0x00080000l
+
+
+/****************************************************************************
+ *
+ * DIRECTDRAWSURFACE LOCK FLAGS
+ *
+ ****************************************************************************/
+
+/*
+ * The default.  Set to indicate that Lock should return a valid memory pointer
+ * to the top of the specified rectangle.  If no rectangle is specified then a
+ * pointer to the top of the surface is returned.
+ */
+#define DDLOCK_SURFACEMEMORYPTR                 0x00000000L     // default
+
+/*
+ * Set to indicate that Lock should wait until it can obtain a valid memory
+ * pointer before returning.  If this bit is set, Lock will never return 
+ * DDERR_WASSTILLDRAWING.
+ */
+#define DDLOCK_WAIT                             0x00000001L
+
+/*
+ * Set if an event handle is being passed to Lock.  Lock will trigger the event
+ * when it can return the surface memory pointer requested.
+ */
+#define DDLOCK_EVENT                            0x00000002L
+
+/*
+ * Indicates that the surface being locked will only be read from.
+ */
+#define DDLOCK_READONLY                         0x00000010L
+
+/*
+ * Indicates that the surface being locked will only be written to
+ */
+#define DDLOCK_WRITEONLY                        0x00000020L
+
+
+/****************************************************************************
+ *
+ * DIRECTDRAWSURFACE PAGELOCK FLAGS
+ *
+ ****************************************************************************/
+
+/*
+ * No flags defined at present
+ */
+
+
+/****************************************************************************
+ *
+ * DIRECTDRAWSURFACE PAGEUNLOCK FLAGS
+ *
+ ****************************************************************************/
+
+/*
+ * No flags defined at present
+ */
+
+
+/****************************************************************************
+ *
+ * DIRECTDRAWSURFACE BLT FX FLAGS
+ *
+ ****************************************************************************/
+
+/*
+ * If stretching, use arithmetic stretching along the Y axis for this blt.
+ */
+#define DDBLTFX_ARITHSTRETCHY                   0x00000001l
+
+/*
+ * Do this blt mirroring the surface left to right.  Spin the
+ * surface around its y-axis.
+ */
+#define DDBLTFX_MIRRORLEFTRIGHT                 0x00000002l
+
+/*
+ * Do this blt mirroring the surface up and down.  Spin the surface
+ * around its x-axis.
+ */
+#define DDBLTFX_MIRRORUPDOWN                    0x00000004l
+
+/*
+ * Schedule this blt to avoid tearing.
+ */
+#define DDBLTFX_NOTEARING                       0x00000008l
+
+/*
+ * Do this blt rotating the surface one hundred and eighty degrees.
+ */
+#define DDBLTFX_ROTATE180                       0x00000010l
+
+/*
+ * Do this blt rotating the surface two hundred and seventy degrees.
+ */
+#define DDBLTFX_ROTATE270                       0x00000020l
+
+/*
+ * Do this blt rotating the surface ninety degrees.
+ */
+#define DDBLTFX_ROTATE90                        0x00000040l
+
+/*
+ * Do this z blt using dwZBufferLow and dwZBufferHigh as  range values
+ * specified to limit the bits copied from the source surface.
+ */
+#define DDBLTFX_ZBUFFERRANGE                    0x00000080l
+
+/*
+ * Do this z blt adding the dwZBufferBaseDest to each of the sources z values
+ * before comparing it with the desting z values.
+ */
+#define DDBLTFX_ZBUFFERBASEDEST                 0x00000100l
+
+/****************************************************************************
+ *
+ * DIRECTDRAWSURFACE OVERLAY FX FLAGS
+ *
+ ****************************************************************************/
+
+/*
+ * If stretching, use arithmetic stretching along the Y axis for this overlay.
+ */
+#define DDOVERFX_ARITHSTRETCHY                  0x00000001l
+
+/*
+ * Mirror the overlay across the vertical axis
+ */
+#define DDOVERFX_MIRRORLEFTRIGHT                0x00000002l
+
+/*
+ * Mirror the overlay across the horizontal axis
+ */
+#define DDOVERFX_MIRRORUPDOWN                   0x00000004l
+
+/****************************************************************************
+ *
+ * DIRECTDRAW WAITFORVERTICALBLANK FLAGS
+ *
+ ****************************************************************************/
+
+/*
+ * return when the vertical blank interval begins
+ */
+#define DDWAITVB_BLOCKBEGIN                     0x00000001l
+
+/*
+ * set up an event to trigger when the vertical blank begins
+ */
+#define DDWAITVB_BLOCKBEGINEVENT                0x00000002l
+
+/*
+ * return when the vertical blank interval ends and display begins
+ */
+#define DDWAITVB_BLOCKEND                       0x00000004l
+
+/****************************************************************************
+ *
+ * DIRECTDRAW GETFLIPSTATUS FLAGS
+ *
+ ****************************************************************************/
+
+/*
+ * is it OK to flip now?
+ */
+#define DDGFS_CANFLIP                   0x00000001l
+
+/*
+ * is the last flip finished?
+ */
+#define DDGFS_ISFLIPDONE                0x00000002l
+
+/****************************************************************************
+ *
+ * DIRECTDRAW GETBLTSTATUS FLAGS
+ *
+ ****************************************************************************/
+
+/*
+ * is it OK to blt now?
+ */
+#define DDGBS_CANBLT                    0x00000001l
+
+/*
+ * is the blt to the surface finished?
+ */
+#define DDGBS_ISBLTDONE                 0x00000002l
+
+
+/****************************************************************************
+ *
+ * DIRECTDRAW ENUMOVERLAYZORDER FLAGS
+ *
+ ****************************************************************************/
+
+/*
+ * Enumerate overlays back to front.
+ */
+#define DDENUMOVERLAYZ_BACKTOFRONT      0x00000000l
+
+/*
+ * Enumerate overlays front to back
+ */
+#define DDENUMOVERLAYZ_FRONTTOBACK      0x00000001l
+
+/****************************************************************************
+ *
+ * DIRECTDRAW UPDATEOVERLAYZORDER FLAGS
+ *
+ ****************************************************************************/
+
+/*
+ * Send overlay to front
+ */
+#define DDOVERZ_SENDTOFRONT             0x00000000l
+
+/*
+ * Send overlay to back
+ */
+#define DDOVERZ_SENDTOBACK              0x00000001l
+
+/*
+ * Move Overlay forward
+ */
+#define DDOVERZ_MOVEFORWARD             0x00000002l
+
+/*
+ * Move Overlay backward
+ */
+#define DDOVERZ_MOVEBACKWARD            0x00000003l
+
+/*
+ * Move Overlay in front of relative surface
+ */
+#define DDOVERZ_INSERTINFRONTOF         0x00000004l
+
+/*
+ * Move Overlay in back of relative surface
+ */
+#define DDOVERZ_INSERTINBACKOF          0x00000005l
+
+/*===========================================================================
+ *
+ *
+ * DIRECTDRAW RETURN CODES
+ *
+ * The return values from DirectDraw Commands and Surface that return an HRESULT
+ * are codes from DirectDraw concerning the results of the action
+ * requested by DirectDraw.
+ *
+ *==========================================================================*/
+
+/*
+ * Status is OK
+ *
+ * Issued by: DirectDraw Commands and all callbacks
+ */
+#define DD_OK                                   0
+
+/****************************************************************************
+ *
+ * DIRECTDRAW ENUMCALLBACK RETURN VALUES
+ *
+ * EnumCallback returns are used to control the flow of the DIRECTDRAW and
+ * DIRECTDRAWSURFACE object enumerations.   They can only be returned by
+ * enumeration callback routines.
+ *
+ ****************************************************************************/
+
+/*
+ * stop the enumeration
+ */
+#define DDENUMRET_CANCEL                        0
+
+/*
+ * continue the enumeration
+ */
+#define DDENUMRET_OK                            1
+
+/****************************************************************************
+ *
+ * DIRECTDRAW ERRORS
+ *
+ * Errors are represented by negative values and cannot be combined.
+ *
+ ****************************************************************************/
+
+/*
+ * This object is already initialized
+ */
+#define DDERR_ALREADYINITIALIZED                MAKE_DDHRESULT( 5 )
+
+/*
+ * This surface can not be attached to the requested surface.
+ */
+#define DDERR_CANNOTATTACHSURFACE               MAKE_DDHRESULT( 10 )
+
+/*
+ * This surface can not be detached from the requested surface.
+ */
+#define DDERR_CANNOTDETACHSURFACE               MAKE_DDHRESULT( 20 )
+
+/*
+ * Support is currently not available.
+ */
+#define DDERR_CURRENTLYNOTAVAIL                 MAKE_DDHRESULT( 40 )
+
+/*
+ * An exception was encountered while performing the requested operation
+ */
+#define DDERR_EXCEPTION                         MAKE_DDHRESULT( 55 )
+
+/*
+ * Generic failure.
+ */
+#define DDERR_GENERIC                           E_FAIL
+
+/*
+ * Height of rectangle provided is not a multiple of reqd alignment
+ */
+#define DDERR_HEIGHTALIGN                       MAKE_DDHRESULT( 90 )
+
+/*
+ * Unable to match primary surface creation request with existing 
+ * primary surface.
+ */
+#define DDERR_INCOMPATIBLEPRIMARY               MAKE_DDHRESULT( 95 )
+
+/*
+ * One or more of the caps bits passed to the callback are incorrect.
+ */
+#define DDERR_INVALIDCAPS                       MAKE_DDHRESULT( 100 )
+
+/*
+ * DirectDraw does not support provided Cliplist.
+ */
+#define DDERR_INVALIDCLIPLIST                   MAKE_DDHRESULT( 110 )
+
+/*
+ * DirectDraw does not support the requested mode
+ */
+#define DDERR_INVALIDMODE                       MAKE_DDHRESULT( 120 )
+
+/*
+ * DirectDraw received a pointer that was an invalid DIRECTDRAW object.
+ */
+#define DDERR_INVALIDOBJECT                     MAKE_DDHRESULT( 130 )
+
+/*
+ * One or more of the parameters passed to the callback function are
+ * incorrect.
+ */
+#define DDERR_INVALIDPARAMS                     E_INVALIDARG
+
+/*
+ * pixel format was invalid as specified
+ */
+#define DDERR_INVALIDPIXELFORMAT                MAKE_DDHRESULT( 145 )
+
+/*
+ * Rectangle provided was invalid.
+ */
+#define DDERR_INVALIDRECT                       MAKE_DDHRESULT( 150 )
+
+/*
+ * Operation could not be carried out because one or more surfaces are locked
+ */
+#define DDERR_LOCKEDSURFACES                    MAKE_DDHRESULT( 160 )
+
+/*
+ * There is no 3D present.
+ */
+#define DDERR_NO3D                              MAKE_DDHRESULT( 170 )
+
+/*
+ * Operation could not be carried out because there is no alpha accleration
+ * hardware present or available.
+ */
+#define DDERR_NOALPHAHW                         MAKE_DDHRESULT( 180 )
+
+
+/*
+ * no clip list available
+ */
+#define DDERR_NOCLIPLIST                        MAKE_DDHRESULT( 205 )
+
+/*
+ * Operation could not be carried out because there is no color conversion
+ * hardware present or available.
+ */
+#define DDERR_NOCOLORCONVHW                     MAKE_DDHRESULT( 210 )
+
+/*
+ * Create function called without DirectDraw object method SetCooperativeLevel
+ * being called.
+ */
+#define DDERR_NOCOOPERATIVELEVELSET             MAKE_DDHRESULT( 212 )
+
+/*
+ * Surface doesn't currently have a color key
+ */
+#define DDERR_NOCOLORKEY                        MAKE_DDHRESULT( 215 )
+
+/*
+ * Operation could not be carried out because there is no hardware support
+ * of the dest color key.
+ */
+#define DDERR_NOCOLORKEYHW                      MAKE_DDHRESULT( 220 )
+
+/*
+ * No DirectDraw support possible with current display driver
+ */
+#define DDERR_NODIRECTDRAWSUPPORT               MAKE_DDHRESULT( 222 )
+
+/*
+ * Operation requires the application to have exclusive mode but the
+ * application does not have exclusive mode.
+ */
+#define DDERR_NOEXCLUSIVEMODE                   MAKE_DDHRESULT( 225 )
+
+/*
+ * Flipping visible surfaces is not supported.
+ */
+#define DDERR_NOFLIPHW                          MAKE_DDHRESULT( 230 )
+
+/*
+ * There is no GDI present.
+ */
+#define DDERR_NOGDI                             MAKE_DDHRESULT( 240 )
+
+/*
+ * Operation could not be carried out because there is no hardware present
+ * or available.
+ */
+#define DDERR_NOMIRRORHW                        MAKE_DDHRESULT( 250 )
+
+/*
+ * Requested item was not found
+ */
+#define DDERR_NOTFOUND                          MAKE_DDHRESULT( 255 )
+
+/*
+ * Operation could not be carried out because there is no overlay hardware
+ * present or available.
+ */
+#define DDERR_NOOVERLAYHW                       MAKE_DDHRESULT( 260 )
+
+/*
+ * Operation could not be carried out because there is no appropriate raster
+ * op hardware present or available.
+ */
+#define DDERR_NORASTEROPHW                      MAKE_DDHRESULT( 280 )
+
+/*
+ * Operation could not be carried out because there is no rotation hardware
+ * present or available.
+ */
+#define DDERR_NOROTATIONHW                      MAKE_DDHRESULT( 290 )
+
+/*
+ * Operation could not be carried out because there is no hardware support
+ * for stretching
+ */
+#define DDERR_NOSTRETCHHW                       MAKE_DDHRESULT( 310 )
+
+/*
+ * DirectDrawSurface is not in 4 bit color palette and the requested operation
+ * requires 4 bit color palette.
+ */
+#define DDERR_NOT4BITCOLOR                      MAKE_DDHRESULT( 316 )
+
+/*
+ * DirectDrawSurface is not in 4 bit color index palette and the requested
+ * operation requires 4 bit color index palette.
+ */
+#define DDERR_NOT4BITCOLORINDEX                 MAKE_DDHRESULT( 317 )
+
+/*
+ * DirectDraw Surface is not in 8 bit color mode and the requested operation
+ * requires 8 bit color.
+ */
+#define DDERR_NOT8BITCOLOR                      MAKE_DDHRESULT( 320 )
+
+/*
+ * Operation could not be carried out because there is no texture mapping
+ * hardware present or available.
+ */
+#define DDERR_NOTEXTUREHW                       MAKE_DDHRESULT( 330 )
+
+/*
+ * Operation could not be carried out because there is no hardware support
+ * for vertical blank synchronized operations.
+ */
+#define DDERR_NOVSYNCHW                         MAKE_DDHRESULT( 335 )
+
+/*
+ * Operation could not be carried out because there is no hardware support
+ * for zbuffer blting.
+ */
+#define DDERR_NOZBUFFERHW                       MAKE_DDHRESULT( 340 )
+
+/*
+ * Overlay surfaces could not be z layered based on their BltOrder because
+ * the hardware does not support z layering of overlays.
+ */
+#define DDERR_NOZOVERLAYHW                      MAKE_DDHRESULT( 350 )
+
+/*
+ * The hardware needed for the requested operation has already been
+ * allocated.
+ */
+#define DDERR_OUTOFCAPS                         MAKE_DDHRESULT( 360 )
+
+/*
+ * DirectDraw does not have enough memory to perform the operation.
+ */
+#define DDERR_OUTOFMEMORY                       E_OUTOFMEMORY
+
+/*
+ * DirectDraw does not have enough memory to perform the operation.
+ */
+#define DDERR_OUTOFVIDEOMEMORY                  MAKE_DDHRESULT( 380 )
+
+/*
+ * hardware does not support clipped overlays
+ */
+#define DDERR_OVERLAYCANTCLIP                   MAKE_DDHRESULT( 382 )
+
+/*
+ * Can only have ony color key active at one time for overlays
+ */
+#define DDERR_OVERLAYCOLORKEYONLYONEACTIVE      MAKE_DDHRESULT( 384 )
+
+/*
+ * Access to this palette is being refused because the palette is already
+ * locked by another thread.
+ */
+#define DDERR_PALETTEBUSY                       MAKE_DDHRESULT( 387 )
+
+/*
+ * No src color key specified for this operation.
+ */
+#define DDERR_COLORKEYNOTSET                    MAKE_DDHRESULT( 400 )
+
+/*
+ * This surface is already attached to the surface it is being attached to.
+ */
+#define DDERR_SURFACEALREADYATTACHED            MAKE_DDHRESULT( 410 )
+
+/*
+ * This surface is already a dependency of the surface it is being made a
+ * dependency of.
+ */
+#define DDERR_SURFACEALREADYDEPENDENT           MAKE_DDHRESULT( 420 )
+
+/*
+ * Access to this surface is being refused because the surface is already
+ * locked by another thread.
+ */
+#define DDERR_SURFACEBUSY                       MAKE_DDHRESULT( 430 )
+
+/*
+ * Access to this surface is being refused because no driver exists
+ * which can supply a pointer to the surface.
+ * This is most likely to happen when attempting to lock the primary
+ * surface when no DCI provider is present.
+ */
+#define DDERR_CANTLOCKSURFACE                   MAKE_DDHRESULT( 435 )
+
+/*
+ * Access to Surface refused because Surface is obscured.
+ */
+#define DDERR_SURFACEISOBSCURED                 MAKE_DDHRESULT( 440 )
+
+/*
+ * Access to this surface is being refused because the surface is gone.
+ * The DIRECTDRAWSURFACE object representing this surface should 
+ * have Restore called on it.
+ */
+#define DDERR_SURFACELOST                       MAKE_DDHRESULT( 450 )
+
+/*
+ * The requested surface is not attached.
+ */
+#define DDERR_SURFACENOTATTACHED                MAKE_DDHRESULT( 460 )
+
+/*
+ * Height requested by DirectDraw is too large.
+ */
+#define DDERR_TOOBIGHEIGHT                      MAKE_DDHRESULT( 470 )
+
+/*
+ * Size requested by DirectDraw is too large --  The individual height and
+ * width are OK.
+ */
+#define DDERR_TOOBIGSIZE                        MAKE_DDHRESULT( 480 )
+
+/*
+ * Width requested by DirectDraw is too large.
+ */
+#define DDERR_TOOBIGWIDTH                       MAKE_DDHRESULT( 490 )
+
+/*
+ * Action not supported.
+ */
+#define DDERR_UNSUPPORTED                       E_NOTIMPL
+
+/*
+ * FOURCC format requested is unsupported by DirectDraw
+ */
+#define DDERR_UNSUPPORTEDFORMAT                 MAKE_DDHRESULT( 510 )
+
+/*
+ * Bitmask in the pixel format requested is unsupported by DirectDraw
+ */
+#define DDERR_UNSUPPORTEDMASK                   MAKE_DDHRESULT( 520 )
+
+/*
+ * vertical blank is in progress
+ */
+#define DDERR_VERTICALBLANKINPROGRESS           MAKE_DDHRESULT( 537 )
+
+/*
+ * Informs DirectDraw that the previous Blt which is transfering information
+ * to or from this Surface is incomplete.
+ */
+#define DDERR_WASSTILLDRAWING                   MAKE_DDHRESULT( 540 )
+
+/*
+ * Rectangle provided was not horizontally aligned on reqd. boundary
+ */
+#define DDERR_XALIGN                            MAKE_DDHRESULT( 560 )
+
+/*
+ * The GUID passed to DirectDrawCreate is not a valid DirectDraw driver
+ * identifier.
+ */
+#define DDERR_INVALIDDIRECTDRAWGUID             MAKE_DDHRESULT( 561 )
+
+/*
+ * A DirectDraw object representing this driver has already been created
+ * for this process.
+ */
+#define DDERR_DIRECTDRAWALREADYCREATED          MAKE_DDHRESULT( 562 )
+
+/*
+ * A hardware only DirectDraw object creation was attempted but the driver
+ * did not support any hardware.
+ */
+#define DDERR_NODIRECTDRAWHW                    MAKE_DDHRESULT( 563 )
+
+/*
+ * this process already has created a primary surface
+ */
+#define DDERR_PRIMARYSURFACEALREADYEXISTS       MAKE_DDHRESULT( 564 )
+
+/*
+ * software emulation not available.
+ */
+#define DDERR_NOEMULATION                       MAKE_DDHRESULT( 565 )
+
+/*
+ * region passed to Clipper::GetClipList is too small.
+ */
+#define DDERR_REGIONTOOSMALL                    MAKE_DDHRESULT( 566 )
+
+/*
+ * an attempt was made to set a clip list for a clipper objec that
+ * is already monitoring an hwnd.
+ */
+#define DDERR_CLIPPERISUSINGHWND                MAKE_DDHRESULT( 567 )
+
+/*
+ * No clipper object attached to surface object
+ */
+#define DDERR_NOCLIPPERATTACHED                 MAKE_DDHRESULT( 568 )
+
+/*
+ * Clipper notification requires an HWND or
+ * no HWND has previously been set as the CooperativeLevel HWND.
+ */
+#define DDERR_NOHWND                            MAKE_DDHRESULT( 569 )
+
+/*
+ * HWND used by DirectDraw CooperativeLevel has been subclassed,
+ * this prevents DirectDraw from restoring state.
+ */
+#define DDERR_HWNDSUBCLASSED                    MAKE_DDHRESULT( 570 )
+
+/*
+ * The CooperativeLevel HWND has already been set.
+ * It can not be reset while the process has surfaces or palettes created.
+ */
+#define DDERR_HWNDALREADYSET                    MAKE_DDHRESULT( 571 )
+
+/*
+ * No palette object attached to this surface.
+ */
+#define DDERR_NOPALETTEATTACHED                 MAKE_DDHRESULT( 572 )
+
+/*
+ * No hardware support for 16 or 256 color palettes.
+ */
+#define DDERR_NOPALETTEHW                       MAKE_DDHRESULT( 573 )
+
+/*
+ * If a clipper object is attached to the source surface passed into a
+ * BltFast call.
+ */
+#define DDERR_BLTFASTCANTCLIP                   MAKE_DDHRESULT( 574 )
+
+/*
+ * No blter.
+ */
+#define DDERR_NOBLTHW                           MAKE_DDHRESULT( 575 )
+
+/*
+ * No DirectDraw ROP hardware.
+ */
+#define DDERR_NODDROPSHW                        MAKE_DDHRESULT( 576 )
+
+/*
+ * returned when GetOverlayPosition is called on a hidden overlay
+ */
+#define DDERR_OVERLAYNOTVISIBLE                 MAKE_DDHRESULT( 577 )
+
+/*
+ * returned when GetOverlayPosition is called on a overlay that UpdateOverlay
+ * has never been called on to establish a destionation.
+ */
+#define DDERR_NOOVERLAYDEST                     MAKE_DDHRESULT( 578 )
+
+/*
+ * returned when the position of the overlay on the destionation is no longer
+ * legal for that destionation.
+ */
+#define DDERR_INVALIDPOSITION                   MAKE_DDHRESULT( 579 )
+
+/*
+ * returned when an overlay member is called for a non-overlay surface
+ */
+#define DDERR_NOTAOVERLAYSURFACE                MAKE_DDHRESULT( 580 )
+ 
+/*
+ * An attempt was made to set the cooperative level when it was already
+ * set to exclusive.
+ */
+#define DDERR_EXCLUSIVEMODEALREADYSET           MAKE_DDHRESULT( 581 )
+
+/*
+ * An attempt has been made to flip a surface that is not flippable.
+ */
+#define DDERR_NOTFLIPPABLE                      MAKE_DDHRESULT( 582 )
+
+/*
+ * Can't duplicate primary & 3D surfaces, or surfaces that are implicitly
+ * created.
+ */
+#define DDERR_CANTDUPLICATE                     MAKE_DDHRESULT( 583 )
+
+/*
+ * Surface was not locked.  An attempt to unlock a surface that was not
+ * locked at all, or by this process, has been attempted.
+ */
+#define DDERR_NOTLOCKED                         MAKE_DDHRESULT( 584 )
+
+/*
+ * Windows can not create any more DCs
+ */
+#define DDERR_CANTCREATEDC                      MAKE_DDHRESULT( 585 )
+
+/*
+ * No DC was ever created for this surface.
+ */
+#define DDERR_NODC                              MAKE_DDHRESULT( 586 )
+
+/*
+ * This surface can not be restored because it was created in a different
+ * mode.
+ */
+#define DDERR_WRONGMODE                         MAKE_DDHRESULT( 587 )
+
+/*
+ * This surface can not be restored because it is an implicitly created
+ * surface.
+ */
+#define DDERR_IMPLICITLYCREATED                 MAKE_DDHRESULT( 588 )
+
+/*
+ * The surface being used is not a palette-based surface
+ */
+#define DDERR_NOTPALETTIZED                     MAKE_DDHRESULT( 589 )
+
+
+/*
+ * The display is currently in an unsupported mode
+ */
+#define DDERR_UNSUPPORTEDMODE                   MAKE_DDHRESULT( 590 )
+
+/*
+ * Operation could not be carried out because there is no mip-map
+ * texture mapping hardware present or available.
+ */
+#define DDERR_NOMIPMAPHW                        MAKE_DDHRESULT( 591 )
+
+/*
+ * The requested action could not be performed because the surface was of
+ * the wrong type.
+ */
+#define DDERR_INVALIDSURFACETYPE                MAKE_DDHRESULT( 592 )
+
+
+
+/*
+ * A DC has already been returned for this surface. Only one DC can be 
+ * retrieved per surface.
+ */
+#define DDERR_DCALREADYCREATED                  MAKE_DDHRESULT( 620 )
+
+/*
+ * The attempt to page lock a surface failed.
+ */
+#define DDERR_CANTPAGELOCK                      MAKE_DDHRESULT( 640 )
+
+/*
+ * The attempt to page unlock a surface failed.
+ */
+#define DDERR_CANTPAGEUNLOCK                    MAKE_DDHRESULT( 660 )
+
+/*
+ * An attempt was made to page unlock a surface with no outstanding page locks.
+ */
+#define DDERR_NOTPAGELOCKED                     MAKE_DDHRESULT( 680 )
+
+/*
+ * An attempt was made to invoke an interface member of a DirectDraw object
+ * created by CoCreateInstance() before it was initialized.
+ */
+#define DDERR_NOTINITIALIZED                    CO_E_NOTINITIALIZED
+
+/* Alpha bit depth constants */
+
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif
--- /dev/null
+++ b/WinQuake/dxsdk/SDK/INC/DINPUT.H
@@ -1,0 +1,873 @@
+/****************************************************************************
+ *
+ *  Copyright (C) 1996 Microsoft Corporation.  All Rights Reserved.
+ *
+ *  File:       dinput.h
+ *  Content:    DirectInput include file
+ *
+ ****************************************************************************/
+
+#ifndef __DINPUT_INCLUDED__
+#define __DINPUT_INCLUDED__
+
+#ifdef _WIN32
+#define COM_NO_WINDOWS_H
+#include <objbase.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define DIRECTINPUT_VERSION         0x0300
+
+/****************************************************************************
+ *
+ *      Class IDs
+ *
+ ****************************************************************************/
+
+DEFINE_GUID(CLSID_DirectInput,      0x25E609E0,0xB259,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00);
+DEFINE_GUID(CLSID_DirectInputDevice,0x25E609E1,0xB259,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00);
+
+/****************************************************************************
+ *
+ *      Interfaces
+ *
+ ****************************************************************************/
+
+DEFINE_GUID(IID_IDirectInputA,     0x89521360,0xAA8A,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00);
+DEFINE_GUID(IID_IDirectInputW,     0x89521361,0xAA8A,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00);
+
+DEFINE_GUID(IID_IDirectInputDeviceA,0x5944E680,0xC92E,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00);
+DEFINE_GUID(IID_IDirectInputDeviceW,0x5944E681,0xC92E,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00);
+
+/****************************************************************************
+ *
+ *      Predefined object types
+ *
+ ****************************************************************************/
+
+DEFINE_GUID(GUID_XAxis,   0xA36D02E0,0xC9F3,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00);
+DEFINE_GUID(GUID_YAxis,   0xA36D02E1,0xC9F3,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00);
+DEFINE_GUID(GUID_ZAxis,   0xA36D02E2,0xC9F3,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00);
+DEFINE_GUID(GUID_RAxis,   0xA36D02E3,0xC9F3,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00);
+DEFINE_GUID(GUID_UAxis,   0xA36D02E4,0xC9F3,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00);
+DEFINE_GUID(GUID_VAxis,   0xA36D02E5,0xC9F3,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00);
+
+DEFINE_GUID(GUID_Button,  0xA36D02F0,0xC9F3,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00);
+DEFINE_GUID(GUID_Key,     0x55728220,0xD33C,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00);
+
+DEFINE_GUID(GUID_POV,     0xA36D02F2,0xC9F3,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00);
+
+/****************************************************************************
+ *
+ *      Predefined product GUIDs
+ *
+ ****************************************************************************/
+
+DEFINE_GUID(GUID_SysMouse,   0x6F1D2B60,0xD5A0,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00);
+DEFINE_GUID(GUID_SysKeyboard,0x6F1D2B61,0xD5A0,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00);
+
+/****************************************************************************
+ *
+ *      Interfaces and Structures...
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ *
+ *      IDirectInputDevice
+ *
+ ****************************************************************************/
+
+#define DIDEVTYPE_DEVICE    1
+#define DIDEVTYPE_MOUSE     2
+#define DIDEVTYPE_KEYBOARD  3
+#define DIDEVTYPE_JOYSTICK  4
+
+#define DIDEVTYPEMOUSE_UNKNOWN          1
+#define DIDEVTYPEMOUSE_TRADITIONAL      2
+#define DIDEVTYPEMOUSE_FINGERSTICK      3
+#define DIDEVTYPEMOUSE_TOUCHPAD         4
+#define DIDEVTYPEMOUSE_TRACKBALL        5
+
+#define DIDEVTYPEKEYBOARD_PCXT          1
+#define DIDEVTYPEKEYBOARD_OLIVETTI      2
+#define DIDEVTYPEKEYBOARD_PCAT          3
+#define DIDEVTYPEKEYBOARD_PCENH         4
+#define DIDEVTYPEKEYBOARD_NOKIA1050     5
+#define DIDEVTYPEKEYBOARD_NOKIA9140     6
+#define DIDEVTYPEKEYBOARD_NEC98         7
+#define DIDEVTYPEKEYBOARD_NEC98LAPTOP   8
+#define DIDEVTYPEKEYBOARD_NEC98106      9
+#define DIDEVTYPEKEYBOARD_JAPAN106     10
+#define DIDEVTYPEKEYBOARD_JAPANAX      11
+#define DIDEVTYPEKEYBOARD_J3100        12
+
+#define GET_DIDEVICE_TYPE(dwDevType)    LOBYTE(dwDevType)
+#define GET_DIDEVICE_SUBTYPE(dwDevType) HIBYTE(dwDevType)
+
+typedef struct _DIDEVCAPS {
+    DWORD   dwSize;
+    DWORD   dwFlags;
+    DWORD   dwDevType;
+    DWORD   dwAxes;
+    DWORD   dwButtons;
+    DWORD   dwPOVs;
+} DIDEVCAPS, *LPDIDEVCAPS;
+
+#define DIDC_ATTACHED           0x00000001
+#define DIDC_POLLEDDEVICE       0x00000002
+
+#define DIDFT_ALL           0x00000000
+
+#define DIDFT_RELAXIS       0x00000001
+#define DIDFT_ABSAXIS       0x00000002
+#define DIDFT_AXIS          0x00000003
+
+#define DIDFT_PSHBUTTON     0x00000004
+#define DIDFT_TGLBUTTON     0x00000008
+#define DIDFT_BUTTON        0x0000000C
+
+#define DIDFT_POV           0x00000010
+
+#define DIDFT_ANYINSTANCE   0x0000FF00
+#define DIDFT_MAKEINSTANCE(n) ((BYTE)(n) << 8)
+#define DIDFT_GETTYPE(n)     LOBYTE(n)
+#define DIDFT_GETINSTANCE(n) HIBYTE(n)
+
+typedef struct _DIOBJECTDATAFORMAT {
+    const GUID *pguid;
+    DWORD   dwOfs;
+    DWORD   dwType;
+    DWORD   dwFlags;
+} DIOBJECTDATAFORMAT, *LPDIOBJECTDATAFORMAT;
+typedef const DIOBJECTDATAFORMAT *LPCDIOBJECTDATAFORMAT;
+
+typedef struct _DIDATAFORMAT {
+    DWORD   dwSize;
+    DWORD   dwObjSize;
+    DWORD   dwFlags;
+    DWORD   dwDataSize;
+    DWORD   dwNumObjs;
+    LPDIOBJECTDATAFORMAT rgodf;
+} DIDATAFORMAT, *LPDIDATAFORMAT;
+typedef const DIDATAFORMAT *LPCDIDATAFORMAT;
+
+#define DIDF_ABSAXIS            0x00000001
+#define DIDF_RELAXIS            0x00000002
+
+extern const DIDATAFORMAT c_dfDIMouse;
+extern const DIDATAFORMAT c_dfDIKeyboard;
+
+typedef struct DIDEVICEOBJECTINSTANCEA {
+    DWORD   dwSize;
+    GUID    guidType;
+    DWORD   dwOfs;
+    DWORD   dwType;
+    DWORD   dwFlags;
+    CHAR    tszName[MAX_PATH];
+} DIDEVICEOBJECTINSTANCEA, *LPDIDEVICEOBJECTINSTANCEA;
+typedef struct DIDEVICEOBJECTINSTANCEW {
+    DWORD   dwSize;
+    GUID    guidType;
+    DWORD   dwOfs;
+    DWORD   dwType;
+    DWORD   dwFlags;
+    WCHAR   tszName[MAX_PATH];
+} DIDEVICEOBJECTINSTANCEW, *LPDIDEVICEOBJECTINSTANCEW;
+#ifdef UNICODE
+typedef DIDEVICEOBJECTINSTANCEW DIDEVICEOBJECTINSTANCE;
+typedef LPDIDEVICEOBJECTINSTANCEW LPDIDEVICEOBJECTINSTANCE;
+#else
+typedef DIDEVICEOBJECTINSTANCEA DIDEVICEOBJECTINSTANCE;
+typedef LPDIDEVICEOBJECTINSTANCEA LPDIDEVICEOBJECTINSTANCE;
+#endif // UNICODE
+typedef const DIDEVICEOBJECTINSTANCEA *LPCDIDEVICEOBJECTINSTANCEA;
+typedef const DIDEVICEOBJECTINSTANCEW *LPCDIDEVICEOBJECTINSTANCEW;
+typedef const DIDEVICEOBJECTINSTANCE  *LPCDIDEVICEOBJECTINSTANCE;
+
+typedef BOOL (FAR PASCAL * LPDIENUMDEVICEOBJECTSCALLBACKA)(LPCDIDEVICEOBJECTINSTANCEA, LPVOID);
+typedef BOOL (FAR PASCAL * LPDIENUMDEVICEOBJECTSCALLBACKW)(LPCDIDEVICEOBJECTINSTANCEW, LPVOID);
+#ifdef UNICODE
+#define LPDIENUMDEVICEOBJECTSCALLBACK  LPDIENUMDEVICEOBJECTSCALLBACKW
+#else
+#define LPDIENUMDEVICEOBJECTSCALLBACK  LPDIENUMDEVICEOBJECTSCALLBACKA
+#endif // !UNICODE
+
+typedef struct DIPROPHEADER {
+    DWORD   dwSize;
+    DWORD   dwHeaderSize;
+    DWORD   dwObj;
+    DWORD   dwHow;
+} DIPROPHEADER, *LPDIPROPHEADER;
+typedef const DIPROPHEADER *LPCDIPROPHEADER;
+
+#define DIPH_DEVICE             0
+#define DIPH_BYOFFSET           1
+#define DIPH_BYID               2
+
+typedef struct DIPROPDWORD {
+    DIPROPHEADER diph;
+    DWORD   dwData;
+} DIPROPDWORD, *LPDIPROPDWORD;
+typedef const DIPROPDWORD *LPCDIPROPDWORD;
+
+typedef struct DIPROPRANGE {
+    DIPROPHEADER diph;
+    LONG    lMin;
+    LONG    lMax;
+} DIPROPRANGE, *LPDIPROPRANGE;
+typedef const DIPROPRANGE *LPCDIPROPRANGE;
+
+#define DIPROPRANGE_NOMIN       ((LONG)0x80000000)
+#define DIPROPRANGE_NOMAX       ((LONG)0x7FFFFFFF)
+
+#ifdef __cplusplus
+#define MAKEDIPROP(prop)    (*(const GUID *)(prop))
+#else
+#define MAKEDIPROP(prop)    ((REFGUID)(prop))
+#endif
+
+#define DIPROP_BUFFERSIZE       MAKEDIPROP(1)
+
+#define DIPROP_AXISMODE         MAKEDIPROP(2)
+
+#define DIPROPAXISMODE_ABS      0
+#define DIPROPAXISMODE_REL      1
+
+#define DIPROP_GRANULARITY      MAKEDIPROP(3)
+
+#define DIPROP_RANGE            MAKEDIPROP(4)
+
+typedef struct DIDEVICEOBJECTDATA {
+    DWORD   dwOfs;
+    DWORD   dwData;
+    DWORD   dwTimeStamp;
+    DWORD   dwSequence;
+} DIDEVICEOBJECTDATA, *LPDIDEVICEOBJECTDATA;
+
+#define DIGDD_PEEK          0x00000001
+
+#define DISEQUENCE_COMPARE(dwSequence1, cmp, dwSequence2) \
+                        ((int)((dwSequence1) - (dwSequence2)) cmp 0)
+
+#define DISCL_EXCLUSIVE     0x00000001
+#define DISCL_NONEXCLUSIVE  0x00000002
+#define DISCL_FOREGROUND    0x00000004
+#define DISCL_BACKGROUND    0x00000008
+
+typedef struct DIDEVICEINSTANCEA {
+    DWORD   dwSize;
+    GUID    guidInstance;
+    GUID    guidProduct;
+    DWORD   dwDevType;
+    CHAR    tszInstanceName[MAX_PATH];
+    CHAR    tszProductName[MAX_PATH];
+} DIDEVICEINSTANCEA, *LPDIDEVICEINSTANCEA;
+typedef struct DIDEVICEINSTANCEW {
+    DWORD   dwSize;
+    GUID    guidInstance;
+    GUID    guidProduct;
+    DWORD   dwDevType;
+    WCHAR   tszInstanceName[MAX_PATH];
+    WCHAR   tszProductName[MAX_PATH];
+} DIDEVICEINSTANCEW, *LPDIDEVICEINSTANCEW;
+#ifdef UNICODE
+typedef DIDEVICEINSTANCEW DIDEVICEINSTANCE;
+typedef LPDIDEVICEINSTANCEW LPDIDEVICEINSTANCE;
+#else
+typedef DIDEVICEINSTANCEA DIDEVICEINSTANCE;
+typedef LPDIDEVICEINSTANCEA LPDIDEVICEINSTANCE;
+#endif // UNICODE
+typedef const DIDEVICEINSTANCEA *LPCDIDEVICEINSTANCEA;
+typedef const DIDEVICEINSTANCEW *LPCDIDEVICEINSTANCEW;
+typedef const DIDEVICEINSTANCE  *LPCDIDEVICEINSTANCE;
+
+#undef INTERFACE
+#define INTERFACE IDirectInputDeviceW
+
+DECLARE_INTERFACE_(IDirectInputDeviceW, IUnknown)
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;
+
+    /*** IDirectInputDeviceW methods ***/
+    STDMETHOD(GetCapabilities)(THIS_ LPDIDEVCAPS) PURE;
+    STDMETHOD(EnumObjects)(THIS_ LPDIENUMDEVICEOBJECTSCALLBACKW,LPVOID,DWORD) PURE;
+    STDMETHOD(GetProperty)(THIS_ REFGUID,LPDIPROPHEADER) PURE;
+    STDMETHOD(SetProperty)(THIS_ REFGUID,LPCDIPROPHEADER) PURE;
+    STDMETHOD(Acquire)(THIS) PURE;
+    STDMETHOD(Unacquire)(THIS) PURE;
+    STDMETHOD(GetDeviceState)(THIS_ DWORD,LPVOID) PURE;
+    STDMETHOD(GetDeviceData)(THIS_ DWORD,LPDIDEVICEOBJECTDATA,LPDWORD,DWORD) PURE;
+    STDMETHOD(SetDataFormat)(THIS_ LPCDIDATAFORMAT) PURE;
+    STDMETHOD(SetEventNotification)(THIS_ HANDLE) PURE;
+    STDMETHOD(SetCooperativeLevel)(THIS_ HWND,DWORD) PURE;
+    STDMETHOD(GetObjectInfo)(THIS_ LPDIDEVICEOBJECTINSTANCEW,DWORD,DWORD) PURE;
+    STDMETHOD(GetDeviceInfo)(THIS_ LPDIDEVICEINSTANCEW) PURE;
+    STDMETHOD(RunControlPanel)(THIS_ HWND,DWORD) PURE;
+    STDMETHOD(Initialize)(THIS_ HINSTANCE,DWORD,REFGUID) PURE;
+};
+
+typedef struct IDirectInputDeviceW *LPDIRECTINPUTDEVICEW;
+
+#undef INTERFACE
+#define INTERFACE IDirectInputDeviceA
+
+DECLARE_INTERFACE_(IDirectInputDeviceA, IUnknown)
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;
+
+    /*** IDirectInputDeviceA methods ***/
+    STDMETHOD(GetCapabilities)(THIS_ LPDIDEVCAPS) PURE;
+    STDMETHOD(EnumObjects)(THIS_ LPDIENUMDEVICEOBJECTSCALLBACKA,LPVOID,DWORD) PURE;
+    STDMETHOD(GetProperty)(THIS_ REFGUID,LPDIPROPHEADER) PURE;
+    STDMETHOD(SetProperty)(THIS_ REFGUID,LPCDIPROPHEADER) PURE;
+    STDMETHOD(Acquire)(THIS) PURE;
+    STDMETHOD(Unacquire)(THIS) PURE;
+    STDMETHOD(GetDeviceState)(THIS_ DWORD,LPVOID) PURE;
+    STDMETHOD(GetDeviceData)(THIS_ DWORD,LPDIDEVICEOBJECTDATA,LPDWORD,DWORD) PURE;
+    STDMETHOD(SetDataFormat)(THIS_ LPCDIDATAFORMAT) PURE;
+    STDMETHOD(SetEventNotification)(THIS_ HANDLE) PURE;
+    STDMETHOD(SetCooperativeLevel)(THIS_ HWND,DWORD) PURE;
+    STDMETHOD(GetObjectInfo)(THIS_ LPDIDEVICEOBJECTINSTANCEA,DWORD,DWORD) PURE;
+    STDMETHOD(GetDeviceInfo)(THIS_ LPDIDEVICEINSTANCEA) PURE;
+    STDMETHOD(RunControlPanel)(THIS_ HWND,DWORD) PURE;
+    STDMETHOD(Initialize)(THIS_ HINSTANCE,DWORD,REFGUID) PURE;
+};
+
+typedef struct IDirectInputDeviceA *LPDIRECTINPUTDEVICEA;
+
+#ifdef UNICODE
+#define IID_IDirectInputDevice IID_IDirectInputDeviceW
+#define IDirectInputDevice IDirectInputDeviceW
+#define IDirectInputDeviceVtbl IDirectInputDeviceWVtbl
+#else
+#define IID_IDirectInputDevice IID_IDirectInputDeviceA
+#define IDirectInputDevice IDirectInputDeviceA
+#define IDirectInputDeviceVtbl IDirectInputDeviceAVtbl
+#endif
+typedef struct IDirectInputDevice *LPDIRECTINPUTDEVICE;
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirectInputDevice_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b)
+#define IDirectInputDevice_AddRef(p) (p)->lpVtbl->AddRef(p)
+#define IDirectInputDevice_Release(p) (p)->lpVtbl->Release(p)
+#define IDirectInputDevice_GetCapabilities(p,a) (p)->lpVtbl->GetCapabilities(p,a)
+#define IDirectInputDevice_EnumObjects(p,a,b,c) (p)->lpVtbl->EnumObjects(p,a,b,c)
+#define IDirectInputDevice_GetProperty(p,a,b) (p)->lpVtbl->GetProperty(p,a,b)
+#define IDirectInputDevice_SetProperty(p,a,b) (p)->lpVtbl->SetProperty(p,a,b)
+#define IDirectInputDevice_Acquire(p) (p)->lpVtbl->Acquire(p)
+#define IDirectInputDevice_Unacquire(p) (p)->lpVtbl->Unacquire(p)
+#define IDirectInputDevice_GetDeviceState(p,a,b) (p)->lpVtbl->GetDeviceState(p,a,b)
+#define IDirectInputDevice_GetDeviceData(p,a,b,c,d) (p)->lpVtbl->GetDeviceData(p,a,b,c,d)
+#define IDirectInputDevice_SetDataFormat(p,a) (p)->lpVtbl->SetDataFormat(p,a)
+#define IDirectInputDevice_SetEventNotification(p,a) (p)->lpVtbl->SetEventNotification(p,a)
+#define IDirectInputDevice_SetCooperativeLevel(p,a,b) (p)->lpVtbl->SetCooperativeLevel(p,a,b)
+#define IDirectInputDevice_GetObjectInfo(p,a,b,c) (p)->lpVtbl->GetObjectInfo(p,a,b,c)
+#define IDirectInputDevice_GetDeviceInfo(p,a) (p)->lpVtbl->GetDeviceInfo(p,a)
+#define IDirectInputDevice_RunControlPanel(p,a,b) (p)->lpVtbl->RunControlPanel(p,a,b)
+#define IDirectInputDevice_Initialize(p,a,b,c) (p)->lpVtbl->Initialize(p,a,b,c)
+#endif
+
+/****************************************************************************
+ *
+ *      Mouse
+ *
+ ****************************************************************************/
+
+typedef struct _DIMOUSESTATE {
+    LONG    lX;
+    LONG    lY;
+    LONG    lZ;
+    BYTE    rgbButtons[4];
+} DIMOUSESTATE, *LPDIMOUSESTATE;
+
+#define DIMOFS_X        FIELD_OFFSET(DIMOUSESTATE, lX)
+#define DIMOFS_Y        FIELD_OFFSET(DIMOUSESTATE, lY)
+#define DIMOFS_Z        FIELD_OFFSET(DIMOUSESTATE, lZ)
+#define DIMOFS_BUTTON0 (FIELD_OFFSET(DIMOUSESTATE, rgbButtons) + 0)
+#define DIMOFS_BUTTON1 (FIELD_OFFSET(DIMOUSESTATE, rgbButtons) + 1)
+#define DIMOFS_BUTTON2 (FIELD_OFFSET(DIMOUSESTATE, rgbButtons) + 2)
+#define DIMOFS_BUTTON3 (FIELD_OFFSET(DIMOUSESTATE, rgbButtons) + 3)
+
+/****************************************************************************
+ *
+ *      Keyboard
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ *
+ *      DirectInput keyboard scan codes
+ *
+ ****************************************************************************/
+
+#define DIK_ESCAPE          0x01
+#define DIK_1               0x02
+#define DIK_2               0x03
+#define DIK_3               0x04
+#define DIK_4               0x05
+#define DIK_5               0x06
+#define DIK_6               0x07
+#define DIK_7               0x08
+#define DIK_8               0x09
+#define DIK_9               0x0A
+#define DIK_0               0x0B
+#define DIK_MINUS           0x0C    /* - on main keyboard */
+#define DIK_EQUALS          0x0D
+#define DIK_BACK            0x0E    /* backspace */
+#define DIK_TAB             0x0F
+#define DIK_Q               0x10
+#define DIK_W               0x11
+#define DIK_E               0x12
+#define DIK_R               0x13
+#define DIK_T               0x14
+#define DIK_Y               0x15
+#define DIK_U               0x16
+#define DIK_I               0x17
+#define DIK_O               0x18
+#define DIK_P               0x19
+#define DIK_LBRACKET        0x1A
+#define DIK_RBRACKET        0x1B
+#define DIK_RETURN          0x1C    /* Enter on main keyboard */
+#define DIK_LCONTROL        0x1D
+#define DIK_A               0x1E
+#define DIK_S               0x1F
+#define DIK_D               0x20
+#define DIK_F               0x21
+#define DIK_G               0x22
+#define DIK_H               0x23
+#define DIK_J               0x24
+#define DIK_K               0x25
+#define DIK_L               0x26
+#define DIK_SEMICOLON       0x27
+#define DIK_APOSTROPHE      0x28
+#define DIK_GRAVE           0x29    /* accent grave */
+#define DIK_LSHIFT          0x2A
+#define DIK_BACKSLASH       0x2B
+#define DIK_Z               0x2C
+#define DIK_X               0x2D
+#define DIK_C               0x2E
+#define DIK_V               0x2F
+#define DIK_B               0x30
+#define DIK_N               0x31
+#define DIK_M               0x32
+#define DIK_COMMA           0x33
+#define DIK_PERIOD          0x34    /* . on main keyboard */
+#define DIK_SLASH           0x35    /* / on main keyboard */
+#define DIK_RSHIFT          0x36
+#define DIK_MULTIPLY        0x37    /* * on numeric keypad */
+#define DIK_LMENU           0x38    /* left Alt */
+#define DIK_SPACE           0x39
+#define DIK_CAPITAL         0x3A
+#define DIK_F1              0x3B
+#define DIK_F2              0x3C
+#define DIK_F3              0x3D
+#define DIK_F4              0x3E
+#define DIK_F5              0x3F
+#define DIK_F6              0x40
+#define DIK_F7              0x41
+#define DIK_F8              0x42
+#define DIK_F9              0x43
+#define DIK_F10             0x44
+#define DIK_NUMLOCK         0x45
+#define DIK_SCROLL          0x46    /* Scroll Lock */
+#define DIK_NUMPAD7         0x47
+#define DIK_NUMPAD8         0x48
+#define DIK_NUMPAD9         0x49
+#define DIK_SUBTRACT        0x4A    /* - on numeric keypad */
+#define DIK_NUMPAD4         0x4B
+#define DIK_NUMPAD5         0x4C
+#define DIK_NUMPAD6         0x4D
+#define DIK_ADD             0x4E    /* + on numeric keypad */
+#define DIK_NUMPAD1         0x4F
+#define DIK_NUMPAD2         0x50
+#define DIK_NUMPAD3         0x51
+#define DIK_NUMPAD0         0x52
+#define DIK_DECIMAL         0x53    /* . on numeric keypad */
+#define DIK_F11             0x57
+#define DIK_F12             0x58
+
+#define DIK_F13             0x64    /*                     (NEC PC98) */
+#define DIK_F14             0x65    /*                     (NEC PC98) */
+#define DIK_F15             0x66    /*                     (NEC PC98) */
+
+#define DIK_KANA            0x70    /* (Japanese keyboard)            */
+#define DIK_CONVERT         0x79    /* (Japanese keyboard)            */
+#define DIK_NOCONVERT       0x7B    /* (Japanese keyboard)            */
+#define DIK_YEN             0x7D    /* (Japanese keyboard)            */
+#define DIK_NUMPADEQUALS    0x8D    /* = on numeric keypad (NEC PC98) */
+#define DIK_CIRCUMFLEX      0x90    /* (Japanese keyboard)            */
+#define DIK_AT              0x91    /*                     (NEC PC98) */
+#define DIK_COLON           0x92    /*                     (NEC PC98) */
+#define DIK_UNDERLINE       0x93    /*                     (NEC PC98) */
+#define DIK_KANJI           0x94    /* (Japanese keyboard)            */
+#define DIK_STOP            0x95    /*                     (NEC PC98) */
+#define DIK_AX              0x96    /*                     (Japan AX) */
+#define DIK_UNLABELED       0x97    /*                        (J3100) */
+#define DIK_NUMPADENTER     0x9C    /* Enter on numeric keypad */
+#define DIK_RCONTROL        0x9D
+#define DIK_NUMPADCOMMA     0xB3    /* , on numeric keypad (NEC PC98) */
+#define DIK_DIVIDE          0xB5    /* / on numeric keypad */
+#define DIK_SYSRQ           0xB7
+#define DIK_RMENU           0xB8    /* right Alt */
+#define DIK_HOME            0xC7    /* Home on arrow keypad */
+#define DIK_UP              0xC8    /* UpArrow on arrow keypad */
+#define DIK_PRIOR           0xC9    /* PgUp on arrow keypad */
+#define DIK_LEFT            0xCB    /* LeftArrow on arrow keypad */
+#define DIK_RIGHT           0xCD    /* RightArrow on arrow keypad */
+#define DIK_END             0xCF    /* End on arrow keypad */
+#define DIK_DOWN            0xD0    /* DownArrow on arrow keypad */
+#define DIK_NEXT            0xD1    /* PgDn on arrow keypad */
+#define DIK_INSERT          0xD2    /* Insert on arrow keypad */
+#define DIK_DELETE          0xD3    /* Delete on arrow keypad */
+#define DIK_LWIN            0xDB    /* Left Windows key */
+#define DIK_RWIN            0xDC    /* Right Windows key */
+#define DIK_APPS            0xDD    /* AppMenu key */
+
+/*
+ *  Alternate names for keys, to facilitate transition from DOS.
+ */
+#define DIK_BACKSPACE       DIK_BACK            /* backspace */
+#define DIK_NUMPADSTAR      DIK_MULTIPLY        /* * on numeric keypad */
+#define DIK_LALT            DIK_LMENU           /* left Alt */
+#define DIK_CAPSLOCK        DIK_CAPITAL         /* CapsLock */
+#define DIK_NUMPADMINUS     DIK_SUBTRACT        /* - on numeric keypad */
+#define DIK_NUMPADPLUS      DIK_ADD             /* + on numeric keypad */
+#define DIK_NUMPADPERIOD    DIK_DECIMAL         /* . on numeric keypad */
+#define DIK_NUMPADSLASH     DIK_DIVIDE          /* / on numeric keypad */
+#define DIK_RALT            DIK_RMENU           /* right Alt */
+#define DIK_UPARROW         DIK_UP              /* UpArrow on arrow keypad */
+#define DIK_PGUP            DIK_PRIOR           /* PgUp on arrow keypad */
+#define DIK_LEFTARROW       DIK_LEFT            /* LeftArrow on arrow keypad */
+#define DIK_RIGHTARROW      DIK_RIGHT           /* RightArrow on arrow keypad */
+#define DIK_DOWNARROW       DIK_DOWN            /* DownArrow on arrow keypad */
+#define DIK_PGDN            DIK_NEXT            /* PgDn on arrow keypad */
+
+/****************************************************************************
+ *
+ *  IDirectInput
+ *
+ ****************************************************************************/
+
+#define DIENUM_STOP             0
+#define DIENUM_CONTINUE         1
+
+typedef BOOL (FAR PASCAL * LPDIENUMDEVICESCALLBACKA)(LPCDIDEVICEINSTANCEA, LPVOID);
+typedef BOOL (FAR PASCAL * LPDIENUMDEVICESCALLBACKW)(LPCDIDEVICEINSTANCEW, LPVOID);
+#ifdef UNICODE
+#define LPDIENUMDEVICESCALLBACK  LPDIENUMDEVICESCALLBACKW
+#else
+#define LPDIENUMDEVICESCALLBACK  LPDIENUMDEVICESCALLBACKA
+#endif // !UNICODE
+
+#define DIEDFL_ALLDEVICES       0x00000000
+#define DIEDFL_ATTACHEDONLY     0x00000001
+
+#undef INTERFACE
+#define INTERFACE IDirectInputW
+
+DECLARE_INTERFACE_(IDirectInputW, IUnknown)
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;
+
+    /*** IDirectInputW methods ***/
+    STDMETHOD(CreateDevice)(THIS_ REFGUID,LPDIRECTINPUTDEVICEW *,LPUNKNOWN) PURE;
+    STDMETHOD(EnumDevices)(THIS_ DWORD,LPDIENUMDEVICESCALLBACKW,LPVOID,DWORD) PURE;
+    STDMETHOD(GetDeviceStatus)(THIS_ REFGUID) PURE;
+    STDMETHOD(RunControlPanel)(THIS_ HWND,DWORD) PURE;
+    STDMETHOD(Initialize)(THIS_ HINSTANCE,DWORD) PURE;
+};
+
+typedef struct IDirectInputW *LPDIRECTINPUTW;
+
+#undef INTERFACE
+#define INTERFACE IDirectInputA
+
+DECLARE_INTERFACE_(IDirectInputA, IUnknown)
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;
+
+    /*** IDirectInputA methods ***/
+    STDMETHOD(CreateDevice)(THIS_ REFGUID,LPDIRECTINPUTDEVICEA *,LPUNKNOWN) PURE;
+    STDMETHOD(EnumDevices)(THIS_ DWORD,LPDIENUMDEVICESCALLBACKA,LPVOID,DWORD) PURE;
+    STDMETHOD(GetDeviceStatus)(THIS_ REFGUID) PURE;
+    STDMETHOD(RunControlPanel)(THIS_ HWND,DWORD) PURE;
+    STDMETHOD(Initialize)(THIS_ HINSTANCE,DWORD) PURE;
+};
+
+typedef struct IDirectInputA *LPDIRECTINPUTA;
+
+#ifdef UNICODE
+#define IID_IDirectInput IID_IDirectInputW
+#define IDirectInput IDirectInputW
+#define IDirectInputVtbl IDirectInputWVtbl
+#else
+#define IID_IDirectInput IID_IDirectInputA
+#define IDirectInput IDirectInputA
+#define IDirectInputVtbl IDirectInputAVtbl
+#endif
+typedef struct IDirectInput *LPDIRECTINPUT;
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirectInput_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b)
+#define IDirectInput_AddRef(p) (p)->lpVtbl->AddRef(p)
+#define IDirectInput_Release(p) (p)->lpVtbl->Release(p)
+#define IDirectInput_CreateDevice(p,a,b,c) (p)->lpVtbl->CreateDevice(p,a,b,c)
+#define IDirectInput_EnumDevices(p,a,b,c,d) (p)->lpVtbl->EnumDevices(p,a,b,c,d)
+#define IDirectInput_GetDeviceStatus(p,a) (p)->lpVtbl->GetDeviceStatus(p,a)
+#define IDirectInput_RunControlPanel(p,a,b) (p)->lpVtbl->RunControlPanel(p,a,b)
+#define IDirectInput_Initialize(p,a,b) (p)->lpVtbl->Initialize(p,a,b)
+#endif
+
+extern HRESULT WINAPI DirectInputCreateA(HINSTANCE hinst, DWORD dwVersion, LPDIRECTINPUTA *ppDI, LPUNKNOWN punkOuter);
+extern HRESULT WINAPI DirectInputCreateW(HINSTANCE hinst, DWORD dwVersion, LPDIRECTINPUTW *ppDI, LPUNKNOWN punkOuter);
+#ifdef UNICODE
+#define DirectInputCreate  DirectInputCreateW
+#else
+#define DirectInputCreate  DirectInputCreateA
+#endif // !UNICODE
+
+/****************************************************************************
+ *
+ *  Return Codes
+ *
+ ****************************************************************************/
+
+/*
+ *  The operation completed successfully.
+ */
+#define DI_OK                           S_OK
+
+/*
+ *  The device exists but is not currently attached.
+ */
+#define DI_NOTATTACHED                  S_FALSE
+
+/*
+ *  The device buffer overflowed; some input was lost.
+ */
+#define DI_BUFFEROVERFLOW               S_FALSE
+
+/*
+ *  The change in device properties had no effect.
+ */
+#define DI_PROPNOEFFECT                 S_FALSE
+
+/*
+ *  The device is a polled device.  As a result, device buffering
+ *  will not collect any data and event notifications will not be
+ *  signalled until GetDeviceState is called.
+ */
+#define DI_POLLEDDEVICE                 ((HRESULT)0x00000002L)
+
+/*
+ *  The application requires a newer version of DirectInput.
+ */
+#define DIERR_OLDDIRECTINPUTVERSION     \
+    MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_OLD_WIN_VERSION)
+
+/*
+ *  The application was written for an unsupported prerelease version
+ *  of DirectInput.
+ */
+#define DIERR_BETADIRECTINPUTVERSION    \
+    MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_RMODE_APP)
+
+/*
+ *  The object could not be created due to an incompatible driver version
+ *  or mismatched or incomplete driver components.
+ */
+#define DIERR_BADDRIVERVER              \
+    MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_BAD_DRIVER_LEVEL)
+
+/*
+ * The device or device instance is not registered with DirectInput.
+ */
+#define DIERR_DEVICENOTREG              REGDB_E_CLASSNOTREG
+
+/*
+ * The requested object does not exist.
+ */
+#define DIERR_OBJECTNOTFOUND            \
+    MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_FILE_NOT_FOUND)
+
+/*
+ * An invalid parameter was passed to the returning function,
+ * or the object was not in a state that admitted the function
+ * to be called.
+ */
+#define DIERR_INVALIDPARAM              E_INVALIDARG
+
+/*
+ * The specified interface is not supported by the object
+ */
+#define DIERR_NOINTERFACE               E_NOINTERFACE
+
+/*
+ * An undetermined error occured inside the DInput subsystem
+ */
+#define DIERR_GENERIC                   E_FAIL
+
+/*
+ * The DInput subsystem couldn't allocate sufficient memory to complete the
+ * caller's request.
+ */
+#define DIERR_OUTOFMEMORY               E_OUTOFMEMORY
+
+/*
+ * The function called is not supported at this time
+ */
+#define DIERR_UNSUPPORTED               E_NOTIMPL
+
+/*
+ * This object has not been initialized
+ */
+#define DIERR_NOTINITIALIZED            \
+    MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_NOT_READY)
+
+/*
+ * This object is already initialized
+ */
+#define DIERR_ALREADYINITIALIZED        \
+    MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_ALREADY_INITIALIZED)
+
+/*
+ * This object does not support aggregation
+ */
+#define DIERR_NOAGGREGATION             CLASS_E_NOAGGREGATION
+
+/*
+ * Another app has a higher priority level, preventing this call from
+ * succeeding.
+ */
+#define DIERR_OTHERAPPHASPRIO           E_ACCESSDENIED
+
+/*
+ * Access to the input device has been lost.  It must be re-acquired.
+ */
+#define DIERR_INPUTLOST                 \
+    MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_READ_FAULT)
+
+/*
+ * The operation cannot be performed while the device is acquired.
+ */
+#define DIERR_ACQUIRED                  \
+    MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_BUSY)
+
+/*
+ * The operation cannot be performed unless the device is acquired.
+ */
+#define DIERR_NOTACQUIRED               \
+    MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_INVALID_ACCESS)
+
+/*
+ * The specified property cannot be changed.
+ */
+#define DIERR_READONLY                  E_ACCESSDENIED
+
+/*
+ * The device already has an event notification associated with it.
+ */
+#define DIERR_HANDLEEXISTS              E_ACCESSDENIED
+
+/*
+ * Data is not yet available.
+ */
+#ifndef E_PENDING
+#define E_PENDING                       0x80070007L
+#endif
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif  /* __DINPUT_INCLUDED__ */
+
+/****************************************************************************
+ *
+ *  Definitions for non-IDirectInput (VJoyD) features defined more recently
+ *  than the current sdk files
+ *
+ ****************************************************************************/
+
+#ifdef _INC_MMSYSTEM
+#ifndef MMNOJOY
+
+#ifndef __VJOYDX_INCLUDED__
+#define __VJOYDX_INCLUDED__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Flag to indicate that the dwReserved2 field of the JOYINFOEX structure
+ * contains mini-driver specific data to be passed by VJoyD to the mini-
+ * driver instead of doing a poll.
+ */
+#define JOY_PASSDRIVERDATA          0x10000000l
+
+/*
+ * Informs the joystick driver that the configuration has been changed
+ * and should be reloaded from the registery.
+ * dwFlags is reserved and should be set to zero
+ */
+WINMMAPI MMRESULT WINAPI joyConfigChanged( DWORD dwFlags );
+
+/*
+ * Hardware Setting indicating that the device is a headtracker
+ */
+#define JOY_HWS_ISHEADTRACKER       0x02000000l
+
+/*
+ * Hardware Setting indicating that the VxD is used to replace
+ * the standard analog polling
+ */
+#define JOY_HWS_ISGAMEPORTDRIVER    0x04000000l
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif  /* __VJOYDX_INCLUDED__ */
+
+#endif  /* not MMNOJOY */
+#endif  /* _INC_MMSYSTEM */
+
+/****************************************************************************
+ *
+ *  Definitions for non-IDirectInput (VJoyD) features defined more recently
+ *  than the current ddk files
+ *
+ ****************************************************************************/
+
+#ifdef _INC_MMDDK
+#ifndef MMNOJOYDEV
+
+#ifndef __VJOYDXD_INCLUDED__
+#define __VJOYDXD_INCLUDED__
+/*
+ * Poll type in which the do_other field of the JOYOEMPOLLDATA
+ * structure contains mini-driver specific data passed from an app.
+ */
+#define JOY_OEMPOLL_PASSDRIVERDATA  7
+
+#endif  /* __VJOYDXD_INCLUDED__ */
+
+#endif  /* not MMNOJOYDEV */
+#endif  /* _INC_MMDDK */
--- /dev/null
+++ b/WinQuake/dxsdk/SDK/INC/DPLAY.H
@@ -1,0 +1,308 @@
+/*==========================================================================;
+ *
+ *  Copyright (C) 1994-1995 Microsoft Corporation.  All Rights Reserved.
+ *
+ *  File:       dplay.h
+ *  Content:    DirectPlay include file
+ *
+ ***************************************************************************/
+
+#ifndef __DPLAY_INCLUDED__
+#define __DPLAY_INCLUDED__
+#ifdef _WIN32
+/* for DECLARE_INTERFACE and HRESULT. */
+#include <ole2.h>
+#endif
+
+#define _FACDP  0x877
+#define MAKE_DPHRESULT( code )    MAKE_HRESULT( 1, _FACDP, code )
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#pragma pack(push, 1)
+
+
+/*============================================================================
+ *
+ * DirectPlay Structures
+ *
+ * Various structures used to invoke DirectPlay.
+ *
+ *==========================================================================*/
+
+#ifdef __cplusplus
+/* 'struct' not 'class' per the way DECLARE_INTERFACE_ is defined */
+struct IDirectPlay;
+typedef struct IDirectPlay        FAR *LPDIRECTPLAY;
+#else                  
+typedef struct IDirectPlay        FAR *LPDIRECTPLAY;
+#endif
+
+typedef DWORD DPID, FAR *LPDPID;
+
+typedef struct _DPCAPS
+{
+    DWORD   dwSize;
+    DWORD   dwFlags;
+    DWORD   dwMaxBufferSize;
+    DWORD   dwMaxQueueSize;             // Function of DPlay, not SP.
+    DWORD   dwMaxPlayers;
+    DWORD   dwHundredBaud;              // 24 is 2400, 96 is 9600, etc.
+    DWORD   dwLatency;
+} DPCAPS;
+
+typedef DPCAPS        FAR *LPDPCAPS;
+
+#define DPLONGNAMELEN           52
+#define DPSHORTNAMELEN          20
+#define DPSESSIONNAMELEN        32
+#define DPPASSWORDLEN           16
+#define DPUSERRESERVED          16
+
+typedef struct
+{
+    DWORD   dwSize;
+    GUID    guidSession;                  // Id for Game.  Null is all games.
+    DWORD   dwSession;                    // session identifier
+    DWORD   dwMaxPlayers;                 // Maximum players allowed in game.
+    DWORD   dwCurrentPlayers;             // Current  players in Game.
+    DWORD   dwFlags;                      // DPOPEN_* flags
+    char    szSessionName[DPSESSIONNAMELEN];// Human readable name for Game
+    char    szUserField[DPUSERRESERVED];
+    DWORD   dwReserved1;                  // Reserved for future MS use.
+    char    szPassword[DPPASSWORDLEN];    // Password to be allowed into game.
+    DWORD   dwReserved2;                  // Reserved for future MS use. 
+    DWORD   dwUser1;
+    DWORD   dwUser2;
+    DWORD   dwUser3;
+    DWORD   dwUser4;
+} DPSESSIONDESC;
+typedef DPSESSIONDESC FAR *LPDPSESSIONDESC;
+
+
+/*
+ * Create API
+ */
+typedef BOOL (FAR PASCAL * LPDPENUMDPCALLBACK)(
+    LPGUID              lpSPGuid,
+    LPSTR               lpFriendlyName,
+    DWORD               dwMajorVersion,
+    DWORD               dwMinorVersion,
+    LPVOID              lpContext);
+
+typedef BOOL (FAR PASCAL * LPDPENUMSESSIONSCALLBACK)(
+    LPDPSESSIONDESC     lpDPSGameDesc,
+    LPVOID              lpContext,
+    LPDWORD             lpdwTimeOut,
+    DWORD               dwFlags);
+
+
+
+extern HRESULT WINAPI DirectPlayCreate( LPGUID lpGUID, LPDIRECTPLAY FAR *lplpDP, IUnknown FAR *pUnk);
+extern HRESULT WINAPI DirectPlayEnumerate( LPDPENUMDPCALLBACK, LPVOID );
+
+
+/* Player enumeration callback prototype */
+typedef BOOL (FAR PASCAL *LPDPENUMPLAYERSCALLBACK)(
+    DPID    dpId,
+    LPSTR   lpFriendlyName,
+    LPSTR   lpFormalName,
+    DWORD   dwFlags,
+    LPVOID  lpContext );
+
+/*
+ * IDirectPlay
+ */
+#undef INTERFACE
+#define INTERFACE IDirectPlay
+#ifdef _WIN32
+DECLARE_INTERFACE_( IDirectPlay, IUnknown )
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface)       (THIS_ REFIID riid, LPVOID * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef)        (THIS)  PURE;
+    STDMETHOD_(ULONG,Release)       (THIS) PURE;
+    /*** IDirectPlay methods ***/
+    STDMETHOD(AddPlayerToGroup)     (THIS_ DPID, DPID) PURE;
+    STDMETHOD(Close)                (THIS) PURE;
+    STDMETHOD(CreatePlayer)         (THIS_ LPDPID,LPSTR,LPSTR,LPHANDLE) PURE;
+    STDMETHOD(CreateGroup)          (THIS_ LPDPID,LPSTR,LPSTR) PURE;
+    STDMETHOD(DeletePlayerFromGroup)(THIS_ DPID,DPID) PURE;
+    STDMETHOD(DestroyPlayer)        (THIS_ DPID) PURE;
+    STDMETHOD(DestroyGroup)         (THIS_ DPID) PURE;
+    STDMETHOD(EnableNewPlayers)     (THIS_ BOOL) PURE;
+    STDMETHOD(EnumGroupPlayers)     (THIS_ DPID, LPDPENUMPLAYERSCALLBACK,LPVOID,DWORD) PURE;
+    STDMETHOD(EnumGroups)           (THIS_ DWORD, LPDPENUMPLAYERSCALLBACK,LPVOID,DWORD) PURE;
+    STDMETHOD(EnumPlayers)          (THIS_ DWORD, LPDPENUMPLAYERSCALLBACK,LPVOID,DWORD) PURE;
+    STDMETHOD(EnumSessions)         (THIS_ LPDPSESSIONDESC,DWORD,LPDPENUMSESSIONSCALLBACK,LPVOID,DWORD) PURE;
+    STDMETHOD(GetCaps)              (THIS_ LPDPCAPS) PURE;
+    STDMETHOD(GetMessageCount)      (THIS_ DPID, LPDWORD) PURE;
+    STDMETHOD(GetPlayerCaps)        (THIS_ DPID, LPDPCAPS) PURE;
+    STDMETHOD(GetPlayerName)        (THIS_ DPID,LPSTR,LPDWORD,LPSTR,LPDWORD) PURE;
+    STDMETHOD(Initialize)           (THIS_ LPGUID) PURE;
+    STDMETHOD(Open)                 (THIS_ LPDPSESSIONDESC) PURE;
+    STDMETHOD(Receive)              (THIS_ LPDPID,LPDPID,DWORD,LPVOID,LPDWORD) PURE;
+    STDMETHOD(SaveSession)          (THIS_ LPSTR) PURE;
+    STDMETHOD(Send)                 (THIS_ DPID, DPID, DWORD, LPVOID, DWORD) PURE;
+    STDMETHOD(SetPlayerName)        (THIS_ DPID,LPSTR,LPSTR) PURE;
+};
+#endif
+
+
+
+
+/****************************************************************************
+ *
+ * DIRECTPLAY ERRORS
+ *
+ * Errors are represented by negative values and cannot be combined.
+ *
+ ****************************************************************************/
+#define DP_OK                           0
+#define DPERR_ALREADYINITIALIZED        MAKE_DPHRESULT(   5 )
+#define DPERR_ACCESSDENIED              MAKE_DPHRESULT(  10 )
+#define DPERR_ACTIVEPLAYERS             MAKE_DPHRESULT(  20 )
+#define DPERR_BUFFERTOOSMALL            MAKE_DPHRESULT(  30 )
+#define DPERR_CANTADDPLAYER             MAKE_DPHRESULT(  40 )
+#define DPERR_CANTCREATEGROUP           MAKE_DPHRESULT(  50 )
+#define DPERR_CANTCREATEPLAYER          MAKE_DPHRESULT(  60 )
+#define DPERR_CANTCREATESESSION         MAKE_DPHRESULT(  70 )
+#define DPERR_CAPSNOTAVAILABLEYET       MAKE_DPHRESULT(  80 )
+#define DPERR_EXCEPTION                 MAKE_DPHRESULT(  90 )
+#define DPERR_GENERIC                   E_FAIL
+
+#define DPERR_INVALIDFLAGS              MAKE_DPHRESULT( 120 )
+#define DPERR_INVALIDOBJECT             MAKE_DPHRESULT( 130 )
+#define DPERR_INVALIDPARAM              E_INVALIDARG
+#define DPERR_INVALIDPARAMS             DPERR_INVALIDPARAM
+#define DPERR_INVALIDPLAYER             MAKE_DPHRESULT( 150 )
+#define DPERR_NOCAPS                    MAKE_DPHRESULT( 160 )
+#define DPERR_NOCONNECTION              MAKE_DPHRESULT( 170 )
+#define DPERR_NOMEMORY                  E_OUTOFMEMORY
+#define DPERR_OUTOFMEMORY               DPERR_NOMEMORY
+#define DPERR_NOMESSAGES                MAKE_DPHRESULT( 190 )
+#define DPERR_NONAMESERVERFOUND         MAKE_DPHRESULT( 200 )
+#define DPERR_NOPLAYERS                 MAKE_DPHRESULT( 210 )
+#define DPERR_NOSESSIONS                MAKE_DPHRESULT( 220 )
+#define DPERR_SENDTOOBIG                MAKE_DPHRESULT( 230 )
+#define DPERR_TIMEOUT                   MAKE_DPHRESULT( 240 )
+#define DPERR_UNAVAILABLE               MAKE_DPHRESULT( 250 )
+#define DPERR_UNSUPPORTED               E_NOTIMPL
+#define DPERR_BUSY                      MAKE_DPHRESULT( 270 )
+#define DPERR_USERCANCEL                MAKE_DPHRESULT( 280 ) 
+
+
+#define DPOPEN_OPENSESSION          0x00000001
+#define DPOPEN_CREATESESSION        0x00000002
+
+#define DPSEND_GUARANTEE            0x00000001
+#define DPSEND_HIGHPRIORITY         0x00000002
+#define DPSEND_TRYONCE              0x00000004
+
+#define DPRECEIVE_ALL               0x00000001
+#define DPRECEIVE_TOPLAYER          0x00000002
+#define DPRECEIVE_FROMPLAYER        0x00000004
+#define DPRECEIVE_PEEK              0x00000008
+
+#define DPCAPS_NAMESERVICE          0x00000001 // A name server is supported.
+#define DPCAPS_NAMESERVER           0x00000002 // You are the name server.
+#define DPCAPS_GUARANTEED           0x00000004 // SP's don't have to implement guarantees.
+
+#define DPENUMSESSIONS_AVAILABLE    0x00000001 // All games that match password (if given)
+                                               // and have openings.
+#define DPENUMSESSIONS_ALL          0x00000002
+#define DPENUMSESSIONS_PREVIOUS     0x00000004
+
+#define DPENUMPLAYERS_ALL           0x00000000
+#define DPENUMPLAYERS_PREVIOUS      0x00000004
+#define DPENUMPLAYERS_LOCAL         0x00000008
+#define DPENUMPLAYERS_REMOTE        0x00000010
+#define DPENUMPLAYERS_GROUP         0x00000020
+#define DPENUMPLAYERS_SESSION       0x00000080
+
+//
+// This flag is set on the enumsessions callback when the time out has occured.
+// This means that there is no session data for this callback.
+// If lpdwTimeOut is set to a non-zero value and the EnumSessionsCallback returns
+// TRUE then EnumSessions will continue until the next timeout occurs.
+// Timeouts are in milliseconds.
+ 
+#define DPESC_TIMEDOUT              0x00000001
+
+
+//
+// System message structures and types.
+//
+// System messages have a leading 4 byte type code to identify the message.
+// an app knows it is a system message because it is addressed 'To' player 0.
+//
+
+                                    
+#define DPSYS_ADDPLAYER               0x0003  // DPMSG_ADDPLAYER
+#define DPSYS_DELETEPLAYER            0x0005  // DPMSG_DELETEPLAYER
+
+#define DPSYS_ADDPLAYERTOGROUP        0x0007  // DPMSG_GROUPADD
+
+#define DPSYS_INVITE                  0x000e  // DPMSG_INVITE, Net only.
+
+#define DPSYS_DELETEGROUP             0x0020  // DPMSG_DELETEPLAYER
+#define DPSYS_DELETEPLAYERFROMGRP     0x0021  // DPMSG_GROUPDELETE
+#define DPSYS_SESSIONLOST             0x0031
+
+#define DPSYS_CONNECT                 0x484b  // DPMSG_GENERIC
+
+
+
+typedef struct
+{
+    DWORD       dwType;
+    DWORD       dwPlayerType;
+    DPID        dpId;
+    char        szLongName[DPLONGNAMELEN];
+    char        szShortName[DPSHORTNAMELEN];
+    DWORD       dwCurrentPlayers;
+}   DPMSG_ADDPLAYER;
+
+typedef DPMSG_ADDPLAYER DPMSG_ADDGROUP;
+
+typedef struct
+{
+    DWORD       dwType;
+    DPID        dpIdGroup;
+    DPID        dpIdPlayer;
+} DPMSG_GROUPADD;
+
+typedef DPMSG_GROUPADD DPMSG_GROUPDELETE;
+typedef struct
+{
+    DWORD       dwType;
+    DPID        dpId;
+} DPMSG_DELETEPLAYER;
+
+typedef struct
+{
+    DWORD           dwType;
+    DPSESSIONDESC   dpsDesc;
+} DPMSG_INVITE;
+
+
+
+typedef struct
+{
+    DWORD           dwType;
+} DPMSG_GENERIC;
+
+#pragma pack(pop)
+
+
+DEFINE_GUID( IID_IDirectPlay, 0x5454e9a0, 0xdb65, 0x11ce, 0x92, 0x1c, 0x00, 0xaa, 0x00, 0x6c, 0x49, 0x72);
+
+
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif
--- /dev/null
+++ b/WinQuake/dxsdk/SDK/INC/DSETUP.H
@@ -1,0 +1,66 @@
+/*==========================================================================
+ *
+ *  Copyright (C) 1995-1996 Microsoft Corporation.  All Rights Reserved.
+ *
+ *  File:       dsetup.h
+ *  Content:    DirectXSetup, error codes and flags
+ ***************************************************************************/
+
+#ifndef __DSETUP_H__
+#define __DSETUP_H__
+
+#ifdef _WIN32
+#define COM_NO_WINDOWS_H
+#include <objbase.h>
+#else
+#define GUID void
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define DSETUPERR_BADWINDOWSVERSION     -1
+#define DSETUPERR_SOURCEFILENOTFOUND    -2
+#define DSETUPERR_BADSOURCESIZE         -3
+#define DSETUPERR_BADSOURCETIME         -4
+#define DSETUPERR_NOCOPY                -5
+#define DSETUPERR_OUTOFDISKSPACE        -6
+#define DSETUPERR_CANTFINDINF           -7
+#define DSETUPERR_CANTFINDDIR           -8
+#define DSETUPERR_INTERNAL              -9
+#define DSETUPERR_NTWITHNO3D            -10
+
+
+#define MAX_INFLINE             (16*1024)
+#define MAX_DESCRIPTION         256
+
+#define DSETUP_DDRAW            0x00000001      /* install DirectDraw           */
+#define DSETUP_DSOUND           0x00000002      /* install DirectSound          */
+#define DSETUP_DPLAY            0x00000004      /* install DirectPlay           */
+#define DSETUP_DDRAWDRV         0x00000008      /* install DirectDraw Drivers   */
+#define DSETUP_DSOUNDDRV        0x00000010      /* install DirectSound Drivers  */
+#define DSETUP_DPLAYSP          0x00000020      /* install DirectPlay Providers */
+#define DSETUP_DVIDEO           0x00000040      /* install DirectVideo          */
+#define DSETUP_REINSTALL        0x00000080      /* install DirectX even if existing components have the same version    */
+#define DSETUP_DRVINFONLY       0x00000100      /* install DirectX inf files but not drivers                            */
+#define DSETUP_D3D              0x00000200      /* install Direct3D                                                     */
+#define DSETUP_REQUIRESD3D      0x00000400 | DSETUP_D3D /* install Direct3D, pop up dialog box on NT, if no D3D present         */
+
+#define DSETUP_DIRECTX          (DSETUP_D3D | DSETUP_DDRAW | DSETUP_DSOUND | DSETUP_DPLAY | DSETUP_DDRAWDRV | DSETUP_DSOUNDDRV | DSETUP_DPLAYSP)
+
+int WINAPI DirectXSetup( HWND hwnd, LPSTR root_path, DWORD flags );
+int WINAPI DirectXDeviceDriverSetup( HWND hwnd, LPSTR driver_class, LPSTR inf_path, LPSTR driver_path, DWORD flags );
+int WINAPI DirectXSetupIsJapan( void );
+int WINAPI DirectXSetupIsJapanNec( void );
+
+typedef int (WINAPI * LPDIRECTXSETUP)( HWND, LPSTR, DWORD );
+typedef int (WINAPI * LPDIRECTXDEVICEDRIVERSETUP)( HWND, LPSTR, LPSTR, LPSTR, DWORD );
+typedef int (WINAPI * LPDIRECTXSETUPISJAPAN)( void );
+typedef int (WINAPI * LPDIRECTXSETUPISJAPANNEC)( void );
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif
--- /dev/null
+++ b/WinQuake/dxsdk/SDK/INC/DSOUND.H
@@ -1,0 +1,366 @@
+/*==========================================================================;
+ *
+ *  Copyright (C) 1995,1996 Microsoft Corporation.  All Rights Reserved.
+ *
+ *  File:       dsound.h
+ *  Content:    DirectSound include file
+ *
+ ***************************************************************************/
+
+#ifndef __DSOUND_INCLUDED__
+#define __DSOUND_INCLUDED__
+
+#ifdef _WIN32
+#define COM_NO_WINDOWS_H
+#include <objbase.h>
+#endif
+
+#define _FACDS  0x878
+#define MAKE_DSHRESULT( code )  MAKE_HRESULT( 1, _FACDS, code )
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Direct Sound Component GUID    {47D4D946-62E8-11cf-93BC-444553540000}
+DEFINE_GUID(CLSID_DirectSound,
+0x47d4d946, 0x62e8, 0x11cf, 0x93, 0xbc, 0x44, 0x45, 0x53, 0x54, 0x0, 0x0);
+
+// DirectSound 279afa83-4981-11ce-a521-0020af0be560
+DEFINE_GUID(IID_IDirectSound,0x279AFA83,0x4981,0x11CE,0xA5,0x21,0x00,0x20,0xAF,0x0B,0xE5,0x60);
+// DirectSoundBuffer 279afa85-4981-11ce-a521-0020af0be560
+DEFINE_GUID(IID_IDirectSoundBuffer,0x279AFA85,0x4981,0x11CE,0xA5,0x21,0x00,0x20,0xAF,0x0B,0xE5,0x60);
+
+
+
+//==========================================================================;
+//
+//                            Structures...
+//
+//==========================================================================;
+#ifdef __cplusplus
+/* 'struct' not 'class' per the way DECLARE_INTERFACE_ is defined */
+struct IDirectSound;
+struct IDirectSoundBuffer;
+#endif
+
+typedef struct IDirectSound           *LPDIRECTSOUND;        
+typedef struct IDirectSoundBuffer     *LPDIRECTSOUNDBUFFER;  
+typedef struct IDirectSoundBuffer    **LPLPDIRECTSOUNDBUFFER;  
+
+
+typedef struct _DSCAPS
+{
+    DWORD       dwSize;
+    DWORD       dwFlags;
+    DWORD       dwMinSecondarySampleRate;
+    DWORD       dwMaxSecondarySampleRate;
+    DWORD       dwPrimaryBuffers;
+    DWORD       dwMaxHwMixingAllBuffers;
+    DWORD       dwMaxHwMixingStaticBuffers;
+    DWORD       dwMaxHwMixingStreamingBuffers;
+    DWORD       dwFreeHwMixingAllBuffers;
+    DWORD       dwFreeHwMixingStaticBuffers;
+    DWORD       dwFreeHwMixingStreamingBuffers;
+    DWORD       dwMaxHw3DAllBuffers;
+    DWORD       dwMaxHw3DStaticBuffers;
+    DWORD       dwMaxHw3DStreamingBuffers;
+    DWORD       dwFreeHw3DAllBuffers;
+    DWORD       dwFreeHw3DStaticBuffers;
+    DWORD       dwFreeHw3DStreamingBuffers;
+    DWORD       dwTotalHwMemBytes;
+    DWORD       dwFreeHwMemBytes;
+    DWORD       dwMaxContigFreeHwMemBytes;
+    DWORD       dwUnlockTransferRateHwBuffers;
+    DWORD       dwPlayCpuOverheadSwBuffers;
+    DWORD       dwReserved1;
+    DWORD       dwReserved2;
+} DSCAPS, *LPDSCAPS;
+
+typedef struct _DSBCAPS
+{
+    
+    DWORD       dwSize;
+    DWORD       dwFlags;
+    DWORD       dwBufferBytes;
+    DWORD       dwUnlockTransferRate;
+    DWORD       dwPlayCpuOverhead;
+} DSBCAPS, *LPDSBCAPS;
+
+typedef struct _DSBUFFERDESC
+{
+    DWORD                   dwSize;
+    DWORD                   dwFlags;
+    DWORD                   dwBufferBytes;
+    DWORD                   dwReserved;
+    LPWAVEFORMATEX          lpwfxFormat;
+} DSBUFFERDESC, *LPDSBUFFERDESC;
+
+
+
+typedef LPVOID* LPLPVOID;
+
+
+typedef BOOL (FAR PASCAL * LPDSENUMCALLBACKW)(GUID FAR *, LPWSTR, LPWSTR, LPVOID);
+typedef BOOL (FAR PASCAL * LPDSENUMCALLBACKA)(GUID FAR *, LPSTR, LPSTR, LPVOID);
+
+extern HRESULT WINAPI DirectSoundCreate(GUID FAR * lpGUID, LPDIRECTSOUND * ppDS, IUnknown FAR *pUnkOuter );
+extern HRESULT WINAPI DirectSoundEnumerateW(LPDSENUMCALLBACKW lpCallback, LPVOID lpContext );
+extern HRESULT WINAPI DirectSoundEnumerateA(LPDSENUMCALLBACKA lpCallback, LPVOID lpContext );
+
+#ifdef UNICODE
+#define LPDSENUMCALLBACK        LPDSENUMCALLBACKW
+#define DirectSoundEnumerate    DirectSoundEnumerateW
+#else
+#define LPDSENUMCALLBACK        LPDSENUMCALLBACKA
+#define DirectSoundEnumerate    DirectSoundEnumerateA
+#endif
+
+//
+// IDirectSound
+//
+#undef INTERFACE
+#define INTERFACE IDirectSound
+#ifdef _WIN32
+DECLARE_INTERFACE_( IDirectSound, IUnknown )
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef) (THIS)  PURE;
+    STDMETHOD_(ULONG,Release) (THIS) PURE;
+    /*** IDirectSound methods ***/
+
+    STDMETHOD( CreateSoundBuffer)(THIS_ LPDSBUFFERDESC, LPLPDIRECTSOUNDBUFFER, IUnknown FAR *) PURE;
+    STDMETHOD( GetCaps)(THIS_ LPDSCAPS ) PURE;
+    STDMETHOD( DuplicateSoundBuffer)(THIS_ LPDIRECTSOUNDBUFFER, LPLPDIRECTSOUNDBUFFER ) PURE;
+    STDMETHOD( SetCooperativeLevel)(THIS_ HWND, DWORD ) PURE;
+    STDMETHOD( Compact)(THIS ) PURE;
+    STDMETHOD( GetSpeakerConfig)(THIS_ LPDWORD ) PURE;
+    STDMETHOD( SetSpeakerConfig)(THIS_ DWORD ) PURE;
+    STDMETHOD( Initialize)(THIS_ GUID FAR * ) PURE;
+};
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirectSound_QueryInterface(p,a,b)       (p)->lpVtbl->QueryInterface(p,a,b)
+#define IDirectSound_AddRef(p)                   (p)->lpVtbl->AddRef(p)
+#define IDirectSound_Release(p)                  (p)->lpVtbl->Release(p)
+#define IDirectSound_CreateSoundBuffer(p,a,b,c)  (p)->lpVtbl->CreateSoundBuffer(p,a,b,c)
+#define IDirectSound_GetCaps(p,a)                (p)->lpVtbl->GetCaps(p,a)
+#define IDirectSound_DuplicateSoundBuffer(p,a,b) (p)->lpVtbl->DuplicateSoundBuffer(p,a,b)
+#define IDirectSound_SetCooperativeLevel(p,a,b)  (p)->lpVtbl->SetCooperativeLevel(p,a,b)
+#define IDirectSound_Compact(p)                  (p)->lpVtbl->Compact(p)
+#define IDirectSound_GetSpeakerConfig(p,a)       (p)->lpVtbl->GetSpeakerConfig(p,a)
+#define IDirectSound_SetSpeakerConfig(p,b)       (p)->lpVtbl->SetSpeakerConfig(p,b)
+#define IDirectSound_Initialize(p,a)             (p)->lpVtbl->Initialize(p,a)
+#endif
+
+#endif
+
+//
+// IDirectSoundBuffer
+//
+#undef INTERFACE
+#define INTERFACE IDirectSoundBuffer
+#ifdef _WIN32
+DECLARE_INTERFACE_( IDirectSoundBuffer, IUnknown )
+{
+    /*** IUnknown methods ***/
+    STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef) (THIS)  PURE;
+    STDMETHOD_(ULONG,Release) (THIS) PURE;
+    /*** IDirectSoundBuffer methods ***/
+
+    STDMETHOD(           GetCaps)(THIS_ LPDSBCAPS ) PURE;
+    STDMETHOD(GetCurrentPosition)(THIS_ LPDWORD,LPDWORD ) PURE;
+    STDMETHOD(         GetFormat)(THIS_ LPWAVEFORMATEX, DWORD, LPDWORD ) PURE;
+    STDMETHOD(         GetVolume)(THIS_ LPLONG ) PURE;
+    STDMETHOD(            GetPan)(THIS_ LPLONG ) PURE;
+    STDMETHOD(      GetFrequency)(THIS_ LPDWORD ) PURE;
+    STDMETHOD(         GetStatus)(THIS_ LPDWORD ) PURE;
+    STDMETHOD(        Initialize)(THIS_ LPDIRECTSOUND, LPDSBUFFERDESC ) PURE;
+    STDMETHOD(              Lock)(THIS_ DWORD,DWORD,LPVOID,LPDWORD,LPVOID,LPDWORD,DWORD ) PURE;
+    STDMETHOD(              Play)(THIS_ DWORD,DWORD,DWORD ) PURE;
+    STDMETHOD(SetCurrentPosition)(THIS_ DWORD ) PURE;
+    STDMETHOD(         SetFormat)(THIS_ LPWAVEFORMATEX ) PURE;
+    STDMETHOD(         SetVolume)(THIS_ LONG ) PURE;
+    STDMETHOD(            SetPan)(THIS_ LONG ) PURE;
+    STDMETHOD(      SetFrequency)(THIS_ DWORD ) PURE;
+    STDMETHOD(              Stop)(THIS  ) PURE;
+    STDMETHOD(            Unlock)(THIS_ LPVOID,DWORD,LPVOID,DWORD ) PURE;
+    STDMETHOD(           Restore)(THIS  ) PURE;
+};
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirectSoundBuffer_QueryInterface(p,a,b)        (p)->lpVtbl->QueryInterface(p,a,b)
+#define IDirectSoundBuffer_AddRef(p)                    (p)->lpVtbl->AddRef(p)
+#define IDirectSoundBuffer_Release(p)                   (p)->lpVtbl->Release(p)
+#define IDirectSoundBuffer_GetCaps(p,a)                 (p)->lpVtbl->GetCaps(p,a)
+#define IDirectSoundBuffer_GetCurrentPosition(p,a,b)    (p)->lpVtbl->GetCurrentPosition(p,a,b)
+#define IDirectSoundBuffer_GetFormat(p,a,b,c)           (p)->lpVtbl->GetFormat(p,a,b,c)
+#define IDirectSoundBuffer_GetVolume(p,a)               (p)->lpVtbl->GetVolume(p,a)
+#define IDirectSoundBuffer_GetPan(p,a)                  (p)->lpVtbl->GetPan(p,a)
+#define IDirectSoundBuffer_GetFrequency(p,a)            (p)->lpVtbl->GetFrequency(p,a)
+#define IDirectSoundBuffer_GetStatus(p,a)               (p)->lpVtbl->GetStatus(p,a)
+#define IDirectSoundBuffer_Initialize(p,a,b)            (p)->lpVtbl->Initialize(p,a,b)
+#define IDirectSoundBuffer_Lock(p,a,b,c,d,e,f,g)        (p)->lpVtbl->Lock(p,a,b,c,d,e,f,g)
+#define IDirectSoundBuffer_Play(p,a,b,c)                (p)->lpVtbl->Play(p,a,b,c)
+#define IDirectSoundBuffer_SetCurrentPosition(p,a)      (p)->lpVtbl->SetCurrentPosition(p,a)
+#define IDirectSoundBuffer_SetFormat(p,a)               (p)->lpVtbl->SetFormat(p,a)
+#define IDirectSoundBuffer_SetVolume(p,a)               (p)->lpVtbl->SetVolume(p,a)
+#define IDirectSoundBuffer_SetPan(p,a)                  (p)->lpVtbl->SetPan(p,a)
+#define IDirectSoundBuffer_SetFrequency(p,a)            (p)->lpVtbl->SetFrequency(p,a)
+#define IDirectSoundBuffer_Stop(p)                      (p)->lpVtbl->Stop(p)
+#define IDirectSoundBuffer_Unlock(p,a,b,c,d)            (p)->lpVtbl->Unlock(p,a,b,c,d)
+#define IDirectSoundBuffer_Restore(p)                   (p)->lpVtbl->Restore(p)
+#endif
+
+#endif
+
+
+
+/*
+ * Return Codes
+ */
+
+#define DS_OK                           0
+
+/*
+ * The call failed because resources (such as a priority level)
+ *  were already being used by another caller.
+ */
+#define DSERR_ALLOCATED                 MAKE_DSHRESULT( 10 )
+/*
+ * The control (vol,pan,etc.) requested by the caller is not available.
+ */
+#define DSERR_CONTROLUNAVAIL            MAKE_DSHRESULT( 30 )
+/*
+ * An invalid parameter was passed to the returning function
+ */
+#define DSERR_INVALIDPARAM              E_INVALIDARG
+/*
+ * This call is not valid for the current state of this object
+ */
+#define DSERR_INVALIDCALL               MAKE_DSHRESULT( 50 )
+/*
+ * An undetermined error occured inside the DSound subsystem
+ */
+#define DSERR_GENERIC                   E_FAIL
+/*
+ * The caller does not have the priority level required for the function to
+ * succeed.
+ */
+#define DSERR_PRIOLEVELNEEDED           MAKE_DSHRESULT( 70 )
+/*
+ * The DSound subsystem couldn't allocate sufficient memory to complete the
+ * caller's request.
+ */
+#define DSERR_OUTOFMEMORY               E_OUTOFMEMORY
+/*
+ * The specified WAVE format is not supported
+ */
+#define DSERR_BADFORMAT                 MAKE_DSHRESULT( 100 )
+/*
+ * The function called is not supported at this time
+ */
+#define DSERR_UNSUPPORTED               E_NOTIMPL
+/*
+ * No sound driver is available for use
+ */
+#define DSERR_NODRIVER                  MAKE_DSHRESULT( 120 )
+/*
+ * This object is already initialized
+ */
+#define DSERR_ALREADYINITIALIZED        MAKE_DSHRESULT( 130 )
+/*
+ * This object does not support aggregation
+ */
+#define DSERR_NOAGGREGATION             CLASS_E_NOAGGREGATION
+/*
+ * The buffer memory has been lost, and must be Restored.
+ */
+#define DSERR_BUFFERLOST                MAKE_DSHRESULT( 150 )
+/*
+ * Another app has a higher priority level, preventing this call from
+ * succeeding.
+ */
+#define DSERR_OTHERAPPHASPRIO           MAKE_DSHRESULT( 160 )
+/*
+ * The Initialize() member on the Direct Sound Object has not been
+ * called or called successfully before calls to other members.
+ */
+#define DSERR_UNINITIALIZED             MAKE_DSHRESULT( 170 )
+
+
+
+
+//==========================================================================;
+//
+//                               Flags...
+//
+//==========================================================================;
+
+#define DSCAPS_PRIMARYMONO          0x00000001
+#define DSCAPS_PRIMARYSTEREO        0x00000002
+#define DSCAPS_PRIMARY8BIT          0x00000004
+#define DSCAPS_PRIMARY16BIT         0x00000008
+#define DSCAPS_CONTINUOUSRATE       0x00000010
+#define DSCAPS_EMULDRIVER           0x00000020
+#define DSCAPS_CERTIFIED            0x00000040
+#define DSCAPS_SECONDARYMONO        0x00000100
+#define DSCAPS_SECONDARYSTEREO      0x00000200
+#define DSCAPS_SECONDARY8BIT        0x00000400
+#define DSCAPS_SECONDARY16BIT       0x00000800
+
+
+
+#define DSBPLAY_LOOPING         0x00000001
+
+
+          
+#define DSBSTATUS_PLAYING           0x00000001
+#define DSBSTATUS_BUFFERLOST        0x00000002
+#define DSBSTATUS_LOOPING           0x00000004
+         
+
+#define DSBLOCK_FROMWRITECURSOR         0x00000001
+
+
+
+#define DSSCL_NORMAL                1
+#define DSSCL_PRIORITY              2
+#define DSSCL_EXCLUSIVE             3
+#define DSSCL_WRITEPRIMARY          4
+
+
+
+#define DSBCAPS_PRIMARYBUFFER       0x00000001
+#define DSBCAPS_STATIC              0x00000002
+#define DSBCAPS_LOCHARDWARE         0x00000004
+#define DSBCAPS_LOCSOFTWARE         0x00000008
+#define DSBCAPS_CTRLFREQUENCY       0x00000020
+#define DSBCAPS_CTRLPAN             0x00000040
+#define DSBCAPS_CTRLVOLUME          0x00000080
+#define DSBCAPS_CTRLDEFAULT         0x000000E0  // Pan + volume + frequency.
+#define DSBCAPS_CTRLALL             0x000000E0  // All control capabilities
+#define DSBCAPS_STICKYFOCUS         0x00004000
+#define DSBCAPS_GETCURRENTPOSITION2 0x00010000  // More accurate play cursor under emulation
+
+
+
+
+#define DSSPEAKER_HEADPHONE     1
+#define DSSPEAKER_MONO          2
+#define DSSPEAKER_QUAD          3
+#define DSSPEAKER_STEREO        4
+#define DSSPEAKER_SURROUND      5
+
+
+
+
+
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif  /* __DSOUND_INCLUDED__ */
--- /dev/null
+++ b/WinQuake/dxsdk/SDK/INC/FASTFILE.H
@@ -1,0 +1,24 @@
+/*==========================================================================
+ *
+ *  Copyright (C) 1995-1996 Microsoft Corporation.  All Rights Reserved.
+ *
+ *  File:       fastfile.h
+ *  Content:    Definitions for fastfile access.
+ *
+ * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
+ * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
+ * WARRANTIES OF MERCHANTBILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ ***************************************************************************/
+
+typedef LPVOID  HFASTFILE;
+
+extern BOOL FastFileInit( LPSTR fname, int max_handles );
+extern void FastFileFini( void );
+extern HFASTFILE FastFileOpen( LPSTR name );
+extern BOOL FastFileClose( HFASTFILE pfe );
+extern BOOL FastFileRead( HFASTFILE pfh, LPVOID ptr, int size );
+extern BOOL FastFileSeek( HFASTFILE pfe, int off, int how );
+extern long FastFileTell( HFASTFILE pfe );
+extern LPVOID FastFileLock( HFASTFILE pfe, int off, int len );
+extern BOOL FastFileUnlock( HFASTFILE pfe, int off, int len );
binary files /dev/null b/WinQuake/dxsdk/SDK/LIB/DINPUT.LIB differ
binary files /dev/null b/WinQuake/dxsdk/SDK/LIB/DXGUID.LIB differ
--- /dev/null
+++ b/WinQuake/gas2masm/gas2masm.c
@@ -1,0 +1,1056 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+//
+// gas to MASM source code converter
+//
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define MAX_TOKENS			100
+#define MAX_TOKEN_LENGTH	1024
+#define LF					0x0A
+
+typedef enum {NOT_WHITESPACE, WHITESPACE, TOKEN_AVAILABLE, LINE_DONE, FILE_DONE, PARSED_OKAY} tokenstat;
+typedef enum {NOSEG, DATASEG, TEXTSEG} segtype;
+
+int		tokennum;
+int		inline, outline;
+
+char	*token;
+char	tokens[MAX_TOKENS][MAX_TOKEN_LENGTH+1];
+
+segtype	currentseg = NOSEG;
+
+typedef struct {
+	char	*text;
+	char	*emit;
+	int		numtokens;
+	void	(*parsefunc) (void);
+} parsefield;
+
+
+void errorexit (void);
+
+
+//==============================================
+
+typedef struct {
+	char	*text;
+	char	*emit;
+	int		len;
+} regdesc;
+
+regdesc	reglist[] = {
+	{"%eax", "eax", 4},
+	{"%ebx", "ebx", 4},
+	{"%ecx", "ecx", 4},
+	{"%edx", "edx", 4},
+	{"%esi", "esi", 4},
+	{"%edi", "edi", 4},
+	{"%ebp", "ebp", 4},
+	{"%esp", "esp", 4},
+	{"%ax", "ax", 3},
+	{"%bx", "bx", 3},
+	{"%cx", "cx", 3},
+	{"%dx", "dx", 3},
+	{"%si", "si", 3},
+	{"%di", "di", 3},
+	{"%bp", "bp", 3},
+	{"%sp", "sp", 3},
+	{"%al", "al", 3},
+	{"%bl", "bl", 3},
+	{"%cl", "cl", 3},
+	{"%dl", "dl", 3},
+	{"%ah", "ah", 3},
+	{"%bh", "bh", 3},
+	{"%ch", "ch", 3},
+	{"%dh", "dh", 3},
+	{"%st(0)", "st(0)", 6},
+	{"%st(1)", "st(1)", 6},
+	{"%st(2)", "st(2)", 6},
+	{"%st(3)", "st(3)", 6},
+	{"%st(4)", "st(4)", 6},
+	{"%st(5)", "st(5)", 6},
+	{"%st(6)", "st(6)", 6},
+	{"%st(7)", "st(7)", 6},
+};
+
+int	numregs = sizeof (reglist) / sizeof (reglist[0]);
+
+//==============================================
+
+
+void emitanoperand (int tnum, char *type, int notdata)
+{
+	int		i, index, something_outside_parens, regfound;
+	int		parencount;
+	char	*pt;
+	char	temp[MAX_TOKEN_LENGTH+1];
+
+	pt = tokens[tnum];
+
+	if (pt[0] == '%')
+	{
+	// register
+		for (i=0 ; i<numregs ; i++)
+		{
+			if (!strcmpi (pt, reglist[i].text))
+			{
+				printf ("%s", reglist[i].emit);
+				return;
+			}
+		}
+
+		fprintf (stderr, "Error: bad register %s\n", pt);
+		errorexit ();
+	}
+	else if (pt[0] == '$')
+	{
+	// constant
+		if (pt[1] == '(')
+		{
+			if ((pt[2] > '9') || (pt[2] < '0'))
+			{
+				i = 2;
+				printf ("offset ");
+
+				parencount = 1;
+
+				while ((pt[i] != ')') || (parencount > 1))
+				{
+					if (!pt[i])
+					{
+						fprintf (stderr, "mismatched parens");
+						errorexit ();
+					}
+
+					if (pt[i] == ')')
+						parencount--;
+					else if (pt[i] == '(')
+						parencount++;
+
+					printf ("%c", pt[i]);
+					i++;
+				}
+			}
+			else
+			{
+				pt++;
+
+				parencount = 1;
+
+				for (i=1 ; (pt[i] != ')') || (parencount > 1) ; i++)
+				{
+					if (!pt[i])
+					{
+						fprintf (stderr, "mismatched parens");
+						errorexit ();
+					}
+
+					if (pt[i] == ')')
+						parencount--;
+					else if (pt[i] == '(')
+						parencount++;
+				}
+
+				pt[i] = 0;
+
+				if ((pt[1] == '0') && ((pt[2] == 'x') || (pt[2] == 'X')))
+				{
+					printf ("0%sh", &pt[3]);
+				}
+				else
+				{
+					printf ("%s", &pt[1]);
+				}
+ 			}
+		}
+		else if ((pt[1] == '0') && ((pt[2] == 'x') || (pt[2] == 'X')))
+		{
+			printf ("0%sh", &pt[3]);
+		}
+		else if ((pt[1] >= '0') && (pt[1] <= '9'))
+		{
+			printf ("%s", &pt[1]);
+		}
+		else
+		{
+			printf ("offset %s", &pt[1]);
+		}
+	}
+	else if (!notdata && ((pt[0] >= '0') && (pt[0] <= '9')))
+	{
+		pt--;
+
+		if ((pt[1] == '0') && ((pt[2] == 'x') || (pt[2] == 'X')))
+		{
+			printf ("0%sh", &pt[3]);
+		}
+		else
+		{
+			printf ("%s", &pt[1]);
+		}
+	}
+	else
+	{
+	// must be a memory location
+		strcpy (temp, type);
+		index = strlen (temp);
+
+		if (notdata)
+			temp[index++] = '[';
+
+		something_outside_parens = 0;
+
+		while (*pt)
+		{
+			if (index > (MAX_TOKEN_LENGTH - 10))
+			{
+				fprintf (stderr, "Error: operand too long %s\n",
+						 tokens[tnum]);
+				errorexit ();
+			}
+
+			if (*pt != ')')
+			{
+				if (*pt == '(')
+				{
+					if (something_outside_parens)
+						temp[index++] = '+';
+				}
+				else if (*pt == '%')
+				{
+					regfound = 0;
+
+					for (i=0 ; i<numregs ; i++)
+					{
+						if (!strnicmp (pt, reglist[i].text,
+							reglist[i].len))
+						{
+							strcpy (&temp[index], reglist[i].emit);
+							index += strlen (reglist[i].emit);
+							pt += strlen (reglist[i].text) - 1;
+							regfound = 1;
+							break;
+						}
+					}
+
+					if (!regfound)
+					{
+						fprintf (stderr, "Error: bad register %s\n", pt);
+						errorexit ();
+					}
+				}
+				else if (*pt == ',')
+				{
+					pt++;
+
+					if ((*pt >= '1') && (*pt <= '8'))
+					{
+						temp[index++] = '*';
+						temp[index++] = *pt;
+					}
+					else if (*pt != ')')
+					{
+						if (temp[index-1] != '+')
+							temp[index++] = '+';
+					}
+				}
+				else
+				{
+					something_outside_parens = 1;
+
+					// handle hexadecimal constants in addresses
+					if ((*pt == '0') &&
+						((*(pt+1) == 'x') || (*(pt+1) == 'X')))
+					{
+						pt += 2;
+
+						do
+						{
+							temp[index++] = *pt++;
+						} while (((*pt >= '0') && (*pt <= '9'))     ||
+								 ((*pt >= 'a') && (*pt <= 'f')) ||
+								 ((*pt >= 'A') && (*pt <= 'F')));
+
+						pt--;
+						temp[index++] = 'h';
+					}
+					else
+					{
+						temp[index++] = *pt;
+					}
+				}
+			}
+
+			pt++;
+		}
+
+		if (notdata)
+			temp[index++] = ']';
+
+		temp[index] = 0;
+		printf ("%s", temp);
+	}
+}
+
+
+void datasegstart (void)
+{
+	if (currentseg == DATASEG)
+		return;
+
+	if (currentseg == TEXTSEG)
+		printf ("_TEXT ENDS\n");
+
+	printf ("_DATA SEGMENT");
+
+	currentseg = DATASEG;
+}
+
+
+void textsegstart (void)
+{
+	if (currentseg == TEXTSEG)
+		return;
+
+	if (currentseg == DATASEG)
+		printf ("_DATA ENDS\n");
+
+	printf ("_TEXT SEGMENT");
+
+	currentseg = TEXTSEG;
+}
+
+
+void emitdata (void)
+{
+	int		i;
+
+	for (i=1 ; i<(tokennum-1) ; i++)
+		printf (" %s,", tokens[i]);
+
+	printf (" %s", tokens[tokennum-1]);
+}
+
+
+void emitonedata (void)
+{
+
+	printf (" %s", tokens[1]);
+}
+
+
+void emitonecalldata (void)
+{
+	int	i, isaddr, len;
+
+	if (tokens[1][0] == '*')
+	{
+		printf (" dword ptr[%s]", &tokens[1][1]);
+	}
+	else
+	{
+		isaddr = 0;
+		len = strlen(tokens[1]);
+
+		for (i=0 ; i<len ; i++)
+		{
+			if (tokens[1][i] == '(')
+			{
+				isaddr = 1;
+				break;
+			}
+		}
+
+		if (!isaddr)
+		{
+			printf (" near ptr %s", tokens[1]);
+		}
+		else
+		{
+			emitanoperand (1, " dword ptr", 1);
+		}
+	}
+}
+
+
+void emitonejumpdata (void)
+{
+	int	i, isaddr, len;
+
+	if (tokens[1][0] == '*')
+	{
+		printf (" dword ptr[%s]", &tokens[1][1]);
+	}
+	else
+	{
+		isaddr = 0;
+		len = strlen(tokens[1]);
+
+		for (i=0 ; i<len ; i++)
+		{
+			if (tokens[1][i] == '(')
+			{
+				isaddr = 1;
+				break;
+			}
+		}
+
+		if (!isaddr)
+		{
+			printf (" %s", tokens[1]);
+		}
+		else
+		{
+			emitanoperand (1, " dword ptr", 1);
+		}
+	}
+}
+
+
+void emitexterndef (void)
+{
+
+	printf (" %s:dword", tokens[1]);
+}
+
+
+void nooperands (void)
+{
+
+}
+
+
+void emitoneoperandl (void)
+{
+
+	printf (" ");
+	emitanoperand (1, "ds:dword ptr", 1);
+}
+
+
+void emitoneoperandb (void)
+{
+
+	printf (" ");
+	emitanoperand (1, "ds:byte ptr", 1);
+}
+
+
+void emitoneoperandw (void)
+{
+
+	printf (" ");
+	emitanoperand (1, "ds:word ptr", 1);
+}
+
+
+void emittwooperandsl (void)
+{
+
+	printf (" ");
+	emitanoperand (2, "ds:dword ptr", 1);
+	printf (",");
+	emitanoperand (1, "ds:dword ptr", 1);
+}
+
+
+void emittwooperandsb (void)
+{
+
+	printf (" ");
+	emitanoperand (2, "ds:byte ptr", 1);
+	printf (",");
+	emitanoperand (1, "ds:byte ptr", 1);
+}
+
+
+void emittwooperandsw (void)
+{
+
+	printf (" ");
+	emitanoperand (2, "ds:word ptr", 1);
+	printf (",");
+	emitanoperand (1, "ds:word ptr", 1);
+}
+
+
+void emit_0_or_1_operandsl (void)
+{
+
+	if (tokennum == 2)
+	{
+		printf (" ");
+		emitanoperand (1, "ds:dword ptr", 1);
+	}
+}
+
+
+void emit_1_or_2_operandsl (void)
+{
+	int		j;
+
+	if (tokennum == 2)
+	{
+		printf (" ");
+		emitanoperand (1, "ds:dword ptr", 1);
+	}
+	else if (tokennum == 3)
+	{
+		printf (" ");
+		emitanoperand (2, "ds:dword ptr", 1);
+		printf (",");
+		emitanoperand (1, "ds:dword ptr", 1);
+	}
+	else
+	{
+
+		fprintf (stderr, "Error: too many operands\n");
+
+		for (j=0 ; j<tokennum ; j++)
+			fprintf (stderr, "%s\n", tokens[j]);
+
+		fprintf (stderr, "\n");
+		errorexit ();
+	}
+}
+
+
+void emit_1_or_2_operandsl_vartext (char *str0, char *str1)
+{
+	int		j;
+
+	if (tokennum == 2)
+	{
+		printf (" %s ", str0);
+		emitanoperand (1, "ds:dword ptr", 1);
+	}
+	else if (tokennum == 3)
+	{
+		if (!strcmpi (tokens[2], "%st(0)"))
+			printf (" %s ", str0);
+		else
+			printf (" %s ", str1);
+
+		emitanoperand (2, "ds:dword ptr", 1);
+		printf (",");
+		emitanoperand (1, "ds:dword ptr", 1);
+	}
+	else
+	{
+
+		fprintf (stderr, "Error: too many operands\n");
+
+		for (j=0 ; j<tokennum ; j++)
+			fprintf (stderr, "%s\n", tokens[j]);
+
+		fprintf (stderr, "\n");
+		errorexit ();
+	}
+}
+
+
+void special_fdivl (void)
+{
+
+	emit_1_or_2_operandsl_vartext ("fdiv", "fdivr");
+}
+
+
+void special_fdivpl (void)
+{
+
+	emit_1_or_2_operandsl_vartext ("fdivp", "fdivrp");
+}
+
+
+void special_fdivrl (void)
+{
+
+	emit_1_or_2_operandsl_vartext ("fdivr", "fdiv");
+}
+
+
+void special_fdivrpl (void)
+{
+
+	emit_1_or_2_operandsl_vartext ("fdivrp", "fdivp");
+}
+
+
+void special_fsubl (void)
+{
+
+	emit_1_or_2_operandsl_vartext ("fsub", "fsubr");
+}
+
+
+void special_fsubpl (void)
+{
+
+	emit_1_or_2_operandsl_vartext ("fsubp", "fsubrp");
+}
+
+
+void special_fsubrl (void)
+{
+
+	emit_1_or_2_operandsl_vartext ("fsubr", "fsub");
+}
+
+
+void special_fsubrpl (void)
+{
+
+	emit_1_or_2_operandsl_vartext ("fsubrp", "fsubp");
+}
+
+
+void emit_multiple_data (void)
+{
+	int		i;
+
+	printf (" ");
+
+	for (i=1 ; i<(tokennum-1) ; i++)
+	{
+		emitanoperand (i, "", 0);
+		printf (", ");
+	}
+
+	emitanoperand (i, "", 0);
+}
+
+
+//==============================================
+
+parsefield	parsedata[] = {
+	{".align", " align", 2, emitonedata},
+	{".byte",  " db", -2, emit_multiple_data},
+	{".data",  "", 1, datasegstart},
+	{".extern"," externdef", 2, emitexterndef},
+	{".globl", " public", -2, emit_multiple_data},
+	{".long",  " dd", -2, emit_multiple_data},
+	{".single"," dd", -2, emit_multiple_data},
+	{".text",  "", 1, textsegstart},
+	{"adcl",   " adc", 3, emittwooperandsl},
+	{"addb",   " add", 3, emittwooperandsb},
+	{"addl",   " add", 3, emittwooperandsl},
+	{"andb",   " and", 3, emittwooperandsb},
+	{"andl",   " and", 3, emittwooperandsl},
+	{"call",   " call", 2, emitonecalldata},
+	{"cmpb",   " cmp", 3, emittwooperandsb},
+	{"cmpl",   " cmp", 3, emittwooperandsl},
+	{"cmpw",   " cmp", 3, emittwooperandsw},
+	{"decl",   " dec", 2, emitoneoperandl},
+	{"decw",   " dec", 2, emitoneoperandw},
+	{"divl",   " div", 2, emitoneoperandl},
+	{"fadd",   " fadd", -2, emit_1_or_2_operandsl},
+	{"faddp",  " faddp", -2, emit_1_or_2_operandsl},
+	{"faddps", " faddp", -2, emit_1_or_2_operandsl},
+	{"fadds",  " fadd", -2, emit_1_or_2_operandsl},
+	{"fcom",   " fcom", 2, emitoneoperandl},
+	{"fcoms",  " fcom", 2, emitoneoperandl},
+	{"fcomp",  " fcomp", 2, emitoneoperandl},
+	{"fcomps", " fcomp", 2, emitoneoperandl},
+	{"fdiv",   "", -2, special_fdivl}, 
+	{"fdivp",  "", -2, special_fdivpl}, 
+	{"fdivr",  "", -2, special_fdivrl},
+	{"fdivrp", "", -2, special_fdivrpl},
+	{"fdivrs", "", -2, special_fdivrl},
+	{"fildl",  " fild", 2, emitoneoperandl},
+	{"fistl",  " fist", 2, emitoneoperandl},
+	{"fistpl", " fistp", 2, emitoneoperandl},
+	{"fld",    " fld", 2, emitoneoperandl},
+	{"fldcw",  " fldcw", 2, emitoneoperandw},
+	{"fldenv", " fldenv", 2, emitoneoperandl},
+	{"flds",   " fld", 2, emitoneoperandl},
+	{"fmul",   " fmul", -2, emit_1_or_2_operandsl},
+	{"fmulp",  " fmulp", -2, emit_1_or_2_operandsl},
+	{"fmulps", " fmulp", -2, emit_1_or_2_operandsl},
+	{"fmuls",  " fmul", -2, emit_1_or_2_operandsl},
+	{"fnstcw", " fnstcw", 2, emitoneoperandw},
+	{"fnstenv"," fnstenv", 2, emitoneoperandl},
+	{"fnstsw", " fnstsw", 2, emitoneoperandw},
+	{"fstp",   " fstp", 2, emitoneoperandl},
+	{"fstps",  " fstp", 2, emitoneoperandl},
+	{"fsts",   " fst", 2, emitoneoperandl},
+	{"fsubr",  "", -2, special_fsubrl},
+	{"fsubrp", "", -2, special_fsubrpl},
+	{"fsubrs", "", -2, special_fsubrl},
+	{"fsub",   "", -2, special_fsubl},
+	{"fsubp",  "", -2, special_fsubpl},
+	{"fsubps", "", -2, special_fsubpl},
+	{"fsubs",  "", -2, special_fsubl},
+	{"fxch",   " fxch", 2, emitoneoperandl},
+	{"imull",  " imul", -2, emit_1_or_2_operandsl},
+	{"incl",   " inc", 2, emitoneoperandl},
+	{"ja",     " ja", 2, emitonedata},
+	{"jae",    " jae", 2, emitonedata},
+	{"jb",     " jb", 2, emitonedata},
+	{"jbe",    " jbe", 2, emitonedata},
+	{"jc",     " jc", 2, emitonedata},
+	{"je",     " je", 2, emitonedata},
+	{"jg",     " jg", 2, emitonedata},
+	{"jge",    " jge", 2, emitonedata},
+	{"jl",     " jl", 2, emitonedata},
+	{"jle",    " jle", 2, emitonedata},
+	{"jmp",    " jmp", 2, emitonejumpdata},
+	{"jna",    " jna", 2, emitonedata},
+	{"jnae",   " jnae", 2, emitonedata},
+	{"jnb",    " jnb", 2, emitonedata},
+	{"jnbe",   " jnbe", 2, emitonedata},
+	{"jnc",    " jnc", 2, emitonedata},
+	{"jne",    " jne", 2, emitonedata},
+	{"jng",    " jng", 2, emitonedata},
+	{"jnge",   " jnge", 2, emitonedata},
+	{"jnl",    " jnl", 2, emitonedata},
+	{"jnle",   " jnle", 2, emitonedata},
+	{"jns",    " jns", 2, emitonedata},
+	{"jnz",    " jnz", 2, emitonedata},
+	{"js",     " js", 2, emitonedata},
+	{"jz",     " jz", 2, emitonedata},
+	{"leal",   " lea", 3, emittwooperandsl},
+	{"movb",   " mov", 3, emittwooperandsb},
+	{"movl",   " mov", 3, emittwooperandsl},
+	{"movw",   " mov", 3, emittwooperandsw},
+	{"negl",   " neg", 2, emitoneoperandl},
+	{"orb",    " or", 3, emittwooperandsb},
+	{"orl",    " or", 3, emittwooperandsl},
+	{"popl",   " pop", 2, emitoneoperandl},
+	{"pushl",  " push", 2, emitoneoperandl},
+	{"ret",    " ret", -1, emit_0_or_1_operandsl},
+	{"rorl",   " ror", 3, emittwooperandsl},
+	{"sarl",   " sar", 3, emittwooperandsl},
+	{"sbbl",   " sbb", 3, emittwooperandsl},
+	{"shll",   " shl", 3, emittwooperandsl},
+	{"shrl",   " shr", 3, emittwooperandsl},	
+	{"subl",   " sub", 3, emittwooperandsl},
+	{"testb",  " test", 3, emittwooperandsb},
+	{"testl",  " test", 3, emittwooperandsl},
+	{"xorb",   " xor", 3, emittwooperandsb},
+	{"xorl",   " xor", 3, emittwooperandsl},
+};
+
+int	numparse = sizeof (parsedata) / sizeof (parsedata[0]);
+
+//==============================================
+
+void errorexit (void)
+{
+	fprintf (stderr, "In line: %d, out line: %d\n", inline, outline);
+	exit (1);
+}
+
+
+tokenstat whitespace (char c)
+{
+	if (c == '\n')
+		return LINE_DONE;
+
+	if ((c <= ' ') ||
+		(c > 127) ||
+		(c == ','))
+	{
+		return WHITESPACE;
+	}
+
+	return NOT_WHITESPACE;
+}
+
+
+int gettoken (void)
+{
+	char		c;
+	int			count, parencount;
+	tokenstat	stat;
+
+	do
+	{
+		if ((c = getchar ()) == EOF)
+			return FILE_DONE;
+
+		if ((stat = whitespace (c)) == LINE_DONE)
+			return LINE_DONE;
+	} while (stat == WHITESPACE);
+
+	token[0] = c;
+	count = 1;
+
+	if (c == '~')
+	{
+		count--;
+		token[count++] = 'n';
+		token[count++] = 'o';
+		token[count++] = 't';
+		token[count++] = ' ';
+	}
+
+	if (c == '(')
+	{
+		do
+		{
+			if ((c = getchar ()) == EOF)
+			{
+				fprintf (stderr, "EOF in middle of parentheses\n");
+				errorexit ();
+			}
+
+			token[count++] = c;
+
+		} while (c != ')');
+	}
+	
+	for ( ;; )
+	{
+		if ((c = getchar ()) == EOF)
+		{
+			token[count] = 0;
+			return TOKEN_AVAILABLE;
+		}
+
+		if (whitespace (c) == LINE_DONE)
+		{
+			if (ungetc (c, stdin) == EOF)
+			{
+				fprintf (stderr, "Couldn't unget character\n");
+				errorexit ();
+			}
+
+			token[count] = 0;
+			return TOKEN_AVAILABLE;
+		}
+
+		if (whitespace (c) == WHITESPACE)
+		{
+			token[count] = 0;
+			return TOKEN_AVAILABLE;
+		}
+
+		if (count >= MAX_TOKEN_LENGTH)
+		{
+			fprintf (stderr, "Error: token too long\n");
+			errorexit ();
+		}
+
+		token[count++] = c;
+
+		if (c == '~')
+		{
+			count--;
+			token[count++] = 'n';
+			token[count++] = 'o';
+			token[count++] = 't';
+			token[count++] = ' ';
+		}
+		else if (c == '(')
+		{
+			parencount = 1;
+
+			do
+			{
+				if ((c = getchar ()) == EOF)
+				{
+					fprintf (stderr, "EOF in middle of parentheses\n");
+					errorexit ();
+				}
+
+				if (c == '(')
+					parencount++;
+				else if (c == ')')
+					parencount--;
+
+				if (c == '~')
+				{
+					token[count++] = 'n';
+					token[count++] = 'o';
+					token[count++] = 't';
+					token[count++] = ' ';
+				}
+				else
+				{
+					token[count++] = c;
+				}
+
+			} while ((c != ')') || (parencount > 0));
+		}
+	}
+}
+
+
+tokenstat parseline (void)
+{
+	tokenstat	stat;
+	int			i, j, firsttoken, labelfound;
+	int			mnemfound;
+
+	firsttoken = 1;
+	tokennum = 0;
+	labelfound = 0;
+
+	for ( ;; )
+	{
+		token = tokens[tokennum];
+		stat = gettoken ();
+
+		switch (stat)
+		{
+		case FILE_DONE:
+			return FILE_DONE;
+
+		case LINE_DONE:
+			if (!firsttoken && tokennum)
+			{
+				mnemfound = 0;
+
+				for (i=0 ; i<numparse; i++)
+				{
+					if (!strcmpi (tokens[0], parsedata[i].text))
+					{
+						if (((parsedata[i].numtokens > 0) &&
+							 (parsedata[i].numtokens != tokennum)) ||
+							((parsedata[i].numtokens < 0) &&
+							 (tokennum < -parsedata[i].numtokens)))
+						{
+							fprintf (stderr, "mismatched number of tokens\n");
+
+							for (j=0 ; j<tokennum ; j++)
+								fprintf (stderr, "%s\n", tokens[j]);
+
+							fprintf (stderr, "\n");
+							errorexit ();
+						}
+
+						printf ("%s", parsedata[i].emit);
+						(*parsedata[i].parsefunc) ();
+
+						mnemfound = 1;
+						break;
+					}
+				}
+
+				if (!mnemfound)
+				{
+					fprintf (stderr, "Error: unknown mnemonic\n");
+
+					for (j=0 ; j<tokennum ; j++)
+						fprintf (stderr, "%s\n", tokens[j]);
+
+					fprintf (stderr, "\n");
+					errorexit ();
+				}
+			}
+
+			if (!firsttoken)
+			{
+				if ((currentseg == DATASEG) && labelfound && !tokennum)
+					printf (":\n");
+				else
+					printf ("\n");
+
+				outline++;
+			}
+			return PARSED_OKAY;
+
+		case TOKEN_AVAILABLE:
+			if (firsttoken)
+			{
+				if (token[strlen(token) - 1] == ':')
+				{
+					labelfound = 1;
+
+					if (currentseg == DATASEG)
+					{
+						token[strlen(token) - 1] = 0;
+						printf ("%s", token);
+					}
+					else if (currentseg == TEXTSEG)
+					{
+						printf ("%s", token);
+					}
+					else
+					{
+						fprintf (stderr, "Error: not in segment block\n");
+						errorexit ();
+					}
+
+					firsttoken = 0;
+					break;
+				}
+			}
+
+			firsttoken = 0;
+
+			if (tokennum >= MAX_TOKENS)
+			{
+				fprintf (stderr, "Error: too many tokens\n");
+				exit (0);
+			}
+
+			tokennum++;
+
+			break;
+
+		default:
+			fprintf (stderr, "Error: unknown tokenstat %d\n", stat);
+			exit (0);
+		}
+	}
+}
+
+
+void main (int argc, char **argv)
+{
+	tokenstat	stat;
+
+	printf (" .386P\n"
+            " .model FLAT\n");
+	inline = 1;
+	outline = 3;
+
+	for ( ;; )
+	{
+		stat = parseline ();
+		inline++;
+
+		switch (stat)
+		{
+		case FILE_DONE:
+			if (currentseg == TEXTSEG)
+				printf ("_TEXT ENDS\n");
+			else if (currentseg == DATASEG)
+				printf ("_DATA ENDS\n");
+
+			printf (" END\n");
+			exit (0);
+		
+		case PARSED_OKAY:
+			break;
+
+		default:
+			fprintf (stderr, "Error: unknown tokenstat %d\n", stat);
+			exit (0);
+		}
+	}
+}
+
--- /dev/null
+++ b/WinQuake/gas2masm/gas2masm.dsp
@@ -1,0 +1,100 @@
+# Microsoft Developer Studio Project File - Name="gas2masm" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=gas2masm - Win32 Release
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "gas2masm.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "gas2masm.mak" CFG="gas2masm - Win32 Release"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "gas2masm - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "gas2masm - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE 
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "gas2masm - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir ".\Release"
+# PROP BASE Intermediate_Dir ".\Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir ".\Release"
+# PROP Intermediate_Dir ".\Release"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /c
+# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+
+!ELSEIF  "$(CFG)" == "gas2masm - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir ".\Debug"
+# PROP BASE Intermediate_Dir ".\Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir ".\Debug"
+# PROP Intermediate_Dir ".\Debug"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /YX /c
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386
+
+!ENDIF 
+
+# Begin Target
+
+# Name "gas2masm - Win32 Release"
+# Name "gas2masm - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat;for;f90"
+# Begin Source File
+
+SOURCE=.\gas2masm.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
--- /dev/null
+++ b/WinQuake/gas2masm/gas2masm.dsw
@@ -1,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "gas2masm"=.\gas2masm.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
binary files /dev/null b/WinQuake/gas2masm/gas2masm.mdp differ
--- /dev/null
+++ b/WinQuake/gas2masm/gas2masm.plg
@@ -1,0 +1,32 @@
+<html>
+<body>
+<pre>
+<h1>Build Log</h1>
+<h3>
+--------------------Configuration: gas2masm - Win32 Debug--------------------
+</h3>
+<h3>Command Lines</h3>
+Creating temporary file "C:\TEMP\RSP730.tmp" with contents
+[
+/nologo /MLd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /Fp".\Debug/gas2masm.pch" /YX /Fo".\Debug/" /Fd".\Debug/" /FD /c 
+"D:\Work\quake source\WinQuake\gas2masm\gas2masm.c"
+]
+Creating command line "cl.exe @C:\TEMP\RSP730.tmp" 
+Creating temporary file "C:\TEMP\RSP731.tmp" with contents
+[
+kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /incremental:yes /pdb:".\Debug/gas2masm.pdb" /debug /machine:I386 /out:".\Debug/gas2masm.exe" 
+".\Debug\gas2masm.obj"
+]
+Creating command line "link.exe @C:\TEMP\RSP731.tmp"
+<h3>Output Window</h3>
+Compiling...
+gas2masm.c
+Linking...
+
+
+
+<h3>Results</h3>
+gas2masm.exe - 0 error(s), 0 warning(s)
+</pre>
+</body>
+</html>
--- /dev/null
+++ b/WinQuake/gl_draw.c
@@ -1,0 +1,1297 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+
+// draw.c -- this is the only file outside the refresh that touches the
+// vid buffer
+
+#include "quakedef.h"
+
+#define GL_COLOR_INDEX8_EXT     0x80E5
+
+extern unsigned char d_15to8table[65536];
+
+cvar_t		gl_nobind = {"gl_nobind", "0"};
+cvar_t		gl_max_size = {"gl_max_size", "1024"};
+cvar_t		gl_picmip = {"gl_picmip", "0"};
+
+byte		*draw_chars;				// 8*8 graphic characters
+qpic_t		*draw_disc;
+qpic_t		*draw_backtile;
+
+int			translate_texture;
+int			char_texture;
+
+typedef struct
+{
+	int		texnum;
+	float	sl, tl, sh, th;
+} glpic_t;
+
+byte		conback_buffer[sizeof(qpic_t) + sizeof(glpic_t)];
+qpic_t		*conback = (qpic_t *)&conback_buffer;
+
+int		gl_lightmap_format = 4;
+int		gl_solid_format = 3;
+int		gl_alpha_format = 4;
+
+int		gl_filter_min = GL_LINEAR_MIPMAP_NEAREST;
+int		gl_filter_max = GL_LINEAR;
+
+
+int		texels;
+
+typedef struct
+{
+	int		texnum;
+	char	identifier[64];
+	int		width, height;
+	qboolean	mipmap;
+} gltexture_t;
+
+#define	MAX_GLTEXTURES	1024
+gltexture_t	gltextures[MAX_GLTEXTURES];
+int			numgltextures;
+
+
+void GL_Bind (int texnum)
+{
+	if (gl_nobind.value)
+		texnum = char_texture;
+	if (currenttexture == texnum)
+		return;
+	currenttexture = texnum;
+#ifdef _WIN32
+	bindTexFunc (GL_TEXTURE_2D, texnum);
+#else
+	glBindTexture(GL_TEXTURE_2D, texnum);
+#endif
+}
+
+
+/*
+=============================================================================
+
+  scrap allocation
+
+  Allocate all the little status bar obejcts into a single texture
+  to crutch up stupid hardware / drivers
+
+=============================================================================
+*/
+
+#define	MAX_SCRAPS		2
+#define	BLOCK_WIDTH		256
+#define	BLOCK_HEIGHT	256
+
+int			scrap_allocated[MAX_SCRAPS][BLOCK_WIDTH];
+byte		scrap_texels[MAX_SCRAPS][BLOCK_WIDTH*BLOCK_HEIGHT*4];
+qboolean	scrap_dirty;
+int			scrap_texnum;
+
+// returns a texture number and the position inside it
+int Scrap_AllocBlock (int w, int h, int *x, int *y)
+{
+	int		i, j;
+	int		best, best2;
+	int		bestx;
+	int		texnum;
+
+	for (texnum=0 ; texnum<MAX_SCRAPS ; texnum++)
+	{
+		best = BLOCK_HEIGHT;
+
+		for (i=0 ; i<BLOCK_WIDTH-w ; i++)
+		{
+			best2 = 0;
+
+			for (j=0 ; j<w ; j++)
+			{
+				if (scrap_allocated[texnum][i+j] >= best)
+					break;
+				if (scrap_allocated[texnum][i+j] > best2)
+					best2 = scrap_allocated[texnum][i+j];
+			}
+			if (j == w)
+			{	// this is a valid spot
+				*x = i;
+				*y = best = best2;
+			}
+		}
+
+		if (best + h > BLOCK_HEIGHT)
+			continue;
+
+		for (i=0 ; i<w ; i++)
+			scrap_allocated[texnum][*x + i] = best + h;
+
+		return texnum;
+	}
+
+	Sys_Error ("Scrap_AllocBlock: full");
+}
+
+int	scrap_uploads;
+
+void Scrap_Upload (void)
+{
+	int		texnum;
+
+	scrap_uploads++;
+
+	for (texnum=0 ; texnum<MAX_SCRAPS ; texnum++) {
+		GL_Bind(scrap_texnum + texnum);
+		GL_Upload8 (scrap_texels[texnum], BLOCK_WIDTH, BLOCK_HEIGHT, false, true);
+	}
+	scrap_dirty = false;
+}
+
+//=============================================================================
+/* Support Routines */
+
+typedef struct cachepic_s
+{
+	char		name[MAX_QPATH];
+	qpic_t		pic;
+	byte		padding[32];	// for appended glpic
+} cachepic_t;
+
+#define	MAX_CACHED_PICS		128
+cachepic_t	menu_cachepics[MAX_CACHED_PICS];
+int			menu_numcachepics;
+
+byte		menuplyr_pixels[4096];
+
+int		pic_texels;
+int		pic_count;
+
+qpic_t *Draw_PicFromWad (char *name)
+{
+	qpic_t	*p;
+	glpic_t	*gl;
+
+	p = W_GetLumpName (name);
+	gl = (glpic_t *)p->data;
+
+	// load little ones into the scrap
+	if (p->width < 64 && p->height < 64)
+	{
+		int		x, y;
+		int		i, j, k;
+		int		texnum;
+
+		texnum = Scrap_AllocBlock (p->width, p->height, &x, &y);
+		scrap_dirty = true;
+		k = 0;
+		for (i=0 ; i<p->height ; i++)
+			for (j=0 ; j<p->width ; j++, k++)
+				scrap_texels[texnum][(y+i)*BLOCK_WIDTH + x + j] = p->data[k];
+		texnum += scrap_texnum;
+		gl->texnum = texnum;
+		gl->sl = (x+0.01)/(float)BLOCK_WIDTH;
+		gl->sh = (x+p->width-0.01)/(float)BLOCK_WIDTH;
+		gl->tl = (y+0.01)/(float)BLOCK_WIDTH;
+		gl->th = (y+p->height-0.01)/(float)BLOCK_WIDTH;
+
+		pic_count++;
+		pic_texels += p->width*p->height;
+	}
+	else
+	{
+		gl->texnum = GL_LoadPicTexture (p);
+		gl->sl = 0;
+		gl->sh = 1;
+		gl->tl = 0;
+		gl->th = 1;
+	}
+	return p;
+}
+
+
+/*
+================
+Draw_CachePic
+================
+*/
+qpic_t	*Draw_CachePic (char *path)
+{
+	cachepic_t	*pic;
+	int			i;
+	qpic_t		*dat;
+	glpic_t		*gl;
+
+	for (pic=menu_cachepics, i=0 ; i<menu_numcachepics ; pic++, i++)
+		if (!strcmp (path, pic->name))
+			return &pic->pic;
+
+	if (menu_numcachepics == MAX_CACHED_PICS)
+		Sys_Error ("menu_numcachepics == MAX_CACHED_PICS");
+	menu_numcachepics++;
+	strcpy (pic->name, path);
+
+//
+// load the pic from disk
+//
+	dat = (qpic_t *)COM_LoadTempFile (path);	
+	if (!dat)
+		Sys_Error ("Draw_CachePic: failed to load %s", path);
+	SwapPic (dat);
+
+	// HACK HACK HACK --- we need to keep the bytes for
+	// the translatable player picture just for the menu
+	// configuration dialog
+	if (!strcmp (path, "gfx/menuplyr.lmp"))
+		memcpy (menuplyr_pixels, dat->data, dat->width*dat->height);
+
+	pic->pic.width = dat->width;
+	pic->pic.height = dat->height;
+
+	gl = (glpic_t *)pic->pic.data;
+	gl->texnum = GL_LoadPicTexture (dat);
+	gl->sl = 0;
+	gl->sh = 1;
+	gl->tl = 0;
+	gl->th = 1;
+
+	return &pic->pic;
+}
+
+
+void Draw_CharToConback (int num, byte *dest)
+{
+	int		row, col;
+	byte	*source;
+	int		drawline;
+	int		x;
+
+	row = num>>4;
+	col = num&15;
+	source = draw_chars + (row<<10) + (col<<3);
+
+	drawline = 8;
+
+	while (drawline--)
+	{
+		for (x=0 ; x<8 ; x++)
+			if (source[x] != 255)
+				dest[x] = 0x60 + source[x];
+		source += 128;
+		dest += 320;
+	}
+
+}
+
+typedef struct
+{
+	char *name;
+	int	minimize, maximize;
+} glmode_t;
+
+glmode_t modes[] = {
+	{"GL_NEAREST", GL_NEAREST, GL_NEAREST},
+	{"GL_LINEAR", GL_LINEAR, GL_LINEAR},
+	{"GL_NEAREST_MIPMAP_NEAREST", GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST},
+	{"GL_LINEAR_MIPMAP_NEAREST", GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR},
+	{"GL_NEAREST_MIPMAP_LINEAR", GL_NEAREST_MIPMAP_LINEAR, GL_NEAREST},
+	{"GL_LINEAR_MIPMAP_LINEAR", GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR}
+};
+
+/*
+===============
+Draw_TextureMode_f
+===============
+*/
+void Draw_TextureMode_f (void)
+{
+	int		i;
+	gltexture_t	*glt;
+
+	if (Cmd_Argc() == 1)
+	{
+		for (i=0 ; i< 6 ; i++)
+			if (gl_filter_min == modes[i].minimize)
+			{
+				Con_Printf ("%s\n", modes[i].name);
+				return;
+			}
+		Con_Printf ("current filter is unknown???\n");
+		return;
+	}
+
+	for (i=0 ; i< 6 ; i++)
+	{
+		if (!Q_strcasecmp (modes[i].name, Cmd_Argv(1) ) )
+			break;
+	}
+	if (i == 6)
+	{
+		Con_Printf ("bad filter name\n");
+		return;
+	}
+
+	gl_filter_min = modes[i].minimize;
+	gl_filter_max = modes[i].maximize;
+
+	// change all the existing mipmap texture objects
+	for (i=0, glt=gltextures ; i<numgltextures ; i++, glt++)
+	{
+		if (glt->mipmap)
+		{
+			GL_Bind (glt->texnum);
+			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
+			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
+		}
+	}
+}
+
+/*
+===============
+Draw_Init
+===============
+*/
+void Draw_Init (void)
+{
+	int		i;
+	qpic_t	*cb;
+	byte	*dest, *src;
+	int		x, y;
+	char	ver[40];
+	glpic_t	*gl;
+	int		start;
+	byte	*ncdata;
+	int		f, fstep;
+
+
+	Cvar_RegisterVariable (&gl_nobind);
+	Cvar_RegisterVariable (&gl_max_size);
+	Cvar_RegisterVariable (&gl_picmip);
+
+	// 3dfx can only handle 256 wide textures
+	if (!Q_strncasecmp ((char *)gl_renderer, "3dfx",4) ||
+		strstr((char *)gl_renderer, "Glide"))
+		Cvar_Set ("gl_max_size", "256");
+
+	Cmd_AddCommand ("gl_texturemode", &Draw_TextureMode_f);
+
+	// load the console background and the charset
+	// by hand, because we need to write the version
+	// string into the background before turning
+	// it into a texture
+	draw_chars = W_GetLumpName ("conchars");
+	for (i=0 ; i<256*64 ; i++)
+		if (draw_chars[i] == 0)
+			draw_chars[i] = 255;	// proper transparent color
+
+	// now turn them into textures
+	char_texture = GL_LoadTexture ("charset", 128, 128, draw_chars, false, true);
+
+	start = Hunk_LowMark();
+
+	cb = (qpic_t *)COM_LoadTempFile ("gfx/conback.lmp");	
+	if (!cb)
+		Sys_Error ("Couldn't load gfx/conback.lmp");
+	SwapPic (cb);
+
+	// hack the version number directly into the pic
+#if defined(__linux__)
+	sprintf (ver, "(Linux %2.2f, gl %4.2f) %4.2f", (float)LINUX_VERSION, (float)GLQUAKE_VERSION, (float)VERSION);
+#else
+	sprintf (ver, "(gl %4.2f) %4.2f", (float)GLQUAKE_VERSION, (float)VERSION);
+#endif
+	dest = cb->data + 320*186 + 320 - 11 - 8*strlen(ver);
+	y = strlen(ver);
+	for (x=0 ; x<y ; x++)
+		Draw_CharToConback (ver[x], dest+(x<<3));
+
+#if 0
+	conback->width = vid.conwidth;
+	conback->height = vid.conheight;
+
+ 	// scale console to vid size
+ 	dest = ncdata = Hunk_AllocName(vid.conwidth * vid.conheight, "conback");
+ 
+ 	for (y=0 ; y<vid.conheight ; y++, dest += vid.conwidth)
+ 	{
+ 		src = cb->data + cb->width * (y*cb->height/vid.conheight);
+ 		if (vid.conwidth == cb->width)
+ 			memcpy (dest, src, vid.conwidth);
+ 		else
+ 		{
+ 			f = 0;
+ 			fstep = cb->width*0x10000/vid.conwidth;
+ 			for (x=0 ; x<vid.conwidth ; x+=4)
+ 			{
+ 				dest[x] = src[f>>16];
+ 				f += fstep;
+ 				dest[x+1] = src[f>>16];
+ 				f += fstep;
+ 				dest[x+2] = src[f>>16];
+ 				f += fstep;
+ 				dest[x+3] = src[f>>16];
+ 				f += fstep;
+ 			}
+ 		}
+ 	}
+#else
+	conback->width = cb->width;
+	conback->height = cb->height;
+	ncdata = cb->data;
+#endif
+
+	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
+	gl = (glpic_t *)conback->data;
+	gl->texnum = GL_LoadTexture ("conback", conback->width, conback->height, ncdata, false, false);
+	gl->sl = 0;
+	gl->sh = 1;
+	gl->tl = 0;
+	gl->th = 1;
+	conback->width = vid.width;
+	conback->height = vid.height;
+
+	// free loaded console
+	Hunk_FreeToLowMark(start);
+
+	// save a texture slot for translated picture
+	translate_texture = texture_extension_number++;
+
+	// save slots for scraps
+	scrap_texnum = texture_extension_number;
+	texture_extension_number += MAX_SCRAPS;
+
+	//
+	// get the other pics we need
+	//
+	draw_disc = Draw_PicFromWad ("disc");
+	draw_backtile = Draw_PicFromWad ("backtile");
+}
+
+
+
+/*
+================
+Draw_Character
+
+Draws one 8*8 graphics character with 0 being transparent.
+It can be clipped to the top of the screen to allow the console to be
+smoothly scrolled off.
+================
+*/
+void Draw_Character (int x, int y, int num)
+{
+	byte			*dest;
+	byte			*source;
+	unsigned short	*pusdest;
+	int				drawline;	
+	int				row, col;
+	float			frow, fcol, size;
+
+	if (num == 32)
+		return;		// space
+
+	num &= 255;
+	
+	if (y <= -8)
+		return;			// totally off screen
+
+	row = num>>4;
+	col = num&15;
+
+	frow = row*0.0625;
+	fcol = col*0.0625;
+	size = 0.0625;
+
+	GL_Bind (char_texture);
+
+	glBegin (GL_QUADS);
+	glTexCoord2f (fcol, frow);
+	glVertex2f (x, y);
+	glTexCoord2f (fcol + size, frow);
+	glVertex2f (x+8, y);
+	glTexCoord2f (fcol + size, frow + size);
+	glVertex2f (x+8, y+8);
+	glTexCoord2f (fcol, frow + size);
+	glVertex2f (x, y+8);
+	glEnd ();
+}
+
+/*
+================
+Draw_String
+================
+*/
+void Draw_String (int x, int y, char *str)
+{
+	while (*str)
+	{
+		Draw_Character (x, y, *str);
+		str++;
+		x += 8;
+	}
+}
+
+/*
+================
+Draw_DebugChar
+
+Draws a single character directly to the upper right corner of the screen.
+This is for debugging lockups by drawing different chars in different parts
+of the code.
+================
+*/
+void Draw_DebugChar (char num)
+{
+}
+
+/*
+=============
+Draw_AlphaPic
+=============
+*/
+void Draw_AlphaPic (int x, int y, qpic_t *pic, float alpha)
+{
+	byte			*dest, *source;
+	unsigned short	*pusdest;
+	int				v, u;
+	glpic_t			*gl;
+
+	if (scrap_dirty)
+		Scrap_Upload ();
+	gl = (glpic_t *)pic->data;
+	glDisable(GL_ALPHA_TEST);
+	glEnable (GL_BLEND);
+//	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+//	glCullFace(GL_FRONT);
+	glColor4f (1,1,1,alpha);
+	GL_Bind (gl->texnum);
+	glBegin (GL_QUADS);
+	glTexCoord2f (gl->sl, gl->tl);
+	glVertex2f (x, y);
+	glTexCoord2f (gl->sh, gl->tl);
+	glVertex2f (x+pic->width, y);
+	glTexCoord2f (gl->sh, gl->th);
+	glVertex2f (x+pic->width, y+pic->height);
+	glTexCoord2f (gl->sl, gl->th);
+	glVertex2f (x, y+pic->height);
+	glEnd ();
+	glColor4f (1,1,1,1);
+	glEnable(GL_ALPHA_TEST);
+	glDisable (GL_BLEND);
+}
+
+
+/*
+=============
+Draw_Pic
+=============
+*/
+void Draw_Pic (int x, int y, qpic_t *pic)
+{
+	byte			*dest, *source;
+	unsigned short	*pusdest;
+	int				v, u;
+	glpic_t			*gl;
+
+	if (scrap_dirty)
+		Scrap_Upload ();
+	gl = (glpic_t *)pic->data;
+	glColor4f (1,1,1,1);
+	GL_Bind (gl->texnum);
+	glBegin (GL_QUADS);
+	glTexCoord2f (gl->sl, gl->tl);
+	glVertex2f (x, y);
+	glTexCoord2f (gl->sh, gl->tl);
+	glVertex2f (x+pic->width, y);
+	glTexCoord2f (gl->sh, gl->th);
+	glVertex2f (x+pic->width, y+pic->height);
+	glTexCoord2f (gl->sl, gl->th);
+	glVertex2f (x, y+pic->height);
+	glEnd ();
+}
+
+
+/*
+=============
+Draw_TransPic
+=============
+*/
+void Draw_TransPic (int x, int y, qpic_t *pic)
+{
+	byte	*dest, *source, tbyte;
+	unsigned short	*pusdest;
+	int				v, u;
+
+	if (x < 0 || (unsigned)(x + pic->width) > vid.width || y < 0 ||
+		 (unsigned)(y + pic->height) > vid.height)
+	{
+		Sys_Error ("Draw_TransPic: bad coordinates");
+	}
+		
+	Draw_Pic (x, y, pic);
+}
+
+
+/*
+=============
+Draw_TransPicTranslate
+
+Only used for the player color selection menu
+=============
+*/
+void Draw_TransPicTranslate (int x, int y, qpic_t *pic, byte *translation)
+{
+	int				v, u, c;
+	unsigned		trans[64*64], *dest;
+	byte			*src;
+	int				p;
+
+	GL_Bind (translate_texture);
+
+	c = pic->width * pic->height;
+
+	dest = trans;
+	for (v=0 ; v<64 ; v++, dest += 64)
+	{
+		src = &menuplyr_pixels[ ((v*pic->height)>>6) *pic->width];
+		for (u=0 ; u<64 ; u++)
+		{
+			p = src[(u*pic->width)>>6];
+			if (p == 255)
+				dest[u] = p;
+			else
+				dest[u] =  d_8to24table[translation[p]];
+		}
+	}
+
+	glTexImage2D (GL_TEXTURE_2D, 0, gl_alpha_format, 64, 64, 0, GL_RGBA, GL_UNSIGNED_BYTE, trans);
+
+	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+	glColor3f (1,1,1);
+	glBegin (GL_QUADS);
+	glTexCoord2f (0, 0);
+	glVertex2f (x, y);
+	glTexCoord2f (1, 0);
+	glVertex2f (x+pic->width, y);
+	glTexCoord2f (1, 1);
+	glVertex2f (x+pic->width, y+pic->height);
+	glTexCoord2f (0, 1);
+	glVertex2f (x, y+pic->height);
+	glEnd ();
+}
+
+
+/*
+================
+Draw_ConsoleBackground
+
+================
+*/
+void Draw_ConsoleBackground (int lines)
+{
+	int y = (vid.height * 3) >> 2;
+
+	if (lines > y)
+		Draw_Pic(0, lines - vid.height, conback);
+	else
+		Draw_AlphaPic (0, lines - vid.height, conback, (float)(1.2 * lines)/y);
+}
+
+
+/*
+=============
+Draw_TileClear
+
+This repeats a 64*64 tile graphic to fill the screen around a sized down
+refresh window.
+=============
+*/
+void Draw_TileClear (int x, int y, int w, int h)
+{
+	glColor3f (1,1,1);
+	GL_Bind (*(int *)draw_backtile->data);
+	glBegin (GL_QUADS);
+	glTexCoord2f (x/64.0, y/64.0);
+	glVertex2f (x, y);
+	glTexCoord2f ( (x+w)/64.0, y/64.0);
+	glVertex2f (x+w, y);
+	glTexCoord2f ( (x+w)/64.0, (y+h)/64.0);
+	glVertex2f (x+w, y+h);
+	glTexCoord2f ( x/64.0, (y+h)/64.0 );
+	glVertex2f (x, y+h);
+	glEnd ();
+}
+
+
+/*
+=============
+Draw_Fill
+
+Fills a box of pixels with a single color
+=============
+*/
+void Draw_Fill (int x, int y, int w, int h, int c)
+{
+	glDisable (GL_TEXTURE_2D);
+	glColor3f (host_basepal[c*3]/255.0,
+		host_basepal[c*3+1]/255.0,
+		host_basepal[c*3+2]/255.0);
+
+	glBegin (GL_QUADS);
+
+	glVertex2f (x,y);
+	glVertex2f (x+w, y);
+	glVertex2f (x+w, y+h);
+	glVertex2f (x, y+h);
+
+	glEnd ();
+	glColor3f (1,1,1);
+	glEnable (GL_TEXTURE_2D);
+}
+//=============================================================================
+
+/*
+================
+Draw_FadeScreen
+
+================
+*/
+void Draw_FadeScreen (void)
+{
+	glEnable (GL_BLEND);
+	glDisable (GL_TEXTURE_2D);
+	glColor4f (0, 0, 0, 0.8);
+	glBegin (GL_QUADS);
+
+	glVertex2f (0,0);
+	glVertex2f (vid.width, 0);
+	glVertex2f (vid.width, vid.height);
+	glVertex2f (0, vid.height);
+
+	glEnd ();
+	glColor4f (1,1,1,1);
+	glEnable (GL_TEXTURE_2D);
+	glDisable (GL_BLEND);
+
+	Sbar_Changed();
+}
+
+//=============================================================================
+
+/*
+================
+Draw_BeginDisc
+
+Draws the little blue disc in the corner of the screen.
+Call before beginning any disc IO.
+================
+*/
+void Draw_BeginDisc (void)
+{
+	if (!draw_disc)
+		return;
+	glDrawBuffer  (GL_FRONT);
+	Draw_Pic (vid.width - 24, 0, draw_disc);
+	glDrawBuffer  (GL_BACK);
+}
+
+
+/*
+================
+Draw_EndDisc
+
+Erases the disc icon.
+Call after completing any disc IO
+================
+*/
+void Draw_EndDisc (void)
+{
+}
+
+/*
+================
+GL_Set2D
+
+Setup as if the screen was 320*200
+================
+*/
+void GL_Set2D (void)
+{
+	glViewport (glx, gly, glwidth, glheight);
+
+	glMatrixMode(GL_PROJECTION);
+    glLoadIdentity ();
+	glOrtho  (0, vid.width, vid.height, 0, -99999, 99999);
+
+	glMatrixMode(GL_MODELVIEW);
+    glLoadIdentity ();
+
+	glDisable (GL_DEPTH_TEST);
+	glDisable (GL_CULL_FACE);
+	glDisable (GL_BLEND);
+	glEnable (GL_ALPHA_TEST);
+//	glDisable (GL_ALPHA_TEST);
+
+	glColor4f (1,1,1,1);
+}
+
+//====================================================================
+
+/*
+================
+GL_FindTexture
+================
+*/
+int GL_FindTexture (char *identifier)
+{
+	int		i;
+	gltexture_t	*glt;
+
+	for (i=0, glt=gltextures ; i<numgltextures ; i++, glt++)
+	{
+		if (!strcmp (identifier, glt->identifier))
+			return gltextures[i].texnum;
+	}
+
+	return -1;
+}
+
+/*
+================
+GL_ResampleTexture
+================
+*/
+void GL_ResampleTexture (unsigned *in, int inwidth, int inheight, unsigned *out,  int outwidth, int outheight)
+{
+	int		i, j;
+	unsigned	*inrow;
+	unsigned	frac, fracstep;
+
+	fracstep = inwidth*0x10000/outwidth;
+	for (i=0 ; i<outheight ; i++, out += outwidth)
+	{
+		inrow = in + inwidth*(i*inheight/outheight);
+		frac = fracstep >> 1;
+		for (j=0 ; j<outwidth ; j+=4)
+		{
+			out[j] = inrow[frac>>16];
+			frac += fracstep;
+			out[j+1] = inrow[frac>>16];
+			frac += fracstep;
+			out[j+2] = inrow[frac>>16];
+			frac += fracstep;
+			out[j+3] = inrow[frac>>16];
+			frac += fracstep;
+		}
+	}
+}
+
+/*
+================
+GL_Resample8BitTexture -- JACK
+================
+*/
+void GL_Resample8BitTexture (unsigned char *in, int inwidth, int inheight, unsigned char *out,  int outwidth, int outheight)
+{
+	int		i, j;
+	unsigned	char *inrow;
+	unsigned	frac, fracstep;
+
+	fracstep = inwidth*0x10000/outwidth;
+	for (i=0 ; i<outheight ; i++, out += outwidth)
+	{
+		inrow = in + inwidth*(i*inheight/outheight);
+		frac = fracstep >> 1;
+		for (j=0 ; j<outwidth ; j+=4)
+		{
+			out[j] = inrow[frac>>16];
+			frac += fracstep;
+			out[j+1] = inrow[frac>>16];
+			frac += fracstep;
+			out[j+2] = inrow[frac>>16];
+			frac += fracstep;
+			out[j+3] = inrow[frac>>16];
+			frac += fracstep;
+		}
+	}
+}
+
+
+/*
+================
+GL_MipMap
+
+Operates in place, quartering the size of the texture
+================
+*/
+void GL_MipMap (byte *in, int width, int height)
+{
+	int		i, j;
+	byte	*out;
+
+	width <<=2;
+	height >>= 1;
+	out = in;
+	for (i=0 ; i<height ; i++, in+=width)
+	{
+		for (j=0 ; j<width ; j+=8, out+=4, in+=8)
+		{
+			out[0] = (in[0] + in[4] + in[width+0] + in[width+4])>>2;
+			out[1] = (in[1] + in[5] + in[width+1] + in[width+5])>>2;
+			out[2] = (in[2] + in[6] + in[width+2] + in[width+6])>>2;
+			out[3] = (in[3] + in[7] + in[width+3] + in[width+7])>>2;
+		}
+	}
+}
+
+/*
+================
+GL_MipMap8Bit
+
+Mipping for 8 bit textures
+================
+*/
+void GL_MipMap8Bit (byte *in, int width, int height)
+{
+	int		i, j;
+	unsigned short     r,g,b;
+	byte	*out, *at1, *at2, *at3, *at4;
+
+//	width <<=2;
+	height >>= 1;
+	out = in;
+	for (i=0 ; i<height ; i++, in+=width)
+	{
+		for (j=0 ; j<width ; j+=2, out+=1, in+=2)
+		{
+			at1 = (byte *) (d_8to24table + in[0]);
+			at2 = (byte *) (d_8to24table + in[1]);
+			at3 = (byte *) (d_8to24table + in[width+0]);
+			at4 = (byte *) (d_8to24table + in[width+1]);
+
+ 			r = (at1[0]+at2[0]+at3[0]+at4[0]); r>>=5;
+ 			g = (at1[1]+at2[1]+at3[1]+at4[1]); g>>=5;
+ 			b = (at1[2]+at2[2]+at3[2]+at4[2]); b>>=5;
+
+			out[0] = d_15to8table[(r<<0) + (g<<5) + (b<<10)];
+		}
+	}
+}
+
+/*
+===============
+GL_Upload32
+===============
+*/
+void GL_Upload32 (unsigned *data, int width, int height,  qboolean mipmap, qboolean alpha)
+{
+	int			samples;
+static	unsigned	scaled[1024*512];	// [512*256];
+	int			scaled_width, scaled_height;
+
+	for (scaled_width = 1 ; scaled_width < width ; scaled_width<<=1)
+		;
+	for (scaled_height = 1 ; scaled_height < height ; scaled_height<<=1)
+		;
+
+	scaled_width >>= (int)gl_picmip.value;
+	scaled_height >>= (int)gl_picmip.value;
+
+	if (scaled_width > gl_max_size.value)
+		scaled_width = gl_max_size.value;
+	if (scaled_height > gl_max_size.value)
+		scaled_height = gl_max_size.value;
+
+	if (scaled_width * scaled_height > sizeof(scaled)/4)
+		Sys_Error ("GL_LoadTexture: too big");
+
+	samples = alpha ? gl_alpha_format : gl_solid_format;
+
+#if 0
+	if (mipmap)
+		gluBuild2DMipmaps (GL_TEXTURE_2D, samples, width, height, GL_RGBA, GL_UNSIGNED_BYTE, trans);
+	else if (scaled_width == width && scaled_height == height)
+		glTexImage2D (GL_TEXTURE_2D, 0, samples, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, trans);
+	else
+	{
+		gluScaleImage (GL_RGBA, width, height, GL_UNSIGNED_BYTE, trans,
+			scaled_width, scaled_height, GL_UNSIGNED_BYTE, scaled);
+		glTexImage2D (GL_TEXTURE_2D, 0, samples, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaled);
+	}
+#else
+texels += scaled_width * scaled_height;
+
+	if (scaled_width == width && scaled_height == height)
+	{
+		if (!mipmap)
+		{
+			glTexImage2D (GL_TEXTURE_2D, 0, samples, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
+			goto done;
+		}
+		memcpy (scaled, data, width*height*4);
+	}
+	else
+		GL_ResampleTexture (data, width, height, scaled, scaled_width, scaled_height);
+
+	glTexImage2D (GL_TEXTURE_2D, 0, samples, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaled);
+	if (mipmap)
+	{
+		int		miplevel;
+
+		miplevel = 0;
+		while (scaled_width > 1 || scaled_height > 1)
+		{
+			GL_MipMap ((byte *)scaled, scaled_width, scaled_height);
+			scaled_width >>= 1;
+			scaled_height >>= 1;
+			if (scaled_width < 1)
+				scaled_width = 1;
+			if (scaled_height < 1)
+				scaled_height = 1;
+			miplevel++;
+			glTexImage2D (GL_TEXTURE_2D, miplevel, samples, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaled);
+		}
+	}
+done: ;
+#endif
+
+
+	if (mipmap)
+	{
+		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
+		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
+	}
+	else
+	{
+		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_max);
+		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
+	}
+}
+
+void GL_Upload8_EXT (byte *data, int width, int height,  qboolean mipmap, qboolean alpha) 
+{
+	int			i, s;
+	qboolean	noalpha;
+	int			p;
+	static unsigned j;
+	int			samples;
+    static	unsigned char scaled[1024*512];	// [512*256];
+	int			scaled_width, scaled_height;
+
+	s = width*height;
+	// if there are no transparent pixels, make it a 3 component
+	// texture even if it was specified as otherwise
+	if (alpha)
+	{
+		noalpha = true;
+		for (i=0 ; i<s ; i++)
+		{
+			if (data[i] == 255)
+				noalpha = false;
+		}
+
+		if (alpha && noalpha)
+			alpha = false;
+	}
+	for (scaled_width = 1 ; scaled_width < width ; scaled_width<<=1)
+		;
+	for (scaled_height = 1 ; scaled_height < height ; scaled_height<<=1)
+		;
+
+	scaled_width >>= (int)gl_picmip.value;
+	scaled_height >>= (int)gl_picmip.value;
+
+	if (scaled_width > gl_max_size.value)
+		scaled_width = gl_max_size.value;
+	if (scaled_height > gl_max_size.value)
+		scaled_height = gl_max_size.value;
+
+	if (scaled_width * scaled_height > sizeof(scaled))
+		Sys_Error ("GL_LoadTexture: too big");
+
+	samples = 1; // alpha ? gl_alpha_format : gl_solid_format;
+
+	texels += scaled_width * scaled_height;
+
+	if (scaled_width == width && scaled_height == height)
+	{
+		if (!mipmap)
+		{
+			glTexImage2D (GL_TEXTURE_2D, 0, GL_COLOR_INDEX8_EXT, scaled_width, scaled_height, 0, GL_COLOR_INDEX , GL_UNSIGNED_BYTE, data);
+			goto done;
+		}
+		memcpy (scaled, data, width*height);
+	}
+	else
+		GL_Resample8BitTexture (data, width, height, scaled, scaled_width, scaled_height);
+
+	glTexImage2D (GL_TEXTURE_2D, 0, GL_COLOR_INDEX8_EXT, scaled_width, scaled_height, 0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, scaled);
+	if (mipmap)
+	{
+		int		miplevel;
+
+		miplevel = 0;
+		while (scaled_width > 1 || scaled_height > 1)
+		{
+			GL_MipMap8Bit ((byte *)scaled, scaled_width, scaled_height);
+			scaled_width >>= 1;
+			scaled_height >>= 1;
+			if (scaled_width < 1)
+				scaled_width = 1;
+			if (scaled_height < 1)
+				scaled_height = 1;
+			miplevel++;
+			glTexImage2D (GL_TEXTURE_2D, miplevel, GL_COLOR_INDEX8_EXT, scaled_width, scaled_height, 0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, scaled);
+		}
+	}
+done: ;
+
+
+	if (mipmap)
+	{
+		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
+		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
+	}
+	else
+	{
+		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_max);
+		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
+	}
+}
+
+/*
+===============
+GL_Upload8
+===============
+*/
+void GL_Upload8 (byte *data, int width, int height,  qboolean mipmap, qboolean alpha)
+{
+static	unsigned	trans[640*480];		// FIXME, temporary
+	int			i, s;
+	qboolean	noalpha;
+	int			p;
+
+	s = width*height;
+	// if there are no transparent pixels, make it a 3 component
+	// texture even if it was specified as otherwise
+	if (alpha)
+	{
+		noalpha = true;
+		for (i=0 ; i<s ; i++)
+		{
+			p = data[i];
+			if (p == 255)
+				noalpha = false;
+			trans[i] = d_8to24table[p];
+		}
+
+		if (alpha && noalpha)
+			alpha = false;
+	}
+	else
+	{
+		if (s&3)
+			Sys_Error ("GL_Upload8: s&3");
+		for (i=0 ; i<s ; i+=4)
+		{
+			trans[i] = d_8to24table[data[i]];
+			trans[i+1] = d_8to24table[data[i+1]];
+			trans[i+2] = d_8to24table[data[i+2]];
+			trans[i+3] = d_8to24table[data[i+3]];
+		}
+	}
+
+ 	if (VID_Is8bit() && !alpha && (data!=scrap_texels[0])) {
+ 		GL_Upload8_EXT (data, width, height, mipmap, alpha);
+ 		return;
+	}
+	GL_Upload32 (trans, width, height, mipmap, alpha);
+}
+
+/*
+================
+GL_LoadTexture
+================
+*/
+int GL_LoadTexture (char *identifier, int width, int height, byte *data, qboolean mipmap, qboolean alpha)
+{
+	qboolean	noalpha;
+	int			i, p, s;
+	gltexture_t	*glt;
+
+	// see if the texture is allready present
+	if (identifier[0])
+	{
+		for (i=0, glt=gltextures ; i<numgltextures ; i++, glt++)
+		{
+			if (!strcmp (identifier, glt->identifier))
+			{
+				if (width != glt->width || height != glt->height)
+					Sys_Error ("GL_LoadTexture: cache mismatch");
+				return gltextures[i].texnum;
+			}
+		}
+	}
+	else {
+		glt = &gltextures[numgltextures];
+		numgltextures++;
+	}
+
+	strcpy (glt->identifier, identifier);
+	glt->texnum = texture_extension_number;
+	glt->width = width;
+	glt->height = height;
+	glt->mipmap = mipmap;
+
+	GL_Bind(texture_extension_number );
+
+	GL_Upload8 (data, width, height, mipmap, alpha);
+
+	texture_extension_number++;
+
+	return texture_extension_number-1;
+}
+
+/*
+================
+GL_LoadPicTexture
+================
+*/
+int GL_LoadPicTexture (qpic_t *pic)
+{
+	return GL_LoadTexture ("", pic->width, pic->height, pic->data, false, true);
+}
+
+/****************************************/
+
+static GLenum oldtarget = TEXTURE0_SGIS;
+
+void GL_SelectTexture (GLenum target) 
+{
+	if (!gl_mtexable)
+		return;
+	qglSelectTextureSGIS(target);
+	if (target == oldtarget) 
+		return;
+	cnttextures[oldtarget-TEXTURE0_SGIS] = currenttexture;
+	currenttexture = cnttextures[target-TEXTURE0_SGIS];
+	oldtarget = target;
+}
--- /dev/null
+++ b/WinQuake/gl_mesh.c
@@ -1,0 +1,360 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// gl_mesh.c: triangle model functions
+
+#include "quakedef.h"
+
+/*
+=================================================================
+
+ALIAS MODEL DISPLAY LIST GENERATION
+
+=================================================================
+*/
+
+model_t		*aliasmodel;
+aliashdr_t	*paliashdr;
+
+qboolean	used[8192];
+
+// the command list holds counts and s/t values that are valid for
+// every frame
+int		commands[8192];
+int		numcommands;
+
+// all frames will have their vertexes rearranged and expanded
+// so they are in the order expected by the command list
+int		vertexorder[8192];
+int		numorder;
+
+int		allverts, alltris;
+
+int		stripverts[128];
+int		striptris[128];
+int		stripcount;
+
+/*
+================
+StripLength
+================
+*/
+int	StripLength (int starttri, int startv)
+{
+	int			m1, m2;
+	int			j;
+	mtriangle_t	*last, *check;
+	int			k;
+
+	used[starttri] = 2;
+
+	last = &triangles[starttri];
+
+	stripverts[0] = last->vertindex[(startv)%3];
+	stripverts[1] = last->vertindex[(startv+1)%3];
+	stripverts[2] = last->vertindex[(startv+2)%3];
+
+	striptris[0] = starttri;
+	stripcount = 1;
+
+	m1 = last->vertindex[(startv+2)%3];
+	m2 = last->vertindex[(startv+1)%3];
+
+	// look for a matching triangle
+nexttri:
+	for (j=starttri+1, check=&triangles[starttri+1] ; j<pheader->numtris ; j++, check++)
+	{
+		if (check->facesfront != last->facesfront)
+			continue;
+		for (k=0 ; k<3 ; k++)
+		{
+			if (check->vertindex[k] != m1)
+				continue;
+			if (check->vertindex[ (k+1)%3 ] != m2)
+				continue;
+
+			// this is the next part of the fan
+
+			// if we can't use this triangle, this tristrip is done
+			if (used[j])
+				goto done;
+
+			// the new edge
+			if (stripcount & 1)
+				m2 = check->vertindex[ (k+2)%3 ];
+			else
+				m1 = check->vertindex[ (k+2)%3 ];
+
+			stripverts[stripcount+2] = check->vertindex[ (k+2)%3 ];
+			striptris[stripcount] = j;
+			stripcount++;
+
+			used[j] = 2;
+			goto nexttri;
+		}
+	}
+done:
+
+	// clear the temp used flags
+	for (j=starttri+1 ; j<pheader->numtris ; j++)
+		if (used[j] == 2)
+			used[j] = 0;
+
+	return stripcount;
+}
+
+/*
+===========
+FanLength
+===========
+*/
+int	FanLength (int starttri, int startv)
+{
+	int		m1, m2;
+	int		j;
+	mtriangle_t	*last, *check;
+	int		k;
+
+	used[starttri] = 2;
+
+	last = &triangles[starttri];
+
+	stripverts[0] = last->vertindex[(startv)%3];
+	stripverts[1] = last->vertindex[(startv+1)%3];
+	stripverts[2] = last->vertindex[(startv+2)%3];
+
+	striptris[0] = starttri;
+	stripcount = 1;
+
+	m1 = last->vertindex[(startv+0)%3];
+	m2 = last->vertindex[(startv+2)%3];
+
+
+	// look for a matching triangle
+nexttri:
+	for (j=starttri+1, check=&triangles[starttri+1] ; j<pheader->numtris ; j++, check++)
+	{
+		if (check->facesfront != last->facesfront)
+			continue;
+		for (k=0 ; k<3 ; k++)
+		{
+			if (check->vertindex[k] != m1)
+				continue;
+			if (check->vertindex[ (k+1)%3 ] != m2)
+				continue;
+
+			// this is the next part of the fan
+
+			// if we can't use this triangle, this tristrip is done
+			if (used[j])
+				goto done;
+
+			// the new edge
+			m2 = check->vertindex[ (k+2)%3 ];
+
+			stripverts[stripcount+2] = m2;
+			striptris[stripcount] = j;
+			stripcount++;
+
+			used[j] = 2;
+			goto nexttri;
+		}
+	}
+done:
+
+	// clear the temp used flags
+	for (j=starttri+1 ; j<pheader->numtris ; j++)
+		if (used[j] == 2)
+			used[j] = 0;
+
+	return stripcount;
+}
+
+
+/*
+================
+BuildTris
+
+Generate a list of trifans or strips
+for the model, which holds for all frames
+================
+*/
+void BuildTris (void)
+{
+	int		i, j, k;
+	int		startv;
+	mtriangle_t	*last, *check;
+	int		m1, m2;
+	int		striplength;
+	trivertx_t	*v;
+	mtriangle_t *tv;
+	float	s, t;
+	int		index;
+	int		len, bestlen, besttype;
+	int		bestverts[1024];
+	int		besttris[1024];
+	int		type;
+
+	//
+	// build tristrips
+	//
+	numorder = 0;
+	numcommands = 0;
+	memset (used, 0, sizeof(used));
+	for (i=0 ; i<pheader->numtris ; i++)
+	{
+		// pick an unused triangle and start the trifan
+		if (used[i])
+			continue;
+
+		bestlen = 0;
+		for (type = 0 ; type < 2 ; type++)
+//	type = 1;
+		{
+			for (startv =0 ; startv < 3 ; startv++)
+			{
+				if (type == 1)
+					len = StripLength (i, startv);
+				else
+					len = FanLength (i, startv);
+				if (len > bestlen)
+				{
+					besttype = type;
+					bestlen = len;
+					for (j=0 ; j<bestlen+2 ; j++)
+						bestverts[j] = stripverts[j];
+					for (j=0 ; j<bestlen ; j++)
+						besttris[j] = striptris[j];
+				}
+			}
+		}
+
+		// mark the tris on the best strip as used
+		for (j=0 ; j<bestlen ; j++)
+			used[besttris[j]] = 1;
+
+		if (besttype == 1)
+			commands[numcommands++] = (bestlen+2);
+		else
+			commands[numcommands++] = -(bestlen+2);
+
+		for (j=0 ; j<bestlen+2 ; j++)
+		{
+			// emit a vertex into the reorder buffer
+			k = bestverts[j];
+			vertexorder[numorder++] = k;
+
+			// emit s/t coords into the commands stream
+			s = stverts[k].s;
+			t = stverts[k].t;
+			if (!triangles[besttris[0]].facesfront && stverts[k].onseam)
+				s += pheader->skinwidth / 2;	// on back side
+			s = (s + 0.5) / pheader->skinwidth;
+			t = (t + 0.5) / pheader->skinheight;
+
+			*(float *)&commands[numcommands++] = s;
+			*(float *)&commands[numcommands++] = t;
+		}
+	}
+
+	commands[numcommands++] = 0;		// end of list marker
+
+	Con_DPrintf ("%3i tri %3i vert %3i cmd\n", pheader->numtris, numorder, numcommands);
+
+	allverts += numorder;
+	alltris += pheader->numtris;
+}
+
+
+/*
+================
+GL_MakeAliasModelDisplayLists
+================
+*/
+void GL_MakeAliasModelDisplayLists (model_t *m, aliashdr_t *hdr)
+{
+	int		i, j;
+	maliasgroup_t	*paliasgroup;
+	int			*cmds;
+	trivertx_t	*verts;
+	char	cache[MAX_QPATH], fullpath[MAX_OSPATH], *c;
+	FILE	*f;
+	int		len;
+	byte	*data;
+
+	aliasmodel = m;
+	paliashdr = hdr;	// (aliashdr_t *)Mod_Extradata (m);
+
+	//
+	// look for a cached version
+	//
+	strcpy (cache, "glquake/");
+	COM_StripExtension (m->name+strlen("progs/"), cache+strlen("glquake/"));
+	strcat (cache, ".ms2");
+
+	COM_FOpenFile (cache, &f);	
+	if (f)
+	{
+		fread (&numcommands, 4, 1, f);
+		fread (&numorder, 4, 1, f);
+		fread (&commands, numcommands * sizeof(commands[0]), 1, f);
+		fread (&vertexorder, numorder * sizeof(vertexorder[0]), 1, f);
+		fclose (f);
+	}
+	else
+	{
+		//
+		// build it from scratch
+		//
+		Con_Printf ("meshing %s...\n",m->name);
+
+		BuildTris ();		// trifans or lists
+
+		//
+		// save out the cached version
+		//
+		sprintf (fullpath, "%s/%s", com_gamedir, cache);
+		f = fopen (fullpath, "wb");
+		if (f)
+		{
+			fwrite (&numcommands, 4, 1, f);
+			fwrite (&numorder, 4, 1, f);
+			fwrite (&commands, numcommands * sizeof(commands[0]), 1, f);
+			fwrite (&vertexorder, numorder * sizeof(vertexorder[0]), 1, f);
+			fclose (f);
+		}
+	}
+
+
+	// save the data out
+
+	paliashdr->poseverts = numorder;
+
+	cmds = Hunk_Alloc (numcommands * 4);
+	paliashdr->commands = (byte *)cmds - (byte *)paliashdr;
+	memcpy (cmds, commands, numcommands * 4);
+
+	verts = Hunk_Alloc (paliashdr->numposes * paliashdr->poseverts 
+		* sizeof(trivertx_t) );
+	paliashdr->posedata = (byte *)verts - (byte *)paliashdr;
+	for (i=0 ; i<paliashdr->numposes ; i++)
+		for (j=0 ; j<numorder ; j++)
+			*verts++ = poseverts[i][vertexorder[j]];
+}
+
--- /dev/null
+++ b/WinQuake/gl_model.c
@@ -1,0 +1,1840 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// models.c -- model loading and caching
+
+// models are the only shared resource between a client and server running
+// on the same machine.
+
+#include "quakedef.h"
+
+model_t	*loadmodel;
+char	loadname[32];	// for hunk tags
+
+void Mod_LoadSpriteModel (model_t *mod, void *buffer);
+void Mod_LoadBrushModel (model_t *mod, void *buffer);
+void Mod_LoadAliasModel (model_t *mod, void *buffer);
+model_t *Mod_LoadModel (model_t *mod, qboolean crash);
+
+byte	mod_novis[MAX_MAP_LEAFS/8];
+
+#define	MAX_MOD_KNOWN	512
+model_t	mod_known[MAX_MOD_KNOWN];
+int		mod_numknown;
+
+cvar_t gl_subdivide_size = {"gl_subdivide_size", "128", true};
+
+/*
+===============
+Mod_Init
+===============
+*/
+void Mod_Init (void)
+{
+	Cvar_RegisterVariable (&gl_subdivide_size);
+	memset (mod_novis, 0xff, sizeof(mod_novis));
+}
+
+/*
+===============
+Mod_Init
+
+Caches the data if needed
+===============
+*/
+void *Mod_Extradata (model_t *mod)
+{
+	void	*r;
+	
+	r = Cache_Check (&mod->cache);
+	if (r)
+		return r;
+
+	Mod_LoadModel (mod, true);
+	
+	if (!mod->cache.data)
+		Sys_Error ("Mod_Extradata: caching failed");
+	return mod->cache.data;
+}
+
+/*
+===============
+Mod_PointInLeaf
+===============
+*/
+mleaf_t *Mod_PointInLeaf (vec3_t p, model_t *model)
+{
+	mnode_t		*node;
+	float		d;
+	mplane_t	*plane;
+	
+	if (!model || !model->nodes)
+		Sys_Error ("Mod_PointInLeaf: bad model");
+
+	node = model->nodes;
+	while (1)
+	{
+		if (node->contents < 0)
+			return (mleaf_t *)node;
+		plane = node->plane;
+		d = DotProduct (p,plane->normal) - plane->dist;
+		if (d > 0)
+			node = node->children[0];
+		else
+			node = node->children[1];
+	}
+	
+	return NULL;	// never reached
+}
+
+
+/*
+===================
+Mod_DecompressVis
+===================
+*/
+byte *Mod_DecompressVis (byte *in, model_t *model)
+{
+	static byte	decompressed[MAX_MAP_LEAFS/8];
+	int		c;
+	byte	*out;
+	int		row;
+
+	row = (model->numleafs+7)>>3;	
+	out = decompressed;
+
+#if 0
+	memcpy (out, in, row);
+#else
+	if (!in)
+	{	// no vis info, so make all visible
+		while (row)
+		{
+			*out++ = 0xff;
+			row--;
+		}
+		return decompressed;		
+	}
+
+	do
+	{
+		if (*in)
+		{
+			*out++ = *in++;
+			continue;
+		}
+	
+		c = in[1];
+		in += 2;
+		while (c)
+		{
+			*out++ = 0;
+			c--;
+		}
+	} while (out - decompressed < row);
+#endif
+	
+	return decompressed;
+}
+
+byte *Mod_LeafPVS (mleaf_t *leaf, model_t *model)
+{
+	if (leaf == model->leafs)
+		return mod_novis;
+	return Mod_DecompressVis (leaf->compressed_vis, model);
+}
+
+/*
+===================
+Mod_ClearAll
+===================
+*/
+void Mod_ClearAll (void)
+{
+	int		i;
+	model_t	*mod;
+	
+	for (i=0 , mod=mod_known ; i<mod_numknown ; i++, mod++)
+		if (mod->type != mod_alias)
+			mod->needload = true;
+}
+
+/*
+==================
+Mod_FindName
+
+==================
+*/
+model_t *Mod_FindName (char *name)
+{
+	int		i;
+	model_t	*mod;
+	
+	if (!name[0])
+		Sys_Error ("Mod_ForName: NULL name");
+		
+//
+// search the currently loaded models
+//
+	for (i=0 , mod=mod_known ; i<mod_numknown ; i++, mod++)
+		if (!strcmp (mod->name, name) )
+			break;
+			
+	if (i == mod_numknown)
+	{
+		if (mod_numknown == MAX_MOD_KNOWN)
+			Sys_Error ("mod_numknown == MAX_MOD_KNOWN");
+		strcpy (mod->name, name);
+		mod->needload = true;
+		mod_numknown++;
+	}
+
+	return mod;
+}
+
+/*
+==================
+Mod_TouchModel
+
+==================
+*/
+void Mod_TouchModel (char *name)
+{
+	model_t	*mod;
+	
+	mod = Mod_FindName (name);
+	
+	if (!mod->needload)
+	{
+		if (mod->type == mod_alias)
+			Cache_Check (&mod->cache);
+	}
+}
+
+/*
+==================
+Mod_LoadModel
+
+Loads a model into the cache
+==================
+*/
+model_t *Mod_LoadModel (model_t *mod, qboolean crash)
+{
+	void	*d;
+	unsigned *buf;
+	byte	stackbuf[1024];		// avoid dirtying the cache heap
+
+	if (!mod->needload)
+	{
+		if (mod->type == mod_alias)
+		{
+			d = Cache_Check (&mod->cache);
+			if (d)
+				return mod;
+		}
+		else
+			return mod;		// not cached at all
+	}
+
+//
+// because the world is so huge, load it one piece at a time
+//
+	if (!crash)
+	{
+	
+	}
+	
+//
+// load the file
+//
+	buf = (unsigned *)COM_LoadStackFile (mod->name, stackbuf, sizeof(stackbuf));
+	if (!buf)
+	{
+		if (crash)
+			Sys_Error ("Mod_NumForName: %s not found", mod->name);
+		return NULL;
+	}
+	
+//
+// allocate a new model
+//
+	COM_FileBase (mod->name, loadname);
+	
+	loadmodel = mod;
+
+//
+// fill it in
+//
+
+// call the apropriate loader
+	mod->needload = false;
+	
+	switch (LittleLong(*(unsigned *)buf))
+	{
+	case IDPOLYHEADER:
+		Mod_LoadAliasModel (mod, buf);
+		break;
+		
+	case IDSPRITEHEADER:
+		Mod_LoadSpriteModel (mod, buf);
+		break;
+	
+	default:
+		Mod_LoadBrushModel (mod, buf);
+		break;
+	}
+
+	return mod;
+}
+
+/*
+==================
+Mod_ForName
+
+Loads in a model for the given name
+==================
+*/
+model_t *Mod_ForName (char *name, qboolean crash)
+{
+	model_t	*mod;
+	
+	mod = Mod_FindName (name);
+	
+	return Mod_LoadModel (mod, crash);
+}
+
+
+/*
+===============================================================================
+
+					BRUSHMODEL LOADING
+
+===============================================================================
+*/
+
+byte	*mod_base;
+
+
+/*
+=================
+Mod_LoadTextures
+=================
+*/
+void Mod_LoadTextures (lump_t *l)
+{
+	int		i, j, pixels, num, max, altmax;
+	miptex_t	*mt;
+	texture_t	*tx, *tx2;
+	texture_t	*anims[10];
+	texture_t	*altanims[10];
+	dmiptexlump_t *m;
+
+	if (!l->filelen)
+	{
+		loadmodel->textures = NULL;
+		return;
+	}
+	m = (dmiptexlump_t *)(mod_base + l->fileofs);
+	
+	m->nummiptex = LittleLong (m->nummiptex);
+	
+	loadmodel->numtextures = m->nummiptex;
+	loadmodel->textures = Hunk_AllocName (m->nummiptex * sizeof(*loadmodel->textures) , loadname);
+
+	for (i=0 ; i<m->nummiptex ; i++)
+	{
+		m->dataofs[i] = LittleLong(m->dataofs[i]);
+		if (m->dataofs[i] == -1)
+			continue;
+		mt = (miptex_t *)((byte *)m + m->dataofs[i]);
+		mt->width = LittleLong (mt->width);
+		mt->height = LittleLong (mt->height);
+		for (j=0 ; j<MIPLEVELS ; j++)
+			mt->offsets[j] = LittleLong (mt->offsets[j]);
+		
+		if ( (mt->width & 15) || (mt->height & 15) )
+			Sys_Error ("Texture %s is not 16 aligned", mt->name);
+		pixels = mt->width*mt->height/64*85;
+		tx = Hunk_AllocName (sizeof(texture_t) +pixels, loadname );
+		loadmodel->textures[i] = tx;
+
+		memcpy (tx->name, mt->name, sizeof(tx->name));
+		tx->width = mt->width;
+		tx->height = mt->height;
+		for (j=0 ; j<MIPLEVELS ; j++)
+			tx->offsets[j] = mt->offsets[j] + sizeof(texture_t) - sizeof(miptex_t);
+		// the pixels immediately follow the structures
+		memcpy ( tx+1, mt+1, pixels);
+		
+
+		if (!Q_strncmp(mt->name,"sky",3))	
+			R_InitSky (tx);
+		else
+		{
+			texture_mode = GL_LINEAR_MIPMAP_NEAREST; //_LINEAR;
+			tx->gl_texturenum = GL_LoadTexture (mt->name, tx->width, tx->height, (byte *)(tx+1), true, false);
+			texture_mode = GL_LINEAR;
+		}
+	}
+
+//
+// sequence the animations
+//
+	for (i=0 ; i<m->nummiptex ; i++)
+	{
+		tx = loadmodel->textures[i];
+		if (!tx || tx->name[0] != '+')
+			continue;
+		if (tx->anim_next)
+			continue;	// allready sequenced
+
+	// find the number of frames in the animation
+		memset (anims, 0, sizeof(anims));
+		memset (altanims, 0, sizeof(altanims));
+
+		max = tx->name[1];
+		altmax = 0;
+		if (max >= 'a' && max <= 'z')
+			max -= 'a' - 'A';
+		if (max >= '0' && max <= '9')
+		{
+			max -= '0';
+			altmax = 0;
+			anims[max] = tx;
+			max++;
+		}
+		else if (max >= 'A' && max <= 'J')
+		{
+			altmax = max - 'A';
+			max = 0;
+			altanims[altmax] = tx;
+			altmax++;
+		}
+		else
+			Sys_Error ("Bad animating texture %s", tx->name);
+
+		for (j=i+1 ; j<m->nummiptex ; j++)
+		{
+			tx2 = loadmodel->textures[j];
+			if (!tx2 || tx2->name[0] != '+')
+				continue;
+			if (strcmp (tx2->name+2, tx->name+2))
+				continue;
+
+			num = tx2->name[1];
+			if (num >= 'a' && num <= 'z')
+				num -= 'a' - 'A';
+			if (num >= '0' && num <= '9')
+			{
+				num -= '0';
+				anims[num] = tx2;
+				if (num+1 > max)
+					max = num + 1;
+			}
+			else if (num >= 'A' && num <= 'J')
+			{
+				num = num - 'A';
+				altanims[num] = tx2;
+				if (num+1 > altmax)
+					altmax = num+1;
+			}
+			else
+				Sys_Error ("Bad animating texture %s", tx->name);
+		}
+		
+#define	ANIM_CYCLE	2
+	// link them all together
+		for (j=0 ; j<max ; j++)
+		{
+			tx2 = anims[j];
+			if (!tx2)
+				Sys_Error ("Missing frame %i of %s",j, tx->name);
+			tx2->anim_total = max * ANIM_CYCLE;
+			tx2->anim_min = j * ANIM_CYCLE;
+			tx2->anim_max = (j+1) * ANIM_CYCLE;
+			tx2->anim_next = anims[ (j+1)%max ];
+			if (altmax)
+				tx2->alternate_anims = altanims[0];
+		}
+		for (j=0 ; j<altmax ; j++)
+		{
+			tx2 = altanims[j];
+			if (!tx2)
+				Sys_Error ("Missing frame %i of %s",j, tx->name);
+			tx2->anim_total = altmax * ANIM_CYCLE;
+			tx2->anim_min = j * ANIM_CYCLE;
+			tx2->anim_max = (j+1) * ANIM_CYCLE;
+			tx2->anim_next = altanims[ (j+1)%altmax ];
+			if (max)
+				tx2->alternate_anims = anims[0];
+		}
+	}
+}
+
+/*
+=================
+Mod_LoadLighting
+=================
+*/
+void Mod_LoadLighting (lump_t *l)
+{
+	if (!l->filelen)
+	{
+		loadmodel->lightdata = NULL;
+		return;
+	}
+	loadmodel->lightdata = Hunk_AllocName ( l->filelen, loadname);	
+	memcpy (loadmodel->lightdata, mod_base + l->fileofs, l->filelen);
+}
+
+
+/*
+=================
+Mod_LoadVisibility
+=================
+*/
+void Mod_LoadVisibility (lump_t *l)
+{
+	if (!l->filelen)
+	{
+		loadmodel->visdata = NULL;
+		return;
+	}
+	loadmodel->visdata = Hunk_AllocName ( l->filelen, loadname);	
+	memcpy (loadmodel->visdata, mod_base + l->fileofs, l->filelen);
+}
+
+
+/*
+=================
+Mod_LoadEntities
+=================
+*/
+void Mod_LoadEntities (lump_t *l)
+{
+	if (!l->filelen)
+	{
+		loadmodel->entities = NULL;
+		return;
+	}
+	loadmodel->entities = Hunk_AllocName ( l->filelen, loadname);	
+	memcpy (loadmodel->entities, mod_base + l->fileofs, l->filelen);
+}
+
+
+/*
+=================
+Mod_LoadVertexes
+=================
+*/
+void Mod_LoadVertexes (lump_t *l)
+{
+	dvertex_t	*in;
+	mvertex_t	*out;
+	int			i, count;
+
+	in = (void *)(mod_base + l->fileofs);
+	if (l->filelen % sizeof(*in))
+		Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
+	count = l->filelen / sizeof(*in);
+	out = Hunk_AllocName ( count*sizeof(*out), loadname);	
+
+	loadmodel->vertexes = out;
+	loadmodel->numvertexes = count;
+
+	for ( i=0 ; i<count ; i++, in++, out++)
+	{
+		out->position[0] = LittleFloat (in->point[0]);
+		out->position[1] = LittleFloat (in->point[1]);
+		out->position[2] = LittleFloat (in->point[2]);
+	}
+}
+
+/*
+=================
+Mod_LoadSubmodels
+=================
+*/
+void Mod_LoadSubmodels (lump_t *l)
+{
+	dmodel_t	*in;
+	dmodel_t	*out;
+	int			i, j, count;
+
+	in = (void *)(mod_base + l->fileofs);
+	if (l->filelen % sizeof(*in))
+		Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
+	count = l->filelen / sizeof(*in);
+	out = Hunk_AllocName ( count*sizeof(*out), loadname);	
+
+	loadmodel->submodels = out;
+	loadmodel->numsubmodels = count;
+
+	for ( i=0 ; i<count ; i++, in++, out++)
+	{
+		for (j=0 ; j<3 ; j++)
+		{	// spread the mins / maxs by a pixel
+			out->mins[j] = LittleFloat (in->mins[j]) - 1;
+			out->maxs[j] = LittleFloat (in->maxs[j]) + 1;
+			out->origin[j] = LittleFloat (in->origin[j]);
+		}
+		for (j=0 ; j<MAX_MAP_HULLS ; j++)
+			out->headnode[j] = LittleLong (in->headnode[j]);
+		out->visleafs = LittleLong (in->visleafs);
+		out->firstface = LittleLong (in->firstface);
+		out->numfaces = LittleLong (in->numfaces);
+	}
+}
+
+/*
+=================
+Mod_LoadEdges
+=================
+*/
+void Mod_LoadEdges (lump_t *l)
+{
+	dedge_t *in;
+	medge_t *out;
+	int 	i, count;
+
+	in = (void *)(mod_base + l->fileofs);
+	if (l->filelen % sizeof(*in))
+		Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
+	count = l->filelen / sizeof(*in);
+	out = Hunk_AllocName ( (count + 1) * sizeof(*out), loadname);	
+
+	loadmodel->edges = out;
+	loadmodel->numedges = count;
+
+	for ( i=0 ; i<count ; i++, in++, out++)
+	{
+		out->v[0] = (unsigned short)LittleShort(in->v[0]);
+		out->v[1] = (unsigned short)LittleShort(in->v[1]);
+	}
+}
+
+/*
+=================
+Mod_LoadTexinfo
+=================
+*/
+void Mod_LoadTexinfo (lump_t *l)
+{
+	texinfo_t *in;
+	mtexinfo_t *out;
+	int 	i, j, count;
+	int		miptex;
+	float	len1, len2;
+
+	in = (void *)(mod_base + l->fileofs);
+	if (l->filelen % sizeof(*in))
+		Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
+	count = l->filelen / sizeof(*in);
+	out = Hunk_AllocName ( count*sizeof(*out), loadname);	
+
+	loadmodel->texinfo = out;
+	loadmodel->numtexinfo = count;
+
+	for ( i=0 ; i<count ; i++, in++, out++)
+	{
+		for (j=0 ; j<8 ; j++)
+			out->vecs[0][j] = LittleFloat (in->vecs[0][j]);
+		len1 = Length (out->vecs[0]);
+		len2 = Length (out->vecs[1]);
+		len1 = (len1 + len2)/2;
+		if (len1 < 0.32)
+			out->mipadjust = 4;
+		else if (len1 < 0.49)
+			out->mipadjust = 3;
+		else if (len1 < 0.99)
+			out->mipadjust = 2;
+		else
+			out->mipadjust = 1;
+#if 0
+		if (len1 + len2 < 0.001)
+			out->mipadjust = 1;		// don't crash
+		else
+			out->mipadjust = 1 / floor( (len1+len2)/2 + 0.1 );
+#endif
+
+		miptex = LittleLong (in->miptex);
+		out->flags = LittleLong (in->flags);
+	
+		if (!loadmodel->textures)
+		{
+			out->texture = r_notexture_mip;	// checkerboard texture
+			out->flags = 0;
+		}
+		else
+		{
+			if (miptex >= loadmodel->numtextures)
+				Sys_Error ("miptex >= loadmodel->numtextures");
+			out->texture = loadmodel->textures[miptex];
+			if (!out->texture)
+			{
+				out->texture = r_notexture_mip; // texture not found
+				out->flags = 0;
+			}
+		}
+	}
+}
+
+/*
+================
+CalcSurfaceExtents
+
+Fills in s->texturemins[] and s->extents[]
+================
+*/
+void CalcSurfaceExtents (msurface_t *s)
+{
+	float	mins[2], maxs[2], val;
+	int		i,j, e;
+	mvertex_t	*v;
+	mtexinfo_t	*tex;
+	int		bmins[2], bmaxs[2];
+
+	mins[0] = mins[1] = 999999;
+	maxs[0] = maxs[1] = -99999;
+
+	tex = s->texinfo;
+	
+	for (i=0 ; i<s->numedges ; i++)
+	{
+		e = loadmodel->surfedges[s->firstedge+i];
+		if (e >= 0)
+			v = &loadmodel->vertexes[loadmodel->edges[e].v[0]];
+		else
+			v = &loadmodel->vertexes[loadmodel->edges[-e].v[1]];
+		
+		for (j=0 ; j<2 ; j++)
+		{
+			val = v->position[0] * tex->vecs[j][0] + 
+				v->position[1] * tex->vecs[j][1] +
+				v->position[2] * tex->vecs[j][2] +
+				tex->vecs[j][3];
+			if (val < mins[j])
+				mins[j] = val;
+			if (val > maxs[j])
+				maxs[j] = val;
+		}
+	}
+
+	for (i=0 ; i<2 ; i++)
+	{	
+		bmins[i] = floor(mins[i]/16);
+		bmaxs[i] = ceil(maxs[i]/16);
+
+		s->texturemins[i] = bmins[i] * 16;
+		s->extents[i] = (bmaxs[i] - bmins[i]) * 16;
+		if ( !(tex->flags & TEX_SPECIAL) && s->extents[i] > 512 /* 256 */ )
+			Sys_Error ("Bad surface extents");
+	}
+}
+
+
+/*
+=================
+Mod_LoadFaces
+=================
+*/
+void Mod_LoadFaces (lump_t *l)
+{
+	dface_t		*in;
+	msurface_t 	*out;
+	int			i, count, surfnum;
+	int			planenum, side;
+
+	in = (void *)(mod_base + l->fileofs);
+	if (l->filelen % sizeof(*in))
+		Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
+	count = l->filelen / sizeof(*in);
+	out = Hunk_AllocName ( count*sizeof(*out), loadname);	
+
+	loadmodel->surfaces = out;
+	loadmodel->numsurfaces = count;
+
+	for ( surfnum=0 ; surfnum<count ; surfnum++, in++, out++)
+	{
+		out->firstedge = LittleLong(in->firstedge);
+		out->numedges = LittleShort(in->numedges);		
+		out->flags = 0;
+
+		planenum = LittleShort(in->planenum);
+		side = LittleShort(in->side);
+		if (side)
+			out->flags |= SURF_PLANEBACK;			
+
+		out->plane = loadmodel->planes + planenum;
+
+		out->texinfo = loadmodel->texinfo + LittleShort (in->texinfo);
+
+		CalcSurfaceExtents (out);
+				
+	// lighting info
+
+		for (i=0 ; i<MAXLIGHTMAPS ; i++)
+			out->styles[i] = in->styles[i];
+		i = LittleLong(in->lightofs);
+		if (i == -1)
+			out->samples = NULL;
+		else
+			out->samples = loadmodel->lightdata + i;
+		
+	// set the drawing flags flag
+		
+		if (!Q_strncmp(out->texinfo->texture->name,"sky",3))	// sky
+		{
+			out->flags |= (SURF_DRAWSKY | SURF_DRAWTILED);
+#ifndef QUAKE2
+			GL_SubdivideSurface (out);	// cut up polygon for warps
+#endif
+			continue;
+		}
+		
+		if (!Q_strncmp(out->texinfo->texture->name,"*",1))		// turbulent
+		{
+			out->flags |= (SURF_DRAWTURB | SURF_DRAWTILED);
+			for (i=0 ; i<2 ; i++)
+			{
+				out->extents[i] = 16384;
+				out->texturemins[i] = -8192;
+			}
+			GL_SubdivideSurface (out);	// cut up polygon for warps
+			continue;
+		}
+
+	}
+}
+
+
+/*
+=================
+Mod_SetParent
+=================
+*/
+void Mod_SetParent (mnode_t *node, mnode_t *parent)
+{
+	node->parent = parent;
+	if (node->contents < 0)
+		return;
+	Mod_SetParent (node->children[0], node);
+	Mod_SetParent (node->children[1], node);
+}
+
+/*
+=================
+Mod_LoadNodes
+=================
+*/
+void Mod_LoadNodes (lump_t *l)
+{
+	int			i, j, count, p;
+	dnode_t		*in;
+	mnode_t 	*out;
+
+	in = (void *)(mod_base + l->fileofs);
+	if (l->filelen % sizeof(*in))
+		Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
+	count = l->filelen / sizeof(*in);
+	out = Hunk_AllocName ( count*sizeof(*out), loadname);	
+
+	loadmodel->nodes = out;
+	loadmodel->numnodes = count;
+
+	for ( i=0 ; i<count ; i++, in++, out++)
+	{
+		for (j=0 ; j<3 ; j++)
+		{
+			out->minmaxs[j] = LittleShort (in->mins[j]);
+			out->minmaxs[3+j] = LittleShort (in->maxs[j]);
+		}
+	
+		p = LittleLong(in->planenum);
+		out->plane = loadmodel->planes + p;
+
+		out->firstsurface = LittleShort (in->firstface);
+		out->numsurfaces = LittleShort (in->numfaces);
+		
+		for (j=0 ; j<2 ; j++)
+		{
+			p = LittleShort (in->children[j]);
+			if (p >= 0)
+				out->children[j] = loadmodel->nodes + p;
+			else
+				out->children[j] = (mnode_t *)(loadmodel->leafs + (-1 - p));
+		}
+	}
+	
+	Mod_SetParent (loadmodel->nodes, NULL);	// sets nodes and leafs
+}
+
+/*
+=================
+Mod_LoadLeafs
+=================
+*/
+void Mod_LoadLeafs (lump_t *l)
+{
+	dleaf_t 	*in;
+	mleaf_t 	*out;
+	int			i, j, count, p;
+
+	in = (void *)(mod_base + l->fileofs);
+	if (l->filelen % sizeof(*in))
+		Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
+	count = l->filelen / sizeof(*in);
+	out = Hunk_AllocName ( count*sizeof(*out), loadname);	
+
+	loadmodel->leafs = out;
+	loadmodel->numleafs = count;
+
+	for ( i=0 ; i<count ; i++, in++, out++)
+	{
+		for (j=0 ; j<3 ; j++)
+		{
+			out->minmaxs[j] = LittleShort (in->mins[j]);
+			out->minmaxs[3+j] = LittleShort (in->maxs[j]);
+		}
+
+		p = LittleLong(in->contents);
+		out->contents = p;
+
+		out->firstmarksurface = loadmodel->marksurfaces +
+			LittleShort(in->firstmarksurface);
+		out->nummarksurfaces = LittleShort(in->nummarksurfaces);
+		
+		p = LittleLong(in->visofs);
+		if (p == -1)
+			out->compressed_vis = NULL;
+		else
+			out->compressed_vis = loadmodel->visdata + p;
+		out->efrags = NULL;
+		
+		for (j=0 ; j<4 ; j++)
+			out->ambient_sound_level[j] = in->ambient_level[j];
+
+		// gl underwater warp
+		if (out->contents != CONTENTS_EMPTY)
+		{
+			for (j=0 ; j<out->nummarksurfaces ; j++)
+				out->firstmarksurface[j]->flags |= SURF_UNDERWATER;
+		}
+	}	
+}
+
+/*
+=================
+Mod_LoadClipnodes
+=================
+*/
+void Mod_LoadClipnodes (lump_t *l)
+{
+	dclipnode_t *in, *out;
+	int			i, count;
+	hull_t		*hull;
+
+	in = (void *)(mod_base + l->fileofs);
+	if (l->filelen % sizeof(*in))
+		Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
+	count = l->filelen / sizeof(*in);
+	out = Hunk_AllocName ( count*sizeof(*out), loadname);	
+
+	loadmodel->clipnodes = out;
+	loadmodel->numclipnodes = count;
+
+	hull = &loadmodel->hulls[1];
+	hull->clipnodes = out;
+	hull->firstclipnode = 0;
+	hull->lastclipnode = count-1;
+	hull->planes = loadmodel->planes;
+	hull->clip_mins[0] = -16;
+	hull->clip_mins[1] = -16;
+	hull->clip_mins[2] = -24;
+	hull->clip_maxs[0] = 16;
+	hull->clip_maxs[1] = 16;
+	hull->clip_maxs[2] = 32;
+
+	hull = &loadmodel->hulls[2];
+	hull->clipnodes = out;
+	hull->firstclipnode = 0;
+	hull->lastclipnode = count-1;
+	hull->planes = loadmodel->planes;
+	hull->clip_mins[0] = -32;
+	hull->clip_mins[1] = -32;
+	hull->clip_mins[2] = -24;
+	hull->clip_maxs[0] = 32;
+	hull->clip_maxs[1] = 32;
+	hull->clip_maxs[2] = 64;
+
+	for (i=0 ; i<count ; i++, out++, in++)
+	{
+		out->planenum = LittleLong(in->planenum);
+		out->children[0] = LittleShort(in->children[0]);
+		out->children[1] = LittleShort(in->children[1]);
+	}
+}
+
+/*
+=================
+Mod_MakeHull0
+
+Deplicate the drawing hull structure as a clipping hull
+=================
+*/
+void Mod_MakeHull0 (void)
+{
+	mnode_t		*in, *child;
+	dclipnode_t *out;
+	int			i, j, count;
+	hull_t		*hull;
+	
+	hull = &loadmodel->hulls[0];	
+	
+	in = loadmodel->nodes;
+	count = loadmodel->numnodes;
+	out = Hunk_AllocName ( count*sizeof(*out), loadname);	
+
+	hull->clipnodes = out;
+	hull->firstclipnode = 0;
+	hull->lastclipnode = count-1;
+	hull->planes = loadmodel->planes;
+
+	for (i=0 ; i<count ; i++, out++, in++)
+	{
+		out->planenum = in->plane - loadmodel->planes;
+		for (j=0 ; j<2 ; j++)
+		{
+			child = in->children[j];
+			if (child->contents < 0)
+				out->children[j] = child->contents;
+			else
+				out->children[j] = child - loadmodel->nodes;
+		}
+	}
+}
+
+/*
+=================
+Mod_LoadMarksurfaces
+=================
+*/
+void Mod_LoadMarksurfaces (lump_t *l)
+{	
+	int		i, j, count;
+	short		*in;
+	msurface_t **out;
+	
+	in = (void *)(mod_base + l->fileofs);
+	if (l->filelen % sizeof(*in))
+		Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
+	count = l->filelen / sizeof(*in);
+	out = Hunk_AllocName ( count*sizeof(*out), loadname);	
+
+	loadmodel->marksurfaces = out;
+	loadmodel->nummarksurfaces = count;
+
+	for ( i=0 ; i<count ; i++)
+	{
+		j = LittleShort(in[i]);
+		if (j >= loadmodel->numsurfaces)
+			Sys_Error ("Mod_ParseMarksurfaces: bad surface number");
+		out[i] = loadmodel->surfaces + j;
+	}
+}
+
+/*
+=================
+Mod_LoadSurfedges
+=================
+*/
+void Mod_LoadSurfedges (lump_t *l)
+{	
+	int		i, count;
+	int		*in, *out;
+	
+	in = (void *)(mod_base + l->fileofs);
+	if (l->filelen % sizeof(*in))
+		Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
+	count = l->filelen / sizeof(*in);
+	out = Hunk_AllocName ( count*sizeof(*out), loadname);	
+
+	loadmodel->surfedges = out;
+	loadmodel->numsurfedges = count;
+
+	for ( i=0 ; i<count ; i++)
+		out[i] = LittleLong (in[i]);
+}
+
+
+/*
+=================
+Mod_LoadPlanes
+=================
+*/
+void Mod_LoadPlanes (lump_t *l)
+{
+	int			i, j;
+	mplane_t	*out;
+	dplane_t 	*in;
+	int			count;
+	int			bits;
+	
+	in = (void *)(mod_base + l->fileofs);
+	if (l->filelen % sizeof(*in))
+		Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
+	count = l->filelen / sizeof(*in);
+	out = Hunk_AllocName ( count*2*sizeof(*out), loadname);	
+	
+	loadmodel->planes = out;
+	loadmodel->numplanes = count;
+
+	for ( i=0 ; i<count ; i++, in++, out++)
+	{
+		bits = 0;
+		for (j=0 ; j<3 ; j++)
+		{
+			out->normal[j] = LittleFloat (in->normal[j]);
+			if (out->normal[j] < 0)
+				bits |= 1<<j;
+		}
+
+		out->dist = LittleFloat (in->dist);
+		out->type = LittleLong (in->type);
+		out->signbits = bits;
+	}
+}
+
+/*
+=================
+RadiusFromBounds
+=================
+*/
+float RadiusFromBounds (vec3_t mins, vec3_t maxs)
+{
+	int		i;
+	vec3_t	corner;
+
+	for (i=0 ; i<3 ; i++)
+	{
+		corner[i] = fabs(mins[i]) > fabs(maxs[i]) ? fabs(mins[i]) : fabs(maxs[i]);
+	}
+
+	return Length (corner);
+}
+
+/*
+=================
+Mod_LoadBrushModel
+=================
+*/
+void Mod_LoadBrushModel (model_t *mod, void *buffer)
+{
+	int			i, j;
+	dheader_t	*header;
+	dmodel_t 	*bm;
+	
+	loadmodel->type = mod_brush;
+	
+	header = (dheader_t *)buffer;
+
+	i = LittleLong (header->version);
+	if (i != BSPVERSION)
+		Sys_Error ("Mod_LoadBrushModel: %s has wrong version number (%i should be %i)", mod->name, i, BSPVERSION);
+
+// swap all the lumps
+	mod_base = (byte *)header;
+
+	for (i=0 ; i<sizeof(dheader_t)/4 ; i++)
+		((int *)header)[i] = LittleLong ( ((int *)header)[i]);
+
+// load into heap
+	
+	Mod_LoadVertexes (&header->lumps[LUMP_VERTEXES]);
+	Mod_LoadEdges (&header->lumps[LUMP_EDGES]);
+	Mod_LoadSurfedges (&header->lumps[LUMP_SURFEDGES]);
+	Mod_LoadTextures (&header->lumps[LUMP_TEXTURES]);
+	Mod_LoadLighting (&header->lumps[LUMP_LIGHTING]);
+	Mod_LoadPlanes (&header->lumps[LUMP_PLANES]);
+	Mod_LoadTexinfo (&header->lumps[LUMP_TEXINFO]);
+	Mod_LoadFaces (&header->lumps[LUMP_FACES]);
+	Mod_LoadMarksurfaces (&header->lumps[LUMP_MARKSURFACES]);
+	Mod_LoadVisibility (&header->lumps[LUMP_VISIBILITY]);
+	Mod_LoadLeafs (&header->lumps[LUMP_LEAFS]);
+	Mod_LoadNodes (&header->lumps[LUMP_NODES]);
+	Mod_LoadClipnodes (&header->lumps[LUMP_CLIPNODES]);
+	Mod_LoadEntities (&header->lumps[LUMP_ENTITIES]);
+	Mod_LoadSubmodels (&header->lumps[LUMP_MODELS]);
+
+	Mod_MakeHull0 ();
+	
+	mod->numframes = 2;		// regular and alternate animation
+	
+//
+// set up the submodels (FIXME: this is confusing)
+//
+	for (i=0 ; i<mod->numsubmodels ; i++)
+	{
+		bm = &mod->submodels[i];
+
+		mod->hulls[0].firstclipnode = bm->headnode[0];
+		for (j=1 ; j<MAX_MAP_HULLS ; j++)
+		{
+			mod->hulls[j].firstclipnode = bm->headnode[j];
+			mod->hulls[j].lastclipnode = mod->numclipnodes-1;
+		}
+		
+		mod->firstmodelsurface = bm->firstface;
+		mod->nummodelsurfaces = bm->numfaces;
+		
+		VectorCopy (bm->maxs, mod->maxs);
+		VectorCopy (bm->mins, mod->mins);
+
+		mod->radius = RadiusFromBounds (mod->mins, mod->maxs);
+
+		mod->numleafs = bm->visleafs;
+
+		if (i < mod->numsubmodels-1)
+		{	// duplicate the basic information
+			char	name[10];
+
+			sprintf (name, "*%i", i+1);
+			loadmodel = Mod_FindName (name);
+			*loadmodel = *mod;
+			strcpy (loadmodel->name, name);
+			mod = loadmodel;
+		}
+	}
+}
+
+/*
+==============================================================================
+
+ALIAS MODELS
+
+==============================================================================
+*/
+
+aliashdr_t	*pheader;
+
+stvert_t	stverts[MAXALIASVERTS];
+mtriangle_t	triangles[MAXALIASTRIS];
+
+// a pose is a single set of vertexes.  a frame may be
+// an animating sequence of poses
+trivertx_t	*poseverts[MAXALIASFRAMES];
+int			posenum;
+
+byte		**player_8bit_texels_tbl;
+byte		*player_8bit_texels;
+
+/*
+=================
+Mod_LoadAliasFrame
+=================
+*/
+void * Mod_LoadAliasFrame (void * pin, maliasframedesc_t *frame)
+{
+	trivertx_t		*pframe, *pinframe;
+	int				i, j;
+	daliasframe_t	*pdaliasframe;
+	
+	pdaliasframe = (daliasframe_t *)pin;
+
+	strcpy (frame->name, pdaliasframe->name);
+	frame->firstpose = posenum;
+	frame->numposes = 1;
+
+	for (i=0 ; i<3 ; i++)
+	{
+	// these are byte values, so we don't have to worry about
+	// endianness
+		frame->bboxmin.v[i] = pdaliasframe->bboxmin.v[i];
+		frame->bboxmin.v[i] = pdaliasframe->bboxmax.v[i];
+	}
+
+	pinframe = (trivertx_t *)(pdaliasframe + 1);
+
+	poseverts[posenum] = pinframe;
+	posenum++;
+
+	pinframe += pheader->numverts;
+
+	return (void *)pinframe;
+}
+
+
+/*
+=================
+Mod_LoadAliasGroup
+=================
+*/
+void *Mod_LoadAliasGroup (void * pin,  maliasframedesc_t *frame)
+{
+	daliasgroup_t		*pingroup;
+	int					i, numframes;
+	daliasinterval_t	*pin_intervals;
+	void				*ptemp;
+	
+	pingroup = (daliasgroup_t *)pin;
+
+	numframes = LittleLong (pingroup->numframes);
+
+	frame->firstpose = posenum;
+	frame->numposes = numframes;
+
+	for (i=0 ; i<3 ; i++)
+	{
+	// these are byte values, so we don't have to worry about endianness
+		frame->bboxmin.v[i] = pingroup->bboxmin.v[i];
+		frame->bboxmin.v[i] = pingroup->bboxmax.v[i];
+	}
+
+	pin_intervals = (daliasinterval_t *)(pingroup + 1);
+
+	frame->interval = LittleFloat (pin_intervals->interval);
+
+	pin_intervals += numframes;
+
+	ptemp = (void *)pin_intervals;
+
+	for (i=0 ; i<numframes ; i++)
+	{
+		poseverts[posenum] = (trivertx_t *)((daliasframe_t *)ptemp + 1);
+		posenum++;
+
+		ptemp = (trivertx_t *)((daliasframe_t *)ptemp + 1) + pheader->numverts;
+	}
+
+	return ptemp;
+}
+
+//=========================================================
+
+/*
+=================
+Mod_FloodFillSkin
+
+Fill background pixels so mipmapping doesn't have haloes - Ed
+=================
+*/
+
+typedef struct
+{
+	short		x, y;
+} floodfill_t;
+
+extern unsigned d_8to24table[];
+
+// must be a power of 2
+#define FLOODFILL_FIFO_SIZE 0x1000
+#define FLOODFILL_FIFO_MASK (FLOODFILL_FIFO_SIZE - 1)
+
+#define FLOODFILL_STEP( off, dx, dy ) \
+{ \
+	if (pos[off] == fillcolor) \
+	{ \
+		pos[off] = 255; \
+		fifo[inpt].x = x + (dx), fifo[inpt].y = y + (dy); \
+		inpt = (inpt + 1) & FLOODFILL_FIFO_MASK; \
+	} \
+	else if (pos[off] != 255) fdc = pos[off]; \
+}
+
+void Mod_FloodFillSkin( byte *skin, int skinwidth, int skinheight )
+{
+	byte				fillcolor = *skin; // assume this is the pixel to fill
+	floodfill_t			fifo[FLOODFILL_FIFO_SIZE];
+	int					inpt = 0, outpt = 0;
+	int					filledcolor = -1;
+	int					i;
+
+	if (filledcolor == -1)
+	{
+		filledcolor = 0;
+		// attempt to find opaque black
+		for (i = 0; i < 256; ++i)
+			if (d_8to24table[i] == (255 << 0)) // alpha 1.0
+			{
+				filledcolor = i;
+				break;
+			}
+	}
+
+	// can't fill to filled color or to transparent color (used as visited marker)
+	if ((fillcolor == filledcolor) || (fillcolor == 255))
+	{
+		//printf( "not filling skin from %d to %d\n", fillcolor, filledcolor );
+		return;
+	}
+
+	fifo[inpt].x = 0, fifo[inpt].y = 0;
+	inpt = (inpt + 1) & FLOODFILL_FIFO_MASK;
+
+	while (outpt != inpt)
+	{
+		int			x = fifo[outpt].x, y = fifo[outpt].y;
+		int			fdc = filledcolor;
+		byte		*pos = &skin[x + skinwidth * y];
+
+		outpt = (outpt + 1) & FLOODFILL_FIFO_MASK;
+
+		if (x > 0)				FLOODFILL_STEP( -1, -1, 0 );
+		if (x < skinwidth - 1)	FLOODFILL_STEP( 1, 1, 0 );
+		if (y > 0)				FLOODFILL_STEP( -skinwidth, 0, -1 );
+		if (y < skinheight - 1)	FLOODFILL_STEP( skinwidth, 0, 1 );
+		skin[x + skinwidth * y] = fdc;
+	}
+}
+
+/*
+===============
+Mod_LoadAllSkins
+===============
+*/
+void *Mod_LoadAllSkins (int numskins, daliasskintype_t *pskintype)
+{
+	int		i, j, k;
+	char	name[32];
+	int		s;
+	byte	*copy;
+	byte	*skin;
+	byte	*texels;
+	daliasskingroup_t		*pinskingroup;
+	int		groupskins;
+	daliasskininterval_t	*pinskinintervals;
+	
+	skin = (byte *)(pskintype + 1);
+
+	if (numskins < 1 || numskins > MAX_SKINS)
+		Sys_Error ("Mod_LoadAliasModel: Invalid # of skins: %d\n", numskins);
+
+	s = pheader->skinwidth * pheader->skinheight;
+
+	for (i=0 ; i<numskins ; i++)
+	{
+		if (pskintype->type == ALIAS_SKIN_SINGLE) {
+			Mod_FloodFillSkin( skin, pheader->skinwidth, pheader->skinheight );
+
+			// save 8 bit texels for the player model to remap
+	//		if (!strcmp(loadmodel->name,"progs/player.mdl")) {
+				texels = Hunk_AllocName(s, loadname);
+				pheader->texels[i] = texels - (byte *)pheader;
+				memcpy (texels, (byte *)(pskintype + 1), s);
+	//		}
+			sprintf (name, "%s_%i", loadmodel->name, i);
+			pheader->gl_texturenum[i][0] =
+			pheader->gl_texturenum[i][1] =
+			pheader->gl_texturenum[i][2] =
+			pheader->gl_texturenum[i][3] =
+				GL_LoadTexture (name, pheader->skinwidth, 
+				pheader->skinheight, (byte *)(pskintype + 1), true, false);
+			pskintype = (daliasskintype_t *)((byte *)(pskintype+1) + s);
+		} else {
+			// animating skin group.  yuck.
+			pskintype++;
+			pinskingroup = (daliasskingroup_t *)pskintype;
+			groupskins = LittleLong (pinskingroup->numskins);
+			pinskinintervals = (daliasskininterval_t *)(pinskingroup + 1);
+
+			pskintype = (void *)(pinskinintervals + groupskins);
+
+			for (j=0 ; j<groupskins ; j++)
+			{
+					Mod_FloodFillSkin( skin, pheader->skinwidth, pheader->skinheight );
+					if (j == 0) {
+						texels = Hunk_AllocName(s, loadname);
+						pheader->texels[i] = texels - (byte *)pheader;
+						memcpy (texels, (byte *)(pskintype), s);
+					}
+					sprintf (name, "%s_%i_%i", loadmodel->name, i,j);
+					pheader->gl_texturenum[i][j&3] = 
+						GL_LoadTexture (name, pheader->skinwidth, 
+						pheader->skinheight, (byte *)(pskintype), true, false);
+					pskintype = (daliasskintype_t *)((byte *)(pskintype) + s);
+			}
+			k = j;
+			for (/* */; j < 4; j++)
+				pheader->gl_texturenum[i][j&3] = 
+				pheader->gl_texturenum[i][j - k]; 
+		}
+	}
+
+	return (void *)pskintype;
+}
+
+//=========================================================================
+
+/*
+=================
+Mod_LoadAliasModel
+=================
+*/
+void Mod_LoadAliasModel (model_t *mod, void *buffer)
+{
+	int					i, j;
+	mdl_t				*pinmodel;
+	stvert_t			*pinstverts;
+	dtriangle_t			*pintriangles;
+	int					version, numframes, numskins;
+	int					size;
+	daliasframetype_t	*pframetype;
+	daliasskintype_t	*pskintype;
+	int					start, end, total;
+	
+	start = Hunk_LowMark ();
+
+	pinmodel = (mdl_t *)buffer;
+
+	version = LittleLong (pinmodel->version);
+	if (version != ALIAS_VERSION)
+		Sys_Error ("%s has wrong version number (%i should be %i)",
+				 mod->name, version, ALIAS_VERSION);
+
+//
+// allocate space for a working header, plus all the data except the frames,
+// skin and group info
+//
+	size = 	sizeof (aliashdr_t) 
+			+ (LittleLong (pinmodel->numframes) - 1) *
+			sizeof (pheader->frames[0]);
+	pheader = Hunk_AllocName (size, loadname);
+	
+	mod->flags = LittleLong (pinmodel->flags);
+
+//
+// endian-adjust and copy the data, starting with the alias model header
+//
+	pheader->boundingradius = LittleFloat (pinmodel->boundingradius);
+	pheader->numskins = LittleLong (pinmodel->numskins);
+	pheader->skinwidth = LittleLong (pinmodel->skinwidth);
+	pheader->skinheight = LittleLong (pinmodel->skinheight);
+
+	if (pheader->skinheight > MAX_LBM_HEIGHT)
+		Sys_Error ("model %s has a skin taller than %d", mod->name,
+				   MAX_LBM_HEIGHT);
+
+	pheader->numverts = LittleLong (pinmodel->numverts);
+
+	if (pheader->numverts <= 0)
+		Sys_Error ("model %s has no vertices", mod->name);
+
+	if (pheader->numverts > MAXALIASVERTS)
+		Sys_Error ("model %s has too many vertices", mod->name);
+
+	pheader->numtris = LittleLong (pinmodel->numtris);
+
+	if (pheader->numtris <= 0)
+		Sys_Error ("model %s has no triangles", mod->name);
+
+	pheader->numframes = LittleLong (pinmodel->numframes);
+	numframes = pheader->numframes;
+	if (numframes < 1)
+		Sys_Error ("Mod_LoadAliasModel: Invalid # of frames: %d\n", numframes);
+
+	pheader->size = LittleFloat (pinmodel->size) * ALIAS_BASE_SIZE_RATIO;
+	mod->synctype = LittleLong (pinmodel->synctype);
+	mod->numframes = pheader->numframes;
+
+	for (i=0 ; i<3 ; i++)
+	{
+		pheader->scale[i] = LittleFloat (pinmodel->scale[i]);
+		pheader->scale_origin[i] = LittleFloat (pinmodel->scale_origin[i]);
+		pheader->eyeposition[i] = LittleFloat (pinmodel->eyeposition[i]);
+	}
+
+
+//
+// load the skins
+//
+	pskintype = (daliasskintype_t *)&pinmodel[1];
+	pskintype = Mod_LoadAllSkins (pheader->numskins, pskintype);
+
+//
+// load base s and t vertices
+//
+	pinstverts = (stvert_t *)pskintype;
+
+	for (i=0 ; i<pheader->numverts ; i++)
+	{
+		stverts[i].onseam = LittleLong (pinstverts[i].onseam);
+		stverts[i].s = LittleLong (pinstverts[i].s);
+		stverts[i].t = LittleLong (pinstverts[i].t);
+	}
+
+//
+// load triangle lists
+//
+	pintriangles = (dtriangle_t *)&pinstverts[pheader->numverts];
+
+	for (i=0 ; i<pheader->numtris ; i++)
+	{
+		triangles[i].facesfront = LittleLong (pintriangles[i].facesfront);
+
+		for (j=0 ; j<3 ; j++)
+		{
+			triangles[i].vertindex[j] =
+					LittleLong (pintriangles[i].vertindex[j]);
+		}
+	}
+
+//
+// load the frames
+//
+	posenum = 0;
+	pframetype = (daliasframetype_t *)&pintriangles[pheader->numtris];
+
+	for (i=0 ; i<numframes ; i++)
+	{
+		aliasframetype_t	frametype;
+
+		frametype = LittleLong (pframetype->type);
+
+		if (frametype == ALIAS_SINGLE)
+		{
+			pframetype = (daliasframetype_t *)
+					Mod_LoadAliasFrame (pframetype + 1, &pheader->frames[i]);
+		}
+		else
+		{
+			pframetype = (daliasframetype_t *)
+					Mod_LoadAliasGroup (pframetype + 1, &pheader->frames[i]);
+		}
+	}
+
+	pheader->numposes = posenum;
+
+	mod->type = mod_alias;
+
+// FIXME: do this right
+	mod->mins[0] = mod->mins[1] = mod->mins[2] = -16;
+	mod->maxs[0] = mod->maxs[1] = mod->maxs[2] = 16;
+
+	//
+	// build the draw lists
+	//
+	GL_MakeAliasModelDisplayLists (mod, pheader);
+
+//
+// move the complete, relocatable alias model to the cache
+//	
+	end = Hunk_LowMark ();
+	total = end - start;
+	
+	Cache_Alloc (&mod->cache, total, loadname);
+	if (!mod->cache.data)
+		return;
+	memcpy (mod->cache.data, pheader, total);
+
+	Hunk_FreeToLowMark (start);
+}
+
+//=============================================================================
+
+/*
+=================
+Mod_LoadSpriteFrame
+=================
+*/
+void * Mod_LoadSpriteFrame (void * pin, mspriteframe_t **ppframe, int framenum)
+{
+	dspriteframe_t		*pinframe;
+	mspriteframe_t		*pspriteframe;
+	int					i, width, height, size, origin[2];
+	unsigned short		*ppixout;
+	byte				*ppixin;
+	char				name[64];
+
+	pinframe = (dspriteframe_t *)pin;
+
+	width = LittleLong (pinframe->width);
+	height = LittleLong (pinframe->height);
+	size = width * height;
+
+	pspriteframe = Hunk_AllocName (sizeof (mspriteframe_t),loadname);
+
+	Q_memset (pspriteframe, 0, sizeof (mspriteframe_t));
+
+	*ppframe = pspriteframe;
+
+	pspriteframe->width = width;
+	pspriteframe->height = height;
+	origin[0] = LittleLong (pinframe->origin[0]);
+	origin[1] = LittleLong (pinframe->origin[1]);
+
+	pspriteframe->up = origin[1];
+	pspriteframe->down = origin[1] - height;
+	pspriteframe->left = origin[0];
+	pspriteframe->right = width + origin[0];
+
+	sprintf (name, "%s_%i", loadmodel->name, framenum);
+	pspriteframe->gl_texturenum = GL_LoadTexture (name, width, height, (byte *)(pinframe + 1), true, true);
+
+	return (void *)((byte *)pinframe + sizeof (dspriteframe_t) + size);
+}
+
+
+/*
+=================
+Mod_LoadSpriteGroup
+=================
+*/
+void * Mod_LoadSpriteGroup (void * pin, mspriteframe_t **ppframe, int framenum)
+{
+	dspritegroup_t		*pingroup;
+	mspritegroup_t		*pspritegroup;
+	int					i, numframes;
+	dspriteinterval_t	*pin_intervals;
+	float				*poutintervals;
+	void				*ptemp;
+
+	pingroup = (dspritegroup_t *)pin;
+
+	numframes = LittleLong (pingroup->numframes);
+
+	pspritegroup = Hunk_AllocName (sizeof (mspritegroup_t) +
+				(numframes - 1) * sizeof (pspritegroup->frames[0]), loadname);
+
+	pspritegroup->numframes = numframes;
+
+	*ppframe = (mspriteframe_t *)pspritegroup;
+
+	pin_intervals = (dspriteinterval_t *)(pingroup + 1);
+
+	poutintervals = Hunk_AllocName (numframes * sizeof (float), loadname);
+
+	pspritegroup->intervals = poutintervals;
+
+	for (i=0 ; i<numframes ; i++)
+	{
+		*poutintervals = LittleFloat (pin_intervals->interval);
+		if (*poutintervals <= 0.0)
+			Sys_Error ("Mod_LoadSpriteGroup: interval<=0");
+
+		poutintervals++;
+		pin_intervals++;
+	}
+
+	ptemp = (void *)pin_intervals;
+
+	for (i=0 ; i<numframes ; i++)
+	{
+		ptemp = Mod_LoadSpriteFrame (ptemp, &pspritegroup->frames[i], framenum * 100 + i);
+	}
+
+	return ptemp;
+}
+
+
+/*
+=================
+Mod_LoadSpriteModel
+=================
+*/
+void Mod_LoadSpriteModel (model_t *mod, void *buffer)
+{
+	int					i;
+	int					version;
+	dsprite_t			*pin;
+	msprite_t			*psprite;
+	int					numframes;
+	int					size;
+	dspriteframetype_t	*pframetype;
+	
+	pin = (dsprite_t *)buffer;
+
+	version = LittleLong (pin->version);
+	if (version != SPRITE_VERSION)
+		Sys_Error ("%s has wrong version number "
+				 "(%i should be %i)", mod->name, version, SPRITE_VERSION);
+
+	numframes = LittleLong (pin->numframes);
+
+	size = sizeof (msprite_t) +	(numframes - 1) * sizeof (psprite->frames);
+
+	psprite = Hunk_AllocName (size, loadname);
+
+	mod->cache.data = psprite;
+
+	psprite->type = LittleLong (pin->type);
+	psprite->maxwidth = LittleLong (pin->width);
+	psprite->maxheight = LittleLong (pin->height);
+	psprite->beamlength = LittleFloat (pin->beamlength);
+	mod->synctype = LittleLong (pin->synctype);
+	psprite->numframes = numframes;
+
+	mod->mins[0] = mod->mins[1] = -psprite->maxwidth/2;
+	mod->maxs[0] = mod->maxs[1] = psprite->maxwidth/2;
+	mod->mins[2] = -psprite->maxheight/2;
+	mod->maxs[2] = psprite->maxheight/2;
+	
+//
+// load the frames
+//
+	if (numframes < 1)
+		Sys_Error ("Mod_LoadSpriteModel: Invalid # of frames: %d\n", numframes);
+
+	mod->numframes = numframes;
+
+	pframetype = (dspriteframetype_t *)(pin + 1);
+
+	for (i=0 ; i<numframes ; i++)
+	{
+		spriteframetype_t	frametype;
+
+		frametype = LittleLong (pframetype->type);
+		psprite->frames[i].type = frametype;
+
+		if (frametype == SPR_SINGLE)
+		{
+			pframetype = (dspriteframetype_t *)
+					Mod_LoadSpriteFrame (pframetype + 1,
+										 &psprite->frames[i].frameptr, i);
+		}
+		else
+		{
+			pframetype = (dspriteframetype_t *)
+					Mod_LoadSpriteGroup (pframetype + 1,
+										 &psprite->frames[i].frameptr, i);
+		}
+	}
+
+	mod->type = mod_sprite;
+}
+
+//=============================================================================
+
+/*
+================
+Mod_Print
+================
+*/
+void Mod_Print (void)
+{
+	int		i;
+	model_t	*mod;
+
+	Con_Printf ("Cached models:\n");
+	for (i=0, mod=mod_known ; i < mod_numknown ; i++, mod++)
+	{
+		Con_Printf ("%8p : %s\n",mod->cache.data, mod->name);
+	}
+}
+
+
--- /dev/null
+++ b/WinQuake/gl_model.h
@@ -1,0 +1,430 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+
+#ifndef __MODEL__
+#define __MODEL__
+
+#include "modelgen.h"
+#include "spritegn.h"
+
+/*
+
+d*_t structures are on-disk representations
+m*_t structures are in-memory
+
+*/
+
+// entity effects
+
+#define	EF_BRIGHTFIELD			1
+#define	EF_MUZZLEFLASH 			2
+#define	EF_BRIGHTLIGHT 			4
+#define	EF_DIMLIGHT 			8
+
+
+/*
+==============================================================================
+
+BRUSH MODELS
+
+==============================================================================
+*/
+
+
+//
+// in memory representation
+//
+// !!! if this is changed, it must be changed in asm_draw.h too !!!
+typedef struct
+{
+	vec3_t		position;
+} mvertex_t;
+
+#define	SIDE_FRONT	0
+#define	SIDE_BACK	1
+#define	SIDE_ON		2
+
+
+// plane_t structure
+// !!! if this is changed, it must be changed in asm_i386.h too !!!
+typedef struct mplane_s
+{
+	vec3_t	normal;
+	float	dist;
+	byte	type;			// for texture axis selection and fast side tests
+	byte	signbits;		// signx + signy<<1 + signz<<1
+	byte	pad[2];
+} mplane_t;
+
+typedef struct texture_s
+{
+	char		name[16];
+	unsigned	width, height;
+	int			gl_texturenum;
+	struct msurface_s	*texturechain;	// for gl_texsort drawing
+	int			anim_total;				// total tenths in sequence ( 0 = no)
+	int			anim_min, anim_max;		// time for this frame min <=time< max
+	struct texture_s *anim_next;		// in the animation sequence
+	struct texture_s *alternate_anims;	// bmodels in frmae 1 use these
+	unsigned	offsets[MIPLEVELS];		// four mip maps stored
+} texture_t;
+
+
+#define	SURF_PLANEBACK		2
+#define	SURF_DRAWSKY		4
+#define SURF_DRAWSPRITE		8
+#define SURF_DRAWTURB		0x10
+#define SURF_DRAWTILED		0x20
+#define SURF_DRAWBACKGROUND	0x40
+#define SURF_UNDERWATER		0x80
+
+// !!! if this is changed, it must be changed in asm_draw.h too !!!
+typedef struct
+{
+	unsigned short	v[2];
+	unsigned int	cachededgeoffset;
+} medge_t;
+
+typedef struct
+{
+	float		vecs[2][4];
+	float		mipadjust;
+	texture_t	*texture;
+	int			flags;
+} mtexinfo_t;
+
+#define	VERTEXSIZE	7
+
+typedef struct glpoly_s
+{
+	struct	glpoly_s	*next;
+	struct	glpoly_s	*chain;
+	int		numverts;
+	int		flags;			// for SURF_UNDERWATER
+	float	verts[4][VERTEXSIZE];	// variable sized (xyz s1t1 s2t2)
+} glpoly_t;
+
+typedef struct msurface_s
+{
+	int			visframe;		// should be drawn when node is crossed
+
+	mplane_t	*plane;
+	int			flags;
+
+	int			firstedge;	// look up in model->surfedges[], negative numbers
+	int			numedges;	// are backwards edges
+	
+	short		texturemins[2];
+	short		extents[2];
+
+	int			light_s, light_t;	// gl lightmap coordinates
+
+	glpoly_t	*polys;				// multiple if warped
+	struct	msurface_s	*texturechain;
+
+	mtexinfo_t	*texinfo;
+	
+// lighting info
+	int			dlightframe;
+	int			dlightbits;
+
+	int			lightmaptexturenum;
+	byte		styles[MAXLIGHTMAPS];
+	int			cached_light[MAXLIGHTMAPS];	// values currently used in lightmap
+	qboolean	cached_dlight;				// true if dynamic light in cache
+	byte		*samples;		// [numstyles*surfsize]
+} msurface_t;
+
+typedef struct mnode_s
+{
+// common with leaf
+	int			contents;		// 0, to differentiate from leafs
+	int			visframe;		// node needs to be traversed if current
+	
+	float		minmaxs[6];		// for bounding box culling
+
+	struct mnode_s	*parent;
+
+// node specific
+	mplane_t	*plane;
+	struct mnode_s	*children[2];	
+
+	unsigned short		firstsurface;
+	unsigned short		numsurfaces;
+} mnode_t;
+
+
+
+typedef struct mleaf_s
+{
+// common with node
+	int			contents;		// wil be a negative contents number
+	int			visframe;		// node needs to be traversed if current
+
+	float		minmaxs[6];		// for bounding box culling
+
+	struct mnode_s	*parent;
+
+// leaf specific
+	byte		*compressed_vis;
+	efrag_t		*efrags;
+
+	msurface_t	**firstmarksurface;
+	int			nummarksurfaces;
+	int			key;			// BSP sequence number for leaf's contents
+	byte		ambient_sound_level[NUM_AMBIENTS];
+} mleaf_t;
+
+// !!! if this is changed, it must be changed in asm_i386.h too !!!
+typedef struct
+{
+	dclipnode_t	*clipnodes;
+	mplane_t	*planes;
+	int			firstclipnode;
+	int			lastclipnode;
+	vec3_t		clip_mins;
+	vec3_t		clip_maxs;
+} hull_t;
+
+/*
+==============================================================================
+
+SPRITE MODELS
+
+==============================================================================
+*/
+
+
+// FIXME: shorten these?
+typedef struct mspriteframe_s
+{
+	int		width;
+	int		height;
+	float	up, down, left, right;
+	int		gl_texturenum;
+} mspriteframe_t;
+
+typedef struct
+{
+	int				numframes;
+	float			*intervals;
+	mspriteframe_t	*frames[1];
+} mspritegroup_t;
+
+typedef struct
+{
+	spriteframetype_t	type;
+	mspriteframe_t		*frameptr;
+} mspriteframedesc_t;
+
+typedef struct
+{
+	int					type;
+	int					maxwidth;
+	int					maxheight;
+	int					numframes;
+	float				beamlength;		// remove?
+	void				*cachespot;		// remove?
+	mspriteframedesc_t	frames[1];
+} msprite_t;
+
+
+/*
+==============================================================================
+
+ALIAS MODELS
+
+Alias models are position independent, so the cache manager can move them.
+==============================================================================
+*/
+
+typedef struct
+{
+	int					firstpose;
+	int					numposes;
+	float				interval;
+	trivertx_t			bboxmin;
+	trivertx_t			bboxmax;
+	int					frame;
+	char				name[16];
+} maliasframedesc_t;
+
+typedef struct
+{
+	trivertx_t			bboxmin;
+	trivertx_t			bboxmax;
+	int					frame;
+} maliasgroupframedesc_t;
+
+typedef struct
+{
+	int						numframes;
+	int						intervals;
+	maliasgroupframedesc_t	frames[1];
+} maliasgroup_t;
+
+// !!! if this is changed, it must be changed in asm_draw.h too !!!
+typedef struct mtriangle_s {
+	int					facesfront;
+	int					vertindex[3];
+} mtriangle_t;
+
+
+#define	MAX_SKINS	32
+typedef struct {
+	int			ident;
+	int			version;
+	vec3_t		scale;
+	vec3_t		scale_origin;
+	float		boundingradius;
+	vec3_t		eyeposition;
+	int			numskins;
+	int			skinwidth;
+	int			skinheight;
+	int			numverts;
+	int			numtris;
+	int			numframes;
+	synctype_t	synctype;
+	int			flags;
+	float		size;
+
+	int					numposes;
+	int					poseverts;
+	int					posedata;	// numposes*poseverts trivert_t
+	int					commands;	// gl command list with embedded s/t
+	int					gl_texturenum[MAX_SKINS][4];
+	int					texels[MAX_SKINS];	// only for player skins
+	maliasframedesc_t	frames[1];	// variable sized
+} aliashdr_t;
+
+#define	MAXALIASVERTS	1024
+#define	MAXALIASFRAMES	256
+#define	MAXALIASTRIS	2048
+extern	aliashdr_t	*pheader;
+extern	stvert_t	stverts[MAXALIASVERTS];
+extern	mtriangle_t	triangles[MAXALIASTRIS];
+extern	trivertx_t	*poseverts[MAXALIASFRAMES];
+
+//===================================================================
+
+//
+// Whole model
+//
+
+typedef enum {mod_brush, mod_sprite, mod_alias} modtype_t;
+
+#define	EF_ROCKET	1			// leave a trail
+#define	EF_GRENADE	2			// leave a trail
+#define	EF_GIB		4			// leave a trail
+#define	EF_ROTATE	8			// rotate (bonus items)
+#define	EF_TRACER	16			// green split trail
+#define	EF_ZOMGIB	32			// small blood trail
+#define	EF_TRACER2	64			// orange split trail + rotate
+#define	EF_TRACER3	128			// purple trail
+
+typedef struct model_s
+{
+	char		name[MAX_QPATH];
+	qboolean	needload;		// bmodels and sprites don't cache normally
+
+	modtype_t	type;
+	int			numframes;
+	synctype_t	synctype;
+	
+	int			flags;
+
+//
+// volume occupied by the model graphics
+//		
+	vec3_t		mins, maxs;
+	float		radius;
+
+//
+// solid volume for clipping 
+//
+	qboolean	clipbox;
+	vec3_t		clipmins, clipmaxs;
+
+//
+// brush model
+//
+	int			firstmodelsurface, nummodelsurfaces;
+
+	int			numsubmodels;
+	dmodel_t	*submodels;
+
+	int			numplanes;
+	mplane_t	*planes;
+
+	int			numleafs;		// number of visible leafs, not counting 0
+	mleaf_t		*leafs;
+
+	int			numvertexes;
+	mvertex_t	*vertexes;
+
+	int			numedges;
+	medge_t		*edges;
+
+	int			numnodes;
+	mnode_t		*nodes;
+
+	int			numtexinfo;
+	mtexinfo_t	*texinfo;
+
+	int			numsurfaces;
+	msurface_t	*surfaces;
+
+	int			numsurfedges;
+	int			*surfedges;
+
+	int			numclipnodes;
+	dclipnode_t	*clipnodes;
+
+	int			nummarksurfaces;
+	msurface_t	**marksurfaces;
+
+	hull_t		hulls[MAX_MAP_HULLS];
+
+	int			numtextures;
+	texture_t	**textures;
+
+	byte		*visdata;
+	byte		*lightdata;
+	char		*entities;
+
+//
+// additional model data
+//
+	cache_user_t	cache;		// only access through Mod_Extradata
+
+} model_t;
+
+//============================================================================
+
+void	Mod_Init (void);
+void	Mod_ClearAll (void);
+model_t *Mod_ForName (char *name, qboolean crash);
+void	*Mod_Extradata (model_t *mod);	// handles caching
+void	Mod_TouchModel (char *name);
+
+mleaf_t *Mod_PointInLeaf (float *p, model_t *model);
+byte	*Mod_LeafPVS (mleaf_t *leaf, model_t *model);
+
+#endif	// __MODEL__
--- /dev/null
+++ b/WinQuake/gl_refrag.c
@@ -1,0 +1,234 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// r_efrag.c
+
+#include "quakedef.h"
+
+mnode_t	*r_pefragtopnode;
+
+
+//===========================================================================
+
+/*
+===============================================================================
+
+					ENTITY FRAGMENT FUNCTIONS
+
+===============================================================================
+*/
+
+efrag_t		**lastlink;
+
+vec3_t		r_emins, r_emaxs;
+
+entity_t	*r_addent;
+
+
+/*
+================
+R_RemoveEfrags
+
+Call when removing an object from the world or moving it to another position
+================
+*/
+void R_RemoveEfrags (entity_t *ent)
+{
+	efrag_t		*ef, *old, *walk, **prev;
+	
+	ef = ent->efrag;
+	
+	while (ef)
+	{
+		prev = &ef->leaf->efrags;
+		while (1)
+		{
+			walk = *prev;
+			if (!walk)
+				break;
+			if (walk == ef)
+			{	// remove this fragment
+				*prev = ef->leafnext;
+				break;
+			}
+			else
+				prev = &walk->leafnext;
+		}
+				
+		old = ef;
+		ef = ef->entnext;
+		
+	// put it on the free list
+		old->entnext = cl.free_efrags;
+		cl.free_efrags = old;
+	}
+	
+	ent->efrag = NULL; 
+}
+
+/*
+===================
+R_SplitEntityOnNode
+===================
+*/
+void R_SplitEntityOnNode (mnode_t *node)
+{
+	efrag_t		*ef;
+	mplane_t	*splitplane;
+	mleaf_t		*leaf;
+	int			sides;
+	
+	if (node->contents == CONTENTS_SOLID)
+	{
+		return;
+	}
+	
+// add an efrag if the node is a leaf
+
+	if ( node->contents < 0)
+	{
+		if (!r_pefragtopnode)
+			r_pefragtopnode = node;
+
+		leaf = (mleaf_t *)node;
+
+// grab an efrag off the free list
+		ef = cl.free_efrags;
+		if (!ef)
+		{
+			Con_Printf ("Too many efrags!\n");
+			return;		// no free fragments...
+		}
+		cl.free_efrags = cl.free_efrags->entnext;
+
+		ef->entity = r_addent;
+		
+// add the entity link	
+		*lastlink = ef;
+		lastlink = &ef->entnext;
+		ef->entnext = NULL;
+		
+// set the leaf links
+		ef->leaf = leaf;
+		ef->leafnext = leaf->efrags;
+		leaf->efrags = ef;
+			
+		return;
+	}
+	
+// NODE_MIXED
+
+	splitplane = node->plane;
+	sides = BOX_ON_PLANE_SIDE(r_emins, r_emaxs, splitplane);
+	
+	if (sides == 3)
+	{
+	// split on this plane
+	// if this is the first splitter of this bmodel, remember it
+		if (!r_pefragtopnode)
+			r_pefragtopnode = node;
+	}
+	
+// recurse down the contacted sides
+	if (sides & 1)
+		R_SplitEntityOnNode (node->children[0]);
+		
+	if (sides & 2)
+		R_SplitEntityOnNode (node->children[1]);
+}
+
+
+
+/*
+===========
+R_AddEfrags
+===========
+*/
+void R_AddEfrags (entity_t *ent)
+{
+	model_t		*entmodel;
+	int			i;
+		
+	if (!ent->model)
+		return;
+
+	r_addent = ent;
+			
+	lastlink = &ent->efrag;
+	r_pefragtopnode = NULL;
+	
+	entmodel = ent->model;
+
+	for (i=0 ; i<3 ; i++)
+	{
+		r_emins[i] = ent->origin[i] + entmodel->mins[i];
+		r_emaxs[i] = ent->origin[i] + entmodel->maxs[i];
+	}
+
+	R_SplitEntityOnNode (cl.worldmodel->nodes);
+
+	ent->topnode = r_pefragtopnode;
+}
+
+
+/*
+================
+R_StoreEfrags
+
+// FIXME: a lot of this goes away with edge-based
+================
+*/
+void R_StoreEfrags (efrag_t **ppefrag)
+{
+	entity_t	*pent;
+	model_t		*clmodel;
+	efrag_t		*pefrag;
+
+
+	while ((pefrag = *ppefrag) != NULL)
+	{
+		pent = pefrag->entity;
+		clmodel = pent->model;
+
+		switch (clmodel->type)
+		{
+		case mod_alias:
+		case mod_brush:
+		case mod_sprite:
+			pent = pefrag->entity;
+
+			if ((pent->visframe != r_framecount) &&
+				(cl_numvisedicts < MAX_VISEDICTS))
+			{
+				cl_visedicts[cl_numvisedicts++] = pent;
+
+			// mark that we've recorded this entity for this frame
+				pent->visframe = r_framecount;
+			}
+
+			ppefrag = &pefrag->leafnext;
+			break;
+
+		default:	
+			Sys_Error ("R_StoreEfrags: Bad entity type %d\n", clmodel->type);
+		}
+	}
+}
+
+
--- /dev/null
+++ b/WinQuake/gl_rlight.c
@@ -1,0 +1,354 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// r_light.c
+
+#include "quakedef.h"
+
+int	r_dlightframecount;
+
+
+/*
+==================
+R_AnimateLight
+==================
+*/
+void R_AnimateLight (void)
+{
+	int			i,j,k;
+	
+//
+// light animations
+// 'm' is normal light, 'a' is no light, 'z' is double bright
+	i = (int)(cl.time*10);
+	for (j=0 ; j<MAX_LIGHTSTYLES ; j++)
+	{
+		if (!cl_lightstyle[j].length)
+		{
+			d_lightstylevalue[j] = 256;
+			continue;
+		}
+		k = i % cl_lightstyle[j].length;
+		k = cl_lightstyle[j].map[k] - 'a';
+		k = k*22;
+		d_lightstylevalue[j] = k;
+	}	
+}
+
+/*
+=============================================================================
+
+DYNAMIC LIGHTS BLEND RENDERING
+
+=============================================================================
+*/
+
+void AddLightBlend (float r, float g, float b, float a2)
+{
+	float	a;
+
+	v_blend[3] = a = v_blend[3] + a2*(1-v_blend[3]);
+
+	a2 = a2/a;
+
+	v_blend[0] = v_blend[1]*(1-a2) + r*a2;
+	v_blend[1] = v_blend[1]*(1-a2) + g*a2;
+	v_blend[2] = v_blend[2]*(1-a2) + b*a2;
+}
+
+void R_RenderDlight (dlight_t *light)
+{
+	int		i, j;
+	float	a;
+	vec3_t	v;
+	float	rad;
+
+	rad = light->radius * 0.35;
+
+	VectorSubtract (light->origin, r_origin, v);
+	if (Length (v) < rad)
+	{	// view is inside the dlight
+		AddLightBlend (1, 0.5, 0, light->radius * 0.0003);
+		return;
+	}
+
+	glBegin (GL_TRIANGLE_FAN);
+	glColor3f (0.2,0.1,0.0);
+	for (i=0 ; i<3 ; i++)
+		v[i] = light->origin[i] - vpn[i]*rad;
+	glVertex3fv (v);
+	glColor3f (0,0,0);
+	for (i=16 ; i>=0 ; i--)
+	{
+		a = i/16.0 * M_PI*2;
+		for (j=0 ; j<3 ; j++)
+			v[j] = light->origin[j] + vright[j]*cos(a)*rad
+				+ vup[j]*sin(a)*rad;
+		glVertex3fv (v);
+	}
+	glEnd ();
+}
+
+/*
+=============
+R_RenderDlights
+=============
+*/
+void R_RenderDlights (void)
+{
+	int		i;
+	dlight_t	*l;
+
+	if (!gl_flashblend.value)
+		return;
+
+	r_dlightframecount = r_framecount + 1;	// because the count hasn't
+											//  advanced yet for this frame
+	glDepthMask (0);
+	glDisable (GL_TEXTURE_2D);
+	glShadeModel (GL_SMOOTH);
+	glEnable (GL_BLEND);
+	glBlendFunc (GL_ONE, GL_ONE);
+
+	l = cl_dlights;
+	for (i=0 ; i<MAX_DLIGHTS ; i++, l++)
+	{
+		if (l->die < cl.time || !l->radius)
+			continue;
+		R_RenderDlight (l);
+	}
+
+	glColor3f (1,1,1);
+	glDisable (GL_BLEND);
+	glEnable (GL_TEXTURE_2D);
+	glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+	glDepthMask (1);
+}
+
+
+/*
+=============================================================================
+
+DYNAMIC LIGHTS
+
+=============================================================================
+*/
+
+/*
+=============
+R_MarkLights
+=============
+*/
+void R_MarkLights (dlight_t *light, int bit, mnode_t *node)
+{
+	mplane_t	*splitplane;
+	float		dist;
+	msurface_t	*surf;
+	int			i;
+	
+	if (node->contents < 0)
+		return;
+
+	splitplane = node->plane;
+	dist = DotProduct (light->origin, splitplane->normal) - splitplane->dist;
+	
+	if (dist > light->radius)
+	{
+		R_MarkLights (light, bit, node->children[0]);
+		return;
+	}
+	if (dist < -light->radius)
+	{
+		R_MarkLights (light, bit, node->children[1]);
+		return;
+	}
+		
+// mark the polygons
+	surf = cl.worldmodel->surfaces + node->firstsurface;
+	for (i=0 ; i<node->numsurfaces ; i++, surf++)
+	{
+		if (surf->dlightframe != r_dlightframecount)
+		{
+			surf->dlightbits = 0;
+			surf->dlightframe = r_dlightframecount;
+		}
+		surf->dlightbits |= bit;
+	}
+
+	R_MarkLights (light, bit, node->children[0]);
+	R_MarkLights (light, bit, node->children[1]);
+}
+
+
+/*
+=============
+R_PushDlights
+=============
+*/
+void R_PushDlights (void)
+{
+	int		i;
+	dlight_t	*l;
+
+	if (gl_flashblend.value)
+		return;
+
+	r_dlightframecount = r_framecount + 1;	// because the count hasn't
+											//  advanced yet for this frame
+	l = cl_dlights;
+
+	for (i=0 ; i<MAX_DLIGHTS ; i++, l++)
+	{
+		if (l->die < cl.time || !l->radius)
+			continue;
+		R_MarkLights ( l, 1<<i, cl.worldmodel->nodes );
+	}
+}
+
+
+/*
+=============================================================================
+
+LIGHT SAMPLING
+
+=============================================================================
+*/
+
+mplane_t		*lightplane;
+vec3_t			lightspot;
+
+int RecursiveLightPoint (mnode_t *node, vec3_t start, vec3_t end)
+{
+	int			r;
+	float		front, back, frac;
+	int			side;
+	mplane_t	*plane;
+	vec3_t		mid;
+	msurface_t	*surf;
+	int			s, t, ds, dt;
+	int			i;
+	mtexinfo_t	*tex;
+	byte		*lightmap;
+	unsigned	scale;
+	int			maps;
+
+	if (node->contents < 0)
+		return -1;		// didn't hit anything
+	
+// calculate mid point
+
+// FIXME: optimize for axial
+	plane = node->plane;
+	front = DotProduct (start, plane->normal) - plane->dist;
+	back = DotProduct (end, plane->normal) - plane->dist;
+	side = front < 0;
+	
+	if ( (back < 0) == side)
+		return RecursiveLightPoint (node->children[side], start, end);
+	
+	frac = front / (front-back);
+	mid[0] = start[0] + (end[0] - start[0])*frac;
+	mid[1] = start[1] + (end[1] - start[1])*frac;
+	mid[2] = start[2] + (end[2] - start[2])*frac;
+	
+// go down front side	
+	r = RecursiveLightPoint (node->children[side], start, mid);
+	if (r >= 0)
+		return r;		// hit something
+		
+	if ( (back < 0) == side )
+		return -1;		// didn't hit anuthing
+		
+// check for impact on this node
+	VectorCopy (mid, lightspot);
+	lightplane = plane;
+
+	surf = cl.worldmodel->surfaces + node->firstsurface;
+	for (i=0 ; i<node->numsurfaces ; i++, surf++)
+	{
+		if (surf->flags & SURF_DRAWTILED)
+			continue;	// no lightmaps
+
+		tex = surf->texinfo;
+		
+		s = DotProduct (mid, tex->vecs[0]) + tex->vecs[0][3];
+		t = DotProduct (mid, tex->vecs[1]) + tex->vecs[1][3];;
+
+		if (s < surf->texturemins[0] ||
+		t < surf->texturemins[1])
+			continue;
+		
+		ds = s - surf->texturemins[0];
+		dt = t - surf->texturemins[1];
+		
+		if ( ds > surf->extents[0] || dt > surf->extents[1] )
+			continue;
+
+		if (!surf->samples)
+			return 0;
+
+		ds >>= 4;
+		dt >>= 4;
+
+		lightmap = surf->samples;
+		r = 0;
+		if (lightmap)
+		{
+
+			lightmap += dt * ((surf->extents[0]>>4)+1) + ds;
+
+			for (maps = 0 ; maps < MAXLIGHTMAPS && surf->styles[maps] != 255 ;
+					maps++)
+			{
+				scale = d_lightstylevalue[surf->styles[maps]];
+				r += *lightmap * scale;
+				lightmap += ((surf->extents[0]>>4)+1) *
+						((surf->extents[1]>>4)+1);
+			}
+			
+			r >>= 8;
+		}
+		
+		return r;
+	}
+
+// go down back side
+	return RecursiveLightPoint (node->children[!side], mid, end);
+}
+
+int R_LightPoint (vec3_t p)
+{
+	vec3_t		end;
+	int			r;
+	
+	if (!cl.worldmodel->lightdata)
+		return 255;
+	
+	end[0] = p[0];
+	end[1] = p[1];
+	end[2] = p[2] - 2048;
+	
+	r = RecursiveLightPoint (cl.worldmodel->nodes, p, end);
+	
+	if (r == -1)
+		r = 0;
+
+	return r;
+}
+
--- /dev/null
+++ b/WinQuake/gl_rmain.c
@@ -1,0 +1,1159 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// r_main.c
+
+#include "quakedef.h"
+
+entity_t	r_worldentity;
+
+qboolean	r_cache_thrash;		// compatability
+
+vec3_t		modelorg, r_entorigin;
+entity_t	*currententity;
+
+int			r_visframecount;	// bumped when going to a new PVS
+int			r_framecount;		// used for dlight push checking
+
+mplane_t	frustum[4];
+
+int			c_brush_polys, c_alias_polys;
+
+qboolean	envmap;				// true during envmap command capture 
+
+int			currenttexture = -1;		// to avoid unnecessary texture sets
+
+int			cnttextures[2] = {-1, -1};     // cached
+
+int			particletexture;	// little dot for particles
+int			playertextures;		// up to 16 color translated skins
+
+int			mirrortexturenum;	// quake texturenum, not gltexturenum
+qboolean	mirror;
+mplane_t	*mirror_plane;
+
+//
+// view origin
+//
+vec3_t	vup;
+vec3_t	vpn;
+vec3_t	vright;
+vec3_t	r_origin;
+
+float	r_world_matrix[16];
+float	r_base_world_matrix[16];
+
+//
+// screen size info
+//
+refdef_t	r_refdef;
+
+mleaf_t		*r_viewleaf, *r_oldviewleaf;
+
+texture_t	*r_notexture_mip;
+
+int		d_lightstylevalue[256];	// 8.8 fraction of base light value
+
+
+void R_MarkLeaves (void);
+
+cvar_t	r_norefresh = {"r_norefresh","0"};
+cvar_t	r_drawentities = {"r_drawentities","1"};
+cvar_t	r_drawviewmodel = {"r_drawviewmodel","1"};
+cvar_t	r_speeds = {"r_speeds","0"};
+cvar_t	r_fullbright = {"r_fullbright","0"};
+cvar_t	r_lightmap = {"r_lightmap","0"};
+cvar_t	r_shadows = {"r_shadows","0"};
+cvar_t	r_mirroralpha = {"r_mirroralpha","1"};
+cvar_t	r_wateralpha = {"r_wateralpha","1"};
+cvar_t	r_dynamic = {"r_dynamic","1"};
+cvar_t	r_novis = {"r_novis","0"};
+
+cvar_t	gl_finish = {"gl_finish","0"};
+cvar_t	gl_clear = {"gl_clear","0"};
+cvar_t	gl_cull = {"gl_cull","1"};
+cvar_t	gl_texsort = {"gl_texsort","1"};
+cvar_t	gl_smoothmodels = {"gl_smoothmodels","1"};
+cvar_t	gl_affinemodels = {"gl_affinemodels","0"};
+cvar_t	gl_polyblend = {"gl_polyblend","1"};
+cvar_t	gl_flashblend = {"gl_flashblend","1"};
+cvar_t	gl_playermip = {"gl_playermip","0"};
+cvar_t	gl_nocolors = {"gl_nocolors","0"};
+cvar_t	gl_keeptjunctions = {"gl_keeptjunctions","0"};
+cvar_t	gl_reporttjunctions = {"gl_reporttjunctions","0"};
+cvar_t	gl_doubleeyes = {"gl_doubleeys", "1"};
+
+extern	cvar_t	gl_ztrick;
+
+/*
+=================
+R_CullBox
+
+Returns true if the box is completely outside the frustom
+=================
+*/
+qboolean R_CullBox (vec3_t mins, vec3_t maxs)
+{
+	int		i;
+
+	for (i=0 ; i<4 ; i++)
+		if (BoxOnPlaneSide (mins, maxs, &frustum[i]) == 2)
+			return true;
+	return false;
+}
+
+
+void R_RotateForEntity (entity_t *e)
+{
+    glTranslatef (e->origin[0],  e->origin[1],  e->origin[2]);
+
+    glRotatef (e->angles[1],  0, 0, 1);
+    glRotatef (-e->angles[0],  0, 1, 0);
+    glRotatef (e->angles[2],  1, 0, 0);
+}
+
+/*
+=============================================================
+
+  SPRITE MODELS
+
+=============================================================
+*/
+
+/*
+================
+R_GetSpriteFrame
+================
+*/
+mspriteframe_t *R_GetSpriteFrame (entity_t *currententity)
+{
+	msprite_t		*psprite;
+	mspritegroup_t	*pspritegroup;
+	mspriteframe_t	*pspriteframe;
+	int				i, numframes, frame;
+	float			*pintervals, fullinterval, targettime, time;
+
+	psprite = currententity->model->cache.data;
+	frame = currententity->frame;
+
+	if ((frame >= psprite->numframes) || (frame < 0))
+	{
+		Con_Printf ("R_DrawSprite: no such frame %d\n", frame);
+		frame = 0;
+	}
+
+	if (psprite->frames[frame].type == SPR_SINGLE)
+	{
+		pspriteframe = psprite->frames[frame].frameptr;
+	}
+	else
+	{
+		pspritegroup = (mspritegroup_t *)psprite->frames[frame].frameptr;
+		pintervals = pspritegroup->intervals;
+		numframes = pspritegroup->numframes;
+		fullinterval = pintervals[numframes-1];
+
+		time = cl.time + currententity->syncbase;
+
+	// when loading in Mod_LoadSpriteGroup, we guaranteed all interval values
+	// are positive, so we don't have to worry about division by 0
+		targettime = time - ((int)(time / fullinterval)) * fullinterval;
+
+		for (i=0 ; i<(numframes-1) ; i++)
+		{
+			if (pintervals[i] > targettime)
+				break;
+		}
+
+		pspriteframe = pspritegroup->frames[i];
+	}
+
+	return pspriteframe;
+}
+
+
+/*
+=================
+R_DrawSpriteModel
+
+=================
+*/
+void R_DrawSpriteModel (entity_t *e)
+{
+	vec3_t	point;
+	mspriteframe_t	*frame;
+	float		*up, *right;
+	vec3_t		v_forward, v_right, v_up;
+	msprite_t		*psprite;
+
+	// don't even bother culling, because it's just a single
+	// polygon without a surface cache
+	frame = R_GetSpriteFrame (e);
+	psprite = currententity->model->cache.data;
+
+	if (psprite->type == SPR_ORIENTED)
+	{	// bullet marks on walls
+		AngleVectors (currententity->angles, v_forward, v_right, v_up);
+		up = v_up;
+		right = v_right;
+	}
+	else
+	{	// normal sprite
+		up = vup;
+		right = vright;
+	}
+
+	glColor3f (1,1,1);
+
+	GL_DisableMultitexture();
+
+    GL_Bind(frame->gl_texturenum);
+
+	glEnable (GL_ALPHA_TEST);
+	glBegin (GL_QUADS);
+
+	glTexCoord2f (0, 1);
+	VectorMA (e->origin, frame->down, up, point);
+	VectorMA (point, frame->left, right, point);
+	glVertex3fv (point);
+
+	glTexCoord2f (0, 0);
+	VectorMA (e->origin, frame->up, up, point);
+	VectorMA (point, frame->left, right, point);
+	glVertex3fv (point);
+
+	glTexCoord2f (1, 0);
+	VectorMA (e->origin, frame->up, up, point);
+	VectorMA (point, frame->right, right, point);
+	glVertex3fv (point);
+
+	glTexCoord2f (1, 1);
+	VectorMA (e->origin, frame->down, up, point);
+	VectorMA (point, frame->right, right, point);
+	glVertex3fv (point);
+	
+	glEnd ();
+
+	glDisable (GL_ALPHA_TEST);
+}
+
+/*
+=============================================================
+
+  ALIAS MODELS
+
+=============================================================
+*/
+
+
+#define NUMVERTEXNORMALS	162
+
+float	r_avertexnormals[NUMVERTEXNORMALS][3] = {
+#include "anorms.h"
+};
+
+vec3_t	shadevector;
+float	shadelight, ambientlight;
+
+// precalculated dot products for quantized angles
+#define SHADEDOT_QUANT 16
+float	r_avertexnormal_dots[SHADEDOT_QUANT][256] =
+#include "anorm_dots.h"
+;
+
+float	*shadedots = r_avertexnormal_dots[0];
+
+int	lastposenum;
+
+/*
+=============
+GL_DrawAliasFrame
+=============
+*/
+void GL_DrawAliasFrame (aliashdr_t *paliashdr, int posenum)
+{
+	float	s, t;
+	float 	l;
+	int		i, j;
+	int		index;
+	trivertx_t	*v, *verts;
+	int		list;
+	int		*order;
+	vec3_t	point;
+	float	*normal;
+	int		count;
+
+lastposenum = posenum;
+
+	verts = (trivertx_t *)((byte *)paliashdr + paliashdr->posedata);
+	verts += posenum * paliashdr->poseverts;
+	order = (int *)((byte *)paliashdr + paliashdr->commands);
+
+	while (1)
+	{
+		// get the vertex count and primitive type
+		count = *order++;
+		if (!count)
+			break;		// done
+		if (count < 0)
+		{
+			count = -count;
+			glBegin (GL_TRIANGLE_FAN);
+		}
+		else
+			glBegin (GL_TRIANGLE_STRIP);
+
+		do
+		{
+			// texture coordinates come from the draw list
+			glTexCoord2f (((float *)order)[0], ((float *)order)[1]);
+			order += 2;
+
+			// normals and vertexes come from the frame list
+			l = shadedots[verts->lightnormalindex] * shadelight;
+			glColor3f (l, l, l);
+			glVertex3f (verts->v[0], verts->v[1], verts->v[2]);
+			verts++;
+		} while (--count);
+
+		glEnd ();
+	}
+}
+
+
+/*
+=============
+GL_DrawAliasShadow
+=============
+*/
+extern	vec3_t			lightspot;
+
+void GL_DrawAliasShadow (aliashdr_t *paliashdr, int posenum)
+{
+	float	s, t, l;
+	int		i, j;
+	int		index;
+	trivertx_t	*v, *verts;
+	int		list;
+	int		*order;
+	vec3_t	point;
+	float	*normal;
+	float	height, lheight;
+	int		count;
+
+	lheight = currententity->origin[2] - lightspot[2];
+
+	height = 0;
+	verts = (trivertx_t *)((byte *)paliashdr + paliashdr->posedata);
+	verts += posenum * paliashdr->poseverts;
+	order = (int *)((byte *)paliashdr + paliashdr->commands);
+
+	height = -lheight + 1.0;
+
+	while (1)
+	{
+		// get the vertex count and primitive type
+		count = *order++;
+		if (!count)
+			break;		// done
+		if (count < 0)
+		{
+			count = -count;
+			glBegin (GL_TRIANGLE_FAN);
+		}
+		else
+			glBegin (GL_TRIANGLE_STRIP);
+
+		do
+		{
+			// texture coordinates come from the draw list
+			// (skipped for shadows) glTexCoord2fv ((float *)order);
+			order += 2;
+
+			// normals and vertexes come from the frame list
+			point[0] = verts->v[0] * paliashdr->scale[0] + paliashdr->scale_origin[0];
+			point[1] = verts->v[1] * paliashdr->scale[1] + paliashdr->scale_origin[1];
+			point[2] = verts->v[2] * paliashdr->scale[2] + paliashdr->scale_origin[2];
+
+			point[0] -= shadevector[0]*(point[2]+lheight);
+			point[1] -= shadevector[1]*(point[2]+lheight);
+			point[2] = height;
+//			height -= 0.001;
+			glVertex3fv (point);
+
+			verts++;
+		} while (--count);
+
+		glEnd ();
+	}	
+}
+
+
+
+/*
+=================
+R_SetupAliasFrame
+
+=================
+*/
+void R_SetupAliasFrame (int frame, aliashdr_t *paliashdr)
+{
+	int				pose, numposes;
+	float			interval;
+
+	if ((frame >= paliashdr->numframes) || (frame < 0))
+	{
+		Con_DPrintf ("R_AliasSetupFrame: no such frame %d\n", frame);
+		frame = 0;
+	}
+
+	pose = paliashdr->frames[frame].firstpose;
+	numposes = paliashdr->frames[frame].numposes;
+
+	if (numposes > 1)
+	{
+		interval = paliashdr->frames[frame].interval;
+		pose += (int)(cl.time / interval) % numposes;
+	}
+
+	GL_DrawAliasFrame (paliashdr, pose);
+}
+
+
+
+/*
+=================
+R_DrawAliasModel
+
+=================
+*/
+void R_DrawAliasModel (entity_t *e)
+{
+	int			i, j;
+	int			lnum;
+	vec3_t		dist;
+	float		add;
+	model_t		*clmodel;
+	vec3_t		mins, maxs;
+	aliashdr_t	*paliashdr;
+	trivertx_t	*verts, *v;
+	int			index;
+	float		s, t, an;
+	int			anim;
+
+	clmodel = currententity->model;
+
+	VectorAdd (currententity->origin, clmodel->mins, mins);
+	VectorAdd (currententity->origin, clmodel->maxs, maxs);
+
+	if (R_CullBox (mins, maxs))
+		return;
+
+
+	VectorCopy (currententity->origin, r_entorigin);
+	VectorSubtract (r_origin, r_entorigin, modelorg);
+
+	//
+	// get lighting information
+	//
+
+	ambientlight = shadelight = R_LightPoint (currententity->origin);
+
+	// allways give the gun some light
+	if (e == &cl.viewent && ambientlight < 24)
+		ambientlight = shadelight = 24;
+
+	for (lnum=0 ; lnum<MAX_DLIGHTS ; lnum++)
+	{
+		if (cl_dlights[lnum].die >= cl.time)
+		{
+			VectorSubtract (currententity->origin,
+							cl_dlights[lnum].origin,
+							dist);
+			add = cl_dlights[lnum].radius - Length(dist);
+
+			if (add > 0) {
+				ambientlight += add;
+				//ZOID models should be affected by dlights as well
+				shadelight += add;
+			}
+		}
+	}
+
+	// clamp lighting so it doesn't overbright as much
+	if (ambientlight > 128)
+		ambientlight = 128;
+	if (ambientlight + shadelight > 192)
+		shadelight = 192 - ambientlight;
+
+	// ZOID: never allow players to go totally black
+	i = currententity - cl_entities;
+	if (i >= 1 && i<=cl.maxclients /* && !strcmp (currententity->model->name, "progs/player.mdl") */)
+		if (ambientlight < 8)
+			ambientlight = shadelight = 8;
+
+	// HACK HACK HACK -- no fullbright colors, so make torches full light
+	if (!strcmp (clmodel->name, "progs/flame2.mdl")
+		|| !strcmp (clmodel->name, "progs/flame.mdl") )
+		ambientlight = shadelight = 256;
+
+	shadedots = r_avertexnormal_dots[((int)(e->angles[1] * (SHADEDOT_QUANT / 360.0))) & (SHADEDOT_QUANT - 1)];
+	shadelight = shadelight / 200.0;
+	
+	an = e->angles[1]/180*M_PI;
+	shadevector[0] = cos(-an);
+	shadevector[1] = sin(-an);
+	shadevector[2] = 1;
+	VectorNormalize (shadevector);
+
+	//
+	// locate the proper data
+	//
+	paliashdr = (aliashdr_t *)Mod_Extradata (currententity->model);
+
+	c_alias_polys += paliashdr->numtris;
+
+	//
+	// draw all the triangles
+	//
+
+	GL_DisableMultitexture();
+
+    glPushMatrix ();
+	R_RotateForEntity (e);
+
+	if (!strcmp (clmodel->name, "progs/eyes.mdl") && gl_doubleeyes.value) {
+		glTranslatef (paliashdr->scale_origin[0], paliashdr->scale_origin[1], paliashdr->scale_origin[2] - (22 + 8));
+// double size of eyes, since they are really hard to see in gl
+		glScalef (paliashdr->scale[0]*2, paliashdr->scale[1]*2, paliashdr->scale[2]*2);
+	} else {
+		glTranslatef (paliashdr->scale_origin[0], paliashdr->scale_origin[1], paliashdr->scale_origin[2]);
+		glScalef (paliashdr->scale[0], paliashdr->scale[1], paliashdr->scale[2]);
+	}
+
+	anim = (int)(cl.time*10) & 3;
+    GL_Bind(paliashdr->gl_texturenum[currententity->skinnum][anim]);
+
+	// we can't dynamically colormap textures, so they are cached
+	// seperately for the players.  Heads are just uncolored.
+	if (currententity->colormap != vid.colormap && !gl_nocolors.value)
+	{
+		i = currententity - cl_entities;
+		if (i >= 1 && i<=cl.maxclients /* && !strcmp (currententity->model->name, "progs/player.mdl") */)
+		    GL_Bind(playertextures - 1 + i);
+	}
+
+	if (gl_smoothmodels.value)
+		glShadeModel (GL_SMOOTH);
+	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+
+	if (gl_affinemodels.value)
+		glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
+
+	R_SetupAliasFrame (currententity->frame, paliashdr);
+
+	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+
+	glShadeModel (GL_FLAT);
+	if (gl_affinemodels.value)
+		glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
+
+	glPopMatrix ();
+
+	if (r_shadows.value)
+	{
+		glPushMatrix ();
+		R_RotateForEntity (e);
+		glDisable (GL_TEXTURE_2D);
+		glEnable (GL_BLEND);
+		glColor4f (0,0,0,0.5);
+		GL_DrawAliasShadow (paliashdr, lastposenum);
+		glEnable (GL_TEXTURE_2D);
+		glDisable (GL_BLEND);
+		glColor4f (1,1,1,1);
+		glPopMatrix ();
+	}
+
+}
+
+//==================================================================================
+
+/*
+=============
+R_DrawEntitiesOnList
+=============
+*/
+void R_DrawEntitiesOnList (void)
+{
+	int		i;
+
+	if (!r_drawentities.value)
+		return;
+
+	// draw sprites seperately, because of alpha blending
+	for (i=0 ; i<cl_numvisedicts ; i++)
+	{
+		currententity = cl_visedicts[i];
+
+		switch (currententity->model->type)
+		{
+		case mod_alias:
+			R_DrawAliasModel (currententity);
+			break;
+
+		case mod_brush:
+			R_DrawBrushModel (currententity);
+			break;
+
+		default:
+			break;
+		}
+	}
+
+	for (i=0 ; i<cl_numvisedicts ; i++)
+	{
+		currententity = cl_visedicts[i];
+
+		switch (currententity->model->type)
+		{
+		case mod_sprite:
+			R_DrawSpriteModel (currententity);
+			break;
+		}
+	}
+}
+
+/*
+=============
+R_DrawViewModel
+=============
+*/
+void R_DrawViewModel (void)
+{
+	float		ambient[4], diffuse[4];
+	int			j;
+	int			lnum;
+	vec3_t		dist;
+	float		add;
+	dlight_t	*dl;
+	int			ambientlight, shadelight;
+
+	if (!r_drawviewmodel.value)
+		return;
+
+	if (chase_active.value)
+		return;
+
+	if (envmap)
+		return;
+
+	if (!r_drawentities.value)
+		return;
+
+	if (cl.items & IT_INVISIBILITY)
+		return;
+
+	if (cl.stats[STAT_HEALTH] <= 0)
+		return;
+
+	currententity = &cl.viewent;
+	if (!currententity->model)
+		return;
+
+	j = R_LightPoint (currententity->origin);
+
+	if (j < 24)
+		j = 24;		// allways give some light on gun
+	ambientlight = j;
+	shadelight = j;
+
+// add dynamic lights		
+	for (lnum=0 ; lnum<MAX_DLIGHTS ; lnum++)
+	{
+		dl = &cl_dlights[lnum];
+		if (!dl->radius)
+			continue;
+		if (!dl->radius)
+			continue;
+		if (dl->die < cl.time)
+			continue;
+
+		VectorSubtract (currententity->origin, dl->origin, dist);
+		add = dl->radius - Length(dist);
+		if (add > 0)
+			ambientlight += add;
+	}
+
+	ambient[0] = ambient[1] = ambient[2] = ambient[3] = (float)ambientlight / 128;
+	diffuse[0] = diffuse[1] = diffuse[2] = diffuse[3] = (float)shadelight / 128;
+
+	// hack the depth range to prevent view model from poking into walls
+	glDepthRange (gldepthmin, gldepthmin + 0.3*(gldepthmax-gldepthmin));
+	R_DrawAliasModel (currententity);
+	glDepthRange (gldepthmin, gldepthmax);
+}
+
+
+/*
+============
+R_PolyBlend
+============
+*/
+void R_PolyBlend (void)
+{
+	if (!gl_polyblend.value)
+		return;
+	if (!v_blend[3])
+		return;
+
+	GL_DisableMultitexture();
+
+	glDisable (GL_ALPHA_TEST);
+	glEnable (GL_BLEND);
+	glDisable (GL_DEPTH_TEST);
+	glDisable (GL_TEXTURE_2D);
+
+    glLoadIdentity ();
+
+    glRotatef (-90,  1, 0, 0);	    // put Z going up
+    glRotatef (90,  0, 0, 1);	    // put Z going up
+
+	glColor4fv (v_blend);
+
+	glBegin (GL_QUADS);
+
+	glVertex3f (10, 100, 100);
+	glVertex3f (10, -100, 100);
+	glVertex3f (10, -100, -100);
+	glVertex3f (10, 100, -100);
+	glEnd ();
+
+	glDisable (GL_BLEND);
+	glEnable (GL_TEXTURE_2D);
+	glEnable (GL_ALPHA_TEST);
+}
+
+
+int SignbitsForPlane (mplane_t *out)
+{
+	int	bits, j;
+
+	// for fast box on planeside test
+
+	bits = 0;
+	for (j=0 ; j<3 ; j++)
+	{
+		if (out->normal[j] < 0)
+			bits |= 1<<j;
+	}
+	return bits;
+}
+
+
+void R_SetFrustum (void)
+{
+	int		i;
+
+	if (r_refdef.fov_x == 90) 
+	{
+		// front side is visible
+
+		VectorAdd (vpn, vright, frustum[0].normal);
+		VectorSubtract (vpn, vright, frustum[1].normal);
+
+		VectorAdd (vpn, vup, frustum[2].normal);
+		VectorSubtract (vpn, vup, frustum[3].normal);
+	}
+	else
+	{
+		// rotate VPN right by FOV_X/2 degrees
+		RotatePointAroundVector( frustum[0].normal, vup, vpn, -(90-r_refdef.fov_x / 2 ) );
+		// rotate VPN left by FOV_X/2 degrees
+		RotatePointAroundVector( frustum[1].normal, vup, vpn, 90-r_refdef.fov_x / 2 );
+		// rotate VPN up by FOV_X/2 degrees
+		RotatePointAroundVector( frustum[2].normal, vright, vpn, 90-r_refdef.fov_y / 2 );
+		// rotate VPN down by FOV_X/2 degrees
+		RotatePointAroundVector( frustum[3].normal, vright, vpn, -( 90 - r_refdef.fov_y / 2 ) );
+	}
+
+	for (i=0 ; i<4 ; i++)
+	{
+		frustum[i].type = PLANE_ANYZ;
+		frustum[i].dist = DotProduct (r_origin, frustum[i].normal);
+		frustum[i].signbits = SignbitsForPlane (&frustum[i]);
+	}
+}
+
+
+
+/*
+===============
+R_SetupFrame
+===============
+*/
+void R_SetupFrame (void)
+{
+	int				edgecount;
+	vrect_t			vrect;
+	float			w, h;
+
+// don't allow cheats in multiplayer
+	if (cl.maxclients > 1)
+		Cvar_Set ("r_fullbright", "0");
+
+	R_AnimateLight ();
+
+	r_framecount++;
+
+// build the transformation matrix for the given view angles
+	VectorCopy (r_refdef.vieworg, r_origin);
+
+	AngleVectors (r_refdef.viewangles, vpn, vright, vup);
+
+// current viewleaf
+	r_oldviewleaf = r_viewleaf;
+	r_viewleaf = Mod_PointInLeaf (r_origin, cl.worldmodel);
+
+	V_SetContentsColor (r_viewleaf->contents);
+	V_CalcBlend ();
+
+	r_cache_thrash = false;
+
+	c_brush_polys = 0;
+	c_alias_polys = 0;
+
+}
+
+
+void MYgluPerspective( GLdouble fovy, GLdouble aspect,
+		     GLdouble zNear, GLdouble zFar )
+{
+   GLdouble xmin, xmax, ymin, ymax;
+
+   ymax = zNear * tan( fovy * M_PI / 360.0 );
+   ymin = -ymax;
+
+   xmin = ymin * aspect;
+   xmax = ymax * aspect;
+
+   glFrustum( xmin, xmax, ymin, ymax, zNear, zFar );
+}
+
+
+/*
+=============
+R_SetupGL
+=============
+*/
+void R_SetupGL (void)
+{
+	float	screenaspect;
+	float	yfov;
+	int		i;
+	extern	int glwidth, glheight;
+	int		x, x2, y2, y, w, h;
+
+	//
+	// set up viewpoint
+	//
+	glMatrixMode(GL_PROJECTION);
+    glLoadIdentity ();
+	x = r_refdef.vrect.x * glwidth/vid.width;
+	x2 = (r_refdef.vrect.x + r_refdef.vrect.width) * glwidth/vid.width;
+	y = (vid.height-r_refdef.vrect.y) * glheight/vid.height;
+	y2 = (vid.height - (r_refdef.vrect.y + r_refdef.vrect.height)) * glheight/vid.height;
+
+	// fudge around because of frac screen scale
+	if (x > 0)
+		x--;
+	if (x2 < glwidth)
+		x2++;
+	if (y2 < 0)
+		y2--;
+	if (y < glheight)
+		y++;
+
+	w = x2 - x;
+	h = y - y2;
+
+	if (envmap)
+	{
+		x = y2 = 0;
+		w = h = 256;
+	}
+
+	glViewport (glx + x, gly + y2, w, h);
+    screenaspect = (float)r_refdef.vrect.width/r_refdef.vrect.height;
+//	yfov = 2*atan((float)r_refdef.vrect.height/r_refdef.vrect.width)*180/M_PI;
+    MYgluPerspective (r_refdef.fov_y,  screenaspect,  4,  4096);
+
+	if (mirror)
+	{
+		if (mirror_plane->normal[2])
+			glScalef (1, -1, 1);
+		else
+			glScalef (-1, 1, 1);
+		glCullFace(GL_BACK);
+	}
+	else
+		glCullFace(GL_FRONT);
+
+	glMatrixMode(GL_MODELVIEW);
+    glLoadIdentity ();
+
+    glRotatef (-90,  1, 0, 0);	    // put Z going up
+    glRotatef (90,  0, 0, 1);	    // put Z going up
+    glRotatef (-r_refdef.viewangles[2],  1, 0, 0);
+    glRotatef (-r_refdef.viewangles[0],  0, 1, 0);
+    glRotatef (-r_refdef.viewangles[1],  0, 0, 1);
+    glTranslatef (-r_refdef.vieworg[0],  -r_refdef.vieworg[1],  -r_refdef.vieworg[2]);
+
+	glGetFloatv (GL_MODELVIEW_MATRIX, r_world_matrix);
+
+	//
+	// set drawing parms
+	//
+	if (gl_cull.value)
+		glEnable(GL_CULL_FACE);
+	else
+		glDisable(GL_CULL_FACE);
+
+	glDisable(GL_BLEND);
+	glDisable(GL_ALPHA_TEST);
+	glEnable(GL_DEPTH_TEST);
+}
+
+/*
+================
+R_RenderScene
+
+r_refdef must be set before the first call
+================
+*/
+void R_RenderScene (void)
+{
+	R_SetupFrame ();
+
+	R_SetFrustum ();
+
+	R_SetupGL ();
+
+	R_MarkLeaves ();	// done here so we know if we're in water
+
+	R_DrawWorld ();		// adds static entities to the list
+
+	S_ExtraUpdate ();	// don't let sound get messed up if going slow
+
+	R_DrawEntitiesOnList ();
+
+	GL_DisableMultitexture();
+
+	R_RenderDlights ();
+
+	R_DrawParticles ();
+
+#ifdef GLTEST
+	Test_Draw ();
+#endif
+
+}
+
+
+/*
+=============
+R_Clear
+=============
+*/
+void R_Clear (void)
+{
+	if (r_mirroralpha.value != 1.0)
+	{
+		if (gl_clear.value)
+			glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+		else
+			glClear (GL_DEPTH_BUFFER_BIT);
+		gldepthmin = 0;
+		gldepthmax = 0.5;
+		glDepthFunc (GL_LEQUAL);
+	}
+	else if (gl_ztrick.value)
+	{
+		static int trickframe;
+
+		if (gl_clear.value)
+			glClear (GL_COLOR_BUFFER_BIT);
+
+		trickframe++;
+		if (trickframe & 1)
+		{
+			gldepthmin = 0;
+			gldepthmax = 0.49999;
+			glDepthFunc (GL_LEQUAL);
+		}
+		else
+		{
+			gldepthmin = 1;
+			gldepthmax = 0.5;
+			glDepthFunc (GL_GEQUAL);
+		}
+	}
+	else
+	{
+		if (gl_clear.value)
+			glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+		else
+			glClear (GL_DEPTH_BUFFER_BIT);
+		gldepthmin = 0;
+		gldepthmax = 1;
+		glDepthFunc (GL_LEQUAL);
+	}
+
+	glDepthRange (gldepthmin, gldepthmax);
+}
+
+/*
+=============
+R_Mirror
+=============
+*/
+void R_Mirror (void)
+{
+	float		d;
+	msurface_t	*s;
+	entity_t	*ent;
+
+	if (!mirror)
+		return;
+
+	memcpy (r_base_world_matrix, r_world_matrix, sizeof(r_base_world_matrix));
+
+	d = DotProduct (r_refdef.vieworg, mirror_plane->normal) - mirror_plane->dist;
+	VectorMA (r_refdef.vieworg, -2*d, mirror_plane->normal, r_refdef.vieworg);
+
+	d = DotProduct (vpn, mirror_plane->normal);
+	VectorMA (vpn, -2*d, mirror_plane->normal, vpn);
+
+	r_refdef.viewangles[0] = -asin (vpn[2])/M_PI*180;
+	r_refdef.viewangles[1] = atan2 (vpn[1], vpn[0])/M_PI*180;
+	r_refdef.viewangles[2] = -r_refdef.viewangles[2];
+
+	ent = &cl_entities[cl.viewentity];
+	if (cl_numvisedicts < MAX_VISEDICTS)
+	{
+		cl_visedicts[cl_numvisedicts] = ent;
+		cl_numvisedicts++;
+	}
+
+	gldepthmin = 0.5;
+	gldepthmax = 1;
+	glDepthRange (gldepthmin, gldepthmax);
+	glDepthFunc (GL_LEQUAL);
+
+	R_RenderScene ();
+	R_DrawWaterSurfaces ();
+
+	gldepthmin = 0;
+	gldepthmax = 0.5;
+	glDepthRange (gldepthmin, gldepthmax);
+	glDepthFunc (GL_LEQUAL);
+
+	// blend on top
+	glEnable (GL_BLEND);
+	glMatrixMode(GL_PROJECTION);
+	if (mirror_plane->normal[2])
+		glScalef (1,-1,1);
+	else
+		glScalef (-1,1,1);
+	glCullFace(GL_FRONT);
+	glMatrixMode(GL_MODELVIEW);
+
+	glLoadMatrixf (r_base_world_matrix);
+
+	glColor4f (1,1,1,r_mirroralpha.value);
+	s = cl.worldmodel->textures[mirrortexturenum]->texturechain;
+	for ( ; s ; s=s->texturechain)
+		R_RenderBrushPoly (s);
+	cl.worldmodel->textures[mirrortexturenum]->texturechain = NULL;
+	glDisable (GL_BLEND);
+	glColor4f (1,1,1,1);
+}
+
+/*
+================
+R_RenderView
+
+r_refdef must be set before the first call
+================
+*/
+void R_RenderView (void)
+{
+	double	time1, time2;
+	GLfloat colors[4] = {(GLfloat) 0.0, (GLfloat) 0.0, (GLfloat) 1, (GLfloat) 0.20};
+
+	if (r_norefresh.value)
+		return;
+
+	if (!r_worldentity.model || !cl.worldmodel)
+		Sys_Error ("R_RenderView: NULL worldmodel");
+
+	if (r_speeds.value)
+	{
+		glFinish ();
+		time1 = Sys_FloatTime ();
+		c_brush_polys = 0;
+		c_alias_polys = 0;
+	}
+
+	mirror = false;
+
+	if (gl_finish.value)
+		glFinish ();
+
+	R_Clear ();
+
+	// render normal view
+
+/***** Experimental silly looking fog ******
+****** Use r_fullbright if you enable ******
+	glFogi(GL_FOG_MODE, GL_LINEAR);
+	glFogfv(GL_FOG_COLOR, colors);
+	glFogf(GL_FOG_END, 512.0);
+	glEnable(GL_FOG);
+********************************************/
+
+	R_RenderScene ();
+	R_DrawViewModel ();
+	R_DrawWaterSurfaces ();
+
+//  More fog right here :)
+//	glDisable(GL_FOG);
+//  End of all fog code...
+
+	// render mirror view
+	R_Mirror ();
+
+	R_PolyBlend ();
+
+	if (r_speeds.value)
+	{
+//		glFinish ();
+		time2 = Sys_FloatTime ();
+		Con_Printf ("%3i ms  %4i wpoly %4i epoly\n", (int)((time2-time1)*1000), c_brush_polys, c_alias_polys); 
+	}
+}
--- /dev/null
+++ b/WinQuake/gl_rmisc.c
@@ -1,0 +1,455 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// r_misc.c
+
+#include "quakedef.h"
+
+
+
+/*
+==================
+R_InitTextures
+==================
+*/
+void	R_InitTextures (void)
+{
+	int		x,y, m;
+	byte	*dest;
+
+// create a simple checkerboard texture for the default
+	r_notexture_mip = Hunk_AllocName (sizeof(texture_t) + 16*16+8*8+4*4+2*2, "notexture");
+	
+	r_notexture_mip->width = r_notexture_mip->height = 16;
+	r_notexture_mip->offsets[0] = sizeof(texture_t);
+	r_notexture_mip->offsets[1] = r_notexture_mip->offsets[0] + 16*16;
+	r_notexture_mip->offsets[2] = r_notexture_mip->offsets[1] + 8*8;
+	r_notexture_mip->offsets[3] = r_notexture_mip->offsets[2] + 4*4;
+	
+	for (m=0 ; m<4 ; m++)
+	{
+		dest = (byte *)r_notexture_mip + r_notexture_mip->offsets[m];
+		for (y=0 ; y< (16>>m) ; y++)
+			for (x=0 ; x< (16>>m) ; x++)
+			{
+				if (  (y< (8>>m) ) ^ (x< (8>>m) ) )
+					*dest++ = 0;
+				else
+					*dest++ = 0xff;
+			}
+	}	
+}
+
+byte	dottexture[8][8] =
+{
+	{0,1,1,0,0,0,0,0},
+	{1,1,1,1,0,0,0,0},
+	{1,1,1,1,0,0,0,0},
+	{0,1,1,0,0,0,0,0},
+	{0,0,0,0,0,0,0,0},
+	{0,0,0,0,0,0,0,0},
+	{0,0,0,0,0,0,0,0},
+	{0,0,0,0,0,0,0,0},
+};
+void R_InitParticleTexture (void)
+{
+	int		x,y;
+	byte	data[8][8][4];
+
+	//
+	// particle texture
+	//
+	particletexture = texture_extension_number++;
+    GL_Bind(particletexture);
+
+	for (x=0 ; x<8 ; x++)
+	{
+		for (y=0 ; y<8 ; y++)
+		{
+			data[y][x][0] = 255;
+			data[y][x][1] = 255;
+			data[y][x][2] = 255;
+			data[y][x][3] = dottexture[x][y]*255;
+		}
+	}
+	glTexImage2D (GL_TEXTURE_2D, 0, gl_alpha_format, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
+
+	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+
+	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+}
+
+/*
+===============
+R_Envmap_f
+
+Grab six views for environment mapping tests
+===============
+*/
+void R_Envmap_f (void)
+{
+	byte	buffer[256*256*4];
+	char	name[1024];
+
+	glDrawBuffer  (GL_FRONT);
+	glReadBuffer  (GL_FRONT);
+	envmap = true;
+
+	r_refdef.vrect.x = 0;
+	r_refdef.vrect.y = 0;
+	r_refdef.vrect.width = 256;
+	r_refdef.vrect.height = 256;
+
+	r_refdef.viewangles[0] = 0;
+	r_refdef.viewangles[1] = 0;
+	r_refdef.viewangles[2] = 0;
+	GL_BeginRendering (&glx, &gly, &glwidth, &glheight);
+	R_RenderView ();
+	glReadPixels (0, 0, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
+	COM_WriteFile ("env0.rgb", buffer, sizeof(buffer));		
+
+	r_refdef.viewangles[1] = 90;
+	GL_BeginRendering (&glx, &gly, &glwidth, &glheight);
+	R_RenderView ();
+	glReadPixels (0, 0, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
+	COM_WriteFile ("env1.rgb", buffer, sizeof(buffer));		
+
+	r_refdef.viewangles[1] = 180;
+	GL_BeginRendering (&glx, &gly, &glwidth, &glheight);
+	R_RenderView ();
+	glReadPixels (0, 0, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
+	COM_WriteFile ("env2.rgb", buffer, sizeof(buffer));		
+
+	r_refdef.viewangles[1] = 270;
+	GL_BeginRendering (&glx, &gly, &glwidth, &glheight);
+	R_RenderView ();
+	glReadPixels (0, 0, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
+	COM_WriteFile ("env3.rgb", buffer, sizeof(buffer));		
+
+	r_refdef.viewangles[0] = -90;
+	r_refdef.viewangles[1] = 0;
+	GL_BeginRendering (&glx, &gly, &glwidth, &glheight);
+	R_RenderView ();
+	glReadPixels (0, 0, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
+	COM_WriteFile ("env4.rgb", buffer, sizeof(buffer));		
+
+	r_refdef.viewangles[0] = 90;
+	r_refdef.viewangles[1] = 0;
+	GL_BeginRendering (&glx, &gly, &glwidth, &glheight);
+	R_RenderView ();
+	glReadPixels (0, 0, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
+	COM_WriteFile ("env5.rgb", buffer, sizeof(buffer));		
+
+	envmap = false;
+	glDrawBuffer  (GL_BACK);
+	glReadBuffer  (GL_BACK);
+	GL_EndRendering ();
+}
+
+/*
+===============
+R_Init
+===============
+*/
+void R_Init (void)
+{	
+	extern byte *hunk_base;
+	extern cvar_t gl_finish;
+
+	Cmd_AddCommand ("timerefresh", R_TimeRefresh_f);	
+	Cmd_AddCommand ("envmap", R_Envmap_f);	
+	Cmd_AddCommand ("pointfile", R_ReadPointFile_f);	
+
+	Cvar_RegisterVariable (&r_norefresh);
+	Cvar_RegisterVariable (&r_lightmap);
+	Cvar_RegisterVariable (&r_fullbright);
+	Cvar_RegisterVariable (&r_drawentities);
+	Cvar_RegisterVariable (&r_drawviewmodel);
+	Cvar_RegisterVariable (&r_shadows);
+	Cvar_RegisterVariable (&r_mirroralpha);
+	Cvar_RegisterVariable (&r_wateralpha);
+	Cvar_RegisterVariable (&r_dynamic);
+	Cvar_RegisterVariable (&r_novis);
+	Cvar_RegisterVariable (&r_speeds);
+
+	Cvar_RegisterVariable (&gl_finish);
+	Cvar_RegisterVariable (&gl_clear);
+	Cvar_RegisterVariable (&gl_texsort);
+
+ 	if (gl_mtexable)
+		Cvar_SetValue ("gl_texsort", 0.0);
+
+	Cvar_RegisterVariable (&gl_cull);
+	Cvar_RegisterVariable (&gl_smoothmodels);
+	Cvar_RegisterVariable (&gl_affinemodels);
+	Cvar_RegisterVariable (&gl_polyblend);
+	Cvar_RegisterVariable (&gl_flashblend);
+	Cvar_RegisterVariable (&gl_playermip);
+	Cvar_RegisterVariable (&gl_nocolors);
+
+	Cvar_RegisterVariable (&gl_keeptjunctions);
+	Cvar_RegisterVariable (&gl_reporttjunctions);
+
+	Cvar_RegisterVariable (&gl_doubleeyes);
+
+	R_InitParticles ();
+	R_InitParticleTexture ();
+
+#ifdef GLTEST
+	Test_Init ();
+#endif
+
+	playertextures = texture_extension_number;
+	texture_extension_number += 16;
+}
+
+/*
+===============
+R_TranslatePlayerSkin
+
+Translates a skin texture by the per-player color lookup
+===============
+*/
+void R_TranslatePlayerSkin (int playernum)
+{
+	int		top, bottom;
+	byte	translate[256];
+	unsigned	translate32[256];
+	int		i, j, s;
+	model_t	*model;
+	aliashdr_t *paliashdr;
+	byte	*original;
+	unsigned	pixels[512*256], *out;
+	unsigned	scaled_width, scaled_height;
+	int			inwidth, inheight;
+	byte		*inrow;
+	unsigned	frac, fracstep;
+	extern	byte		**player_8bit_texels_tbl;
+
+	GL_DisableMultitexture();
+
+	top = cl.scores[playernum].colors & 0xf0;
+	bottom = (cl.scores[playernum].colors &15)<<4;
+
+	for (i=0 ; i<256 ; i++)
+		translate[i] = i;
+
+	for (i=0 ; i<16 ; i++)
+	{
+		if (top < 128)	// the artists made some backwards ranges.  sigh.
+			translate[TOP_RANGE+i] = top+i;
+		else
+			translate[TOP_RANGE+i] = top+15-i;
+				
+		if (bottom < 128)
+			translate[BOTTOM_RANGE+i] = bottom+i;
+		else
+			translate[BOTTOM_RANGE+i] = bottom+15-i;
+	}
+
+	//
+	// locate the original skin pixels
+	//
+	currententity = &cl_entities[1+playernum];
+	model = currententity->model;
+	if (!model)
+		return;		// player doesn't have a model yet
+	if (model->type != mod_alias)
+		return; // only translate skins on alias models
+
+	paliashdr = (aliashdr_t *)Mod_Extradata (model);
+	s = paliashdr->skinwidth * paliashdr->skinheight;
+	if (currententity->skinnum < 0 || currententity->skinnum >= paliashdr->numskins) {
+		Con_Printf("(%d): Invalid player skin #%d\n", playernum, currententity->skinnum);
+		original = (byte *)paliashdr + paliashdr->texels[0];
+	} else
+		original = (byte *)paliashdr + paliashdr->texels[currententity->skinnum];
+	if (s & 3)
+		Sys_Error ("R_TranslateSkin: s&3");
+
+	inwidth = paliashdr->skinwidth;
+	inheight = paliashdr->skinheight;
+
+	// because this happens during gameplay, do it fast
+	// instead of sending it through gl_upload 8
+    GL_Bind(playertextures + playernum);
+
+#if 0
+	byte	translated[320*200];
+
+	for (i=0 ; i<s ; i+=4)
+	{
+		translated[i] = translate[original[i]];
+		translated[i+1] = translate[original[i+1]];
+		translated[i+2] = translate[original[i+2]];
+		translated[i+3] = translate[original[i+3]];
+	}
+
+
+	// don't mipmap these, because it takes too long
+	GL_Upload8 (translated, paliashdr->skinwidth, paliashdr->skinheight, false, false, true);
+#else
+	scaled_width = gl_max_size.value < 512 ? gl_max_size.value : 512;
+	scaled_height = gl_max_size.value < 256 ? gl_max_size.value : 256;
+
+	// allow users to crunch sizes down even more if they want
+	scaled_width >>= (int)gl_playermip.value;
+	scaled_height >>= (int)gl_playermip.value;
+
+	if (VID_Is8bit()) { // 8bit texture upload
+		byte *out2;
+
+		out2 = (byte *)pixels;
+		memset(pixels, 0, sizeof(pixels));
+		fracstep = inwidth*0x10000/scaled_width;
+		for (i=0 ; i<scaled_height ; i++, out2 += scaled_width)
+		{
+			inrow = original + inwidth*(i*inheight/scaled_height);
+			frac = fracstep >> 1;
+			for (j=0 ; j<scaled_width ; j+=4)
+			{
+				out2[j] = translate[inrow[frac>>16]];
+				frac += fracstep;
+				out2[j+1] = translate[inrow[frac>>16]];
+				frac += fracstep;
+				out2[j+2] = translate[inrow[frac>>16]];
+				frac += fracstep;
+				out2[j+3] = translate[inrow[frac>>16]];
+				frac += fracstep;
+			}
+		}
+
+		GL_Upload8_EXT ((byte *)pixels, scaled_width, scaled_height, false, false);
+		return;
+	}
+
+	for (i=0 ; i<256 ; i++)
+		translate32[i] = d_8to24table[translate[i]];
+
+	out = pixels;
+	fracstep = inwidth*0x10000/scaled_width;
+	for (i=0 ; i<scaled_height ; i++, out += scaled_width)
+	{
+		inrow = original + inwidth*(i*inheight/scaled_height);
+		frac = fracstep >> 1;
+		for (j=0 ; j<scaled_width ; j+=4)
+		{
+			out[j] = translate32[inrow[frac>>16]];
+			frac += fracstep;
+			out[j+1] = translate32[inrow[frac>>16]];
+			frac += fracstep;
+			out[j+2] = translate32[inrow[frac>>16]];
+			frac += fracstep;
+			out[j+3] = translate32[inrow[frac>>16]];
+			frac += fracstep;
+		}
+	}
+	glTexImage2D (GL_TEXTURE_2D, 0, gl_solid_format, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
+
+	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+#endif
+
+}
+
+
+/*
+===============
+R_NewMap
+===============
+*/
+void R_NewMap (void)
+{
+	int		i;
+	
+	for (i=0 ; i<256 ; i++)
+		d_lightstylevalue[i] = 264;		// normal light value
+
+	memset (&r_worldentity, 0, sizeof(r_worldentity));
+	r_worldentity.model = cl.worldmodel;
+
+// clear out efrags in case the level hasn't been reloaded
+// FIXME: is this one short?
+	for (i=0 ; i<cl.worldmodel->numleafs ; i++)
+		cl.worldmodel->leafs[i].efrags = NULL;
+		 	
+	r_viewleaf = NULL;
+	R_ClearParticles ();
+
+	GL_BuildLightmaps ();
+
+	// identify sky texture
+	skytexturenum = -1;
+	mirrortexturenum = -1;
+	for (i=0 ; i<cl.worldmodel->numtextures ; i++)
+	{
+		if (!cl.worldmodel->textures[i])
+			continue;
+		if (!Q_strncmp(cl.worldmodel->textures[i]->name,"sky",3) )
+			skytexturenum = i;
+		if (!Q_strncmp(cl.worldmodel->textures[i]->name,"window02_1",10) )
+			mirrortexturenum = i;
+ 		cl.worldmodel->textures[i]->texturechain = NULL;
+	}
+#ifdef QUAKE2
+	R_LoadSkys ();
+#endif
+}
+
+
+/*
+====================
+R_TimeRefresh_f
+
+For program optimization
+====================
+*/
+void R_TimeRefresh_f (void)
+{
+	int			i;
+	float		start, stop, time;
+	int			startangle;
+	vrect_t		vr;
+
+	glDrawBuffer  (GL_FRONT);
+	glFinish ();
+
+	start = Sys_FloatTime ();
+	for (i=0 ; i<128 ; i++)
+	{
+		r_refdef.viewangles[1] = i/128.0*360.0;
+		R_RenderView ();
+	}
+
+	glFinish ();
+	stop = Sys_FloatTime ();
+	time = stop-start;
+	Con_Printf ("%f seconds (%f fps)\n", time, 128/time);
+
+	glDrawBuffer  (GL_BACK);
+	GL_EndRendering ();
+}
+
+void D_FlushCaches (void)
+{
+}
+
+
--- /dev/null
+++ b/WinQuake/gl_rsurf.c
@@ -1,0 +1,1694 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// r_surf.c: surface-related refresh code
+
+#include "quakedef.h"
+
+int			skytexturenum;
+
+#ifndef GL_RGBA4
+#define	GL_RGBA4	0
+#endif
+
+
+int		lightmap_bytes;		// 1, 2, or 4
+
+int		lightmap_textures;
+
+unsigned		blocklights[18*18];
+
+#define	BLOCK_WIDTH		128
+#define	BLOCK_HEIGHT	128
+
+#define	MAX_LIGHTMAPS	64
+int			active_lightmaps;
+
+typedef struct glRect_s {
+	unsigned char l,t,w,h;
+} glRect_t;
+
+glpoly_t	*lightmap_polys[MAX_LIGHTMAPS];
+qboolean	lightmap_modified[MAX_LIGHTMAPS];
+glRect_t	lightmap_rectchange[MAX_LIGHTMAPS];
+
+int			allocated[MAX_LIGHTMAPS][BLOCK_WIDTH];
+
+// the lightmap texture data needs to be kept in
+// main memory so texsubimage can update properly
+byte		lightmaps[4*MAX_LIGHTMAPS*BLOCK_WIDTH*BLOCK_HEIGHT];
+
+// For gl_texsort 0
+msurface_t  *skychain = NULL;
+msurface_t  *waterchain = NULL;
+
+void R_RenderDynamicLightmaps (msurface_t *fa);
+
+/*
+===============
+R_AddDynamicLights
+===============
+*/
+void R_AddDynamicLights (msurface_t *surf)
+{
+	int			lnum;
+	int			sd, td;
+	float		dist, rad, minlight;
+	vec3_t		impact, local;
+	int			s, t;
+	int			i;
+	int			smax, tmax;
+	mtexinfo_t	*tex;
+
+	smax = (surf->extents[0]>>4)+1;
+	tmax = (surf->extents[1]>>4)+1;
+	tex = surf->texinfo;
+
+	for (lnum=0 ; lnum<MAX_DLIGHTS ; lnum++)
+	{
+		if ( !(surf->dlightbits & (1<<lnum) ) )
+			continue;		// not lit by this light
+
+		rad = cl_dlights[lnum].radius;
+		dist = DotProduct (cl_dlights[lnum].origin, surf->plane->normal) -
+				surf->plane->dist;
+		rad -= fabs(dist);
+		minlight = cl_dlights[lnum].minlight;
+		if (rad < minlight)
+			continue;
+		minlight = rad - minlight;
+
+		for (i=0 ; i<3 ; i++)
+		{
+			impact[i] = cl_dlights[lnum].origin[i] -
+					surf->plane->normal[i]*dist;
+		}
+
+		local[0] = DotProduct (impact, tex->vecs[0]) + tex->vecs[0][3];
+		local[1] = DotProduct (impact, tex->vecs[1]) + tex->vecs[1][3];
+
+		local[0] -= surf->texturemins[0];
+		local[1] -= surf->texturemins[1];
+		
+		for (t = 0 ; t<tmax ; t++)
+		{
+			td = local[1] - t*16;
+			if (td < 0)
+				td = -td;
+			for (s=0 ; s<smax ; s++)
+			{
+				sd = local[0] - s*16;
+				if (sd < 0)
+					sd = -sd;
+				if (sd > td)
+					dist = sd + (td>>1);
+				else
+					dist = td + (sd>>1);
+				if (dist < minlight)
+					blocklights[t*smax + s] += (rad - dist)*256;
+			}
+		}
+	}
+}
+
+
+/*
+===============
+R_BuildLightMap
+
+Combine and scale multiple lightmaps into the 8.8 format in blocklights
+===============
+*/
+void R_BuildLightMap (msurface_t *surf, byte *dest, int stride)
+{
+	int			smax, tmax;
+	int			t;
+	int			i, j, size;
+	byte		*lightmap;
+	unsigned	scale;
+	int			maps;
+	int			lightadj[4];
+	unsigned	*bl;
+
+	surf->cached_dlight = (surf->dlightframe == r_framecount);
+
+	smax = (surf->extents[0]>>4)+1;
+	tmax = (surf->extents[1]>>4)+1;
+	size = smax*tmax;
+	lightmap = surf->samples;
+
+// set to full bright if no light data
+	if (r_fullbright.value || !cl.worldmodel->lightdata)
+	{
+		for (i=0 ; i<size ; i++)
+			blocklights[i] = 255*256;
+		goto store;
+	}
+
+// clear to no light
+	for (i=0 ; i<size ; i++)
+		blocklights[i] = 0;
+
+// add all the lightmaps
+	if (lightmap)
+		for (maps = 0 ; maps < MAXLIGHTMAPS && surf->styles[maps] != 255 ;
+			 maps++)
+		{
+			scale = d_lightstylevalue[surf->styles[maps]];
+			surf->cached_light[maps] = scale;	// 8.8 fraction
+			for (i=0 ; i<size ; i++)
+				blocklights[i] += lightmap[i] * scale;
+			lightmap += size;	// skip to next lightmap
+		}
+
+// add all the dynamic lights
+	if (surf->dlightframe == r_framecount)
+		R_AddDynamicLights (surf);
+
+// bound, invert, and shift
+store:
+	switch (gl_lightmap_format)
+	{
+	case GL_RGBA:
+		stride -= (smax<<2);
+		bl = blocklights;
+		for (i=0 ; i<tmax ; i++, dest += stride)
+		{
+			for (j=0 ; j<smax ; j++)
+			{
+				t = *bl++;
+				t >>= 7;
+				if (t > 255)
+					t = 255;
+				dest[3] = 255-t;
+				dest += 4;
+			}
+		}
+		break;
+	case GL_ALPHA:
+	case GL_LUMINANCE:
+	case GL_INTENSITY:
+		bl = blocklights;
+		for (i=0 ; i<tmax ; i++, dest += stride)
+		{
+			for (j=0 ; j<smax ; j++)
+			{
+				t = *bl++;
+				t >>= 7;
+				if (t > 255)
+					t = 255;
+				dest[j] = 255-t;
+			}
+		}
+		break;
+	default:
+		Sys_Error ("Bad lightmap format");
+	}
+}
+
+
+/*
+===============
+R_TextureAnimation
+
+Returns the proper texture for a given time and base texture
+===============
+*/
+texture_t *R_TextureAnimation (texture_t *base)
+{
+	int		reletive;
+	int		count;
+
+	if (currententity->frame)
+	{
+		if (base->alternate_anims)
+			base = base->alternate_anims;
+	}
+	
+	if (!base->anim_total)
+		return base;
+
+	reletive = (int)(cl.time*10) % base->anim_total;
+
+	count = 0;	
+	while (base->anim_min > reletive || base->anim_max <= reletive)
+	{
+		base = base->anim_next;
+		if (!base)
+			Sys_Error ("R_TextureAnimation: broken cycle");
+		if (++count > 100)
+			Sys_Error ("R_TextureAnimation: infinite cycle");
+	}
+
+	return base;
+}
+
+
+/*
+=============================================================
+
+	BRUSH MODELS
+
+=============================================================
+*/
+
+
+extern	int		solidskytexture;
+extern	int		alphaskytexture;
+extern	float	speedscale;		// for top sky and bottom sky
+
+void DrawGLWaterPoly (glpoly_t *p);
+void DrawGLWaterPolyLightmap (glpoly_t *p);
+
+lpMTexFUNC qglMTexCoord2fSGIS = NULL;
+lpSelTexFUNC qglSelectTextureSGIS = NULL;
+
+qboolean mtexenabled = false;
+
+void GL_SelectTexture (GLenum target);
+
+void GL_DisableMultitexture(void) 
+{
+	if (mtexenabled) {
+		glDisable(GL_TEXTURE_2D);
+		GL_SelectTexture(TEXTURE0_SGIS);
+		mtexenabled = false;
+	}
+}
+
+void GL_EnableMultitexture(void) 
+{
+	if (gl_mtexable) {
+		GL_SelectTexture(TEXTURE1_SGIS);
+		glEnable(GL_TEXTURE_2D);
+		mtexenabled = true;
+	}
+}
+
+#if 0
+/*
+================
+R_DrawSequentialPoly
+
+Systems that have fast state and texture changes can
+just do everything as it passes with no need to sort
+================
+*/
+void R_DrawSequentialPoly (msurface_t *s)
+{
+	glpoly_t	*p;
+	float		*v;
+	int			i;
+	texture_t	*t;
+
+	//
+	// normal lightmaped poly
+	//
+	if (! (s->flags & (SURF_DRAWSKY|SURF_DRAWTURB|SURF_UNDERWATER) ) )
+	{
+		p = s->polys;
+
+		t = R_TextureAnimation (s->texinfo->texture);
+		GL_Bind (t->gl_texturenum);
+		glBegin (GL_POLYGON);
+		v = p->verts[0];
+		for (i=0 ; i<p->numverts ; i++, v+= VERTEXSIZE)
+		{
+			glTexCoord2f (v[3], v[4]);
+			glVertex3fv (v);
+		}
+		glEnd ();
+
+		GL_Bind (lightmap_textures + s->lightmaptexturenum);
+		glEnable (GL_BLEND);
+		glBegin (GL_POLYGON);
+		v = p->verts[0];
+		for (i=0 ; i<p->numverts ; i++, v+= VERTEXSIZE)
+		{
+			glTexCoord2f (v[5], v[6]);
+			glVertex3fv (v);
+		}
+		glEnd ();
+
+		glDisable (GL_BLEND);
+
+		return;
+	}
+
+	//
+	// subdivided water surface warp
+	//
+	if (s->flags & SURF_DRAWTURB)
+	{
+		GL_Bind (s->texinfo->texture->gl_texturenum);
+		EmitWaterPolys (s);
+		return;
+	}
+
+	//
+	// subdivided sky warp
+	//
+	if (s->flags & SURF_DRAWSKY)
+	{
+		GL_Bind (solidskytexture);
+		speedscale = realtime*8;
+		speedscale -= (int)speedscale;
+
+		EmitSkyPolys (s);
+
+		glEnable (GL_BLEND);
+		glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+		GL_Bind (alphaskytexture);
+		speedscale = realtime*16;
+		speedscale -= (int)speedscale;
+		EmitSkyPolys (s);
+		if (gl_lightmap_format == GL_LUMINANCE)
+			glBlendFunc (GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
+
+		glDisable (GL_BLEND);
+	}
+
+	//
+	// underwater warped with lightmap
+	//
+	p = s->polys;
+
+	t = R_TextureAnimation (s->texinfo->texture);
+	GL_Bind (t->gl_texturenum);
+	DrawGLWaterPoly (p);
+
+	GL_Bind (lightmap_textures + s->lightmaptexturenum);
+	glEnable (GL_BLEND);
+	DrawGLWaterPolyLightmap (p);
+	glDisable (GL_BLEND);
+}
+#else
+/*
+================
+R_DrawSequentialPoly
+
+Systems that have fast state and texture changes can
+just do everything as it passes with no need to sort
+================
+*/
+void R_DrawSequentialPoly (msurface_t *s)
+{
+	glpoly_t	*p;
+	float		*v;
+	int			i;
+	texture_t	*t;
+	vec3_t		nv, dir;
+	float		ss, ss2, length;
+	float		s1, t1;
+	glRect_t	*theRect;
+
+	//
+	// normal lightmaped poly
+	//
+
+	if (! (s->flags & (SURF_DRAWSKY|SURF_DRAWTURB|SURF_UNDERWATER) ) )
+	{
+		R_RenderDynamicLightmaps (s);
+		if (gl_mtexable) {
+			p = s->polys;
+
+			t = R_TextureAnimation (s->texinfo->texture);
+			// Binds world to texture env 0
+			GL_SelectTexture(TEXTURE0_SGIS);
+			GL_Bind (t->gl_texturenum);
+			glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+			// Binds lightmap to texenv 1
+			GL_EnableMultitexture(); // Same as SelectTexture (TEXTURE1)
+			GL_Bind (lightmap_textures + s->lightmaptexturenum);
+			i = s->lightmaptexturenum;
+			if (lightmap_modified[i])
+			{
+				lightmap_modified[i] = false;
+				theRect = &lightmap_rectchange[i];
+				glTexSubImage2D(GL_TEXTURE_2D, 0, 0, theRect->t, 
+					BLOCK_WIDTH, theRect->h, gl_lightmap_format, GL_UNSIGNED_BYTE,
+					lightmaps+(i* BLOCK_HEIGHT + theRect->t) *BLOCK_WIDTH*lightmap_bytes);
+				theRect->l = BLOCK_WIDTH;
+				theRect->t = BLOCK_HEIGHT;
+				theRect->h = 0;
+				theRect->w = 0;
+			}
+			glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND);
+			glBegin(GL_POLYGON);
+			v = p->verts[0];
+			for (i=0 ; i<p->numverts ; i++, v+= VERTEXSIZE)
+			{
+				qglMTexCoord2fSGIS (TEXTURE0_SGIS, v[3], v[4]);
+				qglMTexCoord2fSGIS (TEXTURE1_SGIS, v[5], v[6]);
+				glVertex3fv (v);
+			}
+			glEnd ();
+			return;
+		} else {
+			p = s->polys;
+
+			t = R_TextureAnimation (s->texinfo->texture);
+			GL_Bind (t->gl_texturenum);
+			glBegin (GL_POLYGON);
+			v = p->verts[0];
+			for (i=0 ; i<p->numverts ; i++, v+= VERTEXSIZE)
+			{
+				glTexCoord2f (v[3], v[4]);
+				glVertex3fv (v);
+			}
+			glEnd ();
+
+			GL_Bind (lightmap_textures + s->lightmaptexturenum);
+			glEnable (GL_BLEND);
+			glBegin (GL_POLYGON);
+			v = p->verts[0];
+			for (i=0 ; i<p->numverts ; i++, v+= VERTEXSIZE)
+			{
+				glTexCoord2f (v[5], v[6]);
+				glVertex3fv (v);
+			}
+			glEnd ();
+
+			glDisable (GL_BLEND);
+		}
+
+		return;
+	}
+
+	//
+	// subdivided water surface warp
+	//
+
+	if (s->flags & SURF_DRAWTURB)
+	{
+		GL_DisableMultitexture();
+		GL_Bind (s->texinfo->texture->gl_texturenum);
+		EmitWaterPolys (s);
+		return;
+	}
+
+	//
+	// subdivided sky warp
+	//
+	if (s->flags & SURF_DRAWSKY)
+	{
+		GL_DisableMultitexture();
+		GL_Bind (solidskytexture);
+		speedscale = realtime*8;
+		speedscale -= (int)speedscale & ~127;
+
+		EmitSkyPolys (s);
+
+		glEnable (GL_BLEND);
+		GL_Bind (alphaskytexture);
+		speedscale = realtime*16;
+		speedscale -= (int)speedscale & ~127;
+		EmitSkyPolys (s);
+
+		glDisable (GL_BLEND);
+		return;
+	}
+
+	//
+	// underwater warped with lightmap
+	//
+	R_RenderDynamicLightmaps (s);
+	if (gl_mtexable) {
+		p = s->polys;
+
+		t = R_TextureAnimation (s->texinfo->texture);
+		GL_SelectTexture(TEXTURE0_SGIS);
+		GL_Bind (t->gl_texturenum);
+		glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+		GL_EnableMultitexture();
+		GL_Bind (lightmap_textures + s->lightmaptexturenum);
+		i = s->lightmaptexturenum;
+		if (lightmap_modified[i])
+		{
+			lightmap_modified[i] = false;
+			theRect = &lightmap_rectchange[i];
+			glTexSubImage2D(GL_TEXTURE_2D, 0, 0, theRect->t, 
+				BLOCK_WIDTH, theRect->h, gl_lightmap_format, GL_UNSIGNED_BYTE,
+				lightmaps+(i* BLOCK_HEIGHT + theRect->t) *BLOCK_WIDTH*lightmap_bytes);
+			theRect->l = BLOCK_WIDTH;
+			theRect->t = BLOCK_HEIGHT;
+			theRect->h = 0;
+			theRect->w = 0;
+		}
+		glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND);
+		glBegin (GL_TRIANGLE_FAN);
+		v = p->verts[0];
+		for (i=0 ; i<p->numverts ; i++, v+= VERTEXSIZE)
+		{
+			qglMTexCoord2fSGIS (TEXTURE0_SGIS, v[3], v[4]);
+			qglMTexCoord2fSGIS (TEXTURE1_SGIS, v[5], v[6]);
+
+			nv[0] = v[0] + 8*sin(v[1]*0.05+realtime)*sin(v[2]*0.05+realtime);
+			nv[1] = v[1] + 8*sin(v[0]*0.05+realtime)*sin(v[2]*0.05+realtime);
+			nv[2] = v[2];
+
+			glVertex3fv (nv);
+		}
+		glEnd ();
+
+	} else {
+		p = s->polys;
+
+		t = R_TextureAnimation (s->texinfo->texture);
+		GL_Bind (t->gl_texturenum);
+		DrawGLWaterPoly (p);
+
+		GL_Bind (lightmap_textures + s->lightmaptexturenum);
+		glEnable (GL_BLEND);
+		DrawGLWaterPolyLightmap (p);
+		glDisable (GL_BLEND);
+	}
+}
+#endif
+
+
+/*
+================
+DrawGLWaterPoly
+
+Warp the vertex coordinates
+================
+*/
+void DrawGLWaterPoly (glpoly_t *p)
+{
+	int		i;
+	float	*v;
+	float	s, t, os, ot;
+	vec3_t	nv;
+
+	GL_DisableMultitexture();
+
+	glBegin (GL_TRIANGLE_FAN);
+	v = p->verts[0];
+	for (i=0 ; i<p->numverts ; i++, v+= VERTEXSIZE)
+	{
+		glTexCoord2f (v[3], v[4]);
+
+		nv[0] = v[0] + 8*sin(v[1]*0.05+realtime)*sin(v[2]*0.05+realtime);
+		nv[1] = v[1] + 8*sin(v[0]*0.05+realtime)*sin(v[2]*0.05+realtime);
+		nv[2] = v[2];
+
+		glVertex3fv (nv);
+	}
+	glEnd ();
+}
+
+void DrawGLWaterPolyLightmap (glpoly_t *p)
+{
+	int		i;
+	float	*v;
+	float	s, t, os, ot;
+	vec3_t	nv;
+
+	GL_DisableMultitexture();
+
+	glBegin (GL_TRIANGLE_FAN);
+	v = p->verts[0];
+	for (i=0 ; i<p->numverts ; i++, v+= VERTEXSIZE)
+	{
+		glTexCoord2f (v[5], v[6]);
+
+		nv[0] = v[0] + 8*sin(v[1]*0.05+realtime)*sin(v[2]*0.05+realtime);
+		nv[1] = v[1] + 8*sin(v[0]*0.05+realtime)*sin(v[2]*0.05+realtime);
+		nv[2] = v[2];
+
+		glVertex3fv (nv);
+	}
+	glEnd ();
+}
+
+/*
+================
+DrawGLPoly
+================
+*/
+void DrawGLPoly (glpoly_t *p)
+{
+	int		i;
+	float	*v;
+
+	glBegin (GL_POLYGON);
+	v = p->verts[0];
+	for (i=0 ; i<p->numverts ; i++, v+= VERTEXSIZE)
+	{
+		glTexCoord2f (v[3], v[4]);
+		glVertex3fv (v);
+	}
+	glEnd ();
+}
+
+
+/*
+================
+R_BlendLightmaps
+================
+*/
+void R_BlendLightmaps (void)
+{
+	int			i, j;
+	glpoly_t	*p;
+	float		*v;
+	glRect_t	*theRect;
+
+	if (r_fullbright.value)
+		return;
+	if (!gl_texsort.value)
+		return;
+
+	glDepthMask (0);		// don't bother writing Z
+
+	if (gl_lightmap_format == GL_LUMINANCE)
+		glBlendFunc (GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
+	else if (gl_lightmap_format == GL_INTENSITY)
+	{
+		glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+		glColor4f (0,0,0,1);
+		glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+	}
+
+	if (!r_lightmap.value)
+	{
+		glEnable (GL_BLEND);
+	}
+
+	for (i=0 ; i<MAX_LIGHTMAPS ; i++)
+	{
+		p = lightmap_polys[i];
+		if (!p)
+			continue;
+		GL_Bind(lightmap_textures+i);
+		if (lightmap_modified[i])
+		{
+			lightmap_modified[i] = false;
+			theRect = &lightmap_rectchange[i];
+//			glTexImage2D (GL_TEXTURE_2D, 0, lightmap_bytes
+//			, BLOCK_WIDTH, BLOCK_HEIGHT, 0, 
+//			gl_lightmap_format, GL_UNSIGNED_BYTE, lightmaps+i*BLOCK_WIDTH*BLOCK_HEIGHT*lightmap_bytes);
+//			glTexImage2D (GL_TEXTURE_2D, 0, lightmap_bytes
+//				, BLOCK_WIDTH, theRect->h, 0, 
+//				gl_lightmap_format, GL_UNSIGNED_BYTE, lightmaps+(i*BLOCK_HEIGHT+theRect->t)*BLOCK_WIDTH*lightmap_bytes);
+			glTexSubImage2D(GL_TEXTURE_2D, 0, 0, theRect->t, 
+				BLOCK_WIDTH, theRect->h, gl_lightmap_format, GL_UNSIGNED_BYTE,
+				lightmaps+(i* BLOCK_HEIGHT + theRect->t) *BLOCK_WIDTH*lightmap_bytes);
+			theRect->l = BLOCK_WIDTH;
+			theRect->t = BLOCK_HEIGHT;
+			theRect->h = 0;
+			theRect->w = 0;
+		}
+		for ( ; p ; p=p->chain)
+		{
+			if (p->flags & SURF_UNDERWATER)
+				DrawGLWaterPolyLightmap (p);
+			else
+			{
+				glBegin (GL_POLYGON);
+				v = p->verts[0];
+				for (j=0 ; j<p->numverts ; j++, v+= VERTEXSIZE)
+				{
+					glTexCoord2f (v[5], v[6]);
+					glVertex3fv (v);
+				}
+				glEnd ();
+			}
+		}
+	}
+
+	glDisable (GL_BLEND);
+	if (gl_lightmap_format == GL_LUMINANCE)
+		glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+	else if (gl_lightmap_format == GL_INTENSITY)
+	{
+		glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+		glColor4f (1,1,1,1);
+	}
+
+	glDepthMask (1);		// back to normal Z buffering
+}
+
+/*
+================
+R_RenderBrushPoly
+================
+*/
+void R_RenderBrushPoly (msurface_t *fa)
+{
+	texture_t	*t;
+	byte		*base;
+	int			maps;
+	glRect_t    *theRect;
+	int smax, tmax;
+
+	c_brush_polys++;
+
+	if (fa->flags & SURF_DRAWSKY)
+	{	// warp texture, no lightmaps
+		EmitBothSkyLayers (fa);
+		return;
+	}
+		
+	t = R_TextureAnimation (fa->texinfo->texture);
+	GL_Bind (t->gl_texturenum);
+
+	if (fa->flags & SURF_DRAWTURB)
+	{	// warp texture, no lightmaps
+		EmitWaterPolys (fa);
+		return;
+	}
+
+	if (fa->flags & SURF_UNDERWATER)
+		DrawGLWaterPoly (fa->polys);
+	else
+		DrawGLPoly (fa->polys);
+
+	// add the poly to the proper lightmap chain
+
+	fa->polys->chain = lightmap_polys[fa->lightmaptexturenum];
+	lightmap_polys[fa->lightmaptexturenum] = fa->polys;
+
+	// check for lightmap modification
+	for (maps = 0 ; maps < MAXLIGHTMAPS && fa->styles[maps] != 255 ;
+		 maps++)
+		if (d_lightstylevalue[fa->styles[maps]] != fa->cached_light[maps])
+			goto dynamic;
+
+	if (fa->dlightframe == r_framecount	// dynamic this frame
+		|| fa->cached_dlight)			// dynamic previously
+	{
+dynamic:
+		if (r_dynamic.value)
+		{
+			lightmap_modified[fa->lightmaptexturenum] = true;
+			theRect = &lightmap_rectchange[fa->lightmaptexturenum];
+			if (fa->light_t < theRect->t) {
+				if (theRect->h)
+					theRect->h += theRect->t - fa->light_t;
+				theRect->t = fa->light_t;
+			}
+			if (fa->light_s < theRect->l) {
+				if (theRect->w)
+					theRect->w += theRect->l - fa->light_s;
+				theRect->l = fa->light_s;
+			}
+			smax = (fa->extents[0]>>4)+1;
+			tmax = (fa->extents[1]>>4)+1;
+			if ((theRect->w + theRect->l) < (fa->light_s + smax))
+				theRect->w = (fa->light_s-theRect->l)+smax;
+			if ((theRect->h + theRect->t) < (fa->light_t + tmax))
+				theRect->h = (fa->light_t-theRect->t)+tmax;
+			base = lightmaps + fa->lightmaptexturenum*lightmap_bytes*BLOCK_WIDTH*BLOCK_HEIGHT;
+			base += fa->light_t * BLOCK_WIDTH * lightmap_bytes + fa->light_s * lightmap_bytes;
+			R_BuildLightMap (fa, base, BLOCK_WIDTH*lightmap_bytes);
+		}
+	}
+}
+
+/*
+================
+R_RenderDynamicLightmaps
+Multitexture
+================
+*/
+void R_RenderDynamicLightmaps (msurface_t *fa)
+{
+	texture_t	*t;
+	byte		*base;
+	int			maps;
+	glRect_t    *theRect;
+	int smax, tmax;
+
+	c_brush_polys++;
+
+	if (fa->flags & ( SURF_DRAWSKY | SURF_DRAWTURB) )
+		return;
+		
+	fa->polys->chain = lightmap_polys[fa->lightmaptexturenum];
+	lightmap_polys[fa->lightmaptexturenum] = fa->polys;
+
+	// check for lightmap modification
+	for (maps = 0 ; maps < MAXLIGHTMAPS && fa->styles[maps] != 255 ;
+		 maps++)
+		if (d_lightstylevalue[fa->styles[maps]] != fa->cached_light[maps])
+			goto dynamic;
+
+	if (fa->dlightframe == r_framecount	// dynamic this frame
+		|| fa->cached_dlight)			// dynamic previously
+	{
+dynamic:
+		if (r_dynamic.value)
+		{
+			lightmap_modified[fa->lightmaptexturenum] = true;
+			theRect = &lightmap_rectchange[fa->lightmaptexturenum];
+			if (fa->light_t < theRect->t) {
+				if (theRect->h)
+					theRect->h += theRect->t - fa->light_t;
+				theRect->t = fa->light_t;
+			}
+			if (fa->light_s < theRect->l) {
+				if (theRect->w)
+					theRect->w += theRect->l - fa->light_s;
+				theRect->l = fa->light_s;
+			}
+			smax = (fa->extents[0]>>4)+1;
+			tmax = (fa->extents[1]>>4)+1;
+			if ((theRect->w + theRect->l) < (fa->light_s + smax))
+				theRect->w = (fa->light_s-theRect->l)+smax;
+			if ((theRect->h + theRect->t) < (fa->light_t + tmax))
+				theRect->h = (fa->light_t-theRect->t)+tmax;
+			base = lightmaps + fa->lightmaptexturenum*lightmap_bytes*BLOCK_WIDTH*BLOCK_HEIGHT;
+			base += fa->light_t * BLOCK_WIDTH * lightmap_bytes + fa->light_s * lightmap_bytes;
+			R_BuildLightMap (fa, base, BLOCK_WIDTH*lightmap_bytes);
+		}
+	}
+}
+
+/*
+================
+R_MirrorChain
+================
+*/
+void R_MirrorChain (msurface_t *s)
+{
+	if (mirror)
+		return;
+	mirror = true;
+	mirror_plane = s->plane;
+}
+
+
+#if 0
+/*
+================
+R_DrawWaterSurfaces
+================
+*/
+void R_DrawWaterSurfaces (void)
+{
+	int			i;
+	msurface_t	*s;
+	texture_t	*t;
+
+	if (r_wateralpha.value == 1.0)
+		return;
+
+	//
+	// go back to the world matrix
+	//
+    glLoadMatrixf (r_world_matrix);
+
+	glEnable (GL_BLEND);
+	glColor4f (1,1,1,r_wateralpha.value);
+	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+
+	for (i=0 ; i<cl.worldmodel->numtextures ; i++)
+	{
+		t = cl.worldmodel->textures[i];
+		if (!t)
+			continue;
+		s = t->texturechain;
+		if (!s)
+			continue;
+		if ( !(s->flags & SURF_DRAWTURB) )
+			continue;
+
+		// set modulate mode explicitly
+		GL_Bind (t->gl_texturenum);
+
+		for ( ; s ; s=s->texturechain)
+			R_RenderBrushPoly (s);
+
+		t->texturechain = NULL;
+	}
+
+	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+
+	glColor4f (1,1,1,1);
+	glDisable (GL_BLEND);
+}
+#else
+/*
+================
+R_DrawWaterSurfaces
+================
+*/
+void R_DrawWaterSurfaces (void)
+{
+	int			i;
+	msurface_t	*s;
+	texture_t	*t;
+
+	if (r_wateralpha.value == 1.0 && gl_texsort.value)
+		return;
+
+	//
+	// go back to the world matrix
+	//
+
+    glLoadMatrixf (r_world_matrix);
+
+	if (r_wateralpha.value < 1.0) {
+		glEnable (GL_BLEND);
+		glColor4f (1,1,1,r_wateralpha.value);
+		glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+	}
+
+	if (!gl_texsort.value) {
+		if (!waterchain)
+			return;
+
+		for ( s = waterchain ; s ; s=s->texturechain) {
+			GL_Bind (s->texinfo->texture->gl_texturenum);
+			EmitWaterPolys (s);
+		}
+		
+		waterchain = NULL;
+	} else {
+
+		for (i=0 ; i<cl.worldmodel->numtextures ; i++)
+		{
+			t = cl.worldmodel->textures[i];
+			if (!t)
+				continue;
+			s = t->texturechain;
+			if (!s)
+				continue;
+			if ( !(s->flags & SURF_DRAWTURB ) )
+				continue;
+
+			// set modulate mode explicitly
+			
+			GL_Bind (t->gl_texturenum);
+
+			for ( ; s ; s=s->texturechain)
+				EmitWaterPolys (s);
+			
+			t->texturechain = NULL;
+		}
+
+	}
+
+	if (r_wateralpha.value < 1.0) {
+		glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+
+		glColor4f (1,1,1,1);
+		glDisable (GL_BLEND);
+	}
+
+}
+
+#endif
+
+/*
+================
+DrawTextureChains
+================
+*/
+void DrawTextureChains (void)
+{
+	int		i;
+	msurface_t	*s;
+	texture_t	*t;
+
+	if (!gl_texsort.value) {
+		GL_DisableMultitexture();
+
+		if (skychain) {
+			R_DrawSkyChain(skychain);
+			skychain = NULL;
+		}
+
+		return;
+	} 
+
+	for (i=0 ; i<cl.worldmodel->numtextures ; i++)
+	{
+		t = cl.worldmodel->textures[i];
+		if (!t)
+			continue;
+		s = t->texturechain;
+		if (!s)
+			continue;
+		if (i == skytexturenum)
+			R_DrawSkyChain (s);
+		else if (i == mirrortexturenum && r_mirroralpha.value != 1.0)
+		{
+			R_MirrorChain (s);
+			continue;
+		}
+		else
+		{
+			if ((s->flags & SURF_DRAWTURB) && r_wateralpha.value != 1.0)
+				continue;	// draw translucent water later
+			for ( ; s ; s=s->texturechain)
+				R_RenderBrushPoly (s);
+		}
+
+		t->texturechain = NULL;
+	}
+}
+
+/*
+=================
+R_DrawBrushModel
+=================
+*/
+void R_DrawBrushModel (entity_t *e)
+{
+	int			j, k;
+	vec3_t		mins, maxs;
+	int			i, numsurfaces;
+	msurface_t	*psurf;
+	float		dot;
+	mplane_t	*pplane;
+	model_t		*clmodel;
+	qboolean	rotated;
+
+	currententity = e;
+	currenttexture = -1;
+
+	clmodel = e->model;
+
+	if (e->angles[0] || e->angles[1] || e->angles[2])
+	{
+		rotated = true;
+		for (i=0 ; i<3 ; i++)
+		{
+			mins[i] = e->origin[i] - clmodel->radius;
+			maxs[i] = e->origin[i] + clmodel->radius;
+		}
+	}
+	else
+	{
+		rotated = false;
+		VectorAdd (e->origin, clmodel->mins, mins);
+		VectorAdd (e->origin, clmodel->maxs, maxs);
+	}
+
+	if (R_CullBox (mins, maxs))
+		return;
+
+	glColor3f (1,1,1);
+	memset (lightmap_polys, 0, sizeof(lightmap_polys));
+
+	VectorSubtract (r_refdef.vieworg, e->origin, modelorg);
+	if (rotated)
+	{
+		vec3_t	temp;
+		vec3_t	forward, right, up;
+
+		VectorCopy (modelorg, temp);
+		AngleVectors (e->angles, forward, right, up);
+		modelorg[0] = DotProduct (temp, forward);
+		modelorg[1] = -DotProduct (temp, right);
+		modelorg[2] = DotProduct (temp, up);
+	}
+
+	psurf = &clmodel->surfaces[clmodel->firstmodelsurface];
+
+// calculate dynamic lighting for bmodel if it's not an
+// instanced model
+	if (clmodel->firstmodelsurface != 0 && !gl_flashblend.value)
+	{
+		for (k=0 ; k<MAX_DLIGHTS ; k++)
+		{
+			if ((cl_dlights[k].die < cl.time) ||
+				(!cl_dlights[k].radius))
+				continue;
+
+			R_MarkLights (&cl_dlights[k], 1<<k,
+				clmodel->nodes + clmodel->hulls[0].firstclipnode);
+		}
+	}
+
+    glPushMatrix ();
+e->angles[0] = -e->angles[0];	// stupid quake bug
+	R_RotateForEntity (e);
+e->angles[0] = -e->angles[0];	// stupid quake bug
+
+	//
+	// draw texture
+	//
+	for (i=0 ; i<clmodel->nummodelsurfaces ; i++, psurf++)
+	{
+	// find which side of the node we are on
+		pplane = psurf->plane;
+
+		dot = DotProduct (modelorg, pplane->normal) - pplane->dist;
+
+	// draw the polygon
+		if (((psurf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) ||
+			(!(psurf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON)))
+		{
+			if (gl_texsort.value)
+				R_RenderBrushPoly (psurf);
+			else
+				R_DrawSequentialPoly (psurf);
+		}
+	}
+
+	R_BlendLightmaps ();
+
+	glPopMatrix ();
+}
+
+/*
+=============================================================
+
+	WORLD MODEL
+
+=============================================================
+*/
+
+/*
+================
+R_RecursiveWorldNode
+================
+*/
+void R_RecursiveWorldNode (mnode_t *node)
+{
+	int			i, c, side, *pindex;
+	vec3_t		acceptpt, rejectpt;
+	mplane_t	*plane;
+	msurface_t	*surf, **mark;
+	mleaf_t		*pleaf;
+	double		d, dot;
+	vec3_t		mins, maxs;
+
+	if (node->contents == CONTENTS_SOLID)
+		return;		// solid
+
+	if (node->visframe != r_visframecount)
+		return;
+	if (R_CullBox (node->minmaxs, node->minmaxs+3))
+		return;
+	
+// if a leaf node, draw stuff
+	if (node->contents < 0)
+	{
+		pleaf = (mleaf_t *)node;
+
+		mark = pleaf->firstmarksurface;
+		c = pleaf->nummarksurfaces;
+
+		if (c)
+		{
+			do
+			{
+				(*mark)->visframe = r_framecount;
+				mark++;
+			} while (--c);
+		}
+
+	// deal with model fragments in this leaf
+		if (pleaf->efrags)
+			R_StoreEfrags (&pleaf->efrags);
+
+		return;
+	}
+
+// node is just a decision point, so go down the apropriate sides
+
+// find which side of the node we are on
+	plane = node->plane;
+
+	switch (plane->type)
+	{
+	case PLANE_X:
+		dot = modelorg[0] - plane->dist;
+		break;
+	case PLANE_Y:
+		dot = modelorg[1] - plane->dist;
+		break;
+	case PLANE_Z:
+		dot = modelorg[2] - plane->dist;
+		break;
+	default:
+		dot = DotProduct (modelorg, plane->normal) - plane->dist;
+		break;
+	}
+
+	if (dot >= 0)
+		side = 0;
+	else
+		side = 1;
+
+// recurse down the children, front side first
+	R_RecursiveWorldNode (node->children[side]);
+
+// draw stuff
+	c = node->numsurfaces;
+
+	if (c)
+	{
+		surf = cl.worldmodel->surfaces + node->firstsurface;
+
+		if (dot < 0 -BACKFACE_EPSILON)
+			side = SURF_PLANEBACK;
+		else if (dot > BACKFACE_EPSILON)
+			side = 0;
+		{
+			for ( ; c ; c--, surf++)
+			{
+				if (surf->visframe != r_framecount)
+					continue;
+
+				// don't backface underwater surfaces, because they warp
+				if ( !(surf->flags & SURF_UNDERWATER) && ( (dot < 0) ^ !!(surf->flags & SURF_PLANEBACK)) )
+					continue;		// wrong side
+
+				// if sorting by texture, just store it out
+				if (gl_texsort.value)
+				{
+					if (!mirror
+					|| surf->texinfo->texture != cl.worldmodel->textures[mirrortexturenum])
+					{
+						surf->texturechain = surf->texinfo->texture->texturechain;
+						surf->texinfo->texture->texturechain = surf;
+					}
+				} else if (surf->flags & SURF_DRAWSKY) {
+					surf->texturechain = skychain;
+					skychain = surf;
+				} else if (surf->flags & SURF_DRAWTURB) {
+					surf->texturechain = waterchain;
+					waterchain = surf;
+				} else
+					R_DrawSequentialPoly (surf);
+
+			}
+		}
+
+	}
+
+// recurse down the back side
+	R_RecursiveWorldNode (node->children[!side]);
+}
+
+
+
+/*
+=============
+R_DrawWorld
+=============
+*/
+void R_DrawWorld (void)
+{
+	entity_t	ent;
+	int			i;
+
+	memset (&ent, 0, sizeof(ent));
+	ent.model = cl.worldmodel;
+
+	VectorCopy (r_refdef.vieworg, modelorg);
+
+	currententity = &ent;
+	currenttexture = -1;
+
+	glColor3f (1,1,1);
+	memset (lightmap_polys, 0, sizeof(lightmap_polys));
+#ifdef QUAKE2
+	R_ClearSkyBox ();
+#endif
+
+	R_RecursiveWorldNode (cl.worldmodel->nodes);
+
+	DrawTextureChains ();
+
+	R_BlendLightmaps ();
+
+#ifdef QUAKE2
+	R_DrawSkyBox ();
+#endif
+}
+
+
+/*
+===============
+R_MarkLeaves
+===============
+*/
+void R_MarkLeaves (void)
+{
+	byte	*vis;
+	mnode_t	*node;
+	int		i;
+	byte	solid[4096];
+
+	if (r_oldviewleaf == r_viewleaf && !r_novis.value)
+		return;
+	
+	if (mirror)
+		return;
+
+	r_visframecount++;
+	r_oldviewleaf = r_viewleaf;
+
+	if (r_novis.value)
+	{
+		vis = solid;
+		memset (solid, 0xff, (cl.worldmodel->numleafs+7)>>3);
+	}
+	else
+		vis = Mod_LeafPVS (r_viewleaf, cl.worldmodel);
+		
+	for (i=0 ; i<cl.worldmodel->numleafs ; i++)
+	{
+		if (vis[i>>3] & (1<<(i&7)))
+		{
+			node = (mnode_t *)&cl.worldmodel->leafs[i+1];
+			do
+			{
+				if (node->visframe == r_visframecount)
+					break;
+				node->visframe = r_visframecount;
+				node = node->parent;
+			} while (node);
+		}
+	}
+}
+
+
+
+/*
+=============================================================================
+
+  LIGHTMAP ALLOCATION
+
+=============================================================================
+*/
+
+// returns a texture number and the position inside it
+int AllocBlock (int w, int h, int *x, int *y)
+{
+	int		i, j;
+	int		best, best2;
+	int		bestx;
+	int		texnum;
+
+	for (texnum=0 ; texnum<MAX_LIGHTMAPS ; texnum++)
+	{
+		best = BLOCK_HEIGHT;
+
+		for (i=0 ; i<BLOCK_WIDTH-w ; i++)
+		{
+			best2 = 0;
+
+			for (j=0 ; j<w ; j++)
+			{
+				if (allocated[texnum][i+j] >= best)
+					break;
+				if (allocated[texnum][i+j] > best2)
+					best2 = allocated[texnum][i+j];
+			}
+			if (j == w)
+			{	// this is a valid spot
+				*x = i;
+				*y = best = best2;
+			}
+		}
+
+		if (best + h > BLOCK_HEIGHT)
+			continue;
+
+		for (i=0 ; i<w ; i++)
+			allocated[texnum][*x + i] = best + h;
+
+		return texnum;
+	}
+
+	Sys_Error ("AllocBlock: full");
+}
+
+
+mvertex_t	*r_pcurrentvertbase;
+model_t		*currentmodel;
+
+int	nColinElim;
+
+/*
+================
+BuildSurfaceDisplayList
+================
+*/
+void BuildSurfaceDisplayList (msurface_t *fa)
+{
+	int			i, lindex, lnumverts, s_axis, t_axis;
+	float		dist, lastdist, lzi, scale, u, v, frac;
+	unsigned	mask;
+	vec3_t		local, transformed;
+	medge_t		*pedges, *r_pedge;
+	mplane_t	*pplane;
+	int			vertpage, newverts, newpage, lastvert;
+	qboolean	visible;
+	float		*vec;
+	float		s, t;
+	glpoly_t	*poly;
+
+// reconstruct the polygon
+	pedges = currentmodel->edges;
+	lnumverts = fa->numedges;
+	vertpage = 0;
+
+	//
+	// draw texture
+	//
+	poly = Hunk_Alloc (sizeof(glpoly_t) + (lnumverts-4) * VERTEXSIZE*sizeof(float));
+	poly->next = fa->polys;
+	poly->flags = fa->flags;
+	fa->polys = poly;
+	poly->numverts = lnumverts;
+
+	for (i=0 ; i<lnumverts ; i++)
+	{
+		lindex = currentmodel->surfedges[fa->firstedge + i];
+
+		if (lindex > 0)
+		{
+			r_pedge = &pedges[lindex];
+			vec = r_pcurrentvertbase[r_pedge->v[0]].position;
+		}
+		else
+		{
+			r_pedge = &pedges[-lindex];
+			vec = r_pcurrentvertbase[r_pedge->v[1]].position;
+		}
+		s = DotProduct (vec, fa->texinfo->vecs[0]) + fa->texinfo->vecs[0][3];
+		s /= fa->texinfo->texture->width;
+
+		t = DotProduct (vec, fa->texinfo->vecs[1]) + fa->texinfo->vecs[1][3];
+		t /= fa->texinfo->texture->height;
+
+		VectorCopy (vec, poly->verts[i]);
+		poly->verts[i][3] = s;
+		poly->verts[i][4] = t;
+
+		//
+		// lightmap texture coordinates
+		//
+		s = DotProduct (vec, fa->texinfo->vecs[0]) + fa->texinfo->vecs[0][3];
+		s -= fa->texturemins[0];
+		s += fa->light_s*16;
+		s += 8;
+		s /= BLOCK_WIDTH*16; //fa->texinfo->texture->width;
+
+		t = DotProduct (vec, fa->texinfo->vecs[1]) + fa->texinfo->vecs[1][3];
+		t -= fa->texturemins[1];
+		t += fa->light_t*16;
+		t += 8;
+		t /= BLOCK_HEIGHT*16; //fa->texinfo->texture->height;
+
+		poly->verts[i][5] = s;
+		poly->verts[i][6] = t;
+	}
+
+	//
+	// remove co-linear points - Ed
+	//
+	if (!gl_keeptjunctions.value && !(fa->flags & SURF_UNDERWATER) )
+	{
+		for (i = 0 ; i < lnumverts ; ++i)
+		{
+			vec3_t v1, v2;
+			float *prev, *this, *next;
+			float f;
+
+			prev = poly->verts[(i + lnumverts - 1) % lnumverts];
+			this = poly->verts[i];
+			next = poly->verts[(i + 1) % lnumverts];
+
+			VectorSubtract( this, prev, v1 );
+			VectorNormalize( v1 );
+			VectorSubtract( next, prev, v2 );
+			VectorNormalize( v2 );
+
+			// skip co-linear points
+			#define COLINEAR_EPSILON 0.001
+			if ((fabs( v1[0] - v2[0] ) <= COLINEAR_EPSILON) &&
+				(fabs( v1[1] - v2[1] ) <= COLINEAR_EPSILON) && 
+				(fabs( v1[2] - v2[2] ) <= COLINEAR_EPSILON))
+			{
+				int j;
+				for (j = i + 1; j < lnumverts; ++j)
+				{
+					int k;
+					for (k = 0; k < VERTEXSIZE; ++k)
+						poly->verts[j - 1][k] = poly->verts[j][k];
+				}
+				--lnumverts;
+				++nColinElim;
+				// retry next vertex next time, which is now current vertex
+				--i;
+			}
+		}
+	}
+	poly->numverts = lnumverts;
+
+}
+
+/*
+========================
+GL_CreateSurfaceLightmap
+========================
+*/
+void GL_CreateSurfaceLightmap (msurface_t *surf)
+{
+	int		smax, tmax, s, t, l, i;
+	byte	*base;
+
+	if (surf->flags & (SURF_DRAWSKY|SURF_DRAWTURB))
+		return;
+
+	smax = (surf->extents[0]>>4)+1;
+	tmax = (surf->extents[1]>>4)+1;
+
+	surf->lightmaptexturenum = AllocBlock (smax, tmax, &surf->light_s, &surf->light_t);
+	base = lightmaps + surf->lightmaptexturenum*lightmap_bytes*BLOCK_WIDTH*BLOCK_HEIGHT;
+	base += (surf->light_t * BLOCK_WIDTH + surf->light_s) * lightmap_bytes;
+	R_BuildLightMap (surf, base, BLOCK_WIDTH*lightmap_bytes);
+}
+
+
+/*
+==================
+GL_BuildLightmaps
+
+Builds the lightmap texture
+with all the surfaces from all brush models
+==================
+*/
+void GL_BuildLightmaps (void)
+{
+	int		i, j;
+	model_t	*m;
+	extern qboolean isPermedia;
+
+	memset (allocated, 0, sizeof(allocated));
+
+	r_framecount = 1;		// no dlightcache
+
+	if (!lightmap_textures)
+	{
+		lightmap_textures = texture_extension_number;
+		texture_extension_number += MAX_LIGHTMAPS;
+	}
+
+	gl_lightmap_format = GL_LUMINANCE;
+	// default differently on the Permedia
+	if (isPermedia)
+		gl_lightmap_format = GL_RGBA;
+
+	if (COM_CheckParm ("-lm_1"))
+		gl_lightmap_format = GL_LUMINANCE;
+	if (COM_CheckParm ("-lm_a"))
+		gl_lightmap_format = GL_ALPHA;
+	if (COM_CheckParm ("-lm_i"))
+		gl_lightmap_format = GL_INTENSITY;
+	if (COM_CheckParm ("-lm_2"))
+		gl_lightmap_format = GL_RGBA4;
+	if (COM_CheckParm ("-lm_4"))
+		gl_lightmap_format = GL_RGBA;
+
+	switch (gl_lightmap_format)
+	{
+	case GL_RGBA:
+		lightmap_bytes = 4;
+		break;
+	case GL_RGBA4:
+		lightmap_bytes = 2;
+		break;
+	case GL_LUMINANCE:
+	case GL_INTENSITY:
+	case GL_ALPHA:
+		lightmap_bytes = 1;
+		break;
+	}
+
+	for (j=1 ; j<MAX_MODELS ; j++)
+	{
+		m = cl.model_precache[j];
+		if (!m)
+			break;
+		if (m->name[0] == '*')
+			continue;
+		r_pcurrentvertbase = m->vertexes;
+		currentmodel = m;
+		for (i=0 ; i<m->numsurfaces ; i++)
+		{
+			GL_CreateSurfaceLightmap (m->surfaces + i);
+			if ( m->surfaces[i].flags & SURF_DRAWTURB )
+				continue;
+#ifndef QUAKE2
+			if ( m->surfaces[i].flags & SURF_DRAWSKY )
+				continue;
+#endif
+			BuildSurfaceDisplayList (m->surfaces + i);
+		}
+	}
+
+ 	if (!gl_texsort.value)
+ 		GL_SelectTexture(TEXTURE1_SGIS);
+
+	//
+	// upload all lightmaps that were filled
+	//
+	for (i=0 ; i<MAX_LIGHTMAPS ; i++)
+	{
+		if (!allocated[i][0])
+			break;		// no more used
+		lightmap_modified[i] = false;
+		lightmap_rectchange[i].l = BLOCK_WIDTH;
+		lightmap_rectchange[i].t = BLOCK_HEIGHT;
+		lightmap_rectchange[i].w = 0;
+		lightmap_rectchange[i].h = 0;
+		GL_Bind(lightmap_textures + i);
+		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+		glTexImage2D (GL_TEXTURE_2D, 0, lightmap_bytes
+		, BLOCK_WIDTH, BLOCK_HEIGHT, 0, 
+		gl_lightmap_format, GL_UNSIGNED_BYTE, lightmaps+i*BLOCK_WIDTH*BLOCK_HEIGHT*lightmap_bytes);
+	}
+
+ 	if (!gl_texsort.value)
+ 		GL_SelectTexture(TEXTURE0_SGIS);
+
+}
+
--- /dev/null
+++ b/WinQuake/gl_screen.c
@@ -1,0 +1,923 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+
+// screen.c -- master for refresh, status bar, console, chat, notify, etc
+
+#include "quakedef.h"
+
+/*
+
+background clear
+rendering
+turtle/net/ram icons
+sbar
+centerprint / slow centerprint
+notify lines
+intermission / finale overlay
+loading plaque
+console
+menu
+
+required background clears
+required update regions
+
+
+syncronous draw mode or async
+One off screen buffer, with updates either copied or xblited
+Need to double buffer?
+
+
+async draw will require the refresh area to be cleared, because it will be
+xblited, but sync draw can just ignore it.
+
+sync
+draw
+
+CenterPrint ()
+SlowPrint ()
+Screen_Update ();
+Con_Printf ();
+
+net 
+turn off messages option
+
+the refresh is allways rendered, unless the console is full screen
+
+
+console is:
+	notify lines
+	half
+	full
+	
+
+*/
+
+
+int			glx, gly, glwidth, glheight;
+
+// only the refresh window will be updated unless these variables are flagged 
+int			scr_copytop;
+int			scr_copyeverything;
+
+float		scr_con_current;
+float		scr_conlines;		// lines of console to display
+
+float		oldscreensize, oldfov;
+cvar_t		scr_viewsize = {"viewsize","100", true};
+cvar_t		scr_fov = {"fov","90"};	// 10 - 170
+cvar_t		scr_conspeed = {"scr_conspeed","300"};
+cvar_t		scr_centertime = {"scr_centertime","2"};
+cvar_t		scr_showram = {"showram","1"};
+cvar_t		scr_showturtle = {"showturtle","0"};
+cvar_t		scr_showpause = {"showpause","1"};
+cvar_t		scr_printspeed = {"scr_printspeed","8"};
+cvar_t		gl_triplebuffer = {"gl_triplebuffer", "1", true };
+
+extern	cvar_t	crosshair;
+
+qboolean	scr_initialized;		// ready to draw
+
+qpic_t		*scr_ram;
+qpic_t		*scr_net;
+qpic_t		*scr_turtle;
+
+int			scr_fullupdate;
+
+int			clearconsole;
+int			clearnotify;
+
+int			sb_lines;
+
+viddef_t	vid;				// global video state
+
+vrect_t		scr_vrect;
+
+qboolean	scr_disabled_for_loading;
+qboolean	scr_drawloading;
+float		scr_disabled_time;
+
+qboolean	block_drawing;
+
+void SCR_ScreenShot_f (void);
+
+/*
+===============================================================================
+
+CENTER PRINTING
+
+===============================================================================
+*/
+
+char		scr_centerstring[1024];
+float		scr_centertime_start;	// for slow victory printing
+float		scr_centertime_off;
+int			scr_center_lines;
+int			scr_erase_lines;
+int			scr_erase_center;
+
+/*
+==============
+SCR_CenterPrint
+
+Called for important messages that should stay in the center of the screen
+for a few moments
+==============
+*/
+void SCR_CenterPrint (char *str)
+{
+	strncpy (scr_centerstring, str, sizeof(scr_centerstring)-1);
+	scr_centertime_off = scr_centertime.value;
+	scr_centertime_start = cl.time;
+
+// count the number of lines for centering
+	scr_center_lines = 1;
+	while (*str)
+	{
+		if (*str == '\n')
+			scr_center_lines++;
+		str++;
+	}
+}
+
+
+void SCR_DrawCenterString (void)
+{
+	char	*start;
+	int		l;
+	int		j;
+	int		x, y;
+	int		remaining;
+
+// the finale prints the characters one at a time
+	if (cl.intermission)
+		remaining = scr_printspeed.value * (cl.time - scr_centertime_start);
+	else
+		remaining = 9999;
+
+	scr_erase_center = 0;
+	start = scr_centerstring;
+
+	if (scr_center_lines <= 4)
+		y = vid.height*0.35;
+	else
+		y = 48;
+
+	do	
+	{
+	// scan the width of the line
+		for (l=0 ; l<40 ; l++)
+			if (start[l] == '\n' || !start[l])
+				break;
+		x = (vid.width - l*8)/2;
+		for (j=0 ; j<l ; j++, x+=8)
+		{
+			Draw_Character (x, y, start[j]);	
+			if (!remaining--)
+				return;
+		}
+			
+		y += 8;
+
+		while (*start && *start != '\n')
+			start++;
+
+		if (!*start)
+			break;
+		start++;		// skip the \n
+	} while (1);
+}
+
+void SCR_CheckDrawCenterString (void)
+{
+	scr_copytop = 1;
+	if (scr_center_lines > scr_erase_lines)
+		scr_erase_lines = scr_center_lines;
+
+	scr_centertime_off -= host_frametime;
+	
+	if (scr_centertime_off <= 0 && !cl.intermission)
+		return;
+	if (key_dest != key_game)
+		return;
+
+	SCR_DrawCenterString ();
+}
+
+//=============================================================================
+
+/*
+====================
+CalcFov
+====================
+*/
+float CalcFov (float fov_x, float width, float height)
+{
+        float   a;
+        float   x;
+
+        if (fov_x < 1 || fov_x > 179)
+                Sys_Error ("Bad fov: %f", fov_x);
+
+        x = width/tan(fov_x/360*M_PI);
+
+        a = atan (height/x);
+
+        a = a*360/M_PI;
+
+        return a;
+}
+
+/*
+=================
+SCR_CalcRefdef
+
+Must be called whenever vid changes
+Internal use only
+=================
+*/
+static void SCR_CalcRefdef (void)
+{
+	vrect_t		vrect;
+	float		size;
+	int		h;
+	qboolean		full = false;
+
+
+	scr_fullupdate = 0;		// force a background redraw
+	vid.recalc_refdef = 0;
+
+// force the status bar to redraw
+	Sbar_Changed ();
+
+//========================================
+	
+// bound viewsize
+	if (scr_viewsize.value < 30)
+		Cvar_Set ("viewsize","30");
+	if (scr_viewsize.value > 120)
+		Cvar_Set ("viewsize","120");
+
+// bound field of view
+	if (scr_fov.value < 10)
+		Cvar_Set ("fov","10");
+	if (scr_fov.value > 170)
+		Cvar_Set ("fov","170");
+
+// intermission is always full screen	
+	if (cl.intermission)
+		size = 120;
+	else
+		size = scr_viewsize.value;
+
+	if (size >= 120)
+		sb_lines = 0;		// no status bar at all
+	else if (size >= 110)
+		sb_lines = 24;		// no inventory
+	else
+		sb_lines = 24+16+8;
+
+	if (scr_viewsize.value >= 100.0) {
+		full = true;
+		size = 100.0;
+	} else
+		size = scr_viewsize.value;
+	if (cl.intermission)
+	{
+		full = true;
+		size = 100;
+		sb_lines = 0;
+	}
+	size /= 100.0;
+
+	h = vid.height - sb_lines;
+
+	r_refdef.vrect.width = vid.width * size;
+	if (r_refdef.vrect.width < 96)
+	{
+		size = 96.0 / r_refdef.vrect.width;
+		r_refdef.vrect.width = 96;	// min for icons
+	}
+
+	r_refdef.vrect.height = vid.height * size;
+	if (r_refdef.vrect.height > vid.height - sb_lines)
+		r_refdef.vrect.height = vid.height - sb_lines;
+	if (r_refdef.vrect.height > vid.height)
+			r_refdef.vrect.height = vid.height;
+	r_refdef.vrect.x = (vid.width - r_refdef.vrect.width)/2;
+	if (full)
+		r_refdef.vrect.y = 0;
+	else 
+		r_refdef.vrect.y = (h - r_refdef.vrect.height)/2;
+
+	r_refdef.fov_x = scr_fov.value;
+	r_refdef.fov_y = CalcFov (r_refdef.fov_x, r_refdef.vrect.width, r_refdef.vrect.height);
+
+	scr_vrect = r_refdef.vrect;
+}
+
+
+/*
+=================
+SCR_SizeUp_f
+
+Keybinding command
+=================
+*/
+void SCR_SizeUp_f (void)
+{
+	Cvar_SetValue ("viewsize",scr_viewsize.value+10);
+	vid.recalc_refdef = 1;
+}
+
+
+/*
+=================
+SCR_SizeDown_f
+
+Keybinding command
+=================
+*/
+void SCR_SizeDown_f (void)
+{
+	Cvar_SetValue ("viewsize",scr_viewsize.value-10);
+	vid.recalc_refdef = 1;
+}
+
+//============================================================================
+
+/*
+==================
+SCR_Init
+==================
+*/
+void SCR_Init (void)
+{
+
+	Cvar_RegisterVariable (&scr_fov);
+	Cvar_RegisterVariable (&scr_viewsize);
+	Cvar_RegisterVariable (&scr_conspeed);
+	Cvar_RegisterVariable (&scr_showram);
+	Cvar_RegisterVariable (&scr_showturtle);
+	Cvar_RegisterVariable (&scr_showpause);
+	Cvar_RegisterVariable (&scr_centertime);
+	Cvar_RegisterVariable (&scr_printspeed);
+	Cvar_RegisterVariable (&gl_triplebuffer);
+
+//
+// register our commands
+//
+	Cmd_AddCommand ("screenshot",SCR_ScreenShot_f);
+	Cmd_AddCommand ("sizeup",SCR_SizeUp_f);
+	Cmd_AddCommand ("sizedown",SCR_SizeDown_f);
+
+	scr_ram = Draw_PicFromWad ("ram");
+	scr_net = Draw_PicFromWad ("net");
+	scr_turtle = Draw_PicFromWad ("turtle");
+
+	scr_initialized = true;
+}
+
+
+
+/*
+==============
+SCR_DrawRam
+==============
+*/
+void SCR_DrawRam (void)
+{
+	if (!scr_showram.value)
+		return;
+
+	if (!r_cache_thrash)
+		return;
+
+	Draw_Pic (scr_vrect.x+32, scr_vrect.y, scr_ram);
+}
+
+/*
+==============
+SCR_DrawTurtle
+==============
+*/
+void SCR_DrawTurtle (void)
+{
+	static int	count;
+	
+	if (!scr_showturtle.value)
+		return;
+
+	if (host_frametime < 0.1)
+	{
+		count = 0;
+		return;
+	}
+
+	count++;
+	if (count < 3)
+		return;
+
+	Draw_Pic (scr_vrect.x, scr_vrect.y, scr_turtle);
+}
+
+/*
+==============
+SCR_DrawNet
+==============
+*/
+void SCR_DrawNet (void)
+{
+	if (realtime - cl.last_received_message < 0.3)
+		return;
+	if (cls.demoplayback)
+		return;
+
+	Draw_Pic (scr_vrect.x+64, scr_vrect.y, scr_net);
+}
+
+/*
+==============
+DrawPause
+==============
+*/
+void SCR_DrawPause (void)
+{
+	qpic_t	*pic;
+
+	if (!scr_showpause.value)		// turn off for screenshots
+		return;
+
+	if (!cl.paused)
+		return;
+
+	pic = Draw_CachePic ("gfx/pause.lmp");
+	Draw_Pic ( (vid.width - pic->width)/2, 
+		(vid.height - 48 - pic->height)/2, pic);
+}
+
+
+
+/*
+==============
+SCR_DrawLoading
+==============
+*/
+void SCR_DrawLoading (void)
+{
+	qpic_t	*pic;
+
+	if (!scr_drawloading)
+		return;
+		
+	pic = Draw_CachePic ("gfx/loading.lmp");
+	Draw_Pic ( (vid.width - pic->width)/2, 
+		(vid.height - 48 - pic->height)/2, pic);
+}
+
+
+
+//=============================================================================
+
+
+/*
+==================
+SCR_SetUpToDrawConsole
+==================
+*/
+void SCR_SetUpToDrawConsole (void)
+{
+	Con_CheckResize ();
+	
+	if (scr_drawloading)
+		return;		// never a console with loading plaque
+		
+// decide on the height of the console
+	con_forcedup = !cl.worldmodel || cls.signon != SIGNONS;
+
+	if (con_forcedup)
+	{
+		scr_conlines = vid.height;		// full screen
+		scr_con_current = scr_conlines;
+	}
+	else if (key_dest == key_console)
+		scr_conlines = vid.height/2;	// half screen
+	else
+		scr_conlines = 0;				// none visible
+	
+	if (scr_conlines < scr_con_current)
+	{
+		scr_con_current -= scr_conspeed.value*host_frametime;
+		if (scr_conlines > scr_con_current)
+			scr_con_current = scr_conlines;
+
+	}
+	else if (scr_conlines > scr_con_current)
+	{
+		scr_con_current += scr_conspeed.value*host_frametime;
+		if (scr_conlines < scr_con_current)
+			scr_con_current = scr_conlines;
+	}
+
+	if (clearconsole++ < vid.numpages)
+	{
+		Sbar_Changed ();
+	}
+	else if (clearnotify++ < vid.numpages)
+	{
+	}
+	else
+		con_notifylines = 0;
+}
+	
+/*
+==================
+SCR_DrawConsole
+==================
+*/
+void SCR_DrawConsole (void)
+{
+	if (scr_con_current)
+	{
+		scr_copyeverything = 1;
+		Con_DrawConsole (scr_con_current, true);
+		clearconsole = 0;
+	}
+	else
+	{
+		if (key_dest == key_game || key_dest == key_message)
+			Con_DrawNotify ();	// only draw notify in game
+	}
+}
+
+
+/* 
+============================================================================== 
+ 
+						SCREEN SHOTS 
+ 
+============================================================================== 
+*/ 
+
+typedef struct _TargaHeader {
+	unsigned char 	id_length, colormap_type, image_type;
+	unsigned short	colormap_index, colormap_length;
+	unsigned char	colormap_size;
+	unsigned short	x_origin, y_origin, width, height;
+	unsigned char	pixel_size, attributes;
+} TargaHeader;
+
+
+/* 
+================== 
+SCR_ScreenShot_f
+================== 
+*/  
+void SCR_ScreenShot_f (void) 
+{
+	byte		*buffer;
+	char		pcxname[80]; 
+	char		checkname[MAX_OSPATH];
+	int			i, c, temp;
+// 
+// find a file name to save it to 
+// 
+	strcpy(pcxname,"quake00.tga");
+		
+	for (i=0 ; i<=99 ; i++) 
+	{ 
+		pcxname[5] = i/10 + '0'; 
+		pcxname[6] = i%10 + '0'; 
+		sprintf (checkname, "%s/%s", com_gamedir, pcxname);
+		if (Sys_FileTime(checkname) == -1)
+			break;	// file doesn't exist
+	} 
+	if (i==100) 
+	{
+		Con_Printf ("SCR_ScreenShot_f: Couldn't create a PCX file\n"); 
+		return;
+ 	}
+
+
+	buffer = malloc(glwidth*glheight*3 + 18);
+	memset (buffer, 0, 18);
+	buffer[2] = 2;		// uncompressed type
+	buffer[12] = glwidth&255;
+	buffer[13] = glwidth>>8;
+	buffer[14] = glheight&255;
+	buffer[15] = glheight>>8;
+	buffer[16] = 24;	// pixel size
+
+	glReadPixels (glx, gly, glwidth, glheight, GL_RGB, GL_UNSIGNED_BYTE, buffer+18 ); 
+
+	// swap rgb to bgr
+	c = 18+glwidth*glheight*3;
+	for (i=18 ; i<c ; i+=3)
+	{
+		temp = buffer[i];
+		buffer[i] = buffer[i+2];
+		buffer[i+2] = temp;
+	}
+	COM_WriteFile (pcxname, buffer, glwidth*glheight*3 + 18 );
+
+	free (buffer);
+	Con_Printf ("Wrote %s\n", pcxname);
+} 
+
+
+//=============================================================================
+
+
+/*
+===============
+SCR_BeginLoadingPlaque
+
+================
+*/
+void SCR_BeginLoadingPlaque (void)
+{
+	S_StopAllSounds (true);
+
+	if (cls.state != ca_connected)
+		return;
+	if (cls.signon != SIGNONS)
+		return;
+	
+// redraw with no console and the loading plaque
+	Con_ClearNotify ();
+	scr_centertime_off = 0;
+	scr_con_current = 0;
+
+	scr_drawloading = true;
+	scr_fullupdate = 0;
+	Sbar_Changed ();
+	SCR_UpdateScreen ();
+	scr_drawloading = false;
+
+	scr_disabled_for_loading = true;
+	scr_disabled_time = realtime;
+	scr_fullupdate = 0;
+}
+
+/*
+===============
+SCR_EndLoadingPlaque
+
+================
+*/
+void SCR_EndLoadingPlaque (void)
+{
+	scr_disabled_for_loading = false;
+	scr_fullupdate = 0;
+	Con_ClearNotify ();
+}
+
+//=============================================================================
+
+char	*scr_notifystring;
+qboolean	scr_drawdialog;
+
+void SCR_DrawNotifyString (void)
+{
+	char	*start;
+	int		l;
+	int		j;
+	int		x, y;
+
+	start = scr_notifystring;
+
+	y = vid.height*0.35;
+
+	do	
+	{
+	// scan the width of the line
+		for (l=0 ; l<40 ; l++)
+			if (start[l] == '\n' || !start[l])
+				break;
+		x = (vid.width - l*8)/2;
+		for (j=0 ; j<l ; j++, x+=8)
+			Draw_Character (x, y, start[j]);	
+			
+		y += 8;
+
+		while (*start && *start != '\n')
+			start++;
+
+		if (!*start)
+			break;
+		start++;		// skip the \n
+	} while (1);
+}
+
+/*
+==================
+SCR_ModalMessage
+
+Displays a text string in the center of the screen and waits for a Y or N
+keypress.  
+==================
+*/
+int SCR_ModalMessage (char *text)
+{
+	if (cls.state == ca_dedicated)
+		return true;
+
+	scr_notifystring = text;
+ 
+// draw a fresh screen
+	scr_fullupdate = 0;
+	scr_drawdialog = true;
+	SCR_UpdateScreen ();
+	scr_drawdialog = false;
+	
+	S_ClearBuffer ();		// so dma doesn't loop current sound
+
+	do
+	{
+		key_count = -1;		// wait for a key down and up
+		Sys_SendKeyEvents ();
+	} while (key_lastpress != 'y' && key_lastpress != 'n' && key_lastpress != K_ESCAPE);
+
+	scr_fullupdate = 0;
+	SCR_UpdateScreen ();
+
+	return key_lastpress == 'y';
+}
+
+
+//=============================================================================
+
+/*
+===============
+SCR_BringDownConsole
+
+Brings the console down and fades the palettes back to normal
+================
+*/
+void SCR_BringDownConsole (void)
+{
+	int		i;
+	
+	scr_centertime_off = 0;
+	
+	for (i=0 ; i<20 && scr_conlines != scr_con_current ; i++)
+		SCR_UpdateScreen ();
+
+	cl.cshifts[0].percent = 0;		// no area contents palette on next frame
+	VID_SetPalette (host_basepal);
+}
+
+void SCR_TileClear (void)
+{
+	if (r_refdef.vrect.x > 0) {
+		// left
+		Draw_TileClear (0, 0, r_refdef.vrect.x, vid.height - sb_lines);
+		// right
+		Draw_TileClear (r_refdef.vrect.x + r_refdef.vrect.width, 0, 
+			vid.width - r_refdef.vrect.x + r_refdef.vrect.width, 
+			vid.height - sb_lines);
+	}
+	if (r_refdef.vrect.y > 0) {
+		// top
+		Draw_TileClear (r_refdef.vrect.x, 0, 
+			r_refdef.vrect.x + r_refdef.vrect.width, 
+			r_refdef.vrect.y);
+		// bottom
+		Draw_TileClear (r_refdef.vrect.x,
+			r_refdef.vrect.y + r_refdef.vrect.height, 
+			r_refdef.vrect.width, 
+			vid.height - sb_lines - 
+			(r_refdef.vrect.height + r_refdef.vrect.y));
+	}
+}
+
+/*
+==================
+SCR_UpdateScreen
+
+This is called every frame, and can also be called explicitly to flush
+text to the screen.
+
+WARNING: be very careful calling this from elsewhere, because the refresh
+needs almost the entire 256k of stack space!
+==================
+*/
+void SCR_UpdateScreen (void)
+{
+	static float	oldscr_viewsize;
+	vrect_t		vrect;
+
+	if (block_drawing)
+		return;
+
+	vid.numpages = 2 + gl_triplebuffer.value;
+
+	scr_copytop = 0;
+	scr_copyeverything = 0;
+
+	if (scr_disabled_for_loading)
+	{
+		if (realtime - scr_disabled_time > 60)
+		{
+			scr_disabled_for_loading = false;
+			Con_Printf ("load failed.\n");
+		}
+		else
+			return;
+	}
+
+	if (!scr_initialized || !con_initialized)
+		return;				// not initialized yet
+
+
+	GL_BeginRendering (&glx, &gly, &glwidth, &glheight);
+	
+	//
+	// determine size of refresh window
+	//
+	if (oldfov != scr_fov.value)
+	{
+		oldfov = scr_fov.value;
+		vid.recalc_refdef = true;
+	}
+
+	if (oldscreensize != scr_viewsize.value)
+	{
+		oldscreensize = scr_viewsize.value;
+		vid.recalc_refdef = true;
+	}
+
+	if (vid.recalc_refdef)
+		SCR_CalcRefdef ();
+
+//
+// do 3D refresh drawing, and then update the screen
+//
+	SCR_SetUpToDrawConsole ();
+	
+	V_RenderView ();
+
+	GL_Set2D ();
+
+	//
+	// draw any areas not covered by the refresh
+	//
+	SCR_TileClear ();
+
+	if (scr_drawdialog)
+	{
+		Sbar_Draw ();
+		Draw_FadeScreen ();
+		SCR_DrawNotifyString ();
+		scr_copyeverything = true;
+	}
+	else if (scr_drawloading)
+	{
+		SCR_DrawLoading ();
+		Sbar_Draw ();
+	}
+	else if (cl.intermission == 1 && key_dest == key_game)
+	{
+		Sbar_IntermissionOverlay ();
+	}
+	else if (cl.intermission == 2 && key_dest == key_game)
+	{
+		Sbar_FinaleOverlay ();
+		SCR_CheckDrawCenterString ();
+	}
+	else
+	{
+		if (crosshair.value)
+			Draw_Character (scr_vrect.x + scr_vrect.width/2, scr_vrect.y + scr_vrect.height/2, '+');
+		
+		SCR_DrawRam ();
+		SCR_DrawNet ();
+		SCR_DrawTurtle ();
+		SCR_DrawPause ();
+		SCR_CheckDrawCenterString ();
+		Sbar_Draw ();
+		SCR_DrawConsole ();	
+		M_Draw ();
+	}
+
+	V_UpdatePalette ();
+
+	GL_EndRendering ();
+}
+
--- /dev/null
+++ b/WinQuake/gl_vidlinux.c
@@ -1,0 +1,866 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+#include <termios.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/vt.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <signal.h>
+
+#include <asm/io.h>
+#include <dlfcn.h>
+
+/*#include "vga.h" */
+#include "vgakeyboard.h"
+#include "vgamouse.h"
+
+#include "quakedef.h"
+#include "GL/fxmesa.h"
+
+#define WARP_WIDTH              320
+#define WARP_HEIGHT             200
+
+static fxMesaContext fc = NULL;
+#define stringify(m) { #m, m }
+
+unsigned short	d_8to16table[256];
+unsigned	d_8to24table[256];
+unsigned char d_15to8table[65536];
+
+int num_shades=32;
+
+struct
+{
+	char *name;
+	int num;
+} mice[] =
+{
+	stringify(MOUSE_MICROSOFT),
+	stringify(MOUSE_MOUSESYSTEMS),
+	stringify(MOUSE_MMSERIES),
+	stringify(MOUSE_LOGITECH),
+	stringify(MOUSE_BUSMOUSE),
+	stringify(MOUSE_PS2),
+};
+
+static unsigned char scantokey[128];
+
+int num_mice = sizeof (mice) / sizeof(mice[0]);
+
+int	d_con_indirect = 0;
+
+int		svgalib_inited=0;
+int		UseMouse = 1;
+int		UseKeyboard = 1;
+
+int		mouserate = MOUSE_DEFAULTSAMPLERATE;
+
+cvar_t		vid_mode = {"vid_mode","5",false};
+cvar_t		vid_redrawfull = {"vid_redrawfull","0",false};
+cvar_t		vid_waitforrefresh = {"vid_waitforrefresh","0",true};
+ 
+char	*framebuffer_ptr;
+
+cvar_t  mouse_button_commands[3] =
+{
+    {"mouse1","+attack"},
+    {"mouse2","+strafe"},
+    {"mouse3","+forward"},
+};
+
+int     mouse_buttons;
+int     mouse_buttonstate;
+int     mouse_oldbuttonstate;
+float   mouse_x, mouse_y;
+float	old_mouse_x, old_mouse_y;
+int		mx, my;
+
+cvar_t	m_filter = {"m_filter","1"};
+
+int scr_width, scr_height;
+
+/*-----------------------------------------------------------------------*/
+
+//int		texture_mode = GL_NEAREST;
+//int		texture_mode = GL_NEAREST_MIPMAP_NEAREST;
+//int		texture_mode = GL_NEAREST_MIPMAP_LINEAR;
+int		texture_mode = GL_LINEAR;
+//int		texture_mode = GL_LINEAR_MIPMAP_NEAREST;
+//int		texture_mode = GL_LINEAR_MIPMAP_LINEAR;
+
+int		texture_extension_number = 1;
+
+float		gldepthmin, gldepthmax;
+
+cvar_t	gl_ztrick = {"gl_ztrick","1"};
+
+const char *gl_vendor;
+const char *gl_renderer;
+const char *gl_version;
+const char *gl_extensions;
+
+void (*qgl3DfxSetPaletteEXT) (GLuint *);
+void (*qglColorTableEXT) (int, int, int, int, int, const void *);
+
+static float vid_gamma = 1.0;
+
+qboolean is8bit = false;
+qboolean isPermedia = false;
+qboolean gl_mtexable = false;
+
+/*-----------------------------------------------------------------------*/
+void D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height)
+{
+}
+
+void D_EndDirectRect (int x, int y, int width, int height)
+{
+}
+
+int matchmouse(int mouse, char *name)
+{
+	int i;
+	for (i=0 ; i<num_mice ; i++)
+		if (!strcmp(mice[i].name, name))
+			return i;
+	return mouse;
+}
+
+#if 0
+
+void vtswitch(int newconsole)
+{
+
+	int fd;
+	struct vt_stat x;
+
+// switch consoles and wait until reactivated
+	fd = open("/dev/console", O_RDONLY);
+	ioctl(fd, VT_GETSTATE, &x);
+	ioctl(fd, VT_ACTIVATE, newconsole);
+	ioctl(fd, VT_WAITACTIVE, x.v_active);
+	close(fd);
+
+}
+
+#endif
+
+void keyhandler(int scancode, int state)
+{
+	
+	int sc;
+
+	sc = scancode & 0x7f;
+
+	Key_Event(scantokey[sc], state == KEY_EVENTPRESS);
+
+}
+
+void VID_Shutdown(void)
+{
+	if (!fc)
+		return;
+
+	fxMesaDestroyContext(fc);
+
+	if (UseKeyboard)
+		keyboard_close();
+}
+
+void signal_handler(int sig)
+{
+	printf("Received signal %d, exiting...\n", sig);
+	Sys_Quit();
+	exit(0);
+}
+
+void InitSig(void)
+{
+	signal(SIGHUP, signal_handler);
+	signal(SIGINT, signal_handler);
+	signal(SIGQUIT, signal_handler);
+	signal(SIGILL, signal_handler);
+	signal(SIGTRAP, signal_handler);
+	signal(SIGIOT, signal_handler);
+	signal(SIGBUS, signal_handler);
+	signal(SIGFPE, signal_handler);
+	signal(SIGSEGV, signal_handler);
+	signal(SIGTERM, signal_handler);
+}
+
+void VID_ShiftPalette(unsigned char *p)
+{
+//	VID_SetPalette(p);
+}
+
+void	VID_SetPalette (unsigned char *palette)
+{
+	byte	*pal;
+	unsigned r,g,b;
+	unsigned v;
+	int     r1,g1,b1;
+	int		j,k,l,m;
+	unsigned short i;
+	unsigned	*table;
+	FILE *f;
+	char s[255];
+	int dist, bestdist;
+	static qboolean palflag = false;
+
+//
+// 8 8 8 encoding
+//
+	pal = palette;
+	table = d_8to24table;
+	for (i=0 ; i<256 ; i++)
+	{
+		r = pal[0];
+		g = pal[1];
+		b = pal[2];
+		pal += 3;
+		
+		v = (255<<24) + (r<<0) + (g<<8) + (b<<16);
+		*table++ = v;
+	}
+	d_8to24table[255] &= 0xffffff;	// 255 is transparent
+
+	// JACK: 3D distance calcs - k is last closest, l is the distance.
+	for (i=0; i < (1<<15); i++) {
+		/* Maps
+		000000000000000
+		000000000011111 = Red  = 0x1F
+		000001111100000 = Blue = 0x03E0
+		111110000000000 = Grn  = 0x7C00
+		*/
+		r = ((i & 0x1F) << 3)+4;
+		g = ((i & 0x03E0) >> 2)+4;
+		b = ((i & 0x7C00) >> 7)+4;
+		pal = (unsigned char *)d_8to24table;
+		for (v=0,k=0,bestdist=10000*10000; v<256; v++,pal+=4) {
+			r1 = (int)r - (int)pal[0];
+			g1 = (int)g - (int)pal[1];
+			b1 = (int)b - (int)pal[2];
+			dist = (r1*r1)+(g1*g1)+(b1*b1);
+			if (dist < bestdist) {
+				k=v;
+				bestdist = dist;
+			}
+		}
+		d_15to8table[i]=k;
+	}
+}
+
+void CheckMultiTextureExtensions(void) 
+{
+	void *prjobj;
+
+	if (strstr(gl_extensions, "GL_SGIS_multitexture ") && !COM_CheckParm("-nomtex")) {
+		Con_Printf("Found GL_SGIS_multitexture...\n");
+
+		if ((prjobj = dlopen(NULL, RTLD_LAZY)) == NULL) {
+			Con_Printf("Unable to open symbol list for main program.\n");
+			return;
+		}
+
+		qglMTexCoord2fSGIS = (void *) dlsym(prjobj, "glMTexCoord2fSGIS");
+		qglSelectTextureSGIS = (void *) dlsym(prjobj, "glSelectTextureSGIS");
+
+		if (qglMTexCoord2fSGIS && qglSelectTextureSGIS) {
+			Con_Printf("Multitexture extensions found.\n");
+			gl_mtexable = true;
+		} else
+			Con_Printf("Symbol not found, disabled.\n");
+
+		dlclose(prjobj);
+	}
+}
+
+/*
+===============
+GL_Init
+===============
+*/
+void GL_Init (void)
+{
+	gl_vendor = glGetString (GL_VENDOR);
+	Con_Printf ("GL_VENDOR: %s\n", gl_vendor);
+	gl_renderer = glGetString (GL_RENDERER);
+	Con_Printf ("GL_RENDERER: %s\n", gl_renderer);
+
+	gl_version = glGetString (GL_VERSION);
+	Con_Printf ("GL_VERSION: %s\n", gl_version);
+	gl_extensions = glGetString (GL_EXTENSIONS);
+	Con_Printf ("GL_EXTENSIONS: %s\n", gl_extensions);
+
+//	Con_Printf ("%s %s\n", gl_renderer, gl_version);
+
+	CheckMultiTextureExtensions ();
+
+	glClearColor (1,0,0,0);
+	glCullFace(GL_FRONT);
+	glEnable(GL_TEXTURE_2D);
+
+	glEnable(GL_ALPHA_TEST);
+	glAlphaFunc(GL_GREATER, 0.666);
+
+	glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
+	glShadeModel (GL_FLAT);
+
+	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+
+	glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+//	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+}
+
+/*
+=================
+GL_BeginRendering
+
+=================
+*/
+void GL_BeginRendering (int *x, int *y, int *width, int *height)
+{
+	extern cvar_t gl_clear;
+
+	*x = *y = 0;
+	*width = scr_width;
+	*height = scr_height;
+
+//    if (!wglMakeCurrent( maindc, baseRC ))
+//		Sys_Error ("wglMakeCurrent failed");
+
+//	glViewport (*x, *y, *width, *height);
+}
+
+
+void GL_EndRendering (void)
+{
+	glFlush();
+	fxMesaSwapBuffers();
+}
+
+void Init_KBD(void)
+{
+	int i;
+
+	if (COM_CheckParm("-nokbd")) UseKeyboard = 0;
+
+	if (UseKeyboard)
+	{
+		for (i=0 ; i<128 ; i++)
+			scantokey[i] = ' ';
+
+		scantokey[42] = K_SHIFT;
+		scantokey[54] = K_SHIFT;
+		scantokey[72] = K_UPARROW;
+		scantokey[103] = K_UPARROW;
+		scantokey[80] = K_DOWNARROW;
+		scantokey[108] = K_DOWNARROW;
+		scantokey[75] = K_LEFTARROW;
+		scantokey[105] = K_LEFTARROW;
+		scantokey[77] = K_RIGHTARROW;
+		scantokey[106] = K_RIGHTARROW;
+		scantokey[29] = K_CTRL;
+		scantokey[97] = K_CTRL;
+		scantokey[56] = K_ALT;
+		scantokey[100] = K_ALT;
+//		scantokey[58] = JK_CAPS;
+//		scantokey[69] = JK_NUM_LOCK;
+		scantokey[71] = K_HOME;
+		scantokey[73] = K_PGUP;
+		scantokey[79] = K_END;
+		scantokey[81] = K_PGDN;
+		scantokey[82] = K_INS;
+		scantokey[83] = K_DEL;
+		scantokey[1 ] = K_ESCAPE;
+		scantokey[28] = K_ENTER;
+		scantokey[15] = K_TAB;
+		scantokey[14] = K_BACKSPACE;
+		scantokey[119] = K_PAUSE;
+		scantokey[57] = ' ';
+
+		scantokey[102] = K_HOME;
+		scantokey[104] = K_PGUP;
+		scantokey[107] = K_END;
+		scantokey[109] = K_PGDN;
+		scantokey[110] = K_INS;
+		scantokey[111] = K_DEL;
+
+		scantokey[2] = '1';
+		scantokey[3] = '2';
+		scantokey[4] = '3';
+		scantokey[5] = '4';
+		scantokey[6] = '5';
+		scantokey[7] = '6';
+		scantokey[8] = '7';
+		scantokey[9] = '8';
+		scantokey[10] = '9';
+		scantokey[11] = '0';
+		scantokey[12] = '-';
+		scantokey[13] = '=';
+		scantokey[41] = '`';
+		scantokey[26] = '[';
+		scantokey[27] = ']';
+		scantokey[39] = ';';
+		scantokey[40] = '\'';
+		scantokey[51] = ',';
+		scantokey[52] = '.';
+		scantokey[53] = '/';
+		scantokey[43] = '\\';
+
+		scantokey[59] = K_F1;
+		scantokey[60] = K_F2;
+		scantokey[61] = K_F3;
+		scantokey[62] = K_F4;
+		scantokey[63] = K_F5;
+		scantokey[64] = K_F6;
+		scantokey[65] = K_F7;
+		scantokey[66] = K_F8;
+		scantokey[67] = K_F9;
+		scantokey[68] = K_F10;
+		scantokey[87] = K_F11;
+		scantokey[88] = K_F12;
+		scantokey[30] = 'a';
+		scantokey[48] = 'b';
+		scantokey[46] = 'c';
+		scantokey[32] = 'd';       
+		scantokey[18] = 'e';       
+		scantokey[33] = 'f';       
+		scantokey[34] = 'g';       
+		scantokey[35] = 'h';       
+		scantokey[23] = 'i';       
+		scantokey[36] = 'j';       
+		scantokey[37] = 'k';       
+		scantokey[38] = 'l';       
+		scantokey[50] = 'm';       
+		scantokey[49] = 'n';       
+		scantokey[24] = 'o';       
+		scantokey[25] = 'p';       
+		scantokey[16] = 'q';       
+		scantokey[19] = 'r';       
+		scantokey[31] = 's';       
+		scantokey[20] = 't';       
+		scantokey[22] = 'u';       
+		scantokey[47] = 'v';       
+		scantokey[17] = 'w';       
+		scantokey[45] = 'x';       
+		scantokey[21] = 'y';       
+		scantokey[44] = 'z';       
+
+		scantokey[78] = '+';
+		scantokey[74] = '-';
+
+		if (keyboard_init())
+			Sys_Error("keyboard_init() failed");
+		keyboard_seteventhandler(keyhandler);
+	}
+}
+
+#define NUM_RESOLUTIONS 16
+
+static int resolutions[NUM_RESOLUTIONS][3]={ 
+	320,200,  GR_RESOLUTION_320x200,
+	320,240,  GR_RESOLUTION_320x240,
+	400,256,  GR_RESOLUTION_400x256,
+	400,300,  GR_RESOLUTION_400x300,
+	512,384,  GR_RESOLUTION_512x384,
+	640,200,  GR_RESOLUTION_640x200,
+	640,350,  GR_RESOLUTION_640x350,
+	640,400,  GR_RESOLUTION_640x400,
+	640,480,  GR_RESOLUTION_640x480,
+	800,600,  GR_RESOLUTION_800x600,
+	960,720,  GR_RESOLUTION_960x720,
+	856,480,  GR_RESOLUTION_856x480,
+	512,256,  GR_RESOLUTION_512x256,
+	1024,768, GR_RESOLUTION_1024x768,
+	1280,1024,GR_RESOLUTION_1280x1024,
+	1600,1200,GR_RESOLUTION_1600x1200
+};
+
+int findres(int *width, int *height)
+{
+	int i;
+
+	for(i=0;i<NUM_RESOLUTIONS;i++)
+		if((*width<=resolutions[i][0]) && (*height<=resolutions[i][1])) {
+			*width = resolutions[i][0];
+			*height = resolutions[i][1];
+			return resolutions[i][2];
+		}
+        
+	*width = 640;
+	*height = 480;
+	return GR_RESOLUTION_640x480;
+}
+
+qboolean VID_Is8bit(void)
+{
+	return is8bit;
+}
+
+void VID_Init8bitPalette(void) 
+{
+	// Check for 8bit Extensions and initialize them.
+	int i;
+	void *prjobj;
+
+	if (COM_CheckParm("-no8bit"))
+		return;
+
+	if ((prjobj = dlopen(NULL, RTLD_LAZY)) == NULL) {
+		Con_Printf("Unable to open symbol list for main program.\n");
+		return;
+	}
+
+	if (strstr(gl_extensions, "3DFX_set_global_palette") &&
+		(qgl3DfxSetPaletteEXT = dlsym(prjobj, "gl3DfxSetPaletteEXT")) != NULL) {
+		GLubyte table[256][4];
+		char *oldpal;
+
+		Con_SafePrintf("... Using 3DFX_set_global_palette\n");
+		glEnable( GL_SHARED_TEXTURE_PALETTE_EXT );
+		oldpal = (char *) d_8to24table; //d_8to24table3dfx;
+		for (i=0;i<256;i++) {
+			table[i][2] = *oldpal++;
+			table[i][1] = *oldpal++;
+			table[i][0] = *oldpal++;
+			table[i][3] = 255;
+			oldpal++;
+		}
+		qgl3DfxSetPaletteEXT((GLuint *)table);
+		is8bit = true;
+
+	} else if (strstr(gl_extensions, "GL_EXT_shared_texture_palette") &&
+		(qglColorTableEXT = dlsym(prjobj, "glColorTableEXT")) != NULL) {
+		char thePalette[256*3];
+		char *oldPalette, *newPalette;
+
+		Con_SafePrintf("... Using GL_EXT_shared_texture_palette\n");
+		glEnable( GL_SHARED_TEXTURE_PALETTE_EXT );
+		oldPalette = (char *) d_8to24table; //d_8to24table3dfx;
+		newPalette = thePalette;
+		for (i=0;i<256;i++) {
+			*newPalette++ = *oldPalette++;
+			*newPalette++ = *oldPalette++;
+			*newPalette++ = *oldPalette++;
+			oldPalette++;
+		}
+		qglColorTableEXT(GL_SHARED_TEXTURE_PALETTE_EXT, GL_RGB, 256, GL_RGB, GL_UNSIGNED_BYTE, (void *) thePalette);
+		is8bit = true;
+	
+	}
+
+	dlclose(prjobj);
+}
+
+static void Check_Gamma (unsigned char *pal)
+{
+	float	f, inf;
+	unsigned char	palette[768];
+	int		i;
+
+	if ((i = COM_CheckParm("-gamma")) == 0) {
+		if ((gl_renderer && strstr(gl_renderer, "Voodoo")) ||
+			(gl_vendor && strstr(gl_vendor, "3Dfx")))
+			vid_gamma = 1;
+		else
+			vid_gamma = 0.7; // default to 0.7 on non-3dfx hardware
+	} else
+		vid_gamma = Q_atof(com_argv[i+1]);
+
+	for (i=0 ; i<768 ; i++)
+	{
+		f = pow ( (pal[i]+1)/256.0 , vid_gamma );
+		inf = f*255 + 0.5;
+		if (inf < 0)
+			inf = 0;
+		if (inf > 255)
+			inf = 255;
+		palette[i] = inf;
+	}
+
+	memcpy (pal, palette, sizeof(palette));
+}
+
+void VID_Init(unsigned char *palette)
+{
+	int i;
+	GLint attribs[32];
+	char	gldir[MAX_OSPATH];
+	int width = 640, height = 480;
+
+	Init_KBD();
+
+	Cvar_RegisterVariable (&vid_mode);
+	Cvar_RegisterVariable (&vid_redrawfull);
+	Cvar_RegisterVariable (&vid_waitforrefresh);
+	Cvar_RegisterVariable (&gl_ztrick);
+	
+	vid.maxwarpwidth = WARP_WIDTH;
+	vid.maxwarpheight = WARP_HEIGHT;
+	vid.colormap = host_colormap;
+	vid.fullbright = 256 - LittleLong (*((int *)vid.colormap + 2048));
+
+// interpret command-line params
+
+// set vid parameters
+	attribs[0] = FXMESA_DOUBLEBUFFER;
+	attribs[1] = FXMESA_ALPHA_SIZE;
+	attribs[2] = 1;
+	attribs[3] = FXMESA_DEPTH_SIZE;
+	attribs[4] = 1;
+	attribs[5] = FXMESA_NONE;
+
+	if ((i = COM_CheckParm("-width")) != 0)
+		width = atoi(com_argv[i+1]);
+	if ((i = COM_CheckParm("-height")) != 0)
+		height = atoi(com_argv[i+1]);
+
+	if ((i = COM_CheckParm("-conwidth")) != 0)
+		vid.conwidth = Q_atoi(com_argv[i+1]);
+	else
+		vid.conwidth = 640;
+
+	vid.conwidth &= 0xfff8; // make it a multiple of eight
+
+	if (vid.conwidth < 320)
+		vid.conwidth = 320;
+
+	// pick a conheight that matches with correct aspect
+	vid.conheight = vid.conwidth*3 / 4;
+
+	if ((i = COM_CheckParm("-conheight")) != 0)
+		vid.conheight = Q_atoi(com_argv[i+1]);
+	if (vid.conheight < 200)
+		vid.conheight = 200;
+
+	fc = fxMesaCreateContext(0, findres(&width, &height), GR_REFRESH_75Hz, 
+		attribs);
+	if (!fc)
+		Sys_Error("Unable to create 3DFX context.\n");
+
+	InitSig(); // trap evil signals
+
+	scr_width = width;
+	scr_height = height;
+
+	fxMesaMakeCurrent(fc);
+
+	if (vid.conheight > height)
+		vid.conheight = height;
+	if (vid.conwidth > width)
+		vid.conwidth = width;
+	vid.width = vid.conwidth;
+	vid.height = vid.conheight;
+
+	vid.aspect = ((float)vid.height / (float)vid.width) *
+				(320.0 / 240.0);
+	vid.numpages = 2;
+
+	GL_Init();
+
+	sprintf (gldir, "%s/glquake", com_gamedir);
+	Sys_mkdir (gldir);
+
+	Check_Gamma(palette);
+	VID_SetPalette(palette);
+
+	// Check for 3DFX Extensions and initialize them.
+	VID_Init8bitPalette();
+
+	Con_SafePrintf ("Video mode %dx%d initialized.\n", width, height);
+
+	vid.recalc_refdef = 1;				// force a surface cache flush
+}
+
+void Sys_SendKeyEvents(void)
+{
+	if (UseKeyboard)
+		while (keyboard_update());
+}
+
+void Force_CenterView_f (void)
+{
+	cl.viewangles[PITCH] = 0;
+}
+
+
+void mousehandler(int buttonstate, int dx, int dy)
+{
+	mouse_buttonstate = buttonstate;
+	mx += dx;
+	my += dy;
+}
+
+void IN_Init(void)
+{
+
+	int mtype;
+	char *mousedev;
+	int mouserate;
+
+	if (UseMouse)
+	{
+
+		Cvar_RegisterVariable (&mouse_button_commands[0]);
+		Cvar_RegisterVariable (&mouse_button_commands[1]);
+		Cvar_RegisterVariable (&mouse_button_commands[2]);
+		Cmd_AddCommand ("force_centerview", Force_CenterView_f);
+
+		mouse_buttons = 3;
+
+		mtype = vga_getmousetype();
+
+		mousedev = "/dev/mouse";
+		if (getenv("MOUSEDEV")) mousedev = getenv("MOUSEDEV");
+		if (COM_CheckParm("-mdev"))
+			mousedev = com_argv[COM_CheckParm("-mdev")+1];
+
+		mouserate = 1200;
+		if (getenv("MOUSERATE")) mouserate = atoi(getenv("MOUSERATE"));
+		if (COM_CheckParm("-mrate"))
+			mouserate = atoi(com_argv[COM_CheckParm("-mrate")+1]);
+
+		if (mouse_init(mousedev, mtype, mouserate))
+		{
+			Con_Printf("No mouse found\n");
+			UseMouse = 0;
+		}
+		else
+			mouse_seteventhandler(mousehandler);
+
+	}
+
+}
+
+void IN_Shutdown(void)
+{
+	if (UseMouse)
+		mouse_close();
+}
+
+/*
+===========
+IN_Commands
+===========
+*/
+void IN_Commands (void)
+{
+	if (UseMouse && cls.state != ca_dedicated)
+	{
+		// poll mouse values
+		while (mouse_update())
+			;
+
+		// perform button actions
+		if ((mouse_buttonstate & MOUSE_LEFTBUTTON) &&
+			!(mouse_oldbuttonstate & MOUSE_LEFTBUTTON))
+			Key_Event (K_MOUSE1, true);
+		else if (!(mouse_buttonstate & MOUSE_LEFTBUTTON) &&
+			(mouse_oldbuttonstate & MOUSE_LEFTBUTTON))
+			Key_Event (K_MOUSE1, false);
+
+		if ((mouse_buttonstate & MOUSE_RIGHTBUTTON) &&
+			!(mouse_oldbuttonstate & MOUSE_RIGHTBUTTON))
+			Key_Event (K_MOUSE2, true);
+		else if (!(mouse_buttonstate & MOUSE_RIGHTBUTTON) &&
+			(mouse_oldbuttonstate & MOUSE_RIGHTBUTTON))
+			Key_Event (K_MOUSE2, false);
+
+		if ((mouse_buttonstate & MOUSE_MIDDLEBUTTON) &&
+			!(mouse_oldbuttonstate & MOUSE_MIDDLEBUTTON))
+			Key_Event (K_MOUSE3, true);
+		else if (!(mouse_buttonstate & MOUSE_MIDDLEBUTTON) &&
+			(mouse_oldbuttonstate & MOUSE_MIDDLEBUTTON))
+			Key_Event (K_MOUSE3, false);
+
+		mouse_oldbuttonstate = mouse_buttonstate;
+	}
+}
+
+/*
+===========
+IN_Move
+===========
+*/
+void IN_MouseMove (usercmd_t *cmd)
+{
+	if (!UseMouse)
+		return;
+
+	// poll mouse values
+	while (mouse_update())
+		;
+
+	if (m_filter.value)
+	{
+		mouse_x = (mx + old_mouse_x) * 0.5;
+		mouse_y = (my + old_mouse_y) * 0.5;
+	}
+	else
+	{
+		mouse_x = mx;
+		mouse_y = my;
+	}
+	old_mouse_x = mx;
+	old_mouse_y = my;
+	mx = my = 0; // clear for next update
+
+	mouse_x *= sensitivity.value;
+	mouse_y *= sensitivity.value;
+
+// add mouse X/Y movement to cmd
+	if ( (in_strafe.state & 1) || (lookstrafe.value && (in_mlook.state & 1) ))
+		cmd->sidemove += m_side.value * mouse_x;
+	else
+		cl.viewangles[YAW] -= m_yaw.value * mouse_x;
+	
+	if (in_mlook.state & 1)
+		V_StopPitchDrift ();
+		
+	if ( (in_mlook.state & 1) && !(in_strafe.state & 1))
+	{
+		cl.viewangles[PITCH] += m_pitch.value * mouse_y;
+		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 * mouse_y;
+		else
+			cmd->forwardmove -= m_forward.value * mouse_y;
+	}
+}
+
+void IN_Move (usercmd_t *cmd)
+{
+	IN_MouseMove(cmd);
+}
+
+
--- /dev/null
+++ b/WinQuake/gl_vidlinuxglx.c
@@ -1,0 +1,997 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+#include <termios.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/vt.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <signal.h>
+
+#include <dlfcn.h>
+
+#include "quakedef.h"
+
+#include <GL/glx.h>
+
+#include <X11/keysym.h>
+#include <X11/cursorfont.h>
+
+#include <X11/extensions/xf86dga.h>
+#include <X11/extensions/xf86vmode.h>
+
+#define WARP_WIDTH              320
+#define WARP_HEIGHT             200
+
+static Display *dpy = NULL;
+static int scrnum;
+static Window win;
+static GLXContext ctx = NULL;
+
+#define KEY_MASK (KeyPressMask | KeyReleaseMask)
+#define MOUSE_MASK (ButtonPressMask | ButtonReleaseMask | \
+		    PointerMotionMask | ButtonMotionMask )
+#define X_MASK (KEY_MASK | MOUSE_MASK | VisibilityChangeMask | StructureNotifyMask )
+
+
+unsigned short	d_8to16table[256];
+unsigned		d_8to24table[256];
+unsigned char	d_15to8table[65536];
+
+cvar_t	vid_mode = {"vid_mode","0",false};
+ 
+static qboolean        mouse_avail;
+static qboolean        mouse_active;
+static int   mx, my;
+static int	old_mouse_x, old_mouse_y;
+
+static cvar_t in_mouse = {"in_mouse", "1", false};
+static cvar_t in_dgamouse = {"in_dgamouse", "1", false};
+static cvar_t m_filter = {"m_filter", "0"};
+
+qboolean dgamouse = false;
+qboolean vidmode_ext = false;
+
+static int win_x, win_y;
+
+static int scr_width, scr_height;
+
+static XF86VidModeModeInfo **vidmodes;
+static int default_dotclock_vidmode;
+static int num_vidmodes;
+static qboolean vidmode_active = false;
+
+/*-----------------------------------------------------------------------*/
+
+//int		texture_mode = GL_NEAREST;
+//int		texture_mode = GL_NEAREST_MIPMAP_NEAREST;
+//int		texture_mode = GL_NEAREST_MIPMAP_LINEAR;
+int		texture_mode = GL_LINEAR;
+//int		texture_mode = GL_LINEAR_MIPMAP_NEAREST;
+//int		texture_mode = GL_LINEAR_MIPMAP_LINEAR;
+
+int		texture_extension_number = 1;
+
+float		gldepthmin, gldepthmax;
+
+cvar_t	gl_ztrick = {"gl_ztrick","1"};
+
+const char *gl_vendor;
+const char *gl_renderer;
+const char *gl_version;
+const char *gl_extensions;
+
+void (*qglColorTableEXT) (int, int, int, int, int, const void*);
+void (*qgl3DfxSetPaletteEXT) (GLuint *);
+
+static float vid_gamma = 1.0;
+
+qboolean is8bit = false;
+qboolean isPermedia = false;
+qboolean gl_mtexable = false;
+
+/*-----------------------------------------------------------------------*/
+void D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height)
+{
+}
+
+void D_EndDirectRect (int x, int y, int width, int height)
+{
+}
+
+static int XLateKey(XKeyEvent *ev)
+{
+
+	int key;
+	char buf[64];
+	KeySym keysym;
+
+	key = 0;
+
+	XLookupString(ev, buf, sizeof buf, &keysym, 0);
+
+	switch(keysym)
+	{
+		case XK_KP_Page_Up:	 
+		case XK_Page_Up:	 key = K_PGUP; break;
+
+		case XK_KP_Page_Down: 
+		case XK_Page_Down:	 key = K_PGDN; break;
+
+		case XK_KP_Home: 
+		case XK_Home:	 key = K_HOME; break;
+
+		case XK_KP_End:  
+		case XK_End:	 key = K_END; break;
+
+		case XK_KP_Left: 
+		case XK_Left:	 key = K_LEFTARROW; break;
+
+		case XK_KP_Right: 
+		case XK_Right:	key = K_RIGHTARROW;		break;
+
+		case XK_KP_Down: 
+		case XK_Down:	 key = K_DOWNARROW; break;
+
+		case XK_KP_Up:   
+		case XK_Up:		 key = K_UPARROW;	 break;
+
+		case XK_Escape: key = K_ESCAPE;		break;
+
+		case XK_KP_Enter: 
+		case XK_Return: key = K_ENTER;		 break;
+
+		case XK_Tab:		key = K_TAB;			 break;
+
+		case XK_F1:		 key = K_F1;				break;
+
+		case XK_F2:		 key = K_F2;				break;
+
+		case XK_F3:		 key = K_F3;				break;
+
+		case XK_F4:		 key = K_F4;				break;
+
+		case XK_F5:		 key = K_F5;				break;
+
+		case XK_F6:		 key = K_F6;				break;
+
+		case XK_F7:		 key = K_F7;				break;
+
+		case XK_F8:		 key = K_F8;				break;
+
+		case XK_F9:		 key = K_F9;				break;
+
+		case XK_F10:		key = K_F10;			 break;
+
+		case XK_F11:		key = K_F11;			 break;
+
+		case XK_F12:		key = K_F12;			 break;
+
+		case XK_BackSpace: key = K_BACKSPACE; break;
+
+		case XK_KP_Delete: 
+		case XK_Delete: key = K_DEL; break;
+
+		case XK_Pause:	key = K_PAUSE;		 break;
+
+		case XK_Shift_L:
+		case XK_Shift_R:	key = K_SHIFT;		break;
+
+		case XK_Execute: 
+		case XK_Control_L: 
+		case XK_Control_R:	key = K_CTRL;		 break;
+
+		case XK_Alt_L:	
+		case XK_Meta_L: 
+		case XK_Alt_R:	
+		case XK_Meta_R: key = K_ALT;			break;
+
+		case XK_KP_Begin: key = '5';	break;
+
+		case XK_KP_Insert: 
+		case XK_Insert:key = K_INS; break;
+
+		case XK_KP_Multiply: key = '*'; break;
+		case XK_KP_Add:  key = '+'; break;
+		case XK_KP_Subtract: key = '-'; break;
+		case XK_KP_Divide: key = '/'; break;
+
+#if 0
+		case 0x021: key = '1';break;/* [!] */
+		case 0x040: key = '2';break;/* [@] */
+		case 0x023: key = '3';break;/* [#] */
+		case 0x024: key = '4';break;/* [$] */
+		case 0x025: key = '5';break;/* [%] */
+		case 0x05e: key = '6';break;/* [^] */
+		case 0x026: key = '7';break;/* [&] */
+		case 0x02a: key = '8';break;/* [*] */
+		case 0x028: key = '9';;break;/* [(] */
+		case 0x029: key = '0';break;/* [)] */
+		case 0x05f: key = '-';break;/* [_] */
+		case 0x02b: key = '=';break;/* [+] */
+		case 0x07c: key = '\'';break;/* [|] */
+		case 0x07d: key = '[';break;/* [}] */
+		case 0x07b: key = ']';break;/* [{] */
+		case 0x022: key = '\'';break;/* ["] */
+		case 0x03a: key = ';';break;/* [:] */
+		case 0x03f: key = '/';break;/* [?] */
+		case 0x03e: key = '.';break;/* [>] */
+		case 0x03c: key = ',';break;/* [<] */
+#endif
+
+		default:
+			key = *(unsigned char*)buf;
+			if (key >= 'A' && key <= 'Z')
+				key = key - 'A' + 'a';
+			break;
+	} 
+
+	return key;
+}
+
+static Cursor CreateNullCursor(Display *display, Window root)
+{
+    Pixmap cursormask; 
+    XGCValues xgc;
+    GC gc;
+    XColor dummycolour;
+    Cursor cursor;
+
+    cursormask = XCreatePixmap(display, root, 1, 1, 1/*depth*/);
+    xgc.function = GXclear;
+    gc =  XCreateGC(display, cursormask, GCFunction, &xgc);
+    XFillRectangle(display, cursormask, gc, 0, 0, 1, 1);
+    dummycolour.pixel = 0;
+    dummycolour.red = 0;
+    dummycolour.flags = 04;
+    cursor = XCreatePixmapCursor(display, cursormask, cursormask,
+          &dummycolour,&dummycolour, 0,0);
+    XFreePixmap(display,cursormask);
+    XFreeGC(display,gc);
+    return cursor;
+}
+
+static void install_grabs(void)
+{
+
+// inviso cursor
+	XDefineCursor(dpy, win, CreateNullCursor(dpy, win));
+
+	XGrabPointer(dpy, win,
+				 True,
+				 0,
+				 GrabModeAsync, GrabModeAsync,
+				 win,
+				 None,
+				 CurrentTime);
+
+	if (in_dgamouse.value) {
+		int MajorVersion, MinorVersion;
+
+		if (!XF86DGAQueryVersion(dpy, &MajorVersion, &MinorVersion)) { 
+			// unable to query, probalby not supported
+			Con_Printf( "Failed to detect XF86DGA Mouse\n" );
+			in_dgamouse.value = 0;
+		} else {
+			dgamouse = true;
+			XF86DGADirectVideo(dpy, DefaultScreen(dpy), XF86DGADirectMouse);
+			XWarpPointer(dpy, None, win, 0, 0, 0, 0, 0, 0);
+		}
+	} else {
+		XWarpPointer(dpy, None, win,
+					 0, 0, 0, 0,
+					 vid.width / 2, vid.height / 2);
+	}
+
+	XGrabKeyboard(dpy, win,
+				  False,
+				  GrabModeAsync, GrabModeAsync,
+				  CurrentTime);
+
+	mouse_active = true;
+
+//	XSync(dpy, True);
+}
+
+static void uninstall_grabs(void)
+{
+	if (!dpy || !win)
+		return;
+
+	if (dgamouse) {
+		dgamouse = false;
+		XF86DGADirectVideo(dpy, DefaultScreen(dpy), 0);
+	}
+
+	XUngrabPointer(dpy, CurrentTime);
+	XUngrabKeyboard(dpy, CurrentTime);
+
+// inviso cursor
+	XUndefineCursor(dpy, win);
+
+	mouse_active = false;
+}
+
+static void HandleEvents(void)
+{
+	XEvent event;
+	KeySym ks;
+	int b;
+	qboolean dowarp = false;
+	int mwx = vid.width/2;
+	int mwy = vid.height/2;
+
+	if (!dpy)
+		return;
+
+	while (XPending(dpy)) {
+		XNextEvent(dpy, &event);
+
+		switch (event.type) {
+		case KeyPress:
+		case KeyRelease:
+			Key_Event(XLateKey(&event.xkey), event.type == KeyPress);
+			break;
+
+		case MotionNotify:
+			if (mouse_active) {
+				if (dgamouse) {
+					mx += (event.xmotion.x + win_x) * 2;
+					my += (event.xmotion.y + win_y) * 2;
+				} 
+				else 
+				{
+					mx += ((int)event.xmotion.x - mwx) * 2;
+					my += ((int)event.xmotion.y - mwy) * 2;
+					mwx = event.xmotion.x;
+					mwy = event.xmotion.y;
+
+					if (mx || my)
+						dowarp = true;
+				}
+			}
+			break;
+
+			break;
+
+		case ButtonPress:
+			b=-1;
+			if (event.xbutton.button == 1)
+				b = 0;
+			else if (event.xbutton.button == 2)
+				b = 2;
+			else if (event.xbutton.button == 3)
+				b = 1;
+			if (b>=0)
+				Key_Event(K_MOUSE1 + b, true);
+			break;
+
+		case ButtonRelease:
+			b=-1;
+			if (event.xbutton.button == 1)
+				b = 0;
+			else if (event.xbutton.button == 2)
+				b = 2;
+			else if (event.xbutton.button == 3)
+				b = 1;
+			if (b>=0)
+				Key_Event(K_MOUSE1 + b, false);
+			break;
+
+		case CreateNotify :
+			win_x = event.xcreatewindow.x;
+			win_y = event.xcreatewindow.y;
+			break;
+
+		case ConfigureNotify :
+			win_x = event.xconfigure.x;
+			win_y = event.xconfigure.y;
+			break;
+		}
+	}
+
+	if (dowarp) {
+		/* move the mouse to the window center again */
+		XWarpPointer(dpy, None, win, 0, 0, 0, 0, vid.width / 2, vid.height / 2);
+	}
+
+}
+
+static void IN_DeactivateMouse( void ) 
+{
+	if (!mouse_avail || !dpy || !win)
+		return;
+
+	if (mouse_active) {
+		uninstall_grabs();
+		mouse_active = false;
+	}
+}
+
+static void IN_ActivateMouse( void ) 
+{
+	if (!mouse_avail || !dpy || !win)
+		return;
+
+	if (!mouse_active) {
+		mx = my = 0; // don't spazz
+		install_grabs();
+		mouse_active = true;
+	}
+}
+
+
+void VID_Shutdown(void)
+{
+	if (!ctx || !dpy)
+		return;
+	IN_DeactivateMouse();
+	if (dpy) {
+		if (ctx)
+			glXDestroyContext(dpy, ctx);
+		if (win)
+			XDestroyWindow(dpy, win);
+		if (vidmode_active)
+			XF86VidModeSwitchToMode(dpy, scrnum, vidmodes[0]);
+		XCloseDisplay(dpy);
+	}
+	vidmode_active = false;
+	dpy = NULL;
+	win = 0;
+	ctx = NULL;
+}
+
+void signal_handler(int sig)
+{
+	printf("Received signal %d, exiting...\n", sig);
+	Sys_Quit();
+	exit(0);
+}
+
+void InitSig(void)
+{
+	signal(SIGHUP, signal_handler);
+	signal(SIGINT, signal_handler);
+	signal(SIGQUIT, signal_handler);
+	signal(SIGILL, signal_handler);
+	signal(SIGTRAP, signal_handler);
+	signal(SIGIOT, signal_handler);
+	signal(SIGBUS, signal_handler);
+	signal(SIGFPE, signal_handler);
+	signal(SIGSEGV, signal_handler);
+	signal(SIGTERM, signal_handler);
+}
+
+void VID_ShiftPalette(unsigned char *p)
+{
+//	VID_SetPalette(p);
+}
+
+void	VID_SetPalette (unsigned char *palette)
+{
+	byte	*pal;
+	unsigned r,g,b;
+	unsigned v;
+	int     r1,g1,b1;
+	int		j,k,l,m;
+	unsigned short i;
+	unsigned	*table;
+	FILE *f;
+	char s[255];
+	int dist, bestdist;
+
+//
+// 8 8 8 encoding
+//
+	pal = palette;
+	table = d_8to24table;
+	for (i=0 ; i<256 ; i++)
+	{
+		r = pal[0];
+		g = pal[1];
+		b = pal[2];
+		pal += 3;
+		
+		v = (255<<24) + (r<<0) + (g<<8) + (b<<16);
+		*table++ = v;
+	}
+	d_8to24table[255] &= 0xffffff;	// 255 is transparent
+
+	for (i=0; i < (1<<15); i++) {
+		/* Maps
+		000000000000000
+		000000000011111 = Red  = 0x1F
+		000001111100000 = Blue = 0x03E0
+		111110000000000 = Grn  = 0x7C00
+		*/
+		r = ((i & 0x1F) << 3)+4;
+		g = ((i & 0x03E0) >> 2)+4;
+		b = ((i & 0x7C00) >> 7)+4;
+		pal = (unsigned char *)d_8to24table;
+		for (v=0,k=0,bestdist=10000*10000; v<256; v++,pal+=4) {
+			r1 = (int)r - (int)pal[0];
+			g1 = (int)g - (int)pal[1];
+			b1 = (int)b - (int)pal[2];
+			dist = (r1*r1)+(g1*g1)+(b1*b1);
+			if (dist < bestdist) {
+				k=v;
+				bestdist = dist;
+			}
+		}
+		d_15to8table[i]=k;
+	}
+}
+
+void CheckMultiTextureExtensions(void) 
+{
+	void *prjobj;
+
+	if (strstr(gl_extensions, "GL_SGIS_multitexture ") && !COM_CheckParm("-nomtex")) {
+		Con_Printf("Found GL_SGIS_multitexture...\n");
+
+		if ((prjobj = dlopen(NULL, RTLD_LAZY)) == NULL) {
+			Con_Printf("Unable to open symbol list for main program.\n");
+			return;
+		}
+
+		qglMTexCoord2fSGIS = (void *) dlsym(prjobj, "glMTexCoord2fSGIS");
+		qglSelectTextureSGIS = (void *) dlsym(prjobj, "glSelectTextureSGIS");
+
+		if (qglMTexCoord2fSGIS && qglSelectTextureSGIS) {
+			Con_Printf("Multitexture extensions found.\n");
+			gl_mtexable = true;
+		} else
+			Con_Printf("Symbol not found, disabled.\n");
+
+		dlclose(prjobj);
+	}
+}
+
+/*
+===============
+GL_Init
+===============
+*/
+void GL_Init (void)
+{
+	gl_vendor = glGetString (GL_VENDOR);
+	Con_Printf ("GL_VENDOR: %s\n", gl_vendor);
+	gl_renderer = glGetString (GL_RENDERER);
+	Con_Printf ("GL_RENDERER: %s\n", gl_renderer);
+
+	gl_version = glGetString (GL_VERSION);
+	Con_Printf ("GL_VERSION: %s\n", gl_version);
+	gl_extensions = glGetString (GL_EXTENSIONS);
+	Con_Printf ("GL_EXTENSIONS: %s\n", gl_extensions);
+
+//	Con_Printf ("%s %s\n", gl_renderer, gl_version);
+
+	CheckMultiTextureExtensions ();
+
+	glClearColor (1,0,0,0);
+	glCullFace(GL_FRONT);
+	glEnable(GL_TEXTURE_2D);
+
+	glEnable(GL_ALPHA_TEST);
+	glAlphaFunc(GL_GREATER, 0.666);
+
+	glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
+	glShadeModel (GL_FLAT);
+
+	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+
+	glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+//	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+}
+
+/*
+=================
+GL_BeginRendering
+
+=================
+*/
+void GL_BeginRendering (int *x, int *y, int *width, int *height)
+{
+	extern cvar_t gl_clear;
+
+	*x = *y = 0;
+	*width = scr_width;
+	*height = scr_height;
+
+//    if (!wglMakeCurrent( maindc, baseRC ))
+//		Sys_Error ("wglMakeCurrent failed");
+
+//	glViewport (*x, *y, *width, *height);
+}
+
+
+void GL_EndRendering (void)
+{
+	glFlush();
+	glXSwapBuffers(dpy, win);
+}
+
+qboolean VID_Is8bit(void)
+{
+	return is8bit;
+}
+
+void VID_Init8bitPalette(void) 
+{
+	// Check for 8bit Extensions and initialize them.
+	int i;
+	void *prjobj;
+
+	if ((prjobj = dlopen(NULL, RTLD_LAZY)) == NULL) {
+		Con_Printf("Unable to open symbol list for main program.\n");
+		return;
+	}
+
+	if (strstr(gl_extensions, "3DFX_set_global_palette") &&
+		(qgl3DfxSetPaletteEXT = dlsym(prjobj, "gl3DfxSetPaletteEXT")) != NULL) {
+		GLubyte table[256][4];
+		char *oldpal;
+
+		Con_SafePrintf("8-bit GL extensions enabled.\n");
+		glEnable( GL_SHARED_TEXTURE_PALETTE_EXT );
+		oldpal = (char *) d_8to24table; //d_8to24table3dfx;
+		for (i=0;i<256;i++) {
+			table[i][2] = *oldpal++;
+			table[i][1] = *oldpal++;
+			table[i][0] = *oldpal++;
+			table[i][3] = 255;
+			oldpal++;
+		}
+		qgl3DfxSetPaletteEXT((GLuint *)table);
+		is8bit = true;
+
+	} else if (strstr(gl_extensions, "GL_EXT_shared_texture_palette") &&
+		(qglColorTableEXT = dlsym(prjobj, "glColorTableEXT")) != NULL) {
+		char thePalette[256*3];
+		char *oldPalette, *newPalette;
+
+		Con_SafePrintf("8-bit GL extensions enabled.\n");
+		glEnable( GL_SHARED_TEXTURE_PALETTE_EXT );
+		oldPalette = (char *) d_8to24table; //d_8to24table3dfx;
+		newPalette = thePalette;
+		for (i=0;i<256;i++) {
+			*newPalette++ = *oldPalette++;
+			*newPalette++ = *oldPalette++;
+			*newPalette++ = *oldPalette++;
+			oldPalette++;
+		}
+		qglColorTableEXT(GL_SHARED_TEXTURE_PALETTE_EXT, GL_RGB, 256, GL_RGB, GL_UNSIGNED_BYTE, (void *) thePalette);
+		is8bit = true;
+	}
+	
+	dlclose(prjobj);
+}
+
+static void Check_Gamma (unsigned char *pal)
+{
+	float	f, inf;
+	unsigned char	palette[768];
+	int		i;
+
+	if ((i = COM_CheckParm("-gamma")) == 0) {
+		if ((gl_renderer && strstr(gl_renderer, "Voodoo")) ||
+			(gl_vendor && strstr(gl_vendor, "3Dfx")))
+			vid_gamma = 1;
+		else
+			vid_gamma = 0.7; // default to 0.7 on non-3dfx hardware
+	} else
+		vid_gamma = Q_atof(com_argv[i+1]);
+
+	for (i=0 ; i<768 ; i++)
+	{
+		f = pow ( (pal[i]+1)/256.0 , vid_gamma );
+		inf = f*255 + 0.5;
+		if (inf < 0)
+			inf = 0;
+		if (inf > 255)
+			inf = 255;
+		palette[i] = inf;
+	}
+
+	memcpy (pal, palette, sizeof(palette));
+}
+
+void VID_Init(unsigned char *palette)
+{
+	int i;
+	int attrib[] = {
+		GLX_RGBA,
+		GLX_RED_SIZE, 1,
+		GLX_GREEN_SIZE, 1,
+		GLX_BLUE_SIZE, 1,
+		GLX_DOUBLEBUFFER,
+		GLX_DEPTH_SIZE, 1,
+		None
+	};
+	char	gldir[MAX_OSPATH];
+	int width = 640, height = 480;
+	XSetWindowAttributes attr;
+	unsigned long mask;
+	Window root;
+	XVisualInfo *visinfo;
+	qboolean fullscreen = true;
+	int MajorVersion, MinorVersion;
+	int actualWidth, actualHeight;
+
+	Cvar_RegisterVariable (&vid_mode);
+	Cvar_RegisterVariable (&in_mouse);
+	Cvar_RegisterVariable (&in_dgamouse);
+	Cvar_RegisterVariable (&m_filter);
+	Cvar_RegisterVariable (&gl_ztrick);
+	
+	vid.maxwarpwidth = WARP_WIDTH;
+	vid.maxwarpheight = WARP_HEIGHT;
+	vid.colormap = host_colormap;
+	vid.fullbright = 256 - LittleLong (*((int *)vid.colormap + 2048));
+
+// interpret command-line params
+
+// set vid parameters
+	if ((i = COM_CheckParm("-window")) != 0)
+		fullscreen = false;
+
+	if ((i = COM_CheckParm("-width")) != 0)
+		width = atoi(com_argv[i+1]);
+
+	if ((i = COM_CheckParm("-height")) != 0)
+		height = atoi(com_argv[i+1]);
+
+	if ((i = COM_CheckParm("-conwidth")) != 0)
+		vid.conwidth = Q_atoi(com_argv[i+1]);
+	else
+		vid.conwidth = 640;
+
+	vid.conwidth &= 0xfff8; // make it a multiple of eight
+
+	if (vid.conwidth < 320)
+		vid.conwidth = 320;
+
+	// pick a conheight that matches with correct aspect
+	vid.conheight = vid.conwidth*3 / 4;
+
+	if ((i = COM_CheckParm("-conheight")) != 0)
+		vid.conheight = Q_atoi(com_argv[i+1]);
+	if (vid.conheight < 200)
+		vid.conheight = 200;
+
+	if (!(dpy = XOpenDisplay(NULL))) {
+		fprintf(stderr, "Error couldn't open the X display\n");
+		exit(1);
+	}
+
+	scrnum = DefaultScreen(dpy);
+	root = RootWindow(dpy, scrnum);
+
+	// Get video mode list
+	MajorVersion = MinorVersion = 0;
+	if (!XF86VidModeQueryVersion(dpy, &MajorVersion, &MinorVersion)) { 
+		vidmode_ext = false;
+	} else {
+		Con_Printf("Using XFree86-VidModeExtension Version %d.%d\n", MajorVersion, MinorVersion);
+		vidmode_ext = true;
+	}
+
+	visinfo = glXChooseVisual(dpy, scrnum, attrib);
+	if (!visinfo) {
+		fprintf(stderr, "qkHack: Error couldn't get an RGB, Double-buffered, Depth visual\n");
+		exit(1);
+	}
+
+	if (vidmode_ext) {
+		int best_fit, best_dist, dist, x, y;
+		
+		XF86VidModeGetAllModeLines(dpy, scrnum, &num_vidmodes, &vidmodes);
+
+		// Are we going fullscreen?  If so, let's change video mode
+		if (fullscreen) {
+			best_dist = 9999999;
+			best_fit = -1;
+
+			for (i = 0; i < num_vidmodes; i++) {
+				if (width > vidmodes[i]->hdisplay ||
+					height > vidmodes[i]->vdisplay)
+					continue;
+
+				x = width - vidmodes[i]->hdisplay;
+				y = height - vidmodes[i]->vdisplay;
+				dist = (x * x) + (y * y);
+				if (dist < best_dist) {
+					best_dist = dist;
+					best_fit = i;
+				}
+			}
+
+			if (best_fit != -1) {
+				actualWidth = vidmodes[best_fit]->hdisplay;
+				actualHeight = vidmodes[best_fit]->vdisplay;
+
+				// change to the mode
+				XF86VidModeSwitchToMode(dpy, scrnum, vidmodes[best_fit]);
+				vidmode_active = true;
+
+				// Move the viewport to top left
+				XF86VidModeSetViewPort(dpy, scrnum, 0, 0);
+			} else
+				fullscreen = 0;
+		}
+	}
+
+	/* window attributes */
+	attr.background_pixel = 0;
+	attr.border_pixel = 0;
+	attr.colormap = XCreateColormap(dpy, root, visinfo->visual, AllocNone);
+	attr.event_mask = X_MASK;
+	if (vidmode_active) {
+		mask = CWBackPixel | CWColormap | CWSaveUnder | CWBackingStore | 
+			CWEventMask | CWOverrideRedirect;
+		attr.override_redirect = True;
+		attr.backing_store = NotUseful;
+		attr.save_under = False;
+	} else
+		mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
+
+	win = XCreateWindow(dpy, root, 0, 0, width, height,
+						0, visinfo->depth, InputOutput,
+						visinfo->visual, mask, &attr);
+	XMapWindow(dpy, win);
+
+	if (vidmode_active) {
+		XMoveWindow(dpy, win, 0, 0);
+		XRaiseWindow(dpy, win);
+		XWarpPointer(dpy, None, win, 0, 0, 0, 0, 0, 0);
+		XFlush(dpy);
+		// Move the viewport to top left
+		XF86VidModeSetViewPort(dpy, scrnum, 0, 0);
+	}
+
+	XFlush(dpy);
+
+	ctx = glXCreateContext(dpy, visinfo, NULL, True);
+
+	glXMakeCurrent(dpy, win, ctx);
+
+	scr_width = width;
+	scr_height = height;
+
+	if (vid.conheight > height)
+		vid.conheight = height;
+	if (vid.conwidth > width)
+		vid.conwidth = width;
+	vid.width = vid.conwidth;
+	vid.height = vid.conheight;
+
+	vid.aspect = ((float)vid.height / (float)vid.width) * (320.0 / 240.0);
+	vid.numpages = 2;
+
+	InitSig(); // trap evil signals
+
+	GL_Init();
+
+	sprintf (gldir, "%s/glquake", com_gamedir);
+	Sys_mkdir (gldir);
+
+	VID_SetPalette(palette);
+
+	// Check for 3DFX Extensions and initialize them.
+	VID_Init8bitPalette();
+
+	Con_SafePrintf ("Video mode %dx%d initialized.\n", width, height);
+
+	vid.recalc_refdef = 1;				// force a surface cache flush
+}
+
+void Sys_SendKeyEvents(void)
+{
+	HandleEvents();
+}
+
+void Force_CenterView_f (void)
+{
+	cl.viewangles[PITCH] = 0;
+}
+
+void IN_Init(void)
+{
+}
+
+void IN_Shutdown(void)
+{
+}
+
+/*
+===========
+IN_Commands
+===========
+*/
+void IN_Commands (void)
+{
+	if (!dpy || !win)
+		return;
+
+	if (vidmode_active || key_dest == key_game)
+		IN_ActivateMouse();
+	else
+		IN_DeactivateMouse ();
+}
+
+/*
+===========
+IN_Move
+===========
+*/
+void IN_MouseMove (usercmd_t *cmd)
+{
+	if (!mouse_avail)
+		return;
+   
+	if (m_filter.value)
+	{
+		mx = (mx + old_mouse_x) * 0.5;
+		my = (my + old_mouse_y) * 0.5;
+	}
+	old_mouse_x = mx;
+	old_mouse_y = my;
+
+	mx *= sensitivity.value;
+	my *= sensitivity.value;
+
+// add mouse X/Y movement to cmd
+	if ( (in_strafe.state & 1) || (lookstrafe.value && (in_mlook.state & 1) ))
+		cmd->sidemove += m_side.value * mx;
+	else
+		cl.viewangles[YAW] -= m_yaw.value * mx;
+	
+	if (in_mlook.state & 1)
+		V_StopPitchDrift ();
+		
+	if ( (in_mlook.state & 1) && !(in_strafe.state & 1))
+	{
+		cl.viewangles[PITCH] += m_pitch.value * my;
+		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 * my;
+		else
+			cmd->forwardmove -= m_forward.value * my;
+	}
+	mx = my = 0;
+}
+
+void IN_Move (usercmd_t *cmd)
+{
+	IN_MouseMove(cmd);
+}
+
+
--- /dev/null
+++ b/WinQuake/gl_vidnt.c
@@ -1,0 +1,1949 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// gl_vidnt.c -- NT GL vid component
+
+#include "quakedef.h"
+#include "winquake.h"
+#include "resource.h"
+#include <commctrl.h>
+
+#define MAX_MODE_LIST	30
+#define VID_ROW_SIZE	3
+#define WARP_WIDTH		320
+#define WARP_HEIGHT		200
+#define MAXWIDTH		10000
+#define MAXHEIGHT		10000
+#define BASEWIDTH		320
+#define BASEHEIGHT		200
+
+#define MODE_WINDOWED			0
+#define NO_MODE					(MODE_WINDOWED - 1)
+#define MODE_FULLSCREEN_DEFAULT	(MODE_WINDOWED + 1)
+
+typedef struct {
+	modestate_t	type;
+	int			width;
+	int			height;
+	int			modenum;
+	int			dib;
+	int			fullscreen;
+	int			bpp;
+	int			halfscreen;
+	char		modedesc[17];
+} vmode_t;
+
+typedef struct {
+	int			width;
+	int			height;
+} lmode_t;
+
+lmode_t	lowresmodes[] = {
+	{320, 200},
+	{320, 240},
+	{400, 300},
+	{512, 384},
+};
+
+const char *gl_vendor;
+const char *gl_renderer;
+const char *gl_version;
+const char *gl_extensions;
+
+qboolean		DDActive;
+qboolean		scr_skipupdate;
+
+static vmode_t	modelist[MAX_MODE_LIST];
+static int		nummodes;
+static vmode_t	*pcurrentmode;
+static vmode_t	badmode;
+
+static DEVMODE	gdevmode;
+static qboolean	vid_initialized = false;
+static qboolean	windowed, leavecurrentmode;
+static qboolean vid_canalttab = false;
+static qboolean vid_wassuspended = false;
+static int		windowed_mouse;
+extern qboolean	mouseactive;  // from in_win.c
+static HICON	hIcon;
+
+int			DIBWidth, DIBHeight;
+RECT		WindowRect;
+DWORD		WindowStyle, ExWindowStyle;
+
+HWND	mainwindow, dibwindow;
+
+int			vid_modenum = NO_MODE;
+int			vid_realmode;
+int			vid_default = MODE_WINDOWED;
+static int	windowed_default;
+unsigned char	vid_curpal[256*3];
+static qboolean fullsbardraw = false;
+
+static float vid_gamma = 1.0;
+
+HGLRC	baseRC;
+HDC		maindc;
+
+glvert_t glv;
+
+cvar_t	gl_ztrick = {"gl_ztrick","1"};
+
+HWND WINAPI InitializeWindow (HINSTANCE hInstance, int nCmdShow);
+
+viddef_t	vid;				// global video state
+
+unsigned short	d_8to16table[256];
+unsigned	d_8to24table[256];
+unsigned char d_15to8table[65536];
+
+float		gldepthmin, gldepthmax;
+
+modestate_t	modestate = MS_UNINIT;
+
+void VID_MenuDraw (void);
+void VID_MenuKey (int key);
+
+LONG WINAPI MainWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
+void AppActivate(BOOL fActive, BOOL minimize);
+char *VID_GetModeDescription (int mode);
+void ClearAllStates (void);
+void VID_UpdateWindowStatus (void);
+void GL_Init (void);
+
+PROC glArrayElementEXT;
+PROC glColorPointerEXT;
+PROC glTexCoordPointerEXT;
+PROC glVertexPointerEXT;
+
+typedef void (APIENTRY *lp3DFXFUNC) (int, int, int, int, int, const void*);
+lp3DFXFUNC glColorTableEXT;
+qboolean is8bit = false;
+qboolean isPermedia = false;
+qboolean gl_mtexable = false;
+
+//====================================
+
+cvar_t		vid_mode = {"vid_mode","0", false};
+// Note that 0 is MODE_WINDOWED
+cvar_t		_vid_default_mode = {"_vid_default_mode","0", true};
+// Note that 3 is MODE_FULLSCREEN_DEFAULT
+cvar_t		_vid_default_mode_win = {"_vid_default_mode_win","3", true};
+cvar_t		vid_wait = {"vid_wait","0"};
+cvar_t		vid_nopageflip = {"vid_nopageflip","0", true};
+cvar_t		_vid_wait_override = {"_vid_wait_override", "0", true};
+cvar_t		vid_config_x = {"vid_config_x","800", true};
+cvar_t		vid_config_y = {"vid_config_y","600", true};
+cvar_t		vid_stretch_by_2 = {"vid_stretch_by_2","1", true};
+cvar_t		_windowed_mouse = {"_windowed_mouse","1", true};
+
+int			window_center_x, window_center_y, window_x, window_y, window_width, window_height;
+RECT		window_rect;
+
+// direct draw software compatability stuff
+
+void VID_HandlePause (qboolean pause)
+{
+}
+
+void VID_ForceLockState (int lk)
+{
+}
+
+void VID_LockBuffer (void)
+{
+}
+
+void VID_UnlockBuffer (void)
+{
+}
+
+int VID_ForceUnlockedAndReturnState (void)
+{
+	return 0;
+}
+
+void D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height)
+{
+}
+
+void D_EndDirectRect (int x, int y, int width, int height)
+{
+}
+
+
+void CenterWindow(HWND hWndCenter, int width, int height, BOOL lefttopjustify)
+{
+    RECT    rect;
+    int     CenterX, CenterY;
+
+	CenterX = (GetSystemMetrics(SM_CXSCREEN) - width) / 2;
+	CenterY = (GetSystemMetrics(SM_CYSCREEN) - height) / 2;
+	if (CenterX > CenterY*2)
+		CenterX >>= 1;	// dual screens
+	CenterX = (CenterX < 0) ? 0: CenterX;
+	CenterY = (CenterY < 0) ? 0: CenterY;
+	SetWindowPos (hWndCenter, NULL, CenterX, CenterY, 0, 0,
+			SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW | SWP_DRAWFRAME);
+}
+
+qboolean VID_SetWindowedMode (int modenum)
+{
+	HDC				hdc;
+	int				lastmodestate, width, height;
+	RECT			rect;
+
+	lastmodestate = modestate;
+
+	WindowRect.top = WindowRect.left = 0;
+
+	WindowRect.right = modelist[modenum].width;
+	WindowRect.bottom = modelist[modenum].height;
+
+	DIBWidth = modelist[modenum].width;
+	DIBHeight = modelist[modenum].height;
+
+	WindowStyle = WS_OVERLAPPED | WS_BORDER | WS_CAPTION | WS_SYSMENU |
+				  WS_MINIMIZEBOX;
+	ExWindowStyle = 0;
+
+	rect = WindowRect;
+	AdjustWindowRectEx(&rect, WindowStyle, FALSE, 0);
+
+	width = rect.right - rect.left;
+	height = rect.bottom - rect.top;
+
+	// Create the DIB window
+	dibwindow = CreateWindowEx (
+		 ExWindowStyle,
+		 "WinQuake",
+		 "GLQuake",
+		 WindowStyle,
+		 rect.left, rect.top,
+		 width,
+		 height,
+		 NULL,
+		 NULL,
+		 global_hInstance,
+		 NULL);
+
+	if (!dibwindow)
+		Sys_Error ("Couldn't create DIB window");
+
+	// Center and show the DIB window
+	CenterWindow(dibwindow, WindowRect.right - WindowRect.left,
+				 WindowRect.bottom - WindowRect.top, false);
+
+	ShowWindow (dibwindow, SW_SHOWDEFAULT);
+	UpdateWindow (dibwindow);
+
+	modestate = MS_WINDOWED;
+
+// because we have set the background brush for the window to NULL
+// (to avoid flickering when re-sizing the window on the desktop),
+// we clear the window to black when created, otherwise it will be
+// empty while Quake starts up.
+	hdc = GetDC(dibwindow);
+	PatBlt(hdc,0,0,WindowRect.right,WindowRect.bottom,BLACKNESS);
+	ReleaseDC(dibwindow, hdc);
+
+	if (vid.conheight > modelist[modenum].height)
+		vid.conheight = modelist[modenum].height;
+	if (vid.conwidth > modelist[modenum].width)
+		vid.conwidth = modelist[modenum].width;
+	vid.width = vid.conwidth;
+	vid.height = vid.conheight;
+
+	vid.numpages = 2;
+
+	mainwindow = dibwindow;
+
+	SendMessage (mainwindow, WM_SETICON, (WPARAM)TRUE, (LPARAM)hIcon);
+	SendMessage (mainwindow, WM_SETICON, (WPARAM)FALSE, (LPARAM)hIcon);
+
+	return true;
+}
+
+
+qboolean VID_SetFullDIBMode (int modenum)
+{
+	HDC				hdc;
+	int				lastmodestate, width, height;
+	RECT			rect;
+
+	if (!leavecurrentmode)
+	{
+		gdevmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
+		gdevmode.dmBitsPerPel = modelist[modenum].bpp;
+		gdevmode.dmPelsWidth = modelist[modenum].width <<
+							   modelist[modenum].halfscreen;
+		gdevmode.dmPelsHeight = modelist[modenum].height;
+		gdevmode.dmSize = sizeof (gdevmode);
+
+		if (ChangeDisplaySettings (&gdevmode, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL)
+			Sys_Error ("Couldn't set fullscreen DIB mode");
+	}
+
+	lastmodestate = modestate;
+	modestate = MS_FULLDIB;
+
+	WindowRect.top = WindowRect.left = 0;
+
+	WindowRect.right = modelist[modenum].width;
+	WindowRect.bottom = modelist[modenum].height;
+
+	DIBWidth = modelist[modenum].width;
+	DIBHeight = modelist[modenum].height;
+
+	WindowStyle = WS_POPUP;
+	ExWindowStyle = 0;
+
+	rect = WindowRect;
+	AdjustWindowRectEx(&rect, WindowStyle, FALSE, 0);
+
+	width = rect.right - rect.left;
+	height = rect.bottom - rect.top;
+
+	// Create the DIB window
+	dibwindow = CreateWindowEx (
+		 ExWindowStyle,
+		 "WinQuake",
+		 "GLQuake",
+		 WindowStyle,
+		 rect.left, rect.top,
+		 width,
+		 height,
+		 NULL,
+		 NULL,
+		 global_hInstance,
+		 NULL);
+
+	if (!dibwindow)
+		Sys_Error ("Couldn't create DIB window");
+
+	ShowWindow (dibwindow, SW_SHOWDEFAULT);
+	UpdateWindow (dibwindow);
+
+	// Because we have set the background brush for the window to NULL
+	// (to avoid flickering when re-sizing the window on the desktop), we
+	// clear the window to black when created, otherwise it will be
+	// empty while Quake starts up.
+	hdc = GetDC(dibwindow);
+	PatBlt(hdc,0,0,WindowRect.right,WindowRect.bottom,BLACKNESS);
+	ReleaseDC(dibwindow, hdc);
+
+	if (vid.conheight > modelist[modenum].height)
+		vid.conheight = modelist[modenum].height;
+	if (vid.conwidth > modelist[modenum].width)
+		vid.conwidth = modelist[modenum].width;
+	vid.width = vid.conwidth;
+	vid.height = vid.conheight;
+
+	vid.numpages = 2;
+
+// needed because we're not getting WM_MOVE messages fullscreen on NT
+	window_x = 0;
+	window_y = 0;
+
+	mainwindow = dibwindow;
+
+	SendMessage (mainwindow, WM_SETICON, (WPARAM)TRUE, (LPARAM)hIcon);
+	SendMessage (mainwindow, WM_SETICON, (WPARAM)FALSE, (LPARAM)hIcon);
+
+	return true;
+}
+
+
+int VID_SetMode (int modenum, unsigned char *palette)
+{
+	int				original_mode, temp;
+	qboolean		stat;
+    MSG				msg;
+	HDC				hdc;
+
+	if ((windowed && (modenum != 0)) ||
+		(!windowed && (modenum < 1)) ||
+		(!windowed && (modenum >= nummodes)))
+	{
+		Sys_Error ("Bad video mode\n");
+	}
+
+// so Con_Printfs don't mess us up by forcing vid and snd updates
+	temp = scr_disabled_for_loading;
+	scr_disabled_for_loading = true;
+
+	CDAudio_Pause ();
+
+	if (vid_modenum == NO_MODE)
+		original_mode = windowed_default;
+	else
+		original_mode = vid_modenum;
+
+	// Set either the fullscreen or windowed mode
+	if (modelist[modenum].type == MS_WINDOWED)
+	{
+		if (_windowed_mouse.value && key_dest == key_game)
+		{
+			stat = VID_SetWindowedMode(modenum);
+			IN_ActivateMouse ();
+			IN_HideMouse ();
+		}
+		else
+		{
+			IN_DeactivateMouse ();
+			IN_ShowMouse ();
+			stat = VID_SetWindowedMode(modenum);
+		}
+	}
+	else if (modelist[modenum].type == MS_FULLDIB)
+	{
+		stat = VID_SetFullDIBMode(modenum);
+		IN_ActivateMouse ();
+		IN_HideMouse ();
+	}
+	else
+	{
+		Sys_Error ("VID_SetMode: Bad mode type in modelist");
+	}
+
+	window_width = DIBWidth;
+	window_height = DIBHeight;
+	VID_UpdateWindowStatus ();
+
+	CDAudio_Resume ();
+	scr_disabled_for_loading = temp;
+
+	if (!stat)
+	{
+		Sys_Error ("Couldn't set video mode");
+	}
+
+// now we try to make sure we get the focus on the mode switch, because
+// sometimes in some systems we don't.  We grab the foreground, then
+// finish setting up, pump all our messages, and sleep for a little while
+// to let messages finish bouncing around the system, then we put
+// ourselves at the top of the z order, then grab the foreground again,
+// Who knows if it helps, but it probably doesn't hurt
+	SetForegroundWindow (mainwindow);
+	VID_SetPalette (palette);
+	vid_modenum = modenum;
+	Cvar_SetValue ("vid_mode", (float)vid_modenum);
+
+	while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE))
+	{
+      	TranslateMessage (&msg);
+      	DispatchMessage (&msg);
+	}
+
+	Sleep (100);
+
+	SetWindowPos (mainwindow, HWND_TOP, 0, 0, 0, 0,
+				  SWP_DRAWFRAME | SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW |
+				  SWP_NOCOPYBITS);
+
+	SetForegroundWindow (mainwindow);
+
+// fix the leftover Alt from any Alt-Tab or the like that switched us away
+	ClearAllStates ();
+
+	if (!msg_suppress_1)
+		Con_SafePrintf ("Video mode %s initialized.\n", VID_GetModeDescription (vid_modenum));
+
+	VID_SetPalette (palette);
+
+	vid.recalc_refdef = 1;
+
+	return true;
+}
+
+
+/*
+================
+VID_UpdateWindowStatus
+================
+*/
+void VID_UpdateWindowStatus (void)
+{
+
+	window_rect.left = window_x;
+	window_rect.top = window_y;
+	window_rect.right = window_x + window_width;
+	window_rect.bottom = window_y + window_height;
+	window_center_x = (window_rect.left + window_rect.right) / 2;
+	window_center_y = (window_rect.top + window_rect.bottom) / 2;
+
+	IN_UpdateClipCursor ();
+}
+
+
+//====================================
+
+BINDTEXFUNCPTR bindTexFunc;
+
+#define TEXTURE_EXT_STRING "GL_EXT_texture_object"
+
+
+void CheckTextureExtensions (void)
+{
+	char		*tmp;
+	qboolean	texture_ext;
+	HINSTANCE	hInstGL;
+
+	texture_ext = FALSE;
+	/* check for texture extension */
+	tmp = (unsigned char *)glGetString(GL_EXTENSIONS);
+	while (*tmp)
+	{
+		if (strncmp((const char*)tmp, TEXTURE_EXT_STRING, strlen(TEXTURE_EXT_STRING)) == 0)
+			texture_ext = TRUE;
+		tmp++;
+	}
+
+	if (!texture_ext || COM_CheckParm ("-gl11") )
+	{
+		hInstGL = LoadLibrary("opengl32.dll");
+		
+		if (hInstGL == NULL)
+			Sys_Error ("Couldn't load opengl32.dll\n");
+
+		bindTexFunc = (void *)GetProcAddress(hInstGL,"glBindTexture");
+
+		if (!bindTexFunc)
+			Sys_Error ("No texture objects!");
+		return;
+	}
+
+/* load library and get procedure adresses for texture extension API */
+	if ((bindTexFunc = (BINDTEXFUNCPTR)
+		wglGetProcAddress((LPCSTR) "glBindTextureEXT")) == NULL)
+	{
+		Sys_Error ("GetProcAddress for BindTextureEXT failed");
+		return;
+	}
+}
+
+void CheckArrayExtensions (void)
+{
+	char		*tmp;
+
+	/* check for texture extension */
+	tmp = (unsigned char *)glGetString(GL_EXTENSIONS);
+	while (*tmp)
+	{
+		if (strncmp((const char*)tmp, "GL_EXT_vertex_array", strlen("GL_EXT_vertex_array")) == 0)
+		{
+			if (
+((glArrayElementEXT = wglGetProcAddress("glArrayElementEXT")) == NULL) ||
+((glColorPointerEXT = wglGetProcAddress("glColorPointerEXT")) == NULL) ||
+((glTexCoordPointerEXT = wglGetProcAddress("glTexCoordPointerEXT")) == NULL) ||
+((glVertexPointerEXT = wglGetProcAddress("glVertexPointerEXT")) == NULL) )
+			{
+				Sys_Error ("GetProcAddress for vertex extension failed");
+				return;
+			}
+			return;
+		}
+		tmp++;
+	}
+
+	Sys_Error ("Vertex array extension not present");
+}
+
+//int		texture_mode = GL_NEAREST;
+//int		texture_mode = GL_NEAREST_MIPMAP_NEAREST;
+//int		texture_mode = GL_NEAREST_MIPMAP_LINEAR;
+int		texture_mode = GL_LINEAR;
+//int		texture_mode = GL_LINEAR_MIPMAP_NEAREST;
+//int		texture_mode = GL_LINEAR_MIPMAP_LINEAR;
+
+int		texture_extension_number = 1;
+
+#ifdef _WIN32
+void CheckMultiTextureExtensions(void) 
+{
+	if (strstr(gl_extensions, "GL_SGIS_multitexture ") && !COM_CheckParm("-nomtex")) {
+		Con_Printf("Multitexture extensions found.\n");
+		qglMTexCoord2fSGIS = (void *) wglGetProcAddress("glMTexCoord2fSGIS");
+		qglSelectTextureSGIS = (void *) wglGetProcAddress("glSelectTextureSGIS");
+		gl_mtexable = true;
+	}
+}
+#else
+void CheckMultiTextureExtensions(void) 
+{
+		gl_mtexable = true;
+}
+#endif
+
+/*
+===============
+GL_Init
+===============
+*/
+void GL_Init (void)
+{
+	gl_vendor = glGetString (GL_VENDOR);
+	Con_Printf ("GL_VENDOR: %s\n", gl_vendor);
+	gl_renderer = glGetString (GL_RENDERER);
+	Con_Printf ("GL_RENDERER: %s\n", gl_renderer);
+
+	gl_version = glGetString (GL_VERSION);
+	Con_Printf ("GL_VERSION: %s\n", gl_version);
+	gl_extensions = glGetString (GL_EXTENSIONS);
+	Con_Printf ("GL_EXTENSIONS: %s\n", gl_extensions);
+
+//	Con_Printf ("%s %s\n", gl_renderer, gl_version);
+
+    if (strnicmp(gl_renderer,"PowerVR",7)==0)
+         fullsbardraw = true;
+
+    if (strnicmp(gl_renderer,"Permedia",8)==0)
+         isPermedia = true;
+
+	CheckTextureExtensions ();
+	CheckMultiTextureExtensions ();
+
+	glClearColor (1,0,0,0);
+	glCullFace(GL_FRONT);
+	glEnable(GL_TEXTURE_2D);
+
+	glEnable(GL_ALPHA_TEST);
+	glAlphaFunc(GL_GREATER, 0.666);
+
+	glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
+	glShadeModel (GL_FLAT);
+
+	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+
+	glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+//	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+
+#if 0
+	CheckArrayExtensions ();
+
+	glEnable (GL_VERTEX_ARRAY_EXT);
+	glEnable (GL_TEXTURE_COORD_ARRAY_EXT);
+	glVertexPointerEXT (3, GL_FLOAT, 0, 0, &glv.x);
+	glTexCoordPointerEXT (2, GL_FLOAT, 0, 0, &glv.s);
+	glColorPointerEXT (3, GL_FLOAT, 0, 0, &glv.r);
+#endif
+}
+
+/*
+=================
+GL_BeginRendering
+
+=================
+*/
+void GL_BeginRendering (int *x, int *y, int *width, int *height)
+{
+	extern cvar_t gl_clear;
+
+	*x = *y = 0;
+	*width = WindowRect.right - WindowRect.left;
+	*height = WindowRect.bottom - WindowRect.top;
+
+//    if (!wglMakeCurrent( maindc, baseRC ))
+//		Sys_Error ("wglMakeCurrent failed");
+
+//	glViewport (*x, *y, *width, *height);
+}
+
+
+void GL_EndRendering (void)
+{
+	if (!scr_skipupdate || block_drawing)
+		SwapBuffers(maindc);
+
+// handle the mouse state when windowed if that's changed
+	if (modestate == MS_WINDOWED)
+	{
+		if (!_windowed_mouse.value) {
+			if (windowed_mouse)	{
+				IN_DeactivateMouse ();
+				IN_ShowMouse ();
+				windowed_mouse = false;
+			}
+		} else {
+			windowed_mouse = true;
+			if (key_dest == key_game && !mouseactive && ActiveApp) {
+				IN_ActivateMouse ();
+				IN_HideMouse ();
+			} else if (mouseactive && key_dest != key_game) {
+				IN_DeactivateMouse ();
+				IN_ShowMouse ();
+			}
+		}
+	}
+	if (fullsbardraw)
+		Sbar_Changed();
+}
+
+void	VID_SetPalette (unsigned char *palette)
+{
+	byte	*pal;
+	unsigned r,g,b;
+	unsigned v;
+	int     r1,g1,b1;
+	int		j,k,l,m;
+	unsigned short i;
+	unsigned	*table;
+	FILE *f;
+	char s[255];
+	HWND hDlg, hProgress;
+	float gamma;
+
+//
+// 8 8 8 encoding
+//
+	pal = palette;
+	table = d_8to24table;
+	for (i=0 ; i<256 ; i++)
+	{
+		r = pal[0];
+		g = pal[1];
+		b = pal[2];
+		pal += 3;
+		
+//		v = (255<<24) + (r<<16) + (g<<8) + (b<<0);
+//		v = (255<<0) + (r<<8) + (g<<16) + (b<<24);
+		v = (255<<24) + (r<<0) + (g<<8) + (b<<16);
+		*table++ = v;
+	}
+	d_8to24table[255] &= 0xffffff;	// 255 is transparent
+
+	// JACK: 3D distance calcs - k is last closest, l is the distance.
+	// FIXME: Precalculate this and cache to disk.
+	for (i=0; i < (1<<15); i++) {
+		/* Maps
+			000000000000000
+			000000000011111 = Red  = 0x1F
+			000001111100000 = Blue = 0x03E0
+			111110000000000 = Grn  = 0x7C00
+		*/
+		r = ((i & 0x1F) << 3)+4;
+		g = ((i & 0x03E0) >> 2)+4;
+		b = ((i & 0x7C00) >> 7)+4;
+		pal = (unsigned char *)d_8to24table;
+		for (v=0,k=0,l=10000*10000; v<256; v++,pal+=4) {
+			r1 = r-pal[0];
+			g1 = g-pal[1];
+			b1 = b-pal[2];
+			j = (r1*r1)+(g1*g1)+(b1*b1);
+			if (j<l) {
+				k=v;
+				l=j;
+			}
+		}
+		d_15to8table[i]=k;
+	}
+}
+
+BOOL	gammaworks;
+
+void	VID_ShiftPalette (unsigned char *palette)
+{
+	extern	byte ramps[3][256];
+	
+//	VID_SetPalette (palette);
+
+//	gammaworks = SetDeviceGammaRamp (maindc, ramps);
+}
+
+
+void VID_SetDefaultMode (void)
+{
+	IN_DeactivateMouse ();
+}
+
+
+void	VID_Shutdown (void)
+{
+   	HGLRC hRC;
+   	HDC	  hDC;
+
+	if (vid_initialized)
+	{
+		vid_canalttab = false;
+		hRC = wglGetCurrentContext();
+    	hDC = wglGetCurrentDC();
+
+    	wglMakeCurrent(NULL, NULL);
+
+    	if (hRC)
+    	    wglDeleteContext(hRC);
+
+		if (hDC && dibwindow)
+			ReleaseDC(dibwindow, hDC);
+
+		if (modestate == MS_FULLDIB)
+			ChangeDisplaySettings (NULL, 0);
+
+		if (maindc && dibwindow)
+			ReleaseDC (dibwindow, maindc);
+
+		AppActivate(false, false);
+	}
+}
+
+
+//==========================================================================
+
+
+BOOL bSetupPixelFormat(HDC hDC)
+{
+    static PIXELFORMATDESCRIPTOR pfd = {
+	sizeof(PIXELFORMATDESCRIPTOR),	// size of this pfd
+	1,				// version number
+	PFD_DRAW_TO_WINDOW 		// support window
+	|  PFD_SUPPORT_OPENGL 	// support OpenGL
+	|  PFD_DOUBLEBUFFER ,	// double buffered
+	PFD_TYPE_RGBA,			// RGBA type
+	24,				// 24-bit color depth
+	0, 0, 0, 0, 0, 0,		// color bits ignored
+	0,				// no alpha buffer
+	0,				// shift bit ignored
+	0,				// no accumulation buffer
+	0, 0, 0, 0, 			// accum bits ignored
+	32,				// 32-bit z-buffer	
+	0,				// no stencil buffer
+	0,				// no auxiliary buffer
+	PFD_MAIN_PLANE,			// main layer
+	0,				// reserved
+	0, 0, 0				// layer masks ignored
+    };
+    int pixelformat;
+
+    if ( (pixelformat = ChoosePixelFormat(hDC, &pfd)) == 0 )
+    {
+        MessageBox(NULL, "ChoosePixelFormat failed", "Error", MB_OK);
+        return FALSE;
+    }
+
+    if (SetPixelFormat(hDC, pixelformat, &pfd) == FALSE)
+    {
+        MessageBox(NULL, "SetPixelFormat failed", "Error", MB_OK);
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
+
+
+byte        scantokey[128] = 
+					{ 
+//  0           1       2       3       4       5       6       7 
+//  8           9       A       B       C       D       E       F 
+	0  ,    27,     '1',    '2',    '3',    '4',    '5',    '6', 
+	'7',    '8',    '9',    '0',    '-',    '=',    K_BACKSPACE, 9, // 0 
+	'q',    'w',    'e',    'r',    't',    'y',    'u',    'i', 
+	'o',    'p',    '[',    ']',    13 ,    K_CTRL,'a',  's',      // 1 
+	'd',    'f',    'g',    'h',    'j',    'k',    'l',    ';', 
+	'\'' ,    '`',    K_SHIFT,'\\',  'z',    'x',    'c',    'v',      // 2 
+	'b',    'n',    'm',    ',',    '.',    '/',    K_SHIFT,'*', 
+	K_ALT,' ',   0  ,    K_F1, K_F2, K_F3, K_F4, K_F5,   // 3 
+	K_F6, K_F7, K_F8, K_F9, K_F10, K_PAUSE  ,    0  , K_HOME, 
+	K_UPARROW,K_PGUP,'-',K_LEFTARROW,'5',K_RIGHTARROW,'+',K_END, //4 
+	K_DOWNARROW,K_PGDN,K_INS,K_DEL,0,0,             0,              K_F11, 
+	K_F12,0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0,        // 5 
+	0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0, 
+	0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0,        // 6 
+	0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0, 
+	0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0         // 7 
+					}; 
+
+byte        shiftscantokey[128] = 
+					{ 
+//  0           1       2       3       4       5       6       7 
+//  8           9       A       B       C       D       E       F 
+	0  ,    27,     '!',    '@',    '#',    '$',    '%',    '^', 
+	'&',    '*',    '(',    ')',    '_',    '+',    K_BACKSPACE, 9, // 0 
+	'Q',    'W',    'E',    'R',    'T',    'Y',    'U',    'I', 
+	'O',    'P',    '{',    '}',    13 ,    K_CTRL,'A',  'S',      // 1 
+	'D',    'F',    'G',    'H',    'J',    'K',    'L',    ':', 
+	'"' ,    '~',    K_SHIFT,'|',  'Z',    'X',    'C',    'V',      // 2 
+	'B',    'N',    'M',    '<',    '>',    '?',    K_SHIFT,'*', 
+	K_ALT,' ',   0  ,    K_F1, K_F2, K_F3, K_F4, K_F5,   // 3 
+	K_F6, K_F7, K_F8, K_F9, K_F10, K_PAUSE  ,    0  , K_HOME, 
+	K_UPARROW,K_PGUP,'_',K_LEFTARROW,'%',K_RIGHTARROW,'+',K_END, //4 
+	K_DOWNARROW,K_PGDN,K_INS,K_DEL,0,0,             0,              K_F11, 
+	K_F12,0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0,        // 5 
+	0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0, 
+	0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0,        // 6 
+	0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0, 
+	0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0         // 7 
+					}; 
+
+
+/*
+=======
+MapKey
+
+Map from windows to quake keynums
+=======
+*/
+int MapKey (int key)
+{
+	key = (key>>16)&255;
+	if (key > 127)
+		return 0;
+	if (scantokey[key] == 0)
+		Con_DPrintf("key 0x%02x has no translation\n", key);
+	return scantokey[key];
+}
+
+/*
+===================================================================
+
+MAIN WINDOW
+
+===================================================================
+*/
+
+/*
+================
+ClearAllStates
+================
+*/
+void ClearAllStates (void)
+{
+	int		i;
+	
+// send an up event for each key, to make sure the server clears them all
+	for (i=0 ; i<256 ; i++)
+	{
+		Key_Event (i, false);
+	}
+
+	Key_ClearStates ();
+	IN_ClearStates ();
+}
+
+void AppActivate(BOOL fActive, BOOL minimize)
+/****************************************************************************
+*
+* Function:     AppActivate
+* Parameters:   fActive - True if app is activating
+*
+* Description:  If the application is activating, then swap the system
+*               into SYSPAL_NOSTATIC mode so that our palettes will display
+*               correctly.
+*
+****************************************************************************/
+{
+	MSG msg;
+    HDC			hdc;
+    int			i, t;
+	static BOOL	sound_active;
+
+	ActiveApp = fActive;
+	Minimized = minimize;
+
+// enable/disable sound on focus gain/loss
+	if (!ActiveApp && sound_active)
+	{
+		S_BlockSound ();
+		sound_active = false;
+	}
+	else if (ActiveApp && !sound_active)
+	{
+		S_UnblockSound ();
+		sound_active = true;
+	}
+
+	if (fActive)
+	{
+		if (modestate == MS_FULLDIB)
+		{
+			IN_ActivateMouse ();
+			IN_HideMouse ();
+			if (vid_canalttab && vid_wassuspended) {
+				vid_wassuspended = false;
+				ChangeDisplaySettings (&gdevmode, CDS_FULLSCREEN);
+				ShowWindow(mainwindow, SW_SHOWNORMAL);
+			}
+		}
+		else if ((modestate == MS_WINDOWED) && _windowed_mouse.value && key_dest == key_game)
+		{
+			IN_ActivateMouse ();
+			IN_HideMouse ();
+		}
+	}
+
+	if (!fActive)
+	{
+		if (modestate == MS_FULLDIB)
+		{
+			IN_DeactivateMouse ();
+			IN_ShowMouse ();
+			if (vid_canalttab) { 
+				ChangeDisplaySettings (NULL, 0);
+				vid_wassuspended = true;
+			}
+		}
+		else if ((modestate == MS_WINDOWED) && _windowed_mouse.value)
+		{
+			IN_DeactivateMouse ();
+			IN_ShowMouse ();
+		}
+	}
+}
+
+
+/* main window procedure */
+LONG WINAPI MainWndProc (
+    HWND    hWnd,
+    UINT    uMsg,
+    WPARAM  wParam,
+    LPARAM  lParam)
+{
+    LONG    lRet = 1;
+	int		fwKeys, xPos, yPos, fActive, fMinimized, temp;
+	extern unsigned int uiWheelMessage;
+
+	if ( uMsg == uiWheelMessage )
+		uMsg = WM_MOUSEWHEEL;
+
+    switch (uMsg)
+    {
+		case WM_KILLFOCUS:
+			if (modestate == MS_FULLDIB)
+				ShowWindow(mainwindow, SW_SHOWMINNOACTIVE);
+			break;
+
+		case WM_CREATE:
+			break;
+
+		case WM_MOVE:
+			window_x = (int) LOWORD(lParam);
+			window_y = (int) HIWORD(lParam);
+			VID_UpdateWindowStatus ();
+			break;
+
+		case WM_KEYDOWN:
+		case WM_SYSKEYDOWN:
+			Key_Event (MapKey(lParam), true);
+			break;
+			
+		case WM_KEYUP:
+		case WM_SYSKEYUP:
+			Key_Event (MapKey(lParam), false);
+			break;
+
+		case WM_SYSCHAR:
+		// keep Alt-Space from happening
+			break;
+
+	// this is complicated because Win32 seems to pack multiple mouse events into
+	// one update sometimes, so we always check all states and look for events
+		case WM_LBUTTONDOWN:
+		case WM_LBUTTONUP:
+		case WM_RBUTTONDOWN:
+		case WM_RBUTTONUP:
+		case WM_MBUTTONDOWN:
+		case WM_MBUTTONUP:
+		case WM_MOUSEMOVE:
+			temp = 0;
+
+			if (wParam & MK_LBUTTON)
+				temp |= 1;
+
+			if (wParam & MK_RBUTTON)
+				temp |= 2;
+
+			if (wParam & MK_MBUTTON)
+				temp |= 4;
+
+			IN_MouseEvent (temp);
+
+			break;
+
+		// JACK: This is the mouse wheel with the Intellimouse
+		// Its delta is either positive or neg, and we generate the proper
+		// Event.
+		case WM_MOUSEWHEEL: 
+			if ((short) HIWORD(wParam) > 0) {
+				Key_Event(K_MWHEELUP, true);
+				Key_Event(K_MWHEELUP, false);
+			} else {
+				Key_Event(K_MWHEELDOWN, true);
+				Key_Event(K_MWHEELDOWN, false);
+			}
+			break;
+
+    	case WM_SIZE:
+            break;
+
+   	    case WM_CLOSE:
+			if (MessageBox (mainwindow, "Are you sure you want to quit?", "Confirm Exit",
+						MB_YESNO | MB_SETFOREGROUND | MB_ICONQUESTION) == IDYES)
+			{
+				Sys_Quit ();
+			}
+
+	        break;
+
+		case WM_ACTIVATE:
+			fActive = LOWORD(wParam);
+			fMinimized = (BOOL) HIWORD(wParam);
+			AppActivate(!(fActive == WA_INACTIVE), fMinimized);
+
+		// fix the leftover Alt from any Alt-Tab or the like that switched us away
+			ClearAllStates ();
+
+			break;
+
+   	    case WM_DESTROY:
+        {
+			if (dibwindow)
+				DestroyWindow (dibwindow);
+
+            PostQuitMessage (0);
+        }
+        break;
+
+		case MM_MCINOTIFY:
+            lRet = CDAudio_MessageHandler (hWnd, uMsg, wParam, lParam);
+			break;
+
+    	default:
+            /* pass all unhandled messages to DefWindowProc */
+            lRet = DefWindowProc (hWnd, uMsg, wParam, lParam);
+        break;
+    }
+
+    /* return 1 if handled message, 0 if not */
+    return lRet;
+}
+
+
+/*
+=================
+VID_NumModes
+=================
+*/
+int VID_NumModes (void)
+{
+	return nummodes;
+}
+
+	
+/*
+=================
+VID_GetModePtr
+=================
+*/
+vmode_t *VID_GetModePtr (int modenum)
+{
+
+	if ((modenum >= 0) && (modenum < nummodes))
+		return &modelist[modenum];
+	else
+		return &badmode;
+}
+
+
+/*
+=================
+VID_GetModeDescription
+=================
+*/
+char *VID_GetModeDescription (int mode)
+{
+	char		*pinfo;
+	vmode_t		*pv;
+	static char	temp[100];
+
+	if ((mode < 0) || (mode >= nummodes))
+		return NULL;
+
+	if (!leavecurrentmode)
+	{
+		pv = VID_GetModePtr (mode);
+		pinfo = pv->modedesc;
+	}
+	else
+	{
+		sprintf (temp, "Desktop resolution (%dx%d)",
+				 modelist[MODE_FULLSCREEN_DEFAULT].width,
+				 modelist[MODE_FULLSCREEN_DEFAULT].height);
+		pinfo = temp;
+	}
+
+	return pinfo;
+}
+
+
+// KJB: Added this to return the mode driver name in description for console
+
+char *VID_GetExtModeDescription (int mode)
+{
+	static char	pinfo[40];
+	vmode_t		*pv;
+
+	if ((mode < 0) || (mode >= nummodes))
+		return NULL;
+
+	pv = VID_GetModePtr (mode);
+	if (modelist[mode].type == MS_FULLDIB)
+	{
+		if (!leavecurrentmode)
+		{
+			sprintf(pinfo,"%s fullscreen", pv->modedesc);
+		}
+		else
+		{
+			sprintf (pinfo, "Desktop resolution (%dx%d)",
+					 modelist[MODE_FULLSCREEN_DEFAULT].width,
+					 modelist[MODE_FULLSCREEN_DEFAULT].height);
+		}
+	}
+	else
+	{
+		if (modestate == MS_WINDOWED)
+			sprintf(pinfo, "%s windowed", pv->modedesc);
+		else
+			sprintf(pinfo, "windowed");
+	}
+
+	return pinfo;
+}
+
+
+/*
+=================
+VID_DescribeCurrentMode_f
+=================
+*/
+void VID_DescribeCurrentMode_f (void)
+{
+	Con_Printf ("%s\n", VID_GetExtModeDescription (vid_modenum));
+}
+
+
+/*
+=================
+VID_NumModes_f
+=================
+*/
+void VID_NumModes_f (void)
+{
+
+	if (nummodes == 1)
+		Con_Printf ("%d video mode is available\n", nummodes);
+	else
+		Con_Printf ("%d video modes are available\n", nummodes);
+}
+
+
+/*
+=================
+VID_DescribeMode_f
+=================
+*/
+void VID_DescribeMode_f (void)
+{
+	int		t, modenum;
+	
+	modenum = Q_atoi (Cmd_Argv(1));
+
+	t = leavecurrentmode;
+	leavecurrentmode = 0;
+
+	Con_Printf ("%s\n", VID_GetExtModeDescription (modenum));
+
+	leavecurrentmode = t;
+}
+
+
+/*
+=================
+VID_DescribeModes_f
+=================
+*/
+void VID_DescribeModes_f (void)
+{
+	int			i, lnummodes, t;
+	char		*pinfo;
+	vmode_t		*pv;
+
+	lnummodes = VID_NumModes ();
+
+	t = leavecurrentmode;
+	leavecurrentmode = 0;
+
+	for (i=1 ; i<lnummodes ; i++)
+	{
+		pv = VID_GetModePtr (i);
+		pinfo = VID_GetExtModeDescription (i);
+		Con_Printf ("%2d: %s\n", i, pinfo);
+	}
+
+	leavecurrentmode = t;
+}
+
+
+void VID_InitDIB (HINSTANCE hInstance)
+{
+	WNDCLASS		wc;
+	HDC				hdc;
+	int				i;
+
+	/* Register the frame class */
+    wc.style         = 0;
+    wc.lpfnWndProc   = (WNDPROC)MainWndProc;
+    wc.cbClsExtra    = 0;
+    wc.cbWndExtra    = 0;
+    wc.hInstance     = hInstance;
+    wc.hIcon         = 0;
+    wc.hCursor       = LoadCursor (NULL,IDC_ARROW);
+	wc.hbrBackground = NULL;
+    wc.lpszMenuName  = 0;
+    wc.lpszClassName = "WinQuake";
+
+    if (!RegisterClass (&wc) )
+		Sys_Error ("Couldn't register window class");
+
+	modelist[0].type = MS_WINDOWED;
+
+	if (COM_CheckParm("-width"))
+		modelist[0].width = Q_atoi(com_argv[COM_CheckParm("-width")+1]);
+	else
+		modelist[0].width = 640;
+
+	if (modelist[0].width < 320)
+		modelist[0].width = 320;
+
+	if (COM_CheckParm("-height"))
+		modelist[0].height= Q_atoi(com_argv[COM_CheckParm("-height")+1]);
+	else
+		modelist[0].height = modelist[0].width * 240/320;
+
+	if (modelist[0].height < 240)
+		modelist[0].height = 240;
+
+	sprintf (modelist[0].modedesc, "%dx%d",
+			 modelist[0].width, modelist[0].height);
+
+	modelist[0].modenum = MODE_WINDOWED;
+	modelist[0].dib = 1;
+	modelist[0].fullscreen = 0;
+	modelist[0].halfscreen = 0;
+	modelist[0].bpp = 0;
+
+	nummodes = 1;
+}
+
+
+/*
+=================
+VID_InitFullDIB
+=================
+*/
+void VID_InitFullDIB (HINSTANCE hInstance)
+{
+	DEVMODE	devmode;
+	int		i, modenum, cmodes, originalnummodes, existingmode, numlowresmodes;
+	int		j, bpp, done;
+	BOOL	stat;
+
+// enumerate >8 bpp modes
+	originalnummodes = nummodes;
+	modenum = 0;
+
+	do
+	{
+		stat = EnumDisplaySettings (NULL, modenum, &devmode);
+
+		if ((devmode.dmBitsPerPel >= 15) &&
+			(devmode.dmPelsWidth <= MAXWIDTH) &&
+			(devmode.dmPelsHeight <= MAXHEIGHT) &&
+			(nummodes < MAX_MODE_LIST))
+		{
+			devmode.dmFields = DM_BITSPERPEL |
+							   DM_PELSWIDTH |
+							   DM_PELSHEIGHT;
+
+			if (ChangeDisplaySettings (&devmode, CDS_TEST | CDS_FULLSCREEN) ==
+					DISP_CHANGE_SUCCESSFUL)
+			{
+				modelist[nummodes].type = MS_FULLDIB;
+				modelist[nummodes].width = devmode.dmPelsWidth;
+				modelist[nummodes].height = devmode.dmPelsHeight;
+				modelist[nummodes].modenum = 0;
+				modelist[nummodes].halfscreen = 0;
+				modelist[nummodes].dib = 1;
+				modelist[nummodes].fullscreen = 1;
+				modelist[nummodes].bpp = devmode.dmBitsPerPel;
+				sprintf (modelist[nummodes].modedesc, "%dx%dx%d",
+						 devmode.dmPelsWidth, devmode.dmPelsHeight,
+						 devmode.dmBitsPerPel);
+
+			// if the width is more than twice the height, reduce it by half because this
+			// is probably a dual-screen monitor
+				if (!COM_CheckParm("-noadjustaspect"))
+				{
+					if (modelist[nummodes].width > (modelist[nummodes].height << 1))
+					{
+						modelist[nummodes].width >>= 1;
+						modelist[nummodes].halfscreen = 1;
+						sprintf (modelist[nummodes].modedesc, "%dx%dx%d",
+								 modelist[nummodes].width,
+								 modelist[nummodes].height,
+								 modelist[nummodes].bpp);
+					}
+				}
+
+				for (i=originalnummodes, existingmode = 0 ; i<nummodes ; i++)
+				{
+					if ((modelist[nummodes].width == modelist[i].width)   &&
+						(modelist[nummodes].height == modelist[i].height) &&
+						(modelist[nummodes].bpp == modelist[i].bpp))
+					{
+						existingmode = 1;
+						break;
+					}
+				}
+
+				if (!existingmode)
+				{
+					nummodes++;
+				}
+			}
+		}
+
+		modenum++;
+	} while (stat);
+
+// see if there are any low-res modes that aren't being reported
+	numlowresmodes = sizeof(lowresmodes) / sizeof(lowresmodes[0]);
+	bpp = 16;
+	done = 0;
+
+	do
+	{
+		for (j=0 ; (j<numlowresmodes) && (nummodes < MAX_MODE_LIST) ; j++)
+		{
+			devmode.dmBitsPerPel = bpp;
+			devmode.dmPelsWidth = lowresmodes[j].width;
+			devmode.dmPelsHeight = lowresmodes[j].height;
+			devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
+
+			if (ChangeDisplaySettings (&devmode, CDS_TEST | CDS_FULLSCREEN) ==
+					DISP_CHANGE_SUCCESSFUL)
+			{
+				modelist[nummodes].type = MS_FULLDIB;
+				modelist[nummodes].width = devmode.dmPelsWidth;
+				modelist[nummodes].height = devmode.dmPelsHeight;
+				modelist[nummodes].modenum = 0;
+				modelist[nummodes].halfscreen = 0;
+				modelist[nummodes].dib = 1;
+				modelist[nummodes].fullscreen = 1;
+				modelist[nummodes].bpp = devmode.dmBitsPerPel;
+				sprintf (modelist[nummodes].modedesc, "%dx%dx%d",
+						 devmode.dmPelsWidth, devmode.dmPelsHeight,
+						 devmode.dmBitsPerPel);
+
+				for (i=originalnummodes, existingmode = 0 ; i<nummodes ; i++)
+				{
+					if ((modelist[nummodes].width == modelist[i].width)   &&
+						(modelist[nummodes].height == modelist[i].height) &&
+						(modelist[nummodes].bpp == modelist[i].bpp))
+					{
+						existingmode = 1;
+						break;
+					}
+				}
+
+				if (!existingmode)
+				{
+					nummodes++;
+				}
+			}
+		}
+		switch (bpp)
+		{
+			case 16:
+				bpp = 32;
+				break;
+
+			case 32:
+				bpp = 24;
+				break;
+
+			case 24:
+				done = 1;
+				break;
+		}
+	} while (!done);
+
+	if (nummodes == originalnummodes)
+		Con_SafePrintf ("No fullscreen DIB modes found\n");
+}
+
+qboolean VID_Is8bit() {
+	return is8bit;
+}
+
+#define GL_SHARED_TEXTURE_PALETTE_EXT 0x81FB
+
+void VID_Init8bitPalette() 
+{
+	// Check for 8bit Extensions and initialize them.
+	int i;
+	char thePalette[256*3];
+	char *oldPalette, *newPalette;
+
+	glColorTableEXT = (void *)wglGetProcAddress("glColorTableEXT");
+    if (!glColorTableEXT || strstr(gl_extensions, "GL_EXT_shared_texture_palette") ||
+		COM_CheckParm("-no8bit"))
+		return;
+
+	Con_SafePrintf("8-bit GL extensions enabled.\n");
+    glEnable( GL_SHARED_TEXTURE_PALETTE_EXT );
+	oldPalette = (char *) d_8to24table; //d_8to24table3dfx;
+	newPalette = thePalette;
+	for (i=0;i<256;i++) {
+		*newPalette++ = *oldPalette++;
+		*newPalette++ = *oldPalette++;
+		*newPalette++ = *oldPalette++;
+		oldPalette++;
+	}
+	glColorTableEXT(GL_SHARED_TEXTURE_PALETTE_EXT, GL_RGB, 256, GL_RGB, GL_UNSIGNED_BYTE,
+		(void *) thePalette);
+	is8bit = TRUE;
+}
+
+static void Check_Gamma (unsigned char *pal)
+{
+	float	f, inf;
+	unsigned char	palette[768];
+	int		i;
+
+	if ((i = COM_CheckParm("-gamma")) == 0) {
+		if ((gl_renderer && strstr(gl_renderer, "Voodoo")) ||
+			(gl_vendor && strstr(gl_vendor, "3Dfx")))
+			vid_gamma = 1;
+		else
+			vid_gamma = 0.7; // default to 0.7 on non-3dfx hardware
+	} else
+		vid_gamma = Q_atof(com_argv[i+1]);
+
+	for (i=0 ; i<768 ; i++)
+	{
+		f = pow ( (pal[i]+1)/256.0 , vid_gamma );
+		inf = f*255 + 0.5;
+		if (inf < 0)
+			inf = 0;
+		if (inf > 255)
+			inf = 255;
+		palette[i] = inf;
+	}
+
+	memcpy (pal, palette, sizeof(palette));
+}
+
+/*
+===================
+VID_Init
+===================
+*/
+void	VID_Init (unsigned char *palette)
+{
+	int		i, existingmode;
+	int		basenummodes, width, height, bpp, findbpp, done;
+	byte	*ptmp;
+	char	gldir[MAX_OSPATH];
+	HDC		hdc;
+	DEVMODE	devmode;
+
+	memset(&devmode, 0, sizeof(devmode));
+
+	Cvar_RegisterVariable (&vid_mode);
+	Cvar_RegisterVariable (&vid_wait);
+	Cvar_RegisterVariable (&vid_nopageflip);
+	Cvar_RegisterVariable (&_vid_wait_override);
+	Cvar_RegisterVariable (&_vid_default_mode);
+	Cvar_RegisterVariable (&_vid_default_mode_win);
+	Cvar_RegisterVariable (&vid_config_x);
+	Cvar_RegisterVariable (&vid_config_y);
+	Cvar_RegisterVariable (&vid_stretch_by_2);
+	Cvar_RegisterVariable (&_windowed_mouse);
+	Cvar_RegisterVariable (&gl_ztrick);
+
+	Cmd_AddCommand ("vid_nummodes", VID_NumModes_f);
+	Cmd_AddCommand ("vid_describecurrentmode", VID_DescribeCurrentMode_f);
+	Cmd_AddCommand ("vid_describemode", VID_DescribeMode_f);
+	Cmd_AddCommand ("vid_describemodes", VID_DescribeModes_f);
+
+	hIcon = LoadIcon (global_hInstance, MAKEINTRESOURCE (IDI_ICON2));
+
+	InitCommonControls();
+
+	VID_InitDIB (global_hInstance);
+	basenummodes = nummodes = 1;
+
+	VID_InitFullDIB (global_hInstance);
+
+	if (COM_CheckParm("-window"))
+	{
+		hdc = GetDC (NULL);
+
+		if (GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE)
+		{
+			Sys_Error ("Can't run in non-RGB mode");
+		}
+
+		ReleaseDC (NULL, hdc);
+
+		windowed = true;
+
+		vid_default = MODE_WINDOWED;
+	}
+	else
+	{
+		if (nummodes == 1)
+			Sys_Error ("No RGB fullscreen modes available");
+
+		windowed = false;
+
+		if (COM_CheckParm("-mode"))
+		{
+			vid_default = Q_atoi(com_argv[COM_CheckParm("-mode")+1]);
+		}
+		else
+		{
+			if (COM_CheckParm("-current"))
+			{
+				modelist[MODE_FULLSCREEN_DEFAULT].width =
+						GetSystemMetrics (SM_CXSCREEN);
+				modelist[MODE_FULLSCREEN_DEFAULT].height =
+						GetSystemMetrics (SM_CYSCREEN);
+				vid_default = MODE_FULLSCREEN_DEFAULT;
+				leavecurrentmode = 1;
+			}
+			else
+			{
+				if (COM_CheckParm("-width"))
+				{
+					width = Q_atoi(com_argv[COM_CheckParm("-width")+1]);
+				}
+				else
+				{
+					width = 640;
+				}
+
+				if (COM_CheckParm("-bpp"))
+				{
+					bpp = Q_atoi(com_argv[COM_CheckParm("-bpp")+1]);
+					findbpp = 0;
+				}
+				else
+				{
+					bpp = 15;
+					findbpp = 1;
+				}
+
+				if (COM_CheckParm("-height"))
+					height = Q_atoi(com_argv[COM_CheckParm("-height")+1]);
+
+			// if they want to force it, add the specified mode to the list
+				if (COM_CheckParm("-force") && (nummodes < MAX_MODE_LIST))
+				{
+					modelist[nummodes].type = MS_FULLDIB;
+					modelist[nummodes].width = width;
+					modelist[nummodes].height = height;
+					modelist[nummodes].modenum = 0;
+					modelist[nummodes].halfscreen = 0;
+					modelist[nummodes].dib = 1;
+					modelist[nummodes].fullscreen = 1;
+					modelist[nummodes].bpp = bpp;
+					sprintf (modelist[nummodes].modedesc, "%dx%dx%d",
+							 devmode.dmPelsWidth, devmode.dmPelsHeight,
+							 devmode.dmBitsPerPel);
+
+					for (i=nummodes, existingmode = 0 ; i<nummodes ; i++)
+					{
+						if ((modelist[nummodes].width == modelist[i].width)   &&
+							(modelist[nummodes].height == modelist[i].height) &&
+							(modelist[nummodes].bpp == modelist[i].bpp))
+						{
+							existingmode = 1;
+							break;
+						}
+					}
+
+					if (!existingmode)
+					{
+						nummodes++;
+					}
+				}
+
+				done = 0;
+
+				do
+				{
+					if (COM_CheckParm("-height"))
+					{
+						height = Q_atoi(com_argv[COM_CheckParm("-height")+1]);
+
+						for (i=1, vid_default=0 ; i<nummodes ; i++)
+						{
+							if ((modelist[i].width == width) &&
+								(modelist[i].height == height) &&
+								(modelist[i].bpp == bpp))
+							{
+								vid_default = i;
+								done = 1;
+								break;
+							}
+						}
+					}
+					else
+					{
+						for (i=1, vid_default=0 ; i<nummodes ; i++)
+						{
+							if ((modelist[i].width == width) && (modelist[i].bpp == bpp))
+							{
+								vid_default = i;
+								done = 1;
+								break;
+							}
+						}
+					}
+
+					if (!done)
+					{
+						if (findbpp)
+						{
+							switch (bpp)
+							{
+							case 15:
+								bpp = 16;
+								break;
+							case 16:
+								bpp = 32;
+								break;
+							case 32:
+								bpp = 24;
+								break;
+							case 24:
+								done = 1;
+								break;
+							}
+						}
+						else
+						{
+							done = 1;
+						}
+					}
+				} while (!done);
+
+				if (!vid_default)
+				{
+					Sys_Error ("Specified video mode not available");
+				}
+			}
+		}
+	}
+
+	vid_initialized = true;
+
+	if ((i = COM_CheckParm("-conwidth")) != 0)
+		vid.conwidth = Q_atoi(com_argv[i+1]);
+	else
+		vid.conwidth = 640;
+
+	vid.conwidth &= 0xfff8; // make it a multiple of eight
+
+	if (vid.conwidth < 320)
+		vid.conwidth = 320;
+
+	// pick a conheight that matches with correct aspect
+	vid.conheight = vid.conwidth*3 / 4;
+
+	if ((i = COM_CheckParm("-conheight")) != 0)
+		vid.conheight = Q_atoi(com_argv[i+1]);
+	if (vid.conheight < 200)
+		vid.conheight = 200;
+
+	vid.maxwarpwidth = WARP_WIDTH;
+	vid.maxwarpheight = WARP_HEIGHT;
+	vid.colormap = host_colormap;
+	vid.fullbright = 256 - LittleLong (*((int *)vid.colormap + 2048));
+
+	DestroyWindow (hwnd_dialog);
+
+	Check_Gamma(palette);
+	VID_SetPalette (palette);
+
+	VID_SetMode (vid_default, palette);
+
+    maindc = GetDC(mainwindow);
+	bSetupPixelFormat(maindc);
+
+    baseRC = wglCreateContext( maindc );
+	if (!baseRC)
+		Sys_Error ("Could not initialize GL (wglCreateContext failed).\n\nMake sure you in are 65535 color mode, and try running -window.");
+    if (!wglMakeCurrent( maindc, baseRC ))
+		Sys_Error ("wglMakeCurrent failed");
+
+	GL_Init ();
+
+	sprintf (gldir, "%s/glquake", com_gamedir);
+	Sys_mkdir (gldir);
+
+	vid_realmode = vid_modenum;
+
+	// Check for 3DFX Extensions and initialize them.
+	VID_Init8bitPalette();
+
+	vid_menudrawfn = VID_MenuDraw;
+	vid_menukeyfn = VID_MenuKey;
+
+	strcpy (badmode.modedesc, "Bad mode");
+	vid_canalttab = true;
+
+	if (COM_CheckParm("-fullsbar"))
+		fullsbardraw = true;
+}
+
+
+//========================================================
+// Video menu stuff
+//========================================================
+
+extern void M_Menu_Options_f (void);
+extern void M_Print (int cx, int cy, char *str);
+extern void M_PrintWhite (int cx, int cy, char *str);
+extern void M_DrawCharacter (int cx, int line, int num);
+extern void M_DrawTransPic (int x, int y, qpic_t *pic);
+extern void M_DrawPic (int x, int y, qpic_t *pic);
+
+static int	vid_line, vid_wmodes;
+
+typedef struct
+{
+	int		modenum;
+	char	*desc;
+	int		iscur;
+} modedesc_t;
+
+#define MAX_COLUMN_SIZE		9
+#define MODE_AREA_HEIGHT	(MAX_COLUMN_SIZE + 2)
+#define MAX_MODEDESCS		(MAX_COLUMN_SIZE*3)
+
+static modedesc_t	modedescs[MAX_MODEDESCS];
+
+/*
+================
+VID_MenuDraw
+================
+*/
+void VID_MenuDraw (void)
+{
+	qpic_t		*p;
+	char		*ptr;
+	int			lnummodes, i, j, k, column, row, dup, dupmode;
+	char		temp[100];
+	vmode_t		*pv;
+
+	p = Draw_CachePic ("gfx/vidmodes.lmp");
+	M_DrawPic ( (320-p->width)/2, 4, p);
+
+	vid_wmodes = 0;
+	lnummodes = VID_NumModes ();
+	
+	for (i=1 ; (i<lnummodes) && (vid_wmodes < MAX_MODEDESCS) ; i++)
+	{
+		ptr = VID_GetModeDescription (i);
+		pv = VID_GetModePtr (i);
+
+		k = vid_wmodes;
+
+		modedescs[k].modenum = i;
+		modedescs[k].desc = ptr;
+		modedescs[k].iscur = 0;
+
+		if (i == vid_modenum)
+			modedescs[k].iscur = 1;
+
+		vid_wmodes++;
+
+	}
+
+	if (vid_wmodes > 0)
+	{
+		M_Print (2*8, 36+0*8, "Fullscreen Modes (WIDTHxHEIGHTxBPP)");
+
+		column = 8;
+		row = 36+2*8;
+
+		for (i=0 ; i<vid_wmodes ; i++)
+		{
+			if (modedescs[i].iscur)
+				M_PrintWhite (column, row, modedescs[i].desc);
+			else
+				M_Print (column, row, modedescs[i].desc);
+
+			column += 13*8;
+
+			if ((i % VID_ROW_SIZE) == (VID_ROW_SIZE - 1))
+			{
+				column = 8;
+				row += 8;
+			}
+		}
+	}
+
+	M_Print (3*8, 36 + MODE_AREA_HEIGHT * 8 + 8*2,
+			 "Video modes must be set from the");
+	M_Print (3*8, 36 + MODE_AREA_HEIGHT * 8 + 8*3,
+			 "command line with -width <width>");
+	M_Print (3*8, 36 + MODE_AREA_HEIGHT * 8 + 8*4,
+			 "and -bpp <bits-per-pixel>");
+	M_Print (3*8, 36 + MODE_AREA_HEIGHT * 8 + 8*6,
+			 "Select windowed mode with -window");
+}
+
+
+/*
+================
+VID_MenuKey
+================
+*/
+void VID_MenuKey (int key)
+{
+	switch (key)
+	{
+	case K_ESCAPE:
+		S_LocalSound ("misc/menu1.wav");
+		M_Menu_Options_f ();
+		break;
+
+	default:
+		break;
+	}
+}
--- /dev/null
+++ b/WinQuake/gl_warp_sin.h
@@ -1,0 +1,51 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+ 0, 0.19633, 0.392541, 0.588517, 0.784137, 0.979285, 1.17384, 1.3677,
+ 1.56072, 1.75281, 1.94384, 2.1337, 2.32228, 2.50945, 2.69512, 2.87916,
+ 3.06147, 3.24193, 3.42044, 3.59689, 3.77117, 3.94319, 4.11282, 4.27998,
+ 4.44456, 4.60647, 4.76559, 4.92185, 5.07515, 5.22538, 5.37247, 5.51632,
+ 5.65685, 5.79398, 5.92761, 6.05767, 6.18408, 6.30677, 6.42566, 6.54068,
+ 6.65176, 6.75883, 6.86183, 6.9607, 7.05537, 7.14579, 7.23191, 7.31368,
+ 7.39104, 7.46394, 7.53235, 7.59623, 7.65552, 7.71021, 7.76025, 7.80562,
+ 7.84628, 7.88222, 7.91341, 7.93984, 7.96148, 7.97832, 7.99036, 7.99759,
+ 8, 7.99759, 7.99036, 7.97832, 7.96148, 7.93984, 7.91341, 7.88222,
+ 7.84628, 7.80562, 7.76025, 7.71021, 7.65552, 7.59623, 7.53235, 7.46394,
+ 7.39104, 7.31368, 7.23191, 7.14579, 7.05537, 6.9607, 6.86183, 6.75883,
+ 6.65176, 6.54068, 6.42566, 6.30677, 6.18408, 6.05767, 5.92761, 5.79398,
+ 5.65685, 5.51632, 5.37247, 5.22538, 5.07515, 4.92185, 4.76559, 4.60647,
+ 4.44456, 4.27998, 4.11282, 3.94319, 3.77117, 3.59689, 3.42044, 3.24193,
+ 3.06147, 2.87916, 2.69512, 2.50945, 2.32228, 2.1337, 1.94384, 1.75281,
+ 1.56072, 1.3677, 1.17384, 0.979285, 0.784137, 0.588517, 0.392541, 0.19633,
+ 9.79717e-16, -0.19633, -0.392541, -0.588517, -0.784137, -0.979285, -1.17384, -1.3677,
+ -1.56072, -1.75281, -1.94384, -2.1337, -2.32228, -2.50945, -2.69512, -2.87916,
+ -3.06147, -3.24193, -3.42044, -3.59689, -3.77117, -3.94319, -4.11282, -4.27998,
+ -4.44456, -4.60647, -4.76559, -4.92185, -5.07515, -5.22538, -5.37247, -5.51632,
+ -5.65685, -5.79398, -5.92761, -6.05767, -6.18408, -6.30677, -6.42566, -6.54068,
+ -6.65176, -6.75883, -6.86183, -6.9607, -7.05537, -7.14579, -7.23191, -7.31368,
+ -7.39104, -7.46394, -7.53235, -7.59623, -7.65552, -7.71021, -7.76025, -7.80562,
+ -7.84628, -7.88222, -7.91341, -7.93984, -7.96148, -7.97832, -7.99036, -7.99759,
+ -8, -7.99759, -7.99036, -7.97832, -7.96148, -7.93984, -7.91341, -7.88222,
+ -7.84628, -7.80562, -7.76025, -7.71021, -7.65552, -7.59623, -7.53235, -7.46394,
+ -7.39104, -7.31368, -7.23191, -7.14579, -7.05537, -6.9607, -6.86183, -6.75883,
+ -6.65176, -6.54068, -6.42566, -6.30677, -6.18408, -6.05767, -5.92761, -5.79398,
+ -5.65685, -5.51632, -5.37247, -5.22538, -5.07515, -4.92185, -4.76559, -4.60647,
+ -4.44456, -4.27998, -4.11282, -3.94319, -3.77117, -3.59689, -3.42044, -3.24193,
+ -3.06147, -2.87916, -2.69512, -2.50945, -2.32228, -2.1337, -1.94384, -1.75281,
+ -1.56072, -1.3677, -1.17384, -0.979285, -0.784137, -0.588517, -0.392541, -0.19633,
--- /dev/null
+++ b/WinQuake/glqnotes.txt
@@ -1,0 +1,171 @@
+Glquake v0.99, Quake v1.09 release notes
+
+3dfx owners -- read the 3dfx.txt file.
+
+On a standard OpenGL system, all you should need to do to run glquake is put 
+glquake.exe in your quake directory, and run it from there.  DO NOT install 
+the opengl32.dll unless you have a 3dfx!  Glquake should change the screen 
+resolution to 640*480*32k colors and run full screen by default.
+
+If you are running win-95, your desktop must be set to 32k or 64k colors 
+before running glquake.  NT can switch automatically.
+
+Theoretically, glquake will run on any compliant OpenGL that supports the 
+texture objects extensions, but unless it is very powerfull hardware that 
+accelerates everything needed, the game play will not be acceptable.  If it 
+has to go through any software emulation paths, the performance will likely 
+by well under one frame per second.
+
+3dfx has provided an opengl32.dll that implements everything glquake needs, 
+but it is not a full opengl implementation.  Other opengl applications are 
+very unlikely to work with it, so consider it basically a "glquake driver".  
+See the encluded 3dfx.txt for specific instalation notes.  3dfx can only run 
+full screen, but you must still have your desktop set to a 16 bit color mode 
+for glquake to start.
+
+resolution options
+------------------
+We had dynamic resolution changing in glquake for a while, but every single 
+opengl driver I tried it on messed up in one way or another, so it is now 
+limited to startup time only.
+
+glquake -window
+This will start glquake in a window on your desktop instead of switching the 
+screen to lower resolution and covering everything.
+
+glquake -width 800 -height 600
+Tries to run glquake at the specified resolution.  Combined with -window, it 
+creates a desktop window that size, otherwise it tries to set a full screen 
+resolution.
+
+You can also specify the resolution of the console independant of the screen
+resolution.
+
+glquake -conwidth 320
+This will specify a console resolution of 320 by 240 (the height is
+automatically determined by the default 4:3 aspect ratio, you can also
+specify the height directly with -conheight).
+
+In higher resolution modes such as 800x600 and 1024x768, glquake will default
+to a 640x480 console, since the font becomes small enough at higher 
+resolutions to become unreadable.  If do you wish to have a higher resolution
+console and status bar, specify it as well, such as:
+glquake -width 800 -height 600 -conwidth 800
+
+texture options
+---------------
+The amount of textures used in the game can have a large impact on performance.  
+There are several options that let you trade off visual quality for better 
+performance.
+
+There is no way to flush already loaded textures, so it is best to change 
+these options on the command line, or they will only take effect on some of 
+the textures when you change levels.
+
+OpenGL only allows textures to repeat on power of two boundaries (32, 64, 
+128, etc), but software quake had a number of textures that repeated at 24 
+or 96 pixel boundaries.  These need to be either stretched out to the next 
+higher size, or shrunk down to the next lower.  By default, they are filtered 
+down to the smaller size, but you can cause it to use the larger size if you 
+really want by using: 
+
+glquake +gl_round_down 0
+This will generally run well on a normal 4 MB 3dfx card, but for other cards 
+that have either worse texture management or slower texture swapping speeds, 
+there are some additional settings that can drastically lower the amount of 
+textures to be managed.
+
+glquake +gl_picmip 1
+This causes all textures to have one half the dimensions they otherwise would.  
+This makes them blurry, but very small.  You can set this to 2 to make the 
+textures one quarter the resolution on each axis for REALLY blurry textures.
+
+glquake +gl_playermip 1
+This is similar to picmip, but is only used for other players in deathmatch.  
+Each player in a deathmatch requires an individual skin texture, so this can 
+be a serious problem for texture management.  It wouldn't be unreasonable to 
+set this to 2 or even 3 if you are playing competatively (and don't care if 
+the other guys have smudged skins).  If you change this during the game, it 
+will take effect as soon as a player changes their skin colors.
+
+GLQuake also supports the following extensions for faster texture operation:
+
+GL_SGIS_multitexture
+Multitextures support allows certain hardware to render the world in one
+pass instead of two.  GLQuake uses two passes, one for the world textures
+and the second for the lightmaps that are blended on the textures.  On some
+hardware, with a GL_SIGS_multitexture supported OpenGL implementation, this
+can be done in one pass.  On hardware that supports this, you will get a
+60% to 100% increase in frame rate.  Currently, only 3DFX dual TMU cards
+(such as the Obsidian 2220) support this extension, but other hardware will
+soon follow.
+
+This extension will be autodetected and used.  If for some reason it is not
+working correctly, specify the command line option "-nomtex" to disable it.
+
+GL_EXT_shared_texture_palette
+GLQuake uses 16bit textures by default but on OpenGL implementations 
+that support the GL_EXT_shared_texture_palette extension, GLQuake will use
+8bit textures instead.  This results in using half the needed texture memory
+of 16bit texture and can improve performance.  This is very little difference
+in visual quality due to the fact that the textures are 8bit sources to
+begin with.
+
+run time options
+----------------
+At the console, you can set these values to effect drawing.
+
+gl_texturemode GL_NEAREST
+Sets texture mapping to point sampled, which may be faster on some GL systems 
+(not on 3dfx).
+
+gl_texturemode GL_LINEAR_MIPMAP
+This is the default texture mode.
+
+gl_texturemode GL_LINEAR_MIPMAP_LINEAR
+This is the highest quality texture mapping (trilinear), but only very high 
+end hardware (intergraph intense 3D / realizm) supports it.  Not that big of 
+a deal, actually.
+
+gl_finish 0
+This causes the game to not issue a glFinish() call each frame, which may make 
+some hardware run faster.  If this is cleared, the 3dfx will back up a number 
+of frames and not be very playable.
+
+gl_flashblend 0
+By default, glquake just draws a shaded ball around objects that are emiting 
+light.  Clearing this variable will cause it to properly relight the world 
+like normal quake, but it can be a significant speed hit on some systems.
+
+gl_ztrick 0
+Glquake uses a buffering method that avoids clearing the Z buffer, but some 
+hardware platforms don't like it.  If the status bar and console are flashing 
+every other frame, clear this variable.
+
+gl_keeptjunctions 0
+If you clear this, glquake will remove colinear vertexes when it reloads the 
+level.  This can give a few percent speedup, but it can leave a couple stray 
+blinking pixels on the screen.
+
+novelty features
+----------------
+These are some rendering tricks that were easy to do in glquake.  They aren't 
+very robust, but they are pretty cool to look at.
+
+r_shadows 1
+This causes every object to cast a shadow.
+
+r_wateralpha 0.7
+This sets the opacity of water textures, so you can see through it in properly 
+processed maps.  0.3 is very faint, almost like fog.  1 is completely solid 
+(the default).  Unfortunately, the standard quake maps don't contain any 
+visibility information for seeing past water surfaces, so you can't just play 
+quake with this turned on.  If you just want to see what it looks like, you 
+can set "r_novis 1", but that will make things go very slow.  When I get a 
+chance, I will probably release some maps that have been processed properly 
+for this.
+
+r_mirroralpha 0.3
+This changes one particular texture (the stained glass texture in the EASY 
+start hall) into a mirror.  The value is the opacity of the mirror surface.
+
--- /dev/null
+++ b/WinQuake/glquake.h
@@ -1,0 +1,251 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// disable data conversion warnings
+
+#pragma warning(disable : 4244)     // MIPS
+#pragma warning(disable : 4136)     // X86
+#pragma warning(disable : 4051)     // ALPHA
+  
+#ifdef _WIN32
+#include <windows.h>
+#endif
+
+#include <GL/gl.h>
+#include <GL/glu.h>
+
+void GL_BeginRendering (int *x, int *y, int *width, int *height);
+void GL_EndRendering (void);
+
+
+#ifdef _WIN32
+// Function prototypes for the Texture Object Extension routines
+typedef GLboolean (APIENTRY *ARETEXRESFUNCPTR)(GLsizei, const GLuint *,
+                    const GLboolean *);
+typedef void (APIENTRY *BINDTEXFUNCPTR)(GLenum, GLuint);
+typedef void (APIENTRY *DELTEXFUNCPTR)(GLsizei, const GLuint *);
+typedef void (APIENTRY *GENTEXFUNCPTR)(GLsizei, GLuint *);
+typedef GLboolean (APIENTRY *ISTEXFUNCPTR)(GLuint);
+typedef void (APIENTRY *PRIORTEXFUNCPTR)(GLsizei, const GLuint *,
+                    const GLclampf *);
+typedef void (APIENTRY *TEXSUBIMAGEPTR)(int, int, int, int, int, int, int, int, void *);
+
+extern	BINDTEXFUNCPTR bindTexFunc;
+extern	DELTEXFUNCPTR delTexFunc;
+extern	TEXSUBIMAGEPTR TexSubImage2DFunc;
+#endif
+
+extern	int texture_extension_number;
+extern	int		texture_mode;
+
+extern	float	gldepthmin, gldepthmax;
+
+void GL_Upload32 (unsigned *data, int width, int height,  qboolean mipmap, qboolean alpha);
+void GL_Upload8 (byte *data, int width, int height,  qboolean mipmap, qboolean alpha);
+int GL_LoadTexture (char *identifier, int width, int height, byte *data, qboolean mipmap, qboolean alpha);
+int GL_FindTexture (char *identifier);
+
+typedef struct
+{
+	float	x, y, z;
+	float	s, t;
+	float	r, g, b;
+} glvert_t;
+
+extern glvert_t glv;
+
+extern	int glx, gly, glwidth, glheight;
+
+#ifdef _WIN32
+extern	PROC glArrayElementEXT;
+extern	PROC glColorPointerEXT;
+extern	PROC glTexturePointerEXT;
+extern	PROC glVertexPointerEXT;
+#endif
+
+// r_local.h -- private refresh defs
+
+#define ALIAS_BASE_SIZE_RATIO		(1.0 / 11.0)
+					// normalizing factor so player model works out to about
+					//  1 pixel per triangle
+#define	MAX_LBM_HEIGHT		480
+
+#define TILE_SIZE		128		// size of textures generated by R_GenTiledSurf
+
+#define SKYSHIFT		7
+#define	SKYSIZE			(1 << SKYSHIFT)
+#define SKYMASK			(SKYSIZE - 1)
+
+#define BACKFACE_EPSILON	0.01
+
+
+void R_TimeRefresh_f (void);
+void R_ReadPointFile_f (void);
+texture_t *R_TextureAnimation (texture_t *base);
+
+typedef struct surfcache_s
+{
+	struct surfcache_s	*next;
+	struct surfcache_s 	**owner;		// NULL is an empty chunk of memory
+	int					lightadj[MAXLIGHTMAPS]; // checked for strobe flush
+	int					dlight;
+	int					size;		// including header
+	unsigned			width;
+	unsigned			height;		// DEBUG only needed for debug
+	float				mipscale;
+	struct texture_s	*texture;	// checked for animating textures
+	byte				data[4];	// width*height elements
+} surfcache_t;
+
+
+typedef struct
+{
+	pixel_t		*surfdat;	// destination for generated surface
+	int			rowbytes;	// destination logical width in bytes
+	msurface_t	*surf;		// description for surface to generate
+	fixed8_t	lightadj[MAXLIGHTMAPS];
+							// adjust for lightmap levels for dynamic lighting
+	texture_t	*texture;	// corrected for animating textures
+	int			surfmip;	// mipmapped ratio of surface texels / world pixels
+	int			surfwidth;	// in mipmapped texels
+	int			surfheight;	// in mipmapped texels
+} drawsurf_t;
+
+
+typedef enum {
+	pt_static, pt_grav, pt_slowgrav, pt_fire, pt_explode, pt_explode2, pt_blob, pt_blob2
+} ptype_t;
+
+// !!! if this is changed, it must be changed in d_ifacea.h too !!!
+typedef struct particle_s
+{
+// driver-usable fields
+	vec3_t		org;
+	float		color;
+// drivers never touch the following fields
+	struct particle_s	*next;
+	vec3_t		vel;
+	float		ramp;
+	float		die;
+	ptype_t		type;
+} particle_t;
+
+
+//====================================================
+
+
+extern	entity_t	r_worldentity;
+extern	qboolean	r_cache_thrash;		// compatability
+extern	vec3_t		modelorg, r_entorigin;
+extern	entity_t	*currententity;
+extern	int			r_visframecount;	// ??? what difs?
+extern	int			r_framecount;
+extern	mplane_t	frustum[4];
+extern	int		c_brush_polys, c_alias_polys;
+
+
+//
+// view origin
+//
+extern	vec3_t	vup;
+extern	vec3_t	vpn;
+extern	vec3_t	vright;
+extern	vec3_t	r_origin;
+
+//
+// screen size info
+//
+extern	refdef_t	r_refdef;
+extern	mleaf_t		*r_viewleaf, *r_oldviewleaf;
+extern	texture_t	*r_notexture_mip;
+extern	int		d_lightstylevalue[256];	// 8.8 fraction of base light value
+
+extern	qboolean	envmap;
+extern	int	currenttexture;
+extern	int	cnttextures[2];
+extern	int	particletexture;
+extern	int	playertextures;
+
+extern	int	skytexturenum;		// index in cl.loadmodel, not gl texture object
+
+extern	cvar_t	r_norefresh;
+extern	cvar_t	r_drawentities;
+extern	cvar_t	r_drawworld;
+extern	cvar_t	r_drawviewmodel;
+extern	cvar_t	r_speeds;
+extern	cvar_t	r_waterwarp;
+extern	cvar_t	r_fullbright;
+extern	cvar_t	r_lightmap;
+extern	cvar_t	r_shadows;
+extern	cvar_t	r_mirroralpha;
+extern	cvar_t	r_wateralpha;
+extern	cvar_t	r_dynamic;
+extern	cvar_t	r_novis;
+
+extern	cvar_t	gl_clear;
+extern	cvar_t	gl_cull;
+extern	cvar_t	gl_poly;
+extern	cvar_t	gl_texsort;
+extern	cvar_t	gl_smoothmodels;
+extern	cvar_t	gl_affinemodels;
+extern	cvar_t	gl_polyblend;
+extern	cvar_t	gl_keeptjunctions;
+extern	cvar_t	gl_reporttjunctions;
+extern	cvar_t	gl_flashblend;
+extern	cvar_t	gl_nocolors;
+extern	cvar_t	gl_doubleeyes;
+
+extern	int		gl_lightmap_format;
+extern	int		gl_solid_format;
+extern	int		gl_alpha_format;
+
+extern	cvar_t	gl_max_size;
+extern	cvar_t	gl_playermip;
+
+extern	int			mirrortexturenum;	// quake texturenum, not gltexturenum
+extern	qboolean	mirror;
+extern	mplane_t	*mirror_plane;
+
+extern	float	r_world_matrix[16];
+
+extern	const char *gl_vendor;
+extern	const char *gl_renderer;
+extern	const char *gl_version;
+extern	const char *gl_extensions;
+
+void R_TranslatePlayerSkin (int playernum);
+void GL_Bind (int texnum);
+
+// Multitexture
+#define    TEXTURE0_SGIS				0x835E
+#define    TEXTURE1_SGIS				0x835F
+
+#ifndef _WIN32
+#define APIENTRY /* */
+#endif
+
+typedef void (APIENTRY *lpMTexFUNC) (GLenum, GLfloat, GLfloat);
+typedef void (APIENTRY *lpSelTexFUNC) (GLenum);
+extern lpMTexFUNC qglMTexCoord2fSGIS;
+extern lpSelTexFUNC qglSelectTextureSGIS;
+
+extern qboolean gl_mtexable;
+
+void GL_DisableMultitexture(void);
+void GL_EnableMultitexture(void);
--- /dev/null
+++ b/WinQuake/host.c
@@ -1,0 +1,958 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// host.c -- coordinates spawning and killing of local servers
+
+#include "quakedef.h"
+#include "r_local.h"
+
+/*
+
+A server can allways be started, even if the system started out as a client
+to a remote system.
+
+A client can NOT be started if the system started as a dedicated server.
+
+Memory is cleared / released when a server or client begins, not when they end.
+
+*/
+
+quakeparms_t host_parms;
+
+qboolean	host_initialized;		// true if into command execution
+
+double		host_frametime;
+double		host_time;
+double		realtime;				// without any filtering or bounding
+double		oldrealtime;			// last frame run
+int			host_framecount;
+
+int			host_hunklevel;
+
+int			minimum_memory;
+
+client_t	*host_client;			// current client
+
+jmp_buf 	host_abortserver;
+
+byte		*host_basepal;
+byte		*host_colormap;
+
+cvar_t	host_framerate = {"host_framerate","0"};	// set for slow motion
+cvar_t	host_speeds = {"host_speeds","0"};			// set for running times
+
+cvar_t	sys_ticrate = {"sys_ticrate","0.05"};
+cvar_t	serverprofile = {"serverprofile","0"};
+
+cvar_t	fraglimit = {"fraglimit","0",false,true};
+cvar_t	timelimit = {"timelimit","0",false,true};
+cvar_t	teamplay = {"teamplay","0",false,true};
+
+cvar_t	samelevel = {"samelevel","0"};
+cvar_t	noexit = {"noexit","0",false,true};
+
+#ifdef QUAKE2
+cvar_t	developer = {"developer","1"};	// should be 0 for release!
+#else
+cvar_t	developer = {"developer","0"};
+#endif
+
+cvar_t	skill = {"skill","1"};						// 0 - 3
+cvar_t	deathmatch = {"deathmatch","0"};			// 0, 1, or 2
+cvar_t	coop = {"coop","0"};			// 0 or 1
+
+cvar_t	pausable = {"pausable","1"};
+
+cvar_t	temp1 = {"temp1","0"};
+
+
+/*
+================
+Host_EndGame
+================
+*/
+void Host_EndGame (char *message, ...)
+{
+	va_list		argptr;
+	char		string[1024];
+	
+	va_start (argptr,message);
+	vsprintf (string,message,argptr);
+	va_end (argptr);
+	Con_DPrintf ("Host_EndGame: %s\n",string);
+	
+	if (sv.active)
+		Host_ShutdownServer (false);
+
+	if (cls.state == ca_dedicated)
+		Sys_Error ("Host_EndGame: %s\n",string);	// dedicated servers exit
+	
+	if (cls.demonum != -1)
+		CL_NextDemo ();
+	else
+		CL_Disconnect ();
+
+	longjmp (host_abortserver, 1);
+}
+
+/*
+================
+Host_Error
+
+This shuts down both the client and server
+================
+*/
+void Host_Error (char *error, ...)
+{
+	va_list		argptr;
+	char		string[1024];
+	static	qboolean inerror = false;
+	
+	if (inerror)
+		Sys_Error ("Host_Error: recursively entered");
+	inerror = true;
+	
+	SCR_EndLoadingPlaque ();		// reenable screen updates
+
+	va_start (argptr,error);
+	vsprintf (string,error,argptr);
+	va_end (argptr);
+	Con_Printf ("Host_Error: %s\n",string);
+	
+	if (sv.active)
+		Host_ShutdownServer (false);
+
+	if (cls.state == ca_dedicated)
+		Sys_Error ("Host_Error: %s\n",string);	// dedicated servers exit
+
+	CL_Disconnect ();
+	cls.demonum = -1;
+
+	inerror = false;
+
+	longjmp (host_abortserver, 1);
+}
+
+/*
+================
+Host_FindMaxClients
+================
+*/
+void	Host_FindMaxClients (void)
+{
+	int		i;
+
+	svs.maxclients = 1;
+		
+	i = COM_CheckParm ("-dedicated");
+	if (i)
+	{
+		cls.state = ca_dedicated;
+		if (i != (com_argc - 1))
+		{
+			svs.maxclients = Q_atoi (com_argv[i+1]);
+		}
+		else
+			svs.maxclients = 8;
+	}
+	else
+		cls.state = ca_disconnected;
+
+	i = COM_CheckParm ("-listen");
+	if (i)
+	{
+		if (cls.state == ca_dedicated)
+			Sys_Error ("Only one of -dedicated or -listen can be specified");
+		if (i != (com_argc - 1))
+			svs.maxclients = Q_atoi (com_argv[i+1]);
+		else
+			svs.maxclients = 8;
+	}
+	if (svs.maxclients < 1)
+		svs.maxclients = 8;
+	else if (svs.maxclients > MAX_SCOREBOARD)
+		svs.maxclients = MAX_SCOREBOARD;
+
+	svs.maxclientslimit = svs.maxclients;
+	if (svs.maxclientslimit < 4)
+		svs.maxclientslimit = 4;
+	svs.clients = Hunk_AllocName (svs.maxclientslimit*sizeof(client_t), "clients");
+
+	if (svs.maxclients > 1)
+		Cvar_SetValue ("deathmatch", 1.0);
+	else
+		Cvar_SetValue ("deathmatch", 0.0);
+}
+
+
+/*
+=======================
+Host_InitLocal
+======================
+*/
+void Host_InitLocal (void)
+{
+	Host_InitCommands ();
+	
+	Cvar_RegisterVariable (&host_framerate);
+	Cvar_RegisterVariable (&host_speeds);
+
+	Cvar_RegisterVariable (&sys_ticrate);
+	Cvar_RegisterVariable (&serverprofile);
+
+	Cvar_RegisterVariable (&fraglimit);
+	Cvar_RegisterVariable (&timelimit);
+	Cvar_RegisterVariable (&teamplay);
+	Cvar_RegisterVariable (&samelevel);
+	Cvar_RegisterVariable (&noexit);
+	Cvar_RegisterVariable (&skill);
+	Cvar_RegisterVariable (&developer);
+	Cvar_RegisterVariable (&deathmatch);
+	Cvar_RegisterVariable (&coop);
+
+	Cvar_RegisterVariable (&pausable);
+
+	Cvar_RegisterVariable (&temp1);
+
+	Host_FindMaxClients ();
+	
+	host_time = 1.0;		// so a think at time 0 won't get called
+}
+
+
+/*
+===============
+Host_WriteConfiguration
+
+Writes key bindings and archived cvars to config.cfg
+===============
+*/
+void Host_WriteConfiguration (void)
+{
+	FILE	*f;
+
+// dedicated servers initialize the host but don't parse and set the
+// config.cfg cvars
+	if (host_initialized & !isDedicated)
+	{
+		f = fopen (va("%s/config.cfg",com_gamedir), "w");
+		if (!f)
+		{
+			Con_Printf ("Couldn't write config.cfg.\n");
+			return;
+		}
+		
+		Key_WriteBindings (f);
+		Cvar_WriteVariables (f);
+
+		fclose (f);
+	}
+}
+
+
+/*
+=================
+SV_ClientPrintf
+
+Sends text across to be displayed 
+FIXME: make this just a stuffed echo?
+=================
+*/
+void SV_ClientPrintf (char *fmt, ...)
+{
+	va_list		argptr;
+	char		string[1024];
+	
+	va_start (argptr,fmt);
+	vsprintf (string, fmt,argptr);
+	va_end (argptr);
+	
+	MSG_WriteByte (&host_client->message, svc_print);
+	MSG_WriteString (&host_client->message, string);
+}
+
+/*
+=================
+SV_BroadcastPrintf
+
+Sends text to all active clients
+=================
+*/
+void SV_BroadcastPrintf (char *fmt, ...)
+{
+	va_list		argptr;
+	char		string[1024];
+	int			i;
+	
+	va_start (argptr,fmt);
+	vsprintf (string, fmt,argptr);
+	va_end (argptr);
+	
+	for (i=0 ; i<svs.maxclients ; i++)
+		if (svs.clients[i].active && svs.clients[i].spawned)
+		{
+			MSG_WriteByte (&svs.clients[i].message, svc_print);
+			MSG_WriteString (&svs.clients[i].message, string);
+		}
+}
+
+/*
+=================
+Host_ClientCommands
+
+Send text over to the client to be executed
+=================
+*/
+void Host_ClientCommands (char *fmt, ...)
+{
+	va_list		argptr;
+	char		string[1024];
+	
+	va_start (argptr,fmt);
+	vsprintf (string, fmt,argptr);
+	va_end (argptr);
+	
+	MSG_WriteByte (&host_client->message, svc_stufftext);
+	MSG_WriteString (&host_client->message, string);
+}
+
+/*
+=====================
+SV_DropClient
+
+Called when the player is getting totally kicked off the host
+if (crash = true), don't bother sending signofs
+=====================
+*/
+void SV_DropClient (qboolean crash)
+{
+	int		saveSelf;
+	int		i;
+	client_t *client;
+
+	if (!crash)
+	{
+		// send any final messages (don't check for errors)
+		if (NET_CanSendMessage (host_client->netconnection))
+		{
+			MSG_WriteByte (&host_client->message, svc_disconnect);
+			NET_SendMessage (host_client->netconnection, &host_client->message);
+		}
+	
+		if (host_client->edict && host_client->spawned)
+		{
+		// call the prog function for removing a client
+		// this will set the body to a dead frame, among other things
+			saveSelf = pr_global_struct->self;
+			pr_global_struct->self = EDICT_TO_PROG(host_client->edict);
+			PR_ExecuteProgram (pr_global_struct->ClientDisconnect);
+			pr_global_struct->self = saveSelf;
+		}
+
+		Sys_Printf ("Client %s removed\n",host_client->name);
+	}
+
+// break the net connection
+	NET_Close (host_client->netconnection);
+	host_client->netconnection = NULL;
+
+// free the client (the body stays around)
+	host_client->active = false;
+	host_client->name[0] = 0;
+	host_client->old_frags = -999999;
+	net_activeconnections--;
+
+// send notification to all clients
+	for (i=0, client = svs.clients ; i<svs.maxclients ; i++, client++)
+	{
+		if (!client->active)
+			continue;
+		MSG_WriteByte (&client->message, svc_updatename);
+		MSG_WriteByte (&client->message, host_client - svs.clients);
+		MSG_WriteString (&client->message, "");
+		MSG_WriteByte (&client->message, svc_updatefrags);
+		MSG_WriteByte (&client->message, host_client - svs.clients);
+		MSG_WriteShort (&client->message, 0);
+		MSG_WriteByte (&client->message, svc_updatecolors);
+		MSG_WriteByte (&client->message, host_client - svs.clients);
+		MSG_WriteByte (&client->message, 0);
+	}
+}
+
+/*
+==================
+Host_ShutdownServer
+
+This only happens at the end of a game, not between levels
+==================
+*/
+void Host_ShutdownServer(qboolean crash)
+{
+	int		i;
+	int		count;
+	sizebuf_t	buf;
+	char		message[4];
+	double	start;
+
+	if (!sv.active)
+		return;
+
+	sv.active = false;
+
+// stop all client sounds immediately
+	if (cls.state == ca_connected)
+		CL_Disconnect ();
+
+// flush any pending messages - like the score!!!
+	start = Sys_FloatTime();
+	do
+	{
+		count = 0;
+		for (i=0, host_client = svs.clients ; i<svs.maxclients ; i++, host_client++)
+		{
+			if (host_client->active && host_client->message.cursize)
+			{
+				if (NET_CanSendMessage (host_client->netconnection))
+				{
+					NET_SendMessage(host_client->netconnection, &host_client->message);
+					SZ_Clear (&host_client->message);
+				}
+				else
+				{
+					NET_GetMessage(host_client->netconnection);
+					count++;
+				}
+			}
+		}
+		if ((Sys_FloatTime() - start) > 3.0)
+			break;
+	}
+	while (count);
+
+// make sure all the clients know we're disconnecting
+	buf.data = message;
+	buf.maxsize = 4;
+	buf.cursize = 0;
+	MSG_WriteByte(&buf, svc_disconnect);
+	count = NET_SendToAll(&buf, 5);
+	if (count)
+		Con_Printf("Host_ShutdownServer: NET_SendToAll failed for %u clients\n", count);
+
+	for (i=0, host_client = svs.clients ; i<svs.maxclients ; i++, host_client++)
+		if (host_client->active)
+			SV_DropClient(crash);
+
+//
+// clear structures
+//
+	memset (&sv, 0, sizeof(sv));
+	memset (svs.clients, 0, svs.maxclientslimit*sizeof(client_t));
+}
+
+
+/*
+================
+Host_ClearMemory
+
+This clears all the memory used by both the client and server, but does
+not reinitialize anything.
+================
+*/
+void Host_ClearMemory (void)
+{
+	Con_DPrintf ("Clearing memory\n");
+	D_FlushCaches ();
+	Mod_ClearAll ();
+	if (host_hunklevel)
+		Hunk_FreeToLowMark (host_hunklevel);
+
+	cls.signon = 0;
+	memset (&sv, 0, sizeof(sv));
+	memset (&cl, 0, sizeof(cl));
+}
+
+
+//============================================================================
+
+
+/*
+===================
+Host_FilterTime
+
+Returns false if the time is too short to run a frame
+===================
+*/
+qboolean Host_FilterTime (float time)
+{
+	realtime += time;
+
+	if (!cls.timedemo && realtime - oldrealtime < 1.0/72.0)
+		return false;		// framerate is too high
+
+	host_frametime = realtime - oldrealtime;
+	oldrealtime = realtime;
+
+	if (host_framerate.value > 0)
+		host_frametime = host_framerate.value;
+	else
+	{	// don't allow really long or short frames
+		if (host_frametime > 0.1)
+			host_frametime = 0.1;
+		if (host_frametime < 0.001)
+			host_frametime = 0.001;
+	}
+	
+	return true;
+}
+
+
+/*
+===================
+Host_GetConsoleCommands
+
+Add them exactly as if they had been typed at the console
+===================
+*/
+void Host_GetConsoleCommands (void)
+{
+	char	*cmd;
+
+	while (1)
+	{
+		cmd = Sys_ConsoleInput ();
+		if (!cmd)
+			break;
+		Cbuf_AddText (cmd);
+	}
+}
+
+
+/*
+==================
+Host_ServerFrame
+
+==================
+*/
+#ifdef FPS_20
+
+void _Host_ServerFrame (void)
+{
+// run the world state	
+	pr_global_struct->frametime = host_frametime;
+
+// read client messages
+	SV_RunClients ();
+	
+// move things around and think
+// always pause in single player if in console or menus
+	if (!sv.paused && (svs.maxclients > 1 || key_dest == key_game) )
+		SV_Physics ();
+}
+
+void Host_ServerFrame (void)
+{
+	float	save_host_frametime;
+	float	temp_host_frametime;
+
+// run the world state	
+	pr_global_struct->frametime = host_frametime;
+
+// set the time and clear the general datagram
+	SV_ClearDatagram ();
+	
+// check for new clients
+	SV_CheckForNewClients ();
+
+	temp_host_frametime = save_host_frametime = host_frametime;
+	while(temp_host_frametime > (1.0/72.0))
+	{
+		if (temp_host_frametime > 0.05)
+			host_frametime = 0.05;
+		else
+			host_frametime = temp_host_frametime;
+		temp_host_frametime -= host_frametime;
+		_Host_ServerFrame ();
+	}
+	host_frametime = save_host_frametime;
+
+// send all messages to the clients
+	SV_SendClientMessages ();
+}
+
+#else
+
+void Host_ServerFrame (void)
+{
+// run the world state	
+	pr_global_struct->frametime = host_frametime;
+
+// set the time and clear the general datagram
+	SV_ClearDatagram ();
+	
+// check for new clients
+	SV_CheckForNewClients ();
+
+// read client messages
+	SV_RunClients ();
+	
+// move things around and think
+// always pause in single player if in console or menus
+	if (!sv.paused && (svs.maxclients > 1 || key_dest == key_game) )
+		SV_Physics ();
+
+// send all messages to the clients
+	SV_SendClientMessages ();
+}
+
+#endif
+
+
+/*
+==================
+Host_Frame
+
+Runs all active servers
+==================
+*/
+void _Host_Frame (float time)
+{
+	static double		time1 = 0;
+	static double		time2 = 0;
+	static double		time3 = 0;
+	int			pass1, pass2, pass3;
+
+	if (setjmp (host_abortserver) )
+		return;			// something bad happened, or the server disconnected
+
+// keep the random time dependent
+	rand ();
+	
+// decide the simulation time
+	if (!Host_FilterTime (time))
+		return;			// don't run too fast, or packets will flood out
+		
+// get new key events
+	Sys_SendKeyEvents ();
+
+// allow mice or other external controllers to add commands
+	IN_Commands ();
+
+// process console commands
+	Cbuf_Execute ();
+
+	NET_Poll();
+
+// if running the server locally, make intentions now
+	if (sv.active)
+		CL_SendCmd ();
+	
+//-------------------
+//
+// server operations
+//
+//-------------------
+
+// check for commands typed to the host
+	Host_GetConsoleCommands ();
+	
+	if (sv.active)
+		Host_ServerFrame ();
+
+//-------------------
+//
+// client operations
+//
+//-------------------
+
+// if running the server remotely, send intentions now after
+// the incoming messages have been read
+	if (!sv.active)
+		CL_SendCmd ();
+
+	host_time += host_frametime;
+
+// fetch results from server
+	if (cls.state == ca_connected)
+	{
+		CL_ReadFromServer ();
+	}
+
+// update video
+	if (host_speeds.value)
+		time1 = Sys_FloatTime ();
+		
+	SCR_UpdateScreen ();
+
+	if (host_speeds.value)
+		time2 = Sys_FloatTime ();
+		
+// update audio
+	if (cls.signon == SIGNONS)
+	{
+		S_Update (r_origin, vpn, vright, vup);
+		CL_DecayLights ();
+	}
+	else
+		S_Update (vec3_origin, vec3_origin, vec3_origin, vec3_origin);
+	
+	CDAudio_Update();
+
+	if (host_speeds.value)
+	{
+		pass1 = (time1 - time3)*1000;
+		time3 = Sys_FloatTime ();
+		pass2 = (time2 - time1)*1000;
+		pass3 = (time3 - time2)*1000;
+		Con_Printf ("%3i tot %3i server %3i gfx %3i snd\n",
+					pass1+pass2+pass3, pass1, pass2, pass3);
+	}
+	
+	host_framecount++;
+}
+
+void Host_Frame (float time)
+{
+	double	time1, time2;
+	static double	timetotal;
+	static int		timecount;
+	int		i, c, m;
+
+	if (!serverprofile.value)
+	{
+		_Host_Frame (time);
+		return;
+	}
+	
+	time1 = Sys_FloatTime ();
+	_Host_Frame (time);
+	time2 = Sys_FloatTime ();	
+	
+	timetotal += time2 - time1;
+	timecount++;
+	
+	if (timecount < 1000)
+		return;
+
+	m = timetotal*1000/timecount;
+	timecount = 0;
+	timetotal = 0;
+	c = 0;
+	for (i=0 ; i<svs.maxclients ; i++)
+	{
+		if (svs.clients[i].active)
+			c++;
+	}
+
+	Con_Printf ("serverprofile: %2i clients %2i msec\n",  c,  m);
+}
+
+//============================================================================
+
+
+extern int vcrFile;
+#define	VCR_SIGNATURE	0x56435231
+// "VCR1"
+
+void Host_InitVCR (quakeparms_t *parms)
+{
+	int		i, len, n;
+	char	*p;
+	
+	if (COM_CheckParm("-playback"))
+	{
+		if (com_argc != 2)
+			Sys_Error("No other parameters allowed with -playback\n");
+
+		Sys_FileOpenRead("quake.vcr", &vcrFile);
+		if (vcrFile == -1)
+			Sys_Error("playback file not found\n");
+
+		Sys_FileRead (vcrFile, &i, sizeof(int));
+		if (i != VCR_SIGNATURE)
+			Sys_Error("Invalid signature in vcr file\n");
+
+		Sys_FileRead (vcrFile, &com_argc, sizeof(int));
+		com_argv = malloc(com_argc * sizeof(char *));
+		com_argv[0] = parms->argv[0];
+		for (i = 0; i < com_argc; i++)
+		{
+			Sys_FileRead (vcrFile, &len, sizeof(int));
+			p = malloc(len);
+			Sys_FileRead (vcrFile, p, len);
+			com_argv[i+1] = p;
+		}
+		com_argc++; /* add one for arg[0] */
+		parms->argc = com_argc;
+		parms->argv = com_argv;
+	}
+
+	if ( (n = COM_CheckParm("-record")) != 0)
+	{
+		vcrFile = Sys_FileOpenWrite("quake.vcr");
+
+		i = VCR_SIGNATURE;
+		Sys_FileWrite(vcrFile, &i, sizeof(int));
+		i = com_argc - 1;
+		Sys_FileWrite(vcrFile, &i, sizeof(int));
+		for (i = 1; i < com_argc; i++)
+		{
+			if (i == n)
+			{
+				len = 10;
+				Sys_FileWrite(vcrFile, &len, sizeof(int));
+				Sys_FileWrite(vcrFile, "-playback", len);
+				continue;
+			}
+			len = Q_strlen(com_argv[i]) + 1;
+			Sys_FileWrite(vcrFile, &len, sizeof(int));
+			Sys_FileWrite(vcrFile, com_argv[i], len);
+		}
+	}
+	
+}
+
+/*
+====================
+Host_Init
+====================
+*/
+void Host_Init (quakeparms_t *parms)
+{
+
+	if (standard_quake)
+		minimum_memory = MINIMUM_MEMORY;
+	else
+		minimum_memory = MINIMUM_MEMORY_LEVELPAK;
+
+	if (COM_CheckParm ("-minmemory"))
+		parms->memsize = minimum_memory;
+
+	host_parms = *parms;
+
+	if (parms->memsize < minimum_memory)
+		Sys_Error ("Only %4.1f megs of memory available, can't execute game", parms->memsize / (float)0x100000);
+
+	com_argc = parms->argc;
+	com_argv = parms->argv;
+
+	Memory_Init (parms->membase, parms->memsize);
+	Cbuf_Init ();
+	Cmd_Init ();	
+	V_Init ();
+	Chase_Init ();
+	Host_InitVCR (parms);
+	COM_Init (parms->basedir);
+	Host_InitLocal ();
+	W_LoadWadFile ("gfx.wad");
+	Key_Init ();
+	Con_Init ();	
+	M_Init ();	
+	PR_Init ();
+	Mod_Init ();
+	NET_Init ();
+	SV_Init ();
+
+	Con_Printf ("Exe: "__TIME__" "__DATE__"\n");
+	Con_Printf ("%4.1f megabyte heap\n",parms->memsize/ (1024*1024.0));
+	
+	R_InitTextures ();		// needed even for dedicated servers
+ 
+	if (cls.state != ca_dedicated)
+	{
+		host_basepal = (byte *)COM_LoadHunkFile ("gfx/palette.lmp");
+		if (!host_basepal)
+			Sys_Error ("Couldn't load gfx/palette.lmp");
+		host_colormap = (byte *)COM_LoadHunkFile ("gfx/colormap.lmp");
+		if (!host_colormap)
+			Sys_Error ("Couldn't load gfx/colormap.lmp");
+
+#ifndef _WIN32 // on non win32, mouse comes before video for security reasons
+		IN_Init ();
+#endif
+		VID_Init (host_basepal);
+
+		Draw_Init ();
+		SCR_Init ();
+		R_Init ();
+#ifndef	_WIN32
+	// on Win32, sound initialization has to come before video initialization, so we
+	// can put up a popup if the sound hardware is in use
+		S_Init ();
+#else
+
+#ifdef	GLQUAKE
+	// FIXME: doesn't use the new one-window approach yet
+		S_Init ();
+#endif
+
+#endif	// _WIN32
+		CDAudio_Init ();
+		Sbar_Init ();
+		CL_Init ();
+#ifdef _WIN32 // on non win32, mouse comes before video for security reasons
+		IN_Init ();
+#endif
+	}
+
+	Cbuf_InsertText ("exec quake.rc\n");
+
+	Hunk_AllocName (0, "-HOST_HUNKLEVEL-");
+	host_hunklevel = Hunk_LowMark ();
+
+	host_initialized = true;
+	
+	Sys_Printf ("========Quake Initialized=========\n");	
+}
+
+
+/*
+===============
+Host_Shutdown
+
+FIXME: this is a callback from Sys_Quit and Sys_Error.  It would be better
+to run quit through here before the final handoff to the sys code.
+===============
+*/
+void Host_Shutdown(void)
+{
+	static qboolean isdown = false;
+	
+	if (isdown)
+	{
+		printf ("recursive shutdown\n");
+		return;
+	}
+	isdown = true;
+
+// keep Con_Printf from trying to update the screen
+	scr_disabled_for_loading = true;
+
+	Host_WriteConfiguration (); 
+
+	CDAudio_Shutdown ();
+	NET_Shutdown ();
+	S_Shutdown();
+	IN_Shutdown ();
+
+	if (cls.state != ca_dedicated)
+	{
+		VID_Shutdown();
+	}
+}
+
--- /dev/null
+++ b/WinQuake/in_dos.c
@@ -1,0 +1,615 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// in_mouse.c -- dos mouse code
+
+#include "quakedef.h"
+#include "dosisms.h"
+
+#define AUX_FLAG_FREELOOK	0x00000001
+
+typedef struct
+{
+	long    interruptVector;
+	char    deviceName[16];
+	long    numAxes;
+	long	numButtons;
+	long	flags;
+	
+	vec3_t  viewangles;
+
+// intended velocities
+	float   forwardmove;
+	float   sidemove;
+	float   upmove;
+
+	long	buttons;
+} externControl_t;
+
+/*
+#define AUX_FLAG_FORCEFREELOOK	0x00000001	// r/o
+#define AUX_FLAG_EXTENDED		0x00000002	// r/o
+#define AUX_FLAG_RUN			0x00000004	// w/o
+#define AUX_FLAG_STRAFE			0x00000008	// w/o
+#define AUX_FLAG_FREELOOK		0x00000010	// w/o
+
+#define AUX_MAP_UNDEFINED	0
+#define AUX_MAP_PITCH		1
+#define AUX_MAP_YAW			2
+#define AUX_MAP_ROLL		3
+#define AUX_MAP_FORWARD		4
+#define AUX_MAP_SIDE		5
+#define AUX_MAP_UP			6
+
+typedef struct
+{
+	long    interruptVector;
+	// r/o
+	char    deviceName[16];
+	// r/o
+	long    numAxes;
+			// r/o	1-6
+	long	numButtons;			// r/o	0-32
+	long	flags;				// see above
+	byte	axisMapping[6];		// w/o	default = p,y,r,f,s,u
+	float	axisValue[6];		// r/w
+	float	sensitivity[6];		// w/o	default = 1.0
+	long	buttons;			// r/o
+	float	last_frame_time;	// w/o
+} externControl_t;
+*/
+
+cvar_t	m_filter = {"m_filter","1"};
+
+qboolean	mouse_avail;
+int		mouse_buttons;
+int		mouse_oldbuttonstate;
+int		mouse_buttonstate;
+float	mouse_x, mouse_y;
+float	old_mouse_x, old_mouse_y;
+
+
+cvar_t	in_joystick = {"joystick","1"};
+cvar_t	joy_numbuttons = {"joybuttons","4", true};
+
+qboolean	joy_avail;
+int		joy_oldbuttonstate;
+int		joy_buttonstate;
+
+int     joyxl, joyxh, joyyl, joyyh; 
+int		joystickx, joysticky;
+
+qboolean		need_center;
+
+qboolean		extern_avail;
+int				extern_buttons;
+int				extern_oldbuttonstate;
+int				extern_buttonstate;
+cvar_t	aux_look = {"auxlook","1", true};
+externControl_t	*extern_control;
+void IN_StartupExternal (void);
+void IN_ExternalMove (usercmd_t *cmd);
+
+void IN_StartupJoystick (void);
+qboolean IN_ReadJoystick (void);
+
+
+void Toggle_AuxLook_f (void)
+{
+	if (aux_look.value)
+		Cvar_Set ("auxlook","0");
+	else
+		Cvar_Set ("auxlook","1");
+}
+
+
+void Force_CenterView_f (void)
+{
+	cl.viewangles[PITCH] = 0;
+}
+
+
+/*
+===========
+IN_StartupMouse
+===========
+*/
+void IN_StartupMouse (void)
+{
+	if ( COM_CheckParm ("-nomouse") ) 
+		return; 
+ 
+// check for mouse
+	regs.x.ax = 0;
+	dos_int86(0x33);
+	mouse_avail = regs.x.ax;
+	if (!mouse_avail)
+	{
+		Con_Printf ("No mouse found\n");
+		return;
+	}
+	
+	mouse_buttons = regs.x.bx;
+	if (mouse_buttons > 3)
+		mouse_buttons = 3;
+	Con_Printf("%d-button mouse available\n", mouse_buttons);
+}
+
+/*
+===========
+IN_Init
+===========
+*/
+void IN_Init (void)
+{
+	int i;
+
+	Cvar_RegisterVariable (&m_filter);
+	Cvar_RegisterVariable (&in_joystick);
+	Cvar_RegisterVariable (&joy_numbuttons);
+	Cvar_RegisterVariable (&aux_look);
+	Cmd_AddCommand ("toggle_auxlook", Toggle_AuxLook_f);
+	Cmd_AddCommand ("force_centerview", Force_CenterView_f);
+
+	IN_StartupMouse ();
+	IN_StartupJoystick ();
+
+	i = COM_CheckParm ("-control");
+	if (i)
+	{
+		extern_control = real2ptr(Q_atoi (com_argv[i+1]));
+		IN_StartupExternal ();
+	}
+}
+
+/*
+===========
+IN_Shutdown
+===========
+*/
+void IN_Shutdown (void)
+{
+
+}
+
+
+/*
+===========
+IN_Commands
+===========
+*/
+void IN_Commands (void)
+{
+	int		i;
+
+	if (mouse_avail)
+	{
+		regs.x.ax = 3;		// read buttons
+		dos_int86(0x33);
+		mouse_buttonstate = regs.x.bx;
+	
+	// perform button actions
+		for (i=0 ; i<mouse_buttons ; i++)
+		{
+			if ( (mouse_buttonstate & (1<<i)) &&
+			!(mouse_oldbuttonstate & (1<<i)) )
+			{
+				Key_Event (K_MOUSE1 + i, true);
+			}
+			if ( !(mouse_buttonstate & (1<<i)) &&
+			(mouse_oldbuttonstate & (1<<i)) )
+			{
+				Key_Event (K_MOUSE1 + i, false);
+			}
+		}	
+		
+		mouse_oldbuttonstate = mouse_buttonstate;
+	}
+	
+	if (joy_avail)
+	{
+		joy_buttonstate = ((dos_inportb(0x201) >> 4)&15)^15;
+	// perform button actions
+		for (i=0 ; i<joy_numbuttons.value ; i++)
+		{
+			if ( (joy_buttonstate & (1<<i)) &&
+			!(joy_oldbuttonstate & (1<<i)) )
+			{
+				Key_Event (K_JOY1 + i, true);
+			}
+			if ( !(joy_buttonstate & (1<<i)) &&
+			(joy_oldbuttonstate & (1<<i)) )
+			{
+				Key_Event (K_JOY1 + i, false);
+			}
+		}
+		
+		joy_oldbuttonstate = joy_buttonstate;
+	}
+
+	if (extern_avail)
+	{
+		extern_buttonstate = extern_control->buttons;
+	
+	// perform button actions
+		for (i=0 ; i<extern_buttons ; i++)
+		{
+			if ( (extern_buttonstate & (1<<i)) &&
+			!(extern_oldbuttonstate & (1<<i)) )
+			{
+				Key_Event (K_AUX1 + i, true);
+			}
+			if ( !(extern_buttonstate & (1<<i)) &&
+			(extern_oldbuttonstate & (1<<i)) )
+			{
+				Key_Event (K_AUX1 + i, false);
+			}
+		}	
+		
+		extern_oldbuttonstate = extern_buttonstate;
+	}
+	
+}
+
+
+/*
+===========
+IN_Move
+===========
+*/
+void IN_MouseMove (usercmd_t *cmd)
+{
+	int		mx, my;
+
+	if (!mouse_avail)
+		return;
+
+	regs.x.ax = 11;		// read move
+	dos_int86(0x33);
+	mx = (short)regs.x.cx;
+	my = (short)regs.x.dx;
+	
+	if (m_filter.value)
+	{
+		mouse_x = (mx + old_mouse_x) * 0.5;
+		mouse_y = (my + old_mouse_y) * 0.5;
+	}
+	else
+	{
+		mouse_x = mx;
+		mouse_y = my;
+	}
+	old_mouse_x = mx;
+	old_mouse_y = my;
+
+	mouse_x *= sensitivity.value;
+	mouse_y *= sensitivity.value;
+
+// add mouse X/Y movement to cmd
+	if ( (in_strafe.state & 1) || (lookstrafe.value && (in_mlook.state & 1) ))
+		cmd->sidemove += m_side.value * mouse_x;
+	else
+		cl.viewangles[YAW] -= m_yaw.value * mouse_x;
+	
+	if (in_mlook.state & 1)
+		V_StopPitchDrift ();
+		
+	if ( (in_mlook.state & 1) && !(in_strafe.state & 1))
+	{
+		cl.viewangles[PITCH] += m_pitch.value * mouse_y;
+		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 * mouse_y;
+		else
+			cmd->forwardmove -= m_forward.value * mouse_y;
+	}
+}
+
+/*
+===========
+IN_JoyMove
+===========
+*/
+void IN_JoyMove (usercmd_t *cmd)
+{
+	float	speed, aspeed;
+
+	if (!joy_avail || !in_joystick.value) 
+		return; 
+ 
+	IN_ReadJoystick (); 
+	if (joysticky > joyyh*2 || joystickx > joyxh*2)
+		return;		// assume something jumped in and messed up the joystick
+					// reading time (win 95)
+
+	if (in_speed.state & 1)
+		speed = cl_movespeedkey.value;
+	else
+		speed = 1;
+	aspeed = speed*host_frametime;
+
+	if (in_strafe.state & 1)
+	{
+		if (joystickx < joyxl)
+			cmd->sidemove -= speed*cl_sidespeed.value; 
+		else if (joystickx > joyxh) 
+			cmd->sidemove += speed*cl_sidespeed.value; 
+	}
+	else
+	{
+		if (joystickx < joyxl)
+			cl.viewangles[YAW] += aspeed*cl_yawspeed.value;
+		else if (joystickx > joyxh) 
+			cl.viewangles[YAW] -= aspeed*cl_yawspeed.value;
+		cl.viewangles[YAW] = anglemod(cl.viewangles[YAW]);
+	}
+
+	if (in_mlook.state & 1)
+	{
+		if (m_pitch.value < 0)
+			speed *= -1;
+		
+		if (joysticky < joyyl) 
+			cl.viewangles[PITCH] += aspeed*cl_pitchspeed.value;
+		else if (joysticky > joyyh) 
+			cl.viewangles[PITCH] -= aspeed*cl_pitchspeed.value;
+	}
+	else
+	{
+		if (joysticky < joyyl) 
+			cmd->forwardmove += speed*cl_forwardspeed.value; 
+		else if (joysticky > joyyh) 
+			cmd->forwardmove -= speed*cl_backspeed.value;  
+	}
+}
+
+/*
+===========
+IN_Move
+===========
+*/
+void IN_Move (usercmd_t *cmd)
+{
+	IN_MouseMove (cmd);
+	IN_JoyMove (cmd);
+	IN_ExternalMove (cmd);
+}
+
+/* 
+============================================================================ 
+ 
+					JOYSTICK 
+ 
+============================================================================ 
+*/
+
+
+
+qboolean IN_ReadJoystick (void)
+{
+	int		b;
+	int		count;
+
+	joystickx = 0;
+	joysticky = 0;
+
+	count = 0;
+
+	b = dos_inportb(0x201);
+	dos_outportb(0x201, b);
+
+// clear counters
+	while (++count < 10000)
+	{
+		b = dos_inportb(0x201);
+
+		joystickx += b&1;
+		joysticky += (b&2)>>1;
+		if ( !(b&3) )
+			return true;
+	}
+	
+	Con_Printf ("IN_ReadJoystick: no response\n");
+	joy_avail = false;
+	return false;
+}
+
+/*
+=============
+WaitJoyButton
+=============
+*/
+qboolean WaitJoyButton (void) 
+{ 
+	int             oldbuttons, buttons; 
+ 
+	oldbuttons = 0; 
+	do 
+	{
+		key_count = -1;
+		Sys_SendKeyEvents ();
+		key_count = 0;
+		if (key_lastpress == K_ESCAPE)
+		{
+			Con_Printf ("aborted.\n");
+			return false;
+		}
+		key_lastpress = 0;
+		SCR_UpdateScreen ();
+		buttons =  ((dos_inportb(0x201) >> 4)&1)^1; 
+		if (buttons != oldbuttons) 
+		{ 
+			oldbuttons = buttons; 
+			continue; 
+		}
+	} while ( !buttons); 
+ 
+	do 
+	{ 
+		key_count = -1;
+		Sys_SendKeyEvents ();
+		key_count = 0;
+		if (key_lastpress == K_ESCAPE)
+		{
+			Con_Printf ("aborted.\n");
+			return false;
+		}
+		key_lastpress = 0;
+		SCR_UpdateScreen ();
+		buttons =  ((dos_inportb(0x201) >> 4)&1)^1; 
+		if (buttons != oldbuttons) 
+		{ 
+			oldbuttons = buttons; 
+			continue; 
+		} 
+	} while ( buttons); 
+ 
+	return true; 
+} 
+ 
+ 
+ 
+/* 
+=============== 
+IN_StartupJoystick 
+=============== 
+*/  
+void IN_StartupJoystick (void) 
+{ 
+	int     centerx, centery; 
+ 
+ 	Con_Printf ("\n");
+
+	joy_avail = false; 
+	if ( COM_CheckParm ("-nojoy") ) 
+		return; 
+ 
+	if (!IN_ReadJoystick ()) 
+	{ 
+		joy_avail = false; 
+		Con_Printf ("joystick not found\n"); 
+		return; 
+	} 
+
+	Con_Printf ("joystick found\n"); 
+ 
+	Con_Printf ("CENTER the joystick\nand press button 1 (ESC to skip):\n"); 
+	if (!WaitJoyButton ()) 
+		return; 
+	IN_ReadJoystick (); 
+	centerx = joystickx; 
+	centery = joysticky; 
+ 
+	Con_Printf ("Push the joystick to the UPPER LEFT\nand press button 1 (ESC to skip):\n"); 
+	if (!WaitJoyButton ()) 
+		return; 
+	IN_ReadJoystick (); 
+	joyxl = (centerx + joystickx)/2; 
+	joyyl = (centerx + joysticky)/2; 
+ 
+	Con_Printf ("Push the joystick to the LOWER RIGHT\nand press button 1 (ESC to skip):\n"); 
+	if (!WaitJoyButton ()) 
+		return; 
+	IN_ReadJoystick (); 
+	joyxh = (centerx + joystickx)/2; 
+	joyyh = (centery + joysticky)/2; 
+
+	joy_avail = true; 
+	Con_Printf ("joystick configured.\n"); 
+
+ 	Con_Printf ("\n");
+} 
+ 
+ 
+/* 
+============================================================================ 
+ 
+					EXTERNAL 
+ 
+============================================================================ 
+*/
+
+
+/* 
+=============== 
+IN_StartupExternal 
+=============== 
+*/  
+void IN_StartupExternal (void) 
+{ 
+	if (extern_control->numButtons > 32)
+		extern_control->numButtons = 32;
+
+	Con_Printf("%s Initialized\n", extern_control->deviceName);
+	Con_Printf("  %u axes  %u buttons\n", extern_control->numAxes, extern_control->numButtons);
+
+	extern_avail = true;
+	extern_buttons = extern_control->numButtons;
+}
+
+
+/*
+===========
+IN_ExternalMove
+===========
+*/
+void IN_ExternalMove (usercmd_t *cmd)
+{
+	qboolean freelook;
+
+	if (! extern_avail)
+		return;
+
+	extern_control->viewangles[YAW] = cl.viewangles[YAW];
+	extern_control->viewangles[PITCH] = cl.viewangles[PITCH];
+	extern_control->viewangles[ROLL] = cl.viewangles[ROLL];
+	extern_control->forwardmove = cmd->forwardmove;
+	extern_control->sidemove = cmd->sidemove;
+	extern_control->upmove = cmd->upmove;
+
+Con_DPrintf("IN:  y:%f p:%f r:%f f:%f s:%f u:%f\n", extern_control->viewangles[YAW], extern_control->viewangles[PITCH], extern_control->viewangles[ROLL], extern_control->forwardmove, extern_control->sidemove, extern_control->upmove);
+
+	dos_int86(extern_control->interruptVector);
+
+Con_DPrintf("OUT: y:%f p:%f r:%f f:%f s:%f u:%f\n", extern_control->viewangles[YAW], extern_control->viewangles[PITCH], extern_control->viewangles[ROLL], extern_control->forwardmove, extern_control->sidemove, extern_control->upmove);
+
+	cl.viewangles[YAW] = extern_control->viewangles[YAW];
+	cl.viewangles[PITCH] = extern_control->viewangles[PITCH];
+	cl.viewangles[ROLL] = extern_control->viewangles[ROLL];
+	cmd->forwardmove = extern_control->forwardmove;
+	cmd->sidemove = extern_control->sidemove;
+	cmd->upmove = extern_control->upmove;
+
+	if (cl.viewangles[PITCH] > 80)
+		cl.viewangles[PITCH] = 80;
+	if (cl.viewangles[PITCH] < -70)
+		cl.viewangles[PITCH] = -70;
+
+	freelook = (extern_control->flags & AUX_FLAG_FREELOOK || aux_look.value || in_mlook.state & 1);
+
+	if (freelook)
+		V_StopPitchDrift ();
+}
+
--- /dev/null
+++ b/WinQuake/in_sun.c
@@ -1,0 +1,245 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// in_sun.c -- SUN/X mouse input handler
+
+#include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/Xatom.h>
+#include <X11/keysym.h>
+
+#include "quakedef.h"
+
+
+//
+// typedefs and defines
+//
+
+#define MOUSE_SCALE		4
+
+//
+// externs
+//
+
+extern Display			*x_disp;
+extern int				x_screen, x_screen_width, x_screen_height;
+extern int			x_center_height, x_center_width;
+extern int				x_std_event_mask;
+extern Window			x_win, x_root_win;
+extern qboolean			x_fullscreen;
+extern qboolean			x_focus;
+extern int			global_dx, global_dy;
+//
+// globals
+//
+
+cvar_t					_windowed_mouse = {"_windowed_mouse","1", true};
+int					x_root, y_root;
+int					x_root_old, y_root_old;
+//
+// locals
+//
+
+static int				x_mouse_num, x_mouse_denom, x_mouse_thresh;
+
+
+static qboolean x_grabbed = false;
+
+//
+// IN_CenterMouse - center the mouse in the screen
+//
+
+void IN_CenterMouse( void )
+{
+	CheckMouseState();
+
+	if (!x_grabbed)
+		return;
+
+	XSelectInput( x_disp, x_win, x_std_event_mask & ~PointerMotionMask );
+	XWarpPointer( x_disp, None, x_root_win, 0, 0, 0, 0, x_center_width,
+		      x_center_height );
+	XSelectInput( x_disp, x_win, x_std_event_mask );
+}
+
+//
+// Check to see if we have grabbed the mouse or not and deal with it
+// appropriately
+//
+static void CheckMouseState(void)
+{
+	if (x_focus && _windowed_mouse.value && !x_grabbed) {
+		x_grabbed = true;
+		printf("fooling with mouse!\n");
+		if (XGetPointerControl( x_disp, &x_mouse_num, &x_mouse_denom, &x_mouse_thresh ))
+			printf( "XGetPointerControl failed!\n" );
+		//printf( "mouse %d/%d thresh %d\n", x_mouse_num, x_mouse_denom, x_mouse_thresh );
+
+		// make input rawer
+		XAutoRepeatOff(x_disp);
+		XGrabKeyboard(x_disp, x_win, True, GrabModeAsync, GrabModeAsync, CurrentTime);
+		XGrabPointer(x_disp, x_win, True, 
+			     PointerMotionMask | ButtonPressMask | ButtonReleaseMask, 
+			     GrabModeAsync, GrabModeAsync, None, None, CurrentTime);
+
+//		if (XChangePointerControl( x_disp, True, True, 1, MOUSE_SCALE, x_mouse_thresh ))
+//			printf( "XChangePointerControl failed!\n" );
+
+		IN_CenterMouse();
+
+		// safe initial values
+		x_root = x_root_old = vid.width >> 1;
+		y_root = y_root_old = vid.height >> 1;
+	} else if (x_grabbed && (!_windowed_mouse.value || !x_focus)) {
+		printf("fooling with mouse!\n");
+		x_grabbed = false;
+		// undo mouse warp
+		if (XChangePointerControl( x_disp, True, True, x_mouse_num, x_mouse_denom, x_mouse_thresh ))
+			printf( "XChangePointerControl failed!\n" );
+
+		XUngrabPointer( x_disp, CurrentTime );
+		XUngrabKeyboard( x_disp, CurrentTime );
+		XAutoRepeatOn( x_disp );
+	}
+}
+
+
+//
+// IN_Init - setup mouse input
+//
+
+void IN_Init (void)
+{
+    if (!x_disp) Sys_Error( "X display not open!\n" );
+
+    Cvar_RegisterVariable (&_windowed_mouse);
+
+	// we really really want to clean these up...
+    atexit( IN_Shutdown );
+}
+
+//
+// IN_Shutdown - clean up mouse settings (must be done from signal handler too!)
+//
+
+void IN_Shutdown (void)
+{
+    if (!x_disp) return;
+
+	// undo mouse warp
+	if (XChangePointerControl( x_disp, True, True, x_mouse_num, x_mouse_denom, x_mouse_thresh ))
+		printf( "XChangePointerControl failed!\n" );
+
+	XUngrabPointer( x_disp, CurrentTime );
+	XUngrabKeyboard( x_disp, CurrentTime );
+	XAutoRepeatOn( x_disp );
+}
+
+//
+// IN_Commands - process buttons
+//
+
+void IN_Commands (void)
+{
+	// done in X event handler
+}
+
+//
+// IN_Move - process mouse moves
+//
+
+void
+IN_Move (usercmd_t *cmd)
+{
+	static int last_dx, last_dy;
+	static long long last_movement;
+	long long now, gethrtime();
+
+	int dx, dy;
+
+	CheckMouseState();
+
+
+	if (!x_grabbed)
+		return; // no mouse movement
+	
+
+	now = gethrtime();
+
+	dx = global_dx;
+	global_dx = 0;
+
+	dy = global_dy;
+	global_dy = 0;
+	
+//	printf("GOT: dx %d dy %d\n", dx, dy);
+
+	dx *= sensitivity.value;
+	dy *= sensitivity.value;
+
+//
+//	implement low pass filter to smooth motion a bit
+//	
+	if (now - last_movement > 100000000) {
+		dx = .6 * dx;
+		dy = .6 * dy;
+	}
+	last_movement = now;
+
+	dx = .6 * dx + .4 * last_dx;
+	dy = .6 * dy + .4 * last_dy;
+
+
+	last_dx = dx;
+	last_dy = dy;
+
+	if (!dx && !dy) {
+		if (in_mlook.state & 1) 
+			V_StopPitchDrift ();
+		return;
+	}
+	
+	// add mouse X/Y movement to cmd
+	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;
+	}
+}
--- /dev/null
+++ b/WinQuake/input.h
@@ -1,0 +1,34 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// input.h -- external (non-keyboard) input devices
+
+void IN_Init (void);
+
+void IN_Shutdown (void);
+
+void IN_Commands (void);
+// oportunity for devices to stick commands on the script buffer
+
+void IN_Move (usercmd_t *cmd);
+// add additional movement on top of the keyboard move cmd
+
+void IN_ClearStates (void);
+// restores all button and position states to defaults
+
--- /dev/null
+++ b/WinQuake/keys.h
@@ -1,0 +1,133 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+
+//
+// these are the key numbers that should be passed to Key_Event
+//
+#define	K_TAB			9
+#define	K_ENTER			13
+#define	K_ESCAPE		27
+#define	K_SPACE			32
+
+// normal keys should be passed as lowercased ascii
+
+#define	K_BACKSPACE		127
+#define	K_UPARROW		128
+#define	K_DOWNARROW		129
+#define	K_LEFTARROW		130
+#define	K_RIGHTARROW	131
+
+#define	K_ALT			132
+#define	K_CTRL			133
+#define	K_SHIFT			134
+#define	K_F1			135
+#define	K_F2			136
+#define	K_F3			137
+#define	K_F4			138
+#define	K_F5			139
+#define	K_F6			140
+#define	K_F7			141
+#define	K_F8			142
+#define	K_F9			143
+#define	K_F10			144
+#define	K_F11			145
+#define	K_F12			146
+#define	K_INS			147
+#define	K_DEL			148
+#define	K_PGDN			149
+#define	K_PGUP			150
+#define	K_HOME			151
+#define	K_END			152
+
+#define K_PAUSE			255
+
+//
+// mouse buttons generate virtual keys
+//
+#define	K_MOUSE1		200
+#define	K_MOUSE2		201
+#define	K_MOUSE3		202
+
+//
+// joystick buttons
+//
+#define	K_JOY1			203
+#define	K_JOY2			204
+#define	K_JOY3			205
+#define	K_JOY4			206
+
+//
+// aux keys are for multi-buttoned joysticks to generate so they can use
+// the normal binding process
+//
+#define	K_AUX1			207
+#define	K_AUX2			208
+#define	K_AUX3			209
+#define	K_AUX4			210
+#define	K_AUX5			211
+#define	K_AUX6			212
+#define	K_AUX7			213
+#define	K_AUX8			214
+#define	K_AUX9			215
+#define	K_AUX10			216
+#define	K_AUX11			217
+#define	K_AUX12			218
+#define	K_AUX13			219
+#define	K_AUX14			220
+#define	K_AUX15			221
+#define	K_AUX16			222
+#define	K_AUX17			223
+#define	K_AUX18			224
+#define	K_AUX19			225
+#define	K_AUX20			226
+#define	K_AUX21			227
+#define	K_AUX22			228
+#define	K_AUX23			229
+#define	K_AUX24			230
+#define	K_AUX25			231
+#define	K_AUX26			232
+#define	K_AUX27			233
+#define	K_AUX28			234
+#define	K_AUX29			235
+#define	K_AUX30			236
+#define	K_AUX31			237
+#define	K_AUX32			238
+
+// JACK: Intellimouse(c) Mouse Wheel Support
+
+#define K_MWHEELUP		239
+#define K_MWHEELDOWN	240
+
+
+
+typedef enum {key_game, key_console, key_message, key_menu} keydest_t;
+
+extern keydest_t	key_dest;
+extern char *keybindings[256];
+extern	int		key_repeats[256];
+extern	int		key_count;			// incremented every key event
+extern	int		key_lastpress;
+
+void Key_Event (int key, qboolean down);
+void Key_Init (void);
+void Key_WriteBindings (FILE *f);
+void Key_SetBinding (int keynum, char *binding);
+void Key_ClearStates (void);
+
binary files /dev/null b/WinQuake/kit/GLQUAKE.EXE differ
binary files /dev/null b/WinQuake/kit/OPENGL32.DLL differ