flycast/core/cfg/cfg.cpp

216 lines
5.2 KiB
C++
Raw Normal View History

2013-12-19 17:10:14 +00:00
/*
Config file crap
Supports various things, as virtual config entries and such crap
Works surprisingly well considering how old it is ...
2013-12-19 17:10:14 +00:00
*/
#include "cfg.h"
#include "ini.h"
#include "stdclass.h"
#include <cerrno>
2013-12-19 17:10:14 +00:00
2020-03-29 17:29:14 +00:00
static std::string cfgPath;
static bool save_config = true;
2019-10-29 13:34:29 +00:00
static bool autoSave = true;
2013-12-19 17:10:14 +00:00
static emucfg::ConfigFile cfgdb;
2020-03-29 17:29:14 +00:00
static std::string game_id;
static bool has_game_specific_config = false;
2013-12-19 17:10:14 +00:00
void savecfgf()
{
FILE* cfgfile = fopen(cfgPath.c_str(),"wt");
if (!cfgfile)
2015-08-24 12:46:45 +00:00
{
2019-07-01 16:23:10 +00:00
WARN_LOG(COMMON, "Error: Unable to open file '%s' for saving", cfgPath.c_str());
2015-08-24 12:46:45 +00:00
}
2013-12-19 17:10:14 +00:00
else
{
cfgdb.save(cfgfile);
2013-12-19 17:10:14 +00:00
fclose(cfgfile);
}
}
2020-01-31 22:51:12 +00:00
void cfgSaveStr(const char * Section, const char * Key, const char * String)
2013-12-19 17:10:14 +00:00
{
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);
2019-10-29 13:34:29 +00:00
if (save_config && autoSave)
savecfgf();
2013-12-19 17:10:14 +00:00
}
//New config code
/*
I want config to be really flexible .. so , here is the new implementation :
2013-12-19 17:10:14 +00:00
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
2013-12-19 17:10:14 +00:00
Config parameters can be read from the config file , and can be given at the command line
2013-12-19 17:10:14 +00:00
-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
2013-12-19 17:10:14 +00:00
*/
///////////////////////////////
/*
** 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";
2020-03-29 17:29:14 +00:00
std::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);
2015-08-24 12:05:51 +00:00
}
else
{
// Config file can't be opened
int error_code = errno;
2019-07-01 16:23:10 +00:00
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
2019-07-01 16:23:10 +00:00
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;
}
2013-12-19 17:10:14 +00:00
}
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
2020-01-31 22:51:12 +00:00
s32 cfgExists(const char * Section, const char * Key)
2013-12-19 17:10:14 +00:00
{
2020-03-29 17:29:14 +00:00
if(cfgdb.has_entry(std::string(Section), std::string(Key)))
{
return 2;
}
else
{
2020-03-29 17:29:14 +00:00
return (cfgdb.has_section(std::string(Section)) ? 1 : 0);
}
2013-12-19 17:10:14 +00:00
}
2020-01-31 22:51:12 +00:00
void cfgLoadStr(const char * Section, const char * Key, char * Return,const char* Default)
2013-12-19 17:10:14 +00:00
{
2020-03-29 17:29:14 +00:00
std::string value = cfgdb.get(Section, Key, Default);
// FIXME: Buffer overflow possible
strcpy(Return, value.c_str());
2013-12-19 17:10:14 +00:00
}
2020-03-29 17:29:14 +00:00
std::string cfgLoadStr(const char * Section, const char * Key, const char* Default)
2015-03-22 00:16:28 +00:00
{
2020-03-29 17:29:14 +00:00
std::string v = cfgdb.get(std::string(Section), std::string(Key), std::string(Default));
if (cfgHasGameSpecificConfig())
2020-03-29 17:29:14 +00:00
v = cfgdb.get(game_id, std::string(Key), v);
return v;
2015-03-22 00:16:28 +00:00
}
2013-12-19 17:10:14 +00:00
//These are helpers , mainly :)
2020-01-31 22:51:12 +00:00
void cfgSaveInt(const char * Section, const char * Key, s32 Int)
2013-12-19 17:10:14 +00:00
{
char str[32];
sprintf(str, "%d", Int);
cfgSaveStr(Section, Key, str);
2013-12-19 17:10:14 +00:00
}
2020-01-31 22:51:12 +00:00
s32 cfgLoadInt(const char * Section, const char * Key,s32 Default)
2013-12-19 17:10:14 +00:00
{
2020-03-29 17:29:14 +00:00
s32 v = cfgdb.get_int(std::string(Section), std::string(Key), Default);
if (cfgHasGameSpecificConfig())
2020-03-29 17:29:14 +00:00
v = cfgdb.get_int(game_id, std::string(Key), v);
return v;
}
2020-01-31 22:51:12 +00:00
void cfgSaveBool(const char * Section, const char * Key, bool BoolValue)
2016-03-02 05:48:34 +00:00
{
cfgSaveStr(Section, Key, BoolValue ? "yes" : "no");
2016-03-02 05:48:34 +00:00
}
2020-01-31 22:51:12 +00:00
bool cfgLoadBool(const char * Section, const char * Key,bool Default)
2016-03-02 05:48:34 +00:00
{
2020-03-29 17:29:14 +00:00
bool v = cfgdb.get_bool(std::string(Section), std::string(Key), Default);
if (cfgHasGameSpecificConfig())
2020-03-29 17:29:14 +00:00
v = cfgdb.get_bool(game_id, std::string(Key), v);
return v;
2016-03-02 05:48:34 +00:00
}
2020-01-31 22:51:12 +00:00
void cfgSetVirtual(const char * Section, const char * Key, const char * String)
2013-12-19 17:10:14 +00:00
{
2020-03-29 17:29:14 +00:00
cfgdb.set(std::string(Section), std::string(Key), std::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);
}
2019-10-29 13:34:29 +00:00
void cfgSetAutoSave(bool autoSave)
{
::autoSave = autoSave;
if (autoSave)
savecfgf();
}