mirror of
https://github.com/libretro/RetroArch
synced 2025-04-17 02:43:03 +00:00
(cheevos) upgrade to rcheevos 11.1 (#16151)
* move pause spam management into rc_client * update to rcheevos 11.1 * show [m] on missables * update makefile
This commit is contained in:
parent
e3329dbbab
commit
4ba5fc0333
@ -2148,6 +2148,7 @@ ifeq ($(HAVE_NETWORKING), 1)
|
||||
deps/rcheevos/src/rcheevos/runtime_progress.o \
|
||||
deps/rcheevos/src/rcheevos/trigger.o \
|
||||
deps/rcheevos/src/rcheevos/value.o \
|
||||
deps/rcheevos/src/rhash/aes.o \
|
||||
deps/rcheevos/src/rhash/cdreader.o \
|
||||
deps/rcheevos/src/rhash/hash.o \
|
||||
deps/rcheevos/src/rapi/rc_api_common.o \
|
||||
|
@ -115,6 +115,7 @@ static rcheevos_locals_t rcheevos_locals =
|
||||
0.0, /* tracker_progress */
|
||||
#endif
|
||||
{RCHEEVOS_LOAD_STATE_NONE, 0, 0 }, /* load_info */
|
||||
0, /* unpaused_frames */
|
||||
false,/* hardcore_active */
|
||||
false,/* loaded */
|
||||
#ifdef HAVE_GFX_WIDGETS
|
||||
@ -370,6 +371,15 @@ void rcheevos_spectating_changed(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
bool rcheevos_is_pause_allowed(void)
|
||||
{
|
||||
#ifdef HAVE_RC_CLIENT
|
||||
return rc_client_can_pause(rcheevos_locals.client, NULL);
|
||||
#else
|
||||
return (rcheevos_locals.unpaused_frames == 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef HAVE_RC_CLIENT
|
||||
|
||||
static void rcheevos_show_mastery_placard(void)
|
||||
@ -1964,6 +1974,11 @@ void rcheevos_test(void)
|
||||
rcheevos_locals.tracker_progress = 0.0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* We processed a frame - if there's a pause delay in effect, process it */
|
||||
if (rcheevos_locals.unpaused_frames > 0)
|
||||
rcheevos_locals.unpaused_frames--;
|
||||
|
||||
#endif /* HAVE_RC_CLIENT */
|
||||
}
|
||||
|
||||
|
@ -45,6 +45,7 @@ void rcheevos_hardcore_enabled_changed(void);
|
||||
void rcheevos_toggle_hardcore_paused(void);
|
||||
bool rcheevos_hardcore_active(void);
|
||||
|
||||
bool rcheevos_is_pause_allowed(void);
|
||||
void rcheevos_spectating_changed(void);
|
||||
|
||||
void rcheevos_validate_config_settings(void);
|
||||
|
@ -230,6 +230,8 @@ typedef struct rcheevos_locals_t
|
||||
|
||||
rcheevos_load_info_t load_info; /* load info */
|
||||
|
||||
uint32_t unpaused_frames; /* number of unpaused frames before next pause is allowed */
|
||||
|
||||
bool hardcore_active; /* hardcore functionality is active */
|
||||
bool loaded; /* load task has completed */
|
||||
#ifdef HAVE_GFX_WIDGETS
|
||||
|
@ -52,14 +52,20 @@ bool rcheevos_menu_get_state(unsigned menu_offset, char* buffer, size_t buffer_s
|
||||
const rc_client_achievement_t* cheevo = menuitem->achievement;
|
||||
if (cheevo)
|
||||
{
|
||||
if (cheevo->measured_progress[0])
|
||||
if (cheevo->state != RC_CLIENT_ACHIEVEMENT_STATE_ACTIVE)
|
||||
{
|
||||
snprintf(buffer, buffer_size, "%s - %s",
|
||||
msg_hash_to_str(menuitem->state_label_idx), cheevo->measured_progress);
|
||||
strlcpy(buffer, msg_hash_to_str(menuitem->state_label_idx), buffer_size);
|
||||
}
|
||||
else
|
||||
strlcpy(buffer, msg_hash_to_str(menuitem->state_label_idx), buffer_size);
|
||||
|
||||
{
|
||||
const char* missable = cheevo->type == RC_CLIENT_ACHIEVEMENT_TYPE_MISSABLE ? "[m] " : "";
|
||||
if (cheevo->measured_progress[0])
|
||||
snprintf(buffer, buffer_size, "%s%s - %s", missable,
|
||||
msg_hash_to_str(menuitem->state_label_idx), cheevo->measured_progress);
|
||||
else
|
||||
snprintf(buffer, buffer_size, "%s%s", missable,
|
||||
msg_hash_to_str(menuitem->state_label_idx));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -405,10 +411,12 @@ void rcheevos_menu_populate(void* data)
|
||||
do
|
||||
{
|
||||
if (menuitem->achievement)
|
||||
{
|
||||
menu_entries_append(info->list, menuitem->achievement->title,
|
||||
menuitem->achievement->description,
|
||||
MENU_ENUM_LABEL_CHEEVOS_LOCKED_ENTRY,
|
||||
MENU_SETTINGS_CHEEVOS_START + idx, 0, 0, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (menuitem->subset_id)
|
||||
|
23
deps/rcheevos/CHANGELOG.md
vendored
23
deps/rcheevos/CHANGELOG.md
vendored
@ -1,3 +1,26 @@
|
||||
# v11.1.0
|
||||
* add rc_client_get_user_agent_clause to generate substring to include in client User-Agents
|
||||
* add rc_client_can_pause function to control pause spam
|
||||
* add achievement type and rarity to rc_api_fetch_game_data_response_t and rc_client_achievement_t
|
||||
* add RC_CLIENT_ACHIEVEMENT_BUCKET_UNSYNCED for achievements that have been unlocked locally but not synced to the server
|
||||
* add RC_CONSOLE_NEO_GEO_CD to supported consoles for chd file extension
|
||||
* add hash logic for RC_CONSOLE_NINTENDO_3DS (note: added new file rhash/aes.c to support this)
|
||||
* add hash logic for RC_CONSOLE_MS_DOS
|
||||
* add game_hash and hardcore fields to rc_api_start_session_request_t and rc_api_ping_request_t
|
||||
* add RC_FORMAT_FIXED1/2/3, RC_FORMAT_TENS, RC_FORMAT_HUNDREDS, RC_FORMAT_THOUSANDS, and RC_FORMAT_UNSIGNED_VALUE
|
||||
* add RC_CONSOLE_STANDALONE
|
||||
* add extern "C" and __cdecl attributes to public functions
|
||||
* add __declspec(dllexport/dllimport) attributes to public functions via #define enablement
|
||||
* add rc_version and rc_version_string functions for accessing version from external linkage
|
||||
* add unicode path support to default filereader (Windows builds)
|
||||
* add rc_mutex support for GEKKO (libogc)
|
||||
* fix async_handle being returned when rc_client_begin_login is aborted synchronously
|
||||
* fix logic error hashing CD files smaller than one sector
|
||||
* fix read across region boundary in rc_libretro_memory_read
|
||||
* fix RC_CLIENT_EVENT_ACHIEVEMENT_CHALLENGE_INDICATOR_SHOW event not being raised if achievement is reset in the same frame that it's primed
|
||||
* moved rc_util.h from src/ to include/
|
||||
* initial (incomplete) support for rc_client_external_t and rc_client_raintegration_t
|
||||
|
||||
# v11.0.0
|
||||
* add rc_client_t and related functions
|
||||
* add RC_MEMSIZE_FLOAT_BE
|
||||
|
16
deps/rcheevos/include/rc_api_request.h
vendored
16
deps/rcheevos/include/rc_api_request.h
vendored
@ -2,13 +2,11 @@
|
||||
#define RC_API_REQUEST_H
|
||||
|
||||
#include "rc_error.h"
|
||||
#include "../src/rc_util.h"
|
||||
#include "rc_util.h"
|
||||
|
||||
#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 */
|
||||
|
65
deps/rcheevos/include/rc_api_runtime.h
vendored
65
deps/rcheevos/include/rc_api_runtime.h
vendored
@ -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 */
|
||||
|
36
deps/rcheevos/include/rc_api_user.h
vendored
36
deps/rcheevos/include/rc_api_user.h
vendored
@ -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 */
|
||||
|
168
deps/rcheevos/include/rc_client.h
vendored
168
deps/rcheevos/include/rc_client.h
vendored
@ -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,45 @@ 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);
|
||||
|
||||
/**
|
||||
* Gets a clause that can be added to the User-Agent to identify the version of rcheevos being used.
|
||||
*/
|
||||
RC_EXPORT size_t RC_CCONV rc_client_get_user_agent_clause(rc_client_t* client, char buffer[], size_t buffer_size);
|
||||
|
||||
/*****************************************************************************\
|
||||
| Logging |
|
||||
@ -145,7 +148,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 +165,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 +193,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 +215,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 +224,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 +232,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 +251,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 +278,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 +299,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 +315,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 +339,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 +379,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 +425,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 +464,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 +490,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 +557,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 +591,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 +612,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 */
|
||||
|
85
deps/rcheevos/include/rc_client_raintegration.h
vendored
Normal file
85
deps/rcheevos/include/rc_client_raintegration.h
vendored
Normal file
@ -0,0 +1,85 @@
|
||||
#ifndef RC_CLIENT_RAINTEGRATION_H
|
||||
#define RC_CLIENT_RAINTEGRATION_H
|
||||
|
||||
#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 <wtypes.h> /* HWND */
|
||||
|
||||
#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);
|
||||
|
||||
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 */
|
||||
|
||||
RC_END_C_DECLS
|
||||
|
||||
#endif /* RC_CLIENT_RAINTEGRATION_H */
|
18
deps/rcheevos/include/rc_consoles.h
vendored
18
deps/rcheevos/include/rc_consoles.h
vendored
@ -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 */
|
||||
|
12
deps/rcheevos/include/rc_error.h
vendored
12
deps/rcheevos/include/rc_error.h
vendored
@ -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 */
|
||||
|
100
deps/rcheevos/include/rc_export.h
vendored
Normal file
100
deps/rcheevos/include/rc_export.h
vendored
Normal 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 */
|
72
deps/rcheevos/include/rc_hash.h
vendored
72
deps/rcheevos/include/rc_hash.h
vendored
@ -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,34 @@ 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);
|
||||
|
||||
/* specifies a function called to obtain a 3DS CIA decryption normal key.
|
||||
* this key would be derived from slot0x3DKeyX and the common key specified by the passed index.
|
||||
* the normal key should be written in big endian format
|
||||
* returns non-zero on success, or zero on failure.
|
||||
*/
|
||||
typedef int (RC_CCONV *rc_hash_3ds_get_cia_normal_key_func)(uint8_t common_key_index, uint8_t out_normal_key[16]);
|
||||
RC_EXPORT void RC_CCONV rc_hash_init_3ds_get_cia_normal_key_func(rc_hash_3ds_get_cia_normal_key_func func);
|
||||
|
||||
/* specifies a function called to obtain 3DS NCCH decryption normal keys.
|
||||
* the primary key will always use slot0x2CKeyX and the passed primary KeyY.
|
||||
* the secondary key will use the KeyX slot passed
|
||||
* the secondary KeyY will be identical to the primary keyY if the passed program id is NULL
|
||||
* if the program id is not null, then the secondary KeyY will be obtained with "seed crypto"
|
||||
* with "seed crypto" the 8 byte program id can be used to obtain a 16 byte "seed" within the seeddb.bin firmware file
|
||||
* the primary KeyY then the seed will then be hashed with SHA256, and the upper 16 bytes of the digest will be the secondary KeyY used
|
||||
* the normal keys should be written in big endian format
|
||||
* returns non-zero on success, or zero on failure.
|
||||
*/
|
||||
typedef int (RC_CCONV *rc_hash_3ds_get_ncch_normal_keys_func)(uint8_t primary_key_y[16], uint8_t secondary_key_x_slot, uint8_t* optional_program_id,
|
||||
uint8_t out_primary_key[16], uint8_t out_secondary_key[16]);
|
||||
RC_EXPORT void RC_CCONV rc_hash_init_3ds_get_ncch_normal_keys_func(rc_hash_3ds_get_ncch_normal_keys_func func);
|
||||
|
||||
/* ===================================================== */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
RC_END_C_DECLS
|
||||
|
||||
#endif /* RC_HASH_H */
|
||||
|
58
deps/rcheevos/include/rc_runtime.h
vendored
58
deps/rcheevos/include/rc_runtime.h
vendored
@ -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 */
|
||||
|
65
deps/rcheevos/include/rc_runtime_types.h
vendored
65
deps/rcheevos/include/rc_runtime_types.h
vendored
@ -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 */
|
||||
|
36
deps/rcheevos/include/rc_url.h
vendored
36
deps/rcheevos/include/rc_url.h
vendored
@ -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 */
|
||||
|
@ -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 */
|
50
deps/rcheevos/src/rapi/rc_api_common.c
vendored
50
deps/rcheevos/src/rapi/rc_api_common.c
vendored
@ -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;
|
||||
|
||||
|
13
deps/rcheevos/src/rapi/rc_api_common.h
vendored
13
deps/rcheevos/src/rapi/rc_api_common.h
vendored
@ -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 */
|
||||
|
57
deps/rcheevos/src/rapi/rc_api_runtime.c
vendored
57
deps/rcheevos/src/rapi/rc_api_runtime.c
vendored
@ -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;
|
||||
}
|
||||
|
11
deps/rcheevos/src/rapi/rc_api_user.c
vendored
11
deps/rcheevos/src/rapi/rc_api_user.c
vendored
@ -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;
|
||||
|
708
deps/rcheevos/src/rc_client.c
vendored
708
deps/rcheevos/src/rc_client.c
vendored
File diff suppressed because it is too large
Load Diff
132
deps/rcheevos/src/rc_client_external.h
vendored
Normal file
132
deps/rcheevos/src/rc_client_external.h
vendored
Normal file
@ -0,0 +1,132 @@
|
||||
#ifndef RC_CLIENT_EXTERNAL_H
|
||||
#define RC_CLIENT_EXTERNAL_H
|
||||
|
||||
#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_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_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_CCONV *rc_client_external_async_handle_func_t)(rc_client_async_handle_t* handle);
|
||||
|
||||
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_CCONV *rc_client_external_get_user_info_func_t)(void);
|
||||
|
||||
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_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_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_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_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_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_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_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_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
|
||||
{
|
||||
rc_client_external_action_func_t destroy;
|
||||
|
||||
rc_client_external_enable_logging_func_t enable_logging;
|
||||
rc_client_external_set_event_handler_func_t set_event_handler;
|
||||
rc_client_external_set_read_memory_func_t set_read_memory;
|
||||
rc_client_external_set_get_time_millisecs_func_t set_get_time_millisecs;
|
||||
rc_client_external_set_string_func_t set_host;
|
||||
rc_client_external_copy_string_func_t get_user_agent_clause;
|
||||
|
||||
rc_client_external_set_int_func_t set_hardcore_enabled;
|
||||
rc_client_external_get_int_func_t get_hardcore_enabled;
|
||||
rc_client_external_set_int_func_t set_unofficial_enabled;
|
||||
rc_client_external_get_int_func_t get_unofficial_enabled;
|
||||
rc_client_external_set_int_func_t set_encore_mode_enabled;
|
||||
rc_client_external_get_int_func_t get_encore_mode_enabled;
|
||||
rc_client_external_set_int_func_t set_spectator_mode_enabled;
|
||||
rc_client_external_get_int_func_t get_spectator_mode_enabled;
|
||||
|
||||
rc_client_external_async_handle_func_t abort_async;
|
||||
|
||||
rc_client_external_begin_login_func_t begin_login_with_password;
|
||||
rc_client_external_begin_login_func_t begin_login_with_token;
|
||||
rc_client_external_action_func_t logout;
|
||||
rc_client_external_get_user_info_func_t get_user_info;
|
||||
|
||||
rc_client_external_begin_identify_and_load_game_func_t begin_identify_and_load_game;
|
||||
rc_client_external_begin_load_game_func_t begin_load_game;
|
||||
rc_client_external_get_game_info_func_t get_game_info;
|
||||
rc_client_external_begin_load_subset_t begin_load_subset;
|
||||
rc_client_external_get_subset_info_func_t get_subset_info;
|
||||
rc_client_external_action_func_t unload_game;
|
||||
rc_client_external_get_user_game_summary_func_t get_user_game_summary;
|
||||
rc_client_external_begin_change_media_func_t begin_change_media;
|
||||
|
||||
rc_client_external_create_achievement_list_func_t create_achievement_list;
|
||||
rc_client_external_get_int_func_t has_achievements;
|
||||
rc_client_external_get_achievement_info_func_t get_achievement_info;
|
||||
|
||||
rc_client_external_create_leaderboard_list_func_t create_leaderboard_list;
|
||||
rc_client_external_get_int_func_t has_leaderboards;
|
||||
rc_client_external_get_leaderboard_info_func_t get_leaderboard_info;
|
||||
rc_client_external_begin_fetch_leaderboard_entries_func_t begin_fetch_leaderboard_entries;
|
||||
rc_client_external_begin_fetch_leaderboard_entries_around_user_func_t begin_fetch_leaderboard_entries_around_user;
|
||||
|
||||
rc_client_external_copy_string_func_t get_rich_presence_message;
|
||||
rc_client_external_get_int_func_t has_rich_presence;
|
||||
|
||||
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;
|
||||
rc_client_external_serialize_progress_func_t serialize_progress;
|
||||
rc_client_external_deserialize_progress_func_t deserialize_progress;
|
||||
|
||||
} rc_client_external_t;
|
||||
|
||||
#define RC_CLIENT_EXTERNAL_VERSION 1
|
||||
|
||||
RC_END_C_DECLS
|
||||
|
||||
#endif /* RC_CLIENT_EXTERNAL_H */
|
70
deps/rcheevos/src/rc_client_internal.h
vendored
70
deps/rcheevos/src/rc_client_internal.h
vendored
@ -1,26 +1,31 @@
|
||||
#ifndef RC_CLIENT_INTERNAL_H
|
||||
#define RC_CLIENT_INTERNAL_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "rc_client.h"
|
||||
|
||||
#ifdef RC_CLIENT_SUPPORTS_RAINTEGRATION
|
||||
#include "rc_client_raintegration_internal.h"
|
||||
#endif
|
||||
#ifdef RC_CLIENT_SUPPORTS_EXTERNAL
|
||||
#include "rc_client_external.h"
|
||||
#endif
|
||||
|
||||
#include "rc_compat.h"
|
||||
#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;
|
||||
@ -37,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
|
||||
{
|
||||
@ -50,6 +55,12 @@ typedef struct rc_client_scheduled_callback_data_t
|
||||
|
||||
void rc_client_schedule_callback(rc_client_t* client, rc_client_scheduled_callback_data_t* scheduled_callback);
|
||||
|
||||
struct rc_client_async_handle_t {
|
||||
uint8_t aborted;
|
||||
};
|
||||
|
||||
int rc_client_async_handle_aborted(rc_client_t* client, rc_client_async_handle_t* async_handle);
|
||||
|
||||
/*****************************************************************************\
|
||||
| Achievements |
|
||||
\*****************************************************************************/
|
||||
@ -78,6 +89,14 @@ typedef struct rc_client_achievement_info_t {
|
||||
time_t updated_time;
|
||||
} rc_client_achievement_info_t;
|
||||
|
||||
struct rc_client_achievement_list_info_t;
|
||||
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_;
|
||||
rc_client_destroy_achievement_list_func_t destroy_func;
|
||||
} rc_client_achievement_list_info_t;
|
||||
|
||||
enum {
|
||||
RC_CLIENT_PROGRESS_TRACKER_ACTION_NONE,
|
||||
RC_CLIENT_PROGRESS_TRACKER_ACTION_SHOW,
|
||||
@ -145,6 +164,22 @@ typedef struct rc_client_leaderboard_info_t {
|
||||
uint8_t hidden;
|
||||
} rc_client_leaderboard_info_t;
|
||||
|
||||
struct rc_client_leaderboard_list_info_t;
|
||||
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_;
|
||||
rc_client_destroy_leaderboard_list_func_t destroy_func;
|
||||
} rc_client_leaderboard_list_info_t;
|
||||
|
||||
struct rc_client_leaderboard_entry_list_info_t;
|
||||
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_;
|
||||
rc_client_destroy_leaderboard_entry_list_func_t destroy_func;
|
||||
} rc_client_leaderboard_entry_list_info_t;
|
||||
|
||||
uint8_t rc_client_map_leaderboard_format(int format);
|
||||
|
||||
/*****************************************************************************\
|
||||
@ -177,7 +212,7 @@ typedef struct rc_client_subset_info_t {
|
||||
uint8_t pending_events;
|
||||
} rc_client_subset_info_t;
|
||||
|
||||
void rc_client_begin_load_subset(rc_client_t* client, uint32_t subset_id, rc_client_callback_t callback, void* callback_userdata);
|
||||
rc_client_async_handle_t* rc_client_begin_load_subset(rc_client_t* client, uint32_t subset_id, rc_client_callback_t callback, void* callback_userdata);
|
||||
|
||||
/*****************************************************************************\
|
||||
| Game |
|
||||
@ -273,6 +308,16 @@ typedef struct rc_client_state_t {
|
||||
|
||||
rc_client_scheduled_callback_data_t* scheduled_callbacks;
|
||||
|
||||
#ifdef RC_CLIENT_SUPPORTS_EXTERNAL
|
||||
rc_client_external_t* external_client;
|
||||
#endif
|
||||
#ifdef RC_CLIENT_SUPPORTS_RAINTEGRATION
|
||||
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;
|
||||
@ -280,6 +325,7 @@ typedef struct rc_client_state_t {
|
||||
uint8_t log_level;
|
||||
uint8_t user;
|
||||
uint8_t disconnect;
|
||||
uint8_t allow_leaderboards_in_softcore;
|
||||
|
||||
struct rc_client_load_state_t* load;
|
||||
struct rc_client_async_handle_t* async_handles[4];
|
||||
@ -343,8 +389,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 */
|
||||
|
493
deps/rcheevos/src/rc_client_raintegration.c
vendored
Normal file
493
deps/rcheevos/src/rc_client_raintegration.c
vendored
Normal file
@ -0,0 +1,493 @@
|
||||
#include "rc_client_raintegration_internal.h"
|
||||
|
||||
#include "rc_client_internal.h"
|
||||
|
||||
#include "rapi/rc_api_common.h"
|
||||
|
||||
#ifdef RC_CLIENT_SUPPORTS_RAINTEGRATION
|
||||
|
||||
static void rc_client_raintegration_load_dll(rc_client_t* client,
|
||||
const wchar_t* search_directory, rc_client_callback_t callback, void* callback_userdata)
|
||||
{
|
||||
wchar_t sPath[_MAX_PATH];
|
||||
const int nPathSize = sizeof(sPath) / sizeof(sPath[0]);
|
||||
rc_client_raintegration_t* raintegration;
|
||||
int sPathIndex = 0;
|
||||
DWORD dwAttrib;
|
||||
HINSTANCE hDLL;
|
||||
|
||||
if (search_directory) {
|
||||
sPathIndex = swprintf_s(sPath, nPathSize, L"%s\\", search_directory);
|
||||
if (sPathIndex > nPathSize - 22) {
|
||||
callback(RC_INVALID_STATE, "search_directory too long", client, callback_userdata);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(_M_X64) || defined(__amd64__)
|
||||
wcscpy_s(&sPath[sPathIndex], nPathSize - sPathIndex, L"RA_Integration-x64.dll");
|
||||
dwAttrib = GetFileAttributesW(sPath);
|
||||
if (dwAttrib == INVALID_FILE_ATTRIBUTES) {
|
||||
wcscpy_s(&sPath[sPathIndex], nPathSize - sPathIndex, L"RA_Integration.dll");
|
||||
dwAttrib = GetFileAttributesW(sPath);
|
||||
}
|
||||
#else
|
||||
wcscpy_s(&sPath[sPathIndex], nPathSize - sPathIndex, L"RA_Integration.dll");
|
||||
dwAttrib = GetFileAttributesW(sPath);
|
||||
#endif
|
||||
|
||||
if (dwAttrib == INVALID_FILE_ATTRIBUTES) {
|
||||
callback(RC_MISSING_VALUE, "RA_Integration.dll not found in search directory", client, callback_userdata);
|
||||
return;
|
||||
}
|
||||
|
||||
hDLL = LoadLibraryW(sPath);
|
||||
if (hDLL == NULL) {
|
||||
char error_message[512];
|
||||
const DWORD last_error = GetLastError();
|
||||
int offset = snprintf(error_message, sizeof(error_message), "Failed to load RA_Integration.dll (%u)", last_error);
|
||||
|
||||
if (last_error != 0) {
|
||||
LPSTR messageBuffer = NULL;
|
||||
const DWORD size = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL, last_error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&messageBuffer, 0, NULL);
|
||||
|
||||
snprintf(&error_message[offset], sizeof(error_message) - offset, ": %.*s", size, messageBuffer);
|
||||
|
||||
LocalFree(messageBuffer);
|
||||
}
|
||||
|
||||
callback(RC_ABORTED, error_message, client, callback_userdata);
|
||||
return;
|
||||
}
|
||||
|
||||
raintegration = (rc_client_raintegration_t*)rc_buffer_alloc(&client->state.buffer, sizeof(rc_client_raintegration_t));
|
||||
memset(raintegration, 0, sizeof(*raintegration));
|
||||
raintegration->hDLL = hDLL;
|
||||
|
||||
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->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 ||
|
||||
!raintegration->get_external_client) {
|
||||
FreeLibrary(hDLL);
|
||||
|
||||
callback(RC_ABORTED, "One or more required exports was not found in RA_Integration.dll", client, callback_userdata);
|
||||
}
|
||||
else {
|
||||
rc_mutex_lock(&client->state.mutex);
|
||||
client->state.raintegration = raintegration;
|
||||
rc_mutex_unlock(&client->state.mutex);
|
||||
|
||||
RC_CLIENT_LOG_INFO_FORMATTED(client, "RA_Integration.dll %s loaded", client->state.raintegration->get_version());
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct rc_client_version_validation_callback_data_t {
|
||||
rc_client_t* client;
|
||||
rc_client_callback_t callback;
|
||||
void* callback_userdata;
|
||||
HWND main_window_handle;
|
||||
char* client_name;
|
||||
char* client_version;
|
||||
rc_client_async_handle_t async_handle;
|
||||
} rc_client_version_validation_callback_data_t;
|
||||
|
||||
int rc_client_version_less(const char* left, const char* right)
|
||||
{
|
||||
do {
|
||||
int left_len = 0;
|
||||
int right_len = 0;
|
||||
while (*left && *left == '0')
|
||||
++left;
|
||||
while (left[left_len] && left[left_len] != '.')
|
||||
++left_len;
|
||||
while (*right && *right == '0')
|
||||
++right;
|
||||
while (right[right_len] && right[right_len] != '.')
|
||||
++right_len;
|
||||
|
||||
if (left_len != right_len)
|
||||
return (left_len < right_len);
|
||||
|
||||
while (left_len--) {
|
||||
if (*left != *right)
|
||||
return (*left < *right);
|
||||
++left;
|
||||
++right;
|
||||
}
|
||||
|
||||
if (*left == '.')
|
||||
++left;
|
||||
if (*right == '.')
|
||||
++right;
|
||||
} while (*left || *right);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
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_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();
|
||||
if (host_url) {
|
||||
if (strcmp(host_url, "OFFLINE") != 0) {
|
||||
rc_client_set_host(client, host_url);
|
||||
}
|
||||
else if (client->state.raintegration->init_client_offline) {
|
||||
init_func = client->state.raintegration->init_client_offline;
|
||||
RC_CLIENT_LOG_INFO(client, "Initializing in offline mode");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!init_func || !init_func(version_validation_callback_data->main_window_handle,
|
||||
version_validation_callback_data->client_name,
|
||||
version_validation_callback_data->client_version)) {
|
||||
const char* error_message = "RA_Integration initialization failed";
|
||||
|
||||
rc_client_unload_raintegration(client);
|
||||
|
||||
RC_CLIENT_LOG_ERR(client, error_message);
|
||||
version_validation_callback_data->callback(RC_ABORTED, error_message, client, version_validation_callback_data->callback_userdata);
|
||||
}
|
||||
else {
|
||||
rc_client_external_t* external_client = (rc_client_external_t*)
|
||||
rc_buffer_alloc(&client->state.buffer, sizeof(*external_client));
|
||||
memset(external_client, 0, sizeof(*external_client));
|
||||
|
||||
if (!client->state.raintegration->get_external_client(external_client, RC_CLIENT_EXTERNAL_VERSION)) {
|
||||
const char* error_message = "RA_Integration external client export failed";
|
||||
|
||||
rc_client_unload_raintegration(client);
|
||||
|
||||
RC_CLIENT_LOG_ERR(client, error_message);
|
||||
version_validation_callback_data->callback(RC_ABORTED, error_message, client, version_validation_callback_data->callback_userdata);
|
||||
}
|
||||
else {
|
||||
/* copy state to the external client */
|
||||
if (external_client->enable_logging)
|
||||
external_client->enable_logging(client, client->state.log_level, client->callbacks.log_call);
|
||||
|
||||
if (external_client->set_event_handler)
|
||||
external_client->set_event_handler(client, client->callbacks.event_handler);
|
||||
if (external_client->set_read_memory)
|
||||
external_client->set_read_memory(client, client->callbacks.read_memory);
|
||||
|
||||
if (external_client->set_hardcore_enabled)
|
||||
external_client->set_hardcore_enabled(rc_client_get_hardcore_enabled(client));
|
||||
if (external_client->set_unofficial_enabled)
|
||||
external_client->set_unofficial_enabled(rc_client_get_unofficial_enabled(client));
|
||||
if (external_client->set_encore_mode_enabled)
|
||||
external_client->set_encore_mode_enabled(rc_client_get_encore_mode_enabled(client));
|
||||
if (external_client->set_spectator_mode_enabled)
|
||||
external_client->set_spectator_mode_enabled(rc_client_get_spectator_mode_enabled(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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void rc_client_version_validation_callback(const rc_api_server_response_t* server_response, void* callback_data)
|
||||
{
|
||||
rc_client_version_validation_callback_data_t* version_validation_callback_data =
|
||||
(rc_client_version_validation_callback_data_t*)callback_data;
|
||||
rc_client_t* client = version_validation_callback_data->client;
|
||||
|
||||
if (rc_client_async_handle_aborted(client, &version_validation_callback_data->async_handle)) {
|
||||
RC_CLIENT_LOG_VERBOSE(client, "Version validation aborted");
|
||||
}
|
||||
else {
|
||||
rc_api_response_t response;
|
||||
int result;
|
||||
const char* current_version;
|
||||
const char* minimum_version = "";
|
||||
|
||||
rc_json_field_t fields[] = {
|
||||
RC_JSON_NEW_FIELD("Success"),
|
||||
RC_JSON_NEW_FIELD("Error"),
|
||||
RC_JSON_NEW_FIELD("MinimumVersion"),
|
||||
};
|
||||
|
||||
memset(&response, 0, sizeof(response));
|
||||
rc_buffer_init(&response.buffer);
|
||||
|
||||
result = rc_json_parse_server_response(&response, server_response, fields, sizeof(fields) / sizeof(fields[0]));
|
||||
if (result == RC_OK) {
|
||||
if (!rc_json_get_required_string(&minimum_version, &response, &fields[2], "MinimumVersion"))
|
||||
result = RC_MISSING_VALUE;
|
||||
}
|
||||
|
||||
if (result != RC_OK) {
|
||||
RC_CLIENT_LOG_ERR_FORMATTED(client, "Failed to fetch latest integration version: %.*s", server_response->body_length, server_response->body);
|
||||
|
||||
rc_client_unload_raintegration(client);
|
||||
|
||||
version_validation_callback_data->callback(result, rc_error_str(result),
|
||||
client, version_validation_callback_data->callback_userdata);
|
||||
}
|
||||
else {
|
||||
current_version = client->state.raintegration->get_version();
|
||||
|
||||
if (rc_client_version_less(current_version, minimum_version)) {
|
||||
char error_message[256];
|
||||
|
||||
rc_client_unload_raintegration(client);
|
||||
|
||||
snprintf(error_message, sizeof(error_message),
|
||||
"RA_Integration version %s is lower than minimum version %s", current_version, minimum_version);
|
||||
RC_CLIENT_LOG_WARN(client, error_message);
|
||||
version_validation_callback_data->callback(RC_ABORTED, error_message, client, version_validation_callback_data->callback_userdata);
|
||||
}
|
||||
else {
|
||||
RC_CLIENT_LOG_INFO_FORMATTED(client, "Validated RA_Integration version %s (minimum %s)", current_version, minimum_version);
|
||||
|
||||
rc_client_init_raintegration(client, version_validation_callback_data);
|
||||
}
|
||||
}
|
||||
|
||||
rc_buffer_destroy(&response.buffer);
|
||||
}
|
||||
|
||||
free(version_validation_callback_data->client_name);
|
||||
free(version_validation_callback_data->client_version);
|
||||
free(version_validation_callback_data);
|
||||
}
|
||||
|
||||
rc_client_async_handle_t* 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)
|
||||
{
|
||||
rc_client_version_validation_callback_data_t* callback_data;
|
||||
rc_api_url_builder_t builder;
|
||||
rc_api_request_t request;
|
||||
|
||||
if (!client) {
|
||||
callback(RC_INVALID_STATE, "client is required", client, callback_userdata);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!client_name) {
|
||||
callback(RC_INVALID_STATE, "client_name is required", client, callback_userdata);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!client_version) {
|
||||
callback(RC_INVALID_STATE, "client_version is required", client, callback_userdata);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (client->state.user != RC_CLIENT_USER_STATE_NONE) {
|
||||
callback(RC_INVALID_STATE, "Cannot initialize RAIntegration after login", client, callback_userdata);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!client->state.raintegration) {
|
||||
if (!main_window_handle) {
|
||||
callback(RC_INVALID_STATE, "main_window_handle is required", client, callback_userdata);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rc_client_raintegration_load_dll(client, search_directory, callback, callback_userdata);
|
||||
if (!client->state.raintegration)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (client->state.raintegration->get_host_url) {
|
||||
const char* host_url = client->state.raintegration->get_host_url();
|
||||
if (host_url && strcmp(host_url, "https://retroachievements.org") != 0 &&
|
||||
strcmp(host_url, "OFFLINE") != 0) {
|
||||
/* if the DLL specifies a custom host, use it */
|
||||
rc_client_set_host(client, host_url);
|
||||
}
|
||||
}
|
||||
|
||||
memset(&request, 0, sizeof(request));
|
||||
rc_api_url_build_dorequest_url(&request);
|
||||
rc_url_builder_init(&builder, &request.buffer, 48);
|
||||
rc_url_builder_append_str_param(&builder, "r", "latestintegration");
|
||||
request.post_data = rc_url_builder_finalize(&builder);
|
||||
|
||||
callback_data = calloc(1, sizeof(*callback_data));
|
||||
if (!callback_data) {
|
||||
callback(RC_OUT_OF_MEMORY, rc_error_str(RC_OUT_OF_MEMORY), client, callback_userdata);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
callback_data->client = client;
|
||||
callback_data->callback = callback;
|
||||
callback_data->callback_userdata = callback_userdata;
|
||||
callback_data->client_name = strdup(client_name);
|
||||
callback_data->client_version = strdup(client_version);
|
||||
callback_data->main_window_handle = main_window_handle;
|
||||
|
||||
client->callbacks.server_call(&request, rc_client_version_validation_callback, callback_data, 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;
|
||||
|
||||
if (!client || !client->state.raintegration)
|
||||
return;
|
||||
|
||||
RC_CLIENT_LOG_INFO(client, "Unloading RA_Integration")
|
||||
|
||||
if (client->state.raintegration->shutdown)
|
||||
client->state.raintegration->shutdown();
|
||||
|
||||
rc_mutex_lock(&client->state.mutex);
|
||||
hDLL = client->state.raintegration->hDLL;
|
||||
client->state.raintegration = NULL;
|
||||
client->state.external_client = NULL;
|
||||
rc_mutex_unlock(&client->state.mutex);
|
||||
|
||||
if (hDLL)
|
||||
FreeLibrary(hDLL);
|
||||
}
|
||||
|
||||
#endif /* RC_CLIENT_SUPPORTS_RAINTEGRATION */
|
52
deps/rcheevos/src/rc_client_raintegration_internal.h
vendored
Normal file
52
deps/rcheevos/src/rc_client_raintegration_internal.h
vendored
Normal file
@ -0,0 +1,52 @@
|
||||
#ifndef RC_CLIENT_RAINTEGRATION_INTERNAL_H
|
||||
#define RC_CLIENT_RAINTEGRATION_INTERNAL_H
|
||||
|
||||
#include "rc_client_raintegration.h"
|
||||
|
||||
#ifdef RC_CLIENT_SUPPORTS_RAINTEGRATION
|
||||
|
||||
#include "rc_client_external.h"
|
||||
#include "rc_compat.h"
|
||||
|
||||
RC_BEGIN_C_DECLS
|
||||
|
||||
/* RAIntegration follows the same calling convention as rcheevos */
|
||||
|
||||
typedef void (RC_CCONV* rc_client_raintegration_action_func_t)(void);
|
||||
typedef const char* (RC_CCONV* rc_client_raintegration_get_string_func_t)(void);
|
||||
typedef int (RC_CCONV* rc_client_raintegration_init_client_func_t)(HWND hMainWnd, const char* sClientName, const char* sClientVersion);
|
||||
typedef int (RC_CCONV* rc_client_raintegration_get_external_client_func_t)(rc_client_external_t* pClient, int nVersion);
|
||||
typedef void (RC_CCONV* rc_client_raintegration_hwnd_action_func_t)(HWND hWnd);
|
||||
typedef const rc_client_raintegration_menu_t* (RC_CCONV* rc_client_raintegration_get_menu_func_t)(void);
|
||||
typedef int (RC_CCONV* rc_client_raintegration_activate_menuitem_func_t)(uint32_t nMenuItemId);
|
||||
typedef void (RC_CCONV* rc_client_raintegration_set_write_memory_func_t)(rc_client_t* pClient, rc_client_raintegration_write_memory_func_t handler);
|
||||
typedef void (RC_CCONV* rc_client_raintegration_set_event_handler_func_t)(rc_client_t* pClient, rc_client_raintegration_event_handler_t handler);
|
||||
|
||||
typedef struct rc_client_raintegration_t
|
||||
{
|
||||
HINSTANCE hDLL;
|
||||
HMENU hPopupMenu;
|
||||
uint8_t bIsInited;
|
||||
|
||||
rc_client_raintegration_get_string_func_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_hwnd_action_func_t update_main_window_handle;
|
||||
|
||||
rc_client_raintegration_set_write_memory_func_t set_write_memory_function;
|
||||
rc_client_raintegration_set_event_handler_func_t set_event_handler;
|
||||
rc_client_raintegration_get_menu_func_t get_menu;
|
||||
rc_client_raintegration_activate_menuitem_func_t activate_menu_item;
|
||||
|
||||
rc_client_raintegration_get_external_client_func_t get_external_client;
|
||||
|
||||
} rc_client_raintegration_t;
|
||||
|
||||
RC_END_C_DECLS
|
||||
|
||||
#endif /* RC_CLIENT_SUPPORTS_RAINTEGRATION */
|
||||
|
||||
#endif /* RC_CLIENT_RAINTEGRATION_INTERNAL_H */
|
4
deps/rcheevos/src/rc_compat.c
vendored
4
deps/rcheevos/src/rc_compat.c
vendored
@ -116,7 +116,9 @@ void rc_mutex_unlock(rc_mutex_t* mutex)
|
||||
|
||||
#elif defined(GEKKO)
|
||||
|
||||
void rc_mutex_init(rc_mutex_t *mutex)
|
||||
/* https://github.com/libretro/RetroArch/pull/16116 */
|
||||
|
||||
void rc_mutex_init(rc_mutex_t* mutex)
|
||||
{
|
||||
LWP_MutexInit(mutex, NULL);
|
||||
}
|
||||
|
10
deps/rcheevos/src/rc_compat.h
vendored
10
deps/rcheevos/src/rc_compat.h
vendored
@ -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 */
|
||||
|
96
deps/rcheevos/src/rc_libretro.c
vendored
96
deps/rcheevos/src/rc_libretro.c
vendored
@ -51,6 +51,11 @@ static const rc_disallowed_setting_t _rc_disallowed_dolphin_settings[] = {
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static const rc_disallowed_setting_t _rc_disallowed_dosbox_pure_settings[] = {
|
||||
{ "dosbox_pure_strict_mode", "false" },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static const rc_disallowed_setting_t _rc_disallowed_duckstation_settings[] = {
|
||||
{ "duckstation_CDROM.LoadImagePatches", "true" },
|
||||
{ NULL, NULL }
|
||||
@ -96,6 +101,11 @@ static const rc_disallowed_setting_t _rc_disallowed_mesen_s_settings[] = {
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static const rc_disallowed_setting_t _rc_disallowed_neocd_settings[] = {
|
||||
{ "neocd_bios", "uni-bios*" },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static const rc_disallowed_setting_t _rc_disallowed_pcsx_rearmed_settings[] = {
|
||||
{ "pcsx_rearmed_region", "pal" },
|
||||
{ NULL, NULL }
|
||||
@ -144,6 +154,7 @@ static const rc_disallowed_core_settings_t rc_disallowed_core_settings[] = {
|
||||
{ "bsnes-mercury", _rc_disallowed_bsnes_settings },
|
||||
{ "cap32", _rc_disallowed_cap32_settings },
|
||||
{ "dolphin-emu", _rc_disallowed_dolphin_settings },
|
||||
{ "DOSBox-pure", _rc_disallowed_dosbox_pure_settings },
|
||||
{ "DuckStation", _rc_disallowed_duckstation_settings },
|
||||
{ "ecwolf", _rc_disallowed_ecwolf_settings },
|
||||
{ "FCEUmm", _rc_disallowed_fceumm_settings },
|
||||
@ -152,6 +163,7 @@ static const rc_disallowed_core_settings_t rc_disallowed_core_settings[] = {
|
||||
{ "Genesis Plus GX Wide", _rc_disallowed_gpgx_wide_settings },
|
||||
{ "Mesen", _rc_disallowed_mesen_settings },
|
||||
{ "Mesen-S", _rc_disallowed_mesen_s_settings },
|
||||
{ "NeoCD", _rc_disallowed_neocd_settings },
|
||||
{ "PPSSPP", _rc_disallowed_ppsspp_settings },
|
||||
{ "PCSX-ReARMed", _rc_disallowed_pcsx_rearmed_settings },
|
||||
{ "PicoDrive", _rc_disallowed_picodrive_settings },
|
||||
@ -318,27 +330,38 @@ uint8_t* rc_libretro_memory_find(const rc_libretro_memory_regions_t* regions, ui
|
||||
|
||||
uint32_t rc_libretro_memory_read(const rc_libretro_memory_regions_t* regions, uint32_t address,
|
||||
uint8_t* buffer, uint32_t num_bytes) {
|
||||
uint32_t i;
|
||||
uint32_t bytes_read = 0;
|
||||
uint32_t avail;
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < regions->count; ++i) {
|
||||
const size_t size = regions->size[i];
|
||||
if (address < size) {
|
||||
if (regions->data[i] == NULL)
|
||||
break;
|
||||
|
||||
avail = (unsigned)(size - address);
|
||||
if (avail < num_bytes)
|
||||
return avail;
|
||||
|
||||
memcpy(buffer, ®ions->data[i][address], num_bytes);
|
||||
return num_bytes;
|
||||
if (address >= size) {
|
||||
/* address is not in this block, adjust and look at next block */
|
||||
address -= (unsigned)size;
|
||||
continue;
|
||||
}
|
||||
|
||||
address -= (unsigned)size;
|
||||
if (regions->data[i] == NULL) /* no memory associated to this block. abort */
|
||||
break;
|
||||
|
||||
avail = (unsigned)(size - address);
|
||||
if (avail >= num_bytes) {
|
||||
/* requested memory is fully within this block, copy and return it */
|
||||
memcpy(buffer, ®ions->data[i][address], num_bytes);
|
||||
bytes_read += num_bytes;
|
||||
return bytes_read;
|
||||
}
|
||||
|
||||
/* copy whatever is available in this block, and adjust for the next block */
|
||||
memcpy(buffer, ®ions->data[i][address], avail);
|
||||
buffer += avail;
|
||||
bytes_read += avail;
|
||||
num_bytes -= avail;
|
||||
address = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return bytes_read;
|
||||
}
|
||||
|
||||
void rc_libretro_init_verbose_message_callback(rc_libretro_message_callback callback) {
|
||||
@ -616,7 +639,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;
|
||||
@ -665,8 +688,7 @@ void rc_libretro_hash_set_init(struct rc_libretro_hash_set_t* hash_set,
|
||||
return;
|
||||
|
||||
file_handle = rc_file_open(m3u_path);
|
||||
if (!file_handle)
|
||||
{
|
||||
if (!file_handle) {
|
||||
rc_hash_error("Could not open playlist");
|
||||
return;
|
||||
}
|
||||
@ -676,8 +698,7 @@ void rc_libretro_hash_set_init(struct rc_libretro_hash_set_t* hash_set,
|
||||
rc_file_seek(file_handle, 0, SEEK_SET);
|
||||
|
||||
m3u_contents = (char*)malloc((size_t)file_len + 1);
|
||||
if (m3u_contents)
|
||||
{
|
||||
if (m3u_contents) {
|
||||
rc_file_read(file_handle, m3u_contents, (int)file_len);
|
||||
m3u_contents[file_len] = '\0';
|
||||
|
||||
@ -690,23 +711,19 @@ void rc_libretro_hash_set_init(struct rc_libretro_hash_set_t* hash_set,
|
||||
while (isspace((int)*ptr))
|
||||
++ptr;
|
||||
|
||||
if (*ptr == '#')
|
||||
{
|
||||
if (*ptr == '#') {
|
||||
/* ignore comment unless it's the special SAVEDISK extension */
|
||||
if (memcmp(ptr, "#SAVEDISK:", 10) == 0)
|
||||
{
|
||||
if (memcmp(ptr, "#SAVEDISK:", 10) == 0) {
|
||||
/* get the path to the save disk from the frontend, assign it a bogus hash so
|
||||
* it doesn't get hashed later */
|
||||
if (get_image_path(index, image_path, sizeof(image_path)))
|
||||
{
|
||||
if (get_image_path(index, image_path, sizeof(image_path))) {
|
||||
const char save_disk_hash[33] = "[SAVE DISK]";
|
||||
rc_libretro_hash_set_add(hash_set, image_path, -1, save_disk_hash);
|
||||
++index;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
/* non-empty line, tally a file */
|
||||
++index;
|
||||
}
|
||||
@ -720,8 +737,7 @@ void rc_libretro_hash_set_init(struct rc_libretro_hash_set_t* hash_set,
|
||||
free(m3u_contents);
|
||||
}
|
||||
|
||||
if (hash_set->entries_count > 0)
|
||||
{
|
||||
if (hash_set->entries_count > 0) {
|
||||
/* at least one save disk was found. make sure the core supports the #SAVEDISK: extension by
|
||||
* asking for the last expected disk. if it's not found, assume no #SAVEDISK: support */
|
||||
if (!get_image_path(index - 1, image_path, sizeof(image_path)))
|
||||
@ -753,13 +769,10 @@ void rc_libretro_hash_set_add(struct rc_libretro_hash_set_t* hash_set,
|
||||
struct rc_libretro_hash_entry_t* scan;
|
||||
struct rc_libretro_hash_entry_t* stop = hash_set->entries + hash_set->entries_count;;
|
||||
|
||||
if (path_djb2)
|
||||
{
|
||||
if (path_djb2) {
|
||||
/* attempt to match the path */
|
||||
for (scan = hash_set->entries; scan < stop; ++scan)
|
||||
{
|
||||
if (scan->path_djb2 == path_djb2)
|
||||
{
|
||||
for (scan = hash_set->entries; scan < stop; ++scan) {
|
||||
if (scan->path_djb2 == path_djb2) {
|
||||
entry = scan;
|
||||
break;
|
||||
}
|
||||
@ -769,19 +782,20 @@ void rc_libretro_hash_set_add(struct rc_libretro_hash_set_t* hash_set,
|
||||
if (!entry)
|
||||
{
|
||||
/* entry not found, allocate a new one */
|
||||
if (hash_set->entries_size == 0)
|
||||
{
|
||||
if (hash_set->entries_size == 0) {
|
||||
hash_set->entries_size = 4;
|
||||
hash_set->entries = (struct rc_libretro_hash_entry_t*)
|
||||
malloc(hash_set->entries_size * sizeof(struct rc_libretro_hash_entry_t));
|
||||
}
|
||||
else if (hash_set->entries_count == hash_set->entries_size)
|
||||
{
|
||||
else if (hash_set->entries_count == hash_set->entries_size) {
|
||||
hash_set->entries_size += 4;
|
||||
hash_set->entries = (struct rc_libretro_hash_entry_t*)realloc(hash_set->entries,
|
||||
hash_set->entries_size * sizeof(struct rc_libretro_hash_entry_t));
|
||||
}
|
||||
|
||||
if (hash_set->entries == NULL) /* unexpected, but better than crashing */
|
||||
return;
|
||||
|
||||
entry = hash_set->entries + hash_set->entries_count++;
|
||||
}
|
||||
|
||||
@ -796,8 +810,7 @@ const char* rc_libretro_hash_set_get_hash(const struct rc_libretro_hash_set_t* h
|
||||
const uint32_t path_djb2 = rc_libretro_djb2(path);
|
||||
struct rc_libretro_hash_entry_t* scan = hash_set->entries;
|
||||
struct rc_libretro_hash_entry_t* stop = scan + hash_set->entries_count;
|
||||
for (; scan < stop; ++scan)
|
||||
{
|
||||
for (; scan < stop; ++scan) {
|
||||
if (scan->path_djb2 == path_djb2)
|
||||
return scan->hash;
|
||||
}
|
||||
@ -809,8 +822,7 @@ int rc_libretro_hash_set_get_game_id(const struct rc_libretro_hash_set_t* hash_s
|
||||
{
|
||||
struct rc_libretro_hash_entry_t* scan = hash_set->entries;
|
||||
struct rc_libretro_hash_entry_t* stop = scan + hash_set->entries_count;
|
||||
for (; scan < stop; ++scan)
|
||||
{
|
||||
for (; scan < stop; ++scan) {
|
||||
if (memcmp(scan->hash, hash, sizeof(scan->hash)) == 0)
|
||||
return scan->game_id;
|
||||
}
|
||||
|
48
deps/rcheevos/src/rc_libretro.h
vendored
48
deps/rcheevos/src/rc_libretro.h
vendored
@ -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 */
|
||||
|
2
deps/rcheevos/src/rc_util.c
vendored
2
deps/rcheevos/src/rc_util.c
vendored
@ -35,7 +35,7 @@ void rc_buffer_destroy(rc_buffer_t* buffer)
|
||||
{
|
||||
rc_buffer_chunk_t* next = chunk->next;
|
||||
#ifdef DEBUG_BUFFERS
|
||||
total += (int)(chunk->end - chunk->data);
|
||||
total += (int)(chunk->end - chunk->start);
|
||||
wasted += (int)(chunk->end - chunk->write);
|
||||
++count;
|
||||
#endif
|
||||
|
11
deps/rcheevos/src/rc_version.c
vendored
Normal file
11
deps/rcheevos/src/rc_version.c
vendored
Normal 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;
|
||||
}
|
17
deps/rcheevos/src/rc_version.h
vendored
17
deps/rcheevos/src/rc_version.h
vendored
@ -1,12 +1,14 @@
|
||||
#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
|
||||
#define RCHEEVOS_VERSION_MINOR 1
|
||||
#define RCHEEVOS_VERSION_PATCH 0
|
||||
|
||||
#define RCHEEVOS_MAKE_VERSION(major, minor, patch) (major * 1000000 + minor * 1000 + patch)
|
||||
@ -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 */
|
||||
|
58
deps/rcheevos/src/rcheevos/alloc.c
vendored
58
deps/rcheevos/src/rcheevos/alloc.c
vendored
@ -5,7 +5,7 @@
|
||||
|
||||
void* rc_alloc_scratch(void* pointer, int32_t* offset, uint32_t size, uint32_t alignment, rc_scratch_t* scratch, uint32_t scratch_object_pointer_offset)
|
||||
{
|
||||
rc_scratch_buffer_t* buffer;
|
||||
void* data;
|
||||
|
||||
/* if we have a real buffer, then allocate the data there */
|
||||
if (pointer)
|
||||
@ -19,49 +19,13 @@ void* rc_alloc_scratch(void* pointer, int32_t* offset, uint32_t size, uint32_t a
|
||||
}
|
||||
|
||||
/* find a scratch buffer to hold the temporary data */
|
||||
buffer = &scratch->buffer;
|
||||
do {
|
||||
const uint32_t aligned_buffer_offset = (buffer->offset + alignment - 1) & ~(alignment - 1);
|
||||
if (aligned_buffer_offset < sizeof(buffer->buffer)) {
|
||||
const uint32_t remaining = sizeof(buffer->buffer) - aligned_buffer_offset;
|
||||
|
||||
if (remaining >= size) {
|
||||
/* claim the required space from an existing buffer */
|
||||
return rc_alloc(buffer->buffer, &buffer->offset, size, alignment, NULL, -1);
|
||||
}
|
||||
}
|
||||
|
||||
if (!buffer->next)
|
||||
break;
|
||||
|
||||
buffer = buffer->next;
|
||||
} while (1);
|
||||
|
||||
/* not enough space in any existing buffer, allocate more */
|
||||
if (size > (uint32_t)sizeof(buffer->buffer)) {
|
||||
/* caller is asking for more than we can fit in a standard rc_scratch_buffer_t.
|
||||
* leverage the fact that the buffer is the last field and extend its size.
|
||||
* this chunk will be exactly large enough to hold the needed data, and since offset
|
||||
* will exceed sizeof(buffer->buffer), it will never be eligible to hold anything else.
|
||||
*/
|
||||
const size_t needed = sizeof(rc_scratch_buffer_t) - sizeof(buffer->buffer) + size;
|
||||
buffer->next = (rc_scratch_buffer_t*)malloc(needed);
|
||||
}
|
||||
else {
|
||||
buffer->next = (rc_scratch_buffer_t*)malloc(sizeof(rc_scratch_buffer_t));
|
||||
}
|
||||
|
||||
if (!buffer->next) {
|
||||
data = rc_buffer_alloc(&scratch->buffer, size);
|
||||
if (!data) {
|
||||
*offset = RC_OUT_OF_MEMORY;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
buffer = buffer->next;
|
||||
buffer->offset = 0;
|
||||
buffer->next = NULL;
|
||||
|
||||
/* claim the required space from the new buffer */
|
||||
return rc_alloc(buffer->buffer, &buffer->offset, size, alignment, NULL, -1);
|
||||
return data;
|
||||
}
|
||||
|
||||
void* rc_alloc(void* pointer, int32_t* offset, uint32_t size, uint32_t alignment, rc_scratch_t* scratch, uint32_t scratch_object_pointer_offset) {
|
||||
@ -73,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;
|
||||
@ -137,9 +101,8 @@ void rc_init_parse_state(rc_parse_state_t* parse, void* buffer, lua_State* L, in
|
||||
parse->L = L;
|
||||
parse->funcs_ndx = funcs_ndx;
|
||||
parse->buffer = buffer;
|
||||
parse->scratch.buffer.offset = 0;
|
||||
parse->scratch.buffer.next = NULL;
|
||||
parse->scratch.strings = NULL;
|
||||
rc_buffer_init(&parse->scratch.buffer);
|
||||
memset(&parse->scratch.objs, 0, sizeof(parse->scratch.objs));
|
||||
parse->first_memref = 0;
|
||||
parse->variables = 0;
|
||||
@ -151,12 +114,5 @@ void rc_init_parse_state(rc_parse_state_t* parse, void* buffer, lua_State* L, in
|
||||
|
||||
void rc_destroy_parse_state(rc_parse_state_t* parse)
|
||||
{
|
||||
rc_scratch_buffer_t* buffer = parse->scratch.buffer.next;
|
||||
rc_scratch_buffer_t* next;
|
||||
|
||||
while (buffer) {
|
||||
next = buffer->next;
|
||||
free(buffer);
|
||||
buffer = next;
|
||||
}
|
||||
rc_buffer_destroy(&parse->scratch.buffer);
|
||||
}
|
||||
|
2
deps/rcheevos/src/rcheevos/condset.c
vendored
2
deps/rcheevos/src/rcheevos/condset.c
vendored
@ -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;
|
||||
|
31
deps/rcheevos/src/rcheevos/consoleinfo.c
vendored
31
deps/rcheevos/src/rcheevos/consoleinfo.c
vendored
@ -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";
|
||||
|
||||
@ -564,6 +567,29 @@ static const rc_memory_region_t _rc_memory_regions_msx[] = {
|
||||
};
|
||||
static const rc_memory_regions_t rc_memory_regions_msx = { _rc_memory_regions_msx, 1 };
|
||||
|
||||
/* ===== MS DOS ===== */
|
||||
static const rc_memory_region_t _rc_memory_regions_ms_dos[] = {
|
||||
/* DOS emulators split the 640 KB conventional memory into two regions.
|
||||
* First the part of the conventional memory given to the running game at $000000.
|
||||
* The part of the conventional memory containing DOS and BIOS controlled memory
|
||||
* is at $100000. The length of these can vary depending on the hardware
|
||||
* and DOS version (or emulated DOS shell).
|
||||
* These first two regions will only ever total to 640 KB but the regions map
|
||||
* to 1 MB bounds to make resulting memory addresses more readable.
|
||||
* When emulating a game not under DOS (so called 'PC Booter' games), the entirety
|
||||
* of the 640 KB conventional memory block will be at $000000.
|
||||
*/
|
||||
{ 0x00000000U, 0x0009FFFFU, 0x00000000U, RC_MEMORY_TYPE_SYSTEM_RAM, "Game Conventional Memory" },
|
||||
{ 0x000A0000U, 0x000FFFFFU, 0x000A0000U, RC_MEMORY_TYPE_UNUSED, "Padding to align OS Conventional Memory" },
|
||||
{ 0x00100000U, 0x0019FFFFU, 0x00100000U, RC_MEMORY_TYPE_SYSTEM_RAM, "OS Conventional Memory" },
|
||||
{ 0x001A0000U, 0x001FFFFFU, 0x001A0000U, RC_MEMORY_TYPE_UNUSED, "Padding to align Expanded Memory" },
|
||||
/* Last is all the expanded memory which for now we map up to 64 MB which should be
|
||||
* enough for the games we want to cover. An emulator might emulate more than that.
|
||||
*/
|
||||
{ 0x00200000U, 0x041FFFFFU, 0x00200000U, RC_MEMORY_TYPE_SYSTEM_RAM, "Expanded Memory" }
|
||||
};
|
||||
static const rc_memory_regions_t rc_memory_regions_ms_dos = { _rc_memory_regions_ms_dos, 5 };
|
||||
|
||||
/* ===== Neo Geo Pocket ===== */
|
||||
/* http://neopocott.emuunlim.com/docs/tech-11.txt */
|
||||
static const rc_memory_region_t _rc_memory_regions_neo_geo_pocket[] = {
|
||||
@ -969,6 +995,9 @@ const rc_memory_regions_t* rc_console_memory_regions(uint32_t console_id)
|
||||
case RC_CONSOLE_MSX:
|
||||
return &rc_memory_regions_msx;
|
||||
|
||||
case RC_CONSOLE_MS_DOS:
|
||||
return &rc_memory_regions_ms_dos;
|
||||
|
||||
case RC_CONSOLE_NEOGEO_POCKET:
|
||||
return &rc_memory_regions_neo_geo_pocket;
|
||||
|
||||
|
74
deps/rcheevos/src/rcheevos/format.c
vendored
74
deps/rcheevos/src/rcheevos/format.c
vendored
@ -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;
|
||||
|
2
deps/rcheevos/src/rcheevos/lboard.c
vendored
2
deps/rcheevos/src/rcheevos/lboard.c
vendored
@ -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);
|
||||
|
13
deps/rcheevos/src/rcheevos/operand.c
vendored
13
deps/rcheevos/src/rcheevos/operand.c
vendored
@ -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);
|
||||
|
18
deps/rcheevos/src/rcheevos/rc_internal.h
vendored
18
deps/rcheevos/src/rcheevos/rc_internal.h
vendored
@ -2,10 +2,9 @@
|
||||
#define RC_INTERNAL_H
|
||||
|
||||
#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;
|
||||
@ -39,15 +38,8 @@ RC_ALLOW_ALIGN(char)
|
||||
/* force alignment to 4 bytes on 32-bit systems, or 8 bytes on 64-bit systems */
|
||||
#define RC_ALIGN(n) (((n) + (sizeof(void*)-1)) & ~(sizeof(void*)-1))
|
||||
|
||||
typedef struct rc_scratch_buffer {
|
||||
struct rc_scratch_buffer* next;
|
||||
int32_t offset;
|
||||
uint8_t buffer[512 - 16];
|
||||
}
|
||||
rc_scratch_buffer_t;
|
||||
|
||||
typedef struct {
|
||||
rc_scratch_buffer_t buffer;
|
||||
rc_buffer_t buffer;
|
||||
rc_scratch_string_t* strings;
|
||||
|
||||
struct objs {
|
||||
@ -200,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 */
|
||||
|
34
deps/rcheevos/src/rcheevos/richpresence.c
vendored
34
deps/rcheevos/src/rcheevos/richpresence.c
vendored
@ -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;
|
||||
|
||||
@ -279,7 +283,6 @@ static void rc_rebalance_richpresence_lookup_rebuild(rc_richpresence_lookup_item
|
||||
static void rc_rebalance_richpresence_lookup(rc_richpresence_lookup_item_t** root, rc_parse_state_t* parse)
|
||||
{
|
||||
rc_richpresence_lookup_item_t** items;
|
||||
rc_scratch_buffer_t* buffer;
|
||||
int index;
|
||||
int size;
|
||||
|
||||
@ -288,29 +291,13 @@ static void rc_rebalance_richpresence_lookup(rc_richpresence_lookup_item_t** roo
|
||||
if (count < 3)
|
||||
return;
|
||||
|
||||
/* allocate space for the flattened list - prefer scratch memory if available */
|
||||
/* allocate space for the flattened list in scratch memory */
|
||||
size = count * sizeof(rc_richpresence_lookup_item_t*);
|
||||
buffer = &parse->scratch.buffer;
|
||||
do {
|
||||
const int aligned_offset = RC_ALIGN(buffer->offset);
|
||||
const int remaining = sizeof(buffer->buffer) - aligned_offset;
|
||||
items = (rc_richpresence_lookup_item_t**)rc_buffer_alloc(&parse->scratch.buffer, size);
|
||||
|
||||
if (remaining >= size) {
|
||||
items = (rc_richpresence_lookup_item_t**)&buffer->buffer[aligned_offset];
|
||||
break;
|
||||
}
|
||||
|
||||
buffer = buffer->next;
|
||||
if (buffer == NULL) {
|
||||
/* could not find large enough block of scratch memory; allocate. if allocation fails,
|
||||
* we can still use the unbalanced tree, so just bail out */
|
||||
items = (rc_richpresence_lookup_item_t**)malloc(size);
|
||||
if (items == NULL)
|
||||
return;
|
||||
|
||||
break;
|
||||
}
|
||||
} while (1);
|
||||
/* if allocation fails, we can still use the unbalanced tree, so just bail out */
|
||||
if (items == NULL)
|
||||
return;
|
||||
|
||||
/* flatten the list */
|
||||
index = 0;
|
||||
@ -318,9 +305,6 @@ static void rc_rebalance_richpresence_lookup(rc_richpresence_lookup_item_t** roo
|
||||
|
||||
/* and rebuild it as a balanced tree */
|
||||
rc_rebalance_richpresence_lookup_rebuild(root, items, 0, count - 1);
|
||||
|
||||
if (buffer == NULL)
|
||||
free(items);
|
||||
}
|
||||
|
||||
static void rc_insert_richpresence_lookup_item(rc_richpresence_lookup_t* lookup,
|
||||
|
@ -1,7 +1,7 @@
|
||||
#include "rc_runtime.h"
|
||||
#include "rc_internal.h"
|
||||
|
||||
#include "../rc_util.h"
|
||||
#include "rc_util.h"
|
||||
#include "../rhash/md5.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
2
deps/rcheevos/src/rcheevos/value.c
vendored
2
deps/rcheevos/src/rcheevos/value.c
vendored
@ -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);
|
||||
|
480
deps/rcheevos/src/rhash/aes.c
vendored
Normal file
480
deps/rcheevos/src/rhash/aes.c
vendored
Normal file
@ -0,0 +1,480 @@
|
||||
/* This file is sourced from https://github.com/kokke/tiny-AES-c, with unused code excised.
|
||||
* This code is licensed under the Unlicense license, effectively public domain.
|
||||
* https://github.com/kokke/tiny-AES-c/blob/f06ac37/unlicense.txt
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
This is an implementation of the AES algorithm, specifically ECB, CTR and CBC mode.
|
||||
Block size can be chosen in aes.h - available choices are AES128, AES192, AES256.
|
||||
|
||||
The implementation is verified against the test vectors in:
|
||||
National Institute of Standards and Technology Special Publication 800-38A 2001 ED
|
||||
|
||||
ECB-AES128
|
||||
----------
|
||||
|
||||
plain-text:
|
||||
6bc1bee22e409f96e93d7e117393172a
|
||||
ae2d8a571e03ac9c9eb76fac45af8e51
|
||||
30c81c46a35ce411e5fbc1191a0a52ef
|
||||
f69f2445df4f9b17ad2b417be66c3710
|
||||
|
||||
key:
|
||||
2b7e151628aed2a6abf7158809cf4f3c
|
||||
|
||||
resulting cipher
|
||||
3ad77bb40d7a3660a89ecaf32466ef97
|
||||
f5d3d58503b9699de785895a96fdbaaf
|
||||
43b1cd7f598ece23881b00e3ed030688
|
||||
7b0c785e27e8ad3f8223207104725dd4
|
||||
|
||||
|
||||
NOTE: String length must be evenly divisible by 16byte (str_len % 16 == 0)
|
||||
You should pad the end of the string with zeros if this is not the case.
|
||||
For AES192/256 the key size is proportionally larger.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Includes: */
|
||||
/*****************************************************************************/
|
||||
#include <string.h> /* CBC mode, for memset */
|
||||
#include "aes.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Defines: */
|
||||
/*****************************************************************************/
|
||||
|
||||
/* The number of columns comprising a state in AES. This is a constant in AES. Value=4 */
|
||||
#define Nb 4
|
||||
|
||||
#define Nk 4 /* The number of 32 bit words in a key. */
|
||||
#define Nr 10 /* The number of rounds in AES Cipher. */
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Private variables: */
|
||||
/*****************************************************************************/
|
||||
|
||||
/* state - array holding the intermediate results during decryption. */
|
||||
typedef uint8_t state_t[4][4];
|
||||
|
||||
/* The lookup-tables are marked const so they can be placed in read-only storage instead of RAM
|
||||
* The numbers below can be computed dynamically trading ROM for RAM -
|
||||
* This can be useful in (embedded) bootloader applications, where ROM is often limited.
|
||||
*/
|
||||
static const uint8_t sbox[256] = {
|
||||
/*0 1 2 3 4 5 6 7 8 9 A B C D E F */
|
||||
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
|
||||
0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
|
||||
0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
|
||||
0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
|
||||
0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
|
||||
0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
|
||||
0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
|
||||
0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
|
||||
0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
|
||||
0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
|
||||
0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
|
||||
0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
|
||||
0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
|
||||
0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
|
||||
0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
|
||||
0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 };
|
||||
|
||||
static const uint8_t rsbox[256] = {
|
||||
0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
|
||||
0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
|
||||
0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
|
||||
0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
|
||||
0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
|
||||
0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
|
||||
0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
|
||||
0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
|
||||
0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
|
||||
0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
|
||||
0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
|
||||
0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
|
||||
0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
|
||||
0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
|
||||
0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
|
||||
0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d };
|
||||
|
||||
/* The round constant word array, Rcon[i], contains the values given by
|
||||
* x to the power (i-1) being powers of x (x is denoted as {02}) in the field GF(2^8)
|
||||
*/
|
||||
static const uint8_t Rcon[11] = {
|
||||
0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36 };
|
||||
|
||||
/*
|
||||
* Jordan Goulder points out in PR #12 (https://github.com/kokke/tiny-AES-C/pull/12),
|
||||
* that you can remove most of the elements in the Rcon array, because they are unused.
|
||||
*
|
||||
* From Wikipedia's article on the Rijndael key schedule @ https://en.wikipedia.org/wiki/Rijndael_key_schedule#Rcon
|
||||
*
|
||||
* "Only the first some of these constants are actually used – up to rcon[10] for AES-128 (as 11 round keys are needed),
|
||||
* up to rcon[8] for AES-192, up to rcon[7] for AES-256. rcon[0] is not used in AES algorithm."
|
||||
*/
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Private functions: */
|
||||
/*****************************************************************************/
|
||||
|
||||
#define getSBoxValue(num) (sbox[(num)])
|
||||
|
||||
/* This function produces Nb(Nr+1) round keys. The round keys are used in each round to decrypt the states. */
|
||||
static void KeyExpansion(uint8_t RoundKey[AES_keyExpSize], const uint8_t Key[AES_KEYLEN])
|
||||
{
|
||||
unsigned i, j, k;
|
||||
uint8_t tempa[4]; /* Used for the column/row operations */
|
||||
|
||||
/* The first round key is the key itself. */
|
||||
for (i = 0; i < Nk; ++i)
|
||||
{
|
||||
RoundKey[(i * 4) + 0] = Key[(i * 4) + 0];
|
||||
RoundKey[(i * 4) + 1] = Key[(i * 4) + 1];
|
||||
RoundKey[(i * 4) + 2] = Key[(i * 4) + 2];
|
||||
RoundKey[(i * 4) + 3] = Key[(i * 4) + 3];
|
||||
}
|
||||
|
||||
/* All other round keys are found from the previous round keys. */
|
||||
for (i = Nk; i < Nb * (Nr + 1); ++i)
|
||||
{
|
||||
{
|
||||
k = (i - 1) * 4;
|
||||
tempa[0]=RoundKey[k + 0];
|
||||
tempa[1]=RoundKey[k + 1];
|
||||
tempa[2]=RoundKey[k + 2];
|
||||
tempa[3]=RoundKey[k + 3];
|
||||
|
||||
}
|
||||
|
||||
if (i % Nk == 0)
|
||||
{
|
||||
/* This function shifts the 4 bytes in a word to the left once. */
|
||||
/* [a0,a1,a2,a3] becomes [a1,a2,a3,a0] */
|
||||
|
||||
/* Function RotWord() */
|
||||
{
|
||||
const uint8_t u8tmp = tempa[0];
|
||||
tempa[0] = tempa[1];
|
||||
tempa[1] = tempa[2];
|
||||
tempa[2] = tempa[3];
|
||||
tempa[3] = u8tmp;
|
||||
}
|
||||
|
||||
/* SubWord() is a function that takes a four-byte input word and
|
||||
* applies the S-box to each of the four bytes to produce an output word.
|
||||
*/
|
||||
|
||||
/* Function Subword() */
|
||||
{
|
||||
tempa[0] = getSBoxValue(tempa[0]);
|
||||
tempa[1] = getSBoxValue(tempa[1]);
|
||||
tempa[2] = getSBoxValue(tempa[2]);
|
||||
tempa[3] = getSBoxValue(tempa[3]);
|
||||
}
|
||||
|
||||
tempa[0] = tempa[0] ^ Rcon[i/Nk];
|
||||
}
|
||||
|
||||
j = i * 4; k=(i - Nk) * 4;
|
||||
RoundKey[j + 0] = RoundKey[k + 0] ^ tempa[0];
|
||||
RoundKey[j + 1] = RoundKey[k + 1] ^ tempa[1];
|
||||
RoundKey[j + 2] = RoundKey[k + 2] ^ tempa[2];
|
||||
RoundKey[j + 3] = RoundKey[k + 3] ^ tempa[3];
|
||||
}
|
||||
}
|
||||
|
||||
void AES_init_ctx(struct AES_ctx* ctx, const uint8_t key[AES_KEYLEN])
|
||||
{
|
||||
KeyExpansion(ctx->RoundKey, key);
|
||||
}
|
||||
|
||||
void AES_init_ctx_iv(struct AES_ctx* ctx, const uint8_t key[AES_KEYLEN], const uint8_t iv[AES_BLOCKLEN])
|
||||
{
|
||||
KeyExpansion(ctx->RoundKey, key);
|
||||
memcpy (ctx->Iv, iv, AES_BLOCKLEN);
|
||||
}
|
||||
|
||||
void AES_ctx_set_iv(struct AES_ctx* ctx, const uint8_t iv[AES_BLOCKLEN])
|
||||
{
|
||||
memcpy (ctx->Iv, iv, AES_BLOCKLEN);
|
||||
}
|
||||
|
||||
/* This function adds the round key to state.
|
||||
* The round key is added to the state by an XOR function.
|
||||
*/
|
||||
static void AddRoundKey(uint8_t round, state_t* state, const uint8_t RoundKey[AES_keyExpSize])
|
||||
{
|
||||
uint8_t i,j;
|
||||
for (i = 0; i < 4; ++i)
|
||||
{
|
||||
for (j = 0; j < 4; ++j)
|
||||
{
|
||||
(*state)[i][j] ^= RoundKey[(round * Nb * 4) + (i * Nb) + j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* The SubBytes Function Substitutes the values in the
|
||||
* state matrix with values in an S-box.
|
||||
*/
|
||||
static void SubBytes(state_t* state)
|
||||
{
|
||||
uint8_t i, j;
|
||||
for (i = 0; i < 4; ++i)
|
||||
{
|
||||
for (j = 0; j < 4; ++j)
|
||||
{
|
||||
(*state)[j][i] = getSBoxValue((*state)[j][i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* The ShiftRows() function shifts the rows in the state to the left.
|
||||
* Each row is shifted with different offset.
|
||||
* Offset = Row number. So the first row is not shifted.
|
||||
*/
|
||||
static void ShiftRows(state_t* state)
|
||||
{
|
||||
uint8_t temp;
|
||||
|
||||
/* Rotate first row 1 columns to left */
|
||||
temp = (*state)[0][1];
|
||||
(*state)[0][1] = (*state)[1][1];
|
||||
(*state)[1][1] = (*state)[2][1];
|
||||
(*state)[2][1] = (*state)[3][1];
|
||||
(*state)[3][1] = temp;
|
||||
|
||||
/* Rotate second row 2 columns to left */
|
||||
temp = (*state)[0][2];
|
||||
(*state)[0][2] = (*state)[2][2];
|
||||
(*state)[2][2] = temp;
|
||||
|
||||
temp = (*state)[1][2];
|
||||
(*state)[1][2] = (*state)[3][2];
|
||||
(*state)[3][2] = temp;
|
||||
|
||||
/* Rotate third row 3 columns to left */
|
||||
temp = (*state)[0][3];
|
||||
(*state)[0][3] = (*state)[3][3];
|
||||
(*state)[3][3] = (*state)[2][3];
|
||||
(*state)[2][3] = (*state)[1][3];
|
||||
(*state)[1][3] = temp;
|
||||
}
|
||||
|
||||
static uint8_t xtime(uint8_t x)
|
||||
{
|
||||
return ((x<<1) ^ (((x>>7) & 1) * 0x1b));
|
||||
}
|
||||
|
||||
/* MixColumns function mixes the columns of the state matrix */
|
||||
static void MixColumns(state_t* state)
|
||||
{
|
||||
uint8_t i;
|
||||
uint8_t Tmp, Tm, t;
|
||||
for (i = 0; i < 4; ++i)
|
||||
{
|
||||
t = (*state)[i][0];
|
||||
Tmp = (*state)[i][0] ^ (*state)[i][1] ^ (*state)[i][2] ^ (*state)[i][3] ;
|
||||
Tm = (*state)[i][0] ^ (*state)[i][1] ; Tm = xtime(Tm); (*state)[i][0] ^= Tm ^ Tmp ;
|
||||
Tm = (*state)[i][1] ^ (*state)[i][2] ; Tm = xtime(Tm); (*state)[i][1] ^= Tm ^ Tmp ;
|
||||
Tm = (*state)[i][2] ^ (*state)[i][3] ; Tm = xtime(Tm); (*state)[i][2] ^= Tm ^ Tmp ;
|
||||
Tm = (*state)[i][3] ^ t ; Tm = xtime(Tm); (*state)[i][3] ^= Tm ^ Tmp ;
|
||||
}
|
||||
}
|
||||
|
||||
/* Multiply is used to multiply numbers in the field GF(2^8)
|
||||
* Note: The last call to xtime() is unneeded, but often ends up generating a smaller binary
|
||||
* The compiler seems to be able to vectorize the operation better this way.
|
||||
* See https://github.com/kokke/tiny-AES-c/pull/34
|
||||
*/
|
||||
|
||||
#define Multiply(x, y) \
|
||||
( ((y & 1) * x) ^ \
|
||||
((y>>1 & 1) * xtime(x)) ^ \
|
||||
((y>>2 & 1) * xtime(xtime(x))) ^ \
|
||||
((y>>3 & 1) * xtime(xtime(xtime(x)))) ^ \
|
||||
((y>>4 & 1) * xtime(xtime(xtime(xtime(x)))))) \
|
||||
|
||||
#define getSBoxInvert(num) (rsbox[(num)])
|
||||
|
||||
/* MixColumns function mixes the columns of the state matrix.
|
||||
* The method used to multiply may be difficult to understand for the inexperienced.
|
||||
* Please use the references to gain more information.
|
||||
*/
|
||||
static void InvMixColumns(state_t* state)
|
||||
{
|
||||
int i;
|
||||
uint8_t a, b, c, d;
|
||||
for (i = 0; i < 4; ++i)
|
||||
{
|
||||
a = (*state)[i][0];
|
||||
b = (*state)[i][1];
|
||||
c = (*state)[i][2];
|
||||
d = (*state)[i][3];
|
||||
|
||||
(*state)[i][0] = Multiply(a, 0x0e) ^ Multiply(b, 0x0b) ^ Multiply(c, 0x0d) ^ Multiply(d, 0x09);
|
||||
(*state)[i][1] = Multiply(a, 0x09) ^ Multiply(b, 0x0e) ^ Multiply(c, 0x0b) ^ Multiply(d, 0x0d);
|
||||
(*state)[i][2] = Multiply(a, 0x0d) ^ Multiply(b, 0x09) ^ Multiply(c, 0x0e) ^ Multiply(d, 0x0b);
|
||||
(*state)[i][3] = Multiply(a, 0x0b) ^ Multiply(b, 0x0d) ^ Multiply(c, 0x09) ^ Multiply(d, 0x0e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* The SubBytes Function Substitutes the values in the
|
||||
* state matrix with values in an S-box.
|
||||
*/
|
||||
static void InvSubBytes(state_t* state)
|
||||
{
|
||||
uint8_t i, j;
|
||||
for (i = 0; i < 4; ++i)
|
||||
{
|
||||
for (j = 0; j < 4; ++j)
|
||||
{
|
||||
(*state)[j][i] = getSBoxInvert((*state)[j][i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void InvShiftRows(state_t* state)
|
||||
{
|
||||
uint8_t temp;
|
||||
|
||||
/* Rotate first row 1 columns to right */
|
||||
temp = (*state)[3][1];
|
||||
(*state)[3][1] = (*state)[2][1];
|
||||
(*state)[2][1] = (*state)[1][1];
|
||||
(*state)[1][1] = (*state)[0][1];
|
||||
(*state)[0][1] = temp;
|
||||
|
||||
/* Rotate second row 2 columns to right */
|
||||
temp = (*state)[0][2];
|
||||
(*state)[0][2] = (*state)[2][2];
|
||||
(*state)[2][2] = temp;
|
||||
|
||||
temp = (*state)[1][2];
|
||||
(*state)[1][2] = (*state)[3][2];
|
||||
(*state)[3][2] = temp;
|
||||
|
||||
/* Rotate third row 3 columns to right */
|
||||
temp = (*state)[0][3];
|
||||
(*state)[0][3] = (*state)[1][3];
|
||||
(*state)[1][3] = (*state)[2][3];
|
||||
(*state)[2][3] = (*state)[3][3];
|
||||
(*state)[3][3] = temp;
|
||||
}
|
||||
|
||||
/* Cipher is the main function that encrypts the PlainText. */
|
||||
static void Cipher(state_t* state, const uint8_t RoundKey[AES_keyExpSize])
|
||||
{
|
||||
uint8_t round = 0;
|
||||
|
||||
/* Add the First round key to the state before starting the rounds. */
|
||||
AddRoundKey(0, state, RoundKey);
|
||||
|
||||
/* There will be Nr rounds.
|
||||
* The first Nr-1 rounds are identical.
|
||||
* These Nr rounds are executed in the loop below.
|
||||
* Last one without MixColumns()
|
||||
*/
|
||||
for (round = 1; ; ++round)
|
||||
{
|
||||
SubBytes(state);
|
||||
ShiftRows(state);
|
||||
if (round == Nr) {
|
||||
break;
|
||||
}
|
||||
MixColumns(state);
|
||||
AddRoundKey(round, state, RoundKey);
|
||||
}
|
||||
/* Add round key to last round */
|
||||
AddRoundKey(Nr, state, RoundKey);
|
||||
}
|
||||
|
||||
static void InvCipher(state_t* state, const uint8_t RoundKey[AES_keyExpSize])
|
||||
{
|
||||
uint8_t round = 0;
|
||||
|
||||
/* Add the First round key to the state before starting the rounds. */
|
||||
AddRoundKey(Nr, state, RoundKey);
|
||||
|
||||
/* There will be Nr rounds.
|
||||
* The first Nr-1 rounds are identical.
|
||||
* These Nr rounds are executed in the loop below.
|
||||
* Last one without InvMixColumn()
|
||||
*/
|
||||
for (round = (Nr - 1); ; --round)
|
||||
{
|
||||
InvShiftRows(state);
|
||||
InvSubBytes(state);
|
||||
AddRoundKey(round, state, RoundKey);
|
||||
if (round == 0) {
|
||||
break;
|
||||
}
|
||||
InvMixColumns(state);
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Public functions: */
|
||||
/*****************************************************************************/
|
||||
|
||||
static void XorWithIv(uint8_t* buf, const uint8_t Iv[AES_BLOCKLEN])
|
||||
{
|
||||
uint8_t i;
|
||||
for (i = 0; i < AES_BLOCKLEN; ++i) /* The block in AES is always 128bit no matter the key size */
|
||||
{
|
||||
buf[i] ^= Iv[i];
|
||||
}
|
||||
}
|
||||
|
||||
void AES_CBC_decrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, size_t length)
|
||||
{
|
||||
size_t i;
|
||||
uint8_t storeNextIv[AES_BLOCKLEN];
|
||||
for (i = 0; i < length; i += AES_BLOCKLEN)
|
||||
{
|
||||
memcpy(storeNextIv, buf, AES_BLOCKLEN);
|
||||
InvCipher((state_t*)buf, ctx->RoundKey);
|
||||
XorWithIv(buf, ctx->Iv);
|
||||
memcpy(ctx->Iv, storeNextIv, AES_BLOCKLEN);
|
||||
buf += AES_BLOCKLEN;
|
||||
}
|
||||
}
|
||||
|
||||
/* Symmetrical operation: same function for encrypting as for decrypting. Note any IV/nonce should never be reused with the same key */
|
||||
void AES_CTR_xcrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, size_t length)
|
||||
{
|
||||
uint8_t buffer[AES_BLOCKLEN];
|
||||
|
||||
size_t i;
|
||||
int bi;
|
||||
for (i = 0, bi = AES_BLOCKLEN; i < length; ++i, ++bi)
|
||||
{
|
||||
if (bi == AES_BLOCKLEN) /* we need to regen xor compliment in buffer */
|
||||
{
|
||||
memcpy(buffer, ctx->Iv, AES_BLOCKLEN);
|
||||
Cipher((state_t*)buffer, ctx->RoundKey);
|
||||
|
||||
/* Increment Iv and handle overflow */
|
||||
for (bi = (AES_BLOCKLEN - 1); bi >= 0; --bi)
|
||||
{
|
||||
/* inc will overflow */
|
||||
if (ctx->Iv[bi] == 255)
|
||||
{
|
||||
ctx->Iv[bi] = 0;
|
||||
continue;
|
||||
}
|
||||
ctx->Iv[bi] += 1;
|
||||
break;
|
||||
}
|
||||
bi = 0;
|
||||
}
|
||||
|
||||
buf[i] = (buf[i] ^ buffer[bi]);
|
||||
}
|
||||
}
|
49
deps/rcheevos/src/rhash/aes.h
vendored
Normal file
49
deps/rcheevos/src/rhash/aes.h
vendored
Normal file
@ -0,0 +1,49 @@
|
||||
#ifndef AES_H
|
||||
#define AES_H
|
||||
|
||||
/* This file is sourced from https://github.com/kokke/tiny-AES-c, with unused code excised.
|
||||
* This code is licensed under the Unlicense license, effectively public domain.
|
||||
* https://github.com/kokke/tiny-AES-c/blob/f06ac37/unlicense.txt
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#define AES_BLOCKLEN 16 /* Block length in bytes - AES is 128b block only */
|
||||
#define AES_KEYLEN 16 /* Key length in bytes */
|
||||
#define AES_keyExpSize 176
|
||||
|
||||
struct AES_ctx
|
||||
{
|
||||
uint8_t RoundKey[AES_keyExpSize];
|
||||
uint8_t Iv[AES_BLOCKLEN];
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void AES_init_ctx(struct AES_ctx* ctx, const uint8_t key[AES_KEYLEN]);
|
||||
void AES_init_ctx_iv(struct AES_ctx* ctx, const uint8_t key[AES_KEYLEN], const uint8_t iv[AES_BLOCKLEN]);
|
||||
void AES_ctx_set_iv(struct AES_ctx* ctx, const uint8_t iv[AES_BLOCKLEN]);
|
||||
|
||||
/* buffer size MUST be mutile of AES_BLOCKLEN;
|
||||
* Suggest https://en.wikipedia.org/wiki/Padding_(cryptography)#PKCS7 for padding scheme
|
||||
* NOTES: you need to set IV in ctx via AES_init_ctx_iv() or AES_ctx_set_iv()
|
||||
* no IV should ever be reused with the same key
|
||||
*/
|
||||
void AES_CBC_decrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, size_t length);
|
||||
|
||||
/* Same function for encrypting as for decrypting.
|
||||
* IV is incremented for every block, and used after encryption as XOR-compliment for output
|
||||
* Suggesting https://en.wikipedia.org/wiki/Padding_(cryptography)#PKCS7 for padding scheme
|
||||
* NOTES: you need to set IV in ctx with AES_init_ctx_iv() or AES_ctx_set_iv()
|
||||
* no IV should ever be reused with the same key
|
||||
*/
|
||||
void AES_CTR_xcrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, size_t length);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* AES_H */
|
1006
deps/rcheevos/src/rhash/hash.c
vendored
1006
deps/rcheevos/src/rhash/hash.c
vendored
File diff suppressed because it is too large
Load Diff
@ -223,6 +223,7 @@ ACHIEVEMENTS
|
||||
#include "../deps/rcheevos/src/rcheevos/runtime_progress.c"
|
||||
#include "../deps/rcheevos/src/rcheevos/trigger.c"
|
||||
#include "../deps/rcheevos/src/rcheevos/value.c"
|
||||
#include "../deps/rcheevos/src/rhash/aes.c"
|
||||
#include "../deps/rcheevos/src/rhash/cdreader.c"
|
||||
#include "../deps/rcheevos/src/rhash/hash.c"
|
||||
|
||||
|
23
runloop.c
23
runloop.c
@ -6247,22 +6247,23 @@ static enum runloop_state_enum runloop_check_state(
|
||||
#ifdef HAVE_CHEEVOS
|
||||
if (cheevos_hardcore_active)
|
||||
{
|
||||
static int unpaused_frames = 0;
|
||||
|
||||
if (runloop_st->flags & RUNLOOP_FLAG_PAUSED)
|
||||
unpaused_frames = 0;
|
||||
else
|
||||
/* Frame advance is not allowed when achievement hardcore is active */
|
||||
if (!(runloop_st->flags & RUNLOOP_FLAG_PAUSED))
|
||||
{
|
||||
/* Limit pause to approximately three times per second (depending on core framerate) */
|
||||
if (unpaused_frames < 20)
|
||||
/* In hardcore mode, the user is only allowed to pause infrequently. */
|
||||
if ((pause_pressed && !old_pause_pressed) ||
|
||||
(!focused && old_focus && pause_nonactive))
|
||||
{
|
||||
++unpaused_frames;
|
||||
pause_pressed = false;
|
||||
/* If the user is trying to pause, check to see if it's allowed. */
|
||||
if (!rcheevos_is_pause_allowed())
|
||||
{
|
||||
pause_pressed = false;
|
||||
if (pause_nonactive)
|
||||
focused = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
else /* frame advance not allowed in hardcore */
|
||||
#endif
|
||||
{
|
||||
frameadvance_pressed = BIT256_GET(current_bits, RARCH_FRAMEADVANCE);
|
||||
|
Loading…
x
Reference in New Issue
Block a user