diff --git a/Readme.md b/Readme.md index 696ba76004f4..bba4eb3f3743 100644 --- a/Readme.md +++ b/Readme.md @@ -234,7 +234,7 @@ Options: Path to disc image FILE. -a ALGORITHM, --algorithm=ALGORITHM Optional. Compute and print the digest using the - selected algorithm, then exit. [crc32|md5|sha1] + selected algorithm, then exit. [crc32|md5|sha1|rchash] ``` ``` diff --git a/Source/Core/Core/AchievementManager.cpp b/Source/Core/Core/AchievementManager.cpp index a1288a2b703f..dc127f599ec2 100644 --- a/Source/Core/Core/AchievementManager.cpp +++ b/Source/Core/Core/AchievementManager.cpp @@ -204,6 +204,22 @@ void AchievementManager::SetBackgroundExecutionAllowed(bool allowed) DoIdle(); } +std::string AchievementManager::CalculateHash(const std::string& file_path) +{ + char hash_result[33] = "0"; + rc_hash_filereader volume_reader{ + .open = &AchievementManager::FilereaderOpenByFilepath, + .seek = &AchievementManager::FilereaderSeek, + .tell = &AchievementManager::FilereaderTell, + .read = &AchievementManager::FilereaderRead, + .close = &AchievementManager::FilereaderClose, + }; + rc_hash_init_custom_filereader(&volume_reader); + rc_hash_generate_from_file(hash_result, RC_CONSOLE_GAMECUBE, file_path.c_str()); + + return std::string(hash_result); +} + void AchievementManager::FetchPlayerBadge() { FetchBadge(&m_player_badge, RC_IMAGE_TYPE_USER, diff --git a/Source/Core/Core/AchievementManager.h b/Source/Core/Core/AchievementManager.h index 2ec4a6dea70f..0571370c7a32 100644 --- a/Source/Core/Core/AchievementManager.h +++ b/Source/Core/Core/AchievementManager.h @@ -110,6 +110,8 @@ class AchievementManager bool IsGameLoaded() const; void SetBackgroundExecutionAllowed(bool allowed); + static std::string CalculateHash(const std::string& file_path); + void FetchPlayerBadge(); void FetchGameBadges(); diff --git a/Source/Core/DolphinTool/DolphinTool.vcxproj b/Source/Core/DolphinTool/DolphinTool.vcxproj index 8bfc2ee295f1..94173a897166 100644 --- a/Source/Core/DolphinTool/DolphinTool.vcxproj +++ b/Source/Core/DolphinTool/DolphinTool.vcxproj @@ -41,6 +41,7 @@ + diff --git a/Source/Core/DolphinTool/VerifyCommand.cpp b/Source/Core/DolphinTool/VerifyCommand.cpp index 13a041274dc5..b80f00a2734c 100644 --- a/Source/Core/DolphinTool/VerifyCommand.cpp +++ b/Source/Core/DolphinTool/VerifyCommand.cpp @@ -12,6 +12,7 @@ #include #include "Common/StringUtil.h" +#include "Core/AchievementManager.h" #include "DiscIO/Volume.h" #include "DiscIO/VolumeVerifier.h" #include "UICommon/UICommon.h" @@ -97,7 +98,7 @@ int VerifyCommand(const std::vector& args) .action("store") .help("Optional. Compute and print the digest using the selected algorithm, then exit. " "[%choices]") - .choices({"crc32", "md5", "sha1"}); + .choices({"crc32", "md5", "sha1", "rchash"}); const optparse::Values& options = parser.parse_args(args); @@ -114,6 +115,9 @@ int VerifyCommand(const std::vector& args) } const std::string& input_file_path = options["input"]; + bool rc_hash_calculate = false; + std::string rc_hash_result = "0"; + DiscIO::Hashes hashes_to_calculate{}; const bool algorithm_is_set = options.is_set("algorithm"); if (!algorithm_is_set) @@ -129,9 +133,12 @@ int VerifyCommand(const std::vector& args) hashes_to_calculate.md5 = true; else if (algorithm == "sha1") hashes_to_calculate.sha1 = true; + else if (algorithm == "rchash") + rc_hash_calculate = true; } - if (!hashes_to_calculate.crc32 && !hashes_to_calculate.md5 && !hashes_to_calculate.sha1) + if (!hashes_to_calculate.crc32 && !hashes_to_calculate.md5 && !hashes_to_calculate.sha1 && + !rc_hash_calculate) { // optparse should protect from this fmt::print(std::cerr, "Error: No algorithms selected for the operation\n"); @@ -156,6 +163,12 @@ int VerifyCommand(const std::vector& args) verifier.Finish(); const DiscIO::VolumeVerifier::Result& result = verifier.GetResult(); + // Calculate rcheevos hash + if (rc_hash_calculate) + { + rc_hash_result = AchievementManager::CalculateHash(input_file_path); + } + // Print the report if (!algorithm_is_set) { @@ -169,6 +182,8 @@ int VerifyCommand(const std::vector& args) fmt::print(std::cout, "{}\n", HashToHexString(result.hashes.md5)); else if (hashes_to_calculate.sha1 && !result.hashes.sha1.empty()) fmt::print(std::cout, "{}\n", HashToHexString(result.hashes.sha1)); + else if (rc_hash_calculate) + fmt::print(std::cout, "{}\n", rc_hash_result); else { fmt::print(std::cerr, "Error: No hash computed\n");