Skip to content

Commit

Permalink
Merge pull request #17589 from hrydgard/retroachievements-initial-work
Browse files Browse the repository at this point in the history
Retroachievements support (work-in-progress)
  • Loading branch information
hrydgard authored Jun 26, 2023
2 parents db8f660 + 81e1293 commit 01cf22e
Show file tree
Hide file tree
Showing 48 changed files with 4,097 additions and 114 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -131,3 +131,5 @@ CMakeFiles
.cache/
build
libretro/obj/local

ppsspp_retroachievements.dat
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,6 @@
[submodule "cpu_features"]
path = ext/cpu_features
url = https://github.com/google/cpu_features.git
[submodule "ext/rcheevos"]
path = ext/rcheevos
url = https://github.com/RetroAchievements/rcheevos.git
6 changes: 5 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1418,6 +1418,10 @@ list(APPEND NativeAppSource
UI/CustomButtonMappingScreen.cpp
UI/Theme.h
UI/Theme.cpp
UI/RetroAchievements.cpp
UI/RetroAchievements.h
UI/RetroAchievementScreens.cpp
UI/RetroAchievementScreens.h
)

if(ANDROID)
Expand Down Expand Up @@ -2214,7 +2218,7 @@ else()
include_directories(ext/zstd/lib)
endif()

target_link_libraries(${CoreLibName} Common native kirk cityhash sfmt19937 xbrz xxhash ${GlslangLibs}
target_link_libraries(${CoreLibName} Common native kirk cityhash sfmt19937 xbrz xxhash rcheevos ${GlslangLibs}
${CoreExtraLibs} ${OPENGL_LIBRARIES} ${X11_LIBRARIES} ${CMAKE_DL_LIBS})

target_compile_features(${CoreLibName} PUBLIC cxx_std_17)
Expand Down
2 changes: 1 addition & 1 deletion Common/Data/Collections/TinySet.h
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ struct FixedTinyVec {
bool operator == (const FixedTinyVec<T, MaxSize> &other) const {
if (count_ != other.count_)
return false;
for (size_t i = 0; i < count_; i++) {
for (int i = 0; i < count_; i++) {
if (!(data_[i] == other.data_[i])) {
return false;
}
Expand Down
1 change: 1 addition & 0 deletions Common/Data/Text/I18n.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ static const char * const g_categoryNames[(size_t)I18NCat::CATEGORY_COUNT] = {
"UI Elements",
"Upgrade",
"VR",
"Achievements",
};

I18NRepo g_i18nrepo;
Expand Down
1 change: 1 addition & 0 deletions Common/Data/Text/I18n.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ enum class I18NCat : uint8_t {
UI_ELEMENTS,
UPGRADE,
VR,
ACHIEVEMENTS,
CATEGORY_COUNT,
NONE = CATEGORY_COUNT,
};
Expand Down
13 changes: 12 additions & 1 deletion Common/File/Path.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,9 @@ Path Path::operator /(const std::string &subdir) const {
}

// Direct string manipulation.

if (path_.empty()) {
return Path(subdir);
}
if (subdir.empty()) {
return Path(path_);
}
Expand Down Expand Up @@ -258,6 +260,15 @@ std::wstring Path::ToWString() const {
}
return w;
}
std::string Path::ToCString() const {
std::string w = path_;
for (size_t i = 0; i < w.size(); i++) {
if (w[i] == '/') {
w[i] = '\\';
}
}
return w;
}
#endif

std::string Path::ToVisualString(const char *relativeRoot) const {
Expand Down
5 changes: 5 additions & 0 deletions Common/File/Path.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,11 @@ class Path {

#if PPSSPP_PLATFORM(WINDOWS)
std::wstring ToWString() const;
std::string ToCString() const; // Flips the slashes back to Windows standard, but string still UTF-8.
#else
std::string ToCString() const {
return ToString();
}
#endif

// Pass in a relative root to turn the path into a relative path - if it is one!
Expand Down
3 changes: 3 additions & 0 deletions Common/Log.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,9 @@ enum LOG_TYPE {
SCEMISC,

NUMBER_OF_LOGS, // Must be last

// Temporary aliases
ACHIEVEMENTS = HLE, // TODO: Make a real category
};

enum LOG_LEVELS : int {
Expand Down
7 changes: 7 additions & 0 deletions Common/Math/geom2d.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,13 @@ struct Bounds {
return Bounds(x + left, y + top, w - left - right, h - bottom - top);
}

Bounds Inset(float xAmount, float yAmount) const {
return Bounds(x + xAmount, y + yAmount, w - xAmount * 2, h - yAmount * 2);
}
Bounds Inset(float left, float top, float right, float bottom) const {
return Bounds(x + left, y + top, w - left - right, h - top - bottom);
}

float x;
float y;
float w;
Expand Down
4 changes: 4 additions & 0 deletions Common/Net/HTTPClient.h
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,10 @@ class Downloader {

std::vector<float> GetCurrentProgress();

size_t GetActiveCount() const {
return downloads_.size();
}

private:
std::vector<std::shared_ptr<Download>> downloads_;
// These get copied to downloads_ in Update(). It's so that callbacks can add new downloads
Expand Down
3 changes: 3 additions & 0 deletions Common/System/NativeApp.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,3 +87,6 @@ void NativeShutdownGraphics();
void NativeShutdown();

void PostLoadConfig();

void NativeSaveSecret(const char *nameOfSecret, const std::string &data);
std::string NativeLoadSecret(const char *nameOfSecret);
18 changes: 17 additions & 1 deletion Common/System/Request.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ std::vector<OnScreenDisplay::ProgressBar> OnScreenDisplay::ProgressBars() {
return bars_; // makes a copy.
}

void OnScreenDisplay::Show(OSDType type, const std::string &text, const std::string &text2, float duration_s, const char *id) {
void OnScreenDisplay::Show(OSDType type, const std::string &text, const std::string &text2, const std::string &icon, float duration_s, const char *id) {
// Automatic duration based on type.
if (duration_s <= 0.0f) {
switch (type) {
Expand Down Expand Up @@ -70,6 +70,7 @@ void OnScreenDisplay::Show(OSDType type, const std::string &text, const std::str
msg.text = text;
msg.text2 = text2;
msg.type = type;
msg.iconName = icon;
// Move to top (should we? maybe not?)
entries_.erase(iter);
entries_.insert(entries_.begin(), msg);
Expand All @@ -81,12 +82,27 @@ void OnScreenDisplay::Show(OSDType type, const std::string &text, const std::str
Entry msg;
msg.text = text;
msg.text2 = text2;
msg.iconName = icon;
msg.startTime = now;
msg.endTime = now + duration_s;
msg.type = type;
msg.id = id;
entries_.insert(entries_.begin(), msg);
}

void OnScreenDisplay::ShowAchievementUnlocked(int achievementID) {
double now = time_now_d();

double duration_s = 5.0;

Entry msg;
msg.numericID = achievementID;
msg.type = OSDType::ACHIEVEMENT_UNLOCKED;
msg.startTime = now;
msg.endTime = now + duration_s;
entries_.insert(entries_.begin(), msg);
}

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
14 changes: 12 additions & 2 deletions Common/System/System.h
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,9 @@ enum class OSDType {
MESSAGE_ERROR,
MESSAGE_ERROR_DUMP, // displays lots of text (after the first line), small size
MESSAGE_FILE_LINK,

ACHIEVEMENT_UNLOCKED,

// PROGRESS_BAR,
// PROGRESS_INDETERMINATE,
};
Expand All @@ -234,7 +237,12 @@ class OnScreenDisplay {
void Show(OSDType type, const std::string &text, float duration_s = 0.0f, const char *id = nullptr) {
Show(type, text, "", duration_s, id);
}
void Show(OSDType type, const std::string &text, const std::string &text2, float duration_s = 0.0f, const char *id = nullptr);
void Show(OSDType type, const std::string &text, const std::string &text2, float duration_s = 0.0f, const char *id = nullptr) {
Show(type, text, "", "", 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);

bool IsEmpty() const { return entries_.empty(); } // Shortcut to skip rendering.
Expand All @@ -251,9 +259,11 @@ class OnScreenDisplay {
OSDType type;
std::string text;
std::string text2;
std::string iconName;
int numericID;
const char *id;
double startTime;
double endTime;
double duration;
};

struct ProgressBar {
Expand Down
10 changes: 10 additions & 0 deletions Common/UI/IconCache.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,16 @@ class IconCache {

IconCacheStats GetStats();

// for testing
std::string GetFirstIconName() const {
if (!cache_.empty()) {
return cache_.begin()->first;
} else if (!pending_.empty()) {
return *pending_.begin();
}
return "";
}

private:
struct Entry {
std::string data;
Expand Down
19 changes: 19 additions & 0 deletions Core/Config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,24 @@ static bool DefaultSasThread() {
return cpu_info.num_cores > 1;
}

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("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),
ConfigSetting("AchievementsToken", &g_Config.sAchievementsToken, "", CfgFlag::DONT_SAVE),
ConfigSetting("AchievementsLoginTimestamp", &g_Config.sAchievementsLoginTimestamp, "", CfgFlag::DEFAULT),
};

static const ConfigSetting cpuSettings[] = {
ConfigSetting("CPUCore", &g_Config.iCpuCore, &DefaultCpuCore, CfgFlag::PER_GAME | CfgFlag::REPORT),
ConfigSetting("SeparateSASThread", &g_Config.bSeparateSASThread, &DefaultSasThread, CfgFlag::PER_GAME | CfgFlag::REPORT),
Expand Down Expand Up @@ -887,6 +905,7 @@ static const ConfigSectionSettings sections[] = {
{"Upgrade", upgradeSettings, ARRAY_SIZE(upgradeSettings)},
{"Theme", themeSettings, ARRAY_SIZE(themeSettings)},
{"VR", vrSettings, ARRAY_SIZE(vrSettings)},
{"Achievements", achievementSettings, ARRAY_SIZE(achievementSettings)},
};

const size_t numSections = ARRAY_SIZE(sections);
Expand Down
18 changes: 18 additions & 0 deletions Core/Config.h
Original file line number Diff line number Diff line change
Expand Up @@ -482,6 +482,24 @@ struct Config {
bool bShowFrameProfiler;
bool bGpuLogProfiler; // Controls the Vulkan logging profiler (profiles textures uploads etc).

// 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 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.
Path defaultCurrentDirectory; // Platform dependent, initialized at startup.
Expand Down
2 changes: 1 addition & 1 deletion Core/HLE/sceSas.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,7 @@ static u32 _sceSasCoreWithMix(u32 core, u32 inoutAddr, int leftVolume, int right

static u32 sceSasSetVoice(u32 core, int voiceNum, u32 vagAddr, int size, int loop) {
if (voiceNum >= PSP_SAS_VOICES_MAX || voiceNum < 0) {
return hleLogWarning(SCESAS, ERROR_SAS_INVALID_VOICE, "invalid voicenum");
return hleLogVerbose(SCESAS, ERROR_SAS_INVALID_VOICE, "invalid voicenum");
}

if (size == 0 || ((u32)size & 0xF) != 0) {
Expand Down
2 changes: 1 addition & 1 deletion UI/DevScreens.h
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ class SystemInfoScreen : public TabbedUIDialogScreenWithGameBackground {
void CreateTabs() override;

protected:
bool ShowSearchControls() override { return false; }
bool ShowSearchControls() const override { return false; }
};

class AddressPromptScreen : public PopupScreen {
Expand Down
5 changes: 5 additions & 0 deletions UI/EmuScreen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ using namespace std::placeholders;
#include "UI/ProfilerDraw.h"
#include "UI/DiscordIntegration.h"
#include "UI/ChatScreen.h"
#include "UI/RetroAchievements.h"

#include "Core/Reporting.h"

Expand Down Expand Up @@ -346,6 +347,8 @@ void EmuScreen::bootGame(const Path &filename) {
g_OSD.Show(OSDType::MESSAGE_WARNING, gr->T("DefaultCPUClockRequired", "Warning: This game requires the CPU clock to be set to default."), 10.0f);
}

Achievements::GameChanged(filename);

loadingViewColor_->Divert(0xFFFFFFFF, 0.75f);
loadingViewVisible_->Divert(UI::V_VISIBLE, 0.75f);

Expand Down Expand Up @@ -1126,6 +1129,8 @@ void EmuScreen::update() {
}
}
}

Achievements::FrameUpdate();
}

void EmuScreen::checkPowerDown() {
Expand Down
6 changes: 6 additions & 0 deletions UI/GameSettingsScreen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
#include "UI/GPUDriverTestScreen.h"
#include "UI/MemStickScreen.h"
#include "UI/Theme.h"
#include "UI/RetroAchievementScreens.h"

#include "Common/File/FileUtil.h"
#include "Common/File/AndroidContentURI.h"
Expand Down Expand Up @@ -852,6 +853,11 @@ void GameSettingsScreen::CreateSystemSettings(UI::ViewGroup *systemSettings) {

systemSettings->Add(new ItemHeader(sy->T("UI")));

systemSettings->Add(new Choice(sy->T("RetroAchievements")))->OnClick.Add([&](UI::EventParams &) -> UI::EventReturn {
screenManager()->push(new RetroAchievementsSettingsScreen(gamePath_));
return UI::EVENT_DONE;
});

auto langCodeToName = [](const char *value) -> std::string {
auto &mapping = g_Config.GetLangValuesMapping();
auto iter = mapping.find(value);
Expand Down
1 change: 1 addition & 0 deletions UI/MiscScreens.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -972,6 +972,7 @@ void CreditsScreen::render() {
"adenovan",
"iota97",
"Lubos",
"stenzek", // For retroachievements integration
"",
cr->T("specialthanks", "Special thanks to:"),
specialthanksMaxim.c_str(),
Expand Down
Loading

0 comments on commit 01cf22e

Please sign in to comment.