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)
: m_type(_type)
_base::_base(type _type, node* owner, const std::string& name, bool dynamic)
: m_type(_type), m_dynamic(dynamic)
{
for (const auto& pair : owner->m_nodes)
{
@ -31,7 +31,7 @@ namespace cfg
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);
}
@ -46,7 +46,7 @@ namespace cfg
// Incrementally load config entries from YAML::Node.
// 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)
@ -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())
{
case type::node:
@ -232,7 +237,7 @@ void cfg::decode(const YAML::Node& data, cfg::_base& rhs)
{
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()};
}
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;
}
catch (const std::exception& e)

View file

@ -42,11 +42,13 @@ namespace cfg
const type m_type;
protected:
bool m_dynamic = true;
// Ownerless entry constructor
_base(type _type);
// 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:
_base(const _base&) = delete;
@ -56,6 +58,9 @@ namespace cfg
// Get 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
virtual void from_default() = 0;
@ -66,7 +71,7 @@ namespace cfg
}
// 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)
virtual std::vector<std::string> to_list() const
@ -93,8 +98,8 @@ namespace cfg
}
// Registered node constructor
node(node* owner, const std::string& name)
: _base(type::node, owner, name)
node(node* owner, const std::string& name, bool dynamic = true)
: _base(type::node, owner, name, dynamic)
{
}
@ -108,7 +113,7 @@ namespace cfg
std::string to_string() const override;
// Deserialize node
bool from_string(const std::string& value) override;
bool from_string(const std::string& value, bool dynamic = false) override;
// Set default values
void from_default() override;
@ -121,8 +126,8 @@ namespace cfg
public:
bool def;
_bool(node* owner, const std::string& name, bool def = false)
: _base(type::_bool, owner, name)
_bool(node* owner, const std::string& name, bool def = false, bool dynamic = false)
: _base(type::_bool, owner, name, dynamic)
, m_value(def)
, def(def)
{
@ -145,7 +150,7 @@ namespace cfg
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")
m_value = false;
@ -172,8 +177,8 @@ namespace cfg
public:
const T def;
_enum(node* owner, const std::string& name, T value = {})
: _base(type::_enum, owner, name)
_enum(node* owner, const std::string& name, T value = {}, bool dynamic = false)
: _base(type::_enum, owner, name, dynamic)
, m_value(value)
, def(value)
{
@ -201,7 +206,7 @@ namespace cfg
return result; // TODO: ???
}
bool from_string(const std::string& value) override
bool from_string(const std::string& value, bool /*dynamic*/ = false) override
{
u64 result;
@ -239,8 +244,8 @@ namespace cfg
static const s64 max = Max;
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)))
: _base(type::_int, owner, name)
_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, dynamic)
, m_value(def)
, def(def)
{
@ -266,7 +271,7 @@ namespace cfg
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;
if (try_to_int64(&result, value, Min, Max))
@ -304,8 +309,8 @@ namespace cfg
public:
std::string def;
string(node* owner, const std::string& name, const std::string& def = {})
: _base(type::string, owner, name)
string(node* owner, const std::string& name, const std::string& def = {}, bool dynamic = false)
: _base(type::string, owner, name, dynamic)
, m_name(name)
, m_value(def)
, def(def)
@ -339,7 +344,7 @@ namespace cfg
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;
return true;
@ -353,8 +358,8 @@ namespace cfg
public:
// Default value is empty list in current implementation
set_entry(node* owner, const std::string& name)
: _base(type::set, owner, name)
set_entry(node* owner, const std::string& name, bool dynamic = false)
: _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 (!ctrl)
{
LOG_NOTICE(LOADER, "SELF: No NPDRM control info found!");
LOG_TRACE(LOADER, "SELF: No NPDRM control info found!");
return true;
}

View file

@ -331,6 +331,7 @@ void Emulator::Init()
if (const fs::file cfg_file{cfg_path, fs::read + fs::create})
{
g_cfg.from_string(cfg_file.to_string());
g_cfg.name = cfg_path;
}
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);
g_cfg.from_string(cfg_file.to_string());
g_cfg.name = config_path_new;
}
// 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") {}
cfg::_bool perf_overlay_enabled{this, "Enabled", false};
cfg::_bool framerate_graph_enabled{ this, "Enable Framerate Graph", false };
cfg::_bool frametime_graph_enabled{ this, "Enable Frametime Graph", false };
cfg::_enum<detail_level> level{this, "Detail level", detail_level::medium};
cfg::_int<30, 5000> update_interval{ this, "Metrics update interval (ms)", 350 };
cfg::_int<4, 36> font_size{ this, "Font size (px)", 10 };
cfg::_enum<screen_quadrant> position{this, "Position", screen_quadrant::top_left};
cfg::string font{this, "Font", "n023055ms.ttf"};
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, 720> margin_y{this, "Vertical Margin (px)", 50}; // vertical distance to the screen border relative to the screen_quadrant in px
cfg::_bool center_x{ this, "Center Horizontally", false };
cfg::_bool center_y{ this, "Center Vertically", false };
cfg::_int<0, 100> opacity{this, "Opacity (%)", 70};
cfg::string color_body{ this, "Body Color (hex)", "#FFE138FF" };
cfg::string background_body{ this, "Body Background (hex)", "#002339FF" };
cfg::string color_title{ this, "Title Color (hex)", "#F26C24FF" };
cfg::string background_title{ this, "Title Background (hex)", "#00000000" };
cfg::_bool perf_overlay_enabled{ this, "Enabled", false, true };
cfg::_bool framerate_graph_enabled{ this, "Enable Framerate Graph", false, true };
cfg::_bool frametime_graph_enabled{ this, "Enable Frametime Graph", false, true };
cfg::_enum<detail_level> level{ this, "Detail level", detail_level::medium, true };
cfg::_int<30, 5000> update_interval{ this, "Metrics update interval (ms)", 350, true };
cfg::_int<4, 36> font_size{ this, "Font size (px)", 10, true };
cfg::_enum<screen_quadrant> position{ this, "Position", screen_quadrant::top_left, true };
cfg::string font{ this, "Font", "n023055ms.ttf", true };
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, true }; // vertical distance to the screen border relative to the screen_quadrant in px
cfg::_bool center_x{ this, "Center Horizontally", false, true };
cfg::_bool center_y{ this, "Center Vertically", false, true };
cfg::_int<0, 100> opacity{ this, "Opacity (%)", 70, true };
cfg::string color_body{ this, "Body Color (hex)", "#FFE138FF", true };
cfg::string background_body{ this, "Body Background (hex)", "#002339FF", true };
cfg::string color_title{ this, "Title Color (hex)", "#F26C24FF", true };
cfg::string background_title{ this, "Title Background (hex)", "#00000000", true };
} 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") {}
cfg::_int<0, 1280> pos_x{this, "Position X (px)", 20}; // 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, 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, true }; // vertical position starting from the left border in px
} 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"){}
cfg::_bool use_custom_background{this, "Allow custom background", true};
cfg::_int<0, 100> darkening_strength{this, "Darkening effect strength", 30};
cfg::_int<0, 100> blur_strength{this, "Blur effect strength", 0};
cfg::_bool use_custom_background{ this, "Allow custom background", true, true };
cfg::_int<0, 100> darkening_strength{ this, "Darkening effect strength", 30, true };
cfg::_int<0, 100> blur_strength{ this, "Blur effect strength", 0, true };
} 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<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<fake_camera_type> camera_type{this, "Camera type", fake_camera_type::unknown};
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") {}
cfg::_bool autostart{this, "Automatically start games after boot", true};
cfg::_bool autoexit{this, "Exit RPCS3 when process finishes"};
cfg::_bool start_fullscreen{ this, "Start games in fullscreen mode" };
cfg::_bool autostart{ this, "Automatically start games after boot", true, true };
cfg::_bool autoexit{ this, "Exit RPCS3 when process finishes", false, true };
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 show_fps_in_title{ this, "Show FPS counter in window title", true};
cfg::_bool show_trophy_popups{ this, "Show trophy popups", true};
cfg::_bool show_shader_compilation_hint{ this, "Show shader compilation hint", 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, 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::string gdb_server{this, "GDB Server", "127.0.0.1:2345"};
} misc{this};
cfg::log_entry log{this, "Log"};
std::string name;
};
extern cfg_root g_cfg;

View file

@ -296,19 +296,36 @@ void emu_settings::SaveSettings()
YAML::Emitter out;
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
{
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
config.seek(0);
config.trunc(0);
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();
}

View file

@ -967,10 +967,14 @@ void game_list_frame::ShowContextMenu(const QPoint &pos)
connect(configure, &QAction::triggered, [=]
{
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;
ShowCustomConfigIcon(item);
if (!gameinfo->hasCustomConfig)
{
gameinfo->hasCustomConfig = true;
ShowCustomConfigIcon(item);
}
Q_EMIT NotifyEmuSettingsChange();
}
});
connect(pad_configure, &QAction::triggered, [=]

View file

@ -230,6 +230,7 @@ Q_SIGNALS:
void GameListFrameClosed();
void RequestBoot(const game_info& game, bool force_global_config = false);
void RequestIconSizeChange(const int& val);
void NotifyEmuSettingsChange();
protected:
/** Override inherited method from Qt to allow signalling when close happened.*/
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);
});
connect(m_gameListFrame, &game_list_frame::NotifyEmuSettingsChange, this, &main_window::NotifyEmuSettingsChange);
}
void main_window::ConfigureGuiFromSettings(bool configure_all)