mirror of
https://github.com/PCSX2/pcsx2.git
synced 2025-12-16 04:08:48 +00:00
3rdparty: Update rcheevos to commit 0a7508d
This commit is contained in:
parent
535ebdbc8c
commit
24cb93d7c5
3
3rdparty/rcheevos/CMakeLists.txt
vendored
3
3rdparty/rcheevos/CMakeLists.txt
vendored
@ -11,7 +11,6 @@ add_library(rcheevos
|
||||
include/rc_hash.h
|
||||
include/rc_runtime.h
|
||||
include/rc_runtime_types.h
|
||||
include/rc_url.h
|
||||
include/rc_util.h
|
||||
src/rapi/rc_api_common.c
|
||||
src/rapi/rc_api_common.h
|
||||
@ -47,5 +46,5 @@ add_library(rcheevos
|
||||
|
||||
target_include_directories(rcheevos PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/include")
|
||||
target_include_directories(rcheevos INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}/include")
|
||||
target_compile_definitions(rcheevos PRIVATE "RC_DISABLE_LUA=1" "RCHEEVOS_URL_SSL=1" "RC_NO_THREADS=1" "RC_HASH_NO_DISC" "RC_HASH_NO_ENCRYPTED" "RC_HASH_NO_ROM" "RC_HASH_NO_ZIP")
|
||||
target_compile_definitions(rcheevos PRIVATE "RC_NO_THREADS=1" "RC_HASH_NO_DISC" "RC_HASH_NO_ENCRYPTED" "RC_HASH_NO_ROM" "RC_HASH_NO_ZIP")
|
||||
|
||||
|
||||
31
3rdparty/rcheevos/include/rc_api_editor.h
vendored
31
3rdparty/rcheevos/include/rc_api_editor.h
vendored
@ -186,6 +186,37 @@ RC_EXPORT int RC_CCONV rc_api_process_update_leaderboard_response(rc_api_update_
|
||||
RC_EXPORT int RC_CCONV rc_api_process_update_leaderboard_server_response(rc_api_update_leaderboard_response_t* response, const rc_api_server_response_t* server_response);
|
||||
RC_EXPORT void RC_CCONV rc_api_destroy_update_leaderboard_response(rc_api_update_leaderboard_response_t* response);
|
||||
|
||||
/* --- Update Rich Presence --- */
|
||||
|
||||
/**
|
||||
* API parameters for an update rich presence request.
|
||||
*/
|
||||
typedef struct rc_api_update_rich_presence_request_t {
|
||||
/* The username of the developer */
|
||||
const char* username;
|
||||
/* The API token from the login request */
|
||||
const char* api_token;
|
||||
/* The unique identifier of the game */
|
||||
uint32_t game_id;
|
||||
/* The script for the rich_presence */
|
||||
const char* script;
|
||||
}
|
||||
rc_api_update_rich_presence_request_t;
|
||||
|
||||
/**
|
||||
* Response data for an update rich presence request.
|
||||
*/
|
||||
typedef struct rc_api_update_rich_presence_response_t {
|
||||
/* Common server-provided response information */
|
||||
rc_api_response_t response;
|
||||
}
|
||||
rc_api_update_rich_presence_response_t;
|
||||
|
||||
RC_EXPORT int RC_CCONV rc_api_init_update_rich_presence_request(rc_api_request_t* request, const rc_api_update_rich_presence_request_t* api_params);
|
||||
RC_EXPORT int RC_CCONV rc_api_init_update_rich_presence_request_hosted(rc_api_request_t* request, const rc_api_update_rich_presence_request_t* api_params, const rc_api_host_t* host);
|
||||
RC_EXPORT int RC_CCONV rc_api_process_update_rich_presence_server_response(rc_api_update_rich_presence_response_t* response, const rc_api_server_response_t* server_response);
|
||||
RC_EXPORT void RC_CCONV rc_api_destroy_update_rich_presence_response(rc_api_update_rich_presence_response_t* response);
|
||||
|
||||
/* --- Fetch Badge Range --- */
|
||||
|
||||
/**
|
||||
|
||||
8
3rdparty/rcheevos/include/rc_client.h
vendored
8
3rdparty/rcheevos/include/rc_client.h
vendored
@ -211,6 +211,10 @@ typedef struct rc_client_user_game_summary_t {
|
||||
|
||||
uint32_t points_core;
|
||||
uint32_t points_unlocked;
|
||||
|
||||
/* minimum version: 12.1 */
|
||||
time_t beaten_time;
|
||||
time_t completed_time;
|
||||
} rc_client_user_game_summary_t;
|
||||
|
||||
/**
|
||||
@ -358,6 +362,8 @@ typedef struct rc_client_subset_t {
|
||||
|
||||
RC_EXPORT const rc_client_subset_t* RC_CCONV rc_client_get_subset_info(rc_client_t* client, uint32_t subset_id);
|
||||
|
||||
RC_EXPORT void RC_CCONV rc_client_get_user_subset_summary(const rc_client_t* client, uint32_t subset_id, rc_client_user_game_summary_t* summary);
|
||||
|
||||
/*****************************************************************************\
|
||||
| Fetch Game Hashes |
|
||||
\*****************************************************************************/
|
||||
@ -582,7 +588,7 @@ enum {
|
||||
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.
|
||||
* Destroys a list allocated by rc_client_create_leaderboard_list.
|
||||
*/
|
||||
RC_EXPORT void RC_CCONV rc_client_destroy_leaderboard_list(rc_client_leaderboard_list_t* list);
|
||||
|
||||
|
||||
2
3rdparty/rcheevos/include/rc_export.h
vendored
2
3rdparty/rcheevos/include/rc_export.h
vendored
@ -37,7 +37,7 @@
|
||||
* #endif
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if defined(__cplusplus) && !defined(CXX_BUILD)
|
||||
#define RC_BEGIN_C_DECLS extern "C" {
|
||||
#define RC_END_C_DECLS }
|
||||
#else
|
||||
|
||||
1
3rdparty/rcheevos/include/rc_hash.h
vendored
1
3rdparty/rcheevos/include/rc_hash.h
vendored
@ -154,6 +154,7 @@ typedef struct rc_hash_iterator {
|
||||
uint8_t consoles[12];
|
||||
int index;
|
||||
const char* path;
|
||||
void* userdata;
|
||||
|
||||
rc_hash_callbacks_t callbacks;
|
||||
} rc_hash_iterator_t;
|
||||
|
||||
36
3rdparty/rcheevos/include/rc_url.h
vendored
36
3rdparty/rcheevos/include/rc_url.h
vendored
@ -1,36 +0,0 @@
|
||||
#ifndef RC_URL_H
|
||||
#define RC_URL_H
|
||||
|
||||
#include "rc_export.h"
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
RC_BEGIN_C_DECLS
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
RC_EXPORT int RC_CCONV rc_url_get_gameid(char* buffer, size_t size, const char* hash);
|
||||
|
||||
RC_EXPORT int RC_CCONV 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_badge_image(char* buffer, size_t size, const char* badge_name);
|
||||
|
||||
RC_EXPORT int RC_CCONV 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_token(char* buffer, size_t size, const char* user_name, const char* login_token);
|
||||
|
||||
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);
|
||||
|
||||
RC_EXPORT int RC_CCONV 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_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_END_C_DECLS
|
||||
|
||||
#endif /* RC_URL_H */
|
||||
6
3rdparty/rcheevos/src/rapi/rc_api_common.c
vendored
6
3rdparty/rcheevos/src/rapi/rc_api_common.c
vendored
@ -273,17 +273,17 @@ static int rc_json_extract_html_error(rc_api_response_t* response, const rc_api_
|
||||
iterator.json = server_response->body;
|
||||
iterator.end = server_response->body + server_response->body_length;
|
||||
|
||||
/* if the title contains an HTTP status code(i.e "404 Not Found"), return the title */
|
||||
/* assume the title contains the most appropriate message to display to the user */
|
||||
if (rc_json_find_substring(&iterator, "<title>")) {
|
||||
const char* title_start = iterator.json + 7;
|
||||
if (isdigit((int)*title_start) && rc_json_find_substring(&iterator, "</title>")) {
|
||||
if (rc_json_find_substring(&iterator, "</title>")) {
|
||||
response->error_message = rc_buffer_strncpy(&response->buffer, title_start, iterator.json - title_start);
|
||||
response->succeeded = 0;
|
||||
return RC_INVALID_JSON;
|
||||
}
|
||||
}
|
||||
|
||||
/* title not found, or did not start with an error code, return the first line of the response */
|
||||
/* title not found, return the first line of the response (up to 200 characters) */
|
||||
iterator.json = server_response->body;
|
||||
|
||||
while (iterator.json < iterator.end && *iterator.json != '\n' &&
|
||||
|
||||
56
3rdparty/rcheevos/src/rapi/rc_api_editor.c
vendored
56
3rdparty/rcheevos/src/rapi/rc_api_editor.c
vendored
@ -100,7 +100,7 @@ int rc_api_process_fetch_code_notes_server_response(rc_api_fetch_code_notes_resp
|
||||
|
||||
if (!rc_json_get_required_string(&address_str, &response->response, ¬e_fields[0], "Address"))
|
||||
return RC_MISSING_VALUE;
|
||||
note->address = (unsigned)strtol(address_str, NULL, 16);
|
||||
note->address = (uint32_t)strtoul(address_str, NULL, 16);
|
||||
if (!rc_json_get_required_string(¬e->note, &response->response, ¬e_fields[2], "Note"))
|
||||
return RC_MISSING_VALUE;
|
||||
|
||||
@ -419,6 +419,60 @@ void rc_api_destroy_update_leaderboard_response(rc_api_update_leaderboard_respon
|
||||
rc_buffer_destroy(&response->response.buffer);
|
||||
}
|
||||
|
||||
/* --- Update Rich Presence --- */
|
||||
|
||||
int rc_api_init_update_rich_presence_request(rc_api_request_t* request, const rc_api_update_rich_presence_request_t* api_params) {
|
||||
return rc_api_init_update_rich_presence_request_hosted(request, api_params, &g_host);
|
||||
}
|
||||
|
||||
int rc_api_init_update_rich_presence_request_hosted(rc_api_request_t* request,
|
||||
const rc_api_update_rich_presence_request_t* api_params,
|
||||
const rc_api_host_t* host) {
|
||||
rc_api_url_builder_t builder;
|
||||
|
||||
rc_api_url_build_dorequest_url(request, host);
|
||||
|
||||
if (api_params->game_id == 0)
|
||||
return RC_INVALID_STATE;
|
||||
if (!api_params->script)
|
||||
return RC_INVALID_STATE;
|
||||
|
||||
rc_url_builder_init(&builder, &request->buffer, 128);
|
||||
if (!rc_api_url_build_dorequest(&builder, "submitrichpresence", api_params->username, api_params->api_token))
|
||||
return builder.result;
|
||||
|
||||
rc_url_builder_append_unum_param(&builder, "g", api_params->game_id);
|
||||
rc_url_builder_append_str_param(&builder, "d", api_params->script);
|
||||
|
||||
request->post_data = rc_url_builder_finalize(&builder);
|
||||
request->content_type = RC_CONTENT_TYPE_URLENCODED;
|
||||
|
||||
return builder.result;
|
||||
}
|
||||
|
||||
int rc_api_process_update_rich_presence_server_response(rc_api_update_rich_presence_response_t* response, const rc_api_server_response_t* server_response) {
|
||||
int result;
|
||||
|
||||
rc_json_field_t fields[] = {
|
||||
RC_JSON_NEW_FIELD("Success"),
|
||||
RC_JSON_NEW_FIELD("Error"),
|
||||
RC_JSON_NEW_FIELD("Code"),
|
||||
};
|
||||
|
||||
memset(response, 0, sizeof(*response));
|
||||
rc_buffer_init(&response->response.buffer);
|
||||
|
||||
result = rc_json_parse_server_response(&response->response, server_response, fields, sizeof(fields) / sizeof(fields[0]));
|
||||
if (result != RC_OK || !response->response.succeeded)
|
||||
return result;
|
||||
|
||||
return RC_OK;
|
||||
}
|
||||
|
||||
void rc_api_destroy_update_rich_presence_response(rc_api_update_rich_presence_response_t* response) {
|
||||
rc_buffer_destroy(&response->response.buffer);
|
||||
}
|
||||
|
||||
/* --- Fetch Badge Range --- */
|
||||
|
||||
int rc_api_init_fetch_badge_range_request(rc_api_request_t* request, const rc_api_fetch_badge_range_request_t* api_params) {
|
||||
|
||||
184
3rdparty/rcheevos/src/rc_client.c
vendored
184
3rdparty/rcheevos/src/rc_client.c
vendored
@ -905,11 +905,22 @@ int rc_client_user_get_image_url(const rc_client_user_t* user, char buffer[], si
|
||||
return rc_client_get_image_url(buffer, buffer_size, RC_IMAGE_TYPE_USER, user->display_name);
|
||||
}
|
||||
|
||||
static void rc_client_subset_get_user_game_summary(const rc_client_subset_info_t* subset,
|
||||
rc_client_user_game_summary_t* summary, const uint8_t unlock_bit)
|
||||
static void rc_client_subset_get_user_game_summary(const rc_client_t* client,
|
||||
const rc_client_subset_info_t* subset, rc_client_user_game_summary_t* summary)
|
||||
{
|
||||
rc_client_achievement_info_t* achievement = subset->achievements;
|
||||
rc_client_achievement_info_t* stop = achievement + subset->public_.num_achievements;
|
||||
time_t last_unlock_time = 0;
|
||||
time_t last_progression_time = 0;
|
||||
time_t first_win_time = 0;
|
||||
int num_progression_achievements = 0;
|
||||
int num_win_achievements = 0;
|
||||
int num_unlocked_progression_achievements = 0;
|
||||
const uint8_t unlock_bit = (client->state.hardcore) ?
|
||||
RC_CLIENT_ACHIEVEMENT_UNLOCKED_HARDCORE : RC_CLIENT_ACHIEVEMENT_UNLOCKED_SOFTCORE;
|
||||
|
||||
rc_mutex_lock((rc_mutex_t*)&client->state.mutex); /* remove const cast for mutex access */
|
||||
|
||||
for (; achievement < stop; ++achievement) {
|
||||
switch (achievement->public_.category) {
|
||||
case RC_CLIENT_ACHIEVEMENT_CATEGORY_CORE:
|
||||
@ -919,10 +930,28 @@ static void rc_client_subset_get_user_game_summary(const rc_client_subset_info_t
|
||||
if (achievement->public_.unlocked & unlock_bit) {
|
||||
++summary->num_unlocked_achievements;
|
||||
summary->points_unlocked += achievement->public_.points;
|
||||
|
||||
if (achievement->public_.unlock_time > last_unlock_time)
|
||||
last_unlock_time = achievement->public_.unlock_time;
|
||||
|
||||
if (achievement->public_.type == RC_CLIENT_ACHIEVEMENT_TYPE_PROGRESSION) {
|
||||
++num_unlocked_progression_achievements;
|
||||
if (achievement->public_.unlock_time > last_progression_time)
|
||||
last_progression_time = achievement->public_.unlock_time;
|
||||
}
|
||||
else if (achievement->public_.type == RC_CLIENT_ACHIEVEMENT_TYPE_WIN) {
|
||||
if (first_win_time == 0 || achievement->public_.unlock_time < first_win_time)
|
||||
first_win_time = achievement->public_.unlock_time;
|
||||
}
|
||||
}
|
||||
if (achievement->public_.bucket == RC_CLIENT_ACHIEVEMENT_BUCKET_UNSUPPORTED) {
|
||||
|
||||
if (achievement->public_.type == RC_CLIENT_ACHIEVEMENT_TYPE_PROGRESSION)
|
||||
++num_progression_achievements;
|
||||
else if (achievement->public_.type == RC_CLIENT_ACHIEVEMENT_TYPE_WIN)
|
||||
++num_win_achievements;
|
||||
|
||||
if (achievement->public_.bucket == RC_CLIENT_ACHIEVEMENT_BUCKET_UNSUPPORTED)
|
||||
++summary->num_unsupported_achievements;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
@ -934,13 +963,18 @@ static void rc_client_subset_get_user_game_summary(const rc_client_subset_info_t
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
rc_mutex_unlock((rc_mutex_t*)&client->state.mutex); /* remove const cast for mutex access */
|
||||
|
||||
if (summary->num_unlocked_achievements == summary->num_core_achievements)
|
||||
summary->completed_time = last_unlock_time;
|
||||
|
||||
if ((first_win_time || num_win_achievements == 0) && num_unlocked_progression_achievements == num_progression_achievements)
|
||||
summary->beaten_time = (first_win_time > last_progression_time) ? first_win_time : last_progression_time;
|
||||
}
|
||||
|
||||
void rc_client_get_user_game_summary(const rc_client_t* client, rc_client_user_game_summary_t* summary)
|
||||
{
|
||||
const uint8_t unlock_bit = (client->state.hardcore) ?
|
||||
RC_CLIENT_ACHIEVEMENT_UNLOCKED_HARDCORE : RC_CLIENT_ACHIEVEMENT_UNLOCKED_SOFTCORE;
|
||||
|
||||
if (!summary)
|
||||
return;
|
||||
|
||||
@ -949,20 +983,47 @@ void rc_client_get_user_game_summary(const rc_client_t* client, rc_client_user_g
|
||||
return;
|
||||
|
||||
#ifdef RC_CLIENT_SUPPORTS_EXTERNAL
|
||||
if (client->state.external_client && client->state.external_client->get_user_game_summary) {
|
||||
client->state.external_client->get_user_game_summary(summary);
|
||||
if (client->state.external_client) {
|
||||
if (client->state.external_client->get_user_game_summary_v5) {
|
||||
client->state.external_client->get_user_game_summary_v5(summary);
|
||||
return;
|
||||
}
|
||||
if (client->state.external_client->get_user_game_summary) {
|
||||
client->state.external_client->get_user_game_summary(summary);
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (rc_client_is_game_loaded(client))
|
||||
rc_client_subset_get_user_game_summary(client, client->game->subsets, summary);
|
||||
}
|
||||
|
||||
void rc_client_get_user_subset_summary(const rc_client_t* client, uint32_t subset_id, rc_client_user_game_summary_t* summary)
|
||||
{
|
||||
if (!summary)
|
||||
return;
|
||||
|
||||
memset(summary, 0, sizeof(*summary));
|
||||
if (!client || !subset_id)
|
||||
return;
|
||||
|
||||
#ifdef RC_CLIENT_SUPPORTS_EXTERNAL
|
||||
if (client->state.external_client && client->state.external_client->get_user_subset_summary) {
|
||||
client->state.external_client->get_user_subset_summary(subset_id, summary);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!rc_client_is_game_loaded(client))
|
||||
return;
|
||||
|
||||
rc_mutex_lock((rc_mutex_t*)&client->state.mutex); /* remove const cast for mutex access */
|
||||
|
||||
rc_client_subset_get_user_game_summary(client->game->subsets, summary, unlock_bit);
|
||||
|
||||
rc_mutex_unlock((rc_mutex_t*)&client->state.mutex); /* remove const cast for mutex access */
|
||||
if (rc_client_is_game_loaded(client)) {
|
||||
const rc_client_subset_info_t* subset = client->game->subsets;
|
||||
for (; subset; subset = subset->next) {
|
||||
if (subset->public_.id == subset_id) {
|
||||
rc_client_subset_get_user_game_summary(client, subset, summary);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct rc_client_fetch_all_user_progress_callback_data_t {
|
||||
@ -1376,29 +1437,34 @@ static uint32_t rc_client_subset_toggle_hardcore_achievements(rc_client_subset_i
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (achievement->public_.state == RC_CLIENT_ACHIEVEMENT_STATE_ACTIVE ||
|
||||
achievement->public_.state == RC_CLIENT_ACHIEVEMENT_STATE_INACTIVE) {
|
||||
|
||||
/* if it's active despite being unlocked, and we're in encore mode, leave it active */
|
||||
if (client->state.encore_mode) {
|
||||
++active_count;
|
||||
continue;
|
||||
}
|
||||
|
||||
achievement->public_.state = RC_CLIENT_ACHIEVEMENT_STATE_UNLOCKED;
|
||||
else {
|
||||
achievement->public_.unlock_time = (active_bit == RC_CLIENT_ACHIEVEMENT_UNLOCKED_HARDCORE) ?
|
||||
achievement->unlock_time_hardcore : achievement->unlock_time_softcore;
|
||||
achievement->unlock_time_hardcore : achievement->unlock_time_softcore;
|
||||
|
||||
if (achievement->trigger && achievement->trigger->state == RC_TRIGGER_STATE_PRIMED) {
|
||||
rc_client_event_t client_event;
|
||||
memset(&client_event, 0, sizeof(client_event));
|
||||
client_event.type = RC_CLIENT_EVENT_ACHIEVEMENT_CHALLENGE_INDICATOR_HIDE;
|
||||
client_event.achievement = &achievement->public_;
|
||||
client->callbacks.event_handler(&client_event, client);
|
||||
if (achievement->public_.state == RC_CLIENT_ACHIEVEMENT_STATE_ACTIVE ||
|
||||
achievement->public_.state == RC_CLIENT_ACHIEVEMENT_STATE_INACTIVE) {
|
||||
/* if it's active despite being unlocked, and we're in encore mode, leave it active */
|
||||
if (client->state.encore_mode) {
|
||||
++active_count;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* switch to inactive */
|
||||
achievement->public_.state = RC_CLIENT_ACHIEVEMENT_STATE_UNLOCKED;
|
||||
|
||||
if (achievement->trigger && rc_trigger_state_active(achievement->trigger->state)) {
|
||||
/* hide any active challenge indicators */
|
||||
if (achievement->trigger->state == RC_TRIGGER_STATE_PRIMED) {
|
||||
rc_client_event_t client_event;
|
||||
memset(&client_event, 0, sizeof(client_event));
|
||||
client_event.type = RC_CLIENT_EVENT_ACHIEVEMENT_CHALLENGE_INDICATOR_HIDE;
|
||||
client_event.achievement = &achievement->public_;
|
||||
client->callbacks.event_handler(&client_event, client);
|
||||
}
|
||||
|
||||
achievement->trigger->state = RC_TRIGGER_STATE_TRIGGERED;
|
||||
}
|
||||
}
|
||||
|
||||
if (achievement->trigger && rc_trigger_state_active(achievement->trigger->state))
|
||||
achievement->trigger->state = RC_TRIGGER_STATE_TRIGGERED;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1728,7 +1794,9 @@ static void rc_client_activate_game(rc_client_load_state_t* load_state, rc_api_s
|
||||
if (load_state->hash->hash[0] != '[') {
|
||||
if (load_state->client->state.spectator_mode != RC_CLIENT_SPECTATOR_MODE_LOCKED) {
|
||||
/* schedule the periodic ping */
|
||||
rc_client_scheduled_callback_data_t* callback_data = rc_buffer_alloc(&load_state->game->buffer, sizeof(rc_client_scheduled_callback_data_t));
|
||||
rc_client_scheduled_callback_data_t* callback_data = (rc_client_scheduled_callback_data_t*)
|
||||
rc_buffer_alloc(&load_state->game->buffer, sizeof(rc_client_scheduled_callback_data_t));
|
||||
|
||||
memset(callback_data, 0, sizeof(*callback_data));
|
||||
callback_data->callback = rc_client_ping;
|
||||
callback_data->related_id = load_state->game->public_.id;
|
||||
@ -1768,7 +1836,9 @@ static void rc_client_dispatch_activate_game(struct rc_client_scheduled_callback
|
||||
|
||||
static void rc_client_queue_activate_game(rc_client_load_state_t* load_state)
|
||||
{
|
||||
rc_client_scheduled_callback_data_t* scheduled_callback_data = calloc(1, sizeof(rc_client_scheduled_callback_data_t));
|
||||
rc_client_scheduled_callback_data_t* scheduled_callback_data =
|
||||
(rc_client_scheduled_callback_data_t*)calloc(1, sizeof(rc_client_scheduled_callback_data_t));
|
||||
|
||||
if (!scheduled_callback_data) {
|
||||
rc_client_load_error(load_state, RC_OUT_OF_MEMORY, rc_error_str(RC_OUT_OF_MEMORY));
|
||||
return;
|
||||
@ -1805,7 +1875,7 @@ static void rc_client_start_session_callback(const rc_api_server_response_t* ser
|
||||
outstanding_requests = rc_client_end_load_state(load_state);
|
||||
|
||||
if (error_message) {
|
||||
rc_client_load_error(callback_data, result, error_message);
|
||||
rc_client_load_error(load_state, result, error_message);
|
||||
}
|
||||
else if (outstanding_requests < 0) {
|
||||
/* previous load state was aborted, load_state was free'd */
|
||||
@ -1818,7 +1888,7 @@ static void rc_client_start_session_callback(const rc_api_server_response_t* ser
|
||||
(rc_api_start_session_response_t*)malloc(sizeof(rc_api_start_session_response_t));
|
||||
|
||||
if (!load_state->start_session_response) {
|
||||
rc_client_load_error(callback_data, RC_OUT_OF_MEMORY, rc_error_str(RC_OUT_OF_MEMORY));
|
||||
rc_client_load_error(load_state, RC_OUT_OF_MEMORY, rc_error_str(RC_OUT_OF_MEMORY));
|
||||
}
|
||||
else {
|
||||
/* safer to parse the response again than to try to copy it */
|
||||
@ -1911,7 +1981,7 @@ static void rc_client_copy_achievements(rc_client_load_state_t* load_state,
|
||||
|
||||
/* allocate the achievement array */
|
||||
size = sizeof(rc_client_achievement_info_t) * num_achievements;
|
||||
achievement = achievements = rc_buffer_alloc(buffer, size);
|
||||
achievement = achievements = (rc_client_achievement_info_t*)rc_buffer_alloc(buffer, size);
|
||||
memset(achievements, 0, size);
|
||||
|
||||
/* copy the achievement data */
|
||||
@ -1960,7 +2030,7 @@ static void rc_client_copy_achievements(rc_client_load_state_t* load_state,
|
||||
achievement->public_.bucket = RC_CLIENT_ACHIEVEMENT_BUCKET_UNSUPPORTED;
|
||||
}
|
||||
else {
|
||||
rc_buffer_consume(buffer, preparse.parse.buffer, (uint8_t*)preparse.parse.buffer + preparse.parse.offset);
|
||||
rc_buffer_consume(buffer, (const uint8_t*)preparse.parse.buffer, (uint8_t*)preparse.parse.buffer + preparse.parse.offset);
|
||||
}
|
||||
|
||||
rc_destroy_preparse_state(&preparse);
|
||||
@ -2053,7 +2123,7 @@ static void rc_client_copy_leaderboards(rc_client_load_state_t* load_state,
|
||||
/* allocate the achievement array */
|
||||
size = sizeof(rc_client_leaderboard_info_t) * num_leaderboards;
|
||||
buffer = &load_state->game->buffer;
|
||||
leaderboard = leaderboards = rc_buffer_alloc(buffer, size);
|
||||
leaderboard = leaderboards = (rc_client_leaderboard_info_t*)rc_buffer_alloc(buffer, size);
|
||||
memset(leaderboards, 0, size);
|
||||
|
||||
/* copy the achievement data */
|
||||
@ -2103,7 +2173,7 @@ static void rc_client_copy_leaderboards(rc_client_load_state_t* load_state,
|
||||
leaderboard->public_.state = RC_CLIENT_LEADERBOARD_STATE_DISABLED;
|
||||
}
|
||||
else {
|
||||
rc_buffer_consume(buffer, preparse.parse.buffer, (uint8_t*)preparse.parse.buffer + preparse.parse.offset);
|
||||
rc_buffer_consume(buffer, (const uint8_t*)preparse.parse.buffer, (uint8_t*)preparse.parse.buffer + preparse.parse.offset);
|
||||
}
|
||||
|
||||
rc_destroy_preparse_state(&preparse);
|
||||
@ -2618,7 +2688,7 @@ rc_client_game_hash_t* rc_client_find_game_hash(rc_client_t* client, const char*
|
||||
}
|
||||
|
||||
if (!game_hash) {
|
||||
game_hash = rc_buffer_alloc(&client->state.buffer, sizeof(rc_client_game_hash_t));
|
||||
game_hash = (rc_client_game_hash_t*)rc_buffer_alloc(&client->state.buffer, sizeof(rc_client_game_hash_t));
|
||||
memset(game_hash, 0, sizeof(*game_hash));
|
||||
snprintf(game_hash->hash, sizeof(game_hash->hash), "%s", hash);
|
||||
game_hash->game_id = RC_CLIENT_UNKNOWN_GAME_ID;
|
||||
@ -2796,16 +2866,14 @@ rc_hash_iterator_t* rc_client_get_load_state_hash_iterator(rc_client_t* client)
|
||||
|
||||
static void rc_client_log_hash_message_verbose(const char* message, const rc_hash_iterator_t* iterator)
|
||||
{
|
||||
rc_client_load_state_t unused;
|
||||
rc_client_load_state_t* load_state = (rc_client_load_state_t*)(((uint8_t*)iterator) - RC_OFFSETOF(unused, hash_iterator));
|
||||
const rc_client_load_state_t* load_state = (const rc_client_load_state_t*)iterator->userdata;
|
||||
if (load_state->client->state.log_level >= RC_CLIENT_LOG_LEVEL_INFO)
|
||||
rc_client_log_message(load_state->client, message);
|
||||
}
|
||||
|
||||
static void rc_client_log_hash_message_error(const char* message, const rc_hash_iterator_t* iterator)
|
||||
{
|
||||
rc_client_load_state_t unused;
|
||||
rc_client_load_state_t* load_state = (rc_client_load_state_t*)(((uint8_t*)iterator) - RC_OFFSETOF(unused, hash_iterator));
|
||||
const rc_client_load_state_t* load_state = (const rc_client_load_state_t*)iterator->userdata;
|
||||
if (load_state->client->state.log_level >= RC_CLIENT_LOG_LEVEL_ERROR)
|
||||
rc_client_log_message(load_state->client, message);
|
||||
}
|
||||
@ -2875,6 +2943,7 @@ rc_client_async_handle_t* rc_client_begin_identify_and_load_game(rc_client_t* cl
|
||||
/* initialize the iterator */
|
||||
rc_hash_initialize_iterator(&load_state->hash_iterator, file_path, data, data_size);
|
||||
rc_hash_merge_callbacks(&load_state->hash_iterator, &client->callbacks.hash);
|
||||
load_state->hash_iterator.userdata = load_state;
|
||||
|
||||
if (!load_state->hash_iterator.callbacks.verbose_message)
|
||||
load_state->hash_iterator.callbacks.verbose_message = rc_client_log_hash_message_verbose;
|
||||
@ -3114,7 +3183,8 @@ static rc_client_async_handle_t* rc_client_begin_change_media_internal(rc_client
|
||||
rc_api_request_t request;
|
||||
int result;
|
||||
|
||||
if (game_hash->game_id != RC_CLIENT_UNKNOWN_GAME_ID) {
|
||||
if (game_hash->game_id != RC_CLIENT_UNKNOWN_GAME_ID || /* previously looked up */
|
||||
game_hash->hash[0] == '[') { /* internal use - don't try to look up */
|
||||
rc_client_change_media_internal(client, game_hash, callback, callback_userdata);
|
||||
return NULL;
|
||||
}
|
||||
@ -3207,7 +3277,7 @@ static rc_client_game_info_t* rc_client_check_pending_media(rc_client_t* client,
|
||||
}
|
||||
|
||||
/* still waiting for game data - don't call callback - it's queued */
|
||||
if (pending_media)
|
||||
if (pending_media)
|
||||
return NULL;
|
||||
|
||||
return game;
|
||||
@ -3364,7 +3434,7 @@ const rc_client_game_t* rc_client_get_game_info(const rc_client_t* client)
|
||||
|
||||
if (client->state.external_client->get_game_info)
|
||||
return rc_client_external_convert_v1_game(client, client->state.external_client->get_game_info());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return client->game ? &client->game->public_ : NULL;
|
||||
@ -4130,7 +4200,7 @@ static void rc_client_award_achievement_callback(const rc_api_server_response_t*
|
||||
}
|
||||
|
||||
static void rc_client_award_achievement_server_call(rc_client_award_achievement_callback_data_t* ach_data)
|
||||
{
|
||||
{
|
||||
rc_api_award_achievement_request_t api_params;
|
||||
rc_api_request_t request;
|
||||
int result;
|
||||
@ -4284,7 +4354,7 @@ const rc_client_leaderboard_t* rc_client_get_leaderboard_info(const rc_client_t*
|
||||
if (leaderboard != NULL)
|
||||
return &leaderboard->public_;
|
||||
}
|
||||
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -4368,7 +4438,7 @@ rc_client_leaderboard_list_t* rc_client_create_leaderboard_list(rc_client_t* cli
|
||||
};
|
||||
|
||||
if (!client)
|
||||
return calloc(1, sizeof(rc_client_leaderboard_list_t));
|
||||
return (rc_client_leaderboard_list_t*)calloc(1, list_size);
|
||||
|
||||
#ifdef RC_CLIENT_SUPPORTS_EXTERNAL
|
||||
if (client->state.external_client && client->state.external_client->create_leaderboard_list)
|
||||
@ -4376,7 +4446,7 @@ rc_client_leaderboard_list_t* rc_client_create_leaderboard_list(rc_client_t* cli
|
||||
#endif
|
||||
|
||||
if (!client->game)
|
||||
return calloc(1, sizeof(rc_client_leaderboard_list_t));
|
||||
return (rc_client_leaderboard_list_t*)calloc(1, list_size);
|
||||
|
||||
memset(&bucket_counts, 0, sizeof(bucket_counts));
|
||||
|
||||
|
||||
7
3rdparty/rcheevos/src/rc_client_external.h
vendored
7
3rdparty/rcheevos/src/rc_client_external.h
vendored
@ -35,6 +35,7 @@ typedef rc_client_async_handle_t* (RC_CCONV *rc_client_external_begin_load_subse
|
||||
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_subset_summary_func_t)(uint32_t subset_id, rc_client_user_game_summary_t* summary);
|
||||
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);
|
||||
@ -139,9 +140,13 @@ typedef struct rc_client_external_t
|
||||
/* VERSION 4 */
|
||||
rc_client_external_set_int_func_t set_allow_background_memory_reads;
|
||||
|
||||
/* VERSION 5 */
|
||||
rc_client_external_get_user_game_summary_func_t get_user_game_summary_v5;
|
||||
rc_client_external_get_user_subset_summary_func_t get_user_subset_summary;
|
||||
|
||||
} rc_client_external_t;
|
||||
|
||||
#define RC_CLIENT_EXTERNAL_VERSION 4
|
||||
#define RC_CLIENT_EXTERNAL_VERSION 5
|
||||
|
||||
void rc_client_add_game_hash(rc_client_t* client, const char* hash, uint32_t game_id);
|
||||
void rc_client_load_unknown_game(rc_client_t* client, const char* hash);
|
||||
|
||||
@ -144,6 +144,28 @@ typedef struct v3_rc_client_achievement_list_info_t {
|
||||
rc_client_destroy_achievement_list_func_t destroy_func;
|
||||
} v3_rc_client_achievement_list_info_t;
|
||||
|
||||
/* user_game_summary */
|
||||
|
||||
typedef struct v1_rc_client_user_game_summary_t {
|
||||
uint32_t num_core_achievements;
|
||||
uint32_t num_unofficial_achievements;
|
||||
uint32_t num_unlocked_achievements;
|
||||
uint32_t num_unsupported_achievements;
|
||||
uint32_t points_core;
|
||||
uint32_t points_unlocked;
|
||||
} v1_rc_client_user_game_summary_t;
|
||||
|
||||
typedef struct v5_rc_client_user_game_summary_t {
|
||||
uint32_t num_core_achievements;
|
||||
uint32_t num_unofficial_achievements;
|
||||
uint32_t num_unlocked_achievements;
|
||||
uint32_t num_unsupported_achievements;
|
||||
uint32_t points_core;
|
||||
uint32_t points_unlocked;
|
||||
time_t beaten_time;
|
||||
time_t completed_time;
|
||||
} v5_rc_client_user_game_summary_t;
|
||||
|
||||
RC_END_C_DECLS
|
||||
|
||||
#endif /* RC_CLIENT_EXTERNAL_CONVERSIONS_H */
|
||||
|
||||
1
3rdparty/rcheevos/src/rc_libretro.c
vendored
1
3rdparty/rcheevos/src/rc_libretro.c
vendored
@ -78,6 +78,7 @@ static const rc_disallowed_setting_t _rc_disallowed_fbneo_settings[] = {
|
||||
};
|
||||
|
||||
static const rc_disallowed_setting_t _rc_disallowed_fceumm_settings[] = {
|
||||
{ "fceumm_game_genie", "!disabled" },
|
||||
{ "fceumm_region", ",PAL,Dendy" },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
8
3rdparty/rcheevos/src/rcheevos/condset.c
vendored
8
3rdparty/rcheevos/src/rcheevos/condset.c
vendored
@ -343,8 +343,12 @@ rc_condset_t* rc_parse_condset(const char** memaddr, rc_parse_state_t* parse) {
|
||||
if (parse->buffer) {
|
||||
classification = rc_classify_condition(&condition);
|
||||
if (classification == RC_CONDITION_CLASSIFICATION_COMBINING) {
|
||||
if (combining_classification == RC_CONDITION_CLASSIFICATION_COMBINING)
|
||||
combining_classification = rc_find_next_classification(&(*memaddr)[1]); /* skip over '_' */
|
||||
if (combining_classification == RC_CONDITION_CLASSIFICATION_COMBINING) {
|
||||
if (**memaddr == '_')
|
||||
combining_classification = rc_find_next_classification(&(*memaddr)[1]); /* skip over '_' */
|
||||
else
|
||||
combining_classification = RC_CONDITION_CLASSIFICATION_OTHER;
|
||||
}
|
||||
|
||||
classification = combining_classification;
|
||||
}
|
||||
|
||||
5
3rdparty/rcheevos/src/rcheevos/consoleinfo.c
vendored
5
3rdparty/rcheevos/src/rcheevos/consoleinfo.c
vendored
@ -971,9 +971,10 @@ static const rc_memory_regions_t rc_memory_regions_wasm4 = { _rc_memory_regions_
|
||||
/* https://wiibrew.org/wiki/Memory_map */
|
||||
static const rc_memory_region_t _rc_memory_regions_wii[] = {
|
||||
{ 0x00000000U, 0x017FFFFF, 0x80000000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" },
|
||||
{ 0x01800000U, 0x057FFFFF, 0x90000000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" }
|
||||
{ 0x01800000U, 0x0FFFFFFF, 0x81800000U, RC_MEMORY_TYPE_UNUSED, "Unused" },
|
||||
{ 0x10000000U, 0x13FFFFFF, 0x90000000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" }
|
||||
};
|
||||
static const rc_memory_regions_t rc_memory_regions_wii = { _rc_memory_regions_wii, 2 };
|
||||
static const rc_memory_regions_t rc_memory_regions_wii = { _rc_memory_regions_wii, 3 };
|
||||
|
||||
/* ===== WonderSwan ===== */
|
||||
/* http://daifukkat.su/docs/wsman/#ovr_memmap */
|
||||
|
||||
2
3rdparty/rcheevos/src/rcheevos/memref.c
vendored
2
3rdparty/rcheevos/src/rcheevos/memref.c
vendored
@ -328,7 +328,7 @@ static float rc_build_float(uint32_t mantissa_bits, int32_t exponent, int sign)
|
||||
if (mantissa_bits == 0) {
|
||||
/* infinity */
|
||||
#ifdef INFINITY /* INFINITY and NAN #defines require C99 */
|
||||
dbl = INFINITY;
|
||||
dbl = (double)INFINITY;
|
||||
#else
|
||||
dbl = -log(0.0);
|
||||
#endif
|
||||
|
||||
6
3rdparty/rcheevos/src/rcheevos/operand.c
vendored
6
3rdparty/rcheevos/src/rcheevos/operand.c
vendored
@ -380,9 +380,6 @@ int rc_operand_is_float_memref(const rc_operand_t* self) {
|
||||
if (!rc_operand_is_memref(self))
|
||||
return 0;
|
||||
|
||||
if (self->type == RC_OPERAND_RECALL)
|
||||
return rc_memsize_is_float(self->memref_access_type);
|
||||
|
||||
if (self->value.memref->value.memref_type == RC_MEMREF_TYPE_MODIFIED_MEMREF) {
|
||||
const rc_modified_memref_t* memref = (const rc_modified_memref_t*)self->value.memref;
|
||||
if (memref->modifier_type != RC_OPERATOR_INDIRECT_READ)
|
||||
@ -434,6 +431,9 @@ int rc_operand_is_float(const rc_operand_t* self) {
|
||||
if (self->type == RC_OPERAND_FP)
|
||||
return 1;
|
||||
|
||||
if (self->type == RC_OPERAND_RECALL)
|
||||
return rc_memsize_is_float(self->size);
|
||||
|
||||
return rc_operand_is_float_memref(self);
|
||||
}
|
||||
|
||||
|
||||
39
3rdparty/rcheevos/src/rcheevos/rc_validate.c
vendored
39
3rdparty/rcheevos/src/rcheevos/rc_validate.c
vendored
@ -174,8 +174,8 @@ static uint32_t rc_scale_value(uint32_t value, uint8_t oper, const rc_operand_t*
|
||||
|
||||
case RC_OPERATOR_SUB:
|
||||
{
|
||||
const uint32_t op_max = (operand->type == RC_OPERAND_CONST) ? operand->value.num : rc_max_value(operand);
|
||||
if (value > op_max)
|
||||
const uint32_t op_max = (operand->type == RC_OPERAND_CONST) ? operand->value.num : 0;
|
||||
if (value >= op_max)
|
||||
return value - op_max;
|
||||
|
||||
return 0xFFFFFFFF;
|
||||
@ -351,11 +351,11 @@ static int rc_validate_condset_internal(const rc_condset_t* condset, char result
|
||||
snprintf(result, result_size, "Condition %d: Using pointer from previous frame", index);
|
||||
return 0;
|
||||
}
|
||||
if (rc_operand_is_float(&cond->operand1) || rc_operand_is_float(&cond->operand2)) {
|
||||
if (rc_operand_is_float(operand1) || rc_operand_is_float(&cond->operand2)) {
|
||||
snprintf(result, result_size, "Condition %d: Using non-integer value in AddAddress calcuation", index);
|
||||
return 0;
|
||||
}
|
||||
if (rc_operand_type_is_transform(cond->operand1.type)) {
|
||||
if (rc_operand_type_is_transform(operand1->type) && cond->oper != RC_OPERATOR_MULT) {
|
||||
snprintf(result, result_size, "Condition %d: Using transformed value in AddAddress calcuation", index);
|
||||
return 0;
|
||||
}
|
||||
@ -721,7 +721,7 @@ static int rc_validate_comparison_overlap(int comparison1, uint32_t value1, int
|
||||
}
|
||||
|
||||
static int rc_validate_conflicting_conditions(const rc_condset_t* conditions, const rc_condset_t* compare_conditions,
|
||||
const char* prefix, const char* compare_prefix, char result[], const size_t result_size)
|
||||
int has_hits, const char* prefix, const char* compare_prefix, char result[], const size_t result_size)
|
||||
{
|
||||
int comparison1, comparison2;
|
||||
uint32_t value1, value2;
|
||||
@ -895,7 +895,15 @@ static int rc_validate_conflicting_conditions(const rc_condset_t* conditions, co
|
||||
{
|
||||
/* only ever report the redundancy on the non-ResetIf condition. The ResetIf is allowed to
|
||||
* fire when the non-ResetIf condition is not true. */
|
||||
continue;
|
||||
if (has_hits)
|
||||
continue;
|
||||
}
|
||||
else if (condition->type == RC_CONDITION_RESET_IF && compare_condition->type != RC_CONDITION_RESET_IF)
|
||||
{
|
||||
/* if the ResetIf condition is more restrictive than the non-ResetIf condition,
|
||||
and there aren't any hits to clear, ignore it */
|
||||
if (has_hits)
|
||||
continue;
|
||||
}
|
||||
else if (compare_condition->type == RC_CONDITION_MEASURED_IF || condition->type == RC_CONDITION_MEASURED_IF)
|
||||
{
|
||||
@ -947,12 +955,21 @@ static int rc_validate_trigger_internal(const rc_trigger_t* trigger, char result
|
||||
{
|
||||
const rc_condset_t* alt;
|
||||
int index;
|
||||
int has_hits = (trigger->requirement && trigger->requirement->num_hittarget_conditions > 0);
|
||||
if (!has_hits) {
|
||||
for (alt = trigger->alternative; alt; alt = alt->next) {
|
||||
if (alt->num_hittarget_conditions > 0) {
|
||||
has_hits = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!trigger->alternative) {
|
||||
if (!rc_validate_condset_internal(trigger->requirement, result, result_size, console_id, max_address))
|
||||
return 0;
|
||||
|
||||
return rc_validate_conflicting_conditions(trigger->requirement, trigger->requirement, "", "", result, result_size);
|
||||
return rc_validate_conflicting_conditions(trigger->requirement, trigger->requirement, has_hits, "", "", result, result_size);
|
||||
}
|
||||
|
||||
snprintf(result, result_size, "Core ");
|
||||
@ -960,7 +977,7 @@ static int rc_validate_trigger_internal(const rc_trigger_t* trigger, char result
|
||||
return 0;
|
||||
|
||||
/* compare core to itself */
|
||||
if (!rc_validate_conflicting_conditions(trigger->requirement, trigger->requirement, "Core", "Core", result, result_size))
|
||||
if (!rc_validate_conflicting_conditions(trigger->requirement, trigger->requirement, has_hits, "Core", "Core", result, result_size))
|
||||
return 0;
|
||||
|
||||
index = 1;
|
||||
@ -972,15 +989,15 @@ static int rc_validate_trigger_internal(const rc_trigger_t* trigger, char result
|
||||
|
||||
/* compare alt to itself */
|
||||
snprintf(altname, sizeof(altname), "Alt%d", index);
|
||||
if (!rc_validate_conflicting_conditions(alt, alt, altname, altname, result, result_size))
|
||||
if (!rc_validate_conflicting_conditions(alt, alt, has_hits, altname, altname, result, result_size))
|
||||
return 0;
|
||||
|
||||
/* compare alt to core */
|
||||
if (!rc_validate_conflicting_conditions(trigger->requirement, alt, "Core", altname, result, result_size))
|
||||
if (!rc_validate_conflicting_conditions(trigger->requirement, alt, has_hits, "Core", altname, result, result_size))
|
||||
return 0;
|
||||
|
||||
/* compare core to alt */
|
||||
if (!rc_validate_conflicting_conditions(alt, trigger->requirement, altname, "Core", result, result_size))
|
||||
if (!rc_validate_conflicting_conditions(alt, trigger->requirement, has_hits, altname, "Core", result, result_size))
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@ -48,8 +48,9 @@ static void rc_alloc_helper_variable_memref_value(rc_richpresence_display_part_t
|
||||
|
||||
condset = value->conditions;
|
||||
if (condset && !condset->next) {
|
||||
/* single value - if it's only "measured" and "indirect" conditions, we can simplify to a memref */
|
||||
if (condset->num_measured_conditions &&
|
||||
/* single value - if it's a single Measured clause (including any AddSource/AddAddress helpers), we can
|
||||
* simplify to a memref. If there are supporting clauses like MeasuredIf or ResetIf, we can't */
|
||||
if (condset->num_measured_conditions == 1 &&
|
||||
!condset->num_pause_conditions && !condset->num_reset_conditions &&
|
||||
!condset->num_other_conditions && !condset->num_hittarget_conditions) {
|
||||
rc_condition_t* condition = condset->conditions;
|
||||
|
||||
6
3rdparty/rcheevos/src/rcheevos/runtime.c
vendored
6
3rdparty/rcheevos/src/rcheevos/runtime.c
vendored
@ -36,7 +36,7 @@ rc_runtime_t* rc_runtime_alloc(void) {
|
||||
rc_runtime_event_handler_t unused = &rc_runtime_natvis_helper;
|
||||
(void)unused;
|
||||
|
||||
self = malloc(sizeof(rc_runtime_t));
|
||||
self = (rc_runtime_t*)malloc(sizeof(rc_runtime_t));
|
||||
|
||||
if (self) {
|
||||
rc_runtime_init(self);
|
||||
@ -307,7 +307,7 @@ int rc_runtime_activate_lboard(rc_runtime_t* self, uint32_t id, const char* mema
|
||||
rc_lboard_t* lboard;
|
||||
rc_preparse_state_t preparse;
|
||||
rc_runtime_lboard_t* runtime_lboard;
|
||||
int size;
|
||||
int32_t size;
|
||||
uint32_t i;
|
||||
|
||||
(void)unused_L;
|
||||
@ -797,7 +797,7 @@ void rc_runtime_invalidate_address(rc_runtime_t* self, uint32_t address) {
|
||||
} while (memref_list);
|
||||
}
|
||||
|
||||
void rc_runtime_validate_addresses(rc_runtime_t* self, rc_runtime_event_handler_t event_handler,
|
||||
void rc_runtime_validate_addresses(rc_runtime_t* self, rc_runtime_event_handler_t event_handler,
|
||||
rc_runtime_validate_address_t validate_handler) {
|
||||
int num_invalid = 0;
|
||||
rc_memref_list_t* memref_list = &self->memrefs->memrefs;
|
||||
|
||||
@ -920,7 +920,7 @@ uint32_t rc_runtime_progress_size(const rc_runtime_t* runtime, void* unused_L)
|
||||
|
||||
int rc_runtime_serialize_progress(void* buffer, const rc_runtime_t* runtime, void* unused_L)
|
||||
{
|
||||
return rc_runtime_serialize_progress_sized(buffer, 0xFFFFFFFF, runtime, unused_L);
|
||||
return rc_runtime_serialize_progress_sized((uint8_t*)buffer, 0xFFFFFFFF, runtime, unused_L);
|
||||
}
|
||||
|
||||
int rc_runtime_serialize_progress_sized(uint8_t* buffer, uint32_t buffer_size, const rc_runtime_t* runtime, void* unused_L)
|
||||
|
||||
40
3rdparty/rcheevos/src/rcheevos/value.c
vendored
40
3rdparty/rcheevos/src/rcheevos/value.c
vendored
@ -61,27 +61,41 @@ static void rc_parse_legacy_value(rc_value_t* self, const char** memaddr, rc_par
|
||||
char buffer[64] = "A:";
|
||||
const char* buffer_ptr;
|
||||
char* ptr;
|
||||
char c;
|
||||
int done;
|
||||
|
||||
/* convert legacy format into condset */
|
||||
next_clause = &self->conditions;
|
||||
do {
|
||||
num_measured_conditions = 0;
|
||||
|
||||
/* count the number of joiners and add one to determine the number of clauses. */
|
||||
done = 0;
|
||||
num_measured_conditions = 1;
|
||||
buffer_ptr = *memaddr;
|
||||
while ((c = *buffer_ptr++) && c != '$') {
|
||||
if (c == '_') {
|
||||
++num_measured_conditions;
|
||||
buffer[0] = 'A'; /* reset to AddSource */
|
||||
do {
|
||||
switch (*buffer_ptr++) {
|
||||
case '_': /* add next */
|
||||
++num_measured_conditions;
|
||||
buffer[0] = 'A'; /* reset to AddSource */
|
||||
break;
|
||||
|
||||
case '*': /* multiply */
|
||||
if (*buffer_ptr == '-') {
|
||||
/* multiplication by a negative number will convert to SubSource */
|
||||
++buffer_ptr;
|
||||
buffer[0] = 'B';
|
||||
}
|
||||
break;
|
||||
|
||||
case '\0': /* end of string */
|
||||
case '$': /* maximum of */
|
||||
case ':': /* end of leaderboard clause */
|
||||
case ')': /* end of rich presence macro */
|
||||
done = 1;
|
||||
break;
|
||||
|
||||
default: /* assume everything else is valid - bad stuff will be filtered out later */
|
||||
break;
|
||||
}
|
||||
else if (c == '*' && *buffer_ptr == '-') {
|
||||
/* multiplication by a negative number will convert to SubSource */
|
||||
++buffer_ptr;
|
||||
buffer[0] = 'B';
|
||||
}
|
||||
}
|
||||
} while (!done);
|
||||
|
||||
/* if last condition is SubSource, we'll need to add a dummy condition for the Measured */
|
||||
if (buffer[0] == 'B')
|
||||
|
||||
6
3rdparty/rcheevos/src/rhash/hash.c
vendored
6
3rdparty/rcheevos/src/rhash/hash.c
vendored
@ -480,6 +480,7 @@ static int rc_hash_file_from_buffer(char hash[33], uint32_t console_id, const rc
|
||||
rc_hash_iterator_t buffered_file_iterator;
|
||||
memset(&buffered_file_iterator, 0, sizeof(buffered_file_iterator));
|
||||
memcpy(&buffered_file_iterator.callbacks, &iterator->callbacks, sizeof(iterator->callbacks));
|
||||
buffered_file_iterator.userdata = iterator->userdata;
|
||||
|
||||
buffered_file_iterator.callbacks.filereader.open = rc_file_open_buffered_file;
|
||||
buffered_file_iterator.callbacks.filereader.close = rc_file_close_buffered_file;
|
||||
@ -650,6 +651,7 @@ int rc_hash_buffered_file(char hash[33], uint32_t console_id, const rc_hash_iter
|
||||
rc_hash_iterator_t buffer_iterator;
|
||||
memset(&buffer_iterator, 0, sizeof(buffer_iterator));
|
||||
memcpy(&buffer_iterator.callbacks, &iterator->callbacks, sizeof(iterator->callbacks));
|
||||
buffer_iterator.userdata = iterator->userdata;
|
||||
buffer_iterator.path = iterator->path;
|
||||
buffer_iterator.buffer = buffer;
|
||||
buffer_iterator.buffer_size = (size_t)size;
|
||||
@ -773,6 +775,7 @@ static int rc_hash_generate_from_playlist(char hash[33], uint32_t console_id, co
|
||||
|
||||
memset(&first_file_iterator, 0, sizeof(first_file_iterator));
|
||||
memcpy(&first_file_iterator.callbacks, &iterator->callbacks, sizeof(iterator->callbacks));
|
||||
first_file_iterator.userdata = iterator->userdata;
|
||||
first_file_iterator.path = disc_path; /* rc_hash_destory_iterator will free */
|
||||
|
||||
result = rc_hash_from_file(hash, console_id, &first_file_iterator);
|
||||
@ -1293,7 +1296,8 @@ static void rc_hash_initialize_iterator_from_path(rc_hash_iterator_t* iterator,
|
||||
}
|
||||
|
||||
/* find the handler for the extension */
|
||||
handler = bsearch(&search, handlers, num_handlers, sizeof(*handler), rc_hash_iterator_find_handler);
|
||||
handler = (const rc_hash_iterator_ext_handler_entry_t*)
|
||||
bsearch(&search, handlers, num_handlers, sizeof(*handler), rc_hash_iterator_find_handler);
|
||||
if (handler) {
|
||||
handler->handler(iterator, handler->data);
|
||||
} else {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user