Skip to content

Commit

Permalink
Add MemoryVerifier to AchievementManager Startup
Browse files Browse the repository at this point in the history
rc_client calls the provided memory peeker asynchronously in the callback for starting a session, to validate/invalidate the memory used for achievements. Dolphin cannot access memory from any thread but host or CPU so this access has a small chance of being invalid. This commit adds a MemoryVerifier that the AchievementManager will use to perform this, before changing the peek method back to the original MemoryPeeker for normal operation.
  • Loading branch information
LillyJadeKatrin committed Jun 18, 2024
1 parent a0d8c10 commit 36a185d
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 6 deletions.
21 changes: 15 additions & 6 deletions Source/Core/Core/AchievementManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ void AchievementManager::Init()
LoadDefaultBadges();
if (!m_client && Config::Get(Config::RA_ENABLED))
{
m_client = rc_client_create(MemoryPeeker, Request);
m_client = rc_client_create(MemoryVerifier, Request);
std::string host_url = Config::Get(Config::RA_HOST_URL);
if (!host_url.empty())
rc_client_set_host(m_client, host_url.c_str());
Expand Down Expand Up @@ -679,12 +679,14 @@ void AchievementManager::LoadGameCallback(int result, const char* error_message,
}
INFO_LOG_FMT(ACHIEVEMENTS, "Loaded data for game ID {}.", game->id);

AchievementManager::GetInstance().m_display_welcome_message = true;
AchievementManager::GetInstance().FetchGameBadges();
AchievementManager::GetInstance().m_system = &Core::System::GetInstance();
AchievementManager::GetInstance().m_update_callback({.all = true});
auto& instance = AchievementManager::GetInstance();
rc_client_set_read_memory_function(instance.m_client, MemoryPeeker);
instance.m_display_welcome_message = true;
instance.FetchGameBadges();
instance.m_system = &Core::System::GetInstance();
instance.m_update_callback({.all = true});
// Set this to a value that will immediately trigger RP
AchievementManager::GetInstance().m_last_rp_time =
instance.m_last_rp_time =
std::chrono::steady_clock::now() - std::chrono::minutes{2};
}

Expand Down Expand Up @@ -914,6 +916,13 @@ void AchievementManager::Request(const rc_api_request_t* request,
});
}

u32 AchievementManager::MemoryVerifier(u32 address, u8* buffer, u32 num_bytes, rc_client_t* client)
{
for (u32 ix = 0; ix < num_bytes; ix++)
buffer[ix] = 0xcd;
return std::min(0x17fffff - address, num_bytes);
}

u32 AchievementManager::MemoryPeeker(u32 address, u8* buffer, u32 num_bytes, rc_client_t* client)
{
if (buffer == nullptr)
Expand Down
1 change: 1 addition & 0 deletions Source/Core/Core/AchievementManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ class AchievementManager

static void Request(const rc_api_request_t* request, rc_client_server_callback_t callback,
void* callback_data, rc_client_t* client);
static u32 MemoryVerifier(u32 address, u8* buffer, u32 num_bytes, rc_client_t* client);
static u32 MemoryPeeker(u32 address, u8* buffer, u32 num_bytes, rc_client_t* client);
void FetchBadge(Badge* badge, u32 badge_type, const BadgeNameFunction function,
const UpdatedItems callback_data);
Expand Down

0 comments on commit 36a185d

Please sign in to comment.