summaryrefslogtreecommitdiff
path: root/src/yuzu
diff options
context:
space:
mode:
Diffstat (limited to 'src/yuzu')
-rw-r--r--src/yuzu/CMakeLists.txt2
-rw-r--r--src/yuzu/compatdb.cpp27
-rw-r--r--src/yuzu/compatdb.h4
-rw-r--r--src/yuzu/configuration/config.cpp16
-rw-r--r--src/yuzu/configuration/configure_debug.cpp2
-rw-r--r--src/yuzu/configuration/configure_debug.ui21
-rw-r--r--src/yuzu/configuration/configure_gamelist.cpp16
-rw-r--r--src/yuzu/configuration/configure_gamelist.h2
-rw-r--r--src/yuzu/configuration/configure_gamelist.ui223
-rw-r--r--src/yuzu/configuration/configure_general.cpp38
-rw-r--r--src/yuzu/configuration/configure_general.h1
-rw-r--r--src/yuzu/configuration/configure_input.cpp2
-rw-r--r--src/yuzu/configuration/configure_input.h6
-rw-r--r--src/yuzu/configuration/configure_system.cpp74
-rw-r--r--src/yuzu/configuration/configure_system.ui228
-rw-r--r--src/yuzu/debugger/graphics/graphics_surface.cpp10
-rw-r--r--src/yuzu/debugger/wait_tree.h1
-rw-r--r--src/yuzu/game_list.cpp33
-rw-r--r--src/yuzu/game_list_worker.cpp24
-rw-r--r--src/yuzu/main.cpp40
-rw-r--r--src/yuzu/main.h6
-rw-r--r--src/yuzu/main.ui7
-rw-r--r--src/yuzu/ui_settings.h3
-rw-r--r--src/yuzu/util/limitable_input_dialog.cpp59
-rw-r--r--src/yuzu/util/limitable_input_dialog.h31
25 files changed, 603 insertions, 273 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..be69fb831 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");
@@ -145,6 +153,7 @@ void Config::ReadValues() {
Settings::values.use_gdbstub = qt_config->value("use_gdbstub", false).toBool();
Settings::values.gdbstub_port = qt_config->value("gdbstub_port", 24689).toInt();
Settings::values.program_args = qt_config->value("program_args", "").toString().toStdString();
+ Settings::values.dump_nso = qt_config->value("dump_nso", false).toBool();
qt_config->endGroup();
qt_config->beginGroup("WebService");
@@ -162,6 +171,7 @@ void Config::ReadValues() {
qt_config->beginGroup("UIGameList");
UISettings::values.show_unknown = qt_config->value("show_unknown", true).toBool();
+ UISettings::values.show_add_ons = qt_config->value("show_add_ons", true).toBool();
UISettings::values.icon_size = qt_config->value("icon_size", 64).toUInt();
UISettings::values.row_1_text_id = qt_config->value("row_1_text_id", 3).toUInt();
UISettings::values.row_2_text_id = qt_config->value("row_2_text_id", 2).toUInt();
@@ -272,6 +282,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");
@@ -283,6 +297,7 @@ void Config::SaveValues() {
qt_config->setValue("use_gdbstub", Settings::values.use_gdbstub);
qt_config->setValue("gdbstub_port", Settings::values.gdbstub_port);
qt_config->setValue("program_args", QString::fromStdString(Settings::values.program_args));
+ qt_config->setValue("dump_nso", Settings::values.dump_nso);
qt_config->endGroup();
qt_config->beginGroup("WebService");
@@ -298,6 +313,7 @@ void Config::SaveValues() {
qt_config->beginGroup("UIGameList");
qt_config->setValue("show_unknown", UISettings::values.show_unknown);
+ qt_config->setValue("show_add_ons", UISettings::values.show_add_ons);
qt_config->setValue("icon_size", UISettings::values.icon_size);
qt_config->setValue("row_1_text_id", UISettings::values.row_1_text_id);
qt_config->setValue("row_2_text_id", UISettings::values.row_2_text_id);
diff --git a/src/yuzu/configuration/configure_debug.cpp b/src/yuzu/configuration/configure_debug.cpp
index 9e765fc93..fd5876b41 100644
--- a/src/yuzu/configuration/configure_debug.cpp
+++ b/src/yuzu/configuration/configure_debug.cpp
@@ -34,6 +34,7 @@ void ConfigureDebug::setConfiguration() {
ui->toggle_console->setChecked(UISettings::values.show_console);
ui->log_filter_edit->setText(QString::fromStdString(Settings::values.log_filter));
ui->homebrew_args_edit->setText(QString::fromStdString(Settings::values.program_args));
+ ui->dump_decompressed_nso->setChecked(Settings::values.dump_nso);
}
void ConfigureDebug::applyConfiguration() {
@@ -42,6 +43,7 @@ void ConfigureDebug::applyConfiguration() {
UISettings::values.show_console = ui->toggle_console->isChecked();
Settings::values.log_filter = ui->log_filter_edit->text().toStdString();
Settings::values.program_args = ui->homebrew_args_edit->text().toStdString();
+ Settings::values.dump_nso = ui->dump_decompressed_nso->isChecked();
Debugger::ToggleConsole();
Log::Filter filter;
filter.ParseFilterString(Settings::values.log_filter);
diff --git a/src/yuzu/configuration/configure_debug.ui b/src/yuzu/configuration/configure_debug.ui
index ff4987604..9c5b702f8 100644
--- a/src/yuzu/configuration/configure_debug.ui
+++ b/src/yuzu/configuration/configure_debug.ui
@@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>400</width>
- <height>300</height>
+ <height>357</height>
</rect>
</property>
<property name="windowTitle">
@@ -130,6 +130,25 @@
</widget>
</item>
<item>
+ <widget class="QGroupBox" name="groupBox_4">
+ <property name="title">
+ <string>Dump</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_4">
+ <item>
+ <widget class="QCheckBox" name="dump_decompressed_nso">
+ <property name="whatsThis">
+ <string>When checked, any NSO yuzu tries to load or patch will be copied decompressed to the yuzu/dump directory.</string>
+ </property>
+ <property name="text">
+ <string>Dump Decompressed NSOs</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
diff --git a/src/yuzu/configuration/configure_gamelist.cpp b/src/yuzu/configuration/configure_gamelist.cpp
index 8743ce982..ae8cac243 100644
--- a/src/yuzu/configuration/configure_gamelist.cpp
+++ b/src/yuzu/configuration/configure_gamelist.cpp
@@ -36,20 +36,36 @@ ConfigureGameList::ConfigureGameList(QWidget* parent)
InitializeRowComboBoxes();
this->setConfiguration();
+
+ // Force game list reload if any of the relevant settings are changed.
+ connect(ui->show_unknown, &QCheckBox::stateChanged, this,
+ &ConfigureGameList::RequestGameListUpdate);
+ connect(ui->icon_size_combobox, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
+ &ConfigureGameList::RequestGameListUpdate);
+ connect(ui->row_1_text_combobox, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
+ &ConfigureGameList::RequestGameListUpdate);
+ connect(ui->row_2_text_combobox, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
+ &ConfigureGameList::RequestGameListUpdate);
}
ConfigureGameList::~ConfigureGameList() = default;
void ConfigureGameList::applyConfiguration() {
UISettings::values.show_unknown = ui->show_unknown->isChecked();
+ UISettings::values.show_add_ons = ui->show_add_ons->isChecked();
UISettings::values.icon_size = ui->icon_size_combobox->currentData().toUInt();
UISettings::values.row_1_text_id = ui->row_1_text_combobox->currentData().toUInt();
UISettings::values.row_2_text_id = ui->row_2_text_combobox->currentData().toUInt();
Settings::Apply();
}
+void ConfigureGameList::RequestGameListUpdate() {
+ UISettings::values.is_game_list_reload_pending.exchange(true);
+}
+
void ConfigureGameList::setConfiguration() {
ui->show_unknown->setChecked(UISettings::values.show_unknown);
+ ui->show_add_ons->setChecked(UISettings::values.show_add_ons);
ui->icon_size_combobox->setCurrentIndex(
ui->icon_size_combobox->findData(UISettings::values.icon_size));
ui->row_1_text_combobox->setCurrentIndex(
diff --git a/src/yuzu/configuration/configure_gamelist.h b/src/yuzu/configuration/configure_gamelist.h
index ff7406c60..bbf7e25f1 100644
--- a/src/yuzu/configuration/configure_gamelist.h
+++ b/src/yuzu/configuration/configure_gamelist.h
@@ -21,6 +21,8 @@ public:
void applyConfiguration();
private:
+ void RequestGameListUpdate();
+
void setConfiguration();
void changeEvent(QEvent*) override;
diff --git a/src/yuzu/configuration/configure_gamelist.ui b/src/yuzu/configuration/configure_gamelist.ui
index 7471fdb60..7a69377e7 100644
--- a/src/yuzu/configuration/configure_gamelist.ui
+++ b/src/yuzu/configuration/configure_gamelist.ui
@@ -1,126 +1,133 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ConfigureGameList</class>
- <widget class="QWidget" name="ConfigureGeneral">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>300</width>
- <height>377</height>
- </rect>
- </property>
- <property name="windowTitle">
- <string>Form</string>
- </property>
- <layout class="QHBoxLayout" name="HorizontalLayout">
- <item>
- <layout class="QVBoxLayout" name="VerticalLayout">
+ <widget class="QWidget" name="ConfigureGameList">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>300</width>
+ <height>377</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Form</string>
+ </property>
+ <layout class="QHBoxLayout" name="HorizontalLayout">
+ <item>
+ <layout class="QVBoxLayout" name="VerticalLayout">
+ <item>
+ <widget class="QGroupBox" name="GeneralGroupBox">
+ <property name="title">
+ <string>General</string>
+ </property>
+ <layout class="QHBoxLayout" name="GeneralHorizontalLayout">
+ <item>
+ <layout class="QVBoxLayout" name="GeneralVerticalLayout">
<item>
- <widget class="QGroupBox" name="GeneralGroupBox">
- <property name="title">
- <string>General</string>
- </property>
- <layout class="QHBoxLayout" name="GeneralHorizontalLayout">
- <item>
- <layout class="QVBoxLayout" name="GeneralVerticalLayout">
- <item>
- <widget class="QCheckBox" name="show_unknown">
- <property name="text">
- <string>Show files with type 'Unknown'</string>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- </layout>
- </widget>
+ <widget class="QCheckBox" name="show_unknown">
+ <property name="text">
+ <string>Show files with type 'Unknown'</string>
+ </property>
+ </widget>
</item>
<item>
- <widget class="QGroupBox" name="IconSizeGroupBox">
- <property name="title">
- <string>Icon Size</string>
- </property>
- <layout class="QHBoxLayout" name="icon_size_qhbox_layout">
- <item>
- <layout class="QVBoxLayout" name="icon_size_qvbox_layout">
- <item>
- <layout class="QHBoxLayout" name="icon_size_qhbox_layout_2">
- <item>
- <widget class="QLabel" name="icon_size_label">
- <property name="text">
- <string>Icon Size:</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QComboBox" name="icon_size_combobox"/>
- </item>
- </layout>
- </item>
- </layout>
- </item>
- </layout>
- </widget>
+ <widget class="QCheckBox" name="show_add_ons">
+ <property name="text">
+ <string>Show Add-Ons Column</string>
+ </property>
+ </widget>
</item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="IconSizeGroupBox">
+ <property name="title">
+ <string>Icon Size</string>
+ </property>
+ <layout class="QHBoxLayout" name="icon_size_qhbox_layout">
+ <item>
+ <layout class="QVBoxLayout" name="icon_size_qvbox_layout">
<item>
- <widget class="QGroupBox" name="RowGroupBox">
- <property name="title">
- <string>Row Text</string>
+ <layout class="QHBoxLayout" name="icon_size_qhbox_layout_2">
+ <item>
+ <widget class="QLabel" name="icon_size_label">
+ <property name="text">
+ <string>Icon Size:</string>
</property>
- <layout class="QHBoxLayout" name="RowHorizontalLayout">
- <item>
- <layout class="QVBoxLayout" name="RowVerticalLayout">
- <item>
- <layout class="QHBoxLayout" name="row_1_qhbox_layout">
- <item>
- <widget class="QLabel" name="row_1_label">
- <property name="text">
- <string>Row 1 Text:</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QComboBox" name="row_1_text_combobox"/>
- </item>
- </layout>
- </item>
- <item>
- <layout class="QHBoxLayout" name="row_2_qhbox_layout">
- <item>
- <widget class="QLabel" name="row_2_label">
- <property name="text">
- <string>Row 2 Text:</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QComboBox" name="row_2_text_combobox"/>
- </item>
- </layout>
- </item>
- </layout>
- </item>
- </layout>
- </widget>
+ </widget>
+ </item>
+ <item>
+ <widget class="QComboBox" name="icon_size_combobox"/>
+ </item>
+ </layout>
</item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="RowGroupBox">
+ <property name="title">
+ <string>Row Text</string>
+ </property>
+ <layout class="QHBoxLayout" name="RowHorizontalLayout">
+ <item>
+ <layout class="QVBoxLayout" name="RowVerticalLayout">
<item>
- <spacer name="verticalSpacer">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
+ <layout class="QHBoxLayout" name="row_1_qhbox_layout">
+ <item>
+ <widget class="QLabel" name="row_1_label">
+ <property name="text">
+ <string>Row 1 Text:</string>
</property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>20</width>
- <height>40</height>
- </size>
+ </widget>
+ </item>
+ <item>
+ <widget class="QComboBox" name="row_1_text_combobox"/>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="row_2_qhbox_layout">
+ <item>
+ <widget class="QLabel" name="row_2_label">
+ <property name="text">
+ <string>Row 2 Text:</string>
</property>
- </spacer>
+ </widget>
+ </item>
+ <item>
+ <widget class="QComboBox" name="row_2_text_combobox"/>
+ </item>
+ </layout>
</item>
- </layout>
- </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
</layout>
- </widget>
+ </item>
+ </layout>
+ </widget>
<resources/>
<connections/>
</ui>
diff --git a/src/yuzu/configuration/configure_general.cpp b/src/yuzu/configuration/configure_general.cpp
index 537d6e576..c22742007 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"
@@ -19,8 +23,10 @@ ConfigureGeneral::ConfigureGeneral(QWidget* parent)
this->setConfiguration();
+ connect(ui->toggle_deepscan, &QCheckBox::stateChanged, this,
+ [] { UISettings::values.is_game_list_reload_pending.exchange(true); });
+
ui->use_cpu_jit->setEnabled(!Core::System::GetInstance().IsPoweredOn());
- ui->use_docked_mode->setEnabled(!Core::System::GetInstance().IsPoweredOn());
}
ConfigureGeneral::~ConfigureGeneral() = default;
@@ -38,6 +44,33 @@ 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()};
+ if (!system.IsPoweredOn()) {
+ return;
+ }
+ 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 +78,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..ab5d46492 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("00000000"));
+ });
+
scene = new QGraphicsScene;
ui->current_user_icon->setScene(scene);
@@ -149,6 +161,13 @@ 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), 8, 16, QLatin1Char{'0'}).toUpper();
+ ui->rng_seed_edit->setText(rng_seed);
}
void ConfigureSystem::PopulateUserList() {
@@ -173,7 +192,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 +208,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 +259,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 +269,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 +284,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 +311,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 +338,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..a91580893 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 notr="true">HHHHHHHH</string>
+ </property>
+ <property name="maxLength">
+ <number>8</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/game_list.cpp b/src/yuzu/game_list.cpp
index a5a4aa432..11a8c390b 100644
--- a/src/yuzu/game_list.cpp
+++ b/src/yuzu/game_list.cpp
@@ -215,12 +215,18 @@ GameList::GameList(FileSys::VirtualFilesystem vfs, GMainWindow* parent)
tree_view->setUniformRowHeights(true);
tree_view->setContextMenuPolicy(Qt::CustomContextMenu);
- item_model->insertColumns(0, COLUMN_COUNT);
+ item_model->insertColumns(0, UISettings::values.show_add_ons ? COLUMN_COUNT : COLUMN_COUNT - 1);
item_model->setHeaderData(COLUMN_NAME, Qt::Horizontal, tr("Name"));
item_model->setHeaderData(COLUMN_COMPATIBILITY, Qt::Horizontal, tr("Compatibility"));
- item_model->setHeaderData(COLUMN_ADD_ONS, Qt::Horizontal, tr("Add-ons"));
- item_model->setHeaderData(COLUMN_FILE_TYPE, Qt::Horizontal, tr("File type"));
- item_model->setHeaderData(COLUMN_SIZE, Qt::Horizontal, tr("Size"));
+
+ if (UISettings::values.show_add_ons) {
+ item_model->setHeaderData(COLUMN_ADD_ONS, Qt::Horizontal, tr("Add-ons"));
+ item_model->setHeaderData(COLUMN_FILE_TYPE, Qt::Horizontal, tr("File type"));
+ item_model->setHeaderData(COLUMN_SIZE, Qt::Horizontal, tr("Size"));
+ } else {
+ item_model->setHeaderData(COLUMN_FILE_TYPE - 1, Qt::Horizontal, tr("File type"));
+ item_model->setHeaderData(COLUMN_SIZE - 1, Qt::Horizontal, tr("Size"));
+ }
connect(tree_view, &QTreeView::activated, this, &GameList::ValidateEntry);
connect(tree_view, &QTreeView::customContextMenuRequested, this, &GameList::PopupContextMenu);
@@ -394,6 +400,25 @@ void GameList::PopulateAsync(const QString& dir_path, bool deep_scan) {
}
tree_view->setEnabled(false);
+
+ // Update the columns in case UISettings has changed
+ item_model->removeColumns(0, item_model->columnCount());
+ item_model->insertColumns(0, UISettings::values.show_add_ons ? COLUMN_COUNT : COLUMN_COUNT - 1);
+ item_model->setHeaderData(COLUMN_NAME, Qt::Horizontal, tr("Name"));
+ item_model->setHeaderData(COLUMN_COMPATIBILITY, Qt::Horizontal, tr("Compatibility"));
+
+ if (UISettings::values.show_add_ons) {
+ item_model->setHeaderData(COLUMN_ADD_ONS, Qt::Horizontal, tr("Add-ons"));
+ item_model->setHeaderData(COLUMN_FILE_TYPE, Qt::Horizontal, tr("File type"));
+ item_model->setHeaderData(COLUMN_SIZE, Qt::Horizontal, tr("Size"));
+ } else {
+ item_model->setHeaderData(COLUMN_FILE_TYPE - 1, Qt::Horizontal, tr("File type"));
+ item_model->setHeaderData(COLUMN_SIZE - 1, Qt::Horizontal, tr("Size"));
+ item_model->removeColumns(COLUMN_COUNT - 1, 1);
+ }
+
+ LoadInterfaceLayout();
+
// Delete any rows that might already exist if we're repopulating
item_model->removeRows(0, item_model->rowCount());
diff --git a/src/yuzu/game_list_worker.cpp b/src/yuzu/game_list_worker.cpp
index 3d865a12d..362902e46 100644
--- a/src/yuzu/game_list_worker.cpp
+++ b/src/yuzu/game_list_worker.cpp
@@ -123,17 +123,22 @@ void GameListWorker::AddInstalledTitlesToGameList() {
if (it != compatibility_list.end())
compatibility = it->second.first;
- emit EntryReady({
+ QList<QStandardItem*> list{
new GameListItemPath(
FormatGameName(file->GetFullPath()), icon, QString::fromStdString(name),
QString::fromStdString(Loader::GetFileTypeString(loader->GetFileType())),
program_id),
new GameListItemCompat(compatibility),
- new GameListItem(FormatPatchNameVersions(patch, *loader)),
new GameListItem(
QString::fromStdString(Loader::GetFileTypeString(loader->GetFileType()))),
new GameListItemSize(file->GetSize()),
- });
+ };
+
+ if (UISettings::values.show_add_ons) {
+ list.insert(2, new GameListItem(FormatPatchNameVersions(patch, *loader)));
+ }
+
+ emit EntryReady(list);
}
const auto control_data = cache->ListEntriesFilter(FileSys::TitleType::Application,
@@ -216,18 +221,23 @@ void GameListWorker::AddFstEntriesToGameList(const std::string& dir_path, unsign
if (it != compatibility_list.end())
compatibility = it->second.first;
- emit EntryReady({
+ QList<QStandardItem*> list{
new GameListItemPath(
FormatGameName(physical_name), icon, QString::fromStdString(name),
QString::fromStdString(Loader::GetFileTypeString(loader->GetFileType())),
program_id),
new GameListItemCompat(compatibility),
new GameListItem(
- FormatPatchNameVersions(patch, *loader, loader->IsRomFSUpdatable())),
- new GameListItem(
QString::fromStdString(Loader::GetFileTypeString(loader->GetFileType()))),
new GameListItemSize(FileUtil::GetSize(physical_name)),
- });
+ };
+
+ if (UISettings::values.show_add_ons) {
+ list.insert(2, new GameListItem(FormatPatchNameVersions(
+ patch, *loader, loader->IsRomFSUpdatable())));
+ }
+
+ emit EntryReady(std::move(list));
} else if (is_dir && recursion > 0) {
watch_list.append(QString::fromStdString(physical_name));
AddFstEntriesToGameList(physical_name, recursion - 1);
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index b5bfa6741..4b969119c 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -12,7 +12,7 @@
#include "core/file_sys/vfs_real.h"
#include "core/hle/service/acc/profile_manager.h"
-// These are wrappers to avoid the calls to CreateDirectory and CreateFile becuase of the Windows
+// These are wrappers to avoid the calls to CreateDirectory and CreateFile because of the Windows
// defines.
static FileSys::VirtualDir VfsFilesystemCreateDirectoryWrapper(
const FileSys::VirtualFilesystem& vfs, const std::string& path, FileSys::Mode mode) {
@@ -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()
@@ -305,6 +308,8 @@ void GMainWindow::InitializeHotkeys() {
Qt::ApplicationShortcut);
hotkey_registry.RegisterHotkey("Main Window", "Decrease Speed Limit", QKeySequence("-"),
Qt::ApplicationShortcut);
+ hotkey_registry.RegisterHotkey("Main Window", "Load Amiibo", QKeySequence(Qt::Key_F2),
+ Qt::ApplicationShortcut);
hotkey_registry.LoadHotkeys();
connect(hotkey_registry.GetHotkey("Main Window", "Load File", this), &QShortcut::activated,
@@ -358,6 +363,12 @@ void GMainWindow::InitializeHotkeys() {
UpdateStatusBar();
}
});
+ connect(hotkey_registry.GetHotkey("Main Window", "Load Amiibo", this), &QShortcut::activated,
+ this, [&] {
+ if (ui.action_Load_Amiibo->isEnabled()) {
+ OnLoadAmiibo();
+ }
+ });
}
void GMainWindow::SetDefaultUIGeometry() {
@@ -454,6 +465,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 +798,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 +941,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);
@@ -1328,7 +1341,13 @@ void GMainWindow::OnConfigure() {
UpdateUITheme();
if (UISettings::values.enable_discord_presence != old_discord_presence)
SetDiscordEnabled(UISettings::values.enable_discord_presence);
- game_list->PopulateAsync(UISettings::values.gamedir, UISettings::values.gamedir_deepscan);
+
+ const auto reload = UISettings::values.is_game_list_reload_pending.exchange(false);
+ if (reload) {
+ game_list->PopulateAsync(UISettings::values.gamedir,
+ UISettings::values.gamedir_deepscan);
+ }
+
config->Save();
}
}
@@ -1374,6 +1393,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 +1556,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 +1584,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 +1611,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 +1636,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..75e96387f 100644
--- a/src/yuzu/main.ui
+++ b/src/yuzu/main.ui
@@ -70,6 +70,8 @@
<addaction name="separator"/>
<addaction name="action_Load_Amiibo"/>
<addaction name="separator"/>
+ <addaction name="action_Open_yuzu_Folder"/>
+ <addaction name="separator"/>
<addaction name="action_Exit"/>
</widget>
<widget class="QMenu" name="menu_Emulation">
@@ -277,6 +279,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/ui_settings.h b/src/yuzu/ui_settings.h
index 2e617d52a..e80aebc0a 100644
--- a/src/yuzu/ui_settings.h
+++ b/src/yuzu/ui_settings.h
@@ -5,6 +5,7 @@
#pragma once
#include <array>
+#include <atomic>
#include <vector>
#include <QByteArray>
#include <QString>
@@ -59,9 +60,11 @@ struct Values {
// Game List
bool show_unknown;
+ bool show_add_ons;
uint32_t icon_size;
uint8_t row_1_text_id;
uint8_t row_2_text_id;
+ std::atomic_bool is_game_list_reload_pending{false};
};
extern Values values;
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;
+};