From 24b22667ac88abfab956a8e77f6b732cd24a50d9 Mon Sep 17 00:00:00 2001 From: Shardul555 Date: Fri, 20 Aug 2021 23:08:01 +0530 Subject: [PATCH] Game API v4.0.0: Achievement support for RetroPlayer --- game.libretro/addon.xml.in | 2 +- src/cheevos/Cheevos.cpp | 48 ++++++++++++++++++++++++++++++++++++++ src/cheevos/Cheevos.h | 14 +++++++++++ src/client.cpp | 22 +++++++++++++++++ src/client.h | 4 ++++ 5 files changed, 89 insertions(+), 1 deletion(-) diff --git a/game.libretro/addon.xml.in b/game.libretro/addon.xml.in index 058737e8..85081a0d 100644 --- a/game.libretro/addon.xml.in +++ b/game.libretro/addon.xml.in @@ -1,7 +1,7 @@ @ADDON_DEPENDS@ diff --git a/src/cheevos/Cheevos.cpp b/src/cheevos/Cheevos.cpp index ea2752c2..53459ef4 100644 --- a/src/cheevos/Cheevos.cpp +++ b/src/cheevos/Cheevos.cpp @@ -88,6 +88,12 @@ bool CCheevos::GetPatchFileUrl(std::string& url, return res == 0; } +void CCheevos::SetRetroAchievementsCredentials(const std::string& username, const std::string& token) +{ + m_username = username; + m_token = token; +} + bool CCheevos::PostRichPresenceUrl(std::string& url, std::string& postData, const std::string& username, @@ -129,6 +135,48 @@ void CCheevos::EvaluateRichPresence(std::string& evaluation, unsigned int consol evaluation = _evaluation; } +void CCheevos::ActivateAchievement(unsigned cheevo_id, const char* memaddr) +{ + rc_runtime_activate_achievement(&m_runtime, cheevo_id, memaddr, NULL, 0); + // it will return integer value 0 in case achivement is activated successfully. +} + +bool CCheevos::AwardAchievement( + char* url, size_t size, unsigned cheevo_id, int hardcore, const std::string& game_hash) +{ + return rc_url_award_cheevo(url, size, m_username.c_str(), m_token.c_str(), cheevo_id, 0, + game_hash.c_str()) >= 0; +} + +void CCheevos::GetCheevo_URL_ID(void (*callback)(const char* achievement_url, unsigned cheevo_id)) +{ + m_callback = callback; +} + +void CCheevos::DeactivateTriggeredAchievement(unsigned cheevo_id) +{ + rc_runtime_deactivate_achievement(&m_runtime, cheevo_id); + char url[URL_SIZE]; + if (AwardAchievement(url, URL_SIZE, cheevo_id, 0, m_hash.c_str())) + { + std::string achievement_url = url; + m_callback(url, cheevo_id); + } +} + +void CCheevos::RuntimeEventHandler(const rc_runtime_event_t* runtime_event) +{ + if (runtime_event->type == RC_RUNTIME_EVENT_ACHIEVEMENT_TRIGGERED) + { + CCheevos::Get().DeactivateTriggeredAchievement(runtime_event->id); + } +} + +void CCheevos::TestCheevoStatusPerFrame() +{ + rc_runtime_do_frame(&m_runtime, &RuntimeEventHandler, PeekInternal, this, NULL); +} + unsigned int CCheevos::PeekInternal(unsigned address, unsigned num_bytes, void* ud) { CCheevos* cheevos = static_cast(ud); diff --git a/src/cheevos/Cheevos.h b/src/cheevos/Cheevos.h index 87ade865..f8b4b3e2 100644 --- a/src/cheevos/Cheevos.h +++ b/src/cheevos/Cheevos.h @@ -30,6 +30,7 @@ class CCheevos void ResetRuntime(); bool GenerateHashFromFile(std::string& hash, unsigned int consoleID, const std::string& filePath); bool GetGameIDUrl(std::string& url, const std::string& hash); + void SetRetroAchievementsCredentials(const std::string& username, const std::string& token); bool GetPatchFileUrl(std::string& url, const std::string& username, const std::string& token, @@ -42,7 +43,13 @@ class CCheevos const std::string& richPresence); void EnableRichPresence(const std::string& script); void EvaluateRichPresence(std::string& evaluation, unsigned int consoleID); + void ActivateAchievement(unsigned cheevo_id, const char* memaddr); + bool AwardAchievement( + char* url, size_t size, unsigned cheevo_id, int hardcore, const std::string& game_hash); + void DeactivateTriggeredAchievement(unsigned cheevo_id); + void TestCheevoStatusPerFrame(); unsigned int Peek(unsigned int address, unsigned int numBytes); + void GetCheevo_URL_ID(void (*callback)(const char* achievement_url, unsigned cheevo_id)); private: const uint8_t* FixupFind(unsigned address, CMemoryMap& mmap, int consolecheevos); @@ -51,6 +58,9 @@ class CCheevos size_t Reduce(size_t addr, size_t mask); static unsigned int PeekInternal(unsigned address, unsigned num_bytes, void* ud); + static void RuntimeEventHandler(const rc_runtime_event_t* runtime_event); + + void (*m_callback)(const char* achievement_url, unsigned cheevo_id); int m_consoleID; @@ -61,5 +71,9 @@ class CCheevos rc_richpresence_t* m_richPresence = nullptr; std::string m_richPresenceScript; std::vector m_richPresenceBuffer; + + std::string m_hash; + std::string m_username; + std::string m_token; }; } // namespace LIBRETRO diff --git a/src/client.cpp b/src/client.cpp index cf7f8df7..86376d1c 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -274,6 +274,8 @@ GAME_ERROR CGameLibRetro::RunFrame() m_client.retro_run(); + CCheevos::Get().TestCheevoStatusPerFrame(); + CLibretroEnvironment::Get().OnFrameEnd(); return GAME_ERROR_NO_ERROR; @@ -502,6 +504,12 @@ GAME_ERROR CGameLibRetro::RCGetPatchFileUrl(std::string& url, return GAME_ERROR_NO_ERROR; } +GAME_ERROR CGameLibRetro::SetRetroAchievementsCredentials(const char* username, const char* token) +{ + CCheevos::Get().SetRetroAchievementsCredentials(username, token); + return GAME_ERROR_NO_ERROR; +} + GAME_ERROR CGameLibRetro::RCPostRichPresenceUrl(std::string& url, std::string& postData, const std::string& username, @@ -530,6 +538,20 @@ GAME_ERROR CGameLibRetro::RCGetRichPresenceEvaluation(std::string& evaluation, return GAME_ERROR_NO_ERROR; } +GAME_ERROR CGameLibRetro::ActivateAchievement(unsigned cheevo_id, const char* memaddr) +{ + CCheevos::Get().ActivateAchievement(cheevo_id, memaddr); + + return GAME_ERROR_NO_ERROR; +} + +GAME_ERROR CGameLibRetro::GetCheevo_URL_ID(void (*Callback)(const char* achievement_url, + unsigned cheevo_id)) +{ + CCheevos::Get().GetCheevo_URL_ID(Callback); + return GAME_ERROR_NO_ERROR; +} + GAME_ERROR CGameLibRetro::RCResetRuntime() { CCheevos::Get().ResetRuntime(); diff --git a/src/client.h b/src/client.h index 460e1144..d06e4b61 100644 --- a/src/client.h +++ b/src/client.h @@ -78,6 +78,7 @@ class ATTR_DLL_LOCAL CGameLibRetro const std::string& username, const std::string& token, unsigned int gameID) override; + GAME_ERROR SetRetroAchievementsCredentials(const char* username, const char* token); GAME_ERROR RCPostRichPresenceUrl(std::string& url, std::string& postData, const std::string& username, @@ -86,7 +87,10 @@ class ATTR_DLL_LOCAL CGameLibRetro const std::string& richPresence) override; GAME_ERROR RCEnableRichPresence(const std::string& script) override; GAME_ERROR RCGetRichPresenceEvaluation(std::string& evaluation, unsigned int consoleID) override; + GAME_ERROR ActivateAchievement(unsigned cheevo_id, const char* memaddr) override; GAME_ERROR RCResetRuntime() override; + GAME_ERROR GetCheevo_URL_ID(void (*Callback)(const char* achievement_url, + unsigned cheevo_id)) override; private: GAME_ERROR AudioAvailable();