DolphinTool: CLI utility interface and disc image tools

This commit is contained in:
ssdsnake 2021-12-03 15:40:19 -06:00
parent 1e212d6212
commit 1aa8a4d46f
19 changed files with 968 additions and 26 deletions

View file

@ -23,6 +23,7 @@
#include "Common/Assert.h"
#include "Common/Logging/Log.h"
#include "DiscIO/Blob.h"
#include "DiscIO/DiscUtils.h"
#include "DiscIO/ScrubbedBlob.h"
#include "DiscIO/WIABlob.h"
#include "DolphinQt/QtUtils/DolphinFileDialog.h"
@ -118,10 +119,9 @@ void ConvertDialog::AddToBlockSizeComboBox(int size)
{
m_block_size->addItem(QString::fromStdString(UICommon::FormatSize(size, 0)), size);
// Select 128 KiB by default, or if it is not available, the size closest to it.
// Select the default, or if it is not available, the size closest to it.
// This code assumes that sizes get added to the combo box in increasing order.
constexpr int DEFAULT_SIZE = 0x20000;
if (size <= DEFAULT_SIZE)
if (size <= DiscIO::GCZ_RVZ_PREFERRED_BLOCK_SIZE)
m_block_size->setCurrentIndex(m_block_size->count() - 1);
}
@ -138,14 +138,6 @@ void ConvertDialog::AddToCompressionLevelComboBox(int level)
void ConvertDialog::OnFormatChanged()
{
// Because DVD timings are emulated as if we can't read less than an entire ECC block at once
// (32 KiB - 0x8000), there is little reason to use a block size smaller than that.
constexpr int MIN_BLOCK_SIZE = 0x8000;
// For performance reasons, blocks shouldn't be too large.
// 2 MiB (0x200000) was picked because it is the smallest block size supported by WIA.
constexpr int MAX_BLOCK_SIZE = 0x200000;
const DiscIO::BlobType format = static_cast<DiscIO::BlobType>(m_format->currentData().toInt());
m_block_size->clear();
@ -156,21 +148,17 @@ void ConvertDialog::OnFormatChanged()
{
case DiscIO::BlobType::GCZ:
{
// In order for versions of Dolphin prior to 5.0-11893 to be able to convert a GCZ file
// to ISO without messing up the final part of the file in some way, the file size
// must be an integer multiple of the block size (fixed in 3aa463c) and must not be
// an integer multiple of the block size multiplied by 32 (fixed in 26b21e3).
// To support legacy versions of dolphin, we have to check the GCZ block size
// See DiscIO::IsGCZBlockSizeLegacyCompatible() for details
const auto block_size_ok = [this](int block_size) {
return std::all_of(m_files.begin(), m_files.end(), [block_size](const auto& file) {
constexpr u64 BLOCKS_PER_BUFFER = 32;
const u64 file_size = file->GetVolumeSize();
return file_size % block_size == 0 && file_size % (block_size * BLOCKS_PER_BUFFER) != 0;
return DiscIO::IsGCZBlockSizeLegacyCompatible(block_size, file->GetVolumeSize());
});
};
// Add all block sizes in the normal range that do not cause problems
for (int block_size = MIN_BLOCK_SIZE; block_size <= MAX_BLOCK_SIZE; block_size *= 2)
for (int block_size = DiscIO::PREFERRED_MIN_BLOCK_SIZE;
block_size <= DiscIO::PREFERRED_MAX_BLOCK_SIZE; block_size *= 2)
{
if (block_size_ok(block_size))
AddToBlockSizeComboBox(block_size);
@ -180,13 +168,12 @@ void ConvertDialog::OnFormatChanged()
// in older versions of Dolphin. That way, at least we're not worse than older versions.
if (m_block_size->count() == 0)
{
constexpr int FALLBACK_BLOCK_SIZE = 0x4000;
if (!block_size_ok(FALLBACK_BLOCK_SIZE))
if (!block_size_ok(DiscIO::GCZ_FALLBACK_BLOCK_SIZE))
{
ERROR_LOG_FMT(MASTER_LOG, "Failed to find a block size which does not cause problems "
"when decompressing using an old version of Dolphin");
}
AddToBlockSizeComboBox(FALLBACK_BLOCK_SIZE);
AddToBlockSizeComboBox(DiscIO::GCZ_FALLBACK_BLOCK_SIZE);
}
break;
@ -195,13 +182,14 @@ void ConvertDialog::OnFormatChanged()
m_block_size->setEnabled(true);
// This is the smallest block size supported by WIA. For performance, larger sizes are avoided.
AddToBlockSizeComboBox(0x200000);
AddToBlockSizeComboBox(DiscIO::WIA_MIN_BLOCK_SIZE);
break;
case DiscIO::BlobType::RVZ:
m_block_size->setEnabled(true);
for (int block_size = MIN_BLOCK_SIZE; block_size <= MAX_BLOCK_SIZE; block_size *= 2)
for (int block_size = DiscIO::PREFERRED_MIN_BLOCK_SIZE;
block_size <= DiscIO::PREFERRED_MAX_BLOCK_SIZE; block_size *= 2)
AddToBlockSizeComboBox(block_size);
break;
@ -257,6 +245,7 @@ void ConvertDialog::OnFormatChanged()
m_block_size->setEnabled(m_block_size->count() > 1);
m_compression->setEnabled(m_compression->count() > 1);
// Block scrubbing of RVZ containers and Datel discs
const bool scrubbing_allowed =
format != DiscIO::BlobType::RVZ &&
std::none_of(m_files.begin(), m_files.end(), std::mem_fn(&UICommon::GameFile::IsDatelDisc));