summaryrefslogtreecommitdiff
path: root/src/yuzu
diff options
context:
space:
mode:
Diffstat (limited to 'src/yuzu')
-rw-r--r--src/yuzu/configuration/configure_audio.cpp3
-rw-r--r--src/yuzu/configuration/shared_translation.cpp3
-rw-r--r--src/yuzu/main.cpp127
-rw-r--r--src/yuzu/main.h9
-rw-r--r--src/yuzu/main.ui39
-rw-r--r--src/yuzu/uisettings.h2
6 files changed, 163 insertions, 20 deletions
diff --git a/src/yuzu/configuration/configure_audio.cpp b/src/yuzu/configuration/configure_audio.cpp
index 9ccfb2435..81dd51ad3 100644
--- a/src/yuzu/configuration/configure_audio.cpp
+++ b/src/yuzu/configuration/configure_audio.cpp
@@ -42,6 +42,9 @@ void ConfigureAudio::Setup(const ConfigurationShared::Builder& builder) {
for (auto* setting : Settings::values.linkage.by_category[category]) {
settings.push_back(setting);
}
+ for (auto* setting : UISettings::values.linkage.by_category[category]) {
+ settings.push_back(setting);
+ }
};
push(Settings::Category::Audio);
diff --git a/src/yuzu/configuration/shared_translation.cpp b/src/yuzu/configuration/shared_translation.cpp
index 276bdbaba..a4e8af1b4 100644
--- a/src/yuzu/configuration/shared_translation.cpp
+++ b/src/yuzu/configuration/shared_translation.cpp
@@ -29,9 +29,10 @@ std::unique_ptr<TranslationMap> InitializeTranslations(QWidget* parent) {
INSERT(Settings, sink_id, "Output Engine:", "");
INSERT(Settings, audio_output_device_id, "Output Device:", "");
INSERT(Settings, audio_input_device_id, "Input Device:", "");
- INSERT(Settings, audio_muted, "Mute audio when in background", "");
+ INSERT(Settings, audio_muted, "Mute audio", "");
INSERT(Settings, volume, "Volume:", "");
INSERT(Settings, dump_audio_commands, "", "");
+ INSERT(UISettings, mute_when_in_background, "Mute audio when in background", "");
// Core
INSERT(Settings, use_multi_core, "Multicore CPU Emulation", "");
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index d32aa9615..1753fec12 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -18,6 +18,8 @@
#include <sys/socket.h>
#endif
+#include <boost/container/flat_set.hpp>
+
// VFS includes must be before glad as they will conflict with Windows file api, which uses defines.
#include "applets/qt_amiibo_settings.h"
#include "applets/qt_controller.h"
@@ -1445,6 +1447,7 @@ void GMainWindow::OnAppFocusStateChanged(Qt::ApplicationState state) {
Settings::values.audio_muted = false;
auto_muted = false;
}
+ UpdateVolumeUI();
}
}
@@ -1551,6 +1554,15 @@ void GMainWindow::ConnectMenuEvents() {
// Tools
connect_menu(ui->action_Rederive, std::bind(&GMainWindow::OnReinitializeKeys, this,
ReinitializeKeyBehavior::Warning));
+ connect_menu(ui->action_Load_Cabinet_Nickname_Owner,
+ [this]() { OnCabinet(Service::NFP::CabinetMode::StartNicknameAndOwnerSettings); });
+ connect_menu(ui->action_Load_Cabinet_Eraser,
+ [this]() { OnCabinet(Service::NFP::CabinetMode::StartGameDataEraser); });
+ connect_menu(ui->action_Load_Cabinet_Restorer,
+ [this]() { OnCabinet(Service::NFP::CabinetMode::StartRestorer); });
+ connect_menu(ui->action_Load_Cabinet_Formatter,
+ [this]() { OnCabinet(Service::NFP::CabinetMode::StartFormatter); });
+ connect_menu(ui->action_Load_Mii_Edit, &GMainWindow::OnMiiEdit);
connect_menu(ui->action_Capture_Screenshot, &GMainWindow::OnCaptureScreenshot);
// TAS
@@ -1567,6 +1579,7 @@ void GMainWindow::ConnectMenuEvents() {
void GMainWindow::UpdateMenuState() {
const bool is_paused = emu_thread == nullptr || !emu_thread->IsRunning();
+ const bool is_firmware_available = CheckFirmwarePresence();
const std::array running_actions{
ui->action_Stop,
@@ -1577,10 +1590,22 @@ void GMainWindow::UpdateMenuState() {
ui->action_Pause,
};
+ const std::array applet_actions{
+ ui->action_Load_Cabinet_Nickname_Owner,
+ ui->action_Load_Cabinet_Eraser,
+ ui->action_Load_Cabinet_Restorer,
+ ui->action_Load_Cabinet_Formatter,
+ ui->action_Load_Mii_Edit,
+ };
+
for (QAction* action : running_actions) {
action->setEnabled(emulation_running);
}
+ for (QAction* action : applet_actions) {
+ action->setEnabled(is_firmware_available && !emulation_running);
+ }
+
ui->action_Capture_Screenshot->setEnabled(emulation_running && !is_paused);
if (emulation_running && is_paused) {
@@ -2100,6 +2125,8 @@ void GMainWindow::OnEmulationStopped() {
OnTasStateChanged();
render_window->FinalizeCamera();
+ system->GetAppletManager().SetCurrentAppletId(Service::AM::Applets::AppletId::None);
+
// Enable all controllers
system->HIDCore().SetSupportedStyleTag({Core::HID::NpadStyleSet::All});
@@ -3110,10 +3137,9 @@ void GMainWindow::OnMenuInstallToNAND() {
QFuture<InstallResult> future;
InstallResult result;
- if (file.endsWith(QStringLiteral("xci"), Qt::CaseInsensitive) ||
- file.endsWith(QStringLiteral("nsp"), Qt::CaseInsensitive)) {
+ if (file.endsWith(QStringLiteral("nsp"), Qt::CaseInsensitive)) {
- future = QtConcurrent::run([this, &file] { return InstallNSPXCI(file); });
+ future = QtConcurrent::run([this, &file] { return InstallNSP(file); });
while (!future.isFinished()) {
QCoreApplication::processEvents();
@@ -3172,7 +3198,7 @@ void GMainWindow::OnMenuInstallToNAND() {
ui->action_Install_File_NAND->setEnabled(true);
}
-InstallResult GMainWindow::InstallNSPXCI(const QString& filename) {
+InstallResult GMainWindow::InstallNSP(const QString& filename) {
const auto qt_raw_copy = [this](const FileSys::VirtualFile& src,
const FileSys::VirtualFile& dest, std::size_t block_size) {
if (src == nullptr || dest == nullptr) {
@@ -3206,9 +3232,7 @@ InstallResult GMainWindow::InstallNSPXCI(const QString& filename) {
return InstallResult::Failure;
}
} else {
- const auto xci = std::make_shared<FileSys::XCI>(
- vfs->OpenFile(filename.toStdString(), FileSys::Mode::Read));
- nsp = xci->GetSecurePartitionNSP();
+ return InstallResult::Failure;
}
if (nsp->GetStatus() != Loader::ResultStatus::Success) {
@@ -4134,6 +4158,53 @@ void GMainWindow::OnToggleStatusBar() {
statusBar()->setVisible(ui->action_Show_Status_Bar->isChecked());
}
+void GMainWindow::OnCabinet(Service::NFP::CabinetMode mode) {
+ constexpr u64 CabinetId = 0x0100000000001002ull;
+ auto bis_system = system->GetFileSystemController().GetSystemNANDContents();
+ if (!bis_system) {
+ QMessageBox::warning(this, tr("No firmware available"),
+ tr("Please install the firmware to use the Cabinet applet."));
+ return;
+ }
+
+ auto cabinet_nca = bis_system->GetEntry(CabinetId, FileSys::ContentRecordType::Program);
+ if (!cabinet_nca) {
+ QMessageBox::warning(this, tr("Cabinet Applet"),
+ tr("Cabinet applet is not available. Please reinstall firmware."));
+ return;
+ }
+
+ system->GetAppletManager().SetCurrentAppletId(Service::AM::Applets::AppletId::Cabinet);
+ system->GetAppletManager().SetCabinetMode(mode);
+
+ const auto filename = QString::fromStdString(cabinet_nca->GetFullPath());
+ UISettings::values.roms_path = QFileInfo(filename).path();
+ BootGame(filename);
+}
+
+void GMainWindow::OnMiiEdit() {
+ constexpr u64 MiiEditId = 0x0100000000001009ull;
+ auto bis_system = system->GetFileSystemController().GetSystemNANDContents();
+ if (!bis_system) {
+ QMessageBox::warning(this, tr("No firmware available"),
+ tr("Please install the firmware to use the Mii editor."));
+ return;
+ }
+
+ auto mii_applet_nca = bis_system->GetEntry(MiiEditId, FileSys::ContentRecordType::Program);
+ if (!mii_applet_nca) {
+ QMessageBox::warning(this, tr("Mii Edit Applet"),
+ tr("Mii editor is not available. Please reinstall firmware."));
+ return;
+ }
+
+ system->GetAppletManager().SetCurrentAppletId(Service::AM::Applets::AppletId::MiiEdit);
+
+ const auto filename = QString::fromStdString((mii_applet_nca->GetFullPath()));
+ UISettings::values.roms_path = QFileInfo(filename).path();
+ BootGame(filename);
+}
+
void GMainWindow::OnCaptureScreenshot() {
if (emu_thread == nullptr || !emu_thread->IsRunning()) {
return;
@@ -4540,6 +4611,8 @@ void GMainWindow::OnReinitializeKeys(ReinitializeKeyBehavior behavior) {
if (behavior == ReinitializeKeyBehavior::Warning) {
game_list->PopulateAsync(UISettings::values.game_dirs);
}
+
+ UpdateMenuState();
}
bool GMainWindow::CheckSystemArchiveDecryption() {
@@ -4561,10 +4634,26 @@ bool GMainWindow::CheckSystemArchiveDecryption() {
return mii_nca->GetRomFS().get() != nullptr;
}
+bool GMainWindow::CheckFirmwarePresence() {
+ constexpr u64 MiiEditId = 0x0100000000001009ull;
+
+ auto bis_system = system->GetFileSystemController().GetSystemNANDContents();
+ if (!bis_system) {
+ return false;
+ }
+
+ auto mii_applet_nca = bis_system->GetEntry(MiiEditId, FileSys::ContentRecordType::Program);
+ if (!mii_applet_nca) {
+ return false;
+ }
+
+ return true;
+}
+
bool GMainWindow::SelectRomFSDumpTarget(const FileSys::ContentProvider& installed, u64 program_id,
u64* selected_title_id, u8* selected_content_record_type) {
- using ContentInfo = std::pair<FileSys::TitleType, FileSys::ContentRecordType>;
- boost::container::flat_map<u64, ContentInfo> available_title_ids;
+ using ContentInfo = std::tuple<u64, FileSys::TitleType, FileSys::ContentRecordType>;
+ boost::container::flat_set<ContentInfo> available_title_ids;
const auto RetrieveEntries = [&](FileSys::TitleType title_type,
FileSys::ContentRecordType record_type) {
@@ -4572,12 +4661,14 @@ bool GMainWindow::SelectRomFSDumpTarget(const FileSys::ContentProvider& installe
for (const auto& entry : entries) {
if (FileSys::GetBaseTitleID(entry.title_id) == program_id &&
installed.GetEntry(entry)->GetStatus() == Loader::ResultStatus::Success) {
- available_title_ids[entry.title_id] = {title_type, record_type};
+ available_title_ids.insert({entry.title_id, title_type, record_type});
}
}
};
RetrieveEntries(FileSys::TitleType::Application, FileSys::ContentRecordType::Program);
+ RetrieveEntries(FileSys::TitleType::Application, FileSys::ContentRecordType::HtmlDocument);
+ RetrieveEntries(FileSys::TitleType::Application, FileSys::ContentRecordType::LegalInformation);
RetrieveEntries(FileSys::TitleType::AOC, FileSys::ContentRecordType::Data);
if (available_title_ids.empty()) {
@@ -4588,10 +4679,14 @@ bool GMainWindow::SelectRomFSDumpTarget(const FileSys::ContentProvider& installe
if (available_title_ids.size() > 1) {
QStringList list;
- for (auto& [title_id, content_info] : available_title_ids) {
+ for (auto& [title_id, title_type, record_type] : available_title_ids) {
const auto hex_title_id = QString::fromStdString(fmt::format("{:X}", title_id));
- if (content_info.first == FileSys::TitleType::Application) {
- list.push_back(QStringLiteral("Application [%1]").arg(hex_title_id));
+ if (record_type == FileSys::ContentRecordType::Program) {
+ list.push_back(QStringLiteral("Program [%1]").arg(hex_title_id));
+ } else if (record_type == FileSys::ContentRecordType::HtmlDocument) {
+ list.push_back(QStringLiteral("HTML document [%1]").arg(hex_title_id));
+ } else if (record_type == FileSys::ContentRecordType::LegalInformation) {
+ list.push_back(QStringLiteral("Legal information [%1]").arg(hex_title_id));
} else {
list.push_back(
QStringLiteral("DLC %1 [%2]").arg(title_id & 0x7FF).arg(hex_title_id));
@@ -4609,9 +4704,9 @@ bool GMainWindow::SelectRomFSDumpTarget(const FileSys::ContentProvider& installe
title_index = list.indexOf(res);
}
- const auto selected_info = available_title_ids.nth(title_index);
- *selected_title_id = selected_info->first;
- *selected_content_record_type = static_cast<u8>(selected_info->second.second);
+ const auto& [title_id, title_type, record_type] = *available_title_ids.nth(title_index);
+ *selected_title_id = title_id;
+ *selected_content_record_type = static_cast<u8>(record_type);
return true;
}
diff --git a/src/yuzu/main.h b/src/yuzu/main.h
index cf191f698..52028234c 100644
--- a/src/yuzu/main.h
+++ b/src/yuzu/main.h
@@ -102,6 +102,10 @@ namespace Service::NFC {
class NfcDevice;
} // namespace Service::NFC
+namespace Service::NFP {
+enum class CabinetMode : u8;
+} // namespace Service::NFP
+
namespace Ui {
class MainWindow;
}
@@ -365,6 +369,8 @@ private slots:
void ResetWindowSize720();
void ResetWindowSize900();
void ResetWindowSize1080();
+ void OnCabinet(Service::NFP::CabinetMode mode);
+ void OnMiiEdit();
void OnCaptureScreenshot();
void OnReinitializeKeys(ReinitializeKeyBehavior behavior);
void OnLanguageChanged(const QString& locale);
@@ -386,7 +392,7 @@ private:
void RemoveCacheStorage(u64 program_id);
bool SelectRomFSDumpTarget(const FileSys::ContentProvider&, u64 program_id,
u64* selected_title_id, u8* selected_content_record_type);
- InstallResult InstallNSPXCI(const QString& filename);
+ InstallResult InstallNSP(const QString& filename);
InstallResult InstallNCA(const QString& filename);
void MigrateConfigFiles();
void UpdateWindowTitle(std::string_view title_name = {}, std::string_view title_version = {},
@@ -409,6 +415,7 @@ private:
void OpenPerGameConfiguration(u64 title_id, const std::string& file_name);
bool CheckDarkMode();
bool CheckSystemArchiveDecryption();
+ bool CheckFirmwarePresence();
void ConfigureFilesystemProvider(const std::string& filepath);
QString GetTasStateDescription() const;
diff --git a/src/yuzu/main.ui b/src/yuzu/main.ui
index e54d7d75d..31c3de9ef 100644
--- a/src/yuzu/main.ui
+++ b/src/yuzu/main.ui
@@ -137,6 +137,15 @@
<property name="title">
<string>&amp;Tools</string>
</property>
+ <widget class="QMenu" name="menu_cabinet_applet">
+ <property name="title">
+ <string>&amp;Amiibo</string>
+ </property>
+ <addaction name="action_Load_Cabinet_Nickname_Owner"/>
+ <addaction name="action_Load_Cabinet_Eraser"/>
+ <addaction name="action_Load_Cabinet_Restorer"/>
+ <addaction name="action_Load_Cabinet_Formatter"/>
+ </widget>
<widget class="QMenu" name="menuTAS">
<property name="title">
<string>&amp;TAS</string>
@@ -150,6 +159,9 @@
<addaction name="action_Rederive"/>
<addaction name="action_Verify_installed_contents"/>
<addaction name="separator"/>
+ <addaction name="menu_cabinet_applet"/>
+ <addaction name="action_Load_Mii_Edit"/>
+ <addaction name="separator"/>
<addaction name="action_Capture_Screenshot"/>
<addaction name="menuTAS"/>
</widget>
@@ -217,7 +229,7 @@
</action>
<action name="action_Verify_installed_contents">
<property name="text">
- <string>Verify installed contents</string>
+ <string>&amp;Verify Installed Contents</string>
</property>
</action>
<action name="action_About">
@@ -368,6 +380,31 @@
<string>&amp;Capture Screenshot</string>
</property>
</action>
+ <action name="action_Load_Cabinet_Nickname_Owner">
+ <property name="text">
+ <string>&amp;Set Nickname and Owner</string>
+ </property>
+ </action>
+ <action name="action_Load_Cabinet_Eraser">
+ <property name="text">
+ <string>&amp;Delete Game Data</string>
+ </property>
+ </action>
+ <action name="action_Load_Cabinet_Restorer">
+ <property name="text">
+ <string>&amp;Restore Amiibo</string>
+ </property>
+ </action>
+ <action name="action_Load_Cabinet_Formatter">
+ <property name="text">
+ <string>&amp;Format Amiibo</string>
+ </property>
+ </action>
+ <action name="action_Load_Mii_Edit">
+ <property name="text">
+ <string>Open &amp;Mii Editor</string>
+ </property>
+ </action>
<action name="action_Configure_Tas">
<property name="text">
<string>&amp;Configure TAS...</string>
diff --git a/src/yuzu/uisettings.h b/src/yuzu/uisettings.h
index 8efd63f31..8a2caa9dd 100644
--- a/src/yuzu/uisettings.h
+++ b/src/yuzu/uisettings.h
@@ -103,7 +103,7 @@ struct Values {
true,
true};
Setting<bool> mute_when_in_background{
- linkage, false, "muteWhenInBackground", Category::Ui, Settings::Specialization::Default,
+ linkage, false, "muteWhenInBackground", Category::Audio, Settings::Specialization::Default,
true, true};
Setting<bool> hide_mouse{
linkage, true, "hideInactiveMouse", Category::UiGeneral, Settings::Specialization::Default,