diff options
Diffstat (limited to 'src/yuzu')
| -rw-r--r-- | src/yuzu/configuration/qt_config.cpp | 1 | ||||
| -rw-r--r-- | src/yuzu/main.cpp | 143 | ||||
| -rw-r--r-- | src/yuzu/main.h | 1 | ||||
| -rw-r--r-- | src/yuzu/main.ui | 18 | 
4 files changed, 161 insertions, 2 deletions
| diff --git a/src/yuzu/configuration/qt_config.cpp b/src/yuzu/configuration/qt_config.cpp index 1051031f2..37951b9c8 100644 --- a/src/yuzu/configuration/qt_config.cpp +++ b/src/yuzu/configuration/qt_config.cpp @@ -90,6 +90,7 @@ void QtConfig::ReadQtPlayerValues(const std::size_t player_index) {          if (profile_name.empty()) {              // Use the global input config              player = Settings::values.players.GetValue(true)[player_index]; +            player.profile_name = "";              return;          }      } diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index dfa50006a..0d16bfd65 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -1603,6 +1603,7 @@ void GMainWindow::ConnectMenuEvents() {      // Help      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_About, &GMainWindow::OnAbout);  } @@ -1631,6 +1632,8 @@ void GMainWindow::UpdateMenuState() {          action->setEnabled(emulation_running);      } +    ui->action_Install_Firmware->setEnabled(!emulation_running); +      for (QAction* action : applet_actions) {          action->setEnabled(is_firmware_available && !emulation_running);      } @@ -4150,6 +4153,146 @@ void GMainWindow::OnVerifyInstalledContents() {      }  } +void GMainWindow::OnInstallFirmware() { +    // Don't do this while emulation is running, that'd probably be a bad idea. +    if (emu_thread != nullptr && emu_thread->IsRunning()) { +        return; +    } + +    // Check for installed keys, error out, suggest restart? +    if (!ContentManager::AreKeysPresent()) { +        QMessageBox::information( +            this, tr("Keys not installed"), +            tr("Install decryption keys and restart yuzu before attempting to install firmware.")); +        return; +    } + +    QString firmware_source_location = +        QFileDialog::getExistingDirectory(this, tr("Select Dumped Firmware Source Location"), +                                          QString::fromStdString(""), QFileDialog::ShowDirsOnly); +    if (firmware_source_location.isEmpty()) { +        return; +    } + +    QProgressDialog progress(tr("Installing Firmware..."), tr("Cancel"), 0, 100, this); +    progress.setWindowModality(Qt::WindowModal); +    progress.setMinimumDuration(100); +    progress.setAutoClose(false); +    progress.setAutoReset(false); +    progress.show(); + +    // Declare progress callback. +    auto QtProgressCallback = [&](size_t total_size, size_t processed_size) { +        progress.setValue(static_cast<int>((processed_size * 100) / total_size)); +        return progress.wasCanceled(); +    }; + +    LOG_INFO(Frontend, "Installing firmware from {}", firmware_source_location.toStdString()); + +    // Check for a reasonable number of .nca files (don't hardcode them, just see if there's some in +    // there.) +    std::filesystem::path firmware_source_path = firmware_source_location.toStdString(); +    if (!Common::FS::IsDir(firmware_source_path)) { +        progress.close(); +        return; +    } + +    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") +                out.emplace_back(entry.path()); + +            return true; +        }; + +    QtProgressCallback(100, 10); + +    Common::FS::IterateDirEntries(firmware_source_path, callback, Common::FS::DirEntryFilter::File); +    if (out.size() <= 0) { +        progress.close(); +        QMessageBox::warning(this, tr("Firmware install failed"), +                             tr("Unable to locate potential firmware NCA files")); +        return; +    } + +    // Locate and erase the content of nand/system/Content/registered/*.nca, if any. +    auto sysnand_content_vdir = system->GetFileSystemController().GetSystemNANDContentDirectory(); +    if (!sysnand_content_vdir->CleanSubdirectoryRecursive("registered")) { +        progress.close(); +        QMessageBox::critical(this, tr("Firmware install failed"), +                              tr("Failed to delete one or more firmware file.")); +        return; +    } + +    LOG_INFO(Frontend, +             "Cleaned nand/system/Content/registered folder in preparation for new firmware."); + +    QtProgressCallback(100, 20); + +    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++; +        auto firmware_src_vfile = +            vfs->OpenFile(firmware_src_path.generic_string(), FileSys::OpenMode::Read); +        auto firmware_dst_vfile = +            firmware_vdir->CreateFileRelative(firmware_src_path.filename().string()); + +        if (!VfsRawCopy(firmware_src_vfile, firmware_dst_vfile)) { +            LOG_ERROR(Frontend, "Failed to copy firmware file {} to {} in registered folder!", +                      firmware_src_path.generic_string(), firmware_src_path.filename().string()); +            success = false; +        } + +        if (QtProgressCallback(100, 20 + (int)(((float)(i) / (float)out.size()) * 70.0))) { +            success = false; +            cancelled = true; +            break; +        } +    } + +    if (!success && !cancelled) { +        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. +    system->GetFileSystemController().CreateFactories(*vfs); + +    auto VerifyFirmwareCallback = [&](size_t total_size, size_t processed_size) { +        progress.setValue(90 + static_cast<int>((processed_size * 10) / total_size)); +        return progress.wasCanceled(); +    }; + +    auto result = +        ContentManager::VerifyInstalledContents(*system, *provider, VerifyFirmwareCallback, true); + +    if (result.size() > 0) { +        const auto failed_names = +            QString::fromStdString(fmt::format("{}", fmt::join(result, "\n"))); +        progress.close(); +        QMessageBox::critical( +            this, tr("Firmware integrity verification failed!"), +            tr("Verification failed for the following files:\n\n%1").arg(failed_names)); +        return; +    } + +    progress.close(); +    OnCheckFirmwareDecryption(); +} +  void GMainWindow::OnAbout() {      AboutDialog aboutDialog(this);      aboutDialog.exec(); diff --git a/src/yuzu/main.h b/src/yuzu/main.h index aba61e388..1f0e35c67 100644 --- a/src/yuzu/main.h +++ b/src/yuzu/main.h @@ -380,6 +380,7 @@ private slots:      void OnLoadAmiibo();      void OnOpenYuzuFolder();      void OnVerifyInstalledContents(); +    void OnInstallFirmware();      void OnAbout();      void OnToggleFilterBar();      void OnToggleStatusBar(); diff --git a/src/yuzu/main.ui b/src/yuzu/main.ui index 6a6b0821f..6ff444a22 100644 --- a/src/yuzu/main.ui +++ b/src/yuzu/main.ui @@ -25,7 +25,16 @@    </property>    <widget class="QWidget" name="centralwidget">     <layout class="QHBoxLayout" name="horizontalLayout"> -    <property name="margin" stdset="0"> +    <property name="leftMargin"> +     <number>0</number> +    </property> +    <property name="topMargin"> +     <number>0</number> +    </property> +    <property name="rightMargin"> +     <number>0</number> +    </property> +    <property name="bottomMargin">       <number>0</number>      </property>     </layout> @@ -156,8 +165,8 @@       <addaction name="separator"/>       <addaction name="action_Configure_Tas"/>      </widget> -    <addaction name="action_Rederive"/>      <addaction name="action_Verify_installed_contents"/> +    <addaction name="action_Install_Firmware"/>      <addaction name="separator"/>      <addaction name="menu_cabinet_applet"/>      <addaction name="action_Load_Album"/> @@ -455,6 +464,11 @@      <string>Open &Controller Menu</string>     </property>    </action> +  <action name="action_Install_Firmware"> +   <property name="text"> +    <string>Install Firmware</string> +   </property> +  </action>   </widget>   <resources>    <include location="yuzu.qrc"/> | 
