mirror of
https://github.com/stenzek/duckstation.git
synced 2026-02-16 03:14:35 +00:00
Deps: Update rcheevos to v12.2.0
This commit is contained in:
@@ -1,3 +1,18 @@
|
||||
# v12.2.0
|
||||
* add rc_client_create_subset_list
|
||||
* add rc_client_begin_fetch_game_titles
|
||||
* greatly improve performance parsing long AddSource chains
|
||||
* don't send pings if not processing frames; allows server to suspend session while emulator is paused
|
||||
* modify validation logic to return most severe error instead of first error found
|
||||
* improve validation warning when 'PauseIf {recall}' attempts to use non-PauseIf Remember
|
||||
* fix rounding error when subtracting floats from integers
|
||||
* fix infinite loop processing 'Remember {recall}' with no modifiers
|
||||
* fix measured value jumping to 0 if all measured-generating alts are paused
|
||||
* fix buffer overflow converting long user names between rc_client_external versions
|
||||
* fix validation warning when adding differently sized values
|
||||
* fix validation warning when ResetIf only applies to hit count inside an AndNext chain
|
||||
* fix validation warning when only last node of modified memref chain differs
|
||||
|
||||
# v12.1.0
|
||||
* add rc_client_get_user_subset_summary
|
||||
* add validation warning for using MeasuredIf without Measured
|
||||
|
||||
@@ -1692,6 +1692,67 @@ static void rc_client_free_pending_media(rc_client_pending_media_t* pending_medi
|
||||
free(pending_media);
|
||||
}
|
||||
|
||||
static void rc_client_log_active_assets(rc_client_t* client)
|
||||
{
|
||||
uint32_t num_achievements;
|
||||
uint32_t num_active_achievements;
|
||||
uint32_t num_unsupported_achievements;
|
||||
uint32_t num_leaderboards;
|
||||
uint32_t num_unsupported_leaderboards;
|
||||
const rc_client_achievement_info_t* ach;
|
||||
const rc_client_achievement_info_t* ach_stop;
|
||||
const rc_client_leaderboard_info_t* lbd;
|
||||
const rc_client_leaderboard_info_t* lbd_stop;
|
||||
|
||||
const rc_client_subset_info_t* subset = client->game->subsets;
|
||||
for (; subset; subset = subset->next) {
|
||||
num_achievements = 0;
|
||||
num_active_achievements = 0;
|
||||
num_unsupported_achievements = 0;
|
||||
num_leaderboards = 0;
|
||||
num_unsupported_leaderboards = 0;
|
||||
|
||||
ach = subset->achievements;
|
||||
ach_stop = ach + subset->public_.num_achievements;
|
||||
for (; ach < ach_stop; ++ach) {
|
||||
if (ach->public_.category == RC_CLIENT_ACHIEVEMENT_CATEGORY_CORE) {
|
||||
++num_achievements;
|
||||
if (ach->public_.state == RC_CLIENT_ACHIEVEMENT_STATE_ACTIVE)
|
||||
++num_active_achievements;
|
||||
else if (ach->public_.state == RC_CLIENT_ACHIEVEMENT_STATE_DISABLED)
|
||||
++num_unsupported_achievements;
|
||||
}
|
||||
}
|
||||
|
||||
lbd = subset->leaderboards;
|
||||
lbd_stop = lbd + subset->public_.num_leaderboards;
|
||||
for (; lbd < lbd_stop; ++lbd) {
|
||||
++num_leaderboards;
|
||||
if (lbd->public_.state == RC_CLIENT_LEADERBOARD_STATE_DISABLED)
|
||||
++num_unsupported_leaderboards;
|
||||
}
|
||||
|
||||
if (num_unsupported_achievements) {
|
||||
if (num_unsupported_leaderboards) {
|
||||
RC_CLIENT_LOG_INFO_FORMATTED(client, "Set %u: %u/%u achievements active (%u unsupported), %u leaderboards (%u unsupported)",
|
||||
subset->public_.id, num_active_achievements, num_achievements, num_unsupported_achievements, num_leaderboards, num_unsupported_leaderboards);
|
||||
}
|
||||
else {
|
||||
RC_CLIENT_LOG_INFO_FORMATTED(client, "Set %u: %u/%u achievements active (%u unsupported), %u leaderboards",
|
||||
subset->public_.id, num_active_achievements, num_achievements, num_unsupported_achievements, num_leaderboards);
|
||||
}
|
||||
}
|
||||
else if (num_unsupported_leaderboards) {
|
||||
RC_CLIENT_LOG_INFO_FORMATTED(client, "Set %u: %u/%u achievements active, %u leaderboards (%u unsupported)",
|
||||
subset->public_.id, num_active_achievements, num_achievements, num_leaderboards, num_unsupported_leaderboards);
|
||||
}
|
||||
else {
|
||||
RC_CLIENT_LOG_INFO_FORMATTED(client, "Set %u: %u/%u achievements active, %u leaderboards",
|
||||
subset->public_.id, num_active_achievements, num_achievements, num_leaderboards);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* NOTE: address validation uses the read_memory callback to make sure the client
|
||||
* will return data for the requested address. As such, this function must
|
||||
* respect the `client->state.allow_background_memory_reads setting. Use
|
||||
@@ -1816,6 +1877,9 @@ static void rc_client_activate_game(rc_client_load_state_t* load_state, rc_api_s
|
||||
RC_CLIENT_LOG_INFO_FORMATTED(client, "Game %u loaded, hardcore %s%s", load_state->game->public_.id,
|
||||
client->state.hardcore ? "enabled" : "disabled",
|
||||
(client->state.spectator_mode != RC_CLIENT_SPECTATOR_MODE_OFF) ? ", spectating" : "");
|
||||
|
||||
if (client->state.log_level >= RC_CLIENT_LOG_LEVEL_INFO)
|
||||
rc_client_log_active_assets(client);
|
||||
}
|
||||
else {
|
||||
RC_CLIENT_LOG_INFO_FORMATTED(client, "Subset %u loaded", load_state->subset->public_.id);
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
RC_BEGIN_C_DECLS
|
||||
|
||||
#define RCHEEVOS_VERSION_MAJOR 12
|
||||
#define RCHEEVOS_VERSION_MINOR 1
|
||||
#define RCHEEVOS_VERSION_MINOR 2
|
||||
#define RCHEEVOS_VERSION_PATCH 0
|
||||
|
||||
#define RCHEEVOS_MAKE_VERSION(major, minor, patch) (major * 1000000 + minor * 1000 + patch)
|
||||
|
||||
@@ -16,6 +16,7 @@ enum
|
||||
|
||||
/* errors that prevent the achievement from functioning */
|
||||
RC_VALIDATION_ERR_ADDRESS_OUT_OF_RANGE,
|
||||
RC_VALIDATION_ERR_RECALL_WITHOUT_REMEMBER,
|
||||
RC_VALIDATION_ERR_RECALL_BEFORE_REMEMBER,
|
||||
RC_VALIDATION_ERR_COMPARISON_NEVER_TRUE_WITH_MAX,
|
||||
RC_VALIDATION_ERR_COMPARISON_NEVER_TRUE_INTEGER_TO_FLOAT,
|
||||
@@ -268,7 +269,14 @@ static int rc_validate_format_error(char buffer[], size_t buffer_size, const rc_
|
||||
break;
|
||||
|
||||
case RC_VALIDATION_ERR_RECALL_BEFORE_REMEMBER:
|
||||
snprintf(buffer, buffer_size, "Recall used before Remember");
|
||||
if (error->data1 == RC_CONDITION_PAUSE_IF)
|
||||
snprintf(buffer, buffer_size, "PauseIf cannot use Remembered value not associated to PauseIf chain");
|
||||
else
|
||||
snprintf(buffer, buffer_size, "Recall used before Remember");
|
||||
break;
|
||||
|
||||
case RC_VALIDATION_ERR_RECALL_WITHOUT_REMEMBER:
|
||||
snprintf(buffer, buffer_size, "Recall used without Remember");
|
||||
break;
|
||||
|
||||
case RC_VALIDATION_ERR_RESET_HIT_TARGET_OF_ONE:
|
||||
@@ -312,6 +320,53 @@ static void rc_validate_add_error(rc_validation_state_t* state, uint32_t error_c
|
||||
error->data2 = data2;
|
||||
}
|
||||
|
||||
/* rc_condition_is_combining doesn't look at conditions that build a memref (like AddSource) */
|
||||
static int rc_validate_is_combining_condition(const rc_condition_t* condition)
|
||||
{
|
||||
switch (condition->type)
|
||||
{
|
||||
case RC_CONDITION_ADD_ADDRESS:
|
||||
case RC_CONDITION_ADD_HITS:
|
||||
case RC_CONDITION_ADD_SOURCE:
|
||||
case RC_CONDITION_AND_NEXT:
|
||||
case RC_CONDITION_OR_NEXT:
|
||||
case RC_CONDITION_RESET_NEXT_IF:
|
||||
case RC_CONDITION_SUB_HITS:
|
||||
case RC_CONDITION_SUB_SOURCE:
|
||||
case RC_CONDITION_REMEMBER:
|
||||
return 1;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static const rc_condition_t* rc_validate_get_next_non_combining_condition(const rc_condition_t* cond)
|
||||
{
|
||||
while (cond && rc_validate_is_combining_condition(cond))
|
||||
cond = cond->next;
|
||||
|
||||
return cond;
|
||||
}
|
||||
|
||||
static int rc_validate_has_condition(const rc_condition_t* cond, uint8_t type)
|
||||
{
|
||||
for (; cond; cond = cond->next) {
|
||||
if (cond->type == type)
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rc_validate_is_invalid_recall(const rc_operand_t* operand)
|
||||
{
|
||||
/* if operand is {recall}, but memref is null, that means the Remember wasn't found */
|
||||
return rc_operand_is_recall(operand) &&
|
||||
rc_operand_type_is_memref(operand->memref_access_type) &&
|
||||
!operand->value.memref;
|
||||
}
|
||||
|
||||
static void rc_validate_memref(const rc_memref_t* memref, rc_validation_state_t* state)
|
||||
{
|
||||
if (memref->address > state->max_address) {
|
||||
@@ -603,15 +658,15 @@ static int rc_validate_condset_internal(const rc_condset_t* condset, rc_validati
|
||||
}
|
||||
|
||||
/* if operand is {recall}, but memref is null, that means the Remember wasn't found */
|
||||
if (rc_operand_is_recall(operand1) &&
|
||||
rc_operand_type_is_memref(operand1->memref_access_type) &&
|
||||
!operand1->value.memref) {
|
||||
rc_validate_add_error(state, RC_VALIDATION_ERR_RECALL_BEFORE_REMEMBER, 0, 0);
|
||||
}
|
||||
if (rc_operand_is_recall(&cond->operand2) &&
|
||||
rc_operand_type_is_memref(cond->operand2.memref_access_type) &&
|
||||
!cond->operand2.value.memref) {
|
||||
rc_validate_add_error(state, RC_VALIDATION_ERR_RECALL_BEFORE_REMEMBER, 0, 0);
|
||||
if (rc_validate_is_invalid_recall(operand1) || rc_validate_is_invalid_recall(&cond->operand2)) {
|
||||
if (!rc_validate_has_condition(condset->conditions, RC_CONDITION_REMEMBER)) {
|
||||
rc_validate_add_error(state, RC_VALIDATION_ERR_RECALL_WITHOUT_REMEMBER, 0, 0);
|
||||
}
|
||||
else {
|
||||
const rc_condition_t* next_cond = rc_validate_get_next_non_combining_condition(cond);
|
||||
const uint8_t next_cond_type = next_cond ? next_cond->type : RC_CONDITION_STANDARD;
|
||||
rc_validate_add_error(state, RC_VALIDATION_ERR_RECALL_BEFORE_REMEMBER, next_cond_type, 0);
|
||||
}
|
||||
}
|
||||
|
||||
switch (cond->type) {
|
||||
@@ -840,27 +895,6 @@ int rc_validate_condset_for_console(const rc_condset_t* condset, char result[],
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* rc_condition_is_combining doesn't look at conditions that build a memref (like AddSource) */
|
||||
static int rc_validate_is_combining_condition(const rc_condition_t* condition)
|
||||
{
|
||||
switch (condition->type)
|
||||
{
|
||||
case RC_CONDITION_ADD_ADDRESS:
|
||||
case RC_CONDITION_ADD_HITS:
|
||||
case RC_CONDITION_ADD_SOURCE:
|
||||
case RC_CONDITION_AND_NEXT:
|
||||
case RC_CONDITION_OR_NEXT:
|
||||
case RC_CONDITION_RESET_NEXT_IF:
|
||||
case RC_CONDITION_SUB_HITS:
|
||||
case RC_CONDITION_SUB_SOURCE:
|
||||
case RC_CONDITION_REMEMBER:
|
||||
return 1;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int rc_validate_get_opposite_comparison(int oper)
|
||||
{
|
||||
switch (oper)
|
||||
|
||||
Reference in New Issue
Block a user