diff --git a/configuration.c b/configuration.c index e93420c106..1db7f8e156 100644 --- a/configuration.c +++ b/configuration.c @@ -1088,6 +1088,82 @@ static void config_file_dump_all(config_file_t *conf) } } +/** + * config_append_specific: + * @conf : base config + * + * Tries to append game-specific and core-specific configuration. + * These settings will always have precedence, thus this feature + * can be used to enforce overrides. + * + * Let $RETROARCH_CFG be the directory that contains retroarch.cfg, + * $CORE_NAME be the name of the libretro core library in use and + * $ROM_NAME the basename of the ROM (without the extension and + * directory). + * + * This function only has an effect if a game-specific or core-specific + * configuration file exists at the folling locations respectively. + * + * core-specific: $RETROARCH_CFG/$CORE_NAME/$CORE_NAME.cfg + * game-specific: $RETROARCH_CFG/$CORE_NAME/$ROM_NAME.cfg + * + * Returns: False if there was an error. + * + */ +static bool config_append_specific(config_file_t *conf) +{ + char config_directory[PATH_MAX_LENGTH], /* path to the directory containing retroarch.cfg (prefix) */ + core_name_buffer[PATH_MAX_LENGTH], /* temporary array */ + core_path[PATH_MAX_LENGTH], /* final path for core-specific configuration (prefix+suffix) */ + game_path[PATH_MAX_LENGTH]; /* final path for game-specific configuration (prefix+suffix) */ + const char *core_name, *game_name; /* suffix */ + + global_t *global = global_get_ptr(); + if (!global || !conf) + RARCH_ERR("Could not obtain global pointer or configuration file pointer to retrieve path of retroarch.cfg.\n"); + + /* Core name: core_name + * Gets path to libretro.so or libretro.dll and strips the extension */ + else if (!global->has_set_libretro && ( !config_get_path(conf, "libretro_path", core_name_buffer, PATH_MAX_LENGTH) || !path_remove_extension(core_name_buffer) )) + RARCH_ERR("libretro_path is not set. Can't tell what core is running.\n"); + else /* if everything is O.K. */ + { + core_name = path_basename(core_name_buffer); /* and afterwards the basedirectory. What's left is i.e. "mupen64plus_libretro" */ + + /* Configuration directory: config_directory. + * Contains retroarch.cfg */ + fill_pathname_basedir(config_directory, global->config_path, PATH_MAX_LENGTH); + + /* ROM basename: game_name + * no extension or leading directory i.e. "Super Mario 64 (USA)" */ + game_name = path_basename(global->basename); + + /* Concatenate strings into full paths: core_path, game_path */ + fill_pathname_join(core_path, config_directory, core_name, PATH_MAX_LENGTH); + fill_pathname_join(core_path, core_path, core_name, PATH_MAX_LENGTH); + strlcat(core_path, ".cfg", PATH_MAX_LENGTH); + fill_pathname_join(game_path, config_directory, core_name, PATH_MAX_LENGTH); + fill_pathname_join(game_path, game_path, game_name, PATH_MAX_LENGTH); + strlcat(game_path, ".cfg", PATH_MAX_LENGTH); + + /* Append core-specific */ + if (config_append_file(conf, core_path)) + RARCH_LOG("Core-specific configuration found at %s. Appending.\n", core_path); + else + RARCH_LOG("No core-specific configuration found at %s.\n", core_path); + + /* Append game-specific */ + if (config_append_file(conf, game_path)) + RARCH_LOG("Game-specific configuration found at %s. Appending.\n", game_path); + else + RARCH_LOG("No game-specific configuration found at %s.\n", game_path); + + return true; /* only means no errors were caught */ + } + + return false; +} + /** * config_load: * @path : path to be read from. @@ -1123,6 +1199,8 @@ static bool config_load_file(const char *path, bool set_defaults) if (set_defaults) config_set_defaults(); + config_append_specific(conf); + strlcpy(tmp_append_path, global->append_config_path, sizeof(tmp_append_path)); extra_path = strtok_r(tmp_append_path, ",", &save);