diff --git a/Utilities/Config.cpp b/Utilities/Config.cpp index 77a4189440..f03d06b1d8 100644 --- a/Utilities/Config.cpp +++ b/Utilities/Config.cpp @@ -262,6 +262,22 @@ void cfg::encode(YAML::Emitter& out, const cfg::_base& rhs) out << YAML::EndMap; return; } + case type::device: + { + out << YAML::BeginMap; + for (const auto& [key, info] : static_cast(rhs).get_map()) + { + out << YAML::Key << key; + out << YAML::BeginMap; + out << YAML::Key << "Path" << YAML::Value << info.path; + out << YAML::Key << "Serial" << YAML::Value << info.serial; + out << YAML::Key << "VID" << YAML::Value << info.vid; + out << YAML::Key << "PID" << YAML::Value << info.pid; + out << YAML::EndMap; + } + out << YAML::EndMap; + return; + } default: { out << rhs.to_string(); @@ -355,6 +371,44 @@ void cfg::decode(const YAML::Node& data, cfg::_base& rhs, bool dynamic) static_cast(rhs).set_map(std::move(values)); break; } + case type::device: + { + if (!data.IsMap()) + { + return; // ??? + } + + map_of_type values; + + for (const auto& pair : data) + { + if (!pair.first.IsScalar() || !pair.second.IsMap()) continue; + + device_info info{}; + + for (const auto& key_value : pair.second) + { + if (!key_value.first.IsScalar() || !key_value.second.IsScalar()) continue; + + if (key_value.first.Scalar() == "Path") + info.path = key_value.second.Scalar(); + + if (key_value.first.Scalar() == "Serial") + info.serial = key_value.second.Scalar(); + + if (key_value.first.Scalar() == "VID") + info.vid = key_value.second.Scalar(); + + if (key_value.first.Scalar() == "PID") + info.pid = key_value.second.Scalar(); + } + + values.emplace(pair.first.Scalar(), std::move(info)); + } + + static_cast(rhs).set_map(std::move(values)); + break; + } default: { std::string value; @@ -456,3 +510,13 @@ void cfg::log_entry::from_default() { set_map({}); } + +void cfg::device_entry::set_map(map_of_type&& map) +{ + m_map = std::move(map); +} + +void cfg::device_entry::from_default() +{ + m_map = m_def; +} diff --git a/Utilities/Config.h b/Utilities/Config.h index 1ca8bbf75d..b28802964b 100644 --- a/Utilities/Config.h +++ b/Utilities/Config.h @@ -37,7 +37,8 @@ namespace cfg string, // cfg::string type set, // cfg::set_entry type map, // cfg::map_entry type - log, + log, // cfg::log_entry type + device, // cfg::device_entry type }; // Config tree entry abstract base class @@ -521,4 +522,40 @@ namespace cfg void from_default() override; }; + + struct device_info + { + std::string path; + std::string serial; + std::string vid; + std::string pid; + }; + + class device_entry final : public _base + { + map_of_type m_map{}; + map_of_type m_def{}; + + public: + device_entry(node* owner, const std::string& name, map_of_type def = {}) + : _base(type::device, owner, name, true) + , m_map(std::move(def)) + { + m_def = m_map; + } + + const map_of_type& get_map() const + { + return m_map; + } + + const map_of_type& get_default() const + { + return m_def; + } + + void set_map(map_of_type&& map); + + void from_default() override; + }; } diff --git a/rpcs3/Emu/System.cpp b/rpcs3/Emu/System.cpp index aa8e0b6f80..3867f9a2bd 100644 --- a/rpcs3/Emu/System.cpp +++ b/rpcs3/Emu/System.cpp @@ -164,15 +164,40 @@ void Emulator::Init(bool add_only) // Mount all devices const std::string emu_dir = rpcs3::utils::get_emu_dir(); const std::string elf_dir = fs::get_parent_dir(m_path); + const std::string dev_hdd0 = g_cfg_vfs.get(g_cfg_vfs.dev_hdd0, emu_dir); + const std::string dev_hdd1 = g_cfg_vfs.get(g_cfg_vfs.dev_hdd1, emu_dir); + const std::string dev_flsh = g_cfg_vfs.get_dev_flash(); + const std::string dev_flsh2 = g_cfg_vfs.get_dev_flash2(); + const std::string dev_flsh3 = g_cfg_vfs.get_dev_flash3(); - vfs::mount("/dev_hdd0", g_cfg_vfs.get(g_cfg_vfs.dev_hdd0, emu_dir)); - vfs::mount("/dev_flash", g_cfg_vfs.get_dev_flash()); - vfs::mount("/dev_flash2", g_cfg_vfs.get_dev_flash2()); - vfs::mount("/dev_flash3", g_cfg_vfs.get_dev_flash3()); - vfs::mount("/dev_usb", g_cfg_vfs.get(g_cfg_vfs.dev_usb000, emu_dir)); - vfs::mount("/dev_usb000", g_cfg_vfs.get(g_cfg_vfs.dev_usb000, emu_dir)); + vfs::mount("/dev_hdd0", dev_hdd0); + vfs::mount("/dev_flash", dev_flsh); + vfs::mount("/dev_flash2", dev_flsh2); + vfs::mount("/dev_flash3", dev_flsh3); vfs::mount("/app_home", g_cfg_vfs.app_home.to_string().empty() ? elf_dir + '/' : g_cfg_vfs.get(g_cfg_vfs.app_home, emu_dir)); + std::string dev_usb; + + for (const auto& [key, value] : g_cfg_vfs.dev_usb.get_map()) + { + const cfg::device_info usb_info = g_cfg_vfs.get_device(g_cfg_vfs.dev_usb, key, emu_dir); + + if (key.size() != 11 || !key.starts_with("/dev_usb00"sv) || key.back() < '0' || key.back() > '7') + { + sys_log.error("Trying to mount unsupported usb device: %s", key); + continue; + } + + vfs::mount(key, usb_info.path); + + if (key == "/dev_usb000"sv) + { + dev_usb = usb_info.path; + } + } + + ensure(!dev_usb.empty()); + if (!hdd1.empty()) { vfs::mount("/dev_hdd1", hdd1); @@ -229,13 +254,6 @@ void Emulator::Init(bool add_only) } // Create directories (can be disabled if necessary) - const std::string dev_hdd0 = rpcs3::utils::get_hdd0_dir(); - const std::string dev_hdd1 = g_cfg_vfs.get(g_cfg_vfs.dev_hdd1, emu_dir); - const std::string dev_usb = g_cfg_vfs.get(g_cfg_vfs.dev_usb000, emu_dir); - const std::string dev_flsh = g_cfg_vfs.get_dev_flash(); - const std::string dev_flsh2 = g_cfg_vfs.get_dev_flash2(); - const std::string dev_flsh3 = g_cfg_vfs.get_dev_flash3(); - auto make_path_verbose = [](const std::string& path) { if (!fs::create_path(path)) diff --git a/rpcs3/Emu/vfs_config.cpp b/rpcs3/Emu/vfs_config.cpp index 6a0cb00c52..54a0bf71e3 100644 --- a/rpcs3/Emu/vfs_config.cpp +++ b/rpcs3/Emu/vfs_config.cpp @@ -8,6 +8,11 @@ LOG_CHANNEL(vfs_log, "VFS"); cfg_vfs g_cfg_vfs{}; std::string cfg_vfs::get(const cfg::string& _cfg, std::string_view emu_dir) const +{ + return get(_cfg.to_string(), _cfg.def, emu_dir); +} + +std::string cfg_vfs::get(const std::string& _cfg, const std::string& def, std::string_view emu_dir) const { std::string _emu_dir; // Storage only @@ -29,12 +34,12 @@ std::string cfg_vfs::get(const cfg::string& _cfg, std::string_view emu_dir) cons emu_dir = _emu_dir; } - std::string path = _cfg.to_string(); + std::string path = _cfg; if (path.empty()) { // Fallback - path = _cfg.def; + path = def; } path = fmt::replace_all(path, "$(EmulatorDir)", emu_dir); @@ -48,6 +53,34 @@ std::string cfg_vfs::get(const cfg::string& _cfg, std::string_view emu_dir) cons return path; } +cfg::device_info cfg_vfs::get_device(const cfg::device_entry& _cfg, std::string_view key, std::string_view emu_dir) const +{ + return get_device_info(_cfg, key, emu_dir); +} + +cfg::device_info cfg_vfs::get_device_info(const cfg::device_entry& _cfg, std::string_view key, std::string_view emu_dir) const +{ + const auto& device_map = _cfg.get_map(); + + if (auto it = device_map.find(key); it != device_map.cend()) + { + // Make sure the path is properly resolved + cfg::device_info info = it->second; + const auto& def_map = _cfg.get_default(); + std::string def_path; + + if (auto def_it = def_map.find(key); def_it != def_map.cend()) + { + def_path = def_it->second.path; + } + + info.path = get(info.path, def_path, emu_dir); + return info; + } + + return {}; +} + void cfg_vfs::load() { const std::string path = cfg_vfs::get_path(); diff --git a/rpcs3/Emu/vfs_config.h b/rpcs3/Emu/vfs_config.h index f7f54b8e38..86d965e6ea 100644 --- a/rpcs3/Emu/vfs_config.h +++ b/rpcs3/Emu/vfs_config.h @@ -4,7 +4,7 @@ struct cfg_vfs : cfg::node { - std::string get(const cfg::string&, std::string_view emu_dir = {}) const; + std::string get(const cfg::string& _cfg, std::string_view emu_dir = {}) const; void load(); void save() const; static std::string get_path(); @@ -15,10 +15,14 @@ struct cfg_vfs : cfg::node cfg::string dev_flash{ this, "/dev_flash/", "$(EmulatorDir)dev_flash/" }; cfg::string dev_flash2{ this, "/dev_flash2/", "$(EmulatorDir)dev_flash2/" }; cfg::string dev_flash3{ this, "/dev_flash3/", "$(EmulatorDir)dev_flash3/" }; - cfg::string dev_usb000{ this, "/dev_usb000/", "$(EmulatorDir)dev_usb000/" }; cfg::string dev_bdvd{ this, "/dev_bdvd/" }; // Not mounted cfg::string app_home{ this, "/app_home/" }; // Not mounted + cfg::device_entry dev_usb{ this, "/dev_usb***/", + { + { "/dev_usb000", cfg::device_info{.path = "$(EmulatorDir)dev_usb000/"} } + }}; + std::string get_dev_flash() const { return get(dev_flash); @@ -33,6 +37,12 @@ struct cfg_vfs : cfg::node { return get(dev_flash3); } + + cfg::device_info get_device(const cfg::device_entry& _cfg, std::string_view key, std::string_view emu_dir = {}) const; + +private: + std::string get(const std::string& _cfg, const std::string& def, std::string_view emu_dir) const; + cfg::device_info get_device_info(const cfg::device_entry& _cfg, std::string_view key, std::string_view emu_dir = {}) const; }; extern cfg_vfs g_cfg_vfs; diff --git a/rpcs3/rpcs3qt/gui_settings.h b/rpcs3/rpcs3qt/gui_settings.h index 8edce9cdd3..f657d2f54b 100644 --- a/rpcs3/rpcs3qt/gui_settings.h +++ b/rpcs3/rpcs3qt/gui_settings.h @@ -182,7 +182,6 @@ namespace gui const gui_save fs_dev_flash_list = gui_save(fs, "dev_flash_list", QStringList()); const gui_save fs_dev_flash2_list = gui_save(fs, "dev_flash2_list", QStringList()); const gui_save fs_dev_flash3_list = gui_save(fs, "dev_flash3_list", QStringList()); - const gui_save fs_dev_usb000_list = gui_save(fs, "dev_usb000_list", QStringList()); const gui_save l_tty = gui_save(logger, "TTY", true); const gui_save l_level = gui_save(logger, "level", static_cast(logs::level::success)); diff --git a/rpcs3/rpcs3qt/vfs_dialog.cpp b/rpcs3/rpcs3qt/vfs_dialog.cpp index bf18a96277..b3b5ed5abc 100644 --- a/rpcs3/rpcs3qt/vfs_dialog.cpp +++ b/rpcs3/rpcs3qt/vfs_dialog.cpp @@ -40,16 +40,12 @@ vfs_dialog::vfs_dialog(std::shared_ptr guiSettings, std::shared_pt vfs_dialog_tab* dev_flash3_tab = new vfs_dialog_tab({ "dev_flash3", gui::fs_dev_flash3_list, &g_cfg_vfs.dev_flash3 }, m_gui_settings, this); - vfs_dialog_tab* dev_usb000_tab = new vfs_dialog_tab({ "dev_usb000", gui::fs_dev_usb000_list, &g_cfg_vfs.dev_usb000 }, - m_gui_settings, this); - tabs->addTab(emulator_tab, "$(EmulatorDir)"); tabs->addTab(dev_hdd0_tab, "dev_hdd0"); tabs->addTab(dev_hdd1_tab, "dev_hdd1"); tabs->addTab(dev_flash_tab, "dev_flash"); tabs->addTab(dev_flash2_tab, "dev_flash2"); tabs->addTab(dev_flash3_tab, "dev_flash3"); - tabs->addTab(dev_usb000_tab, "dev_usb000"); // Create buttons QDialogButtonBox* buttons = new QDialogButtonBox(QDialogButtonBox::Close | QDialogButtonBox::Save | QDialogButtonBox::RestoreDefaults);