forked from suyu/suyu
Merge pull request #11437 from liamwhite/dump-shenanigans
qt: measure romfs dump completion by bytes read
This commit is contained in:
commit
70790711d2
1 changed files with 50 additions and 26 deletions
|
@ -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."));
|
||||||
|
|
Loading…
Reference in a new issue