diff --git a/rpcs3/Json/tooltips.json b/rpcs3/Json/tooltips.json index 5819d2fbb6..62a0135fe2 100644 --- a/rpcs3/Json/tooltips.json +++ b/rpcs3/Json/tooltips.json @@ -1,5 +1,12 @@ { "advanced": { + "libraries": { + "manual": "Allows the user to manually choose the LLE libraries to load.\nIf unsure, don't use this option. Nothing will work if you use this.", + "both": "Load libsysmodule.sprx and chosen list of libraries. Option for backward compatibility.\nIf unsure, don't use this option.", + "liblv2both": "Loads liblv2.sprx and chosen list of libraries.\nIf unsure, don't use this option.", + "liblv2list": "Loads liblv2.sprx and nothing but selected libraries.\nDon't use this option.", + "liblv2": "This closely emulates how games can load and unload system module files on a real PlayStation 3.\nSome games require this.\nThis is the preferred option." + }, "debugConsoleMode": "Increases the amount of usable system memory to match a DECR console and more.\nCauses some software to behave differently than on retail hardware.", "readColor": "Initializes render target memory using vm memory.", "readDepth": "Initializes render target memory using vm memory.", @@ -36,13 +43,6 @@ "ASMJIT": "This is the fast option with very good compatibility.\nIf unsure, use this option.", "LLVM": "This is the fastest option with very good compatibility.\nRecompiles the game's SPU LLVM cache before running which adds extra start-up time.\nIf you experience issues, use the ASMJIT Recompiler." }, - "libraries": { - "manual": "Allows the user to manually choose the LLE libraries to load.\nIf unsure, don't use this option. Nothing will work if you use this.", - "both": "Load libsysmodule.sprx and chosen list of libraries. Option for backward compatibility.\nIf unsure, don't use this option.", - "liblv2both": "Loads liblv2.sprx and chosen list of libraries.\nIf unsure, don't use this option.", - "liblv2list": "Loads liblv2.sprx and nothing but selected libraries.\nDon't use this option.", - "liblv2": "This closely emulates how games can load and unload system module files on a real PlayStation 3.\nSome games require this.\nThis is the preferred option." - }, "checkboxes": { "accurateXFloat": "Fixes bugs in various games at the cost of performance.\nThis setting is only applied when SPU LLVM is active.", "spuCache": "Should normally stay enabled.\nDisable this if the cache becomes too large.\nDisabling it does not remove the existing cache.", diff --git a/rpcs3/rpcs3qt/settings_dialog.cpp b/rpcs3/rpcs3qt/settings_dialog.cpp index 269c5ff834..0573454138 100644 --- a/rpcs3/rpcs3qt/settings_dialog.cpp +++ b/rpcs3/rpcs3qt/settings_dialog.cpp @@ -80,7 +80,6 @@ settings_dialog::settings_dialog(std::shared_ptr guiSettings, std: QJsonObject json_cpu_spu = json_cpu.value("SPU").toObject(); QJsonObject json_cpu_cbs = json_cpu.value("checkboxes").toObject(); QJsonObject json_cpu_cbo = json_cpu.value("comboboxes").toObject(); - QJsonObject json_cpu_lib = json_cpu.value("libraries").toObject(); QJsonObject json_gpu = json_obj.value("gpu").toObject(); QJsonObject json_gpu_cbo = json_gpu.value("comboboxes").toObject(); @@ -92,7 +91,8 @@ settings_dialog::settings_dialog(std::shared_ptr guiSettings, std: QJsonObject json_sys = json_obj.value("system").toObject(); QJsonObject json_net = json_obj.value("network").toObject(); - QJsonObject json_advanced = json_obj.value("advanced").toObject(); + QJsonObject json_advanced = json_obj.value("advanced").toObject(); + QJsonObject json_advanced_libs = json_advanced.value("libraries").toObject(); QJsonObject json_emu = json_obj.value("emulator").toObject(); QJsonObject json_emu_misc = json_emu.value("misc").toObject(); @@ -309,151 +309,6 @@ settings_dialog::settings_dialog(std::shared_ptr guiSettings, std: ui->spu_llvm->setEnabled(false); #endif - // lib options tool tips - SubscribeTooltip(ui->lib_manu, json_cpu_lib["manual"].toString()); - SubscribeTooltip(ui->lib_both, json_cpu_lib["both"].toString()); - SubscribeTooltip(ui->lib_lv2, json_cpu_lib["liblv2"].toString()); - SubscribeTooltip(ui->lib_lv2b, json_cpu_lib["liblv2both"].toString()); - SubscribeTooltip(ui->lib_lv2l, json_cpu_lib["liblv2list"].toString()); - - // creating this in ui file keeps scrambling the order... - QButtonGroup *libModeBG = new QButtonGroup(this); - libModeBG->addButton(ui->lib_manu, static_cast(lib_loading_type::manual)); - libModeBG->addButton(ui->lib_both, static_cast(lib_loading_type::hybrid)); - libModeBG->addButton(ui->lib_lv2, static_cast(lib_loading_type::liblv2only)); - libModeBG->addButton(ui->lib_lv2b, static_cast(lib_loading_type::liblv2both)); - libModeBG->addButton(ui->lib_lv2l, static_cast(lib_loading_type::liblv2list)); - - {// Handle lib loading options - QString selectedLib = qstr(xemu_settings->GetSetting(emu_settings::LibLoadOptions)); - QStringList libmode_list = xemu_settings->GetSettingOptions(emu_settings::LibLoadOptions); - - for (int i = 0; i < libmode_list.count(); i++) - { - libModeBG->button(i)->setText(libmode_list[i]); - - if (libmode_list[i] == selectedLib) - { - libModeBG->button(i)->setChecked(true); - } - - connect(libModeBG->button(i), &QAbstractButton::clicked, [=]() - { - xemu_settings->SetSetting(emu_settings::LibLoadOptions, sstr(libmode_list[i])); - }); - } - } - - // Sort string vector alphabetically - static const auto sort_string_vector = [](std::vector& vec) - { - std::sort(vec.begin(), vec.end(), [](const std::string &str1, const std::string &str2) { return str1 < str2; }); - }; - - std::vector loadedLibs = xemu_settings->GetLoadedLibraries(); - - sort_string_vector(loadedLibs); - - for (const auto& lib : loadedLibs) - { - QListWidgetItem* item = new QListWidgetItem(qstr(lib), ui->lleList); - item->setFlags(item->flags() | Qt::ItemIsUserCheckable); // set checkable flag - item->setCheckState(Qt::Checked); // AND initialize check state - ui->lleList->addItem(item); - } - - const std::string lle_dir = g_cfg.vfs.get_dev_flash() + "sys/external/"; - - std::unordered_set set(loadedLibs.begin(), loadedLibs.end()); - std::vector lle_module_list_unselected; - - for (const auto& prxf : fs::dir(lle_dir)) - { - // List found unselected modules - if (prxf.is_directory || (prxf.name.substr(std::max(size_t(3), prxf.name.length()) - 4)) != "sprx") - { - continue; - } - if (verify_npdrm_self_headers(fs::file(lle_dir + prxf.name)) && !set.count(prxf.name)) - { - lle_module_list_unselected.push_back(prxf.name); - } - } - - sort_string_vector(lle_module_list_unselected); - - for (const auto& lib : lle_module_list_unselected) - { - QListWidgetItem* item = new QListWidgetItem(qstr(lib), ui->lleList); - item->setFlags(item->flags() | Qt::ItemIsUserCheckable); // set checkable flag - item->setCheckState(Qt::Unchecked); // AND initialize check state - ui->lleList->addItem(item); - } - - ui->searchBox->setPlaceholderText(tr("Search libraries")); - - auto l_OnLibButtonClicked = [=](int ind) - { - if (ind != static_cast(lib_loading_type::liblv2only)) - { - ui->searchBox->setEnabled(true); - ui->lleList->setEnabled(true); - } - else - { - ui->searchBox->setEnabled(false); - ui->lleList->setEnabled(false); - } - }; - - auto l_OnSearchBoxTextChanged = [=](QString text) - { - QString searchTerm = text.toLower(); - std::vector items; - - // duplicate current items, we need clones to preserve checkstates - for (int i = 0; i < ui->lleList->count(); i++) - { - items.push_back(ui->lleList->item(i)->clone()); - } - - // sort items: checked items first then alphabetical order - std::sort(items.begin(), items.end(), [](QListWidgetItem *i1, QListWidgetItem *i2) - { - return (i1->checkState() != i2->checkState()) ? (i1->checkState() > i2->checkState()) : (i1->text() < i2->text()); - }); - - // refill library list - ui->lleList->clear(); - - for (uint i = 0; i < items.size(); i++) - { - ui->lleList->addItem(items[i]); - - // only show items filtered for search text - ui->lleList->setRowHidden(i, !items[i]->text().contains(searchTerm)); - } - }; - - // Events - connect(libModeBG, static_cast(&QButtonGroup::buttonClicked), l_OnLibButtonClicked); - connect(ui->searchBox, &QLineEdit::textChanged, l_OnSearchBoxTextChanged); - - // enable multiselection (there must be a better way) - connect(ui->lleList, &QListWidget::itemChanged, [&](QListWidgetItem* item) - { - for (auto cb : ui->lleList->selectedItems()) - { - cb->setCheckState(item->checkState()); - } - }); - - int buttid = libModeBG->checkedId(); - if (buttid != -1) - { - l_OnLibButtonClicked(buttid); - } - // _____ _____ _ _ _______ _ // / ____| __ \| | | | |__ __| | | // | | __| |__) | | | | | | __ _| |__ @@ -1108,6 +963,151 @@ settings_dialog::settings_dialog(std::shared_ptr guiSettings, std: SubscribeTooltip(ui->clockScale, json_advanced["clocksScale"].toString()); } + // lib options tool tips + SubscribeTooltip(ui->lib_manu, json_advanced_libs["manual"].toString()); + SubscribeTooltip(ui->lib_both, json_advanced_libs["both"].toString()); + SubscribeTooltip(ui->lib_lv2, json_advanced_libs["liblv2"].toString()); + SubscribeTooltip(ui->lib_lv2b, json_advanced_libs["liblv2both"].toString()); + SubscribeTooltip(ui->lib_lv2l, json_advanced_libs["liblv2list"].toString()); + + // creating this in ui file keeps scrambling the order... + QButtonGroup *libModeBG = new QButtonGroup(this); + libModeBG->addButton(ui->lib_manu, static_cast(lib_loading_type::manual)); + libModeBG->addButton(ui->lib_both, static_cast(lib_loading_type::hybrid)); + libModeBG->addButton(ui->lib_lv2, static_cast(lib_loading_type::liblv2only)); + libModeBG->addButton(ui->lib_lv2b, static_cast(lib_loading_type::liblv2both)); + libModeBG->addButton(ui->lib_lv2l, static_cast(lib_loading_type::liblv2list)); + + {// Handle lib loading options + QString selectedLib = qstr(xemu_settings->GetSetting(emu_settings::LibLoadOptions)); + QStringList libmode_list = xemu_settings->GetSettingOptions(emu_settings::LibLoadOptions); + + for (int i = 0; i < libmode_list.count(); i++) + { + libModeBG->button(i)->setText(libmode_list[i]); + + if (libmode_list[i] == selectedLib) + { + libModeBG->button(i)->setChecked(true); + } + + connect(libModeBG->button(i), &QAbstractButton::clicked, [=]() + { + xemu_settings->SetSetting(emu_settings::LibLoadOptions, sstr(libmode_list[i])); + }); + } + } + + // Sort string vector alphabetically + static const auto sort_string_vector = [](std::vector& vec) + { + std::sort(vec.begin(), vec.end(), [](const std::string &str1, const std::string &str2) { return str1 < str2; }); + }; + + std::vector loadedLibs = xemu_settings->GetLoadedLibraries(); + + sort_string_vector(loadedLibs); + + for (const auto& lib : loadedLibs) + { + QListWidgetItem* item = new QListWidgetItem(qstr(lib), ui->lleList); + item->setFlags(item->flags() | Qt::ItemIsUserCheckable); // set checkable flag + item->setCheckState(Qt::Checked); // AND initialize check state + ui->lleList->addItem(item); + } + + const std::string lle_dir = g_cfg.vfs.get_dev_flash() + "sys/external/"; + + std::unordered_set set(loadedLibs.begin(), loadedLibs.end()); + std::vector lle_module_list_unselected; + + for (const auto& prxf : fs::dir(lle_dir)) + { + // List found unselected modules + if (prxf.is_directory || (prxf.name.substr(std::max(size_t(3), prxf.name.length()) - 4)) != "sprx") + { + continue; + } + if (verify_npdrm_self_headers(fs::file(lle_dir + prxf.name)) && !set.count(prxf.name)) + { + lle_module_list_unselected.push_back(prxf.name); + } + } + + sort_string_vector(lle_module_list_unselected); + + for (const auto& lib : lle_module_list_unselected) + { + QListWidgetItem* item = new QListWidgetItem(qstr(lib), ui->lleList); + item->setFlags(item->flags() | Qt::ItemIsUserCheckable); // set checkable flag + item->setCheckState(Qt::Unchecked); // AND initialize check state + ui->lleList->addItem(item); + } + + ui->searchBox->setPlaceholderText(tr("Search libraries")); + + auto l_OnLibButtonClicked = [=](int ind) + { + if (ind != static_cast(lib_loading_type::liblv2only)) + { + ui->searchBox->setEnabled(true); + ui->lleList->setEnabled(true); + } + else + { + ui->searchBox->setEnabled(false); + ui->lleList->setEnabled(false); + } + }; + + auto l_OnSearchBoxTextChanged = [=](QString text) + { + QString searchTerm = text.toLower(); + std::vector items; + + // duplicate current items, we need clones to preserve checkstates + for (int i = 0; i < ui->lleList->count(); i++) + { + items.push_back(ui->lleList->item(i)->clone()); + } + + // sort items: checked items first then alphabetical order + std::sort(items.begin(), items.end(), [](QListWidgetItem *i1, QListWidgetItem *i2) + { + return (i1->checkState() != i2->checkState()) ? (i1->checkState() > i2->checkState()) : (i1->text() < i2->text()); + }); + + // refill library list + ui->lleList->clear(); + + for (uint i = 0; i < items.size(); i++) + { + ui->lleList->addItem(items[i]); + + // only show items filtered for search text + ui->lleList->setRowHidden(i, !items[i]->text().contains(searchTerm)); + } + }; + + // Events + connect(libModeBG, static_cast(&QButtonGroup::buttonClicked), l_OnLibButtonClicked); + connect(ui->searchBox, &QLineEdit::textChanged, l_OnSearchBoxTextChanged); + + // enable multiselection (there must be a better way) + connect(ui->lleList, &QListWidget::itemChanged, [&](QListWidgetItem* item) + { + for (auto cb : ui->lleList->selectedItems()) + { + cb->setCheckState(item->checkState()); + } + }); + + int buttid = libModeBG->checkedId(); + if (buttid != -1) + { + l_OnLibButtonClicked(buttid); + } + // ______ _ _ _______ _ // | ____| | | | | |__ __| | | // | |__ _ __ ___ _ _| | __ _| |_ ___ _ __ | | __ _| |__ diff --git a/rpcs3/rpcs3qt/settings_dialog.ui b/rpcs3/rpcs3qt/settings_dialog.ui index 81bf576f6d..1b3cce9453 100644 --- a/rpcs3/rpcs3qt/settings_dialog.ui +++ b/rpcs3/rpcs3qt/settings_dialog.ui @@ -6,8 +6,8 @@ 0 0 - 752 - 584 + 753 + 597 @@ -42,11 +42,11 @@ CPU - + - + @@ -115,107 +115,25 @@ - - - - 0 - 0 - + + + Qt::Vertical - - Preferred SPU Threads + + QSizePolicy::MinimumExpanding - - - - - - + + + 0 + 0 + + + - - - - - - 0 - 0 - - - - Firmware Settings - - - - - - - 0 - 0 - - - - Manually load selected libraries - - - - - - - - 0 - 0 - - - - Load automatic and manual selection - - - - - - - - 0 - 0 - - - - Load liblv2.sprx only - - - - - - - - 0 - 0 - - - - Load liblv2.sprx and manual selection - - - - - - - - 0 - 0 - - - - Load liblv2.sprx and strict selection - - - - - - + @@ -261,68 +179,25 @@ - - - - 0 - 0 - + + + Qt::Vertical - - SPU Block Size + + QSizePolicy::MinimumExpanding - - - - - - + + + 0 + 0 + + + - - - - - - 0 - 0 - - - - Firmware Libraries - - - - - - - 0 - 0 - - - - QAbstractItemView::ExtendedSelection - - - QListView::ListMode - - - - - - - - 0 - 0 - - - - - - - + @@ -341,6 +216,58 @@ + + + + + 0 + 0 + + + + SPU Block Size + + + + + + + + + + + + + 0 + 0 + + + + Preferred SPU Threads + + + + + + + + + + + + Qt::Vertical + + + QSizePolicy::MinimumExpanding + + + + 0 + 0 + + + + @@ -1640,6 +1567,86 @@ + + + + + 0 + 0 + + + + Firmware Settings + + + + + + + 0 + 0 + + + + Manually load selected libraries + + + + + + + + 0 + 0 + + + + Load automatic and manual selection + + + + + + + + 0 + 0 + + + + Load liblv2.sprx only + + + + + + + + 0 + 0 + + + + Load liblv2.sprx and manual selection + + + + + + + + 0 + 0 + + + + Load liblv2.sprx and strict selection + + + + + + @@ -1655,6 +1662,51 @@ + + + + + + + 0 + 0 + + + + Firmware Libraries + + + + + + + 0 + 0 + + + + QAbstractItemView::ExtendedSelection + + + QListView::ListMode + + + + + + + + 0 + 0 + + + + + + + + + @@ -1700,23 +1752,6 @@ - - - - Qt::Vertical - - - - 0 - 0 - - - - - - - - @@ -1804,7 +1839,7 @@ - + Qt::Vertical