openxr plugin: tweaked - inputs should be working properly now, and are visible to csqc. subject to further breaking changes, however.

_pext_vrinputs: added cvar to enable vr inputs protocol extension allowing vr inputs to be networked to ssqc too. defaults to 0 for now, will be renamed when deemed final.
updates menu: the prompt to enable sources is now more explicit instead of expecting the user to have a clue.
updates menu: added a v3 sources format, which should be more maintainable. not final.
updates menu: try to give reasons why sources might be failing (to help blame ISPs if they try fucking over TTH dns again).
presets menu: no longer closes the instant a preset is chosen. some presets have a couple of modifiers listed. force the demo loop in the background to serve as a preview.
prompts menus: now does word wrapping.
ftemaster: support importing server lists from other master servers (requested by Eukara).
server: try to detect when non-reply inbound packets are blocked by firewalls/nats/etc (using ftemaster to do so).
qcvm: added pointcontentsmask builtin, allowing it to probe more than just world, with fte's full contentbit range instead of just q1 legacy.
qcvm: memfill8 builtin now works on createbuffer() pointers.
qcvm: add missing unsigned ops. Fixed double comparison ops. fixed bug with op_store_i64. added missing OP_LOADP_I64
qcc: added '#pragma framerate RATE' for overriding implicit nextthink durations.
qcc: fixed '#pragma DONT_COMPILE_THIS_FILE' to not screw up comments.
qcc: added __GITURL__ __GITHASH__ __GITDATE__ __GITDATETIME__ __GITDESC__ for any mods that might want to make use of that.
qcc: fix up -Fhashonly a little
setrenderer: support for vulkan gpu enumeration.
rulesets: reworked to support custom rulesets (using hashes to catch haxxors, though still nothing prevents just changing the client to ignore rulesets)
bspx: use our BIH code for the bspx BRUSHLIST lump instead of the older less efficient code.
(static)iqm+obj: these model formats can now be used for the worldmodel (with a suitable .ent file). Also using BIH for much better collision performance.
pmove: tried to optimise PM_NudgePosition, should boost fps in stress tests.
wayland: fix a crash on startup. mousegrabs now works better.
imagetool: uses sdl for previews.


git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5813 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2021-04-14 05:21:04 +00:00
parent cd50a54a5a
commit b9cd6ec91b
160 changed files with 13078 additions and 5542 deletions

View File

@ -68,6 +68,7 @@ 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_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}) SET(FTE_LIB_DEFINES ${FTE_LIB_DEFINES};CONFIG_FILE_NAME=${FTE_BUILD_CONFIG})
SET(FTE_USE_SDL false CACHE BOOL "Force the use of SDL instead of using native builds.")
IF(NOT WIN32) IF(NOT WIN32)
SET(SYS_LIBS ${SYS_LIBS} m) SET(SYS_LIBS ${SYS_LIBS} m)
@ -166,6 +167,7 @@ IF(CMAKE_C_COMPILER_ID MATCHES "GNU")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wformat-truncation=1") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wformat-truncation=1")
#TODO SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wmissing-prototypes") #for finding missing statics. #TODO SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wmissing-prototypes") #for finding missing statics.
#SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-unused-function") # #SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-unused-function") #
# set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wswitch-enum") #to warn about omitted enums despite default.
#might as well do this, public builds use the regular Makefile. #might as well do this, public builds use the regular Makefile.
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=native") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=native")
@ -184,6 +186,7 @@ IF(CMAKE_BUILD_TYPE MATCHES "Debug")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu89") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu89")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_DEBUG") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_DEBUG")
ENDIF() ENDIF()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_FILE_OFFSET_BITS=64")
IF(${ANDROID}) IF(${ANDROID})
# FIND_PACKAGE(Freetype REQUIRED) # FIND_PACKAGE(Freetype REQUIRED)
@ -244,16 +247,35 @@ ELSEIF(${WIN32})
engine/common/fs_win32.c engine/common/fs_win32.c
engine/server/sv_sys_win.c engine/server/sv_sys_win.c
) )
ELSEIF(${UNIX}) #linux(ish) ELSEIF(${UNIX} AND NOT FTE_USE_SDL) #linux(ish)
#openbsd will have issues with snd_linux.c #openbsd will have issues with snd_linux.c
#linux-only packages IF(FTE_PRIVATE_USE_ONLY)
#the openssl license is incompatible with the GPL, so while we have code to use it distributing the binaries built with it is not a (legal) option.
#note that openssl 3.0.0 upwards are apache-2 licensed, which IS gpl-3 compatible. debian has not caught up with that yet, however.
FIND_PACKAGE(OpenSSL)
IF(NOT OPENSSL_FOUND)
MESSAGE(WARNING "openssl library NOT available. HTTPS/DTLS will not be available.")
ELSEIF(OPENSSL_VERSION_MAJOR LESS 3 AND NOT FTE_PRIVATE_USE_ONLY)
MESSAGE(WARNING "openssl library version is not 3 or above. Ignoring due to incompatible license.")
ELSE()
MESSAGE(WARNING "Using openssl.")
SET(FTE_LIB_DEFINES ${FTE_LIB_DEFINES};HAVE_OPENSSL)
SET(FTE_ARCH_FILES ${FTE_ARCH_FILES} engine/common/net_ssl_openssl.c)
SET(FTE_LIBS ${FTE_LIBS} ${OPENSSL_LIBRARIES})
SET(FTESV_ARCH_FILES ${FTESV_ARCH_FILES} engine/common/net_ssl_openssl.c)
SET(FTESV_LIBS ${FTESV_LIBS} ${OPENSSL_LIBRARIES})
ENDIF()
ENDIF()
FIND_PACKAGE(GnuTLS) FIND_PACKAGE(GnuTLS)
IF(NOT GNUTLS_FOUND) IF(NOT GNUTLS_FOUND)
MESSAGE(WARNING "gnutls library NOT available. HTTPS/DTLS will not be available.") MESSAGE(WARNING "gnutls library NOT available. HTTPS/DTLS will not be available.")
SET(FTE_LIB_DEFINES ${FTE_LIB_DEFINES};NO_GNUTLS) SET(FTE_LIB_DEFINES ${FTE_LIB_DEFINES};NO_GNUTLS)
ENDIF() ENDIF()
#linux-only packages
FIND_PACKAGE(ALSA) FIND_PACKAGE(ALSA)
IF(ALSA_FOUND) IF(ALSA_FOUND)
SET(FTE_LIB_DEFINES ${FTE_LIB_DEFINES};AUDIO_ALSA;AUDIO_PULSE) SET(FTE_LIB_DEFINES ${FTE_LIB_DEFINES};AUDIO_ALSA;AUDIO_PULSE)
@ -278,7 +300,7 @@ ELSEIF(${UNIX}) #linux(ish)
SET(FTE_DEFINES ${FTE_DEFINES};DYNAMIC_SDL;MULTITHREAD) SET(FTE_DEFINES ${FTE_DEFINES};DYNAMIC_SDL;MULTITHREAD)
SET(FTE_LIBS ${FTE_LIBS} ${SYS_LIBS} ${CMAKE_DL_LIBS} pthread ${SDL2_LIBRARIES}) SET(FTE_LIBS ${FTE_LIBS} ${SYS_LIBS} ${CMAKE_DL_LIBS} pthread ${SDL2_LIBRARIES})
SET(FTE_ARCH_FILES SET(FTE_ARCH_FILES ${FTE_ARCH_FILES}
engine/client/sys_linux.c engine/client/sys_linux.c
engine/common/sys_linux_threads.c engine/common/sys_linux_threads.c
engine/common/net_ssl_gnutls.c engine/common/net_ssl_gnutls.c
@ -307,11 +329,15 @@ ELSEIF(${UNIX}) #linux(ish)
SET(FTE_LIBS ${FTE_LIBS} ${OSSAUDIO_LIBRARY}) SET(FTE_LIBS ${FTE_LIBS} ${OSSAUDIO_LIBRARY})
ENDIF() ENDIF()
#on linux, use wayland. #on linux, use wayland (we normally dynamically link, but we still need headers).
FIND_LIBRARY( FIND_LIBRARY(
WAYLAND_CLIENT_LIBRARY WAYLAND_CLIENT_LIBRARY
NAMES wayland-client libwayland-client NAMES wayland-client libwayland-client
) )
FIND_LIBRARY(
WAYLAND_EGL
NAMES wayland-egl
)
FIND_LIBRARY( FIND_LIBRARY(
HAVE_XKBCOMMON HAVE_XKBCOMMON
NAMES xkbcommon NAMES xkbcommon
@ -320,7 +346,10 @@ ELSEIF(${UNIX}) #linux(ish)
MESSAGE(WARNING "xkbcommon library not found, needed for wayland to be usable.") MESSAGE(WARNING "xkbcommon library not found, needed for wayland to be usable.")
UNSET(WAYLAND_CLIENT_LIBRARY) UNSET(WAYLAND_CLIENT_LIBRARY)
ENDIF() ENDIF()
IF(WAYLAND_CLIENT_LIBRARY) IF(WAYLAND_CLIENT_LIBRARY AND WAYLAND_EGL)
# SET(FTE_LIBS ${FTE_LIBS} ${WAYLAND_CLIENT_LIBRARY} ${HAVE_XKBCOMMON} ${WAYLAND_EGL})
# SET(FTE_DEFINES ${FTE_DEFINES};STATIC_WAYLAND)
SET(FTE_DEFINES ${FTE_DEFINES};WAYLANDQUAKE;USE_EGL) SET(FTE_DEFINES ${FTE_DEFINES};WAYLANDQUAKE;USE_EGL)
SET(FTE_ARCH_FILES ${FTE_ARCH_FILES} SET(FTE_ARCH_FILES ${FTE_ARCH_FILES}
engine/gl/gl_vidwayland.c engine/gl/gl_vidwayland.c
@ -334,7 +363,7 @@ ELSEIF(${UNIX}) #linux(ish)
ENDIF() ENDIF()
SET(FTESV_DEFINES MULTITHREAD) SET(FTESV_DEFINES MULTITHREAD)
SET(FTESV_ARCH_FILES SET(FTESV_ARCH_FILES ${FTESV_ARCH_FILES}
engine/server/sv_sys_unix.c engine/server/sv_sys_unix.c
engine/common/sys_linux_threads.c engine/common/sys_linux_threads.c
engine/common/net_ssl_gnutls.c engine/common/net_ssl_gnutls.c
@ -451,10 +480,30 @@ SET(FTE_VK_FILES
engine/vk/vk_backend.c engine/vk/vk_backend.c
engine/vk/vk_init.c engine/vk/vk_init.c
) )
SET(FTE_QCVM_FILES
engine/qclib/comprout.c
engine/qclib/initlib.c
engine/qclib/pr_edict.c
engine/qclib/pr_exec.c
engine/qclib/pr_multi.c
engine/qclib/qcc_cmdlib.c
engine/qclib/qcc_pr_comp.c
engine/qclib/qcc_pr_lex.c
# engine/qclib/decomp.c
# engine/qclib/packager.c
# engine/qclib/pr_x86.c
# engine/qclib/qccgui.c
# engine/qclib/qccguistuff.c
# engine/qclib/qcctui.c
engine/qclib/qccmain.c
engine/qclib/qcd_main.c
engine/qclib/qcdecomp.c
)
SET(FTE_COMMON_FILES SET(FTE_COMMON_FILES
#these files are common to both server-only and client+server builds. #these files are common to both server-only and client+server builds.
engine/common/cmd.c engine/common/cmd.c
engine/common/com_mesh.c engine/common/com_mesh.c
engine/common/com_bih.c
engine/common/common.c engine/common/common.c
engine/common/crc.c engine/common/crc.c
engine/common/cvar.c engine/common/cvar.c
@ -583,6 +632,17 @@ SET(FTE_COMMON_FILES
engine/gl/gl_hlmdl.c engine/gl/gl_hlmdl.c
engine/gl/gl_model.c engine/gl/gl_model.c
engine/server/sv_move.c
engine/server/sv_phys.c
engine/server/world.c
${FTE_QCVM_FILES}
engine/qclib/hash.c
engine/http/httpclient.c
)
SET(FTE_SERVER_FILES
engine/server/net_preparse.c engine/server/net_preparse.c
engine/server/pr_cmds.c engine/server/pr_cmds.c
engine/server/pr_lua.c engine/server/pr_lua.c
@ -596,10 +656,8 @@ SET(FTE_COMMON_FILES
engine/server/sv_init.c engine/server/sv_init.c
engine/server/sv_main.c engine/server/sv_main.c
engine/server/sv_master.c engine/server/sv_master.c
engine/server/sv_move.c
engine/server/sv_mvd.c engine/server/sv_mvd.c
engine/server/sv_nchan.c engine/server/sv_nchan.c
engine/server/sv_phys.c
engine/server/sv_rankin.c engine/server/sv_rankin.c
engine/server/sv_send.c engine/server/sv_send.c
engine/server/sv_sql.c engine/server/sv_sql.c
@ -610,28 +668,6 @@ SET(FTE_COMMON_FILES
engine/server/svq2_ents.c engine/server/svq2_ents.c
engine/server/svq2_game.c engine/server/svq2_game.c
engine/server/svq3_game.c engine/server/svq3_game.c
engine/server/world.c
engine/qclib/comprout.c
engine/qclib/hash.c
engine/qclib/initlib.c
engine/qclib/pr_edict.c
engine/qclib/pr_exec.c
engine/qclib/pr_multi.c
engine/qclib/qcc_cmdlib.c
engine/qclib/qcc_pr_comp.c
engine/qclib/qcc_pr_lex.c
# engine/qclib/decomp.c
# engine/qclib/packager.c
# engine/qclib/pr_x86.c
# engine/qclib/qccgui.c
# engine/qclib/qccguistuff.c
# engine/qclib/qcctui.c
engine/qclib/qccmain.c
engine/qclib/qcd_main.c
engine/qclib/qcdecomp.c
engine/http/httpclient.c
) )
#these files are only in the client #these files are only in the client
@ -786,6 +822,7 @@ ELSE()
${FTE_ARCH_FILES} ${FTE_ARCH_FILES}
${FTE_COMMON_FILES} ${FTE_COMMON_FILES}
${FTE_CLIENT_FILES} ${FTE_CLIENT_FILES}
${FTE_SERVER_FILES}
) )
SET_TARGET_PROPERTIES(fteqw PROPERTIES COMPILE_DEFINITIONS "${FTE_LIB_DEFINES};${FTE_DEFINES};${FTE_REVISON}") SET_TARGET_PROPERTIES(fteqw PROPERTIES COMPILE_DEFINITIONS "${FTE_LIB_DEFINES};${FTE_DEFINES};${FTE_REVISON}")
TARGET_LINK_LIBRARIES(fteqw ${FTE_LIBS}) TARGET_LINK_LIBRARIES(fteqw ${FTE_LIBS})
@ -794,11 +831,29 @@ ELSE()
ADD_EXECUTABLE(fteqw-sv ADD_EXECUTABLE(fteqw-sv
${FTESV_ARCH_FILES} ${FTESV_ARCH_FILES}
${FTE_COMMON_FILES} ${FTE_COMMON_FILES}
${FTE_SERVER_FILES}
) )
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})
SET(INSTALLTARGS ${INSTALLTARGS} fteqw-sv) SET(INSTALLTARGS ${INSTALLTARGS} fteqw-sv)
IF(0)
ADD_EXECUTABLE(fteqw-cl
${FTE_ARCH_FILES}
${FTE_COMMON_FILES}
${FTE_CLIENT_FILES}
)
SET_TARGET_PROPERTIES(fteqw-cl PROPERTIES COMPILE_DEFINITIONS "CLIENTONLY;${FTE_LIB_DEFINES};${FTE_DEFINES};${FTE_REVISON}")
TARGET_LINK_LIBRARIES(fteqw-cl ${FTE_LIBS})
SET(INSTALLTARGS ${INSTALLTARGS} fteqw-cl)
ENDIF()
FIND_PACKAGE(SDL2 REQUIRED)
IF(SDL2_FOUND)
SET(FTE_SDL2 FTE_SDL)
SET(FTE_SDL2_INCLUDES ${SDL2_INCLUDE_DIRS})
ENDIF()
ADD_EXECUTABLE(iqmtool ADD_EXECUTABLE(iqmtool
iqm/iqm.cpp iqm/iqm.cpp
plugins/models/gltf.c plugins/models/gltf.c
@ -814,7 +869,8 @@ ELSE()
engine/client/image.c engine/client/image.c
imgtool.c imgtool.c
) )
SET_TARGET_PROPERTIES(imgtool PROPERTIES COMPILE_DEFINITIONS "IMGTOOL;${FTE_LIB_DEFINES};${FTE_DEFINES};${FTE_REVISON}") TARGET_INCLUDE_DIRECTORIES(imgtool PUBLIC ${FTE_SDL2_INCLUDES})
SET_TARGET_PROPERTIES(imgtool PROPERTIES COMPILE_DEFINITIONS "IMGTOOL;${FTE_LIB_DEFINES};${FTE_DEFINES};${FTE_REVISON};${FTE_SDL2}")
TARGET_LINK_LIBRARIES(imgtool ${FTE_LIBS} ) TARGET_LINK_LIBRARIES(imgtool ${FTE_LIBS} )
SET(INSTALLTARGS ${INSTALLTARGS} imgtool) SET(INSTALLTARGS ${INSTALLTARGS} imgtool)
@ -888,6 +944,7 @@ ELSE()
engine/qclib/qcc_pr_lex.c engine/qclib/qcc_pr_lex.c
engine/qclib/qccmain.c engine/qclib/qccmain.c
engine/qclib/qcd_main.c engine/qclib/qcd_main.c
engine/qclib/packager.c
) )
SET_TARGET_PROPERTIES(fteqcc PROPERTIES COMPILE_DEFINITIONS "${FTE_LIB_DEFINES};${FTE_REVISON}") SET_TARGET_PROPERTIES(fteqcc PROPERTIES COMPILE_DEFINITIONS "${FTE_LIB_DEFINES};${FTE_REVISON}")
TARGET_LINK_LIBRARIES(fteqcc ${FTEQCC_LIBS} ${SYS_LIBS}) TARGET_LINK_LIBRARIES(fteqcc ${FTEQCC_LIBS} ${SYS_LIBS})
@ -938,7 +995,7 @@ ELSE()
engine/qclib/qcc_pr_lex.c engine/qclib/qcc_pr_lex.c
engine/qclib/qccmain.c engine/qclib/qccmain.c
engine/qclib/decomp.c engine/qclib/decomp.c
engine/qclib/packager.c # engine/qclib/packager.c
engine/qclib/qcd_main.c engine/qclib/qcd_main.c
) )
TARGET_INCLUDE_DIRECTORIES(fteqccgui PUBLIC ${Qt5Widgets_INCLUDE_DIRS} ${QSCINTILLA_INCLUDE_DIR}) TARGET_INCLUDE_DIRECTORIES(fteqccgui PUBLIC ${Qt5Widgets_INCLUDE_DIRS} ${QSCINTILLA_INCLUDE_DIR})
@ -952,6 +1009,29 @@ ELSE()
ENDIF() ENDIF()
ENDIF() ENDIF()
IF(0)
#software renderer plugin
#not stable enough, and probably won't ever be
ADD_LIBRARY(sw MODULE
plugins/plugin.c
engine/sw/sw_backend.c
engine/sw/sw_image.c
engine/sw/sw_rast.c
#engine/sw/sw_viddos.c
# engine/sw/sw_vidwin.c
engine/common/mathlib.c
# engine/client/in_win.c
engine/sw/sw.h
engine/sw/sw_spans.h
)
SET_TARGET_PROPERTIES(sw PROPERTIES COMPILE_DEFINITIONS "FTEPLUGIN;${FTE_LIB_DEFINES};SWQUAKE")
SET_TARGET_PROPERTIES(sw PROPERTIES PREFIX "fteplug_")
SET_TARGET_PROPERTIES(sw PROPERTIES LINK_FLAGS "-Wl,--no-undefined")
TARGET_LINK_LIBRARIES(sw ${SYS_LIBS})
SET(INSTALLTARGS ${INSTALLTARGS} sw)
ENDIF()
#Quake Injector Alike plugin #Quake Injector Alike plugin
ADD_LIBRARY(qi MODULE ADD_LIBRARY(qi MODULE
plugins/plugin.c plugins/plugin.c
@ -1088,6 +1168,27 @@ ELSE()
MESSAGE(WARNING "ffmpeg library NOT available. Quake shouldn't be playing fmv anyway.") MESSAGE(WARNING "ffmpeg library NOT available. Quake shouldn't be playing fmv anyway.")
ENDIF() ENDIF()
IF(0)
#timidity
FIND_PATH(TIMIDITY_INCLUDE_DIR timidity/timidity.h)
IF(TIMIDITY_INCLUDE_DIR)
FIND_LIBRARY(TIMIDITY_LIBRARY timidity)
ADD_LIBRARY(timidity MODULE
plugins/plugin.c
plugins/timidity.c
)
TARGET_INCLUDE_DIRECTORIES(timidity PUBLIC ${TIMIDITY_INCLUDE_DIR})
SET_TARGET_PROPERTIES(timidity PROPERTIES LINK_FLAGS "-Wl,--no-undefined")
TARGET_LINK_LIBRARIES(timidity ${SYS_LIBS} ${TIMIDITY_LIBRARY})
SET_TARGET_PROPERTIES(timidity PROPERTIES COMPILE_DEFINITIONS "FTEPLUGIN;${FTE_LIB_DEFINES}")
SET_TARGET_PROPERTIES(timidity PROPERTIES PREFIX "fteplug_")
SET(INSTALLTARGS ${INSTALLTARGS} timidity)
ELSE()
MESSAGE(WARNING "timidity library NOT available. We'll just stick to fake-cd music for hexen2.")
ENDIF()
ENDIF()
#openxr plugin #openxr plugin
FIND_PACKAGE(PkgConfig) FIND_PACKAGE(PkgConfig)
IF (PKGCONFIG_FOUND) IF (PKGCONFIG_FOUND)
@ -1149,6 +1250,7 @@ IF(NOT ANDROID)
plugins/jabber/jingle.c plugins/jabber/jingle.c
plugins/jabber/sift.c plugins/jabber/sift.c
engine/common/sha1.c engine/common/sha1.c
engine/common/sha2.c
plugins/emailnot/md5.c plugins/emailnot/md5.c
) )
SET_TARGET_PROPERTIES(xmpp PROPERTIES COMPILE_DEFINITIONS "FTEPLUGIN;${FTE_LIB_DEFINES}") SET_TARGET_PROPERTIES(xmpp PROPERTIES COMPILE_DEFINITIONS "FTEPLUGIN;${FTE_LIB_DEFINES}")
@ -1164,11 +1266,11 @@ ENDIF()
INCLUDE(GNUInstallDirs) INCLUDE(GNUInstallDirs)
SET(FTE_INSTALL_BINDIR games CACHE STRING "Binary dir to install to.") SET(FTE_INSTALL_BINDIR games CACHE STRING "Binary dir to install to.")
INSTALL(TARGETS ${INSTALLTARGS} INSTALL(TARGETS ${INSTALLTARGS}
RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}${FTE_INSTALL_BINDIR}" RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}/${FTE_INSTALL_BINDIR}"
LIBRARY DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}" LIBRARY DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}"
) )
IF (0) IF (1)
ADD_CUSTOM_TARGET(menusys ALL ADD_CUSTOM_TARGET(menusys ALL
VERBATIM VERBATIM
COMMAND fteqcc -srcfile "${CMAKE_CURRENT_SOURCE_DIR}/quakec/menusys/menu.src" -o "${CMAKE_CURRENT_BINARY_DIR}/menu.dat" COMMAND fteqcc -srcfile "${CMAKE_CURRENT_SOURCE_DIR}/quakec/menusys/menu.src" -o "${CMAKE_CURRENT_BINARY_DIR}/menu.dat"

View File

@ -852,6 +852,7 @@ COMMON_OBJS = \
gl_hlmdl.o \ gl_hlmdl.o \
gl_heightmap.o \ gl_heightmap.o \
gl_model.o \ gl_model.o \
com_bih.o \
com_mesh.o \ com_mesh.o \
common.o \ common.o \
cvar.o \ cvar.o \

View File

@ -184,8 +184,10 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#undef idx64 #undef idx64
#define idx64 1 #define idx64 1
#define ARCH_STRING "x86_64" #define ARCH_STRING "x86_64"
#elif defined __ppc64le__
#define ARCH_STRING "ppc64le" //more common than ppc64[be] on linux nowadays.
#elif defined __powerpc64__ #elif defined __powerpc64__
#define ARCH_STRING "ppc64" #define ARCH_STRING "ppc64" //big-endian/original variant.
#elif defined __powerpc__ #elif defined __powerpc__
#define ARCH_STRING "ppc" #define ARCH_STRING "ppc"
#elif defined __s390__ #elif defined __s390__

View File

@ -3347,6 +3347,12 @@ void CL_LinkStaticEntities(void *pvs, int *areas)
} }
cl.worldmodel->funcs.FindTouchedLeafs(cl.worldmodel, &stat->ent.pvscache, mins, maxs); cl.worldmodel->funcs.FindTouchedLeafs(cl.worldmodel, &stat->ent.pvscache, mins, maxs);
} }
else if (clmodel->loadstate != MLS_LOADED)
{
if (clmodel->loadstate == MLS_NOTLOADED) //flushed?
Mod_LoadModel(clmodel, MLV_WARN); //load it, but don't otherwise care for now.
continue;
}
/*pvs test*/ /*pvs test*/
if (pvs && !cl.worldmodel->funcs.EdictInFatPVS(cl.worldmodel, &stat->ent.pvscache, pvs, areas)) if (pvs && !cl.worldmodel->funcs.EdictInFatPVS(cl.worldmodel, &stat->ent.pvscache, pvs, areas))
@ -4325,7 +4331,10 @@ void CL_LinkPacketEntities (void)
} }
VectorCopy(angles, ent->angles); VectorCopy(angles, ent->angles);
AngleVectorsMesh(angles, ent->axis[0], ent->axis[1], ent->axis[2]); if (model->type == mod_alias)
AngleVectorsMesh(angles, ent->axis[0], ent->axis[1], ent->axis[2]);
else
AngleVectors(angles, ent->axis[0], ent->axis[1], ent->axis[2]);
VectorInverse(ent->axis[1]); VectorInverse(ent->axis[1]);
/*if this entity is in a player's slot...*/ /*if this entity is in a player's slot...*/
@ -4815,7 +4824,7 @@ void CLQW_ParsePlayerinfo (void)
if (flags & PF_COMMAND) if (flags & PF_COMMAND)
{ {
MSG_ReadDeltaUsercmd (&nullcmd, &state->command, cl.protocol_qw); MSGQW_ReadDeltaUsercmd (&nullcmd, &state->command, cl.protocol_qw);
state->viewangles[0] = state->command.angles[0] * (360.0/65536); state->viewangles[0] = state->command.angles[0] * (360.0/65536);
state->viewangles[1] = state->command.angles[1] * (360.0/65536); state->viewangles[1] = state->command.angles[1] * (360.0/65536);

View File

@ -798,10 +798,10 @@ void CL_GatherButtons (usercmd_t *cmd, int pnum)
GATHERBIT(in_button[7], 6); GATHERBIT(in_button[7], 6);
GATHERBIT(in_button[8], 7); GATHERBIT(in_button[8], 7);
//these are fucked, as required for dpcompat. //more inconsistencies, as required for dpcompat.
GATHERBIT(in_use, (cls.protocol==CP_QUAKEWORLD)?4:8); GATHERBIT(in_use, (cls.protocol==CP_QUAKEWORLD)?4:8);
bits |= (Key_Dest_Has(~kdm_game)) ?(1u<<9):0; //game is the lowest priority, anything else will take focus away. we consider that to mean 'chat' (although it could be menus). bits |= (Key_Dest_Has(~kdm_game)) ?(1u<<9):0; //'buttonchat'. game is the lowest priority, anything else will take focus away. we consider that to mean 'chat' (although it could be menus).
bits |= (cursor_active) ?(1u<<10):0; //prydon cursor stuff. bits |= (cursor_active) ?(1u<<10):0; //'cursor_active'. prydon cursor stuff.
GATHERBIT(in_button[9], 11); GATHERBIT(in_button[9], 11);
GATHERBIT(in_button[10], 12); GATHERBIT(in_button[10], 12);
GATHERBIT(in_button[11], 13); GATHERBIT(in_button[11], 13);
@ -815,6 +815,10 @@ void CL_GatherButtons (usercmd_t *cmd, int pnum)
UNUSEDBUTTON(18); UNUSEDBUTTON(18);
UNUSEDBUTTON(19); UNUSEDBUTTON(19);
// UNUSEDBUTTON(20); // UNUSEDBUTTON(20);
//NQ protocol:
//bit 30 means input_weapon field is sent. figured out at time of sending.
//bit 31 means input_cursor* fields are sent. figured out at time of sending.
cmd->buttons |= bits; cmd->buttons |= bits;
} }
@ -911,6 +915,9 @@ void CL_BaseMove (usercmd_t *cmd, int pnum, float priortime, float extratime)
float nscale = extratime?extratime / (extratime+priortime):0; float nscale = extratime?extratime / (extratime+priortime):0;
float oscale = 1 - nscale; float oscale = 1 - nscale;
cmd->fservertime = cl.time*1000;
cmd->servertime = cl.time*1000;
// //
// adjust for speed key // adjust for speed key
// //
@ -1253,6 +1260,7 @@ void CL_UpdatePrydonCursor(usercmd_t *from, int pnum)
void CLNQ_SendMove (usercmd_t *cmd, int pnum, sizebuf_t *buf) void CLNQ_SendMove (usercmd_t *cmd, int pnum, sizebuf_t *buf)
{ {
int i; int i;
unsigned int bits;
if (cls.demoplayback!=DPB_NONE) if (cls.demoplayback!=DPB_NONE)
return; //err... don't bother... :) return; //err... don't bother... :)
@ -1278,42 +1286,59 @@ void CLNQ_SendMove (usercmd_t *cmd, int pnum, sizebuf_t *buf)
else if (cls.fteprotocolextensions2 & PEXT2_PREDINFO) else if (cls.fteprotocolextensions2 & PEXT2_PREDINFO)
MSG_WriteShort(buf, cl.movesequence&0xffff); MSG_WriteShort(buf, cl.movesequence&0xffff);
MSG_WriteFloat (buf, cmd->fservertime); // use latest time. because ping reports! if (cls.fteprotocolextensions2 & PEXT2_VRINPUTS)
MSGFTE_WriteDeltaUsercmd(buf, &nullcmd, cmd);
for (i=0 ; i<3 ; i++)
{
if (cls.protocol_nq == CPNQ_FITZ666 || (cls.proquake_angles_hack && buf->prim.anglesize <= 1))
{
//fitz/proquake protocols are always 16bit for this angle and 8bit elsewhere. rmq is always at least 16bit
//the above logic should satify everything.
MSG_WriteAngle16 (buf, cl.playerview[pnum].viewangles[i]);
}
else
MSG_WriteAngle (buf, cl.playerview[pnum].viewangles[i]);
}
MSG_WriteShort (buf, cmd->forwardmove);
MSG_WriteShort (buf, cmd->sidemove);
MSG_WriteShort (buf, cmd->upmove);
if (cls.protocol_nq >= CPNQ_DP6 || (cls.fteprotocolextensions2 & PEXT2_PRYDONCURSOR))
{
MSG_WriteLong (buf, cmd->buttons);
MSG_WriteByte (buf, cmd->impulse);
MSG_WriteShort (buf, cmd->cursor_screen[0] * 32767.0f);
MSG_WriteShort (buf, cmd->cursor_screen[1] * 32767.0f);
MSG_WriteFloat (buf, cmd->cursor_start[0]);
MSG_WriteFloat (buf, cmd->cursor_start[1]);
MSG_WriteFloat (buf, cmd->cursor_start[2]);
MSG_WriteFloat (buf, cmd->cursor_impact[0]);
MSG_WriteFloat (buf, cmd->cursor_impact[1]);
MSG_WriteFloat (buf, cmd->cursor_impact[2]);
MSG_WriteEntity (buf, cmd->cursor_entitynumber);
}
else else
{ {
MSG_WriteByte (buf, cmd->buttons); MSG_WriteFloat (buf, cmd->fservertime); // use latest time. because ping reports!
for (i=0 ; i<3 ; i++)
{
if (cls.protocol_nq == CPNQ_FITZ666 || (cls.proquake_angles_hack && buf->prim.anglesize <= 1))
{
//fitz/proquake protocols are always 16bit for this angle and 8bit elsewhere. rmq is always at least 16bit
//the above logic should satify everything.
MSG_WriteAngle16 (buf, cl.playerview[pnum].viewangles[i]);
}
else
MSG_WriteAngle (buf, cl.playerview[pnum].viewangles[i]);
}
MSG_WriteShort (buf, cmd->forwardmove);
MSG_WriteShort (buf, cmd->sidemove);
MSG_WriteShort (buf, cmd->upmove);
bits = cmd->buttons;
if (cls.fteprotocolextensions2 & PEXT2_PRYDONCURSOR)
{
if (cmd->cursor_screen[0] || cmd->cursor_screen[1] ||
cmd->cursor_start[0] || cmd->cursor_start[1] || cmd->cursor_start[2] ||
cmd->cursor_impact[0] || cmd->cursor_impact[1] || cmd->cursor_impact[2] ||
cmd->cursor_entitynumber)
bits |= (1u<<31); //set it if there's actually something to send.
MSG_WriteLong (buf, bits);
}
else if (cls.protocol_nq >= CPNQ_DP6)
{
MSG_WriteLong (buf, bits);
bits |= (1u<<31); //unconditionally set it (without writing it)
}
else
MSG_WriteByte (buf, cmd->buttons);
MSG_WriteByte (buf, cmd->impulse); MSG_WriteByte (buf, cmd->impulse);
if (bits & (1u<<31))
{
MSG_WriteShort (buf, cmd->cursor_screen[0] * 32767.0f);
MSG_WriteShort (buf, cmd->cursor_screen[1] * 32767.0f);
MSG_WriteFloat (buf, cmd->cursor_start[0]);
MSG_WriteFloat (buf, cmd->cursor_start[1]);
MSG_WriteFloat (buf, cmd->cursor_start[2]);
MSG_WriteFloat (buf, cmd->cursor_impact[0]);
MSG_WriteFloat (buf, cmd->cursor_impact[1]);
MSG_WriteFloat (buf, cmd->cursor_impact[2]);
MSG_WriteEntity (buf, cmd->cursor_entitynumber);
}
} }
} }
@ -1700,21 +1725,21 @@ qboolean CL_WriteDeltas (int plnum, sizebuf_t *buf)
cmd = &cl.outframes[i].cmd[plnum]; cmd = &cl.outframes[i].cmd[plnum];
if (cl_c2sImpulseBackup.ival >= 2) if (cl_c2sImpulseBackup.ival >= 2)
dontdrop = dontdrop || cmd->impulse; dontdrop = dontdrop || cmd->impulse;
MSG_WriteDeltaUsercmd (buf, &nullcmd, cmd); MSGCL_WriteDeltaUsercmd (buf, &nullcmd, cmd);
oldcmd = cmd; oldcmd = cmd;
i = (cls.netchan.outgoing_sequence-1) & UPDATE_MASK; i = (cls.netchan.outgoing_sequence-1) & UPDATE_MASK;
if (cl_c2sImpulseBackup.ival >= 3) if (cl_c2sImpulseBackup.ival >= 3)
dontdrop = dontdrop || cmd->impulse; dontdrop = dontdrop || cmd->impulse;
cmd = &cl.outframes[i].cmd[plnum]; cmd = &cl.outframes[i].cmd[plnum];
MSG_WriteDeltaUsercmd (buf, oldcmd, cmd); MSGCL_WriteDeltaUsercmd (buf, oldcmd, cmd);
oldcmd = cmd; oldcmd = cmd;
i = (cls.netchan.outgoing_sequence) & UPDATE_MASK; i = (cls.netchan.outgoing_sequence) & UPDATE_MASK;
if (cl_c2sImpulseBackup.ival >= 1) if (cl_c2sImpulseBackup.ival >= 1)
dontdrop = dontdrop || cmd->impulse; dontdrop = dontdrop || cmd->impulse;
cmd = &cl.outframes[i].cmd[plnum]; cmd = &cl.outframes[i].cmd[plnum];
MSG_WriteDeltaUsercmd (buf, oldcmd, cmd); MSGCL_WriteDeltaUsercmd (buf, oldcmd, cmd);
return dontdrop; return dontdrop;
} }

View File

@ -163,7 +163,7 @@ cvar_t cl_chatsound = CVAR("cl_chatsound","1");
cvar_t cl_enemychatsound = CVAR("cl_enemychatsound", "misc/talk.wav"); cvar_t cl_enemychatsound = CVAR("cl_enemychatsound", "misc/talk.wav");
cvar_t cl_teamchatsound = CVAR("cl_teamchatsound", "misc/talk.wav"); cvar_t cl_teamchatsound = CVAR("cl_teamchatsound", "misc/talk.wav");
cvar_t r_torch = CVARF("r_torch", "0", CVAR_CHEAT); cvar_t r_torch = CVARFD("r_torch", "0", CVAR_CHEAT, "Generate a dynamic light at the player's position.");
cvar_t r_rocketlight = CVARFC("r_rocketlight", "1", CVAR_ARCHIVE, Cvar_Limiter_ZeroToOne_Callback); cvar_t r_rocketlight = CVARFC("r_rocketlight", "1", CVAR_ARCHIVE, Cvar_Limiter_ZeroToOne_Callback);
cvar_t r_lightflicker = CVAR("r_lightflicker", "1"); cvar_t r_lightflicker = CVAR("r_lightflicker", "1");
cvar_t cl_r2g = CVARFD("cl_r2g", "0", CVAR_ARCHIVE, "Uses progs/grenade.mdl instead of progs/missile.mdl when 1."); cvar_t cl_r2g = CVARFD("cl_r2g", "0", CVAR_ARCHIVE, "Uses progs/grenade.mdl instead of progs/missile.mdl when 1.");
@ -188,7 +188,7 @@ cvar_t cl_download_redirection = CVARFD("cl_download_redirection", "2", CVAR_NOT
cvar_t cl_download_mapsrc = CVARFD("cl_download_mapsrc", "", CVAR_ARCHIVE, "Specifies an http location prefix for map downloads. EG: \"http://example.com/path/quakemaps/\""); cvar_t cl_download_mapsrc = CVARFD("cl_download_mapsrc", "", CVAR_ARCHIVE, "Specifies an http location prefix for map downloads. EG: \"http://example.com/path/quakemaps/\"");
cvar_t cl_download_packages = CVARFD("cl_download_packages", "1", CVAR_NOTFROMSERVER, "0=Do not download packages simply because the server is using them. 1=Download and load packages as needed (does not affect games which do not use this package). 2=Do download and install permanently (use with caution!)"); cvar_t cl_download_packages = CVARFD("cl_download_packages", "1", CVAR_NOTFROMSERVER, "0=Do not download packages simply because the server is using them. 1=Download and load packages as needed (does not affect games which do not use this package). 2=Do download and install permanently (use with caution!)");
cvar_t requiredownloads = CVARFD("requiredownloads","1", CVAR_ARCHIVE, "0=join the game before downloads have even finished (might be laggy). 1=wait for all downloads to complete before joining."); cvar_t requiredownloads = CVARFD("requiredownloads","1", CVAR_ARCHIVE, "0=join the game before downloads have even finished (might be laggy). 1=wait for all downloads to complete before joining.");
cvar_t mod_precache = CVARD("mod_precache","1", "Controls when models are loaded.\n0: Load them only when they're visible.\n1: Load them upfront.\n2: Lazily load them to shorten load times at the risk of brief stuttering during only the start of the map."); cvar_t mod_precache = CVARD("mod_precache","1", "Controls when models are loaded.\n0: Load them only when they're actually needed.\n1: Load them upfront.\n2: Lazily load them to shorten load times at the risk of brief stuttering during only the start of the map.");
cvar_t cl_muzzleflash = CVAR("cl_muzzleflash", "1"); cvar_t cl_muzzleflash = CVAR("cl_muzzleflash", "1");
@ -225,6 +225,7 @@ cvar_t ruleset_allow_localvolume = CVARD("ruleset_allow_localvolume", "1", "Al
cvar_t ruleset_allow_shaders = CVARFD("ruleset_allow_shaders", "1", CVAR_SHADERSYSTEM, "When 0, this completely disables the use of external shader files, preventing custom shaders from being used for wallhacks."RULESETADVICE); cvar_t ruleset_allow_shaders = CVARFD("ruleset_allow_shaders", "1", CVAR_SHADERSYSTEM, "When 0, this completely disables the use of external shader files, preventing custom shaders from being used for wallhacks."RULESETADVICE);
cvar_t ruleset_allow_watervis = CVARFCD("ruleset_allow_watervis", "1", CVAR_SHADERSYSTEM, Cvar_CheckServerInfo, "When 0, this enforces ugly opaque water."RULESETADVICE); cvar_t ruleset_allow_watervis = CVARFCD("ruleset_allow_watervis", "1", CVAR_SHADERSYSTEM, Cvar_CheckServerInfo, "When 0, this enforces ugly opaque water."RULESETADVICE);
cvar_t ruleset_allow_fbmodels = CVARFD("ruleset_allow_fbmodels", "0", CVAR_SHADERSYSTEM, "When 1, allows all models to be displayed fullbright, completely ignoring the lightmaps. This feature exists only for parity with ezquake's defaults."RULESETADVICE); cvar_t ruleset_allow_fbmodels = CVARFD("ruleset_allow_fbmodels", "0", CVAR_SHADERSYSTEM, "When 1, allows all models to be displayed fullbright, completely ignoring the lightmaps. This feature exists only for parity with ezquake's defaults."RULESETADVICE);
cvar_t ruleset_allow_triggers = CVARAD("ruleset_allow_triggers", "1", "tp_msgtriggers"/*ez*/, "When 0, blocks the use of msg_trigger checks."RULESETADVICE);
extern cvar_t cl_hightrack; extern cvar_t cl_hightrack;
extern cvar_t vid_renderer; extern cvar_t vid_renderer;
@ -1261,6 +1262,7 @@ void CL_BeginServerReconnect(void)
connectinfo.trying = true; connectinfo.trying = true;
connectinfo.istransfer = false; connectinfo.istransfer = false;
connectinfo.time = 0; connectinfo.time = 0;
connectinfo.tries = 0; //re-ensure routes.
NET_InitClient(false); NET_InitClient(false);
} }
@ -1705,7 +1707,7 @@ void CL_ClearState (qboolean gamestart)
S_UntouchAll(); S_UntouchAll();
S_ResetFailedLoad(); S_ResetFailedLoad();
Cvar_ApplyLatches(CVAR_SERVEROVERRIDE); Cvar_ApplyLatches(CVAR_SERVEROVERRIDE, true);
Con_DPrintf ("Clearing memory\n"); Con_DPrintf ("Clearing memory\n");
if (!serverrunning || !tolocalserver) if (!serverrunning || !tolocalserver)
@ -1717,7 +1719,7 @@ void CL_ClearState (qboolean gamestart)
Mod_ClearAll (); Mod_ClearAll ();
r_regsequence++; r_regsequence++;
Cvar_ApplyLatches(CVAR_LATCH); Cvar_ApplyLatches(CVAR_MAPLATCH, false);
} }
CL_ClearParseState(); CL_ClearParseState();
@ -1894,7 +1896,7 @@ void CL_Disconnect (const char *reason)
SCR_SetLoadingStage(0); SCR_SetLoadingStage(0);
Cvar_ApplyLatches(CVAR_SERVEROVERRIDE); Cvar_ApplyLatches(CVAR_SERVEROVERRIDE, true);
// stop sounds (especially looping!) // stop sounds (especially looping!)
S_StopAllSounds (true); S_StopAllSounds (true);
@ -2000,8 +2002,6 @@ void CL_Disconnect (const char *reason)
cls.findtrack = false; cls.findtrack = false;
cls.realserverip.type = NA_INVALID; cls.realserverip.type = NA_INVALID;
Validation_DelatchRulesets();
#ifdef TCPCONNECT #ifdef TCPCONNECT
//disconnects it, without disconnecting the others. //disconnects it, without disconnecting the others.
FTENET_AddToCollection(cls.sockets, "conn", NULL, NA_INVALID, NP_DGRAM); FTENET_AddToCollection(cls.sockets, "conn", NULL, NA_INVALID, NP_DGRAM);
@ -2899,6 +2899,15 @@ Return to looping demos
*/ */
void CL_Demos_f (void) void CL_Demos_f (void)
{ {
const char *mode = Cmd_Argv(1);
if (!strcmp(mode, "idle"))
{ //'demos idle' only plays the demos when we're idle.
//this can be used for menu backgrounds (engine and menuqc).
if (cls.state || cls.demoplayback || CL_TryingToConnect())
return;
}
//else disconnects can switch gamedirs/paks and kill menuqc etc.
if (cls.demonum == -1) if (cls.demonum == -1)
cls.demonum = 1; cls.demonum = 1;
CL_Disconnect_f (); CL_Disconnect_f ();
@ -3012,7 +3021,6 @@ void CL_Reconnect_f (void)
#endif #endif
CL_Disconnect(NULL); CL_Disconnect(NULL);
connectinfo.tries = 0; //re-ensure routes.
CL_BeginServerReconnect(); CL_BeginServerReconnect();
} }
@ -6325,47 +6333,51 @@ double Host_Frame (double time)
if (host_speeds.ival) if (host_speeds.ival)
time1 = Sys_DoubleTime (); time1 = Sys_DoubleTime ();
for (i = 0; i < MAX_SPLITS; i++) if (!VID_MayRefresh || VID_MayRefresh())
{ {
cl.playerview[i].audio.defaulted = true; if (R2D_Flush)
cl.playerview[i].audio.entnum = cl.playerview[i].viewentity;
VectorClear(cl.playerview[i].audio.origin);
VectorSet(cl.playerview[i].audio.forward, 1, 0, 0);
VectorSet(cl.playerview[i].audio.right, 0, 1, 0);
VectorSet(cl.playerview[i].audio.up, 0, 0, 1);
cl.playerview[i].audio.reverbtype = 0;
VectorClear(cl.playerview[i].audio.velocity);
}
if (R2D_Flush)
{
R2D_Flush();
Con_Printf("R2D_Flush was set outside of SCR_UpdateScreen\n");
}
if (SCR_UpdateScreen && !vid.isminimized)
{
extern cvar_t r_stereo_method;
r_refdef.warndraw = false;
r_refdef.stereomethod = r_stereo_method.ival;
#ifdef FTE_TARGET_WEB
if (emscriptenfte_getvrframedata())
r_refdef.stereomethod = STEREO_WEBVR;
#endif
CL_UpdateHeadAngles();
{ {
RSpeedMark(); R2D_Flush();
vid.ime_allow = false; Con_Printf("R2D_Flush was set outside of SCR_UpdateScreen\n");
if (SCR_UpdateScreen())
fps_count++;
if (R2D_Flush)
Sys_Error("update didn't flush 2d cache\n");
RSpeedEnd(RSPEED_TOTALREFRESH);
} }
r_refdef.warndraw = true;
for (i = 0; i < MAX_SPLITS; i++)
{
cl.playerview[i].audio.defaulted = true;
cl.playerview[i].audio.entnum = cl.playerview[i].viewentity;
VectorClear(cl.playerview[i].audio.origin);
VectorSet(cl.playerview[i].audio.forward, 1, 0, 0);
VectorSet(cl.playerview[i].audio.right, 0, 1, 0);
VectorSet(cl.playerview[i].audio.up, 0, 0, 1);
cl.playerview[i].audio.reverbtype = 0;
VectorClear(cl.playerview[i].audio.velocity);
}
if (SCR_UpdateScreen && !vid.isminimized)
{
extern cvar_t r_stereo_method;
r_refdef.warndraw = false;
r_refdef.stereomethod = r_stereo_method.ival;
#ifdef FTE_TARGET_WEB
if (emscriptenfte_getvrframedata())
r_refdef.stereomethod = STEREO_WEBVR;
#endif
CL_UpdateHeadAngles();
{
RSpeedMark();
vid.ime_allow = false;
if (SCR_UpdateScreen())
fps_count++;
if (R2D_Flush)
Sys_Error("update didn't flush 2d cache\n");
RSpeedEnd(RSPEED_TOTALREFRESH);
}
r_refdef.warndraw = true;
}
else
fps_count++;
} }
else
fps_count++;
if (host_speeds.ival) if (host_speeds.ival)
time2 = Sys_DoubleTime (); time2 = Sys_DoubleTime ();
@ -6446,7 +6458,7 @@ void CL_ReadCDKey(void)
break; break;
} }
} }
Cvar_Get("cl_cdkey", buffer, CVAR_LATCH|CVAR_NOUNSAFEEXPAND, "Q3 compatability"); Cvar_Get("cl_cdkey", buffer, CVAR_MAPLATCH|CVAR_NOUNSAFEEXPAND, "Q3 compatability");
} }
} }
#endif #endif
@ -6549,7 +6561,7 @@ void CL_StartCinematicOrMenu(void)
#endif #endif
if (!cls.state && !Key_Dest_Has(~kdm_game) && cl_demoreel.ival) if (!cls.state && !Key_Dest_Has(~kdm_game) && cl_demoreel.ival)
{ {
cls.demonum = 0; cls.demonum = MAX_DEMOS;
CL_NextDemo(); CL_NextDemo();
} }
if (!cls.state && !Key_Dest_Has(~kdm_game)) if (!cls.state && !Key_Dest_Has(~kdm_game))
@ -6596,6 +6608,9 @@ void CL_ArgumentOverrides(void)
if ((i = COM_CheckParm ("-particles"))) if ((i = COM_CheckParm ("-particles")))
Cvar_Set(Cvar_FindVar("r_part_maxparticles"), com_argv[i+1]); Cvar_Set(Cvar_FindVar("r_part_maxparticles"), com_argv[i+1]);
if (COM_CheckParm("-qmenu"))
Cvar_ForceSet(Cvar_FindVar("forceqmenu"), "1");
} }
//note that this does NOT include commandline. //note that this does NOT include commandline.
@ -6692,6 +6707,8 @@ void CL_ExecInitialConfigs(char *resetcommand)
//and disable the 'you have unsaved stuff' prompt. //and disable the 'you have unsaved stuff' prompt.
Cvar_Saved(); Cvar_Saved();
Ruleset_Scan();
} }
@ -6969,6 +6986,7 @@ void Host_Shutdown(void)
#ifdef QUAKEHUD #ifdef QUAKEHUD
Stats_Clear(); Stats_Clear();
#endif #endif
Ruleset_Shutdown();
#ifdef Q3CLIENT #ifdef Q3CLIENT
VMQ3_FlushStringHandles(); VMQ3_FlushStringHandles();
#endif #endif

View File

@ -2967,6 +2967,7 @@ static void CLDP_ParseDownloadFinished(char *s)
{ {
qdownload_t *dl = cls.download; qdownload_t *dl = cls.download;
unsigned short runningcrc = 0; unsigned short runningcrc = 0;
const hashfunc_t *hfunc = &hash_crc16;
char buffer[8192]; char buffer[8192];
int size, pos, chunk; int size, pos, chunk;
if (!dl || !dl->file) if (!dl || !dl->file)
@ -2979,18 +2980,21 @@ static void CLDP_ParseDownloadFinished(char *s)
dl->file = FS_OpenVFS (dl->tempname+dl->prefixbytes, "rb", dl->fsroot); dl->file = FS_OpenVFS (dl->tempname+dl->prefixbytes, "rb", dl->fsroot);
if (dl->file) if (dl->file)
{ {
char *hashctx = alloca(hfunc->digestsize);
size = dl->size; size = dl->size;
QCRC_Init(&runningcrc); hfunc->init(&hashctx);
for (pos = 0, chunk = 1; chunk; pos += chunk) for (pos = 0, chunk = 1; chunk; pos += chunk)
{ {
chunk = size - pos; chunk = size - pos;
if (chunk > sizeof(buffer)) if (chunk > sizeof(buffer))
chunk = sizeof(buffer); chunk = sizeof(buffer);
VFS_READ(dl->file, buffer, chunk); VFS_READ(dl->file, buffer, chunk);
QCRC_AddBlock(&runningcrc, buffer, chunk); hfunc->process(&hashctx, buffer, chunk);
} }
VFS_CLOSE (dl->file); VFS_CLOSE (dl->file);
dl->file = NULL; dl->file = NULL;
runningcrc = hashfunc_terminate_uint(hfunc, hashctx);
} }
else else
{ {
@ -3376,7 +3380,7 @@ static void CLQW_ParseServerData (void)
{ {
cl.playerview[pnum].spectator = true; cl.playerview[pnum].spectator = true;
if (cls.z_ext & Z_EXT_VIEWHEIGHT) if (cls.z_ext & Z_EXT_VIEWHEIGHT)
cl.playerview[pnum].viewheight = 0; cl.playerview[pnum].viewheight = cl.playerview[pnum].statsf[STAT_VIEWHEIGHT];
cl.playerview[pnum].playernum = (qbyte)MSG_ReadByte(); cl.playerview[pnum].playernum = (qbyte)MSG_ReadByte();
if (cl.playerview[pnum].playernum >= cl.allocated_client_slots) if (cl.playerview[pnum].playernum >= cl.allocated_client_slots)
Host_EndGame("unsupported local player slot\n"); Host_EndGame("unsupported local player slot\n");
@ -3392,7 +3396,7 @@ static void CLQW_ParseServerData (void)
if (clnum == MAX_SPLITS) if (clnum == MAX_SPLITS)
Host_EndGame("Server sent us over %u seats\n", MAX_SPLITS); Host_EndGame("Server sent us over %u seats\n", MAX_SPLITS);
if (cls.z_ext & Z_EXT_VIEWHEIGHT) if (cls.z_ext & Z_EXT_VIEWHEIGHT)
cl.playerview[pnum].viewheight = 0; cl.playerview[pnum].viewheight = cl.playerview[pnum].statsf[STAT_VIEWHEIGHT];
cl.playerview[clnum].playernum = pnum; cl.playerview[clnum].playernum = pnum;
if (cl.playerview[clnum].playernum & 128) if (cl.playerview[clnum].playernum & 128)
{ {
@ -5333,6 +5337,8 @@ static void CL_ProcessUserInfo (int slot, player_info_t *player)
Q_strncpyz (player->name, InfoBuf_ValueForKey (&player->userinfo, "name"), sizeof(player->name)); Q_strncpyz (player->name, InfoBuf_ValueForKey (&player->userinfo, "name"), sizeof(player->name));
Q_strncpyz (player->team, InfoBuf_ValueForKey (&player->userinfo, "team"), sizeof(player->team)); Q_strncpyz (player->team, InfoBuf_ValueForKey (&player->userinfo, "team"), sizeof(player->team));
Ruleset_Check(InfoBuf_ValueForKey (&player->userinfo, RULESET_USERINFO), player->ruleset, sizeof(player->ruleset));
col = InfoBuf_ValueForKey (&player->userinfo, "topcolor"); col = InfoBuf_ValueForKey (&player->userinfo, "topcolor");
if (!strncmp(col, "0x", 2)) if (!strncmp(col, "0x", 2))
player->rtopcolor = 0xff000000|strtoul(col+2, NULL, 16); player->rtopcolor = 0xff000000|strtoul(col+2, NULL, 16);

View File

@ -328,6 +328,7 @@ typedef struct associatedeffect_s
unsigned int meflags; unsigned int meflags;
} associatedeffect_t; } associatedeffect_t;
associatedeffect_t *associatedeffect; associatedeffect_t *associatedeffect;
char part_parsenamespace[MAX_QPATH];
void CL_AssociateEffect_f(void) void CL_AssociateEffect_f(void)
{ {
char *modelname = Cmd_Argv(1); char *modelname = Cmd_Argv(1);
@ -335,6 +336,16 @@ void CL_AssociateEffect_f(void)
int type, i; int type, i;
unsigned int flags = 0; unsigned int flags = 0;
struct associatedeffect_s *ae; struct associatedeffect_s *ae;
if (Cmd_Argc() == 1)
{
for(ae = associatedeffect; ae; ae = ae->next)
{
Con_Printf("^h%c^h %s: %s%s%s\n", (ae->type==AE_TRAIL)?'t':'e', ae->mname, ae->pname,
(ae->meflags & MDLF_EMITREPLACE)?" (replace)":"",
(ae->meflags & MDLF_EMITFORWARDS)?" (foward)":"");
}
return;
}
if (!strcmp(Cmd_Argv(0), "r_trail")) if (!strcmp(Cmd_Argv(0), "r_trail"))
type = AE_TRAIL; type = AE_TRAIL;
else else
@ -367,6 +378,9 @@ void CL_AssociateEffect_f(void)
return; return;
} }
if (*part_parsenamespace && !strchr(effectname, '.'))
effectname = va("%s.%s", part_parsenamespace, effectname);
if (strlen (modelname) >= MAX_QPATH || strlen(effectname) >= MAX_QPATH) if (strlen (modelname) >= MAX_QPATH || strlen(effectname) >= MAX_QPATH)
return; return;

View File

@ -171,6 +171,7 @@ typedef struct player_info_s
int frags; int frags;
int ping; int ping;
qbyte pl; qbyte pl;
char ruleset[19]; //has colour markup to say if its accepted or not
char ip[128]; char ip[128];
@ -1066,6 +1067,7 @@ extern cvar_t ruleset_allow_sensitive_texture_replacements;
extern cvar_t ruleset_allow_localvolume; extern cvar_t ruleset_allow_localvolume;
extern cvar_t ruleset_allow_shaders; extern cvar_t ruleset_allow_shaders;
extern cvar_t ruleset_allow_watervis; extern cvar_t ruleset_allow_watervis;
extern cvar_t ruleset_allow_triggers;
#ifndef SERVERONLY #ifndef SERVERONLY
extern client_state_t cl; extern client_state_t cl;
@ -1614,13 +1616,17 @@ void Skin_FlushAll(void);
//valid.c //valid.c
void RulesetLatch(cvar_t *cvar); #define RULESET_USERINFO "*rs" //the userinfo used to report the ruleset name to other clients. FIXME: remove the _dbg when we think its all working properly.
void Ruleset_Check(char *keyval, char *out, size_t outsize);
void Ruleset_Scan(void);
void Ruleset_Shutdown(void);
const char *Ruleset_GetRulesetName(void);
qboolean Ruleset_FileLoaded(const char *filename, const qbyte *filedata, size_t filesize); //return false if the file is not permitted.
void Validation_Apply_Ruleset(void); void Validation_Apply_Ruleset(void);
void Validation_FlushFileList(void); void Validation_FlushFileList(void);
void Validation_CheckIfResponse(char *text); void Validation_CheckIfResponse(char *text);
void Validation_DelatchRulesets(void); void Validation_DelatchRulesets(void);
void InitValidation(void); void InitValidation(void);
void Validation_FileLoaded(const char *filename, const qbyte *filedata, size_t filesize);
void Validation_Auto_Response(int playernum, char *s); void Validation_Auto_Response(int playernum, char *s);
extern qboolean f_modified_particles; extern qboolean f_modified_particles;

View File

@ -903,7 +903,8 @@ void CLQ3_SendCmd(usercmd_t *cmd)
sizebuf_t msg; sizebuf_t msg;
outframe_t *frame, *oldframe; outframe_t *frame, *oldframe;
int cmdcount, key; int cmdcount, key;
usercmd_t *to, *from; usercmd_t *to;
const usercmd_t *from;
extern cvar_t cl_nodelta, cl_c2sdupe; extern cvar_t cl_nodelta, cl_c2sdupe;
//reuse the q1 array //reuse the q1 array

View File

@ -1208,7 +1208,7 @@ void VARGS Con_SafeTPrintf (translation_t text, ...)
static void Con_DPrintFromThread (void *ctx, void *data, size_t a, size_t b) static void Con_DPrintFromThread (void *ctx, void *data, size_t a, size_t b)
{ {
if (log_developer.ival) if (log_developer.ival || !a)
Con_Log(data); Con_Log(data);
if (developer.ival >= (int)a) if (developer.ival >= (int)a)
{ {
@ -1272,7 +1272,7 @@ void VARGS Con_DLPrintf (int level, const char *fmt, ...)
Sys_Printf("%s", msg); Sys_Printf("%s", msg);
return; return;
#else #else
if (developer.ival<level && !log_developer.ival) if (developer.ival<level && (!log_developer.ival && level))
return; // early exit return; // early exit
#endif #endif
@ -1286,7 +1286,7 @@ void VARGS Con_DLPrintf (int level, const char *fmt, ...)
return; return;
} }
if (log_developer.ival) if (log_developer.ival || !level)
Con_Log(msg); Con_Log(msg);
if (developer.ival >= level) if (developer.ival >= level)
{ {

View File

@ -11572,6 +11572,19 @@ static struct
{PTI_RGBX8, PTI_RGBA8, Image_Tr_NoTransform}, {PTI_RGBX8, PTI_RGBA8, Image_Tr_NoTransform},
{PTI_BGRX8, PTI_BGRA8, Image_Tr_NoTransform}, {PTI_BGRX8, PTI_BGRA8, Image_Tr_NoTransform},
{PTI_LLLX8, PTI_RGBA5551, Image_Tr_8888to5551, false, true},
{PTI_RGBX8, PTI_RGBA5551, Image_Tr_8888to5551, false, true},
{PTI_BGRX8, PTI_RGBA5551, Image_Tr_8888to5551, true, true},
{PTI_LLLX8, PTI_ARGB1555, Image_Tr_8888to1555, false, true},
{PTI_RGBX8, PTI_ARGB1555, Image_Tr_8888to1555, false, true},
{PTI_BGRX8, PTI_ARGB1555, Image_Tr_8888to1555, true, true},
{PTI_LLLX8, PTI_RGBA4444, Image_Tr_8888to4444, false},
{PTI_RGBX8, PTI_RGBA4444, Image_Tr_8888to4444, false},
{PTI_BGRX8, PTI_RGBA4444, Image_Tr_8888to4444, true},
{PTI_LLLX8, PTI_ARGB4444, Image_Tr_8888toARGB4444, false},
{PTI_RGBX8, PTI_ARGB4444, Image_Tr_8888toARGB4444, false},
{PTI_BGRX8, PTI_ARGB4444, Image_Tr_8888toARGB4444, true},
{PTI_RGBX8, PTI_R8, Image_Tr_DropBytes, (4<<16)|1, true}, {PTI_RGBX8, PTI_R8, Image_Tr_DropBytes, (4<<16)|1, true},
{PTI_RGBX8, PTI_RG8, Image_Tr_DropBytes, (4<<16)|2, true}, //for small normalmaps (b can be inferred, a isn't available so avoid offsetmapping) {PTI_RGBX8, PTI_RG8, Image_Tr_DropBytes, (4<<16)|2, true}, //for small normalmaps (b can be inferred, a isn't available so avoid offsetmapping)
{PTI_RGBA16, PTI_R16, Image_Tr_DropBytes, (8<<16)|2, true}, {PTI_RGBA16, PTI_R16, Image_Tr_DropBytes, (8<<16)|2, true},

View File

@ -1085,3 +1085,49 @@ void IN_Gyroscope(unsigned int devid, float pitch, float yaw, float roll)
ev->gyro.roll = roll; ev->gyro.roll = roll;
in_finishevent(); in_finishevent();
} }
extern usercmd_t cl_pendingcmd[MAX_SPLITS];
qboolean IN_SetHandPosition(const char *devname, vec3_t org, vec3_t ang, vec3_t vel, vec3_t avel)
{
int dtype;
int seat;
if (!strncmp(devname, "left", 4))
{
seat = atoi(devname+4);
dtype = VRDEV_LEFT;
}
else if (!strncmp(devname, "right", 5))
{
seat = atoi(devname+5);
dtype = VRDEV_RIGHT;
}
else if (!strncmp(devname, "head", 4))
{
seat = atoi(devname+4);
dtype = VRDEV_HEAD;
}
else
return false; //no idea what you're talking about.
if (seat < 0 || seat >= MAX_SPLITS)
return false; //duuuude!
cl_pendingcmd[seat].vr[dtype].status =
(org ?VRSTATUS_ORG:0)|
(ang ?VRSTATUS_ANG:0)|
(vel ?VRSTATUS_VEL:0)|
(avel?VRSTATUS_AVEL:0);
if (org)
VectorCopy(org, cl_pendingcmd[seat].vr[dtype].origin);
if (ang)
cl_pendingcmd[seat].vr[dtype].angles[0] = ANGLE2SHORT(ang[0]),
cl_pendingcmd[seat].vr[dtype].angles[1] = ANGLE2SHORT(ang[1]),
cl_pendingcmd[seat].vr[dtype].angles[2] = ANGLE2SHORT(ang[2]);
if (vel)
VectorCopy(vel, cl_pendingcmd[seat].vr[dtype].velocity);
if (avel)
cl_pendingcmd[seat].vr[dtype].avelocity[0] = ANGLE2SHORT(avel[0]),
cl_pendingcmd[seat].vr[dtype].avelocity[1] = ANGLE2SHORT(avel[1]),
cl_pendingcmd[seat].vr[dtype].avelocity[2] = ANGLE2SHORT(avel[2]);
return true;
}

View File

@ -51,6 +51,7 @@ void IN_MouseMove(unsigned int devid, int abs, float x, float y, float z, float
void IN_JoystickAxisEvent(unsigned int devid, int axis, float value); void IN_JoystickAxisEvent(unsigned int devid, int axis, float value);
void IN_Accelerometer(unsigned int devid, float x, float y, float z); void IN_Accelerometer(unsigned int devid, float x, float y, float z);
void IN_Gyroscope(unsigned int devid, float pitch, float yaw, float roll); void IN_Gyroscope(unsigned int devid, float pitch, float yaw, float roll);
qboolean IN_SetHandPosition(const char *devname, vec3_t org, vec3_t ang, vec3_t vel, vec3_t avel);
//system-specific functions //system-specific functions
void INS_Move (void); void INS_Move (void);

File diff suppressed because it is too large Load Diff

View File

@ -482,12 +482,6 @@ static void MenuDrawItems(int xpos, int ypos, menuoption_t *option, emenu_t *men
menuframe_t *framescroller = NULL; menuframe_t *framescroller = NULL;
if (option && option->common.type == mt_box && !option->common.ishidden)
{ //FIXME: why is this here? why is this special?
Draw_ApproxTextBox(xpos+option->common.posx, ypos+option->common.posy, option->box.width, option->box.height);
option = option->common.next;
}
for (; option; option = option->common.next) for (; option; option = option->common.next)
{ {
if (option->common.ishidden) if (option->common.ishidden)
@ -1382,21 +1376,23 @@ menucombo_t *MC_AddCvarCombo(emenu_t *menu, int tx, int cx, int y, const char *c
char **newops; char **newops;
char **newvalues; char **newvalues;
char *optbuf; char *optbuf;
const char *v;
int i; int i;
maxoptlen = 0; maxoptlen = 0;
optbufsize = sizeof(char*)*2 + strlen(caption)+1; optbufsize = sizeof(char*)*2 + strlen(caption)+1;
numopts = 0;
optlen = 0; optlen = 0;
while(ops[numopts]) for (i = 0; ops[i]; i++)
{ {
optlen = strlen(ops[numopts]); v = values?values[i]:va("%i", i);
optlen = strlen(ops[i]);
if (maxoptlen < optlen) if (maxoptlen < optlen)
maxoptlen = optlen; maxoptlen = optlen;
optbufsize += optlen+1+sizeof(char*); optbufsize += optlen+1+sizeof(char*);
optbufsize += strlen(values[numopts])+1+sizeof(char*); optbufsize += strlen(v)+1+sizeof(char*);
numopts++;
} }
numopts = i;
@ -1432,14 +1428,16 @@ menucombo_t *MC_AddCvarCombo(emenu_t *menu, int tx, int cx, int y, const char *c
n->numoptions = numopts; n->numoptions = numopts;
for (i = 0; i < numopts; i++) for (i = 0; i < numopts; i++)
{ {
if (!strcmp(values[i], cvar->string)) v = values?values[i]:va("%i", i);
if (!strcmp(v, cvar->string))
n->selectedoption = i; n->selectedoption = i;
strcpy(optbuf, ops[i]); strcpy(optbuf, ops[i]);
newops[i] = optbuf; newops[i] = optbuf;
optbuf += strlen(optbuf)+1; optbuf += strlen(optbuf)+1;
strcpy(optbuf, values[i]); strcpy(optbuf, v);
newvalues[i] = optbuf; newvalues[i] = optbuf;
optbuf += strlen(optbuf)+1; optbuf += strlen(optbuf)+1;
} }
@ -1729,7 +1727,7 @@ static void M_Draw (menu_t *menu)
} }
if ((!menu_script || scr_con_current)) if ((!menu_script || scr_con_current))
{ {
if (m->selecteditem && m->selecteditem->common.type == mt_slider && (m->selecteditem->slider.var == &v_gamma || m->selecteditem->slider.var == &v_contrast)) if (m->nobacktint || (m->selecteditem && m->selecteditem->common.type == mt_slider && (m->selecteditem->slider.var == &v_gamma || m->selecteditem->slider.var == &v_contrast)))
/*no menu tint if we're trying to adjust gamma*/; /*no menu tint if we're trying to adjust gamma*/;
else else
R2D_FadeScreen (); R2D_FadeScreen ();
@ -1873,7 +1871,7 @@ void M_MenuPop_f (void)
Menu_Unlink(topmenu); Menu_Unlink(topmenu);
} }
menuoption_t *M_NextItem(emenu_t *m, menuoption_t *old) static menuoption_t *M_NextItem(emenu_t *m, menuoption_t *old)
{ {
menuoption_t *op = m->options; menuoption_t *op = m->options;
while(op->common.next) while(op->common.next)
@ -1889,6 +1887,9 @@ menuoption_t *M_NextSelectableItem(emenu_t *m, menuoption_t *old)
{ {
menuoption_t *op; menuoption_t *op;
if (!m->options)
return NULL; //erk!
if (!old) if (!old)
old = M_NextItem(m, old); old = M_NextItem(m, old);
@ -1920,6 +1921,9 @@ menuoption_t *M_PrevSelectableItem(emenu_t *m, menuoption_t *old)
{ {
menuoption_t *op; menuoption_t *op;
if (!m->options)
return NULL; //erk!
if (!old) if (!old)
old = m->options; old = m->options;
@ -2485,7 +2489,7 @@ void M_Menu_Main_f (void)
int MC_AddBulk(struct emenu_s *menu, menuresel_t *resel, menubulk_t *bulk, int xstart, int xtextend, int y) int MC_AddBulk(struct emenu_s *menu, menuresel_t *resel, menubulk_t *bulk, int xstart, int xtextend, int y)
{ {
int selectedy = y; int selectedy = y, last_y = y;
menuoption_t *selected = NULL; menuoption_t *selected = NULL;
while (bulk) while (bulk)
@ -2597,6 +2601,9 @@ int MC_AddBulk(struct emenu_s *menu, menuresel_t *resel, menubulk_t *bulk, int x
if (bulk->ret) if (bulk->ret)
*bulk->ret = control; *bulk->ret = control;
if (control)
control->common.grav_y = y-last_y;
last_y = y;
if (control && MI_Selectable(control) && !selected) if (control && MI_Selectable(control) && !selected)
selected = control; selected = control;
if (control && bulk->tooltip) if (control && bulk->tooltip)

View File

@ -1042,7 +1042,7 @@ const char *presetexec[] =
, // realtime options , // realtime options
"r_bloom 1;" "r_bloom 1;"
"r_deluxemapping 0;" //won't be seen anyway "r_deluxemapping 1;" //won't be seen anyway
"r_particledesc \"high tsshaft\";" "r_particledesc \"high tsshaft\";"
// "r_waterstyle 3;" //too expensive. // "r_waterstyle 3;" //too expensive.
"r_glsl_offsetmapping 1;" "r_glsl_offsetmapping 1;"
@ -1176,12 +1176,106 @@ static void ApplyPreset (int presetnum, qboolean doreload)
if (doreload) if (doreload)
{ {
forcesaveprompt = true; forcesaveprompt = true;
Cbuf_InsertText("\nfs_restart\nvid_reload\n", RESTRICT_LOCAL, true); Cbuf_InsertText("\nfs_restart\nvid_reload\ncl_warncmd 1\n", RESTRICT_LOCAL, true);
} }
for (i = presetnum; i >= 0; i--) for (i = presetnum; i >= 0; i--)
{ {
Cbuf_InsertText(presetexec[i], RESTRICT_LOCAL, true); Cbuf_InsertText(presetexec[i], RESTRICT_LOCAL, true);
} }
if (doreload)
{
Cbuf_InsertText("\ncl_warncmd 0\n", RESTRICT_LOCAL, true);
}
}
static int M_Menu_Preset_GetActive(void)
{
extern cvar_t r_drawflat;
//bottoms up!
#ifdef RTLIGHTS
if (r_shadow_realtime_world.ival)
return 6; //realtime
else
#endif
if (r_deluxemapping_cvar.ival)
return 5; //nice
else if (gl_load24bit.ival)
return 4; //normal
else if (r_softwarebanding_cvar.ival)
return 3; //vanilla
else if (cl_sbar.ival == 2)
return 2; //spasm
else if (!r_drawflat.ival)
return 1; //fast
else
return 0; //simple
}
static void M_Menu_Preset_Predraw(emenu_t *menu)
{
extern cvar_t m_preset_chosen;
int last_y;
menuoption_t *op, *prev;
int preset = M_Menu_Preset_GetActive();
int i;
qboolean forcereload = false;
#ifdef RTLIGHTS
preset = 6-preset;
#else
preset = 5-preset;
#endif
for (op = menu->options; op; op = op->common.next)
{
prev = op->common.next;
while (prev && prev->common.ishidden)
{ //this uglyness is because the menu items are added bottom-up.
prev = prev->common.next; //erk...
}
last_y = prev?prev->common.posy:0;
if (op->common.type == mt_button)
{
if (!strcmp(op->button.command, "menupop\n"))
{
if (m_preset_chosen.ival)
op->button.text = "^sAccept";
}
else if (!strncmp(op->button.command, "fps_preset ", 11))
{
((char*)op->button.text)[1] = (preset==0)?'m':'7';
preset--;
}
}
else if(op->common.type == mt_checkbox||
op->common.type == mt_slider||
op->common.type == mt_combo) op->common.ishidden = preset!=0;
if (op->common.type == mt_combo && op->combo.cvar)
{ //make sure combo items are updated properly if their cvar value is changed via some other mechanism...
const char *curval = op->combo.cvar->latched_string?op->combo.cvar->latched_string:op->combo.cvar->string;
if (strcmp(curval, op->combo.values[op->combo.selectedoption]))
{
for (i = 0; i < op->combo.numoptions; i++)
{
if (!strcmp(curval, op->combo.values[i]))
{
op->combo.selectedoption = i;
break;
}
}
}
if (op->combo.cvar->latched_string && (op->combo.cvar->flags&CVAR_LATCHMASK) == CVAR_RENDERERLATCH)
forcereload = true;
}
if (op->common.grav_y)
op->common.posy = last_y+op->common.grav_y;
}
if (forcereload)
Cbuf_InsertText("\nfs_restart\nvid_reload\n", RESTRICT_LOCAL, true);
} }
void M_Menu_Preset_f (void) void M_Menu_Preset_f (void)
@ -1189,25 +1283,45 @@ void M_Menu_Preset_f (void)
extern cvar_t cfg_save_auto; extern cvar_t cfg_save_auto;
emenu_t *menu; emenu_t *menu;
int y; int y;
menuoption_t *presetoption[7];
extern cvar_t r_nolerp, r_bloom, sv_nqplayerphysics, r_shadow_realtime_world_importlightentitiesfrommap;
static const char *deluxeopts[] = {
"Off",
"Auto",
"Force",
NULL
};
menubulk_t bulk[] = menubulk_t bulk[] =
{ {
MB_REDTEXT("Please Choose Preset", true), MB_REDTEXT("Please Choose Preset", true),
MB_TEXT("^Ue080^Ue081^Ue081^Ue081^Ue081^Ue081^Ue081^Ue081^Ue081^Ue081^Ue081^Ue081^Ue081^Ue081^Ue081^Ue081^Ue082", true), MB_TEXT("^Ue080^Ue081^Ue081^Ue081^Ue081^Ue081^Ue081^Ue081^Ue081^Ue081^Ue081^Ue081^Ue081^Ue081^Ue081^Ue081^Ue082", true),
MB_CONSOLECMD("simple (untextured)", "fps_preset 286;menupop\n", "Lacks textures, particles, pretty much everything."), MB_CONSOLECMDRETURN("^7simple (untextured)", "fps_preset 286\n", "Lacks textures, particles, pretty much everything.", presetoption[0]),
MB_CONSOLECMD("fast (qw deathmatch)", "fps_preset fast;menupop\n", "Fullscreen effects off to give consistant framerates"), MB_CHECKBOXCVAR("anim snapping", r_nolerp, 0),
MB_CONSOLECMD("spasm (nq compat)", "fps_preset spasm;menupop\n", "Aims for visual compatibility with common NQ engines. Also affects mods slightly."), MB_CONSOLECMDRETURN("^7fast (qw deathmatch)", "fps_preset fast\n", "Fullscreen effects off to give consistant framerates", presetoption[1]),
MB_CONSOLECMD("vanilla (softwarey)", "fps_preset vanilla;menupop\n", "This is for purists! Party like its 1995! No sanity spared!"), MB_CONSOLECMDRETURN("^7spasm (nq compat)", "fps_preset spasm\n", "Aims for visual compatibility with common NQ engines. Also affects mods slightly.", presetoption[2]),
MB_CONSOLECMD("normal (faithful)", "fps_preset normal;menupop\n", "An updated but still faithful appearance, using content replacements where applicable"), #ifdef HAVE_SERVER
MB_CONSOLECMD("nice (dynamic)", "fps_preset nice;menupop\n", "For people who like nice things, but still want to actually play"), MB_CHECKBOXCVAR("nq physics", sv_nqplayerphysics, 0),
#endif
MB_CONSOLECMDRETURN("^7vanilla (softwarey)", "fps_preset vanilla\n", "This is for purists! Party like its 1995! No sanity spared!", presetoption[3]),
MB_CHECKBOXCVAR("anim snapping", r_nolerp, 1),
MB_CHECKBOXCVAR("model swimming", gl_affinemodels, 0),
MB_CONSOLECMDRETURN("^7normal (faithful)", "fps_preset normal\n", "An updated but still faithful appearance, using content replacements where applicable", presetoption[4]),
MB_CONSOLECMDRETURN("^7nice (dynamic)", "fps_preset nice\n", "For people who like nice things, but still want to actually play", presetoption[5]),
MB_COMBOCVAR("gen deluxemaps", r_deluxemapping_cvar, deluxeopts, NULL, NULL),
#ifdef RTLIGHTS #ifdef RTLIGHTS
MB_CONSOLECMD("realtime (all on)", "fps_preset realtime;menupop\n", "For people who value pretty over fast/smooth. Not viable for deathmatch."), MB_CONSOLECMDRETURN("^7realtime (all on)", "fps_preset realtime\n", "For people who value pretty over fast/smooth. Not viable for deathmatch.", presetoption[6]),
MB_CHECKBOXCVAR("bloom", r_bloom, 1),
MB_CHECKBOXCVAR("force rtlights", r_shadow_realtime_world_importlightentitiesfrommap, 1),
#endif #endif
MB_SPACING(16), MB_SPACING(16),
MB_CHECKBOXCVARTIP("Auto-save Settings", cfg_save_auto, 1, "If this is disabled, you will need to explicitly save your settings."), MB_CHECKBOXCVARTIP("Auto-save Settings", cfg_save_auto, 1, "If this is disabled, you will need to explicitly save your settings."),
MB_SPACING(16),
MB_CONSOLECMD("Accept", "menupop\n", NULL),
MB_END() MB_END()
}; };
static menuresel_t resel; static menuresel_t resel;
int item, bias = 0; int item;
extern cvar_t r_drawflat; extern cvar_t r_drawflat;
menu = M_Options_Title(&y, 0); menu = M_Options_Title(&y, 0);
MC_AddBulk(menu, &resel, bulk, 16, 216, y); MC_AddBulk(menu, &resel, bulk, 16, 216, y);
@ -1215,28 +1329,32 @@ void M_Menu_Preset_f (void)
//bottoms up! //bottoms up!
#ifdef RTLIGHTS #ifdef RTLIGHTS
if (r_shadow_realtime_world.ival) if (r_shadow_realtime_world.ival)
item = 1; //realtime item = 6; //realtime
else else
#else
bias = 1;
#endif #endif
if (r_deluxemapping_cvar.ival) if (r_deluxemapping_cvar.ival)
item = 2; //nice item = 5; //nice
else if (gl_load24bit.ival) else if (gl_load24bit.ival)
item = 3; //normal item = 4; //normal
else if (r_softwarebanding_cvar.ival) else if (r_softwarebanding_cvar.ival)
item = 4; //vanilla item = 3; //vanilla
else if (cl_sbar.ival == 2) else if (cl_sbar.ival == 2)
item = 5; //spasm item = 2; //spasm
else if (!r_drawflat.ival) else if (!r_drawflat.ival)
item = 6; //fast item = 1; //fast
else else
item = 7; //simple item = 0; //simple
item++; //the autosave option if (presetoption[item])
item -= bias; {
while (item --> 0) menu->selecteditem = presetoption[item];
menu->selecteditem = menu->selecteditem->common.next; menu->cursoritem->common.posy = menu->selecteditem->common.posy;
menu->cursoritem->common.posy = menu->selecteditem->common.posy; }
//so they can actually see the preset they're picking.
menu->nobacktint = true;
menu->predraw = M_Menu_Preset_Predraw;
Cbuf_InsertText("\ndemos idle\n", RESTRICT_LOCAL, false);
} }
void FPS_Preset_f (void) void FPS_Preset_f (void)
@ -3959,6 +4077,19 @@ void M_Modelviewer_Shutdown(struct emenu_s *menu)
skel_reset(&mv->ragworld); skel_reset(&mv->ragworld);
World_RBE_Shutdown(&mv->ragworld); World_RBE_Shutdown(&mv->ragworld);
} }
void M_Modelviewer_Reset(struct menu_s *cmenu)
{
emenu_t *menu = (emenu_t*)cmenu;
modelview_t *mv = menu->data;
mv->ragworld.worldmodel = NULL; //already went away
rag_removedeltaent(&mv->ragent);
skel_reset(&mv->ragworld);
World_RBE_Shutdown(&mv->ragworld);
//we still want it.
mv->ragworld.worldmodel = NULL;//Mod_ForName("", MLV_SILENT);
// World_RBE_Start(&mv->ragworld);
}
//haxors, for skeletal objects+RBE //haxors, for skeletal objects+RBE
char *PDECL M_Modelviewer_AddString(pubprogfuncs_t *prinst, const char *val, int minlength, pbool demarkup) char *PDECL M_Modelviewer_AddString(pubprogfuncs_t *prinst, const char *val, int minlength, pbool demarkup)
{ {
@ -3977,6 +4108,8 @@ void M_Menu_ModelViewer_f(void)
emenu_t *menu; emenu_t *menu;
menu = M_CreateMenu(sizeof(*mv)); menu = M_CreateMenu(sizeof(*mv));
menu->menu.persist = true;
menu->menu.videoreset = M_Modelviewer_Reset;
mv = menu->data; mv = menu->data;
c = MC_AddCustom(menu, 64, 32, mv, 0, NULL); c = MC_AddCustom(menu, 64, 32, mv, 0, NULL);
menu->cursoritem = (menuoption_t*)c; menu->cursoritem = (menuoption_t*)c;

View File

@ -540,10 +540,9 @@ void M_Menu_SinglePlayer_f (void)
p = R2D_SafeCachePic("gfx/sp_menu.lmp"); p = R2D_SafeCachePic("gfx/sp_menu.lmp");
if (!p) if (!p)
{ {
MC_AddBox (menu, 60, 10*8, 23*8, 4*8);
MC_AddWhiteText(menu, 92, 0, 12*8, "Couldn't find file", false); MC_AddWhiteText(menu, 92, 0, 12*8, "Couldn't find file", false);
MC_AddWhiteText(menu, 92, 0, 13*8, "gfx/sp_menu.lmp", false); MC_AddWhiteText(menu, 92, 0, 13*8, "gfx/sp_menu.lmp", false);
MC_AddBox (menu, 72, 11*8, 23*8, 4*8);
} }
else else
{ {

View File

@ -418,8 +418,8 @@ typedef struct
void (*callback)(void *, promptbutton_t); void (*callback)(void *, promptbutton_t);
void *ctx; void *ctx;
int lines; conchar_t *msg;
const char *messages; size_t msglen;
const char *buttons[3]; const char *buttons[3];
int kbutton, mbutton; int kbutton, mbutton;
qboolean mousedown; qboolean mousedown;
@ -516,22 +516,35 @@ static void Prompt_Draw(struct menu_s *g)
promptmenu_t *m = (promptmenu_t*)g; promptmenu_t *m = (promptmenu_t*)g;
int x = 64; int x = 64;
int y = 76; int y = 76;
int px, py;
float scale = Font_CharVHeight(font_console); float scale = Font_CharVHeight(font_console);
int w = 320*scale/8; int w = 320*scale/8;
int h = (m->lines+3)*scale; int h, lines;
int i; int i;
const char *msg = m->messages;
int bx[4]; int bx[4];
conchar_t *linestart[16];
conchar_t *lineend[countof(linestart)];
x = ((vid.width-w)>>1); x = (((int)vid.width-w)>>1);
Font_BeginString(font_console, w, 0, &px, &py);
lines = Font_LineBreaks(m->msg, m->msg+m->msglen, px, countof(linestart), linestart, lineend);
h = (lines+3)*scale;
Font_EndString(font_console);
Draw_ApproxTextBox(x, y, w, h); Draw_ApproxTextBox(x, y, w, h);
y+=scale; y+=scale;
for (i = 0; i < m->lines; i++, msg = msg+strlen(msg)+1)
Font_BeginString(font_console, x, y, &px, &py);
for (i = 0; i < lines; i++)
{ {
Draw_FunStringWidthFont(font_console, x, y, msg, w, 2, false); int xoffset = (w*vid.rotpixelwidth/vid.width) - Font_LineWidth(linestart[i], lineend[i]);
y+=scale; Font_LineDraw(px + xoffset/2, py, linestart[i], lineend[i]);
py+=Font_CharHeight();
} }
Font_EndString(font_console);
y+=scale*lines;
y+=scale; y+=scale;
m->mbutton = -1; m->mbutton = -1;
bx[0] = x; bx[0] = x;
@ -576,8 +589,11 @@ void Menu_Prompt (void (*callback)(void *, promptbutton_t), void *ctx, const cha
{ {
promptmenu_t *m; promptmenu_t *m;
char *t; char *t;
conchar_t message[8192], *e;
m = (promptmenu_t*)Z_Malloc(sizeof(*m) + strlen(messages)+(optionyes?strlen(optionyes):0)+(optionno?strlen(optionno):0)+(optioncancel?strlen(optioncancel):0)+7); e = COM_ParseFunString(CON_WHITEMASK, messages, message, sizeof(message)-sizeof(conchar_t), false);
m = (promptmenu_t*)Z_Malloc(sizeof(*m) + (e-message)*sizeof(conchar_t)+(optionyes?strlen(optionyes):0)+(optionno?strlen(optionno):0)+(optioncancel?strlen(optioncancel):0)+7);
m->m.cursor = &key_customcursor[kc_console]; m->m.cursor = &key_customcursor[kc_console];
/*void (*videoreset) (struct menu_s *); //called after a video mode switch / shader reload. /*void (*videoreset) (struct menu_s *); //called after a video mode switch / shader reload.
@ -617,16 +633,8 @@ void Menu_Prompt (void (*callback)(void *, promptbutton_t), void *ctx, const cha
t += strlen(t)+1; t += strlen(t)+1;
} }
m->messages = t; m->msglen = e-message;
strcpy(t, messages); m->msg = memcpy(t, message, (m->msglen)*sizeof(conchar_t));
for(messages = t; t;)
{
t = strchr(t, '\n');
if (t)
*t++ = 0;
m->lines++;
}
} }
#ifndef NOBUILTINMENUS #ifndef NOBUILTINMENUS

View File

@ -174,6 +174,10 @@ typedef struct { //must be first of each structure type.
int width; //total width int width; //total width
int height; //total height int height; //total height
int extracollide; // dirty hack to stretch collide box left (the real fix is to have separate collide/render rects) int extracollide; // dirty hack to stretch collide box left (the real fix is to have separate collide/render rects)
//unsigned int grav_type;
//int grav_x; //
int grav_y; //
//int grav_size[2];
const char *tooltip; const char *tooltip;
qboolean noselectionsound:1; qboolean noselectionsound:1;
qboolean iszone:1; qboolean iszone:1;
@ -309,11 +313,12 @@ struct emenu_s {
int ypos; int ypos;
int width; int width;
int height; int height;
qboolean dontexpand; qboolean dontexpand; //false=recenter xpos
int numoptions; int numoptions;
menuresel_t *reselection; //stores some info to restore selection properly. menuresel_t *reselection; //stores some info to restore selection properly.
qboolean iszone; qboolean iszone;
qboolean nobacktint;
void *data; //typecast void *data; //typecast
@ -384,9 +389,10 @@ typedef struct menubulk_s {
} menubulk_t; } menubulk_t;
#define MB_CONSOLECMD(text, cmd, tip) {mt_button, 0, text, tip, cmd} #define MB_CONSOLECMD(text, cmd, tip) {mt_button, 0, text, tip, cmd}
#define MB_CHECKBOXCVAR(text, cvar, flags) {mt_checkbox, 0, text, NULL, NULL, &cvar, flags} #define MB_CONSOLECMDRETURN(text, cmd, tip, ret) {mt_button, 0, text, tip, cmd, NULL, 0, NULL, 0, 0, 0, false, NULL, NULL, NULL, NULL, 0, (union menuoption_s **)&ret}
#define MB_CHECKBOXCVARTIP(text, cvar, flags, tip) {mt_checkbox, 0, text, tip, NULL, &cvar, flags} #define MB_CHECKBOXCVAR(text, cvar, cvarflag) {mt_checkbox, 0, text, NULL, NULL, &cvar, cvarflag}
#define MB_CHECKBOXCVARRETURN(text, cvar, flags, ret) {mt_checkbox, 0, text, NULL, NULL, &cvar, flags, NULL, 0, 0, 0, false, NULL, NULL, NULL, NULL, 0, (union menuoption_s **)&ret} #define MB_CHECKBOXCVARTIP(text, cvar, cvarflag, tip) {mt_checkbox, 0, text, tip, NULL, &cvar, cvarflag}
#define MB_CHECKBOXCVARRETURN(text, cvar, cvarflag, ret) {mt_checkbox, 0, text, NULL, NULL, &cvar, cvarflag, NULL, 0, 0, 0, false, NULL, NULL, NULL, NULL, 0, (union menuoption_s **)&ret}
#define MB_CHECKBOXFUNC(text, func, flags, tip) {mt_checkbox, 0, text, tip, NULL, NULL, flags, func} #define MB_CHECKBOXFUNC(text, func, flags, tip) {mt_checkbox, 0, text, tip, NULL, NULL, flags, func}
#define MB_SLIDER(text, cvar, min, max, delta, tip) {mt_slider, 0, text, tip, NULL, &cvar, 0, NULL, min, max, delta} #define MB_SLIDER(text, cvar, min, max, delta, tip) {mt_slider, 0, text, tip, NULL, &cvar, 0, NULL, min, max, delta}
#define MB_TEXT(text, align) {mt_text, 0, text, NULL, NULL, NULL, 0, NULL, 0, 0, 0, align} #define MB_TEXT(text, align) {mt_text, 0, text, NULL, NULL, NULL, 0, NULL, 0, 0, 0, align}

View File

@ -482,9 +482,10 @@ typedef struct rendererinfo_s {
char *alignment; //just to make sure that added functions cause compile warnings. char *alignment; //just to make sure that added functions cause compile warnings.
//FIXME: keep this...
int (*VID_GetPriority) (void); //so that eg x11 or wayland can be prioritised depending on environment settings. assumed to be 1. int (*VID_GetPriority) (void); //so that eg x11 or wayland can be prioritised depending on environment settings. assumed to be 1.
void (*VID_EnumerateVideoModes) (const char *driver, const char *output, void (*cb) (int w, int h)); void (*VID_EnumerateVideoModes) (const char *driver, const char *output, void (*cb) (int w, int h));
qboolean(*VID_EnumerateDevices) (void *usercontext, void(*callback)(void *context, const char *devicename, const char *outputname, const char *desc));
qboolean(*VID_MayRefresh) (void);
//FIXME: add getdestopres //FIXME: add getdestopres
//FIXME: add clipboard handling //FIXME: add clipboard handling
@ -493,6 +494,7 @@ typedef struct rendererinfo_s {
#define rf currentrendererstate.renderer #define rf currentrendererstate.renderer
#define VID_SwapBuffers rf->VID_SwapBuffers #define VID_SwapBuffers rf->VID_SwapBuffers
#define VID_MayRefresh rf->VID_MayRefresh
#define BE_Init rf->BE_Init #define BE_Init rf->BE_Init
#define BE_SelectMode rf->BE_SelectMode #define BE_SelectMode rf->BE_SelectMode

View File

@ -85,6 +85,7 @@ static void SV_SetMaster_f (void);
extern cvar_t sv_public; extern cvar_t sv_public;
extern cvar_t sv_reportheartbeats; extern cvar_t sv_reportheartbeats;
extern cvar_t sv_heartbeat_interval; extern cvar_t sv_heartbeat_interval;
extern cvar_t sv_heartbeat_checks;
extern cvar_t sv_listen_qw; extern cvar_t sv_listen_qw;
extern cvar_t sv_listen_nq; extern cvar_t sv_listen_nq;
@ -204,7 +205,8 @@ static net_masterlist_t net_masterlist[] = {
{MP_UNSPECIFIED, CVAR(NULL, NULL)} {MP_UNSPECIFIED, CVAR(NULL, NULL)}
}; };
qboolean Net_AddressIsMaster(netadr_t *adr) #ifdef HAVE_SERVER
qboolean SV_Master_AddressIsMaster(netadr_t *adr)
{ {
size_t i, j; size_t i, j;
//never throttle packets from master servers. we don't want to go missing. //never throttle packets from master servers. we don't want to go missing.
@ -214,13 +216,51 @@ qboolean Net_AddressIsMaster(netadr_t *adr)
continue; continue;
for (j = 0; j < MAX_MASTER_ADDRESSES; j++) for (j = 0; j < MAX_MASTER_ADDRESSES; j++)
if (net_masterlist[i].adr[j].type != NA_INVALID) if (net_masterlist[i].adr[j].type != NA_INVALID)
if (NET_CompareAdr(&net_from, &net_masterlist[i].adr[j])) if (NET_CompareBaseAdr(&net_from, &net_masterlist[i].adr[j]))
return true; return true;
} }
return false; return false;
} }
void SV_Master_HeartbeatResponse(netadr_t *adr, const char *challenge)
{
//ftemaster responds from two different ports. one direct, one indirect.
//if there's a NAT/firewall issue then the indirect response is lost.
//thus if we get more than X direct responses without any indirect ones in that time, start warning because the server is unreachable and thus probably pointless.
qboolean directresponse = (*challenge=='?'); //this is a fallback (direct) response.
static size_t directresponse_count;
static double okaytimestamp; //timer throttle, in case there's spoofing going on. we won't get any DoS attacks but its still annoying.
#ifdef HAVE_SERVER //'?' denotes the master trying to send a direct response.
//length>0&&length<12 denotes a dpmaster query
//no challengedenotes a client (if they get our address then its all good)
if (*challenge && strlen(challenge) <= 12)
return; //outdated dpmaster. these are (probably) direct responses that don't really mean anything.
if (NET_ClassifyAddress(adr, NULL) != ASCOPE_NET)
return; //ignore any broadcast lan probes.
//if we're getting fake-direct responses without typical indirect ones then someone's probably being obnoxious and trying to trigger some false positives.
//FIXME: spoofed fake-direct responses can still be an annoyance, but this is informative only, so not a real issue.
if (directresponse && !SV_Master_AddressIsMaster(adr))
directresponse = false;
if (directresponse && sv_public.ival == 1)
directresponse_count++; //bad...
else
directresponse_count = 0; //yay! we're reachable!... for now...
if (directresponse_count >= 4)
{
if ((realtime - okaytimestamp) > 60)
{
Con_Printf(CON_ERROR"WARNING: 'sv_public %s' is ineffective, this server appears unreachable due to NAT/Firewall issues\n", sv_public.string);
okaytimestamp = realtime;
directresponse_count = 0;
}
}
else
okaytimestamp = realtime;
}
static void QDECL Net_Masterlist_Callback(struct cvar_s *var, char *oldvalue) static void QDECL Net_Masterlist_Callback(struct cvar_s *var, char *oldvalue)
{ {
@ -238,7 +278,7 @@ static void QDECL Net_Masterlist_Callback(struct cvar_s *var, char *oldvalue)
net_masterlist[i].needsresolve = true; net_masterlist[i].needsresolve = true;
} }
void SV_Master_SingleHeartbeat(net_masterlist_t *master) static void SV_Master_SingleHeartbeat(net_masterlist_t *master)
{ {
char string[2048]; char string[2048];
qboolean madeqwstring = false; qboolean madeqwstring = false;
@ -286,7 +326,7 @@ void SV_Master_SingleHeartbeat(net_masterlist_t *master)
case MP_QUAKE2: case MP_QUAKE2:
if (svs.gametype == GT_QUAKE2 && sv_listen_qw.value && na->type == NA_IP) //sv_listen==sv_listen_qw, yes, weird. if (svs.gametype == GT_QUAKE2 && sv_listen_qw.value && na->type == NA_IP) //sv_listen==sv_listen_qw, yes, weird.
{ {
char *str = "\377\377\377\377heartbeat\n%s\n%s"; char *str = "\377\377\377\377""heartbeat\n%s\n%s";
char info[8192]; char info[8192];
char q2users[8192]; char q2users[8192];
size_t i; size_t i;
@ -314,7 +354,7 @@ void SV_Master_SingleHeartbeat(net_masterlist_t *master)
{ {
//darkplaces here refers to the master server protocol, rather than the game protocol //darkplaces here refers to the master server protocol, rather than the game protocol
//(specifies that the server responds to infoRequest packets from the master) //(specifies that the server responds to infoRequest packets from the master)
char *str = "\377\377\377\377heartbeat DarkPlaces\x0A"; char *str = "\377\377\377\377""heartbeat DarkPlaces\n";
e = NET_SendPacket (svs.sockets, strlen(str), str, na); e = NET_SendPacket (svs.sockets, strlen(str), str, na);
} }
break; break;
@ -374,10 +414,10 @@ struct thr_res
netadr_t na[8]; netadr_t na[8];
char str[1]; //trailing char str[1]; //trailing
}; };
void SV_Master_Worker_Resolved(void *ctx, void *data, size_t a, size_t b) static void SV_Master_Worker_Resolved(void *ctx, void *data, size_t a, size_t b)
{ {
char adr[256]; char adr[256];
int i; int i, j;
struct thr_res *work = data; struct thr_res *work = data;
netadr_t *na; netadr_t *na;
net_masterlist_t *master = &net_masterlist[a]; net_masterlist_t *master = &net_masterlist[a];
@ -411,6 +451,17 @@ void SV_Master_Worker_Resolved(void *ctx, void *data, size_t a, size_t b)
na->type = NA_INVALID; na->type = NA_INVALID;
break; //protocol break; //protocol
} }
if (na->type != NA_INVALID)
{
for (j = 0; j < i; j++)
{
if (NET_CompareAdr(&master->adr[j], na))
{ //a dupe of a previous one...
na->type = NA_INVALID;
break;
}
}
}
if (na->type == NA_INVALID) if (na->type == NA_INVALID)
memset(na, 0, sizeof(*na)); memset(na, 0, sizeof(*na));
@ -470,7 +521,7 @@ void SV_Master_Worker_Resolved(void *ctx, void *data, size_t a, size_t b)
Z_Free(work); Z_Free(work);
} }
//worker thread //worker thread
void SV_Master_Worker_Resolve(void *ctx, void *data, size_t a, size_t b) static void SV_Master_Worker_Resolve(void *ctx, void *data, size_t a, size_t b)
{ {
char token[1024]; char token[1024];
int found = 0; int found = 0;

View File

@ -434,7 +434,7 @@ static int numparticletypes;
static part_type_t *part_type; static part_type_t *part_type;
static part_type_t *part_run_list; static part_type_t *part_run_list;
static char part_parsenamespace[MAX_QPATH]; extern char part_parsenamespace[MAX_QPATH];
static qboolean part_parseweak; static qboolean part_parseweak;
static struct { static struct {
@ -3305,19 +3305,19 @@ static void P_ImportEffectInfo(char *config, char *line)
} }
#if 1 #if 1
else if (!strcmp(arg[0], "staincolor") && args == 3) //stainmaps multiplier else if (!strcmp(arg[0], "staincolor") && args == 3) //stainmaps multiplier
Con_ThrottlePrintf(&printtimer, 1, "Particle effect token %s not supported\n", arg[0]); Con_ThrottlePrintf(&printtimer, 1, "%s.%s: Particle effect token %s not supported\n", ptype->config?ptype->config:"<NONE>", ptype->name,arg[0]);
else if (!strcmp(arg[0], "stainalpha") && args == 3) //affects stainmaps AND stain-decals. else if (!strcmp(arg[0], "stainalpha") && args == 3) //affects stainmaps AND stain-decals.
Con_ThrottlePrintf(&printtimer, 1, "Particle effect token %s not supported\n", arg[0]); Con_ThrottlePrintf(&printtimer, 1, "%s.%s: Particle effect token %s not supported\n", ptype->config?ptype->config:"<NONE>", ptype->name,arg[0]);
else if (!strcmp(arg[0], "stainsize") && args == 3) //affects stainmaps AND stain-decals. else if (!strcmp(arg[0], "stainsize") && args == 3) //affects stainmaps AND stain-decals.
Con_ThrottlePrintf(&printtimer, 1, "Particle effect token %s not supported\n", arg[0]); Con_ThrottlePrintf(&printtimer, 1, "%s.%s: Particle effect token %s not supported\n", ptype->config?ptype->config:"<NONE>", ptype->name,arg[0]);
else if (!strcmp(arg[0], "staintex") && args == 3) //actually spawns a decal else if (!strcmp(arg[0], "staintex") && args == 3) //actually spawns a decal
Con_ThrottlePrintf(&printtimer, 1, "Particle effect token %s not supported\n", arg[0]); Con_ThrottlePrintf(&printtimer, 1, "%s.%s: Particle effect token %s not supported\n", ptype->config?ptype->config:"<NONE>", ptype->name,arg[0]);
else if (!strcmp(arg[0], "stainless") && args == 2) else if (!strcmp(arg[0], "stainless") && args == 2)
Con_ThrottlePrintf(&printtimer, 1, "Particle effect token %s not supported\n", arg[0]); Con_ThrottlePrintf(&printtimer, 1, "%s.%s: Particle effect token %s not supported\n", ptype->config?ptype->config:"<NONE>", ptype->name,arg[0]);
else if (!strcmp(arg[0], "relativeoriginoffset") && args == 4) else if (!strcmp(arg[0], "relativeoriginoffset") && args == 4)
Con_ThrottlePrintf(&printtimer, 1, "Particle effect token %s not supported\n", arg[0]); Con_ThrottlePrintf(&printtimer, 1, "%s.%s: Particle effect token %s not supported\n", ptype->config?ptype->config:"<NONE>", ptype->name,arg[0]);
else if (!strcmp(arg[0], "relativevelocityoffset") && args == 4) else if (!strcmp(arg[0], "relativevelocityoffset") && args == 4)
Con_ThrottlePrintf(&printtimer, 1, "Particle effect token %s not supported\n", arg[0]); Con_ThrottlePrintf(&printtimer, 1, "%s.%s: Particle effect token %s not supported\n", ptype->config?ptype->config:"<NONE>", ptype->name, arg[0]);
#endif #endif
else if (!strcmp(arg[0], "rotate") && args == 5) else if (!strcmp(arg[0], "rotate") && args == 5)
{ {
@ -3332,7 +3332,7 @@ static void P_ImportEffectInfo(char *config, char *line)
ptype->rotationstartmin += M_PI/4; ptype->rotationstartmin += M_PI/4;
} }
else else
Con_ThrottlePrintf(&printtimer, 0, "Particle effect token not recognised, or invalid args: %s %s %s %s %s %s\n", arg[0], args<2?"":arg[1], args<3?"":arg[2], args<4?"":arg[3], args<5?"":arg[4], args<6?"":arg[5]); Con_ThrottlePrintf(&printtimer, 0, "%s.%s: Particle effect token not recognised, or invalid args: %s %s %s %s %s %s\n", ptype->config?ptype->config:"<NONE>", ptype->name, arg[0], args<2?"":arg[1], args<3?"":arg[2], args<4?"":arg[3], args<5?"":arg[4], args<6?"":arg[5]);
args = 0; args = 0;
} }

View File

@ -105,6 +105,7 @@ typedef struct {
#define globalfloatdep(name,dep) globalfloat(name) #define globalfloatdep(name,dep) globalfloat(name)
#define globalfloat(name) float *name; #define globalfloat(name) float *name;
#define globalint(name) int *name; #define globalint(name) int *name;
#define globaluint(name) unsigned int *name;
#define globalvector(name) float *name; #define globalvector(name) float *name;
#define globalentity(name) int *name; #define globalentity(name) int *name;
#define globalstring(name) string_t *name; #define globalstring(name) string_t *name;
@ -115,6 +116,7 @@ typedef struct {
#undef globalfloat #undef globalfloat
#undef globalint #undef globalint
#undef globaluint
#undef globalvector #undef globalvector
#undef globalentity #undef globalentity
#undef globalstring #undef globalstring
@ -204,6 +206,7 @@ static void CSQC_FindGlobals(qboolean nofuncs)
static vec3_t defaultgravity = {0, 0, -1}; static vec3_t defaultgravity = {0, 0, -1};
#define globalfloat(name) csqcg.name = (float*)PR_FindGlobal(csqcprogs, #name, 0, NULL); #define globalfloat(name) csqcg.name = (float*)PR_FindGlobal(csqcprogs, #name, 0, NULL);
#define globalint(name) csqcg.name = (int*)PR_FindGlobal(csqcprogs, #name, 0, NULL); #define globalint(name) csqcg.name = (int*)PR_FindGlobal(csqcprogs, #name, 0, NULL);
#define globaluint(name) csqcg.name = (unsigned int*)PR_FindGlobal(csqcprogs, #name, 0, NULL);
#define globalvector(name) csqcg.name = (float*)PR_FindGlobal(csqcprogs, #name, 0, NULL); #define globalvector(name) csqcg.name = (float*)PR_FindGlobal(csqcprogs, #name, 0, NULL);
#define globalentity(name) csqcg.name = (int*)PR_FindGlobal(csqcprogs, #name, 0, NULL); #define globalentity(name) csqcg.name = (int*)PR_FindGlobal(csqcprogs, #name, 0, NULL);
#define globalstring(name) csqcg.name = (string_t*)PR_FindGlobal(csqcprogs, #name, 0, NULL); #define globalstring(name) csqcg.name = (string_t*)PR_FindGlobal(csqcprogs, #name, 0, NULL);
@ -213,6 +216,7 @@ static void CSQC_FindGlobals(qboolean nofuncs)
#undef globalfloat #undef globalfloat
#undef globalint #undef globalint
#undef globaluint
#undef globalvector #undef globalvector
#undef globalentity #undef globalentity
#undef globalstring #undef globalstring
@ -237,8 +241,12 @@ static void CSQC_FindGlobals(qboolean nofuncs)
csqcg.pmove_org = NULL; //can't make aimbots if you don't know where you're aiming from. csqcg.pmove_org = NULL; //can't make aimbots if you don't know where you're aiming from.
csqcg.pmove_vel = NULL; //no dead reckoning please csqcg.pmove_vel = NULL; //no dead reckoning please
csqcg.pmove_mins = csqcg.pmove_maxs = csqcg.pmove_jump_held = csqcg.pmove_waterjumptime = csqcg.pmove_onground = NULL; //I just want to kill theses csqcg.pmove_mins = csqcg.pmove_maxs = csqcg.pmove_jump_held = csqcg.pmove_waterjumptime = csqcg.pmove_onground = NULL; //I just want to kill theses
csqcg.input_angles = csqcg.input_movevalues = csqcg.input_buttons = csqcg.input_impulse = csqcg.input_lightlevel = csqcg.input_weapon = csqcg.input_servertime = NULL; csqcg.input_angles = csqcg.input_movevalues = csqcg.input_buttons = csqcg.input_impulse = csqcg.input_lightlevel = csqcg.input_servertime = NULL;
csqcg.input_weapon = NULL;
csqcg.input_clienttime = csqcg.input_cursor_screen = csqcg.input_cursor_trace_start = csqcg.input_cursor_trace_endpos = csqcg.input_cursor_entitynumber = NULL; csqcg.input_clienttime = csqcg.input_cursor_screen = csqcg.input_cursor_trace_start = csqcg.input_cursor_trace_endpos = csqcg.input_cursor_entitynumber = NULL;
csqcg.input_head_status = csqcg.input_left_status = csqcg.input_right_status = NULL;
csqcg.input_head_angles = csqcg.input_left_angles = csqcg.input_right_angles = NULL;
csqcg.input_head_origin = csqcg.input_left_origin = csqcg.input_right_origin = NULL;
} }
else if (csqcg.CSQC_UpdateView || csqcg.CSQC_UpdateViewLoading) else if (csqcg.CSQC_UpdateView || csqcg.CSQC_UpdateViewLoading)
{ //full csqc AND simplecsqc's entry points at the same time are a bad idea that just result in confusion. { //full csqc AND simplecsqc's entry points at the same time are a bad idea that just result in confusion.
@ -1218,6 +1226,15 @@ static void QCBUILTIN PF_R_DynamicLight_Set(pubprogfuncs_t *prinst, struct globa
case lfield_radiusdecay: case lfield_radiusdecay:
l->decay = G_FLOAT(OFS_PARM2); l->decay = G_FLOAT(OFS_PARM2);
break; break;
case lfield_owner:
{
csqcedict_t *ed = (csqcedict_t*)G_EDICT(prinst, OFS_PARM2);
if (ed->xv->entnum > 0)
l->key = ed->xv->entnum; //attach it to the indicated ssqc ent.
else
l->key = -ed->entnum; //use the csqc index for it.
}
break;
default: default:
break; break;
} }
@ -1304,6 +1321,15 @@ static void QCBUILTIN PF_R_DynamicLight_Get(pubprogfuncs_t *prinst, struct globa
case lfield_radiusdecay: case lfield_radiusdecay:
G_FLOAT(OFS_RETURN) = l->decay; G_FLOAT(OFS_RETURN) = l->decay;
break; break;
case lfield_owner:
if (l->key < 0 && -l->key < prinst->edicttable_length && prinst->edicttable[-l->key]) //csqc ent
RETURN_EDICT(prinst, prinst->edicttable[-l->key]);
else if (l->key > 0 && l->key < maxcsqcentities && csqcent[l->key]) //ssqc ent
RETURN_EDICT(prinst, csqcent[l->key]);
else
RETURN_EDICT(prinst, prinst->edicttable[0]); //probably an ssqc ent not known to the csqc, so we can't report this info.
break;
default: default:
G_INT(OFS_RETURN) = 0; G_INT(OFS_RETURN) = 0;
break; break;
@ -1833,7 +1859,7 @@ void QCBUILTIN PF_R_AddTrisoup_Simple(pubprogfuncs_t *prinst, struct globalvars_
unsigned int numindexes = G_INT(OFS_PARM4); unsigned int numindexes = G_INT(OFS_PARM4);
qboolean twod = qcflags & DRAWFLAG_2D; qboolean twod = qcflags & DRAWFLAG_2D;
unsigned int beflags; unsigned int beflags;
unsigned int numverts; unsigned int maxverts;
const qcvertex_t *fte_restrict vert; const qcvertex_t *fte_restrict vert;
const unsigned int *fte_restrict idx; const unsigned int *fte_restrict idx;
unsigned int i, j, first; unsigned int i, j, first;
@ -1860,8 +1886,8 @@ void QCBUILTIN PF_R_AddTrisoup_Simple(pubprogfuncs_t *prinst, struct globalvars_
} }
//validates the pointer. //validates the pointer.
numverts = (prinst->stringtablesize - vertsptr) / sizeof(qcvertex_t); maxverts = (prinst->stringtablesize - vertsptr) / sizeof(qcvertex_t);
if (numverts < 1 || vertsptr <= 0 || vertsptr+numverts*sizeof(qcvertex_t) > prinst->stringtablesize) if (maxverts < 1 || vertsptr <= 0 || vertsptr+maxverts*sizeof(qcvertex_t) > prinst->stringtablesize)
{ {
PR_BIError(prinst, "PF_R_AddTrisoup: invalid vertexes pointer\n"); PR_BIError(prinst, "PF_R_AddTrisoup: invalid vertexes pointer\n");
return; return;
@ -1886,6 +1912,8 @@ void QCBUILTIN PF_R_AddTrisoup_Simple(pubprogfuncs_t *prinst, struct globalvars_
{ {
R2D_Flush(); R2D_Flush();
first = 0; first = 0;
csqc_poly_origvert = cl_numstrisvert;
csqc_poly_origidx = cl_numstrisidx;
} }
} }
@ -1906,7 +1934,7 @@ void QCBUILTIN PF_R_AddTrisoup_Simple(pubprogfuncs_t *prinst, struct globalvars_
for (i = 0; i < numindexes; i++) for (i = 0; i < numindexes; i++)
{ {
j = *idx++; j = *idx++;
if (j >= numverts) if (j >= maxverts)
j = 0; //out of bounds. j = 0; //out of bounds.
VectorCopy(vert[j].xyz, cl_strisvertv[cl_numstrisvert]); VectorCopy(vert[j].xyz, cl_strisvertv[cl_numstrisvert]);
@ -3026,6 +3054,23 @@ static void QCBUILTIN PF_cs_pointcontents(pubprogfuncs_t *prinst, struct globalv
else else
G_FLOAT(OFS_RETURN) = Q1CONTENTS_EMPTY; G_FLOAT(OFS_RETURN) = Q1CONTENTS_EMPTY;
} }
static void QCBUILTIN PF_cs_pointcontentsmask(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
world_t *w = prinst->parms->user;
float *v;
int cont;
v = G_VECTOR(OFS_PARM0);
if (!w->worldmodel || w->worldmodel->loadstate != MLS_LOADED)
cont = FTECONTENTS_EMPTY;
else if (prinst->callargc < 1 || G_FLOAT(OFS_PARM1))
cont = World_PointContentsWorldOnly(w, v);
else
cont = World_PointContentsAllBSPs(w, v);
G_UINT(OFS_RETURN) = cont;
}
static model_t *csqc_setmodel(pubprogfuncs_t *prinst, csqcedict_t *ent, int modelindex) static model_t *csqc_setmodel(pubprogfuncs_t *prinst, csqcedict_t *ent, int modelindex)
{ {
@ -3791,6 +3836,64 @@ static void cs_set_input_state (usercmd_t *cmd)
VectorCopy(cmd->cursor_impact, csqcg.input_cursor_trace_endpos); VectorCopy(cmd->cursor_impact, csqcg.input_cursor_trace_endpos);
if (csqcg.input_cursor_entitynumber) if (csqcg.input_cursor_entitynumber)
*csqcg.input_cursor_entitynumber = cmd->cursor_entitynumber; *csqcg.input_cursor_entitynumber = cmd->cursor_entitynumber;
if (csqcg.input_head_status)
*csqcg.input_head_status = cmd->vr[VRDEV_HEAD].status;
if (csqcg.input_head_origin)
VectorCopy(cmd->vr[VRDEV_HEAD].origin, csqcg.input_head_origin);
if (csqcg.input_head_velocity)
VectorCopy(cmd->vr[VRDEV_HEAD].velocity, csqcg.input_head_velocity);
if (csqcg.input_head_angles)
{
csqcg.input_head_angles[0] = SHORT2ANGLE(cmd->vr[VRDEV_HEAD].angles[0]);
csqcg.input_head_angles[1] = SHORT2ANGLE(cmd->vr[VRDEV_HEAD].angles[1]);
csqcg.input_head_angles[2] = SHORT2ANGLE(cmd->vr[VRDEV_HEAD].angles[2]);
}
if (csqcg.input_head_avelocity)
{
csqcg.input_head_avelocity[0] = SHORT2ANGLE(cmd->vr[VRDEV_HEAD].avelocity[0]);
csqcg.input_head_avelocity[1] = SHORT2ANGLE(cmd->vr[VRDEV_HEAD].avelocity[1]);
csqcg.input_head_avelocity[2] = SHORT2ANGLE(cmd->vr[VRDEV_HEAD].avelocity[2]);
}
if (csqcg.input_left_status)
*csqcg.input_left_status = cmd->vr[VRDEV_LEFT].status;
if (csqcg.input_left_origin)
VectorCopy(cmd->vr[VRDEV_LEFT].origin, csqcg.input_left_origin);
if (csqcg.input_left_velocity)
VectorCopy(cmd->vr[VRDEV_LEFT].velocity, csqcg.input_left_velocity);
if (csqcg.input_left_angles)
{
csqcg.input_left_angles[0] = SHORT2ANGLE(cmd->vr[VRDEV_LEFT].angles[0]);
csqcg.input_left_angles[1] = SHORT2ANGLE(cmd->vr[VRDEV_LEFT].angles[1]);
csqcg.input_left_angles[2] = SHORT2ANGLE(cmd->vr[VRDEV_LEFT].angles[2]);
}
if (csqcg.input_left_avelocity)
{
csqcg.input_left_avelocity[0] = SHORT2ANGLE(cmd->vr[VRDEV_LEFT].avelocity[0]);
csqcg.input_left_avelocity[1] = SHORT2ANGLE(cmd->vr[VRDEV_LEFT].avelocity[1]);
csqcg.input_left_avelocity[2] = SHORT2ANGLE(cmd->vr[VRDEV_LEFT].avelocity[2]);
}
if (csqcg.input_right_status)
*csqcg.input_right_status = cmd->vr[VRDEV_RIGHT].status;
if (csqcg.input_right_origin)
VectorCopy(cmd->vr[VRDEV_RIGHT].origin, csqcg.input_right_origin);
if (csqcg.input_right_velocity)
VectorCopy(cmd->vr[VRDEV_RIGHT].velocity, csqcg.input_right_velocity);
if (csqcg.input_right_angles)
{
csqcg.input_right_angles[0] = SHORT2ANGLE(cmd->vr[VRDEV_RIGHT].angles[0]);
csqcg.input_right_angles[1] = SHORT2ANGLE(cmd->vr[VRDEV_RIGHT].angles[1]);
csqcg.input_right_angles[2] = SHORT2ANGLE(cmd->vr[VRDEV_RIGHT].angles[2]);
}
if (csqcg.input_right_avelocity)
{
csqcg.input_right_avelocity[0] = SHORT2ANGLE(cmd->vr[VRDEV_RIGHT].avelocity[0]);
csqcg.input_right_avelocity[1] = SHORT2ANGLE(cmd->vr[VRDEV_RIGHT].avelocity[1]);
csqcg.input_right_avelocity[2] = SHORT2ANGLE(cmd->vr[VRDEV_RIGHT].avelocity[2]);
}
} }
static void cs_get_input_state (usercmd_t *cmd) static void cs_get_input_state (usercmd_t *cmd)
@ -3829,6 +3932,63 @@ static void cs_get_input_state (usercmd_t *cmd)
VectorCopy(csqcg.input_cursor_trace_endpos, cmd->cursor_impact); VectorCopy(csqcg.input_cursor_trace_endpos, cmd->cursor_impact);
if (csqcg.input_cursor_entitynumber) if (csqcg.input_cursor_entitynumber)
cmd->cursor_entitynumber = *csqcg.input_cursor_entitynumber; cmd->cursor_entitynumber = *csqcg.input_cursor_entitynumber;
if (csqcg.input_head_status)
cmd->vr[VRDEV_HEAD].status = *csqcg.input_head_status;
if (csqcg.input_head_origin)
VectorCopy(csqcg.input_head_origin, cmd->vr[VRDEV_HEAD].origin);
if (csqcg.input_head_velocity)
VectorCopy(csqcg.input_head_velocity, cmd->vr[VRDEV_HEAD].velocity);
if (csqcg.input_head_angles)
{
cmd->vr[VRDEV_HEAD].angles[0] = ANGLE2SHORT(csqcg.input_head_angles[0]);
cmd->vr[VRDEV_HEAD].angles[1] = ANGLE2SHORT(csqcg.input_head_angles[1]);
cmd->vr[VRDEV_HEAD].angles[2] = ANGLE2SHORT(csqcg.input_head_angles[2]);
}
if (csqcg.input_head_avelocity)
{
cmd->vr[VRDEV_HEAD].avelocity[0] = ANGLE2SHORT(csqcg.input_head_avelocity[0]);
cmd->vr[VRDEV_HEAD].avelocity[1] = ANGLE2SHORT(csqcg.input_head_avelocity[1]);
cmd->vr[VRDEV_HEAD].avelocity[2] = ANGLE2SHORT(csqcg.input_head_avelocity[2]);
}
if (csqcg.input_left_status)
cmd->vr[VRDEV_LEFT].status = *csqcg.input_left_status;
if (csqcg.input_left_origin)
VectorCopy(csqcg.input_left_origin, cmd->vr[VRDEV_LEFT].origin);
if (csqcg.input_left_velocity)
VectorCopy(csqcg.input_left_velocity, cmd->vr[VRDEV_LEFT].velocity);
if (csqcg.input_left_angles)
{
cmd->vr[VRDEV_LEFT].angles[0] = ANGLE2SHORT(csqcg.input_left_angles[0]);
cmd->vr[VRDEV_LEFT].angles[1] = ANGLE2SHORT(csqcg.input_left_angles[1]);
cmd->vr[VRDEV_LEFT].angles[2] = ANGLE2SHORT(csqcg.input_left_angles[2]);
}
if (csqcg.input_left_avelocity)
{
cmd->vr[VRDEV_LEFT].avelocity[0] = ANGLE2SHORT(csqcg.input_left_avelocity[0]);
cmd->vr[VRDEV_LEFT].avelocity[1] = ANGLE2SHORT(csqcg.input_left_avelocity[1]);
cmd->vr[VRDEV_LEFT].avelocity[2] = ANGLE2SHORT(csqcg.input_left_avelocity[2]);
}
if (csqcg.input_right_status)
cmd->vr[VRDEV_RIGHT].status = *csqcg.input_right_status;
if (csqcg.input_right_origin)
VectorCopy(csqcg.input_right_origin, cmd->vr[VRDEV_RIGHT].origin);
if (csqcg.input_right_velocity)
VectorCopy(csqcg.input_right_velocity, cmd->vr[VRDEV_RIGHT].velocity);
if (csqcg.input_right_angles)
{
cmd->vr[VRDEV_RIGHT].angles[0] = ANGLE2SHORT(csqcg.input_right_angles[0]);
cmd->vr[VRDEV_RIGHT].angles[1] = ANGLE2SHORT(csqcg.input_right_angles[1]);
cmd->vr[VRDEV_RIGHT].angles[2] = ANGLE2SHORT(csqcg.input_right_angles[2]);
}
if (csqcg.input_right_avelocity)
{
cmd->vr[VRDEV_RIGHT].avelocity[0] = ANGLE2SHORT(csqcg.input_right_avelocity[0]);
cmd->vr[VRDEV_RIGHT].avelocity[1] = ANGLE2SHORT(csqcg.input_right_avelocity[1]);
cmd->vr[VRDEV_RIGHT].avelocity[2] = ANGLE2SHORT(csqcg.input_right_avelocity[2]);
}
} }
//sets implicit pause (only works when singleplayer) //sets implicit pause (only works when singleplayer)
@ -4492,13 +4652,15 @@ static void QCBUILTIN PF_checkextension (pubprogfuncs_t *prinst, struct globalva
if (!QSG_Extensions[i].name) if (!QSG_Extensions[i].name)
continue; continue;
if (i < 32 && cls.protocol == CP_QUAKEWORLD)
if (!(cls.fteprotocolextensions & (1<<i)))
continue;
if (!strcmp(QSG_Extensions[i].name, extname)) if (!strcmp(QSG_Extensions[i].name, extname))
{ {
G_FLOAT(OFS_RETURN) = true; if (QSG_Extensions[i].extensioncheck)
{
extcheck_t ctx = {cls.fteprotocolextensions, cls.fteprotocolextensions2};
G_FLOAT(OFS_RETURN) = QSG_Extensions[i].extensioncheck(&ctx);
}
else
G_FLOAT(OFS_RETURN) = true;
return; return;
} }
} }
@ -6136,15 +6298,25 @@ static void QCBUILTIN PF_cs_getplayerstat(pubprogfuncs_t *prinst, struct globalv
break; break;
case ev_integer: case ev_integer:
case ev_uint:
case ev_field: //Hopefully NOT useful, certainly not reliable case ev_field: //Hopefully NOT useful, certainly not reliable
case ev_function: //Hopefully NOT useful case ev_function: //Hopefully NOT useful
case ev_pointer: //NOT useful in a networked capacity. case ev_pointer: //NOT useful in a networked capacity.
G_INT(OFS_RETURN) = cl.players[playernum].stats[statnum]; G_INT(OFS_RETURN) = cl.players[playernum].stats[statnum];
break; break;
case ev_int64: //lamely takes two consecutive stats.
case ev_uint64:
G_UINT64(OFS_RETURN) = (puint64_t)((statnum+0 >= MAX_CL_STATS)?0:cl.players[playernum].stats[statnum+0]) |
((puint64_t)((statnum+1 >= MAX_CL_STATS)?0:cl.players[playernum].stats[statnum+1]) <<32);
break;
case ev_float: case ev_float:
G_FLOAT(OFS_RETURN) = cl.players[playernum].statsf[statnum]; G_FLOAT(OFS_RETURN) = cl.players[playernum].statsf[statnum];
break; break;
case ev_double: //lame truncation for network.
G_DOUBLE(OFS_RETURN) = cl.players[playernum].statsf[statnum];
break;
case ev_vector: case ev_vector:
G_FLOAT(OFS_RETURN+0) = (statnum+0 >= MAX_CL_STATS)?0:cl.players[playernum].statsf[statnum+0]; G_FLOAT(OFS_RETURN+0) = (statnum+0 >= MAX_CL_STATS)?0:cl.players[playernum].statsf[statnum+0];
G_FLOAT(OFS_RETURN+1) = (statnum+1 >= MAX_CL_STATS)?0:cl.players[playernum].statsf[statnum+1]; G_FLOAT(OFS_RETURN+1) = (statnum+1 >= MAX_CL_STATS)?0:cl.players[playernum].statsf[statnum+1];
@ -6573,7 +6745,7 @@ static struct {
{"setmodel", PF_cs_SetModel, 3}, // #3 void(entity e, string modl) setmodel (QUAKE) {"setmodel", PF_cs_SetModel, 3}, // #3 void(entity e, string modl) setmodel (QUAKE)
{"setsize", PF_cs_SetSize, 4}, // #4 void(entity e, vector mins, vector maxs) setsize (QUAKE) {"setsize", PF_cs_SetSize, 4}, // #4 void(entity e, vector mins, vector maxs) setsize (QUAKE)
//5 //5
{"debugbreak", PF_cs_break, 6}, // #6 void() debugbreak (QUAKE) {"breakpoint", PF_cs_break, 6}, // #6 void() debugbreak (QUAKE)
{"random", PF_random, 7}, // #7 float() random (QUAKE) {"random", PF_random, 7}, // #7 float() random (QUAKE)
{"sound", PF_cs_sound, 8}, // #8 void(entity e, float chan, string samp, float vol, float atten) sound (QUAKE) {"sound", PF_cs_sound, 8}, // #8 void(entity e, float chan, string samp, float vol, float atten) sound (QUAKE)
{"normalize", PF_normalize, 9}, // #9 vector(vector in) normalize (QUAKE) {"normalize", PF_normalize, 9}, // #9 vector(vector in) normalize (QUAKE)
@ -6618,6 +6790,7 @@ static struct {
//40 //40
{"checkbottom", PF_checkbottom, 40}, // #40 float(entity e) checkbottom (QUAKE) {"checkbottom", PF_checkbottom, 40}, // #40 float(entity e) checkbottom (QUAKE)
{"pointcontents", PF_cs_pointcontents, 41}, // #41 float(vector org) pointcontents (QUAKE) {"pointcontents", PF_cs_pointcontents, 41}, // #41 float(vector org) pointcontents (QUAKE)
{"pointcontentsmask", PF_cs_pointcontentsmask, 0}, // #41 float(vector org) pointcontents (QUAKE)
// {"?", PF_Fixme, 42}, // #42 // {"?", PF_Fixme, 42}, // #42
{"fabs", PF_fabs, 43}, // #43 float(float f) fabs (QUAKE) {"fabs", PF_fabs, 43}, // #43 float(float f) fabs (QUAKE)
{"aim", PF_NoCSQC, 44}, // #44 vector(entity e, float speed) aim (QUAKE) (don't support) {"aim", PF_NoCSQC, 44}, // #44 vector(entity e, float speed) aim (QUAKE) (don't support)
@ -7595,7 +7768,7 @@ static qboolean CSQC_ValidateMainCSProgs(void *file, size_t filesize, unsigned i
return false; return false;
if (cls.protocol == CP_NETQUAKE && !(cls.fteprotocolextensions2 & PEXT2_PREDINFO)) if (cls.protocol == CP_NETQUAKE && !(cls.fteprotocolextensions2 & PEXT2_PREDINFO))
{ //DP uses really lame checksums. { //DP uses really lame checksums.
if (QCRC_Block(file, filesize) != checksum) if (CalcHashInt(&hash_crc16, file, filesize) != checksum)
return false; return false;
} }
else else
@ -8265,7 +8438,7 @@ void PR_CSExtensionList_f(void)
int i; int i;
int ebi; int ebi;
int bi; int bi;
lh_extension_t *extlist; qc_extension_t *extlist;
#define SHOW_ACTIVEEXT 1 #define SHOW_ACTIVEEXT 1
#define SHOW_ACTIVEBI 2 #define SHOW_ACTIVEBI 2

View File

@ -3275,9 +3275,6 @@ void MP_RegisterCvarsAndCmds(void)
Cvar_Register(&forceqmenu, MENUPROGSGROUP); Cvar_Register(&forceqmenu, MENUPROGSGROUP);
Cvar_Register(&pr_menu_coreonerror, MENUPROGSGROUP); Cvar_Register(&pr_menu_coreonerror, MENUPROGSGROUP);
Cvar_Register(&pr_menu_memsize, MENUPROGSGROUP); Cvar_Register(&pr_menu_memsize, MENUPROGSGROUP);
if (COM_CheckParm("-qmenu"))
Cvar_Set(&forceqmenu, "1");
} }
qboolean MP_UsingGamecodeLoadingScreen(void) qboolean MP_UsingGamecodeLoadingScreen(void)

View File

@ -191,7 +191,6 @@ extern "C" {
#include "keys.h" #include "keys.h"
#include "view.h" #include "view.h"
#include "menu.h" #include "menu.h"
#include "../common/crc.h"
#include "cdaudio.h" #include "cdaudio.h"
#include "../common/pmove.h" #include "../common/pmove.h"
@ -320,7 +319,6 @@ extern quakeparms_t host_parms;
extern cvar_t fs_gamename; extern cvar_t fs_gamename;
#ifdef PACKAGEMANAGER #ifdef PACKAGEMANAGER
extern cvar_t pkg_downloads_url;
extern cvar_t pkg_autoupdate; extern cvar_t pkg_autoupdate;
#endif #endif
extern cvar_t com_protocolname; extern cvar_t com_protocolname;

View File

@ -304,6 +304,7 @@ void R2D_Init(void)
"rgbgen vertex\n" "rgbgen vertex\n"
"alphagen vertex\n" "alphagen vertex\n"
"blendfunc blend\n" "blendfunc blend\n"
"maskalpha\n"
"}\n" "}\n"
"}\n"); "}\n");
shader_contrastup = R_RegisterShader("contrastupshader", SUF_NONE, shader_contrastup = R_RegisterShader("contrastupshader", SUF_NONE,
@ -315,6 +316,7 @@ void R2D_Init(void)
"blendfunc gl_dst_color gl_one\n" "blendfunc gl_dst_color gl_one\n"
"rgbgen vertex\n" "rgbgen vertex\n"
"alphagen vertex\n" "alphagen vertex\n"
"maskalpha\n"
"}\n" "}\n"
"}\n" "}\n"
); );
@ -327,6 +329,7 @@ void R2D_Init(void)
"blendfunc gl_dst_color gl_zero\n" "blendfunc gl_dst_color gl_zero\n"
"rgbgen vertex\n" "rgbgen vertex\n"
"alphagen vertex\n" "alphagen vertex\n"
"maskalpha\n"
"}\n" "}\n"
"}\n" "}\n"
); );
@ -339,6 +342,7 @@ void R2D_Init(void)
"blendfunc gl_one gl_one\n" "blendfunc gl_one gl_one\n"
"rgbgen vertex\n" "rgbgen vertex\n"
"alphagen vertex\n" "alphagen vertex\n"
"maskalpha\n"
"}\n" "}\n"
"}\n" "}\n"
); );
@ -349,6 +353,7 @@ void R2D_Init(void)
"{\n" "{\n"
"map $currentrender\n" "map $currentrender\n"
"nodepthtest\n" "nodepthtest\n"
"maskalpha\n"
"}\n" "}\n"
"}\n" "}\n"
); );
@ -360,6 +365,7 @@ void R2D_Init(void)
"blendfunc gl_src_alpha gl_one_minus_src_alpha\n" "blendfunc gl_src_alpha gl_one_minus_src_alpha\n"
"rgbgen vertex\n" "rgbgen vertex\n"
"alphagen vertex\n" "alphagen vertex\n"
"maskalpha\n"
"}\n" "}\n"
"}\n" "}\n"
); );

View File

@ -624,6 +624,7 @@ cvar_t r_part_contentswitch = CVARFD("r_part_contentswitch", "1", CVAR_ARCHIVE,
cvar_t r_part_density = CVARF("r_part_density", "1", CVAR_ARCHIVE); cvar_t r_part_density = CVARF("r_part_density", "1", CVAR_ARCHIVE);
cvar_t r_part_classic_expgrav = CVARFD("r_part_classic_expgrav", "10", CVAR_ARCHIVE, "Scaler for how fast classic explosion particles should accelerate due to gravity. 1 for like vanilla, 10 for like zquake."); cvar_t r_part_classic_expgrav = CVARFD("r_part_classic_expgrav", "10", CVAR_ARCHIVE, "Scaler for how fast classic explosion particles should accelerate due to gravity. 1 for like vanilla, 10 for like zquake.");
cvar_t r_part_classic_opaque = CVARFD("r_part_classic_opaque", "0", CVAR_ARCHIVE, "Disables transparency on classic particles, for the oldskool look."); cvar_t r_part_classic_opaque = CVARFD("r_part_classic_opaque", "0", CVAR_ARCHIVE, "Disables transparency on classic particles, for the oldskool look.");
cvar_t r_part_classic_square = CVARFD("r_part_classic_square", "0", CVAR_ARCHIVE, "Enables square particles, for the oldskool look.");
cvar_t r_part_maxparticles = CVAR("r_part_maxparticles", "65536"); cvar_t r_part_maxparticles = CVAR("r_part_maxparticles", "65536");
cvar_t r_part_maxdecals = CVAR("r_part_maxdecals", "8192"); cvar_t r_part_maxdecals = CVAR("r_part_maxdecals", "8192");
@ -669,6 +670,7 @@ void P_InitParticleSystem(void)
Cvar_Register(&r_part_density, particlecvargroupname); Cvar_Register(&r_part_density, particlecvargroupname);
Cvar_Register(&r_part_classic_expgrav, particlecvargroupname); Cvar_Register(&r_part_classic_expgrav, particlecvargroupname);
Cvar_Register(&r_part_classic_opaque, particlecvargroupname); Cvar_Register(&r_part_classic_opaque, particlecvargroupname);
Cvar_Register(&r_part_classic_square, particlecvargroupname);
Cvar_Register (&gl_part_flame, particlecvargroupname); Cvar_Register (&gl_part_flame, particlecvargroupname);

View File

@ -1348,7 +1348,7 @@ R_BuildLightMap
Combine and scale multiple lightmaps into the 8.8 format in blocklights Combine and scale multiple lightmaps into the 8.8 format in blocklights
=============== ===============
*/ */
static void Surf_BuildLightMap (model_t *currentmodel, msurface_t *surf, int map, int shift, int ambient, int *d_lightstylevalue) static void Surf_BuildLightMap (model_t *model, msurface_t *surf, int map, int shift, int ambient, int *d_lightstylevalue)
{ {
int smax = (surf->extents[0]>>surf->lmshift)+1; int smax = (surf->extents[0]>>surf->lmshift)+1;
int tmax = (surf->extents[1]>>surf->lmshift)+1; int tmax = (surf->extents[1]>>surf->lmshift)+1;
@ -1398,7 +1398,7 @@ static void Surf_BuildLightMap (model_t *currentmodel, msurface_t *surf, int map
stainsrc = lm->stainmaps + (surf->light_t[map] * lm->width + surf->light_s[map]) * 3; stainsrc = lm->stainmaps + (surf->light_t[map] * lm->width + surf->light_s[map]) * 3;
lm->modified = true; lm->modified = true;
if (lm->hasdeluxe && currentmodel->deluxdata) if (lm->hasdeluxe && model->deluxdata)
{ {
lightmapinfo_t *dlm = lightmap[surf->lightmaptexturenums[map]+1]; lightmapinfo_t *dlm = lightmap[surf->lightmaptexturenums[map]+1];
dlm->modified = true; dlm->modified = true;
@ -1414,7 +1414,7 @@ static void Surf_BuildLightMap (model_t *currentmodel, msurface_t *surf, int map
deluxedest = dlm->lightmaps + (surf->light_t[map] * dlm->width + surf->light_s[map]) * dlm->pixbytes; deluxedest = dlm->lightmaps + (surf->light_t[map] * dlm->width + surf->light_s[map]) * dlm->pixbytes;
Surf_BuildDeluxMap(currentmodel, surf, deluxedest, dlm, blocknormals); Surf_BuildDeluxMap(model, surf, deluxedest, dlm, blocknormals);
} }
if (lm->fmt != PTI_L8) if (lm->fmt != PTI_L8)
@ -1449,7 +1449,7 @@ static void Surf_BuildLightMap (model_t *currentmodel, msurface_t *surf, int map
} }
} }
} }
else if (!currentmodel->lightdata) else if (!model->lightdata)
{ {
/*fullbright if map is not lit. but not overbright*/ /*fullbright if map is not lit. but not overbright*/
for (i=0 ; i<size*3 ; i++) for (i=0 ; i<size*3 ; i++)
@ -1480,9 +1480,9 @@ static void Surf_BuildLightMap (model_t *currentmodel, msurface_t *surf, int map
// add all the lightmaps // add all the lightmaps
if (src) if (src)
{ {
if (currentmodel->fromgame == fg_quake3) if (model->fromgame == fg_quake3)
Sys_Error("Surf_BuildLightMap: q3bsp"); Sys_Error("Surf_BuildLightMap: q3bsp");
switch(currentmodel->lightmaps.fmt) switch(model->lightmaps.fmt)
{ {
case LM_E5BGR9: case LM_E5BGR9:
for (maps = 0 ; maps < MAXCPULIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ; maps++) for (maps = 0 ; maps < MAXCPULIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ; maps++)
@ -1589,7 +1589,7 @@ static void Surf_BuildLightMap (model_t *currentmodel, msurface_t *surf, int map
} }
} }
} }
else if (!currentmodel->lightdata) else if (!model->lightdata)
{ //no scalers here. { //no scalers here.
for (i=0 ; i<size ; i++) for (i=0 ; i<size ; i++)
blocklights[i] = 255*256; blocklights[i] = 255*256;
@ -1613,7 +1613,7 @@ static void Surf_BuildLightMap (model_t *currentmodel, msurface_t *surf, int map
// add all the lightmaps // add all the lightmaps
if (src) if (src)
{ {
switch(currentmodel->lightmaps.fmt) switch(model->lightmaps.fmt)
{ {
case LM_E5BGR9: case LM_E5BGR9:
for (maps = 0 ; maps < MAXCPULIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ; maps++) for (maps = 0 ; maps < MAXCPULIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ; maps++)
@ -2699,7 +2699,7 @@ void Surf_SetupFrame(void)
vec3_t temp, pvsorg; vec3_t temp, pvsorg;
int viewcontents; int viewcontents;
if (!cl.worldmodel || (!cl.worldmodel->nodes && cl.worldmodel->type != mod_heightmap)) if (!cl.worldmodel || cl.worldmodel->loadstate!=MLS_LOADED)
r_refdef.flags |= RDF_NOWORLDMODEL; r_refdef.flags |= RDF_NOWORLDMODEL;
R_AnimateLight(); R_AnimateLight();
@ -3374,7 +3374,7 @@ void Surf_DrawWorld (void)
Surf_LightmapShift(currentmodel); Surf_LightmapShift(currentmodel);
#ifdef THREADEDWORLD #ifdef THREADEDWORLD
if ((r_temporalscenecache.ival || currentmodel->numbatches) && !r_refdef.recurse && currentmodel->type == mod_brush) if ((r_temporalscenecache.ival /*|| currentmodel->numbatches*/) && !r_refdef.recurse && currentmodel->type == mod_brush)
{ {
struct webostate_s *webostate, *best = NULL, *kill, **link; struct webostate_s *webostate, *best = NULL, *kill, **link;
vec_t bestdist = FLT_MAX; vec_t bestdist = FLT_MAX;
@ -3608,16 +3608,13 @@ void Surf_DrawWorld (void)
Surf_PushChains(currentmodel->batches); Surf_PushChains(currentmodel->batches);
#ifdef TERRAIN if (currentmodel->type != mod_brush)
if (currentmodel->type == mod_heightmap)
{ {
frustumvis = NULL; frustumvis = NULL;
entvis = surfvis = NULL; entvis = surfvis = NULL;
} }
else
#endif
#if defined(Q2BSPS) || defined(Q3BSPS) #if defined(Q2BSPS) || defined(Q3BSPS)
if (currentmodel->fromgame == fg_quake2 || currentmodel->fromgame == fg_quake3) else if (currentmodel->fromgame == fg_quake2 || currentmodel->fromgame == fg_quake3)
{ {
pvsbuffer_t *vis = &surf_frustumvis[r_refdef.recurse]; pvsbuffer_t *vis = &surf_frustumvis[r_refdef.recurse];
if (vis->buffersize < currentmodel->pvsbytes) if (vis->buffersize < currentmodel->pvsbytes)
@ -3656,25 +3653,22 @@ void Surf_DrawWorld (void)
surfvis = frustumvis; surfvis = frustumvis;
} }
else
#endif #endif
#ifdef MAP_PROC #ifdef MAP_PROC
if (currentmodel->fromgame == fg_doom3) else if (currentmodel->fromgame == fg_doom3)
{ {
entvis = surfvis = D3_CalcVis(currentmodel, r_origin); entvis = surfvis = D3_CalcVis(currentmodel, r_origin);
} }
else
#endif #endif
#ifdef MAP_DOOM #ifdef MAP_DOOM
if (currentmodel->fromgame == fg_doom) else if (currentmodel->fromgame == fg_doom)
{ {
entvis = surfvis = NULL; entvis = surfvis = NULL;
R_DoomWorld(); R_DoomWorld();
} }
else
#endif #endif
#ifdef Q1BSPS #ifdef Q1BSPS
if (1) else if (1)
{ {
//extern cvar_t temp1; //extern cvar_t temp1;
// if (0)//temp1.value) // if (0)//temp1.value)
@ -3699,8 +3693,8 @@ void Surf_DrawWorld (void)
surfvis = frustumvis; surfvis = frustumvis;
} }
} }
else
#endif #endif
else
{ {
frustumvis = NULL; frustumvis = NULL;
entvis = surfvis = NULL; entvis = surfvis = NULL;
@ -4533,7 +4527,7 @@ TRACE(("dbg: Surf_NewMap: tp\n"));
VectorCopy(mins, cl_static_entities[i].ent.origin); VectorCopy(mins, cl_static_entities[i].ent.origin);
VectorCopy(maxs, cl_static_entities[i].ent.origin); VectorCopy(maxs, cl_static_entities[i].ent.origin);
} }
if (cl.worldmodel->funcs.FindTouchedLeafs) if (cl.worldmodel && cl.worldmodel->loadstate == MLS_LOADED)
cl.worldmodel->funcs.FindTouchedLeafs(cl.worldmodel, &cl_static_entities[i].ent.pvscache, mins, maxs); cl.worldmodel->funcs.FindTouchedLeafs(cl.worldmodel, &cl_static_entities[i].ent.pvscache, mins, maxs);
cl_static_entities[i].emit = NULL; cl_static_entities[i].emit = NULL;
} }

View File

@ -317,6 +317,8 @@ cvar_t vid_renderer_opts = CVARFD ("_vid_renderer_opts", NULL, CVAR_NOSET, "
cvar_t vid_bpp = CVARFD ("vid_bpp", "0", cvar_t vid_bpp = CVARFD ("vid_bpp", "0",
CVAR_ARCHIVE | CVAR_VIDEOLATCH, "The number of colour bits to request from the renedering context"); CVAR_ARCHIVE | CVAR_VIDEOLATCH, "The number of colour bits to request from the renedering context");
cvar_t vid_depthbits = CVARFD ("vid_depthbits", "0",
CVAR_ARCHIVE | CVAR_VIDEOLATCH, "The number of depth bits to request from the renedering context. Try 24.");
cvar_t vid_desktopsettings = CVARFD ("vid_desktopsettings", "0", cvar_t vid_desktopsettings = CVARFD ("vid_desktopsettings", "0",
CVAR_ARCHIVE | CVAR_VIDEOLATCH, "Ignore the values of vid_width and vid_height, and just use the same settings that are used for the desktop."); CVAR_ARCHIVE | CVAR_VIDEOLATCH, "Ignore the values of vid_width and vid_height, and just use the same settings that are used for the desktop.");
cvar_t vid_fullscreen = CVARF ("vid_fullscreen", "2", cvar_t vid_fullscreen = CVARF ("vid_fullscreen", "2",
@ -494,7 +496,7 @@ cvar_t r_lodscale = CVARFD ("r_lodscale", "5", CVAR_ARCHIVE, "Scales the l
cvar_t r_lodbias = CVARFD ("r_lodbias", "0", CVAR_ARCHIVE, "Biases the level-of-detail on models (for those that have lod)."); cvar_t r_lodbias = CVARFD ("r_lodbias", "0", CVAR_ARCHIVE, "Biases the level-of-detail on models (for those that have lod).");
cvar_t r_shadows = CVARFD ("r_shadows", "0", CVAR_ARCHIVE, "Draw basic blob shadows underneath entities without using realtime lighting."); cvar_t r_shadows = CVARFD ("r_shadows", "0", CVAR_ARCHIVE, "Draw basic blob shadows underneath entities without using realtime lighting.");
cvar_t r_showbboxes = CVARD("r_showbboxes", "0", "Debugging. Shows bounding boxes. 1=ssqc, 2=csqc. Red=solid, Green=stepping/toss/bounce, Blue=onground."); cvar_t r_showbboxes = CVARD("r_showbboxes", "0", "Debugging. Shows bounding boxes. 1=ssqc, 2=csqc. Red=solid, Green=stepping/toss/bounce, Blue=onground.");
cvar_t r_showfields = CVARD("r_showfields", "0", "Debugging. Shows entity fields boxes (entity closest to crosshair). 1=ssqc, 2=csqc."); cvar_t r_showfields = CVARD("r_showfields", "0", "Debugging. Shows entity fields boxes (entity closest to crosshair). 1=ssqc, 2=csqc, 3=snapshots.");
cvar_t r_showshaders = CVARD("r_showshaders", "0", "Debugging. Shows the name of the (worldmodel) shader being pointed to."); cvar_t r_showshaders = CVARD("r_showshaders", "0", "Debugging. Shows the name of the (worldmodel) shader being pointed to.");
cvar_t r_lightprepass_cvar = CVARFD("r_lightprepass", "0", CVAR_ARCHIVE, "Experimental. Attempt to use a different lighting mechanism (aka: deferred lighting). Requires vid_reload to take effect."); cvar_t r_lightprepass_cvar = CVARFD("r_lightprepass", "0", CVAR_ARCHIVE, "Experimental. Attempt to use a different lighting mechanism (aka: deferred lighting). Requires vid_reload to take effect.");
int r_lightprepass; int r_lightprepass;
@ -741,7 +743,7 @@ void R_ToggleFullscreen_f(void)
if (currentrendererstate.renderer->rtype == QR_HEADLESS || currentrendererstate.renderer->rtype == QR_NONE) if (currentrendererstate.renderer->rtype == QR_HEADLESS || currentrendererstate.renderer->rtype == QR_NONE)
return; return;
Cvar_ApplyLatches(CVAR_VIDEOLATCH|CVAR_RENDERERLATCH); Cvar_ApplyLatches(CVAR_VIDEOLATCH|CVAR_RENDERERLATCH, false);
newr = currentrendererstate; newr = currentrendererstate;
if (newr.fullscreen) if (newr.fullscreen)
@ -834,6 +836,7 @@ void Renderer_Init(void)
Cvar_Register (&vid_fullscreen, VIDCOMMANDGROUP); Cvar_Register (&vid_fullscreen, VIDCOMMANDGROUP);
Cvar_Register (&vid_bpp, VIDCOMMANDGROUP); Cvar_Register (&vid_bpp, VIDCOMMANDGROUP);
Cvar_Register (&vid_depthbits, VIDCOMMANDGROUP);
Cvar_Register (&vid_conwidth, VIDCOMMANDGROUP); Cvar_Register (&vid_conwidth, VIDCOMMANDGROUP);
Cvar_Register (&vid_conheight, VIDCOMMANDGROUP); Cvar_Register (&vid_conheight, VIDCOMMANDGROUP);
@ -1097,7 +1100,7 @@ qboolean Renderer_Started(void)
void Renderer_Start(void) void Renderer_Start(void)
{ {
r_blockvidrestart = false; r_blockvidrestart = false;
Cvar_ApplyLatches(CVAR_VIDEOLATCH|CVAR_RENDERERLATCH); Cvar_ApplyLatches(CVAR_VIDEOLATCH|CVAR_RENDERERLATCH, false);
//renderer = none && currentrendererstate.bpp == -1 means we've never applied any mode at all //renderer = none && currentrendererstate.bpp == -1 means we've never applied any mode at all
//if we currently have none, we do actually need to apply it still //if we currently have none, we do actually need to apply it still
@ -1155,6 +1158,7 @@ qboolean R_RegisterRenderer(void *module, rendererinfo_t *ri)
{ {
rendererinfo[i].module = module; rendererinfo[i].module = module;
rendererinfo[i].ri = ri; rendererinfo[i].ri = ri;
R_UpdateRendererOpts();
return true; return true;
} }
} }
@ -1586,15 +1590,15 @@ qboolean R_ApplyRenderer_Load (rendererstate_t *newr)
memcpy(host_basepal, default_quakepal, 768); memcpy(host_basepal, default_quakepal, 768);
} }
} }
Validation_FileLoaded("gfx/palette.lmp", host_basepal, 768); if (!Ruleset_FileLoaded("gfx/palette.lmp", host_basepal, 768))
memcpy(host_basepal, default_quakepal, 768);
{ {
size_t csize; size_t csize;
qbyte *colormap = (qbyte *)FS_LoadMallocFile ("gfx/colormap.lmp", &csize); qbyte *colormap = (qbyte *)FS_LoadMallocFile ("gfx/colormap.lmp", &csize);
if (colormap && csize == VID_GRADES*256+1) if (colormap && csize == VID_GRADES*256+1 && Ruleset_FileLoaded("gfx/colormap.lmp", colormap, csize))
{ {
Validation_FileLoaded("gfx/colormap.lmp", colormap, csize);
j = VID_GRADES-1; j = VID_GRADES-1;
data = colormap + j*256; data = colormap + j*256;
vid.fullbright = 0; vid.fullbright = 0;
@ -1959,7 +1963,7 @@ void R_ReloadRenderer_f (void)
} }
#endif #endif
Cvar_ApplyLatches(CVAR_VIDEOLATCH|CVAR_RENDERERLATCH); Cvar_ApplyLatches(CVAR_VIDEOLATCH|CVAR_RENDERERLATCH, false);
R_ShutdownRenderer(false); R_ShutdownRenderer(false);
Con_DPrintf("teardown = %f\n", Sys_DoubleTime() - time); Con_DPrintf("teardown = %f\n", Sys_DoubleTime() - time);
//reloads textures without destroying video context. //reloads textures without destroying video context.
@ -2006,6 +2010,7 @@ qboolean R_BuildRenderstate(rendererstate_t *newr, char *rendererstring)
newr->triplebuffer = vid_triplebuffer.value; newr->triplebuffer = vid_triplebuffer.value;
newr->multisample = vid_multisample.value; newr->multisample = vid_multisample.value;
newr->bpp = vid_bpp.value; newr->bpp = vid_bpp.value;
newr->depthbits = vid_depthbits.value;
newr->fullscreen = vid_fullscreen.value; newr->fullscreen = vid_fullscreen.value;
newr->rate = vid_refreshrate.value; newr->rate = vid_refreshrate.value;
newr->stereo = (r_stereo_method.ival == 1); newr->stereo = (r_stereo_method.ival == 1);
@ -2301,6 +2306,7 @@ void R_RestartRenderer (rendererstate_t *newr)
Con_Printf("%s: %s\n", vid_width.name, vid_width.string); Con_Printf("%s: %s\n", vid_width.name, vid_width.string);
Con_Printf("%s: %s\n", vid_height.name, vid_height.string); Con_Printf("%s: %s\n", vid_height.name, vid_height.string);
Con_Printf("%s: %s\n", vid_bpp.name, vid_bpp.string); Con_Printf("%s: %s\n", vid_bpp.name, vid_bpp.string);
Con_Printf("%s: %s\n", vid_depthbits.name, vid_depthbits.string);
Con_Printf("%s: %s\n", vid_refreshrate.name, vid_refreshrate.string); Con_Printf("%s: %s\n", vid_refreshrate.name, vid_refreshrate.string);
Con_Printf("%s: %s\n", vid_renderer.name, vid_renderer.string); Con_Printf("%s: %s\n", vid_renderer.name, vid_renderer.string);
Con_Printf("%s: %s\n", gl_driver.name, gl_driver.string); Con_Printf("%s: %s\n", gl_driver.name, gl_driver.string);
@ -2332,7 +2338,7 @@ void R_RestartRenderer_f (void)
double time; double time;
rendererstate_t newr; rendererstate_t newr;
Cvar_ApplyLatches(CVAR_VIDEOLATCH|CVAR_RENDERERLATCH); Cvar_ApplyLatches(CVAR_VIDEOLATCH|CVAR_RENDERERLATCH, false);
if (!R_BuildRenderstate(&newr, vid_renderer.string)) if (!R_BuildRenderstate(&newr, vid_renderer.string))
{ {
Con_Printf("vid_renderer \"%s\" unsupported. Using default.\n", vid_renderer.string); Con_Printf("vid_renderer \"%s\" unsupported. Using default.\n", vid_renderer.string);
@ -2349,6 +2355,34 @@ void R_RestartRenderer_f (void)
// Con_Printf("full video restart took %f secs\n", Sys_DoubleTime() - time); // Con_Printf("full video restart took %f secs\n", Sys_DoubleTime() - time);
} }
static void R_EnumeratedRenderer(void *ctx, const char *devname, const char *outputname, const char *desc)
{
rendererinfo_t *r = ctx;
char quoteddesc[1024];
const char *dev;
if (*outputname)
dev = va("%s %s %s", r->name[0], devname, outputname);
else if (*devname)
dev = va("%s %s", r->name[0], devname);
else
dev = r->name[0];
dev = COM_QuotedString(dev, quoteddesc,sizeof(quoteddesc), false);
if (*outputname)
Con_Printf("^[%s (%s, %s)\\type\\/setrenderer %s^]^7: %s%s\n",
r->name[0], devname, outputname, //link text
dev, //link itself.
desc, (currentrendererstate.renderer == r)?" ^2(current)":"");
else if (*devname)
Con_Printf("^[%s (%s)\\type\\/setrenderer %s^]^7: %s%s\n",
r->name[0], devname, //link text
dev, //link itself.
desc, (currentrendererstate.renderer == r)?" ^2(current)":"");
else
Con_Printf("^[%s\\type\\/setrenderer %s^]^7: %s%s\n", r->name[0], dev, r->description, (currentrendererstate.renderer == r)?" ^2(current)":"");
}
void R_SetRenderer_f (void) void R_SetRenderer_f (void)
{ {
int i; int i;
@ -2371,12 +2405,15 @@ void R_SetRenderer_f (void)
{ {
rendererinfo_t *r = sorted[i].r; rendererinfo_t *r = sorted[i].r;
if (r && r->description) 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)":""); {
if (!r->VID_EnumerateDevices || !r->VID_EnumerateDevices(r, R_EnumeratedRenderer))
R_EnumeratedRenderer(r, "", "", r->description);
}
} }
return; return;
} }
Cvar_ApplyLatches(CVAR_VIDEOLATCH|CVAR_RENDERERLATCH); Cvar_ApplyLatches(CVAR_VIDEOLATCH|CVAR_RENDERERLATCH, false);
if (!R_BuildRenderstate(&newr, param)) if (!R_BuildRenderstate(&newr, param))
{ {
Con_Printf("setrenderer: parameter not supported (%s)\n", param); Con_Printf("setrenderer: parameter not supported (%s)\n", param);
@ -2395,11 +2432,32 @@ void R_SetRenderer_f (void)
R_RestartRenderer(&newr); R_RestartRenderer(&newr);
} }
static void R_UpdateRendererOpts(void) struct videnumctx_s
{ {
char *v = NULL; char *v;
char *apiname;
};
static void R_DeviceEnumerated(void *context, const char *devicename, const char *outputname, const char *description)
{
struct videnumctx_s *ctx = context;
char quotedname[1024];
char quoteddesc[1024];
char *name = va("%s %s %s", ctx->apiname,
COM_QuotedString(devicename, quotedname,sizeof(quotedname), false),
COM_QuotedString(outputname, quoteddesc,sizeof(quoteddesc), false));
Z_StrCat(&ctx->v, va("%s %s ", COM_QuotedString(name, quotedname, sizeof(quotedname), false), COM_QuotedString(description, quoteddesc, sizeof(quoteddesc), false)));
}
static qboolean rendereroptsupdated;
static void R_UpdateRendererOptsNow(int iarg, void *data)
{
struct videnumctx_s e = {NULL};
size_t i; size_t i;
struct sortedrenderers_s sorted[countof(rendererinfo)]; struct sortedrenderers_s sorted[countof(rendererinfo)];
if (!rendereroptsupdated)
return; //multiple got queued...
rendereroptsupdated = false;
for (i = 0; i < countof(sorted); i++) for (i = 0; i < countof(sorted); i++)
{ {
sorted[i].index = i; sorted[i].index = i;
@ -2409,7 +2467,7 @@ static void R_UpdateRendererOpts(void)
qsort(sorted, countof(sorted), sizeof(sorted[0]), R_SortRenderers); qsort(sorted, countof(sorted), sizeof(sorted[0]), R_SortRenderers);
v = NULL; e.v = NULL;
for (i = 0; i < countof(rendererinfo); i++) for (i = 0; i < countof(rendererinfo); i++)
{ {
rendererinfo_t *r = sorted[i].r; rendererinfo_t *r = sorted[i].r;
@ -2417,12 +2475,20 @@ static void R_UpdateRendererOpts(void)
{ {
if (r->rtype == QR_HEADLESS || r->rtype == QR_NONE) if (r->rtype == QR_HEADLESS || r->rtype == QR_NONE)
continue; //skip these, they're kinda dangerous. continue; //skip these, they're kinda dangerous.
Z_StrCat(&v, va("%s \"%s\" ", r->name[0], r->description)); e.apiname = r->name[0];
if (!r->VID_EnumerateDevices || !r->VID_EnumerateDevices(&e, R_DeviceEnumerated))
R_DeviceEnumerated(&e, r->name[0], "", r->description);
} }
} }
Z_Free(vid_renderer_opts.enginevalue); Cvar_SetEngineDefault(&vid_renderer_opts, e.v?e.v:"");
vid_renderer_opts.enginevalue = v; Cvar_ForceSet(&vid_renderer_opts, e.v?e.v:"");
Z_Free(e.v);
}
static void R_UpdateRendererOpts(void)
{ //use a timer+flag, so we don't reenumerate everything any time any device gets registered.
rendereroptsupdated = true;
Cmd_AddTimer(0, R_UpdateRendererOptsNow, 0, NULL, 0);
} }

View File

@ -39,6 +39,7 @@ cvar_t scr_scoreboard_backgroundalpha = CVARD("scr_scoreboard_backgroundalpha",
cvar_t scr_scoreboard_teamscores = CVARD("scr_scoreboard_teamscores", "1", "Makes +showscores act as +showteamscores. Because reasons."); cvar_t scr_scoreboard_teamscores = CVARD("scr_scoreboard_teamscores", "1", "Makes +showscores act as +showteamscores. Because reasons.");
cvar_t scr_scoreboard_teamsort = CVARD("scr_scoreboard_teamsort", "0", "On the scoreboard, sort players by their team BEFORE their personal score."); cvar_t scr_scoreboard_teamsort = CVARD("scr_scoreboard_teamsort", "0", "On the scoreboard, sort players by their team BEFORE their personal score.");
cvar_t scr_scoreboard_titleseperator = CVAR("scr_scoreboard_titleseperator", "1"); cvar_t scr_scoreboard_titleseperator = CVAR("scr_scoreboard_titleseperator", "1");
cvar_t scr_scoreboard_showruleset = CVAR("scr_scoreboard_showruleset", "1");
cvar_t sbar_teamstatus = CVARD("sbar_teamstatus", "1", "Display the last team say from each of your team members just above the sbar area."); cvar_t sbar_teamstatus = CVARD("sbar_teamstatus", "1", "Display the last team say from each of your team members just above the sbar area.");
cvar_t cl_sbaralpha = CVARAD("cl_sbaralpha", "0.75", "scr_sbaralpha", "Specifies the transparency of the status bar. Only Takes effect when cl_sbar is set to 2."); //with premultiplied alpha, this needs to affect the RGB values too. cvar_t cl_sbaralpha = CVARAD("cl_sbaralpha", "0.75", "scr_sbaralpha", "Specifies the transparency of the status bar. Only Takes effect when cl_sbar is set to 2."); //with premultiplied alpha, this needs to affect the RGB values too.
@ -1141,6 +1142,7 @@ void Sbar_Init (void)
Cvar_Register(&scr_scoreboard_newstyle, "Scoreboard settings"); Cvar_Register(&scr_scoreboard_newstyle, "Scoreboard settings");
Cvar_Register(&scr_scoreboard_showfrags, "Scoreboard settings"); Cvar_Register(&scr_scoreboard_showfrags, "Scoreboard settings");
Cvar_Register(&scr_scoreboard_showflags, "Scoreboard settings"); Cvar_Register(&scr_scoreboard_showflags, "Scoreboard settings");
Cvar_Register(&scr_scoreboard_showruleset, "Scoreboard settings");
Cvar_Register(&scr_scoreboard_fillalpha, "Scoreboard settings"); Cvar_Register(&scr_scoreboard_fillalpha, "Scoreboard settings");
Cvar_Register(&scr_scoreboard_backgroundalpha, "Scoreboard settings"); Cvar_Register(&scr_scoreboard_backgroundalpha, "Scoreboard settings");
Cvar_Register(&scr_scoreboard_teamscores, "Scoreboard settings"); Cvar_Register(&scr_scoreboard_teamscores, "Scoreboard settings");
@ -3316,6 +3318,7 @@ ping time frags name
Draw_FunStringWidth(x, y, s->team, 4*8, false, false); \ Draw_FunStringWidth(x, y, s->team, 4*8, false, false); \
} \ } \
},NOFILL) },NOFILL)
#define COLUMN_RULESET COLUMN(ruleset, 8*8, {Draw_FunStringWidth(x, y, s->ruleset, 8*8, false, false);},NOFILL)
#define COLUMN_NAME COLUMN(name, namesize, {Draw_FunStringWidth(x, y, s->name, namesize, false, false);},NOFILL) #define COLUMN_NAME COLUMN(name, namesize, {Draw_FunStringWidth(x, y, s->name, namesize, false, false);},NOFILL)
#define COLUMN_KILLS COLUMN(kils, 4*8, {Draw_FunStringWidth(x, y, va("%4i", Stats_GetKills(k)), 4*8, false, false);},NOFILL) #define COLUMN_KILLS COLUMN(kils, 4*8, {Draw_FunStringWidth(x, y, va("%4i", Stats_GetKills(k)), 4*8, false, false);},NOFILL)
#define COLUMN_TKILLS COLUMN(tkil, 4*8, {Draw_FunStringWidth(x, y, va("%4i", Stats_GetTKills(k)), 4*8, false, false);},NOFILL) #define COLUMN_TKILLS COLUMN(tkil, 4*8, {Draw_FunStringWidth(x, y, va("%4i", Stats_GetTKills(k)), 4*8, false, false);},NOFILL)
@ -3326,7 +3329,7 @@ ping time frags name
//columns are listed here in display order //columns are listed here in display order
#define ALLCOLUMNS COLUMN_PING COLUMN_PL COLUMN_TIME COLUMN_FRAGS COLUMN_TEAMNAME COLUMN_NAME COLUMN_KILLS COLUMN_TKILLS COLUMN_DEATHS COLUMN_TOUCHES COLUMN_CAPS COLUMN_AFK #define ALLCOLUMNS COLUMN_PING COLUMN_PL COLUMN_TIME COLUMN_RULESET COLUMN_FRAGS COLUMN_TEAMNAME COLUMN_NAME COLUMN_KILLS COLUMN_TKILLS COLUMN_DEATHS COLUMN_TOUCHES COLUMN_CAPS COLUMN_AFK
enum enum
{ {
@ -3458,6 +3461,10 @@ void Sbar_DeathmatchOverlay (playerview_t *pv, int start)
{ {
COLUMN_TOUCHES COLUMN_TOUCHES
} }
if (scr_scoreboard_showruleset.ival && (scr_scoreboard_showruleset.ival==2||Ruleset_GetRulesetName()))
{
COLUMN_RULESET
}
COLUMN_AFK COLUMN_AFK
#undef COLUMN #undef COLUMN

View File

@ -57,7 +57,7 @@ qboolean snd_initialized = false;
int snd_speed; int snd_speed;
float voicevolumemod = 1; float voicevolumemod = 1;
static struct static struct listener_s
{ {
int entnum; int entnum;
vec3_t origin; vec3_t origin;
@ -3884,6 +3884,7 @@ static void S_UpdateCard(soundcardinfo_t *sc)
// //
if (snd_show.ival) if (snd_show.ival)
{ {
struct listener_s *l;
int active, mute; int active, mute;
active = 0; active = 0;
mute = 0; mute = 0;
@ -3900,7 +3901,11 @@ static void S_UpdateCard(soundcardinfo_t *sc)
mute++; mute++;
} }
Con_Printf ("----(%i+%i)----\n", active, mute); if (sc->seat < 0)
l = &listener[0];
else
l = &listener[sc->seat];
Con_Printf ("----(%i+%i %s %i %.1f %.1f %.1f)----\n", active, mute, sc->name, l->entnum, l->origin[0], l->origin[1], l->origin[2]);
} }
#ifdef HAVE_MIXER #ifdef HAVE_MIXER

View File

@ -994,8 +994,12 @@ static void S_LoadSoundWorker (void *ctx, void *ctxdata, size_t forcedecode, siz
} }
} }
if (data) if (data && !Ruleset_FileLoaded(name, data, filesize))
Validation_FileLoaded(name, data, filesize); {
BZ_Free(data);
data = NULL;
filesize = 0;
}
} }
if (!data) if (!data)

View File

@ -1077,7 +1077,7 @@ char *Sys_ConsoleInput(void)
} }
#ifdef HAVE_GNUTLS #ifdef HAVE_GNUTLS
static void DoSign(const char *fname) static void DoSign(const char *fname, int signtype)
{ {
qbyte digest[1024]; qbyte digest[1024];
qbyte signature[2048]; qbyte signature[2048];
@ -1104,14 +1104,30 @@ static void DoSign(const char *fname)
} }
h->terminate(digest, ctx); h->terminate(digest, ctx);
VFS_CLOSE(f); VFS_CLOSE(f);
printf(" \\\"dlsize=%zu\\\"", ts);
Base16_EncodeBlock(digest, h->digestsize, base64, sizeof(base64)); if (signtype == 0)
printf(" \\\"sha512=%s\\\"", base64); { //old junk
printf(" \\\"dlsize=%zu\\\"", ts);
sigsize = GNUTLS_GenerateSignature(digest, h->digestsize, signature, sizeof(signature)); Base16_EncodeBlock(digest, h->digestsize, base64, sizeof(base64));
Base64_EncodeBlock(signature, sigsize, base64, sizeof(base64)); printf(" \\\"sha512=%s\\\"", base64);
printf(" \\\"sign=%s:%s\\\"\n", auth, base64);
sigsize = GNUTLS_GenerateSignature(digest, h->digestsize, signature, sizeof(signature));
Base64_EncodeBlock(signature, sigsize, base64, sizeof(base64));
printf(" \\\"sign=%s:%s\\\"\n", auth, base64);
}
else if (signtype == 2)
{ //signature "auth" "signdata"
//printf(" \\\"dlsize=%zu\\\"", ts);
//Base16_EncodeBlock(digest, h->digestsize, base64, sizeof(base64));
//printf(" \\\"sha512=%s\\\"", base64);
sigsize = GNUTLS_GenerateSignature(digest, h->digestsize, signature, sizeof(signature));
Base64_EncodeBlock(signature, sigsize, base64, sizeof(base64));
printf("%s\n", base64);
}
} }
} }
#endif #endif
@ -1272,6 +1288,8 @@ int main (int c, const char **v)
#ifdef HAVE_GNUTLS #ifdef HAVE_GNUTLS
//fteqw -privcert privcert.key -pubcert pubcert.key -sign binaryfile.pk3 //fteqw -privcert privcert.key -pubcert pubcert.key -sign binaryfile.pk3
i = COM_CheckParm("-sign"); i = COM_CheckParm("-sign");
if (!i)
i = COM_CheckParm("-sign2");
if (i) if (i)
{ {
//init some useless crap //init some useless crap
@ -1280,7 +1298,7 @@ int main (int c, const char **v)
Memory_Init (); Memory_Init ();
COM_Init (); COM_Init ();
DoSign(com_argv[i+1]); DoSign(com_argv[i+1], atoi(com_argv[i+0]+5));
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
#endif #endif

File diff suppressed because it is too large Load Diff

View File

@ -75,7 +75,10 @@ typedef struct
} pxrect_t; } pxrect_t;
//srgb colourspace displays smoother visual gradients, but its more of an illusion than anything else. //srgb colourspace displays smoother visual gradients, but its more of an illusion than anything else.
// //we can be in a few different modes:
//linear - rendering is done using some float framebuffer or so. lighting is more correct. textures are converted from srgb colourspace when reading.
//non-linear - the lame option where lighting is wrong, but used anyway for compat. final colours will be whatever the screen uses (probably srgb, so artwork looks fine)
//srgb - like linear, except our framebuffer does extra transforms to hide that its storage is actually non-linear.
#define VID_SRGBAWARE (1u<<0) //we need to convert input srgb values to actual linear values (requires vid_reload to change...) #define VID_SRGBAWARE (1u<<0) //we need to convert input srgb values to actual linear values (requires vid_reload to change...)
#define VID_SRGB_FB_LINEAR (1u<<1) //framebuffer is linear (either the presentation engine is linear, or the blend unit is faking it) #define VID_SRGB_FB_LINEAR (1u<<1) //framebuffer is linear (either the presentation engine is linear, or the blend unit is faking it)
#define VID_SRGB_FB_FAKED (1u<<2) //renderer is faking it with a linear texture #define VID_SRGB_FB_FAKED (1u<<2) //renderer is faking it with a linear texture

View File

@ -818,7 +818,7 @@ void V_CalcBlend (float *hw_blend)
//don't apply it to the server, we'll blend the two later if the user has no hardware gamma (if they do have it, we use just the server specified value) This way we avoid winnt users having a cheat with flashbangs and stuff. //don't apply it to the server, we'll blend the two later if the user has no hardware gamma (if they do have it, we use just the server specified value) This way we avoid winnt users having a cheat with flashbangs and stuff.
for (j=0 ; j<NUM_CSHIFTS ; j++) for (j=0 ; j<NUM_CSHIFTS ; j++)
{ {
if ((j == CSHIFT_SERVER&&!cls.demoplayback) || j == CSHIFT_BONUS) if ((j == CSHIFT_SERVER&&!cls.demoplayback&&!pv->spectator) || j == CSHIFT_BONUS)
{ {
a2 = pv->cshifts[j].percent / 255.0; //don't allow modification of this one. a2 = pv->cshifts[j].percent / 255.0; //don't allow modification of this one.
} }
@ -2034,7 +2034,7 @@ void R_DrawNameTags(void)
#endif #endif
cl.worldmodel->funcs.NativeTrace(cl.worldmodel, 0, PE_FRAMESTATE, NULL, r_refdef.vieworg, targ, vec3_origin, vec3_origin, false, ~0, &trace); cl.worldmodel->funcs.NativeTrace(cl.worldmodel, 0, PE_FRAMESTATE, NULL, r_refdef.vieworg, targ, vec3_origin, vec3_origin, false, ~0, &trace);
surf = Mod_GetSurfaceNearPoint(cl.worldmodel, trace.endpos); surf = (trace.fraction == 1)?NULL:Mod_GetSurfaceNearPoint(cl.worldmodel, trace.endpos);
if (surf) if (surf)
{ {
shader_t *shader = surf->texinfo->texture->shader; shader_t *shader = surf->texinfo->texture->shader;
@ -2703,6 +2703,7 @@ void V_Init (void)
Cvar_Register (&r_projection, VIEWVARS); Cvar_Register (&r_projection, VIEWVARS);
BuildGammaTable (1.0, 1.0, 1.0, 0.0); // no gamma yet BuildGammaTable (1.0, 1.0, 1.0, 0.0); // no gamma yet
Cvar_Register (&v_gammainverted, VIEWVARS);
Cvar_Register (&v_gamma, VIEWVARS); Cvar_Register (&v_gamma, VIEWVARS);
Cvar_Register (&v_contrast, VIEWVARS); Cvar_Register (&v_contrast, VIEWVARS);
Cvar_Register (&v_contrastboost, VIEWVARS); Cvar_Register (&v_contrastboost, VIEWVARS);

View File

@ -74,7 +74,7 @@ typedef struct plugvrfuncs_s
qboolean (*Prepare) (vrsetup_t *setupinfo); //called before graphics context init qboolean (*Prepare) (vrsetup_t *setupinfo); //called before graphics context init
qboolean (*Init) (vrsetup_t *setupinfo, rendererstate_t *info); //called after graphics context init qboolean (*Init) (vrsetup_t *setupinfo, rendererstate_t *info); //called after graphics context init
qboolean (*SyncFrame)(double *frametime); //called in the client's main loop, to block/tweak frame times. True means the game should render as fast as possible. qboolean (*SyncFrame)(double *frametime); //called in the client's main loop, to block/tweak frame times. True means the game should render as fast as possible.
qboolean (*Render) (void(*rendereye)(texid_t tex, vec4_t fovoverride, vec3_t axisorg[4])); qboolean (*Render) (void(*rendereye)(texid_t tex, vec4_t fovoverride, matrix3x4 axisorg));
void (*Shutdown) (void); void (*Shutdown) (void);
#define plugvrfuncs_name "VR" #define plugvrfuncs_name "VR"
} plugvrfuncs_t; } plugvrfuncs_t;

View File

@ -494,7 +494,7 @@ qbyte *W_GetTexture(const char *name, int *width, int *height, uploadfmt_t *form
if (con_ocranaleds.ival) if (con_ocranaleds.ival)
{ {
if (con_ocranaleds.ival != 2 || QCRC_Block(lump, 128*128) == 798) if (con_ocranaleds.ival != 2 || CalcHashInt(&hash_crc16, lump, 128*128) == 798)
AddOcranaLEDsIndexed (lump, 128, 128); AddOcranaLEDsIndexed (lump, 128, 128);
} }

View File

@ -866,6 +866,17 @@ static char *Macro_TF_Skin (void)
} }
//Spike: added these: //Spike: added these:
static char *Macro_Team (void)
{
infobuf_t *info;
int seat = SP;
//read the userinfo's team from the server instead of our local/private cvar/userinfo, if we can.
if (cl.players[cl.playerview[seat].playernum].userinfovalid)
info = &cl.players[cl.playerview[seat].playernum].userinfo;
else //just use the userinfo (which should mirror the cvar - fixme: splitscreen...)
info = &cls.userinfo[seat];
return InfoBuf_ValueForKey(info, "team");
}
static char *Macro_ConnectionType (void) static char *Macro_ConnectionType (void)
{ {
playerview_t *pv = &cl.playerview[SP]; playerview_t *pv = &cl.playerview[SP];
@ -1271,7 +1282,7 @@ static char *Macro_Match_Status(void)
} }
} }
/*static char *Macro_LastIP(void) /*static char *Macro_LastIP(void)
{ //report the last ip that someone said in chat. { //report the last ip that someone said in chat. requires making guesses about what's an ip or not. can't handle hostnames properly
return "---"; return "---";
} }
static char *Macro_MP3Info(void) static char *Macro_MP3Info(void)
@ -1331,6 +1342,7 @@ static void TP_InitMacros(void)
Cmd_AddMacro("powerups", Macro_Powerups, true); Cmd_AddMacro("powerups", Macro_Powerups, true);
Cmd_AddMacro("droppedweapon", Macro_DroppedWeapon, true); Cmd_AddMacro("droppedweapon", Macro_DroppedWeapon, true);
Cmd_AddMacro("tf_skin", Macro_TF_Skin, true); Cmd_AddMacro("tf_skin", Macro_TF_Skin, true);
Cmd_AddMacro("team", Macro_Team, true); //confusing
Cmd_AddMacro("deathloc", Macro_LastDeath, true); Cmd_AddMacro("deathloc", Macro_LastDeath, true);
Cmd_AddMacro("tookatloc", Macro_TookAtLoc, true); Cmd_AddMacro("tookatloc", Macro_TookAtLoc, true);
@ -1897,7 +1909,7 @@ static void TP_MsgTrigger_f (void)
} }
if (c >= 3) { if (c >= 3) {
if (strlen(Cmd_Argv(2)) > 63) { if (strlen(Cmd_Argv(2)) >= countof(trig->string)) {
Com_Printf ("trigger string too long\n"); Com_Printf ("trigger string too long\n");
return; return;
} }
@ -1935,6 +1947,9 @@ void TP_SearchForMsgTriggers (char *s, int level)
if (cls.demoplayback) if (cls.demoplayback)
return; return;
if (!ruleset_allow_triggers.ival)
return;
for (t=msg_triggers; t; t=t->next) for (t=msg_triggers; t; t=t->next)
if ((t->level == level || (t->level == 3 && level == 4)) if ((t->level == level || (t->level == 3 && level == 4))
&& t->string[0] && strstr(s, t->string)) && t->string[0] && strstr(s, t->string))
@ -1959,45 +1974,6 @@ void TP_SearchForMsgTriggers (char *s, int level)
} }
} }
/*
void TP_CheckVersionRequest (char *s)
{
char buf[11];
int i;
if (cl.spectator)
return;
if (vars.f_version_reply_time
&& realtime - vars.f_version_reply_time < 20)
return; // don't reply again if 20 seconds haven't passed
while (1)
{
switch (*s++)
{
case 0:
case '\n':
return;
case ':':
case (char)(':'|128): // hmm.... why is this here?
goto ok;
}
}
return;
ok:
for (i = 0; i < 11 && s[i]; i++)
buf[i] = s[i] &~ 128; // strip high bit
if (!strncmp(buf, " f_version\n", 11) || !strncmp(buf, " z_version\n", 11))
{
Cbuf_AddText (va("say ZQuake version %s "
QW_PLATFORM ":" QW_RENDERER "\n", VersionString()));
vars.f_version_reply_time = realtime;
}
}*/
#ifdef QWSKINS #ifdef QWSKINS
/* /*
============================================================================= =============================================================================

View File

@ -1130,4 +1130,25 @@ STAT_MOVEVARS_AIRACCEL_SIDEWAYS_FRICTION = 255, // DP
#define dem_all 6 #define dem_all 6
#if 0 //fuck sake, just build it in an older chroot.
/*
glibc SUCKS. 64bit glibc is depending upon glibc 2.14 because of some implementation-defined copy direction change that breaks flash.
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.
*/
#if defined(__GNUC__) && defined(__amd64__) && defined(__linux__) && !defined(FTE_SDL)
#include <features.h> /* for glibc version */
#if defined(__GLIBC__) && (__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 14)
__asm__(".symver memcpy,memcpy@GLIBC_2.2.5");
__asm__(".symver memmove,memmove@GLIBC_2.2.5");
#endif
#if defined(__GLIBC__) && (__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 29)
__asm__(".symver exp,exp@GLIBC_2.2.5");
__asm__(".symver log,log@GLIBC_2.2.5");
__asm__(".symver pow,pow@GLIBC_2.2.5");
#endif
#endif
/*end glibc workaround*/
#endif
#endif //ifndef __BOTHDEFS_H #endif //ifndef __BOTHDEFS_H

View File

@ -76,7 +76,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
typedef struct typedef struct
{ {
int fileofs, filelen; unsigned int fileofs, filelen;
} lump_t; } lump_t;
#define LUMP_ENTITIES 0 #define LUMP_ENTITIES 0
@ -160,23 +160,28 @@ typedef struct
} dplane_t; } dplane_t;
enum q1contents_e
#define Q1CONTENTS_EMPTY -1 { //q1 and halflife bsp contents values.
#define Q1CONTENTS_SOLID -2 //also used for .skin for content forcing.
#define Q1CONTENTS_WATER -3 Q1CONTENTS_EMPTY = -1,
#define Q1CONTENTS_SLIME -4 Q1CONTENTS_SOLID = -2,
#define Q1CONTENTS_LAVA -5 Q1CONTENTS_WATER = -3,
#define Q1CONTENTS_SKY -6 Q1CONTENTS_SLIME = -4,
#define Q1CONTENTS_STRIPPED -7 /*not known to engine*/ Q1CONTENTS_LAVA = -5,
#define Q1CONTENTS_CLIP -8 /*solid to players*/ Q1CONTENTS_SKY = -6,
#define Q1CONTENTS_FLOW_1 -9 /*moves player*/ //#define Q1CONTENTS_ORIGIN -7 /*not known to engine - origin or something*/
#define Q1CONTENTS_FLOW_2 -10 /*moves player*/ Q1CONTENTS_CLIP = -8, /*solid to players+monsters, but not tracelines*/
#define Q1CONTENTS_FLOW_3 -11 /*moves player*/ Q1CONTENTS_CURRENT_0 = -9, /*moves player*/
#define Q1CONTENTS_FLOW_4 -12 /*moves player*/ Q1CONTENTS_CURRENT_90 = -10, /*moves player*/
#define Q1CONTENTS_FLOW_5 -13 /*moves player*/ Q1CONTENTS_CURRENT_180 = -11, /*moves player*/
#define Q1CONTENTS_FLOW_6 -14 /*moves player*/ Q1CONTENTS_CURRENT_270 = -12, /*moves player*/
#define Q1CONTENTS_TRANS -15 /*should be solid I guess*/ Q1CONTENTS_CURRENT_UP = -13, /*moves player*/
#define Q1CONTENTS_LADDER -16 /*player can climb up/down*/ Q1CONTENTS_CURRENT_DOWN = -14, /*moves player*/
Q1CONTENTS_TRANS = -15, /*should be solid I guess*/
Q1CONTENTS_LADDER = -16, /*player can climb up/down*/
Q1CONTENTS_MONSTERCLIP = -17, /*solid to monster movement*/
Q1CONTENTS_PLAYERCLIP = -18, /*solid to player movement*/
};
// !!! if this is changed, it must be changed in asm_i386.h too !!! // !!! if this is changed, it must be changed in asm_i386.h too !!!
typedef struct typedef struct

1813
engine/common/com_bih.c Normal file

File diff suppressed because it is too large Load Diff

105
engine/common/com_bih.h Normal file
View File

@ -0,0 +1,105 @@
#if 1
#define BIH_USEBIH
#else
#define BIH_USEBVH
#endif
typedef struct q2mapsurface_s // used internally due to name len probs //ZOID
{
q2csurface_t c;
char rname[32];
} q2mapsurface_t;
typedef struct
{
mplane_t *plane;
q2mapsurface_t *surface;
} q2cbrushside_t;
typedef struct q2cbrush_s
{
int checkcount; // to avoid repeated testings
int contents;
vec3_t absmins;
vec3_t absmaxs;
int numsides;
q2cbrushside_t *brushside;
} q2cbrush_t;
typedef struct
{
vec3_t absmins, absmaxs;
vecV_t *xyz_array;
size_t numverts;
index_t *indicies;
size_t numincidies;
q2mapsurface_t *surface;
int checkcount; // to avoid repeated testings
} q3cmesh_t;
typedef struct
{
vec3_t absmins, absmaxs;
int numfacets;
q2cbrush_t *facets;
q2mapsurface_t *surface;
int checkcount; // to avoid repeated testings
} q3cpatch_t;
enum bihtype_e
{
//node types
#ifdef BIH_USEBIH
BIH_X,
BIH_Y,
BIH_Z,
#endif
#ifdef BIH_USEBVH
BVH_X,
BVH_Y,
BVH_Z,
#endif
BIH_GROUP,
//leaf types
#ifdef Q2BSPS
BIH_BRUSH,
#endif
#ifdef Q3BSPS
BIH_PATCHBRUSH,
BIH_TRISOUP,
#endif
BIH_TRIANGLE,
};
struct bihdata_s
{
unsigned int contents;
union {
#ifdef Q2BSPS
q2cbrush_t *brush;
#endif
#ifdef Q3BSPS
q2cbrush_t *patchbrush;
q3cmesh_t *cmesh;
#endif
struct {
// vec3_t norm;
index_t *indexes; //might be better to just bake 3 indexes instead of using a pointer to them
vecV_t *xyz;
} tri;
};
};
struct bihleaf_s
{
enum bihtype_e type;
vec3_t mins;
vec3_t maxs;
struct bihdata_s data;
};
struct galiasinfo_s;
//generates a BIH tree and updates mod->funcs.NativeTrace|NativeContents funcs
void BIH_Build (model_t *mod, struct bihleaf_s *items, size_t numitems);
void BIH_BuildAlias (model_t *mod, struct galiasinfo_s *meshes);

View File

@ -1,5 +1,6 @@
#include "quakedef.h" #include "quakedef.h"
#include "com_bih.h"
#include "com_mesh.h" #include "com_mesh.h"
#ifdef __F16C__ #ifdef __F16C__
@ -25,6 +26,9 @@ cvar_t mod_h2holey_bugged = CVARD ("mod_h2holey_bugged", "0", "Hexen2's hole
cvar_t mod_halftexel = CVARD ("mod_halftexel", "1", "Offset texture coords by a half-texel, for compatibility with glquake and the majority of engine forks."); cvar_t mod_halftexel = CVARD ("mod_halftexel", "1", "Offset texture coords by a half-texel, for compatibility with glquake and the majority of engine forks.");
cvar_t mod_nomipmap = CVARD ("mod_nomipmap", "0", "Disables the use of mipmaps on quake1 mdls, consistent with its original software renderer."); cvar_t mod_nomipmap = CVARD ("mod_nomipmap", "0", "Disables the use of mipmaps on quake1 mdls, consistent with its original software renderer.");
#endif #endif
#ifdef MODELFMT_OBJ
cvar_t mod_obj_orientation = CVARD("mod_obj_orientation", "1", "Controls how the model's axis are interpreted.\n0: x=forward, z=up (Quake)\n1: x=forward, y=up\n2: z=forward, y=up");
#endif
static void QDECL r_meshpitch_callback(cvar_t *var, char *oldvalue) static void QDECL r_meshpitch_callback(cvar_t *var, char *oldvalue)
{ {
if (!strcmp(var->string, "-1") || !strcmp(var->string, "1")) if (!strcmp(var->string, "-1") || !strcmp(var->string, "1"))
@ -57,28 +61,22 @@ static void Mod_UpdateCRC(void *ctx, void *data, size_t a, size_t b)
#endif #endif
//Common loader function. //Common loader function.
void Mod_DoCRC(model_t *mod, char *buffer, int buffersize) qboolean Mod_DoCRC(model_t *mod, char *buffer, int buffersize)
{ {
#ifdef HAVE_CLIENT #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)
{ {
unsigned short crc; unsigned int crc = CalcHashInt(&hash_crc16, buffer, buffersize);
qbyte *p;
int len;
QCRC_Init(&crc);
for (len = buffersize, p = buffer; len; len--, p++)
QCRC_ProcessByte(&crc, *p);
COM_AddWork(WG_MAIN, Mod_UpdateCRC, (mod->engineflags & MDLF_PLAYER) ? pmodel_name : emodel_name, NULL, crc, 0);
if (!(mod->engineflags & MDLF_PLAYER)) if (!(mod->engineflags & MDLF_PLAYER))
{ //eyes { //eyes
mod->tainted = (crc != 6967); mod->tainted = (crc != 6967);
} }
COM_AddWork(WG_MAIN, Mod_UpdateCRC, (mod->engineflags & MDLF_PLAYER) ? pmodel_name : emodel_name, NULL, crc, 0);
} }
Validation_FileLoaded(mod->publicname, buffer, buffersize); return Ruleset_FileLoaded(mod->publicname, buffer, buffersize);
#else
return true;
#endif #endif
} }
@ -2649,6 +2647,69 @@ static qboolean Mod_Trace(model_t *model, int forcehullnum, const framestate_t *
return trace->fraction != 1; return trace->fraction != 1;
} }
static unsigned int Mod_Mesh_PointContents(struct model_s *model, const vec3_t axis[3], const vec3_t p)
{ //trisoup doesn't have any actual volumes, thus we can't report anything...
return 0;
}
static int Mod_Mesh_ClusterForPoint(struct model_s *model, const vec3_t point, int *areaout)
{ //trisoup doesn't have any actual pvs, thus we can't report anything...
if (areaout)
*areaout = 0;
return -1;
}
static qbyte *Mod_Mesh_ClusterPVS(struct model_s *model, int cluster, pvsbuffer_t *pvsbuffer, pvsmerge_t merge)
{ //trisoup doesn't have any actual pvs, thus we can't report anything...
return NULL;
}
static unsigned int Mod_Mesh_FatPVS(struct model_s *model, const vec3_t org, pvsbuffer_t *pvsbuffer, qboolean merge)
{ //trisoup doesn't have any actual pvs, thus we can't report anything...
return 0;
}
qboolean Mod_Mesh_EdictInFatPVS(struct model_s *model, const struct pvscache_s *edict, const qbyte *pvs, const int *areas)
{ //trisoup doesn't have any actual pvs, thus we always report visible
return true;
}
void Mod_Mesh_FindTouchedLeafs(struct model_s *model, struct pvscache_s *ent, const vec3_t cullmins, const vec3_t cullmaxs)
{
}
static void Mod_Mesh_LightPointValues(struct model_s *model, const vec3_t point, vec3_t res_diffuse, vec3_t res_ambient, vec3_t res_dir)
{ //trisoup doesn't have any actual pvs, thus we can't report anything...
VectorSet(res_diffuse, 255,255,255);
VectorSet(res_ambient, 128,128,128);
VectorSet(res_dir, 0,0,1);
}
static void Mod_SetMeshModelFuncs(model_t *mod, qboolean isstatic)
{
if (!isstatic)
{
mod->funcs.NativeTrace = Mod_Trace;
return;
}
// void (*PurgeModel) (struct model_s *mod);
mod->funcs.PointContents = Mod_Mesh_PointContents;
// unsigned int (*BoxContents) (struct model_s *model, int hulloverride, const framestate_t *framestate, const vec3_t axis[3], const vec3_t p, const vec3_t mins, const vec3_t maxs);
//deals with whatever is native for the bsp (gamecode is expected to distinguish this).
mod->funcs.NativeTrace = Mod_Trace;
// unsigned int (*NativeContents)(struct model_s *model, int hulloverride, const framestate_t *framestate, const vec3_t axis[3], const vec3_t p, const vec3_t mins, const vec3_t maxs);
mod->funcs.FatPVS = Mod_Mesh_FatPVS;
mod->funcs.EdictInFatPVS = Mod_Mesh_EdictInFatPVS;
mod->funcs.FindTouchedLeafs = Mod_Mesh_FindTouchedLeafs;
mod->funcs.LightPointValues = Mod_Mesh_LightPointValues;
// void (*StainNode) (struct mnode_s *node, float *parms);
// void (*MarkLights) (struct dlight_s *light, dlightbitmask_t bit, struct mnode_s *node);
mod->funcs.ClusterForPoint = Mod_Mesh_ClusterForPoint;
mod->funcs.ClusterPVS = Mod_Mesh_ClusterPVS;
// qbyte *(*ClustersInSphere) (struct model_s *model, const vec3_t point, float radius, pvsbuffer_t *pvsbuffer, const qbyte *fte_restrict unionwith);
BIH_BuildAlias(mod, mod->meshinfo);
}
static void Mod_ClampModelSize(model_t *mod) static void Mod_ClampModelSize(model_t *mod)
{ {
@ -8345,8 +8406,8 @@ static galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, const char *buffer, siz
AddPointToBounds(maxs, mod->mins, mod->maxs); AddPointToBounds(maxs, mod->mins, mod->maxs);
} }
} }
else
AddPointToBounds(vec3_origin, mod->mins, mod->maxs);
ftemesh = IQM_FindExtension(buffer, fsize, "FTE_MESH", 0, &extsize); ftemesh = IQM_FindExtension(buffer, fsize, "FTE_MESH", 0, &extsize);
if (!extsize || extsize != sizeof(*ftemesh)*h->num_meshes) if (!extsize || extsize != sizeof(*ftemesh)*h->num_meshes)
@ -8409,15 +8470,23 @@ static galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, const char *buffer, siz
tris = (const 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; idx = ZG_Malloc(&mod->memgroup, sizeof(*idx)*numtris*3);
idx = ZG_Malloc(&mod->memgroup, sizeof(*idx)*gai[i].numindexes);
gai[i].ofs_indexes = idx; gai[i].ofs_indexes = idx;
for (t = 0; t < numtris; t++) for (t = 0; t < numtris; t++)
{ {
*idx++ = LittleLong(tris[t].vertex[0]) - firstvert; unsigned int a,b,c;
*idx++ = LittleLong(tris[t].vertex[1]) - firstvert; a = LittleLong(tris[t].vertex[0]) - firstvert;
*idx++ = LittleLong(tris[t].vertex[2]) - firstvert; b = LittleLong(tris[t].vertex[1]) - firstvert;
c = LittleLong(tris[t].vertex[2]) - firstvert;
if (a > MAX_INDICIES || b > MAX_INDICIES || c > MAX_INDICIES)
continue; //we can't handle this triangle properly.
*idx++ = a;
*idx++ = b;
*idx++ = c;
} }
gai[i].numindexes = idx - gai[i].ofs_indexes;
if (gai[i].numindexes != numtris*3)
Con_Printf("%s(%s|%s): Dropped %u of %u triangles due to index size limit\n", mod->name, gai[i].surfacename,strings+mesh[i].material, numtris-gai[i].numindexes/3, numtris);
/*verts*/ /*verts*/
gai[i].shares_verts = i; gai[i].shares_verts = i;
@ -8460,9 +8529,9 @@ static galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, const char *buffer, siz
IQM_ImportArrayF(buffer, &vnorm, (float*)onorm1, 3, h->num_vertexes, defaultcolour); IQM_ImportArrayF(buffer, &vnorm, (float*)onorm1, 3, h->num_vertexes, defaultcolour);
IQM_ImportArrayF(buffer, &vpos, (float*)opos, sizeof(opos[0])/sizeof(float), h->num_vertexes, defaultvert); IQM_ImportArrayF(buffer, &vpos, (float*)opos, sizeof(opos[0])/sizeof(float), h->num_vertexes, defaultvert);
//fixme: shouldn't really be needed for an animated model if (!h->ofs_bounds || !h->num_frames)
for (i = 0; i < h->num_vertexes; i++) for (i = 0; i < h->num_vertexes; i++)
AddPointToBounds(opos[i], mod->mins, mod->maxs); AddPointToBounds(opos[i], mod->mins, mod->maxs);
if (vnorm.offset && vtang) if (vnorm.offset && vtang)
{ {
@ -8515,7 +8584,7 @@ static qboolean QDECL Mod_LoadInterQuakeModel(model_t *mod, void *buffer, size_t
mod->numframes = root->numanimations; mod->numframes = root->numanimations;
mod->meshinfo = root; mod->meshinfo = root;
mod->type = mod_alias; mod->type = mod_alias;
mod->funcs.NativeTrace = Mod_Trace; Mod_SetMeshModelFuncs(mod, !root->ofs_skel_idx&&!root->ofs_skel_weight);
return true; return true;
} }
@ -9346,7 +9415,7 @@ struct objattrib_s {
size_t maxlength; size_t maxlength;
float *data; float *data;
}; };
static qboolean parseobjvert(char *s, struct objattrib_s *out) static qboolean parseobjvert(char *s, struct objattrib_s *out, int reorient)
{ {
int i; int i;
float *v; float *v;
@ -9368,6 +9437,23 @@ static qboolean parseobjvert(char *s, struct objattrib_s *out)
} }
for (; i < 3; i++) for (; i < 3; i++)
v[i] = 0; v[i] = 0;
if (reorient)
{
if (reorient == 1)
{ //xzy - DP's orientation.
float z = v[2];
v[2] = v[1];
v[1] = z;
}
else
{ //zxy - match iqmtool (doesn't need negative scaling)
float z = v[2];
v[2] = v[1];
v[1] = v[0];
v[0] = z;
}
}
return true; return true;
} }
@ -9395,6 +9481,7 @@ static galiasinfo_t *Obj_FinishFace(model_t *mod, galiasinfo_t *m, struct objatt
Vector2Clear(m->ofs_st_array[i]); Vector2Clear(m->ofs_st_array[i]);
else else
Vector2Copy(attribs[1].data+3*vert[i].attrib[1], m->ofs_st_array[i]); Vector2Copy(attribs[1].data+3*vert[i].attrib[1], m->ofs_st_array[i]);
m->ofs_st_array[i][1] = 1-m->ofs_st_array[i][1]; //flip y coords.
if (vert[i].attrib[2] >= attribs[2].length) if (vert[i].attrib[2] >= attribs[2].length)
{ {
@ -9437,6 +9524,7 @@ static qboolean QDECL Mod_LoadObjModel(model_t *mod, void *buffer, size_t fsize)
qboolean badinput = false; qboolean badinput = false;
int meshidx = 0; int meshidx = 0;
int reorient = mod_obj_orientation.ival;
ClearBounds(mod->mins, mod->maxs); ClearBounds(mod->mins, mod->maxs);
@ -9448,9 +9536,9 @@ static qboolean QDECL Mod_LoadObjModel(model_t *mod, void *buffer, size_t fsize)
{ {
case '#': continue; case '#': continue;
case 'v': case 'v':
if(isspace(c[1])) badinput |= !parseobjvert(c, &attrib[0]); if(isspace(c[1])) badinput |= !parseobjvert(c, &attrib[0], reorient);
else if(c[1]=='t') badinput |= !parseobjvert(c, &attrib[1]); else if(c[1]=='t') badinput |= !parseobjvert(c, &attrib[1], false);
else if(c[1]=='n') badinput |= !parseobjvert(c, &attrib[2]); else if(c[1]=='n') badinput |= !parseobjvert(c, &attrib[2], reorient);
break; break;
case 'g': case 'g':
{ {
@ -9480,12 +9568,15 @@ static qboolean QDECL Mod_LoadObjModel(model_t *mod, void *buffer, size_t fsize)
namelen = strlen(name); namelen = strlen(name);
while(namelen > 0 && isspace(name[namelen-1])) namelen--; while(namelen > 0 && isspace(name[namelen-1])) namelen--;
Z_Free(matname); if (!matname || strncmp(matname, name, namelen)||matname[namelen])
matname = Z_Malloc(namelen+1); {
memcpy(matname, name, namelen); Z_Free(matname);
matname[namelen] = 0; matname = Z_Malloc(namelen+1);
memcpy(matname, name, namelen);
matname[namelen] = 0;
m = Obj_FinishFace(mod, m, attrib, vert, numverts, elem, &numelems); m = Obj_FinishFace(mod, m, attrib, vert, numverts, elem, &numelems);
}
break; break;
} }
case 's': case 's':
@ -9590,9 +9681,18 @@ static qboolean QDECL Mod_LoadObjModel(model_t *mod, void *buffer, size_t fsize)
} }
Z_ReallocElements((void**)&elem,&maxelems,numelems+1024,sizeof(*elem)); Z_ReallocElements((void**)&elem,&maxelems,numelems+1024,sizeof(*elem));
} }
elem[numelems++] = cur; if (reorient == 1)
elem[numelems++] = prev; {
elem[numelems++] = first; elem[numelems++] = first;
elem[numelems++] = prev;
elem[numelems++] = cur;
}
else
{
elem[numelems++] = cur;
elem[numelems++] = prev;
elem[numelems++] = first;
}
} }
prev = cur; prev = cur;
v++; v++;
@ -9621,7 +9721,9 @@ static qboolean QDECL Mod_LoadObjModel(model_t *mod, void *buffer, size_t fsize)
mod->flags = 0; mod->flags = 0;
mod->type = mod_alias; mod->type = mod_alias;
mod->numframes = 0; mod->numframes = 0;
mod->funcs.NativeTrace = Mod_Trace; Mod_SetMeshModelFuncs(mod, true);
// Con_Printf(CON_WARNING "%s: multi-surface obj files are unoptimised\n", mod->name);
return !!mod->meshinfo; return !!mod->meshinfo;
} }
#endif #endif
@ -9670,6 +9772,7 @@ void Alias_Register(void)
#endif #endif
#ifdef MODELFMT_OBJ #ifdef MODELFMT_OBJ
Mod_RegisterModelFormatText(NULL, "Wavefront Object (obj)", ".obj", Mod_LoadObjModel); Mod_RegisterModelFormatText(NULL, "Wavefront Object (obj)", ".obj", Mod_LoadObjModel);
Cvar_Register(&mod_obj_orientation, NULL);
#endif #endif
#ifndef SERVERONLY #ifndef SERVERONLY

View File

@ -273,7 +273,7 @@ const char *Mod_FrameNameForNum(model_t *model, int surfaceidx, int num);
const char *Mod_SkinNameForNum(model_t *model, int surfaceidx, int num); const char *Mod_SkinNameForNum(model_t *model, int surfaceidx, int num);
qboolean Mod_FrameInfoForNum(model_t *model, int surfaceidx, int num, char **name, int *numframes, float *duration, qboolean *loop); qboolean Mod_FrameInfoForNum(model_t *model, int surfaceidx, int num, char **name, int *numframes, float *duration, qboolean *loop);
void Mod_DoCRC(model_t *mod, char *buffer, int buffersize); qboolean Mod_DoCRC(model_t *mod, char *buffer, int buffersize);
void QDECL Mod_AccumulateTextureVectors(vecV_t *const vc, vec2_t *const tc, vec3_t *nv, vec3_t *sv, vec3_t *tv, const index_t *idx, int numidx, qboolean calcnorms); void QDECL Mod_AccumulateTextureVectors(vecV_t *const vc, vec2_t *const tc, vec3_t *nv, vec3_t *sv, vec3_t *tv, const index_t *idx, int numidx, qboolean calcnorms);
void Mod_AccumulateMeshTextureVectors(mesh_t *mesh); void Mod_AccumulateMeshTextureVectors(mesh_t *mesh);

View File

@ -56,21 +56,7 @@ fte_inlinebody float M_LinearToSRGB(float x, float mag);
#endif #endif
#endif #endif
/* const usercmd_t nullcmd; // guarenteed to be zero
glibc SUCKS. 64bit glibc is depending upon glibc 2.14 because of some implementation-defined copy direction change that breaks flash.
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.
*/
#if defined(__GNUC__) && defined(__amd64__) && defined(__linux__) && !defined(FTE_SDL)
#include <features.h> /* for glibc version */
#if defined(__GLIBC__) && (__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 14)
__asm__(".symver memcpy,memcpy@GLIBC_2.2.5");
__asm__(".symver memmove,memmove@GLIBC_2.2.5");
#endif
#endif
/*end glibc workaround*/
usercmd_t nullcmd; // guarenteed to be zero
entity_state_t nullentitystate; //this is the default state entity_state_t nullentitystate; //this is the default state
@ -914,19 +900,27 @@ void MSG_WriteLong (sizebuf_t *sb, int c)
buf[2] = (c>>16)&0xff; buf[2] = (c>>16)&0xff;
buf[3] = (c>>24)&0xff; buf[3] = (c>>24)&0xff;
} }
void MSG_WriteUInt64 (sizebuf_t *sb, quint64_t c)
{ //0* 10*,*, 110*,*,* etc, up to 0xff followed by 8 continuation bytes
qbyte *buf;
int b = 0;
quint64_t l = 128;
while (c > l-1u)
{ //count the extra bytes we need
b++;
l <<= 7; //each byte we add gains 8 bits, but we spend one on length.
}
buf = (qbyte*)SZ_GetSpace (sb, 1+b);
*buf++ = 0xffu<<(8-b) | (c >> (b*8));
while(b --> 0)
*buf++ = (c >> (b*8))&0xff;
}
void MSG_WriteInt64 (sizebuf_t *sb, qint64_t c) void MSG_WriteInt64 (sizebuf_t *sb, qint64_t c)
{ { //move the sign bit into the low bit and avoid sign extension for more efficient length coding.
qbyte *buf; if (c < 0)
MSG_WriteUInt64(sb, ((quint64_t)(-1-c)<<1)|1);
buf = (qbyte*)SZ_GetSpace (sb, 8); else
buf[0] = c&0xff; MSG_WriteUInt64(sb, c<<1);
buf[1] = (c>>8)&0xff;
buf[2] = (c>>16)&0xff;
buf[3] = (c>>24)&0xff;
buf[4] = (c>>32)&0xff;
buf[5] = (c>>40)&0xff;
buf[6] = (c>>48)&0xff;
buf[7] = (c>>52)&0xff;
} }
void MSG_WriteFloat (sizebuf_t *sb, float f) void MSG_WriteFloat (sizebuf_t *sb, float f)
@ -947,12 +941,21 @@ void MSG_WriteDouble (sizebuf_t *sb, double f)
{ {
union union
{ {
double f; double f;
qint64_t l; quint64_t l;
} dat; } dat = {f};
quint64_t c = dat.l;
qbyte *buf;
dat.f = f; buf = (qbyte*)SZ_GetSpace (sb, 8);
MSG_WriteInt64(sb, dat.l); buf[0] = (c>> 0)&0xff;
buf[1] = (c>> 8)&0xff;
buf[2] = (c>>16)&0xff;
buf[3] = (c>>24)&0xff;
buf[4] = (c>>32)&0xff;
buf[5] = (c>>40)&0xff;
buf[6] = (c>>48)&0xff;
buf[7] = (c>>56)&0xff;
} }
void MSG_WriteString (sizebuf_t *sb, const char *s) void MSG_WriteString (sizebuf_t *sb, const char *s)
@ -1154,7 +1157,7 @@ void MSG_WriteEntity(sizebuf_t *sb, unsigned int entnum)
else else
MSG_WriteShort(sb, entnum); MSG_WriteShort(sb, entnum);
} }
static unsigned int MSG_ReadBigEntity(void) unsigned int MSG_ReadBigEntity(void)
{ {
unsigned int num; unsigned int num;
num = MSG_ReadShort(); num = MSG_ReadShort();
@ -1197,7 +1200,420 @@ unsigned int MSGCL_ReadEntity(void)
} }
#endif #endif
void MSG_WriteDeltaUsercmd (sizebuf_t *buf, usercmd_t *from, usercmd_t *cmd) #if defined(Q2CLIENT) && defined(HAVE_CLIENT)
void MSGQ2_WriteDeltaUsercmd (sizebuf_t *buf, const usercmd_t *from, const usercmd_t *cmd)
{
unsigned int bits = 0;
unsigned char buttons = 0;
if (cmd->angles[0] != from->angles[0])
bits |= Q2CM_ANGLE1;
if (cmd->angles[1] != from->angles[1])
bits |= Q2CM_ANGLE2;
if (cmd->angles[2] != from->angles[2])
bits |= Q2CM_ANGLE3;
if (cmd->forwardmove != from->forwardmove)
bits |= Q2CM_FORWARD;
if (cmd->sidemove != from->sidemove)
bits |= Q2CM_SIDE;
if (cmd->upmove != from->upmove)
bits |= Q2CM_UP;
if (cmd->buttons != from->buttons)
bits |= Q2CM_BUTTONS;
if (cmd->impulse != from->impulse)
bits |= Q2CM_IMPULSE;
if (buf->prim.flags & NPQ2_R1Q2_UCMD)
{
if (bits & Q2CM_ANGLE1)
buttons = cmd->buttons & (1|2|128); //attack, jump, any.
if ((bits & Q2CM_FORWARD) && !(cmd->forwardmove % 5) && abs(cmd->forwardmove/5) < 128)
buttons |= R1Q2_BUTTON_BYTE_FORWARD;
if ((bits & Q2CM_SIDE) && !(cmd->sidemove % 5) && abs(cmd->sidemove/5) < 128)
buttons |= R1Q2_BUTTON_BYTE_SIDE;
if ((bits & Q2CM_UP) && !(cmd->upmove % 5) && abs(cmd->upmove/5) < 128)
buttons |= R1Q2_BUTTON_BYTE_UP;
if ((bits & Q2CM_ANGLE1) && !(cmd->angles[0] % 64) && abs(cmd->angles[0] / 64) < 128)
buttons |= R1Q2_BUTTON_BYTE_ANGLE1;
if ((bits & Q2CM_ANGLE2) && !(cmd->angles[1] % 256))
buttons |= R1Q2_BUTTON_BYTE_ANGLE2;
if (buttons & (R1Q2_BUTTON_BYTE_FORWARD|R1Q2_BUTTON_BYTE_SIDE|R1Q2_BUTTON_BYTE_UP|R1Q2_BUTTON_BYTE_ANGLE1|R1Q2_BUTTON_BYTE_ANGLE2))
bits |= Q2CM_BUTTONS;
}
MSG_WriteByte (buf, bits);
if (buf->prim.flags & NPQ2_R1Q2_UCMD)
{
if (bits & Q2CM_BUTTONS)
MSG_WriteByte (buf, buttons);
}
if (bits & Q2CM_ANGLE1)
{
if (buttons & R1Q2_BUTTON_BYTE_ANGLE1)
MSG_WriteChar (buf, cmd->angles[0] / 64);
else
MSG_WriteShort (buf, cmd->angles[0]);
}
if (bits & Q2CM_ANGLE2)
{
if (buttons & R1Q2_BUTTON_BYTE_ANGLE2)
MSG_WriteChar (buf, cmd->angles[1] / 256);
else
MSG_WriteShort (buf, cmd->angles[1]);
}
if (bits & Q2CM_ANGLE3)
MSG_WriteShort (buf, cmd->angles[2]);
if (bits & Q2CM_FORWARD)
{
if (buttons & R1Q2_BUTTON_BYTE_FORWARD)
MSG_WriteChar (buf, cmd->forwardmove/5);
else
MSG_WriteShort (buf, cmd->forwardmove);
}
if (bits & Q2CM_SIDE)
{
if (buttons & R1Q2_BUTTON_BYTE_SIDE)
MSG_WriteChar (buf, cmd->sidemove/5);
else
MSG_WriteShort (buf, cmd->sidemove);
}
if (bits & Q2CM_UP)
{
if (buttons & R1Q2_BUTTON_BYTE_UP)
MSG_WriteChar (buf, cmd->upmove/5);
else
MSG_WriteShort (buf, cmd->upmove);
}
if (!(buf->prim.flags & NPQ2_R1Q2_UCMD))
{
if (bits & Q2CM_BUTTONS)
MSG_WriteByte (buf, cmd->buttons);
}
if (bits & Q2CM_IMPULSE)
MSG_WriteByte (buf, cmd->impulse);
MSG_WriteByte (buf, bound(0, cmd->msec, 250)); //clamp msecs to 250, because r1q2 likes kicking us if we stall for any reason
MSG_WriteByte (buf, cmd->lightlevel);
}
#endif
#define UC_ANGLE1 (1<<0)
#define UC_ANGLE2 (1<<1)
#define UC_ANGLE3 (1<<2)
#define UC_FORWARD (1<<3)
#define UC_RIGHT (1<<4)
#define UC_BUTTONS (1<<5)
#define UC_IMPULSE (1<<6)
#define UC_UP (1<<7) //split from forward/right because its rare, and this avoids sending an extra byte.
#define UC_ABSANG (1<<8) //angle values are shorts
#define UC_BIGMOVES (1<<9) //fwd/left/up are shorts, rather than a fith.
#define UC_WEAPON (1<<10)
#define UC_CURSORFLDS (1<<11) //lots of data in one.
#define UC_LIGHTLEV (1<<12)
#define UC_VR_HEAD (1<<13)
#define UC_VR_RIGHT (1<<14)
#define UC_VR_LEFT (1<<15)
//#define UC_UNUSED (1<<16)
//#define UC_UNUSED (1<<17)
//#define UC_UNUSED (1<<18)
//#define UC_UNUSED (1<<19)
//#define UC_UNUSED (1<<20)
//#define UC_UNUSED (1<<21)
//#define UC_UNUSED (1<<22)
//#define UC_UNUSED (1<<23)
//#define UC_UNUSED (1<<24)
//#define UC_UNUSED (1<<25)
//#define UC_UNUSED (1<<26)
//#define UC_UNUSED (1<<27)
//#define UC_UNUSED (1<<28)
//#define UC_UNUSED (1<<29)
//#define UC_UNUSED (1<<30)
//#define UC_UNUSED (1<<31)
#define UC_UNSUPPORTED (~(UC_ANGLE1 | UC_ANGLE2 | UC_ANGLE3 | UC_FORWARD | UC_RIGHT | UC_BUTTONS | UC_IMPULSE | UC_UP | UC_ABSANG | UC_BIGMOVES | UC_WEAPON | UC_CURSORFLDS | UC_LIGHTLEV | UC_VR_HEAD | UC_VR_RIGHT | UC_VR_LEFT))
#ifdef HAVE_CLIENT
fte_inlinestatic qboolean MSG_CompareVR(int i, const usercmd_t *from, const usercmd_t *cmd)
{
if (cmd->vr[i].status != from->vr[i].status)
return true;
return
(cmd->vr[i].angles[0] != from->vr[i].angles[0]||cmd->vr[i].angles[1] != from->vr[i].angles[1]||cmd->vr[i].angles[2] != from->vr[i].angles[2])|
(cmd->vr[i].avelocity[0] != from->vr[i].avelocity[0]||cmd->vr[i].avelocity[1] != from->vr[i].avelocity[1]||cmd->vr[i].avelocity[2] != from->vr[i].avelocity[2])|
(cmd->vr[i].origin[0] != from->vr[i].angles[0]||cmd->vr[i].origin[1] != from->vr[i].origin[1]||cmd->vr[i].origin[2] != from->vr[i].origin[2])|
(cmd->vr[i].velocity[0] != from->vr[i].velocity[0]||cmd->vr[i].velocity[1] != from->vr[i].velocity[1]||cmd->vr[i].velocity[2] != from->vr[i].velocity[2]);
}
static void MSG_WriteVR(int i, sizebuf_t *buf, const usercmd_t *from, const usercmd_t *cmd)
{
quint64_t status = cmd->vr[i].status;
status <<= 4;
if (cmd->vr[i].angles[0] != from->vr[i].angles[0] || cmd->vr[i].angles[1] != from->vr[i].angles[1] || cmd->vr[i].angles[2] != from->vr[i].angles[2])
status |= VRSTATUS_ANG;
if (cmd->vr[i].avelocity[0] != from->vr[i].avelocity[0] || cmd->vr[i].avelocity[1] != from->vr[i].avelocity[1] || cmd->vr[i].avelocity[2] != from->vr[i].avelocity[2])
status |= VRSTATUS_AVEL;
if (cmd->vr[i].origin[0] != from->vr[i].origin[0] || cmd->vr[i].origin[1] != from->vr[i].origin[1] || cmd->vr[i].origin[2] != from->vr[i].origin[2])
status |= VRSTATUS_ORG;
if (cmd->vr[i].velocity[0] != from->vr[i].velocity[0] || cmd->vr[i].velocity[1] != from->vr[i].velocity[1] || cmd->vr[i].velocity[2] != from->vr[i].velocity[2])
status |= VRSTATUS_VEL;
MSG_WriteUInt64(buf,status);
if (status & VRSTATUS_ANG)
{
MSG_WriteShort(buf, cmd->vr[i].angles[0]);
MSG_WriteShort(buf, cmd->vr[i].angles[1]);
MSG_WriteShort(buf, cmd->vr[i].angles[2]);
}
if (status & VRSTATUS_AVEL)
{
MSG_WriteShort(buf, cmd->vr[i].avelocity[0]);
MSG_WriteShort(buf, cmd->vr[i].avelocity[1]);
MSG_WriteShort(buf, cmd->vr[i].avelocity[2]);
}
if (status & VRSTATUS_ORG)
{
MSG_WriteFloat(buf, cmd->vr[i].origin[0]);
MSG_WriteFloat(buf, cmd->vr[i].origin[1]);
MSG_WriteFloat(buf, cmd->vr[i].origin[2]);
}
if (status & VRSTATUS_VEL)
{
MSG_WriteFloat(buf, cmd->vr[i].velocity[0]);
MSG_WriteFloat(buf, cmd->vr[i].velocity[1]);
MSG_WriteFloat(buf, cmd->vr[i].velocity[2]);
}
}
void MSGFTE_WriteDeltaUsercmd (sizebuf_t *buf, const usercmd_t *from, const usercmd_t *cmd)
{
unsigned int bits = 0;
int i;
short d;
//
// send the movement message
//
for (i = 0; i < 3; i++)
{
d = cmd->angles[i]-from->angles[i];
if (d)
{
bits |= UC_ANGLE1<<i;
if (d < -128 || d > 127)
bits |= UC_ABSANG; //can't delta it.
}
}
if (cmd->forwardmove != from->forwardmove)
{
bits |= UC_FORWARD;
if ((cmd->forwardmove%5) || cmd->forwardmove > 127*5 || cmd->forwardmove < -128*5)
bits |= UC_BIGMOVES; //can't compact it.
}
if (cmd->sidemove != from->sidemove)
{
bits |= UC_RIGHT;
if ((cmd->sidemove%5) || cmd->sidemove > 127*5 || cmd->sidemove < -128*5)
bits |= UC_BIGMOVES; //can't compact it.
}
if (cmd->upmove != from->upmove)
{
bits |= UC_UP;
if ((cmd->upmove%5) || cmd->upmove > 127*5 || cmd->upmove < -128*5)
bits |= UC_BIGMOVES; //can't compact it.
}
if (cmd->buttons != from->buttons)
bits |= UC_BUTTONS;
if (cmd->buttons != from->buttons)
bits |= UC_WEAPON;
if (cmd->impulse != from->impulse)
bits |= UC_IMPULSE;
if (cmd->lightlevel != from->lightlevel)
bits |= UC_LIGHTLEV;
if (cmd->cursor_screen[0] != from->cursor_screen[0] || cmd->cursor_screen[1] != from->cursor_screen[1] ||
cmd->cursor_start[0] != from->cursor_start[0] || cmd->cursor_start[1] != from->cursor_start[1] || cmd->cursor_start[2] != from->cursor_start[2] ||
cmd->cursor_impact[0] != from->cursor_impact[0] || cmd->cursor_impact[1] != from->cursor_impact[1] || cmd->cursor_impact[2] != from->cursor_impact[2] ||
cmd->cursor_entitynumber != from->cursor_entitynumber)
bits |= UC_CURSORFLDS;
if (MSG_CompareVR(VRDEV_HEAD, from, cmd))
bits |= UC_VR_HEAD;
if (MSG_CompareVR(VRDEV_RIGHT, from, cmd))
bits |= UC_VR_RIGHT;
if (MSG_CompareVR(VRDEV_LEFT, from, cmd))
bits |= UC_VR_LEFT;
//NOTE: WriteUInt64 actually uses some utf-8-like length coding, so its not quite as bloated as it looks.
MSG_WriteUInt64(buf, bits);
MSG_WriteUInt64(buf, cmd->servertime-from->servertime);
for (i = 0; i < 3; i++)
{
if (bits & (UC_ANGLE1<<i))
{
if (bits & UC_ABSANG)
MSG_WriteShort(buf, cmd->angles[i]);
else
MSG_WriteChar(buf, cmd->angles[i]-from->angles[i]);
}
}
if (bits & UC_FORWARD)
{
if (bits & UC_BIGMOVES)
MSG_WriteShort(buf, cmd->forwardmove);
else
MSG_WriteChar(buf, cmd->forwardmove/5);
}
if (bits & UC_RIGHT)
{
if (bits & UC_BIGMOVES)
MSG_WriteShort(buf, cmd->sidemove);
else
MSG_WriteChar(buf, cmd->sidemove/5);
}
if (bits & UC_UP)
{
if (bits & UC_BIGMOVES)
MSG_WriteShort(buf, cmd->upmove);
else
MSG_WriteChar(buf, cmd->upmove/5);
}
if (bits & UC_BUTTONS)
MSG_WriteUInt64 (buf, cmd->buttons);
if (bits & UC_IMPULSE)
MSG_WriteUInt64 (buf, cmd->impulse);
if (bits & UC_WEAPON)
MSG_WriteUInt64 (buf, cmd->weapon);
if (bits & UC_CURSORFLDS)
{
//prydon cursor crap. kinda bloated.
MSG_WriteShort(buf, cmd->cursor_screen[0] * 32767);
MSG_WriteShort(buf, cmd->cursor_screen[1] * 32767);
MSG_WriteFloat(buf, cmd->cursor_start[0]); //avoiding WriteAngle/WriteCoord means we can avoid netprim size difference issues.
MSG_WriteFloat(buf, cmd->cursor_start[1]);
MSG_WriteFloat(buf, cmd->cursor_start[2]);
MSG_WriteFloat(buf, cmd->cursor_impact[0]);
MSG_WriteFloat(buf, cmd->cursor_impact[1]);
MSG_WriteFloat(buf, cmd->cursor_impact[2]);
MSG_WriteEntity(buf, cmd->cursor_entitynumber);
}
if (bits & UC_LIGHTLEV)
MSG_WriteUInt64 (buf, cmd->lightlevel); //yay hdr?
if (bits & UC_VR_HEAD)
MSG_WriteVR(VRDEV_HEAD, buf, from, cmd);
if (bits & UC_VR_RIGHT)
MSG_WriteVR(VRDEV_RIGHT, buf, from, cmd);
if (bits & UC_VR_LEFT)
MSG_WriteVR(VRDEV_LEFT, buf, from, cmd);
}
#endif
#ifdef HAVE_SERVER
static void MSG_ReadVR(int i, usercmd_t *cmd)
{
quint64_t status = MSG_ReadUInt64();
cmd->vr[i].status = status>>4;
if (status & VRSTATUS_ANG)
{
cmd->vr[i].angles[0] = MSG_ReadShort();
cmd->vr[i].angles[1] = MSG_ReadShort();
cmd->vr[i].angles[2] = MSG_ReadShort();
}
if (status & VRSTATUS_AVEL)
{
cmd->vr[i].avelocity[0] = MSG_ReadShort();
cmd->vr[i].avelocity[1] = MSG_ReadShort();
cmd->vr[i].avelocity[2] = MSG_ReadShort();
}
if (status & VRSTATUS_ORG)
{
cmd->vr[i].origin[0] = MSG_ReadFloat();
cmd->vr[i].origin[1] = MSG_ReadFloat();
cmd->vr[i].origin[2] = MSG_ReadFloat();
}
if (status & VRSTATUS_VEL)
{
cmd->vr[i].velocity[0] = MSG_ReadFloat();
cmd->vr[i].velocity[1] = MSG_ReadFloat();
cmd->vr[i].velocity[2] = MSG_ReadFloat();
}
}
void MSGFTE_ReadDeltaUsercmd (const usercmd_t *from, usercmd_t *cmd)
{
int i;
unsigned int bits = MSG_ReadUInt64();
if (bits & UC_UNSUPPORTED)
{
if (!msg_badread)
Con_Printf("MSG_ReadDeltaUsercmdNew: Unsupported bits (%#x)\n", bits&UC_UNSUPPORTED);
msg_badread = true;
return;
}
*cmd = *from;
cmd->servertime = from->servertime+MSG_ReadUInt64();
for (i = 0; i < 3; i++)
{
if (bits & (UC_ANGLE1<<i))
{
if (bits & UC_ABSANG)
cmd->angles[i] = MSG_ReadShort();
else
cmd->angles[i] = from->angles[i]+MSG_ReadChar();
}
}
if (bits & UC_FORWARD)
{
if (bits & UC_BIGMOVES)
cmd->forwardmove = MSG_ReadShort();
else
cmd->forwardmove = MSG_ReadChar()*5;
}
if (bits & UC_RIGHT)
{
if (bits & UC_BIGMOVES)
cmd->sidemove = MSG_ReadShort();
else
cmd->sidemove = MSG_ReadChar()*5;
}
if (bits & UC_UP)
{
if (bits & UC_BIGMOVES)
cmd->upmove = MSG_ReadShort();
else
cmd->upmove = MSG_ReadChar()*5;
}
if (bits & UC_BUTTONS)
cmd->buttons = MSG_ReadUInt64();
if (bits & UC_IMPULSE)
cmd->impulse = MSG_ReadUInt64();
if (bits & UC_WEAPON)
cmd->weapon = MSG_ReadUInt64();
if (bits & UC_CURSORFLDS)
{ //prydon cursor crap. kinda bloated.
cmd->cursor_screen[0] = MSG_ReadShort() / 32767.0;
cmd->cursor_screen[1] = MSG_ReadShort() / 32767.0;
cmd->cursor_start[0] = MSG_ReadFloat(); //avoiding WriteAngle/WriteCoord means we can avoid netprim size difference issues.
cmd->cursor_start[1] = MSG_ReadFloat();
cmd->cursor_start[2] = MSG_ReadFloat();
cmd->cursor_impact[0] = MSG_ReadFloat();
cmd->cursor_impact[1] = MSG_ReadFloat();
cmd->cursor_impact[2] = MSG_ReadFloat();
cmd->cursor_entitynumber = MSG_ReadBigEntity();
}
if (bits & UC_LIGHTLEV)
cmd->lightlevel = MSG_ReadUInt64();
if (bits & UC_VR_HEAD)
MSG_ReadVR(VRDEV_HEAD, cmd);
if (bits & UC_VR_RIGHT)
MSG_ReadVR(VRDEV_RIGHT, cmd);
if (bits & UC_VR_LEFT)
MSG_ReadVR(VRDEV_LEFT, cmd);
}
#endif
void MSGQW_WriteDeltaUsercmd (sizebuf_t *buf, const usercmd_t *from, const usercmd_t *cmd)
{ {
int bits; int bits;
@ -1207,102 +1623,7 @@ void MSG_WriteDeltaUsercmd (sizebuf_t *buf, usercmd_t *from, usercmd_t *cmd)
bits = 0; bits = 0;
#if defined(Q2CLIENT) && defined(HAVE_CLIENT) #if defined(Q2CLIENT) && defined(HAVE_CLIENT)
if (cls_state && cls.protocol == CP_QUAKE2) if (cls_state && cls.protocol == CP_QUAKE2)
{ MSGQ2_WriteDeltaUsercmd(buf, from, cmd);
unsigned char buttons = 0;
if (cmd->angles[0] != from->angles[0])
bits |= Q2CM_ANGLE1;
if (cmd->angles[1] != from->angles[1])
bits |= Q2CM_ANGLE2;
if (cmd->angles[2] != from->angles[2])
bits |= Q2CM_ANGLE3;
if (cmd->forwardmove != from->forwardmove)
bits |= Q2CM_FORWARD;
if (cmd->sidemove != from->sidemove)
bits |= Q2CM_SIDE;
if (cmd->upmove != from->upmove)
bits |= Q2CM_UP;
if (cmd->buttons != from->buttons)
bits |= Q2CM_BUTTONS;
if (cmd->impulse != from->impulse)
bits |= Q2CM_IMPULSE;
if (buf->prim.flags & NPQ2_R1Q2_UCMD)
{
if (bits & Q2CM_ANGLE1)
buttons = cmd->buttons & (1|2|128); //attack, jump, any.
if ((bits & Q2CM_FORWARD) && !(cmd->forwardmove % 5) && abs(cmd->forwardmove/5) < 128)
buttons |= R1Q2_BUTTON_BYTE_FORWARD;
if ((bits & Q2CM_SIDE) && !(cmd->sidemove % 5) && abs(cmd->sidemove/5) < 128)
buttons |= R1Q2_BUTTON_BYTE_SIDE;
if ((bits & Q2CM_UP) && !(cmd->upmove % 5) && abs(cmd->upmove/5) < 128)
buttons |= R1Q2_BUTTON_BYTE_UP;
if ((bits & Q2CM_ANGLE1) && !(cmd->angles[0] % 64) && abs(cmd->angles[0] / 64) < 128)
buttons |= R1Q2_BUTTON_BYTE_ANGLE1;
if ((bits & Q2CM_ANGLE2) && !(cmd->angles[1] % 256))
buttons |= R1Q2_BUTTON_BYTE_ANGLE2;
if (buttons & (R1Q2_BUTTON_BYTE_FORWARD|R1Q2_BUTTON_BYTE_SIDE|R1Q2_BUTTON_BYTE_UP|R1Q2_BUTTON_BYTE_ANGLE1|R1Q2_BUTTON_BYTE_ANGLE2))
bits |= Q2CM_BUTTONS;
}
MSG_WriteByte (buf, bits);
if (buf->prim.flags & NPQ2_R1Q2_UCMD)
{
if (bits & Q2CM_BUTTONS)
MSG_WriteByte (buf, buttons);
}
if (bits & Q2CM_ANGLE1)
{
if (buttons & R1Q2_BUTTON_BYTE_ANGLE1)
MSG_WriteChar (buf, cmd->angles[0] / 64);
else
MSG_WriteShort (buf, cmd->angles[0]);
}
if (bits & Q2CM_ANGLE2)
{
if (buttons & R1Q2_BUTTON_BYTE_ANGLE2)
MSG_WriteChar (buf, cmd->angles[1] / 256);
else
MSG_WriteShort (buf, cmd->angles[1]);
}
if (bits & Q2CM_ANGLE3)
MSG_WriteShort (buf, cmd->angles[2]);
if (bits & Q2CM_FORWARD)
{
if (buttons & R1Q2_BUTTON_BYTE_FORWARD)
MSG_WriteChar (buf, cmd->forwardmove/5);
else
MSG_WriteShort (buf, cmd->forwardmove);
}
if (bits & Q2CM_SIDE)
{
if (buttons & R1Q2_BUTTON_BYTE_SIDE)
MSG_WriteChar (buf, cmd->sidemove/5);
else
MSG_WriteShort (buf, cmd->sidemove);
}
if (bits & Q2CM_UP)
{
if (buttons & R1Q2_BUTTON_BYTE_UP)
MSG_WriteChar (buf, cmd->upmove/5);
else
MSG_WriteShort (buf, cmd->upmove);
}
if (!(buf->prim.flags & NPQ2_R1Q2_UCMD))
{
if (bits & Q2CM_BUTTONS)
MSG_WriteByte (buf, cmd->buttons);
}
if (bits & Q2CM_IMPULSE)
MSG_WriteByte (buf, cmd->impulse);
MSG_WriteByte (buf, bound(0, cmd->msec, 250)); //clamp msecs to 250, because r1q2 likes kicking us if we stall for any reason
MSG_WriteByte (buf, cmd->lightlevel);
}
else else
#endif #endif
{ {
@ -1347,6 +1668,20 @@ void MSG_WriteDeltaUsercmd (sizebuf_t *buf, usercmd_t *from, usercmd_t *cmd)
} }
} }
#ifdef HAVE_CLIENT
void MSGCL_WriteDeltaUsercmd (sizebuf_t *buf, const usercmd_t *from, const usercmd_t *cmd)
{
#if defined(Q2CLIENT)
if (cls_state && cls.protocol == CP_QUAKE2)
MSGQ2_WriteDeltaUsercmd(buf, from, cmd);
else
#endif
if (cls.fteprotocolextensions2 & PEXT2_VRINPUTS)
MSGFTE_WriteDeltaUsercmd(buf, from, cmd);
else
MSGQW_WriteDeltaUsercmd(buf, from, cmd);
}
#endif
// //
// reading functions // reading functions
@ -1611,35 +1946,28 @@ int MSG_ReadLong (void)
return c; return c;
} }
quint64_t MSG_ReadUInt64 (void)
{ //0* 10*,*, 110*,*,* etc, up to 0xff followed by 8 continuation bytes
qbyte l=0x80, v, b = 0;
quint64_t r;
v = MSG_ReadByte();
for (; v&l; l>>=1)
{
v-=l;
b++;
}
r = v<<(b*8);
while(b --> 0)
r |= MSG_ReadByte()<<(b*8);
return r;
}
qint64_t MSG_ReadInt64 (void) qint64_t MSG_ReadInt64 (void)
{ { //we do some fancy bit recoding for more efficient length coding.
qint64_t c; quint64_t c = MSG_ReadUInt64();
if (c&1)
if (net_message.packing!=SZ_RAWBYTES) return -1-(qint64_t)(c>>1);
{ else
c = (unsigned int)MSG_ReadBits(32) return (qint64_t)(c>>1);
| ((qint64_t)(unsigned int)MSG_ReadBits(32)<<32);
return c;
}
if (msg_readcount+4 > net_message.cursize)
{
msg_badread = true;
return -1;
}
c = (net_message.data[msg_readcount+0]<<0)
| (net_message.data[msg_readcount+1]<<8)
| (net_message.data[msg_readcount+2]<<16)
| (net_message.data[msg_readcount+3]<<24)
| ((qint64_t)net_message.data[msg_readcount+5]<<32)
| ((qint64_t)net_message.data[msg_readcount+6]<<40)
| ((qint64_t)net_message.data[msg_readcount+7]<<48)
| ((qint64_t)net_message.data[msg_readcount+8]<<52);
msg_readcount += 8;
return c;
} }
float MSG_ReadFloat (void) float MSG_ReadFloat (void)
@ -1675,14 +2003,30 @@ float MSG_ReadFloat (void)
return dat.f; return dat.f;
} }
double MSG_ReadDouble (void) double MSG_ReadDouble (void)
{ //type-pun it as an int64 over the network for easier handling of endian. {
union union
{ {
double d; quint64_t l;
qint64_t l; double f;
} dat; } dat;
dat.l = MSG_ReadInt64();
return dat.d; if (msg_readcount+8 > net_message.cursize)
{
msg_badread = true;
return -1;
}
dat.l = ( net_message.data[msg_readcount+0]<< 0)|
( net_message.data[msg_readcount+1]<< 8)|
( net_message.data[msg_readcount+2]<<16)|
( net_message.data[msg_readcount+3]<<24)|
((quint64_t)net_message.data[msg_readcount+4]<<32)|
((quint64_t)net_message.data[msg_readcount+5]<<40)|
((quint64_t)net_message.data[msg_readcount+6]<<48)|
((quint64_t)net_message.data[msg_readcount+7]<<56);
msg_readcount += 8;
return dat.f;
} }
char *MSG_ReadStringBuffer (char *out, size_t outsize) char *MSG_ReadStringBuffer (char *out, size_t outsize)
@ -1838,7 +2182,7 @@ float MSG_ReadAngle (void)
} }
} }
void MSG_ReadDeltaUsercmd (usercmd_t *from, usercmd_t *move, int protover) void MSGQW_ReadDeltaUsercmd (const usercmd_t *from, usercmd_t *move, int protover)
{ {
int bits; int bits;
@ -1903,7 +2247,7 @@ void MSG_ReadDeltaUsercmd (usercmd_t *from, usercmd_t *move, int protover)
} }
} }
void MSGQ2_ReadDeltaUsercmd (usercmd_t *from, usercmd_t *move) void MSGQ2_ReadDeltaUsercmd (const usercmd_t *from, usercmd_t *move)
{ {
int bits; int bits;
unsigned int buttons = 0; unsigned int buttons = 0;
@ -2131,7 +2475,7 @@ char *COM_FileExtension (const char *in, char *result, size_t sizeofresult)
for (dot = in + strlen(in); dot >= in && *dot != '.' && *dot != '/' && *dot != '\\'; dot--) for (dot = in + strlen(in); dot >= in && *dot != '.' && *dot != '/' && *dot != '\\'; dot--)
; ;
if (dot < in) if (dot < in || *dot != '.')
{ {
*result = 0; *result = 0;
return result; return result;
@ -6258,18 +6602,20 @@ size_t Base16_EncodeBlock(const char *in, size_t length, qbyte *out, size_t outs
/* /*
Info Buffers Info Buffers
*/ */
const char *basicuserinfos[] = { const char *basicuserinfos[] = //these are used by the client itself, and ignored when the user isn't using csqc.
"*", {
"*", //special: all '*' prefixed keys
"name", "name",
"team", "team",
"skin", "skin",
"topcolor", "topcolor",
"bottomcolor", "bottomcolor",
"chat", //ezquake's afk indicators "chat", //ezquake's afk indicators
NULL}; NULL
const char *privateuserinfos[] = };
const char *privateuserinfos[] = //these can be sent to the server, but must NOT be reported to other clients.
{ {
"_", //ignore comments "_", //special prefix: ignore comments
"password", //many users will forget to clear it after. "password", //many users will forget to clear it after.
"prx", //if someone has this set, don't bother broadcasting it. "prx", //if someone has this set, don't bother broadcasting it.
"*ip", //this is the ip the client used to connect to the server. this isn't useful as any proxy that would affect it can trivially strip/rewrite it anyway. "*ip", //this is the ip the client used to connect to the server. this isn't useful as any proxy that would affect it can trivially strip/rewrite it anyway.
@ -7529,7 +7875,7 @@ qbyte COM_BlockSequenceCRCByte (qbyte *base, int length, int sequence)
length += 4; length += 4;
crc = QCRC_Block(chkb, length); crc = CalcHashInt(&hash_crc16, chkb, length);
crc &= 0xff; crc &= 0xff;
@ -7637,7 +7983,7 @@ qbyte Q2COM_BlockSequenceCRCByte (qbyte *base, int length, int sequence)
length += 4; length += 4;
crc = QCRC_Block(chkb, length); crc = CalcHashInt(&hash_crc16, chkb, length);
for (x=0, n=0; n<length; n++) for (x=0, n=0; n<length; n++)
x += chkb[n]; x += chkb[n];

View File

@ -261,7 +261,7 @@ void COM_SwapLittleShortBlock (short *s, int size);
struct usercmd_s; struct usercmd_s;
extern struct usercmd_s nullcmd; extern const struct usercmd_s nullcmd;
typedef union { //note: reading from packets can be misaligned typedef union { //note: reading from packets can be misaligned
char b[4]; char b[4];
@ -278,6 +278,7 @@ void MSG_WriteByte (sizebuf_t *sb, int c);
void MSG_WriteShort (sizebuf_t *sb, int c); void MSG_WriteShort (sizebuf_t *sb, int c);
void MSG_WriteLong (sizebuf_t *sb, int c); void MSG_WriteLong (sizebuf_t *sb, int c);
void MSG_WriteInt64 (sizebuf_t *sb, qint64_t c); void MSG_WriteInt64 (sizebuf_t *sb, qint64_t c);
void MSG_WriteUInt64 (sizebuf_t *sb, quint64_t c);
void MSG_WriteEntity (sizebuf_t *sb, unsigned int e); void MSG_WriteEntity (sizebuf_t *sb, unsigned int e);
void MSG_WriteFloat (sizebuf_t *sb, float f); void MSG_WriteFloat (sizebuf_t *sb, float f);
void MSG_WriteDouble (sizebuf_t *sb, double f); void MSG_WriteDouble (sizebuf_t *sb, double f);
@ -287,7 +288,9 @@ void MSG_WriteBigCoord (sizebuf_t *sb, float f);
void MSG_WriteAngle (sizebuf_t *sb, float f); void MSG_WriteAngle (sizebuf_t *sb, float f);
void MSG_WriteAngle8 (sizebuf_t *sb, float f); void MSG_WriteAngle8 (sizebuf_t *sb, float f);
void MSG_WriteAngle16 (sizebuf_t *sb, float f); void MSG_WriteAngle16 (sizebuf_t *sb, float f);
void MSG_WriteDeltaUsercmd (sizebuf_t *sb, struct usercmd_s *from, struct usercmd_s *cmd); void MSGFTE_WriteDeltaUsercmd (sizebuf_t *buf, const struct usercmd_s *from, const struct usercmd_s *cmd);
void MSGQW_WriteDeltaUsercmd (sizebuf_t *sb, const struct usercmd_s *from, const struct usercmd_s *cmd);
void MSGCL_WriteDeltaUsercmd (sizebuf_t *sb, const struct usercmd_s *from, const struct usercmd_s *cmd);
void MSG_WriteDir (sizebuf_t *sb, float *dir); void MSG_WriteDir (sizebuf_t *sb, float *dir);
extern int msg_readcount; extern int msg_readcount;
@ -303,9 +306,11 @@ int MSG_ReadByte (void);
int MSG_ReadShort (void); int MSG_ReadShort (void);
int MSG_ReadLong (void); int MSG_ReadLong (void);
qint64_t MSG_ReadInt64 (void); qint64_t MSG_ReadInt64 (void);
quint64_t MSG_ReadUInt64 (void);
struct client_s; struct client_s;
unsigned int MSGSV_ReadEntity (struct client_s *fromclient); unsigned int MSGSV_ReadEntity (struct client_s *fromclient);
unsigned int MSGCL_ReadEntity (void); unsigned int MSGCL_ReadEntity (void);
unsigned int MSG_ReadBigEntity(void);
float MSG_ReadFloat (void); float MSG_ReadFloat (void);
double MSG_ReadDouble (void); double MSG_ReadDouble (void);
char *MSG_ReadStringBuffer (char *out, size_t outsize); char *MSG_ReadStringBuffer (char *out, size_t outsize);
@ -317,8 +322,9 @@ float MSG_ReadCoordFloat (void);
void MSG_ReadPos (float *pos); void MSG_ReadPos (float *pos);
float MSG_ReadAngle (void); float MSG_ReadAngle (void);
float MSG_ReadAngle16 (void); float MSG_ReadAngle16 (void);
void MSG_ReadDeltaUsercmd (struct usercmd_s *from, struct usercmd_s *cmd, int qwprotocolver); void MSGQW_ReadDeltaUsercmd (const struct usercmd_s *from, struct usercmd_s *cmd, int qwprotocolver);
void MSGQ2_ReadDeltaUsercmd (struct usercmd_s *from, struct usercmd_s *move); void MSGFTE_ReadDeltaUsercmd (const struct usercmd_s *from, struct usercmd_s *move);
void MSGQ2_ReadDeltaUsercmd (const struct usercmd_s *from, struct usercmd_s *move);
void MSG_ReadData (void *data, int len); void MSG_ReadData (void *data, int len);
void MSG_ReadSkip (int len); void MSG_ReadSkip (int len);
@ -583,10 +589,11 @@ typedef struct vfsfile_s
#define VFS_ERROR_TRYLATER 0 //nothing to write/read yet. #define VFS_ERROR_TRYLATER 0 //nothing to write/read yet.
#define VFS_ERROR_UNSPECIFIED -1 //no reason given #define VFS_ERROR_UNSPECIFIED -1 //no reason given
#define VFS_ERROR_NORESPONSE -2 //no reason given #define VFS_ERROR_NORESPONSE -2 //no reason given
#define VFS_ERROR_EOF -3 //no reason given #define VFS_ERROR_REFUSED -3 //no reason given
#define VFS_ERROR_DNSFAILURE -4 //weird one, but oh well #define VFS_ERROR_EOF -4 //no reason given
#define VFS_ERROR_WRONGCERT -5 //server gave a certificate with the wrong name #define VFS_ERROR_DNSFAILURE -5 //weird one, but oh well
#define VFS_ERROR_UNTRUSTED -6 //server gave a certificate with the right name, but we don't have a full chain of trust #define VFS_ERROR_WRONGCERT -6 //server gave a certificate with the wrong name
#define VFS_ERROR_UNTRUSTED -7 //server gave a certificate with the right name, but we don't have a full chain of trust
#define VFS_CLOSE(vf) ((vf)->Close(vf)) #define VFS_CLOSE(vf) ((vf)->Close(vf))
#define VFS_TELL(vf) ((vf)->Tell(vf)) #define VFS_TELL(vf) ((vf)->Tell(vf))
@ -679,8 +686,8 @@ typedef struct
enum enum
{ {
MANIFEST_SECURITY_NOT, //don't trust it, don't even allow downloadsurl. MANIFEST_SECURITY_NOT, //don't trust it, don't even allow downloadsurl.
MANIFEST_SECURITY_DEFAULT, //the default.fmf file may suggest packages MANIFEST_SECURITY_DEFAULT, //the default.fmf file may suggest packages+force sources
MANIFEST_SECURITY_INSTALLER //built-in fmf files can force packages MANIFEST_SECURITY_INSTALLER //built-in fmf files can force packages+sources
} security; //manifest was embedded in the engine. don't assume its already installed, but ask to install it (also, enable some extra permissions for writing dlls) } security; //manifest was embedded in the engine. don't assume its already installed, but ask to install it (also, enable some extra permissions for writing dlls)
enum enum
@ -779,6 +786,7 @@ qboolean COM_LoadMapPackFile(const char *name, qofs_t offset);
void COM_FlushTempoaryPacks(void); void COM_FlushTempoaryPacks(void);
void COM_EnumerateFiles (const char *match, int (QDECL *func)(const char *fname, qofs_t fsize, time_t mtime, void *parm, searchpathfuncs_t *spath), void *parm); void COM_EnumerateFiles (const char *match, int (QDECL *func)(const char *fname, qofs_t fsize, time_t mtime, void *parm, searchpathfuncs_t *spath), void *parm);
searchpathfuncs_t *FS_OpenPackByExtension(vfsfile_t *f, searchpathfuncs_t *parent, const char *filename, const char *pakname);
extern qboolean com_installer; //says that the engine is running in an 'installer' mode, and that the correct basedir is not yet known. extern qboolean com_installer; //says that the engine is running in an 'installer' mode, and that the correct basedir is not yet known.
extern struct cvar_s registered; extern struct cvar_s registered;
@ -893,9 +901,12 @@ extern hashfunc_t hash_sha224;
extern hashfunc_t hash_sha256; extern hashfunc_t hash_sha256;
extern hashfunc_t hash_sha384; extern hashfunc_t hash_sha384;
extern hashfunc_t hash_sha512; extern hashfunc_t hash_sha512;
#define HMAC HMAC_quake //stop conflicts... extern hashfunc_t hash_crc16;
size_t CalcHash(hashfunc_t *hash, unsigned char *digest, size_t maxdigestsize, const unsigned char *string, size_t stringlen); extern hashfunc_t hash_crc16_lower;
size_t HMAC(hashfunc_t *hashfunc, unsigned char *digest, size_t maxdigestsize, const unsigned char *data, size_t datalen, const unsigned char *key, size_t keylen); unsigned int hashfunc_terminate_uint(const hashfunc_t *hash, void *context); //terminate, except returning the digest as a uint instead of a blob. folds the digest if longer than 4 bytes.
unsigned int CalcHashInt(const hashfunc_t *hash, const unsigned char *data, size_t datasize);
size_t CalcHash(const hashfunc_t *hash, unsigned char *digest, size_t maxdigestsize, const unsigned char *data, size_t datasize);
size_t CalcHMAC(const hashfunc_t *hashfunc, unsigned char *digest, size_t maxdigestsize, const unsigned char *data, size_t datalen, const unsigned char *key, size_t keylen);
int version_number(void); int version_number(void);
char *version_string(void); char *version_string(void);

View File

@ -20,7 +20,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
/* crc.c */ /* crc.c */
#include "quakedef.h" #include "quakedef.h"
#include "crc.h"
#include <ctype.h> #include <ctype.h>
// this is a 16 bit, non-reflected CRC using the polynomial 0x1021 // this is a 16 bit, non-reflected CRC using the polynomial 0x1021
@ -66,45 +65,51 @@ static unsigned short crctable[256] =
0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
}; };
void QCRC_Init(unsigned short *crcvalue) static void CRC16_Init (void *context)
{ {
*crcvalue = QCRC_INIT_VALUE; unsigned short *ctx = context;
*ctx = QCRC_INIT_VALUE;
} }
static void CRC16_Update (void *context, const void *data, size_t datasize)
void QCRC_ProcessByte(unsigned short *crcvalue, qbyte data)
{ {
*crcvalue = ((*crcvalue << 8)&0xffff) ^ crctable[(*crcvalue >> 8) ^ data]; unsigned short *ctx = context;
} unsigned short crc = *ctx;
const char *start = data;
unsigned short QCRC_Value(unsigned short crcvalue) while (datasize --> 0)
{
return crcvalue ^ QCRC_XOR_VALUE;
}
unsigned short QCRC_Block (const qbyte *start, int count)
{
unsigned short crc;
QCRC_Init (&crc);
while (count--)
crc = ((crc << 8) & 0xffff) ^ crctable[(crc >> 8) ^ *start++]; crc = ((crc << 8) & 0xffff) ^ crctable[(crc >> 8) ^ *start++];
*ctx = crc;
return crc;
} }
static void CRC16_Finish (unsigned char *digest, void *context)
unsigned short QCRC_Block_AsLower (const qbyte *start, int count)
{ {
unsigned short crc; unsigned short *ctx = context;
unsigned short crc = *ctx ^ QCRC_XOR_VALUE;
QCRC_Init (&crc); digest[0] = (crc>>0)&0xff; //digest should be the same regardless of endian. spit it out as little endian.
while (count--) digest[1] = (crc>>8)&0xff;
crc = (crc << 8) ^ crctable[(crc >> 8) ^ tolower(*start++)];
return crc;
} }
hashfunc_t hash_crc16 =
void QCRC_AddBlock (unsigned short *crcvalue, const qbyte *start, int count)
{ {
while (count--) 2,
QCRC_ProcessByte(crcvalue, *start++); 2,
CRC16_Init,
CRC16_Update,
CRC16_Finish,
};
static void CRC16_Update_Lower (void *context, const void *data, size_t datasize)
{
unsigned short *ctx = context;
unsigned short crc = *ctx;
const char *start = data;
while (datasize --> 0)
crc = ((crc << 8) & 0xffff) ^ crctable[(crc >> 8) ^ tolower(*start++)];
*ctx = crc;
} }
hashfunc_t hash_crc16_lower = //a case insensitive version...
{
2,
2,
CRC16_Init,
CRC16_Update_Lower,
CRC16_Finish,
};

View File

@ -1,27 +0,0 @@
/*
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* crc.h */
void QCRC_Init(unsigned short *crcvalue);
void QCRC_AddBlock (unsigned short *crcvalue, const qbyte *start, int count);
void QCRC_ProcessByte(unsigned short *crcvalue, qbyte data);
unsigned short QCRC_Value(unsigned short crcvalue);
unsigned short QCRC_Block (const qbyte *start, int count);
unsigned short QCRC_Block_AsLower (const qbyte *start, int count);

View File

@ -213,7 +213,7 @@ static char *Cvar_FlagToName(int flag)
return "serverinfo"; return "serverinfo";
case CVAR_NOSET: case CVAR_NOSET:
return "noset"; return "noset";
case CVAR_LATCH: case CVAR_MAPLATCH:
return "latch"; return "latch";
case CVAR_POINTER: case CVAR_POINTER:
return "pointer"; return "pointer";
@ -868,7 +868,7 @@ static cvar_t *Cvar_SetCore (cvar_t *var, const char *value, qboolean force)
; ;
else if (0)//var->flags & CVAR_SERVEROVERRIDE && !force) else if (0)//var->flags & CVAR_SERVEROVERRIDE && !force)
latch = "variable %s is under server control - latched\n"; latch = "variable %s is under server control - latched\n";
else if (var->flags & CVAR_LATCH && (sv_state || cls_state)) else if (var->flags & CVAR_MAPLATCH && (sv_state || cls_state))
latch = "variable %s is latched and will be applied for the start of the next map\n"; latch = "variable %s is latched and will be applied for the start of the next map\n";
// else if (var->flags & CVAR_LATCHFLUSH) // else if (var->flags & CVAR_LATCHFLUSH)
// latch = "variable %s is latched (type flush)\n"; // latch = "variable %s is latched (type flush)\n";
@ -1017,12 +1017,12 @@ static cvar_t *Cvar_SetCore (cvar_t *var, const char *value, qboolean force)
return var; return var;
} }
qboolean Cvar_ApplyLatchFlag(cvar_t *var, char *value, int flag) qboolean Cvar_ApplyLatchFlag(cvar_t *var, char *value, unsigned int newflag, unsigned int ignoreflags)
{ {
qboolean result = true; qboolean result = true;
char *latch; char *latch;
var->flags &= ~flag; var->flags &= ~newflag;
latch = var->latched_string; latch = var->latched_string;
var->latched_string = NULL; var->latched_string = NULL;
if (!latch) if (!latch)
@ -1033,10 +1033,11 @@ qboolean Cvar_ApplyLatchFlag(cvar_t *var, char *value, int flag)
latch = Z_StrDup(var->string); latch = Z_StrDup(var->string);
// var->string = NULL; // var->string = NULL;
} }
#ifdef warningmsg
#pragma warningmsg("set or forceset?") ignoreflags = var->flags & ignoreflags; //figure out which latching flags we're ignoring
#endif var->flags -= ignoreflags; //and clear them
Cvar_ForceSet(var, value); Cvar_ForceSet(var, value);
var->flags |= ignoreflags; //give them back.
if (var->latched_string) if (var->latched_string)
{ //something else latched it { //something else latched it
@ -1045,7 +1046,7 @@ qboolean Cvar_ApplyLatchFlag(cvar_t *var, char *value, int flag)
result = false; result = false;
} }
else else
var->flags |= flag; var->flags |= newflag;
if (latch) if (latch)
{ {
@ -1081,7 +1082,12 @@ void Cvar_ForceCheatVars(qboolean semicheats, qboolean absolutecheats)
if (var->flags & CVAR_CHEAT) if (var->flags & CVAR_CHEAT)
{ {
if (!absolutecheats) if (!absolutecheats)
Cvar_ForceSet(var, var->defaultstr); {
if (var->enginevalue)
Cvar_ForceSet(var, var->enginevalue);
else
Cvar_ForceSet(var, var->defaultstr);
}
else else
Cvar_ForceSet(var, latch); Cvar_ForceSet(var, latch);
} }
@ -1105,7 +1111,7 @@ void Cvar_ForceCheatVars(qboolean semicheats, qboolean absolutecheats)
} }
} }
int Cvar_ApplyLatches(int latchflag) int Cvar_ApplyLatches(int latchflag, qboolean clearflag)
{ {
int result = 0; int result = 0;
cvar_group_t *grp; cvar_group_t *grp;
@ -1113,7 +1119,7 @@ int Cvar_ApplyLatches(int latchflag)
int mask = ~0; int mask = ~0;
int of; int of;
if (latchflag == CVAR_SERVEROVERRIDE || latchflag == CVAR_RULESETLATCH) //these ones are cleared if (clearflag) //these flags are cleared from cvars.
mask = ~latchflag; mask = ~latchflag;
for (grp=cvar_groups ; grp ; grp=grp->next) for (grp=cvar_groups ; grp ; grp=grp->next)
@ -1243,7 +1249,7 @@ qboolean Cvar_Register (cvar_t *variable, const char *groupname)
// check to see if it has already been defined // check to see if it has already been defined
old = Cvar_FindVar (variable->name); old = Cvar_FindVar (variable->name);
if (old && variable->name2) if (!old && variable->name2)
old = Cvar_FindVar (variable->name2); old = Cvar_FindVar (variable->name2);
if (old) if (old)
{ {
@ -1419,7 +1425,7 @@ qboolean Cvar_Command (int level)
{ {
if (v->latched_string) if (v->latched_string)
{ {
if (v->flags & CVAR_LATCH) if (v->flags & CVAR_MAPLATCH)
{ {
Con_TPrintf ("\"%s\" is currently \"%s\"\n", v->name, COM_QuotedString(v->string, buffer, sizeof(buffer), true)); Con_TPrintf ("\"%s\" is currently \"%s\"\n", v->name, COM_QuotedString(v->string, buffer, sizeof(buffer), true));
Con_TPrintf ("Will be changed to \"%s\" on the next map\n", COM_QuotedString(v->latched_string, buffer, sizeof(buffer), true)); Con_TPrintf ("Will be changed to \"%s\" on the next map\n", COM_QuotedString(v->latched_string, buffer, sizeof(buffer), true));

View File

@ -60,7 +60,7 @@ typedef struct cvar_s
//must match q2's definition //must match q2's definition
char *name; char *name;
char *string; char *string;
char *latched_string; // for CVAR_LATCH vars char *latched_string; // for CVAR_LATCHMASK vars
unsigned int flags; unsigned int flags;
int modified; // increased each time the cvar is changed int modified; // increased each time the cvar is changed
float value; float value;
@ -116,7 +116,7 @@ typedef struct cvar_group_s
#define CVAR_SERVERINFO (1<<2) // added to serverinfo when changed #define CVAR_SERVERINFO (1<<2) // added to serverinfo when changed
#define CVAR_NOSET (1<<3) // don't allow change from console at all, #define CVAR_NOSET (1<<3) // don't allow change from console at all,
// but can be set from the command line // but can be set from the command line
#define CVAR_LATCH (1<<4) // save changes until server restart #define CVAR_MAPLATCH (1<<4) // save changes until server restart, to avoid q2 gamecode bugging out.
//freestyle //freestyle
#define CVAR_POINTER (1<<5) // q2 style. May be converted to q1 if needed. These are often specified on the command line and then converted into q1 when registered properly. #define CVAR_POINTER (1<<5) // q2 style. May be converted to q1 if needed. These are often specified on the command line and then converted into q1 when registered properly.
@ -143,7 +143,7 @@ typedef struct cvar_group_s
#define CVAR_LASTFLAG CVAR_VIDEOLATCH #define CVAR_LASTFLAG CVAR_VIDEOLATCH
#define CVAR_LATCHMASK (CVAR_LATCH|CVAR_RENDERERLATCH|CVAR_SERVEROVERRIDE|CVAR_CHEAT|CVAR_SEMICHEAT) //you're only allowed one of these. #define CVAR_LATCHMASK (CVAR_MAPLATCH|CVAR_RENDERERLATCH|CVAR_VIDEOLATCH|CVAR_SERVEROVERRIDE|CVAR_CHEAT|CVAR_SEMICHEAT) //you're only allowed one of these.
#define CVAR_NEEDDEFAULT CVAR_CHEAT #define CVAR_NEEDDEFAULT CVAR_CHEAT
//an alias //an alias
@ -166,7 +166,7 @@ void Cvar_ForceSetValue (cvar_t *var, float value);
void Cvar_SetValue (cvar_t *var, float value); void Cvar_SetValue (cvar_t *var, float value);
// expands value to a string and calls Cvar_Set // expands value to a string and calls Cvar_Set
qboolean Cvar_ApplyLatchFlag(cvar_t *var, char *value, int flag); qboolean Cvar_ApplyLatchFlag(cvar_t *var, char *value, unsigned int newflag, unsigned int ignoreflags);
qboolean Cvar_UnsavedArchive(void); qboolean Cvar_UnsavedArchive(void);
void Cvar_Saved(void); void Cvar_Saved(void);
@ -175,8 +175,8 @@ void Cvar_ConfigChanged(void);
extern int cvar_watched; //so that cmd.c knows that it should add messages when configs are execed extern int cvar_watched; //so that cmd.c knows that it should add messages when configs are execed
void Cvar_ParseWatches(void); //parse -watch args void Cvar_ParseWatches(void); //parse -watch args
int Cvar_ApplyLatches(int latchflag); int Cvar_ApplyLatches(int latchflag, qboolean clearflag);
//sets vars to their latched values //sets vars to their latched values (and optionally forgets the cvarflag in question)
void Cvar_Hook(cvar_t *cvar, void (QDECL *callback) (struct cvar_s *var, char *oldvalue)); void Cvar_Hook(cvar_t *cvar, void (QDECL *callback) (struct cvar_s *var, char *oldvalue));
//hook a cvar with a given callback function at runtime //hook a cvar with a given callback function at runtime

View File

@ -16,7 +16,7 @@ void FS_BeginManifestUpdates(void);
static void QDECL fs_game_callback(cvar_t *var, char *oldvalue); static void QDECL fs_game_callback(cvar_t *var, char *oldvalue);
static void COM_InitHomedir(ftemanifest_t *man); static void COM_InitHomedir(ftemanifest_t *man);
hashtable_t filesystemhash; hashtable_t filesystemhash;
qboolean com_fschanged = true; static qboolean com_fschanged = true;
qboolean com_installer = false; qboolean com_installer = false;
qboolean fs_readonly; qboolean fs_readonly;
int waitingformanifest; int waitingformanifest;
@ -24,20 +24,20 @@ static unsigned int fs_restarts;
void *fs_thread_mutex; void *fs_thread_mutex;
float fs_accessed_time; //timestamp of read (does not include flocates, which should normally happen via a cache). float fs_accessed_time; //timestamp of read (does not include flocates, which should normally happen via a cache).
cvar_t com_fs_cache = CVARF("fs_cache", IFMINIMAL("2","1"), CVAR_ARCHIVE); static cvar_t com_fs_cache = CVARF("fs_cache", IFMINIMAL("2","1"), CVAR_ARCHIVE);
cvar_t fs_noreexec = CVARD("fs_noreexec", "0", "Disables automatic re-execing configs on gamedir switches.\nThis means your cvar defaults etc may be from the wrong mod, and cfg_save will leave that stuff corrupted!"); static cvar_t fs_noreexec = CVARD("fs_noreexec", "0", "Disables automatic re-execing configs on gamedir switches.\nThis means your cvar defaults etc may be from the wrong mod, and cfg_save will leave that stuff corrupted!");
cvar_t cfg_reload_on_gamedir = CVAR("cfg_reload_on_gamedir", "1"); static cvar_t cfg_reload_on_gamedir = CVAR("cfg_reload_on_gamedir", "1");
cvar_t fs_game = CVARAFCD("fs_game"/*q3*/, "", "game"/*q2/qs*/, CVAR_NOSAVE|CVAR_NORESET, fs_game_callback, "Provided for Q2 compat."); static cvar_t fs_game = CVARAFCD("fs_game"/*q3*/, "", "game"/*q2/qs*/, CVAR_NOSAVE|CVAR_NORESET, fs_game_callback, "Provided for Q2 compat.");
cvar_t fs_gamedir = CVARFD("fs_gamedir", "", CVAR_NOUNSAFEEXPAND|CVAR_NOSET|CVAR_NOSAVE, "Provided for Q2 compat."); static cvar_t fs_gamedir = CVARFD("fs_gamedir", "", CVAR_NOUNSAFEEXPAND|CVAR_NOSET|CVAR_NOSAVE, "Provided for Q2 compat.");
cvar_t fs_basedir = CVARFD("fs_basedir", "", CVAR_NOUNSAFEEXPAND|CVAR_NOSET|CVAR_NOSAVE, "Provided for Q2 compat."); static cvar_t fs_basedir = CVARFD("fs_basedir", "", CVAR_NOUNSAFEEXPAND|CVAR_NOSET|CVAR_NOSAVE, "Provided for Q2 compat.");
cvar_t dpcompat_ignoremodificationtimes = CVARAFD("fs_packageprioritisation", "1", "dpcompat_ignoremodificationtimes", CVAR_NOUNSAFEEXPAND|CVAR_NOSAVE, "Favours the package that is:\n0: Most recently modified\n1: Is alphabetically last (favour z over a, 9 over 0)."); static cvar_t dpcompat_ignoremodificationtimes = CVARAFD("fs_packageprioritisation", "1", "dpcompat_ignoremodificationtimes", CVAR_NOUNSAFEEXPAND|CVAR_NOSAVE, "Favours the package that is:\n0: Most recently modified\n1: Is alphabetically last (favour z over a, 9 over 0).");
int active_fs_cachetype; int active_fs_cachetype;
static int fs_referencetype; static int fs_referencetype;
int fs_finds; int fs_finds;
void COM_CheckRegistered (void); void COM_CheckRegistered (void);
void Mods_FlushModList(void); void Mods_FlushModList(void);
static qboolean Sys_SteamHasFile(char *basepath, int basepathlen, char *steamdir, char *fname); static qboolean Sys_SteamHasFile(char *basepath, int basepathlen, char *steamdir, char *fname);
static searchpathfuncs_t *FS_OpenPackByExtension(vfsfile_t *f, searchpathfuncs_t *parent, const char *filename, const char *pakname); searchpathfuncs_t *FS_OpenPackByExtension(vfsfile_t *f, searchpathfuncs_t *parent, const char *filename, const char *pakname);
static void QDECL fs_game_callback(cvar_t *var, char *oldvalue) static void QDECL fs_game_callback(cvar_t *var, char *oldvalue)
{ {
@ -52,7 +52,7 @@ static void QDECL fs_game_callback(cvar_t *var, char *oldvalue)
runaway = false; runaway = false;
} }
struct static struct
{ {
void *module; void *module;
const char *extension; const char *extension;
@ -169,16 +169,16 @@ void VARGS VFS_PRINTF(vfsfile_t *vf, const char *format, ...)
char gamedirfile[MAX_OSPATH]; char gamedirfile[MAX_OSPATH];
char pubgamedirfile[MAX_OSPATH]; //like gamedirfile, but not set to the fte-only paths static char pubgamedirfile[MAX_OSPATH]; //like gamedirfile, but not set to the fte-only paths
searchpath_t *gameonly_homedir; static searchpath_t *gameonly_homedir;
searchpath_t *gameonly_gamedir; static searchpath_t *gameonly_gamedir;
char com_gamepath[MAX_OSPATH]; //c:\games\quake char com_gamepath[MAX_OSPATH]; //c:\games\quake
char com_homepath[MAX_OSPATH]; //c:\users\foo\my docs\fte\quake char com_homepath[MAX_OSPATH]; //c:\users\foo\my docs\fte\quake
qboolean com_homepathenabled; qboolean com_homepathenabled;
qboolean com_homepathusable; //com_homepath is safe, even if not enabled. static qboolean com_homepathusable; //com_homepath is safe, even if not enabled.
//char com_configdir[MAX_OSPATH]; //homedir/fte/configs //char com_configdir[MAX_OSPATH]; //homedir/fte/configs
@ -192,9 +192,9 @@ int fs_hash_files;
static const char *FS_GetCleanPath(const char *pattern, qboolean silent, char *outbuf, int outlen); static const char *FS_GetCleanPath(const char *pattern, qboolean silent, char *outbuf, int outlen);
void FS_RegisterDefaultFileSystems(void); static void FS_RegisterDefaultFileSystems(void);
static void COM_CreatePath (char *path); static void COM_CreatePath (char *path);
ftemanifest_t *FS_ReadDefaultManifest(char *newbasedir, size_t newbasedirsize, qboolean fixedbasedir); static ftemanifest_t *FS_ReadDefaultManifest(char *newbasedir, size_t newbasedirsize, qboolean fixedbasedir);
#define ENFORCEFOPENMODE(mode) {if (strcmp(mode, "r") && strcmp(mode, "w")/* && strcmp(mode, "rw")*/)Sys_Error("fs mode %s is not permitted here\n");} #define ENFORCEFOPENMODE(mode) {if (strcmp(mode, "r") && strcmp(mode, "w")/* && strcmp(mode, "rw")*/)Sys_Error("fs mode %s is not permitted here\n");}
@ -900,7 +900,7 @@ ftemanifest_t *FS_Manifest_ReadMod(const char *moddir)
//====================================================================================================== //======================================================================================================
char *fs_loadedcommand; //execed once all packages are (down)loaded static char *fs_loadedcommand; //execed once all packages are (down)loaded
ftemanifest_t *fs_manifest; //currently active manifest. ftemanifest_t *fs_manifest; //currently active manifest.
static searchpath_t *com_searchpaths; static searchpath_t *com_searchpaths;
static searchpath_t *com_purepaths; static searchpath_t *com_purepaths;
@ -2992,7 +2992,7 @@ static void FS_LoadWildDataFiles (filelist_t *list, wildpaks_t *wp)
list->maxfiles = list->maxnames = 0; list->maxfiles = list->maxnames = 0;
} }
static searchpathfuncs_t *FS_OpenPackByExtension(vfsfile_t *f, searchpathfuncs_t *parent, const char *filename, const char *pakname) searchpathfuncs_t *FS_OpenPackByExtension(vfsfile_t *f, searchpathfuncs_t *parent, const char *filename, const char *pakname)
{ {
searchpathfuncs_t *pak; searchpathfuncs_t *pak;
int j; int j;
@ -3740,7 +3740,7 @@ typedef struct {
const char *downloadsurl; const char *downloadsurl;
const char *manifestfile; const char *manifestfile;
} gamemode_info_t; } gamemode_info_t;
const gamemode_info_t gamemode_info[] = { static const gamemode_info_t gamemode_info[] = {
#ifdef GAME_SHORTNAME #ifdef GAME_SHORTNAME
#ifndef GAME_PROTOCOL #ifndef GAME_PROTOCOL
#define GAME_PROTOCOL DISTRIBUTION #define GAME_PROTOCOL DISTRIBUTION
@ -5124,9 +5124,6 @@ void FS_Shutdown(void)
fs_thread_mutex = NULL; fs_thread_mutex = NULL;
Cvar_SetEngineDefault(&fs_gamename, NULL); Cvar_SetEngineDefault(&fs_gamename, NULL);
#ifdef PACKAGEMANAGER
Cvar_SetEngineDefault(&pkg_downloads_url, NULL);
#endif
Cvar_SetEngineDefault(&com_protocolname, NULL); Cvar_SetEngineDefault(&com_protocolname, NULL);
} }
@ -5759,6 +5756,8 @@ qboolean FS_ChangeGame(ftemanifest_t *man, qboolean allowreloadconfigs, qboolean
fs_manifest = man; fs_manifest = man;
#ifdef PACKAGEMANAGER #ifdef PACKAGEMANAGER
PM_Shutdown(true);
if (man->security == MANIFEST_SECURITY_NOT && strcmp(man->downloadsurl?man->downloadsurl:"", olddownloadsurl?olddownloadsurl:"")) if (man->security == MANIFEST_SECURITY_NOT && strcmp(man->downloadsurl?man->downloadsurl:"", olddownloadsurl?olddownloadsurl:""))
{ //make sure we only fuck over the user if this is a 'secure' manifest, and not hacked in some way. { //make sure we only fuck over the user if this is a 'secure' manifest, and not hacked in some way.
Z_Free(man->downloadsurl); Z_Free(man->downloadsurl);
@ -5956,31 +5955,27 @@ qboolean FS_ChangeGame(ftemanifest_t *man, qboolean allowreloadconfigs, qboolean
if (reloadconfigs) if (reloadconfigs)
{ {
Cvar_SetEngineDefault(&fs_gamename, man->formalname?man->formalname:"FTE"); Cvar_SetEngineDefault(&fs_gamename, man->formalname?man->formalname:"FTE");
#ifdef PACKAGEMANAGER
Cvar_SetEngineDefault(&pkg_downloads_url, man->downloadsurl?man->downloadsurl:"");
#endif
Cvar_SetEngineDefault(&com_protocolname, man->protocolname?man->protocolname:"FTE"); Cvar_SetEngineDefault(&com_protocolname, man->protocolname?man->protocolname:"FTE");
//FIXME: flag this instead and do it after a delay? //FIXME: flag this instead and do it after a delay?
Cvar_ForceSet(&fs_gamename, fs_gamename.enginevalue); Cvar_ForceSet(&fs_gamename, fs_gamename.enginevalue);
#ifdef PACKAGEMANAGER
Cvar_ForceSet(&pkg_downloads_url, pkg_downloads_url.enginevalue);
#endif
Cvar_ForceSet(&com_protocolname, com_protocolname.enginevalue); Cvar_ForceSet(&com_protocolname, com_protocolname.enginevalue);
#ifdef HAVE_CLIENT #ifdef HAVE_CLIENT
vidrestart = false; vidrestart = false;
#endif #endif
if (isDedicated)
{
#ifdef HAVE_SERVER #ifdef HAVE_SERVER
if (isDedicated)
SV_ExecInitialConfigs(man->defaultexec?man->defaultexec:""); SV_ExecInitialConfigs(man->defaultexec?man->defaultexec:"");
#endif
}
else else
{
#ifdef HAVE_CLIENT
CL_ExecInitialConfigs(man->defaultexec?man->defaultexec:"");
#endif #endif
#ifdef HAVE_CLIENT
if (1)
CL_ExecInitialConfigs(man->defaultexec?man->defaultexec:"");
else
#endif
{
COM_ParsePlusSets(true);
Cbuf_Execute ();
} }
} }
#ifdef HAVE_CLIENT #ifdef HAVE_CLIENT
@ -6673,6 +6668,13 @@ static void FS_ChangeMod_f(void)
packages++; packages++;
} }
} }
else if (!strcmp(arg, "hash"))
{
if (!packages)
break;
arg = Cmd_Argv(i++);
// packagespaths[packages-1].hash = Z_StrDup(arg);
}
else if (!strcmp(arg, "prefix")) else if (!strcmp(arg, "prefix"))
{ {
if (!packages) if (!packages)
@ -7069,7 +7071,6 @@ void COM_InitFilesystem (void)
Cvar_Register(&com_fs_cache, "Filesystem"); Cvar_Register(&com_fs_cache, "Filesystem");
Cvar_Register(&fs_gamename, "Filesystem"); Cvar_Register(&fs_gamename, "Filesystem");
#ifdef PACKAGEMANAGER #ifdef PACKAGEMANAGER
Cvar_Register(&pkg_downloads_url, "Filesystem");
Cvar_Register(&pkg_autoupdate, "Filesystem"); Cvar_Register(&pkg_autoupdate, "Filesystem");
#endif #endif
Cvar_Register(&com_protocolname, "Server Info"); Cvar_Register(&com_protocolname, "Server Info");

View File

@ -1230,7 +1230,7 @@ static int QDECL FSDZ_GeneratePureCRC(searchpathfuncs_t *handle, int seed, int c
{ {
if (pak->files[i].filelen > 0) if (pak->files[i].filelen > 0)
{ {
filecrcs[numcrcs++] = pak->files[i].filepos ^ pak->files[i].filelen ^ QCRC_Block(pak->files[i].name, sizeof(56)); filecrcs[numcrcs++] = pak->files[i].filepos ^ pak->files[i].filelen ^ CalcHashInt(&hash_crc16, pak->files[i].name, sizeof(56));
} }
} }

View File

@ -154,7 +154,7 @@ static int QDECL FSPAK_EnumerateFiles (searchpathfuncs_t *handle, const char *ma
} }
static int QDECL FSPAK_GeneratePureCRC(searchpathfuncs_t *handle, int seed, int crctype) static int QDECL FSPAK_GeneratePureCRC(searchpathfuncs_t *handle, int seed, int crctype)
{ { //this is really weak. :(
pack_t *pak = (void*)handle; pack_t *pak = (void*)handle;
int result; int result;
@ -169,7 +169,7 @@ static int QDECL FSPAK_GeneratePureCRC(searchpathfuncs_t *handle, int seed, int
{ {
if (pak->files[i].filelen > 0) if (pak->files[i].filelen > 0)
{ {
filecrcs[numcrcs++] = pak->files[i].filepos ^ pak->files[i].filelen ^ QCRC_Block(pak->files[i].name, sizeof(56)); filecrcs[numcrcs++] = pak->files[i].filepos ^ pak->files[i].filelen ^ CalcHashInt(&hash_crc16, pak->files[i].name, sizeof(56));
} }
} }
@ -313,14 +313,12 @@ searchpathfuncs_t *QDECL FSPAK_LoadArchive (vfsfile_t *file, searchpathfuncs_t *
{ {
dpackheader_t header; dpackheader_t header;
int i; int i;
// int j;
mpackfile_t *newfiles; mpackfile_t *newfiles;
int numpackfiles; int numpackfiles;
pack_t *pack; pack_t *pack;
vfsfile_t *packhandle; vfsfile_t *packhandle;
dpackfile_t info; dpackfile_t info;
int read; int read;
// unsigned short crc;
packhandle = file; packhandle = file;
if (packhandle == NULL) if (packhandle == NULL)
@ -341,22 +339,9 @@ searchpathfuncs_t *QDECL FSPAK_LoadArchive (vfsfile_t *file, searchpathfuncs_t *
numpackfiles = header.dirlen / sizeof(dpackfile_t); numpackfiles = header.dirlen / sizeof(dpackfile_t);
// if (numpackfiles > MAX_FILES_IN_PACK)
// Sys_Error ("%s has %i files", packfile, numpackfiles);
// if (numpackfiles != PAK0_COUNT)
// com_modified = true; // not the original file
newfiles = (mpackfile_t*)Z_Malloc (numpackfiles * sizeof(mpackfile_t)); newfiles = (mpackfile_t*)Z_Malloc (numpackfiles * sizeof(mpackfile_t));
VFS_SEEK(packhandle, header.dirofs); VFS_SEEK(packhandle, header.dirofs);
// fread (&info, 1, header.dirlen, packhandle);
// crc the directory to check for modifications
// crc = QCRC_Block((qbyte *)info, header.dirlen);
// QCRC_Init (&crc);
pack = (pack_t*)Z_Malloc (sizeof (pack_t)); pack = (pack_t*)Z_Malloc (sizeof (pack_t));
// parse the directory // parse the directory
@ -370,10 +355,7 @@ searchpathfuncs_t *QDECL FSPAK_LoadArchive (vfsfile_t *file, searchpathfuncs_t *
numpackfiles = i; numpackfiles = i;
break; break;
} }
/*
for (j=0 ; j<sizeof(info) ; j++)
CRC_ProcessByte(&crc, ((qbyte *)&info)[j]);
*/
memcpy(newfiles[i].name, info.name, sizeof(info.name)); memcpy(newfiles[i].name, info.name, sizeof(info.name));
newfiles[i].name[min(sizeof(info.name), MAX_QPATH-1)] = 0; //paranoid newfiles[i].name[min(sizeof(info.name), MAX_QPATH-1)] = 0; //paranoid
COM_CleanUpPath(newfiles[i].name); //blooming tanks. COM_CleanUpPath(newfiles[i].name); //blooming tanks.
@ -381,7 +363,7 @@ searchpathfuncs_t *QDECL FSPAK_LoadArchive (vfsfile_t *file, searchpathfuncs_t *
newfiles[i].filelen = LittleLong(info.filelen); newfiles[i].filelen = LittleLong(info.filelen);
} }
/* /*
if (crc != PAK0_CRC) if (crc != PAK0_CRC || numpackfiles != PAK0_COUNT)
com_modified = true; com_modified = true;
*/ */
strcpy (pack->descname, desc); strcpy (pack->descname, desc);

File diff suppressed because it is too large Load Diff

View File

@ -540,24 +540,15 @@ R_ConcatRotations
*/ */
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])
{ {
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]; out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] + in1[0][2] * in2[2][1];
out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] + out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] + in1[0][2] * in2[2][2];
in1[0][2] * in2[2][1]; out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] + in1[1][2] * in2[2][0];
out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] + out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] + in1[1][2] * in2[2][1];
in1[0][2] * in2[2][2]; out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] + in1[1][2] * in2[2][2];
out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] + out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] + in1[2][2] * in2[2][0];
in1[1][2] * in2[2][0]; out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] + in1[2][2] * in2[2][1];
out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] + out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] + in1[2][2] * in2[2][2];
in1[1][2] * in2[2][1];
out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] +
in1[1][2] * in2[2][2];
out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] +
in1[2][2] * in2[2][0];
out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] +
in1[2][2] * in2[2][1];
out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] +
in1[2][2] * in2[2][2];
} }
/* /*
@ -1084,6 +1075,32 @@ void Matrix4x4_CM_Transform34(const float *matrix, const vec3_t vector, vec4_t p
void Matrix4x4_CM_ModelViewMatrix(float *modelview, const vec3_t viewangles, const vec3_t vieworg) void Matrix4x4_CM_ModelViewMatrix(float *modelview, const vec3_t viewangles, const vec3_t vieworg)
{ {
#if 1
float *out = modelview;
float cp = cos(-viewangles[0] * M_PI / 180.0);
float sp = sin(-viewangles[0] * M_PI / 180.0);
float cy = cos(-viewangles[1] * M_PI / 180.0);
float sy = sin(-viewangles[1] * M_PI / 180.0);
float cr = cos(-viewangles[2] * M_PI / 180.0);
float sr = sin(-viewangles[2] * M_PI / 180.0);
out[0] = -sr*sp*cy - cr*sy;
out[1] = -cr*sp*cy + sr*sy;
out[2] = -cp*cy;
out[3] = 0;
out[4] = sr*sp*sy - cr*cy;
out[5] = cr*sp*sy + sr*cy;
out[6] = cp*sy;
out[7] = 0;
out[8] = sr*cp;
out[9] = cr*cp;
out[10] = -sp;
out[11] = 0;
out[12] = - out[0]*vieworg[0] - out[4]*vieworg[1] - out[ 8]*vieworg[2];
out[13] = - out[1]*vieworg[0] - out[5]*vieworg[1] - out[ 9]*vieworg[2];
out[14] = - out[2]*vieworg[0] - out[6]*vieworg[1] - out[10]*vieworg[2];
out[15] = 1 - out[3]*vieworg[0] - out[7]*vieworg[1] - out[11]*vieworg[2];
#else
float tempmat[16]; float tempmat[16];
//load identity. //load identity.
memset(modelview, 0, sizeof(*modelview)*16); memset(modelview, 0, sizeof(*modelview)*16);
@ -1110,6 +1127,7 @@ void Matrix4x4_CM_ModelViewMatrix(float *modelview, const vec3_t viewangles, con
Matrix4_Multiply(modelview, Matrix4x4_CM_NewRotation(-viewangles[1], 0, 0, 1), tempmat); Matrix4_Multiply(modelview, Matrix4x4_CM_NewRotation(-viewangles[1], 0, 0, 1), tempmat);
Matrix4_Multiply(tempmat, Matrix4x4_CM_NewTranslation(-vieworg[0], -vieworg[1], -vieworg[2]), modelview); // put Z going up Matrix4_Multiply(tempmat, Matrix4x4_CM_NewTranslation(-vieworg[0], -vieworg[1], -vieworg[2]), modelview); // put Z going up
#endif
} }
void Matrix4x4_CM_CreateTranslate (float *out, float x, float y, float z) void Matrix4x4_CM_CreateTranslate (float *out, float x, float y, float z)
@ -1203,6 +1221,36 @@ void Matrix4x4_CM_ModelViewMatrixFromAxis(float *modelview, const vec3_t pn, con
} }
void Matrix3x4_RM_FromAngles(const vec3_t angles, const vec3_t origin, float *out)
{
float angle;
float sr, sp, sy, cr, cp, cy;
angle = angles[YAW] * (M_PI*2 / 360);
sy = sin(angle);
cy = cos(angle);
angle = angles[PITCH] * (M_PI*2 / 360);
sp = sin(angle);
cp = cos(angle);
angle = angles[ROLL] * (M_PI*2 / 360);
sr = sin(angle);
cr = cos(angle);
out[0] = cp*cy;
out[1] = (sr*sp*cy+cr*-sy);
out[2] = (cr*sp*cy+-sr*-sy);
out[3] = origin[0];
out[4] = cp*sy;
out[5] = (sr*sp*sy+cr*cy);
out[6] = (cr*sp*sy+-sr*cy);
out[7] = origin[1];
out[8] = -sp;
out[9] = sr*cp;
out[10] = cr*cp;
out[11] = origin[2];
}
void Matrix3x4_RM_ToVectors(const float *in, float vx[3], float vy[3], float vz[3], float t[3]) void Matrix3x4_RM_ToVectors(const float *in, float vx[3], float vy[3], float vz[3], float t[3])
{ {
vx[0] = in[0]; vx[0] = in[0];

View File

@ -174,6 +174,7 @@ void Matrix4x4_CM_Transform3 (const float *matrix, const float *vector, float *
void Matrix4x4_CM_Transform4 (const float *matrix, const float *vector, float *product); void Matrix4x4_CM_Transform4 (const float *matrix, const float *vector, float *product);
void Matrix4x4_CM_Transform34(const float *matrix, const vec3_t vector, vec4_t product); void Matrix4x4_CM_Transform34(const float *matrix, const vec3_t vector, vec4_t product);
void Matrix4x4_CM_UnProject (const vec3_t in, vec3_t out, const vec3_t viewangles, const vec3_t vieworg, float fovx, float fovy); void Matrix4x4_CM_UnProject (const vec3_t in, vec3_t out, const vec3_t viewangles, const vec3_t vieworg, float fovx, float fovy);
void Matrix3x4_RM_FromAngles(const vec3_t angles, const vec3_t origin, float *out);
void Matrix3x4_RM_FromVectors(float *out, const float vx[3], const float vy[3], const float vz[3], const float t[3]); void Matrix3x4_RM_FromVectors(float *out, const float vx[3], const float vy[3], const float vz[3], const float t[3]);
void Matrix4x4_RM_FromVectors(float *out, const float vx[3], const float vy[3], const float vz[3], const float t[3]); void Matrix4x4_RM_FromVectors(float *out, const float vx[3], const float vy[3], const float vz[3], const float t[3]);
void Matrix3x4_RM_ToVectors(const float *in, float vx[3], float vy[3], float vz[3], float t[3]); void Matrix3x4_RM_ToVectors(const float *in, float vx[3], float vy[3], float vz[3], float t[3]);

View File

@ -276,7 +276,6 @@ typedef struct
extern int net_drop; // packets dropped before this one extern int net_drop; // packets dropped before this one
void Net_Master_Init(void); void Net_Master_Init(void);
qboolean Net_AddressIsMaster(netadr_t *adr);
void Netchan_Init (void); void Netchan_Init (void);
int Netchan_Transmit (netchan_t *chan, int length, qbyte *data, int rate); int Netchan_Transmit (netchan_t *chan, int length, qbyte *data, int rate);
@ -292,7 +291,14 @@ qboolean Netchan_CanPacket (netchan_t *chan, int rate);
void Netchan_Block (netchan_t *chan, int bytes, int rate); void Netchan_Block (netchan_t *chan, int bytes, int rate);
qboolean Netchan_CanReliable (netchan_t *chan, int rate); qboolean Netchan_CanReliable (netchan_t *chan, int rate);
#ifdef NQPROT #ifdef NQPROT
qboolean NQNetChan_Process(netchan_t *chan); enum nqnc_packettype_e
{
NQNC_IGNORED,
NQNC_ACK,
NQNC_RELIABLE,
NQNC_UNRELIABLE,
};
enum nqnc_packettype_e NQNetChan_Process(netchan_t *chan);
#endif #endif
#ifdef HUFFNETWORK #ifdef HUFFNETWORK

View File

@ -89,6 +89,7 @@ cvar_t qport = CVARF("qport_", "0", CVAR_NOSAVE);
cvar_t net_mtu = CVARD("net_mtu", "1440", "Specifies a maximum udp payload size, above which packets will be fragmented. If routers all worked properly this could be some massive value, and some massive value may work really nicely for lans. Use smaller values than the default if you're connecting through nested tunnels through routers that fail with IP fragmentation."); cvar_t net_mtu = CVARD("net_mtu", "1440", "Specifies a maximum udp payload size, above which packets will be fragmented. If routers all worked properly this could be some massive value, and some massive value may work really nicely for lans. Use smaller values than the default if you're connecting through nested tunnels through routers that fail with IP fragmentation.");
cvar_t net_compress = CVARD("net_compress", "0", "Enables huffman compression of network packets."); cvar_t net_compress = CVARD("net_compress", "0", "Enables huffman compression of network packets.");
cvar_t pext_vrinputs = CVARD("_pext_vrinputs", "0", "RENAME ME WHEN STABLE. Networks player inputs slightly differently, allowing for greater capabilities, particuarly vr controller info.");
cvar_t pext_infoblobs = CVARD("_pext_infoblobs", "0", "RENAME ME WHEN STABLE. Enables the use of very large infokeys containing potentially invalid chars. Note that the userinfo is still limited by sv_userinfo_bytelimit and sv_userinfo_keylimit."); cvar_t pext_infoblobs = CVARD("_pext_infoblobs", "0", "RENAME ME WHEN STABLE. Enables the use of very large infokeys containing potentially invalid chars. Note that the userinfo is still limited by sv_userinfo_bytelimit and sv_userinfo_keylimit.");
cvar_t pext_replacementdeltas = CVARD("pext_replacementdeltas", "1", "Enables the use of alternative nack-based entity deltas"); cvar_t pext_replacementdeltas = CVARD("pext_replacementdeltas", "1", "Enables the use of alternative nack-based entity deltas");
cvar_t pext_predinfo = CVARD("pext_predinfo", "1", "Enables some extra things to support prediction over NQ protocols."); cvar_t pext_predinfo = CVARD("pext_predinfo", "1", "Enables some extra things to support prediction over NQ protocols.");
@ -221,6 +222,9 @@ unsigned int Net_PextMask(unsigned int protover, qboolean fornq)
if (pext_infoblobs.ival) if (pext_infoblobs.ival)
mask |= PEXT2_INFOBLOBS; mask |= PEXT2_INFOBLOBS;
if (pext_vrinputs.ival)
mask |= PEXT2_VRINPUTS;
if (MAX_CLIENTS != QWMAX_CLIENTS) if (MAX_CLIENTS != QWMAX_CLIENTS)
mask |= PEXT2_MAXPLAYERS; mask |= PEXT2_MAXPLAYERS;
@ -232,7 +236,7 @@ unsigned int Net_PextMask(unsigned int protover, qboolean fornq)
if (fornq) if (fornq)
{ {
//only ones that are tested //only ones that are tested
mask &= /*PEXT2_PRYDONCURSOR |*/ PEXT2_VOICECHAT | PEXT2_SETANGLEDELTA | PEXT2_REPLACEMENTDELTAS | PEXT2_MAXPLAYERS | PEXT2_PREDINFO | PEXT2_NEWSIZEENCODING; mask &= PEXT2_PRYDONCURSOR | PEXT2_VOICECHAT | PEXT2_SETANGLEDELTA | PEXT2_REPLACEMENTDELTAS | PEXT2_MAXPLAYERS | PEXT2_PREDINFO | PEXT2_NEWSIZEENCODING /*| PEXT2_VRINPUTS - FIXME: do we want multiple per packet, to cover packetloss?*/;
} }
// else // else
// mask &= ~PEXT2_PREDINFO; // mask &= ~PEXT2_PREDINFO;
@ -270,6 +274,7 @@ void Netchan_Init (void)
Cvar_Register (&pext_predinfo, "Protocol Extensions"); Cvar_Register (&pext_predinfo, "Protocol Extensions");
Cvar_Register (&pext_replacementdeltas, "Protocol Extensions"); Cvar_Register (&pext_replacementdeltas, "Protocol Extensions");
Cvar_Register (&pext_infoblobs, "Protocol Extensions"); Cvar_Register (&pext_infoblobs, "Protocol Extensions");
Cvar_Register (&pext_vrinputs, "Protocol Extensions");
Cvar_Register (&showpackets, "Networking"); Cvar_Register (&showpackets, "Networking");
Cvar_Register (&showdrop, "Networking"); Cvar_Register (&showdrop, "Networking");
Cvar_Register (&qport, "Networking"); Cvar_Register (&qport, "Networking");
@ -432,7 +437,7 @@ qboolean ServerPaused(void);
#endif #endif
#ifdef NQPROT #ifdef NQPROT
qboolean NQNetChan_Process(netchan_t *chan) enum nqnc_packettype_e NQNetChan_Process(netchan_t *chan)
{ {
int header; int header;
int sequence; int sequence;
@ -443,10 +448,10 @@ qboolean NQNetChan_Process(netchan_t *chan)
header = LongSwap(MSG_ReadLong()); header = LongSwap(MSG_ReadLong());
if (net_message.cursize != (header & NETFLAG_LENGTH_MASK)) if (net_message.cursize != (header & NETFLAG_LENGTH_MASK))
return false; //size was wrong, couldn't have been ours. return NQNC_IGNORED; //size was wrong, couldn't have been ours.
if (header & NETFLAG_CTL) if (header & NETFLAG_CTL)
return false; //huh? return NQNC_IGNORED; //huh?
sequence = LongSwap(MSG_ReadLong()); sequence = LongSwap(MSG_ReadLong());
@ -483,7 +488,7 @@ qboolean NQNetChan_Process(netchan_t *chan)
, sequence , sequence
, 0); , 0);
return false; //don't try execing the 'payload'. I hate ack packets. return NQNC_ACK; //don't try execing the 'payload'. I hate ack packets.
} }
if (header & NETFLAG_UNRELIABLE) if (header & NETFLAG_UNRELIABLE)
@ -492,7 +497,7 @@ qboolean NQNetChan_Process(netchan_t *chan)
{ {
if (showdrop.ival) if (showdrop.ival)
Con_Printf("Stale datagram recieved (%i<=%i)\n", sequence, chan->incoming_unreliable); Con_Printf("Stale datagram recieved (%i<=%i)\n", sequence, chan->incoming_unreliable);
return false; return NQNC_IGNORED;
} }
drop = sequence - chan->incoming_unreliable - 1; drop = sequence - chan->incoming_unreliable - 1;
if (drop > 0) if (drop > 0)
@ -520,7 +525,7 @@ qboolean NQNetChan_Process(netchan_t *chan)
, chan->sock != NS_SERVER?"s2c":"c2s" , chan->sock != NS_SERVER?"s2c":"c2s"
, chan->incoming_unreliable , chan->incoming_unreliable
, net_message.cursize); , net_message.cursize);
return true; return NQNC_UNRELIABLE;
} }
if (header & NETFLAG_DATA) if (header & NETFLAG_DATA)
{ {
@ -543,7 +548,7 @@ qboolean NQNetChan_Process(netchan_t *chan)
if (chan->in_fragment_length + net_message.cursize-8 >= sizeof(chan->in_fragment_buf)) if (chan->in_fragment_length + net_message.cursize-8 >= sizeof(chan->in_fragment_buf))
{ {
chan->fatal_error = true; chan->fatal_error = true;
return false; return NQNC_IGNORED;
} }
memcpy(chan->in_fragment_buf + chan->in_fragment_length, net_message.data+8, net_message.cursize-8); memcpy(chan->in_fragment_buf + chan->in_fragment_length, net_message.data+8, net_message.cursize-8);
@ -561,7 +566,7 @@ qboolean NQNetChan_Process(netchan_t *chan)
, chan->sock != NS_SERVER?"s2c":"c2s" , chan->sock != NS_SERVER?"s2c":"c2s"
, sequence , sequence
, net_message.cursize); , net_message.cursize);
return true; //we can read it now return NQNC_RELIABLE; //we can read it now
} }
} }
else else
@ -570,10 +575,10 @@ qboolean NQNetChan_Process(netchan_t *chan)
Con_Printf("Stale reliable (%i)\n", sequence); Con_Printf("Stale reliable (%i)\n", sequence);
} }
return false; return NQNC_IGNORED;
} }
return false; //not supported. return NQNC_IGNORED; //not supported.
} }
#endif #endif

View File

@ -477,7 +477,7 @@ static qboolean ICE_SendSpam(struct icestate_s *con)
data[2] = ((buf.cursize+4+sizeof(integ)-20)>>8)&0xff; //hashed header length is up to the end of the hmac attribute data[2] = ((buf.cursize+4+sizeof(integ)-20)>>8)&0xff; //hashed header length is up to the end of the hmac attribute
data[3] = ((buf.cursize+4+sizeof(integ)-20)>>0)&0xff; data[3] = ((buf.cursize+4+sizeof(integ)-20)>>0)&0xff;
//but the hash is to the start of the attribute's header //but the hash is to the start of the attribute's header
HMAC(&hash_sha1, integ, sizeof(integ), data, buf.cursize, con->rpwd, strlen(con->rpwd)); CalcHMAC(&hash_sha1, integ, sizeof(integ), data, buf.cursize, con->rpwd, strlen(con->rpwd));
MSG_WriteShort(&buf, BigShort(0x8)); //MESSAGE-INTEGRITY MSG_WriteShort(&buf, BigShort(0x8)); //MESSAGE-INTEGRITY
MSG_WriteShort(&buf, BigShort(20)); //sha1 key length MSG_WriteShort(&buf, BigShort(20)); //sha1 key length
SZ_Write(&buf, integ, sizeof(integ)); //integrity data SZ_Write(&buf, integ, sizeof(integ)); //integrity data
@ -1523,7 +1523,7 @@ qboolean ICE_WasStun(ftenet_connections_t *col)
char key[20]; char key[20];
//the hmac is a bit weird. the header length includes the integrity attribute's length, but the checksum doesn't even consider the attribute header. //the hmac is a bit weird. the header length includes the integrity attribute's length, but the checksum doesn't even consider the attribute header.
stun->msglen = BigShort(integritypos+sizeof(integrity) - (char*)stun - sizeof(*stun)); stun->msglen = BigShort(integritypos+sizeof(integrity) - (char*)stun - sizeof(*stun));
HMAC(&hash_sha1, key, sizeof(key), (qbyte*)stun, integritypos-4 - (char*)stun, con->lpwd, strlen(con->lpwd)); CalcHMAC(&hash_sha1, key, sizeof(key), (qbyte*)stun, integritypos-4 - (char*)stun, con->lpwd, strlen(con->lpwd));
if (memcmp(key, integrity, sizeof(integrity))) if (memcmp(key, integrity, sizeof(integrity)))
{ {
Con_DPrintf("Integrity is bad! needed %x got %x\n", *(int*)key, *(int*)integrity); Con_DPrintf("Integrity is bad! needed %x got %x\n", *(int*)key, *(int*)integrity);
@ -1690,7 +1690,7 @@ qboolean ICE_WasStun(ftenet_connections_t *col)
data[2] = ((buf.cursize+4+sizeof(integrity)-20)>>8)&0xff; //hashed header length is up to the end of the hmac attribute data[2] = ((buf.cursize+4+sizeof(integrity)-20)>>8)&0xff; //hashed header length is up to the end of the hmac attribute
data[3] = ((buf.cursize+4+sizeof(integrity)-20)>>0)&0xff; data[3] = ((buf.cursize+4+sizeof(integrity)-20)>>0)&0xff;
//but the hash is to the start of the attribute's header //but the hash is to the start of the attribute's header
HMAC(&hash_sha1, integrity, sizeof(integrity), data, buf.cursize, con->lpwd, strlen(con->lpwd)); CalcHMAC(&hash_sha1, integrity, sizeof(integrity), data, buf.cursize, con->lpwd, strlen(con->lpwd));
MSG_WriteShort(&buf, BigShort(0x8)); //MESSAGE-INTEGRITY MSG_WriteShort(&buf, BigShort(0x8)); //MESSAGE-INTEGRITY
MSG_WriteShort(&buf, BigShort(sizeof(integrity))); //sha1 key length MSG_WriteShort(&buf, BigShort(sizeof(integrity))); //sha1 key length
SZ_Write(&buf, integrity, sizeof(integrity)); //integrity data SZ_Write(&buf, integrity, sizeof(integrity)); //integrity data

View File

@ -795,6 +795,11 @@ static ssize_t SSL_Push(gnutls_transport_ptr_t p, const void *data, size_t size)
case VFS_ERROR_DNSFAILURE: case VFS_ERROR_DNSFAILURE:
case VFS_ERROR_NORESPONSE: eno = ECONNRESET; break; case VFS_ERROR_NORESPONSE: eno = ECONNRESET; break;
case VFS_ERROR_TRYLATER: eno = EAGAIN; break; case VFS_ERROR_TRYLATER: eno = EAGAIN; break;
case VFS_ERROR_REFUSED: eno = ECONNREFUSED; break;
// case VFS_ERROR_UNSPECIFIED:
// case VFS_ERROR_DNSFAILURE:
// case VFS_ERROR_WRONGCERT:
// case VFS_ERROR_UNTRUSTED:
default: eno = ECONNRESET; break; default: eno = ECONNRESET; break;
} }
qgnutls_transport_set_errno(file->session, eno); qgnutls_transport_set_errno(file->session, eno);
@ -817,6 +822,7 @@ static ssize_t SSL_Pull(gnutls_transport_ptr_t p, void *data, size_t size)
case VFS_ERROR_DNSFAILURE: case VFS_ERROR_DNSFAILURE:
case VFS_ERROR_NORESPONSE: eno = ECONNRESET; break; case VFS_ERROR_NORESPONSE: eno = ECONNRESET; break;
case VFS_ERROR_TRYLATER: eno = EAGAIN; break; case VFS_ERROR_TRYLATER: eno = EAGAIN; break;
case VFS_ERROR_REFUSED: eno = ECONNREFUSED; break;
default: eno = ECONNRESET; break; default: eno = ECONNRESET; break;
} }
qgnutls_transport_set_errno(file->session, eno); qgnutls_transport_set_errno(file->session, eno);

View File

@ -499,7 +499,44 @@ qboolean NET_CompareBaseAdr (netadr_t *a, netadr_t *b)
return false; return false;
if (a->type != b->type) if (a->type != b->type)
{
int i;
if ((a->type == NA_INVALID || b->type == NA_INVALID) && (a->prot==NP_RTC_TCP||a->prot==NP_RTC_TLS)&&(b->prot==NP_RTC_TCP||b->prot==NP_RTC_TLS))
return true; //broker stuff can be written as /foo which doesn't necessarily have all the info.
if (a->type == NA_IP && b->type == NA_IPV6)
{
for (i = 0; i < 10; i++)
if (b->address.ip6[i] != 0)
return false; //only matches if they're 0s, otherwise its not an ipv4 address there
for (; i < 12; i++)
if (b->address.ip6[i] != 0xff)// && b->address.ip6[i] != 0x00) //0x00 is depricated
return false; //only matches if they're 0s or ffs, otherwise its not an ipv4 address there
for (i = 0; i < 4; i++)
{
if (a->address.ip[i] != b->address.ip6[12+i])
return false; //mask doesn't match
}
return true; //its an ipv4 address in there, the mask matched the whole way through
}
if (a->type == NA_IPV6 && b->type == NA_IP)
{
for (i = 0; i < 10; i++)
if (a->address.ip6[i] != 0)
return false; //only matches if they're 0s, otherwise its not an ipv4 address there
for (; i < 12; i++)
if (a->address.ip6[i] != 0xff)// && a->address.ip6[i] != 0x00) //0x00 is depricated
return false; //only matches if they're 0s or ffs, otherwise its not an ipv4 address there
for (i = 0; i < 4; i++)
{
if (a->address.ip6[12+i] != b->address.ip[i])
return false; //mask doesn't match
}
return true; //its an ipv4 address in there, the mask matched the whole way through
}
return false; return false;
}
if (a->type == NA_LOOPBACK) if (a->type == NA_LOOPBACK)
return true; return true;
@ -2332,7 +2369,10 @@ vfsfile_t *FS_OpenSSL(const char *peername, vfsfile_t *source, qboolean isserver
f = SSPI_OpenVFS(hostname, source, isserver); f = SSPI_OpenVFS(hostname, source, isserver);
#endif #endif
if (!f) //it all failed. if (!f) //it all failed.
{
Con_Printf("%s: no tls provider available\n", peername);
VFS_CLOSE(source); VFS_CLOSE(source);
}
return f; return f;
} }
int TLS_GetChannelBinding(vfsfile_t *stream, qbyte *data, size_t *datasize) int TLS_GetChannelBinding(vfsfile_t *stream, qbyte *data, size_t *datasize)
@ -4188,6 +4228,7 @@ qboolean FTENET_TCP_HTTPResponse(ftenet_tcp_stream_t *st, httparg_t arg[WCATTR_C
const char *resp = NULL; //response headers (no length/gap) const char *resp = NULL; //response headers (no length/gap)
const char *body = NULL; //response body const char *body = NULL; //response body
int method; int method;
net_from = st->remoteaddr;
if (!strcmp(arg[WCATTR_METHOD], "GET")) if (!strcmp(arg[WCATTR_METHOD], "GET"))
method = 0; method = 0;
else if (!strcmp(arg[WCATTR_METHOD], "HEAD")) else if (!strcmp(arg[WCATTR_METHOD], "HEAD"))
@ -4319,7 +4360,7 @@ qboolean FTENET_TCP_HTTPResponse(ftenet_tcp_stream_t *st, httparg_t arg[WCATTR_C
} }
#endif #endif
#if defined(SV_MASTER) && !defined(HAVE_SERVER) #if defined(SV_MASTER) && !defined(HAVE_SERVER)
else if ((st->dlfile=SVM_GenerateIndex(arg[WCATTR_HOST], name))) else if ((st->dlfile=SVM_GenerateIndex(arg[WCATTR_HOST], name, &filetype, query)))
; ;
#endif #endif
#ifdef HAVE_SERVER #ifdef HAVE_SERVER
@ -8888,7 +8929,7 @@ int QDECL VFSTCP_ReadBytes (struct vfsfile_s *file, void *buffer, int bytestorea
break; break;
case NET_ECONNREFUSED: case NET_ECONNREFUSED:
Con_DPrintf("connection to \"%s\" refused\n", tf->peer); Con_DPrintf("connection to \"%s\" refused\n", tf->peer);
tf->readaborted = VFS_ERROR_NORESPONSE; tf->readaborted = VFS_ERROR_REFUSED;
break; break;
case NET_ECONNRESET: case NET_ECONNRESET:
Con_DPrintf("connection to \"%s\" reset\n", tf->peer); Con_DPrintf("connection to \"%s\" reset\n", tf->peer);
@ -8962,10 +9003,17 @@ int QDECL VFSTCP_WriteBytes (struct vfsfile_s *file, const void *buffer, int byt
case NET_ETIMEDOUT: case NET_ETIMEDOUT:
Con_Printf("connection to \"%s\" timed out\n", tf->peer); Con_Printf("connection to \"%s\" timed out\n", tf->peer);
return VFS_ERROR_NORESPONSE; //don't bother trying to read if we never connected. return VFS_ERROR_NORESPONSE; //don't bother trying to read if we never connected.
case NET_ECONNABORTED: case NET_ECONNREFUSED: //peer sent a reset instead of accepting a new connection
Con_DPrintf("connection to \"%s\" refused\n", tf->peer);
return VFS_ERROR_REFUSED; //don't bother trying to read if we never connected.
case NET_ECONNABORTED: //peer closed its socket
Con_Printf("connection to \"%s\" aborted\n", tf->peer); Con_Printf("connection to \"%s\" aborted\n", tf->peer);
reason = len?VFS_ERROR_NORESPONSE:VFS_ERROR_EOF; reason = len?VFS_ERROR_NORESPONSE:VFS_ERROR_EOF;
break; break;
case NET_ECONNRESET: //'peer' claims no knowledge (rebooted?) or forcefully closed
Con_DPrintf("connection to \"%s\" reset\n", tf->peer);
reason = VFS_ERROR_EOF;
break;
case NET_ENOTCONN: case NET_ENOTCONN:
#ifdef __unix__ #ifdef __unix__
case EPIPE: case EPIPE:

View File

@ -1919,6 +1919,8 @@ static void *QDECL PlugBI_GetEngineInterface(const char *interfacename, size_t s
M_FindKeysForBind, M_FindKeysForBind,
Plug_Key_GetKeyBind, Plug_Key_GetKeyBind,
Plug_Key_SetKeyBind, Plug_Key_SetKeyBind,
IN_SetHandPosition,
}; };
if (structsize == sizeof(funcs)) if (structsize == sizeof(funcs))
return &funcs; return &funcs;
@ -1959,7 +1961,7 @@ static void *QDECL PlugBI_GetEngineInterface(const char *interfacename, size_t s
return &iceapi; return &iceapi;
#endif #endif
#ifdef USERBE #ifdef USERBE
if (!strcmp(interfacename, "RBE")) if (!strcmp(interfacename, plugrbefuncs_name))
{ {
static rbeplugfuncs_t funcs = static rbeplugfuncs_t funcs =
{ {
@ -1995,7 +1997,7 @@ static void *QDECL PlugBI_GetEngineInterface(const char *interfacename, size_t s
} }
#endif #endif
#ifdef SKELETALMODELS #ifdef SKELETALMODELS
if (!strcmp(interfacename, "Models")) if (!strcmp(interfacename, plugmodfuncs_name))
{ {
static plugmodfuncs_t funcs = static plugmodfuncs_t funcs =
{ {
@ -2032,7 +2034,7 @@ static void *QDECL PlugBI_GetEngineInterface(const char *interfacename, size_t s
#endif #endif
#ifdef TERRAIN #ifdef TERRAIN
if (!strcmp(interfacename, "Terrain")) if (!strcmp(interfacename, /*plugterrainfuncs_name*/"Terrain"))
return Terr_GetTerrainFuncs(structsize); return Terr_GetTerrainFuncs(structsize);
#endif #endif

View File

@ -1222,7 +1222,7 @@ static void PM_NudgePosition (void)
vec3_t base; vec3_t base;
int x, y, z; int x, y, z;
int i; int i;
static float sign[5] = {0, -1/8.0, 1/8.0, -2/8.0, 2/8.0}; static float sign[] = {0, -1/8.0, 1/8.0};
//really we want to just use this here //really we want to just use this here
//base[i] = MSG_FromCoord(MSG_ToCoord(pmove.origin[i], movevars.coordsize), movevars.coordsize); //base[i] = MSG_FromCoord(MSG_ToCoord(pmove.origin[i], movevars.coordsize), movevars.coordsize);
@ -1240,10 +1240,20 @@ static void PM_NudgePosition (void)
{ {
for (i=0 ; i<3 ; i++) for (i=0 ; i<3 ; i++)
{ {
if (pmove.origin[i] >= 0) if (pmove.velocity[i])
base[i] = (qintptr_t)(pmove.origin[i]*8+0.5f) / 8.0; { //round in the direction of velocity, which means we're less likely to get stuck.
if (pmove.velocity[i] >= 0)
base[i] = (qintptr_t)(pmove.origin[i]*8+0.5f) / 8.0;
else
base[i] = (qintptr_t)(pmove.origin[i]*8-0.5f) / 8.0;
}
else else
base[i] = (qintptr_t)(pmove.origin[i]*8-0.5f) / 8.0; {
if (pmove.origin[i] >= 0)
base[i] = (qintptr_t)(pmove.origin[i]*8+0.5f) / 8.0;
else
base[i] = (qintptr_t)(pmove.origin[i]*8-0.5f) / 8.0;
}
} }
} }
else for (i=0 ; i<3 ; i++) else for (i=0 ; i<3 ; i++)
@ -1256,6 +1266,8 @@ static void PM_NudgePosition (void)
// if (PM_TestPlayerPosition (pmove.origin, false)) // if (PM_TestPlayerPosition (pmove.origin, false))
// return; // return;
//this is potentially 27 tests, and required for qw compat...
//with unquantized floors it often succeeds only after 19 checks. which sucks.
for (z=0 ; z<countof(sign) ; z++) for (z=0 ; z<countof(sign) ; z++)
{ {
for (x=0 ; x<countof(sign) ; x++) for (x=0 ; x<countof(sign) ; x++)
@ -1271,6 +1283,20 @@ static void PM_NudgePosition (void)
} }
} }
//still not managed it... be more agressive axially.
for (z=0 ; z<3; z++)
{
VectorCopy(base, pmove.origin);
pmove.origin[z] = base[z] + (2/8.0);
if (PM_TestPlayerPosition (pmove.origin, false))
return;
VectorCopy(base, pmove.origin);
pmove.origin[z] = base[z] - (2/8.0);
if (PM_TestPlayerPosition (pmove.origin, false))
return;
}
//be more aggresssive at moving up, to match NQ //be more aggresssive at moving up, to match NQ
for (z=1 ; z<movevars.stepheight ; z++) for (z=1 ; z<movevars.stepheight ; z++)
{ {

View File

@ -29,7 +29,7 @@ cvar_t dpcompat_strcat_limit = CVARD("dpcompat_strcat_limit", "", "When set, cri
cvar_t pr_autocreatecvars = CVARD("pr_autocreatecvars", "1", "Implicitly create any cvars that don't exist when read."); cvar_t pr_autocreatecvars = CVARD("pr_autocreatecvars", "1", "Implicitly create any cvars that don't exist when read.");
cvar_t pr_droptofloorunits = CVARD("pr_droptofloorunits", "256", "Distance that droptofloor is allowed to drop to be considered successul."); cvar_t pr_droptofloorunits = CVARD("pr_droptofloorunits", "256", "Distance that droptofloor is allowed to drop to be considered successul.");
cvar_t pr_brokenfloatconvert = CVAR("pr_brokenfloatconvert", "0"); cvar_t pr_brokenfloatconvert = CVAR("pr_brokenfloatconvert", "0");
cvar_t pr_fixbrokenqccarrays = CVARFD("pr_fixbrokenqccarrays", "0", CVAR_LATCH, "As part of its nq/qw/h2/csqc support, FTE remaps QC fields to match an internal order. This is a faster way to handle extended fields. However, some QCCs are buggy and don't report all field defs.\n0: do nothing. QCC must be well behaved.\n1: Duplicate engine fields, remap the ones we can to known offsets. This is sufficient for QCCX/FrikQCC mods that use hardcoded or even occasional calculated offsets (fixes ktpro).\n2: Scan the mod for field accessing instructions, and assume those are the fields (and that they don't alias non-fields). This can be used to work around gmqcc's WTFs (fixes xonotic)."); cvar_t pr_fixbrokenqccarrays = CVARFD("pr_fixbrokenqccarrays", "0", CVAR_MAPLATCH, "As part of its nq/qw/h2/csqc support, FTE remaps QC fields to match an internal order. This is a faster way to handle extended fields. However, some QCCs are buggy and don't report all field defs.\n0: do nothing. QCC must be well behaved.\n1: Duplicate engine fields, remap the ones we can to known offsets. This is sufficient for QCCX/FrikQCC mods that use hardcoded or even occasional calculated offsets (fixes ktpro).\n2: Scan the mod for field accessing instructions, and assume those are the fields (and that they don't alias non-fields). This can be used to work around gmqcc's WTFs (fixes xonotic).");
cvar_t pr_tempstringcount = CVARD("pr_tempstringcount", "", "Obsolete. Set to 16 if you want to recycle+reuse the same 16 tempstring references and break lots of mods."); cvar_t pr_tempstringcount = CVARD("pr_tempstringcount", "", "Obsolete. Set to 16 if you want to recycle+reuse the same 16 tempstring references and break lots of mods.");
cvar_t pr_tempstringsize = CVARD("pr_tempstringsize", "4096", "Obsolete"); cvar_t pr_tempstringsize = CVARD("pr_tempstringsize", "4096", "Obsolete");
#ifdef MULTITHREAD #ifdef MULTITHREAD
@ -1526,7 +1526,7 @@ void QCBUILTIN PF_FindList (pubprogfuncs_t *prinst, struct globalvars_s *pr_glob
ed = WEDICT_NUM_PB(prinst, e); ed = WEDICT_NUM_PB(prinst, e);
if (ED_ISFREE(ed)) if (ED_ISFREE(ed))
continue; continue;
if (*(double*)((pvec_t*)ed->v+f) == s) if (*(pdouble_t*)((pvec_t*)ed->v+f) == s)
list[found++] = EDICT_TO_PROG(prinst, ed); list[found++] = EDICT_TO_PROG(prinst, ed);
} }
} }
@ -1788,17 +1788,20 @@ void QCBUILTIN PF_memcpy (pubprogfuncs_t *prinst, struct globalvars_s *pr_global
else else
memmove(prinst->stringtable + dst, prinst->stringtable + src, size); memmove(prinst->stringtable + dst, prinst->stringtable + src, size);
} }
void *PR_PointerToNative_Resize(pubprogfuncs_t *inst, pint_t ptr, size_t offset, size_t datasize);
void QCBUILTIN PF_memfill8 (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) void QCBUILTIN PF_memfill8 (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{ {
int dst = G_INT(OFS_PARM0); int dst = G_INT(OFS_PARM0);
int val = G_INT(OFS_PARM1); int val = G_INT(OFS_PARM1);
int size = G_INT(OFS_PARM2); int size = G_INT(OFS_PARM2);
if (size < 0 || size > prinst->stringtablesize) int dstoffset = (prinst->callargc>3)?G_INT(OFS_PARM3):0;
PR_BIError(prinst, "PF_memcpy: invalid size\n");
else if (dst < 0 || dst+size > prinst->stringtablesize) void *ptr = PR_PointerToNative_Resize(prinst, dst, dstoffset, size);
PR_BIError(prinst, "PF_memfill8: invalid dest\n"); if (ptr)
memset(ptr, val, size);
else else
memset(prinst->stringtable + dst, val, size); PR_BIError(prinst, "PF_memfill8: invalid dest\n");
} }
void QCBUILTIN PF_memptradd (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) void QCBUILTIN PF_memptradd (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
@ -5291,9 +5294,9 @@ void QCBUILTIN PF_crc16 (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals
int len = strlen(str); int len = strlen(str);
if (insens) if (insens)
G_FLOAT(OFS_RETURN) = QCRC_Block_AsLower(str, len); G_FLOAT(OFS_RETURN) = CalcHashInt(&hash_crc16_lower, str, len);
else else
G_FLOAT(OFS_RETURN) = QCRC_Block(str, len); G_FLOAT(OFS_RETURN) = CalcHashInt(&hash_crc16, str, len);
} }
static void QCBUILTIN PF_digest_internal (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals, const char *hashtype, const void *str, size_t len) static void QCBUILTIN PF_digest_internal (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals, const char *hashtype, const void *str, size_t len)
@ -5319,10 +5322,7 @@ static void QCBUILTIN PF_digest_internal (pubprogfuncs_t *prinst, struct globalv
else if (!strcmp(hashtype, "SHA512")) else if (!strcmp(hashtype, "SHA512"))
digestsize = CalcHash(&hash_sha512, digest, sizeof(digest), str, len); digestsize = CalcHash(&hash_sha512, digest, sizeof(digest), str, len);
else if (!strcmp(hashtype, "CRC16")) else if (!strcmp(hashtype, "CRC16"))
{ digestsize = CalcHash(&hash_crc16, digest, sizeof(digest), str, len);
digestsize = 2;
*(unsigned short*)digest = QCRC_Block(str, len);
}
else else
digestsize = 0; digestsize = 0;
@ -6364,17 +6364,17 @@ void QCBUILTIN PF_rotatevectorsbyangles (pubprogfuncs_t *prinst, struct globalva
void QCBUILTIN PF_rotatevectorsbymatrix (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) void QCBUILTIN PF_rotatevectorsbymatrix (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{ {
world_t *w = prinst->parms->user; world_t *w = prinst->parms->user;
vec3_t src[3], trans[3], res[3]; vec3_t base[3], trans[3], res[3];
VectorCopy(G_VECTOR(OFS_PARM0), src[0]); VectorCopy(G_VECTOR(OFS_PARM0), base[0]);
VectorNegate(G_VECTOR(OFS_PARM1), src[1]); VectorNegate(G_VECTOR(OFS_PARM1), base[1]);
VectorCopy(G_VECTOR(OFS_PARM2), src[2]); VectorCopy(G_VECTOR(OFS_PARM2), base[2]);
VectorCopy(w->g.v_forward, src[0]); VectorCopy(w->g.v_forward, trans[0]);
VectorNegate(w->g.v_right, src[1]); VectorNegate(w->g.v_right, trans[1]);
VectorCopy(w->g.v_up, src[2]); VectorCopy(w->g.v_up, trans[2]);
R_ConcatRotations(trans, src, res); R_ConcatRotations(trans, base, res);
VectorCopy(res[0], w->g.v_forward); VectorCopy(res[0], w->g.v_forward);
VectorNegate(res[1], w->g.v_right); VectorNegate(res[1], w->g.v_right);
@ -6580,7 +6580,7 @@ void QCBUILTIN PF_gettime (pubprogfuncs_t *prinst, struct globalvars_s *pr_globa
G_FLOAT(OFS_RETURN) = realtime; G_FLOAT(OFS_RETURN) = realtime;
break; break;
case 1: //actual time, ish. we round to milliseconds to reduce spectre exposure case 1: //actual time, ish. we round to milliseconds to reduce spectre exposure
G_FLOAT(OFS_RETURN) = (qint64_t)Sys_Milliseconds(); G_FLOAT(OFS_RETURN) = (qint64_t)Sys_Milliseconds()/1000.0;
break; break;
//case 2: //highres.. looks like time into the frame //case 2: //highres.. looks like time into the frame
//case 3: //uptime //case 3: //uptime
@ -6788,12 +6788,15 @@ noflags:
{ {
switch(*s) switch(*s)
{ {
case 'h': isfloat = 1; break; case 'h': isfloat = 1; break; //short in C, interpreted as float here. doubled for char.
case 'l': isfloat = 0; break; case 'l': isfloat = 0; break; //long, twice for long long... we interpret as int32.
case 'L': isfloat = 0; break; case 'L': isfloat = 0; break; //'long double'
case 'j': break; //case 'q': isfloat = 0; break; //synonym for long long.
case 'z': break; case 'j': break; //intmax_t
case 't': break; //case 'Z': //synonym for 'z'. do not use
case 'z': break; //size_t
case 't': break; //ptrdiff_t
default: default:
goto nolength; goto nolength;
} }
@ -6853,7 +6856,7 @@ nolength:
switch(*s) switch(*s)
{ {
case 'd': case 'i': case 'I': case 'd': case 'i': case 'I':
if(precision < 0) // not set if(precision < 0) // not set
Q_snprintfz(o, end - o, formatbuf, width, (isfloat ? (int) GETARG_FLOAT(thisarg) : (int) GETARG_INT(thisarg))); Q_snprintfz(o, end - o, formatbuf, width, (isfloat ? (int) GETARG_FLOAT(thisarg) : (int) GETARG_INT(thisarg)));
else else
@ -7414,70 +7417,69 @@ void PR_ProgsAdded(pubprogfuncs_t *prinst, int newprogs, const char *modulename)
QCLoadBreakpoints("", modulename); QCLoadBreakpoints("", modulename);
} }
#define NOBI 0, NULL, {NULL}, static qboolean check_pext_rpd (extcheck_t *extcheck, unsigned int pext1) {return (extcheck->pext1 & pext1) || (extcheck->pext2&PEXT2_REPLACEMENTDELTAS);}
lh_extension_t QSG_Extensions[] = {
//as a special hack, the first 32 entries are PEXT features. static qboolean check_pext_setview (extcheck_t *extcheck) {return !!(extcheck->pext1 & PEXT_SETVIEW);}
//some of these are overkill yes, but they are all derived from the fteextensions flags and document the underlaying protocol available. static qboolean check_pext_scale (extcheck_t *extcheck) {return check_pext_rpd(extcheck,PEXT_SCALE);}
//(which is why there are two lists of extensions here) static qboolean check_pext_lightstylecol (extcheck_t *extcheck) {return !!(extcheck->pext1 & PEXT_LIGHTSTYLECOL);}
//note: not all of these are actually supported. This list mearly reflects the values of the PEXT_ constants. static qboolean check_pext_trans (extcheck_t *extcheck) {return check_pext_rpd(extcheck,PEXT_TRANS);}
//Check protocol.h to make sure that the related PEXT is enabled. The engine will only accept if they are actually supported. static qboolean check_pext_view2 (extcheck_t *extcheck) {return !!(extcheck->pext1 & PEXT_VIEW2_);}
{"FTE_PEXT_SETVIEW", 0, NULL, {NULL}, "NQ's svc_setview works correctly even in quakeworld"}, //static qboolean check_pext_scale (extcheck_t *extcheck) {return !!(extcheck->pext1 & PEXT_BULLETENS);}
{"DP_ENT_SCALE"}, //entities may be rescaled //static qboolean check_pext_senttimings (extcheck_t *extcheck) {return check_pext_rpd(extcheck,PEXT_ACCURATETIMINGS);}
{"FTE_PEXT_LIGHTSTYLECOL"}, //lightstyles may have colours. //static qboolean check_pext_sounddbl (extcheck_t *extcheck) {return !!(extcheck->pext1 & PEXT_SOUNDDBL);}
{"DP_ENT_ALPHA"}, //transparent entites static qboolean check_pext_fatness (extcheck_t *extcheck) {return check_pext_rpd(extcheck,PEXT_FATNESS);}
{"FTE_PEXT_VIEW2"}, //secondary view. //static qboolean check_pext_hlbsp (extcheck_t *extcheck) {return !!(extcheck->pext1 & PEXT_HLBSP);}
{"FTE_PEXT_ACURATETIMINGS"}, //allows full interpolation static qboolean check_pext_tebullet (extcheck_t *extcheck) {return !!(extcheck->pext1 & PEXT_TE_BULLET);}
{"FTE_PEXT_SOUNDDBL"}, //twice the sound indexes //static qboolean check_pext_hullsize (extcheck_t *extcheck) {return check_pext_rpd(extcheck,PEXT_HULLSIZE);}
{"FTE_PEXT_FATNESS"}, //entities may be expanded along their vertex normals //static qboolean check_pext_modeldbl (extcheck_t *extcheck) {return check_pext_rpd(extcheck,PEXT_MODELDBL);}
{"DP_HALFLIFE_MAP"}, //entity can visit a hl bsp //static qboolean check_pext_entitydbl (extcheck_t *extcheck) {return check_pext_rpd(extcheck,PEXT_ENTITYDBL);}
{"FTE_PEXT_TE_BULLET"}, //additional particle effect. Like TE_SPIKE and TE_SUPERSPIKE //static qboolean check_pext_entitydbl2 (extcheck_t *extcheck) {return check_pext_rpd(extcheck,PEXT_ENTITYDBL2);}
{"FTE_PEXT_HULLSIZE"}, //means we can tell a client to go to crouching hull static qboolean check_pext_floatcoords (extcheck_t *extcheck) {return !!(extcheck->pext1 & PEXT_FLOATCOORDS);}
{"FTE_PEXT_MODELDBL"}, //max of 512 models //static qboolean check_pext_vweap (extcheck_t *extcheck) {return !!(extcheck->pext1 & PEXT_VWEAP);}
{"FTE_PEXT_ENTITYDBL"}, //max of 1024 ents static qboolean check_pext_q2bsp (extcheck_t *extcheck) {return !!(extcheck->pext1 & PEXT_Q2BSP_);}
{"FTE_PEXT_ENTITYDBL2"}, //max of 2048 ents static qboolean check_pext_q3bsp (extcheck_t *extcheck) {return !!(extcheck->pext1 & PEXT_Q3BSP_);}
{"FTE_PEXT_FLOATCOORDS"}, static qboolean check_pext_colourmod (extcheck_t *extcheck) {return check_pext_rpd(extcheck,PEXT_COLOURMOD);}
{"FTE_PEXT_VWEAP"}, //static qboolean check_pext_splitscreen (extcheck_t *extcheck) {return !!(extcheck->pext1 & PEXT_SPLITSCREEN);}
{"FTE_PEXT_Q2BSP"}, //supports q2 maps. No bugs are apparent. static qboolean check_pext_hexen2 (extcheck_t *extcheck) {return !!(extcheck->pext1 & PEXT_HEXEN2);}
{"FTE_PEXT_Q3BSP"}, //quake3 bsp support. dp probably has an equivelent, but this is queryable per client. static qboolean check_pext_spawnstatic (extcheck_t *extcheck) {return check_pext_rpd(extcheck,PEXT_SPAWNSTATIC2);}
{"DP_ENT_COLORMOD"}, static qboolean check_pext_customtempeffects(extcheck_t *extcheck) {return !!(extcheck->pext1 & PEXT_CUSTOMTEMPEFFECTS);}
{NULL}, //splitscreen - not queryable. static qboolean check_pext_256packetentities(extcheck_t *extcheck) {return check_pext_rpd(extcheck,PEXT_256PACKETENTITIES);}
{"FTE_HEXEN2", 3, NULL, {"particle2", "particle3", "particle4"}}, //client can use hexen2 maps. server can use hexen2 progs static qboolean check_pext_showpic (extcheck_t *extcheck) {return !!(extcheck->pext1 & PEXT_SHOWPIC);}
{"FTE_PEXT_SPAWNSTATIC"}, //means that static entities can have alpha/scale and anything else the engine supports on normal ents. (Added for >256 models, while still being compatible - previous system failed with -1 skins) static qboolean check_pext_setattachment (extcheck_t *extcheck) {return check_pext_rpd(extcheck,PEXT_SETATTACHMENT);}
{"FTE_PEXT_CUSTOMTENTS", 2, NULL, {"RegisterTempEnt", "CustomTempEnt"}}, //static qboolean check_pext_chunkeddownloads (extcheck_t *extcheck) {return !!(extcheck->pext1 & PEXT_CHUNKEDDOWNLOADS);}
{"FTE_PEXT_256PACKETENTITIES"}, //client is able to receive unlimited packet entities (server caps itself to 256 to prevent insanity). static qboolean check_pext_csqc (extcheck_t *extcheck) {return !!(extcheck->pext1 & PEXT_CSQC);}
{NULL}, //static qboolean check_pext_dpflags (extcheck_t *extcheck) {return check_pext_rpd(extcheck,PEXT_DPFLAGS);}
{"TEI_SHOWLMP2", 6, NULL, {"showpic", "hidepic", "movepic", "changepic", "showpicent", "hidepicent"}}, //telejano doesn't actually export the moveent/changeent (we don't want to either cos it would stop frik_file stuff being autoregistered) #define check_pext_pointparticle NULL
{"DP_GFX_QUAKE3MODELTAGS", 1, NULL, {"setattachment"}},
{"FTE_PK3DOWNLOADS"},
{"PEXT_CHUNKEDDOWNLOADS"},
{"EXT_CSQC_SHARED"}, //this is a separate extension because it requires protocol modifications. note: this is also the extension that extends the allowed stats. //static qboolean check_pext2_prydoncursor (extcheck_t *extcheck) {return !!(extcheck->pext2 & PEXT2_PRYDONCURSOR);}
//static qboolean check_pext2_voicechat (extcheck_t *extcheck) {return !!(extcheck->pext2 & PEXT2_VOICECHAT);}
//static qboolean check_pext2_setangledelta (extcheck_t *extcheck) {return !!(extcheck->pext2 & PEXT2_SETANGLEDELTA);}
//static qboolean check_pext2_replacementdeltas(extcheck_t *extcheck) {return !!(extcheck->pext2 & PEXT2_REPLACEMENTDELTAS);}
//static qboolean check_pext2_maxplayers (extcheck_t *extcheck) {return !!(extcheck->pext2 & PEXT2_MAXPLAYERS);}
//static qboolean check_pext2_predinfo (extcheck_t *extcheck) {return !!(extcheck->pext2 & PEXT2_PREDINFO);}
//static qboolean check_pext2_newsizeencoding (extcheck_t *extcheck) {return !!(extcheck->pext2 & PEXT2_NEWSIZEENCODING);}
//static qboolean check_pext2_infoblobs (extcheck_t *extcheck) {return !!(extcheck->pext2 & PEXT2_INFOBLOBS);}
//static qboolean check_pext2_stunaware (extcheck_t *extcheck) {return !!(extcheck->pext2 & PEXT2_STUNAWARE);}
//static qboolean check_pext2_vrinputs (extcheck_t *extcheck) {return !!(extcheck->pext2 & PEXT2_VRINPUTS);}
{"PEXT_DPFLAGS"}, #define NOBI NULL, 0,{NULL},
qc_extension_t QSG_Extensions[] = {
{"EXT_CSQC"}, //this is the base csqc extension. I'm not sure what needs to be separate and what does not. //these don't have well-defined names...
//{"EXT_CSQC_DELTAS"},//this is a separate extension because the feature may be banned in a league due to cheat protection. {"??TOMAZ_STRINGS", NULL, 6,{"tq_zone", "tq_unzone", "tq_strcat", "tq_substring", "tq_stof", "tq_stov"}},
{"??TOMAZ_FILE", NULL, 4,{"tq_fopen", "tq_fclose", "tq_fgets", "tq_fputs"}},
//the rest are generic extensions {"??MVDSV_BUILTINS", NULL, 21,{"executecommand", "mvdtokenize", "mvdargc", "mvdargv",
{"??TOMAZ_STRINGS", 6, NULL, {"tq_zone", "tq_unzone", "tq_strcat", "tq_substring", "tq_stof", "tq_stov"}},
{"??TOMAZ_FILE", 4, NULL, {"tq_fopen", "tq_fclose", "tq_fgets", "tq_fputs"}},
{"??MVDSV_BUILTINS", 21, NULL, {"executecommand", "mvdtokenize", "mvdargc", "mvdargv",
"teamfield", "substr", "mvdstrcat", "mvdstrlen", "str2byte", "teamfield", "substr", "mvdstrcat", "mvdstrlen", "str2byte",
"str2short", "mvdnewstr", "mvdfreestr", "conprint", "readcmd", "str2short", "mvdnewstr", "mvdfreestr", "conprint", "readcmd",
"mvdstrcpy", "strstr", "mvdstrncpy", "log", "redirectcmd", "mvdstrcpy", "strstr", "mvdstrncpy", "log", "redirectcmd",
"mvdcalltimeofday", "forcedemoframe"}}, "mvdcalltimeofday", "forcedemoframe"}},
//end of mvdsv
// Tomaz - QuakeC File System End
{"BX_COLOREDTEXT"}, {"BX_COLOREDTEXT"},
{"DP_CON_SET", 0, NULL, {NULL}, "The 'set' console command exists, and can be used to create/set cvars."}, {"DP_CON_SET", NULL, 0,{NULL}, "The 'set' console command exists, and can be used to create/set cvars."},
#ifndef SERVERONLY #ifndef SERVERONLY
{"DP_CON_SETA", 0, NULL, {NULL}, "The 'seta' console command exists, like the 'set' command, but also marks the cvar for archiving, allowing it to be written into the user's config. Use this command in your default.cfg file."}, {"DP_CON_SETA", NULL, 0,{NULL}, "The 'seta' console command exists, like the 'set' command, but also marks the cvar for archiving, allowing it to be written into the user's config. Use this command in your default.cfg file."},
#endif #endif
{"DP_CSQC_ROTATEMOVES"}, {"DP_CSQC_ROTATEMOVES"},
{"DP_EF_ADDITIVE"}, {"DP_EF_ADDITIVE"},
//--{"DP_ENT_ALPHA"}, //listed above {"DP_ENT_ALPHA", check_pext_trans}, //transparent entites
{"DP_EF_BLUE"}, //hah!! This is QuakeWorld!!! {"DP_EF_BLUE"}, //hah!! This is QuakeWorld!!!
{"DP_EF_FULLBRIGHT"}, //Rerouted to hexen2 support. {"DP_EF_FULLBRIGHT"}, //Rerouted to hexen2 support.
{"DP_EF_NODEPTHTEST"}, //for cheats {"DP_EF_NODEPTHTEST"}, //for cheats
@ -7485,263 +7487,292 @@ lh_extension_t QSG_Extensions[] = {
{"DP_EF_NOGUNBOB"}, //nogunbob. sane people should use csqc instead. {"DP_EF_NOGUNBOB"}, //nogunbob. sane people should use csqc instead.
{"DP_EF_NOSHADOW"}, {"DP_EF_NOSHADOW"},
{"DP_EF_RED"}, {"DP_EF_RED"},
//--{"DP_ENT_COLORMOD"}, //listed above {"DP_ENT_COLORMOD", check_pext_colourmod},
{"DP_ENT_CUSTOMCOLORMAP"}, {"DP_ENT_CUSTOMCOLORMAP"},
{"DP_ENT_EXTERIORMODELTOCLIENT"}, {"DP_ENT_EXTERIORMODELTOCLIENT"},
//--{"DP_ENT_SCALE"}, //listed above {"DP_ENT_SCALE", check_pext_scale}, //listed above
{"DP_ENT_TRAILEFFECTNUM", 1, NULL, {"particleeffectnum"}, "self.traileffectnum=particleeffectnum(\"myeffectname\"); can be used to attach a particle trail to the given server entity. This is equivelent to calling trailparticles each frame."}, {"DP_ENT_TRAILEFFECTNUM", NULL, 1,{"particleeffectnum"}, "self.traileffectnum=particleeffectnum(\"myeffectname\"); can be used to attach a particle trail to the given server entity. This is equivelent to calling trailparticles each frame."},
//only in dp6 currently {"DP_ENT_GLOW"}, //only in dp6 currently {"DP_ENT_GLOW"},
{"DP_ENT_VIEWMODEL"}, {"DP_ENT_VIEWMODEL"},
{"DP_GECKO_SUPPORT", 7, NULL, {"gecko_create", "gecko_destroy", "gecko_navigate", "gecko_keyevent", "gecko_mousemove", "gecko_resize", "gecko_get_texture_extent"}}, {"DP_GECKO_SUPPORT", NULL, 7,{"gecko_create", "gecko_destroy", "gecko_navigate", "gecko_keyevent", "gecko_mousemove", "gecko_resize", "gecko_get_texture_extent"}},
{"DP_GFX_FONTS", 2, NULL, {"findfont", "loadfont"}}, //note: font slot numbers/names are not special in fte. {"DP_GFX_FONTS", NULL, 2,{"findfont", "loadfont"}}, //note: font slot numbers/names are not special in fte.
// {"DP_GFX_FONTS_FREETYPE"}, //extra cvars are not supported. // {"DP_GFX_FONTS_FREETYPE"}, //extra cvars are not supported.
// {"DP_GFX_QUAKE3MODELTAGS"}, {"DP_GFX_QUAKE3MODELTAGS", check_pext_setattachment, 1,{"setattachment"}},
{"DP_GFX_SKINFILES"}, {"DP_GFX_SKINFILES"},
{"DP_GFX_SKYBOX"}, //according to the spec. :) {"DP_GFX_SKYBOX"}, //according to the spec. :)
{"DP_HALFLIFE_MAP"}, //entity can visit a hl bsp
{"DP_HALFLIFE_MAP_CVAR"}, {"DP_HALFLIFE_MAP_CVAR"},
//to an extend {"DP_HALFLIFE_SPRITE"}, //to an extent {"DP_HALFLIFE_SPRITE"},
{"DP_INPUTBUTTONS"}, {"DP_INPUTBUTTONS"},
{"DP_LIGHTSTYLE_STATICVALUE"}, {"DP_LIGHTSTYLE_STATICVALUE"},
{"DP_LITSUPPORT"}, {"DP_LITSUPPORT"},
{"DP_MONSTERWALK", 0, NULL, {NULL}, "MOVETYPE_WALK is valid on non-player entities. Note that only players receive acceleration etc in line with none/bounce/fly/noclip movetypes on the player, thus you will have to provide your own accelerations (incluing gravity) yourself."}, {"DP_MONSTERWALK", NULL, 0,{NULL}, "MOVETYPE_WALK is valid on non-player entities. Note that only players receive acceleration etc in line with none/bounce/fly/noclip movetypes on the player, thus you will have to provide your own accelerations (incluing gravity) yourself."},
{"DP_MOVETYPEBOUNCEMISSILE"}, //I added the code for hexen2 support. {"DP_MOVETYPEBOUNCEMISSILE"}, //I added the code for hexen2 support.
{"DP_MOVETYPEFOLLOW"}, {"DP_MOVETYPEFOLLOW"},
{"DP_QC_ASINACOSATANATAN2TAN", 5, NULL, {"asin", "acos", "atan", "atan2", "tan"}}, {"DP_QC_ASINACOSATANATAN2TAN", NULL, 5,{"asin", "acos", "atan", "atan2", "tan"}},
{"DP_QC_CHANGEPITCH", 1, NULL, {"changepitch"}}, {"DP_QC_CHANGEPITCH", NULL, 1,{"changepitch"}},
{"DP_QC_COPYENTITY", 1, NULL, {"copyentity"}}, {"DP_QC_COPYENTITY", NULL, 1,{"copyentity"}},
{"DP_QC_CRC16", 1, NULL, {"crc16"}}, {"DP_QC_CRC16", NULL, 1,{"crc16"}},
{"DP_QC_CVAR_DEFSTRING", 1, NULL, {"cvar_defstring"}}, {"DP_QC_CVAR_DEFSTRING", NULL, 1,{"cvar_defstring"}},
{"DP_QC_CVAR_STRING", 1, NULL, {"cvar_string"}}, //448 builtin. {"DP_QC_CVAR_STRING", NULL, 1,{"cvar_string"}}, //448 builtin.
{"DP_QC_CVAR_TYPE", 1, NULL, {"cvar_type"}}, {"DP_QC_CVAR_TYPE", NULL, 1,{"cvar_type"}},
{"DP_QC_DIGEST_SHA256"}, {"DP_QC_DIGEST_SHA256"},
{"DP_QC_EDICT_NUM", 1, NULL, {"edict_num"}}, {"DP_QC_EDICT_NUM", NULL, 1,{"edict_num"}},
{"DP_QC_ENTITYDATA", 5, NULL, {"numentityfields", "entityfieldname", "entityfieldtype", "getentityfieldstring", "putentityfieldstring"}}, {"DP_QC_ENTITYDATA", NULL, 5,{"numentityfields", "entityfieldname", "entityfieldtype", "getentityfieldstring", "putentityfieldstring"}},
{"DP_QC_ETOS", 1, NULL, {"etos"}}, {"DP_QC_ETOS", NULL, 1,{"etos"}},
{"DP_QC_FINDCHAIN", 1, NULL, {"findchain"}}, {"DP_QC_FINDCHAIN", NULL, 1,{"findchain"}},
{"DP_QC_FINDCHAINFLOAT", 1, NULL, {"findchainfloat"}}, {"DP_QC_FINDCHAINFLOAT", NULL, 1,{"findchainfloat"}},
{"DP_QC_FINDFLAGS", 1, NULL, {"findflags"}}, {"DP_QC_FINDFLAGS", NULL, 1,{"findflags"}},
{"DP_QC_FINDCHAINFLAGS", 1, NULL, {"findchainflags"}}, {"DP_QC_FINDCHAINFLAGS", NULL, 1,{"findchainflags"}},
{"DP_QC_FINDFLOAT", 1, NULL, {"findfloat"}}, {"DP_QC_FINDFLOAT", NULL, 1,{"findfloat"}},
{"DP_QC_FS_SEARCH", 4, NULL, {"search_begin", "search_end", "search_getsize", "search_getfilename"}}, {"DP_QC_FS_SEARCH", NULL, 4,{"search_begin", "search_end", "search_getsize", "search_getfilename"}},
{"DP_QC_FS_SEARCH_PACKFILE", 4, NULL, {"search_begin", "search_end", "search_getsize", "search_getfilename"}}, {"DP_QC_FS_SEARCH_PACKFILE", NULL, 4,{"search_begin", "search_end", "search_getsize", "search_getfilename"}},
{"DP_QC_GETSURFACE", 6, NULL, {"getsurfacenumpoints", "getsurfacepoint", "getsurfacenormal", "getsurfacetexture", "getsurfacenearpoint", "getsurfaceclippedpoint"}}, {"DP_QC_GETSURFACE", NULL, 6,{"getsurfacenumpoints", "getsurfacepoint", "getsurfacenormal", "getsurfacetexture", "getsurfacenearpoint", "getsurfaceclippedpoint"}},
{"DP_QC_GETSURFACEPOINTATTRIBUTE", 1, NULL, {"getsurfacepointattribute"}}, {"DP_QC_GETSURFACEPOINTATTRIBUTE", NULL, 1,{"getsurfacepointattribute"}},
{"DP_QC_GETTAGINFO", 2, NULL, {"gettagindex", "gettaginfo"}}, {"DP_QC_GETTAGINFO", NULL, 2,{"gettagindex", "gettaginfo"}},
{"DP_QC_MINMAXBOUND", 3, NULL, {"min", "max", "bound"}}, {"DP_QC_MINMAXBOUND", NULL, 3,{"min", "max", "bound"}},
{"DP_QC_MULTIPLETEMPSTRINGS", 0, NULL, {NULL}, "Superseded by DP_QC_UNLIMITEDTEMPSTRINGS. Functions that return a temporary string will not overwrite/destroy previous temporary strings until at least 16 strings are returned (or control returns to the engine)."}, {"DP_QC_MULTIPLETEMPSTRINGS", NULL, 0,{NULL}, "Superseded by DP_QC_UNLIMITEDTEMPSTRINGS. Functions that return a temporary string will not overwrite/destroy previous temporary strings until at least 16 strings are returned (or control returns to the engine)."},
{"DP_QC_RANDOMVEC", 1, NULL, {"randomvec"}}, {"DP_QC_RANDOMVEC", NULL, 1,{"randomvec"}},
{"DP_QC_RENDER_SCENE", 0, NULL, {NULL}, "clearscene+addentity+setviewprop+renderscene+setmodel are available to menuqc. WARNING: DP advertises this extension without actually supporting it, FTE does actually support it."}, {"DP_QC_RENDER_SCENE", NULL, 0,{NULL}, "clearscene+addentity+setviewprop+renderscene+setmodel are available to menuqc. WARNING: DP advertises this extension without actually supporting it, FTE does actually support it."},
{"DP_QC_SINCOSSQRTPOW", 4, NULL, {"sin", "cos", "sqrt", "pow"}}, {"DP_QC_SINCOSSQRTPOW", NULL, 4,{"sin", "cos", "sqrt", "pow"}},
{"DP_QC_SPRINTF", 1, NULL, {"sprintf"}, "Provides the sprintf builtin, which allows for rich formatting along the lines of C's function with the same name. Not to be confused with QC's sprint builtin."}, {"DP_QC_SPRINTF", NULL, 1,{"sprintf"}, "Provides the sprintf builtin, which allows for rich formatting along the lines of C's function with the same name. Not to be confused with QC's sprint builtin."},
{"DP_QC_STRFTIME", 1, NULL, {"strftime"}}, {"DP_QC_STRFTIME", NULL, 1,{"strftime"}},
{"DP_QC_STRING_CASE_FUNCTIONS", 2, NULL, {"strtolower", "strtoupper"}}, {"DP_QC_STRING_CASE_FUNCTIONS", NULL, 2,{"strtolower", "strtoupper"}},
{"DP_QC_STRINGBUFFERS", 10, NULL, {"buf_create", "buf_del", "buf_getsize", "buf_copy", "buf_sort", "buf_implode", "bufstr_get", "bufstr_set", "bufstr_add", "bufstr_free"}}, {"DP_QC_STRINGBUFFERS", NULL, 10,{"buf_create", "buf_del", "buf_getsize", "buf_copy", "buf_sort", "buf_implode", "bufstr_get", "bufstr_set", "bufstr_add", "bufstr_free"}},
{"DP_QC_STRINGCOLORFUNCTIONS", 2, NULL, {"strlennocol", "strdecolorize"}}, {"DP_QC_STRINGCOLORFUNCTIONS", NULL, 2,{"strlennocol", "strdecolorize"}},
{"DP_QC_STRREPLACE", 2, NULL, {"strreplace", "strireplace"}}, {"DP_QC_STRREPLACE", NULL, 2,{"strreplace", "strireplace"}},
{"DP_QC_TOKENIZEBYSEPARATOR", 1, NULL, {"tokenizebyseparator"}}, {"DP_QC_TOKENIZEBYSEPARATOR", NULL, 1,{"tokenizebyseparator"}},
{"DP_QC_TRACEBOX", 1, NULL, {"tracebox"}}, {"DP_QC_TRACEBOX", NULL, 1,{"tracebox"}},
{"DP_QC_TRACETOSS"}, {"DP_QC_TRACETOSS"},
{"DP_QC_TRACE_MOVETYPE_HITMODEL"}, {"DP_QC_TRACE_MOVETYPE_HITMODEL"},
{"DP_QC_TRACE_MOVETYPE_WORLDONLY"}, {"DP_QC_TRACE_MOVETYPE_WORLDONLY"},
{"DP_QC_TRACE_MOVETYPES"}, //this one is just a lame excuse to add annother extension... {"DP_QC_TRACE_MOVETYPES"}, //this one is just a lame excuse to add annother extension...
{"DP_QC_UNLIMITEDTEMPSTRINGS", 0, NULL, {NULL}, "Supersedes DP_QC_MULTIPLETEMPSTRINGS, superseded by FTE_QC_PERSISTENTTEMPSTRINGS. Specifies that all temp strings will be valid at least until the QCVM returns."}, {"DP_QC_UNLIMITEDTEMPSTRINGS", NULL, 0,{NULL}, "Supersedes DP_QC_MULTIPLETEMPSTRINGS, superseded by FTE_QC_PERSISTENTTEMPSTRINGS. Specifies that all temp strings will be valid at least until the QCVM returns."},
{"DP_QC_URI_ESCAPE", 2, NULL, {"uri_escape", "uri_unescape"}}, {"DP_QC_URI_ESCAPE", NULL, 2,{"uri_escape", "uri_unescape"}},
#ifdef WEBCLIENT #ifdef WEBCLIENT
{"DP_QC_URI_GET", 1, NULL, {"uri_get"}}, {"DP_QC_URI_GET", NULL, 1,{"uri_get"}},
{"DP_QC_URI_POST", 1, NULL, {"uri_get"}}, {"DP_QC_URI_POST", NULL, 1,{"uri_get"}},
#endif #endif
{"DP_QC_VECTOANGLES_WITH_ROLL"}, {"DP_QC_VECTOANGLES_WITH_ROLL"},
{"DP_QC_VECTORVECTORS", 1, NULL, {"vectorvectors"}}, {"DP_QC_VECTORVECTORS", NULL, 1,{"vectorvectors"}},
{"DP_QC_WHICHPACK", 1, NULL, {"whichpack"}}, {"DP_QC_WHICHPACK", NULL, 1,{"whichpack"}},
{"DP_QUAKE2_MODEL"}, {"DP_QUAKE2_MODEL"},
{"DP_QUAKE2_SPRITE"}, {"DP_QUAKE2_SPRITE"},
{"DP_QUAKE3_MAP"},
{"DP_QUAKE3_MODEL"}, {"DP_QUAKE3_MODEL"},
{"DP_REGISTERCVAR", 1, NULL, {"registercvar"}}, {"DP_REGISTERCVAR", NULL, 1,{"registercvar"}},
{"DP_SND_SOUND7_WIP2"}, //listed only to silence xonotic, if anyone tries running that. {"DP_SND_SOUND7_WIP2"}, //listed only to silence xonotic, if anyone tries running that.
{"DP_SND_STEREOWAV"}, {"DP_SND_STEREOWAV"},
{"DP_SND_OGGVORBIS"}, {"DP_SND_OGGVORBIS"},
{"DP_SOLIDCORPSE"}, {"DP_SOLIDCORPSE"},
{"DP_SPRITE32"}, //hmm... is it legal to advertise this one? {"DP_SPRITE32"}, //hmm... is it legal to advertise this one?
{"DP_SV_BOTCLIENT", 2, NULL, {"spawnclient", "clienttype"}}, {"DP_SV_BOTCLIENT", NULL, 2,{"spawnclient", "clienttype"}},
{"DP_SV_CLIENTCAMERA", 0, NULL, {NULL}, "Works like svc_setview except also handles pvs."}, {"DP_SV_CLIENTCAMERA", NULL, 0,{NULL}, "Works like svc_setview except also handles pvs."},
{"DP_SV_CLIENTCOLORS", 0, NULL, {NULL}, "Provided only for compatibility with DP."}, {"DP_SV_CLIENTCOLORS", NULL, 0,{NULL}, "Provided only for compatibility with DP."},
{"DP_SV_CLIENTNAME", 0, NULL, {NULL}, "Provided only for compatibility with DP."}, {"DP_SV_CLIENTNAME", NULL, 0,{NULL}, "Provided only for compatibility with DP."},
{"DP_SV_DRAWONLYTOCLIENT"}, {"DP_SV_DRAWONLYTOCLIENT"},
{"DP_SV_DROPCLIENT", 1, NULL, {"dropclient"}, "Equivelent to quakeworld's stuffcmd(self,\"disconnect\\n\"); hack"}, {"DP_SV_DROPCLIENT", NULL, 1,{"dropclient"}, "Equivelent to quakeworld's stuffcmd(self,\"disconnect\\n\"); hack"},
{"DP_SV_EFFECT", 1, NULL, {"effect"}}, {"DP_SV_EFFECT", NULL, 1,{"effect"}},
{"DP_SV_EXTERIORMODELFORCLIENT"}, {"DP_SV_EXTERIORMODELFORCLIENT"},
{"DP_SV_NODRAWTOCLIENT"}, //I prefer my older system. Guess I might as well remove that older system at some point. {"DP_SV_NODRAWTOCLIENT"}, //I prefer my older system. Guess I might as well remove that older system at some point.
{"DP_SV_PLAYERPHYSICS", 0, NULL, {NULL}, "Allows reworking parts of NQ player physics. USE AT OWN RISK - this necessitates NQ physics and is thus guarenteed to break prediction."}, {"DP_SV_PLAYERPHYSICS", NULL, 0,{NULL}, "Allows reworking parts of NQ player physics. USE AT OWN RISK - this necessitates NQ physics and is thus guarenteed to break prediction."},
// {"DP_SV_POINTPARTICLES", 3, NULL, {"particleeffectnum", "pointparticles", "trailparticles"}, "Specifies that pointparticles (and trailparticles) exists in ssqc as well as csqc (and that dp's trailparticles argument fuckup will normally work). ssqc values can be passed to csqc for use, the reverse is not true. Does NOT mean that DP's effectinfo.txt is supported, only that ssqc has functionality equivelent to csqc."}, // {"DP_SV_POINTPARTICLES", check_pext_pointparticle, 3,{"particleeffectnum", "pointparticles", "trailparticles"}, "Specifies that pointparticles (and trailparticles) exists in ssqc as well as csqc (and that dp's trailparticles argument fuckup will normally work). ssqc values can be passed to csqc for use, the reverse is not true. Does NOT mean that DP's effectinfo.txt is supported, only that ssqc has functionality equivelent to csqc."},
{"DP_SV_POINTSOUND", 1, NULL, {"pointsound"}}, {"DP_SV_POINTSOUND", NULL, 1,{"pointsound"}},
{"DP_SV_PRECACHEANYTIME", 0, NULL, {NULL}, "Specifies that the various precache builtins can be called at any time. WARNING: precaches are sent reliably while sound events, modelindexes, and particle events are not. This can mean sounds and particles might not work the first time around, or models may take a while to appear (after the reliables are received and the model is loaded from disk). Always attempt to precache a little in advance in order to reduce these issues (preferably at the start of the map...)"}, {"DP_SV_PRECACHEANYTIME", NULL, 0,{NULL}, "Specifies that the various precache builtins can be called at any time. WARNING: precaches are sent reliably while sound events, modelindexes, and particle events are not. This can mean sounds and particles might not work the first time around, or models may take a while to appear (after the reliables are received and the model is loaded from disk). Always attempt to precache a little in advance in order to reduce these issues (preferably at the start of the map...)"},
{"DP_SV_PRINT", 1, NULL, {"print"}, "Says that the print builtin can be used from nqssqc (as well as just csqc), bypassing the developer cvar issues."}, {"DP_SV_PRINT", NULL, 1,{"print"}, "Says that the print builtin can be used from nqssqc (as well as just csqc), bypassing the developer cvar issues."},
{"DP_SV_SETCOLOR"}, {"DP_SV_ROTATINGBMODEL", NOBI "Engines that support this support avelocity on MOVETYPE_PUSH entities, pushing entities out of the way as needed."},
{"DP_SV_SETCOLOR", NULL, 1,{"setcolors"}},
{"DP_SV_SPAWNFUNC_PREFIX"}, {"DP_SV_SPAWNFUNC_PREFIX"},
{"DP_SV_WRITEPICTURE", 1, NULL, {"WritePicture"}}, {"DP_SV_WRITEPICTURE", NULL, 1,{"WritePicture"}},
{"DP_SV_WRITEUNTERMINATEDSTRING", 1, NULL, {"WriteUnterminatedString"}}, {"DP_SV_WRITEUNTERMINATEDSTRING", NULL, 1,{"WriteUnterminatedString"}},
{"DP_TE_BLOOD", 1, NULL, {"te_blood"}}, {"DP_TE_BLOOD", NULL, 1,{"te_blood"}},
{"_DP_TE_BLOODSHOWER", 1, NULL, {"te_bloodshower"}}, {"_DP_TE_BLOODSHOWER", NULL, 1,{"te_bloodshower"}, "Requires external particle config."},
{"DP_TE_CUSTOMFLASH", 1, NULL, {"te_customflash"}}, {"DP_TE_CUSTOMFLASH", NULL, 1,{"te_customflash"}},
{"DP_TE_EXPLOSIONRGB", 1, NULL, {"te_explosionrgb"}}, {"DP_TE_EXPLOSIONRGB", NULL, 1,{"te_explosionrgb"}},
{"_DP_TE_FLAMEJET", 1, NULL, {"te_flamejet"}}, {"_DP_TE_FLAMEJET", NULL, 1,{"te_flamejet"}, "Requires external particle config."},
{"DP_TE_PARTICLECUBE", 1, NULL, {"te_particlecube"}}, {"DP_TE_PARTICLECUBE", NULL, 1,{"te_particlecube"}},
{"DP_TE_PARTICLERAIN", 1, NULL, {"te_particlerain"}}, {"DP_TE_PARTICLERAIN", NULL, 1,{"te_particlerain"}},
{"DP_TE_PARTICLESNOW", 1, NULL, {"te_particlesnow"}}, {"DP_TE_PARTICLESNOW", NULL, 1,{"te_particlesnow"}},
{"_DP_TE_PLASMABURN", 1, NULL, {"te_plasmaburn"}}, {"_DP_TE_PLASMABURN", NULL, 1,{"te_plasmaburn"}, "Requires external particle config."},
{"_DP_TE_QUADEFFECTS1", 4, NULL, {"te_gunshotquad", "te_spikequad", "te_superspikequad", "te_explosionquad"}}, {"_DP_TE_QUADEFFECTS1", NULL, 4,{"te_gunshotquad", "te_spikequad", "te_superspikequad", "te_explosionquad"}, "Requires external particle config."},
{"DP_TE_SMALLFLASH", 1, NULL, {"te_smallflash"}}, {"DP_TE_SMALLFLASH", NULL, 1,{"te_smallflash"}},
{"DP_TE_SPARK", 1, NULL, {"te_spark"}}, {"DP_TE_SPARK", NULL, 1,{"te_spark"}},
{"DP_TE_STANDARDEFFECTBUILTINS", 14, NULL, { "te_gunshot", "te_spike", "te_superspike", "te_explosion", "te_tarexplosion", "te_wizspike", "te_knightspike", {"DP_TE_STANDARDEFFECTBUILTINS", NULL, 14,{ "te_gunshot", "te_spike", "te_superspike", "te_explosion", "te_tarexplosion", "te_wizspike", "te_knightspike",
"te_lavasplash", "te_teleport", "te_explosion2", "te_lightning1", "te_lightning2", "te_lightning3", "te_beam"}}, "te_lavasplash", "te_teleport", "te_explosion2", "te_lightning1", "te_lightning2", "te_lightning3", "te_beam"}},
{"DP_VIEWZOOM"}, {"DP_VIEWZOOM"},
{"EXT_BITSHIFT", 1, NULL, {"bitshift"}}, {"EXT_BITSHIFT", NULL, 1,{"bitshift"}},
{"EXT_CSQC", check_pext_csqc, 2,{"multicast","clientstat"}}, //this is the base csqc extension. I'm not sure what needs to be separate and what does not.
{"EXT_CSQC_SHARED", check_pext_csqc}, //this is a separate extension because it requires protocol modifications. note: this is also the extension that extends the allowed stats.
{"EXT_DIMENSION_VISIBILITY"}, {"EXT_DIMENSION_VISIBILITY"},
{"EXT_DIMENSION_PHYSICS"}, {"EXT_DIMENSION_PHYSICS"},
{"EXT_DIMENSION_GHOST"}, {"EXT_DIMENSION_GHOST"},
{"FRIK_FILE", 11, NULL, {"stof", "fopen","fclose","fgets","fputs","strlen","strcat","substring","stov","strzone","strunzone"}}, {"FRIK_FILE", NULL, 11,{"stof", "fopen","fclose","fgets","fputs","strlen","strcat","substring","stov","strzone","strunzone"}},
{"FTE_CALLTIMEOFDAY", 1, NULL, {"calltimeofday"}, "Replication of mvdsv functionality (call calltimeofday to cause 'timeofday' to be called, with arguments that can be saved off to a global). Generally strftime is simpler to use."}, {"FTE_CALLTIMEOFDAY", NULL, 1,{"calltimeofday"}, "Replication of mvdsv functionality (call calltimeofday to cause 'timeofday' to be called, with arguments that can be saved off to a global). Generally strftime is simpler to use."},
{"FTE_CSQC_ALTCONSOLES", 4, NULL, {"con_getset", "con_printf", "con_draw", "con_input"}, "The engine tracks multiple consoles. These may or may not be directly visible to the user."}, {"FTE_CSQC_ALTCONSOLES", NULL, 4,{"con_getset", "con_printf", "con_draw", "con_input"}, "The engine tracks multiple consoles. These may or may not be directly visible to the user."},
{"FTE_CSQC_BASEFRAME", 0, NULL, {NULL}, "Specifies that .basebone, .baseframe2, .baselerpfrac, baseframe1time, etc exist in csqc. These fields affect all bones in the entity's model with a lower index than the .basebone field, allowing you to give separate control to the legs of a skeletal model, without affecting the torso animations."}, {"FTE_CSQC_BASEFRAME", NULL, 0,{NULL}, "Specifies that .basebone, .baseframe2, .baselerpfrac, baseframe1time, etc exist in csqc. These fields affect all bones in the entity's model with a lower index than the .basebone field, allowing you to give separate control to the legs of a skeletal model, without affecting the torso animations."},
#ifdef HALFLIFEMODELS #ifdef HALFLIFEMODELS
{"FTE_CSQC_HALFLIFE_MODELS"}, //hl-specific skeletal model control {"FTE_CSQC_HALFLIFE_MODELS"}, //hl-specific skeletal model control
#endif #endif
{"FTE_CSQC_SERVERBROWSER", 12, NULL, { "gethostcachevalue", "gethostcachestring", "resethostcachemasks", "sethostcachemaskstring", "sethostcachemasknumber", {"FTE_CSQC_SERVERBROWSER", NULL, 12,{"gethostcachevalue", "gethostcachestring", "resethostcachemasks", "sethostcachemaskstring", "sethostcachemasknumber",
"resorthostcache", "sethostcachesort", "refreshhostcache", "gethostcachenumber", "gethostcacheindexforkey", "resorthostcache", "sethostcachesort", "refreshhostcache", "gethostcachenumber", "gethostcacheindexforkey",
"addwantedhostcachekey", "getextresponse"}, "Provides builtins to query the engine's serverbrowser servers list from ssqc. Note that these builtins are always available in menuqc."}, "addwantedhostcachekey", "getextresponse"}, "Provides builtins to query the engine's serverbrowser servers list from ssqc. Note that these builtins are always available in menuqc."},
{"FTE_CSQC_SKELETONOBJECTS", 15, NULL, { "skel_create", "skel_build", "skel_get_numbones", "skel_get_bonename", "skel_get_boneparent", "skel_find_bone", {"FTE_CSQC_SKELETONOBJECTS", NULL, 15,{"skel_create", "skel_build", "skel_get_numbones", "skel_get_bonename", "skel_get_boneparent", "skel_find_bone",
"skel_get_bonerel", "skel_get_boneabs", "skel_set_bone", "skel_premul_bone", "skel_premul_bones", "skel_copybones", "skel_get_bonerel", "skel_get_boneabs", "skel_set_bone", "skel_premul_bone", "skel_premul_bones", "skel_copybones",
"skel_delete", "frameforname", "frameduration"}, "Provides container objects for skeletal bone data, which can be modified on a per bone basis if needed. This allows you to dynamically generate animations (or just blend them with greater customisation) instead of being limited to a single animation or two."}, "skel_delete", "frameforname", "frameduration"}, "Provides container objects for skeletal bone data, which can be modified on a per bone basis if needed. This allows you to dynamically generate animations (or just blend them with greater customisation) instead of being limited to a single animation or two."},
{"FTE_CSQC_RAWIMAGES", 2, NULL, {"r_uploadimage","r_readimage"}, "Provides raw rgba image access to csqc. With this, the csprogs can read textures into qc-accessible memory, modify it, and then upload it to the renderer."}, {"FTE_CSQC_RAWIMAGES", NULL, 2,{"r_uploadimage","r_readimage"}, "Provides raw rgba image access to csqc. With this, the csprogs can read textures into qc-accessible memory, modify it, and then upload it to the renderer."},
{"FTE_CSQC_RENDERTARGETS", 0, NULL, {NULL}, "VF_RT_DESTCOLOUR exists and can be used to redirect any rendering to a texture instead of the screen."}, {"FTE_CSQC_RENDERTARGETS", NULL, 0,{NULL}, "VF_RT_DESTCOLOUR exists and can be used to redirect any rendering to a texture instead of the screen."},
{"FTE_CSQC_REVERB", 1, NULL, {"setup_reverb"}, "Specifies that the mod can create custom reverb effects. Whether they will actually be used or not depends upon the sound driver."}, {"FTE_CSQC_REVERB", NULL, 1,{"setup_reverb"}, "Specifies that the mod can create custom reverb effects. Whether they will actually be used or not depends upon the sound driver."},
{"FTE_CSQC_WINDOWCAPTION", 1, NULL, {"setwindowcaption"}, "Provides csqc with the ability to change the window caption as displayed when running windowed or in the task bar when switched out."}, {"FTE_CSQC_WINDOWCAPTION", NULL, 1,{"setwindowcaption"}, "Provides csqc with the ability to change the window caption as displayed when running windowed or in the task bar when switched out."},
{"FTE_ENT_SKIN_CONTENTS", 0, NULL, {NULL}, "self.skin = CONTENTS_WATER; makes a brush entity into water. use -16 for a ladder."}, {"FTE_ENT_SKIN_CONTENTS", NULL, 0,{NULL}, "self.skin = CONTENTS_WATER; makes a brush entity into water. use -16 for a ladder."},
{"FTE_ENT_UNIQUESPAWNID"}, {"FTE_ENT_UNIQUESPAWNID"},
{"FTE_EXTENDEDTEXTCODES"}, {"FTE_EXTENDEDTEXTCODES"},
{"FTE_FORCESHADER", 1, NULL, {"shaderforname"}, "Allows csqc to override shaders on models with an explicitly named replacement. Also allows you to define shaders with a fallback if it does not exist on disk."}, //I'd rename this to _CSQC_ but it does technically provide this builtin to menuqc too, not that the forceshader entity field exists there... but whatever. {"FTE_FORCESHADER", NULL, 1,{"shaderforname"}, "Allows csqc to override shaders on models with an explicitly named replacement. Also allows you to define shaders with a fallback if it does not exist on disk."}, //I'd rename this to _CSQC_ but it does technically provide this builtin to menuqc too, not that the forceshader entity field exists there... but whatever.
{"FTE_FORCEINFOKEY", 1, NULL, {"forceinfokey"}, "Provides an easy way to change a user's userinfo from the server."}, {"FTE_FORCEINFOKEY", NULL, 1,{"forceinfokey"}, "Provides an easy way to change a user's userinfo from the server."},
{"FTE_GFX_QUAKE3SHADERS", 0, NULL, {NULL}, "specifies that the engine has full support for vanilla quake3 shaders"}, {"FTE_GFX_QUAKE3SHADERS", NULL, 0,{NULL}, "specifies that the engine has full support for vanilla quake3 shaders"},
{"FTE_GFX_REMAPSHADER", 0, NULL, {NULL}, "With the raw power of stuffcmds, the r_remapshader console command is exposed! This mystical command can be used to remap any shader to another. Remapped shaders that specify $diffuse etc in some form will inherit the textures implied by the surface."}, {"FTE_GFX_REMAPSHADER", NULL, 0,{NULL}, "With the raw power of stuffcmds, the r_remapshader console command is exposed! This mystical command can be used to remap any shader to another. Remapped shaders that specify $diffuse etc in some form will inherit the textures implied by the surface."},
// {"FTE_GFX_IQM_HITMESH", 0, NULL, {NULL}, "Supports hitmesh iqm extensions. Also supports geomsets and embedded events."}, {"FTE_GFX_IQM_HITMESH", NULL, 0,{NULL}, "Supports hitmesh iqm extensions. Also supports geomsets and embedded events."},
{"FTE_GFX_MODELEVENTS", 1, NULL, {"processmodelevents", "getnextmodelevent", "getmodeleventidx"}, "Provides a query for per-animation events in model files, including from progs/foo.mdl.events files."}, {"FTE_GFX_MODELEVENTS", NULL, 1,{"processmodelevents", "getnextmodelevent", "getmodeleventidx"}, "Provides a query for per-animation events in model files, including from progs/foo.mdl.events files."},
{"FTE_ISBACKBUFFERED", 1, NULL, {"isbackbuffered"}, "Allows you to check if a client has too many reliable messages pending."}, {"FTE_ISBACKBUFFERED", NULL, 1,{"isbackbuffered"}, "Allows you to check if a client has too many reliable messages pending."},
{"FTE_MEMALLOC", 4, NULL, {"memalloc", "memfree", "memcpy", "memfill8"}, "Allows dynamically allocating memory. Use pointers to access this memory. Memory will not be saved into saved games."}, {"FTE_MEMALLOC", NULL, 4,{"memalloc", "memfree", "memcpy", "memfill8"}, "Allows dynamically allocating memory. Use pointers to access this memory. Memory will not be saved into saved games."},
#ifdef HAVE_MEDIA_DECODER #ifdef HAVE_MEDIA_DECODER
#if defined(_WIN32) && !defined(WINRT) #if defined(_WIN32) && !defined(WINRT)
{"FTE_MEDIA_AVI", 0, NULL, {NULL}, "playfilm command supports avi files."}, {"FTE_MEDIA_AVI", NULL, 0,{NULL}, "playfilm command supports avi files."},
#endif #endif
#ifdef Q2CLIENT #ifdef Q2CLIENT
{"FTE_MEDIA_CIN", 0, NULL, {NULL}, "playfilm command supports q2 cin files."}, {"FTE_MEDIA_CIN", NULL, 0,{NULL}, "playfilm command supports q2 cin files."},
#endif #endif
#ifdef Q3CLIENT #ifdef Q3CLIENT
{"FTE_MEDIA_ROQ", 0, NULL, {NULL}, "playfilm command supports q3 roq files."}, {"FTE_MEDIA_ROQ", NULL, 0,{NULL}, "playfilm command supports q3 roq files."},
#endif #endif
#endif #endif
{"FTE_MULTIPROGS", 5, NULL, {"externcall", "addprogs", "externvalue", "externset", "instr"}, "Multiple progs.dat files can be loaded inside the same qcvm. Insert new ones with addprogs inside the 'init' function, and use externvalue+externset to rewrite globals (and hook functions) to link them together. Note that the result is generally not very clean unless you carefully design for it beforehand."}, //multiprogs functions are available. {"FTE_MULTIPROGS", NULL, 5,{"externcall", "addprogs", "externvalue", "externset", "instr"}, "Multiple progs.dat files can be loaded inside the same qcvm. Insert new ones with addprogs inside the 'init' function, and use externvalue+externset to rewrite globals (and hook functions) to link them together. Note that the result is generally not very clean unless you carefully design for it beforehand."}, //multiprogs functions are available.
{"FTE_MULTITHREADED", 3, NULL, {"sleep", "fork", "abort"}, "Faux multithreading, allowing multiple contexts to run in sequence."}, {"FTE_MULTITHREADED", NULL, 3,{"sleep", "fork", "abort"}, "Faux multithreading, allowing multiple contexts to run in sequence."},
{"FTE_MVD_PLAYERSTATS", 0, NULL, {NULL}, "In csqc, getplayerstat can be used to query any player's stats when playing back MVDs. isdemo will return 2 in this case."}, {"FTE_MVD_PLAYERSTATS", NULL, 0,{NULL}, "In csqc, getplayerstat can be used to query any player's stats when playing back MVDs. isdemo will return 2 in this case."},
#ifdef SERVER_DEMO_PLAYBACK #ifdef SERVER_DEMO_PLAYBACK
{"FTE_MVD_PLAYBACK", NOBI "The server itself is able to play back MVDs."}, {"FTE_MVD_PLAYBACK", NOBI "The server itself is able to play back MVDs."},
#endif #endif
#ifdef SVCHAT #ifdef SVCHAT
{"FTE_QC_NPCCHAT", 1, NULL, {"chat"}}, //server looks at chat files. It automagically branches through calling qc functions as requested. {"FTE_QC_NPCCHAT", NULL, 1,{"chat"}}, //server looks at chat files. It automagically branches through calling qc functions as requested.
#endif #endif
#ifdef PSET_SCRIPT #ifdef PSET_SCRIPT
{"FTE_PART_SCRIPT", 0, NULL, {NULL}, "Specifies that the r_particledesc cvar can be used to select a list of particle effects to load from particles/foo.cfg, the format of which is documented elsewhere."}, {"FTE_PART_SCRIPT", NULL, 0,{NULL}, "Specifies that the r_particledesc cvar can be used to select a list of particle effects to load from particles/foo.cfg, the format of which is documented elsewhere."},
{"FTE_PART_NAMESPACES", 0, NULL, {NULL}, "Specifies that the engine can use foo.bar to load effect foo from particle description bar. When used via ssqc, this should cause the client to download whatever effects as needed."}, {"FTE_PART_NAMESPACES", NULL, 0,{NULL}, "Specifies that the engine can use foo.bar to load effect foo from particle description bar. When used via ssqc, this should cause the client to download whatever effects as needed."},
#ifdef HAVE_LEGACY #ifdef HAVE_LEGACY
{"FTE_PART_NAMESPACE_EFFECTINFO", 0, NULL, {NULL}, "Specifies that effectinfo.bar can load effects from effectinfo.txt for DP compatibility."}, {"FTE_PART_NAMESPACE_EFFECTINFO", NULL, 0,{NULL}, "Specifies that effectinfo.bar can load effects from effectinfo.txt for DP compatibility."},
#endif #endif
#endif #endif
{"FTE_QC_BASEFRAME", 0, NULL, {NULL}, "Specifies that .basebone and .baseframe exist in ssqc. These fields affect all bones in the entity's model with a lower index than the .basebone field, allowing you to give separate control to the legs of a skeletal model, without affecting the torso animations, from ssqc."},
{"FTE_QC_FILE_BINARY", 4, NULL, {"fread","fwrite","fseek","fsize"}, "Extends FRIK_FILE with binary read+write, as well as allowing seeking. Requires pointers."}, {"FTE_PEXT_SETVIEW", check_pext_setview, 0,{NULL}, "NQ's svc_setview works correctly even in quakeworld"},
{"FTE_QC_CHANGELEVEL_HUB", 0, NULL, {NULL}, "Adds an extra argument to changelevel which is carried over to the next map in the 'spawnspot' global. Maps will be saved+reloaded until the extra argument is omitted again, purging all saved maps. Saved games will contain a copy of each preserved map. parm1-parm64 globals can be used, giving more space to transfer more player data."}, {"FTE_PEXT_LIGHTSTYLECOL", check_pext_lightstylecol}, //lightstyles may have colours.
{"FTE_QC_CHECKCOMMAND", 1, NULL, {"checkcommand"}, "Provides a way to test if a console command exists, and whether its a command/alias/cvar. Does not say anything about the expected meanings of any arguments or values."}, {"FTE_PEXT_VIEW2", check_pext_view2}, //secondary view.
{"FTE_QC_CHECKPVS", 1, NULL, {"checkpvs"}}, // {"FTE_PEXT_ACURATETIMINGS", check_pext_senttimings}, //allows full interpolation
{"FTE_QC_CROSSPRODUCT", 1, NULL, {"crossproduct"}}, // {"FTE_PEXT_SOUNDDBL", check_pext_sounddbl}, //twice the sound indexes
{"FTE_QC_CUSTOMSKINS", 1, NULL, {"setcustomskin", "loadcustomskin", "applycustomskin", "releasecustomskin"}, "The engine supports the use of q3 skins, as well as the use of such skin 'files' to specify rich top+bottom colours, qw skins, geomsets, or texture composition even on non-players.."}, {"FTE_PEXT_FATNESS", check_pext_fatness}, //entities may be expanded along their vertex normals
{"FTE_QC_DIGEST_SHA1"}, {"FTE_PEXT_TE_BULLET", check_pext_tebullet}, //additional particle effect. Like TE_SPIKE and TE_SUPERSPIKE
{"FTE_QC_DIGEST_SHA224"}, // {"FTE_PEXT_HULLSIZE", check_pext_}, //means we can tell a client to go to crouching hull
{"FTE_QC_DIGEST_SHA384"}, // {"FTE_PEXT_MODELDBL", check_pext_modeldbl}, //max of 512 models
{"FTE_QC_DIGEST_SHA512"}, // {"FTE_PEXT_ENTITYDBL", check_pext_}, //max of 1024 ents
{"FTE_QC_FS_SEARCH_SIZEMTIME", 2, NULL, {"search_getfilesize", "search_getfilemtime"}}, // {"FTE_PEXT_ENTITYDBL2", check_pext_}, //max of 2048 ents
{"FTE_QC_HARDWARECURSORS", 0, NULL, {NULL}, "setcursormode exists in both csqc+menuqc, and accepts additional arguments to specify a cursor image to use when this module has focus. If the image exceeds hardware limits (or hardware cursors are unsupported), it will be emulated using regular draws - this at least still avoids conflicting cursors as only one will ever be used, even if console+menu+csqc are all overlayed."}, {"FTE_PEXT_FLOATCOORDS", check_pext_floatcoords},
{"FTE_QC_HASHTABLES", 6, NULL, {"hash_createtab", "hash_destroytab", "hash_add", "hash_get", "hash_delete", "hash_getkey"}, "Provides efficient string-based lookups."}, {"FTE_PEXT_Q2BSP", check_pext_q2bsp, 0,{NULL},"Specifies that the client supports q2bsps."},
{"FTE_QC_INFOKEY", 2, NULL, {"infokey", "stof"}, "QuakeWorld's infokey builtin works, and reports at least name+topcolor+bottomcolor+ping(in ms)+ip(unmasked, but not always ipv4)+team(aka bottomcolor in nq). Does not require actual localinfo/serverinfo/userinfo, but they're _highly_ recommended to any engines with csqc"}, {"FTE_PEXT_Q3BSP", check_pext_q3bsp, 0,{NULL},"Specifies that the client supports q3bsps."}, //quake3 bsp support. dp probably has an equivelent, but this is queryable per client.
{"FTE_QC_INTCONV", 6, NULL, {"stoi", "itos", "stoh", "htos", "itof", "ftoi"}, "Provides string<>int conversions, including hex representations."}, {"FTE_HEXEN2", check_pext_hexen2, 3,{"particle2", "particle3", "particle4"}}, //client can use hexen2 maps. server can use hexen2 progs
{"FTE_QC_MATCHCLIENTNAME", 1, NULL, {"matchclientname"}}, {"FTE_PEXT_SPAWNSTATIC", check_pext_spawnstatic}, //means that static entities can have alpha/scale and anything else the engine supports on normal ents. (Added for >256 models, while still being compatible - previous system failed with -1 skins)
{"FTE_QC_MULTICAST", 1, NULL, {"multicast"}, "QuakeWorld's multicast builtin works along with MSG_MULTICAST, but also with unicast support."}, {"FTE_PEXT_CUSTOMTENTS", check_pext_customtempeffects, 2,{"RegisterTempEnt", "CustomTempEnt"}},
// {"FTE_QC_MESHOBJECTS", 0, NULL, {"mesh_create", "mesh_build", "mesh_getvertex", "mesh_getindex", "mesh_setvertex", "mesh_setindex", "mesh_destroy"}, "Provides qc with the ability to create its own meshes."}, {"FTE_PEXT_256PACKETENTITIES", check_pext_256packetentities, 0,{NULL},"Specifies that the client is not limited to vanilla's limit of only 64 ents visible at once."}, //client is able to receive unlimited packet entities (server caps itself to 256 to prevent insanity).
// {"PEXT_CHUNKEDDOWNLOADS", check_pext_chunkeddownloads},
// {"PEXT_DPFLAGS", check_pext_dpflags},
{"FTE_QC_BASEFRAME", NULL, 0,{NULL}, "Specifies that .basebone and .baseframe exist in ssqc. These fields affect all bones in the entity's model with a lower index than the .basebone field, allowing you to give separate control to the legs of a skeletal model, without affecting the torso animations, from ssqc."},
{"FTE_QC_FILE_BINARY", NULL, 4,{"fread","fwrite","fseek","fsize"}, "Extends FRIK_FILE with binary read+write, as well as allowing seeking. Requires pointers."},
{"FTE_QC_CHANGELEVEL_HUB", NULL, 0,{NULL}, "Adds an extra argument to changelevel which is carried over to the next map in the 'spawnspot' global. Maps will be saved+reloaded until the extra argument is omitted again, purging all saved maps. Saved games will contain a copy of each preserved map. parm1-parm64 globals can be used, giving more space to transfer more player data."},
{"FTE_QC_CHECKCOMMAND", NULL, 1,{"checkcommand"}, "Provides a way to test if a console command exists, and whether its a command/alias/cvar. Does not say anything about the expected meanings of any arguments or values."},
{"FTE_QC_CHECKPVS", NULL, 1,{"checkpvs"}},
{"FTE_QC_CROSSPRODUCT", NULL, 1,{"crossproduct"}},
{"FTE_QC_CUSTOMSKINS", NULL, 1,{"setcustomskin", "loadcustomskin", "applycustomskin", "releasecustomskin"}, "The engine supports the use of q3 skins, as well as the use of such skin 'files' to specify rich top+bottom colours, qw skins, geomsets, or texture composition even on non-players.."},
{"FTE_QC_DIGEST_SHA1", NOBI "The digest_hex builtin supports 160-bit sha1 hashes."},
{"FTE_QC_DIGEST_SHA224", NOBI "The digest_hex builtin supports 224-bit sha2 hashes."},
{"FTE_QC_DIGEST_SHA384", NOBI "The digest_hex builtin supports 384-bit sha2 hashes."},
{"FTE_QC_DIGEST_SHA512", NOBI "The digest_hex builtin supports 512-bit sha2 hashes."},
{"FTE_QC_FS_SEARCH_SIZEMTIME", NULL, 2,{"search_getfilesize", "search_getfilemtime"}},
{"FTE_QC_HARDWARECURSORS", NULL, 0,{NULL}, "setcursormode exists in both csqc+menuqc, and accepts additional arguments to specify a cursor image to use when this module has focus. If the image exceeds hardware limits (or hardware cursors are unsupported), it will be emulated using regular draws - this at least still avoids conflicting cursors as only one will ever be used, even if console+menu+csqc are all overlayed."},
{"FTE_QC_HASHTABLES", NULL, 6,{"hash_createtab", "hash_destroytab", "hash_add", "hash_get", "hash_delete", "hash_getkey"}, "Provides efficient string-based lookups."},
{"FTE_QC_INFOKEY", NULL, 2,{"infokey", "stof"}, "QuakeWorld's infokey builtin works, and reports at least name+topcolor+bottomcolor+ping(in ms)+ip(unmasked, but not always ipv4)+team(aka bottomcolor in nq). Does not require actual localinfo/serverinfo/userinfo, but they're _highly_ recommended to any engines with csqc"},
{"FTE_QC_INTCONV", NULL, 6,{"stoi", "itos", "stoh", "htos", "itof", "ftoi"}, "Provides string<>int conversions, including hex representations."},
{"FTE_QC_MATCHCLIENTNAME", NULL, 1,{"matchclientname"}},
{"FTE_QC_MULTICAST", NULL, 1,{"multicast"}, "QuakeWorld's multicast builtin works along with MSG_MULTICAST, but also with unicast support."},
// {"FTE_QC_MESHOBJECTS", NULL, 0,{"mesh_create", "mesh_build", "mesh_getvertex", "mesh_getindex", "mesh_setvertex", "mesh_setindex", "mesh_destroy"}, "Provides qc with the ability to create its own meshes."},
{"FTE_QC_PAUSED"}, {"FTE_QC_PAUSED"},
#ifdef QCGC #ifdef QCGC
{"FTE_QC_PERSISTENTTEMPSTRINGS", NOBI "Supersedes DP_QC_MULTIPLETEMPSTRINGS. Temp strings are garbage collected automatically, and do not expire while they're still in use. This makes strzone redundant."}, {"FTE_QC_PERSISTENTTEMPSTRINGS", NOBI "Supersedes DP_QC_MULTIPLETEMPSTRINGS. Temp strings are garbage collected automatically, and do not expire while they're still in use. This makes strzone redundant."},
#endif #endif
#ifdef RAGDOLL #ifdef RAGDOLL
{"FTE_QC_RAGDOLL_WIP", 1, NULL, {"ragupdate", "skel_set_bone_world", "skel_mmap"}}, {"FTE_QC_RAGDOLL_WIP", NULL, 1,{"ragupdate", "skel_set_bone_world", "skel_mmap"}},
#endif #endif
{"FTE_QC_SENDPACKET", 1, NULL, {"sendpacket"}, "Allows the use of out-of-band udp packets to/from other hosts. Includes the SV_ParseConnectionlessPacket event."}, {"FTE_QC_SENDPACKET", NULL, 1,{"sendpacket"}, "Allows the use of out-of-band udp packets to/from other hosts. Includes the SV_ParseConnectionlessPacket event."},
{"FTE_QC_STUFFCMDFLAGS", 1, NULL, {"stuffcmdflags"}, "Variation on regular stuffcmd that gives control over how spectators/mvds should be treated."}, {"FTE_QC_STUFFCMDFLAGS", NULL, 1,{"stuffcmdflags"}, "Variation on regular stuffcmd that gives control over how spectators/mvds should be treated."},
{"FTE_QC_TRACETRIGGER"}, {"FTE_QC_TRACETRIGGER"},
#ifdef Q2CLIENT #ifdef Q2CLIENT
{"FTE_QUAKE2_CLIENT", 0, NULL, {NULL}, "This engine is able to act as a quake2 client"}, {"FTE_QUAKE2_CLIENT", NULL, 0,{NULL}, "This engine is able to act as a quake2 client"},
#endif #endif
#ifdef Q2SERVER #ifdef Q2SERVER
{"FTE_QUAKE2_SERVER", 0, NULL, {NULL}, "This engine is able to act as a quake2 server"}, {"FTE_QUAKE2_SERVER", NULL, 0,{NULL}, "This engine is able to act as a quake2 server"},
#endif #endif
#ifdef Q3CLIENT #ifdef Q3CLIENT
{"FTE_QUAKE3_CLIENT", 0, NULL, {NULL}, "This engine is able to act as a quake3 client"}, {"FTE_QUAKE3_CLIENT", NULL, 0,{NULL}, "This engine is able to act as a quake3 client"},
#endif #endif
#ifdef Q3SERVER #ifdef Q3SERVER
{"FTE_QUAKE3_SERVER", 0, NULL, {NULL}, "This engine is able to act as a quake3 server"}, {"FTE_QUAKE3_SERVER", NULL, 0,{NULL}, "This engine is able to act as a quake3 server"},
#endif #endif
{"FTE_SOLID_LADDER", NOBI "Allows a simple trigger to remove effects of gravity (solid 20). obsolete. will prolly be removed at some point as it is not networked properly. Use FTE_ENT_SKIN_CONTENTS"}, {"FTE_SOLID_LADDER", NOBI "Allows a simple trigger to remove effects of gravity (solid 20). obsolete. will prolly be removed at some point as it is not networked properly. Use FTE_ENT_SKIN_CONTENTS"},
{"FTE_SPLITSCREEN", NOBI "Client supports splitscreen, controlled via cl_splitscreen. Servers require allow_splitscreen 1 if splitscreen is to be used over the internet. Mods that use csqc will need to be aware for this to work properly. per-client networking may be problematic."}, {"FTE_SPLITSCREEN", NOBI "Client supports splitscreen, controlled via cl_splitscreen. Servers require allow_splitscreen 1 if splitscreen is to be used over the internet. Mods that use csqc will need to be aware for this to work properly. per-client networking may be problematic."},
#ifdef SQL #ifdef SQL
// serverside SQL functions for managing an SQL database connection // serverside SQL functions for managing an SQL database connection
{"FTE_SQL", 9, NULL, {"sqlconnect","sqldisconnect","sqlopenquery","sqlclosequery","sqlreadfield","sqlerror","sqlescape","sqlversion", {"FTE_SQL", NULL, 9,{"sqlconnect","sqldisconnect","sqlopenquery","sqlclosequery","sqlreadfield","sqlerror","sqlescape","sqlversion",
"sqlreadfloat"}, "Provides sql* builtins which can be used for sql database access"}, "sqlreadfloat"}, "Provides sql* builtins which can be used for sql database access"},
#ifdef USE_MYSQL #ifdef USE_MYSQL
{"FTE_SQL_MYSQL", 0, NULL, {NULL}, "SQL functionality is able to utilise mysql"}, {"FTE_SQL_MYSQL", NULL, 0, NULL, {NULL}, "SQL functionality is able to utilise mysql"},
#endif #endif
#ifdef USE_SQLITE #ifdef USE_SQLITE
{"FTE_SQL_SQLITE", 0, NULL, {NULL}, "SQL functionality is able to utilise sqlite databases"}, {"FTE_SQL_SQLITE", NULL, 0,{NULL}, "SQL functionality is able to utilise sqlite databases"},
#endif #endif
#endif #endif
//eperimental advanced strings functions. //eperimental advanced strings functions.
//reuses the FRIK_FILE builtins (with substring extension) //reuses the FRIK_FILE builtins (with substring extension)
{"FTE_STRINGS", 17, NULL, {"stof", "strlen","strcat","substring","stov","strzone","strunzone", {"FTE_STRINGS", NULL, 17,{"stof", "strlen","strcat","substring","stov","strzone","strunzone",
"strstrofs", "str2chr", "chr2str", "strconv", "infoadd", "infoget", "strncmp", "strcasecmp", "strncasecmp", "strpad"}, "Extra builtins (and additional behaviour) to make string manipulation easier"}, "strstrofs", "str2chr", "chr2str", "strconv", "infoadd", "infoget", "strncmp", "strcasecmp", "strncasecmp", "strpad"}, "Extra builtins (and additional behaviour) to make string manipulation easier"},
{"FTE_SV_POINTPARTICLES", 3, NULL, {"particleeffectnum", "pointparticles", "trailparticles"}, "Specifies that particleeffectnum, pointparticles, and trailparticles exist in ssqc as well as csqc. particleeffectnum acts as a precache, allowing ssqc values to be networked up with csqc for use. Use in combination with FTE_PART_SCRIPT+FTE_PART_NAMESPACES to use custom effects. This extension is functionally identical to the DP version, but avoids any misplaced assumptions about the format of the client's particle descriptions."}, {"FTE_SV_POINTPARTICLES", check_pext_pointparticle, 3,{"particleeffectnum", "pointparticles", "trailparticles"}, "Specifies that particleeffectnum, pointparticles, and trailparticles exist in ssqc as well as csqc. particleeffectnum acts as a precache, allowing ssqc values to be networked up with csqc for use. Use in combination with FTE_PART_SCRIPT+FTE_PART_NAMESPACES to use custom effects. This extension is functionally identical to the DP version, but avoids any misplaced assumptions about the format of the client's particle descriptions."},
{"FTE_SV_REENTER"}, {"FTE_SV_REENTER"},
{"FTE_TE_STANDARDEFFECTBUILTINS", 14, NULL, {"te_gunshot", "te_spike", "te_superspike", "te_explosion", "te_tarexplosion", "te_wizspike", "te_knightspike", "te_lavasplash", {"FTE_TE_STANDARDEFFECTBUILTINS", NULL, 14,{"te_gunshot", "te_spike", "te_superspike", "te_explosion", "te_tarexplosion", "te_wizspike", "te_knightspike", "te_lavasplash",
"te_teleport", "te_lightning1", "te_lightning2", "te_lightning3", "te_lightningblood", "te_bloodqw"}, "Provides builtins to replace writebytes, with a QW compatible twist."}, "te_teleport", "te_lightning1", "te_lightning2", "te_lightning3", "te_lightningblood", "te_bloodqw"}, "Provides builtins to replace writebytes, with a QW compatible twist."},
#ifdef TERRAIN #ifdef TERRAIN
{"FTE_TERRAIN_MAP", 1, NULL, {"terrain_edit"}, "This engine supports .hmp files, as well as terrain embedded within bsp files."}, {"FTE_TERRAIN_MAP", NULL, 1,{"terrain_edit"}, "This engine supports .hmp files, as well as terrain embedded within bsp files."},
{"FTE_RAW_MAP", 7, NULL, {"brush_get","brush_create","brush_delete","brush_selected","brush_getfacepoints","brush_calcfacepoints","brush_findinvolume"}, "This engine supports directly loading .map files, as well as realtime editing of the various brushes."}, {"FTE_RAW_MAP", NULL, 7,{"brush_get","brush_create","brush_delete","brush_selected","brush_getfacepoints","brush_calcfacepoints","brush_findinvolume"}, "This engine supports directly loading .map files, as well as realtime editing of the various brushes."},
#endif #endif
{"KRIMZON_SV_PARSECLIENTCOMMAND", 3, NULL, {"clientcommand", "tokenize", "argv"}, "SSQC's SV_ParseClientCommand function is able to handle client 'cmd' commands. The tokenizing parts also work in csqc."}, //very very similar to the mvdsv system. {"KRIMZON_SV_PARSECLIENTCOMMAND", NULL, 3,{"clientcommand", "tokenize", "argv"}, "SSQC's SV_ParseClientCommand function is able to handle client 'cmd' commands. The tokenizing parts also work in csqc."}, //very very similar to the mvdsv system.
{"NEH_CMD_PLAY2"}, {"NEH_CMD_PLAY2"},
{"NEH_RESTOREGAME"}, {"NEH_RESTOREGAME"},
//{"PRYDON_CLIENTCURSOR"}, //{"PRYDON_CLIENTCURSOR", check_pext2_prydoncursor},
{"QSG_CVARSTRING", 1, NULL, {"qsg_cvar_string"}}, {"QSG_CVARSTRING", NULL, 1,{"qsg_cvar_string"}},
{"QW_ENGINE", 3, NULL, {"infokey", "stof", "logfrag"}}, //warning: interpretation of .skin on players can be dodgy, as can some other QW features that differ from NQ. {"QW_ENGINE", NULL, 3,{"infokey", "stof", "logfrag"}}, //warning: interpretation of .skin on players can be dodgy, as can some other QW features that differ from NQ.
{"QWE_MVD_RECORD", NOBI "You can use the easyrecord command to record MVD demos serverside."}, //Quakeworld extended get the credit for this one. (mvdsv) {"QWE_MVD_RECORD", NOBI "You can use the easyrecord command to record MVD demos serverside."}, //Quakeworld extended get the credit for this one. (mvdsv)
{"TEI_MD3_MODEL"}, {"TEI_MD3_MODEL"},
{"TENEBRAE_GFX_DLIGHTS", 0, NULL,{NULL}, "Allows ssqc to attach rtlights to entities with various special properties."}, {"TEI_SHOWLMP2", check_pext_showpic, 6,{"showpic", "hidepic", "movepic", "changepic", "showpicent", "hidepicent"}}, //telejano doesn't actually export the moveent/changeent (we don't want to either cos it would stop frik_file stuff being autoregistered)
{"TENEBRAE_GFX_DLIGHTS", NULL, 0,{NULL}, "Allows ssqc to attach rtlights to entities with various special properties."},
// {"TQ_RAILTRAIL"}, //treat this as the ZQ style railtrails which the client already supports, okay so the preparse stuff needs strengthening. // {"TQ_RAILTRAIL"}, //treat this as the ZQ style railtrails which the client already supports, okay so the preparse stuff needs strengthening.
{"ZQ_MOVETYPE_FLY", NOBI "MOVETYPE_FLY works on players."}, {"ZQ_MOVETYPE_FLY", NOBI "MOVETYPE_FLY works on players."},
{"ZQ_MOVETYPE_NOCLIP", NOBI "MOVETYPE_NOCLIP works on players."}, {"ZQ_MOVETYPE_NOCLIP", NOBI "MOVETYPE_NOCLIP works on players."},
{"ZQ_MOVETYPE_NONE", NOBI "MOVETYPE_NONE works on players."}, {"ZQ_MOVETYPE_NONE", NOBI "MOVETYPE_NONE works on players."},
// {"ZQ_QC_PARTICLE"}, //particle builtin works in QW ( we don't mimic ZQ fully though) // {"ZQ_QC_PARTICLE"}, //particle builtin works in QW ( we don't mimic ZQ fully though)
{"ZQ_VWEP", 1, NULL, {"precache_vwep_model"}}, {"ZQ_VWEP", NULL, 1,{"precache_vwep_model"}},
{"ZQ_QC_STRINGS", 7, NULL, {"stof", "strlen","strcat","substring","stov","strzone","strunzone"}, "The strings-only subset of FRIK_FILE is supported."} //a trimmed down FRIK_FILE. {"ZQ_QC_STRINGS", NULL, 7,{"stof", "strlen","strcat","substring","stov","strzone","strunzone"}, "The strings-only subset of FRIK_FILE is supported."} //a trimmed down FRIK_FILE.
}; };
unsigned int QSG_Extensions_count = sizeof(QSG_Extensions)/sizeof(QSG_Extensions[0]); unsigned int QSG_Extensions_count = sizeof(QSG_Extensions)/sizeof(QSG_Extensions[0]);
#endif #endif

View File

@ -41,18 +41,22 @@ struct wedict_s
#define G_PROG G_FLOAT #define G_PROG G_FLOAT
//the lh extension system asks for a name for the extension. //the checkextension system asks for a name for the extension.
//the ebfs version is a function that returns a builtin number. //the ebfs version is a function that returns a builtin number.
//thus lh's system requires various builtins to exist at specific numbers. //thus this system requires various builtins to exist at specific numbers.
typedef struct lh_extension_s { //this competes against checkbuiltin(funcreference).
typedef struct {
unsigned int pext1, pext2;
} extcheck_t;
typedef struct qc_extension_s {
char *name; char *name;
qboolean(*extensioncheck)(extcheck_t *info);
int numbuiltins; int numbuiltins;
qboolean *queried;
char *builtinnames[21]; //extend freely char *builtinnames[21]; //extend freely
char *description; char *description;
} lh_extension_t; } qc_extension_t;
extern lh_extension_t QSG_Extensions[]; extern qc_extension_t QSG_Extensions[];
extern unsigned int QSG_Extensions_count; extern unsigned int QSG_Extensions_count;
pbool QDECL QC_WriteFile(const char *name, void *data, int len); pbool QDECL QC_WriteFile(const char *name, void *data, int len);
@ -685,6 +689,7 @@ typedef struct
void (QDECL *VectorAngles)(const float *forward, const float *up, float *result, qboolean meshpitch); void (QDECL *VectorAngles)(const float *forward, const 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);
#define plugrbefuncs_name "RBE"
} rbeplugfuncs_t; } rbeplugfuncs_t;
#define RBEPLUGFUNCS_VERSION 1 #define RBEPLUGFUNCS_VERSION 1
@ -856,7 +861,8 @@ enum lightfield_e
lfield_rgbdecay=15, lfield_rgbdecay=15,
lfield_radiusdecay=16, lfield_radiusdecay=16,
lfield_stylestring=17, lfield_stylestring=17,
lfield_nearclip=18 lfield_nearclip=18,
lfield_owner=19,
}; };
enum csqc_input_event enum csqc_input_event
{ {
@ -1107,13 +1113,28 @@ enum
globalfloat (input_buttons) /*float filled by getinputstate, read by runplayerphysics*/ \ globalfloat (input_buttons) /*float filled by getinputstate, read by runplayerphysics*/ \
globalfloat (input_impulse) /*float filled by getinputstate, read by runplayerphysics*/ \ globalfloat (input_impulse) /*float filled by getinputstate, read by runplayerphysics*/ \
globalfloat (input_lightlevel) /*unused float filled by getinputstate, read by runplayerphysics*/ \ globalfloat (input_lightlevel) /*unused float filled by getinputstate, read by runplayerphysics*/ \
globalfloat (input_weapon) /*unused float filled by getinputstate, read by runplayerphysics*/ \ globaluint (input_weapon) /*unused float filled by getinputstate, read by runplayerphysics*/ \
globalfloat (input_servertime) /*float filled by getinputstate, read by runplayerphysics*/ \ globalfloat (input_servertime) /*float filled by getinputstate, read by runplayerphysics*/ \
globalfloat (input_clienttime) /*float filled by getinputstate, read by runplayerphysics*/ \ globalfloat (input_clienttime) /*float filled by getinputstate, read by runplayerphysics*/ \
globalvector(input_cursor_screen) /*float filled by getinputstate*/ \ globalvector(input_cursor_screen) /*float filled by getinputstate*/ \
globalvector(input_cursor_trace_start) /*float filled by getinputstate*/ \ globalvector(input_cursor_trace_start) /*float filled by getinputstate*/ \
globalvector(input_cursor_trace_endpos) /*float filled by getinputstate*/ \ globalvector(input_cursor_trace_endpos) /*float filled by getinputstate*/ \
globalfloat (input_cursor_entitynumber) /*float filled by getinputstate*/ \ globalfloat (input_cursor_entitynumber) /*float filled by getinputstate*/ \
globaluint (input_head_status) /*filled by getinputstate, for vr*/ \
globalvector(input_head_origin) /*filled by getinputstate, for vr*/ \
globalvector(input_head_angles) /*filled by getinputstate, for vr*/ \
globalvector(input_head_velocity) /*filled by getinputstate, for vr*/ \
globalvector(input_head_avelocity) /*filled by getinputstate, for vr*/ \
globaluint (input_left_status) /*filled by getinputstate, for vr*/ \
globalvector(input_left_origin) /*filled by getinputstate, for vr*/ \
globalvector(input_left_angles) /*filled by getinputstate, for vr*/ \
globalvector(input_left_velocity) /*filled by getinputstate, for vr*/ \
globalvector(input_left_avelocity) /*filled by getinputstate, for vr*/ \
globaluint (input_right_status) /*filled by getinputstate, for vr*/ \
globalvector(input_right_origin) /*filled by getinputstate, for vr*/ \
globalvector(input_right_angles) /*filled by getinputstate, for vr*/ \
globalvector(input_right_velocity) /*filled by getinputstate, for vr*/ \
globalvector(input_right_avelocity) /*filled by getinputstate, for vr*/ \
\ \
globalvector(global_gravitydir) /*vector used when .gravitydir is 0 0 0 */ \ globalvector(global_gravitydir) /*vector used when .gravitydir is 0 0 0 */ \
globalfloat (dimension_default) /*float default value for dimension_hit+dimension_solid*/ \ globalfloat (dimension_default) /*float default value for dimension_hit+dimension_solid*/ \

View File

@ -83,8 +83,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define PEXT2_NEWSIZEENCODING 0x00000040 //richer size encoding. #define PEXT2_NEWSIZEENCODING 0x00000040 //richer size encoding.
#define PEXT2_INFOBLOBS 0x00000080 //serverinfo+userinfo lengths can be MUCH higher (protocol is unbounded, but expect low sanity limits on userinfo), and contain nulls etc. #define PEXT2_INFOBLOBS 0x00000080 //serverinfo+userinfo lengths can be MUCH higher (protocol is unbounded, but expect low sanity limits on userinfo), and contain nulls etc.
#define PEXT2_STUNAWARE 0x00000100 //changes the netchan to biased-bigendian (so lead two bits are 1 and not stun's 0, so we don't get confused) #define PEXT2_STUNAWARE 0x00000100 //changes the netchan to biased-bigendian (so lead two bits are 1 and not stun's 0, so we don't get confused)
//#define PEXT2_NEWINTENTS 0x00000200 //clc_move changes, more buttons etc. vr stuff! #define PEXT2_VRINPUTS 0x00000200 //clc_move changes, more buttons etc. vr stuff!
#define PEXT2_CLIENTSUPPORT (PEXT2_PRYDONCURSOR|PEXT2_VOICECHAT|PEXT2_SETANGLEDELTA|PEXT2_REPLACEMENTDELTAS|PEXT2_MAXPLAYERS|PEXT2_PREDINFO|PEXT2_NEWSIZEENCODING|PEXT2_INFOBLOBS|PEXT2_STUNAWARE) #define PEXT2_CLIENTSUPPORT (PEXT2_PRYDONCURSOR|PEXT2_VOICECHAT|PEXT2_SETANGLEDELTA|PEXT2_REPLACEMENTDELTAS|PEXT2_MAXPLAYERS|PEXT2_PREDINFO|PEXT2_NEWSIZEENCODING|PEXT2_INFOBLOBS|PEXT2_STUNAWARE|PEXT2_VRINPUTS)
//EzQuake/Mvdsv extensions. (use ezquake name, to avoid confusion about .mvd format and its protocol differences) //EzQuake/Mvdsv extensions. (use ezquake name, to avoid confusion about .mvd format and its protocol differences)
#define EZPEXT1_FLOATENTCOORDS 0x00000001 //quirky - doesn't apply to broadcasts, just players+ents. this gives more precision, but will bug out if you try using it to increase map bounds in ways that may not be immediately apparent. iiuc this was added instead of fixing some inconsistent rounding... #define EZPEXT1_FLOATENTCOORDS 0x00000001 //quirky - doesn't apply to broadcasts, just players+ents. this gives more precision, but will bug out if you try using it to increase map bounds in ways that may not be immediately apparent. iiuc this was added instead of fixing some inconsistent rounding...
@ -147,6 +147,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define PORT_QWMASTER 27000 #define PORT_QWMASTER 27000
#define PORT_QWSERVER 27500 #define PORT_QWSERVER 27500
#define PORT_H2SERVER 26900 #define PORT_H2SERVER 26900
#define PORT_Q2MASTER 27900
#define PORT_Q2CLIENT 27901 #define PORT_Q2CLIENT 27901
#define PORT_Q2SERVER 27910 #define PORT_Q2SERVER 27910
#define PORT_Q3MASTER 27950 #define PORT_Q3MASTER 27950
@ -1200,9 +1201,9 @@ typedef struct usercmd_s
//end q2 compat //end q2 compat
float msec; //replace msec, but with more precision float msec; //replace msec, but with more precision
int buttons; //replaces buttons, but with more bits. unsigned int buttons; //replaces buttons, but with more bits.
int weapon; //q3 has a separate weapon field to supplement impulse. unsigned int weapon;//q3 has a separate weapon field to supplement impulse.
int servertime; //q3 networks the time in order to calculate msecs unsigned int servertime; //q3 networks the time in order to calculate msecs
float fservertime;//used as part of nq msec calcs float fservertime;//used as part of nq msec calcs
float fclienttime;//not used? float fclienttime;//not used?
@ -1210,7 +1211,24 @@ typedef struct usercmd_s
vec2_t cursor_screen; vec2_t cursor_screen;
vec3_t cursor_start; vec3_t cursor_start;
vec3_t cursor_impact; vec3_t cursor_impact;
int cursor_entitynumber; unsigned int cursor_entitynumber;
//vr things
struct
{
unsigned int status;
#define VRSTATUS_ORG (1u<<0)
#define VRSTATUS_ANG (1u<<1)
#define VRSTATUS_VEL (1u<<2)
#define VRSTATUS_AVEL (1u<<3)
short angles[3];
short avelocity[3];
vec3_t origin;
vec3_t velocity;
#define VRDEV_LEFT 0
#define VRDEV_RIGHT 1
#define VRDEV_HEAD 2
} vr[3]; //left, right, head.
} usercmd_t; } usercmd_t;
typedef struct q2usercmd_s typedef struct q2usercmd_s

View File

@ -3,6 +3,7 @@
#include "pr_common.h" #include "pr_common.h"
#include "shader.h" #include "shader.h"
#include "com_bih.h"
extern cvar_t r_decal_noperpendicular; extern cvar_t r_decal_noperpendicular;
extern cvar_t mod_loadsurfenvmaps; extern cvar_t mod_loadsurfenvmaps;
@ -1047,7 +1048,7 @@ qboolean Q1BSP_RecursiveHullCheck (hull_t *hull, int num, float p1f, float p2f,
} }
#endif #endif
#ifdef Q1BSPS #if 0//def Q1BSPS
/* /*
the bsp tree we're walking through is the renderable hull the bsp tree we're walking through is the renderable hull
@ -1325,44 +1326,29 @@ static void Q1BSP_RecursiveBrushCheck (struct traceinfo_s *traceinfo, mnode_t *n
} }
#endif //Q1BSPS #endif //Q1BSPS
static unsigned int Q1BSP_TranslateContents(int contents) static unsigned int Q1BSP_TranslateContents(enum q1contents_e contents)
{ {
switch(contents) safeswitch(contents)
{ {
case Q1CONTENTS_EMPTY: case Q1CONTENTS_EMPTY: return FTECONTENTS_EMPTY;
return FTECONTENTS_EMPTY; case Q1CONTENTS_SOLID: return FTECONTENTS_SOLID;
case Q1CONTENTS_SOLID: case Q1CONTENTS_WATER: return FTECONTENTS_WATER;
return FTECONTENTS_SOLID; case Q1CONTENTS_SLIME: return FTECONTENTS_SLIME;
case Q1CONTENTS_WATER: case Q1CONTENTS_LAVA: return FTECONTENTS_LAVA;
return FTECONTENTS_WATER; case Q1CONTENTS_SKY: return FTECONTENTS_SKY|FTECONTENTS_PLAYERCLIP|FTECONTENTS_MONSTERCLIP;
case Q1CONTENTS_SLIME: case Q1CONTENTS_LADDER: return FTECONTENTS_LADDER;
return FTECONTENTS_SLIME; case Q1CONTENTS_CLIP: return FTECONTENTS_PLAYERCLIP|FTECONTENTS_MONSTERCLIP;
case Q1CONTENTS_LAVA: case Q1CONTENTS_CURRENT_0: return FTECONTENTS_WATER|Q2CONTENTS_CURRENT_0; //q2 is better than nothing, right?
return FTECONTENTS_LAVA; case Q1CONTENTS_CURRENT_90: return FTECONTENTS_WATER|Q2CONTENTS_CURRENT_90;
case Q1CONTENTS_SKY: case Q1CONTENTS_CURRENT_180: return FTECONTENTS_WATER|Q2CONTENTS_CURRENT_180;
return FTECONTENTS_SKY|FTECONTENTS_PLAYERCLIP|FTECONTENTS_MONSTERCLIP; case Q1CONTENTS_CURRENT_270: return FTECONTENTS_WATER|Q2CONTENTS_CURRENT_270;
case Q1CONTENTS_LADDER: case Q1CONTENTS_CURRENT_UP: return FTECONTENTS_WATER|Q2CONTENTS_CURRENT_UP;
return FTECONTENTS_LADDER; case Q1CONTENTS_CURRENT_DOWN: return FTECONTENTS_WATER|Q2CONTENTS_CURRENT_DOWN;
case Q1CONTENTS_CLIP: case Q1CONTENTS_TRANS: return FTECONTENTS_SOLID;
return FTECONTENTS_PLAYERCLIP|FTECONTENTS_MONSTERCLIP; case Q1CONTENTS_MONSTERCLIP: return FTECONTENTS_MONSTERCLIP;
case Q1CONTENTS_TRANS: case Q1CONTENTS_PLAYERCLIP: return FTECONTENTS_PLAYERCLIP;
return FTECONTENTS_SOLID;
//q2 is better than nothing, right? safedefault:
case Q1CONTENTS_FLOW_1:
return Q2CONTENTS_CURRENT_0;
case Q1CONTENTS_FLOW_2:
return Q2CONTENTS_CURRENT_90;
case Q1CONTENTS_FLOW_3:
return Q2CONTENTS_CURRENT_180;
case Q1CONTENTS_FLOW_4:
return Q2CONTENTS_CURRENT_270;
case Q1CONTENTS_FLOW_5:
return Q2CONTENTS_CURRENT_UP;
case Q1CONTENTS_FLOW_6:
return Q2CONTENTS_CURRENT_DOWN;
default:
Con_Printf("Q1BSP_TranslateContents: Unknown contents type - %i", contents); Con_Printf("Q1BSP_TranslateContents: Unknown contents type - %i", contents);
return FTECONTENTS_SOLID; return FTECONTENTS_SOLID;
} }
@ -1403,116 +1389,120 @@ unsigned int Q1BSP_PointContents(model_t *model, const vec3_t axis[3], const vec
void Q1BSP_LoadBrushes(model_t *model, bspx_header_t *bspx, void *mod_base) void Q1BSP_LoadBrushes(model_t *model, bspx_header_t *bspx, void *mod_base)
{ {
struct { const struct {
unsigned int ver; unsigned int ver;
unsigned int modelnum; unsigned int modelnum;
unsigned int numbrushes; unsigned int numbrushes;
unsigned int numplanes; unsigned int numplanes;
} *permodel; } *srcmodel;
struct { const struct {
float mins[3]; float mins[3];
float maxs[3]; float maxs[3];
signed short contents; signed short contents;
unsigned short numplanes; unsigned short numplanes;
} *perbrush; } *srcbrush;
/* /*
Note to implementors: Note to implementors:
a pointy brush with angles pointier than 90 degrees will extend further than any adjacent brush, thus creating invisible walls with larger expansions. a pointy brush with angles pointier than 90 degrees will extend further than any adjacent brush, thus creating invisible walls with larger expansions.
the engine inserts 6 axial planes acording to the bbox, thus the qbsp need not write any axial planes the engine inserts 6 axial planes acording to the bbox, thus the qbsp need not write any axial planes
note that doing it this way probably isn't good if you want to query textures... note that doing it this way probably isn't good if you want to query textures...
*/ */
struct { const struct{
vec3_t normal; vec3_t normal;
float dist; float dist;
} *perplane; } *srcplane;
static vec3_t axis[3] = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}; static vec3_t axis[3] = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}};
int br, pl, remainingplanes; unsigned int br, pl;
mbrush_t *brush; q2cbrush_t *brush;
mnode_t *rootnode; q2cbrushside_t *sides; //grr!
mplane_t *planes; //bulky?
unsigned int lumpsizeremaining; unsigned int lumpsizeremaining;
unsigned int numplanes;
model->engineflags &= ~MDLF_HASBRUSHES; unsigned int srcver, srcmodelidx, modbrushes, modplanes;
permodel = BSPX_FindLump(bspx, mod_base, "BRUSHLIST", &lumpsizeremaining); srcmodel = BSPX_FindLump(bspx, mod_base, "BRUSHLIST", &lumpsizeremaining);
if (!permodel) if (!srcmodel)
return; return;
while (lumpsizeremaining) while (lumpsizeremaining)
{ {
if (lumpsizeremaining < sizeof(*permodel)) if (lumpsizeremaining < sizeof(*srcmodel))
return; return;
permodel->ver = LittleLong(permodel->ver); srcver = LittleLong(srcmodel->ver);
permodel->modelnum = LittleLong(permodel->modelnum); srcmodelidx = LittleLong(srcmodel->modelnum);
permodel->numbrushes = LittleLong(permodel->numbrushes); modbrushes = LittleLong(srcmodel->numbrushes);
permodel->numplanes = LittleLong(permodel->numplanes); modplanes = LittleLong(srcmodel->numplanes);
if (permodel->ver != 1 || lumpsizeremaining < sizeof(*permodel) + permodel->numbrushes*sizeof(*perbrush) + permodel->numplanes*sizeof(*perplane)) if (srcver != 1 || lumpsizeremaining < sizeof(*srcmodel) + modbrushes*sizeof(*srcmodel) + modplanes*sizeof(*srcplane))
return;
lumpsizeremaining -= ((const char*)(srcmodel+1) + modbrushes*sizeof(*srcbrush) + modplanes*sizeof(*srcplane)) - (const char*)srcmodel;
if (srcmodelidx > model->numsubmodels)
return; return;
//find the correct rootnode for the submodel (submodels are not set up yet). brush = ZG_Malloc(&model->memgroup, sizeof(*brush)*modbrushes +
rootnode = model->nodes; sizeof(*sides)*(modbrushes*6+modplanes) +
if (permodel->modelnum > model->numsubmodels) sizeof(*planes)*(modbrushes*6+modplanes));
return; sides = (void*)(brush + modbrushes);
rootnode += model->submodels[permodel->modelnum].headnode[0]; planes = (void*)(sides + modbrushes*6+modplanes);
model->submodels[srcmodelidx].brushes = brush;
brush = ZG_Malloc(&model->memgroup, (sizeof(*brush) - sizeof(brush->planes[0]))*permodel->numbrushes + sizeof(brush->planes[0])*(permodel->numbrushes*6+permodel->numplanes)); srcbrush = (const void*)(srcmodel+1);
remainingplanes = permodel->numplanes; for (br = 0; br < modbrushes; br++, srcbrush = (const void*)srcplane)
perbrush = (void*)(permodel+1);
for (br = 0; br < permodel->numbrushes; br++)
{ {
/*byteswap it all in place*/ /*byteswap it all in place*/
perbrush->mins[0] = LittleFloat(perbrush->mins[0]); brush->absmins[0] = LittleFloat(srcbrush->mins[0]);
perbrush->mins[1] = LittleFloat(perbrush->mins[1]); brush->absmins[1] = LittleFloat(srcbrush->mins[1]);
perbrush->mins[2] = LittleFloat(perbrush->mins[2]); brush->absmins[2] = LittleFloat(srcbrush->mins[2]);
perbrush->maxs[0] = LittleFloat(perbrush->maxs[0]); brush->absmaxs[0] = LittleFloat(srcbrush->maxs[0]);
perbrush->maxs[1] = LittleFloat(perbrush->maxs[1]); brush->absmaxs[1] = LittleFloat(srcbrush->maxs[1]);
perbrush->maxs[2] = LittleFloat(perbrush->maxs[2]); brush->absmaxs[2] = LittleFloat(srcbrush->maxs[2]);
perbrush->contents = LittleShort(perbrush->contents); numplanes = (unsigned short)LittleShort(srcbrush->numplanes);
perbrush->numplanes = LittleShort(perbrush->numplanes);
/*make sure planes don't overflow*/ /*make sure planes don't overflow*/
if (perbrush->numplanes > remainingplanes) if (numplanes > modplanes)
return; return;
remainingplanes-=perbrush->numplanes; modplanes-=numplanes;
/*set up the mbrush from the file*/ /*set up the mbrush from the file*/
brush->contents = Q1BSP_TranslateContents(perbrush->contents); brush->contents = Q1BSP_TranslateContents(LittleShort(srcbrush->contents));
brush->numplanes = perbrush->numplanes; brush->brushside = sides;
for (pl = 0, perplane = (void*)(perbrush+1); pl < perbrush->numplanes; pl++, perplane++) for (srcplane = (const void*)(srcbrush+1); numplanes --> 0; srcplane++)
{ {
brush->planes[pl].normal[0] = LittleFloat(perplane->normal[0]); planes->normal[0] = LittleFloat(srcplane->normal[0]);
brush->planes[pl].normal[1] = LittleFloat(perplane->normal[1]); planes->normal[1] = LittleFloat(srcplane->normal[1]);
brush->planes[pl].normal[2] = LittleFloat(perplane->normal[2]); planes->normal[2] = LittleFloat(srcplane->normal[2]);
brush->planes[pl].dist = LittleFloat(perplane->dist); planes->dist = LittleFloat(srcplane->dist);
sides->surface = NULL;
sides++->plane = planes++;
} }
/*and add axial planes acording to the brush's bbox*/ /*and add axial planes acording to the brush's bbox*/
for (pl = 0; pl < 3; pl++) for (pl = 0; pl < 3; pl++)
{ {
VectorCopy(axis[pl], brush->planes[brush->numplanes].normal); VectorCopy(axis[pl], planes->normal);
brush->planes[brush->numplanes].dist = perbrush->maxs[pl]; planes->dist = brush->absmaxs[pl];
brush->numplanes++;
sides->surface = NULL;
sides++->plane = planes++;
} }
for (pl = 0; pl < 3; pl++) for (pl = 0; pl < 3; pl++)
{ {
VectorNegate(axis[pl], brush->planes[brush->numplanes].normal); VectorNegate(axis[pl], planes->normal);
brush->planes[brush->numplanes].dist = -perbrush->mins[pl]; planes->dist = -brush->absmins[pl];
brush->numplanes++;
sides->surface = NULL;
sides++->plane = planes++;
} }
brush->numsides = sides - brush->brushside;
/*link it in to the bsp tree*/ brush++;
Q1BSP_InsertBrush(rootnode, brush, perbrush->mins, perbrush->maxs);
/*set up for the next brush*/
brush = (void*)&brush->planes[brush->numplanes];
perbrush = (void*)perplane;
} }
model->submodels[srcmodelidx].numbrushes = brush-model->submodels[srcmodelidx].brushes;
/*move on to the next model*/ /*move on to the next model*/
lumpsizeremaining -= sizeof(*permodel) + permodel->numbrushes*sizeof(*perbrush) + permodel->numplanes*sizeof(*perplane); srcmodel = (const void*)srcbrush;
permodel = (void*)((char*)permodel + sizeof(*permodel) + permodel->numbrushes*sizeof(*perbrush) + permodel->numplanes*sizeof(*perplane));
} }
/*parsing was successful! flag it as okay*/
model->engineflags |= MDLF_HASBRUSHES;
} }
hull_t *Q1BSP_ChooseHull(model_t *model, int forcehullnum, const vec3_t mins, const vec3_t maxs, vec3_t offset) hull_t *Q1BSP_ChooseHull(model_t *model, int forcehullnum, const vec3_t mins, const vec3_t maxs, vec3_t offset)
@ -1567,82 +1557,6 @@ qboolean Q1BSP_Trace(model_t *model, int forcehullnum, const framestate_t *frame
vec3_t start_l, end_l; vec3_t start_l, end_l;
vec3_t offset; vec3_t offset;
if ((model->engineflags & MDLF_HASBRUSHES))// && (size[0] || size[1] || size[2]))
{
struct traceinfo_s traceinfo;
memset (&traceinfo.trace, 0, sizeof(trace_t));
traceinfo.trace.fraction = 1;
traceinfo.trace.allsolid = false;
VectorCopy(mins, traceinfo.mins);
VectorCopy(maxs, traceinfo.maxs);
if (axis)
{
traceinfo.start[0] = DotProduct(start, axis[0]);
traceinfo.start[1] = DotProduct(start, axis[1]);
traceinfo.start[2] = DotProduct(start, axis[2]);
traceinfo.end[0] = DotProduct(end, axis[0]);
traceinfo.end[1] = DotProduct(end, axis[1]);
traceinfo.end[2] = DotProduct(end, axis[2]);
}
else
{
VectorCopy(start, traceinfo.start);
VectorCopy(end, traceinfo.end);
}
traceinfo.capsule = capsule;
if (traceinfo.capsule)
{
float ext;
traceinfo.capsulesize[0] = ((maxs[0]-mins[0]) + (maxs[1]-mins[1]))/4.0;
traceinfo.capsulesize[1] = maxs[2];
traceinfo.capsulesize[2] = mins[2];
ext = (traceinfo.capsulesize[1] > -traceinfo.capsulesize[2])?traceinfo.capsulesize[1]:-traceinfo.capsulesize[2];
traceinfo.capsulesize[1] -= traceinfo.capsulesize[0];
traceinfo.capsulesize[2] += traceinfo.capsulesize[0];
traceinfo.extents[0] = ext+1;
traceinfo.extents[1] = ext+1;
traceinfo.extents[2] = ext+1;
VectorSet(traceinfo.up, 0, 0, 1);
}
/* traceinfo.sphere = true;
traceinfo.radius = 48;
traceinfo.mins[0] = -traceinfo.radius;
traceinfo.mins[1] = -traceinfo.radius;
traceinfo.mins[2] = -traceinfo.radius;
traceinfo.maxs[0] = traceinfo.radius;
traceinfo.maxs[1] = traceinfo.radius;
traceinfo.maxs[2] = traceinfo.radius;
*/
traceinfo.solidcontents = hitcontentsmask;
Q1BSP_RecursiveBrushCheck(&traceinfo, model->rootnode, 0, 1, traceinfo.start, traceinfo.end);
memcpy(trace, &traceinfo.trace, sizeof(trace_t));
if (trace->fraction < 1)
{
float d1 = DotProduct(start, trace->plane.normal) - trace->plane.dist;
float d2 = DotProduct(end, trace->plane.normal) - trace->plane.dist;
float f = (d1 - DIST_EPSILON) / (d1 - d2);
if (f < 0)
f = 0;
trace->fraction = f;
if (axis)
{
vec3_t iaxis[3];
vec3_t norm;
Matrix3x3_RM_Invert_Simple((const void *)axis, iaxis);
VectorCopy(trace->plane.normal, norm);
trace->plane.normal[0] = DotProduct(norm, iaxis[0]);
trace->plane.normal[1] = DotProduct(norm, iaxis[1]);
trace->plane.normal[2] = DotProduct(norm, iaxis[2]);
}
}
VectorInterpolate(start, trace->fraction, end, trace->endpos);
return trace->fraction != 1;
}
memset (trace, 0, sizeof(trace_t)); memset (trace, 0, sizeof(trace_t));
trace->fraction = 1; trace->fraction = 1;
trace->allsolid = true; trace->allsolid = true;
@ -1793,6 +1707,43 @@ void Q1BSP_MarkLights (dlight_t *light, dlightbitmask_t bit, mnode_t *node)
Q1BSP_MarkLights (light, bit, node->children[1]); Q1BSP_MarkLights (light, bit, node->children[1]);
} }
//combination of R_AddDynamicLights and R_MarkLights
static void Q1BSP_StainNode (mnode_t *node, float *parms)
{
mplane_t *splitplane;
float dist;
msurface_t *surf;
int i;
if (node->contents < 0)
return;
splitplane = node->plane;
dist = DotProduct ((parms+1), splitplane->normal) - splitplane->dist;
if (dist > (*parms))
{
Q1BSP_StainNode (node->children[0], parms);
return;
}
if (dist < (-*parms))
{
Q1BSP_StainNode (node->children[1], parms);
return;
}
// mark the polygons
surf = cl.worldmodel->surfaces + node->firstsurface;
for (i=0 ; i<node->numsurfaces ; i++, surf++)
{
if (surf->flags&~(SURF_DRAWALPHA|SURF_DONTWARP|SURF_PLANEBACK))
continue;
Surf_StainSurf(surf, parms);
}
Q1BSP_StainNode (node->children[0], parms);
Q1BSP_StainNode (node->children[1], parms);
}
#endif #endif
/* /*
Rendering functions (Client only) Rendering functions (Client only)
@ -2227,9 +2178,6 @@ void Q1BSP_SetModelFuncs(model_t *mod)
#endif #endif
mod->funcs.EdictInFatPVS = Q1BSP_EdictInFatPVS; mod->funcs.EdictInFatPVS = Q1BSP_EdictInFatPVS;
mod->funcs.FindTouchedLeafs = Q1BSP_FindTouchedLeafs; mod->funcs.FindTouchedLeafs = Q1BSP_FindTouchedLeafs;
mod->funcs.LightPointValues = NULL;
mod->funcs.StainNode = NULL;
mod->funcs.MarkLights = NULL;
mod->funcs.ClustersInSphere = Q1BSP_ClustersInSphere; mod->funcs.ClustersInSphere = Q1BSP_ClustersInSphere;
mod->funcs.ClusterForPoint = Q1BSP_ClusterForPoint; mod->funcs.ClusterForPoint = Q1BSP_ClusterForPoint;
@ -2237,6 +2185,12 @@ void Q1BSP_SetModelFuncs(model_t *mod)
// mod->funcs.ClusterPHS = Q1BSP_ClusterPHS; // mod->funcs.ClusterPHS = Q1BSP_ClusterPHS;
mod->funcs.NativeTrace = Q1BSP_Trace; mod->funcs.NativeTrace = Q1BSP_Trace;
mod->funcs.PointContents = Q1BSP_PointContents; mod->funcs.PointContents = Q1BSP_PointContents;
#ifndef SERVERONLY
mod->funcs.LightPointValues = GLQ1BSP_LightPointValues;
mod->funcs.MarkLights = Q1BSP_MarkLights;
mod->funcs.StainNode = Q1BSP_StainNode;
#endif
} }
#endif #endif

View File

@ -43,7 +43,7 @@ typedef struct
float frametime; float frametime;
q2csurface_t *groundsurface; const q2csurface_t *groundsurface;
cplane_t groundplane; cplane_t groundplane;
int groundcontents; int groundcontents;

View File

@ -185,9 +185,23 @@ hashfunc_t hash_sha1 =
SHA1Final, SHA1Final,
}; };
unsigned int hashfunc_terminate_uint(const hashfunc_t *func, void *context)
{
size_t CalcHash(hashfunc_t *func, unsigned char *digest, size_t maxdigestsize, const unsigned char *string, size_t stringlen) unsigned int r = 0, l;
unsigned char *digest = alloca(func->digestsize);
func->terminate(digest, context);
for (l = 0; l < func->digestsize; l++)
r ^= digest[l]<<((l%sizeof(r))*8);
return r;
}
unsigned int CalcHashInt(const hashfunc_t *func, const unsigned char *data, size_t datasize)
{
void *ctx = alloca(func->contextsize);
func->init(ctx);
func->process(ctx, data, datasize);
return hashfunc_terminate_uint(func, ctx);
}
size_t CalcHash(const hashfunc_t *func, unsigned char *digest, size_t maxdigestsize, const unsigned char *string, size_t stringlen)
{ {
void *ctx = alloca(func->contextsize); void *ctx = alloca(func->contextsize);
if (maxdigestsize < func->digestsize) if (maxdigestsize < func->digestsize)
@ -232,7 +246,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 CalcHMAC(const 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

@ -61,24 +61,24 @@ typedef struct trace_s
{ {
//DON'T ADD ANYTHING BETWEEN THIS LINE //DON'T ADD ANYTHING BETWEEN THIS LINE
//q2 game dll code will memcpy the lot from trace_t to q2trace_t. //q2 game dll code will memcpy the lot from trace_t to q2trace_t.
qboolean allsolid; // if true, plane is not valid qboolean allsolid; // if true, plane is not valid
qboolean startsolid; // if true, the initial point was in a solid area qboolean startsolid; // if true, the initial point was in a solid area
float fraction; // time completed, 1.0 = didn't hit anything (nudged closer to the start point to cover precision issues) float fraction; // time completed, 1.0 = didn't hit anything (nudged closer to the start point to cover precision issues)
vec3_t endpos; // final position vec3_t endpos; // final position
cplane_t plane; // surface normal at impact cplane_t plane; // surface normal at impact
q2csurface_t *surface; // q2-compat surface hit const q2csurface_t *surface; // q2-compat surface hit
int contents; // contents on other side of surface hit unsigned int contents; // contents on other side of surface hit
void *ent; // not set by CM_*() functions void *ent; // not set by CM_*() functions
//AND THIS LINE //AND THIS LINE
int entnum; int entnum;
qboolean inopen, inwater; qboolean inopen, inwater;
float truefraction; //can be negative, also has floating point precision issues, etc. float truefraction; //can be negative, also has floating point precision issues, etc.
int brush_id; int brush_id;
int brush_face; int brush_face;
int surface_id; int surface_id;
int triangle_id; int triangle_id;
int bone_id; int bone_id;
} trace_t; } trace_t;
typedef struct q2trace_s typedef struct q2trace_s
@ -88,7 +88,7 @@ typedef struct q2trace_s
float fraction; // time completed, 1.0 = didn't hit anything float fraction; // time completed, 1.0 = didn't hit anything
vec3_t endpos; // final position vec3_t endpos; // final position
cplane_t plane; // surface normal at impact cplane_t plane; // surface normal at impact
q2csurface_t *surface; // surface hit const q2csurface_t *surface; // surface hit
int contents; // contents on other side of surface hit int contents; // contents on other side of surface hit
void *ent; // not set by CM_*() functions void *ent; // not set by CM_*() functions
} q2trace_t; } q2trace_t;

View File

@ -519,6 +519,7 @@ void *QDECL ZG_Malloc(zonegroup_t *ctx, size_t size)
#else #else
newm = Z_Malloc(size); newm = Z_Malloc(size);
#endif #endif
newm->next = ctx->first; newm->next = ctx->first;
ctx->first = newm; ctx->first = newm;
ctx->totalbytes += size; ctx->totalbytes += size;

View File

@ -347,7 +347,7 @@ skinid_t Mod_ReadSkinFile(const char *skinname, const char *skintext)
skin->nummappings++; skin->nummappings++;
} }
} }
else if (!strcmp(com_token, "geomset")) else if (!strcmp(com_token, "geomset") || !strcmp(com_token, "meshgroup"))
{ {
int set; int set;
skintext = COM_ParseToken(skintext, NULL); skintext = COM_ParseToken(skintext, NULL);
@ -2826,10 +2826,25 @@ void BE_GenModelBatches(batch_t **batches, const dlight_t *dl, unsigned int bemo
for (i = 0; i < SHADER_SORT_COUNT; i++) for (i = 0; i < SHADER_SORT_COUNT; i++)
batches[i] = NULL; batches[i] = NULL;
if (cl.worldmodel && !(r_refdef.flags & RDF_NOWORLDMODEL))
{
if (cl.worldmodel->terrain)
#if defined(TERRAIN) #if defined(TERRAIN)
if (cl.worldmodel && cl.worldmodel->terrain && !(r_refdef.flags & RDF_NOWORLDMODEL)) Terr_DrawTerrainModel(batches, &r_worldentity);
Terr_DrawTerrainModel(batches, &r_worldentity);
#endif #endif
if (cl.worldmodel->type == mod_alias)
{
r_worldentity.framestate.g[FS_REG].lerpweight[0] = 1;
r_worldentity.scale = 1;
VectorSet(r_worldentity.light_avg, 1.0, 1.0, 1.0);
VectorSet(r_worldentity.light_range, 0.5, 0.5, 0.5);
VectorSet(r_worldentity.light_dir, 0.0, 0.196, 0.98);
r_worldentity.light_known = 1;
R_GAlias_GenerateBatches(&r_worldentity, batches);
}
}
R_Clutter_Emit(batches); R_Clutter_Emit(batches);

View File

@ -1624,7 +1624,7 @@ void GLBE_Init(void)
(!gl_config.tex_env_combine && !gl_config_nofixedfunc) (!gl_config.tex_env_combine && !gl_config_nofixedfunc)
#endif #endif
&& gl_overbright.ival) && gl_overbright.ival)
Cvar_ApplyLatchFlag(&gl_overbright, "0", CVAR_RENDERERLATCH); Cvar_ApplyLatchFlag(&gl_overbright, "0", CVAR_RENDERERLATCH, 0);
shaderstate.shaderbits = ~SBITS_ATEST_BITS; shaderstate.shaderbits = ~SBITS_ATEST_BITS;
BE_SendPassBlendDepthMask(0); BE_SendPassBlendDepthMask(0);
currententity = &r_worldentity; currententity = &r_worldentity;
@ -1770,7 +1770,10 @@ static void GenerateTCFog(int passnum, mfog_t *fog)
for (m = 0; m < shaderstate.meshcount; m++) for (m = 0; m < shaderstate.meshcount; m++)
{ {
mesh = shaderstate.meshes[m]; mesh = shaderstate.meshes[m];
tcgen_fog(texcoordarray[passnum]+mesh->vbofirstvert*2, mesh->numvertexes, (float*)mesh->xyz_array, fog); if (!mesh->xyz_array)
memset(texcoordarray[passnum]+mesh->vbofirstvert*2, 0, mesh->numvertexes*sizeof(float)*2);
else
tcgen_fog(texcoordarray[passnum]+mesh->vbofirstvert*2, mesh->numvertexes, (float*)mesh->xyz_array, fog);
} }
shaderstate.pendingtexcoordparts[passnum] = 2; shaderstate.pendingtexcoordparts[passnum] = 2;

View File

@ -519,7 +519,12 @@ void GLDraw_Init (void)
extern cvar_t vid_srgb; extern cvar_t vid_srgb;
if ((vid.flags & VID_SRGB_CAPABLE) && gl_config.arb_framebuffer_srgb) if ((vid.flags & VID_SRGB_CAPABLE) && gl_config.arb_framebuffer_srgb)
{ //srgb-capable { //srgb-capable
if (!vid_srgb.ival) if (vid.vr)
{ //try to force our rendering to be linear when using vr output.
vid.flags |= VID_SRGB_FB_LINEAR;
qglEnable(GL_FRAMEBUFFER_SRGB);
}
else if (!vid_srgb.ival)
{ //srgb framebuffer not wanted... { //srgb framebuffer not wanted...
qglDisable(GL_FRAMEBUFFER_SRGB); qglDisable(GL_FRAMEBUFFER_SRGB);
vid.flags &= ~VID_SRGB_FB_LINEAR; vid.flags &= ~VID_SRGB_FB_LINEAR;
@ -551,7 +556,7 @@ void GLDraw_Init (void)
qglDisable(GL_SCISSOR_TEST); qglDisable(GL_SCISSOR_TEST);
GL_Set2D(false); GL_Set2D(false);
if (scr_showloading.ival) if (scr_showloading.ival && (!VID_MayRefresh || VID_MayRefresh()))
{ {
extern cvar_t scr_loadingscreen_picture; extern cvar_t scr_loadingscreen_picture;
mpic_t *pic = R2D_SafeCachePic (scr_loadingscreen_picture.string); mpic_t *pic = R2D_SafeCachePic (scr_loadingscreen_picture.string);

View File

@ -61,6 +61,7 @@ static FT_Library fontlib;
#define pFT_New_Face FT_New_Face #define pFT_New_Face FT_New_Face
#define pFT_New_Memory_Face FT_New_Memory_Face #define pFT_New_Memory_Face FT_New_Memory_Face
#define pFT_Done_Face FT_Done_Face #define pFT_Done_Face FT_Done_Face
#define pFT_Error_String FT_Error_String
#else #else
qboolean triedtoloadfreetype; qboolean triedtoloadfreetype;
dllhandle_t *fontmodule; dllhandle_t *fontmodule;
@ -72,6 +73,7 @@ FT_Error (VARGS *pFT_Select_Size) (FT_Face face, FT_Int strike_index);
FT_Error (VARGS *pFT_New_Face) (FT_Library library, const char *pathname, FT_Long face_index, FT_Face *aface); FT_Error (VARGS *pFT_New_Face) (FT_Library library, const char *pathname, FT_Long face_index, FT_Face *aface);
FT_Error (VARGS *pFT_New_Memory_Face) (FT_Library library, const FT_Byte* file_base, FT_Long file_size, FT_Long face_index, FT_Face *aface); FT_Error (VARGS *pFT_New_Memory_Face) (FT_Library library, const FT_Byte* file_base, FT_Long file_size, FT_Long face_index, FT_Face *aface);
FT_Error (VARGS *pFT_Done_Face) (FT_Face face); FT_Error (VARGS *pFT_Done_Face) (FT_Face face);
const char *(VARGS *pFT_Error_String) (FT_Error error_code);
#endif #endif
#else #else
typedef unsigned int FT_Pixel_Mode; //for consistency even without freetype support. typedef unsigned int FT_Pixel_Mode; //for consistency even without freetype support.
@ -1674,6 +1676,7 @@ qboolean Font_LoadFreeTypeFont(struct font_s *f, int height, const char *fontfil
{(void**)&pFT_New_Memory_Face, "FT_New_Memory_Face"}, {(void**)&pFT_New_Memory_Face, "FT_New_Memory_Face"},
{(void**)&pFT_Init_FreeType, "FT_Init_FreeType"}, {(void**)&pFT_Init_FreeType, "FT_Init_FreeType"},
{(void**)&pFT_Done_Face, "FT_Done_Face"}, {(void**)&pFT_Done_Face, "FT_Done_Face"},
{(void**)&pFT_Error_String, "FT_Error_String"},
{NULL, NULL} {NULL, NULL}
}; };
if (triedtoloadfreetype) if (triedtoloadfreetype)
@ -1800,7 +1803,7 @@ qboolean Font_LoadFreeTypeFont(struct font_s *f, int height, const char *fontfil
Z_Free(qface); Z_Free(qface);
} }
if (error && error != FT_Err_Cannot_Open_Resource) if (error && error != FT_Err_Cannot_Open_Resource)
Con_Printf("Freetype error: %i\n", error); Con_Printf("Freetype(%s): error %i - %s\n", fontfilename, error, pFT_Error_String(error));
if (fbase) if (fbase)
BZ_Free(fbase); BZ_Free(fbase);
@ -2067,7 +2070,7 @@ static qboolean Font_LoadFontLump(font_t *f, const char *facename)
if (con_ocranaleds.ival) if (con_ocranaleds.ival)
{ {
if (con_ocranaleds.ival != 2 || QCRC_Block(lumpdata, 128*128) == 798) if (con_ocranaleds.ival != 2 || CalcHashInt(&hash_crc16, lumpdata, 128*128) == 798)
AddOcranaLEDsIndexed (lumpdata, 128, 128); AddOcranaLEDsIndexed (lumpdata, 128, 128);
} }

View File

@ -2,6 +2,10 @@
See gl_terrain.h for terminology, networking notes, etc. See gl_terrain.h for terminology, networking notes, etc.
*/ */
//FIXME: render in lightmap batches. generate vbos accordingly.
//FIXME: assign to lightmaps by matching textures. should be able to get up to 65536/(17*17)=226 per section before index limits hit, 16*16=256 allows for 1024*1024 lightmaps.
//FIXME: sort texture blend names to reduce combinations
#include "quakedef.h" #include "quakedef.h"
#ifdef TERRAIN #ifdef TERRAIN
@ -2687,6 +2691,20 @@ static void Terr_RebuildMesh(model_t *model, hmsection_t *s, int x, int y)
} }
#ifdef GLQUAKE #ifdef GLQUAKE
#if 0
if (qrenderer == QR_OPENGL && qglGenBuffersARB)
{
vbobctx_t ctx;
size_t vertsize = sizeof(*mesh->xyz_array)+sizeof(*mesh->st_array)+sizeof(*mesh->lmst_array)+(mesh->colors4f_array?sizeof(*mesh->colors4f_array):0);
BE_VBO_Begin(&ctx, vertsize * mesh->numvertexes);
BE_VBO_Data(&ctx, mesh->xyz_array, sizeof(*mesh->xyz_array) * mesh->numvertexes, &s->vbo.coord);
BE_VBO_Data(&ctx, mesh->st_array, sizeof(*mesh->st_array) * mesh->numvertexes, &s->vbo.texcoord);
BE_VBO_Data(&ctx, mesh->lmst_array, sizeof(*mesh->lmst_array) * mesh->numvertexes, &s->vbo.lmcoord[0]);
if (mesh->colors4f_array)
BE_VBO_Data(&ctx, mesh->colors4f_array, sizeof(*mesh->colors4f_array) * mesh->numvertexes, &s->vbo.colours[0]);
BE_VBO_Finish(&ctx, mesh->indexes, sizeof(*mesh->indexes)*mesh->numindexes, &s->vbo.indicies, NULL, NULL);
}
#else
if (qrenderer == QR_OPENGL && qglGenBuffersARB) if (qrenderer == QR_OPENGL && qglGenBuffersARB)
{ {
if (!s->vbo.coord.gl.vbo) if (!s->vbo.coord.gl.vbo)
@ -2728,6 +2746,7 @@ static void Terr_RebuildMesh(model_t *model, hmsection_t *s, int x, int y)
mesh->indexes = NULL; mesh->indexes = NULL;
#endif #endif
} }
#endif
#endif #endif
#ifdef VKQUAKE #ifdef VKQUAKE
if (qrenderer == QR_VULKAN) if (qrenderer == QR_VULKAN)

View File

@ -426,7 +426,7 @@ qboolean QDECL Mod_LoadHLModel (model_t *mod, void *buffer, size_t fsize)
for(i = 0; i < texheader->numtextures; i++) for(i = 0; i < texheader->numtextures; i++)
while (sz < tex[i].w || sz < tex[i].h) while (sz < tex[i].w || sz < tex[i].h)
sz <<= 1; sz <<= 1;
for (; sz < sh_config.texture2d_maxsize; sz<<=1) for (; sz < sh_config.texture2d_maxsize && sz <= LMBLOCK_SIZE_MAX; sz<<=1)
{ {
unsigned short x,y; unsigned short x,y;
int atlasid; int atlasid;

View File

@ -24,7 +24,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "quakedef.h" #include "quakedef.h"
#include "com_bih.h"
#if 1//ndef SERVERONLY //FIXME #if 1//ndef SERVERONLY //FIXME
#include "glquake.h" #include "glquake.h"
#include "com_mesh.h" #include "com_mesh.h"
@ -340,7 +340,14 @@ const char *Mod_GetEntitiesString(model_t *mod)
if (mod->entities_raw) //still cached/correct if (mod->entities_raw) //still cached/correct
return mod->entities_raw; return mod->entities_raw;
if (!mod->numentityinfo) if (!mod->numentityinfo)
return NULL; {
if (mod->loadstate != MLS_LOADED)
return NULL;
mod->entities_raw = FS_LoadMallocFile(va("%s.ent", mod->name), NULL);
if (!mod->entities_raw)
mod->entities_raw = FS_LoadMallocFile(va("%s.ent", mod->name), NULL);
return mod->entities_raw;
}
//reform the entities back into a full string now that we apparently need it //reform the entities back into a full string now that we apparently need it
//find needed buffer size //find needed buffer size
@ -423,8 +430,7 @@ void Mod_ParseEntities(model_t *mod)
Z_Free(mod->entityinfo); Z_Free(mod->entityinfo);
mod->entityinfo = NULL; mod->entityinfo = NULL;
entdata = Mod_GetEntitiesString(mod);
entdata = mod->entities_raw;
while(1) while(1)
{ {
if (!(entdata=COM_ParseOut(entdata, key, sizeof(key)))) if (!(entdata=COM_ParseOut(entdata, key, sizeof(key))))
@ -1227,7 +1233,13 @@ static void Mod_LoadModelWorker (void *ctx, void *data, size_t a, size_t b)
// //
// fill it in // fill it in
// //
Mod_DoCRC(mod, (char*)buf, filesize); if (!Mod_DoCRC(mod, (char*)buf, filesize))
{
BZ_Free(buf);
continue;
}
memset(&mod->funcs, 0, sizeof(mod->funcs)); //just in case...
if (filesize < 4) if (filesize < 4)
magic = 0; magic = 0;
@ -2234,7 +2246,7 @@ void Mod_LoadEntities (model_t *loadmodel, qbyte *mod_base, lump_t *l)
ents[l->filelen] = 0; ents[l->filelen] = 0;
} }
else else
loadmodel->entitiescrc = QCRC_Block(ents, strlen(ents)); loadmodel->entitiescrc = CalcHashInt(&hash_crc16, ents, strlen(ents));
Mod_SetEntitiesString(loadmodel, ents, false); Mod_SetEntitiesString(loadmodel, ents, false);
@ -2817,8 +2829,8 @@ void Mod_LightmapAllocInit(lmalloc_t *lmallocator, qboolean hasdeluxe, unsigned
lmallocator->lmnum = firstlm; lmallocator->lmnum = firstlm;
lmallocator->firstlm = firstlm; lmallocator->firstlm = firstlm;
lmallocator->width = width; lmallocator->width = min(LMBLOCK_SIZE_MAX, width);
lmallocator->height = height; lmallocator->height = min(LMBLOCK_SIZE_MAX, height);
} }
void Mod_LightmapAllocDone(lmalloc_t *lmallocator, model_t *mod) void Mod_LightmapAllocDone(lmalloc_t *lmallocator, model_t *mod)
{ {
@ -3080,8 +3092,6 @@ static void Mod_Batches_Build(model_t *mod, builddata_t *bd)
mesh_t *meshlist; mesh_t *meshlist;
int merge = 1; int merge = 1;
currentmodel = mod;
if (!mod->textures) if (!mod->textures)
return; return;
@ -4922,46 +4932,6 @@ static qboolean Mod_LoadPlanes (model_t *loadmodel, qbyte *mod_base, lump_t *l)
return true; return true;
} }
#ifndef SERVERONLY
//combination of R_AddDynamicLights and R_MarkLights
static void Q1BSP_StainNode (mnode_t *node, float *parms)
{
mplane_t *splitplane;
float dist;
msurface_t *surf;
int i;
if (node->contents < 0)
return;
splitplane = node->plane;
dist = DotProduct ((parms+1), splitplane->normal) - splitplane->dist;
if (dist > (*parms))
{
Q1BSP_StainNode (node->children[0], parms);
return;
}
if (dist < (-*parms))
{
Q1BSP_StainNode (node->children[1], parms);
return;
}
// mark the polygons
surf = cl.worldmodel->surfaces + node->firstsurface;
for (i=0 ; i<node->numsurfaces ; i++, surf++)
{
if (surf->flags&~(SURF_DRAWALPHA|SURF_DONTWARP|SURF_PLANEBACK))
continue;
Surf_StainSurf(surf, parms);
}
Q1BSP_StainNode (node->children[0], parms);
Q1BSP_StainNode (node->children[1], parms);
}
#endif
static void Mod_FixupNodeMinsMaxs (mnode_t *node, mnode_t *parent) static void Mod_FixupNodeMinsMaxs (mnode_t *node, mnode_t *parent)
{ {
if (!node) if (!node)
@ -5467,13 +5437,6 @@ static qboolean QDECL Mod_LoadBrushModel (model_t *mod, void *buffer, size_t fsi
TRACE(("LoadBrushModel %i\n", __LINE__)); TRACE(("LoadBrushModel %i\n", __LINE__));
Q1BSP_LoadBrushes(mod, bspx, mod_base); Q1BSP_LoadBrushes(mod, bspx, mod_base);
TRACE(("LoadBrushModel %i\n", __LINE__)); TRACE(("LoadBrushModel %i\n", __LINE__));
Q1BSP_SetModelFuncs(mod);
TRACE(("LoadBrushModel %i\n", __LINE__));
#ifndef SERVERONLY
mod->funcs.LightPointValues = GLQ1BSP_LightPointValues;
mod->funcs.MarkLights = Q1BSP_MarkLights;
mod->funcs.StainNode = Q1BSP_StainNode;
#endif
mod->numframes = 2; // regular and alternate animation mod->numframes = 2; // regular and alternate animation
@ -5544,6 +5507,27 @@ TRACE(("LoadBrushModel %i\n", __LINE__));
} }
TRACE(("LoadBrushModel %i\n", __LINE__)); TRACE(("LoadBrushModel %i\n", __LINE__));
submod->cnodes = NULL;
Q1BSP_SetModelFuncs(submod);
if (bm->brushes)
{
struct bihleaf_s *leafs, *l;
size_t i;
leafs = l = BZ_Malloc(sizeof(*leafs)*bm->numbrushes);
for (i = 0; i < bm->numbrushes; i++)
{
struct q2cbrush_s *b = &bm->brushes[i];
l->type = BIH_BRUSH;
l->data.brush = b;
l->data.contents = b->contents;
VectorCopy(b->absmins, l->mins);
VectorCopy(b->absmaxs, l->maxs);
l++;
}
BIH_Build(submod, leafs, l-leafs);
BZ_Free(leafs);
}
if (i) if (i)
COM_AddWork(WG_MAIN, Mod_ModelLoaded, submod, NULL, MLS_LOADED, 0); COM_AddWork(WG_MAIN, Mod_ModelLoaded, submod, NULL, MLS_LOADED, 0);
if (i < submod->numsubmodels-1) if (i < submod->numsubmodels-1)

View File

@ -265,7 +265,7 @@ typedef struct {
void (*PurgeModel) (struct model_s *mod); void (*PurgeModel) (struct model_s *mod);
unsigned int (*PointContents) (struct model_s *model, const vec3_t axis[3], const vec3_t p); unsigned int (*PointContents) (struct model_s *model, const vec3_t axis[3], const vec3_t p);
unsigned int (*BoxContents) (struct model_s *model, int hulloverride, const framestate_t *framestate, const vec3_t axis[3], const vec3_t p, const vec3_t mins, const vec3_t maxs); // unsigned int (*BoxContents) (struct model_s *model, int hulloverride, const framestate_t *framestate, const vec3_t axis[3], const vec3_t p, const vec3_t mins, const vec3_t maxs);
//deals with whatever is native for the bsp (gamecode is expected to distinguish this). //deals with whatever is native for the bsp (gamecode is expected to distinguish this).
qboolean (*NativeTrace) (struct model_s *model, int hulloverride, const framestate_t *framestate, const vec3_t axis[3], const vec3_t p1, const vec3_t p2, const vec3_t mins, const vec3_t maxs, qboolean capsule, unsigned int against, struct trace_s *trace); qboolean (*NativeTrace) (struct model_s *model, int hulloverride, const framestate_t *framestate, const vec3_t axis[3], const vec3_t p1, const vec3_t p2, const vec3_t mins, const vec3_t maxs, qboolean capsule, unsigned int against, struct trace_s *trace);
@ -482,7 +482,7 @@ typedef struct msurface_s
qbyte *samples; // [numstyles*surfsize] qbyte *samples; // [numstyles*surfsize]
} msurface_t; } msurface_t;
typedef struct mbrush_s /*typedef struct mbrush_s
{ {
struct mbrush_s *next; struct mbrush_s *next;
unsigned int contents; unsigned int contents;
@ -492,7 +492,7 @@ typedef struct mbrush_s
vec3_t normal; vec3_t normal;
float dist; float dist;
} planes[1]; } planes[1];
} mbrush_t; } mbrush_t;*/
typedef struct mnode_s typedef struct mnode_s
{ {
@ -504,7 +504,7 @@ typedef struct mnode_s
float minmaxs[6]; // for bounding box culling float minmaxs[6]; // for bounding box culling
struct mnode_s *parent; struct mnode_s *parent;
struct mbrush_s *brushes; // struct mbrush_s *brushes;
// node specific // node specific
mplane_t *plane; mplane_t *plane;
@ -529,7 +529,6 @@ typedef struct mleaf_s
float minmaxs[6]; // for bounding box culling float minmaxs[6]; // for bounding box culling
struct mnode_s *parent; struct mnode_s *parent;
struct mbrush_s *brushes;
// leaf specific // leaf specific
qbyte *compressed_vis; qbyte *compressed_vis;
@ -555,12 +554,15 @@ typedef struct mleaf_s
typedef struct typedef struct
{ {
float mins[3], maxs[3]; float mins[3], maxs[3];
float origin[3]; float origin[3];
int headnode[MAX_MAP_HULLSM]; unsigned int headnode[MAX_MAP_HULLSM];
int visleafs; // not including the solid leaf 0 unsigned int visleafs; // not including the solid leaf 0
int firstface, numfaces; unsigned int firstface, numfaces;
qboolean hullavailable[MAX_MAP_HULLSM]; qboolean hullavailable[MAX_MAP_HULLSM];
struct q2cbrush_s *brushes;
unsigned int numbrushes;
} mmodel_t; } mmodel_t;
@ -932,13 +934,13 @@ typedef struct model_s
{ {
char name[MAX_QPATH]; //actual name on disk char name[MAX_QPATH]; //actual name on disk
char publicname[MAX_QPATH]; //name that the gamecode etc sees char publicname[MAX_QPATH]; //name that the gamecode etc sees
int datasequence; int datasequence; //if it gets old enough, we can purge it.
int loadstate;//MLS_ int loadstate; //MLS_
qboolean tainted; // differs from the server's version. this model will be invisible as a result, to avoid spiked models. qboolean tainted; // differs from the server's version. this model will be invisible as a result, to avoid spiked models.
qboolean pushdepth; // bsp submodels have this flag set so you don't get z fighting on co-planar surfaces. qboolean pushdepth; // bsp submodels have this flag set so you don't get z fighting on co-planar surfaces.
time_t mtime; // modification time. so we can flush models if they're changed on disk. or at least worldmodels. time_t mtime; // modification time. so we can flush models if they're changed on disk. or at least worldmodels.
struct model_s *submodelof; struct model_s *submodelof; // shares memory allocations with this model.
modtype_t type; modtype_t type;
fromgame_t fromgame; fromgame_t fromgame;
@ -951,9 +953,6 @@ typedef struct model_s
int particleeffect; int particleeffect;
int particletrail; int particletrail;
int traildefaultindex; int traildefaultindex;
struct skytris_s *skytris; //for surface emittance
float skytime; //for surface emittance
struct skytriblock_s *skytrimem;
// //
// volume occupied by the model graphics // volume occupied by the model graphics
@ -969,6 +968,7 @@ typedef struct model_s
qboolean clipbox; qboolean clipbox;
vec3_t clipmins, clipmaxs; vec3_t clipmins, clipmaxs;
void *cnodes; //BIH tree
// //
// brush model // brush model
// //
@ -994,7 +994,6 @@ typedef struct model_s
int numnodes; int numnodes;
mnode_t *nodes; mnode_t *nodes;
void *cnodes;
mnode_t *rootnode; mnode_t *rootnode;
int numtexinfo; int numtexinfo;
@ -1028,13 +1027,20 @@ typedef struct model_s
int numfogs; int numfogs;
menvmap_t *envmaps; menvmap_t *envmaps;
unsigned numenvmaps; unsigned numenvmaps;
struct skytris_s *skytris; //for surface emittance
float skytime; //for surface emittance
struct skytriblock_s *skytrimem;
struct {unsigned int id; char *keyvals;} *entityinfo; struct {unsigned int id; char *keyvals;} *entityinfo;
size_t numentityinfo; size_t numentityinfo;
const char *entities_raw; const char *entities_raw;
int entitiescrc; int entitiescrc;
struct doll_s *dollinfo; struct doll_s *dollinfo; //ragdoll info
shader_t *simpleskin[4]; int camerabone; //the 1-based bone index that the camera should be attached to (for gltf rather than anything else)
shader_t *simpleskin[4]; //simpleitems cache
struct { struct {
texture_t *tex; texture_t *tex;
@ -1079,7 +1085,6 @@ typedef struct model_s
// //
void *meshinfo; //data allocated within the memgroup allocations, will be nulled out when the model is flushed void *meshinfo; //data allocated within the memgroup allocations, will be nulled out when the model is flushed
zonegroup_t memgroup; zonegroup_t memgroup;
int camerabone; //the 1-based bone index that the camera should be attached to (for gltf rather than anything else)
} model_t; } model_t;
#define MDLF_EMITREPLACE 0x0001 // particle effect engulphs model (don't draw) #define MDLF_EMITREPLACE 0x0001 // particle effect engulphs model (don't draw)
@ -1093,7 +1098,7 @@ typedef struct model_s
#define MDLF_BOLT 0x0100 // doesn't produce shadows #define MDLF_BOLT 0x0100 // doesn't produce shadows
#define MDLF_NOTREPLACEMENTS 0x0200 // can be considered a cheat, disable texture replacements #define MDLF_NOTREPLACEMENTS 0x0200 // can be considered a cheat, disable texture replacements
#define MDLF_EZQUAKEFBCHEAT 0x0400 // this is a blatent cheat, one that can disadvantage us fairly significantly if we don't support it. #define MDLF_EZQUAKEFBCHEAT 0x0400 // this is a blatent cheat, one that can disadvantage us fairly significantly if we don't support it.
#define MDLF_HASBRUSHES 0x0800 // q1bsp has brush info for more precise traceboxes //#define MDLF_HASBRUSHES 0x0800 // q1bsp has brush info for more precise traceboxes
#define MDLF_RECALCULATERAIN 0x1000 // particles changed, recalculate any sky polys #define MDLF_RECALCULATERAIN 0x1000 // particles changed, recalculate any sky polys
//============================================================================ //============================================================================

View File

@ -438,7 +438,9 @@ void R_RenderDlights (void)
if (coronastyle) if (coronastyle)
{ {
int method; int method;
if (!*r_coronas_occlusion.string) if (r_refdef.recurse)
method = 1; //don't confuse queries... FIXME: splitscreen/PIP will still have issues.
else if (!*r_coronas_occlusion.string)
method = 4; //default to using hardware queries where possible. method = 4; //default to using hardware queries where possible.
else else
method = r_coronas_occlusion.ival; method = r_coronas_occlusion.ival;

View File

@ -52,7 +52,7 @@ extern cvar_t r_bloom;
extern cvar_t r_wireframe, r_wireframe_smooth; extern cvar_t r_wireframe, r_wireframe_smooth;
extern cvar_t r_outline; extern cvar_t r_outline;
cvar_t gl_affinemodels = CVAR("gl_affinemodels","0"); cvar_t gl_affinemodels = CVARFD("gl_affinemodels","0", CVAR_ARCHIVE, "Use affine texture sampling for models. This replicates software rendering's distortions.");
cvar_t gl_finish = CVAR("gl_finish","0"); cvar_t gl_finish = CVAR("gl_finish","0");
cvar_t gl_dither = CVAR("gl_dither", "1"); cvar_t gl_dither = CVAR("gl_dither", "1");
extern cvar_t r_stereo_separation; extern cvar_t r_stereo_separation;
@ -435,7 +435,7 @@ void R_RotateForEntity (float *m, float *modelview, const entity_t *e, const mod
R_SetupGL R_SetupGL
============= =============
*/ */
static void R_SetupGL (vec3_t axisorigin[4], vec4_t fovoverrides, float projmatrix[16]/*for webvr*/, texid_t fbo) static void R_SetupGL (matrix3x4 eyematrix, vec4_t fovoverrides, float projmatrix[16]/*for webvr*/, texid_t fbo)
{ {
int x, x2, y2, y, w, h; int x, x2, y2, y, w, h;
vec3_t newa; vec3_t newa;
@ -450,29 +450,14 @@ static void R_SetupGL (vec3_t axisorigin[4], vec4_t fovoverrides, float projmatr
newa[0] = r_refdef.viewangles[0]; newa[0] = r_refdef.viewangles[0];
newa[1] = r_refdef.viewangles[1]; newa[1] = r_refdef.viewangles[1];
newa[2] = r_refdef.viewangles[2] + gl_screenangle.value; newa[2] = r_refdef.viewangles[2] + gl_screenangle.value;
if (axisorigin) if (eyematrix)
{ {
vec3_t paxis[3]; matrix3x4 headmatrix;
AngleVectors (newa, paxis[0], paxis[1], paxis[2]); matrix3x4 viewmatrix;
Matrix3x4_RM_FromAngles(newa, r_refdef.vieworg, headmatrix[0]);
//R_ConcatRotations(r_refdef.headaxis, paxis, vpn); Matrix3x4_Multiply(headmatrix[0], eyematrix[0], viewmatrix[0]);
Matrix3x4_RM_ToVectors(viewmatrix[0], vpn, vright, vup, r_origin);
VectorMA(vec3_origin, axisorigin[0][0], paxis[0], vpn); VectorNegate(vright, vright);
VectorMA(vpn, axisorigin[0][1], paxis[1], vpn);
VectorMA(vpn, axisorigin[0][2], paxis[2], vpn);
VectorMA(vec3_origin, axisorigin[1][0], paxis[0], vright);
VectorMA(vright, axisorigin[1][1], paxis[1], vright);
VectorMA(vright, axisorigin[1][2], paxis[2], vright);
VectorMA(vec3_origin, axisorigin[2][0], paxis[0], vup);
VectorMA(vup, axisorigin[2][1], paxis[1], vup);
VectorMA(vup, axisorigin[2][2], paxis[2], vup);
VectorMA(r_refdef.vieworg, axisorigin[3][0], vpn, r_origin);
VectorMA(r_origin, axisorigin[3][1], vright, r_origin);
VectorMA(r_origin, axisorigin[3][2], vup, r_origin);
} }
else else
{ {
@ -732,7 +717,7 @@ static void R_RenderScene_Internal(void)
depthcleared = false; //whatever is in the depth buffer is no longer useful. depthcleared = false; //whatever is in the depth buffer is no longer useful.
} }
static void R_RenderEyeScene (texid_t rendertarget, vec4_t fovoverride, vec3_t axisorigin[4]) static void R_RenderEyeScene (texid_t rendertarget, vec4_t fovoverride, matrix3x4 eyematrix)
{ {
extern qboolean depthcleared; extern qboolean depthcleared;
refdef_t refdef = r_refdef; refdef_t refdef = r_refdef;
@ -750,9 +735,47 @@ static void R_RenderEyeScene (texid_t rendertarget, vec4_t fovoverride, vec3_t a
vid.fbpheight = rendertarget->height; vid.fbpheight = rendertarget->height;
} }
R_SetupGL (axisorigin, fovoverride, NULL, rendertarget); R_SetupGL (eyematrix, fovoverride, NULL, rendertarget);
R_RenderScene_Internal(); R_RenderScene_Internal();
//if (eyematrix)
{
vec3_t newa, newo;
matrix3x4 headmatrix; //position of the head in local space
//eyematrix //position of the eye in head space...
matrix3x4 headeyematrix;
matrix3x4 correctionmatrix; //to nudge the 2d stuff into view
matrix3x4 viewmatrix; //final transform
extern usercmd_t cl_pendingcmd[MAX_SPLITS];
newa[0] = SHORT2ANGLE(cl_pendingcmd[0].vr[VRDEV_HEAD].angles[0]);
newa[1] = SHORT2ANGLE(cl_pendingcmd[0].vr[VRDEV_HEAD].angles[1]);
newa[2] = SHORT2ANGLE(cl_pendingcmd[0].vr[VRDEV_HEAD].angles[2]);
Matrix3x4_RM_FromAngles(newa, cl_pendingcmd[0].vr[VRDEV_HEAD].origin, headmatrix[0]);
newa[0] = Cvar_Get("2dpitch", "-90", 0, "")->value;
newa[1] = Cvar_Get("2dyaw", "0", 0, "")->value;
newa[2] = Cvar_Get("2droll", "90", 0, "")->value;
//why /4, not /2? wtf?
newo[0] = vid.width/4 + Cvar_Get("2dfwd", "0", 0, "")->value;
newo[1] = vid.height/4 + Cvar_Get("2dleft", "0", 0, "")->value;
newo[2] = Cvar_Get("2dup", "-256", 0, "")->value;
Matrix3x4_RM_FromAngles(newa, newo, correctionmatrix[0]);
Matrix3x4_Multiply(headmatrix[0], eyematrix[0], headeyematrix[0]);
Matrix3x4_Multiply(headeyematrix[0], correctionmatrix[0], viewmatrix[0]);
Matrix3x4_RM_ToVectors(viewmatrix[0], vpn, vright, vup, r_origin);
VectorNegate(vright, vright);
Matrix4x4_CM_ModelViewMatrixFromAxis(r_refdef.m_view, vpn, vright, vup, r_origin);
GL_SetShaderState2D(true);
Menu_Draw();
SCR_DrawConsole(false);
if (R2D_Flush)
R2D_Flush();
GL_SetShaderState2D(false);
}
if (rendertarget) if (rendertarget)
{ {
GLBE_FBO_Pop(r); GLBE_FBO_Pop(r);
@ -772,7 +795,8 @@ static void R_RenderScene (void)
int i; int i;
int cull = r_refdef.flipcull; int cull = r_refdef.flipcull;
unsigned int colourmask = r_refdef.colourmask; unsigned int colourmask = r_refdef.colourmask;
vec3_t axisorg[4], ang; vec3_t ang, org;
matrix3x4 eyematrix;
extern qboolean depthcleared; extern qboolean depthcleared;
r_refdef.colourmask = 0u; r_refdef.colourmask = 0u;
@ -893,11 +917,9 @@ static void R_RenderScene (void)
ang[0] = 0; ang[0] = 0;
ang[1] = r_stereo_convergence.value * (i?0.5:-0.5); ang[1] = r_stereo_convergence.value * (i?0.5:-0.5);
ang[2] = 0; ang[2] = 0;
AngleVectorsFLU(ang, axisorg[0], axisorg[1], axisorg[2]); VectorSet(org, 0, stereooffset[i], 0);
axisorg[3][0] = 0; Matrix3x4_RM_FromAngles(ang, org, eyematrix[0]);
axisorg[3][1] = stereooffset[i]; R_SetupGL (eyematrix, NULL, NULL, NULL);
axisorg[3][2] = 0;
R_SetupGL (axisorg, NULL, NULL, NULL);
R_RenderScene_Internal (); R_RenderScene_Internal ();
} }

View File

@ -780,6 +780,11 @@ static int Shader_SetImageFlags(parsestate_t *parsestate, shaderpass_t *pass, ch
flags &= ~IF_NEAREST; flags &= ~IF_NEAREST;
flags |= IF_LINEAR; flags |= IF_LINEAR;
} }
else if (!Q_strnicmp(*name, "$palettize:", 11))
{
*name+=11;
flags |= IF_PALETTIZE;
}
else else
break; break;
} }
@ -6519,7 +6524,7 @@ char *Shader_DefaultBSPWater(parsestate_t *ps, const char *shortname, char *buff
else else
wstyle = 1; wstyle = 1;
if (wstyle > 1 && !cls.allow_watervis) if ((wstyle < 0 || wstyle > 1) && !cls.allow_watervis)
wstyle = 1; wstyle = 1;
if (wstyle > 1 && !sh_config.progs_supported) if (wstyle > 1 && !sh_config.progs_supported)
@ -6559,8 +6564,8 @@ char *Shader_DefaultBSPWater(parsestate_t *ps, const char *shortname, char *buff
case -2: //regular with r_wateralpha forced off. case -2: //regular with r_wateralpha forced off.
return ( return (
"{\n" "{\n"
"fte_program defaultwarp\n"
"{\n" "{\n"
"program defaultwarp\n"
"map $diffuse\n" "map $diffuse\n"
"tcmod turb 0.02 0.1 0.5 0.1\n" "tcmod turb 0.02 0.1 0.5 0.1\n"
"}\n" "}\n"
@ -6591,8 +6596,8 @@ char *Shader_DefaultBSPWater(parsestate_t *ps, const char *shortname, char *buff
"if %g < 1\n" "if %g < 1\n"
"sort underwater\n" "sort underwater\n"
"endif\n" "endif\n"
"fte_program defaultwarp%s\n"
"{\n" "{\n"
"program defaultwarp%s\n"
"map $diffuse\n" "map $diffuse\n"
"tcmod turb 0.02 0.1 0.5 0.1\n" "tcmod turb 0.02 0.1 0.5 0.1\n"
"if %g < 1\n" "if %g < 1\n"
@ -7008,6 +7013,9 @@ void Shader_DefaultSkin(parsestate_t *ps, const char *shortname, const void *arg
"{\n" "{\n"
"map $diffuse\n" "map $diffuse\n"
"rgbgen lightingDiffuse\n" "rgbgen lightingDiffuse\n"
"if #BLEND\n"
"blendfunc blend\n" //straight blend
"endif\n"
"}\n" "}\n"
"{\n" "{\n"
"map $loweroverlay\n" "map $loweroverlay\n"

View File

@ -57,7 +57,7 @@ cvar_t r_shadow_scissor = CVARD("r_shadow_scissor", "1", "constrains stencil sha
cvar_t r_shadow_realtime_world = CVARFD ("r_shadow_realtime_world", "0", CVAR_ARCHIVE, "Enables the use of static/world realtime lights."); cvar_t r_shadow_realtime_world = CVARFD ("r_shadow_realtime_world", "0", CVAR_ARCHIVE, "Enables the use of static/world realtime lights.");
cvar_t r_shadow_realtime_world_shadows = CVARF ("r_shadow_realtime_world_shadows", "1", CVAR_ARCHIVE); cvar_t r_shadow_realtime_world_shadows = CVARF ("r_shadow_realtime_world_shadows", "1", CVAR_ARCHIVE);
cvar_t r_shadow_realtime_world_lightmaps = CVARFD ("r_shadow_realtime_world_lightmaps", "0", 0, "Specifies how much of the map's normal lightmap to retain when using world realtime lights. 0 completely replaces lighting."); cvar_t r_shadow_realtime_world_lightmaps = CVARFD ("r_shadow_realtime_world_lightmaps", "0", 0, "Specifies how much of the map's normal lightmap to retain when using world realtime lights. 0 completely replaces lighting.");
cvar_t r_shadow_realtime_world_importlightentitiesfrommap = CVARFD ("r_shadow_realtime_world_importlightentitiesfrommap", "0", 0, "Controls default loading of map-based realtime lights.\n0: Load explicit .rtlight files only.\n1: Load explicit lights then try fallback to parsing the entities lump.\n2: Load only the entities lump."); cvar_t r_shadow_realtime_world_importlightentitiesfrommap = CVARFD ("r_shadow_realtime_world_importlightentitiesfrommap", "0", CVAR_ARCHIVE, "Controls default loading of map-based realtime lights.\n0: Load explicit .rtlight files only.\n1: Load explicit lights then try fallback to parsing the entities lump.\n2: Load only the entities lump.");
cvar_t r_shadow_realtime_dlight = CVARFD ("r_shadow_realtime_dlight", "1", CVAR_ARCHIVE, "Enables the use of dynamic realtime lights, allowing explosions to use bumpmaps etc properly."); cvar_t r_shadow_realtime_dlight = CVARFD ("r_shadow_realtime_dlight", "1", CVAR_ARCHIVE, "Enables the use of dynamic realtime lights, allowing explosions to use bumpmaps etc properly.");
cvar_t r_shadow_realtime_dlight_shadows = CVARFD ("r_shadow_realtime_dlight_shadows", "1", CVAR_ARCHIVE, "Allows dynamic realtime lights to cast shadows as they move."); cvar_t r_shadow_realtime_dlight_shadows = CVARFD ("r_shadow_realtime_dlight_shadows", "1", CVAR_ARCHIVE, "Allows dynamic realtime lights to cast shadows as they move.");
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");
@ -3730,6 +3730,13 @@ void Sh_PreGenerateLights(void)
qbyte *lvis; qbyte *lvis;
int i; int i;
if (r_shadow_realtime_world_importlightentitiesfrommap.modified)
{
rtlights_first = RTL_FIRST;
rtlights_max = RTL_FIRST;
}
r_shadow_realtime_world_importlightentitiesfrommap.modified = false;
r_shadow_realtime_world_lightmaps.value = atof(r_shadow_realtime_world_lightmaps.string); r_shadow_realtime_world_lightmaps.value = atof(r_shadow_realtime_world_lightmaps.string);
if (!cl.worldmodel) if (!cl.worldmodel)
return; return;
@ -3981,6 +3988,7 @@ void Sh_DrawLights(qbyte *vis)
if (r_shadow_realtime_world.modified || if (r_shadow_realtime_world.modified ||
r_shadow_realtime_world_shadows.modified || r_shadow_realtime_world_shadows.modified ||
r_shadow_realtime_world_importlightentitiesfrommap.modified ||
r_shadow_realtime_dlight.modified || r_shadow_realtime_dlight.modified ||
r_shadow_realtime_dlight_shadows.modified || r_shadow_realtime_dlight_shadows.modified ||
r_shadow_shadowmapping.modified || r_shadows.modified) r_shadow_shadowmapping.modified || r_shadows.modified)

View File

@ -42,7 +42,7 @@ int Surf_NewLightmaps(int count, int width, int height, uploadfmt_t fmt, qboolea
#define CHUNKBIAS (MAXCLUSTERS*MAXSECTIONS/2) #define CHUNKBIAS (MAXCLUSTERS*MAXSECTIONS/2)
#define CHUNKLIMIT (MAXCLUSTERS*MAXSECTIONS) #define CHUNKLIMIT (MAXCLUSTERS*MAXSECTIONS)
#define LMCHUNKS 8//(LMBLOCK_WIDTH/SECTTEXSIZE) #define LMCHUNKS 8//(LMBLOCK_WIDTH/SECTTEXSIZE) //FIXME: make dynamic.
#define HMLMSTRIDE (LMCHUNKS*SECTTEXSIZE) #define HMLMSTRIDE (LMCHUNKS*SECTTEXSIZE)
#define SECTION_MAGIC (*(int*)"HMMS") #define SECTION_MAGIC (*(int*)"HMMS")

View File

@ -3309,7 +3309,7 @@ void GL_ForgetPointers(void)
qboolean GL_Init(rendererstate_t *info, void *(*getglfunction) (char *name)) qboolean GL_Init(rendererstate_t *info, void *(*getglfunction) (char *name))
{ {
#ifndef GL_STATIC #ifndef GL_STATIC
qglBindTexture = (void *)getglcore("glBindTexture"); //for compleateness. core in 1.1. needed by fte. qglBindTexture = (void *)getglcore("glBindTexture"); //for compleateness. core in 1.1. needed by fte.
qglBlendFunc = (void *)getglcore("glBlendFunc"); qglBlendFunc = (void *)getglcore("glBlendFunc");
qglClear = (void *)getglcore("glClear"); qglClear = (void *)getglcore("glClear");
qglClearColor = (void *)getglcore("glClearColor"); qglClearColor = (void *)getglcore("glClearColor");

View File

@ -450,18 +450,13 @@ qboolean EGL_InitWindow (rendererstate_t *info, int eglplat, void *nwindow, EGLN
return false; return false;
} }
if (!qeglMakeCurrent(egldpy, eglsurf, eglsurf, eglctx)) if (!qeglMakeCurrent(egldpy, eglsurf, eglsurf, eglctx))
{ {
Con_Printf(CON_ERROR "EGL: can't make current!\n"); Con_Printf(CON_ERROR "EGL: can't make current!\n");
return false; return false;
} }
if (eglplat == EGL_PLATFORM_WAYLAND_KHR)
{ //if we don't do this, only the first frame will get displayed, and we'll lock up
qeglSwapInterval = NULL;
Con_DPrintf(CON_WARNING"Wayland: Disabling vsync controls to work around wayland bug\n");
}
EGL_UpdateSwapInterval(); EGL_UpdateSwapInterval();

View File

@ -4388,6 +4388,7 @@ static qboolean X11VID_Init (rendererstate_t *info, unsigned char *palette, int
const char *extnames[] = {VK_KHR_XLIB_SURFACE_EXTENSION_NAME, NULL}; const char *extnames[] = {VK_KHR_XLIB_SURFACE_EXTENSION_NAME, NULL};
if (VK_Init(info, extnames, XVK_SetupSurface_XLib, NULL)) if (VK_Init(info, extnames, XVK_SetupSurface_XLib, NULL))
break; break;
VK_Shutdown();
} }
#endif #endif
#ifdef VK_USE_PLATFORM_XCB_KHR #ifdef VK_USE_PLATFORM_XCB_KHR
@ -4395,6 +4396,7 @@ static qboolean X11VID_Init (rendererstate_t *info, unsigned char *palette, int
const char *extnames[] = {VK_KHR_XCB_SURFACE_EXTENSION_NAME, NULL}; const char *extnames[] = {VK_KHR_XCB_SURFACE_EXTENSION_NAME, NULL};
if (x11xcb_initlib() && VK_Init(info, extnames, XVK_SetupSurface_XCB, NULL)) if (x11xcb_initlib() && VK_Init(info, extnames, XVK_SetupSurface_XCB, NULL))
break; break;
VK_Shutdown();
} }
#endif #endif
//Con_Printf(CON_ERROR "Failed to create a vulkan context.\n"); //Con_Printf(CON_ERROR "Failed to create a vulkan context.\n");
@ -4565,6 +4567,31 @@ static qboolean XVK_SetupSurface_XCB(void)
return false; return false;
} }
#endif #endif
static qboolean XVK_EnumerateDevices(void *usercontext, void(*callback)(void *context, const char *devicename, const char *outputname, const char *desc))
{
qboolean ret = false;
#ifdef VK_NO_PROTOTYPES
PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr;
void *lib = NULL;
dllfunction_t func[] =
{
{(void*)&vkGetInstanceProcAddr, "vkGetInstanceProcAddr"},
{NULL, NULL}
};
if (!lib)
lib = Sys_LoadLibrary("libvulkan.so.1", func);
if (!lib)
lib = Sys_LoadLibrary("libvulkan.so", func);
if (!lib)
return false;
#endif
ret = VK_EnumerateDevices(usercontext, callback, "Vulkan-X11-", vkGetInstanceProcAddr);
#ifdef VK_NO_PROTOTYPES
Sys_CloseLibrary(lib);
#endif
return ret;
}
rendererinfo_t vkrendererinfo = rendererinfo_t vkrendererinfo =
{ {
"Vulkan (X11)", "Vulkan (X11)",
@ -4622,7 +4649,11 @@ rendererinfo_t vkrendererinfo =
VKBE_RenderToTextureUpdate2d, VKBE_RenderToTextureUpdate2d,
"" "",
NULL,//int (*VID_GetPriority) (void); //so that eg x11 or wayland can be prioritised depending on environment settings. assumed to be 1.
NULL,//void (*VID_EnumerateVideoModes) (const char *driver, const char *output, void (*cb) (int w, int h));
XVK_EnumerateDevices,//qboolean (*VID_EnumerateDevices) (void *usercontext, void(*callback)(void *context, const char *devicename, const char *outputname, const char *desc));
}; };
#endif #endif

View File

@ -48,7 +48,7 @@ extern cvar_t vid_conautoscale;
#define WP_POINTER_CONSTRAINTS_NAME "zwp_pointer_constraints_v1" #define WP_POINTER_CONSTRAINTS_NAME "zwp_pointer_constraints_v1"
#define WP_RELATIVE_POINTER_MANAGER_NAME "zwp_relative_pointer_manager_v1" #define WP_RELATIVE_POINTER_MANAGER_NAME "zwp_relative_pointer_manager_v1"
#define ORG_KDE_KWIN_SERVER_DECORATION_MANAGER_NAME "org_kde_kwin_server_decoration_manager" //comment out to disable once XDG_SHELL_DESKTOP #define ORG_KDE_KWIN_SERVER_DECORATION_MANAGER_NAME "org_kde_kwin_server_decoration_manager" //comment out to disable once XDG_SHELL_DESKTOP
#define XDG_SHELL_UNSTABLE //#define XDG_SHELL_UNSTABLE
#ifdef XDG_SHELL_UNSTABLE #ifdef XDG_SHELL_UNSTABLE
#define XDG_SHELL_NAME "zxdg_shell_v6" #define XDG_SHELL_NAME "zxdg_shell_v6"
#else #else
@ -56,7 +56,10 @@ extern cvar_t vid_conautoscale;
#endif #endif
#define WL_SHELL_NAME "wl_shell" //fall back on this if xdg_shell is missing #define WL_SHELL_NAME "wl_shell" //fall back on this if xdg_shell is missing
#if 1 #ifndef STATIC_WAYLAND
#define DYNAMIC_WAYLAND
#endif
#ifdef DYNAMIC_WAYLAND
static struct wl_display *(*pwl_display_connect)(const char *name); static struct wl_display *(*pwl_display_connect)(const char *name);
static void (*pwl_display_disconnect)(struct wl_display *display); static void (*pwl_display_disconnect)(struct wl_display *display);
@ -85,6 +88,7 @@ static const struct wl_interface *pwl_output_interface;
static const struct wl_interface *pwl_shm_interface; static const struct wl_interface *pwl_shm_interface;
static const struct wl_interface *pwl_shm_pool_interface; static const struct wl_interface *pwl_shm_pool_interface;
static const struct wl_interface *pwl_buffer_interface; static const struct wl_interface *pwl_buffer_interface;
static const struct wl_interface *pwl_callback_interface;
static dllfunction_t waylandexports_wl[] = static dllfunction_t waylandexports_wl[] =
{ {
@ -113,6 +117,7 @@ static dllfunction_t waylandexports_wl[] =
{(void**)&pwl_shm_interface, "wl_shm_interface"}, {(void**)&pwl_shm_interface, "wl_shm_interface"},
{(void**)&pwl_shm_pool_interface, "wl_shm_pool_interface"}, {(void**)&pwl_shm_pool_interface, "wl_shm_pool_interface"},
{(void**)&pwl_buffer_interface, "wl_buffer_interface"}, {(void**)&pwl_buffer_interface, "wl_buffer_interface"},
{(void**)&pwl_callback_interface, "wl_callback_interface"},
{NULL, NULL} {NULL, NULL}
}; };
static dllhandle_t *lib_wayland_wl; static dllhandle_t *lib_wayland_wl;
@ -192,6 +197,19 @@ static inline struct wl_pointer *pwl_seat_get_pointer(struct wl_seat *wl_seat)
static inline struct wl_keyboard *pwl_seat_get_keyboard(struct wl_seat *wl_seat) {return (struct wl_keyboard *)(struct wl_proxy *) pwl_proxy_marshal_constructor((struct wl_proxy *) wl_seat, WL_SEAT_GET_KEYBOARD, pwl_keyboard_interface, NULL);} static inline struct wl_keyboard *pwl_seat_get_keyboard(struct wl_seat *wl_seat) {return (struct wl_keyboard *)(struct wl_proxy *) pwl_proxy_marshal_constructor((struct wl_proxy *) wl_seat, WL_SEAT_GET_KEYBOARD, pwl_keyboard_interface, NULL);}
static inline int pwl_seat_add_listener(struct wl_seat *wl_seat, const struct wl_seat_listener *listener, void *data) {return pwl_proxy_add_listener((struct wl_proxy *) wl_seat, (void (**)(void)) listener, data);} static inline int pwl_seat_add_listener(struct wl_seat *wl_seat, const struct wl_seat_listener *listener, void *data) {return pwl_proxy_add_listener((struct wl_proxy *) wl_seat, (void (**)(void)) listener, data);}
static inline struct wl_callback *pwl_surface_frame(struct wl_surface *wl_surface) {return (struct wl_callback*)(struct wl_proxy *) pwl_proxy_marshal_constructor((struct wl_proxy *) wl_surface, WL_SURFACE_FRAME, pwl_callback_interface, NULL);}
static inline int pwl_callback_add_listener(struct wl_callback *wl_callback, const struct wl_callback_listener *listener, void *data) {return pwl_proxy_add_listener((struct wl_proxy *) wl_callback, (void (**)(void)) listener, data);}
static inline void pwl_pointer_set_cursor(struct wl_pointer *wl_pointer, uint32_t serial, struct wl_surface *surface, int32_t hotspot_x, int32_t hotspot_y) { pwl_proxy_marshal((struct wl_proxy *) wl_pointer, WL_POINTER_SET_CURSOR, serial, surface, hotspot_x, hotspot_y); }
static inline struct wl_shm_pool *pwl_shm_create_pool(struct wl_shm *wl_shm, int32_t fd, int32_t size) { return (struct wl_shm_pool *)pwl_proxy_marshal_constructor((struct wl_proxy *) wl_shm, WL_SHM_CREATE_POOL, pwl_shm_pool_interface, NULL, fd, size); }
static inline struct wl_buffer *pwl_shm_pool_create_buffer(struct wl_shm_pool *wl_shm_pool, int32_t offset, int32_t width, int32_t height, int32_t stride, uint32_t format) { return (struct wl_buffer *)pwl_proxy_marshal_constructor((struct wl_proxy *) wl_shm_pool, WL_SHM_POOL_CREATE_BUFFER, pwl_buffer_interface, NULL, offset, width, height, stride, format); }
static inline void pwl_shm_pool_destroy(struct wl_shm_pool *wl_shm_pool) { pwl_proxy_marshal((struct wl_proxy *) wl_shm_pool, WL_SHM_POOL_DESTROY); pwl_proxy_destroy((struct wl_proxy *) wl_shm_pool); }
static inline void pwl_surface_commit(struct wl_surface *wl_surface) { pwl_proxy_marshal((struct wl_proxy *) wl_surface, WL_SURFACE_COMMIT); }
static inline void pwl_buffer_destroy(struct wl_buffer *wl_buffer) { pwl_proxy_marshal((struct wl_proxy *) wl_buffer, WL_BUFFER_DESTROY); pwl_proxy_destroy((struct wl_proxy *) wl_buffer); }
static inline void pwl_surface_attach(struct wl_surface *wl_surface, struct wl_buffer *buffer, int32_t x, int32_t y) { pwl_proxy_marshal((struct wl_proxy *) wl_surface, WL_SURFACE_ATTACH, buffer, x, y); }
static inline void pwl_surface_damage(struct wl_surface *wl_surface, int32_t x, int32_t y, int32_t width, int32_t height) { pwl_proxy_marshal((struct wl_proxy *) wl_surface, WL_SURFACE_DAMAGE, x, y, width, height); }
static inline void pwl_surface_destroy(struct wl_surface *wl_surface) { pwl_proxy_marshal((struct wl_proxy *) wl_surface, WL_SURFACE_DESTROY); pwl_proxy_destroy((struct wl_proxy *) wl_surface); }
#else #else
#define pwl_keyboard_interface &wl_keyboard_interface #define pwl_keyboard_interface &wl_keyboard_interface
#define pwl_pointer_interface &wl_pointer_interface #define pwl_pointer_interface &wl_pointer_interface
@ -204,6 +222,66 @@ static inline int pwl_seat_add_listener(struct wl_seat *wl_seat, const struct wl
#define pwl_shell_interface &wl_shell_interface #define pwl_shell_interface &wl_shell_interface
#endif #endif
#define pwl_seat_interface &wl_seat_interface #define pwl_seat_interface &wl_seat_interface
#define pwl_output_interface &wl_output_interface
#define pwl_shm_interface &wl_shm_interface
#define pwl_display_connect wl_display_connect
#define pwl_display_disconnect wl_display_disconnect
#define pwl_display_dispatch wl_display_dispatch
#define pwl_display_dispatch_pending wl_display_dispatch_pending
#define pwl_display_roundtrip wl_display_roundtrip
#define pwl_proxy_marshal wl_proxy_marshal
#define pwl_proxy_marshal_constructor wl_proxy_marshal_constructor
#define pwl_proxy_marshal_constructor_versioned wl_proxy_marshal_constructor_versioned
#define pwl_proxy_destroy wl_proxy_destroy
#define pwl_proxy_add_listener wl_proxy_add_listener
#define pwl_compositor_create_region wl_compositor_create_region
#define pwl_compositor_create_surface wl_compositor_create_surface
#define pwl_surface_set_opaque_region wl_surface_set_opaque_region
#define pwl_region_add wl_region_add
#define pwl_shell_get_shell_surface wl_shell_get_shell_surface
#define pwl_shell_surface_set_toplevel wl_shell_surface_set_toplevel
#define pwl_shell_surface_set_fullscreen wl_shell_surface_set_fullscreen
#define pwl_shell_surface_add_listener wl_shell_surface_add_listener
#define pwl_shell_surface_pong wl_shell_surface_pong
#define pwl_shell_surface_set_title wl_shell_surface_set_title
#define pwl_display_get_registry wl_display_get_registry
#define pwl_registry_bind wl_registry_bind
#define pwl_registry_add_listener wl_registry_add_listener
#define pwl_keyboard_destroy wl_keyboard_destroy
#define pwl_keyboard_add_listener wl_keyboard_add_listener
#define pwl_pointer_destroy wl_pointer_destroy
#define pwl_pointer_add_listener wl_pointer_add_listener
#define pwl_seat_get_pointer wl_seat_get_pointer
#define pwl_seat_get_keyboard wl_seat_get_keyboard
#define pwl_seat_add_listener wl_seat_add_listener
#define pwl_surface_frame wl_surface_frame
#define pwl_callback_add_listener wl_callback_add_listener
#define pwl_pointer_set_cursor wl_pointer_set_cursor
#define pwl_shm_create_pool wl_shm_create_pool
#define pwl_shm_pool_create_buffer wl_shm_pool_create_buffer
#define pwl_shm_pool_destroy wl_shm_pool_destroy
#define pwl_surface_commit wl_surface_commit
#define pwl_buffer_destroy wl_buffer_destroy
#define pwl_surface_attach wl_surface_attach
#define pwl_surface_damage wl_surface_damage
#define pwl_surface_destroy wl_surface_destroy
#define pwl_egl_window_create wl_egl_window_create
#define pwl_egl_window_destroy wl_egl_window_destroy
#define pwl_egl_window_resize wl_egl_window_resize
#define pxkb_context_new xkb_context_new
#define pxkb_keymap_new_from_string xkb_keymap_new_from_string
#define pxkb_state_new xkb_state_new
#define pxkb_state_key_get_one_sym xkb_state_key_get_one_sym
#define pxkb_keysym_to_utf32 xkb_keysym_to_utf32
#define pxkb_state_unref xkb_state_unref
#define pxkb_keymap_unref xkb_keymap_unref
#define pxkb_state_update_mask xkb_state_update_mask
#endif #endif
static const struct wl_interface *pzwp_relative_pointer_v1_interface; static const struct wl_interface *pzwp_relative_pointer_v1_interface;
static const struct wl_interface *pzwp_locked_pointer_v1_interface; static const struct wl_interface *pzwp_locked_pointer_v1_interface;
@ -236,7 +314,7 @@ static struct wdisplay_s
struct xkb_context *xkb_context; struct xkb_context *xkb_context;
struct xkb_state *xkb_state; struct xkb_state *xkb_state;
//to try to fix mouse stuff //to try to fix mouse stuff
qboolean absmouse; qboolean relative_mouse_active;
#ifdef WP_POINTER_CONSTRAINTS_NAME #ifdef WP_POINTER_CONSTRAINTS_NAME
struct zwp_pointer_constraints_v1 *pointer_constraints; struct zwp_pointer_constraints_v1 *pointer_constraints;
struct zwp_locked_pointer_v1 *locked_pointer; struct zwp_locked_pointer_v1 *locked_pointer;
@ -269,6 +347,8 @@ static struct wdisplay_s
struct wl_shell_surface *ssurface; struct wl_shell_surface *ssurface;
struct wl_shell *shell; //manager struct wl_shell *shell; //manager
#endif #endif
qboolean wait_for_configure; //WL is being slow and won't let us redraw yet.
qboolean waylandisblocking;
//belated sanity stuff //belated sanity stuff
#ifdef ORG_KDE_KWIN_SERVER_DECORATION_MANAGER_NAME #ifdef ORG_KDE_KWIN_SERVER_DECORATION_MANAGER_NAME
@ -480,6 +560,8 @@ static const struct xdg_wm_base_listener myxdg_wm_base_listener =
static void xdg_surface_handle_configure(void *data, struct xdg_surface *xdg_surface, uint32_t serial) static void xdg_surface_handle_configure(void *data, struct xdg_surface *xdg_surface, uint32_t serial)
{ {
xdg_surface_ack_configure(xdg_surface, serial); xdg_surface_ack_configure(xdg_surface, serial);
w.wait_for_configure = false; //all good now
} }
static const struct xdg_surface_listener myxdg_surface_listener = static const struct xdg_surface_listener myxdg_surface_listener =
{ {
@ -549,6 +631,8 @@ static void WL_shell_handle_configure(void *data, struct wl_shell_surface *shell
vid.pixelheight = height-w.csdsize; vid.pixelheight = height-w.csdsize;
Cvar_ForceCallback(&vid_conautoscale); Cvar_ForceCallback(&vid_conautoscale);
} }
w.wait_for_configure = false; //all good now
} }
static void WL_shell_handle_popup_done(void *data, struct wl_shell_surface *shell_surface) static void WL_shell_handle_popup_done(void *data, struct wl_shell_surface *shell_surface)
{ {
@ -602,16 +686,6 @@ static qbyte waylandinputsucksbighairydonkeyballsshift[] =
0,0,0,0,0,K_LWIN,K_RWIN,K_APP 0,0,0,0,0,K_LWIN,K_RWIN,K_APP
}; };
static inline void pwl_pointer_set_cursor(struct wl_pointer *wl_pointer, uint32_t serial, struct wl_surface *surface, int32_t hotspot_x, int32_t hotspot_y) { pwl_proxy_marshal((struct wl_proxy *) wl_pointer, WL_POINTER_SET_CURSOR, serial, surface, hotspot_x, hotspot_y); }
static inline struct wl_shm_pool *pwl_shm_create_pool(struct wl_shm *wl_shm, int32_t fd, int32_t size) { return (struct wl_shm_pool *)pwl_proxy_marshal_constructor((struct wl_proxy *) wl_shm, WL_SHM_CREATE_POOL, pwl_shm_pool_interface, NULL, fd, size); }
static inline struct wl_buffer *pwl_shm_pool_create_buffer(struct wl_shm_pool *wl_shm_pool, int32_t offset, int32_t width, int32_t height, int32_t stride, uint32_t format) { return (struct wl_buffer *)pwl_proxy_marshal_constructor((struct wl_proxy *) wl_shm_pool, WL_SHM_POOL_CREATE_BUFFER, pwl_buffer_interface, NULL, offset, width, height, stride, format); }
static inline void pwl_shm_pool_destroy(struct wl_shm_pool *wl_shm_pool) { pwl_proxy_marshal((struct wl_proxy *) wl_shm_pool, WL_SHM_POOL_DESTROY); pwl_proxy_destroy((struct wl_proxy *) wl_shm_pool); }
static inline void pwl_surface_commit(struct wl_surface *wl_surface) { pwl_proxy_marshal((struct wl_proxy *) wl_surface, WL_SURFACE_COMMIT); }
static inline void pwl_buffer_destroy(struct wl_buffer *wl_buffer) { pwl_proxy_marshal((struct wl_proxy *) wl_buffer, WL_BUFFER_DESTROY); pwl_proxy_destroy((struct wl_proxy *) wl_buffer); }
static inline void pwl_surface_attach(struct wl_surface *wl_surface, struct wl_buffer *buffer, int32_t x, int32_t y) { pwl_proxy_marshal((struct wl_proxy *) wl_surface, WL_SURFACE_ATTACH, buffer, x, y); }
static inline void pwl_surface_damage(struct wl_surface *wl_surface, int32_t x, int32_t y, int32_t width, int32_t height) { pwl_proxy_marshal((struct wl_proxy *) wl_surface, WL_SURFACE_DAMAGE, x, y, width, height); }
static inline void pwl_surface_destroy(struct wl_surface *wl_surface) { pwl_proxy_marshal((struct wl_proxy *) wl_surface, WL_SURFACE_DESTROY); pwl_proxy_destroy((struct wl_proxy *) wl_surface); }
static void WL_SetHWCursor(void) static void WL_SetHWCursor(void)
{ //called when the hardware cursor needs to be re-applied { //called when the hardware cursor needs to be re-applied
@ -623,7 +697,7 @@ static void WL_SetHWCursor(void)
return; //nope, we don't own the cursor, don't try changing it. return; //nope, we don't own the cursor, don't try changing it.
/*'If surface is NULL, the pointer image is hidden'*/ /*'If surface is NULL, the pointer image is hidden'*/
if (w.absmouse && !w.locked_pointer && w.cursor) if (!w.relative_mouse_active && !w.locked_pointer && w.cursor)
{ {
struct cursorinfo_s *c = w.cursor; struct cursorinfo_s *c = w.cursor;
//weston bugs out if we don't redo this junk //weston bugs out if we don't redo this junk
@ -792,7 +866,7 @@ static void WL_pointer_handle_motion(void *data, struct wl_pointer *pointer, uin
y -= s->csdsize; y -= s->csdsize;
//and let the game know. //and let the game know.
if (s->absmouse) if (!s->relative_mouse_active)
IN_MouseMove(0, true, x, y, 0, 0); IN_MouseMove(0, true, x, y, 0, 0);
} }
@ -807,7 +881,7 @@ static void WL_pointer_handle_button(void *data, struct wl_pointer *wl_pointer,
return; //blurgh. return; //blurgh.
case BTN_LEFT: case BTN_LEFT:
qkey = K_MOUSE1; qkey = K_MOUSE1;
if ((s->absmouse||!vid.activeapp) && s->mousey < s->csdsize) if ((!s->relative_mouse_active||!vid.activeapp) && s->mousey < s->csdsize)
{ {
#ifdef XDG_SHELL_NAME #ifdef XDG_SHELL_NAME
if (s->xdg_toplevel) if (s->xdg_toplevel)
@ -822,7 +896,7 @@ static void WL_pointer_handle_button(void *data, struct wl_pointer *wl_pointer,
break; break;
case BTN_RIGHT: case BTN_RIGHT:
qkey = K_MOUSE2; qkey = K_MOUSE2;
if ((s->absmouse||!vid.activeapp) && s->mousey < s->csdsize) if ((!s->relative_mouse_active||!vid.activeapp) && s->mousey < s->csdsize)
{ {
#ifdef XDG_SHELL_NAME #ifdef XDG_SHELL_NAME
if (s->xdg_toplevel) if (s->xdg_toplevel)
@ -889,8 +963,12 @@ struct zwp_relative_pointer_v1;
static void WL_pointer_handle_delta(void *data, struct zwp_relative_pointer_v1 *pointer, uint32_t time_hi, uint32_t time_lo, wl_fixed_t dx_w, wl_fixed_t dy_w, wl_fixed_t dx_raw_w, wl_fixed_t dy_raw_w) static void WL_pointer_handle_delta(void *data, struct zwp_relative_pointer_v1 *pointer, uint32_t time_hi, uint32_t time_lo, wl_fixed_t dx_w, wl_fixed_t dy_w, wl_fixed_t dx_raw_w, wl_fixed_t dy_raw_w)
{ {
if (!w.absmouse) if (w.relative_mouse_active)
IN_MouseMove(0, false, wl_fixed_to_double(dx_raw_w), wl_fixed_to_double(dy_raw_w), 0, 0); {
double xmove = wl_fixed_to_double(dx_raw_w);
double ymove = wl_fixed_to_double(dy_raw_w);
IN_MouseMove(0, false, xmove, ymove, 0, 0);
}
} }
struct zwp_relative_pointer_v1_listener struct zwp_relative_pointer_v1_listener
{ {
@ -940,16 +1018,23 @@ static void WL_BindRelativePointerManager(struct wl_registry *registry, uint32_t
#define ZWP_POINTER_CONSTRAINTS_V1_LOCK_POINTER 1 #define ZWP_POINTER_CONSTRAINTS_V1_LOCK_POINTER 1
#define ZWP_POINTER_CONSTRAINTS_V1_CONFINE_POINTER 2 #define ZWP_POINTER_CONSTRAINTS_V1_CONFINE_POINTER 2
#define ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_ONESHOT 1 #define ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_ONESHOT 1
#define ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT 2
#define ZWP_LOCKED_POINTER_V1_DESTROY 0 #define ZWP_LOCKED_POINTER_V1_DESTROY 0
#define ZWP_LOCKED_POINTER_V1_SET_CURSOR_POSITION_HINT 1 #define ZWP_LOCKED_POINTER_V1_SET_CURSOR_POSITION_HINT 1
#define ZWP_LOCKED_POINTER_V1_SET_REGION 2 #define ZWP_LOCKED_POINTER_V1_SET_REGION 2
static void WL_pointer_handle_locked(void *data, struct zwp_locked_pointer_v1 *pointer) static void WL_pointer_handle_locked(void *data, struct zwp_locked_pointer_v1 *pointer)
{ {
struct wdisplay_s *s = data;
s->relative_mouse_active = true; //yay, everything works!...
WL_SetHWCursor();
} }
static void WL_pointer_handle_unlocked(void *data, struct zwp_locked_pointer_v1 *pointer) static void WL_pointer_handle_unlocked(void *data, struct zwp_locked_pointer_v1 *pointer)
{ //this is a one-shot. it gets destroyed automatically, but we still need to null it { //this is a one-shot. it gets destroyed automatically, but we still need to null it
struct wdisplay_s *s = data; struct wdisplay_s *s = data;
s->locked_pointer = NULL; s->relative_mouse_active = false; //probably the compositor killed it.
WL_SetHWCursor();
// s->locked_pointer = NULL;
} }
struct zwp_locked_pointer_v1_listener struct zwp_locked_pointer_v1_listener
{ {
@ -1017,11 +1102,14 @@ static void WL_keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard,
{ {
struct xkb_keymap *keymap; struct xkb_keymap *keymap;
char *keymap_string = mmap (NULL, size, PROT_READ, MAP_SHARED, fd, 0); char *keymap_string = mmap (NULL, size, PROT_READ, MAP_SHARED, fd, 0);
keymap = pxkb_keymap_new_from_string (d->xkb_context, keymap_string, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS); if (keymap_string != MAP_FAILED)
munmap (keymap_string, size); {
pxkb_state_unref (d->xkb_state); keymap = pxkb_keymap_new_from_string (d->xkb_context, keymap_string, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS);
d->xkb_state = pxkb_state_new (keymap); munmap (keymap_string, size);
pxkb_keymap_unref (keymap); pxkb_state_unref (d->xkb_state);
d->xkb_state = pxkb_state_new (keymap);
pxkb_keymap_unref (keymap);
}
} }
close(fd); close(fd);
@ -1238,7 +1326,7 @@ static struct org_kde_kwin_server_decoration_listener myorg_kde_kwin_server_deco
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;
Con_DLPrintf(2, "Wayland Interface %s id %u version %u\n", interface, id, version); Con_DLPrintf(0, "Wayland Interface %s id %u version %u\n", interface, id, version);
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_shm") == 0) else if (strcmp(interface, "wl_shm") == 0)
@ -1249,7 +1337,7 @@ Con_DLPrintf(2, "Wayland Interface %s id %u version %u\n", interface, id, versio
#endif #endif
#ifdef XDG_SHELL_NAME #ifdef XDG_SHELL_NAME
else if (strcmp(interface, XDG_SHELL_NAME) == 0 && version > 1) //old versions of kwin are buggy, sidestep it. else if (strcmp(interface, XDG_SHELL_NAME) == 0 && version > 1) //old versions of kwin are buggy, sidestep it.
w.xdg_wm_base = pwl_registry_bind(registry, id, pxdg_wm_base_interface, 2); d->xdg_wm_base = pwl_registry_bind(registry, id, pxdg_wm_base_interface, 2);
#endif #endif
else if (strcmp(interface, "wl_seat") == 0 && !d->seat) else if (strcmp(interface, "wl_seat") == 0 && !d->seat)
{ {
@ -1275,12 +1363,42 @@ Con_DLPrintf(2, "Wayland Interface %s id %u version %u\n", interface, id, versio
*/ */
} }
static void WL_handle_global_remove(void *data, struct wl_registry *wl_registry, uint32_t id)
{
Con_Printf("WL_handle_global_remove: %u\n", id);
}
static const struct wl_registry_listener WL_registry_listener = { static const struct wl_registry_listener WL_registry_listener = {
WL_handle_global WL_handle_global,
WL_handle_global_remove
};
qboolean WL_MayRefresh(void)
{
if (w.wait_for_configure || w.waylandisblocking)
{
if (pwl_display_dispatch(w.display) == -1)
{
Sys_Sleep(2);
Con_Printf(CON_ERROR "wayland connection was lost. Restarting video\n");
Cbuf_InsertText("vid_restart", RESTRICT_LOCAL, true);
}
return false;
}
return true;
}
static void frame_handle_done(void *data, struct wl_callback *callback, uint32_t time)
{
pwl_proxy_destroy((struct wl_proxy *)callback);
w.waylandisblocking = false;
}
static const struct wl_callback_listener frame_listener = {
.done = frame_handle_done,
}; };
static void WL_SwapBuffers(void) static void WL_SwapBuffers(void)
{ {
qboolean wantabs;
TRACE(("WL_SwapBuffers\n")); TRACE(("WL_SwapBuffers\n"));
switch(qrenderer) switch(qrenderer)
@ -1311,6 +1429,13 @@ static void WL_SwapBuffers(void)
if (R2D_Flush) if (R2D_Flush)
R2D_Flush(); R2D_Flush();
{
// Register a frame callback to know when we need to draw the next frame
struct wl_callback *callback = pwl_surface_frame(w.surface);
w.waylandisblocking = true;
pwl_callback_add_listener(callback, &frame_listener, NULL);
}
EGL_SwapBuffers(); EGL_SwapBuffers();
//wl_surface_damage(w.surface, 0, 0, vid.pixelwidth, vid.pixelheight); //wl_surface_damage(w.surface, 0, 0, vid.pixelwidth, vid.pixelheight);
if (pwl_display_dispatch_pending(w.display) < 0) if (pwl_display_dispatch_pending(w.display) < 0)
@ -1321,7 +1446,7 @@ static void WL_SwapBuffers(void)
} }
if (w.hasssd) if (w.hasssd)
w.csdsize = 0; //kde's implementation-specific/legacy extension doesn't need us to draw crappy lame CSD junk w.csdsize = 0; //kde's implementation-specific/legacy extension doesn't need us to draw crappy lame CSD junk
else if (vid.activeapp && !w.absmouse) else if (vid.activeapp && w.relative_mouse_active)
w.csdsize = 0; //kill the csd while using relative mouse coords. w.csdsize = 0; //kill the csd while using relative mouse coords.
else else
w.csdsize = Font_CharPHeight(font_default)+8; w.csdsize = Font_CharPHeight(font_default)+8;
@ -1339,21 +1464,24 @@ static void WL_SwapBuffers(void)
} }
//if the game wants absolute mouse positions... //if the game wants absolute mouse positions...
w.absmouse = !vid.activeapp || Key_MouseShouldBeFree() || !in_windowed_mouse.value; wantabs = !vid.activeapp || Key_MouseShouldBeFree() || !in_windowed_mouse.value;
//and force it on if we're lacking one of the plethora of extensions that were needed to get the damn thing actually usable. //and force it on if we're lacking one of the plethora of extensions that were needed to get the damn thing actually usable.
w.absmouse |= !w.relative_pointer || !w.locked_pointer; wantabs |= !w.relative_pointer || !w.pointer_constraints;
if (!w.absmouse && !w.locked_pointer && w.pointer_constraints) if (!wantabs && w.cursorfocus && !w.locked_pointer && w.pointer_constraints)
{ {
w.locked_pointer = zwp_pointer_constraints_v1_lock_pointer(w.pointer_constraints, w.surface, w.pointer, NULL, ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_ONESHOT); w.locked_pointer = zwp_pointer_constraints_v1_lock_pointer(w.pointer_constraints, w.surface, w.pointer, NULL, ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT);
zwp_locked_pointer_v1_add_listener(w.locked_pointer, &locked_pointer_listener, &w); zwp_locked_pointer_v1_add_listener(w.locked_pointer, &locked_pointer_listener, &w);
WL_SetHWCursor();
} }
if (w.absmouse && w.locked_pointer) if (wantabs && w.locked_pointer)
{ {
pwl_proxy_marshal((struct wl_proxy *) w.locked_pointer, ZWP_LOCKED_POINTER_V1_DESTROY); pwl_proxy_marshal((struct wl_proxy *) w.locked_pointer, ZWP_LOCKED_POINTER_V1_DESTROY);
pwl_proxy_destroy((struct wl_proxy *) w.locked_pointer); pwl_proxy_destroy((struct wl_proxy *) w.locked_pointer);
w.locked_pointer = NULL; w.locked_pointer = NULL;
WL_SetHWCursor(); if (!w.relative_mouse_active)
{
w.relative_mouse_active = false;
WL_SetHWCursor();
}
} }
} }
@ -1386,23 +1514,27 @@ static qboolean WL_NameAndShame(void)
static qboolean WL_Init (rendererstate_t *info, unsigned char *palette) static qboolean WL_Init (rendererstate_t *info, unsigned char *palette)
{ {
#ifdef DYNAMIC_WAYLAND
if (!WL_InitLibrary()) if (!WL_InitLibrary())
{ {
Con_Printf("couldn't load wayland client libraries\n"); Con_Printf("couldn't load wayland client libraries\n");
return false; return false;
} }
#endif
WL_Setup_XDG_Shell(); WL_Setup_XDG_Shell();
switch(qrenderer) switch(qrenderer)
{ {
#if defined(GLQUAKE) && defined(USE_EGL) #if defined(GLQUAKE) && defined(USE_EGL)
case QR_OPENGL: case QR_OPENGL:
#ifdef DYNAMIC_WAYLAND
lib_wayland_egl = Sys_LoadLibrary("libwayland-egl.so.1", waylandexports_egl); lib_wayland_egl = Sys_LoadLibrary("libwayland-egl.so.1", waylandexports_egl);
if (!lib_wayland_egl) if (!lib_wayland_egl)
{ {
Con_Printf("couldn't load libwayland-egl.so.1 library\n"); Con_Printf("couldn't load libwayland-egl.so.1 library\n");
return false; return false;
} }
#endif
// setenv("EGL_PLATFORM", "wayland", 1); //if this actually matters then we're kinda screwed // setenv("EGL_PLATFORM", "wayland", 1); //if this actually matters then we're kinda screwed
if (!EGL_LoadLibrary(info->subrenderer)) if (!EGL_LoadLibrary(info->subrenderer))
@ -1441,7 +1573,9 @@ static qboolean WL_Init (rendererstate_t *info, unsigned char *palette)
memset(&w, 0, sizeof(w)); memset(&w, 0, sizeof(w));
#ifdef DYNAMIC_WAYLAND
if (WL_InitLibraryXKB()) if (WL_InitLibraryXKB())
#endif
w.xkb_context = pxkb_context_new(XKB_CONTEXT_NO_FLAGS); w.xkb_context = pxkb_context_new(XKB_CONTEXT_NO_FLAGS);
w.csdsize = 0; w.csdsize = 0;
@ -1493,6 +1627,11 @@ static qboolean WL_Init (rendererstate_t *info, unsigned char *palette)
pwl_shell_surface_add_listener(w.ssurface, &shell_surface_listener, &w); pwl_shell_surface_add_listener(w.ssurface, &shell_surface_listener, &w);
} }
#endif #endif
else
{
Con_Printf("no compositor shell running, apparently\n");
return false; //no way to make it fullscreen/top-level means it'll probably stay hidden, so make this fatal.
}
WL_SetCaption("FTE Quake"); WL_SetCaption("FTE Quake");
#ifdef ORG_KDE_KWIN_SERVER_DECORATION_MANAGER_NAME #ifdef ORG_KDE_KWIN_SERVER_DECORATION_MANAGER_NAME
@ -1569,6 +1708,13 @@ pwl_display_roundtrip(w.display);
Con_Printf("couldn't find suitable EGL config\n"); Con_Printf("couldn't find suitable EGL config\n");
return false; return false;
} }
#ifdef XDG_SHELL_NAME
if (w.xdg_toplevel)
{
w.wait_for_configure = true;
pwl_surface_commit(w.surface);
}
#endif
if (!EGL_InitWindow(info, EGL_PLATFORM_WAYLAND_KHR, w.enwindow, (EGLNativeWindowType)w.enwindow, cfg)) if (!EGL_InitWindow(info, EGL_PLATFORM_WAYLAND_KHR, w.enwindow, (EGLNativeWindowType)w.enwindow, cfg))
{ {
Con_Printf("couldn't initialise EGL context\n"); Con_Printf("couldn't initialise EGL context\n");
@ -1711,7 +1857,10 @@ rendererinfo_t rendererinfo_wayland_gl =
GLBE_RenderToTextureUpdate2d, GLBE_RenderToTextureUpdate2d,
"", "",
WL_GetPriority WL_GetPriority,
NULL,
NULL,
WL_MayRefresh
}; };
#endif #endif

View File

@ -52,260 +52,242 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
#endif #endif
#ifdef VKQUAKE #ifdef VKQUAKE
{QR_VULKAN, -1, "fixedemu", {QR_VULKAN, -1, "fixedemu",
"\xFF\x53\x50\x56\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x2C\x00\x00\x00\x14\x00\x00\x00\x40\x00\x00\x00" "\xFF\x53\x50\x56\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x2C\x00\x00\x00\x00\x00\x00\x00\x2C\x00\x00\x00"
"\x74\x10\x00\x00\xB4\x10\x00\x00\x00\x0F\x00\x00\x01\x00\x42\x31\x63\x6F\x6E\x73\x74\x63\x6F\x6C\x6F\x75\x72\x00\x00\x00\x00\x00" "\x10\x0F\x00\x00\x3C\x0F\x00\x00\x40\x0E\x00\x00\x03\x02\x23\x07\x00\x00\x01\x00\x08\x00\x08\x00\x4F\x00\x00\x00\x00\x00\x00\x00"
"\x03\x02\x23\x07\x00\x00\x01\x00\x08\x00\x08\x00\x5B\x00\x00\x00\x00\x00\x00\x00\x11\x00\x02\x00\x01\x00\x00\x00\x0B\x00\x06\x00" "\x11\x00\x02\x00\x01\x00\x00\x00\x0B\x00\x06\x00\x01\x00\x00\x00\x47\x4C\x53\x4C\x2E\x73\x74\x64\x2E\x34\x35\x30\x00\x00\x00\x00"
"\x01\x00\x00\x00\x47\x4C\x53\x4C\x2E\x73\x74\x64\x2E\x34\x35\x30\x00\x00\x00\x00\x0E\x00\x03\x00\x00\x00\x00\x00\x01\x00\x00\x00" "\x0E\x00\x03\x00\x00\x00\x00\x00\x01\x00\x00\x00\x0F\x00\x0F\x00\x00\x00\x00\x00\x04\x00\x00\x00\x6D\x61\x69\x6E\x00\x00\x00\x00"
"\x0F\x00\x0F\x00\x00\x00\x00\x00\x04\x00\x00\x00\x6D\x61\x69\x6E\x00\x00\x00\x00\x1C\x00\x00\x00\x39\x00\x00\x00\x3B\x00\x00\x00" "\x1C\x00\x00\x00\x39\x00\x00\x00\x3B\x00\x00\x00\x3E\x00\x00\x00\x40\x00\x00\x00\x44\x00\x00\x00\x4B\x00\x00\x00\x4C\x00\x00\x00"
"\x43\x00\x00\x00\x4C\x00\x00\x00\x50\x00\x00\x00\x57\x00\x00\x00\x58\x00\x00\x00\x59\x00\x00\x00\x5A\x00\x00\x00\x03\x00\x03\x00" "\x4D\x00\x00\x00\x4E\x00\x00\x00\x03\x00\x03\x00\x02\x00\x00\x00\xC2\x01\x00\x00\x05\x00\x04\x00\x04\x00\x00\x00\x6D\x61\x69\x6E"
"\x02\x00\x00\x00\xC2\x01\x00\x00\x05\x00\x04\x00\x04\x00\x00\x00\x6D\x61\x69\x6E\x00\x00\x00\x00\x05\x00\x06\x00\x09\x00\x00\x00" "\x00\x00\x00\x00\x05\x00\x06\x00\x09\x00\x00\x00\x66\x74\x65\x74\x72\x61\x6E\x73\x66\x6F\x72\x6D\x28\x00\x00\x00\x05\x00\x04\x00"
"\x66\x74\x65\x74\x72\x61\x6E\x73\x66\x6F\x72\x6D\x28\x00\x00\x00\x05\x00\x04\x00\x0C\x00\x00\x00\x70\x72\x6F\x6A\x00\x00\x00\x00" "\x0C\x00\x00\x00\x70\x72\x6F\x6A\x00\x00\x00\x00\x05\x00\x05\x00\x13\x00\x00\x00\x65\x6E\x74\x69\x74\x79\x62\x6C\x6F\x63\x6B\x00"
"\x05\x00\x05\x00\x13\x00\x00\x00\x65\x6E\x74\x69\x74\x79\x62\x6C\x6F\x63\x6B\x00\x06\x00\x07\x00\x13\x00\x00\x00\x00\x00\x00\x00" "\x06\x00\x07\x00\x13\x00\x00\x00\x00\x00\x00\x00\x6D\x5F\x6D\x6F\x64\x65\x6C\x76\x69\x65\x77\x70\x72\x6F\x6A\x00\x06\x00\x05\x00"
"\x6D\x5F\x6D\x6F\x64\x65\x6C\x76\x69\x65\x77\x70\x72\x6F\x6A\x00\x06\x00\x05\x00\x13\x00\x00\x00\x01\x00\x00\x00\x6D\x5F\x6D\x6F" "\x13\x00\x00\x00\x01\x00\x00\x00\x6D\x5F\x6D\x6F\x64\x65\x6C\x00\x06\x00\x06\x00\x13\x00\x00\x00\x02\x00\x00\x00\x6D\x5F\x6D\x6F"
"\x64\x65\x6C\x00\x06\x00\x06\x00\x13\x00\x00\x00\x02\x00\x00\x00\x6D\x5F\x6D\x6F\x64\x65\x6C\x69\x6E\x76\x00\x00\x06\x00\x06\x00" "\x64\x65\x6C\x69\x6E\x76\x00\x00\x06\x00\x06\x00\x13\x00\x00\x00\x03\x00\x00\x00\x65\x5F\x65\x79\x65\x70\x6F\x73\x00\x00\x00\x00"
"\x13\x00\x00\x00\x03\x00\x00\x00\x65\x5F\x65\x79\x65\x70\x6F\x73\x00\x00\x00\x00\x06\x00\x05\x00\x13\x00\x00\x00\x04\x00\x00\x00" "\x06\x00\x05\x00\x13\x00\x00\x00\x04\x00\x00\x00\x65\x5F\x74\x69\x6D\x65\x00\x00\x06\x00\x07\x00\x13\x00\x00\x00\x05\x00\x00\x00"
"\x65\x5F\x74\x69\x6D\x65\x00\x00\x06\x00\x07\x00\x13\x00\x00\x00\x05\x00\x00\x00\x65\x5F\x6C\x69\x67\x68\x74\x5F\x61\x6D\x62\x69" "\x65\x5F\x6C\x69\x67\x68\x74\x5F\x61\x6D\x62\x69\x65\x6E\x74\x00\x06\x00\x05\x00\x13\x00\x00\x00\x06\x00\x00\x00\x65\x70\x61\x64"
"\x65\x6E\x74\x00\x06\x00\x05\x00\x13\x00\x00\x00\x06\x00\x00\x00\x65\x70\x61\x64\x31\x00\x00\x00\x06\x00\x06\x00\x13\x00\x00\x00" "\x31\x00\x00\x00\x06\x00\x06\x00\x13\x00\x00\x00\x07\x00\x00\x00\x65\x5F\x6C\x69\x67\x68\x74\x5F\x64\x69\x72\x00\x06\x00\x05\x00"
"\x07\x00\x00\x00\x65\x5F\x6C\x69\x67\x68\x74\x5F\x64\x69\x72\x00\x06\x00\x05\x00\x13\x00\x00\x00\x08\x00\x00\x00\x65\x70\x61\x64" "\x13\x00\x00\x00\x08\x00\x00\x00\x65\x70\x61\x64\x32\x00\x00\x00\x06\x00\x06\x00\x13\x00\x00\x00\x09\x00\x00\x00\x65\x5F\x6C\x69"
"\x32\x00\x00\x00\x06\x00\x06\x00\x13\x00\x00\x00\x09\x00\x00\x00\x65\x5F\x6C\x69\x67\x68\x74\x5F\x6D\x75\x6C\x00\x06\x00\x05\x00" "\x67\x68\x74\x5F\x6D\x75\x6C\x00\x06\x00\x05\x00\x13\x00\x00\x00\x0A\x00\x00\x00\x65\x70\x61\x64\x33\x00\x00\x00\x06\x00\x06\x00"
"\x13\x00\x00\x00\x0A\x00\x00\x00\x65\x70\x61\x64\x33\x00\x00\x00\x06\x00\x06\x00\x13\x00\x00\x00\x0B\x00\x00\x00\x65\x5F\x6C\x6D" "\x13\x00\x00\x00\x0B\x00\x00\x00\x65\x5F\x6C\x6D\x73\x63\x61\x6C\x65\x73\x00\x00\x06\x00\x07\x00\x13\x00\x00\x00\x0C\x00\x00\x00"
"\x73\x63\x61\x6C\x65\x73\x00\x00\x06\x00\x07\x00\x13\x00\x00\x00\x0C\x00\x00\x00\x65\x5F\x75\x70\x70\x65\x72\x63\x6F\x6C\x6F\x75" "\x65\x5F\x75\x70\x70\x65\x72\x63\x6F\x6C\x6F\x75\x72\x00\x00\x00\x06\x00\x05\x00\x13\x00\x00\x00\x0D\x00\x00\x00\x65\x70\x61\x64"
"\x72\x00\x00\x00\x06\x00\x05\x00\x13\x00\x00\x00\x0D\x00\x00\x00\x65\x70\x61\x64\x34\x00\x00\x00\x06\x00\x07\x00\x13\x00\x00\x00" "\x34\x00\x00\x00\x06\x00\x07\x00\x13\x00\x00\x00\x0E\x00\x00\x00\x65\x5F\x6C\x6F\x77\x65\x72\x63\x6F\x6C\x6F\x75\x72\x00\x00\x00"
"\x0E\x00\x00\x00\x65\x5F\x6C\x6F\x77\x65\x72\x63\x6F\x6C\x6F\x75\x72\x00\x00\x00\x06\x00\x05\x00\x13\x00\x00\x00\x0F\x00\x00\x00" "\x06\x00\x05\x00\x13\x00\x00\x00\x0F\x00\x00\x00\x65\x70\x61\x64\x35\x00\x00\x00\x06\x00\x06\x00\x13\x00\x00\x00\x10\x00\x00\x00"
"\x65\x70\x61\x64\x35\x00\x00\x00\x06\x00\x06\x00\x13\x00\x00\x00\x10\x00\x00\x00\x65\x5F\x67\x6C\x6F\x77\x6D\x6F\x64\x00\x00\x00" "\x65\x5F\x67\x6C\x6F\x77\x6D\x6F\x64\x00\x00\x00\x06\x00\x05\x00\x13\x00\x00\x00\x11\x00\x00\x00\x65\x70\x61\x64\x36\x00\x00\x00"
"\x06\x00\x05\x00\x13\x00\x00\x00\x11\x00\x00\x00\x65\x70\x61\x64\x36\x00\x00\x00\x06\x00\x07\x00\x13\x00\x00\x00\x12\x00\x00\x00" "\x06\x00\x07\x00\x13\x00\x00\x00\x12\x00\x00\x00\x65\x5F\x63\x6F\x6C\x6F\x75\x72\x69\x64\x65\x6E\x74\x00\x00\x00\x06\x00\x07\x00"
"\x65\x5F\x63\x6F\x6C\x6F\x75\x72\x69\x64\x65\x6E\x74\x00\x00\x00\x06\x00\x07\x00\x13\x00\x00\x00\x13\x00\x00\x00\x77\x5F\x66\x6F" "\x13\x00\x00\x00\x13\x00\x00\x00\x77\x5F\x66\x6F\x67\x63\x6F\x6C\x6F\x75\x72\x73\x00\x00\x00\x00\x06\x00\x07\x00\x13\x00\x00\x00"
"\x67\x63\x6F\x6C\x6F\x75\x72\x73\x00\x00\x00\x00\x06\x00\x07\x00\x13\x00\x00\x00\x14\x00\x00\x00\x77\x5F\x66\x6F\x67\x64\x65\x6E" "\x14\x00\x00\x00\x77\x5F\x66\x6F\x67\x64\x65\x6E\x73\x69\x74\x79\x00\x00\x00\x00\x06\x00\x07\x00\x13\x00\x00\x00\x15\x00\x00\x00"
"\x73\x69\x74\x79\x00\x00\x00\x00\x06\x00\x07\x00\x13\x00\x00\x00\x15\x00\x00\x00\x77\x5F\x66\x6F\x67\x64\x65\x70\x74\x68\x62\x69" "\x77\x5F\x66\x6F\x67\x64\x65\x70\x74\x68\x62\x69\x61\x73\x00\x00\x06\x00\x05\x00\x13\x00\x00\x00\x16\x00\x00\x00\x65\x70\x61\x64"
"\x61\x73\x00\x00\x06\x00\x05\x00\x13\x00\x00\x00\x16\x00\x00\x00\x65\x70\x61\x64\x37\x00\x00\x00\x05\x00\x03\x00\x15\x00\x00\x00" "\x37\x00\x00\x00\x05\x00\x03\x00\x15\x00\x00\x00\x00\x00\x00\x00\x05\x00\x05\x00\x1C\x00\x00\x00\x76\x5F\x70\x6F\x73\x69\x74\x69"
"\x00\x00\x00\x00\x05\x00\x05\x00\x1C\x00\x00\x00\x76\x5F\x70\x6F\x73\x69\x74\x69\x6F\x6E\x00\x00\x05\x00\x03\x00\x39\x00\x00\x00" "\x6F\x6E\x00\x00\x05\x00\x03\x00\x39\x00\x00\x00\x74\x63\x00\x00\x05\x00\x05\x00\x3B\x00\x00\x00\x76\x5F\x74\x65\x78\x63\x6F\x6F"
"\x74\x63\x00\x00\x05\x00\x05\x00\x3B\x00\x00\x00\x76\x5F\x74\x65\x78\x63\x6F\x6F\x72\x64\x00\x00\x05\x00\x07\x00\x3D\x00\x00\x00" "\x72\x64\x00\x00\x05\x00\x03\x00\x3E\x00\x00\x00\x76\x63\x00\x00\x05\x00\x05\x00\x40\x00\x00\x00\x76\x5F\x63\x6F\x6C\x6F\x75\x72"
"\x5F\x61\x72\x67\x5F\x63\x6F\x6E\x73\x74\x63\x6F\x6C\x6F\x75\x72\x00\x00\x00\x00\x05\x00\x03\x00\x43\x00\x00\x00\x76\x63\x00\x00" "\x00\x00\x00\x00\x05\x00\x06\x00\x42\x00\x00\x00\x67\x6C\x5F\x50\x65\x72\x56\x65\x72\x74\x65\x78\x00\x00\x00\x00\x06\x00\x06\x00"
"\x05\x00\x05\x00\x44\x00\x00\x00\x70\x75\x73\x68\x69\x6E\x74\x66\x00\x00\x00\x00\x06\x00\x05\x00\x44\x00\x00\x00\x00\x00\x00\x00" "\x42\x00\x00\x00\x00\x00\x00\x00\x67\x6C\x5F\x50\x6F\x73\x69\x74\x69\x6F\x6E\x00\x05\x00\x03\x00\x44\x00\x00\x00\x00\x00\x00\x00"
"\x63\x6F\x6C\x6F\x75\x72\x00\x00\x05\x00\x04\x00\x46\x00\x00\x00\x70\x75\x73\x68\x00\x00\x00\x00\x05\x00\x05\x00\x4C\x00\x00\x00" "\x05\x00\x05\x00\x47\x00\x00\x00\x61\x6C\x70\x68\x61\x74\x65\x73\x74\x00\x00\x00\x05\x00\x05\x00\x48\x00\x00\x00\x6C\x69\x67\x68"
"\x76\x5F\x63\x6F\x6C\x6F\x75\x72\x00\x00\x00\x00\x05\x00\x06\x00\x4E\x00\x00\x00\x67\x6C\x5F\x50\x65\x72\x56\x65\x72\x74\x65\x78" "\x74\x62\x6C\x6F\x63\x6B\x00\x00\x06\x00\x07\x00\x48\x00\x00\x00\x00\x00\x00\x00\x6C\x5F\x63\x75\x62\x65\x6D\x61\x74\x72\x69\x78"
"\x00\x00\x00\x00\x06\x00\x06\x00\x4E\x00\x00\x00\x00\x00\x00\x00\x67\x6C\x5F\x50\x6F\x73\x69\x74\x69\x6F\x6E\x00\x05\x00\x03\x00" "\x00\x00\x00\x00\x06\x00\x07\x00\x48\x00\x00\x00\x01\x00\x00\x00\x6C\x5F\x6C\x69\x67\x68\x74\x70\x6F\x73\x69\x74\x69\x6F\x6E\x00"
"\x50\x00\x00\x00\x00\x00\x00\x00\x05\x00\x05\x00\x53\x00\x00\x00\x61\x6C\x70\x68\x61\x74\x65\x73\x74\x00\x00\x00\x05\x00\x05\x00" "\x06\x00\x05\x00\x48\x00\x00\x00\x02\x00\x00\x00\x6C\x70\x61\x64\x31\x00\x00\x00\x06\x00\x07\x00\x48\x00\x00\x00\x03\x00\x00\x00"
"\x54\x00\x00\x00\x6C\x69\x67\x68\x74\x62\x6C\x6F\x63\x6B\x00\x00\x06\x00\x07\x00\x54\x00\x00\x00\x00\x00\x00\x00\x6C\x5F\x63\x75" "\x6C\x5F\x6C\x69\x67\x68\x74\x63\x6F\x6C\x6F\x75\x72\x00\x00\x00\x06\x00\x05\x00\x48\x00\x00\x00\x04\x00\x00\x00\x6C\x70\x61\x64"
"\x62\x65\x6D\x61\x74\x72\x69\x78\x00\x00\x00\x00\x06\x00\x07\x00\x54\x00\x00\x00\x01\x00\x00\x00\x6C\x5F\x6C\x69\x67\x68\x74\x70" "\x32\x00\x00\x00\x06\x00\x08\x00\x48\x00\x00\x00\x05\x00\x00\x00\x6C\x5F\x6C\x69\x67\x68\x74\x63\x6F\x6C\x6F\x75\x72\x73\x63\x61"
"\x6F\x73\x69\x74\x69\x6F\x6E\x00\x06\x00\x05\x00\x54\x00\x00\x00\x02\x00\x00\x00\x6C\x70\x61\x64\x31\x00\x00\x00\x06\x00\x07\x00" "\x6C\x65\x00\x00\x06\x00\x07\x00\x48\x00\x00\x00\x06\x00\x00\x00\x6C\x5F\x6C\x69\x67\x68\x74\x72\x61\x64\x69\x75\x73\x00\x00\x00"
"\x54\x00\x00\x00\x03\x00\x00\x00\x6C\x5F\x6C\x69\x67\x68\x74\x63\x6F\x6C\x6F\x75\x72\x00\x00\x00\x06\x00\x05\x00\x54\x00\x00\x00" "\x06\x00\x07\x00\x48\x00\x00\x00\x07\x00\x00\x00\x6C\x5F\x73\x68\x61\x64\x6F\x77\x6D\x61\x70\x70\x72\x6F\x6A\x00\x06\x00\x08\x00"
"\x04\x00\x00\x00\x6C\x70\x61\x64\x32\x00\x00\x00\x06\x00\x08\x00\x54\x00\x00\x00\x05\x00\x00\x00\x6C\x5F\x6C\x69\x67\x68\x74\x63" "\x48\x00\x00\x00\x08\x00\x00\x00\x6C\x5F\x73\x68\x61\x64\x6F\x77\x6D\x61\x70\x73\x63\x61\x6C\x65\x00\x00\x00\x00\x06\x00\x05\x00"
"\x6F\x6C\x6F\x75\x72\x73\x63\x61\x6C\x65\x00\x00\x06\x00\x07\x00\x54\x00\x00\x00\x06\x00\x00\x00\x6C\x5F\x6C\x69\x67\x68\x74\x72" "\x48\x00\x00\x00\x09\x00\x00\x00\x6C\x70\x61\x64\x33\x00\x00\x00\x05\x00\x03\x00\x4A\x00\x00\x00\x00\x00\x00\x00\x05\x00\x05\x00"
"\x61\x64\x69\x75\x73\x00\x00\x00\x06\x00\x07\x00\x54\x00\x00\x00\x07\x00\x00\x00\x6C\x5F\x73\x68\x61\x64\x6F\x77\x6D\x61\x70\x70" "\x4B\x00\x00\x00\x76\x5F\x6C\x6D\x63\x6F\x6F\x72\x64\x00\x00\x00\x05\x00\x05\x00\x4C\x00\x00\x00\x76\x5F\x6E\x6F\x72\x6D\x61\x6C"
"\x72\x6F\x6A\x00\x06\x00\x08\x00\x54\x00\x00\x00\x08\x00\x00\x00\x6C\x5F\x73\x68\x61\x64\x6F\x77\x6D\x61\x70\x73\x63\x61\x6C\x65" "\x00\x00\x00\x00\x05\x00\x05\x00\x4D\x00\x00\x00\x76\x5F\x73\x76\x65\x63\x74\x6F\x72\x00\x00\x00\x05\x00\x05\x00\x4E\x00\x00\x00"
"\x00\x00\x00\x00\x06\x00\x05\x00\x54\x00\x00\x00\x09\x00\x00\x00\x6C\x70\x61\x64\x33\x00\x00\x00\x05\x00\x03\x00\x56\x00\x00\x00" "\x76\x5F\x74\x76\x65\x63\x74\x6F\x72\x00\x00\x00\x47\x00\x04\x00\x11\x00\x00\x00\x06\x00\x00\x00\x10\x00\x00\x00\x48\x00\x04\x00"
"\x00\x00\x00\x00\x05\x00\x05\x00\x57\x00\x00\x00\x76\x5F\x6C\x6D\x63\x6F\x6F\x72\x64\x00\x00\x00\x05\x00\x05\x00\x58\x00\x00\x00" "\x13\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00\x00\x00\x00\x00\x23\x00\x00\x00\x00\x00\x00\x00"
"\x76\x5F\x6E\x6F\x72\x6D\x61\x6C\x00\x00\x00\x00\x05\x00\x05\x00\x59\x00\x00\x00\x76\x5F\x73\x76\x65\x63\x74\x6F\x72\x00\x00\x00" "\x48\x00\x05\x00\x13\x00\x00\x00\x00\x00\x00\x00\x07\x00\x00\x00\x10\x00\x00\x00\x48\x00\x04\x00\x13\x00\x00\x00\x01\x00\x00\x00"
"\x05\x00\x05\x00\x5A\x00\x00\x00\x76\x5F\x74\x76\x65\x63\x74\x6F\x72\x00\x00\x00\x47\x00\x04\x00\x11\x00\x00\x00\x06\x00\x00\x00" "\x05\x00\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00\x01\x00\x00\x00\x23\x00\x00\x00\x40\x00\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00"
"\x10\x00\x00\x00\x48\x00\x04\x00\x13\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00\x00\x00\x00\x00" "\x01\x00\x00\x00\x07\x00\x00\x00\x10\x00\x00\x00\x48\x00\x04\x00\x13\x00\x00\x00\x02\x00\x00\x00\x05\x00\x00\x00\x48\x00\x05\x00"
"\x23\x00\x00\x00\x00\x00\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00\x00\x00\x00\x00\x07\x00\x00\x00\x10\x00\x00\x00\x48\x00\x04\x00" "\x13\x00\x00\x00\x02\x00\x00\x00\x23\x00\x00\x00\x80\x00\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00\x02\x00\x00\x00\x07\x00\x00\x00"
"\x13\x00\x00\x00\x01\x00\x00\x00\x05\x00\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00\x01\x00\x00\x00\x23\x00\x00\x00\x40\x00\x00\x00" "\x10\x00\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00\x03\x00\x00\x00\x23\x00\x00\x00\xC0\x00\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00"
"\x48\x00\x05\x00\x13\x00\x00\x00\x01\x00\x00\x00\x07\x00\x00\x00\x10\x00\x00\x00\x48\x00\x04\x00\x13\x00\x00\x00\x02\x00\x00\x00" "\x04\x00\x00\x00\x23\x00\x00\x00\xCC\x00\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00\x05\x00\x00\x00\x23\x00\x00\x00\xD0\x00\x00\x00"
"\x05\x00\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00\x02\x00\x00\x00\x23\x00\x00\x00\x80\x00\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00" "\x48\x00\x05\x00\x13\x00\x00\x00\x06\x00\x00\x00\x23\x00\x00\x00\xDC\x00\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00\x07\x00\x00\x00"
"\x02\x00\x00\x00\x07\x00\x00\x00\x10\x00\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00\x03\x00\x00\x00\x23\x00\x00\x00\xC0\x00\x00\x00" "\x23\x00\x00\x00\xE0\x00\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00\x08\x00\x00\x00\x23\x00\x00\x00\xEC\x00\x00\x00\x48\x00\x05\x00"
"\x48\x00\x05\x00\x13\x00\x00\x00\x04\x00\x00\x00\x23\x00\x00\x00\xCC\x00\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00\x05\x00\x00\x00" "\x13\x00\x00\x00\x09\x00\x00\x00\x23\x00\x00\x00\xF0\x00\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00\x0A\x00\x00\x00\x23\x00\x00\x00"
"\x23\x00\x00\x00\xD0\x00\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00\x06\x00\x00\x00\x23\x00\x00\x00\xDC\x00\x00\x00\x48\x00\x05\x00" "\xFC\x00\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00\x0B\x00\x00\x00\x23\x00\x00\x00\x00\x01\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00"
"\x13\x00\x00\x00\x07\x00\x00\x00\x23\x00\x00\x00\xE0\x00\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00\x08\x00\x00\x00\x23\x00\x00\x00" "\x0C\x00\x00\x00\x23\x00\x00\x00\x40\x01\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00\x0D\x00\x00\x00\x23\x00\x00\x00\x4C\x01\x00\x00"
"\xEC\x00\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00\x09\x00\x00\x00\x23\x00\x00\x00\xF0\x00\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00" "\x48\x00\x05\x00\x13\x00\x00\x00\x0E\x00\x00\x00\x23\x00\x00\x00\x50\x01\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00\x0F\x00\x00\x00"
"\x0A\x00\x00\x00\x23\x00\x00\x00\xFC\x00\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00\x0B\x00\x00\x00\x23\x00\x00\x00\x00\x01\x00\x00" "\x23\x00\x00\x00\x5C\x01\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00\x10\x00\x00\x00\x23\x00\x00\x00\x60\x01\x00\x00\x48\x00\x05\x00"
"\x48\x00\x05\x00\x13\x00\x00\x00\x0C\x00\x00\x00\x23\x00\x00\x00\x40\x01\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00\x0D\x00\x00\x00" "\x13\x00\x00\x00\x11\x00\x00\x00\x23\x00\x00\x00\x6C\x01\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00\x12\x00\x00\x00\x23\x00\x00\x00"
"\x23\x00\x00\x00\x4C\x01\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00\x0E\x00\x00\x00\x23\x00\x00\x00\x50\x01\x00\x00\x48\x00\x05\x00" "\x70\x01\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00\x13\x00\x00\x00\x23\x00\x00\x00\x80\x01\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00"
"\x13\x00\x00\x00\x0F\x00\x00\x00\x23\x00\x00\x00\x5C\x01\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00\x10\x00\x00\x00\x23\x00\x00\x00" "\x14\x00\x00\x00\x23\x00\x00\x00\x90\x01\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00\x15\x00\x00\x00\x23\x00\x00\x00\x94\x01\x00\x00"
"\x60\x01\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00\x11\x00\x00\x00\x23\x00\x00\x00\x6C\x01\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00" "\x48\x00\x05\x00\x13\x00\x00\x00\x16\x00\x00\x00\x23\x00\x00\x00\x98\x01\x00\x00\x47\x00\x03\x00\x13\x00\x00\x00\x02\x00\x00\x00"
"\x12\x00\x00\x00\x23\x00\x00\x00\x70\x01\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00\x13\x00\x00\x00\x23\x00\x00\x00\x80\x01\x00\x00" "\x47\x00\x04\x00\x15\x00\x00\x00\x22\x00\x00\x00\x00\x00\x00\x00\x47\x00\x04\x00\x15\x00\x00\x00\x21\x00\x00\x00\x00\x00\x00\x00"
"\x48\x00\x05\x00\x13\x00\x00\x00\x14\x00\x00\x00\x23\x00\x00\x00\x90\x01\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00\x15\x00\x00\x00" "\x47\x00\x04\x00\x1C\x00\x00\x00\x1E\x00\x00\x00\x00\x00\x00\x00\x47\x00\x04\x00\x39\x00\x00\x00\x1E\x00\x00\x00\x00\x00\x00\x00"
"\x23\x00\x00\x00\x94\x01\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00\x16\x00\x00\x00\x23\x00\x00\x00\x98\x01\x00\x00\x47\x00\x03\x00" "\x47\x00\x04\x00\x3B\x00\x00\x00\x1E\x00\x00\x00\x01\x00\x00\x00\x47\x00\x04\x00\x3E\x00\x00\x00\x1E\x00\x00\x00\x01\x00\x00\x00"
"\x13\x00\x00\x00\x02\x00\x00\x00\x47\x00\x04\x00\x15\x00\x00\x00\x22\x00\x00\x00\x00\x00\x00\x00\x47\x00\x04\x00\x15\x00\x00\x00" "\x47\x00\x04\x00\x40\x00\x00\x00\x1E\x00\x00\x00\x02\x00\x00\x00\x48\x00\x05\x00\x42\x00\x00\x00\x00\x00\x00\x00\x0B\x00\x00\x00"
"\x21\x00\x00\x00\x00\x00\x00\x00\x47\x00\x04\x00\x1C\x00\x00\x00\x1E\x00\x00\x00\x00\x00\x00\x00\x47\x00\x04\x00\x39\x00\x00\x00" "\x00\x00\x00\x00\x47\x00\x03\x00\x42\x00\x00\x00\x02\x00\x00\x00\x47\x00\x04\x00\x47\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00"
"\x1E\x00\x00\x00\x00\x00\x00\x00\x47\x00\x04\x00\x3B\x00\x00\x00\x1E\x00\x00\x00\x01\x00\x00\x00\x47\x00\x04\x00\x3D\x00\x00\x00" "\x48\x00\x04\x00\x48\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00\x48\x00\x05\x00\x48\x00\x00\x00\x00\x00\x00\x00\x23\x00\x00\x00"
"\x01\x00\x00\x00\x00\x01\x00\x00\x47\x00\x04\x00\x43\x00\x00\x00\x1E\x00\x00\x00\x01\x00\x00\x00\x48\x00\x05\x00\x44\x00\x00\x00" "\x00\x00\x00\x00\x48\x00\x05\x00\x48\x00\x00\x00\x00\x00\x00\x00\x07\x00\x00\x00\x10\x00\x00\x00\x48\x00\x05\x00\x48\x00\x00\x00"
"\x00\x00\x00\x00\x23\x00\x00\x00\x00\x00\x00\x00\x47\x00\x03\x00\x44\x00\x00\x00\x02\x00\x00\x00\x47\x00\x04\x00\x4C\x00\x00\x00" "\x01\x00\x00\x00\x23\x00\x00\x00\x40\x00\x00\x00\x48\x00\x05\x00\x48\x00\x00\x00\x02\x00\x00\x00\x23\x00\x00\x00\x4C\x00\x00\x00"
"\x1E\x00\x00\x00\x02\x00\x00\x00\x48\x00\x05\x00\x4E\x00\x00\x00\x00\x00\x00\x00\x0B\x00\x00\x00\x00\x00\x00\x00\x47\x00\x03\x00" "\x48\x00\x05\x00\x48\x00\x00\x00\x03\x00\x00\x00\x23\x00\x00\x00\x50\x00\x00\x00\x48\x00\x05\x00\x48\x00\x00\x00\x04\x00\x00\x00"
"\x4E\x00\x00\x00\x02\x00\x00\x00\x47\x00\x04\x00\x53\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x48\x00\x04\x00\x54\x00\x00\x00" "\x23\x00\x00\x00\x5C\x00\x00\x00\x48\x00\x05\x00\x48\x00\x00\x00\x05\x00\x00\x00\x23\x00\x00\x00\x60\x00\x00\x00\x48\x00\x05\x00"
"\x00\x00\x00\x00\x05\x00\x00\x00\x48\x00\x05\x00\x54\x00\x00\x00\x00\x00\x00\x00\x23\x00\x00\x00\x00\x00\x00\x00\x48\x00\x05\x00" "\x48\x00\x00\x00\x06\x00\x00\x00\x23\x00\x00\x00\x6C\x00\x00\x00\x48\x00\x05\x00\x48\x00\x00\x00\x07\x00\x00\x00\x23\x00\x00\x00"
"\x54\x00\x00\x00\x00\x00\x00\x00\x07\x00\x00\x00\x10\x00\x00\x00\x48\x00\x05\x00\x54\x00\x00\x00\x01\x00\x00\x00\x23\x00\x00\x00" "\x70\x00\x00\x00\x48\x00\x05\x00\x48\x00\x00\x00\x08\x00\x00\x00\x23\x00\x00\x00\x80\x00\x00\x00\x48\x00\x05\x00\x48\x00\x00\x00"
"\x40\x00\x00\x00\x48\x00\x05\x00\x54\x00\x00\x00\x02\x00\x00\x00\x23\x00\x00\x00\x4C\x00\x00\x00\x48\x00\x05\x00\x54\x00\x00\x00" "\x09\x00\x00\x00\x23\x00\x00\x00\x88\x00\x00\x00\x47\x00\x03\x00\x48\x00\x00\x00\x02\x00\x00\x00\x47\x00\x04\x00\x4A\x00\x00\x00"
"\x03\x00\x00\x00\x23\x00\x00\x00\x50\x00\x00\x00\x48\x00\x05\x00\x54\x00\x00\x00\x04\x00\x00\x00\x23\x00\x00\x00\x5C\x00\x00\x00" "\x22\x00\x00\x00\x00\x00\x00\x00\x47\x00\x04\x00\x4A\x00\x00\x00\x21\x00\x00\x00\x01\x00\x00\x00\x47\x00\x04\x00\x4B\x00\x00\x00"
"\x48\x00\x05\x00\x54\x00\x00\x00\x05\x00\x00\x00\x23\x00\x00\x00\x60\x00\x00\x00\x48\x00\x05\x00\x54\x00\x00\x00\x06\x00\x00\x00" "\x1E\x00\x00\x00\x03\x00\x00\x00\x47\x00\x04\x00\x4C\x00\x00\x00\x1E\x00\x00\x00\x04\x00\x00\x00\x47\x00\x04\x00\x4D\x00\x00\x00"
"\x23\x00\x00\x00\x6C\x00\x00\x00\x48\x00\x05\x00\x54\x00\x00\x00\x07\x00\x00\x00\x23\x00\x00\x00\x70\x00\x00\x00\x48\x00\x05\x00" "\x1E\x00\x00\x00\x05\x00\x00\x00\x47\x00\x04\x00\x4E\x00\x00\x00\x1E\x00\x00\x00\x06\x00\x00\x00\x13\x00\x02\x00\x02\x00\x00\x00"
"\x54\x00\x00\x00\x08\x00\x00\x00\x23\x00\x00\x00\x80\x00\x00\x00\x48\x00\x05\x00\x54\x00\x00\x00\x09\x00\x00\x00\x23\x00\x00\x00" "\x21\x00\x03\x00\x03\x00\x00\x00\x02\x00\x00\x00\x16\x00\x03\x00\x06\x00\x00\x00\x20\x00\x00\x00\x17\x00\x04\x00\x07\x00\x00\x00"
"\x88\x00\x00\x00\x47\x00\x03\x00\x54\x00\x00\x00\x02\x00\x00\x00\x47\x00\x04\x00\x56\x00\x00\x00\x22\x00\x00\x00\x00\x00\x00\x00" "\x06\x00\x00\x00\x04\x00\x00\x00\x21\x00\x03\x00\x08\x00\x00\x00\x07\x00\x00\x00\x20\x00\x04\x00\x0B\x00\x00\x00\x07\x00\x00\x00"
"\x47\x00\x04\x00\x56\x00\x00\x00\x21\x00\x00\x00\x01\x00\x00\x00\x47\x00\x04\x00\x57\x00\x00\x00\x1E\x00\x00\x00\x03\x00\x00\x00" "\x07\x00\x00\x00\x18\x00\x04\x00\x0D\x00\x00\x00\x07\x00\x00\x00\x04\x00\x00\x00\x17\x00\x04\x00\x0E\x00\x00\x00\x06\x00\x00\x00"
"\x47\x00\x04\x00\x58\x00\x00\x00\x1E\x00\x00\x00\x04\x00\x00\x00\x47\x00\x04\x00\x59\x00\x00\x00\x1E\x00\x00\x00\x05\x00\x00\x00" "\x03\x00\x00\x00\x15\x00\x04\x00\x0F\x00\x00\x00\x20\x00\x00\x00\x00\x00\x00\x00\x2B\x00\x04\x00\x0F\x00\x00\x00\x10\x00\x00\x00"
"\x47\x00\x04\x00\x5A\x00\x00\x00\x1E\x00\x00\x00\x06\x00\x00\x00\x13\x00\x02\x00\x02\x00\x00\x00\x21\x00\x03\x00\x03\x00\x00\x00" "\x04\x00\x00\x00\x1C\x00\x04\x00\x11\x00\x00\x00\x07\x00\x00\x00\x10\x00\x00\x00\x17\x00\x04\x00\x12\x00\x00\x00\x06\x00\x00\x00"
"\x02\x00\x00\x00\x16\x00\x03\x00\x06\x00\x00\x00\x20\x00\x00\x00\x17\x00\x04\x00\x07\x00\x00\x00\x06\x00\x00\x00\x04\x00\x00\x00" "\x02\x00\x00\x00\x1E\x00\x19\x00\x13\x00\x00\x00\x0D\x00\x00\x00\x0D\x00\x00\x00\x0D\x00\x00\x00\x0E\x00\x00\x00\x06\x00\x00\x00"
"\x21\x00\x03\x00\x08\x00\x00\x00\x07\x00\x00\x00\x20\x00\x04\x00\x0B\x00\x00\x00\x07\x00\x00\x00\x07\x00\x00\x00\x18\x00\x04\x00" "\x0E\x00\x00\x00\x06\x00\x00\x00\x0E\x00\x00\x00\x06\x00\x00\x00\x0E\x00\x00\x00\x06\x00\x00\x00\x11\x00\x00\x00\x0E\x00\x00\x00"
"\x0D\x00\x00\x00\x07\x00\x00\x00\x04\x00\x00\x00\x17\x00\x04\x00\x0E\x00\x00\x00\x06\x00\x00\x00\x03\x00\x00\x00\x15\x00\x04\x00" "\x06\x00\x00\x00\x0E\x00\x00\x00\x06\x00\x00\x00\x0E\x00\x00\x00\x06\x00\x00\x00\x07\x00\x00\x00\x07\x00\x00\x00\x06\x00\x00\x00"
"\x0F\x00\x00\x00\x20\x00\x00\x00\x00\x00\x00\x00\x2B\x00\x04\x00\x0F\x00\x00\x00\x10\x00\x00\x00\x04\x00\x00\x00\x1C\x00\x04\x00" "\x06\x00\x00\x00\x12\x00\x00\x00\x20\x00\x04\x00\x14\x00\x00\x00\x02\x00\x00\x00\x13\x00\x00\x00\x3B\x00\x04\x00\x14\x00\x00\x00"
"\x11\x00\x00\x00\x07\x00\x00\x00\x10\x00\x00\x00\x17\x00\x04\x00\x12\x00\x00\x00\x06\x00\x00\x00\x02\x00\x00\x00\x1E\x00\x19\x00" "\x15\x00\x00\x00\x02\x00\x00\x00\x15\x00\x04\x00\x16\x00\x00\x00\x20\x00\x00\x00\x01\x00\x00\x00\x2B\x00\x04\x00\x16\x00\x00\x00"
"\x13\x00\x00\x00\x0D\x00\x00\x00\x0D\x00\x00\x00\x0D\x00\x00\x00\x0E\x00\x00\x00\x06\x00\x00\x00\x0E\x00\x00\x00\x06\x00\x00\x00" "\x17\x00\x00\x00\x00\x00\x00\x00\x20\x00\x04\x00\x18\x00\x00\x00\x02\x00\x00\x00\x0D\x00\x00\x00\x20\x00\x04\x00\x1B\x00\x00\x00"
"\x0E\x00\x00\x00\x06\x00\x00\x00\x0E\x00\x00\x00\x06\x00\x00\x00\x11\x00\x00\x00\x0E\x00\x00\x00\x06\x00\x00\x00\x0E\x00\x00\x00" "\x01\x00\x00\x00\x0E\x00\x00\x00\x3B\x00\x04\x00\x1B\x00\x00\x00\x1C\x00\x00\x00\x01\x00\x00\x00\x2B\x00\x04\x00\x06\x00\x00\x00"
"\x06\x00\x00\x00\x0E\x00\x00\x00\x06\x00\x00\x00\x07\x00\x00\x00\x07\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x12\x00\x00\x00" "\x1E\x00\x00\x00\x00\x00\x80\x3F\x2B\x00\x04\x00\x06\x00\x00\x00\x24\x00\x00\x00\x00\x00\x80\xBF\x2B\x00\x04\x00\x0F\x00\x00\x00"
"\x20\x00\x04\x00\x14\x00\x00\x00\x02\x00\x00\x00\x13\x00\x00\x00\x3B\x00\x04\x00\x14\x00\x00\x00\x15\x00\x00\x00\x02\x00\x00\x00" "\x25\x00\x00\x00\x01\x00\x00\x00\x20\x00\x04\x00\x26\x00\x00\x00\x07\x00\x00\x00\x06\x00\x00\x00\x2B\x00\x04\x00\x0F\x00\x00\x00"
"\x15\x00\x04\x00\x16\x00\x00\x00\x20\x00\x00\x00\x01\x00\x00\x00\x2B\x00\x04\x00\x16\x00\x00\x00\x17\x00\x00\x00\x00\x00\x00\x00" "\x2B\x00\x00\x00\x02\x00\x00\x00\x2B\x00\x04\x00\x0F\x00\x00\x00\x2E\x00\x00\x00\x03\x00\x00\x00\x2B\x00\x04\x00\x06\x00\x00\x00"
"\x20\x00\x04\x00\x18\x00\x00\x00\x02\x00\x00\x00\x0D\x00\x00\x00\x20\x00\x04\x00\x1B\x00\x00\x00\x01\x00\x00\x00\x0E\x00\x00\x00" "\x32\x00\x00\x00\x00\x00\x00\x40\x20\x00\x04\x00\x38\x00\x00\x00\x03\x00\x00\x00\x12\x00\x00\x00\x3B\x00\x04\x00\x38\x00\x00\x00"
"\x3B\x00\x04\x00\x1B\x00\x00\x00\x1C\x00\x00\x00\x01\x00\x00\x00\x2B\x00\x04\x00\x06\x00\x00\x00\x1E\x00\x00\x00\x00\x00\x80\x3F" "\x39\x00\x00\x00\x03\x00\x00\x00\x20\x00\x04\x00\x3A\x00\x00\x00\x01\x00\x00\x00\x12\x00\x00\x00\x3B\x00\x04\x00\x3A\x00\x00\x00"
"\x2B\x00\x04\x00\x06\x00\x00\x00\x24\x00\x00\x00\x00\x00\x80\xBF\x2B\x00\x04\x00\x0F\x00\x00\x00\x25\x00\x00\x00\x01\x00\x00\x00" "\x3B\x00\x00\x00\x01\x00\x00\x00\x20\x00\x04\x00\x3D\x00\x00\x00\x03\x00\x00\x00\x07\x00\x00\x00\x3B\x00\x04\x00\x3D\x00\x00\x00"
"\x20\x00\x04\x00\x26\x00\x00\x00\x07\x00\x00\x00\x06\x00\x00\x00\x2B\x00\x04\x00\x0F\x00\x00\x00\x2B\x00\x00\x00\x02\x00\x00\x00" "\x3E\x00\x00\x00\x03\x00\x00\x00\x20\x00\x04\x00\x3F\x00\x00\x00\x01\x00\x00\x00\x07\x00\x00\x00\x3B\x00\x04\x00\x3F\x00\x00\x00"
"\x2B\x00\x04\x00\x0F\x00\x00\x00\x2E\x00\x00\x00\x03\x00\x00\x00\x2B\x00\x04\x00\x06\x00\x00\x00\x32\x00\x00\x00\x00\x00\x00\x40" "\x40\x00\x00\x00\x01\x00\x00\x00\x1E\x00\x03\x00\x42\x00\x00\x00\x07\x00\x00\x00\x20\x00\x04\x00\x43\x00\x00\x00\x03\x00\x00\x00"
"\x20\x00\x04\x00\x38\x00\x00\x00\x03\x00\x00\x00\x12\x00\x00\x00\x3B\x00\x04\x00\x38\x00\x00\x00\x39\x00\x00\x00\x03\x00\x00\x00" "\x42\x00\x00\x00\x3B\x00\x04\x00\x43\x00\x00\x00\x44\x00\x00\x00\x03\x00\x00\x00\x32\x00\x04\x00\x16\x00\x00\x00\x47\x00\x00\x00"
"\x20\x00\x04\x00\x3A\x00\x00\x00\x01\x00\x00\x00\x12\x00\x00\x00\x3B\x00\x04\x00\x3A\x00\x00\x00\x3B\x00\x00\x00\x01\x00\x00\x00" "\x04\x00\x00\x00\x1E\x00\x0C\x00\x48\x00\x00\x00\x0D\x00\x00\x00\x0E\x00\x00\x00\x06\x00\x00\x00\x0E\x00\x00\x00\x06\x00\x00\x00"
"\x32\x00\x04\x00\x16\x00\x00\x00\x3D\x00\x00\x00\x00\x01\x00\x00\x14\x00\x02\x00\x3E\x00\x00\x00\x34\x00\x06\x00\x3E\x00\x00\x00" "\x0E\x00\x00\x00\x06\x00\x00\x00\x07\x00\x00\x00\x12\x00\x00\x00\x12\x00\x00\x00\x20\x00\x04\x00\x49\x00\x00\x00\x02\x00\x00\x00"
"\x3F\x00\x00\x00\xAB\x00\x00\x00\x3D\x00\x00\x00\x17\x00\x00\x00\x20\x00\x04\x00\x42\x00\x00\x00\x03\x00\x00\x00\x07\x00\x00\x00" "\x48\x00\x00\x00\x3B\x00\x04\x00\x49\x00\x00\x00\x4A\x00\x00\x00\x02\x00\x00\x00\x3B\x00\x04\x00\x3A\x00\x00\x00\x4B\x00\x00\x00"
"\x3B\x00\x04\x00\x42\x00\x00\x00\x43\x00\x00\x00\x03\x00\x00\x00\x1E\x00\x03\x00\x44\x00\x00\x00\x07\x00\x00\x00\x20\x00\x04\x00" "\x01\x00\x00\x00\x3B\x00\x04\x00\x1B\x00\x00\x00\x4C\x00\x00\x00\x01\x00\x00\x00\x3B\x00\x04\x00\x1B\x00\x00\x00\x4D\x00\x00\x00"
"\x45\x00\x00\x00\x09\x00\x00\x00\x44\x00\x00\x00\x3B\x00\x04\x00\x45\x00\x00\x00\x46\x00\x00\x00\x09\x00\x00\x00\x20\x00\x04\x00" "\x01\x00\x00\x00\x3B\x00\x04\x00\x1B\x00\x00\x00\x4E\x00\x00\x00\x01\x00\x00\x00\x36\x00\x05\x00\x02\x00\x00\x00\x04\x00\x00\x00"
"\x47\x00\x00\x00\x09\x00\x00\x00\x07\x00\x00\x00\x20\x00\x04\x00\x4B\x00\x00\x00\x01\x00\x00\x00\x07\x00\x00\x00\x3B\x00\x04\x00" "\x00\x00\x00\x00\x03\x00\x00\x00\xF8\x00\x02\x00\x05\x00\x00\x00\x3D\x00\x04\x00\x12\x00\x00\x00\x3C\x00\x00\x00\x3B\x00\x00\x00"
"\x4B\x00\x00\x00\x4C\x00\x00\x00\x01\x00\x00\x00\x1E\x00\x03\x00\x4E\x00\x00\x00\x07\x00\x00\x00\x20\x00\x04\x00\x4F\x00\x00\x00" "\x3E\x00\x03\x00\x39\x00\x00\x00\x3C\x00\x00\x00\x3D\x00\x04\x00\x07\x00\x00\x00\x41\x00\x00\x00\x40\x00\x00\x00\x3E\x00\x03\x00"
"\x03\x00\x00\x00\x4E\x00\x00\x00\x3B\x00\x04\x00\x4F\x00\x00\x00\x50\x00\x00\x00\x03\x00\x00\x00\x32\x00\x04\x00\x16\x00\x00\x00" "\x3E\x00\x00\x00\x41\x00\x00\x00\x39\x00\x04\x00\x07\x00\x00\x00\x45\x00\x00\x00\x09\x00\x00\x00\x41\x00\x05\x00\x3D\x00\x00\x00"
"\x53\x00\x00\x00\x04\x00\x00\x00\x1E\x00\x0C\x00\x54\x00\x00\x00\x0D\x00\x00\x00\x0E\x00\x00\x00\x06\x00\x00\x00\x0E\x00\x00\x00" "\x46\x00\x00\x00\x44\x00\x00\x00\x17\x00\x00\x00\x3E\x00\x03\x00\x46\x00\x00\x00\x45\x00\x00\x00\xFD\x00\x01\x00\x38\x00\x01\x00"
"\x06\x00\x00\x00\x0E\x00\x00\x00\x06\x00\x00\x00\x07\x00\x00\x00\x12\x00\x00\x00\x12\x00\x00\x00\x20\x00\x04\x00\x55\x00\x00\x00" "\x36\x00\x05\x00\x07\x00\x00\x00\x09\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\xF8\x00\x02\x00\x0A\x00\x00\x00\x3B\x00\x04\x00"
"\x02\x00\x00\x00\x54\x00\x00\x00\x3B\x00\x04\x00\x55\x00\x00\x00\x56\x00\x00\x00\x02\x00\x00\x00\x3B\x00\x04\x00\x3A\x00\x00\x00" "\x0B\x00\x00\x00\x0C\x00\x00\x00\x07\x00\x00\x00\x41\x00\x05\x00\x18\x00\x00\x00\x19\x00\x00\x00\x15\x00\x00\x00\x17\x00\x00\x00"
"\x57\x00\x00\x00\x01\x00\x00\x00\x3B\x00\x04\x00\x1B\x00\x00\x00\x58\x00\x00\x00\x01\x00\x00\x00\x3B\x00\x04\x00\x1B\x00\x00\x00" "\x3D\x00\x04\x00\x0D\x00\x00\x00\x1A\x00\x00\x00\x19\x00\x00\x00\x3D\x00\x04\x00\x0E\x00\x00\x00\x1D\x00\x00\x00\x1C\x00\x00\x00"
"\x59\x00\x00\x00\x01\x00\x00\x00\x3B\x00\x04\x00\x1B\x00\x00\x00\x5A\x00\x00\x00\x01\x00\x00\x00\x36\x00\x05\x00\x02\x00\x00\x00" "\x51\x00\x05\x00\x06\x00\x00\x00\x1F\x00\x00\x00\x1D\x00\x00\x00\x00\x00\x00\x00\x51\x00\x05\x00\x06\x00\x00\x00\x20\x00\x00\x00"
"\x04\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\xF8\x00\x02\x00\x05\x00\x00\x00\x3D\x00\x04\x00\x12\x00\x00\x00\x3C\x00\x00\x00" "\x1D\x00\x00\x00\x01\x00\x00\x00\x51\x00\x05\x00\x06\x00\x00\x00\x21\x00\x00\x00\x1D\x00\x00\x00\x02\x00\x00\x00\x50\x00\x07\x00"
"\x3B\x00\x00\x00\x3E\x00\x03\x00\x39\x00\x00\x00\x3C\x00\x00\x00\xF7\x00\x03\x00\x41\x00\x00\x00\x00\x00\x00\x00\xFA\x00\x04\x00" "\x07\x00\x00\x00\x22\x00\x00\x00\x1F\x00\x00\x00\x20\x00\x00\x00\x21\x00\x00\x00\x1E\x00\x00\x00\x91\x00\x05\x00\x07\x00\x00\x00"
"\x3F\x00\x00\x00\x40\x00\x00\x00\x4A\x00\x00\x00\xF8\x00\x02\x00\x40\x00\x00\x00\x41\x00\x05\x00\x47\x00\x00\x00\x48\x00\x00\x00" "\x23\x00\x00\x00\x1A\x00\x00\x00\x22\x00\x00\x00\x3E\x00\x03\x00\x0C\x00\x00\x00\x23\x00\x00\x00\x41\x00\x05\x00\x26\x00\x00\x00"
"\x46\x00\x00\x00\x17\x00\x00\x00\x3D\x00\x04\x00\x07\x00\x00\x00\x49\x00\x00\x00\x48\x00\x00\x00\x3E\x00\x03\x00\x43\x00\x00\x00" "\x27\x00\x00\x00\x0C\x00\x00\x00\x25\x00\x00\x00\x3D\x00\x04\x00\x06\x00\x00\x00\x28\x00\x00\x00\x27\x00\x00\x00\x85\x00\x05\x00"
"\x49\x00\x00\x00\xF9\x00\x02\x00\x41\x00\x00\x00\xF8\x00\x02\x00\x4A\x00\x00\x00\x3D\x00\x04\x00\x07\x00\x00\x00\x4D\x00\x00\x00" "\x06\x00\x00\x00\x29\x00\x00\x00\x28\x00\x00\x00\x24\x00\x00\x00\x41\x00\x05\x00\x26\x00\x00\x00\x2A\x00\x00\x00\x0C\x00\x00\x00"
"\x4C\x00\x00\x00\x3E\x00\x03\x00\x43\x00\x00\x00\x4D\x00\x00\x00\xF9\x00\x02\x00\x41\x00\x00\x00\xF8\x00\x02\x00\x41\x00\x00\x00" "\x25\x00\x00\x00\x3E\x00\x03\x00\x2A\x00\x00\x00\x29\x00\x00\x00\x41\x00\x05\x00\x26\x00\x00\x00\x2C\x00\x00\x00\x0C\x00\x00\x00"
"\x39\x00\x04\x00\x07\x00\x00\x00\x51\x00\x00\x00\x09\x00\x00\x00\x41\x00\x05\x00\x42\x00\x00\x00\x52\x00\x00\x00\x50\x00\x00\x00" "\x2B\x00\x00\x00\x3D\x00\x04\x00\x06\x00\x00\x00\x2D\x00\x00\x00\x2C\x00\x00\x00\x41\x00\x05\x00\x26\x00\x00\x00\x2F\x00\x00\x00"
"\x17\x00\x00\x00\x3E\x00\x03\x00\x52\x00\x00\x00\x51\x00\x00\x00\xFD\x00\x01\x00\x38\x00\x01\x00\x36\x00\x05\x00\x07\x00\x00\x00" "\x0C\x00\x00\x00\x2E\x00\x00\x00\x3D\x00\x04\x00\x06\x00\x00\x00\x30\x00\x00\x00\x2F\x00\x00\x00\x81\x00\x05\x00\x06\x00\x00\x00"
"\x09\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\xF8\x00\x02\x00\x0A\x00\x00\x00\x3B\x00\x04\x00\x0B\x00\x00\x00\x0C\x00\x00\x00" "\x31\x00\x00\x00\x2D\x00\x00\x00\x30\x00\x00\x00\x88\x00\x05\x00\x06\x00\x00\x00\x33\x00\x00\x00\x31\x00\x00\x00\x32\x00\x00\x00"
"\x07\x00\x00\x00\x41\x00\x05\x00\x18\x00\x00\x00\x19\x00\x00\x00\x15\x00\x00\x00\x17\x00\x00\x00\x3D\x00\x04\x00\x0D\x00\x00\x00" "\x41\x00\x05\x00\x26\x00\x00\x00\x34\x00\x00\x00\x0C\x00\x00\x00\x2B\x00\x00\x00\x3E\x00\x03\x00\x34\x00\x00\x00\x33\x00\x00\x00"
"\x1A\x00\x00\x00\x19\x00\x00\x00\x3D\x00\x04\x00\x0E\x00\x00\x00\x1D\x00\x00\x00\x1C\x00\x00\x00\x51\x00\x05\x00\x06\x00\x00\x00" "\x3D\x00\x04\x00\x07\x00\x00\x00\x35\x00\x00\x00\x0C\x00\x00\x00\xFE\x00\x02\x00\x35\x00\x00\x00\x38\x00\x01\x00\x03\x02\x23\x07"
"\x1F\x00\x00\x00\x1D\x00\x00\x00\x00\x00\x00\x00\x51\x00\x05\x00\x06\x00\x00\x00\x20\x00\x00\x00\x1D\x00\x00\x00\x01\x00\x00\x00" "\x00\x00\x01\x00\x08\x00\x08\x00\x52\x00\x00\x00\x00\x00\x00\x00\x11\x00\x02\x00\x01\x00\x00\x00\x0B\x00\x06\x00\x01\x00\x00\x00"
"\x51\x00\x05\x00\x06\x00\x00\x00\x21\x00\x00\x00\x1D\x00\x00\x00\x02\x00\x00\x00\x50\x00\x07\x00\x07\x00\x00\x00\x22\x00\x00\x00" "\x47\x4C\x53\x4C\x2E\x73\x74\x64\x2E\x34\x35\x30\x00\x00\x00\x00\x0E\x00\x03\x00\x00\x00\x00\x00\x01\x00\x00\x00\x0F\x00\x08\x00"
"\x1F\x00\x00\x00\x20\x00\x00\x00\x21\x00\x00\x00\x1E\x00\x00\x00\x91\x00\x05\x00\x07\x00\x00\x00\x23\x00\x00\x00\x1A\x00\x00\x00" "\x04\x00\x00\x00\x04\x00\x00\x00\x6D\x61\x69\x6E\x00\x00\x00\x00\x11\x00\x00\x00\x15\x00\x00\x00\x46\x00\x00\x00\x10\x00\x03\x00"
"\x22\x00\x00\x00\x3E\x00\x03\x00\x0C\x00\x00\x00\x23\x00\x00\x00\x41\x00\x05\x00\x26\x00\x00\x00\x27\x00\x00\x00\x0C\x00\x00\x00" "\x04\x00\x00\x00\x07\x00\x00\x00\x03\x00\x03\x00\x02\x00\x00\x00\xC2\x01\x00\x00\x05\x00\x04\x00\x04\x00\x00\x00\x6D\x61\x69\x6E"
"\x25\x00\x00\x00\x3D\x00\x04\x00\x06\x00\x00\x00\x28\x00\x00\x00\x27\x00\x00\x00\x85\x00\x05\x00\x06\x00\x00\x00\x29\x00\x00\x00" "\x00\x00\x00\x00\x05\x00\x03\x00\x09\x00\x00\x00\x66\x63\x00\x00\x05\x00\x04\x00\x0D\x00\x00\x00\x73\x5F\x74\x30\x00\x00\x00\x00"
"\x28\x00\x00\x00\x24\x00\x00\x00\x41\x00\x05\x00\x26\x00\x00\x00\x2A\x00\x00\x00\x0C\x00\x00\x00\x25\x00\x00\x00\x3E\x00\x03\x00" "\x05\x00\x03\x00\x11\x00\x00\x00\x74\x63\x00\x00\x05\x00\x03\x00\x15\x00\x00\x00\x76\x63\x00\x00\x05\x00\x05\x00\x19\x00\x00\x00"
"\x2A\x00\x00\x00\x29\x00\x00\x00\x41\x00\x05\x00\x26\x00\x00\x00\x2C\x00\x00\x00\x0C\x00\x00\x00\x2B\x00\x00\x00\x3D\x00\x04\x00" "\x61\x6C\x70\x68\x61\x74\x65\x73\x74\x00\x00\x00\x05\x00\x05\x00\x46\x00\x00\x00\x6F\x75\x74\x63\x6F\x6C\x6F\x75\x72\x00\x00\x00"
"\x06\x00\x00\x00\x2D\x00\x00\x00\x2C\x00\x00\x00\x41\x00\x05\x00\x26\x00\x00\x00\x2F\x00\x00\x00\x0C\x00\x00\x00\x2E\x00\x00\x00" "\x05\x00\x05\x00\x4C\x00\x00\x00\x65\x6E\x74\x69\x74\x79\x62\x6C\x6F\x63\x6B\x00\x06\x00\x07\x00\x4C\x00\x00\x00\x00\x00\x00\x00"
"\x3D\x00\x04\x00\x06\x00\x00\x00\x30\x00\x00\x00\x2F\x00\x00\x00\x81\x00\x05\x00\x06\x00\x00\x00\x31\x00\x00\x00\x2D\x00\x00\x00" "\x6D\x5F\x6D\x6F\x64\x65\x6C\x76\x69\x65\x77\x70\x72\x6F\x6A\x00\x06\x00\x05\x00\x4C\x00\x00\x00\x01\x00\x00\x00\x6D\x5F\x6D\x6F"
"\x30\x00\x00\x00\x88\x00\x05\x00\x06\x00\x00\x00\x33\x00\x00\x00\x31\x00\x00\x00\x32\x00\x00\x00\x41\x00\x05\x00\x26\x00\x00\x00" "\x64\x65\x6C\x00\x06\x00\x06\x00\x4C\x00\x00\x00\x02\x00\x00\x00\x6D\x5F\x6D\x6F\x64\x65\x6C\x69\x6E\x76\x00\x00\x06\x00\x06\x00"
"\x34\x00\x00\x00\x0C\x00\x00\x00\x2B\x00\x00\x00\x3E\x00\x03\x00\x34\x00\x00\x00\x33\x00\x00\x00\x3D\x00\x04\x00\x07\x00\x00\x00" "\x4C\x00\x00\x00\x03\x00\x00\x00\x65\x5F\x65\x79\x65\x70\x6F\x73\x00\x00\x00\x00\x06\x00\x05\x00\x4C\x00\x00\x00\x04\x00\x00\x00"
"\x35\x00\x00\x00\x0C\x00\x00\x00\xFE\x00\x02\x00\x35\x00\x00\x00\x38\x00\x01\x00\x03\x02\x23\x07\x00\x00\x01\x00\x08\x00\x08\x00" "\x65\x5F\x74\x69\x6D\x65\x00\x00\x06\x00\x07\x00\x4C\x00\x00\x00\x05\x00\x00\x00\x65\x5F\x6C\x69\x67\x68\x74\x5F\x61\x6D\x62\x69"
"\x56\x00\x00\x00\x00\x00\x00\x00\x11\x00\x02\x00\x01\x00\x00\x00\x0B\x00\x06\x00\x01\x00\x00\x00\x47\x4C\x53\x4C\x2E\x73\x74\x64" "\x65\x6E\x74\x00\x06\x00\x05\x00\x4C\x00\x00\x00\x06\x00\x00\x00\x65\x70\x61\x64\x31\x00\x00\x00\x06\x00\x06\x00\x4C\x00\x00\x00"
"\x2E\x34\x35\x30\x00\x00\x00\x00\x0E\x00\x03\x00\x00\x00\x00\x00\x01\x00\x00\x00\x0F\x00\x08\x00\x04\x00\x00\x00\x04\x00\x00\x00" "\x07\x00\x00\x00\x65\x5F\x6C\x69\x67\x68\x74\x5F\x64\x69\x72\x00\x06\x00\x05\x00\x4C\x00\x00\x00\x08\x00\x00\x00\x65\x70\x61\x64"
"\x6D\x61\x69\x6E\x00\x00\x00\x00\x11\x00\x00\x00\x15\x00\x00\x00\x46\x00\x00\x00\x10\x00\x03\x00\x04\x00\x00\x00\x07\x00\x00\x00" "\x32\x00\x00\x00\x06\x00\x06\x00\x4C\x00\x00\x00\x09\x00\x00\x00\x65\x5F\x6C\x69\x67\x68\x74\x5F\x6D\x75\x6C\x00\x06\x00\x05\x00"
"\x03\x00\x03\x00\x02\x00\x00\x00\xC2\x01\x00\x00\x05\x00\x04\x00\x04\x00\x00\x00\x6D\x61\x69\x6E\x00\x00\x00\x00\x05\x00\x03\x00" "\x4C\x00\x00\x00\x0A\x00\x00\x00\x65\x70\x61\x64\x33\x00\x00\x00\x06\x00\x06\x00\x4C\x00\x00\x00\x0B\x00\x00\x00\x65\x5F\x6C\x6D"
"\x09\x00\x00\x00\x66\x63\x00\x00\x05\x00\x04\x00\x0D\x00\x00\x00\x73\x5F\x74\x30\x00\x00\x00\x00\x05\x00\x03\x00\x11\x00\x00\x00" "\x73\x63\x61\x6C\x65\x73\x00\x00\x06\x00\x07\x00\x4C\x00\x00\x00\x0C\x00\x00\x00\x65\x5F\x75\x70\x70\x65\x72\x63\x6F\x6C\x6F\x75"
"\x74\x63\x00\x00\x05\x00\x03\x00\x15\x00\x00\x00\x76\x63\x00\x00\x05\x00\x05\x00\x19\x00\x00\x00\x61\x6C\x70\x68\x61\x74\x65\x73" "\x72\x00\x00\x00\x06\x00\x05\x00\x4C\x00\x00\x00\x0D\x00\x00\x00\x65\x70\x61\x64\x34\x00\x00\x00\x06\x00\x07\x00\x4C\x00\x00\x00"
"\x74\x00\x00\x00\x05\x00\x05\x00\x46\x00\x00\x00\x6F\x75\x74\x63\x6F\x6C\x6F\x75\x72\x00\x00\x00\x05\x00\x07\x00\x48\x00\x00\x00" "\x0E\x00\x00\x00\x65\x5F\x6C\x6F\x77\x65\x72\x63\x6F\x6C\x6F\x75\x72\x00\x00\x00\x06\x00\x05\x00\x4C\x00\x00\x00\x0F\x00\x00\x00"
"\x5F\x61\x72\x67\x5F\x63\x6F\x6E\x73\x74\x63\x6F\x6C\x6F\x75\x72\x00\x00\x00\x00\x05\x00\x05\x00\x49\x00\x00\x00\x70\x75\x73\x68" "\x65\x70\x61\x64\x35\x00\x00\x00\x06\x00\x06\x00\x4C\x00\x00\x00\x10\x00\x00\x00\x65\x5F\x67\x6C\x6F\x77\x6D\x6F\x64\x00\x00\x00"
"\x69\x6E\x74\x66\x00\x00\x00\x00\x06\x00\x05\x00\x49\x00\x00\x00\x00\x00\x00\x00\x63\x6F\x6C\x6F\x75\x72\x00\x00\x05\x00\x04\x00" "\x06\x00\x05\x00\x4C\x00\x00\x00\x11\x00\x00\x00\x65\x70\x61\x64\x36\x00\x00\x00\x06\x00\x07\x00\x4C\x00\x00\x00\x12\x00\x00\x00"
"\x4B\x00\x00\x00\x70\x75\x73\x68\x00\x00\x00\x00\x05\x00\x05\x00\x50\x00\x00\x00\x65\x6E\x74\x69\x74\x79\x62\x6C\x6F\x63\x6B\x00" "\x65\x5F\x63\x6F\x6C\x6F\x75\x72\x69\x64\x65\x6E\x74\x00\x00\x00\x06\x00\x07\x00\x4C\x00\x00\x00\x13\x00\x00\x00\x77\x5F\x66\x6F"
"\x06\x00\x07\x00\x50\x00\x00\x00\x00\x00\x00\x00\x6D\x5F\x6D\x6F\x64\x65\x6C\x76\x69\x65\x77\x70\x72\x6F\x6A\x00\x06\x00\x05\x00" "\x67\x63\x6F\x6C\x6F\x75\x72\x73\x00\x00\x00\x00\x06\x00\x07\x00\x4C\x00\x00\x00\x14\x00\x00\x00\x77\x5F\x66\x6F\x67\x64\x65\x6E"
"\x50\x00\x00\x00\x01\x00\x00\x00\x6D\x5F\x6D\x6F\x64\x65\x6C\x00\x06\x00\x06\x00\x50\x00\x00\x00\x02\x00\x00\x00\x6D\x5F\x6D\x6F" "\x73\x69\x74\x79\x00\x00\x00\x00\x06\x00\x07\x00\x4C\x00\x00\x00\x15\x00\x00\x00\x77\x5F\x66\x6F\x67\x64\x65\x70\x74\x68\x62\x69"
"\x64\x65\x6C\x69\x6E\x76\x00\x00\x06\x00\x06\x00\x50\x00\x00\x00\x03\x00\x00\x00\x65\x5F\x65\x79\x65\x70\x6F\x73\x00\x00\x00\x00" "\x61\x73\x00\x00\x06\x00\x05\x00\x4C\x00\x00\x00\x16\x00\x00\x00\x65\x70\x61\x64\x37\x00\x00\x00\x05\x00\x03\x00\x4E\x00\x00\x00"
"\x06\x00\x05\x00\x50\x00\x00\x00\x04\x00\x00\x00\x65\x5F\x74\x69\x6D\x65\x00\x00\x06\x00\x07\x00\x50\x00\x00\x00\x05\x00\x00\x00" "\x00\x00\x00\x00\x05\x00\x05\x00\x4F\x00\x00\x00\x6C\x69\x67\x68\x74\x62\x6C\x6F\x63\x6B\x00\x00\x06\x00\x07\x00\x4F\x00\x00\x00"
"\x65\x5F\x6C\x69\x67\x68\x74\x5F\x61\x6D\x62\x69\x65\x6E\x74\x00\x06\x00\x05\x00\x50\x00\x00\x00\x06\x00\x00\x00\x65\x70\x61\x64" "\x00\x00\x00\x00\x6C\x5F\x63\x75\x62\x65\x6D\x61\x74\x72\x69\x78\x00\x00\x00\x00\x06\x00\x07\x00\x4F\x00\x00\x00\x01\x00\x00\x00"
"\x31\x00\x00\x00\x06\x00\x06\x00\x50\x00\x00\x00\x07\x00\x00\x00\x65\x5F\x6C\x69\x67\x68\x74\x5F\x64\x69\x72\x00\x06\x00\x05\x00" "\x6C\x5F\x6C\x69\x67\x68\x74\x70\x6F\x73\x69\x74\x69\x6F\x6E\x00\x06\x00\x05\x00\x4F\x00\x00\x00\x02\x00\x00\x00\x6C\x70\x61\x64"
"\x50\x00\x00\x00\x08\x00\x00\x00\x65\x70\x61\x64\x32\x00\x00\x00\x06\x00\x06\x00\x50\x00\x00\x00\x09\x00\x00\x00\x65\x5F\x6C\x69" "\x31\x00\x00\x00\x06\x00\x07\x00\x4F\x00\x00\x00\x03\x00\x00\x00\x6C\x5F\x6C\x69\x67\x68\x74\x63\x6F\x6C\x6F\x75\x72\x00\x00\x00"
"\x67\x68\x74\x5F\x6D\x75\x6C\x00\x06\x00\x05\x00\x50\x00\x00\x00\x0A\x00\x00\x00\x65\x70\x61\x64\x33\x00\x00\x00\x06\x00\x06\x00" "\x06\x00\x05\x00\x4F\x00\x00\x00\x04\x00\x00\x00\x6C\x70\x61\x64\x32\x00\x00\x00\x06\x00\x08\x00\x4F\x00\x00\x00\x05\x00\x00\x00"
"\x50\x00\x00\x00\x0B\x00\x00\x00\x65\x5F\x6C\x6D\x73\x63\x61\x6C\x65\x73\x00\x00\x06\x00\x07\x00\x50\x00\x00\x00\x0C\x00\x00\x00" "\x6C\x5F\x6C\x69\x67\x68\x74\x63\x6F\x6C\x6F\x75\x72\x73\x63\x61\x6C\x65\x00\x00\x06\x00\x07\x00\x4F\x00\x00\x00\x06\x00\x00\x00"
"\x65\x5F\x75\x70\x70\x65\x72\x63\x6F\x6C\x6F\x75\x72\x00\x00\x00\x06\x00\x05\x00\x50\x00\x00\x00\x0D\x00\x00\x00\x65\x70\x61\x64" "\x6C\x5F\x6C\x69\x67\x68\x74\x72\x61\x64\x69\x75\x73\x00\x00\x00\x06\x00\x07\x00\x4F\x00\x00\x00\x07\x00\x00\x00\x6C\x5F\x73\x68"
"\x34\x00\x00\x00\x06\x00\x07\x00\x50\x00\x00\x00\x0E\x00\x00\x00\x65\x5F\x6C\x6F\x77\x65\x72\x63\x6F\x6C\x6F\x75\x72\x00\x00\x00" "\x61\x64\x6F\x77\x6D\x61\x70\x70\x72\x6F\x6A\x00\x06\x00\x08\x00\x4F\x00\x00\x00\x08\x00\x00\x00\x6C\x5F\x73\x68\x61\x64\x6F\x77"
"\x06\x00\x05\x00\x50\x00\x00\x00\x0F\x00\x00\x00\x65\x70\x61\x64\x35\x00\x00\x00\x06\x00\x06\x00\x50\x00\x00\x00\x10\x00\x00\x00" "\x6D\x61\x70\x73\x63\x61\x6C\x65\x00\x00\x00\x00\x06\x00\x05\x00\x4F\x00\x00\x00\x09\x00\x00\x00\x6C\x70\x61\x64\x33\x00\x00\x00"
"\x65\x5F\x67\x6C\x6F\x77\x6D\x6F\x64\x00\x00\x00\x06\x00\x05\x00\x50\x00\x00\x00\x11\x00\x00\x00\x65\x70\x61\x64\x36\x00\x00\x00" "\x05\x00\x03\x00\x51\x00\x00\x00\x00\x00\x00\x00\x47\x00\x04\x00\x0D\x00\x00\x00\x22\x00\x00\x00\x00\x00\x00\x00\x47\x00\x04\x00"
"\x06\x00\x07\x00\x50\x00\x00\x00\x12\x00\x00\x00\x65\x5F\x63\x6F\x6C\x6F\x75\x72\x69\x64\x65\x6E\x74\x00\x00\x00\x06\x00\x07\x00" "\x0D\x00\x00\x00\x21\x00\x00\x00\x02\x00\x00\x00\x47\x00\x04\x00\x11\x00\x00\x00\x1E\x00\x00\x00\x00\x00\x00\x00\x47\x00\x04\x00"
"\x50\x00\x00\x00\x13\x00\x00\x00\x77\x5F\x66\x6F\x67\x63\x6F\x6C\x6F\x75\x72\x73\x00\x00\x00\x00\x06\x00\x07\x00\x50\x00\x00\x00" "\x15\x00\x00\x00\x1E\x00\x00\x00\x01\x00\x00\x00\x47\x00\x04\x00\x19\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x47\x00\x04\x00"
"\x14\x00\x00\x00\x77\x5F\x66\x6F\x67\x64\x65\x6E\x73\x69\x74\x79\x00\x00\x00\x00\x06\x00\x07\x00\x50\x00\x00\x00\x15\x00\x00\x00" "\x46\x00\x00\x00\x1E\x00\x00\x00\x00\x00\x00\x00\x47\x00\x04\x00\x4B\x00\x00\x00\x06\x00\x00\x00\x10\x00\x00\x00\x48\x00\x04\x00"
"\x77\x5F\x66\x6F\x67\x64\x65\x70\x74\x68\x62\x69\x61\x73\x00\x00\x06\x00\x05\x00\x50\x00\x00\x00\x16\x00\x00\x00\x65\x70\x61\x64" "\x4C\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00\x48\x00\x05\x00\x4C\x00\x00\x00\x00\x00\x00\x00\x23\x00\x00\x00\x00\x00\x00\x00"
"\x37\x00\x00\x00\x05\x00\x03\x00\x52\x00\x00\x00\x00\x00\x00\x00\x05\x00\x05\x00\x53\x00\x00\x00\x6C\x69\x67\x68\x74\x62\x6C\x6F" "\x48\x00\x05\x00\x4C\x00\x00\x00\x00\x00\x00\x00\x07\x00\x00\x00\x10\x00\x00\x00\x48\x00\x04\x00\x4C\x00\x00\x00\x01\x00\x00\x00"
"\x63\x6B\x00\x00\x06\x00\x07\x00\x53\x00\x00\x00\x00\x00\x00\x00\x6C\x5F\x63\x75\x62\x65\x6D\x61\x74\x72\x69\x78\x00\x00\x00\x00" "\x05\x00\x00\x00\x48\x00\x05\x00\x4C\x00\x00\x00\x01\x00\x00\x00\x23\x00\x00\x00\x40\x00\x00\x00\x48\x00\x05\x00\x4C\x00\x00\x00"
"\x06\x00\x07\x00\x53\x00\x00\x00\x01\x00\x00\x00\x6C\x5F\x6C\x69\x67\x68\x74\x70\x6F\x73\x69\x74\x69\x6F\x6E\x00\x06\x00\x05\x00" "\x01\x00\x00\x00\x07\x00\x00\x00\x10\x00\x00\x00\x48\x00\x04\x00\x4C\x00\x00\x00\x02\x00\x00\x00\x05\x00\x00\x00\x48\x00\x05\x00"
"\x53\x00\x00\x00\x02\x00\x00\x00\x6C\x70\x61\x64\x31\x00\x00\x00\x06\x00\x07\x00\x53\x00\x00\x00\x03\x00\x00\x00\x6C\x5F\x6C\x69" "\x4C\x00\x00\x00\x02\x00\x00\x00\x23\x00\x00\x00\x80\x00\x00\x00\x48\x00\x05\x00\x4C\x00\x00\x00\x02\x00\x00\x00\x07\x00\x00\x00"
"\x67\x68\x74\x63\x6F\x6C\x6F\x75\x72\x00\x00\x00\x06\x00\x05\x00\x53\x00\x00\x00\x04\x00\x00\x00\x6C\x70\x61\x64\x32\x00\x00\x00" "\x10\x00\x00\x00\x48\x00\x05\x00\x4C\x00\x00\x00\x03\x00\x00\x00\x23\x00\x00\x00\xC0\x00\x00\x00\x48\x00\x05\x00\x4C\x00\x00\x00"
"\x06\x00\x08\x00\x53\x00\x00\x00\x05\x00\x00\x00\x6C\x5F\x6C\x69\x67\x68\x74\x63\x6F\x6C\x6F\x75\x72\x73\x63\x61\x6C\x65\x00\x00" "\x04\x00\x00\x00\x23\x00\x00\x00\xCC\x00\x00\x00\x48\x00\x05\x00\x4C\x00\x00\x00\x05\x00\x00\x00\x23\x00\x00\x00\xD0\x00\x00\x00"
"\x06\x00\x07\x00\x53\x00\x00\x00\x06\x00\x00\x00\x6C\x5F\x6C\x69\x67\x68\x74\x72\x61\x64\x69\x75\x73\x00\x00\x00\x06\x00\x07\x00" "\x48\x00\x05\x00\x4C\x00\x00\x00\x06\x00\x00\x00\x23\x00\x00\x00\xDC\x00\x00\x00\x48\x00\x05\x00\x4C\x00\x00\x00\x07\x00\x00\x00"
"\x53\x00\x00\x00\x07\x00\x00\x00\x6C\x5F\x73\x68\x61\x64\x6F\x77\x6D\x61\x70\x70\x72\x6F\x6A\x00\x06\x00\x08\x00\x53\x00\x00\x00" "\x23\x00\x00\x00\xE0\x00\x00\x00\x48\x00\x05\x00\x4C\x00\x00\x00\x08\x00\x00\x00\x23\x00\x00\x00\xEC\x00\x00\x00\x48\x00\x05\x00"
"\x08\x00\x00\x00\x6C\x5F\x73\x68\x61\x64\x6F\x77\x6D\x61\x70\x73\x63\x61\x6C\x65\x00\x00\x00\x00\x06\x00\x05\x00\x53\x00\x00\x00" "\x4C\x00\x00\x00\x09\x00\x00\x00\x23\x00\x00\x00\xF0\x00\x00\x00\x48\x00\x05\x00\x4C\x00\x00\x00\x0A\x00\x00\x00\x23\x00\x00\x00"
"\x09\x00\x00\x00\x6C\x70\x61\x64\x33\x00\x00\x00\x05\x00\x03\x00\x55\x00\x00\x00\x00\x00\x00\x00\x47\x00\x04\x00\x0D\x00\x00\x00" "\xFC\x00\x00\x00\x48\x00\x05\x00\x4C\x00\x00\x00\x0B\x00\x00\x00\x23\x00\x00\x00\x00\x01\x00\x00\x48\x00\x05\x00\x4C\x00\x00\x00"
"\x22\x00\x00\x00\x00\x00\x00\x00\x47\x00\x04\x00\x0D\x00\x00\x00\x21\x00\x00\x00\x02\x00\x00\x00\x47\x00\x04\x00\x11\x00\x00\x00" "\x0C\x00\x00\x00\x23\x00\x00\x00\x40\x01\x00\x00\x48\x00\x05\x00\x4C\x00\x00\x00\x0D\x00\x00\x00\x23\x00\x00\x00\x4C\x01\x00\x00"
"\x1E\x00\x00\x00\x00\x00\x00\x00\x47\x00\x04\x00\x15\x00\x00\x00\x1E\x00\x00\x00\x01\x00\x00\x00\x47\x00\x04\x00\x19\x00\x00\x00" "\x48\x00\x05\x00\x4C\x00\x00\x00\x0E\x00\x00\x00\x23\x00\x00\x00\x50\x01\x00\x00\x48\x00\x05\x00\x4C\x00\x00\x00\x0F\x00\x00\x00"
"\x01\x00\x00\x00\x00\x00\x00\x00\x47\x00\x04\x00\x46\x00\x00\x00\x1E\x00\x00\x00\x00\x00\x00\x00\x47\x00\x04\x00\x48\x00\x00\x00" "\x23\x00\x00\x00\x5C\x01\x00\x00\x48\x00\x05\x00\x4C\x00\x00\x00\x10\x00\x00\x00\x23\x00\x00\x00\x60\x01\x00\x00\x48\x00\x05\x00"
"\x01\x00\x00\x00\x00\x01\x00\x00\x48\x00\x05\x00\x49\x00\x00\x00\x00\x00\x00\x00\x23\x00\x00\x00\x00\x00\x00\x00\x47\x00\x03\x00" "\x4C\x00\x00\x00\x11\x00\x00\x00\x23\x00\x00\x00\x6C\x01\x00\x00\x48\x00\x05\x00\x4C\x00\x00\x00\x12\x00\x00\x00\x23\x00\x00\x00"
"\x49\x00\x00\x00\x02\x00\x00\x00\x47\x00\x04\x00\x4F\x00\x00\x00\x06\x00\x00\x00\x10\x00\x00\x00\x48\x00\x04\x00\x50\x00\x00\x00" "\x70\x01\x00\x00\x48\x00\x05\x00\x4C\x00\x00\x00\x13\x00\x00\x00\x23\x00\x00\x00\x80\x01\x00\x00\x48\x00\x05\x00\x4C\x00\x00\x00"
"\x00\x00\x00\x00\x05\x00\x00\x00\x48\x00\x05\x00\x50\x00\x00\x00\x00\x00\x00\x00\x23\x00\x00\x00\x00\x00\x00\x00\x48\x00\x05\x00" "\x14\x00\x00\x00\x23\x00\x00\x00\x90\x01\x00\x00\x48\x00\x05\x00\x4C\x00\x00\x00\x15\x00\x00\x00\x23\x00\x00\x00\x94\x01\x00\x00"
"\x50\x00\x00\x00\x00\x00\x00\x00\x07\x00\x00\x00\x10\x00\x00\x00\x48\x00\x04\x00\x50\x00\x00\x00\x01\x00\x00\x00\x05\x00\x00\x00" "\x48\x00\x05\x00\x4C\x00\x00\x00\x16\x00\x00\x00\x23\x00\x00\x00\x98\x01\x00\x00\x47\x00\x03\x00\x4C\x00\x00\x00\x02\x00\x00\x00"
"\x48\x00\x05\x00\x50\x00\x00\x00\x01\x00\x00\x00\x23\x00\x00\x00\x40\x00\x00\x00\x48\x00\x05\x00\x50\x00\x00\x00\x01\x00\x00\x00" "\x47\x00\x04\x00\x4E\x00\x00\x00\x22\x00\x00\x00\x00\x00\x00\x00\x47\x00\x04\x00\x4E\x00\x00\x00\x21\x00\x00\x00\x00\x00\x00\x00"
"\x07\x00\x00\x00\x10\x00\x00\x00\x48\x00\x04\x00\x50\x00\x00\x00\x02\x00\x00\x00\x05\x00\x00\x00\x48\x00\x05\x00\x50\x00\x00\x00" "\x48\x00\x04\x00\x4F\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00\x48\x00\x05\x00\x4F\x00\x00\x00\x00\x00\x00\x00\x23\x00\x00\x00"
"\x02\x00\x00\x00\x23\x00\x00\x00\x80\x00\x00\x00\x48\x00\x05\x00\x50\x00\x00\x00\x02\x00\x00\x00\x07\x00\x00\x00\x10\x00\x00\x00" "\x00\x00\x00\x00\x48\x00\x05\x00\x4F\x00\x00\x00\x00\x00\x00\x00\x07\x00\x00\x00\x10\x00\x00\x00\x48\x00\x05\x00\x4F\x00\x00\x00"
"\x48\x00\x05\x00\x50\x00\x00\x00\x03\x00\x00\x00\x23\x00\x00\x00\xC0\x00\x00\x00\x48\x00\x05\x00\x50\x00\x00\x00\x04\x00\x00\x00" "\x01\x00\x00\x00\x23\x00\x00\x00\x40\x00\x00\x00\x48\x00\x05\x00\x4F\x00\x00\x00\x02\x00\x00\x00\x23\x00\x00\x00\x4C\x00\x00\x00"
"\x23\x00\x00\x00\xCC\x00\x00\x00\x48\x00\x05\x00\x50\x00\x00\x00\x05\x00\x00\x00\x23\x00\x00\x00\xD0\x00\x00\x00\x48\x00\x05\x00" "\x48\x00\x05\x00\x4F\x00\x00\x00\x03\x00\x00\x00\x23\x00\x00\x00\x50\x00\x00\x00\x48\x00\x05\x00\x4F\x00\x00\x00\x04\x00\x00\x00"
"\x50\x00\x00\x00\x06\x00\x00\x00\x23\x00\x00\x00\xDC\x00\x00\x00\x48\x00\x05\x00\x50\x00\x00\x00\x07\x00\x00\x00\x23\x00\x00\x00" "\x23\x00\x00\x00\x5C\x00\x00\x00\x48\x00\x05\x00\x4F\x00\x00\x00\x05\x00\x00\x00\x23\x00\x00\x00\x60\x00\x00\x00\x48\x00\x05\x00"
"\xE0\x00\x00\x00\x48\x00\x05\x00\x50\x00\x00\x00\x08\x00\x00\x00\x23\x00\x00\x00\xEC\x00\x00\x00\x48\x00\x05\x00\x50\x00\x00\x00" "\x4F\x00\x00\x00\x06\x00\x00\x00\x23\x00\x00\x00\x6C\x00\x00\x00\x48\x00\x05\x00\x4F\x00\x00\x00\x07\x00\x00\x00\x23\x00\x00\x00"
"\x09\x00\x00\x00\x23\x00\x00\x00\xF0\x00\x00\x00\x48\x00\x05\x00\x50\x00\x00\x00\x0A\x00\x00\x00\x23\x00\x00\x00\xFC\x00\x00\x00" "\x70\x00\x00\x00\x48\x00\x05\x00\x4F\x00\x00\x00\x08\x00\x00\x00\x23\x00\x00\x00\x80\x00\x00\x00\x48\x00\x05\x00\x4F\x00\x00\x00"
"\x48\x00\x05\x00\x50\x00\x00\x00\x0B\x00\x00\x00\x23\x00\x00\x00\x00\x01\x00\x00\x48\x00\x05\x00\x50\x00\x00\x00\x0C\x00\x00\x00" "\x09\x00\x00\x00\x23\x00\x00\x00\x88\x00\x00\x00\x47\x00\x03\x00\x4F\x00\x00\x00\x02\x00\x00\x00\x47\x00\x04\x00\x51\x00\x00\x00"
"\x23\x00\x00\x00\x40\x01\x00\x00\x48\x00\x05\x00\x50\x00\x00\x00\x0D\x00\x00\x00\x23\x00\x00\x00\x4C\x01\x00\x00\x48\x00\x05\x00" "\x22\x00\x00\x00\x00\x00\x00\x00\x47\x00\x04\x00\x51\x00\x00\x00\x21\x00\x00\x00\x01\x00\x00\x00\x13\x00\x02\x00\x02\x00\x00\x00"
"\x50\x00\x00\x00\x0E\x00\x00\x00\x23\x00\x00\x00\x50\x01\x00\x00\x48\x00\x05\x00\x50\x00\x00\x00\x0F\x00\x00\x00\x23\x00\x00\x00" "\x21\x00\x03\x00\x03\x00\x00\x00\x02\x00\x00\x00\x16\x00\x03\x00\x06\x00\x00\x00\x20\x00\x00\x00\x17\x00\x04\x00\x07\x00\x00\x00"
"\x5C\x01\x00\x00\x48\x00\x05\x00\x50\x00\x00\x00\x10\x00\x00\x00\x23\x00\x00\x00\x60\x01\x00\x00\x48\x00\x05\x00\x50\x00\x00\x00" "\x06\x00\x00\x00\x04\x00\x00\x00\x20\x00\x04\x00\x08\x00\x00\x00\x07\x00\x00\x00\x07\x00\x00\x00\x19\x00\x09\x00\x0A\x00\x00\x00"
"\x11\x00\x00\x00\x23\x00\x00\x00\x6C\x01\x00\x00\x48\x00\x05\x00\x50\x00\x00\x00\x12\x00\x00\x00\x23\x00\x00\x00\x70\x01\x00\x00" "\x06\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x1B\x00\x03\x00"
"\x48\x00\x05\x00\x50\x00\x00\x00\x13\x00\x00\x00\x23\x00\x00\x00\x80\x01\x00\x00\x48\x00\x05\x00\x50\x00\x00\x00\x14\x00\x00\x00" "\x0B\x00\x00\x00\x0A\x00\x00\x00\x20\x00\x04\x00\x0C\x00\x00\x00\x00\x00\x00\x00\x0B\x00\x00\x00\x3B\x00\x04\x00\x0C\x00\x00\x00"
"\x23\x00\x00\x00\x90\x01\x00\x00\x48\x00\x05\x00\x50\x00\x00\x00\x15\x00\x00\x00\x23\x00\x00\x00\x94\x01\x00\x00\x48\x00\x05\x00" "\x0D\x00\x00\x00\x00\x00\x00\x00\x17\x00\x04\x00\x0F\x00\x00\x00\x06\x00\x00\x00\x02\x00\x00\x00\x20\x00\x04\x00\x10\x00\x00\x00"
"\x50\x00\x00\x00\x16\x00\x00\x00\x23\x00\x00\x00\x98\x01\x00\x00\x47\x00\x03\x00\x50\x00\x00\x00\x02\x00\x00\x00\x47\x00\x04\x00" "\x01\x00\x00\x00\x0F\x00\x00\x00\x3B\x00\x04\x00\x10\x00\x00\x00\x11\x00\x00\x00\x01\x00\x00\x00\x20\x00\x04\x00\x14\x00\x00\x00"
"\x52\x00\x00\x00\x22\x00\x00\x00\x00\x00\x00\x00\x47\x00\x04\x00\x52\x00\x00\x00\x21\x00\x00\x00\x00\x00\x00\x00\x48\x00\x04\x00" "\x01\x00\x00\x00\x07\x00\x00\x00\x3B\x00\x04\x00\x14\x00\x00\x00\x15\x00\x00\x00\x01\x00\x00\x00\x15\x00\x04\x00\x18\x00\x00\x00"
"\x53\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00\x48\x00\x05\x00\x53\x00\x00\x00\x00\x00\x00\x00\x23\x00\x00\x00\x00\x00\x00\x00" "\x20\x00\x00\x00\x01\x00\x00\x00\x32\x00\x04\x00\x18\x00\x00\x00\x19\x00\x00\x00\x04\x00\x00\x00\x2B\x00\x04\x00\x18\x00\x00\x00"
"\x48\x00\x05\x00\x53\x00\x00\x00\x00\x00\x00\x00\x07\x00\x00\x00\x10\x00\x00\x00\x48\x00\x05\x00\x53\x00\x00\x00\x01\x00\x00\x00" "\x1A\x00\x00\x00\x04\x00\x00\x00\x14\x00\x02\x00\x1B\x00\x00\x00\x34\x00\x06\x00\x1B\x00\x00\x00\x1C\x00\x00\x00\xAA\x00\x00\x00"
"\x23\x00\x00\x00\x40\x00\x00\x00\x48\x00\x05\x00\x53\x00\x00\x00\x02\x00\x00\x00\x23\x00\x00\x00\x4C\x00\x00\x00\x48\x00\x05\x00" "\x19\x00\x00\x00\x1A\x00\x00\x00\x2B\x00\x04\x00\x18\x00\x00\x00\x20\x00\x00\x00\x03\x00\x00\x00\x34\x00\x06\x00\x1B\x00\x00\x00"
"\x53\x00\x00\x00\x03\x00\x00\x00\x23\x00\x00\x00\x50\x00\x00\x00\x48\x00\x05\x00\x53\x00\x00\x00\x04\x00\x00\x00\x23\x00\x00\x00" "\x21\x00\x00\x00\xAA\x00\x00\x00\x19\x00\x00\x00\x20\x00\x00\x00\x15\x00\x04\x00\x24\x00\x00\x00\x20\x00\x00\x00\x00\x00\x00\x00"
"\x5C\x00\x00\x00\x48\x00\x05\x00\x53\x00\x00\x00\x05\x00\x00\x00\x23\x00\x00\x00\x60\x00\x00\x00\x48\x00\x05\x00\x53\x00\x00\x00" "\x2B\x00\x04\x00\x24\x00\x00\x00\x25\x00\x00\x00\x03\x00\x00\x00\x20\x00\x04\x00\x26\x00\x00\x00\x07\x00\x00\x00\x06\x00\x00\x00"
"\x06\x00\x00\x00\x23\x00\x00\x00\x6C\x00\x00\x00\x48\x00\x05\x00\x53\x00\x00\x00\x07\x00\x00\x00\x23\x00\x00\x00\x70\x00\x00\x00" "\x2B\x00\x04\x00\x06\x00\x00\x00\x29\x00\x00\x00\x00\x00\x00\x3F\x2B\x00\x04\x00\x18\x00\x00\x00\x2F\x00\x00\x00\x02\x00\x00\x00"
"\x48\x00\x05\x00\x53\x00\x00\x00\x08\x00\x00\x00\x23\x00\x00\x00\x80\x00\x00\x00\x48\x00\x05\x00\x53\x00\x00\x00\x09\x00\x00\x00" "\x34\x00\x06\x00\x1B\x00\x00\x00\x30\x00\x00\x00\xAA\x00\x00\x00\x19\x00\x00\x00\x2F\x00\x00\x00\x2B\x00\x04\x00\x06\x00\x00\x00"
"\x23\x00\x00\x00\x88\x00\x00\x00\x47\x00\x03\x00\x53\x00\x00\x00\x02\x00\x00\x00\x47\x00\x04\x00\x55\x00\x00\x00\x22\x00\x00\x00" "\x35\x00\x00\x00\x00\x00\x00\x00\x2B\x00\x04\x00\x18\x00\x00\x00\x3B\x00\x00\x00\x01\x00\x00\x00\x34\x00\x06\x00\x1B\x00\x00\x00"
"\x00\x00\x00\x00\x47\x00\x04\x00\x55\x00\x00\x00\x21\x00\x00\x00\x01\x00\x00\x00\x13\x00\x02\x00\x02\x00\x00\x00\x21\x00\x03\x00" "\x3C\x00\x00\x00\xAA\x00\x00\x00\x19\x00\x00\x00\x3B\x00\x00\x00\x20\x00\x04\x00\x45\x00\x00\x00\x03\x00\x00\x00\x07\x00\x00\x00"
"\x03\x00\x00\x00\x02\x00\x00\x00\x16\x00\x03\x00\x06\x00\x00\x00\x20\x00\x00\x00\x17\x00\x04\x00\x07\x00\x00\x00\x06\x00\x00\x00" "\x3B\x00\x04\x00\x45\x00\x00\x00\x46\x00\x00\x00\x03\x00\x00\x00\x18\x00\x04\x00\x48\x00\x00\x00\x07\x00\x00\x00\x04\x00\x00\x00"
"\x04\x00\x00\x00\x20\x00\x04\x00\x08\x00\x00\x00\x07\x00\x00\x00\x07\x00\x00\x00\x19\x00\x09\x00\x0A\x00\x00\x00\x06\x00\x00\x00" "\x17\x00\x04\x00\x49\x00\x00\x00\x06\x00\x00\x00\x03\x00\x00\x00\x2B\x00\x04\x00\x24\x00\x00\x00\x4A\x00\x00\x00\x04\x00\x00\x00"
"\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x1B\x00\x03\x00\x0B\x00\x00\x00" "\x1C\x00\x04\x00\x4B\x00\x00\x00\x07\x00\x00\x00\x4A\x00\x00\x00\x1E\x00\x19\x00\x4C\x00\x00\x00\x48\x00\x00\x00\x48\x00\x00\x00"
"\x0A\x00\x00\x00\x20\x00\x04\x00\x0C\x00\x00\x00\x00\x00\x00\x00\x0B\x00\x00\x00\x3B\x00\x04\x00\x0C\x00\x00\x00\x0D\x00\x00\x00" "\x48\x00\x00\x00\x49\x00\x00\x00\x06\x00\x00\x00\x49\x00\x00\x00\x06\x00\x00\x00\x49\x00\x00\x00\x06\x00\x00\x00\x49\x00\x00\x00"
"\x00\x00\x00\x00\x17\x00\x04\x00\x0F\x00\x00\x00\x06\x00\x00\x00\x02\x00\x00\x00\x20\x00\x04\x00\x10\x00\x00\x00\x01\x00\x00\x00" "\x06\x00\x00\x00\x4B\x00\x00\x00\x49\x00\x00\x00\x06\x00\x00\x00\x49\x00\x00\x00\x06\x00\x00\x00\x49\x00\x00\x00\x06\x00\x00\x00"
"\x0F\x00\x00\x00\x3B\x00\x04\x00\x10\x00\x00\x00\x11\x00\x00\x00\x01\x00\x00\x00\x20\x00\x04\x00\x14\x00\x00\x00\x01\x00\x00\x00" "\x07\x00\x00\x00\x07\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x0F\x00\x00\x00\x20\x00\x04\x00\x4D\x00\x00\x00\x02\x00\x00\x00"
"\x07\x00\x00\x00\x3B\x00\x04\x00\x14\x00\x00\x00\x15\x00\x00\x00\x01\x00\x00\x00\x15\x00\x04\x00\x18\x00\x00\x00\x20\x00\x00\x00" "\x4C\x00\x00\x00\x3B\x00\x04\x00\x4D\x00\x00\x00\x4E\x00\x00\x00\x02\x00\x00\x00\x1E\x00\x0C\x00\x4F\x00\x00\x00\x48\x00\x00\x00"
"\x01\x00\x00\x00\x32\x00\x04\x00\x18\x00\x00\x00\x19\x00\x00\x00\x04\x00\x00\x00\x2B\x00\x04\x00\x18\x00\x00\x00\x1A\x00\x00\x00" "\x49\x00\x00\x00\x06\x00\x00\x00\x49\x00\x00\x00\x06\x00\x00\x00\x49\x00\x00\x00\x06\x00\x00\x00\x07\x00\x00\x00\x0F\x00\x00\x00"
"\x04\x00\x00\x00\x14\x00\x02\x00\x1B\x00\x00\x00\x34\x00\x06\x00\x1B\x00\x00\x00\x1C\x00\x00\x00\xAA\x00\x00\x00\x19\x00\x00\x00" "\x0F\x00\x00\x00\x20\x00\x04\x00\x50\x00\x00\x00\x02\x00\x00\x00\x4F\x00\x00\x00\x3B\x00\x04\x00\x50\x00\x00\x00\x51\x00\x00\x00"
"\x1A\x00\x00\x00\x2B\x00\x04\x00\x18\x00\x00\x00\x20\x00\x00\x00\x03\x00\x00\x00\x34\x00\x06\x00\x1B\x00\x00\x00\x21\x00\x00\x00" "\x02\x00\x00\x00\x36\x00\x05\x00\x02\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\xF8\x00\x02\x00\x05\x00\x00\x00"
"\xAA\x00\x00\x00\x19\x00\x00\x00\x20\x00\x00\x00\x15\x00\x04\x00\x24\x00\x00\x00\x20\x00\x00\x00\x00\x00\x00\x00\x2B\x00\x04\x00" "\x3B\x00\x04\x00\x08\x00\x00\x00\x09\x00\x00\x00\x07\x00\x00\x00\x3D\x00\x04\x00\x0B\x00\x00\x00\x0E\x00\x00\x00\x0D\x00\x00\x00"
"\x24\x00\x00\x00\x25\x00\x00\x00\x03\x00\x00\x00\x20\x00\x04\x00\x26\x00\x00\x00\x07\x00\x00\x00\x06\x00\x00\x00\x2B\x00\x04\x00" "\x3D\x00\x04\x00\x0F\x00\x00\x00\x12\x00\x00\x00\x11\x00\x00\x00\x57\x00\x05\x00\x07\x00\x00\x00\x13\x00\x00\x00\x0E\x00\x00\x00"
"\x06\x00\x00\x00\x29\x00\x00\x00\x00\x00\x00\x3F\x2B\x00\x04\x00\x18\x00\x00\x00\x2F\x00\x00\x00\x02\x00\x00\x00\x34\x00\x06\x00" "\x12\x00\x00\x00\x3D\x00\x04\x00\x07\x00\x00\x00\x16\x00\x00\x00\x15\x00\x00\x00\x85\x00\x05\x00\x07\x00\x00\x00\x17\x00\x00\x00"
"\x1B\x00\x00\x00\x30\x00\x00\x00\xAA\x00\x00\x00\x19\x00\x00\x00\x2F\x00\x00\x00\x2B\x00\x04\x00\x06\x00\x00\x00\x35\x00\x00\x00" "\x13\x00\x00\x00\x16\x00\x00\x00\x3E\x00\x03\x00\x09\x00\x00\x00\x17\x00\x00\x00\xF7\x00\x03\x00\x1E\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x2B\x00\x04\x00\x18\x00\x00\x00\x3B\x00\x00\x00\x01\x00\x00\x00\x34\x00\x06\x00\x1B\x00\x00\x00\x3C\x00\x00\x00" "\xFA\x00\x04\x00\x1C\x00\x00\x00\x1D\x00\x00\x00\x1E\x00\x00\x00\xF8\x00\x02\x00\x1D\x00\x00\x00\xFC\x00\x01\x00\xF8\x00\x02\x00"
"\xAA\x00\x00\x00\x19\x00\x00\x00\x3B\x00\x00\x00\x20\x00\x04\x00\x45\x00\x00\x00\x03\x00\x00\x00\x07\x00\x00\x00\x3B\x00\x04\x00" "\x1E\x00\x00\x00\xF7\x00\x03\x00\x23\x00\x00\x00\x00\x00\x00\x00\xFA\x00\x04\x00\x21\x00\x00\x00\x22\x00\x00\x00\x2E\x00\x00\x00"
"\x45\x00\x00\x00\x46\x00\x00\x00\x03\x00\x00\x00\x32\x00\x04\x00\x18\x00\x00\x00\x48\x00\x00\x00\x00\x01\x00\x00\x1E\x00\x03\x00" "\xF8\x00\x02\x00\x22\x00\x00\x00\x41\x00\x05\x00\x26\x00\x00\x00\x27\x00\x00\x00\x09\x00\x00\x00\x25\x00\x00\x00\x3D\x00\x04\x00"
"\x49\x00\x00\x00\x07\x00\x00\x00\x20\x00\x04\x00\x4A\x00\x00\x00\x09\x00\x00\x00\x49\x00\x00\x00\x3B\x00\x04\x00\x4A\x00\x00\x00" "\x06\x00\x00\x00\x28\x00\x00\x00\x27\x00\x00\x00\xB8\x00\x05\x00\x1B\x00\x00\x00\x2A\x00\x00\x00\x28\x00\x00\x00\x29\x00\x00\x00"
"\x4B\x00\x00\x00\x09\x00\x00\x00\x18\x00\x04\x00\x4C\x00\x00\x00\x07\x00\x00\x00\x04\x00\x00\x00\x17\x00\x04\x00\x4D\x00\x00\x00" "\xF7\x00\x03\x00\x2C\x00\x00\x00\x00\x00\x00\x00\xFA\x00\x04\x00\x2A\x00\x00\x00\x2B\x00\x00\x00\x2C\x00\x00\x00\xF8\x00\x02\x00"
"\x06\x00\x00\x00\x03\x00\x00\x00\x2B\x00\x04\x00\x24\x00\x00\x00\x4E\x00\x00\x00\x04\x00\x00\x00\x1C\x00\x04\x00\x4F\x00\x00\x00" "\x2B\x00\x00\x00\xFC\x00\x01\x00\xF8\x00\x02\x00\x2C\x00\x00\x00\xF9\x00\x02\x00\x23\x00\x00\x00\xF8\x00\x02\x00\x2E\x00\x00\x00"
"\x07\x00\x00\x00\x4E\x00\x00\x00\x1E\x00\x19\x00\x50\x00\x00\x00\x4C\x00\x00\x00\x4C\x00\x00\x00\x4C\x00\x00\x00\x4D\x00\x00\x00" "\xF7\x00\x03\x00\x32\x00\x00\x00\x00\x00\x00\x00\xFA\x00\x04\x00\x30\x00\x00\x00\x31\x00\x00\x00\x3A\x00\x00\x00\xF8\x00\x02\x00"
"\x06\x00\x00\x00\x4D\x00\x00\x00\x06\x00\x00\x00\x4D\x00\x00\x00\x06\x00\x00\x00\x4D\x00\x00\x00\x06\x00\x00\x00\x4F\x00\x00\x00" "\x31\x00\x00\x00\x41\x00\x05\x00\x26\x00\x00\x00\x33\x00\x00\x00\x09\x00\x00\x00\x25\x00\x00\x00\x3D\x00\x04\x00\x06\x00\x00\x00"
"\x4D\x00\x00\x00\x06\x00\x00\x00\x4D\x00\x00\x00\x06\x00\x00\x00\x4D\x00\x00\x00\x06\x00\x00\x00\x07\x00\x00\x00\x07\x00\x00\x00" "\x34\x00\x00\x00\x33\x00\x00\x00\xBC\x00\x05\x00\x1B\x00\x00\x00\x36\x00\x00\x00\x34\x00\x00\x00\x35\x00\x00\x00\xF7\x00\x03\x00"
"\x06\x00\x00\x00\x06\x00\x00\x00\x0F\x00\x00\x00\x20\x00\x04\x00\x51\x00\x00\x00\x02\x00\x00\x00\x50\x00\x00\x00\x3B\x00\x04\x00" "\x38\x00\x00\x00\x00\x00\x00\x00\xFA\x00\x04\x00\x36\x00\x00\x00\x37\x00\x00\x00\x38\x00\x00\x00\xF8\x00\x02\x00\x37\x00\x00\x00"
"\x51\x00\x00\x00\x52\x00\x00\x00\x02\x00\x00\x00\x1E\x00\x0C\x00\x53\x00\x00\x00\x4C\x00\x00\x00\x4D\x00\x00\x00\x06\x00\x00\x00" "\xFC\x00\x01\x00\xF8\x00\x02\x00\x38\x00\x00\x00\xF9\x00\x02\x00\x32\x00\x00\x00\xF8\x00\x02\x00\x3A\x00\x00\x00\xF7\x00\x03\x00"
"\x4D\x00\x00\x00\x06\x00\x00\x00\x4D\x00\x00\x00\x06\x00\x00\x00\x07\x00\x00\x00\x0F\x00\x00\x00\x0F\x00\x00\x00\x20\x00\x04\x00" "\x3E\x00\x00\x00\x00\x00\x00\x00\xFA\x00\x04\x00\x3C\x00\x00\x00\x3D\x00\x00\x00\x3E\x00\x00\x00\xF8\x00\x02\x00\x3D\x00\x00\x00"
"\x54\x00\x00\x00\x02\x00\x00\x00\x53\x00\x00\x00\x3B\x00\x04\x00\x54\x00\x00\x00\x55\x00\x00\x00\x02\x00\x00\x00\x36\x00\x05\x00" "\x41\x00\x05\x00\x26\x00\x00\x00\x3F\x00\x00\x00\x09\x00\x00\x00\x25\x00\x00\x00\x3D\x00\x04\x00\x06\x00\x00\x00\x40\x00\x00\x00"
"\x02\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\xF8\x00\x02\x00\x05\x00\x00\x00\x3B\x00\x04\x00\x08\x00\x00\x00" "\x3F\x00\x00\x00\xBE\x00\x05\x00\x1B\x00\x00\x00\x41\x00\x00\x00\x40\x00\x00\x00\x29\x00\x00\x00\xF7\x00\x03\x00\x43\x00\x00\x00"
"\x09\x00\x00\x00\x07\x00\x00\x00\x3D\x00\x04\x00\x0B\x00\x00\x00\x0E\x00\x00\x00\x0D\x00\x00\x00\x3D\x00\x04\x00\x0F\x00\x00\x00" "\x00\x00\x00\x00\xFA\x00\x04\x00\x41\x00\x00\x00\x42\x00\x00\x00\x43\x00\x00\x00\xF8\x00\x02\x00\x42\x00\x00\x00\xFC\x00\x01\x00"
"\x12\x00\x00\x00\x11\x00\x00\x00\x57\x00\x05\x00\x07\x00\x00\x00\x13\x00\x00\x00\x0E\x00\x00\x00\x12\x00\x00\x00\x3D\x00\x04\x00" "\xF8\x00\x02\x00\x43\x00\x00\x00\xF9\x00\x02\x00\x3E\x00\x00\x00\xF8\x00\x02\x00\x3E\x00\x00\x00\xF9\x00\x02\x00\x32\x00\x00\x00"
"\x07\x00\x00\x00\x16\x00\x00\x00\x15\x00\x00\x00\x85\x00\x05\x00\x07\x00\x00\x00\x17\x00\x00\x00\x13\x00\x00\x00\x16\x00\x00\x00" "\xF8\x00\x02\x00\x32\x00\x00\x00\xF9\x00\x02\x00\x23\x00\x00\x00\xF8\x00\x02\x00\x23\x00\x00\x00\x3D\x00\x04\x00\x07\x00\x00\x00"
"\x3E\x00\x03\x00\x09\x00\x00\x00\x17\x00\x00\x00\xF7\x00\x03\x00\x1E\x00\x00\x00\x00\x00\x00\x00\xFA\x00\x04\x00\x1C\x00\x00\x00" "\x47\x00\x00\x00\x09\x00\x00\x00\x3E\x00\x03\x00\x46\x00\x00\x00\x47\x00\x00\x00\xFD\x00\x01\x00\x38\x00\x01\x00"},
"\x1D\x00\x00\x00\x1E\x00\x00\x00\xF8\x00\x02\x00\x1D\x00\x00\x00\xFC\x00\x01\x00\xF8\x00\x02\x00\x1E\x00\x00\x00\xF7\x00\x03\x00"
"\x23\x00\x00\x00\x00\x00\x00\x00\xFA\x00\x04\x00\x21\x00\x00\x00\x22\x00\x00\x00\x2E\x00\x00\x00\xF8\x00\x02\x00\x22\x00\x00\x00"
"\x41\x00\x05\x00\x26\x00\x00\x00\x27\x00\x00\x00\x09\x00\x00\x00\x25\x00\x00\x00\x3D\x00\x04\x00\x06\x00\x00\x00\x28\x00\x00\x00"
"\x27\x00\x00\x00\xB8\x00\x05\x00\x1B\x00\x00\x00\x2A\x00\x00\x00\x28\x00\x00\x00\x29\x00\x00\x00\xF7\x00\x03\x00\x2C\x00\x00\x00"
"\x00\x00\x00\x00\xFA\x00\x04\x00\x2A\x00\x00\x00\x2B\x00\x00\x00\x2C\x00\x00\x00\xF8\x00\x02\x00\x2B\x00\x00\x00\xFC\x00\x01\x00"
"\xF8\x00\x02\x00\x2C\x00\x00\x00\xF9\x00\x02\x00\x23\x00\x00\x00\xF8\x00\x02\x00\x2E\x00\x00\x00\xF7\x00\x03\x00\x32\x00\x00\x00"
"\x00\x00\x00\x00\xFA\x00\x04\x00\x30\x00\x00\x00\x31\x00\x00\x00\x3A\x00\x00\x00\xF8\x00\x02\x00\x31\x00\x00\x00\x41\x00\x05\x00"
"\x26\x00\x00\x00\x33\x00\x00\x00\x09\x00\x00\x00\x25\x00\x00\x00\x3D\x00\x04\x00\x06\x00\x00\x00\x34\x00\x00\x00\x33\x00\x00\x00"
"\xBC\x00\x05\x00\x1B\x00\x00\x00\x36\x00\x00\x00\x34\x00\x00\x00\x35\x00\x00\x00\xF7\x00\x03\x00\x38\x00\x00\x00\x00\x00\x00\x00"
"\xFA\x00\x04\x00\x36\x00\x00\x00\x37\x00\x00\x00\x38\x00\x00\x00\xF8\x00\x02\x00\x37\x00\x00\x00\xFC\x00\x01\x00\xF8\x00\x02\x00"
"\x38\x00\x00\x00\xF9\x00\x02\x00\x32\x00\x00\x00\xF8\x00\x02\x00\x3A\x00\x00\x00\xF7\x00\x03\x00\x3E\x00\x00\x00\x00\x00\x00\x00"
"\xFA\x00\x04\x00\x3C\x00\x00\x00\x3D\x00\x00\x00\x3E\x00\x00\x00\xF8\x00\x02\x00\x3D\x00\x00\x00\x41\x00\x05\x00\x26\x00\x00\x00"
"\x3F\x00\x00\x00\x09\x00\x00\x00\x25\x00\x00\x00\x3D\x00\x04\x00\x06\x00\x00\x00\x40\x00\x00\x00\x3F\x00\x00\x00\xBE\x00\x05\x00"
"\x1B\x00\x00\x00\x41\x00\x00\x00\x40\x00\x00\x00\x29\x00\x00\x00\xF7\x00\x03\x00\x43\x00\x00\x00\x00\x00\x00\x00\xFA\x00\x04\x00"
"\x41\x00\x00\x00\x42\x00\x00\x00\x43\x00\x00\x00\xF8\x00\x02\x00\x42\x00\x00\x00\xFC\x00\x01\x00\xF8\x00\x02\x00\x43\x00\x00\x00"
"\xF9\x00\x02\x00\x3E\x00\x00\x00\xF8\x00\x02\x00\x3E\x00\x00\x00\xF9\x00\x02\x00\x32\x00\x00\x00\xF8\x00\x02\x00\x32\x00\x00\x00"
"\xF9\x00\x02\x00\x23\x00\x00\x00\xF8\x00\x02\x00\x23\x00\x00\x00\x3D\x00\x04\x00\x07\x00\x00\x00\x47\x00\x00\x00\x09\x00\x00\x00"
"\x3E\x00\x03\x00\x46\x00\x00\x00\x47\x00\x00\x00\xFD\x00\x01\x00\x38\x00\x01\x00"},
#endif #endif
#ifdef D3D11QUAKE #ifdef D3D11QUAKE
{QR_DIRECT3D11, 11, "fixedemu", {QR_DIRECT3D11, 11, "fixedemu",
@ -354,6 +336,247 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"#endif\n" "#endif\n"
}, },
#endif #endif
#ifdef VKQUAKE
{QR_VULKAN, -1, "fixedemu_flat",
"\xFF\x53\x50\x56\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x2C\x00\x00\x00\x00\x00\x00\x00\x2C\x00\x00\x00"
"\xC4\x0E\x00\x00\xF0\x0E\x00\x00\xB8\x0E\x00\x00\x03\x02\x23\x07\x00\x00\x01\x00\x08\x00\x08\x00\x4D\x00\x00\x00\x00\x00\x00\x00"
"\x11\x00\x02\x00\x01\x00\x00\x00\x0B\x00\x06\x00\x01\x00\x00\x00\x47\x4C\x53\x4C\x2E\x73\x74\x64\x2E\x34\x35\x30\x00\x00\x00\x00"
"\x0E\x00\x03\x00\x00\x00\x00\x00\x01\x00\x00\x00\x0F\x00\x0E\x00\x00\x00\x00\x00\x04\x00\x00\x00\x6D\x61\x69\x6E\x00\x00\x00\x00"
"\x1C\x00\x00\x00\x39\x00\x00\x00\x3B\x00\x00\x00\x3F\x00\x00\x00\x48\x00\x00\x00\x49\x00\x00\x00\x4A\x00\x00\x00\x4B\x00\x00\x00"
"\x4C\x00\x00\x00\x03\x00\x03\x00\x02\x00\x00\x00\xC2\x01\x00\x00\x05\x00\x04\x00\x04\x00\x00\x00\x6D\x61\x69\x6E\x00\x00\x00\x00"
"\x05\x00\x06\x00\x09\x00\x00\x00\x66\x74\x65\x74\x72\x61\x6E\x73\x66\x6F\x72\x6D\x28\x00\x00\x00\x05\x00\x04\x00\x0C\x00\x00\x00"
"\x70\x72\x6F\x6A\x00\x00\x00\x00\x05\x00\x05\x00\x13\x00\x00\x00\x65\x6E\x74\x69\x74\x79\x62\x6C\x6F\x63\x6B\x00\x06\x00\x07\x00"
"\x13\x00\x00\x00\x00\x00\x00\x00\x6D\x5F\x6D\x6F\x64\x65\x6C\x76\x69\x65\x77\x70\x72\x6F\x6A\x00\x06\x00\x05\x00\x13\x00\x00\x00"
"\x01\x00\x00\x00\x6D\x5F\x6D\x6F\x64\x65\x6C\x00\x06\x00\x06\x00\x13\x00\x00\x00\x02\x00\x00\x00\x6D\x5F\x6D\x6F\x64\x65\x6C\x69"
"\x6E\x76\x00\x00\x06\x00\x06\x00\x13\x00\x00\x00\x03\x00\x00\x00\x65\x5F\x65\x79\x65\x70\x6F\x73\x00\x00\x00\x00\x06\x00\x05\x00"
"\x13\x00\x00\x00\x04\x00\x00\x00\x65\x5F\x74\x69\x6D\x65\x00\x00\x06\x00\x07\x00\x13\x00\x00\x00\x05\x00\x00\x00\x65\x5F\x6C\x69"
"\x67\x68\x74\x5F\x61\x6D\x62\x69\x65\x6E\x74\x00\x06\x00\x05\x00\x13\x00\x00\x00\x06\x00\x00\x00\x65\x70\x61\x64\x31\x00\x00\x00"
"\x06\x00\x06\x00\x13\x00\x00\x00\x07\x00\x00\x00\x65\x5F\x6C\x69\x67\x68\x74\x5F\x64\x69\x72\x00\x06\x00\x05\x00\x13\x00\x00\x00"
"\x08\x00\x00\x00\x65\x70\x61\x64\x32\x00\x00\x00\x06\x00\x06\x00\x13\x00\x00\x00\x09\x00\x00\x00\x65\x5F\x6C\x69\x67\x68\x74\x5F"
"\x6D\x75\x6C\x00\x06\x00\x05\x00\x13\x00\x00\x00\x0A\x00\x00\x00\x65\x70\x61\x64\x33\x00\x00\x00\x06\x00\x06\x00\x13\x00\x00\x00"
"\x0B\x00\x00\x00\x65\x5F\x6C\x6D\x73\x63\x61\x6C\x65\x73\x00\x00\x06\x00\x07\x00\x13\x00\x00\x00\x0C\x00\x00\x00\x65\x5F\x75\x70"
"\x70\x65\x72\x63\x6F\x6C\x6F\x75\x72\x00\x00\x00\x06\x00\x05\x00\x13\x00\x00\x00\x0D\x00\x00\x00\x65\x70\x61\x64\x34\x00\x00\x00"
"\x06\x00\x07\x00\x13\x00\x00\x00\x0E\x00\x00\x00\x65\x5F\x6C\x6F\x77\x65\x72\x63\x6F\x6C\x6F\x75\x72\x00\x00\x00\x06\x00\x05\x00"
"\x13\x00\x00\x00\x0F\x00\x00\x00\x65\x70\x61\x64\x35\x00\x00\x00\x06\x00\x06\x00\x13\x00\x00\x00\x10\x00\x00\x00\x65\x5F\x67\x6C"
"\x6F\x77\x6D\x6F\x64\x00\x00\x00\x06\x00\x05\x00\x13\x00\x00\x00\x11\x00\x00\x00\x65\x70\x61\x64\x36\x00\x00\x00\x06\x00\x07\x00"
"\x13\x00\x00\x00\x12\x00\x00\x00\x65\x5F\x63\x6F\x6C\x6F\x75\x72\x69\x64\x65\x6E\x74\x00\x00\x00\x06\x00\x07\x00\x13\x00\x00\x00"
"\x13\x00\x00\x00\x77\x5F\x66\x6F\x67\x63\x6F\x6C\x6F\x75\x72\x73\x00\x00\x00\x00\x06\x00\x07\x00\x13\x00\x00\x00\x14\x00\x00\x00"
"\x77\x5F\x66\x6F\x67\x64\x65\x6E\x73\x69\x74\x79\x00\x00\x00\x00\x06\x00\x07\x00\x13\x00\x00\x00\x15\x00\x00\x00\x77\x5F\x66\x6F"
"\x67\x64\x65\x70\x74\x68\x62\x69\x61\x73\x00\x00\x06\x00\x05\x00\x13\x00\x00\x00\x16\x00\x00\x00\x65\x70\x61\x64\x37\x00\x00\x00"
"\x05\x00\x03\x00\x15\x00\x00\x00\x00\x00\x00\x00\x05\x00\x05\x00\x1C\x00\x00\x00\x76\x5F\x70\x6F\x73\x69\x74\x69\x6F\x6E\x00\x00"
"\x05\x00\x03\x00\x39\x00\x00\x00\x74\x63\x00\x00\x05\x00\x05\x00\x3B\x00\x00\x00\x76\x5F\x74\x65\x78\x63\x6F\x6F\x72\x64\x00\x00"
"\x05\x00\x06\x00\x3D\x00\x00\x00\x67\x6C\x5F\x50\x65\x72\x56\x65\x72\x74\x65\x78\x00\x00\x00\x00\x06\x00\x06\x00\x3D\x00\x00\x00"
"\x00\x00\x00\x00\x67\x6C\x5F\x50\x6F\x73\x69\x74\x69\x6F\x6E\x00\x05\x00\x03\x00\x3F\x00\x00\x00\x00\x00\x00\x00\x05\x00\x05\x00"
"\x43\x00\x00\x00\x61\x6C\x70\x68\x61\x74\x65\x73\x74\x00\x00\x00\x05\x00\x05\x00\x44\x00\x00\x00\x6C\x69\x67\x68\x74\x62\x6C\x6F"
"\x63\x6B\x00\x00\x06\x00\x07\x00\x44\x00\x00\x00\x00\x00\x00\x00\x6C\x5F\x63\x75\x62\x65\x6D\x61\x74\x72\x69\x78\x00\x00\x00\x00"
"\x06\x00\x07\x00\x44\x00\x00\x00\x01\x00\x00\x00\x6C\x5F\x6C\x69\x67\x68\x74\x70\x6F\x73\x69\x74\x69\x6F\x6E\x00\x06\x00\x05\x00"
"\x44\x00\x00\x00\x02\x00\x00\x00\x6C\x70\x61\x64\x31\x00\x00\x00\x06\x00\x07\x00\x44\x00\x00\x00\x03\x00\x00\x00\x6C\x5F\x6C\x69"
"\x67\x68\x74\x63\x6F\x6C\x6F\x75\x72\x00\x00\x00\x06\x00\x05\x00\x44\x00\x00\x00\x04\x00\x00\x00\x6C\x70\x61\x64\x32\x00\x00\x00"
"\x06\x00\x08\x00\x44\x00\x00\x00\x05\x00\x00\x00\x6C\x5F\x6C\x69\x67\x68\x74\x63\x6F\x6C\x6F\x75\x72\x73\x63\x61\x6C\x65\x00\x00"
"\x06\x00\x07\x00\x44\x00\x00\x00\x06\x00\x00\x00\x6C\x5F\x6C\x69\x67\x68\x74\x72\x61\x64\x69\x75\x73\x00\x00\x00\x06\x00\x07\x00"
"\x44\x00\x00\x00\x07\x00\x00\x00\x6C\x5F\x73\x68\x61\x64\x6F\x77\x6D\x61\x70\x70\x72\x6F\x6A\x00\x06\x00\x08\x00\x44\x00\x00\x00"
"\x08\x00\x00\x00\x6C\x5F\x73\x68\x61\x64\x6F\x77\x6D\x61\x70\x73\x63\x61\x6C\x65\x00\x00\x00\x00\x06\x00\x05\x00\x44\x00\x00\x00"
"\x09\x00\x00\x00\x6C\x70\x61\x64\x33\x00\x00\x00\x05\x00\x03\x00\x46\x00\x00\x00\x00\x00\x00\x00\x05\x00\x05\x00\x48\x00\x00\x00"
"\x76\x5F\x63\x6F\x6C\x6F\x75\x72\x00\x00\x00\x00\x05\x00\x05\x00\x49\x00\x00\x00\x76\x5F\x6C\x6D\x63\x6F\x6F\x72\x64\x00\x00\x00"
"\x05\x00\x05\x00\x4A\x00\x00\x00\x76\x5F\x6E\x6F\x72\x6D\x61\x6C\x00\x00\x00\x00\x05\x00\x05\x00\x4B\x00\x00\x00\x76\x5F\x73\x76"
"\x65\x63\x74\x6F\x72\x00\x00\x00\x05\x00\x05\x00\x4C\x00\x00\x00\x76\x5F\x74\x76\x65\x63\x74\x6F\x72\x00\x00\x00\x47\x00\x04\x00"
"\x11\x00\x00\x00\x06\x00\x00\x00\x10\x00\x00\x00\x48\x00\x04\x00\x13\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00\x48\x00\x05\x00"
"\x13\x00\x00\x00\x00\x00\x00\x00\x23\x00\x00\x00\x00\x00\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00\x00\x00\x00\x00\x07\x00\x00\x00"
"\x10\x00\x00\x00\x48\x00\x04\x00\x13\x00\x00\x00\x01\x00\x00\x00\x05\x00\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00\x01\x00\x00\x00"
"\x23\x00\x00\x00\x40\x00\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00\x01\x00\x00\x00\x07\x00\x00\x00\x10\x00\x00\x00\x48\x00\x04\x00"
"\x13\x00\x00\x00\x02\x00\x00\x00\x05\x00\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00\x02\x00\x00\x00\x23\x00\x00\x00\x80\x00\x00\x00"
"\x48\x00\x05\x00\x13\x00\x00\x00\x02\x00\x00\x00\x07\x00\x00\x00\x10\x00\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00\x03\x00\x00\x00"
"\x23\x00\x00\x00\xC0\x00\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00\x04\x00\x00\x00\x23\x00\x00\x00\xCC\x00\x00\x00\x48\x00\x05\x00"
"\x13\x00\x00\x00\x05\x00\x00\x00\x23\x00\x00\x00\xD0\x00\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00\x06\x00\x00\x00\x23\x00\x00\x00"
"\xDC\x00\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00\x07\x00\x00\x00\x23\x00\x00\x00\xE0\x00\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00"
"\x08\x00\x00\x00\x23\x00\x00\x00\xEC\x00\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00\x09\x00\x00\x00\x23\x00\x00\x00\xF0\x00\x00\x00"
"\x48\x00\x05\x00\x13\x00\x00\x00\x0A\x00\x00\x00\x23\x00\x00\x00\xFC\x00\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00\x0B\x00\x00\x00"
"\x23\x00\x00\x00\x00\x01\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00\x0C\x00\x00\x00\x23\x00\x00\x00\x40\x01\x00\x00\x48\x00\x05\x00"
"\x13\x00\x00\x00\x0D\x00\x00\x00\x23\x00\x00\x00\x4C\x01\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00\x0E\x00\x00\x00\x23\x00\x00\x00"
"\x50\x01\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00\x0F\x00\x00\x00\x23\x00\x00\x00\x5C\x01\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00"
"\x10\x00\x00\x00\x23\x00\x00\x00\x60\x01\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00\x11\x00\x00\x00\x23\x00\x00\x00\x6C\x01\x00\x00"
"\x48\x00\x05\x00\x13\x00\x00\x00\x12\x00\x00\x00\x23\x00\x00\x00\x70\x01\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00\x13\x00\x00\x00"
"\x23\x00\x00\x00\x80\x01\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00\x14\x00\x00\x00\x23\x00\x00\x00\x90\x01\x00\x00\x48\x00\x05\x00"
"\x13\x00\x00\x00\x15\x00\x00\x00\x23\x00\x00\x00\x94\x01\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00\x16\x00\x00\x00\x23\x00\x00\x00"
"\x98\x01\x00\x00\x47\x00\x03\x00\x13\x00\x00\x00\x02\x00\x00\x00\x47\x00\x04\x00\x15\x00\x00\x00\x22\x00\x00\x00\x00\x00\x00\x00"
"\x47\x00\x04\x00\x15\x00\x00\x00\x21\x00\x00\x00\x00\x00\x00\x00\x47\x00\x04\x00\x1C\x00\x00\x00\x1E\x00\x00\x00\x00\x00\x00\x00"
"\x47\x00\x04\x00\x39\x00\x00\x00\x1E\x00\x00\x00\x00\x00\x00\x00\x47\x00\x04\x00\x3B\x00\x00\x00\x1E\x00\x00\x00\x01\x00\x00\x00"
"\x48\x00\x05\x00\x3D\x00\x00\x00\x00\x00\x00\x00\x0B\x00\x00\x00\x00\x00\x00\x00\x47\x00\x03\x00\x3D\x00\x00\x00\x02\x00\x00\x00"
"\x47\x00\x04\x00\x43\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x48\x00\x04\x00\x44\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00"
"\x48\x00\x05\x00\x44\x00\x00\x00\x00\x00\x00\x00\x23\x00\x00\x00\x00\x00\x00\x00\x48\x00\x05\x00\x44\x00\x00\x00\x00\x00\x00\x00"
"\x07\x00\x00\x00\x10\x00\x00\x00\x48\x00\x05\x00\x44\x00\x00\x00\x01\x00\x00\x00\x23\x00\x00\x00\x40\x00\x00\x00\x48\x00\x05\x00"
"\x44\x00\x00\x00\x02\x00\x00\x00\x23\x00\x00\x00\x4C\x00\x00\x00\x48\x00\x05\x00\x44\x00\x00\x00\x03\x00\x00\x00\x23\x00\x00\x00"
"\x50\x00\x00\x00\x48\x00\x05\x00\x44\x00\x00\x00\x04\x00\x00\x00\x23\x00\x00\x00\x5C\x00\x00\x00\x48\x00\x05\x00\x44\x00\x00\x00"
"\x05\x00\x00\x00\x23\x00\x00\x00\x60\x00\x00\x00\x48\x00\x05\x00\x44\x00\x00\x00\x06\x00\x00\x00\x23\x00\x00\x00\x6C\x00\x00\x00"
"\x48\x00\x05\x00\x44\x00\x00\x00\x07\x00\x00\x00\x23\x00\x00\x00\x70\x00\x00\x00\x48\x00\x05\x00\x44\x00\x00\x00\x08\x00\x00\x00"
"\x23\x00\x00\x00\x80\x00\x00\x00\x48\x00\x05\x00\x44\x00\x00\x00\x09\x00\x00\x00\x23\x00\x00\x00\x88\x00\x00\x00\x47\x00\x03\x00"
"\x44\x00\x00\x00\x02\x00\x00\x00\x47\x00\x04\x00\x46\x00\x00\x00\x22\x00\x00\x00\x00\x00\x00\x00\x47\x00\x04\x00\x46\x00\x00\x00"
"\x21\x00\x00\x00\x01\x00\x00\x00\x47\x00\x04\x00\x48\x00\x00\x00\x1E\x00\x00\x00\x02\x00\x00\x00\x47\x00\x04\x00\x49\x00\x00\x00"
"\x1E\x00\x00\x00\x03\x00\x00\x00\x47\x00\x04\x00\x4A\x00\x00\x00\x1E\x00\x00\x00\x04\x00\x00\x00\x47\x00\x04\x00\x4B\x00\x00\x00"
"\x1E\x00\x00\x00\x05\x00\x00\x00\x47\x00\x04\x00\x4C\x00\x00\x00\x1E\x00\x00\x00\x06\x00\x00\x00\x13\x00\x02\x00\x02\x00\x00\x00"
"\x21\x00\x03\x00\x03\x00\x00\x00\x02\x00\x00\x00\x16\x00\x03\x00\x06\x00\x00\x00\x20\x00\x00\x00\x17\x00\x04\x00\x07\x00\x00\x00"
"\x06\x00\x00\x00\x04\x00\x00\x00\x21\x00\x03\x00\x08\x00\x00\x00\x07\x00\x00\x00\x20\x00\x04\x00\x0B\x00\x00\x00\x07\x00\x00\x00"
"\x07\x00\x00\x00\x18\x00\x04\x00\x0D\x00\x00\x00\x07\x00\x00\x00\x04\x00\x00\x00\x17\x00\x04\x00\x0E\x00\x00\x00\x06\x00\x00\x00"
"\x03\x00\x00\x00\x15\x00\x04\x00\x0F\x00\x00\x00\x20\x00\x00\x00\x00\x00\x00\x00\x2B\x00\x04\x00\x0F\x00\x00\x00\x10\x00\x00\x00"
"\x04\x00\x00\x00\x1C\x00\x04\x00\x11\x00\x00\x00\x07\x00\x00\x00\x10\x00\x00\x00\x17\x00\x04\x00\x12\x00\x00\x00\x06\x00\x00\x00"
"\x02\x00\x00\x00\x1E\x00\x19\x00\x13\x00\x00\x00\x0D\x00\x00\x00\x0D\x00\x00\x00\x0D\x00\x00\x00\x0E\x00\x00\x00\x06\x00\x00\x00"
"\x0E\x00\x00\x00\x06\x00\x00\x00\x0E\x00\x00\x00\x06\x00\x00\x00\x0E\x00\x00\x00\x06\x00\x00\x00\x11\x00\x00\x00\x0E\x00\x00\x00"
"\x06\x00\x00\x00\x0E\x00\x00\x00\x06\x00\x00\x00\x0E\x00\x00\x00\x06\x00\x00\x00\x07\x00\x00\x00\x07\x00\x00\x00\x06\x00\x00\x00"
"\x06\x00\x00\x00\x12\x00\x00\x00\x20\x00\x04\x00\x14\x00\x00\x00\x02\x00\x00\x00\x13\x00\x00\x00\x3B\x00\x04\x00\x14\x00\x00\x00"
"\x15\x00\x00\x00\x02\x00\x00\x00\x15\x00\x04\x00\x16\x00\x00\x00\x20\x00\x00\x00\x01\x00\x00\x00\x2B\x00\x04\x00\x16\x00\x00\x00"
"\x17\x00\x00\x00\x00\x00\x00\x00\x20\x00\x04\x00\x18\x00\x00\x00\x02\x00\x00\x00\x0D\x00\x00\x00\x20\x00\x04\x00\x1B\x00\x00\x00"
"\x01\x00\x00\x00\x0E\x00\x00\x00\x3B\x00\x04\x00\x1B\x00\x00\x00\x1C\x00\x00\x00\x01\x00\x00\x00\x2B\x00\x04\x00\x06\x00\x00\x00"
"\x1E\x00\x00\x00\x00\x00\x80\x3F\x2B\x00\x04\x00\x06\x00\x00\x00\x24\x00\x00\x00\x00\x00\x80\xBF\x2B\x00\x04\x00\x0F\x00\x00\x00"
"\x25\x00\x00\x00\x01\x00\x00\x00\x20\x00\x04\x00\x26\x00\x00\x00\x07\x00\x00\x00\x06\x00\x00\x00\x2B\x00\x04\x00\x0F\x00\x00\x00"
"\x2B\x00\x00\x00\x02\x00\x00\x00\x2B\x00\x04\x00\x0F\x00\x00\x00\x2E\x00\x00\x00\x03\x00\x00\x00\x2B\x00\x04\x00\x06\x00\x00\x00"
"\x32\x00\x00\x00\x00\x00\x00\x40\x20\x00\x04\x00\x38\x00\x00\x00\x03\x00\x00\x00\x12\x00\x00\x00\x3B\x00\x04\x00\x38\x00\x00\x00"
"\x39\x00\x00\x00\x03\x00\x00\x00\x20\x00\x04\x00\x3A\x00\x00\x00\x01\x00\x00\x00\x12\x00\x00\x00\x3B\x00\x04\x00\x3A\x00\x00\x00"
"\x3B\x00\x00\x00\x01\x00\x00\x00\x1E\x00\x03\x00\x3D\x00\x00\x00\x07\x00\x00\x00\x20\x00\x04\x00\x3E\x00\x00\x00\x03\x00\x00\x00"
"\x3D\x00\x00\x00\x3B\x00\x04\x00\x3E\x00\x00\x00\x3F\x00\x00\x00\x03\x00\x00\x00\x20\x00\x04\x00\x41\x00\x00\x00\x03\x00\x00\x00"
"\x07\x00\x00\x00\x32\x00\x04\x00\x16\x00\x00\x00\x43\x00\x00\x00\x04\x00\x00\x00\x1E\x00\x0C\x00\x44\x00\x00\x00\x0D\x00\x00\x00"
"\x0E\x00\x00\x00\x06\x00\x00\x00\x0E\x00\x00\x00\x06\x00\x00\x00\x0E\x00\x00\x00\x06\x00\x00\x00\x07\x00\x00\x00\x12\x00\x00\x00"
"\x12\x00\x00\x00\x20\x00\x04\x00\x45\x00\x00\x00\x02\x00\x00\x00\x44\x00\x00\x00\x3B\x00\x04\x00\x45\x00\x00\x00\x46\x00\x00\x00"
"\x02\x00\x00\x00\x20\x00\x04\x00\x47\x00\x00\x00\x01\x00\x00\x00\x07\x00\x00\x00\x3B\x00\x04\x00\x47\x00\x00\x00\x48\x00\x00\x00"
"\x01\x00\x00\x00\x3B\x00\x04\x00\x3A\x00\x00\x00\x49\x00\x00\x00\x01\x00\x00\x00\x3B\x00\x04\x00\x1B\x00\x00\x00\x4A\x00\x00\x00"
"\x01\x00\x00\x00\x3B\x00\x04\x00\x1B\x00\x00\x00\x4B\x00\x00\x00\x01\x00\x00\x00\x3B\x00\x04\x00\x1B\x00\x00\x00\x4C\x00\x00\x00"
"\x01\x00\x00\x00\x36\x00\x05\x00\x02\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\xF8\x00\x02\x00\x05\x00\x00\x00"
"\x3D\x00\x04\x00\x12\x00\x00\x00\x3C\x00\x00\x00\x3B\x00\x00\x00\x3E\x00\x03\x00\x39\x00\x00\x00\x3C\x00\x00\x00\x39\x00\x04\x00"
"\x07\x00\x00\x00\x40\x00\x00\x00\x09\x00\x00\x00\x41\x00\x05\x00\x41\x00\x00\x00\x42\x00\x00\x00\x3F\x00\x00\x00\x17\x00\x00\x00"
"\x3E\x00\x03\x00\x42\x00\x00\x00\x40\x00\x00\x00\xFD\x00\x01\x00\x38\x00\x01\x00\x36\x00\x05\x00\x07\x00\x00\x00\x09\x00\x00\x00"
"\x00\x00\x00\x00\x08\x00\x00\x00\xF8\x00\x02\x00\x0A\x00\x00\x00\x3B\x00\x04\x00\x0B\x00\x00\x00\x0C\x00\x00\x00\x07\x00\x00\x00"
"\x41\x00\x05\x00\x18\x00\x00\x00\x19\x00\x00\x00\x15\x00\x00\x00\x17\x00\x00\x00\x3D\x00\x04\x00\x0D\x00\x00\x00\x1A\x00\x00\x00"
"\x19\x00\x00\x00\x3D\x00\x04\x00\x0E\x00\x00\x00\x1D\x00\x00\x00\x1C\x00\x00\x00\x51\x00\x05\x00\x06\x00\x00\x00\x1F\x00\x00\x00"
"\x1D\x00\x00\x00\x00\x00\x00\x00\x51\x00\x05\x00\x06\x00\x00\x00\x20\x00\x00\x00\x1D\x00\x00\x00\x01\x00\x00\x00\x51\x00\x05\x00"
"\x06\x00\x00\x00\x21\x00\x00\x00\x1D\x00\x00\x00\x02\x00\x00\x00\x50\x00\x07\x00\x07\x00\x00\x00\x22\x00\x00\x00\x1F\x00\x00\x00"
"\x20\x00\x00\x00\x21\x00\x00\x00\x1E\x00\x00\x00\x91\x00\x05\x00\x07\x00\x00\x00\x23\x00\x00\x00\x1A\x00\x00\x00\x22\x00\x00\x00"
"\x3E\x00\x03\x00\x0C\x00\x00\x00\x23\x00\x00\x00\x41\x00\x05\x00\x26\x00\x00\x00\x27\x00\x00\x00\x0C\x00\x00\x00\x25\x00\x00\x00"
"\x3D\x00\x04\x00\x06\x00\x00\x00\x28\x00\x00\x00\x27\x00\x00\x00\x85\x00\x05\x00\x06\x00\x00\x00\x29\x00\x00\x00\x28\x00\x00\x00"
"\x24\x00\x00\x00\x41\x00\x05\x00\x26\x00\x00\x00\x2A\x00\x00\x00\x0C\x00\x00\x00\x25\x00\x00\x00\x3E\x00\x03\x00\x2A\x00\x00\x00"
"\x29\x00\x00\x00\x41\x00\x05\x00\x26\x00\x00\x00\x2C\x00\x00\x00\x0C\x00\x00\x00\x2B\x00\x00\x00\x3D\x00\x04\x00\x06\x00\x00\x00"
"\x2D\x00\x00\x00\x2C\x00\x00\x00\x41\x00\x05\x00\x26\x00\x00\x00\x2F\x00\x00\x00\x0C\x00\x00\x00\x2E\x00\x00\x00\x3D\x00\x04\x00"
"\x06\x00\x00\x00\x30\x00\x00\x00\x2F\x00\x00\x00\x81\x00\x05\x00\x06\x00\x00\x00\x31\x00\x00\x00\x2D\x00\x00\x00\x30\x00\x00\x00"
"\x88\x00\x05\x00\x06\x00\x00\x00\x33\x00\x00\x00\x31\x00\x00\x00\x32\x00\x00\x00\x41\x00\x05\x00\x26\x00\x00\x00\x34\x00\x00\x00"
"\x0C\x00\x00\x00\x2B\x00\x00\x00\x3E\x00\x03\x00\x34\x00\x00\x00\x33\x00\x00\x00\x3D\x00\x04\x00\x07\x00\x00\x00\x35\x00\x00\x00"
"\x0C\x00\x00\x00\xFE\x00\x02\x00\x35\x00\x00\x00\x38\x00\x01\x00\x03\x02\x23\x07\x00\x00\x01\x00\x08\x00\x08\x00\x56\x00\x00\x00"
"\x00\x00\x00\x00\x11\x00\x02\x00\x01\x00\x00\x00\x0B\x00\x06\x00\x01\x00\x00\x00\x47\x4C\x53\x4C\x2E\x73\x74\x64\x2E\x34\x35\x30"
"\x00\x00\x00\x00\x0E\x00\x03\x00\x00\x00\x00\x00\x01\x00\x00\x00\x0F\x00\x07\x00\x04\x00\x00\x00\x04\x00\x00\x00\x6D\x61\x69\x6E"
"\x00\x00\x00\x00\x11\x00\x00\x00\x4A\x00\x00\x00\x10\x00\x03\x00\x04\x00\x00\x00\x07\x00\x00\x00\x03\x00\x03\x00\x02\x00\x00\x00"
"\xC2\x01\x00\x00\x05\x00\x04\x00\x04\x00\x00\x00\x6D\x61\x69\x6E\x00\x00\x00\x00\x05\x00\x03\x00\x09\x00\x00\x00\x66\x63\x00\x00"
"\x05\x00\x04\x00\x0D\x00\x00\x00\x73\x5F\x74\x30\x00\x00\x00\x00\x05\x00\x03\x00\x11\x00\x00\x00\x74\x63\x00\x00\x05\x00\x05\x00"
"\x14\x00\x00\x00\x70\x75\x73\x68\x69\x6E\x74\x66\x00\x00\x00\x00\x06\x00\x05\x00\x14\x00\x00\x00\x00\x00\x00\x00\x63\x6F\x6C\x6F"
"\x75\x72\x00\x00\x05\x00\x04\x00\x16\x00\x00\x00\x70\x75\x73\x68\x00\x00\x00\x00\x05\x00\x05\x00\x1D\x00\x00\x00\x61\x6C\x70\x68"
"\x61\x74\x65\x73\x74\x00\x00\x00\x05\x00\x05\x00\x4A\x00\x00\x00\x6F\x75\x74\x63\x6F\x6C\x6F\x75\x72\x00\x00\x00\x05\x00\x05\x00"
"\x50\x00\x00\x00\x65\x6E\x74\x69\x74\x79\x62\x6C\x6F\x63\x6B\x00\x06\x00\x07\x00\x50\x00\x00\x00\x00\x00\x00\x00\x6D\x5F\x6D\x6F"
"\x64\x65\x6C\x76\x69\x65\x77\x70\x72\x6F\x6A\x00\x06\x00\x05\x00\x50\x00\x00\x00\x01\x00\x00\x00\x6D\x5F\x6D\x6F\x64\x65\x6C\x00"
"\x06\x00\x06\x00\x50\x00\x00\x00\x02\x00\x00\x00\x6D\x5F\x6D\x6F\x64\x65\x6C\x69\x6E\x76\x00\x00\x06\x00\x06\x00\x50\x00\x00\x00"
"\x03\x00\x00\x00\x65\x5F\x65\x79\x65\x70\x6F\x73\x00\x00\x00\x00\x06\x00\x05\x00\x50\x00\x00\x00\x04\x00\x00\x00\x65\x5F\x74\x69"
"\x6D\x65\x00\x00\x06\x00\x07\x00\x50\x00\x00\x00\x05\x00\x00\x00\x65\x5F\x6C\x69\x67\x68\x74\x5F\x61\x6D\x62\x69\x65\x6E\x74\x00"
"\x06\x00\x05\x00\x50\x00\x00\x00\x06\x00\x00\x00\x65\x70\x61\x64\x31\x00\x00\x00\x06\x00\x06\x00\x50\x00\x00\x00\x07\x00\x00\x00"
"\x65\x5F\x6C\x69\x67\x68\x74\x5F\x64\x69\x72\x00\x06\x00\x05\x00\x50\x00\x00\x00\x08\x00\x00\x00\x65\x70\x61\x64\x32\x00\x00\x00"
"\x06\x00\x06\x00\x50\x00\x00\x00\x09\x00\x00\x00\x65\x5F\x6C\x69\x67\x68\x74\x5F\x6D\x75\x6C\x00\x06\x00\x05\x00\x50\x00\x00\x00"
"\x0A\x00\x00\x00\x65\x70\x61\x64\x33\x00\x00\x00\x06\x00\x06\x00\x50\x00\x00\x00\x0B\x00\x00\x00\x65\x5F\x6C\x6D\x73\x63\x61\x6C"
"\x65\x73\x00\x00\x06\x00\x07\x00\x50\x00\x00\x00\x0C\x00\x00\x00\x65\x5F\x75\x70\x70\x65\x72\x63\x6F\x6C\x6F\x75\x72\x00\x00\x00"
"\x06\x00\x05\x00\x50\x00\x00\x00\x0D\x00\x00\x00\x65\x70\x61\x64\x34\x00\x00\x00\x06\x00\x07\x00\x50\x00\x00\x00\x0E\x00\x00\x00"
"\x65\x5F\x6C\x6F\x77\x65\x72\x63\x6F\x6C\x6F\x75\x72\x00\x00\x00\x06\x00\x05\x00\x50\x00\x00\x00\x0F\x00\x00\x00\x65\x70\x61\x64"
"\x35\x00\x00\x00\x06\x00\x06\x00\x50\x00\x00\x00\x10\x00\x00\x00\x65\x5F\x67\x6C\x6F\x77\x6D\x6F\x64\x00\x00\x00\x06\x00\x05\x00"
"\x50\x00\x00\x00\x11\x00\x00\x00\x65\x70\x61\x64\x36\x00\x00\x00\x06\x00\x07\x00\x50\x00\x00\x00\x12\x00\x00\x00\x65\x5F\x63\x6F"
"\x6C\x6F\x75\x72\x69\x64\x65\x6E\x74\x00\x00\x00\x06\x00\x07\x00\x50\x00\x00\x00\x13\x00\x00\x00\x77\x5F\x66\x6F\x67\x63\x6F\x6C"
"\x6F\x75\x72\x73\x00\x00\x00\x00\x06\x00\x07\x00\x50\x00\x00\x00\x14\x00\x00\x00\x77\x5F\x66\x6F\x67\x64\x65\x6E\x73\x69\x74\x79"
"\x00\x00\x00\x00\x06\x00\x07\x00\x50\x00\x00\x00\x15\x00\x00\x00\x77\x5F\x66\x6F\x67\x64\x65\x70\x74\x68\x62\x69\x61\x73\x00\x00"
"\x06\x00\x05\x00\x50\x00\x00\x00\x16\x00\x00\x00\x65\x70\x61\x64\x37\x00\x00\x00\x05\x00\x03\x00\x52\x00\x00\x00\x00\x00\x00\x00"
"\x05\x00\x05\x00\x53\x00\x00\x00\x6C\x69\x67\x68\x74\x62\x6C\x6F\x63\x6B\x00\x00\x06\x00\x07\x00\x53\x00\x00\x00\x00\x00\x00\x00"
"\x6C\x5F\x63\x75\x62\x65\x6D\x61\x74\x72\x69\x78\x00\x00\x00\x00\x06\x00\x07\x00\x53\x00\x00\x00\x01\x00\x00\x00\x6C\x5F\x6C\x69"
"\x67\x68\x74\x70\x6F\x73\x69\x74\x69\x6F\x6E\x00\x06\x00\x05\x00\x53\x00\x00\x00\x02\x00\x00\x00\x6C\x70\x61\x64\x31\x00\x00\x00"
"\x06\x00\x07\x00\x53\x00\x00\x00\x03\x00\x00\x00\x6C\x5F\x6C\x69\x67\x68\x74\x63\x6F\x6C\x6F\x75\x72\x00\x00\x00\x06\x00\x05\x00"
"\x53\x00\x00\x00\x04\x00\x00\x00\x6C\x70\x61\x64\x32\x00\x00\x00\x06\x00\x08\x00\x53\x00\x00\x00\x05\x00\x00\x00\x6C\x5F\x6C\x69"
"\x67\x68\x74\x63\x6F\x6C\x6F\x75\x72\x73\x63\x61\x6C\x65\x00\x00\x06\x00\x07\x00\x53\x00\x00\x00\x06\x00\x00\x00\x6C\x5F\x6C\x69"
"\x67\x68\x74\x72\x61\x64\x69\x75\x73\x00\x00\x00\x06\x00\x07\x00\x53\x00\x00\x00\x07\x00\x00\x00\x6C\x5F\x73\x68\x61\x64\x6F\x77"
"\x6D\x61\x70\x70\x72\x6F\x6A\x00\x06\x00\x08\x00\x53\x00\x00\x00\x08\x00\x00\x00\x6C\x5F\x73\x68\x61\x64\x6F\x77\x6D\x61\x70\x73"
"\x63\x61\x6C\x65\x00\x00\x00\x00\x06\x00\x05\x00\x53\x00\x00\x00\x09\x00\x00\x00\x6C\x70\x61\x64\x33\x00\x00\x00\x05\x00\x03\x00"
"\x55\x00\x00\x00\x00\x00\x00\x00\x47\x00\x04\x00\x0D\x00\x00\x00\x22\x00\x00\x00\x00\x00\x00\x00\x47\x00\x04\x00\x0D\x00\x00\x00"
"\x21\x00\x00\x00\x02\x00\x00\x00\x47\x00\x04\x00\x11\x00\x00\x00\x1E\x00\x00\x00\x00\x00\x00\x00\x48\x00\x05\x00\x14\x00\x00\x00"
"\x00\x00\x00\x00\x23\x00\x00\x00\x00\x00\x00\x00\x47\x00\x03\x00\x14\x00\x00\x00\x02\x00\x00\x00\x47\x00\x04\x00\x1D\x00\x00\x00"
"\x01\x00\x00\x00\x00\x00\x00\x00\x47\x00\x04\x00\x4A\x00\x00\x00\x1E\x00\x00\x00\x00\x00\x00\x00\x47\x00\x04\x00\x4F\x00\x00\x00"
"\x06\x00\x00\x00\x10\x00\x00\x00\x48\x00\x04\x00\x50\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00\x48\x00\x05\x00\x50\x00\x00\x00"
"\x00\x00\x00\x00\x23\x00\x00\x00\x00\x00\x00\x00\x48\x00\x05\x00\x50\x00\x00\x00\x00\x00\x00\x00\x07\x00\x00\x00\x10\x00\x00\x00"
"\x48\x00\x04\x00\x50\x00\x00\x00\x01\x00\x00\x00\x05\x00\x00\x00\x48\x00\x05\x00\x50\x00\x00\x00\x01\x00\x00\x00\x23\x00\x00\x00"
"\x40\x00\x00\x00\x48\x00\x05\x00\x50\x00\x00\x00\x01\x00\x00\x00\x07\x00\x00\x00\x10\x00\x00\x00\x48\x00\x04\x00\x50\x00\x00\x00"
"\x02\x00\x00\x00\x05\x00\x00\x00\x48\x00\x05\x00\x50\x00\x00\x00\x02\x00\x00\x00\x23\x00\x00\x00\x80\x00\x00\x00\x48\x00\x05\x00"
"\x50\x00\x00\x00\x02\x00\x00\x00\x07\x00\x00\x00\x10\x00\x00\x00\x48\x00\x05\x00\x50\x00\x00\x00\x03\x00\x00\x00\x23\x00\x00\x00"
"\xC0\x00\x00\x00\x48\x00\x05\x00\x50\x00\x00\x00\x04\x00\x00\x00\x23\x00\x00\x00\xCC\x00\x00\x00\x48\x00\x05\x00\x50\x00\x00\x00"
"\x05\x00\x00\x00\x23\x00\x00\x00\xD0\x00\x00\x00\x48\x00\x05\x00\x50\x00\x00\x00\x06\x00\x00\x00\x23\x00\x00\x00\xDC\x00\x00\x00"
"\x48\x00\x05\x00\x50\x00\x00\x00\x07\x00\x00\x00\x23\x00\x00\x00\xE0\x00\x00\x00\x48\x00\x05\x00\x50\x00\x00\x00\x08\x00\x00\x00"
"\x23\x00\x00\x00\xEC\x00\x00\x00\x48\x00\x05\x00\x50\x00\x00\x00\x09\x00\x00\x00\x23\x00\x00\x00\xF0\x00\x00\x00\x48\x00\x05\x00"
"\x50\x00\x00\x00\x0A\x00\x00\x00\x23\x00\x00\x00\xFC\x00\x00\x00\x48\x00\x05\x00\x50\x00\x00\x00\x0B\x00\x00\x00\x23\x00\x00\x00"
"\x00\x01\x00\x00\x48\x00\x05\x00\x50\x00\x00\x00\x0C\x00\x00\x00\x23\x00\x00\x00\x40\x01\x00\x00\x48\x00\x05\x00\x50\x00\x00\x00"
"\x0D\x00\x00\x00\x23\x00\x00\x00\x4C\x01\x00\x00\x48\x00\x05\x00\x50\x00\x00\x00\x0E\x00\x00\x00\x23\x00\x00\x00\x50\x01\x00\x00"
"\x48\x00\x05\x00\x50\x00\x00\x00\x0F\x00\x00\x00\x23\x00\x00\x00\x5C\x01\x00\x00\x48\x00\x05\x00\x50\x00\x00\x00\x10\x00\x00\x00"
"\x23\x00\x00\x00\x60\x01\x00\x00\x48\x00\x05\x00\x50\x00\x00\x00\x11\x00\x00\x00\x23\x00\x00\x00\x6C\x01\x00\x00\x48\x00\x05\x00"
"\x50\x00\x00\x00\x12\x00\x00\x00\x23\x00\x00\x00\x70\x01\x00\x00\x48\x00\x05\x00\x50\x00\x00\x00\x13\x00\x00\x00\x23\x00\x00\x00"
"\x80\x01\x00\x00\x48\x00\x05\x00\x50\x00\x00\x00\x14\x00\x00\x00\x23\x00\x00\x00\x90\x01\x00\x00\x48\x00\x05\x00\x50\x00\x00\x00"
"\x15\x00\x00\x00\x23\x00\x00\x00\x94\x01\x00\x00\x48\x00\x05\x00\x50\x00\x00\x00\x16\x00\x00\x00\x23\x00\x00\x00\x98\x01\x00\x00"
"\x47\x00\x03\x00\x50\x00\x00\x00\x02\x00\x00\x00\x47\x00\x04\x00\x52\x00\x00\x00\x22\x00\x00\x00\x00\x00\x00\x00\x47\x00\x04\x00"
"\x52\x00\x00\x00\x21\x00\x00\x00\x00\x00\x00\x00\x48\x00\x04\x00\x53\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00\x48\x00\x05\x00"
"\x53\x00\x00\x00\x00\x00\x00\x00\x23\x00\x00\x00\x00\x00\x00\x00\x48\x00\x05\x00\x53\x00\x00\x00\x00\x00\x00\x00\x07\x00\x00\x00"
"\x10\x00\x00\x00\x48\x00\x05\x00\x53\x00\x00\x00\x01\x00\x00\x00\x23\x00\x00\x00\x40\x00\x00\x00\x48\x00\x05\x00\x53\x00\x00\x00"
"\x02\x00\x00\x00\x23\x00\x00\x00\x4C\x00\x00\x00\x48\x00\x05\x00\x53\x00\x00\x00\x03\x00\x00\x00\x23\x00\x00\x00\x50\x00\x00\x00"
"\x48\x00\x05\x00\x53\x00\x00\x00\x04\x00\x00\x00\x23\x00\x00\x00\x5C\x00\x00\x00\x48\x00\x05\x00\x53\x00\x00\x00\x05\x00\x00\x00"
"\x23\x00\x00\x00\x60\x00\x00\x00\x48\x00\x05\x00\x53\x00\x00\x00\x06\x00\x00\x00\x23\x00\x00\x00\x6C\x00\x00\x00\x48\x00\x05\x00"
"\x53\x00\x00\x00\x07\x00\x00\x00\x23\x00\x00\x00\x70\x00\x00\x00\x48\x00\x05\x00\x53\x00\x00\x00\x08\x00\x00\x00\x23\x00\x00\x00"
"\x80\x00\x00\x00\x48\x00\x05\x00\x53\x00\x00\x00\x09\x00\x00\x00\x23\x00\x00\x00\x88\x00\x00\x00\x47\x00\x03\x00\x53\x00\x00\x00"
"\x02\x00\x00\x00\x47\x00\x04\x00\x55\x00\x00\x00\x22\x00\x00\x00\x00\x00\x00\x00\x47\x00\x04\x00\x55\x00\x00\x00\x21\x00\x00\x00"
"\x01\x00\x00\x00\x13\x00\x02\x00\x02\x00\x00\x00\x21\x00\x03\x00\x03\x00\x00\x00\x02\x00\x00\x00\x16\x00\x03\x00\x06\x00\x00\x00"
"\x20\x00\x00\x00\x17\x00\x04\x00\x07\x00\x00\x00\x06\x00\x00\x00\x04\x00\x00\x00\x20\x00\x04\x00\x08\x00\x00\x00\x07\x00\x00\x00"
"\x07\x00\x00\x00\x19\x00\x09\x00\x0A\x00\x00\x00\x06\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x01\x00\x00\x00\x00\x00\x00\x00\x1B\x00\x03\x00\x0B\x00\x00\x00\x0A\x00\x00\x00\x20\x00\x04\x00\x0C\x00\x00\x00\x00\x00\x00\x00"
"\x0B\x00\x00\x00\x3B\x00\x04\x00\x0C\x00\x00\x00\x0D\x00\x00\x00\x00\x00\x00\x00\x17\x00\x04\x00\x0F\x00\x00\x00\x06\x00\x00\x00"
"\x02\x00\x00\x00\x20\x00\x04\x00\x10\x00\x00\x00\x01\x00\x00\x00\x0F\x00\x00\x00\x3B\x00\x04\x00\x10\x00\x00\x00\x11\x00\x00\x00"
"\x01\x00\x00\x00\x1E\x00\x03\x00\x14\x00\x00\x00\x07\x00\x00\x00\x20\x00\x04\x00\x15\x00\x00\x00\x09\x00\x00\x00\x14\x00\x00\x00"
"\x3B\x00\x04\x00\x15\x00\x00\x00\x16\x00\x00\x00\x09\x00\x00\x00\x15\x00\x04\x00\x17\x00\x00\x00\x20\x00\x00\x00\x01\x00\x00\x00"
"\x2B\x00\x04\x00\x17\x00\x00\x00\x18\x00\x00\x00\x00\x00\x00\x00\x20\x00\x04\x00\x19\x00\x00\x00\x09\x00\x00\x00\x07\x00\x00\x00"
"\x32\x00\x04\x00\x17\x00\x00\x00\x1D\x00\x00\x00\x04\x00\x00\x00\x2B\x00\x04\x00\x17\x00\x00\x00\x1E\x00\x00\x00\x04\x00\x00\x00"
"\x14\x00\x02\x00\x1F\x00\x00\x00\x34\x00\x06\x00\x1F\x00\x00\x00\x20\x00\x00\x00\xAA\x00\x00\x00\x1D\x00\x00\x00\x1E\x00\x00\x00"
"\x2B\x00\x04\x00\x17\x00\x00\x00\x24\x00\x00\x00\x03\x00\x00\x00\x34\x00\x06\x00\x1F\x00\x00\x00\x25\x00\x00\x00\xAA\x00\x00\x00"
"\x1D\x00\x00\x00\x24\x00\x00\x00\x15\x00\x04\x00\x28\x00\x00\x00\x20\x00\x00\x00\x00\x00\x00\x00\x2B\x00\x04\x00\x28\x00\x00\x00"
"\x29\x00\x00\x00\x03\x00\x00\x00\x20\x00\x04\x00\x2A\x00\x00\x00\x07\x00\x00\x00\x06\x00\x00\x00\x2B\x00\x04\x00\x06\x00\x00\x00"
"\x2D\x00\x00\x00\x00\x00\x00\x3F\x2B\x00\x04\x00\x17\x00\x00\x00\x33\x00\x00\x00\x02\x00\x00\x00\x34\x00\x06\x00\x1F\x00\x00\x00"
"\x34\x00\x00\x00\xAA\x00\x00\x00\x1D\x00\x00\x00\x33\x00\x00\x00\x2B\x00\x04\x00\x06\x00\x00\x00\x39\x00\x00\x00\x00\x00\x00\x00"
"\x2B\x00\x04\x00\x17\x00\x00\x00\x3F\x00\x00\x00\x01\x00\x00\x00\x34\x00\x06\x00\x1F\x00\x00\x00\x40\x00\x00\x00\xAA\x00\x00\x00"
"\x1D\x00\x00\x00\x3F\x00\x00\x00\x20\x00\x04\x00\x49\x00\x00\x00\x03\x00\x00\x00\x07\x00\x00\x00\x3B\x00\x04\x00\x49\x00\x00\x00"
"\x4A\x00\x00\x00\x03\x00\x00\x00\x18\x00\x04\x00\x4C\x00\x00\x00\x07\x00\x00\x00\x04\x00\x00\x00\x17\x00\x04\x00\x4D\x00\x00\x00"
"\x06\x00\x00\x00\x03\x00\x00\x00\x2B\x00\x04\x00\x28\x00\x00\x00\x4E\x00\x00\x00\x04\x00\x00\x00\x1C\x00\x04\x00\x4F\x00\x00\x00"
"\x07\x00\x00\x00\x4E\x00\x00\x00\x1E\x00\x19\x00\x50\x00\x00\x00\x4C\x00\x00\x00\x4C\x00\x00\x00\x4C\x00\x00\x00\x4D\x00\x00\x00"
"\x06\x00\x00\x00\x4D\x00\x00\x00\x06\x00\x00\x00\x4D\x00\x00\x00\x06\x00\x00\x00\x4D\x00\x00\x00\x06\x00\x00\x00\x4F\x00\x00\x00"
"\x4D\x00\x00\x00\x06\x00\x00\x00\x4D\x00\x00\x00\x06\x00\x00\x00\x4D\x00\x00\x00\x06\x00\x00\x00\x07\x00\x00\x00\x07\x00\x00\x00"
"\x06\x00\x00\x00\x06\x00\x00\x00\x0F\x00\x00\x00\x20\x00\x04\x00\x51\x00\x00\x00\x02\x00\x00\x00\x50\x00\x00\x00\x3B\x00\x04\x00"
"\x51\x00\x00\x00\x52\x00\x00\x00\x02\x00\x00\x00\x1E\x00\x0C\x00\x53\x00\x00\x00\x4C\x00\x00\x00\x4D\x00\x00\x00\x06\x00\x00\x00"
"\x4D\x00\x00\x00\x06\x00\x00\x00\x4D\x00\x00\x00\x06\x00\x00\x00\x07\x00\x00\x00\x0F\x00\x00\x00\x0F\x00\x00\x00\x20\x00\x04\x00"
"\x54\x00\x00\x00\x02\x00\x00\x00\x53\x00\x00\x00\x3B\x00\x04\x00\x54\x00\x00\x00\x55\x00\x00\x00\x02\x00\x00\x00\x36\x00\x05\x00"
"\x02\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\xF8\x00\x02\x00\x05\x00\x00\x00\x3B\x00\x04\x00\x08\x00\x00\x00"
"\x09\x00\x00\x00\x07\x00\x00\x00\x3D\x00\x04\x00\x0B\x00\x00\x00\x0E\x00\x00\x00\x0D\x00\x00\x00\x3D\x00\x04\x00\x0F\x00\x00\x00"
"\x12\x00\x00\x00\x11\x00\x00\x00\x57\x00\x05\x00\x07\x00\x00\x00\x13\x00\x00\x00\x0E\x00\x00\x00\x12\x00\x00\x00\x41\x00\x05\x00"
"\x19\x00\x00\x00\x1A\x00\x00\x00\x16\x00\x00\x00\x18\x00\x00\x00\x3D\x00\x04\x00\x07\x00\x00\x00\x1B\x00\x00\x00\x1A\x00\x00\x00"
"\x85\x00\x05\x00\x07\x00\x00\x00\x1C\x00\x00\x00\x13\x00\x00\x00\x1B\x00\x00\x00\x3E\x00\x03\x00\x09\x00\x00\x00\x1C\x00\x00\x00"
"\xF7\x00\x03\x00\x22\x00\x00\x00\x00\x00\x00\x00\xFA\x00\x04\x00\x20\x00\x00\x00\x21\x00\x00\x00\x22\x00\x00\x00\xF8\x00\x02\x00"
"\x21\x00\x00\x00\xFC\x00\x01\x00\xF8\x00\x02\x00\x22\x00\x00\x00\xF7\x00\x03\x00\x27\x00\x00\x00\x00\x00\x00\x00\xFA\x00\x04\x00"
"\x25\x00\x00\x00\x26\x00\x00\x00\x32\x00\x00\x00\xF8\x00\x02\x00\x26\x00\x00\x00\x41\x00\x05\x00\x2A\x00\x00\x00\x2B\x00\x00\x00"
"\x09\x00\x00\x00\x29\x00\x00\x00\x3D\x00\x04\x00\x06\x00\x00\x00\x2C\x00\x00\x00\x2B\x00\x00\x00\xB8\x00\x05\x00\x1F\x00\x00\x00"
"\x2E\x00\x00\x00\x2C\x00\x00\x00\x2D\x00\x00\x00\xF7\x00\x03\x00\x30\x00\x00\x00\x00\x00\x00\x00\xFA\x00\x04\x00\x2E\x00\x00\x00"
"\x2F\x00\x00\x00\x30\x00\x00\x00\xF8\x00\x02\x00\x2F\x00\x00\x00\xFC\x00\x01\x00\xF8\x00\x02\x00\x30\x00\x00\x00\xF9\x00\x02\x00"
"\x27\x00\x00\x00\xF8\x00\x02\x00\x32\x00\x00\x00\xF7\x00\x03\x00\x36\x00\x00\x00\x00\x00\x00\x00\xFA\x00\x04\x00\x34\x00\x00\x00"
"\x35\x00\x00\x00\x3E\x00\x00\x00\xF8\x00\x02\x00\x35\x00\x00\x00\x41\x00\x05\x00\x2A\x00\x00\x00\x37\x00\x00\x00\x09\x00\x00\x00"
"\x29\x00\x00\x00\x3D\x00\x04\x00\x06\x00\x00\x00\x38\x00\x00\x00\x37\x00\x00\x00\xBC\x00\x05\x00\x1F\x00\x00\x00\x3A\x00\x00\x00"
"\x38\x00\x00\x00\x39\x00\x00\x00\xF7\x00\x03\x00\x3C\x00\x00\x00\x00\x00\x00\x00\xFA\x00\x04\x00\x3A\x00\x00\x00\x3B\x00\x00\x00"
"\x3C\x00\x00\x00\xF8\x00\x02\x00\x3B\x00\x00\x00\xFC\x00\x01\x00\xF8\x00\x02\x00\x3C\x00\x00\x00\xF9\x00\x02\x00\x36\x00\x00\x00"
"\xF8\x00\x02\x00\x3E\x00\x00\x00\xF7\x00\x03\x00\x42\x00\x00\x00\x00\x00\x00\x00\xFA\x00\x04\x00\x40\x00\x00\x00\x41\x00\x00\x00"
"\x42\x00\x00\x00\xF8\x00\x02\x00\x41\x00\x00\x00\x41\x00\x05\x00\x2A\x00\x00\x00\x43\x00\x00\x00\x09\x00\x00\x00\x29\x00\x00\x00"
"\x3D\x00\x04\x00\x06\x00\x00\x00\x44\x00\x00\x00\x43\x00\x00\x00\xBE\x00\x05\x00\x1F\x00\x00\x00\x45\x00\x00\x00\x44\x00\x00\x00"
"\x2D\x00\x00\x00\xF7\x00\x03\x00\x47\x00\x00\x00\x00\x00\x00\x00\xFA\x00\x04\x00\x45\x00\x00\x00\x46\x00\x00\x00\x47\x00\x00\x00"
"\xF8\x00\x02\x00\x46\x00\x00\x00\xFC\x00\x01\x00\xF8\x00\x02\x00\x47\x00\x00\x00\xF9\x00\x02\x00\x42\x00\x00\x00\xF8\x00\x02\x00"
"\x42\x00\x00\x00\xF9\x00\x02\x00\x36\x00\x00\x00\xF8\x00\x02\x00\x36\x00\x00\x00\xF9\x00\x02\x00\x27\x00\x00\x00\xF8\x00\x02\x00"
"\x27\x00\x00\x00\x3D\x00\x04\x00\x07\x00\x00\x00\x4B\x00\x00\x00\x09\x00\x00\x00\x3E\x00\x03\x00\x4A\x00\x00\x00\x4B\x00\x00\x00"
"\xFD\x00\x01\x00\x38\x00\x01\x00"},
#endif
#ifdef GLQUAKE #ifdef GLQUAKE
{QR_OPENGL, 110, "altwater", {QR_OPENGL, 110, "altwater",
"!!cvardf r_glsl_turbscale_reflect=1 //simpler scaler\n" "!!cvardf r_glsl_turbscale_reflect=1 //simpler scaler\n"

View File

@ -519,6 +519,8 @@ static int VFSError_To_HTTP(int vfserr)
default: default:
case VFS_ERROR_UNSPECIFIED: case VFS_ERROR_UNSPECIFIED:
return 0; //don't know, no reason given. return 0; //don't know, no reason given.
case VFS_ERROR_REFUSED:
return HTTP_REFUSED;
case VFS_ERROR_EOF: case VFS_ERROR_EOF:
return HTTP_EOF; return HTTP_EOF;
case VFS_ERROR_DNSFAILURE: case VFS_ERROR_DNSFAILURE:

View File

@ -152,9 +152,10 @@ void DL_DeThread(void);
//internal 'http' error codes. //internal 'http' error codes.
#define HTTP_DNSFAILURE 900 //no ip known #define HTTP_DNSFAILURE 900 //no ip known
#define HTTP_NORESPONSE 901 //tcp failure #define HTTP_NORESPONSE 901 //tcp failure
#define HTTP_EOF 902 //unexpected eof #define HTTP_REFUSED 902 //tcp failure
#define HTTP_MITM 903 //wrong cert #define HTTP_EOF 903 //unexpected eof
#define HTTP_UNTRUSTED 904 //unverifiable cert #define HTTP_MITM 904 //wrong cert
#define HTTP_UNTRUSTED 905 //unverifiable cert
#endif #endif

View File

@ -98,7 +98,7 @@ reeval:
op = st->op; op = st->op;
#endif #endif
switch (op) safeswitch ((enum qcop_e)op)
{ {
case OP_ADD_F: case OP_ADD_F:
OPC->_float = OPA->_float + OPB->_float; OPC->_float = OPA->_float + OPB->_float;
@ -180,10 +180,10 @@ reeval:
OPC->_int = (int)(OPA->_int >= OPB->_int); OPC->_int = (int)(OPA->_int >= OPB->_int);
break; break;
case OP_GE_IF: case OP_GE_IF:
OPC->_int = (float)(OPA->_int >= OPB->_float); OPC->_int = (int)(OPA->_int >= OPB->_float);
break; break;
case OP_GE_FI: case OP_GE_FI:
OPC->_int = (float)(OPA->_float >= OPB->_int); OPC->_int = (int)(OPA->_float >= OPB->_int);
break; break;
case OP_LE_F: case OP_LE_F:
@ -193,10 +193,13 @@ reeval:
OPC->_int = (int)(OPA->_int <= OPB->_int); OPC->_int = (int)(OPA->_int <= OPB->_int);
break; break;
case OP_LE_IF: case OP_LE_IF:
OPC->_int = (float)(OPA->_int <= OPB->_float); OPC->_int = (int)(OPA->_int <= OPB->_float);
break; break;
case OP_LE_FI: case OP_LE_FI:
OPC->_int = (float)(OPA->_float <= OPB->_int); OPC->_int = (int)(OPA->_float <= OPB->_int);
break;
case OP_LE_U:
OPC->_int = (int)(OPA->_uint <= OPB->_uint);
break; break;
case OP_GT_F: case OP_GT_F:
@ -206,10 +209,10 @@ reeval:
OPC->_int = (int)(OPA->_int > OPB->_int); OPC->_int = (int)(OPA->_int > OPB->_int);
break; break;
case OP_GT_IF: case OP_GT_IF:
OPC->_int = (float)(OPA->_int > OPB->_float); OPC->_int = (int)(OPA->_int > OPB->_float);
break; break;
case OP_GT_FI: case OP_GT_FI:
OPC->_int = (float)(OPA->_float > OPB->_int); OPC->_int = (int)(OPA->_float > OPB->_int);
break; break;
case OP_LT_F: case OP_LT_F:
@ -219,10 +222,13 @@ reeval:
OPC->_int = (int)(OPA->_int < OPB->_int); OPC->_int = (int)(OPA->_int < OPB->_int);
break; break;
case OP_LT_IF: case OP_LT_IF:
OPC->_int = (float)(OPA->_int < OPB->_float); OPC->_int = (int)(OPA->_int < OPB->_float);
break; break;
case OP_LT_FI: case OP_LT_FI:
OPC->_int = (float)(OPA->_float < OPB->_int); OPC->_int = (int)(OPA->_float < OPB->_int);
break;
case OP_LT_U:
OPC->_int = (OPA->_uint < OPB->_uint);
break; break;
case OP_AND_F: case OP_AND_F:
@ -1015,6 +1021,12 @@ reeval:
else else
OPC->_int = OPA->_int / OPB->_int; OPC->_int = OPA->_int / OPB->_int;
break; break;
case OP_DIV_U:
if (OPB->_uint == 0) //no division by zero allowed...
OPC->_uint = 0;
else
OPC->_uint = OPA->_uint / OPB->_uint;
break;
case OP_EQ_I: case OP_EQ_I:
OPC->_int = (OPA->_int == OPB->_int); OPC->_int = (OPA->_int == OPB->_int);
break; break;
@ -1136,6 +1148,25 @@ reeval:
OPC->_int = ptr->_int; OPC->_int = ptr->_int;
break; break;
case OP_LOADP_I64:
i = OPA->_int + OPB->_int*4;
errorif (QCPOINTERREADFAIL(i, sizeof(pint64_t)))
{
if (!(ptr=PR_GetReadTempStringPtr(progfuncs, OPA->_int, OPB->_int*4, sizeof(pint64_t))))
{
if (i == -1)
{
OPC->_int64 = 0;
break;
}
QCFAULT(&progfuncs->funcs, "bad pointer read in %s (from %#x)", PR_StringToNative(&progfuncs->funcs, prinst.pr_xfunction->s_name), i);
}
}
else
ptr = QCPOINTERM(i);
OPC->_int64 = ptr->_int64;
break;
case OP_LOADP_V: case OP_LOADP_V:
i = OPA->_int + OPB->_int*4; //NOTE: inconsistant, but a bit more practical for the qcc when structs etc are involved i = OPA->_int + OPB->_int*4; //NOTE: inconsistant, but a bit more practical for the qcc when structs etc are involved
errorif (QCPOINTERREADFAIL(i, sizeof(pvec3_t))) errorif (QCPOINTERREADFAIL(i, sizeof(pvec3_t)))
@ -1165,6 +1196,9 @@ reeval:
case OP_RSHIFT_I: case OP_RSHIFT_I:
OPC->_int = OPA->_int >> OPB->_int; OPC->_int = OPA->_int >> OPB->_int;
break; break;
case OP_RSHIFT_U:
OPC->_uint = OPA->_uint >> OPB->_uint;
break;
case OP_LSHIFT_I: case OP_LSHIFT_I:
OPC->_int = OPA->_int << OPB->_int; OPC->_int = OPA->_int << OPB->_int;
break; break;
@ -1454,9 +1488,12 @@ reeval:
OPC->_float = (OPA->_float / OPB->_int); OPC->_float = (OPA->_float / OPB->_int);
break; break;
case OP_MOD_I: /*case OP_MOD_I:
OPC->_int = (OPA->_int % OPB->_int); OPC->_int = (OPA->_int % OPB->_int);
break; break;
case OP_MOD_U:
OPC->_uint = (OPA->_uint % OPB->_uint);
break;
case OP_MOD_F: case OP_MOD_F:
OPC->_float = OPA->_float - OPB->_float*(int)(OPA->_float/OPB->_float); OPC->_float = OPA->_float - OPB->_float*(int)(OPA->_float/OPB->_float);
break; break;
@ -1464,7 +1501,7 @@ reeval:
OPC->_vector[0] = OPA->_vector[0] - OPB->_vector[0]*(int)(OPA->_vector[0]/OPB->_vector[0]); OPC->_vector[0] = OPA->_vector[0] - OPB->_vector[0]*(int)(OPA->_vector[0]/OPB->_vector[0]);
OPC->_vector[1] = OPA->_vector[1] - OPB->_vector[1]*(int)(OPA->_vector[1]/OPB->_vector[1]); OPC->_vector[1] = OPA->_vector[1] - OPB->_vector[1]*(int)(OPA->_vector[1]/OPB->_vector[1]);
OPC->_vector[2] = OPA->_vector[2] - OPB->_vector[2]*(int)(OPA->_vector[2]/OPB->_vector[2]); OPC->_vector[2] = OPA->_vector[2] - OPB->_vector[2]*(int)(OPA->_vector[2]/OPB->_vector[2]);
break; break;*/
case OP_AND_I: case OP_AND_I:
@ -1605,9 +1642,7 @@ reeval:
case OP_LE_U64: OPC->_int = OPA->_uint64 <= OPB->_uint64; break; case OP_LE_U64: OPC->_int = OPA->_uint64 <= OPB->_uint64; break;
case OP_DIV_U64: OPC->_uint64 = OPA->_uint64 / OPB->_uint64; break; case OP_DIV_U64: OPC->_uint64 = OPA->_uint64 / OPB->_uint64; break;
case OP_RSHIFT_U64I: OPC->_uint64 = OPA->_uint64 >> OPB->_int; break; case OP_RSHIFT_U64I: OPC->_uint64 = OPA->_uint64 >> OPB->_int; break;
case OP_STORE_I64: OPB->_int64 = OPA->_int64; case OP_STORE_I64: OPB->_int64 = OPA->_int64; break;
// case OP_LOADF_I64: OPC->_int64 = OPA->_int64 X OPB->_int64; break;
// case OP_LOADP_I64: OPC->_int64 = OPA->_int64 X OPB->_int64; break;
case OP_CONV_UI64: OPC->_int64 = OPA->_uint; break; case OP_CONV_UI64: OPC->_int64 = OPA->_uint; break;
case OP_CONV_II64: OPC->_int64 = OPA->_int; break; case OP_CONV_II64: OPC->_int64 = OPA->_int; break;
case OP_CONV_I64I: OPC->_int = OPA->_int64; break; case OP_CONV_I64I: OPC->_int = OPA->_int64; break;
@ -1621,13 +1656,20 @@ reeval:
case OP_SUB_D: OPC->_double = OPA->_double - OPB->_double; break; case OP_SUB_D: OPC->_double = OPA->_double - OPB->_double; break;
case OP_MUL_D: OPC->_double = OPA->_double * OPB->_double; break; case OP_MUL_D: OPC->_double = OPA->_double * OPB->_double; break;
case OP_DIV_D: OPC->_double = OPA->_double / OPB->_double; break; case OP_DIV_D: OPC->_double = OPA->_double / OPB->_double; break;
case OP_LT_D: OPC->_double = OPA->_double < OPB->_double; break; case OP_LT_D: OPC->_int = OPA->_double < OPB->_double; break;
case OP_LE_D: OPC->_double = OPA->_double <= OPB->_double; break; case OP_LE_D: OPC->_int = OPA->_double <= OPB->_double; break;
case OP_EQ_D: OPC->_double = OPA->_double == OPB->_double; break; case OP_EQ_D: OPC->_int = OPA->_double == OPB->_double; break;
case OP_NE_D: OPC->_double = OPA->_double != OPB->_double; break; case OP_NE_D: OPC->_int = OPA->_double != OPB->_double; break;
default:
case OP_UNUSED:
case OP_POP:
case OP_NUMREALOPS ... OP_NUMOPS:
safedefault:
if (op & OP_BIT_BREAKPOINT) //break point! if (op & OP_BIT_BREAKPOINT) //break point!
{ {
op &= ~OP_BIT_BREAKPOINT; op &= ~OP_BIT_BREAKPOINT;

View File

@ -517,7 +517,7 @@ int PDECL PR_InitEnts(pubprogfuncs_t *ppf, int max_ents)
return prinst.max_fields_size; return prinst.max_fields_size;
} }
edictrun_t tempedict; //used as a safty buffer edictrun_t tempedict={ER_FREE}; //used as a safty buffer
static float tempedictfields[2048]; static float tempedictfields[2048];
static void PDECL PR_Configure (pubprogfuncs_t *ppf, size_t addressable_size, int max_progs, pbool profiling) //can be used to wipe all memory static void PDECL PR_Configure (pubprogfuncs_t *ppf, size_t addressable_size, int max_progs, pbool profiling) //can be used to wipe all memory
@ -574,14 +574,13 @@ static void PDECL PR_Configure (pubprogfuncs_t *ppf, size_t addressable_size, in
prinst.profiling = profiling; prinst.profiling = profiling;
prinst.profilingalert = Sys_GetClockRate(); prinst.profilingalert = Sys_GetClockRate();
prinst.maxedicts = 1; progfuncs->funcs.edicttable_length = prinst.maxedicts = 0;
prinst.edicttable = (edictrun_t**)(progfuncs->funcs.edicttable = &sv_edicts); prinst.edicttable = (edictrun_t**)(progfuncs->funcs.edicttable = &sv_edicts);
progfuncs->funcs.edicttable_length = 1; sv_num_edicts = 0; //set up a safty buffer so things won't go horribly wrong too often
sv_num_edicts = 1; //set up a safty buffer so things won't go horribly wrong too often
sv_edicts=(struct edict_s *)&tempedict; sv_edicts=(struct edict_s *)&tempedict;
tempedict.readonly = true; tempedict.readonly = true;
tempedict.fields = tempedictfields; tempedict.fields = tempedictfields;
tempedict.ereftype = ER_ENTITY; tempedict.ereftype = ER_OBJECT;
} }
@ -1033,9 +1032,10 @@ const char *ASMCALL PR_StringToNative (pubprogfuncs_t *ppf, string_t str)
return progfuncs->funcs.stringtable + str; return progfuncs->funcs.stringtable + str;
} }
//guarentees a return value for tempstrings, but requires a small enough data size to do so.
eval_t *PR_GetReadTempStringPtr(progfuncs_t *progfuncs, string_t str, size_t offset, size_t datasize) eval_t *PR_GetReadTempStringPtr(progfuncs_t *progfuncs, string_t str, size_t offset, size_t datasize)
{ {
static pvec3_t dummy; //don't resize anything when reading. static eval_t dummy; //don't resize anything when reading.
if (((unsigned int)str & STRING_SPECMASK) == STRING_TEMP) if (((unsigned int)str & STRING_SPECMASK) == STRING_TEMP)
{ {
unsigned int i = str & ~STRING_SPECMASK; unsigned int i = str & ~STRING_SPECMASK;
@ -1044,8 +1044,8 @@ eval_t *PR_GetReadTempStringPtr(progfuncs_t *progfuncs, string_t str, size_t off
{ {
if (offset + datasize <= temp->size) if (offset + datasize <= temp->size)
return (eval_t*)(temp->value + offset); return (eval_t*)(temp->value + offset);
else else if (datasize <= sizeof(dummy))
return (eval_t*)dummy; return &dummy;
} }
} }
return NULL; return NULL;
@ -1067,6 +1067,8 @@ eval_t *PR_GetWriteTempStringPtr(progfuncs_t *progfuncs, string_t str, size_t of
return NULL; //gotta have a cut-off point somewhere. return NULL; //gotta have a cut-off point somewhere.
newsize = (newsize+sizeof(float)-1)&~(sizeof(float)-1); newsize = (newsize+sizeof(float)-1)&~(sizeof(float)-1);
newtemp = progfuncs->funcs.parms->memalloc(sizeof(tempstr_t) - sizeof(((tempstr_t*)NULL)->value) + newsize); newtemp = progfuncs->funcs.parms->memalloc(sizeof(tempstr_t) - sizeof(((tempstr_t*)NULL)->value) + newsize);
if (!newtemp)
return NULL;
newtemp->size = newsize; newtemp->size = newsize;
memcpy(newtemp->value, temp->value, temp->size); memcpy(newtemp->value, temp->value, temp->size);
memset(newtemp->value+temp->size, 0, newsize-temp->size); memset(newtemp->value+temp->size, 0, newsize-temp->size);
@ -1079,6 +1081,47 @@ eval_t *PR_GetWriteTempStringPtr(progfuncs_t *progfuncs, string_t str, size_t of
return NULL; return NULL;
} }
//returns null for invalid accesses.
void *PR_PointerToNative_Resize(pubprogfuncs_t *inst, pint_t ptr, size_t offset, size_t datasize)
{
progfuncs_t *progfuncs = (progfuncs_t*)inst;
if (((unsigned int)ptr & STRING_SPECMASK) == STRING_TEMP)
{ //buffer. these auto-upsize.
unsigned int i = ptr & ~STRING_SPECMASK;
tempstr_t *temp;
if (i < prinst.maxtempstrings && (temp=prinst.tempstrings[i]))
{
if (datasize > temp->size || offset >= temp->size-datasize)
{ //access is beyond the current size. expand it.
unsigned int newsize;
tempstr_t *newtemp;
newsize = offset + datasize;
if (newsize > (1u<<20u))
return NULL; //gotta have a cut-off point somewhere.
newsize = (newsize+sizeof(float)-1)&~(sizeof(float)-1);
newtemp = progfuncs->funcs.parms->memalloc(sizeof(tempstr_t) - sizeof(((tempstr_t*)NULL)->value) + newsize);
if (!newtemp)
return NULL; //erk!
newtemp->size = newsize;
memcpy(newtemp->value, temp->value, temp->size);
memset(newtemp->value+temp->size, 0, newsize-temp->size);
progfuncs->funcs.parms->memfree(temp);
prinst.tempstrings[i] = temp = newtemp;
}
return (eval_t*)(temp->value + offset);
}
return NULL; //nothing not allocated.
}
else
{ //regular pointer
offset += ptr;
if (datasize > inst->stringtablesize || offset >= inst->stringtablesize-datasize || !offset)
return NULL; //can't autoresize these. just fail.
return inst->stringtable + ptr;
}
return NULL;
}
void QCBUILTIN PF_memgetval (pubprogfuncs_t *inst, struct globalvars_s *globals) void QCBUILTIN PF_memgetval (pubprogfuncs_t *inst, struct globalvars_s *globals)
{ {
progfuncs_t *progfuncs = (progfuncs_t*)inst; progfuncs_t *progfuncs = (progfuncs_t*)inst;

View File

@ -563,7 +563,7 @@ enum qcop_e {
OPD_GOTO_WHILE1, OPD_GOTO_WHILE1,
OP_NUMOPS, OP_NUMOPS,
OP_BIT_BREAKPOINT = 0x8000, #define OP_BIT_BREAKPOINT 0x8000
}; };
#define MAX_PARMS 8 #define MAX_PARMS 8

View File

@ -52,6 +52,23 @@ typedef unsigned char pbyte;
#include "pr_comp.h" #include "pr_comp.h"
#ifndef safeswitch
//safeswitch(foo){safedefault: break;}
//switch, but errors for any omitted enum values despite the presence of a default case.
//(gcc will generally give warnings without the default, but sometimes you don't have control over the source of your enumeration values)
#if (__GNUC__ >= 4)
#define safeswitch \
_Pragma("GCC diagnostic push") \
_Pragma("GCC diagnostic error \"-Wswitch-enum\"") \
_Pragma("GCC diagnostic error \"-Wswitch-default\"") \
switch
#define safedefault _Pragma("GCC diagnostic pop") default
#else
#define safeswitch switch
#define safedefault default
#endif
#endif
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(disable : 4244) #pragma warning(disable : 4244)

View File

@ -288,7 +288,7 @@ typedef struct progexterns_s {
pubprogfuncs_t * PDECL InitProgs(progparms_t *ext); pubprogfuncs_t * PDECL InitProgs(progparms_t *ext);
typedef union eval_s typedef union eval_s
{ { //FIXME: we should not be using a leading underscore here. that is reserved for libc.
string_t string; string_t string;
pvec_t _float; pvec_t _float;
pvec_t _vector[3]; pvec_t _vector[3];
@ -297,7 +297,7 @@ typedef union eval_s
puint_t _uint; puint_t _uint;
pint64_t _int64; pint64_t _int64;
puint64_t _uint64; puint64_t _uint64;
double _double; pdouble_t _double;
pint_t edict; pint_t edict;
pvec_t prog; //so it can easily be changed pvec_t prog; //so it can easily be changed
} eval_t; } eval_t;
@ -368,7 +368,7 @@ typedef union eval_s
//To use these outside of builtins, you will likly have to use the 'globals' method. //To use these outside of builtins, you will likly have to use the 'globals' method.
#define G_FLOAT(o) (((pvec_t *)pr_globals)[o]) #define G_FLOAT(o) (((pvec_t *)pr_globals)[o])
#define G_FLOAT2(o) (((pvec_t *)pr_globals)[OFS_PARM0 + o*3]) #define G_FLOAT2(o) (((pvec_t *)pr_globals)[OFS_PARM0 + o*3])
#define G_DOUBLE(o) (*(double *)(((pvec_t *)pr_globals+(o)))) #define G_DOUBLE(o) (*(pdouble_t *)(((pvec_t *)pr_globals+(o))))
#define G_INT(o) (((pint_t *)pr_globals)[o]) #define G_INT(o) (((pint_t *)pr_globals)[o])
#define G_UINT(o) (((puint_t *)pr_globals)[o]) #define G_UINT(o) (((puint_t *)pr_globals)[o])
#define G_INT64(o) (*(pint64_t *)((pint_t *)pr_globals+(o))) #define G_INT64(o) (*(pint64_t *)((pint_t *)pr_globals+(o)))

View File

@ -1,6 +1,14 @@
#ifndef QCLIB_PROGTYPE_H #ifndef QCLIB_PROGTYPE_H
#define QCLIB_PROGTYPE_H #define QCLIB_PROGTYPE_H
#if _MSC_VER >= 1300
#define QC_ALIGN(a) __declspec(align(a))
#elif (__GNUC__ >= 3) || defined(__clang__)
#define QC_ALIGN(a) __attribute__((aligned(a)))
#else
#define QC_ALIGN(a) //I hope misaligned accesses are okay...
#endif
#if 0 #if 0
//64bit primitives allows for: //64bit primitives allows for:
// greater precision timers (so maps can last longer without getting restarted) // greater precision timers (so maps can last longer without getting restarted)
@ -24,8 +32,8 @@ typedef float pvec_t;
typedef int pint_t; typedef int pint_t;
typedef unsigned int puint_t; typedef unsigned int puint_t;
#ifdef _MSC_VER #ifdef _MSC_VER
typedef __int64 pint64_t; typedef __int64 pint64_t QC_ALIGN(4);
typedef unsigned __int64 puint64_t; typedef unsigned __int64 puint64_t QC_ALIGN(4);
#define pPRId "d" #define pPRId "d"
#define pPRIi "i" #define pPRIi "i"
@ -36,8 +44,8 @@ typedef unsigned int puint_t;
#define pPRIx64 "I64x" #define pPRIx64 "I64x"
#else #else
#include <inttypes.h> #include <inttypes.h>
typedef int64_t pint64_t; typedef int64_t pint64_t QC_ALIGN(4);
typedef uint64_t puint64_t; typedef uint64_t puint64_t QC_ALIGN(4);
#define pPRId PRId32 #define pPRId PRId32
#define pPRIi PRIi32 #define pPRIi PRIi32
@ -50,6 +58,7 @@ typedef unsigned int puint_t;
#define QCVM_32 #define QCVM_32
#endif #endif
typedef double pdouble_t QC_ALIGN(4); //the qcvm uses vectors and stuff, so any 64bit types are only 4-byte aligned. we don't do atomics so this is fine so long as the compiler handles it for us.
typedef unsigned int pbool; typedef unsigned int pbool;
typedef pvec_t pvec3_t[3]; typedef pvec_t pvec3_t[3];
typedef pint_t progsnum_t; typedef pint_t progsnum_t;

View File

@ -86,6 +86,7 @@ extern int MAX_CONSTANTS;
typedef enum {QCF_STANDARD, QCF_HEXEN2, QCF_UHEXEN2, QCF_DARKPLACES, QCF_QSS, QCF_FTE, QCF_FTEDEBUG, QCF_FTEH2, QCF_KK7, QCF_QTEST} qcc_targetformat_t; typedef enum {QCF_STANDARD, QCF_HEXEN2, QCF_UHEXEN2, QCF_DARKPLACES, QCF_QSS, QCF_FTE, QCF_FTEDEBUG, QCF_FTEH2, QCF_KK7, QCF_QTEST} qcc_targetformat_t;
extern qcc_targetformat_t qcc_targetformat; extern qcc_targetformat_t qcc_targetformat;
#define qcc_targetformat_ishexen2() (qcc_targetformat == QCF_HEXEN2 || qcc_targetformat == QCF_UHEXEN2 || qcc_targetformat == QCF_FTEH2)
extern unsigned int qcc_targetversion; extern unsigned int qcc_targetversion;
void QCC_OPCodeSetTarget(qcc_targetformat_t targfmt, unsigned int targver); void QCC_OPCodeSetTarget(qcc_targetformat_t targfmt, unsigned int targver);
pbool QCC_OPCodeSetTargetName(const char *targ); pbool QCC_OPCodeSetTargetName(const char *targ);
@ -337,7 +338,7 @@ typedef union QCC_eval_s
{ {
QCC_string_t string; QCC_string_t string;
pvec_t _float; pvec_t _float;
double _double; pdouble_t _double;
pvec_t vector[3]; pvec_t vector[3];
func_t function; func_t function;
pint_t _int; pint_t _int;
@ -1126,6 +1127,7 @@ extern int numtypeinfos;
extern int maxtypeinfos; extern int maxtypeinfos;
extern int ForcedCRC; extern int ForcedCRC;
extern float qcc_framerate; //number of OP_STATE ticks per second.
extern pbool defaultnoref; extern pbool defaultnoref;
extern pbool defaultnosave; extern pbool defaultnosave;
extern pbool defaultstatic; extern pbool defaultstatic;

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