// SPDX-FileCopyrightText: 2019-2025 Connor McLaughlin <[email protected]>1// SPDX-License-Identifier: CC-BY-NC-ND-4.023#pragma once45#include "common/small_string.h"6#include "common/types.h"78#include <array>9#include <functional>10#include <mutex>11#include <optional>12#include <span>13#include <string>14#include <utility>15#include <vector>1617class Error;18class ProgressCallback;19class StateWrapper;20class CDImage;2122struct Settings;2324namespace Achievements {2526enum class LoginRequestReason27{28UserInitiated,29TokenInvalid,30};3132inline constexpr size_t GAME_HASH_LENGTH = 16;33using GameHash = std::array<u8, GAME_HASH_LENGTH>;3435struct HashDatabaseEntry36{37GameHash hash;38u32 game_id;39u32 num_achievements;40};4142class ProgressDatabase43{44public:45struct Entry46{47u32 game_id;48u16 num_achievements_unlocked;49u16 num_hc_achievements_unlocked;50};5152ProgressDatabase();53~ProgressDatabase();5455bool Load(Error* error);5657const Entry* LookupGame(u32 game_id) const;5859private:60std::vector<Entry> m_entries;61};6263/// Acquires the achievements lock. Must be held when accessing any achievement state from another thread.64std::unique_lock<std::recursive_mutex> GetLock();6566/// Returns the achievements game hash for a given disc.67std::optional<GameHash> GetGameHash(CDImage* image);68std::optional<GameHash> GetGameHash(const std::string_view executable_name, std::span<const u8> executable_data);6970/// Returns the number of achievements for a given hash.71const HashDatabaseEntry* LookupGameHash(const GameHash& hash);7273/// Converts a game hash to a string for display. If the hash is nullopt, returns "[NO HASH]".74TinyString GameHashToString(const std::optional<GameHash>& hash);7576/// Initializes the RetroAchievments client.77bool Initialize();7879/// Updates achievements settings.80void UpdateSettings(const Settings& old_config);8182/// Shuts down the RetroAchievements client.83void Shutdown();8485/// Call to refresh the all-progress database.86bool RefreshAllProgressDatabase(ProgressCallback* progress, Error* error);8788/// Called when the system is start. Engages hardcore mode if enabled.89void OnSystemStarting(CDImage* image, bool disable_hardcore_mode);9091/// Called when the system is shutting down. If this returns false, the shutdown should be aborted.92void OnSystemDestroyed();9394/// Called when the system is being reset. Resets the internal state of all achievement tracking.95void OnSystemReset();9697/// Called when the system changes game.98void GameChanged(CDImage* image);99100/// Called once a frame at vsync time on the CPU thread.101void FrameUpdate();102103/// Called when the system is paused, because FrameUpdate() won't be getting called.104void IdleUpdate();105106/// Returns true if idle updates are necessary (e.g. outstanding requests).107bool NeedsIdleUpdate();108109/// Saves/loads state.110bool DoState(StateWrapper& sw);111112/// Attempts to log in to RetroAchievements using the specified credentials.113/// If the login is successful, the token returned by the server will be saved.114bool Login(const char* username, const char* password, Error* error);115116/// Logs out of RetroAchievements, clearing any credentials.117void Logout();118119/// Forces hardcore mode off until next reset.120void DisableHardcoreMode(bool show_message, bool display_game_summary);121122/// Prompts the user to disable hardcore mode. Invokes callback with result.123void ConfirmHardcoreModeDisableAsync(std::string_view trigger, std::function<void(bool)> callback);124125/// Returns true if hardcore mode is active, and functionality should be restricted.126bool IsHardcoreModeActive();127128/// RAIntegration only exists for Windows, so no point checking it on other platforms.129bool IsUsingRAIntegration();130bool IsRAIntegrationAvailable();131132/// Returns true if the achievement system is active. Achievements can be active without a valid client.133bool IsActive();134135/// Returns true if RetroAchievements game data has been loaded.136bool HasActiveGame();137138/// Returns the RetroAchievements ID for the current game.139u32 GetGameID();140141/// Returns true if the current game has any achievements or leaderboards.142bool HasAchievementsOrLeaderboards();143144/// Returns true if the current game has any leaderboards.145bool HasAchievements();146147/// Returns true if the current game has any leaderboards.148bool HasLeaderboards();149150/// Returns true if the game supports rich presence.151bool HasRichPresence();152153/// Returns the current rich presence string.154/// Should be called with the lock held.155const std::string& GetRichPresenceString();156157/// Returns the URL for the current icon of the game158const std::string& GetGameIconURL();159160/// Returns the path for the current icon of the game161const std::string& GetGameIconPath();162163/// Returns the RetroAchievements title for the current game.164/// Should be called with the lock held.165const std::string& GetGameTitle();166167/// Returns the path for the game that is current hashed/running.168const std::string& GetGamePath();169170/// Returns true if the user has been successfully logged in.171bool IsLoggedIn();172173/// Returns true if the user has been successfully logged in, or the request is in progress.174bool IsLoggedInOrLoggingIn();175176/// Returns the logged-in user name.177const char* GetLoggedInUserName();178179/// Returns the path to the user's profile avatar.180/// Should be called with the lock held.181const std::string& GetLoggedInUserBadgePath();182183/// Returns a summary of the user's points.184/// Should be called with the lock held.185SmallString GetLoggedInUserPointsSummary();186187/// Returns the path to the local cache for the specified badge name.188std::string GetGameBadgePath(std::string_view badge_name);189190/// Downloads game icons from RetroAchievements for all games that have an achievements_game_id.191/// This fetches the game badge images that are normally downloaded when a game is opened.192bool DownloadGameIcons(ProgressCallback* progress, Error* error);193194/// Returns 0 if pausing is allowed, otherwise the number of frames until pausing is allowed.195u32 GetPauseThrottleFrames();196197/// Returns the number of unlocks that have not been synchronized with the server.198u32 GetPendingUnlockCount();199200/// The name of the RetroAchievements icon, which can be used in notifications.201extern const char* const RA_LOGO_ICON_NAME;202203} // namespace Achievements204205/// Functions implemented in the frontend.206namespace Host {207208/// Called if the big picture UI requests achievements login, or token login fails.209void OnAchievementsLoginRequested(Achievements::LoginRequestReason reason);210211/// Called when achievements login completes.212void OnAchievementsLoginSuccess(const char* display_name, u32 points, u32 sc_points, u32 unread_messages);213214/// Called when achievements login completes or they are disabled.215void OnAchievementsActiveChanged(bool active);216217/// Called whenever hardcore mode is toggled.218void OnAchievementsHardcoreModeChanged(bool enabled);219220#ifdef RC_CLIENT_SUPPORTS_RAINTEGRATION221222/// Called when the RAIntegration menu changes.223void OnRAIntegrationMenuChanged();224225#endif226227} // namespace Host228229230