mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-20 17:59:08 +02:00
Correct handling of fallbacks and defaulting
This commit is contained in:
1 parent
2b863aafe1
commit
1246b2d131
5 files changed
+211
-122
No files matched your search
+116
-81
@@ -637,22 +637,34 @@ bool DisplayLayoutConfig::InternalRotationIsPortrait() const {
|
||||
return (iInternalScreenRotation == ROTATION_LOCKED_VERTICAL || iInternalScreenRotation == ROTATION_LOCKED_VERTICAL180) && !g_Config.bSkipBufferEffects;
|
||||
}
|
||||
|
||||
bool DisplayLayoutConfig::ResetToDefault(std::string_view blockName) {
|
||||
static const DisplayLayoutConfig defaultLayout = DisplayLayoutConfig();
|
||||
*this = defaultLayout;
|
||||
if (endsWith(blockName, ".Portrait")) {
|
||||
// TODO: On mobile, where the aspect is fixed, we should use the screen size to compute this properly,
|
||||
// so the screen almost touches the top edge.
|
||||
fDisplayOffsetY = 0.25f;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// These were previously part of Graphics.
|
||||
// It's instantiated into g_Config.displayLayoutLandscape and g_Config.displayLayoutPortrait.
|
||||
// Defaults are set directly on the struct declaration (and adjusted per instance in ResetToDefault above).
|
||||
static const ConfigSetting displayLayoutSettings[] = {
|
||||
ConfigSetting("BufferFiltering", SETTING(g_Config.displayLayoutLandscape, iDisplayFilter), SCALE_LINEAR, CfgFlag::PER_GAME),
|
||||
ConfigSetting("DisplayStretch", SETTING(g_Config.displayLayoutLandscape, bDisplayStretch), false, CfgFlag::PER_GAME),
|
||||
ConfigSetting("DisplayOffsetX", SETTING(g_Config.displayLayoutLandscape, fDisplayOffsetX), 0.5f, CfgFlag::PER_GAME),
|
||||
ConfigSetting("DisplayOffsetY", SETTING(g_Config.displayLayoutLandscape, fDisplayOffsetY), 0.5f, CfgFlag::PER_GAME),
|
||||
ConfigSetting("DisplayScale", SETTING(g_Config.displayLayoutLandscape, fDisplayScale), 1.0f, CfgFlag::PER_GAME),
|
||||
ConfigSetting("DisplayIntegerScale", SETTING(g_Config.displayLayoutLandscape, bDisplayIntegerScale), false, CfgFlag::PER_GAME),
|
||||
ConfigSetting("DisplayAspectRatio", SETTING(g_Config.displayLayoutLandscape, fDisplayAspectRatio), 1.0f, CfgFlag::PER_GAME),
|
||||
ConfigSetting("IgnoreScreenInsets", SETTING(g_Config.displayLayoutLandscape, bIgnoreScreenInsets), true, CfgFlag::PER_GAME),
|
||||
ConfigSetting("InternalScreenRotation", SETTING(g_Config.displayLayoutLandscape, iInternalScreenRotation), ROTATION_LOCKED_HORIZONTAL, CfgFlag::PER_GAME),
|
||||
ConfigSetting("EnableCardboardVR", SETTING(g_Config.displayLayoutLandscape, bEnableCardboardVR), false, CfgFlag::PER_GAME),
|
||||
ConfigSetting("CardboardScreenSize", SETTING(g_Config.displayLayoutLandscape, iCardboardScreenSize), 50, CfgFlag::PER_GAME),
|
||||
ConfigSetting("CardboardXShift", SETTING(g_Config.displayLayoutLandscape, iCardboardXShift), 0, CfgFlag::PER_GAME),
|
||||
ConfigSetting("CardboardYShift", SETTING(g_Config.displayLayoutLandscape, iCardboardYShift), 0, CfgFlag::PER_GAME),
|
||||
ConfigSetting("BufferFiltering", SETTING(g_Config.displayLayoutLandscape, iDisplayFilter), CfgFlag::PER_GAME),
|
||||
ConfigSetting("DisplayStretch", SETTING(g_Config.displayLayoutLandscape, bDisplayStretch), CfgFlag::PER_GAME),
|
||||
ConfigSetting("DisplayOffsetX", SETTING(g_Config.displayLayoutLandscape, fDisplayOffsetX), CfgFlag::PER_GAME),
|
||||
ConfigSetting("DisplayOffsetY", SETTING(g_Config.displayLayoutLandscape, fDisplayOffsetY), CfgFlag::PER_GAME),
|
||||
ConfigSetting("DisplayScale", SETTING(g_Config.displayLayoutLandscape, fDisplayScale), CfgFlag::PER_GAME),
|
||||
ConfigSetting("DisplayIntegerScale", SETTING(g_Config.displayLayoutLandscape, bDisplayIntegerScale), CfgFlag::PER_GAME),
|
||||
ConfigSetting("DisplayAspectRatio", SETTING(g_Config.displayLayoutLandscape, fDisplayAspectRatio), CfgFlag::PER_GAME),
|
||||
ConfigSetting("IgnoreScreenInsets", SETTING(g_Config.displayLayoutLandscape, bIgnoreScreenInsets), CfgFlag::PER_GAME),
|
||||
ConfigSetting("InternalScreenRotation", SETTING(g_Config.displayLayoutLandscape, iInternalScreenRotation), CfgFlag::PER_GAME),
|
||||
ConfigSetting("EnableCardboardVR", SETTING(g_Config.displayLayoutLandscape, bEnableCardboardVR), CfgFlag::PER_GAME),
|
||||
ConfigSetting("CardboardScreenSize", SETTING(g_Config.displayLayoutLandscape, iCardboardScreenSize), CfgFlag::PER_GAME),
|
||||
ConfigSetting("CardboardXShift", SETTING(g_Config.displayLayoutLandscape, iCardboardXShift), CfgFlag::PER_GAME),
|
||||
ConfigSetting("CardboardYShift", SETTING(g_Config.displayLayoutLandscape, iCardboardYShift), CfgFlag::PER_GAME),
|
||||
};
|
||||
|
||||
static const ConfigSetting graphicsSettings[] = {
|
||||
@@ -1064,7 +1076,7 @@ static const ConfigSetting vrSettings[] = {
|
||||
};
|
||||
|
||||
// The first column says what structure the parameters are relative to.
|
||||
static const ConfigSectionMeta sectionMeta[] = {
|
||||
static const ConfigSectionMeta g_sectionMeta[] = {
|
||||
{ &g_Config, generalSettings, ARRAY_SIZE(generalSettings), "General" },
|
||||
{ &g_Config, cpuSettings, ARRAY_SIZE(cpuSettings), "CPU" },
|
||||
{ &g_Config, graphicsSettings, ARRAY_SIZE(graphicsSettings), "Graphics" },
|
||||
@@ -1081,54 +1093,32 @@ static const ConfigSectionMeta sectionMeta[] = {
|
||||
{ &g_Config.displayLayoutPortrait, displayLayoutSettings, ARRAY_SIZE(displayLayoutSettings), "DisplayLayout.Portrait"}, // These we don't want to read from the old settings, since for most people, those settings will be bad.
|
||||
};
|
||||
|
||||
const size_t numSections = ARRAY_SIZE(sectionMeta);
|
||||
|
||||
static inline void IterateSettingsIni(IniFile &iniFile, std::function<void(ConfigBlock *configBlock, Section *section, const ConfigSetting &setting)> func, bool tryFallback) {
|
||||
for (size_t i = 0; i < numSections; ++i) {
|
||||
Section *section = iniFile.GetSection(sectionMeta[i].section);
|
||||
// Not found? Try the fallback (to upgrade settings that have been moved from old sections).
|
||||
if (!section && tryFallback) {
|
||||
section = iniFile.GetSection(sectionMeta[i].fallbackSection);
|
||||
}
|
||||
// Still not found? Create the original section.
|
||||
if (!section) {
|
||||
section = iniFile.GetOrCreateSection(sectionMeta[i].section);
|
||||
}
|
||||
// Now section is guaranteed to be valid.
|
||||
ConfigBlock *configBlock = sectionMeta[i].configBlock;
|
||||
for (size_t j = 0; j < sectionMeta[i].settingsCount; j++) {
|
||||
func(configBlock, section, sectionMeta[i].settings[j]);
|
||||
ConfigBlock *GetConfigBlockForSection(std::string_view sectionName) {
|
||||
for (const ConfigSectionMeta &meta : g_sectionMeta) {
|
||||
if (equals(meta.section, sectionName)) {
|
||||
return meta.configBlock;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static inline void IterateSettings(std::function<void(ConfigBlock *configBlock, const ConfigSetting &setting)> func) {
|
||||
for (size_t i = 0; i < numSections; ++i) {
|
||||
ConfigBlock *configBlock = sectionMeta[i].configBlock;
|
||||
for (size_t j = 0; j < sectionMeta[i].settingsCount; j++) {
|
||||
func(configBlock, sectionMeta[i].settings[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
const size_t numSections = ARRAY_SIZE(g_sectionMeta);
|
||||
|
||||
static inline void IterateConfigBlock(ConfigSectionMeta *meta, std::function<void(const ConfigSectionMeta &meta, const ConfigSetting &setting)> func) {
|
||||
for (size_t j = 0; j < meta->settingsCount; j++) {
|
||||
func(*meta, meta->settings[j]);
|
||||
}
|
||||
}
|
||||
|
||||
std::map<const void *, const ConfigSetting *> &Config::getPtrLUT() {
|
||||
static std::map<const void *, const ConfigSetting *> lut;
|
||||
std::map<const void *, std::pair<const ConfigBlock *, const ConfigSetting *>> &Config::getPtrLUT() {
|
||||
static std::map<const void *, std::pair<const ConfigBlock *, const ConfigSetting *>> lut;
|
||||
return lut;
|
||||
}
|
||||
|
||||
Config::Config() {
|
||||
// Initialize the pointer->setting lookup map.
|
||||
auto ref = getPtrLUT();
|
||||
IterateSettings([&ref](ConfigBlock *configBlock, const ConfigSetting &setting) {
|
||||
const void *ptr = setting.GetVoidPtr(configBlock);
|
||||
ref[ptr] = &setting;
|
||||
});
|
||||
for (size_t i = 0; i < numSections; ++i) {
|
||||
ConfigBlock *configBlock = g_sectionMeta[i].configBlock;
|
||||
for (size_t j = 0; j < g_sectionMeta[i].settingsCount; j++) {
|
||||
const void *ptr = g_sectionMeta[i].settings[j].GetVoidPtr(configBlock);
|
||||
ref[ptr] = std::make_pair(configBlock, &g_sectionMeta[i].settings[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Config::~Config() {
|
||||
@@ -1162,11 +1152,15 @@ bool Config::LoadAppendedConfig() {
|
||||
return false;
|
||||
}
|
||||
|
||||
IterateSettingsIni(iniFile, [&iniFile](ConfigBlock *configBlock, Section *section, const ConfigSetting &setting) {
|
||||
if (section->HasKey(setting.iniKey_)) {
|
||||
setting.ReadFromIniSection(configBlock, section, true);
|
||||
for (const ConfigSectionMeta &meta : g_sectionMeta) {
|
||||
Section *section = iniFile.GetSection(meta.section);
|
||||
if (!section) {
|
||||
continue;
|
||||
}
|
||||
}, true);
|
||||
for (size_t j = 0; j < meta.settingsCount; j++) {
|
||||
meta.settings[j].ReadFromIniSection(meta.configBlock, section, false);
|
||||
}
|
||||
}
|
||||
|
||||
INFO_LOG(Log::Loader, "Loaded appended config '%s'.", appendedConfigFileName_.c_str());
|
||||
|
||||
@@ -1184,6 +1178,28 @@ void Config::UpdateAfterSettingAutoFrameSkip() {
|
||||
}
|
||||
}
|
||||
|
||||
void Config::ReadAllSettings(const IniFile &iniFile) {
|
||||
// Read settings. Note, configblocks can now support their own defaulting mechanism.
|
||||
for (const ConfigSectionMeta &meta : g_sectionMeta) {
|
||||
const Section *section = iniFile.GetSection(meta.section);
|
||||
ConfigBlock *configBlock = meta.configBlock;
|
||||
// Not found? Try the fallback (to upgrade settings that have been moved from old sections).
|
||||
if (!section && !meta.fallbackSectionName.empty()) {
|
||||
section = iniFile.GetSection(meta.fallbackSectionName);
|
||||
configBlock = GetConfigBlockForSection(meta.fallbackSectionName);
|
||||
}
|
||||
// If section is still null, we'll handle that gracefully by resetting to defaults.
|
||||
_dbg_assert_(configBlock);
|
||||
bool applyDefaultPerSetting = true;
|
||||
if (configBlock->ResetToDefault(meta.section)) {
|
||||
applyDefaultPerSetting = false;
|
||||
}
|
||||
for (size_t j = 0; j < meta.settingsCount; j++) {
|
||||
meta.settings[j].ReadFromIniSection(configBlock, section, applyDefaultPerSetting);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Config::Load(const char *iniFileName, const char *controllerIniFilename) {
|
||||
double startTime = time_now_d();
|
||||
|
||||
@@ -1205,9 +1221,7 @@ void Config::Load(const char *iniFileName, const char *controllerIniFilename) {
|
||||
// Continue anyway to initialize the config.
|
||||
}
|
||||
|
||||
IterateSettingsIni(iniFile, [](ConfigBlock *configBlock, const Section *section, const ConfigSetting &setting) {
|
||||
setting.ReadFromIniSection(configBlock, section, true);
|
||||
}, true);
|
||||
ReadAllSettings(iniFile);
|
||||
|
||||
iRunCount++;
|
||||
|
||||
@@ -1331,11 +1345,14 @@ bool Config::Save(const char *saveReason) {
|
||||
// Need to do this somewhere...
|
||||
bFirstRun = false;
|
||||
|
||||
IterateSettingsIni(iniFile, [&](ConfigBlock *configBlock, Section *section, const ConfigSetting &setting) {
|
||||
if (!gameSpecific_ || !setting.PerGame()) {
|
||||
setting.WriteToIniSection(configBlock, section);
|
||||
// Do the writing.
|
||||
for (const ConfigSectionMeta &meta : g_sectionMeta) {
|
||||
Section *section = iniFile.GetOrCreateSection(meta.section);
|
||||
ConfigBlock *configBlock = meta.configBlock;
|
||||
for (size_t j = 0; j < meta.settingsCount; j++) {
|
||||
meta.settings[j].WriteToIniSection(configBlock, section);
|
||||
}
|
||||
}, false);
|
||||
}
|
||||
|
||||
Section *recent = iniFile.GetOrCreateSection("Recent");
|
||||
recent->Set("MaxRecent", iMaxRecent);
|
||||
@@ -1544,9 +1561,17 @@ void Config::RestoreDefaults(RestoreSettingsBits whatToRestore, bool log) {
|
||||
Load();
|
||||
} else {
|
||||
if (whatToRestore & RestoreSettingsBits::SETTINGS) {
|
||||
IterateSettings([log](ConfigBlock *configBlock, const ConfigSetting &setting) {
|
||||
setting.RestoreToDefault(configBlock, log);
|
||||
});
|
||||
// Read settings. Note, ConfigBlocks can now support their own defaulting mechanism.
|
||||
for (const auto &meta : g_sectionMeta) {
|
||||
ConfigBlock *configBlock = meta.configBlock;
|
||||
bool applyDefaultPerSetting = true;
|
||||
if (!configBlock->ResetToDefault(meta.section)) {
|
||||
// Reset the settings one by one.
|
||||
for (size_t j = 0; j < meta.settingsCount; j++) {
|
||||
meta.settings[j].RestoreToDefault(configBlock, log);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (whatToRestore & RestoreSettingsBits::CONTROLS) {
|
||||
@@ -1629,11 +1654,15 @@ bool Config::SaveGameConfig(const std::string &gameId, std::string_view titleFor
|
||||
|
||||
PreSaveCleanup();
|
||||
|
||||
IterateSettingsIni(iniFile, [](ConfigBlock *configBlock, Section *section, const ConfigSetting &setting) {
|
||||
if (setting.PerGame()) {
|
||||
setting.WriteToIniSection(configBlock, section);
|
||||
for (const ConfigSectionMeta &meta : g_sectionMeta) {
|
||||
Section *section = iniFile.GetOrCreateSection(meta.section);
|
||||
ConfigBlock *configBlock = meta.configBlock;
|
||||
for (size_t j = 0; j < meta.settingsCount; j++) {
|
||||
if (meta.settings[j].PerGame()) {
|
||||
meta.settings[j].WriteToIniSection(configBlock, section);
|
||||
}
|
||||
}
|
||||
}, false);
|
||||
}
|
||||
|
||||
Section *postShaderSetting = iniFile.GetOrCreateSection("PostShaderSetting");
|
||||
postShaderSetting->Clear();
|
||||
@@ -1691,11 +1720,18 @@ bool Config::LoadGameConfig(const std::string &gameId) {
|
||||
vPostShaderNames.push_back(v);
|
||||
}
|
||||
|
||||
IterateSettingsIni(iniFile, [](ConfigBlock *configBlock, const Section *section, const ConfigSetting &setting) {
|
||||
if (setting.PerGame()) {
|
||||
setting.ReadFromIniSection(configBlock, section, true);
|
||||
for (const ConfigSectionMeta &meta : g_sectionMeta) {
|
||||
Section *section = iniFile.GetSection(meta.section);
|
||||
ConfigBlock *configBlock = meta.configBlock;
|
||||
// Not found? Try the fallback (to upgrade settings that have been moved from old sections).
|
||||
if (!section && !meta.fallbackSectionName.empty()) {
|
||||
section = iniFile.GetSection(meta.fallbackSectionName);
|
||||
configBlock = GetConfigBlockForSection(meta.fallbackSectionName);
|
||||
}
|
||||
}, true);
|
||||
for (size_t j = 0; j < meta.settingsCount; j++) {
|
||||
meta.settings[j].ReadFromIniSection(configBlock, section, false);
|
||||
}
|
||||
}
|
||||
|
||||
KeyMap::LoadFromIni(iniFile);
|
||||
|
||||
@@ -1721,9 +1757,8 @@ void Config::UnloadGameConfig() {
|
||||
// Reload all settings from the main ini file.
|
||||
IniFile iniFile;
|
||||
iniFile.Load(iniFilename_);
|
||||
IterateSettingsIni(iniFile, [](ConfigBlock *configBlock, const Section *section, const ConfigSetting &setting) {
|
||||
setting.ReadFromIniSection(configBlock, section, true);
|
||||
}, true);
|
||||
|
||||
ReadAllSettings(iniFile);
|
||||
|
||||
auto postShaderSetting = iniFile.GetOrCreateSection("PostShaderSetting")->ToMap();
|
||||
mPostShaderSetting.clear();
|
||||
@@ -1778,11 +1813,11 @@ void Config::ResetControlLayout() {
|
||||
}
|
||||
|
||||
void Config::GetReportingInfo(UrlEncoder &data) const {
|
||||
for (size_t i = 0; i < numSections; ++i) {
|
||||
const std::string prefix = join("config.", sectionMeta[i].section);
|
||||
ConfigBlock *configBlock = sectionMeta[i].configBlock;
|
||||
for (size_t j = 0; j < sectionMeta[i].settingsCount; j++) {
|
||||
sectionMeta[i].settings[j].ReportSetting(configBlock, data, prefix);
|
||||
for (const ConfigSectionMeta &meta : g_sectionMeta) {
|
||||
const std::string prefix = join("config.", meta.section);
|
||||
ConfigBlock *configBlock = meta.configBlock;
|
||||
for (size_t j = 0; j < meta.settingsCount; j++) {
|
||||
meta.settings[j].ReportSetting(configBlock, data, prefix);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+28
-20
@@ -39,6 +39,7 @@ namespace http {
|
||||
struct UrlEncoder;
|
||||
|
||||
class Section;
|
||||
class IniFile;
|
||||
|
||||
class PlayTimeTracker {
|
||||
public:
|
||||
@@ -65,6 +66,9 @@ struct ConfigSetting;
|
||||
|
||||
struct ConfigBlock {
|
||||
virtual ~ConfigBlock() = default;
|
||||
virtual bool CanResetToDefault() const { return false; }
|
||||
// If a block returns false here (like Config itself does), resetting to default will happen by the old per-setting mechanism.
|
||||
virtual bool ResetToDefault(std::string_view blockName) { return false; }
|
||||
};
|
||||
|
||||
struct ConfigSectionMeta {
|
||||
@@ -72,26 +76,29 @@ struct ConfigSectionMeta {
|
||||
const ConfigSetting *settings;
|
||||
size_t settingsCount;
|
||||
std::string_view section;
|
||||
std::string_view fallbackSection; // used if section is not found (useful when moving settings into a struct from Config).
|
||||
std::string_view fallbackSectionName; // used if section is not found (useful when moving settings into a struct from Config).
|
||||
};
|
||||
|
||||
struct DisplayLayoutConfig : public ConfigBlock {
|
||||
int iDisplayFilter; // 1 = linear, 2 = nearest
|
||||
bool bDisplayStretch; // Automatically matches the aspect ratio of the window.
|
||||
float fDisplayOffsetX;
|
||||
float fDisplayOffsetY;
|
||||
float fDisplayScale; // Relative to the most constraining axis (x or y).
|
||||
bool bDisplayIntegerScale; // Snaps scaling to integer scale factors in raw pixels.
|
||||
float fDisplayAspectRatio; // Stored relative to the PSP's native ratio, so 1.0 is the normal pixel aspect ratio.
|
||||
int iInternalScreenRotation; // The internal screen rotation angle. Useful for vertical SHMUPs and similar.
|
||||
bool bIgnoreScreenInsets; // Android: Center screen disregarding insets if this is enabled.
|
||||
int iDisplayFilter = SCALE_LINEAR; // 1 = linear, 2 = nearest
|
||||
bool bDisplayStretch = false; // Automatically matches the aspect ratio of the window.
|
||||
float fDisplayOffsetX = 0.5f;
|
||||
float fDisplayOffsetY = 0.5f;
|
||||
float fDisplayScale = 1.0f; // Relative to the most constraining axis (x or y).
|
||||
bool bDisplayIntegerScale = false; // Snaps scaling to integer scale factors in raw pixels.
|
||||
float fDisplayAspectRatio = 1.0f; // Stored relative to the PSP's native ratio, so 1.0 is the normal pixel aspect ratio.
|
||||
int iInternalScreenRotation = ROTATION_LOCKED_HORIZONTAL; // The internal screen rotation angle. Useful for vertical SHMUPs and similar.
|
||||
bool bIgnoreScreenInsets = true; // Android: Center screen disregarding insets if this is enabled.
|
||||
|
||||
bool bEnableCardboardVR; // Cardboard Master Switch
|
||||
int iCardboardScreenSize; // Screen Size (in %)
|
||||
int iCardboardXShift; // X-Shift of Screen (in %)
|
||||
int iCardboardYShift; // Y-Shift of Screen (in %)
|
||||
// Deprecated
|
||||
bool bEnableCardboardVR = false; // Cardboard Master Switch
|
||||
int iCardboardScreenSize = 50; // Screen Size (in %)
|
||||
int iCardboardXShift = 0; // X-Shift of Screen (in %)
|
||||
int iCardboardYShift = 0; // Y-Shift of Screen (in %)
|
||||
|
||||
bool InternalRotationIsPortrait() const;
|
||||
bool CanResetToDefault() const override { return true; }
|
||||
bool ResetToDefault(std::string_view blockName) override;
|
||||
};
|
||||
|
||||
struct Config : public ConfigBlock {
|
||||
@@ -689,16 +696,20 @@ public:
|
||||
return orientation == DeviceOrientation::Portrait ? displayLayoutPortrait : displayLayoutLandscape;
|
||||
}
|
||||
|
||||
protected:
|
||||
private:
|
||||
void LoadStandardControllerIni();
|
||||
|
||||
void PostLoadCleanup();
|
||||
void PreSaveCleanup();
|
||||
void PostSaveCleanup();
|
||||
|
||||
static std::map<const void*, const ConfigSetting *> &getPtrLUT();
|
||||
friend struct ConfigSetting;
|
||||
|
||||
static std::map<const void *, std::pair<const ConfigBlock *, const ConfigSetting *>> &getPtrLUT();
|
||||
|
||||
// Applies defaults for missing settings.
|
||||
void ReadAllSettings(const IniFile &iniFile);
|
||||
|
||||
private:
|
||||
bool reload_ = false;
|
||||
|
||||
bool gameSpecific_ = false;
|
||||
@@ -711,9 +722,6 @@ private:
|
||||
Path appendedConfigFileName_;
|
||||
// A set make more sense, but won't have many entry, and I dont want to include the whole std::set header here
|
||||
std::vector<std::string> appendedConfigUpdatedGames_;
|
||||
|
||||
// TODO: Remove hack.
|
||||
friend struct ConfigSetting;
|
||||
};
|
||||
|
||||
std::string CreateRandMAC();
|
||||
|
||||
+46
-21
@@ -9,7 +9,7 @@
|
||||
#include "Core/Config.h"
|
||||
|
||||
bool ConfigSetting::perGame(void *ptr) {
|
||||
return g_Config.gameSpecific_ && g_Config.getPtrLUT().count(ptr) > 0 && g_Config.getPtrLUT()[ptr]->PerGame();
|
||||
return g_Config.IsGameSpecific() && g_Config.getPtrLUT().count(ptr) > 0 && g_Config.getPtrLUT()[ptr].second->PerGame();
|
||||
}
|
||||
|
||||
bool ConfigSetting::ReadFromIniSection(ConfigBlock *configBlock, const Section *section, bool applyDefaultIfMissing) const {
|
||||
@@ -18,7 +18,7 @@ bool ConfigSetting::ReadFromIniSection(ConfigBlock *configBlock, const Section *
|
||||
case Type::TYPE_BOOL:
|
||||
{
|
||||
bool *target = (bool *)(owner + offset_);
|
||||
if (!section->Get(iniKey_, target)) {
|
||||
if (!section || !section->Get(iniKey_, target)) {
|
||||
if (applyDefaultIfMissing) {
|
||||
*target = defaultCallback_.b ? defaultCallback_.b() : default_.b;
|
||||
}
|
||||
@@ -29,14 +29,14 @@ bool ConfigSetting::ReadFromIniSection(ConfigBlock *configBlock, const Section *
|
||||
case Type::TYPE_INT:
|
||||
{
|
||||
int *target = (int *)(owner + offset_);
|
||||
if (translateFrom_) {
|
||||
if (translateFrom_ && section) {
|
||||
std::string value;
|
||||
if (section->Get(iniKey_, &value)) {
|
||||
*((int *)(owner + offset_)) = translateFrom_(value);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (!section->Get(iniKey_, target)) {
|
||||
if (!section || !section->Get(iniKey_, target)) {
|
||||
if (applyDefaultIfMissing) {
|
||||
*target = defaultCallback_.i ? defaultCallback_.i() : default_.i;
|
||||
}
|
||||
@@ -47,7 +47,7 @@ bool ConfigSetting::ReadFromIniSection(ConfigBlock *configBlock, const Section *
|
||||
case Type::TYPE_UINT32:
|
||||
{
|
||||
uint32_t *target = (uint32_t *)(owner + offset_);
|
||||
if (!section->Get(iniKey_, target)) {
|
||||
if (!section || !section->Get(iniKey_, target)) {
|
||||
if (applyDefaultIfMissing) {
|
||||
*target = defaultCallback_.u ? defaultCallback_.u() : default_.u;
|
||||
}
|
||||
@@ -58,7 +58,7 @@ bool ConfigSetting::ReadFromIniSection(ConfigBlock *configBlock, const Section *
|
||||
case Type::TYPE_UINT64:
|
||||
{
|
||||
uint64_t *target = (uint64_t *)(owner + offset_);
|
||||
if (!section->Get(iniKey_, target)) {
|
||||
if (!section || !section->Get(iniKey_, target)) {
|
||||
if (applyDefaultIfMissing) {
|
||||
*target = defaultCallback_.lu ? defaultCallback_.lu() : default_.lu;
|
||||
}
|
||||
@@ -69,7 +69,7 @@ bool ConfigSetting::ReadFromIniSection(ConfigBlock *configBlock, const Section *
|
||||
case Type::TYPE_FLOAT:
|
||||
{
|
||||
float *target = (float *)(owner + offset_);
|
||||
if (!section->Get(iniKey_, target)) {
|
||||
if (!section || !section->Get(iniKey_, target)) {
|
||||
if (applyDefaultIfMissing) {
|
||||
*target = defaultCallback_.f ? defaultCallback_.f() : default_.f;
|
||||
}
|
||||
@@ -80,7 +80,7 @@ bool ConfigSetting::ReadFromIniSection(ConfigBlock *configBlock, const Section *
|
||||
case Type::TYPE_STRING:
|
||||
{
|
||||
std::string *target = (std::string *)(owner + offset_);
|
||||
if (!section->Get(iniKey_, target)) {
|
||||
if (!section || !section->Get(iniKey_, target)) {
|
||||
if (applyDefaultIfMissing) {
|
||||
if (defaultCallback_.s) {
|
||||
*target = defaultCallback_.s();
|
||||
@@ -98,7 +98,7 @@ bool ConfigSetting::ReadFromIniSection(ConfigBlock *configBlock, const Section *
|
||||
{
|
||||
// No support for callbacks for these yet. that's not an issue.
|
||||
std::vector<std::string> *ptr = (std::vector<std::string> *)(owner + offset_);
|
||||
if (!section->Get(iniKey_, ptr)) {
|
||||
if (!section || !section->Get(iniKey_, ptr)) {
|
||||
if (applyDefaultIfMissing && default_.v) {
|
||||
CopyStrings(ptr, *default_.v);
|
||||
}
|
||||
@@ -112,16 +112,16 @@ bool ConfigSetting::ReadFromIniSection(ConfigBlock *configBlock, const Section *
|
||||
ConfigTouchPos defaultTouchPos = defaultCallback_.touchPos ? defaultCallback_.touchPos() : default_.touchPos;
|
||||
|
||||
ConfigTouchPos *touchPos = ((ConfigTouchPos *)(owner + offset_));
|
||||
if (!section->Get(iniKey_, &touchPos->x) && applyDefaultIfMissing) {
|
||||
if (!section || (!section->Get(iniKey_, &touchPos->x) && applyDefaultIfMissing)) {
|
||||
touchPos->x = defaultTouchPos.x;
|
||||
}
|
||||
if (!section->Get(ini2_, &touchPos->y) && applyDefaultIfMissing) {
|
||||
if (!section || (!section->Get(ini2_, &touchPos->y) && applyDefaultIfMissing)) {
|
||||
touchPos->y = defaultTouchPos.y;
|
||||
}
|
||||
if (!section->Get(ini3_, &touchPos->scale) && applyDefaultIfMissing) {
|
||||
if (!section || (!section->Get(ini3_, &touchPos->scale) && applyDefaultIfMissing)) {
|
||||
touchPos->scale = defaultTouchPos.scale;
|
||||
}
|
||||
if (ini4_ && section->Get(ini4_, &touchPos->show)) {
|
||||
if (ini4_ && section && section->Get(ini4_, &touchPos->show)) {
|
||||
// do nothing, succeeded.
|
||||
} else if (applyDefaultIfMissing) {
|
||||
touchPos->show = defaultTouchPos.show;
|
||||
@@ -132,7 +132,7 @@ bool ConfigSetting::ReadFromIniSection(ConfigBlock *configBlock, const Section *
|
||||
{
|
||||
Path *target = (Path *)(owner + offset_);
|
||||
std::string tmp;
|
||||
if (!section->Get(iniKey_, &tmp)) {
|
||||
if (!section || !section->Get(iniKey_, &tmp)) {
|
||||
if (applyDefaultIfMissing) {
|
||||
if (defaultCallback_.p) {
|
||||
*target = defaultCallback_.p();
|
||||
@@ -150,19 +150,19 @@ bool ConfigSetting::ReadFromIniSection(ConfigBlock *configBlock, const Section *
|
||||
ConfigCustomButton defaultCustomButton = defaultCallback_.customButton ? defaultCallback_.customButton() : default_.customButton;
|
||||
|
||||
ConfigCustomButton *customButton = ((ConfigCustomButton *)(owner + offset_));
|
||||
if (!section->Get(iniKey_, &customButton->key) && applyDefaultIfMissing) {
|
||||
if (!section || (!section->Get(iniKey_, &customButton->key) && applyDefaultIfMissing)) {
|
||||
customButton->key = defaultCustomButton.key;
|
||||
}
|
||||
if (!section->Get(ini2_, &customButton->image) && applyDefaultIfMissing) {
|
||||
if (!section || (!section->Get(ini2_, &customButton->image) && applyDefaultIfMissing)) {
|
||||
customButton->image = defaultCustomButton.image;
|
||||
}
|
||||
if (!section->Get(ini3_, &customButton->shape) && applyDefaultIfMissing) {
|
||||
if (!section || (!section->Get(ini3_, &customButton->shape) && applyDefaultIfMissing)) {
|
||||
customButton->shape = defaultCustomButton.shape;
|
||||
}
|
||||
if (!section->Get(ini4_, &customButton->toggle) && applyDefaultIfMissing) {
|
||||
if (!section || (!section->Get(ini4_, &customButton->toggle) && applyDefaultIfMissing)) {
|
||||
customButton->toggle = defaultCustomButton.toggle;
|
||||
}
|
||||
if (!section->Get(ini5_, &customButton->repeat) && applyDefaultIfMissing) {
|
||||
if (!section || (!section->Get(ini5_, &customButton->repeat) && applyDefaultIfMissing)) {
|
||||
customButton->repeat = defaultCustomButton.repeat;
|
||||
}
|
||||
return true;
|
||||
@@ -177,6 +177,7 @@ void ConfigSetting::WriteToIniSection(const ConfigBlock *configBlock, Section *s
|
||||
if (!SaveSetting()) {
|
||||
return;
|
||||
}
|
||||
_dbg_assert_(section);
|
||||
|
||||
const char *owner = (const char *)configBlock;
|
||||
switch (type_) {
|
||||
@@ -232,6 +233,9 @@ void ConfigSetting::WriteToIniSection(const ConfigBlock *configBlock, Section *s
|
||||
}
|
||||
|
||||
bool ConfigSetting::RestoreToDefault(ConfigBlock *configBlock, bool log) const {
|
||||
// If the block supports resetting itself, don't allow per-setting resets. Shake them out with this assert.
|
||||
_dbg_assert_(!configBlock->CanResetToDefault());
|
||||
|
||||
const char *owner = (const char *)configBlock;
|
||||
switch (type_) {
|
||||
case Type::TYPE_BOOL:
|
||||
@@ -363,6 +367,27 @@ bool ConfigSetting::RestoreToDefault(ConfigBlock *configBlock, bool log) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Might be used to copy individual settings from defaulted blocks. Didn't end up using this for now.
|
||||
void ConfigSetting::CopyFromBlock(const ConfigBlock *other) {
|
||||
const char *otherOwner = (const char *)other;
|
||||
const char *thisOwner = (const char *)this;
|
||||
switch (type_) {
|
||||
case Type::TYPE_BOOL: *(bool *)(thisOwner + offset_) = *(const bool *)(otherOwner + offset_); break;
|
||||
case Type::TYPE_INT: *(int *)(thisOwner + offset_) = *(const int *)(otherOwner + offset_); break;
|
||||
case Type::TYPE_UINT32: *(uint32_t *)(thisOwner + offset_) = *(const uint32_t *)(otherOwner + offset_); break;
|
||||
case Type::TYPE_UINT64: *(uint64_t *)(thisOwner + offset_) = *(const uint64_t *)(otherOwner + offset_); break;
|
||||
case Type::TYPE_FLOAT: *(float *)(thisOwner + offset_) = *(const float *)(otherOwner + offset_); break;
|
||||
case Type::TYPE_STRING: *(std::string *)(thisOwner + offset_) = *(const std::string *)(otherOwner + offset_); break;
|
||||
case Type::TYPE_STRING_VECTOR: *(std::vector<std::string> *)(thisOwner + offset_) = *(const std::vector<std::string> *)(otherOwner + offset_); break;
|
||||
case Type::TYPE_PATH: *(Path *)(thisOwner + offset_) = *(const Path *)(otherOwner + offset_); break;
|
||||
case Type::TYPE_TOUCH_POS: *(ConfigTouchPos *)(thisOwner + offset_) = *(const ConfigTouchPos *)(otherOwner + offset_); break;
|
||||
case Type::TYPE_CUSTOM_BUTTON: *(ConfigCustomButton *)(thisOwner + offset_) = *(const ConfigCustomButton *)(otherOwner + offset_); break;
|
||||
default:
|
||||
_dbg_assert_msg_(false, "CopyFromBlock(%.*s): Unexpected setting type: %d", STR_VIEW(iniKey_), (int)type_);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void ConfigSetting::ReportSetting(const ConfigBlock *configBlock, UrlEncoder &data, const std::string &prefix) const {
|
||||
if (!Report())
|
||||
return;
|
||||
@@ -373,8 +398,8 @@ void ConfigSetting::ReportSetting(const ConfigBlock *configBlock, UrlEncoder &da
|
||||
switch (type_) {
|
||||
case Type::TYPE_BOOL: return data.Add(key, *(const bool *)(owner + offset_));
|
||||
case Type::TYPE_INT: return data.Add(key, *(const int *)(owner + offset_));
|
||||
case Type::TYPE_UINT32: return data.Add(key, *(const u32 *)(owner + offset_));
|
||||
case Type::TYPE_UINT64: return data.Add(key, *(const u64 *)(owner + offset_));
|
||||
case Type::TYPE_UINT32: return data.Add(key, *(const uint32_t *)(owner + offset_));
|
||||
case Type::TYPE_UINT64: return data.Add(key, *(const uint64_t *)(owner + offset_));
|
||||
case Type::TYPE_FLOAT: return data.Add(key, *(const float *)(owner + offset_));
|
||||
case Type::TYPE_STRING: return data.Add(key, *(const std::string *)(owner + offset_));
|
||||
case Type::TYPE_STRING_VECTOR: return data.Add(key, *(const std::vector<std::string> *)(owner + offset_));
|
||||
|
||||
@@ -73,12 +73,24 @@ struct ConfigSetting {
|
||||
default_.b = def;
|
||||
}
|
||||
|
||||
ConfigSetting(std::string_view ini, const char *owner, bool *v, CfgFlag flags) noexcept
|
||||
: iniKey_(ini), type_(Type::TYPE_BOOL), flags_(flags), offset_((const char *)v - owner) {
|
||||
defaultCallback_.b = nullptr;
|
||||
default_.b = false; // unused with this constructor
|
||||
}
|
||||
|
||||
ConfigSetting(std::string_view ini, const char *owner, int *v, int def, CfgFlag flags) noexcept
|
||||
: iniKey_(ini), type_(Type::TYPE_INT), flags_(flags), offset_((const char *)v - owner) {
|
||||
defaultCallback_.i = nullptr;
|
||||
default_.i = def;
|
||||
}
|
||||
|
||||
ConfigSetting(std::string_view ini, const char *owner, int *v, CfgFlag flags) noexcept
|
||||
: iniKey_(ini), type_(Type::TYPE_INT), flags_(flags), offset_((const char *)v - owner) {
|
||||
defaultCallback_.i = nullptr;
|
||||
default_.i = 0; // unused with this constructor
|
||||
}
|
||||
|
||||
ConfigSetting(std::string_view ini, const char *owner, int *v, int def, std::string (*transTo)(int), int (*transFrom)(const std::string &), CfgFlag flags) noexcept
|
||||
: iniKey_(ini), type_(Type::TYPE_INT), flags_(flags), translateTo_(transTo), translateFrom_(transFrom), offset_((const char *)v - owner) {
|
||||
defaultCallback_.i = nullptr;
|
||||
@@ -103,6 +115,12 @@ struct ConfigSetting {
|
||||
default_.f = def;
|
||||
}
|
||||
|
||||
ConfigSetting(std::string_view ini, const char *owner, float *v, CfgFlag flags) noexcept
|
||||
: iniKey_(ini), type_(Type::TYPE_FLOAT), flags_(flags), offset_((const char *)v - owner) {
|
||||
defaultCallback_.f = nullptr;
|
||||
default_.f = 0.0f;
|
||||
}
|
||||
|
||||
ConfigSetting(std::string_view ini, const char *owner, std::string *v, const char *def, CfgFlag flags) noexcept
|
||||
: iniKey_(ini), type_(Type::TYPE_STRING), flags_(flags), offset_((const char *)v - owner) {
|
||||
defaultCallback_.s = nullptr;
|
||||
@@ -169,6 +187,8 @@ struct ConfigSetting {
|
||||
|
||||
bool ReadFromIniSection(ConfigBlock *configBlock, const Section *section, bool applyDefaultIfMissing) const;
|
||||
|
||||
void CopyFromBlock(const ConfigBlock *other);
|
||||
|
||||
// Yes, this can be const because what's modified is not the ConfigSetting struct, but the value which is stored elsewhere.
|
||||
// Should actually be called WriteToIni or something.
|
||||
void WriteToIniSection(const ConfigBlock *configBlock, Section *section) const;
|
||||
|
||||
@@ -122,6 +122,7 @@ enum class AudioSyncMode {
|
||||
CLASSIC_PITCH = 1,
|
||||
};
|
||||
|
||||
// TODO: We can make this more fine-grained.
|
||||
enum class RestoreSettingsBits : int {
|
||||
SETTINGS = 1,
|
||||
CONTROLS = 2,
|
||||
|
||||
Reference in new issue
Block a user