Many general cleaups and warning fixes.

Console code no longer makes assumptions about con_main
Screenshots rework, for screenshot_360, but also some other cleanups.
Fixed an issue with beginpolygon (finally).
Added per-rtlight style strings.
Added cvar to control whether ents will be culled by fog.
Added define to disable IPLOG, etc.
Added r_editlights cvar and related commands, for whenever csaddon isn't available.



git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5338 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2018-11-19 06:37:25 +00:00
parent 398c1afaf9
commit 2ee8387644
102 changed files with 4081 additions and 1630 deletions

View file

@ -6,7 +6,7 @@
CMAKE_MINIMUM_REQUIRED(VERSION 3.0) CMAKE_MINIMUM_REQUIRED(VERSION 3.0)
cmake_policy(SET CMP0063 NEW) cmake_policy(SET CMP0063 NEW)
PROJECT(fteqw) PROJECT(FTEQuake)
INCLUDE_DIRECTORIES( INCLUDE_DIRECTORIES(
engine/common engine/common
@ -35,51 +35,40 @@ set(CMAKE_CXX_VISIBILITY_PRESET hidden)
set(CMAKE_C_VISIBILITY_PRESET hidden) set(CMAKE_C_VISIBILITY_PRESET hidden)
IF(${CMAKE_VERSION} VERSION_LESS "3.9.0") IF(${CMAKE_VERSION} VERSION_LESS "3.9.0")
MESSAGE(STATUS "no LTO - old cmake.")
ELSE() ELSE()
IF(NOT ${CMAKE_BUILD_TYPE} MATCHES "Debug") cmake_policy(SET CMP0069 NEW)
IF(NOT CMAKE_BUILD_TYPE MATCHES "Debug")
#use LTO where possible. reportedly requires cmake 3.9 to actually work #use LTO where possible. reportedly requires cmake 3.9 to actually work
INCLUDE(CheckIPOSupported) INCLUDE(CheckIPOSupported)
check_ipo_supported(RESULT result) check_ipo_supported(RESULT result)
IF(result) IF(result)
SET(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE) SET(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE)
MESSAGE(STATUS "Using LTO.")
ELSE()
MESSAGE(STATUS "no LTO - not supported.")
ENDIF() ENDIF()
ELSE()
MESSAGE(STATUS "no LTO - debug.")
ENDIF() ENDIF()
ENDIF() ENDIF()
SET(FTE_BUILD_CONFIG ${CMAKE_HOME_DIRECTORY}/engine/common/config_fteqw.h CACHE FILEPATH "Which build config file to use to control supported features.")
SET(FTE_LIB_DEFINES ${FTE_LIB_DEFINES};CONFIG_FILE_NAME=${FTE_BUILD_CONFIG})
FIND_PACKAGE(ZLIB) FIND_PACKAGE(ZLIB)
IF(NOT ZLIB_FOUND) IF(NOT ZLIB_FOUND)
MESSAGE(WARNING "libz library NOT available. compressed pk3 will not be available.") MESSAGE(WARNING "libz library NOT available. compressed pk3 will not be available.")
SET(FTE_LIB_DEFINES ${FTE_LIB_DEFINES};NO_ZLIB) SET(FTE_LIB_DEFINES ${FTE_LIB_DEFINES};NO_ZLIB)
SET(ZLIB_LIBRARY m) SET(ZLIB_LIBRARY )
SET(ZLIB_LIBRARIES m) SET(ZLIB_LIBRARIES )
ENDIF()
FIND_PACKAGE(GnuTLS)
IF(NOT GNUTLS_FOUND)
MESSAGE(WARNING "gnutls library NOT available. HTTPS/DTLS will not be available.")
SET(FTE_LIB_DEFINES ${FTE_LIB_DEFINES};NO_GNUTLS)
ENDIF()
FIND_PACKAGE(ALSA)
IF(NOT ALSA_FOUND)
MESSAGE(WARNING "asound (alsa) library NOT available.")
SET(FTE_LIB_DEFINES ${FTE_LIB_DEFINES};NO_ALSA)
ENDIF()
FIND_PACKAGE(X11)
IF(X11_FOUND)
IF (NOT X11_Xcursor_FOUND)
SET(FTE_LIB_DEFINES ${FTE_LIB_DEFINES};NO_X11_CURSOR)
MESSAGE(WARNING "Xcursor library NOT available.")
ENDIF()
ELSE()
MESSAGE(WARNING "x11 library NOT available.")
SET(FTE_LIB_DEFINES ${FTE_LIB_DEFINES};NO_X11)
ENDIF() ENDIF()
SET(OpenGL_GL_PREFERENCE LEGACY) SET(OpenGL_GL_PREFERENCE LEGACY)
FIND_PACKAGE(OpenGL) FIND_PACKAGE(OpenGL)
IF(NOT OpenGL_FOUND) IF(OpenGL_FOUND)
SET(FTE_LIB_DEFINES ${FTE_LIB_DEFINES};GLQUAKE)
ELSE()
MESSAGE(WARNING "opengl library NOT available. Will depend upon vulkan.") MESSAGE(WARNING "opengl library NOT available. Will depend upon vulkan.")
SET(FTE_LIB_DEFINES ${FTE_LIB_DEFINES};NO_OPENGL) SET(FTE_LIB_DEFINES ${FTE_LIB_DEFINES};NO_OPENGL)
ENDIF() ENDIF()
@ -104,6 +93,15 @@ ELSE()
SET(FTE_LIB_DEFINES ${FTE_LIB_DEFINES};NO_FREETYPE) SET(FTE_LIB_DEFINES ${FTE_LIB_DEFINES};NO_FREETYPE)
ENDIF() ENDIF()
#FIND_PACKAGE(Vulkan)
#IF(Vulkan_FOUND)
# INCLUDE_DIRECTORIES( ${Vulkan_INCLUDE_DIRS} )
SET(FTE_DEFINES ${FTE_DEFINES};VKQUAKE)
#ELSE()
# SET(FTE_DEFINES ${FTE_DEFINES};VKQUAKE)
# MESSAGE(WARNING "System vulkan headers NOT available.")
#ENDIF()
FIND_LIBRARY(VORBISFILE_LIBRARY NAMES vorbisfile) FIND_LIBRARY(VORBISFILE_LIBRARY NAMES vorbisfile)
IF(NOT VORBISFILE_LIBRARY) IF(NOT VORBISFILE_LIBRARY)
MESSAGE(WARNING "libvorbisfile library NOT available. Who listens to the bgm anyway?") MESSAGE(WARNING "libvorbisfile library NOT available. Who listens to the bgm anyway?")
@ -133,7 +131,7 @@ IF(${ANDROID})
# INCLUDE_DIRECTORIES( ${FREETYPE_INCLUDE_DIRS} ) # INCLUDE_DIRECTORIES( ${FREETYPE_INCLUDE_DIRS} )
SET(FTE_DEFINES ${FTE_DEFINES};ANDROID;GLQUAKE;VKQUAKE;DYNAMIC_LIBPNG;DYNAMIC_LIBJPEG;MULTITHREAD;stricmp=strcasecmp;strnicmp=strncasecmp) SET(FTE_DEFINES ${FTE_DEFINES};ANDROID;VKQUAKE;DYNAMIC_LIBPNG;DYNAMIC_LIBJPEG;MULTITHREAD;stricmp=strcasecmp;strnicmp=strncasecmp)
SET(FTE_LIBS android log EGL ${ZLIB_LIBRARIES} m ${CMAKE_DL_LIBS}) SET(FTE_LIBS android log EGL ${ZLIB_LIBRARIES} m ${CMAKE_DL_LIBS})
SET(FTE_ARCH_FILES SET(FTE_ARCH_FILES
engine/client/sys_droid.c engine/client/sys_droid.c
@ -148,8 +146,8 @@ ELSEIF(${WIN32})
# engine/server/sv_sys_win.c # engine/server/sv_sys_win.c
SET(FTE_LIBS ${ZLIB_LIBRARIES} ole32 gdi32 wsock32 winmm) SET(FTE_LIBS ${ZLIB_LIBRARIES} ole32 gdi32 wsock32 winmm dxguid)
SET(FTE_DEFINES ${FTE_DEFINES};GLQUAKE;VKQUAKE;D3D9QUAKE;DYNAMIC_LIBPNG;DYNAMIC_LIBJPEG) #D3D11QUAKE not included. SET(FTE_DEFINES ${FTE_DEFINES};D3D9QUAKE;D3D11QUAKE;DYNAMIC_LIBPNG;DYNAMIC_LIBJPEG)
SET(FTE_ARCH_FILES SET(FTE_ARCH_FILES
engine/client/winquake.rc engine/client/winquake.rc
engine/common/sys_win_threads.c engine/common/sys_win_threads.c
@ -189,7 +187,32 @@ ELSEIF(${WIN32})
) )
ELSEIF(${UNIX}) #linux(ish) ELSEIF(${UNIX}) #linux(ish)
#openbsd will have issues with snd_linux.c #openbsd will have issues with snd_linux.c
SET(FTE_DEFINES ${FTE_DEFINES};GLQUAKE;VKQUAKE;DYNAMIC_LIBPNG;DYNAMIC_LIBJPEG;DYNAMIC_SDL;MULTITHREAD;stricmp=strcasecmp;strnicmp=strncasecmp)
#linux-only packages
FIND_PACKAGE(GnuTLS)
IF(NOT GNUTLS_FOUND)
MESSAGE(WARNING "gnutls library NOT available. HTTPS/DTLS will not be available.")
SET(FTE_LIB_DEFINES ${FTE_LIB_DEFINES};NO_GNUTLS)
ENDIF()
FIND_PACKAGE(ALSA)
IF(NOT ALSA_FOUND)
MESSAGE(WARNING "asound (alsa) library NOT available.")
SET(FTE_LIB_DEFINES ${FTE_LIB_DEFINES};NO_ALSA)
ENDIF()
FIND_PACKAGE(X11)
IF(X11_FOUND)
IF (NOT X11_Xcursor_FOUND)
SET(FTE_LIB_DEFINES ${FTE_LIB_DEFINES};NO_X11_CURSOR)
MESSAGE(WARNING "Xcursor library NOT available.")
ENDIF()
ELSE()
MESSAGE(WARNING "x11 library NOT available.")
SET(FTE_LIB_DEFINES ${FTE_LIB_DEFINES};NO_X11)
ENDIF()
SET(FTE_DEFINES ${FTE_DEFINES};DYNAMIC_LIBPNG;DYNAMIC_LIBJPEG;DYNAMIC_SDL;MULTITHREAD;stricmp=strcasecmp;strnicmp=strncasecmp)
SET(FTE_LIBS ${ZLIB_LIBRARIES} m ${CMAKE_DL_LIBS} pthread ${SDL2_LIBRARIES}) SET(FTE_LIBS ${ZLIB_LIBRARIES} m ${CMAKE_DL_LIBS} pthread ${SDL2_LIBRARIES})
SET(FTE_ARCH_FILES SET(FTE_ARCH_FILES
engine/client/sys_linux.c engine/client/sys_linux.c
@ -262,7 +285,7 @@ ELSEIF(1) #SDL
INCLUDE_DIRECTORIES(${FREETYPE_INCLUDE_DIRS} ${SDL2_INCLUDE_DIRS}) INCLUDE_DIRECTORIES(${FREETYPE_INCLUDE_DIRS} ${SDL2_INCLUDE_DIRS})
#SDL2.0.7 supports vulkan, so lets use it. #SDL2.0.7 supports vulkan, so lets use it.
SET(FTE_DEFINES ${FTE_DEFINES};GLQUAKE;VKQUAKE;FTE_SDL;DYNAMIC_LIBPNG;DYNAMIC_LIBJPEG;stricmp=strcasecmp;strnicmp=strncasecmp) SET(FTE_DEFINES ${FTE_DEFINES};FTE_SDL;DYNAMIC_LIBPNG;DYNAMIC_LIBJPEG;stricmp=strcasecmp;strnicmp=strncasecmp)
SET(FTE_LIBS ${ZLIB_LIBRARIES} m ${CMAKE_DL_LIBS} ${SDL2_LIBRARIES}) SET(FTE_LIBS ${ZLIB_LIBRARIES} m ${CMAKE_DL_LIBS} ${SDL2_LIBRARIES})
SET(FTE_ARCH_FILES SET(FTE_ARCH_FILES
engine/client/sys_sdl.c engine/client/sys_sdl.c
@ -519,7 +542,7 @@ SET(FTE_CLIENT_FILES
engine/vk/vk_init.c engine/vk/vk_init.c
) )
IF(${ANDROID}) IF(ANDROID)
#android sucks. everything is a library. so we build the engine as a shared library and completely ignore dedicated servers+tools #android sucks. everything is a library. so we build the engine as a shared library and completely ignore dedicated servers+tools
ADD_LIBRARY(ftedroid MODULE ADD_LIBRARY(ftedroid MODULE
${FTE_ARCH_FILES} ${FTE_ARCH_FILES}
@ -545,6 +568,19 @@ ELSE()
SET_TARGET_PROPERTIES(fteqw-sv PROPERTIES COMPILE_DEFINITIONS "SERVERONLY;${FTE_LIB_DEFINES};${FTESV_DEFINES};${FTE_REVISON}") SET_TARGET_PROPERTIES(fteqw-sv PROPERTIES COMPILE_DEFINITIONS "SERVERONLY;${FTE_LIB_DEFINES};${FTESV_DEFINES};${FTE_REVISON}")
TARGET_LINK_LIBRARIES(fteqw-sv ${FTESV_LIBS}) TARGET_LINK_LIBRARIES(fteqw-sv ${FTESV_LIBS})
ADD_EXECUTABLE(iqmtool
iqm/iqm.cpp
iqm/iqm.h
)
SET_TARGET_PROPERTIES(iqmtool PROPERTIES COMPILE_DEFINITIONS "${FTE_REVISON}")
ADD_EXECUTABLE(httpserver
engine/common/fs_stdio.c
engine/http/httpserver.c
engine/http/iwebiface.c
engine/http/ftpserver.c
)
SET_TARGET_PROPERTIES(httpserver PROPERTIES COMPILE_DEFINITIONS "WEBSERVER;WEBSVONLY;${FTE_REVISON};stricmp=strcasecmp;strnicmp=strncasecmp")
ADD_EXECUTABLE(fteqcc ADD_EXECUTABLE(fteqcc
engine/qclib/qcctui.c engine/qclib/qcctui.c
@ -593,7 +629,7 @@ SET_TARGET_PROPERTIES(qi PROPERTIES PREFIX "fteplug_")
#Bullet Physics library plugin #Bullet Physics library plugin
#FIND_PACKAGE(Bullet) #FIND_PACKAGE(Bullet)
IF (${BULLET_FOUND}) IF (BULLET_FOUND)
ADD_LIBRARY(bullet MODULE ADD_LIBRARY(bullet MODULE
plugins/qvm_api.c plugins/qvm_api.c
plugins/plugin.c plugins/plugin.c
@ -606,7 +642,7 @@ ENDIF()
#ODE Physics library plugin #ODE Physics library plugin
#FIND_PACKAGE(ode) #FIND_PACKAGE(ode)
IF (${ODE_FOUND}) IF (ODE_FOUND)
ADD_LIBRARY(ode MODULE ADD_LIBRARY(ode MODULE
plugins/qvm_api.c plugins/qvm_api.c
plugins/plugin.c plugins/plugin.c
@ -638,7 +674,34 @@ ADD_LIBRARY(irc MODULE
SET_TARGET_PROPERTIES(irc PROPERTIES COMPILE_DEFINITIONS "FTEPLUGIN;${FTE_LIB_DEFINES}") SET_TARGET_PROPERTIES(irc PROPERTIES COMPILE_DEFINITIONS "FTEPLUGIN;${FTE_LIB_DEFINES}")
SET_TARGET_PROPERTIES(irc PROPERTIES PREFIX "fteplug_") SET_TARGET_PROPERTIES(irc PROPERTIES PREFIX "fteplug_")
IF(NOT ${ANDROID}) #ffmpeg client plugin. no proper way to detect dependancies right now, so I've gotta try the manual way.
FIND_PATH(AVCODEC_INCLUDE_DIR libavcodec/avcodec.h)
FIND_PATH(AVFORMAT_INCLUDE_DIR libavformat/avformat.h)
FIND_PATH(AVUTIL_INCLUDE_DIR libavutil/avutil.h)
FIND_PATH(AVSWSCALE_INCLUDE_DIR libswscale/swscale.h)
IF(AVFORMAT_INCLUDE_DIR)
FIND_LIBRARY(AVCODEC_LIBRARY avcodec)
FIND_LIBRARY(AVFORMAT_LIBRARY avformat)
FIND_LIBRARY(AVUTIL_LIBRARY avutil)
FIND_LIBRARY(AVSWSCALE_LIBRARY swscale)
ADD_LIBRARY(ffmpeg MODULE
plugins/qvm_api.c
plugins/plugin.c
plugins/avplug/avaudio.c
plugins/avplug/avdecode.c
plugins/avplug/avencode.c
)
TARGET_INCLUDE_DIRECTORIES(ffmpeg PUBLIC ${AVCODEC_INCLUDE_DIR} ${AVFORMAT_INCLUDE_DIR} ${AVUTIL_INCLUDE_DIR} ${AVSWSCALE_INCLUDE_DIR})
SET_TARGET_PROPERTIES(ffmpeg PROPERTIES LINK_FLAGS "-Wl,--no-undefined")
TARGET_LINK_LIBRARIES(ffmpeg m ${AVFORMAT_LIBRARY} ${AVCODEC_LIBRARY} ${AVUTIL_LIBRARY} ${AVSWSCALE_LIBRARY})
SET_TARGET_PROPERTIES(ffmpeg PROPERTIES COMPILE_DEFINITIONS "FTEPLUGIN;${FTE_LIB_DEFINES}")
SET_TARGET_PROPERTIES(ffmpeg PROPERTIES PREFIX "fteplug_")
ELSE()
MESSAGE(WARNING "ffmpeg library NOT available. Quake shouldn't be playing fmv anyway.")
ENDIF()
IF(NOT ANDROID)
#XMPP/jabber client plugin #XMPP/jabber client plugin
ADD_LIBRARY(xmpp MODULE ADD_LIBRARY(xmpp MODULE
plugins/qvm_api.c plugins/qvm_api.c
@ -654,5 +717,4 @@ IF(NOT ${ANDROID})
SET_TARGET_PROPERTIES(xmpp PROPERTIES PREFIX "fteplug_") SET_TARGET_PROPERTIES(xmpp PROPERTIES PREFIX "fteplug_")
ENDIF() ENDIF()
#ffmpeg plugin
#cef plugin #cef plugin

View file

@ -40,16 +40,22 @@ BULLETVER=2.87
#only limited forms of cross-making is supported #only limited forms of cross-making is supported
#only the following 3 are supported #only the following 3 are supported
#linux->win32 (FTE_TARGET=win32) RPM Package: "mingw32-gcc", DEB Package: "mingw32" #linux->win32 (FTE_TARGET=win32) RPM Package: "mingw32-gcc", DEB Package: "mingw32"
#linux->linux32 (FTE_TARGET=linux32) #linux->win64 (FTE_TARGET=win64) RPM Package: "mingw32-gcc", DEB Package: "mingw32"
#linux->linux64 (FTE_TARGET=linux64) #linux->linux 32 (FTE_TARGET=linux32)
#linux->linux 64 (FTE_TARGET=linux64)
#linux->linux x32 (FTE_TARGET=linuxx32)
#linux->linux armhf (FTE_TARGET=linuxarmhf)
#linux->linux arm64/aarch64 (FTE_TARGET=linuxarm64)
#linux->linux *others* (FTE_TARGET=linux CC=other-gcc)
#linux->morphos (FTE_TARGET=morphos) #linux->morphos (FTE_TARGET=morphos)
#linux->macosx (FTE_TARGET=macosx) or (FTE_TARGET=macosx_x86) #linux->macosx (FTE_TARGET=macosx) or (FTE_TARGET=macosx_x86)
#linux->javascript (FTE_TARGET=web) #linux->javascript (FTE_TARGET=web)
#linux->nacl (FTE_TARGET=nacl NARCH=x86_64) #linux->nacl (FTE_TARGET=nacl NARCH=x86_64) deprecated.
#win32->nacl #win32->nacl
#linux->droid (make droid) #linux->droid (make droid)
#win32->droid (make droid) #win32->droid (make droid)
#if you are cross compiling, you'll need to use FTE_TARGET=mytarget #if you are cross compiling, you'll need to use FTE_TARGET=mytarget
#note: cross compiling will typically require 'make makelibs FTE_TARGET=mytarget', which avoids installing lots of extra system packages.
#cygwin's make's paths confuses non-cygwin things #cygwin's make's paths confuses non-cygwin things
RELEASE_DIR=$(BASE_DIR)/release RELEASE_DIR=$(BASE_DIR)/release
@ -86,7 +92,7 @@ endif
BRANDFLAGS+=-DCONFIG_FILE_NAME=config_$(FTE_CONFIG).h $(FTE_CONFIG_EXTRA) BRANDFLAGS+=-DCONFIG_FILE_NAME=config_$(FTE_CONFIG).h $(FTE_CONFIG_EXTRA)
EXE_NAME=$(FTE_CONFIG) EXE_NAME=$(FTE_CONFIG)
ifeq (,$(findstring DNO_SPEEX,$(FTE_CONFIG_EXTRA))) ifeq (,$(findstring DNO_SPEEX,$(FTE_CONFIG_EXTRA)))
USE_SPEEX=1 USE_SPEEX?=1
endif endif
ifeq (,$(findstring DNO_OPUS,$(FTE_CONFIG_EXTRA))) ifeq (,$(findstring DNO_OPUS,$(FTE_CONFIG_EXTRA)))
USE_OPUS=1 USE_OPUS=1
@ -395,12 +401,25 @@ ifeq ($(FTE_TARGET),linuxarmhf)
CXX=arm-linux-gnueabihf-g++ -marm -march=armv6 -mfpu=vfp -mfloat-abi=hard CXX=arm-linux-gnueabihf-g++ -marm -march=armv6 -mfpu=vfp -mfloat-abi=hard
BITS=armhf BITS=armhf
endif endif
ifeq ($(FTE_TARGET),linuxarm64)
FTE_TARGET=linux
CC=aarch64-linux-gnu-gcc
CXX=aarch64-linux-gnu-g++
BITS=arm64
USE_SPEEX=0 #fails to compile due to neon asm, I'm just going to disable it (will still soft-link).
endif
ifeq ($(FTE_TARGET),linuxx32) ifeq ($(FTE_TARGET),linuxx32)
#note: the x32 abi is still not finished or something. #note: the x32 abi is still not finished or something.
#at the current time, you will need to edit your kernel's commandline to allow this stuff to run #at the current time, you will need to edit your kernel's commandline to allow this stuff to run
#try and use a proper cross-compiler if we can, otherwise fall back on multi-arch.
FTE_TARGET=linux FTE_TARGET=linux
ifneq ($(shell which x86_64-linux-gnux32-gcc 2> /dev/null),)
CC=x86_64-linux-gnux32-gcc
CXX=x86_64-linux-gnux32-g++
else
CC=gcc -mx32 CC=gcc -mx32
CXX=g++ -mx32 CXX=g++ -mx32
endif
BITS=x32 BITS=x32
endif endif
ifeq ($(FTE_TARGET),linux64) ifeq ($(FTE_TARGET),linux64)
@ -1351,12 +1370,12 @@ ifneq (,$(findstring linux,$(FTE_TARGET)))
SV_LDFLAGS= SV_LDFLAGS=
SV_CFLAGS=$(SERVER_ONLY_CFLAGS) -DMULTITHREAD SV_CFLAGS=$(SERVER_ONLY_CFLAGS) -DMULTITHREAD
ifneq ("$(wildcard $(/usr/include/wayland-client.h))","") ifneq ("$(wildcard /usr/include/wayland-client.h)","")
HAVE_WAYLAND=-DWAYLANDQUAKE HAVE_WAYLAND=-DWAYLANDQUAKE
else else
HAVE_WAYLAND= HAVE_WAYLAND=
endif endif
ifneq ("$(wildcard $(/usr/include/EGL/egl.h))","") ifneq ("$(wildcard /usr/include/EGL/egl.h)","")
HAVE_EGL=-DUSE_EGL HAVE_EGL=-DUSE_EGL
else else
HAVE_EGL= HAVE_EGL=

View file

@ -27,7 +27,7 @@ float recdemostart; //keyed to Sys_DoubleTime
int demoframe; int demoframe;
int cls_lastto; int cls_lastto;
int cls_lasttype; static int cls_lasttype;
void CL_PlayDemo(char *demoname, qboolean usesystempath); void CL_PlayDemo(char *demoname, qboolean usesystempath);
void CL_PlayDemoFile(vfsfile_t *f, char *demoname, qboolean issyspath); void CL_PlayDemoFile(vfsfile_t *f, char *demoname, qboolean issyspath);
@ -1680,7 +1680,7 @@ static int CL_RecordInitialPlayers(sizebuf_t *buf, int seq, qboolean isnq)
} }
static int CL_RecordInitialStats(sizebuf_t *buf, int seq, qboolean isnq) static int CL_RecordInitialStats(sizebuf_t *buf, int seq, qboolean isnq)
{ {
int seat, i; size_t seat, i;
for (seat = 0; seat < cl.splitclients; seat++) for (seat = 0; seat < cl.splitclients; seat++)
{ {
//higher stats should be 0 and thus not be sent, if not valid. //higher stats should be 0 and thus not be sent, if not valid.
@ -1741,7 +1741,7 @@ void CL_Record_f (void)
int c; int c;
char name[MAX_OSPATH]; char name[MAX_OSPATH];
sizebuf_t buf; sizebuf_t buf;
char buf_data[MAX_OVERALLMSGLEN]; qbyte buf_data[MAX_OVERALLMSGLEN];
int n, i; int n, i;
char *s, *p, *fname; char *s, *p, *fname;
extern char gamedirfile[]; extern char gamedirfile[];
@ -2601,12 +2601,12 @@ void CL_Demo_ClientCommand(char *commandtext)
} }
} }
char qtvhostname[1024]; static char qtvhostname[1024];
char qtvrequestbuffer[4096]; static char qtvrequestbuffer[4096];
int qtvrequestsize; static size_t qtvrequestsize;
char qtvrequestcmdbuffer[4096]; static char qtvrequestcmdbuffer[4096];
int qtvrequestcmdsize; static int qtvrequestcmdsize;
vfsfile_t *qtvrequest; static vfsfile_t *qtvrequest;
void CL_QTVPoll (void) void CL_QTVPoll (void)
{ {

View file

@ -125,6 +125,8 @@ void CL_FreeDlights(void)
if (cl_dlights) if (cl_dlights)
for (i = 0; i < rtlights_max; i++) for (i = 0; i < rtlights_max; i++)
{ {
if (cl_dlights[i].customstyle)
Z_Free(cl_dlights[i].customstyle);
if (cl_dlights[i].worldshadowmesh) if (cl_dlights[i].worldshadowmesh)
SH_FreeShadowMesh(cl_dlights[i].worldshadowmesh); SH_FreeShadowMesh(cl_dlights[i].worldshadowmesh);
@ -147,11 +149,26 @@ void CL_InitDlights(void)
memset(cl_dlights, 0, sizeof(*cl_dlights)*cl_maxdlights); memset(cl_dlights, 0, sizeof(*cl_dlights)*cl_maxdlights);
} }
void CL_CloneDlight(dlight_t *dl, dlight_t *src)
{
char *customstyle = dl->customstyle;
void *sm = dl->worldshadowmesh;
unsigned int oq = dl->coronaocclusionquery;
unsigned int oqr = (dl->key == src->key)?dl->coronaocclusionresult:false;
memcpy (dl, src, sizeof(*dl));
dl->coronaocclusionquery = oq;
dl->coronaocclusionresult = oqr;
dl->rebuildcache = true;
dl->worldshadowmesh = sm;
dl->customstyle = src->customstyle?Z_StrDup(src->customstyle):NULL;
Z_Free(customstyle);
}
static void CL_ClearDlight(dlight_t *dl, int key) static void CL_ClearDlight(dlight_t *dl, int key)
{ {
void *sm = dl->worldshadowmesh; void *sm = dl->worldshadowmesh;
unsigned int oq = dl->coronaocclusionquery; unsigned int oq = dl->coronaocclusionquery;
unsigned int oqr = (dl->key == key)?dl->coronaocclusionresult:false; unsigned int oqr = (dl->key == key)?dl->coronaocclusionresult:false;
Z_Free(dl->customstyle);
memset (dl, 0, sizeof(*dl)); memset (dl, 0, sizeof(*dl));
dl->coronaocclusionquery = oq; dl->coronaocclusionquery = oq;
dl->coronaocclusionresult = oqr; dl->coronaocclusionresult = oqr;
@ -179,13 +196,23 @@ static void CL_ClearDlight(dlight_t *dl, int key)
dlight_t *CL_AllocSlight(void) dlight_t *CL_AllocSlight(void)
{ {
dlight_t *dl; dlight_t *dl;
if (rtlights_max == cl_maxdlights) int i;
for (i = RTL_FIRST; i < rtlights_max; i++)
{ {
cl_maxdlights = rtlights_max+8; if (cl_dlights[i].radius <= 0)
cl_dlights = BZ_Realloc(cl_dlights, sizeof(*cl_dlights)*cl_maxdlights); break;
memset(&cl_dlights[rtlights_max], 0, sizeof(*cl_dlights)*(cl_maxdlights-rtlights_max));
} }
dl = &cl_dlights[rtlights_max++]; if (i == rtlights_max)
{
if (rtlights_max == cl_maxdlights)
{
cl_maxdlights = rtlights_max+8;
cl_dlights = BZ_Realloc(cl_dlights, sizeof(*cl_dlights)*cl_maxdlights);
memset(&cl_dlights[rtlights_max], 0, sizeof(*cl_dlights)*(cl_maxdlights-rtlights_max));
}
i = rtlights_max++;
}
dl = &cl_dlights[i];
CL_ClearDlight(dl, 0); CL_ClearDlight(dl, 0);
dl->flags = LFLAG_REALTIMEMODE; dl->flags = LFLAG_REALTIMEMODE;
@ -2459,10 +2486,86 @@ void CLQ1_DrawLine(shader_t *shader, vec3_t v1, vec3_t v2, float r, float g, flo
t->numidx = cl_numstrisidx - t->firstidx; t->numidx = cl_numstrisidx - t->firstidx;
cl_numstrisvert += 2; cl_numstrisvert += 2;
} }
void CLQ1_AddSpriteQuad(shader_t *shader, vec3_t mid, float radius)
{
float r=1, g=1, b=1;
scenetris_t *t;
int flags = BEF_NODLIGHT|BEF_NOSHADOWS;
if (cl_numstris && cl_stris[cl_numstris-1].shader == shader && cl_stris[cl_numstris-1].flags == flags && cl_stris[cl_numstris-1].numvert + 4 <= MAX_INDICIES)
t = &cl_stris[cl_numstris-1];
else
{
if (cl_numstris == cl_maxstris)
{
cl_maxstris+=8;
cl_stris = BZ_Realloc(cl_stris, sizeof(*cl_stris)*cl_maxstris);
}
t = &cl_stris[cl_numstris++];
t->shader = shader;
t->firstidx = cl_numstrisidx;
t->firstvert = cl_numstrisvert;
t->numvert = 0;
t->numidx = 0;
t->flags = flags;
}
if (cl_numstrisidx+6 > cl_maxstrisidx)
{
cl_maxstrisidx=cl_numstrisidx+6 + 64;
cl_strisidx = BZ_Realloc(cl_strisidx, sizeof(*cl_strisidx)*cl_maxstrisidx);
}
if (cl_numstrisvert+4 > cl_maxstrisvert)
{
cl_maxstrisvert+=64;
cl_strisvertv = BZ_Realloc(cl_strisvertv, sizeof(*cl_strisvertv)*cl_maxstrisvert);
cl_strisvertt = BZ_Realloc(cl_strisvertt, sizeof(*cl_strisvertt)*cl_maxstrisvert);
cl_strisvertc = BZ_Realloc(cl_strisvertc, sizeof(*cl_strisvertc)*cl_maxstrisvert);
}
{
VectorMA(mid, radius, vright, cl_strisvertv[cl_numstrisvert]);
VectorMA(cl_strisvertv[cl_numstrisvert], radius, vup, cl_strisvertv[cl_numstrisvert]);
Vector4Set(cl_strisvertc[cl_numstrisvert], r, g, b, 0.2);
Vector2Set(cl_strisvertt[cl_numstrisvert], 1, 1);
cl_numstrisvert++;
VectorMA(mid, radius, vright, cl_strisvertv[cl_numstrisvert]);
VectorMA(cl_strisvertv[cl_numstrisvert], -radius, vup, cl_strisvertv[cl_numstrisvert]);
Vector4Set(cl_strisvertc[cl_numstrisvert], r, g, b, 0.2);
Vector2Set(cl_strisvertt[cl_numstrisvert], 1, 0);
cl_numstrisvert++;
VectorMA(mid, -radius, vright, cl_strisvertv[cl_numstrisvert]);
VectorMA(cl_strisvertv[cl_numstrisvert], -radius, vup, cl_strisvertv[cl_numstrisvert]);
Vector4Set(cl_strisvertc[cl_numstrisvert], r, g, b, 0.2);
Vector2Set(cl_strisvertt[cl_numstrisvert], 0, 0);
cl_numstrisvert++;
VectorMA(mid, -radius, vright, cl_strisvertv[cl_numstrisvert]);
VectorMA(cl_strisvertv[cl_numstrisvert], radius, vup, cl_strisvertv[cl_numstrisvert]);
Vector4Set(cl_strisvertc[cl_numstrisvert], r, g, b, 0.2);
Vector2Set(cl_strisvertt[cl_numstrisvert], 0, 1);
cl_numstrisvert++;
}
/*build the triangles*/
cl_strisidx[cl_numstrisidx++] = t->numvert + 0;
cl_strisidx[cl_numstrisidx++] = t->numvert + 1;
cl_strisidx[cl_numstrisidx++] = t->numvert + 2;
cl_strisidx[cl_numstrisidx++] = t->numvert + 0;
cl_strisidx[cl_numstrisidx++] = t->numvert + 2;
cl_strisidx[cl_numstrisidx++] = t->numvert + 3;
t->numidx = cl_numstrisidx - t->firstidx;
t->numvert += 4;
}
#include "shader.h" #include "shader.h"
//well, 8192
void CL_DrawDebugPlane(float *normal, float dist, float r, float g, float b, qboolean enqueue) void CL_DrawDebugPlane(float *normal, float dist, float r, float g, float b, qboolean enqueue)
{ {
const float radius = 8192; //infinite is quite small nowadays.
scenetris_t *t; scenetris_t *t;
if (!enqueue) if (!enqueue)
cl_numstris = 0; cl_numstris = 0;
@ -2501,26 +2604,26 @@ void CL_DrawDebugPlane(float *normal, float dist, float r, float g, float b, qbo
VectorNormalize(forward); VectorNormalize(forward);
VectorScale( normal, dist, cl_strisvertv[cl_numstrisvert]); VectorScale( normal, dist, cl_strisvertv[cl_numstrisvert]);
VectorMA(cl_strisvertv[cl_numstrisvert], 8192, right, cl_strisvertv[cl_numstrisvert]); VectorMA(cl_strisvertv[cl_numstrisvert], radius, right, cl_strisvertv[cl_numstrisvert]);
VectorMA(cl_strisvertv[cl_numstrisvert], 8192, forward, cl_strisvertv[cl_numstrisvert]); VectorMA(cl_strisvertv[cl_numstrisvert], radius, forward, cl_strisvertv[cl_numstrisvert]);
Vector4Set(cl_strisvertc[cl_numstrisvert], r, g, b, 0.2); Vector4Set(cl_strisvertc[cl_numstrisvert], r, g, b, 0.2);
cl_numstrisvert++; cl_numstrisvert++;
VectorScale( normal, dist, cl_strisvertv[cl_numstrisvert]); VectorScale( normal, dist, cl_strisvertv[cl_numstrisvert]);
VectorMA(cl_strisvertv[cl_numstrisvert], 8192, right, cl_strisvertv[cl_numstrisvert]); VectorMA(cl_strisvertv[cl_numstrisvert], radius, right, cl_strisvertv[cl_numstrisvert]);
VectorMA(cl_strisvertv[cl_numstrisvert], -8192, forward, cl_strisvertv[cl_numstrisvert]); VectorMA(cl_strisvertv[cl_numstrisvert], -radius, forward, cl_strisvertv[cl_numstrisvert]);
Vector4Set(cl_strisvertc[cl_numstrisvert], r, g, b, 0.2); Vector4Set(cl_strisvertc[cl_numstrisvert], r, g, b, 0.2);
cl_numstrisvert++; cl_numstrisvert++;
VectorScale( normal, dist, cl_strisvertv[cl_numstrisvert]); VectorScale( normal, dist, cl_strisvertv[cl_numstrisvert]);
VectorMA(cl_strisvertv[cl_numstrisvert], -8192, right, cl_strisvertv[cl_numstrisvert]); VectorMA(cl_strisvertv[cl_numstrisvert], -radius, right, cl_strisvertv[cl_numstrisvert]);
VectorMA(cl_strisvertv[cl_numstrisvert], -8192, forward, cl_strisvertv[cl_numstrisvert]); VectorMA(cl_strisvertv[cl_numstrisvert], -radius, forward, cl_strisvertv[cl_numstrisvert]);
Vector4Set(cl_strisvertc[cl_numstrisvert], r, g, b, 0.2); Vector4Set(cl_strisvertc[cl_numstrisvert], r, g, b, 0.2);
cl_numstrisvert++; cl_numstrisvert++;
VectorScale( normal, dist, cl_strisvertv[cl_numstrisvert]); VectorScale( normal, dist, cl_strisvertv[cl_numstrisvert]);
VectorMA(cl_strisvertv[cl_numstrisvert], -8192, right, cl_strisvertv[cl_numstrisvert]); VectorMA(cl_strisvertv[cl_numstrisvert], -radius, right, cl_strisvertv[cl_numstrisvert]);
VectorMA(cl_strisvertv[cl_numstrisvert], 8192, forward, cl_strisvertv[cl_numstrisvert]); VectorMA(cl_strisvertv[cl_numstrisvert], radius, forward, cl_strisvertv[cl_numstrisvert]);
Vector4Set(cl_strisvertc[cl_numstrisvert], r, g, b, 0.2); Vector4Set(cl_strisvertc[cl_numstrisvert], r, g, b, 0.2);
cl_numstrisvert++; cl_numstrisvert++;
} }
@ -2874,7 +2977,7 @@ static void CL_AddDecal_Callback(void *vctx, vec3_t *fte_restrict points, size_t
cl_strisvertc[cl_numstrisvert+v][0] = ctx->rgbavalue[0]; cl_strisvertc[cl_numstrisvert+v][0] = ctx->rgbavalue[0];
cl_strisvertc[cl_numstrisvert+v][1] = ctx->rgbavalue[1]; cl_strisvertc[cl_numstrisvert+v][1] = ctx->rgbavalue[1];
cl_strisvertc[cl_numstrisvert+v][2] = ctx->rgbavalue[2]; cl_strisvertc[cl_numstrisvert+v][2] = ctx->rgbavalue[2];
cl_strisvertc[cl_numstrisvert+v][3] = ctx->rgbavalue[3] * (1-(DotProduct(points[v], ctx->axis[0]) - ctx->offset[0]) * ctx->scale[0]); cl_strisvertc[cl_numstrisvert+v][3] = ctx->rgbavalue[3] * (1-fabs(DotProduct(points[v], ctx->axis[0]) - ctx->offset[0]) * ctx->scale[0]);
} }
for (v = 0; v < numpoints; v++) for (v = 0; v < numpoints; v++)
{ {
@ -2889,7 +2992,7 @@ static void CL_AddDecal_Callback(void *vctx, vec3_t *fte_restrict points, size_t
void CL_AddDecal(shader_t *shader, vec3_t origin, vec3_t up, vec3_t side, vec3_t rgbvalue, float alphavalue) void CL_AddDecal(shader_t *shader, vec3_t origin, vec3_t up, vec3_t side, vec3_t rgbvalue, float alphavalue)
{ {
scenetris_t *t; scenetris_t *t;
float l, s, radius; float l, s, radius, vradius;
cl_adddecal_ctx_t ctx; cl_adddecal_ctx_t ctx;
VectorNegate(up, ctx.axis[0]); VectorNegate(up, ctx.axis[0]);
@ -2897,20 +3000,24 @@ void CL_AddDecal(shader_t *shader, vec3_t origin, vec3_t up, vec3_t side, vec3_t
s = DotProduct(ctx.axis[2], ctx.axis[2]); s = DotProduct(ctx.axis[2], ctx.axis[2]);
l = DotProduct(ctx.axis[0], ctx.axis[0]); l = DotProduct(ctx.axis[0], ctx.axis[0]);
vradius = 1/sqrt(l);
radius = 1/sqrt(s); radius = 1/sqrt(s);
VectorScale(ctx.axis[0], 1/sqrt(l), ctx.axis[0]); VectorScale(ctx.axis[0], vradius, ctx.axis[0]);
VectorScale(ctx.axis[2], radius, ctx.axis[2]); VectorScale(ctx.axis[2], radius, ctx.axis[2]);
CrossProduct(ctx.axis[0], ctx.axis[2], ctx.axis[1]); CrossProduct(ctx.axis[0], ctx.axis[2], ctx.axis[1]);
ctx.offset[1] = DotProduct(origin, ctx.axis[1]) + 0.5*radius;
ctx.offset[2] = DotProduct(origin, ctx.axis[2]) + 0.5*radius; ctx.offset[2] = DotProduct(origin, ctx.axis[2]) + 0.5*radius;
ctx.offset[1] = DotProduct(origin, ctx.axis[1]) + 0.5*radius;
ctx.offset[0] = DotProduct(origin, ctx.axis[0]); ctx.offset[0] = DotProduct(origin, ctx.axis[0]);
ctx.scale[1] = 1/radius;
ctx.scale[2] = 1/radius; ctx.scale[2] = 1/radius;
ctx.scale[0] = 1; ctx.scale[1] = 1/radius;
ctx.scale[0] = 2/vradius;
if (R2D_Flush)
R2D_Flush();
/*reuse the previous trigroup if its the same shader*/ /*reuse the previous trigroup if its the same shader*/
if (cl_numstris && cl_stris[cl_numstris-1].shader == shader && cl_stris[cl_numstris-1].flags == (BEF_NODLIGHT|BEF_NOSHADOWS)) if (cl_numstris && cl_stris[cl_numstris-1].shader == shader && cl_stris[cl_numstris-1].flags == (BEF_NODLIGHT|BEF_NOSHADOWS))
@ -2934,7 +3041,7 @@ void CL_AddDecal(shader_t *shader, vec3_t origin, vec3_t up, vec3_t side, vec3_t
ctx.t = t; ctx.t = t;
VectorCopy(rgbvalue, ctx.rgbavalue); VectorCopy(rgbvalue, ctx.rgbavalue);
ctx.rgbavalue[3] = alphavalue; ctx.rgbavalue[3] = alphavalue;
Mod_ClipDecal(cl.worldmodel, origin, ctx.axis[0], ctx.axis[1], ctx.axis[2], radius, 0,0, CL_AddDecal_Callback, &ctx); Mod_ClipDecal(cl.worldmodel, origin, ctx.axis[0], ctx.axis[1], ctx.axis[2], max(radius, vradius), 0,0, CL_AddDecal_Callback, &ctx);
if (!t->numidx) if (!t->numidx)
cl_numstris--; cl_numstris--;
@ -4302,6 +4409,10 @@ void CL_LinkPacketEntities (void)
#endif #endif
CLQ1_AddVisibleBBoxes(); CLQ1_AddVisibleBBoxes();
#ifdef RTLIGHTS
R_EditLights_DrawLights();
#endif
} }
/* /*

View file

@ -232,10 +232,10 @@ static_entity_t *cl_static_entities;
unsigned int cl_max_static_entities; unsigned int cl_max_static_entities;
lightstyle_t cl_lightstyle[MAX_LIGHTSTYLES]; lightstyle_t cl_lightstyle[MAX_LIGHTSTYLES];
dlight_t *cl_dlights; dlight_t *cl_dlights;
unsigned int cl_maxdlights; /*size of cl_dlights array*/ size_t cl_maxdlights; /*size of cl_dlights array*/
int cl_baselines_count; int cl_baselines_count;
int rtlights_first, rtlights_max; size_t rtlights_first, rtlights_max;
// refresh list // refresh list
// this is double buffered so the last frame // this is double buffered so the last frame
@ -2448,7 +2448,7 @@ void CL_SetInfo_f (void)
if (Cmd_Argc() == 1) if (Cmd_Argc() == 1)
{ {
InfoBuf_Print (&cls.userinfo[pnum], ""); InfoBuf_Print (&cls.userinfo[pnum], "");
Con_Printf("[%u]", (unsigned int)cls.userinfo[pnum].totalsize); Con_Printf("[%u]\n", (unsigned int)cls.userinfo[pnum].totalsize);
return; return;
} }
if (Cmd_Argc() != 3) if (Cmd_Argc() != 3)
@ -4876,10 +4876,10 @@ void Host_RunFileNotify(struct dl_download *dl)
#define HRF_DEMO (HRF_DEMO_MVD|HRF_DEMO_QWD|HRF_DEMO_DM2|HRF_DEMO_DEM) #define HRF_DEMO (HRF_DEMO_MVD|HRF_DEMO_QWD|HRF_DEMO_DM2|HRF_DEMO_DEM)
#define HRF_FILETYPES (HRF_DEMO|HRF_QTVINFO|HRF_MANIFEST|HRF_BSP|HRF_PACKAGE|HRF_ARCHIVE|HRF_MODEL|HRF_CONFIG) #define HRF_FILETYPES (HRF_DEMO|HRF_QTVINFO|HRF_MANIFEST|HRF_BSP|HRF_PACKAGE|HRF_ARCHIVE|HRF_MODEL|HRF_CONFIG)
typedef struct { typedef struct {
unsigned int flags;
struct dl_download *dl; struct dl_download *dl;
vfsfile_t *srcfile; vfsfile_t *srcfile;
vfsfile_t *dstfile; vfsfile_t *dstfile;
unsigned int flags;
char fname[1]; //system path or url. char fname[1]; //system path or url.
} hrf_t; } hrf_t;
@ -6294,8 +6294,10 @@ void Host_FinishLoading(void)
Menu_Download_Update(); Menu_Download_Update();
#ifdef IPLOG
IPLog_Merge_File("iplog.txt"); IPLog_Merge_File("iplog.txt");
IPLog_Merge_File("iplog.dat"); //legacy crap, for compat with proquake IPLog_Merge_File("iplog.dat"); //legacy crap, for compat with proquake
#endif
} }
if (PM_IsApplying(true)) if (PM_IsApplying(true))

View file

@ -6029,7 +6029,8 @@ void CL_PrintChat(player_info_t *plr, char *msg, int plrflags)
if (con_separatechat.ival == 1) if (con_separatechat.ival == 1)
{ {
Con_PrintCon(&con_main, fullchatmessage, con_main.parseflags|PFS_NONOTIFY); console_t *c = Con_GetMain();
Con_PrintCon(c, fullchatmessage, c->parseflags|PFS_NONOTIFY);
return; return;
} }
} }
@ -6585,7 +6586,7 @@ static void CL_ParsePrecache(void)
} }
} }
static void Con_HexDump(qbyte *packet, size_t len) static void Con_HexDump(qbyte *packet, size_t len, size_t badoffset)
{ {
int i; int i;
int pos; int pos;
@ -6598,6 +6599,8 @@ static void Con_HexDump(qbyte *packet, size_t len)
{ {
if (pos >= len) if (pos >= len)
Con_Printf(" - "); Con_Printf(" - ");
else if (pos == badoffset)
Con_Printf("^b^1%2x ", packet[pos]);
else else
Con_Printf("%2x ", packet[pos]); Con_Printf("%2x ", packet[pos]);
pos++; pos++;
@ -6608,9 +6611,19 @@ static void Con_HexDump(qbyte *packet, size_t len)
if (pos >= len) if (pos >= len)
Con_Printf("X"); Con_Printf("X");
else if (packet[pos] == 0 || packet[pos] == '\t' || packet[pos] == '\r' || packet[pos] == '\n') else if (packet[pos] == 0 || packet[pos] == '\t' || packet[pos] == '\r' || packet[pos] == '\n')
Con_Printf("."); {
if (pos == badoffset)
Con_Printf("^b^1.");
else
Con_Printf(".");
}
else else
Con_Printf("%c", packet[pos]); {
if (pos == badoffset)
Con_Printf("^b^1%c", packet[pos]);
else
Con_Printf("%c", packet[pos]);
}
pos++; pos++;
} }
Con_Printf("\n"); Con_Printf("\n");
@ -6619,7 +6632,7 @@ static void Con_HexDump(qbyte *packet, size_t len)
} }
void CL_DumpPacket(void) void CL_DumpPacket(void)
{ {
Con_HexDump(net_message.data, net_message.cursize); Con_HexDump(net_message.data, net_message.cursize, msg_readcount-1);
} }
static void CL_ParsePortalState(void) static void CL_ParsePortalState(void)

View file

@ -183,8 +183,8 @@ float mousemove_x, mousemove_y;
float multicursor_x[8], multicursor_y[8]; float multicursor_x[8], multicursor_y[8];
qboolean multicursor_active[8]; qboolean multicursor_active[8];
float scr_con_current; float scr_con_current; //current console lines shown
float scr_conlines; // lines of console to display float scr_con_target; //the target number of lines (not a local, because it helps to know if we're at the target yet, etc)
qboolean scr_con_forcedraw; qboolean scr_con_forcedraw;
@ -200,7 +200,6 @@ extern cvar_t scr_printspeed;
extern cvar_t scr_allowsnap; extern cvar_t scr_allowsnap;
extern cvar_t scr_sshot_type; extern cvar_t scr_sshot_type;
extern cvar_t scr_sshot_prefix; extern cvar_t scr_sshot_prefix;
extern cvar_t scr_sshot_compression;
extern cvar_t crosshair; extern cvar_t crosshair;
extern cvar_t scr_consize; extern cvar_t scr_consize;
cvar_t scr_neticontimeout = CVAR("scr_neticontimeout", "0.3"); cvar_t scr_neticontimeout = CVAR("scr_neticontimeout", "0.3");
@ -222,7 +221,7 @@ qboolean scr_disabled_for_loading;
qboolean scr_drawloading; qboolean scr_drawloading;
float scr_disabled_time; float scr_disabled_time;
cvar_t con_stayhidden = CVARFD("con_stayhidden", "0", CVAR_NOTFROMSERVER, "0: allow console to pounce on the user\n1: console stays hidden unless explicitly invoked\n2:toggleconsole command no longer works\n3: shift+escape key no longer works"); cvar_t con_stayhidden = CVARFD("con_stayhidden", "1", CVAR_NOTFROMSERVER, "0: allow console to pounce on the user\n1: console stays hidden unless explicitly invoked\n2:toggleconsole command no longer works\n3: shift+escape key no longer works");
cvar_t show_fps = CVARFD("show_fps", "0", CVAR_ARCHIVE, "Displays the current framerate on-screen.\n1: framerate average over a second.\n2: Slowest frame over the last second (the game will play like shit if this is significantly lower than the average).\n3: Shows the rate of the fastest frame (not very useful).\n4: Shows the current frame's timings (this depends upon timer precision).\n5: Display a graph of how long it took to render each frame, large spikes are BAD BAD BAD.\n6: Displays the standard deviation of the frame times, if its greater than 3 then something is probably badly made, or you've a virus scanner running...\n7: Framegraph, for use with slower frames."); cvar_t show_fps = CVARFD("show_fps", "0", CVAR_ARCHIVE, "Displays the current framerate on-screen.\n1: framerate average over a second.\n2: Slowest frame over the last second (the game will play like shit if this is significantly lower than the average).\n3: Shows the rate of the fastest frame (not very useful).\n4: Shows the current frame's timings (this depends upon timer precision).\n5: Display a graph of how long it took to render each frame, large spikes are BAD BAD BAD.\n6: Displays the standard deviation of the frame times, if its greater than 3 then something is probably badly made, or you've a virus scanner running...\n7: Framegraph, for use with slower frames.");
cvar_t show_fps_x = CVAR("show_fps_x", "-1"); cvar_t show_fps_x = CVAR("show_fps_x", "-1");
cvar_t show_fps_y = CVAR("show_fps_y", "-1"); cvar_t show_fps_y = CVAR("show_fps_y", "-1");
@ -727,7 +726,7 @@ void SCR_DrawCenterString (vrect_t *rect, cprint_t *p, struct font_s *font)
Font_BeginString(font, rect->x, y, &left, &top); Font_BeginString(font, rect->x, y, &left, &top);
Font_BeginString(font, rect->x+rect->width, rect->y+rect->height, &right, &bottom); Font_BeginString(font, rect->x+rect->width, rect->y+rect->height, &right, &bottom);
linecount = Font_LineBreaks(p->string, p->string + p->charcount, right - left, MAX_CPRINT_LINES, line_start, line_end); linecount = Font_LineBreaks(p->string, p->string + p->charcount, (p->flags & CPRINT_NOWRAP)?0x7fffffff:(right - left), MAX_CPRINT_LINES, line_start, line_end);
ch = Font_CharHeight(); ch = Font_CharHeight();
@ -1943,8 +1942,6 @@ void SCR_SetLoadingStage(int stage)
SCR_SetLoadingFile("waiting for connection..."); SCR_SetLoadingFile("waiting for connection...");
break; break;
case LS_SERVER: case LS_SERVER:
if (scr_con_current > vid.height*scr_consize.value)
scr_con_current = vid.height*scr_consize.value;
SCR_SetLoadingFile("starting server..."); SCR_SetLoadingFile("starting server...");
break; break;
case LS_CLIENT: case LS_CLIENT:
@ -2287,85 +2284,85 @@ SCR_SetUpToDrawConsole
void SCR_SetUpToDrawConsole (void) void SCR_SetUpToDrawConsole (void)
{ {
extern int startuppending; //true if we're downloading media or something and have not yet triggered the startup action (read: main menu or cinematic) extern int startuppending; //true if we're downloading media or something and have not yet triggered the startup action (read: main menu or cinematic)
// if (scr_drawloading) float fullscreenpercent = 1;
// return; // never a console with loading plaque
// decide on the height of the console
// if (!scr_disabled_for_loading)
{
float fullscreenpercent = 1;
#ifdef ANDROID #ifdef ANDROID
//android has an onscreen imm that we don't want to obscure //android has an onscreen imm that we don't want to obscure
fullscreenpercent = scr_consize.value; fullscreenpercent = scr_consize.value;
#endif #endif
if (!con_stayhidden.ival && (!Key_Dest_Has(~(kdm_console|kdm_game))) && (!cl.sendprespawn && cl.worldmodel && cl.worldmodel->loadstate != MLS_LOADED)) if (!con_stayhidden.ival && (!Key_Dest_Has(~(kdm_console|kdm_game))) && (!cl.sendprespawn && cl.worldmodel && cl.worldmodel->loadstate != MLS_LOADED))
{
//force console to fullscreen if we're loading stuff (but don't necessarily force focus)
// Key_Dest_Add(kdm_console);
scr_con_target = scr_con_current = vid.height * fullscreenpercent;
}
else if (!startuppending && !Key_Dest_Has(kdm_emenu|kdm_gmenu) && (!Key_Dest_Has(~((!con_stayhidden.ival?kdm_console:0)|kdm_game))) && SCR_GetLoadingStage() == LS_NONE && cls.state < ca_active && !Media_PlayingFullScreen() && !CSQC_UnconnectedOkay(false))
{
//go fullscreen if we're not doing anything
if (con_curwindow && !cls.state && !scr_drawloading && !Key_Dest_Has(kdm_console))
{ {
//force console to fullscreen if we're loading stuff Key_Dest_Add(kdm_cwindows);
// Key_Dest_Add(kdm_console); scr_con_target = 0; // not looking at an normal console
scr_conlines = scr_con_current = vid.height * fullscreenpercent;
} }
else if (!startuppending && !Key_Dest_Has(kdm_emenu|kdm_gmenu) && (!Key_Dest_Has(~((!con_stayhidden.ival?kdm_console:0)|kdm_game))) && SCR_GetLoadingStage() == LS_NONE && cls.state < ca_active && !Media_PlayingFullScreen() && !CSQC_UnconnectedOkay(false))
{
//go fullscreen if we're not doing anything
if (con_curwindow && !cls.state && !scr_drawloading)
{
Key_Dest_Add(kdm_cwindows);
scr_conlines = 0;
}
#ifdef VM_UI #ifdef VM_UI
else if (UI_MenuState() || UI_OpenMenu()) else if (UI_MenuState() || UI_OpenMenu())
scr_con_current = scr_conlines = 0; scr_con_current = scr_con_target = 0; //force instantly hidden.
#endif #endif
else else
{
qboolean legacyfullscreen = false;
if (cls.state < ca_demostart)
{ {
if (cls.state < ca_demostart) if (con_stayhidden.ival)
{ { //go to the menu instead of the console.
if (con_stayhidden.ival) extern int startuppending;
if (!scr_drawloading && SCR_GetLoadingStage() == LS_NONE)
{ {
extern int startuppending; if (CL_TryingToConnect()) //if we're trying to connect, make sure there's a loading/connecting screen showing instead of forcing the menu visible
scr_conlines = 0; SCR_SetLoadingStage(LS_CONNECTION);
if (SCR_GetLoadingStage() == LS_NONE) else if (!Key_Dest_Has(kdm_emenu) && !startuppending) //don't force anything until the startup stuff has been done
{ M_ToggleMenu_f();
if (CL_TryingToConnect()) //if we're trying to connect, make sure there's a loading/connecting screen showing instead of forcing the menu visible
SCR_SetLoadingStage(LS_CONNECTION);
else if (!Key_Dest_Has(kdm_emenu) && !startuppending) //don't force anything until the startup stuff has been done
M_ToggleMenu_f();
}
} }
else }
else
{ //nothing happening, make sure the console is visible or something.
if (!scr_drawloading)
Key_Dest_Add(kdm_console); Key_Dest_Add(kdm_console);
legacyfullscreen = true;
} }
} }
if (Key_Dest_Has(kdm_console) || (!con_stayhidden.ival && !startuppending && !scr_drawloading && !scr_disabled_for_loading && cls.state < ca_connected))
scr_con_current = scr_conlines = vid.height * fullscreenpercent;
else
scr_conlines = 0;
}
else if (Key_Dest_Has(kdm_console))
{
//go half-screen if we're meant to have the console visible
scr_conlines = vid.height*scr_consize.value; // half screen
if (scr_conlines < 32)
scr_conlines = 32; //prevent total loss of console.
else if (scr_conlines>vid.height)
scr_conlines = vid.height;
}
else
scr_conlines = 0; // none visible
if (startuppending)
scr_con_target = 0; //not made any decisions yet
else if (Key_Dest_Has(kdm_console) || legacyfullscreen)
scr_con_current = scr_con_target = vid.height * fullscreenpercent; // force instantly to fullscreen
else
scr_con_target = 0;
}
} }
if (scr_conlines < scr_con_current) else if (Key_Dest_Has(kdm_console))
{
//go half-screen if we're meant to have the console visible
scr_con_target = vid.height*scr_consize.value; // half screen
if (scr_con_target < 32)
scr_con_target = 32; //prevent total loss of console.
else if (scr_con_target>vid.height)
scr_con_target = vid.height;
}
else
scr_con_target = 0; // scroll to nothing
if (scr_con_target < scr_con_current)
{ {
scr_con_current -= scr_conspeed.value*host_frametime * (vid.height/320.0f); scr_con_current -= scr_conspeed.value*host_frametime * (vid.height/320.0f);
if (scr_conlines > scr_con_current) if (scr_con_target > scr_con_current)
scr_con_current = scr_conlines; scr_con_current = scr_con_target;
} }
else if (scr_conlines > scr_con_current) else if (scr_con_target > scr_con_current)
{ {
scr_con_current += scr_conspeed.value*host_frametime * (vid.height/320.0f); scr_con_current += scr_conspeed.value*host_frametime * (vid.height/320.0f);
if (scr_conlines < scr_con_current) if (scr_con_target < scr_con_current)
scr_con_current = scr_conlines; scr_con_current = scr_con_target;
} }
if (scr_con_current>vid.height) if (scr_con_current>vid.height)
@ -2406,266 +2403,6 @@ void SCR_DrawConsole (qboolean noback)
============================================================================== ==============================================================================
*/ */
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;
#if defined(AVAIL_JPEGLIB) && !defined(NO_JPEG)
qboolean screenshotJPEG(char *filename, enum fs_relative fsroot, int compression, qbyte *screendata, int bytestride, int screenwidth, int screenheight, enum uploadfmt fmt);
#endif
#ifdef AVAIL_PNGLIB
int Image_WritePNG (char *filename, enum fs_relative fsroot, int compression, void **buffers, int numbuffers, int bytestride, int width, int height, enum uploadfmt fmt);
#endif
qboolean WriteBMPFile(char *filename, enum fs_relative fsroot, qbyte *in, int instride, int width, int height, uploadfmt_t fmt);
qboolean WriteTGA(char *filename, enum fs_relative fsroot, const qbyte *fte_restrict rgb_buffer, int bytestride, int width, int height, enum uploadfmt fmt)
{
size_t c, i;
vfsfile_t *vfs;
if (fmt != TF_BGRA32 && fmt != TF_RGB24 && fmt != TF_RGBA32 && fmt != TF_BGR24 && fmt != TF_RGBX32 && fmt != TF_BGRX32)
return false;
FS_CreatePath(filename, fsroot);
vfs = FS_OpenVFS(filename, "wb", fsroot);
if (vfs)
{
int ipx,opx;
qboolean rgb;
unsigned char header[18];
memset (header, 0, 18);
if (fmt == TF_BGRA32 || fmt == TF_RGBA32)
{
rgb = fmt==TF_RGBA32;
ipx = 4;
opx = 4;
}
else if (fmt == TF_RGBX32 || fmt == TF_BGRX32)
{
rgb = fmt==TF_RGBX32;
ipx = 4;
opx = 3;
}
else
{
rgb = fmt==TF_RGB24;
ipx = 3;
opx = 3;
}
header[2] = 2; // uncompressed type
header[12] = width&255;
header[13] = width>>8;
header[14] = height&255;
header[15] = height>>8;
header[16] = opx*8; // pixel size
header[17] = 0x00; // flags
if (bytestride < 0)
{ //if we're upside down, lets just use an upside down tga.
rgb_buffer += bytestride*(height-1);
bytestride = -bytestride;
//now we can just do everything without worrying about rows
}
else //our data is top-down, set up the header to also be top-down.
header[17] = 0x20;
if (ipx == opx && !rgb)
{ //can just directly write it
//bgr24, bgra24
c = width*height*opx;
VFS_WRITE(vfs, header, sizeof(header));
VFS_WRITE(vfs, rgb_buffer, c);
}
else
{
qbyte *fte_restrict rgb_out = malloc(width*opx*height);
//no need to swap alpha, and if we're just swapping alpha will be fine in-place.
if (rgb)
{ //rgb24, rgbx32, rgba32
// compact, and swap
c = width*height;
for (i=0 ; i<c ; i++)
{
rgb_out[i*opx+2] = rgb_buffer[i*ipx+0];
rgb_out[i*opx+1] = rgb_buffer[i*ipx+1];
rgb_out[i*opx+0] = rgb_buffer[i*ipx+2];
}
}
else
{ //(bgr24), bgrx32, (bgra32)
// compact
c = width*height;
for (i=0 ; i<c ; i++)
{
rgb_out[i*opx+0] = rgb_buffer[i*ipx+0];
rgb_out[i*opx+1] = rgb_buffer[i*ipx+1];
rgb_out[i*opx+2] = rgb_buffer[i*ipx+2];
}
}
c *= opx;
VFS_WRITE(vfs, header, sizeof(header));
VFS_WRITE(vfs, rgb_out, c);
free(rgb_out);
}
VFS_CLOSE(vfs);
}
return true;
}
/*
Find closest color in the palette for named color
*/
int MipColor(int r, int g, int b)
{
int i;
float dist;
int best=15;
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;
}
qboolean SCR_ScreenShot (char *filename, enum fs_relative fsroot, void **buffer, int numbuffers, int bytestride, int width, int height, enum uploadfmt fmt)
{
#if defined(AVAIL_PNGLIB) || defined(AVAIL_JPEGLIB)
extern cvar_t scr_sshot_compression;
#endif
char ext[8];
void *nbuffers[2];
switch(fmt)
{ //nuke any alpha channel...
case TF_RGBA32: fmt = TF_RGBX32; break;
case TF_BGRA32: fmt = TF_BGRX32; break;
default: break;
}
if (!bytestride)
bytestride = width*4;
if (bytestride < 0)
{ //fix up the buffers so callers don't have to.
int nb = numbuffers;
for (numbuffers = 0; numbuffers < nb && numbuffers < countof(nbuffers); numbuffers++)
nbuffers[numbuffers] = (char*)buffer[numbuffers] - bytestride*(height-1);
buffer = nbuffers;
}
COM_FileExtension(filename, ext, sizeof(ext));
#ifdef AVAIL_PNGLIB
if (!Q_strcasecmp(ext, "png") || !Q_strcasecmp(ext, "pns"))
{
//png can do bgr+rgb
//rgba bgra will result in an extra alpha chan
//actual stereo is also supported. huzzah.
return Image_WritePNG(filename, fsroot, scr_sshot_compression.value, buffer, numbuffers, bytestride, width, height, fmt);
}
else
#endif
#ifdef AVAIL_JPEGLIB
if (!Q_strcasecmp(ext, "jpeg") || !Q_strcasecmp(ext, "jpg"))
{
return screenshotJPEG(filename, fsroot, scr_sshot_compression.value, buffer[0], bytestride, width, height, fmt);
}
else
#endif
if (!Q_strcasecmp(ext, "bmp"))
{
return WriteBMPFile(filename, fsroot, buffer[0], bytestride, width, height, fmt);
}
else
if (!Q_strcasecmp(ext, "pcx"))
{
int y, x, s;
qbyte *src, *dest;
qbyte *srcbuf = buffer[0], *dstbuf;
if (fmt == TF_RGB24 || fmt == TF_RGBA32 || fmt == TF_RGBX32)
{
dstbuf = malloc(width*height);
s = (fmt == TF_RGB24)?3:4;
// convert in-place to eight bit
for (y = 0; y < height; y++)
{
src = srcbuf + (bytestride * y);
dest = dstbuf + (width * y);
for (x = 0; x < width; x++) {
*dest++ = MipColor(src[0], src[1], src[2]);
src += s;
}
}
}
else if (fmt == TF_BGR24 || fmt == TF_BGRA32 || fmt == TF_BGRX32)
{
dstbuf = malloc(width*height);
s = (fmt == TF_BGR24)?3:4;
// convert in-place to eight bit
for (y = 0; y < height; y++)
{
src = srcbuf + (bytestride * y);
dest = dstbuf + (width * y);
for (x = 0; x < width; x++) {
*dest++ = MipColor(src[2], src[1], src[0]);
src += s;
}
}
}
else
return false;
WritePCXfile (filename, fsroot, dstbuf, width, height, width, host_basepal, false);
free(dstbuf);
}
else if (!Q_strcasecmp(ext, "tga")) //tga
return WriteTGA(filename, fsroot, buffer[0], bytestride, width, height, fmt);
/*else if (!Q_strcasecmp(ext, "ktx")) //ktx
{
struct pendingtextureinfo out = {PTI_2D};
out.encoding = fmt;
out.mipcount = 1;
out.mip[0].data = buffer[0];
out.mip[0].datasize = bytestride*height;
out.mip[0].width = width;
out.mip[0].height = height;
out.mip[0].depth = 1;
return Image_WriteKTXFile(filename, fsroot, &out);
}*/
else //extension / type not recognised.
return false;
return true;
}
/* /*
================== ==================
SCR_ScreenShot_f SCR_ScreenShot_f
@ -2726,7 +2463,8 @@ static void SCR_ScreenShot_f (void)
rgbbuffer = VID_GetRGBInfo(&stride, &width, &height, &fmt); rgbbuffer = VID_GetRGBInfo(&stride, &width, &height, &fmt);
if (rgbbuffer) if (rgbbuffer)
{ {
if (SCR_ScreenShot(pcxname, FS_GAMEONLY, &rgbbuffer, 1, stride, width, height, fmt)) //regarding metadata - we don't really know what's on the screen, so don't write something that may be wrong (eg: if there's only a console, don't claim that its a 360 image)
if (SCR_ScreenShot(pcxname, FS_GAMEONLY, &rgbbuffer, 1, stride, width, height, fmt, false))
{ {
Con_Printf ("Wrote %s\n", sysname); Con_Printf ("Wrote %s\n", sysname);
BZ_Free(rgbbuffer); BZ_Free(rgbbuffer);
@ -2737,7 +2475,7 @@ static void SCR_ScreenShot_f (void)
Con_Printf (CON_ERROR "Couldn't write %s\n", sysname); Con_Printf (CON_ERROR "Couldn't write %s\n", sysname);
} }
void *SCR_ScreenShot_Capture(int fbwidth, int fbheight, int *stride, enum uploadfmt *fmt) void *SCR_ScreenShot_Capture(int fbwidth, int fbheight, int *stride, enum uploadfmt *fmt, qboolean no2d)
{ {
int width, height; int width, height;
void *buf; void *buf;
@ -2764,7 +2502,7 @@ void *SCR_ScreenShot_Capture(int fbwidth, int fbheight, int *stride, enum upload
#endif #endif
if (!okay && r_worldentity.model) if (!okay && r_worldentity.model)
{ {
V_RenderView (); V_RenderView (no2d);
okay = true; okay = true;
} }
//fixme: add a way to get+save the depth values too //fixme: add a way to get+save the depth values too
@ -2792,6 +2530,7 @@ void *SCR_ScreenShot_Capture(int fbwidth, int fbheight, int *stride, enum upload
static void SCR_ScreenShot_Mega_f(void) static void SCR_ScreenShot_Mega_f(void)
{ {
extern cvar_t r_projection;
int stride[2]; int stride[2];
int width[2]; int width[2];
int height[2]; int height[2];
@ -2801,6 +2540,7 @@ static void SCR_ScreenShot_Mega_f(void)
int buf; int buf;
char filename[MAX_QPATH]; char filename[MAX_QPATH];
stereomethod_t osm = r_refdef.stereomethod; stereomethod_t osm = r_refdef.stereomethod;
int projection = r_projection.ival;
//massage the rendering code to redraw the screen with an fbo forced. //massage the rendering code to redraw the screen with an fbo forced.
//this allows us to generate screenshots which are not otherwise possible to actually draw. //this allows us to generate screenshots which are not otherwise possible to actually draw.
@ -2841,8 +2581,12 @@ static void SCR_ScreenShot_Mega_f(void)
mangle = COM_SkipPath(filename); mangle = COM_SkipPath(filename);
Q_snprintfz(mangle, sizeof(filename) - (mangle-filename), "%s", screenyname); Q_snprintfz(mangle, sizeof(filename) - (mangle-filename), "%s", screenyname);
} }
if (!strcmp(Cmd_Argv(0), "screenshot_360"))
r_projection.ival = PROJ_EQUIRECTANGULAR;
if (!strcmp(Cmd_Argv(0), "screenshot_stereo")) if (!strcmp(Cmd_Argv(0), "screenshot_stereo"))
COM_DefaultExtension (filename, "png", sizeof(filename)); COM_DefaultExtension (filename, "png", sizeof(filename)); //png/pns is the only format that can really cope with this right now.
else else
COM_DefaultExtension (filename, scr_sshot_type.string, sizeof(filename)); COM_DefaultExtension (filename, scr_sshot_type.string, sizeof(filename));
@ -2868,7 +2612,7 @@ static void SCR_ScreenShot_Mega_f(void)
r_refdef.stereomethod = STEREO_LEFTONLY; r_refdef.stereomethod = STEREO_LEFTONLY;
} }
buffers[buf] = SCR_ScreenShot_Capture(fbwidth, fbheight, &stride[buf], &fmt[buf]); buffers[buf] = SCR_ScreenShot_Capture(fbwidth, fbheight, &stride[buf], &fmt[buf], false);
width[buf] = fbwidth; width[buf] = fbwidth;
height[buf] = fbheight; height[buf] = fbheight;
@ -2885,7 +2629,7 @@ static void SCR_ScreenShot_Mega_f(void)
//okay, we drew something, we're good to save a screeny. //okay, we drew something, we're good to save a screeny.
if (buffers[0]) if (buffers[0])
{ {
if (SCR_ScreenShot(filename, FS_GAMEONLY, buffers, numbuffers, stride[0], width[0], height[0], fmt[0])) if (SCR_ScreenShot(filename, FS_GAMEONLY, buffers, numbuffers, stride[0], width[0], height[0], fmt[0], true))
{ {
char sysname[1024]; char sysname[1024];
FS_NativePath(filename, FS_GAMEONLY, sysname, sizeof(sysname)); FS_NativePath(filename, FS_GAMEONLY, sysname, sizeof(sysname));
@ -2899,11 +2643,13 @@ static void SCR_ScreenShot_Mega_f(void)
BZ_Free(buffers[buf]); BZ_Free(buffers[buf]);
r_refdef.stereomethod = osm; r_refdef.stereomethod = osm;
r_projection.ival = projection;
} }
static void SCR_ScreenShot_VR_f(void) static void SCR_ScreenShot_VR_f(void)
{ {
char *screenyname = Cmd_Argv(1); char *screenyname = Cmd_Argv(1);
const char *ext;
int width = atoi(Cmd_Argv(2)); int width = atoi(Cmd_Argv(2));
int stride=0; int stride=0;
//we spin the camera around, taking slices from equirectangular screenshots //we spin the camera around, taking slices from equirectangular screenshots
@ -2911,13 +2657,14 @@ static void SCR_ScreenShot_VR_f(void)
int height; //equirectangular 360 * 180 gives a nice clean ratio int height; //equirectangular 360 * 180 gives a nice clean ratio
int px = 4; int px = 4;
int step = atof(Cmd_Argv(3)); int step = atof(Cmd_Argv(3));
void *left_buffer, *right_buffer, *buf; void *buffer[2], *buf;
enum uploadfmt fmt; enum uploadfmt fmt;
int lx, rx, x, y; int lx, rx, x, y;
vec3_t baseang; vec3_t baseang;
float ang; float ang;
qboolean fail = false; qboolean fail = false;
extern cvar_t r_projection, r_stereo_separation, r_stereo_convergence;; extern cvar_t r_projection, r_stereo_separation, r_stereo_convergence;
qboolean stereo;
VectorCopy(r_refdef.viewangles, baseang); VectorCopy(r_refdef.viewangles, baseang);
if (width <= 2) if (width <= 2)
@ -2928,8 +2675,8 @@ static void SCR_ScreenShot_VR_f(void)
if (step <= 0) if (step <= 0)
step = 5; step = 5;
left_buffer = BZF_Malloc (width*height*2*px); buffer[0] = BZF_Malloc (width*height*2*px);
right_buffer = (qbyte*)left_buffer + width*height*px; buffer[1] = (qbyte*)buffer[0] + width*height*px;
if (strstr (screenyname, "..") || strchr(screenyname, ':') || *screenyname == '.' || *screenyname == '/') if (strstr (screenyname, "..") || strchr(screenyname, ':') || *screenyname == '.' || *screenyname == '/')
screenyname = ""; screenyname = "";
@ -2947,9 +2694,12 @@ static void SCR_ScreenShot_VR_f(void)
} }
COM_DefaultExtension (filename, scr_sshot_type.string, sizeof(filename)); COM_DefaultExtension (filename, scr_sshot_type.string, sizeof(filename));
ext = COM_GetFileExtension(filename, NULL);
stereo = !strcasecmp(ext, ".pns") || !strcasecmp(ext, ".jns");
if (!left_buffer)
if (!buffer[0])
{ {
Con_Printf("out of memory\n"); Con_Printf("out of memory\n");
return; return;
@ -2977,22 +2727,22 @@ static void SCR_ScreenShot_VR_f(void)
r_refdef.eyeoffset[0] = sin(ang) * r_stereo_separation.value * 0.5; r_refdef.eyeoffset[0] = sin(ang) * r_stereo_separation.value * 0.5;
r_refdef.eyeoffset[1] = cos(ang) * r_stereo_separation.value * 0.5; r_refdef.eyeoffset[1] = cos(ang) * r_stereo_separation.value * 0.5;
r_refdef.eyeoffset[2] = 0; r_refdef.eyeoffset[2] = 0;
buf = SCR_ScreenShot_Capture(width, height, &stride, &fmt); buf = SCR_ScreenShot_Capture(width, height, &stride, &fmt, true);
switch(fmt) switch(fmt)
{ {
case TF_BGRA32: case TF_BGRA32:
for (y = 0; y < height; y++) for (y = 0; y < height; y++)
for (x = lx; x < rx; x++) for (x = lx; x < rx; x++)
((unsigned int*)left_buffer)[y*width + x] = ((unsigned int*)buf)[y*width + x]; ((unsigned int*)buffer[0])[y*width + x] = ((unsigned int*)buf)[y*width + x];
break; break;
case TF_RGB24: case TF_RGB24:
for (y = 0; y < height; y++) for (y = 0; y < height; y++)
for (x = lx; x < rx; x++) for (x = lx; x < rx; x++)
{ {
((qbyte*)left_buffer)[(y*width + x)*4+0] = ((qbyte*)buf)[(y*width + x)*3+2]; ((qbyte*)buffer[0])[(y*width + x)*4+0] = ((qbyte*)buf)[(y*width + x)*3+2];
((qbyte*)left_buffer)[(y*width + x)*4+1] = ((qbyte*)buf)[(y*width + x)*3+1]; ((qbyte*)buffer[0])[(y*width + x)*4+1] = ((qbyte*)buf)[(y*width + x)*3+1];
((qbyte*)left_buffer)[(y*width + x)*4+2] = ((qbyte*)buf)[(y*width + x)*3+0]; ((qbyte*)buffer[0])[(y*width + x)*4+2] = ((qbyte*)buf)[(y*width + x)*3+0];
((qbyte*)left_buffer)[(y*width + x)*4+3] = 255; ((qbyte*)buffer[0])[(y*width + x)*4+3] = 255;
} }
break; break;
default: default:
@ -3011,22 +2761,22 @@ static void SCR_ScreenShot_VR_f(void)
r_refdef.eyeoffset[0] *= -1; r_refdef.eyeoffset[0] *= -1;
r_refdef.eyeoffset[1] *= -1; r_refdef.eyeoffset[1] *= -1;
r_refdef.eyeoffset[2] = 0; r_refdef.eyeoffset[2] = 0;
buf = SCR_ScreenShot_Capture(width, height, &stride, &fmt); buf = SCR_ScreenShot_Capture(width, height, &stride, &fmt, true);
switch(fmt) switch(fmt)
{ {
case TF_BGRA32: case TF_BGRA32:
for (y = 0; y < height; y++) for (y = 0; y < height; y++)
for (x = lx; x < rx; x++) for (x = lx; x < rx; x++)
((unsigned int*)right_buffer)[y*width + x] = ((unsigned int*)buf)[y*width + x]; ((unsigned int*)buffer)[y*width + x] = ((unsigned int*)buf)[y*width + x];
break; break;
case TF_RGB24: case TF_RGB24:
for (y = 0; y < height; y++) for (y = 0; y < height; y++)
for (x = lx; x < rx; x++) for (x = lx; x < rx; x++)
{ {
((qbyte*)right_buffer)[(y*width + x)*4+0] = ((qbyte*)buf)[(y*width + x)*3+2]; ((qbyte*)buffer[1])[(y*width + x)*4+0] = ((qbyte*)buf)[(y*width + x)*3+2];
((qbyte*)right_buffer)[(y*width + x)*4+1] = ((qbyte*)buf)[(y*width + x)*3+1]; ((qbyte*)buffer[1])[(y*width + x)*4+1] = ((qbyte*)buf)[(y*width + x)*3+1];
((qbyte*)right_buffer)[(y*width + x)*4+2] = ((qbyte*)buf)[(y*width + x)*3+0]; ((qbyte*)buffer[1])[(y*width + x)*4+2] = ((qbyte*)buf)[(y*width + x)*3+0];
((qbyte*)right_buffer)[(y*width + x)*4+3] = 255; ((qbyte*)buffer[1])[(y*width + x)*4+3] = 255;
} }
break; break;
default: default:
@ -3038,31 +2788,82 @@ static void SCR_ScreenShot_VR_f(void)
if (fail) if (fail)
Con_Printf ("Unable to capture suitable screen image\n"); Con_Printf ("Unable to capture suitable screen image\n");
else if (SCR_ScreenShot(filename, FS_GAMEONLY, &left_buffer, 1, stride, width, height*2, TF_BGRA32)) else if (SCR_ScreenShot(filename, FS_GAMEONLY, buffer, (stereo?2:1), stride, width, height*(stereo?1:2), TF_BGRX32, true))
{ {
char sysname[1024]; char sysname[1024];
FS_NativePath(filename, FS_GAMEONLY, sysname, sizeof(sysname)); FS_NativePath(filename, FS_GAMEONLY, sysname, sizeof(sysname));
Con_Printf ("Wrote %s\n", sysname); Con_Printf ("Wrote %s\n", sysname);
} }
BZ_Free(left_buffer); BZ_Free(buffer[0]);
r_projection.ival = r_projection.value; r_projection.ival = r_projection.value;
VectorCopy(baseang, r_refdef.viewangles); VectorCopy(baseang, r_refdef.viewangles);
VectorClear(r_refdef.eyeoffset); VectorClear(r_refdef.eyeoffset);
} }
//flips an image so that the result is always top-down
static void *SCR_ScreenShot_FixStride(void *buffer, unsigned int fbwidth, unsigned int fbheight, int *stride, uploadfmt_t fmt, qboolean horizontalflip, qboolean verticalflip)
{
unsigned int bb, bw, bh;
Image_BlockSizeForEncoding(fmt, &bb, &bw, &bh);
if (bw == 1 && bh == 1)
{
if (horizontalflip)
{
int y, x, p;
char *bad = buffer;
char *in = buffer, *out;
buffer = out = BZ_Malloc(fbwidth*fbheight*bb);
if (*stride < 0)
in += fbwidth*bb*(fbheight-1);
for (y = 0; y < fbheight; y++, in += *stride, out += fbwidth*bb)
{
for (x = 0; x < fbwidth*bb; x+=bb)
{
for (p = 0; p < bb; p++)
out[x+p] = in[(fbwidth-1)*bb-x+p];
}
}
BZ_Free(bad);
*stride = fbwidth*bb;
}
if (verticalflip && bh == 1)
*stride = -*stride;
if (*stride != fbwidth*bw)
{
unsigned int y;
char *tofree = buffer;
char *out = BZ_Malloc(fbwidth*fbheight*bb);
char *in = buffer;
buffer = out;
if (*stride < 0)
in += fbwidth*bb*(fbheight-1); //the memory pointer always starts at the lowest address regardless of bottom-up state.
for (y = 0; y < fbheight; y++, in += *stride, out += fbwidth*bb)
{
memcpy(out, in, fbwidth*bb);
}
BZ_Free(tofree);
*stride = fbwidth*bb;
}
}
return buffer;
}
void SCR_ScreenShot_Cubemap_f(void) void SCR_ScreenShot_Cubemap_f(void)
{ {
void *buffer; void *buffer;
int stride, fbwidth, fbheight; int stride, fbwidth, fbheight;
uploadfmt_t fmt; uploadfmt_t fmt;
char filename[MAX_QPATH]; char filename[MAX_QPATH];
char sysname[1024];
char *fname = Cmd_Argv(1); char *fname = Cmd_Argv(1);
int i, firstside; int i, firstside;
char olddrawviewmodel[64]; //hack, so we can set r_drawviewmodel to 0 so that it doesn't appear in screenshots even if the csqc is generating new data. char olddrawviewmodel[64]; //hack, so we can set r_drawviewmodel to 0 so that it doesn't appear in screenshots even if the csqc is generating new data.
vec3_t oldangles; vec3_t oldangles;
const struct struct pendingtextureinfo mips;
static const struct
{ {
vec3_t angle; vec3_t angle;
const char *postfix; const char *postfix;
@ -3086,6 +2887,8 @@ void SCR_ScreenShot_Cubemap_f(void)
{{90, 0, 0}, "_dn"}, {{90, 0, 0}, "_dn"},
{{-90, 0, 0}, "_up"} {{-90, 0, 0}, "_up"}
}; };
const char *ext;
unsigned int bb, bw, bh;
if (!cls.state || !cl.worldmodel || cl.worldmodel->loadstate != MLS_LOADED) if (!cls.state || !cl.worldmodel || cl.worldmodel->loadstate != MLS_LOADED)
{ {
@ -3106,74 +2909,146 @@ void SCR_ScreenShot_Cubemap_f(void)
fbheight = 512; fbheight = 512;
fbwidth = fbheight; fbwidth = fbheight;
for (i = firstside; i < firstside+6; i++) ext = COM_GetFileExtension(fname, NULL);
if (!*fname || ext == fname)
{ //generate a default filename if none exists yet.
char base[MAX_QPATH];
COM_FileBase(cl.worldmodel->name, base, sizeof(base));
fname = va("%s/%i_%i_%i", base, (int)r_refdef.vieworg[0], (int)r_refdef.vieworg[1], (int)r_refdef.vieworg[2]);
}
if (!strcmp(ext, ".ktx") || !strcmp(ext, ".dds"))
{ {
if (!*fname) qboolean fail = false;
mips.type = PTI_CUBEMAP;
mips.encoding = 0;
mips.extrafree = NULL;
mips.mipcount = 6;
for (i = 0; i < 6; i++)
{ {
char base[MAX_QPATH]; VectorCopy(sides[i].angle, cl.playerview->simangles);
COM_FileBase(cl.worldmodel->name, base, sizeof(base)); VectorCopy(cl.playerview->simangles, cl.playerview->viewangles);
fname = va("%s/%i_%i_%i", base, (int)r_refdef.vieworg[0], (int)r_refdef.vieworg[1], (int)r_refdef.vieworg[2]);
mips.mip[i].data = SCR_ScreenShot_Capture(fbwidth, fbheight, &stride, &fmt, true);
if (!mips.mip[i].data)
fail = true;
if (!i)
mips.encoding = fmt;
else if (fmt != mips.encoding || fbwidth != mips.mip[0].width || fbheight != mips.mip[0].height)
fail = true; //zomgwtfbbq
mips.mip[i].data = SCR_ScreenShot_FixStride(mips.mip[i].data, fbwidth, fbheight, &stride, fmt, sides[i].horizontalflip, sides[i].verticalflip);
Image_BlockSizeForEncoding(fmt, &bb, &bw, &bh);
mips.mip[i].datasize = bb*((fbwidth+bw-1)/bw)*((fbheight+bh-1)/bh);
mips.mip[i].width = fbwidth;
mips.mip[i].height = fbheight;
mips.mip[i].depth = 0;
mips.mip[i].needfree = true;
} }
Q_snprintfz(filename, sizeof(filename), "textures/%s%s", fname, sides[i].postfix);
COM_DefaultExtension (filename, scr_sshot_type.string, sizeof(filename));
VectorCopy(sides[i].angle, cl.playerview->simangles); /*FIXME:
VectorCopy(cl.playerview->simangles, cl.playerview->viewangles); while (!fail && (w > 1 || h > 1))
{ //warning: d3d is different
w = max(1,w>>1);
h = max(1,h>>1);
if (mips.mipcount+6 > countof(mips.mip))
break; //erk! how big was the original image?!?
buffer = SCR_ScreenShot_Capture(fbwidth, fbheight, &stride, &fmt); for (i = 0; i < 6; i++)
if (buffer)
{
char sysname[1024];
if (sides[i].horizontalflip)
{ {
int y, x, p; mips.mip[mips.mipcount] = GenerateMip(mips.mip[mips.mipcount-6]);
int pxsize; mips.mipcount++;
char *bad = buffer;
char *in = buffer, *out;
switch(fmt)
{
case TF_RGBA32:
case TF_BGRA32:
case TF_RGBX32:
case TF_BGRX32:
pxsize = 4;
break;
case TF_RGB24:
case TF_BGR24:
pxsize = 3;
break;
default: //erk!
pxsize = 1;
break;
}
buffer = out = BZ_Malloc(fbwidth*fbheight*pxsize);
for (y = 0; y < fbheight; y++, in += abs(stride), out += fbwidth*pxsize)
{
for (x = 0; x < fbwidth*pxsize; x+=pxsize)
{
for (p = 0; p < pxsize; p++)
out[x+p] = in[(fbwidth-1)*pxsize-x+p];
}
}
BZ_Free(bad);
if (stride < 0)
stride = -fbwidth*pxsize;
else
stride = fbwidth*pxsize;
} }
if (sides[i].verticalflip) }
stride = -stride; */
if (SCR_ScreenShot(filename, FS_GAMEONLY, &buffer, 1, stride, fbwidth, fbheight, fmt))
Q_snprintfz(filename, sizeof(filename), "textures/%s", fname);
COM_DefaultExtension (filename, ext, sizeof(filename));
#ifdef IMAGEFMT_KTX
COM_DefaultExtension (filename, ".ktx", sizeof(filename));
#endif
#ifdef IMAGEFMT_DDS
COM_DefaultExtension (filename, ".dds", sizeof(filename));
#endif
ext = COM_GetFileExtension(filename, NULL);
if (fail)
Con_Printf("Unable to generate cubemap data\n");
#ifdef IMAGEFMT_DDS
else if (!strcmp(ext, ".dds"))
{
if (Image_WriteDDSFile(filename, FS_GAMEONLY, &mips))
{ {
FS_NativePath(filename, FS_GAMEONLY, sysname, sizeof(sysname)); FS_NativePath(filename, FS_GAMEONLY, sysname, sizeof(sysname));
Con_Printf ("Wrote %s\n", sysname); Con_Printf ("Wrote %s\n", sysname);
} }
else }
#endif
#ifdef IMAGEFMT_KTX
else if (!strcmp(ext, ".ktx"))
{
if (Image_WriteKTXFile(filename, FS_GAMEONLY, &mips))
{ {
FS_NativePath(filename, FS_GAMEONLY, sysname, sizeof(sysname)); FS_NativePath(filename, FS_GAMEONLY, sysname, sizeof(sysname));
Con_Printf ("Failed to write %s\n", sysname); Con_Printf ("Wrote %s\n", sysname);
}
}
#endif
else
Con_Printf ("%s: Unknown format %s\n", Cmd_Argv(0), filename);
while (i-- > 0)
if (mips.mip[i].needfree)
BZ_Free(mips.mip[i].data);
}
else
{
for (i = firstside; i < firstside+6; i++)
{
VectorCopy(sides[i].angle, cl.playerview->simangles);
VectorCopy(cl.playerview->simangles, cl.playerview->viewangles);
buffer = SCR_ScreenShot_Capture(fbwidth, fbheight, &stride, &fmt, true);
if (buffer)
{
Image_BlockSizeForEncoding(fmt, &bb, &bw, &bh);
if (sides[i].horizontalflip)
{
int y, x, p;
char *bad = buffer;
char *in = buffer, *out;
buffer = out = BZ_Malloc(fbwidth*fbheight*bb);
for (y = 0; y < fbheight; y++, in += abs(stride), out += fbwidth*bb)
{
for (x = 0; x < fbwidth*bb; x+=bb)
{
for (p = 0; p < bb; p++)
out[x+p] = in[(fbwidth-1)*bb-x+p];
}
}
BZ_Free(bad);
if (stride < 0)
stride = -fbwidth*bb;
else
stride = fbwidth*bb;
}
if (sides[i].verticalflip)
stride = -stride;
Q_snprintfz(filename, sizeof(filename), "textures/%s%s", fname, sides[i].postfix);
COM_DefaultExtension (filename, scr_sshot_type.string, sizeof(filename));
if (SCR_ScreenShot(filename, FS_GAMEONLY, &buffer, 1, stride, fbwidth, fbheight, fmt, false))
{
FS_NativePath(filename, FS_GAMEONLY, sysname, sizeof(sysname));
Con_Printf ("Wrote %s\n", sysname);
}
else
{
FS_NativePath(filename, FS_GAMEONLY, sysname, sizeof(sysname));
Con_Printf ("Failed to write %s\n", sysname);
}
BZ_Free(buffer);
} }
BZ_Free(buffer);
} }
} }
@ -3527,6 +3402,7 @@ void SCR_Init (void)
// //
Cmd_AddCommandD ("screenshot_mega",SCR_ScreenShot_Mega_f, "screenshot_mega <name> [width] [height]\nTakes a screenshot with explicit sizes that are not tied to the size of your monitor, allowing for true monstrosities."); Cmd_AddCommandD ("screenshot_mega",SCR_ScreenShot_Mega_f, "screenshot_mega <name> [width] [height]\nTakes a screenshot with explicit sizes that are not tied to the size of your monitor, allowing for true monstrosities.");
Cmd_AddCommandD ("screenshot_stereo",SCR_ScreenShot_Mega_f, "screenshot_stereo <name> [width] [height]\nTakes a simple stereo screenshot."); Cmd_AddCommandD ("screenshot_stereo",SCR_ScreenShot_Mega_f, "screenshot_stereo <name> [width] [height]\nTakes a simple stereo screenshot.");
Cmd_AddCommandD ("screenshot_360",SCR_ScreenShot_Mega_f, "screenshot_360 <name> [width] [height]\nTakes an equirectangular screenshot.");
Cmd_AddCommandD ("screenshot_vr",SCR_ScreenShot_VR_f, "screenshot_vr <name> [width]\nTakes a spherical stereoscopic panorama image, for viewing with VR displays."); Cmd_AddCommandD ("screenshot_vr",SCR_ScreenShot_VR_f, "screenshot_vr <name> [width]\nTakes a spherical stereoscopic panorama image, for viewing with VR displays.");
Cmd_AddCommandD ("screenshot_cubemap",SCR_ScreenShot_Cubemap_f, "screenshot_cubemap <name> [size]\nTakes 6 screenshots forming a single cubemap."); Cmd_AddCommandD ("screenshot_cubemap",SCR_ScreenShot_Cubemap_f, "screenshot_cubemap <name> [size]\nTakes 6 screenshots forming a single cubemap.");
Cmd_AddCommandD ("envmap",SCR_ScreenShot_Cubemap_f, "Legacy name for the screenshot_cubemap command."); //legacy Cmd_AddCommandD ("envmap",SCR_ScreenShot_Cubemap_f, "Legacy name for the screenshot_cubemap command."); //legacy

View file

@ -1561,8 +1561,6 @@ qboolean UI_KeyPress(int key, int unicode, qboolean down)
} }
UI_OpenMenu(); UI_OpenMenu();
scr_conlines = 0;
return true; return true;
} }
return false; return false;

View file

@ -315,6 +315,7 @@ typedef struct dlight_s
int key; // so entities can reuse same entry int key; // so entities can reuse same entry
vec3_t origin; vec3_t origin;
vec3_t axis[3]; vec3_t axis[3];
vec3_t angles; //used only for reflection, to avoid things getting rounded/cycled.
vec3_t rotation; //cubemap/spotlight rotation vec3_t rotation; //cubemap/spotlight rotation
float radius; float radius;
float die; // stop lighting after this time float die; // stop lighting after this time
@ -330,6 +331,7 @@ typedef struct dlight_s
unsigned int flags; unsigned int flags;
char cubemapname[64]; char cubemapname[64];
char *customstyle;
int coronaocclusionquery; int coronaocclusionquery;
unsigned int coronaocclusionresult; unsigned int coronaocclusionresult;
@ -780,7 +782,7 @@ typedef struct
double last_servermessage; double last_servermessage;
//list of ent frames that still need to be acked. //list of ent frames that still need to be acked.
int numackframes; unsigned int numackframes;
int ackframes[64]; int ackframes[64];
#ifdef Q2CLIENT #ifdef Q2CLIENT
@ -1049,9 +1051,9 @@ extern static_entity_t *cl_static_entities;
extern unsigned int cl_max_static_entities; extern unsigned int cl_max_static_entities;
extern lightstyle_t cl_lightstyle[MAX_LIGHTSTYLES]; extern lightstyle_t cl_lightstyle[MAX_LIGHTSTYLES];
extern dlight_t *cl_dlights; extern dlight_t *cl_dlights;
extern unsigned int cl_maxdlights; extern size_t cl_maxdlights;
extern int rtlights_first, rtlights_max; extern size_t rtlights_first, rtlights_max;
extern int cl_baselines_count; extern int cl_baselines_count;
extern qboolean nomaster; extern qboolean nomaster;
@ -1068,6 +1070,7 @@ dlight_t *CL_AllocDlight (int key);
dlight_t *CL_AllocSlight (void); //allocates a static light dlight_t *CL_AllocSlight (void); //allocates a static light
dlight_t *CL_NewDlight (int key, const vec3_t origin, float radius, float time, float r, float g, float b); dlight_t *CL_NewDlight (int key, const vec3_t origin, float radius, float time, float r, float g, float b);
dlight_t *CL_NewDlightCube (int key, const vec3_t origin, vec3_t angles, float radius, float time, vec3_t colours); dlight_t *CL_NewDlightCube (int key, const vec3_t origin, vec3_t angles, float radius, float time, vec3_t colours);
void CL_CloneDlight(dlight_t *dl, dlight_t *src); //copies one light to another safely
void CL_DecayLights (void); void CL_DecayLights (void);
void CLQW_ParseDelta (struct entity_state_s *from, struct entity_state_s *to, int bits); void CLQW_ParseDelta (struct entity_state_s *from, struct entity_state_s *to, int bits);
@ -1305,7 +1308,7 @@ qboolean CL_CheckBaselines (int size);
void V_StartPitchDrift (playerview_t *pv); void V_StartPitchDrift (playerview_t *pv);
void V_StopPitchDrift (playerview_t *pv); void V_StopPitchDrift (playerview_t *pv);
void V_RenderView (void); void V_RenderView (qboolean no2d);
void V_Register (void); void V_Register (void);
void V_ParseDamage (playerview_t *pv); void V_ParseDamage (playerview_t *pv);
void V_SetContentsColor (int contents); void V_SetContentsColor (int contents);

View file

@ -22,10 +22,12 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "quakedef.h" #include "quakedef.h"
#include "shader.h" #include "shader.h"
console_t con_main; console_t *con_head; // first console in the list
console_t *con_curwindow; console_t *con_curwindow; // the (window) console that's currently got focus.
console_t *con_current; // points to whatever is the visible console console_t *con_current; // points to whatever is the active console (the one that has focus ONLY when kdm_console)
console_t *con_mouseover; // points to whichever console's title is currently mouseovered, or null console_t *con_mouseover; // points to whichever console's title is currently mouseovered, or null
console_t *con_main; // the default console that text will be thrown at. recreated as needed.
console_t *con_chat; // points to a chat console console_t *con_chat; // points to a chat console
#define Font_ScreenWidth() (vid.pixelwidth) #define Font_ScreenWidth() (vid.pixelwidth)
@ -55,27 +57,55 @@ qterm_t *activeqterm;
//int con_linewidth; // characters across screen //int con_linewidth; // characters across screen
//int con_totallines; // total lines in console scrollback //int con_totallines; // total lines in console scrollback
float con_cursorspeed = 4; static float con_cursorspeed = 4;
cvar_t con_numnotifylines = CVAR("con_notifylines","4"); //max lines to show static cvar_t con_numnotifylines = CVAR("con_notifylines","4"); //max lines to show
cvar_t con_notifytime = CVAR("con_notifytime","3"); //seconds static cvar_t con_notifytime = CVAR("con_notifytime","3"); //seconds
cvar_t con_notify_x = CVAR("con_notify_x","0"); static cvar_t con_notify_x = CVAR("con_notify_x","0");
cvar_t con_notify_y = CVAR("con_notify_y","0"); static cvar_t con_notify_y = CVAR("con_notify_y","0");
cvar_t con_notify_w = CVAR("con_notify_w","1"); static cvar_t con_notify_w = CVAR("con_notify_w","1");
cvar_t con_centernotify = CVAR("con_centernotify", "0"); static cvar_t con_centernotify = CVAR("con_centernotify", "0");
cvar_t con_displaypossibilities = CVAR("con_displaypossibilities", "1"); static cvar_t con_displaypossibilities = CVAR("con_displaypossibilities", "1");
cvar_t con_showcompletion = CVAR("con_showcompletion", "1"); static cvar_t con_showcompletion = CVAR("con_showcompletion", "1");
cvar_t con_maxlines = CVAR("con_maxlines", "1024"); static cvar_t con_maxlines = CVAR("con_maxlines", "1024");
cvar_t cl_chatmode = CVARD("cl_chatmode", "2", "0(nq) - everything is assumed to be a console command. prefix with 'say', or just use a messagemode bind\n1(q3) - everything is assumed to be chat, unless its prefixed with a /\n2(qw) - anything explicitly recognised as a command will be used as a command, anything unrecognised will be a chat message.\n/ prefix is supported in all cases.\nctrl held when pressing enter always makes any implicit chat into team chat instead."); cvar_t cl_chatmode = CVARD("cl_chatmode", "2", "0(nq) - everything is assumed to be a console command. prefix with 'say', or just use a messagemode bind\n1(q3) - everything is assumed to be chat, unless its prefixed with a /\n2(qw) - anything explicitly recognised as a command will be used as a command, anything unrecognised will be a chat message.\n/ prefix is supported in all cases.\nctrl held when pressing enter always makes any implicit chat into team chat instead.");
cvar_t con_numnotifylines_chat = CVAR("con_numnotifylines_chat", "8"); static cvar_t con_numnotifylines_chat = CVAR("con_numnotifylines_chat", "8");
cvar_t con_notifytime_chat = CVAR("con_notifytime_chat", "8"); static cvar_t con_notifytime_chat = CVAR("con_notifytime_chat", "8");
cvar_t con_separatechat = CVAR("con_separatechat", "0"); cvar_t con_separatechat = CVAR("con_separatechat", "0");
cvar_t con_timestamps = CVAR("con_timestamps", "0"); static cvar_t con_timestamps = CVAR("con_timestamps", "0");
cvar_t con_timeformat = CVAR("con_timeformat", "(%H:%M:%S) "); static cvar_t con_timeformat = CVAR("con_timeformat", "(%H:%M:%S) ");
cvar_t con_textsize = CVARD("con_textsize", "8", "Resize the console text to be a different height, scaled separately from the hud. The value is the height in (virtual) pixels."); cvar_t con_textsize = CVARD("con_textsize", "8", "Resize the console text to be a different height, scaled separately from the hud. The value is the height in (virtual) pixels.");
extern cvar_t log_developer; extern cvar_t log_developer;
void con_window_cb(cvar_t *var, char *oldval)
{
if (!con_main)
return; //doesn't matter right now.
if (var->ival)
{
con_main->flags &= ~CONF_NOTIFY;
if (!(con_main->flags & CONF_ISWINDOW))
{
con_main->flags |= CONF_ISWINDOW;
if (con_current == con_main)
Con_SetActive(con_main);
}
}
else
{
con_main->flags |= CONF_NOTIFY;
if (con_main->flags & CONF_ISWINDOW)
{
con_main->flags &= ~CONF_ISWINDOW;
if (con_curwindow == con_main)
Con_SetActive(con_main);
}
}
}
static cvar_t con_window = CVARCD("con_window", "0", con_window_cb, "States whether the console should be a floating window as in source engine games, or a top-of-the-screen-only thing.");
#define NUM_CON_TIMES 24 #define NUM_CON_TIMES 24
qboolean con_initialized; qboolean con_initialized;
@ -110,7 +140,7 @@ int Con_IsActive (console_t *con)
void Con_Destroy (console_t *con) void Con_Destroy (console_t *con)
{ {
shader_t *shader; shader_t *shader;
console_t *prev; console_t **link;
conline_t *t; conline_t *t;
if (con->close) if (con->close)
@ -135,19 +165,11 @@ void Con_Destroy (console_t *con)
Z_Free(con->completionline); Z_Free(con->completionline);
con->completionline = NULL; con->completionline = NULL;
if (con == &con_main) for (link = &con_head; *link; link = &(*link)->next)
{ {
/*main console is never destroyed, only cleared (unless shutting down)*/ if (*link == con)
if (con_initialized)
Con_Finit(con);
return;
}
for (prev = &con_main; prev->next; prev = prev->next)
{
if (prev->next == con)
{ {
prev->next = con->next; (*link) = con->next;
break; break;
} }
} }
@ -156,12 +178,15 @@ void Con_Destroy (console_t *con)
BZ_Free(con); BZ_Free(con);
//make sure any special references are fixed up now that its gone
if (con_mouseover == con)
con_mouseover = NULL;
if (con_current == con) if (con_current == con)
con_current = &con_main; con_current = con_head;
if (con_curwindow == con) if (con_curwindow == con)
{ {
for (con_curwindow = &con_main; con_curwindow; con_curwindow = con_curwindow->next) for (con_curwindow = con_head; con_curwindow; con_curwindow = con_curwindow->next)
{ {
if (con_curwindow->flags & CONF_ISWINDOW) if (con_curwindow->flags & CONF_ISWINDOW)
break; break;
@ -180,7 +205,7 @@ void Con_FlushBackgrounds(void)
{ {
console_t *con; console_t *con;
//fixme: we really need to handle videomaps differently here, for vid_restarts. //fixme: we really need to handle videomaps differently here, for vid_restarts.
for (con = &con_main; con; con = con->next) for (con = con_head; con; con = con->next)
{ {
if (con->backshader) if (con->backshader)
R_UnloadShader(con->backshader); R_UnloadShader(con->backshader);
@ -194,7 +219,9 @@ console_t *Con_FindConsole(const char *name)
console_t *con; console_t *con;
if (!strcmp(name, "current") && con_current) if (!strcmp(name, "current") && con_current)
return con_current; return con_current;
for (con = &con_main; con; con = con->next) if (!strcmp(name, "head") && con_current)
return con_head;
for (con = con_head; con; con = con->next)
{ {
if (!strcmp(con->name, name)) if (!strcmp(con->name, name))
return con; return con;
@ -204,9 +231,11 @@ console_t *Con_FindConsole(const char *name)
/*creates a potentially duplicate console_t - please use Con_FindConsole first, as its confusing otherwise*/ /*creates a potentially duplicate console_t - please use Con_FindConsole first, as its confusing otherwise*/
console_t *Con_Create(const char *name, unsigned int flags) console_t *Con_Create(const char *name, unsigned int flags)
{ {
console_t *con; console_t *con, *p;
if (!strcmp(name, "current")) if (!strcmp(name, "current"))
return NULL; return NULL;
if (!strcmp(name, "head"))
return NULL;
con = Z_Malloc(sizeof(console_t)); con = Z_Malloc(sizeof(console_t));
Q_strncpyz(con->name, name, sizeof(con->name)); Q_strncpyz(con->name, name, sizeof(con->name));
Q_strncpyz(con->title, name, sizeof(con->title)); Q_strncpyz(con->title, name, sizeof(con->title));
@ -214,11 +243,51 @@ console_t *Con_Create(const char *name, unsigned int flags)
con->flags = flags; con->flags = flags;
Con_Finit(con); Con_Finit(con);
con->next = con_main.next;
con_main.next = con; //insert at end. make it active if you must.
if (!con_head)
con_head = con;
else
{
for (p = con_head; p->next; p = p->next)
;
p->next = con;
}
return con; return con;
} }
static qboolean Con_Main_BlockClose(console_t *con, qboolean force)
{
if (!force)
{ //trying to close it just hides it (this is to avoid it getting cleared).
if (con_curwindow == con)
Key_Dest_Remove(kdm_cwindows);
return false;
}
con_main = NULL; //its forced to die. and don't forget it.
return true;
}
console_t *Con_GetMain(void)
{
if (!con_main)
{
con_main = Con_Create("", 0);
con_main->linebuffered = Con_ExecuteLine;
con_main->commandcompletion = true;
con_main->wnd_w = 640;
con_main->wnd_h = 480;
con_main->wnd_x = 0;
con_main->wnd_y = 0;
con_main->close = Con_Main_BlockClose;
Q_strncpyz(con_main->title, "MAIN", sizeof(con_main->title));
Q_strncpyz(con_main->prompt, "]", sizeof(con_main->prompt));
Cvar_ForceCallback(&con_window);
}
return con_main;
}
/*sets a console as the active one*/ /*sets a console as the active one*/
void Con_SetActive (console_t *con) void Con_SetActive (console_t *con)
{ {
@ -231,7 +300,7 @@ void Con_SetActive (console_t *con)
if (con_curwindow == con) if (con_curwindow == con)
return; return;
for (prev = &con_main; prev; prev = prev->next) for (prev = con_head; prev; prev = prev->next)
{ {
if (prev->next == con) if (prev->next == con)
{ {
@ -248,7 +317,13 @@ void Con_SetActive (console_t *con)
con_curwindow = con; con_curwindow = con;
} }
else else
{
if (con_curwindow == con)
con_curwindow = NULL;
Key_Dest_Add(kdm_console);
Key_Dest_Remove(kdm_cwindows);
con_current = con; con_current = con;
}
if (con->footerline) if (con->footerline)
{ {
@ -263,7 +338,7 @@ void Con_SetActive (console_t *con)
qboolean Con_NameForNum(int num, char *buffer, int buffersize) qboolean Con_NameForNum(int num, char *buffer, int buffersize)
{ {
console_t *con; console_t *con;
for (con = &con_main; con; con = con->next, num--) for (con = con_head; con; con = con->next, num--)
{ {
if (num <= 0) if (num <= 0)
{ {
@ -544,9 +619,11 @@ void Con_ToggleConsole_f (void)
{ {
extern cvar_t con_stayhidden; extern cvar_t con_stayhidden;
Con_GetMain();
if (!con_curwindow) if (!con_curwindow)
{ {
for (con_curwindow = &con_main; con_curwindow; con_curwindow = con_curwindow->next) for (con_curwindow = con_head; con_curwindow; con_curwindow = con_curwindow->next)
if (con_curwindow->flags & CONF_ISWINDOW) if (con_curwindow->flags & CONF_ISWINDOW)
break; break;
} }
@ -598,9 +675,10 @@ Con_Clear_f
*/ */
void Con_Clear_f (void) void Con_Clear_f (void)
{ {
if (Cmd_IsInsecure()) console_t *con = Con_FindConsole(Cmd_Argv(1));
if (!con || Cmd_IsInsecure())
return; return;
Con_ClearCon(&con_main); Con_ClearCon(con);
} }
@ -680,7 +758,7 @@ void Con_MessageMode2_f (void)
void Con_ForceActiveNow(void) void Con_ForceActiveNow(void)
{ {
Key_Dest_Add(kdm_console); Key_Dest_Add(kdm_console);
scr_conlines = scr_con_current = vid.height; scr_con_target = scr_con_current = vid.height;
} }
/* /*
@ -692,18 +770,10 @@ void Log_Init (void);
void Con_Init (void) void Con_Init (void)
{ {
con_current = &con_main; con_current = NULL;
Con_Finit(&con_main); con_head = NULL;
con_main.linebuffered = Con_ExecuteLine; con_main = Con_GetMain();
con_main.commandcompletion = true;
// con_main.flags |= CONF_ISWINDOW;
con_main.wnd_w = 640;
con_main.wnd_h = 480;
con_main.wnd_x = 0;
con_main.wnd_y = 0;
Q_strncpyz(con_main.title, "MAIN", sizeof(con_main.title));
Q_strncpyz(con_main.prompt, "]", sizeof(con_main.prompt));
con_initialized = true; con_initialized = true;
// Con_TPrintf ("Console initialized.\n"); // Con_TPrintf ("Console initialized.\n");
@ -727,6 +797,8 @@ void Con_Init (void)
Cvar_Register (&con_timestamps, "Console controls"); Cvar_Register (&con_timestamps, "Console controls");
Cvar_Register (&con_timeformat, "Console controls"); Cvar_Register (&con_timeformat, "Console controls");
Cvar_Register (&con_textsize, "Console controls"); Cvar_Register (&con_textsize, "Console controls");
Cvar_Register (&con_window, "Console controls");
Cvar_ForceCallback(&con_window);
Cmd_AddCommand ("toggleconsole", Con_ToggleConsole_f); Cmd_AddCommand ("toggleconsole", Con_ToggleConsole_f);
Cmd_AddCommand ("messagemode", Con_MessageMode_f); Cmd_AddCommand ("messagemode", Con_MessageMode_f);
@ -736,11 +808,11 @@ void Con_Init (void)
Cmd_AddCommand ("qterm", Con_QTerm_f); Cmd_AddCommand ("qterm", Con_QTerm_f);
#endif #endif
Cmd_AddCommand ("conecho_center", Cmd_ConEchoCenter_f); Cmd_AddCommandD ("conecho_center", Cmd_ConEchoCenter_f, "conecho_center consolename The Text To Echo\nUse \"\" for the main console.\nAny added lines will be aligned to the middle of the console.");
Cmd_AddCommand ("conecho", Cmd_ConEcho_f); Cmd_AddCommandD ("conecho", Cmd_ConEcho_f, "conecho consolename The Text To Echo\nEchos text to a named console instead of just the main one.");
Cmd_AddCommand ("conclear", Cmd_ConClear_f); Cmd_AddCommandD ("conclear", Cmd_ConClear_f, "Clears a named console (instead of just the main one)");
Cmd_AddCommand ("conclose", Cmd_ConClose_f); Cmd_AddCommandD ("conclose", Cmd_ConClose_f, "Destroys a named console");
Cmd_AddCommand ("conactivate", Cmd_ConActivate_f); Cmd_AddCommandD ("conactivate", Cmd_ConActivate_f, "Brings focus to the named console. Will not do anything if the named console is not created yet (so be sure to do any echos before using this command)");
Log_Init(); Log_Init();
} }
@ -754,12 +826,9 @@ void Con_Shutdown(void)
BZ_Free(key_lines[i]); BZ_Free(key_lines[i]);
} }
while(con_main.next) while(con_head)
{ Con_Destroy(con_head);
Con_Destroy(con_main.next);
}
con_initialized = false; con_initialized = false;
Con_Destroy(&con_main);
} }
void TTS_SayConString(conchar_t *stringtosay); void TTS_SayConString(conchar_t *stringtosay);
@ -935,19 +1004,22 @@ void Con_PrintCon (console_t *con, const char *txt, unsigned int parseflags)
void Con_CenterPrint(const char *txt) void Con_CenterPrint(const char *txt)
{ {
int flags = con_main.parseflags|PFS_NONOTIFY|PFS_CENTERED; console_t *c = Con_GetMain();
Con_PrintCon(&con_main, "^Ue01d^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01f\n", flags); int flags = c->parseflags|PFS_NONOTIFY|PFS_CENTERED;
Con_PrintCon(&con_main, txt, flags); //client console Con_PrintCon(c, "^Ue01d^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01f\n", flags);
Con_PrintCon(&con_main, "\n^Ue01d^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01f\n", flags); Con_PrintCon(c, txt, flags); //client console
Con_PrintCon(c, "\n^Ue01d^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01f\n", flags);
} }
void Con_Print (const char *txt) void Con_Print (const char *txt)
{ {
Con_PrintCon(&con_main, txt, con_main.parseflags); //client console console_t *c = Con_GetMain();
Con_PrintCon(c, txt, c->parseflags); //client console
} }
void Con_PrintFlags(const char *txt, unsigned int setflags, unsigned int clearflags) void Con_PrintFlags(const char *txt, unsigned int setflags, unsigned int clearflags)
{ {
setflags |= con_main.parseflags; console_t *c = Con_GetMain();
setflags |= c->parseflags;
setflags &= ~clearflags; setflags &= ~clearflags;
// also echo to debugging console // also echo to debugging console
@ -957,19 +1029,26 @@ void Con_PrintFlags(const char *txt, unsigned int setflags, unsigned int clearfl
Con_Log (txt); Con_Log (txt);
if (con_initialized) if (con_initialized)
Con_PrintCon(&con_main, txt, setflags); Con_PrintCon(c, txt, setflags);
} }
void Con_CycleConsole(void) void Con_CycleConsole(void)
{ {
console_t *first = con_current?con_current:con_head;
while(1) while(1)
{ {
con_current = con_current->next; con_current = con_current->next;
if (!con_current) if (!con_current)
con_current = &con_main; con_current = con_head;
if (con_current == first)
{
if (con_current->flags & (CONF_HIDDEN|CONF_ISWINDOW))
con_current = NULL; //no valid consoles
break; //we wrapped? oh noes
}
if (con_current->flags & (CONF_HIDDEN|CONF_ISWINDOW)) if (con_current->flags & (CONF_HIDDEN|CONF_ISWINDOW))
continue; continue; //this is a valid choice
break; break;
} }
} }
@ -1098,8 +1177,9 @@ static void Con_DPrintFromThread (void *ctx, void *data, size_t a, size_t b)
Con_Log(data); Con_Log(data);
if (developer.ival >= (int)a) if (developer.ival >= (int)a)
{ {
console_t *c = Con_GetMain();
Sys_Printf ("%s", (const char*)data); // also echo to debugging console Sys_Printf ("%s", (const char*)data); // also echo to debugging console
Con_PrintCon(&con_main, data, con_main.parseflags); Con_PrintCon(c, data, c->parseflags);
} }
BZ_Free(data); BZ_Free(data);
} }
@ -1140,9 +1220,9 @@ void VARGS Con_DPrintf (const char *fmt, ...)
Con_Log(msg); Con_Log(msg);
if (developer.ival) if (developer.ival)
{ {
console_t *c = Con_GetMain();
Sys_Printf ("%s", msg); // also echo to debugging console Sys_Printf ("%s", msg); // also echo to debugging console
if (con_initialized) Con_PrintCon(c, msg, c->parseflags);
Con_PrintCon(&con_main, msg, con_main.parseflags);
} }
} }
void VARGS Con_DLPrintf (int level, const char *fmt, ...) void VARGS Con_DLPrintf (int level, const char *fmt, ...)
@ -1177,7 +1257,10 @@ void VARGS Con_DLPrintf (int level, const char *fmt, ...)
{ {
Sys_Printf ("%s", msg); // also echo to debugging console Sys_Printf ("%s", msg); // also echo to debugging console
if (con_initialized) if (con_initialized)
Con_PrintCon(&con_main, msg, con_main.parseflags); {
console_t *c = Con_GetMain();
Con_PrintCon(c, msg, c->parseflags);
}
} }
} }
@ -1607,7 +1690,7 @@ void Con_ClearNotify(void)
{ {
console_t *con; console_t *con;
conline_t *l; conline_t *l;
for (con = &con_main; con; con = con->next) for (con = con_head; con; con = con->next)
{ {
for (l = con->current; l; l = l->older) for (l = con->current; l; l = l->older)
l->flags |= CONL_NONOTIFY; l->flags |= CONL_NONOTIFY;
@ -1618,13 +1701,15 @@ void Con_DrawNotify (void)
extern int startuppending; extern int startuppending;
console_t *con; console_t *con;
con_main.flags |= CONF_NOTIFY; if (con_main)
/*keep the main console up to date*/ {
con_main.notif_l = con_numnotifylines.ival; /*keep the main console up to date*/
con_main.notif_w = con_notify_w.value; con_main->notif_l = con_numnotifylines.ival;
con_main.notif_x = con_notify_x.value; con_main->notif_w = con_notify_w.value;
con_main.notif_y = con_notify_y.value; con_main->notif_x = con_notify_x.value;
con_main.notif_t = con_notifytime.value; con_main->notif_y = con_notify_y.value;
con_main->notif_t = con_notifytime.value;
}
if (con_chat) if (con_chat)
{ {
@ -1643,7 +1728,7 @@ void Con_DrawNotify (void)
} }
else else
{ {
for (con = &con_main; con; con = con->next) for (con = con_head; con; con = con->next)
{ {
if (con->flags & CONF_NOTIFY) if (con->flags & CONF_NOTIFY)
Con_DrawNotifyOne(con); Con_DrawNotifyOne(con);
@ -1660,7 +1745,7 @@ void Con_DrawNotify (void)
char *foo = va(chat_team?"say_team: %s":"say: %s", chat_buffer?(char*)chat_buffer:""); char *foo = va(chat_team?"say_team: %s":"say: %s", chat_buffer?(char*)chat_buffer:"");
int lines, i, pos; int lines, i, pos;
Font_BeginString(font_console, 0, 0, &x, &y); Font_BeginString(font_console, 0, 0, &x, &y);
y = con_main.notif_l * Font_CharHeight(); y = con_numnotifylines.ival * Font_CharHeight();
i = chat_team?10:5; i = chat_team?10:5;
pos = strlen(foo)+i; pos = strlen(foo)+i;
@ -1697,12 +1782,15 @@ void Con_DrawNotify (void)
//This is so that system consoles in windows can scroll up and have all the text. //This is so that system consoles in windows can scroll up and have all the text.
void Con_PrintToSys(void) void Con_PrintToSys(void)
{ {
console_t *curcon = &con_main; console_t *curcon = con_main;
conline_t *l; conline_t *l;
int i; int i;
conchar_t *t; conchar_t *t;
char buf[16]; char buf[16];
if (!curcon)
return;
for (l = curcon->oldest; l; l = l->newer) for (l = curcon->oldest; l; l = l->newer)
{ {
t = (conchar_t*)(l+1); t = (conchar_t*)(l+1);
@ -1896,23 +1984,23 @@ int Con_DrawAlternateConsoles(int lines)
char *txt; char *txt;
int x, y = 0, lx; int x, y = 0, lx;
int consshown = 0; int consshown = 0;
console_t *con = &con_main, *om = con_mouseover; console_t *con, *om = con_mouseover;
conchar_t buffer[512], *end, *start; conchar_t buffer[512], *end, *start;
unsigned int codeflags, codepoint; unsigned int codeflags, codepoint;
for (con = &con_main; con; con = con->next) for (con = con_head; con; con = con->next)
{ {
if (!(con->flags & (CONF_HIDDEN|CONF_ISWINDOW))) if (!(con->flags & (CONF_HIDDEN|CONF_ISWINDOW)))
consshown++; consshown++;
} }
if (lines == (int)scr_conlines && consshown > 1) if (lines == (int)scr_con_target && consshown > 1)
{ {
int mx, my, h; int mx, my, h;
Font_BeginString(font_console, mousecursor_x, mousecursor_y, &mx, &my); Font_BeginString(font_console, mousecursor_x, mousecursor_y, &mx, &my);
Font_BeginString(font_console, 0, y, &x, &y); Font_BeginString(font_console, 0, y, &x, &y);
h = Font_CharHeight(); h = Font_CharHeight();
for (x = 0, con = &con_main; con; con = con->next) for (x = 0, con = con_head; con; con = con->next)
{ {
if (con->flags & (CONF_HIDDEN|CONF_ISWINDOW)) if (con->flags & (CONF_HIDDEN|CONF_ISWINDOW))
continue; continue;
@ -2386,10 +2474,13 @@ void Con_DrawConsole (int lines, qboolean noback)
console_t *w, *mouseconsole; console_t *w, *mouseconsole;
float fadetime; float fadetime;
if (!con_current)
con_current = Con_GetMain();
con_mouseover = NULL; con_mouseover = NULL;
//draw any windowed consoles (under main console) //draw any windowed consoles (under main console)
for (w = &con_main; w; w = w->next) for (w = con_head; w; w = w->next)
{ {
srect_t srect; srect_t srect;
if ((w->flags & (CONF_HIDDEN|CONF_ISWINDOW)) != CONF_ISWINDOW) if ((w->flags & (CONF_HIDDEN|CONF_ISWINDOW)) != CONF_ISWINDOW)
@ -2576,7 +2667,7 @@ void Con_DrawConsole (int lines, qboolean noback)
} }
//draw main console... //draw main console...
if (lines > 0 && !(con_current->flags & CONF_ISWINDOW)) if (lines > 0 && con_current && !(con_current->flags & CONF_ISWINDOW))
{ {
int top; int top;
#ifdef QTERM #ifdef QTERM

File diff suppressed because it is too large Load diff

View file

@ -1579,16 +1579,16 @@ qboolean Key_Console (console_t *con, int key, unsigned int unicode)
if ((unicode >= '0' && unicode <= '9') || unicode == '.' || key < 0) if ((unicode >= '0' && unicode <= '9') || unicode == '.' || key < 0)
key = 0; key = 0;
if (key == K_TAB && !(con->flags & CONF_ISWINDOW) && ctrl&&shift)
{ // cycle consoles with ctrl+shift+tab.
// (ctrl+tab forces tab completion,
// shift+tab controls completion cycle,
// so it has to be both.)
Con_CycleConsole();
return true;
}
if (con->redirect) if (con->redirect)
{ {
if (key == K_TAB)
{ // command completion
if (ctrl || shift)
{
Con_CycleConsole();
return true;
}
}
if (key == K_MOUSE1 || key == K_MOUSE2) if (key == K_MOUSE1 || key == K_MOUSE2)
; ;
else if (con->redirect(con, unicode, key)) else if (con->redirect(con, unicode, key))
@ -1614,7 +1614,7 @@ qboolean Key_Console (console_t *con, int key, unsigned int unicode)
{ {
if (key == K_MOUSE2 && !(con->flags & CONF_ISWINDOW)) if (key == K_MOUSE2 && !(con->flags & CONF_ISWINDOW))
{ {
if (con->close && !con->close(con, true)) if (con->close && !con->close(con, false))
return true; return true;
Con_Destroy (con); Con_Destroy (con);
} }
@ -1843,12 +1843,6 @@ qboolean Key_Console (console_t *con, int key, unsigned int unicode)
if (key == K_TAB) if (key == K_TAB)
{ // command completion { // command completion
if (ctrl&&shift)
{
Con_CycleConsole();
return true;
}
if (con->commandcompletion) if (con->commandcompletion)
CompleteCommand (ctrl, shift?-1:1); CompleteCommand (ctrl, shift?-1:1);
return true; return true;
@ -2841,7 +2835,13 @@ void Key_Event (unsigned int devid, int key, unsigned int unicode, qboolean down
{ {
if (Key_Dest_Has(kdm_console|kdm_cwindows)) if (Key_Dest_Has(kdm_console|kdm_cwindows))
{ {
console_t *con = Key_Dest_Has(kdm_console)?con_current:con_curwindow; console_t *con;
if (Key_Dest_Has(kdm_console))
con = con_current;
else if (Key_Dest_Has(kdm_cwindows))
con = con_curwindow;
else
con = NULL;
if (con_mouseover && key >= K_MOUSE1 && key <= K_MWHEELDOWN) if (con_mouseover && key >= K_MOUSE1 && key <= K_MWHEELDOWN)
con = con_mouseover; con = con_mouseover;
if (con_curwindow && con_curwindow != con) if (con_curwindow && con_curwindow != con)

View file

@ -2321,7 +2321,17 @@ static void PM_StartADownload(void)
} }
if (tmpfile) if (tmpfile)
{
p->download = HTTP_CL_Get(mirror, NULL, PM_Download_Got); p->download = HTTP_CL_Get(mirror, NULL, PM_Download_Got);
if (!p->download)
Con_Printf("Unable to download %s\n", p->name);
}
else
{
char syspath[MAX_OSPATH];
FS_NativePath(temp, p->fsroot, syspath, sizeof(syspath));
Con_Printf("Unable to write %s. Fix permissions before trying to download %s\n", syspath, p->name);
}
if (p->download) if (p->download)
{ {
Con_Printf("Downloading %s\n", p->name); Con_Printf("Downloading %s\n", p->name);
@ -2333,7 +2343,6 @@ static void PM_StartADownload(void)
} }
else else
{ {
Con_Printf("Unable to download %s\n", p->name);
p->flags &= ~DPF_MARKED; //can't do it. p->flags &= ~DPF_MARKED; //can't do it.
if (tmpfile) if (tmpfile)
VFS_CLOSE(tmpfile); VFS_CLOSE(tmpfile);

View file

@ -213,7 +213,7 @@ void Draw_BigFontString(int x, int y, const char *text)
p = QBigFontWorks(); p = QBigFontWorks();
if (!p) if (!p)
{ {
Draw_AltFunString(x, y, text); Draw_AltFunString(x, y + (20-8)/2, text);
return; return;
} }
@ -438,7 +438,10 @@ static void MenuDrawItems(int xpos, int ypos, menuoption_t *option, menu_t *menu
case mt_menudot: case mt_menudot:
i = (int)(realtime * 10)%maxdots; i = (int)(realtime * 10)%maxdots;
p = R2D_SafeCachePic(va(menudotstyle, i+mindot )); p = R2D_SafeCachePic(va(menudotstyle, i+mindot ));
R2D_ScalePic(xpos+option->common.posx, ypos+option->common.posy+dotofs, option->common.width, option->common.height, p); if (R_GetShaderSizes(p, NULL, NULL, false)>0)
R2D_ScalePic(xpos+option->common.posx, ypos+option->common.posy+dotofs, option->common.width, option->common.height, p);
else if ((int)(realtime*4)&1)
Draw_FunString(xpos+option->common.posx, ypos+option->common.posy + (option->common.height-8)/2, "^a^Ue00d");
break; break;
case mt_picturesel: case mt_picturesel:
p = NULL; p = NULL;
@ -2206,6 +2209,8 @@ void M_Menu_Main_f (void)
MC_AddConsoleCommandQBigFont (mainm, 72, y, "Options", "menu_options\n"); y += 20; MC_AddConsoleCommandQBigFont (mainm, 72, y, "Options", "menu_options\n"); y += 20;
y = M_Main_AddExtraOptions(mainm, y); y = M_Main_AddExtraOptions(mainm, y);
MC_AddConsoleCommandQBigFont (mainm, 72, y, "Quit", "menu_quit\n"); y += 20; MC_AddConsoleCommandQBigFont (mainm, 72, y, "Quit", "menu_quit\n"); y += 20;
mainm->cursoritem = (menuoption_t *)MC_AddCursor(mainm, &resel, 54, 36);
} }
if (!m_preset_chosen.ival) if (!m_preset_chosen.ival)

View file

@ -2986,7 +2986,7 @@ static void QDECL capture_raw_video (void *vctx, int frame, void *data, int stri
char filename[MAX_OSPATH]; char filename[MAX_OSPATH];
ctx->frames = frame+1; ctx->frames = frame+1;
Q_snprintfz(filename, sizeof(filename), "%s%8.8i.%s", ctx->videonameprefix, frame, ctx->videonameextension); Q_snprintfz(filename, sizeof(filename), "%s%8.8i.%s", ctx->videonameprefix, frame, ctx->videonameextension);
SCR_ScreenShot(filename, ctx->fsroot, &data, 1, stride, width, height, fmt); SCR_ScreenShot(filename, ctx->fsroot, &data, 1, stride, width, height, fmt, true);
if (capturethrottlesize.ival) if (capturethrottlesize.ival)
{ {
@ -5159,10 +5159,10 @@ void Media_Init(void)
#endif #endif
Media_RegisterEncoder(NULL, &capture_raw); Media_RegisterEncoder(NULL, &capture_raw);
Cmd_AddCommand("capture", Media_RecordFilm_f); Cmd_AddCommandD("capture", Media_RecordFilm_f, "Captures realtime action to a named video file. Check the capture* cvars to control driver/codecs/rates.");
Cmd_AddCommand("capturedemo", Media_RecordDemo_f); Cmd_AddCommandD("capturedemo", Media_RecordDemo_f, "Capture a nemed demo to a named video file. Demo capturing can be performed offscreen, allowing arbitrary video sizes, or smooth captures on underpowered hardware.");
Cmd_AddCommand("capturestop", Media_StopRecordFilm_f); Cmd_AddCommandD("capturestop", Media_StopRecordFilm_f, "Aborts the current video capture.");
Cmd_AddCommand("capturepause", Media_CapturePause_f); Cmd_AddCommandD("capturepause", Media_CapturePause_f, "Pauses the video capture, allowing you to avoid capturing uninteresting parts. This is a toggle, so reuse the same command to resume capturing again.");
Cvar_Register(&capturemessage, "Video Capture Controls"); Cvar_Register(&capturemessage, "Video Capture Controls");
Cvar_Register(&capturesound, "Video Capture Controls"); Cvar_Register(&capturesound, "Video Capture Controls");

View file

@ -145,6 +145,7 @@ void R_DrawTextField(int x, int y, int w, int h, const char *text, unsigned int
#define CPRINT_RALIGN (1<<2) //R #define CPRINT_RALIGN (1<<2) //R
#define CPRINT_BALIGN (1<<3) //B #define CPRINT_BALIGN (1<<3) //B
#define CPRINT_BACKGROUND (1<<4) //P #define CPRINT_BACKGROUND (1<<4) //P
#define CPRINT_NOWRAP (1<<5)
#define CPRINT_OBITUARTY (1<<16) //O (show at 2/3rds from top) #define CPRINT_OBITUARTY (1<<16) //O (show at 2/3rds from top)
#define CPRINT_PERSIST (1<<17) //P (doesn't time out) #define CPRINT_PERSIST (1<<17) //P (doesn't time out)
@ -309,6 +310,8 @@ struct pendingtextureinfo
int depth; int depth;
qboolean needfree; qboolean needfree;
} mip[72]; //enough for a 4096 cubemap. or a really smegging big 2d texture... } mip[72]; //enough for a 4096 cubemap. or a really smegging big 2d texture...
//mips are ordered as in arrayindex THEN mip order, allowing easy truncation of mip levels.
//cubemaps are just arrayindex*6
}; };
//small context for easy vbo creation. //small context for easy vbo creation.

View file

@ -1117,7 +1117,7 @@ static void QCBUILTIN PF_R_DynamicLight_Set(pubprogfuncs_t *prinst, struct globa
{ {
const char *s; const char *s;
dlight_t *l; dlight_t *l;
unsigned int lno = G_FLOAT(OFS_PARM0); size_t lno = G_FLOAT(OFS_PARM0);
int field = G_FLOAT(OFS_PARM1); int field = G_FLOAT(OFS_PARM1);
while (lno >= cl_maxdlights) while (lno >= cl_maxdlights)
{ {
@ -1149,7 +1149,8 @@ static void QCBUILTIN PF_R_DynamicLight_Set(pubprogfuncs_t *prinst, struct globa
l->style = G_FLOAT(OFS_PARM2)+1; l->style = G_FLOAT(OFS_PARM2)+1;
break; break;
case lfield_angles: case lfield_angles:
AngleVectors(G_VECTOR(OFS_PARM2), l->axis[0], l->axis[1], l->axis[2]); VectorCopy(G_VECTOR(OFS_PARM2), l->angles);
AngleVectors(l->angles, l->axis[0], l->axis[1], l->axis[2]);
VectorInverse(l->axis[1]); VectorInverse(l->axis[1]);
break; break;
case lfield_fov: case lfield_fov:
@ -1170,6 +1171,11 @@ static void QCBUILTIN PF_R_DynamicLight_Set(pubprogfuncs_t *prinst, struct globa
l->cubetexture = r_nulltex; l->cubetexture = r_nulltex;
break; break;
#ifdef RTLIGHTS #ifdef RTLIGHTS
case lfield_stylestring:
s = PR_GetStringOfs(prinst, OFS_PARM2);
Z_Free(l->customstyle);
l->customstyle = (s&&*s)?Z_StrDup(s):NULL;
break;
case lfield_ambientscale: case lfield_ambientscale:
l->lightcolourscales[0] = G_FLOAT(OFS_PARM2); l->lightcolourscales[0] = G_FLOAT(OFS_PARM2);
break; break;
@ -1202,7 +1208,6 @@ static void QCBUILTIN PF_R_DynamicLight_Set(pubprogfuncs_t *prinst, struct globa
} }
static void QCBUILTIN PF_R_DynamicLight_Get(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) static void QCBUILTIN PF_R_DynamicLight_Get(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{ {
vec3_t v;
dlight_t *l; dlight_t *l;
unsigned int lno = G_FLOAT(OFS_PARM0); unsigned int lno = G_FLOAT(OFS_PARM0);
enum lightfield_e field = G_FLOAT(OFS_PARM1); enum lightfield_e field = G_FLOAT(OFS_PARM1);
@ -1233,10 +1238,7 @@ static void QCBUILTIN PF_R_DynamicLight_Get(pubprogfuncs_t *prinst, struct globa
G_FLOAT(OFS_RETURN) = l->style-1; G_FLOAT(OFS_RETURN) = l->style-1;
break; break;
case lfield_angles: case lfield_angles:
VectorAngles(l->axis[0], l->axis[2], v, false); VectorCopy(l->angles, G_VECTOR(OFS_RETURN));
G_FLOAT(OFS_RETURN+0) = anglemod(v[0]);
G_FLOAT(OFS_RETURN+1) = v[1];
G_FLOAT(OFS_RETURN+2) = v[2];
break; break;
case lfield_fov: case lfield_fov:
G_FLOAT(OFS_RETURN) = l->fov; G_FLOAT(OFS_RETURN) = l->fov;
@ -1251,6 +1253,12 @@ static void QCBUILTIN PF_R_DynamicLight_Get(pubprogfuncs_t *prinst, struct globa
RETURN_TSTRING(l->cubemapname); RETURN_TSTRING(l->cubemapname);
break; break;
#ifdef RTLIGHTS #ifdef RTLIGHTS
case lfield_stylestring:
if (l->customstyle)
RETURN_TSTRING(l->customstyle);
else
RETURN_TSTRING("");
break;
case lfield_ambientscale: case lfield_ambientscale:
G_FLOAT(OFS_RETURN) = l->lightcolourscales[0]; G_FLOAT(OFS_RETURN) = l->lightcolourscales[0];
break; break;
@ -1497,7 +1505,6 @@ static void CSQC_PolyFlush(void)
if (!csqc_poly_2d) if (!csqc_poly_2d)
{ {
scenetris_t *t; scenetris_t *t;
/*regular 3d polys are inserted into a 'scene trisoup' that the backend can then source from (multiple times, depending on how its drawn)*/
if (cl_numstris == cl_maxstris) if (cl_numstris == cl_maxstris)
{ {
cl_maxstris+=8; cl_maxstris+=8;
@ -1510,7 +1517,7 @@ static void CSQC_PolyFlush(void)
t->firstvert = csqc_poly_origvert; t->firstvert = csqc_poly_origvert;
t->numidx = cl_numstrisidx - t->firstidx; t->numidx = cl_numstrisidx - t->firstidx;
t->numvert = cl_numstrisvert-csqc_poly_origvert; t->numvert = cl_numstrisvert-t->firstvert;
} }
else else
{ {
@ -2135,7 +2142,7 @@ void QCBUILTIN PF_R_SetViewFlag(pubprogfuncs_t *prinst, struct globalvars_s *pr_
case VF_ACTIVESEAT: case VF_ACTIVESEAT:
if (prinst == csqc_world.progs) if (prinst == csqc_world.progs)
{ {
if (csqc_playerseat != *p) if (csqc_playerseat != (int)*p)
{ {
CSQC_ChangeLocalPlayer(*p); CSQC_ChangeLocalPlayer(*p);
if (prinst->callargc < 3 || G_FLOAT(OFS_PARM2)) if (prinst->callargc < 3 || G_FLOAT(OFS_PARM2))
@ -2419,6 +2426,9 @@ static void QCBUILTIN PF_R_RenderScene(pubprogfuncs_t *prinst, struct globalvars
scissored = false; scissored = false;
R_DrawNameTags(); R_DrawNameTags();
#ifdef RTLIGHTS
R_EditLights_DrawInfo();
#endif
if (r_refdef.drawsbar) if (r_refdef.drawsbar)
{ {
@ -7010,6 +7020,9 @@ void CSQC_Shutdown(void)
int i; int i;
if (csqcprogs) if (csqcprogs)
{ {
if (csqcg.shutdown_function)
PR_ExecuteProgram(csqcprogs, csqcg.shutdown_function);
key_dest_absolutemouse &= ~kdm_game; key_dest_absolutemouse &= ~kdm_game;
CSQC_ForgetThreads(); CSQC_ForgetThreads();
PR_ReleaseFonts(kdm_game); PR_ReleaseFonts(kdm_game);

View file

@ -996,7 +996,7 @@ void QCBUILTIN PF_SubConGetSet (pubprogfuncs_t *prinst, struct globalvars_s *pr_
else if (!strcmp(field, "next")) else if (!strcmp(field, "next"))
{ {
con = con->next; con = con->next;
if (con && con != &con_main) if (con)
RETURN_TSTRING(con->name); RETURN_TSTRING(con->name);
} }
else if (!strcmp(field, "unseen")) else if (!strcmp(field, "unseen"))

View file

@ -164,6 +164,7 @@ extern "C" {
#include "mathlib.h" #include "mathlib.h"
#include "cvar.h" #include "cvar.h"
#include "net.h" #include "net.h"
#ifndef WEBSVONLY
#include "protocol.h" #include "protocol.h"
#include "cmd.h" #include "cmd.h"
#include "console.h" #include "console.h"
@ -197,6 +198,7 @@ extern "C" {
#else #else
#include "server.h" #include "server.h"
#endif #endif
#endif
#ifndef max #ifndef max
#define max(a,b) ((a) > (b) ? (a) : (b)) #define max(a,b) ((a) > (b) ? (a) : (b))

View file

@ -967,6 +967,7 @@ void QDECL R2D_Conback_Callback(struct cvar_s *var, char *oldvalue)
} }
} }
#ifdef AVAIL_FREETYPE
#if defined(_WIN32) && !defined(FTE_SDL) && !defined(WINRT) && !defined(_XBOX) #if defined(_WIN32) && !defined(FTE_SDL) && !defined(WINRT) && !defined(_XBOX)
#include <windows.h> #include <windows.h>
qboolean R2D_Font_WasAdded(char *buffer, char *fontfilename) qboolean R2D_Font_WasAdded(char *buffer, char *fontfilename)
@ -1026,6 +1027,7 @@ int R2D_Font_ListSystemFonts(const char *fname, qofs_t fsize, time_t modtime, vo
return true; return true;
} }
#endif #endif
#endif
void R2D_Font_Changed(void) void R2D_Font_Changed(void)
{ {
float tsize; float tsize;
@ -1062,7 +1064,9 @@ void R2D_Font_Changed(void)
if (!strcmp(gl_font.string, "?")) if (!strcmp(gl_font.string, "?"))
{ {
#if defined(_WIN32) && !defined(FTE_SDL) && !defined(WINRT) && !defined(_XBOX) #ifndef AVAIL_FREETYPE
Cvar_Set(&gl_font, "");
#elif defined(_WIN32) && !defined(FTE_SDL) && !defined(WINRT) && !defined(_XBOX)
BOOL (APIENTRY *pChooseFontW)(LPCHOOSEFONTW) = NULL; BOOL (APIENTRY *pChooseFontW)(LPCHOOSEFONTW) = NULL;
dllfunction_t funcs[] = dllfunction_t funcs[] =
{ {
@ -1112,6 +1116,7 @@ void R2D_Font_Changed(void)
return; return;
#else #else
Sys_EnumerateFiles("/usr/share/fonts/truetype/", "*/*.ttf", R2D_Font_ListSystemFonts, NULL, NULL); Sys_EnumerateFiles("/usr/share/fonts/truetype/", "*/*.ttf", R2D_Font_ListSystemFonts, NULL, NULL);
COM_EnumerateFiles("*.ttf", R2D_Font_ListSystemFonts, NULL);
Cvar_Set(&gl_font, ""); Cvar_Set(&gl_font, "");
#endif #endif
} }

View file

@ -452,6 +452,8 @@ void Image_Upload (texid_t tex, uploadfmt_t fmt, void *data, void *palette, in
void Image_Purge(void); //purge any textures which are not needed any more (releases memory, but doesn't give null pointers). void Image_Purge(void); //purge any textures which are not needed any more (releases memory, but doesn't give null pointers).
void Image_Init(void); void Image_Init(void);
void Image_Shutdown(void); void Image_Shutdown(void);
qboolean Image_WriteKTXFile(const char *filename, enum fs_relative fsroot, struct pendingtextureinfo *mips);
qboolean Image_WriteDDSFile(const char *filename, enum fs_relative fsroot, struct pendingtextureinfo *mips);
void Image_BlockSizeForEncoding(uploadfmt_t encoding, unsigned int *blockbytes, unsigned int *blockwidth, unsigned int *blockheight); void Image_BlockSizeForEncoding(uploadfmt_t encoding, unsigned int *blockbytes, unsigned int *blockwidth, unsigned int *blockheight);
const char *Image_FormatName(uploadfmt_t encoding); const char *Image_FormatName(uploadfmt_t encoding);
@ -612,10 +614,6 @@ extern cvar_t r_shadow_realtime_dlight_diffuse;
extern cvar_t r_shadow_realtime_dlight_specular; extern cvar_t r_shadow_realtime_dlight_specular;
extern cvar_t r_shadow_realtime_world, r_shadow_realtime_world_shadows, r_shadow_realtime_world_lightmaps; extern cvar_t r_shadow_realtime_world, r_shadow_realtime_world_shadows, r_shadow_realtime_world_lightmaps;
extern cvar_t r_shadow_shadowmapping; extern cvar_t r_shadow_shadowmapping;
extern cvar_t r_editlights_import_radius;
extern cvar_t r_editlights_import_ambient;
extern cvar_t r_editlights_import_diffuse;
extern cvar_t r_editlights_import_specular;
extern cvar_t r_mirroralpha; extern cvar_t r_mirroralpha;
extern cvar_t r_wateralpha; extern cvar_t r_wateralpha;
extern cvar_t r_lavaalpha; extern cvar_t r_lavaalpha;

View file

@ -240,7 +240,7 @@ cvar_t scr_showpause = CVAR ("showpause", "1");
cvar_t scr_showturtle = CVAR ("showturtle", "0"); cvar_t scr_showturtle = CVAR ("showturtle", "0");
cvar_t scr_turtlefps = CVAR ("scr_turtlefps", "10"); cvar_t scr_turtlefps = CVAR ("scr_turtlefps", "10");
cvar_t scr_sshot_compression = CVAR ("scr_sshot_compression", "75"); cvar_t scr_sshot_compression = CVAR ("scr_sshot_compression", "75");
cvar_t scr_sshot_type = CVAR ("scr_sshot_type", "png"); cvar_t scr_sshot_type = CVARD ("scr_sshot_type", "png", "This specifies the default extension(and thus file format) for screenshots.\nKnown extensions are: png, jpg/jpeg, bmp, pcx, tga, ktx, dds.");
cvar_t scr_sshot_prefix = CVAR ("scr_sshot_prefix", "screenshots/fte-"); cvar_t scr_sshot_prefix = CVAR ("scr_sshot_prefix", "screenshots/fte-");
cvar_t scr_viewsize = CVARFC("viewsize", "100", CVAR_ARCHIVE, SCR_Viewsize_Callback); cvar_t scr_viewsize = CVARFC("viewsize", "100", CVAR_ARCHIVE, SCR_Viewsize_Callback);
@ -458,6 +458,7 @@ cvar_t vid_hardwaregamma = CVARFD ("vid_hardwaregamma", "1",
cvar_t vid_desktopgamma = CVARFD ("vid_desktopgamma", "0", cvar_t vid_desktopgamma = CVARFD ("vid_desktopgamma", "0",
CVAR_ARCHIVE | CVAR_RENDERERLATCH, "Apply gamma ramps upon the desktop rather than the window."); CVAR_ARCHIVE | CVAR_RENDERERLATCH, "Apply gamma ramps upon the desktop rather than the window.");
cvar_t r_fog_cullentities = CVARD ("r_fog_cullentities", "1", "Automatically cull entities according to fog.");
cvar_t r_fog_exp2 = CVARD ("r_fog_exp2", "1", "Expresses how fog fades with distance. 0 (matching DarkPlaces's default) is typically more realistic, while 1 (matching FitzQuake and others) is more common."); cvar_t r_fog_exp2 = CVARD ("r_fog_exp2", "1", "Expresses how fog fades with distance. 0 (matching DarkPlaces's default) is typically more realistic, while 1 (matching FitzQuake and others) is more common.");
cvar_t r_fog_permutation = CVARFD ("r_fog_permutation", "1", CVAR_SHADERSYSTEM, "Renders fog using a material permutation. 0 plays nicer with q3 shaders, but 1 is otherwise a better choice."); cvar_t r_fog_permutation = CVARFD ("r_fog_permutation", "1", CVAR_SHADERSYSTEM, "Renders fog using a material permutation. 0 plays nicer with q3 shaders, but 1 is otherwise a better choice.");
@ -557,6 +558,7 @@ void GLRenderer_Init(void)
Cvar_Register (&gl_overbright, GRAPHICALNICETIES); Cvar_Register (&gl_overbright, GRAPHICALNICETIES);
Cvar_Register (&gl_overbright_all, GRAPHICALNICETIES); Cvar_Register (&gl_overbright_all, GRAPHICALNICETIES);
Cvar_Register (&gl_dither, GRAPHICALNICETIES); Cvar_Register (&gl_dither, GRAPHICALNICETIES);
Cvar_Register (&r_fog_cullentities, GRAPHICALNICETIES);
Cvar_Register (&r_fog_exp2, GLRENDEREROPTIONS); Cvar_Register (&r_fog_exp2, GLRENDEREROPTIONS);
Cvar_Register (&r_fog_permutation, GLRENDEREROPTIONS); Cvar_Register (&r_fog_permutation, GLRENDEREROPTIONS);
@ -732,14 +734,9 @@ void Renderer_Init(void)
Cmd_AddCommand("vid_toggle", R_ToggleFullscreen_f); Cmd_AddCommand("vid_toggle", R_ToggleFullscreen_f);
#ifdef RTLIGHTS #ifdef RTLIGHTS
Cmd_AddCommand ("r_editlights_reload", R_ReloadRTLights_f); R_EditLights_RegisterCommands();
Cmd_AddCommand ("r_editlights_save", R_SaveRTLights_f);
Cvar_Register (&r_editlights_import_radius, "Realtime Light editing/importing");
Cvar_Register (&r_editlights_import_ambient, "Realtime Light editing/importing");
Cvar_Register (&r_editlights_import_diffuse, "Realtime Light editing/importing");
Cvar_Register (&r_editlights_import_specular, "Realtime Light editing/importing");
#endif #endif
Cmd_AddCommand("r_dumpshaders", Shader_WriteOutGenerics_f); Cmd_AddCommand("r_dumpshaders", Shader_WriteOutGenerics_f);
Cmd_AddCommand("r_remapshader", Shader_RemapShader_f); Cmd_AddCommand("r_remapshader", Shader_RemapShader_f);
Cmd_AddCommand("r_showshader", Shader_ShowShader_f); Cmd_AddCommand("r_showshader", Shader_ShowShader_f);
@ -1243,12 +1240,12 @@ rendererinfo_t *rendererinfo[16] =
void R_RegisterRenderer(rendererinfo_t *ri) void R_RegisterRenderer(rendererinfo_t *ri)
{ {
size_t i; size_t i;
for (i = 0; i < sizeof(rendererinfo)/sizeof(rendererinfo[0]); i++) for (i = 0; i < countof(rendererinfo); i++)
{ //already registered { //already registered
if (rendererinfo[i] == ri) if (rendererinfo[i] == ri)
return; return;
} }
for (i = 0; i < sizeof(rendererinfo)/sizeof(rendererinfo[0]); i++) for (i = 0; i < countof(rendererinfo); i++)
{ //register it in the first empty slot { //register it in the first empty slot
if (!rendererinfo[i]) if (!rendererinfo[i])
{ {
@ -1603,7 +1600,6 @@ TRACE(("dbg: R_ApplyRenderer: initing mods\n"));
Cvar_ForceSetValue(&vid_dpi_x, vid.dpi_x); Cvar_ForceSetValue(&vid_dpi_x, vid.dpi_x);
Cvar_ForceSetValue(&vid_dpi_y, vid.dpi_y); Cvar_ForceSetValue(&vid_dpi_y, vid.dpi_y);
TRACE(("dbg: R_ApplyRenderer: R_PreNewMap (how handy)\n")); TRACE(("dbg: R_ApplyRenderer: R_PreNewMap (how handy)\n"));
Surf_PreNewMap(); Surf_PreNewMap();
@ -1690,6 +1686,10 @@ TRACE(("dbg: R_ApplyRenderer: clearing world\n"));
Plug_ResChanged(); Plug_ResChanged();
#endif #endif
Cvar_ForceCallback(&r_particlesystem); Cvar_ForceCallback(&r_particlesystem);
#ifdef MENU_NATIVECODE
if (mn_entry)
mn_entry->Init(MI_RENDERER, vid.width, vid.height, vid.rotpixelwidth, vid.rotpixelheight);
#endif
CL_InitDlights(); CL_InitDlights();
@ -1861,6 +1861,22 @@ void R_ReloadRenderer_f (void)
#endif #endif
} }
static int R_PriorityForRenderer(rendererinfo_t *r)
{
if (r && r->name[0])
{
if (r->VID_GetPriority)
return r->VID_GetPriority();
else if (r->rtype == QR_HEADLESS)
return -1; //headless renderers are a really poor choice, and will make the user think it buggy.
else if (r->rtype == QR_NONE)
return 0; //dedicated servers are possible, but we really don't want to use them unless we have no other choice.
else
return 1; //assume 1 for most renderers.
}
return -2; //invalid renderer
}
//use Cvar_ApplyLatches(CVAR_RENDERERLATCH) beforehand. //use Cvar_ApplyLatches(CVAR_RENDERERLATCH) beforehand.
qboolean R_BuildRenderstate(rendererstate_t *newr, char *rendererstring) qboolean R_BuildRenderstate(rendererstate_t *newr, char *rendererstring)
{ {
@ -1932,20 +1948,7 @@ qboolean R_BuildRenderstate(rendererstate_t *newr, char *rendererstring)
//I'd like to just qsort the renderers, but that isn't stable and might reorder gl+d3d etc. //I'd like to just qsort the renderers, but that isn't stable and might reorder gl+d3d etc.
for (i = 0; i < countof(rendererinfo); i++) for (i = 0; i < countof(rendererinfo); i++)
{ {
if (rendererinfo[i] && rendererinfo[i]->name[0]) pri = R_PriorityForRenderer(rendererinfo[i]);
{
if (rendererinfo[i]->VID_GetPriority)
pri = rendererinfo[i]->VID_GetPriority();
else if (rendererinfo[i]->rtype == QR_HEADLESS)
pri = -1; //headless renderers are a really poor choice, and will make the user think it buggy.
else if (rendererinfo[i]->rtype == QR_NONE)
pri = 0; //dedicated servers are possible, but we really don't want to use them unless we have no other choice.
else
pri = 1; //assume 1 for most renderers.
}
else
pri = -2;
if (pri > bestpri) if (pri > bestpri)
{ {
bestpri = pri; bestpri = pri;
@ -1956,7 +1959,7 @@ qboolean R_BuildRenderstate(rendererstate_t *newr, char *rendererstring)
else if (!strcmp(com_token, "random")) else if (!strcmp(com_token, "random"))
{ {
int count; int count;
for (i = 0, count = 0; i < sizeof(rendererinfo)/sizeof(rendererinfo[0]); i++) for (i = 0, count = 0; i < countof(rendererinfo); i++)
{ {
if (!rendererinfo[i] || !rendererinfo[i]->description) if (!rendererinfo[i] || !rendererinfo[i]->description)
continue; //not valid in this build. :( continue; //not valid in this build. :(
@ -1967,7 +1970,7 @@ qboolean R_BuildRenderstate(rendererstate_t *newr, char *rendererstring)
count++; count++;
} }
count = rand()%count; count = rand()%count;
for (i = 0; i < sizeof(rendererinfo)/sizeof(rendererinfo[0]); i++) for (i = 0; i < countof(rendererinfo); i++)
{ {
if (!rendererinfo[i] || !rendererinfo[i]->description) if (!rendererinfo[i] || !rendererinfo[i]->description)
continue; //not valid in this build. :( continue; //not valid in this build. :(
@ -1986,7 +1989,7 @@ qboolean R_BuildRenderstate(rendererstate_t *newr, char *rendererstring)
else else
{ {
int bestpri = -2, pri; int bestpri = -2, pri;
for (i = 0; i < sizeof(rendererinfo)/sizeof(rendererinfo[0]); i++) for (i = 0; i < countof(rendererinfo); i++)
{ {
if (!rendererinfo[i] || !rendererinfo[i]->description) if (!rendererinfo[i] || !rendererinfo[i]->description)
continue; //not valid in this build. :( continue; //not valid in this build. :(
@ -1996,14 +1999,7 @@ qboolean R_BuildRenderstate(rendererstate_t *newr, char *rendererstring)
continue; continue;
if (!stricmp(rendererinfo[i]->name[j], com_token)) if (!stricmp(rendererinfo[i]->name[j], com_token))
{ {
if (rendererinfo[i]->VID_GetPriority) pri = R_PriorityForRenderer(rendererinfo[i]);
pri = rendererinfo[i]->VID_GetPriority();
else if (rendererinfo[i]->rtype == QR_HEADLESS)
pri = -1; //headless renderers are a really poor choice, and will make the user think it buggy.
else if (rendererinfo[i]->rtype == QR_NONE)
pri = 0; //dedicated servers are possible, but we really don't want to use them unless we have no other choice.
else
pri = 1;
if (pri > bestpri) if (pri > bestpri)
{ {
@ -2073,6 +2069,21 @@ qboolean R_BuildRenderstate(rendererstate_t *newr, char *rendererstring)
return newr->renderer != NULL; return newr->renderer != NULL;
} }
struct sortedrenderers_s
{
int index; //original index, to try to retain stable sort orders.
int pri;
rendererinfo_t *r;
};
static int QDECL R_SortRenderers(const void *av, const void *bv)
{
const struct sortedrenderers_s *a = av;
const struct sortedrenderers_s *b = bv;
if (a->pri == b->pri)
return (a->index > b->index)?1:-1;
return (a->pri < b->pri)?1:-1;
}
void R_RestartRenderer (rendererstate_t *newr) void R_RestartRenderer (rendererstate_t *newr)
{ {
#ifndef CLIENTONLY #ifndef CLIENTONLY
@ -2112,6 +2123,7 @@ void R_RestartRenderer (rendererstate_t *newr)
int i; int i;
qboolean failed = true; qboolean failed = true;
rendererinfo_t *skip = newr->renderer; rendererinfo_t *skip = newr->renderer;
struct sortedrenderers_s sorted[countof(rendererinfo)];
if (failed && newr->fullscreen == 1) if (failed && newr->fullscreen == 1)
{ {
@ -2141,10 +2153,16 @@ void R_RestartRenderer (rendererstate_t *newr)
failed = !R_ApplyRenderer(newr); failed = !R_ApplyRenderer(newr);
} }
//FIXME: query renderers for their priority and then use that. then we can favour X11 when DISPLAY is set and wayland when WAYLAND_DISPLAY is set, etc. for (i = 0; i < countof(sorted); i++)
for (i = 0; failed && i < sizeof(rendererinfo)/sizeof(rendererinfo[0]); i++)
{ {
newr->renderer = rendererinfo[i]; sorted[i].index = i;
sorted[i].r = rendererinfo[i];
sorted[i].pri = R_PriorityForRenderer(sorted[i].r);
}
qsort(sorted, countof(sorted), sizeof(sorted[0]), R_SortRenderers);
for (i = 0; failed && i < countof(sorted); i++)
{
newr->renderer = sorted[i].r;
if (newr->renderer && newr->renderer != skip && newr->renderer->rtype != QR_HEADLESS) if (newr->renderer && newr->renderer != skip && newr->renderer->rtype != QR_HEADLESS)
{ {
Con_Printf(CON_NOTICE "Trying %s"CON_DEFAULT"\n", newr->renderer->description); Con_Printf(CON_NOTICE "Trying %s"CON_DEFAULT"\n", newr->renderer->description);
@ -2216,11 +2234,21 @@ void R_SetRenderer_f (void)
if (Cmd_Argc() == 1 || !stricmp(param, "help")) if (Cmd_Argc() == 1 || !stricmp(param, "help"))
{ {
Con_Printf ("\nValid setrenderer parameters are:\n"); struct sortedrenderers_s sorted[countof(rendererinfo)];
for (i = 0; i < sizeof(rendererinfo)/sizeof(rendererinfo[0]); i++) for (i = 0; i < countof(sorted); i++)
{ {
if (rendererinfo[i] && rendererinfo[i]->description) sorted[i].index = i;
Con_Printf("^[%s\\type\\/setrenderer %s^]^7: %s%s\n", rendererinfo[i]->name[0], rendererinfo[i]->name[0], rendererinfo[i]->description, (currentrendererstate.renderer == rendererinfo[i])?" ^2(current)":""); sorted[i].r = rendererinfo[i];
sorted[i].pri = R_PriorityForRenderer(sorted[i].r);
}
qsort(sorted, countof(sorted), sizeof(sorted[0]), R_SortRenderers);
Con_Printf ("\nValid setrenderer parameters are:\n");
for (i = 0; i < countof(rendererinfo); i++)
{
rendererinfo_t *r = sorted[i].r;
if (r && r->description)
Con_Printf("^[%s\\type\\/setrenderer %s^]^7: %s%s\n", r->name[0], r->name[0], r->description, (currentrendererstate.renderer == r)?" ^2(current)":"");
} }
return; return;
} }
@ -2966,7 +2994,7 @@ void R_SetFrustum (float projmat[16], float viewmat[16])
//do far plane //do far plane
//fog will logically not actually reach 0, though precision issues will force it. we cut off at an exponant of -500 //fog will logically not actually reach 0, though precision issues will force it. we cut off at an exponant of -500
if (r_refdef.globalfog.density) if (r_refdef.globalfog.density && r_fog_cullentities.ival)
{ {
float culldist; float culldist;
float fog; float fog;

View file

@ -22,7 +22,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
typedef struct playerview_s playerview_t; typedef struct playerview_s playerview_t;
extern float scr_con_current; extern float scr_con_current;
extern float scr_conlines; // lines of console to display extern float scr_con_target; // lines of console to display
extern int sb_lines; extern int sb_lines;
@ -231,7 +231,7 @@ typedef enum uploadfmt
#define PTI_EMULATED TF_INVALID:case TF_BGR24_FLIP:case TF_MIP4_R8:case TF_MIP4_SOLID8:case TF_MIP4_8PAL24:case TF_MIP4_8PAL24_T255:case TF_SOLID8:case TF_TRANS8:case TF_TRANS8_FULLBRIGHT:case TF_HEIGHT8:case TF_HEIGHT8PAL:case TF_H2_T7G1:case TF_H2_TRANS8_0:case TF_H2_T4A4:case TF_8PAL24:case TF_8PAL32:case PTI_LLLX8:case PTI_LLLA8 #define PTI_EMULATED TF_INVALID:case TF_BGR24_FLIP:case TF_MIP4_R8:case TF_MIP4_SOLID8:case TF_MIP4_8PAL24:case TF_MIP4_8PAL24_T255:case TF_SOLID8:case TF_TRANS8:case TF_TRANS8_FULLBRIGHT:case TF_HEIGHT8:case TF_HEIGHT8PAL:case TF_H2_T7G1:case TF_H2_TRANS8_0:case TF_H2_T4A4:case TF_8PAL24:case TF_8PAL32:case PTI_LLLX8:case PTI_LLLA8
} uploadfmt_t; } uploadfmt_t;
qboolean SCR_ScreenShot (char *filename, enum fs_relative fsroot, void **buffer, int numbuffers, int bytestride, int width, int height, enum uploadfmt fmt); qboolean SCR_ScreenShot (char *filename, enum fs_relative fsroot, void **buffer, int numbuffers, int bytestride, int width, int height, enum uploadfmt fmt, qboolean writemeta);
void SCR_DrawTwoDimensional(int uimenu, qboolean nohud); void SCR_DrawTwoDimensional(int uimenu, qboolean nohud);

View file

@ -33,6 +33,7 @@
#include <alsa/asoundlib.h> #include <alsa/asoundlib.h>
#include "quakedef.h" #include "quakedef.h"
#ifdef HAVE_MIXER
#include <dlfcn.h> #include <dlfcn.h>
static void *alsasharedobject; static void *alsasharedobject;
@ -589,4 +590,4 @@ sounddriver_t ALSA_Output =
ALSA_Enumerate ALSA_Enumerate
}; };
#endif #endif
#endif

View file

@ -316,13 +316,13 @@ typedef struct {
GUID SubFormat; GUID SubFormat;
} QWAVEFORMATEX; } QWAVEFORMATEX;
const static GUID QKSDATAFORMAT_SUBTYPE_PCM = {0x00000001,0x0000,0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}}; static const GUID QKSDATAFORMAT_SUBTYPE_PCM = {0x00000001,0x0000,0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
const static GUID QKSDATAFORMAT_SUBTYPE_IEEE_FLOAT = {0x00000003,0x0000,0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}}; static const GUID QKSDATAFORMAT_SUBTYPE_IEEE_FLOAT = {0x00000003,0x0000,0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
#ifdef _IKsPropertySet_ #ifdef _IKsPropertySet_
//const static GUID CLSID_EAXDIRECTSOUND = {0x4ff53b81, 0x1ce0, 0x11d3, //const static GUID CLSID_EAXDIRECTSOUND = {0x4ff53b81, 0x1ce0, 0x11d3,
//{0xaa, 0xb8, 0x0, 0xa0, 0xc9, 0x59, 0x49, 0xd5}}; //{0xaa, 0xb8, 0x0, 0xa0, 0xc9, 0x59, 0x49, 0xd5}};
const static GUID DSPROPSETID_EAX20_LISTENERPROPERTIES = {0x306a6a8, 0xb224, 0x11d2, static const GUID DSPROPSETID_EAX20_LISTENERPROPERTIES = {0x306a6a8, 0xb224, 0x11d2,
{0x99, 0xe5, 0x0, 0x0, 0xe8, 0xd8, 0xc7, 0x22}}; {0x99, 0xe5, 0x0, 0x0, 0xe8, 0xd8, 0xc7, 0x22}};
typedef struct _EAXLISTENERPROPERTIES typedef struct _EAXLISTENERPROPERTIES
@ -399,7 +399,7 @@ typedef enum
0x11d2, 0x11d2,
{0x99, 0xe5, 0x0, 0x0, 0xe8, 0xd8, 0xc7, 0x22}};*/ {0x99, 0xe5, 0x0, 0x0, 0xe8, 0xd8, 0xc7, 0x22}};*/
const static GUID CLSID_EAXDirectSound ={ static const GUID CLSID_EAXDirectSound ={
0x4ff53b81, 0x4ff53b81,
0x1ce0, 0x1ce0,
0x11d3, 0x11d3,

View file

@ -14,6 +14,8 @@
#include <stdio.h> #include <stdio.h>
#include "quakedef.h" #include "quakedef.h"
#ifdef HAVE_MIXER
#ifdef __linux__ #ifdef __linux__
#include <sys/stat.h> #include <sys/stat.h>
#endif #endif
@ -458,23 +460,30 @@ static qboolean QDECL OSS_Enumerate(void (QDECL *cb) (const char *drivername, co
int i; int i;
int fd; int fd;
oss_sysinfo si; oss_sysinfo si;
const char *devmixer;
if (COM_CheckParm("-nooss")) if (COM_CheckParm("-nooss"))
return true; return true;
fd = open("/dev/mixer", O_RDWR, 0);
devmixer = getenv("OSS_MIXERDEV");
if (!devmixer)
devmixer = "/dev/mixer";
fd = open(devmixer, O_RDWR|O_NONBLOCK, 0);
if (fd == -1) if (fd == -1)
return true; //oss not supported. don't list any devices. return true; //oss not supported. don't list any devices.
if (ioctl(fd, SNDCTL_SYSINFO, &si) != -1) memset(&si, 0, sizeof(si)); //just in case the driver is really dodgy...
if (ioctl(fd, SNDCTL_SYSINFO, &si) >= 0)
{ {
if ((si.versionnum>>16) >= 4) if ((si.versionnum>>16) >= 4 || si.numaudios > 128)
{ //only trust all the fields if its recent enough { //only trust all the fields if its recent enough and doesn't look dodgy.
for(i = 0; i < si.numaudios; i++) for(i = 0; i < si.numaudios; i++)
{ {
oss_audioinfo ai; oss_audioinfo ai;
memset(&ai, 0, sizeof(ai)); //just in case the driver is really dodgy...
ai.dev = i; ai.dev = i;
if (ioctl(fd, SNDCTL_AUDIOINFO, &ai) != -1) if (ioctl(fd, SNDCTL_AUDIOINFO, &ai) >= 0)
cb(SDRVNAME, ai.devnode, ai.name); cb(SDRVNAME, ai.devnode, ai.name);
} }
close(fd); close(fd);
@ -497,9 +506,7 @@ sounddriver_t OSS_Output =
OSS_Enumerate OSS_Enumerate
}; };
#endif
#ifdef VOICECHAT //this does apparently work after all. #ifdef VOICECHAT //this does apparently work after all.
#include <stdint.h> #include <stdint.h>
@ -597,4 +604,3 @@ snd_capture_driver_t OSS_Capture =
OSS_Capture_Shutdown OSS_Capture_Shutdown
}; };
#endif #endif

View file

@ -146,16 +146,16 @@ CHANNEL MIXING
=============================================================================== ===============================================================================
*/ */
static void SND_PaintChannel8_O2I1 (channel_t *ch, sfxcache_t *sc, int starttime, int count); static void SND_PaintChannel8_O2I1 (channel_t *ch, sfxcache_t *sc, int starttime, int count, int rate);
static void SND_PaintChannel16_O2I1 (channel_t *ch, sfxcache_t *sc, int starttime, int count); static void SND_PaintChannel16_O2I1 (channel_t *ch, sfxcache_t *sc, int starttime, int count, int rate);
static void SND_PaintChannel8_O4I1 (channel_t *ch, sfxcache_t *sc, int count); static void SND_PaintChannel8_O4I1 (channel_t *ch, sfxcache_t *sc, int count, int rate);
static void SND_PaintChannel16_O4I1 (channel_t *ch, sfxcache_t *sc, int count); static void SND_PaintChannel16_O4I1 (channel_t *ch, sfxcache_t *sc, int count, int rate);
static void SND_PaintChannel8_O6I1 (channel_t *ch, sfxcache_t *sc, int count); static void SND_PaintChannel8_O6I1 (channel_t *ch, sfxcache_t *sc, int count, int rate);
static void SND_PaintChannel16_O6I1 (channel_t *ch, sfxcache_t *sc, int count); static void SND_PaintChannel16_O6I1 (channel_t *ch, sfxcache_t *sc, int count, int rate);
static void SND_PaintChannel8_O8I1 (channel_t *ch, sfxcache_t *sc, int count); static void SND_PaintChannel8_O8I1 (channel_t *ch, sfxcache_t *sc, int count, int rate);
static void SND_PaintChannel16_O8I1 (channel_t *ch, sfxcache_t *sc, int count); static void SND_PaintChannel16_O8I1 (channel_t *ch, sfxcache_t *sc, int count, int rate);
static void SND_PaintChannel8_O2I2 (channel_t *ch, sfxcache_t *sc, int starttime, int count); static void SND_PaintChannel8_O2I2 (channel_t *ch, sfxcache_t *sc, int starttime, int count, int rate);
static void SND_PaintChannel16_O2I2 (channel_t *ch, sfxcache_t *sc, int starttime, int count); static void SND_PaintChannel16_O2I2 (channel_t *ch, sfxcache_t *sc, int starttime, int count, int rate);
//NOTE: MAY NOT CALL SYS_ERROR //NOTE: MAY NOT CALL SYS_ERROR
void S_PaintChannels(soundcardinfo_t *sc, int endtime) void S_PaintChannels(soundcardinfo_t *sc, int endtime)
@ -169,6 +169,7 @@ void S_PaintChannels(soundcardinfo_t *sc, int endtime)
int ltime, count; int ltime, count;
int avail; int avail;
unsigned int maxlen = ruleset_allow_overlongsounds.ival?0xffffffffu>>PITCHSHIFT:snd_speed*20; unsigned int maxlen = ruleset_allow_overlongsounds.ival?0xffffffffu>>PITCHSHIFT:snd_speed*20;
int rate;
while (sc->paintedtime < endtime) while (sc->paintedtime < endtime)
{ {
@ -272,6 +273,11 @@ void S_PaintChannels(soundcardinfo_t *sc, int endtime)
break; break;
} }
if (sc->sn.speed != scache->speed)
rate = (ch->rate * scache->speed) / sc->sn.speed; //sound was loaded at the wrong speed. just play it back at a different speed and hope that all is well. this is nearest sampling, so expect it to be a little poo.
else
rate = ch->rate;
if (spos < scache->soundoffset || spos > scache->soundoffset+scache->length) if (spos < scache->soundoffset || spos > scache->soundoffset+scache->length)
avail = 0; //urm, we would be trying to read outside of the buffer. let mixing slip when there's no data available yet. avail = 0; //urm, we would be trying to read outside of the buffer. let mixing slip when there's no data available yet.
else else
@ -280,7 +286,7 @@ void S_PaintChannels(soundcardinfo_t *sc, int endtime)
avail = scache->length; avail = scache->length;
if (avail > maxlen) if (avail > maxlen)
avail = snd_speed*10; avail = snd_speed*10;
avail = (((int)(scache->soundoffset + avail)<<PITCHSHIFT) - ch->pos + (ch->rate-1)) / ch->rate; avail = (((int)(scache->soundoffset + avail)<<PITCHSHIFT) - ch->pos + (rate-1)) / rate;
} }
// mix the smaller of how much is available or the time left // mix the smaller of how much is available or the time left
count = min(avail, end - ltime); count = min(avail, end - ltime);
@ -293,38 +299,38 @@ void S_PaintChannels(soundcardinfo_t *sc, int endtime)
if (count > (-ch->pos+255)>>PITCHSHIFT) if (count > (-ch->pos+255)>>PITCHSHIFT)
count = ((-ch->pos+255)>>PITCHSHIFT); count = ((-ch->pos+255)>>PITCHSHIFT);
ltime += count; ltime += count;
ch->pos += count*ch->rate; ch->pos += count*rate;
continue; continue;
} }
if (scache->width == 1) if (scache->width == 1)
{ {
if (scache->numchannels==2) if (scache->numchannels==2)
SND_PaintChannel8_O2I2(ch, scache, ltime-sc->paintedtime, count); SND_PaintChannel8_O2I2(ch, scache, ltime-sc->paintedtime, count, rate);
else if (sc->sn.numchannels <= 2) else if (sc->sn.numchannels <= 2)
SND_PaintChannel8_O2I1(ch, scache, ltime-sc->paintedtime, count); SND_PaintChannel8_O2I1(ch, scache, ltime-sc->paintedtime, count, rate);
else if (sc->sn.numchannels <= 4) else if (sc->sn.numchannels <= 4)
SND_PaintChannel8_O4I1(ch, scache, count); SND_PaintChannel8_O4I1(ch, scache, count, rate);
else if (sc->sn.numchannels <= 6) else if (sc->sn.numchannels <= 6)
SND_PaintChannel8_O6I1(ch, scache, count); SND_PaintChannel8_O6I1(ch, scache, count, rate);
else else
SND_PaintChannel8_O8I1(ch, scache, count); SND_PaintChannel8_O8I1(ch, scache, count, rate);
} }
else if (scache->width == 2) else if (scache->width == 2)
{ {
if (scache->numchannels==2) if (scache->numchannels==2)
SND_PaintChannel16_O2I2(ch, scache, ltime-sc->paintedtime, count); SND_PaintChannel16_O2I2(ch, scache, ltime-sc->paintedtime, count, rate);
else if (sc->sn.numchannels <= 2) else if (sc->sn.numchannels <= 2)
SND_PaintChannel16_O2I1(ch, scache, ltime-sc->paintedtime, count); SND_PaintChannel16_O2I1(ch, scache, ltime-sc->paintedtime, count, rate);
else if (sc->sn.numchannels <= 4) else if (sc->sn.numchannels <= 4)
SND_PaintChannel16_O4I1(ch, scache, count); SND_PaintChannel16_O4I1(ch, scache, count, rate);
else if (sc->sn.numchannels <= 6) else if (sc->sn.numchannels <= 6)
SND_PaintChannel16_O6I1(ch, scache, count); SND_PaintChannel16_O6I1(ch, scache, count, rate);
else else
SND_PaintChannel16_O8I1(ch, scache, count); SND_PaintChannel16_O8I1(ch, scache, count, rate);
} }
ltime += count; ltime += count;
ch->pos += ch->rate * count; ch->pos += rate * count;
} }
else else
break; break;
@ -337,20 +343,20 @@ void S_PaintChannels(soundcardinfo_t *sc, int endtime)
} }
} }
static void SND_PaintChannel8_O2I1 (channel_t *ch, sfxcache_t *sc, int starttime, int count) static void SND_PaintChannel8_O2I1 (channel_t *ch, sfxcache_t *sc, int starttime, int count, int rate)
{ {
int data; int data;
signed char *sfx; signed char *sfx;
int i; int i;
unsigned int pos = ch->pos-(sc->soundoffset<<PITCHSHIFT); unsigned int pos = ch->pos-(sc->soundoffset<<PITCHSHIFT);
if (ch->rate != (1<<PITCHSHIFT)) if (rate != (1<<PITCHSHIFT))
{ {
sfx = (signed char *)sc->data; sfx = (signed char *)sc->data;
for (i=0 ; i<count ; i++) for (i=0 ; i<count ; i++)
{ {
data = sfx[pos>>PITCHSHIFT]; data = sfx[pos>>PITCHSHIFT];
pos += ch->rate; pos += rate;
paintbuffer[starttime+i].s[0] += ch->vol[0] * data; paintbuffer[starttime+i].s[0] += ch->vol[0] * data;
paintbuffer[starttime+i].s[1] += ch->vol[1] * data; paintbuffer[starttime+i].s[1] += ch->vol[1] * data;
} }
@ -367,21 +373,21 @@ static void SND_PaintChannel8_O2I1 (channel_t *ch, sfxcache_t *sc, int starttime
} }
} }
static void SND_PaintChannel8_O2I2 (channel_t *ch, sfxcache_t *sc, int starttime, int count) static void SND_PaintChannel8_O2I2 (channel_t *ch, sfxcache_t *sc, int starttime, int count, int rate)
{ {
// int data; // int data;
signed char *sfx; signed char *sfx;
int i; int i;
unsigned int pos = ch->pos-(sc->soundoffset<<PITCHSHIFT); unsigned int pos = ch->pos-(sc->soundoffset<<PITCHSHIFT);
if (ch->rate != (1<<PITCHSHIFT)) if (rate != (1<<PITCHSHIFT))
{ {
sfx = (signed char *)sc->data; sfx = (signed char *)sc->data;
for (i=0 ; i<count ; i++) for (i=0 ; i<count ; i++)
{ {
paintbuffer[starttime+i].s[0] += ch->vol[0] * sfx[(pos>>(PITCHSHIFT-1))&~1]; paintbuffer[starttime+i].s[0] += ch->vol[0] * sfx[(pos>>(PITCHSHIFT-1))&~1];
paintbuffer[starttime+i].s[1] += ch->vol[1] * sfx[(pos>>(PITCHSHIFT-1))|1]; paintbuffer[starttime+i].s[1] += ch->vol[1] * sfx[(pos>>(PITCHSHIFT-1))|1];
pos += ch->rate; pos += rate;
} }
} }
else else
@ -395,20 +401,20 @@ static void SND_PaintChannel8_O2I2 (channel_t *ch, sfxcache_t *sc, int starttime
} }
} }
static void SND_PaintChannel8_O4I1 (channel_t *ch, sfxcache_t *sc, int count) static void SND_PaintChannel8_O4I1 (channel_t *ch, sfxcache_t *sc, int count, int rate)
{ {
signed char *sfx; signed char *sfx;
int i; int i;
unsigned int pos = ch->pos-(sc->soundoffset<<PITCHSHIFT); unsigned int pos = ch->pos-(sc->soundoffset<<PITCHSHIFT);
if (ch->rate != (1<<PITCHSHIFT)) if (rate != (1<<PITCHSHIFT))
{ {
signed char data; signed char data;
sfx = (signed char *)sc->data; sfx = (signed char *)sc->data;
for (i=0 ; i<count ; i++) for (i=0 ; i<count ; i++)
{ {
data = sfx[pos>>PITCHSHIFT]; data = sfx[pos>>PITCHSHIFT];
pos += ch->rate; pos += rate;
paintbuffer[i].s[0] += ch->vol[0] * data; paintbuffer[i].s[0] += ch->vol[0] * data;
paintbuffer[i].s[1] += ch->vol[1] * data; paintbuffer[i].s[1] += ch->vol[1] * data;
paintbuffer[i].s[2] += ch->vol[2] * data; paintbuffer[i].s[2] += ch->vol[2] * data;
@ -428,20 +434,20 @@ static void SND_PaintChannel8_O4I1 (channel_t *ch, sfxcache_t *sc, int count)
} }
} }
static void SND_PaintChannel8_O6I1 (channel_t *ch, sfxcache_t *sc, int count) static void SND_PaintChannel8_O6I1 (channel_t *ch, sfxcache_t *sc, int count, int rate)
{ {
signed char *sfx; signed char *sfx;
int i; int i;
unsigned int pos = ch->pos-(sc->soundoffset<<PITCHSHIFT); unsigned int pos = ch->pos-(sc->soundoffset<<PITCHSHIFT);
if (ch->rate != (1<<PITCHSHIFT)) if (rate != (1<<PITCHSHIFT))
{ {
signed char data; signed char data;
sfx = (signed char *)sc->data; sfx = (signed char *)sc->data;
for (i=0 ; i<count ; i++) for (i=0 ; i<count ; i++)
{ {
data = sfx[pos>>PITCHSHIFT]; data = sfx[pos>>PITCHSHIFT];
pos += ch->rate; pos += rate;
paintbuffer[i].s[0] += ch->vol[0] * data; paintbuffer[i].s[0] += ch->vol[0] * data;
paintbuffer[i].s[1] += ch->vol[1] * data; paintbuffer[i].s[1] += ch->vol[1] * data;
paintbuffer[i].s[2] += ch->vol[2] * data; paintbuffer[i].s[2] += ch->vol[2] * data;
@ -465,20 +471,20 @@ static void SND_PaintChannel8_O6I1 (channel_t *ch, sfxcache_t *sc, int count)
} }
} }
static void SND_PaintChannel8_O8I1 (channel_t *ch, sfxcache_t *sc, int count) static void SND_PaintChannel8_O8I1 (channel_t *ch, sfxcache_t *sc, int count, int rate)
{ {
signed char *sfx; signed char *sfx;
int i; int i;
unsigned int pos = ch->pos-(sc->soundoffset<<PITCHSHIFT); unsigned int pos = ch->pos-(sc->soundoffset<<PITCHSHIFT);
if (ch->rate != (1<<PITCHSHIFT)) if (rate != (1<<PITCHSHIFT))
{ {
signed char data; signed char data;
sfx = (signed char *)sc->data; sfx = (signed char *)sc->data;
for (i=0 ; i<count ; i++) for (i=0 ; i<count ; i++)
{ {
data = sfx[pos>>PITCHSHIFT]; data = sfx[pos>>PITCHSHIFT];
pos += ch->rate; pos += rate;
paintbuffer[i].s[0] += ch->vol[0] * data; paintbuffer[i].s[0] += ch->vol[0] * data;
paintbuffer[i].s[1] += ch->vol[1] * data; paintbuffer[i].s[1] += ch->vol[1] * data;
paintbuffer[i].s[2] += ch->vol[2] * data; paintbuffer[i].s[2] += ch->vol[2] * data;
@ -507,7 +513,7 @@ static void SND_PaintChannel8_O8I1 (channel_t *ch, sfxcache_t *sc, int count)
} }
static void SND_PaintChannel16_O2I1 (channel_t *ch, sfxcache_t *sc, int starttime, int count) static void SND_PaintChannel16_O2I1 (channel_t *ch, sfxcache_t *sc, int starttime, int count, int rate)
{ {
int data; int data;
int left, right; int left, right;
@ -519,7 +525,7 @@ static void SND_PaintChannel16_O2I1 (channel_t *ch, sfxcache_t *sc, int starttim
leftvol = ch->vol[0]; leftvol = ch->vol[0];
rightvol = ch->vol[1]; rightvol = ch->vol[1];
if (ch->rate != (1<<PITCHSHIFT)) if (rate != (1<<PITCHSHIFT))
{ {
signed short data; signed short data;
sfx = (signed short *)sc->data; sfx = (signed short *)sc->data;
@ -527,7 +533,7 @@ static void SND_PaintChannel16_O2I1 (channel_t *ch, sfxcache_t *sc, int starttim
{ {
float frac = pos&((1<<PITCHSHIFT)-1); float frac = pos&((1<<PITCHSHIFT)-1);
data = sfx[pos>>PITCHSHIFT] * (1-frac) + sfx[(pos>>PITCHSHIFT)+1] * frac; data = sfx[pos>>PITCHSHIFT] * (1-frac) + sfx[(pos>>PITCHSHIFT)+1] * frac;
pos += ch->rate; pos += rate;
paintbuffer[starttime+i].s[0] += (leftvol * data)>>8; paintbuffer[starttime+i].s[0] += (leftvol * data)>>8;
paintbuffer[starttime+i].s[1] += (rightvol * data)>>8; paintbuffer[starttime+i].s[1] += (rightvol * data)>>8;
} }
@ -546,7 +552,7 @@ static void SND_PaintChannel16_O2I1 (channel_t *ch, sfxcache_t *sc, int starttim
} }
} }
static void SND_PaintChannel16_O2I2 (channel_t *ch, sfxcache_t *sc, int starttime, int count) static void SND_PaintChannel16_O2I2 (channel_t *ch, sfxcache_t *sc, int starttime, int count, int rate)
{ {
int leftvol, rightvol; int leftvol, rightvol;
signed short *sfx; signed short *sfx;
@ -556,7 +562,7 @@ static void SND_PaintChannel16_O2I2 (channel_t *ch, sfxcache_t *sc, int starttim
leftvol = ch->vol[0]; leftvol = ch->vol[0];
rightvol = ch->vol[1]; rightvol = ch->vol[1];
if (ch->rate != (1<<PITCHSHIFT)) if (rate != (1<<PITCHSHIFT))
{ {
signed short l, r; signed short l, r;
sfx = (signed short *)sc->data; sfx = (signed short *)sc->data;
@ -564,7 +570,7 @@ static void SND_PaintChannel16_O2I2 (channel_t *ch, sfxcache_t *sc, int starttim
{ {
l = sfx[(pos>>(PITCHSHIFT-1))&~1]; l = sfx[(pos>>(PITCHSHIFT-1))&~1];
r = sfx[(pos>>(PITCHSHIFT-1))|1]; r = sfx[(pos>>(PITCHSHIFT-1))|1];
pos += ch->rate; pos += rate;
paintbuffer[starttime+i].s[0] += (ch->vol[0] * l)>>8; paintbuffer[starttime+i].s[0] += (ch->vol[0] * l)>>8;
paintbuffer[starttime+i].s[1] += (ch->vol[1] * r)>>8; paintbuffer[starttime+i].s[1] += (ch->vol[1] * r)>>8;
} }
@ -580,7 +586,7 @@ static void SND_PaintChannel16_O2I2 (channel_t *ch, sfxcache_t *sc, int starttim
} }
} }
static void SND_PaintChannel16_O4I1 (channel_t *ch, sfxcache_t *sc, int count) static void SND_PaintChannel16_O4I1 (channel_t *ch, sfxcache_t *sc, int count, int rate)
{ {
int vol[4]; int vol[4];
signed short *sfx; signed short *sfx;
@ -592,14 +598,14 @@ static void SND_PaintChannel16_O4I1 (channel_t *ch, sfxcache_t *sc, int count)
vol[2] = ch->vol[2]; vol[2] = ch->vol[2];
vol[3] = ch->vol[3]; vol[3] = ch->vol[3];
if (ch->rate != (1<<PITCHSHIFT)) if (rate != (1<<PITCHSHIFT))
{ {
signed short data; signed short data;
sfx = (signed short *)sc->data; sfx = (signed short *)sc->data;
for (i=0 ; i<count ; i++) for (i=0 ; i<count ; i++)
{ {
data = sfx[pos>>PITCHSHIFT]; data = sfx[pos>>PITCHSHIFT];
pos += ch->rate; pos += rate;
paintbuffer[i].s[0] += (vol[0] * data)>>8; paintbuffer[i].s[0] += (vol[0] * data)>>8;
paintbuffer[i].s[1] += (vol[1] * data)>>8; paintbuffer[i].s[1] += (vol[1] * data)>>8;
paintbuffer[i].s[2] += (vol[2] * data)>>8; paintbuffer[i].s[2] += (vol[2] * data)>>8;
@ -619,7 +625,7 @@ static void SND_PaintChannel16_O4I1 (channel_t *ch, sfxcache_t *sc, int count)
} }
} }
static void SND_PaintChannel16_O6I1 (channel_t *ch, sfxcache_t *sc, int count) static void SND_PaintChannel16_O6I1 (channel_t *ch, sfxcache_t *sc, int count, int rate)
{ {
int vol[6]; int vol[6];
signed short *sfx; signed short *sfx;
@ -633,14 +639,14 @@ static void SND_PaintChannel16_O6I1 (channel_t *ch, sfxcache_t *sc, int count)
vol[4] = ch->vol[4]; vol[4] = ch->vol[4];
vol[5] = ch->vol[5]; vol[5] = ch->vol[5];
if (ch->rate != (1<<PITCHSHIFT)) if (rate != (1<<PITCHSHIFT))
{ {
signed short data; signed short data;
sfx = (signed short *)sc->data; sfx = (signed short *)sc->data;
for (i=0 ; i<count ; i++) for (i=0 ; i<count ; i++)
{ {
data = sfx[pos>>PITCHSHIFT]; data = sfx[pos>>PITCHSHIFT];
pos += ch->rate; pos += rate;
paintbuffer[i].s[0] += (vol[0] * data)>>8; paintbuffer[i].s[0] += (vol[0] * data)>>8;
paintbuffer[i].s[1] += (vol[1] * data)>>8; paintbuffer[i].s[1] += (vol[1] * data)>>8;
paintbuffer[i].s[2] += (vol[2] * data)>>8; paintbuffer[i].s[2] += (vol[2] * data)>>8;
@ -664,7 +670,7 @@ static void SND_PaintChannel16_O6I1 (channel_t *ch, sfxcache_t *sc, int count)
} }
} }
static void SND_PaintChannel16_O8I1 (channel_t *ch, sfxcache_t *sc, int count) static void SND_PaintChannel16_O8I1 (channel_t *ch, sfxcache_t *sc, int count, int rate)
{ {
int vol[8]; int vol[8];
signed short *sfx; signed short *sfx;
@ -680,14 +686,14 @@ static void SND_PaintChannel16_O8I1 (channel_t *ch, sfxcache_t *sc, int count)
vol[6] = ch->vol[6]; vol[6] = ch->vol[6];
vol[7] = ch->vol[7]; vol[7] = ch->vol[7];
if (ch->rate != (1<<PITCHSHIFT)) if (rate != (1<<PITCHSHIFT))
{ {
signed short data; signed short data;
sfx = (signed short *)sc->data; sfx = (signed short *)sc->data;
for (i=0 ; i<count ; i++) for (i=0 ; i<count ; i++)
{ {
data = sfx[pos>>PITCHSHIFT]; data = sfx[pos>>PITCHSHIFT];
pos += ch->rate; pos += rate;
paintbuffer[i].s[0] += (vol[0] * data)>>8; paintbuffer[i].s[0] += (vol[0] * data)>>8;
paintbuffer[i].s[1] += (vol[1] * data)>>8; paintbuffer[i].s[1] += (vol[1] * data)>>8;
paintbuffer[i].s[2] += (vol[2] * data)>>8; paintbuffer[i].s[2] += (vol[2] * data)>>8;

View file

@ -65,6 +65,25 @@ static const char *(SDLCALL *SDL_GetError) (void);
static uint32_t (SDLCALL *SDL_GetQueuedAudioSize) (SDL_AudioDeviceID dev); static uint32_t (SDLCALL *SDL_GetQueuedAudioSize) (SDL_AudioDeviceID dev);
static uint32_t (SDLCALL *SDL_DequeueAudio) (SDL_AudioDeviceID dev, void *data, uint32_t len); static uint32_t (SDLCALL *SDL_DequeueAudio) (SDL_AudioDeviceID dev, void *data, uint32_t len);
#endif #endif
static dllfunction_t sdl_funcs[] =
{
{(void*)&SDL_Init, "SDL_Init"},
{(void*)&SDL_InitSubSystem, "SDL_InitSubSystem"},
{(void*)&SDL_OpenAudioDevice, "SDL_OpenAudioDevice"},
{(void*)&SDL_PauseAudioDevice, "SDL_PauseAudioDevice"},
{(void*)&SDL_LockAudioDevice, "SDL_LockAudioDevice"},
{(void*)&SDL_UnlockAudioDevice, "SDL_UnlockAudioDevice"},
{(void*)&SDL_CloseAudioDevice, "SDL_CloseAudioDevice"},
{(void*)&SDL_GetNumAudioDevices, "SDL_GetNumAudioDevices"},
{(void*)&SDL_GetAudioDeviceName, "SDL_GetAudioDeviceName"},
{(void*)&SDL_GetError, "SDL_GetError"},
#if SDL_VERSION_ATLEAST(2,0,5)
{(void*)&SDL_GetQueuedAudioSize, "SDL_GetQueuedAudioSize"},
{(void*)&SDL_DequeueAudio, "SDL_DequeueAudio"},
#endif
{NULL, NULL}
};
static dllhandle_t *libsdl;
#else #else
#include <SDL.h> #include <SDL.h>
#endif #endif
@ -81,34 +100,17 @@ static uint32_t (SDLCALL *SDL_DequeueAudio) (SDL_AudioDeviceID dev, void *da
static qboolean SSDL_InitAudio(void) static qboolean SSDL_InitAudio(void)
{ {
static qboolean inited = false; static qboolean inited = false;
if (COM_CheckParm("-nosdlsnd") || COM_CheckParm("-nosdl"))
return false;
#ifdef DYNAMIC_SDL #ifdef DYNAMIC_SDL
static dllfunction_t funcs[] =
{
{(void*)&SDL_Init, "SDL_Init"},
{(void*)&SDL_InitSubSystem, "SDL_InitSubSystem"},
{(void*)&SDL_OpenAudioDevice, "SDL_OpenAudioDevice"},
{(void*)&SDL_PauseAudioDevice, "SDL_PauseAudioDevice"},
{(void*)&SDL_LockAudioDevice, "SDL_LockAudioDevice"},
{(void*)&SDL_UnlockAudioDevice, "SDL_UnlockAudioDevice"},
{(void*)&SDL_CloseAudioDevice, "SDL_CloseAudioDevice"},
{(void*)&SDL_GetNumAudioDevices, "SDL_GetNumAudioDevices"},
{(void*)&SDL_GetAudioDeviceName, "SDL_GetAudioDeviceName"},
{(void*)&SDL_GetError, "SDL_GetError"},
#if SDL_VERSION_ATLEAST(2,0,5)
{(void*)&SDL_GetQueuedAudioSize, "SDL_GetQueuedAudioSize"},
{(void*)&SDL_DequeueAudio, "SDL_DequeueAudio"},
#endif
{NULL, NULL}
};
static dllhandle_t *libsdl;
if (!libsdl) if (!libsdl)
{ {
libsdl = Sys_LoadLibrary("libSDL2-2.0.so.0", funcs); libsdl = Sys_LoadLibrary("libSDL2-2.0.so.0", sdl_funcs);
if (!libsdl) if (!libsdl)
libsdl = Sys_LoadLibrary("libSDL2.so", funcs); //maybe they have a dev package installed that fixes this mess. libsdl = Sys_LoadLibrary("libSDL2.so", sdl_funcs); //maybe they have a dev package installed that fixes this mess.
#ifdef _WIN32 #ifdef _WIN32
if (!libsdl) if (!libsdl)
libsdl = Sys_LoadLibrary("SDL2", funcs); libsdl = Sys_LoadLibrary("SDL2", sdl_funcs);
#endif #endif
if (libsdl) if (libsdl)
SDL_Init(SDL_INIT_NOPARACHUTE); SDL_Init(SDL_INIT_NOPARACHUTE);
@ -120,9 +122,6 @@ static qboolean SSDL_InitAudio(void)
} }
#endif #endif
if (COM_CheckParm("-nosndsnd"))
return false;
if (!inited) if (!inited)
if(SDL_InitSubSystem(SDL_INIT_AUDIO | SDL_INIT_NOPARACHUTE)) if(SDL_InitSubSystem(SDL_INIT_AUDIO | SDL_INIT_NOPARACHUTE))
{ {

View file

@ -791,7 +791,11 @@ static void Friendly_Crash_Handler(int sig, siginfo_t *info, void *vcontext)
#endif #endif
// print out all the frames to stderr // print out all the frames to stderr
#ifdef SVNREVISION
fprintf(stderr, "Error: signal %s (revision "STRINGIFY(SVNREVISION)")\n", signame);
#else
fprintf(stderr, "Error: signal %s:\n", signame); fprintf(stderr, "Error: signal %s:\n", signame);
#endif
backtrace_symbols_fd(array+firstframe, size-firstframe, 2); backtrace_symbols_fd(array+firstframe, size-firstframe, 2);
if (sig == SIGINT) if (sig == SIGINT)

View file

@ -23,6 +23,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "winquake.h" #include "winquake.h"
#include "glquake.h" #include "glquake.h"
#include "shader.h"
#include <ctype.h> // for isdigit(); #include <ctype.h> // for isdigit();
@ -103,8 +104,8 @@ cvar_t v_gunkick = CVARD("v_gunkick", "0", "Controls the strength of view ang
cvar_t v_gunkick_q2 = CVARD("v_gunkick_q2", "1", "Controls the strength of view angle changes when firing weapons (in Quake2)."); cvar_t v_gunkick_q2 = CVARD("v_gunkick_q2", "1", "Controls the strength of view angle changes when firing weapons (in Quake2).");
cvar_t v_viewmodel_quake = CVARD("r_viewmodel_quake", "0", "Controls whether to use weird viewmodel movements from vanilla quake."); //name comes from MarkV. cvar_t v_viewmodel_quake = CVARD("r_viewmodel_quake", "0", "Controls whether to use weird viewmodel movements from vanilla quake."); //name comes from MarkV.
cvar_t v_viewheight = CVAR("v_viewheight", "0"); cvar_t v_viewheight = CVARF("v_viewheight", "0", CVAR_ARCHIVE);
cvar_t v_projectionmode = CVAR("v_projectionmode", "0"); cvar_t v_projectionmode = CVARF("v_projectionmode", "0", CVAR_ARCHIVE);
cvar_t v_depthsortentities = CVARAD("v_depthsortentities", "0", "v_reorderentitiesrandomly", "Reorder entities for transparency such that the furthest entities are drawn first, allowing nearer transparent entities to draw over the top of them."); cvar_t v_depthsortentities = CVARAD("v_depthsortentities", "0", "v_reorderentitiesrandomly", "Reorder entities for transparency such that the furthest entities are drawn first, allowing nearer transparent entities to draw over the top of them.");
@ -2160,6 +2161,9 @@ void V_RenderPlayerViews(playerview_t *pv)
R_RenderView (); R_RenderView ();
R2D_PolyBlend (); R2D_PolyBlend ();
R_DrawNameTags(); R_DrawNameTags();
#ifdef RTLIGHTS
R_EditLights_DrawInfo();
#endif
if(cl.intermissionmode == IM_NONE) if(cl.intermissionmode == IM_NONE)
R2D_DrawCrosshair(); R2D_DrawCrosshair();
@ -2271,8 +2275,7 @@ void V_RenderPlayerViews(playerview_t *pv)
r_refdef.externalview = false; r_refdef.externalview = false;
} }
#include "shader.h" void V_RenderView (qboolean no2d)
void V_RenderView (void)
{ {
int seatnum; int seatnum;
int maxseats = cl.splitclients; int maxseats = cl.splitclients;
@ -2291,6 +2294,8 @@ void V_RenderView (void)
for (seatnum = 0; seatnum < cl.splitclients && seatnum < maxseats; seatnum++) for (seatnum = 0; seatnum < cl.splitclients && seatnum < maxseats; seatnum++)
{ {
V_ClearRefdef(&cl.playerview[seatnum]); V_ClearRefdef(&cl.playerview[seatnum]);
if (no2d)
r_refdef.drawcrosshair = r_refdef.drawsbar = 0;
if (seatnum) if (seatnum)
{ {
//should be enough to just hack a few things. //should be enough to just hack a few things.
@ -2348,7 +2353,7 @@ void V_RenderView (void)
#ifdef QUAKEHUD #ifdef QUAKEHUD
case 0: //show a mini-console. case 0: //show a mini-console.
{ {
console_t *con = &con_main; console_t *con = Con_GetMain();
extern cvar_t gl_conback; extern cvar_t gl_conback;
shader_t *conback; shader_t *conback;
if (*gl_conback.string && (conback = R_RegisterPic(gl_conback.string, NULL)) && R_GetShaderSizes(conback, NULL, NULL, true) > 0) if (*gl_conback.string && (conback = R_RegisterPic(gl_conback.string, NULL)) && R_GetShaderSizes(conback, NULL, NULL, true) > 0)
@ -2357,7 +2362,7 @@ void V_RenderView (void)
R2D_Image(r_refdef.grect.x, r_refdef.grect.y, r_refdef.grect.width, r_refdef.grect.height, 0, 0, 1, 1, conback); R2D_Image(r_refdef.grect.x, r_refdef.grect.y, r_refdef.grect.width, r_refdef.grect.height, 0, 0, 1, 1, conback);
else else
R2D_TileClear (r_refdef.grect.x, r_refdef.grect.y, r_refdef.grect.width, r_refdef.grect.height); R2D_TileClear (r_refdef.grect.x, r_refdef.grect.y, r_refdef.grect.width, r_refdef.grect.height);
if (!scr_conlines) if (!scr_con_target && con)
{ {
int gah; int gah;
Font_BeginString(font_console, 0, 0, &gah, &gah); Font_BeginString(font_console, 0, 0, &gah, &gah);

View file

@ -28,7 +28,7 @@ extern float hw_blend[4];
extern qboolean r_secondaryview; extern qboolean r_secondaryview;
void V_Init (void); void V_Init (void);
void V_RenderView (void); void V_RenderView (qboolean no2d);
float V_CalcRoll (vec3_t angles, vec3_t velocity); float V_CalcRoll (vec3_t angles, vec3_t velocity);
void V_UpdatePalette (qboolean force); void V_UpdatePalette (qboolean force);
void V_ClearCShifts (void); void V_ClearCShifts (void);

View file

@ -835,7 +835,7 @@ void Mod_ParseInfoFromEntityLump(model_t *wmodel) //actually, this should be in
Q_strncatz(wads, token, sizeof(wads)); //cache it for later (so that we don't play with any temp memory yet) Q_strncatz(wads, token, sizeof(wads)); //cache it for later (so that we don't play with any temp memory yet)
#endif #endif
} }
else if (!strcmp("fog", key)) //q1 extension. FIXME: should be made temporary. else if (!strcmp("fog", key) || !strcmp("airfog", key)) //q1 extension. FIXME: should be made temporary.
{ {
key[0] = 'f'; key[0] = 'f';
key[1] = 'o'; key[1] = 'o';

View file

@ -96,259 +96,15 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#endif #endif
#endif #endif
#ifdef CONFIG_FILE_NAME #undef MULTITHREAD
#undef MULTITHREAD #define HEADLESSQUAKE //usable renderers are normally specified via the makefile, but HEADLESS is considered a feature rather than an actual renderer, so usually gets forgotten about...
#define HEADLESSQUAKE //usable renderers are normally specified via the makefile, but HEADLESS is considered a feature rather than an actual renderer, so usually gets forgotten about...
//yup, C89 allows this (doesn't like C's token concat though). //yup, C89 allows this (doesn't like C's token concat though).
#include STRINGIFY(CONFIG_FILE_NAME) #include STRINGIFY(CONFIG_FILE_NAME)
#else
#define QWSKINS //disables qw .pcx skins, as well as enemy/team colour forcing.
#ifndef NO_LIBRARIES
#define AVAIL_OPENAL
#define AVAIL_FREETYPE
#endif
#define AVAIL_OGGVORBIS
#if defined(__CYGWIN__)
#define AVAIL_ZLIB
#else
#define AVAIL_PNGLIB
#define AVAIL_JPEGLIB
#define AVAIL_ZLIB
#define AVAIL_OGGVORBIS
#endif
#ifdef WINRT
#define AVAIL_XAUDIO2
#define AVAIL_WASAPI
#elif !defined(NO_DIRECTX) && !defined(NODIRECTX) && defined(_WIN32)
#define AVAIL_DINPUT
#define AVAIL_DSOUND
#define AVAIL_WASAPI
//#define AVAIL_XAUDIO2 //gcc doesn't provide any headers
#endif
#define AVAIL_XZDEC
#if !defined(MINIMAL) && !defined(NPFTE) && !defined(NPQTV)
#if defined(_WIN32) && !defined(FTE_SDL) && !defined(WINRT) && !defined(_XBOX)
#if !defined(_MSC_VER) || _MSC_VER > 1200
#define HAVE_WINSSPI //built in component, checks against windows' root ca database and revocations etc.
#endif
#elif (defined(__linux__) || defined(__CYGWIN__)) && !defined(ANDROID)
#define HAVE_GNUTLS //currently disabled as it does not validate the server's certificate, beware the mitm attack.
#endif
#endif
//#define DYNAMIC_ZLIB
//#define DYNAMIC_LIBPNG
//#define DYNAMIC_LIBJPEG
//#define LIBVORBISFILE_STATIC
//#define SPEEX_STATIC
#if defined(_WIN32) && defined(GLQUAKE)
//#define USE_EGL
#endif
#if defined(_MSC_VER) && !defined(BOTLIB_STATIC) //too lazy to fix up the makefile
#define BOTLIB_STATIC
#endif
#if (defined(_MSC_VER) && (_MSC_VER < 1500)) || defined(FTE_SDL)
#undef AVAIL_WASAPI //wasapi is available in the vista sdk, while that's compatible with earlier versions, its not really expected until 2008
#endif
#define HAVE_TCP //says we can use tcp too (either ipv4 or ipv6)
#define HAVE_PACKET //if we have the socket api at all...
#define HAVE_MIXER //can be disabled if you have eg openal instead.
//set any additional defines or libs in win32
#define LOADERTHREAD
#define PACKAGE_Q1PAK
#define PACKAGE_PK3
#define AVAIL_GZDEC
#define PACKAGE_TEXWAD //quake's image wad support
#ifdef GLQUAKE
#define HEADLESSQUAKE
#endif
#define AVAIL_MP3_ACM //microsoft's Audio Compression Manager api
#ifdef NOLEGACY
//these are only the features that really make sense in a more modern engine
#define QUAKETC //skip some legacy stuff
#define SPRMODELS //quake1 sprite models
#define INTERQUAKEMODELS
#define RTLIGHTS //realtime lighting
#define Q1BSPS //quake 1 bsp support, because we're still a quake engine
#define Q2BSPS //quake 2 bsp support (a dependancy of q3bsp)
#define Q3BSPS //quake 3 bsp support
// #define TERRAIN //heightmap support
#define WEBCLIENT //http/ftp clients.
#define IMAGEFMT_DDS //a sort of image file format.
#define PSET_SCRIPT
// #define PLUGINS //qvm/dll plugins.
// #define SUPPORT_ICE //Interactive Connectivity Establishment protocol, for peer-to-peer connections
#define CSQC_DAT //support for csqc
// #define VOICECHAT
#undef AVAIL_JPEGLIB
#undef AVAIL_XZDEC
#elif defined(MINIMAL)
#define QUAKESTATS
#define QUAKEHUD
#define CL_MASTER //this is useful
#undef AVAIL_JPEGLIB //no jpeg support
#undef AVAIL_PNGLIB //no png support
#undef AVAIL_OPENAL //just bloat...
#undef AVAIL_GZDEC
#define Q1BSPS
#define SPRMODELS //quake1 sprite models
#define MD1MODELS //quake ain't much use without this
#define MD3MODELS //we DO want to use quake3 alias models. This might be a minimal build, but we still want this.
#define PLUGINS
#define NOQCDESCRIPTIONS 2 //trim space from no fteextensions.qc info
#define PSET_CLASSIC
//#define CSQC_DAT //support for csqc
#ifndef SERVERONLY //don't be stupid, stupid.
#ifndef CLIENTONLY
#define CLIENTONLY
#endif
#endif
#else
#define NETPREPARSE
#define QUAKESTATS
#define QUAKEHUD
#define SVRANKING
#define USE_SQLITE
#ifdef SERVERONLY
// #define USE_MYSQL //allow mysql in dedicated servers.
#endif
#if defined(_WIN32) && !defined(FTE_SDL) && !defined(WINRT)
#define SUBSERVERS //use subserver code.
#elif defined(__linux__) && !defined(ANDROID) && !defined(FTE_SDL)
#define SUBSERVERS //use subserver code.
#endif
#define SIDEVIEWS 4 //enable secondary/reverse views.
// #define DSPMODELS //doom sprites (only needs PACKAGE_DOOMWAD to generate the right wad file names)
#define SPRMODELS //quake1 sprite models
#define SP2MODELS //quake2 sprite models
#define MD1MODELS //quake1 alias models
#define MD2MODELS //quake2 alias models
#define MD3MODELS //quake3 alias models
#define MD5MODELS //doom3 models
#define ZYMOTICMODELS //zymotic skeletal models.
#define DPMMODELS //darkplaces model format (which I've never seen anyone use)
// #define PSKMODELS //PSK model format (ActorX stuff from UT, though not the format the game itself uses)
#define HALFLIFEMODELS //halflife model support (experimental)
#define INTERQUAKEMODELS
#define RAGDOLL
#define USEAREAGRID //world collision optimisation. REQUIRED for performance with xonotic. hopefully it helps a few other mods too.
#define HUFFNETWORK //huffman network compression
// #define PACKAGE_DOOMWAD //doom wad support (maps+sprites are separate)
// #define MAP_DOOM //doom map support
// #define MAP_PROC //doom3/quake4 map support
//#define WOLF3DSUPPORT //wolfenstein3d map support (not started yet)
#define Q1BSPS //quake 1 bsp support, because we're still a quake engine
#define Q2BSPS //quake 2 bsp support
#define Q3BSPS //quake 3 bsp support
#define RFBSPS //rogue(sof+jk2o)+qfusion bsp support
#define TERRAIN //heightmap support
// #define SV_MASTER //starts up a master server
#define SVCHAT //serverside npc chatting. see sv_chat.c
#define Q2SERVER //server can run a q2 game dll and switches to q2 network and everything else.
#define Q2CLIENT //client can connect to q2 servers
#define Q3CLIENT
#define Q3SERVER
#define HEXEN2 //mostly server only, but also includes some hud+menu stuff, and effects
// #define HLCLIENT 7 //we can run HL gamecode (not protocol compatible, set to 6 or 7)
// #define HLSERVER 140 //we can run HL gamecode (not protocol compatible, set to 138 or 140)
#define NQPROT //server and client are capable of using quake1/netquake protocols. (qw is still prefered. uses the command 'nqconnect')
#define PACKAGE_DZIP //support for the dzip format, common with the speed-demos-archive site
// #define WEBSERVER //http server
#define FTPSERVER //ftp server
#define WEBCLIENT //http clients.
#define RUNTIMELIGHTING //calculate lit/lux files the first time the map is loaded and doesn't have a loadable lit.
// #define QTERM //qterm... adds a console command that allows running programs from within quake - bit like xterm.
#define CL_MASTER //query master servers and stuff for a dynamic server listing.
#define R_XFLIP //allow view to be flipped horizontally
#define TEXTEDITOR
#define IMAGEFMT_KTX //Khronos TeXture. common on gles3 devices for etc2 compression
#define IMAGEFMT_PKM //file format generally written by etcpack or android's etc1tool
#define IMAGEFMT_DDS //a sort of image file format.
#define IMAGEFMT_BLP //a sort of image file format.
#define DECOMPRESS_ETC2 //decompress etc2(core in gles3/gl4.3) if the graphics driver doesn't support it (eg d3d or crappy gpus with vulkan).
// #define DECOMPRESS_S3TC //allows bc1-3 to work even when drivers don't support it. This is probably only an issue on mobile chips. WARNING: not entirely sure if all patents expired yet...
#define DECOMPRESS_RGTC //bc4+bc5
//would be nice to have BPTC decompression too, for gl<4.2, d3d9, or d3d11_level10, but frankly its overcomplicated. I'm not going to bother with ASTC either.
#ifndef RTLIGHTS
#define RTLIGHTS //realtime lighting
#endif
//#define SHADOWDBG_COLOURNOTDEPTH //for debugging. renders shadowmaps to a colour buffer instead of a depth buffer. resulting in projected textures instead of actual shadows (the glsl only picks up the red component, but whatever)
// #define QWOVERQ3 //allows qw servers with q3 clients. requires specific cgame.
#define VM_Q1 //q1 qvm gamecode interface
//#define VM_LUA //q1 lua gamecode interface
#define TCPCONNECT //a tcpconnect command, that allows the player to connect to tcp-encapsulated qw protocols.
// #define IRCCONNECT //an ircconnect command, that allows the player to connect to irc-encapsulated qw protocols... yeah, really.
#define PLUGINS //qvm/dll plugins.
#define SUPPORT_ICE //Interactive Connectivity Establishment protocol, for peer-to-peer connections
#define CSQC_DAT //support for csqc
#define MENU_DAT //support for menu.dat
#define PSET_SCRIPT
#define PSET_CLASSIC
#define HAVE_CDPLAYER //includes cd playback. actual cds. faketracks are supported regardless.
#define HAVE_JUKEBOX //includes built-in jukebox crap
#define HAVE_MEDIA_DECODER //can play cin/roq, more with plugins
#define HAVE_MEDIA_ENCODER //capture/capturedemo work.
#define HAVE_SPEECHTOTEXT //windows speech-to-text thing
#define VOICECHAT
#if defined(_WIN32) && !defined(FTE_SDL) && !defined(MULTITHREAD) //always thread on win32 non-minimal builds
#define MULTITHREAD
#endif
#endif
#ifdef QUAKETC #ifndef MSVCLIBSPATH
#define NOBUILTINMENUS //kill engine menus (should be replaced with ewither csqc or menuqc)
#undef Q2CLIENT //not useful
#undef Q2SERVER //not useful
#undef Q3CLIENT //not useful
#undef Q3SERVER //not useful
#undef HLCLIENT //not useful
#undef HLSERVER //not useful
#undef VM_Q1 //not useful
#undef VM_LUA //not useful
#undef HALFLIFEMODELS //yuck
#undef RUNTIMELIGHTING //presumably not useful
#undef HEXEN2
#endif
#endif
#ifndef MSVCLIBSPATH
#ifdef MSVCLIBPATH #ifdef MSVCLIBPATH
#define MSVCLIBSPATH STRINGIFY(MSVCLIBPATH) #define MSVCLIBSPATH STRINGIFY(MSVCLIBPATH)
#elif _MSC_VER == 1200 #elif _MSC_VER == 1200
@ -356,16 +112,18 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#else #else
#define MSVCLIBSPATH "../libs/" #define MSVCLIBSPATH "../libs/"
#endif #endif
#endif #endif
#if defined(SERVERONLY) && defined(CLIENTONLY) #if defined(SERVERONLY) && defined(CLIENTONLY)
#undef CLIENTONLY //impossible build. assume the config had CLIENTONLY and they tried building a dedicated server #undef CLIENTONLY //impossible build. assume the config had CLIENTONLY and they tried building a dedicated server
#endif #endif
#ifndef CLIENTONLY #ifndef WEBSVONLY
#define HAVE_SERVER #ifndef CLIENTONLY
#endif #define HAVE_SERVER
#ifndef SERVERONLY #endif
#define HAVE_CLIENT #ifndef SERVERONLY
#define HAVE_CLIENT
#endif
#endif #endif
#ifndef HAVE_SERVER #ifndef HAVE_SERVER
@ -796,8 +554,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define IFMINIMAL(x,y) y #define IFMINIMAL(x,y) y
#endif #endif
//#define PRE_SAYONE 2.487 //FIXME: remove.
// defs common to client and server // defs common to client and server
#ifndef PLATFORM #ifndef PLATFORM
@ -863,30 +619,32 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define ARCH_DL_POSTFIX ".so" #define ARCH_DL_POSTFIX ".so"
#endif #endif
#if defined(_M_AMD64) || defined(__amd64__) || defined(__x86_64__) #ifndef ARCH_CPU_POSTFIX
#ifdef __ILP32__ #if defined(_M_AMD64) || defined(__amd64__) || defined(__x86_64__)
#define ARCH_CPU_POSTFIX "x32" //32bit pointers, with 16 registers. #ifdef __ILP32__
#else #define ARCH_CPU_POSTFIX "x32" //32bit pointers, with 16 registers.
#ifdef _WIN32
#define ARCH_CPU_POSTFIX "x64"
#else #else
#define ARCH_CPU_POSTFIX "amd64" #ifdef _WIN32
#define ARCH_CPU_POSTFIX "x64"
#else
#define ARCH_CPU_POSTFIX "amd64"
#endif
#endif
#elif defined(_M_IX86) || defined(__i386__)
#define ARCH_CPU_POSTFIX "x86"
#elif defined(__powerpc__) || defined(__ppc__)
#define ARCH_CPU_POSTFIX "ppc"
#elif defined(__aarch64__)
#define ARCH_CPU_POSTFIX "arm64"
#elif defined(__arm__)
#ifdef __SOFTFP__
#define ARCH_CPU_POSTFIX "arm"
#else
#define ARCH_CPU_POSTFIX "armhf"
#endif #endif
#endif
#elif defined(_M_IX86) || defined(__i386__)
#define ARCH_CPU_POSTFIX "x86"
#elif defined(__powerpc__) || defined(__ppc__)
#define ARCH_CPU_POSTFIX "ppc"
#elif defined(__aarch64__)
#define ARCH_CPU_POSTFIX "arm64"
#elif defined(__arm__)
#ifdef __SOFTFP__
#define ARCH_CPU_POSTFIX "arm"
#else #else
#define ARCH_CPU_POSTFIX "armhf" #define ARCH_CPU_POSTFIX "unk"
#endif #endif
#else
#define ARCH_CPU_POSTFIX "unk"
#endif #endif
#ifdef _MSC_VER #ifdef _MSC_VER

View file

@ -45,9 +45,9 @@ typedef struct cmdalias_s
{ {
struct cmdalias_s *next; struct cmdalias_s *next;
char *value; char *value;
int flags;
qbyte execlevel; qbyte execlevel;
qbyte restriction; qbyte restriction;
int flags;
char name[1]; char name[1];
} cmdalias_t; } cmdalias_t;
@ -4044,11 +4044,12 @@ static void Cmd_Reset_f(void)
// dumps current console contents to a text file // dumps current console contents to a text file
static void Cmd_Condump_f(void) static void Cmd_Condump_f(void)
{ {
console_t *c = Con_GetMain();
vfsfile_t *f; vfsfile_t *f;
char *filename; char *filename;
char line[8192]; char line[8192];
if (!con_current) if (!c)
{ {
Con_Printf ("No console to dump.\n"); Con_Printf ("No console to dump.\n");
return; return;
@ -4074,13 +4075,12 @@ static void Cmd_Condump_f(void)
// print out current contents of console // print out current contents of console
// stripping out starting blank lines and blank spaces // stripping out starting blank lines and blank spaces
{ {
console_t *curcon = &con_main;
conline_t *l; conline_t *l;
conchar_t *t; conchar_t *t;
for (l = curcon->oldest; l; l = l->newer) for (l = c->oldest; l; l = l->newer)
{ {
t = (conchar_t*)(l+1); t = (conchar_t*)(l+1);
COM_DeFunString(t, t + l->length, line, sizeof(line), true, !!(curcon->parseflags & PFS_FORCEUTF8)); COM_DeFunString(t, t + l->length, line, sizeof(line), true, !!(c->parseflags & PFS_FORCEUTF8));
VFS_WRITE(f, line, strlen(line)); VFS_WRITE(f, line, strlen(line));
VFS_WRITE(f, "\n", 1); VFS_WRITE(f, "\n", 1);
} }

View file

@ -148,6 +148,7 @@ char *Cmd_AliasExist(const char *name, int restrictionlevel);
void Alias_WipeStuffedAliases(void); void Alias_WipeStuffedAliases(void);
void Cmd_AddMacro(char *s, char *(*f)(void), int disputableintentions); void Cmd_AddMacro(char *s, char *(*f)(void), int disputableintentions);
#define Cmd_AddMacroD(s,f,unsafe,desc) Cmd_AddMacro(s,f,unsafe)
void Cmd_TokenizePunctation (char *text, char *punctuation); void Cmd_TokenizePunctation (char *text, char *punctuation);
const char *Cmd_TokenizeString (const char *text, qboolean expandmacros, qboolean qctokenize); const char *Cmd_TokenizeString (const char *text, qboolean expandmacros, qboolean qctokenize);

View file

@ -33,7 +33,7 @@ cvar_t r_meshpitch = CVARCD ("r_meshpitch", "1", r_meshpitch_callback, "Sp
cvar_t r_meshpitch = CVARCD ("r_meshpitch", "-1", r_meshpitch_callback, "Specifies the direction of the pitch angle on mesh models formats, Quake compatibility requires -1."); cvar_t r_meshpitch = CVARCD ("r_meshpitch", "-1", r_meshpitch_callback, "Specifies the direction of the pitch angle on mesh models formats, Quake compatibility requires -1.");
#endif #endif
#ifndef SERVERONLY #ifdef HAVE_CLIENT
static void Mod_UpdateCRC(void *ctx, void *data, size_t a, size_t b) static void Mod_UpdateCRC(void *ctx, void *data, size_t a, size_t b)
{ {
char st[40]; char st[40];
@ -50,7 +50,7 @@ static void Mod_UpdateCRC(void *ctx, void *data, size_t a, size_t b)
//Common loader function. //Common loader function.
void Mod_DoCRC(model_t *mod, char *buffer, int buffersize) void Mod_DoCRC(model_t *mod, char *buffer, int buffersize)
{ {
#ifndef SERVERONLY #ifdef HAVE_CLIENT
//we've got to have this bit //we've got to have this bit
if (mod->engineflags & MDLF_DOCRC) if (mod->engineflags & MDLF_DOCRC)
{ {
@ -78,7 +78,7 @@ extern cvar_t r_skin_overlays;
extern cvar_t mod_md3flags; extern cvar_t mod_md3flags;
#ifdef HAVE_CLIENT
typedef struct typedef struct
{ {
char *name; char *name;
@ -88,7 +88,7 @@ typedef struct
//these should be rounded up slightly. //these should be rounded up slightly.
//really this is only to catch spiked models. This doesn't prevent more visible models, just bigger ones. //really this is only to catch spiked models. This doesn't prevent more visible models, just bigger ones.
clampedmodel_t clampedmodel[] = { static clampedmodel_t clampedmodel[] = {
{"maps/b_bh100.bsp", 3440}, {"maps/b_bh100.bsp", 3440},
{"progs/player.mdl", 22497}, {"progs/player.mdl", 22497},
{"progs/eyes.mdl", 755}, {"progs/eyes.mdl", 755},
@ -129,7 +129,7 @@ clampedmodel_t clampedmodel[] = {
{"progs/turrbase.mdl", 3000}, {"progs/turrbase.mdl", 3000},
{"progs/turrgun.mdl", 3000} {"progs/turrgun.mdl", 3000}
}; };
#endif
@ -240,7 +240,7 @@ void Mod_NormaliseTextureVectors(vec3_t *n, vec3_t *s, vec3_t *t, int v, qboolea
#ifdef SKELETALMODELS #ifdef SKELETALMODELS
/*like above, but guess the quat.w*/ /*like above, but guess the quat.w*/
static void GenMatrixPosQuat3Scale(vec3_t pos, vec3_t quat3, vec3_t scale, float result[12]) static void GenMatrixPosQuat3Scale(vec3_t const pos, vec3_t const quat3, vec3_t const scale, float result[12])
{ {
vec4_t quat4; vec4_t quat4;
float term = 1 - DotProduct(quat3, quat3); float term = 1 - DotProduct(quat3, quat3);
@ -581,7 +581,7 @@ static const float *Alias_ConvertBoneData(skeltype_t sourcetype, const float *so
for (i = 0; i < bonecount; i++) for (i = 0; i < bonecount; i++)
{ {
if (bones[i].parent >= 0) if (bones[i].parent >= 0)
R_ConcatTransforms((void*)(dest + bones[i].parent*12), (void*)(sourcedata+i*12), (void*)(dest+i*12)); R_ConcatTransforms((void*)(dest + bones[i].parent*12), (const void*)(sourcedata+i*12), (void*)(dest+i*12));
else else
{ {
Vector4Copy(sourcedata+i*12+0, dest+i*12+0); Vector4Copy(sourcedata+i*12+0, dest+i*12+0);
@ -605,7 +605,7 @@ static const float *Alias_ConvertBoneData(skeltype_t sourcetype, const float *so
for (i = 0; i < bonecount; i++) for (i = 0; i < bonecount; i++)
{ {
Matrix3x4_Invert_Simple(bones[i].inverse, iim); Matrix3x4_Invert_Simple(bones[i].inverse, iim);
R_ConcatTransforms((void*)(sourcedata + i*12), (void*)iim, (void*)(dest + i*12)); R_ConcatTransforms((const void*)(sourcedata + i*12), (const void*)iim, (void*)(dest + i*12));
} }
sourcedata = dest; sourcedata = dest;
sourcetype = SKEL_ABSOLUTE; sourcetype = SKEL_ABSOLUTE;
@ -623,7 +623,7 @@ static const float *Alias_ConvertBoneData(skeltype_t sourcetype, const float *so
if (bones[i].parent >= 0) if (bones[i].parent >= 0)
{ {
Matrix3x4_Invert_Simple(sourcedata+bones[i].parent*12, ip); Matrix3x4_Invert_Simple(sourcedata+bones[i].parent*12, ip);
R_ConcatTransforms((void*)ip, (void*)(sourcedata+i*12), (void*)(dest+i*12)); R_ConcatTransforms((void*)ip, (const void*)(sourcedata+i*12), (void*)(dest+i*12));
} }
else else
{ {
@ -644,7 +644,7 @@ static const float *Alias_ConvertBoneData(skeltype_t sourcetype, const float *so
{ {
float *dest = (sourcedata == destbuffer)?destbufferalt:destbuffer; float *dest = (sourcedata == destbuffer)?destbufferalt:destbuffer;
for (i = 0; i < bonecount; i++) for (i = 0; i < bonecount; i++)
R_ConcatTransforms((void*)(sourcedata + i*12), (void*)(bones[i].inverse), (void*)(dest + i*12)); R_ConcatTransforms((const void*)(sourcedata + i*12), (void*)(bones[i].inverse), (void*)(dest + i*12));
sourcedata = dest; sourcedata = dest;
sourcetype = SKEL_INVERSE_ABSOLUTE; sourcetype = SKEL_INVERSE_ABSOLUTE;
} }
@ -1002,9 +1002,9 @@ typedef struct
skeltype_t skeltype; //the skeletal type of this bone block. all blocks should have the same result or the whole thing is unusable or whatever. skeltype_t skeltype; //the skeletal type of this bone block. all blocks should have the same result or the whole thing is unusable or whatever.
int firstbone; //first bone of interest int firstbone; //first bone of interest
int endbone; //the first bone of the next group (ie: if first is 0, this is the count) int endbone; //the first bone of the next group (ie: if first is 0, this is the count)
int lerpcount; //number of pose+frac entries.
float frac[FRAME_BLENDS*2]; //weight of this animation (1 if lerpcount is 1) float frac[FRAME_BLENDS*2]; //weight of this animation (1 if lerpcount is 1)
float *pose[FRAME_BLENDS*2]; //pointer to the raw frame data for bone 0. float *pose[FRAME_BLENDS*2]; //pointer to the raw frame data for bone 0.
int lerpcount; //number of pose+frac entries.
} skellerps_t; } skellerps_t;
static qboolean Alias_BuildSkelLerps(skellerps_t *lerps, struct framestateregion_s *fs, int numbones, galiasinfo_t *inf) static qboolean Alias_BuildSkelLerps(skellerps_t *lerps, struct framestateregion_s *fs, int numbones, galiasinfo_t *inf)
{ {
@ -1470,7 +1470,7 @@ static void Alias_BuildGPUWeights(model_t *mod, galiasinfo_t *inf, size_t num_tr
#endif #endif
#ifndef SERVERONLY #ifndef SERVERONLY
static void Alias_DrawSkeletalBones(galiasbone_t *bones, float *bonepose, int bonecount, int basebone) static void Alias_DrawSkeletalBones(galiasbone_t *bones, float const*bonepose, int bonecount, int basebone)
{ {
scenetris_t *t; scenetris_t *t;
int flags = BEF_NODLIGHT|BEF_NOSHADOWS|BEF_LINES; int flags = BEF_NODLIGHT|BEF_NOSHADOWS|BEF_LINES;
@ -1788,7 +1788,7 @@ qboolean Alias_GAliasBuildMesh(mesh_t *mesh, vbo_t **vbop, galiasinfo_t *inf, in
meshcache.usebonepose = Alias_GetBoneInformation(inf, &e->framestate, meshcache.bonecachetype=SKEL_ABSOLUTE, meshcache.boneposebuffer1, meshcache.boneposebuffer2, MAX_BONES); meshcache.usebonepose = Alias_GetBoneInformation(inf, &e->framestate, meshcache.bonecachetype=SKEL_ABSOLUTE, meshcache.boneposebuffer1, meshcache.boneposebuffer2, MAX_BONES);
#ifndef SERVERONLY #ifndef SERVERONLY
if (inf->shares_bones != surfnum && qrenderer) if (inf->shares_bones != surfnum && qrenderer)
Alias_DrawSkeletalBones(inf->ofsbones, (float *)meshcache.usebonepose, inf->numbones, e->framestate.g[0].endbone); Alias_DrawSkeletalBones(inf->ofsbones, (const float *)meshcache.usebonepose, inf->numbones, e->framestate.g[0].endbone);
#endif #endif
} }
} }
@ -3104,7 +3104,7 @@ static void Q1MDL_LoadPose(galiasinfo_t *galias, dmdl_t *pq1inmodel, vecV_t *ver
} }
} }
} }
static void Q1MDL_LoadPose16(galiasinfo_t *galias, dmdl_t *pq1inmodel, vecV_t *verts, vec3_t *normals, vec3_t *svec, vec3_t *tvec, dtrivertx_t *pinframe, int *seamremaps, int mdltype) static void Q1MDL_LoadPoseQF16(galiasinfo_t *galias, dmdl_t *pq1inmodel, vecV_t *verts, vec3_t *normals, vec3_t *svec, vec3_t *tvec, dtrivertx_t *pinframe, int *seamremaps, int mdltype)
{ {
//quakeforge's MD16 format has regular 8bit stuff, trailed by an extra low-order set of the verts providing the extra 8bits of precision. //quakeforge's MD16 format has regular 8bit stuff, trailed by an extra low-order set of the verts providing the extra 8bits of precision.
//its worth noting that the model could be rendered using the high-order parts only, if your software renderer only supports that or whatever. //its worth noting that the model could be rendered using the high-order parts only, if your software renderer only supports that or whatever.
@ -3186,24 +3186,24 @@ static void *Q1MDL_LoadFrameGroup (galiasinfo_t *galias, dmdl_t *pq1inmodel, mod
if (mdltype & 16) if (mdltype & 16)
{ {
Q1MDL_LoadPose16(galias, pq1inmodel, verts, normals, svec, tvec, pinframe, seamremaps, mdltype); Q1MDL_LoadPoseQF16(galias, pq1inmodel, verts, normals, svec, tvec, pinframe, seamremaps, mdltype);
pframetype = (daliasframetype_t *)&pinframe[pq1inmodel->numverts*2]; pframetype = (daliasframetype_t *)&pinframe[pq1inmodel->numverts*2];
} }
else else
{ {
Q1MDL_LoadPose(galias, pq1inmodel, verts, normals, svec, tvec, pinframe, seamremaps, mdltype, bbox); Q1MDL_LoadPose(galias, pq1inmodel, verts, normals, svec, tvec, pinframe, seamremaps, mdltype, bbox);
pframetype = (daliasframetype_t *)&pinframe[pq1inmodel->numverts]; pframetype = (daliasframetype_t *)&pinframe[pq1inmodel->numverts];
}
#ifdef _DEBUG #ifdef _DEBUG
if ((bbox[3] > frameinfo->bboxmax.v[0] || bbox[4] > frameinfo->bboxmax.v[1] || bbox[5] > frameinfo->bboxmax.v[2] || if ((bbox[3] > frameinfo->bboxmax.v[0] || bbox[4] > frameinfo->bboxmax.v[1] || bbox[5] > frameinfo->bboxmax.v[2] ||
bbox[0] < frameinfo->bboxmin.v[0] || bbox[1] < frameinfo->bboxmin.v[1] || bbox[2] < frameinfo->bboxmin.v[2]) && !galias->warned) bbox[0] < frameinfo->bboxmin.v[0] || bbox[1] < frameinfo->bboxmin.v[1] || bbox[2] < frameinfo->bboxmin.v[2]) && !galias->warned)
#else #else
if (galias->numverts && pinframe[0].v[2] > frameinfo->bboxmax.v[2] && !galias->warned) if (galias->numverts && pinframe[0].v[2] > frameinfo->bboxmax.v[2] && !galias->warned)
#endif #endif
{ {
Con_DPrintf(CON_WARNING"%s has incorrect frame bounds\n", loadmodel->name); Con_DPrintf(CON_WARNING"%s has incorrect frame bounds\n", loadmodel->name);
galias->warned = true; galias->warned = true;
}
} }
@ -3260,26 +3260,26 @@ static void *Q1MDL_LoadFrameGroup (galiasinfo_t *galias, dmdl_t *pq1inmodel, mod
if (mdltype & 16) if (mdltype & 16)
{ {
Q1MDL_LoadPose16(galias, pq1inmodel, verts, normals, svec, tvec, pinframe, seamremaps, mdltype); Q1MDL_LoadPoseQF16(galias, pq1inmodel, verts, normals, svec, tvec, pinframe, seamremaps, mdltype);
pinframe += pq1inmodel->numverts*2; pinframe += pq1inmodel->numverts*2;
} }
else else
{ {
Q1MDL_LoadPose(galias, pq1inmodel, verts, normals, svec, tvec, pinframe, seamremaps, mdltype, bbox); Q1MDL_LoadPose(galias, pq1inmodel, verts, normals, svec, tvec, pinframe, seamremaps, mdltype, bbox);
pinframe += pq1inmodel->numverts; pinframe += pq1inmodel->numverts;
}
#ifdef _DEBUG #ifdef _DEBUG
if ((bbox[3] > frameinfo->bboxmax.v[0] || bbox[4] > frameinfo->bboxmax.v[1] || bbox[5] > frameinfo->bboxmax.v[2] || if ((bbox[3] > frameinfo->bboxmax.v[0] || bbox[4] > frameinfo->bboxmax.v[1] || bbox[5] > frameinfo->bboxmax.v[2] ||
bbox[0] < frameinfo->bboxmin.v[0] || bbox[1] < frameinfo->bboxmin.v[1] || bbox[2] < frameinfo->bboxmin.v[2] || bbox[0] < frameinfo->bboxmin.v[0] || bbox[1] < frameinfo->bboxmin.v[1] || bbox[2] < frameinfo->bboxmin.v[2] ||
#else #else
if (galias->numverts && (pinframe[0].v[2] > frameinfo->bboxmax.v[2] || if (galias->numverts && (pinframe[0].v[2] > frameinfo->bboxmax.v[2] ||
#endif #endif
frameinfo->bboxmin.v[0] < ingroup->bboxmin.v[0] || frameinfo->bboxmin.v[1] < ingroup->bboxmin.v[1] || frameinfo->bboxmin.v[2] < ingroup->bboxmin.v[2] || frameinfo->bboxmin.v[0] < ingroup->bboxmin.v[0] || frameinfo->bboxmin.v[1] < ingroup->bboxmin.v[1] || frameinfo->bboxmin.v[2] < ingroup->bboxmin.v[2] ||
frameinfo->bboxmax.v[0] > ingroup->bboxmax.v[0] || frameinfo->bboxmax.v[1] > ingroup->bboxmax.v[1] || frameinfo->bboxmax.v[2] > ingroup->bboxmax.v[2]) && !galias->warned) frameinfo->bboxmax.v[0] > ingroup->bboxmax.v[0] || frameinfo->bboxmax.v[1] > ingroup->bboxmax.v[1] || frameinfo->bboxmax.v[2] > ingroup->bboxmax.v[2]) && !galias->warned)
{ {
Con_DPrintf(CON_WARNING"%s has incorrect frame bounds\n", loadmodel->name); Con_DPrintf(CON_WARNING"%s has incorrect frame bounds\n", loadmodel->name);
galias->warned = true; galias->warned = true;
}
} }
#ifndef SERVERONLY #ifndef SERVERONLY
@ -6899,7 +6899,7 @@ galisskeletaltransforms_t *IQM_ImportTransforms(int *resultcount, int inverts, f
} }
*/ */
static qboolean IQM_ImportArray4B(const qbyte *base, const struct iqmvertexarray *src, byte_vec4_t *out, size_t count, unsigned int maxval) static qboolean IQM_ImportArray4B(const qbyte *fte_restrict base, const struct iqmvertexarray *fte_restrict src, byte_vec4_t *fte_restrict out, size_t count, unsigned int maxval)
{ {
size_t i; size_t i;
unsigned int j; unsigned int j;
@ -6922,7 +6922,7 @@ static qboolean IQM_ImportArray4B(const qbyte *base, const struct iqmvertexarray
case IQM_BYTE: //FIXME: should be signed, but this makes no sense for our uses case IQM_BYTE: //FIXME: should be signed, but this makes no sense for our uses
case IQM_UBYTE: case IQM_UBYTE:
{ {
qbyte *in = (qbyte*)(base+offset); const qbyte *in = (const qbyte*)(base+offset);
/*if (sz == 4) /*if (sz == 4)
memcpy(out, in, count * sizeof(*out)); //the fast path. memcpy(out, in, count * sizeof(*out)); //the fast path.
else*/ for (i = 0; i < count; i++) else*/ for (i = 0; i < count; i++)
@ -6943,7 +6943,7 @@ static qboolean IQM_ImportArray4B(const qbyte *base, const struct iqmvertexarray
case IQM_SHORT://FIXME: should be signed, but this makes no sense for our uses case IQM_SHORT://FIXME: should be signed, but this makes no sense for our uses
case IQM_USHORT: case IQM_USHORT:
{ {
unsigned short *in = (unsigned short*)(base+offset); const unsigned short *in = (const unsigned short*)(base+offset);
for (i = 0; i < count; i++) for (i = 0; i < count; i++)
{ {
for (j = 0; j < 4 && j < sz; j++) for (j = 0; j < 4 && j < sz; j++)
@ -6962,7 +6962,7 @@ static qboolean IQM_ImportArray4B(const qbyte *base, const struct iqmvertexarray
case IQM_INT://FIXME: should be signed, but this makes no sense for our uses case IQM_INT://FIXME: should be signed, but this makes no sense for our uses
case IQM_UINT: case IQM_UINT:
{ {
unsigned int *in = (unsigned int*)(base+offset); const unsigned int *in = (const unsigned int*)(base+offset);
for (i = 0; i < count; i++) for (i = 0; i < count; i++)
{ {
for (j = 0; j < 4 && j < sz; j++) for (j = 0; j < 4 && j < sz; j++)
@ -6993,7 +6993,7 @@ static qboolean IQM_ImportArray4B(const qbyte *base, const struct iqmvertexarray
return !invalid; return !invalid;
} }
static void IQM_ImportArrayF(const qbyte *base, const struct iqmvertexarray *src, float *out, size_t e, size_t count, float *def) static void IQM_ImportArrayF(const qbyte *fte_restrict base, const struct iqmvertexarray *fte_restrict src, float *fte_restrict out, size_t e, size_t count, float *def)
{ {
size_t i; size_t i;
unsigned int j; unsigned int j;
@ -7012,7 +7012,7 @@ static void IQM_ImportArrayF(const qbyte *base, const struct iqmvertexarray *src
break; break;
case IQM_BYTE: //negatives not handled properly case IQM_BYTE: //negatives not handled properly
{ {
signed char *in = (signed char*)(base+offset); const signed char *in = (const signed char*)(base+offset);
for (i = 0; i < count; i++) for (i = 0; i < count; i++)
{ {
for (j = 0; j < e && j < sz; j++) for (j = 0; j < e && j < sz; j++)
@ -7022,7 +7022,7 @@ static void IQM_ImportArrayF(const qbyte *base, const struct iqmvertexarray *src
break; break;
case IQM_UBYTE: case IQM_UBYTE:
{ {
qbyte *in = (qbyte*)(base+offset); const qbyte *in = (const qbyte*)(base+offset);
for (i = 0; i < count; i++) for (i = 0; i < count; i++)
{ {
for (j = 0; j < e && j < sz; j++) for (j = 0; j < e && j < sz; j++)
@ -7032,7 +7032,7 @@ static void IQM_ImportArrayF(const qbyte *base, const struct iqmvertexarray *src
break; break;
case IQM_SHORT: //negatives not handled properly case IQM_SHORT: //negatives not handled properly
{ {
signed short *in = (signed short*)(base+offset); const signed short *in = (const signed short*)(base+offset);
for (i = 0; i < count; i++) for (i = 0; i < count; i++)
{ {
for (j = 0; j < e && j < sz; j++) for (j = 0; j < e && j < sz; j++)
@ -7042,7 +7042,7 @@ static void IQM_ImportArrayF(const qbyte *base, const struct iqmvertexarray *src
break; break;
case IQM_USHORT: case IQM_USHORT:
{ {
unsigned short *in = (unsigned short*)(base+offset); const unsigned short *in = (const unsigned short*)(base+offset);
for (i = 0; i < count; i++) for (i = 0; i < count; i++)
{ {
for (j = 0; j < e && j < sz; j++) for (j = 0; j < e && j < sz; j++)
@ -7052,7 +7052,7 @@ static void IQM_ImportArrayF(const qbyte *base, const struct iqmvertexarray *src
break; break;
case IQM_INT: //negatives not handled properly case IQM_INT: //negatives not handled properly
{ {
signed int *in = (signed int*)(base+offset); const signed int *in = (const signed int*)(base+offset);
for (i = 0; i < count; i++) for (i = 0; i < count; i++)
{ {
for (j = 0; j < e && j < sz; j++) for (j = 0; j < e && j < sz; j++)
@ -7062,7 +7062,7 @@ static void IQM_ImportArrayF(const qbyte *base, const struct iqmvertexarray *src
break; break;
case IQM_UINT: case IQM_UINT:
{ {
unsigned int *in = (unsigned int*)(base+offset); const unsigned int *in = (const unsigned int*)(base+offset);
for (i = 0; i < count; i++) for (i = 0; i < count; i++)
{ {
for (j = 0; j < e && j < sz; j++) for (j = 0; j < e && j < sz; j++)
@ -7074,7 +7074,7 @@ static void IQM_ImportArrayF(const qbyte *base, const struct iqmvertexarray *src
case IQM_HALF: case IQM_HALF:
#ifdef __F16C__ #ifdef __F16C__
{ //x86 intrinsics { //x86 intrinsics
unsigned short *in = (qbyte*)(base+offset); const unsigned short *in = (const qbyte*)(base+offset);
for (i = 0; i < count; i++) for (i = 0; i < count; i++)
{ {
for (j = 0; j < e && j < sz; j++) for (j = 0; j < e && j < sz; j++)
@ -7083,7 +7083,7 @@ static void IQM_ImportArrayF(const qbyte *base, const struct iqmvertexarray *src
} }
#elif 0 #elif 0
{ {
_Float16 *in = (qbyte*)(base+offset); const _Float16 *in = (const _Float16*)(base+offset);
for (i = 0; i < count; i++) for (i = 0; i < count; i++)
{ {
for (j = 0; j < e && j < sz; j++) for (j = 0; j < e && j < sz; j++)
@ -7096,7 +7096,7 @@ static void IQM_ImportArrayF(const qbyte *base, const struct iqmvertexarray *src
break; break;
case IQM_FLOAT: case IQM_FLOAT:
{ {
float *in = (float*)(base+offset); const float *in = (const float*)(base+offset);
if (e == sz) if (e == sz)
memcpy(out, in, e * sizeof(float) * count); memcpy(out, in, e * sizeof(float) * count);
else for (i = 0; i < count; i++) else for (i = 0; i < count; i++)
@ -7108,7 +7108,7 @@ static void IQM_ImportArrayF(const qbyte *base, const struct iqmvertexarray *src
break; break;
case IQM_DOUBLE: case IQM_DOUBLE:
{ {
double *in = (double*)(base+offset); const double *in = (const double*)(base+offset);
for (i = 0; i < count; i++) for (i = 0; i < count; i++)
{ {
for (j = 0; j < e && j < sz; j++) for (j = 0; j < e && j < sz; j++)
@ -7131,13 +7131,13 @@ static void IQM_ImportArrayF(const qbyte *base, const struct iqmvertexarray *src
static const void *IQM_FindExtension(const char *buffer, size_t buffersize, const char *extname, int index, size_t *extsize) static const void *IQM_FindExtension(const char *buffer, size_t buffersize, const char *extname, int index, size_t *extsize)
{ {
struct iqmheader *h = (struct iqmheader *)buffer; const struct iqmheader *h = (const struct iqmheader *)buffer;
const char *strings = buffer + h->ofs_text; const char *strings = buffer + h->ofs_text;
struct iqmextension *ext; const struct iqmextension *ext;
int i; int i;
for (i = 0, ext = (struct iqmextension*)(buffer + h->ofs_extensions); i < h->num_extensions; i++, ext = (struct iqmextension*)(buffer + ext->ofs_extensions)) for (i = 0, ext = (const struct iqmextension*)(buffer + h->ofs_extensions); i < h->num_extensions; i++, ext = (const struct iqmextension*)(buffer + ext->ofs_extensions))
{ {
if ((char*)ext > buffer+buffersize || ext->name > h->num_text || ext->ofs_data+ext->num_data>buffersize) if ((const char*)ext > buffer+buffersize || ext->name > h->num_text || ext->ofs_data+ext->num_data>buffersize)
break; break;
if (!Q_strcasecmp(strings + ext->name, extname) && index-->=0) if (!Q_strcasecmp(strings + ext->name, extname) && index-->=0)
{ {
@ -7185,7 +7185,7 @@ static void Mod_CleanWeights(const char *modelname, size_t numverts, vec4_t *owe
static galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, const char *buffer, size_t fsize) static galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, const char *buffer, size_t fsize)
{ {
const struct iqmheader *h = (struct iqmheader *)buffer; const struct iqmheader *h = (const struct iqmheader *)buffer;
const struct iqmmesh *mesh; const struct iqmmesh *mesh;
const struct iqmvertexarray *varray; const struct iqmvertexarray *varray;
const struct iqmtriangle *tris; const struct iqmtriangle *tris;
@ -7197,15 +7197,15 @@ static galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, const char *buffer, siz
unsigned int i, j, t, numtris, numverts, firstvert, firsttri; unsigned int i, j, t, numtris, numverts, firstvert, firsttri;
size_t extsize; size_t extsize;
float *vtang = NULL; const float *vtang = NULL;
struct iqmvertexarray vpos = {0}, vnorm = {0}, vtcoord = {0}, vbone = {0}, vweight = {0}, vrgba = {0}; struct iqmvertexarray vpos = {0}, vnorm = {0}, vtcoord = {0}, vbone = {0}, vweight = {0}, vrgba = {0};
unsigned int type, fmt, size, offset; unsigned int type, fmt, size, offset;
unsigned short *framedata; const unsigned short *framedata;
vec4_t defaultcolour = {1,1,1,1}; vec4_t defaultcolour = {1,1,1,1};
vec4_t defaultweight = {0,0,0,0}; vec4_t defaultweight = {0,0,0,0};
vec4_t defaultvert = {0,0,0,1}; vec4_t defaultvert = {0,0,0,1};
struct iqmbounds *inbounds; const struct iqmbounds *inbounds;
int memsize; int memsize;
qbyte *obase=NULL; qbyte *obase=NULL;
@ -7249,7 +7249,7 @@ static galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, const char *buffer, siz
return NULL; return NULL;
} }
varray = (struct iqmvertexarray*)(buffer + h->ofs_vertexarrays); varray = (const struct iqmvertexarray*)(buffer + h->ofs_vertexarrays);
for (i = 0; i < h->num_vertexarrays; i++) for (i = 0; i < h->num_vertexarrays; i++)
{ {
type = LittleLong(varray[i].type); type = LittleLong(varray[i].type);
@ -7263,7 +7263,7 @@ static galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, const char *buffer, siz
else if (type == IQM_NORMAL) else if (type == IQM_NORMAL)
vnorm = varray[i]; vnorm = varray[i];
else if (type == IQM_TANGENT && fmt == IQM_FLOAT && size == 4) /*yup, 4, extra is side, for the bitangent*/ else if (type == IQM_TANGENT && fmt == IQM_FLOAT && size == 4) /*yup, 4, extra is side, for the bitangent*/
vtang = (float*)(buffer + offset); vtang = (const float*)(buffer + offset);
else if (type == IQM_BLENDINDEXES) else if (type == IQM_BLENDINDEXES)
vbone = varray[i]; vbone = varray[i];
else if (type == IQM_BLENDWEIGHTS) else if (type == IQM_BLENDWEIGHTS)
@ -7340,7 +7340,7 @@ static galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, const char *buffer, siz
numgroups = h->num_anims; numgroups = h->num_anims;
framegroups = malloc(sizeof(*framegroups)*numgroups); framegroups = malloc(sizeof(*framegroups)*numgroups);
anim = (struct iqmanim*)(buffer + h->ofs_anims); anim = (const struct iqmanim*)(buffer + h->ofs_anims);
for (i = 0; i < numgroups; i++) for (i = 0; i < numgroups; i++)
{ {
framegroups[i].firstpose = LittleLong(anim[i].first_frame); framegroups[i].firstpose = LittleLong(anim[i].first_frame);
@ -7363,7 +7363,7 @@ static galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, const char *buffer, siz
strcpy(framegroups->name, "base"); strcpy(framegroups->name, "base");
} }
mesh = (struct iqmmesh*)(buffer + h->ofs_meshes); mesh = (const struct iqmmesh*)(buffer + h->ofs_meshes);
#ifndef SERVERONLY #ifndef SERVERONLY
skinfiles = Mod_CountSkinFiles(mod); skinfiles = Mod_CountSkinFiles(mod);
@ -7414,13 +7414,13 @@ static galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, const char *buffer, siz
#undef dalloc #undef dalloc
//no code to load animations or bones //no code to load animations or bones
framedata = (unsigned short*)(buffer + h->ofs_frames); framedata = (const unsigned short*)(buffer + h->ofs_frames);
/*Version 1 supports only normalized quaternions, version 2 uses complete quaternions. Some struct sizes change for this, otherwise functionally identical.*/ /*Version 1 supports only normalized quaternions, version 2 uses complete quaternions. Some struct sizes change for this, otherwise functionally identical.*/
if (h->version == IQM_VERSION1) if (h->version == IQM_VERSION1)
{ {
struct iqmpose1 *p, *ipose = (struct iqmpose1*)(buffer + h->ofs_poses); const struct iqmpose1 *p, *ipose = (const struct iqmpose1*)(buffer + h->ofs_poses);
struct iqmjoint1 *ijoint = (struct iqmjoint1*)(buffer + h->ofs_joints); const struct iqmjoint1 *ijoint = (const struct iqmjoint1*)(buffer + h->ofs_joints);
vec3_t pos; vec3_t pos;
vec4_t quat; vec4_t quat;
vec3_t scale; vec3_t scale;
@ -7464,8 +7464,8 @@ static galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, const char *buffer, siz
} }
else else
{ {
struct iqmpose2 *p, *ipose = (struct iqmpose2*)(buffer + h->ofs_poses); const struct iqmpose2 *p, *ipose = (const struct iqmpose2*)(buffer + h->ofs_poses);
struct iqmjoint2 *ijoint = (struct iqmjoint2*)(buffer + h->ofs_joints); const struct iqmjoint2 *ijoint = (const struct iqmjoint2*)(buffer + h->ofs_joints);
vec3_t pos; vec3_t pos;
vec4_t quat; vec4_t quat;
vec3_t scale; vec3_t scale;
@ -7564,7 +7564,7 @@ static galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, const char *buffer, siz
} }
//determine the bounds //determine the bounds
inbounds = (struct iqmbounds*)(buffer + h->ofs_bounds); inbounds = (const struct iqmbounds*)(buffer + h->ofs_bounds);
if (h->ofs_bounds) if (h->ofs_bounds)
{ {
for (i = 0; i < h->num_frames; i++) for (i = 0; i < h->num_frames; i++)
@ -7642,7 +7642,7 @@ static galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, const char *buffer, siz
} }
#endif #endif
tris = (struct iqmtriangle*)(buffer + LittleLong(h->ofs_triangles)); tris = (const struct iqmtriangle*)(buffer + LittleLong(h->ofs_triangles));
tris += firsttri; tris += firsttri;
gai[i].numindexes = numtris*3; gai[i].numindexes = numtris*3;
idx = ZG_Malloc(&mod->memgroup, sizeof(*idx)*gai[i].numindexes); idx = ZG_Malloc(&mod->memgroup, sizeof(*idx)*gai[i].numindexes);

View file

@ -218,7 +218,7 @@ typedef struct modplugfuncs_s
void *(QDECL *ZG_Malloc)(zonegroup_t *ctx, int size); //ctx=&mod->memgroup and the data will be freed when the model is freed. void *(QDECL *ZG_Malloc)(zonegroup_t *ctx, int size); //ctx=&mod->memgroup and the data will be freed when the model is freed.
void (QDECL *ConcatTransforms) (float in1[3][4], float in2[3][4], float out[3][4]); void (QDECL *ConcatTransforms) (const float in1[3][4], const float in2[3][4], float out[3][4]);
void (QDECL *M3x4_Invert) (const float *in1, float *out); void (QDECL *M3x4_Invert) (const float *in1, float *out);
void (QDECL *VectorAngles)(float *forward, float *up, float *result, qboolean meshpitch); void (QDECL *VectorAngles)(float *forward, float *up, float *result, qboolean meshpitch);
void (QDECL *AngleVectors)(const vec3_t angles, vec3_t forward, vec3_t right, vec3_t up); void (QDECL *AngleVectors)(const vec3_t angles, vec3_t forward, vec3_t right, vec3_t up);

View file

@ -84,7 +84,7 @@ glibc SUCKS. 64bit glibc is depending upon glibc 2.14 because of some implementa
or something. or something.
anyway, the actual interface is the same. the old version might be slower, but when updating glibc generally results in also installing systemd, requiring the new version is NOT an option. anyway, the actual interface is the same. the old version might be slower, but when updating glibc generally results in also installing systemd, requiring the new version is NOT an option.
*/ */
#if defined(__GNUC__) && defined(__LP64__) && defined(__linux__) && !defined(FTE_SDL) #if defined(__GNUC__) && defined(__amd64__) && defined(__linux__) && !defined(FTE_SDL)
#include <features.h> /* for glibc version */ #include <features.h> /* for glibc version */
#if defined(__GLIBC__) && (__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 14) #if defined(__GLIBC__) && (__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 14)
__asm__(".symver memcpy,memcpy@GLIBC_2.2.5"); __asm__(".symver memcpy,memcpy@GLIBC_2.2.5");
@ -4790,7 +4790,7 @@ static void COM_Version_f (void)
{ {
Con_Printf("\n"); Con_Printf("\n");
Con_Printf("^&F0%s\n", FULLENGINENAME); Con_Printf("^&F0%s\n", FULLENGINENAME);
Con_Printf("%s\n", ENGINEWEBSITE); Con_Printf("^[%s\\url\\%s^]\n", ENGINEWEBSITE, ENGINEWEBSITE);
Con_Printf("%s\n", version_string()); Con_Printf("%s\n", version_string());
Con_TPrintf ("Exe: %s %s\n", __DATE__, __TIME__); Con_TPrintf ("Exe: %s %s\n", __DATE__, __TIME__);
@ -4799,7 +4799,7 @@ static void COM_Version_f (void)
Con_Printf("SVN Revision: %s\n",STRINGIFY(SVNREVISION)); Con_Printf("SVN Revision: %s\n",STRINGIFY(SVNREVISION));
#endif #endif
#ifdef CONFIG_FILE_NAME #ifdef CONFIG_FILE_NAME
Con_Printf("Build config: %s\n\n", STRINGIFY(CONFIG_FILE_NAME)); Con_Printf("Build config: %s\n\n", COM_SkipPath(STRINGIFY(CONFIG_FILE_NAME)));
#endif #endif
#ifdef _DEBUG #ifdef _DEBUG
@ -5150,8 +5150,8 @@ static void COM_ErrorMe_f(void)
#ifdef LOADERTHREAD #ifdef LOADERTHREAD
static void QDECL COM_WorkerCount_Change(cvar_t *var, char *oldvalue); static void QDECL COM_WorkerCount_Change(cvar_t *var, char *oldvalue);
cvar_t worker_flush = CVARD("worker_flush", "1", "If set, process the entire load queue, loading stuff faster but at the risk of stalling the main thread."); cvar_t worker_flush = CVARD("worker_flush", "1", "If set, process the entire load queue, loading stuff faster but at the risk of stalling the main thread.");
cvar_t worker_count = CVARFCD("worker_count", "", CVAR_NOTFROMSERVER, COM_WorkerCount_Change, "Specifies the number of worker threads to utilise."); static cvar_t worker_count = CVARFCD("worker_count", "", CVAR_NOTFROMSERVER, COM_WorkerCount_Change, "Specifies the number of worker threads to utilise.");
cvar_t worker_sleeptime = CVARFD("worker_sleeptime", "0", CVAR_NOTFROMSERVER, "Causes workers to sleep for a period of time after each job."); static cvar_t worker_sleeptime = CVARFD("worker_sleeptime", "0", CVAR_NOTFROMSERVER, "Causes workers to sleep for a period of time after each job.");
#define WORKERTHREADS 16 //max #define WORKERTHREADS 16 //max
/*multithreading worker thread stuff*/ /*multithreading worker thread stuff*/
@ -6429,7 +6429,7 @@ static qboolean InfoBuf_EncodeString_Internal(const char *n, size_t s, char *out
for (c = n; c < n+s; c++) for (c = n; c < n+s; c++)
{ {
base64_cur |= *(unsigned char*)c<<(16- base64_bits);//first byte fills highest bits base64_cur |= *(const unsigned char*)c<<(16- base64_bits);//first byte fills highest bits
base64_bits += 8; base64_bits += 8;
if (base64_bits == 24) if (base64_bits == 24)

View file

@ -164,13 +164,13 @@ typedef struct sizebuf_s
{ {
qboolean allowoverflow; // if false, do a Sys_Error qboolean allowoverflow; // if false, do a Sys_Error
qboolean overflowed; // set to true if the buffer size failed qboolean overflowed; // set to true if the buffer size failed
qbyte *data; qbyte *data;
int maxsize; int maxsize; //storage size of data
int cursize; int cursize; //assigned size of data
int packing; sbpacking_t packing; //required for q3
int currentbit; int currentbit; //ignored for rawbytes
struct netprim_s prim; struct netprim_s prim; //for unsized write/read coord/angles
} sizebuf_t; } sizebuf_t;
void SZ_Clear (sizebuf_t *buf); void SZ_Clear (sizebuf_t *buf);
@ -851,8 +851,10 @@ void Con_Log (const char *s);
void Log_Logfile_f (void); void Log_Logfile_f (void);
void Log_Init(void); void Log_Init(void);
void Log_ShutDown(void); void Log_ShutDown(void);
#ifdef IPLOG
void IPLog_Add(const char *ip, const char *name); //for associating player ip addresses with names. void IPLog_Add(const char *ip, const char *name); //for associating player ip addresses with names.
qboolean IPLog_Merge_File(const char *fname); qboolean IPLog_Merge_File(const char *fname);
#endif
qboolean CertLog_ConnectOkay(const char *hostname, void *cert, size_t certsize); qboolean CertLog_ConnectOkay(const char *hostname, void *cert, size_t certsize);

View file

@ -104,6 +104,8 @@
#undef IMAGEFMT_PKM #undef IMAGEFMT_PKM
#undef IMAGEFMT_DDS //.dds files embed mipmaps and texture compression. faster to load. #undef IMAGEFMT_DDS //.dds files embed mipmaps and texture compression. faster to load.
#undef IMAGEFMT_BLP //legacy crap #undef IMAGEFMT_BLP //legacy crap
#undef IMAGEFMT_BMP //legacy crap
#undef IMAGEFMT_PCX //legacy crap
#undef DECOMPRESS_ETC2 #undef DECOMPRESS_ETC2
#undef DECOMPRESS_RGTC #undef DECOMPRESS_RGTC
#undef DECOMPRESS_S3TC #undef DECOMPRESS_S3TC

View file

@ -48,6 +48,7 @@
#define TEXTEDITOR //my funky text editor! its awesome! #define TEXTEDITOR //my funky text editor! its awesome!
#define PLUGINS //support for external plugins (like huds or fancy menus or whatever) #define PLUGINS //support for external plugins (like huds or fancy menus or whatever)
#define USE_SQLITE //sql-database-as-file support #define USE_SQLITE //sql-database-as-file support
#define IPLOG //track player's ip addresses (any decent server will hide ip addresses, so this probably isn't that useful, but nq players expect its)
//Filesystem formats //Filesystem formats
#define PACKAGE_PK3 #define PACKAGE_PK3
@ -87,9 +88,11 @@
#define IMAGEFMT_PKM //file format generally written by etcpack or android's etc1tool. doesn't support mips. #define IMAGEFMT_PKM //file format generally written by etcpack or android's etc1tool. doesn't support mips.
#define IMAGEFMT_DDS //.dds files embed mipmaps and texture compression. faster to load. #define IMAGEFMT_DDS //.dds files embed mipmaps and texture compression. faster to load.
#define IMAGEFMT_BLP //legacy crap #define IMAGEFMT_BLP //legacy crap
#define PACKAGE_TEXWAD //quake's image wad support #define IMAGEFMT_BMP //windows bmp. yuck.
#define IMAGEFMT_PCX //paletted junk. required for qw player skins, q2 and a few old skyboxes.
#define AVAIL_PNGLIB //.png image format support (read+screenshots) #define AVAIL_PNGLIB //.png image format support (read+screenshots)
#define AVAIL_JPEGLIB //.jpeg image format support (read+screenshots) #define AVAIL_JPEGLIB //.jpeg image format support (read+screenshots)
#define PACKAGE_TEXWAD //quake's image wad support
#define AVAIL_FREETYPE //for truetype font rendering #define AVAIL_FREETYPE //for truetype font rendering
#define DECOMPRESS_ETC2 //decompress etc2(core in gles3/gl4.3) if the graphics driver doesn't support it (eg d3d or crappy gpus with vulkan). #define DECOMPRESS_ETC2 //decompress etc2(core in gles3/gl4.3) if the graphics driver doesn't support it (eg d3d or crappy gpus with vulkan).
#define DECOMPRESS_S3TC //allows bc1-3 to work even when drivers don't support it. This is probably only an issue on mobile chips. WARNING: not entirely sure if all patents expired yet... #define DECOMPRESS_S3TC //allows bc1-3 to work even when drivers don't support it. This is probably only an issue on mobile chips. WARNING: not entirely sure if all patents expired yet...

View file

@ -89,13 +89,15 @@
//#define IMAGEFMT_PKM //file format generally written by etcpack or android's etc1tool. doesn't support mips. //#define IMAGEFMT_PKM //file format generally written by etcpack or android's etc1tool. doesn't support mips.
//#define IMAGEFMT_DDS //.dds files embed mipmaps and texture compression. faster to load. //#define IMAGEFMT_DDS //.dds files embed mipmaps and texture compression. faster to load.
//#define IMAGEFMT_BLP //legacy crap //#define IMAGEFMT_BLP //legacy crap
#define PACKAGE_TEXWAD //quake's image wad support //#define IMAGEFMT_BMP //windows bmp. yuck.
//#define IMAGEFMT_PCX //paletted junk. required for qw player skins, q2 and a few old skyboxes.
#define AVAIL_PNGLIB //.png image format support (read+screenshots) #define AVAIL_PNGLIB //.png image format support (read+screenshots)
//#define AVAIL_JPEGLIB //.jpeg image format support (read+screenshots) //#define AVAIL_JPEGLIB //.jpeg image format support (read+screenshots)
//#define AVAIL_FREETYPE //for truetype font rendering #define PACKAGE_TEXWAD //quake's image wad support
//#define DECOMPRESS_ETC2 //decompress etc2(core in gles3/gl4.3) if the graphics driver doesn't support it (eg d3d or crappy gpus with vulkan). //#define AVAIL_FREETYPE //for truetype font rendering
////#define DECOMPRESS_S3TC //allows bc1-3 to work even when drivers don't support it. This is probably only an issue on mobile chips. WARNING: not entirely sure if all patents expired yet... //#define DECOMPRESS_ETC2 //decompress etc2(core in gles3/gl4.3) if the graphics driver doesn't support it (eg d3d or crappy gpus with vulkan).
//#define DECOMPRESS_RGTC //bc4+bc5 ////#define DECOMPRESS_S3TC //allows bc1-3 to work even when drivers don't support it. This is probably only an issue on mobile chips. WARNING: not entirely sure if all patents expired yet...
//#define DECOMPRESS_RGTC //bc4+bc5
// Game/Gamecode Support // Game/Gamecode Support
//#define CSQC_DAT //#define CSQC_DAT

View file

@ -1,5 +1,5 @@
// Build-Config file for FTE's standard builds, the default settings. // Build-Config file for Quake-derived total-conversion mods that have chosen to break compatibility.
// to use: make FTE_CONFIG=fteqw // to use: make FTE_CONFIG=nocompat
// Features should either be commented or not. If you change undefs to defines or vice versa then expect problems. // Features should either be commented or not. If you change undefs to defines or vice versa then expect problems.
// Later code will disable any features if they're not supported on the current platform, so don't worry about win/lin/mac/android/web/etc here - any such issues should be fixed elsewhere. // Later code will disable any features if they're not supported on the current platform, so don't worry about win/lin/mac/android/web/etc here - any such issues should be fixed elsewhere.
@ -86,12 +86,14 @@
//#define IMAGEFMT_PKM //file format generally written by etcpack or android's etc1tool. doesn't support mips. //#define IMAGEFMT_PKM //file format generally written by etcpack or android's etc1tool. doesn't support mips.
#define IMAGEFMT_DDS //.dds files embed mipmaps and texture compression. faster to load. #define IMAGEFMT_DDS //.dds files embed mipmaps and texture compression. faster to load.
//#define IMAGEFMT_BLP //legacy crap //#define IMAGEFMT_BLP //legacy crap
//#define PACKAGE_TEXWAD //quake's image wad support //#define IMAGEFMT_BMP //windows bmp. yuck.
//#define IMAGEFMT_PCX //paletted junk. required for qw player skins, q2 and a few old skyboxes.
#define AVAIL_PNGLIB //.png image format support (read+screenshots) #define AVAIL_PNGLIB //.png image format support (read+screenshots)
//#define AVAIL_JPEGLIB //.jpeg image format support (read+screenshots) //#define AVAIL_JPEGLIB //.jpeg image format support (read+screenshots)
//#define PACKAGE_TEXWAD //quake's image wad support
#define AVAIL_FREETYPE //for truetype font rendering #define AVAIL_FREETYPE //for truetype font rendering
#define DECOMPRESS_ETC2 //decompress etc2(core in gles3/gl4.3) if the graphics driver doesn't support it (eg d3d or crappy gpus with vulkan). #define DECOMPRESS_ETC2 //decompress etc2(core in gles3/gl4.3) if the graphics driver doesn't support it (eg d3d or crappy gpus with vulkan).
//#define DECOMPRESS_S3TC //allows bc1-3 to work even when drivers don't support it. This is probably only an issue on mobile chips. WARNING: not entirely sure if all patents expired yet... //#define DECOMPRESS_S3TC //allows bc1-3 to work even when drivers don't support it. This is probably only an issue on mobile chips. WARNING: not entirely sure if all patents expired yet...
#define DECOMPRESS_RGTC //bc4+bc5 #define DECOMPRESS_RGTC //bc4+bc5
// Game/Gamecode Support // Game/Gamecode Support

View file

@ -112,6 +112,8 @@
#undef IMAGEFMT_KTX #undef IMAGEFMT_KTX
#undef IMAGEFMT_PKM #undef IMAGEFMT_PKM
#undef IMAGEFMT_BLP //legacy crap #undef IMAGEFMT_BLP //legacy crap
#undef IMAGEFMT_BMP //legacy crap
#undef IMAGEFMT_PCX //legacy crap
#undef NETPREPARSE //allows for running both nq+qw on the same server (if not, protocol used must match gamecode). #undef NETPREPARSE //allows for running both nq+qw on the same server (if not, protocol used must match gamecode).
#undef USE_SQLITE //sql-database-as-file support #undef USE_SQLITE //sql-database-as-file support
#undef QUAKESTATS //defines STAT_HEALTH etc. if omitted, you'll need to provide that functionality yourself. #undef QUAKESTATS //defines STAT_HEALTH etc. if omitted, you'll need to provide that functionality yourself.

View file

@ -200,10 +200,11 @@ typedef struct console_s
struct console_s *next; struct console_s *next;
} console_t; } console_t;
extern console_t con_main; extern console_t *con_head;
extern console_t *con_curwindow; // refers to a windowed console extern console_t *con_curwindow; // refers to a windowed console
extern console_t *con_current; // point to either con_main or con_chat extern console_t *con_current; // point to either con_main or con_chat
extern console_t *con_mouseover; extern console_t *con_mouseover;
extern console_t *con_chat; extern console_t *con_chat;
//shared between console and keys. //shared between console and keys.
@ -260,6 +261,7 @@ void Con_SetActive (console_t *con);
qboolean Con_NameForNum(int num, char *buffer, int buffersize); qboolean Con_NameForNum(int num, char *buffer, int buffersize);
console_t *Con_FindConsole(const char *name); console_t *Con_FindConsole(const char *name);
console_t *Con_Create(const char *name, unsigned int flags); console_t *Con_Create(const char *name, unsigned int flags);
console_t *Con_GetMain(void); //retrieves the main console (creating it if needed)
void Con_PrintCon (console_t *con, const char *txt, unsigned int parseflags); void Con_PrintCon (console_t *con, const char *txt, unsigned int parseflags);
qboolean Con_InsertConChars (console_t *con, conline_t *line, int offset, conchar_t *c, int len); qboolean Con_InsertConChars (console_t *con, conline_t *line, int offset, conchar_t *c, int len);
conline_t *Con_ResizeLineBuffer(console_t *con, conline_t *old, unsigned int length); conline_t *Con_ResizeLineBuffer(console_t *con, conline_t *old, unsigned int length);

View file

@ -3066,7 +3066,7 @@ void COM_Gamedir (const char *dir, const struct gamepacks *packagespaths)
/*quake requires a few settings for compatibility*/ /*quake requires a few settings for compatibility*/
#define EZQUAKECOMPETITIVE "set ruleset_allow_fbmodels 1\nset sv_demoExtensions \"\"\n" #define EZQUAKECOMPETITIVE "set ruleset_allow_fbmodels 1\nset sv_demoExtensions \"\"\n"
#define QRPCOMPAT "set cl_cursor_scale 0.2\nset cl_cursor_bias_x 7.5\nset cl_cursor_bias_y 0.8" #define QRPCOMPAT "set cl_cursor_scale 0.2\nset cl_cursor_bias_x 7.5\nset cl_cursor_bias_y 0.8"
#define QCFG "set com_parseutf8 0\nset allow_download_refpackages 0\nset sv_bigcoords \"\"\nmap_autoopenportals 1\n" "sv_port "STRINGIFY(PORT_QWSERVER)" "STRINGIFY(PORT_NQSERVER)"\n" ZFIXHACK EZQUAKECOMPETITIVE QRPCOMPAT #define QCFG "set con_stayhidden 0\nset com_parseutf8 0\nset allow_download_refpackages 0\nset sv_bigcoords \"\"\nmap_autoopenportals 1\n" "sv_port "STRINGIFY(PORT_QWSERVER)" "STRINGIFY(PORT_NQSERVER)"\n" ZFIXHACK EZQUAKECOMPETITIVE QRPCOMPAT
/*NetQuake reconfiguration, to make certain people feel more at home...*/ /*NetQuake reconfiguration, to make certain people feel more at home...*/
#define NQCFG "//-nohome\ncfg_save_auto 1\n" QCFG "sv_nqplayerphysics 1\ncl_loopbackprotocol auto\ncl_sbar 1\nplug_sbar 0\nsv_port "STRINGIFY(PORT_NQSERVER)"\ncl_defaultport "STRINGIFY(PORT_NQSERVER)"\n" #define NQCFG "//-nohome\ncfg_save_auto 1\n" QCFG "sv_nqplayerphysics 1\ncl_loopbackprotocol auto\ncl_sbar 1\nplug_sbar 0\nsv_port "STRINGIFY(PORT_NQSERVER)"\ncl_defaultport "STRINGIFY(PORT_NQSERVER)"\n"
//nehahra has to be weird with its extra cvars, and buggy fullbrights. //nehahra has to be weird with its extra cvars, and buggy fullbrights.

View file

@ -5,13 +5,13 @@
#if !defined(NACL) && !defined(FTE_TARGET_WEB) #if !defined(NACL) && !defined(FTE_TARGET_WEB)
#ifdef WEBSVONLY #ifdef WEBSVONLY
#define Z_Free free #define Z_Free free
#define Z_Malloc malloc #define Z_Malloc malloc
#else #else
#if !defined(_WIN32) || defined(FTE_SDL) || defined(WINRT) || defined(_XBOX) #if !defined(_WIN32) || defined(FTE_SDL) || defined(WINRT) || defined(_XBOX)
#define FSSTDIO_OpenPath VFSOS_OpenPath #define FSSTDIO_OpenPath VFSOS_OpenPath
#endif #endif
#define FSSTDIO_OpenTemp FS_OpenTemp #define FSSTDIO_OpenTemp FS_OpenTemp
#endif #endif
typedef struct { typedef struct {
@ -148,7 +148,7 @@ vfsfile_t *FSSTDIO_OpenTemp(void)
vfsfile_t *Sys_OpenAsset(const char *fname); vfsfile_t *Sys_OpenAsset(const char *fname);
#endif #endif
static vfsfile_t *VFSSTDIO_Open(const char *osname, const char *mode, qboolean *needsflush) vfsfile_t *VFSSTDIO_Open(const char *osname, const char *mode, qboolean *needsflush)
{ {
FILE *f; FILE *f;
vfsstdiofile_t *file; vfsstdiofile_t *file;

View file

@ -254,18 +254,24 @@ typedef struct
q2cbrushside_t *brushside; q2cbrushside_t *brushside;
} q2cbrush_t; } q2cbrush_t;
#ifdef Q2BSPS
typedef struct typedef struct
{ {
int numareaportals; int numareaportals;
int firstareaportal; int firstareaportal;
int floodnum; // if two areas have equal floodnums, they are connected
int floodvalid;
} q2carea_t; } q2carea_t;
#endif
#ifdef Q3BSPS
typedef struct typedef struct
{ {
int numareaportals[MAX_CM_AREAS]; int numareaportals[MAX_CM_AREAS];
} q3carea_t; } q3carea_t;
#endif
typedef struct
{
int floodnum; // if two areas have equal floodnums, they are connected
int floodvalid; // flags the area as having been visited (sequence numbers matching prv->floodvalid)
} careaflood_t;
typedef struct typedef struct
{ {
@ -353,10 +359,22 @@ typedef struct cminfo_s
q3dvis_t *q3phs; q3dvis_t *q3phs;
int numareas; int numareas;
q2carea_t q2areas[MAX_Q2MAP_AREAS]; int floodvalid;
careaflood_t areaflood[MAX_CM_AREAS];
#ifdef Q3BSPS
//q3's areas are simple bidirectional area1/area2 pairs. refcounted (so two areas can have two doors/openings)
q3carea_t q3areas[MAX_CM_AREAS]; q3carea_t q3areas[MAX_CM_AREAS];
int numareaportals; #endif
q2dareaportal_t areaportals[MAX_Q2MAP_AREAPORTALS]; #ifdef Q2BSPS
//q2's areas have a list of portals that open into other areas.
q2carea_t *q2areas; //indexes into q2areaportals for flooding
size_t numq2areaportals;
q2dareaportal_t *q2areaportals;
//and this is the state that is actually changed. booleans.
qbyte q2portalopen[MAX_Q2MAP_AREAPORTALS]; //memset will work if it's a qbyte, really it should be a qboolean
#endif
//list of mesh surfaces within the leaf //list of mesh surfaces within the leaf
q3cmesh_t cmeshes[MAX_CM_PATCHES]; q3cmesh_t cmeshes[MAX_CM_PATCHES];
@ -374,10 +392,7 @@ typedef struct cminfo_s
int maxleafpatches; int maxleafpatches;
//FIXME: remove the above //FIXME: remove the above
int floodvalid; qboolean mapisq3;
qbyte portalopen[MAX_Q2MAP_AREAPORTALS]; //memset will work if it's a qbyte, really it should be a qboolean
int mapisq3;
@ -1964,7 +1979,7 @@ static qboolean CModQ2_LoadAreas (model_t *mod, qbyte *mod_base, lump_t *l)
{ {
cminfo_t *prv = (cminfo_t*)mod->meshinfo; cminfo_t *prv = (cminfo_t*)mod->meshinfo;
int i; int i;
q2carea_t *out; q2carea_t *out;
q2darea_t *in; q2darea_t *in;
int count; int count;
@ -1982,15 +1997,13 @@ static qboolean CModQ2_LoadAreas (model_t *mod, qbyte *mod_base, lump_t *l)
return false; return false;
} }
out = prv->q2areas; out = prv->q2areas = ZG_Malloc(&mod->memgroup, sizeof(*out) * count);;
prv->numareas = count; prv->numareas = count;
for ( i=0 ; i<count ; i++, in++, out++) for ( i=0 ; i<count ; i++, in++, out++)
{ {
out->numareaportals = LittleLong (in->numareaportals); out->numareaportals = LittleLong (in->numareaportals);
out->firstareaportal = LittleLong (in->firstareaportal); out->firstareaportal = LittleLong (in->firstareaportal);
out->floodvalid = 0;
out->floodnum = 0;
} }
return true; return true;
@ -2023,8 +2036,8 @@ static qboolean CModQ2_LoadAreaPortals (model_t *mod, qbyte *mod_base, lump_t *l
return false; return false;
} }
out = prv->areaportals; out = prv->q2areaportals = ZG_Malloc(&mod->memgroup, sizeof(*out) * count);
prv->numareaportals = count; prv->numq2areaportals = count;
for ( i=0 ; i<count ; i++, in++, out++) for ( i=0 ; i<count ; i++, in++, out++)
{ {
@ -3533,11 +3546,12 @@ static void CModQ3_LoadLighting (model_t *loadmodel, qbyte *mod_base, lump_t *l)
BuildLightMapGammaTable(1, (1<<(2-gl_overbright.ival))); BuildLightMapGammaTable(1, (1<<(2-gl_overbright.ival)));
loadmodel->lightmaps.merge = 0; loadmodel->lightmaps.merge = 0;
if (!samples)
return;
loadmodel->engineflags |= MDLF_NEEDOVERBRIGHT; loadmodel->engineflags |= MDLF_NEEDOVERBRIGHT;
if (!samples)
return;
loadmodel->lightmaps.fmt = LM_RGB8; loadmodel->lightmaps.fmt = LM_RGB8;
if (loadmodel->lightmaps.deluxemapping) if (loadmodel->lightmaps.deluxemapping)
@ -4450,10 +4464,20 @@ static cmodel_t *CM_LoadMap (model_t *mod, qbyte *filein, size_t filelen, qboole
BSPX_LoadEnvmaps(mod, bspx, mod_base); BSPX_LoadEnvmaps(mod, bspx, mod_base);
#ifdef Q3BSPS
{
int x, y;
for (x = 0; x < prv->numareas; x++)
for (y = 0; y < prv->numareas; y++)
prv->q3areas[x].numareaportals[y] = map_autoopenportals.ival;
}
#endif
#ifdef Q2BSPS
if (map_autoopenportals.value) if (map_autoopenportals.value)
memset (prv->portalopen, 1, sizeof(prv->portalopen)); //open them all. Used for progs that havn't got a clue. memset (prv->q2portalopen, 1, sizeof(prv->q2portalopen)); //open them all. Used for progs that havn't got a clue.
else else
memset (prv->portalopen, 0, sizeof(prv->portalopen)); //make them start closed. memset (prv->q2portalopen, 0, sizeof(prv->q2portalopen)); //make them start closed.
#endif
FloodAreaConnections (prv); FloodAreaConnections (prv);
mod->checksum = mod->checksum2 = *checksum; mod->checksum = mod->checksum2 = *checksum;
@ -6485,36 +6509,45 @@ AREAPORTALS
=============================================================================== ===============================================================================
*/ */
static void FloodArea_r (cminfo_t *prv, q2carea_t *area, int floodnum) static void FloodArea_r (cminfo_t *prv, size_t areaidx, int floodnum)
{ {
int i; size_t i;
if (area->floodvalid == prv->floodvalid) careaflood_t *flood = &prv->areaflood[areaidx];
if (flood->floodvalid == prv->floodvalid)
{ {
if (area->floodnum == floodnum) if (flood->floodnum == floodnum)
return; return;
Con_Printf ("FloodArea_r: reflooded\n"); Con_Printf ("FloodArea_r: reflooded\n");
return; return;
} }
area->floodnum = floodnum; flood->floodnum = floodnum;
area->floodvalid = prv->floodvalid; flood->floodvalid = prv->floodvalid;
if (prv->mapisq3) switch(prv->mapisq3)
{ {
case true:
#ifdef Q3BSPS
for (i=0 ; i<prv->numareas ; i++) for (i=0 ; i<prv->numareas ; i++)
{ {
if (prv->q3areas[area - prv->q2areas].numareaportals[i]>0) if (prv->q3areas[areaidx].numareaportals[i]>0)
FloodArea_r (prv, &prv->q2areas[i], floodnum); FloodArea_r (prv, i, floodnum);
} }
} #endif
else break;
{ case false:
q2dareaportal_t *p = &prv->areaportals[area->firstareaportal]; #ifdef Q2BSPS
for (i=0 ; i<area->numareaportals ; i++, p++)
{ {
if (prv->portalopen[p->portalnum]) q2carea_t *area = &prv->q2areas[areaidx];
FloodArea_r (prv, &prv->q2areas[p->otherarea], floodnum); q2dareaportal_t *p = &prv->q2areaportals[area->firstareaportal];
for (i=0 ; i<area->numareaportals ; i++, p++)
{
if (prv->q2portalopen[p->portalnum])
FloodArea_r (prv, p->otherarea, floodnum);
}
} }
#endif
break;
} }
} }
@ -6527,8 +6560,7 @@ FloodAreaConnections
*/ */
static void FloodAreaConnections (cminfo_t *prv) static void FloodAreaConnections (cminfo_t *prv)
{ {
int i; size_t i;
q2carea_t *area;
int floodnum; int floodnum;
// all current floods are now invalid // all current floods are now invalid
@ -6538,15 +6570,14 @@ static void FloodAreaConnections (cminfo_t *prv)
// area 0 is not used // area 0 is not used
for (i=0 ; i<prv->numareas ; i++) for (i=0 ; i<prv->numareas ; i++)
{ {
area = &prv->q2areas[i]; if (prv->areaflood[i].floodvalid == prv->floodvalid)
if (area->floodvalid == prv->floodvalid)
continue; // already flooded into continue; // already flooded into
floodnum++; floodnum++;
FloodArea_r (prv, area, floodnum); FloodArea_r (prv, i, floodnum);
} }
} }
#ifdef Q2BSPS
void CMQ2_SetAreaPortalState (model_t *mod, unsigned int portalnum, qboolean open) void CMQ2_SetAreaPortalState (model_t *mod, unsigned int portalnum, qboolean open)
{ {
cminfo_t *prv; cminfo_t *prv;
@ -6555,17 +6586,19 @@ void CMQ2_SetAreaPortalState (model_t *mod, unsigned int portalnum, qboolean ope
prv = (cminfo_t*)mod->meshinfo; prv = (cminfo_t*)mod->meshinfo;
if (prv->mapisq3) if (prv->mapisq3)
return; return;
if (portalnum > prv->numareaportals) if (portalnum > prv->numq2areaportals)
Host_Error ("areaportal > numareaportals"); Host_Error ("areaportal > numareaportals");
if (prv->portalopen[portalnum] == open) if (prv->q2portalopen[portalnum] == open)
return; return;
prv->portalopen[portalnum] = open; prv->q2portalopen[portalnum] = open;
FloodAreaConnections (prv); FloodAreaConnections (prv);
return; return;
} }
#endif
#ifdef Q3BSPS
void CMQ3_SetAreaPortalState (model_t *mod, unsigned int area1, unsigned int area2, qboolean open) void CMQ3_SetAreaPortalState (model_t *mod, unsigned int area1, unsigned int area2, qboolean open)
{ {
cminfo_t *prv = (cminfo_t*)mod->meshinfo; cminfo_t *prv = (cminfo_t*)mod->meshinfo;
@ -6589,6 +6622,7 @@ void CMQ3_SetAreaPortalState (model_t *mod, unsigned int area1, unsigned int are
FloodAreaConnections(prv); FloodAreaConnections(prv);
} }
#endif
qboolean VARGS CM_AreasConnected (model_t *mod, unsigned int area1, unsigned int area2) qboolean VARGS CM_AreasConnected (model_t *mod, unsigned int area1, unsigned int area2)
{ {
@ -6602,7 +6636,7 @@ qboolean VARGS CM_AreasConnected (model_t *mod, unsigned int area1, unsigned int
if (area1 > prv->numareas || area2 > prv->numareas) if (area1 > prv->numareas || area2 > prv->numareas)
Host_Error ("area > numareas"); Host_Error ("area > numareas");
if (prv->q2areas[area1].floodnum == prv->q2areas[area2].floodnum) if (prv->areaflood[area1].floodnum == prv->areaflood[area2].floodnum)
return true; return true;
return false; return false;
} }
@ -6637,10 +6671,10 @@ int CM_WriteAreaBits (model_t *mod, qbyte *buffer, int area, qboolean merge)
if (!merge) if (!merge)
memset (buffer, 0, bytes); memset (buffer, 0, bytes);
floodnum = prv->q2areas[area].floodnum; floodnum = prv->areaflood[area].floodnum;
for (i=0 ; i<prv->numareas ; i++) for (i=0 ; i<prv->numareas ; i++)
{ {
if (prv->q2areas[i].floodnum == floodnum || !area) if (prv->areaflood[i].floodnum == floodnum || !area)
buffer[i>>3] |= 1<<(i&7); buffer[i>>3] |= 1<<(i&7);
} }
} }
@ -6661,17 +6695,19 @@ size_t CM_WritePortalState (model_t *mod, void **data)
if (mod->type == mod_brush && (mod->fromgame == fg_quake2 || mod->fromgame == fg_quake3)) if (mod->type == mod_brush && (mod->fromgame == fg_quake2 || mod->fromgame == fg_quake3))
{ {
switch(prv->mapisq3)
{
#ifdef Q3BSPS #ifdef Q3BSPS
if (prv->mapisq3) case true:
{ //endian issues. oh well. //endian issues. oh well.
*data = prv->q3areas; *data = prv->q3areas;
return sizeof(prv->q3areas); return sizeof(prv->q3areas);
}
else
#endif #endif
{ #ifdef Q2BSPS
*data = prv->portalopen; case false:
return sizeof(prv->portalopen); *data = prv->q2portalopen;
return sizeof(prv->q2portalopen);
#endif
} }
} }
*data = NULL; *data = NULL;
@ -6692,9 +6728,10 @@ qofs_t CM_ReadPortalState (model_t *mod, qbyte *ptr, qofs_t ptrsize)
if (mod->type == mod_brush && (mod->fromgame == fg_quake2 || mod->fromgame == fg_quake3)) if (mod->type == mod_brush && (mod->fromgame == fg_quake2 || mod->fromgame == fg_quake3))
{ {
#ifdef Q3BSPS switch(prv->mapisq3)
if (prv->mapisq3)
{ {
#ifdef Q3BSPS
case 1:
if (ptrsize < sizeof(prv->q3areas)) if (ptrsize < sizeof(prv->q3areas))
Con_Printf("CM_ReadPortalState() expected %u, but only %u available\n",(unsigned int)sizeof(prv->q3areas),(unsigned int)ptrsize); Con_Printf("CM_ReadPortalState() expected %u, but only %u available\n",(unsigned int)sizeof(prv->q3areas),(unsigned int)ptrsize);
else else
@ -6702,21 +6739,23 @@ qofs_t CM_ReadPortalState (model_t *mod, qbyte *ptr, qofs_t ptrsize)
memcpy(prv->q3areas, ptr, sizeof(prv->q3areas)); memcpy(prv->q3areas, ptr, sizeof(prv->q3areas));
FloodAreaConnections (prv); FloodAreaConnections (prv);
return sizeof(prv->portalopen); return sizeof(prv->q3areas);
} }
} break;
else
#endif #endif
{ #ifdef Q2BSPS
if (ptrsize < sizeof(prv->portalopen)) case 0:
Con_Printf("CM_ReadPortalState() expected %u, but only %u available\n",(unsigned int)sizeof(prv->portalopen),(unsigned int)ptrsize); if (ptrsize < sizeof(prv->q2portalopen))
Con_Printf("CM_ReadPortalState() expected %u, but only %u available\n",(unsigned int)sizeof(prv->q2portalopen),(unsigned int)ptrsize);
else else
{ {
memcpy(prv->portalopen, ptr, sizeof(prv->portalopen)); memcpy(prv->q2portalopen, ptr, sizeof(prv->q2portalopen));
FloodAreaConnections (prv); FloodAreaConnections (prv);
return sizeof(prv->portalopen); return sizeof(prv->q2portalopen);
} }
break;
#endif
} }
} }
return 0; return 0;

View file

@ -28,6 +28,10 @@ cvar_t log_dosformat = CVARF("log_dosformat", "0", CVAR_NOTFROMSERVER);
#endif #endif
qboolean log_newline[LOG_TYPES]; qboolean log_newline[LOG_TYPES];
#ifdef IPLOG
cvar_t iplog_autodump = CVARFD("ipautodump", "1", CVAR_NOTFROMSERVER, "Enables dumping the 'iplog.txt' file, which contains a log of usernames seen for a given IP, which is useful for detecting fake-nicks.");
#endif
static char log_dir[MAX_OSPATH]; static char log_dir[MAX_OSPATH];
static enum fs_relative log_root = FS_GAMEONLY; static enum fs_relative log_root = FS_GAMEONLY;
@ -335,6 +339,7 @@ void SV_Fraglogfile_f (void)
} }
*/ */
#ifdef IPLOG
/*for fuck sake, why can people still not write simple files. proquake is writing binary files as text ones. this function is to try to deal with that fuckup*/ /*for fuck sake, why can people still not write simple files. proquake is writing binary files as text ones. this function is to try to deal with that fuckup*/
static size_t IPLog_Read_Fucked(qbyte *file, size_t *offset, size_t totalsize, qbyte *out, size_t outsize) static size_t IPLog_Read_Fucked(qbyte *file, size_t *offset, size_t totalsize, qbyte *out, size_t outsize)
{ {
@ -356,7 +361,7 @@ static size_t IPLog_Read_Fucked(qbyte *file, size_t *offset, size_t totalsize, q
} }
return read; return read;
} }
/*need to make sure any 13 bytes followed by 10s don't bug out when read back in *sigh* */ /*need to make sure any 13 bytes are followed by 10s so that we don't bug out when read back in *sigh* */
static size_t IPLog_Write_Fucked(vfsfile_t *file, qbyte *out, size_t outsize) static size_t IPLog_Write_Fucked(vfsfile_t *file, qbyte *out, size_t outsize)
{ {
qbyte tmp[64]; qbyte tmp[64];
@ -623,6 +628,7 @@ static void IPLog_Merge_f(void)
if (!IPLog_Merge_File(fname)) if (!IPLog_Merge_File(fname))
Con_Printf("unable to read %s\n", fname); Con_Printf("unable to read %s\n", fname);
} }
#endif
#ifndef SERVERONLY #ifndef SERVERONLY
struct certlog_s struct certlog_s
@ -791,7 +797,9 @@ qboolean CertLog_ConnectOkay(const char *hostname, void *cert, size_t certsize)
void Log_ShutDown(void) void Log_ShutDown(void)
{ {
IPLog_Dump("iplog.txt"); #ifdef IPLOG
if (iplog_autodump.ival)
IPLog_Dump("iplog.txt");
// IPLog_Dump("iplog.dat"); // IPLog_Dump("iplog.dat");
while(iplog_num > 0) while(iplog_num > 0)
@ -802,6 +810,7 @@ void Log_ShutDown(void)
BZ_Free(iplog_entries); BZ_Free(iplog_entries);
iplog_entries = NULL; iplog_entries = NULL;
iplog_max = iplog_num = 0; iplog_max = iplog_num = 0;
#endif
} }
void Log_Init(void) void Log_Init(void)
@ -824,9 +833,12 @@ void Log_Init(void)
Cmd_AddCommand("logfile", Log_Logfile_f); Cmd_AddCommand("logfile", Log_Logfile_f);
Cmd_AddCommand("identify", IPLog_Identify_f); #ifdef IPLOG
Cmd_AddCommandD("identify", IPLog_Identify_f, "Looks up a player's ip to see if they're using a different name");
Cmd_AddCommand("ipmerge", IPLog_Merge_f); Cmd_AddCommand("ipmerge", IPLog_Merge_f);
Cmd_AddCommand("ipdump", IPLog_Dump_f); Cmd_AddCommand("ipdump", IPLog_Dump_f);
Cvar_Register (&iplog_autodump, CONLOGGROUP);
#endif
// cmd line options, debug options // cmd line options, debug options
#ifdef CRAZYDEBUGGING #ifdef CRAZYDEBUGGING

View file

@ -554,7 +554,7 @@ void R_ConcatRotations (float in1[3][3], float in2[3][3], float out[3][3])
R_ConcatTransforms R_ConcatTransforms
================ ================
*/ */
void QDECL R_ConcatTransforms (float in1[3][4], float in2[3][4], float out[3][4]) void QDECL R_ConcatTransforms (const float in1[3][4], const float in2[3][4], float out[3][4])
{ {
out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] + out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] +
in1[0][2] * in2[2][0]; in1[0][2] * in2[2][0];

View file

@ -203,7 +203,7 @@ fixed16_t Mul16_30 (fixed16_t multiplier, fixed16_t multiplicand);
int Q_log2 (int val); int Q_log2 (int val);
void R_ConcatRotations (float in1[3][3], float in2[3][3], float out[3][3]); void R_ConcatRotations (float in1[3][3], float in2[3][3], float out[3][3]);
void R_ConcatRotationsPad (float in1[3][4], float in2[3][4], float out[3][4]); void R_ConcatRotationsPad (float in1[3][4], float in2[3][4], float out[3][4]);
void QDECL R_ConcatTransforms (matrix3x4 in1, matrix3x4 in2, matrix3x4 out); void QDECL R_ConcatTransforms (const matrix3x4 in1, const matrix3x4 in2, matrix3x4 out);
void R_ConcatTransformsAxis (float in1[3][3], float in2[3][4], float out[3][4]); void R_ConcatTransformsAxis (float in1[3][3], float in2[3][4], float out[3][4]);
void RotatePointAroundVector (vec3_t dst, const vec3_t dir, const vec3_t point, float degrees); void RotatePointAroundVector (vec3_t dst, const vec3_t dir, const vec3_t point, float degrees);
void RotateLightVector(const vec3_t *axis, const vec3_t origin, const vec3_t lightpoint, vec3_t result); void RotateLightVector(const vec3_t *axis, const vec3_t origin, const vec3_t lightpoint, vec3_t result);

View file

@ -177,6 +177,12 @@ qboolean NET_CompareAdrMasked(netadr_t *a, netadr_t *b, netadr_t *mask);
qboolean FTENET_AddToCollection(struct ftenet_connections_s *col, const char *name, const char *address, netadrtype_t addrtype, netproto_t addrprot); qboolean FTENET_AddToCollection(struct ftenet_connections_s *col, const char *name, const char *address, netadrtype_t addrtype, netproto_t addrprot);
enum certprops_e
{
QCERT_PEERFINGERPRINT
};
size_t NET_GetConnectionCertificate(struct ftenet_connections_s *col, netadr_t *a, enum certprops_e prop, char *out, size_t outsize);
#ifdef HAVE_DTLS #ifdef HAVE_DTLS
qboolean NET_DTLS_Create(struct ftenet_connections_s *col, netadr_t *to); qboolean NET_DTLS_Create(struct ftenet_connections_s *col, netadr_t *to);
qboolean NET_DTLS_Decode(struct ftenet_connections_s *col); qboolean NET_DTLS_Decode(struct ftenet_connections_s *col);

View file

@ -2715,6 +2715,37 @@ qboolean NET_DTLS_Decode(ftenet_connections_t *col)
#endif #endif
size_t NET_GetConnectionCertificate(struct ftenet_connections_s *col, netadr_t *a, enum certprops_e prop, char *out, size_t outsize)
{
if (!col)
return 0;
switch(prop)
{
default:
break;
case QCERT_PEERFINGERPRINT:
#if 0//def HAVE_DTLS
if (a->prot == NP_DTLS)
{
struct dtlspeer_s *peer;
{
a->prot = NP_DGRAM;
for (peer = col->dtls; peer; peer = peer->next)
{
if (NET_CompareAdr(&peer->addr, a))
break;
}
a->prot = NP_DTLS;
}
if (peer)
return peer->funcs->GetPeerCertificate(peer->dtlsstate, data, length);
}
#endif
return 0;
}
return 0;
}

View file

@ -308,6 +308,7 @@ typedef struct dtlsfuncs_s
neterr_t (*Transmit)(void *ctx, const qbyte *data, size_t datasize); neterr_t (*Transmit)(void *ctx, const qbyte *data, size_t datasize);
neterr_t (*Received)(void *ctx, qbyte *data, size_t datasize); neterr_t (*Received)(void *ctx, qbyte *data, size_t datasize);
neterr_t (*Timeouts)(void *ctx); neterr_t (*Timeouts)(void *ctx);
void (*GetPeerCertificate)(void *ctx);
} dtlsfuncs_t; } dtlsfuncs_t;
const dtlsfuncs_t *DTLS_InitServer(void); const dtlsfuncs_t *DTLS_InitServer(void);
const dtlsfuncs_t *DTLS_InitClient(void); const dtlsfuncs_t *DTLS_InitClient(void);

View file

@ -1640,10 +1640,10 @@ typedef struct
char *stringdata; char *stringdata;
}; };
} pf_hashentry_t; } pf_hashentry_t;
pf_hashtab_t *pf_hashtab; static pf_hashtab_t *pf_hashtab;
size_t pf_hash_maxtables; static size_t pf_hash_maxtables;
pf_hashtab_t pf_peristanthashtab; //persists over map changes. static pf_hashtab_t pf_peristanthashtab; //persists over map changes.
pf_hashtab_t pf_reverthashtab; //pf_peristanthashtab as it was at map start, for map restarts. //static pf_hashtab_t pf_reverthashtab; //pf_peristanthashtab as it was at map start, for map restarts.
static pf_hashtab_t *PF_hash_findtab(pubprogfuncs_t *prinst, int idx) static pf_hashtab_t *PF_hash_findtab(pubprogfuncs_t *prinst, int idx)
{ {
idx -= 1; idx -= 1;
@ -1664,7 +1664,7 @@ static pf_hashtab_t *PF_hash_findtab(pubprogfuncs_t *prinst, int idx)
else else
PR_BIError(prinst, "PF_hash_findtab: invalid hash table\n"); PR_BIError(prinst, "PF_hash_findtab: invalid hash table\n");
return NULL; return NULL;
}; }
void QCBUILTIN PF_hash_getkey (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) void QCBUILTIN PF_hash_getkey (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{ {
@ -1734,10 +1734,10 @@ void QCBUILTIN PF_hash_get (pubprogfuncs_t *prinst, struct globalvars_s *pr_glob
} }
else else
memcpy(G_VECTOR(OFS_RETURN), ent->data, sizeof(vec3_t)); memcpy(G_VECTOR(OFS_RETURN), ent->data, sizeof(vec3_t));
return;
} }
else
memcpy(G_VECTOR(OFS_RETURN), dflt, sizeof(vec3_t));
} }
memcpy(G_VECTOR(OFS_RETURN), dflt, sizeof(vec3_t));
} }
void QCBUILTIN PF_hash_getcb (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) void QCBUILTIN PF_hash_getcb (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{ {
@ -1904,10 +1904,10 @@ typedef struct {
size_t bufferlen; size_t bufferlen;
size_t len; size_t len;
size_t ofs; size_t ofs;
int accessmode;
pubprogfuncs_t *prinst; pubprogfuncs_t *prinst;
long accessmode;
} pf_fopen_files_t; } pf_fopen_files_t;
pf_fopen_files_t pf_fopen_files[MAX_QC_FILES]; static pf_fopen_files_t pf_fopen_files[MAX_QC_FILES];
//returns false if the file is denied. //returns false if the file is denied.
//fallbackread can be NULL, if the qc is not allowed to read that (original) file at all. //fallbackread can be NULL, if the qc is not allowed to read that (original) file at all.

View file

@ -775,7 +775,9 @@ enum lightfield_e
lfield_rotation=13, lfield_rotation=13,
lfield_dietime=14, lfield_dietime=14,
lfield_rgbdecay=15, lfield_rgbdecay=15,
lfield_radiusdecay=16 lfield_radiusdecay=16,
lfield_stylestring=17
}; };
enum csqc_input_event enum csqc_input_event
{ {

View file

@ -2199,7 +2199,15 @@ struct bspx_header_s {
}; };
//supported lumps: //supported lumps:
//RGBLIGHTING (.lit) //RGBLIGHTING (.lit)
//LIGHTING_E5BGR9 (hdr lit)
//LIGHTINGDIR (.lux) //LIGHTINGDIR (.lux)
//LMSHIFT (lightmap scaling)
//LMOFFSET (lightmap scaling)
//LMSTYLE (lightmap scaling)
//VERTEXNORMALS (smooth specular)
//BRUSHLIST (no hull size issues)
//ENVMAP (cubemaps)
//SURFENVMAP (cubemaps)
void *BSPX_FindLump(bspx_header_t *bspxheader, void *mod_base, char *lumpname, int *lumpsize) void *BSPX_FindLump(bspx_header_t *bspxheader, void *mod_base, char *lumpname, int *lumpsize)
{ {
int i; int i;
@ -2424,11 +2432,11 @@ void BSPX_LoadEnvmaps(model_t *mod, bspx_header_t *bspx, void *mod_base)
struct bspxrw struct bspxrw
{ {
fromgame_t fg;
const char *fname; const char *fname;
char *origfile; char *origfile;
qofs_t origsize; qofs_t origsize;
int lumpofs; int lumpofs;
fromgame_t fg;
size_t corelumps; size_t corelumps;
size_t totallumps; size_t totallumps;

View file

@ -240,7 +240,7 @@ static void memxor(char *dest, const char *src, size_t length)
} }
} }
typedef size_t hashfunc_t(unsigned char *digest, size_t maxdigestsize, size_t numstrings, const unsigned char **strings, size_t *stringlens); //typedef size_t hashfunc_t(unsigned char *digest, size_t maxdigestsize, size_t numstrings, const unsigned char **strings, size_t *stringlens);
size_t HMAC(hashfunc_t *hashfunc, unsigned char *digest, size_t maxdigestsize, size_t HMAC(hashfunc_t *hashfunc, unsigned char *digest, size_t maxdigestsize,
const unsigned char *data, size_t datalen, const unsigned char *data, size_t datalen,
const unsigned char *key, size_t keylen) const unsigned char *key, size_t keylen)

View file

@ -122,7 +122,9 @@ typedef struct q2trace_s
#define MOVE_NORMAL 0 #define MOVE_NORMAL 0
#define MOVE_NOMONSTERS (1<<0) #define MOVE_NOMONSTERS (1<<0)
#define MOVE_MISSILE (1<<1) #define MOVE_MISSILE (1<<1)
#define MOVE_WORLDONLY (MOVE_NOMONSTERS|MOVE_MISSILE) #ifndef NOLEGACY
#define MOVE_WORLDONLY (MOVE_NOMONSTERS|MOVE_MISSILE) //use MOVE_OTHERONLY instead
#endif
#define MOVE_HITMODEL (1<<2) #define MOVE_HITMODEL (1<<2)
#define MOVE_RESERVED (1<<3) //so we are less likly to get into tricky situations when we want to steal annother future DP extension. #define MOVE_RESERVED (1<<3) //so we are less likly to get into tricky situations when we want to steal annother future DP extension.
#define MOVE_TRIGGERS (1<<4) //triggers must be marked with FINDABLE_NONSOLID (an alternative to solid-corpse) #define MOVE_TRIGGERS (1<<4) //triggers must be marked with FINDABLE_NONSOLID (an alternative to solid-corpse)

View file

@ -3,11 +3,11 @@
#include "gl_draw.h" #include "gl_draw.h"
#ifdef D3D9QUAKE #ifdef D3D9QUAKE
#include "shader.h" #include "shader.h"
#include <d3d9.h>
#if !defined(HMONITOR_DECLARED) && (WINVER < 0x0500) #if !defined(HMONITOR_DECLARED) && (WINVER < 0x0500)
#define HMONITOR_DECLARED #define HMONITOR_DECLARED
DECLARE_HANDLE(HMONITOR); DECLARE_HANDLE(HMONITOR);
#endif #endif
#include <d3d9.h>
/* /*
Things to improve: Things to improve:

View file

@ -1127,7 +1127,7 @@ static qboolean (D3D9_SCR_UpdateScreen) (void)
if (uimenu != 1) if (uimenu != 1)
{ {
if (r_worldentity.model && cls.state == ca_active) if (r_worldentity.model && cls.state == ca_active)
V_RenderView (); V_RenderView (nohud);
else else
{ {
noworld = true; noworld = true;

View file

@ -1426,7 +1426,7 @@ static qboolean (D3D11_SCR_UpdateScreen) (void)
if (uimenu != 1) if (uimenu != 1)
{ {
if (r_worldentity.model && cls.state == ca_active) if (r_worldentity.model && cls.state == ca_active)
V_RenderView (); V_RenderView (nohud);
else else
{ {
noworld = true; noworld = true;

View file

@ -1079,16 +1079,19 @@ qboolean GLBE_BeginShadowMap(int id, int w, int h, int *restorefbo)
if (!TEXVALID(shadowmap[id])) if (!TEXVALID(shadowmap[id]))
{ {
shadowmap[id] = Image_CreateTexture(va("***shadowmap2d%i***", id), NULL, 0); uploadfmt_t encoding = PTI_DEPTH32;
qglGenTextures(1, &shadowmap[id]->num); texid_t tex = shadowmap[id] = Image_CreateTexture(va("***shadowmap2d%i***", id), NULL, 0);
GL_MTBind(0, GL_TEXTURE_2D, shadowmap[id]); qglGenTextures(1, &tex->num);
GL_MTBind(0, GL_TEXTURE_2D, tex);
#ifdef SHADOWDBG_COLOURNOTDEPTH #ifdef SHADOWDBG_COLOURNOTDEPTH
qglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); qglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
#else #else
if (gl_config.gles) if (qglTexStorage2D)
qglTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, w, h, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, NULL); qglTexStorage2D(GL_TEXTURE_2D, 1, gl_config.formatinfo[encoding].sizedformat, w, h);
else if (gl_config.formatinfo[encoding].type)
qglTexImage2D (GL_TEXTURE_2D, 0, gl_config.formatinfo[encoding].sizedformat, w, h, 0, gl_config.formatinfo[encoding].format, gl_config.formatinfo[encoding].type, NULL);
else else
qglTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16_ARB, w, h, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, NULL); qglCompressedTexImage2D (GL_TEXTURE_2D, 0, gl_config.formatinfo[encoding].sizedformat, w, h, 0, 0, NULL);
#endif #endif
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
@ -1614,7 +1617,16 @@ void GLBE_Init(void)
gl_overbright.modified = true; /*in case the d3d renderer does the same*/ gl_overbright.modified = true; /*in case the d3d renderer does the same*/
/*lock the cvar down if the backend can't actually do it*/ /*lock the cvar down if the backend can't actually do it*/
if (!gl_config.tex_env_combine && !gl_config_nofixedfunc && gl_overbright.ival) if (
#if 1//defined(QUAKETC)
//TCs are expected to be using glsl and weird overbright things etc, don't take the risk.
(!sh_config.progs_supported)
#else
//Q3 can get away with tex_env_combine for everything, if only because the content allows everything to be flattened to a single pass if needed...
//some shaders might screw up from our approach though...
(!gl_config.tex_env_combine && !gl_config_nofixedfunc)
#endif
&& gl_overbright.ival)
Cvar_ApplyLatchFlag(&gl_overbright, "0", CVAR_RENDERERLATCH); Cvar_ApplyLatchFlag(&gl_overbright, "0", CVAR_RENDERERLATCH);
shaderstate.shaderbits = ~SBITS_ATEST_BITS; shaderstate.shaderbits = ~SBITS_ATEST_BITS;
BE_SendPassBlendDepthMask(0); BE_SendPassBlendDepthMask(0);

View file

@ -43,8 +43,6 @@ static int gl_filter_mip[3]; //everything else
int gl_mipcap_min = 0; int gl_mipcap_min = 0;
int gl_mipcap_max = 1000; int gl_mipcap_max = 1000;
void Image_WriteKTXFile(const char *filename, struct pendingtextureinfo *mips);
void GL_DestroyTexture(texid_t tex) void GL_DestroyTexture(texid_t tex)
{ {
if (!tex) if (!tex)
@ -964,7 +962,7 @@ qboolean GL_LoadTextureMips(texid_t tex, const struct pendingtextureinfo *mips)
if (i) if (i)
{ {
out.mipcount = i; out.mipcount = i;
Image_WriteKTXFile(va("textures/%s.ktx", tex->ident), &out); Image_WriteKTXFile(va("textures/%s.ktx", tex->ident), FS_GAMEONLY, &out);
} }
while (i-- > 0) while (i-- > 0)
if (out.mip[i].needfree) if (out.mip[i].needfree)

View file

@ -1750,15 +1750,26 @@ static texid_t Font_LoadFallbackConchars(void)
Font_CopyGlyph('[', 128, lump); Font_CopyGlyph('[', 128, lump);
Font_CopyGlyph('-', 129, lump); Font_CopyGlyph('-', 129, lump);
Font_CopyGlyph(']', 130, lump); Font_CopyGlyph(']', 130, lump);
Font_CopyGlyph('o', 131, lump); Font_CopyGlyph('|', 131, lump);
Font_CopyGlyph('>', 13, lump);
} }
tex = R_LoadTexture32("charset", width, height, (void*)lump, IF_PREMULTIPLYALPHA|IF_LOADNOW|IF_UIPIC|IF_NOMIPMAP|IF_NOGAMMA); tex = R_LoadTexture32("charset", width, height, (void*)lump, IF_PREMULTIPLYALPHA|IF_LOADNOW|IF_UIPIC|IF_NOMIPMAP|IF_NOGAMMA);
BZ_Free(lump); BZ_Free(lump);
return tex; return tex;
} }
enum fontfmt_e
{
FMT_AUTO, //freetype, or quake
FMT_QUAKE, //first is default
FMT_ISO88591, //latin-1 (first 256 chars of unicode too, c1 glyphs are usually invisible)
FMT_WINDOWS1252,//variation of latin-1 with extra glyphs
FMT_KOI8U, //image is 16*16 koi8-u codepage.
FMT_HORIZONTAL, //unicode, charcount=width/(height-2). single strip of chars, like halflife.
};
/*loads a fallback image. not allowed to fail (use syserror if needed)*/ /*loads a fallback image. not allowed to fail (use syserror if needed)*/
static texid_t Font_LoadDefaultConchars(void) static texid_t Font_LoadDefaultConchars(enum fontfmt_e *fmt)
{ {
texid_t tex; texid_t tex;
tex = Font_LoadReplacementConchars(); tex = Font_LoadReplacementConchars();
@ -1774,13 +1785,19 @@ static texid_t Font_LoadDefaultConchars(void)
if (tex && tex->status == TEX_LOADING) if (tex && tex->status == TEX_LOADING)
COM_WorkerPartialSync(tex, &tex->status, TEX_LOADING); COM_WorkerPartialSync(tex, &tex->status, TEX_LOADING);
if (TEXLOADED(tex)) if (TEXLOADED(tex))
{
*fmt = FMT_ISO88591;
return tex; return tex;
}
#endif #endif
tex = Font_LoadFallbackConchars(); tex = Font_LoadFallbackConchars();
if (tex && tex->status == TEX_LOADING) if (tex && tex->status == TEX_LOADING)
COM_WorkerPartialSync(tex, &tex->status, TEX_LOADING); COM_WorkerPartialSync(tex, &tex->status, TEX_LOADING);
if (TEXLOADED(tex)) if (TEXLOADED(tex))
{
*fmt = FMT_QUAKE;
return tex; return tex;
}
Sys_Error("Unable to load any conchars\n"); Sys_Error("Unable to load any conchars\n");
} }
@ -1838,15 +1855,7 @@ struct font_s *Font_LoadFont(const char *fontfilename, float vheight)
char facename[MAX_QPATH*12]; char facename[MAX_QPATH*12];
struct charcache_s *c; struct charcache_s *c;
float aspect = 1; float aspect = 1;
enum enum fontfmt_e fmt = FMT_AUTO;
{
FMT_AUTO, //freetype, or quake
FMT_QUAKE, //first is default
FMT_ISO88591, //latin-1 (first 256 chars of unicode too, c1 glyphs are usually invisible)
FMT_WINDOWS1252,//variation of latin-1 with extra glyphs
FMT_KOI8U, //image is 16*16 koi8-u codepage.
FMT_HORIZONTAL, //unicode, charcount=width/(height-2). single strip of chars, like halflife.
} fmt = FMT_AUTO;
Q_strncpyz(facename, fontfilename, sizeof(facename)); Q_strncpyz(facename, fontfilename, sizeof(facename));
@ -2155,7 +2164,7 @@ struct font_s *Font_LoadFont(const char *fontfilename, float vheight)
{ {
if (!TEXLOADED(fontplanes.defaultfont)) if (!TEXLOADED(fontplanes.defaultfont))
{ {
fontplanes.defaultfont = Font_LoadDefaultConchars(); fontplanes.defaultfont = Font_LoadDefaultConchars(&fmt);
} }
#ifdef HEXEN2 #ifdef HEXEN2

View file

@ -1997,23 +1997,26 @@ void Mod_LoadLighting (model_t *loadmodel, bspx_header_t *bspx, qbyte *mod_base,
#endif #endif
#ifdef RUNTIMELIGHTING #ifdef RUNTIMELIGHTING
if (!lightmodel && r_loadlits.value == 2 && (!litdata || (!luxdata && r_deluxemapping))) if ((loadmodel->type == mod_brush && loadmodel->fromgame == fg_quake) || loadmodel->type == mod_heightmap)
{ { //we only support a couple of formats. :(
writelitfile = !litdata; if (!lightmodel && r_loadlits.value == 2 && (!litdata || (!luxdata && r_deluxemapping)))
numlightdata = l->filelen; {
lightmodel = loadmodel; writelitfile = !litdata;
relitsurface = 0; numlightdata = l->filelen;
} lightmodel = loadmodel;
else if (!lightmodel && r_deluxemapping_cvar.value>1 && r_deluxemapping && !luxdata relitsurface = 0;
}
else if (!lightmodel && r_deluxemapping_cvar.value>1 && r_deluxemapping && !luxdata
#ifdef RTLIGHTS #ifdef RTLIGHTS
&& !(r_shadow_realtime_world.ival && r_shadow_realtime_world_lightmaps.value<=0) && !(r_shadow_realtime_world.ival && r_shadow_realtime_world_lightmaps.value<=0)
#endif #endif
) )
{ //if deluxemapping is on, generate missing lux files a little more often, but don't bother if we have rtlights on anyway. { //if deluxemapping is on, generate missing lux files a little more often, but don't bother if we have rtlights on anyway.
writelitfile = false; writelitfile = false;
numlightdata = l->filelen; numlightdata = l->filelen;
lightmodel = loadmodel; lightmodel = loadmodel;
relitsurface = 0; relitsurface = 0;
}
} }
/*if we're relighting, make sure there's the proper lit data to be updated*/ /*if we're relighting, make sure there's the proper lit data to be updated*/

View file

@ -27,7 +27,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
extern cvar_t r_shadow_realtime_world, r_shadow_realtime_world_lightmaps; extern cvar_t r_shadow_realtime_world, r_shadow_realtime_world_lightmaps;
extern cvar_t r_hdr_irisadaptation, r_hdr_irisadaptation_multiplier, r_hdr_irisadaptation_minvalue, r_hdr_irisadaptation_maxvalue, r_hdr_irisadaptation_fade_down, r_hdr_irisadaptation_fade_up; extern cvar_t r_hdr_irisadaptation, r_hdr_irisadaptation_multiplier, r_hdr_irisadaptation_minvalue, r_hdr_irisadaptation_maxvalue, r_hdr_irisadaptation_fade_down, r_hdr_irisadaptation_fade_up;
int r_dlightframecount; int r_dlightframecount;
int d_lightstylevalue[256]; // 8.8 fraction of base light value int d_lightstylevalue[256]; // 8.8 fraction of base light value
@ -363,9 +362,6 @@ void R_RenderDlights (void)
if (!r_coronas.value && !r_flashblend.value) if (!r_coronas.value && !r_flashblend.value)
return; return;
// r_dlightframecount = r_framecount + 1; // because the count hasn't
// advanced yet for this frame
l = cl_dlights+rtlights_first; l = cl_dlights+rtlights_first;
for (i=rtlights_first; i<rtlights_max; i++, l++) for (i=rtlights_first; i<rtlights_max; i++, l++)
{ {
@ -734,6 +730,25 @@ void R_PushDlights (void)
//rtlight loading //rtlight loading
#ifdef RTLIGHTS #ifdef RTLIGHTS
//These affect importing
static cvar_t r_editlights_import_radius = CVARAD ("r_editlights_import_radius", "1", "r_editlights_quakelightsizescale", "changes size of light entities loaded from a map");
static cvar_t r_editlights_import_ambient = CVARD ("r_editlights_import_ambient", "0", "ambient light scaler for imported lights");
static cvar_t r_editlights_import_diffuse = CVARD ("r_editlights_import_diffuse", "1", "diffuse light scaler for imported lights");
static cvar_t r_editlights_import_specular = CVARD ("r_editlights_import_specular", "1", "specular light scaler for imported lights"); //excessive, but noticable. its called stylized, okay? shiesh, some people
//these are just for the crappy editor
static cvar_t r_editlights = CVARD ("r_editlights", "0", "enables .rtlights file editing mode. Consider using csaddon/equivelent instead.");
static cvar_t r_editlights_cursordistance = CVARD ("r_editlights_cursordistance", "1024", "maximum distance of cursor from eye");
static cvar_t r_editlights_cursorpushoff = CVARD ("r_editlights_cursorpushoff", "4", "how far to push the cursor off the impacted surface");
static cvar_t r_editlights_cursorpushback = CVARD ("r_editlights_cursorpushback", "0", "how far to pull the cursor back toward the eye, for some reason");
static cvar_t r_editlights_cursorgrid = CVARD ("r_editlights_cursorgrid", "1", "snaps cursor to this grid size");
//internal settings
static qboolean r_editlights_locked = false; //don't change the selected light
static int r_editlights_selected = -1; //the light closest to the cursor
static vec3_t r_editlights_cursor; //the position of the crosshair/cursor (new lights will be spawned here)
static dlight_t r_editlights_copybuffer; //written by r_editlights_copyinfo, read by r_editlights_pasteinfo. FIXME: use system clipboard?
qboolean R_ImportRTLights(const char *entlump) qboolean R_ImportRTLights(const char *entlump)
{ {
typedef enum lighttype_e {LIGHTTYPE_MINUSX, LIGHTTYPE_RECIPX, LIGHTTYPE_RECIPXX, LIGHTTYPE_INFINITE, LIGHTTYPE_LOCALMIN, LIGHTTYPE_RECIPXX2, LIGHTTYPE_SUN} lighttype_t; typedef enum lighttype_e {LIGHTTYPE_MINUSX, LIGHTTYPE_RECIPX, LIGHTTYPE_RECIPXX, LIGHTTYPE_INFINITE, LIGHTTYPE_LOCALMIN, LIGHTTYPE_RECIPXX2, LIGHTTYPE_SUN} lighttype_t;
@ -1103,7 +1118,8 @@ qboolean R_ImportRTLights(const char *entlump)
break; break;
VectorCopy(origin, dl->origin); VectorCopy(origin, dl->origin);
AngleVectors(angles, dl->axis[0], dl->axis[1], dl->axis[2]); VectorCopy(angles, dl->angles);
AngleVectors(dl->angles, dl->axis[0], dl->axis[1], dl->axis[2]);
VectorInverse(dl->axis[1]); VectorInverse(dl->axis[1]);
dl->radius = radius; dl->radius = radius;
VectorCopy(color, dl->color); VectorCopy(color, dl->color);
@ -1121,7 +1137,8 @@ qboolean R_ImportRTLights(const char *entlump)
if (!dl->fov) //default is 40, supposedly if (!dl->fov) //default is 40, supposedly
dl->fov = 40; dl->fov = 40;
AngleVectors(mangle, dl->axis[0], dl->axis[1], dl->axis[2]); VectorCopy(mangle, dl->angles);
AngleVectors(dl->angles, dl->axis[0], dl->axis[1], dl->axis[2]);
VectorInverse(dl->axis[1]); VectorInverse(dl->axis[1]);
} }
else if (*target) else if (*target)
@ -1138,6 +1155,10 @@ qboolean R_ImportRTLights(const char *entlump)
VectorVectors(dl->axis[0], dl->axis[1], dl->axis[2]); VectorVectors(dl->axis[0], dl->axis[1], dl->axis[2]);
VectorInverse(dl->axis[1]); VectorInverse(dl->axis[1]);
//we don't have any control over the inner cone. //we don't have any control over the inner cone.
//so queries work properly
VectorAngles(dl->axis[0], dl->axis[2], dl->angles, false);
dl->angles[0] = anglemod(dl->angles[0]);
} }
} }
@ -1158,6 +1179,7 @@ qboolean R_LoadRTLights(void)
dlight_t *dl; dlight_t *dl;
char fname[MAX_QPATH]; char fname[MAX_QPATH];
char cubename[MAX_QPATH]; char cubename[MAX_QPATH];
char customstyle[1024];
char *file; char *file;
char *end; char *end;
int style; int style;
@ -1273,6 +1295,7 @@ qboolean R_LoadRTLights(void)
flags |= file?atoi(com_token):LFLAG_REALTIMEMODE; flags |= file?atoi(com_token):LFLAG_REALTIMEMODE;
fov = avel[0] = avel[1] = avel[2] = 0; fov = avel[0] = avel[1] = avel[2] = 0;
*customstyle = 0;
while(file) while(file)
{ {
file = COM_Parse(file); file = COM_Parse(file);
@ -1284,6 +1307,16 @@ qboolean R_LoadRTLights(void)
avel[2] = file?atof(com_token+5):0; avel[2] = file?atof(com_token+5):0;
else if (!strncmp(com_token, "fov=", 4)) else if (!strncmp(com_token, "fov=", 4))
fov = file?atof(com_token+4):0; fov = file?atof(com_token+4):0;
else if (!strncmp(com_token, "nostencil=", 10))
flags |= atoi(com_token+10)?LFLAG_SHADOWMAP:0;
else if (!strncmp(com_token, "crepuscular=", 12))
flags |= atoi(com_token+12)?LFLAG_CREPUSCULAR:0;
else if (!strncmp(com_token, "ortho=", 6))
flags |= atoi(com_token+6)?LFLAG_ORTHO:0;
else if (!strncmp(com_token, "stylestring=", 12))
Q_strncpyz(customstyle, com_token+12, sizeof(customstyle));
else if (file)
Con_DPrintf("Unknown .rtlights arg \"%s\"\n", com_token);
} }
if (radius) if (radius)
@ -1313,13 +1346,14 @@ qboolean R_LoadRTLights(void)
dl->cubetexture = r_nulltex; dl->cubetexture = r_nulltex;
dl->style = style+1; dl->style = style+1;
dl->customstyle = (*customstyle)?Z_StrDup(customstyle):NULL;
} }
file = end+1; file = end+1;
} }
return !!file; return !!file;
} }
void R_SaveRTLights_f(void) static void R_SaveRTLights_f(void)
{ {
dlight_t *light; dlight_t *light;
vfsfile_t *f; vfsfile_t *f;
@ -1327,6 +1361,7 @@ void R_SaveRTLights_f(void)
char fname[MAX_QPATH]; char fname[MAX_QPATH];
char sysname[MAX_OSPATH]; char sysname[MAX_OSPATH];
vec3_t ang; vec3_t ang;
int ver = 0;
COM_StripExtension(cl.worldmodel->name, fname, sizeof(fname)); COM_StripExtension(cl.worldmodel->name, fname, sizeof(fname));
strncat(fname, ".rtlights", MAX_QPATH-1); strncat(fname, ".rtlights", MAX_QPATH-1);
@ -1347,24 +1382,46 @@ void R_SaveRTLights_f(void)
if (!light->radius) if (!light->radius)
continue; continue;
VectorAngles(light->axis[0], light->axis[2], ang, false); VectorAngles(light->axis[0], light->axis[2], ang, false);
VFS_PUTS(f, va(
//the .rtlights format is defined by DP, the first few parts cannot be changed without breaking wider compat.
//it got extended a few times. only write what we need for greater compat, just in case.
if ((light->flags & (LFLAG_SHADOWMAP|LFLAG_CREPUSCULAR|LFLAG_ORTHO)) || light->rotation[0] || light->rotation[1] || light->rotation[2] || light->fov || light->customstyle)
ver = 2; //one of our own flags. always spew the full DP stuff to try to avoid confusion
else if (light->coronascale!=0.25 || light->lightcolourscales[0]!=0 || light->lightcolourscales[1]!=1 || light->lightcolourscales[2]!=1 || (light->flags&~LFLAG_NOSHADOWS) != LFLAG_REALTIMEMODE)
ver = 2;
else if (*light->cubemapname || light->corona || ang[0] || ang[1] || ang[2])
ver = 1;
else
ver = 0;
VFS_PRINTF(f,
"%s%f %f %f " "%s%f %f %f "
"%f %f %f %f " "%f %f %f %f "
"%i " "%i",
"\"%s\" %f "
"%f %f %f "
"%f %f %f %f %i "
"rotx=%g roty=%g rotz=%g fov=%g "
"\n"
,
(light->flags & LFLAG_NOSHADOWS)?"!":"", light->origin[0], light->origin[1], light->origin[2], (light->flags & LFLAG_NOSHADOWS)?"!":"", light->origin[0], light->origin[1], light->origin[2],
light->radius, light->color[0], light->color[1], light->color[2], light->radius, light->color[0], light->color[1], light->color[2],
light->style-1, light->style-1);
light->cubemapname, light->corona, if (ver > 0)
ang[0], ang[1], ang[2], VFS_PRINTF(f, " \"%s\" %f %f %f %f", light->cubemapname, light->corona, ang[0], ang[1], ang[2]);
light->coronascale, light->lightcolourscales[0], light->lightcolourscales[1], light->lightcolourscales[2], light->flags&~(LFLAG_NOSHADOWS|LFLAG_INTERNAL), if (ver > 1)
light->rotation[0],light->rotation[1],light->rotation[2],light->fov VFS_PRINTF(f, " %f %f %f %f %i", light->coronascale, light->lightcolourscales[0], light->lightcolourscales[1], light->lightcolourscales[2], light->flags&(LFLAG_NORMALMODE|LFLAG_REALTIMEMODE));
));
//our weird flags
if (light->flags&LFLAG_SHADOWMAP)
VFS_PRINTF(f, " nostencil=1");
if (light->flags&LFLAG_CREPUSCULAR)
VFS_PRINTF(f, " crepuscular=1");
if (light->flags&LFLAG_ORTHO)
VFS_PRINTF(f, " ortho=1");
//spinning lights (for cubemaps)
if (light->rotation[0] || light->rotation[1] || light->rotation[2])
VFS_PRINTF(f, " rotx=%g roty=%g rotz=%g", light->rotation[0],light->rotation[1],light->rotation[2]);
//spotlights
if (light->fov)
VFS_PRINTF(f, " fov=%g", light->fov); //aka: outer cone
if (light->customstyle)
VFS_PRINTF(f, " \"stylestring=%s\"", light->customstyle); //aka: outer cone
VFS_PUTS(f, "\n");
} }
VFS_CLOSE(f); VFS_CLOSE(f);
@ -1412,7 +1469,7 @@ void R_StaticEntityToRTLight(int i)
R_LoadNumberedLightTexture(dl, state->skinnum); R_LoadNumberedLightTexture(dl, state->skinnum);
} }
void R_ReloadRTLights_f(void) static void R_ReloadRTLights_f(void)
{ {
int i; int i;
@ -1427,19 +1484,800 @@ void R_ReloadRTLights_f(void)
R_ImportRTLights(Mod_GetEntitiesString(cl.worldmodel)); R_ImportRTLights(Mod_GetEntitiesString(cl.worldmodel));
else if (!strcmp(Cmd_Argv(1), "rtlights")) else if (!strcmp(Cmd_Argv(1), "rtlights"))
R_LoadRTLights(); R_LoadRTLights();
else if (!strcmp(Cmd_Argv(1), "statics"))
{
for (i = 0; i < cl.num_statics; i++)
R_StaticEntityToRTLight(i);
}
else if (!strcmp(Cmd_Argv(1), "none")) else if (!strcmp(Cmd_Argv(1), "none"))
; ;
else else
{ {
R_LoadRTLights(); //try to load .rtlights file
if (rtlights_first == rtlights_max)
R_LoadRTLights();
//if there's a static entity with rtlights set, then assume the mod is taking care of it for us.
if (rtlights_first == rtlights_max)
for (i = 0; i < cl.num_statics; i++)
R_StaticEntityToRTLight(i);
//otherwise try to import.
if (rtlights_first == rtlights_max) if (rtlights_first == rtlights_max)
R_ImportRTLights(Mod_GetEntitiesString(cl.worldmodel)); R_ImportRTLights(Mod_GetEntitiesString(cl.worldmodel));
} }
}
for (i = 0; i < cl.num_statics; i++) //-1 for arg error
static int R_EditLight(dlight_t *dl, const char *cmd, int argc, const char *x, const char *y, const char *z)
{
if (argc == 1)
{ {
R_StaticEntityToRTLight(i); y = x;
z = x;
} }
if (!strcmp(cmd, "origin"))
{
dl->origin[0] = atof(x);
dl->origin[1] = atof(y);
dl->origin[2] = atof(z);
}
else if (!strcmp(cmd, "originscale"))
{
dl->origin[0] *= atof(x);
dl->origin[1] *= atof(y);
dl->origin[2] *= atof(z);
}
else if (!strcmp(cmd, "originx"))
dl->origin[0] = atof(x);
else if (!strcmp(cmd, "originy"))
dl->origin[1] = atof(x);
else if (!strcmp(cmd, "originz"))
dl->origin[2] = atof(x);
else if (!strcmp(cmd, "move"))
{
dl->origin[0] += atof(x);
dl->origin[1] += atof(y);
dl->origin[2] += atof(z);
}
else if (!strcmp(cmd, "movex"))
dl->origin[0] += atof(x);
else if (!strcmp(cmd, "movey"))
dl->origin[1] += atof(x);
else if (!strcmp(cmd, "movez"))
dl->origin[2] += atof(x);
else if (!strcmp(cmd, "angles"))
{
dl->angles[0] = atof(x);
dl->angles[1] = atof(y);
dl->angles[2] = atof(z);
AngleVectors(dl->angles, dl->axis[0], dl->axis[1], dl->axis[2]);
VectorInverse(dl->axis[1]);
}
else if (!strcmp(cmd, "anglesx"))
{
dl->angles[0] = atof(x);
AngleVectors(dl->angles, dl->axis[0], dl->axis[1], dl->axis[2]);
VectorInverse(dl->axis[1]);
}
else if (!strcmp(cmd, "anglesy"))
{
dl->angles[1] = atof(x);
AngleVectors(dl->angles, dl->axis[0], dl->axis[1], dl->axis[2]);
VectorInverse(dl->axis[1]);
}
else if (!strcmp(cmd, "anglesz"))
{
dl->angles[2] = atof(x);
AngleVectors(dl->angles, dl->axis[0], dl->axis[1], dl->axis[2]);
VectorInverse(dl->axis[1]);
}
else if (!strcmp(cmd, "avel"))
{
dl->rotation[0] = atof(x);
dl->rotation[1] = atof(y);
dl->rotation[2] = atof(z);
}
else if (!strcmp(cmd, "avelx"))
dl->rotation[0] = atof(x);
else if (!strcmp(cmd, "avey"))
dl->rotation[1] = atof(x);
else if (!strcmp(cmd, "avelz"))
dl->rotation[2] = atof(x);
else if (!strcmp(cmd, "outercone") || !strcmp(cmd, "fov"))
dl->fov = atof(x);
else if (!strcmp(cmd, "color") || !strcmp(cmd, "colour"))
{
dl->color[0] = atof(x);
dl->color[1] = atof(y);
dl->color[2] = atof(z);
}
else if (!strcmp(cmd, "colorscale") || !strcmp(cmd, "colourscale"))
{
dl->color[0] *= atof(x);
dl->color[1] *= atof(y);
dl->color[2] *= atof(z);
}
else if (!strcmp(cmd, "radius"))
dl->radius = atof(x);
else if (!strcmp(cmd, "radiusscale") || !strcmp(cmd, "sizescale"))
dl->radius *= atof(x);
else if (!strcmp(cmd, "style"))
dl->style = atoi(x)+1; //fte's styles are internally 1-based, with 0 being a null style that ignores lightstyles entirely, which admittedly isn't often used.
else if (!strcmp(cmd, "stylestring"))
{
Z_Free(dl->customstyle);
dl->customstyle = x?Z_StrDup(x):NULL;
}
else if (!strcmp(cmd, "cubemap"))
{
Q_strncpyz(dl->cubemapname, x, sizeof(dl->cubemapname));
if (*dl->cubemapname)
dl->cubetexture = R_LoadReplacementTexture(dl->cubemapname, "", IF_CUBEMAP, NULL, 0, 0, TF_INVALID);
else
dl->cubetexture = r_nulltex;
}
else if (!strcmp(cmd, "shadows"))
dl->flags = (dl->flags&~LFLAG_NOSHADOWS) | ((*x=='y'||*x=='Y'||*x=='t'||atoi(x))?0:LFLAG_NOSHADOWS);
else if (!strcmp(cmd, "nostencil"))
dl->flags = (dl->flags&~LFLAG_SHADOWMAP) | ((*x=='y'||*x=='Y'||*x=='t'||atoi(x))?0:LFLAG_SHADOWMAP);
else if (!strcmp(cmd, "crepuscular"))
dl->flags = (dl->flags&~LFLAG_CREPUSCULAR) | ((*x=='y'||*x=='Y'||*x=='t'||atoi(x))?LFLAG_CREPUSCULAR:0);
else if (!strcmp(cmd, "ortho"))
dl->flags = (dl->flags&~LFLAG_ORTHO) | ((*x=='y'||*x=='Y'||*x=='t'||atoi(x))?LFLAG_ORTHO:0);
else if (!strcmp(cmd, "corona"))
dl->corona = atof(x);
else if (!strcmp(cmd, "coronasize"))
dl->coronascale = atof(x);
else if (!strcmp(cmd, "ambient"))
dl->lightcolourscales[0] = atof(x);
else if (!strcmp(cmd, "diffuse"))
dl->lightcolourscales[1] = atof(x);
else if (!strcmp(cmd, "specular"))
dl->lightcolourscales[2] = atof(x);
else if (!strcmp(cmd, "normalmode"))
dl->flags = (dl->flags&~LFLAG_NORMALMODE) | ((*x=='y'||*x=='Y'||*x=='t'||atoi(x))?LFLAG_NORMALMODE:0);
else if (!strcmp(cmd, "realtimemode"))
dl->flags = (dl->flags&~LFLAG_REALTIMEMODE) | ((*x=='y'||*x=='Y'||*x=='t'||atoi(x))?LFLAG_REALTIMEMODE:0);
else
return -2;
dl->rebuildcache = true; //mneh, lets just flag it for everything.
return 1;
}
void R_EditLights_DrawInfo(void)
{
float fontscale[2] = {8,8};
float x = vid.width - 320;
float y = 0;
const char *s;
if (!r_editlights.ival)
return;
if (r_editlights_selected >= RTL_FIRST && r_editlights_selected < rtlights_max)
{
dlight_t *dl = &cl_dlights[r_editlights_selected];
s = va( " Origin : %.0f %.0f %.0f\n"
" Angles : %.0f %.0f %.0f\n"
" Colour : %.2f %.2f %.2f\n"
" Radius : %.0f\n"
" Corona : %.0f\n"
" Style : %i\n"
"Style String : %s\n"
" Shadows : %s\n"
" Cubemap : \"%s\"\n"
" CoronaSize : %.2f\n"
" Ambient : %.2f\n"
" Diffuse : %.2f\n"
" Specular : %.2f\n"
" NormalMode : %s\n"
"RealTimeMode : %s\n"
" Spin : %.0f %.0f %.0f\n"
" Cone : %.0f\n"
//"NoStencil : %s\n"
//"Crepuscular : %s\n"
//"Ortho : %s\n"
,dl->origin[0],dl->origin[1],dl->origin[2]
,dl->angles[0],dl->angles[1],dl->angles[2]
,dl->color[0],dl->color[1],dl->color[2]
,dl->radius, dl->corona, dl->style-1, dl->customstyle?dl->customstyle:"---"
,((dl->flags&LFLAG_NOSHADOWS)?"no":"yes"), dl->cubemapname, dl->coronascale
,dl->lightcolourscales[0], dl->lightcolourscales[1], dl->lightcolourscales[2]
,((dl->flags&LFLAG_NORMALMODE)?"yes":"no"), ((dl->flags&LFLAG_REALTIMEMODE)?"yes":"no")
,dl->rotation[0],dl->rotation[1],dl->rotation[2], dl->fov
//,((dl->flags&LFLAG_SHADOWMAP)?"no":"yes"),((dl->flags&LFLAG_CREPUSCULAR)?"yes":"no"),((dl->flags&LFLAG_ORTHO)?"yes":"no")
);
}
else
s = "No light selected";
R2D_ImageColours(0,0,0,.35);
R2D_FillBlock(x-4, y, 320+4, 16*8+4);
R2D_ImageColours(1,1,1,1);
R_DrawTextField(x, y, 320, 16*8, s, CON_WHITEMASK, CPRINT_LALIGN|CPRINT_TALIGN|CPRINT_NOWRAP, font_default, fontscale);
}
void R_EditLights_DrawLights(void)
{
const float SPRITE_SIZE = 8;
int i;
dlight_t *l;
enum
{
// ELS_CURSOR,
ELS_SELECTED,
ELS_LIGHT,
ELS_NOSHADOW,
ELS_MAX
};
char *lightshaderinfo[] =
{
/* "gfx/editlights/cursor",
".59..95."
"59....95"
"9.9..9.9"
"...99..."
"...99..."
"9.9..9.9"
"59....95"
".59..95.",
*/
"gfx/editlights/selected",
"999..999"
"99....99"
"9......9"
"........"
"........"
"9......9"
"99....99"
"999..999",
"gfx/editlights/light",
"..1221.."
".245542."
"14677641"
"25799752"
"25799752"
"14677641"
".245542."
"..1221..",
"gfx/editlights/noshadow",
"..1221.."
".245542."
"14644641"
"274..472" //mmm, donuts.
"274..472"
"14644641"
".247742."
"..1221..",
};
shader_t *shaders[ELS_MAX], *s;
unsigned int asciipalette[256];
asciipalette['.'] = 0;
for (i = 0; i < 10; i++)
asciipalette['0'+i] = 0xff000000 | ((int)(255/9.0*i)*0x010101);
if (!r_editlights.ival)
return;
for (i = 0; i < ELS_MAX; i++)
{
shaders[i] = R_RegisterShader(lightshaderinfo[i*2+0], SUF_NONE, va(
"{\n"
"program defaultadditivesprite\n"
"{\n"
"map $diffuse\n"
"blendfunc gl_one gl_one\n"
"rgbgen vertex\n"
"alphagen vertex\n"
"%s"
"}\n"
"}\n"
,(i==ELS_SELECTED)?"nodepth\n":"")
);
if (!shaders[i]->defaulttextures->base)
shaders[i]->defaulttextures->base = Image_GetTexture(shaders[i]->name, NULL, IF_LINEAR|IF_NOMIPMAP|IF_NOPICMIP|IF_CLAMP, lightshaderinfo[i*2+1], asciipalette, 8, 8, TF_8PAL32);
}
if (!r_editlights_locked)
{
vec3_t targ, norm;
int ent;
int best = -1;
float bestscore = 0, score;
VectorMA(r_refdef.vieworg, r_editlights_cursordistance.value, vpn, targ); //try to aim about 1024qu infront of the camera
CL_TraceLine(r_refdef.vieworg, targ, r_editlights_cursor, norm, &ent); //figure out where the cursor ends up
VectorMA(r_editlights_cursor, r_editlights_cursorpushoff.value, norm, r_editlights_cursor); //push off from the surface by 4qu.
VectorMA(r_editlights_cursor, -r_editlights_cursorpushback.value, vpn, r_editlights_cursor);//move it back towards the camera, for no apparent reason
if (r_editlights_cursorgrid.value)
{ //snap to a grid, if set
for (i =0; i < 3; i++)
r_editlights_cursor[i] = floor(r_editlights_cursor[i] / r_editlights_cursorgrid.value + 0.5) * r_editlights_cursorgrid.value;
}
// CLQ1_AddSpriteQuad(shaders[ELS_CURSOR], r_editlights_cursor, SPRITE_SIZE);
for (i=RTL_FIRST; i<rtlights_max; i++)
{
l = &cl_dlights[i];
if (!l->radius) //dead light is dead.
continue;
VectorSubtract(l->origin, r_refdef.vieworg, targ);
score = DotProduct(vpn, targ) / sqrt(DotProduct(targ,targ));
if (score >= .95) //there's a threshhold required for a light to be selectable.
{
//trace from the light to the view (so startsolid doesn't cause so many problems)
if (score > bestscore && CL_TraceLine(l->origin, r_refdef.vieworg, r_editlights_cursor, norm, &ent) == 1.0)
{
bestscore = score;
best = i;
}
}
}
r_editlights_selected = best;
}
for (i=RTL_FIRST; i<rtlights_max; i++)
{
l = &cl_dlights[i];
if (!l->radius) //dead light is dead.
continue;
//we should probably show spotlights with a special icon or something
//dp has alternate icons for cubemaps.
if (l->flags & LFLAG_NOSHADOWS)
s = shaders[ELS_NOSHADOW];
else
s = shaders[ELS_LIGHT];
CLQ1_AddSpriteQuad(s, l->origin, SPRITE_SIZE);
}
if (r_editlights_selected >= RTL_FIRST && r_editlights_selected < rtlights_max)
{
l = &cl_dlights[r_editlights_selected];
CLQ1_AddSpriteQuad(shaders[ELS_SELECTED], l->origin, SPRITE_SIZE);
}
}
static void R_EditLights_Edit_f(void)
{
int i = r_editlights_selected;
const char *cmd = Cmd_Argv(1);
const char *x = Cmd_Argv(2);
const char *y = Cmd_Argv(3);
const char *z = Cmd_Argv(4);
int argc = Cmd_Argc()-2;
dlight_t *dl;
if (!r_editlights.ival)
{
Con_Printf("Toggle r_editlights first\n");
return;
}
if (i < RTL_FIRST || i >= rtlights_max)
{
Con_Printf("No light selected\n");
return;
}
dl = &cl_dlights[i];
if (!*cmd)
{
Con_Print("Selected light's properties:\n");
Con_Printf("Origin : ^[%f %f %f\\type\\r_editlights_edit origin %g %g %g^]\n", dl->origin[0],dl->origin[1],dl->origin[2], dl->origin[0],dl->origin[1],dl->origin[2]);
Con_Printf("Angles : ^[%f %f %f\\type\\r_editlights_edit angles %g %g %g^]\n", dl->angles[0],dl->angles[1],dl->angles[2], dl->angles[0],dl->angles[1],dl->angles[2]);
Con_Printf("Colour : ^[%f %f %f\\type\\r_editlights_edit avel %g %g %g^]\n", dl->color[0],dl->color[1],dl->color[2], dl->color[0],dl->color[1],dl->color[2]);
Con_Printf("Radius : ^[%f\\type\\r_editlights_edit radius %g^]\n", dl->radius, dl->radius);
Con_Printf("Corona : ^[%f\\type\\r_editlights_edit corona %g^]\n", dl->corona, dl->corona);
Con_Printf("Style : ^[%i\\type\\r_editlights_edit style %i^]\n", dl->style-1, dl->style-1);
Con_Printf("Style String : ^[%s\\type\\r_editlights_edit stylestring %s^]\n", dl->customstyle?dl->customstyle:"---", dl->customstyle?dl->customstyle:"");
Con_Printf("Shadows : ^[%s\\type\\r_editlights_edit shadows %s^]\n", ((dl->flags&LFLAG_NOSHADOWS)?"no":"yes"), ((dl->flags&LFLAG_NOSHADOWS)?"no":"yes"));
Con_Printf("Cubemap : ^[\"%s\"\\type\\r_editlights_edit cubemap \"%s\"^]\n", dl->cubemapname, dl->cubemapname);
Con_Printf("CoronaSize : ^[%f\\type\\r_editlights_edit coronasize %g^]\n", dl->coronascale, dl->coronascale);
Con_Printf("Ambient : ^[%f\\type\\r_editlights_edit ambient %g^]\n", dl->lightcolourscales[0], dl->lightcolourscales[0]);
Con_Printf("Diffuse : ^[%f\\type\\r_editlights_edit diffuse %g^]\n", dl->lightcolourscales[1], dl->lightcolourscales[1]);
Con_Printf("Specular : ^[%f\\type\\r_editlights_edit specular %g^]\n", dl->lightcolourscales[2], dl->lightcolourscales[2]);
Con_Printf("NormalMode : ^[%s\\type\\r_editlights_edit normalmode %s^]\n", ((dl->flags&LFLAG_NORMALMODE)?"yes":"no"), ((dl->flags&LFLAG_NORMALMODE)?"yes":"no"));
Con_Printf("RealTimeMode : ^[%s\\type\\r_editlights_edit realtimemode %s^]\n", ((dl->flags&LFLAG_REALTIMEMODE)?"yes":"no"), ((dl->flags&LFLAG_REALTIMEMODE)?"yes":"no"));
Con_Printf("Spin : ^[%f %f %f\\type\\r_editlights_edit avel %g %g %g^]\n", dl->rotation[0],dl->rotation[1],dl->rotation[2], dl->origin[0],dl->origin[1],dl->origin[2]);
Con_Printf("Cone : ^[%f\\type\\r_editlights_edit outercone %g^]\n", dl->fov, dl->fov);
// Con_Printf("NoStencil : ^[%s\\type\\r_editlights_edit nostencil %s^]\n", ((dl->flags&LFLAG_SHADOWMAP)?"no":"yes"), ((dl->flags&LFLAG_SHADOWMAP)?"no":"yes"));
// Con_Printf("Crepuscular : ^[%s\\type\\r_editlights_edit crepuscular %s^]\n", ((dl->flags&LFLAG_CREPUSCULAR)?"yes":"no"), ((dl->flags&LFLAG_CREPUSCULAR)?"yes":"no"));
// Con_Printf("Ortho : ^[%s\\type\\r_editlights_edit ortho %s^]\n", ((dl->flags&LFLAG_ORTHO)?"yes":"no"), ((dl->flags&LFLAG_ORTHO)?"yes":"no"));
return;
}
switch(R_EditLight(dl, cmd, argc, x,y,z))
{
case -1:
Con_Printf("Not enough args for %s\n", cmd);
return;
case -2:
Con_Printf("Argument not known: %s\n", cmd);
return;
}
}
static void R_EditLights_Remove_f(void)
{
int i = r_editlights_selected;
dlight_t *dl;
if (!r_editlights.ival)
{
Con_Printf("Toggle r_editlights first\n");
return;
}
if (i < RTL_FIRST || i >= rtlights_max)
{
Con_Printf("No light selected\n");
return;
}
dl = &cl_dlights[i];
dl->radius = 0;
r_editlights_selected = -1;
}
static void R_EditLights_EditAll_f(void)
{
int i = 0;
const char *cmd = Cmd_Argv(1);
const char *x = Cmd_Argv(2);
const char *y = Cmd_Argv(3);
const char *z = Cmd_Argv(4);
int argc = Cmd_Argc()-2;
dlight_t *dl;
if (!r_editlights.ival)
{
Con_Printf("No light selected\n");
return;
}
for (i = RTL_FIRST; i < rtlights_max; i++)
{
dl = &cl_dlights[i];
if (dl->radius <= 0)
continue; //don't edit dead lights back to life
switch(R_EditLight(dl, cmd, argc, x,y,z))
{
case -1:
Con_Printf("Not enough args for %s\n", cmd);
return;
case -2:
Con_Printf("Argument not known: %s\n", cmd);
return;
}
}
}
static void R_EditLights_Spawn_f(void)
{
dlight_t *dl;
if (!r_editlights.ival)
{
Con_Printf("Toggle r_editlights first\n");
return;
}
dl = CL_AllocSlight();
r_editlights_selected = dl - cl_dlights;
VectorCopy(r_editlights_cursor, dl->origin);
dl->radius = 200;
dl->style = 1; //0... gah. match DP's results.
dl->lightcolourscales[0] = 0;
dl->lightcolourscales[1] = 1;
dl->lightcolourscales[2] = 1;
}
static void R_EditLights_Clone_f(void)
{
int i = r_editlights_selected;
dlight_t *dl;
dlight_t *src;
if (!r_editlights.ival)
{
Con_Printf("Toggle r_editlights first\n");
return;
}
if (i < RTL_FIRST || i >= rtlights_max)
{
Con_Printf("No light selected\n");
return;
}
src = &cl_dlights[i];
dl = CL_AllocSlight();
r_editlights_selected = dl - cl_dlights;
CL_CloneDlight(dl, src);
VectorCopy(r_editlights_cursor, dl->origin);
}
static void R_EditLights_ToggleShadow_f(void)
{
int i = r_editlights_selected;
dlight_t *dl;
if (!r_editlights.ival)
{
Con_Printf("Toggle r_editlights first\n");
return;
}
if (i < RTL_FIRST || i >= rtlights_max)
{
Con_Printf("No light selected\n");
return;
}
dl = &cl_dlights[i];
dl->flags ^= LFLAG_NOSHADOWS;
}
static void R_EditLights_ToggleCorona_f(void)
{
int i = r_editlights_selected;
dlight_t *dl;
if (!r_editlights.ival)
{
Con_Printf("Toggle r_editlights first\n");
return;
}
if (i < RTL_FIRST || i >= rtlights_max)
{
Con_Printf("No light selected\n");
return;
}
dl = &cl_dlights[i];
dl->corona = !dl->corona;
}
static void R_EditLights_CopyInfo_f(void)
{
int i = r_editlights_selected;
dlight_t *dl;
if (!r_editlights.ival)
{
Con_Printf("Toggle r_editlights first\n");
return;
}
if (i < RTL_FIRST || i >= rtlights_max)
return;
dl = &cl_dlights[i];
CL_CloneDlight(&r_editlights_copybuffer, dl);
}
static void R_EditLights_PasteInfo_f(void)
{
int i = r_editlights_selected;
dlight_t *dl;
vec3_t org;
if (!r_editlights.ival)
{
Con_Printf("Toggle r_editlights first\n");
return;
}
if (i < RTL_FIRST || i >= rtlights_max)
{
Con_Printf("No light selected\n");
return;
}
dl = &cl_dlights[i];
VectorCopy(dl->origin, org);
CL_CloneDlight(dl, &r_editlights_copybuffer);
VectorCopy(org, dl->origin); //undo the origin's copy.
//just in case its from a different map...
if (*dl->cubemapname)
dl->cubetexture = R_LoadReplacementTexture(dl->cubemapname, "", IF_CUBEMAP, NULL, 0, 0, TF_INVALID);
else
dl->cubetexture = r_nulltex;
}
static void R_EditLights_Lock_f(void)
{
if (!r_editlights.ival)
{
Con_Printf("Toggle r_editlights first\n");
return;
}
if ((r_editlights_selected < RTL_FIRST || r_editlights_selected >= rtlights_max) && !r_editlights_locked)
{
Con_Printf("No light selected\n");
return;
}
r_editlights_locked = !r_editlights_locked;
}
static char macro_buf[256] = "";
static char *r_editlights_current_origin(void)
{
int i = r_editlights_selected;
dlight_t *dl;
if (i < RTL_FIRST || i >= rtlights_max)
return "";
dl = &cl_dlights[i];
Q_snprintfz (macro_buf, sizeof(macro_buf), "%g %g %g", dl->origin[0], dl->origin[1], dl->origin[2]);
return macro_buf;
}
static char *r_editlights_current_angles(void)
{
int i = r_editlights_selected;
dlight_t *dl;
if (i < RTL_FIRST || i >= rtlights_max)
return "";
dl = &cl_dlights[i];
Q_snprintfz (macro_buf, sizeof(macro_buf), "%g %g %g", dl->angles[0], dl->angles[1], dl->angles[2]);
return macro_buf;
}
static char *r_editlights_current_color(void)
{
int i = r_editlights_selected;
dlight_t *dl;
if (i < RTL_FIRST || i >= rtlights_max)
return "";
dl = &cl_dlights[i];
Q_snprintfz (macro_buf, sizeof(macro_buf), "%g %g %g", dl->color[0], dl->color[1], dl->color[2]);
return macro_buf;
}
static char *r_editlights_current_radius(void)
{
int i = r_editlights_selected;
dlight_t *dl;
if (i < RTL_FIRST || i >= rtlights_max)
return "";
dl = &cl_dlights[i];
Q_snprintfz (macro_buf, sizeof(macro_buf), "%g", dl->radius);
return macro_buf;
}
static char *r_editlights_current_corona(void)
{
int i = r_editlights_selected;
dlight_t *dl;
if (i < RTL_FIRST || i >= rtlights_max)
return "";
dl = &cl_dlights[i];
Q_snprintfz (macro_buf, sizeof(macro_buf), "%g", dl->corona);
return macro_buf;
}
static char *r_editlights_current_coronasize(void)
{
int i = r_editlights_selected;
dlight_t *dl;
if (i < RTL_FIRST || i >= rtlights_max)
return "";
dl = &cl_dlights[i];
Q_snprintfz (macro_buf, sizeof(macro_buf), "%g", dl->coronascale);
return macro_buf;
}
static char *r_editlights_current_style(void)
{
int i = r_editlights_selected;
dlight_t *dl;
if (i < RTL_FIRST || i >= rtlights_max)
return "";
dl = &cl_dlights[i];
Q_snprintfz (macro_buf, sizeof(macro_buf), "%i", dl->style-1);
return macro_buf;
}
static char *r_editlights_current_shadows(void)
{
int i = r_editlights_selected;
dlight_t *dl;
if (i < RTL_FIRST || i >= rtlights_max)
return "";
dl = &cl_dlights[i];
if (dl->flags & LFLAG_NOSHADOWS)
return "0";
return "1";
}
static char *r_editlights_current_cubemap(void)
{
int i = r_editlights_selected;
dlight_t *dl;
if (i < RTL_FIRST || i >= rtlights_max)
return "";
dl = &cl_dlights[i];
Q_snprintfz (macro_buf, sizeof(macro_buf), "\"%s\"", dl->cubemapname);
return macro_buf;
}
static char *r_editlights_current_ambient(void)
{
int i = r_editlights_selected;
dlight_t *dl;
if (i < RTL_FIRST || i >= rtlights_max)
return "";
dl = &cl_dlights[i];
Q_snprintfz (macro_buf, sizeof(macro_buf), "%g", dl->lightcolourscales[0]);
return macro_buf;
}
static char *r_editlights_current_diffuse(void)
{
int i = r_editlights_selected;
dlight_t *dl;
if (i < RTL_FIRST || i >= rtlights_max)
return "";
dl = &cl_dlights[i];
Q_snprintfz (macro_buf, sizeof(macro_buf), "%g", dl->lightcolourscales[1]);
return macro_buf;
}
static char *r_editlights_current_specular(void)
{
int i = r_editlights_selected;
dlight_t *dl;
if (i < RTL_FIRST || i >= rtlights_max)
return "";
dl = &cl_dlights[i];
Q_snprintfz (macro_buf, sizeof(macro_buf), "%g", dl->lightcolourscales[2]);
return macro_buf;
}
static char *r_editlights_current_normalmode(void)
{
int i = r_editlights_selected;
dlight_t *dl;
if (i < RTL_FIRST || i >= rtlights_max)
return "";
dl = &cl_dlights[i];
if (dl->flags & LFLAG_NORMALMODE)
return "1";
return "0";
}
static char *r_editlights_current_realtimemode(void)
{
int i = r_editlights_selected;
dlight_t *dl;
if (i < RTL_FIRST || i >= rtlights_max)
return "";
dl = &cl_dlights[i];
if (dl->flags & LFLAG_REALTIMEMODE)
return "1";
return "0";
}
void R_EditLights_RegisterCommands(void)
{
Cmd_AddCommandD ("r_editlights_reload", R_ReloadRTLights_f, "Reload static rtlights. Argument can be rtlights|statics|bsp|none to override the source.");
Cmd_AddCommandD ("r_editlights_save", R_SaveRTLights_f, "Saves rtlights to maps/FOO.rtlights");
Cvar_Register (&r_editlights_import_radius, "Realtime Light editing/importing");
Cvar_Register (&r_editlights_import_ambient, "Realtime Light editing/importing");
Cvar_Register (&r_editlights_import_diffuse, "Realtime Light editing/importing");
Cvar_Register (&r_editlights_import_specular, "Realtime Light editing/importing");
Cvar_Register (&r_editlights, "Realtime Light editing/importing");
Cvar_Register (&r_editlights_cursordistance, "Realtime Light editing/importing");
Cvar_Register (&r_editlights_cursorpushoff, "Realtime Light editing/importing");
Cvar_Register (&r_editlights_cursorpushback, "Realtime Light editing/importing");
Cvar_Register (&r_editlights_cursorgrid, "Realtime Light editing/importing");
//the rest is optional stuff that should normally be handled via csqc instead, but hurrah for dp compat...
Cmd_AddCommandD("r_editlights_spawn", R_EditLights_Spawn_f, "Spawn a new light with default properties");
Cmd_AddCommandD("r_editlights_clone", R_EditLights_Clone_f, "Duplicate the current light (with a new origin)");
Cmd_AddCommandD("r_editlights_remove", R_EditLights_Remove_f, "Removes the current light.");
Cmd_AddCommandD("r_editlights_edit", R_EditLights_Edit_f, "Changes named properties on the current light.");
Cmd_AddCommandD("r_editlights_editall", R_EditLights_EditAll_f, "Like r_editlights_edit, but affects all lights instead of just the selected one.");
Cmd_AddCommandD("r_editlights_toggleshadow", R_EditLights_ToggleShadow_f, "Toggles the shadow flag on the current light.");
Cmd_AddCommandD("r_editlights_togglecorona", R_EditLights_ToggleCorona_f, "Toggles the current light's corona field.");
Cmd_AddCommandD("r_editlights_copyinfo", R_EditLights_CopyInfo_f, "store a copy of all properties (except origin) of the selected light");
Cmd_AddCommandD("r_editlights_pasteinfo", R_EditLights_PasteInfo_f, "apply the stored properties onto the selected light (making it exactly identical except for origin)");
Cmd_AddCommandD("r_editlights_lock", R_EditLights_Lock_f, "Blocks changing the current light according the crosshair.");
//DP has these as cvars. mneh.
Cmd_AddMacroD("r_editlights_current_origin", r_editlights_current_origin, false, "origin of selected light");
Cmd_AddMacroD("r_editlights_current_angles", r_editlights_current_angles, false, "angles of selected light");
Cmd_AddMacroD("r_editlights_current_color", r_editlights_current_color, false, "color of selected light");
Cmd_AddMacroD("r_editlights_current_radius", r_editlights_current_radius, false, "radius of selected light");
Cmd_AddMacroD("r_editlights_current_corona", r_editlights_current_corona, false, "corona intensity of selected light");
Cmd_AddMacroD("r_editlights_current_coronasize",r_editlights_current_coronasize,false, "corona size of selected light");
Cmd_AddMacroD("r_editlights_current_style", r_editlights_current_style, false, "style of selected light");
Cmd_AddMacroD("r_editlights_current_shadows", r_editlights_current_shadows, false, "shadows flag of selected light");
Cmd_AddMacroD("r_editlights_current_cubemap", r_editlights_current_cubemap, false, "cubemap of selected light");
Cmd_AddMacroD("r_editlights_current_ambient", r_editlights_current_ambient, false, "ambient intensity of selected light");
Cmd_AddMacroD("r_editlights_current_diffuse", r_editlights_current_diffuse, false, "diffuse intensity of selected light");
Cmd_AddMacroD("r_editlights_current_specular", r_editlights_current_specular, false, "specular intensity of selected light");
Cmd_AddMacroD("r_editlights_current_normalmode",r_editlights_current_normalmode,false, "normalmode flag of selected light");
Cmd_AddMacroD("r_editlights_current_realtimemode", r_editlights_current_realtimemode, false, "realtimemode flag of selected light");
} }
#endif #endif

View file

@ -1947,7 +1947,7 @@ void GLR_RenderView (void)
if (dofbo) if (dofbo)
forcedfb = false; forcedfb = false;
else if (renderscale != 1) else if (renderscale != 1)
forcedfb = true; forcedfb = gl_config.ext_framebuffer_objects && sh_config.texture_non_power_of_two_pic;
BE_Scissor(NULL); BE_Scissor(NULL);
if (dofbo) if (dofbo)
@ -1956,6 +1956,13 @@ void GLR_RenderView (void)
texid_t col[R_MAX_RENDERTARGETS], depth = r_nulltex; texid_t col[R_MAX_RENDERTARGETS], depth = r_nulltex;
unsigned int cw=0, ch=0, dw=0, dh=0; unsigned int cw=0, ch=0, dw=0, dh=0;
int mrt; int mrt;
if (!gl_config.ext_framebuffer_objects && sh_config.texture_non_power_of_two_pic)
{
Con_DPrintf(CON_WARNING"Render targets are not supported on this gpu.\n");
return; //not supported on this gpu. you'll just get black textures or something.
}
//3d views generally ignore source colour+depth. //3d views generally ignore source colour+depth.
//FIXME: support depth with no colour //FIXME: support depth with no colour
for (mrt = 0; mrt < R_MAX_RENDERTARGETS; mrt++) for (mrt = 0; mrt < R_MAX_RENDERTARGETS; mrt++)

View file

@ -195,7 +195,7 @@ qboolean GLSCR_UpdateScreen (void)
if (uimenu != 1) if (uimenu != 1)
{ {
if (r_worldentity.model && cls.state == ca_active) if (r_worldentity.model && cls.state == ca_active)
V_RenderView (); V_RenderView (nohud);
else else
{ {
noworld = true; noworld = true;

View file

@ -7298,9 +7298,7 @@ char *Shader_GetShaderBody(shader_t *s, char *fname, size_t fnamesize)
break; break;
} }
} }
}
if ( parsename ) {
if (!strchr(parsename, ':')) if (!strchr(parsename, ':'))
{ {
//if the named shader is a .shader file then just directly load it. //if the named shader is a .shader file then just directly load it.

View file

@ -62,10 +62,6 @@ cvar_t r_shadow_realtime_dlight_shadows = CVARFD ("r_shadow_realtime_dlight_sha
cvar_t r_shadow_realtime_dlight_ambient = CVAR ("r_shadow_realtime_dlight_ambient", "0"); cvar_t r_shadow_realtime_dlight_ambient = CVAR ("r_shadow_realtime_dlight_ambient", "0");
cvar_t r_shadow_realtime_dlight_diffuse = CVAR ("r_shadow_realtime_dlight_diffuse", "1"); cvar_t r_shadow_realtime_dlight_diffuse = CVAR ("r_shadow_realtime_dlight_diffuse", "1");
cvar_t r_shadow_realtime_dlight_specular = CVAR ("r_shadow_realtime_dlight_specular", "4"); //excessive, but noticable. its called stylized, okay? shiesh, some people cvar_t r_shadow_realtime_dlight_specular = CVAR ("r_shadow_realtime_dlight_specular", "4"); //excessive, but noticable. its called stylized, okay? shiesh, some people
cvar_t r_editlights_import_radius = CVAR ("r_editlights_import_radius", "1");
cvar_t r_editlights_import_ambient = CVAR ("r_editlights_import_ambient", "0");
cvar_t r_editlights_import_diffuse = CVAR ("r_editlights_import_diffuse", "1");
cvar_t r_editlights_import_specular = CVAR ("r_editlights_import_specular", "1"); //excessive, but noticable. its called stylized, okay? shiesh, some people
cvar_t r_shadow_playershadows = CVARD ("r_shadow_playershadows", "1", "Controls the presence of shadows on the local player."); cvar_t r_shadow_playershadows = CVARD ("r_shadow_playershadows", "1", "Controls the presence of shadows on the local player.");
cvar_t r_shadow_shadowmapping = CVARD ("r_shadow_shadowmapping", "1", "Enables soft shadows instead of stencil shadows."); cvar_t r_shadow_shadowmapping = CVARD ("r_shadow_shadowmapping", "1", "Enables soft shadows instead of stencil shadows.");
cvar_t r_shadow_shadowmapping_precision = CVARD ("r_shadow_shadowmapping_precision", "1", "Scales the shadowmap detail level up or down."); cvar_t r_shadow_shadowmapping_precision = CVARD ("r_shadow_shadowmapping_precision", "1", "Scales the shadowmap detail level up or down.");
@ -3571,7 +3567,7 @@ void Sh_DrawCrepuscularLight(dlight_t *dl, float *colours)
void Sh_PurgeShadowMeshes(void) void Sh_PurgeShadowMeshes(void)
{ {
dlight_t *dl; dlight_t *dl;
int i; size_t i;
for (dl = cl_dlights, i=0; i<cl_maxdlights; i++, dl++) for (dl = cl_dlights, i=0; i<cl_maxdlights; i++, dl++)
{ {
if (dl->worldshadowmesh) if (dl->worldshadowmesh)
@ -3604,6 +3600,12 @@ void Sh_PreGenerateLights(void)
qboolean okay = false; qboolean okay = false;
if (!okay) if (!okay)
okay |= R_LoadRTLights(); okay |= R_LoadRTLights();
if (!okay)
{
for (i = 0; i < cl.num_statics; i++)
R_StaticEntityToRTLight(i);
okay |= rtlights_max != RTL_FIRST;
}
if (!okay) if (!okay)
okay |= R_ImportRTLights(Mod_GetEntitiesString(cl.worldmodel)); okay |= R_ImportRTLights(Mod_GetEntitiesString(cl.worldmodel));
if (!okay && r_shadow_realtime_world.ival && r_shadow_realtime_world_lightmaps.value != 1) if (!okay && r_shadow_realtime_world.ival && r_shadow_realtime_world_lightmaps.value != 1)
@ -3867,6 +3869,54 @@ void Sh_DrawLights(qbyte *vis)
colour[0] = dl->color[0]; colour[0] = dl->color[0];
colour[1] = dl->color[1]; colour[1] = dl->color[1];
colour[2] = dl->color[2]; colour[2] = dl->color[2];
if (dl->customstyle)
{
const char *map = dl->customstyle;
int maplen = strlen(map);
int idx, v1, v2, vd;
float frac, strength;
if (!maplen)
{
strength = ('m'-'a')*22 * r_lightstylescale.value/255.0;
}
else if (map[0] == '=')
{
strength = atof(map+1)*r_lightstylescale.value;
}
else
{
frac = (cl.time*r_lightstylespeed.value);
if (*map == '?' && maplen>1)
{
map++;
maplen--;
frac += i*M_PI;
}
frac += i*M_PI;
if (frac < 0)
frac = 0;
idx = (int)frac;
frac -= idx; //this can require updates at 1000 times a second.. Depends on your framerate of course
v1 = idx % maplen;
v1 = map[v1] - 'a';
v2 = (idx+1) % maplen;
v2 = map[v2] - 'a';
vd = v1 - v2;
if (/*!r_lightstylesmooth.ival ||*/ vd < -r_lightstylesmooth_limit.ival || vd > r_lightstylesmooth_limit.ival)
strength = v1*(22/255.0)*r_lightstylescale.value;
else
strength = (v1*(1-frac) + v2*(frac))*(22/255.0)*r_lightstylescale.value;
}
strength *= d_lightstylevalue[0]/255.0f; //a lot of QW mods use lightstyle 0 for a global darkening fade-in thing, so be sure to respect that.
colour[0] *= strength;
colour[1] *= strength;
colour[2] *= strength;
}
if (dl->style) if (dl->style)
{ {
colour[0] *= cl_lightstyle[dl->style-1].colours[0] * d_lightstylevalue[dl->style-1]/255.0f; colour[0] *= cl_lightstyle[dl->style-1].colours[0] * d_lightstylevalue[dl->style-1]/255.0f;

View file

@ -3450,7 +3450,7 @@ static qboolean X11VID_Init (rendererstate_t *info, unsigned char *palette, int
break; break;
} }
#endif #endif
Con_Printf("Failed to create a vulkan context.\n"); Con_Printf(CON_ERROR "Failed to create a vulkan context.\n");
GLVID_Shutdown(); GLVID_Shutdown();
return false; return false;
#endif #endif

View file

@ -375,26 +375,6 @@ static void WL_BindRelativePointerManager(struct wl_registry *registry, uint32_t
w.relative_pointer_manager = pwl_registry_bind(registry, id, &zwp_relative_pointer_manager_v1_interface, 1); w.relative_pointer_manager = pwl_registry_bind(registry, id, &zwp_relative_pointer_manager_v1_interface, 1);
} }
/*
struct zwp_locked_pointer_v1;
static void WL_locked_pointer_locked(void *data, struct zwp_locked_pointer_v1 *locked_pointer)
{
}
static void WL_locked_pointer_unlocked(void *data, struct zwp_locked_pointer_v1 *locked_pointer)
{
}
struct zwp_locked_pointer_v1_listener
{
void (*pointer_locked)(void *data, struct zwp_locked_pointer_v1 *locked_pointer);
void (*pointer_unlocked)(void *data, struct zwp_locked_pointer_v1 *locked_pointer);
};
static const struct zwp_locked_pointer_v1_listener locked_pointer_listener =
{
WL_locked_pointer_locked,
WL_locked_pointer_unlocked,
};
*/
static void WL_keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard, uint32_t format, int fd, uint32_t size) static void WL_keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard, uint32_t format, int fd, uint32_t size)
{ {
} }
@ -490,10 +470,49 @@ static const struct wl_seat_listener seat_listener =
WL_seat_handle_capabilities WL_seat_handle_capabilities
}; };
#if 0
static void WL_BindDecoraionManager(struct wl_registry *registry, uint32_t id)
{ /*oh hey, I wrote lots of code! pay me more! fuck that shit.*/
static const struct wl_interface *types[3];
static const struct wl_message zxdg_decoration_manager_v1_requests[] = {
{ "destroy", "", types + 0 },
{ "get_toplevel_decoration", "no", types + 1 },
};
static const struct wl_interface zxdg_decoration_manager_v1_interface = {
"zxdg_decoration_manager_v1", 1,
2, zxdg_decoration_manager_v1_requests,
0, NULL,
};
static const struct wl_message zxdg_toplevel_decoration_v1_requests[] = {
{ "destroy", "", types + 0 },
{ "set_mode", "u", types + 0 },
{ "unset_mode", "", types + 0 },
};
static const struct wl_message zxdg_toplevel_decoration_v1_events[] = {
{ "configure", "u", types + 0 },
};
static const struct wl_interface zxdg_toplevel_decoration_v1_interface = {
"zxdg_toplevel_decoration_v1", 1,
3, zxdg_toplevel_decoration_v1_requests,
1, zxdg_toplevel_decoration_v1_events,
};
//fix up types...
types[1] = &zxdg_toplevel_decoration_v1_interface;
types[2] = NULL;//&xdg_toplevel_interface;
// pzwp_relative_pointer_v1_interface = &zxdg_toplevel_decoration_v1_interface;
w.decoration_manager = pwl_registry_bind(registry, id, &zxdg_decoration_manager_v1_interface, 1);
}
#endif
static void WL_handle_global(void *data, struct wl_registry *registry, uint32_t id, const char *interface, uint32_t version) static void WL_handle_global(void *data, struct wl_registry *registry, uint32_t id, const char *interface, uint32_t version)
{ {
struct wdisplay_s *d = data; struct wdisplay_s *d = data;
//Sys_Printf("Interface %s id %u\n", interface, id); Con_DLPrintf(2, "Wayland Interface %s id %u\n", interface, id);
if (strcmp(interface, "wl_compositor") == 0) if (strcmp(interface, "wl_compositor") == 0)
d->compositor = pwl_registry_bind(registry, id, pwl_compositor_interface, 1); d->compositor = pwl_registry_bind(registry, id, pwl_compositor_interface, 1);
else if (strcmp(interface, "wl_shell") == 0) else if (strcmp(interface, "wl_shell") == 0)
@ -505,6 +524,8 @@ static void WL_handle_global(void *data, struct wl_registry *registry, uint32_t
} }
else if (strcmp(interface, "zwp_relative_pointer_manager_v1") == 0) else if (strcmp(interface, "zwp_relative_pointer_manager_v1") == 0)
WL_BindRelativePointerManager(registry, id); WL_BindRelativePointerManager(registry, id);
// else if (strcmp(interface, "zxdg_decoration_manager_v1") == 0)
// WL_BindDecorationManager(registry, id);
// else if (strcmp(interface, "zwp_pointer_constraints_v1") == 0) // else if (strcmp(interface, "zwp_pointer_constraints_v1") == 0)
// d->shell = pwl_registry_bind(registry, id, pwl_shell_interface, 1); // d->shell = pwl_registry_bind(registry, id, pwl_shell_interface, 1);
/* else if (!strcmp(interface, "input_device")) /* else if (!strcmp(interface, "input_device"))
@ -659,7 +680,10 @@ static qboolean WL_Init (rendererstate_t *info, unsigned char *palette)
case QR_VULKAN: case QR_VULKAN:
{ {
const char *extnames[] = {VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME, NULL}; const char *extnames[] = {VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME, NULL};
return VK_Init(info, extnames, WLVK_SetupSurface, NULL); if (VK_Init(info, extnames, WLVK_SetupSurface, NULL))
return true;
Con_Printf(CON_ERROR "Unable to initialise vulkan-on-wayland.\n");
return false;
} }
break; break;
#endif #endif

View file

@ -405,10 +405,8 @@ void R_InitFlashblends(void);
void GLR_MarkQ2Lights (dlight_t *light, int bit, mnode_t *node); void GLR_MarkQ2Lights (dlight_t *light, int bit, mnode_t *node);
#endif #endif
void GLQ3_LightGrid(model_t *mod, vec3_t point, vec3_t res_diffuse, vec3_t res_ambient, vec3_t res_dir); void GLQ3_LightGrid(model_t *mod, vec3_t point, vec3_t res_diffuse, vec3_t res_ambient, vec3_t res_dir);
void R_ReloadRTLights_f(void);
qboolean R_LoadRTLights(void); qboolean R_LoadRTLights(void);
qboolean R_ImportRTLights(const char *entlump); qboolean R_ImportRTLights(const char *entlump);
void R_SaveRTLights_f(void);
//doom //doom
#ifdef MAP_DOOM #ifdef MAP_DOOM

View file

@ -947,6 +947,9 @@ void BE_GenerateProgram(shader_t *shader);
void Sh_RegisterCvars(void); void Sh_RegisterCvars(void);
#ifdef RTLIGHTS #ifdef RTLIGHTS
void R_EditLights_DrawLights(void); //3d light previews
void R_EditLights_DrawInfo(void); //2d light info display.
void R_EditLights_RegisterCommands(void);
// //
#ifdef BEF_PUSHDEPTH #ifdef BEF_PUSHDEPTH
void GLBE_PolyOffsetStencilShadow(qboolean foobar); void GLBE_PolyOffsetStencilShadow(qboolean foobar);
@ -982,6 +985,7 @@ extern struct shader_field_names_s shader_unif_names[];
extern struct shader_field_names_s shader_attr_names[]; extern struct shader_field_names_s shader_attr_names[];
void CLQ1_AddSpriteQuad(shader_t *shader, vec3_t mid, float radius);
void CLQ1_DrawLine(shader_t *shader, vec3_t v1, vec3_t v2, float r, float g, float b, float a); void CLQ1_DrawLine(shader_t *shader, vec3_t v1, vec3_t v2, float r, float g, float b, float a);
void CLQ1_AddOrientedCube(shader_t *shader, vec3_t mins, vec3_t maxs, float *matrix, float r, float g, float b, float a); void CLQ1_AddOrientedCube(shader_t *shader, vec3_t mins, vec3_t maxs, float *matrix, float r, float g, float b, float a);
void CL_DrawDebugPlane(float *normal, float dist, float r, float g, float b, qboolean enqueue); void CL_DrawDebugPlane(float *normal, float dist, float r, float g, float b, qboolean enqueue);

View file

@ -91,7 +91,7 @@ struct dl_download
qboolean isquery; //will not be displayed in the download/progress bar stuff. qboolean isquery; //will not be displayed in the download/progress bar stuff.
#ifndef SERVERONLY #ifdef HAVE_CLIENT
qdownload_t qdownload; qdownload_t qdownload;
#endif #endif

View file

@ -7,7 +7,7 @@
#ifdef WEBSVONLY //we need some functions from quake #ifdef WEBSVONLY //we need some functions from quake
char *NET_SockadrToString(char *s, int slen, struct sockaddr_qstorage *addr) char *NET_SockadrToString(char *s, int slen, struct sockaddr_qstorage *addr, size_t sizeofaddr)
{ {
switch(((struct sockaddr*)addr)->sa_family) switch(((struct sockaddr*)addr)->sa_family)
{ {
@ -221,8 +221,14 @@ int main(int argc, char **argv)
if (arg < argc) if (arg < argc)
autheduserpassword = argv[arg++]; autheduserpassword = argv[arg++];
printf("http port %i\n", httpport); if (httpport)
printf("ftp port %i\n", ftpport); printf("http port %i\n", httpport);
else
printf("http not enabled\n");
if (ftpport)
printf("ftp port %i\n", ftpport);
else
printf("ftp not enabled\n");
if (authedusername || autheduserpassword) if (authedusername || autheduserpassword)
printf("Username = \"%s\"\nPassword = \"%s\"\n", authedusername, autheduserpassword); printf("Username = \"%s\"\nPassword = \"%s\"\n", authedusername, autheduserpassword);
else else

View file

@ -59,7 +59,7 @@ texa0
struct pkgctx_s struct pkgctx_s
{ {
void (*messagecallback)(void *userctx, char *message, ...); void (*messagecallback)(void *userctx, const char *message, ...);
void *userctx; void *userctx;
char *listfile; char *listfile;
@ -1557,7 +1557,7 @@ void Packager_WriteDataset(struct pkgctx_s *ctx, char *setname)
PKG_WriteDataset(ctx, dataset); PKG_WriteDataset(ctx, dataset);
} }
} }
struct pkgctx_s *Packager_Create(void (*messagecallback)(void *userctx, char *message, ...), void *userctx) struct pkgctx_s *Packager_Create(void (*messagecallback)(void *userctx, const char *message, ...), void *userctx)
{ {
struct pkgctx_s *ctx; struct pkgctx_s *ctx;
ctx = malloc(sizeof(*ctx)); ctx = malloc(sizeof(*ctx));

View file

@ -823,6 +823,7 @@ enum {
WARN_COMPATIBILITYHACK, //work around old defs.qc or invalid dpextensions.qc WARN_COMPATIBILITYHACK, //work around old defs.qc or invalid dpextensions.qc
WARN_REDECLARATIONMISMATCH, WARN_REDECLARATIONMISMATCH,
WARN_PARAMWITHNONAME, WARN_PARAMWITHNONAME,
WARN_ARGUMENTCHECK,
ERR_PARSEERRORS, //caused by qcc_pr_parseerror being called. ERR_PARSEERRORS, //caused by qcc_pr_parseerror being called.
@ -1148,7 +1149,7 @@ int WriteSourceFiles(qcc_cachedsourcefile_t *filelist, int h, pbool sourceaswell
struct pkgctx_s; struct pkgctx_s;
struct pkgctx_s *Packager_Create(void (*messagecallback)(void *userctx, char *message, ...), void *userctx); struct pkgctx_s *Packager_Create(void (*messagecallback)(void *userctx, const char *message, ...), void *userctx);
void Packager_ParseFile(struct pkgctx_s *ctx, char *scriptfilename); void Packager_ParseFile(struct pkgctx_s *ctx, char *scriptfilename);
void Packager_ParseText(struct pkgctx_s *ctx, char *scripttext); void Packager_ParseText(struct pkgctx_s *ctx, char *scripttext);
void Packager_WriteDataset(struct pkgctx_s *ctx, char *setname); void Packager_WriteDataset(struct pkgctx_s *ctx, char *setname);

View file

@ -4831,6 +4831,107 @@ nolength:
} }
} }
static void QCC_VerifyArgs_setviewprop (const char *funcname, QCC_ref_t **arglist, unsigned int argcount)
{
static struct
{
const char *name;
int n;
etype_t t1;
etype_t t2;
etype_t t3;
} argtypes[] =
{
{"VF_MIN", 1, ev_vector},
{"VF_MIN_X", 2, ev_float},
{"VF_MIN_Y", 3, ev_float},
{"VF_SIZE", 4, ev_vector},
{"VF_SIZE_X", 5, ev_float},
{"VF_SIZE_Y", 6, ev_float},
{"VF_VIEWPORT", 7, ev_vector},
{"VF_FOV", 8, ev_vector},
{"VF_FOVX", 9, ev_float},
{"VF_FOVY", 10, ev_float},
{"VF_ORIGIN", 11, ev_vector},
{"VF_ORIGIN_X", 12, ev_float},
{"VF_ORIGIN_Y", 13, ev_float},
{"VF_ORIGIN_Z", 14, ev_float},
{"VF_ANGLES", 15, ev_vector},
{"VF_ANGLES_X", 16, ev_float},
{"VF_ANGLES_Y", 17, ev_float},
{"VF_ANGLES_Z", 18, ev_float},
{"VF_DRAWWORLD", 19, ev_float},
{"VF_ENGINESBAR", 20, ev_float},
{"VF_DRAWCROSSHAIR", 21, ev_float},
// {"VF_CARTESIAN_ANGLES", 22, ev_vector},
{"VF_MINDIST", 23, ev_float},
{"VF_MAXDIST", 24, ev_float},
{"VF_CL_VIEWANGLES_V", 33, ev_vector},
{"VF_CL_VIEWANGLES_X", 34, ev_float},
{"VF_CL_VIEWANGLES_X", 35, ev_float},
{"VF_CL_VIEWANGLES_X", 36, ev_float},
{"VF_PERSPECTIVE", 200, ev_float},
//201
{"VF_ACTIVESEAT", 202, ev_float},
{"VF_AFOV", 203, ev_float},
// {"VF_SCREENVSIZE", 204, ev_vector},
// {"VF_SCREENPSIZE", 205, ev_vector},
{"VF_VIEWENTITY", 206, ev_float},
// {"VF_STATSENTITY", 207, ev_float},
// {"VF_SCREENVOFFSET", 208, ev_float},
{"VF_RT_SOURCECOLOUR", 209, ev_string},
{"VF_RT_DEPTH", 210, ev_string, ev_float, ev_vector},
{"VF_RT_RIPPLE", 211, ev_string, ev_float, ev_vector},
{"VF_RT_DESTCOLOUR0", 212, ev_string, ev_float, ev_vector},
{"VF_RT_DESTCOLOUR1", 213, ev_string, ev_float, ev_vector},
{"VF_RT_DESTCOLOUR2", 214, ev_string, ev_float, ev_vector},
{"VF_RT_DESTCOLOUR3", 215, ev_string, ev_float, ev_vector},
{"VF_RT_DESTCOLOUR4", 216, ev_string, ev_float, ev_vector},
{"VF_RT_DESTCOLOUR5", 217, ev_string, ev_float, ev_vector},
{"VF_RT_DESTCOLOUR6", 218, ev_string, ev_float, ev_vector},
{"VF_RT_DESTCOLOUR7", 219, ev_string, ev_float, ev_vector},
{"VF_ENVMAP", 220, ev_string},
{"VF_USERDATA", 221, ev_pointer, ev_integer},
};
char temp[256];
const QCC_eval_t *ev;
int i, vf;
if (!argcount)
return; // o.O
ev = QCC_SRef_EvalConst(arglist[0]->base);
if (!ev) //can't check variables.
return;
vf = ev->_float;
if (!qccwarningaction[WARN_ARGUMENTCHECK])
return; //don't bother if its not relevant anyway.
for (i = 0; i < sizeof(argtypes)/sizeof(argtypes[0]); i++)
{
if (argtypes[i].n == vf)
{
if (argcount >= 2 && argtypes[i].t1 != arglist[1]->cast->type)
{
QCC_PR_ParseWarning(WARN_ARGUMENTCHECK, "%s(%s, ...): expected %s, got %s", funcname, argtypes[i].name, basictypenames[argtypes[i].t1], TypeName(arglist[1]->cast, temp, sizeof(temp)));
return;
}
if (argcount >= 3 && argtypes[i].t2 != arglist[2]->cast->type)
{
QCC_PR_ParseWarning(WARN_ARGUMENTCHECK, "%s(%s, X, ...): expected %s, got %s", funcname, argtypes[i].name, basictypenames[argtypes[i].t2], TypeName(arglist[2]->cast, temp, sizeof(temp)));
return;
}
if (argcount >= 4 && argtypes[i].t3 != arglist[3]->cast->type)
{
QCC_PR_ParseWarning(WARN_ARGUMENTCHECK, "%s(%s, X, Y, ...): expected %s, got %s", funcname, argtypes[i].name, basictypenames[argtypes[i].t3], TypeName(arglist[3]->cast, temp, sizeof(temp)));
return;
}
return;
}
}
QCC_PR_ParseWarning(WARN_ARGUMENTCHECK, "%s: unknown argument %i", funcname, vf);
}
#ifdef SUPPORTINLINE #ifdef SUPPORTINLINE
struct inlinectx_s struct inlinectx_s
{ {
@ -5336,6 +5437,8 @@ QCC_sref_t QCC_PR_GenerateFunctionCallRef (QCC_sref_t newself, QCC_sref_t func,
if (!strcmp(funcname, "sprintf")) if (!strcmp(funcname, "sprintf"))
QCC_VerifyFormatString(funcname, arglist, argcount); QCC_VerifyFormatString(funcname, arglist, argcount);
if (!strcmp(funcname, "setviewprop") || !strcmp(funcname, "setproperty"))
QCC_VerifyArgs_setviewprop(funcname, arglist, argcount);
func.sym->timescalled++; func.sym->timescalled++;

View file

@ -3012,7 +3012,7 @@ static void EditorReload(editor_t *editor)
size_t flensz; size_t flensz;
char *rawfile; char *rawfile;
char *file; char *file;
unsigned int flen; size_t flen;
pbool dofree; pbool dofree;
rawfile = QCC_ReadFile(editor->filename, NULL, NULL, &flensz); rawfile = QCC_ReadFile(editor->filename, NULL, NULL, &flensz);
flen = flensz; flen = flensz;

View file

@ -12022,6 +12022,7 @@ void PR_DumpPlatform_f(void)
{"MOVETYPE_6DOF", "const float", QW|NQ|CS, D("A glorified MOVETYPE_FLY. Players using this movetype will get some flightsim-like physics, with fully independant rotations (order-dependant transforms)."), MOVETYPE_6DOF}, {"MOVETYPE_6DOF", "const float", QW|NQ|CS, D("A glorified MOVETYPE_FLY. Players using this movetype will get some flightsim-like physics, with fully independant rotations (order-dependant transforms)."), MOVETYPE_6DOF},
{"MOVETYPE_WALLWALK", "const float", QW|NQ|CS, D("Players using this movetype will be able to orient themselves to walls, and then run up them."), MOVETYPE_WALLWALK}, {"MOVETYPE_WALLWALK", "const float", QW|NQ|CS, D("Players using this movetype will be able to orient themselves to walls, and then run up them."), MOVETYPE_WALLWALK},
{"MOVETYPE_PHYSICS", "const float", QW|NQ|CS, D("Enable the use of ODE physics upon this entity."), MOVETYPE_PHYSICS}, {"MOVETYPE_PHYSICS", "const float", QW|NQ|CS, D("Enable the use of ODE physics upon this entity."), MOVETYPE_PHYSICS},
// {"MOVETYPE_FLY_WORLDONLY", "const float", QW|NQ|CS, D("A cross between noclip and fly. Basically, this prevents the player/spectator from being able to move into the void, which avoids pvs issues that are common with caulk brushes on q3bsp. ONLY the world model will be solid, all doors/etc will be non-solid."), MOVETYPE_FLY_WORLDONLY},
{"SOLID_NOT", "const float", QW|NQ|CS, NULL, SOLID_NOT}, {"SOLID_NOT", "const float", QW|NQ|CS, NULL, SOLID_NOT},
{"SOLID_TRIGGER", "const float", QW|NQ|CS, NULL, SOLID_TRIGGER}, {"SOLID_TRIGGER", "const float", QW|NQ|CS, NULL, SOLID_TRIGGER},
@ -12463,6 +12464,7 @@ void PR_DumpPlatform_f(void)
{"LFIELD_DIETIME", "const float", CS, NULL, lfield_dietime}, {"LFIELD_DIETIME", "const float", CS, NULL, lfield_dietime},
{"LFIELD_RGBDECAY", "const float", CS, NULL, lfield_rgbdecay}, {"LFIELD_RGBDECAY", "const float", CS, NULL, lfield_rgbdecay},
{"LFIELD_RADIUSDECAY", "const float", CS, NULL, lfield_radiusdecay}, {"LFIELD_RADIUSDECAY", "const float", CS, NULL, lfield_radiusdecay},
{"LFIELD_STYLESTRING", "const float", CS, NULL, lfield_stylestring},
{"LFLAG_NORMALMODE", "const float", CS, NULL, LFLAG_NORMALMODE}, {"LFLAG_NORMALMODE", "const float", CS, NULL, LFLAG_NORMALMODE},
{"LFLAG_REALTIMEMODE", "const float", CS, NULL, LFLAG_REALTIMEMODE}, {"LFLAG_REALTIMEMODE", "const float", CS, NULL, LFLAG_REALTIMEMODE},
@ -12614,17 +12616,17 @@ void PR_DumpPlatform_f(void)
VFS_PRINTF(f, "#pragma noref 1\n"); VFS_PRINTF(f, "#pragma noref 1\n");
VFS_PRINTF(f, "//#pragma flag enable logicops\n"); VFS_PRINTF(f, "//#pragma flag enable logicops\n");
VFS_PRINTF(f, "#pragma warning error Q101 /*too many parms*/\n"); VFS_PRINTF(f, "#pragma warning error Q101 /*too many parms. The vanilla qcc didn't validate properly, hence why fteqcc normally treats it as a warning.*/\n");
VFS_PRINTF(f, "#pragma warning error Q105 /*too few parms*/\n"); VFS_PRINTF(f, "#pragma warning error Q105 /*too few parms. The vanilla qcc didn't validate properly, hence why fteqcc normally treats it as a warning.*/\n");
VFS_PRINTF(f, "#pragma warning error Q106 /*assignment to constant/lvalue*/\n"); VFS_PRINTF(f, "#pragma warning error Q106 /*assignment to constant/lvalue. Define them as var if you want to initialise something.*/\n");
VFS_PRINTF(f, "#pragma warning error Q208 /*system crc unknown*/\n"); VFS_PRINTF(f, "#pragma warning error Q208 /*system crc unknown. Compatibility goes out of the window if you disable this.*/\n");
#ifdef NOLEGACY #ifdef NOLEGACY
VFS_PRINTF(f, "#pragma warning error F211 /*system crc outdated (eg: dp's csqc)*/\n"); VFS_PRINTF(f, "#pragma warning error F211 /*system crc outdated (eg: dp's csqc). Such mods will not run properly in FTE.*/\n");
#else #else
VFS_PRINTF(f, "#pragma warning disable F211 /*system crc outdated (eg: dp's csqc)*/\n"); VFS_PRINTF(f, "#pragma warning disable F211 /*system crc outdated (eg: dp's csqc). Note that this may trigger emulation.*/\n");
#endif #endif
VFS_PRINTF(f, "#pragma warning enable F301 /*non-utf-8 strings*/\n"); VFS_PRINTF(f, "#pragma warning enable F301 /*non-utf-8 strings. Think of the foreigners! Also think of text editors that insist on screwing up your char encodings.*/\n");
VFS_PRINTF(f, "#pragma warning enable F302 /*uninitialised locals*/\n"); VFS_PRINTF(f, "#pragma warning enable F302 /*uninitialised locals. They usually default to 0 in qc (except in recursive functions), but its still probably a bug*/\n");
if ((targ&ALL) == H2) if ((targ&ALL) == H2)
{ {

View file

@ -1571,7 +1571,7 @@ void SV_Savegame (const char *savename, qboolean mapchange)
#endif #endif
if (!okay && r_worldentity.model) if (!okay && r_worldentity.model)
{ {
V_RenderView (); V_RenderView (false);
okay = true; okay = true;
} }
@ -1583,7 +1583,7 @@ void SV_Savegame (const char *savename, qboolean mapchange)
if (rgbbuffer) if (rgbbuffer)
{ {
// extern cvar_t scr_sshot_type; // extern cvar_t scr_sshot_type;
SCR_ScreenShot(savefilename, FS_GAMEONLY, &rgbbuffer, 1, stride, width, height, fmt); SCR_ScreenShot(savefilename, FS_GAMEONLY, &rgbbuffer, 1, stride, width, height, fmt, false);
BZ_Free(rgbbuffer); BZ_Free(rgbbuffer);

View file

@ -1310,7 +1310,9 @@ void SV_UpdateToReliableMessages (void);
void SV_FlushBroadcasts (void); void SV_FlushBroadcasts (void);
qboolean SV_CanTrack(client_t *client, int entity); qboolean SV_CanTrack(client_t *client, int entity);
#ifdef NQPROT
void SV_DarkPlacesDownloadChunk(client_t *cl, sizebuf_t *msg); void SV_DarkPlacesDownloadChunk(client_t *cl, sizebuf_t *msg);
#endif
void SV_New_f (void); void SV_New_f (void);
void SV_PreRunCmd(void); void SV_PreRunCmd(void);

View file

@ -2639,6 +2639,9 @@ client_t *SVC_DirectConnect(void)
} }
} }
msg_badread=false; msg_badread=false;
if (!*guid)
NET_GetConnectionCertificate(svs.sockets, &net_from, QCERT_PEERFINGERPRINT, guid, sizeof(guid));
/*allow_splitscreen applies only to non-local clients, so that clients have only one enabler*/ /*allow_splitscreen applies only to non-local clients, so that clients have only one enabler*/
if (!sv_allow_splitscreen.ival && net_from.type != NA_LOOPBACK) if (!sv_allow_splitscreen.ival && net_from.type != NA_LOOPBACK)
@ -3303,8 +3306,10 @@ client_t *SVC_DirectConnect(void)
SSV_SavePlayerStats(newcl, 0); SSV_SavePlayerStats(newcl, 0);
#endif #endif
#ifdef IPLOG
if (Q_strncasecmp(newcl->name, "unconnected", 11) && Q_strncasecmp(newcl->name, "connecting", 10)) if (Q_strncasecmp(newcl->name, "unconnected", 11) && Q_strncasecmp(newcl->name, "connecting", 10))
IPLog_Add(NET_AdrToString(adrbuf,sizeof(adrbuf), &newcl->netchan.remote_address), newcl->name); IPLog_Add(NET_AdrToString(adrbuf,sizeof(adrbuf), &newcl->netchan.remote_address), newcl->name);
#endif
return newcl; return newcl;
} }
@ -5799,8 +5804,10 @@ void SV_Init (quakeparms_t *parms)
} }
#endif #endif
IPLog_Merge_File("iplog.txt"); #ifdef IPLOG
IPLog_Merge_File("iplog.txt"); //should be compatible with DP's take on the feature.
IPLog_Merge_File("iplog.dat"); //legacy crap, for compat with proquake IPLog_Merge_File("iplog.dat"); //legacy crap, for compat with proquake
#endif
// if a map wasn't specified on the command line, spawn start.map // if a map wasn't specified on the command line, spawn start.map
//aliases require that we flush the cbuf in order to actually see the results. //aliases require that we flush the cbuf in order to actually see the results.

View file

@ -32,7 +32,7 @@ is not a staircase.
============= =============
*/ */
int c_yes, c_no; //int c_yes, c_no;
hull_t *Q1BSP_ChooseHull(model_t *model, int hullnum, vec3_t mins, vec3_t maxs, vec3_t offset); hull_t *Q1BSP_ChooseHull(model_t *model, int hullnum, vec3_t mins, vec3_t maxs, vec3_t offset);
@ -92,11 +92,11 @@ qboolean World_CheckBottom (world_t *world, wedict_t *ent, vec3_t up)
goto realcheck; goto realcheck;
} }
c_yes++; // c_yes++;
return true; // we got out easy return true; // we got out easy
realcheck: realcheck:
c_no++; // c_no++;
// //
// check it for real... // check it for real...
// //
@ -128,7 +128,7 @@ realcheck:
return false; return false;
} }
c_yes++; // c_yes++;
return true; return true;
} }
@ -629,7 +629,7 @@ qboolean World_MoveToGoal (world_t *world, wedict_t *ent, float dist)
#ifdef ENGINE_ROUTING #ifdef ENGINE_ROUTING
cvar_t route_shownodes = CVAR("route_shownodes", "0"); static cvar_t route_shownodes = CVAR("route_shownodes", "0");
#define LF_EDGE 0x00000001 #define LF_EDGE 0x00000001
#define LF_JUMP 0x00000002 #define LF_JUMP 0x00000002
@ -648,7 +648,7 @@ struct waypointnetwork_s
vec3_t pos; vec3_t pos;
int linkflags; int linkflags;
} *displaynode; } *displaynode;
int displaynodes; size_t displaynodes;
struct waypoint_s struct waypoint_s
{ {
@ -660,7 +660,7 @@ struct waypointnetwork_s
float linkcost;//might be much lower in the case of teleports, or expensive if someone wanted it to be a lower priority link. float linkcost;//might be much lower in the case of teleports, or expensive if someone wanted it to be a lower priority link.
int linkflags; //LF_* int linkflags; //LF_*
} *neighbour; } *neighbour;
int neighbours; size_t neighbours;
} waypoints[1]; } waypoints[1];
}; };
void WayNet_Done(struct waypointnetwork_s *net) void WayNet_Done(struct waypointnetwork_s *net)
@ -814,8 +814,8 @@ int WayNet_FindNearestNode(struct waypointnetwork_s *net, vec3_t pos)
struct routecalc_s struct routecalc_s
{ {
world_t *world; world_t *world;
int spawncount; //so we don't confuse stuff if the map gets restarted.
wedict_t *ed; wedict_t *ed;
int spawncount; //so we don't confuse stuff if the map gets restarted.
// float spawnid; //so the route fails if the ent is removed. // float spawnid; //so the route fails if the ent is removed.
func_t callback; func_t callback;

View file

@ -2831,7 +2831,9 @@ qboolean SV_SendClientDatagram (client_t *client)
SZ_Clear (&msg); SZ_Clear (&msg);
} }
#ifdef NQPROT
SV_DarkPlacesDownloadChunk(client, &msg); SV_DarkPlacesDownloadChunk(client, &msg);
#endif
// send the datagram // send the datagram
sentbytes = Netchan_Transmit (&client->netchan, msg.cursize, buf, SV_RateForClient(client)); sentbytes = Netchan_Transmit (&client->netchan, msg.cursize, buf, SV_RateForClient(client));
@ -3693,7 +3695,9 @@ void SV_SendClientMessages (void)
SV_SendClientDatagram (c); SV_SendClientDatagram (c);
else else
{ {
#ifdef NQPROT
SV_DarkPlacesDownloadChunk(c, &c->datagram); SV_DarkPlacesDownloadChunk(c, &c->datagram);
#endif
fnum = c->netchan.outgoing_sequence; fnum = c->netchan.outgoing_sequence;
sentbytes = Netchan_Transmit (&c->netchan, c->datagram.cursize, c->datagram.data, SV_RateForClient(c)); // just update reliable sentbytes = Netchan_Transmit (&c->netchan, c->datagram.cursize, c->datagram.data, SV_RateForClient(c)); // just update reliable
if (ISQWCLIENT(c) || ISNQCLIENT(c)) if (ISQWCLIENT(c) || ISNQCLIENT(c))

View file

@ -349,7 +349,7 @@ void SV_New_f (void)
for (split = host_client; split; split = split->controlled) for (split = host_client; split; split = split->controlled)
{ {
playernum = split - svs.clients;// NUM_FOR_EDICT(svprogfuncs, split->edict)-1; playernum = split - svs.clients;// NUM_FOR_EDICT(svprogfuncs, split->edict)-1;
if (sv.state == ss_cinematic) if (ISQ2CLIENT(host_client) && sv.state == ss_cinematic)
playernum = -1; playernum = -1;
ClientReliableWrite_Byte (host_client, playernum); ClientReliableWrite_Byte (host_client, playernum);
@ -391,9 +391,6 @@ void SV_New_f (void)
if (split->spectator) if (split->spectator)
playernum |= 128; playernum |= 128;
if (sv.state == ss_cinematic)
playernum = -1;
split->state = cs_connected; split->state = cs_connected;
split->connection_started = realtime; split->connection_started = realtime;
#ifdef SVRANKING #ifdef SVRANKING
@ -403,6 +400,8 @@ void SV_New_f (void)
if (ISQ2CLIENT(host_client)) if (ISQ2CLIENT(host_client))
{ {
if (sv.state == ss_cinematic)
playernum = -1;
ClientReliableWrite_Short (host_client, playernum); ClientReliableWrite_Short (host_client, playernum);
break; break;
} }
@ -462,6 +461,16 @@ void SV_New_f (void)
SV_LogPlayer(host_client, "new (QW)"); SV_LogPlayer(host_client, "new (QW)");
if (sv.state == ss_cinematic)
{
char tmp[1024];
MSG_WriteByte (&host_client->netchan.message, svc_stufftext);
MSG_WriteString(&host_client->netchan.message, va("\nplayfilm %s\n", COM_QuotedString(svs.name, tmp, sizeof(tmp), false)));
host_client->prespawn_stage = PRESPAWN_INVALID;
host_client->prespawn_idx = 0;
return;
}
host_client->prespawn_stage = PRESPAWN_SERVERINFO; host_client->prespawn_stage = PRESPAWN_SERVERINFO;
host_client->prespawn_idx = 0; host_client->prespawn_idx = 0;
} }
@ -718,6 +727,16 @@ void SVNQ_New_f (void)
MSG_WriteString (&host_client->netchan.message, "cl_serverextension_download 1\n"); MSG_WriteString (&host_client->netchan.message, "cl_serverextension_download 1\n");
} }
if (sv.state == ss_cinematic)
{
MSG_WriteByte (&host_client->netchan.message, svc_stufftext);
MSG_WriteString(&host_client->netchan.message, va("\nplayfilm %s\n", COM_QuotedString(svs.name, message, sizeof(message), false)));
host_client->prespawn_stage = PRESPAWN_INVALID;
host_client->prespawn_idx = 0;
host_client->netchan.nqunreliableonly = 2;
return;
}
MSG_WriteByte (&host_client->netchan.message, svc_serverdata); MSG_WriteByte (&host_client->netchan.message, svc_serverdata);
if (protext1) if (protext1)
{ {
@ -2242,6 +2261,7 @@ void SV_Begin_f (void)
//============================================================================= //=============================================================================
#ifdef NQPROT
//dp downloads are a 2-stream system //dp downloads are a 2-stream system
//the server->client stream is as you'd expect. except that its unreliable rather than reliable //the server->client stream is as you'd expect. except that its unreliable rather than reliable
//the client->server stream contains no actual data. //the client->server stream contains no actual data.
@ -2349,6 +2369,7 @@ void SV_DarkPlacesDownloadAck(client_t *cl)
host_client->downloadsize = 0; host_client->downloadsize = 0;
} }
} }
#endif
static void SV_NextChunkedDownload(unsigned int chunknum, int ezpercent, int ezfilenum, int chunks) static void SV_NextChunkedDownload(unsigned int chunknum, int ezpercent, int ezfilenum, int chunks)
{ {
@ -5485,14 +5506,6 @@ void SV_DisableClientsCSQC(void)
} }
void SV_UserCmdMVDList_f (void); void SV_UserCmdMVDList_f (void);
static void SV_STFU_f(void)
{
char *msg;
SV_ClientPrintf(host_client, 255, "stfu\n");
msg = "cl_antilag 0\n";
ClientReliableWrite_Begin(host_client, svc_stufftext, 2+strlen(msg));
ClientReliableWrite_String(host_client, msg);
}
#ifdef NQPROT #ifdef NQPROT
static void SVNQ_Spawn_f (void) static void SVNQ_Spawn_f (void)
@ -5975,9 +5988,6 @@ ucmd_t ucmds[] =
{"spawn", SVQW_Spawn_f, true}, {"spawn", SVQW_Spawn_f, true},
{"begin", SV_Begin_f, true}, {"begin", SV_Begin_f, true},
/*ezquake warning*/
{"al", SV_STFU_f, true}, //can probably be removed now.
{"drop", SV_Drop_f}, {"drop", SV_Drop_f},
{"disconnect", SV_Drop_f}, {"disconnect", SV_Drop_f},
{"pings", SV_Pings_f}, {"pings", SV_Pings_f},

View file

@ -43,6 +43,9 @@ void *SVQ2_GetGameAPI (void *parms)
#endif #endif
"game" ARCH_CPU_POSTFIX ARCH_DL_POSTFIX, "game" ARCH_CPU_POSTFIX ARCH_DL_POSTFIX,
"game" ARCH_DL_POSTFIX, "game" ARCH_DL_POSTFIX,
#if defined(__linux__) //FTE doesn't provide gamecode. Borrow someone else's. Lets just hope that its installed.
"/usr/lib/yamagi-quake2/%s/game.so",
#endif
NULL NULL
}; };
void *ret; void *ret;
@ -70,6 +73,12 @@ void *SVQ2_GetGameAPI (void *parms)
continue; continue;
Q_snprintfz(name, sizeof(name), "%slibgame_%s"ARCH_DL_POSTFIX, host_parms.binarydir, gamepath); Q_snprintfz(name, sizeof(name), "%slibgame_%s"ARCH_DL_POSTFIX, host_parms.binarydir, gamepath);
} }
else if (*gamename[o] == '/')
{ //system path. o.O
if (com_nogamedirnativecode.ival) //just in case they match.
continue;
Q_snprintfz(name, sizeof(name), gamename[o], gamepath);
}
else else
{ //gamedir paths as specified above. { //gamedir paths as specified above.
if (com_nogamedirnativecode.ival) if (com_nogamedirnativecode.ival)

View file

@ -2237,8 +2237,6 @@ static void World_ClipToNetwork (world_t *w, moveclip_t *clip)
trace_t trace; trace_t trace;
static framestate_t framestate; //meh static framestate_t framestate; //meh
if (clip->type == MOVE_WORLDONLY)
return;
if (clip->type & MOVE_ENTCHAIN) if (clip->type & MOVE_ENTCHAIN)
return; return;
@ -2565,6 +2563,13 @@ trace_t World_Move (world_t *w, vec3_t start, vec3_t mins, vec3_t maxs, vec3_t e
wedict_t *other = WEDICT_NUM_UB(w->progs, *w->g.other); wedict_t *other = WEDICT_NUM_UB(w->progs, *w->g.other);
return World_ClipMoveToEntity (w, other, other->v->origin, start, mins, maxs, end, hullnum, type & MOVE_HITMODEL, clip.capsule, clip.hitcontentsmask); return World_ClipMoveToEntity (w, other, other->v->origin, start, mins, maxs, end, hullnum, type & MOVE_HITMODEL, clip.capsule, clip.hitcontentsmask);
} }
#ifndef NOLEGACY
if ((type&MOVE_WORLDONLY) == MOVE_WORLDONLY)
{ //for compat with DP
wedict_t *other = w->edicts;
return World_ClipMoveToEntity (w, other, other->v->origin, start, mins, maxs, end, hullnum, type & MOVE_HITMODEL, clip.capsule, clip.hitcontentsmask);
}
#endif
// clip to world // clip to world
clip.trace = World_ClipMoveToEntity (w, w->edicts, w->edicts->v->origin, start, mins, maxs, end, hullnum, false, clip.capsule, clip.hitcontentsmask); clip.trace = World_ClipMoveToEntity (w, w->edicts, w->edicts->v->origin, start, mins, maxs, end, hullnum, false, clip.capsule, clip.hitcontentsmask);

View file

@ -1750,7 +1750,7 @@ static void T_Gen_CurrentRender(void)
if (img->width != vid.fbpwidth || img->height != vid.fbpheight) if (img->width != vid.fbpwidth || img->height != vid.fbpheight)
{ {
//FIXME: free the old image when its safe to do so. //FIXME: free the old image when its safe to do so.
*img = VK_CreateTexture2DArray(vid.fbpwidth, vid.fbpheight, 1, 1, -vk.backbufformat, PTI_2D, true); *img = VK_CreateTexture2DArray(vid.fbpwidth, vid.fbpheight, 1, 1, -vk.backbufformat, PTI_2D, true, shaderstate.tex_currentrender->ident);
if (!img->sampler) if (!img->sampler)
VK_CreateSampler(shaderstate.tex_currentrender->flags, img); VK_CreateSampler(shaderstate.tex_currentrender->flags, img);

View file

@ -56,8 +56,14 @@ const char *vklayerlist[] =
#ifdef VK_NO_PROTOTYPES #ifdef VK_NO_PROTOTYPES
#define VKFunc(n) PFN_vk##n vk##n; #define VKFunc(n) PFN_vk##n vk##n;
VKFunc(CreateDebugReportCallbackEXT) #ifdef VK_EXT_debug_utils
VKFunc(DestroyDebugReportCallbackEXT) VKFunc(CreateDebugUtilsMessengerEXT)
VKFunc(DestroyDebugUtilsMessengerEXT)
#endif
#ifdef VK_EXT_debug_report
VKFunc(CreateDebugReportCallbackEXT)
VKFunc(DestroyDebugReportCallbackEXT)
#endif
VKFuncs VKFuncs
#undef VKFunc #undef VKFunc
#endif #endif
@ -97,6 +103,133 @@ do { \
#define DOBACKTRACE() #define DOBACKTRACE()
#endif #endif
#ifdef VK_EXT_debug_utils
static void DebugSetName(VkObjectType objtype, uint64_t handle, const char *name)
{
if (vkSetDebugUtilsObjectNameEXT)
{
VkDebugUtilsObjectNameInfoEXT info =
{
VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT,
NULL,
objtype,
handle,
name
};
vkSetDebugUtilsObjectNameEXT(vk.device, &info);
}
}
static VkDebugUtilsMessengerEXT vk_debugucallback;
char *DebugAnnotObjectToString(VkObjectType t)
{
switch(t)
{
case VK_OBJECT_TYPE_UNKNOWN: return "VK_OBJECT_TYPE_UNKNOWN";
case VK_OBJECT_TYPE_INSTANCE: return "VK_OBJECT_TYPE_INSTANCE";
case VK_OBJECT_TYPE_PHYSICAL_DEVICE: return "VK_OBJECT_TYPE_PHYSICAL_DEVICE";
case VK_OBJECT_TYPE_DEVICE: return "VK_OBJECT_TYPE_DEVICE";
case VK_OBJECT_TYPE_QUEUE: return "VK_OBJECT_TYPE_QUEUE";
case VK_OBJECT_TYPE_SEMAPHORE: return "VK_OBJECT_TYPE_SEMAPHORE";
case VK_OBJECT_TYPE_COMMAND_BUFFER: return "VK_OBJECT_TYPE_COMMAND_BUFFER";
case VK_OBJECT_TYPE_FENCE: return "VK_OBJECT_TYPE_FENCE";
case VK_OBJECT_TYPE_DEVICE_MEMORY: return "VK_OBJECT_TYPE_DEVICE_MEMORY";
case VK_OBJECT_TYPE_BUFFER: return "VK_OBJECT_TYPE_BUFFER";
case VK_OBJECT_TYPE_IMAGE: return "VK_OBJECT_TYPE_IMAGE";
case VK_OBJECT_TYPE_EVENT: return "VK_OBJECT_TYPE_EVENT";
case VK_OBJECT_TYPE_QUERY_POOL: return "VK_OBJECT_TYPE_QUERY_POOL";
case VK_OBJECT_TYPE_BUFFER_VIEW: return "VK_OBJECT_TYPE_BUFFER_VIEW";
case VK_OBJECT_TYPE_IMAGE_VIEW: return "VK_OBJECT_TYPE_IMAGE_VIEW";
case VK_OBJECT_TYPE_SHADER_MODULE: return "VK_OBJECT_TYPE_SHADER_MODULE";
case VK_OBJECT_TYPE_PIPELINE_CACHE: return "VK_OBJECT_TYPE_PIPELINE_CACHE";
case VK_OBJECT_TYPE_PIPELINE_LAYOUT: return "VK_OBJECT_TYPE_PIPELINE_LAYOUT";
case VK_OBJECT_TYPE_RENDER_PASS: return "VK_OBJECT_TYPE_RENDER_PASS";
case VK_OBJECT_TYPE_PIPELINE: return "VK_OBJECT_TYPE_PIPELINE";
case VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT: return "VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT";
case VK_OBJECT_TYPE_SAMPLER: return "VK_OBJECT_TYPE_SAMPLER";
case VK_OBJECT_TYPE_DESCRIPTOR_POOL: return "VK_OBJECT_TYPE_DESCRIPTOR_POOL";
case VK_OBJECT_TYPE_DESCRIPTOR_SET: return "VK_OBJECT_TYPE_DESCRIPTOR_SET";
case VK_OBJECT_TYPE_FRAMEBUFFER: return "VK_OBJECT_TYPE_FRAMEBUFFER";
case VK_OBJECT_TYPE_COMMAND_POOL: return "VK_OBJECT_TYPE_COMMAND_POOL";
case VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION: return "VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION";
case VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE: return "VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE";
case VK_OBJECT_TYPE_SURFACE_KHR: return "VK_OBJECT_TYPE_SURFACE_KHR";
case VK_OBJECT_TYPE_SWAPCHAIN_KHR: return "VK_OBJECT_TYPE_SWAPCHAIN_KHR";
case VK_OBJECT_TYPE_DISPLAY_KHR: return "VK_OBJECT_TYPE_DISPLAY_KHR";
case VK_OBJECT_TYPE_DISPLAY_MODE_KHR: return "VK_OBJECT_TYPE_DISPLAY_MODE_KHR";
case VK_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT: return "VK_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT";
case VK_OBJECT_TYPE_OBJECT_TABLE_NVX: return "VK_OBJECT_TYPE_OBJECT_TABLE_NVX";
case VK_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NVX: return "VK_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NVX";
case VK_OBJECT_TYPE_DEBUG_UTILS_MESSENGER_EXT: return "VK_OBJECT_TYPE_DEBUG_UTILS_MESSENGER_EXT";
case VK_OBJECT_TYPE_VALIDATION_CACHE_EXT: return "VK_OBJECT_TYPE_VALIDATION_CACHE_EXT";
case VK_OBJECT_TYPE_RANGE_SIZE:
case VK_OBJECT_TYPE_MAX_ENUM:
break;
}
return "UNKNOWNTYPE";
}
static VKAPI_ATTR VkBool32 VKAPI_CALL mydebugutilsmessagecallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT messageType, const VkDebugUtilsMessengerCallbackDataEXT*pCallbackData, void* pUserData)
{
char prefix[64];
int l = 0; //developer level
if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT)
{ //spam?
strcpy(prefix, "VERBOSE:");
l = 2;
}
else if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT)
{ //generally stuff like 'object created'
strcpy(prefix, "INFO:");
l = 1;
}
else if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT)
strcpy(prefix, CON_WARNING"WARNING:");
else if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT)
strcpy(prefix, CON_ERROR "ERROR:");
if (messageType & VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT)
strcat(prefix, "GENERAL");
else
{
if (messageType & VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT)
strcat(prefix, "SPEC");
if (messageType & VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT)
{
if (messageType & VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT)
{
strcat(prefix, "|");
}
strcat(prefix,"PERF");
}
}
Con_DLPrintf(l, "%s[%d] %s - %s\n", prefix, pCallbackData->messageIdNumber, pCallbackData->pMessageIdName?pCallbackData->pMessageIdName:"", pCallbackData->pMessage);
if (pCallbackData->objectCount > 0)
{
uint32_t object;
for(object = 0; object < pCallbackData->objectCount; ++object)
Con_DLPrintf(l, " Object[%d] - Type %s, Value %"PRIx64", Name \"%s\"\n", object,
DebugAnnotObjectToString(pCallbackData->pObjects[object].objectType),
pCallbackData->pObjects[object].objectHandle,
pCallbackData->pObjects[object].pObjectName);
}
if (pCallbackData->cmdBufLabelCount > 0)
{
uint32_t label;
for (label = 0; label < pCallbackData->cmdBufLabelCount; ++label)
Con_DLPrintf(l, " Label[%d] - %s { %f, %f, %f, %f}\n", label,
pCallbackData->pCmdBufLabels[label].pLabelName,
pCallbackData->pCmdBufLabels[label].color[0],
pCallbackData->pCmdBufLabels[label].color[1],
pCallbackData->pCmdBufLabels[label].color[2],
pCallbackData->pCmdBufLabels[label].color[3]);
}
return false;
}
#else
#define DebugSetName(objtype,handle,name)
#endif
#ifdef VK_EXT_debug_report
static VkDebugReportCallbackEXT vk_debugcallback; static VkDebugReportCallbackEXT vk_debugcallback;
static VkBool32 VKAPI_PTR mydebugreportcallback( static VkBool32 VKAPI_PTR mydebugreportcallback(
VkDebugReportFlagsEXT flags, VkDebugReportFlagsEXT flags,
@ -146,6 +279,7 @@ static VkBool32 VKAPI_PTR mydebugreportcallback(
} }
return false; return false;
} }
#endif
//typeBits is some vulkan requirement thing (like textures must be device-local). //typeBits is some vulkan requirement thing (like textures must be device-local).
//requirements_mask are things that the engine may require (like host-visible). //requirements_mask are things that the engine may require (like host-visible).
@ -388,6 +522,7 @@ static qboolean VK_CreateSwapChain(void)
ici.initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; ici.initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
VkAssert(vkCreateImage(vk.device, &ici, vkallocationcb, &images[i])); VkAssert(vkCreateImage(vk.device, &ici, vkallocationcb, &images[i]));
DebugSetName(VK_OBJECT_TYPE_IMAGE, (uint64_t)images[i], "backbuffer");
vkGetImageMemoryRequirements(vk.device, images[i], &mem_reqs); vkGetImageMemoryRequirements(vk.device, images[i], &mem_reqs);
@ -730,6 +865,10 @@ static qboolean VK_CreateSwapChain(void)
for (i = 0; i < vk.backbuf_count; i++) for (i = 0; i < vk.backbuf_count; i++)
{ {
VkImageViewCreateInfo ivci = {VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO}; VkImageViewCreateInfo ivci = {VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO};
vk.backbufs[i].colour.image = images[i];
DebugSetName(VK_OBJECT_TYPE_IMAGE, (uint64_t)vk.backbufs[i].colour.image, "backbuffer");
ivci.format = vk.backbufformat; ivci.format = vk.backbufformat;
// ivci.components.r = VK_COMPONENT_SWIZZLE_R; // ivci.components.r = VK_COMPONENT_SWIZZLE_R;
// ivci.components.g = VK_COMPONENT_SWIZZLE_G; // ivci.components.g = VK_COMPONENT_SWIZZLE_G;
@ -743,7 +882,6 @@ static qboolean VK_CreateSwapChain(void)
ivci.viewType = VK_IMAGE_VIEW_TYPE_2D; ivci.viewType = VK_IMAGE_VIEW_TYPE_2D;
ivci.flags = 0; ivci.flags = 0;
ivci.image = images[i]; ivci.image = images[i];
vk.backbufs[i].colour.image = images[i];
if (memories) if (memories)
vk.backbufs[i].colour.mem.memory = memories[i]; vk.backbufs[i].colour.mem.memory = memories[i];
vk.backbufs[i].colour.width = swapinfo.imageExtent.width; vk.backbufs[i].colour.width = swapinfo.imageExtent.width;
@ -773,6 +911,7 @@ static qboolean VK_CreateSwapChain(void)
depthinfo.pQueueFamilyIndices = NULL; depthinfo.pQueueFamilyIndices = NULL;
depthinfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; depthinfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
VkAssert(vkCreateImage(vk.device, &depthinfo, vkallocationcb, &vk.backbufs[i].depth.image)); VkAssert(vkCreateImage(vk.device, &depthinfo, vkallocationcb, &vk.backbufs[i].depth.image));
DebugSetName(VK_OBJECT_TYPE_IMAGE, (uint64_t)vk.backbufs[i].depth.image, "backbuffer depth");
} }
//depth memory //depth memory
@ -821,6 +960,7 @@ static qboolean VK_CreateSwapChain(void)
mscolourinfo.pQueueFamilyIndices = NULL; mscolourinfo.pQueueFamilyIndices = NULL;
mscolourinfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; mscolourinfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
VkAssert(vkCreateImage(vk.device, &mscolourinfo, vkallocationcb, &vk.backbufs[i].mscolour.image)); VkAssert(vkCreateImage(vk.device, &mscolourinfo, vkallocationcb, &vk.backbufs[i].mscolour.image));
DebugSetName(VK_OBJECT_TYPE_IMAGE, (uint64_t)vk.backbufs[i].mscolour.image, "multisample");
} }
//mscolour memory //mscolour memory
@ -1088,7 +1228,7 @@ qboolean VK_AllocateBindImageMemory(vk_image_t *image, qboolean dedicated)
} }
vk_image_t VK_CreateTexture2DArray(uint32_t width, uint32_t height, uint32_t layers, uint32_t mips, uploadfmt_t encoding, unsigned int type, qboolean rendertarget) vk_image_t VK_CreateTexture2DArray(uint32_t width, uint32_t height, uint32_t layers, uint32_t mips, uploadfmt_t encoding, unsigned int type, qboolean rendertarget, const char *debugname)
{ {
vk_image_t ret; vk_image_t ret;
VkImageViewCreateInfo viewInfo = {VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO}; VkImageViewCreateInfo viewInfo = {VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO};
@ -1235,6 +1375,7 @@ vk_image_t VK_CreateTexture2DArray(uint32_t width, uint32_t height, uint32_t lay
ici.initialLayout = ret.layout; ici.initialLayout = ret.layout;
VkAssert(vkCreateImage(vk.device, &ici, vkallocationcb, &ret.image)); VkAssert(vkCreateImage(vk.device, &ici, vkallocationcb, &ret.image));
DebugSetName(VK_OBJECT_TYPE_IMAGE, (uint64_t)ret.image, debugname);
ret.view = VK_NULL_HANDLE; ret.view = VK_NULL_HANDLE;
ret.sampler = VK_NULL_HANDLE; ret.sampler = VK_NULL_HANDLE;
@ -1556,7 +1697,7 @@ qboolean VK_LoadTextureMips (texid_t tex, const struct pendingtextureinfo *mips)
} }
else else
{ {
target = VK_CreateTexture2DArray(mips->mip[0].width, mips->mip[0].height, layers, mipcount/layers, mips->encoding, mips->type, !!(tex->flags&IF_RENDERTARGET)); target = VK_CreateTexture2DArray(mips->mip[0].width, mips->mip[0].height, layers, mipcount/layers, mips->encoding, mips->type, !!(tex->flags&IF_RENDERTARGET), tex->ident);
if (target.mem.memory == VK_NULL_HANDLE) if (target.mem.memory == VK_NULL_HANDLE)
{ {
@ -2663,6 +2804,7 @@ char *VKVID_GetRGBInfo (int *bytestride, int *truevidwidth, int *truevidheight
ici.pQueueFamilyIndices = NULL; ici.pQueueFamilyIndices = NULL;
ici.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; ici.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
VkAssert(vkCreateImage(vk.device, &ici, vkallocationcb, &tempimage)); VkAssert(vkCreateImage(vk.device, &ici, vkallocationcb, &tempimage));
DebugSetName(VK_OBJECT_TYPE_IMAGE, (uint64_t)tempimage, "VKVID_GetRGBInfo staging");
vkGetImageMemoryRequirements(vk.device, tempimage, &mem_reqs); vkGetImageMemoryRequirements(vk.device, tempimage, &mem_reqs);
memAllocInfo.allocationSize = mem_reqs.size; memAllocInfo.allocationSize = mem_reqs.size;
memAllocInfo.memoryTypeIndex = vk_find_memory_require(mem_reqs.memoryTypeBits, 0); memAllocInfo.memoryTypeIndex = vk_find_memory_require(mem_reqs.memoryTypeBits, 0);
@ -2880,7 +3022,7 @@ static void VK_PaintScreen(void)
if (uimenu != 1) if (uimenu != 1)
{ {
if (r_worldentity.model && cls.state == ca_active) if (r_worldentity.model && cls.state == ca_active)
V_RenderView (); V_RenderView (nohud);
else else
{ {
noworld = true; noworld = true;
@ -3844,14 +3986,26 @@ qboolean VK_Init(rendererstate_t *info, const char **sysextnames, qboolean (*cre
qboolean surfext = false; qboolean surfext = false;
uint32_t count, i, j; uint32_t count, i, j;
VkExtensionProperties *ext; VkExtensionProperties *ext;
#ifdef VK_EXT_debug_utils
qboolean havedebugutils = false;
#endif
#ifdef VK_EXT_debug_report
qboolean havedebugreport = false;
#endif
vkEnumerateInstanceExtensionProperties(NULL, &count, NULL); vkEnumerateInstanceExtensionProperties(NULL, &count, NULL);
ext = malloc(sizeof(*ext)*count); ext = malloc(sizeof(*ext)*count);
vkEnumerateInstanceExtensionProperties(NULL, &count, ext); vkEnumerateInstanceExtensionProperties(NULL, &count, ext);
for (i = 0; i < count && extensions_count < countof(extensions); i++) for (i = 0; i < count && extensions_count < countof(extensions); i++)
{ {
if (!strcmp(ext[i].extensionName, VK_EXT_DEBUG_REPORT_EXTENSION_NAME) && vk_debug.ival) #ifdef VK_EXT_debug_utils
extensions[extensions_count++] = VK_EXT_DEBUG_REPORT_EXTENSION_NAME; if (!strcmp(ext[i].extensionName, VK_EXT_DEBUG_REPORT_EXTENSION_NAME))
else if (!strcmp(ext[i].extensionName, VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) havedebugutils = true;
#endif
#ifdef VK_EXT_debug_report
if (!strcmp(ext[i].extensionName, VK_EXT_DEBUG_REPORT_EXTENSION_NAME))
havedebugreport = true;
#endif
if (!strcmp(ext[i].extensionName, VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME))
extensions[extensions_count++] = VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME; extensions[extensions_count++] = VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME;
else if (sysextnames && !strcmp(ext[i].extensionName, VK_KHR_SURFACE_EXTENSION_NAME)) else if (sysextnames && !strcmp(ext[i].extensionName, VK_KHR_SURFACE_EXTENSION_NAME))
{ {
@ -3871,9 +4025,21 @@ qboolean VK_Init(rendererstate_t *info, const char **sysextnames, qboolean (*cre
} }
} }
free(ext); free(ext);
if (!vk_debug.ival)
;
#ifdef VK_EXT_debug_utils
else if (havedebugutils)
extensions[extensions_count++] = VK_EXT_DEBUG_UTILS_EXTENSION_NAME;
#endif
#ifdef VK_EXT_debug_report
else if (havedebugreport)
extensions[extensions_count++] = VK_EXT_DEBUG_REPORT_EXTENSION_NAME;
#endif
if (sysextnames && (!vk.khr_swapchain || !surfext)) if (sysextnames && (!vk.khr_swapchain || !surfext))
{ {
Con_Printf("Vulkan instance driver lacks support for %s\n", sysextnames[0]); Con_Printf("Vulkan instance lacks driver support for %s\n", sysextnames[0]);
return false; return false;
} }
} }
@ -3926,6 +4092,27 @@ qboolean VK_Init(rendererstate_t *info, const char **sysextnames, qboolean (*cre
//set up debug callbacks //set up debug callbacks
if (vk_debug.ival) if (vk_debug.ival)
{ {
#ifdef VK_EXT_debug_utils
vkCreateDebugUtilsMessengerEXT = (PFN_vkCreateDebugUtilsMessengerEXT)vkGetInstanceProcAddr(vk.instance, "vkCreateDebugUtilsMessengerEXT");
vkDestroyDebugUtilsMessengerEXT = (PFN_vkDestroyDebugUtilsMessengerEXT)vkGetInstanceProcAddr(vk.instance, "vkDestroyDebugUtilsMessengerEXT");
if (vkCreateDebugUtilsMessengerEXT)
{
VkDebugUtilsMessengerCreateInfoEXT dbgCreateInfo;
memset(&dbgCreateInfo, 0, sizeof(dbgCreateInfo));
dbgCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
dbgCreateInfo.pfnUserCallback = mydebugutilsmessagecallback;
dbgCreateInfo.pUserData = NULL;
dbgCreateInfo.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT |
VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT |
VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT |
VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT;
dbgCreateInfo.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT |
VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT |
VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
vkCreateDebugUtilsMessengerEXT(vk.instance, &dbgCreateInfo, vkallocationcb, &vk_debugucallback);
}
#endif
#ifdef VK_EXT_debug_report
vkCreateDebugReportCallbackEXT = (PFN_vkCreateDebugReportCallbackEXT)vkGetInstanceProcAddr(vk.instance, "vkCreateDebugReportCallbackEXT"); vkCreateDebugReportCallbackEXT = (PFN_vkCreateDebugReportCallbackEXT)vkGetInstanceProcAddr(vk.instance, "vkCreateDebugReportCallbackEXT");
vkDestroyDebugReportCallbackEXT = (PFN_vkDestroyDebugReportCallbackEXT)vkGetInstanceProcAddr(vk.instance, "vkDestroyDebugReportCallbackEXT"); vkDestroyDebugReportCallbackEXT = (PFN_vkDestroyDebugReportCallbackEXT)vkGetInstanceProcAddr(vk.instance, "vkDestroyDebugReportCallbackEXT");
if (vkCreateDebugReportCallbackEXT && vkDestroyDebugReportCallbackEXT) if (vkCreateDebugReportCallbackEXT && vkDestroyDebugReportCallbackEXT)
@ -3942,6 +4129,7 @@ qboolean VK_Init(rendererstate_t *info, const char **sysextnames, qboolean (*cre
VK_DEBUG_REPORT_DEBUG_BIT_EXT; VK_DEBUG_REPORT_DEBUG_BIT_EXT;
vkCreateDebugReportCallbackEXT(vk.instance, &dbgCreateInfo, vkallocationcb, &vk_debugcallback); vkCreateDebugReportCallbackEXT(vk.instance, &dbgCreateInfo, vkallocationcb, &vk_debugcallback);
} }
#endif
} }
//create the platform-specific surface //create the platform-specific surface
@ -4461,11 +4649,20 @@ void VK_Shutdown(void)
if (vk.device) if (vk.device)
vkDestroyDevice(vk.device, vkallocationcb); vkDestroyDevice(vk.device, vkallocationcb);
#ifdef VK_EXT_debug_utils
if (vk_debugucallback)
{
vkDestroyDebugUtilsMessengerEXT(vk.instance, vk_debugucallback, vkallocationcb);
vk_debugucallback = VK_NULL_HANDLE;
}
#endif
#ifdef VK_EXT_debug_report
if (vk_debugcallback) if (vk_debugcallback)
{ {
vkDestroyDebugReportCallbackEXT(vk.instance, vk_debugcallback, vkallocationcb); vkDestroyDebugReportCallbackEXT(vk.instance, vk_debugcallback, vkallocationcb);
vk_debugcallback = VK_NULL_HANDLE; vk_debugcallback = VK_NULL_HANDLE;
} }
#endif
if (vk.surface) if (vk.surface)
vkDestroySurfaceKHR(vk.instance, vk.surface, vkallocationcb); vkDestroySurfaceKHR(vk.instance, vk.surface, vkallocationcb);

View file

@ -28,7 +28,7 @@
#endif #endif
#define VK_NO_PROTOTYPES #define VK_NO_PROTOTYPES
#include "../vulkan/vulkan.h" #include <vulkan/vulkan.h>
#if defined(_MSC_VER) && !defined(UINT64_MAX) #if defined(_MSC_VER) && !defined(UINT64_MAX)
#define UINT64_MAX _UI64_MAX #define UINT64_MAX _UI64_MAX
@ -51,6 +51,12 @@
#endif #endif
#define VKInstArchFuncs VKInstWin32Funcs VKInstXLibFuncs VKInstXCBFuncs VKInstWaylandFuncs #define VKInstArchFuncs VKInstWin32Funcs VKInstXLibFuncs VKInstXCBFuncs VKInstWaylandFuncs
#ifdef VK_EXT_debug_utils
#define VKDebugFuncs \
VKFunc(SetDebugUtilsObjectNameEXT)
#else
#define VKDebugFuncs
#endif
//funcs needed for creating an instance //funcs needed for creating an instance
#define VKInstFuncs \ #define VKInstFuncs \
@ -61,7 +67,6 @@
//funcs specific to an instance //funcs specific to an instance
#define VKInst2Funcs \ #define VKInst2Funcs \
VKFunc(EnumeratePhysicalDevices) \ VKFunc(EnumeratePhysicalDevices) \
VKFunc(EnumeratePhysicalDeviceGroupsKHX) \
VKFunc(EnumerateDeviceExtensionProperties) \ VKFunc(EnumerateDeviceExtensionProperties) \
VKFunc(GetPhysicalDeviceProperties) \ VKFunc(GetPhysicalDeviceProperties) \
VKFunc(GetPhysicalDeviceQueueFamilyProperties) \ VKFunc(GetPhysicalDeviceQueueFamilyProperties) \
@ -75,6 +80,7 @@
VKFunc(DestroySurfaceKHR) \ VKFunc(DestroySurfaceKHR) \
VKFunc(CreateDevice) \ VKFunc(CreateDevice) \
VKFunc(DestroyInstance) \ VKFunc(DestroyInstance) \
VKDebugFuncs \
VKInstArchFuncs VKInstArchFuncs
//funcs specific to a device //funcs specific to a device
@ -169,7 +175,6 @@
VKFunc(CreateImageView) \ VKFunc(CreateImageView) \
VKFunc(DestroyImageView) VKFunc(DestroyImageView)
//all vulkan funcs //all vulkan funcs
#define VKFuncs \ #define VKFuncs \
VKInstFuncs \ VKInstFuncs \
@ -488,7 +493,7 @@ struct stagingbuf
size_t size; size_t size;
VkBufferUsageFlags usage; VkBufferUsageFlags usage;
}; };
vk_image_t VK_CreateTexture2DArray(uint32_t width, uint32_t height, uint32_t layers, uint32_t mips, uploadfmt_t encoding, unsigned int type, qboolean rendertarget); vk_image_t VK_CreateTexture2DArray(uint32_t width, uint32_t height, uint32_t layers, uint32_t mips, uploadfmt_t encoding, unsigned int type, qboolean rendertarget, const char *debugname);
void set_image_layout(VkCommandBuffer cmd, VkImage image, VkImageAspectFlags aspectMask, VkImageLayout old_image_layout, VkAccessFlags srcaccess, VkPipelineStageFlagBits srcstagemask, VkImageLayout new_image_layout, VkAccessFlags dstaccess, VkPipelineStageFlagBits dststagemask); void set_image_layout(VkCommandBuffer cmd, VkImage image, VkImageAspectFlags aspectMask, VkImageLayout old_image_layout, VkAccessFlags srcaccess, VkPipelineStageFlagBits srcstagemask, VkImageLayout new_image_layout, VkAccessFlags dstaccess, VkPipelineStageFlagBits dststagemask);
void VK_CreateSampler(unsigned int flags, vk_image_t *img); void VK_CreateSampler(unsigned int flags, vk_image_t *img);
void *VKBE_CreateStagingBuffer(struct stagingbuf *n, size_t size, VkBufferUsageFlags usage); void *VKBE_CreateStagingBuffer(struct stagingbuf *n, size_t size, VkBufferUsageFlags usage);

View file

@ -20,7 +20,10 @@ Unless you're doing complex stuff like any of the above, there's probably not al
Command File Format: Command File Format:
output <FILENAME> - specified the output file name. you should only have one of these. output <FILENAME> - specifies the output file name. you should only have one of each type of output.
output_qmdl <FILENAME> - specifies which file to write a quake1-format model. May only occur once.
output_md16 <FILENAME> - specifies the filename to write a quakeforge 16-bit md16 model to (a upgraded variation of quake's format). May only occur once.
output_md3 <FILENAME> - specifies the filename to write a quake3 md3 file to. May only occur once.
exec <FILENAME> - exec the specified command file, before parsing the rest of the current file. exec <FILENAME> - exec the specified command file, before parsing the rest of the current file.
hitbox <BODY NUM> <BONE NAME> <MIN POS VECTOR> <MAX POS VECTOR> - generates a hitmesh as a bbox centered around the bone in the base pose (the hitbox will rotate/move with animations). The bodynum will be visible to gamecode, and may merge with other hitboxes with the same group. hitbox <BODY NUM> <BONE NAME> <MIN POS VECTOR> <MAX POS VECTOR> - generates a hitmesh as a bbox centered around the bone in the base pose (the hitbox will rotate/move with animations). The bodynum will be visible to gamecode, and may merge with other hitboxes with the same group.
modelflags <NAME OR HEX> - enables the specified bit in the iqm header. supported names include q1_rocket, q1_grenade, q1_gib, q1_rotate, q1_tracer1, q1_zomgib, q1_tracer2, q1_tracer3 modelflags <NAME OR HEX> - enables the specified bit in the iqm header. supported names include q1_rocket, q1_grenade, q1_gib, q1_rotate, q1_tracer1, q1_zomgib, q1_tracer2, q1_tracer3
@ -53,4 +56,4 @@ Anim/Import Properties:
scale <SCALER> - rescales the model scale <SCALER> - rescales the model
origin <X> <Y> <Z> - moves the thing origin <X> <Y> <Z> - moves the thing
event [ANIM,]<POSE[.FRAC]> <EVENTCODE> <"EVENTDATA"> - embeds event info within the animation, for stuff like footsteps. How this is used depends on the engine... If used at global scope, can be reset with 'event reset' in order to not apply to later files. event [ANIM,]<POSE[.FRAC]> <EVENTCODE> <"EVENTDATA"> - embeds event info within the animation, for stuff like footsteps. How this is used depends on the engine... If used at global scope, can be reset with 'event reset' in order to not apply to later files.

View file

@ -4283,6 +4283,243 @@ bool writeiqm(const char *filename)
} }
uchar qmdl_bestnorm(Vec3 &v)
{
//FIXME
return 0;
}
struct qmdl_vertex_t
{
unsigned char v[3];
unsigned char normalIndex;
};
template<int md16> bool writemdl(const char *filename)
{
if (meshes.length() != 1)
{
conoutf("warning: mdl output requires exactly one mesh");
return false; //must have ONE mesh only.
}
auto mesh = meshes[0];
vertexarray *texcoords = NULL;
vertexarray *vertcoords = NULL;
vertexarray *vertnorm = NULL;
uint skinwidth = 0;
uint skinheight = 0;
Vec3 offset={0,0,0};
Vec3 scale={1,1,1};
uint numskins = 0;
vector<uchar> skindata;
loopv(varrays)
{
if(varrays[i].type == IQM_TEXCOORD && varrays[i].format == IQM_FLOAT && varrays[i].count == 2)
texcoords = &varrays[i];
if(varrays[i].type == IQM_POSITION && varrays[i].format == IQM_FLOAT && varrays[i].count == 3)
vertcoords = &varrays[i];
if(varrays[i].type == IQM_NORMAL && varrays[i].format == IQM_FLOAT && varrays[i].count == 3)
vertnorm = &varrays[i];
// if(varrays[i].type == IQM_BLENDINDEXES && varrays[i].format == IQM_BYTE && varrays[i].count == 4)
// vertbones = &varrays[i];
// if(varrays[i].type == IQM_BLENDWEIGHTS && varrays[i].format == IQM_FLOAT && varrays[i].count == 4)
// vertweights = &varrays[i];
}
if (!texcoords)
{
conoutf("warning: mdl output requires a float texcoord array");
return false; //must have some vertex coords...
}
float *tcdata = (float*)texcoords->vdata.getbuf();
skinwidth = 4;
skinheight = 4;
memset(skindata.reserve(skinwidth*skinheight), 15, skinwidth*skinheight);
skindata.advance(skinwidth*skinheight);
numskins++;
//we're going to need the transformed pose data, without any bone weights getting in the way.
vector<Vec3> vpos, vnorm;
Vec3 min={FLT_MAX,FLT_MAX,FLT_MAX}, max={-FLT_MAX,-FLT_MAX,-FLT_MAX};
loopv(anims)
{
anim &a = anims[i];
Vec3 *outv = vpos.reserve(mesh.numverts*a.numframes);
Vec3 *outn = vnorm.reserve(mesh.numverts*a.numframes);
Vec3 *invert = (Vec3*)vertcoords->vdata.getbuf();
Vec3 *innorm = (Vec3*)vertnorm->vdata.getbuf();
// uchar *inbones = (uchar*)vertbones->vdata.getbuf();
// Vec4 *inweights = (Vec4*)vertweights->vdata.getbuf();
for (int j = 0; j < a.numframes; j++)
{
//FIXME: generate bone matricies
for (int i = mesh.firstvert; i < mesh.numverts; i++, outv++, outn++)
{
//FIXME: generate vert's matrix
//transform each vert
*outv = invert[i];
//bound it to find the model's extents
for (uint c = 0; c < 3; c++)
{
if (min.v[c] > outv->v[c])
min.v[c] = outv->v[c];
if (max.v[c] < outv->v[c])
max.v[c] = outv->v[c];
}
*outn = innorm[i];
}
vpos.advance(mesh.numverts);
vnorm.advance(mesh.numverts);
}
}
offset = -min;
scale = (max-min)/255; //ignore low order info here
stream *f = openfile(filename, "wb");
if(!f) return false;
if (md16)
f->putlil((uint)(('M'<<0)|('D'<<8)|('1'<<16)|('6'<<24)));
else
f->putlil((uint)(('I'<<0)|('D'<<8)|('P'<<16)|('O'<<24)));
f->putlil((uint)6); //version
f->putlil((float)scale[0]);
f->putlil((float)scale[1]);
f->putlil((float)scale[2]);
f->putlil((float)offset[0]);
f->putlil((float)offset[1]);
f->putlil((float)offset[2]);
f->putlil(0.f); //radius
f->putlil(0.f); //eyeposx, never used afaik
f->putlil(0.f); //eyeposy
f->putlil(0.f); //eyeposz
f->putlil((uint)numskins);
f->putlil((uint)skinwidth);
f->putlil((uint)skinheight);
f->putlil((uint)mesh.numverts);
f->putlil((uint)mesh.numtris);
f->putlil((uint)anims.length()); //numanims
f->putlil((uint)0); //synctype
f->putlil((uint)modelflags); //flags
f->putlil(0.f); //size
//skins
for (int i = 0; i < numskins; i++)
{
f->putlil((uint)0); //ALIAS_SKIN_SINGLE
f->write(skindata.getbuf()+i*skinwidth*skinheight, skinwidth*skinheight);
}
//texcoords
for (int i = mesh.firstvert; i < mesh.numverts; i++)
{
f->putlil((uint)(0?32:0)); //onseam. no verts are ever onseam for us, as we don't do that nonsense here.
f->putlil((int)((tcdata[i*2+0]+.5)*skinwidth)); //mdl texcoords are ints, in texels. which sucks, but what can you do...
f->putlil((int)((tcdata[i*2+1]+.5)*skinheight));
}
//tris
for (int i = mesh.firsttri; i < mesh.firsttri+mesh.numtris; i++)
{
f->putlil((uint)1); //faces front. All are effectively front-facing for us. This avoids annoying tc additions.
f->putlil((uint)triangles[i].vert[0]);
f->putlil((uint)triangles[i].vert[1]);
f->putlil((uint)triangles[i].vert[2]);
}
//animations
vector<qmdl_vertex_t> high, low;
size_t voffset = 0;
loopv(anims)
{
anim &a = anims[i];
for (int j = 0; j < a.numframes; j++)
{
qmdl_vertex_t *th=high.reserve(mesh.numverts),*tl=low.reserve(mesh.numverts);
for (int i = mesh.firstvert; i < mesh.numverts; i++, th++, tl++)
{
int l;
for (uint c = 0; c < 3; c++)
{
l = (((vpos[voffset][c]-offset[c])*256) / scale[c]);
if (l<0) l = 0;
if (l > 0xff00) l = 0xff00; //0xffff would exceed the bounds values, so don't use it.
th->v[c] = l>>8;
tl->v[c] = l&0xff;
}
tl->normalIndex = th->normalIndex = qmdl_bestnorm(vnorm[voffset]);
voffset++;
}
high.advance(mesh.numverts);
low.advance(mesh.numverts);
}
}
voffset = 0;
loopv(anims)
{
anim &a = anims[i];
if (a.numframes == 1)
f->putlil((uint)0); //single-pose type
else
{
f->putlil((uint)1); //anim type
f->putlil((uint)a.numframes);
qmdl_vertex_t min={{255,255,255}}, max={{0,0,0}};
for (uint k = 0; k < mesh.numverts*a.numframes; k++)
{
for (uint c = 0; c < 3; c++)
{
if (min.v[c] > high[voffset+k].v[c])
min.v[c] = high[voffset+k].v[c];
if (max.v[c] < high[voffset+k].v[c])
max.v[c] = high[voffset+k].v[c];
}
}
f->put(min);
f->put(max);
for (int j = 0; j < a.numframes; j++)
f->putlil(1.0f/a.fps); //intervals. we use the same value for each
}
for (int j = 0; j < a.numframes; j++)
{
char name[16]={0};
qmdl_vertex_t min={{255,255,255}}, max={{0,0,0}};
for (uint k = 0; k < mesh.numverts; k++)
{
for (uint c = 0; c < 3; c++)
{
if (min.v[c] > high[voffset+k].v[c])
min.v[c] = high[voffset+k].v[c];
if (max.v[c] < high[voffset+k].v[c])
max.v[c] = high[voffset+k].v[c];
}
}
f->put(min);
f->put(max);
strncpy(name, &stringdata[a.name], sizeof(name));
f->put(name);
f->write(&high[voffset], sizeof(qmdl_vertex_t)*mesh.numverts);
if (md16)
f->write(&low[voffset], sizeof(qmdl_vertex_t)*mesh.numverts);
voffset += mesh.numverts;
}
}
delete f;
return true;
}
void help(bool exitstatus = EXIT_SUCCESS) void help(bool exitstatus = EXIT_SUCCESS)
{ {
fprintf(exitstatus != EXIT_SUCCESS ? stderr : stdout, fprintf(exitstatus != EXIT_SUCCESS ? stderr : stdout,
@ -4568,7 +4805,20 @@ bool parseanimfield(const char *tok, char **line, filespec &spec, bool defaults)
return true; return true;
} }
void parsecommands(char *filename, const char *&outfile, vector<filespec> &infiles, vector<hitbox> &hitboxes) struct
{
bool (*write)(const char *filename);
const char *cmdname;
const char *altcmdname;
} outputtypes[] =
{
{writeiqm, "output_iqm"},
{writemdl<0>, "output_qmdl"},
{writemdl<1>, "output_md16"},
// {writemd3, "output_md3"},
};
void parsecommands(char *filename, const char *outfiles[countof(outputtypes)], vector<filespec> &infiles, vector<hitbox> &hitboxes)
{ {
filespec defaultspec; filespec defaultspec;
defaultspec.reset(); defaultspec.reset();
@ -4586,7 +4836,7 @@ void parsecommands(char *filename, const char *&outfile, vector<filespec> &infil
char buf[2048]; char buf[2048];
while(f->getline(buf, sizeof(buf))) while(f->getline(buf, sizeof(buf)))
{ {
char *tok; const char *tok;
char *line = buf; char *line = buf;
tok = mystrtok(&line); tok = mystrtok(&line);
if (tok && *tok == '$') if (tok && *tok == '$')
@ -4600,8 +4850,6 @@ void parsecommands(char *filename, const char *&outfile, vector<filespec> &infil
} }
// else if (!strcasecmp(tok, "outputdir")) // else if (!strcasecmp(tok, "outputdir"))
// (void)mystrtok(&line); // (void)mystrtok(&line);
else if (!strcasecmp(tok, "output"))
outfile = newstring(mystrtok(&line));
else if (!strcasecmp(tok, "hitbox") || !strcasecmp(tok, "hbox")) else if (!strcasecmp(tok, "hitbox") || !strcasecmp(tok, "hbox"))
{ {
hitbox &hb = hitboxes.add(); hitbox &hb = hitboxes.add();
@ -4613,7 +4861,7 @@ void parsecommands(char *filename, const char *&outfile, vector<filespec> &infil
hb.maxs[i] = atof(mystrtok(&line)); hb.maxs[i] = atof(mystrtok(&line));
} }
else if (!strcasecmp(tok, "exec")) else if (!strcasecmp(tok, "exec"))
parsecommands(mystrtok(&line), outfile, infiles, hitboxes); parsecommands(mystrtok(&line), outfiles, infiles, hitboxes);
else if (!strcasecmp(tok, "modelflags")) else if (!strcasecmp(tok, "modelflags"))
{ {
bitnames modelflagnames[] = { bitnames modelflagnames[] = {
@ -4691,10 +4939,34 @@ void parsecommands(char *filename, const char *&outfile, vector<filespec> &infil
infiles.add(inspec); infiles.add(inspec);
} }
else if (*tok) else
{ {
printf("unsupported command \"%s\"\n", tok); size_t n, j;
continue; if (!strcasecmp(tok, "output"))
tok = "output_iqm";
for (n = 0; n < countof(outputtypes); n++)
{
if (!strcasecmp(tok, outputtypes[n].cmdname))
{
outfiles[n] = newstring(mystrtok(&line));
for (j = 0; j < countof(outputtypes); j++)
{
if (n!=j && outfiles[j] && !strcasecmp(outfiles[n], outfiles[j]))
{
printf("cancelling %s\n", outputtypes[j].cmdname);
outfiles[j] = NULL;
break;
}
}
tok = "";
break;
}
}
if (*tok)
{
printf("unsupported command \"%s\"\n", tok);
continue;
}
} }
if ((tok=mystrtok(&line))) if ((tok=mystrtok(&line)))
@ -4711,14 +4983,14 @@ int main(int argc, char **argv)
vector<filespec> infiles; vector<filespec> infiles;
vector<hitbox> hitboxes; vector<hitbox> hitboxes;
filespec inspec; filespec inspec;
const char *outfile = NULL; const char *outfiles[countof(outputtypes)] = {};
for(int i = 1; i < argc; i++) for(int i = 1; i < argc; i++)
{ {
if(argv[i][0] == '-') if(argv[i][0] == '-')
{ {
if(argv[i][1] == '-') if(argv[i][1] == '-')
{ {
if(!strcasecmp(&argv[i][2], "cmd")) { if(i + 1 < argc) parsecommands(argv[++i], outfile, infiles, hitboxes); } if(!strcasecmp(&argv[i][2], "cmd")) { if(i + 1 < argc) parsecommands(argv[++i], outfiles, infiles, hitboxes); }
else if(!strcasecmp(&argv[i][2], "noext")) noext = true; else if(!strcasecmp(&argv[i][2], "noext")) noext = true;
else if(!strcasecmp(&argv[i][2], "fps")) { if(i + 1 < argc) inspec.fps = atof(argv[++i]); } else if(!strcasecmp(&argv[i][2], "fps")) { if(i + 1 < argc) inspec.fps = atof(argv[++i]); }
else if(!strcasecmp(&argv[i][2], "name")) { if(i + 1 < argc) inspec.name = argv[++i]; } else if(!strcasecmp(&argv[i][2], "name")) { if(i + 1 < argc) inspec.name = argv[++i]; }
@ -4762,9 +5034,9 @@ int main(int argc, char **argv)
{ {
const char *type = strrchr(argv[i], '.'); const char *type = strrchr(argv[i], '.');
if (type && (!strcasecmp(type, ".cmd")||!strcasecmp(type, ".cfg")||!strcasecmp(type, ".txt")||!strcasecmp(type, ".qc"))) //.qc to humour halflife fanboys if (type && (!strcasecmp(type, ".cmd")||!strcasecmp(type, ".cfg")||!strcasecmp(type, ".txt")||!strcasecmp(type, ".qc"))) //.qc to humour halflife fanboys
parsecommands(argv[i], outfile, infiles, hitboxes); parsecommands(argv[i], outfiles, infiles, hitboxes);
else if(!outfile) else if(!outfiles[0] && !outfiles[1] && !outfiles[2])
outfile = argv[i]; outfiles[0] = argv[i]; //first arg is the output name, if its not an export script thingie.
else else
{ {
infiles.add(inspec).file = argv[i]; infiles.add(inspec).file = argv[i];
@ -4773,8 +5045,10 @@ int main(int argc, char **argv)
} }
} }
if(!outfile) fatal("no output file specified"); size_t n;
else if(infiles.empty()) fatal("no input files specified"); for (n = 0; n < countof(outputtypes) && !outfiles[n]; n++);
if(n == countof(outfiles)) fatal("no output file specified");
if(infiles.empty()) fatal("no input files specified");
if(gscale != 1) printf("scale: %f\n", escale); if(gscale != 1) printf("scale: %f\n", escale);
if(gmeshtrans != Vec3(0, 0, 0)) printf("mesh translate: %f, %f, %f\n", gmeshtrans.x, gmeshtrans.y, gmeshtrans.z); if(gmeshtrans != Vec3(0, 0, 0)) printf("mesh translate: %f, %f, %f\n", gmeshtrans.x, gmeshtrans.y, gmeshtrans.z);
@ -4833,13 +5107,18 @@ int main(int argc, char **argv)
if (!quiet) if (!quiet)
conoutf(""); conoutf("");
if(writeiqm(outfile)) for (size_t n = 0; n < countof(outputtypes); n++)
{ {
if (!quiet) if (outfiles[n] != NULL)
conoutf("exported: %s", outfile); {
if(outputtypes[n].write(outfiles[n]))
{
if (!quiet)
conoutf("exported: %s", outfiles[n]);
}
else fatal("failed writing: %s", outfiles[n]);
}
} }
else fatal("failed writing: %s", outfile);
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }

View file

@ -6,6 +6,7 @@
#include <stdarg.h> #include <stdarg.h>
#include <limits.h> #include <limits.h>
#include <assert.h> #include <assert.h>
#include <float.h>
#include "iqm.h" #include "iqm.h"
#define ASSERT(c) if(c) {} #define ASSERT(c) if(c) {}
@ -76,6 +77,7 @@ static inline T min(T a, T b)
return a < b ? a : b; return a < b ? a : b;
} }
#define countof(n) (sizeof(n)/sizeof(n[0]))
#define clamp(a,b,c) (max(b, min(a, c))) #define clamp(a,b,c) (max(b, min(a, c)))
#define loop(v,m) for(int v = 0; v<int(m); v++) #define loop(v,m) for(int v = 0; v<int(m); v++)

View file

@ -6,6 +6,8 @@
static cvar_t *ffmpeg_audiodecoder; static cvar_t *ffmpeg_audiodecoder;
#define HAVE_DECOUPLED_API (LIBAVCODEC_VERSION_MAJOR>57 || (LIBAVCODEC_VERSION_MAJOR==57&&LIBAVCODEC_VERSION_MINOR>=36))
struct avaudioctx struct avaudioctx
{ {
//raw file //raw file
@ -56,6 +58,127 @@ static void S_AV_Purge(sfx_t *s)
memset(&s->decoder, 0, sizeof(s->decoder)); memset(&s->decoder, 0, sizeof(s->decoder));
} }
static void S_AV_ReadFrame(struct avaudioctx *ctx)
{ //reads an audioframe and spits its data into the output sound file for the game engine to use.
int width = 2;
int channels = ctx->pACodecCtx->channels;
unsigned int auddatasize = av_samples_get_buffer_size(NULL, ctx->pACodecCtx->channels, ctx->pAFrame->nb_samples, ctx->pACodecCtx->sample_fmt, 1);
void *auddata = ctx->pAFrame->data[0];
switch(ctx->pACodecCtx->sample_fmt)
{ //we don't support planar audio. we just treat it as mono instead.
default:
auddatasize = 0;
break;
case AV_SAMPLE_FMT_U8P:
auddatasize /= channels;
channels = 1;
case AV_SAMPLE_FMT_U8:
width = 1;
break;
case AV_SAMPLE_FMT_S16P:
auddatasize /= channels;
channels = 1;
case AV_SAMPLE_FMT_S16:
width = 2;
break;
case AV_SAMPLE_FMT_FLTP:
//FIXME: support float audio internally.
{
float *in[2] = {(float*)ctx->pAFrame->data[0],(float*)ctx->pAFrame->data[1]};
signed short *out = (void*)auddata;
int v;
unsigned int i, c;
unsigned int frames = ctx->pAFrame->nb_samples;
if (channels > 2)
channels = 2;
for (i = 0; i < frames; i++)
{
for (c = 0; c < channels; c++)
{
v = (short)(in[c][i]*32767);
if (v < -32767)
v = -32767;
else if (v > 32767)
v = 32767;
*out++ = v;
}
}
width = sizeof(*out);
auddatasize = frames*width*channels;
}
break;
case AV_SAMPLE_FMT_FLT:
//FIXME: support float audio internally.
{
float *in = (void*)auddata;
signed short *out = (void*)auddata;
int v;
unsigned int i;
for (i = 0; i < auddatasize/sizeof(*in); i++)
{
v = (short)(in[i]*32767);
if (v < -32767)
v = -32767;
else if (v > 32767)
v = 32767;
out[i] = v;
}
auddatasize/=2;
width = 2;
}
case AV_SAMPLE_FMT_DBLP:
auddatasize /= channels;
channels = 1;
case AV_SAMPLE_FMT_DBL:
{
double *in = (double*)auddata;
signed short *out = (void*)auddata;
int v;
unsigned int i;
for (i = 0; i < auddatasize/sizeof(*in); i++)
{
v = (short)(in[i]*32767);
if (v < -32767)
v = -32767;
else if (v > 32767)
v = 32767;
out[i] = v;
}
auddatasize/=4;
width = 2;
}
break;
}
if (ctx->samples_channels != channels || ctx->samples_speed != ctx->pACodecCtx->sample_rate || ctx->samples_width != width)
{ //something changed, update
ctx->samples_channels = channels;
ctx->samples_speed = ctx->pACodecCtx->sample_rate;
ctx->samples_width = width;
//and discard any decoded audio. this might loose some.
ctx->samples_start += ctx->samples_count;
ctx->samples_count = 0;
}
if (ctx->samples_max < (ctx->samples_count*ctx->samples_width*ctx->samples_channels)+auddatasize)
{
ctx->samples_max = (ctx->samples_count*ctx->samples_width*ctx->samples_channels)+auddatasize;
ctx->samples_max *= 2; //slop
ctx->samples_buffer = realloc(ctx->samples_buffer, ctx->samples_max);
}
if (width == 1)
{ //FTE uses signed 8bit audio. ffmpeg uses unsigned 8bit audio. *sigh*.
char *out = (char*)(ctx->samples_buffer + ctx->samples_count*(ctx->samples_width*ctx->samples_channels));
unsigned char *in = auddata;
int i;
for (i = 0; i < auddatasize; i++)
out[i] = in[i]-128;
}
else
memcpy(ctx->samples_buffer + ctx->samples_count*(ctx->samples_width*ctx->samples_channels), auddata, auddatasize);
ctx->samples_count += auddatasize/(ctx->samples_width*ctx->samples_channels);
}
static sfxcache_t *S_AV_Locate(sfx_t *sfx, sfxcache_t *buf, ssamplepos_t start, int length) static sfxcache_t *S_AV_Locate(sfx_t *sfx, sfxcache_t *buf, ssamplepos_t start, int length)
{ //warning: can be called on a different thread. { //warning: can be called on a different thread.
struct avaudioctx *ctx = (struct avaudioctx*)sfx->decoder.buf; struct avaudioctx *ctx = (struct avaudioctx*)sfx->decoder.buf;
@ -67,12 +190,21 @@ static sfxcache_t *S_AV_Locate(sfx_t *sfx, sfxcache_t *buf, ssamplepos_t start,
curtime = start + length; curtime = start + length;
// curtime = (mediatime * ctx->denum) / ctx->num;
while (1) while (1)
{ {
if (ctx->lasttime > curtime) if (start < ctx->samples_start)
break; break; //o.O rewind!
if (ctx->samples_start+ctx->samples_count > curtime)
break; //no need yet.
#ifdef HAVE_DECOUPLED_API
if(0==avcodec_receive_frame(ctx->pACodecCtx, ctx->pAFrame))
{
S_AV_ReadFrame(ctx);
continue;
}
#endif
// We're ahead of the previous frame. try and read the next. // We're ahead of the previous frame. try and read the next.
if (av_read_frame(ctx->pFormatCtx, &packet) < 0) if (av_read_frame(ctx->pFormatCtx, &packet) < 0)
@ -81,11 +213,14 @@ static sfxcache_t *S_AV_Locate(sfx_t *sfx, sfxcache_t *buf, ssamplepos_t start,
// Is this a packet from the video stream? // Is this a packet from the video stream?
if(packet.stream_index==ctx->audioStream) if(packet.stream_index==ctx->audioStream)
{ {
#ifdef HAVE_DECOUPLED_API
avcodec_send_packet(ctx->pACodecCtx, &packet);
#else
int okay; int okay;
int len; int len;
void *odata = packet.data; void *odata = packet.data;
while (packet.size > 0) while (packet.size > 0)
{ { //this old api only decodes part of the packet with each itteration, so keep reading until we decoded the entire thing.
okay = false; okay = false;
len = avcodec_decode_audio4(ctx->pACodecCtx, ctx->pAFrame, &okay, &packet); len = avcodec_decode_audio4(ctx->pACodecCtx, ctx->pAFrame, &okay, &packet);
if (len < 0) if (len < 0)
@ -93,105 +228,10 @@ static sfxcache_t *S_AV_Locate(sfx_t *sfx, sfxcache_t *buf, ssamplepos_t start,
packet.size -= len; packet.size -= len;
packet.data += len; packet.data += len;
if (okay) if (okay)
{ S_AV_ReadFrame(ctx);
int width = 2;
int channels = ctx->pACodecCtx->channels;
unsigned int auddatasize = av_samples_get_buffer_size(NULL, ctx->pACodecCtx->channels, ctx->pAFrame->nb_samples, ctx->pACodecCtx->sample_fmt, 1);
void *auddata = ctx->pAFrame->data[0];
switch(ctx->pACodecCtx->sample_fmt)
{ //we don't support planar audio. we just treat it as mono instead.
default:
auddatasize = 0;
break;
case AV_SAMPLE_FMT_U8P:
auddatasize /= channels;
channels = 1;
case AV_SAMPLE_FMT_U8:
width = 1;
break;
case AV_SAMPLE_FMT_S16P:
auddatasize /= channels;
channels = 1;
case AV_SAMPLE_FMT_S16:
width = 2;
break;
case AV_SAMPLE_FMT_FLTP:
auddatasize /= channels;
channels = 1;
case AV_SAMPLE_FMT_FLT:
//FIXME: support float audio internally.
{
float *in = (void*)auddata;
signed short *out = (void*)auddata;
int v;
unsigned int i;
for (i = 0; i < auddatasize/sizeof(*in); i++)
{
v = (short)(in[i]*32767);
if (v < -32767)
v = -32767;
else if (v > 32767)
v = 32767;
out[i] = v;
}
auddatasize/=2;
width = 2;
}
case AV_SAMPLE_FMT_DBLP:
auddatasize /= channels;
channels = 1;
case AV_SAMPLE_FMT_DBL:
{
double *in = (double*)auddata;
signed short *out = (void*)auddata;
int v;
unsigned int i;
for (i = 0; i < auddatasize/sizeof(*in); i++)
{
v = (short)(in[i]*32767);
if (v < -32767)
v = -32767;
else if (v > 32767)
v = 32767;
out[i] = v;
}
auddatasize/=4;
width = 2;
}
break;
}
if (ctx->samples_channels != channels || ctx->samples_speed != ctx->pACodecCtx->sample_rate || ctx->samples_width != width)
{ //something changed, update
ctx->samples_channels = channels;
ctx->samples_speed = ctx->pACodecCtx->sample_rate;
ctx->samples_width = width;
//and discard any decoded audio. this might loose some.
ctx->samples_start += ctx->samples_count;
ctx->samples_count = 0;
}
if (ctx->samples_max < (ctx->samples_count*ctx->samples_width*ctx->samples_channels)+auddatasize)
{
ctx->samples_max = (ctx->samples_count*ctx->samples_width*ctx->samples_channels)+auddatasize;
ctx->samples_max *= 2; //slop
ctx->samples_buffer = realloc(ctx->samples_buffer, ctx->samples_max);
}
if (width == 1)
{ //FTE uses signed 8bit audio. ffmpeg uses unsigned 8bit audio. *sigh*.
char *out = (char*)(ctx->samples_buffer + ctx->samples_count*(ctx->samples_width*ctx->samples_channels));
unsigned char *in = auddata;
int i;
for (i = 0; i < auddatasize; i++)
out[i] = in[i]-128;
}
else
memcpy(ctx->samples_buffer + ctx->samples_count*(ctx->samples_width*ctx->samples_channels), auddata, auddatasize);
ctx->samples_count += auddatasize/(ctx->samples_width*ctx->samples_channels);
}
} }
packet.data = odata; packet.data = odata;
#endif
} }
// Free the packet that was allocated by av_read_frame // Free the packet that was allocated by av_read_frame
@ -319,16 +359,29 @@ static qboolean QDECL S_LoadAVSound (sfx_t *s, qbyte *data, size_t datalen, int
{ {
ctx->audioStream=-1; ctx->audioStream=-1;
for(i=0; i<ctx->pFormatCtx->nb_streams; i++) for(i=0; i<ctx->pFormatCtx->nb_streams; i++)
#if LIBAVFORMAT_VERSION_MAJOR >= 57
if(ctx->pFormatCtx->streams[i]->codecpar->codec_type==AVMEDIA_TYPE_AUDIO)
#else
if(ctx->pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_AUDIO) if(ctx->pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_AUDIO)
#endif
{ {
ctx->audioStream=i; ctx->audioStream=i;
break; break;
} }
if(ctx->audioStream!=-1) if(ctx->audioStream!=-1)
{ {
#if LIBAVFORMAT_VERSION_MAJOR >= 57
pCodec=avcodec_find_decoder(ctx->pFormatCtx->streams[ctx->audioStream]->codecpar->codec_id);
ctx->pACodecCtx = avcodec_alloc_context3(pCodec);
if (avcodec_parameters_to_context(ctx->pACodecCtx, ctx->pFormatCtx->streams[ctx->audioStream]->codecpar) < 0)
{
avcodec_free_context(&ctx->pACodecCtx);
pCodec = NULL;
}
#else
ctx->pACodecCtx=ctx->pFormatCtx->streams[ctx->audioStream]->codec; ctx->pACodecCtx=ctx->pFormatCtx->streams[ctx->audioStream]->codec;
pCodec=avcodec_find_decoder(ctx->pACodecCtx->codec_id); pCodec=avcodec_find_decoder(ctx->pACodecCtx->codec_id);
#endif
ctx->pAFrame=av_frame_alloc(); ctx->pAFrame=av_frame_alloc();
if(pCodec!=NULL && ctx->pAFrame && avcodec_open2(ctx->pACodecCtx, pCodec, NULL) >= 0) if(pCodec!=NULL && ctx->pAFrame && avcodec_open2(ctx->pACodecCtx, pCodec, NULL) >= 0)
{ //success { //success
@ -358,11 +411,10 @@ static qboolean AVAudio_Init(void)
{ {
if (!pPlug_ExportNative("S_LoadSound", S_LoadAVSound)) if (!pPlug_ExportNative("S_LoadSound", S_LoadAVSound))
{ {
ffmpeg_audiodecoder = pCvar_GetNVFDG("ffmpeg_audiodecoder_wip", "0", 0, "Enables the use of ffmpeg's decoder for pure audio files.", "ffmpeg");
Con_Printf("avplug: Engine doesn't support audio decoder plugins\n"); Con_Printf("avplug: Engine doesn't support audio decoder plugins\n");
return false; return false;
} }
ffmpeg_audiodecoder = pCvar_GetNVFDG("ffmpeg_audiodecoder_wip", "0", 0, "Enables the use of ffmpeg's decoder for pure audio files.", "ffmpeg");
return true; return true;
} }
@ -389,8 +441,10 @@ qintptr_t Plug_Init(qintptr_t *args)
okay |= AVEnc_Init(); okay |= AVEnc_Init();
if (okay) if (okay)
{ {
#if ( LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(58,9,100) )
av_register_all(); av_register_all();
avcodec_register_all(); avcodec_register_all();
#endif
av_log_set_level(AV_LOG_WARNING); av_log_set_level(AV_LOG_WARNING);
av_log_set_callback(AVLogCallback); av_log_set_callback(AVLogCallback);

View file

@ -27,7 +27,7 @@
#define PASSFLOAT(f) *(int*)&(f) #define PASSFLOAT(f) *(int*)&(f)
#define ARGNAMES ,sourceid, data, speed, samples, channels, width, PASSFLOAT(volume) #define ARGNAMES ,sourceid, data, speed, samples, channels, width, PASSFLOAT(volume)
BUILTIN(void, S_RawAudio, (int sourceid, void *data, int speed, int samples, int channels, int width, float volume)); BUILTIN(void, S_RawAudio, (int sourceid, void *data, int speed, int samples, int channels, int width, float volume))
#undef ARGNAMES #undef ARGNAMES
/*should probably try threading this, though I suppose it should be the engine doing that.*/ /*should probably try threading this, though I suppose it should be the engine doing that.*/

View file

@ -119,7 +119,7 @@ static AVStream *add_video_stream(struct encctx *ctx, AVCodec *codec, int fps, i
return NULL; return NULL;
st->id = ctx->fc->nb_streams-1; st->id = ctx->fc->nb_streams-1;
#if 1//LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57, 48, 0) #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57, 48, 101)
c = st->codec; c = st->codec;
#else #else
c = avcodec_alloc_context3(codec); c = avcodec_alloc_context3(codec);
@ -304,7 +304,7 @@ static AVStream *add_audio_stream(struct encctx *ctx, AVCodec *codec, int *sampl
return NULL; return NULL;
st->id = ctx->fc->nb_streams-1; st->id = ctx->fc->nb_streams-1;
#if 1//LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57, 48, 0) #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57, 48, 101)
c = st->codec; c = st->codec;
#else #else
c = avcodec_alloc_context3(codec); c = avcodec_alloc_context3(codec);
@ -613,7 +613,7 @@ static void *AVEnc_Begin (char *streamname, int videorate, int width, int height
ctx->fc = avformat_alloc_context(); ctx->fc = avformat_alloc_context();
ctx->fc->oformat = fmt; ctx->fc->oformat = fmt;
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 6, 100) || defined(FF_API_FORMAT_FILENAME) #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 6, 100)
Q_strncatz(ctx->fc->filename, streamname, sizeof(ctx->fc->filename)); Q_strncatz(ctx->fc->filename, streamname, sizeof(ctx->fc->filename));
#else #else
ctx->fc->url = av_strdup(streamname); ctx->fc->url = av_strdup(streamname);
@ -684,6 +684,10 @@ static void *AVEnc_Begin (char *streamname, int videorate, int width, int height
} }
} }
//different formats have different metadata formats. there's no standards here.
//av_dict_set(&ctx->fc->metadata, "TPFL", "testtest", 0);
//FIXME: use ffmpeg's sidedata stuff, which should handle it in a generic way
//nearly complete, can make the file dirty now. //nearly complete, can make the file dirty now.
err = avformat_write_header(ctx->fc, NULL); err = avformat_write_header(ctx->fc, NULL);
if (err < 0) if (err < 0)
@ -742,12 +746,13 @@ static media_encoder_funcs_t encoderfuncs =
AVEnc_End AVEnc_End
}; };
/*
qintptr_t AVEnc_ExecuteCommand(qintptr_t *args) qintptr_t AVEnc_ExecuteCommand(qintptr_t *args)
{ {
char cmd[256]; char cmd[256];
Cmd_Argv(0, cmd, sizeof(cmd)); pCmd_Argv(0, cmd, sizeof(cmd));
if (!strcmp(cmd, "avcapture")) /*
if (!strcmp(cmd, ENCODERNAME"_configure"))
{ {
menuclear menuclear
menualias menucallback menualias menucallback
@ -762,9 +767,48 @@ menutext 0 24 "Report in" "radio26"
menutext 0 24 "Cancel" menutext 0 24 "Cancel"
return true; return true;
} }
*/
if (!strcmp(cmd, ENCODERNAME"_nvidia"))
{
pCvar_SetString("capturedriver", ENCODERNAME); //be sure to use our encoder
pCvar_SetString(ENCODERNAME"_videocodec", "h264_nvenc");
pCvar_SetString("capturerate", "60"); //we should be able to cope with it, and the default of 30 sucks
pCvar_SetString("capturedemowidth", "1920"); //force a specific size, some codecs need multiples of 16 or whatever.
pCvar_SetString("capturedemoheight", "1080"); //so this avoids issues with various video codecs.
pCvar_SetString("capturesound", "1");
pCvar_SetString("capturesoundchannels", "2");
pCvar_SetString("capturesoundbits", "16");
Con_Printf(ENCODERNAME": now configured for nvidia's hardware encoder\n");
Con_Printf(ENCODERNAME": use ^[/capture foo.mp4^] or ^[/capturedemo foo.mvd foo.mkv^] commands to begin capturing\n");
}
if (!strcmp(cmd, ENCODERNAME"_defaults"))
{ //most formats will end up using the x264 encoder or something
pCvar_SetString(ENCODERNAME"_format_force", "");
pCvar_SetString(ENCODERNAME"_videocodec", "");
pCvar_SetString(ENCODERNAME"_videobitrate", "");
pCvar_SetString(ENCODERNAME"_videoforcewidth", "");
pCvar_SetString(ENCODERNAME"_videoforceheight", "");
pCvar_SetString(ENCODERNAME"_videopreset", "veryfast");
pCvar_SetString(ENCODERNAME"_video_crf", "");
pCvar_SetString(ENCODERNAME"_audiocodec", "");
pCvar_SetString(ENCODERNAME"_audiobitrate", "");
pCvar_SetString("capturedriver", ENCODERNAME);
pCvar_SetString("capturerate", "30");
pCvar_SetString("capturedemowidth", "0");
pCvar_SetString("capturedemoheight", "0");
pCvar_SetString("capturesound", "1");
pCvar_SetString("capturesoundchannels", "2");
pCvar_SetString("capturesoundbits", "16");
Con_Printf(ENCODERNAME": capture settings reset to "ENCODERNAME" defaults\n");
Con_Printf(ENCODERNAME": Note that some codecs may have restrictions on video sizes\n");
}
return false; return false;
} }
*/
qboolean AVEnc_Init(void) qboolean AVEnc_Init(void)
{ {
@ -790,8 +834,11 @@ qboolean AVEnc_Init(void)
ffmpeg_audiocodec = pCvar_GetNVFDG(ENCODERNAME"_audiocodec", "", 0, "Forces which audio encoder to use. If blank, guesses based upon container defaults.", ENCODERNAME); ffmpeg_audiocodec = pCvar_GetNVFDG(ENCODERNAME"_audiocodec", "", 0, "Forces which audio encoder to use. If blank, guesses based upon container defaults.", ENCODERNAME);
ffmpeg_audiobitrate = pCvar_GetNVFDG(ENCODERNAME"_audiobitrate", "", 0, "Specifies the target audio bitrate", ENCODERNAME); ffmpeg_audiobitrate = pCvar_GetNVFDG(ENCODERNAME"_audiobitrate", "", 0, "Specifies the target audio bitrate", ENCODERNAME);
// if (Plug_Export("ExecuteCommand", AVEnc_ExecuteCommand)) if (Plug_Export("ExecuteCommand", AVEnc_ExecuteCommand))
// Cmd_AddCommand("avcapture"); {
// pCmd_AddCommand(ENCODERNAME"_configure");
pCmd_AddCommand(ENCODERNAME"_nvidia");
}
return true; return true;
} }

View file

@ -162,3 +162,65 @@ void Draw_Polygon(int x, int y, vec3_t *vertices, int num_vertices, qbool fill,
//glue //glue
EBUILTIN(cvar_t*, Cvar_GetNVFDG, (const char *name, const char *defaultval, unsigned int flags, const char *description, const char *groupname)); EBUILTIN(cvar_t*, Cvar_GetNVFDG, (const char *name, const char *defaultval, unsigned int flags, const char *description, const char *groupname));
#undef sb_lines //just in case.
#ifndef SBAR_HEIGHT
#define SBAR_HEIGHT 24
#define STAT_HEALTH 0
#define STAT_WEAPONMODELI 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 //same as zquake
#define STAT_TIME 17 //zquake
#define STAT_MATCHSTARTTIME 18
#define IT_SHOTGUN (1u<<0)
#define IT_SUPER_SHOTGUN (1u<<1)
#define IT_NAILGUN (1u<<2)
#define IT_SUPER_NAILGUN (1u<<3)
#define IT_GRENADE_LAUNCHER (1u<<4)
#define IT_ROCKET_LAUNCHER (1u<<5)
#define IT_LIGHTNING (1u<<6)
#define IT_SUPER_LIGHTNING (1u<<7)
#define IT_SHELLS (1u<<8)
#define IT_NAILS (1u<<9)
#define IT_ROCKETS (1u<<10)
#define IT_CELLS (1u<<11)
#define IT_AXE (1u<<12)
#define IT_ARMOR1 (1u<<13)
#define IT_ARMOR2 (1u<<14)
#define IT_ARMOR3 (1u<<15)
#define IT_SUPERHEALTH (1u<<16)
#define IT_KEY1 (1u<<17)
#define IT_KEY2 (1u<<18)
#define IT_INVISIBILITY (1u<<19)
#define IT_INVULNERABILITY (1u<<20)
#define IT_SUIT (1u<<21)
#define IT_QUAD (1u<<22)
#define IT_SIGIL1 (1u<<28)
#define IT_SIGIL2 (1u<<29)
#define IT_SIGIL3 (1u<<30)
#define IT_SIGIL4 (1u<<31)
#endif

Some files were not shown because too many files have changed in this diff Show more