diff --git a/Makefile.win b/Makefile.win
index 635e573ff4..f4ea879abf 100644
--- a/Makefile.win
+++ b/Makefile.win
@@ -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 \
diff --git a/conf/config_file.c b/conf/config_file.c
index 8fcbd92ceb..05327d6cc3 100644
--- a/conf/config_file.c
+++ b/conf/config_file.c
@@ -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);
diff --git a/conf/config_file.h b/conf/config_file.h
index 8ae7554181..ad366e84ca 100644
--- a/conf/config_file.h
+++ b/conf/config_file.h
@@ -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);
diff --git a/input/autoconf_builtin.c b/input/autoconf_builtin.c
new file mode 100644
index 0000000000..ba919a7f02
--- /dev/null
+++ b/input/autoconf_builtin.c
@@ -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
+};
diff --git a/input/input_common.c b/input/input_common.c
index fb799e3884..14a39c4cd0 100644
--- a/input/input_common.c
+++ b/input/input_common.c
@@ -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)
diff --git a/input/input_common.h b/input/input_common.h
index dc118ff4e1..ffc08d99a3 100644
--- a/input/input_common.h
+++ b/input/input_common.h
@@ -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,
diff --git a/msvc/msvc-2010/RetroArch-msvc2010.vcxproj b/msvc/msvc-2010/RetroArch-msvc2010.vcxproj
index 45bbb6b6cd..9ebc1423fc 100644
--- a/msvc/msvc-2010/RetroArch-msvc2010.vcxproj
+++ b/msvc/msvc-2010/RetroArch-msvc2010.vcxproj
@@ -254,6 +254,8 @@
+
+
diff --git a/settings.c b/settings.c
index eca070c127..c13ad20b91 100644
--- a/settings.c
+++ b/settings.c
@@ -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);