diff options
Diffstat (limited to 'src/yuzu')
-rw-r--r-- | src/yuzu/CMakeLists.txt | 2 | ||||
-rw-r--r-- | src/yuzu/compatdb.cpp | 27 | ||||
-rw-r--r-- | src/yuzu/compatdb.h | 4 | ||||
-rw-r--r-- | src/yuzu/configuration/config.cpp | 12 | ||||
-rw-r--r-- | src/yuzu/configuration/configure_general.cpp | 32 | ||||
-rw-r--r-- | src/yuzu/configuration/configure_general.h | 1 | ||||
-rw-r--r-- | src/yuzu/configuration/configure_input.cpp | 2 | ||||
-rw-r--r-- | src/yuzu/configuration/configure_input.h | 6 | ||||
-rw-r--r-- | src/yuzu/configuration/configure_system.cpp | 75 | ||||
-rw-r--r-- | src/yuzu/configuration/configure_system.ui | 228 | ||||
-rw-r--r-- | src/yuzu/debugger/graphics/graphics_surface.cpp | 10 | ||||
-rw-r--r-- | src/yuzu/debugger/wait_tree.h | 1 | ||||
-rw-r--r-- | src/yuzu/main.cpp | 22 | ||||
-rw-r--r-- | src/yuzu/main.h | 6 | ||||
-rw-r--r-- | src/yuzu/main.ui | 6 | ||||
-rw-r--r-- | src/yuzu/util/limitable_input_dialog.cpp | 59 | ||||
-rw-r--r-- | src/yuzu/util/limitable_input_dialog.h | 31 |
17 files changed, 373 insertions, 151 deletions
diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt index 9379d9110..f9ca2948e 100644 --- a/src/yuzu/CMakeLists.txt +++ b/src/yuzu/CMakeLists.txt @@ -56,6 +56,8 @@ add_executable(yuzu main.h ui_settings.cpp ui_settings.h + util/limitable_input_dialog.cpp + util/limitable_input_dialog.h util/spinbox.cpp util/spinbox.h util/util.cpp diff --git a/src/yuzu/compatdb.cpp b/src/yuzu/compatdb.cpp index 91e754274..5f0896f84 100644 --- a/src/yuzu/compatdb.cpp +++ b/src/yuzu/compatdb.cpp @@ -5,6 +5,7 @@ #include <QButtonGroup> #include <QMessageBox> #include <QPushButton> +#include <QtConcurrent/qtconcurrentrun.h> #include "common/logging/log.h" #include "common/telemetry.h" #include "core/core.h" @@ -23,6 +24,8 @@ CompatDB::CompatDB(QWidget* parent) connect(ui->radioButton_IntroMenu, &QRadioButton::clicked, this, &CompatDB::EnableNext); connect(ui->radioButton_WontBoot, &QRadioButton::clicked, this, &CompatDB::EnableNext); connect(button(NextButton), &QPushButton::clicked, this, &CompatDB::Submit); + connect(&testcase_watcher, &QFutureWatcher<bool>::finished, this, + &CompatDB::OnTestcaseSubmitted); } CompatDB::~CompatDB() = default; @@ -48,18 +51,38 @@ void CompatDB::Submit() { } break; case CompatDBPage::Final: + back(); LOG_DEBUG(Frontend, "Compatibility Rating: {}", compatibility->checkedId()); Core::Telemetry().AddField(Telemetry::FieldType::UserFeedback, "Compatibility", compatibility->checkedId()); - // older versions of QT don't support the "NoCancelButtonOnLastPage" option, this is a - // workaround + + button(NextButton)->setEnabled(false); + button(NextButton)->setText(tr("Submitting")); button(QWizard::CancelButton)->setVisible(false); + + testcase_watcher.setFuture(QtConcurrent::run( + [this]() { return Core::System::GetInstance().TelemetrySession().SubmitTestcase(); })); break; default: LOG_ERROR(Frontend, "Unexpected page: {}", currentId()); } } +void CompatDB::OnTestcaseSubmitted() { + if (!testcase_watcher.result()) { + QMessageBox::critical(this, tr("Communication error"), + tr("An error occured while sending the Testcase")); + button(NextButton)->setEnabled(true); + button(NextButton)->setText(tr("Next")); + button(QWizard::CancelButton)->setVisible(true); + } else { + next(); + // older versions of QT don't support the "NoCancelButtonOnLastPage" option, this is a + // workaround + button(QWizard::CancelButton)->setVisible(false); + } +} + void CompatDB::EnableNext() { button(NextButton)->setEnabled(true); } diff --git a/src/yuzu/compatdb.h b/src/yuzu/compatdb.h index ca0dd11d6..5381f67f7 100644 --- a/src/yuzu/compatdb.h +++ b/src/yuzu/compatdb.h @@ -5,6 +5,7 @@ #pragma once #include <memory> +#include <QFutureWatcher> #include <QWizard> namespace Ui { @@ -19,8 +20,11 @@ public: ~CompatDB(); private: + QFutureWatcher<bool> testcase_watcher; + std::unique_ptr<Ui::CompatDB> ui; void Submit(); + void OnTestcaseSubmitted(); void EnableNext(); }; diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp index d4fd60a73..d3b7fa59d 100644 --- a/src/yuzu/configuration/config.cpp +++ b/src/yuzu/configuration/config.cpp @@ -134,6 +134,14 @@ void Config::ReadValues() { Service::Account::MAX_USERS - 1); Settings::values.language_index = qt_config->value("language_index", 1).toInt(); + + const auto enabled = qt_config->value("rng_seed_enabled", false).toBool(); + if (enabled) { + Settings::values.rng_seed = qt_config->value("rng_seed", 0).toULongLong(); + } else { + Settings::values.rng_seed = std::nullopt; + } + qt_config->endGroup(); qt_config->beginGroup("Miscellaneous"); @@ -272,6 +280,10 @@ void Config::SaveValues() { qt_config->setValue("current_user", Settings::values.current_user); qt_config->setValue("language_index", Settings::values.language_index); + + qt_config->setValue("rng_seed_enabled", Settings::values.rng_seed.has_value()); + qt_config->setValue("rng_seed", Settings::values.rng_seed.value_or(0)); + qt_config->endGroup(); qt_config->beginGroup("Miscellaneous"); diff --git a/src/yuzu/configuration/configure_general.cpp b/src/yuzu/configuration/configure_general.cpp index 537d6e576..b322258a0 100644 --- a/src/yuzu/configuration/configure_general.cpp +++ b/src/yuzu/configuration/configure_general.cpp @@ -3,6 +3,10 @@ // Refer to the license.txt file included. #include "core/core.h" +#include "core/hle/service/am/am.h" +#include "core/hle/service/am/applet_ae.h" +#include "core/hle/service/am/applet_oe.h" +#include "core/hle/service/sm/sm.h" #include "core/settings.h" #include "ui_configure_general.h" #include "yuzu/configuration/configure_general.h" @@ -20,7 +24,6 @@ ConfigureGeneral::ConfigureGeneral(QWidget* parent) this->setConfiguration(); ui->use_cpu_jit->setEnabled(!Core::System::GetInstance().IsPoweredOn()); - ui->use_docked_mode->setEnabled(!Core::System::GetInstance().IsPoweredOn()); } ConfigureGeneral::~ConfigureGeneral() = default; @@ -38,6 +41,30 @@ void ConfigureGeneral::PopulateHotkeyList(const HotkeyRegistry& registry) { ui->widget->Populate(registry); } +void ConfigureGeneral::OnDockedModeChanged(bool last_state, bool new_state) { + if (last_state == new_state) { + return; + } + + Core::System& system{Core::System::GetInstance()}; + Service::SM::ServiceManager& sm = system.ServiceManager(); + + // Message queue is shared between these services, we just need to signal an operation + // change to one and it will handle both automatically + auto applet_oe = sm.GetService<Service::AM::AppletOE>("appletOE"); + auto applet_ae = sm.GetService<Service::AM::AppletAE>("appletAE"); + bool has_signalled = false; + + if (applet_oe != nullptr) { + applet_oe->GetMessageQueue()->OperationModeChanged(); + has_signalled = true; + } + + if (applet_ae != nullptr && !has_signalled) { + applet_ae->GetMessageQueue()->OperationModeChanged(); + } +} + void ConfigureGeneral::applyConfiguration() { UISettings::values.gamedir_deepscan = ui->toggle_deepscan->isChecked(); UISettings::values.confirm_before_closing = ui->toggle_check_exit->isChecked(); @@ -45,6 +72,9 @@ void ConfigureGeneral::applyConfiguration() { ui->theme_combobox->itemData(ui->theme_combobox->currentIndex()).toString(); Settings::values.use_cpu_jit = ui->use_cpu_jit->isChecked(); + const bool pre_docked_mode = Settings::values.use_docked_mode; Settings::values.use_docked_mode = ui->use_docked_mode->isChecked(); + OnDockedModeChanged(pre_docked_mode, Settings::values.use_docked_mode); + Settings::values.enable_nfc = ui->enable_nfc->isChecked(); } diff --git a/src/yuzu/configuration/configure_general.h b/src/yuzu/configuration/configure_general.h index 4770034cc..2210d48da 100644 --- a/src/yuzu/configuration/configure_general.h +++ b/src/yuzu/configuration/configure_general.h @@ -25,6 +25,7 @@ public: private: void setConfiguration(); + void OnDockedModeChanged(bool last_state, bool new_state); std::unique_ptr<Ui::ConfigureGeneral> ui; }; diff --git a/src/yuzu/configuration/configure_input.cpp b/src/yuzu/configuration/configure_input.cpp index 94789c064..42a7beac6 100644 --- a/src/yuzu/configuration/configure_input.cpp +++ b/src/yuzu/configuration/configure_input.cpp @@ -322,7 +322,7 @@ void ConfigureInput::setPollingResult(const Common::ParamPackage& params, bool a } updateButtonLabels(); - input_setter = boost::none; + input_setter = {}; } void ConfigureInput::keyPressEvent(QKeyEvent* event) { diff --git a/src/yuzu/configuration/configure_input.h b/src/yuzu/configuration/configure_input.h index d1198db81..32c7183f9 100644 --- a/src/yuzu/configuration/configure_input.h +++ b/src/yuzu/configuration/configure_input.h @@ -7,11 +7,13 @@ #include <array> #include <functional> #include <memory> +#include <optional> #include <string> #include <unordered_map> + #include <QKeyEvent> #include <QWidget> -#include <boost/optional.hpp> + #include "common/param_package.h" #include "core/settings.h" #include "input_common/main.h" @@ -41,7 +43,7 @@ private: std::unique_ptr<QTimer> poll_timer; /// This will be the the setting function when an input is awaiting configuration. - boost::optional<std::function<void(const Common::ParamPackage&)>> input_setter; + std::optional<std::function<void(const Common::ParamPackage&)>> input_setter; std::array<Common::ParamPackage, Settings::NativeButton::NumButtons> buttons_param; std::array<Common::ParamPackage, Settings::NativeAnalog::NumAnalogs> analogs_param; diff --git a/src/yuzu/configuration/configure_system.cpp b/src/yuzu/configuration/configure_system.cpp index 4b34c1e28..67f07ecb1 100644 --- a/src/yuzu/configuration/configure_system.cpp +++ b/src/yuzu/configuration/configure_system.cpp @@ -6,20 +6,20 @@ #include <QFileDialog> #include <QGraphicsItem> #include <QGraphicsScene> -#include <QInputDialog> +#include <QHeaderView> #include <QMessageBox> #include <QStandardItemModel> #include <QTreeView> #include <QVBoxLayout> -#include "common/common_paths.h" -#include "common/logging/backend.h" +#include "common/assert.h" +#include "common/file_util.h" #include "common/string_util.h" #include "core/core.h" #include "core/hle/service/acc/profile_manager.h" #include "core/settings.h" #include "ui_configure_system.h" #include "yuzu/configuration/configure_system.h" -#include "yuzu/main.h" +#include "yuzu/util/limitable_input_dialog.h" namespace { constexpr std::array<int, 12> days_in_month = {{ @@ -78,11 +78,17 @@ QPixmap GetIcon(Service::Account::UUID uuid) { if (!icon) { icon.fill(Qt::black); - icon.loadFromData(backup_jpeg.data(), backup_jpeg.size()); + icon.loadFromData(backup_jpeg.data(), static_cast<u32>(backup_jpeg.size())); } return icon.scaled(64, 64, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); } + +QString GetProfileUsernameFromUser(QWidget* parent, const QString& description_text) { + return LimitableInputDialog::GetText(parent, ConfigureSystem::tr("Enter Username"), + description_text, 1, + static_cast<int>(Service::Account::profile_username_size)); +} } // Anonymous namespace ConfigureSystem::ConfigureSystem(QWidget* parent) @@ -131,6 +137,12 @@ ConfigureSystem::ConfigureSystem(QWidget* parent) connect(ui->pm_remove, &QPushButton::pressed, this, &ConfigureSystem::DeleteUser); connect(ui->pm_set_image, &QPushButton::pressed, this, &ConfigureSystem::SetUserImage); + connect(ui->rng_seed_checkbox, &QCheckBox::stateChanged, this, [this](bool checked) { + ui->rng_seed_edit->setEnabled(checked); + if (!checked) + ui->rng_seed_edit->setText(QStringLiteral("0000000000000000")); + }); + scene = new QGraphicsScene; ui->current_user_icon->setScene(scene); @@ -149,6 +161,14 @@ void ConfigureSystem::setConfiguration() { PopulateUserList(); UpdateCurrentUser(); + + ui->rng_seed_checkbox->setChecked(Settings::values.rng_seed.has_value()); + ui->rng_seed_edit->setEnabled(Settings::values.rng_seed.has_value()); + + const auto rng_seed = QString("%1") + .arg(Settings::values.rng_seed.value_or(0), 16, 16, QLatin1Char{'0'}) + .toUpper(); + ui->rng_seed_edit->setText(rng_seed); } void ConfigureSystem::PopulateUserList() { @@ -173,7 +193,7 @@ void ConfigureSystem::UpdateCurrentUser() { ui->pm_add->setEnabled(profile_manager->GetUserCount() < Service::Account::MAX_USERS); const auto& current_user = profile_manager->GetUser(Settings::values.current_user); - ASSERT(current_user != std::nullopt); + ASSERT(current_user); const auto username = GetAccountUsername(*profile_manager, *current_user); scene->clear(); @@ -189,6 +209,12 @@ void ConfigureSystem::applyConfiguration() { return; Settings::values.language_index = ui->combo_language->currentIndex(); + + if (ui->rng_seed_checkbox->isChecked()) + Settings::values.rng_seed = ui->rng_seed_edit->text().toULongLong(nullptr, 16); + else + Settings::values.rng_seed = std::nullopt; + Settings::Apply(); } @@ -234,7 +260,7 @@ void ConfigureSystem::RefreshConsoleID() { void ConfigureSystem::SelectUser(const QModelIndex& index) { Settings::values.current_user = - std::clamp<std::size_t>(index.row(), 0, profile_manager->GetUserCount() - 1); + std::clamp<s32>(index.row(), 0, static_cast<s32>(profile_manager->GetUserCount() - 1)); UpdateCurrentUser(); @@ -244,15 +270,13 @@ void ConfigureSystem::SelectUser(const QModelIndex& index) { } void ConfigureSystem::AddUser() { - const auto uuid = Service::Account::UUID::Generate(); - - bool ok = false; const auto username = - QInputDialog::getText(this, tr("Enter Username"), tr("Enter a username for the new user:"), - QLineEdit::Normal, QString(), &ok); - if (!ok) + GetProfileUsernameFromUser(this, tr("Enter a username for the new user:")); + if (username.isEmpty()) { return; + } + const auto uuid = Service::Account::UUID::Generate(); profile_manager->CreateNewUser(uuid, username.toStdString()); item_model->appendRow(new QStandardItem{GetIcon(uuid), FormatUserEntryText(username, uuid)}); @@ -261,29 +285,20 @@ void ConfigureSystem::AddUser() { void ConfigureSystem::RenameUser() { const auto user = tree_view->currentIndex().row(); const auto uuid = profile_manager->GetUser(user); - ASSERT(uuid != std::nullopt); + ASSERT(uuid); Service::Account::ProfileBase profile; if (!profile_manager->GetProfileBase(*uuid, profile)) return; - bool ok = false; - const auto old_username = GetAccountUsername(*profile_manager, *uuid); - const auto new_username = - QInputDialog::getText(this, tr("Enter Username"), tr("Enter a new username:"), - QLineEdit::Normal, old_username, &ok); - - if (!ok) + const auto new_username = GetProfileUsernameFromUser(this, tr("Enter a new username:")); + if (new_username.isEmpty()) { return; + } - std::fill(profile.username.begin(), profile.username.end(), '\0'); const auto username_std = new_username.toStdString(); - if (username_std.size() > profile.username.size()) { - std::copy_n(username_std.begin(), std::min(profile.username.size(), username_std.size()), - profile.username.begin()); - } else { - std::copy(username_std.begin(), username_std.end(), profile.username.begin()); - } + std::fill(profile.username.begin(), profile.username.end(), '\0'); + std::copy(username_std.begin(), username_std.end(), profile.username.begin()); profile_manager->SetProfileBase(*uuid, profile); @@ -297,7 +312,7 @@ void ConfigureSystem::RenameUser() { void ConfigureSystem::DeleteUser() { const auto index = tree_view->currentIndex().row(); const auto uuid = profile_manager->GetUser(index); - ASSERT(uuid != std::nullopt); + ASSERT(uuid); const auto username = GetAccountUsername(*profile_manager, *uuid); const auto confirm = QMessageBox::question( @@ -324,7 +339,7 @@ void ConfigureSystem::DeleteUser() { void ConfigureSystem::SetUserImage() { const auto index = tree_view->currentIndex().row(); const auto uuid = profile_manager->GetUser(index); - ASSERT(uuid != std::nullopt); + ASSERT(uuid); const auto file = QFileDialog::getOpenFileName(this, tr("Select User Image"), QString(), tr("JPEG Images (*.jpg *.jpeg)")); diff --git a/src/yuzu/configuration/configure_system.ui b/src/yuzu/configuration/configure_system.ui index 020b32a37..d0fcd0163 100644 --- a/src/yuzu/configuration/configure_system.ui +++ b/src/yuzu/configuration/configure_system.ui @@ -6,7 +6,7 @@ <rect> <x>0</x> <y>0</y> - <width>360</width> + <width>366</width> <height>483</height> </rect> </property> @@ -22,98 +22,6 @@ <string>System Settings</string> </property> <layout class="QGridLayout" name="gridLayout"> - <item row="1" column="0"> - <widget class="QLabel" name="label_language"> - <property name="text"> - <string>Language</string> - </property> - </widget> - </item> - <item row="0" column="0"> - <widget class="QLabel" name="label_birthday"> - <property name="text"> - <string>Birthday</string> - </property> - </widget> - </item> - <item row="3" column="0"> - <widget class="QLabel" name="label_console_id"> - <property name="text"> - <string>Console ID:</string> - </property> - </widget> - </item> - <item row="0" column="1"> - <layout class="QHBoxLayout" name="horizontalLayout_birthday2"> - <item> - <widget class="QComboBox" name="combo_birthmonth"> - <item> - <property name="text"> - <string>January</string> - </property> - </item> - <item> - <property name="text"> - <string>February</string> - </property> - </item> - <item> - <property name="text"> - <string>March</string> - </property> - </item> - <item> - <property name="text"> - <string>April</string> - </property> - </item> - <item> - <property name="text"> - <string>May</string> - </property> - </item> - <item> - <property name="text"> - <string>June</string> - </property> - </item> - <item> - <property name="text"> - <string>July</string> - </property> - </item> - <item> - <property name="text"> - <string>August</string> - </property> - </item> - <item> - <property name="text"> - <string>September</string> - </property> - </item> - <item> - <property name="text"> - <string>October</string> - </property> - </item> - <item> - <property name="text"> - <string>November</string> - </property> - </item> - <item> - <property name="text"> - <string>December</string> - </property> - </item> - </widget> - </item> - <item> - <widget class="QComboBox" name="combo_birthday"/> - </item> - </layout> - </item> <item row="1" column="1"> <widget class="QComboBox" name="combo_language"> <property name="toolTip"> @@ -206,6 +114,13 @@ </item> </widget> </item> + <item row="3" column="0"> + <widget class="QLabel" name="label_console_id"> + <property name="text"> + <string>Console ID:</string> + </property> + </widget> + </item> <item row="2" column="0"> <widget class="QLabel" name="label_sound"> <property name="text"> @@ -213,6 +128,100 @@ </property> </widget> </item> + <item row="0" column="0"> + <widget class="QLabel" name="label_birthday"> + <property name="text"> + <string>Birthday</string> + </property> + </widget> + </item> + <item row="0" column="1"> + <layout class="QHBoxLayout" name="horizontalLayout_birthday2"> + <item> + <widget class="QComboBox" name="combo_birthmonth"> + <item> + <property name="text"> + <string>January</string> + </property> + </item> + <item> + <property name="text"> + <string>February</string> + </property> + </item> + <item> + <property name="text"> + <string>March</string> + </property> + </item> + <item> + <property name="text"> + <string>April</string> + </property> + </item> + <item> + <property name="text"> + <string>May</string> + </property> + </item> + <item> + <property name="text"> + <string>June</string> + </property> + </item> + <item> + <property name="text"> + <string>July</string> + </property> + </item> + <item> + <property name="text"> + <string>August</string> + </property> + </item> + <item> + <property name="text"> + <string>September</string> + </property> + </item> + <item> + <property name="text"> + <string>October</string> + </property> + </item> + <item> + <property name="text"> + <string>November</string> + </property> + </item> + <item> + <property name="text"> + <string>December</string> + </property> + </item> + </widget> + </item> + <item> + <widget class="QComboBox" name="combo_birthday"/> + </item> + </layout> + </item> + <item row="3" column="1"> + <widget class="QPushButton" name="button_regenerate_console_id"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="layoutDirection"> + <enum>Qt::RightToLeft</enum> + </property> + <property name="text"> + <string>Regenerate</string> + </property> + </widget> + </item> <item row="2" column="1"> <widget class="QComboBox" name="combo_sound"> <item> @@ -232,19 +241,38 @@ </item> </widget> </item> - <item row="3" column="1"> - <widget class="QPushButton" name="button_regenerate_console_id"> + <item row="1" column="0"> + <widget class="QLabel" name="label_language"> + <property name="text"> + <string>Language</string> + </property> + </widget> + </item> + <item row="4" column="0"> + <widget class="QCheckBox" name="rng_seed_checkbox"> + <property name="text"> + <string>RNG Seed</string> + </property> + </widget> + </item> + <item row="4" column="1"> + <widget class="QLineEdit" name="rng_seed_edit"> <property name="sizePolicy"> - <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> <horstretch>0</horstretch> <verstretch>0</verstretch> </sizepolicy> </property> - <property name="layoutDirection"> - <enum>Qt::RightToLeft</enum> + <property name="font"> + <font> + <family>Lucida Console</family> + </font> </property> - <property name="text"> - <string>Regenerate</string> + <property name="inputMask"> + <string>HHHHHHHHHHHHHHHH</string> + </property> + <property name="maxLength"> + <number>16</number> </property> </widget> </item> diff --git a/src/yuzu/debugger/graphics/graphics_surface.cpp b/src/yuzu/debugger/graphics/graphics_surface.cpp index 44d423da2..707747422 100644 --- a/src/yuzu/debugger/graphics/graphics_surface.cpp +++ b/src/yuzu/debugger/graphics/graphics_surface.cpp @@ -382,13 +382,13 @@ void GraphicsSurfaceWidget::OnUpdate() { // TODO: Implement a good way to visualize alpha components! QImage decoded_image(surface_width, surface_height, QImage::Format_ARGB32); - boost::optional<VAddr> address = gpu.MemoryManager().GpuToCpuAddress(surface_address); + std::optional<VAddr> address = gpu.MemoryManager().GpuToCpuAddress(surface_address); // TODO(bunnei): Will not work with BCn formats that swizzle 4x4 tiles. // Needs to be fixed if we plan to use this feature more, otherwise we may remove it. - auto unswizzled_data = - Tegra::Texture::UnswizzleTexture(*address, 1, Tegra::Texture::BytesPerPixel(surface_format), - surface_width, surface_height, 1U); + auto unswizzled_data = Tegra::Texture::UnswizzleTexture( + *address, 1, 1, Tegra::Texture::BytesPerPixel(surface_format), surface_width, + surface_height, 1U); auto texture_data = Tegra::Texture::DecodeTexture(unswizzled_data, surface_format, surface_width, surface_height); @@ -444,7 +444,7 @@ void GraphicsSurfaceWidget::SaveSurface() { pixmap->save(&file, "PNG"); } else if (selectedFilter == bin_filter) { auto& gpu = Core::System::GetInstance().GPU(); - boost::optional<VAddr> address = gpu.MemoryManager().GpuToCpuAddress(surface_address); + std::optional<VAddr> address = gpu.MemoryManager().GpuToCpuAddress(surface_address); const u8* buffer = Memory::GetPointer(*address); ASSERT_MSG(buffer != nullptr, "Memory not accessible"); diff --git a/src/yuzu/debugger/wait_tree.h b/src/yuzu/debugger/wait_tree.h index defbf734f..331f89885 100644 --- a/src/yuzu/debugger/wait_tree.h +++ b/src/yuzu/debugger/wait_tree.h @@ -11,7 +11,6 @@ #include <QAbstractItemModel> #include <QDockWidget> #include <QTreeView> -#include <boost/container/flat_set.hpp> #include "common/common_types.h" #include "core/hle/kernel/object.h" diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index b5bfa6741..131ad19de 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -142,6 +142,9 @@ static void InitializeLogging() { const std::string& log_dir = FileUtil::GetUserPath(FileUtil::UserPath::LogDir); FileUtil::CreateFullPath(log_dir); Log::AddBackend(std::make_unique<Log::FileBackend>(log_dir + LOG_FILE)); +#ifdef _WIN32 + Log::AddBackend(std::make_unique<Log::DebuggerBackend>()); +#endif } GMainWindow::GMainWindow() @@ -454,6 +457,7 @@ void GMainWindow::ConnectMenuEvents() { connect(ui.action_Fullscreen, &QAction::triggered, this, &GMainWindow::ToggleFullscreen); // Help + connect(ui.action_Open_yuzu_Folder, &QAction::triggered, this, &GMainWindow::OnOpenYuzuFolder); connect(ui.action_Rederive, &QAction::triggered, this, std::bind(&GMainWindow::OnReinitializeKeys, this, ReinitializeKeyBehavior::Warning)); connect(ui.action_About, &QAction::triggered, this, &GMainWindow::OnAbout); @@ -786,7 +790,7 @@ void GMainWindow::OnGameListOpenFolder(u64 program_id, GameListOpenTarget target ASSERT(index != -1 && index < 8); const auto user_id = manager.GetUser(index); - ASSERT(user_id != std::nullopt); + ASSERT(user_id); path = nand_dir + FileSys::SaveDataFactory::GetFullPath(FileSys::SaveDataSpaceId::NandUser, FileSys::SaveDataType::SaveData, program_id, user_id->uuid, 0); @@ -929,7 +933,8 @@ void GMainWindow::OnGameListDumpRomFS(u64 program_id, const std::string& game_pa const auto full = res == "Full"; const auto entry_size = CalculateRomFSEntrySize(extracted, full); - QProgressDialog progress(tr("Extracting RomFS..."), tr("Cancel"), 0, entry_size, this); + QProgressDialog progress(tr("Extracting RomFS..."), tr("Cancel"), 0, + static_cast<s32>(entry_size), this); progress.setWindowModality(Qt::WindowModal); progress.setMinimumDuration(100); @@ -1374,6 +1379,11 @@ void GMainWindow::OnLoadAmiibo() { } } +void GMainWindow::OnOpenYuzuFolder() { + QDesktopServices::openUrl(QUrl::fromLocalFile( + QString::fromStdString(FileUtil::GetUserPath(FileUtil::UserPath::UserDir)))); +} + void GMainWindow::OnAbout() { AboutDialog aboutDialog(this); aboutDialog.exec(); @@ -1532,7 +1542,7 @@ void GMainWindow::OnReinitializeKeys(ReinitializeKeyBehavior behavior) { "derivation. It will be attempted but may not complete.<br><br>") + errors + tr("<br><br>You can get all of these and dump all of your games easily by " - "following <a href='https://yuzu-emu.org/help/quickstart/quickstart/'>the " + "following <a href='https://yuzu-emu.org/help/quickstart/'>the " "quickstart guide</a>. Alternatively, you can use another method of dumping " "to obtain all of your keys.")); } @@ -1560,7 +1570,7 @@ void GMainWindow::OnReinitializeKeys(ReinitializeKeyBehavior behavior) { } } -boost::optional<u64> GMainWindow::SelectRomFSDumpTarget( +std::optional<u64> GMainWindow::SelectRomFSDumpTarget( const FileSys::RegisteredCacheUnion& installed, u64 program_id) { const auto dlc_entries = installed.ListEntriesFilter(FileSys::TitleType::AOC, FileSys::ContentRecordType::Data); @@ -1587,7 +1597,7 @@ boost::optional<u64> GMainWindow::SelectRomFSDumpTarget( this, tr("Select RomFS Dump Target"), tr("Please select which RomFS you would like to dump."), list, 0, false, &ok); if (!ok) { - return boost::none; + return {}; } return romfs_tids[list.indexOf(res)]; @@ -1612,7 +1622,7 @@ void GMainWindow::closeEvent(QCloseEvent* event) { return; } - if (ui.action_Fullscreen->isChecked()) { + if (!ui.action_Fullscreen->isChecked()) { UISettings::values.geometry = saveGeometry(); UISettings::values.renderwindow_geometry = render_window->saveGeometry(); } diff --git a/src/yuzu/main.h b/src/yuzu/main.h index 7c7c223e1..929250e8c 100644 --- a/src/yuzu/main.h +++ b/src/yuzu/main.h @@ -5,12 +5,12 @@ #pragma once #include <memory> +#include <optional> #include <unordered_map> #include <QMainWindow> #include <QTimer> -#include <boost/optional.hpp> #include "common/common_types.h" #include "core/core.h" #include "ui_main.h" @@ -167,6 +167,7 @@ private slots: void OnMenuRecentFile(); void OnConfigure(); void OnLoadAmiibo(); + void OnOpenYuzuFolder(); void OnAbout(); void OnToggleFilterBar(); void OnDisplayTitleBars(bool); @@ -178,8 +179,7 @@ private slots: void OnReinitializeKeys(ReinitializeKeyBehavior behavior); private: - boost::optional<u64> SelectRomFSDumpTarget(const FileSys::RegisteredCacheUnion&, - u64 program_id); + std::optional<u64> SelectRomFSDumpTarget(const FileSys::RegisteredCacheUnion&, u64 program_id); void UpdateStatusBar(); Ui::MainWindow ui; diff --git a/src/yuzu/main.ui b/src/yuzu/main.ui index 48d099591..28cf269e7 100644 --- a/src/yuzu/main.ui +++ b/src/yuzu/main.ui @@ -110,6 +110,7 @@ <string>&Help</string> </property> <addaction name="action_Report_Compatibility"/> + <addaction name="action_Open_yuzu_Folder" /> <addaction name="separator"/> <addaction name="action_About"/> </widget> @@ -277,6 +278,11 @@ <bool>false</bool> </property> </action> + <action name="action_Open_yuzu_Folder"> + <property name="text"> + <string>Open yuzu Folder</string> + </property> + </action> </widget> <resources/> <connections/> diff --git a/src/yuzu/util/limitable_input_dialog.cpp b/src/yuzu/util/limitable_input_dialog.cpp new file mode 100644 index 000000000..edd78e579 --- /dev/null +++ b/src/yuzu/util/limitable_input_dialog.cpp @@ -0,0 +1,59 @@ +// Copyright 2018 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include <QDialogButtonBox> +#include <QLabel> +#include <QLineEdit> +#include <QPushButton> +#include <QVBoxLayout> +#include "yuzu/util/limitable_input_dialog.h" + +LimitableInputDialog::LimitableInputDialog(QWidget* parent) : QDialog{parent} { + CreateUI(); + ConnectEvents(); +} + +LimitableInputDialog::~LimitableInputDialog() = default; + +void LimitableInputDialog::CreateUI() { + setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); + + text_label = new QLabel(this); + text_entry = new QLineEdit(this); + buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this); + + auto* const layout = new QVBoxLayout; + layout->addWidget(text_label); + layout->addWidget(text_entry); + layout->addWidget(buttons); + + setLayout(layout); +} + +void LimitableInputDialog::ConnectEvents() { + connect(buttons, &QDialogButtonBox::accepted, this, &QDialog::accept); + connect(buttons, &QDialogButtonBox::rejected, this, &QDialog::reject); +} + +QString LimitableInputDialog::GetText(QWidget* parent, const QString& title, const QString& text, + int min_character_limit, int max_character_limit) { + Q_ASSERT(min_character_limit <= max_character_limit); + + LimitableInputDialog dialog{parent}; + dialog.setWindowTitle(title); + dialog.text_label->setText(text); + dialog.text_entry->setMaxLength(max_character_limit); + + auto* const ok_button = dialog.buttons->button(QDialogButtonBox::Ok); + ok_button->setEnabled(false); + connect(dialog.text_entry, &QLineEdit::textEdited, [&](const QString& new_text) { + ok_button->setEnabled(new_text.length() >= min_character_limit); + }); + + if (dialog.exec() != QDialog::Accepted) { + return {}; + } + + return dialog.text_entry->text(); +} diff --git a/src/yuzu/util/limitable_input_dialog.h b/src/yuzu/util/limitable_input_dialog.h new file mode 100644 index 000000000..164ad7301 --- /dev/null +++ b/src/yuzu/util/limitable_input_dialog.h @@ -0,0 +1,31 @@ +// Copyright 2018 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include <QDialog> + +class QDialogButtonBox; +class QLabel; +class QLineEdit; + +/// A QDialog that functions similarly to QInputDialog, however, it allows +/// restricting the minimum and total number of characters that can be entered. +class LimitableInputDialog final : public QDialog { + Q_OBJECT +public: + explicit LimitableInputDialog(QWidget* parent = nullptr); + ~LimitableInputDialog() override; + + static QString GetText(QWidget* parent, const QString& title, const QString& text, + int min_character_limit, int max_character_limit); + +private: + void CreateUI(); + void ConnectEvents(); + + QLabel* text_label; + QLineEdit* text_entry; + QDialogButtonBox* buttons; +}; |