diff options
Diffstat (limited to 'src/yuzu')
-rw-r--r-- | src/yuzu/configuration/shared_translation.cpp | 10 | ||||
-rw-r--r-- | src/yuzu/main.cpp | 193 | ||||
-rw-r--r-- | src/yuzu/main.h | 1 | ||||
-rw-r--r-- | src/yuzu/main.ui | 8 |
4 files changed, 153 insertions, 59 deletions
diff --git a/src/yuzu/configuration/shared_translation.cpp b/src/yuzu/configuration/shared_translation.cpp index d138b53c8..0549e8ae4 100644 --- a/src/yuzu/configuration/shared_translation.cpp +++ b/src/yuzu/configuration/shared_translation.cpp @@ -164,6 +164,11 @@ std::unique_ptr<TranslationMap> InitializeTranslations(QWidget* parent) { "the emulator to decompress to an intermediate format any card supports, RGBA8.\n" "This option recompresses RGBA8 to either the BC1 or BC3 format, saving VRAM but " "negatively affecting image quality.")); + INSERT(Settings, vram_usage_mode, tr("VRAM Usage Mode:"), + tr("Selects whether the emulator should prefer to conserve memory or make maximum usage " + "of available video memory for performance. Has no effect on integrated graphics. " + "Aggressive mode may severely impact the performance of other applications such as " + "recording software.")); INSERT( Settings, vsync_mode, tr("VSync Mode:"), tr("FIFO (VSync) does not drop frames or exhibit tearing but is limited by the screen " @@ -315,6 +320,11 @@ std::unique_ptr<ComboboxTranslationMap> ComboboxEnumeration(QWidget* parent) { PAIR(AstcRecompression, Bc1, tr("BC1 (Low quality)")), PAIR(AstcRecompression, Bc3, tr("BC3 (Medium quality)")), }}); + translations->insert({Settings::EnumMetadata<Settings::VramUsageMode>::Index(), + { + PAIR(VramUsageMode, Conservative, tr("Conservative")), + PAIR(VramUsageMode, Aggressive, tr("Aggressive")), + }}); translations->insert({Settings::EnumMetadata<Settings::RendererBackend>::Index(), { #ifdef HAS_OPENGL diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 9d63b5935..c0c0a19b8 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -1604,6 +1604,7 @@ void GMainWindow::ConnectMenuEvents() { connect_menu(ui->action_Open_yuzu_Folder, &GMainWindow::OnOpenYuzuFolder); connect_menu(ui->action_Verify_installed_contents, &GMainWindow::OnVerifyInstalledContents); connect_menu(ui->action_Install_Firmware, &GMainWindow::OnInstallFirmware); + connect_menu(ui->action_Install_Keys, &GMainWindow::OnInstallDecryptionKeys); connect_menu(ui->action_About, &GMainWindow::OnAbout); } @@ -1633,6 +1634,7 @@ void GMainWindow::UpdateMenuState() { } ui->action_Install_Firmware->setEnabled(!emulation_running); + ui->action_Install_Keys->setEnabled(!emulation_running); for (QAction* action : applet_actions) { action->setEnabled(is_firmware_available && !emulation_running); @@ -3008,9 +3010,6 @@ bool GMainWindow::MakeShortcutIcoPath(const u64 program_id, const std::string_vi void GMainWindow::OnGameListCreateShortcut(u64 program_id, const std::string& game_path, GameListShortcutTarget target) { - std::string game_title; - QString qt_game_title; - std::filesystem::path out_icon_path; // Get path to yuzu executable const QStringList args = QApplication::arguments(); std::filesystem::path yuzu_command = args[0].toStdString(); @@ -3027,48 +3026,51 @@ void GMainWindow::OnGameListCreateShortcut(u64 program_id, const std::string& ga shortcut_path = QStandardPaths::writableLocation(QStandardPaths::ApplicationsLocation).toStdString(); } - // Icon path and title - if (std::filesystem::exists(shortcut_path)) { - // Get title from game file - const FileSys::PatchManager pm{program_id, system->GetFileSystemController(), - system->GetContentProvider()}; - const auto control = pm.GetControlMetadata(); - const auto loader = - Loader::GetLoader(*system, vfs->OpenFile(game_path, FileSys::OpenMode::Read)); - game_title = fmt::format("{:016X}", program_id); - if (control.first != nullptr) { - game_title = control.first->GetApplicationName(); - } else { - loader->ReadTitle(game_title); - } - // Delete illegal characters from title - const std::string illegal_chars = "<>:\"/\\|?*."; - for (auto it = game_title.rbegin(); it != game_title.rend(); ++it) { - if (illegal_chars.find(*it) != std::string::npos) { - game_title.erase(it.base() - 1); - } - } - qt_game_title = QString::fromStdString(game_title); - // Get icon from game file - std::vector<u8> icon_image_file{}; - if (control.second != nullptr) { - icon_image_file = control.second->ReadAllBytes(); - } else if (loader->ReadIcon(icon_image_file) != Loader::ResultStatus::Success) { - LOG_WARNING(Frontend, "Could not read icon from {:s}", game_path); + + if (!std::filesystem::exists(shortcut_path)) { + GMainWindow::CreateShortcutMessagesGUI( + this, GMainWindow::CREATE_SHORTCUT_MSGBOX_ERROR, + QString::fromStdString(shortcut_path.generic_string())); + LOG_ERROR(Frontend, "Invalid shortcut target {}", shortcut_path.generic_string()); + return; + } + + // Get title from game file + const FileSys::PatchManager pm{program_id, system->GetFileSystemController(), + system->GetContentProvider()}; + const auto control = pm.GetControlMetadata(); + const auto loader = + Loader::GetLoader(*system, vfs->OpenFile(game_path, FileSys::OpenMode::Read)); + std::string game_title = fmt::format("{:016X}", program_id); + if (control.first != nullptr) { + game_title = control.first->GetApplicationName(); + } else { + loader->ReadTitle(game_title); + } + // Delete illegal characters from title + const std::string illegal_chars = "<>:\"/\\|?*."; + for (auto it = game_title.rbegin(); it != game_title.rend(); ++it) { + if (illegal_chars.find(*it) != std::string::npos) { + game_title.erase(it.base() - 1); } - QImage icon_data = - QImage::fromData(icon_image_file.data(), static_cast<int>(icon_image_file.size())); - if (GMainWindow::MakeShortcutIcoPath(program_id, game_title, out_icon_path)) { - if (!SaveIconToFile(out_icon_path, icon_data)) { - LOG_ERROR(Frontend, "Could not write icon to file"); - } + } + const QString qt_game_title = QString::fromStdString(game_title); + // Get icon from game file + std::vector<u8> icon_image_file{}; + if (control.second != nullptr) { + icon_image_file = control.second->ReadAllBytes(); + } else if (loader->ReadIcon(icon_image_file) != Loader::ResultStatus::Success) { + LOG_WARNING(Frontend, "Could not read icon from {:s}", game_path); + } + QImage icon_data = + QImage::fromData(icon_image_file.data(), static_cast<int>(icon_image_file.size())); + std::filesystem::path out_icon_path; + if (GMainWindow::MakeShortcutIcoPath(program_id, game_title, out_icon_path)) { + if (!SaveIconToFile(out_icon_path, icon_data)) { + LOG_ERROR(Frontend, "Could not write icon to file"); } - } else { - GMainWindow::CreateShortcutMessagesGUI(this, GMainWindow::CREATE_SHORTCUT_MSGBOX_ERROR, - qt_game_title); - LOG_ERROR(Frontend, "Invalid shortcut target"); - return; } + #if defined(__linux__) // Special case for AppImages // Warn once if we are making a shortcut to a volatile AppImage @@ -4169,9 +4171,8 @@ void GMainWindow::OnInstallFirmware() { return; } - QString firmware_source_location = - QFileDialog::getExistingDirectory(this, tr("Select Dumped Firmware Source Location"), - QString::fromStdString(""), QFileDialog::ShowDirsOnly); + const QString firmware_source_location = QFileDialog::getExistingDirectory( + this, tr("Select Dumped Firmware Source Location"), {}, QFileDialog::ShowDirsOnly); if (firmware_source_location.isEmpty()) { return; } @@ -4202,8 +4203,9 @@ void GMainWindow::OnInstallFirmware() { std::vector<std::filesystem::path> out; const Common::FS::DirEntryCallable callback = [&out](const std::filesystem::directory_entry& entry) { - if (entry.path().has_extension() && entry.path().extension() == ".nca") + if (entry.path().has_extension() && entry.path().extension() == ".nca") { out.emplace_back(entry.path()); + } return true; }; @@ -4235,7 +4237,6 @@ void GMainWindow::OnInstallFirmware() { auto firmware_vdir = sysnand_content_vdir->GetDirectoryRelative("registered"); bool success = true; - bool cancelled = false; int i = 0; for (const auto& firmware_src_path : out) { i++; @@ -4250,24 +4251,22 @@ void GMainWindow::OnInstallFirmware() { success = false; } - if (QtProgressCallback(100, 20 + (int)(((float)(i) / (float)out.size()) * 70.0))) { - success = false; - cancelled = true; - break; + if (QtProgressCallback( + 100, 20 + static_cast<int>(((i) / static_cast<float>(out.size())) * 70.0))) { + progress.close(); + QMessageBox::warning( + this, tr("Firmware install failed"), + tr("Firmware installation cancelled, firmware may be in bad state, " + "restart yuzu or re-install firmware.")); + return; } } - if (!success && !cancelled) { + if (!success) { progress.close(); QMessageBox::critical(this, tr("Firmware install failed"), tr("One or more firmware files failed to copy into NAND.")); return; - } else if (cancelled) { - progress.close(); - QMessageBox::warning(this, tr("Firmware install failed"), - tr("Firmware installation cancelled, firmware may be in bad state, " - "restart yuzu or re-install firmware.")); - return; } // Re-scan VFS for the newly placed firmware files. @@ -4295,6 +4294,84 @@ void GMainWindow::OnInstallFirmware() { OnCheckFirmwareDecryption(); } +void GMainWindow::OnInstallDecryptionKeys() { + // Don't do this while emulation is running. + if (emu_thread != nullptr && emu_thread->IsRunning()) { + return; + } + + const QString key_source_location = QFileDialog::getOpenFileName( + this, tr("Select Dumped Keys Location"), {}, QStringLiteral("prod.keys (prod.keys)"), {}, + QFileDialog::ReadOnly); + if (key_source_location.isEmpty()) { + return; + } + + // Verify that it contains prod.keys, title.keys and optionally, key_retail.bin + LOG_INFO(Frontend, "Installing key files from {}", key_source_location.toStdString()); + + const std::filesystem::path prod_key_path = key_source_location.toStdString(); + const std::filesystem::path key_source_path = prod_key_path.parent_path(); + if (!Common::FS::IsDir(key_source_path)) { + return; + } + + bool prod_keys_found = false; + std::vector<std::filesystem::path> source_key_files; + + if (Common::FS::Exists(prod_key_path)) { + prod_keys_found = true; + source_key_files.emplace_back(prod_key_path); + } + + if (Common::FS::Exists(key_source_path / "title.keys")) { + source_key_files.emplace_back(key_source_path / "title.keys"); + } + + if (Common::FS::Exists(key_source_path / "key_retail.bin")) { + source_key_files.emplace_back(key_source_path / "key_retail.bin"); + } + + // There should be at least prod.keys. + if (source_key_files.empty() || !prod_keys_found) { + QMessageBox::warning(this, tr("Decryption Keys install failed"), + tr("prod.keys is a required decryption key file.")); + return; + } + + const auto yuzu_keys_dir = Common::FS::GetYuzuPath(Common::FS::YuzuPath::KeysDir); + for (auto key_file : source_key_files) { + std::filesystem::path destination_key_file = yuzu_keys_dir / key_file.filename(); + if (!std::filesystem::copy_file(key_file, destination_key_file, + std::filesystem::copy_options::overwrite_existing)) { + LOG_ERROR(Frontend, "Failed to copy file {} to {}", key_file.string(), + destination_key_file.string()); + QMessageBox::critical(this, tr("Decryption Keys install failed"), + tr("One or more keys failed to copy.")); + return; + } + } + + // Reinitialize the key manager, re-read the vfs (for update/dlc files), + // and re-populate the game list in the UI if the user has already added + // game folders. + Core::Crypto::KeyManager::Instance().ReloadKeys(); + system->GetFileSystemController().CreateFactories(*vfs); + game_list->PopulateAsync(UISettings::values.game_dirs); + + if (ContentManager::AreKeysPresent()) { + QMessageBox::information(this, tr("Decryption Keys install succeeded"), + tr("Decryption Keys were successfully installed")); + } else { + QMessageBox::critical( + this, tr("Decryption Keys install failed"), + tr("Decryption Keys failed to initialize. Check that your dumping tools are " + "up to date and re-dump keys.")); + } + + OnCheckFirmwareDecryption(); +} + void GMainWindow::OnAbout() { AboutDialog aboutDialog(this); aboutDialog.exec(); diff --git a/src/yuzu/main.h b/src/yuzu/main.h index 1f0e35c67..fce643f3f 100644 --- a/src/yuzu/main.h +++ b/src/yuzu/main.h @@ -381,6 +381,7 @@ private slots: void OnOpenYuzuFolder(); void OnVerifyInstalledContents(); void OnInstallFirmware(); + void OnInstallDecryptionKeys(); void OnAbout(); void OnToggleFilterBar(); void OnToggleStatusBar(); diff --git a/src/yuzu/main.ui b/src/yuzu/main.ui index 6ff444a22..85dc1f2f6 100644 --- a/src/yuzu/main.ui +++ b/src/yuzu/main.ui @@ -165,8 +165,9 @@ <addaction name="separator"/> <addaction name="action_Configure_Tas"/> </widget> - <addaction name="action_Verify_installed_contents"/> + <addaction name="action_Install_Keys"/> <addaction name="action_Install_Firmware"/> + <addaction name="action_Verify_installed_contents"/> <addaction name="separator"/> <addaction name="menu_cabinet_applet"/> <addaction name="action_Load_Album"/> @@ -469,6 +470,11 @@ <string>Install Firmware</string> </property> </action> + <action name="action_Install_Keys"> + <property name="text"> + <string>Install Decryption Keys</string> + </property> + </action> </widget> <resources> <include location="yuzu.qrc"/> |