/* Config file crap Supports various things, as virtual config entries and such crap Works surprisingly well considering how old it is ... */ #define _CRT_SECURE_NO_DEPRECATE (1) #include #include "cfg.h" #include "ini.h" static string cfgPath; static bool save_config = true; static emucfg::ConfigFile cfgdb; static string game_id; static bool has_game_specific_config = false; void savecfgf() { FILE* cfgfile = fopen(cfgPath.c_str(),"wt"); if (!cfgfile) { WARN_LOG(COMMON, "Error: Unable to open file '%s' for saving", cfgPath.c_str()); } else { cfgdb.save(cfgfile); fclose(cfgfile); } } void cfgSaveStr(const wchar * Section, const wchar * Key, const wchar * String) { const std::string section(Section); const std::string key(Key); const std::string value(String); if (cfgHasGameSpecificConfig()) { if (cfgdb.get(section, key, "") == value) // Same value as main config: delete entry cfgdb.delete_entry(game_id, key); else cfgdb.set(game_id, key, value); } else cfgdb.set(section, key, value); if(save_config) { savecfgf(); } } //New config code /* I want config to be really flexible .. so , here is the new implementation : Functions : cfgLoadInt : Load an int , if it does not exist save the default value to it and return it cfgSaveInt : Save an int cfgLoadStr : Load a str , if it does not exist save the default value to it and return it cfgSaveStr : Save a str cfgExists : Returns true if the Section:Key exists. If Key is null , it retuns true if Section exists Config parameters can be read from the config file , and can be given at the command line -cfg section:key=value -> defines a value at command line If a cfgSave* is made on a value defined by command line , then the command line value is replaced by it cfg values set by command line are not written to the cfg file , unless a cfgSave* is used */ /////////////////////////////// /* ** This will verify there is a working file @ ./szIniFn ** - if not present, it will write defaults */ bool cfgOpen() { if (get_writable_config_path("").empty()) // Config dir not set (android onboarding) return false; const char* filename = "/emu.cfg"; string config_path_read = get_readonly_config_path(filename); cfgPath = get_writable_config_path(filename); FILE* cfgfile = fopen(config_path_read.c_str(),"r"); if(cfgfile != NULL) { cfgdb.parse(cfgfile); fclose(cfgfile); } else { // Config file can't be opened int error_code = errno; WARN_LOG(COMMON, "Warning: Unable to open the config file '%s' for reading (%s)", config_path_read.c_str(), strerror(error_code)); if (error_code == ENOENT || cfgPath != config_path_read) { // Config file didn't exist INFO_LOG(COMMON, "Creating new empty config file at '%s'", cfgPath.c_str()); savecfgf(); } else { // There was some other error (may be a permissions problem or something like that) save_config = false; } } return true; } //Implementations of the interface :) //Section must be set //If key is 0 , it looks for the section //0 : not found //1 : found section , key was 0 //2 : found section & key s32 cfgExists(const wchar * Section, const wchar * Key) { if(cfgdb.has_entry(string(Section), string(Key))) { return 2; } else { return (cfgdb.has_section(string(Section)) ? 1 : 0); } } void cfgLoadStr(const wchar * Section, const wchar * Key, wchar * Return,const wchar* Default) { string value = cfgdb.get(Section, Key, Default); // FIXME: Buffer overflow possible strcpy(Return, value.c_str()); } string cfgLoadStr(const wchar * Section, const wchar * Key, const wchar* Default) { std::string v = cfgdb.get(string(Section), string(Key), string(Default)); if (cfgHasGameSpecificConfig()) v = cfgdb.get(game_id, string(Key), v); return v; } //These are helpers , mainly :) void cfgSaveInt(const wchar * Section, const wchar * Key, s32 Int) { char str[32]; sprintf(str, "%d", Int); cfgSaveStr(Section, Key, str); } s32 cfgLoadInt(const wchar * Section, const wchar * Key,s32 Default) { s32 v = cfgdb.get_int(string(Section), string(Key), Default); if (cfgHasGameSpecificConfig()) v = cfgdb.get_int(game_id, string(Key), v); return v; } void cfgSaveBool(const wchar * Section, const wchar * Key, bool BoolValue) { cfgSaveStr(Section, Key, BoolValue ? "yes" : "no"); } bool cfgLoadBool(const wchar * Section, const wchar * Key,bool Default) { bool v = cfgdb.get_bool(string(Section), string(Key), Default); if (cfgHasGameSpecificConfig()) v = cfgdb.get_bool(game_id, string(Key), v); return v; } void cfgSetVirtual(const wchar * Section, const wchar * Key, const wchar * String) { cfgdb.set(string(Section), string(Key), string(String), true); } void cfgSetGameId(const char *id) { game_id = id; } const char *cfgGetGameId() { return game_id.c_str(); } bool cfgHasGameSpecificConfig() { return has_game_specific_config || cfgdb.has_section(game_id); } void cfgMakeGameSpecificConfig() { has_game_specific_config = true; } void cfgDeleteGameSpecificConfig() { has_game_specific_config = false; cfgdb.delete_section(game_id); }