Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implementing support for Achievements in RetroPlayer #73

Open
wants to merge 2 commits into
base: feature_achievements
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 55 additions & 1 deletion src/cheevos/Cheevos.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,13 @@

using namespace LIBRETRO;

constexpr int URL_SIZE = 512;

CCheevos::CCheevos()
{
rc_runtime_init(&m_runtime);
m_cheevo_id = 0;
m_url = NULL;
}

void CCheevos::Initialize()
Expand All @@ -46,7 +50,9 @@ CCheevos& CCheevos::Get(void)

bool CCheevos::GenerateHashFromFile(char* hash, int consoleID, const char* filePath)
{
return rc_hash_generate_from_file(hash, consoleID, filePath) != 0;
int res = rc_hash_generate_from_file(hash, consoleID, filePath);
m_hash = hash;
return res != 0;
}

bool CCheevos::GetGameIDUrl(char* url, size_t size, const char* hash)
Expand All @@ -63,6 +69,12 @@ bool CCheevos::GetPatchFileUrl(char* url,
return rc_url_get_patch(url, size, username, token, gameID) == 0;
}

void CCheevos::SetRetroAchievementsCredentials(const char* username, const char* token)
{
m_username = username;
m_token = token;
}

bool CCheevos::PostRichPresenceUrl(char* url,
size_t urlSize,
char* postData,
Expand Down Expand Up @@ -91,6 +103,48 @@ void CCheevos::EvaluateRichPresence(char* evaluation, size_t size)
rc_evaluate_richpresence(m_richPresence, evaluation, size, PeekInternal, this, NULL);
}

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 char* game_hash)
{
return rc_url_award_cheevo(url, size, m_username.c_str(), m_token.c_str(), cheevo_id, 0,
game_hash) >= 0;
}

void CCheevos::GetCheevo_URL_ID(void (*Callback)(const char* achievement_url, unsigned cheevo_id))
{
this->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;
this->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<CCheevos*>(ud);
Expand Down
16 changes: 16 additions & 0 deletions src/cheevos/Cheevos.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ class CCheevos
void ResetRuntime();
bool GenerateHashFromFile(char* hash, int consoleID, const char* filePath);
bool GetGameIDUrl(char* url, size_t size, const char* hash);
void SetRetroAchievementsCredentials(const char* username, const char* token);
bool GetPatchFileUrl(
char* url, size_t size, const char* username, const char* token, unsigned gameID);
bool PostRichPresenceUrl(char* url,
Expand All @@ -42,7 +43,13 @@ class CCheevos
const char* richPresence);
void EnableRichPresence(const char* script);
void EvaluateRichPresence(char* evaluation, size_t size);
void ActivateAchievement(unsigned cheevo_id, const char* memaddr);
bool AwardAchievement(
char* url, size_t size, unsigned cheevo_id, int hardcore, const char* 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);
Expand All @@ -51,6 +58,9 @@ class CCheevos
size_t Reduse(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 (*Callback)(const char* achievement_url, unsigned cheevo_id);

rc_runtime_t m_runtime;
std::unordered_map<unsigned, const uint8_t*> m_addressFixups;
Expand All @@ -59,5 +69,11 @@ class CCheevos
rc_richpresence_t* m_richPresence = nullptr;
std::string m_richPresenceScript;
std::vector<char> m_richPresenceBuffer;

std::string m_hash;
std::string m_username;
std::string m_token;
char* m_url;
unsigned m_cheevo_id;
};
}
22 changes: 22 additions & 0 deletions src/client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,8 @@ GAME_ERROR CGameLibRetro::RunFrame()

m_client.retro_run();

CCheevos::Get().TestCheevoStatusPerFrame();

CLibretroEnvironment::Get().OnFrameEnd();

return GAME_ERROR_NO_ERROR;
Expand Down Expand Up @@ -493,6 +495,12 @@ GAME_ERROR CGameLibRetro::RCGetPatchFileUrl(char* 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(char* url,
size_t urlSize,
char* postData,
Expand Down Expand Up @@ -523,6 +531,20 @@ GAME_ERROR CGameLibRetro::GetRichPresenceEvaluation(char* evaluation, size_t siz
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();
Expand Down
4 changes: 4 additions & 0 deletions src/client.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ class ATTRIBUTE_HIDDEN CGameLibRetro
const char* username,
const char* token,
unsigned gameID) override;
GAME_ERROR SetRetroAchievementsCredentials(const char* username, const char* token);
GAME_ERROR RCPostRichPresenceUrl(char* url,
size_t urlSize,
char* postData,
Expand All @@ -88,7 +89,10 @@ class ATTRIBUTE_HIDDEN CGameLibRetro
const char* richPresence) override;
GAME_ERROR EnableRichPresence(const char* script) override;
GAME_ERROR GetRichPresenceEvaluation(char* evaluation, size_t size) 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();
Expand Down