mirror of
https://github.com/RPCSX/rpcsx.git
synced 2025-12-06 07:12:14 +01:00
D3D12 is not in the list of supported renderes on platforms other than windows. Deleting an item, that can't be found, triggers an assert in debug builds, so let's avoid that.
635 lines
26 KiB
C++
635 lines
26 KiB
C++
#include "stdafx.h"
|
|
#include "stdafx_gui.h"
|
|
#include "Utilities/Config.h"
|
|
#include "Crypto/unself.h"
|
|
#include "Loader/ELF.h"
|
|
#include "Emu/System.h"
|
|
|
|
#ifdef _MSC_VER
|
|
#include <Windows.h>
|
|
#undef GetHwnd
|
|
#include <d3d12.h>
|
|
#include <wrl/client.h>
|
|
#include <dxgi1_4.h>
|
|
#endif
|
|
|
|
#include "SettingsDialog.h"
|
|
|
|
#include <set>
|
|
#include <unordered_set>
|
|
#include <algorithm>
|
|
|
|
// Node location
|
|
using cfg_location = std::vector<const char*>;
|
|
|
|
extern std::string g_cfg_defaults;
|
|
|
|
static YAML::Node loaded;
|
|
static YAML::Node saved;
|
|
|
|
// Emit sorted YAML
|
|
static NEVER_INLINE void emit(YAML::Emitter& out, const YAML::Node& node)
|
|
{
|
|
// TODO
|
|
out << node;
|
|
}
|
|
|
|
// Incrementally load YAML
|
|
static NEVER_INLINE void operator +=(YAML::Node& left, const YAML::Node& node)
|
|
{
|
|
if (node && !node.IsNull())
|
|
{
|
|
if (node.IsMap())
|
|
{
|
|
for (const auto& pair : node)
|
|
{
|
|
if (pair.first.IsScalar())
|
|
{
|
|
auto&& lhs = left[pair.first.Scalar()];
|
|
lhs += pair.second;
|
|
}
|
|
else
|
|
{
|
|
// Exotic case (TODO: probably doesn't work)
|
|
auto&& lhs = left[YAML::Clone(pair.first)];
|
|
lhs += pair.second;
|
|
}
|
|
}
|
|
}
|
|
else if (node.IsScalar() || node.IsSequence())
|
|
{
|
|
// Scalars and sequences are replaced completely, but this may change in future.
|
|
// This logic may be overwritten by custom demands of every specific cfg:: node.
|
|
left = node;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Connects wx gui element to the config node; abstract base class
|
|
struct cfg_adapter
|
|
{
|
|
cfg_location location;
|
|
|
|
cfg_adapter(cfg_location&& _loc)
|
|
: location(std::move(_loc))
|
|
{
|
|
}
|
|
|
|
static cfg::entry_base& get_cfg(cfg::entry_base& root, cfg_location::const_iterator begin, cfg_location::const_iterator end)
|
|
{
|
|
return begin == end ? root : get_cfg(root[*begin], begin + 1, end);
|
|
}
|
|
|
|
static YAML::Node get_node(YAML::Node node, cfg_location::const_iterator begin, cfg_location::const_iterator end)
|
|
{
|
|
return begin == end ? node : get_node(node[*begin], begin + 1, end); // TODO
|
|
}
|
|
|
|
cfg::entry_base& get_cfg() const
|
|
{
|
|
return get_cfg(cfg::root, location.cbegin(), location.cend());
|
|
}
|
|
|
|
YAML::Node get_node(YAML::Node root) const
|
|
{
|
|
return get_node(root, location.cbegin(), location.cend());
|
|
}
|
|
|
|
virtual void save() = 0;
|
|
};
|
|
|
|
struct radiobox_pad_helper
|
|
{
|
|
cfg_location location;
|
|
wxArrayString values;
|
|
|
|
radiobox_pad_helper(cfg_location&& _loc)
|
|
: location(std::move(_loc))
|
|
{
|
|
for (const auto& v : cfg_adapter::get_cfg(cfg::root, location.cbegin(), location.cend()).to_list())
|
|
{
|
|
values.Add(fmt::FromUTF8(v));
|
|
}
|
|
}
|
|
|
|
operator const wxArrayString&() const
|
|
{
|
|
return values;
|
|
}
|
|
};
|
|
|
|
struct radiobox_pad : cfg_adapter
|
|
{
|
|
wxRadioBox*& ptr;
|
|
|
|
radiobox_pad(radiobox_pad_helper&& helper, wxRadioBox*& ptr)
|
|
: cfg_adapter(std::move(helper.location))
|
|
, ptr(ptr)
|
|
{
|
|
const auto& value = get_node(loaded).Scalar();
|
|
const auto& values = get_cfg().to_list();
|
|
|
|
for (int i = 0; i < values.size(); i++)
|
|
{
|
|
if (value == values[i])
|
|
{
|
|
ptr->SetSelection(i);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
void save() override
|
|
{
|
|
get_node(saved) = get_cfg().to_list()[ptr->GetSelection()];
|
|
}
|
|
};
|
|
|
|
struct combobox_pad : cfg_adapter
|
|
{
|
|
wxComboBox*& ptr;
|
|
|
|
combobox_pad(cfg_location&& _loc, wxComboBox*& ptr)
|
|
: cfg_adapter(std::move(_loc))
|
|
, ptr(ptr)
|
|
{
|
|
for (const auto& v : get_cfg().to_list())
|
|
{
|
|
ptr->Append(fmt::FromUTF8(v));
|
|
}
|
|
|
|
ptr->SetValue(fmt::FromUTF8(get_node(loaded).Scalar()));
|
|
}
|
|
|
|
void save() override
|
|
{
|
|
get_node(saved) = fmt::ToUTF8(ptr->GetValue());
|
|
}
|
|
};
|
|
|
|
struct checkbox_pad : cfg_adapter
|
|
{
|
|
wxCheckBox*& ptr;
|
|
|
|
checkbox_pad(cfg_location&& _loc, wxCheckBox*& ptr)
|
|
: cfg_adapter(std::move(_loc))
|
|
, ptr(ptr)
|
|
{
|
|
ptr->SetValue(get_node(loaded).as<bool>(false));
|
|
}
|
|
|
|
void save() override
|
|
{
|
|
get_node(saved) = ptr->GetValue() ? "true" : "false";
|
|
}
|
|
};
|
|
|
|
struct textctrl_pad : cfg_adapter
|
|
{
|
|
wxTextCtrl*& ptr;
|
|
|
|
textctrl_pad(cfg_location&& _loc, wxTextCtrl*& ptr)
|
|
: cfg_adapter(std::move(_loc))
|
|
, ptr(ptr)
|
|
{
|
|
ptr->SetValue(fmt::FromUTF8(get_node(loaded).Scalar()));
|
|
}
|
|
|
|
void save() override
|
|
{
|
|
get_node(saved) = fmt::ToUTF8(ptr->GetValue());
|
|
}
|
|
};
|
|
|
|
|
|
SettingsDialog::SettingsDialog(wxWindow* parent, const std::string& path)
|
|
: wxDialog(parent, wxID_ANY, "Settings", wxDefaultPosition)
|
|
{
|
|
// Load default config
|
|
loaded = YAML::Load(g_cfg_defaults);
|
|
|
|
// Create config path if necessary
|
|
fs::create_path(fs::get_config_dir() + path);
|
|
|
|
// Incrementally load config.yml
|
|
const fs::file config(fs::get_config_dir() + path + "/config.yml", fs::read + fs::write + fs::create);
|
|
|
|
if (config.size() == 0 && !path.empty()) // First time
|
|
{
|
|
const fs::file configexisted(fs::get_config_dir() + "/config.yml", fs::read + fs::write + fs::create);
|
|
loaded += YAML::Load(configexisted.to_string());
|
|
}
|
|
else
|
|
{
|
|
loaded += YAML::Load(config.to_string());
|
|
}
|
|
|
|
std::vector<std::unique_ptr<cfg_adapter>> pads;
|
|
|
|
static const u32 width = 458;
|
|
static const u32 height = 400;
|
|
|
|
// Settings panels
|
|
wxNotebook* nb_config = new wxNotebook(this, wxID_ANY, wxPoint(6, 6), wxSize(width, height));
|
|
wxPanel* p_system = new wxPanel(nb_config, wxID_ANY);
|
|
wxPanel* p_core = new wxPanel(nb_config, wxID_ANY);
|
|
wxPanel* p_graphics = new wxPanel(nb_config, wxID_ANY);
|
|
wxPanel* p_audio = new wxPanel(nb_config, wxID_ANY);
|
|
wxPanel* p_io = new wxPanel(nb_config, wxID_ANY);
|
|
wxPanel* p_misc = new wxPanel(nb_config, wxID_ANY);
|
|
wxPanel* p_networking = new wxPanel(nb_config, wxID_ANY);
|
|
|
|
nb_config->AddPage(p_core, "Core");
|
|
nb_config->AddPage(p_graphics, "Graphics");
|
|
nb_config->AddPage(p_audio, "Audio");
|
|
nb_config->AddPage(p_io, "Input / Output");
|
|
nb_config->AddPage(p_misc, "Misc");
|
|
nb_config->AddPage(p_networking, "Networking");
|
|
nb_config->AddPage(p_system, "System");
|
|
|
|
wxBoxSizer* s_subpanel_core = new wxBoxSizer(wxHORIZONTAL);
|
|
wxBoxSizer* s_subpanel_core1 = new wxBoxSizer(wxVERTICAL);
|
|
wxBoxSizer* s_subpanel_core2 = new wxBoxSizer(wxVERTICAL);
|
|
wxBoxSizer* s_subpanel_graphics = new wxBoxSizer(wxHORIZONTAL);
|
|
wxBoxSizer* s_subpanel_graphics1 = new wxBoxSizer(wxVERTICAL);
|
|
wxBoxSizer* s_subpanel_graphics2 = new wxBoxSizer(wxVERTICAL);
|
|
wxBoxSizer* s_subpanel_audio = new wxBoxSizer(wxVERTICAL);
|
|
wxBoxSizer* s_subpanel_io = new wxBoxSizer(wxHORIZONTAL);
|
|
wxBoxSizer* s_subpanel_io1 = new wxBoxSizer(wxVERTICAL);
|
|
wxBoxSizer* s_subpanel_io2 = new wxBoxSizer(wxVERTICAL);
|
|
|
|
wxBoxSizer* s_subpanel_system = new wxBoxSizer(wxVERTICAL);
|
|
wxBoxSizer* s_subpanel_misc = new wxBoxSizer(wxVERTICAL);
|
|
wxBoxSizer* s_subpanel_networking = new wxBoxSizer(wxVERTICAL);
|
|
|
|
// Core
|
|
wxStaticBoxSizer* s_round_core_lle = new wxStaticBoxSizer(wxVERTICAL, p_core, "Load libraries");
|
|
chbox_list_core_lle = new wxCheckListBox(p_core, wxID_ANY, wxDefaultPosition, wxDefaultSize, {}, wxLB_EXTENDED);
|
|
chbox_list_core_lle->Bind(wxEVT_CHECKLISTBOX, &SettingsDialog::OnModuleListItemToggled, this);
|
|
wxTextCtrl* s_module_search_box = new wxTextCtrl(p_core, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, {});
|
|
s_module_search_box->Bind(wxEVT_TEXT, &SettingsDialog::OnSearchBoxTextChanged, this);
|
|
|
|
// Graphics
|
|
wxStaticBoxSizer* s_round_gs_render = new wxStaticBoxSizer(wxVERTICAL, p_graphics, "Render");
|
|
wxStaticBoxSizer* s_round_gs_d3d_adapter = new wxStaticBoxSizer(wxVERTICAL, p_graphics, "D3D Adapter");
|
|
wxStaticBoxSizer* s_round_gs_res = new wxStaticBoxSizer(wxVERTICAL, p_graphics, "Resolution");
|
|
wxStaticBoxSizer* s_round_gs_aspect = new wxStaticBoxSizer(wxVERTICAL, p_graphics, "Aspect ratio");
|
|
wxStaticBoxSizer* s_round_gs_frame_limit = new wxStaticBoxSizer(wxVERTICAL, p_graphics, "Frame limit");
|
|
|
|
// Input / Output
|
|
wxStaticBoxSizer* s_round_io_pad_handler = new wxStaticBoxSizer(wxVERTICAL, p_io, "Pad Handler");
|
|
wxStaticBoxSizer* s_round_io_keyboard_handler = new wxStaticBoxSizer(wxVERTICAL, p_io, "Keyboard Handler");
|
|
wxStaticBoxSizer* s_round_io_mouse_handler = new wxStaticBoxSizer(wxVERTICAL, p_io, "Mouse Handler");
|
|
wxStaticBoxSizer* s_round_io_camera = new wxStaticBoxSizer(wxVERTICAL, p_io, "Camera");
|
|
wxStaticBoxSizer* s_round_io_camera_type = new wxStaticBoxSizer(wxVERTICAL, p_io, "Camera type");
|
|
|
|
// Audio
|
|
wxStaticBoxSizer* s_round_audio_out = new wxStaticBoxSizer(wxVERTICAL, p_audio, "Audio Out");
|
|
|
|
// Networking
|
|
wxStaticBoxSizer* s_round_net_status = new wxStaticBoxSizer(wxVERTICAL, p_networking, "Connection status");
|
|
|
|
// System
|
|
wxStaticBoxSizer* s_round_sys_lang = new wxStaticBoxSizer(wxVERTICAL, p_system, "Language");
|
|
|
|
|
|
wxRadioBox* rbox_ppu_decoder;
|
|
wxRadioBox* rbox_spu_decoder;
|
|
wxComboBox* cbox_gs_render = new wxComboBox(p_graphics, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(150, -1), 0, NULL, wxCB_READONLY);
|
|
wxComboBox* cbox_gs_d3d_adapter = new wxComboBox(p_graphics, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(150, -1), 0, NULL, wxCB_READONLY);
|
|
wxComboBox* cbox_gs_resolution = new wxComboBox(p_graphics, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(150, -1), 0, NULL, wxCB_READONLY);
|
|
wxComboBox* cbox_gs_aspect = new wxComboBox(p_graphics, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(150, -1), 0, NULL, wxCB_READONLY);
|
|
wxComboBox* cbox_gs_frame_limit = new wxComboBox(p_graphics, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(150, -1), 0, NULL, wxCB_READONLY);
|
|
wxComboBox* cbox_pad_handler = new wxComboBox(p_io, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(150, -1), 0, NULL, wxCB_READONLY);;
|
|
wxComboBox* cbox_keyboard_handler = new wxComboBox(p_io, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(150, -1), 0, NULL, wxCB_READONLY);
|
|
wxComboBox* cbox_mouse_handler = new wxComboBox(p_io, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(150, -1), 0, NULL, wxCB_READONLY);
|
|
wxComboBox* cbox_camera = new wxComboBox(p_io, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(150, -1), 0, NULL, wxCB_READONLY);
|
|
wxComboBox* cbox_camera_type = new wxComboBox(p_io, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(150, -1), 0, NULL, wxCB_READONLY);
|
|
wxComboBox* cbox_audio_out = new wxComboBox(p_audio, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(150, -1), 0, NULL, wxCB_READONLY);
|
|
wxComboBox* cbox_net_status = new wxComboBox(p_networking, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, wxCB_READONLY);
|
|
wxComboBox* cbox_sys_lang = new wxComboBox(p_system, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, wxCB_READONLY);
|
|
|
|
wxCheckBox* chbox_core_hook_stfunc = new wxCheckBox(p_core, wxID_ANY, "Hook static functions");
|
|
wxCheckBox* chbox_core_load_liblv2 = new wxCheckBox(p_core, wxID_ANY, "Load liblv2.sprx only");
|
|
wxCheckBox* chbox_core_load_libreq = new wxCheckBox(p_core, wxID_ANY, "Load required libraries");
|
|
wxCheckBox* chbox_vfs_enable_host_root = new wxCheckBox(p_system, wxID_ANY, "Enable /host_root/");
|
|
wxCheckBox* chbox_gs_log_prog = new wxCheckBox(p_graphics, wxID_ANY, "Log Shader Programs");
|
|
wxCheckBox* chbox_gs_dump_depth = new wxCheckBox(p_graphics, wxID_ANY, "Write Depth Buffer");
|
|
wxCheckBox* chbox_gs_dump_color = new wxCheckBox(p_graphics, wxID_ANY, "Write Color Buffers");
|
|
wxCheckBox* chbox_gs_read_color = new wxCheckBox(p_graphics, wxID_ANY, "Read Color Buffers");
|
|
wxCheckBox* chbox_gs_read_depth = new wxCheckBox(p_graphics, wxID_ANY, "Read Depth Buffer");
|
|
wxCheckBox* chbox_gs_vsync = new wxCheckBox(p_graphics, wxID_ANY, "VSync");
|
|
wxCheckBox* chbox_gs_debug_output = new wxCheckBox(p_graphics, wxID_ANY, "Debug Output");
|
|
wxCheckBox* chbox_gs_overlay = new wxCheckBox(p_graphics, wxID_ANY, "Debug Overlay");
|
|
wxCheckBox* chbox_gs_gl_legacy_buffers = new wxCheckBox(p_graphics, wxID_ANY, "Use Legacy OpenGL Buffers");
|
|
wxCheckBox* chbox_gs_gpu_texture_scaling = new wxCheckBox(p_graphics, wxID_ANY, "Use GPU texture scaling");
|
|
wxCheckBox* chbox_audio_dump = new wxCheckBox(p_audio, wxID_ANY, "Dump to file");
|
|
wxCheckBox* chbox_audio_conv = new wxCheckBox(p_audio, wxID_ANY, "Convert to 16 bit");
|
|
wxCheckBox* chbox_audio_dnmx = new wxCheckBox(p_audio, wxID_ANY, "Downmix to Stereo");
|
|
wxCheckBox* chbox_hle_exitonstop = new wxCheckBox(p_misc, wxID_ANY, "Exit RPCS3 when process finishes");
|
|
wxCheckBox* chbox_hle_always_start = new wxCheckBox(p_misc, wxID_ANY, "Always start after boot");
|
|
wxCheckBox* chbox_dbg_ap_systemcall = new wxCheckBox(p_misc, wxID_ANY, "Auto Pause at System Call");
|
|
wxCheckBox* chbox_dbg_ap_functioncall = new wxCheckBox(p_misc, wxID_ANY, "Auto Pause at Function Call");
|
|
|
|
{
|
|
// Sort string vector alphabetically
|
|
static const auto sort_string_vector = [](std::vector<std::string>& vec)
|
|
{
|
|
std::sort(vec.begin(), vec.end(), [](const std::string &str1, const std::string &str2) { return str1 < str2; });
|
|
};
|
|
|
|
auto&& data = loaded["Core"]["Load libraries"].as<std::vector<std::string>, std::initializer_list<std::string>>({});
|
|
sort_string_vector(data);
|
|
|
|
// List selected modules first
|
|
for (const auto& unk : data)
|
|
{
|
|
lle_module_list.insert(lle_module_list.end(), std::pair<std::string, bool>(unk, true));
|
|
chbox_list_core_lle->Check(chbox_list_core_lle->Append(unk));
|
|
}
|
|
|
|
const std::string& lle_dir = Emu.GetLibDir(); // TODO
|
|
|
|
std::unordered_set<std::string> set(data.begin(), data.end());
|
|
std::vector<std::string> lle_module_list_unselected;
|
|
|
|
for (const auto& prxf : fs::dir(lle_dir))
|
|
{
|
|
// List found unselected modules
|
|
if (!prxf.is_directory && ppu_prx_object(decrypt_self(fs::file(lle_dir + prxf.name))) == elf_error::ok && !set.count(prxf.name))
|
|
{
|
|
lle_module_list_unselected.push_back(prxf.name);
|
|
}
|
|
}
|
|
|
|
sort_string_vector(lle_module_list_unselected);
|
|
|
|
for (const auto& prxf : lle_module_list_unselected)
|
|
{
|
|
lle_module_list.insert(lle_module_list.end(), std::pair<std::string, bool>(prxf, false));
|
|
chbox_list_core_lle->Check(chbox_list_core_lle->Append(prxf), false);
|
|
}
|
|
|
|
lle_module_list_unselected.clear();
|
|
}
|
|
|
|
radiobox_pad_helper ppu_decoder_modes({ "Core", "PPU Decoder" });
|
|
rbox_ppu_decoder = new wxRadioBox(p_core, wxID_ANY, "PPU Decoder", wxDefaultPosition, wxSize(-1, -1), ppu_decoder_modes, 1);
|
|
pads.emplace_back(std::make_unique<radiobox_pad>(std::move(ppu_decoder_modes), rbox_ppu_decoder));
|
|
rbox_ppu_decoder->Enable(0, false); // TODO
|
|
|
|
radiobox_pad_helper spu_decoder_modes({ "Core", "SPU Decoder" });
|
|
rbox_spu_decoder = new wxRadioBox(p_core, wxID_ANY, "SPU Decoder", wxDefaultPosition, wxSize(-1, -1), spu_decoder_modes, 1);
|
|
pads.emplace_back(std::make_unique<radiobox_pad>(std::move(spu_decoder_modes), rbox_spu_decoder));
|
|
rbox_spu_decoder->Enable(3, false); // TODO
|
|
|
|
pads.emplace_back(std::make_unique<checkbox_pad>(cfg_location{ "Core", "Hook static functions" }, chbox_core_hook_stfunc));
|
|
pads.emplace_back(std::make_unique<checkbox_pad>(cfg_location{ "Core", "Load liblv2.sprx only" }, chbox_core_load_liblv2));
|
|
pads.emplace_back(std::make_unique<checkbox_pad>(cfg_location{ "Core", "Load required libraries" }, chbox_core_load_libreq));
|
|
pads.emplace_back(std::make_unique<checkbox_pad>(cfg_location{ "VFS", "Enable /host_root/" }, chbox_vfs_enable_host_root));
|
|
|
|
pads.emplace_back(std::make_unique<combobox_pad>(cfg_location{ "Video", "Renderer" }, cbox_gs_render));
|
|
pads.emplace_back(std::make_unique<combobox_pad>(cfg_location{ "Video", "Resolution" }, cbox_gs_resolution));
|
|
pads.emplace_back(std::make_unique<combobox_pad>(cfg_location{ "Video", "Aspect ratio" }, cbox_gs_aspect));
|
|
pads.emplace_back(std::make_unique<combobox_pad>(cfg_location{ "Video", "Frame limit" }, cbox_gs_frame_limit));
|
|
pads.emplace_back(std::make_unique<checkbox_pad>(cfg_location{ "Video", "Log shader programs" }, chbox_gs_log_prog));
|
|
pads.emplace_back(std::make_unique<checkbox_pad>(cfg_location{ "Video", "Write Depth Buffer" }, chbox_gs_dump_depth));
|
|
pads.emplace_back(std::make_unique<checkbox_pad>(cfg_location{ "Video", "Write Color Buffers" }, chbox_gs_dump_color));
|
|
pads.emplace_back(std::make_unique<checkbox_pad>(cfg_location{ "Video", "Read Color Buffers" }, chbox_gs_read_color));
|
|
pads.emplace_back(std::make_unique<checkbox_pad>(cfg_location{ "Video", "Read Depth Buffer" }, chbox_gs_read_depth));
|
|
pads.emplace_back(std::make_unique<checkbox_pad>(cfg_location{ "Video", "VSync" }, chbox_gs_vsync));
|
|
pads.emplace_back(std::make_unique<checkbox_pad>(cfg_location{ "Video", "Debug output" }, chbox_gs_debug_output));
|
|
pads.emplace_back(std::make_unique<checkbox_pad>(cfg_location{ "Video", "Debug overlay" }, chbox_gs_overlay));
|
|
pads.emplace_back(std::make_unique<checkbox_pad>(cfg_location{ "Video", "Use Legacy OpenGL Buffers (Debug)" }, chbox_gs_gl_legacy_buffers));
|
|
pads.emplace_back(std::make_unique<checkbox_pad>(cfg_location{ "Video", "Use GPU texture scaling" }, chbox_gs_gpu_texture_scaling));
|
|
|
|
pads.emplace_back(std::make_unique<combobox_pad>(cfg_location{ "Audio", "Renderer" }, cbox_audio_out));
|
|
pads.emplace_back(std::make_unique<checkbox_pad>(cfg_location{ "Audio", "Dump to file" }, chbox_audio_dump));
|
|
pads.emplace_back(std::make_unique<checkbox_pad>(cfg_location{ "Audio", "Convert to 16 bit" }, chbox_audio_conv));
|
|
pads.emplace_back(std::make_unique<checkbox_pad>(cfg_location{ "Audio", "Downmix to Stereo" }, chbox_audio_dnmx));
|
|
|
|
pads.emplace_back(std::make_unique<combobox_pad>(cfg_location{ "Input/Output", "Pad" }, cbox_pad_handler));
|
|
pads.emplace_back(std::make_unique<combobox_pad>(cfg_location{ "Input/Output", "Keyboard" }, cbox_keyboard_handler));
|
|
pads.emplace_back(std::make_unique<combobox_pad>(cfg_location{ "Input/Output", "Mouse" }, cbox_mouse_handler));
|
|
pads.emplace_back(std::make_unique<combobox_pad>(cfg_location{ "Input/Output", "Camera" }, cbox_camera));
|
|
pads.emplace_back(std::make_unique<combobox_pad>(cfg_location{ "Input/Output", "Camera type" }, cbox_camera_type));
|
|
|
|
pads.emplace_back(std::make_unique<combobox_pad>(cfg_location{ "Net", "Connection status" }, cbox_net_status));
|
|
|
|
pads.emplace_back(std::make_unique<combobox_pad>(cfg_location{ "System", "Language" }, cbox_sys_lang));
|
|
|
|
pads.emplace_back(std::make_unique<checkbox_pad>(cfg_location{ "Miscellaneous", "Exit RPCS3 when process finishes" }, chbox_hle_exitonstop));
|
|
pads.emplace_back(std::make_unique<checkbox_pad>(cfg_location{ "Miscellaneous", "Always start after boot" }, chbox_hle_always_start));
|
|
pads.emplace_back(std::make_unique<checkbox_pad>(cfg_location{ "Miscellaneous", "Auto Pause at System Call" }, chbox_dbg_ap_systemcall));
|
|
pads.emplace_back(std::make_unique<checkbox_pad>(cfg_location{ "Miscellaneous", "Auto Pause at Function Call" }, chbox_dbg_ap_functioncall));
|
|
|
|
#ifdef _MSC_VER
|
|
Microsoft::WRL::ComPtr<IDXGIFactory4> dxgi_factory;
|
|
|
|
if (SUCCEEDED(CreateDXGIFactory(IID_PPV_ARGS(&dxgi_factory))))
|
|
{
|
|
Microsoft::WRL::ComPtr<IDXGIAdapter> adapter;
|
|
|
|
for (UINT id = 0; dxgi_factory->EnumAdapters(id, adapter.ReleaseAndGetAddressOf()) != DXGI_ERROR_NOT_FOUND; id++)
|
|
{
|
|
DXGI_ADAPTER_DESC desc;
|
|
adapter->GetDesc(&desc);
|
|
cbox_gs_d3d_adapter->Append(desc.Description);
|
|
}
|
|
|
|
pads.emplace_back(std::make_unique<combobox_pad>(cfg_location{ "Video", "D3D12", "Adapter" }, cbox_gs_d3d_adapter));
|
|
}
|
|
else
|
|
{
|
|
// Removes D3D12 from Render list when the system doesn't support it
|
|
cbox_gs_render->Delete(cbox_gs_render->FindString("D3D12"));
|
|
cbox_gs_d3d_adapter->Enable(false);
|
|
}
|
|
#else
|
|
cbox_gs_d3d_adapter->Enable(false);
|
|
#endif
|
|
|
|
// Core
|
|
s_round_core_lle->Add(chbox_list_core_lle, wxSizerFlags().Border(wxALL, 5).Expand());
|
|
s_round_core_lle->Add(s_module_search_box, wxSizerFlags().Border(wxALL, 5).Expand());
|
|
|
|
// Rendering
|
|
s_round_gs_render->Add(cbox_gs_render, wxSizerFlags().Border(wxALL, 5).Expand());
|
|
s_round_gs_d3d_adapter->Add(cbox_gs_d3d_adapter, wxSizerFlags().Border(wxALL, 5).Expand());
|
|
s_round_gs_res->Add(cbox_gs_resolution, wxSizerFlags().Border(wxALL, 5).Expand());
|
|
s_round_gs_aspect->Add(cbox_gs_aspect, wxSizerFlags().Border(wxALL, 5).Expand());
|
|
s_round_gs_frame_limit->Add(cbox_gs_frame_limit, wxSizerFlags().Border(wxALL, 5).Expand());
|
|
|
|
// Input/Output
|
|
s_round_io_pad_handler->Add(cbox_pad_handler, wxSizerFlags().Border(wxALL, 5).Expand());
|
|
s_round_io_keyboard_handler->Add(cbox_keyboard_handler, wxSizerFlags().Border(wxALL, 5).Expand());
|
|
s_round_io_mouse_handler->Add(cbox_mouse_handler, wxSizerFlags().Border(wxALL, 5).Expand());
|
|
s_round_io_camera->Add(cbox_camera, wxSizerFlags().Border(wxALL, 5).Expand());
|
|
s_round_io_camera_type->Add(cbox_camera_type, wxSizerFlags().Border(wxALL, 5).Expand());
|
|
|
|
s_round_audio_out->Add(cbox_audio_out, wxSizerFlags().Border(wxALL, 5).Expand());
|
|
|
|
// Networking
|
|
s_round_net_status->Add(cbox_net_status, wxSizerFlags().Border(wxALL, 5).Expand());
|
|
|
|
// System
|
|
s_round_sys_lang->Add(cbox_sys_lang, wxSizerFlags().Border(wxALL, 5).Expand());
|
|
|
|
// Core
|
|
s_subpanel_core1->Add(rbox_ppu_decoder, wxSizerFlags().Border(wxALL, 5).Expand());
|
|
s_subpanel_core1->Add(rbox_spu_decoder, wxSizerFlags().Border(wxALL, 5).Expand());
|
|
s_subpanel_core1->Add(chbox_core_hook_stfunc, wxSizerFlags().Border(wxALL, 5).Expand());
|
|
s_subpanel_core1->Add(chbox_core_load_liblv2, wxSizerFlags().Border(wxALL, 5).Expand());
|
|
s_subpanel_core1->Add(chbox_core_load_libreq, wxSizerFlags().Border(wxALL, 5).Expand());
|
|
s_subpanel_core2->Add(s_round_core_lle, wxSizerFlags().Border(wxALL, 5).Expand());
|
|
s_subpanel_core->Add(s_subpanel_core1);
|
|
s_subpanel_core->Add(s_subpanel_core2);
|
|
|
|
// Graphics
|
|
s_subpanel_graphics1->Add(s_round_gs_render, wxSizerFlags().Border(wxALL, 5).Expand());
|
|
s_subpanel_graphics1->Add(s_round_gs_res, wxSizerFlags().Border(wxALL, 5).Expand());
|
|
s_subpanel_graphics1->Add(s_round_gs_d3d_adapter, wxSizerFlags().Border(wxALL, 5).Expand());
|
|
s_subpanel_graphics1->Add(chbox_gs_dump_color, wxSizerFlags().Border(wxALL, 5).Expand());
|
|
s_subpanel_graphics1->Add(chbox_gs_read_color, wxSizerFlags().Border(wxALL, 5).Expand());
|
|
s_subpanel_graphics1->Add(chbox_gs_dump_depth, wxSizerFlags().Border(wxALL, 5).Expand());
|
|
s_subpanel_graphics1->Add(chbox_gs_read_depth, wxSizerFlags().Border(wxALL, 5).Expand());
|
|
s_subpanel_graphics1->Add(chbox_gs_gl_legacy_buffers, wxSizerFlags().Border(wxALL, 5).Expand());
|
|
s_subpanel_graphics2->Add(s_round_gs_aspect, wxSizerFlags().Border(wxALL, 5).Expand());
|
|
s_subpanel_graphics2->Add(s_round_gs_frame_limit, wxSizerFlags().Border(wxALL, 5).Expand());
|
|
s_subpanel_graphics2->AddSpacer(68);
|
|
s_subpanel_graphics2->Add(chbox_gs_debug_output, wxSizerFlags().Border(wxALL, 5).Expand());
|
|
s_subpanel_graphics2->Add(chbox_gs_overlay, wxSizerFlags().Border(wxALL, 5).Expand());
|
|
s_subpanel_graphics2->Add(chbox_gs_log_prog, wxSizerFlags().Border(wxALL, 5).Expand());
|
|
s_subpanel_graphics2->Add(chbox_gs_vsync, wxSizerFlags().Border(wxALL, 5).Expand());
|
|
s_subpanel_graphics2->Add(chbox_gs_gpu_texture_scaling, wxSizerFlags().Border(wxALL, 5).Expand());
|
|
s_subpanel_graphics->Add(s_subpanel_graphics1);
|
|
s_subpanel_graphics->Add(s_subpanel_graphics2);
|
|
|
|
// Input - Output
|
|
s_subpanel_io1->Add(s_round_io_pad_handler, wxSizerFlags().Border(wxALL, 5).Expand());
|
|
s_subpanel_io1->Add(s_round_io_keyboard_handler, wxSizerFlags().Border(wxALL, 5).Expand());
|
|
s_subpanel_io1->Add(s_round_io_mouse_handler, wxSizerFlags().Border(wxALL, 5).Expand());
|
|
s_subpanel_io2->Add(s_round_io_camera, wxSizerFlags().Border(wxALL, 5).Expand());
|
|
s_subpanel_io2->Add(s_round_io_camera_type, wxSizerFlags().Border(wxALL, 5).Expand());
|
|
s_subpanel_io->Add(s_subpanel_io1);
|
|
s_subpanel_io->Add(s_subpanel_io2);
|
|
|
|
// Audio
|
|
s_subpanel_audio->Add(s_round_audio_out, wxSizerFlags().Border(wxALL, 5).Expand());
|
|
s_subpanel_audio->Add(chbox_audio_dump, wxSizerFlags().Border(wxALL, 5).Expand());
|
|
s_subpanel_audio->Add(chbox_audio_conv, wxSizerFlags().Border(wxALL, 5).Expand());
|
|
s_subpanel_audio->Add(chbox_audio_dnmx, wxSizerFlags().Border(wxALL, 5).Expand());
|
|
|
|
// Miscellaneous
|
|
s_subpanel_misc->Add(chbox_hle_exitonstop, wxSizerFlags().Border(wxALL, 5).Expand());
|
|
s_subpanel_misc->Add(chbox_hle_always_start, wxSizerFlags().Border(wxALL, 5).Expand());
|
|
|
|
// Auto Pause
|
|
s_subpanel_misc->Add(chbox_dbg_ap_systemcall, wxSizerFlags().Border(wxALL, 5).Expand());
|
|
s_subpanel_misc->Add(chbox_dbg_ap_functioncall, wxSizerFlags().Border(wxALL, 5).Expand());
|
|
|
|
// Networking
|
|
s_subpanel_networking->Add(s_round_net_status, wxSizerFlags().Border(wxALL, 5).Expand());
|
|
|
|
// System
|
|
s_subpanel_system->Add(chbox_vfs_enable_host_root, wxSizerFlags().Border(wxALL, 5).Expand());
|
|
s_subpanel_system->Add(s_round_sys_lang, wxSizerFlags().Border(wxALL, 5).Expand());
|
|
|
|
// Buttons
|
|
wxBoxSizer* s_b_panel(new wxBoxSizer(wxHORIZONTAL));
|
|
s_b_panel->Add(new wxButton(this, wxID_OK), wxSizerFlags().Border(wxALL, 5).Bottom());
|
|
s_b_panel->Add(new wxButton(this, wxID_CANCEL), wxSizerFlags().Border(wxALL, 5).Bottom());
|
|
|
|
// Resize panels
|
|
SetSizerAndFit(s_subpanel_core, false);
|
|
SetSizerAndFit(s_subpanel_graphics, false);
|
|
SetSizerAndFit(s_subpanel_io, false);
|
|
SetSizerAndFit(s_subpanel_audio, false);
|
|
SetSizerAndFit(s_subpanel_misc, false);
|
|
SetSizerAndFit(s_subpanel_networking, false);
|
|
SetSizerAndFit(s_subpanel_system, false);
|
|
SetSizerAndFit(s_b_panel, false);
|
|
|
|
SetSize(width + 26, height + 80);
|
|
|
|
if (ShowModal() == wxID_OK)
|
|
{
|
|
std::set<std::string> lle_selected;
|
|
|
|
for (auto& i : lle_module_list)
|
|
{
|
|
if (i.second) // selected
|
|
{
|
|
lle_selected.emplace(i.first);
|
|
}
|
|
}
|
|
|
|
saved.reset();
|
|
saved["Core"]["Load libraries"] = std::vector<std::string>(lle_selected.begin(), lle_selected.end());
|
|
|
|
for (auto& pad : pads)
|
|
{
|
|
pad->save();
|
|
}
|
|
|
|
loaded += saved;
|
|
YAML::Emitter out;
|
|
emit(out, loaded);
|
|
|
|
// Save config
|
|
config.seek(0);
|
|
config.trunc(0);
|
|
config.write(out.c_str(), out.size());
|
|
}
|
|
}
|
|
|
|
void SettingsDialog::OnModuleListItemToggled(wxCommandEvent &event)
|
|
{
|
|
lle_module_list[fmt::ToUTF8(event.GetString())] = chbox_list_core_lle->IsChecked(event.GetSelection());
|
|
}
|
|
|
|
void SettingsDialog::OnSearchBoxTextChanged(wxCommandEvent &event)
|
|
{
|
|
// helper to preserve alphabetically order while inserting items
|
|
int item_index = 0;
|
|
|
|
if (event.GetString().IsEmpty())
|
|
{
|
|
for (auto& i : lle_module_list)
|
|
{
|
|
if (i.second)
|
|
{
|
|
chbox_list_core_lle->Check(chbox_list_core_lle->Insert(i.first, item_index));
|
|
item_index++;
|
|
}
|
|
|
|
else
|
|
{
|
|
chbox_list_core_lle->Check(chbox_list_core_lle->Insert(i.first, chbox_list_core_lle->GetCount()), false);
|
|
}
|
|
}
|
|
}
|
|
|
|
chbox_list_core_lle->Clear();
|
|
|
|
wxString search_term = event.GetString().Lower();
|
|
item_index = 0;
|
|
|
|
for (auto& i : lle_module_list)
|
|
{
|
|
if (fmt::FromUTF8(i.first).Find(search_term) != wxString::npos)
|
|
{
|
|
if (i.second)
|
|
{
|
|
chbox_list_core_lle->Check(chbox_list_core_lle->Insert(i.first, item_index));
|
|
item_index++;
|
|
}
|
|
|
|
else
|
|
{
|
|
chbox_list_core_lle->Check(chbox_list_core_lle->Insert(i.first, chbox_list_core_lle->GetCount()), false);
|
|
}
|
|
}
|
|
}
|
|
}
|