[yquake2] 01/05: New upstream version 7.10+ctf1.05~dfsg
Simon McVittie
smcv at debian.org
Sun Dec 10 21:16:22 UTC 2017
This is an automated email from the git hooks/post-receive script.
smcv pushed a commit to annotated tag debian/7.10+ctf1.05_dfsg-1
in repository yquake2.
commit ec97f12c8d5b898fb4652c4e60b3d38409f612ef
Author: Simon McVittie <smcv at debian.org>
Date: Sun Dec 10 19:55:14 2017 +0000
New upstream version 7.10+ctf1.05~dfsg
---
CHANGELOG | 15 +
CMakeLists.txt | 3 +
Makefile | 6 +-
src/backends/generic/vid.c | 23 +-
src/backends/sdl/input.c | 724 +++++++++++++++++++++++++++++++++++++-
src/backends/sdl/refresh.c | 32 +-
src/backends/unix/system.c | 49 ++-
src/backends/windows/system.c | 2 +-
src/client/cl_cin.c | 17 +-
src/client/cl_keyboard.c | 58 ++-
src/client/cl_main.c | 10 +-
src/client/cl_prediction.c | 4 +-
src/client/cl_screen.c | 2 +-
src/client/cl_tempentities.c | 20 +-
src/client/header/client.h | 6 +-
src/client/header/keyboard.h | 14 +-
src/client/menu/menu.c | 280 +++++++++------
src/client/menu/videomenu.c | 11 +-
src/client/refresh/files/pcx.c | 64 +++-
src/client/refresh/gl/r_main.c | 11 +
src/client/refresh/gl/r_sdl.c | 13 +
src/client/refresh/gl3/gl3_main.c | 11 +
src/client/refresh/gl3/gl3_sdl.c | 16 +-
src/client/sound/ogg.c | 21 +-
src/client/sound/sound.c | 10 +
src/common/collision.c | 24 +-
src/common/frame.c | 16 +
src/common/header/common.h | 2 +-
src/common/header/shared.h | 4 +-
29 files changed, 1264 insertions(+), 204 deletions(-)
diff --git a/CHANGELOG b/CHANGELOG
index 17aeb32..862e844 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,18 @@
+Quake II 7.02 to 7.10:
+- Joystick support including haptic feedback. This fantastic work was
+ done by Denis Pauk. The dirty work is done by SDL, how good or bad
+ a joystick or gamepad is supported depends on SDLs support for it.
+- Fix the old SDL sound backend, s_openal set to 0 is working again.
+- Fix possible Vorbis buffer underruns if too many sound samples are
+ in flight. This occured only in large multi player games with at
+ least 6 custom models.
+- Fix a possible crash on Windows if MSAA was set to a value not
+ supported by the driver.
+- It's now possible to play through the whole game on a Raspberry PI
+ and other ARM boards. Please note that the RPIs hardware is really
+ limited. Only the OpenGL 1.4 renderer is supported and the framerate
+ is highly dependend on the screen resolution.
+
Quake II 7.01 to 7.02:
- Fix several corner cases regarding render library loading. The game
should now always fall back to the OpenGL 1.4 renderer if the new
diff --git a/CMakeLists.txt b/CMakeLists.txt
index c836f02..84e260d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -531,6 +531,7 @@ set_target_properties(game PROPERTIES
PREFIX ""
LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/release/baseq2
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/release/baseq2
+ SUFFIX ${CMAKE_SHARED_LIBRARY_SUFFIX}
)
target_link_libraries(game ${yquake2LinkerFlags})
@@ -540,6 +541,7 @@ set_target_properties(ref_gl1 PROPERTIES
PREFIX ""
LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/release
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/release
+ SUFFIX ${CMAKE_SHARED_LIBRARY_SUFFIX}
)
target_link_libraries(ref_gl1 ${yquake2LinkerFlags} ${yquake2OpenGLLinkerFlags} ${yquake2SDLLinkerFlags})
@@ -549,5 +551,6 @@ set_target_properties(ref_gl3 PROPERTIES
PREFIX ""
LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/release
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/release
+ SUFFIX ${CMAKE_SHARED_LIBRARY_SUFFIX}
)
target_link_libraries(ref_gl3 ${yquake2LinkerFlags} ${yquake2SDLLinkerFlags})
diff --git a/Makefile b/Makefile
index 801db08..a34985f 100755
--- a/Makefile
+++ b/Makefile
@@ -277,7 +277,7 @@ endif
CFLAGS += -fvisibility=hidden
LDFLAGS += -fvisibility=hidden
-ifneq ($(YQ2_OSTYPE), $(filter $(YQ2_OSTYPE), Darwin, OpenBSD))
+ifneq ($(YQ2_OSTYPE), $(filter $(YQ2_OSTYPE), Darwin OpenBSD))
# for some reason the OSX & OpenBSD linker doesn't support this
LDFLAGS += -Wl,--no-undefined
endif
@@ -451,7 +451,7 @@ ifeq ($(YQ2_OSTYPE), OpenBSD)
release/quake2 : CFLAGS += -DUSE_OPENAL -DDEFAULT_OPENAL_DRIVER='"libopenal.so"' -DDLOPEN_OPENAL
else ifeq ($(YQ2_OSTYPE), Darwin)
release/quake2 : CFLAGS += -DUSE_OPENAL -DDEFAULT_OPENAL_DRIVER='"libopenal.dylib"' -I/usr/local/opt/openal-soft/include -DDLOPEN_OPENAL
-release/quake2 : LDFLAGS += -L/usr/local/opt/openal-soft/lib
+release/quake2 : LDFLAGS += -L/usr/local/opt/openal-soft/lib -rpath /usr/local/opt/openal-soft/lib
else
release/quake2 : CFLAGS += -DUSE_OPENAL -DDEFAULT_OPENAL_DRIVER='"libopenal.so.1"' -DDLOPEN_OPENAL
endif
@@ -460,7 +460,7 @@ release/quake2 : CFLAGS += -DUSE_OPENAL
release/quake2 : LDFLAGS += -lopenal
ifeq ($(YQ2_OSTYPE), Darwin)
release/quake2 : CFLAGS += -I/usr/local/opt/openal-soft/include
-release/quake2 : LDFLAGS += -L/usr/local/opt/openal-soft/lib
+release/quake2 : LDFLAGS += -L/usr/local/opt/openal-soft/lib -rpath /usr/local/opt/openal-soft/lib
endif # Darwin
endif # !DLOPEN_OPENAL
endif # WITH_OPENAL
diff --git a/src/backends/generic/vid.c b/src/backends/generic/vid.c
index 76f6a9c..8a653b6 100644
--- a/src/backends/generic/vid.c
+++ b/src/backends/generic/vid.c
@@ -101,6 +101,14 @@ vidmode_t vid_modes[] = {
{"Mode 21: 1920x1080", 1920, 1080, 21},
{"Mode 22: 1920x1200", 1920, 1200, 22},
{"Mode 23: 2048x1536", 2048, 1536, 23},
+ {"Mode 24: 2560x1080", 2560, 1080, 24},
+ {"Mode 25: 2560x1440", 2560, 1440, 25},
+ {"Mode 26: 2560x1600", 2560, 1600, 26},
+ {"Mode 27: 3440x1440", 3440, 1440, 27},
+ {"Mode 28: 3840x1600", 3840, 1600, 28},
+ {"Mode 29: 3840x2160", 3840, 2160, 29},
+ {"Mode 30: 4096x2160", 4096, 2160, 30},
+ {"Mode 31: 5120x2880", 5120, 2880, 31},
};
/* Console variables that we need to access from this module */
@@ -177,11 +185,18 @@ VID_CheckChanges(void)
cls.disable_screen = true;
// Proceed to reboot the refresher
- if(!VID_LoadRefresh() && (strcmp(vid_renderer->string, "gl1") != 0))
+ if(!VID_LoadRefresh())
{
- Com_Printf("\n ... trying again with standard OpenGL1.x renderer ... \n\n");
- Cvar_Set("vid_renderer", "gl1");
- VID_LoadRefresh();
+ if (strcmp(vid_renderer->string, "gl1") != 0)
+ {
+ Com_Printf("\n ... trying again with standard OpenGL1.x renderer ... \n\n");
+ Cvar_Set("vid_renderer", "gl1");
+ VID_LoadRefresh();
+ }
+ else
+ {
+ Com_Error(ERR_FATAL, "Couldn't load a rendering backend!\n");
+ }
}
cls.disable_screen = false;
}
diff --git a/src/backends/sdl/input.c b/src/backends/sdl/input.c
index 2034617..23233bb 100644
--- a/src/backends/sdl/input.c
+++ b/src/backends/sdl/input.c
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2010 Yamagi Burmeister
- * Copyright (C) 1997-2001 Id Software, Inc.
+ * Copyright (C) 1997-2005 Id Software, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -23,6 +23,8 @@
* This is the Quake II input system backend, implemented with SDL.
*
* =======================================================================
+ *
+ * Joystick threshold code is partially based on http://ioquake3.org code.
*/
#include "../../client/header/keyboard.h"
@@ -61,16 +63,65 @@
#define MOUSE_MAX 3000
#define MOUSE_MIN 40
-
+
/* Globals */
static int mouse_x, mouse_y;
static int old_mouse_x, old_mouse_y;
static qboolean mlooking;
+#if SDL_VERSION_ATLEAST(2, 0, 0)
+static float joystick_yaw, joystick_pitch;
+static float joystick_forwardmove, joystick_sidemove;
+static float joystick_up;
+static int back_button_id = -1;
+static char last_hat = SDL_HAT_CENTERED;
+static qboolean left_trigger = false;
+static qboolean right_trigger = false;
+qboolean show_haptic = false;
+
+/* Haptic feedback types */
+enum QHARPICTYPES {
+ HAPTIC_EFFECT_UNKNOWN = -1,
+ HAPTIC_EFFECT_BLASTER = 0,
+ HAPTIC_EFFECT_MENY,
+ HAPTIC_EFFECT_HYPER_BLASTER,
+ HAPTIC_EFFECT_MACHINEGUN,
+ HAPTIC_EFFECT_SHOTGUN,
+ HAPTIC_EFFECT_SSHOTGUN,
+ HAPTIC_EFFECT_RAILGUN,
+ HAPTIC_EFFECT_ROCKETGUN,
+ HAPTIC_EFFECT_GRENADE,
+ HAPTIC_EFFECT_BFG,
+ HAPTIC_EFFECT_PALANX,
+ HAPTIC_EFFECT_IONRIPPER,
+ HAPTIC_EFFECT_ETFRIFLE,
+ HAPTIC_EFFECT_SHOTGUN2,
+ HAPTIC_EFFECT_TRACKER,
+ HAPTIC_EFFECT_PAIN,
+ HAPTIC_EFFECT_STEP,
+ HAPTIC_EFFECT_TRAPCOCK,
+ HAPTIC_EFFECT_LAST
+};
+
+struct hapric_effects_cache {
+ int effect_type;
+ int effect_id;
+};
+
+static int last_haptic_volume = 0;
+static struct hapric_effects_cache last_haptic_efffect[HAPTIC_EFFECT_LAST];
+static int last_haptic_efffect_size = HAPTIC_EFFECT_LAST;
+static int last_haptic_efffect_pos = 0;
+
+/* Joystick */
+static SDL_Haptic *joystick_haptic = NULL;
+static SDL_Joystick *joystick = NULL;
+static SDL_GameController *controller = NULL;
+#endif
+
/* CVars */
cvar_t *vid_fullscreen;
static cvar_t *in_grab;
-static cvar_t *in_mouse;
static cvar_t *exponential_speedup;
cvar_t *freelook;
cvar_t *lookstrafe;
@@ -78,10 +129,35 @@ cvar_t *m_forward;
static cvar_t *m_filter;
cvar_t *m_pitch;
cvar_t *m_side;
+cvar_t *m_up;
cvar_t *m_yaw;
cvar_t *sensitivity;
static cvar_t *windowed_mouse;
+#if SDL_VERSION_ATLEAST(2, 0, 0)
+/* Joystick sensitivity */
+static cvar_t *joy_yawsensitivity;
+static cvar_t *joy_pitchsensitivity;
+static cvar_t *joy_forwardsensitivity;
+static cvar_t *joy_sidesensitivity;
+static cvar_t *joy_upsensitivity;
+/* Joystick direction settings */
+static cvar_t *joy_axis_leftx;
+static cvar_t *joy_axis_lefty;
+static cvar_t *joy_axis_rightx;
+static cvar_t *joy_axis_righty;
+static cvar_t *joy_axis_triggerleft;
+static cvar_t *joy_axis_triggerright;
+/* Joystick threshold settings */
+static cvar_t *joy_axis_leftx_threshold;
+static cvar_t *joy_axis_lefty_threshold;
+static cvar_t *joy_axis_rightx_threshold;
+static cvar_t *joy_axis_righty_threshold;
+static cvar_t *joy_axis_triggerleft_threshold;
+static cvar_t *joy_axis_triggerright_threshold;
+/* Joystick haptic */
+static cvar_t *joy_haptic_magnitude;
+#endif
extern void GLimp_GrabInput(qboolean grab);
@@ -447,10 +523,162 @@ IN_Update(void)
}
#endif
break;
+#if SDL_VERSION_ATLEAST(2, 0, 0)
+ case SDL_CONTROLLERBUTTONUP:
+ case SDL_CONTROLLERBUTTONDOWN: /* Handle Controller Back button */
+ {
+ qboolean down = (event.type == SDL_CONTROLLERBUTTONDOWN);
+ if(event.cbutton.button == SDL_CONTROLLER_BUTTON_BACK) {
+ Key_Event(K_JOY_BACK, down, true);
+ }
+ }
+ break;
+ case SDL_CONTROLLERAXISMOTION: /* Handle Controller Motion */
+ {
+ char* direction_type;
+ float threshold = 0;
+ float fix_value = 0;
+ int axis_value = event.caxis.value;
+ switch (event.caxis.axis)
+ {
+ /* left/right */
+ case SDL_CONTROLLER_AXIS_LEFTX:
+ direction_type = joy_axis_leftx->string;
+ threshold = joy_axis_leftx_threshold->value;
+ break;
+ /* top/bottom */
+ case SDL_CONTROLLER_AXIS_LEFTY:
+ direction_type = joy_axis_lefty->string;
+ threshold = joy_axis_lefty_threshold->value;
+ break;
+ /* second left/right */
+ case SDL_CONTROLLER_AXIS_RIGHTX:
+ direction_type = joy_axis_rightx->string;
+ threshold = joy_axis_rightx_threshold->value;
+ break;
+ /* second top/bottom */
+ case SDL_CONTROLLER_AXIS_RIGHTY:
+ direction_type = joy_axis_righty->string;
+ threshold = joy_axis_righty_threshold->value;
+ break;
+ case SDL_CONTROLLER_AXIS_TRIGGERLEFT:
+ direction_type = joy_axis_triggerleft->string;
+ threshold = joy_axis_triggerleft_threshold->value;
+ break;
+ case SDL_CONTROLLER_AXIS_TRIGGERRIGHT:
+ direction_type = joy_axis_triggerright->string;
+ threshold = joy_axis_triggerright_threshold->value;
+ break;
+ default:
+ direction_type = "none";
+ }
+
+ if (threshold > 0.9)
+ threshold = 0.9;
+
+ if (axis_value < 0 && (axis_value > (32768 * threshold)))
+ axis_value = 0;
+ else if (axis_value > 0 && (axis_value < (32768 * threshold)))
+ axis_value = 0;
+
+ // Smoothly ramp from dead zone to maximum value (from ioquake)
+ // https://github.com/ioquake/ioq3/blob/master/code/sdl/sdl_input.c
+ fix_value = ((float)abs(axis_value) / 32767.0f - threshold) / (1.0f - threshold);
+ if (fix_value < 0.0f)
+ fix_value = 0.0f;
+
+ axis_value = (int)(32767 * ((axis_value < 0) ? -fix_value : fix_value));
+
+ if (cls.key_dest == key_game && (int)cl_paused->value == 0)
+ {
+ if (strcmp(direction_type, "sidemove") == 0)
+ {
+ joystick_sidemove = axis_value * joy_sidesensitivity->value;
+ // We need to be twice faster because with joystic we run...
+ joystick_sidemove *= cl_sidespeed->value * 2.0f;
+ }
+ else if (strcmp(direction_type, "forwardmove") == 0)
+ {
+ joystick_forwardmove = axis_value * joy_forwardsensitivity->value;
+ // We need to be twice faster because with joystic we run...
+ joystick_forwardmove *= cl_forwardspeed->value * 2.0f;
+ }
+ else if (strcmp(direction_type, "yaw") == 0)
+ {
+ joystick_yaw = axis_value * joy_yawsensitivity->value;
+ joystick_yaw *= cl_yawspeed->value;
+ }
+ else if (strcmp(direction_type, "pitch") == 0)
+ {
+ joystick_pitch = axis_value * joy_pitchsensitivity->value;
+ joystick_pitch *= cl_pitchspeed->value;
+ }
+ else if (strcmp(direction_type, "updown") == 0)
+ {
+ joystick_up = axis_value * joy_upsensitivity->value;
+ joystick_up *= cl_upspeed->value;
+ }
+ }
+
+ if (strcmp(direction_type, "triggerleft") == 0)
+ {
+ qboolean new_left_trigger = abs(axis_value) > (32767 / 4);
+ if (new_left_trigger != left_trigger)
+ {
+ left_trigger = new_left_trigger;
+ Key_Event(K_TRIG_LEFT, left_trigger, true);
+ }
+ }
+ else if (strcmp(direction_type, "triggerright") == 0)
+ {
+ qboolean new_right_trigger = abs(axis_value) > (32767 / 4);
+ if (new_right_trigger != right_trigger)
+ {
+ right_trigger = new_right_trigger;
+ Key_Event(K_TRIG_RIGHT, right_trigger, true);
+ }
+ }
+ }
+ break;
+ /* Joystick can have more buttons than on general game controller
+ * so try to map not free buttons */
+ case SDL_JOYBUTTONUP:
+ case SDL_JOYBUTTONDOWN:
+ {
+ qboolean down = (event.type == SDL_JOYBUTTONDOWN);
+ /* Ignore back button, we dont need event for such button */
+ if (back_button_id == event.jbutton.button)
+ return;
+ if(event.jbutton.button <= (K_JOY32 - K_JOY1)) {
+ Key_Event(event.jbutton.button + K_JOY1, down, true);
+ }
+ }
+ break;
+ case SDL_JOYHATMOTION:
+ {
+ if (last_hat != event.jhat.value)
+ {
+ char diff = last_hat ^ event.jhat.value;
+ int i;
+ for (i=0; i < 4; i++) {
+ if (diff & (1 << i)) {
+ /* check that we have button up for some bit */
+ if (last_hat & (1 << i))
+ Key_Event(i + K_HAT_UP, false, true);
+ /* check that we have button down for some bit */
+ if (event.jhat.value & (1 << i))
+ Key_Event(i + K_HAT_UP, true, true);
+ }
+ }
+ last_hat = event.jhat.value;
+ }
+ }
+ break;
+#endif
case SDL_QUIT:
Com_Quit();
-
+
break;
}
}
@@ -480,7 +708,7 @@ In_FlushQueue(void)
Key_MarkAllUp();
}
-
+
/*
* Move handling
*/
@@ -559,8 +787,41 @@ IN_Move(usercmd_t *cmd)
mouse_x = mouse_y = 0;
}
+
+#if SDL_VERSION_ATLEAST(2, 0, 0)
+ // to make the the viewangles changes independent of framerate
+ // we need to scale with frametime (assuming the configured values are for 60hz)
+ // 1/32768 is to normalize the input values from SDL (they're between -32768 and 32768 and we want -1 to 1)
+ // (for movement this is not needed, as those are absolute values independent of framerate)
+ float joyViewFactor = (1.0f/32768.0f) * (cls.rframetime/0.01666f);
+
+ if (joystick_yaw)
+ {
+ cl.viewangles[YAW] -= (m_yaw->value * joystick_yaw) * joyViewFactor;
+ }
+
+ if(joystick_pitch)
+ {
+ cl.viewangles[PITCH] += (m_pitch->value * joystick_pitch) * joyViewFactor;
+ }
+
+ if (joystick_forwardmove)
+ {
+ cmd->forwardmove -= (m_forward->value * joystick_forwardmove) / 32768;
+ }
+
+ if (joystick_sidemove)
+ {
+ cmd->sidemove += (m_side->value * joystick_sidemove) / 32768;
+ }
+
+ if (joystick_up)
+ {
+ cmd->upmove -= (m_up->value * joystick_up) / 32768;
+ }
+#endif
}
-
+
/* ------------------------------------------------------------------ */
/*
@@ -582,7 +843,317 @@ IN_MLookUp(void)
IN_CenterView();
}
+#if SDL_VERSION_ATLEAST(2, 0, 0)
+/*
+ * Shutdown haptic functionality
+ */
+static void IN_Haptic_Shutdown(void);
+
/* ------------------------------------------------------------------ */
+/*
+ * Init haptic effects
+ */
+static int
+IN_Haptic_Effect_Init(int dir, int period, int magnitude, int length, int attack, int fade)
+{
+ /*
+ * Direction:
+ * North - 0
+ * East - 9000
+ * South - 18000
+ * West - 27000
+ */
+ int effect_id;
+ static SDL_HapticEffect haptic_effect;
+ SDL_memset(&haptic_effect, 0, sizeof(SDL_HapticEffect)); // 0 is safe default
+ haptic_effect.type = SDL_HAPTIC_SINE;
+ haptic_effect.periodic.direction.type = SDL_HAPTIC_POLAR; // Polar coordinates
+ haptic_effect.periodic.direction.dir[0] = dir;
+ haptic_effect.periodic.period = period;
+ haptic_effect.periodic.magnitude = magnitude;
+ haptic_effect.periodic.length = length;
+ haptic_effect.periodic.attack_length = attack;
+ haptic_effect.periodic.fade_length = fade;
+ effect_id = SDL_HapticNewEffect(joystick_haptic, &haptic_effect);
+ if (effect_id < 0)
+ {
+ Com_Printf ("SDL_HapticNewEffect failed: %s\n", SDL_GetError());
+ Com_Printf ("Please try to rerun game. Effects will be disabled for now.\n");
+ IN_Haptic_Shutdown();
+ }
+ return effect_id;
+}
+
+static int
+IN_Haptic_Effects_To_Id(int haptic_effect)
+{
+ if ((SDL_HapticQuery(joystick_haptic) & SDL_HAPTIC_SINE)==0)
+ return -1;
+
+ int hapric_volume = joy_haptic_magnitude->value * 255; // * 128 = 32767 max strength;
+ if (hapric_volume > 255)
+ hapric_volume = 255;
+ else if (hapric_volume < 0)
+ hapric_volume = 0;
+
+ switch(haptic_effect) {
+ case HAPTIC_EFFECT_MENY:
+ case HAPTIC_EFFECT_TRAPCOCK:
+ case HAPTIC_EFFECT_STEP:
+ /* North */
+ return IN_Haptic_Effect_Init(
+ 0/* Force comes from N*/, 500/* 500 ms*/, hapric_volume * 48,
+ 200/* 0.2 seconds long */, 100/* Takes 0.1 second to get max strength */,
+ 100/* Takes 0.1 second to fade away */);
+ case HAPTIC_EFFECT_PAIN:
+ return IN_Haptic_Effect_Init(
+ 0/* Force comes from N*/, 700/* 700 ms*/, hapric_volume * 196,
+ 300/* 0.3 seconds long */, 200/* Takes 0.2 second to get max strength */,
+ 200/* Takes 0.2 second to fade away */);
+ case HAPTIC_EFFECT_BLASTER:
+ /* 30 degrees */
+ return IN_Haptic_Effect_Init(
+ 2000/* Force comes from NNE*/, 500/* 500 ms*/, hapric_volume * 64,
+ 200/* 0.2 seconds long */, 100/* Takes 0.1 second to get max strength */,
+ 100/* Takes 0.1 second to fade away */);
+ case HAPTIC_EFFECT_HYPER_BLASTER:
+ return IN_Haptic_Effect_Init(
+ 4000/* Force comes from NNE*/, 500/* 500 ms*/, hapric_volume * 64,
+ 200/* 0.2 seconds long */, 100/* Takes 0.1 second to get max strength */,
+ 100/* Takes 0.1 second to fade away */);
+ case HAPTIC_EFFECT_ETFRIFLE:
+ /* 60 degrees */
+ return IN_Haptic_Effect_Init(
+ 5000/* Force comes from NEE*/, 500/* 500 ms*/, hapric_volume * 64,
+ 200/* 0.2 seconds long */, 100/* Takes 0.1 second to get max strength */,
+ 100/* Takes 0.1 second to fade away */);
+ case HAPTIC_EFFECT_TRACKER:
+ return IN_Haptic_Effect_Init(
+ 7000/* Force comes from NEE*/, 500/* 500 ms*/, hapric_volume * 64,
+ 200/* 0.2 seconds long */, 100/* Takes 0.1 second to get max strength */,
+ 100/* Takes 0.1 second to fade away */);
+ case HAPTIC_EFFECT_MACHINEGUN:
+ /* 90 degrees */
+ return IN_Haptic_Effect_Init(
+ 9000/* Force comes from E*/, 800/* 800 ms*/, hapric_volume * 88,
+ 600/* 0.6 seconds long */, 200/* Takes 0.2 second to get max strength */,
+ 400/* Takes 0.4 second to fade away */);
+ case HAPTIC_EFFECT_SHOTGUN:
+ /* 120 degrees */
+ return IN_Haptic_Effect_Init(
+ 12000/* Force comes from EES*/, 700/* 700 ms*/, hapric_volume * 100,
+ 500/* 0.5 seconds long */, 100/* Takes 0.1 second to get max strength */,
+ 200/* Takes 0.2 second to fade away */);
+ case HAPTIC_EFFECT_SHOTGUN2:
+ /* 150 degrees */
+ return IN_Haptic_Effect_Init(
+ 14000/* Force comes from ESS*/, 700/* 700 ms*/, hapric_volume * 96,
+ 500/* 0.5 seconds long */, 100/* Takes 0.1 second to get max strength */,
+ 100/* Takes 0.1 second to fade away */);
+ case HAPTIC_EFFECT_SSHOTGUN:
+ return IN_Haptic_Effect_Init(
+ 16000/* Force comes from ESS*/, 700/* 700 ms*/, hapric_volume * 96,
+ 500/* 0.5 seconds long */, 100/* Takes 0.1 second to get max strength */,
+ 100/* Takes 0.1 second to fade away */);
+ case HAPTIC_EFFECT_RAILGUN:
+ /* 180 degrees */
+ return IN_Haptic_Effect_Init(
+ 18000/* Force comes from S*/, 700/* 700 ms*/, hapric_volume * 64,
+ 400/* 0.4 seconds long */, 100/* Takes 0.1 second to get max strength */,
+ 100/* Takes 0.1 second to fade away */);
+ case HAPTIC_EFFECT_ROCKETGUN:
+ /* 210 degrees */
+ return IN_Haptic_Effect_Init(
+ 21000/* Force comes from SSW*/, 700/* 700 ms*/, hapric_volume * 128,
+ 400/* 0.4 seconds long */, 300/* Takes 0.3 second to get max strength */,
+ 100/* Takes 0.1 second to fade away */);
+ case HAPTIC_EFFECT_GRENADE:
+ /* 240 degrees */
+ return IN_Haptic_Effect_Init(
+ 24000/* Force comes from SWW*/, 500/* 500 ms*/, hapric_volume * 64,
+ 200/* 0.2 seconds long */, 100/* Takes 0.1 second to get max strength */,
+ 100/* Takes 0.1 second to fade away */);
+ case HAPTIC_EFFECT_BFG:
+ /* 270 degrees */
+ return IN_Haptic_Effect_Init(
+ 27000/* Force comes from W*/, 800/* 800 ms*/, hapric_volume * 100,
+ 600/* 0.2 seconds long */, 100/* Takes 0.1 second to get max strength */,
+ 100/* Takes 0.1 second to fade away */);
+ case HAPTIC_EFFECT_PALANX:
+ /* 300 degrees */
+ return IN_Haptic_Effect_Init(
+ 30000/* Force comes from WWN*/, 500/* 500 ms*/, hapric_volume * 64,
+ 200/* 0.2 seconds long */, 100/* Takes 0.1 second to get max strength */,
+ 100/* Takes 0.1 second to fade away */);
+ case HAPTIC_EFFECT_IONRIPPER:
+ /* 330 degrees */
+ return IN_Haptic_Effect_Init(
+ 33000/* Force comes from WNN*/, 500/* 500 ms*/, hapric_volume * 64,
+ 200/* 0.2 seconds long */, 100/* Takes 0.1 second to get max strength */,
+ 100/* Takes 0.1 second to fade away */);
+ default:
+ return -1;
+ }
+}
+
+static void
+IN_Haptic_Effects_Info(void)
+{
+ show_haptic = true;
+ Com_Printf ("Joystic/Mouse haptic:\n");
+ Com_Printf (" * %d effects\n", SDL_HapticNumEffects(joystick_haptic));
+ Com_Printf (" * %d effects in same time\n", SDL_HapticNumEffectsPlaying(joystick_haptic));
+ Com_Printf (" * %d haptic axis\n", SDL_HapticNumAxes(joystick_haptic));
+}
+
+static void
+IN_Haptic_Effects_Init(void)
+{
+ last_haptic_efffect_size = SDL_HapticNumEffectsPlaying(joystick_haptic);
+ if (last_haptic_efffect_size > HAPTIC_EFFECT_LAST)
+ last_haptic_efffect_size = HAPTIC_EFFECT_LAST;
+ for (int i=0; i<HAPTIC_EFFECT_LAST; i++)
+ {
+ last_haptic_efffect[i].effect_type = HAPTIC_EFFECT_UNKNOWN;
+ last_haptic_efffect[i].effect_id = -1;
+ }
+}
+
+/*
+ * Shuts the backend down
+ */
+static void
+IN_Haptic_Effect_Shutdown(int * effect_id)
+{
+ if (!effect_id)
+ return;
+ if (*effect_id >= 0)
+ SDL_HapticDestroyEffect(joystick_haptic, *effect_id);
+ *effect_id = -1;
+}
+
+static void
+IN_Haptic_Effects_Shutdown(void)
+{
+ for (int i=0; i<HAPTIC_EFFECT_LAST; i++)
+ {
+ last_haptic_efffect[i].effect_type = HAPTIC_EFFECT_UNKNOWN;
+ IN_Haptic_Effect_Shutdown(&last_haptic_efffect[i].effect_id);
+ }
+}
+#endif
+
+void
+Haptic_Feedback(char *name)
+{
+#if SDL_VERSION_ATLEAST(2, 0, 0)
+ int effect_type = HAPTIC_EFFECT_UNKNOWN;
+
+ if (joy_haptic_magnitude->value <= 0)
+ return;
+
+ if (!joystick_haptic)
+ return;
+
+ if (last_haptic_volume != (int)(joy_haptic_magnitude->value * 255))
+ {
+ IN_Haptic_Effects_Shutdown();
+ IN_Haptic_Effects_Init();
+ }
+ last_haptic_volume = joy_haptic_magnitude->value * 255;
+
+ if (strstr(name, "misc/menu"))
+ {
+ effect_type = HAPTIC_EFFECT_MENY;
+ }
+ else if (strstr(name, "weapons/blastf1a"))
+ {
+ effect_type = HAPTIC_EFFECT_BLASTER;
+ }
+ else if (strstr(name, "weapons/hyprbf1a"))
+ {
+ effect_type = HAPTIC_EFFECT_HYPER_BLASTER;
+ }
+ else if (strstr(name, "weapons/machgf"))
+ {
+ effect_type = HAPTIC_EFFECT_MACHINEGUN;
+ }
+ else if (strstr(name, "weapons/shotgf1b"))
+ {
+ effect_type = HAPTIC_EFFECT_SHOTGUN;
+ }
+ else if (strstr(name, "weapons/sshotf1b"))
+ {
+ effect_type = HAPTIC_EFFECT_SSHOTGUN;
+ }
+ else if (strstr(name, "weapons/railgf1a"))
+ {
+ effect_type = HAPTIC_EFFECT_RAILGUN;
+ }
+ else if (strstr(name, "weapons/rocklf1a"))
+ {
+ effect_type = HAPTIC_EFFECT_ROCKETGUN;
+ }
+ else if (strstr(name, "weapons/grenlf1a") || strstr(name, "weapons/hgrent1a"))
+ {
+ effect_type = HAPTIC_EFFECT_GRENADE;
+ }
+ else if (strstr(name, "weapons/bfg__f1y"))
+ {
+ effect_type = HAPTIC_EFFECT_BFG;
+ }
+ else if (strstr(name, "weapons/plasshot"))
+ {
+ effect_type = HAPTIC_EFFECT_PALANX;
+ }
+ else if (strstr(name, "weapons/rippfire"))
+ {
+ effect_type = HAPTIC_EFFECT_IONRIPPER;
+ }
+ else if (strstr(name, "weapons/nail1"))
+ {
+ effect_type = HAPTIC_EFFECT_ETFRIFLE;
+ }
+ else if (strstr(name, "weapons/shotg2"))
+ {
+ effect_type = HAPTIC_EFFECT_SHOTGUN2;
+ }
+ else if (strstr(name, "weapons/disint2"))
+ {
+ effect_type = HAPTIC_EFFECT_TRACKER;
+ }
+ else if (strstr(name, "player/male/pain") ||
+ strstr(name, "player/female/pain") ||
+ strstr(name, "players/male/pain") ||
+ strstr(name, "players/female/pain"))
+ {
+ effect_type = HAPTIC_EFFECT_PAIN;
+ }
+ else if (strstr(name, "player/step") ||
+ strstr(name, "player/land"))
+ {
+ effect_type = HAPTIC_EFFECT_STEP;
+ }
+ else if (strstr(name, "weapons/trapcock"))
+ {
+ effect_type = HAPTIC_EFFECT_TRAPCOCK;
+ }
+
+ if (effect_type != HAPTIC_EFFECT_UNKNOWN)
+ {
+ // check last effect for reuse
+ if (last_haptic_efffect[last_haptic_efffect_pos].effect_type != effect_type)
+ {
+ // FIFO for effects
+ last_haptic_efffect_pos = (last_haptic_efffect_pos+1) % last_haptic_efffect_size;
+ IN_Haptic_Effect_Shutdown(&last_haptic_efffect[last_haptic_efffect_pos].effect_id);
+ last_haptic_efffect[last_haptic_efffect_pos].effect_type = effect_type;
+ last_haptic_efffect[last_haptic_efffect_pos].effect_id = IN_Haptic_Effects_To_Id(effect_type);
+ }
+ SDL_HapticRunEffect(joystick_haptic, last_haptic_efffect[last_haptic_efffect_pos].effect_id, 1);
+ }
+#endif
+}
/*
* Initializes the backend
@@ -594,17 +1165,46 @@ IN_Init(void)
mouse_x = mouse_y = 0;
+#if SDL_VERSION_ATLEAST(2, 0, 0)
+ joystick_yaw = joystick_pitch = joystick_forwardmove = joystick_sidemove = 0;
+#endif
+
exponential_speedup = Cvar_Get("exponential_speedup", "0", CVAR_ARCHIVE);
freelook = Cvar_Get("freelook", "1", 0);
in_grab = Cvar_Get("in_grab", "2", CVAR_ARCHIVE);
- in_mouse = Cvar_Get("in_mouse", "0", CVAR_ARCHIVE);
lookstrafe = Cvar_Get("lookstrafe", "0", 0);
m_filter = Cvar_Get("m_filter", "0", CVAR_ARCHIVE);
+ m_up = Cvar_Get("m_up", "1", 0);
m_forward = Cvar_Get("m_forward", "1", 0);
m_pitch = Cvar_Get("m_pitch", "0.022", 0);
m_side = Cvar_Get("m_side", "0.8", 0);
m_yaw = Cvar_Get("m_yaw", "0.022", 0);
sensitivity = Cvar_Get("sensitivity", "3", 0);
+
+#if SDL_VERSION_ATLEAST(2, 0, 0)
+ joy_haptic_magnitude = Cvar_Get("joy_haptic_magnitude", "0.0", CVAR_ARCHIVE);
+
+ joy_yawsensitivity = Cvar_Get("joy_yawsensitivity", "1.0", CVAR_ARCHIVE);
+ joy_pitchsensitivity = Cvar_Get("joy_pitchsensitivity", "1.0", CVAR_ARCHIVE);
+ joy_forwardsensitivity = Cvar_Get("joy_forwardsensitivity", "1.0", CVAR_ARCHIVE);
+ joy_sidesensitivity = Cvar_Get("joy_sidesensitivity", "1.0", CVAR_ARCHIVE);
+ joy_upsensitivity = Cvar_Get("joy_upsensitivity", "1.0", CVAR_ARCHIVE);
+
+ joy_axis_leftx = Cvar_Get("joy_axis_leftx", "sidemove", CVAR_ARCHIVE);
+ joy_axis_lefty = Cvar_Get("joy_axis_lefty", "forwardmove", CVAR_ARCHIVE);
+ joy_axis_rightx = Cvar_Get("joy_axis_rightx", "yaw", CVAR_ARCHIVE);
+ joy_axis_righty = Cvar_Get("joy_axis_righty", "pitch", CVAR_ARCHIVE);
+ joy_axis_triggerleft = Cvar_Get("joy_axis_triggerleft", "triggerleft", CVAR_ARCHIVE);
+ joy_axis_triggerright = Cvar_Get("joy_axis_triggerright", "triggerright", CVAR_ARCHIVE);
+
+ joy_axis_leftx_threshold = Cvar_Get("joy_axis_leftx_threshold", "0.15", CVAR_ARCHIVE);
+ joy_axis_lefty_threshold = Cvar_Get("joy_axis_lefty_threshold", "0.15", CVAR_ARCHIVE);
+ joy_axis_rightx_threshold = Cvar_Get("joy_axis_rightx_threshold", "0.15", CVAR_ARCHIVE);
+ joy_axis_righty_threshold = Cvar_Get("joy_axis_righty_threshold", "0.15", CVAR_ARCHIVE);
+ joy_axis_triggerleft_threshold = Cvar_Get("joy_axis_triggerleft_threshold", "0.15", CVAR_ARCHIVE);
+ joy_axis_triggerright_threshold = Cvar_Get("joy_axis_triggerright_threshold", "0.15", CVAR_ARCHIVE);
+#endif
+
vid_fullscreen = Cvar_Get("vid_fullscreen", "0", CVAR_ARCHIVE);
windowed_mouse = Cvar_Get("windowed_mouse", "1", CVAR_USERINFO | CVAR_ARCHIVE);
@@ -617,12 +1217,103 @@ IN_Init(void)
SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
#endif
+#if SDL_VERSION_ATLEAST(2, 0, 0)
+ /* joystik init */
+ if (!SDL_WasInit(SDL_INIT_GAMECONTROLLER | SDL_INIT_HAPTIC))
+ {
+ if (SDL_Init(SDL_INIT_GAMECONTROLLER | SDL_INIT_HAPTIC) == -1)
+ {
+ Com_Printf ("Couldn't init SDL joystick: %s.\n", SDL_GetError ());
+ } else {
+ Com_Printf ("%i joysticks were found.\n", SDL_NumJoysticks());
+ if (SDL_NumJoysticks() > 0) {
+ int i;
+ for (i=0; i<SDL_NumJoysticks(); i ++) {
+ joystick = SDL_JoystickOpen(i);
+ Com_Printf ("The name of the joystick is '%s'\n", SDL_JoystickName(joystick));
+ Com_Printf ("Number of Axes: %d\n", SDL_JoystickNumAxes(joystick));
+ Com_Printf ("Number of Buttons: %d\n", SDL_JoystickNumButtons(joystick));
+ Com_Printf ("Number of Balls: %d\n", SDL_JoystickNumBalls(joystick));
+ Com_Printf ("Number of Hats: %d\n", SDL_JoystickNumHats(joystick));
+
+ joystick_haptic = SDL_HapticOpenFromJoystick(joystick);
+ if (joystick_haptic == NULL)
+ Com_Printf ("Most likely joystick isn't haptic\n");
+ else
+ IN_Haptic_Effects_Info();
+
+ if(SDL_IsGameController(i))
+ {
+ SDL_GameControllerButtonBind backBind;
+ controller = SDL_GameControllerOpen(i);
+ Com_Printf ("Controller settings: %s\n", SDL_GameControllerMapping(controller));
+ Com_Printf ("Controller axis: \n");
+ Com_Printf (" * leftx = %s\n", joy_axis_leftx->string);
+ Com_Printf (" * lefty = %s\n", joy_axis_lefty->string);
+ Com_Printf (" * rightx = %s\n", joy_axis_rightx->string);
+ Com_Printf (" * righty = %s\n", joy_axis_righty->string);
+ Com_Printf (" * triggerleft = %s\n", joy_axis_triggerleft->string);
+ Com_Printf (" * triggerright = %s\n", joy_axis_triggerright->string);
+
+ Com_Printf ("Controller thresholds: \n");
+ Com_Printf (" * leftx = %f\n", joy_axis_leftx_threshold->value);
+ Com_Printf (" * lefty = %f\n", joy_axis_lefty_threshold->value);
+ Com_Printf (" * rightx = %f\n", joy_axis_rightx_threshold->value);
+ Com_Printf (" * righty = %f\n", joy_axis_righty_threshold->value);
+ Com_Printf (" * triggerleft = %f\n", joy_axis_triggerleft_threshold->value);
+ Com_Printf (" * triggerright = %f\n", joy_axis_triggerright_threshold->value);
+
+ backBind = SDL_GameControllerGetBindForButton(controller, SDL_CONTROLLER_BUTTON_BACK);
+
+ if (backBind.bindType == SDL_CONTROLLER_BINDTYPE_BUTTON) {
+ back_button_id = backBind.value.button;
+ Com_Printf ("\nBack button JOY%d will be unbindable.\n", back_button_id+1);
+ }
+ break;
+ }
+ else
+ {
+ char joystick_guid[256] = {0};
+ SDL_JoystickGUID guid;
+ guid = SDL_JoystickGetDeviceGUID(i);
+ SDL_JoystickGetGUIDString(guid, joystick_guid, 255);
+ Com_Printf ("For use joystic as game contoller please set SDL_GAMECONTROLLERCONFIG:\n");
+ Com_Printf ("e.g.: SDL_GAMECONTROLLERCONFIG='%s,%s,leftx:a0,lefty:a1,rightx:a2,righty:a3,back:b1,...\n", joystick_guid, SDL_JoystickName(joystick));
+ }
+ }
+ }
+ else
+ {
+ joystick_haptic = SDL_HapticOpenFromMouse();
+ if (joystick_haptic == NULL)
+ Com_Printf ("Most likely mouse isn't haptic\n");
+ else
+ IN_Haptic_Effects_Info();
+ }
+ }
+ }
+#endif
+
Com_Printf("------------------------------------\n\n");
}
+#if SDL_VERSION_ATLEAST(2, 0, 0)
/*
* Shuts the backend down
*/
+static void
+IN_Haptic_Shutdown(void)
+{
+ if (joystick_haptic)
+ {
+ IN_Haptic_Effects_Shutdown();
+
+ SDL_HapticClose(joystick_haptic);
+ joystick_haptic = NULL;
+ }
+}
+#endif
+
void
IN_Shutdown(void)
{
@@ -630,7 +1321,24 @@ IN_Shutdown(void)
Cmd_RemoveCommand("+mlook");
Cmd_RemoveCommand("-mlook");
- Com_Printf("Shutting down input.\n");
+ Com_Printf("Shutting down input.\n");
+
+#if SDL_VERSION_ATLEAST(2, 0, 0)
+ IN_Haptic_Shutdown();
+
+ if (controller)
+ {
+ back_button_id = -1;
+ SDL_GameControllerClose(controller);
+ controller = NULL;
+ }
+
+ if (joystick)
+ {
+ SDL_JoystickClose(joystick);
+ joystick = NULL;
+ }
+#endif
}
/* ------------------------------------------------------------------ */
diff --git a/src/backends/sdl/refresh.c b/src/backends/sdl/refresh.c
index 073db64..569bce7 100644
--- a/src/backends/sdl/refresh.c
+++ b/src/backends/sdl/refresh.c
@@ -232,6 +232,7 @@ static qboolean GetWindowSize(int* w, int* h)
return true;
}
+static qboolean initSuccessful = false;
/*
* Initializes the OpenGL window
@@ -257,7 +258,9 @@ GLimp_InitGraphics(int fullscreen, int *pwidth, int *pheight)
}
#endif
- if (GetWindowSize(&curWidth, &curHeight) && (curWidth == width) && (curHeight == height))
+ // only do this if we already have a working window and fully initialized rendering backend
+ // (GLimp_InitGraphics() is also called when recovering if creating GL context fails or the one we got is unusable)
+ if (initSuccessful && GetWindowSize(&curWidth, &curHeight) && (curWidth == width) && (curHeight == height))
{
/* If we want fullscreen, but aren't */
if (fullscreen != IsFullscreen())
@@ -319,20 +322,17 @@ GLimp_InitGraphics(int fullscreen, int *pwidth, int *pheight)
{
if (!CreateSDLWindow(flags, width, height))
{
- if (flags & SDL_OPENGL)
+ if((flags & SDL_OPENGL) && gl_msaa_samples->value)
{
- if (gl_msaa_samples->value)
- {
- Com_Printf("SDL SetVideoMode failed: %s\n", SDL_GetError());
- Com_Printf("Reverting to %s gl_mode %i (%ix%i) without MSAA.\n",
- (flags & fs_flag) ? "fullscreen" : "windowed",
- (int) Cvar_VariableValue("gl_mode"), width, height);
-
- /* Try to recover */
- Cvar_SetValue("gl_msaa_samples", 0);
- SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 0);
- SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 0);
- }
+ Com_Printf("SDL SetVideoMode failed: %s\n", SDL_GetError());
+ Com_Printf("Reverting to %s gl_mode %i (%ix%i) without MSAA.\n",
+ (flags & fs_flag) ? "fullscreen" : "windowed",
+ (int) Cvar_VariableValue("gl_mode"), width, height);
+
+ /* Try to recover */
+ Cvar_SetValue("gl_msaa_samples", 0);
+ SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 0);
+ SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 0);
}
else if (width != 640 || height != 480 || (flags & fs_flag))
{
@@ -374,6 +374,8 @@ GLimp_InitGraphics(int fullscreen, int *pwidth, int *pheight)
/* No cursor */
SDL_ShowCursor(0);
+ initSuccessful = true;
+
return true;
}
@@ -453,6 +455,8 @@ VID_ShutdownWindow(void)
// make sure that after vid_restart the refreshrate will be queried from SDL2 again.
glimp_refreshRate = -1;
+ initSuccessful = false; // not initialized anymore
+
if (SDL_WasInit(SDL_INIT_EVERYTHING) == SDL_INIT_VIDEO)
{
SDL_Quit();
diff --git a/src/backends/unix/system.c b/src/backends/unix/system.c
index 410f436..1b6409a 100644
--- a/src/backends/unix/system.c
+++ b/src/backends/unix/system.c
@@ -46,6 +46,11 @@
#include <dirent.h>
#include <time.h>
+#ifdef __APPLE__
+#include <mach/clock.h>
+#include <mach/mach.h>
+#endif
+
#include "../../common/header/common.h"
#include "../../common/header/glob.h"
#include "../generic/header/input.h"
@@ -82,19 +87,49 @@ Sys_Init(void)
long long
Sys_Microseconds(void)
{
- static struct timespec last;
- struct timespec now;
+#ifdef __APPLE__
+ // OSX didn't have clock_gettime() until recently, so use Mach's clock_get_time()
+ // instead. fortunately its mach_timespec_t seems identical to POSIX struct timespec
+ // so lots of code can be shared
+ clock_serv_t cclock;
+ mach_timespec_t now;
+ static mach_timespec_t first;
+
+ host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &cclock);
+ clock_get_time(cclock, &now);
+ mach_port_deallocate(mach_task_self(), cclock);
+
+#else // not __APPLE__ - other Unix-likes will hopefully support clock_gettime()
+ struct timespec now;
+ static struct timespec first;
+ #ifdef _POSIX_MONOTONIC_CLOCK
clock_gettime(CLOCK_MONOTONIC, &now);
+ #else
+ clock_gettime(CLOCK_REALTIME, &now);
+ #endif
+
+#endif // not __APPLE__
- if(last.tv_sec == 0)
+ if(first.tv_sec == 0)
{
- clock_gettime(CLOCK_MONOTONIC, &last);
- return last.tv_nsec / 1000ll;
+ long long nsec = now.tv_nsec;
+ long long sec = now.tv_sec;
+ // set back first by 1ms so neither this function nor Sys_Milliseconds()
+ // (which calls this) will ever return 0
+ nsec -= 1000000;
+ if(nsec < 0)
+ {
+ nsec += 1000000000ll; // 1s in ns => definitely positive now
+ --sec;
+ }
+
+ first.tv_sec = sec;
+ first.tv_nsec = nsec;
}
- long long sec = now.tv_sec - last.tv_sec;
- long long nsec = now.tv_nsec - last.tv_nsec;
+ long long sec = now.tv_sec - first.tv_sec;
+ long long nsec = now.tv_nsec - first.tv_nsec;
if(nsec < 0)
{
diff --git a/src/backends/windows/system.c b/src/backends/windows/system.c
index 94c4267..3fa5147 100644
--- a/src/backends/windows/system.c
+++ b/src/backends/windows/system.c
@@ -432,7 +432,7 @@ Sys_Microseconds(void)
if (!uSecbase)
{
- uSecbase = microseconds / 1000ll;
+ uSecbase = microseconds - 1001ll;
}
return microseconds - uSecbase;
diff --git a/src/client/cl_cin.c b/src/client/cl_cin.c
index 36b278b..62644e4 100644
--- a/src/client/cl_cin.c
+++ b/src/client/cl_cin.c
@@ -66,7 +66,7 @@ SCR_LoadPCX(char *filename, byte **pic, byte **palette, int *width, int *height)
byte *raw;
pcx_t *pcx;
int x, y;
- int len;
+ int len, full_size;
int dataByte, runLength;
byte *out, *pix;
@@ -75,7 +75,7 @@ SCR_LoadPCX(char *filename, byte **pic, byte **palette, int *width, int *height)
/* load the file */
len = FS_LoadFile(filename, (void **)&raw);
- if (!raw)
+ if (!raw || len < sizeof(pcx_t))
{
return;
}
@@ -95,7 +95,8 @@ SCR_LoadPCX(char *filename, byte **pic, byte **palette, int *width, int *height)
return;
}
- out = Z_Malloc((pcx->ymax + 1) * (pcx->xmax + 1));
+ full_size = (pcx->ymax + 1) * (pcx->xmax + 1);
+ out = Z_Malloc(full_size);
*pic = out;
@@ -135,7 +136,15 @@ SCR_LoadPCX(char *filename, byte **pic, byte **palette, int *width, int *height)
while (runLength-- > 0)
{
- pix[x++] = dataByte;
+ if ((*pic + full_size) <= (pix + x))
+ {
+ x += runLength;
+ runLength = 0;
+ }
+ else
+ {
+ pix[x++] = dataByte;
+ }
}
}
}
diff --git a/src/client/cl_keyboard.c b/src/client/cl_keyboard.c
index 2b3c26c..3e612b3 100644
--- a/src/client/cl_keyboard.c
+++ b/src/client/cl_keyboard.c
@@ -106,6 +106,49 @@ keyname_t keynames[] = {
{"MOUSE4", K_MOUSE4},
{"MOUSE5", K_MOUSE5},
+ {"JOY1", K_JOY1},
+ {"JOY2", K_JOY2},
+ {"JOY3", K_JOY3},
+ {"JOY4", K_JOY4},
+ {"JOY5", K_JOY5},
+ {"JOY6", K_JOY6},
+ {"JOY7", K_JOY7},
+ {"JOY8", K_JOY8},
+ {"JOY9", K_JOY9},
+ {"JOY10", K_JOY10},
+ {"JOY11", K_JOY11},
+ {"JOY12", K_JOY12},
+ {"JOY13", K_JOY13},
+ {"JOY14", K_JOY14},
+ {"JOY15", K_JOY15},
+ {"JOY16", K_JOY16},
+ {"JOY17", K_JOY17},
+ {"JOY18", K_JOY18},
+ {"JOY19", K_JOY19},
+ {"JOY20", K_JOY20},
+ {"JOY21", K_JOY21},
+ {"JOY22", K_JOY22},
+ {"JOY23", K_JOY23},
+ {"JOY24", K_JOY24},
+ {"JOY25", K_JOY25},
+ {"JOY26", K_JOY26},
+ {"JOY27", K_JOY27},
+ {"JOY28", K_JOY28},
+ {"JOY29", K_JOY29},
+ {"JOY30", K_JOY30},
+ {"JOY31", K_JOY31},
+ {"JOY32", K_JOY32},
+
+ {"HAT_UP", K_HAT_UP},
+ {"HAT_RIGHT", K_HAT_RIGHT},
+ {"HAT_DOWN", K_HAT_DOWN},
+ {"HAT_LEFT", K_HAT_LEFT},
+
+ {"TRIG_LEFT", K_TRIG_LEFT},
+ {"TRIG_RIGHT", K_TRIG_RIGHT},
+
+ {"JOY_BACK", K_JOY_BACK},
+
{"AUX1", K_AUX1},
{"AUX2", K_AUX2},
{"AUX3", K_AUX3},
@@ -562,7 +605,7 @@ Key_Message(int key)
}
/*
- * Returns a key number to be used to index
+ * Returns a key number to be used to index
* keybindings[] by looking at the given string.
* Single ascii characters return themselves, while
* the K_* names are matched up.
@@ -715,7 +758,7 @@ Key_Bind_f(void)
}
/* don't allow binding escape or the special console keys */
- if(b == K_ESCAPE || b == '^' || b == '`' || b == '~')
+ if(b == K_ESCAPE || b == '^' || b == '`' || b == '~' || b == K_JOY_BACK)
{
if(doneWithDefaultCfg)
{
@@ -773,7 +816,7 @@ Key_WriteBindings(FILE *f)
{
if (keybindings[i] && keybindings[i][0])
{
- fprintf(f, "bind %s \"%s\"\n",
+ fprintf(f, "bind %s \"%s\"\n",
Key_KeynumToString(i), keybindings[i]);
}
}
@@ -1061,12 +1104,12 @@ Key_Event(int key, qboolean down, qboolean special)
}
/* Key is unbound */
- if ((key >= 200) && !keybindings[key] && (cls.key_dest != key_console))
+ if ((key >= K_MOUSE1 && key != K_JOY_BACK) && !keybindings[key] && (cls.key_dest != key_console))
{
Com_Printf("%s is unbound, hit F4 to set.\n", Key_KeynumToString(key));
}
- /* While in attract loop all keys besides F1 to F12 (to
+ /* While in attract loop all keys besides F1 to F12 (to
allow quick load and the like) are treated like escape. */
if (cl.attractloop && (cls.key_dest != key_menu) &&
!((key >= K_F1) && (key <= K_F12)))
@@ -1081,10 +1124,11 @@ Key_Event(int key, qboolean down, qboolean special)
- moves one menu level up
- closes the menu
- closes the help computer
- - closes the chat window */
+ - closes the chat window
+ Fully same logic for K_JOY_BACK */
if (!cls.disable_screen)
{
- if (key == K_ESCAPE)
+ if (key == K_ESCAPE || key == K_JOY_BACK)
{
if (!down)
{
diff --git a/src/client/cl_main.c b/src/client/cl_main.c
index 3ee4091..4180206 100644
--- a/src/client/cl_main.c
+++ b/src/client/cl_main.c
@@ -57,7 +57,6 @@ cvar_t *cl_showclamp;
cvar_t *cl_paused;
-cvar_t *lookspring;
cvar_t *lookstrafe;
cvar_t *sensitivity;
@@ -93,6 +92,11 @@ centity_t cl_entities[MAX_EDICTS];
entity_state_t cl_parse_entities[MAX_PARSE_ENTITIES];
+/*Evil hack against too many power screen and power
+ shield impact sounds. For example if the player
+ fires his shotgun onto a Brain. */
+int num_power_sounds;
+
extern cvar_t *allow_download;
extern cvar_t *allow_download_players;
extern cvar_t *allow_download_models;
@@ -490,7 +494,6 @@ CL_InitLocal(void)
cl_run = Cvar_Get("cl_run", "0", CVAR_ARCHIVE);
freelook = Cvar_Get("freelook", "1", CVAR_ARCHIVE);
- lookspring = Cvar_Get("lookspring", "0", CVAR_ARCHIVE);
lookstrafe = Cvar_Get("lookstrafe", "0", CVAR_ARCHIVE);
sensitivity = Cvar_Get("sensitivity", "3", CVAR_ARCHIVE);
@@ -735,6 +738,9 @@ CL_Frame(int packetdelta, int renderdelta, int timedelta, qboolean packetframe,
cls.netchan.last_received = Sys_Milliseconds();
}
+ // Reset power shield / power screen sound counter.
+ num_power_sounds = 0;
+
if (!cl_timedemo->value)
{
// Don't throttle too much when connecting / loading.
diff --git a/src/client/cl_prediction.c b/src/client/cl_prediction.c
index a451e23..b607f9e 100644
--- a/src/client/cl_prediction.c
+++ b/src/client/cl_prediction.c
@@ -231,6 +231,7 @@ CL_PredictMovement(void)
pmove_t pm;
int i;
int step;
+ vec3_t tmp;
if (cls.state != ca_active)
{
@@ -296,9 +297,10 @@ CL_PredictMovement(void)
}
step = pm.s.origin[2] - (int)(cl.predicted_origin[2] * 8);
+ VectorCopy(tmp, pm.s.velocity);
if (((step > 126 && step < 130))
- && !VectorCompare((float *)pm.s.velocity, vec3_origin)
+ && !VectorCompare(tmp, vec3_origin)
&& (pm.s.pm_flags & PMF_ON_GROUND))
{
cl.predicted_step = step * 0.125f;
diff --git a/src/client/cl_screen.c b/src/client/cl_screen.c
index e7a6f9d..1c0334d 100644
--- a/src/client/cl_screen.c
+++ b/src/client/cl_screen.c
@@ -1445,7 +1445,7 @@ SCR_Framecounter(void) {
char str[10];
snprintf(str, sizeof(str), "%3.2ffps", (1000.0 * 1000.0) / (avg / num));
- DrawStringScaled(scale*(viddef.width - 80), 0, str, scale);
+ DrawStringScaled(viddef.width - scale*(strlen(str)*8 + 2), 0, str, scale);
} else if (cl_drawfps->value >= 2) {
// Calculate average of frames.
int avg = 0;
diff --git a/src/client/cl_tempentities.c b/src/client/cl_tempentities.c
index 0cb4f69..5b3f539 100644
--- a/src/client/cl_tempentities.c
+++ b/src/client/cl_tempentities.c
@@ -24,7 +24,9 @@
* =======================================================================
*/
+#include <SDL2/SDL_scancode.h>
#include "header/client.h"
+#include "sound/header/local.h"
typedef enum
{
@@ -716,7 +718,23 @@ CL_ParseTEnt(void)
CL_ParticleEffect(pos, dir, 0xb0, 40);
}
- S_StartSound(pos, 0, 0, cl_sfx_lashit, 1, ATTN_NORM, 0);
+ num_power_sounds++;
+
+ /* If too many of these sounds are started in one frame (for
+ * example if the player shoots with the super shotgun into
+ * the power screen of a Brain) things get too loud and OpenAL
+ * is forced to scale the volume of several other sounds and
+ * the background music down. That leads to a noticable and
+ * annoying drop in the overall volume.
+ *
+ * Work around that by limiting the number of sounds started.
+ * 16 was choosen by empirical testing.
+ */
+ if (sound_started == SS_OAL && num_power_sounds < 16)
+ {
+ S_StartSound(pos, 0, 0, cl_sfx_lashit, 1, ATTN_NORM, 0);
+ }
+
break;
case TE_SHOTGUN: /* bullet hitting wall */
diff --git a/src/client/header/client.h b/src/client/header/client.h
index eacad82..9c58b0e 100644
--- a/src/client/header/client.h
+++ b/src/client/header/client.h
@@ -249,6 +249,11 @@ typedef struct
extern client_static_t cls;
+/*Evil hack against too many power screen and power
+ shield impact sounds. For example if the player
+ fires his shotgun onto a Brain. */
+extern int num_power_sounds;
+
/* cvars */
extern cvar_t *gl_stereo_separation;
extern cvar_t *gl_stereo_convergence;
@@ -271,7 +276,6 @@ extern cvar_t *cl_anglespeedkey;
extern cvar_t *cl_shownet;
extern cvar_t *cl_showmiss;
extern cvar_t *cl_showclamp;
-extern cvar_t *lookspring;
extern cvar_t *lookstrafe;
extern cvar_t *sensitivity;
extern cvar_t *m_pitch;
diff --git a/src/client/header/keyboard.h b/src/client/header/keyboard.h
index c6431c0..668606b 100644
--- a/src/client/header/keyboard.h
+++ b/src/client/header/keyboard.h
@@ -144,6 +144,17 @@ enum QKEYS {
K_JOY31,
K_JOY32,
+ K_HAT_UP,
+ K_HAT_RIGHT,
+ K_HAT_DOWN,
+ K_HAT_LEFT,
+
+ K_TRIG_LEFT,
+ K_TRIG_RIGHT,
+
+ /* Can't be mapped to any action */
+ K_JOY_BACK,
+
K_AUX1,
K_AUX2,
K_AUX3,
@@ -305,6 +316,7 @@ void Key_ReadConsoleHistory();
void Key_WriteConsoleHistory();
void Key_SetBinding(int keynum, char *binding);
void Key_MarkAllUp(void);
-int Key_GetKey(void);
+void Haptic_Feedback(char *name);
+int Key_GetMenuKey(int key);
#endif
diff --git a/src/client/menu/menu.c b/src/client/menu/menu.c
index b8c07f6..93336f1 100644
--- a/src/client/menu/menu.c
+++ b/src/client/menu/menu.c
@@ -165,7 +165,7 @@ M_PushMenu(void (*draw)(void), const char *(*key)(int))
}
#ifdef USE_OPENAL
- if (cl.cinematic_file)
+ if (cl.cinematic_file && sound_started == SS_OAL)
{
AL_UnqueueRawSamples();
}
@@ -215,11 +215,122 @@ M_PushMenu(void (*draw)(void), const char *(*key)(int))
cls.key_dest = key_menu;
}
+int
+Key_GetMenuKey(int key)
+{
+ switch (key)
+ {
+ case K_KP_UPARROW:
+ case K_UPARROW:
+ case K_HAT_UP:
+ return K_UPARROW;
+
+ case K_TAB:
+ case K_KP_DOWNARROW:
+ case K_DOWNARROW:
+ case K_HAT_DOWN:
+ return K_DOWNARROW;
+
+ case K_KP_LEFTARROW:
+ case K_LEFTARROW:
+ case K_HAT_LEFT:
+ case K_TRIG_LEFT:
+ return K_LEFTARROW;
+
+ case K_KP_RIGHTARROW:
+ case K_RIGHTARROW:
+ case K_HAT_RIGHT:
+ case K_TRIG_RIGHT:
+ return K_RIGHTARROW;
+
+ case K_MOUSE1:
+ case K_MOUSE2:
+ case K_MOUSE3:
+ case K_MOUSE4:
+ case K_MOUSE5:
+
+ case K_JOY1:
+ case K_JOY2:
+ case K_JOY3:
+ case K_JOY4:
+ case K_JOY5:
+ case K_JOY6:
+ case K_JOY7:
+ case K_JOY8:
+ case K_JOY9:
+ case K_JOY10:
+ case K_JOY11:
+ case K_JOY12:
+ case K_JOY13:
+ case K_JOY14:
+ case K_JOY15:
+ case K_JOY16:
+ case K_JOY17:
+ case K_JOY18:
+ case K_JOY19:
+ case K_JOY20:
+ case K_JOY21:
+ case K_JOY22:
+ case K_JOY23:
+ case K_JOY24:
+ case K_JOY25:
+ case K_JOY26:
+ case K_JOY27:
+ case K_JOY28:
+ case K_JOY29:
+ case K_JOY30:
+ case K_JOY31:
+
+ case K_AUX1:
+ case K_AUX2:
+ case K_AUX3:
+ case K_AUX4:
+ case K_AUX5:
+ case K_AUX6:
+ case K_AUX7:
+ case K_AUX8:
+ case K_AUX9:
+ case K_AUX10:
+ case K_AUX11:
+ case K_AUX12:
+ case K_AUX13:
+ case K_AUX14:
+ case K_AUX15:
+ case K_AUX16:
+ case K_AUX17:
+ case K_AUX18:
+ case K_AUX19:
+ case K_AUX20:
+ case K_AUX21:
+ case K_AUX22:
+ case K_AUX23:
+ case K_AUX24:
+ case K_AUX25:
+ case K_AUX26:
+ case K_AUX27:
+ case K_AUX28:
+ case K_AUX29:
+ case K_AUX30:
+ case K_AUX31:
+ case K_AUX32:
+
+ case K_KP_ENTER:
+ case K_ENTER:
+ return K_ENTER;
+
+ case K_ESCAPE:
+ case K_JOY_BACK:
+ return K_ESCAPE;
+ }
+
+ return key;
+}
const char *
Default_MenuKey(menuframework_s *m, int key)
{
const char *sound = NULL;
menucommon_s *item;
+ int menu_key = Key_GetMenuKey(key);
if (m)
{
@@ -235,110 +346,51 @@ Default_MenuKey(menuframework_s *m, int key)
}
}
- switch (key)
+ switch (menu_key)
{
case K_ESCAPE:
M_PopMenu();
return menu_out_sound;
- case K_KP_UPARROW:
- case K_UPARROW:
+ case K_UPARROW:
if (m)
{
m->cursor--;
Menu_AdjustCursor(m, -1);
sound = menu_move_sound;
}
-
break;
- case K_TAB:
- if (m)
- {
- m->cursor++;
- Menu_AdjustCursor(m, 1);
- sound = menu_move_sound;
- }
-
- break;
- case K_KP_DOWNARROW:
case K_DOWNARROW:
-
if (m)
{
m->cursor++;
Menu_AdjustCursor(m, 1);
sound = menu_move_sound;
}
-
break;
- case K_KP_LEFTARROW:
- case K_LEFTARROW:
+ case K_LEFTARROW:
if (m)
{
Menu_SlideItem(m, -1);
sound = menu_move_sound;
}
-
break;
- case K_KP_RIGHTARROW:
- case K_RIGHTARROW:
+ case K_RIGHTARROW:
if (m)
{
Menu_SlideItem(m, 1);
sound = menu_move_sound;
}
-
break;
- case K_MOUSE1:
- case K_MOUSE2:
- case K_MOUSE3:
- case K_MOUSE4:
- case K_MOUSE5:
- case K_AUX1:
- case K_AUX2:
- case K_AUX3:
- case K_AUX4:
- case K_AUX5:
- case K_AUX6:
- case K_AUX7:
- case K_AUX8:
- case K_AUX9:
- case K_AUX10:
- case K_AUX11:
- case K_AUX12:
- case K_AUX13:
- case K_AUX14:
- case K_AUX15:
- case K_AUX16:
- case K_AUX17:
- case K_AUX18:
- case K_AUX19:
- case K_AUX20:
- case K_AUX21:
- case K_AUX22:
- case K_AUX23:
- case K_AUX24:
- case K_AUX25:
- case K_AUX26:
- case K_AUX27:
- case K_AUX28:
- case K_AUX29:
- case K_AUX30:
- case K_AUX31:
- case K_AUX32:
-
- case K_KP_ENTER:
case K_ENTER:
-
if (m)
{
Menu_SelectItem(m);
}
-
sound = menu_move_sound;
break;
}
@@ -593,35 +645,29 @@ M_Main_Draw(void)
const char *
M_Main_Key(int key)
{
- const char *sound = menu_move_sound;
+ const char *sound = menu_move_sound;
+ int menu_key = Key_GetMenuKey(key);
- switch (key)
+ switch (menu_key)
{
case K_ESCAPE:
M_PopMenu();
break;
- case K_KP_DOWNARROW:
case K_DOWNARROW:
-
if (++m_main_cursor >= MAIN_ITEMS)
{
m_main_cursor = 0;
}
-
return sound;
- case K_KP_UPARROW:
case K_UPARROW:
-
if (--m_main_cursor < 0)
{
m_main_cursor = MAIN_ITEMS - 1;
}
-
return sound;
- case K_KP_ENTER:
case K_ENTER:
m_entersound = true;
@@ -1003,10 +1049,12 @@ static menuslider_s s_options_sensitivity_slider;
static menulist_s s_options_freelook_box;
static menulist_s s_options_alwaysrun_box;
static menulist_s s_options_invertmouse_box;
-static menulist_s s_options_lookspring_box;
static menulist_s s_options_lookstrafe_box;
static menulist_s s_options_crosshair_box;
static menuslider_s s_options_sfxvolume_slider;
+#ifdef SDL2
+static menuslider_s s_options_haptic_slider;
+#endif
#if defined(OGG) || defined(CDA)
static menulist_s s_options_cdshuffle_box;
#endif
@@ -1023,6 +1071,14 @@ CrosshairFunc(void *unused)
Cvar_SetValue("crosshair", (float)s_options_crosshair_box.curvalue);
}
+#ifdef SDL2
+static void
+HapticMagnitudeFunc(void *unused)
+{
+ Cvar_SetValue("joy_haptic_magnitude", s_options_haptic_slider.curvalue / 10.0F);
+}
+#endif
+
static void
CustomizeControlsFunc(void *unused)
{
@@ -1097,13 +1153,15 @@ ControlsSetMenuItemValues(void)
s_options_invertmouse_box.curvalue = (m_pitch->value < 0);
- s_options_lookspring_box.curvalue = (lookspring->value != 0);
-
s_options_lookstrafe_box.curvalue = (lookstrafe->value != 0);
s_options_freelook_box.curvalue = (freelook->value != 0);
s_options_crosshair_box.curvalue = ClampCvar(0, 3, crosshair->value);
+
+#ifdef SDL2
+ s_options_haptic_slider.curvalue = Cvar_VariableValue("joy_haptic_magnitude") * 10.0F;
+#endif
}
static void
@@ -1123,12 +1181,6 @@ InvertMouseFunc(void *unused)
}
static void
-LookspringFunc(void *unused)
-{
- Cvar_SetValue("lookspring", (float)!lookspring->value);
-}
-
-static void
LookstrafeFunc(void *unused)
{
Cvar_SetValue("lookstrafe", (float)!lookstrafe->value);
@@ -1319,7 +1371,11 @@ Options_MenuInit(void)
0
};
- float scale = SCR_GetMenuScale();
+ float scale = SCR_GetMenuScale();
+
+#ifdef SDL2
+ extern qboolean show_haptic;
+#endif
/* configure controls menu and menu items */
s_options_menu.x = viddef.width / 2;
@@ -1389,34 +1445,37 @@ Options_MenuInit(void)
s_options_invertmouse_box.generic.callback = InvertMouseFunc;
s_options_invertmouse_box.itemnames = yesno_names;
- s_options_lookspring_box.generic.type = MTYPE_SPINCONTROL;
- s_options_lookspring_box.generic.x = 0;
- s_options_lookspring_box.generic.y = 90;
- s_options_lookspring_box.generic.name = "lookspring";
- s_options_lookspring_box.generic.callback = LookspringFunc;
- s_options_lookspring_box.itemnames = yesno_names;
-
s_options_lookstrafe_box.generic.type = MTYPE_SPINCONTROL;
s_options_lookstrafe_box.generic.x = 0;
- s_options_lookstrafe_box.generic.y = 100;
+ s_options_lookstrafe_box.generic.y = 90;
s_options_lookstrafe_box.generic.name = "lookstrafe";
s_options_lookstrafe_box.generic.callback = LookstrafeFunc;
s_options_lookstrafe_box.itemnames = yesno_names;
s_options_freelook_box.generic.type = MTYPE_SPINCONTROL;
s_options_freelook_box.generic.x = 0;
- s_options_freelook_box.generic.y = 110;
+ s_options_freelook_box.generic.y = 100;
s_options_freelook_box.generic.name = "free look";
s_options_freelook_box.generic.callback = FreeLookFunc;
s_options_freelook_box.itemnames = yesno_names;
s_options_crosshair_box.generic.type = MTYPE_SPINCONTROL;
s_options_crosshair_box.generic.x = 0;
- s_options_crosshair_box.generic.y = 120;
+ s_options_crosshair_box.generic.y = 110;
s_options_crosshair_box.generic.name = "crosshair";
s_options_crosshair_box.generic.callback = CrosshairFunc;
s_options_crosshair_box.itemnames = crosshair_names;
+#ifdef SDL2
+ s_options_haptic_slider.generic.type = MTYPE_SLIDER;
+ s_options_haptic_slider.generic.x = 0;
+ s_options_haptic_slider.generic.y = 120;
+ s_options_haptic_slider.generic.name = "haptic magnitude";
+ s_options_haptic_slider.generic.callback = HapticMagnitudeFunc;
+ s_options_haptic_slider.minvalue = 0;
+ s_options_haptic_slider.maxvalue = 22;
+#endif
+
s_options_customize_options_action.generic.type = MTYPE_ACTION;
s_options_customize_options_action.generic.x = 0;
s_options_customize_options_action.generic.y = 140;
@@ -1450,10 +1509,15 @@ Options_MenuInit(void)
Menu_AddItem(&s_options_menu, (void *)&s_options_sensitivity_slider);
Menu_AddItem(&s_options_menu, (void *)&s_options_alwaysrun_box);
Menu_AddItem(&s_options_menu, (void *)&s_options_invertmouse_box);
- Menu_AddItem(&s_options_menu, (void *)&s_options_lookspring_box);
Menu_AddItem(&s_options_menu, (void *)&s_options_lookstrafe_box);
Menu_AddItem(&s_options_menu, (void *)&s_options_freelook_box);
Menu_AddItem(&s_options_menu, (void *)&s_options_crosshair_box);
+
+#ifdef SDL2
+ if (show_haptic)
+ Menu_AddItem(&s_options_menu, (void *)&s_options_haptic_slider);
+#endif
+
Menu_AddItem(&s_options_menu, (void *)&s_options_customize_options_action);
Menu_AddItem(&s_options_menu, (void *)&s_options_defaults_action);
Menu_AddItem(&s_options_menu, (void *)&s_options_console_action);
@@ -2305,10 +2369,10 @@ static const char *
LoadGame_MenuKey(int key)
{
static menuframework_s *m = &s_loadgame_menu;
+ int menu_key = Key_GetMenuKey(key);
- switch (key)
+ switch (menu_key)
{
- case K_KP_UPARROW:
case K_UPARROW:
if (m->cursor == 0)
{
@@ -2316,8 +2380,7 @@ LoadGame_MenuKey(int key)
LoadGame_MenuInit();
}
break;
- case K_TAB:
- case K_KP_DOWNARROW:
+
case K_DOWNARROW:
if (m->cursor == m->nitems - 1)
{
@@ -2325,16 +2388,17 @@ LoadGame_MenuKey(int key)
LoadGame_MenuInit();
}
break;
- case K_KP_LEFTARROW:
+
case K_LEFTARROW:
LoadSave_AdjustPage(-1);
LoadGame_MenuInit();
return menu_move_sound;
- case K_KP_RIGHTARROW:
+
case K_RIGHTARROW:
LoadSave_AdjustPage(1);
LoadGame_MenuInit();
return menu_move_sound;
+
default:
s_savegame_menu.cursor = s_loadgame_menu.cursor;
break;
@@ -2416,6 +2480,7 @@ static const char *
SaveGame_MenuKey(int key)
{
static menuframework_s *m = &s_savegame_menu;
+ int menu_key = Key_GetMenuKey(key);
if (m_popup_string)
{
@@ -2423,9 +2488,8 @@ SaveGame_MenuKey(int key)
return NULL;
}
- switch (key)
+ switch (menu_key)
{
- case K_KP_UPARROW:
case K_UPARROW:
if (m->cursor == 0)
{
@@ -2433,8 +2497,7 @@ SaveGame_MenuKey(int key)
SaveGame_MenuInit();
}
break;
- case K_TAB:
- case K_KP_DOWNARROW:
+
case K_DOWNARROW:
if (m->cursor == m->nitems - 1)
{
@@ -2442,16 +2505,17 @@ SaveGame_MenuKey(int key)
SaveGame_MenuInit();
}
break;
- case K_KP_LEFTARROW:
+
case K_LEFTARROW:
LoadSave_AdjustPage(-1);
SaveGame_MenuInit();
return menu_move_sound;
- case K_KP_RIGHTARROW:
+
case K_RIGHTARROW:
LoadSave_AdjustPage(1);
SaveGame_MenuInit();
return menu_move_sound;
+
default:
s_loadgame_menu.cursor = s_savegame_menu.cursor;
break;
@@ -4257,7 +4321,8 @@ M_Menu_PlayerConfig_f(void)
static const char *
M_Quit_Key(int key)
{
- switch (key)
+ int menu_key = Key_GetMenuKey(key);
+ switch (menu_key)
{
case K_ESCAPE:
case 'n':
@@ -4265,6 +4330,7 @@ M_Quit_Key(int key)
M_PopMenu();
break;
+ case K_ENTER:
case 'Y':
case 'y':
cls.key_dest = key_console;
diff --git a/src/client/menu/videomenu.c b/src/client/menu/videomenu.c
index 331dbf7..8511907 100644
--- a/src/client/menu/videomenu.c
+++ b/src/client/menu/videomenu.c
@@ -261,6 +261,14 @@ VID_MenuInit(void)
"[1920 1080 ]",
"[1920 1200 ]",
"[2048 1536 ]",
+ "[2560x1080 ]",
+ "[2560x1440 ]",
+ "[2560x1600 ]",
+ "[3440x1440 ]",
+ "[3840x1600 ]",
+ "[3840x2160 ]",
+ "[4096x2160 ]",
+ "[5120x2880 ]",
"[custom ]",
0
};
@@ -522,8 +530,9 @@ VID_MenuKey(int key)
menuframework_s *m = &s_opengl_menu;
static const char *sound = "misc/menu1.wav";
+ int menu_key = Key_GetMenuKey(key);
- switch (key)
+ switch (menu_key)
{
case K_ESCAPE:
M_PopMenu();
diff --git a/src/client/refresh/files/pcx.c b/src/client/refresh/files/pcx.c
index 010a224..926e0ea 100644
--- a/src/client/refresh/files/pcx.c
+++ b/src/client/refresh/files/pcx.c
@@ -122,7 +122,9 @@ LoadPCX(char *origname, byte **pic, byte **palette, int *width, int *height)
byte *raw;
pcx_t *pcx;
int x, y;
- int len;
+ int len, full_size;
+ int pcx_width, pcx_height;
+ qboolean image_issues = false;
int dataByte, runLength;
byte *out, *pix;
char filename[256];
@@ -145,7 +147,7 @@ LoadPCX(char *origname, byte **pic, byte **palette, int *width, int *height)
/* load the file */
len = ri.FS_LoadFile(filename, (void **)&raw);
- if (!raw)
+ if (!raw || len < sizeof(pcx_t))
{
R_Printf(PRINT_DEVELOPER, "Bad pcx file %s\n", filename);
return;
@@ -165,15 +167,19 @@ LoadPCX(char *origname, byte **pic, byte **palette, int *width, int *height)
raw = &pcx->data;
+ pcx_width = pcx->xmax - pcx->xmin;
+ pcx_height = pcx->ymax - pcx->ymin;
+
if ((pcx->manufacturer != 0x0a) || (pcx->version != 5) ||
(pcx->encoding != 1) || (pcx->bits_per_pixel != 8) ||
- (pcx->xmax >= 640) || (pcx->ymax >= 480))
+ (pcx_width >= 4096) || (pcx_height >= 4096))
{
R_Printf(PRINT_ALL, "Bad pcx file %s\n", filename);
return;
}
- out = malloc((pcx->ymax + 1) * (pcx->xmax + 1));
+ full_size = (pcx_height + 1) * (pcx_width + 1);
+ out = malloc(full_size);
*pic = out;
@@ -182,28 +188,49 @@ LoadPCX(char *origname, byte **pic, byte **palette, int *width, int *height)
if (palette)
{
*palette = malloc(768);
- memcpy(*palette, (byte *)pcx + len - 768, 768);
+ if (len > 768)
+ {
+ memcpy(*palette, (byte *)pcx + len - 768, 768);
+ }
+ else
+ {
+ image_issues = true;
+ }
}
if (width)
{
- *width = pcx->xmax + 1;
+ *width = pcx_width + 1;
}
if (height)
{
- *height = pcx->ymax + 1;
+ *height = pcx_height + 1;
}
- for (y = 0; y <= pcx->ymax; y++, pix += pcx->xmax + 1)
+ for (y = 0; y <= pcx_height; y++, pix += pcx_width + 1)
{
- for (x = 0; x <= pcx->xmax; )
+ for (x = 0; x <= pcx_width; )
{
+ if (raw - (byte *)pcx > len)
+ {
+ // no place for read
+ image_issues = true;
+ x = pcx_width;
+ break;
+ }
dataByte = *raw++;
if ((dataByte & 0xC0) == 0xC0)
{
runLength = dataByte & 0x3F;
+ if (raw - (byte *)pcx > len)
+ {
+ // no place for read
+ image_issues = true;
+ x = pcx_width;
+ break;
+ }
dataByte = *raw++;
}
else
@@ -213,7 +240,17 @@ LoadPCX(char *origname, byte **pic, byte **palette, int *width, int *height)
while (runLength-- > 0)
{
- pix[x++] = dataByte;
+ if ((*pic + full_size) <= (pix + x))
+ {
+ // no place for write
+ image_issues = true;
+ x += runLength;
+ runLength = 0;
+ }
+ else
+ {
+ pix[x++] = dataByte;
+ }
}
}
}
@@ -224,7 +261,7 @@ LoadPCX(char *origname, byte **pic, byte **palette, int *width, int *height)
free(*pic);
*pic = NULL;
}
- else if(pcx->xmax == 319 && pcx->ymax == 239
+ else if(pcx_width == 319 && pcx_height == 239
&& Q_strcasecmp(origname, "pics/quit.pcx") == 0
&& Com_BlockChecksum(pcx, len) == 3329419434u)
{
@@ -233,6 +270,11 @@ LoadPCX(char *origname, byte **pic, byte **palette, int *width, int *height)
fixQuitScreen(*pic);
}
+ if (image_issues)
+ {
+ R_Printf(PRINT_ALL, "PCX file %s has possible size issues.\n", filename);
+ }
+
ri.FS_FreeFile(pcx);
}
diff --git a/src/client/refresh/gl/r_main.c b/src/client/refresh/gl/r_main.c
index 003465b..bc0e213 100644
--- a/src/client/refresh/gl/r_main.c
+++ b/src/client/refresh/gl/r_main.c
@@ -1344,6 +1344,17 @@ R_SetMode(void)
else if (err == rserr_invalid_mode)
{
R_Printf(PRINT_ALL, "ref_gl::R_SetMode() - invalid mode\n");
+ if (gl_msaa_samples->value != 0.0f)
+ {
+ R_Printf(PRINT_ALL, "gl_msaa_samples was %d - will try again with gl_msaa_samples = 0\n", (int)gl_msaa_samples->value);
+ ri.Cvar_SetValue("gl_msaa_samples", 0.0f);
+ gl_msaa_samples->modified = false;
+
+ if ((err = SetMode_impl(&vid.width, &vid.height, gl_mode->value, 0)) == rserr_ok)
+ {
+ return true;
+ }
+ }
if(gl_mode->value == gl_state.prev_mode)
{
// trying again would result in a crash anyway, give up already
diff --git a/src/client/refresh/gl/r_sdl.c b/src/client/refresh/gl/r_sdl.c
index dd64c3c..7a6f261 100644
--- a/src/client/refresh/gl/r_sdl.c
+++ b/src/client/refresh/gl/r_sdl.c
@@ -360,6 +360,11 @@ int RI_PrepareForWindow(void)
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 0);
}
}
+ else
+ {
+ SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 0);
+ SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 0);
+ }
/* Initiate the flags */
#if SDL_VERSION_ATLEAST(2, 0, 0)
@@ -410,6 +415,14 @@ int RI_InitContext(void* win)
#endif
+ const char* glver = (char *)glGetString(GL_VERSION);
+ sscanf(glver, "%d.%d", &gl_config.major_version, &gl_config.minor_version);
+ if (gl_config.major_version < 1 || (gl_config.major_version == 1 && gl_config.minor_version < 4))
+ {
+ R_Printf(PRINT_ALL, "R_InitContext(): Got an OpenGL version %d.%d context - need (at least) 1.4!\n", gl_config.major_version, gl_config.minor_version);
+ return false;
+ }
+
if (gl_msaa_samples->value)
{
if (SDL_GL_GetAttribute(SDL_GL_MULTISAMPLESAMPLES, &msaa_samples) == 0)
diff --git a/src/client/refresh/gl3/gl3_main.c b/src/client/refresh/gl3/gl3_main.c
index b40cff0..ea517d3 100644
--- a/src/client/refresh/gl3/gl3_main.c
+++ b/src/client/refresh/gl3/gl3_main.c
@@ -406,6 +406,17 @@ GL3_SetMode(void)
{
R_Printf(PRINT_ALL, "ref_gl3::GL3_SetMode() - invalid mode\n");
+ if (gl_msaa_samples->value != 0.0f)
+ {
+ R_Printf(PRINT_ALL, "gl_msaa_samples was %d - will try again with gl_msaa_samples = 0\n", (int)gl_msaa_samples->value);
+ ri.Cvar_SetValue("gl_msaa_samples", 0.0f);
+ gl_msaa_samples->modified = false;
+
+ if ((err = SetMode_impl(&vid.width, &vid.height, gl_mode->value, 0)) == rserr_ok)
+ {
+ return true;
+ }
+ }
if(gl_mode->value == gl3state.prev_mode)
{
// trying again would result in a crash anyway, give up already
diff --git a/src/client/refresh/gl3/gl3_sdl.c b/src/client/refresh/gl3/gl3_sdl.c
index 45519c6..c932364 100644
--- a/src/client/refresh/gl3/gl3_sdl.c
+++ b/src/client/refresh/gl3/gl3_sdl.c
@@ -113,6 +113,11 @@ int GL3_PrepareForWindow(void)
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 0);
}
}
+ else
+ {
+ SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 0);
+ SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 0);
+ }
/* Initiate the flags */
#if SDL_VERSION_ATLEAST(2, 0, 0)
@@ -131,7 +136,7 @@ enum {
QGL_DEBUG_SEVERITY_NOTIFICATION = 0x826B
};
-static void
+static void APIENTRY
DebugCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length,
const GLchar *message, const void *userParam)
{
@@ -230,12 +235,17 @@ int GL3_InitContext(void* win)
if(!gladLoadGLLoader(SDL_GL_GetProcAddress))
{
- R_Printf(PRINT_ALL, "R_InitContext(): loading OpenGL function pointers failed!\n");
+ R_Printf(PRINT_ALL, "GL3_InitContext(): ERROR: loading OpenGL function pointers failed!\n");
+ return false;
+ }
+ else if (GLVersion.major < 3 || (GLVersion.major == 3 && GLVersion.minor < 2))
+ {
+ R_Printf(PRINT_ALL, "GL3_InitContext(): ERROR: glad only got GL version %d.%d!\n", GLVersion.major, GLVersion.minor);
return false;
}
else
{
- R_Printf(PRINT_ALL, "Successfully loaded OpenGL function pointers using glad!\n");
+ R_Printf(PRINT_ALL, "Successfully loaded OpenGL function pointers using glad, got version %d.%d!\n", GLVersion.major, GLVersion.minor);
}
#if SDL_VERSION_ATLEAST(2, 0, 0)
diff --git a/src/client/sound/ogg.c b/src/client/sound/ogg.c
index 4f521f7..35fab85 100644
--- a/src/client/sound/ogg.c
+++ b/src/client/sound/ogg.c
@@ -636,18 +636,12 @@ OGG_Stream(void)
/* Calculate the number of buffers used
for storing decoded OGG/Vorbis data.
We take the number of active buffers
- at startup (at this point most of the
- samples should be precached and loaded
- into buffers) and add 64. Empircal
- testing showed, that at most times
- at least 52 buffers remain available
- for OGG/Vorbis, enough for about 3
- seconds playback. The music won't
- stutter as long as the framerate
- stayes over 1 FPS. */
- if (ogg_numbufs == 0)
+ and add 256. 256 are about 12 seconds
+ worth of sound, more than enough to
+ be resilent against underruns. */
+ if (ogg_numbufs == 0 || active_buffers < ogg_numbufs - 256)
{
- ogg_numbufs = active_buffers + 64;
+ ogg_numbufs = active_buffers + 256;
}
/* active_buffers are all active OpenAL buffers,
@@ -761,7 +755,10 @@ OGG_PauseCmd(void)
}
#ifdef USE_OPENAL
- AL_UnqueueRawSamples();
+ if (sound_started == SS_OAL)
+ {
+ AL_UnqueueRawSamples();
+ }
#endif
}
diff --git a/src/client/sound/sound.c b/src/client/sound/sound.c
index 6f98c39..36d384d 100644
--- a/src/client/sound/sound.c
+++ b/src/client/sound/sound.c
@@ -669,6 +669,16 @@ S_StartSound(vec3_t origin, int entnum, int entchannel, sfx_t *sfx,
ps->fixed_origin = false;
}
+ if (sfx->name[0])
+ {
+ // with !fixed we have all sounds related directly to player,
+ // e.g. players fire, pain, menu
+ if (!ps->fixed_origin)
+ {
+ Haptic_Feedback(sfx->name);
+ }
+ }
+
ps->entnum = entnum;
ps->entchannel = entchannel;
ps->attenuation = attenuation;
diff --git a/src/common/collision.c b/src/common/collision.c
index f494013..bdaa5e4 100644
--- a/src/common/collision.c
+++ b/src/common/collision.c
@@ -119,7 +119,7 @@ vec3_t trace_extents;
int c_pointcontents;
int c_traces, c_brush_traces;
#endif
-
+
/* 1/32 epsilon to keep floating point happy */
#define DIST_EPSILON (0.03125f)
@@ -738,7 +738,7 @@ CM_ClipBoxToBrush(vec3_t mins, vec3_t maxs, vec3_t p1,
}
void
-CM_TestBoxInBrush(vec3_t mins, vec3_t maxs, vec3_t p1,
+CM_TestBoxInBrush(vec3_t mins, vec3_t maxs, vec3_t p1,
trace_t *trace, cbrush_t *brush)
{
int i, j;
@@ -1186,7 +1186,7 @@ CMod_LoadSubmodels(lump_t *l)
if (l->filelen % sizeof(*in))
{
- Com_Error(ERR_DROP, "MOD_LoadBmodel: funny lump size");
+ Com_Error(ERR_DROP, "Mod_LoadSubmodels: funny lump size");
}
count = l->filelen / sizeof(*in);
@@ -1230,7 +1230,7 @@ CMod_LoadSurfaces(lump_t *l)
if (l->filelen % sizeof(*in))
{
- Com_Error(ERR_DROP, "MOD_LoadBmodel: funny lump size");
+ Com_Error(ERR_DROP, "Mod_LoadSurfaces: funny lump size");
}
count = l->filelen / sizeof(*in);
@@ -1269,7 +1269,7 @@ CMod_LoadNodes(lump_t *l)
if (l->filelen % sizeof(*in))
{
- Com_Error(ERR_DROP, "MOD_LoadBmodel: funny lump size");
+ Com_Error(ERR_DROP, "Mod_LoadNodes: funny lump size");
}
count = l->filelen / sizeof(*in);
@@ -1311,7 +1311,7 @@ CMod_LoadBrushes(lump_t *l)
if (l->filelen % sizeof(*in))
{
- Com_Error(ERR_DROP, "MOD_LoadBmodel: funny lump size");
+ Com_Error(ERR_DROP, "Mod_LoadBrushes: funny lump size");
}
count = l->filelen / sizeof(*in);
@@ -1345,7 +1345,7 @@ CMod_LoadLeafs(lump_t *l)
if (l->filelen % sizeof(*in))
{
- Com_Error(ERR_DROP, "MOD_LoadBmodel: funny lump size");
+ Com_Error(ERR_DROP, "Mod_LoadLeafs: funny lump size");
}
count = l->filelen / sizeof(*in);
@@ -1415,7 +1415,7 @@ CMod_LoadPlanes(lump_t *l)
if (l->filelen % sizeof(*in))
{
- Com_Error(ERR_DROP, "MOD_LoadBmodel: funny lump size");
+ Com_Error(ERR_DROP, "Mod_LoadPlanes: funny lump size");
}
count = l->filelen / sizeof(*in);
@@ -1466,7 +1466,7 @@ CMod_LoadLeafBrushes(lump_t *l)
if (l->filelen % sizeof(*in))
{
- Com_Error(ERR_DROP, "MOD_LoadBmodel: funny lump size");
+ Com_Error(ERR_DROP, "Mod_LoadLeafBrushes: funny lump size");
}
count = l->filelen / sizeof(*in);
@@ -1504,7 +1504,7 @@ CMod_LoadBrushSides(lump_t *l)
if (l->filelen % sizeof(*in))
{
- Com_Error(ERR_DROP, "MOD_LoadBmodel: funny lump size");
+ Com_Error(ERR_DROP, "Mod_LoadBrushSides: funny lump size");
}
count = l->filelen / sizeof(*in);
@@ -1545,7 +1545,7 @@ CMod_LoadAreas(lump_t *l)
if (l->filelen % sizeof(*in))
{
- Com_Error(ERR_DROP, "MOD_LoadBmodel: funny lump size");
+ Com_Error(ERR_DROP, "Mod_LoadAreas: funny lump size");
}
count = l->filelen / sizeof(*in);
@@ -1578,7 +1578,7 @@ CMod_LoadAreaPortals(lump_t *l)
if (l->filelen % sizeof(*in))
{
- Com_Error(ERR_DROP, "MOD_LoadBmodel: funny lump size");
+ Com_Error(ERR_DROP, "Mod_LoadAreaPortals: funny lump size");
}
count = l->filelen / sizeof(*in);
diff --git a/src/common/frame.c b/src/common/frame.c
index 1fcc90f..606ac14 100644
--- a/src/common/frame.c
+++ b/src/common/frame.c
@@ -293,6 +293,22 @@ Qcommon_Frame(int msec)
c_pointcontents = 0;
}
+ // gl_maxfps > 1000 breaks things, and so does <= 0
+ // so cap to 1000 and treat <= 0 as "as fast as possible", which is 1000
+ if (gl_maxfps->value > 1000 || gl_maxfps->value < 1)
+ {
+ Cvar_SetValue("gl_maxfps", 1000);
+ }
+
+ if(cl_maxfps->value > 250)
+ {
+ Cvar_SetValue("cl_maxfps", 130);
+ }
+ else if(cl_maxfps->value < 1)
+ {
+ Cvar_SetValue("cl_maxfps", 60);
+ }
+
// Save global time for network- und input code.
curtime = Sys_Milliseconds();
diff --git a/src/common/header/common.h b/src/common/header/common.h
index 2f8afe2..2d6c598 100644
--- a/src/common/header/common.h
+++ b/src/common/header/common.h
@@ -32,7 +32,7 @@
#include "shared.h"
#include "crc.h"
-#define YQ2VERSION "7.02"
+#define YQ2VERSION "7.10"
#define BASEDIRNAME "baseq2"
#ifndef YQ2OSTYPE
diff --git a/src/common/header/shared.h b/src/common/header/shared.h
index b6813c0..d12ab68 100644
--- a/src/common/header/shared.h
+++ b/src/common/header/shared.h
@@ -457,8 +457,8 @@ typedef struct cmodel_s
typedef struct csurface_s
{
char name[16];
- int flags;
- int value;
+ int flags; /* SURF_* */
+ int value; /* unused */
} csurface_t;
typedef struct mapsurface_s /* used internally due to name len probs */
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-games/yquake2.git
More information about the Pkg-games-commits
mailing list