Merge pull request #11437 from liamwhite/dump-shenanigans
qt: measure romfs dump completion by bytes read
This commit is contained in:
		| @@ -2275,40 +2275,62 @@ void GMainWindow::OnTransferableShaderCacheOpenFile(u64 program_id) { | |||||||
|     QDesktopServices::openUrl(QUrl::fromLocalFile(qt_shader_cache_path)); |     QDesktopServices::openUrl(QUrl::fromLocalFile(qt_shader_cache_path)); | ||||||
| } | } | ||||||
|  |  | ||||||
| static std::size_t CalculateRomFSEntrySize(const FileSys::VirtualDir& dir, bool full) { | static bool RomFSRawCopy(size_t total_size, size_t& read_size, QProgressDialog& dialog, | ||||||
|     std::size_t out = 0; |                          const FileSys::VirtualDir& src, const FileSys::VirtualDir& dest, | ||||||
|  |                          bool full) { | ||||||
|     for (const auto& subdir : dir->GetSubdirectories()) { |  | ||||||
|         out += 1 + CalculateRomFSEntrySize(subdir, full); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     return out + (full ? dir->GetFiles().size() : 0); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static bool RomFSRawCopy(QProgressDialog& dialog, const FileSys::VirtualDir& src, |  | ||||||
|                          const FileSys::VirtualDir& dest, std::size_t block_size, bool full) { |  | ||||||
|     if (src == nullptr || dest == nullptr || !src->IsReadable() || !dest->IsWritable()) |     if (src == nullptr || dest == nullptr || !src->IsReadable() || !dest->IsWritable()) | ||||||
|         return false; |         return false; | ||||||
|     if (dialog.wasCanceled()) |     if (dialog.wasCanceled()) | ||||||
|         return false; |         return false; | ||||||
|  |  | ||||||
|  |     std::vector<u8> buffer(CopyBufferSize); | ||||||
|  |     auto last_timestamp = std::chrono::steady_clock::now(); | ||||||
|  |  | ||||||
|  |     const auto QtRawCopy = [&](const FileSys::VirtualFile& src_file, | ||||||
|  |                                const FileSys::VirtualFile& dest_file) { | ||||||
|  |         if (src_file == nullptr || dest_file == nullptr) { | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  |         if (!dest_file->Resize(src_file->GetSize())) { | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         for (std::size_t i = 0; i < src_file->GetSize(); i += buffer.size()) { | ||||||
|  |             if (dialog.wasCanceled()) { | ||||||
|  |                 dest_file->Resize(0); | ||||||
|  |                 return false; | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             using namespace std::literals::chrono_literals; | ||||||
|  |             const auto new_timestamp = std::chrono::steady_clock::now(); | ||||||
|  |  | ||||||
|  |             if ((new_timestamp - last_timestamp) > 33ms) { | ||||||
|  |                 last_timestamp = new_timestamp; | ||||||
|  |                 dialog.setValue( | ||||||
|  |                     static_cast<int>(std::min(read_size, total_size) * 100 / total_size)); | ||||||
|  |                 QCoreApplication::processEvents(); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             const auto read = src_file->Read(buffer.data(), buffer.size(), i); | ||||||
|  |             dest_file->Write(buffer.data(), read, i); | ||||||
|  |  | ||||||
|  |             read_size += read; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         return true; | ||||||
|  |     }; | ||||||
|  |  | ||||||
|     if (full) { |     if (full) { | ||||||
|         for (const auto& file : src->GetFiles()) { |         for (const auto& file : src->GetFiles()) { | ||||||
|             const auto out = VfsDirectoryCreateFileWrapper(dest, file->GetName()); |             const auto out = VfsDirectoryCreateFileWrapper(dest, file->GetName()); | ||||||
|             if (!FileSys::VfsRawCopy(file, out, block_size)) |             if (!QtRawCopy(file, out)) | ||||||
|                 return false; |  | ||||||
|             dialog.setValue(dialog.value() + 1); |  | ||||||
|             if (dialog.wasCanceled()) |  | ||||||
|                 return false; |                 return false; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     for (const auto& dir : src->GetSubdirectories()) { |     for (const auto& dir : src->GetSubdirectories()) { | ||||||
|         const auto out = dest->CreateSubdirectory(dir->GetName()); |         const auto out = dest->CreateSubdirectory(dir->GetName()); | ||||||
|         if (!RomFSRawCopy(dialog, dir, out, block_size, full)) |         if (!RomFSRawCopy(total_size, read_size, dialog, dir, out, full)) | ||||||
|             return false; |  | ||||||
|         dialog.setValue(dialog.value() + 1); |  | ||||||
|         if (dialog.wasCanceled()) |  | ||||||
|             return false; |             return false; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -2653,10 +2675,9 @@ void GMainWindow::OnGameListDumpRomFS(u64 program_id, const std::string& game_pa | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     const auto full = res == selections.constFirst(); |     const auto full = res == selections.constFirst(); | ||||||
|     const auto entry_size = CalculateRomFSEntrySize(extracted, full); |  | ||||||
|  |  | ||||||
|     // The minimum required space is the size of the extracted RomFS + 1 GiB |     // The expected required space is the size of the RomFS + 1 GiB | ||||||
|     const auto minimum_free_space = extracted->GetSize() + 0x40000000; |     const auto minimum_free_space = romfs->GetSize() + 0x40000000; | ||||||
|  |  | ||||||
|     if (full && Common::FS::GetFreeSpaceSize(path) < minimum_free_space) { |     if (full && Common::FS::GetFreeSpaceSize(path) < minimum_free_space) { | ||||||
|         QMessageBox::warning(this, tr("RomFS Extraction Failed!"), |         QMessageBox::warning(this, tr("RomFS Extraction Failed!"), | ||||||
| @@ -2667,12 +2688,15 @@ void GMainWindow::OnGameListDumpRomFS(u64 program_id, const std::string& game_pa | |||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     QProgressDialog progress(tr("Extracting RomFS..."), tr("Cancel"), 0, |     QProgressDialog progress(tr("Extracting RomFS..."), tr("Cancel"), 0, 100, this); | ||||||
|                              static_cast<s32>(entry_size), this); |  | ||||||
|     progress.setWindowModality(Qt::WindowModal); |     progress.setWindowModality(Qt::WindowModal); | ||||||
|     progress.setMinimumDuration(100); |     progress.setMinimumDuration(100); | ||||||
|  |     progress.setAutoClose(false); | ||||||
|  |     progress.setAutoReset(false); | ||||||
|  |  | ||||||
|     if (RomFSRawCopy(progress, extracted, out, 0x400000, full)) { |     size_t read_size = 0; | ||||||
|  |  | ||||||
|  |     if (RomFSRawCopy(romfs->GetSize(), read_size, progress, extracted, out, full)) { | ||||||
|         progress.close(); |         progress.close(); | ||||||
|         QMessageBox::information(this, tr("RomFS Extraction Succeeded!"), |         QMessageBox::information(this, tr("RomFS Extraction Succeeded!"), | ||||||
|                                  tr("The operation completed successfully.")); |                                  tr("The operation completed successfully.")); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user