Path: blob/master/dep/rcheevos/src/rc_client_internal.h
4804 views
#ifndef RC_CLIENT_INTERNAL_H1#define RC_CLIENT_INTERNAL_H23#include "rc_client.h"45#ifdef RC_CLIENT_SUPPORTS_RAINTEGRATION6#include "rc_client_raintegration_internal.h"7#endif8#ifdef RC_CLIENT_SUPPORTS_EXTERNAL9#include "rc_client_external.h"10#endif11#ifdef RC_CLIENT_SUPPORTS_HASH12#include "rhash/rc_hash_internal.h"13#endif1415#include "rc_compat.h"16#include "rc_runtime.h"17#include "rc_runtime_types.h"1819RC_BEGIN_C_DECLS2021/*****************************************************************************\22| Callbacks |23\*****************************************************************************/2425struct rc_api_fetch_game_sets_response_t;26typedef void (RC_CCONV *rc_client_post_process_game_sets_response_t)(const rc_api_server_response_t* server_response,27struct rc_api_fetch_game_sets_response_t* game_sets_response, rc_client_t* client, void* userdata);28typedef int (RC_CCONV *rc_client_can_submit_achievement_unlock_t)(uint32_t achievement_id, rc_client_t* client);29typedef int (RC_CCONV *rc_client_can_submit_leaderboard_entry_t)(uint32_t leaderboard_id, rc_client_t* client);30typedef int (RC_CCONV *rc_client_rich_presence_override_t)(rc_client_t* client, char buffer[], size_t buffersize);31typedef uint32_t (RC_CCONV* rc_client_identify_hash_func_t)(uint32_t console_id, const char* hash,32rc_client_t* client, void* callback_userdata);3334typedef struct rc_client_callbacks_t {35rc_client_read_memory_func_t read_memory;36rc_client_event_handler_t event_handler;37rc_client_server_call_t server_call;38rc_client_message_callback_t log_call;39rc_get_time_millisecs_func_t get_time_millisecs;40rc_client_identify_hash_func_t identify_unknown_hash;41rc_client_post_process_game_sets_response_t post_process_game_sets_response;42rc_client_can_submit_achievement_unlock_t can_submit_achievement_unlock;43rc_client_can_submit_leaderboard_entry_t can_submit_leaderboard_entry;44rc_client_rich_presence_override_t rich_presence_override;4546#ifdef RC_CLIENT_SUPPORTS_HASH47rc_hash_callbacks_t hash;48#endif4950void* client_data;51} rc_client_callbacks_t;5253struct rc_client_scheduled_callback_data_t;54typedef void (RC_CCONV *rc_client_scheduled_callback_t)(struct rc_client_scheduled_callback_data_t* callback_data, rc_client_t* client, rc_clock_t now);5556typedef struct rc_client_scheduled_callback_data_t57{58rc_clock_t when;59uint32_t related_id;60rc_client_scheduled_callback_t callback;61void* data;62struct rc_client_scheduled_callback_data_t* next;63} rc_client_scheduled_callback_data_t;6465void rc_client_schedule_callback(rc_client_t* client, rc_client_scheduled_callback_data_t* scheduled_callback);6667struct rc_client_async_handle_t {68uint8_t aborted;69};7071int rc_client_async_handle_aborted(rc_client_t* client, rc_client_async_handle_t* async_handle);7273/*****************************************************************************\74| Achievements |75\*****************************************************************************/7677enum {78RC_CLIENT_ACHIEVEMENT_PENDING_EVENT_NONE = 0,79RC_CLIENT_ACHIEVEMENT_PENDING_EVENT_TRIGGERED = (1 << 1),80RC_CLIENT_ACHIEVEMENT_PENDING_EVENT_CHALLENGE_INDICATOR_SHOW = (1 << 2),81RC_CLIENT_ACHIEVEMENT_PENDING_EVENT_CHALLENGE_INDICATOR_HIDE = (1 << 3),82RC_CLIENT_ACHIEVEMENT_PENDING_EVENT_UPDATE = (1 << 4) /* not a real event, just triggers update */83};8485typedef struct rc_client_achievement_info_t {86rc_client_achievement_t public_;8788rc_trigger_t* trigger;89uint8_t md5[16];9091time_t unlock_time_hardcore;92time_t unlock_time_softcore;9394uint8_t pending_events;9596const char* author;97time_t created_time;98time_t updated_time;99} rc_client_achievement_info_t;100101struct rc_client_achievement_list_info_t;102typedef void (RC_CCONV *rc_client_destroy_achievement_list_func_t)(struct rc_client_achievement_list_info_t* list);103104typedef struct rc_client_achievement_list_info_t {105rc_client_achievement_list_t public_;106rc_client_destroy_achievement_list_func_t destroy_func;107} rc_client_achievement_list_info_t;108109enum {110RC_CLIENT_PROGRESS_TRACKER_ACTION_NONE,111RC_CLIENT_PROGRESS_TRACKER_ACTION_SHOW,112RC_CLIENT_PROGRESS_TRACKER_ACTION_UPDATE,113RC_CLIENT_PROGRESS_TRACKER_ACTION_HIDE114};115116typedef struct rc_client_progress_tracker_t {117rc_client_achievement_info_t* achievement;118float progress;119120rc_client_scheduled_callback_data_t* hide_callback;121uint8_t action;122} rc_client_progress_tracker_t;123124/*****************************************************************************\125| Leaderboard Trackers |126\*****************************************************************************/127128enum {129RC_CLIENT_LEADERBOARD_TRACKER_PENDING_EVENT_NONE = 0,130RC_CLIENT_LEADERBOARD_TRACKER_PENDING_EVENT_UPDATE = (1 << 1),131RC_CLIENT_LEADERBOARD_TRACKER_PENDING_EVENT_SHOW = (1 << 2),132RC_CLIENT_LEADERBOARD_TRACKER_PENDING_EVENT_HIDE = (1 << 3)133};134135typedef struct rc_client_leaderboard_tracker_info_t {136rc_client_leaderboard_tracker_t public_;137struct rc_client_leaderboard_tracker_info_t* next;138int32_t raw_value;139140uint32_t value_djb2;141142uint8_t format;143uint8_t pending_events;144uint8_t reference_count;145uint8_t value_from_hits;146} rc_client_leaderboard_tracker_info_t;147148/*****************************************************************************\149| Leaderboards |150\*****************************************************************************/151152enum {153RC_CLIENT_LEADERBOARD_PENDING_EVENT_NONE = 0,154RC_CLIENT_LEADERBOARD_PENDING_EVENT_STARTED = (1 << 1),155RC_CLIENT_LEADERBOARD_PENDING_EVENT_FAILED = (1 << 2),156RC_CLIENT_LEADERBOARD_PENDING_EVENT_SUBMITTED = (1 << 3)157};158159typedef struct rc_client_leaderboard_info_t {160rc_client_leaderboard_t public_;161162rc_lboard_t* lboard;163uint8_t md5[16];164165rc_client_leaderboard_tracker_info_t* tracker;166167uint32_t value_djb2;168int32_t value;169170uint8_t format;171uint8_t pending_events;172uint8_t bucket;173uint8_t hidden;174} rc_client_leaderboard_info_t;175176struct rc_client_leaderboard_list_info_t;177typedef void (RC_CCONV *rc_client_destroy_leaderboard_list_func_t)(struct rc_client_leaderboard_list_info_t* list);178179typedef struct rc_client_leaderboard_list_info_t {180rc_client_leaderboard_list_t public_;181rc_client_destroy_leaderboard_list_func_t destroy_func;182} rc_client_leaderboard_list_info_t;183184struct rc_client_leaderboard_entry_list_info_t;185typedef void (RC_CCONV *rc_client_destroy_leaderboard_entry_list_func_t)(struct rc_client_leaderboard_entry_list_info_t* list);186187typedef struct rc_client_leaderboard_entry_list_info_t {188rc_client_leaderboard_entry_list_t public_;189rc_client_destroy_leaderboard_entry_list_func_t destroy_func;190} rc_client_leaderboard_entry_list_info_t;191192uint8_t rc_client_map_leaderboard_format(int format);193194/*****************************************************************************\195| Subsets |196\*****************************************************************************/197198enum {199RC_CLIENT_SUBSET_PENDING_EVENT_NONE = 0,200RC_CLIENT_SUBSET_PENDING_EVENT_ACHIEVEMENT = (1 << 1),201RC_CLIENT_SUBSET_PENDING_EVENT_LEADERBOARD = (1 << 2)202};203204typedef struct rc_client_subset_info_t {205rc_client_subset_t public_;206207rc_client_achievement_info_t* achievements;208rc_client_leaderboard_info_t* leaderboards;209210struct rc_client_subset_info_t* next;211212const char* all_label;213const char* inactive_label;214const char* locked_label;215const char* unlocked_label;216const char* unofficial_label;217const char* unsupported_label;218219uint8_t active;220uint8_t mastery;221uint8_t pending_events;222} rc_client_subset_info_t;223224/*****************************************************************************\225| Game |226\*****************************************************************************/227228typedef struct rc_client_game_hash_t {229char hash[33];230uint8_t is_unknown;231uint32_t game_id;232struct rc_client_game_hash_t* next;233} rc_client_game_hash_t;234235rc_client_game_hash_t* rc_client_find_game_hash(rc_client_t* client, const char* hash);236237typedef struct rc_client_media_hash_t {238rc_client_game_hash_t* game_hash;239struct rc_client_media_hash_t* next;240uint32_t path_djb2;241} rc_client_media_hash_t;242243enum {244RC_CLIENT_GAME_PENDING_EVENT_NONE = 0,245RC_CLIENT_GAME_PENDING_EVENT_LEADERBOARD_TRACKER = (1 << 1),246RC_CLIENT_GAME_PENDING_EVENT_UPDATE_ACTIVE_ACHIEVEMENTS = (1 << 2),247RC_CLIENT_GAME_PENDING_EVENT_PROGRESS_TRACKER = (1 << 3)248};249250typedef struct rc_client_game_info_t {251rc_client_game_t public_;252rc_client_leaderboard_tracker_info_t* leaderboard_trackers;253rc_client_progress_tracker_t progress_tracker;254255rc_client_subset_info_t* subsets;256257rc_client_media_hash_t* media_hash;258259rc_runtime_t runtime;260261uint32_t max_valid_address;262263uint8_t waiting_for_reset;264uint8_t pending_events;265266rc_buffer_t buffer;267} rc_client_game_info_t;268269void rc_client_update_active_achievements(rc_client_game_info_t* game);270void rc_client_update_active_leaderboards(rc_client_game_info_t* game);271272/*****************************************************************************\273| Client |274\*****************************************************************************/275276enum {277RC_CLIENT_USER_STATE_NONE,278RC_CLIENT_USER_STATE_LOGIN_REQUESTED,279RC_CLIENT_USER_STATE_LOGGED_IN280};281282enum {283RC_CLIENT_MASTERY_STATE_NONE,284RC_CLIENT_MASTERY_STATE_PENDING,285RC_CLIENT_MASTERY_STATE_SHOWN286};287288enum {289RC_CLIENT_SPECTATOR_MODE_OFF,290RC_CLIENT_SPECTATOR_MODE_ON,291RC_CLIENT_SPECTATOR_MODE_LOCKED292};293294enum {295RC_CLIENT_DISCONNECT_HIDDEN = 0,296RC_CLIENT_DISCONNECT_VISIBLE = (1 << 0),297RC_CLIENT_DISCONNECT_SHOW_PENDING = (1 << 1),298RC_CLIENT_DISCONNECT_HIDE_PENDING = (1 << 2)299};300301struct rc_client_load_state_t;302303typedef struct rc_client_state_t {304rc_mutex_t mutex;305rc_buffer_t buffer;306307rc_client_scheduled_callback_data_t* scheduled_callbacks;308rc_api_host_t host;309310#ifdef RC_CLIENT_SUPPORTS_EXTERNAL311rc_client_external_t* external_client;312struct rc_client_external_conversions_t* external_client_conversions;313#endif314#ifdef RC_CLIENT_SUPPORTS_RAINTEGRATION315rc_client_raintegration_t* raintegration;316#endif317318uint16_t unpaused_frame_decay;319uint16_t required_unpaused_frames;320321uint8_t hardcore;322uint8_t encore_mode;323uint8_t spectator_mode;324uint8_t unofficial_enabled;325uint8_t log_level;326uint8_t user;327uint8_t disconnect;328uint8_t allow_leaderboards_in_softcore;329uint8_t allow_background_memory_reads;330331struct rc_client_load_state_t* load;332struct rc_client_async_handle_t* async_handles[4];333rc_memref_t* processing_memref;334335rc_peek_t legacy_peek;336} rc_client_state_t;337338struct rc_client_t {339rc_client_game_info_t* game;340rc_client_game_hash_t* hashes;341342rc_client_user_t user;343344rc_client_callbacks_t callbacks;345346rc_client_state_t state;347};348349/*****************************************************************************\350| Helpers |351\*****************************************************************************/352353#ifdef RC_NO_VARIADIC_MACROS354void RC_CLIENT_LOG_ERR_FORMATTED(const rc_client_t* client, const char* format, ...);355void RC_CLIENT_LOG_WARN_FORMATTED(const rc_client_t* client, const char* format, ...);356void RC_CLIENT_LOG_INFO_FORMATTED(const rc_client_t* client, const char* format, ...);357void RC_CLIENT_LOG_VERBOSE_FORMATTED(const rc_client_t* client, const char* format, ...);358#else359void rc_client_log_message_formatted(const rc_client_t* client, const char* format, ...);360#define RC_CLIENT_LOG_ERR_FORMATTED(client, format, ...) { if (client->state.log_level >= RC_CLIENT_LOG_LEVEL_ERROR) rc_client_log_message_formatted(client, format, __VA_ARGS__); }361#define RC_CLIENT_LOG_WARN_FORMATTED(client, format, ...) { if (client->state.log_level >= RC_CLIENT_LOG_LEVEL_WARN) rc_client_log_message_formatted(client, format, __VA_ARGS__); }362#define RC_CLIENT_LOG_INFO_FORMATTED(client, format, ...) { if (client->state.log_level >= RC_CLIENT_LOG_LEVEL_INFO) rc_client_log_message_formatted(client, format, __VA_ARGS__); }363#define RC_CLIENT_LOG_VERBOSE_FORMATTED(client, format, ...) { if (client->state.log_level >= RC_CLIENT_LOG_LEVEL_VERBOSE) rc_client_log_message_formatted(client, format, __VA_ARGS__); }364#endif365366void rc_client_log_message(const rc_client_t* client, const char* message);367#define RC_CLIENT_LOG_ERR(client, message) { if (client->state.log_level >= RC_CLIENT_LOG_LEVEL_ERROR) rc_client_log_message(client, message); }368#define RC_CLIENT_LOG_WARN(client, message) { if (client->state.log_level >= RC_CLIENT_LOG_LEVEL_WARN) rc_client_log_message(client, message); }369#define RC_CLIENT_LOG_INFO(client, message) { if (client->state.log_level >= RC_CLIENT_LOG_LEVEL_INFO) rc_client_log_message(client, message); }370#define RC_CLIENT_LOG_VERBOSE(client, message) { if (client->state.log_level >= RC_CLIENT_LOG_LEVEL_VERBOSE) rc_client_log_message(client, message); }371372/* internals pulled from runtime.c */373void rc_runtime_checksum(const char* memaddr, uint8_t* md5);374int rc_trigger_contains_memref(const rc_trigger_t* trigger, const rc_memref_t* memref);375int rc_value_contains_memref(const rc_value_t* value, const rc_memref_t* memref);376/* end runtime.c internals */377378/* helper functions for unit tests */379#ifdef RC_CLIENT_SUPPORTS_HASH380struct rc_hash_iterator;381struct rc_hash_iterator* rc_client_get_load_state_hash_iterator(rc_client_t* client);382#endif383/* end helper functions for unit tests */384385enum {386RC_CLIENT_LEGACY_PEEK_AUTO,387RC_CLIENT_LEGACY_PEEK_CONSTRUCTED,388RC_CLIENT_LEGACY_PEEK_LITTLE_ENDIAN_READS389};390391void rc_client_set_legacy_peek(rc_client_t* client, int method);392393void rc_client_allocate_leaderboard_tracker(rc_client_game_info_t* game, rc_client_leaderboard_info_t* leaderboard);394void rc_client_release_leaderboard_tracker(rc_client_game_info_t* game, rc_client_leaderboard_info_t* leaderboard);395396RC_END_C_DECLS397398#endif /* RC_CLIENT_INTERNAL_H */399400401