Skip to content

Commit

Permalink
Merge pull request #17646 from hrydgard/rc-client
Browse files Browse the repository at this point in the history
Switch RetroAchievements support to the new rc_client_t API, add more features
  • Loading branch information
hrydgard committed Jul 10, 2023
2 parents f3d95a2 + c83abbf commit 591b9eb
Show file tree
Hide file tree
Showing 40 changed files with 1,359 additions and 2,169 deletions.
2 changes: 1 addition & 1 deletion Common/GPU/Vulkan/VulkanMemory.h
Expand Up @@ -5,6 +5,7 @@
#include <functional>
#include <vector>

#include "Common/Data/Collections/FastVec.h"
#include "Common/GPU/Vulkan/VulkanContext.h"
#include "Common/GPU/GPUBackendCommon.h"

Expand Down Expand Up @@ -205,4 +206,3 @@ class VulkanDescSetPool {
uint32_t usage_ = 0;
bool grow_;
};

3 changes: 3 additions & 0 deletions Common/Math/geom2d.h
Expand Up @@ -69,6 +69,9 @@ struct Bounds {
Bounds Expand(float xAmount, float yAmount) const {
return Bounds(x - xAmount, y - yAmount, w + xAmount * 2, h + yAmount * 2);
}
Bounds Expand(float left, float top, float right, float bottom) const {
return Bounds(x - left, y - top, w + left + right, h + top + bottom);
}
Bounds Offset(float xAmount, float yAmount) const {
return Bounds(x + xAmount, y + yAmount, w, h);
}
Expand Down
5 changes: 5 additions & 0 deletions Common/Serialize/Serializer.h
Expand Up @@ -147,6 +147,11 @@ class PointerWrap

void DoMarker(const char *prevName, u32 arbitraryNumber = 0x42);

void SkipBytes(size_t bytes) {
// Should work in all modes.
*ptr += bytes;
}

size_t Offset() const { return *ptr - ptrStart_; }

private:
Expand Down
100 changes: 98 additions & 2 deletions Common/System/OSD.cpp
Expand Up @@ -2,6 +2,7 @@

#include "Common/System/OSD.h"
#include "Common/TimeUtil.h"
#include "Common/Log.h"

OnScreenDisplay g_OSD;

Expand All @@ -17,6 +18,14 @@ void OnScreenDisplay::Update() {
}
}

for (auto iter = sideEntries_.begin(); iter != sideEntries_.end(); ) {
if (now >= iter->endTime) {
iter = sideEntries_.erase(iter);
} else {
iter++;
}
}

for (auto iter = bars_.begin(); iter != bars_.end(); ) {
if (now >= iter->endTime) {
iter = bars_.erase(iter);
Expand All @@ -31,6 +40,11 @@ std::vector<OnScreenDisplay::Entry> OnScreenDisplay::Entries() {
return entries_; // makes a copy.
}

std::vector<OnScreenDisplay::Entry> OnScreenDisplay::SideEntries() {
std::lock_guard<std::mutex> guard(mutex_);
return sideEntries_; // makes a copy.
}

std::vector<OnScreenDisplay::ProgressBar> OnScreenDisplay::ProgressBars() {
std::lock_guard<std::mutex> guard(mutex_);
return bars_; // makes a copy.
Expand Down Expand Up @@ -99,6 +113,88 @@ void OnScreenDisplay::ShowAchievementUnlocked(int achievementID) {
entries_.insert(entries_.begin(), msg);
}

void OnScreenDisplay::ShowAchievementProgress(int achievementID, float duration_s) {
double now = time_now_d();

for (auto &entry : sideEntries_) {
if (entry.numericID == achievementID && entry.type == OSDType::ACHIEVEMENT_PROGRESS) {
// Duplicate, let's just bump the timer.
entry.startTime = now;
entry.endTime = now + (double)duration_s;
// We're done.
return;
}
}

// OK, let's make a new side-entry.
Entry entry;
entry.numericID = achievementID;
entry.type = OSDType::ACHIEVEMENT_PROGRESS;
entry.startTime = now;
entry.endTime = now + (double)duration_s;
sideEntries_.insert(sideEntries_.begin(), entry);
}

void OnScreenDisplay::ShowChallengeIndicator(int achievementID, bool show) {
double now = time_now_d();

for (auto &entry : sideEntries_) {
if (entry.numericID == achievementID && entry.type == OSDType::ACHIEVEMENT_CHALLENGE_INDICATOR && !show) {
// Hide and eventually delete it.
entry.endTime = now + (double)FadeoutTime();
// Found it, we're done.
return;
}
}

if (!show) {
// Sanity check
return;
}

// OK, let's make a new side-entry.
Entry entry;
entry.numericID = achievementID;
entry.type = OSDType::ACHIEVEMENT_CHALLENGE_INDICATOR;
entry.startTime = now;
entry.endTime = now + 10000000.0; // Don't auto-fadeout.
sideEntries_.insert(sideEntries_.begin(), entry);
}

void OnScreenDisplay::ShowLeaderboardTracker(int leaderboardTrackerID, const char *trackerText, bool show) { // show=true is used both for create and update.
double now = time_now_d();

for (auto &entry : sideEntries_) {
if (entry.numericID == leaderboardTrackerID && entry.type == OSDType::LEADERBOARD_TRACKER) {
if (show) {
// Just an update.
entry.text = trackerText;
} else {
// Keep the current text, hide and eventually delete it.
entry.endTime = now + (double)FadeoutTime();
}
// Found it, we're done.
return;
}
}

if (!show) {
// Sanity check
return;
}

// OK, let's make a new side-entry.
Entry entry;
entry.numericID = leaderboardTrackerID;
entry.type = OSDType::LEADERBOARD_TRACKER;
entry.startTime = now;
entry.endTime = now + 10000000.0; // Don't auto-fadeout
if (trackerText) {
entry.text = trackerText;
}
sideEntries_.insert(sideEntries_.begin(), entry);
}

void OnScreenDisplay::ShowOnOff(const std::string &message, bool on, float duration_s) {
// TODO: translate "on" and "off"? Or just get rid of this whole thing?
Show(OSDType::MESSAGE_INFO, message + ": " + (on ? "on" : "off"), duration_s);
Expand Down Expand Up @@ -129,12 +225,12 @@ void OnScreenDisplay::SetProgressBar(std::string id, std::string &&message, int
bars_.push_back(bar);
}

void OnScreenDisplay::RemoveProgressBar(std::string id, float fadeout_s) {
void OnScreenDisplay::RemoveProgressBar(std::string id) {
std::lock_guard<std::mutex> guard(mutex_);
for (auto iter = bars_.begin(); iter != bars_.end(); iter++) {
if (iter->id == id) {
iter->progress = iter->maxValue;
iter->endTime = time_now_d() + (double)fadeout_s;
iter->endTime = time_now_d() + FadeoutTime();
break;
}
}
Expand Down
22 changes: 17 additions & 5 deletions Common/System/OSD.h
Expand Up @@ -16,8 +16,10 @@ enum class OSDType {

ACHIEVEMENT_UNLOCKED,

// PROGRESS_BAR,
// PROGRESS_INDETERMINATE,
// Side entries
ACHIEVEMENT_PROGRESS, // Achievement icon + "measured_progress" text, auto-hide after 2s
ACHIEVEMENT_CHALLENGE_INDICATOR, // Achievement icon ONLY, no auto-hide
LEADERBOARD_TRACKER,
};

// Data holder for on-screen messages.
Expand All @@ -31,7 +33,6 @@ class OnScreenDisplay {
Show(type, text, text2, "", duration_s, id);
}
void Show(OSDType type, const std::string &text, const std::string &text2, const std::string &icon, float duration_s = 0.0f, const char *id = nullptr);
void ShowAchievementUnlocked(int achievementID);

void ShowOnOff(const std::string &message, bool on, float duration_s = 0.0f);

Expand All @@ -40,10 +41,17 @@ class OnScreenDisplay {
// Call this every frame, cleans up old entries.
void Update();

// Specialized achievement-related types. These go to the side notifications, not the top-middle.
void ShowAchievementUnlocked(int achievementID);
void ShowAchievementProgress(int achievementID, float duration_s);
void ShowChallengeIndicator(int achievementID, bool show); // call with show=false to hide.
void ShowLeaderboardTracker(int leaderboardTrackerID, const char *trackerText, bool show); // show=true is used both for create and update.

// Progress bar controls
// Set is both create and update.
// Set is both create and update. If you set maxValue <= minValue, you'll create an "indeterminate" progress
// bar that doesn't show a specific amount of progress.
void SetProgressBar(std::string id, std::string &&message, int minValue, int maxValue, int progress);
void RemoveProgressBar(std::string id, float fadeout_s);
void RemoveProgressBar(std::string id);

struct Entry {
OSDType type;
Expand All @@ -66,10 +74,14 @@ class OnScreenDisplay {
};

std::vector<Entry> Entries();
std::vector<Entry> SideEntries();
std::vector<ProgressBar> ProgressBars();

static float FadeoutTime() { return 0.25f; }

private:
std::vector<Entry> entries_;
std::vector<Entry> sideEntries_;
std::vector<ProgressBar> bars_;
std::mutex mutex_;
};
Expand Down
11 changes: 11 additions & 0 deletions Common/UI/Context.cpp
Expand Up @@ -313,6 +313,17 @@ void UIContext::FillRect(const UI::Drawable &drawable, const Bounds &bounds) {
}
}

void UIContext::DrawRectDropShadow(const Bounds &bounds, float radius, float alpha, uint32_t color) {
if (alpha <= 0.0f)
return;

color = colorAlpha(color, alpha);

// Bias the shadow downwards a bit.
Bounds shadowBounds = bounds.Expand(radius, 0.5 * radius, radius, 1.5 * radius);
Draw()->DrawImage4Grid(theme->dropShadow4Grid, shadowBounds.x, shadowBounds.y, shadowBounds.x2(), shadowBounds.y2(), color, radius * (1.0f / 24.0f) * 2.0f);
}

void UIContext::DrawImageVGradient(ImageID image, uint32_t color1, uint32_t color2, const Bounds &bounds) {
uidrawbuffer_->DrawImageStretchVGradient(image, bounds.x, bounds.y, bounds.x2(), bounds.y2(), color1, color2);
}
Expand Down
3 changes: 3 additions & 0 deletions Common/UI/Context.h
Expand Up @@ -77,6 +77,8 @@ class UIContext {

void SetTintSaturation(float tint, float sat);

// High level drawing functions. They generally assume the default texture to be bounds.

void SetFontStyle(const UI::FontStyle &style);
const UI::FontStyle &GetFontStyle() { return *fontStyle_; }
void SetFontScale(float scaleX, float scaleY);
Expand All @@ -88,6 +90,7 @@ class UIContext {
void DrawTextRect(const char *str, const Bounds &bounds, uint32_t color, int align = 0);
void DrawTextShadowRect(const char *str, const Bounds &bounds, uint32_t color, int align = 0);
void FillRect(const UI::Drawable &drawable, const Bounds &bounds);
void DrawRectDropShadow(const Bounds &bounds, float radius, float alpha, uint32_t color = 0);
void DrawImageVGradient(ImageID image, uint32_t color1, uint32_t color2, const Bounds &bounds);

// in dps, like dp_xres and dp_yres
Expand Down
13 changes: 5 additions & 8 deletions Core/Config.cpp
Expand Up @@ -266,20 +266,17 @@ static bool DefaultSasThread() {

static const ConfigSetting achievementSettings[] = {
ConfigSetting("AchievementsEnable", &g_Config.bAchievementsEnable, true, CfgFlag::DEFAULT),
ConfigSetting("AchievementsLeaderboards", &g_Config.bAchievementsLeaderboards, false, CfgFlag::DEFAULT),
ConfigSetting("AchievementsTestMode", &g_Config.bAchievementsTestMode, false, CfgFlag::DEFAULT),
ConfigSetting("AchievementsUnofficialTestMode", &g_Config.bAchievementsUnofficialTestMode, false, CfgFlag::DEFAULT),
ConfigSetting("AchievementsRichPresence", &g_Config.bAchievementsRichPresence, true, CfgFlag::DEFAULT),
ConfigSetting("AchievementsChallengeMode", &g_Config.bAchievementsChallengeMode, false, CfgFlag::DEFAULT),
ConfigSetting("AchievementsEncoreMode", &g_Config.bAchievementsEncoreMode, false, CfgFlag::DEFAULT),
ConfigSetting("AchievementsUnofficial", &g_Config.bAchievementsUnofficial, false, CfgFlag::DEFAULT),
ConfigSetting("AchievementsSoundEffects", &g_Config.bAchievementsSoundEffects, true, CfgFlag::DEFAULT),
ConfigSetting("AchievementsNotifications", &g_Config.bAchievementsNotifications, true, CfgFlag::DEFAULT),
ConfigSetting("AchievementsLogBadMemReads", &g_Config.bAchievementsLogBadMemReads, false, CfgFlag::DEFAULT),

// Achievements login info. Note that password is NOT stored, only a login token.
// And that login token is stored separately from the ini, see NativeSaveSecret.
ConfigSetting("AchievementsUserName", &g_Config.sAchievementsUserName, "", CfgFlag::DEFAULT),
// And that login token is stored separately from the ini, see NativeSaveSecret, but it can also be loaded
// from the ini if manually entered (useful when testing various builds on Android).
ConfigSetting("AchievementsToken", &g_Config.sAchievementsToken, "", CfgFlag::DONT_SAVE),
ConfigSetting("AchievementsLoginTimestamp", &g_Config.sAchievementsLoginTimestamp, "", CfgFlag::DEFAULT),
ConfigSetting("AchievementsUserName", &g_Config.sAchievementsUserName, "", CfgFlag::DEFAULT),
};

static const ConfigSetting cpuSettings[] = {
Expand Down
8 changes: 2 additions & 6 deletions Core/Config.h
Expand Up @@ -488,20 +488,16 @@ struct Config {
// Retro Achievement settings
// Copied from Duckstation, we might want to remove some.
bool bAchievementsEnable;
bool bAchievementsLeaderboards;
bool bAchievementsTestMode;
bool bAchievementsUnofficialTestMode;
bool bAchievementsRichPresence;
bool bAchievementsChallengeMode;
bool bAchievementsEncoreMode;
bool bAchievementsUnofficial;
bool bAchievementsSoundEffects;
bool bAchievementsNotifications;
bool bAchievementsLogBadMemReads;

// Achivements login info. Note that password is NOT stored, only a login token.
// Still, we may wanna store it more securely than in PPSSPP.ini, especially on Android.
std::string sAchievementsUserName;
std::string sAchievementsToken; // Not saved, to be used if you want to manually make your RA login persistent. See Native_SaveSecret for the normal case.
std::string sAchievementsLoginTimestamp;

// Various directories. Autoconfigured, not read from ini.
Path currentDirectory; // The directory selected in the game browsing window.
Expand Down
14 changes: 10 additions & 4 deletions Core/CwCheat.cpp
Expand Up @@ -19,6 +19,7 @@
#include "Core/System.h"
#include "Core/HLE/sceCtrl.h"
#include "Core/MIPS/JitCommon/JitCommon.h"
#include "Core/RetroAchievements.h"
#include "GPU/Common/PostShader.h"

#ifdef _WIN32
Expand Down Expand Up @@ -319,9 +320,11 @@ void __CheatDoState(PointerWrap &p) {
}

void hleCheat(u64 userdata, int cyclesLate) {
if (cheatsEnabled != g_Config.bEnableCheats) {
bool shouldBeEnabled = !Achievements::ChallengeModeActive() && g_Config.bEnableCheats;

if (cheatsEnabled != shouldBeEnabled) {
// Okay, let's move to the desired state, then.
if (g_Config.bEnableCheats) {
if (shouldBeEnabled) {
__CheatStart();
} else {
__CheatStop();
Expand Down Expand Up @@ -1193,6 +1196,10 @@ void CWCheatEngine::ExecuteOp(const CheatOperation &op, const CheatCode &cheat,
}

void CWCheatEngine::Run() {
if (Achievements::ChallengeModeActive()) {
return;
}

for (CheatCode cheat : cheats_) {
// InterpretNextOp and ExecuteOp move i.
for (size_t i = 0; i < cheat.lines.size(); ) {
Expand All @@ -1207,8 +1214,7 @@ bool CWCheatEngine::HasCheats() {
}

bool CheatsInEffect() {
if (!cheatEngine || !cheatsEnabled)
if (!cheatEngine || !cheatsEnabled || Achievements::ChallengeModeActive())
return false;
return cheatEngine->HasCheats();
}

16 changes: 10 additions & 6 deletions Core/HLE/sceDisplay.cpp
Expand Up @@ -49,6 +49,7 @@
#include "Core/HLE/sceKernelInterrupt.h"
#include "Core/HW/Display.h"
#include "Core/Util/PPGeDraw.h"
#include "Core/RetroAchievements.h"

#include "GPU/GPU.h"
#include "GPU/GPUState.h"
Expand Down Expand Up @@ -348,12 +349,15 @@ void __DisplaySetWasPaused() {
}

static int FrameTimingLimit() {
if (PSP_CoreParameter().fpsLimit == FPSLimit::CUSTOM1)
return g_Config.iFpsLimit1;
if (PSP_CoreParameter().fpsLimit == FPSLimit::CUSTOM2)
return g_Config.iFpsLimit2;
if (PSP_CoreParameter().fpsLimit == FPSLimit::ANALOG)
return PSP_CoreParameter().analogFpsLimit;
if (!Achievements::ChallengeModeActive()) {
if (PSP_CoreParameter().fpsLimit == FPSLimit::CUSTOM1)
return g_Config.iFpsLimit1;
if (PSP_CoreParameter().fpsLimit == FPSLimit::CUSTOM2)
return g_Config.iFpsLimit2;
if (PSP_CoreParameter().fpsLimit == FPSLimit::ANALOG)
return PSP_CoreParameter().analogFpsLimit;
}
// Note: Fast-forward is OK in challenge mode.
if (PSP_CoreParameter().fastForward)
return 0;
return framerate;
Expand Down
3 changes: 1 addition & 2 deletions Core/HLE/sceKernel.cpp
Expand Up @@ -85,8 +85,7 @@
#include "sceDmac.h"
#include "sceMp4.h"
#include "sceOpenPSID.h"

#include "../Util/PPGeDraw.h"
#include "Core/Util/PPGeDraw.h"

/*
17: [MIPS32 R4K 00000000 ]: Loader: Type: 1 Vaddr: 00000000 Filesz: 2856816 Memsz: 2856816
Expand Down

0 comments on commit 591b9eb

Please sign in to comment.