flycast/shell/libretro/option_lr.h

205 lines
5.2 KiB
C++

/*
Copyright 2021 flyinghead
This file is part of Flycast.
Flycast is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
Flycast is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Flycast. If not, see <https://www.gnu.org/licenses/>.
*/
#pragma once
class Settings {
public:
void reset() {}
void load(bool gameSpecific)
{
if (gameSpecific)
return;
for (const auto& o : options)
o->load();
}
void save() {}
void setGameId(const std::string& gameId) {
this->gameId = gameId;
}
bool hasPerGameConfig() const {
return false;
}
void setPerGameConfig(bool perGameConfig) {}
void setRetroEnvironment(retro_environment_t retroEnv) {
this->retroEnv = retroEnv;
}
void setOptionDefinitions(const retro_core_option_v2_definition *optionDefs) {
this->optionDefs = optionDefs;
}
static Settings& instance() {
static Settings *_instance = new Settings();
return *_instance;
}
private:
std::vector<BaseOption *> options;
std::string gameId;
retro_environment_t retroEnv = nullptr;
const retro_core_option_v2_definition *optionDefs;
template<typename T, bool>
friend class Option;
friend class IntOption;
};
// Missing in C++11
template <bool B, typename T = void>
using enable_if_t = typename std::enable_if<B, T>::type;
template<typename T, bool PerGameOption = true>
class Option : public BaseOption {
public:
Option(const std::string& name, T defaultValue = T())
: name(name), value(defaultValue), defaultValue(defaultValue),
settings(Settings::instance())
{
settings.options.push_back(this);
}
void reset() override {
set(defaultValue);
overridden = false;
}
void load() override {
if (!name.empty())
set(doLoad(name));
}
void save() const override {}
T& get() { return value; }
void set(T v) { value = v; }
void override(T v) {
overriddenDefault = v;
overridden = true;
value = v;
}
bool isReadOnly() const {
return overridden;
}
explicit operator T() const { return value; }
operator T&() { return value; }
T& operator=(const T& v) { set(v); return value; }
protected:
const retro_core_option_v2_definition *findDefinition(const std::string& name) const {
for (const retro_core_option_v2_definition *pDef = settings.optionDefs; pDef->key != nullptr; pDef++)
if (name == pDef->key)
return pDef;
return nullptr;
}
template <typename U = T>
enable_if_t<std::is_same<U, bool>::value, T>
doLoad(const std::string& name) const
{
retro_variable var { name.c_str() };
if (settings.retroEnv(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value != nullptr)
{
const retro_core_option_v2_definition *def = findDefinition(name);
verify(def != nullptr);
if (!strcmp(var.value, def->values[1].value)) // TODO change defs so that choice 1 is true (and choice 0 is false)
return true;
else
return false;
}
return value;
}
template <typename U = T>
enable_if_t<(std::is_integral<U>::value || std::is_enum<U>::value)
&& !std::is_same<U, bool>::value, T>
doLoad(const std::string& name) const
{
retro_variable var { name.c_str() };
if (settings.retroEnv(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value != nullptr)
{
const retro_core_option_v2_definition *def = findDefinition(name);
verify(def != nullptr);
for (int i = 0; def->values[i].value != nullptr; i++)
if (!strcmp(var.value, def->values[i].value))
return (T)i;
}
return value;
}
template <typename U = T>
enable_if_t<std::is_same<U, std::string>::value, T>
doLoad(const std::string& name) const
{
retro_variable var { name.c_str() };
if (settings.retroEnv(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value != nullptr)
return var.value;
return value;
}
template <typename U = T>
enable_if_t<std::is_same<float, U>::value, T>
doLoad(const std::string& name) const
{
retro_variable var { name.c_str() };
if (settings.retroEnv(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value != nullptr)
return atof(var.value);
return value;
}
template <typename U = T>
enable_if_t<std::is_same<std::vector<std::string>, U>::value, T>
doLoad(const std::string& section, const std::string& name) const
{
return value;
}
std::string name;
T value;
T defaultValue;
T overriddenDefault = T();
bool overridden = false;
Settings& settings;
};
// Uses the setting value converted to int instead of the value index
class IntOption : public Option<int> {
public:
IntOption(const std::string& name, int defaultValue = 0)
: Option<int>(name, defaultValue)
{
}
void load() override {
retro_variable var { name.c_str() };
if (settings.retroEnv(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value != nullptr)
set(atoi(var.value));
}
};
extern Option<bool> PowerVR2Filter;
extern IntOption TextureUpscale;
extern IntOption MaxFilteredTextureSize;
extern IntOption PerPixelLayers;