From 56665d64af24a5a3c7d7470b272ed94706864ddf Mon Sep 17 00:00:00 2001 From: Stenzek Date: Sat, 13 Sep 2025 13:32:19 +1000 Subject: [PATCH] Achievements: Simplify hash-to-string routine --- src/core/achievements.cpp | 78 +++++++++++++++++++-------------------- src/core/achievements.h | 5 +-- 2 files changed, 41 insertions(+), 42 deletions(-) diff --git a/src/core/achievements.cpp b/src/core/achievements.cpp index 2f6c310bb..da8ca69c3 100644 --- a/src/core/achievements.cpp +++ b/src/core/achievements.cpp @@ -153,7 +153,7 @@ struct PauseMenuTimedMeasuredAchievementInfo : PauseMenuMeasuredAchievementInfo } // namespace -static TinyString GameHashToString(const GameHash& hash); +static TinyString GameHashToString(const std::optional& hash); static void ReportError(std::string_view sv); template @@ -334,12 +334,24 @@ ALIGN_TO_CACHE_LINE static State s_state; } // namespace Achievements -TinyString Achievements::GameHashToString(const GameHash& hash) +TinyString Achievements::GameHashToString(const std::optional& hash) { - return TinyString::from_format( - "{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}", hash[0], - hash[1], hash[2], hash[3], hash[4], hash[5], hash[6], hash[7], hash[8], hash[9], hash[10], hash[11], hash[12], - hash[13], hash[14], hash[15]); + TinyString ret; + + // Use a hash that will never match if we removed the disc. See rc_client_begin_change_media(). + if (!hash.has_value()) + { + ret = "[NO HASH]"; + } + else + { + ret.format("{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}", + hash.value()[0], hash.value()[1], hash.value()[2], hash.value()[3], hash.value()[4], hash.value()[5], + hash.value()[6], hash.value()[7], hash.value()[8], hash.value()[9], hash.value()[10], hash.value()[11], + hash.value()[12], hash.value()[13], hash.value()[14], hash.value()[15]); + } + + return ret; } std::unique_lock Achievements::GetLock() @@ -380,7 +392,7 @@ void Achievements::ReportRCError(int err, fmt::format_string fmt, T&&... a ReportError(str); } -std::optional Achievements::GetGameHash(CDImage* image, u32* bytes_hashed) +std::optional Achievements::GetGameHash(CDImage* image) { std::optional ret; @@ -389,12 +401,11 @@ std::optional Achievements::GetGameHash(CDImage* image, if (!System::ReadExecutableFromImage(image, &executable_name, &executable_data)) return ret; - return GetGameHash(executable_name, executable_data, bytes_hashed); + return GetGameHash(executable_name, executable_data); } std::optional Achievements::GetGameHash(const std::string_view executable_name, - std::span executable_data, - u32* bytes_hashed /* = nullptr */) + std::span executable_data) { std::optional ret; @@ -413,11 +424,11 @@ std::optional Achievements::GetGameHash(const std::strin if (hash_size > 0) digest.Update(executable_data.data(), hash_size); - ret = GameHash(); + ret.emplace(); digest.Final(ret.value()); - if (bytes_hashed) - *bytes_hashed = hash_size; + INFO_COLOR_LOG(StrongOrange, "RA Hash for '{}': {} ({} bytes hashed)", executable_name, GameHashToString(ret), + hash_size); return ret; } @@ -1169,36 +1180,24 @@ void Achievements::GameChanged(CDImage* image) s_state.load_game_request = nullptr; } - // Use a hash that will never match if we removed the disc. See rc_client_begin_change_media(). - TinyString game_hash_str; - if (s_state.game_hash.has_value()) - game_hash_str = GameHashToString(s_state.game_hash.value()); - else - game_hash_str = "[NO HASH]"; - - s_state.load_game_request = rc_client_begin_change_media_from_hash( - s_state.client, game_hash_str.c_str(), ClientLoadGameCallback, reinterpret_cast(static_cast(1))); + s_state.load_game_request = + rc_client_begin_change_media_from_hash(s_state.client, GameHashToString(s_state.game_hash).c_str(), + ClientLoadGameCallback, reinterpret_cast(static_cast(1))); } bool Achievements::IdentifyGame(CDImage* image) { std::optional game_hash; if (image) + game_hash = GetGameHash(image); + + if (!game_hash.has_value() && !rc_client_is_game_loaded(s_state.client)) { - u32 bytes_hashed; - game_hash = GetGameHash(image, &bytes_hashed); - if (game_hash.has_value()) - { - INFO_COLOR_LOG(StrongOrange, "RA Hash: {} ({} bytes hashed)", GameHashToString(game_hash.value()), bytes_hashed); - } - else - { - // If we are starting with this game and it's bad, notify the user that this is why. - Host::AddIconOSDWarning( - "AchievementsHashFailed", ICON_EMOJI_WARNING, - TRANSLATE_STR("Achievements", "Failed to read executable from disc. Achievements disabled."), - Host::OSD_ERROR_DURATION); - } + // If we are starting with this game and it's bad, notify the user that this is why. + Host::AddIconOSDWarning( + "AchievementsHashFailed", ICON_EMOJI_WARNING, + TRANSLATE_STR("Achievements", "Failed to read executable from disc. Achievements disabled."), + Host::OSD_ERROR_DURATION); } s_state.game_path = image ? image->GetPath() : std::string(); @@ -1240,7 +1239,7 @@ void Achievements::BeginLoadGame() return; } - s_state.load_game_request = rc_client_begin_load_game(s_state.client, GameHashToString(s_state.game_hash.value()), + s_state.load_game_request = rc_client_begin_load_game(s_state.client, GameHashToString(s_state.game_hash).c_str(), ClientLoadGameCallback, nullptr); } @@ -1253,7 +1252,7 @@ void Achievements::ClientLoadGameCallback(int result, const char* error_message, if (result == RC_NO_GAME_LOADED) { // Unknown game. - INFO_LOG("Unknown game '{}', disabling achievements.", GameHashToString(s_state.game_hash.value_or(GameHash{}))); + INFO_LOG("Unknown game '{}', disabling achievements.", GameHashToString(s_state.game_hash)); if (was_disc_change) ClearGameInfo(); @@ -2592,7 +2591,8 @@ void Achievements::DrawPauseMenuOverlays(float start_pos_y) const float box_content_width = box_width - box_padding - box_padding; const float box_rounding = LayoutScale(20.0f); const u32 box_background_color = ImGui::GetColorU32(ModAlpha(UIStyle.BackgroundColor, 0.8f)); - const ImU32 box_title_text_color = ImGui::GetColorU32(DarkerColor(UIStyle.BackgroundTextColor, 0.9f)) | IM_COL32_A_MASK; + const ImU32 box_title_text_color = + ImGui::GetColorU32(DarkerColor(UIStyle.BackgroundTextColor, 0.9f)) | IM_COL32_A_MASK; const ImU32 title_text_color = ImGui::GetColorU32(UIStyle.BackgroundTextColor) | IM_COL32_A_MASK; const ImU32 text_color = ImGui::GetColorU32(DarkerColor(DarkerColor(UIStyle.BackgroundTextColor, 0.9f))) | IM_COL32_A_MASK; diff --git a/src/core/achievements.h b/src/core/achievements.h index eb91e9931..b13f4a8a5 100644 --- a/src/core/achievements.h +++ b/src/core/achievements.h @@ -64,9 +64,8 @@ private: std::unique_lock GetLock(); /// Returns the achievements game hash for a given disc. -std::optional GetGameHash(CDImage* image, u32* bytes_hashed = nullptr); -std::optional GetGameHash(const std::string_view executable_name, std::span executable_data, - u32* bytes_hashed = nullptr); +std::optional GetGameHash(CDImage* image); +std::optional GetGameHash(const std::string_view executable_name, std::span executable_data); /// Returns the number of achievements for a given hash. const HashDatabaseEntry* LookupGameHash(const GameHash& hash);