Support variable strength for rumble motors.

This commit is contained in:
Themaister 2013-09-26 12:55:05 +02:00
parent aa882c3515
commit c7db4aff64
11 changed files with 52 additions and 30 deletions

View File

@ -309,10 +309,10 @@ void driver_set_nonblock_state(bool nonblock)
g_extern.audio_data.nonblock_chunk_size : g_extern.audio_data.block_chunk_size;
}
bool driver_set_rumble_state(unsigned port, enum retro_rumble_effect effect, bool enable)
bool driver_set_rumble_state(unsigned port, enum retro_rumble_effect effect, uint16_t strength)
{
if (driver.input && driver.input_data && driver.input->set_rumble)
return driver.input->set_rumble(driver.input_data, port, effect, enable);
return driver.input->set_rumble(driver.input_data, port, effect, strength);
else
return false;
}

View File

@ -335,7 +335,7 @@ typedef struct input_driver
const char *ident;
void (*grab_mouse)(void *data, bool state);
bool (*set_rumble)(void *data, unsigned port, enum retro_rumble_effect effect, bool state);
bool (*set_rumble)(void *data, unsigned port, enum retro_rumble_effect effect, uint16_t state);
} input_driver_t;
struct rarch_viewport;
@ -497,7 +497,7 @@ uintptr_t driver_get_current_framebuffer(void);
retro_proc_address_t driver_get_proc_address(const char *sym);
// Used by RETRO_ENVIRONMENT_GET_RUMBLE_INTERFACE
bool driver_set_rumble_state(unsigned port, enum retro_rumble_effect effect, bool enable);
bool driver_set_rumble_state(unsigned port, enum retro_rumble_effect effect, uint16_t strength);
extern driver_t driver;

View File

@ -334,10 +334,10 @@ static void dinput_grab_mouse(void *data, bool state)
IDirectInputDevice8_Acquire(di->mouse);
}
static bool dinput_set_rumble(void *data, unsigned port, enum retro_rumble_effect effect, bool state)
static bool dinput_set_rumble(void *data, unsigned port, enum retro_rumble_effect effect, uint16_t strength)
{
struct dinput_input *di = (struct dinput_input*)data;
return input_joypad_set_rumble(di->joypad, port, effect, state);
return input_joypad_set_rumble(di->joypad, port, effect, strength);
}
const input_driver_t input_dinput = {

View File

@ -107,7 +107,7 @@ const char *input_joypad_name(const rarch_joypad_driver_t *driver, unsigned joyp
}
bool input_joypad_set_rumble(const rarch_joypad_driver_t *driver,
unsigned port, enum retro_rumble_effect effect, bool state)
unsigned port, enum retro_rumble_effect effect, uint16_t strength)
{
if (!driver || !driver->set_rumble)
return false;
@ -116,7 +116,7 @@ bool input_joypad_set_rumble(const rarch_joypad_driver_t *driver,
if (joy_index < 0 || joy_index >= MAX_PLAYERS)
return false;
return driver->set_rumble(joy_index, effect, state);
return driver->set_rumble(joy_index, effect, strength);
}
bool input_joypad_pressed(const rarch_joypad_driver_t *driver,

View File

@ -66,7 +66,7 @@ typedef struct rarch_joypad_driver
bool (*button)(unsigned, uint16_t);
int16_t (*axis)(unsigned, uint32_t);
void (*poll)(void);
bool (*set_rumble)(unsigned, enum retro_rumble_effect, bool); // Optional
bool (*set_rumble)(unsigned, enum retro_rumble_effect, uint16_t); // Optional
const char *(*name)(unsigned);
const char *ident;
@ -83,7 +83,7 @@ int16_t input_joypad_analog(const rarch_joypad_driver_t *driver,
unsigned port, unsigned index, unsigned id, const struct retro_keybind *binds);
bool input_joypad_set_rumble(const rarch_joypad_driver_t *driver,
unsigned port, enum retro_rumble_effect effect, bool state);
unsigned port, enum retro_rumble_effect effect, uint16_t strength);
int16_t input_joypad_axis_raw(const rarch_joypad_driver_t *driver,
unsigned joypad, unsigned axis);

View File

@ -285,10 +285,10 @@ static void linuxraw_input_free(void *data)
free(data);
}
static bool linuxraw_set_rumble(void *data, unsigned port, enum retro_rumble_effect effect, bool state)
static bool linuxraw_set_rumble(void *data, unsigned port, enum retro_rumble_effect effect, uint16_t strength)
{
linuxraw_input_t *linuxraw = (linuxraw_input_t*)data;
return input_joypad_set_rumble(linuxraw->joypad, port, effect, state);
return input_joypad_set_rumble(linuxraw->joypad, port, effect, strength);
}
static void linuxraw_input_poll(void *data)

View File

@ -214,10 +214,10 @@ static void sdl_input_free(void *data)
free(data);
}
static bool sdl_set_rumble(void *data, unsigned port, enum retro_rumble_effect effect, bool state)
static bool sdl_set_rumble(void *data, unsigned port, enum retro_rumble_effect effect, uint16_t strength)
{
sdl_input_t *sdl = (sdl_input_t*)data;
return input_joypad_set_rumble(sdl->joypad, port, effect, state);
return input_joypad_set_rumble(sdl->joypad, port, effect, strength);
}
static void sdl_poll_mouse(sdl_input_t *sdl)

View File

@ -57,6 +57,7 @@ struct udev_joypad
int num_effects;
int effects[2]; // [0] - strong, [1] - weak
bool has_set_ff[2];
uint16_t strength[2];
char *ident;
char *path;
@ -177,7 +178,7 @@ end:
udev_device_unref(dev);
}
static bool udev_set_rumble(unsigned i, enum retro_rumble_effect effect, bool state)
static bool udev_set_rumble(unsigned i, enum retro_rumble_effect effect, uint16_t strength)
{
struct udev_joypad *pad = &g_pads[i];
@ -186,6 +187,30 @@ static bool udev_set_rumble(unsigned i, enum retro_rumble_effect effect, bool st
if (pad->num_effects < 2)
return false;
if (pad->strength[effect] == strength)
return true;
if (pad->has_set_ff[effect] && strength != pad->strength[effect])
{
struct input_event play;
memset(&play, 0, sizeof(play));
play.type = EV_FF;
play.code = pad->effects[effect];
play.value = 0;
if (write(pad->fd, &play, sizeof(play)) < (ssize_t)sizeof(play))
{
RARCH_ERR("[udev]: Failed to set rumble effect %u on pad %u.\n",
effect, i);
return false;
}
if (ioctl(pad->fd, EVIOCRMFF, (void*)(uintptr_t)pad->effects[effect]) < 0)
RARCH_WARN("[udev]: Failed to remove effect.\n");
pad->has_set_ff[effect] = false;
pad->effects[effect] = -1;
}
// Have to defer the force feedback settings to here.
// For some reason, effects are getting dropped when they're set at init.
// Setting at init seems to work for pads which are hotplugged ...
@ -199,8 +224,8 @@ static bool udev_set_rumble(unsigned i, enum retro_rumble_effect effect, bool st
e.id = -1;
switch (effect)
{
case RETRO_RUMBLE_STRONG: e.u.rumble.strong_magnitude = 0xc000; break;
case RETRO_RUMBLE_WEAK: e.u.rumble.weak_magnitude = 0xc000; break;
case RETRO_RUMBLE_STRONG: e.u.rumble.strong_magnitude = strength; break;
case RETRO_RUMBLE_WEAK: e.u.rumble.weak_magnitude = strength; break;
default: return false;
}
@ -212,13 +237,14 @@ static bool udev_set_rumble(unsigned i, enum retro_rumble_effect effect, bool st
pad->has_set_ff[effect] = true;
pad->effects[effect] = e.id;
pad->strength[effect] = strength;
}
struct input_event play;
memset(&play, 0, sizeof(play));
play.type = EV_FF;
play.code = pad->effects[effect];
play.value = state;
play.value = strength != 0;
if (write(pad->fd, &play, sizeof(play)) < (ssize_t)sizeof(play))
{
RARCH_ERR("[udev]: Failed to set rumble effect %u on pad %u.\n",

View File

@ -269,10 +269,10 @@ static void x_grab_mouse(void *data, bool state)
x11->grab_mouse = state;
}
static bool x_set_rumble(void *data, unsigned port, enum retro_rumble_effect effect, bool state)
static bool x_set_rumble(void *data, unsigned port, enum retro_rumble_effect effect, uint16_t strength)
{
x11_input_t *x11 = (x11_input_t*)data;
return input_joypad_set_rumble(x11->joypad, port, effect, state);
return input_joypad_set_rumble(x11->joypad, port, effect, strength);
}
const input_driver_t input_x = {

View File

@ -180,21 +180,17 @@ static void update_input(void)
{
static bool old_start;
static bool old_select;
uint16_t strength_strong = input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R2) ? 0x4000 : 0xffff;
uint16_t strength_weak = input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L2) ? 0x4000 : 0xffff;
bool start = input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START);
bool select = input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT);
if (old_start != start)
{
fprintf(stderr, "Strong rumble: %s.\n", start ? "ON": "OFF");
if (!rumble.set_rumble_state(0, RETRO_RUMBLE_STRONG, start))
fprintf(stderr, "Strong rumble; failed to set state.\n");
}
rumble.set_rumble_state(0, RETRO_RUMBLE_STRONG, start * strength_strong);
if (old_select != select)
{
fprintf(stderr, "Weak rumble: %s.\n", select ? "ON": "OFF");
if (!rumble.set_rumble_state(0, RETRO_RUMBLE_WEAK, select))
fprintf(stderr, "Weak rumble; failed to set state.\n");
}
rumble.set_rumble_state(0, RETRO_RUMBLE_WEAK, select * strength_weak);
old_start = start;
old_select = select;

View File

@ -531,10 +531,10 @@ enum retro_rumble_effect
// Sets rumble state for joypad plugged in port 'port'. Rumble effects are controlled independently,
// and setting e.g. strong rumble does not override weak rumble.
// Should only be called when rumble state changes.
// Strength has a range of [0, 0xffff].
//
// Returns true if rumble state request was honored. Calling this before first retro_run() is likely to return false.
typedef bool (*retro_set_rumble_state_t)(unsigned port, enum retro_rumble_effect effect, bool enable);
typedef bool (*retro_set_rumble_state_t)(unsigned port, enum retro_rumble_effect effect, uint16_t strength);
struct retro_rumble_interface
{
retro_set_rumble_state_t set_rumble_state;