settings: enable dynamic reload of some emu values

This commit is contained in:
Megamouse 2019-11-14 22:45:07 +01:00
parent f2b530823b
commit d91f8193b0
9 changed files with 100 additions and 63 deletions

View file

@ -17,8 +17,8 @@ namespace cfg
} }
} }
_base::_base(type _type, node* owner, const std::string& name) _base::_base(type _type, node* owner, const std::string& name, bool dynamic)
: m_type(_type) : m_type(_type), m_dynamic(dynamic)
{ {
for (const auto& pair : owner->m_nodes) for (const auto& pair : owner->m_nodes)
{ {
@ -31,7 +31,7 @@ namespace cfg
owner->m_nodes.emplace_back(name, this); owner->m_nodes.emplace_back(name, this);
} }
bool _base::from_string(const std::string&) bool _base::from_string(const std::string&, bool)
{ {
fmt::throw_exception("from_string() purecall" HERE); fmt::throw_exception("from_string() purecall" HERE);
} }
@ -46,7 +46,7 @@ namespace cfg
// Incrementally load config entries from YAML::Node. // Incrementally load config entries from YAML::Node.
// The config value is preserved if the corresponding YAML node doesn't exist. // The config value is preserved if the corresponding YAML node doesn't exist.
static void decode(const YAML::Node& data, class _base& rhs); static void decode(const YAML::Node& data, class _base& rhs, bool dynamic = false);
} }
std::vector<std::string> cfg::make_int_range(s64 min, s64 max) std::vector<std::string> cfg::make_int_range(s64 min, s64 max)
@ -212,8 +212,13 @@ void cfg::encode(YAML::Emitter& out, const cfg::_base& rhs)
} }
} }
void cfg::decode(const YAML::Node& data, cfg::_base& rhs) void cfg::decode(const YAML::Node& data, cfg::_base& rhs, bool dynamic)
{ {
if (dynamic && !rhs.get_is_dynamic())
{
return;
}
switch (rhs.get_type()) switch (rhs.get_type())
{ {
case type::node: case type::node:
@ -232,7 +237,7 @@ void cfg::decode(const YAML::Node& data, cfg::_base& rhs)
{ {
if (_pair.first == pair.first.Scalar()) if (_pair.first == pair.first.Scalar())
{ {
decode(pair.second, *_pair.second); decode(pair.second, *_pair.second, dynamic);
} }
} }
} }
@ -295,9 +300,9 @@ std::string cfg::node::to_string() const
return {out.c_str(), out.size()}; return {out.c_str(), out.size()};
} }
bool cfg::node::from_string(const std::string& value) try bool cfg::node::from_string(const std::string& value, bool dynamic) try
{ {
cfg::decode(YAML::Load(value), *this); cfg::decode(YAML::Load(value), *this, dynamic);
return true; return true;
} }
catch (const std::exception& e) catch (const std::exception& e)

View file

@ -42,11 +42,13 @@ namespace cfg
const type m_type; const type m_type;
protected: protected:
bool m_dynamic = true;
// Ownerless entry constructor // Ownerless entry constructor
_base(type _type); _base(type _type);
// Owned entry constructor // Owned entry constructor
_base(type _type, class node* owner, const std::string& name); _base(type _type, class node* owner, const std::string& name, bool dynamic = true);
public: public:
_base(const _base&) = delete; _base(const _base&) = delete;
@ -56,6 +58,9 @@ namespace cfg
// Get type // Get type
type get_type() const { return m_type; } type get_type() const { return m_type; }
// Get dynamic property for reloading configs during games
bool get_is_dynamic() const { return m_dynamic; };
// Reset defaults // Reset defaults
virtual void from_default() = 0; virtual void from_default() = 0;
@ -66,7 +71,7 @@ namespace cfg
} }
// Try to convert from string (optional) // Try to convert from string (optional)
virtual bool from_string(const std::string&); virtual bool from_string(const std::string&, bool /*dynamic*/ = false);
// Get string list (optional) // Get string list (optional)
virtual std::vector<std::string> to_list() const virtual std::vector<std::string> to_list() const
@ -93,8 +98,8 @@ namespace cfg
} }
// Registered node constructor // Registered node constructor
node(node* owner, const std::string& name) node(node* owner, const std::string& name, bool dynamic = true)
: _base(type::node, owner, name) : _base(type::node, owner, name, dynamic)
{ {
} }
@ -108,7 +113,7 @@ namespace cfg
std::string to_string() const override; std::string to_string() const override;
// Deserialize node // Deserialize node
bool from_string(const std::string& value) override; bool from_string(const std::string& value, bool dynamic = false) override;
// Set default values // Set default values
void from_default() override; void from_default() override;
@ -121,8 +126,8 @@ namespace cfg
public: public:
bool def; bool def;
_bool(node* owner, const std::string& name, bool def = false) _bool(node* owner, const std::string& name, bool def = false, bool dynamic = false)
: _base(type::_bool, owner, name) : _base(type::_bool, owner, name, dynamic)
, m_value(def) , m_value(def)
, def(def) , def(def)
{ {
@ -145,7 +150,7 @@ namespace cfg
return m_value ? "true" : "false"; return m_value ? "true" : "false";
} }
bool from_string(const std::string& value) override bool from_string(const std::string& value, bool /*dynamic*/ = false) override
{ {
if (value == "false") if (value == "false")
m_value = false; m_value = false;
@ -172,8 +177,8 @@ namespace cfg
public: public:
const T def; const T def;
_enum(node* owner, const std::string& name, T value = {}) _enum(node* owner, const std::string& name, T value = {}, bool dynamic = false)
: _base(type::_enum, owner, name) : _base(type::_enum, owner, name, dynamic)
, m_value(value) , m_value(value)
, def(value) , def(value)
{ {
@ -201,7 +206,7 @@ namespace cfg
return result; // TODO: ??? return result; // TODO: ???
} }
bool from_string(const std::string& value) override bool from_string(const std::string& value, bool /*dynamic*/ = false) override
{ {
u64 result; u64 result;
@ -239,8 +244,8 @@ namespace cfg
static const s64 max = Max; static const s64 max = Max;
static const s64 min = Min; static const s64 min = Min;
_int(node* owner, const std::string& name, int_type def = std::min<int_type>(Max, std::max<int_type>(Min, 0))) _int(node* owner, const std::string& name, int_type def = std::min<int_type>(Max, std::max<int_type>(Min, 0)), bool dynamic = false)
: _base(type::_int, owner, name) : _base(type::_int, owner, name, dynamic)
, m_value(def) , m_value(def)
, def(def) , def(def)
{ {
@ -266,7 +271,7 @@ namespace cfg
return std::to_string(m_value); return std::to_string(m_value);
} }
bool from_string(const std::string& value) override bool from_string(const std::string& value, bool /*dynamic*/ = false) override
{ {
s64 result; s64 result;
if (try_to_int64(&result, value, Min, Max)) if (try_to_int64(&result, value, Min, Max))
@ -304,8 +309,8 @@ namespace cfg
public: public:
std::string def; std::string def;
string(node* owner, const std::string& name, const std::string& def = {}) string(node* owner, const std::string& name, const std::string& def = {}, bool dynamic = false)
: _base(type::string, owner, name) : _base(type::string, owner, name, dynamic)
, m_name(name) , m_name(name)
, m_value(def) , m_value(def)
, def(def) , def(def)
@ -339,7 +344,7 @@ namespace cfg
return m_value; return m_value;
} }
bool from_string(const std::string& value) override bool from_string(const std::string& value, bool /*dynamic*/ = false) override
{ {
m_value = value; m_value = value;
return true; return true;
@ -353,8 +358,8 @@ namespace cfg
public: public:
// Default value is empty list in current implementation // Default value is empty list in current implementation
set_entry(node* owner, const std::string& name) set_entry(node* owner, const std::string& name, bool dynamic = false)
: _base(type::set, owner, name) : _base(type::set, owner, name, dynamic)
{ {
} }

View file

@ -1081,7 +1081,7 @@ bool SELFDecrypter::DecryptNPDRM(u8 *metadata, u32 metadata_size)
// If not, the data has no NPDRM layer. // If not, the data has no NPDRM layer.
if (!ctrl) if (!ctrl)
{ {
LOG_NOTICE(LOADER, "SELF: No NPDRM control info found!"); LOG_TRACE(LOADER, "SELF: No NPDRM control info found!");
return true; return true;
} }

View file

@ -331,6 +331,7 @@ void Emulator::Init()
if (const fs::file cfg_file{cfg_path, fs::read + fs::create}) if (const fs::file cfg_file{cfg_path, fs::read + fs::create})
{ {
g_cfg.from_string(cfg_file.to_string()); g_cfg.from_string(cfg_file.to_string());
g_cfg.name = cfg_path;
} }
else else
{ {
@ -1021,6 +1022,7 @@ void Emulator::Load(const std::string& title_id, bool add_only, bool force_globa
{ {
LOG_NOTICE(LOADER, "Applying custom config: %s", config_path_new); LOG_NOTICE(LOADER, "Applying custom config: %s", config_path_new);
g_cfg.from_string(cfg_file.to_string()); g_cfg.from_string(cfg_file.to_string());
g_cfg.name = config_path_new;
} }
// Load custom config-3 // Load custom config-3

View file

@ -514,23 +514,23 @@ struct cfg_root : cfg::node
{ {
node_perf_overlay(cfg::node* _this) : cfg::node(_this, "Performance Overlay") {} node_perf_overlay(cfg::node* _this) : cfg::node(_this, "Performance Overlay") {}
cfg::_bool perf_overlay_enabled{this, "Enabled", false}; cfg::_bool perf_overlay_enabled{ this, "Enabled", false, true };
cfg::_bool framerate_graph_enabled{ this, "Enable Framerate Graph", false }; cfg::_bool framerate_graph_enabled{ this, "Enable Framerate Graph", false, true };
cfg::_bool frametime_graph_enabled{ this, "Enable Frametime Graph", false }; cfg::_bool frametime_graph_enabled{ this, "Enable Frametime Graph", false, true };
cfg::_enum<detail_level> level{this, "Detail level", detail_level::medium}; cfg::_enum<detail_level> level{ this, "Detail level", detail_level::medium, true };
cfg::_int<30, 5000> update_interval{ this, "Metrics update interval (ms)", 350 }; cfg::_int<30, 5000> update_interval{ this, "Metrics update interval (ms)", 350, true };
cfg::_int<4, 36> font_size{ this, "Font size (px)", 10 }; cfg::_int<4, 36> font_size{ this, "Font size (px)", 10, true };
cfg::_enum<screen_quadrant> position{this, "Position", screen_quadrant::top_left}; cfg::_enum<screen_quadrant> position{ this, "Position", screen_quadrant::top_left, true };
cfg::string font{this, "Font", "n023055ms.ttf"}; cfg::string font{ this, "Font", "n023055ms.ttf", true };
cfg::_int<0, 1280> margin_x{this, "Horizontal Margin (px)", 50}; // horizontal distance to the screen border relative to the screen_quadrant in px cfg::_int<0, 1280> margin_x{ this, "Horizontal Margin (px)", 50, true }; // horizontal distance to the screen border relative to the screen_quadrant in px
cfg::_int<0, 720> margin_y{this, "Vertical Margin (px)", 50}; // vertical distance to the screen border relative to the screen_quadrant in px cfg::_int<0, 720> margin_y{ this, "Vertical Margin (px)", 50, true }; // vertical distance to the screen border relative to the screen_quadrant in px
cfg::_bool center_x{ this, "Center Horizontally", false }; cfg::_bool center_x{ this, "Center Horizontally", false, true };
cfg::_bool center_y{ this, "Center Vertically", false }; cfg::_bool center_y{ this, "Center Vertically", false, true };
cfg::_int<0, 100> opacity{this, "Opacity (%)", 70}; cfg::_int<0, 100> opacity{ this, "Opacity (%)", 70, true };
cfg::string color_body{ this, "Body Color (hex)", "#FFE138FF" }; cfg::string color_body{ this, "Body Color (hex)", "#FFE138FF", true };
cfg::string background_body{ this, "Body Background (hex)", "#002339FF" }; cfg::string background_body{ this, "Body Background (hex)", "#002339FF", true };
cfg::string color_title{ this, "Title Color (hex)", "#F26C24FF" }; cfg::string color_title{ this, "Title Color (hex)", "#F26C24FF", true };
cfg::string background_title{ this, "Title Background (hex)", "#00000000" }; cfg::string background_title{ this, "Title Background (hex)", "#00000000", true };
} perf_overlay{this}; } perf_overlay{this};
@ -538,8 +538,8 @@ struct cfg_root : cfg::node
{ {
node_shader_compilation_hint(cfg::node* _this) : cfg::node(_this, "Shader Compilation Hint") {} node_shader_compilation_hint(cfg::node* _this) : cfg::node(_this, "Shader Compilation Hint") {}
cfg::_int<0, 1280> pos_x{this, "Position X (px)", 20}; // horizontal position starting from the upper border in px cfg::_int<0, 1280> pos_x{ this, "Position X (px)", 20, true }; // horizontal position starting from the upper border in px
cfg::_int<0, 720> pos_y{this, "Position Y (px)", 690}; // vertical position starting from the left border in px cfg::_int<0, 720> pos_y{ this, "Position Y (px)", 690, true }; // vertical position starting from the left border in px
} shader_compilation_hint{this}; } shader_compilation_hint{this};
@ -547,9 +547,9 @@ struct cfg_root : cfg::node
{ {
node_shader_preloading_dialog(cfg::node* _this) : cfg::node(_this, "Shader Loading Dialog"){} node_shader_preloading_dialog(cfg::node* _this) : cfg::node(_this, "Shader Loading Dialog"){}
cfg::_bool use_custom_background{this, "Allow custom background", true}; cfg::_bool use_custom_background{ this, "Allow custom background", true, true };
cfg::_int<0, 100> darkening_strength{this, "Darkening effect strength", 30}; cfg::_int<0, 100> darkening_strength{ this, "Darkening effect strength", 30, true };
cfg::_int<0, 100> blur_strength{this, "Blur effect strength", 0}; cfg::_int<0, 100> blur_strength{ this, "Blur effect strength", 0, true };
} shader_preloading_dialog{this}; } shader_preloading_dialog{this};
@ -581,7 +581,6 @@ struct cfg_root : cfg::node
cfg::_enum<keyboard_handler> keyboard{this, "Keyboard", keyboard_handler::null}; cfg::_enum<keyboard_handler> keyboard{this, "Keyboard", keyboard_handler::null};
cfg::_enum<mouse_handler> mouse{this, "Mouse", mouse_handler::basic}; cfg::_enum<mouse_handler> mouse{this, "Mouse", mouse_handler::basic};
cfg::_enum<pad_handler> pad{this, "Pad", pad_handler::keyboard};
cfg::_enum<camera_handler> camera{this, "Camera", camera_handler::null}; cfg::_enum<camera_handler> camera{this, "Camera", camera_handler::null};
cfg::_enum<fake_camera_type> camera_type{this, "Camera type", fake_camera_type::unknown}; cfg::_enum<fake_camera_type> camera_type{this, "Camera type", fake_camera_type::unknown};
cfg::_enum<move_handler> move{this, "Move", move_handler::null}; cfg::_enum<move_handler> move{this, "Move", move_handler::null};
@ -610,19 +609,21 @@ struct cfg_root : cfg::node
{ {
node_misc(cfg::node* _this) : cfg::node(_this, "Miscellaneous") {} node_misc(cfg::node* _this) : cfg::node(_this, "Miscellaneous") {}
cfg::_bool autostart{this, "Automatically start games after boot", true}; cfg::_bool autostart{ this, "Automatically start games after boot", true, true };
cfg::_bool autoexit{this, "Exit RPCS3 when process finishes"}; cfg::_bool autoexit{ this, "Exit RPCS3 when process finishes", false, true };
cfg::_bool start_fullscreen{ this, "Start games in fullscreen mode" }; cfg::_bool start_fullscreen{ this, "Start games in fullscreen mode", false, true };
cfg::_bool prevent_display_sleep{ this, "Prevent display sleep while running games", true}; cfg::_bool prevent_display_sleep{ this, "Prevent display sleep while running games", true};
cfg::_bool show_fps_in_title{ this, "Show FPS counter in window title", true}; cfg::_bool show_fps_in_title{ this, "Show FPS counter in window title", true, true };
cfg::_bool show_trophy_popups{ this, "Show trophy popups", true}; cfg::_bool show_trophy_popups{ this, "Show trophy popups", true, true };
cfg::_bool show_shader_compilation_hint{ this, "Show shader compilation hint", true }; cfg::_bool show_shader_compilation_hint{ this, "Show shader compilation hint", true, true };
cfg::_bool use_native_interface{ this, "Use native user interface", true }; cfg::_bool use_native_interface{ this, "Use native user interface", true };
cfg::string gdb_server{this, "GDB Server", "127.0.0.1:2345"}; cfg::string gdb_server{this, "GDB Server", "127.0.0.1:2345"};
} misc{this}; } misc{this};
cfg::log_entry log{this, "Log"}; cfg::log_entry log{this, "Log"};
std::string name;
}; };
extern cfg_root g_cfg; extern cfg_root g_cfg;

View file

@ -296,19 +296,36 @@ void emu_settings::SaveSettings()
YAML::Emitter out; YAML::Emitter out;
emitData(out, m_currentSettings); emitData(out, m_currentSettings);
if (!m_title_id.empty()) std::string config_name;
if (m_title_id.empty())
{ {
config = fs::file(Emulator::GetCustomConfigPath(m_title_id), fs::read + fs::write + fs::create); config_name = fs::get_config_dir() + "/config.yml";
} }
else else
{ {
config = fs::file(fs::get_config_dir() + "/config.yml", fs::read + fs::write + fs::create); config_name = Emulator::GetCustomConfigPath(m_title_id);
} }
config = fs::file(config_name, fs::read + fs::write + fs::create);
// Save config // Save config
config.seek(0); config.seek(0);
config.trunc(0); config.trunc(0);
config.write(out.c_str(), out.size()); config.write(out.c_str(), out.size());
// Check if the running config/title is the same as the edited config/title.
if (config_name == g_cfg.name || m_title_id == Emu.GetTitleID())
{
// Update current config
g_cfg.from_string(config.to_string(), true);
if (!Emu.IsStopped()) // Don't spam the log while emulation is stopped. The config will be logged on boot anyway.
{
LOG_NOTICE(LOADER, "Updated configuration:\n%s\n", g_cfg.to_string());
}
}
config.close(); config.close();
} }

View file

@ -967,10 +967,14 @@ void game_list_frame::ShowContextMenu(const QPoint &pos)
connect(configure, &QAction::triggered, [=] connect(configure, &QAction::triggered, [=]
{ {
settings_dialog dlg(m_gui_settings, m_emu_settings, 0, this, &currGame); settings_dialog dlg(m_gui_settings, m_emu_settings, 0, this, &currGame);
if (dlg.exec() == QDialog::Accepted && !gameinfo->hasCustomConfig) if (dlg.exec() == QDialog::Accepted)
{ {
gameinfo->hasCustomConfig = true; if (!gameinfo->hasCustomConfig)
ShowCustomConfigIcon(item); {
gameinfo->hasCustomConfig = true;
ShowCustomConfigIcon(item);
}
Q_EMIT NotifyEmuSettingsChange();
} }
}); });
connect(pad_configure, &QAction::triggered, [=] connect(pad_configure, &QAction::triggered, [=]

View file

@ -230,6 +230,7 @@ Q_SIGNALS:
void GameListFrameClosed(); void GameListFrameClosed();
void RequestBoot(const game_info& game, bool force_global_config = false); void RequestBoot(const game_info& game, bool force_global_config = false);
void RequestIconSizeChange(const int& val); void RequestIconSizeChange(const int& val);
void NotifyEmuSettingsChange();
protected: protected:
/** Override inherited method from Qt to allow signalling when close happened.*/ /** Override inherited method from Qt to allow signalling when close happened.*/
void closeEvent(QCloseEvent* event) override; void closeEvent(QCloseEvent* event) override;

View file

@ -1593,6 +1593,8 @@ void main_window::CreateDockWindows()
{ {
Boot(game->info.path, game->info.serial, false, false, force_global_config); Boot(game->info.path, game->info.serial, false, false, force_global_config);
}); });
connect(m_gameListFrame, &game_list_frame::NotifyEmuSettingsChange, this, &main_window::NotifyEmuSettingsChange);
} }
void main_window::ConfigureGuiFromSettings(bool configure_all) void main_window::ConfigureGuiFromSettings(bool configure_all)