duckstation

duckstation, but archived from the revision just before upstream changed it to a proprietary software project, this version is the libre one
git clone https://git.neptards.moe/u3shit/duckstation.git
Log | Files | Refs | README | LICENSE

rc_client.h (27476B)


      1 #ifndef RC_CLIENT_H
      2 #define RC_CLIENT_H
      3 
      4 #include "rc_api_request.h"
      5 #include "rc_error.h"
      6 
      7 #include <stddef.h>
      8 #include <stdint.h>
      9 #include <time.h>
     10 
     11 RC_BEGIN_C_DECLS
     12 
     13 /* implementation abstracted in rc_client_internal.h */
     14 typedef struct rc_client_t rc_client_t;
     15 typedef struct rc_client_async_handle_t rc_client_async_handle_t;
     16 
     17 /*****************************************************************************\
     18 | Callbacks                                                                   |
     19 \*****************************************************************************/
     20 
     21 /**
     22  * Callback used to read num_bytes bytes from memory starting at address into buffer.
     23  * Returns the number of bytes read. A return value of 0 indicates the address was invalid.
     24  */
     25 typedef uint32_t (RC_CCONV *rc_client_read_memory_func_t)(uint32_t address, uint8_t* buffer, uint32_t num_bytes, rc_client_t* client);
     26 
     27 /**
     28  * Internal method passed to rc_client_server_call_t to process the server response.
     29  */
     30 typedef void (RC_CCONV *rc_client_server_callback_t)(const rc_api_server_response_t* server_response, void* callback_data);
     31 
     32 /**
     33  * Callback used to issue a request to the server.
     34  */
     35 typedef void (RC_CCONV *rc_client_server_call_t)(const rc_api_request_t* request, rc_client_server_callback_t callback, void* callback_data, rc_client_t* client);
     36 
     37 /**
     38  * Generic callback for asynchronous eventing.
     39  */
     40 typedef void (RC_CCONV *rc_client_callback_t)(int result, const char* error_message, rc_client_t* client, void* userdata);
     41 
     42 /**
     43  * Callback for logging or displaying a message.
     44  */
     45 typedef void (RC_CCONV *rc_client_message_callback_t)(const char* message, const rc_client_t* client);
     46 
     47 /*****************************************************************************\
     48 | Runtime                                                                     |
     49 \*****************************************************************************/
     50 
     51 /**
     52  * Creates a new rc_client_t object.
     53  */
     54 RC_EXPORT rc_client_t* RC_CCONV rc_client_create(rc_client_read_memory_func_t read_memory_function, rc_client_server_call_t server_call_function);
     55 
     56 /**
     57  * Releases resources associated to a rc_client_t object.
     58  * Pointer will no longer be valid after making this call.
     59  */
     60 RC_EXPORT void RC_CCONV rc_client_destroy(rc_client_t* client);
     61 
     62 /**
     63  * Sets whether hardcore is enabled (on by default).
     64  * Can be called with a game loaded.
     65  * Enabling hardcore with a game loaded will raise an RC_CLIENT_EVENT_RESET
     66  * event. Processing will be disabled until rc_client_reset is called.
     67  */
     68 RC_EXPORT void RC_CCONV rc_client_set_hardcore_enabled(rc_client_t* client, int enabled);
     69 
     70 /**
     71  * Gets whether hardcore is enabled (on by default).
     72  */
     73 RC_EXPORT int RC_CCONV rc_client_get_hardcore_enabled(const rc_client_t* client);
     74 
     75 /**
     76  * Sets whether encore mode is enabled (off by default).
     77  * Evaluated when loading a game. Has no effect while a game is loaded.
     78  */
     79 RC_EXPORT void RC_CCONV rc_client_set_encore_mode_enabled(rc_client_t* client, int enabled);
     80 
     81 /**
     82  * Gets whether encore mode is enabled (off by default).
     83  */
     84 RC_EXPORT int RC_CCONV rc_client_get_encore_mode_enabled(const rc_client_t* client);
     85 
     86 /**
     87  * Sets whether unofficial achievements should be loaded.
     88  * Evaluated when loading a game. Has no effect while a game is loaded.
     89  */
     90 RC_EXPORT void RC_CCONV rc_client_set_unofficial_enabled(rc_client_t* client, int enabled);
     91 
     92 /**
     93  * Gets whether unofficial achievements should be loaded.
     94  */
     95 RC_EXPORT int RC_CCONV rc_client_get_unofficial_enabled(const rc_client_t* client);
     96 
     97 /**
     98  * Sets whether spectator mode is enabled (off by default).
     99  * If enabled, events for achievement unlocks and leaderboard submissions will be
    100  * raised, but server calls to actually perform the unlock/submit will not occur.
    101  * Can be modified while a game is loaded. Evaluated at unlock/submit time.
    102  * Cannot be modified if disabled before a game is loaded.
    103  */
    104 RC_EXPORT void RC_CCONV rc_client_set_spectator_mode_enabled(rc_client_t* client, int enabled);
    105 
    106 /**
    107  * Gets whether spectator mode is enabled (off by default).
    108  */
    109 RC_EXPORT int RC_CCONV rc_client_get_spectator_mode_enabled(const rc_client_t* client);
    110 
    111 /**
    112  * Attaches client-specific data to the runtime.
    113  */
    114 RC_EXPORT void RC_CCONV rc_client_set_userdata(rc_client_t* client, void* userdata);
    115 
    116 /**
    117  * Gets the client-specific data attached to the runtime.
    118  */
    119 RC_EXPORT void* RC_CCONV rc_client_get_userdata(const rc_client_t* client);
    120 
    121 /**
    122  * Sets the name of the server to use.
    123  */
    124 RC_EXPORT void RC_CCONV rc_client_set_host(const rc_client_t* client, const char* hostname);
    125 
    126 typedef uint64_t rc_clock_t;
    127 typedef rc_clock_t (RC_CCONV *rc_get_time_millisecs_func_t)(const rc_client_t* client);
    128 
    129 /**
    130  * Specifies a function that returns a value that increases once per millisecond.
    131  */
    132 RC_EXPORT void RC_CCONV rc_client_set_get_time_millisecs_function(rc_client_t* client, rc_get_time_millisecs_func_t handler);
    133 
    134 /**
    135  * Marks an async process as aborted. The associated callback will not be called.
    136  */
    137 RC_EXPORT void RC_CCONV rc_client_abort_async(rc_client_t* client, rc_client_async_handle_t* async_handle);
    138 
    139 /**
    140  * Gets a clause that can be added to the User-Agent to identify the version of rcheevos being used.
    141  */
    142 RC_EXPORT size_t RC_CCONV rc_client_get_user_agent_clause(rc_client_t* client, char buffer[], size_t buffer_size);
    143 
    144 /*****************************************************************************\
    145 | Logging                                                                     |
    146 \*****************************************************************************/
    147 
    148 /**
    149  * Sets the logging level and provides a callback to be called to do the logging.
    150  */
    151 RC_EXPORT void RC_CCONV rc_client_enable_logging(rc_client_t* client, int level, rc_client_message_callback_t callback);
    152 enum {
    153   RC_CLIENT_LOG_LEVEL_NONE = 0,
    154   RC_CLIENT_LOG_LEVEL_ERROR = 1,
    155   RC_CLIENT_LOG_LEVEL_WARN = 2,
    156   RC_CLIENT_LOG_LEVEL_INFO = 3,
    157   RC_CLIENT_LOG_LEVEL_VERBOSE = 4,
    158   NUM_RC_CLIENT_LOG_LEVELS = 5
    159 };
    160 
    161 /*****************************************************************************\
    162 | User                                                                        |
    163 \*****************************************************************************/
    164 
    165 /**
    166  * Attempt to login a user.
    167  */
    168 RC_EXPORT rc_client_async_handle_t* RC_CCONV rc_client_begin_login_with_password(rc_client_t* client,
    169     const char* username, const char* password,
    170     rc_client_callback_t callback, void* callback_userdata);
    171 
    172 /**
    173  * Attempt to login a user.
    174  */
    175 RC_EXPORT rc_client_async_handle_t* RC_CCONV rc_client_begin_login_with_token(rc_client_t* client,
    176     const char* username, const char* token,
    177     rc_client_callback_t callback, void* callback_userdata);
    178 
    179 /**
    180  * Logout the user.
    181  */
    182 RC_EXPORT void RC_CCONV rc_client_logout(rc_client_t* client);
    183 
    184 typedef struct rc_client_user_t {
    185   const char* display_name;
    186   const char* username;
    187   const char* token;
    188   uint32_t score;
    189   uint32_t score_softcore;
    190   uint32_t num_unread_messages;
    191 } rc_client_user_t;
    192 
    193 /**
    194  * Gets information about the logged in user. Will return NULL if the user is not logged in.
    195  */
    196 RC_EXPORT const rc_client_user_t* RC_CCONV rc_client_get_user_info(const rc_client_t* client);
    197 
    198 /**
    199  * Gets the URL for the user's profile picture.
    200  * Returns RC_OK on success.
    201  */
    202 RC_EXPORT int RC_CCONV rc_client_user_get_image_url(const rc_client_user_t* user, char buffer[], size_t buffer_size);
    203 
    204 typedef struct rc_client_user_game_summary_t {
    205   uint32_t num_core_achievements;
    206   uint32_t num_unofficial_achievements;
    207   uint32_t num_unlocked_achievements;
    208   uint32_t num_unsupported_achievements;
    209 
    210   uint32_t points_core;
    211   uint32_t points_unlocked;
    212 } rc_client_user_game_summary_t;
    213 
    214 /**
    215  * Gets a breakdown of the number of achievements in the game, and how many the user has unlocked.
    216  * Used for the "You have unlocked X of Y achievements" message shown when the game starts.
    217  */
    218 RC_EXPORT void RC_CCONV rc_client_get_user_game_summary(const rc_client_t* client, rc_client_user_game_summary_t* summary);
    219 
    220 /*****************************************************************************\
    221 | Game                                                                        |
    222 \*****************************************************************************/
    223 
    224 #ifdef RC_CLIENT_SUPPORTS_HASH
    225 /**
    226  * Start loading an unidentified game.
    227  */
    228 RC_EXPORT rc_client_async_handle_t* RC_CCONV rc_client_begin_identify_and_load_game(rc_client_t* client,
    229     uint32_t console_id, const char* file_path,
    230     const uint8_t* data, size_t data_size,
    231     rc_client_callback_t callback, void* callback_userdata);
    232 #endif
    233 
    234 /**
    235  * Start loading a game.
    236  */
    237 RC_EXPORT rc_client_async_handle_t* RC_CCONV rc_client_begin_load_game(rc_client_t* client, const char* hash,
    238     rc_client_callback_t callback, void* callback_userdata);
    239 
    240 /**
    241  * Gets the current progress of the asynchronous load game process.
    242  */
    243 RC_EXPORT int RC_CCONV rc_client_get_load_game_state(const rc_client_t* client);
    244 enum {
    245   RC_CLIENT_LOAD_GAME_STATE_NONE,
    246   RC_CLIENT_LOAD_GAME_STATE_IDENTIFYING_GAME,
    247   RC_CLIENT_LOAD_GAME_STATE_AWAIT_LOGIN,
    248   RC_CLIENT_LOAD_GAME_STATE_FETCHING_GAME_DATA,
    249   RC_CLIENT_LOAD_GAME_STATE_STARTING_SESSION,
    250   RC_CLIENT_LOAD_GAME_STATE_DONE,
    251   RC_CLIENT_LOAD_GAME_STATE_ABORTED
    252 };
    253 
    254 /**
    255  * Determines if a game was successfully identified and loaded.
    256  */
    257 RC_EXPORT int RC_CCONV rc_client_is_game_loaded(const rc_client_t* client);
    258 
    259 /**
    260  * Unloads the current game.
    261  */
    262 RC_EXPORT void RC_CCONV rc_client_unload_game(rc_client_t* client);
    263 
    264 typedef struct rc_client_game_t {
    265   uint32_t id;
    266   uint32_t console_id;
    267   const char* title;
    268   const char* hash;
    269   const char* badge_name;
    270 } rc_client_game_t;
    271 
    272 /**
    273  * Get information about the current game. Returns NULL if no game is loaded.
    274  * NOTE: returns a dummy game record if an unidentified game is loaded.
    275  */
    276 RC_EXPORT const rc_client_game_t* RC_CCONV rc_client_get_game_info(const rc_client_t* client);
    277 
    278 /**
    279  * Gets the URL for the game image.
    280  * Returns RC_OK on success.
    281  */
    282 RC_EXPORT int RC_CCONV rc_client_game_get_image_url(const rc_client_game_t* game, char buffer[], size_t buffer_size);
    283 
    284 #ifdef RC_CLIENT_SUPPORTS_HASH
    285 /**
    286  * Changes the active disc in a multi-disc game.
    287  */
    288 RC_EXPORT rc_client_async_handle_t* RC_CCONV rc_client_begin_change_media(rc_client_t* client, const char* file_path,
    289     const uint8_t* data, size_t data_size, rc_client_callback_t callback, void* callback_userdata);
    290 #endif
    291 
    292 /**
    293  * Changes the active disc in a multi-disc game.
    294  */
    295 RC_EXPORT rc_client_async_handle_t* RC_CCONV rc_client_begin_change_media_from_hash(rc_client_t* client, const char* hash,
    296     rc_client_callback_t callback, void* callback_userdata);
    297 
    298 /*****************************************************************************\
    299 | Subsets                                                                     |
    300 \*****************************************************************************/
    301 
    302 typedef struct rc_client_subset_t {
    303   uint32_t id;
    304   const char* title;
    305   char badge_name[16];
    306 
    307   uint32_t num_achievements;
    308   uint32_t num_leaderboards;
    309 } rc_client_subset_t;
    310 
    311 RC_EXPORT const rc_client_subset_t* RC_CCONV rc_client_get_subset_info(rc_client_t* client, uint32_t subset_id);
    312 
    313 /*****************************************************************************\
    314 | Achievements                                                                |
    315 \*****************************************************************************/
    316 
    317 enum {
    318   RC_CLIENT_ACHIEVEMENT_STATE_INACTIVE = 0, /* unprocessed */
    319   RC_CLIENT_ACHIEVEMENT_STATE_ACTIVE = 1,   /* eligible to trigger */
    320   RC_CLIENT_ACHIEVEMENT_STATE_UNLOCKED = 2, /* earned by user */
    321   RC_CLIENT_ACHIEVEMENT_STATE_DISABLED = 3, /* not supported by this version of the runtime */
    322   NUM_RC_CLIENT_ACHIEVEMENT_STATES = 4
    323 };
    324 
    325 enum {
    326   RC_CLIENT_ACHIEVEMENT_CATEGORY_NONE = 0,
    327   RC_CLIENT_ACHIEVEMENT_CATEGORY_CORE = (1 << 0),
    328   RC_CLIENT_ACHIEVEMENT_CATEGORY_UNOFFICIAL = (1 << 1),
    329   RC_CLIENT_ACHIEVEMENT_CATEGORY_CORE_AND_UNOFFICIAL = RC_CLIENT_ACHIEVEMENT_CATEGORY_CORE | RC_CLIENT_ACHIEVEMENT_CATEGORY_UNOFFICIAL
    330 };
    331 
    332 enum {
    333   RC_CLIENT_ACHIEVEMENT_TYPE_STANDARD = 0,
    334   RC_CLIENT_ACHIEVEMENT_TYPE_MISSABLE = 1,
    335   RC_CLIENT_ACHIEVEMENT_TYPE_PROGRESSION = 2,
    336   RC_CLIENT_ACHIEVEMENT_TYPE_WIN = 3
    337 };
    338 
    339 enum {
    340   RC_CLIENT_ACHIEVEMENT_BUCKET_UNKNOWN = 0,
    341   RC_CLIENT_ACHIEVEMENT_BUCKET_LOCKED = 1,
    342   RC_CLIENT_ACHIEVEMENT_BUCKET_UNLOCKED = 2,
    343   RC_CLIENT_ACHIEVEMENT_BUCKET_UNSUPPORTED = 3,
    344   RC_CLIENT_ACHIEVEMENT_BUCKET_UNOFFICIAL = 4,
    345   RC_CLIENT_ACHIEVEMENT_BUCKET_RECENTLY_UNLOCKED = 5,
    346   RC_CLIENT_ACHIEVEMENT_BUCKET_ACTIVE_CHALLENGE = 6,
    347   RC_CLIENT_ACHIEVEMENT_BUCKET_ALMOST_THERE = 7,
    348   RC_CLIENT_ACHIEVEMENT_BUCKET_UNSYNCED = 8,
    349   NUM_RC_CLIENT_ACHIEVEMENT_BUCKETS = 9
    350 };
    351 
    352 enum {
    353   RC_CLIENT_ACHIEVEMENT_UNLOCKED_NONE = 0,
    354   RC_CLIENT_ACHIEVEMENT_UNLOCKED_SOFTCORE = (1 << 0),
    355   RC_CLIENT_ACHIEVEMENT_UNLOCKED_HARDCORE = (1 << 1),
    356   RC_CLIENT_ACHIEVEMENT_UNLOCKED_BOTH = RC_CLIENT_ACHIEVEMENT_UNLOCKED_SOFTCORE | RC_CLIENT_ACHIEVEMENT_UNLOCKED_HARDCORE
    357 };
    358 
    359 typedef struct rc_client_achievement_t {
    360   const char* title;
    361   const char* description;
    362   char badge_name[8];
    363   char measured_progress[24];
    364   float measured_percent;
    365   uint32_t id;
    366   uint32_t points;
    367   time_t unlock_time;
    368   uint8_t state;
    369   uint8_t category;
    370   uint8_t bucket;
    371   uint8_t unlocked;
    372   /* minimum version: 11.1 */
    373   float rarity;
    374   float rarity_hardcore;
    375   uint8_t type;
    376 } rc_client_achievement_t;
    377 
    378 /**
    379  * Get information about an achievement. Returns NULL if not found.
    380  */
    381 RC_EXPORT const rc_client_achievement_t* RC_CCONV rc_client_get_achievement_info(rc_client_t* client, uint32_t id);
    382 
    383 /**
    384  * Gets the URL for the achievement image.
    385  * Returns RC_OK on success.
    386  */
    387 RC_EXPORT int RC_CCONV rc_client_achievement_get_image_url(const rc_client_achievement_t* achievement, int state, char buffer[], size_t buffer_size);
    388 
    389 typedef struct rc_client_achievement_bucket_t {
    390   rc_client_achievement_t** achievements;
    391   uint32_t num_achievements;
    392 
    393   const char* label;
    394   uint32_t subset_id;
    395   uint8_t bucket_type;
    396 } rc_client_achievement_bucket_t;
    397 
    398 typedef struct rc_client_achievement_list_t {
    399   rc_client_achievement_bucket_t* buckets;
    400   uint32_t num_buckets;
    401 } rc_client_achievement_list_t;
    402 
    403 enum {
    404   RC_CLIENT_ACHIEVEMENT_LIST_GROUPING_LOCK_STATE = 0,
    405   RC_CLIENT_ACHIEVEMENT_LIST_GROUPING_PROGRESS = 1
    406 };
    407 
    408 /**
    409  * Creates a list of achievements matching the specified category and grouping.
    410  * Returns an allocated list that must be free'd by calling rc_client_destroy_achievement_list.
    411  */
    412 RC_EXPORT rc_client_achievement_list_t* RC_CCONV rc_client_create_achievement_list(rc_client_t* client, int category, int grouping);
    413 
    414 /**
    415  * Destroys a list allocated by rc_client_get_achievement_list.
    416  */
    417 RC_EXPORT void RC_CCONV rc_client_destroy_achievement_list(rc_client_achievement_list_t* list);
    418 
    419 /**
    420  * Returns non-zero if there are any achievements that can be queried through rc_client_create_achievement_list().
    421  */
    422 RC_EXPORT int RC_CCONV rc_client_has_achievements(rc_client_t* client);
    423 
    424 /*****************************************************************************\
    425 | Leaderboards                                                                |
    426 \*****************************************************************************/
    427 
    428 enum {
    429   RC_CLIENT_LEADERBOARD_STATE_INACTIVE = 0,
    430   RC_CLIENT_LEADERBOARD_STATE_ACTIVE = 1,
    431   RC_CLIENT_LEADERBOARD_STATE_TRACKING = 2,
    432   RC_CLIENT_LEADERBOARD_STATE_DISABLED = 3,
    433   NUM_RC_CLIENT_LEADERBOARD_STATES = 4
    434 };
    435 
    436 enum {
    437   RC_CLIENT_LEADERBOARD_FORMAT_TIME = 0,
    438   RC_CLIENT_LEADERBOARD_FORMAT_SCORE = 1,
    439   RC_CLIENT_LEADERBOARD_FORMAT_VALUE = 2,
    440   NUM_RC_CLIENT_LEADERBOARD_FORMATS = 3
    441 };
    442 
    443 #define RC_CLIENT_LEADERBOARD_DISPLAY_SIZE 24
    444 
    445 typedef struct rc_client_leaderboard_t {
    446   const char* title;
    447   const char* description;
    448   const char* tracker_value;
    449   uint32_t id;
    450   uint8_t state;
    451   uint8_t format;
    452   uint8_t lower_is_better;
    453 } rc_client_leaderboard_t;
    454 
    455 /**
    456  * Get information about a leaderboard. Returns NULL if not found.
    457  */
    458 RC_EXPORT const rc_client_leaderboard_t* RC_CCONV rc_client_get_leaderboard_info(const rc_client_t* client, uint32_t id);
    459 
    460 typedef struct rc_client_leaderboard_tracker_t {
    461   char display[RC_CLIENT_LEADERBOARD_DISPLAY_SIZE];
    462   uint32_t id;
    463 } rc_client_leaderboard_tracker_t;
    464 
    465 typedef struct rc_client_leaderboard_bucket_t {
    466   rc_client_leaderboard_t** leaderboards;
    467   uint32_t num_leaderboards;
    468 
    469   const char* label;
    470   uint32_t subset_id;
    471   uint8_t bucket_type;
    472 } rc_client_leaderboard_bucket_t;
    473 
    474 typedef struct rc_client_leaderboard_list_t {
    475   rc_client_leaderboard_bucket_t* buckets;
    476   uint32_t num_buckets;
    477 } rc_client_leaderboard_list_t;
    478 
    479 enum {
    480   RC_CLIENT_LEADERBOARD_BUCKET_UNKNOWN = 0,
    481   RC_CLIENT_LEADERBOARD_BUCKET_INACTIVE = 1,
    482   RC_CLIENT_LEADERBOARD_BUCKET_ACTIVE = 2,
    483   RC_CLIENT_LEADERBOARD_BUCKET_UNSUPPORTED = 3,
    484   RC_CLIENT_LEADERBOARD_BUCKET_ALL = 4,
    485   NUM_RC_CLIENT_LEADERBOARD_BUCKETS = 5
    486 };
    487 
    488 enum {
    489   RC_CLIENT_LEADERBOARD_LIST_GROUPING_NONE = 0,
    490   RC_CLIENT_LEADERBOARD_LIST_GROUPING_TRACKING = 1
    491 };
    492 
    493 /**
    494  * Creates a list of leaderboards matching the specified grouping.
    495  * Returns an allocated list that must be free'd by calling rc_client_destroy_leaderboard_list.
    496  */
    497 RC_EXPORT rc_client_leaderboard_list_t* RC_CCONV rc_client_create_leaderboard_list(rc_client_t* client, int grouping);
    498 
    499 /**
    500  * Destroys a list allocated by rc_client_get_leaderboard_list.
    501  */
    502 RC_EXPORT void RC_CCONV rc_client_destroy_leaderboard_list(rc_client_leaderboard_list_t* list);
    503 
    504 /**
    505  * Returns non-zero if the current game has any leaderboards.
    506  */
    507 RC_EXPORT int RC_CCONV rc_client_has_leaderboards(rc_client_t* client);
    508 
    509 typedef struct rc_client_leaderboard_entry_t {
    510   const char* user;
    511   char display[RC_CLIENT_LEADERBOARD_DISPLAY_SIZE];
    512   time_t submitted;
    513   uint32_t rank;
    514   uint32_t index;
    515 } rc_client_leaderboard_entry_t;
    516 
    517 typedef struct rc_client_leaderboard_entry_list_t {
    518   rc_client_leaderboard_entry_t* entries;
    519   uint32_t num_entries;
    520   uint32_t total_entries;
    521   int32_t user_index;
    522 } rc_client_leaderboard_entry_list_t;
    523 
    524 typedef void (RC_CCONV *rc_client_fetch_leaderboard_entries_callback_t)(int result, const char* error_message,
    525     rc_client_leaderboard_entry_list_t* list, rc_client_t* client, void* callback_userdata);
    526 
    527 /**
    528  * Fetches a list of leaderboard entries from the server.
    529  * Callback receives an allocated list that must be free'd by calling rc_client_destroy_leaderboard_entry_list.
    530  */
    531 RC_EXPORT rc_client_async_handle_t* RC_CCONV rc_client_begin_fetch_leaderboard_entries(rc_client_t* client, uint32_t leaderboard_id,
    532     uint32_t first_entry, uint32_t count, rc_client_fetch_leaderboard_entries_callback_t callback, void* callback_userdata);
    533 
    534 /**
    535  * Fetches a list of leaderboard entries from the server containing the logged-in user.
    536  * Callback receives an allocated list that must be free'd by calling rc_client_destroy_leaderboard_entry_list.
    537  */
    538 RC_EXPORT rc_client_async_handle_t* RC_CCONV rc_client_begin_fetch_leaderboard_entries_around_user(rc_client_t* client, uint32_t leaderboard_id,
    539     uint32_t count, rc_client_fetch_leaderboard_entries_callback_t callback, void* callback_userdata);
    540 
    541 /**
    542  * Gets the URL for the profile picture of the user associated to a leaderboard entry.
    543  * Returns RC_OK on success.
    544  */
    545 RC_EXPORT int RC_CCONV rc_client_leaderboard_entry_get_user_image_url(const rc_client_leaderboard_entry_t* entry, char buffer[], size_t buffer_size);
    546 
    547 /**
    548  * Destroys a list allocated by rc_client_begin_fetch_leaderboard_entries or rc_client_begin_fetch_leaderboard_entries_around_user.
    549  */
    550 RC_EXPORT void RC_CCONV rc_client_destroy_leaderboard_entry_list(rc_client_leaderboard_entry_list_t* list);
    551 
    552 /**
    553  * Used for scoreboard events. Contains the response from the server when a leaderboard entry is submitted.
    554  * NOTE: This structure is only valid within the event callback. If you want to make use of the data outside
    555  * of the callback, you should create copies of both the top entries and usernames within.
    556  */
    557 typedef struct rc_client_leaderboard_scoreboard_entry_t {
    558   /* The user associated to the entry */
    559   const char* username;
    560   /* The rank of the entry */
    561   uint32_t rank;
    562   /* The value of the entry */
    563   char score[RC_CLIENT_LEADERBOARD_DISPLAY_SIZE];
    564 } rc_client_leaderboard_scoreboard_entry_t;
    565 
    566 typedef struct rc_client_leaderboard_scoreboard_t {
    567   /* The ID of the leaderboard which was submitted */
    568   uint32_t leaderboard_id;
    569   /* The value that was submitted */
    570   char submitted_score[RC_CLIENT_LEADERBOARD_DISPLAY_SIZE];
    571   /* The player's best submitted value */
    572   char best_score[RC_CLIENT_LEADERBOARD_DISPLAY_SIZE];
    573   /* The player's new rank within the leaderboard */
    574   uint32_t new_rank;
    575   /* The total number of entries in the leaderboard */
    576   uint32_t num_entries;
    577 
    578   /* An array of the top entries for the leaderboard */
    579   rc_client_leaderboard_scoreboard_entry_t* top_entries;
    580   /* The number of items in the top_entries array */
    581   uint32_t num_top_entries;
    582 } rc_client_leaderboard_scoreboard_t;
    583 
    584 /*****************************************************************************\
    585 | Rich Presence                                                               |
    586 \*****************************************************************************/
    587 
    588 /**
    589  * Returns non-zero if the current game supports rich presence.
    590  */
    591 RC_EXPORT int RC_CCONV rc_client_has_rich_presence(rc_client_t* client);
    592 
    593 /**
    594  * Gets the current rich presence message.
    595  * Returns the number of characters written to buffer.
    596  */
    597 RC_EXPORT size_t RC_CCONV rc_client_get_rich_presence_message(rc_client_t* client, char buffer[], size_t buffer_size);
    598 
    599 /**
    600  * Returns a list of all possible rich presence strings.
    601  * The list is terminated by NULL.
    602  */
    603 RC_EXPORT int RC_CCONV rc_client_get_rich_presence_strings(rc_client_t* client, const char** buffer, size_t buffer_size, size_t* count);
    604 
    605 /*****************************************************************************\
    606 | Processing                                                                  |
    607 \*****************************************************************************/
    608 
    609 enum {
    610   RC_CLIENT_EVENT_TYPE_NONE = 0,
    611   RC_CLIENT_EVENT_ACHIEVEMENT_TRIGGERED = 1, /* [achievement] was earned by the player */
    612   RC_CLIENT_EVENT_LEADERBOARD_STARTED = 2, /* [leaderboard] attempt has started */
    613   RC_CLIENT_EVENT_LEADERBOARD_FAILED = 3, /* [leaderboard] attempt failed */
    614   RC_CLIENT_EVENT_LEADERBOARD_SUBMITTED = 4, /* [leaderboard] attempt submitted */
    615   RC_CLIENT_EVENT_ACHIEVEMENT_CHALLENGE_INDICATOR_SHOW = 5, /* [achievement] challenge indicator should be shown */
    616   RC_CLIENT_EVENT_ACHIEVEMENT_CHALLENGE_INDICATOR_HIDE = 6, /* [achievement] challenge indicator should be hidden */
    617   RC_CLIENT_EVENT_ACHIEVEMENT_PROGRESS_INDICATOR_SHOW = 7, /* progress indicator should be shown for [achievement] */
    618   RC_CLIENT_EVENT_ACHIEVEMENT_PROGRESS_INDICATOR_HIDE = 8, /* progress indicator should be hidden */
    619   RC_CLIENT_EVENT_ACHIEVEMENT_PROGRESS_INDICATOR_UPDATE = 9, /* progress indicator should be updated to reflect new badge/progress for [achievement] */
    620   RC_CLIENT_EVENT_LEADERBOARD_TRACKER_SHOW = 10, /* [leaderboard_tracker] should be shown */
    621   RC_CLIENT_EVENT_LEADERBOARD_TRACKER_HIDE = 11, /* [leaderboard_tracker] should be hidden */
    622   RC_CLIENT_EVENT_LEADERBOARD_TRACKER_UPDATE = 12, /* [leaderboard_tracker] updated */
    623   RC_CLIENT_EVENT_LEADERBOARD_SCOREBOARD = 13, /* [leaderboard_scoreboard] possibly-new ranking received for [leaderboard] */
    624   RC_CLIENT_EVENT_RESET = 14, /* emulated system should be reset (as the result of enabling hardcore) */
    625   RC_CLIENT_EVENT_GAME_COMPLETED = 15, /* all achievements for the game have been earned */
    626   RC_CLIENT_EVENT_SERVER_ERROR = 16, /* an API response returned a [server_error] and will not be retried */
    627   RC_CLIENT_EVENT_DISCONNECTED = 17, /* an unlock request could not be completed and is pending */
    628   RC_CLIENT_EVENT_RECONNECTED = 18 /* all pending unlocks have been completed */
    629 };
    630 
    631 typedef struct rc_client_server_error_t {
    632   const char* error_message;
    633   const char* api;
    634   int result;
    635   uint32_t related_id;
    636 } rc_client_server_error_t;
    637 
    638 typedef struct rc_client_event_t {
    639   uint32_t type;
    640 
    641   rc_client_achievement_t* achievement;
    642   rc_client_leaderboard_t* leaderboard;
    643   rc_client_leaderboard_tracker_t* leaderboard_tracker;
    644   rc_client_leaderboard_scoreboard_t* leaderboard_scoreboard;
    645   rc_client_server_error_t* server_error;
    646 
    647 } rc_client_event_t;
    648 
    649 /**
    650  * Callback used to notify the client when certain events occur.
    651  */
    652 typedef void (RC_CCONV *rc_client_event_handler_t)(const rc_client_event_t* event, rc_client_t* client);
    653 
    654 /**
    655  * Provides a callback for event handling.
    656  */
    657 RC_EXPORT void RC_CCONV rc_client_set_event_handler(rc_client_t* client, rc_client_event_handler_t handler);
    658 
    659 /**
    660  * Provides a callback for reading memory.
    661  */
    662 RC_EXPORT void RC_CCONV rc_client_set_read_memory_function(rc_client_t* client, rc_client_read_memory_func_t handler);
    663 
    664 /**
    665  * Determines if there are any active achievements/leaderboards/rich presence that need processing.
    666  */
    667 RC_EXPORT int RC_CCONV rc_client_is_processing_required(rc_client_t* client);
    668 
    669 /**
    670  * Processes achievements for the current frame.
    671  */
    672 RC_EXPORT void RC_CCONV rc_client_do_frame(rc_client_t* client);
    673 
    674 /**
    675  * Processes the periodic queue.
    676  * Called internally by rc_client_do_frame.
    677  * Should be explicitly called if rc_client_do_frame is not being called because emulation is paused.
    678  */
    679 RC_EXPORT void RC_CCONV rc_client_idle(rc_client_t* client);
    680 
    681 /**
    682  * Determines if a sufficient amount of frames have been processed since the last call to rc_client_can_pause.
    683  * Should not be called unless the client is trying to pause.
    684  * If false is returned, and frames_remaining is not NULL, frames_remaining will be set to the number of frames
    685  * still required before pause is allowed, which can be converted to a time in seconds for displaying to the user.
    686  */
    687 RC_EXPORT int RC_CCONV rc_client_can_pause(rc_client_t* client, uint32_t* frames_remaining);
    688 
    689 /**
    690  * Informs the runtime that the emulator has been reset. Will reset all achievements and leaderboards
    691  * to their initial state (includes hiding indicators/trackers).
    692  */
    693 RC_EXPORT void RC_CCONV rc_client_reset(rc_client_t* client);
    694 
    695 /**
    696  * Gets the number of bytes needed to serialized the runtime state.
    697  */
    698 RC_EXPORT size_t RC_CCONV rc_client_progress_size(rc_client_t* client);
    699 
    700 /**
    701  * Serializes the runtime state into a buffer.
    702  * Returns RC_OK on success, or an error indicator.
    703  * [deprecated] use rc_client_serialize_progress_sized instead
    704  */
    705 RC_EXPORT int RC_CCONV rc_client_serialize_progress(rc_client_t* client, uint8_t* buffer);
    706 
    707 /**
    708  * Serializes the runtime state into a buffer.
    709  * Returns RC_OK on success, or an error indicator.
    710  */
    711 RC_EXPORT int RC_CCONV rc_client_serialize_progress_sized(rc_client_t* client, uint8_t* buffer, size_t buffer_size);
    712 
    713 /**
    714  * Deserializes the runtime state from a buffer.
    715  * Returns RC_OK on success, or an error indicator.
    716  * [deprecated] use rc_client_deserialize_progress_sized instead
    717  */
    718 RC_EXPORT int RC_CCONV rc_client_deserialize_progress(rc_client_t* client, const uint8_t* serialized);
    719 
    720 /**
    721  * Serializes the runtime state into a buffer.
    722  * Returns RC_OK on success, or an error indicator.
    723  */
    724 RC_EXPORT int RC_CCONV rc_client_deserialize_progress_sized(rc_client_t* client, const uint8_t* serialized, size_t serialized_size);
    725 
    726 RC_END_C_DECLS
    727 
    728 #endif /* RC_RUNTIME_H */