[Config] Gracefully handle type mismatches in cvars.

Detect cvar type mismatch and reset to default value, as well
as show message to the user that the cvar from the config has
been updated.
This commit is contained in:
Herman S.
2025-11-06 09:42:28 +09:00
committed by Radosław Gliński
parent 70e44ab6ec
commit 93adb2bb95
3 changed files with 45 additions and 2 deletions

View File

@@ -30,6 +30,7 @@ cxxopts::Options options("xenia", "Xbox 360 Emulator");
std::map<std::string, ICommandVar*>* CmdVars;
std::map<std::string, IConfigVar*>* ConfigVars;
std::multimap<uint32_t, const IConfigVarUpdate*>* IConfigVarUpdate::updates_;
std::vector<std::string>* config_type_mismatch_warnings = nullptr;
void PrintHelpAndExit() {
std::cout << options.help({""}) << std::endl;

View File

@@ -33,6 +33,9 @@ namespace toml_internal {
std::string EscapeString(const std::string_view str);
}
// Track config values that had type mismatches during loading
extern std::vector<std::string>* config_type_mismatch_warnings;
class ICommandVar {
public:
virtual ~ICommandVar() = default;
@@ -147,7 +150,16 @@ inline void CommandVar<std::filesystem::path>::LoadFromLaunchOptions(
}
template <class T>
void ConfigVar<T>::LoadConfigValue(const toml::node* result) {
SetConfigValue(result->value<T>().value());
auto value_opt = result->value<T>();
if (value_opt) {
SetConfigValue(value_opt.value());
} else {
// Type mismatch - track for warning
if (!config_type_mismatch_warnings) {
config_type_mismatch_warnings = new std::vector<std::string>();
}
config_type_mismatch_warnings->push_back(this->name_);
}
}
template <>
inline void ConfigVar<std::filesystem::path>::LoadConfigValue(
@@ -157,7 +169,16 @@ inline void ConfigVar<std::filesystem::path>::LoadConfigValue(
}
template <class T>
void ConfigVar<T>::LoadGameConfigValue(const toml::node* result) {
SetGameConfigValue(result->value<T>().value());
auto value_opt = result->value<T>();
if (value_opt) {
SetGameConfigValue(value_opt.value());
} else {
// Type mismatch - track for warning
if (!config_type_mismatch_warnings) {
config_type_mismatch_warnings = new std::vector<std::string>();
}
config_type_mismatch_warnings->push_back(this->name_);
}
}
template <>
inline void ConfigVar<std::filesystem::path>::LoadGameConfigValue(

View File

@@ -16,6 +16,7 @@
#include "xenia/base/logging.h"
#include "xenia/base/string.h"
#include "xenia/base/string_buffer.h"
#include "xenia/base/system.h"
toml::parse_result ParseFile(const std::filesystem::path& filename) {
return toml::parse_file(xe::path_to_utf8(filename));
@@ -118,6 +119,26 @@ void ReadConfig(const std::filesystem::path& file_path,
cvar::IConfigVarUpdate::ApplyUpdates(config_defaults_date);
}
// Check for type mismatch warnings
if (cvar::config_type_mismatch_warnings &&
!cvar::config_type_mismatch_warnings->empty()) {
std::string warning_message =
"The following config values had invalid types and have been reset to "
"defaults:\n\n";
for (const auto& name : *cvar::config_type_mismatch_warnings) {
warning_message += " - " + name + "\n";
}
warning_message +=
"\nPlease check your config file. The config will be saved with the "
"correct types.";
xe::ShowSimpleMessageBox(xe::SimpleMessageBoxType::Warning,
warning_message);
// Clear warnings
cvar::config_type_mismatch_warnings->clear();
}
XELOGI("Loaded config: {}", file_path);
}