summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/yuzu/main.cpp76
1 files changed, 50 insertions, 26 deletions
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index f2e6c03f0..4e435c7e2 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -2275,40 +2275,62 @@ void GMainWindow::OnTransferableShaderCacheOpenFile(u64 program_id) {
QDesktopServices::openUrl(QUrl::fromLocalFile(qt_shader_cache_path));
}
-static std::size_t CalculateRomFSEntrySize(const FileSys::VirtualDir& dir, bool full) {
- std::size_t out = 0;
-
- 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) {
+static bool RomFSRawCopy(size_t total_size, size_t& read_size, QProgressDialog& dialog,
+ const FileSys::VirtualDir& src, const FileSys::VirtualDir& dest,
+ bool full) {
if (src == nullptr || dest == nullptr || !src->IsReadable() || !dest->IsWritable())
return false;
if (dialog.wasCanceled())
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) {
for (const auto& file : src->GetFiles()) {
const auto out = VfsDirectoryCreateFileWrapper(dest, file->GetName());
- if (!FileSys::VfsRawCopy(file, out, block_size))
- return false;
- dialog.setValue(dialog.value() + 1);
- if (dialog.wasCanceled())
+ if (!QtRawCopy(file, out))
return false;
}
}
for (const auto& dir : src->GetSubdirectories()) {
const auto out = dest->CreateSubdirectory(dir->GetName());
- if (!RomFSRawCopy(dialog, dir, out, block_size, full))
- return false;
- dialog.setValue(dialog.value() + 1);
- if (dialog.wasCanceled())
+ if (!RomFSRawCopy(total_size, read_size, dialog, dir, out, full))
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 entry_size = CalculateRomFSEntrySize(extracted, full);
- // The minimum required space is the size of the extracted RomFS + 1 GiB
- const auto minimum_free_space = extracted->GetSize() + 0x40000000;
+ // The expected required space is the size of the RomFS + 1 GiB
+ const auto minimum_free_space = romfs->GetSize() + 0x40000000;
if (full && Common::FS::GetFreeSpaceSize(path) < minimum_free_space) {
QMessageBox::warning(this, tr("RomFS Extraction Failed!"),
@@ -2667,12 +2688,15 @@ void GMainWindow::OnGameListDumpRomFS(u64 program_id, const std::string& game_pa
return;
}
- QProgressDialog progress(tr("Extracting RomFS..."), tr("Cancel"), 0,
- static_cast<s32>(entry_size), this);
+ QProgressDialog progress(tr("Extracting RomFS..."), tr("Cancel"), 0, 100, this);
progress.setWindowModality(Qt::WindowModal);
progress.setMinimumDuration(100);
+ progress.setAutoClose(false);
+ progress.setAutoReset(false);
+
+ size_t read_size = 0;
- if (RomFSRawCopy(progress, extracted, out, 0x400000, full)) {
+ if (RomFSRawCopy(romfs->GetSize(), read_size, progress, extracted, out, full)) {
progress.close();
QMessageBox::information(this, tr("RomFS Extraction Succeeded!"),
tr("The operation completed successfully."));