diff --git a/Source/Core/Common/Crypto/SHA1.cpp b/Source/Core/Common/Crypto/SHA1.cpp index 9789818f13..4f0ef6b491 100644 --- a/Source/Core/Common/Crypto/SHA1.cpp +++ b/Source/Core/Common/Crypto/SHA1.cpp @@ -59,6 +59,7 @@ public: ASSERT(!mbedtls_sha1_finish_ret(&ctx, digest.data())); return digest; } + virtual bool HwAccelerated() const override { return false; } private: mbedtls_sha1_context ctx{}; @@ -249,6 +250,8 @@ private: return digest; } + virtual bool HwAccelerated() const override { return true; } + std::array<__m128i, 2> state{}; }; @@ -363,6 +366,8 @@ private: return digest; } + virtual bool HwAccelerated() const override { return true; } + State state; }; diff --git a/Source/Core/Common/Crypto/SHA1.h b/Source/Core/Common/Crypto/SHA1.h index 9bb188494e..83c9875a71 100644 --- a/Source/Core/Common/Crypto/SHA1.h +++ b/Source/Core/Common/Crypto/SHA1.h @@ -25,6 +25,7 @@ public: virtual void Update(const u8* msg, size_t len) = 0; void Update(const std::vector& msg) { return Update(msg.data(), msg.size()); } virtual Digest Finish() = 0; + virtual bool HwAccelerated() const = 0; }; std::unique_ptr CreateContext(); diff --git a/Source/Core/DiscIO/VolumeVerifier.cpp b/Source/Core/DiscIO/VolumeVerifier.cpp index 1e5f6515f0..c4c5539fe2 100644 --- a/Source/Core/DiscIO/VolumeVerifier.cpp +++ b/Source/Core/DiscIO/VolumeVerifier.cpp @@ -18,6 +18,7 @@ #include "Common/Align.h" #include "Common/Assert.h" +#include "Common/CPUDetect.h" #include "Common/CommonPaths.h" #include "Common/CommonTypes.h" #include "Common/Crypto/SHA1.h" @@ -374,6 +375,24 @@ VolumeVerifier::~VolumeVerifier() WaitForAsyncOperations(); } +Hashes VolumeVerifier::GetDefaultHashesToCalculate() +{ + Hashes hashes_to_calculate{.crc32 = true, .md5 = true, .sha1 = true}; + // If the system can compute certain hashes faster than others, only default-enable the fast ones. + const bool sha1_hw_accel = Common::SHA1::CreateContext()->HwAccelerated(); + // For crc32, we assume zlib-ng will be fast if cpu supports crc32 + const bool crc32_hw_accel = cpu_info.bCRC32; + if (crc32_hw_accel || sha1_hw_accel) + { + hashes_to_calculate.crc32 = crc32_hw_accel; + // md5 has no accelerated implementation at the moment, always default to off + hashes_to_calculate.md5 = false; + // Always enable SHA1, to avoid situation where only crc32 is computed + hashes_to_calculate.sha1 = true; + } + return hashes_to_calculate; +} + void VolumeVerifier::Start() { ASSERT(!m_started); diff --git a/Source/Core/DiscIO/VolumeVerifier.h b/Source/Core/DiscIO/VolumeVerifier.h index 79c45c508e..abd8c7f8ee 100644 --- a/Source/Core/DiscIO/VolumeVerifier.h +++ b/Source/Core/DiscIO/VolumeVerifier.h @@ -127,6 +127,7 @@ public: VolumeVerifier(const Volume& volume, bool redump_verification, Hashes hashes_to_calculate); ~VolumeVerifier(); + static Hashes GetDefaultHashesToCalculate(); void Start(); void Process(); u64 GetBytesProcessed() const; diff --git a/Source/Core/DolphinQt/Config/VerifyWidget.cpp b/Source/Core/DolphinQt/Config/VerifyWidget.cpp index 967f748465..87879c6659 100644 --- a/Source/Core/DolphinQt/Config/VerifyWidget.cpp +++ b/Source/Core/DolphinQt/Config/VerifyWidget.cpp @@ -74,11 +74,18 @@ void VerifyWidget::CreateWidgets() std::tie(m_md5_checkbox, m_md5_line_edit) = AddHashLine(m_hash_layout, tr("MD5:")); std::tie(m_sha1_checkbox, m_sha1_line_edit) = AddHashLine(m_hash_layout, tr("SHA-1:")); + const auto default_to_calculate = DiscIO::VolumeVerifier::GetDefaultHashesToCalculate(); + m_crc32_checkbox->setChecked(default_to_calculate.crc32); + m_md5_checkbox->setChecked(default_to_calculate.md5); + m_sha1_checkbox->setChecked(default_to_calculate.sha1); + m_redump_layout = new QFormLayout; if (DiscIO::IsDisc(m_volume->GetVolumeType())) { std::tie(m_redump_checkbox, m_redump_line_edit) = AddHashLine(m_redump_layout, tr("Redump.org Status:")); + m_redump_checkbox->setChecked(CanVerifyRedump()); + UpdateRedumpEnabled(); } else { @@ -98,7 +105,6 @@ std::pair VerifyWidget::AddHashLine(QFormLayout* layout, QLineEdit* line_edit = new QLineEdit(this); line_edit->setReadOnly(true); QCheckBox* checkbox = new QCheckBox(tr("Calculate"), this); - checkbox->setChecked(true); QHBoxLayout* hbox_layout = new QHBoxLayout; hbox_layout->addWidget(line_edit); diff --git a/Source/Core/DolphinTool/VerifyCommand.cpp b/Source/Core/DolphinTool/VerifyCommand.cpp index 6f2ff03b24..f046025c12 100644 --- a/Source/Core/DolphinTool/VerifyCommand.cpp +++ b/Source/Core/DolphinTool/VerifyCommand.cpp @@ -57,11 +57,22 @@ int VerifyCommand::Main(const std::vector& args) algorithm = static_cast(options.get("algorithm")); } - bool enable_crc32 = algorithm == std::nullopt || algorithm == "crc32"; - bool enable_md5 = algorithm == std::nullopt || algorithm == "md5"; - bool enable_sha1 = algorithm == std::nullopt || algorithm == "sha1"; + DiscIO::Hashes hashes_to_calculate{}; + if (algorithm == std::nullopt) + { + hashes_to_calculate = DiscIO::VolumeVerifier::GetDefaultHashesToCalculate(); + } + else + { + if (algorithm == "crc32") + hashes_to_calculate.crc32 = true; + else if (algorithm == "md5") + hashes_to_calculate.md5 = true; + else if (algorithm == "sha1") + hashes_to_calculate.sha1 = true; + } - if (!enable_crc32 && !enable_md5 && !enable_sha1) + if (!hashes_to_calculate.crc32 && !hashes_to_calculate.md5 && !hashes_to_calculate.sha1) { // optparse should protect from this std::cerr << "Error: No algorithms selected for the operation" << std::endl; @@ -78,7 +89,7 @@ int VerifyCommand::Main(const std::vector& args) // Verify the volume const std::optional result = - VerifyVolume(volume, enable_crc32, enable_md5, enable_sha1); + VerifyVolume(volume, hashes_to_calculate); if (!result) { std::cerr << "Error: Unable to verify volume" << std::endl; @@ -91,15 +102,15 @@ int VerifyCommand::Main(const std::vector& args) } else { - if (enable_crc32 && !result->hashes.crc32.empty()) + if (hashes_to_calculate.crc32 && !result->hashes.crc32.empty()) std::cout << HashToHexString(result->hashes.crc32) << std::endl; - else if (enable_md5 && !result->hashes.md5.empty()) + else if (hashes_to_calculate.md5 && !result->hashes.md5.empty()) std::cout << HashToHexString(result->hashes.md5) << std::endl; - else if (enable_sha1 && !result->hashes.sha1.empty()) + else if (hashes_to_calculate.sha1 && !result->hashes.sha1.empty()) std::cout << HashToHexString(result->hashes.sha1) << std::endl; else { - std::cerr << "Error: No hash available" << std::endl; + std::cerr << "Error: No hash computed" << std::endl; return 1; } } @@ -112,17 +123,17 @@ void VerifyCommand::PrintFullReport(const std::optionalhashes.crc32.empty()) std::cout << "CRC32: " << HashToHexString(result->hashes.crc32) << std::endl; else - std::cout << "CRC32 not available" << std::endl; + std::cout << "CRC32 not computed" << std::endl; if (!result->hashes.md5.empty()) std::cout << "MD5: " << HashToHexString(result->hashes.md5) << std::endl; else - std::cout << "MD5 not available" << std::endl; + std::cout << "MD5 not computed" << std::endl; if (!result->hashes.sha1.empty()) std::cout << "SHA1: " << HashToHexString(result->hashes.sha1) << std::endl; else - std::cout << "SHA1 not available" << std::endl; + std::cout << "SHA1 not computed" << std::endl; std::cout << "Problems Found: " << (result->problems.size() > 0 ? "Yes" : "No") << std::endl; @@ -156,13 +167,13 @@ void VerifyCommand::PrintFullReport(const std::optional -VerifyCommand::VerifyVolume(std::shared_ptr volume, bool enable_crc32, - bool enable_md5, bool enable_sha1) +VerifyCommand::VerifyVolume(std::shared_ptr volume, + const DiscIO::Hashes& hashes_to_calculate) { if (!volume) return std::nullopt; - DiscIO::VolumeVerifier verifier(*volume, false, {enable_crc32, enable_md5, enable_sha1}); + DiscIO::VolumeVerifier verifier(*volume, false, hashes_to_calculate); verifier.Start(); while (verifier.GetBytesProcessed() != verifier.GetTotalBytes()) diff --git a/Source/Core/DolphinTool/VerifyCommand.h b/Source/Core/DolphinTool/VerifyCommand.h index 1cd0794ba5..5067501107 100644 --- a/Source/Core/DolphinTool/VerifyCommand.h +++ b/Source/Core/DolphinTool/VerifyCommand.h @@ -23,8 +23,8 @@ private: void PrintFullReport(const std::optional result); std::optional - VerifyVolume(std::shared_ptr volume, bool enable_crc32, bool enable_md5, - bool enable_sha1); + VerifyVolume(std::shared_ptr volume, + const DiscIO::Hashes& hashes_to_calculate); std::string HashToHexString(const std::vector& hash); };