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_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)
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")
#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} -Wswitch-enum") #to warn about omitted enums despite default.
#might as well do this, public builds use the regular Makefile.
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} -D_DEBUG")
ENDIF()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_FILE_OFFSET_BITS=64")
IF(${ANDROID})
# FIND_PACKAGE(Freetype REQUIRED)
@ -244,16 +247,35 @@ ELSEIF(${WIN32})
engine/common/fs_win32.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
#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)
IF(NOT GNUTLS_FOUND)
MESSAGE(WARNING "gnutls library NOT available. HTTPS/DTLS will not be available.")
SET(FTE_LIB_DEFINES ${FTE_LIB_DEFINES};NO_GNUTLS)
ENDIF()
#linux-only packages
FIND_PACKAGE(ALSA)
IF(ALSA_FOUND)
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_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/common/sys_linux_threads.c
engine/common/net_ssl_gnutls.c
@ -307,11 +329,15 @@ ELSEIF(${UNIX}) #linux(ish)
SET(FTE_LIBS ${FTE_LIBS} ${OSSAUDIO_LIBRARY})
ENDIF()
#on linux, use wayland.
#on linux, use wayland (we normally dynamically link, but we still need headers).
FIND_LIBRARY(
WAYLAND_CLIENT_LIBRARY
NAMES wayland-client libwayland-client
)
FIND_LIBRARY(
WAYLAND_EGL
NAMES wayland-egl
)
FIND_LIBRARY(
HAVE_XKBCOMMON
NAMES xkbcommon
@ -320,7 +346,10 @@ ELSEIF(${UNIX}) #linux(ish)
MESSAGE(WARNING "xkbcommon library not found, needed for wayland to be usable.")
UNSET(WAYLAND_CLIENT_LIBRARY)
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_ARCH_FILES ${FTE_ARCH_FILES}
engine/gl/gl_vidwayland.c
@ -334,7 +363,7 @@ ELSEIF(${UNIX}) #linux(ish)
ENDIF()
SET(FTESV_DEFINES MULTITHREAD)
SET(FTESV_ARCH_FILES
SET(FTESV_ARCH_FILES ${FTESV_ARCH_FILES}
engine/server/sv_sys_unix.c
engine/common/sys_linux_threads.c
engine/common/net_ssl_gnutls.c
@ -451,10 +480,30 @@ SET(FTE_VK_FILES
engine/vk/vk_backend.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
#these files are common to both server-only and client+server builds.
engine/common/cmd.c
engine/common/com_mesh.c
engine/common/com_bih.c
engine/common/common.c
engine/common/crc.c
engine/common/cvar.c
@ -583,6 +632,17 @@ SET(FTE_COMMON_FILES
engine/gl/gl_hlmdl.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/pr_cmds.c
engine/server/pr_lua.c
@ -596,10 +656,8 @@ SET(FTE_COMMON_FILES
engine/server/sv_init.c
engine/server/sv_main.c
engine/server/sv_master.c
engine/server/sv_move.c
engine/server/sv_mvd.c
engine/server/sv_nchan.c
engine/server/sv_phys.c
engine/server/sv_rankin.c
engine/server/sv_send.c
engine/server/sv_sql.c
@ -610,28 +668,6 @@ SET(FTE_COMMON_FILES
engine/server/svq2_ents.c
engine/server/svq2_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
@ -786,6 +822,7 @@ ELSE()
${FTE_ARCH_FILES}
${FTE_COMMON_FILES}
${FTE_CLIENT_FILES}
${FTE_SERVER_FILES}
)
SET_TARGET_PROPERTIES(fteqw PROPERTIES COMPILE_DEFINITIONS "${FTE_LIB_DEFINES};${FTE_DEFINES};${FTE_REVISON}")
TARGET_LINK_LIBRARIES(fteqw ${FTE_LIBS})
@ -794,11 +831,29 @@ ELSE()
ADD_EXECUTABLE(fteqw-sv
${FTESV_ARCH_FILES}
${FTE_COMMON_FILES}
${FTE_SERVER_FILES}
)
SET_TARGET_PROPERTIES(fteqw-sv PROPERTIES COMPILE_DEFINITIONS "SERVERONLY;${FTE_LIB_DEFINES};${FTESV_DEFINES};${FTE_REVISON}")
TARGET_LINK_LIBRARIES(fteqw-sv ${FTESV_LIBS})
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
iqm/iqm.cpp
plugins/models/gltf.c
@ -814,7 +869,8 @@ ELSE()
engine/client/image.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} )
SET(INSTALLTARGS ${INSTALLTARGS} imgtool)
@ -888,6 +944,7 @@ ELSE()
engine/qclib/qcc_pr_lex.c
engine/qclib/qccmain.c
engine/qclib/qcd_main.c
engine/qclib/packager.c
)
SET_TARGET_PROPERTIES(fteqcc PROPERTIES COMPILE_DEFINITIONS "${FTE_LIB_DEFINES};${FTE_REVISON}")
TARGET_LINK_LIBRARIES(fteqcc ${FTEQCC_LIBS} ${SYS_LIBS})
@ -938,7 +995,7 @@ ELSE()
engine/qclib/qcc_pr_lex.c
engine/qclib/qccmain.c
engine/qclib/decomp.c
engine/qclib/packager.c
# engine/qclib/packager.c
engine/qclib/qcd_main.c
)
TARGET_INCLUDE_DIRECTORIES(fteqccgui PUBLIC ${Qt5Widgets_INCLUDE_DIRS} ${QSCINTILLA_INCLUDE_DIR})
@ -952,6 +1009,29 @@ ELSE()
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
ADD_LIBRARY(qi MODULE
plugins/plugin.c
@ -1088,6 +1168,27 @@ ELSE()
MESSAGE(WARNING "ffmpeg library NOT available. Quake shouldn't be playing fmv anyway.")
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
FIND_PACKAGE(PkgConfig)
IF (PKGCONFIG_FOUND)
@ -1149,6 +1250,7 @@ IF(NOT ANDROID)
plugins/jabber/jingle.c
plugins/jabber/sift.c
engine/common/sha1.c
engine/common/sha2.c
plugins/emailnot/md5.c
)
SET_TARGET_PROPERTIES(xmpp PROPERTIES COMPILE_DEFINITIONS "FTEPLUGIN;${FTE_LIB_DEFINES}")
@ -1164,11 +1266,11 @@ ENDIF()
INCLUDE(GNUInstallDirs)
SET(FTE_INSTALL_BINDIR games CACHE STRING "Binary dir to install to.")
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}"
)
IF (0)
IF (1)
ADD_CUSTOM_TARGET(menusys ALL
VERBATIM
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_heightmap.o \
gl_model.o \
com_bih.o \
com_mesh.o \
common.o \
cvar.o \

View File

@ -184,8 +184,10 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#undef idx64
#define idx64 1
#define ARCH_STRING "x86_64"
#elif defined __ppc64le__
#define ARCH_STRING "ppc64le" //more common than ppc64[be] on linux nowadays.
#elif defined __powerpc64__
#define ARCH_STRING "ppc64"
#define ARCH_STRING "ppc64" //big-endian/original variant.
#elif defined __powerpc__
#define ARCH_STRING "ppc"
#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);
}
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*/
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);
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]);
/*if this entity is in a player's slot...*/
@ -4815,7 +4824,7 @@ void CLQW_ParsePlayerinfo (void)
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[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[8], 7);
//these are fucked, as required for dpcompat.
//more inconsistencies, as required for dpcompat.
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 |= (cursor_active) ?(1u<<10):0; //prydon cursor stuff.
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; //'cursor_active'. prydon cursor stuff.
GATHERBIT(in_button[9], 11);
GATHERBIT(in_button[10], 12);
GATHERBIT(in_button[11], 13);
@ -815,6 +815,10 @@ void CL_GatherButtons (usercmd_t *cmd, int pnum)
UNUSEDBUTTON(18);
UNUSEDBUTTON(19);
// 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;
}
@ -911,6 +915,9 @@ void CL_BaseMove (usercmd_t *cmd, int pnum, float priortime, float extratime)
float nscale = extratime?extratime / (extratime+priortime):0;
float oscale = 1 - nscale;
cmd->fservertime = cl.time*1000;
cmd->servertime = cl.time*1000;
//
// 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)
{
int i;
unsigned int bits;
if (cls.demoplayback!=DPB_NONE)
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)
MSG_WriteShort(buf, cl.movesequence&0xffff);
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);
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);
}
if (cls.fteprotocolextensions2 & PEXT2_VRINPUTS)
MSGFTE_WriteDeltaUsercmd(buf, &nullcmd, cmd);
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);
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];
if (cl_c2sImpulseBackup.ival >= 2)
dontdrop = dontdrop || cmd->impulse;
MSG_WriteDeltaUsercmd (buf, &nullcmd, cmd);
MSGCL_WriteDeltaUsercmd (buf, &nullcmd, cmd);
oldcmd = cmd;
i = (cls.netchan.outgoing_sequence-1) & UPDATE_MASK;
if (cl_c2sImpulseBackup.ival >= 3)
dontdrop = dontdrop || cmd->impulse;
cmd = &cl.outframes[i].cmd[plnum];
MSG_WriteDeltaUsercmd (buf, oldcmd, cmd);
MSGCL_WriteDeltaUsercmd (buf, oldcmd, cmd);
oldcmd = cmd;
i = (cls.netchan.outgoing_sequence) & UPDATE_MASK;
if (cl_c2sImpulseBackup.ival >= 1)
dontdrop = dontdrop || cmd->impulse;
cmd = &cl.outframes[i].cmd[plnum];
MSG_WriteDeltaUsercmd (buf, oldcmd, cmd);
MSGCL_WriteDeltaUsercmd (buf, oldcmd, cmd);
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_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_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.");
@ -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_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 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");
@ -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_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_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 vid_renderer;
@ -1261,6 +1262,7 @@ void CL_BeginServerReconnect(void)
connectinfo.trying = true;
connectinfo.istransfer = false;
connectinfo.time = 0;
connectinfo.tries = 0; //re-ensure routes.
NET_InitClient(false);
}
@ -1705,7 +1707,7 @@ void CL_ClearState (qboolean gamestart)
S_UntouchAll();
S_ResetFailedLoad();
Cvar_ApplyLatches(CVAR_SERVEROVERRIDE);
Cvar_ApplyLatches(CVAR_SERVEROVERRIDE, true);
Con_DPrintf ("Clearing memory\n");
if (!serverrunning || !tolocalserver)
@ -1717,7 +1719,7 @@ void CL_ClearState (qboolean gamestart)
Mod_ClearAll ();
r_regsequence++;
Cvar_ApplyLatches(CVAR_LATCH);
Cvar_ApplyLatches(CVAR_MAPLATCH, false);
}
CL_ClearParseState();
@ -1894,7 +1896,7 @@ void CL_Disconnect (const char *reason)
SCR_SetLoadingStage(0);
Cvar_ApplyLatches(CVAR_SERVEROVERRIDE);
Cvar_ApplyLatches(CVAR_SERVEROVERRIDE, true);
// stop sounds (especially looping!)
S_StopAllSounds (true);
@ -2000,8 +2002,6 @@ void CL_Disconnect (const char *reason)
cls.findtrack = false;
cls.realserverip.type = NA_INVALID;
Validation_DelatchRulesets();
#ifdef TCPCONNECT
//disconnects it, without disconnecting the others.
FTENET_AddToCollection(cls.sockets, "conn", NULL, NA_INVALID, NP_DGRAM);
@ -2899,6 +2899,15 @@ Return to looping demos
*/
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)
cls.demonum = 1;
CL_Disconnect_f ();
@ -3012,7 +3021,6 @@ void CL_Reconnect_f (void)
#endif
CL_Disconnect(NULL);
connectinfo.tries = 0; //re-ensure routes.
CL_BeginServerReconnect();
}
@ -6325,47 +6333,51 @@ double Host_Frame (double time)
if (host_speeds.ival)
time1 = Sys_DoubleTime ();
for (i = 0; i < MAX_SPLITS; i++)
if (!VID_MayRefresh || VID_MayRefresh())
{
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 (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();
if (R2D_Flush)
{
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);
R2D_Flush();
Con_Printf("R2D_Flush was set outside of SCR_UpdateScreen\n");
}
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)
time2 = Sys_DoubleTime ();
@ -6446,7 +6458,7 @@ void CL_ReadCDKey(void)
break;
}
}
Cvar_Get("cl_cdkey", buffer, CVAR_LATCH|CVAR_NOUNSAFEEXPAND, "Q3 compatability");
Cvar_Get("cl_cdkey", buffer, CVAR_MAPLATCH|CVAR_NOUNSAFEEXPAND, "Q3 compatability");
}
}
#endif
@ -6549,7 +6561,7 @@ void CL_StartCinematicOrMenu(void)
#endif
if (!cls.state && !Key_Dest_Has(~kdm_game) && cl_demoreel.ival)
{
cls.demonum = 0;
cls.demonum = MAX_DEMOS;
CL_NextDemo();
}
if (!cls.state && !Key_Dest_Has(~kdm_game))
@ -6596,6 +6608,9 @@ void CL_ArgumentOverrides(void)
if ((i = COM_CheckParm ("-particles")))
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.
@ -6692,6 +6707,8 @@ void CL_ExecInitialConfigs(char *resetcommand)
//and disable the 'you have unsaved stuff' prompt.
Cvar_Saved();
Ruleset_Scan();
}
@ -6969,6 +6986,7 @@ void Host_Shutdown(void)
#ifdef QUAKEHUD
Stats_Clear();
#endif
Ruleset_Shutdown();
#ifdef Q3CLIENT
VMQ3_FlushStringHandles();
#endif

View File

@ -2967,6 +2967,7 @@ static void CLDP_ParseDownloadFinished(char *s)
{
qdownload_t *dl = cls.download;
unsigned short runningcrc = 0;
const hashfunc_t *hfunc = &hash_crc16;
char buffer[8192];
int size, pos, chunk;
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);
if (dl->file)
{
char *hashctx = alloca(hfunc->digestsize);
size = dl->size;
QCRC_Init(&runningcrc);
hfunc->init(&hashctx);
for (pos = 0, chunk = 1; chunk; pos += chunk)
{
chunk = size - pos;
if (chunk > sizeof(buffer))
chunk = sizeof(buffer);
VFS_READ(dl->file, buffer, chunk);
QCRC_AddBlock(&runningcrc, buffer, chunk);
hfunc->process(&hashctx, buffer, chunk);
}
VFS_CLOSE (dl->file);
dl->file = NULL;
runningcrc = hashfunc_terminate_uint(hfunc, hashctx);
}
else
{
@ -3376,7 +3380,7 @@ static void CLQW_ParseServerData (void)
{
cl.playerview[pnum].spectator = true;
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();
if (cl.playerview[pnum].playernum >= cl.allocated_client_slots)
Host_EndGame("unsupported local player slot\n");
@ -3392,7 +3396,7 @@ static void CLQW_ParseServerData (void)
if (clnum == MAX_SPLITS)
Host_EndGame("Server sent us over %u seats\n", MAX_SPLITS);
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;
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->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");
if (!strncmp(col, "0x", 2))
player->rtopcolor = 0xff000000|strtoul(col+2, NULL, 16);

View File

@ -328,6 +328,7 @@ typedef struct associatedeffect_s
unsigned int meflags;
} associatedeffect_t;
associatedeffect_t *associatedeffect;
char part_parsenamespace[MAX_QPATH];
void CL_AssociateEffect_f(void)
{
char *modelname = Cmd_Argv(1);
@ -335,6 +336,16 @@ void CL_AssociateEffect_f(void)
int type, i;
unsigned int flags = 0;
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"))
type = AE_TRAIL;
else
@ -367,6 +378,9 @@ void CL_AssociateEffect_f(void)
return;
}
if (*part_parsenamespace && !strchr(effectname, '.'))
effectname = va("%s.%s", part_parsenamespace, effectname);
if (strlen (modelname) >= MAX_QPATH || strlen(effectname) >= MAX_QPATH)
return;

View File

@ -171,6 +171,7 @@ typedef struct player_info_s
int frags;
int ping;
qbyte pl;
char ruleset[19]; //has colour markup to say if its accepted or not
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_shaders;
extern cvar_t ruleset_allow_watervis;
extern cvar_t ruleset_allow_triggers;
#ifndef SERVERONLY
extern client_state_t cl;
@ -1614,13 +1616,17 @@ void Skin_FlushAll(void);
//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_FlushFileList(void);
void Validation_CheckIfResponse(char *text);
void Validation_DelatchRulesets(void);
void InitValidation(void);
void Validation_FileLoaded(const char *filename, const qbyte *filedata, size_t filesize);
void Validation_Auto_Response(int playernum, char *s);
extern qboolean f_modified_particles;

View File

@ -903,7 +903,8 @@ void CLQ3_SendCmd(usercmd_t *cmd)
sizebuf_t msg;
outframe_t *frame, *oldframe;
int cmdcount, key;
usercmd_t *to, *from;
usercmd_t *to;
const usercmd_t *from;
extern cvar_t cl_nodelta, cl_c2sdupe;
//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)
{
if (log_developer.ival)
if (log_developer.ival || !a)
Con_Log(data);
if (developer.ival >= (int)a)
{
@ -1272,7 +1272,7 @@ void VARGS Con_DLPrintf (int level, const char *fmt, ...)
Sys_Printf("%s", msg);
return;
#else
if (developer.ival<level && !log_developer.ival)
if (developer.ival<level && (!log_developer.ival && level))
return; // early exit
#endif
@ -1286,7 +1286,7 @@ void VARGS Con_DLPrintf (int level, const char *fmt, ...)
return;
}
if (log_developer.ival)
if (log_developer.ival || !level)
Con_Log(msg);
if (developer.ival >= level)
{

View File

@ -11572,6 +11572,19 @@ static struct
{PTI_RGBX8, PTI_RGBA8, 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_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},

View File

@ -1085,3 +1085,49 @@ void IN_Gyroscope(unsigned int devid, float pitch, float yaw, float roll)
ev->gyro.roll = roll;
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_Accelerometer(unsigned int devid, float x, float y, float z);
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
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;
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)
{
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 **newvalues;
char *optbuf;
const char *v;
int i;
maxoptlen = 0;
optbufsize = sizeof(char*)*2 + strlen(caption)+1;
numopts = 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)
maxoptlen = optlen;
optbufsize += optlen+1+sizeof(char*);
optbufsize += strlen(values[numopts])+1+sizeof(char*);
numopts++;
optbufsize += strlen(v)+1+sizeof(char*);
}
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;
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;
strcpy(optbuf, ops[i]);
newops[i] = optbuf;
optbuf += strlen(optbuf)+1;
strcpy(optbuf, values[i]);
strcpy(optbuf, v);
newvalues[i] = optbuf;
optbuf += strlen(optbuf)+1;
}
@ -1729,7 +1727,7 @@ static void M_Draw (menu_t *menu)
}
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*/;
else
R2D_FadeScreen ();
@ -1873,7 +1871,7 @@ void M_MenuPop_f (void)
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;
while(op->common.next)
@ -1889,6 +1887,9 @@ menuoption_t *M_NextSelectableItem(emenu_t *m, menuoption_t *old)
{
menuoption_t *op;
if (!m->options)
return NULL; //erk!
if (!old)
old = M_NextItem(m, old);
@ -1920,6 +1921,9 @@ menuoption_t *M_PrevSelectableItem(emenu_t *m, menuoption_t *old)
{
menuoption_t *op;
if (!m->options)
return NULL; //erk!
if (!old)
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 selectedy = y;
int selectedy = y, last_y = y;
menuoption_t *selected = NULL;
while (bulk)
@ -2597,6 +2601,9 @@ int MC_AddBulk(struct emenu_s *menu, menuresel_t *resel, menubulk_t *bulk, int x
if (bulk->ret)
*bulk->ret = control;
if (control)
control->common.grav_y = y-last_y;
last_y = y;
if (control && MI_Selectable(control) && !selected)
selected = control;
if (control && bulk->tooltip)

View File

@ -1042,7 +1042,7 @@ const char *presetexec[] =
, // realtime options
"r_bloom 1;"
"r_deluxemapping 0;" //won't be seen anyway
"r_deluxemapping 1;" //won't be seen anyway
"r_particledesc \"high tsshaft\";"
// "r_waterstyle 3;" //too expensive.
"r_glsl_offsetmapping 1;"
@ -1176,12 +1176,106 @@ static void ApplyPreset (int presetnum, qboolean doreload)
if (doreload)
{
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--)
{
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)
@ -1189,25 +1283,45 @@ void M_Menu_Preset_f (void)
extern cvar_t cfg_save_auto;
emenu_t *menu;
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[] =
{
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_CONSOLECMD("simple (untextured)", "fps_preset 286;menupop\n", "Lacks textures, particles, pretty much everything."),
MB_CONSOLECMD("fast (qw deathmatch)", "fps_preset fast;menupop\n", "Fullscreen effects off to give consistant framerates"),
MB_CONSOLECMD("spasm (nq compat)", "fps_preset spasm;menupop\n", "Aims for visual compatibility with common NQ engines. Also affects mods slightly."),
MB_CONSOLECMD("vanilla (softwarey)", "fps_preset vanilla;menupop\n", "This is for purists! Party like its 1995! No sanity spared!"),
MB_CONSOLECMD("normal (faithful)", "fps_preset normal;menupop\n", "An updated but still faithful appearance, using content replacements where applicable"),
MB_CONSOLECMD("nice (dynamic)", "fps_preset nice;menupop\n", "For people who like nice things, but still want to actually play"),
MB_CONSOLECMDRETURN("^7simple (untextured)", "fps_preset 286\n", "Lacks textures, particles, pretty much everything.", presetoption[0]),
MB_CHECKBOXCVAR("anim snapping", r_nolerp, 0),
MB_CONSOLECMDRETURN("^7fast (qw deathmatch)", "fps_preset fast\n", "Fullscreen effects off to give consistant framerates", presetoption[1]),
MB_CONSOLECMDRETURN("^7spasm (nq compat)", "fps_preset spasm\n", "Aims for visual compatibility with common NQ engines. Also affects mods slightly.", presetoption[2]),
#ifdef HAVE_SERVER
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
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
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_SPACING(16),
MB_CONSOLECMD("Accept", "menupop\n", NULL),
MB_END()
};
static menuresel_t resel;
int item, bias = 0;
int item;
extern cvar_t r_drawflat;
menu = M_Options_Title(&y, 0);
MC_AddBulk(menu, &resel, bulk, 16, 216, y);
@ -1215,28 +1329,32 @@ void M_Menu_Preset_f (void)
//bottoms up!
#ifdef RTLIGHTS
if (r_shadow_realtime_world.ival)
item = 1; //realtime
item = 6; //realtime
else
#else
bias = 1;
#endif
if (r_deluxemapping_cvar.ival)
item = 2; //nice
item = 5; //nice
else if (gl_load24bit.ival)
item = 3; //normal
item = 4; //normal
else if (r_softwarebanding_cvar.ival)
item = 4; //vanilla
item = 3; //vanilla
else if (cl_sbar.ival == 2)
item = 5; //spasm
item = 2; //spasm
else if (!r_drawflat.ival)
item = 6; //fast
item = 1; //fast
else
item = 7; //simple
item++; //the autosave option
item -= bias;
while (item --> 0)
menu->selecteditem = menu->selecteditem->common.next;
menu->cursoritem->common.posy = menu->selecteditem->common.posy;
item = 0; //simple
if (presetoption[item])
{
menu->selecteditem = presetoption[item];
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)
@ -3959,6 +4077,19 @@ void M_Modelviewer_Shutdown(struct emenu_s *menu)
skel_reset(&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
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;
menu = M_CreateMenu(sizeof(*mv));
menu->menu.persist = true;
menu->menu.videoreset = M_Modelviewer_Reset;
mv = menu->data;
c = MC_AddCustom(menu, 64, 32, mv, 0, NULL);
menu->cursoritem = (menuoption_t*)c;

View File

@ -540,10 +540,9 @@ void M_Menu_SinglePlayer_f (void)
p = R2D_SafeCachePic("gfx/sp_menu.lmp");
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, 13*8, "gfx/sp_menu.lmp", false);
MC_AddBox (menu, 72, 11*8, 23*8, 4*8);
}
else
{

View File

@ -418,8 +418,8 @@ typedef struct
void (*callback)(void *, promptbutton_t);
void *ctx;
int lines;
const char *messages;
conchar_t *msg;
size_t msglen;
const char *buttons[3];
int kbutton, mbutton;
qboolean mousedown;
@ -516,22 +516,35 @@ static void Prompt_Draw(struct menu_s *g)
promptmenu_t *m = (promptmenu_t*)g;
int x = 64;
int y = 76;
int px, py;
float scale = Font_CharVHeight(font_console);
int w = 320*scale/8;
int h = (m->lines+3)*scale;
int h, lines;
int i;
const char *msg = m->messages;
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);
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);
y+=scale;
int xoffset = (w*vid.rotpixelwidth/vid.width) - Font_LineWidth(linestart[i], lineend[i]);
Font_LineDraw(px + xoffset/2, py, linestart[i], lineend[i]);
py+=Font_CharHeight();
}
Font_EndString(font_console);
y+=scale*lines;
y+=scale;
m->mbutton = -1;
bx[0] = x;
@ -576,8 +589,11 @@ void Menu_Prompt (void (*callback)(void *, promptbutton_t), void *ctx, const cha
{
promptmenu_t *m;
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];
/*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;
}
m->messages = t;
strcpy(t, messages);
for(messages = t; t;)
{
t = strchr(t, '\n');
if (t)
*t++ = 0;
m->lines++;
}
m->msglen = e-message;
m->msg = memcpy(t, message, (m->msglen)*sizeof(conchar_t));
}
#ifndef NOBUILTINMENUS

View File

@ -174,6 +174,10 @@ typedef struct { //must be first of each structure type.
int width; //total width
int height; //total height
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;
qboolean noselectionsound:1;
qboolean iszone:1;
@ -309,11 +313,12 @@ struct emenu_s {
int ypos;
int width;
int height;
qboolean dontexpand;
qboolean dontexpand; //false=recenter xpos
int numoptions;
menuresel_t *reselection; //stores some info to restore selection properly.
qboolean iszone;
qboolean iszone;
qboolean nobacktint;
void *data; //typecast
@ -384,9 +389,10 @@ typedef struct menubulk_s {
} menubulk_t;
#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_CHECKBOXCVARTIP(text, cvar, flags, tip) {mt_checkbox, 0, text, tip, NULL, &cvar, flags}
#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_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_CHECKBOXCVAR(text, cvar, cvarflag) {mt_checkbox, 0, text, NULL, NULL, &cvar, cvarflag}
#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_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}

View File

@ -482,9 +482,10 @@ typedef struct rendererinfo_s {
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.
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 clipboard handling
@ -493,6 +494,7 @@ typedef struct rendererinfo_s {
#define rf currentrendererstate.renderer
#define VID_SwapBuffers rf->VID_SwapBuffers
#define VID_MayRefresh rf->VID_MayRefresh
#define BE_Init rf->BE_Init
#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_reportheartbeats;
extern cvar_t sv_heartbeat_interval;
extern cvar_t sv_heartbeat_checks;
extern cvar_t sv_listen_qw;
extern cvar_t sv_listen_nq;
@ -204,7 +205,8 @@ static net_masterlist_t net_masterlist[] = {
{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;
//never throttle packets from master servers. we don't want to go missing.
@ -214,13 +216,51 @@ qboolean Net_AddressIsMaster(netadr_t *adr)
continue;
for (j = 0; j < MAX_MASTER_ADDRESSES; j++)
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 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)
{
@ -238,7 +278,7 @@ static void QDECL Net_Masterlist_Callback(struct cvar_s *var, char *oldvalue)
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];
qboolean madeqwstring = false;
@ -286,7 +326,7 @@ void SV_Master_SingleHeartbeat(net_masterlist_t *master)
case MP_QUAKE2:
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 q2users[8192];
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
//(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);
}
break;
@ -374,10 +414,10 @@ struct thr_res
netadr_t na[8];
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];
int i;
int i, j;
struct thr_res *work = data;
netadr_t *na;
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;
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)
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);
}
//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];
int found = 0;

View File

@ -434,7 +434,7 @@ static int numparticletypes;
static part_type_t *part_type;
static part_type_t *part_run_list;
static char part_parsenamespace[MAX_QPATH];
extern char part_parsenamespace[MAX_QPATH];
static qboolean part_parseweak;
static struct {
@ -3305,19 +3305,19 @@ static void P_ImportEffectInfo(char *config, char *line)
}
#if 1
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.
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.
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
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)
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)
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)
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
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;
}
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;
}

View File

@ -105,6 +105,7 @@ typedef struct {
#define globalfloatdep(name,dep) globalfloat(name)
#define globalfloat(name) float *name;
#define globalint(name) int *name;
#define globaluint(name) unsigned int *name;
#define globalvector(name) float *name;
#define globalentity(name) int *name;
#define globalstring(name) string_t *name;
@ -115,6 +116,7 @@ typedef struct {
#undef globalfloat
#undef globalint
#undef globaluint
#undef globalvector
#undef globalentity
#undef globalstring
@ -204,6 +206,7 @@ static void CSQC_FindGlobals(qboolean nofuncs)
static vec3_t defaultgravity = {0, 0, -1};
#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 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 globalentity(name) csqcg.name = (int*)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 globalint
#undef globaluint
#undef globalvector
#undef globalentity
#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_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.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_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)
{ //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:
l->decay = G_FLOAT(OFS_PARM2);
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:
break;
}
@ -1304,6 +1321,15 @@ static void QCBUILTIN PF_R_DynamicLight_Get(pubprogfuncs_t *prinst, struct globa
case lfield_radiusdecay:
G_FLOAT(OFS_RETURN) = l->decay;
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:
G_INT(OFS_RETURN) = 0;
break;
@ -1833,7 +1859,7 @@ void QCBUILTIN PF_R_AddTrisoup_Simple(pubprogfuncs_t *prinst, struct globalvars_
unsigned int numindexes = G_INT(OFS_PARM4);
qboolean twod = qcflags & DRAWFLAG_2D;
unsigned int beflags;
unsigned int numverts;
unsigned int maxverts;
const qcvertex_t *fte_restrict vert;
const unsigned int *fte_restrict idx;
unsigned int i, j, first;
@ -1860,8 +1886,8 @@ void QCBUILTIN PF_R_AddTrisoup_Simple(pubprogfuncs_t *prinst, struct globalvars_
}
//validates the pointer.
numverts = (prinst->stringtablesize - vertsptr) / sizeof(qcvertex_t);
if (numverts < 1 || vertsptr <= 0 || vertsptr+numverts*sizeof(qcvertex_t) > prinst->stringtablesize)
maxverts = (prinst->stringtablesize - vertsptr) / sizeof(qcvertex_t);
if (maxverts < 1 || vertsptr <= 0 || vertsptr+maxverts*sizeof(qcvertex_t) > prinst->stringtablesize)
{
PR_BIError(prinst, "PF_R_AddTrisoup: invalid vertexes pointer\n");
return;
@ -1886,6 +1912,8 @@ void QCBUILTIN PF_R_AddTrisoup_Simple(pubprogfuncs_t *prinst, struct globalvars_
{
R2D_Flush();
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++)
{
j = *idx++;
if (j >= numverts)
if (j >= maxverts)
j = 0; //out of bounds.
VectorCopy(vert[j].xyz, cl_strisvertv[cl_numstrisvert]);
@ -3026,6 +3054,23 @@ static void QCBUILTIN PF_cs_pointcontents(pubprogfuncs_t *prinst, struct globalv
else
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)
{
@ -3791,6 +3836,64 @@ static void cs_set_input_state (usercmd_t *cmd)
VectorCopy(cmd->cursor_impact, csqcg.input_cursor_trace_endpos);
if (csqcg.input_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)
@ -3829,6 +3932,63 @@ static void cs_get_input_state (usercmd_t *cmd)
VectorCopy(csqcg.input_cursor_trace_endpos, cmd->cursor_impact);
if (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)
@ -4492,13 +4652,15 @@ static void QCBUILTIN PF_checkextension (pubprogfuncs_t *prinst, struct globalva
if (!QSG_Extensions[i].name)
continue;
if (i < 32 && cls.protocol == CP_QUAKEWORLD)
if (!(cls.fteprotocolextensions & (1<<i)))
continue;
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;
}
}
@ -6136,15 +6298,25 @@ static void QCBUILTIN PF_cs_getplayerstat(pubprogfuncs_t *prinst, struct globalv
break;
case ev_integer:
case ev_uint:
case ev_field: //Hopefully NOT useful, certainly not reliable
case ev_function: //Hopefully NOT useful
case ev_pointer: //NOT useful in a networked capacity.
G_INT(OFS_RETURN) = cl.players[playernum].stats[statnum];
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:
G_FLOAT(OFS_RETURN) = cl.players[playernum].statsf[statnum];
break;
case ev_double: //lame truncation for network.
G_DOUBLE(OFS_RETURN) = cl.players[playernum].statsf[statnum];
break;
case ev_vector:
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];
@ -6573,7 +6745,7 @@ static struct {
{"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)
//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)
{"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)
@ -6618,6 +6790,7 @@ static struct {
//40
{"checkbottom", PF_checkbottom, 40}, // #40 float(entity e) checkbottom (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
{"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)
@ -7595,7 +7768,7 @@ static qboolean CSQC_ValidateMainCSProgs(void *file, size_t filesize, unsigned i
return false;
if (cls.protocol == CP_NETQUAKE && !(cls.fteprotocolextensions2 & PEXT2_PREDINFO))
{ //DP uses really lame checksums.
if (QCRC_Block(file, filesize) != checksum)
if (CalcHashInt(&hash_crc16, file, filesize) != checksum)
return false;
}
else
@ -8265,7 +8438,7 @@ void PR_CSExtensionList_f(void)
int i;
int ebi;
int bi;
lh_extension_t *extlist;
qc_extension_t *extlist;
#define SHOW_ACTIVEEXT 1
#define SHOW_ACTIVEBI 2

View File

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

View File

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

View File

@ -304,6 +304,7 @@ void R2D_Init(void)
"rgbgen vertex\n"
"alphagen vertex\n"
"blendfunc blend\n"
"maskalpha\n"
"}\n"
"}\n");
shader_contrastup = R_RegisterShader("contrastupshader", SUF_NONE,
@ -315,6 +316,7 @@ void R2D_Init(void)
"blendfunc gl_dst_color gl_one\n"
"rgbgen vertex\n"
"alphagen vertex\n"
"maskalpha\n"
"}\n"
"}\n"
);
@ -327,6 +329,7 @@ void R2D_Init(void)
"blendfunc gl_dst_color gl_zero\n"
"rgbgen vertex\n"
"alphagen vertex\n"
"maskalpha\n"
"}\n"
"}\n"
);
@ -339,6 +342,7 @@ void R2D_Init(void)
"blendfunc gl_one gl_one\n"
"rgbgen vertex\n"
"alphagen vertex\n"
"maskalpha\n"
"}\n"
"}\n"
);
@ -349,6 +353,7 @@ void R2D_Init(void)
"{\n"
"map $currentrender\n"
"nodepthtest\n"
"maskalpha\n"
"}\n"
"}\n"
);
@ -360,6 +365,7 @@ void R2D_Init(void)
"blendfunc gl_src_alpha gl_one_minus_src_alpha\n"
"rgbgen vertex\n"
"alphagen vertex\n"
"maskalpha\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_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_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_maxdecals = CVAR("r_part_maxdecals", "8192");
@ -669,6 +670,7 @@ void P_InitParticleSystem(void)
Cvar_Register(&r_part_density, particlecvargroupname);
Cvar_Register(&r_part_classic_expgrav, particlecvargroupname);
Cvar_Register(&r_part_classic_opaque, particlecvargroupname);
Cvar_Register(&r_part_classic_square, 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
===============
*/
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 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;
lm->modified = true;
if (lm->hasdeluxe && currentmodel->deluxdata)
if (lm->hasdeluxe && model->deluxdata)
{
lightmapinfo_t *dlm = lightmap[surf->lightmaptexturenums[map]+1];
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;
Surf_BuildDeluxMap(currentmodel, surf, deluxedest, dlm, blocknormals);
Surf_BuildDeluxMap(model, surf, deluxedest, dlm, blocknormals);
}
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*/
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
if (src)
{
if (currentmodel->fromgame == fg_quake3)
if (model->fromgame == fg_quake3)
Sys_Error("Surf_BuildLightMap: q3bsp");
switch(currentmodel->lightmaps.fmt)
switch(model->lightmaps.fmt)
{
case LM_E5BGR9:
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.
for (i=0 ; i<size ; i++)
blocklights[i] = 255*256;
@ -1613,7 +1613,7 @@ static void Surf_BuildLightMap (model_t *currentmodel, msurface_t *surf, int map
// add all the lightmaps
if (src)
{
switch(currentmodel->lightmaps.fmt)
switch(model->lightmaps.fmt)
{
case LM_E5BGR9:
for (maps = 0 ; maps < MAXCPULIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ; maps++)
@ -2699,7 +2699,7 @@ void Surf_SetupFrame(void)
vec3_t temp, pvsorg;
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_AnimateLight();
@ -3374,7 +3374,7 @@ void Surf_DrawWorld (void)
Surf_LightmapShift(currentmodel);
#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;
vec_t bestdist = FLT_MAX;
@ -3608,16 +3608,13 @@ void Surf_DrawWorld (void)
Surf_PushChains(currentmodel->batches);
#ifdef TERRAIN
if (currentmodel->type == mod_heightmap)
if (currentmodel->type != mod_brush)
{
frustumvis = NULL;
entvis = surfvis = NULL;
}
else
#endif
#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];
if (vis->buffersize < currentmodel->pvsbytes)
@ -3656,25 +3653,22 @@ void Surf_DrawWorld (void)
surfvis = frustumvis;
}
else
#endif
#ifdef MAP_PROC
if (currentmodel->fromgame == fg_doom3)
else if (currentmodel->fromgame == fg_doom3)
{
entvis = surfvis = D3_CalcVis(currentmodel, r_origin);
}
else
#endif
#ifdef MAP_DOOM
if (currentmodel->fromgame == fg_doom)
else if (currentmodel->fromgame == fg_doom)
{
entvis = surfvis = NULL;
R_DoomWorld();
}
else
#endif
#ifdef Q1BSPS
if (1)
else if (1)
{
//extern cvar_t temp1;
// if (0)//temp1.value)
@ -3699,8 +3693,8 @@ void Surf_DrawWorld (void)
surfvis = frustumvis;
}
}
else
#endif
else
{
frustumvis = NULL;
entvis = surfvis = NULL;
@ -4533,7 +4527,7 @@ TRACE(("dbg: Surf_NewMap: tp\n"));
VectorCopy(mins, 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_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_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_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",
@ -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_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_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_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;
@ -741,7 +743,7 @@ void R_ToggleFullscreen_f(void)
if (currentrendererstate.renderer->rtype == QR_HEADLESS || currentrendererstate.renderer->rtype == QR_NONE)
return;
Cvar_ApplyLatches(CVAR_VIDEOLATCH|CVAR_RENDERERLATCH);
Cvar_ApplyLatches(CVAR_VIDEOLATCH|CVAR_RENDERERLATCH, false);
newr = currentrendererstate;
if (newr.fullscreen)
@ -834,6 +836,7 @@ void Renderer_Init(void)
Cvar_Register (&vid_fullscreen, VIDCOMMANDGROUP);
Cvar_Register (&vid_bpp, VIDCOMMANDGROUP);
Cvar_Register (&vid_depthbits, VIDCOMMANDGROUP);
Cvar_Register (&vid_conwidth, VIDCOMMANDGROUP);
Cvar_Register (&vid_conheight, VIDCOMMANDGROUP);
@ -1097,7 +1100,7 @@ qboolean Renderer_Started(void)
void Renderer_Start(void)
{
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
//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].ri = ri;
R_UpdateRendererOpts();
return true;
}
}
@ -1586,15 +1590,15 @@ qboolean R_ApplyRenderer_Load (rendererstate_t *newr)
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;
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;
data = colormap + j*256;
vid.fullbright = 0;
@ -1959,7 +1963,7 @@ void R_ReloadRenderer_f (void)
}
#endif
Cvar_ApplyLatches(CVAR_VIDEOLATCH|CVAR_RENDERERLATCH);
Cvar_ApplyLatches(CVAR_VIDEOLATCH|CVAR_RENDERERLATCH, false);
R_ShutdownRenderer(false);
Con_DPrintf("teardown = %f\n", Sys_DoubleTime() - time);
//reloads textures without destroying video context.
@ -2006,6 +2010,7 @@ qboolean R_BuildRenderstate(rendererstate_t *newr, char *rendererstring)
newr->triplebuffer = vid_triplebuffer.value;
newr->multisample = vid_multisample.value;
newr->bpp = vid_bpp.value;
newr->depthbits = vid_depthbits.value;
newr->fullscreen = vid_fullscreen.value;
newr->rate = vid_refreshrate.value;
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_height.name, vid_height.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_renderer.name, vid_renderer.string);
Con_Printf("%s: %s\n", gl_driver.name, gl_driver.string);
@ -2332,7 +2338,7 @@ void R_RestartRenderer_f (void)
double time;
rendererstate_t newr;
Cvar_ApplyLatches(CVAR_VIDEOLATCH|CVAR_RENDERERLATCH);
Cvar_ApplyLatches(CVAR_VIDEOLATCH|CVAR_RENDERERLATCH, false);
if (!R_BuildRenderstate(&newr, 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);
}
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)
{
int i;
@ -2371,12 +2405,15 @@ void R_SetRenderer_f (void)
{
rendererinfo_t *r = sorted[i].r;
if (r && r->description)
Con_Printf("^[%s\\type\\/setrenderer %s^]^7: %s%s\n", r->name[0], r->name[0], r->description, (currentrendererstate.renderer == r)?" ^2(current)":"");
{
if (!r->VID_EnumerateDevices || !r->VID_EnumerateDevices(r, R_EnumeratedRenderer))
R_EnumeratedRenderer(r, "", "", r->description);
}
}
return;
}
Cvar_ApplyLatches(CVAR_VIDEOLATCH|CVAR_RENDERERLATCH);
Cvar_ApplyLatches(CVAR_VIDEOLATCH|CVAR_RENDERERLATCH, false);
if (!R_BuildRenderstate(&newr, param))
{
Con_Printf("setrenderer: parameter not supported (%s)\n", param);
@ -2395,11 +2432,32 @@ void R_SetRenderer_f (void)
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;
struct sortedrenderers_s sorted[countof(rendererinfo)];
if (!rendereroptsupdated)
return; //multiple got queued...
rendereroptsupdated = false;
for (i = 0; i < countof(sorted); i++)
{
sorted[i].index = i;
@ -2409,7 +2467,7 @@ static void R_UpdateRendererOpts(void)
qsort(sorted, countof(sorted), sizeof(sorted[0]), R_SortRenderers);
v = NULL;
e.v = NULL;
for (i = 0; i < countof(rendererinfo); i++)
{
rendererinfo_t *r = sorted[i].r;
@ -2417,12 +2475,20 @@ static void R_UpdateRendererOpts(void)
{
if (r->rtype == QR_HEADLESS || r->rtype == QR_NONE)
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);
vid_renderer_opts.enginevalue = v;
Cvar_SetEngineDefault(&vid_renderer_opts, e.v?e.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_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_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 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_showfrags, "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_backgroundalpha, "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); \
} \
},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_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)
@ -3326,7 +3329,7 @@ ping time frags name
//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
{
@ -3458,6 +3461,10 @@ void Sbar_DeathmatchOverlay (playerview_t *pv, int start)
{
COLUMN_TOUCHES
}
if (scr_scoreboard_showruleset.ival && (scr_scoreboard_showruleset.ival==2||Ruleset_GetRulesetName()))
{
COLUMN_RULESET
}
COLUMN_AFK
#undef COLUMN

View File

@ -57,7 +57,7 @@ qboolean snd_initialized = false;
int snd_speed;
float voicevolumemod = 1;
static struct
static struct listener_s
{
int entnum;
vec3_t origin;
@ -3884,6 +3884,7 @@ static void S_UpdateCard(soundcardinfo_t *sc)
//
if (snd_show.ival)
{
struct listener_s *l;
int active, mute;
active = 0;
mute = 0;
@ -3900,7 +3901,11 @@ static void S_UpdateCard(soundcardinfo_t *sc)
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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

@ -75,7 +75,10 @@ typedef struct
} pxrect_t;
//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_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

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.
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.
}
@ -2034,7 +2034,7 @@ void R_DrawNameTags(void)
#endif
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)
{
shader_t *shader = surf->texinfo->texture->shader;
@ -2703,6 +2703,7 @@ void V_Init (void)
Cvar_Register (&r_projection, VIEWVARS);
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_contrast, 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 (*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 (*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);
#define plugvrfuncs_name "VR"
} 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 != 2 || QCRC_Block(lump, 128*128) == 798)
if (con_ocranaleds.ival != 2 || CalcHashInt(&hash_crc16, lump, 128*128) == 798)
AddOcranaLEDsIndexed (lump, 128, 128);
}

View File

@ -866,6 +866,17 @@ static char *Macro_TF_Skin (void)
}
//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)
{
playerview_t *pv = &cl.playerview[SP];
@ -1271,7 +1282,7 @@ static char *Macro_Match_Status(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 "---";
}
static char *Macro_MP3Info(void)
@ -1331,6 +1342,7 @@ static void TP_InitMacros(void)
Cmd_AddMacro("powerups", Macro_Powerups, true);
Cmd_AddMacro("droppedweapon", Macro_DroppedWeapon, true);
Cmd_AddMacro("tf_skin", Macro_TF_Skin, true);
Cmd_AddMacro("team", Macro_Team, true); //confusing
Cmd_AddMacro("deathloc", Macro_LastDeath, true);
Cmd_AddMacro("tookatloc", Macro_TookAtLoc, true);
@ -1897,7 +1909,7 @@ static void TP_MsgTrigger_f (void)
}
if (c >= 3) {
if (strlen(Cmd_Argv(2)) > 63) {
if (strlen(Cmd_Argv(2)) >= countof(trig->string)) {
Com_Printf ("trigger string too long\n");
return;
}
@ -1935,6 +1947,9 @@ void TP_SearchForMsgTriggers (char *s, int level)
if (cls.demoplayback)
return;
if (!ruleset_allow_triggers.ival)
return;
for (t=msg_triggers; t; t=t->next)
if ((t->level == level || (t->level == 3 && level == 4))
&& 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
/*
=============================================================================

View File

@ -1130,4 +1130,25 @@ STAT_MOVEVARS_AIRACCEL_SIDEWAYS_FRICTION = 255, // DP
#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

View File

@ -76,7 +76,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
typedef struct
{
int fileofs, filelen;
unsigned int fileofs, filelen;
} lump_t;
#define LUMP_ENTITIES 0
@ -160,23 +160,28 @@ typedef struct
} dplane_t;
#define Q1CONTENTS_EMPTY -1
#define Q1CONTENTS_SOLID -2
#define Q1CONTENTS_WATER -3
#define Q1CONTENTS_SLIME -4
#define Q1CONTENTS_LAVA -5
#define Q1CONTENTS_SKY -6
#define Q1CONTENTS_STRIPPED -7 /*not known to engine*/
#define Q1CONTENTS_CLIP -8 /*solid to players*/
#define Q1CONTENTS_FLOW_1 -9 /*moves player*/
#define Q1CONTENTS_FLOW_2 -10 /*moves player*/
#define Q1CONTENTS_FLOW_3 -11 /*moves player*/
#define Q1CONTENTS_FLOW_4 -12 /*moves player*/
#define Q1CONTENTS_FLOW_5 -13 /*moves player*/
#define Q1CONTENTS_FLOW_6 -14 /*moves player*/
#define Q1CONTENTS_TRANS -15 /*should be solid I guess*/
#define Q1CONTENTS_LADDER -16 /*player can climb up/down*/
enum q1contents_e
{ //q1 and halflife bsp contents values.
//also used for .skin for content forcing.
Q1CONTENTS_EMPTY = -1,
Q1CONTENTS_SOLID = -2,
Q1CONTENTS_WATER = -3,
Q1CONTENTS_SLIME = -4,
Q1CONTENTS_LAVA = -5,
Q1CONTENTS_SKY = -6,
//#define Q1CONTENTS_ORIGIN -7 /*not known to engine - origin or something*/
Q1CONTENTS_CLIP = -8, /*solid to players+monsters, but not tracelines*/
Q1CONTENTS_CURRENT_0 = -9, /*moves player*/
Q1CONTENTS_CURRENT_90 = -10, /*moves player*/
Q1CONTENTS_CURRENT_180 = -11, /*moves player*/
Q1CONTENTS_CURRENT_270 = -12, /*moves player*/
Q1CONTENTS_CURRENT_UP = -13, /*moves player*/
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 !!!
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 "com_bih.h"
#include "com_mesh.h"
#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_nomipmap = CVARD ("mod_nomipmap", "0", "Disables the use of mipmaps on quake1 mdls, consistent with its original software renderer.");
#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)
{
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
//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
//we've got to have this bit
if (mod->engineflags & MDLF_DOCRC)
{
unsigned short crc;
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);
unsigned int crc = CalcHashInt(&hash_crc16, buffer, buffersize);
if (!(mod->engineflags & MDLF_PLAYER))
{ //eyes
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
}
@ -2649,6 +2647,69 @@ static qboolean Mod_Trace(model_t *model, int forcehullnum, const framestate_t *
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)
{
@ -8345,8 +8406,8 @@ static galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, const char *buffer, siz
AddPointToBounds(maxs, mod->mins, mod->maxs);
}
}
else
AddPointToBounds(vec3_origin, mod->mins, mod->maxs);
ftemesh = IQM_FindExtension(buffer, fsize, "FTE_MESH", 0, &extsize);
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 += firsttri;
gai[i].numindexes = numtris*3;
idx = ZG_Malloc(&mod->memgroup, sizeof(*idx)*gai[i].numindexes);
idx = ZG_Malloc(&mod->memgroup, sizeof(*idx)*numtris*3);
gai[i].ofs_indexes = idx;
for (t = 0; t < numtris; t++)
{
*idx++ = LittleLong(tris[t].vertex[0]) - firstvert;
*idx++ = LittleLong(tris[t].vertex[1]) - firstvert;
*idx++ = LittleLong(tris[t].vertex[2]) - firstvert;
unsigned int a,b,c;
a = LittleLong(tris[t].vertex[0]) - 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*/
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, &vpos, (float*)opos, sizeof(opos[0])/sizeof(float), h->num_vertexes, defaultvert);
//fixme: shouldn't really be needed for an animated model
for (i = 0; i < h->num_vertexes; i++)
AddPointToBounds(opos[i], mod->mins, mod->maxs);
if (!h->ofs_bounds || !h->num_frames)
for (i = 0; i < h->num_vertexes; i++)
AddPointToBounds(opos[i], mod->mins, mod->maxs);
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->meshinfo = root;
mod->type = mod_alias;
mod->funcs.NativeTrace = Mod_Trace;
Mod_SetMeshModelFuncs(mod, !root->ofs_skel_idx&&!root->ofs_skel_weight);
return true;
}
@ -9346,7 +9415,7 @@ struct objattrib_s {
size_t maxlength;
float *data;
};
static qboolean parseobjvert(char *s, struct objattrib_s *out)
static qboolean parseobjvert(char *s, struct objattrib_s *out, int reorient)
{
int i;
float *v;
@ -9368,6 +9437,23 @@ static qboolean parseobjvert(char *s, struct objattrib_s *out)
}
for (; i < 3; i++)
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;
}
@ -9395,6 +9481,7 @@ static galiasinfo_t *Obj_FinishFace(model_t *mod, galiasinfo_t *m, struct objatt
Vector2Clear(m->ofs_st_array[i]);
else
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)
{
@ -9437,6 +9524,7 @@ static qboolean QDECL Mod_LoadObjModel(model_t *mod, void *buffer, size_t fsize)
qboolean badinput = false;
int meshidx = 0;
int reorient = mod_obj_orientation.ival;
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 'v':
if(isspace(c[1])) badinput |= !parseobjvert(c, &attrib[0]);
else if(c[1]=='t') badinput |= !parseobjvert(c, &attrib[1]);
else if(c[1]=='n') badinput |= !parseobjvert(c, &attrib[2]);
if(isspace(c[1])) badinput |= !parseobjvert(c, &attrib[0], reorient);
else if(c[1]=='t') badinput |= !parseobjvert(c, &attrib[1], false);
else if(c[1]=='n') badinput |= !parseobjvert(c, &attrib[2], reorient);
break;
case 'g':
{
@ -9480,12 +9568,15 @@ static qboolean QDECL Mod_LoadObjModel(model_t *mod, void *buffer, size_t fsize)
namelen = strlen(name);
while(namelen > 0 && isspace(name[namelen-1])) namelen--;
Z_Free(matname);
matname = Z_Malloc(namelen+1);
memcpy(matname, name, namelen);
matname[namelen] = 0;
if (!matname || strncmp(matname, name, namelen)||matname[namelen])
{
Z_Free(matname);
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;
}
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));
}
elem[numelems++] = cur;
elem[numelems++] = prev;
elem[numelems++] = first;
if (reorient == 1)
{
elem[numelems++] = first;
elem[numelems++] = prev;
elem[numelems++] = cur;
}
else
{
elem[numelems++] = cur;
elem[numelems++] = prev;
elem[numelems++] = first;
}
}
prev = cur;
v++;
@ -9621,7 +9721,9 @@ static qboolean QDECL Mod_LoadObjModel(model_t *mod, void *buffer, size_t fsize)
mod->flags = 0;
mod->type = mod_alias;
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;
}
#endif
@ -9670,6 +9772,7 @@ void Alias_Register(void)
#endif
#ifdef MODELFMT_OBJ
Mod_RegisterModelFormatText(NULL, "Wavefront Object (obj)", ".obj", Mod_LoadObjModel);
Cvar_Register(&mod_obj_orientation, NULL);
#endif
#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);
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 Mod_AccumulateMeshTextureVectors(mesh_t *mesh);

View File

@ -56,21 +56,7 @@ fte_inlinebody float M_LinearToSRGB(float x, float mag);
#endif
#endif
/*
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
const usercmd_t nullcmd; // guarenteed to be zero
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[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)
{
qbyte *buf;
buf = (qbyte*)SZ_GetSpace (sb, 8);
buf[0] = c&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>>52)&0xff;
{ //move the sign bit into the low bit and avoid sign extension for more efficient length coding.
if (c < 0)
MSG_WriteUInt64(sb, ((quint64_t)(-1-c)<<1)|1);
else
MSG_WriteUInt64(sb, c<<1);
}
void MSG_WriteFloat (sizebuf_t *sb, float f)
@ -947,12 +941,21 @@ void MSG_WriteDouble (sizebuf_t *sb, double f)
{
union
{
double f;
qint64_t l;
} dat;
double f;
quint64_t l;
} dat = {f};
quint64_t c = dat.l;
qbyte *buf;
dat.f = f;
MSG_WriteInt64(sb, dat.l);
buf = (qbyte*)SZ_GetSpace (sb, 8);
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)
@ -1154,7 +1157,7 @@ void MSG_WriteEntity(sizebuf_t *sb, unsigned int entnum)
else
MSG_WriteShort(sb, entnum);
}
static unsigned int MSG_ReadBigEntity(void)
unsigned int MSG_ReadBigEntity(void)
{
unsigned int num;
num = MSG_ReadShort();
@ -1197,7 +1200,420 @@ unsigned int MSGCL_ReadEntity(void)
}
#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;
@ -1207,102 +1623,7 @@ void MSG_WriteDeltaUsercmd (sizebuf_t *buf, usercmd_t *from, usercmd_t *cmd)
bits = 0;
#if defined(Q2CLIENT) && defined(HAVE_CLIENT)
if (cls_state && cls.protocol == CP_QUAKE2)
{
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);
}
MSGQ2_WriteDeltaUsercmd(buf, from, cmd);
else
#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
@ -1611,35 +1946,28 @@ int MSG_ReadLong (void)
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 c;
if (net_message.packing!=SZ_RAWBYTES)
{
c = (unsigned int)MSG_ReadBits(32)
| ((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;
{ //we do some fancy bit recoding for more efficient length coding.
quint64_t c = MSG_ReadUInt64();
if (c&1)
return -1-(qint64_t)(c>>1);
else
return (qint64_t)(c>>1);
}
float MSG_ReadFloat (void)
@ -1675,14 +2003,30 @@ float MSG_ReadFloat (void)
return dat.f;
}
double MSG_ReadDouble (void)
{ //type-pun it as an int64 over the network for easier handling of endian.
{
union
{
double d;
qint64_t l;
quint64_t l;
double f;
} 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)
@ -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;
@ -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;
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--)
;
if (dot < in)
if (dot < in || *dot != '.')
{
*result = 0;
return result;
@ -6258,18 +6602,20 @@ size_t Base16_EncodeBlock(const char *in, size_t length, qbyte *out, size_t outs
/*
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",
"team",
"skin",
"topcolor",
"bottomcolor",
"chat", //ezquake's afk indicators
NULL};
const char *privateuserinfos[] =
NULL
};
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.
"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.
@ -7529,7 +7875,7 @@ qbyte COM_BlockSequenceCRCByte (qbyte *base, int length, int sequence)
length += 4;
crc = QCRC_Block(chkb, length);
crc = CalcHashInt(&hash_crc16, chkb, length);
crc &= 0xff;
@ -7637,7 +7983,7 @@ qbyte Q2COM_BlockSequenceCRCByte (qbyte *base, int length, int sequence)
length += 4;
crc = QCRC_Block(chkb, length);
crc = CalcHashInt(&hash_crc16, chkb, length);
for (x=0, n=0; n<length; n++)
x += chkb[n];

View File

@ -261,7 +261,7 @@ void COM_SwapLittleShortBlock (short *s, int size);
struct usercmd_s;
extern struct usercmd_s nullcmd;
extern const struct usercmd_s nullcmd;
typedef union { //note: reading from packets can be misaligned
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_WriteLong (sizebuf_t *sb, int 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_WriteFloat (sizebuf_t *sb, float 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_WriteAngle8 (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);
extern int msg_readcount;
@ -303,9 +306,11 @@ int MSG_ReadByte (void);
int MSG_ReadShort (void);
int MSG_ReadLong (void);
qint64_t MSG_ReadInt64 (void);
quint64_t MSG_ReadUInt64 (void);
struct client_s;
unsigned int MSGSV_ReadEntity (struct client_s *fromclient);
unsigned int MSGCL_ReadEntity (void);
unsigned int MSG_ReadBigEntity(void);
float MSG_ReadFloat (void);
double MSG_ReadDouble (void);
char *MSG_ReadStringBuffer (char *out, size_t outsize);
@ -317,8 +322,9 @@ float MSG_ReadCoordFloat (void);
void MSG_ReadPos (float *pos);
float MSG_ReadAngle (void);
float MSG_ReadAngle16 (void);
void MSG_ReadDeltaUsercmd (struct usercmd_s *from, struct usercmd_s *cmd, int qwprotocolver);
void MSGQ2_ReadDeltaUsercmd (struct usercmd_s *from, struct usercmd_s *move);
void MSGQW_ReadDeltaUsercmd (const struct usercmd_s *from, struct usercmd_s *cmd, int qwprotocolver);
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_ReadSkip (int len);
@ -583,10 +589,11 @@ typedef struct vfsfile_s
#define VFS_ERROR_TRYLATER 0 //nothing to write/read yet.
#define VFS_ERROR_UNSPECIFIED -1 //no reason given
#define VFS_ERROR_NORESPONSE -2 //no reason given
#define VFS_ERROR_EOF -3 //no reason given
#define VFS_ERROR_DNSFAILURE -4 //weird one, but oh well
#define VFS_ERROR_WRONGCERT -5 //server gave a certificate with the wrong name
#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_REFUSED -3 //no reason given
#define VFS_ERROR_EOF -4 //no reason given
#define VFS_ERROR_DNSFAILURE -5 //weird one, but oh well
#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_TELL(vf) ((vf)->Tell(vf))
@ -679,8 +686,8 @@ typedef struct
enum
{
MANIFEST_SECURITY_NOT, //don't trust it, don't even allow downloadsurl.
MANIFEST_SECURITY_DEFAULT, //the default.fmf file may suggest packages
MANIFEST_SECURITY_INSTALLER //built-in fmf files can force packages
MANIFEST_SECURITY_DEFAULT, //the default.fmf file may suggest packages+force sources
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)
enum
@ -779,6 +786,7 @@ qboolean COM_LoadMapPackFile(const char *name, qofs_t offset);
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);
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 struct cvar_s registered;
@ -893,9 +901,12 @@ extern hashfunc_t hash_sha224;
extern hashfunc_t hash_sha256;
extern hashfunc_t hash_sha384;
extern hashfunc_t hash_sha512;
#define HMAC HMAC_quake //stop conflicts...
size_t CalcHash(hashfunc_t *hash, unsigned char *digest, size_t maxdigestsize, const unsigned char *string, size_t stringlen);
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);
extern hashfunc_t hash_crc16;
extern hashfunc_t hash_crc16_lower;
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);
char *version_string(void);

View File

@ -20,7 +20,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
/* crc.c */
#include "quakedef.h"
#include "crc.h"
#include <ctype.h>
// 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
};
void QCRC_Init(unsigned short *crcvalue)
static void CRC16_Init (void *context)
{
*crcvalue = QCRC_INIT_VALUE;
unsigned short *ctx = context;
*ctx = QCRC_INIT_VALUE;
}
void QCRC_ProcessByte(unsigned short *crcvalue, qbyte data)
static void CRC16_Update (void *context, const void *data, size_t datasize)
{
*crcvalue = ((*crcvalue << 8)&0xffff) ^ crctable[(*crcvalue >> 8) ^ data];
}
unsigned short QCRC_Value(unsigned short crcvalue)
{
return crcvalue ^ QCRC_XOR_VALUE;
}
unsigned short QCRC_Block (const qbyte *start, int count)
{
unsigned short crc;
QCRC_Init (&crc);
while (count--)
unsigned short *ctx = context;
unsigned short crc = *ctx;
const char *start = data;
while (datasize --> 0)
crc = ((crc << 8) & 0xffff) ^ crctable[(crc >> 8) ^ *start++];
return crc;
*ctx = crc;
}
unsigned short QCRC_Block_AsLower (const qbyte *start, int count)
static void CRC16_Finish (unsigned char *digest, void *context)
{
unsigned short crc;
QCRC_Init (&crc);
while (count--)
crc = (crc << 8) ^ crctable[(crc >> 8) ^ tolower(*start++)];
return crc;
unsigned short *ctx = context;
unsigned short crc = *ctx ^ QCRC_XOR_VALUE;
digest[0] = (crc>>0)&0xff; //digest should be the same regardless of endian. spit it out as little endian.
digest[1] = (crc>>8)&0xff;
}
void QCRC_AddBlock (unsigned short *crcvalue, const qbyte *start, int count)
hashfunc_t hash_crc16 =
{
while (count--)
QCRC_ProcessByte(crcvalue, *start++);
2,
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";
case CVAR_NOSET:
return "noset";
case CVAR_LATCH:
case CVAR_MAPLATCH:
return "latch";
case CVAR_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)
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";
// else if (var->flags & CVAR_LATCHFLUSH)
// 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;
}
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;
char *latch;
var->flags &= ~flag;
var->flags &= ~newflag;
latch = var->latched_string;
var->latched_string = NULL;
if (!latch)
@ -1033,10 +1033,11 @@ qboolean Cvar_ApplyLatchFlag(cvar_t *var, char *value, int flag)
latch = Z_StrDup(var->string);
// var->string = NULL;
}
#ifdef warningmsg
#pragma warningmsg("set or forceset?")
#endif
ignoreflags = var->flags & ignoreflags; //figure out which latching flags we're ignoring
var->flags -= ignoreflags; //and clear them
Cvar_ForceSet(var, value);
var->flags |= ignoreflags; //give them back.
if (var->latched_string)
{ //something else latched it
@ -1045,7 +1046,7 @@ qboolean Cvar_ApplyLatchFlag(cvar_t *var, char *value, int flag)
result = false;
}
else
var->flags |= flag;
var->flags |= newflag;
if (latch)
{
@ -1081,7 +1082,12 @@ void Cvar_ForceCheatVars(qboolean semicheats, qboolean absolutecheats)
if (var->flags & CVAR_CHEAT)
{
if (!absolutecheats)
Cvar_ForceSet(var, var->defaultstr);
{
if (var->enginevalue)
Cvar_ForceSet(var, var->enginevalue);
else
Cvar_ForceSet(var, var->defaultstr);
}
else
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;
cvar_group_t *grp;
@ -1113,7 +1119,7 @@ int Cvar_ApplyLatches(int latchflag)
int mask = ~0;
int of;
if (latchflag == CVAR_SERVEROVERRIDE || latchflag == CVAR_RULESETLATCH) //these ones are cleared
if (clearflag) //these flags are cleared from cvars.
mask = ~latchflag;
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
old = Cvar_FindVar (variable->name);
if (old && variable->name2)
if (!old && variable->name2)
old = Cvar_FindVar (variable->name2);
if (old)
{
@ -1419,7 +1425,7 @@ qboolean Cvar_Command (int level)
{
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 ("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
char *name;
char *string;
char *latched_string; // for CVAR_LATCH vars
char *latched_string; // for CVAR_LATCHMASK vars
unsigned int flags;
int modified; // increased each time the cvar is changed
float value;
@ -116,7 +116,7 @@ typedef struct cvar_group_s
#define CVAR_SERVERINFO (1<<2) // added to serverinfo when changed
#define CVAR_NOSET (1<<3) // don't allow change from console at all,
// 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
#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_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
//an alias
@ -166,7 +166,7 @@ void Cvar_ForceSetValue (cvar_t *var, float value);
void Cvar_SetValue (cvar_t *var, float value);
// 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);
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
void Cvar_ParseWatches(void); //parse -watch args
int Cvar_ApplyLatches(int latchflag);
//sets vars to their latched values
int Cvar_ApplyLatches(int latchflag, qboolean clearflag);
//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));
//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 COM_InitHomedir(ftemanifest_t *man);
hashtable_t filesystemhash;
qboolean com_fschanged = true;
static qboolean com_fschanged = true;
qboolean com_installer = false;
qboolean fs_readonly;
int waitingformanifest;
@ -24,20 +24,20 @@ static unsigned int fs_restarts;
void *fs_thread_mutex;
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);
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");
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.");
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 com_fs_cache = CVARF("fs_cache", IFMINIMAL("2","1"), CVAR_ARCHIVE);
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!");
static cvar_t cfg_reload_on_gamedir = CVAR("cfg_reload_on_gamedir", "1");
static 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_gamedir = CVARFD("fs_gamedir", "", 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.");
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;
static int fs_referencetype;
int fs_finds;
void COM_CheckRegistered (void);
void Mods_FlushModList(void);
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)
{
@ -52,7 +52,7 @@ static void QDECL fs_game_callback(cvar_t *var, char *oldvalue)
runaway = false;
}
struct
static struct
{
void *module;
const char *extension;
@ -169,16 +169,16 @@ void VARGS VFS_PRINTF(vfsfile_t *vf, const char *format, ...)
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;
searchpath_t *gameonly_gamedir;
static searchpath_t *gameonly_homedir;
static searchpath_t *gameonly_gamedir;
char com_gamepath[MAX_OSPATH]; //c:\games\quake
char com_homepath[MAX_OSPATH]; //c:\users\foo\my docs\fte\quake
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
@ -192,9 +192,9 @@ int fs_hash_files;
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);
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");}
@ -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.
static searchpath_t *com_searchpaths;
static searchpath_t *com_purepaths;
@ -2992,7 +2992,7 @@ static void FS_LoadWildDataFiles (filelist_t *list, wildpaks_t *wp)
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;
int j;
@ -3740,7 +3740,7 @@ typedef struct {
const char *downloadsurl;
const char *manifestfile;
} gamemode_info_t;
const gamemode_info_t gamemode_info[] = {
static const gamemode_info_t gamemode_info[] = {
#ifdef GAME_SHORTNAME
#ifndef GAME_PROTOCOL
#define GAME_PROTOCOL DISTRIBUTION
@ -5124,9 +5124,6 @@ void FS_Shutdown(void)
fs_thread_mutex = NULL;
Cvar_SetEngineDefault(&fs_gamename, NULL);
#ifdef PACKAGEMANAGER
Cvar_SetEngineDefault(&pkg_downloads_url, NULL);
#endif
Cvar_SetEngineDefault(&com_protocolname, NULL);
}
@ -5759,6 +5756,8 @@ qboolean FS_ChangeGame(ftemanifest_t *man, qboolean allowreloadconfigs, qboolean
fs_manifest = man;
#ifdef PACKAGEMANAGER
PM_Shutdown(true);
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.
Z_Free(man->downloadsurl);
@ -5956,31 +5955,27 @@ qboolean FS_ChangeGame(ftemanifest_t *man, qboolean allowreloadconfigs, qboolean
if (reloadconfigs)
{
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");
//FIXME: flag this instead and do it after a delay?
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);
#ifdef HAVE_CLIENT
vidrestart = false;
#endif
if (isDedicated)
{
#ifdef HAVE_SERVER
if (isDedicated)
SV_ExecInitialConfigs(man->defaultexec?man->defaultexec:"");
#endif
}
else
{
#ifdef HAVE_CLIENT
CL_ExecInitialConfigs(man->defaultexec?man->defaultexec:"");
#endif
#ifdef HAVE_CLIENT
if (1)
CL_ExecInitialConfigs(man->defaultexec?man->defaultexec:"");
else
#endif
{
COM_ParsePlusSets(true);
Cbuf_Execute ();
}
}
#ifdef HAVE_CLIENT
@ -6673,6 +6668,13 @@ static void FS_ChangeMod_f(void)
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"))
{
if (!packages)
@ -7069,7 +7071,6 @@ void COM_InitFilesystem (void)
Cvar_Register(&com_fs_cache, "Filesystem");
Cvar_Register(&fs_gamename, "Filesystem");
#ifdef PACKAGEMANAGER
Cvar_Register(&pkg_downloads_url, "Filesystem");
Cvar_Register(&pkg_autoupdate, "Filesystem");
#endif
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)
{
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)
{
{ //this is really weak. :(
pack_t *pak = (void*)handle;
int result;
@ -169,7 +169,7 @@ static int QDECL FSPAK_GeneratePureCRC(searchpathfuncs_t *handle, int seed, int
{
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;
int i;
// int j;
mpackfile_t *newfiles;
int numpackfiles;
pack_t *pack;
vfsfile_t *packhandle;
dpackfile_t info;
int read;
// unsigned short crc;
packhandle = file;
if (packhandle == NULL)
@ -341,22 +339,9 @@ searchpathfuncs_t *QDECL FSPAK_LoadArchive (vfsfile_t *file, searchpathfuncs_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));
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));
// parse the directory
@ -370,10 +355,7 @@ searchpathfuncs_t *QDECL FSPAK_LoadArchive (vfsfile_t *file, searchpathfuncs_t *
numpackfiles = i;
break;
}
/*
for (j=0 ; j<sizeof(info) ; j++)
CRC_ProcessByte(&crc, ((qbyte *)&info)[j]);
*/
memcpy(newfiles[i].name, info.name, sizeof(info.name));
newfiles[i].name[min(sizeof(info.name), MAX_QPATH-1)] = 0; //paranoid
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);
}
/*
if (crc != PAK0_CRC)
if (crc != PAK0_CRC || numpackfiles != PAK0_COUNT)
com_modified = true;
*/
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])
{
out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] +
in1[0][2] * in2[2][0];
out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] +
in1[0][2] * in2[2][1];
out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] +
in1[0][2] * in2[2][2];
out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] +
in1[1][2] * in2[2][0];
out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] +
in1[1][2] * in2[2][1];
out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] +
in1[1][2] * in2[2][2];
out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] +
in1[2][2] * in2[2][0];
out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] +
in1[2][2] * in2[2][1];
out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] +
in1[2][2] * in2[2][2];
out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] + in1[0][2] * in2[2][0];
out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] + in1[0][2] * in2[2][1];
out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] + in1[0][2] * in2[2][2];
out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] + in1[1][2] * in2[2][0];
out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] + in1[1][2] * in2[2][1];
out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] + in1[1][2] * in2[2][2];
out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] + in1[2][2] * in2[2][0];
out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] + in1[2][2] * in2[2][1];
out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] + in1[2][2] * in2[2][2];
}
/*
@ -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)
{
#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];
//load identity.
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(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)
@ -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])
{
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_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 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 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]);

View File

@ -276,7 +276,6 @@ typedef struct
extern int net_drop; // packets dropped before this one
void Net_Master_Init(void);
qboolean Net_AddressIsMaster(netadr_t *adr);
void Netchan_Init (void);
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);
qboolean Netchan_CanReliable (netchan_t *chan, int rate);
#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
#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_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_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.");
@ -221,6 +222,9 @@ unsigned int Net_PextMask(unsigned int protover, qboolean fornq)
if (pext_infoblobs.ival)
mask |= PEXT2_INFOBLOBS;
if (pext_vrinputs.ival)
mask |= PEXT2_VRINPUTS;
if (MAX_CLIENTS != QWMAX_CLIENTS)
mask |= PEXT2_MAXPLAYERS;
@ -232,7 +236,7 @@ unsigned int Net_PextMask(unsigned int protover, qboolean fornq)
if (fornq)
{
//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
// mask &= ~PEXT2_PREDINFO;
@ -270,6 +274,7 @@ void Netchan_Init (void)
Cvar_Register (&pext_predinfo, "Protocol Extensions");
Cvar_Register (&pext_replacementdeltas, "Protocol Extensions");
Cvar_Register (&pext_infoblobs, "Protocol Extensions");
Cvar_Register (&pext_vrinputs, "Protocol Extensions");
Cvar_Register (&showpackets, "Networking");
Cvar_Register (&showdrop, "Networking");
Cvar_Register (&qport, "Networking");
@ -432,7 +437,7 @@ qboolean ServerPaused(void);
#endif
#ifdef NQPROT
qboolean NQNetChan_Process(netchan_t *chan)
enum nqnc_packettype_e NQNetChan_Process(netchan_t *chan)
{
int header;
int sequence;
@ -443,10 +448,10 @@ qboolean NQNetChan_Process(netchan_t *chan)
header = LongSwap(MSG_ReadLong());
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)
return false; //huh?
return NQNC_IGNORED; //huh?
sequence = LongSwap(MSG_ReadLong());
@ -483,7 +488,7 @@ qboolean NQNetChan_Process(netchan_t *chan)
, sequence
, 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)
@ -492,7 +497,7 @@ qboolean NQNetChan_Process(netchan_t *chan)
{
if (showdrop.ival)
Con_Printf("Stale datagram recieved (%i<=%i)\n", sequence, chan->incoming_unreliable);
return false;
return NQNC_IGNORED;
}
drop = sequence - chan->incoming_unreliable - 1;
if (drop > 0)
@ -520,7 +525,7 @@ qboolean NQNetChan_Process(netchan_t *chan)
, chan->sock != NS_SERVER?"s2c":"c2s"
, chan->incoming_unreliable
, net_message.cursize);
return true;
return NQNC_UNRELIABLE;
}
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))
{
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);
@ -561,7 +566,7 @@ qboolean NQNetChan_Process(netchan_t *chan)
, chan->sock != NS_SERVER?"s2c":"c2s"
, sequence
, net_message.cursize);
return true; //we can read it now
return NQNC_RELIABLE; //we can read it now
}
}
else
@ -570,10 +575,10 @@ qboolean NQNetChan_Process(netchan_t *chan)
Con_Printf("Stale reliable (%i)\n", sequence);
}
return false;
return NQNC_IGNORED;
}
return false; //not supported.
return NQNC_IGNORED; //not supported.
}
#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[3] = ((buf.cursize+4+sizeof(integ)-20)>>0)&0xff;
//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(20)); //sha1 key length
SZ_Write(&buf, integ, sizeof(integ)); //integrity data
@ -1523,7 +1523,7 @@ qboolean ICE_WasStun(ftenet_connections_t *col)
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.
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)))
{
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[3] = ((buf.cursize+4+sizeof(integrity)-20)>>0)&0xff;
//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(sizeof(integrity))); //sha1 key length
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_NORESPONSE: eno = ECONNRESET; 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;
}
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_NORESPONSE: eno = ECONNRESET; break;
case VFS_ERROR_TRYLATER: eno = EAGAIN; break;
case VFS_ERROR_REFUSED: eno = ECONNREFUSED; break;
default: eno = ECONNRESET; break;
}
qgnutls_transport_set_errno(file->session, eno);

View File

@ -499,7 +499,44 @@ qboolean NET_CompareBaseAdr (netadr_t *a, netadr_t *b)
return false;
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;
}
if (a->type == NA_LOOPBACK)
return true;
@ -2332,7 +2369,10 @@ vfsfile_t *FS_OpenSSL(const char *peername, vfsfile_t *source, qboolean isserver
f = SSPI_OpenVFS(hostname, source, isserver);
#endif
if (!f) //it all failed.
{
Con_Printf("%s: no tls provider available\n", peername);
VFS_CLOSE(source);
}
return f;
}
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 *body = NULL; //response body
int method;
net_from = st->remoteaddr;
if (!strcmp(arg[WCATTR_METHOD], "GET"))
method = 0;
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
#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
#ifdef HAVE_SERVER
@ -8888,7 +8929,7 @@ int QDECL VFSTCP_ReadBytes (struct vfsfile_s *file, void *buffer, int bytestorea
break;
case NET_ECONNREFUSED:
Con_DPrintf("connection to \"%s\" refused\n", tf->peer);
tf->readaborted = VFS_ERROR_NORESPONSE;
tf->readaborted = VFS_ERROR_REFUSED;
break;
case NET_ECONNRESET:
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:
Con_Printf("connection to \"%s\" timed out\n", tf->peer);
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);
reason = len?VFS_ERROR_NORESPONSE:VFS_ERROR_EOF;
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:
#ifdef __unix__
case EPIPE:

View File

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

View File

@ -1222,7 +1222,7 @@ static void PM_NudgePosition (void)
vec3_t base;
int x, y, z;
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
//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++)
{
if (pmove.origin[i] >= 0)
base[i] = (qintptr_t)(pmove.origin[i]*8+0.5f) / 8.0;
if (pmove.velocity[i])
{ //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
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++)
@ -1256,6 +1266,8 @@ static void PM_NudgePosition (void)
// if (PM_TestPlayerPosition (pmove.origin, false))
// 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 (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
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_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_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_tempstringsize = CVARD("pr_tempstringsize", "4096", "Obsolete");
#ifdef MULTITHREAD
@ -1526,7 +1526,7 @@ void QCBUILTIN PF_FindList (pubprogfuncs_t *prinst, struct globalvars_s *pr_glob
ed = WEDICT_NUM_PB(prinst, e);
if (ED_ISFREE(ed))
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);
}
}
@ -1788,17 +1788,20 @@ void QCBUILTIN PF_memcpy (pubprogfuncs_t *prinst, struct globalvars_s *pr_global
else
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)
{
int dst = G_INT(OFS_PARM0);
int val = G_INT(OFS_PARM1);
int size = G_INT(OFS_PARM2);
if (size < 0 || size > prinst->stringtablesize)
PR_BIError(prinst, "PF_memcpy: invalid size\n");
else if (dst < 0 || dst+size > prinst->stringtablesize)
PR_BIError(prinst, "PF_memfill8: invalid dest\n");
int dstoffset = (prinst->callargc>3)?G_INT(OFS_PARM3):0;
void *ptr = PR_PointerToNative_Resize(prinst, dst, dstoffset, size);
if (ptr)
memset(ptr, val, size);
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)
@ -5291,9 +5294,9 @@ void QCBUILTIN PF_crc16 (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals
int len = strlen(str);
if (insens)
G_FLOAT(OFS_RETURN) = QCRC_Block_AsLower(str, len);
G_FLOAT(OFS_RETURN) = CalcHashInt(&hash_crc16_lower, str, len);
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)
@ -5319,10 +5322,7 @@ static void QCBUILTIN PF_digest_internal (pubprogfuncs_t *prinst, struct globalv
else if (!strcmp(hashtype, "SHA512"))
digestsize = CalcHash(&hash_sha512, digest, sizeof(digest), str, len);
else if (!strcmp(hashtype, "CRC16"))
{
digestsize = 2;
*(unsigned short*)digest = QCRC_Block(str, len);
}
digestsize = CalcHash(&hash_crc16, digest, sizeof(digest), str, len);
else
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)
{
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]);
VectorNegate(G_VECTOR(OFS_PARM1), src[1]);
VectorCopy(G_VECTOR(OFS_PARM2), src[2]);
VectorCopy(G_VECTOR(OFS_PARM0), base[0]);
VectorNegate(G_VECTOR(OFS_PARM1), base[1]);
VectorCopy(G_VECTOR(OFS_PARM2), base[2]);
VectorCopy(w->g.v_forward, src[0]);
VectorNegate(w->g.v_right, src[1]);
VectorCopy(w->g.v_up, src[2]);
VectorCopy(w->g.v_forward, trans[0]);
VectorNegate(w->g.v_right, trans[1]);
VectorCopy(w->g.v_up, trans[2]);
R_ConcatRotations(trans, src, res);
R_ConcatRotations(trans, base, res);
VectorCopy(res[0], w->g.v_forward);
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;
break;
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;
//case 2: //highres.. looks like time into the frame
//case 3: //uptime
@ -6788,12 +6788,15 @@ noflags:
{
switch(*s)
{
case 'h': isfloat = 1; break;
case 'l': isfloat = 0; break;
case 'L': isfloat = 0; break;
case 'j': break;
case 'z': break;
case 't': break;
case 'h': isfloat = 1; break; //short in C, interpreted as float here. doubled for char.
case 'l': isfloat = 0; break; //long, twice for long long... we interpret as int32.
case 'L': isfloat = 0; break; //'long double'
//case 'q': isfloat = 0; break; //synonym for long long.
case 'j': break; //intmax_t
//case 'Z': //synonym for 'z'. do not use
case 'z': break; //size_t
case 't': break; //ptrdiff_t
default:
goto nolength;
}
@ -6853,7 +6856,7 @@ nolength:
switch(*s)
{
case 'd': case 'i': case 'I':
case 'd': case 'i': case 'I':
if(precision < 0) // not set
Q_snprintfz(o, end - o, formatbuf, width, (isfloat ? (int) GETARG_FLOAT(thisarg) : (int) GETARG_INT(thisarg)));
else
@ -7414,70 +7417,69 @@ void PR_ProgsAdded(pubprogfuncs_t *prinst, int newprogs, const char *modulename)
QCLoadBreakpoints("", modulename);
}
#define NOBI 0, NULL, {NULL},
lh_extension_t QSG_Extensions[] = {
static qboolean check_pext_rpd (extcheck_t *extcheck, unsigned int pext1) {return (extcheck->pext1 & pext1) || (extcheck->pext2&PEXT2_REPLACEMENTDELTAS);}
//as a special hack, the first 32 entries are PEXT features.
//some of these are overkill yes, but they are all derived from the fteextensions flags and document the underlaying protocol available.
//(which is why there are two lists of extensions here)
//note: not all of these are actually supported. This list mearly reflects the values of the PEXT_ constants.
//Check protocol.h to make sure that the related PEXT is enabled. The engine will only accept if they are actually supported.
{"FTE_PEXT_SETVIEW", 0, NULL, {NULL}, "NQ's svc_setview works correctly even in quakeworld"},
{"DP_ENT_SCALE"}, //entities may be rescaled
{"FTE_PEXT_LIGHTSTYLECOL"}, //lightstyles may have colours.
{"DP_ENT_ALPHA"}, //transparent entites
{"FTE_PEXT_VIEW2"}, //secondary view.
{"FTE_PEXT_ACURATETIMINGS"}, //allows full interpolation
{"FTE_PEXT_SOUNDDBL"}, //twice the sound indexes
{"FTE_PEXT_FATNESS"}, //entities may be expanded along their vertex normals
{"DP_HALFLIFE_MAP"}, //entity can visit a hl bsp
{"FTE_PEXT_TE_BULLET"}, //additional particle effect. Like TE_SPIKE and TE_SUPERSPIKE
{"FTE_PEXT_HULLSIZE"}, //means we can tell a client to go to crouching hull
{"FTE_PEXT_MODELDBL"}, //max of 512 models
{"FTE_PEXT_ENTITYDBL"}, //max of 1024 ents
{"FTE_PEXT_ENTITYDBL2"}, //max of 2048 ents
{"FTE_PEXT_FLOATCOORDS"},
{"FTE_PEXT_VWEAP"},
{"FTE_PEXT_Q2BSP"}, //supports q2 maps. No bugs are apparent.
{"FTE_PEXT_Q3BSP"}, //quake3 bsp support. dp probably has an equivelent, but this is queryable per client.
{"DP_ENT_COLORMOD"},
{NULL}, //splitscreen - not queryable.
{"FTE_HEXEN2", 3, NULL, {"particle2", "particle3", "particle4"}}, //client can use hexen2 maps. server can use hexen2 progs
{"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)
{"FTE_PEXT_CUSTOMTENTS", 2, NULL, {"RegisterTempEnt", "CustomTempEnt"}},
{"FTE_PEXT_256PACKETENTITIES"}, //client is able to receive unlimited packet entities (server caps itself to 256 to prevent insanity).
{NULL},
{"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)
{"DP_GFX_QUAKE3MODELTAGS", 1, NULL, {"setattachment"}},
{"FTE_PK3DOWNLOADS"},
{"PEXT_CHUNKEDDOWNLOADS"},
static qboolean check_pext_setview (extcheck_t *extcheck) {return !!(extcheck->pext1 & PEXT_SETVIEW);}
static qboolean check_pext_scale (extcheck_t *extcheck) {return check_pext_rpd(extcheck,PEXT_SCALE);}
static qboolean check_pext_lightstylecol (extcheck_t *extcheck) {return !!(extcheck->pext1 & PEXT_LIGHTSTYLECOL);}
static qboolean check_pext_trans (extcheck_t *extcheck) {return check_pext_rpd(extcheck,PEXT_TRANS);}
static qboolean check_pext_view2 (extcheck_t *extcheck) {return !!(extcheck->pext1 & PEXT_VIEW2_);}
//static qboolean check_pext_scale (extcheck_t *extcheck) {return !!(extcheck->pext1 & PEXT_BULLETENS);}
//static qboolean check_pext_senttimings (extcheck_t *extcheck) {return check_pext_rpd(extcheck,PEXT_ACCURATETIMINGS);}
//static qboolean check_pext_sounddbl (extcheck_t *extcheck) {return !!(extcheck->pext1 & PEXT_SOUNDDBL);}
static qboolean check_pext_fatness (extcheck_t *extcheck) {return check_pext_rpd(extcheck,PEXT_FATNESS);}
//static qboolean check_pext_hlbsp (extcheck_t *extcheck) {return !!(extcheck->pext1 & PEXT_HLBSP);}
static qboolean check_pext_tebullet (extcheck_t *extcheck) {return !!(extcheck->pext1 & PEXT_TE_BULLET);}
//static qboolean check_pext_hullsize (extcheck_t *extcheck) {return check_pext_rpd(extcheck,PEXT_HULLSIZE);}
//static qboolean check_pext_modeldbl (extcheck_t *extcheck) {return check_pext_rpd(extcheck,PEXT_MODELDBL);}
//static qboolean check_pext_entitydbl (extcheck_t *extcheck) {return check_pext_rpd(extcheck,PEXT_ENTITYDBL);}
//static qboolean check_pext_entitydbl2 (extcheck_t *extcheck) {return check_pext_rpd(extcheck,PEXT_ENTITYDBL2);}
static qboolean check_pext_floatcoords (extcheck_t *extcheck) {return !!(extcheck->pext1 & PEXT_FLOATCOORDS);}
//static qboolean check_pext_vweap (extcheck_t *extcheck) {return !!(extcheck->pext1 & PEXT_VWEAP);}
static qboolean check_pext_q2bsp (extcheck_t *extcheck) {return !!(extcheck->pext1 & PEXT_Q2BSP_);}
static qboolean check_pext_q3bsp (extcheck_t *extcheck) {return !!(extcheck->pext1 & PEXT_Q3BSP_);}
static qboolean check_pext_colourmod (extcheck_t *extcheck) {return check_pext_rpd(extcheck,PEXT_COLOURMOD);}
//static qboolean check_pext_splitscreen (extcheck_t *extcheck) {return !!(extcheck->pext1 & PEXT_SPLITSCREEN);}
static qboolean check_pext_hexen2 (extcheck_t *extcheck) {return !!(extcheck->pext1 & PEXT_HEXEN2);}
static qboolean check_pext_spawnstatic (extcheck_t *extcheck) {return check_pext_rpd(extcheck,PEXT_SPAWNSTATIC2);}
static qboolean check_pext_customtempeffects(extcheck_t *extcheck) {return !!(extcheck->pext1 & PEXT_CUSTOMTEMPEFFECTS);}
static qboolean check_pext_256packetentities(extcheck_t *extcheck) {return check_pext_rpd(extcheck,PEXT_256PACKETENTITIES);}
static qboolean check_pext_showpic (extcheck_t *extcheck) {return !!(extcheck->pext1 & PEXT_SHOWPIC);}
static qboolean check_pext_setattachment (extcheck_t *extcheck) {return check_pext_rpd(extcheck,PEXT_SETATTACHMENT);}
//static qboolean check_pext_chunkeddownloads (extcheck_t *extcheck) {return !!(extcheck->pext1 & PEXT_CHUNKEDDOWNLOADS);}
static qboolean check_pext_csqc (extcheck_t *extcheck) {return !!(extcheck->pext1 & PEXT_CSQC);}
//static qboolean check_pext_dpflags (extcheck_t *extcheck) {return check_pext_rpd(extcheck,PEXT_DPFLAGS);}
#define check_pext_pointparticle NULL
{"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"},
{"EXT_CSQC"}, //this is the base csqc extension. I'm not sure what needs to be separate and what does not.
//{"EXT_CSQC_DELTAS"},//this is a separate extension because the feature may be banned in a league due to cheat protection.
//the rest are generic extensions
{"??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",
#define NOBI NULL, 0,{NULL},
qc_extension_t QSG_Extensions[] = {
//these don't have well-defined names...
{"??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"}},
{"??MVDSV_BUILTINS", NULL, 21,{"executecommand", "mvdtokenize", "mvdargc", "mvdargv",
"teamfield", "substr", "mvdstrcat", "mvdstrlen", "str2byte",
"str2short", "mvdnewstr", "mvdfreestr", "conprint", "readcmd",
"mvdstrcpy", "strstr", "mvdstrncpy", "log", "redirectcmd",
"mvdcalltimeofday", "forcedemoframe"}},
//end of mvdsv
// Tomaz - QuakeC File System End
{"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
{"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
{"DP_CSQC_ROTATEMOVES"},
{"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_FULLBRIGHT"}, //Rerouted to hexen2 support.
{"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_NOSHADOW"},
{"DP_EF_RED"},
//--{"DP_ENT_COLORMOD"}, //listed above
{"DP_ENT_COLORMOD", check_pext_colourmod},
{"DP_ENT_CUSTOMCOLORMAP"},
{"DP_ENT_EXTERIORMODELTOCLIENT"},
//--{"DP_ENT_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_SCALE", check_pext_scale}, //listed above
{"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"},
{"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_GFX_FONTS", 2, NULL, {"findfont", "loadfont"}}, //note: font slot numbers/names are not special in fte.
{"DP_GECKO_SUPPORT", NULL, 7,{"gecko_create", "gecko_destroy", "gecko_navigate", "gecko_keyevent", "gecko_mousemove", "gecko_resize", "gecko_get_texture_extent"}},
{"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_QUAKE3MODELTAGS"},
{"DP_GFX_QUAKE3MODELTAGS", check_pext_setattachment, 1,{"setattachment"}},
{"DP_GFX_SKINFILES"},
{"DP_GFX_SKYBOX"}, //according to the spec. :)
{"DP_HALFLIFE_MAP"}, //entity can visit a hl bsp
{"DP_HALFLIFE_MAP_CVAR"},
//to an extend {"DP_HALFLIFE_SPRITE"},
//to an extent {"DP_HALFLIFE_SPRITE"},
{"DP_INPUTBUTTONS"},
{"DP_LIGHTSTYLE_STATICVALUE"},
{"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_MOVETYPEFOLLOW"},
{"DP_QC_ASINACOSATANATAN2TAN", 5, NULL, {"asin", "acos", "atan", "atan2", "tan"}},
{"DP_QC_CHANGEPITCH", 1, NULL, {"changepitch"}},
{"DP_QC_COPYENTITY", 1, NULL, {"copyentity"}},
{"DP_QC_CRC16", 1, NULL, {"crc16"}},
{"DP_QC_CVAR_DEFSTRING", 1, NULL, {"cvar_defstring"}},
{"DP_QC_CVAR_STRING", 1, NULL, {"cvar_string"}}, //448 builtin.
{"DP_QC_CVAR_TYPE", 1, NULL, {"cvar_type"}},
{"DP_QC_ASINACOSATANATAN2TAN", NULL, 5,{"asin", "acos", "atan", "atan2", "tan"}},
{"DP_QC_CHANGEPITCH", NULL, 1,{"changepitch"}},
{"DP_QC_COPYENTITY", NULL, 1,{"copyentity"}},
{"DP_QC_CRC16", NULL, 1,{"crc16"}},
{"DP_QC_CVAR_DEFSTRING", NULL, 1,{"cvar_defstring"}},
{"DP_QC_CVAR_STRING", NULL, 1,{"cvar_string"}}, //448 builtin.
{"DP_QC_CVAR_TYPE", NULL, 1,{"cvar_type"}},
{"DP_QC_DIGEST_SHA256"},
{"DP_QC_EDICT_NUM", 1, NULL, {"edict_num"}},
{"DP_QC_ENTITYDATA", 5, NULL, {"numentityfields", "entityfieldname", "entityfieldtype", "getentityfieldstring", "putentityfieldstring"}},
{"DP_QC_ETOS", 1, NULL, {"etos"}},
{"DP_QC_FINDCHAIN", 1, NULL, {"findchain"}},
{"DP_QC_FINDCHAINFLOAT", 1, NULL, {"findchainfloat"}},
{"DP_QC_FINDFLAGS", 1, NULL, {"findflags"}},
{"DP_QC_FINDCHAINFLAGS", 1, NULL, {"findchainflags"}},
{"DP_QC_FINDFLOAT", 1, NULL, {"findfloat"}},
{"DP_QC_FS_SEARCH", 4, NULL, {"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_GETSURFACE", 6, NULL, {"getsurfacenumpoints", "getsurfacepoint", "getsurfacenormal", "getsurfacetexture", "getsurfacenearpoint", "getsurfaceclippedpoint"}},
{"DP_QC_GETSURFACEPOINTATTRIBUTE", 1, NULL, {"getsurfacepointattribute"}},
{"DP_QC_GETTAGINFO", 2, NULL, {"gettagindex", "gettaginfo"}},
{"DP_QC_MINMAXBOUND", 3, NULL, {"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_RANDOMVEC", 1, NULL, {"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_SINCOSSQRTPOW", 4, NULL, {"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_STRFTIME", 1, NULL, {"strftime"}},
{"DP_QC_STRING_CASE_FUNCTIONS", 2, NULL, {"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_STRINGCOLORFUNCTIONS", 2, NULL, {"strlennocol", "strdecolorize"}},
{"DP_QC_STRREPLACE", 2, NULL, {"strreplace", "strireplace"}},
{"DP_QC_TOKENIZEBYSEPARATOR", 1, NULL, {"tokenizebyseparator"}},
{"DP_QC_TRACEBOX", 1, NULL, {"tracebox"}},
{"DP_QC_EDICT_NUM", NULL, 1,{"edict_num"}},
{"DP_QC_ENTITYDATA", NULL, 5,{"numentityfields", "entityfieldname", "entityfieldtype", "getentityfieldstring", "putentityfieldstring"}},
{"DP_QC_ETOS", NULL, 1,{"etos"}},
{"DP_QC_FINDCHAIN", NULL, 1,{"findchain"}},
{"DP_QC_FINDCHAINFLOAT", NULL, 1,{"findchainfloat"}},
{"DP_QC_FINDFLAGS", NULL, 1,{"findflags"}},
{"DP_QC_FINDCHAINFLAGS", NULL, 1,{"findchainflags"}},
{"DP_QC_FINDFLOAT", NULL, 1,{"findfloat"}},
{"DP_QC_FS_SEARCH", NULL, 4,{"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", NULL, 6,{"getsurfacenumpoints", "getsurfacepoint", "getsurfacenormal", "getsurfacetexture", "getsurfacenearpoint", "getsurfaceclippedpoint"}},
{"DP_QC_GETSURFACEPOINTATTRIBUTE", NULL, 1,{"getsurfacepointattribute"}},
{"DP_QC_GETTAGINFO", NULL, 2,{"gettagindex", "gettaginfo"}},
{"DP_QC_MINMAXBOUND", NULL, 3,{"min", "max", "bound"}},
{"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", NULL, 1,{"randomvec"}},
{"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", NULL, 4,{"sin", "cos", "sqrt", "pow"}},
{"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", NULL, 1,{"strftime"}},
{"DP_QC_STRING_CASE_FUNCTIONS", NULL, 2,{"strtolower", "strtoupper"}},
{"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", NULL, 2,{"strlennocol", "strdecolorize"}},
{"DP_QC_STRREPLACE", NULL, 2,{"strreplace", "strireplace"}},
{"DP_QC_TOKENIZEBYSEPARATOR", NULL, 1,{"tokenizebyseparator"}},
{"DP_QC_TRACEBOX", NULL, 1,{"tracebox"}},
{"DP_QC_TRACETOSS"},
{"DP_QC_TRACE_MOVETYPE_HITMODEL"},
{"DP_QC_TRACE_MOVETYPE_WORLDONLY"},
{"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_URI_ESCAPE", 2, NULL, {"uri_escape", "uri_unescape"}},
{"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", NULL, 2,{"uri_escape", "uri_unescape"}},
#ifdef WEBCLIENT
{"DP_QC_URI_GET", 1, NULL, {"uri_get"}},
{"DP_QC_URI_POST", 1, NULL, {"uri_get"}},
{"DP_QC_URI_GET", NULL, 1,{"uri_get"}},
{"DP_QC_URI_POST", NULL, 1,{"uri_get"}},
#endif
{"DP_QC_VECTOANGLES_WITH_ROLL"},
{"DP_QC_VECTORVECTORS", 1, NULL, {"vectorvectors"}},
{"DP_QC_WHICHPACK", 1, NULL, {"whichpack"}},
{"DP_QC_VECTORVECTORS", NULL, 1,{"vectorvectors"}},
{"DP_QC_WHICHPACK", NULL, 1,{"whichpack"}},
{"DP_QUAKE2_MODEL"},
{"DP_QUAKE2_SPRITE"},
{"DP_QUAKE3_MAP"},
{"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_STEREOWAV"},
{"DP_SND_OGGVORBIS"},
{"DP_SOLIDCORPSE"},
{"DP_SPRITE32"}, //hmm... is it legal to advertise this one?
{"DP_SV_BOTCLIENT", 2, NULL, {"spawnclient", "clienttype"}},
{"DP_SV_CLIENTCAMERA", 0, NULL, {NULL}, "Works like svc_setview except also handles pvs."},
{"DP_SV_CLIENTCOLORS", 0, NULL, {NULL}, "Provided only for compatibility with DP."},
{"DP_SV_CLIENTNAME", 0, NULL, {NULL}, "Provided only for compatibility with DP."},
{"DP_SV_BOTCLIENT", NULL, 2,{"spawnclient", "clienttype"}},
{"DP_SV_CLIENTCAMERA", NULL, 0,{NULL}, "Works like svc_setview except also handles pvs."},
{"DP_SV_CLIENTCOLORS", NULL, 0,{NULL}, "Provided only for compatibility with DP."},
{"DP_SV_CLIENTNAME", NULL, 0,{NULL}, "Provided only for compatibility with DP."},
{"DP_SV_DRAWONLYTOCLIENT"},
{"DP_SV_DROPCLIENT", 1, NULL, {"dropclient"}, "Equivelent to quakeworld's stuffcmd(self,\"disconnect\\n\"); hack"},
{"DP_SV_EFFECT", 1, NULL, {"effect"}},
{"DP_SV_DROPCLIENT", NULL, 1,{"dropclient"}, "Equivelent to quakeworld's stuffcmd(self,\"disconnect\\n\"); hack"},
{"DP_SV_EFFECT", NULL, 1,{"effect"}},
{"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_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_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_POINTSOUND", 1, NULL, {"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_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_SETCOLOR"},
{"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", 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", NULL, 1,{"pointsound"}},
{"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", 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_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_WRITEPICTURE", 1, NULL, {"WritePicture"}},
{"DP_SV_WRITEUNTERMINATEDSTRING", 1, NULL, {"WriteUnterminatedString"}},
{"DP_TE_BLOOD", 1, NULL, {"te_blood"}},
{"_DP_TE_BLOODSHOWER", 1, NULL, {"te_bloodshower"}},
{"DP_TE_CUSTOMFLASH", 1, NULL, {"te_customflash"}},
{"DP_TE_EXPLOSIONRGB", 1, NULL, {"te_explosionrgb"}},
{"_DP_TE_FLAMEJET", 1, NULL, {"te_flamejet"}},
{"DP_TE_PARTICLECUBE", 1, NULL, {"te_particlecube"}},
{"DP_TE_PARTICLERAIN", 1, NULL, {"te_particlerain"}},
{"DP_TE_PARTICLESNOW", 1, NULL, {"te_particlesnow"}},
{"_DP_TE_PLASMABURN", 1, NULL, {"te_plasmaburn"}},
{"_DP_TE_QUADEFFECTS1", 4, NULL, {"te_gunshotquad", "te_spikequad", "te_superspikequad", "te_explosionquad"}},
{"DP_TE_SMALLFLASH", 1, NULL, {"te_smallflash"}},
{"DP_TE_SPARK", 1, NULL, {"te_spark"}},
{"DP_TE_STANDARDEFFECTBUILTINS", 14, NULL, { "te_gunshot", "te_spike", "te_superspike", "te_explosion", "te_tarexplosion", "te_wizspike", "te_knightspike",
{"DP_SV_WRITEPICTURE", NULL, 1,{"WritePicture"}},
{"DP_SV_WRITEUNTERMINATEDSTRING", NULL, 1,{"WriteUnterminatedString"}},
{"DP_TE_BLOOD", NULL, 1,{"te_blood"}},
{"_DP_TE_BLOODSHOWER", NULL, 1,{"te_bloodshower"}, "Requires external particle config."},
{"DP_TE_CUSTOMFLASH", NULL, 1,{"te_customflash"}},
{"DP_TE_EXPLOSIONRGB", NULL, 1,{"te_explosionrgb"}},
{"_DP_TE_FLAMEJET", NULL, 1,{"te_flamejet"}, "Requires external particle config."},
{"DP_TE_PARTICLECUBE", NULL, 1,{"te_particlecube"}},
{"DP_TE_PARTICLERAIN", NULL, 1,{"te_particlerain"}},
{"DP_TE_PARTICLESNOW", NULL, 1,{"te_particlesnow"}},
{"_DP_TE_PLASMABURN", NULL, 1,{"te_plasmaburn"}, "Requires external particle config."},
{"_DP_TE_QUADEFFECTS1", NULL, 4,{"te_gunshotquad", "te_spikequad", "te_superspikequad", "te_explosionquad"}, "Requires external particle config."},
{"DP_TE_SMALLFLASH", NULL, 1,{"te_smallflash"}},
{"DP_TE_SPARK", NULL, 1,{"te_spark"}},
{"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"}},
{"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_PHYSICS"},
{"EXT_DIMENSION_GHOST"},
{"FRIK_FILE", 11, NULL, {"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_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_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."},
{"FRIK_FILE", NULL, 11,{"stof", "fopen","fclose","fgets","fputs","strlen","strcat","substring","stov","strzone","strunzone"}},
{"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", 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", 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
{"FTE_CSQC_HALFLIFE_MODELS"}, //hl-specific skeletal model control
#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",
"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_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_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_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_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_ENT_SKIN_CONTENTS", 0, NULL, {NULL}, "self.skin = CONTENTS_WATER; makes a brush entity into water. use -16 for a ladder."},
{"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", 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", 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", 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", NULL, 0,{NULL}, "self.skin = CONTENTS_WATER; makes a brush entity into water. use -16 for a ladder."},
{"FTE_ENT_UNIQUESPAWNID"},
{"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_FORCEINFOKEY", 1, NULL, {"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_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_IQM_HITMESH", 0, NULL, {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_ISBACKBUFFERED", 1, NULL, {"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_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", NULL, 1,{"forceinfokey"}, "Provides an easy way to change a user's userinfo from the server."},
{"FTE_GFX_QUAKE3SHADERS", NULL, 0,{NULL}, "specifies that the engine has full support for vanilla quake3 shaders"},
{"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", NULL, 0,{NULL}, "Supports hitmesh iqm extensions. Also supports geomsets and embedded events."},
{"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", NULL, 1,{"isbackbuffered"}, "Allows you to check if a client has too many reliable messages pending."},
{"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
#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
#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
#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
{"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_MULTITHREADED", 3, NULL, {"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_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", NULL, 3,{"sleep", "fork", "abort"}, "Faux multithreading, allowing multiple contexts to run in sequence."},
{"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
{"FTE_MVD_PLAYBACK", NOBI "The server itself is able to play back MVDs."},
#endif
#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
#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_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_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", 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
{"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
{"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_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_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_QC_CHECKPVS", 1, NULL, {"checkpvs"}},
{"FTE_QC_CROSSPRODUCT", 1, NULL, {"crossproduct"}},
{"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_QC_DIGEST_SHA1"},
{"FTE_QC_DIGEST_SHA224"},
{"FTE_QC_DIGEST_SHA384"},
{"FTE_QC_DIGEST_SHA512"},
{"FTE_QC_FS_SEARCH_SIZEMTIME", 2, NULL, {"search_getfilesize", "search_getfilemtime"}},
{"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_QC_HASHTABLES", 6, NULL, {"hash_createtab", "hash_destroytab", "hash_add", "hash_get", "hash_delete", "hash_getkey"}, "Provides efficient string-based lookups."},
{"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_QC_INTCONV", 6, NULL, {"stoi", "itos", "stoh", "htos", "itof", "ftoi"}, "Provides string<>int conversions, including hex representations."},
{"FTE_QC_MATCHCLIENTNAME", 1, NULL, {"matchclientname"}},
{"FTE_QC_MULTICAST", 1, NULL, {"multicast"}, "QuakeWorld's multicast builtin works along with MSG_MULTICAST, but also with unicast support."},
// {"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_SETVIEW", check_pext_setview, 0,{NULL}, "NQ's svc_setview works correctly even in quakeworld"},
{"FTE_PEXT_LIGHTSTYLECOL", check_pext_lightstylecol}, //lightstyles may have colours.
{"FTE_PEXT_VIEW2", check_pext_view2}, //secondary view.
// {"FTE_PEXT_ACURATETIMINGS", check_pext_senttimings}, //allows full interpolation
// {"FTE_PEXT_SOUNDDBL", check_pext_sounddbl}, //twice the sound indexes
{"FTE_PEXT_FATNESS", check_pext_fatness}, //entities may be expanded along their vertex normals
{"FTE_PEXT_TE_BULLET", check_pext_tebullet}, //additional particle effect. Like TE_SPIKE and TE_SUPERSPIKE
// {"FTE_PEXT_HULLSIZE", check_pext_}, //means we can tell a client to go to crouching hull
// {"FTE_PEXT_MODELDBL", check_pext_modeldbl}, //max of 512 models
// {"FTE_PEXT_ENTITYDBL", check_pext_}, //max of 1024 ents
// {"FTE_PEXT_ENTITYDBL2", check_pext_}, //max of 2048 ents
{"FTE_PEXT_FLOATCOORDS", check_pext_floatcoords},
{"FTE_PEXT_Q2BSP", check_pext_q2bsp, 0,{NULL},"Specifies that the client supports q2bsps."},
{"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_HEXEN2", check_pext_hexen2, 3,{"particle2", "particle3", "particle4"}}, //client can use hexen2 maps. server can use hexen2 progs
{"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_PEXT_CUSTOMTENTS", check_pext_customtempeffects, 2,{"RegisterTempEnt", "CustomTempEnt"}},
{"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"},
#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."},
#endif
#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
{"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_STUFFCMDFLAGS", 1, NULL, {"stuffcmdflags"}, "Variation on regular stuffcmd that gives control over how spectators/mvds should be treated."},
{"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", NULL, 1,{"stuffcmdflags"}, "Variation on regular stuffcmd that gives control over how spectators/mvds should be treated."},
{"FTE_QC_TRACETRIGGER"},
#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
#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
#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
#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
{"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."},
#ifdef SQL
// 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"},
#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
#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
//eperimental advanced strings functions.
//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"},
{"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_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."},
#ifdef TERRAIN
{"FTE_TERRAIN_MAP", 1, NULL, {"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_TERRAIN_MAP", NULL, 1,{"terrain_edit"}, "This engine supports .hmp files, as well as terrain embedded within bsp files."},
{"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
{"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_RESTOREGAME"},
//{"PRYDON_CLIENTCURSOR"},
{"QSG_CVARSTRING", 1, NULL, {"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.
//{"PRYDON_CLIENTCURSOR", check_pext2_prydoncursor},
{"QSG_CVARSTRING", NULL, 1,{"qsg_cvar_string"}},
{"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)
{"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.
{"ZQ_MOVETYPE_FLY", NOBI "MOVETYPE_FLY works on players."},
{"ZQ_MOVETYPE_NOCLIP", NOBI "MOVETYPE_NOCLIP 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_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]);
#endif

View File

@ -41,18 +41,22 @@ struct wedict_s
#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.
//thus lh's system requires various builtins to exist at specific numbers.
typedef struct lh_extension_s {
//thus this system requires various builtins to exist at specific numbers.
//this competes against checkbuiltin(funcreference).
typedef struct {
unsigned int pext1, pext2;
} extcheck_t;
typedef struct qc_extension_s {
char *name;
qboolean(*extensioncheck)(extcheck_t *info);
int numbuiltins;
qboolean *queried;
char *builtinnames[21]; //extend freely
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;
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 *AngleVectors)(const vec3_t angles, vec3_t forward, vec3_t right, vec3_t up);
#define plugrbefuncs_name "RBE"
} rbeplugfuncs_t;
#define RBEPLUGFUNCS_VERSION 1
@ -856,7 +861,8 @@ enum lightfield_e
lfield_rgbdecay=15,
lfield_radiusdecay=16,
lfield_stylestring=17,
lfield_nearclip=18
lfield_nearclip=18,
lfield_owner=19,
};
enum csqc_input_event
{
@ -1107,13 +1113,28 @@ enum
globalfloat (input_buttons) /*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_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_clienttime) /*float filled by getinputstate, read by runplayerphysics*/ \
globalvector(input_cursor_screen) /*float filled by getinputstate*/ \
globalvector(input_cursor_trace_start) /*float filled by getinputstate*/ \
globalvector(input_cursor_trace_endpos) /*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 */ \
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_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_NEWINTENTS 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_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|PEXT2_VRINPUTS)
//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...
@ -147,6 +147,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define PORT_QWMASTER 27000
#define PORT_QWSERVER 27500
#define PORT_H2SERVER 26900
#define PORT_Q2MASTER 27900
#define PORT_Q2CLIENT 27901
#define PORT_Q2SERVER 27910
#define PORT_Q3MASTER 27950
@ -1200,9 +1201,9 @@ typedef struct usercmd_s
//end q2 compat
float msec; //replace msec, but with more precision
int buttons; //replaces buttons, but with more bits.
int weapon; //q3 has a separate weapon field to supplement impulse.
int servertime; //q3 networks the time in order to calculate msecs
unsigned int buttons; //replaces buttons, but with more bits.
unsigned int weapon;//q3 has a separate weapon field to supplement impulse.
unsigned int servertime; //q3 networks the time in order to calculate msecs
float fservertime;//used as part of nq msec calcs
float fclienttime;//not used?
@ -1210,7 +1211,24 @@ typedef struct usercmd_s
vec2_t cursor_screen;
vec3_t cursor_start;
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;
typedef struct q2usercmd_s

View File

@ -3,6 +3,7 @@
#include "pr_common.h"
#include "shader.h"
#include "com_bih.h"
extern cvar_t r_decal_noperpendicular;
extern cvar_t mod_loadsurfenvmaps;
@ -1047,7 +1048,7 @@ qboolean Q1BSP_RecursiveHullCheck (hull_t *hull, int num, float p1f, float p2f,
}
#endif
#ifdef Q1BSPS
#if 0//def Q1BSPS
/*
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
static unsigned int Q1BSP_TranslateContents(int contents)
static unsigned int Q1BSP_TranslateContents(enum q1contents_e contents)
{
switch(contents)
safeswitch(contents)
{
case Q1CONTENTS_EMPTY:
return FTECONTENTS_EMPTY;
case Q1CONTENTS_SOLID:
return FTECONTENTS_SOLID;
case Q1CONTENTS_WATER:
return FTECONTENTS_WATER;
case Q1CONTENTS_SLIME:
return FTECONTENTS_SLIME;
case Q1CONTENTS_LAVA:
return FTECONTENTS_LAVA;
case Q1CONTENTS_SKY:
return FTECONTENTS_SKY|FTECONTENTS_PLAYERCLIP|FTECONTENTS_MONSTERCLIP;
case Q1CONTENTS_LADDER:
return FTECONTENTS_LADDER;
case Q1CONTENTS_CLIP:
return FTECONTENTS_PLAYERCLIP|FTECONTENTS_MONSTERCLIP;
case Q1CONTENTS_TRANS:
return FTECONTENTS_SOLID;
case Q1CONTENTS_EMPTY: return FTECONTENTS_EMPTY;
case Q1CONTENTS_SOLID: return FTECONTENTS_SOLID;
case Q1CONTENTS_WATER: return FTECONTENTS_WATER;
case Q1CONTENTS_SLIME: return FTECONTENTS_SLIME;
case Q1CONTENTS_LAVA: return FTECONTENTS_LAVA;
case Q1CONTENTS_SKY: return FTECONTENTS_SKY|FTECONTENTS_PLAYERCLIP|FTECONTENTS_MONSTERCLIP;
case Q1CONTENTS_LADDER: return FTECONTENTS_LADDER;
case Q1CONTENTS_CLIP: return FTECONTENTS_PLAYERCLIP|FTECONTENTS_MONSTERCLIP;
case Q1CONTENTS_CURRENT_0: return FTECONTENTS_WATER|Q2CONTENTS_CURRENT_0; //q2 is better than nothing, right?
case Q1CONTENTS_CURRENT_90: return FTECONTENTS_WATER|Q2CONTENTS_CURRENT_90;
case Q1CONTENTS_CURRENT_180: return FTECONTENTS_WATER|Q2CONTENTS_CURRENT_180;
case Q1CONTENTS_CURRENT_270: return FTECONTENTS_WATER|Q2CONTENTS_CURRENT_270;
case Q1CONTENTS_CURRENT_UP: return FTECONTENTS_WATER|Q2CONTENTS_CURRENT_UP;
case Q1CONTENTS_CURRENT_DOWN: return FTECONTENTS_WATER|Q2CONTENTS_CURRENT_DOWN;
case Q1CONTENTS_TRANS: return FTECONTENTS_SOLID;
case Q1CONTENTS_MONSTERCLIP: return FTECONTENTS_MONSTERCLIP;
case Q1CONTENTS_PLAYERCLIP: return FTECONTENTS_PLAYERCLIP;
//q2 is better than nothing, right?
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:
safedefault:
Con_Printf("Q1BSP_TranslateContents: Unknown contents type - %i", contents);
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)
{
struct {
const struct {
unsigned int ver;
unsigned int modelnum;
unsigned int numbrushes;
unsigned int numplanes;
} *permodel;
struct {
} *srcmodel;
const struct {
float mins[3];
float maxs[3];
signed short contents;
unsigned short numplanes;
} *perbrush;
} *srcbrush;
/*
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.
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...
*/
struct {
const struct{
vec3_t normal;
float dist;
} *perplane;
} *srcplane;
static vec3_t axis[3] = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}};
int br, pl, remainingplanes;
mbrush_t *brush;
mnode_t *rootnode;
unsigned int br, pl;
q2cbrush_t *brush;
q2cbrushside_t *sides; //grr!
mplane_t *planes; //bulky?
unsigned int lumpsizeremaining;
unsigned int numplanes;
model->engineflags &= ~MDLF_HASBRUSHES;
unsigned int srcver, srcmodelidx, modbrushes, modplanes;
permodel = BSPX_FindLump(bspx, mod_base, "BRUSHLIST", &lumpsizeremaining);
if (!permodel)
srcmodel = BSPX_FindLump(bspx, mod_base, "BRUSHLIST", &lumpsizeremaining);
if (!srcmodel)
return;
while (lumpsizeremaining)
{
if (lumpsizeremaining < sizeof(*permodel))
if (lumpsizeremaining < sizeof(*srcmodel))
return;
permodel->ver = LittleLong(permodel->ver);
permodel->modelnum = LittleLong(permodel->modelnum);
permodel->numbrushes = LittleLong(permodel->numbrushes);
permodel->numplanes = LittleLong(permodel->numplanes);
if (permodel->ver != 1 || lumpsizeremaining < sizeof(*permodel) + permodel->numbrushes*sizeof(*perbrush) + permodel->numplanes*sizeof(*perplane))
srcver = LittleLong(srcmodel->ver);
srcmodelidx = LittleLong(srcmodel->modelnum);
modbrushes = LittleLong(srcmodel->numbrushes);
modplanes = LittleLong(srcmodel->numplanes);
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;
//find the correct rootnode for the submodel (submodels are not set up yet).
rootnode = model->nodes;
if (permodel->modelnum > model->numsubmodels)
return;
rootnode += model->submodels[permodel->modelnum].headnode[0];
brush = ZG_Malloc(&model->memgroup, (sizeof(*brush) - sizeof(brush->planes[0]))*permodel->numbrushes + sizeof(brush->planes[0])*(permodel->numbrushes*6+permodel->numplanes));
remainingplanes = permodel->numplanes;
perbrush = (void*)(permodel+1);
for (br = 0; br < permodel->numbrushes; br++)
brush = ZG_Malloc(&model->memgroup, sizeof(*brush)*modbrushes +
sizeof(*sides)*(modbrushes*6+modplanes) +
sizeof(*planes)*(modbrushes*6+modplanes));
sides = (void*)(brush + modbrushes);
planes = (void*)(sides + modbrushes*6+modplanes);
model->submodels[srcmodelidx].brushes = brush;
srcbrush = (const void*)(srcmodel+1);
for (br = 0; br < modbrushes; br++, srcbrush = (const void*)srcplane)
{
/*byteswap it all in place*/
perbrush->mins[0] = LittleFloat(perbrush->mins[0]);
perbrush->mins[1] = LittleFloat(perbrush->mins[1]);
perbrush->mins[2] = LittleFloat(perbrush->mins[2]);
perbrush->maxs[0] = LittleFloat(perbrush->maxs[0]);
perbrush->maxs[1] = LittleFloat(perbrush->maxs[1]);
perbrush->maxs[2] = LittleFloat(perbrush->maxs[2]);
perbrush->contents = LittleShort(perbrush->contents);
perbrush->numplanes = LittleShort(perbrush->numplanes);
brush->absmins[0] = LittleFloat(srcbrush->mins[0]);
brush->absmins[1] = LittleFloat(srcbrush->mins[1]);
brush->absmins[2] = LittleFloat(srcbrush->mins[2]);
brush->absmaxs[0] = LittleFloat(srcbrush->maxs[0]);
brush->absmaxs[1] = LittleFloat(srcbrush->maxs[1]);
brush->absmaxs[2] = LittleFloat(srcbrush->maxs[2]);
numplanes = (unsigned short)LittleShort(srcbrush->numplanes);
/*make sure planes don't overflow*/
if (perbrush->numplanes > remainingplanes)
if (numplanes > modplanes)
return;
remainingplanes-=perbrush->numplanes;
modplanes-=numplanes;
/*set up the mbrush from the file*/
brush->contents = Q1BSP_TranslateContents(perbrush->contents);
brush->numplanes = perbrush->numplanes;
for (pl = 0, perplane = (void*)(perbrush+1); pl < perbrush->numplanes; pl++, perplane++)
brush->contents = Q1BSP_TranslateContents(LittleShort(srcbrush->contents));
brush->brushside = sides;
for (srcplane = (const void*)(srcbrush+1); numplanes --> 0; srcplane++)
{
brush->planes[pl].normal[0] = LittleFloat(perplane->normal[0]);
brush->planes[pl].normal[1] = LittleFloat(perplane->normal[1]);
brush->planes[pl].normal[2] = LittleFloat(perplane->normal[2]);
brush->planes[pl].dist = LittleFloat(perplane->dist);
planes->normal[0] = LittleFloat(srcplane->normal[0]);
planes->normal[1] = LittleFloat(srcplane->normal[1]);
planes->normal[2] = LittleFloat(srcplane->normal[2]);
planes->dist = LittleFloat(srcplane->dist);
sides->surface = NULL;
sides++->plane = planes++;
}
/*and add axial planes acording to the brush's bbox*/
for (pl = 0; pl < 3; pl++)
{
VectorCopy(axis[pl], brush->planes[brush->numplanes].normal);
brush->planes[brush->numplanes].dist = perbrush->maxs[pl];
brush->numplanes++;
VectorCopy(axis[pl], planes->normal);
planes->dist = brush->absmaxs[pl];
sides->surface = NULL;
sides++->plane = planes++;
}
for (pl = 0; pl < 3; pl++)
{
VectorNegate(axis[pl], brush->planes[brush->numplanes].normal);
brush->planes[brush->numplanes].dist = -perbrush->mins[pl];
brush->numplanes++;
VectorNegate(axis[pl], planes->normal);
planes->dist = -brush->absmins[pl];
sides->surface = NULL;
sides++->plane = planes++;
}
/*link it in to the bsp tree*/
Q1BSP_InsertBrush(rootnode, brush, perbrush->mins, perbrush->maxs);
/*set up for the next brush*/
brush = (void*)&brush->planes[brush->numplanes];
perbrush = (void*)perplane;
brush->numsides = sides - brush->brushside;
brush++;
}
model->submodels[srcmodelidx].numbrushes = brush-model->submodels[srcmodelidx].brushes;
/*move on to the next model*/
lumpsizeremaining -= sizeof(*permodel) + permodel->numbrushes*sizeof(*perbrush) + permodel->numplanes*sizeof(*perplane);
permodel = (void*)((char*)permodel + sizeof(*permodel) + permodel->numbrushes*sizeof(*perbrush) + permodel->numplanes*sizeof(*perplane));
srcmodel = (const void*)srcbrush;
}
/*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)
@ -1567,82 +1557,6 @@ qboolean Q1BSP_Trace(model_t *model, int forcehullnum, const framestate_t *frame
vec3_t start_l, end_l;
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));
trace->fraction = 1;
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]);
}
//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
/*
Rendering functions (Client only)
@ -2227,9 +2178,6 @@ void Q1BSP_SetModelFuncs(model_t *mod)
#endif
mod->funcs.EdictInFatPVS = Q1BSP_EdictInFatPVS;
mod->funcs.FindTouchedLeafs = Q1BSP_FindTouchedLeafs;
mod->funcs.LightPointValues = NULL;
mod->funcs.StainNode = NULL;
mod->funcs.MarkLights = NULL;
mod->funcs.ClustersInSphere = Q1BSP_ClustersInSphere;
mod->funcs.ClusterForPoint = Q1BSP_ClusterForPoint;
@ -2237,6 +2185,12 @@ void Q1BSP_SetModelFuncs(model_t *mod)
// mod->funcs.ClusterPHS = Q1BSP_ClusterPHS;
mod->funcs.NativeTrace = Q1BSP_Trace;
mod->funcs.PointContents = Q1BSP_PointContents;
#ifndef SERVERONLY
mod->funcs.LightPointValues = GLQ1BSP_LightPointValues;
mod->funcs.MarkLights = Q1BSP_MarkLights;
mod->funcs.StainNode = Q1BSP_StainNode;
#endif
}
#endif

View File

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

View File

@ -185,9 +185,23 @@ hashfunc_t hash_sha1 =
SHA1Final,
};
size_t CalcHash(hashfunc_t *func, unsigned char *digest, size_t maxdigestsize, const unsigned char *string, size_t stringlen)
unsigned int hashfunc_terminate_uint(const hashfunc_t *func, void *context)
{
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);
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);
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 *key, size_t keylen)
{

View File

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

View File

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

View File

@ -347,7 +347,7 @@ skinid_t Mod_ReadSkinFile(const char *skinname, const char *skintext)
skin->nummappings++;
}
}
else if (!strcmp(com_token, "geomset"))
else if (!strcmp(com_token, "geomset") || !strcmp(com_token, "meshgroup"))
{
int set;
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++)
batches[i] = NULL;
if (cl.worldmodel && !(r_refdef.flags & RDF_NOWORLDMODEL))
{
if (cl.worldmodel->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
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);

View File

@ -1624,7 +1624,7 @@ void GLBE_Init(void)
(!gl_config.tex_env_combine && !gl_config_nofixedfunc)
#endif
&& gl_overbright.ival)
Cvar_ApplyLatchFlag(&gl_overbright, "0", CVAR_RENDERERLATCH);
Cvar_ApplyLatchFlag(&gl_overbright, "0", CVAR_RENDERERLATCH, 0);
shaderstate.shaderbits = ~SBITS_ATEST_BITS;
BE_SendPassBlendDepthMask(0);
currententity = &r_worldentity;
@ -1770,7 +1770,10 @@ static void GenerateTCFog(int passnum, mfog_t *fog)
for (m = 0; m < shaderstate.meshcount; 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;

View File

@ -519,7 +519,12 @@ void GLDraw_Init (void)
extern cvar_t vid_srgb;
if ((vid.flags & VID_SRGB_CAPABLE) && gl_config.arb_framebuffer_srgb)
{ //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...
qglDisable(GL_FRAMEBUFFER_SRGB);
vid.flags &= ~VID_SRGB_FB_LINEAR;
@ -551,7 +556,7 @@ void GLDraw_Init (void)
qglDisable(GL_SCISSOR_TEST);
GL_Set2D(false);
if (scr_showloading.ival)
if (scr_showloading.ival && (!VID_MayRefresh || VID_MayRefresh()))
{
extern cvar_t scr_loadingscreen_picture;
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_Memory_Face FT_New_Memory_Face
#define pFT_Done_Face FT_Done_Face
#define pFT_Error_String FT_Error_String
#else
qboolean triedtoloadfreetype;
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_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);
const char *(VARGS *pFT_Error_String) (FT_Error error_code);
#endif
#else
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_Init_FreeType, "FT_Init_FreeType"},
{(void**)&pFT_Done_Face, "FT_Done_Face"},
{(void**)&pFT_Error_String, "FT_Error_String"},
{NULL, NULL}
};
if (triedtoloadfreetype)
@ -1800,7 +1803,7 @@ qboolean Font_LoadFreeTypeFont(struct font_s *f, int height, const char *fontfil
Z_Free(qface);
}
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)
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 != 2 || QCRC_Block(lumpdata, 128*128) == 798)
if (con_ocranaleds.ival != 2 || CalcHashInt(&hash_crc16, lumpdata, 128*128) == 798)
AddOcranaLEDsIndexed (lumpdata, 128, 128);
}

View File

@ -2,6 +2,10 @@
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"
#ifdef TERRAIN
@ -2687,6 +2691,20 @@ static void Terr_RebuildMesh(model_t *model, hmsection_t *s, int x, int y)
}
#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 (!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;
#endif
}
#endif
#endif
#ifdef VKQUAKE
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++)
while (sz < tex[i].w || sz < tex[i].h)
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;
int atlasid;

View File

@ -24,7 +24,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "quakedef.h"
#include "com_bih.h"
#if 1//ndef SERVERONLY //FIXME
#include "glquake.h"
#include "com_mesh.h"
@ -340,7 +340,14 @@ const char *Mod_GetEntitiesString(model_t *mod)
if (mod->entities_raw) //still cached/correct
return mod->entities_raw;
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
//find needed buffer size
@ -423,8 +430,7 @@ void Mod_ParseEntities(model_t *mod)
Z_Free(mod->entityinfo);
mod->entityinfo = NULL;
entdata = mod->entities_raw;
entdata = Mod_GetEntitiesString(mod);
while(1)
{
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
//
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)
magic = 0;
@ -2234,7 +2246,7 @@ void Mod_LoadEntities (model_t *loadmodel, qbyte *mod_base, lump_t *l)
ents[l->filelen] = 0;
}
else
loadmodel->entitiescrc = QCRC_Block(ents, strlen(ents));
loadmodel->entitiescrc = CalcHashInt(&hash_crc16, ents, strlen(ents));
Mod_SetEntitiesString(loadmodel, ents, false);
@ -2817,8 +2829,8 @@ void Mod_LightmapAllocInit(lmalloc_t *lmallocator, qboolean hasdeluxe, unsigned
lmallocator->lmnum = firstlm;
lmallocator->firstlm = firstlm;
lmallocator->width = width;
lmallocator->height = height;
lmallocator->width = min(LMBLOCK_SIZE_MAX, width);
lmallocator->height = min(LMBLOCK_SIZE_MAX, height);
}
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;
int merge = 1;
currentmodel = mod;
if (!mod->textures)
return;
@ -4922,46 +4932,6 @@ static qboolean Mod_LoadPlanes (model_t *loadmodel, qbyte *mod_base, lump_t *l)
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)
{
if (!node)
@ -5467,13 +5437,6 @@ static qboolean QDECL Mod_LoadBrushModel (model_t *mod, void *buffer, size_t fsi
TRACE(("LoadBrushModel %i\n", __LINE__));
Q1BSP_LoadBrushes(mod, bspx, mod_base);
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
@ -5544,6 +5507,27 @@ 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)
COM_AddWork(WG_MAIN, Mod_ModelLoaded, submod, NULL, MLS_LOADED, 0);
if (i < submod->numsubmodels-1)

View File

@ -265,7 +265,7 @@ typedef struct {
void (*PurgeModel) (struct model_s *mod);
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).
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]
} msurface_t;
typedef struct mbrush_s
/*typedef struct mbrush_s
{
struct mbrush_s *next;
unsigned int contents;
@ -492,7 +492,7 @@ typedef struct mbrush_s
vec3_t normal;
float dist;
} planes[1];
} mbrush_t;
} mbrush_t;*/
typedef struct mnode_s
{
@ -504,7 +504,7 @@ typedef struct mnode_s
float minmaxs[6]; // for bounding box culling
struct mnode_s *parent;
struct mbrush_s *brushes;
// struct mbrush_s *brushes;
// node specific
mplane_t *plane;
@ -529,7 +529,6 @@ typedef struct mleaf_s
float minmaxs[6]; // for bounding box culling
struct mnode_s *parent;
struct mbrush_s *brushes;
// leaf specific
qbyte *compressed_vis;
@ -555,12 +554,15 @@ typedef struct mleaf_s
typedef struct
{
float mins[3], maxs[3];
float origin[3];
int headnode[MAX_MAP_HULLSM];
int visleafs; // not including the solid leaf 0
int firstface, numfaces;
qboolean hullavailable[MAX_MAP_HULLSM];
float mins[3], maxs[3];
float origin[3];
unsigned int headnode[MAX_MAP_HULLSM];
unsigned int visleafs; // not including the solid leaf 0
unsigned int firstface, numfaces;
qboolean hullavailable[MAX_MAP_HULLSM];
struct q2cbrush_s *brushes;
unsigned int numbrushes;
} mmodel_t;
@ -932,13 +934,13 @@ typedef struct model_s
{
char name[MAX_QPATH]; //actual name on disk
char publicname[MAX_QPATH]; //name that the gamecode etc sees
int datasequence;
int loadstate;//MLS_
int datasequence; //if it gets old enough, we can purge it.
int loadstate; //MLS_
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.
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;
fromgame_t fromgame;
@ -951,9 +953,6 @@ typedef struct model_s
int particleeffect;
int particletrail;
int traildefaultindex;
struct skytris_s *skytris; //for surface emittance
float skytime; //for surface emittance
struct skytriblock_s *skytrimem;
//
// volume occupied by the model graphics
@ -969,6 +968,7 @@ typedef struct model_s
qboolean clipbox;
vec3_t clipmins, clipmaxs;
void *cnodes; //BIH tree
//
// brush model
//
@ -994,7 +994,6 @@ typedef struct model_s
int numnodes;
mnode_t *nodes;
void *cnodes;
mnode_t *rootnode;
int numtexinfo;
@ -1028,13 +1027,20 @@ typedef struct model_s
int numfogs;
menvmap_t *envmaps;
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;
size_t numentityinfo;
const char *entities_raw;
int entitiescrc;
struct doll_s *dollinfo;
shader_t *simpleskin[4];
struct doll_s *dollinfo; //ragdoll info
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 {
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
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;
#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_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_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
//============================================================================

View File

@ -438,7 +438,9 @@ void R_RenderDlights (void)
if (coronastyle)
{
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.
else
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_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_dither = CVAR("gl_dither", "1");
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
=============
*/
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;
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[1] = r_refdef.viewangles[1];
newa[2] = r_refdef.viewangles[2] + gl_screenangle.value;
if (axisorigin)
if (eyematrix)
{
vec3_t paxis[3];
AngleVectors (newa, paxis[0], paxis[1], paxis[2]);
//R_ConcatRotations(r_refdef.headaxis, paxis, vpn);
VectorMA(vec3_origin, axisorigin[0][0], paxis[0], vpn);
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);
matrix3x4 headmatrix;
matrix3x4 viewmatrix;
Matrix3x4_RM_FromAngles(newa, r_refdef.vieworg, headmatrix[0]);
Matrix3x4_Multiply(headmatrix[0], eyematrix[0], viewmatrix[0]);
Matrix3x4_RM_ToVectors(viewmatrix[0], vpn, vright, vup, r_origin);
VectorNegate(vright, vright);
}
else
{
@ -732,7 +717,7 @@ static void R_RenderScene_Internal(void)
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;
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;
}
R_SetupGL (axisorigin, fovoverride, NULL, rendertarget);
R_SetupGL (eyematrix, fovoverride, NULL, rendertarget);
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)
{
GLBE_FBO_Pop(r);
@ -772,7 +795,8 @@ static void R_RenderScene (void)
int i;
int cull = r_refdef.flipcull;
unsigned int colourmask = r_refdef.colourmask;
vec3_t axisorg[4], ang;
vec3_t ang, org;
matrix3x4 eyematrix;
extern qboolean depthcleared;
r_refdef.colourmask = 0u;
@ -893,11 +917,9 @@ static void R_RenderScene (void)
ang[0] = 0;
ang[1] = r_stereo_convergence.value * (i?0.5:-0.5);
ang[2] = 0;
AngleVectorsFLU(ang, axisorg[0], axisorg[1], axisorg[2]);
axisorg[3][0] = 0;
axisorg[3][1] = stereooffset[i];
axisorg[3][2] = 0;
R_SetupGL (axisorg, NULL, NULL, NULL);
VectorSet(org, 0, stereooffset[i], 0);
Matrix3x4_RM_FromAngles(ang, org, eyematrix[0]);
R_SetupGL (eyematrix, NULL, NULL, NULL);
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_LINEAR;
}
else if (!Q_strnicmp(*name, "$palettize:", 11))
{
*name+=11;
flags |= IF_PALETTIZE;
}
else
break;
}
@ -6519,7 +6524,7 @@ char *Shader_DefaultBSPWater(parsestate_t *ps, const char *shortname, char *buff
else
wstyle = 1;
if (wstyle > 1 && !cls.allow_watervis)
if ((wstyle < 0 || wstyle > 1) && !cls.allow_watervis)
wstyle = 1;
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.
return (
"{\n"
"fte_program defaultwarp\n"
"{\n"
"program defaultwarp\n"
"map $diffuse\n"
"tcmod turb 0.02 0.1 0.5 0.1\n"
"}\n"
@ -6591,8 +6596,8 @@ char *Shader_DefaultBSPWater(parsestate_t *ps, const char *shortname, char *buff
"if %g < 1\n"
"sort underwater\n"
"endif\n"
"fte_program defaultwarp%s\n"
"{\n"
"program defaultwarp%s\n"
"map $diffuse\n"
"tcmod turb 0.02 0.1 0.5 0.1\n"
"if %g < 1\n"
@ -7008,6 +7013,9 @@ void Shader_DefaultSkin(parsestate_t *ps, const char *shortname, const void *arg
"{\n"
"map $diffuse\n"
"rgbgen lightingDiffuse\n"
"if #BLEND\n"
"blendfunc blend\n" //straight blend
"endif\n"
"}\n"
"{\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_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_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_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");
@ -3730,6 +3730,13 @@ void Sh_PreGenerateLights(void)
qbyte *lvis;
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);
if (!cl.worldmodel)
return;
@ -3981,6 +3988,7 @@ void Sh_DrawLights(qbyte *vis)
if (r_shadow_realtime_world.modified ||
r_shadow_realtime_world_shadows.modified ||
r_shadow_realtime_world_importlightentitiesfrommap.modified ||
r_shadow_realtime_dlight.modified ||
r_shadow_realtime_dlight_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 CHUNKLIMIT (MAXCLUSTERS*MAXSECTIONS)
#define LMCHUNKS 8//(LMBLOCK_WIDTH/SECTTEXSIZE)
#define LMCHUNKS 8//(LMBLOCK_WIDTH/SECTTEXSIZE) //FIXME: make dynamic.
#define HMLMSTRIDE (LMCHUNKS*SECTTEXSIZE)
#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))
{
#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");
qglClear = (void *)getglcore("glClear");
qglClearColor = (void *)getglcore("glClearColor");

View File

@ -450,18 +450,13 @@ qboolean EGL_InitWindow (rendererstate_t *info, int eglplat, void *nwindow, EGLN
return false;
}
if (!qeglMakeCurrent(egldpy, eglsurf, eglsurf, eglctx))
{
Con_Printf(CON_ERROR "EGL: can't make current!\n");
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();

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};
if (VK_Init(info, extnames, XVK_SetupSurface_XLib, NULL))
break;
VK_Shutdown();
}
#endif
#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};
if (x11xcb_initlib() && VK_Init(info, extnames, XVK_SetupSurface_XCB, NULL))
break;
VK_Shutdown();
}
#endif
//Con_Printf(CON_ERROR "Failed to create a vulkan context.\n");
@ -4565,6 +4567,31 @@ static qboolean XVK_SetupSurface_XCB(void)
return false;
}
#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 =
{
"Vulkan (X11)",
@ -4622,7 +4649,11 @@ rendererinfo_t vkrendererinfo =
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

View File

@ -48,7 +48,7 @@ extern cvar_t vid_conautoscale;
#define WP_POINTER_CONSTRAINTS_NAME "zwp_pointer_constraints_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 XDG_SHELL_UNSTABLE
//#define XDG_SHELL_UNSTABLE
#ifdef XDG_SHELL_UNSTABLE
#define XDG_SHELL_NAME "zxdg_shell_v6"
#else
@ -56,7 +56,10 @@ extern cvar_t vid_conautoscale;
#endif
#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 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_pool_interface;
static const struct wl_interface *pwl_buffer_interface;
static const struct wl_interface *pwl_callback_interface;
static dllfunction_t waylandexports_wl[] =
{
@ -113,6 +117,7 @@ static dllfunction_t waylandexports_wl[] =
{(void**)&pwl_shm_interface, "wl_shm_interface"},
{(void**)&pwl_shm_pool_interface, "wl_shm_pool_interface"},
{(void**)&pwl_buffer_interface, "wl_buffer_interface"},
{(void**)&pwl_callback_interface, "wl_callback_interface"},
{NULL, NULL}
};
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 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
#define pwl_keyboard_interface &wl_keyboard_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
#endif
#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
static const struct wl_interface *pzwp_relative_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_state *xkb_state;
//to try to fix mouse stuff
qboolean absmouse;
qboolean relative_mouse_active;
#ifdef WP_POINTER_CONSTRAINTS_NAME
struct zwp_pointer_constraints_v1 *pointer_constraints;
struct zwp_locked_pointer_v1 *locked_pointer;
@ -269,6 +347,8 @@ static struct wdisplay_s
struct wl_shell_surface *ssurface;
struct wl_shell *shell; //manager
#endif
qboolean wait_for_configure; //WL is being slow and won't let us redraw yet.
qboolean waylandisblocking;
//belated sanity stuff
#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)
{
xdg_surface_ack_configure(xdg_surface, serial);
w.wait_for_configure = false; //all good now
}
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;
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)
{
@ -602,16 +686,6 @@ static qbyte waylandinputsucksbighairydonkeyballsshift[] =
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)
{ //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.
/*'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;
//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;
//and let the game know.
if (s->absmouse)
if (!s->relative_mouse_active)
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.
case BTN_LEFT:
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
if (s->xdg_toplevel)
@ -822,7 +896,7 @@ static void WL_pointer_handle_button(void *data, struct wl_pointer *wl_pointer,
break;
case BTN_RIGHT:
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
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)
{
if (!w.absmouse)
IN_MouseMove(0, false, wl_fixed_to_double(dx_raw_w), wl_fixed_to_double(dy_raw_w), 0, 0);
if (w.relative_mouse_active)
{
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
{
@ -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_CONFINE_POINTER 2
#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_SET_CURSOR_POSITION_HINT 1
#define ZWP_LOCKED_POINTER_V1_SET_REGION 2
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)
{ //this is a one-shot. it gets destroyed automatically, but we still need to null it
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
{
@ -1017,11 +1102,14 @@ static void WL_keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard,
{
struct xkb_keymap *keymap;
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);
munmap (keymap_string, size);
pxkb_state_unref (d->xkb_state);
d->xkb_state = pxkb_state_new (keymap);
pxkb_keymap_unref (keymap);
if (keymap_string != MAP_FAILED)
{
keymap = pxkb_keymap_new_from_string (d->xkb_context, keymap_string, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS);
munmap (keymap_string, size);
pxkb_state_unref (d->xkb_state);
d->xkb_state = pxkb_state_new (keymap);
pxkb_keymap_unref (keymap);
}
}
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)
{
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)
d->compositor = pwl_registry_bind(registry, id, pwl_compositor_interface, 1);
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
#ifdef XDG_SHELL_NAME
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
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 = {
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)
{
qboolean wantabs;
TRACE(("WL_SwapBuffers\n"));
switch(qrenderer)
@ -1311,6 +1429,13 @@ static void WL_SwapBuffers(void)
if (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();
//wl_surface_damage(w.surface, 0, 0, vid.pixelwidth, vid.pixelheight);
if (pwl_display_dispatch_pending(w.display) < 0)
@ -1321,7 +1446,7 @@ static void WL_SwapBuffers(void)
}
if (w.hasssd)
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.
else
w.csdsize = Font_CharPHeight(font_default)+8;
@ -1339,21 +1464,24 @@ static void WL_SwapBuffers(void)
}
//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.
w.absmouse |= !w.relative_pointer || !w.locked_pointer;
if (!w.absmouse && !w.locked_pointer && w.pointer_constraints)
wantabs |= !w.relative_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);
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_destroy((struct wl_proxy *) w.locked_pointer);
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)
{
#ifdef DYNAMIC_WAYLAND
if (!WL_InitLibrary())
{
Con_Printf("couldn't load wayland client libraries\n");
return false;
}
#endif
WL_Setup_XDG_Shell();
switch(qrenderer)
{
#if defined(GLQUAKE) && defined(USE_EGL)
case QR_OPENGL:
#ifdef DYNAMIC_WAYLAND
lib_wayland_egl = Sys_LoadLibrary("libwayland-egl.so.1", waylandexports_egl);
if (!lib_wayland_egl)
{
Con_Printf("couldn't load libwayland-egl.so.1 library\n");
return false;
}
#endif
// setenv("EGL_PLATFORM", "wayland", 1); //if this actually matters then we're kinda screwed
if (!EGL_LoadLibrary(info->subrenderer))
@ -1441,7 +1573,9 @@ static qboolean WL_Init (rendererstate_t *info, unsigned char *palette)
memset(&w, 0, sizeof(w));
#ifdef DYNAMIC_WAYLAND
if (WL_InitLibraryXKB())
#endif
w.xkb_context = pxkb_context_new(XKB_CONTEXT_NO_FLAGS);
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);
}
#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");
#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");
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))
{
Con_Printf("couldn't initialise EGL context\n");
@ -1711,7 +1857,10 @@ rendererinfo_t rendererinfo_wayland_gl =
GLBE_RenderToTextureUpdate2d,
"",
WL_GetPriority
WL_GetPriority,
NULL,
NULL,
WL_MayRefresh
};
#endif

View File

@ -52,260 +52,242 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
#endif
#ifdef VKQUAKE
{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"
"\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"
"\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"
"\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\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"
"\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"
"\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\x07\x00\x3D\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\x03\x00\x43\x00\x00\x00\x76\x63\x00\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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\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"
"\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"
"\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"
"\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"
"\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\x47\x00\x04\x00\x3D\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\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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\xF7\x00\x03\x00\x41\x00\x00\x00\x00\x00\x00\x00\xFA\x00\x04\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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\x08\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\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\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"
"\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"
"\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"
"\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"
"\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"
"\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\x47\x00\x04\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\x46\x00\x00\x00\x1E\x00\x00\x00\x00\x00\x00\x00\x47\x00\x04\x00\x48\x00\x00\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"
"\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"
"\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\x20\x00\x04\x00\x14\x00\x00\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\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\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\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\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\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\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\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\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\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\x3B\x00\x04\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"
"\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"
"\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"
"\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"
"\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\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\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\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\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"},
"\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"
"\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"
"\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\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\x3E\x00\x00\x00\x40\x00\x00\x00\x44\x00\x00\x00\x4B\x00\x00\x00\x4C\x00\x00\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"
"\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\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"
"\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"
"\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"
"\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"
"\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\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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\x47\x00\x04\x00\x3E\x00\x00\x00\x1E\x00\x00\x00\x01\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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\x20\x00\x04\x00\x3D\x00\x00\x00\x03\x00\x00\x00\x07\x00\x00\x00\x3B\x00\x04\x00\x3D\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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\x3D\x00\x04\x00\x07\x00\x00\x00\x41\x00\x00\x00\x40\x00\x00\x00\x3E\x00\x03\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"
"\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"
"\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\x52\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\x08\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"
"\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\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\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\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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\x20\x00\x04\x00\x14\x00\x00\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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"
"\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\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"
"\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"
"\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"
"\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
#ifdef D3D11QUAKE
{QR_DIRECT3D11, 11, "fixedemu",
@ -354,6 +336,247 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"#endif\n"
},
#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
{QR_OPENGL, 110, "altwater",
"!!cvardf r_glsl_turbscale_reflect=1 //simpler scaler\n"

View File

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

View File

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

View File

@ -98,7 +98,7 @@ reeval:
op = st->op;
#endif
switch (op)
safeswitch ((enum qcop_e)op)
{
case OP_ADD_F:
OPC->_float = OPA->_float + OPB->_float;
@ -180,10 +180,10 @@ reeval:
OPC->_int = (int)(OPA->_int >= OPB->_int);
break;
case OP_GE_IF:
OPC->_int = (float)(OPA->_int >= OPB->_float);
OPC->_int = (int)(OPA->_int >= OPB->_float);
break;
case OP_GE_FI:
OPC->_int = (float)(OPA->_float >= OPB->_int);
OPC->_int = (int)(OPA->_float >= OPB->_int);
break;
case OP_LE_F:
@ -193,10 +193,13 @@ reeval:
OPC->_int = (int)(OPA->_int <= OPB->_int);
break;
case OP_LE_IF:
OPC->_int = (float)(OPA->_int <= OPB->_float);
OPC->_int = (int)(OPA->_int <= OPB->_float);
break;
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;
case OP_GT_F:
@ -206,10 +209,10 @@ reeval:
OPC->_int = (int)(OPA->_int > OPB->_int);
break;
case OP_GT_IF:
OPC->_int = (float)(OPA->_int > OPB->_float);
OPC->_int = (int)(OPA->_int > OPB->_float);
break;
case OP_GT_FI:
OPC->_int = (float)(OPA->_float > OPB->_int);
OPC->_int = (int)(OPA->_float > OPB->_int);
break;
case OP_LT_F:
@ -219,10 +222,13 @@ reeval:
OPC->_int = (int)(OPA->_int < OPB->_int);
break;
case OP_LT_IF:
OPC->_int = (float)(OPA->_int < OPB->_float);
OPC->_int = (int)(OPA->_int < OPB->_float);
break;
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;
case OP_AND_F:
@ -1015,6 +1021,12 @@ reeval:
else
OPC->_int = OPA->_int / OPB->_int;
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:
OPC->_int = (OPA->_int == OPB->_int);
break;
@ -1136,6 +1148,25 @@ reeval:
OPC->_int = ptr->_int;
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:
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)))
@ -1165,6 +1196,9 @@ reeval:
case OP_RSHIFT_I:
OPC->_int = OPA->_int >> OPB->_int;
break;
case OP_RSHIFT_U:
OPC->_uint = OPA->_uint >> OPB->_uint;
break;
case OP_LSHIFT_I:
OPC->_int = OPA->_int << OPB->_int;
break;
@ -1454,9 +1488,12 @@ reeval:
OPC->_float = (OPA->_float / OPB->_int);
break;
case OP_MOD_I:
/*case OP_MOD_I:
OPC->_int = (OPA->_int % OPB->_int);
break;
case OP_MOD_U:
OPC->_uint = (OPA->_uint % OPB->_uint);
break;
case OP_MOD_F:
OPC->_float = OPA->_float - OPB->_float*(int)(OPA->_float/OPB->_float);
break;
@ -1464,7 +1501,7 @@ reeval:
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[2] = OPA->_vector[2] - OPB->_vector[2]*(int)(OPA->_vector[2]/OPB->_vector[2]);
break;
break;*/
case OP_AND_I:
@ -1605,9 +1642,7 @@ reeval:
case OP_LE_U64: OPC->_int = 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_STORE_I64: OPB->_int64 = OPA->_int64;
// 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_STORE_I64: OPB->_int64 = OPA->_int64; break;
case OP_CONV_UI64: OPC->_int64 = OPA->_uint; break;
case OP_CONV_II64: OPC->_int64 = OPA->_int; 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_MUL_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_LE_D: OPC->_double = OPA->_double <= OPB->_double; break;
case OP_EQ_D: OPC->_double = OPA->_double == OPB->_double; break;
case OP_NE_D: OPC->_double = OPA->_double != OPB->_double; break;
case OP_LT_D: OPC->_int = OPA->_double < OPB->_double; break;
case OP_LE_D: OPC->_int = OPA->_double <= OPB->_double; break;
case OP_EQ_D: OPC->_int = 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!
{
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;
}
edictrun_t tempedict; //used as a safty buffer
edictrun_t tempedict={ER_FREE}; //used as a safty buffer
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
@ -574,14 +574,13 @@ static void PDECL PR_Configure (pubprogfuncs_t *ppf, size_t addressable_size, in
prinst.profiling = profiling;
prinst.profilingalert = Sys_GetClockRate();
prinst.maxedicts = 1;
progfuncs->funcs.edicttable_length = prinst.maxedicts = 0;
prinst.edicttable = (edictrun_t**)(progfuncs->funcs.edicttable = &sv_edicts);
progfuncs->funcs.edicttable_length = 1;
sv_num_edicts = 1; //set up a safty buffer so things won't go horribly wrong too often
sv_num_edicts = 0; //set up a safty buffer so things won't go horribly wrong too often
sv_edicts=(struct edict_s *)&tempedict;
tempedict.readonly = true;
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;
}
//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)
{
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)
{
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)
return (eval_t*)(temp->value + offset);
else
return (eval_t*)dummy;
else if (datasize <= sizeof(dummy))
return &dummy;
}
}
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.
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;
newtemp->size = newsize;
memcpy(newtemp->value, temp->value, 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;
}
//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)
{
progfuncs_t *progfuncs = (progfuncs_t*)inst;

View File

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

View File

@ -52,6 +52,23 @@ typedef unsigned char pbyte;
#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
#pragma warning(disable : 4244)

View File

@ -288,7 +288,7 @@ typedef struct progexterns_s {
pubprogfuncs_t * PDECL InitProgs(progparms_t *ext);
typedef union eval_s
{
{ //FIXME: we should not be using a leading underscore here. that is reserved for libc.
string_t string;
pvec_t _float;
pvec_t _vector[3];
@ -297,7 +297,7 @@ typedef union eval_s
puint_t _uint;
pint64_t _int64;
puint64_t _uint64;
double _double;
pdouble_t _double;
pint_t edict;
pvec_t prog; //so it can easily be changed
} 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.
#define G_FLOAT(o) (((pvec_t *)pr_globals)[o])
#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_UINT(o) (((puint_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
#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
//64bit primitives allows for:
// greater precision timers (so maps can last longer without getting restarted)
@ -24,8 +32,8 @@ typedef float pvec_t;
typedef int pint_t;
typedef unsigned int puint_t;
#ifdef _MSC_VER
typedef __int64 pint64_t;
typedef unsigned __int64 puint64_t;
typedef __int64 pint64_t QC_ALIGN(4);
typedef unsigned __int64 puint64_t QC_ALIGN(4);
#define pPRId "d"
#define pPRIi "i"
@ -36,8 +44,8 @@ typedef unsigned int puint_t;
#define pPRIx64 "I64x"
#else
#include <inttypes.h>
typedef int64_t pint64_t;
typedef uint64_t puint64_t;
typedef int64_t pint64_t QC_ALIGN(4);
typedef uint64_t puint64_t QC_ALIGN(4);
#define pPRId PRId32
#define pPRIi PRIi32
@ -50,6 +58,7 @@ typedef unsigned int puint_t;
#define QCVM_32
#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 pvec_t pvec3_t[3];
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;
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;
void QCC_OPCodeSetTarget(qcc_targetformat_t targfmt, unsigned int targver);
pbool QCC_OPCodeSetTargetName(const char *targ);
@ -337,7 +338,7 @@ typedef union QCC_eval_s
{
QCC_string_t string;
pvec_t _float;
double _double;
pdouble_t _double;
pvec_t vector[3];
func_t function;
pint_t _int;
@ -1126,6 +1127,7 @@ extern int numtypeinfos;
extern int maxtypeinfos;
extern int ForcedCRC;
extern float qcc_framerate; //number of OP_STATE ticks per second.
extern pbool defaultnoref;
extern pbool defaultnosave;
extern pbool defaultstatic;

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