Merge pull request #12895 from LillyJadeKatrin/retroachievements-badge-cache
RetroAchievements Integration - Badge Cache
This commit is contained in:
commit
1b1523d6e0
|
@ -63,6 +63,7 @@
|
||||||
#define COVERCACHE_DIR "GameCovers"
|
#define COVERCACHE_DIR "GameCovers"
|
||||||
#define REDUMPCACHE_DIR "Redump"
|
#define REDUMPCACHE_DIR "Redump"
|
||||||
#define SHADERCACHE_DIR "Shaders"
|
#define SHADERCACHE_DIR "Shaders"
|
||||||
|
#define RETROACHIEVEMENTSCACHE_DIR "RetroAchievements"
|
||||||
#define STATESAVES_DIR "StateSaves"
|
#define STATESAVES_DIR "StateSaves"
|
||||||
#define SCREENSHOTS_DIR "ScreenShots"
|
#define SCREENSHOTS_DIR "ScreenShots"
|
||||||
#define LOAD_DIR "Load"
|
#define LOAD_DIR "Load"
|
||||||
|
|
|
@ -385,4 +385,20 @@ Digest CalculateDigest(const u8* msg, size_t len)
|
||||||
ctx->Update(msg, len);
|
ctx->Update(msg, len);
|
||||||
return ctx->Finish();
|
return ctx->Finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string DigestToString(const Digest& digest)
|
||||||
|
{
|
||||||
|
static constexpr std::array<char, 16> lookup = {'0', '1', '2', '3', '4', '5', '6', '7',
|
||||||
|
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
|
||||||
|
std::string hash;
|
||||||
|
hash.reserve(digest.size() * 2);
|
||||||
|
for (size_t i = 0; i < digest.size(); ++i)
|
||||||
|
{
|
||||||
|
const u8 upper = static_cast<u8>((digest[i] >> 4) & 0xf);
|
||||||
|
const u8 lower = static_cast<u8>(digest[i] & 0xf);
|
||||||
|
hash.push_back(lookup[upper]);
|
||||||
|
hash.push_back(lookup[lower]);
|
||||||
|
}
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
} // namespace Common::SHA1
|
} // namespace Common::SHA1
|
||||||
|
|
|
@ -51,4 +51,6 @@ inline Digest CalculateDigest(const std::array<T, Size>& msg)
|
||||||
static_assert(std::is_trivially_copyable_v<T>);
|
static_assert(std::is_trivially_copyable_v<T>);
|
||||||
return CalculateDigest(reinterpret_cast<const u8*>(msg.data()), sizeof(msg));
|
return CalculateDigest(reinterpret_cast<const u8*>(msg.data()), sizeof(msg));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string DigestToString(const Digest& digest);
|
||||||
} // namespace Common::SHA1
|
} // namespace Common::SHA1
|
||||||
|
|
|
@ -843,6 +843,8 @@ static void RebuildUserDirectories(unsigned int dir_index)
|
||||||
s_user_paths[D_COVERCACHE_IDX] = s_user_paths[D_CACHE_IDX] + COVERCACHE_DIR DIR_SEP;
|
s_user_paths[D_COVERCACHE_IDX] = s_user_paths[D_CACHE_IDX] + COVERCACHE_DIR DIR_SEP;
|
||||||
s_user_paths[D_REDUMPCACHE_IDX] = s_user_paths[D_CACHE_IDX] + REDUMPCACHE_DIR DIR_SEP;
|
s_user_paths[D_REDUMPCACHE_IDX] = s_user_paths[D_CACHE_IDX] + REDUMPCACHE_DIR DIR_SEP;
|
||||||
s_user_paths[D_SHADERCACHE_IDX] = s_user_paths[D_CACHE_IDX] + SHADERCACHE_DIR DIR_SEP;
|
s_user_paths[D_SHADERCACHE_IDX] = s_user_paths[D_CACHE_IDX] + SHADERCACHE_DIR DIR_SEP;
|
||||||
|
s_user_paths[D_RETROACHIEVEMENTSCACHE_IDX] =
|
||||||
|
s_user_paths[D_CACHE_IDX] + RETROACHIEVEMENTSCACHE_DIR DIR_SEP;
|
||||||
s_user_paths[D_SHADERS_IDX] = s_user_paths[D_USER_IDX] + SHADERS_DIR DIR_SEP;
|
s_user_paths[D_SHADERS_IDX] = s_user_paths[D_USER_IDX] + SHADERS_DIR DIR_SEP;
|
||||||
s_user_paths[D_STATESAVES_IDX] = s_user_paths[D_USER_IDX] + STATESAVES_DIR DIR_SEP;
|
s_user_paths[D_STATESAVES_IDX] = s_user_paths[D_USER_IDX] + STATESAVES_DIR DIR_SEP;
|
||||||
s_user_paths[D_SCREENSHOTS_IDX] = s_user_paths[D_USER_IDX] + SCREENSHOTS_DIR DIR_SEP;
|
s_user_paths[D_SCREENSHOTS_IDX] = s_user_paths[D_USER_IDX] + SCREENSHOTS_DIR DIR_SEP;
|
||||||
|
@ -926,6 +928,8 @@ static void RebuildUserDirectories(unsigned int dir_index)
|
||||||
s_user_paths[D_COVERCACHE_IDX] = s_user_paths[D_CACHE_IDX] + COVERCACHE_DIR DIR_SEP;
|
s_user_paths[D_COVERCACHE_IDX] = s_user_paths[D_CACHE_IDX] + COVERCACHE_DIR DIR_SEP;
|
||||||
s_user_paths[D_REDUMPCACHE_IDX] = s_user_paths[D_CACHE_IDX] + REDUMPCACHE_DIR DIR_SEP;
|
s_user_paths[D_REDUMPCACHE_IDX] = s_user_paths[D_CACHE_IDX] + REDUMPCACHE_DIR DIR_SEP;
|
||||||
s_user_paths[D_SHADERCACHE_IDX] = s_user_paths[D_CACHE_IDX] + SHADERCACHE_DIR DIR_SEP;
|
s_user_paths[D_SHADERCACHE_IDX] = s_user_paths[D_CACHE_IDX] + SHADERCACHE_DIR DIR_SEP;
|
||||||
|
s_user_paths[D_RETROACHIEVEMENTSCACHE_IDX] =
|
||||||
|
s_user_paths[D_CACHE_IDX] + RETROACHIEVEMENTSCACHE_DIR DIR_SEP;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case D_GCUSER_IDX:
|
case D_GCUSER_IDX:
|
||||||
|
|
|
@ -40,6 +40,7 @@ enum
|
||||||
D_COVERCACHE_IDX,
|
D_COVERCACHE_IDX,
|
||||||
D_REDUMPCACHE_IDX,
|
D_REDUMPCACHE_IDX,
|
||||||
D_SHADERCACHE_IDX,
|
D_SHADERCACHE_IDX,
|
||||||
|
D_RETROACHIEVEMENTSCACHE_IDX,
|
||||||
D_SHADERS_IDX,
|
D_SHADERS_IDX,
|
||||||
D_STATESAVES_IDX,
|
D_STATESAVES_IDX,
|
||||||
D_SCREENSHOTS_IDX,
|
D_SCREENSHOTS_IDX,
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#include "Common/Assert.h"
|
#include "Common/Assert.h"
|
||||||
#include "Common/CommonPaths.h"
|
#include "Common/CommonPaths.h"
|
||||||
#include "Common/FileUtil.h"
|
#include "Common/FileUtil.h"
|
||||||
|
#include "Common/IOFile.h"
|
||||||
#include "Common/Image.h"
|
#include "Common/Image.h"
|
||||||
#include "Common/Logging/Log.h"
|
#include "Common/Logging/Log.h"
|
||||||
#include "Common/ScopeGuard.h"
|
#include "Common/ScopeGuard.h"
|
||||||
|
@ -993,6 +994,14 @@ void AchievementManager::FetchBadge(AchievementManager::Badge* badge, u32 badge_
|
||||||
if (name_to_fetch.empty())
|
if (name_to_fetch.empty())
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::string cache_path = fmt::format(
|
||||||
|
"{}/badge-{}-{}.png", File::GetUserPath(D_RETROACHIEVEMENTSCACHE_IDX), badge_type,
|
||||||
|
Common::SHA1::DigestToString(Common::SHA1::CalculateDigest(name_to_fetch)));
|
||||||
|
|
||||||
|
AchievementManager::Badge tmp_badge;
|
||||||
|
if (!LoadPNGTexture(&tmp_badge, cache_path))
|
||||||
|
{
|
||||||
rc_api_fetch_image_request_t icon_request = {.image_name = name_to_fetch.c_str(),
|
rc_api_fetch_image_request_t icon_request = {.image_name = name_to_fetch.c_str(),
|
||||||
.image_type = badge_type};
|
.image_type = badge_type};
|
||||||
Badge fetched_badge;
|
Badge fetched_badge;
|
||||||
|
@ -1007,7 +1016,8 @@ void AchievementManager::FetchBadge(AchievementManager::Badge* badge, u32 badge_
|
||||||
Common::HttpRequest::AllowedReturnCodes::All);
|
Common::HttpRequest::AllowedReturnCodes::All);
|
||||||
if (http_response.has_value() && http_response->size() <= 0)
|
if (http_response.has_value() && http_response->size() <= 0)
|
||||||
{
|
{
|
||||||
WARN_LOG_FMT(ACHIEVEMENTS, "RetroAchievements connection failed on image request.\n URL: {}",
|
WARN_LOG_FMT(ACHIEVEMENTS,
|
||||||
|
"RetroAchievements connection failed on image request.\n URL: {}",
|
||||||
api_request.url);
|
api_request.url);
|
||||||
rc_api_destroy_request(&api_request);
|
rc_api_destroy_request(&api_request);
|
||||||
m_update_callback(callback_data);
|
m_update_callback(callback_data);
|
||||||
|
@ -1017,6 +1027,24 @@ void AchievementManager::FetchBadge(AchievementManager::Badge* badge, u32 badge_
|
||||||
rc_api_destroy_request(&api_request);
|
rc_api_destroy_request(&api_request);
|
||||||
|
|
||||||
INFO_LOG_FMT(ACHIEVEMENTS, "Successfully downloaded badge id {}.", name_to_fetch);
|
INFO_LOG_FMT(ACHIEVEMENTS, "Successfully downloaded badge id {}.", name_to_fetch);
|
||||||
|
|
||||||
|
if (!LoadPNGTexture(&tmp_badge, *http_response))
|
||||||
|
{
|
||||||
|
ERROR_LOG_FMT(ACHIEVEMENTS, "Badge '{}' failed to load", name_to_fetch);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string temp_path = fmt::format("{}.tmp", cache_path);
|
||||||
|
File::IOFile temp_file(temp_path, "wb");
|
||||||
|
if (!temp_file.IsOpen() ||
|
||||||
|
!temp_file.WriteBytes(http_response->data(), http_response->size()) ||
|
||||||
|
!temp_file.Close() || !File::Rename(temp_path, cache_path))
|
||||||
|
{
|
||||||
|
File::Delete(temp_path);
|
||||||
|
WARN_LOG_FMT(ACHIEVEMENTS, "Failed to store badge '{}' to cache", name_to_fetch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::lock_guard lg{m_lock};
|
std::lock_guard lg{m_lock};
|
||||||
if (function(*this).empty() || name_to_fetch != function(*this))
|
if (function(*this).empty() || name_to_fetch != function(*this))
|
||||||
{
|
{
|
||||||
|
@ -1024,12 +1052,7 @@ void AchievementManager::FetchBadge(AchievementManager::Badge* badge, u32 badge_
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!LoadPNGTexture(badge, *http_response))
|
*badge = std::move(tmp_badge);
|
||||||
{
|
|
||||||
ERROR_LOG_FMT(ACHIEVEMENTS, "Default game badge '{}' failed to load",
|
|
||||||
DEFAULT_GAME_BADGE_FILENAME);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_update_callback(callback_data);
|
m_update_callback(callback_data);
|
||||||
if (badge_type == RC_IMAGE_TYPE_ACHIEVEMENT &&
|
if (badge_type == RC_IMAGE_TYPE_ACHIEVEMENT &&
|
||||||
m_active_challenges.contains(*callback_data.achievements.begin()))
|
m_active_challenges.contains(*callback_data.achievements.begin()))
|
||||||
|
|
|
@ -271,6 +271,7 @@ void CreateDirectories()
|
||||||
File::CreateFullPath(File::GetUserPath(D_SCREENSHOTS_IDX));
|
File::CreateFullPath(File::GetUserPath(D_SCREENSHOTS_IDX));
|
||||||
File::CreateFullPath(File::GetUserPath(D_SHADERS_IDX));
|
File::CreateFullPath(File::GetUserPath(D_SHADERS_IDX));
|
||||||
File::CreateFullPath(File::GetUserPath(D_SHADERS_IDX) + ANAGLYPH_DIR DIR_SEP);
|
File::CreateFullPath(File::GetUserPath(D_SHADERS_IDX) + ANAGLYPH_DIR DIR_SEP);
|
||||||
|
File::CreateFullPath(File::GetUserPath(D_RETROACHIEVEMENTSCACHE_IDX));
|
||||||
File::CreateFullPath(File::GetUserPath(D_STATESAVES_IDX));
|
File::CreateFullPath(File::GetUserPath(D_STATESAVES_IDX));
|
||||||
File::CreateFullPath(File::GetUserPath(D_ASM_ROOT_IDX));
|
File::CreateFullPath(File::GetUserPath(D_ASM_ROOT_IDX));
|
||||||
#ifndef ANDROID
|
#ifndef ANDROID
|
||||||
|
|
Loading…
Reference in New Issue