Merge pull request #481 from libretro/dpad-map

Analog D-pad mapping
This commit is contained in:
Twinaphex 2014-01-08 12:01:39 -08:00
commit 165698b9f2
11 changed files with 189 additions and 35 deletions

View File

@ -151,6 +151,8 @@ struct retro_keybind
uint32_t joyaxis;
uint32_t def_joyaxis;
uint32_t orig_joyaxis; // Used by input_{push,pop}_analog_dpad().
};
struct platform_bind
@ -319,7 +321,7 @@ enum input_devices
DEVICE_LAST
};
enum analog_dpad_bind_enums
enum analog_dpad_mode
{
ANALOG_DPAD_NONE = 0,
ANALOG_DPAD_LSTICK,

View File

@ -489,6 +489,10 @@ static uint64_t menu_input(void)
static const struct retro_keybind *binds[] = { g_settings.input.binds[0] };
#endif
input_push_analog_dpad((struct retro_keybind*)binds[0], g_settings.input.analog_dpad_mode[0]);
for (i = 0; i < MAX_PLAYERS; i++)
input_push_analog_dpad(g_settings.input.autoconf_binds[i], g_settings.input.analog_dpad_mode[i]);
for (i = 0; i < RETRO_DEVICE_ID_JOYPAD_R2; i++)
{
input_state |= input_input_state_func(binds,
@ -500,6 +504,10 @@ static uint64_t menu_input(void)
input_state |= input_key_pressed_func(RARCH_MENU_TOGGLE) ? (1ULL << RARCH_MENU_TOGGLE) : 0;
input_pop_analog_dpad((struct retro_keybind*)binds[0]);
for (i = 0; i < MAX_PLAYERS; i++)
input_pop_analog_dpad(g_settings.input.autoconf_binds[i]);
rgui->trigger_state = input_state & ~rgui->old_input_state;
rgui->do_held = (input_state & (
@ -1974,6 +1982,7 @@ void menu_populate_entries(void *data, unsigned menu_type)
file_list_push(rgui->selection_buf, "Player", RGUI_SETTINGS_BIND_PLAYER, 0);
file_list_push(rgui->selection_buf, "Device", RGUI_SETTINGS_BIND_DEVICE, 0);
file_list_push(rgui->selection_buf, "Device Type", RGUI_SETTINGS_BIND_DEVICE_TYPE, 0);
file_list_push(rgui->selection_buf, "Analog D-pad Mode", RGUI_SETTINGS_BIND_ANALOG_MODE, 0);
file_list_push(rgui->selection_buf, "Autodetect enable", RGUI_SETTINGS_DEVICE_AUTODETECT_ENABLE, 0);
file_list_push(rgui->selection_buf, "Configure All (RetroPad)", RGUI_SETTINGS_CUSTOM_BIND_ALL, 0);

View File

@ -157,6 +157,7 @@ typedef enum
RGUI_SETTINGS_BIND_PLAYER,
RGUI_SETTINGS_BIND_DEVICE,
RGUI_SETTINGS_BIND_DEVICE_TYPE,
RGUI_SETTINGS_BIND_ANALOG_MODE,
RGUI_SETTINGS_DEVICE_AUTODETECT_ENABLE,
// Match up with libretro order for simplicity.

View File

@ -781,6 +781,26 @@ int menu_set_settings(void *data, unsigned setting, unsigned action)
*p = MAX_PLAYERS - 1;
}
break;
case RGUI_SETTINGS_BIND_ANALOG_MODE:
switch (action)
{
case RGUI_ACTION_START:
g_settings.input.analog_dpad_mode[port] = 0;
break;
case RGUI_ACTION_OK:
case RGUI_ACTION_RIGHT:
g_settings.input.analog_dpad_mode[port] = (g_settings.input.analog_dpad_mode[port] + 1) % ANALOG_DPAD_LAST;
break;
case RGUI_ACTION_LEFT:
g_settings.input.analog_dpad_mode[port] = (g_settings.input.analog_dpad_mode[port] + ANALOG_DPAD_LAST - 1) % ANALOG_DPAD_LAST;
break;
default:
break;
}
break;
case RGUI_SETTINGS_BIND_DEVICE_TYPE:
{
static const unsigned device_types[] = {
@ -1702,9 +1722,9 @@ void menu_set_settings_label(char *type_str, size_t type_str_size, unsigned *w,
break;
case RGUI_SETTINGS_VIDEO_PAL60:
if (g_extern.lifecycle_state & (1ULL << MODE_VIDEO_PAL_TEMPORAL_ENABLE))
strlcpy(type_str, "ON", sizeof(type_str));
strlcpy(type_str, "ON", type_str_size);
else
strlcpy(type_str, "OFF", sizeof(type_str));
strlcpy(type_str, "OFF", type_str_size);
break;
#endif
case RGUI_FILE_PLAIN:
@ -1845,41 +1865,53 @@ void menu_set_settings_label(char *type_str, size_t type_str_size, unsigned *w,
snprintf(type_str, type_str_size, "#%d", rgui->current_pad + 1);
break;
case RGUI_SETTINGS_BIND_DEVICE:
{
int map = g_settings.input.joypad_map[rgui->current_pad];
if (map >= 0 && map < MAX_PLAYERS)
{
int map = g_settings.input.joypad_map[rgui->current_pad];
if (map >= 0 && map < MAX_PLAYERS)
{
const char *device_name = g_settings.input.device_names[map];
if (*device_name)
strlcpy(type_str, device_name, type_str_size);
else
snprintf(type_str, type_str_size, "N/A (port #%u)", map);
}
const char *device_name = g_settings.input.device_names[map];
if (*device_name)
strlcpy(type_str, device_name, type_str_size);
else
strlcpy(type_str, "Disabled", type_str_size);
break;
snprintf(type_str, type_str_size, "N/A (port #%u)", map);
}
case RGUI_SETTINGS_BIND_DEVICE_TYPE:
{
const char *name;
switch (g_settings.input.libretro_device[rgui->current_pad])
{
case RETRO_DEVICE_NONE: name = "None"; break;
case RETRO_DEVICE_JOYPAD: name = "Joypad"; break;
case RETRO_DEVICE_ANALOG: name = "Joypad w/ Analog"; break;
case RETRO_DEVICE_JOYPAD_MULTITAP: name = "Multitap"; break;
case RETRO_DEVICE_MOUSE: name = "Mouse"; break;
case RETRO_DEVICE_LIGHTGUN_JUSTIFIER: name = "Justifier"; break;
case RETRO_DEVICE_LIGHTGUN_JUSTIFIERS: name = "Justifiers"; break;
case RETRO_DEVICE_LIGHTGUN_SUPER_SCOPE: name = "SuperScope"; break;
default: name = "Unknown"; break;
}
else
strlcpy(type_str, "Disabled", type_str_size);
break;
}
case RGUI_SETTINGS_BIND_ANALOG_MODE:
{
static const char *modes[] = {
"None",
"Left Analog",
"Right Analog",
"Dual Analog",
};
strlcpy(type_str, name, type_str_size);
break;
strlcpy(type_str, modes[g_settings.input.analog_dpad_mode[rgui->current_pad] % ANALOG_DPAD_LAST], type_str_size);
break;
}
case RGUI_SETTINGS_BIND_DEVICE_TYPE:
{
const char *name;
switch (g_settings.input.libretro_device[rgui->current_pad])
{
case RETRO_DEVICE_NONE: name = "None"; break;
case RETRO_DEVICE_JOYPAD: name = "Joypad"; break;
case RETRO_DEVICE_ANALOG: name = "Joypad w/ Analog"; break;
case RETRO_DEVICE_JOYPAD_MULTITAP: name = "Multitap"; break;
case RETRO_DEVICE_MOUSE: name = "Mouse"; break;
case RETRO_DEVICE_LIGHTGUN_JUSTIFIER: name = "Justifier"; break;
case RETRO_DEVICE_LIGHTGUN_JUSTIFIERS: name = "Justifiers"; break;
case RETRO_DEVICE_LIGHTGUN_SUPER_SCOPE: name = "SuperScope"; break;
default: name = "Unknown"; break;
}
strlcpy(type_str, name, type_str_size);
break;
}
case RGUI_SETTINGS_DEVICE_AUTODETECT_ENABLE:
strlcpy(type_str, g_settings.input.autodetect_enable ? "ON" : "OFF", sizeof(type_str));
strlcpy(type_str, g_settings.input.autodetect_enable ? "ON" : "OFF", type_str_size);
break;
case RGUI_SETTINGS_BIND_UP:
case RGUI_SETTINGS_BIND_DOWN:
@ -1921,15 +1953,15 @@ void menu_set_settings_label(char *type_str, size_t type_str_size, unsigned *w,
break;
#ifdef _XBOX1
case RGUI_SETTINGS_FLICKER_FILTER:
snprintf(type_str, sizeof(type_str), "%d", g_extern.console.screen.flicker_filter_index);
snprintf(type_str, type_str_size, "%d", g_extern.console.screen.flicker_filter_index);
break;
case RGUI_SETTINGS_SOFT_DISPLAY_FILTER:
snprintf(type_str, sizeof(type_str),
snprintf(type_str, type_str_size,
(g_extern.lifecycle_state & (1ULL << MODE_VIDEO_SOFT_FILTER_ENABLE)) ? "ON" : "OFF");
break;
#endif
case RGUI_SETTINGS_CUSTOM_BGM_CONTROL_ENABLE:
strlcpy(type_str, (g_extern.lifecycle_state & (1ULL << MODE_AUDIO_CUSTOM_BGM_ENABLE)) ? "ON" : "OFF", sizeof(type_str));
strlcpy(type_str, (g_extern.lifecycle_state & (1ULL << MODE_AUDIO_CUSTOM_BGM_ENABLE)) ? "ON" : "OFF", type_str_size);
break;
default:
type_str[0] = 0;

View File

@ -239,6 +239,7 @@ struct settings
bool autoconfigured[MAX_PLAYERS];
unsigned libretro_device[MAX_PLAYERS];
unsigned analog_dpad_mode[MAX_PLAYERS];
float axis_threshold;
int joypad_map[MAX_PLAYERS];

View File

@ -25,6 +25,7 @@
#include "../../general.h"
#include "../../compat/strl.h"
#include "../../compat/posix_string.h"
#include "../../input/input_common.h"
#include "../../file.h"
static PyObject* py_read_wram(PyObject *self, PyObject *args)
@ -336,7 +337,21 @@ void py_state_free(py_state_t *handle)
float py_state_get(py_state_t *handle, const char *id,
unsigned frame_count)
{
unsigned i;
for (i = 0; i < MAX_PLAYERS; i++)
{
input_push_analog_dpad(g_settings.input.binds[i], g_settings.input.analog_dpad_mode[i]);
input_push_analog_dpad(g_settings.input.autoconf_binds[i], g_settings.input.analog_dpad_mode[i]);
}
PyObject *ret = PyObject_CallMethod(handle->inst, (char*)id, (char*)"I", frame_count);
for (i = 0; i < MAX_PLAYERS; i++)
{
input_pop_analog_dpad(g_settings.input.binds[i]);
input_pop_analog_dpad(g_settings.input.autoconf_binds[i]);
}
if (!ret)
{
if (!handle->warned_ret)

View File

@ -18,6 +18,7 @@
#include "../compat/strl.h"
#include "../general.h"
#include "../libretro.h"
#include "../input/input_common.h"
#ifdef HAVE_PYTHON
#include "py_state/py_state.h"
@ -244,6 +245,11 @@ static void update_input(state_tracker_t *tracker)
g_settings.input.binds[1],
};
for (i = 0; i < 2; i++)
input_push_analog_dpad(g_settings.input.binds[i], g_settings.input.analog_dpad_mode[i]);
for (i = 0; i < MAX_PLAYERS; i++)
input_push_analog_dpad(g_settings.input.autoconf_binds[i], g_settings.input.analog_dpad_mode[i]);
uint16_t state[2] = {0};
for (i = 4; i < 16; i++)
{
@ -251,6 +257,11 @@ static void update_input(state_tracker_t *tracker)
state[1] |= (input_input_state_func(binds, 1, RETRO_DEVICE_JOYPAD, 0, buttons[i - 4]) ? 1 : 0) << i;
}
for (i = 0; i < 2; i++)
input_pop_analog_dpad(g_settings.input.binds[i]);
for (i = 0; i < MAX_PLAYERS; i++)
input_pop_analog_dpad(g_settings.input.autoconf_binds[i]);
for (i = 0; i < 2; i++)
tracker->input_state[i] = state[i];
}

View File

@ -1283,3 +1283,40 @@ void input_config_autoconfigure_joypad(unsigned index, const char *name, const c
}
#endif
void input_push_analog_dpad(struct retro_keybind *binds, unsigned mode)
{
unsigned i;
unsigned analog_base;
switch (mode)
{
case ANALOG_DPAD_LSTICK:
case ANALOG_DPAD_RSTICK:
analog_base = mode == ANALOG_DPAD_LSTICK ? RARCH_ANALOG_LEFT_X_PLUS : RARCH_ANALOG_RIGHT_X_PLUS;
binds[RETRO_DEVICE_ID_JOYPAD_RIGHT].orig_joyaxis = binds[RETRO_DEVICE_ID_JOYPAD_RIGHT].joyaxis;
binds[RETRO_DEVICE_ID_JOYPAD_LEFT].orig_joyaxis = binds[RETRO_DEVICE_ID_JOYPAD_LEFT].joyaxis;
binds[RETRO_DEVICE_ID_JOYPAD_DOWN].orig_joyaxis = binds[RETRO_DEVICE_ID_JOYPAD_DOWN].joyaxis;
binds[RETRO_DEVICE_ID_JOYPAD_UP].orig_joyaxis = binds[RETRO_DEVICE_ID_JOYPAD_UP].joyaxis;
// Inherit joyaxis from analogs.
binds[RETRO_DEVICE_ID_JOYPAD_RIGHT].joyaxis = binds[analog_base + 0].joyaxis;
binds[RETRO_DEVICE_ID_JOYPAD_LEFT].joyaxis = binds[analog_base + 1].joyaxis;
binds[RETRO_DEVICE_ID_JOYPAD_DOWN].joyaxis = binds[analog_base + 2].joyaxis;
binds[RETRO_DEVICE_ID_JOYPAD_UP].joyaxis = binds[analog_base + 3].joyaxis;
break;
default:
for (i = RETRO_DEVICE_ID_JOYPAD_UP; i <= RETRO_DEVICE_ID_JOYPAD_RIGHT; i++)
binds[i].orig_joyaxis = binds[i].joyaxis;
break;
}
}
// Restore binds temporarily overridden by input_push_analog_dpad.
void input_pop_analog_dpad(struct retro_keybind *binds)
{
unsigned i;
for (i = RETRO_DEVICE_ID_JOYPAD_UP; i <= RETRO_DEVICE_ID_JOYPAD_RIGHT; i++)
binds[i].joyaxis = binds[i].orig_joyaxis;
}

View File

@ -167,6 +167,9 @@ void input_config_parse_joy_axis(config_file_t *conf, const char *prefix,
void input_config_autoconfigure_joypad(unsigned index, const char *name, const char *driver);
void input_push_analog_dpad(struct retro_keybind *binds, unsigned mode);
void input_pop_analog_dpad(struct retro_keybind *binds);
#ifdef __cplusplus
}
#endif

View File

@ -37,6 +37,7 @@
#include "compat/getopt_rarch.h"
#include "compat/posix_string.h"
#include "input/keyboard_line.h"
#include "input/input_common.h"
#ifdef _WIN32
#ifdef _XBOX
@ -562,6 +563,27 @@ static inline void input_poll_overlay(void)
}
}
// Check for analog_dpad_mode. Map analogs to d-pad buttons when configured.
switch (g_settings.input.analog_dpad_mode[0])
{
case ANALOG_DPAD_LSTICK:
case ANALOG_DPAD_RSTICK:
{
unsigned analog_base = g_settings.input.analog_dpad_mode[0] == ANALOG_DPAD_LSTICK ?
0 : 2;
float analog_x = (float)driver.overlay_state.analog[analog_base + 0] / 0x7fff;
float analog_y = (float)driver.overlay_state.analog[analog_base + 1] / 0x7fff;
driver.overlay_state.buttons |= (analog_x <= -g_settings.input.axis_threshold) ? (1ULL << RETRO_DEVICE_ID_JOYPAD_LEFT) : 0;
driver.overlay_state.buttons |= (analog_x >= g_settings.input.axis_threshold) ? (1ULL << RETRO_DEVICE_ID_JOYPAD_RIGHT) : 0;
driver.overlay_state.buttons |= (analog_y <= -g_settings.input.axis_threshold) ? (1ULL << RETRO_DEVICE_ID_JOYPAD_UP) : 0;
driver.overlay_state.buttons |= (analog_y >= g_settings.input.axis_threshold) ? (1ULL << RETRO_DEVICE_ID_JOYPAD_DOWN) : 0;
break;
}
default:
break;
}
if (polled)
input_overlay_post_poll(driver.overlay);
else
@ -3131,6 +3153,8 @@ static inline void limit_frame_time(void)
bool rarch_main_iterate(void)
{
unsigned i;
#ifdef HAVE_DYLIB
// DSP plugin GUI events.
if (g_extern.audio_data.dsp_handle && g_extern.audio_data.dsp_plugin->events)
@ -3182,10 +3206,23 @@ bool rarch_main_iterate(void)
driver_camera_poll();
#endif
// Update binds for analog dpad modes.
for (i = 0; i < MAX_PLAYERS; i++)
{
input_push_analog_dpad(g_settings.input.binds[i], g_settings.input.analog_dpad_mode[i]);
input_push_analog_dpad(g_settings.input.autoconf_binds[i], g_settings.input.analog_dpad_mode[i]);
}
update_frame_time();
pretro_run();
limit_frame_time();
for (i = 0; i < MAX_PLAYERS; i++)
{
input_pop_analog_dpad(g_settings.input.binds[i]);
input_pop_analog_dpad(g_settings.input.autoconf_binds[i]);
}
#ifdef HAVE_BSV_MOVIE
if (g_extern.bsv.movie)
bsv_movie_set_frame_end(g_extern.bsv.movie);

View File

@ -347,6 +347,7 @@ void config_set_defaults(void)
for (i = 0; i < MAX_PLAYERS; i++)
{
g_settings.input.joypad_map[i] = i;
g_settings.input.analog_dpad_mode[i] = ANALOG_DPAD_NONE;
if (!g_extern.has_set_libretro_device[i])
g_settings.input.libretro_device[i] = RETRO_DEVICE_JOYPAD;
}
@ -858,6 +859,9 @@ bool config_load_file(const char *path, bool set_defaults)
snprintf(buf, sizeof(buf), "input_player%u_joypad_index", i + 1);
CONFIG_GET_INT(input.joypad_map[i], buf);
snprintf(buf, sizeof(buf), "input_player%u_analog_dpad_mode", i + 1);
CONFIG_GET_INT(input.analog_dpad_mode[i], buf);
if (!g_extern.has_set_libretro_device[i])
{
snprintf(buf, sizeof(buf), "input_libretro_device_p%u", i + 1);
@ -1328,6 +1332,8 @@ bool config_save_file(const char *path)
config_set_int(conf, cfg, g_settings.input.joypad_map[i]);
snprintf(cfg, sizeof(cfg), "input_libretro_device_p%u", i + 1);
config_set_int(conf, cfg, g_settings.input.libretro_device[i]);
snprintf(cfg, sizeof(cfg), "input_player%u_analog_dpad_mode", i + 1);
config_set_int(conf, cfg, g_settings.input.analog_dpad_mode[i]);
}
for (i = 0; i < MAX_PLAYERS; i++)