Commit f6d01fd3 authored by jdgleaver's avatar jdgleaver
Browse files

Improved rumble support

parent d2c077f0
......@@ -84,7 +84,6 @@ unsigned device_type = 0;
unsigned MEMSIZE_MB;
static struct retro_rumble_interface rumble;
static bool libretro_supports_bitmasks = false;
#if defined(HW_DOL)
......@@ -218,7 +217,9 @@ gp_layout_t classic_alt = {
gp_layout_t *gp_layoutp = NULL;
static float framerate = 60.0f;
static float framerate = 60.0f;
static float frametime_usec = 1000.0f / 60.0f;
static bool initial_resolution_set = false;
static int invert_y_axis = 1;
......@@ -247,6 +248,61 @@ static void extract_basename(char *buf, const char *path, size_t size)
*ext = '\0';
}
static struct retro_rumble_interface rumble = {0};
static bool rumble_enabled = false;
static uint16_t rumble_damage_strength = 0;
static uint16_t rumble_touch_strength = 0;
static int16_t rumble_touch_counter = -1;
void retro_set_rumble_damage(int damage)
{
/* Rumble scales linearly from 0xFFF to 0xFFFF
* as damage increases from 1 to 50 */
int capped_damage = (damage < 50) ? damage : 50;
uint16_t strength = 0;
if (!rumble.set_rumble_state ||
(!rumble_enabled && (capped_damage > 0)))
return;
if (capped_damage > 0)
strength = 0xFFF + (capped_damage * 0x4CC);
/* Return early if strength matches last
* set value */
if (strength == rumble_damage_strength)
return;
rumble.set_rumble_state(0, RETRO_RUMBLE_STRONG, strength);
rumble_damage_strength = strength;
}
void retro_set_rumble_touch(unsigned intensity, float duration)
{
/* Rumble scales linearly from 0xFF to 0xFFFF
* as intensity increases from 1 to 20 */
unsigned capped_intensity = (intensity < 20) ? intensity : 20;
uint16_t strength = 0;
if (!rumble.set_rumble_state ||
(!rumble_enabled && (capped_intensity > 0)))
return;
if ((capped_intensity > 0) && (duration > 0.0f))
{
strength = 0xFF + (capped_intensity * 0xCC0);
rumble_touch_counter = (int16_t)((duration / frametime_usec) + 1.0f);
}
/* Return early if strength matches last
* set value */
if (strength == rumble_touch_strength)
return;
rumble.set_rumble_state(0, RETRO_RUMBLE_WEAK, strength);
rumble_touch_strength = strength;
}
// =======================================================================
// General routines
// =======================================================================
......@@ -438,6 +494,15 @@ void retro_deinit(void)
free(heap);
libretro_supports_bitmasks = false;
retro_set_rumble_damage(0);
retro_set_rumble_touch(0, 0.0f);
memset(&rumble, 0, sizeof(struct retro_rumble_interface));
rumble_enabled = false;
rumble_damage_strength = 0;
rumble_touch_strength = 0;
rumble_touch_counter = -1;
}
unsigned retro_api_version(void)
......@@ -697,27 +762,8 @@ void Sys_Sleep(void)
const char *argv[MAX_NUM_ARGVS];
static const char *empty_string = "";
void retro_set_rumble_strong(void)
{
uint16_t strength_strong = 0xffff;
if (!rumble.set_rumble_state)
return;
rumble.set_rumble_state(0, RETRO_RUMBLE_STRONG, strength_strong);
}
void retro_unset_rumble_strong(void)
{
if (!rumble.set_rumble_state)
return;
rumble.set_rumble_state(0, RETRO_RUMBLE_STRONG, 0);
}
extern int coloredlights;
bool state_rumble;
static void update_variables(bool startup)
{
struct retro_variable var;
......@@ -745,6 +791,8 @@ static void update_variables(bool startup)
else
framerate = 60.0f;
frametime_usec = 1000.0f / framerate;
/* Note: The audio handling code of the game engine
* completely falls apart below 50 FPS. To go any
* lower than this, we have to manipulate the actual
......@@ -804,9 +852,15 @@ static void update_variables(bool startup)
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
{
if (strcmp(var.value, "disabled") == 0)
state_rumble = false;
rumble_enabled = false;
else
state_rumble = true;
rumble_enabled = true;
}
if (!rumble_enabled)
{
retro_set_rumble_damage(0);
retro_set_rumble_touch(0, 0.0f);
}
var.key = "tyrquake_invert_y_axis";
......@@ -871,12 +925,17 @@ void retro_run(void)
update_env_variables();
has_set_username = true;
}
if (!state_rumble)
retro_unset_rumble_strong();
Host_Frame(1.0 / framerate);
if (rumble_touch_counter > -1)
{
rumble_touch_counter--;
if (rumble_touch_counter == 0)
retro_set_rumble_touch(0, 0.0f);
}
if (shutdown_core)
return;
......
......@@ -73,6 +73,11 @@ float v_oldz, v_stepz;
float v_steptime;
/* EOF - Framerate-independent stair-step smoothing */
static int old_health = 100;
static float old_velocity_z = 0.0;
extern void retro_set_rumble_damage(int damage);
extern void retro_set_rumble_touch(unsigned intensity, float duration);
/*
===============
V_CalcRoll
......@@ -149,6 +154,14 @@ float V_CalcBob(void)
else if (bob < -7)
bob = -7;
/* Check for a sudden stop in downwards motion
* > Means we've just 'touched' the ground, so
* trigger a weak touch-type rumble */
if ((old_velocity_z < 0.0) &&
(cl.velocity[2] == 0.0))
retro_set_rumble_touch(6, 120.0f);
old_velocity_z = cl.velocity[2];
return bob;
}
......@@ -407,6 +420,10 @@ void V_BonusFlash_f(void)
cl.cshifts[CSHIFT_BONUS].initialpct = 50;
cl.cshifts[CSHIFT_BONUS].time = cl.time;
/* EOF - Frame-rate independent damage and bonus shifts */
/* We have touched an item - trigger a moderate
* touch-type rumble */
retro_set_rumble_touch(9, 140.0f);
}
/*
......@@ -677,10 +694,6 @@ V_CalcViewRoll
Roll is induced by movement and damage
==============
*/
static int old_health = 100;
void retro_set_rumble_strong(void);
void retro_unset_rumble_strong(void);
void V_CalcViewRoll(void)
{
float side = V_CalcRoll(cl_entities[cl.viewentity].angles, cl.velocity);
......@@ -695,12 +708,12 @@ void V_CalcViewRoll(void)
v_dmg_time -= host_frametime;
if (old_health > cl.stats[STAT_HEALTH])
retro_set_rumble_strong();
retro_set_rumble_damage(old_health - cl.stats[STAT_HEALTH]);
old_health = cl.stats[STAT_HEALTH];
}
else
retro_unset_rumble_strong();
retro_set_rumble_damage(0);
if (cl.stats[STAT_HEALTH] <= 0) {
r_refdef.viewangles[ROLL] = 80; // dead view angle
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment