Merge pull request #299 from pinumbernumber/improve-xinput

Add some hardcoded autoconf configs in addition to the file-based system
This commit is contained in:
Hans-Kristian Arntzen 2013-09-06 14:14:05 -07:00
commit 02528942ac
8 changed files with 198 additions and 37 deletions

View File

@ -17,6 +17,7 @@ OBJ = frontend/frontend.o \
movie.o \
gfx/gfx_common.o \
input/input_common.o \
input/autoconf_builtin.o \
core_options.o \
patch.o \
compat/compat.o \

View File

@ -355,6 +355,54 @@ static config_file_t *config_file_new_internal(const char *path, unsigned depth)
return conf;
}
config_file_t *config_file_new_from_string(const char *from_string)
{
struct config_file *conf = (struct config_file*)calloc(1, sizeof(*conf));
if (!conf)
return NULL;
if (!from_string)
return conf;
conf->path = NULL;
conf->include_depth = 0;
struct string_list *lines = string_split(from_string, "\n");
if (!lines)
return conf;
for (size_t i = 0; i < lines->size; i++)
{
struct config_entry_list *list = (struct config_entry_list*)calloc(1, sizeof(*list));
char* line = lines->elems[i].data;
if (line)
{
if (parse_line(conf, list, line))
{
if (conf->entries)
{
conf->tail->next = list;
conf->tail = list;
}
else
{
conf->entries = list;
conf->tail = list;
}
}
}
if (list != conf->tail)
free(list);
}
string_list_free(lines);
return conf;
}
config_file_t *config_file_new(const char *path)
{
return config_file_new_internal(path, 0);

View File

@ -41,6 +41,8 @@ typedef struct config_file config_file_t;
// Loads a config file. Returns NULL if file doesn't exist.
// NULL path will create an empty config file.
config_file_t *config_file_new(const char *path);
// Load a config file from a string.
config_file_t *config_file_new_from_string(const char *from_string);
// Frees config file.
void config_file_free(config_file_t *conf);

80
input/autoconf_builtin.c Normal file
View File

@ -0,0 +1,80 @@
#include "input_common.h"
#define DECL_BTN(btn, bind) "input_" #btn "_btn = " #bind "\n"
#define DECL_AXIS(axis, bind) "input_" #axis "_axis = " #bind "\n"
#define XINPUT_DEFAULT_BINDS \
DECL_BTN(a,1)\
DECL_BTN(b,0)\
DECL_BTN(x,3)\
DECL_BTN(y,2)\
DECL_BTN(start, 6)\
DECL_BTN(select,7)\
DECL_BTN(up,h0up)\
DECL_BTN(down,h0down)\
DECL_BTN(left,h0left)\
DECL_BTN(right,h0right)\
DECL_BTN(l, 4)\
DECL_BTN(r, 5)\
DECL_BTN(l3,8)\
DECL_BTN(r3,9)\
DECL_AXIS(l2, +4)\
DECL_AXIS(r2, +5)\
DECL_AXIS(l_x_plus, +0)\
DECL_AXIS(l_x_minus, -0)\
DECL_AXIS(l_y_plus, -1)\
DECL_AXIS(l_y_minus, +1)\
DECL_AXIS(r_x_plus, +2)\
DECL_AXIS(r_x_minus, -2)\
DECL_AXIS(r_y_plus, -3)\
DECL_AXIS(r_y_minus, +3)
// Some hardcoded autoconfig information. Will be used for pads with no autoconfig cfg files.
const char* const input_builtin_autoconfs[] =
{
"input_device = \"XInput Controller (Player 1)\" \n"
"input_driver = \"winxinput\" \n"
XINPUT_DEFAULT_BINDS,
"input_device = \"XInput Controller (Player 2)\" \n"
"input_driver = \"winxinput\" \n"
XINPUT_DEFAULT_BINDS,
"input_device = \"XInput Controller (Player 3)\" \n"
"input_driver = \"winxinput\" \n"
XINPUT_DEFAULT_BINDS,
"input_device = \"XInput Controller (Player 4)\" \n"
"input_driver = \"winxinput\" \n"
XINPUT_DEFAULT_BINDS,
"input_device = \"Dual Trigger 3-in-1\" \n"
"input_driver = \"dinput\" \n"
DECL_BTN(a,2)
DECL_BTN(b,1)
DECL_BTN(x,3)
DECL_BTN(y,0)
DECL_BTN(start, 9)
DECL_BTN(select,8)
DECL_BTN(up,h0up)
DECL_BTN(down,h0down)
DECL_BTN(left,h0left)
DECL_BTN(right,h0right)
DECL_BTN(l, 4)
DECL_BTN(r, 5)
DECL_BTN(l2, 6)
DECL_BTN(r2, 7)
DECL_BTN(l3,10)
DECL_BTN(r3,11)
DECL_AXIS(l_x_plus, +0)
DECL_AXIS(l_x_minus, -0)
DECL_AXIS(l_y_plus, +1)
DECL_AXIS(l_y_minus, -1)
DECL_AXIS(r_x_plus, +2)
DECL_AXIS(r_x_minus, -2)
DECL_AXIS(r_y_plus, +5)
DECL_AXIS(r_y_minus, -5)
,
NULL
};

View File

@ -810,6 +810,38 @@ static void input_autoconfigure_joypad_conf(config_file_t *conf, struct retro_ke
}
}
static bool input_try_autoconfigure_joypad_from_conf(config_file_t *conf, unsigned index, const char *name, const char *driver, bool block_osd_spam)
{
if (!conf)
return false;
char ident[1024];
char input_driver[1024];
*ident = *input_driver = '\0';
config_get_array(conf, "input_device", ident, sizeof(ident));
config_get_array(conf, "input_driver", input_driver, sizeof(input_driver));
if (!strcmp(ident, name) && !strcmp(driver, input_driver))
{
g_settings.input.autoconfigured[index] = true;
input_autoconfigure_joypad_conf(conf, g_settings.input.autoconf_binds[index]);
char msg[512];
snprintf(msg, sizeof(msg), "Joypad port #%u (%s) configured.",
index, name);
if (!block_osd_spam)
msg_queue_push(g_extern.msg_queue, msg, 0, 60);
RARCH_LOG("%s\n", msg);
return true;
}
return false;
}
void input_config_autoconfigure_joypad(unsigned index, const char *name, const char *driver)
{
if (!g_settings.input.autodetect_enable)
@ -829,47 +861,39 @@ void input_config_autoconfigure_joypad(unsigned index, const char *name, const c
if (!name)
return;
if (!*g_settings.input.autoconfig_dir)
return;
// false = load from both cfg files and internal
bool internal_only = (!*g_settings.input.autoconfig_dir);
struct string_list *list = dir_list_new(g_settings.input.autoconfig_dir, "cfg", false);
if (!list)
return;
char ident[1024];
char input_driver[1024];
for (size_t i = 0; i < list->size; i++)
// First internal
for (size_t i = 0; input_builtin_autoconfs[i] /* array is NULL terminated */; i++)
{
*ident = *input_driver = '\0';
config_file_t *conf = config_file_new(list->elems[i].data);
if (!conf)
continue;
config_get_array(conf, "input_device", ident, sizeof(ident));
config_get_array(conf, "input_driver", input_driver, sizeof(input_driver));
if (!strcmp(ident, name) && !strcmp(driver, input_driver))
{
g_settings.input.autoconfigured[index] = true;
input_autoconfigure_joypad_conf(conf, g_settings.input.autoconf_binds[index]);
char msg[512];
snprintf(msg, sizeof(msg), "Joypad port #%u (%s) configured.",
index, name);
if (!block_osd_spam)
msg_queue_push(g_extern.msg_queue, msg, 0, 60);
RARCH_LOG("%s\n", msg);
config_file_free(conf);
config_file_t *conf = config_file_new_from_string(input_builtin_autoconfs[i]);
bool success = input_try_autoconfigure_joypad_from_conf(conf, index, name, driver, block_osd_spam);
config_file_free(conf);
if (success)
break;
}
else
config_file_free(conf);
}
string_list_free(list);
// Now try files
if (!internal_only)
{
struct string_list *list = dir_list_new(g_settings.input.autoconfig_dir, "cfg", false);
if (!list)
return;
for (size_t i = 0; i < list->size; i++)
{
config_file_t *conf = config_file_new(list->elems[i].data);
if (!conf)
continue;
bool success = input_try_autoconfigure_joypad_from_conf(conf, index, name, driver, block_osd_spam);
config_file_free(conf);
if (success)
break;
}
string_list_free(list);
}
}
#else
void input_config_autoconfigure_joypad(unsigned index, const char *name, const char *driver)

View File

@ -135,6 +135,8 @@ struct input_key_map
};
extern const struct input_key_map input_config_key_map[];
extern const char* const input_builtin_autoconfs[];
const char *input_config_get_prefix(unsigned player, bool meta);
void input_config_parse_key(config_file_t *conf, const char *prefix, const char *btn,

View File

@ -254,6 +254,8 @@
</ClCompile>
<ClCompile Include="..\..\input\input_common.c">
</ClCompile>
<ClCompile Include="..\..\input\autoconf_builtin.c">
</ClCompile>
<ClCompile Include="..\..\message.c">
</ClCompile>
<ClCompile Include="..\..\movie.c">

View File

@ -1093,6 +1093,8 @@ bool config_save_file(const char *path)
config_set_int(conf, cfg, g_settings.input.dpad_emulation[i]);
snprintf(cfg, sizeof(cfg), "input_device_p%u", i + 1);
config_set_int(conf, cfg, g_settings.input.device[i]);
snprintf(cfg, sizeof(cfg), "input_player%u_joypad_index", i + 1);
config_set_int(conf, cfg, g_settings.input.joypad_map[i]);
}
config_file_write(conf, path);