summaryrefslogtreecommitdiff
path: root/Source/Core
diff options
context:
space:
mode:
authorLillyJadeKatrin <lilly.kitty.1988@gmail.com>2024-06-26 20:05:54 -0400
committerAdmiral H. Curtiss <pikachu025@gmail.com>2024-07-04 22:12:28 +0200
commitbf97305a60a605b02e169add190dea35f74d789a (patch)
treeff25d2692e3369e71563db1007804ad9717a7ce2 /Source/Core
parent360f899f68a97f4bae5eaf898dc32dcd063cdf1d (diff)
AchievementManager: Cache Badges on Disk
Badges are saved in /User/Cache/RetroAchievements on first download and reused from there instead of redownloaded.
Diffstat (limited to 'Source/Core')
-rw-r--r--Source/Core/Common/CommonPaths.h1
-rw-r--r--Source/Core/Common/FileUtil.cpp4
-rw-r--r--Source/Core/Common/FileUtil.h1
-rw-r--r--Source/Core/Core/AchievementManager.cpp75
-rw-r--r--Source/Core/UICommon/UICommon.cpp1
5 files changed, 56 insertions, 26 deletions
diff --git a/Source/Core/Common/CommonPaths.h b/Source/Core/Common/CommonPaths.h
index bd0f946991..5561b0e187 100644
--- a/Source/Core/Common/CommonPaths.h
+++ b/Source/Core/Common/CommonPaths.h
@@ -63,6 +63,7 @@
#define COVERCACHE_DIR "GameCovers"
#define REDUMPCACHE_DIR "Redump"
#define SHADERCACHE_DIR "Shaders"
+#define RETROACHIEVEMENTSCACHE_DIR "RetroAchievements"
#define STATESAVES_DIR "StateSaves"
#define SCREENSHOTS_DIR "ScreenShots"
#define LOAD_DIR "Load"
diff --git a/Source/Core/Common/FileUtil.cpp b/Source/Core/Common/FileUtil.cpp
index 34350c9207..5582018b30 100644
--- a/Source/Core/Common/FileUtil.cpp
+++ b/Source/Core/Common/FileUtil.cpp
@@ -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_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_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_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;
@@ -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_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_RETROACHIEVEMENTSCACHE_IDX] =
+ s_user_paths[D_CACHE_IDX] + RETROACHIEVEMENTSCACHE_DIR DIR_SEP;
break;
case D_GCUSER_IDX:
diff --git a/Source/Core/Common/FileUtil.h b/Source/Core/Common/FileUtil.h
index 7d2d5e737a..a887ffd8f3 100644
--- a/Source/Core/Common/FileUtil.h
+++ b/Source/Core/Common/FileUtil.h
@@ -40,6 +40,7 @@ enum
D_COVERCACHE_IDX,
D_REDUMPCACHE_IDX,
D_SHADERCACHE_IDX,
+ D_RETROACHIEVEMENTSCACHE_IDX,
D_SHADERS_IDX,
D_STATESAVES_IDX,
D_SCREENSHOTS_IDX,
diff --git a/Source/Core/Core/AchievementManager.cpp b/Source/Core/Core/AchievementManager.cpp
index 99128d68dd..4ef78bf322 100644
--- a/Source/Core/Core/AchievementManager.cpp
+++ b/Source/Core/Core/AchievementManager.cpp
@@ -16,6 +16,7 @@
#include "Common/Assert.h"
#include "Common/CommonPaths.h"
#include "Common/FileUtil.h"
+#include "Common/IOFile.h"
#include "Common/Image.h"
#include "Common/Logging/Log.h"
#include "Common/ScopeGuard.h"
@@ -993,30 +994,57 @@ void AchievementManager::FetchBadge(AchievementManager::Badge* badge, u32 badge_
if (name_to_fetch.empty())
return;
}
- rc_api_fetch_image_request_t icon_request = {.image_name = name_to_fetch.c_str(),
- .image_type = badge_type};
- Badge fetched_badge;
- rc_api_request_t api_request;
- Common::HttpRequest http_request;
- if (rc_api_init_fetch_image_request(&api_request, &icon_request) != RC_OK)
- {
- ERROR_LOG_FMT(ACHIEVEMENTS, "Invalid request for image {}.", name_to_fetch);
- return;
- }
- auto http_response = http_request.Get(api_request.url, USER_AGENT_HEADER,
- Common::HttpRequest::AllowedReturnCodes::All);
- if (http_response.has_value() && http_response->size() <= 0)
+
+ 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))
{
- WARN_LOG_FMT(ACHIEVEMENTS, "RetroAchievements connection failed on image request.\n URL: {}",
- api_request.url);
+ rc_api_fetch_image_request_t icon_request = {.image_name = name_to_fetch.c_str(),
+ .image_type = badge_type};
+ Badge fetched_badge;
+ rc_api_request_t api_request;
+ Common::HttpRequest http_request;
+ if (rc_api_init_fetch_image_request(&api_request, &icon_request) != RC_OK)
+ {
+ ERROR_LOG_FMT(ACHIEVEMENTS, "Invalid request for image {}.", name_to_fetch);
+ return;
+ }
+ auto http_response = http_request.Get(api_request.url, USER_AGENT_HEADER,
+ Common::HttpRequest::AllowedReturnCodes::All);
+ if (http_response.has_value() && http_response->size() <= 0)
+ {
+ WARN_LOG_FMT(ACHIEVEMENTS,
+ "RetroAchievements connection failed on image request.\n URL: {}",
+ api_request.url);
+ rc_api_destroy_request(&api_request);
+ m_update_callback(callback_data);
+ return;
+ }
+
rc_api_destroy_request(&api_request);
- m_update_callback(callback_data);
- return;
- }
- rc_api_destroy_request(&api_request);
+ 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);
+ }
+ }
- INFO_LOG_FMT(ACHIEVEMENTS, "Successfully downloaded badge id {}.", name_to_fetch);
std::lock_guard lg{m_lock};
if (function(*this).empty() || name_to_fetch != function(*this))
{
@@ -1024,12 +1052,7 @@ void AchievementManager::FetchBadge(AchievementManager::Badge* badge, u32 badge_
return;
}
- if (!LoadPNGTexture(badge, *http_response))
- {
- ERROR_LOG_FMT(ACHIEVEMENTS, "Default game badge '{}' failed to load",
- DEFAULT_GAME_BADGE_FILENAME);
- }
-
+ *badge = std::move(tmp_badge);
m_update_callback(callback_data);
if (badge_type == RC_IMAGE_TYPE_ACHIEVEMENT &&
m_active_challenges.contains(*callback_data.achievements.begin()))
diff --git a/Source/Core/UICommon/UICommon.cpp b/Source/Core/UICommon/UICommon.cpp
index 0875b53383..4575498fb5 100644
--- a/Source/Core/UICommon/UICommon.cpp
+++ b/Source/Core/UICommon/UICommon.cpp
@@ -271,6 +271,7 @@ void CreateDirectories()
File::CreateFullPath(File::GetUserPath(D_SCREENSHOTS_IDX));
File::CreateFullPath(File::GetUserPath(D_SHADERS_IDX));
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_ASM_ROOT_IDX));
#ifndef ANDROID