Achievements: Simplify hash-to-string routine

pull/3566/head
Stenzek 1 month ago
parent fe09b5d16f
commit 56665d64af
No known key found for this signature in database

@ -153,7 +153,7 @@ struct PauseMenuTimedMeasuredAchievementInfo : PauseMenuMeasuredAchievementInfo
} // namespace } // namespace
static TinyString GameHashToString(const GameHash& hash); static TinyString GameHashToString(const std::optional<GameHash>& hash);
static void ReportError(std::string_view sv); static void ReportError(std::string_view sv);
template<typename... T> template<typename... T>
@ -334,12 +334,24 @@ ALIGN_TO_CACHE_LINE static State s_state;
} // namespace Achievements } // namespace Achievements
TinyString Achievements::GameHashToString(const GameHash& hash) TinyString Achievements::GameHashToString(const std::optional<GameHash>& hash)
{ {
return TinyString::from_format( TinyString ret;
"{: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], // Use a hash that will never match if we removed the disc. See rc_client_begin_change_media().
hash[13], hash[14], hash[15]); 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<std::recursive_mutex> Achievements::GetLock() std::unique_lock<std::recursive_mutex> Achievements::GetLock()
@ -380,7 +392,7 @@ void Achievements::ReportRCError(int err, fmt::format_string<T...> fmt, T&&... a
ReportError(str); ReportError(str);
} }
std::optional<Achievements::GameHash> Achievements::GetGameHash(CDImage* image, u32* bytes_hashed) std::optional<Achievements::GameHash> Achievements::GetGameHash(CDImage* image)
{ {
std::optional<GameHash> ret; std::optional<GameHash> ret;
@ -389,12 +401,11 @@ std::optional<Achievements::GameHash> Achievements::GetGameHash(CDImage* image,
if (!System::ReadExecutableFromImage(image, &executable_name, &executable_data)) if (!System::ReadExecutableFromImage(image, &executable_name, &executable_data))
return ret; return ret;
return GetGameHash(executable_name, executable_data, bytes_hashed); return GetGameHash(executable_name, executable_data);
} }
std::optional<Achievements::GameHash> Achievements::GetGameHash(const std::string_view executable_name, std::optional<Achievements::GameHash> Achievements::GetGameHash(const std::string_view executable_name,
std::span<const u8> executable_data, std::span<const u8> executable_data)
u32* bytes_hashed /* = nullptr */)
{ {
std::optional<GameHash> ret; std::optional<GameHash> ret;
@ -413,11 +424,11 @@ std::optional<Achievements::GameHash> Achievements::GetGameHash(const std::strin
if (hash_size > 0) if (hash_size > 0)
digest.Update(executable_data.data(), hash_size); digest.Update(executable_data.data(), hash_size);
ret = GameHash(); ret.emplace();
digest.Final(ret.value()); digest.Final(ret.value());
if (bytes_hashed) INFO_COLOR_LOG(StrongOrange, "RA Hash for '{}': {} ({} bytes hashed)", executable_name, GameHashToString(ret),
*bytes_hashed = hash_size; hash_size);
return ret; return ret;
} }
@ -1169,36 +1180,24 @@ void Achievements::GameChanged(CDImage* image)
s_state.load_game_request = nullptr; s_state.load_game_request = nullptr;
} }
// Use a hash that will never match if we removed the disc. See rc_client_begin_change_media(). s_state.load_game_request =
TinyString game_hash_str; rc_client_begin_change_media_from_hash(s_state.client, GameHashToString(s_state.game_hash).c_str(),
if (s_state.game_hash.has_value()) ClientLoadGameCallback, reinterpret_cast<void*>(static_cast<uintptr_t>(1)));
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<void*>(static_cast<uintptr_t>(1)));
} }
bool Achievements::IdentifyGame(CDImage* image) bool Achievements::IdentifyGame(CDImage* image)
{ {
std::optional<GameHash> game_hash; std::optional<GameHash> game_hash;
if (image) if (image)
game_hash = GetGameHash(image);
if (!game_hash.has_value() && !rc_client_is_game_loaded(s_state.client))
{ {
u32 bytes_hashed; // If we are starting with this game and it's bad, notify the user that this is why.
game_hash = GetGameHash(image, &bytes_hashed); Host::AddIconOSDWarning(
if (game_hash.has_value()) "AchievementsHashFailed", ICON_EMOJI_WARNING,
{ TRANSLATE_STR("Achievements", "Failed to read executable from disc. Achievements disabled."),
INFO_COLOR_LOG(StrongOrange, "RA Hash: {} ({} bytes hashed)", GameHashToString(game_hash.value()), bytes_hashed); Host::OSD_ERROR_DURATION);
}
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);
}
} }
s_state.game_path = image ? image->GetPath() : std::string(); s_state.game_path = image ? image->GetPath() : std::string();
@ -1240,7 +1239,7 @@ void Achievements::BeginLoadGame()
return; 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); ClientLoadGameCallback, nullptr);
} }
@ -1253,7 +1252,7 @@ void Achievements::ClientLoadGameCallback(int result, const char* error_message,
if (result == RC_NO_GAME_LOADED) if (result == RC_NO_GAME_LOADED)
{ {
// Unknown game. // 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) if (was_disc_change)
ClearGameInfo(); 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_content_width = box_width - box_padding - box_padding;
const float box_rounding = LayoutScale(20.0f); const float box_rounding = LayoutScale(20.0f);
const u32 box_background_color = ImGui::GetColorU32(ModAlpha(UIStyle.BackgroundColor, 0.8f)); 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 title_text_color = ImGui::GetColorU32(UIStyle.BackgroundTextColor) | IM_COL32_A_MASK;
const ImU32 text_color = const ImU32 text_color =
ImGui::GetColorU32(DarkerColor(DarkerColor(UIStyle.BackgroundTextColor, 0.9f))) | IM_COL32_A_MASK; ImGui::GetColorU32(DarkerColor(DarkerColor(UIStyle.BackgroundTextColor, 0.9f))) | IM_COL32_A_MASK;

@ -64,9 +64,8 @@ private:
std::unique_lock<std::recursive_mutex> GetLock(); std::unique_lock<std::recursive_mutex> GetLock();
/// Returns the achievements game hash for a given disc. /// Returns the achievements game hash for a given disc.
std::optional<GameHash> GetGameHash(CDImage* image, u32* bytes_hashed = nullptr); std::optional<GameHash> GetGameHash(CDImage* image);
std::optional<GameHash> GetGameHash(const std::string_view executable_name, std::span<const u8> executable_data, std::optional<GameHash> GetGameHash(const std::string_view executable_name, std::span<const u8> executable_data);
u32* bytes_hashed = nullptr);
/// Returns the number of achievements for a given hash. /// Returns the number of achievements for a given hash.
const HashDatabaseEntry* LookupGameHash(const GameHash& hash); const HashDatabaseEntry* LookupGameHash(const GameHash& hash);

Loading…
Cancel
Save