summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTim Angus <tim@ngus.net>2009-11-16 00:23:28 +0000
committerTim Angus <tim@ngus.net>2013-01-03 00:17:20 +0000
commit21674b587ca1aa1e956b66ae6e613d5afb2111d3 (patch)
treeef74238d6371114ac0f773eacd209f728225ffb9
parentd22e46c9afdaf65a06ed0836d4f7e2b9e689e4d9 (diff)
* Merge ioq3-r1752
-rw-r--r--Makefile212
-rw-r--r--src/client/cl_input.c96
-rw-r--r--src/client/cl_main.c43
-rw-r--r--src/client/client.h2
-rw-r--r--src/client/snd_dma.c13
-rw-r--r--src/client/snd_local.h1
-rw-r--r--src/client/snd_main.c41
-rw-r--r--src/client/snd_mix.c5
-rw-r--r--src/client/snd_openal.c47
-rw-r--r--src/null/null_client.c4
-rw-r--r--src/qcommon/common.c131
-rw-r--r--src/qcommon/cvar.c306
-rw-r--r--src/qcommon/files.c56
-rw-r--r--src/qcommon/net_ip.c6
-rw-r--r--src/qcommon/q_shared.h55
-rw-r--r--src/qcommon/qcommon.h9
-rw-r--r--src/qcommon/vm.c16
-rw-r--r--src/qcommon/vm_interpreted.c21
-rw-r--r--src/qcommon/vm_local.h11
-rw-r--r--src/qcommon/vm_x86_64.c229
-rw-r--r--src/qcommon/vm_x86_64_assembler.c41
-rw-r--r--src/renderer/tr_init.c2
-rw-r--r--src/renderer/tr_local.h1
-rw-r--r--src/sdl/sdl_glimp.c24
-rw-r--r--src/sys/con_tty.c6
-rw-r--r--src/sys/sys_unix.c40
-rw-r--r--src/sys/sys_win32.c31
27 files changed, 1035 insertions, 414 deletions
diff --git a/Makefile b/Makefile
index a49915d1..6af788ee 100644
--- a/Makefile
+++ b/Makefile
@@ -149,6 +149,10 @@ ifndef BUILD_MASTER_SERVER
BUILD_MASTER_SERVER=0
endif
+ifndef DEBUG_CFLAGS
+DEBUG_CFLAGS=-g -O0
+endif
+
#############################################################################
BD=$(BUILD_DIR)/debug-$(PLATFORM)-$(ARCH)
@@ -243,38 +247,43 @@ ifeq ($(PLATFORM),linux)
endif
BASE_CFLAGS = -Wall -fno-strict-aliasing -Wimplicit -Wstrict-prototypes \
- -pipe -DUSE_ICON $(SDL_CFLAGS)
+ -pipe -DUSE_ICON
+ CLIENT_CFLAGS = $(SDL_CFLAGS)
+ SERVER_CFLAGS =
ifeq ($(USE_OPENAL),1)
- BASE_CFLAGS += -DUSE_OPENAL
+ CLIENT_CFLAGS += -DUSE_OPENAL
ifeq ($(USE_OPENAL_DLOPEN),1)
- BASE_CFLAGS += -DUSE_OPENAL_DLOPEN
+ CLIENT_CFLAGS += -DUSE_OPENAL_DLOPEN
endif
endif
ifeq ($(USE_CURL),1)
- BASE_CFLAGS += -DUSE_CURL
+ CLIENT_CFLAGS += -DUSE_CURL
ifeq ($(USE_CURL_DLOPEN),1)
- BASE_CFLAGS += -DUSE_CURL_DLOPEN
+ CLIENT_CFLAGS += -DUSE_CURL_DLOPEN
endif
endif
ifeq ($(USE_CODEC_VORBIS),1)
- BASE_CFLAGS += -DUSE_CODEC_VORBIS
+ CLIENT_CFLAGS += -DUSE_CODEC_VORBIS
endif
- OPTIMIZE = -O3 -ffast-math -funroll-loops -fomit-frame-pointer
+ OPTIMIZEVM = -O3 -funroll-loops -fomit-frame-pointer
+ OPTIMIZE = $(OPTIMIZEVM) -ffast-math
ifeq ($(ARCH),x86_64)
- OPTIMIZE = -O3 -fomit-frame-pointer -ffast-math -funroll-loops \
+ OPTIMIZEVM = -O3 -fomit-frame-pointer -funroll-loops \
-falign-loops=2 -falign-jumps=2 -falign-functions=2 \
-fstrength-reduce
+ OPTIMIZE = $(OPTIMIZEVM) -ffast-math
HAVE_VM_COMPILED = true
else
ifeq ($(ARCH),x86)
- OPTIMIZE = -O3 -march=i586 -fomit-frame-pointer -ffast-math \
+ OPTIMIZEVM = -O3 -march=i586 -fomit-frame-pointer \
-funroll-loops -falign-loops=2 -falign-jumps=2 \
-falign-functions=2 -fstrength-reduce
+ OPTIMIZE = $(OPTIMIZEVM) -ffast-math
HAVE_VM_COMPILED=true
else
ifeq ($(ARCH),ppc)
@@ -287,6 +296,7 @@ ifeq ($(PLATFORM),linux)
endif
ifeq ($(ARCH),sparc)
OPTIMIZE += -mtune=ultrasparc3 -mv8plus
+ OPTIMIZEVM += -mtune=ultrasparc3 -mv8plus
HAVE_VM_COMPILED=true
endif
endif
@@ -326,7 +336,7 @@ ifeq ($(PLATFORM),linux)
endif
ifeq ($(USE_LOCAL_HEADERS),1)
- BASE_CFLAGS += -I$(SDLHDIR)/include
+ CLIENT_CFLAGS += -I$(SDLHDIR)/include
endif
ifeq ($(ARCH),x86)
@@ -337,10 +347,6 @@ ifeq ($(PLATFORM),linux)
BASE_CFLAGS += -m64
endif
endif
-
- DEBUG_CFLAGS = $(BASE_CFLAGS) -g -O0
- RELEASE_CFLAGS=$(BASE_CFLAGS) -DNDEBUG $(OPTIMIZE)
-
else # ifeq Linux
#############################################################################
@@ -350,19 +356,21 @@ else # ifeq Linux
ifeq ($(PLATFORM),darwin)
HAVE_VM_COMPILED=true
CLIENT_LIBS=
- OPTIMIZE=
+ OPTIMIZEVM=
BASE_CFLAGS = -Wall -Wimplicit -Wstrict-prototypes
+ CLIENT_CFLAGS =
+ SERVER_CFLAGS =
ifeq ($(ARCH),ppc)
BASE_CFLAGS += -faltivec
- OPTIMIZE += -O3
+ OPTIMIZEVM += -O3
endif
ifeq ($(ARCH),ppc64)
BASE_CFLAGS += -faltivec
endif
ifeq ($(ARCH),x86)
- OPTIMIZE += -march=prescott -mfpmath=sse
+ OPTIMIZEVM += -march=prescott -mfpmath=sse
# x86 vm will crash without -mstackrealign since MMX instructions will be
# used no matter what and they corrupt the frame pointer in VM calls
BASE_CFLAGS += -mstackrealign
@@ -375,21 +383,21 @@ ifeq ($(PLATFORM),darwin)
ifneq ($(USE_OPENAL_DLOPEN),1)
CLIENT_LIBS += -framework OpenAL
else
- BASE_CFLAGS += -DUSE_OPENAL_DLOPEN
+ CLIENT_CFLAGS += -DUSE_OPENAL_DLOPEN
endif
endif
ifeq ($(USE_CURL),1)
- BASE_CFLAGS += -DUSE_CURL
+ CLIENT_CFLAGS += -DUSE_CURL
ifneq ($(USE_CURL_DLOPEN),1)
CLIENT_LIBS += -lcurl
else
- BASE_CFLAGS += -DUSE_CURL_DLOPEN
+ CLIENT_CFLAGS += -DUSE_CURL_DLOPEN
endif
endif
ifeq ($(USE_CODEC_VORBIS),1)
- BASE_CFLAGS += -DUSE_CODEC_VORBIS
+ CLIENT_CFLAGS += -DUSE_CODEC_VORBIS
CLIENT_LIBS += -lvorbisfile -lvorbis -logg
endif
@@ -406,16 +414,13 @@ ifeq ($(PLATFORM),darwin)
CLIENT_LIBS += -framework Cocoa -framework IOKit -framework OpenGL \
$(LIBSDIR)/macosx/libSDL-1.2.0.dylib
- OPTIMIZE += -ffast-math -falign-loops=16
+ OPTIMIZEVM += -falign-loops=16
+ OPTIMIZE = $(OPTIMIZEVM) -ffast-math
ifneq ($(HAVE_VM_COMPILED),true)
BASE_CFLAGS += -DNO_VM_COMPILED
endif
- DEBUG_CFLAGS = $(BASE_CFLAGS) -g -O0
-
- RELEASE_CFLAGS=$(BASE_CFLAGS) -DNDEBUG $(OPTIMIZE)
-
SHLIBEXT=dylib
SHLIBCFLAGS=-fPIC -fno-common
SHLIBLDFLAGS=-dynamiclib $(LDFLAGS)
@@ -447,6 +452,8 @@ ifeq ($(PLATFORM),mingw32)
BASE_CFLAGS = -Wall -fno-strict-aliasing -Wimplicit -Wstrict-prototypes \
-DUSE_ICON
+ CLIENT_CFLAGS =
+ SERVER_CFLAGS =
# In the absence of wspiapi.h, require Windows XP or later
ifeq ($(shell test -e $(CMDIR)/wspiapi.h; echo $$?),1)
@@ -454,22 +461,23 @@ ifeq ($(PLATFORM),mingw32)
endif
ifeq ($(USE_OPENAL),1)
- BASE_CFLAGS += -DUSE_OPENAL
- BASE_CFLAGS += $(OPENAL_CFLAGS)
+ CLIENT_CFLAGS += -DUSE_OPENAL
+ CLIENT_CFLAGS += $(OPENAL_CFLAGS)
ifeq ($(USE_OPENAL_DLOPEN),1)
- BASE_CFLAGS += -DUSE_OPENAL_DLOPEN
+ CLIENT_CFLAGS += -DUSE_OPENAL_DLOPEN
else
CLIENT_LDFLAGS += $(OPENAL_LDFLAGS)
endif
endif
ifeq ($(USE_CODEC_VORBIS),1)
- BASE_CFLAGS += -DUSE_CODEC_VORBIS
+ CLIENT_CFLAGS += -DUSE_CODEC_VORBIS
endif
- OPTIMIZE = -O3 -march=i586 -fno-omit-frame-pointer -ffast-math \
+ OPTIMIZEVM = -O3 -march=i586 -fno-omit-frame-pointer \
-falign-loops=2 -funroll-loops -falign-jumps=2 -falign-functions=2 \
-fstrength-reduce
+ OPTIMIZE = $(OPTIMIZEVM) -ffast-math
HAVE_VM_COMPILED = true
@@ -484,11 +492,11 @@ ifeq ($(PLATFORM),mingw32)
CLIENT_LIBS = -lgdi32 -lole32 -lopengl32
ifeq ($(USE_CURL),1)
- BASE_CFLAGS += -DUSE_CURL
- BASE_CFLAGS += $(CURL_CFLAGS)
+ CLIENT_CFLAGS += -DUSE_CURL
+ CLIENT_CFLAGS += $(CURL_CFLAGS)
ifneq ($(USE_CURL_DLOPEN),1)
ifeq ($(USE_LOCAL_HEADERS),1)
- BASE_CFLAGS += -DCURL_STATICLIB
+ CLIENT_CFLAGS += -DCURL_STATICLIB
CLIENT_LIBS += $(LIBSDIR)/win32/libcurl.a
else
CLIENT_LIBS += $(CURL_LIBS)
@@ -505,22 +513,17 @@ ifeq ($(PLATFORM),mingw32)
BASE_CFLAGS += -m32
endif
- DEBUG_CFLAGS=$(BASE_CFLAGS) -g -O0
- RELEASE_CFLAGS=$(BASE_CFLAGS) -DNDEBUG $(OPTIMIZE)
-
# libmingw32 must be linked before libSDLmain
CLIENT_LIBS += -lmingw32
ifeq ($(USE_LOCAL_HEADERS),1)
- BASE_CFLAGS += -I$(SDLHDIR)/include
+ CLIENT_CFLAGS += -I$(SDLHDIR)/include
CLIENT_LIBS += $(LIBSDIR)/win32/libSDLmain.a \
$(LIBSDIR)/win32/libSDL.dll.a
else
- BASE_CFLAGS += $(SDL_CFLAGS)
+ CLIENT_CFLAGS += $(SDL_CFLAGS)
CLIENT_LIBS += $(SDL_LIBS)
endif
-
-
BUILD_CLIENT_SMP = 0
else # ifeq mingw32
@@ -537,38 +540,39 @@ ifeq ($(PLATFORM),freebsd)
ARCH=x86
endif #alpha test
-
BASE_CFLAGS = -Wall -fno-strict-aliasing -Wimplicit -Wstrict-prototypes \
- -DUSE_ICON $(SDL_CFLAGS)
+ -DUSE_ICON
+ CLIENT_CFLAGS = $(SDL_CFLAGS)
+ SERVER_CFLAGS =
ifeq ($(USE_OPENAL),1)
- BASE_CFLAGS += -DUSE_OPENAL
+ CLIENT_CFLAGS += -DUSE_OPENAL
ifeq ($(USE_OPENAL_DLOPEN),1)
- BASE_CFLAGS += -DUSE_OPENAL_DLOPEN
+ CLIENT_CFLAGS += -DUSE_OPENAL_DLOPEN
endif
endif
ifeq ($(USE_CODEC_VORBIS),1)
- BASE_CFLAGS += -DUSE_CODEC_VORBIS
+ CLIENT_CFLAGS += -DUSE_CODEC_VORBIS
endif
+ OPTIMIZEVM = -DNDEBUG -O3 -funroll-loops -fomit-frame-pointer
+
ifeq ($(ARCH),axp)
BASE_CFLAGS += -DNO_VM_COMPILED
- RELEASE_CFLAGS=$(BASE_CFLAGS) -DNDEBUG -O3 -ffast-math -funroll-loops \
- -fomit-frame-pointer -fexpensive-optimizations
+ OPTIMIZEVM += -fexpensive-optimizations
else
ifeq ($(ARCH),x86)
- RELEASE_CFLAGS=$(BASE_CFLAGS) -DNDEBUG -O3 -mtune=pentiumpro \
- -march=pentium -fomit-frame-pointer -pipe -ffast-math \
- -falign-loops=2 -falign-jumps=2 -falign-functions=2 \
- -funroll-loops -fstrength-reduce
+ OPTIMIZEVM += -mtune=pentiumpro \
+ -march=pentium -pipe -falign-loops=2 -falign-jumps=2 \
+ -falign-functions=2 -funroll-loops -fstrength-reduce
HAVE_VM_COMPILED=true
else
BASE_CFLAGS += -DNO_VM_COMPILED
endif
endif
- DEBUG_CFLAGS=$(BASE_CFLAGS) -g
+ OPTIMIZE = $(OPTIMIZEVM) -ffast-math
SHLIBEXT=so
SHLIBCFLAGS=-fPIC
@@ -603,32 +607,30 @@ ifeq ($(PLATFORM),openbsd)
#default to i386, no tests done on anything else
ARCH=i386
-
BASE_CFLAGS = -Wall -fno-strict-aliasing -Wimplicit -Wstrict-prototypes \
- -DUSE_ICON $(SDL_CFLAGS)
+ -DUSE_ICON
+ CLIENT_CFLAGS = $(SDL_CFLAGS)
+ SERVER_CFLAGS =
ifeq ($(USE_OPENAL),1)
- BASE_CFLAGS += -DUSE_OPENAL
+ CLIENT_CFLAGS += -DUSE_OPENAL
ifeq ($(USE_OPENAL_DLOPEN),1)
- BASE_CFLAGS += -DUSE_OPENAL_DLOPEN
+ CLIENT_CFLAGS += -DUSE_OPENAL_DLOPEN
endif
endif
ifeq ($(USE_CODEC_VORBIS),1)
- BASE_CFLAGS += -DUSE_CODEC_VORBIS
+ CLIENT_CFLAGS += -DUSE_CODEC_VORBIS
endif
ifeq ($(USE_CURL),1)
- BASE_CFLAGS += -DUSE_CURL $(CURL_CFLAGS)
+ CLIENT_CFLAGS += -DUSE_CURL $(CURL_CFLAGS)
USE_CURL_DLOPEN=0
endif
BASE_CFLAGS += -DNO_VM_COMPILED
- RELEASE_CFLAGS=$(BASE_CFLAGS) -DNDEBUG
HAVE_VM_COMPILED=false
- DEBUG_CFLAGS=$(BASE_CFLAGS) -g
-
SHLIBEXT=so
SHLIBNAME=.$(SHLIBEXT)
SHLIBCFLAGS=-fPIC
@@ -676,13 +678,13 @@ ifeq ($(PLATFORM),netbsd)
THREAD_LIBS=-lpthread
BASE_CFLAGS = -Wall -fno-strict-aliasing -Wimplicit -Wstrict-prototypes
+ CLIENT_CFLAGS =
+ SERVER_CFLAGS =
ifneq ($(ARCH),x86)
BASE_CFLAGS += -DNO_VM_COMPILED
endif
- DEBUG_CFLAGS=$(BASE_CFLAGS) -g
-
BUILD_CLIENT = 0
BUILD_GAME_QVM = 0
@@ -700,10 +702,10 @@ ifeq ($(PLATFORM),irix64)
MKDIR = mkdir -p
BASE_CFLAGS=-Dstricmp=strcasecmp -Xcpluscomm -woff 1185 \
- -I. $(SDL_CFLAGS) -I$(ROOT)/usr/include -DNO_VM_COMPILED
- RELEASE_CFLAGS=$(BASE_CFLAGS) -O3
- DEBUG_CFLAGS=$(BASE_CFLAGS) -g
-
+ -I. -I$(ROOT)/usr/include -DNO_VM_COMPILED
+ CLIENT_CFLAGS = $(SDL_CFLAGS)
+ OPTIMIZE = -O3
+
SHLIBEXT=so
SHLIBCFLAGS=
SHLIBLDFLAGS=-shared
@@ -739,36 +741,35 @@ ifeq ($(PLATFORM),sunos)
endif
BASE_CFLAGS = -Wall -fno-strict-aliasing -Wimplicit -Wstrict-prototypes \
- -pipe -DUSE_ICON $(SDL_CFLAGS)
+ -pipe -DUSE_ICON
+ CLIENT_CFLAGS = $(SDL_CFLAGS)
+ SERVER_CFLAGS =
- OPTIMIZE = -O3 -ffast-math -funroll-loops
+ OPTIMIZEVM = -O3 -funroll-loops -DNDEBUG
ifeq ($(ARCH),sparc)
- OPTIMIZE = -O3 -ffast-math \
+ OPTIMIZEVM += -O3 \
-fstrength-reduce -falign-functions=2 \
- -mtune=ultrasparc3 -mv8plus -mno-faster-structs \
- -funroll-loops #-mv8plus
+ -mtune=ultrasparc3 -mv8plus -mno-faster-structs
HAVE_VM_COMPILED=true
else
ifeq ($(ARCH),x86)
- OPTIMIZE = -O3 -march=i586 -fomit-frame-pointer -ffast-math \
- -funroll-loops -falign-loops=2 -falign-jumps=2 \
+ OPTIMIZEVM += -march=i586 -fomit-frame-pointer \
+ -falign-loops=2 -falign-jumps=2 \
-falign-functions=2 -fstrength-reduce
HAVE_VM_COMPILED=true
BASE_CFLAGS += -m32
- BASE_CFLAGS += -I/usr/X11/include/NVIDIA
+ CLIENT_CFLAGS += -I/usr/X11/include/NVIDIA
CLIENT_LDFLAGS += -L/usr/X11/lib/NVIDIA -R/usr/X11/lib/NVIDIA
endif
endif
+
+ OPTIMIZE = $(OPTIMIZEVM) -ffast-math
ifneq ($(HAVE_VM_COMPILED),true)
BASE_CFLAGS += -DNO_VM_COMPILED
endif
- DEBUG_CFLAGS = $(BASE_CFLAGS) -ggdb -O0
-
- RELEASE_CFLAGS=$(BASE_CFLAGS) -DNDEBUG $(OPTIMIZE)
-
SHLIBEXT=so
SHLIBCFLAGS=-fPIC
SHLIBLDFLAGS=-shared $(LDFLAGS)
@@ -786,8 +787,7 @@ else # ifeq sunos
# SETUP AND BUILD -- GENERIC
#############################################################################
BASE_CFLAGS=-DNO_VM_COMPILED
- DEBUG_CFLAGS=$(BASE_CFLAGS) -g
- RELEASE_CFLAGS=$(BASE_CFLAGS) -DNDEBUG -O3
+ OPTIMIZE = -DNDEBUG -O3
SHLIBEXT=so
SHLIBCFLAGS=-fPIC
@@ -840,13 +840,13 @@ ifneq ($(BUILD_GAME_QVM),0)
endif
ifeq ($(USE_MUMBLE),1)
- BASE_CFLAGS += -DUSE_MUMBLE
+ CLIENT_CFLAGS += -DUSE_MUMBLE
endif
ifeq ($(USE_VOIP),1)
- BASE_CFLAGS += -DUSE_VOIP
+ CLIENT_CFLAGS += -DUSE_VOIP
ifeq ($(USE_INTERNAL_SPEEX),1)
- BASE_CFLAGS += -DFLOATING_POINT -DUSE_ALLOCA -I$(SPEEXDIR)/include
+ CLIENT_CFLAGS += -DFLOATING_POINT -DUSE_ALLOCA -I$(SPEEXDIR)/include
else
CLIENT_LIBS += -lspeex -lspeexdsp
endif
@@ -897,12 +897,12 @@ endif
define DO_CC
$(echo_cmd) "CC $<"
-$(Q)$(CC) $(NOTSHLIBCFLAGS) $(CFLAGS) -o $@ -c $<
+$(Q)$(CC) $(NOTSHLIBCFLAGS) $(CFLAGS) $(CLIENT_CFLAGS) $(OPTIMIZE) -o $@ -c $<
endef
define DO_SMP_CC
$(echo_cmd) "SMP_CC $<"
-$(Q)$(CC) $(NOTSHLIBCFLAGS) $(CFLAGS) -DSMP -o $@ -c $<
+$(Q)$(CC) $(NOTSHLIBCFLAGS) $(CFLAGS) $(CLIENT_CFLAGS) $(OPTIMIZE) -DSMP -o $@ -c $<
endef
ifeq ($(GENERATE_DEPENDENCIES),1)
@@ -911,36 +911,36 @@ endif
define DO_SHLIB_CC
$(echo_cmd) "SHLIB_CC $<"
-$(Q)$(CC) $(CFLAGS) $(SHLIBCFLAGS) -o $@ -c $<
+$(Q)$(CC) $(SHLIBCFLAGS) $(CFLAGS) $(OPTIMIZEVM) -o $@ -c $<
$(Q)$(DO_QVM_DEP)
endef
define DO_GAME_CC
$(echo_cmd) "GAME_CC $<"
-$(Q)$(CC) -DGAME $(CFLAGS) $(SHLIBCFLAGS) -o $@ -c $<
+$(Q)$(CC) -DGAME $(SHLIBCFLAGS) $(CFLAGS) $(OPTIMIZEVM) -o $@ -c $<
$(Q)$(DO_QVM_DEP)
endef
define DO_CGAME_CC
$(echo_cmd) "CGAME_CC $<"
-$(Q)$(CC) -DCGAME $(CFLAGS) $(SHLIBCFLAGS) -o $@ -c $<
+$(Q)$(CC) -DCGAME $(SHLIBCFLAGS) $(CFLAGS) $(OPTIMIZEVM) -o $@ -c $<
$(Q)$(DO_QVM_DEP)
endef
define DO_UI_CC
$(echo_cmd) "UI_CC $<"
-$(Q)$(CC) -DUI $(CFLAGS) $(SHLIBCFLAGS) -o $@ -c $<
+$(Q)$(CC) -DUI $(SHLIBCFLAGS) $(CFLAGS) $(OPTIMIZEVM) -o $@ -c $<
$(Q)$(DO_QVM_DEP)
endef
define DO_AS
$(echo_cmd) "AS $<"
-$(Q)$(CC) $(CFLAGS) -x assembler-with-cpp -o $@ -c $<
+$(Q)$(CC) $(CFLAGS) $(OPTIMIZE) -x assembler-with-cpp -o $@ -c $<
endef
define DO_DED_CC
$(echo_cmd) "DED_CC $<"
-$(Q)$(CC) $(NOTSHLIBCFLAGS) -DDEDICATED $(CFLAGS) -o $@ -c $<
+$(Q)$(CC) $(NOTSHLIBCFLAGS) -DDEDICATED $(CFLAGS) $(SERVER_CFLAGS) $(OPTIMIZE) -o $@ -c $<
endef
define DO_WINDRES
@@ -957,15 +957,17 @@ default: release
all: debug release
debug:
- @$(MAKE) targets B=$(BD) CFLAGS="$(CFLAGS) $(DEPEND_CFLAGS) \
- $(DEBUG_CFLAGS)" V=$(V)
+ @$(MAKE) targets B=$(BD) CFLAGS="$(CFLAGS) $(BASE_CFLAGS) $(DEPEND_CFLAGS)" \
+ OPTIMIZE="$(DEBUG_CFLAGS)" OPTIMIZEVM="$(DEBUG_CFLAGS)" \
+ CLIENT_CFLAGS="$(CLIENT_CFLAGS)" SERVER_CFLAGS="$(SERVER_CFLAGS)" V=$(V)
ifeq ($(BUILD_MASTER_SERVER),1)
$(MAKE) -C $(MASTERDIR) debug
endif
release:
- @$(MAKE) targets B=$(BR) CFLAGS="$(CFLAGS) $(DEPEND_CFLAGS) \
- $(RELEASE_CFLAGS)" V=$(V)
+ @$(MAKE) targets B=$(BR) CFLAGS="$(CFLAGS) $(BASE_CFLAGS) $(DEPEND_CFLAGS)" \
+ OPTIMIZE="$(OPTIMIZE)" OPTIMIZEVM="$(OPTIMIZEVM)" \
+ CLIENT_CFLAGS="$(CLIENT_CFLAGS)" SERVER_CFLAGS="$(SERVER_CFLAGS)" V=$(V)
ifeq ($(BUILD_MASTER_SERVER),1)
$(MAKE) -C $(MASTERDIR) release
endif
@@ -987,6 +989,22 @@ targets: makedirs
do \
echo " $$i"; \
done
+ -@for i in $(OPTIMIZE); \
+ do \
+ echo " $$i"; \
+ done
+ @echo ""
+ @echo " CLIENT_CFLAGS:"
+ -@for i in $(CLIENT_CFLAGS); \
+ do \
+ echo " $$i"; \
+ done
+ @echo ""
+ @echo " SERVER_CFLAGS:"
+ -@for i in $(SERVER_CFLAGS); \
+ do \
+ echo " $$i"; \
+ done
@echo ""
@echo " LDFLAGS:"
-@for i in $(LDFLAGS); \
diff --git a/src/client/cl_input.c b/src/client/cl_input.c
index 49551662..19bdb95a 100644
--- a/src/client/cl_input.c
+++ b/src/client/cl_input.c
@@ -436,52 +436,88 @@ void CL_JoystickMove( usercmd_t *cmd ) {
CL_MouseMove
=================
*/
-void CL_MouseMove( usercmd_t *cmd ) {
- float mx, my;
- float accelSensitivity;
- float rate;
+
+void CL_MouseMove(usercmd_t *cmd)
+{
+ float mx, my;
// allow mouse smoothing
- if ( m_filter->integer ) {
- mx = ( cl.mouseDx[0] + cl.mouseDx[1] ) * 0.5;
- my = ( cl.mouseDy[0] + cl.mouseDy[1] ) * 0.5;
- } else {
+ if (m_filter->integer)
+ {
+ mx = (cl.mouseDx[0] + cl.mouseDx[1]) * 0.5f;
+ my = (cl.mouseDy[0] + cl.mouseDy[1]) * 0.5f;
+ }
+ else
+ {
mx = cl.mouseDx[cl.mouseIndex];
my = cl.mouseDy[cl.mouseIndex];
}
+
cl.mouseIndex ^= 1;
cl.mouseDx[cl.mouseIndex] = 0;
cl.mouseDy[cl.mouseIndex] = 0;
- rate = sqrt( mx * mx + my * my ) / (float)frame_msec;
- accelSensitivity = cl_sensitivity->value + rate * cl_mouseAccel->value;
-
- // scale by FOV
- accelSensitivity *= cl.cgameSensitivity;
-
- if ( rate && cl_showMouseRate->integer ) {
- Com_Printf( "%f : %f\n", rate, accelSensitivity );
- }
-
- mx *= accelSensitivity;
- my *= accelSensitivity;
-
- if (!mx && !my) {
+ if (mx == 0.0f && my == 0.0f)
return;
+
+ if (cl_mouseAccel->value != 0.0f)
+ {
+ if(cl_mouseAccelStyle->integer == 0)
+ {
+ float accelSensitivity;
+ float rate;
+
+ rate = sqrt(mx * mx + my * my) / (float) frame_msec;
+
+ accelSensitivity = cl_sensitivity->value + rate * cl_mouseAccel->value;
+ mx *= accelSensitivity;
+ my *= accelSensitivity;
+
+ if(cl_showMouseRate->integer)
+ Com_Printf("rate: %f, accelSensitivity: %f\n", rate, accelSensitivity);
+ }
+ else
+ {
+ float rate[2];
+ float power[2];
+
+ // sensitivity remains pretty much unchanged at low speeds
+ // cl_mouseAccel is a power value to how the acceleration is shaped
+ // cl_mouseAccelOffset is the rate for which the acceleration will have doubled the non accelerated amplification
+ // NOTE: decouple the config cvars for independent acceleration setup along X and Y?
+
+ rate[0] = fabs(mx) / (float) frame_msec;
+ rate[1] = fabs(my) / (float) frame_msec;
+ power[0] = powf(rate[0] / cl_mouseAccelOffset->value, cl_mouseAccel->value);
+ power[1] = powf(rate[1] / cl_mouseAccelOffset->value, cl_mouseAccel->value);
+
+ mx = cl_sensitivity->value * (mx + ((mx < 0) ? -power[0] : power[0]) * cl_mouseAccelOffset->value);
+ my = cl_sensitivity->value * (my + ((my < 0) ? -power[1] : power[1]) * cl_mouseAccelOffset->value);
+
+ if(cl_showMouseRate->integer)
+ Com_Printf("ratex: %f, ratey: %f, powx: %f, powy: %f\n", rate[0], rate[1], power[0], power[1]);
+ }
}
+ else
+ {
+ mx *= cl_sensitivity->value;
+ my *= cl_sensitivity->value;
+ }
+
+ // ingame FOV
+ mx *= cl.cgameSensitivity;
+ my *= cl.cgameSensitivity;
// add mouse X/Y movement to cmd
- if ( in_strafe.active ) {
- cmd->rightmove = ClampChar( cmd->rightmove + m_side->value * mx );
- } else {
+ if(in_strafe.active)
+ cmd->rightmove = ClampChar(cmd->rightmove + m_side->value * mx);
+ else
cl.viewangles[YAW] -= m_yaw->value * mx;
- }
- if ( (in_mlooking || cl_freelook->integer) && !in_strafe.active ) {
+ if ((in_mlooking || cl_freelook->integer) && !in_strafe.active)
cl.viewangles[PITCH] += m_pitch->value * my;
- } else {
- cmd->forwardmove = ClampChar( cmd->forwardmove - m_forward->value * my );
- }
+ else
+ cmd->forwardmove = ClampChar(cmd->forwardmove - m_forward->value * my);
}
diff --git a/src/client/cl_main.c b/src/client/cl_main.c
index 4c8ded12..ff86ee2f 100644
--- a/src/client/cl_main.c
+++ b/src/client/cl_main.c
@@ -74,6 +74,8 @@ cvar_t *cl_freelook;
cvar_t *cl_sensitivity;
cvar_t *cl_mouseAccel;
+cvar_t *cl_mouseAccelOffset;
+cvar_t *cl_mouseAccelStyle;
cvar_t *cl_showMouseRate;
cvar_t *m_pitch;
@@ -977,7 +979,7 @@ void CL_PlayDemo_f( void ) {
char retry[MAX_OSPATH];
if (Cmd_Argc() != 2) {
- Com_Printf ("playdemo <demoname>\n");
+ Com_Printf ("demo <demoname>\n");
return;
}
@@ -985,14 +987,17 @@ void CL_PlayDemo_f( void ) {
// 2 means don't force disconnect of local client
Cvar_Set( "sv_killserver", "2" );
- CL_Disconnect( qtrue );
-
// open the demo file
arg = Cmd_Argv(1);
+ CL_Disconnect( qtrue );
+
// check for an extension .dm_?? (?? is protocol)
ext_test = arg + strlen(arg) - 6;
- if ((strlen(arg) > 6) && (ext_test[0] == '.') && ((ext_test[1] == 'd') || (ext_test[1] == 'D')) && ((ext_test[2] == 'm') || (ext_test[2] == 'M')) && (ext_test[3] == '_'))
+ if ((strlen(arg) > 6) && (ext_test[0] == '.') &&
+ ((ext_test[1] == 'd') || (ext_test[1] == 'D')) &&
+ ((ext_test[2] == 'm') || (ext_test[2] == 'M')) &&
+ (ext_test[3] == '_'))
{
protocol = atoi(ext_test+4);
i=0;
@@ -1343,6 +1348,9 @@ void CL_Disconnect( qboolean showMainMenu ) {
CL_WritePacket();
}
+ // Remove pure paks
+ FS_PureServerSetLoadedPaks("", "");
+
CL_ClearState ();
// wipe the client connection
@@ -1752,17 +1760,29 @@ void CL_Vid_Restart_f( void ) {
/*
=================
-CL_Snd_Restart_f
+CL_Snd_Restart
Restart the sound subsystem
-The cgame and game must also be forced to restart because
-handles will be invalid
=================
*/
-void CL_Snd_Restart_f( void ) {
+void CL_Snd_Restart(void)
+{
S_Shutdown();
S_Init();
+}
+/*
+=================
+CL_Snd_Restart_f
+
+Restart the sound subsystem
+The cgame and game must also be forced to restart because
+handles will be invalid
+=================
+*/
+void CL_Snd_Restart_f(void)
+{
+ CL_Snd_Restart();
CL_Vid_Restart_f();
}
@@ -3337,6 +3357,13 @@ void CL_Init( void ) {
cl_mouseAccel = Cvar_Get ("cl_mouseAccel", "0", CVAR_ARCHIVE);
cl_freelook = Cvar_Get( "cl_freelook", "1", CVAR_ARCHIVE );
+ // 0: legacy mouse acceleration
+ // 1: new implementation
+ cl_mouseAccelStyle = Cvar_Get( "cl_mouseAccelStyle", "0", CVAR_ARCHIVE );
+ // offset for the power function (for style 1, ignored otherwise)
+ // this should be set to the max rate value
+ cl_mouseAccelOffset = Cvar_Get( "cl_mouseAccelOffset", "5", CVAR_ARCHIVE );
+
cl_showMouseRate = Cvar_Get ("cl_showmouserate", "0", 0);
cl_allowDownload = Cvar_Get ("cl_allowDownload", "0", CVAR_ARCHIVE);
diff --git a/src/client/client.h b/src/client/client.h
index 1e18a9ad..0dc2490e 100644
--- a/src/client/client.h
+++ b/src/client/client.h
@@ -387,6 +387,8 @@ extern cvar_t *cl_sensitivity;
extern cvar_t *cl_freelook;
extern cvar_t *cl_mouseAccel;
+extern cvar_t *cl_mouseAccelOffset;
+extern cvar_t *cl_mouseAccelStyle;
extern cvar_t *cl_showMouseRate;
extern cvar_t *m_pitch;
diff --git a/src/client/snd_dma.c b/src/client/snd_dma.c
index 472af0d8..ad6193c8 100644
--- a/src/client/snd_dma.c
+++ b/src/client/snd_dma.c
@@ -34,10 +34,6 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "snd_codec.h"
#include "client.h"
-void S_Play_f(void);
-void S_SoundList_f(void);
-void S_Music_f(void);
-
void S_Update_( void );
void S_Base_StopAllSounds(void);
void S_Base_StopBackgroundTrack( void );
@@ -953,7 +949,10 @@ void S_Base_RawSamples( int stream, int samples, int rate, int width, int s_chan
}
rawsamples = s_rawsamples[stream];
- intVolume = 256 * volume * s_volume->value;
+ if(s_muted->integer)
+ intVolume = 0;
+ else
+ intVolume = 256 * volume * s_volume->value;
if ( s_rawend[stream] < s_soundtime ) {
Com_DPrintf( "S_Base_RawSamples: resetting minimum: %i < %i\n", s_rawend[stream], s_soundtime );
@@ -1328,7 +1327,9 @@ void S_Base_StartBackgroundTrack( const char *intro, const char *loop ){
}
Com_DPrintf( "S_StartBackgroundTrack( %s, %s )\n", intro, loop );
- if ( !intro[0] ) {
+ if(!*intro)
+ {
+ S_Base_StopBackgroundTrack();
return;
}
diff --git a/src/client/snd_local.h b/src/client/snd_local.h
index a926e7f9..24ddc54d 100644
--- a/src/client/snd_local.h
+++ b/src/client/snd_local.h
@@ -195,6 +195,7 @@ extern int s_rawend[MAX_RAW_STREAMS];
extern cvar_t *s_volume;
extern cvar_t *s_musicVolume;
+extern cvar_t *s_muted;
extern cvar_t *s_doppler;
extern cvar_t *s_testsound;
diff --git a/src/client/snd_main.c b/src/client/snd_main.c
index c386cd75..66c3f9e7 100644
--- a/src/client/snd_main.c
+++ b/src/client/snd_main.c
@@ -28,6 +28,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "snd_public.h"
cvar_t *s_volume;
+cvar_t *s_muted;
cvar_t *s_musicVolume;
cvar_t *s_doppler;
cvar_t *s_backend;
@@ -231,12 +232,25 @@ S_Update
*/
void S_Update( void )
{
- if( ( s_muteWhenMinimized->integer && com_minimized->integer ) ||
- ( s_muteWhenUnfocused->integer && com_unfocused->integer ) ) {
- S_StopAllSounds( );
- return;
+ if(s_muted->integer)
+ {
+ if(!(s_muteWhenMinimized->integer && com_minimized->integer) &&
+ !(s_muteWhenUnfocused->integer && com_unfocused->integer))
+ {
+ s_muted->integer = qfalse;
+ s_muted->modified = qtrue;
+ }
}
-
+ else
+ {
+ if((s_muteWhenMinimized->integer && com_minimized->integer) ||
+ (s_muteWhenUnfocused->integer && com_unfocused->integer))
+ {
+ s_muted->integer = qtrue;
+ s_muted->modified = qtrue;
+ }
+ }
+
if( si.Update ) {
si.Update( );
}
@@ -449,6 +463,20 @@ void S_Music_f( void ) {
}
+/*
+=================
+S_Music_f
+=================
+*/
+void S_StopMusic_f( void )
+{
+ if(!si.StopBackgroundTrack)
+ return;
+
+ si.StopBackgroundTrack();
+}
+
+
//=============================================================================
/*
@@ -465,6 +493,7 @@ void S_Init( void )
s_volume = Cvar_Get( "s_volume", "0.8", CVAR_ARCHIVE );
s_musicVolume = Cvar_Get( "s_musicvolume", "0.25", CVAR_ARCHIVE );
+ s_muted = Cvar_Get("s_muted", "0", CVAR_ROM);
s_doppler = Cvar_Get( "s_doppler", "1", CVAR_ARCHIVE );
s_backend = Cvar_Get( "s_backend", "", CVAR_ROM );
s_muteWhenMinimized = Cvar_Get( "s_muteWhenMinimized", "0", CVAR_ARCHIVE );
@@ -479,6 +508,7 @@ void S_Init( void )
Cmd_AddCommand( "play", S_Play_f );
Cmd_AddCommand( "music", S_Music_f );
+ Cmd_AddCommand( "stopmusic", S_StopMusic_f );
Cmd_AddCommand( "s_list", S_SoundList );
Cmd_AddCommand( "s_stop", S_StopAllSounds );
Cmd_AddCommand( "s_info", S_SoundInfo );
@@ -525,6 +555,7 @@ void S_Shutdown( void )
Cmd_RemoveCommand( "play" );
Cmd_RemoveCommand( "music");
+ Cmd_RemoveCommand( "stopmusic");
Cmd_RemoveCommand( "s_list" );
Cmd_RemoveCommand( "s_stop" );
Cmd_RemoveCommand( "s_info" );
diff --git a/src/client/snd_mix.c b/src/client/snd_mix.c
index fa2a841d..a9d4c794 100644
--- a/src/client/snd_mix.c
+++ b/src/client/snd_mix.c
@@ -638,7 +638,10 @@ void S_PaintChannels( int endtime ) {
int ltime, count;
int sampleOffset;
- snd_vol = s_volume->value*255;
+ if(s_muted->integer)
+ snd_vol = 0;
+ else
+ snd_vol = s_volume->value*255;
//Com_Printf ("%i to %i\n", s_paintedtime, endtime);
while ( s_paintedtime < endtime ) {
diff --git a/src/client/snd_openal.c b/src/client/snd_openal.c
index 96068075..12df259c 100644
--- a/src/client/snd_openal.c
+++ b/src/client/snd_openal.c
@@ -581,6 +581,21 @@ static void _S_AL_SanitiseVector( vec3_t v, int line )
/*
=================
+S_AL_Gain
+Set gain to 0 if muted, otherwise set it to given value.
+=================
+*/
+
+static void S_AL_Gain(ALuint source, float gainval)
+{
+ if(s_muted->integer)
+ qalSourcef(source, AL_GAIN, 0.0f);
+ else
+ qalSourcef(source, AL_GAIN, gainval);
+}
+
+/*
+=================
S_AL_ScaleGain
Adapt the gain if necessary to get a quicker fadeout when the source is too far away.
=================
@@ -609,13 +624,13 @@ static void S_AL_ScaleGain(src_t *chksrc, vec3_t origin)
if(chksrc->scaleGain != scaleFactor);
{
chksrc->scaleGain = scaleFactor;
- qalSourcef(chksrc->alSource, AL_GAIN, chksrc->scaleGain);
+ S_AL_Gain(chksrc->alSource, chksrc->scaleGain);
}
}
else if(chksrc->scaleGain != chksrc->curGain)
{
chksrc->scaleGain = chksrc->curGain;
- qalSourcef(chksrc->alSource, AL_GAIN, chksrc->scaleGain);
+ S_AL_Gain(chksrc->alSource, chksrc->scaleGain);
}
}
@@ -757,7 +772,7 @@ static void S_AL_SrcSetup(srcHandle_t src, sfxHandle_t sfx, alSrcPriority_t prio
// Set up OpenAL source
qalSourcei(curSource->alSource, AL_BUFFER, buffer);
qalSourcef(curSource->alSource, AL_PITCH, 1.0f);
- qalSourcef(curSource->alSource, AL_GAIN, curSource->curGain);
+ S_AL_Gain(curSource->alSource, curSource->curGain);
qalSourcefv(curSource->alSource, AL_POSITION, vec3_origin);
qalSourcefv(curSource->alSource, AL_VELOCITY, vec3_origin);
qalSourcei(curSource->alSource, AL_LOOPING, AL_FALSE);
@@ -1615,6 +1630,10 @@ static void S_AL_AllocateStreamChannel( int stream )
S_AL_SrcLock(streamSourceHandles[stream]);
streamSources[stream] = S_AL_SrcGet(streamSourceHandles[stream]);
+ // make sure that after unmuting the S_AL_Gain in S_Update() does not turn
+ // volume up prematurely for this source
+ srcList[streamSourceHandles[stream]].scaleGain = 0.0f;
+
// Set some streamSource parameters
qalSourcei (streamSources[stream], AL_BUFFER, 0 );
qalSourcei (streamSources[stream], AL_LOOPING, AL_FALSE );
@@ -1678,7 +1697,7 @@ void S_AL_RawSamples(int stream, int samples, int rate, int width, int channels,
qalSourceQueueBuffers(streamSources[stream], 1, &buffer);
// Volume
- qalSourcef (streamSources[stream], AL_GAIN, volume * s_volume->value * s_alGain->value);
+ S_AL_Gain (streamSources[stream], volume * s_volume->value * s_alGain->value);
}
/*
@@ -1792,6 +1811,10 @@ static void S_AL_MusicSourceGet( void )
S_AL_SrcLock(musicSourceHandle);
musicSource = S_AL_SrcGet(musicSourceHandle);
+ // make sure that after unmuting the S_AL_Gain in S_Update() does not turn
+ // volume up prematurely for this source
+ srcList[musicSourceHandle].scaleGain = 0.0f;
+
// Set some musicSource parameters
qalSource3f(musicSource, AL_POSITION, 0.0, 0.0, 0.0);
qalSource3f(musicSource, AL_VELOCITY, 0.0, 0.0, 0.0);
@@ -1995,7 +2018,7 @@ void S_AL_StartBackgroundTrack( const char *intro, const char *loop )
qalSourceQueueBuffers(musicSource, NUM_MUSIC_BUFFERS, musicBuffers);
// Set the initial gain property
- qalSourcef(musicSource, AL_GAIN, s_alGain->value * s_musicVolume->value);
+ S_AL_Gain(musicSource, s_alGain->value * s_musicVolume->value);
// Start playing
qalSourcePlay(musicSource);
@@ -2038,7 +2061,7 @@ void S_AL_MusicUpdate( void )
}
// Set the gain property
- qalSourcef(musicSource, AL_GAIN, s_alGain->value * s_musicVolume->value);
+ S_AL_Gain(musicSource, s_alGain->value * s_musicVolume->value);
}
@@ -2117,6 +2140,18 @@ void S_AL_Update( void )
{
int i;
+ if(s_muted->modified)
+ {
+ // muted state changed. Let S_AL_Gain turn up all sources again.
+ for(i = 0; i < srcCount; i++)
+ {
+ if(srcList[i].isActive)
+ S_AL_Gain(srcList[i].alSource, srcList[i].scaleGain);
+ }
+
+ s_muted->modified = qfalse;
+ }
+
// Update SFX channels
S_AL_SrcUpdate();
diff --git a/src/null/null_client.c b/src/null/null_client.c
index e7340804..419339da 100644
--- a/src/null/null_client.c
+++ b/src/null/null_client.c
@@ -86,4 +86,8 @@ void CL_FlushMemory( void ) {
void CL_StartHunkUsers( qboolean rendererOnly ) {
}
+void CL_Snd_Restart(void)
+{
+}
+
void CL_ShutdownAll(void) {}
diff --git a/src/qcommon/common.c b/src/qcommon/common.c
index ddd3c023..d1e702c6 100644
--- a/src/qcommon/common.c
+++ b/src/qcommon/common.c
@@ -92,8 +92,9 @@ int com_frameTime;
int com_frameMsec;
int com_frameNumber;
-qboolean com_errorEntered;
-qboolean com_fullyInitialized;
+qboolean com_errorEntered = qfalse;
+qboolean com_fullyInitialized = qfalse;
+qboolean com_gameRestarting = qfalse;
char com_errorMessage[MAXPRINTMSG];
@@ -244,9 +245,23 @@ void QDECL Com_Error( int code, const char *fmt, ... ) {
va_list argptr;
static int lastErrorTime;
static int errorCount;
+ static qboolean calledSysError = qfalse;
int currentTime;
- Cvar_Set( "com_errorCode", va( "%i", code ) );
+ if(com_errorEntered)
+ {
+ if(!calledSysError)
+ {
+ calledSysError = qtrue;
+ Sys_Error("recursive error after: %s", com_errorMessage);
+ }
+
+ return;
+ }
+
+ com_errorEntered = qtrue;
+
+ Cvar_Set("com_errorCode", va("%i", code));
// when we are running automated scripts, make sure we
// know if anything failed
@@ -265,11 +280,6 @@ void QDECL Com_Error( int code, const char *fmt, ... ) {
}
lastErrorTime = currentTime;
- if ( com_errorEntered ) {
- Sys_Error( "recursive error after: %s", com_errorMessage );
- }
- com_errorEntered = qtrue;
-
va_start (argptr,fmt);
Q_vsnprintf (com_errorMessage, sizeof(com_errorMessage),fmt,argptr);
va_end (argptr);
@@ -304,12 +314,13 @@ void QDECL Com_Error( int code, const char *fmt, ... ) {
VM_Forced_Unload_Start();
CL_FlushMemory( );
VM_Forced_Unload_Done();
- com_errorEntered = qfalse;
CL_CDDialog();
} else {
Com_Printf("Server didn't have CD\n" );
}
FS_PureServerSetLoadedPaks("", "");
+
+ com_errorEntered = qfalse;
longjmp (abortframe, -1);
} else {
CL_Shutdown ();
@@ -318,6 +329,7 @@ void QDECL Com_Error( int code, const char *fmt, ... ) {
Com_Shutdown ();
+ calledSysError = qtrue;
Sys_Error ("%s", com_errorMessage);
}
@@ -2363,15 +2375,7 @@ void Com_Setenv_f(void)
{
char *arg2 = Cmd_ArgsFrom(2);
-#ifdef _WIN32
- // windows already removes env variable if value is an empty string
- _putenv(va("%s=%s", arg1, arg2));
-#else
- if(!*arg2)
- unsetenv(arg1);
- else
- setenv(arg1, arg2, 1);
-#endif
+ Sys_SetEnv(arg1, arg2);
}
else if(argc == 2)
{
@@ -2384,6 +2388,85 @@ void Com_Setenv_f(void)
}
}
+/*
+==================
+Com_ExecuteCfg
+
+For controlling environment variables
+==================
+*/
+
+void Com_ExecuteCfg(void)
+{
+ Cbuf_ExecuteText(EXEC_NOW, "exec default.cfg\n");
+ Cbuf_Execute(); // Always execute after exec to prevent text buffer overflowing
+
+ if(!Com_SafeMode())
+ {
+ // skip the q3config.cfg and autoexec.cfg if "safe" is on the command line
+ Cbuf_ExecuteText(EXEC_NOW, "exec " Q3CONFIG_CFG "\n");
+ Cbuf_Execute();
+ Cbuf_ExecuteText(EXEC_NOW, "exec autoexec.cfg\n");
+ Cbuf_Execute();
+ }
+}
+
+/*
+==================
+Com_GameRestart
+
+Change to a new mod properly with cleaning up cvars before switching.
+==================
+*/
+
+void Com_GameRestart(int checksumFeed, qboolean clientRestart)
+{
+ // make sure no recursion can be triggered
+ if(!com_gameRestarting && com_fullyInitialized)
+ {
+ com_gameRestarting = qtrue;
+
+ if(clientRestart)
+ {
+ CL_Disconnect(qfalse);
+ CL_ShutdownAll();
+ }
+
+ // Kill server if we have one
+ if(com_sv_running->integer)
+ SV_Shutdown("Game directory changed");
+
+ FS_Restart(checksumFeed);
+
+ // Clean out any user and VM created cvars
+ Cvar_Restart(qtrue);
+ Com_ExecuteCfg();
+
+ // Restart sound subsystem so old handles are flushed
+ CL_Snd_Restart();
+
+ if(clientRestart)
+ CL_StartHunkUsers(qfalse);
+
+ com_gameRestarting = qfalse;
+ }
+}
+
+/*
+==================
+Com_GameRestart_f
+
+Expose possibility to change current running mod to the user
+==================
+*/
+
+void Com_GameRestart_f(void)
+{
+ Cvar_Set("fs_game", Cmd_Argv(1));
+
+ Com_GameRestart(0, qtrue);
+}
+
static void Com_DetectAltivec(void)
{
// Only detect if user hasn't forcibly disabled it.
@@ -2480,17 +2563,9 @@ void Com_Init( char *commandLine ) {
Cmd_AddCommand ("changeVectors", MSG_ReportChangeVectors_f );
Cmd_AddCommand ("writeconfig", Com_WriteConfig_f );
Cmd_SetCommandCompletionFunc( "writeconfig", Cmd_CompleteCfgName );
+ Cmd_AddCommand("game_restart", Com_GameRestart_f);
- // Make it execute the configuration files
- Cbuf_AddText ("exec default.cfg\n");
-
- // skip the autogen.cfg if "safe" is on the command line
- if (!Com_SafeMode())
- Cbuf_AddText("exec " Q3CONFIG_CFG "\n");
-
- Cbuf_AddText ("exec autoexec.cfg\n");
-
- Cbuf_Execute ();
+ Com_ExecuteCfg();
// override anything from the config files with command line args
Com_StartupVariable( NULL );
diff --git a/src/qcommon/cvar.c b/src/qcommon/cvar.c
index f82eb78f..459f602b 100644
--- a/src/qcommon/cvar.c
+++ b/src/qcommon/cvar.c
@@ -25,7 +25,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "q_shared.h"
#include "qcommon.h"
-cvar_t *cvar_vars;
+cvar_t *cvar_vars = NULL;
cvar_t *cvar_cheats;
int cvar_modifiedFlags;
@@ -34,7 +34,7 @@ cvar_t cvar_indexes[MAX_CVARS];
int cvar_numIndexes;
#define FILE_HASH_SIZE 256
-static cvar_t* hashTable[FILE_HASH_SIZE];
+static cvar_t *hashTable[FILE_HASH_SIZE];
cvar_t *Cvar_Set2( const char *var_name, const char *value, qboolean force);
@@ -182,11 +182,14 @@ int Cvar_Flags(const char *var_name)
Cvar_CommandCompletion
============
*/
-void Cvar_CommandCompletion( void(*callback)(const char *s) ) {
+void Cvar_CommandCompletion(void (*callback)(const char *s))
+{
cvar_t *cvar;
- for ( cvar = cvar_vars ; cvar ; cvar = cvar->next ) {
- callback( cvar->name );
+ for(cvar = cvar_vars; cvar; cvar = cvar->next)
+ {
+ if(cvar->name)
+ callback(cvar->name);
}
}
@@ -305,6 +308,7 @@ The flags will be or'ed in if the variable exists.
cvar_t *Cvar_Get( const char *var_name, const char *var_value, int flags ) {
cvar_t *var;
long hash;
+ int index;
if ( !var_name || ! var_value ) {
Com_Error( ERR_FATAL, "Cvar_Get: NULL parameter" );
@@ -323,13 +327,15 @@ cvar_t *Cvar_Get( const char *var_name, const char *var_value, int flags ) {
#endif
var = Cvar_FindVar (var_name);
- if ( var ) {
- var_value = Cvar_Validate( var, var_value, qfalse );
+
+ if(var)
+ {
+ var_value = Cvar_Validate(var, var_value, qfalse);
// if the C code is now specifying a variable that the user already
// set a value for, take the new value as the reset value
- if ( ( var->flags & CVAR_USER_CREATED ) && !( flags & CVAR_USER_CREATED )
- && var_value[0] ) {
+ if(var->flags & CVAR_USER_CREATED)
+ {
var->flags &= ~CVAR_USER_CREATED;
Z_Free( var->resetString );
var->resetString = CopyString( var_value );
@@ -344,13 +350,22 @@ cvar_t *Cvar_Get( const char *var_name, const char *var_value, int flags ) {
var->latchedString = CopyString(var_value);
}
-
- // ZOID--needs to be set so that cvars the game sets as
- // SERVERINFO get sent to clients
- cvar_modifiedFlags |= flags;
}
-
+
+ // Make sure the game code cannot mark engine-added variables as gamecode vars
+ if(var->flags & CVAR_VM_CREATED)
+ {
+ if(!(flags & CVAR_VM_CREATED))
+ var->flags &= ~CVAR_VM_CREATED;
+ }
+ else
+ {
+ if(flags & CVAR_VM_CREATED)
+ flags &= ~CVAR_VM_CREATED;
+ }
+
var->flags |= flags;
+
// only allow one non-empty reset string without a warning
if ( !var->resetString[0] ) {
// we don't have a reset string yet
@@ -368,6 +383,10 @@ cvar_t *Cvar_Get( const char *var_name, const char *var_value, int flags ) {
var->latchedString = NULL; // otherwise cvar_set2 would free it
Cvar_Set2( var_name, s, qtrue );
Z_Free( s );
+
+ // ZOID--needs to be set so that cvars the game sets as
+ // SERVERINFO get sent to clients
+ cvar_modifiedFlags |= flags;
}
return var;
@@ -376,11 +395,27 @@ cvar_t *Cvar_Get( const char *var_name, const char *var_value, int flags ) {
//
// allocate a new cvar
//
- if ( cvar_numIndexes >= MAX_CVARS ) {
- Com_Error( ERR_FATAL, "MAX_CVARS" );
+
+ // find a free cvar
+ for(index = 0; index < MAX_CVARS; index++)
+ {
+ if(!cvar_indexes[index].name)
+ break;
+ }
+
+ if(index >= MAX_CVARS)
+ {
+ if(!com_errorEntered)
+ Com_Error(ERR_FATAL, "Error: Too many cvars, cannot create a new one!");
+
+ return NULL;
}
- var = &cvar_indexes[cvar_numIndexes];
- cvar_numIndexes++;
+
+ var = &cvar_indexes[index];
+
+ if(index >= cvar_numIndexes)
+ cvar_numIndexes = index + 1;
+
var->name = CopyString (var_name);
var->string = CopyString (var_value);
var->modified = qtrue;
@@ -392,6 +427,10 @@ cvar_t *Cvar_Get( const char *var_name, const char *var_value, int flags ) {
// link the variable in
var->next = cvar_vars;
+ if(cvar_vars)
+ cvar_vars->prev = var;
+
+ var->prev = NULL;
cvar_vars = var;
var->flags = flags;
@@ -399,7 +438,13 @@ cvar_t *Cvar_Get( const char *var_name, const char *var_value, int flags ) {
cvar_modifiedFlags |= var->flags;
hash = generateHashValue(var_name);
+ var->hashIndex = hash;
+
var->hashNext = hashTable[hash];
+ if(hashTable[hash])
+ hashTable[hash]->hashPrev = var;
+
+ var->hashPrev = NULL;
hashTable[hash] = var;
return var;
@@ -471,15 +516,23 @@ cvar_t *Cvar_Set2( const char *var_name, const char *value, qboolean force ) {
value = var->resetString;
}
- value = Cvar_Validate( var, value, qtrue );
+ value = Cvar_Validate(var, value, qtrue);
- if((var->flags & CVAR_LATCH) && var->latchedString) {
- if(!strcmp(value,var->latchedString))
+ if((var->flags & CVAR_LATCH) && var->latchedString)
+ {
+ if(!strcmp(value, var->string))
+ {
+ Z_Free(var->latchedString);
+ var->latchedString = NULL;
+ return var;
+ }
+
+ if(!strcmp(value, var->latchedString))
return var;
}
- else if (!strcmp(value,var->string)) {
+ else if(!strcmp(value, var->string))
return var;
- }
+
// note what types of cvars have been modified (userinfo, archive, serverinfo, systeminfo)
cvar_modifiedFlags |= var->flags;
@@ -610,12 +663,15 @@ Cvar_SetCheatState
Any testing variables will be reset to the safe values
============
*/
-void Cvar_SetCheatState( void ) {
+void Cvar_SetCheatState(void)
+{
cvar_t *var;
// set all default vars to the safe value
- for ( var = cvar_vars ; var ; var = var->next ) {
- if ( var->flags & CVAR_CHEAT ) {
+ for(var = cvar_vars; var ; var = var->next)
+ {
+ if(var->flags & CVAR_CHEAT)
+ {
// the CVAR_LATCHED|CVAR_CHEAT vars might escape the reset here
// because of a different var->latchedString
if (var->latchedString)
@@ -623,9 +679,8 @@ void Cvar_SetCheatState( void ) {
Z_Free(var->latchedString);
var->latchedString = NULL;
}
- if (strcmp(var->resetString,var->string)) {
- Cvar_Set( var->name, var->resetString );
- }
+ if (strcmp(var->resetString,var->string))
+ Cvar_Set(var->name, var->resetString);
}
}
}
@@ -803,11 +858,16 @@ Appends lines containing "set variable value" for all variables
with the archive flag set to qtrue.
============
*/
-void Cvar_WriteVariables( fileHandle_t f ) {
+void Cvar_WriteVariables(fileHandle_t f)
+{
cvar_t *var;
char buffer[1024];
- for (var = cvar_vars ; var ; var = var->next) {
+ for (var = cvar_vars; var; var = var->next)
+ {
+ if(!var->name)
+ continue;
+
if( var->flags & CVAR_ARCHIVE ) {
// write the latched value, even if it hasn't taken effect yet
if ( var->latchedString ) {
@@ -849,7 +909,8 @@ void Cvar_List_f( void ) {
i = 0;
for (var = cvar_vars ; var ; var = var->next, i++)
{
- if (match && !Com_Filter(match, var->name, qfalse)) continue;
+ if(!var->name || (match && !Com_Filter(match, var->name, qfalse)))
+ continue;
if (var->flags & CVAR_SERVERINFO) {
Com_Printf("S");
@@ -906,74 +967,141 @@ void Cvar_List_f( void ) {
/*
============
-Cvar_Restart_f
+Cvar_Unset
-Resets all cvars to their hardcoded values
+Unsets a cvar
============
*/
-void Cvar_Restart_f( void ) {
- cvar_t *var;
- cvar_t **prev;
- prev = &cvar_vars;
- while ( 1 ) {
- var = *prev;
- if ( !var ) {
- break;
- }
+cvar_t *Cvar_Unset(cvar_t *cv)
+{
+ cvar_t *next = cv->next;
+
+ if(cv->name)
+ Z_Free(cv->name);
+ if(cv->string)
+ Z_Free(cv->string);
+ if(cv->latchedString)
+ Z_Free(cv->latchedString);
+ if(cv->resetString)
+ Z_Free(cv->resetString);
+
+ if(cv->prev)
+ cv->prev->next = cv->next;
+ else
+ cvar_vars = cv->next;
+ if(cv->next)
+ cv->next->prev = cv->prev;
- // don't mess with rom values, or some inter-module
- // communication will get broken (com_cl_running, etc)
- if ( var->flags & ( CVAR_ROM | CVAR_INIT | CVAR_NORESTART ) ) {
- prev = &var->next;
- continue;
- }
+ if(cv->hashPrev)
+ cv->hashPrev->hashNext = cv->hashNext;
+ else
+ hashTable[cv->hashIndex] = cv->hashNext;
+ if(cv->hashNext)
+ cv->hashNext->hashPrev = cv->hashPrev;
- // throw out any variables the user created
- if ( var->flags & CVAR_USER_CREATED ) {
- *prev = var->next;
- if ( var->name ) {
- Z_Free( var->name );
- }
- if ( var->string ) {
- Z_Free( var->string );
- }
- if ( var->latchedString ) {
- Z_Free( var->latchedString );
- }
- if ( var->resetString ) {
- Z_Free( var->resetString );
- }
- // clear the var completely, since we
- // can't remove the index from the list
- Com_Memset( var, 0, sizeof( var ) );
- continue;
- }
+ Com_Memset(cv, '\0', sizeof(*cv));
+
+ return next;
+}
- Cvar_Set( var->name, var->resetString );
+/*
+============
+Cvar_Unset_f
+
+Unsets a userdefined cvar
+============
+*/
- prev = &var->next;
+void Cvar_Unset_f(void)
+{
+ cvar_t *cv;
+
+ if(Cmd_Argc() != 2)
+ {
+ Com_Printf("Usage: %s <varname>\n", Cmd_Argv(0));
+ return;
}
+
+ cv = Cvar_FindVar(Cmd_Argv(1));
+
+ if(!cv)
+ return;
+
+ if(cv->flags & CVAR_USER_CREATED)
+ Cvar_Unset(cv);
+ else
+ Com_Printf("Error: %s: Variable %s is not user created.\n", Cmd_Argv(0), cv->name);
}
/*
+============
+Cvar_Restart
+
+Resets all cvars to their hardcoded values and removes userdefined variables
+and variables added via the VMs if requested.
+============
+*/
+
+void Cvar_Restart(qboolean unsetVM)
+{
+ cvar_t *curvar;
+
+ curvar = cvar_vars;
+
+ while(curvar)
+ {
+ if((curvar->flags & CVAR_USER_CREATED) ||
+ (unsetVM && (curvar->flags & CVAR_VM_CREATED)))
+ {
+ // throw out any variables the user/vm created
+ curvar = Cvar_Unset(curvar);
+ continue;
+ }
+
+ if(!(curvar->flags & (CVAR_ROM | CVAR_INIT | CVAR_NORESTART)))
+ {
+ // Just reset the rest to their default values.
+ Cvar_Set2(curvar->name, curvar->resetString, qfalse);
+ }
+
+ curvar = curvar->next;
+ }
+}
+
+
+/*
+============
+Cvar_Restart_f
+
+Resets all cvars to their hardcoded values
+============
+*/
+void Cvar_Restart_f(void)
+{
+ Cvar_Restart(qfalse);
+}
+
+/*
=====================
Cvar_InfoString
=====================
*/
-char *Cvar_InfoString( int bit ) {
+char *Cvar_InfoString(int bit)
+{
static char info[MAX_INFO_STRING];
cvar_t *var;
info[0] = 0;
- for (var = cvar_vars ; var ; var = var->next) {
- if (var->flags & bit) {
+ for(var = cvar_vars; var; var = var->next)
+ {
+ if(var->name && (var->flags & bit))
Info_SetValueForKey (info, var->name, var->string);
- }
}
+
return info;
}
@@ -984,16 +1112,17 @@ Cvar_InfoString_Big
handles large info strings ( CS_SYSTEMINFO )
=====================
*/
-char *Cvar_InfoString_Big( int bit ) {
+char *Cvar_InfoString_Big(int bit)
+{
static char info[BIG_INFO_STRING];
cvar_t *var;
info[0] = 0;
- for (var = cvar_vars ; var ; var = var->next) {
- if (var->flags & bit) {
+ for (var = cvar_vars; var; var = var->next)
+ {
+ if(var->name && (var->flags & bit))
Info_SetValueForKey_Big (info, var->name, var->string);
- }
}
return info;
}
@@ -1032,13 +1161,15 @@ Cvar_Register
basically a slightly modified Cvar_Get for the interpreted modules
=====================
*/
-void Cvar_Register( vmCvar_t *vmCvar, const char *varName, const char *defaultValue, int flags ) {
+void Cvar_Register(vmCvar_t *vmCvar, const char *varName, const char *defaultValue, int flags)
+{
cvar_t *cv;
- cv = Cvar_Get( varName, defaultValue, flags );
- if ( !vmCvar ) {
+ cv = Cvar_Get(varName, defaultValue, flags | CVAR_VM_CREATED);
+
+ if (!vmCvar)
return;
- }
+
vmCvar->handle = cv - cvar_indexes;
vmCvar->modificationCount = -1;
Cvar_Update( vmCvar );
@@ -1103,7 +1234,11 @@ Cvar_Init
Reads in all archived cvars
============
*/
-void Cvar_Init (void) {
+void Cvar_Init (void)
+{
+ Com_Memset(cvar_indexes, '\0', sizeof(cvar_indexes));
+ Com_Memset(hashTable, '\0', sizeof(hashTable));
+
cvar_cheats = Cvar_Get("sv_cheats", "1", CVAR_ROM | CVAR_SYSTEMINFO );
Cmd_AddCommand ("print", Cvar_Print_f);
@@ -1119,6 +1254,9 @@ void Cvar_Init (void) {
Cmd_SetCommandCompletionFunc( "seta", Cvar_CompleteCvarName );
Cmd_AddCommand ("reset", Cvar_Reset_f);
Cmd_SetCommandCompletionFunc( "reset", Cvar_CompleteCvarName );
+ Cmd_AddCommand ("unset", Cvar_Unset_f);
+ Cmd_SetCommandCompletionFunc("unset", Cvar_CompleteCvarName);
+
Cmd_AddCommand ("cvarlist", Cvar_List_f);
Cmd_AddCommand ("cvar_restart", Cvar_Restart_f);
}
diff --git a/src/qcommon/files.c b/src/qcommon/files.c
index 87301441..bb1f3f15 100644
--- a/src/qcommon/files.c
+++ b/src/qcommon/files.c
@@ -249,7 +249,7 @@ static searchpath_t *fs_searchpaths;
static int fs_readCount; // total bytes read
static int fs_loadCount; // total files read
static int fs_loadStack; // total files in memory
-static int fs_packFiles; // total number of files in packs
+static int fs_packFiles = 0; // total number of files in packs
static int fs_checksumFeed;
@@ -281,7 +281,7 @@ static fileHandleData_t fsh[MAX_FILE_HANDLES];
static qboolean fs_reordered;
// never load anything from pk3 files that are not present at the server when pure
-static int fs_numServerPaks;
+static int fs_numServerPaks = 0;
static int fs_serverPaks[MAX_SEARCH_PATHS]; // checksums
static char *fs_serverPakNames[MAX_SEARCH_PATHS]; // pk3 names
@@ -438,10 +438,18 @@ Fix things up differently for win/unix/mac
*/
static void FS_ReplaceSeparators( char *path ) {
char *s;
+ qboolean lastCharWasSep = qfalse;
for ( s = path ; *s ; s++ ) {
if ( *s == '/' || *s == '\\' ) {
- *s = PATH_SEP;
+ if ( !lastCharWasSep ) {
+ *s = PATH_SEP;
+ lastCharWasSep = qtrue;
+ } else {
+ memmove (s, s + 1, strlen (s));
+ }
+ } else {
+ lastCharWasSep = qfalse;
}
}
}
@@ -465,7 +473,7 @@ char *FS_BuildOSPath( const char *base, const char *game, const char *qpath ) {
}
Com_sprintf( temp, sizeof(temp), "/%s/%s", game, qpath );
- FS_ReplaceSeparators( temp );
+ FS_ReplaceSeparators( temp );
Com_sprintf( ospath[toggle], sizeof( ospath[0] ), "%s%s", base, temp );
return ospath[toggle];
@@ -481,6 +489,7 @@ Creates any directories needed to store the given filename
*/
qboolean FS_CreatePath (char *OSPath) {
char *ofs;
+ char path[MAX_OSPATH];
// make absolutely sure that it can't back up the path
// FIXME: is c: allowed???
@@ -489,14 +498,25 @@ qboolean FS_CreatePath (char *OSPath) {
return qtrue;
}
- for (ofs = OSPath+1 ; *ofs ; ofs++) {
- if (*ofs == PATH_SEP) {
+ Q_strncpyz( path, OSPath, sizeof( path ) );
+ FS_ReplaceSeparators( path );
+
+ // Skip creation of the root directory as it will always be there
+ ofs = strchr( path, PATH_SEP );
+ ofs++;
+
+ for (; ofs != NULL && *ofs ; ofs++) {
+ if (*ofs == PATH_SEP) {
// create the directory
*ofs = 0;
- Sys_Mkdir (OSPath);
+ if (!Sys_Mkdir (path)) {
+ Com_Error( ERR_FATAL, "FS_CreatePath: failed to create path \"%s\"\n",
+ path );
+ }
*ofs = PATH_SEP;
}
}
+
return qfalse;
}
@@ -2839,6 +2859,8 @@ static void FS_Startup( const char *gameName )
Com_Printf( "----- FS_Startup -----\n" );
+ fs_packFiles = 0;
+
fs_debug = Cvar_Get( "fs_debug", "0", 0 );
fs_basepath = Cvar_Get ("fs_basepath", Sys_DefaultInstallPath(), CVAR_INIT );
fs_basegame = Cvar_Get ("fs_basegame", "", CVAR_INIT );
@@ -2864,11 +2886,12 @@ static void FS_Startup( const char *gameName )
// NOTE: same filtering below for mods and basegame
if (fs_homepath->string[0] && Q_stricmp(fs_homepath->string,fs_basepath->string)) {
+ FS_CreatePath ( fs_homepath->string );
FS_AddGameDirectory ( fs_homepath->string, gameName );
}
// check for additional base game so mods can be based upon other mods
- if ( fs_basegame->string[0] && !Q_stricmp( gameName, BASEGAME ) && Q_stricmp( fs_basegame->string, gameName ) ) {
+ if ( fs_basegame->string[0] && Q_stricmp( fs_basegame->string, gameName ) ) {
if (fs_basepath->string[0]) {
FS_AddGameDirectory(fs_basepath->string, fs_basegame->string);
}
@@ -2878,7 +2901,7 @@ static void FS_Startup( const char *gameName )
}
// check for additional game folder for mods
- if ( fs_gamedirvar->string[0] && !Q_stricmp( gameName, BASEGAME ) && Q_stricmp( fs_gamedirvar->string, gameName ) ) {
+ if ( fs_gamedirvar->string[0] && Q_stricmp( fs_gamedirvar->string, gameName ) ) {
if (fs_basepath->string[0]) {
FS_AddGameDirectory(fs_basepath->string, fs_gamedirvar->string);
}
@@ -3348,11 +3371,20 @@ FS_ConditionalRestart
restart if necessary
=================
*/
-qboolean FS_ConditionalRestart( int checksumFeed ) {
- if( fs_gamedirvar->modified || checksumFeed != fs_checksumFeed ) {
- FS_Restart( checksumFeed );
+qboolean FS_ConditionalRestart(int checksumFeed)
+{
+ if(fs_gamedirvar->modified)
+ {
+ Com_GameRestart(checksumFeed, qfalse);
return qtrue;
}
+
+ else if(checksumFeed != fs_checksumFeed)
+ {
+ FS_Restart(checksumFeed);
+ return qtrue;
+ }
+
return qfalse;
}
diff --git a/src/qcommon/net_ip.c b/src/qcommon/net_ip.c
index 9ad4a821..db9f2924 100644
--- a/src/qcommon/net_ip.c
+++ b/src/qcommon/net_ip.c
@@ -995,7 +995,7 @@ void NET_SetMulticast6(void)
if(*net_mcast6iface->string)
{
#ifdef _WIN32
- curgroup.ipv6mr_interface = atoi(net_mcast6iface->string);
+ curgroup.ipv6mr_interface = net_mcast6iface->integer;
#else
curgroup.ipv6mr_interface = if_nametoindex(net_mcast6iface->string);
#endif
@@ -1470,7 +1470,11 @@ static qboolean NET_GetCvars( void ) {
modified += net_mcast6addr->modified;
net_mcast6addr->modified = qfalse;
+#ifdef _WIN32
net_mcast6iface = Cvar_Get( "net_mcast6iface", "0", CVAR_LATCH | CVAR_ARCHIVE );
+#else
+ net_mcast6iface = Cvar_Get( "net_mcast6iface", "", CVAR_LATCH | CVAR_ARCHIVE );
+#endif
modified += net_mcast6iface->modified;
net_mcast6iface->modified = qfalse;
diff --git a/src/qcommon/q_shared.h b/src/qcommon/q_shared.h
index 29cc4b9b..186bb461 100644
--- a/src/qcommon/q_shared.h
+++ b/src/qcommon/q_shared.h
@@ -863,30 +863,33 @@ default values.
==========================================================
*/
-#define CVAR_ARCHIVE 1 // set to cause it to be saved to vars.rc
- // used for system variables, not for player
- // specific configurations
-#define CVAR_USERINFO 2 // sent to server on connect or change
-#define CVAR_SERVERINFO 4 // sent in response to front end requests
-#define CVAR_SYSTEMINFO 8 // these cvars will be duplicated on all clients
-#define CVAR_INIT 16 // don't allow change from console at all,
- // but can be set from the command line
-#define CVAR_LATCH 32 // will only change when C code next does
- // a Cvar_Get(), so it can't be changed
- // without proper initialization. modified
- // will be set, even though the value hasn't
- // changed yet
-#define CVAR_ROM 64 // display only, cannot be set by user at all
-#define CVAR_USER_CREATED 128 // created by a set command
-#define CVAR_TEMP 256 // can be set even when cheats are disabled, but is not archived
-#define CVAR_CHEAT 512 // can not be changed if cheats are disabled
-#define CVAR_NORESTART 1024 // do not clear when a cvar_restart is issued
-
-#define CVAR_SERVER_CREATED 2048 // cvar was created by a server the client connected to.
+#define CVAR_ARCHIVE 0x0001 // set to cause it to be saved to vars.rc
+ // used for system variables, not for player
+ // specific configurations
+#define CVAR_USERINFO 0x0002 // sent to server on connect or change
+#define CVAR_SERVERINFO 0x0004 // sent in response to front end requests
+#define CVAR_SYSTEMINFO 0x0008 // these cvars will be duplicated on all clients
+#define CVAR_INIT 0x0010 // don't allow change from console at all,
+ // but can be set from the command line
+#define CVAR_LATCH 0x0020 // will only change when C code next does
+ // a Cvar_Get(), so it can't be changed
+ // without proper initialization. modified
+ // will be set, even though the value hasn't
+ // changed yet
+#define CVAR_ROM 0x0040 // display only, cannot be set by user at all
+#define CVAR_USER_CREATED 0x0080 // created by a set command
+#define CVAR_TEMP 0x0100 // can be set even when cheats are disabled, but is not archived
+#define CVAR_CHEAT 0x0200 // can not be changed if cheats are disabled
+#define CVAR_NORESTART 0x0400 // do not clear when a cvar_restart is issued
+
+#define CVAR_SERVER_CREATED 0x0800 // cvar was created by a server the client connected to.
+#define CVAR_VM_CREATED 0x1000 // cvar was created exclusively in one of the VMs.
#define CVAR_NONEXISTENT 0xFFFFFFFF // Cvar doesn't exist.
// nothing outside the Cvar_*() functions should modify these fields!
-typedef struct cvar_s {
+typedef struct cvar_s cvar_t;
+
+struct cvar_s {
char *name;
char *string;
char *resetString; // cvar_restart will reset to this value
@@ -900,9 +903,13 @@ typedef struct cvar_s {
qboolean integral;
float min;
float max;
- struct cvar_s *next;
- struct cvar_s *hashNext;
-} cvar_t;
+
+ cvar_t *next;
+ cvar_t *prev;
+ cvar_t *hashNext;
+ cvar_t *hashPrev;
+ int hashIndex;
+};
#define MAX_CVAR_VALUE_STRING 256
diff --git a/src/qcommon/qcommon.h b/src/qcommon/qcommon.h
index 1f9e744d..690e89c6 100644
--- a/src/qcommon/qcommon.h
+++ b/src/qcommon/qcommon.h
@@ -534,6 +534,7 @@ char *Cvar_InfoString_Big( int bit );
void Cvar_InfoStringBuffer( int bit, char *buff, int buffsize );
void Cvar_CheckRange( cvar_t *cv, float minVal, float maxVal, qboolean shouldBeIntegral );
+void Cvar_Restart(qboolean unsetVM);
void Cvar_Restart_f( void );
void Cvar_CompleteCvarName( char *args, int argNum );
@@ -784,6 +785,7 @@ void QDECL Com_Printf( const char *fmt, ... ) __attribute__ ((format (printf,
void QDECL Com_DPrintf( const char *fmt, ... ) __attribute__ ((format (printf, 1, 2)));
void QDECL Com_Error( int code, const char *fmt, ... ) __attribute__ ((format (printf, 2, 3)));
void Com_Quit_f( void );
+void Com_GameRestart(int checksumFeed, qboolean clientRestart);
int Com_Milliseconds( void ); // will be journaled properly
unsigned Com_BlockChecksum( const void *buffer, int length );
@@ -961,6 +963,9 @@ void CL_FlushMemory( void );
void CL_StartHunkUsers( qboolean rendererOnly );
// start all the client stuff using the hunk
+void CL_Snd_Restart(void);
+// Restart sound subsystem
+
void Key_KeynameCompletion( void(*callback)(const char *s) );
// for keyname autocompletion
@@ -1057,7 +1062,7 @@ qboolean Sys_StringToAdr( const char *s, netadr_t *a, netadrtype_t family );
qboolean Sys_IsLANAddress (netadr_t adr);
void Sys_ShowIP(void);
-void Sys_Mkdir( const char *path );
+qboolean Sys_Mkdir( const char *path );
char *Sys_Cwd( void );
void Sys_SetDefaultInstallPath(const char *path);
char *Sys_DefaultInstallPath(void);
@@ -1078,6 +1083,8 @@ void Sys_Sleep(int msec);
qboolean Sys_LowPhysicalMemory( void );
+void Sys_SetEnv(const char *name, const char *value);
+
/* This is based on the Adaptive Huffman algorithm described in Sayood's Data
* Compression book. The ranks are not actually stored, but implicitly defined
* by the location of a node within a doubly-linked list */
diff --git a/src/qcommon/vm.c b/src/qcommon/vm.c
index 876d36d5..5956c89a 100644
--- a/src/qcommon/vm.c
+++ b/src/qcommon/vm.c
@@ -246,7 +246,7 @@ void VM_LoadSymbols( vm_t *vm ) {
return;
}
- numInstructions = vm->instructionPointersLength >> 2;
+ numInstructions = vm->instructionCount;
// parse the symbols
text_p = mapfile.c;
@@ -358,8 +358,6 @@ intptr_t QDECL VM_DllSyscall( intptr_t arg, ... ) {
}
-#define STACK_SIZE 0x20000
-
/*
=================
VM_LoadQVM
@@ -431,7 +429,7 @@ vmHeader_t *VM_LoadQVM( vm_t *vm, qboolean alloc ) {
// round up to next power of 2 so all data operations can
// be mask protected
dataLength = header.h->dataLength + header.h->litLength +
- header.h->bssLength + STACK_SIZE;
+ header.h->bssLength;
for ( i = 0 ; dataLength > ( 1 << i ) ; i++ ) {
}
dataLength = 1 << i;
@@ -577,8 +575,8 @@ vm_t *VM_Create( const char *module, intptr_t (*systemCalls)(intptr_t *),
}
// allocate space for the jump targets, which will be filled in by the compile/prep functions
- vm->instructionPointersLength = header->instructionCount * 4;
- vm->instructionPointers = Hunk_Alloc( vm->instructionPointersLength, h_high );
+ vm->instructionCount = header->instructionCount;
+ vm->instructionPointers = Hunk_Alloc( vm->instructionCount*4, h_high );
// copy or compile the instructions
vm->codeLength = header->codeLength;
@@ -610,7 +608,7 @@ vm_t *VM_Create( const char *module, intptr_t (*systemCalls)(intptr_t *),
// the stack is implicitly at the end of the image
vm->programStack = vm->dataMask + 1;
- vm->stackBottom = vm->programStack - STACK_SIZE;
+ vm->stackBottom = vm->programStack - PROGRAM_STACK_SIZE;
Com_Printf("%s loaded in %d bytes on the hunk\n", module, remaining - Hunk_MemoryRemaining());
@@ -734,8 +732,6 @@ an OP_ENTER instruction, which will subtract space for
locals from sp
==============
*/
-#define MAX_STACK 256
-#define STACK_MASK (MAX_STACK-1)
intptr_t QDECL VM_Call( vm_t *vm, int callnum, ... ) {
vm_t *oldVM;
@@ -896,7 +892,7 @@ void VM_VmInfo_f( void ) {
Com_Printf( "interpreted\n" );
}
Com_Printf( " code length : %7i\n", vm->codeLength );
- Com_Printf( " table length: %7i\n", vm->instructionPointersLength );
+ Com_Printf( " table length: %7i\n", vm->instructionCount*4 );
Com_Printf( " data length : %7i\n", vm->dataMask + 1 );
}
}
diff --git a/src/qcommon/vm_interpreted.c b/src/qcommon/vm_interpreted.c
index cb6ae2f2..5f755623 100644
--- a/src/qcommon/vm_interpreted.c
+++ b/src/qcommon/vm_interpreted.c
@@ -312,13 +312,11 @@ an OP_ENTER instruction, which will subtract space for
locals from sp
==============
*/
-#define MAX_STACK 256
-#define STACK_MASK (MAX_STACK-1)
#define DEBUGSTR va("%s%i", VM_Indent(vm), opStack-stack )
int VM_CallInterpreted( vm_t *vm, int *args ) {
- int stack[MAX_STACK];
+ int stack[OPSTACK_SIZE];
int *opStack;
int programCounter;
int programStack;
@@ -393,7 +391,7 @@ nextInstruction2:
if ( opStack < stack ) {
Com_Error( ERR_DROP, "VM opStack underflow" );
}
- if ( opStack >= stack+MAX_STACK ) {
+ if ( opStack >= stack+OPSTACK_SIZE ) {
Com_Error( ERR_DROP, "VM opStack overflow" );
}
@@ -441,10 +439,10 @@ nextInstruction2:
Com_Error( ERR_DROP, "OP_LOAD4 misaligned" );
}
#endif
- r0 = *opStack = *(int *)&image[ r0&dataMask ];
+ r0 = *opStack = *(int *)&image[ r0&dataMask&~3 ];
goto nextInstruction2;
case OP_LOAD2:
- r0 = *opStack = *(unsigned short *)&image[ r0&dataMask ];
+ r0 = *opStack = *(unsigned short *)&image[ r0&dataMask&~1 ];
goto nextInstruction2;
case OP_LOAD1:
r0 = *opStack = image[ r0&dataMask ];
@@ -465,7 +463,7 @@ nextInstruction2:
case OP_ARG:
// single byte offset from programStack
- *(int *)&image[ codeImage[programCounter] + programStack ] = r0;
+ *(int *)&image[ (codeImage[programCounter] + programStack)&dataMask&~3 ] = r0;
opStack--;
programCounter += 1;
goto nextInstruction;
@@ -549,7 +547,7 @@ nextInstruction2:
Com_Printf( "%s<--- %s\n", DEBUGSTR, VM_ValueToSymbol( vm, programCounter ) );
}
#endif
- } else if ( (unsigned)programCounter >= vm->codeLength ) {
+ } else if ( (unsigned)programCounter >= vm->instructionCount ) {
Com_Error( ERR_DROP, "VM program counter out of range in OP_CALL" );
} else {
programCounter = vm->instructionPointers[ programCounter ];
@@ -618,8 +616,11 @@ nextInstruction2:
*/
case OP_JUMP:
- programCounter = r0;
- programCounter = vm->instructionPointers[ programCounter ];
+ if ( (unsigned)r0 >= vm->instructionCount )
+ Com_Error( ERR_DROP, "VM program counter out of range in OP_JUMP" );
+
+ programCounter = vm->instructionPointers[ r0 ];
+
opStack--;
goto nextInstruction;
diff --git a/src/qcommon/vm_local.h b/src/qcommon/vm_local.h
index e1545d37..75ffee55 100644
--- a/src/qcommon/vm_local.h
+++ b/src/qcommon/vm_local.h
@@ -23,6 +23,14 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "q_shared.h"
#include "qcommon.h"
+#define OPSTACK_SIZE 256
+#define OPSTACK_MASK (OPSTACK_SIZE-1)
+
+// don't change
+// Hardcoded in q3asm an reserved at end of bss
+#define PROGRAM_STACK_SIZE 0x10000
+#define PROGRAM_STACK_MASK (PROGRAM_STACK_SIZE-1)
+
typedef enum {
OP_UNDEF,
@@ -147,7 +155,7 @@ struct vm_s {
int codeLength;
int *instructionPointers;
- int instructionPointersLength;
+ int instructionCount;
byte *dataBase;
int dataMask;
@@ -181,4 +189,3 @@ vmSymbol_t *VM_ValueToFunctionSymbol( vm_t *vm, int value );
int VM_SymbolToValue( vm_t *vm, const char *symbol );
const char *VM_ValueToSymbol( vm_t *vm, int value );
void VM_LogSyscalls( int *args );
-
diff --git a/src/qcommon/vm_x86_64.c b/src/qcommon/vm_x86_64.c
index 02e7bf9c..3f950b2a 100644
--- a/src/qcommon/vm_x86_64.c
+++ b/src/qcommon/vm_x86_64.c
@@ -229,12 +229,47 @@ void emit(const char* fmt, ...)
assemble_line(line, strlen(line));
}
+#define CHECK_INSTR_REG(reg) \
+ emit("cmpl $%u, %%"#reg, header->instructionCount); \
+ emit("jb jmp_ok_i_%08x", instruction); \
+ emit("movq $%lu, %%rax", (unsigned long)jmpviolation); \
+ emit("callq *%%rax"); \
+ emit("jmp_ok_i_%08x:", instruction);
+
+#define PREPARE_JMP(reg) \
+ CHECK_INSTR_REG(reg) \
+ emit("movq $%lu, %%rbx", (unsigned long)vm->instructionPointers); \
+ emit("movl (%%rbx, %%rax, 4), %%eax"); \
+ emit("addq %%r10, %%rax");
+
+#define CHECK_INSTR(nr) \
+ do { if(nr < 0 || nr >= header->instructionCount) { \
+ Com_Error( ERR_DROP, \
+ "%s: jump target 0x%x out of range at offset %d", __func__, nr, pc ); \
+ } } while(0)
+
#define JMPIARG \
+ CHECK_INSTR(iarg); \
emit("movq $%lu, %%rax", vm->codeBase+vm->instructionPointers[iarg]); \
emit("jmpq *%%rax");
+#define CONST_OPTIMIZE
+#ifdef CONST_OPTIMIZE
+#define MAYBE_EMIT_CONST() \
+ if (got_const) \
+ { \
+ got_const = 0; \
+ vm->instructionPointers[instruction-1] = assembler_get_code_size(); \
+ emit("addq $4, %%rsi"); \
+ emit("movl $%d, 0(%%rsi)", const_value); \
+ }
+#else
+#define MAYBE_EMIT_CONST()
+#endif
+
// integer compare and jump
#define IJ(op) \
+ MAYBE_EMIT_CONST(); \
emit("subq $8, %%rsi"); \
emit("movl 4(%%rsi), %%eax"); \
emit("cmpl 8(%%rsi), %%eax"); \
@@ -244,6 +279,7 @@ void emit(const char* fmt, ...)
#ifdef USE_X87
#define FJ(bits, op) \
+ MAYBE_EMIT_CONST(); \
emit("subq $8, %%rsi");\
emit("flds 4(%%rsi)");\
emit("fcomps 8(%%rsi)");\
@@ -256,6 +292,7 @@ void emit(const char* fmt, ...)
#else
#define FJ(x, y)
#define XJ(op) \
+ MAYBE_EMIT_CONST(); \
emit("subq $8, %%rsi");\
emit("movss 4(%%rsi), %%xmm0");\
emit("ucomiss 8(%%rsi), %%xmm0");\
@@ -266,12 +303,14 @@ void emit(const char* fmt, ...)
#endif
#define SIMPLE(op) \
+ MAYBE_EMIT_CONST(); \
emit("subq $4, %%rsi"); \
emit("movl 4(%%rsi), %%eax"); \
emit(op " %%eax, 0(%%rsi)");
#ifdef USE_X87
#define FSIMPLE(op) \
+ MAYBE_EMIT_CONST(); \
emit("subq $4, %%rsi"); \
emit("flds 0(%%rsi)"); \
emit(op " 4(%%rsi)"); \
@@ -280,6 +319,7 @@ void emit(const char* fmt, ...)
#else
#define FSIMPLE(op)
#define XSIMPLE(op) \
+ MAYBE_EMIT_CONST(); \
emit("subq $4, %%rsi"); \
emit("movss 0(%%rsi), %%xmm0"); \
emit(op " 4(%%rsi), %%xmm0"); \
@@ -287,26 +327,28 @@ void emit(const char* fmt, ...)
#endif
#define SHIFT(op) \
+ MAYBE_EMIT_CONST(); \
emit("subq $4, %%rsi"); \
emit("movl 4(%%rsi), %%ecx"); \
emit("movl 0(%%rsi), %%eax"); \
emit(op " %%cl, %%eax"); \
emit("movl %%eax, 0(%%rsi)");
-#if 1
-#define RANGECHECK(reg) \
- emit("andl $0x%x, %%" #reg, vm->dataMask);
-#elif 0
-#define RANGECHECK(reg) \
- emit("pushl %%" #reg); \
- emit("andl $0x%x, %%" #reg, ~vm->dataMask); \
- emit("jz rangecheck_ok_i_%08x", instruction); \
- emit("int3"); \
- emit("rangecheck_ok_i_%08x:", instruction); \
- emit("popl %%" #reg); \
- emit("andl $0x%x, %%" #reg, vm->dataMask);
+#ifdef DEBUG_VM
+#define RANGECHECK(reg, bytes) \
+ emit("movl %%" #reg ", %%ecx"); \
+ emit("andl $0x%x, %%ecx", vm->dataMask &~(bytes-1)); \
+ emit("cmpl %%" #reg ", %%ecx"); \
+ emit("jz rc_ok_i_%08x", instruction); \
+ emit("movq $%lu, %%rax", (unsigned long)memviolation); \
+ emit("callq *%%rax"); \
+ emit("rc_ok_i_%08x:", instruction);
+#elif 1
+// check is too expensive, so just confine memory access
+#define RANGECHECK(reg, bytes) \
+ emit("andl $0x%x, %%" #reg, vm->dataMask &~(bytes-1));
#else
-#define RANGECHECK(reg)
+#define RANGECHECK(reg, bytes)
#endif
#ifdef DEBUG_VM
@@ -337,6 +379,26 @@ static void block_copy_vm(unsigned dest, unsigned src, unsigned count)
memcpy(currentVM->dataBase+dest, currentVM->dataBase+src, count);
}
+static void eop(void)
+{
+ Com_Error(ERR_DROP, "end of program reached without return!\n");
+ exit(1);
+}
+
+static void jmpviolation(void)
+{
+ Com_Error(ERR_DROP, "program tried to execute code outside VM\n");
+ exit(1);
+}
+
+#ifdef DEBUG_VM
+static void memviolation(void)
+{
+ Com_Error(ERR_DROP, "program tried to access memory outside VM\n");
+ exit(1);
+}
+#endif
+
/*
=================
VM_Compile
@@ -358,6 +420,9 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {
int pass;
size_t compiledOfs = 0;
+ // const optimization
+ unsigned got_const = 0, const_value = 0;
+
gettimeofday(&tvstart, NULL);
for (pass = 0; pass < 2; ++pass) {
@@ -394,7 +459,7 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {
vm->instructionPointers[instruction] = assembler_get_code_size();
/* store current instruction number in r15 for debugging */
-#if DEBUG_VM
+#if DEBUG_VM0
emit("nop");
emit("movq $%d, %%r15", instruction);
emit("nop");
@@ -428,31 +493,52 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {
NOTIMPL(op);
break;
case OP_IGNORE:
+ MAYBE_EMIT_CONST();
emit("nop");
break;
case OP_BREAK:
+ MAYBE_EMIT_CONST();
emit("int3");
break;
case OP_ENTER:
+ MAYBE_EMIT_CONST();
emit("subl $%d, %%edi", iarg);
- RANGECHECK(edi);
break;
case OP_LEAVE:
+ MAYBE_EMIT_CONST();
emit("addl $%d, %%edi", iarg); // get rid of stack frame
emit("ret");
break;
case OP_CALL:
- emit("movl 0(%%rsi), %%eax"); // get instr from stack
- emit("subq $4, %%rsi");
+ RANGECHECK(edi, 4);
emit("movl $%d, 0(%%r8, %%rdi, 1)", instruction+1); // save next instruction
- emit("orl %%eax, %%eax");
- emit("jl callSyscall%d", instruction);
- emit("movq $%lu, %%rbx", (unsigned long)vm->instructionPointers);
- emit("movl (%%rbx, %%rax, 4), %%eax"); // load new relative jump address
- emit("addq %%r10, %%rax");
- emit("callq *%%rax");
- emit("jmp i_%08x", instruction+1);
- emit("callSyscall%d:", instruction);
+ if(got_const)
+ {
+ if ((int)const_value < 0)
+ goto emit_do_syscall;
+
+ CHECK_INSTR(const_value);
+ emit("movq $%lu, %%rax", vm->codeBase+vm->instructionPointers[const_value]);
+ emit("callq *%%rax");
+ got_const = 0;
+ break;
+ }
+ else
+ {
+ MAYBE_EMIT_CONST();
+ emit("movl 0(%%rsi), %%eax"); // get instr from stack
+ emit("subq $4, %%rsi");
+
+ emit("orl %%eax, %%eax");
+ emit("jl callSyscall%d", instruction);
+
+ PREPARE_JMP(eax);
+ emit("callq *%%rax");
+
+ emit("jmp i_%08x", instruction+1);
+ emit("callSyscall%d:", instruction);
+ }
+emit_do_syscall:
// emit("fnsave 4(%%rsi)");
emit("push %%rsi");
emit("push %%rdi");
@@ -464,10 +550,15 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {
emit("andq $127, %%rbx"); // |
emit("subq %%rbx, %%rsp"); // <-+
emit("push %%rbx");
- emit("negl %%eax"); // convert to actual number
- emit("decl %%eax");
- // first argument already in rdi
- emit("movq %%rax, %%rsi"); // second argument in rsi
+ if(got_const) {
+ got_const = 0;
+ emit("movq $%u, %%rsi", -1-const_value); // second argument in rsi
+ } else {
+ emit("negl %%eax"); // convert to actual number
+ emit("decl %%eax");
+ // first argument already in rdi
+ emit("movq %%rax, %%rsi"); // second argument in rsi
+ }
emit("movq $%lu, %%rax", (unsigned long)callAsmCall);
emit("callq *%%rax");
emit("pop %%rbx");
@@ -483,28 +574,42 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {
neednilabel = 1;
break;
case OP_PUSH:
+ MAYBE_EMIT_CONST();
emit("addq $4, %%rsi");
break;
case OP_POP:
+ MAYBE_EMIT_CONST();
emit("subq $4, %%rsi");
break;
case OP_CONST:
+ MAYBE_EMIT_CONST();
+#ifdef CONST_OPTIMIZE
+ got_const = 1;
+ const_value = iarg;
+#else
emit("addq $4, %%rsi");
emit("movl $%d, 0(%%rsi)", iarg);
+#endif
break;
case OP_LOCAL:
+ MAYBE_EMIT_CONST();
emit("movl %%edi, %%ebx");
emit("addl $%d,%%ebx", iarg);
emit("addq $4, %%rsi");
emit("movl %%ebx, 0(%%rsi)");
break;
case OP_JUMP:
- emit("movl 0(%%rsi), %%eax"); // get instr from stack
- emit("subq $4, %%rsi");
- emit("movq $%lu, %%rbx", (unsigned long)vm->instructionPointers);
- emit("movl (%%rbx, %%rax, 4), %%eax"); // load new relative jump address
- emit("addq %%r10, %%rax");
- emit("jmp *%%rax");
+ if(got_const) {
+ iarg = const_value;
+ got_const = 0;
+ JMPIARG;
+ } else {
+ emit("movl 0(%%rsi), %%eax"); // get instr from stack
+ emit("subq $4, %%rsi");
+
+ PREPARE_JMP(eax);
+ emit("jmp *%%rax");
+ }
break;
case OP_EQ:
IJ("jne");
@@ -543,6 +648,7 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {
case OP_NEF:
FJ(0x40, "jnz");
#ifndef USE_X87
+ MAYBE_EMIT_CONST();
emit("subq $8, %%rsi");
emit("movss 4(%%rsi), %%xmm0");
emit("ucomiss 8(%%rsi), %%xmm0");
@@ -570,56 +676,64 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {
XJ("jb");
break;
case OP_LOAD1:
+ MAYBE_EMIT_CONST();
emit("movl 0(%%rsi), %%eax"); // get value from stack
- RANGECHECK(eax);
+ RANGECHECK(eax, 1);
emit("movb 0(%%r8, %%rax, 1), %%al"); // deref into eax
emit("andq $255, %%rax");
emit("movl %%eax, 0(%%rsi)"); // store on stack
break;
case OP_LOAD2:
+ MAYBE_EMIT_CONST();
emit("movl 0(%%rsi), %%eax"); // get value from stack
- RANGECHECK(eax);
+ RANGECHECK(eax, 2);
emit("movw 0(%%r8, %%rax, 1), %%ax"); // deref into eax
emit("movl %%eax, 0(%%rsi)"); // store on stack
break;
case OP_LOAD4:
+ MAYBE_EMIT_CONST();
emit("movl 0(%%rsi), %%eax"); // get value from stack
- RANGECHECK(eax); // not a pointer!?
+ RANGECHECK(eax, 4); // not a pointer!?
emit("movl 0(%%r8, %%rax, 1), %%eax"); // deref into eax
emit("movl %%eax, 0(%%rsi)"); // store on stack
break;
case OP_STORE1:
+ MAYBE_EMIT_CONST();
emit("movl 0(%%rsi), %%eax"); // get value from stack
emit("andq $255, %%rax");
emit("movl -4(%%rsi), %%ebx"); // get pointer from stack
- RANGECHECK(ebx);
+ RANGECHECK(ebx, 1);
emit("movb %%al, 0(%%r8, %%rbx, 1)"); // store in memory
emit("subq $8, %%rsi");
break;
case OP_STORE2:
+ MAYBE_EMIT_CONST();
emit("movl 0(%%rsi), %%eax"); // get value from stack
emit("movl -4(%%rsi), %%ebx"); // get pointer from stack
- RANGECHECK(ebx);
+ RANGECHECK(ebx, 2);
emit("movw %%ax, 0(%%r8, %%rbx, 1)"); // store in memory
emit("subq $8, %%rsi");
break;
case OP_STORE4:
+ MAYBE_EMIT_CONST();
emit("movl -4(%%rsi), %%ebx"); // get pointer from stack
- RANGECHECK(ebx);
+ RANGECHECK(ebx, 4);
emit("movl 0(%%rsi), %%ecx"); // get value from stack
emit("movl %%ecx, 0(%%r8, %%rbx, 1)"); // store in memory
emit("subq $8, %%rsi");
break;
case OP_ARG:
+ MAYBE_EMIT_CONST();
emit("subq $4, %%rsi");
emit("movl 4(%%rsi), %%eax"); // get value from stack
emit("movl $0x%hhx, %%ebx", barg);
emit("addl %%edi, %%ebx");
- RANGECHECK(ebx);
+ RANGECHECK(ebx, 4);
emit("movl %%eax, 0(%%r8,%%rbx, 1)"); // store in args space
break;
case OP_BLOCK_COPY:
+ MAYBE_EMIT_CONST();
emit("subq $8, %%rsi");
emit("push %%rsi");
emit("push %%rdi");
@@ -639,6 +753,7 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {
break;
case OP_SEX8:
+ MAYBE_EMIT_CONST();
emit("movw 0(%%rsi), %%ax");
emit("andq $255, %%rax");
emit("cbw");
@@ -646,11 +761,13 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {
emit("movl %%eax, 0(%%rsi)");
break;
case OP_SEX16:
+ MAYBE_EMIT_CONST();
emit("movw 0(%%rsi), %%ax");
emit("cwde");
emit("movl %%eax, 0(%%rsi)");
break;
case OP_NEGI:
+ MAYBE_EMIT_CONST();
emit("negl 0(%%rsi)");
break;
case OP_ADD:
@@ -660,6 +777,7 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {
SIMPLE("subl");
break;
case OP_DIVI:
+ MAYBE_EMIT_CONST();
emit("subq $4, %%rsi");
emit("movl 0(%%rsi), %%eax");
emit("cdq");
@@ -667,6 +785,7 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {
emit("movl %%eax, 0(%%rsi)");
break;
case OP_DIVU:
+ MAYBE_EMIT_CONST();
emit("subq $4, %%rsi");
emit("movl 0(%%rsi), %%eax");
emit("xorq %%rdx, %%rdx");
@@ -674,6 +793,7 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {
emit("movl %%eax, 0(%%rsi)");
break;
case OP_MODI:
+ MAYBE_EMIT_CONST();
emit("subq $4, %%rsi");
emit("movl 0(%%rsi), %%eax");
emit("xorl %%edx, %%edx");
@@ -682,6 +802,7 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {
emit("movl %%edx, 0(%%rsi)");
break;
case OP_MODU:
+ MAYBE_EMIT_CONST();
emit("subq $4, %%rsi");
emit("movl 0(%%rsi), %%eax");
emit("xorl %%edx, %%edx");
@@ -689,12 +810,14 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {
emit("movl %%edx, 0(%%rsi)");
break;
case OP_MULI:
+ MAYBE_EMIT_CONST();
emit("subq $4, %%rsi");
emit("movl 0(%%rsi), %%eax");
emit("imull 4(%%rsi)");
emit("movl %%eax, 0(%%rsi)");
break;
case OP_MULU:
+ MAYBE_EMIT_CONST();
emit("subq $4, %%rsi");
emit("movl 0(%%rsi), %%eax");
emit("mull 4(%%rsi)");
@@ -710,6 +833,7 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {
SIMPLE("xorl");
break;
case OP_BCOM:
+ MAYBE_EMIT_CONST();
emit("notl 0(%%rsi)");
break;
case OP_LSH:
@@ -722,6 +846,7 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {
SHIFT("shrl");
break;
case OP_NEGF:
+ MAYBE_EMIT_CONST();
#ifdef USE_X87
emit("flds 0(%%rsi)");
emit("fchs");
@@ -748,6 +873,7 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {
XSIMPLE("mulss");
break;
case OP_CVIF:
+ MAYBE_EMIT_CONST();
#ifdef USE_X87
emit("filds 0(%%rsi)");
emit("fstps 0(%%rsi)");
@@ -758,6 +884,7 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {
#endif
break;
case OP_CVFI:
+ MAYBE_EMIT_CONST();
#ifdef USE_X87
emit("flds 0(%%rsi)");
emit("fnstcw 4(%%rsi)");
@@ -775,8 +902,17 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {
NOTIMPL(op);
break;
}
+
+
}
+ if(got_const) {
+ Com_Error(ERR_DROP, "leftover const\n");
+ }
+
+ emit("movq $%lu, %%rax", (unsigned long)eop);
+ emit("callq *%%rax");
+
} // pass loop
assembler_init(0);
@@ -789,6 +925,15 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {
#ifdef DEBUG_VM
fflush(qdasmout);
fclose(qdasmout);
+
+#if 0
+ strcpy(fn_d,vm->name);
+ strcat(fn_d, ".bin");
+ qdasmout = fopen(fn_d, "w");
+ fwrite(vm->codeBase, compiledOfs, 1, qdasmout);
+ fflush(qdasmout);
+ fclose(qdasmout);
+#endif
#endif
if(vm->compiled)
diff --git a/src/qcommon/vm_x86_64_assembler.c b/src/qcommon/vm_x86_64_assembler.c
index 5747626a..c36c7a66 100644
--- a/src/qcommon/vm_x86_64_assembler.c
+++ b/src/qcommon/vm_x86_64_assembler.c
@@ -68,10 +68,15 @@ static void _crap(const char* func, const char* fmt, ...)
static void emit1(unsigned char v)
{
+ int writecnt;
+
if(assembler_pass)
{
out[compiledOfs++] = v;
- if(fout) fwrite(&v, 1, 1, fout);
+
+ if(fout)
+ writecnt = fwrite(&v, 1, 1, fout);
+
debug("%02hhx ", v);
}
else
@@ -811,24 +816,34 @@ static void emit_call(const char* mnemonic, arg_t arg1, arg_t arg2, void* data)
{
u8 rex, modrm, sib;
- if(arg1.type != T_REGISTER || arg2.type != T_NONE)
+ if((arg1.type != T_REGISTER && arg1.type != T_IMMEDIATE) || arg2.type != T_NONE)
CRAP_INVALID_ARGS;
- if(!arg1.absolute)
- crap("call must be absolute");
+ if(arg1.type == T_REGISTER)
+ {
+ if(!arg1.absolute)
+ crap("call must be absolute");
- if((arg1.v.reg & R_64) != R_64)
- crap("register must be 64bit");
+ if((arg1.v.reg & R_64) != R_64)
+ crap("register must be 64bit");
- arg1.v.reg ^= R_64; // no rex required for call
+ arg1.v.reg ^= R_64; // no rex required for call
- compute_rexmodrmsib(&rex, &modrm, &sib, &arg2, &arg1);
+ compute_rexmodrmsib(&rex, &modrm, &sib, &arg2, &arg1);
- modrm |= 0x2 << 3;
+ modrm |= 0x2 << 3;
- if(rex) emit1(rex);
- emit1(0xff);
- emit1(modrm);
+ if(rex) emit1(rex);
+ emit1(0xff);
+ emit1(modrm);
+ }
+ else
+ {
+ if(!isu32(arg1.v.imm))
+ crap("must be 32bit argument");
+ emit1(0xe8);
+ emit4(arg1.v.imm);
+ }
}
@@ -875,7 +890,7 @@ static opparam_t params_or = { subcode: 1, rmcode: 0x09, };
static opparam_t params_and = { subcode: 4, rmcode: 0x21, };
static opparam_t params_sub = { subcode: 5, rmcode: 0x29, };
static opparam_t params_xor = { subcode: 6, rmcode: 0x31, };
-static opparam_t params_cmp = { subcode: 6, rmcode: 0x39, mrcode: 0x3b, };
+static opparam_t params_cmp = { subcode: 7, rmcode: 0x39, mrcode: 0x3b, };
static opparam_t params_dec = { subcode: 1, rcode: 0xff, rcode8: 0xfe, };
static opparam_t params_sar = { subcode: 7, rcode: 0xd3, rcode8: 0xd2, };
static opparam_t params_shl = { subcode: 4, rcode: 0xd3, rcode8: 0xd2, };
diff --git a/src/renderer/tr_init.c b/src/renderer/tr_init.c
index 6fb7fed3..b08cdbb8 100644
--- a/src/renderer/tr_init.c
+++ b/src/renderer/tr_init.c
@@ -131,6 +131,7 @@ cvar_t *r_subdivisions;
cvar_t *r_lodCurveError;
cvar_t *r_fullscreen;
+cvar_t *r_noborder;
cvar_t *r_width;
cvar_t *r_height;
@@ -921,6 +922,7 @@ void R_Register( void )
r_overBrightBits = ri.Cvar_Get ("r_overBrightBits", "1", CVAR_ARCHIVE | CVAR_LATCH );
r_ignorehwgamma = ri.Cvar_Get( "r_ignorehwgamma", "0", CVAR_ARCHIVE | CVAR_LATCH);
r_fullscreen = ri.Cvar_Get( "r_fullscreen", "1", CVAR_ARCHIVE );
+ r_noborder = Cvar_Get("r_noborder", "0", CVAR_ARCHIVE);
r_width = ri.Cvar_Get( "r_width", "640", CVAR_ARCHIVE | CVAR_LATCH );
r_height = ri.Cvar_Get( "r_height", "480", CVAR_ARCHIVE | CVAR_LATCH );
r_pixelAspect = ri.Cvar_Get( "r_pixelAspect", "1", CVAR_ARCHIVE | CVAR_LATCH );
diff --git a/src/renderer/tr_local.h b/src/renderer/tr_local.h
index 03908826..f0f3cada 100644
--- a/src/renderer/tr_local.h
+++ b/src/renderer/tr_local.h
@@ -1042,6 +1042,7 @@ extern cvar_t *r_height;
extern cvar_t *r_pixelAspect;
extern cvar_t *r_fullscreen;
+extern cvar_t *r_noborder;
extern cvar_t *r_gamma;
extern cvar_t *r_displayRefresh; // optional display refresh option
extern cvar_t *r_ignorehwgamma; // overrides hardware gamma capabilities
diff --git a/src/sdl/sdl_glimp.c b/src/sdl/sdl_glimp.c
index 58e9c7ed..8028eb59 100644
--- a/src/sdl/sdl_glimp.c
+++ b/src/sdl/sdl_glimp.c
@@ -73,6 +73,7 @@ static const SDL_VideoInfo *videoInfo = NULL;
cvar_t *r_allowSoftwareGL; // Don't abort out if a hardware visual can't be obtained
cvar_t *r_allowResize; // make window resizable
+cvar_t *r_centerWindow;
cvar_t *r_sdlDriver;
void (APIENTRYP qglActiveTextureARB) (GLenum texture);
@@ -133,9 +134,10 @@ static int GLimp_CompareModes( const void *a, const void *b )
else if( aspectDiffsDiff < -ASPECT_EPSILON )
return -1;
else
- return areaA - areaB;
+ return areaA - areaB;
}
+
/*
===============
GLimp_DetectAvailableModes
@@ -193,7 +195,7 @@ static void GLimp_DetectAvailableModes(void)
GLimp_SetMode
===============
*/
-static int GLimp_SetMode( qboolean failSafe, qboolean fullscreen )
+static int GLimp_SetMode( qboolean failSafe, qboolean fullscreen, qboolean noborder )
{
const char* glstring;
int sdlcolorbits;
@@ -267,7 +269,12 @@ static int GLimp_SetMode( qboolean failSafe, qboolean fullscreen )
glConfig.isFullscreen = qtrue;
}
else
+ {
+ if (noborder)
+ flags |= SDL_NOFRAME;
+
glConfig.isFullscreen = qfalse;
+ }
colorbits = r_colorbits->value;
if ((!colorbits) || (colorbits >= 32))
@@ -446,7 +453,7 @@ static int GLimp_SetMode( qboolean failSafe, qboolean fullscreen )
GLimp_StartDriverAndSetMode
===============
*/
-static qboolean GLimp_StartDriverAndSetMode( qboolean failSafe, qboolean fullscreen )
+static qboolean GLimp_StartDriverAndSetMode( qboolean failSafe, qboolean fullscreen, qboolean noborder )
{
rserr_t err;
@@ -474,7 +481,7 @@ static qboolean GLimp_StartDriverAndSetMode( qboolean failSafe, qboolean fullscr
fullscreen = qfalse;
}
- err = GLimp_SetMode( failSafe, fullscreen );
+ err = GLimp_SetMode( failSafe, fullscreen, noborder );
switch ( err )
{
@@ -681,21 +688,24 @@ void GLimp_Init( void )
r_allowSoftwareGL = ri.Cvar_Get( "r_allowSoftwareGL", "0", CVAR_LATCH );
r_sdlDriver = ri.Cvar_Get( "r_sdlDriver", "", CVAR_ROM );
r_allowResize = ri.Cvar_Get( "r_allowResize", "0", CVAR_ARCHIVE );
+ r_centerWindow = ri.Cvar_Get( "r_centerWindow", "0", CVAR_ARCHIVE );
+
+ Sys_SetEnv( "SDL_VIDEO_CENTERED", r_centerWindow->integer ? "1" : "" );
Sys_GLimpInit( );
// Create the window and set up the context
- if( GLimp_StartDriverAndSetMode( qfalse, r_fullscreen->integer ) )
+ if( GLimp_StartDriverAndSetMode( qfalse, r_fullscreen->integer, r_noborder->integer ) )
goto success;
// Try again, this time in a platform specific "safe mode"
Sys_GLimpSafeInit( );
- if( GLimp_StartDriverAndSetMode( qfalse, r_fullscreen->integer ) )
+ if( GLimp_StartDriverAndSetMode( qfalse, r_fullscreen->integer, qfalse ) )
goto success;
// Finally, try the default screen resolution
- if( GLimp_StartDriverAndSetMode( qtrue, r_fullscreen->integer ) )
+ if( GLimp_StartDriverAndSetMode( qtrue, r_fullscreen->integer, qfalse ) )
goto success;
// Nothing worked, give up
diff --git a/src/sys/con_tty.c b/src/sys/con_tty.c
index a66a3faf..b0990032 100644
--- a/src/sys/con_tty.c
+++ b/src/sys/con_tty.c
@@ -327,7 +327,7 @@ CON_Input
char *CON_Input( void )
{
// we use this when sending back commands
- static char text[256];
+ static char text[MAX_EDIT_LINE];
int avail;
char key;
field_t *history;
@@ -358,7 +358,7 @@ char *CON_Input( void )
{
// push it in history
Hist_Add(&TTY_con);
- strcpy(text, TTY_con.buffer);
+ Q_strncpyz(text, TTY_con.buffer, sizeof(text));
Field_Clear(&TTY_con);
key = '\n';
size = write(1, &key, 1);
@@ -420,6 +420,8 @@ char *CON_Input( void )
CON_FlushIn();
return NULL;
}
+ if (TTY_con.cursor >= sizeof(text) - 1)
+ return NULL;
// push regular character
TTY_con.buffer[TTY_con.cursor] = key;
TTY_con.cursor++;
diff --git a/src/sys/sys_unix.c b/src/sys/sys_unix.c
index 3360469d..60623a27 100644
--- a/src/sys/sys_unix.c
+++ b/src/sys/sys_unix.c
@@ -55,22 +55,11 @@ char *Sys_DefaultHomePath(void)
{
Q_strncpyz( homePath, p, sizeof( homePath ) );
#ifdef MACOS_X
- Q_strcat( homePath, sizeof( homePath ), "/Library" );
- mkdir( homePath, 0750 );
- Q_strcat( homePath, sizeof( homePath ), "/Application Support" );
- mkdir( homePath, 0750 );
- Q_strcat( homePath, sizeof( homePath ), "/Tremulous" );
+ Q_strcat( homePath, sizeof( homePath ),
+ "/Library/Application Support/Tremulous" );
#else
Q_strcat( homePath, sizeof( homePath ), "/.tremulous" );
#endif
- if( mkdir( homePath, 0750 ) )
- {
- if( errno != EEXIST )
- {
- Sys_Error( "Unable to create directory \"%s\", error is %s(%d)\n",
- homePath, strerror( errno ), errno );
- }
- }
}
}
@@ -222,9 +211,14 @@ const char *Sys_Dirname( char *path )
Sys_Mkdir
==================
*/
-void Sys_Mkdir( const char *path )
+qboolean Sys_Mkdir( const char *path )
{
- mkdir( path, 0777 );
+ int result = mkdir( path, 0750 );
+
+ if( result != 0 )
+ return errno == EEXIST;
+
+ return qtrue;
}
/*
@@ -583,3 +577,19 @@ void Sys_PlatformInit( void )
signal( SIGIOT, Sys_SigHandler );
signal( SIGBUS, Sys_SigHandler );
}
+
+/*
+==============
+Sys_SetEnv
+
+set/unset environment variables (empty value removes it)
+==============
+*/
+
+void Sys_SetEnv(const char *name, const char *value)
+{
+ if(value && *value)
+ setenv(name, value, 1);
+ else
+ unsetenv(name);
+}
diff --git a/src/sys/sys_win32.c b/src/sys/sys_win32.c
index 18efe406..e5b0cb00 100644
--- a/src/sys/sys_win32.c
+++ b/src/sys/sys_win32.c
@@ -77,14 +77,6 @@ char *Sys_DefaultHomePath( void )
Q_strncpyz( homePath, szPath, sizeof( homePath ) );
Q_strcat( homePath, sizeof( homePath ), "\\Tremulous" );
FreeLibrary(shfolder);
- if( !CreateDirectory( homePath, NULL ) )
- {
- if( GetLastError() != ERROR_ALREADY_EXISTS )
- {
- Com_Printf("Unable to create directory \"%s\"\n", homePath );
- return NULL;
- }
- }
}
return homePath;
@@ -279,9 +271,15 @@ const char *Sys_Dirname( char *path )
Sys_Mkdir
==============
*/
-void Sys_Mkdir( const char *path )
+qboolean Sys_Mkdir( const char *path )
{
- _mkdir (path);
+ if( !CreateDirectory( path, NULL ) )
+ {
+ if( GetLastError( ) != ERROR_ALREADY_EXISTS )
+ return qfalse;
+ }
+
+ return qtrue;
}
/*
@@ -652,3 +650,16 @@ void Sys_PlatformInit( void )
SDL_VIDEODRIVER_externallySet = qfalse;
#endif
}
+
+/*
+==============
+Sys_SetEnv
+
+set/unset environment variables (empty value removes it)
+==============
+*/
+
+void Sys_SetEnv(const char *name, const char *value)
+{
+ _putenv(va("%s=%s", name, value));
+}