diff --git a/dep/rcheevos/include/rc_api_editor.h b/dep/rcheevos/include/rc_api_editor.h index c3c45fee7..2a6df339e 100644 --- a/dep/rcheevos/include/rc_api_editor.h +++ b/dep/rcheevos/include/rc_api_editor.h @@ -5,9 +5,7 @@ #include -#ifdef __cplusplus -extern "C" { -#endif +RC_BEGIN_C_DECLS /* --- Fetch Code Notes --- */ @@ -44,10 +42,10 @@ typedef struct rc_api_fetch_code_notes_response_t { } rc_api_fetch_code_notes_response_t; -int rc_api_init_fetch_code_notes_request(rc_api_request_t* request, const rc_api_fetch_code_notes_request_t* api_params); -int rc_api_process_fetch_code_notes_response(rc_api_fetch_code_notes_response_t* response, const char* server_response); -int rc_api_process_fetch_code_notes_server_response(rc_api_fetch_code_notes_response_t* response, const rc_api_server_response_t* server_response); -void rc_api_destroy_fetch_code_notes_response(rc_api_fetch_code_notes_response_t* response); +RC_EXPORT int RC_CCONV rc_api_init_fetch_code_notes_request(rc_api_request_t* request, const rc_api_fetch_code_notes_request_t* api_params); +RC_EXPORT int RC_CCONV rc_api_process_fetch_code_notes_response(rc_api_fetch_code_notes_response_t* response, const char* server_response); +RC_EXPORT int RC_CCONV rc_api_process_fetch_code_notes_server_response(rc_api_fetch_code_notes_response_t* response, const rc_api_server_response_t* server_response); +RC_EXPORT void RC_CCONV rc_api_destroy_fetch_code_notes_response(rc_api_fetch_code_notes_response_t* response); /* --- Update Code Note --- */ @@ -77,10 +75,10 @@ typedef struct rc_api_update_code_note_response_t { } rc_api_update_code_note_response_t; -int rc_api_init_update_code_note_request(rc_api_request_t* request, const rc_api_update_code_note_request_t* api_params); -int rc_api_process_update_code_note_response(rc_api_update_code_note_response_t* response, const char* server_response); -int rc_api_process_update_code_note_server_response(rc_api_update_code_note_response_t* response, const rc_api_server_response_t* server_response); -void rc_api_destroy_update_code_note_response(rc_api_update_code_note_response_t* response); +RC_EXPORT int RC_CCONV rc_api_init_update_code_note_request(rc_api_request_t* request, const rc_api_update_code_note_request_t* api_params); +RC_EXPORT int RC_CCONV rc_api_process_update_code_note_response(rc_api_update_code_note_response_t* response, const char* server_response); +RC_EXPORT int RC_CCONV rc_api_process_update_code_note_server_response(rc_api_update_code_note_response_t* response, const rc_api_server_response_t* server_response); +RC_EXPORT void RC_CCONV rc_api_destroy_update_code_note_response(rc_api_update_code_note_response_t* response); /* --- Update Achievement --- */ @@ -108,6 +106,8 @@ typedef struct rc_api_update_achievement_request_t { uint32_t points; /* The category of the achievement */ uint32_t category; + /* The type of the achievement */ + uint32_t type; } rc_api_update_achievement_request_t; @@ -123,10 +123,10 @@ typedef struct rc_api_update_achievement_response_t { } rc_api_update_achievement_response_t; -int rc_api_init_update_achievement_request(rc_api_request_t* request, const rc_api_update_achievement_request_t* api_params); -int rc_api_process_update_achievement_response(rc_api_update_achievement_response_t* response, const char* server_response); -int rc_api_process_update_achievement_server_response(rc_api_update_achievement_response_t* response, const rc_api_server_response_t* server_response); -void rc_api_destroy_update_achievement_response(rc_api_update_achievement_response_t* response); +RC_EXPORT int RC_CCONV rc_api_init_update_achievement_request(rc_api_request_t* request, const rc_api_update_achievement_request_t* api_params); +RC_EXPORT int RC_CCONV rc_api_process_update_achievement_response(rc_api_update_achievement_response_t* response, const char* server_response); +RC_EXPORT int RC_CCONV rc_api_process_update_achievement_server_response(rc_api_update_achievement_response_t* response, const rc_api_server_response_t* server_response); +RC_EXPORT void RC_CCONV rc_api_destroy_update_achievement_response(rc_api_update_achievement_response_t* response); /* --- Update Leaderboard --- */ @@ -173,10 +173,10 @@ typedef struct rc_api_update_leaderboard_response_t { } rc_api_update_leaderboard_response_t; -int rc_api_init_update_leaderboard_request(rc_api_request_t* request, const rc_api_update_leaderboard_request_t* api_params); -int rc_api_process_update_leaderboard_response(rc_api_update_leaderboard_response_t* response, const char* server_response); -int rc_api_process_update_leaderboard_server_response(rc_api_update_leaderboard_response_t* response, const rc_api_server_response_t* server_response); -void rc_api_destroy_update_leaderboard_response(rc_api_update_leaderboard_response_t* response); +RC_EXPORT int RC_CCONV rc_api_init_update_leaderboard_request(rc_api_request_t* request, const rc_api_update_leaderboard_request_t* api_params); +RC_EXPORT int RC_CCONV rc_api_process_update_leaderboard_response(rc_api_update_leaderboard_response_t* response, const char* server_response); +RC_EXPORT int RC_CCONV rc_api_process_update_leaderboard_server_response(rc_api_update_leaderboard_response_t* response, const rc_api_server_response_t* server_response); +RC_EXPORT void RC_CCONV rc_api_destroy_update_leaderboard_response(rc_api_update_leaderboard_response_t* response); /* --- Fetch Badge Range --- */ @@ -203,10 +203,10 @@ typedef struct rc_api_fetch_badge_range_response_t { } rc_api_fetch_badge_range_response_t; -int rc_api_init_fetch_badge_range_request(rc_api_request_t* request, const rc_api_fetch_badge_range_request_t* api_params); -int rc_api_process_fetch_badge_range_response(rc_api_fetch_badge_range_response_t* response, const char* server_response); -int rc_api_process_fetch_badge_range_server_response(rc_api_fetch_badge_range_response_t* response, const rc_api_server_response_t* server_response); -void rc_api_destroy_fetch_badge_range_response(rc_api_fetch_badge_range_response_t* response); +RC_EXPORT int RC_CCONV rc_api_init_fetch_badge_range_request(rc_api_request_t* request, const rc_api_fetch_badge_range_request_t* api_params); +RC_EXPORT int RC_CCONV rc_api_process_fetch_badge_range_response(rc_api_fetch_badge_range_response_t* response, const char* server_response); +RC_EXPORT int RC_CCONV rc_api_process_fetch_badge_range_server_response(rc_api_fetch_badge_range_response_t* response, const rc_api_server_response_t* server_response); +RC_EXPORT void RC_CCONV rc_api_destroy_fetch_badge_range_response(rc_api_fetch_badge_range_response_t* response); /* --- Add Game Hash --- */ @@ -243,13 +243,11 @@ typedef struct rc_api_add_game_hash_response_t { } rc_api_add_game_hash_response_t; -int rc_api_init_add_game_hash_request(rc_api_request_t* request, const rc_api_add_game_hash_request_t* api_params); -int rc_api_process_add_game_hash_response(rc_api_add_game_hash_response_t* response, const char* server_response); -int rc_api_process_add_game_hash_server_response(rc_api_add_game_hash_response_t* response, const rc_api_server_response_t* server_response); -void rc_api_destroy_add_game_hash_response(rc_api_add_game_hash_response_t* response); +RC_EXPORT int RC_CCONV rc_api_init_add_game_hash_request(rc_api_request_t* request, const rc_api_add_game_hash_request_t* api_params); +RC_EXPORT int RC_CCONV rc_api_process_add_game_hash_response(rc_api_add_game_hash_response_t* response, const char* server_response); +RC_EXPORT int RC_CCONV rc_api_process_add_game_hash_server_response(rc_api_add_game_hash_response_t* response, const rc_api_server_response_t* server_response); +RC_EXPORT void RC_CCONV rc_api_destroy_add_game_hash_response(rc_api_add_game_hash_response_t* response); -#ifdef __cplusplus -} -#endif +RC_END_C_DECLS #endif /* RC_EDITOR_H */ diff --git a/dep/rcheevos/include/rc_api_info.h b/dep/rcheevos/include/rc_api_info.h index a9586eeb9..93b652bf7 100644 --- a/dep/rcheevos/include/rc_api_info.h +++ b/dep/rcheevos/include/rc_api_info.h @@ -6,9 +6,7 @@ #include #include -#ifdef __cplusplus -extern "C" { -#endif +RC_BEGIN_C_DECLS /* --- Fetch Achievement Info --- */ @@ -63,10 +61,10 @@ typedef struct rc_api_fetch_achievement_info_response_t { } rc_api_fetch_achievement_info_response_t; -int rc_api_init_fetch_achievement_info_request(rc_api_request_t* request, const rc_api_fetch_achievement_info_request_t* api_params); -int rc_api_process_fetch_achievement_info_response(rc_api_fetch_achievement_info_response_t* response, const char* server_response); -int rc_api_process_fetch_achievement_info_server_response(rc_api_fetch_achievement_info_response_t* response, const rc_api_server_response_t* server_response); -void rc_api_destroy_fetch_achievement_info_response(rc_api_fetch_achievement_info_response_t* response); +RC_EXPORT int RC_CCONV rc_api_init_fetch_achievement_info_request(rc_api_request_t* request, const rc_api_fetch_achievement_info_request_t* api_params); +RC_EXPORT int RC_CCONV rc_api_process_fetch_achievement_info_response(rc_api_fetch_achievement_info_response_t* response, const char* server_response); +RC_EXPORT int RC_CCONV rc_api_process_fetch_achievement_info_server_response(rc_api_fetch_achievement_info_response_t* response, const rc_api_server_response_t* server_response); +RC_EXPORT void RC_CCONV rc_api_destroy_fetch_achievement_info_response(rc_api_fetch_achievement_info_response_t* response); /* --- Fetch Leaderboard Info --- */ @@ -135,10 +133,10 @@ typedef struct rc_api_fetch_leaderboard_info_response_t { } rc_api_fetch_leaderboard_info_response_t; -int rc_api_init_fetch_leaderboard_info_request(rc_api_request_t* request, const rc_api_fetch_leaderboard_info_request_t* api_params); -int rc_api_process_fetch_leaderboard_info_response(rc_api_fetch_leaderboard_info_response_t* response, const char* server_response); -int rc_api_process_fetch_leaderboard_info_server_response(rc_api_fetch_leaderboard_info_response_t* response, const rc_api_server_response_t* server_response); -void rc_api_destroy_fetch_leaderboard_info_response(rc_api_fetch_leaderboard_info_response_t* response); +RC_EXPORT int RC_CCONV rc_api_init_fetch_leaderboard_info_request(rc_api_request_t* request, const rc_api_fetch_leaderboard_info_request_t* api_params); +RC_EXPORT int RC_CCONV rc_api_process_fetch_leaderboard_info_response(rc_api_fetch_leaderboard_info_response_t* response, const char* server_response); +RC_EXPORT int RC_CCONV rc_api_process_fetch_leaderboard_info_server_response(rc_api_fetch_leaderboard_info_response_t* response, const rc_api_server_response_t* server_response); +RC_EXPORT void RC_CCONV rc_api_destroy_fetch_leaderboard_info_response(rc_api_fetch_leaderboard_info_response_t* response); /* --- Fetch Games List --- */ @@ -174,13 +172,11 @@ typedef struct rc_api_fetch_games_list_response_t { } rc_api_fetch_games_list_response_t; -int rc_api_init_fetch_games_list_request(rc_api_request_t* request, const rc_api_fetch_games_list_request_t* api_params); -int rc_api_process_fetch_games_list_response(rc_api_fetch_games_list_response_t* response, const char* server_response); -int rc_api_process_fetch_games_list_server_response(rc_api_fetch_games_list_response_t* response, const rc_api_server_response_t* server_response); -void rc_api_destroy_fetch_games_list_response(rc_api_fetch_games_list_response_t* response); +RC_EXPORT int RC_CCONV rc_api_init_fetch_games_list_request(rc_api_request_t* request, const rc_api_fetch_games_list_request_t* api_params); +RC_EXPORT int RC_CCONV rc_api_process_fetch_games_list_response(rc_api_fetch_games_list_response_t* response, const char* server_response); +RC_EXPORT int RC_CCONV rc_api_process_fetch_games_list_server_response(rc_api_fetch_games_list_response_t* response, const rc_api_server_response_t* server_response); +RC_EXPORT void RC_CCONV rc_api_destroy_fetch_games_list_response(rc_api_fetch_games_list_response_t* response); -#ifdef __cplusplus -} -#endif +RC_END_C_DECLS #endif /* RC_API_INFO_H */ diff --git a/dep/rcheevos/include/rc_api_request.h b/dep/rcheevos/include/rc_api_request.h index 578488f3d..4eba7f0d7 100644 --- a/dep/rcheevos/include/rc_api_request.h +++ b/dep/rcheevos/include/rc_api_request.h @@ -6,9 +6,7 @@ #include -#ifdef __cplusplus -extern "C" { -#endif +RC_BEGIN_C_DECLS /** * A constructed request to send to the retroachievements server. @@ -42,10 +40,10 @@ typedef struct rc_api_response_t { } rc_api_response_t; -void rc_api_destroy_request(rc_api_request_t* request); +RC_EXPORT void RC_CCONV rc_api_destroy_request(rc_api_request_t* request); -void rc_api_set_host(const char* hostname); -void rc_api_set_image_host(const char* hostname); +RC_EXPORT void RC_CCONV rc_api_set_host(const char* hostname); +RC_EXPORT void RC_CCONV rc_api_set_image_host(const char* hostname); typedef struct rc_api_server_response_t { /* Pointer to the data returned from the server */ @@ -61,8 +59,6 @@ enum { RC_API_SERVER_RESPONSE_RETRYABLE_CLIENT_ERROR = -2 }; -#ifdef __cplusplus -} -#endif +RC_END_C_DECLS #endif /* RC_API_REQUEST_H */ diff --git a/dep/rcheevos/include/rc_api_runtime.h b/dep/rcheevos/include/rc_api_runtime.h index e6d72a20d..5b5552ca5 100644 --- a/dep/rcheevos/include/rc_api_runtime.h +++ b/dep/rcheevos/include/rc_api_runtime.h @@ -6,9 +6,7 @@ #include #include -#ifdef __cplusplus -extern "C" { -#endif +RC_BEGIN_C_DECLS /* --- Fetch Image --- */ @@ -29,7 +27,7 @@ rc_api_fetch_image_request_t; #define RC_IMAGE_TYPE_ACHIEVEMENT_LOCKED 3 #define RC_IMAGE_TYPE_USER 4 -int rc_api_init_fetch_image_request(rc_api_request_t* request, const rc_api_fetch_image_request_t* api_params); +RC_EXPORT int RC_CCONV rc_api_init_fetch_image_request(rc_api_request_t* request, const rc_api_fetch_image_request_t* api_params); /* --- Resolve Hash --- */ @@ -58,10 +56,10 @@ typedef struct rc_api_resolve_hash_response_t { } rc_api_resolve_hash_response_t; -int rc_api_init_resolve_hash_request(rc_api_request_t* request, const rc_api_resolve_hash_request_t* api_params); -int rc_api_process_resolve_hash_response(rc_api_resolve_hash_response_t* response, const char* server_response); -int rc_api_process_resolve_hash_server_response(rc_api_resolve_hash_response_t* response, const rc_api_server_response_t* server_response); -void rc_api_destroy_resolve_hash_response(rc_api_resolve_hash_response_t* response); +RC_EXPORT int RC_CCONV rc_api_init_resolve_hash_request(rc_api_request_t* request, const rc_api_resolve_hash_request_t* api_params); +RC_EXPORT int RC_CCONV rc_api_process_resolve_hash_response(rc_api_resolve_hash_response_t* response, const char* server_response); +RC_EXPORT int RC_CCONV rc_api_process_resolve_hash_server_response(rc_api_resolve_hash_response_t* response, const rc_api_server_response_t* server_response); +RC_EXPORT void RC_CCONV rc_api_destroy_resolve_hash_response(rc_api_resolve_hash_response_t* response); /* --- Fetch Game Data --- */ @@ -119,12 +117,23 @@ typedef struct rc_api_achievement_definition_t { time_t created; /* When the achievement was last modified on the server */ time_t updated; + /* The achievement type (win/progression/missable) */ + uint32_t type; + /* The approximate rarity of the achievement (X% of users have earned the achievement) */ + float rarity; + /* The approximate rarity of the achievement in hardcore (X% of users have earned the achievement in hardcore) */ + float rarity_hardcore; } rc_api_achievement_definition_t; #define RC_ACHIEVEMENT_CATEGORY_CORE 3 #define RC_ACHIEVEMENT_CATEGORY_UNOFFICIAL 5 +#define RC_ACHIEVEMENT_TYPE_STANDARD 0 +#define RC_ACHIEVEMENT_TYPE_MISSABLE 1 +#define RC_ACHIEVEMENT_TYPE_PROGRESSION 2 +#define RC_ACHIEVEMENT_TYPE_WIN 3 + /** * Response data for a fetch game data request. */ @@ -155,10 +164,10 @@ typedef struct rc_api_fetch_game_data_response_t { } rc_api_fetch_game_data_response_t; -int rc_api_init_fetch_game_data_request(rc_api_request_t* request, const rc_api_fetch_game_data_request_t* api_params); -int rc_api_process_fetch_game_data_response(rc_api_fetch_game_data_response_t* response, const char* server_response); -int rc_api_process_fetch_game_data_server_response(rc_api_fetch_game_data_response_t* response, const rc_api_server_response_t* server_response); -void rc_api_destroy_fetch_game_data_response(rc_api_fetch_game_data_response_t* response); +RC_EXPORT int RC_CCONV rc_api_init_fetch_game_data_request(rc_api_request_t* request, const rc_api_fetch_game_data_request_t* api_params); +RC_EXPORT int RC_CCONV rc_api_process_fetch_game_data_response(rc_api_fetch_game_data_response_t* response, const char* server_response); +RC_EXPORT int RC_CCONV rc_api_process_fetch_game_data_server_response(rc_api_fetch_game_data_response_t* response, const rc_api_server_response_t* server_response); +RC_EXPORT void RC_CCONV rc_api_destroy_fetch_game_data_response(rc_api_fetch_game_data_response_t* response); /* --- Ping --- */ @@ -174,6 +183,10 @@ typedef struct rc_api_ping_request_t { uint32_t game_id; /* (optional) The current rich presence evaluation for the user */ const char* rich_presence; + /* (recommended) The hash associated to the game being played */ + const char* game_hash; + /* Non-zero if hardcore is currently enabled (ignored if game_hash is null) */ + uint32_t hardcore; } rc_api_ping_request_t; @@ -186,10 +199,10 @@ typedef struct rc_api_ping_response_t { } rc_api_ping_response_t; -int rc_api_init_ping_request(rc_api_request_t* request, const rc_api_ping_request_t* api_params); -int rc_api_process_ping_response(rc_api_ping_response_t* response, const char* server_response); -int rc_api_process_ping_server_response(rc_api_ping_response_t* response, const rc_api_server_response_t* server_response); -void rc_api_destroy_ping_response(rc_api_ping_response_t* response); +RC_EXPORT int RC_CCONV rc_api_init_ping_request(rc_api_request_t* request, const rc_api_ping_request_t* api_params); +RC_EXPORT int RC_CCONV rc_api_process_ping_response(rc_api_ping_response_t* response, const char* server_response); +RC_EXPORT int RC_CCONV rc_api_process_ping_server_response(rc_api_ping_response_t* response, const rc_api_server_response_t* server_response); +RC_EXPORT void RC_CCONV rc_api_destroy_ping_response(rc_api_ping_response_t* response); /* --- Award Achievement --- */ @@ -229,10 +242,10 @@ typedef struct rc_api_award_achievement_response_t { } rc_api_award_achievement_response_t; -int rc_api_init_award_achievement_request(rc_api_request_t* request, const rc_api_award_achievement_request_t* api_params); -int rc_api_process_award_achievement_response(rc_api_award_achievement_response_t* response, const char* server_response); -int rc_api_process_award_achievement_server_response(rc_api_award_achievement_response_t* response, const rc_api_server_response_t* server_response); -void rc_api_destroy_award_achievement_response(rc_api_award_achievement_response_t* response); +RC_EXPORT int RC_CCONV rc_api_init_award_achievement_request(rc_api_request_t* request, const rc_api_award_achievement_request_t* api_params); +RC_EXPORT int RC_CCONV rc_api_process_award_achievement_response(rc_api_award_achievement_response_t* response, const char* server_response); +RC_EXPORT int RC_CCONV rc_api_process_award_achievement_server_response(rc_api_award_achievement_response_t* response, const rc_api_server_response_t* server_response); +RC_EXPORT void RC_CCONV rc_api_destroy_award_achievement_response(rc_api_award_achievement_response_t* response); /* --- Submit Leaderboard Entry --- */ @@ -287,13 +300,11 @@ typedef struct rc_api_submit_lboard_entry_response_t { } rc_api_submit_lboard_entry_response_t; -int rc_api_init_submit_lboard_entry_request(rc_api_request_t* request, const rc_api_submit_lboard_entry_request_t* api_params); -int rc_api_process_submit_lboard_entry_response(rc_api_submit_lboard_entry_response_t* response, const char* server_response); -int rc_api_process_submit_lboard_entry_server_response(rc_api_submit_lboard_entry_response_t* response, const rc_api_server_response_t* server_response); -void rc_api_destroy_submit_lboard_entry_response(rc_api_submit_lboard_entry_response_t* response); +RC_EXPORT int RC_CCONV rc_api_init_submit_lboard_entry_request(rc_api_request_t* request, const rc_api_submit_lboard_entry_request_t* api_params); +RC_EXPORT int RC_CCONV rc_api_process_submit_lboard_entry_response(rc_api_submit_lboard_entry_response_t* response, const char* server_response); +RC_EXPORT int RC_CCONV rc_api_process_submit_lboard_entry_server_response(rc_api_submit_lboard_entry_response_t* response, const rc_api_server_response_t* server_response); +RC_EXPORT void RC_CCONV rc_api_destroy_submit_lboard_entry_response(rc_api_submit_lboard_entry_response_t* response); -#ifdef __cplusplus -} -#endif +RC_END_C_DECLS #endif /* RC_API_RUNTIME_H */ diff --git a/dep/rcheevos/include/rc_api_user.h b/dep/rcheevos/include/rc_api_user.h index 9fb348315..c06cec445 100644 --- a/dep/rcheevos/include/rc_api_user.h +++ b/dep/rcheevos/include/rc_api_user.h @@ -6,9 +6,7 @@ #include #include -#ifdef __cplusplus -extern "C" { -#endif +RC_BEGIN_C_DECLS /* --- Login --- */ @@ -48,10 +46,10 @@ typedef struct rc_api_login_response_t { } rc_api_login_response_t; -int rc_api_init_login_request(rc_api_request_t* request, const rc_api_login_request_t* api_params); -int rc_api_process_login_response(rc_api_login_response_t* response, const char* server_response); -int rc_api_process_login_server_response(rc_api_login_response_t* response, const rc_api_server_response_t* server_response); -void rc_api_destroy_login_response(rc_api_login_response_t* response); +RC_EXPORT int RC_CCONV rc_api_init_login_request(rc_api_request_t* request, const rc_api_login_request_t* api_params); +RC_EXPORT int RC_CCONV rc_api_process_login_response(rc_api_login_response_t* response, const char* server_response); +RC_EXPORT int RC_CCONV rc_api_process_login_server_response(rc_api_login_response_t* response, const rc_api_server_response_t* server_response); +RC_EXPORT void RC_CCONV rc_api_destroy_login_response(rc_api_login_response_t* response); /* --- Start Session --- */ @@ -65,6 +63,10 @@ typedef struct rc_api_start_session_request_t { const char* api_token; /* The unique identifier of the game */ uint32_t game_id; + /* (recommended) The hash associated to the game being played */ + const char* game_hash; + /* Non-zero if hardcore is currently enabled (ignored if game_hash is null) */ + uint32_t hardcore; } rc_api_start_session_request_t; @@ -101,10 +103,10 @@ typedef struct rc_api_start_session_response_t { } rc_api_start_session_response_t; -int rc_api_init_start_session_request(rc_api_request_t* request, const rc_api_start_session_request_t* api_params); -int rc_api_process_start_session_response(rc_api_start_session_response_t* response, const char* server_response); -int rc_api_process_start_session_server_response(rc_api_start_session_response_t* response, const rc_api_server_response_t* server_response); -void rc_api_destroy_start_session_response(rc_api_start_session_response_t* response); +RC_EXPORT int RC_CCONV rc_api_init_start_session_request(rc_api_request_t* request, const rc_api_start_session_request_t* api_params); +RC_EXPORT int RC_CCONV rc_api_process_start_session_response(rc_api_start_session_response_t* response, const char* server_response); +RC_EXPORT int RC_CCONV rc_api_process_start_session_server_response(rc_api_start_session_response_t* response, const rc_api_server_response_t* server_response); +RC_EXPORT void RC_CCONV rc_api_destroy_start_session_response(rc_api_start_session_response_t* response); /* --- Fetch User Unlocks --- */ @@ -137,13 +139,11 @@ typedef struct rc_api_fetch_user_unlocks_response_t { } rc_api_fetch_user_unlocks_response_t; -int rc_api_init_fetch_user_unlocks_request(rc_api_request_t* request, const rc_api_fetch_user_unlocks_request_t* api_params); -int rc_api_process_fetch_user_unlocks_response(rc_api_fetch_user_unlocks_response_t* response, const char* server_response); -int rc_api_process_fetch_user_unlocks_server_response(rc_api_fetch_user_unlocks_response_t* response, const rc_api_server_response_t* server_response); -void rc_api_destroy_fetch_user_unlocks_response(rc_api_fetch_user_unlocks_response_t* response); +RC_EXPORT int RC_CCONV rc_api_init_fetch_user_unlocks_request(rc_api_request_t* request, const rc_api_fetch_user_unlocks_request_t* api_params); +RC_EXPORT int RC_CCONV rc_api_process_fetch_user_unlocks_response(rc_api_fetch_user_unlocks_response_t* response, const char* server_response); +RC_EXPORT int RC_CCONV rc_api_process_fetch_user_unlocks_server_response(rc_api_fetch_user_unlocks_response_t* response, const rc_api_server_response_t* server_response); +RC_EXPORT void RC_CCONV rc_api_destroy_fetch_user_unlocks_response(rc_api_fetch_user_unlocks_response_t* response); -#ifdef __cplusplus -} -#endif +RC_END_C_DECLS #endif /* RC_API_H */ diff --git a/dep/rcheevos/include/rc_client.h b/dep/rcheevos/include/rc_client.h index da0c40bdf..5659aa74f 100644 --- a/dep/rcheevos/include/rc_client.h +++ b/dep/rcheevos/include/rc_client.h @@ -1,10 +1,6 @@ #ifndef RC_CLIENT_H #define RC_CLIENT_H -#ifdef __cplusplus -extern "C" { -#endif - #include "rc_api_request.h" #include "rc_error.h" @@ -12,6 +8,8 @@ extern "C" { #include #include +RC_BEGIN_C_DECLS + /* implementation abstracted in rc_client_internal.h */ typedef struct rc_client_t rc_client_t; typedef struct rc_client_async_handle_t rc_client_async_handle_t; @@ -24,27 +22,27 @@ typedef struct rc_client_async_handle_t rc_client_async_handle_t; * Callback used to read num_bytes bytes from memory starting at address into buffer. * Returns the number of bytes read. A return value of 0 indicates the address was invalid. */ -typedef uint32_t (*rc_client_read_memory_func_t)(uint32_t address, uint8_t* buffer, uint32_t num_bytes, rc_client_t* client); +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); /** * Internal method passed to rc_client_server_call_t to process the server response. */ -typedef void (*rc_client_server_callback_t)(const rc_api_server_response_t* server_response, void* callback_data); +typedef void (RC_CCONV *rc_client_server_callback_t)(const rc_api_server_response_t* server_response, void* callback_data); /** * Callback used to issue a request to the server. */ -typedef void (*rc_client_server_call_t)(const rc_api_request_t* request, rc_client_server_callback_t callback, void* callback_data, rc_client_t* client); +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); /** * Generic callback for asynchronous eventing. */ -typedef void (*rc_client_callback_t)(int result, const char* error_message, rc_client_t* client, void* userdata); +typedef void (RC_CCONV *rc_client_callback_t)(int result, const char* error_message, rc_client_t* client, void* userdata); /** * Callback for logging or displaying a message. */ -typedef void (*rc_client_message_callback_t)(const char* message, const rc_client_t* client); +typedef void (RC_CCONV *rc_client_message_callback_t)(const char* message, const rc_client_t* client); /*****************************************************************************\ | Runtime | @@ -53,13 +51,13 @@ typedef void (*rc_client_message_callback_t)(const char* message, const rc_clien /** * Creates a new rc_client_t object. */ -rc_client_t* rc_client_create(rc_client_read_memory_func_t read_memory_function, rc_client_server_call_t server_call_function); +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); /** * Releases resources associated to a rc_client_t object. * Pointer will no longer be valid after making this call. */ -void rc_client_destroy(rc_client_t* client); +RC_EXPORT void RC_CCONV rc_client_destroy(rc_client_t* client); /** * Sets whether hardcore is enabled (on by default). @@ -67,34 +65,34 @@ void rc_client_destroy(rc_client_t* client); * Enabling hardcore with a game loaded will raise an RC_CLIENT_EVENT_RESET * event. Processing will be disabled until rc_client_reset is called. */ -void rc_client_set_hardcore_enabled(rc_client_t* client, int enabled); +RC_EXPORT void RC_CCONV rc_client_set_hardcore_enabled(rc_client_t* client, int enabled); /** * Gets whether hardcore is enabled (on by default). */ -int rc_client_get_hardcore_enabled(const rc_client_t* client); +RC_EXPORT int RC_CCONV rc_client_get_hardcore_enabled(const rc_client_t* client); /** * Sets whether encore mode is enabled (off by default). * Evaluated when loading a game. Has no effect while a game is loaded. */ -void rc_client_set_encore_mode_enabled(rc_client_t* client, int enabled); +RC_EXPORT void RC_CCONV rc_client_set_encore_mode_enabled(rc_client_t* client, int enabled); /** * Gets whether encore mode is enabled (off by default). */ -int rc_client_get_encore_mode_enabled(const rc_client_t* client); +RC_EXPORT int RC_CCONV rc_client_get_encore_mode_enabled(const rc_client_t* client); /** * Sets whether unofficial achievements should be loaded. * Evaluated when loading a game. Has no effect while a game is loaded. */ -void rc_client_set_unofficial_enabled(rc_client_t* client, int enabled); +RC_EXPORT void RC_CCONV rc_client_set_unofficial_enabled(rc_client_t* client, int enabled); /** * Gets whether unofficial achievements should be loaded. */ -int rc_client_get_unofficial_enabled(const rc_client_t* client); +RC_EXPORT int RC_CCONV rc_client_get_unofficial_enabled(const rc_client_t* client); /** * Sets whether spectator mode is enabled (off by default). @@ -103,40 +101,40 @@ int rc_client_get_unofficial_enabled(const rc_client_t* client); * Can be modified while a game is loaded. Evaluated at unlock/submit time. * Cannot be modified if disabled before a game is loaded. */ -void rc_client_set_spectator_mode_enabled(rc_client_t* client, int enabled); +RC_EXPORT void RC_CCONV rc_client_set_spectator_mode_enabled(rc_client_t* client, int enabled); /** * Gets whether spectator mode is enabled (off by default). */ -int rc_client_get_spectator_mode_enabled(const rc_client_t* client); +RC_EXPORT int RC_CCONV rc_client_get_spectator_mode_enabled(const rc_client_t* client); /** * Attaches client-specific data to the runtime. */ -void rc_client_set_userdata(rc_client_t* client, void* userdata); +RC_EXPORT void RC_CCONV rc_client_set_userdata(rc_client_t* client, void* userdata); /** * Gets the client-specific data attached to the runtime. */ -void* rc_client_get_userdata(const rc_client_t* client); +RC_EXPORT void* RC_CCONV rc_client_get_userdata(const rc_client_t* client); /** * Sets the name of the server to use. */ -void rc_client_set_host(const rc_client_t* client, const char* hostname); +RC_EXPORT void RC_CCONV rc_client_set_host(const rc_client_t* client, const char* hostname); typedef uint64_t rc_clock_t; -typedef rc_clock_t (*rc_get_time_millisecs_func_t)(const rc_client_t* client); +typedef rc_clock_t (RC_CCONV *rc_get_time_millisecs_func_t)(const rc_client_t* client); /** * Specifies a function that returns a value that increases once per millisecond. */ -void rc_client_set_get_time_millisecs_function(rc_client_t* client, rc_get_time_millisecs_func_t handler); +RC_EXPORT void RC_CCONV rc_client_set_get_time_millisecs_function(rc_client_t* client, rc_get_time_millisecs_func_t handler); /** * Marks an async process as aborted. The associated callback will not be called. */ -void rc_client_abort_async(rc_client_t* client, rc_client_async_handle_t* async_handle); +RC_EXPORT void RC_CCONV rc_client_abort_async(rc_client_t* client, rc_client_async_handle_t* async_handle); /*****************************************************************************\ | Logging | @@ -145,7 +143,7 @@ void rc_client_abort_async(rc_client_t* client, rc_client_async_handle_t* async_ /** * Sets the logging level and provides a callback to be called to do the logging. */ -void rc_client_enable_logging(rc_client_t* client, int level, rc_client_message_callback_t callback); +RC_EXPORT void RC_CCONV rc_client_enable_logging(rc_client_t* client, int level, rc_client_message_callback_t callback); enum { RC_CLIENT_LOG_LEVEL_NONE = 0, RC_CLIENT_LOG_LEVEL_ERROR = 1, @@ -162,21 +160,21 @@ enum { /** * Attempt to login a user. */ -rc_client_async_handle_t* rc_client_begin_login_with_password(rc_client_t* client, +RC_EXPORT rc_client_async_handle_t* RC_CCONV rc_client_begin_login_with_password(rc_client_t* client, const char* username, const char* password, rc_client_callback_t callback, void* callback_userdata); /** * Attempt to login a user. */ -rc_client_async_handle_t* rc_client_begin_login_with_token(rc_client_t* client, +RC_EXPORT rc_client_async_handle_t* RC_CCONV rc_client_begin_login_with_token(rc_client_t* client, const char* username, const char* token, rc_client_callback_t callback, void* callback_userdata); /** * Logout the user. */ -void rc_client_logout(rc_client_t* client); +RC_EXPORT void RC_CCONV rc_client_logout(rc_client_t* client); typedef struct rc_client_user_t { const char* display_name; @@ -190,16 +188,15 @@ typedef struct rc_client_user_t { /** * Gets information about the logged in user. Will return NULL if the user is not logged in. */ -const rc_client_user_t* rc_client_get_user_info(const rc_client_t* client); +RC_EXPORT const rc_client_user_t* RC_CCONV rc_client_get_user_info(const rc_client_t* client); /** * Gets the URL for the user's profile picture. * Returns RC_OK on success. */ -int rc_client_user_get_image_url(const rc_client_user_t* user, char buffer[], size_t buffer_size); +RC_EXPORT int RC_CCONV rc_client_user_get_image_url(const rc_client_user_t* user, char buffer[], size_t buffer_size); -typedef struct rc_client_user_game_summary_t -{ +typedef struct rc_client_user_game_summary_t { uint32_t num_core_achievements; uint32_t num_unofficial_achievements; uint32_t num_unlocked_achievements; @@ -213,7 +210,7 @@ typedef struct rc_client_user_game_summary_t * Gets a breakdown of the number of achievements in the game, and how many the user has unlocked. * Used for the "You have unlocked X of Y achievements" message shown when the game starts. */ -void rc_client_get_user_game_summary(const rc_client_t* client, rc_client_user_game_summary_t* summary); +RC_EXPORT void RC_CCONV rc_client_get_user_game_summary(const rc_client_t* client, rc_client_user_game_summary_t* summary); /*****************************************************************************\ | Game | @@ -222,7 +219,7 @@ void rc_client_get_user_game_summary(const rc_client_t* client, rc_client_user_g /** * Start loading an unidentified game. */ -rc_client_async_handle_t* rc_client_begin_identify_and_load_game(rc_client_t* client, +RC_EXPORT rc_client_async_handle_t* RC_CCONV rc_client_begin_identify_and_load_game(rc_client_t* client, uint32_t console_id, const char* file_path, const uint8_t* data, size_t data_size, rc_client_callback_t callback, void* callback_userdata); @@ -230,13 +227,13 @@ rc_client_async_handle_t* rc_client_begin_identify_and_load_game(rc_client_t* cl /** * Start loading a game. */ -rc_client_async_handle_t* rc_client_begin_load_game(rc_client_t* client, const char* hash, +RC_EXPORT rc_client_async_handle_t* RC_CCONV rc_client_begin_load_game(rc_client_t* client, const char* hash, rc_client_callback_t callback, void* callback_userdata); /** * Unloads the current game. */ -void rc_client_unload_game(rc_client_t* client); +RC_EXPORT void RC_CCONV rc_client_unload_game(rc_client_t* client); typedef struct rc_client_game_t { uint32_t id; @@ -249,18 +246,18 @@ typedef struct rc_client_game_t { /** * Get information about the current game. Returns NULL if no game is loaded. */ -const rc_client_game_t* rc_client_get_game_info(const rc_client_t* client); +RC_EXPORT const rc_client_game_t* RC_CCONV rc_client_get_game_info(const rc_client_t* client); /** * Gets the URL for the game image. * Returns RC_OK on success. */ -int rc_client_game_get_image_url(const rc_client_game_t* game, char buffer[], size_t buffer_size); +RC_EXPORT int RC_CCONV rc_client_game_get_image_url(const rc_client_game_t* game, char buffer[], size_t buffer_size); /** * Changes the active disc in a multi-disc game. */ -rc_client_async_handle_t* rc_client_begin_change_media(rc_client_t* client, const char* file_path, +RC_EXPORT rc_client_async_handle_t* RC_CCONV rc_client_begin_change_media(rc_client_t* client, const char* file_path, const uint8_t* data, size_t data_size, rc_client_callback_t callback, void* callback_userdata); /*****************************************************************************\ @@ -276,7 +273,7 @@ typedef struct rc_client_subset_t { uint32_t num_leaderboards; } rc_client_subset_t; -const rc_client_subset_t* rc_client_get_subset_info(rc_client_t* client, uint32_t subset_id); +RC_EXPORT const rc_client_subset_t* RC_CCONV rc_client_get_subset_info(rc_client_t* client, uint32_t subset_id); /*****************************************************************************\ | Achievements | @@ -297,6 +294,13 @@ enum { RC_CLIENT_ACHIEVEMENT_CATEGORY_CORE_AND_UNOFFICIAL = RC_CLIENT_ACHIEVEMENT_CATEGORY_CORE | RC_CLIENT_ACHIEVEMENT_CATEGORY_UNOFFICIAL }; +enum { + RC_CLIENT_ACHIEVEMENT_TYPE_STANDARD = 0, + RC_CLIENT_ACHIEVEMENT_TYPE_MISSABLE = 1, + RC_CLIENT_ACHIEVEMENT_TYPE_PROGRESSION = 2, + RC_CLIENT_ACHIEVEMENT_TYPE_WIN = 3 +}; + enum { RC_CLIENT_ACHIEVEMENT_BUCKET_UNKNOWN = 0, RC_CLIENT_ACHIEVEMENT_BUCKET_LOCKED = 1, @@ -306,7 +310,8 @@ enum { RC_CLIENT_ACHIEVEMENT_BUCKET_RECENTLY_UNLOCKED = 5, RC_CLIENT_ACHIEVEMENT_BUCKET_ACTIVE_CHALLENGE = 6, RC_CLIENT_ACHIEVEMENT_BUCKET_ALMOST_THERE = 7, - NUM_RC_CLIENT_ACHIEVEMENT_BUCKETS = 8 + RC_CLIENT_ACHIEVEMENT_BUCKET_UNSYNCED = 8, + NUM_RC_CLIENT_ACHIEVEMENT_BUCKETS = 9 }; enum { @@ -329,18 +334,22 @@ typedef struct rc_client_achievement_t { uint8_t category; uint8_t bucket; uint8_t unlocked; + /* minimum version: 11.1 */ + float rarity; + float rarity_hardcore; + uint8_t type; } rc_client_achievement_t; /** * Get information about an achievement. Returns NULL if not found. */ -const rc_client_achievement_t* rc_client_get_achievement_info(rc_client_t* client, uint32_t id); +RC_EXPORT const rc_client_achievement_t* RC_CCONV rc_client_get_achievement_info(rc_client_t* client, uint32_t id); /** * Gets the URL for the achievement image. * Returns RC_OK on success. */ -int rc_client_achievement_get_image_url(const rc_client_achievement_t* achievement, int state, char buffer[], size_t buffer_size); +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); typedef struct rc_client_achievement_bucket_t { rc_client_achievement_t** achievements; @@ -365,17 +374,17 @@ enum { * Creates a list of achievements matching the specified category and grouping. * Returns an allocated list that must be free'd by calling rc_client_destroy_achievement_list. */ -rc_client_achievement_list_t* rc_client_create_achievement_list(rc_client_t* client, int category, int grouping); +RC_EXPORT rc_client_achievement_list_t* RC_CCONV rc_client_create_achievement_list(rc_client_t* client, int category, int grouping); /** * Destroys a list allocated by rc_client_get_achievement_list. */ -void rc_client_destroy_achievement_list(rc_client_achievement_list_t* list); +RC_EXPORT void RC_CCONV rc_client_destroy_achievement_list(rc_client_achievement_list_t* list); /** * Returns non-zero if there are any achievements that can be queried through rc_client_create_achievement_list(). */ -int rc_client_has_achievements(rc_client_t* client); +RC_EXPORT int RC_CCONV rc_client_has_achievements(rc_client_t* client); /*****************************************************************************\ | Leaderboards | @@ -411,7 +420,7 @@ typedef struct rc_client_leaderboard_t { /** * Get information about a leaderboard. Returns NULL if not found. */ -const rc_client_leaderboard_t* rc_client_get_leaderboard_info(const rc_client_t* client, uint32_t id); +RC_EXPORT const rc_client_leaderboard_t* RC_CCONV rc_client_get_leaderboard_info(const rc_client_t* client, uint32_t id); typedef struct rc_client_leaderboard_tracker_t { char display[RC_CLIENT_LEADERBOARD_DISPLAY_SIZE]; @@ -450,17 +459,17 @@ enum { * Creates a list of leaderboards matching the specified grouping. * Returns an allocated list that must be free'd by calling rc_client_destroy_leaderboard_list. */ -rc_client_leaderboard_list_t* rc_client_create_leaderboard_list(rc_client_t* client, int grouping); +RC_EXPORT rc_client_leaderboard_list_t* RC_CCONV rc_client_create_leaderboard_list(rc_client_t* client, int grouping); /** * Destroys a list allocated by rc_client_get_leaderboard_list. */ -void rc_client_destroy_leaderboard_list(rc_client_leaderboard_list_t* list); +RC_EXPORT void RC_CCONV rc_client_destroy_leaderboard_list(rc_client_leaderboard_list_t* list); /** * Returns non-zero if the current game has any leaderboards. */ -int rc_client_has_leaderboards(rc_client_t* client); +RC_EXPORT int RC_CCONV rc_client_has_leaderboards(rc_client_t* client); typedef struct rc_client_leaderboard_entry_t { const char* user; @@ -476,33 +485,33 @@ typedef struct rc_client_leaderboard_entry_list_t { int32_t user_index; } rc_client_leaderboard_entry_list_t; -typedef void (*rc_client_fetch_leaderboard_entries_callback_t)(int result, const char* error_message, +typedef void (RC_CCONV *rc_client_fetch_leaderboard_entries_callback_t)(int result, const char* error_message, rc_client_leaderboard_entry_list_t* list, rc_client_t* client, void* callback_userdata); /** * Fetches a list of leaderboard entries from the server. * Callback receives an allocated list that must be free'd by calling rc_client_destroy_leaderboard_entry_list. */ -rc_client_async_handle_t* rc_client_begin_fetch_leaderboard_entries(rc_client_t* client, uint32_t leaderboard_id, +RC_EXPORT rc_client_async_handle_t* RC_CCONV rc_client_begin_fetch_leaderboard_entries(rc_client_t* client, uint32_t leaderboard_id, uint32_t first_entry, uint32_t count, rc_client_fetch_leaderboard_entries_callback_t callback, void* callback_userdata); /** * Fetches a list of leaderboard entries from the server containing the logged-in user. * Callback receives an allocated list that must be free'd by calling rc_client_destroy_leaderboard_entry_list. */ -rc_client_async_handle_t* rc_client_begin_fetch_leaderboard_entries_around_user(rc_client_t* client, uint32_t leaderboard_id, +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, uint32_t count, rc_client_fetch_leaderboard_entries_callback_t callback, void* callback_userdata); /** * Gets the URL for the profile picture of the user associated to a leaderboard entry. * Returns RC_OK on success. */ -int rc_client_leaderboard_entry_get_user_image_url(const rc_client_leaderboard_entry_t* entry, char buffer[], size_t buffer_size); +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); /** * Destroys a list allocated by rc_client_begin_fetch_leaderboard_entries or rc_client_begin_fetch_leaderboard_entries_around_user. */ -void rc_client_destroy_leaderboard_entry_list(rc_client_leaderboard_entry_list_t* list); +RC_EXPORT void RC_CCONV rc_client_destroy_leaderboard_entry_list(rc_client_leaderboard_entry_list_t* list); /** * Used for scoreboard events. Contains the response from the server when a leaderboard entry is submitted. @@ -543,13 +552,13 @@ typedef struct rc_client_leaderboard_scoreboard_t { /** * Returns non-zero if the current game supports rich presence. */ -int rc_client_has_rich_presence(rc_client_t* client); +RC_EXPORT int RC_CCONV rc_client_has_rich_presence(rc_client_t* client); /** * Gets the current rich presence message. * Returns the number of characters written to buffer. */ -size_t rc_client_get_rich_presence_message(rc_client_t* client, char buffer[], size_t buffer_size); +RC_EXPORT size_t RC_CCONV rc_client_get_rich_presence_message(rc_client_t* client, char buffer[], size_t buffer_size); /*****************************************************************************\ | Processing | @@ -577,16 +586,14 @@ enum { RC_CLIENT_EVENT_RECONNECTED = 18 /* all pending unlocks have been completed */ }; -typedef struct rc_client_server_error_t -{ +typedef struct rc_client_server_error_t { const char* error_message; const char* api; int result; uint32_t related_id; } rc_client_server_error_t; -typedef struct rc_client_event_t -{ +typedef struct rc_client_event_t { uint32_t type; rc_client_achievement_t* achievement; @@ -600,60 +607,66 @@ typedef struct rc_client_event_t /** * Callback used to notify the client when certain events occur. */ -typedef void (*rc_client_event_handler_t)(const rc_client_event_t* event, rc_client_t* client); +typedef void (RC_CCONV *rc_client_event_handler_t)(const rc_client_event_t* event, rc_client_t* client); /** * Provides a callback for event handling. */ -void rc_client_set_event_handler(rc_client_t* client, rc_client_event_handler_t handler); +RC_EXPORT void RC_CCONV rc_client_set_event_handler(rc_client_t* client, rc_client_event_handler_t handler); /** * Provides a callback for reading memory. */ -void rc_client_set_read_memory_function(rc_client_t* client, rc_client_read_memory_func_t handler); +RC_EXPORT void RC_CCONV rc_client_set_read_memory_function(rc_client_t* client, rc_client_read_memory_func_t handler); /** * Determines if there are any active achievements/leaderboards/rich presence that need processing. */ -int rc_client_is_processing_required(rc_client_t* client); +RC_EXPORT int RC_CCONV rc_client_is_processing_required(rc_client_t* client); /** * Processes achievements for the current frame. */ -void rc_client_do_frame(rc_client_t* client); +RC_EXPORT void RC_CCONV rc_client_do_frame(rc_client_t* client); /** * Processes the periodic queue. * Called internally by rc_client_do_frame. * Should be explicitly called if rc_client_do_frame is not being called because emulation is paused. */ -void rc_client_idle(rc_client_t* client); +RC_EXPORT void RC_CCONV rc_client_idle(rc_client_t* client); + +/** + * Determines if a sufficient amount of frames have been processed since the last call to rc_client_can_pause. + * Should not be called unless the client is trying to pause. + * If false is returned, and frames_remaining is not NULL, frames_remaining will be set to the number of frames + * still required before pause is allowed, which can be converted to a time in seconds for displaying to the user. + */ +RC_EXPORT int RC_CCONV rc_client_can_pause(rc_client_t* client, uint32_t* frames_remaining); /** * Informs the runtime that the emulator has been reset. Will reset all achievements and leaderboards * to their initial state (includes hiding indicators/trackers). */ -void rc_client_reset(rc_client_t* client); +RC_EXPORT void RC_CCONV rc_client_reset(rc_client_t* client); /** * Gets the number of bytes needed to serialized the runtime state. */ -size_t rc_client_progress_size(rc_client_t* client); +RC_EXPORT size_t RC_CCONV rc_client_progress_size(rc_client_t* client); /** * Serializes the runtime state into a buffer. * Returns RC_OK on success, or an error indicator. */ -int rc_client_serialize_progress(rc_client_t* client, uint8_t* buffer); +RC_EXPORT int RC_CCONV rc_client_serialize_progress(rc_client_t* client, uint8_t* buffer); /** * Deserializes the runtime state from a buffer. * Returns RC_OK on success, or an error indicator. */ -int rc_client_deserialize_progress(rc_client_t* client, const uint8_t* serialized); +RC_EXPORT int RC_CCONV rc_client_deserialize_progress(rc_client_t* client, const uint8_t* serialized); -#ifdef __cplusplus -} -#endif +RC_END_C_DECLS #endif /* RC_RUNTIME_H */ diff --git a/dep/rcheevos/include/rc_client_raintegration.h b/dep/rcheevos/include/rc_client_raintegration.h index d8a6ef181..b2e77cdec 100644 --- a/dep/rcheevos/include/rc_client_raintegration.h +++ b/dep/rcheevos/include/rc_client_raintegration.h @@ -1,35 +1,85 @@ #ifndef RC_CLIENT_RAINTEGRATION_H #define RC_CLIENT_RAINTEGRATION_H -#ifdef __cplusplus -extern "C" { -#endif - #ifndef _WIN32 #undef RC_CLIENT_SUPPORTS_RAINTEGRATION /* Windows required for RAIntegration */ #endif +#include + +#include "rc_export.h" + +RC_BEGIN_C_DECLS + +typedef struct rc_client_t rc_client_t; /* forward reference; in rc_client.h */ + +/* types needed to implement raintegration */ + +typedef struct rc_client_raintegration_menu_item_t { + const char* label; + uint32_t id; + uint8_t checked; + uint8_t enabled; +} rc_client_raintegration_menu_item_t; + +typedef struct rc_client_raintegration_menu_t { + rc_client_raintegration_menu_item_t* items; + uint32_t num_items; +} rc_client_raintegration_menu_t; + +enum { + RC_CLIENT_RAINTEGRATION_EVENT_TYPE_NONE = 0, + RC_CLIENT_RAINTEGRATION_EVENT_MENUITEM_CHECKED_CHANGED = 1, /* [menu_item] checked changed */ + RC_CLIENT_RAINTEGRATION_EVENT_HARDCORE_CHANGED = 2, /* hardcore was enabled or disabled */ + RC_CLIENT_RAINTEGRATION_EVENT_PAUSE = 3 /* emulated system should be paused */ +}; + +typedef struct rc_client_raintegration_event_t { + uint32_t type; + + const rc_client_raintegration_menu_item_t* menu_item; +} rc_client_raintegration_event_t; + +typedef void (RC_CCONV *rc_client_raintegration_event_handler_t)(const rc_client_raintegration_event_t* event, + rc_client_t* client); + +typedef void (RC_CCONV *rc_client_raintegration_write_memory_func_t)(uint32_t address, uint8_t* buffer, + uint32_t num_bytes, rc_client_t* client); + +/* types needed to integrate raintegration */ + #ifdef RC_CLIENT_SUPPORTS_RAINTEGRATION #ifndef RC_CLIENT_SUPPORTS_EXTERNAL #define RC_CLIENT_SUPPORTS_EXTERNAL /* external rc_client required for RAIntegration */ #endif -#include "rc_client.h" - #include /* HWND */ -rc_client_async_handle_t* rc_client_begin_load_raintegration(rc_client_t* client, +#include "rc_client.h" + +RC_EXPORT rc_client_async_handle_t* RC_CCONV rc_client_begin_load_raintegration(rc_client_t* client, const wchar_t* search_directory, HWND main_window_handle, const char* client_name, const char* client_version, rc_client_callback_t callback, void* callback_userdata); -void rc_client_unload_raintegration(rc_client_t* client); +RC_EXPORT void RC_CCONV rc_client_unload_raintegration(rc_client_t* client); + +RC_EXPORT void RC_CCONV rc_client_raintegration_update_main_window_handle(rc_client_t* client, HWND main_window_handle); + +RC_EXPORT const rc_client_raintegration_menu_t* RC_CCONV rc_client_raintegration_get_menu(const rc_client_t* client); + +RC_EXPORT void RC_CCONV rc_client_raintegration_rebuild_submenu(rc_client_t* client, HMENU hMenu); +RC_EXPORT void RC_CCONV rc_client_raintegration_update_menu_item(const rc_client_t* client, const rc_client_raintegration_menu_item_t* menu_item); +RC_EXPORT int RC_CCONV rc_client_raintegration_activate_menu_item(const rc_client_t* client, uint32_t nMenuItemId); + +RC_EXPORT void RC_CCONV rc_client_raintegration_set_write_memory_function(rc_client_t* client, rc_client_raintegration_write_memory_func_t handler); + +RC_EXPORT void RC_CCONV rc_client_raintegration_set_event_handler(rc_client_t* client, + rc_client_raintegration_event_handler_t handler); #endif /* RC_CLIENT_SUPPORTS_RAINTEGRATION */ -#ifdef __cplusplus -} -#endif +RC_END_C_DECLS #endif /* RC_CLIENT_RAINTEGRATION_H */ diff --git a/dep/rcheevos/include/rc_consoles.h b/dep/rcheevos/include/rc_consoles.h index e416bc9e0..269879202 100644 --- a/dep/rcheevos/include/rc_consoles.h +++ b/dep/rcheevos/include/rc_consoles.h @@ -1,12 +1,12 @@ #ifndef RC_CONSOLES_H #define RC_CONSOLES_H -#ifdef __cplusplus -extern "C" { -#endif +#include "rc_export.h" #include +RC_BEGIN_C_DECLS + /*****************************************************************************\ | Console identifiers | \*****************************************************************************/ @@ -95,10 +95,11 @@ enum { RC_CONSOLE_UZEBOX = 80, RC_CONSOLE_HUBS = 100, - RC_CONSOLE_EVENTS = 101 + RC_CONSOLE_EVENTS = 101, + RC_CONSOLE_STANDALONE = 102 }; -const char* rc_console_name(int console_id); +RC_EXPORT const char* RC_CCONV rc_console_name(uint32_t console_id); /*****************************************************************************\ | Memory mapping | @@ -129,11 +130,8 @@ typedef struct rc_memory_regions_t { } rc_memory_regions_t; -const rc_memory_regions_t* rc_console_memory_regions(uint32_t console_id); +RC_EXPORT const rc_memory_regions_t* RC_CCONV rc_console_memory_regions(uint32_t console_id); - -#ifdef __cplusplus -} -#endif +RC_END_C_DECLS #endif /* RC_CONSOLES_H */ diff --git a/dep/rcheevos/include/rc_error.h b/dep/rcheevos/include/rc_error.h index 89d762708..d0aca2fd7 100644 --- a/dep/rcheevos/include/rc_error.h +++ b/dep/rcheevos/include/rc_error.h @@ -1,9 +1,9 @@ #ifndef RC_ERROR_H #define RC_ERROR_H -#ifdef __cplusplus -extern "C" { -#endif +#include "rc_export.h" + +RC_BEGIN_C_DECLS /*****************************************************************************\ | Return values | @@ -48,10 +48,8 @@ enum { RC_EXPIRED_TOKEN = -35 }; -const char* rc_error_str(int ret); +RC_EXPORT const char* RC_CCONV rc_error_str(int ret); -#ifdef __cplusplus -} -#endif +RC_END_C_DECLS #endif /* RC_ERROR_H */ diff --git a/dep/rcheevos/include/rc_export.h b/dep/rcheevos/include/rc_export.h new file mode 100644 index 000000000..da111056d --- /dev/null +++ b/dep/rcheevos/include/rc_export.h @@ -0,0 +1,100 @@ +#ifndef RC_EXPORT_H +#define RC_EXPORT_H + +/* These macros control how callbacks and public functions are defined */ + +/* RC_SHARED should be defined when building rcheevos as a shared library (e.g. dll/dylib/so). External code should not define this macro. */ +/* RC_STATIC should be defined when building rcheevos as a static library. External code should also define this macro. */ +/* RC_IMPORT should be defined for external code using rcheevos as a shared library. */ + +/* For compatibility, if none of these three macros are defined, then the build is assumed to be RC_STATIC */ + +#if !defined(RC_SHARED) && !defined(RC_STATIC) && !defined(RC_IMPORT) + #define RC_STATIC +#endif + +#if (defined(RC_SHARED) && defined(RC_STATIC)) || (defined(RC_SHARED) && defined(RC_IMPORT)) || (defined(RC_STATIC) && defined(RC_IMPORT)) + #error RC_SHARED, RC_STATIC, and RC_IMPORT are mutually exclusive +#endif + +/* RC_BEGIN_C_DECLS and RC_END_C_DECLS should be used for all headers, to enforce C linkage and the C calling convention */ +/* RC_BEGIN_C_DECLS should be placed after #include's and before header declarations */ +/* RC_END_C_DECLS should be placed after header declarations */ + +/* example usage + * + * #ifndef RC_HEADER_H + * #define RC_HEADER_H + * + * #include + * + * RC_BEGIN_C_DECLS + * + * uint8_t rc_function(void); + * + * RC_END_C_DECLS + * + * #endif + */ + +#ifdef __cplusplus + #define RC_BEGIN_C_DECLS extern "C" { + #define RC_END_C_DECLS } +#else + #define RC_BEGIN_C_DECLS + #define RC_END_C_DECLS +#endif + +/* RC_CCONV should be used for public functions and callbacks, to enforce the cdecl calling convention, if applicable */ +/* RC_CCONV should be placed after the return type, and between the ( and * for callbacks */ + +/* example usage */ +/* void RC_CCONV rc_function(void) */ +/* void (RC_CCONV *rc_callback)(void) */ + +#if defined(_WIN32) + /* Windows compilers will ignore __cdecl when not applicable */ + #define RC_CCONV __cdecl +#elif defined(__GNUC__) && defined(__i386__) + /* GNU C compilers will warn if cdecl is defined on an unsupported platform */ + #define RC_CCONV __attribute__((cdecl)) +#else + #define RC_CCONV +#endif + +/* RC_EXPORT should be used for public functions */ +/* RC_EXPORT will provide necessary hints for shared library usage, if applicable */ +/* RC_EXPORT should be placed before the return type */ + +/* example usage */ +/* RC_EXPORT void rc_function(void) */ + +#ifdef RC_SHARED + #if defined(_WIN32) + #define RC_EXPORT __declspec(dllexport) + #elif defined(__GNUC__) && __GNUC__ >= 4 + #define RC_EXPORT __attribute__((visibility("default"))) + #else + #define RC_EXPORT + #endif +#endif + +#ifdef RC_IMPORT + #if defined(_WIN32) + #define RC_EXPORT __declspec(dllimport) + #elif defined(__GNUC__) && __GNUC__ >= 4 + #define RC_EXPORT __attribute__((visibility("default"))) + #else + #define RC_EXPORT + #endif +#endif + +#ifdef RC_STATIC + #if defined(__GNUC__) && __GNUC__ >= 4 + #define RC_EXPORT __attribute__((visibility("default"))) + #else + #define RC_EXPORT + #endif +#endif + +#endif /* RC_EXPORT_H */ diff --git a/dep/rcheevos/include/rc_hash.h b/dep/rcheevos/include/rc_hash.h index ba9ea1c02..a762615cb 100644 --- a/dep/rcheevos/include/rc_hash.h +++ b/dep/rcheevos/include/rc_hash.h @@ -7,21 +7,19 @@ #include "rc_consoles.h" -#ifdef __cplusplus -extern "C" { -#endif +RC_BEGIN_C_DECLS /* ===================================================== */ /* generates a hash from a block of memory. * returns non-zero on success, or zero on failure. */ - int rc_hash_generate_from_buffer(char hash[33], int console_id, const uint8_t* buffer, size_t buffer_size); + RC_EXPORT int RC_CCONV rc_hash_generate_from_buffer(char hash[33], uint32_t console_id, const uint8_t* buffer, size_t buffer_size); /* generates a hash from a file. * returns non-zero on success, or zero on failure. */ - int rc_hash_generate_from_file(char hash[33], int console_id, const char* path); + RC_EXPORT int RC_CCONV rc_hash_generate_from_file(char hash[33], uint32_t console_id, const char* path); /* ===================================================== */ @@ -40,44 +38,44 @@ extern "C" { * - path must be provided * - if buffer and buffer_size are provided, path may be a filename (i.e. for something extracted from a zip file) */ - void rc_hash_initialize_iterator(struct rc_hash_iterator* iterator, const char* path, const uint8_t* buffer, size_t buffer_size); + RC_EXPORT void RC_CCONV rc_hash_initialize_iterator(struct rc_hash_iterator* iterator, const char* path, const uint8_t* buffer, size_t buffer_size); /* releases resources associated to a rc_hash_iterator */ - void rc_hash_destroy_iterator(struct rc_hash_iterator* iterator); + RC_EXPORT void RC_CCONV rc_hash_destroy_iterator(struct rc_hash_iterator* iterator); /* generates the next hash for the data in the rc_hash_iterator. * returns non-zero if a hash was generated, or zero if no more hashes can be generated for the data. */ - int rc_hash_iterate(char hash[33], struct rc_hash_iterator* iterator); + RC_EXPORT int RC_CCONV rc_hash_iterate(char hash[33], struct rc_hash_iterator* iterator); /* ===================================================== */ /* specifies a function to call when an error occurs to display the error message */ - typedef void (*rc_hash_message_callback)(const char*); - void rc_hash_init_error_message_callback(rc_hash_message_callback callback); + typedef void (RC_CCONV *rc_hash_message_callback)(const char*); + RC_EXPORT void RC_CCONV rc_hash_init_error_message_callback(rc_hash_message_callback callback); /* specifies a function to call for verbose logging */ - void rc_hash_init_verbose_message_callback(rc_hash_message_callback callback); + RC_EXPORT void rc_hash_init_verbose_message_callback(rc_hash_message_callback callback); /* ===================================================== */ /* opens a file */ - typedef void* (*rc_hash_filereader_open_file_handler)(const char* path_utf8); + typedef void* (RC_CCONV *rc_hash_filereader_open_file_handler)(const char* path_utf8); /* moves the file pointer - standard fseek parameters */ - typedef void (*rc_hash_filereader_seek_handler)(void* file_handle, int64_t offset, int origin); + typedef void (RC_CCONV *rc_hash_filereader_seek_handler)(void* file_handle, int64_t offset, int origin); /* locates the file pointer */ - typedef int64_t (*rc_hash_filereader_tell_handler)(void* file_handle); + typedef int64_t (RC_CCONV *rc_hash_filereader_tell_handler)(void* file_handle); /* reads the specified number of bytes from the file starting at the read pointer. * returns the number of bytes actually read. */ - typedef size_t (*rc_hash_filereader_read_handler)(void* file_handle, void* buffer, size_t requested_bytes); + typedef size_t (RC_CCONV *rc_hash_filereader_read_handler)(void* file_handle, void* buffer, size_t requested_bytes); /* closes the file */ - typedef void (*rc_hash_filereader_close_file_handler)(void* file_handle); + typedef void (RC_CCONV *rc_hash_filereader_close_file_handler)(void* file_handle); struct rc_hash_filereader { @@ -88,7 +86,7 @@ extern "C" { rc_hash_filereader_close_file_handler close; }; - void rc_hash_init_custom_filereader(struct rc_hash_filereader* reader); + RC_EXPORT void RC_CCONV rc_hash_init_custom_filereader(struct rc_hash_filereader* reader); /* ===================================================== */ @@ -100,18 +98,18 @@ extern "C" { /* opens a track from the specified file. see the RC_HASH_CDTRACK_ defines for special tracks. * returns a handle to be passed to the other functions, or NULL if the track could not be opened. */ - typedef void* (*rc_hash_cdreader_open_track_handler)(const char* path, uint32_t track); + typedef void* (RC_CCONV *rc_hash_cdreader_open_track_handler)(const char* path, uint32_t track); /* attempts to read the specified number of bytes from the file starting at the specified absolute sector. * returns the number of bytes actually read. */ - typedef size_t (*rc_hash_cdreader_read_sector_handler)(void* track_handle, uint32_t sector, void* buffer, size_t requested_bytes); + typedef size_t (RC_CCONV *rc_hash_cdreader_read_sector_handler)(void* track_handle, uint32_t sector, void* buffer, size_t requested_bytes); /* closes the track handle */ - typedef void (*rc_hash_cdreader_close_track_handler)(void* track_handle); + typedef void (RC_CCONV *rc_hash_cdreader_close_track_handler)(void* track_handle); /* gets the absolute sector index for the first sector of a track */ - typedef uint32_t(*rc_hash_cdreader_first_track_sector_handler)(void* track_handle); + typedef uint32_t(RC_CCONV *rc_hash_cdreader_first_track_sector_handler)(void* track_handle); struct rc_hash_cdreader { @@ -121,14 +119,12 @@ extern "C" { rc_hash_cdreader_first_track_sector_handler first_track_sector; }; - void rc_hash_get_default_cdreader(struct rc_hash_cdreader* cdreader); - void rc_hash_init_default_cdreader(void); - void rc_hash_init_custom_cdreader(struct rc_hash_cdreader* reader); + RC_EXPORT void RC_CCONV rc_hash_get_default_cdreader(struct rc_hash_cdreader* cdreader); + RC_EXPORT void RC_CCONV rc_hash_init_default_cdreader(void); + RC_EXPORT void RC_CCONV rc_hash_init_custom_cdreader(struct rc_hash_cdreader* reader); /* ===================================================== */ -#ifdef __cplusplus -} -#endif +RC_END_C_DECLS #endif /* RC_HASH_H */ diff --git a/dep/rcheevos/include/rc_runtime.h b/dep/rcheevos/include/rc_runtime.h index 2804cc97d..c5780c47a 100644 --- a/dep/rcheevos/include/rc_runtime.h +++ b/dep/rcheevos/include/rc_runtime.h @@ -1,15 +1,13 @@ #ifndef RC_RUNTIME_H #define RC_RUNTIME_H -#ifdef __cplusplus -extern "C" { -#endif - #include "rc_error.h" #include #include +RC_BEGIN_C_DECLS + /*****************************************************************************\ | Forward Declarations (defined in rc_runtime_types.h) | \*****************************************************************************/ @@ -35,7 +33,7 @@ typedef struct rc_value_t rc_value_t; * num_bytes is greater than 1, the value is read in little-endian from * memory. */ -typedef uint32_t(*rc_runtime_peek_t)(uint32_t address, uint32_t num_bytes, void* ud); +typedef uint32_t(RC_CCONV *rc_runtime_peek_t)(uint32_t address, uint32_t num_bytes, void* ud); /*****************************************************************************\ | Runtime | @@ -94,24 +92,24 @@ typedef struct rc_runtime_t { } rc_runtime_t; -rc_runtime_t* rc_runtime_alloc(void); -void rc_runtime_init(rc_runtime_t* runtime); -void rc_runtime_destroy(rc_runtime_t* runtime); +RC_EXPORT rc_runtime_t* RC_CCONV rc_runtime_alloc(void); +RC_EXPORT void RC_CCONV rc_runtime_init(rc_runtime_t* runtime); +RC_EXPORT void RC_CCONV rc_runtime_destroy(rc_runtime_t* runtime); -int rc_runtime_activate_achievement(rc_runtime_t* runtime, uint32_t id, const char* memaddr, lua_State* L, int funcs_idx); -void rc_runtime_deactivate_achievement(rc_runtime_t* runtime, uint32_t id); -rc_trigger_t* rc_runtime_get_achievement(const rc_runtime_t* runtime, uint32_t id); -int rc_runtime_get_achievement_measured(const rc_runtime_t* runtime, uint32_t id, unsigned* measured_value, unsigned* measured_target); -int rc_runtime_format_achievement_measured(const rc_runtime_t* runtime, uint32_t id, char *buffer, size_t buffer_size); +RC_EXPORT int RC_CCONV rc_runtime_activate_achievement(rc_runtime_t* runtime, uint32_t id, const char* memaddr, lua_State* L, int funcs_idx); +RC_EXPORT void RC_CCONV rc_runtime_deactivate_achievement(rc_runtime_t* runtime, uint32_t id); +RC_EXPORT rc_trigger_t* RC_CCONV rc_runtime_get_achievement(const rc_runtime_t* runtime, uint32_t id); +RC_EXPORT int RC_CCONV rc_runtime_get_achievement_measured(const rc_runtime_t* runtime, uint32_t id, unsigned* measured_value, unsigned* measured_target); +RC_EXPORT int RC_CCONV rc_runtime_format_achievement_measured(const rc_runtime_t* runtime, uint32_t id, char *buffer, size_t buffer_size); -int rc_runtime_activate_lboard(rc_runtime_t* runtime, uint32_t id, const char* memaddr, lua_State* L, int funcs_idx); -void rc_runtime_deactivate_lboard(rc_runtime_t* runtime, uint32_t id); -rc_lboard_t* rc_runtime_get_lboard(const rc_runtime_t* runtime, uint32_t id); -int rc_runtime_format_lboard_value(char* buffer, int size, int32_t value, int format); +RC_EXPORT int RC_CCONV rc_runtime_activate_lboard(rc_runtime_t* runtime, uint32_t id, const char* memaddr, lua_State* L, int funcs_idx); +RC_EXPORT void RC_CCONV rc_runtime_deactivate_lboard(rc_runtime_t* runtime, uint32_t id); +RC_EXPORT rc_lboard_t* RC_CCONV rc_runtime_get_lboard(const rc_runtime_t* runtime, uint32_t id); +RC_EXPORT int RC_CCONV rc_runtime_format_lboard_value(char* buffer, int size, int32_t value, int format); -int rc_runtime_activate_richpresence(rc_runtime_t* runtime, const char* script, lua_State* L, int funcs_idx); -int rc_runtime_get_richpresence(const rc_runtime_t* runtime, char* buffer, size_t buffersize, rc_runtime_peek_t peek, void* peek_ud, lua_State* L); +RC_EXPORT int RC_CCONV rc_runtime_activate_richpresence(rc_runtime_t* runtime, const char* script, lua_State* L, int funcs_idx); +RC_EXPORT int RC_CCONV rc_runtime_get_richpresence(const rc_runtime_t* runtime, char* buffer, size_t buffersize, rc_runtime_peek_t peek, void* peek_ud, lua_State* L); enum { RC_RUNTIME_EVENT_ACHIEVEMENT_ACTIVATED, /* from WAITING, PAUSED, or PRIMED to ACTIVE */ @@ -136,21 +134,19 @@ typedef struct rc_runtime_event_t { } rc_runtime_event_t; -typedef void (*rc_runtime_event_handler_t)(const rc_runtime_event_t* runtime_event); +typedef void (RC_CCONV *rc_runtime_event_handler_t)(const rc_runtime_event_t* runtime_event); -void rc_runtime_do_frame(rc_runtime_t* runtime, rc_runtime_event_handler_t event_handler, rc_runtime_peek_t peek, void* ud, lua_State* L); -void rc_runtime_reset(rc_runtime_t* runtime); +RC_EXPORT void RC_CCONV rc_runtime_do_frame(rc_runtime_t* runtime, rc_runtime_event_handler_t event_handler, rc_runtime_peek_t peek, void* ud, lua_State* L); +RC_EXPORT void RC_CCONV rc_runtime_reset(rc_runtime_t* runtime); -typedef int (*rc_runtime_validate_address_t)(uint32_t address); -void rc_runtime_validate_addresses(rc_runtime_t* runtime, rc_runtime_event_handler_t event_handler, rc_runtime_validate_address_t validate_handler); -void rc_runtime_invalidate_address(rc_runtime_t* runtime, uint32_t address); +typedef int (RC_CCONV *rc_runtime_validate_address_t)(uint32_t address); +RC_EXPORT void RC_CCONV rc_runtime_validate_addresses(rc_runtime_t* runtime, rc_runtime_event_handler_t event_handler, rc_runtime_validate_address_t validate_handler); +RC_EXPORT void RC_CCONV rc_runtime_invalidate_address(rc_runtime_t* runtime, uint32_t address); -int rc_runtime_progress_size(const rc_runtime_t* runtime, lua_State* L); -int rc_runtime_serialize_progress(void* buffer, const rc_runtime_t* runtime, lua_State* L); -int rc_runtime_deserialize_progress(rc_runtime_t* runtime, const uint8_t* serialized, lua_State* L); +RC_EXPORT int RC_CCONV rc_runtime_progress_size(const rc_runtime_t* runtime, lua_State* L); +RC_EXPORT int RC_CCONV rc_runtime_serialize_progress(void* buffer, const rc_runtime_t* runtime, lua_State* L); +RC_EXPORT int RC_CCONV rc_runtime_deserialize_progress(rc_runtime_t* runtime, const uint8_t* serialized, lua_State* L); -#ifdef __cplusplus -} -#endif +RC_END_C_DECLS #endif /* RC_RUNTIME_H */ diff --git a/dep/rcheevos/include/rc_runtime_types.h b/dep/rcheevos/include/rc_runtime_types.h index 04a0c931c..d8a7db65d 100644 --- a/dep/rcheevos/include/rc_runtime_types.h +++ b/dep/rcheevos/include/rc_runtime_types.h @@ -1,15 +1,13 @@ #ifndef RC_RUNTIME_TYPES_H #define RC_RUNTIME_TYPES_H -#ifdef __cplusplus -extern "C" { -#endif - #include "rc_error.h" #include #include +RC_BEGIN_C_DECLS + #ifndef RC_RUNTIME_H /* prevents pedantic redefiniton error */ typedef struct lua_State lua_State; @@ -31,7 +29,7 @@ typedef struct rc_value_t rc_value_t; * num_bytes is greater than 1, the value is read in little-endian from * memory. */ -typedef uint32_t(*rc_peek_t)(uint32_t address, uint32_t num_bytes, void* ud); +typedef uint32_t(RC_CCONV *rc_peek_t)(uint32_t address, uint32_t num_bytes, void* ud); /*****************************************************************************\ | Memory References | @@ -132,7 +130,7 @@ typedef struct rc_operand_t { } rc_operand_t; -int rc_operand_is_memref(const rc_operand_t* operand); +RC_EXPORT int RC_CCONV rc_operand_is_memref(const rc_operand_t* operand); /*****************************************************************************\ | Conditions | @@ -276,11 +274,11 @@ struct rc_trigger_t { uint8_t measured_as_percent; }; -int rc_trigger_size(const char* memaddr); -rc_trigger_t* rc_parse_trigger(void* buffer, const char* memaddr, lua_State* L, int funcs_ndx); -int rc_evaluate_trigger(rc_trigger_t* trigger, rc_peek_t peek, void* ud, lua_State* L); -int rc_test_trigger(rc_trigger_t* trigger, rc_peek_t peek, void* ud, lua_State* L); -void rc_reset_trigger(rc_trigger_t* self); +RC_EXPORT int RC_CCONV rc_trigger_size(const char* memaddr); +RC_EXPORT rc_trigger_t* RC_CCONV rc_parse_trigger(void* buffer, const char* memaddr, lua_State* L, int funcs_ndx); +RC_EXPORT int RC_CCONV rc_evaluate_trigger(rc_trigger_t* trigger, rc_peek_t peek, void* ud, lua_State* L); +RC_EXPORT int RC_CCONV rc_test_trigger(rc_trigger_t* trigger, rc_peek_t peek, void* ud, lua_State* L); +RC_EXPORT void RC_CCONV rc_reset_trigger(rc_trigger_t* self); /*****************************************************************************\ | Values | @@ -303,9 +301,9 @@ struct rc_value_t { rc_value_t* next; }; -int rc_value_size(const char* memaddr); -rc_value_t* rc_parse_value(void* buffer, const char* memaddr, lua_State* L, int funcs_ndx); -int32_t rc_evaluate_value(rc_value_t* value, rc_peek_t peek, void* ud, lua_State* L); +RC_EXPORT int RC_CCONV rc_value_size(const char* memaddr); +RC_EXPORT rc_value_t* RC_CCONV rc_parse_value(void* buffer, const char* memaddr, lua_State* L, int funcs_ndx); +RC_EXPORT int32_t RC_CCONV rc_evaluate_value(rc_value_t* value, rc_peek_t peek, void* ud, lua_State* L); /*****************************************************************************\ | Leaderboards | @@ -333,10 +331,10 @@ struct rc_lboard_t { uint8_t state; }; -int rc_lboard_size(const char* memaddr); -rc_lboard_t* rc_parse_lboard(void* buffer, const char* memaddr, lua_State* L, int funcs_ndx); -int rc_evaluate_lboard(rc_lboard_t* lboard, int32_t* value, rc_peek_t peek, void* peek_ud, lua_State* L); -void rc_reset_lboard(rc_lboard_t* lboard); +RC_EXPORT int RC_CCONV rc_lboard_size(const char* memaddr); +RC_EXPORT rc_lboard_t* RC_CCONV rc_parse_lboard(void* buffer, const char* memaddr, lua_State* L, int funcs_ndx); +RC_EXPORT int RC_CCONV rc_evaluate_lboard(rc_lboard_t* lboard, int32_t* value, rc_peek_t peek, void* peek_ud, lua_State* L); +RC_EXPORT void RC_CCONV rc_reset_lboard(rc_lboard_t* lboard); /*****************************************************************************\ | Value formatting | @@ -356,11 +354,18 @@ enum { RC_FORMAT_FLOAT3, RC_FORMAT_FLOAT4, RC_FORMAT_FLOAT5, - RC_FORMAT_FLOAT6 + RC_FORMAT_FLOAT6, + RC_FORMAT_FIXED1, + RC_FORMAT_FIXED2, + RC_FORMAT_FIXED3, + RC_FORMAT_TENS, + RC_FORMAT_HUNDREDS, + RC_FORMAT_THOUSANDS, + RC_FORMAT_UNSIGNED_VALUE }; -int rc_parse_format(const char* format_str); -int rc_format_value(char* buffer, int size, int32_t value, int format); +RC_EXPORT int RC_CCONV rc_parse_format(const char* format_str); +RC_EXPORT int RC_CCONV rc_format_value(char* buffer, int size, int32_t value, int format); /*****************************************************************************\ | Rich Presence | @@ -411,16 +416,14 @@ struct rc_richpresence_t { rc_value_t* variables; }; -int rc_richpresence_size(const char* script); -int rc_richpresence_size_lines(const char* script, int* lines_read); -rc_richpresence_t* rc_parse_richpresence(void* buffer, const char* script, lua_State* L, int funcs_ndx); -int rc_evaluate_richpresence(rc_richpresence_t* richpresence, char* buffer, size_t buffersize, rc_peek_t peek, void* peek_ud, lua_State* L); -void rc_update_richpresence(rc_richpresence_t* richpresence, rc_peek_t peek, void* peek_ud, lua_State* L); -int rc_get_richpresence_display_string(rc_richpresence_t* richpresence, char* buffer, size_t buffersize, rc_peek_t peek, void* peek_ud, lua_State* L); -void rc_reset_richpresence(rc_richpresence_t* self); +RC_EXPORT int RC_CCONV rc_richpresence_size(const char* script); +RC_EXPORT int RC_CCONV rc_richpresence_size_lines(const char* script, int* lines_read); +RC_EXPORT rc_richpresence_t* RC_CCONV rc_parse_richpresence(void* buffer, const char* script, lua_State* L, int funcs_ndx); +RC_EXPORT int RC_CCONV rc_evaluate_richpresence(rc_richpresence_t* richpresence, char* buffer, size_t buffersize, rc_peek_t peek, void* peek_ud, lua_State* L); +RC_EXPORT void RC_CCONV rc_update_richpresence(rc_richpresence_t* richpresence, rc_peek_t peek, void* peek_ud, lua_State* L); +RC_EXPORT int RC_CCONV rc_get_richpresence_display_string(rc_richpresence_t* richpresence, char* buffer, size_t buffersize, rc_peek_t peek, void* peek_ud, lua_State* L); +RC_EXPORT void RC_CCONV rc_reset_richpresence(rc_richpresence_t* self); -#ifdef __cplusplus -} -#endif +RC_END_C_DECLS #endif /* RC_RUNTIME_TYPES_H */ diff --git a/dep/rcheevos/include/rc_url.h b/dep/rcheevos/include/rc_url.h index b61cd808c..e3f06d698 100644 --- a/dep/rcheevos/include/rc_url.h +++ b/dep/rcheevos/include/rc_url.h @@ -1,38 +1,36 @@ #ifndef RC_URL_H #define RC_URL_H +#include "rc_export.h" + #include -#ifdef __cplusplus -extern "C" { -#endif +RC_BEGIN_C_DECLS -int rc_url_award_cheevo(char* buffer, size_t size, const char* user_name, const char* login_token, unsigned cheevo_id, int hardcore, const char* game_hash); +RC_EXPORT int RC_CCONV rc_url_award_cheevo(char* buffer, size_t size, const char* user_name, const char* login_token, unsigned cheevo_id, int hardcore, const char* game_hash); -int rc_url_submit_lboard(char* buffer, size_t size, const char* user_name, const char* login_token, unsigned lboard_id, int value); +RC_EXPORT int RC_CCONV rc_url_submit_lboard(char* buffer, size_t size, const char* user_name, const char* login_token, unsigned lboard_id, int value); -int rc_url_get_lboard_entries(char* buffer, size_t size, unsigned lboard_id, unsigned first_index, unsigned count); -int rc_url_get_lboard_entries_near_user(char* buffer, size_t size, unsigned lboard_id, const char* user_name, unsigned count); +RC_EXPORT int RC_CCONV rc_url_get_lboard_entries(char* buffer, size_t size, unsigned lboard_id, unsigned first_index, unsigned count); +RC_EXPORT int RC_CCONV rc_url_get_lboard_entries_near_user(char* buffer, size_t size, unsigned lboard_id, const char* user_name, unsigned count); -int rc_url_get_gameid(char* buffer, size_t size, const char* hash); +RC_EXPORT int RC_CCONV rc_url_get_gameid(char* buffer, size_t size, const char* hash); -int rc_url_get_patch(char* buffer, size_t size, const char* user_name, const char* login_token, unsigned gameid); +RC_EXPORT int RC_CCONV rc_url_get_patch(char* buffer, size_t size, const char* user_name, const char* login_token, unsigned gameid); -int rc_url_get_badge_image(char* buffer, size_t size, const char* badge_name); +RC_EXPORT int RC_CCONV rc_url_get_badge_image(char* buffer, size_t size, const char* badge_name); -int rc_url_login_with_password(char* buffer, size_t size, const char* user_name, const char* password); +RC_EXPORT int RC_CCONV rc_url_login_with_password(char* buffer, size_t size, const char* user_name, const char* password); -int rc_url_login_with_token(char* buffer, size_t size, const char* user_name, const char* login_token); +RC_EXPORT int RC_CCONV rc_url_login_with_token(char* buffer, size_t size, const char* user_name, const char* login_token); -int rc_url_get_unlock_list(char* buffer, size_t size, const char* user_name, const char* login_token, unsigned gameid, int hardcore); +RC_EXPORT int RC_CCONV rc_url_get_unlock_list(char* buffer, size_t size, const char* user_name, const char* login_token, unsigned gameid, int hardcore); -int rc_url_post_playing(char* buffer, size_t size, const char* user_name, const char* login_token, unsigned gameid); +RC_EXPORT int RC_CCONV rc_url_post_playing(char* buffer, size_t size, const char* user_name, const char* login_token, unsigned gameid); -int rc_url_ping(char* url_buffer, size_t url_buffer_size, char* post_buffer, size_t post_buffer_size, - const char* user_name, const char* login_token, unsigned gameid, const char* rich_presence); +RC_EXPORT int RC_CCONV rc_url_ping(char* url_buffer, size_t url_buffer_size, char* post_buffer, size_t post_buffer_size, + const char* user_name, const char* login_token, unsigned gameid, const char* rich_presence); -#ifdef __cplusplus -} -#endif +RC_END_C_DECLS #endif /* RC_URL_H */ diff --git a/dep/rcheevos/src/rapi/rc_api_common.c b/dep/rcheevos/src/rapi/rc_api_common.c index 96c32b32e..5835b2801 100644 --- a/dep/rcheevos/src/rapi/rc_api_common.c +++ b/dep/rcheevos/src/rapi/rc_api_common.c @@ -475,13 +475,13 @@ int rc_json_get_required_array(uint32_t* num_entries, rc_json_field_t* array_fie return 0; #endif - if (!rc_json_get_optional_array(num_entries, array_field, response, field, field_name)) + if (!rc_json_get_optional_array(num_entries, array_field, field, field_name)) return rc_json_missing_field(response, field); return 1; } -int rc_json_get_optional_array(uint32_t* num_entries, rc_json_field_t* array_field, rc_api_response_t* response, const rc_json_field_t* field, const char* field_name) { +int rc_json_get_optional_array(uint32_t* num_entries, rc_json_field_t* array_field, const rc_json_field_t* field, const char* field_name) { #ifndef NDEBUG if (strcmp(field->name, field_name) != 0) return 0; @@ -783,6 +783,52 @@ int rc_json_get_required_unum(uint32_t* out, rc_api_response_t* response, const return rc_json_missing_field(response, field); } +int rc_json_get_float(float* out, const rc_json_field_t* field, const char* field_name) { + int32_t whole, fraction, fraction_denominator; + const char* decimal = field->value_start; + + if (!decimal) { + *out = 0.0f; + return 0; + } + + if (!rc_json_get_num(&whole, field, field_name)) + return 0; + + while (decimal < field->value_end && *decimal != '.') + ++decimal; + + fraction = 0; + fraction_denominator = 1; + if (decimal) { + ++decimal; + while (decimal < field->value_end && *decimal >= '0' && *decimal <= '9') { + fraction *= 10; + fraction += *decimal - '0'; + fraction_denominator *= 10; + ++decimal; + } + } + + if (whole < 0) + fraction = -fraction; + + *out = (float)whole + ((float)fraction / (float)fraction_denominator); + return 1; +} + +void rc_json_get_optional_float(float* out, const rc_json_field_t* field, const char* field_name, float default_value) { + if (!rc_json_get_float(out, field, field_name)) + *out = default_value; +} + +int rc_json_get_required_float(float* out, rc_api_response_t* response, const rc_json_field_t* field, const char* field_name) { + if (rc_json_get_float(out, field, field_name)) + return 1; + + return rc_json_missing_field(response, field); +} + int rc_json_get_datetime(time_t* out, const rc_json_field_t* field, const char* field_name) { struct tm tm; diff --git a/dep/rcheevos/src/rapi/rc_api_common.h b/dep/rcheevos/src/rapi/rc_api_common.h index 9fbb8a23d..7311cfff5 100644 --- a/dep/rcheevos/src/rapi/rc_api_common.h +++ b/dep/rcheevos/src/rapi/rc_api_common.h @@ -6,9 +6,7 @@ #include #include -#ifdef __cplusplus -extern "C" { -#endif +RC_BEGIN_C_DECLS #define RC_CONTENT_TYPE_URLENCODED "application/x-www-form-urlencoded" @@ -47,16 +45,19 @@ int rc_json_parse_server_response(rc_api_response_t* response, const rc_api_serv int rc_json_get_string(const char** out, rc_buffer_t* buffer, const rc_json_field_t* field, const char* field_name); int rc_json_get_num(int32_t* out, const rc_json_field_t* field, const char* field_name); int rc_json_get_unum(uint32_t* out, const rc_json_field_t* field, const char* field_name); +int rc_json_get_float(float* out, const rc_json_field_t* field, const char* field_name); int rc_json_get_bool(int* out, const rc_json_field_t* field, const char* field_name); int rc_json_get_datetime(time_t* out, const rc_json_field_t* field, const char* field_name); void rc_json_get_optional_string(const char** out, rc_api_response_t* response, const rc_json_field_t* field, const char* field_name, const char* default_value); void rc_json_get_optional_num(int32_t* out, const rc_json_field_t* field, const char* field_name, int default_value); void rc_json_get_optional_unum(uint32_t* out, const rc_json_field_t* field, const char* field_name, uint32_t default_value); +void rc_json_get_optional_float(float* out, const rc_json_field_t* field, const char* field_name, float default_value); void rc_json_get_optional_bool(int* out, const rc_json_field_t* field, const char* field_name, int default_value); -int rc_json_get_optional_array(uint32_t* num_entries, rc_json_field_t* iterator, rc_api_response_t* response, const rc_json_field_t* field, const char* field_name); +int rc_json_get_optional_array(uint32_t* num_entries, rc_json_field_t* iterator, const rc_json_field_t* field, const char* field_name); int rc_json_get_required_string(const char** out, rc_api_response_t* response, const rc_json_field_t* field, const char* field_name); int rc_json_get_required_num(int32_t* out, rc_api_response_t* response, const rc_json_field_t* field, const char* field_name); int rc_json_get_required_unum(uint32_t* out, rc_api_response_t* response, const rc_json_field_t* field, const char* field_name); +int rc_json_get_required_float(float* out, rc_api_response_t* response, const rc_json_field_t* field, const char* field_name); int rc_json_get_required_bool(int* out, rc_api_response_t* response, const rc_json_field_t* field, const char* field_name); int rc_json_get_required_datetime(time_t* out, rc_api_response_t* response, const rc_json_field_t* field, const char* field_name); int rc_json_get_required_object(rc_json_field_t* fields, size_t field_count, rc_api_response_t* response, rc_json_field_t* field, const char* field_name); @@ -74,8 +75,6 @@ void rc_url_builder_append_str_param(rc_api_url_builder_t* builder, const char* void rc_api_url_build_dorequest_url(rc_api_request_t* request); int rc_api_url_build_dorequest(rc_api_url_builder_t* builder, const char* api, const char* username, const char* api_token); -#ifdef __cplusplus -} -#endif +RC_END_C_DECLS #endif /* RC_API_COMMON_H */ diff --git a/dep/rcheevos/src/rapi/rc_api_editor.c b/dep/rcheevos/src/rapi/rc_api_editor.c index 78724058f..8cf6369f1 100644 --- a/dep/rcheevos/src/rapi/rc_api_editor.c +++ b/dep/rcheevos/src/rapi/rc_api_editor.c @@ -1,5 +1,6 @@ #include "rc_api_editor.h" #include "rc_api_common.h" +#include "rc_api_runtime.h" #include "../rc_compat.h" #include "../rhash/md5.h" @@ -185,6 +186,15 @@ void rc_api_destroy_update_code_note_response(rc_api_update_code_note_response_t /* --- Update Achievement --- */ +static const char* rc_type_string(uint32_t type) { + switch (type) { + case RC_ACHIEVEMENT_TYPE_MISSABLE: return "missable"; + case RC_ACHIEVEMENT_TYPE_PROGRESSION: return "progression"; + case RC_ACHIEVEMENT_TYPE_WIN: return "win_condition"; + default: return ""; + } +} + int rc_api_init_update_achievement_request(rc_api_request_t* request, const rc_api_update_achievement_request_t* api_params) { rc_api_url_builder_t builder; char buffer[33]; @@ -216,6 +226,7 @@ int rc_api_init_update_achievement_request(rc_api_request_t* request, const rc_a rc_url_builder_append_unum_param(&builder, "f", api_params->category); if (api_params->badge) rc_url_builder_append_str_param(&builder, "b", api_params->badge); + rc_url_builder_append_str_param(&builder, "x", rc_type_string(api_params->type)); /* Evaluate the signature. */ md5_init(&md5); diff --git a/dep/rcheevos/src/rapi/rc_api_runtime.c b/dep/rcheevos/src/rapi/rc_api_runtime.c index 27aeac13d..4f3bc5b57 100644 --- a/dep/rcheevos/src/rapi/rc_api_runtime.c +++ b/dep/rcheevos/src/rapi/rc_api_runtime.c @@ -92,6 +92,20 @@ int rc_api_process_fetch_game_data_response(rc_api_fetch_game_data_response_t* r return rc_api_process_fetch_game_data_server_response(response, &response_obj); } +static int rc_parse_achievement_type(const char* type) +{ + if (strcmp(type, "missable") == 0) + return RC_ACHIEVEMENT_TYPE_MISSABLE; + + if (strcmp(type, "win_condition") == 0) + return RC_ACHIEVEMENT_TYPE_WIN; + + if (strcmp(type, "progression") == 0) + return RC_ACHIEVEMENT_TYPE_PROGRESSION; + + return RC_ACHIEVEMENT_TYPE_STANDARD; +} + int rc_api_process_fetch_game_data_server_response(rc_api_fetch_game_data_response_t* response, const rc_api_server_response_t* server_response) { rc_api_achievement_definition_t* achievement; rc_api_leaderboard_definition_t* leaderboard; @@ -120,10 +134,6 @@ int rc_api_process_fetch_game_data_server_response(rc_api_fetch_game_data_respon RC_JSON_NEW_FIELD("RichPresencePatch"), RC_JSON_NEW_FIELD("Achievements"), /* array */ RC_JSON_NEW_FIELD("Leaderboards") /* array */ - /* unused fields - RC_JSON_NEW_FIELD("ForumTopicID"), - RC_JSON_NEW_FIELD("Flags") - * unused fields */ }; rc_json_field_t achievement_fields[] = { @@ -136,7 +146,10 @@ int rc_api_process_fetch_game_data_server_response(rc_api_fetch_game_data_respon RC_JSON_NEW_FIELD("Author"), RC_JSON_NEW_FIELD("BadgeName"), RC_JSON_NEW_FIELD("Created"), - RC_JSON_NEW_FIELD("Modified") + RC_JSON_NEW_FIELD("Modified"), + RC_JSON_NEW_FIELD("Type"), + RC_JSON_NEW_FIELD("Rarity"), + RC_JSON_NEW_FIELD("RarityHardcore") }; rc_json_field_t leaderboard_fields[] = { @@ -247,6 +260,35 @@ int rc_api_process_fetch_game_data_server_response(rc_api_fetch_game_data_respon return RC_MISSING_VALUE; achievement->updated = (time_t)timet; + achievement->type = RC_ACHIEVEMENT_TYPE_STANDARD; + if (achievement_fields[10].value_end) { + len = achievement_fields[10].value_end - achievement_fields[10].value_start - 2; + if (len < sizeof(format) - 1) { + memcpy(format, achievement_fields[10].value_start + 1, len); + format[len] = '\0'; + achievement->type = rc_parse_achievement_type(format); + } + } + + /* legacy support : if title contains[m], change type to missable and remove[m] from title */ + if (memcmp(achievement->title, "[m]", 3) == 0) { + len = 3; + while (achievement->title[len] == ' ') + ++len; + achievement->title += len; + achievement->type = RC_ACHIEVEMENT_TYPE_MISSABLE; + } + else if (achievement_fields[1].value_end && memcmp(achievement_fields[1].value_end - 4, "[m]", 3) == 0) { + len = strlen(achievement->title) - 3; + while (achievement->title[len - 1] == ' ') + --len; + ((char*)achievement->title)[len] = '\0'; + achievement->type = RC_ACHIEVEMENT_TYPE_MISSABLE; + } + + rc_json_get_optional_float(&achievement->rarity, &achievement_fields[11], "Rarity", 100.0); + rc_json_get_optional_float(&achievement->rarity_hardcore, &achievement_fields[12], "RarityHardcore", 100.0); + ++achievement; } } @@ -318,6 +360,11 @@ int rc_api_init_ping_request(rc_api_request_t* request, const rc_api_ping_reques if (api_params->rich_presence && *api_params->rich_presence) rc_url_builder_append_str_param(&builder, "m", api_params->rich_presence); + if (api_params->game_hash && *api_params->game_hash) { + rc_url_builder_append_unum_param(&builder, "h", api_params->hardcore); + rc_url_builder_append_str_param(&builder, "x", api_params->game_hash); + } + request->post_data = rc_url_builder_finalize(&builder); request->content_type = RC_CONTENT_TYPE_URLENCODED; } diff --git a/dep/rcheevos/src/rapi/rc_api_user.c b/dep/rcheevos/src/rapi/rc_api_user.c index 0fa279c48..0349f4a58 100644 --- a/dep/rcheevos/src/rapi/rc_api_user.c +++ b/dep/rcheevos/src/rapi/rc_api_user.c @@ -94,7 +94,14 @@ int rc_api_init_start_session_request(rc_api_request_t* request, const rc_api_st rc_url_builder_init(&builder, &request->buffer, 48); if (rc_api_url_build_dorequest(&builder, "startsession", api_params->username, api_params->api_token)) { rc_url_builder_append_unum_param(&builder, "g", api_params->game_id); + + if (api_params->game_hash && *api_params->game_hash) { + rc_url_builder_append_unum_param(&builder, "h", api_params->hardcore); + rc_url_builder_append_str_param(&builder, "m", api_params->game_hash); + } + rc_url_builder_append_str_param(&builder, "l", RCHEEVOS_VERSION_STRING); + request->post_data = rc_url_builder_finalize(&builder); request->content_type = RC_CONTENT_TYPE_URLENCODED; } @@ -139,7 +146,7 @@ int rc_api_process_start_session_server_response(rc_api_start_session_response_t if (result != RC_OK || !response->response.succeeded) return result; - if (rc_json_get_optional_array(&response->num_unlocks, &array_field, &response->response, &fields[2], "Unlocks") && response->num_unlocks) { + if (rc_json_get_optional_array(&response->num_unlocks, &array_field, &fields[2], "Unlocks") && response->num_unlocks) { response->unlocks = (rc_api_unlock_entry_t*)rc_buffer_alloc(&response->response.buffer, response->num_unlocks * sizeof(rc_api_unlock_entry_t)); if (!response->unlocks) return RC_OUT_OF_MEMORY; @@ -160,7 +167,7 @@ int rc_api_process_start_session_server_response(rc_api_start_session_response_t } } - if (rc_json_get_optional_array(&response->num_hardcore_unlocks, &array_field, &response->response, &fields[3], "HardcoreUnlocks") && response->num_hardcore_unlocks) { + if (rc_json_get_optional_array(&response->num_hardcore_unlocks, &array_field, &fields[3], "HardcoreUnlocks") && response->num_hardcore_unlocks) { response->hardcore_unlocks = (rc_api_unlock_entry_t*)rc_buffer_alloc(&response->response.buffer, response->num_hardcore_unlocks * sizeof(rc_api_unlock_entry_t)); if (!response->hardcore_unlocks) return RC_OUT_OF_MEMORY; diff --git a/dep/rcheevos/src/rc_client.c b/dep/rcheevos/src/rc_client.c index b2a6463f2..0028f4132 100644 --- a/dep/rcheevos/src/rc_client.c +++ b/dep/rcheevos/src/rc_client.c @@ -23,6 +23,9 @@ #define RC_CLIENT_UNKNOWN_GAME_ID (uint32_t)-1 #define RC_CLIENT_RECENT_UNLOCK_DELAY_SECONDS (10 * 60) /* ten minutes */ +#define RC_MINIMUM_UNPAUSED_FRAMES 20 +#define RC_PAUSE_DECAY_MULTIPLIER 4 + enum { RC_CLIENT_ASYNC_NOT_ABORTED = 0, RC_CLIENT_ASYNC_ABORTED = 1, @@ -76,12 +79,15 @@ static void rc_client_raise_leaderboard_events(rc_client_t* client, rc_client_su static void rc_client_raise_pending_events(rc_client_t* client, rc_client_game_info_t* game); static void rc_client_reschedule_callback(rc_client_t* client, rc_client_scheduled_callback_data_t* callback, rc_clock_t when); static void rc_client_award_achievement_retry(rc_client_scheduled_callback_data_t* callback_data, rc_client_t* client, rc_clock_t now); +static int rc_client_is_award_achievement_pending(const rc_client_t* client, uint32_t achievement_id); static void rc_client_submit_leaderboard_entry_retry(rc_client_scheduled_callback_data_t* callback_data, rc_client_t* client, rc_clock_t now); /* ===== Construction/Destruction ===== */ static void rc_client_dummy_event_handler(const rc_client_event_t* event, rc_client_t* client) { + (void)event; + (void)client; } rc_client_t* rc_client_create(rc_client_read_memory_func_t read_memory_function, rc_client_server_call_t server_call_function) @@ -91,6 +97,7 @@ rc_client_t* rc_client_create(rc_client_read_memory_func_t read_memory_function, return NULL; client->state.hardcore = 1; + client->state.required_unpaused_frames = RC_MINIMUM_UNPAUSED_FRAMES; client->callbacks.read_memory = read_memory_function; client->callbacks.server_call = server_call_function; @@ -241,6 +248,8 @@ static rc_clock_t rc_client_clock_get_now_millisecs(const rc_client_t* client) { #if defined(CLOCK_MONOTONIC) struct timespec now; + (void)client; + if (clock_gettime(CLOCK_MONOTONIC, &now) < 0) return 0; @@ -250,6 +259,8 @@ static rc_clock_t rc_client_clock_get_now_millisecs(const rc_client_t* client) static LARGE_INTEGER freq; LARGE_INTEGER ticks; + (void)client; + /* Frequency is the number of ticks per second and is guaranteed to not change. */ if (!freq.QuadPart) { if (!QueryPerformanceFrequency(&freq)) @@ -265,6 +276,9 @@ static rc_clock_t rc_client_clock_get_now_millisecs(const rc_client_t* client) return (rc_clock_t)(ticks.QuadPart / freq.QuadPart); #else const clock_t clock_now = clock(); + + (void)client; + if (sizeof(clock_t) == 4) { static uint32_t clock_wraps = 0; static clock_t last_clock = 0; @@ -403,6 +417,8 @@ static const char* rc_client_server_error_message(int* result, int http_status_c return response->error_message; } + (void)http_status_code; + if (*result != RC_OK) return rc_error_str(*result); @@ -1342,7 +1358,7 @@ static void rc_client_deactivate_leaderboards(rc_client_game_info_t* game, rc_cl case RC_CLIENT_LEADERBOARD_STATE_TRACKING: rc_client_release_leaderboard_tracker(client->game, leaderboard); - /* fallthrough to default */ + /* fallthrough */ /* to default */ default: leaderboard->public_.state = RC_CLIENT_LEADERBOARD_STATE_INACTIVE; break; @@ -1533,6 +1549,8 @@ static void rc_client_begin_start_session(rc_client_load_state_t* load_state) start_session_params.username = client->user.username; start_session_params.api_token = client->user.token; start_session_params.game_id = load_state->hash->game_id; + start_session_params.game_hash = load_state->hash->hash; + start_session_params.hardcore = client->state.hardcore; result = rc_api_init_start_session_request(&start_session_request, &start_session_params); if (result != RC_OK) { @@ -1609,6 +1627,9 @@ static void rc_client_copy_achievements(rc_client_load_state_t* load_state, achievement->public_.points = read->points; achievement->public_.category = (read->category != RC_ACHIEVEMENT_CATEGORY_CORE) ? RC_CLIENT_ACHIEVEMENT_CATEGORY_UNOFFICIAL : RC_CLIENT_ACHIEVEMENT_CATEGORY_CORE; + achievement->public_.rarity = read->rarity; + achievement->public_.rarity_hardcore = read->rarity_hardcore; + achievement->public_.type = read->type; /* assert: mapping is 1:1 */ memaddr = read->definition; rc_runtime_checksum(memaddr, achievement->md5); @@ -1680,6 +1701,13 @@ uint8_t rc_client_map_leaderboard_format(int format) case RC_FORMAT_FLOAT4: case RC_FORMAT_FLOAT5: case RC_FORMAT_FLOAT6: + case RC_FORMAT_FIXED1: + case RC_FORMAT_FIXED2: + case RC_FORMAT_FIXED3: + case RC_FORMAT_TENS: + case RC_FORMAT_HUNDREDS: + case RC_FORMAT_THOUSANDS: + case RC_FORMAT_UNSIGNED_VALUE: default: return RC_CLIENT_LEADERBOARD_FORMAT_VALUE; } @@ -2731,7 +2759,14 @@ static void rc_client_update_achievement_display_information(rc_client_t* client if (achievement->public_.state == RC_CLIENT_ACHIEVEMENT_STATE_UNLOCKED) { /* achievement unlocked */ - new_bucket = RC_CLIENT_ACHIEVEMENT_BUCKET_UNLOCKED; + if (achievement->public_.unlock_time >= recent_unlock_time) { + new_bucket = RC_CLIENT_ACHIEVEMENT_BUCKET_RECENTLY_UNLOCKED; + } else { + new_bucket = RC_CLIENT_ACHIEVEMENT_BUCKET_UNLOCKED; + + if (client->state.disconnect && rc_client_is_award_achievement_pending(client, achievement->public_.id)) + new_bucket = RC_CLIENT_ACHIEVEMENT_BUCKET_UNSYNCED; + } } else { /* active achievement */ @@ -2772,9 +2807,6 @@ static void rc_client_update_achievement_display_information(rc_client_t* client } } - if (new_bucket == RC_CLIENT_ACHIEVEMENT_BUCKET_UNLOCKED && achievement->public_.unlock_time >= recent_unlock_time) - new_bucket = RC_CLIENT_ACHIEVEMENT_BUCKET_RECENTLY_UNLOCKED; - achievement->public_.bucket = new_bucket; } @@ -2788,6 +2820,7 @@ static const char* rc_client_get_achievement_bucket_label(uint8_t bucket_type) case RC_CLIENT_ACHIEVEMENT_BUCKET_RECENTLY_UNLOCKED: return "Recently Unlocked"; case RC_CLIENT_ACHIEVEMENT_BUCKET_ACTIVE_CHALLENGE: return "Active Challenges"; case RC_CLIENT_ACHIEVEMENT_BUCKET_ALMOST_THERE: return "Almost There"; + case RC_CLIENT_ACHIEVEMENT_BUCKET_UNSYNCED: return "Unlocks Not Synced to Server"; default: return "Unknown"; } } @@ -2845,6 +2878,7 @@ static uint8_t rc_client_map_bucket(uint8_t bucket, int grouping) if (grouping == RC_CLIENT_ACHIEVEMENT_LIST_GROUPING_LOCK_STATE) { switch (bucket) { case RC_CLIENT_ACHIEVEMENT_BUCKET_RECENTLY_UNLOCKED: + case RC_CLIENT_ACHIEVEMENT_BUCKET_UNSYNCED: return RC_CLIENT_ACHIEVEMENT_BUCKET_UNLOCKED; case RC_CLIENT_ACHIEVEMENT_BUCKET_ACTIVE_CHALLENGE: @@ -2869,7 +2903,7 @@ rc_client_achievement_list_t* rc_client_create_achievement_list(rc_client_t* cli rc_client_achievement_list_info_t* list; rc_client_subset_info_t* subset; const uint32_t list_size = RC_ALIGN(sizeof(*list)); - uint32_t bucket_counts[16]; + uint32_t bucket_counts[NUM_RC_CLIENT_ACHIEVEMENT_BUCKETS]; uint32_t num_buckets; uint32_t num_achievements; size_t buckets_size; @@ -2879,7 +2913,8 @@ rc_client_achievement_list_t* rc_client_create_achievement_list(rc_client_t* cli const uint8_t shared_bucket_order[] = { RC_CLIENT_ACHIEVEMENT_BUCKET_ACTIVE_CHALLENGE, RC_CLIENT_ACHIEVEMENT_BUCKET_RECENTLY_UNLOCKED, - RC_CLIENT_ACHIEVEMENT_BUCKET_ALMOST_THERE + RC_CLIENT_ACHIEVEMENT_BUCKET_ALMOST_THERE, + RC_CLIENT_ACHIEVEMENT_BUCKET_UNSYNCED, }; const uint8_t subset_bucket_order[] = { RC_CLIENT_ACHIEVEMENT_BUCKET_LOCKED, @@ -3158,6 +3193,24 @@ typedef struct rc_client_award_achievement_callback_data_t rc_client_scheduled_callback_data_t* scheduled_callback_data; } rc_client_award_achievement_callback_data_t; +static int rc_client_is_award_achievement_pending(const rc_client_t* client, uint32_t achievement_id) +{ + /* assume lock already held */ + rc_client_scheduled_callback_data_t* scheduled_callback = client->state.scheduled_callbacks; + for (; scheduled_callback; scheduled_callback = scheduled_callback->next) + { + if (scheduled_callback->callback == rc_client_award_achievement_retry) + { + rc_client_award_achievement_callback_data_t* ach_data = + (rc_client_award_achievement_callback_data_t*)scheduled_callback->data; + if (ach_data->id == achievement_id) + return 1; + } + } + + return 0; +} + static void rc_client_award_achievement_server_call(rc_client_award_achievement_callback_data_t* ach_data); static void rc_client_award_achievement_retry(rc_client_scheduled_callback_data_t* callback_data, rc_client_t* client, rc_clock_t now) @@ -3165,6 +3218,9 @@ static void rc_client_award_achievement_retry(rc_client_scheduled_callback_data_ rc_client_award_achievement_callback_data_t* ach_data = (rc_client_award_achievement_callback_data_t*)callback_data->data; + (void)client; + (void)now; + rc_client_award_achievement_server_call(ach_data); } @@ -3793,6 +3849,9 @@ static void rc_client_submit_leaderboard_entry_retry(rc_client_scheduled_callbac rc_client_submit_leaderboard_entry_callback_data_t* lboard_data = (rc_client_submit_leaderboard_entry_callback_data_t*)callback_data->data; + (void)client; + (void)now; + rc_client_submit_leaderboard_entry_server_call(lboard_data); } @@ -3995,7 +4054,7 @@ static void rc_client_subset_reset_leaderboards(rc_client_game_info_t* game, rc_ case RC_CLIENT_LEADERBOARD_STATE_TRACKING: rc_client_release_leaderboard_tracker(game, leaderboard); - /* fallthrough to default */ + /* fallthrough */ /* to default */ default: leaderboard->public_.state = RC_CLIENT_LEADERBOARD_STATE_ACTIVE; rc_reset_lboard(lboard); @@ -4224,6 +4283,8 @@ static void rc_client_ping(rc_client_scheduled_callback_data_t* callback_data, r api_params.api_token = client->user.token; api_params.game_id = client->game->public_.id; api_params.rich_presence = buffer; + api_params.game_hash = client->game->public_.hash; + api_params.hardcore = client->state.hardcore; result = rc_api_init_ping_request(&request, &api_params); if (result != RC_OK) { @@ -4545,6 +4606,9 @@ static void rc_client_progress_tracker_timer_elapsed(rc_client_scheduled_callbac rc_client_event_t client_event; memset(&client_event, 0, sizeof(client_event)); + (void)callback_data; + (void)now; + rc_mutex_lock(&client->state.mutex); if (client->game->progress_tracker.action == RC_CLIENT_PROGRESS_TRACKER_ACTION_NONE) { client->game->progress_tracker.hide_callback->when = 0; @@ -4892,6 +4956,24 @@ void rc_client_do_frame(rc_client_t* client) rc_client_raise_pending_events(client, client->game); } + /* we've processed a frame. if there's a pause delay in effect, process it */ + if (client->state.unpaused_frame_decay > 0) { + client->state.unpaused_frame_decay--; + + if (client->state.unpaused_frame_decay == 0 && + client->state.required_unpaused_frames > RC_MINIMUM_UNPAUSED_FRAMES) { + /* the full decay has elapsed and a penalty still exists. + * lower the penalty and reset the decay counter */ + client->state.required_unpaused_frames >>= 1; + + if (client->state.required_unpaused_frames <= RC_MINIMUM_UNPAUSED_FRAMES) + client->state.required_unpaused_frames = RC_MINIMUM_UNPAUSED_FRAMES; + + client->state.unpaused_frame_decay = + client->state.required_unpaused_frames * (RC_PAUSE_DECAY_MULTIPLIER - 1) - 1; + } + } + rc_client_idle(client); } @@ -5072,6 +5154,49 @@ void rc_client_reset(rc_client_t* client) rc_client_raise_pending_events(client, client->game); } +int rc_client_can_pause(rc_client_t* client, uint32_t* frames_remaining) +{ +#ifdef RC_CLIENT_SUPPORTS_EXTERNAL + if (client->state.external_client && client->state.external_client->can_pause) + return client->state.external_client->can_pause(frames_remaining); +#endif + + if (frames_remaining) + *frames_remaining = 0; + + /* pause is always allowed in softcore */ + if (!rc_client_get_hardcore_enabled(client)) + return 1; + + /* a full decay means we haven't processed any frames since the last time this was called. */ + if (client->state.unpaused_frame_decay == client->state.required_unpaused_frames * RC_PAUSE_DECAY_MULTIPLIER) + return 1; + + /* if less than RC_MINIMUM_UNPAUSED_FRAMES have been processed, don't allow the pause */ + if (client->state.unpaused_frame_decay > client->state.required_unpaused_frames * (RC_PAUSE_DECAY_MULTIPLIER - 1)) { + if (frames_remaining) { + *frames_remaining = client->state.unpaused_frame_decay - + client->state.required_unpaused_frames * (RC_PAUSE_DECAY_MULTIPLIER - 1); + } + return 0; + } + + /* we're going to allow the emulator to pause. calculate how many frames are needed before the next + * pause will be allowed. */ + + if (client->state.unpaused_frame_decay > 0) { + /* The user has paused within the decay window. Require a longer + * run of unpaused frames before allowing the next pause */ + if (client->state.required_unpaused_frames < 5 * 60) /* don't make delay longer then 5 seconds */ + client->state.required_unpaused_frames += RC_MINIMUM_UNPAUSED_FRAMES; + } + + /* require multiple unpaused_frames windows to decay the penalty */ + client->state.unpaused_frame_decay = client->state.required_unpaused_frames * RC_PAUSE_DECAY_MULTIPLIER; + + return 1; +} + size_t rc_client_progress_size(rc_client_t* client) { size_t result; @@ -5463,7 +5588,7 @@ void rc_client_set_host(const rc_client_t* client, const char* hostname) rc_api_set_host(hostname); #ifdef RC_CLIENT_SUPPORTS_EXTERNAL - if (client->state.external_client && client->state.external_client->set_host) + if (client && client->state.external_client && client->state.external_client->set_host) client->state.external_client->set_host(hostname); #endif } diff --git a/dep/rcheevos/src/rc_client_external.h b/dep/rcheevos/src/rc_client_external.h index 32258ff39..1d625421e 100644 --- a/dep/rcheevos/src/rc_client_external.h +++ b/dep/rcheevos/src/rc_client_external.h @@ -1,69 +1,68 @@ #ifndef RC_CLIENT_EXTERNAL_H #define RC_CLIENT_EXTERNAL_H -#ifdef __cplusplus -extern "C" { -#endif - #include "rc_client.h" +RC_BEGIN_C_DECLS + /* NOTE: any function that is passed a callback also needs to be passed a client instance to pass * to the callback, and the external interface has to capture both. */ -typedef void (*rc_client_external_enable_logging_func_t)(rc_client_t* client, int level, rc_client_message_callback_t callback); -typedef void (*rc_client_external_set_event_handler_func_t)(rc_client_t* client, rc_client_event_handler_t handler); -typedef void (*rc_client_external_set_read_memory_func_t)(rc_client_t* client, rc_client_read_memory_func_t handler); -typedef void (*rc_client_external_set_get_time_millisecs_func_t)(rc_client_t* client, rc_get_time_millisecs_func_t handler); +typedef void (RC_CCONV *rc_client_external_enable_logging_func_t)(rc_client_t* client, int level, rc_client_message_callback_t callback); +typedef void (RC_CCONV *rc_client_external_set_event_handler_func_t)(rc_client_t* client, rc_client_event_handler_t handler); +typedef void (RC_CCONV *rc_client_external_set_read_memory_func_t)(rc_client_t* client, rc_client_read_memory_func_t handler); +typedef void (RC_CCONV *rc_client_external_set_get_time_millisecs_func_t)(rc_client_t* client, rc_get_time_millisecs_func_t handler); +typedef int (RC_CCONV *rc_client_external_can_pause_func_t)(uint32_t* frames_remaining); -typedef void (*rc_client_external_set_int_func_t)(int value); -typedef int (*rc_client_external_get_int_func_t)(void); -typedef void (*rc_client_external_set_string_func_t)(const char* value); -typedef size_t (*rc_client_external_copy_string_func_t)(char buffer[], size_t buffer_size); -typedef void (*rc_client_external_action_func_t)(void); +typedef void (RC_CCONV *rc_client_external_set_int_func_t)(int value); +typedef int (RC_CCONV *rc_client_external_get_int_func_t)(void); +typedef void (RC_CCONV *rc_client_external_set_string_func_t)(const char* value); +typedef size_t (RC_CCONV *rc_client_external_copy_string_func_t)(char buffer[], size_t buffer_size); +typedef void (RC_CCONV *rc_client_external_action_func_t)(void); -typedef void (*rc_client_external_async_handle_func_t)(rc_client_async_handle_t* handle); +typedef void (RC_CCONV *rc_client_external_async_handle_func_t)(rc_client_async_handle_t* handle); -typedef rc_client_async_handle_t* (*rc_client_external_begin_login_func_t)(rc_client_t* client, +typedef rc_client_async_handle_t* (RC_CCONV *rc_client_external_begin_login_func_t)(rc_client_t* client, const char* username, const char* pass_token, rc_client_callback_t callback, void* callback_userdata); -typedef const rc_client_user_t* (*rc_client_external_get_user_info_func_t)(void); +typedef const rc_client_user_t* (RC_CCONV *rc_client_external_get_user_info_func_t)(void); -typedef rc_client_async_handle_t* (*rc_client_external_begin_identify_and_load_game_func_t)( +typedef rc_client_async_handle_t* (RC_CCONV *rc_client_external_begin_identify_and_load_game_func_t)( rc_client_t* client, uint32_t console_id, const char* file_path, const uint8_t* data, size_t data_size, rc_client_callback_t callback, void* callback_userdata); -typedef rc_client_async_handle_t* (*rc_client_external_begin_load_game_func_t)(rc_client_t* client, +typedef rc_client_async_handle_t* (RC_CCONV *rc_client_external_begin_load_game_func_t)(rc_client_t* client, const char* hash, rc_client_callback_t callback, void* callback_userdata); -typedef rc_client_async_handle_t* (*rc_client_external_begin_load_subset_t)(rc_client_t* client, +typedef rc_client_async_handle_t* (RC_CCONV *rc_client_external_begin_load_subset_t)(rc_client_t* client, uint32_t subset_id, rc_client_callback_t callback, void* callback_userdata); -typedef const rc_client_game_t* (*rc_client_external_get_game_info_func_t)(void); -typedef const rc_client_subset_t* (*rc_client_external_get_subset_info_func_t)(uint32_t subset_id); -typedef void (*rc_client_external_get_user_game_summary_func_t)(rc_client_user_game_summary_t* summary); -typedef rc_client_async_handle_t* (*rc_client_external_begin_change_media_func_t)(rc_client_t* client, const char* file_path, +typedef const rc_client_game_t* (RC_CCONV *rc_client_external_get_game_info_func_t)(void); +typedef const rc_client_subset_t* (RC_CCONV *rc_client_external_get_subset_info_func_t)(uint32_t subset_id); +typedef void (RC_CCONV *rc_client_external_get_user_game_summary_func_t)(rc_client_user_game_summary_t* summary); +typedef rc_client_async_handle_t* (RC_CCONV *rc_client_external_begin_change_media_func_t)(rc_client_t* client, const char* file_path, const uint8_t* data, size_t data_size, rc_client_callback_t callback, void* callback_userdata); /* NOTE: rc_client_external_create_achievement_list_func_t returns an internal wrapper structure which contains the public list * and a destructor function. */ struct rc_client_achievement_list_info_t; -typedef struct rc_client_achievement_list_info_t* (*rc_client_external_create_achievement_list_func_t)(int category, int grouping); -typedef const rc_client_achievement_t* (*rc_client_external_get_achievement_info_func_t)(uint32_t id); +typedef struct rc_client_achievement_list_info_t* (RC_CCONV *rc_client_external_create_achievement_list_func_t)(int category, int grouping); +typedef const rc_client_achievement_t* (RC_CCONV *rc_client_external_get_achievement_info_func_t)(uint32_t id); /* NOTE: rc_client_external_create_leaderboard_list_func_t returns an internal wrapper structure which contains the public list * and a destructor function. */ struct rc_client_leaderboard_list_info_t; -typedef struct rc_client_leaderboard_list_info_t* (*rc_client_external_create_leaderboard_list_func_t)(int grouping); -typedef const rc_client_leaderboard_t* (*rc_client_external_get_leaderboard_info_func_t)(uint32_t id); +typedef struct rc_client_leaderboard_list_info_t* (RC_CCONV *rc_client_external_create_leaderboard_list_func_t)(int grouping); +typedef const rc_client_leaderboard_t* (RC_CCONV *rc_client_external_get_leaderboard_info_func_t)(uint32_t id); /* NOTE: rc_client_external_begin_fetch_leaderboard_entries_func_t and rc_client_external_begin_fetch_leaderboard_entries_around_user_func_t * pass an internal wrapper structure around the list, which contains the public list and a destructor function. */ -typedef rc_client_async_handle_t* (*rc_client_external_begin_fetch_leaderboard_entries_func_t)(rc_client_t* client, +typedef rc_client_async_handle_t* (RC_CCONV *rc_client_external_begin_fetch_leaderboard_entries_func_t)(rc_client_t* client, uint32_t leaderboard_id, uint32_t first_entry, uint32_t count, rc_client_fetch_leaderboard_entries_callback_t callback, void* callback_userdata); -typedef rc_client_async_handle_t* (*rc_client_external_begin_fetch_leaderboard_entries_around_user_func_t)(rc_client_t* client, +typedef rc_client_async_handle_t* (RC_CCONV *rc_client_external_begin_fetch_leaderboard_entries_around_user_func_t)(rc_client_t* client, uint32_t leaderboard_id, uint32_t count, rc_client_fetch_leaderboard_entries_callback_t callback, void* callback_userdata); -typedef size_t (*rc_client_external_progress_size_func_t)(void); -typedef int (*rc_client_external_serialize_progress_func_t)(uint8_t* buffer); -typedef int (*rc_client_external_deserialize_progress_func_t)(const uint8_t* buffer); +typedef size_t (RC_CCONV *rc_client_external_progress_size_func_t)(void); +typedef int (RC_CCONV *rc_client_external_serialize_progress_func_t)(uint8_t* buffer); +typedef int (RC_CCONV *rc_client_external_deserialize_progress_func_t)(const uint8_t* buffer); typedef struct rc_client_external_t { @@ -116,6 +115,7 @@ typedef struct rc_client_external_t rc_client_external_action_func_t do_frame; rc_client_external_action_func_t idle; rc_client_external_get_int_func_t is_processing_required; + rc_client_external_can_pause_func_t can_pause; rc_client_external_action_func_t reset; rc_client_external_progress_size_func_t progress_size; @@ -126,8 +126,6 @@ typedef struct rc_client_external_t #define RC_CLIENT_EXTERNAL_VERSION 1 -#ifdef __cplusplus -} -#endif +RC_END_C_DECLS #endif /* RC_CLIENT_EXTERNAL_H */ diff --git a/dep/rcheevos/src/rc_client_internal.h b/dep/rcheevos/src/rc_client_internal.h index 9c5454770..509c56750 100644 --- a/dep/rcheevos/src/rc_client_internal.h +++ b/dep/rcheevos/src/rc_client_internal.h @@ -1,10 +1,6 @@ #ifndef RC_CLIENT_INTERNAL_H #define RC_CLIENT_INTERNAL_H -#ifdef __cplusplus -extern "C" { -#endif - #include "rc_client.h" #ifdef RC_CLIENT_SUPPORTS_RAINTEGRATION @@ -18,16 +14,18 @@ extern "C" { #include "rc_runtime.h" #include "rc_runtime_types.h" +RC_BEGIN_C_DECLS + /*****************************************************************************\ | Callbacks | \*****************************************************************************/ struct rc_api_fetch_game_data_response_t; -typedef void (*rc_client_post_process_game_data_response_t)(const rc_api_server_response_t* server_response, +typedef void (RC_CCONV *rc_client_post_process_game_data_response_t)(const rc_api_server_response_t* server_response, struct rc_api_fetch_game_data_response_t* game_data_response, rc_client_t* client, void* userdata); -typedef int (*rc_client_can_submit_achievement_unlock_t)(uint32_t achievement_id, rc_client_t* client); -typedef int (*rc_client_can_submit_leaderboard_entry_t)(uint32_t leaderboard_id, rc_client_t* client); -typedef int (*rc_client_rich_presence_override_t)(rc_client_t* client, char buffer[], size_t buffersize); +typedef int (RC_CCONV *rc_client_can_submit_achievement_unlock_t)(uint32_t achievement_id, rc_client_t* client); +typedef int (RC_CCONV *rc_client_can_submit_leaderboard_entry_t)(uint32_t leaderboard_id, rc_client_t* client); +typedef int (RC_CCONV *rc_client_rich_presence_override_t)(rc_client_t* client, char buffer[], size_t buffersize); typedef struct rc_client_callbacks_t { rc_client_read_memory_func_t read_memory; @@ -44,7 +42,7 @@ typedef struct rc_client_callbacks_t { } rc_client_callbacks_t; struct rc_client_scheduled_callback_data_t; -typedef void (*rc_client_scheduled_callback_t)(struct rc_client_scheduled_callback_data_t* callback_data, rc_client_t* client, rc_clock_t now); +typedef 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); typedef struct rc_client_scheduled_callback_data_t { @@ -92,7 +90,7 @@ typedef struct rc_client_achievement_info_t { } rc_client_achievement_info_t; struct rc_client_achievement_list_info_t; -typedef void (*rc_client_destroy_achievement_list_func_t)(struct rc_client_achievement_list_info_t* list); +typedef void (RC_CCONV *rc_client_destroy_achievement_list_func_t)(struct rc_client_achievement_list_info_t* list); typedef struct rc_client_achievement_list_info_t { rc_client_achievement_list_t public_; @@ -167,7 +165,7 @@ typedef struct rc_client_leaderboard_info_t { } rc_client_leaderboard_info_t; struct rc_client_leaderboard_list_info_t; -typedef void (*rc_client_destroy_leaderboard_list_func_t)(struct rc_client_leaderboard_list_info_t* list); +typedef void (RC_CCONV *rc_client_destroy_leaderboard_list_func_t)(struct rc_client_leaderboard_list_info_t* list); typedef struct rc_client_leaderboard_list_info_t { rc_client_leaderboard_list_t public_; @@ -175,7 +173,7 @@ typedef struct rc_client_leaderboard_list_info_t { } rc_client_leaderboard_list_info_t; struct rc_client_leaderboard_entry_list_info_t; -typedef void (*rc_client_destroy_leaderboard_entry_list_func_t)(struct rc_client_leaderboard_entry_list_info_t* list); +typedef void (RC_CCONV *rc_client_destroy_leaderboard_entry_list_func_t)(struct rc_client_leaderboard_entry_list_info_t* list); typedef struct rc_client_leaderboard_entry_list_info_t { rc_client_leaderboard_entry_list_t public_; @@ -317,6 +315,9 @@ typedef struct rc_client_state_t { rc_client_raintegration_t* raintegration; #endif + uint16_t unpaused_frame_decay; + uint16_t required_unpaused_frames; + uint8_t hardcore; uint8_t encore_mode; uint8_t spectator_mode; @@ -387,8 +388,6 @@ void rc_client_set_legacy_peek(rc_client_t* client, int method); void rc_client_release_leaderboard_tracker(rc_client_game_info_t* game, rc_client_leaderboard_info_t* leaderboard); -#ifdef __cplusplus -} -#endif +RC_END_C_DECLS #endif /* RC_CLIENT_INTERNAL_H */ diff --git a/dep/rcheevos/src/rc_client_raintegration.c b/dep/rcheevos/src/rc_client_raintegration.c index eac5218fb..efea7e449 100644 --- a/dep/rcheevos/src/rc_client_raintegration.c +++ b/dep/rcheevos/src/rc_client_raintegration.c @@ -65,13 +65,19 @@ static void rc_client_raintegration_load_dll(rc_client_t* client, memset(raintegration, 0, sizeof(*raintegration)); raintegration->hDLL = hDLL; - raintegration->get_version = (rc_client_raintegration_get_string_func)GetProcAddress(hDLL, "_RA_IntegrationVersion"); - raintegration->get_host_url = (rc_client_raintegration_get_string_func)GetProcAddress(hDLL, "_RA_HostUrl"); - raintegration->init_client = (rc_client_raintegration_init_client_func)GetProcAddress(hDLL, "_RA_InitClient"); - raintegration->init_client_offline = (rc_client_raintegration_init_client_func)GetProcAddress(hDLL, "_RA_InitOffline"); - raintegration->shutdown = (rc_client_raintegration_action_func)GetProcAddress(hDLL, "_RA_Shutdown"); + raintegration->get_version = (rc_client_raintegration_get_string_func_t)GetProcAddress(hDLL, "_RA_IntegrationVersion"); + raintegration->get_host_url = (rc_client_raintegration_get_string_func_t)GetProcAddress(hDLL, "_RA_HostUrl"); + raintegration->init_client = (rc_client_raintegration_init_client_func_t)GetProcAddress(hDLL, "_RA_InitClient"); + raintegration->init_client_offline = (rc_client_raintegration_init_client_func_t)GetProcAddress(hDLL, "_RA_InitOffline"); + raintegration->shutdown = (rc_client_raintegration_action_func_t)GetProcAddress(hDLL, "_RA_Shutdown"); - raintegration->get_external_client = (rc_client_raintegration_get_external_client)GetProcAddress(hDLL, "_Rcheevos_GetExternalClient"); + raintegration->update_main_window_handle = (rc_client_raintegration_hwnd_action_func_t)GetProcAddress(hDLL, "_RA_UpdateHWnd"); + + raintegration->get_external_client = (rc_client_raintegration_get_external_client_func_t)GetProcAddress(hDLL, "_Rcheevos_GetExternalClient"); + raintegration->get_menu = (rc_client_raintegration_get_menu_func_t)GetProcAddress(hDLL, "_Rcheevos_RAIntegrationGetMenu"); + raintegration->activate_menu_item = (rc_client_raintegration_activate_menuitem_func_t)GetProcAddress(hDLL, "_Rcheevos_ActivateRAIntegrationMenuItem"); + raintegration->set_write_memory_function = (rc_client_raintegration_set_write_memory_func_t)GetProcAddress(hDLL, "_Rcheevos_SetRAIntegrationWriteMemoryFunction"); + raintegration->set_event_handler = (rc_client_raintegration_set_event_handler_func_t)GetProcAddress(hDLL, "_Rcheevos_SetRAIntegrationEventHandler"); if (!raintegration->get_version || !raintegration->init_client || @@ -135,7 +141,7 @@ int rc_client_version_less(const char* left, const char* right) static void rc_client_init_raintegration(rc_client_t* client, rc_client_version_validation_callback_data_t* version_validation_callback_data) { - rc_client_raintegration_init_client_func init_func = client->state.raintegration->init_client; + rc_client_raintegration_init_client_func_t init_func = client->state.raintegration->init_client; if (client->state.raintegration->get_host_url) { const char* host_url = client->state.raintegration->get_host_url(); @@ -195,6 +201,8 @@ static void rc_client_init_raintegration(rc_client_t* client, /* attach the external client and call the callback */ client->state.external_client = external_client; + client->state.raintegration->bIsInited = 1; + version_validation_callback_data->callback(RC_OK, NULL, client, version_validation_callback_data->callback_userdata); } @@ -339,6 +347,127 @@ rc_client_async_handle_t* rc_client_begin_load_raintegration(rc_client_t* client return &callback_data->async_handle; } +void rc_client_raintegration_update_main_window_handle(rc_client_t* client, HWND main_window_handle) +{ + if (client && client->state.raintegration && + client->state.raintegration->bIsInited && + client->state.raintegration->update_main_window_handle) + { + client->state.raintegration->update_main_window_handle(main_window_handle); + } +} + +void rc_client_raintegration_set_write_memory_function(rc_client_t* client, rc_client_raintegration_write_memory_func_t handler) +{ + if (client && client->state.raintegration && client->state.raintegration->set_write_memory_function) + client->state.raintegration->set_write_memory_function(client, handler); +} + +void rc_client_raintegration_set_event_handler(rc_client_t* client, + rc_client_raintegration_event_handler_t handler) +{ + if (client && client->state.raintegration && client->state.raintegration->set_event_handler) + client->state.raintegration->set_event_handler(client, handler); +} + +const rc_client_raintegration_menu_t* rc_client_raintegration_get_menu(const rc_client_t* client) +{ + if (!client || !client->state.raintegration || + !client->state.raintegration->bIsInited || + !client->state.raintegration->get_menu) + { + return NULL; + } + + return client->state.raintegration->get_menu(); +} + +void rc_client_raintegration_rebuild_submenu(rc_client_t* client, HMENU hMenu) +{ + HMENU hPopupMenu = NULL; + const rc_client_raintegration_menu_t* menu; + + if (!client || !client->state.raintegration) + return; + + /* destroy the existing menu */ + if (client->state.raintegration->hPopupMenu) + DestroyMenu(client->state.raintegration->hPopupMenu); + + /* create the popup menu */ + hPopupMenu = CreatePopupMenu(); + + menu = rc_client_raintegration_get_menu(client); + if (menu && menu->num_items) + { + const rc_client_raintegration_menu_item_t* menuitem = menu->items; + const rc_client_raintegration_menu_item_t* stop = menu->items + menu->num_items; + + for (; menuitem < stop; ++menuitem) + { + if (menuitem->id == 0) + AppendMenuA(hPopupMenu, MF_SEPARATOR, 0U, NULL); + else + { + UINT flags = MF_STRING; + if (menuitem->checked) + flags |= MF_CHECKED; + if (!menuitem->enabled) + flags |= MF_DISABLED | MF_GRAYED; + + AppendMenuA(hPopupMenu, flags, menuitem->id, menuitem->label); + } + } + } + + /* add/update the item containing the popup menu */ + { + int nIndex = GetMenuItemCount(hMenu); + const char* menuText = "&RetroAchievements"; + char buffer[64]; + + UINT flags = MF_POPUP | MF_STRING; + if (!menu || !menu->num_items) + flags |= MF_DISABLED | MF_GRAYED; + + while (--nIndex >= 0) + { + if (GetMenuStringA(hMenu, nIndex, buffer, sizeof(buffer) - 1, MF_BYPOSITION)) + { + if (strcmp(buffer, menuText) == 0) + break; + } + } + + if (nIndex == -1) + AppendMenuA(hMenu, flags, (UINT_PTR)hPopupMenu, menuText); + else + ModifyMenuA(hMenu, nIndex, flags | MF_BYPOSITION, (UINT_PTR)hPopupMenu, menuText); + } + + client->state.raintegration->hPopupMenu = hPopupMenu; +} + +void rc_client_raintegration_update_menu_item(const rc_client_t* client, const rc_client_raintegration_menu_item_t* menuitem) +{ + if (client && client->state.raintegration && client->state.raintegration->hPopupMenu) + { + UINT flags = MF_STRING; + if (menuitem->checked) + flags |= MF_CHECKED; + + CheckMenuItem(client->state.raintegration->hPopupMenu, menuitem->id, flags | MF_BYCOMMAND); + } +} + +int rc_client_raintegration_activate_menu_item(const rc_client_t* client, uint32_t nMenuItemId) +{ + if (!client || !client->state.raintegration || !client->state.raintegration->activate_menu_item) + return 0; + + return client->state.raintegration->activate_menu_item(nMenuItemId); +} + void rc_client_unload_raintegration(rc_client_t* client) { HINSTANCE hDLL; @@ -348,17 +477,8 @@ void rc_client_unload_raintegration(rc_client_t* client) RC_CLIENT_LOG_INFO(client, "Unloading RA_Integration") - if (client->state.raintegration->shutdown) { -#ifdef __cplusplus - try { -#endif - client->state.raintegration->shutdown(); -#ifdef __cplusplus - } - catch (std::runtime_error&) { - } -#endif - } + if (client->state.raintegration->shutdown) + client->state.raintegration->shutdown(); rc_mutex_lock(&client->state.mutex); hDLL = client->state.raintegration->hDLL; diff --git a/dep/rcheevos/src/rc_client_raintegration_internal.h b/dep/rcheevos/src/rc_client_raintegration_internal.h index e2be7e8de..530d98e1a 100644 --- a/dep/rcheevos/src/rc_client_raintegration_internal.h +++ b/dep/rcheevos/src/rc_client_raintegration_internal.h @@ -1,10 +1,6 @@ #ifndef RC_CLIENT_RAINTEGRATION_INTERNAL_H #define RC_CLIENT_RAINTEGRATION_INTERNAL_H -#ifdef __cplusplus -extern "C" { -#endif - #include "rc_client_raintegration.h" #ifdef RC_CLIENT_SUPPORTS_RAINTEGRATION @@ -12,33 +8,45 @@ extern "C" { #include "rc_client_external.h" #include "rc_compat.h" -#ifndef CCONV - #define CCONV __cdecl -#endif +RC_BEGIN_C_DECLS -typedef void (CCONV* rc_client_raintegration_action_func)(void); -typedef const char* (CCONV* rc_client_raintegration_get_string_func)(void); -typedef int (CCONV* rc_client_raintegration_init_client_func)(HWND hMainWnd, const char* sClientName, const char* sClientVersion); -typedef int (CCONV* rc_client_raintegration_get_external_client)(rc_client_external_t* pClient, int nVersion); +/* RAIntegration follows the same calling convention as rcheevos */ + +typedef void (RC_CCONV* rc_client_raintegration_action_func_t)(void); +typedef const char* (RC_CCONV* rc_client_raintegration_get_string_func_t)(void); +typedef int (RC_CCONV* rc_client_raintegration_init_client_func_t)(HWND hMainWnd, const char* sClientName, const char* sClientVersion); +typedef int (RC_CCONV* rc_client_raintegration_get_external_client_func_t)(rc_client_external_t* pClient, int nVersion); +typedef void (RC_CCONV* rc_client_raintegration_hwnd_action_func_t)(HWND hWnd); +typedef const rc_client_raintegration_menu_t* (RC_CCONV* rc_client_raintegration_get_menu_func_t)(void); +typedef int (RC_CCONV* rc_client_raintegration_activate_menuitem_func_t)(uint32_t nMenuItemId); +typedef void (RC_CCONV* rc_client_raintegration_set_write_memory_func_t)(rc_client_t* pClient, rc_client_raintegration_write_memory_func_t handler); +typedef void (RC_CCONV* rc_client_raintegration_set_event_handler_func_t)(rc_client_t* pClient, rc_client_raintegration_event_handler_t handler); typedef struct rc_client_raintegration_t { HINSTANCE hDLL; + HMENU hPopupMenu; + uint8_t bIsInited; - rc_client_raintegration_get_string_func get_version; - rc_client_raintegration_get_string_func get_host_url; - rc_client_raintegration_init_client_func init_client; - rc_client_raintegration_init_client_func init_client_offline; - rc_client_raintegration_action_func shutdown; + rc_client_raintegration_get_string_func_t get_version; + rc_client_raintegration_get_string_func_t get_host_url; + rc_client_raintegration_init_client_func_t init_client; + rc_client_raintegration_init_client_func_t init_client_offline; + rc_client_raintegration_action_func_t shutdown; - rc_client_raintegration_get_external_client get_external_client; + rc_client_raintegration_hwnd_action_func_t update_main_window_handle; + + rc_client_raintegration_set_write_memory_func_t set_write_memory_function; + rc_client_raintegration_set_event_handler_func_t set_event_handler; + rc_client_raintegration_get_menu_func_t get_menu; + rc_client_raintegration_activate_menuitem_func_t activate_menu_item; + + rc_client_raintegration_get_external_client_func_t get_external_client; } rc_client_raintegration_t; +RC_END_C_DECLS + #endif /* RC_CLIENT_SUPPORTS_RAINTEGRATION */ -#ifdef __cplusplus -} -#endif - #endif /* RC_CLIENT_RAINTEGRATION_INTERNAL_H */ diff --git a/dep/rcheevos/src/rc_compat.h b/dep/rcheevos/src/rc_compat.h index e22f9b84e..2ef9ae0c5 100644 --- a/dep/rcheevos/src/rc_compat.h +++ b/dep/rcheevos/src/rc_compat.h @@ -1,14 +1,14 @@ #ifndef RC_COMPAT_H #define RC_COMPAT_H -#ifdef __cplusplus -extern "C" { -#endif +#include "rc_export.h" #include #include #include +RC_BEGIN_C_DECLS + #if defined(MINGW) || defined(__MINGW32__) || defined(__MINGW64__) /* MinGW redefinitions */ @@ -92,8 +92,6 @@ extern "C" { void rc_mutex_unlock(rc_mutex_t* mutex); #endif -#ifdef __cplusplus -} -#endif +RC_END_C_DECLS #endif /* RC_COMPAT_H */ diff --git a/dep/rcheevos/src/rc_libretro.c b/dep/rcheevos/src/rc_libretro.c index d07cce9eb..70bf06be1 100644 --- a/dep/rcheevos/src/rc_libretro.c +++ b/dep/rcheevos/src/rc_libretro.c @@ -622,7 +622,7 @@ static void rc_libretro_memory_init_from_unmapped_memory(rc_libretro_memory_regi } int rc_libretro_memory_init(rc_libretro_memory_regions_t* regions, const struct retro_memory_map* mmap, - rc_libretro_get_core_memory_info_func get_core_memory_info, int console_id) { + rc_libretro_get_core_memory_info_func get_core_memory_info, uint32_t console_id) { const rc_memory_regions_t* console_regions = rc_console_memory_regions(console_id); rc_libretro_memory_regions_t new_regions; int has_valid_region = 0; diff --git a/dep/rcheevos/src/rc_libretro.h b/dep/rcheevos/src/rc_libretro.h index ceb92983f..66ab9a352 100644 --- a/dep/rcheevos/src/rc_libretro.h +++ b/dep/rcheevos/src/rc_libretro.h @@ -1,9 +1,7 @@ #ifndef RC_LIBRETRO_H #define RC_LIBRETRO_H -#ifdef __cplusplus -extern "C" { -#endif +#include "rc_export.h" /* this file comes from the libretro repository, which is not an explicit submodule. * the integration must set up paths appropriately to find it. */ @@ -12,6 +10,8 @@ extern "C" { #include #include +RC_BEGIN_C_DECLS + /*****************************************************************************\ | Disallowed Settings | \*****************************************************************************/ @@ -22,17 +22,17 @@ typedef struct rc_disallowed_setting_t const char* value; } rc_disallowed_setting_t; -const rc_disallowed_setting_t* rc_libretro_get_disallowed_settings(const char* library_name); -int rc_libretro_is_setting_allowed(const rc_disallowed_setting_t* disallowed_settings, const char* setting, const char* value); -int rc_libretro_is_system_allowed(const char* library_name, uint32_t console_id); +RC_EXPORT const rc_disallowed_setting_t* RC_CCONV rc_libretro_get_disallowed_settings(const char* library_name); +RC_EXPORT int RC_CCONV rc_libretro_is_setting_allowed(const rc_disallowed_setting_t* disallowed_settings, const char* setting, const char* value); +RC_EXPORT int RC_CCONV rc_libretro_is_system_allowed(const char* library_name, uint32_t console_id); /*****************************************************************************\ | Memory Mapping | \*****************************************************************************/ /* specifies a function to call for verbose logging */ -typedef void (*rc_libretro_message_callback)(const char*); -void rc_libretro_init_verbose_message_callback(rc_libretro_message_callback callback); +typedef void (RC_CCONV *rc_libretro_message_callback)(const char*); +RC_EXPORT void RC_CCONV rc_libretro_init_verbose_message_callback(rc_libretro_message_callback callback); #define RC_LIBRETRO_MAX_MEMORY_REGIONS 32 typedef struct rc_libretro_memory_regions_t @@ -49,15 +49,15 @@ typedef struct rc_libretro_core_memory_info_t size_t size; } rc_libretro_core_memory_info_t; -typedef void (*rc_libretro_get_core_memory_info_func)(uint32_t id, rc_libretro_core_memory_info_t* info); +typedef void (RC_CCONV *rc_libretro_get_core_memory_info_func)(uint32_t id, rc_libretro_core_memory_info_t* info); -int rc_libretro_memory_init(rc_libretro_memory_regions_t* regions, const struct retro_memory_map* mmap, - rc_libretro_get_core_memory_info_func get_core_memory_info, int console_id); -void rc_libretro_memory_destroy(rc_libretro_memory_regions_t* regions); +RC_EXPORT int RC_CCONV rc_libretro_memory_init(rc_libretro_memory_regions_t* regions, const struct retro_memory_map* mmap, + rc_libretro_get_core_memory_info_func get_core_memory_info, uint32_t console_id); +RC_EXPORT void RC_CCONV rc_libretro_memory_destroy(rc_libretro_memory_regions_t* regions); -uint8_t* rc_libretro_memory_find(const rc_libretro_memory_regions_t* regions, uint32_t address); -uint8_t* rc_libretro_memory_find_avail(const rc_libretro_memory_regions_t* regions, uint32_t address, uint32_t* avail); -uint32_t rc_libretro_memory_read(const rc_libretro_memory_regions_t* regions, uint32_t address, uint8_t* buffer, uint32_t num_bytes); +RC_EXPORT uint8_t* RC_CCONV rc_libretro_memory_find(const rc_libretro_memory_regions_t* regions, uint32_t address); +RC_EXPORT uint8_t* RC_CCONV rc_libretro_memory_find_avail(const rc_libretro_memory_regions_t* regions, uint32_t address, uint32_t* avail); +RC_EXPORT uint32_t RC_CCONV rc_libretro_memory_read(const rc_libretro_memory_regions_t* regions, uint32_t address, uint8_t* buffer, uint32_t num_bytes); /*****************************************************************************\ | Disk Identification | @@ -77,19 +77,17 @@ typedef struct rc_libretro_hash_set_t uint16_t entries_size; } rc_libretro_hash_set_t; -typedef int (*rc_libretro_get_image_path_func)(uint32_t index, char* buffer, size_t buffer_size); +typedef int (RC_CCONV *rc_libretro_get_image_path_func)(uint32_t index, char* buffer, size_t buffer_size); -void rc_libretro_hash_set_init(struct rc_libretro_hash_set_t* hash_set, +RC_EXPORT void RC_CCONV rc_libretro_hash_set_init(struct rc_libretro_hash_set_t* hash_set, const char* m3u_path, rc_libretro_get_image_path_func get_image_path); -void rc_libretro_hash_set_destroy(struct rc_libretro_hash_set_t* hash_set); +RC_EXPORT void RC_CCONV rc_libretro_hash_set_destroy(struct rc_libretro_hash_set_t* hash_set); -void rc_libretro_hash_set_add(struct rc_libretro_hash_set_t* hash_set, - const char* path, uint32_t game_id, const char hash[33]); -const char* rc_libretro_hash_set_get_hash(const struct rc_libretro_hash_set_t* hash_set, const char* path); -int rc_libretro_hash_set_get_game_id(const struct rc_libretro_hash_set_t* hash_set, const char* hash); +RC_EXPORT void RC_CCONV rc_libretro_hash_set_add(struct rc_libretro_hash_set_t* hash_set, + const char* path, uint32_t game_id, const char hash[33]); +RC_EXPORT const char* RC_CCONV rc_libretro_hash_set_get_hash(const struct rc_libretro_hash_set_t* hash_set, const char* path); +RC_EXPORT int RC_CCONV rc_libretro_hash_set_get_game_id(const struct rc_libretro_hash_set_t* hash_set, const char* hash); -#ifdef __cplusplus -} -#endif +RC_END_C_DECLS #endif /* RC_LIBRETRO_H */ diff --git a/dep/rcheevos/src/rc_util.h b/dep/rcheevos/src/rc_util.h index 34f75da91..18d27e0fc 100644 --- a/dep/rcheevos/src/rc_util.h +++ b/dep/rcheevos/src/rc_util.h @@ -1,12 +1,12 @@ #ifndef RC_UTIL_H #define RC_UTIL_H +#include "rc_export.h" + #include #include -#ifdef __cplusplus -extern "C" { -#endif +RC_BEGIN_C_DECLS /** * A block of memory for variable length data (like strings and arrays). @@ -46,8 +46,6 @@ uint32_t rc_djb2(const char* input); void rc_format_md5(char checksum[33], const uint8_t digest[16]); -#ifdef __cplusplus -} -#endif +RC_END_C_DECLS #endif /* RC_UTIL_H */ diff --git a/dep/rcheevos/src/rc_version.c b/dep/rcheevos/src/rc_version.c new file mode 100644 index 000000000..a29d0a5f5 --- /dev/null +++ b/dep/rcheevos/src/rc_version.c @@ -0,0 +1,11 @@ +#include "rc_version.h" + +uint32_t rc_version(void) +{ + return RCHEEVOS_VERSION; +} + +const char* rc_version_string(void) +{ + return RCHEEVOS_VERSION_STRING; +} diff --git a/dep/rcheevos/src/rc_version.h b/dep/rcheevos/src/rc_version.h index 19be5671a..6aa57af6c 100644 --- a/dep/rcheevos/src/rc_version.h +++ b/dep/rcheevos/src/rc_version.h @@ -1,9 +1,11 @@ #ifndef RC_VERSION_H #define RC_VERSION_H -#ifdef __cplusplus -extern "C" { -#endif +#include "rc_export.h" + +#include + +RC_BEGIN_C_DECLS #define RCHEEVOS_VERSION_MAJOR 11 #define RCHEEVOS_VERSION_MINOR 0 @@ -22,8 +24,9 @@ extern "C" { #define RCHEEVOS_VERSION_STRING RCHEEVOS_MAKE_VERSION_STRING_SHORT(RCHEEVOS_VERSION_MAJOR, RCHEEVOS_VERSION_MINOR) #endif -#ifdef __cplusplus -} -#endif +RC_EXPORT uint32_t rc_version(void); +RC_EXPORT const char* rc_version_string(void); + +RC_END_C_DECLS #endif /* RC_VERSION_H */ diff --git a/dep/rcheevos/src/rcheevos/alloc.c b/dep/rcheevos/src/rcheevos/alloc.c index 7ac3a8f69..0aa4e5cb5 100644 --- a/dep/rcheevos/src/rcheevos/alloc.c +++ b/dep/rcheevos/src/rcheevos/alloc.c @@ -37,7 +37,7 @@ void* rc_alloc(void* pointer, int32_t* offset, uint32_t size, uint32_t alignment /* valid buffer, grab the next chunk */ ptr = (void*)((char*)pointer + *offset); } - else if (scratch != 0 && scratch_object_pointer_offset >= 0) { + else if (scratch != 0 && scratch_object_pointer_offset < sizeof(scratch->objs)) { /* only allocate one instance of each object type (indentified by scratch_object_pointer_offset) */ void** scratch_object_pointer = (void**)((char*)&scratch->objs + scratch_object_pointer_offset); ptr = *scratch_object_pointer; diff --git a/dep/rcheevos/src/rcheevos/condset.c b/dep/rcheevos/src/rcheevos/condset.c index 4c2e7ea37..23a0e30e1 100644 --- a/dep/rcheevos/src/rcheevos/condset.c +++ b/dep/rcheevos/src/rcheevos/condset.c @@ -60,7 +60,7 @@ rc_condset_t* rc_parse_condset(const char** memaddr, rc_parse_state_t* parse, in /* right hand side is not required when Measured is used in a value */ if (is_value) break; - /* fallthrough to default */ + /* fallthrough */ /* to default */ default: parse->offset = RC_INVALID_OPERATOR; diff --git a/dep/rcheevos/src/rcheevos/consoleinfo.c b/dep/rcheevos/src/rcheevos/consoleinfo.c index 985c42922..95eb406cf 100644 --- a/dep/rcheevos/src/rcheevos/consoleinfo.c +++ b/dep/rcheevos/src/rcheevos/consoleinfo.c @@ -2,7 +2,7 @@ #include -const char* rc_console_name(int console_id) +const char* rc_console_name(uint32_t console_id) { switch (console_id) { @@ -195,6 +195,9 @@ const char* rc_console_name(int console_id) case RC_CONSOLE_SHARPX1: return "Sharp X1"; + case RC_CONSOLE_STANDALONE: + return "Standalone"; + case RC_CONSOLE_SUPER_NINTENDO: return "Super Nintendo Entertainment System"; diff --git a/dep/rcheevos/src/rcheevos/format.c b/dep/rcheevos/src/rcheevos/format.c index c797faeb4..0aa44ee6a 100644 --- a/dep/rcheevos/src/rcheevos/format.c +++ b/dep/rcheevos/src/rcheevos/format.c @@ -14,6 +14,9 @@ int rc_parse_format(const char* format_str) { if (!strncmp(format_str, "LOAT", 4) && format_str[4] >= '1' && format_str[4] <= '6' && format_str[5] == '\0') { return RC_FORMAT_FLOAT1 + (format_str[4] - '1'); } + if (!strncmp(format_str, "IXED", 4) && format_str[4] >= '1' && format_str[4] <= '3' && format_str[5] == '\0') { + return RC_FORMAT_FIXED1 + (format_str[4] - '1'); + } break; @@ -24,6 +27,12 @@ int rc_parse_format(const char* format_str) { if (!strcmp(format_str, "IMESECS")) { return RC_FORMAT_SECONDS; } + if (!strcmp(format_str, "HOUSANDS")) { + return RC_FORMAT_THOUSANDS; + } + if (!strcmp(format_str, "ENS")) { + return RC_FORMAT_TENS; + } break; @@ -64,11 +73,25 @@ int rc_parse_format(const char* format_str) { break; + case 'U': + if (!strcmp(format_str, "NSIGNED")) { + return RC_FORMAT_UNSIGNED_VALUE; + } + + break; + case 'O': if (!strcmp(format_str, "THER")) { return RC_FORMAT_SCORE; } + break; + + case 'H': + if (!strcmp(format_str, "UNDREDS")) { + return RC_FORMAT_HUNDREDS; + } + break; } @@ -119,6 +142,22 @@ static int rc_format_value_centiseconds(char* buffer, size_t size, uint32_t cent return chars; } +static int rc_format_value_fixed(char* buffer, size_t size, const char* format, int32_t value, int32_t factor) +{ + if (value >= 0) + return snprintf(buffer, size, format, value / factor, value % factor); + + return snprintf(buffer, size, format, value / factor, (-value) % factor); +} + +static int rc_format_value_padded(char* buffer, size_t size, const char* format, int32_t value) +{ + if (value == 0) + return snprintf(buffer, size, "0"); + + return snprintf(buffer, size, format, value); +} + int rc_format_typed_value(char* buffer, size_t size, const rc_typed_value_t* value, int format) { int chars; rc_typed_value_t converted_value; @@ -192,6 +231,41 @@ int rc_format_typed_value(char* buffer, size_t size, const rc_typed_value_t* val rc_typed_value_convert(&converted_value, RC_VALUE_TYPE_FLOAT); chars = snprintf(buffer, size, "%.6f", converted_value.value.f32); break; + + case RC_FORMAT_FIXED1: + rc_typed_value_convert(&converted_value, RC_VALUE_TYPE_SIGNED); + chars = rc_format_value_fixed(buffer, size, "%d.%u", converted_value.value.i32, 10); + break; + + case RC_FORMAT_FIXED2: + rc_typed_value_convert(&converted_value, RC_VALUE_TYPE_SIGNED); + chars = rc_format_value_fixed(buffer, size, "%d.%02u", converted_value.value.i32, 100); + break; + + case RC_FORMAT_FIXED3: + rc_typed_value_convert(&converted_value, RC_VALUE_TYPE_SIGNED); + chars = rc_format_value_fixed(buffer, size, "%d.%03u", converted_value.value.i32, 1000); + break; + + case RC_FORMAT_TENS: + rc_typed_value_convert(&converted_value, RC_VALUE_TYPE_SIGNED); + chars = rc_format_value_padded(buffer, size, "%d0", converted_value.value.i32); + break; + + case RC_FORMAT_HUNDREDS: + rc_typed_value_convert(&converted_value, RC_VALUE_TYPE_SIGNED); + chars = rc_format_value_padded(buffer, size, "%d00", converted_value.value.i32); + break; + + case RC_FORMAT_THOUSANDS: + rc_typed_value_convert(&converted_value, RC_VALUE_TYPE_SIGNED); + chars = rc_format_value_padded(buffer, size, "%d000", converted_value.value.i32); + break; + + case RC_FORMAT_UNSIGNED_VALUE: + rc_typed_value_convert(&converted_value, RC_VALUE_TYPE_UNSIGNED); + chars = snprintf(buffer, size, "%u", converted_value.value.u32); + break; } return chars; diff --git a/dep/rcheevos/src/rcheevos/lboard.c b/dep/rcheevos/src/rcheevos/lboard.c index 0191336a2..98b4ec2f1 100644 --- a/dep/rcheevos/src/rcheevos/lboard.c +++ b/dep/rcheevos/src/rcheevos/lboard.c @@ -235,7 +235,7 @@ int rc_evaluate_lboard(rc_lboard_t* self, int32_t* value, rc_peek_t peek, void* *value = rc_evaluate_value(self->progress, peek, peek_ud, L); break; } - /* fallthrough to RC_LBOARD_STATE_TRIGGERED */ + /* fallthrough */ /* to RC_LBOARD_STATE_TRIGGERED */ case RC_LBOARD_STATE_TRIGGERED: *value = rc_evaluate_value(&self->value, peek, peek_ud, L); diff --git a/dep/rcheevos/src/rcheevos/operand.c b/dep/rcheevos/src/rcheevos/operand.c index d7e20908f..252258275 100644 --- a/dep/rcheevos/src/rcheevos/operand.c +++ b/dep/rcheevos/src/rcheevos/operand.c @@ -6,16 +6,12 @@ #ifndef RC_DISABLE_LUA -#ifdef __cplusplus -extern "C" { -#endif +RC_BEGIN_C_DECLS #include #include -#ifdef __cplusplus -} -#endif +RC_END_C_DECLS #endif /* RC_DISABLE_LUA */ @@ -238,7 +234,7 @@ int rc_parse_operand(rc_operand_t* self, const char** memaddr, uint8_t is_indire case '0': if (aux[1] == 'x' || aux[1] == 'X') { /* hex integer constant */ - /* fall through */ + /* fallthrough */ /* to default */ default: ret = rc_parse_operand_memory(self, &aux, parse, is_indirect); @@ -247,8 +243,7 @@ int rc_parse_operand(rc_operand_t* self, const char** memaddr, uint8_t is_indire break; } - - /* fall through for case '0' where not '0x' */ + /* fallthrough */ /* to case '1' for case '0' where not '0x' */ case '1': case '2': case '3': case '4': case '5': /* unsigned integer constant */ case '6': case '7': case '8': case '9': value = strtoul(aux, &end, 10); diff --git a/dep/rcheevos/src/rcheevos/rc_internal.h b/dep/rcheevos/src/rcheevos/rc_internal.h index 2623355bc..8dac46146 100644 --- a/dep/rcheevos/src/rcheevos/rc_internal.h +++ b/dep/rcheevos/src/rcheevos/rc_internal.h @@ -4,9 +4,7 @@ #include "rc_runtime_types.h" #include "../rc_util.h" -#ifdef __cplusplus -extern "C" { -#endif +RC_BEGIN_C_DECLS typedef struct rc_scratch_string { char* value; @@ -194,8 +192,6 @@ int rc_lboard_state_active(int state); void rc_parse_richpresence_internal(rc_richpresence_t* self, const char* script, rc_parse_state_t* parse); -#ifdef __cplusplus -} -#endif +RC_END_C_DECLS #endif /* RC_INTERNAL_H */ diff --git a/dep/rcheevos/src/rcheevos/rc_validate.c b/dep/rcheevos/src/rcheevos/rc_validate.c index e1e848df7..1dc6a8742 100644 --- a/dep/rcheevos/src/rcheevos/rc_validate.c +++ b/dep/rcheevos/src/rcheevos/rc_validate.c @@ -306,8 +306,7 @@ int rc_validate_condset_internal(const rc_condset_t* condset, char result[], con snprintf(result, result_size, "Condition %d: Hit target of 1 is redundant on ResetIf", index); return 0; } - /* fallthrough to default */ - + /* fallthrough */ /* to default */ default: if (in_add_hits) { if (cond->required_hits == 0) { diff --git a/dep/rcheevos/src/rcheevos/rc_validate.h b/dep/rcheevos/src/rcheevos/rc_validate.h index 08394b59b..09c90ab7f 100644 --- a/dep/rcheevos/src/rcheevos/rc_validate.h +++ b/dep/rcheevos/src/rcheevos/rc_validate.h @@ -5,9 +5,7 @@ #include -#ifdef __cplusplus -extern "C" { -#endif +RC_BEGIN_C_DECLS int rc_validate_memrefs(const rc_memref_t* memref, char result[], const size_t result_size, uint32_t max_address); @@ -19,8 +17,6 @@ int rc_validate_memrefs_for_console(const rc_memref_t* memref, char result[], co int rc_validate_condset_for_console(const rc_condset_t* condset, char result[], const size_t result_size, uint32_t console_id); int rc_validate_trigger_for_console(const rc_trigger_t* trigger, char result[], const size_t result_size, uint32_t console_id); -#ifdef __cplusplus -} -#endif +RC_END_C_DECLS #endif /* RC_VALIDATE_H */ diff --git a/dep/rcheevos/src/rcheevos/richpresence.c b/dep/rcheevos/src/rcheevos/richpresence.c index 31df33426..0dd660e68 100644 --- a/dep/rcheevos/src/rcheevos/richpresence.c +++ b/dep/rcheevos/src/rcheevos/richpresence.c @@ -189,6 +189,10 @@ static rc_richpresence_display_t* rc_parse_richpresence_display_internal(const c {"Float4", 6, RC_FORMAT_FLOAT4}, {"Float5", 6, RC_FORMAT_FLOAT5}, {"Float6", 6, RC_FORMAT_FLOAT6}, + {"Fixed1", 6, RC_FORMAT_FIXED1}, + {"Fixed2", 6, RC_FORMAT_FIXED2}, + {"Fixed3", 6, RC_FORMAT_FIXED3}, + {"Unsigned", 8, RC_FORMAT_UNSIGNED_VALUE} }; size_t i; diff --git a/dep/rcheevos/src/rcheevos/value.c b/dep/rcheevos/src/rcheevos/value.c index e7df82df9..3662fc364 100644 --- a/dep/rcheevos/src/rcheevos/value.c +++ b/dep/rcheevos/src/rcheevos/value.c @@ -447,7 +447,7 @@ void rc_typed_value_negate(rc_typed_value_t* value) { { case RC_VALUE_TYPE_UNSIGNED: rc_typed_value_convert(value, RC_VALUE_TYPE_SIGNED); - /* fallthrough to RC_VALUE_TYPE_SIGNED */ + /* fallthrough */ /* to RC_VALUE_TYPE_SIGNED */ case RC_VALUE_TYPE_SIGNED: value->value.i32 = -(value->value.i32); diff --git a/dep/rcheevos/src/rhash/hash.c b/dep/rcheevos/src/rhash/hash.c index 0cc5fb4e7..382076c20 100644 --- a/dep/rcheevos/src/rhash/hash.c +++ b/dep/rcheevos/src/rhash/hash.c @@ -7,6 +7,11 @@ #include #include +#if defined(_WIN32) +#define WIN32_LEAN_AND_MEAN +#include +#endif + /* arbitrary limit to prevent allocating and hashing large files */ #define MAX_BUFFER_SIZE 64 * 1024 * 1024 @@ -48,7 +53,35 @@ static struct rc_hash_filereader* filereader = NULL; static void* filereader_open(const char* path) { +#if defined(WINVER) && WINVER >= 0x0500 + /* Windows requires using wchar APIs for Unicode paths */ + /* Note that MultiByteToWideChar will only be defined for >= Windows 2000 */ + wchar_t* wpath; + int wpath_length; + FILE* fp; + + /* Calculate wpath length from path */ + wpath_length = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, path, -1, NULL, 0); + if (wpath_length == 0) /* 0 indicates error (this is likely from invalid UTF-8) */ + return NULL; + + wpath = (wchar_t*)malloc(wpath_length * sizeof(wchar_t)); + if (!wpath) + return NULL; + + if (MultiByteToWideChar(CP_UTF8, 0, path, -1, wpath, wpath_length) == 0) + { + free(wpath); + return NULL; + } #if defined(__STDC_WANT_SECURE_LIB__) + _wfopen_s(&fp, wpath, L"rb"); +#else + fp = _wfopen(wpath, L"rb"); +#endif + free(wpath); + return fp; +#elif defined(__STDC_WANT_SECURE_LIB__) FILE* fp; fopen_s(&fp, path, "rb"); return fp; @@ -1925,7 +1958,7 @@ void rc_file_seek_buffered_file(void* file_handle, int64_t offset, int origin) { case SEEK_SET: buffered_file->read_ptr = buffered_file->data + offset; break; case SEEK_CUR: buffered_file->read_ptr += offset; break; - case SEEK_END: buffered_file->read_ptr = buffered_file->data + buffered_file->data_size - offset; break; + case SEEK_END: buffered_file->read_ptr = buffered_file->data + buffered_file->data_size + offset; break; } if (buffered_file->read_ptr < buffered_file->data) @@ -1957,7 +1990,7 @@ void rc_file_close_buffered_file(void* file_handle) free(file_handle); } -static int rc_hash_file_from_buffer(char hash[33], int console_id, const uint8_t* buffer, size_t buffer_size) +static int rc_hash_file_from_buffer(char hash[33], uint32_t console_id, const uint8_t* buffer, size_t buffer_size) { struct rc_hash_filereader buffered_filereader_funcs; struct rc_hash_filereader* old_filereader = filereader; @@ -1980,7 +2013,7 @@ static int rc_hash_file_from_buffer(char hash[33], int console_id, const uint8_t return result; } -int rc_hash_generate_from_buffer(char hash[33], int console_id, const uint8_t* buffer, size_t buffer_size) +int rc_hash_generate_from_buffer(char hash[33], uint32_t console_id, const uint8_t* buffer, size_t buffer_size) { switch (console_id) { @@ -2115,7 +2148,7 @@ static int rc_hash_whole_file(char hash[33], const char* path) return result; } -static int rc_hash_buffered_file(char hash[33], int console_id, const char* path) +static int rc_hash_buffered_file(char hash[33], uint32_t console_id, const char* path) { uint8_t* buffer; int64_t size; @@ -2261,7 +2294,7 @@ static const char* rc_hash_get_first_item_from_playlist(const char* path) return disc_path; } -static int rc_hash_generate_from_playlist(char hash[33], int console_id, const char* path) +static int rc_hash_generate_from_playlist(char hash[33], uint32_t console_id, const char* path) { int result; const char* disc_path; @@ -2283,7 +2316,7 @@ static int rc_hash_generate_from_playlist(char hash[33], int console_id, const c return result; } -int rc_hash_generate_from_file(char hash[33], int console_id, const char* path) +int rc_hash_generate_from_file(char hash[33], uint32_t console_id, const char* path) { switch (console_id) {