dep/rcheevos: Bump to 74860c9

This commit is contained in:
Stenzek 2024-01-13 14:24:04 +10:00
parent ecbd693d22
commit e2e85a06cd
No known key found for this signature in database
42 changed files with 1126 additions and 505 deletions

View file

@ -5,9 +5,7 @@
#include <stdint.h>
#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 */

View file

@ -6,9 +6,7 @@
#include <stdint.h>
#include <time.h>
#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 */

View file

@ -6,9 +6,7 @@
#include <stddef.h>
#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 */

View file

@ -6,9 +6,7 @@
#include <stdint.h>
#include <time.h>
#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 */

View file

@ -6,9 +6,7 @@
#include <stdint.h>
#include <time.h>
#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 */

View file

@ -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 <stdint.h>
#include <time.h>
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 */

View file

@ -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 <stdint.h>
#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 <wtypes.h> /* 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 */

View file

@ -1,12 +1,12 @@
#ifndef RC_CONSOLES_H
#define RC_CONSOLES_H
#ifdef __cplusplus
extern "C" {
#endif
#include "rc_export.h"
#include <stdint.h>
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 */

View file

@ -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 */

View file

@ -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 <stdint.h>
*
* 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 */

View file

@ -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 */

View file

@ -1,15 +1,13 @@
#ifndef RC_RUNTIME_H
#define RC_RUNTIME_H
#ifdef __cplusplus
extern "C" {
#endif
#include "rc_error.h"
#include <stddef.h>
#include <stdint.h>
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 */

View file

@ -1,15 +1,13 @@
#ifndef RC_RUNTIME_TYPES_H
#define RC_RUNTIME_TYPES_H
#ifdef __cplusplus
extern "C" {
#endif
#include "rc_error.h"
#include <stddef.h>
#include <stdint.h>
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 */

View file

@ -1,38 +1,36 @@
#ifndef RC_URL_H
#define RC_URL_H
#include "rc_export.h"
#include <stddef.h>
#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 */

View file

@ -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;

View file

@ -6,9 +6,7 @@
#include <stddef.h>
#include <time.h>
#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 */

View file

@ -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);

View file

@ -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;
}

View file

@ -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;

View file

@ -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
}

View file

@ -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 */

View file

@ -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 */

View file

@ -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;

View file

@ -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
/* RAIntegration follows the same calling convention as rcheevos */
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);
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_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_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_hwnd_action_func_t update_main_window_handle;
rc_client_raintegration_get_external_client get_external_client;
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;
#endif /* RC_CLIENT_SUPPORTS_RAINTEGRATION */
RC_END_C_DECLS
#ifdef __cplusplus
}
#endif
#endif /* RC_CLIENT_SUPPORTS_RAINTEGRATION */
#endif /* RC_CLIENT_RAINTEGRATION_INTERNAL_H */

View file

@ -1,14 +1,14 @@
#ifndef RC_COMPAT_H
#define RC_COMPAT_H
#ifdef __cplusplus
extern "C" {
#endif
#include "rc_export.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
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 */

View file

@ -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;

View file

@ -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 <stddef.h>
#include <stdint.h>
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 */

View file

@ -1,12 +1,12 @@
#ifndef RC_UTIL_H
#define RC_UTIL_H
#include "rc_export.h"
#include <stddef.h>
#include <stdint.h>
#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 */

View file

@ -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;
}

View file

@ -1,9 +1,11 @@
#ifndef RC_VERSION_H
#define RC_VERSION_H
#ifdef __cplusplus
extern "C" {
#endif
#include "rc_export.h"
#include <stdint.h>
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 */

View file

@ -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;

View file

@ -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;

View file

@ -2,7 +2,7 @@
#include <ctype.h>
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";

View file

@ -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;

View file

@ -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);

View file

@ -6,16 +6,12 @@
#ifndef RC_DISABLE_LUA
#ifdef __cplusplus
extern "C" {
#endif
RC_BEGIN_C_DECLS
#include <lua.h>
#include <lauxlib.h>
#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);

View file

@ -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 */

View file

@ -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) {

View file

@ -5,9 +5,7 @@
#include <stddef.h>
#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 */

View file

@ -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;

View file

@ -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);

View file

@ -7,6 +7,11 @@
#include <stdio.h>
#include <ctype.h>
#if defined(_WIN32)
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#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)
{