From 92509d953f696abdc9da8bdc80bf3e8055fbd623 Mon Sep 17 00:00:00 2001 From: Jamiras <32680403+Jamiras@users.noreply.github.com> Date: Sat, 21 Dec 2024 07:30:47 -0700 Subject: [PATCH] Remove memref references from each data object (#390) --- include/rc_runtime.h | 10 +- include/rc_runtime_types.h | 26 +-- src/rc_client.c | 171 +++++++-------- src/rc_util.c | 7 + src/rcheevos/alloc.c | 223 ++++++++++++++++---- src/rcheevos/condition.c | 5 + src/rcheevos/condset.c | 8 +- src/rcheevos/lboard.c | 52 ++--- src/rcheevos/memref.c | 269 ++++++++++++++++++++---- src/rcheevos/rc_internal.h | 99 ++++++++- src/rcheevos/rc_runtime_types.natvis | 60 ++++-- src/rcheevos/rc_validate.c | 36 ++-- src/rcheevos/rc_validate.h | 4 - src/rcheevos/richpresence.c | 117 +++++++---- src/rcheevos/runtime.c | 287 ++++++++++---------------- src/rcheevos/runtime_progress.c | 226 +++++++++++--------- src/rcheevos/trigger.c | 73 ++++--- src/rcheevos/value.c | 127 +++++++----- test/rcheevos/test_condition.c | 62 +++--- test/rcheevos/test_condset.c | 216 ++++++++++--------- test/rcheevos/test_memref.c | 30 +-- test/rcheevos/test_operand.c | 76 +++---- test/rcheevos/test_richpresence.c | 17 +- test/rcheevos/test_runtime.c | 74 +++---- test/rcheevos/test_runtime_progress.c | 80 ++++--- test/rcheevos/test_trigger.c | 54 +++-- test/test.c | 1 - validator/validator.c | 2 +- 28 files changed, 1442 insertions(+), 970 deletions(-) diff --git a/include/rc_runtime.h b/include/rc_runtime.h index d778fde5..ebd0b85d 100644 --- a/include/rc_runtime.h +++ b/include/rc_runtime.h @@ -46,7 +46,6 @@ typedef struct rc_runtime_trigger_t { rc_memref_t* invalid_memref; uint8_t md5[16]; int32_t serialized_size; - uint8_t owns_memrefs; } rc_runtime_trigger_t; @@ -58,16 +57,13 @@ typedef struct rc_runtime_lboard_t { rc_memref_t* invalid_memref; uint8_t md5[16]; uint32_t serialized_size; - uint8_t owns_memrefs; } rc_runtime_lboard_t; typedef struct rc_runtime_richpresence_t { rc_richpresence_t* richpresence; void* buffer; - struct rc_runtime_richpresence_t* previous; uint8_t md5[16]; - uint8_t owns_memrefs; } rc_runtime_richpresence_t; @@ -82,11 +78,7 @@ typedef struct rc_runtime_t { rc_runtime_richpresence_t* richpresence; - rc_memref_t* memrefs; - rc_memref_t** next_memref; - - rc_value_t* variables; - rc_value_t** next_variable; + struct rc_memrefs_t* memrefs; uint8_t owns_self; } diff --git a/include/rc_runtime_types.h b/include/rc_runtime_types.h index e60b5b5b..ba2cfb0e 100644 --- a/include/rc_runtime_types.h +++ b/include/rc_runtime_types.h @@ -87,12 +87,8 @@ struct rc_memref_t { /* The memory address of this variable. */ uint32_t address; - - /* The next memory reference in the chain. */ - rc_memref_t* next; }; - /*****************************************************************************\ | Operands | \*****************************************************************************/ @@ -270,9 +266,6 @@ struct rc_trigger_t { /* The list of sub condition sets in this test. */ rc_condset_t* alternative; - /* The memory references required by the trigger. */ - rc_memref_t* memrefs; - /* The current state of the MEASURED condition. */ uint32_t measured_value; @@ -285,11 +278,11 @@ struct rc_trigger_t { /* True if at least one condition has a non-zero hit count */ uint8_t has_hits; - /* True if at least one condition has a non-zero required hit count */ - uint8_t has_required_hits; - /* True if the measured value should be displayed as a percentage */ uint8_t measured_as_percent; + + /* True if the trigger has its own rc_memrefs_t */ + uint8_t has_memrefs; }; RC_EXPORT int RC_CCONV rc_trigger_size(const char* memaddr); @@ -308,12 +301,12 @@ struct rc_value_t { /* The current value of the variable. */ rc_memref_value_t value; + /* True if the value has its own rc_memrefs_t */ + uint8_t has_memrefs; + /* The list of possible values (traverse next chain, pick max). */ rc_condset_t* conditions; - /* The memory references required by the variable. */ - rc_memref_t* memrefs; - /* The name of the variable. */ const char* name; @@ -346,9 +339,9 @@ struct rc_lboard_t { rc_trigger_t cancel; rc_value_t value; rc_value_t* progress; - rc_memref_t* memrefs; uint8_t state; + uint8_t has_memrefs; }; RC_EXPORT int RC_CCONV rc_lboard_size(const char* memaddr); @@ -427,13 +420,14 @@ struct rc_richpresence_display_t { rc_trigger_t trigger; rc_richpresence_display_t* next; rc_richpresence_display_part_t* display; + uint8_t has_required_hits; }; struct rc_richpresence_t { rc_richpresence_display_t* first_display; rc_richpresence_lookup_t* first_lookup; - rc_memref_t* memrefs; - rc_value_t* variables; + rc_value_t* values; + uint8_t has_memrefs; }; RC_EXPORT int RC_CCONV rc_richpresence_size(const char* script); diff --git a/src/rc_client.c b/src/rc_client.c index 187d3d09..72d16572 100644 --- a/src/rc_client.c +++ b/src/rc_client.c @@ -1130,27 +1130,23 @@ static void rc_client_validate_addresses(rc_client_game_info_t* game, rc_client_ uint32_t total_count = 0; uint32_t invalid_count = 0; - rc_memref_t** last_memref = &game->runtime.memrefs; - rc_memref_t* memref = game->runtime.memrefs; - for (; memref; memref = memref->next) { - if (memref->value.memref_type == RC_MEMREF_TYPE_MEMREF) { - total_count++; + rc_memref_list_t* memref_list = &game->runtime.memrefs->memrefs; + for (; memref_list; memref_list = memref_list->next) { + rc_memref_t* memref = memref_list->items; + const rc_memref_t* memref_end = memref + memref_list->count; + total_count += memref_list->count; + for (; memref < memref_end; ++memref) { if (memref->address > max_address || - client->callbacks.read_memory(memref->address, buffer, 1, client) == 0) { - /* invalid address, remove from chain so we don't have to evaluate it in the future. - * it's still there, so anything referencing it will always fetch 0. */ - *last_memref = memref->next; + client->callbacks.read_memory(memref->address, buffer, 1, client) == 0) { + memref->value.type = RC_VALUE_TYPE_NONE; rc_client_invalidate_memref_achievements(game, client, memref); rc_client_invalidate_memref_leaderboards(game, client, memref); invalid_count++; - continue; } } - - last_memref = &memref->next; } game->max_valid_address = max_address; @@ -1713,9 +1709,10 @@ static void rc_client_copy_achievements(rc_client_load_state_t* load_state, rc_client_achievement_info_t* achievement; rc_client_achievement_info_t* scan; rc_buffer_t* buffer; - rc_parse_state_t parse; + rc_preparse_state_t preparse; const char* memaddr; size_t size; + rc_trigger_t* trigger; int trigger_size; subset->achievements = NULL; @@ -1745,11 +1742,11 @@ static void rc_client_copy_achievements(rc_client_load_state_t* load_state, + sizeof(rc_trigger_t) + sizeof(rc_condset_t) * 2 /* trigger container */ + sizeof(rc_condition_t) * 8 /* assume average trigger length of 8 conditions */ + sizeof(rc_client_achievement_info_t); - rc_buffer_reserve(&load_state->game->buffer, size * num_achievements); + buffer = &load_state->game->buffer; + rc_buffer_reserve(buffer, size * num_achievements); /* allocate the achievement array */ size = sizeof(rc_client_achievement_info_t) * num_achievements; - buffer = &load_state->game->buffer; achievement = achievements = rc_buffer_alloc(buffer, size); memset(achievements, 0, size); @@ -1772,7 +1769,12 @@ static void rc_client_copy_achievements(rc_client_load_state_t* load_state, memaddr = read->definition; rc_runtime_checksum(memaddr, achievement->md5); - trigger_size = rc_trigger_size(memaddr); + rc_init_preparse_state(&preparse, NULL, 0); + preparse.parse.existing_memrefs = load_state->game->runtime.memrefs; + trigger = RC_ALLOC(rc_trigger_t, &preparse.parse); + rc_parse_trigger_internal(trigger, &memaddr, &preparse.parse); + + trigger_size = preparse.parse.offset; if (trigger_size < 0) { RC_CLIENT_LOG_WARN_FORMATTED(load_state->client, "Parse error %d processing achievement %u", trigger_size, read->id); achievement->public_.state = RC_CLIENT_ACHIEVEMENT_STATE_DISABLED; @@ -1780,23 +1782,22 @@ static void rc_client_copy_achievements(rc_client_load_state_t* load_state, } else { /* populate the item, using the communal memrefs pool */ - rc_init_parse_state(&parse, rc_buffer_reserve(buffer, trigger_size), NULL, 0); - parse.first_memref = &load_state->game->runtime.memrefs; - parse.variables = &load_state->game->runtime.variables; - achievement->trigger = RC_ALLOC(rc_trigger_t, &parse); - rc_parse_trigger_internal(achievement->trigger, &memaddr, &parse); - - if (parse.offset < 0) { - RC_CLIENT_LOG_WARN_FORMATTED(load_state->client, "Parse error %d processing achievement %u", parse.offset, read->id); + rc_reset_parse_state(&preparse.parse, rc_buffer_reserve(buffer, trigger_size), NULL, 0); + rc_preparse_reserve_memrefs(&preparse, load_state->game->runtime.memrefs); + achievement->trigger = RC_ALLOC(rc_trigger_t, &preparse.parse); + memaddr = read->definition; + rc_parse_trigger_internal(achievement->trigger, &memaddr, &preparse.parse); + + if (preparse.parse.offset < 0) { + RC_CLIENT_LOG_WARN_FORMATTED(load_state->client, "Parse error %d processing achievement %u", preparse.parse.offset, read->id); achievement->public_.state = RC_CLIENT_ACHIEVEMENT_STATE_DISABLED; achievement->public_.bucket = RC_CLIENT_ACHIEVEMENT_BUCKET_UNSUPPORTED; } else { - rc_buffer_consume(buffer, parse.buffer, (uint8_t*)parse.buffer + parse.offset); - achievement->trigger->memrefs = NULL; /* memrefs managed by runtime */ + rc_buffer_consume(buffer, preparse.parse.buffer, (uint8_t*)preparse.parse.buffer + preparse.parse.offset); } - rc_destroy_parse_state(&parse); + rc_destroy_preparse_state(&preparse); } achievement->created_time = read->created; @@ -1860,10 +1861,11 @@ static void rc_client_copy_leaderboards(rc_client_load_state_t* load_state, rc_client_leaderboard_info_t* leaderboards; rc_client_leaderboard_info_t* leaderboard; rc_buffer_t* buffer; - rc_parse_state_t parse; + rc_preparse_state_t preparse; const char* memaddr; const char* ptr; size_t size; + rc_lboard_t* lboard; int lboard_size; subset->leaderboards = NULL; @@ -1913,29 +1915,32 @@ static void rc_client_copy_leaderboards(rc_client_load_state_t* load_state, leaderboard->value_djb2 = hash; } - lboard_size = rc_lboard_size(memaddr); + rc_init_preparse_state(&preparse, NULL, 0); + preparse.parse.existing_memrefs = load_state->game->runtime.memrefs; + lboard = RC_ALLOC(rc_lboard_t, &preparse.parse); + rc_parse_lboard_internal(lboard, memaddr, &preparse.parse); + + lboard_size = preparse.parse.offset; if (lboard_size < 0) { RC_CLIENT_LOG_WARN_FORMATTED(load_state->client, "Parse error %d processing leaderboard %u", lboard_size, read->id); leaderboard->public_.state = RC_CLIENT_LEADERBOARD_STATE_DISABLED; } else { /* populate the item, using the communal memrefs pool */ - rc_init_parse_state(&parse, rc_buffer_reserve(buffer, lboard_size), NULL, 0); - parse.first_memref = &load_state->game->runtime.memrefs; - parse.variables = &load_state->game->runtime.variables; - leaderboard->lboard = RC_ALLOC(rc_lboard_t, &parse); - rc_parse_lboard_internal(leaderboard->lboard, memaddr, &parse); - - if (parse.offset < 0) { - RC_CLIENT_LOG_WARN_FORMATTED(load_state->client, "Parse error %d processing leaderboard %u", parse.offset, read->id); + rc_reset_parse_state(&preparse.parse, rc_buffer_reserve(buffer, lboard_size), NULL, 0); + rc_preparse_reserve_memrefs(&preparse, load_state->game->runtime.memrefs); + leaderboard->lboard = RC_ALLOC(rc_lboard_t, &preparse.parse); + rc_parse_lboard_internal(leaderboard->lboard, memaddr, &preparse.parse); + + if (preparse.parse.offset < 0) { + RC_CLIENT_LOG_WARN_FORMATTED(load_state->client, "Parse error %d processing leaderboard %u", preparse.parse.offset, read->id); leaderboard->public_.state = RC_CLIENT_LEADERBOARD_STATE_DISABLED; } else { - rc_buffer_consume(buffer, parse.buffer, (uint8_t*)parse.buffer + parse.offset); - leaderboard->lboard->memrefs = NULL; /* memrefs managed by runtime */ + rc_buffer_consume(buffer, preparse.parse.buffer, (uint8_t*)preparse.parse.buffer + preparse.parse.offset); } - rc_destroy_parse_state(&parse); + rc_destroy_preparse_state(&preparse); } ++leaderboard; @@ -4848,22 +4853,11 @@ void rc_client_set_read_memory_function(rc_client_t* client, rc_client_read_memo static void rc_client_invalidate_processing_memref(rc_client_t* client) { - rc_memref_t** next_memref = &client->game->runtime.memrefs; - rc_memref_t* memref; - /* if processing_memref is not set, this occurred following a pointer chain. ignore it. */ if (!client->state.processing_memref) return; - /* invalid memref. remove from chain so we don't have to evaluate it in the future. - * it's still there, so anything referencing it will always fetch the current value. */ - while ((memref = *next_memref) != NULL) { - if (memref == client->state.processing_memref) { - *next_memref = memref->next; - break; - } - next_memref = &memref->next; - } + client->state.processing_memref->value.type = RC_VALUE_TYPE_NONE; rc_client_invalidate_memref_achievements(client->game, client, client->state.processing_memref); rc_client_invalidate_memref_leaderboards(client->game, client, client->state.processing_memref); @@ -4971,40 +4965,57 @@ int rc_client_is_processing_required(rc_client_t* client) return (client->game->runtime.richpresence && client->game->runtime.richpresence->richpresence); } -static void rc_client_update_memref_values(rc_client_t* client) -{ - rc_memref_t* memref = client->game->runtime.memrefs; - uint32_t value; +static void rc_client_update_memref_values(rc_client_t* client) { + rc_memrefs_t* memrefs = client->game->runtime.memrefs; + rc_memref_list_t* memref_list; + rc_modified_memref_list_t* modified_memref_list; int invalidated_memref = 0; - for (; memref; memref = memref->next) { - switch (memref->value.memref_type) { - case RC_MEMREF_TYPE_MEMREF: - /* if processing_memref is set, and the memory read fails, all dependent achievements will be disabled */ - client->state.processing_memref = memref; + memref_list = &memrefs->memrefs; + do { + rc_memref_t* memref = memref_list->items; + const rc_memref_t* memref_stop = memref + memref_list->count; + uint32_t value; - value = rc_peek_value(memref->address, memref->value.size, client->state.legacy_peek, client); + for (; memref < memref_stop; ++memref) { + if (memref->value.type == RC_VALUE_TYPE_NONE) + continue; - if (client->state.processing_memref) { - rc_update_memref_value(&memref->value, value); - } - else { - /* if the peek function cleared the processing_memref, the memref was invalidated */ - invalidated_memref = 1; - } - break; + /* if processing_memref is set, and the memory read fails, all dependent achievements will be disabled */ + client->state.processing_memref = memref; - case RC_MEMREF_TYPE_MODIFIED_MEMREF: - /* clear processing_memref so an invalid read doesn't disable anything */ - client->state.processing_memref = NULL; - rc_update_memref_value(&memref->value, - rc_get_modified_memref_value((rc_modified_memref_t*)memref, client->state.legacy_peek, client)); - break; + value = rc_peek_value(memref->address, memref->value.size, client->state.legacy_peek, client); + + if (client->state.processing_memref) { + rc_update_memref_value(&memref->value, value); + } + else { + /* if the peek function cleared the processing_memref, the memref was invalidated */ + invalidated_memref = 1; + } } - } + + memref_list = memref_list->next; + } while (memref_list); client->state.processing_memref = NULL; + modified_memref_list = &memrefs->modified_memrefs; + if (modified_memref_list->count) { + do { + rc_modified_memref_t* modified_memref = modified_memref_list->items; + const rc_modified_memref_t* modified_memref_stop = modified_memref + modified_memref_list->count; + + for (; modified_memref < modified_memref_stop; ++modified_memref) + rc_update_memref_value(&modified_memref->memref.value, rc_get_modified_memref_value(modified_memref, client->state.legacy_peek, client)); + + modified_memref_list = modified_memref_list->next; + } while (modified_memref_list); + } + + if (client->game->runtime.richpresence && client->game->runtime.richpresence->richpresence) + rc_update_values(client->game->runtime.richpresence->richpresence->values, client->state.legacy_peek, client, NULL); + if (invalidated_memref) rc_client_update_active_achievements(client->game); } @@ -5418,7 +5429,6 @@ void rc_client_do_frame(rc_client_t* client) rc_client_reset_pending_events(client); rc_client_update_memref_values(client); - rc_update_variables(client->game->runtime.variables, client->state.legacy_peek, client, NULL); client->game->progress_tracker.progress = 0.0; for (subset = client->game->subsets; subset; subset = subset->next) { @@ -5590,9 +5600,8 @@ static void rc_client_reset_richpresence(rc_client_t* client) static void rc_client_reset_variables(rc_client_t* client) { - rc_value_t* variable = client->game->runtime.variables; - for (; variable; variable = variable->next) - rc_reset_value(variable); + if (client->game->runtime.richpresence && client->game->runtime.richpresence->richpresence) + rc_reset_values(client->game->runtime.richpresence->richpresence->values); } static void rc_client_reset_all(rc_client_t* client) diff --git a/src/rc_util.c b/src/rc_util.c index b6aa5bf6..7d4d966e 100644 --- a/src/rc_util.c +++ b/src/rc_util.c @@ -38,6 +38,9 @@ void rc_buffer_destroy(rc_buffer_t* buffer) total += (int)(chunk->end - chunk->start); wasted += (int)(chunk->end - chunk->write); ++count; +#endif +#ifdef DEBUG_BUFFERS + printf("< free %p.%p\n", (void*)buffer, (void*)chunk); #endif free(chunk); chunk = next; @@ -70,6 +73,10 @@ uint8_t* rc_buffer_reserve(rc_buffer_t* buffer, size_t amount) if (!chunk->next) break; +#ifdef DEBUG_BUFFERS + printf("> alloc %p.%p\n", (void*)buffer, (void*)chunk->next); +#endif + chunk->next->start = (uint8_t*)chunk->next + chunk_header_size; chunk->next->write = chunk->next->start; chunk->next->end = (uint8_t*)chunk->next + alloc_size; diff --git a/src/rcheevos/alloc.c b/src/rcheevos/alloc.c index d045c437..68b0514c 100644 --- a/src/rcheevos/alloc.c +++ b/src/rcheevos/alloc.c @@ -94,78 +94,223 @@ char* rc_alloc_str(rc_parse_state_t* parse, const char* text, size_t length) { return ptr; } -void rc_sync_operand(rc_operand_t* operand, rc_parse_state_t* parse, const rc_memref_t* memrefs) +void rc_init_preparse_state(rc_preparse_state_t* preparse, lua_State* L, int funcs_ndx) { - if (rc_operand_is_memref(operand) || rc_operand_is_recall(operand)) { - const rc_memref_t* src_memref = operand->value.memref; - const rc_memref_t* memref; + rc_init_parse_state(&preparse->parse, NULL, L, funcs_ndx); + rc_init_parse_state_memrefs(&preparse->parse, &preparse->memrefs); +} + +void rc_destroy_preparse_state(rc_preparse_state_t* preparse) +{ + rc_destroy_parse_state(&preparse->parse); +} - memref = memrefs; - while (memref && memref != src_memref) - memref = memref->next; +void rc_preparse_alloc_memrefs(rc_memrefs_t* memrefs, rc_preparse_state_t* preparse) +{ + const uint32_t num_memrefs = rc_memrefs_count_memrefs(&preparse->memrefs); + const uint32_t num_modified_memrefs = rc_memrefs_count_modified_memrefs(&preparse->memrefs); - if (memref) { - switch (memref->value.memref_type) { - case RC_MEMREF_TYPE_MEMREF: - operand->value.memref = rc_alloc_memref(parse, memref->address, memref->value.size); - break; + if (preparse->parse.offset < 0) + return; - case RC_MEMREF_TYPE_MODIFIED_MEMREF: { - const rc_modified_memref_t* modified_memref = (const rc_modified_memref_t*)memref; + if (memrefs) { + memset(memrefs, 0, sizeof(*memrefs)); + preparse->parse.memrefs = memrefs; + } - rc_modified_memref_t* dst_modified_memref = rc_alloc_modified_memref(parse, modified_memref->memref.value.size, - &modified_memref->parent, modified_memref->modifier_type, &modified_memref->modifier); + if (num_memrefs) { + rc_memref_t* memref_items = RC_ALLOC_ARRAY(rc_memref_t, num_memrefs, &preparse->parse); - operand->value.memref = &dst_modified_memref->memref; - break; - } - } + if (memrefs) { + memrefs->memrefs.capacity = num_memrefs; + memrefs->memrefs.items = memref_items; } } + + if (num_modified_memrefs) { + rc_modified_memref_t* modified_memref_items = + RC_ALLOC_ARRAY(rc_modified_memref_t, num_modified_memrefs, &preparse->parse); + + if (memrefs) { + memrefs->modified_memrefs.capacity = num_modified_memrefs; + memrefs->modified_memrefs.items = modified_memref_items; + } + } + + /* when preparsing, this structure will be allocated at the end. when it's allocated earlier + * in the buffer, it could be followed by something aligned at 8 bytes. force the offset to + * an 8-byte boundary */ + if (!memrefs) { + rc_alloc(preparse->parse.buffer, &preparse->parse.offset, 0, 8, &preparse->parse.scratch, 0); + } +} + +static uint32_t rc_preparse_array_size(uint32_t needed, uint32_t minimum) +{ + while (minimum < needed) + minimum <<= 1; + + return minimum; } -void rc_copy_memrefs_into_parse_state(rc_parse_state_t* parse, rc_memref_t* memrefs) +void rc_preparse_reserve_memrefs(rc_preparse_state_t* preparse, rc_memrefs_t* memrefs) { - rc_memref_t* memref; - for (memref = memrefs; memref; memref = memref->next) { - switch (memref->value.memref_type) { - case RC_MEMREF_TYPE_MEMREF: - rc_alloc_memref(parse, memref->address, memref->value.size); + uint32_t num_memrefs = rc_memrefs_count_memrefs(&preparse->memrefs); + uint32_t num_modified_memrefs = rc_memrefs_count_modified_memrefs(&preparse->memrefs); + uint32_t available; + + if (preparse->parse.offset < 0) + return; + + if (num_memrefs) { + rc_memref_list_t* memref_list = &memrefs->memrefs; + while (memref_list->count == memref_list->capacity) { + if (!memref_list->next) break; - case RC_MEMREF_TYPE_MODIFIED_MEMREF: { - rc_modified_memref_t* modified_memref = (rc_modified_memref_t*)memref; - rc_sync_operand(&modified_memref->parent, parse, memrefs); - rc_sync_operand(&modified_memref->modifier, parse, memrefs); + memref_list = memref_list->next; + } + + available = memref_list->capacity - memref_list->count; + if (available < num_memrefs) { + rc_memref_list_t* new_memref_list = (rc_memref_list_t*)calloc(1, sizeof(rc_memref_list_t)); + if (!new_memref_list) + return; + + new_memref_list->capacity = rc_preparse_array_size(num_memrefs - available, 16); + new_memref_list->items = (rc_memref_t*)malloc(new_memref_list->capacity * sizeof(rc_memref_t)); + new_memref_list->allocated = 1; + memref_list->next = new_memref_list; + } + } - rc_alloc_modified_memref(parse, modified_memref->memref.value.size, - &modified_memref->parent, modified_memref->modifier_type, &modified_memref->modifier); + if (num_modified_memrefs) { + rc_modified_memref_list_t* modified_memref_list = &memrefs->modified_memrefs; + while (modified_memref_list->count == modified_memref_list->capacity) { + if (!modified_memref_list->next) break; + + modified_memref_list = modified_memref_list->next; + } + + available = modified_memref_list->capacity - modified_memref_list->count; + if (available < num_modified_memrefs) { + rc_modified_memref_list_t* new_modified_memref_list = (rc_modified_memref_list_t*)calloc(1, sizeof(rc_modified_memref_list_t)); + if (!new_modified_memref_list) + return; + + new_modified_memref_list->capacity = rc_preparse_array_size(num_modified_memrefs - available, 8); + new_modified_memref_list->items = (rc_modified_memref_t*)malloc(new_modified_memref_list->capacity * sizeof(rc_modified_memref_t)); + new_modified_memref_list->allocated = 1; + modified_memref_list->next = new_modified_memref_list; + } + } + + preparse->parse.memrefs = memrefs; +} + +static void rc_preparse_sync_operand(rc_operand_t* operand, rc_parse_state_t* parse, const rc_memrefs_t* memrefs) +{ + if (rc_operand_is_memref(operand) || rc_operand_is_recall(operand)) { + const rc_memref_t* src_memref = operand->value.memref; + + if (src_memref->value.memref_type == RC_MEMREF_TYPE_MODIFIED_MEMREF) { + const rc_modified_memref_list_t* modified_memref_list = &memrefs->modified_memrefs; + for (; modified_memref_list; modified_memref_list = modified_memref_list->next) { + const rc_modified_memref_t* modified_memref = modified_memref_list->items; + const rc_modified_memref_t* modified_memref_end = modified_memref + modified_memref_list->count; + + for (; modified_memref < modified_memref_end; ++modified_memref) { + if ((const rc_modified_memref_t*)src_memref == modified_memref) { + rc_modified_memref_t* dst_modified_memref = rc_alloc_modified_memref(parse, modified_memref->memref.value.size, + &modified_memref->parent, modified_memref->modifier_type, &modified_memref->modifier); + + operand->value.memref = &dst_modified_memref->memref; + return; + } + } + } + } + else { + const rc_memref_list_t* memref_list = &memrefs->memrefs; + for (; memref_list; memref_list = memref_list->next) { + const rc_memref_t* memref = memref_list->items; + const rc_memref_t* memref_end = memref + memref_list->count; + + for (; memref < memref_end; ++memref) { + if (src_memref == memref) { + operand->value.memref = rc_alloc_memref(parse, memref->address, memref->value.size); + return; + } + } } } } } -void rc_init_parse_state(rc_parse_state_t* parse, void* buffer, lua_State* L, int funcs_ndx) +void rc_preparse_copy_memrefs(rc_parse_state_t* parse, rc_memrefs_t* memrefs) { - /* could use memset here, but rc_parse_state_t contains a 512 byte buffer that doesn't need to be initialized */ - parse->offset = 0; + const rc_memref_list_t* memref_list = &memrefs->memrefs; + const rc_modified_memref_list_t* modified_memref_list = &memrefs->modified_memrefs; + + for (; memref_list; memref_list = memref_list->next) { + const rc_memref_t* memref = memref_list->items; + const rc_memref_t* memref_end = memref + memref_list->count; + + for (; memref < memref_end; ++memref) + rc_alloc_memref(parse, memref->address, memref->value.size); + } + + for (; modified_memref_list; modified_memref_list = modified_memref_list->next) { + rc_modified_memref_t* modified_memref = modified_memref_list->items; + const rc_modified_memref_t* modified_memref_end = modified_memref + modified_memref_list->count; + + for (; modified_memref < modified_memref_end; ++modified_memref) { + rc_preparse_sync_operand(&modified_memref->parent, parse, memrefs); + rc_preparse_sync_operand(&modified_memref->modifier, parse, memrefs); + + rc_alloc_modified_memref(parse, modified_memref->memref.value.size, + &modified_memref->parent, modified_memref->modifier_type, &modified_memref->modifier); + } + } +} + +void rc_reset_parse_state(rc_parse_state_t* parse, void* buffer, lua_State* L, int funcs_ndx) +{ +#ifndef RC_DISABLE_LUA parse->L = L; parse->funcs_ndx = funcs_ndx; +#else + (void)L; + (void)funcs_ndx; +#endif + parse->buffer = buffer; - parse->scratch.strings = NULL; - rc_buffer_init(&parse->scratch.buffer); - memset(&parse->scratch.objs, 0, sizeof(parse->scratch.objs)); - parse->first_memref = NULL; + + parse->offset = 0; + parse->memrefs = NULL; + parse->existing_memrefs = NULL; parse->variables = NULL; parse->measured_target = 0; parse->lines_read = 0; + parse->addsource_oper = RC_OPERATOR_NONE; parse->addsource_parent.type = RC_OPERAND_NONE; parse->indirect_parent.type = RC_OPERAND_NONE; parse->remember.type = RC_OPERAND_NONE; parse->is_value = 0; parse->has_required_hits = 0; parse->measured_as_percent = 0; + + parse->scratch.strings = NULL; +} + +void rc_init_parse_state(rc_parse_state_t* parse, void* buffer, lua_State* L, int funcs_ndx) +{ + /* could use memset here, but rc_parse_state_t contains a 512 byte buffer that doesn't need to be initialized */ + rc_buffer_init(&parse->scratch.buffer); + memset(&parse->scratch.objs, 0, sizeof(parse->scratch.objs)); + + rc_reset_parse_state(parse, buffer, L, funcs_ndx); } void rc_destroy_parse_state(rc_parse_state_t* parse) diff --git a/src/rcheevos/condition.c b/src/rcheevos/condition.c index 15e3a82d..57913f26 100644 --- a/src/rcheevos/condition.c +++ b/src/rcheevos/condition.c @@ -173,6 +173,11 @@ void rc_condition_convert_to_operand(const rc_condition_t* condition, rc_operand if (rc_operand_is_float(&condition->operand1) || rc_operand_is_float(&condition->operand2)) new_size = RC_MEMSIZE_FLOAT; + /* NOTE: this makes the operand include the modification, but we have to also + * leave the modification in the condition so the condition reflects the actual + * definition. This doesn't affect the evaluation logic since this method is only + * called for combining conditions and Measured, and the Measured handling function + * ignores the operator assuming it's been handled by a modified memref chain */ operand->value.memref = (rc_memref_t*)rc_alloc_modified_memref(parse, new_size, &condition->operand1, condition->oper, &condition->operand2); diff --git a/src/rcheevos/condset.c b/src/rcheevos/condset.c index d7cf2843..1ac64b33 100644 --- a/src/rcheevos/condset.c +++ b/src/rcheevos/condset.c @@ -49,7 +49,7 @@ static int rc_classify_condition(const rc_condition_t* cond) { static int32_t rc_classify_conditions(rc_condset_t* self, const char* memaddr) { rc_parse_state_t parse; - rc_memref_t* memrefs; + rc_memrefs_t memrefs; rc_condition_t condition; int classification; uint32_t index = 0; @@ -105,7 +105,7 @@ static int32_t rc_classify_conditions(rc_condset_t* self, const char* memaddr) { static int rc_find_next_classification(const char* memaddr) { rc_parse_state_t parse; - rc_memref_t* memrefs; + rc_memrefs_t memrefs; rc_condition_t condition; int classification; @@ -114,6 +114,8 @@ static int rc_find_next_classification(const char* memaddr) { do { rc_parse_condition_internal(&condition, &memaddr, &parse); + if (parse.offset < 0) + break; classification = rc_classify_condition(&condition); switch (classification) { @@ -710,8 +712,6 @@ int rc_test_condset(rc_condset_t* self, rc_eval_state_t* eval_state) { eval_state->measured_value.value.u32 = 0; } } - - conditions += self->num_pause_conditions; } if (self->num_other_conditions) { diff --git a/src/rcheevos/lboard.c b/src/rcheevos/lboard.c index 47e05f27..dbe8a7d0 100644 --- a/src/rcheevos/lboard.c +++ b/src/rcheevos/lboard.c @@ -29,7 +29,6 @@ void rc_parse_lboard_internal(rc_lboard_t* self, const char* memaddr, rc_parse_s if (*memaddr && *memaddr != ':') { found |= RC_LBOARD_START; rc_parse_trigger_internal(&self->start, &memaddr, parse); - self->start.memrefs = 0; } } else if ((memaddr[0] == 'c' || memaddr[0] == 'C') && @@ -44,7 +43,6 @@ void rc_parse_lboard_internal(rc_lboard_t* self, const char* memaddr, rc_parse_s if (*memaddr && *memaddr != ':') { found |= RC_LBOARD_CANCEL; rc_parse_trigger_internal(&self->cancel, &memaddr, parse); - self->cancel.memrefs = 0; } } else if ((memaddr[0] == 's' || memaddr[0] == 'S') && @@ -59,7 +57,6 @@ void rc_parse_lboard_internal(rc_lboard_t* self, const char* memaddr, rc_parse_s if (*memaddr && *memaddr != ':') { found |= RC_LBOARD_SUBMIT; rc_parse_trigger_internal(&self->submit, &memaddr, parse); - self->submit.memrefs = 0; } } else if ((memaddr[0] == 'v' || memaddr[0] == 'V') && @@ -74,7 +71,6 @@ void rc_parse_lboard_internal(rc_lboard_t* self, const char* memaddr, rc_parse_s if (*memaddr && *memaddr != ':') { found |= RC_LBOARD_VALUE; rc_parse_value_internal(&self->value, &memaddr, parse); - self->value.memrefs = 0; } } else if ((memaddr[0] == 'p' || memaddr[0] == 'P') && @@ -91,7 +87,6 @@ void rc_parse_lboard_internal(rc_lboard_t* self, const char* memaddr, rc_parse_s self->progress = RC_ALLOC(rc_value_t, parse); rc_parse_value_internal(self->progress, &memaddr, parse); - self->progress->memrefs = 0; } } @@ -130,44 +125,55 @@ void rc_parse_lboard_internal(rc_lboard_t* self, const char* memaddr, rc_parse_s } self->state = RC_LBOARD_STATE_WAITING; + self->has_memrefs = 0; } int rc_lboard_size(const char* memaddr) { - rc_lboard_t* self; - rc_parse_state_t parse; - rc_memref_t* first_memref; - rc_init_parse_state(&parse, 0, 0, 0); - rc_init_parse_state_memrefs(&parse, &first_memref); + rc_lboard_with_memrefs_t* lboard; + rc_preparse_state_t preparse; + rc_init_preparse_state(&preparse, NULL, 0); - self = RC_ALLOC(rc_lboard_t, &parse); - rc_parse_lboard_internal(self, memaddr, &parse); + lboard = RC_ALLOC(rc_lboard_with_memrefs_t, &preparse.parse); + rc_parse_lboard_internal(&lboard->lboard, memaddr, &preparse.parse); + rc_preparse_alloc_memrefs(NULL, &preparse); - rc_destroy_parse_state(&parse); - return parse.offset; + rc_destroy_preparse_state(&preparse); + return preparse.parse.offset; } rc_lboard_t* rc_parse_lboard(void* buffer, const char* memaddr, lua_State* L, int funcs_ndx) { - rc_lboard_t* self; - rc_parse_state_t parse; + rc_lboard_with_memrefs_t* lboard; + rc_preparse_state_t preparse; if (!buffer || !memaddr) return 0; - rc_init_parse_state(&parse, buffer, L, funcs_ndx); + rc_init_preparse_state(&preparse, L, funcs_ndx); + lboard = RC_ALLOC(rc_lboard_with_memrefs_t, &preparse.parse); + rc_parse_lboard_internal(&lboard->lboard, memaddr, &preparse.parse); - self = RC_ALLOC(rc_lboard_t, &parse); - rc_init_parse_state_memrefs(&parse, &self->memrefs); + rc_reset_parse_state(&preparse.parse, buffer, L, funcs_ndx); + lboard = RC_ALLOC(rc_lboard_with_memrefs_t, &preparse.parse); + rc_preparse_alloc_memrefs(&lboard->memrefs, &preparse); - rc_parse_lboard_internal(self, memaddr, &parse); + rc_parse_lboard_internal(&lboard->lboard, memaddr, &preparse.parse); + lboard->lboard.has_memrefs = 1; - rc_destroy_parse_state(&parse); - return (parse.offset >= 0) ? self : 0; + rc_destroy_preparse_state(&preparse); + return (preparse.parse.offset >= 0) ? &lboard->lboard : NULL; +} + +static void rc_update_lboard_memrefs(rc_lboard_t* self, rc_peek_t peek, void* ud) { + if (self->has_memrefs) { + rc_lboard_with_memrefs_t* lboard = (rc_lboard_with_memrefs_t*)self; + rc_update_memref_values(&lboard->memrefs, peek, ud); + } } int rc_evaluate_lboard(rc_lboard_t* self, int32_t* value, rc_peek_t peek, void* peek_ud, lua_State* L) { int start_ok, cancel_ok, submit_ok; - rc_update_memref_values(self->memrefs, peek, peek_ud); + rc_update_lboard_memrefs(self, peek, peek_ud); if (self->state == RC_LBOARD_STATE_INACTIVE || self->state == RC_LBOARD_STATE_DISABLED) return RC_LBOARD_STATE_INACTIVE; diff --git a/src/rcheevos/memref.c b/src/rcheevos/memref.c index 380ae0cf..70622bfb 100644 --- a/src/rcheevos/memref.c +++ b/src/rcheevos/memref.c @@ -7,22 +7,68 @@ #define MEMREF_PLACEHOLDER_ADDRESS 0xFFFFFFFF rc_memref_t* rc_alloc_memref(rc_parse_state_t* parse, uint32_t address, uint8_t size) { - rc_memref_t** next_memref; - rc_memref_t* memref; + rc_memref_list_t* memref_list = NULL; + rc_memref_t* memref = NULL; + int i; - /* attempt to find an existing memref that can be shared */ - next_memref = parse->first_memref; - while (*next_memref) { - memref = *next_memref; - if (memref->address == address && memref->value.memref_type == RC_MEMREF_TYPE_MEMREF && memref->value.size == size) - return memref; + for (i = 0; i < 2; i++) { + if (i == 0) { + if (!parse->existing_memrefs) + continue; - next_memref = &memref->next; + memref_list = &parse->existing_memrefs->memrefs; + } + else { + memref_list = &parse->memrefs->memrefs; + } + + do + { + const rc_memref_t* memref_stop; + + memref = memref_list->items; + memref_stop = memref + memref_list->count; + + for (; memref < memref_stop; ++memref) { + if (memref->address == address && memref->value.size == size) + return memref; + } + + if (!memref_list->next) + break; + + memref_list = memref_list->next; + } while (1); } - /* no match found, create a new entry */ - memref = RC_ALLOC_SCRATCH(rc_memref_t, parse); - *next_memref = memref; + /* no match found, find a place to put the new entry */ + memref_list = &parse->memrefs->memrefs; + while (memref_list->count == memref_list->capacity && memref_list->next) + memref_list = memref_list->next; + + /* create a new entry */ + if (memref_list->count < memref_list->capacity) { + memref = &memref_list->items[memref_list->count++]; + } else { + const int32_t old_offset = parse->offset; + + if (memref_list->capacity != 0) { + memref_list = memref_list->next = RC_ALLOC_SCRATCH(rc_memref_list_t, parse); + memref_list->next = NULL; + } + + memref_list->items = RC_ALLOC_ARRAY_SCRATCH(rc_memref_t, 8, parse); + memref_list->count = 1; + memref_list->capacity = 8; + memref_list->allocated = 0; + + memref = memref_list->items; + + /* in preparse mode, don't count this memory, we'll do a single allocation once we have + * the final total */ + if (!parse->buffer) + parse->offset = old_offset; + } memset(memref, 0, sizeof(*memref)); memref->value.memref_type = RC_MEMREF_TYPE_MEMREF; @@ -35,29 +81,71 @@ rc_memref_t* rc_alloc_memref(rc_parse_state_t* parse, uint32_t address, uint8_t rc_modified_memref_t* rc_alloc_modified_memref(rc_parse_state_t* parse, uint8_t size, const rc_operand_t* parent, uint8_t modifier_type, const rc_operand_t* modifier) { - rc_memref_t** next_memref; - rc_memref_t* memref; - rc_modified_memref_t* modified_memref; - - /* attempt to find an existing memref that can be shared */ - next_memref = parse->first_memref; - while (*next_memref) { - memref = *next_memref; - if (memref->value.memref_type == RC_MEMREF_TYPE_MODIFIED_MEMREF && memref->value.size == size) { - modified_memref = (rc_modified_memref_t*)memref; - if (modified_memref->modifier_type == modifier_type && - rc_operands_are_equal(&modified_memref->parent, parent) && - rc_operands_are_equal(&modified_memref->modifier, modifier)) { - return modified_memref; - } + rc_modified_memref_list_t* modified_memref_list = NULL; + rc_modified_memref_t* modified_memref = NULL; + int i = 0; + + for (i = 0; i < 2; i++) { + if (i == 0) { + if (!parse->existing_memrefs) + continue; + + modified_memref_list = &parse->existing_memrefs->modified_memrefs; + } + else { + modified_memref_list = &parse->memrefs->modified_memrefs; } - next_memref = &memref->next; + do { + const rc_modified_memref_t* memref_stop; + + modified_memref = modified_memref_list->items; + memref_stop = modified_memref + modified_memref_list->count; + + for (; modified_memref < memref_stop; ++modified_memref) { + if (modified_memref->memref.value.size == size && + modified_memref->modifier_type == modifier_type && + rc_operands_are_equal(&modified_memref->parent, parent) && + rc_operands_are_equal(&modified_memref->modifier, modifier)) { + return modified_memref; + } + } + + if (!modified_memref_list->next) + break; + + modified_memref_list = modified_memref_list->next; + } while (1); } - /* no match found, create a new entry */ - modified_memref = RC_ALLOC_SCRATCH(rc_modified_memref_t, parse); - *next_memref = (rc_memref_t*)modified_memref; + /* no match found, find a place to put the new entry */ + modified_memref_list = &parse->memrefs->modified_memrefs; + while (modified_memref_list->count == modified_memref_list->capacity && modified_memref_list->next) + modified_memref_list = modified_memref_list->next; + + /* create a new entry */ + if (modified_memref_list->count < modified_memref_list->capacity) { + modified_memref = &modified_memref_list->items[modified_memref_list->count++]; + } else { + const int32_t old_offset = parse->offset; + + if (modified_memref_list->capacity != 0) { + modified_memref_list = modified_memref_list->next = RC_ALLOC_SCRATCH(rc_modified_memref_list_t, parse); + modified_memref_list->next = NULL; + } + + modified_memref_list->items = RC_ALLOC_ARRAY_SCRATCH(rc_modified_memref_t, 8, parse); + modified_memref_list->count = 1; + modified_memref_list->capacity = 8; + modified_memref_list->allocated = 0; + + modified_memref = modified_memref_list->items; + + /* in preparse mode, don't count this memory, we'll do a single allocation once we have + * the final total */ + if (!parse->buffer) + parse->offset = old_offset; + } memset(modified_memref, 0, sizeof(*modified_memref)); modified_memref->memref.value.memref_type = RC_MEMREF_TYPE_MODIFIED_MEMREF; @@ -71,6 +159,79 @@ rc_modified_memref_t* rc_alloc_modified_memref(rc_parse_state_t* parse, uint8_t return modified_memref; } +void rc_memrefs_init(rc_memrefs_t* memrefs) +{ + memset(memrefs, 0, sizeof(*memrefs)); + + memrefs->memrefs.capacity = 32; + memrefs->memrefs.items = + (rc_memref_t*)malloc(memrefs->memrefs.capacity * sizeof(rc_memref_t)); + memrefs->memrefs.allocated = 1; + + memrefs->modified_memrefs.capacity = 16; + memrefs->modified_memrefs.items = + (rc_modified_memref_t*)malloc(memrefs->modified_memrefs.capacity * sizeof(rc_modified_memref_t)); + memrefs->modified_memrefs.allocated = 1; +} + +void rc_memrefs_destroy(rc_memrefs_t* memrefs) +{ + rc_memref_list_t* memref_list = &memrefs->memrefs; + rc_modified_memref_list_t* modified_memref_list = &memrefs->modified_memrefs; + + do { + rc_memref_list_t* current_memref_list = memref_list; + memref_list = memref_list->next; + + if (current_memref_list->allocated) { + if (current_memref_list->items) + free(current_memref_list->items); + + if (current_memref_list != &memrefs->memrefs) + free(current_memref_list); + } + } while (memref_list); + + do { + rc_modified_memref_list_t* current_modified_memref_list = modified_memref_list; + modified_memref_list = modified_memref_list->next; + + if (current_modified_memref_list->allocated) { + if (current_modified_memref_list->items) + free(current_modified_memref_list->items); + + if (current_modified_memref_list != &memrefs->modified_memrefs) + free(current_modified_memref_list); + } + } while (modified_memref_list); + + free(memrefs); +} + +uint32_t rc_memrefs_count_memrefs(const rc_memrefs_t* memrefs) +{ + uint32_t count = 0; + const rc_memref_list_t* memref_list = &memrefs->memrefs; + while (memref_list) { + count += memref_list->count; + memref_list = memref_list->next; + } + + return count; +} + +uint32_t rc_memrefs_count_modified_memrefs(const rc_memrefs_t* memrefs) +{ + uint32_t count = 0; + const rc_modified_memref_list_t* modified_memref_list = &memrefs->modified_memrefs; + while (modified_memref_list) { + count += modified_memref_list->count; + modified_memref_list = modified_memref_list->next; + } + + return count; +} + int rc_parse_memref(const char** memaddr, uint8_t* size, uint32_t* address) { const char* aux = *memaddr; char* end; @@ -515,9 +676,12 @@ void rc_update_memref_value(rc_memref_value_t* memref, uint32_t new_value) { } } -void rc_init_parse_state_memrefs(rc_parse_state_t* parse, rc_memref_t** memrefs) { - parse->first_memref = memrefs; - *memrefs = 0; +void rc_init_parse_state_memrefs(rc_parse_state_t* parse, rc_memrefs_t* memrefs) +{ + if (memrefs) + memset(memrefs, 0, sizeof(*memrefs)); + + parse->memrefs = memrefs; } static uint32_t rc_get_memref_value_value(const rc_memref_value_t* memref, int operand_type) { @@ -574,19 +738,34 @@ uint32_t rc_get_modified_memref_value(const rc_modified_memref_t* memref, rc_pee return value.value.u32; } -void rc_update_memref_values(rc_memref_t* memref, rc_peek_t peek, void* ud) { - while (memref) { - /* indirect memory references are not shared and will be updated in rc_get_memref_value */ - switch (memref->value.memref_type) { - case RC_MEMREF_TYPE_MEMREF: - rc_update_memref_value(&memref->value, rc_peek_value(memref->address, memref->value.size, peek, ud)); - break; +void rc_update_memref_values(rc_memrefs_t* memrefs, rc_peek_t peek, void* ud) { + rc_memref_list_t* memref_list; + rc_modified_memref_list_t* modified_memref_list; - case RC_MEMREF_TYPE_MODIFIED_MEMREF: - rc_update_memref_value(&memref->value, rc_get_modified_memref_value((rc_modified_memref_t*)memref, peek, ud)); - break; + memref_list = &memrefs->memrefs; + do + { + rc_memref_t* memref = memref_list->items; + const rc_memref_t* memref_stop = memref + memref_list->count; + + for (; memref < memref_stop; ++memref) { + if (memref->value.type != RC_VALUE_TYPE_NONE) + rc_update_memref_value(&memref->value, rc_peek_value(memref->address, memref->value.size, peek, ud)); } - memref = memref->next; + memref_list = memref_list->next; + } while (memref_list); + + modified_memref_list = &memrefs->modified_memrefs; + if (modified_memref_list->count) { + do { + rc_modified_memref_t* modified_memref = modified_memref_list->items; + const rc_modified_memref_t* modified_memref_stop = modified_memref + modified_memref_list->count; + + for (; modified_memref < modified_memref_stop; ++modified_memref) + rc_update_memref_value(&modified_memref->memref.value, rc_get_modified_memref_value(modified_memref, peek, ud)); + + modified_memref_list = modified_memref_list->next; + } while (modified_memref_list); } } diff --git a/src/rcheevos/rc_internal.h b/src/rcheevos/rc_internal.h index b4d81d5b..d412be83 100644 --- a/src/rcheevos/rc_internal.h +++ b/src/rcheevos/rc_internal.h @@ -21,6 +21,47 @@ typedef struct rc_modified_memref_t { } rc_modified_memref_t; +typedef struct rc_memref_list_t { + rc_memref_t* items; + struct rc_memref_list_t* next; + uint16_t count; + uint16_t capacity; + uint8_t allocated; +} rc_memref_list_t; + +typedef struct rc_modified_memref_list_t { + rc_modified_memref_t* items; + struct rc_modified_memref_list_t* next; + uint16_t count; + uint16_t capacity; + uint8_t allocated; +} rc_modified_memref_list_t; + +typedef struct rc_memrefs_t { + rc_memref_list_t memrefs; + rc_modified_memref_list_t modified_memrefs; +} rc_memrefs_t; + +typedef struct rc_trigger_with_memrefs_t { + rc_trigger_t trigger; + rc_memrefs_t memrefs; +} rc_trigger_with_memrefs_t; + +typedef struct rc_lboard_with_memrefs_t { + rc_lboard_t lboard; + rc_memrefs_t memrefs; +} rc_lboard_with_memrefs_t; + +typedef struct rc_richpresence_with_memrefs_t { + rc_richpresence_t richpresence; + rc_memrefs_t memrefs; +} rc_richpresence_with_memrefs_t; + +typedef struct rc_value_with_memrefs_t { + rc_value_t value; + rc_memrefs_t memrefs; +} rc_value_with_memrefs_t; + /* enum helpers for natvis expansion. Have to use a struct to define the mapping, * and a single field to allow the conditional logic to switch on the value */ typedef struct __rc_bool_enum_t { uint8_t value; } __rc_bool_enum_t; @@ -35,7 +76,6 @@ typedef struct __rc_condset_list_t { rc_condset_t* first_condset; } __rc_condset typedef struct __rc_operator_enum_t { uint8_t value; } __rc_operator_enum_t; typedef struct __rc_operator_enum_str_t { uint8_t value; } __rc_operator_enum_str_t; typedef struct __rc_operand_memref_t { rc_operand_t operand; } __rc_operand_memref_t; /* requires &rc_operand_t to be the same as &rc_operand_t.value.memref */ -typedef struct __rc_memref_list_t { rc_memref_t* first_memref; } __rc_memref_list_t; typedef struct __rc_value_list_t { rc_value_t* first_value; } __rc_value_list_t; typedef struct __rc_trigger_state_enum_t { uint8_t value; } __rc_trigger_state_enum_t; typedef struct __rc_lboard_state_enum_t { uint8_t value; } __rc_lboard_state_enum_t; @@ -50,16 +90,23 @@ RC_ALLOW_ALIGN(rc_condition_t) RC_ALLOW_ALIGN(rc_condset_t) RC_ALLOW_ALIGN(rc_modified_memref_t) RC_ALLOW_ALIGN(rc_lboard_t) +RC_ALLOW_ALIGN(rc_lboard_with_memrefs_t) RC_ALLOW_ALIGN(rc_memref_t) +RC_ALLOW_ALIGN(rc_memref_list_t) +RC_ALLOW_ALIGN(rc_memrefs_t) +RC_ALLOW_ALIGN(rc_modified_memref_list_t) RC_ALLOW_ALIGN(rc_operand_t) RC_ALLOW_ALIGN(rc_richpresence_t) RC_ALLOW_ALIGN(rc_richpresence_display_t) RC_ALLOW_ALIGN(rc_richpresence_display_part_t) RC_ALLOW_ALIGN(rc_richpresence_lookup_t) RC_ALLOW_ALIGN(rc_richpresence_lookup_item_t) +RC_ALLOW_ALIGN(rc_richpresence_with_memrefs_t) RC_ALLOW_ALIGN(rc_scratch_string_t) RC_ALLOW_ALIGN(rc_trigger_t) +RC_ALLOW_ALIGN(rc_trigger_with_memrefs_t) RC_ALLOW_ALIGN(rc_value_t) +RC_ALLOW_ALIGN(rc_value_with_memrefs_t) RC_ALLOW_ALIGN(char) #define RC_ALIGNOF(T) (sizeof(struct __align_ ## T) - sizeof(T)) @@ -67,6 +114,8 @@ RC_ALLOW_ALIGN(char) #define RC_ALLOC(t, p) ((t*)rc_alloc((p)->buffer, &(p)->offset, sizeof(t), RC_ALIGNOF(t), &(p)->scratch, RC_OFFSETOF((p)->scratch.objs, __ ## t))) #define RC_ALLOC_SCRATCH(t, p) ((t*)rc_alloc_scratch((p)->buffer, &(p)->offset, sizeof(t), RC_ALIGNOF(t), &(p)->scratch, RC_OFFSETOF((p)->scratch.objs, __ ## t))) +#define RC_ALLOC_ARRAY(t, n, p) ((t*)rc_alloc((p)->buffer, &(p)->offset, (n) * sizeof(t), RC_ALIGNOF(t), &(p)->scratch, RC_OFFSETOF((p)->scratch.objs, __ ## t))) +#define RC_ALLOC_ARRAY_SCRATCH(t, n, p) ((t*)rc_alloc_scratch((p)->buffer, &(p)->offset, (n) * sizeof(t), RC_ALIGNOF(t), &(p)->scratch, RC_OFFSETOF((p)->scratch.objs, __ ## t))) #define RC_ALLOC_WITH_TRAILING(container_type, trailing_type, trailing_field, trailing_count, parse) ((container_type*)rc_alloc(\ (parse)->buffer, &(parse)->offset, \ @@ -86,16 +135,23 @@ typedef struct { rc_condset_t* __rc_condset_t; rc_modified_memref_t* __rc_modified_memref_t; rc_lboard_t* __rc_lboard_t; + rc_lboard_with_memrefs_t* __rc_lboard_with_memrefs_t; rc_memref_t* __rc_memref_t; + rc_memref_list_t* __rc_memref_list_t; + rc_memrefs_t* __rc_memrefs_t; + rc_modified_memref_list_t* __rc_modified_memref_list_t; rc_operand_t* __rc_operand_t; rc_richpresence_t* __rc_richpresence_t; rc_richpresence_display_t* __rc_richpresence_display_t; rc_richpresence_display_part_t* __rc_richpresence_display_part_t; rc_richpresence_lookup_t* __rc_richpresence_lookup_t; rc_richpresence_lookup_item_t* __rc_richpresence_lookup_item_t; + rc_richpresence_with_memrefs_t* __rc_richpresence_with_memrefs_t; rc_scratch_string_t __rc_scratch_string_t; rc_trigger_t* __rc_trigger_t; + rc_trigger_with_memrefs_t* __rc_trigger_with_memrefs_t; rc_value_t* __rc_value_t; + rc_value_with_memrefs_t* __rc_value_with_memrefs_t; /* these fields aren't actually used by the code, but they force the * virtual enum wrapper types to exist so natvis can use them */ @@ -112,7 +168,6 @@ typedef struct { __rc_operator_enum_t oper; __rc_operator_enum_str_t oper_str; __rc_operand_memref_t operand_memref; - __rc_memref_list_t memref_list; __rc_value_list_t value_list; __rc_trigger_state_enum_t trigger_state; __rc_lboard_state_enum_t lboard_state; @@ -145,7 +200,7 @@ rc_typed_value_t; enum { RC_MEMREF_TYPE_MEMREF, /* rc_memref_t */ - RC_MEMREF_TYPE_MODIFIED_MEMREF, /* rc_indirect_memref_t */ + RC_MEMREF_TYPE_MODIFIED_MEMREF, /* rc_modified_memref_t */ RC_MEMREF_TYPE_VALUE /* rc_value_t */ }; @@ -156,7 +211,9 @@ typedef struct { /* memory accessors */ rc_peek_t peek; void* peek_userdata; +#ifndef RC_DISABLE_LUA lua_State* L; +#endif /* processing state */ rc_typed_value_t measured_value; /* captured Measured value */ @@ -184,13 +241,16 @@ rc_eval_state_t; typedef struct { int32_t offset; +#ifndef RC_DISABLE_LUA lua_State* L; int funcs_ndx; +#endif void* buffer; rc_scratch_t scratch; - rc_memref_t** first_memref; + rc_memrefs_t* memrefs; + rc_memrefs_t* existing_memrefs; rc_value_t** variables; uint32_t measured_target; @@ -207,10 +267,20 @@ typedef struct { } rc_parse_state_t; +typedef struct rc_preparse_state_t { + rc_parse_state_t parse; + rc_memrefs_t memrefs; +} rc_preparse_state_t; + void rc_init_parse_state(rc_parse_state_t* parse, void* buffer, lua_State* L, int funcs_ndx); -void rc_init_parse_state_memrefs(rc_parse_state_t* parse, rc_memref_t** memrefs); -void rc_init_parse_state_variables(rc_parse_state_t* parse, rc_value_t** variables); +void rc_init_parse_state_memrefs(rc_parse_state_t* parse, rc_memrefs_t* memrefs); +void rc_reset_parse_state(rc_parse_state_t* parse, void* buffer, lua_State* L, int funcs_ndx); void rc_destroy_parse_state(rc_parse_state_t* parse); +void rc_init_preparse_state(rc_preparse_state_t* preparse, lua_State* L, int funcs_ndx); +void rc_preparse_alloc_memrefs(rc_memrefs_t* memrefs, rc_preparse_state_t* preparse); +void rc_preparse_reserve_memrefs(rc_preparse_state_t* preparse, rc_memrefs_t* memrefs); +void rc_preparse_copy_memrefs(rc_parse_state_t* parse, rc_memrefs_t* memrefs); +void rc_destroy_preparse_state(rc_preparse_state_t *preparse); void rc_copy_memrefs_into_parse_state(rc_parse_state_t* parse, rc_memref_t* memrefs); void rc_sync_operand(rc_operand_t* operand, rc_parse_state_t* parse, const rc_memref_t* memrefs); @@ -222,7 +292,7 @@ rc_memref_t* rc_alloc_memref(rc_parse_state_t* parse, uint32_t address, uint8_t rc_modified_memref_t* rc_alloc_modified_memref(rc_parse_state_t* parse, uint8_t size, const rc_operand_t* parent, uint8_t modifier_type, const rc_operand_t* modifier); int rc_parse_memref(const char** memaddr, uint8_t* size, uint32_t* address); -void rc_update_memref_values(rc_memref_t* memref, rc_peek_t peek, void* ud); +void rc_update_memref_values(rc_memrefs_t* memrefs, rc_peek_t peek, void* ud); void rc_update_memref_value(rc_memref_value_t* memref, uint32_t value); void rc_get_memref_value(rc_typed_value_t* value, rc_memref_t* memref, int operand_type); uint32_t rc_get_modified_memref_value(const rc_modified_memref_t* memref, rc_peek_t peek, void* ud); @@ -231,8 +301,14 @@ uint32_t rc_memref_mask(uint8_t size); void rc_transform_memref_value(rc_typed_value_t* value, uint8_t size); uint32_t rc_peek_value(uint32_t address, uint8_t size, rc_peek_t peek, void* ud); +void rc_memrefs_init(rc_memrefs_t* memrefs); +void rc_memrefs_destroy(rc_memrefs_t* memrefs); +uint32_t rc_memrefs_count_memrefs(const rc_memrefs_t* memrefs); +uint32_t rc_memrefs_count_modified_memrefs(const rc_memrefs_t* memrefs); + void rc_parse_trigger_internal(rc_trigger_t* self, const char** memaddr, rc_parse_state_t* parse); int rc_trigger_state_active(int state); +rc_memrefs_t* rc_trigger_get_memrefs(rc_trigger_t* self); typedef struct rc_condset_with_trailing_conditions_t { rc_condset_t condset; @@ -287,7 +363,9 @@ int rc_evaluate_value_typed(rc_value_t* self, rc_typed_value_t* value, rc_peek_t void rc_reset_value(rc_value_t* self); int rc_value_from_hits(rc_value_t* self); rc_value_t* rc_alloc_variable(const char* memaddr, size_t memaddr_len, rc_parse_state_t* parse); -void rc_update_variables(rc_value_t* variable, rc_peek_t peek, void* ud, lua_State* L); +uint32_t rc_count_values(const rc_value_t* values); +void rc_update_values(rc_value_t* values, rc_peek_t peek, void* ud, lua_State* L); +void rc_reset_values(rc_value_t* values); void rc_typed_value_convert(rc_typed_value_t* value, char new_type); void rc_typed_value_add(rc_typed_value_t* value, const rc_typed_value_t* amount); @@ -305,6 +383,11 @@ void rc_parse_lboard_internal(rc_lboard_t* self, const char* memaddr, rc_parse_s int rc_lboard_state_active(int state); void rc_parse_richpresence_internal(rc_richpresence_t* self, const char* script, rc_parse_state_t* parse); +rc_memrefs_t* rc_richpresence_get_memrefs(rc_richpresence_t* self); +void rc_reset_richpresence_triggers(rc_richpresence_t* self); + +int rc_validate_memrefs(const rc_memrefs_t* memrefs, char result[], const size_t result_size, uint32_t max_address); +int rc_validate_memrefs_for_console(const rc_memrefs_t* memrefs, char result[], const size_t result_size, uint32_t console_id); RC_END_C_DECLS diff --git a/src/rcheevos/rc_runtime_types.natvis b/src/rcheevos/rc_runtime_types.natvis index db32c9a3..2acf75be 100644 --- a/src/rcheevos/rc_runtime_types.natvis +++ b/src/rcheevos/rc_runtime_types.natvis @@ -105,7 +105,18 @@ (rc_modified_memref_t*)&value value address - next + + + + {{count = {count}}} + + next + count + capacity + + count + items + @@ -116,7 +127,6 @@ (rc_modified_memref_t*)&operand.value operand.value.memref->value operand.value.memref->address - operand.value.memref->next @@ -279,6 +289,18 @@ modifier + + {{count = {count}}} + + next + count + capacity + + count + items + + + {RC_TRIGGER_STATE_INACTIVE} {RC_TRIGGER_STATE_WAITING} @@ -294,7 +316,6 @@ *((__rc_trigger_state_enum_t*)&state) *((__rc_bool_enum_t*)&has_hits) - *((__rc_bool_enum_t*)&has_required_hits) *((__rc_bool_enum_t*)&measured_as_percent) requirement *((__rc_condset_list_t*)&alternative) @@ -306,8 +327,17 @@ value conditions name - *((__rc_memref_list_t*)&memrefs) - next + + + + {{count = {count}}} + + count + capacity + + count + items + @@ -329,17 +359,6 @@ value - - {{NULL}} - {(void**)&first_memref,na} - - - first_memref - next - this - - - {RC_FORMAT_FRAMES} {RC_FORMAT_SECONDS} @@ -458,8 +477,10 @@ {{offset={offset} addsource_parent={addsource_parent} indirect_parent={indirect_parent}}} offset - ((__rc_memref_list_t*)first_memref) - ((__rc_value_list_t*)&variables) + memrefs + existing_memrefs + variables + ((__rc_value_list_t*)&variables) addsource_parent *((__rc_operator_enum_t*)&addsource_oper) indirect_parent @@ -512,8 +533,7 @@ *((__rc_runtime_trigger_list_t*)this) *((__rc_runtime_lboard_list_t*)this) richpresence - ((__rc_memref_list_t*)&memrefs) - ((__rc_value_list_t*)&variables) + memrefs diff --git a/src/rcheevos/rc_validate.c b/src/rcheevos/rc_validate.c index c09603f4..cb8cf5c1 100644 --- a/src/rcheevos/rc_validate.c +++ b/src/rcheevos/rc_validate.c @@ -43,14 +43,19 @@ static int rc_validate_memref(const rc_memref_t* memref, char result[], const si return 1; } -int rc_validate_memrefs(const rc_memref_t* memref, char result[], const size_t result_size, uint32_t max_address) +int rc_validate_memrefs(const rc_memrefs_t* memrefs, char result[], const size_t result_size, uint32_t max_address) { - while (memref) { - if (!rc_validate_memref(memref, result, result_size, 0, max_address)) - return 0; + const rc_memref_list_t* memref_list = &memrefs->memrefs; + do { + const rc_memref_t* memref = memref_list->items; + const rc_memref_t* memref_stop = memref + memref_list->count; + for (; memref < memref_stop; ++memref) { + if (!rc_validate_memref(memref, result, result_size, 0, max_address)) + return 0; + } - memref = memref->next; - } + memref_list = memref_list->next; + } while (memref_list); return 1; } @@ -65,15 +70,22 @@ static uint32_t rc_console_max_address(uint32_t console_id) return 0xFFFFFFFF; } -int rc_validate_memrefs_for_console(const rc_memref_t* memref, char result[], const size_t result_size, uint32_t console_id) +int rc_validate_memrefs_for_console(const rc_memrefs_t* memrefs, char result[], const size_t result_size, uint32_t console_id) { const uint32_t max_address = rc_console_max_address(console_id); - while (memref) { - if (!rc_validate_memref(memref, result, result_size, console_id, max_address)) - return 0; + const rc_memref_list_t* memref_list = &memrefs->memrefs; + do + { + const rc_memref_t* memref = memref_list->items; + const rc_memref_t* memref_stop = memref + memref_list->count; + for (; memref < memref_stop; ++memref) + { + if (!rc_validate_memref(memref, result, result_size, console_id, max_address)) + return 0; + } - memref = memref->next; - } + memref_list = memref_list->next; + } while (memref_list); return 1; } diff --git a/src/rcheevos/rc_validate.h b/src/rcheevos/rc_validate.h index 09c90ab7..cfda9407 100644 --- a/src/rcheevos/rc_validate.h +++ b/src/rcheevos/rc_validate.h @@ -7,13 +7,9 @@ RC_BEGIN_C_DECLS -int rc_validate_memrefs(const rc_memref_t* memref, char result[], const size_t result_size, uint32_t max_address); - int rc_validate_condset(const rc_condset_t* condset, char result[], const size_t result_size, uint32_t max_address); int rc_validate_trigger(const rc_trigger_t* trigger, char result[], const size_t result_size, uint32_t max_address); -int rc_validate_memrefs_for_console(const rc_memref_t* memref, char result[], const size_t result_size, uint32_t console_id); - int rc_validate_condset_for_console(const rc_condset_t* condset, char result[], const size_t result_size, uint32_t console_id); int rc_validate_trigger_for_console(const rc_trigger_t* trigger, char result[], const size_t result_size, uint32_t console_id); diff --git a/src/rcheevos/richpresence.c b/src/rcheevos/richpresence.c index f145b482..a9d9b2f0 100644 --- a/src/rcheevos/richpresence.c +++ b/src/rcheevos/richpresence.c @@ -14,22 +14,37 @@ enum { }; static void rc_alloc_helper_variable_memref_value(rc_richpresence_display_part_t* part, const char* memaddr, int memaddr_len, rc_parse_state_t* parse) { + rc_preparse_state_t preparse; + const char* test_memaddr = memaddr; rc_condset_t* condset; rc_value_t* value; - void* buffer; - int value_size; + int32_t size; part->value.type = RC_OPERAND_NONE; - value_size = rc_value_size(memaddr); - if (value_size < 0) { - parse->offset = value_size; + /* if the expression can be represented as just a memory reference, do so */ + rc_init_preparse_state(&preparse, NULL, 0); + preparse.parse.existing_memrefs = parse->memrefs; + value = RC_ALLOC(rc_value_t, &preparse.parse); + rc_parse_value_internal(value, &test_memaddr, &preparse.parse); + + size = preparse.parse.offset; + if (size < 0) { + parse->offset = size; + rc_destroy_preparse_state(&preparse); return; } - buffer = rc_buffer_alloc(&parse->scratch.buffer, value_size); - value = rc_parse_value(buffer, memaddr, NULL, 0); - rc_copy_memrefs_into_parse_state(parse, value->memrefs); + /* ensure new needed memrefs are allocated in the primary buffer */ + rc_preparse_copy_memrefs(parse, &preparse.memrefs); + + /* parse the value into the scratch buffer so we can look at it */ + rc_reset_parse_state(&preparse.parse, rc_buffer_alloc(&preparse.parse.scratch.buffer, (size_t)size), NULL, 0); + preparse.parse.memrefs = parse->memrefs; + preparse.parse.existing_memrefs = parse->existing_memrefs; + value = RC_ALLOC(rc_value_t, &preparse.parse); + test_memaddr = memaddr; + rc_parse_value_internal(value, &test_memaddr, &preparse.parse); condset = value->conditions; if (condset && !condset->next) { @@ -40,7 +55,6 @@ static void rc_alloc_helper_variable_memref_value(rc_richpresence_display_part_t rc_condition_t* condition = condset->conditions; for (; condition; condition = condition->next) { if (condition->type == RC_CONDITION_MEASURED && condition->required_hits == 0) { - rc_sync_operand(&condition->operand1, parse, value->memrefs); memcpy(&part->value, &condition->operand1, sizeof(condition->operand1)); break; } @@ -48,6 +62,8 @@ static void rc_alloc_helper_variable_memref_value(rc_richpresence_display_part_t } } + rc_destroy_preparse_state(&preparse); + /* could not express value with just a memory reference, create a helper variable */ if (part->value.type == RC_OPERAND_NONE) { value = rc_alloc_variable(memaddr, memaddr_len, parse); @@ -490,6 +506,8 @@ void rc_parse_richpresence_internal(rc_richpresence_t* self, const char* script, int display_line = 0; int chars; + self->values = NULL; + /* special case for empty script to return 1 line read */ if (!*script) { parse->lines_read = 1; @@ -582,9 +600,9 @@ void rc_parse_richpresence_internal(rc_richpresence_t* self, const char* script, return; trigger = &((*nextdisplay)->trigger); rc_parse_trigger_internal(trigger, &line, parse); - trigger->memrefs = 0; if (parse->offset < 0) return; + (*nextdisplay)->has_required_hits = parse->has_required_hits; if (parse->buffer) nextdisplay = &((*nextdisplay)->next); } @@ -615,6 +633,7 @@ void rc_parse_richpresence_internal(rc_richpresence_t* self, const char* script, /* finalize */ *nextdisplay = 0; + self->has_memrefs = 0; if (!hasdisplay && parse->offset > 0) { parse->offset = RC_MISSING_DISPLAY_STRING; @@ -622,22 +641,20 @@ void rc_parse_richpresence_internal(rc_richpresence_t* self, const char* script, } int rc_richpresence_size_lines(const char* script, int* lines_read) { - rc_richpresence_t* self; - rc_parse_state_t parse; - rc_memref_t* first_memref; - rc_value_t* variables; - rc_init_parse_state(&parse, 0, 0, 0); - rc_init_parse_state_memrefs(&parse, &first_memref); - rc_init_parse_state_variables(&parse, &variables); + rc_richpresence_with_memrefs_t* richpresence; + rc_preparse_state_t preparse; + rc_init_preparse_state(&preparse, NULL, 0); - self = RC_ALLOC(rc_richpresence_t, &parse); - rc_parse_richpresence_internal(self, script, &parse); + richpresence = RC_ALLOC(rc_richpresence_with_memrefs_t, &preparse.parse); + preparse.parse.variables = &richpresence->richpresence.values; + rc_parse_richpresence_internal(&richpresence->richpresence, script, &preparse.parse); + rc_preparse_alloc_memrefs(NULL, &preparse); if (lines_read) - *lines_read = parse.lines_read; + *lines_read = preparse.parse.lines_read; - rc_destroy_parse_state(&parse); - return parse.offset; + rc_destroy_preparse_state(&preparse); + return preparse.parse.offset; } int rc_richpresence_size(const char* script) { @@ -645,32 +662,53 @@ int rc_richpresence_size(const char* script) { } rc_richpresence_t* rc_parse_richpresence(void* buffer, const char* script, lua_State* L, int funcs_ndx) { - rc_richpresence_t* self; - rc_parse_state_t parse; + rc_richpresence_with_memrefs_t* richpresence; + rc_preparse_state_t preparse; if (!buffer || !script) return NULL; - rc_init_parse_state(&parse, buffer, L, funcs_ndx); + rc_init_preparse_state(&preparse, L, funcs_ndx); + richpresence = RC_ALLOC(rc_richpresence_with_memrefs_t, &preparse.parse); + preparse.parse.variables = &richpresence->richpresence.values; + rc_parse_richpresence_internal(&richpresence->richpresence, script, &preparse.parse); + + rc_reset_parse_state(&preparse.parse, buffer, L, funcs_ndx); + richpresence = RC_ALLOC(rc_richpresence_with_memrefs_t, &preparse.parse); + preparse.parse.variables = &richpresence->richpresence.values; + rc_preparse_alloc_memrefs(&richpresence->memrefs, &preparse); + + rc_parse_richpresence_internal(&richpresence->richpresence, script, &preparse.parse); + richpresence->richpresence.has_memrefs = 1; + + rc_destroy_preparse_state(&preparse); + return (preparse.parse.offset >= 0) ? &richpresence->richpresence : NULL; +} - self = RC_ALLOC(rc_richpresence_t, &parse); - rc_init_parse_state_memrefs(&parse, &self->memrefs); - rc_init_parse_state_variables(&parse, &self->variables); +static void rc_update_richpresence_memrefs(rc_richpresence_t* self, rc_peek_t peek, void* ud) { + if (self->has_memrefs) { + rc_richpresence_with_memrefs_t* richpresence = (rc_richpresence_with_memrefs_t*)self; + rc_update_memref_values(&richpresence->memrefs, peek, ud); + } +} - rc_parse_richpresence_internal(self, script, &parse); +rc_memrefs_t* rc_richpresence_get_memrefs(rc_richpresence_t* self) { + if (self->has_memrefs) { + rc_richpresence_with_memrefs_t* richpresence = (rc_richpresence_with_memrefs_t*)self; + return &richpresence->memrefs; + } - rc_destroy_parse_state(&parse); - return (parse.offset >= 0) ? self : NULL; + return NULL; } void rc_update_richpresence(rc_richpresence_t* richpresence, rc_peek_t peek, void* peek_ud, lua_State* L) { rc_richpresence_display_t* display; - rc_update_memref_values(richpresence->memrefs, peek, peek_ud); - rc_update_variables(richpresence->variables, peek, peek_ud, L); + rc_update_richpresence_memrefs(richpresence, peek, peek_ud); + rc_update_values(richpresence->values, peek, peek_ud, L); for (display = richpresence->first_display; display; display = display->next) { - if (display->trigger.has_required_hits) + if (display->has_required_hits) rc_test_trigger(&display->trigger, peek, peek_ud, L); } } @@ -828,7 +866,7 @@ int rc_get_richpresence_display_string(rc_richpresence_t* richpresence, char* bu return rc_evaluate_richpresence_display(display->display, buffer, buffersize); /* triggers with required hits will be updated in rc_update_richpresence */ - if (!display->trigger.has_required_hits) + if (!display->has_required_hits) rc_test_trigger(&display->trigger, peek, peek_ud, L); /* if we've found a valid condition, process it */ @@ -845,13 +883,14 @@ int rc_evaluate_richpresence(rc_richpresence_t* richpresence, char* buffer, size return rc_get_richpresence_display_string(richpresence, buffer, buffersize, peek, peek_ud, L); } -void rc_reset_richpresence(rc_richpresence_t* self) { +void rc_reset_richpresence_triggers(rc_richpresence_t* self) { rc_richpresence_display_t* display; - rc_value_t* variable; for (display = self->first_display; display; display = display->next) rc_reset_trigger(&display->trigger); +} - for (variable = self->variables; variable; variable = variable->next) - rc_reset_value(variable); +void rc_reset_richpresence(rc_richpresence_t* self) { + rc_reset_richpresence_triggers(self); + rc_reset_values(self->values); } diff --git a/src/rcheevos/runtime.c b/src/rcheevos/runtime.c index 5c1d27d9..abc4d758 100644 --- a/src/rcheevos/runtime.c +++ b/src/rcheevos/runtime.c @@ -48,16 +48,19 @@ rc_runtime_t* rc_runtime_alloc(void) { void rc_runtime_init(rc_runtime_t* self) { memset(self, 0, sizeof(rc_runtime_t)); - self->next_memref = &self->memrefs; - self->next_variable = &self->variables; + + self->memrefs = (rc_memrefs_t*)malloc(sizeof(*self->memrefs)); + rc_memrefs_init(self->memrefs); } void rc_runtime_destroy(rc_runtime_t* self) { uint32_t i; if (self->triggers) { - for (i = 0; i < self->trigger_count; ++i) - free(self->triggers[i].buffer); + for (i = 0; i < self->trigger_count; ++i) { + if (self->triggers[i].buffer) + free(self->triggers[i].buffer); + } free(self->triggers); self->triggers = NULL; @@ -66,8 +69,10 @@ void rc_runtime_destroy(rc_runtime_t* self) { } if (self->lboards) { - for (i = 0; i < self->lboard_count; ++i) - free(self->lboards[i].buffer); + for (i = 0; i < self->lboard_count; ++i) { + if (self->lboards[i].buffer) + free(self->lboards[i].buffer); + } free(self->lboards); self->lboards = NULL; @@ -75,20 +80,17 @@ void rc_runtime_destroy(rc_runtime_t* self) { self->lboard_count = self->lboard_capacity = 0; } - while (self->richpresence) { - rc_runtime_richpresence_t* previous = self->richpresence->previous; - - free(self->richpresence->buffer); + if (self->richpresence) { + if (self->richpresence->buffer) + free(self->richpresence->buffer); free(self->richpresence); - self->richpresence = previous; } - self->next_memref = 0; - self->memrefs = 0; + if (self->memrefs) + rc_memrefs_destroy(self->memrefs); - if (self->owns_self) { + if (self->owns_self) free(self); - } } void rc_runtime_checksum(const char* memaddr, uint8_t* md5) { @@ -98,45 +100,12 @@ void rc_runtime_checksum(const char* memaddr, uint8_t* md5) { md5_finish(&state, md5); } -static char rc_runtime_allocated_memrefs(rc_runtime_t* self) { - char owns_memref = 0; - - /* if at least one memref was allocated within the object, we can't free the buffer when the object is deactivated */ - if (*self->next_memref != NULL) { - owns_memref = 1; - /* advance through the new memrefs so we're ready for the next allocation */ - do { - self->next_memref = &(*self->next_memref)->next; - } while (*self->next_memref != NULL); - } - - /* if at least one variable was allocated within the object, we can't free the buffer when the object is deactivated */ - if (*self->next_variable != NULL) { - owns_memref = 1; - /* advance through the new variables so we're ready for the next allocation */ - do { - self->next_variable = &(*self->next_variable)->next; - } while (*self->next_variable != NULL); - } - - return owns_memref; -} - static void rc_runtime_deactivate_trigger_by_index(rc_runtime_t* self, uint32_t index) { - if (self->triggers[index].owns_memrefs) { - /* if the trigger has one or more memrefs in its buffer, we can't free the buffer. - * just null out the trigger so the runtime processor will skip it - */ - rc_reset_trigger(self->triggers[index].trigger); - self->triggers[index].trigger = NULL; - } - else { - /* trigger doesn't own any memrefs, go ahead and free it, then replace it with the last trigger */ - free(self->triggers[index].buffer); + /* free the trigger, then replace it with the last trigger */ + free(self->triggers[index].buffer); - if (--self->trigger_count > index) - memcpy(&self->triggers[index], &self->triggers[self->trigger_count], sizeof(rc_runtime_trigger_t)); - } + if (--self->trigger_count > index) + memcpy(&self->triggers[index], &self->triggers[self->trigger_count], sizeof(rc_runtime_trigger_t)); } void rc_runtime_deactivate_achievement(rc_runtime_t* self, uint32_t id) { @@ -152,7 +121,8 @@ int rc_runtime_activate_achievement(rc_runtime_t* self, uint32_t id, const char* void* trigger_buffer; rc_trigger_t* trigger; rc_runtime_trigger_t* runtime_trigger; - rc_parse_state_t parse; + rc_preparse_state_t preparse; + const char* preparse_memaddr = memaddr; uint8_t md5[16]; int32_t size; uint32_t i; @@ -195,7 +165,12 @@ int rc_runtime_activate_achievement(rc_runtime_t* self, uint32_t id, const char* } /* item has not been previously registered, determine how much space we need for it, and allocate it */ - size = rc_trigger_size(memaddr); + rc_init_preparse_state(&preparse, NULL, 0); + preparse.parse.existing_memrefs = self->memrefs; + trigger = RC_ALLOC(rc_trigger_t, &preparse.parse); + rc_parse_trigger_internal(trigger, &preparse_memaddr, &preparse.parse); + + size = preparse.parse.offset; if (size < 0) return size; @@ -204,16 +179,15 @@ int rc_runtime_activate_achievement(rc_runtime_t* self, uint32_t id, const char* return RC_OUT_OF_MEMORY; /* populate the item, using the communal memrefs pool */ - rc_init_parse_state(&parse, trigger_buffer, L, funcs_idx); - parse.first_memref = &self->memrefs; - trigger = RC_ALLOC(rc_trigger_t, &parse); - rc_parse_trigger_internal(trigger, &memaddr, &parse); - rc_destroy_parse_state(&parse); + rc_reset_parse_state(&preparse.parse, trigger_buffer, L, funcs_idx); + rc_preparse_reserve_memrefs(&preparse, self->memrefs); + trigger = RC_ALLOC(rc_trigger_t, &preparse.parse); + rc_parse_trigger_internal(trigger, &memaddr, &preparse.parse); + rc_destroy_preparse_state(&preparse); - if (parse.offset < 0) { + if (preparse.parse.offset < 0) { free(trigger_buffer); - *self->next_memref = NULL; /* disassociate any memrefs allocated by the failed parse */ - return parse.offset; + return preparse.parse.offset; } /* grow the trigger buffer if necessary */ @@ -226,7 +200,6 @@ int rc_runtime_activate_achievement(rc_runtime_t* self, uint32_t id, const char* if (!self->triggers) { free(trigger_buffer); - *self->next_memref = NULL; /* disassociate any memrefs allocated by the failed parse */ return RC_OUT_OF_MEMORY; } } @@ -239,11 +212,9 @@ int rc_runtime_activate_achievement(rc_runtime_t* self, uint32_t id, const char* runtime_trigger->invalid_memref = NULL; memcpy(runtime_trigger->md5, md5, 16); runtime_trigger->serialized_size = 0; - runtime_trigger->owns_memrefs = rc_runtime_allocated_memrefs(self); ++self->trigger_count; /* reset it, and return it */ - trigger->memrefs = NULL; rc_reset_trigger(trigger); return RC_OK; } @@ -311,20 +282,11 @@ int rc_runtime_format_achievement_measured(const rc_runtime_t* runtime, uint32_t } static void rc_runtime_deactivate_lboard_by_index(rc_runtime_t* self, uint32_t index) { - if (self->lboards[index].owns_memrefs) { - /* if the lboard has one or more memrefs in its buffer, we can't free the buffer. - * just null out the lboard so the runtime processor will skip it - */ - rc_reset_lboard(self->lboards[index].lboard); - self->lboards[index].lboard = NULL; - } - else { - /* lboard doesn't own any memrefs, go ahead and free it, then replace it with the last lboard */ - free(self->lboards[index].buffer); + /* free the lboard, then replace it with the last lboard */ + free(self->lboards[index].buffer); - if (--self->lboard_count > index) - memcpy(&self->lboards[index], &self->lboards[self->lboard_count], sizeof(rc_runtime_lboard_t)); - } + if (--self->lboard_count > index) + memcpy(&self->lboards[index], &self->lboards[self->lboard_count], sizeof(rc_runtime_lboard_t)); } void rc_runtime_deactivate_lboard(rc_runtime_t* self, uint32_t id) { @@ -340,7 +302,7 @@ int rc_runtime_activate_lboard(rc_runtime_t* self, uint32_t id, const char* mema void* lboard_buffer; uint8_t md5[16]; rc_lboard_t* lboard; - rc_parse_state_t parse; + rc_preparse_state_t preparse; rc_runtime_lboard_t* runtime_lboard; int size; uint32_t i; @@ -383,7 +345,12 @@ int rc_runtime_activate_lboard(rc_runtime_t* self, uint32_t id, const char* mema } /* item has not been previously registered, determine how much space we need for it, and allocate it */ - size = rc_lboard_size(memaddr); + rc_init_preparse_state(&preparse, NULL, 0); + preparse.parse.existing_memrefs = self->memrefs; + lboard = RC_ALLOC(rc_lboard_t, &preparse.parse); + rc_parse_lboard_internal(lboard, memaddr, &preparse.parse); + + size = preparse.parse.offset; if (size < 0) return size; @@ -392,16 +359,15 @@ int rc_runtime_activate_lboard(rc_runtime_t* self, uint32_t id, const char* mema return RC_OUT_OF_MEMORY; /* populate the item, using the communal memrefs pool */ - rc_init_parse_state(&parse, lboard_buffer, L, funcs_idx); - lboard = RC_ALLOC(rc_lboard_t, &parse); - parse.first_memref = &self->memrefs; - rc_parse_lboard_internal(lboard, memaddr, &parse); - rc_destroy_parse_state(&parse); + rc_reset_parse_state(&preparse.parse, lboard_buffer, L, funcs_idx); + rc_preparse_reserve_memrefs(&preparse, self->memrefs); + lboard = RC_ALLOC(rc_lboard_t, &preparse.parse); + rc_parse_lboard_internal(lboard, memaddr, &preparse.parse); + rc_destroy_preparse_state(&preparse); - if (parse.offset < 0) { + if (preparse.parse.offset < 0) { free(lboard_buffer); - *self->next_memref = NULL; /* disassociate any memrefs allocated by the failed parse */ - return parse.offset; + return preparse.parse.offset; } /* grow the lboard buffer if necessary */ @@ -414,7 +380,6 @@ int rc_runtime_activate_lboard(rc_runtime_t* self, uint32_t id, const char* mema if (!self->lboards) { free(lboard_buffer); - *self->next_memref = NULL; /* disassociate any memrefs allocated by the failed parse */ return RC_OUT_OF_MEMORY; } } @@ -428,10 +393,8 @@ int rc_runtime_activate_lboard(rc_runtime_t* self, uint32_t id, const char* mema runtime_lboard->invalid_memref = NULL; memcpy(runtime_lboard->md5, md5, 16); runtime_lboard->serialized_size = 0; - runtime_lboard->owns_memrefs = rc_runtime_allocated_memrefs(self); /* reset it, and return it */ - lboard->memrefs = NULL; rc_reset_lboard(lboard); return RC_OK; } @@ -455,9 +418,7 @@ int rc_runtime_format_lboard_value(char* buffer, int size, int32_t value, int fo int rc_runtime_activate_richpresence(rc_runtime_t* self, const char* script, lua_State* L, int funcs_idx) { rc_richpresence_t* richpresence; - rc_runtime_richpresence_t* previous; - rc_runtime_richpresence_t** previous_ptr; - rc_parse_state_t parse; + rc_preparse_state_t preparse; uint8_t md5[16]; int size; @@ -467,47 +428,29 @@ int rc_runtime_activate_richpresence(rc_runtime_t* self, const char* script, lua rc_runtime_checksum(script, md5); /* look for existing match */ - previous_ptr = NULL; - previous = self->richpresence; - while (previous) { - if (previous && self->richpresence->richpresence && memcmp(self->richpresence->md5, md5, 16) == 0) { - /* unchanged. reset all of the conditions */ - rc_reset_richpresence(self->richpresence->richpresence); - - /* move to front of linked list*/ - if (previous_ptr) { - *previous_ptr = previous->previous; - if (!self->richpresence->owns_memrefs) { - free(self->richpresence->buffer); - previous->previous = self->richpresence->previous; - } - else { - previous->previous = self->richpresence; - } - - self->richpresence = previous; - } - - /* return success*/ - return RC_OK; - } + if (self->richpresence && self->richpresence->richpresence && memcmp(self->richpresence->md5, md5, 16) == 0) { + /* unchanged. reset all of the conditions */ + rc_reset_richpresence(self->richpresence->richpresence); - previous_ptr = &previous->previous; - previous = previous->previous; + /* return success*/ + return RC_OK; } /* no existing match found, parse script */ - size = rc_richpresence_size(script); + rc_init_preparse_state(&preparse, NULL, 0); + preparse.parse.existing_memrefs = self->memrefs; + richpresence = RC_ALLOC(rc_richpresence_t, &preparse.parse); + preparse.parse.variables = &richpresence->values; + rc_parse_richpresence_internal(richpresence, script, &preparse.parse); + + size = preparse.parse.offset; if (size < 0) return size; - /* if the previous script doesn't have any memrefs, free it */ - previous = self->richpresence; - if (previous) { - if (!previous->owns_memrefs) { - free(previous->buffer); - previous = previous->previous; - } + /* if there's a previous script, free it */ + if (self->richpresence) { + free(self->richpresence->buffer); + free(self->richpresence); } /* allocate and process the new script */ @@ -515,34 +458,26 @@ int rc_runtime_activate_richpresence(rc_runtime_t* self, const char* script, lua if (!self->richpresence) return RC_OUT_OF_MEMORY; - self->richpresence->previous = previous; - self->richpresence->owns_memrefs = 0; memcpy(self->richpresence->md5, md5, sizeof(md5)); - self->richpresence->buffer = malloc(size); + self->richpresence->buffer = malloc(size); if (!self->richpresence->buffer) return RC_OUT_OF_MEMORY; - rc_init_parse_state(&parse, self->richpresence->buffer, L, funcs_idx); - self->richpresence->richpresence = richpresence = RC_ALLOC(rc_richpresence_t, &parse); - parse.first_memref = &self->memrefs; - parse.variables = &self->variables; - rc_parse_richpresence_internal(richpresence, script, &parse); - rc_destroy_parse_state(&parse); + rc_reset_parse_state(&preparse.parse, self->richpresence->buffer, L, funcs_idx); + rc_preparse_reserve_memrefs(&preparse, self->memrefs); + richpresence = RC_ALLOC(rc_richpresence_t, &preparse.parse); + preparse.parse.variables = &richpresence->values; + rc_parse_richpresence_internal(richpresence, script, &preparse.parse); + rc_destroy_preparse_state(&preparse); - if (parse.offset < 0) { + if (preparse.parse.offset < 0) { free(self->richpresence->buffer); free(self->richpresence); - self->richpresence = previous; - *self->next_memref = NULL; /* disassociate any memrefs allocated by the failed parse */ - return parse.offset; + self->richpresence = NULL; + return preparse.parse.offset; } - self->richpresence->owns_memrefs = rc_runtime_allocated_memrefs(self); - - richpresence->memrefs = NULL; - richpresence->variables = NULL; - if (!richpresence->first_display || !richpresence->first_display->display) { /* non-existant rich presence */ self->richpresence->richpresence = NULL; @@ -550,6 +485,7 @@ int rc_runtime_activate_richpresence(rc_runtime_t* self, const char* script, lua else { /* reset all of the conditions */ rc_reset_richpresence(richpresence); + self->richpresence->richpresence = richpresence; } return RC_OK; @@ -570,7 +506,6 @@ void rc_runtime_do_frame(rc_runtime_t* self, rc_runtime_event_handler_t event_ha runtime_event.value = 0; rc_update_memref_values(self->memrefs, peek, ud); - rc_update_variables(self->variables, peek, ud, L); for (i = self->trigger_count - 1; i >= 0; --i) { rc_trigger_t* trigger = self->triggers[i].trigger; @@ -740,7 +675,6 @@ void rc_runtime_do_frame(rc_runtime_t* self, rc_runtime_event_handler_t event_ha } void rc_runtime_reset(rc_runtime_t* self) { - rc_value_t* variable; uint32_t i; for (i = 0; i < self->trigger_count; ++i) { @@ -755,9 +689,6 @@ void rc_runtime_reset(rc_runtime_t* self) { if (self->richpresence && self->richpresence->richpresence) rc_reset_richpresence(self->richpresence->richpresence); - - for (variable = self->variables; variable; variable = variable->next) - rc_reset_value(variable); } static int rc_condset_contains_memref(const rc_condset_t* condset, const rc_memref_t* memref) { @@ -841,47 +772,41 @@ static void rc_runtime_invalidate_memref(rc_runtime_t* self, rc_memref_t* memref } void rc_runtime_invalidate_address(rc_runtime_t* self, uint32_t address) { - rc_memref_t** last_memref = &self->memrefs; - rc_memref_t* memref = self->memrefs; - - while (memref) { - if (memref->address == address && memref->value.memref_type == RC_MEMREF_TYPE_MEMREF) { - /* remove the invalid memref from the chain so we don't try to evaluate it in the future. - * it's still there, so anything referencing it will continue to fetch 0. - */ - *last_memref = memref->next; - - rc_runtime_invalidate_memref(self, memref); - break; + rc_memref_list_t* memref_list = &self->memrefs->memrefs; + do { + rc_memref_t* memref = memref_list->items; + const rc_memref_t* memref_stop = memref + memref_list->count; + + for (; memref < memref_stop; ++memref) { + if (memref->address == address) { + memref->value.type = RC_VALUE_TYPE_NONE; + rc_runtime_invalidate_memref(self, memref); + } } - last_memref = &memref->next; - memref = *last_memref; - } + memref_list = memref_list->next; + } while (memref_list); } void rc_runtime_validate_addresses(rc_runtime_t* self, rc_runtime_event_handler_t event_handler, rc_runtime_validate_address_t validate_handler) { - rc_memref_t** last_memref = &self->memrefs; - rc_memref_t* memref = self->memrefs; int num_invalid = 0; + rc_memref_list_t* memref_list = &self->memrefs->memrefs; + do { + rc_memref_t* memref = memref_list->items; + const rc_memref_t* memref_stop = memref + memref_list->count; - while (memref) { - if (memref->value.memref_type == RC_MEMREF_TYPE_MEMREF && !validate_handler(memref->address)) { - /* remove the invalid memref from the chain so we don't try to evaluate it in the future. - * it's still there, so anything referencing it will continue to fetch 0. - */ - *last_memref = memref->next; + for (; memref < memref_stop; ++memref) { + if (!validate_handler(memref->address)) { + memref->value.type = RC_VALUE_TYPE_NONE; + rc_runtime_invalidate_memref(self, memref); - rc_runtime_invalidate_memref(self, memref); - ++num_invalid; - } - else { - last_memref = &memref->next; + ++num_invalid; + } } - memref = *last_memref; - } + memref_list = memref_list->next; + } while (memref_list); if (num_invalid) { rc_runtime_event_t runtime_event; diff --git a/src/rcheevos/runtime_progress.c b/src/rcheevos/runtime_progress.c index 2f9ea96d..c20bae3a 100644 --- a/src/rcheevos/runtime_progress.c +++ b/src/rcheevos/runtime_progress.c @@ -127,13 +127,7 @@ static void rc_runtime_progress_init(rc_runtime_progress_t* progress, const rc_r static int rc_runtime_progress_write_memrefs(rc_runtime_progress_t* progress) { - rc_memref_t* memref; - uint32_t count = 0; - - for (memref = progress->runtime->memrefs; memref; memref = memref->next) { - if (memref->value.memref_type == RC_MEMREF_TYPE_MEMREF) - ++count; - } + uint32_t count = rc_memrefs_count_memrefs(progress->runtime->memrefs); if (count == 0) return RC_OK; @@ -147,18 +141,24 @@ static int rc_runtime_progress_write_memrefs(rc_runtime_progress_t* progress) } else { uint32_t flags = 0; - for (memref = progress->runtime->memrefs; memref; memref = memref->next) { - if (memref->value.memref_type != RC_MEMREF_TYPE_MEMREF) - continue; - - flags = memref->value.size; - if (memref->value.changed) - flags |= RC_MEMREF_FLAG_CHANGED_THIS_FRAME; - - rc_runtime_progress_write_uint(progress, memref->address); - rc_runtime_progress_write_uint(progress, flags); - rc_runtime_progress_write_uint(progress, memref->value.value); - rc_runtime_progress_write_uint(progress, memref->value.prior); + const rc_memref_list_t* memref_list = &progress->runtime->memrefs->memrefs; + const rc_memref_t* memref; + + for (; memref_list; memref_list = memref_list->next) { + const rc_memref_t* memref_end; + + memref = memref_list->items; + memref_end = memref + memref_list->count; + for (; memref < memref_end; ++memref) { + flags = memref->value.size; + if (memref->value.changed) + flags |= RC_MEMREF_FLAG_CHANGED_THIS_FRAME; + + rc_runtime_progress_write_uint(progress, memref->address); + rc_runtime_progress_write_uint(progress, flags); + rc_runtime_progress_write_uint(progress, memref->value.value); + rc_runtime_progress_write_uint(progress, memref->value.prior); + } } } @@ -170,61 +170,63 @@ static int rc_runtime_progress_write_memrefs(rc_runtime_progress_t* progress) static void rc_runtime_progress_update_modified_memrefs(rc_runtime_progress_t* progress) { rc_typed_value_t value, prior_value, modifier, prior_modifier; + rc_modified_memref_list_t* modified_memref_list; rc_modified_memref_t* modified_memref; rc_operand_t prior_parent_operand, prior_modifier_operand; rc_memref_t prior_parent_memref, prior_modifier_memref; - rc_memref_t* memref; - - for (memref = progress->runtime->memrefs; memref; memref = memref->next) { - if (memref->value.memref_type == RC_MEMREF_TYPE_MEMREF) - continue; - memref->value.changed = 0; - modified_memref = (rc_modified_memref_t*)memref; + modified_memref_list = &progress->runtime->memrefs->modified_memrefs; + for (; modified_memref_list; modified_memref_list = modified_memref_list->next) { + const rc_modified_memref_t* modified_memref_end; + modified_memref = modified_memref_list->items; + modified_memref_end = modified_memref + modified_memref_list->count; + for (; modified_memref < modified_memref_end; ++modified_memref) { + modified_memref->memref.value.changed = 0; - /* indirect memref values are stored in conditions */ - if (modified_memref->modifier_type == RC_OPERATOR_INDIRECT_READ) - continue; + /* indirect memref values are stored in conditions */ + if (modified_memref->modifier_type == RC_OPERATOR_INDIRECT_READ) + continue; - /* non-indirect memref values can be reconstructed from the parents */ - memcpy(&prior_parent_operand, &modified_memref->parent, sizeof(prior_parent_operand)); - if (rc_operand_is_memref(&prior_parent_operand)) { - memcpy(&prior_parent_memref, modified_memref->parent.value.memref, sizeof(prior_parent_memref)); - prior_parent_memref.value.value = prior_parent_memref.value.prior; - memref->value.changed |= prior_parent_memref.value.changed; - prior_parent_operand.value.memref = &prior_parent_memref; - } + /* non-indirect memref values can be reconstructed from the parents */ + memcpy(&prior_parent_operand, &modified_memref->parent, sizeof(prior_parent_operand)); + if (rc_operand_is_memref(&prior_parent_operand)) { + memcpy(&prior_parent_memref, modified_memref->parent.value.memref, sizeof(prior_parent_memref)); + prior_parent_memref.value.value = prior_parent_memref.value.prior; + modified_memref->memref.value.changed |= prior_parent_memref.value.changed; + prior_parent_operand.value.memref = &prior_parent_memref; + } - memcpy(&prior_modifier_operand, &modified_memref->modifier, sizeof(prior_modifier_operand)); - if (rc_operand_is_memref(&prior_modifier_operand)) { - memcpy(&prior_modifier_memref, modified_memref->modifier.value.memref, sizeof(prior_modifier_memref)); - prior_modifier_memref.value.value = prior_modifier_memref.value.prior; - memref->value.changed |= prior_modifier_memref.value.changed; - prior_modifier_operand.value.memref = &prior_modifier_memref; - } + memcpy(&prior_modifier_operand, &modified_memref->modifier, sizeof(prior_modifier_operand)); + if (rc_operand_is_memref(&prior_modifier_operand)) { + memcpy(&prior_modifier_memref, modified_memref->modifier.value.memref, sizeof(prior_modifier_memref)); + prior_modifier_memref.value.value = prior_modifier_memref.value.prior; + modified_memref->memref.value.changed |= prior_modifier_memref.value.changed; + prior_modifier_operand.value.memref = &prior_modifier_memref; + } - rc_evaluate_operand(&value, &modified_memref->parent, NULL); - rc_evaluate_operand(&modifier, &modified_memref->modifier, NULL); - rc_evaluate_operand(&prior_value, &prior_parent_operand, NULL); - rc_evaluate_operand(&prior_modifier, &prior_modifier_operand, NULL); + rc_evaluate_operand(&value, &modified_memref->parent, NULL); + rc_evaluate_operand(&modifier, &modified_memref->modifier, NULL); + rc_evaluate_operand(&prior_value, &prior_parent_operand, NULL); + rc_evaluate_operand(&prior_modifier, &prior_modifier_operand, NULL); - if (modified_memref->modifier_type == RC_OPERATOR_SUB_PARENT) { - rc_typed_value_negate(&value); - rc_typed_value_add(&value, &modifier); + if (modified_memref->modifier_type == RC_OPERATOR_SUB_PARENT) { + rc_typed_value_negate(&value); + rc_typed_value_add(&value, &modifier); - rc_typed_value_negate(&prior_value); - rc_typed_value_add(&prior_value, &prior_modifier); - } - else { - rc_typed_value_combine(&value, &modifier, modified_memref->modifier_type); - rc_typed_value_combine(&prior_value, &prior_modifier, modified_memref->modifier_type); - } + rc_typed_value_negate(&prior_value); + rc_typed_value_add(&prior_value, &prior_modifier); + } + else { + rc_typed_value_combine(&value, &modifier, modified_memref->modifier_type); + rc_typed_value_combine(&prior_value, &prior_modifier, modified_memref->modifier_type); + } - rc_typed_value_convert(&value, modified_memref->memref.value.type); - memref->value.value = value.value.u32; + rc_typed_value_convert(&value, modified_memref->memref.value.type); + modified_memref->memref.value.value = value.value.u32; - rc_typed_value_convert(&prior_value, modified_memref->memref.value.type); - memref->value.prior = prior_value.value.u32; + rc_typed_value_convert(&prior_value, modified_memref->memref.value.type); + modified_memref->memref.value.prior = prior_value.value.u32; + } } } @@ -233,11 +235,9 @@ static int rc_runtime_progress_read_memrefs(rc_runtime_progress_t* progress) uint32_t entries; uint32_t address, flags, value, prior; uint8_t size; + rc_memref_list_t* unmatched_memref_list = &progress->runtime->memrefs->memrefs; + rc_memref_t* first_unmatched_memref = unmatched_memref_list->items; rc_memref_t* memref; - rc_memref_t* first_unmatched_memref = progress->runtime->memrefs; - - while (first_unmatched_memref && first_unmatched_memref->value.memref_type != RC_MEMREF_TYPE_MEMREF) - first_unmatched_memref = first_unmatched_memref->next; /* re-read the chunk size to determine how many memrefs are present */ progress->offset -= 4; @@ -252,23 +252,39 @@ static int rc_runtime_progress_read_memrefs(rc_runtime_progress_t* progress) size = flags & 0xFF; memref = first_unmatched_memref; - while (memref) { - if (memref->address == address && memref->value.size == size && memref->value.memref_type == RC_MEMREF_TYPE_MEMREF) { - memref->value.value = value; - memref->value.changed = (flags & RC_MEMREF_FLAG_CHANGED_THIS_FRAME) ? 1 : 0; - memref->value.prior = prior; - - if (memref == first_unmatched_memref) { - first_unmatched_memref = memref->next; - - while (first_unmatched_memref && first_unmatched_memref->value.memref_type != RC_MEMREF_TYPE_MEMREF) - first_unmatched_memref = first_unmatched_memref->next; + if (memref->address == address && memref->value.size == size) { + memref->value.value = value; + memref->value.changed = (flags & RC_MEMREF_FLAG_CHANGED_THIS_FRAME) ? 1 : 0; + memref->value.prior = prior; + + first_unmatched_memref++; + if (first_unmatched_memref >= unmatched_memref_list->items + unmatched_memref_list->count) { + unmatched_memref_list = unmatched_memref_list->next; + if (!unmatched_memref_list) + break; + first_unmatched_memref = unmatched_memref_list->items; + } + } + else { + rc_memref_list_t* memref_list = unmatched_memref_list; + do { + ++memref; + if (memref >= memref_list->items + memref_list->count) { + memref_list = memref_list->next; + if (!memref_list) + break; + + memref = memref_list->items; } - break; - } + if (memref->address == address && memref->value.size == size) { + memref->value.value = value; + memref->value.changed = (flags & RC_MEMREF_FLAG_CHANGED_THIS_FRAME) ? 1 : 0; + memref->value.prior = prior; + break; + } - memref = memref->next; + } while (1); } --entries; @@ -436,12 +452,15 @@ static int rc_runtime_progress_write_variable(rc_runtime_progress_t* progress, c static int rc_runtime_progress_write_variables(rc_runtime_progress_t* progress) { - uint32_t count = 0; - const rc_value_t* variable; + uint32_t count; + const rc_value_t* value; int result; - for (variable = progress->runtime->variables; variable; variable = variable->next) - ++count; + if (!progress->runtime->richpresence || !progress->runtime->richpresence->richpresence) + return RC_OK; + + value = progress->runtime->richpresence->richpresence->values; + count = rc_count_values(value); if (count == 0) return RC_OK; @@ -452,14 +471,14 @@ static int rc_runtime_progress_write_variables(rc_runtime_progress_t* progress) rc_runtime_progress_start_chunk(progress, RC_RUNTIME_CHUNK_VARIABLES); rc_runtime_progress_write_uint(progress, count); - for (variable = progress->runtime->variables; variable; variable = variable->next) { - uint32_t djb2 = rc_djb2(variable->name); + for (; value; value = value->next) { + const uint32_t djb2 = rc_djb2(value->name); if (progress->offset + 16 > progress->buffer_size) return RC_INSUFFICIENT_BUFFER; rc_runtime_progress_write_uint(progress, djb2); - result = rc_runtime_progress_write_variable(progress, variable); + result = rc_runtime_progress_write_variable(progress, value); if (result != RC_OK) return result; } @@ -496,19 +515,20 @@ static int rc_runtime_progress_read_variables(rc_runtime_progress_t* progress) }; struct rc_pending_value_t local_pending_variables[32]; struct rc_pending_value_t* pending_variables; - rc_value_t* variable; + rc_value_t* value; uint32_t count, serialized_count; int result; - uint32_t i; + int32_t i; serialized_count = rc_runtime_progress_read_uint(progress); if (serialized_count == 0) return RC_OK; - count = 0; - for (variable = progress->runtime->variables; variable; variable = variable->next) - ++count; + if (!progress->runtime->richpresence || !progress->runtime->richpresence->richpresence) + return RC_OK; + value = progress->runtime->richpresence->richpresence->values; + count = rc_count_values(value); if (count == 0) return RC_OK; @@ -521,22 +541,22 @@ static int rc_runtime_progress_read_variables(rc_runtime_progress_t* progress) return RC_OUT_OF_MEMORY; } - count = 0; - for (variable = progress->runtime->variables; variable; variable = variable->next) { - pending_variables[count].variable = variable; - pending_variables[count].djb2 = rc_djb2(variable->name); - ++count; + i = (int32_t)count; + for (; value; value = value->next) { + --i; + pending_variables[i].variable = value; + pending_variables[i].djb2 = rc_djb2(value->name); } result = RC_OK; for (; serialized_count > 0 && result == RC_OK; --serialized_count) { uint32_t djb2 = rc_runtime_progress_read_uint(progress); - for (i = 0; i < count; ++i) { + for (i = (int32_t)count - 1; i >= 0; --i) { if (pending_variables[i].djb2 == djb2) { - variable = pending_variables[i].variable; - result = rc_runtime_progress_read_variable(progress, variable); + value = pending_variables[i].variable; + result = rc_runtime_progress_read_variable(progress, value); if (result == RC_OK) { - if (i < count - 1) + if (i < (int32_t)count - 1) memcpy(&pending_variables[i], &pending_variables[count - 1], sizeof(struct rc_pending_value_t)); count--; } @@ -820,7 +840,7 @@ static int rc_runtime_progress_read_rich_presence(rc_runtime_progress_t* progres return RC_OK; if (!rc_runtime_progress_match_md5(progress, progress->runtime->richpresence->md5)) { - rc_reset_richpresence(progress->runtime->richpresence->richpresence); + rc_reset_richpresence_triggers(progress->runtime->richpresence->richpresence); return RC_OK; } @@ -1036,7 +1056,7 @@ int rc_runtime_deserialize_progress_sized(rc_runtime_t* runtime, const uint8_t* } if (!seen_rich_presence && runtime->richpresence && runtime->richpresence->richpresence) - rc_reset_richpresence(runtime->richpresence->richpresence); + rc_reset_richpresence_triggers(runtime->richpresence->richpresence); } return result; diff --git a/src/rcheevos/trigger.c b/src/rcheevos/trigger.c index 83ddd668..1d529e01 100644 --- a/src/rcheevos/trigger.c +++ b/src/rcheevos/trigger.c @@ -16,7 +16,7 @@ void rc_parse_trigger_internal(rc_trigger_t* self, const char** memaddr, rc_pars parse->measured_as_percent = 0; if (*aux == 's' || *aux == 'S') { - self->requirement = 0; + self->requirement = NULL; } else { self->requirement = rc_parse_condset(&aux, parse); @@ -24,7 +24,7 @@ void rc_parse_trigger_internal(rc_trigger_t* self, const char** memaddr, rc_pars if (parse->offset < 0) return; - self->requirement->next = 0; + self->requirement->next = NULL; } while (*aux == 's' || *aux == 'S') { @@ -38,7 +38,7 @@ void rc_parse_trigger_internal(rc_trigger_t* self, const char** memaddr, rc_pars next = &(*next)->next; } - *next = 0; + *next = NULL; *memaddr = aux; self->measured_target = parse->measured_target; @@ -46,39 +46,46 @@ void rc_parse_trigger_internal(rc_trigger_t* self, const char** memaddr, rc_pars self->measured_as_percent = parse->measured_as_percent; self->state = RC_TRIGGER_STATE_WAITING; self->has_hits = 0; - self->has_required_hits = parse->has_required_hits; + self->has_memrefs = 0; } int rc_trigger_size(const char* memaddr) { - rc_trigger_t* self; - rc_parse_state_t parse; - rc_memref_t* memrefs; - rc_init_parse_state(&parse, 0, 0, 0); - rc_init_parse_state_memrefs(&parse, &memrefs); + rc_trigger_with_memrefs_t* trigger; + rc_preparse_state_t preparse; + rc_init_preparse_state(&preparse, NULL, 0); - self = RC_ALLOC(rc_trigger_t, &parse); - rc_parse_trigger_internal(self, &memaddr, &parse); + trigger = RC_ALLOC(rc_trigger_with_memrefs_t, &preparse.parse); + rc_parse_trigger_internal(&trigger->trigger, &memaddr, &preparse.parse); + rc_preparse_alloc_memrefs(NULL, &preparse); - rc_destroy_parse_state(&parse); - return parse.offset; + rc_destroy_preparse_state(&preparse); + return preparse.parse.offset; } rc_trigger_t* rc_parse_trigger(void* buffer, const char* memaddr, lua_State* L, int funcs_ndx) { - rc_trigger_t* self; - rc_parse_state_t parse; + rc_trigger_with_memrefs_t* trigger; + rc_preparse_state_t preparse; + const char* preparse_memaddr = memaddr; if (!buffer || !memaddr) return NULL; - rc_init_parse_state(&parse, buffer, L, funcs_ndx); + /* first pass : determine how many memrefs are needed */ + rc_init_preparse_state(&preparse, L, funcs_ndx); + trigger = RC_ALLOC(rc_trigger_with_memrefs_t, &preparse.parse); + rc_parse_trigger_internal(&trigger->trigger, &preparse_memaddr, &preparse.parse); - self = RC_ALLOC(rc_trigger_t, &parse); - rc_init_parse_state_memrefs(&parse, &self->memrefs); + /* allocate the trigger and memrefs */ + rc_reset_parse_state(&preparse.parse, buffer, L, funcs_ndx); + trigger = RC_ALLOC(rc_trigger_with_memrefs_t, &preparse.parse); + rc_preparse_alloc_memrefs(&trigger->memrefs, &preparse); - rc_parse_trigger_internal(self, &memaddr, &parse); + /* parse the trigger */ + rc_parse_trigger_internal(&trigger->trigger, &memaddr, &preparse.parse); + trigger->trigger.has_memrefs = 1; - rc_destroy_parse_state(&parse); - return (parse.offset >= 0) ? self : NULL; + rc_destroy_preparse_state(&preparse); + return (preparse.parse.offset >= 0) ? &trigger->trigger : NULL; } int rc_trigger_state_active(int state) @@ -123,6 +130,22 @@ static void rc_reset_trigger_hitcounts(rc_trigger_t* self) { } } +static void rc_update_trigger_memrefs(rc_trigger_t* self, rc_peek_t peek, void* ud) { + if (self->has_memrefs) { + rc_trigger_with_memrefs_t* trigger = (rc_trigger_with_memrefs_t*)self; + rc_update_memref_values(&trigger->memrefs, peek, ud); + } +} + +rc_memrefs_t* rc_trigger_get_memrefs(rc_trigger_t* self) { + if (self->has_memrefs) { + rc_trigger_with_memrefs_t* trigger = (rc_trigger_with_memrefs_t*)self; + return &trigger->memrefs; + } + + return NULL; +} + int rc_evaluate_trigger(rc_trigger_t* self, rc_peek_t peek, void* ud, lua_State* L) { rc_eval_state_t eval_state; rc_condset_t* condset; @@ -144,7 +167,7 @@ int rc_evaluate_trigger(rc_trigger_t* self, rc_peek_t peek, void* ud, lua_State* case RC_TRIGGER_STATE_INACTIVE: /* not yet active. update the memrefs so deltas are correct when it becomes active, then return INACTIVE */ - rc_update_memref_values(self->memrefs, peek, ud); + rc_update_trigger_memrefs(self, peek, ud); return RC_TRIGGER_STATE_INACTIVE; default: @@ -152,13 +175,17 @@ int rc_evaluate_trigger(rc_trigger_t* self, rc_peek_t peek, void* ud, lua_State* } /* update the memory references */ - rc_update_memref_values(self->memrefs, peek, ud); + rc_update_trigger_memrefs(self, peek, ud); /* process the trigger */ memset(&eval_state, 0, sizeof(eval_state)); eval_state.peek = peek; eval_state.peek_userdata = ud; +#ifndef RC_DISABLE_LUA eval_state.L = L; +#else + (void)L; +#endif measured_value.type = RC_VALUE_TYPE_NONE; diff --git a/src/rcheevos/value.c b/src/rcheevos/value.c index 36059fff..34fbdefb 100644 --- a/src/rcheevos/value.c +++ b/src/rcheevos/value.c @@ -216,12 +216,12 @@ void rc_parse_value_internal(rc_value_t* self, const char** memaddr, rc_parse_st else rc_parse_legacy_value(self, memaddr, parse); - if (parse->offset >= 0) { + if (parse->offset >= 0 && parse->buffer) { self->name = "(unnamed)"; self->value.value = self->value.prior = 0; self->value.memref_type = RC_MEMREF_TYPE_VALUE; self->value.changed = 0; - self->next = NULL; + self->has_memrefs = 0; for (condition = self->conditions->conditions; condition; condition = condition->next) { if (condition->type == RC_CONDITION_MEASURED) { @@ -242,35 +242,46 @@ void rc_parse_value_internal(rc_value_t* self, const char** memaddr, rc_parse_st } int rc_value_size(const char* memaddr) { - rc_value_t* self; - rc_parse_state_t parse; - rc_memref_t* first_memref; - rc_init_parse_state(&parse, 0, 0, 0); - rc_init_parse_state_memrefs(&parse, &first_memref); + rc_value_with_memrefs_t* value; + rc_preparse_state_t preparse; + rc_init_preparse_state(&preparse, NULL, 0); - self = RC_ALLOC(rc_value_t, &parse); - rc_parse_value_internal(self, &memaddr, &parse); + value = RC_ALLOC(rc_value_with_memrefs_t, &preparse.parse); + rc_parse_value_internal(&value->value, &memaddr, &preparse.parse); + rc_preparse_alloc_memrefs(NULL, &preparse); - rc_destroy_parse_state(&parse); - return parse.offset; + rc_destroy_preparse_state(&preparse); + return preparse.parse.offset; } rc_value_t* rc_parse_value(void* buffer, const char* memaddr, lua_State* L, int funcs_ndx) { - rc_value_t* self; - rc_parse_state_t parse; + rc_value_with_memrefs_t* value; + rc_preparse_state_t preparse; + const char* preparse_memaddr = memaddr; if (!buffer || !memaddr) return NULL; - rc_init_parse_state(&parse, buffer, L, funcs_ndx); + rc_init_preparse_state(&preparse, L, funcs_ndx); + value = RC_ALLOC(rc_value_with_memrefs_t, &preparse.parse); + rc_parse_value_internal(&value->value, &preparse_memaddr, &preparse.parse); - self = RC_ALLOC(rc_value_t, &parse); - rc_init_parse_state_memrefs(&parse, &self->memrefs); + rc_reset_parse_state(&preparse.parse, buffer, L, funcs_ndx); + value = RC_ALLOC(rc_value_with_memrefs_t, &preparse.parse); + rc_preparse_alloc_memrefs(&value->memrefs, &preparse); - rc_parse_value_internal(self, &memaddr, &parse); + rc_parse_value_internal(&value->value, &memaddr, &preparse.parse); + value->value.has_memrefs = 1; - rc_destroy_parse_state(&parse); - return (parse.offset >= 0) ? self : NULL; + rc_destroy_preparse_state(&preparse); + return (preparse.parse.offset >= 0) ? &value->value : NULL; +} + +static void rc_update_value_memrefs(rc_value_t* self, rc_peek_t peek, void* ud) { + if (self->has_memrefs) { + rc_value_with_memrefs_t* value = (rc_value_with_memrefs_t*)self; + rc_update_memref_values(&value->memrefs, peek, ud); + } } int rc_evaluate_value_typed(rc_value_t* self, rc_typed_value_t* value, rc_peek_t peek, void* ud, lua_State* L) { @@ -278,7 +289,7 @@ int rc_evaluate_value_typed(rc_value_t* self, rc_typed_value_t* value, rc_peek_t rc_condset_t* condset; int valid = 0; - rc_update_memref_values(self->memrefs, peek, ud); + rc_update_value_memrefs(self, peek, ud); value->value.i32 = 0; value->type = RC_VALUE_TYPE_SIGNED; @@ -287,7 +298,11 @@ int rc_evaluate_value_typed(rc_value_t* self, rc_typed_value_t* value, rc_peek_t memset(&eval_state, 0, sizeof(eval_state)); eval_state.peek = peek; eval_state.peek_userdata = ud; +#ifndef RC_DISABLE_LUA eval_state.L = L; +#else + (void)L; +#endif rc_test_condset(condset, &eval_state); @@ -364,73 +379,77 @@ int rc_value_from_hits(rc_value_t* self) return 0; } -void rc_init_parse_state_variables(rc_parse_state_t* parse, rc_value_t** variables) { - parse->variables = variables; - *variables = 0; -} - -rc_value_t* rc_alloc_variable(const char* memaddr, size_t memaddr_len, rc_parse_state_t* parse) -{ - rc_value_t** variables = parse->variables; +rc_value_t* rc_alloc_variable(const char* memaddr, size_t memaddr_len, rc_parse_state_t* parse) { + rc_value_t** value_ptr = parse->variables; rc_value_t* value; const char* name; uint32_t measured_target; - while ((value = *variables) != NULL) { + if (!value_ptr) + return NULL; + + while (*value_ptr) { + value = *value_ptr; if (strncmp(value->name, memaddr, memaddr_len) == 0 && value->name[memaddr_len] == 0) return value; - variables = &value->next; + value_ptr = &value->next; } - value = RC_ALLOC_SCRATCH(rc_value_t, parse); - memset(&value->value, 0, sizeof(value->value)); - value->value.size = RC_MEMSIZE_VARIABLE; - value->memrefs = NULL; - /* capture name before calling parse as parse will update memaddr pointer */ name = rc_alloc_str(parse, memaddr, memaddr_len); if (!name) return NULL; + /* no match found, create a new entry */ + value = RC_ALLOC_SCRATCH(rc_value_t, parse); + memset(value, 0, sizeof(value->value)); + value->value.size = RC_MEMSIZE_VARIABLE; + value->next = NULL; + /* the helper variable likely has a Measured condition. capture the current measured_target so we can restore it * after generating the variable so the variable's Measured target doesn't conflict with the rest of the trigger. */ measured_target = parse->measured_target; - - /* disable variable resolution when defining a variable to prevent infinite recursion */ - variables = parse->variables; - parse->variables = NULL; rc_parse_value_internal(value, &memaddr, parse); - parse->variables = variables; - - /* restore the measured target */ parse->measured_target = measured_target; /* store name after calling parse as parse will set name to (unnamed) */ value->name = name; - /* append the new variable to the end of the list (have to re-evaluate in case any others were added) */ - while (*variables != NULL) - variables = &(*variables)->next; - *variables = value; - + *value_ptr = value; return value; } -void rc_update_variables(rc_value_t* variable, rc_peek_t peek, void* ud, lua_State* L) { +uint32_t rc_count_values(const rc_value_t* values) { + uint32_t count = 0; + while (values) { + ++count; + values = values->next; + } + + return count; +} + +void rc_update_values(rc_value_t* values, rc_peek_t peek, void* ud, lua_State* L) { rc_typed_value_t result; - while (variable) { - if (rc_evaluate_value_typed(variable, &result, peek, ud, L)) { + rc_value_t* value = values; + for (; value; value = value->next) { + if (rc_evaluate_value_typed(value, &result, peek, ud, L)) { /* store the raw bytes and type to be restored by rc_typed_value_from_memref_value */ - rc_update_memref_value(&variable->value, result.value.u32); - variable->value.type = result.type; + rc_update_memref_value(&value->value, result.value.u32); + value->value.type = result.type; } - - variable = variable->next; } } +void rc_reset_values(rc_value_t* values) { + rc_value_t* value = values; + + for (; value; value = value->next) + rc_reset_value(value); +} + void rc_typed_value_from_memref_value(rc_typed_value_t* value, const rc_memref_value_t* memref) { /* raw value is always u32, type can mark it as something else */ value->value.u32 = memref->value; diff --git a/test/rcheevos/test_condition.c b/test/rcheevos/test_condition.c index 04619765..070b5928 100644 --- a/test/rcheevos/test_condition.c +++ b/test/rcheevos/test_condition.c @@ -30,7 +30,7 @@ static void _assert_parse_condition( ) { rc_condition_t* self; rc_parse_state_t parse; - rc_memref_t* memrefs; + rc_memrefs_t memrefs; char buffer[512]; rc_init_parse_state(&parse, buffer, 0, 0); @@ -106,7 +106,7 @@ static void test_parse_condition_error(const char* memaddr, int expected_error) } } -static int evaluate_condition(rc_condition_t* cond, memory_t* memory, rc_memref_t* memrefs) { +static int evaluate_condition(rc_condition_t* cond, memory_t* memory, rc_memrefs_t* memrefs) { rc_eval_state_t eval_state; memset(&eval_state, 0, sizeof(eval_state)); @@ -121,7 +121,7 @@ static void test_evaluate_condition(const char* memaddr, uint8_t expected_compar rc_condition_t* self; rc_parse_state_t parse; char buffer[512]; - rc_memref_t* memrefs; + rc_memrefs_t memrefs; int ret; uint8_t ram[] = {0x00, 0x11, 0x34, 0xAB, 0x56}; memory_t memory; @@ -137,11 +137,11 @@ static void test_evaluate_condition(const char* memaddr, uint8_t expected_compar ASSERT_NUM_GREATER(parse.offset, 0); ASSERT_NUM_EQUALS(*memaddr, 0); - rc_update_memref_values(memrefs, peek, &memory); /* capture delta for ram[1] */ + rc_update_memref_values(&memrefs, peek, &memory); /* capture delta for ram[1] */ ram[1] = 0x12; ASSERT_NUM_EQUALS(self->optimized_comparator, expected_comparator); - ret = evaluate_condition(self, &memory, memrefs); + ret = evaluate_condition(self, &memory, &memrefs); if (expected_result) { ASSERT_NUM_EQUALS(ret, 1); @@ -155,7 +155,7 @@ static void test_default_comparator(const char* memaddr) { rc_condition_t* condition; rc_parse_state_t parse; char buffer[512]; - rc_memref_t* memrefs; + rc_memrefs_t memrefs; rc_init_parse_state(&parse, buffer, 0, 0); rc_init_parse_state_memrefs(&parse, &memrefs); @@ -177,7 +177,7 @@ static void test_evaluate_condition_float(const char* memaddr, int expected_resu rc_condition_t* self; rc_parse_state_t parse; char buffer[512]; - rc_memref_t* memrefs; + rc_memrefs_t memrefs; int ret; uint8_t ram[] = {0x00, 0x00, 0x00, 0x40, 0x83, 0x49, 0x0F, 0xDB}; /* FF0=2, FF4=2*pi */ memory_t memory; @@ -193,7 +193,7 @@ static void test_evaluate_condition_float(const char* memaddr, int expected_resu ASSERT_NUM_GREATER(parse.offset, 0); ASSERT_NUM_EQUALS(*memaddr, 0); - ret = evaluate_condition(self, &memory, memrefs); + ret = evaluate_condition(self, &memory, &memrefs); if (expected_result) { ASSERT_NUM_EQUALS(ret, 1); @@ -208,7 +208,7 @@ static void test_condition_compare_delta() { rc_condition_t* cond; rc_parse_state_t parse; char buffer[512]; - rc_memref_t* memrefs; + rc_memrefs_t memrefs; const char* cond_str = "0xH0001>d0xH0001"; rc_init_parse_state(&parse, buffer, 0, 0); @@ -222,18 +222,18 @@ static void test_condition_compare_delta() { memory.size = sizeof(ram); /* initial delta value is 0, 0x12 > 0 */ - ASSERT_NUM_EQUALS(evaluate_condition(cond, &memory, memrefs), 1); + ASSERT_NUM_EQUALS(evaluate_condition(cond, &memory, &memrefs), 1); /* delta value is now 0x12, 0x12 = 0x12 */ - ASSERT_NUM_EQUALS(evaluate_condition(cond, &memory, memrefs), 0); + ASSERT_NUM_EQUALS(evaluate_condition(cond, &memory, &memrefs), 0); /* delta value is now 0x12, 0x11 < 0x12 */ ram[1] = 0x11; - ASSERT_NUM_EQUALS(evaluate_condition(cond, &memory, memrefs), 0); + ASSERT_NUM_EQUALS(evaluate_condition(cond, &memory, &memrefs), 0); /* delta value is now 0x13, 0x12 > 0x11 */ ram[1] = 0x12; - ASSERT_NUM_EQUALS(evaluate_condition(cond, &memory, memrefs), 1); + ASSERT_NUM_EQUALS(evaluate_condition(cond, &memory, &memrefs), 1); } static void test_condition_delta_24bit() { @@ -242,7 +242,7 @@ static void test_condition_delta_24bit() { rc_condition_t* cond; rc_parse_state_t parse; char buffer[512]; - rc_memref_t* memrefs; + rc_memrefs_t memrefs; const char* cond_str = "0xW0001>d0xW0001"; rc_init_parse_state(&parse, buffer, 0, 0); @@ -256,30 +256,30 @@ static void test_condition_delta_24bit() { memory.size = sizeof(ram); /* initial delta value is 0x000000, 0xAB3412 > 0x000000 */ - ASSERT_NUM_EQUALS(evaluate_condition(cond, &memory, memrefs), 1); + ASSERT_NUM_EQUALS(evaluate_condition(cond, &memory, &memrefs), 1); /* delta value is now 0xAB3412, 0xAB3412 == 0xAB3412 */ - ASSERT_NUM_EQUALS(evaluate_condition(cond, &memory, memrefs), 0); + ASSERT_NUM_EQUALS(evaluate_condition(cond, &memory, &memrefs), 0); /* value changes to 0xAB3411, delta value is now 0xAB3412, 0xAB3411 < 0xAB3412 */ ram[1] = 0x11; - ASSERT_NUM_EQUALS(evaluate_condition(cond, &memory, memrefs), 0); + ASSERT_NUM_EQUALS(evaluate_condition(cond, &memory, &memrefs), 0); /* value changes to 0xAB3412, delta value is now 0xAB3411, 0xAB3412 > 0xAB3411 */ ram[1] = 0x12; - ASSERT_NUM_EQUALS(evaluate_condition(cond, &memory, memrefs), 1); + ASSERT_NUM_EQUALS(evaluate_condition(cond, &memory, &memrefs), 1); /* ram[4] should not affect the 24-bit value, 0xAB3412 == 0xAB3412 */ ram[4] = 0xAC; - ASSERT_NUM_EQUALS(evaluate_condition(cond, &memory, memrefs), 0); + ASSERT_NUM_EQUALS(evaluate_condition(cond, &memory, &memrefs), 0); /* value changes to 0xAB3411, delta is still 0xAB3412, 0xAB3411 < 0xAB3412 */ ram[1] = 0x11; - ASSERT_NUM_EQUALS(evaluate_condition(cond, &memory, memrefs), 0); + ASSERT_NUM_EQUALS(evaluate_condition(cond, &memory, &memrefs), 0); /* ram[4] should not affect the 24-bit value, 0xAB3411 == 0xAB3411 */ ram[4] = 0xAD; - ASSERT_NUM_EQUALS(evaluate_condition(cond, &memory, memrefs), 0); + ASSERT_NUM_EQUALS(evaluate_condition(cond, &memory, &memrefs), 0); } static void test_condition_prior_24bit() { @@ -288,7 +288,7 @@ static void test_condition_prior_24bit() { rc_condition_t* cond; rc_parse_state_t parse; char buffer[512]; - rc_memref_t* memrefs; + rc_memrefs_t memrefs; const char* cond_str = "0xW0001>p0xW0001"; rc_init_parse_state(&parse, buffer, 0, 0); @@ -302,38 +302,38 @@ static void test_condition_prior_24bit() { memory.size = sizeof(ram); /* initial prior value is 0x000000, 0xAB3412 > 0x000000 */ - ASSERT_NUM_EQUALS(evaluate_condition(cond, &memory, memrefs), 1); + ASSERT_NUM_EQUALS(evaluate_condition(cond, &memory, &memrefs), 1); /* delta value is now 0xAB3412, but prior is still 0x000000, 0xAB3412 > 0x000000 */ - ASSERT_NUM_EQUALS(evaluate_condition(cond, &memory, memrefs), 1); + ASSERT_NUM_EQUALS(evaluate_condition(cond, &memory, &memrefs), 1); /* value changes to 0xAB3411, delta and prior values are now 0xAB3412, 0xAB3411 < 0xAB3412 */ ram[1] = 0x11; - ASSERT_NUM_EQUALS(evaluate_condition(cond, &memory, memrefs), 0); + ASSERT_NUM_EQUALS(evaluate_condition(cond, &memory, &memrefs), 0); /* value changes to 0xAB3412, delta and prior values are now 0xAB3411, 0xAB3412 > 0xAB3411 */ ram[1] = 0x12; - ASSERT_NUM_EQUALS(evaluate_condition(cond, &memory, memrefs), 1); + ASSERT_NUM_EQUALS(evaluate_condition(cond, &memory, &memrefs), 1); /* ram[4] should not affect the 24-bit value, 0xAB3412 > 0xAB3411 */ ram[4] = 0xAC; - ASSERT_NUM_EQUALS(evaluate_condition(cond, &memory, memrefs), 1); + ASSERT_NUM_EQUALS(evaluate_condition(cond, &memory, &memrefs), 1); /* ram[4] should not affect the 24-bit value, 0xAB3412 > 0xAB3411 */ ram[4] = 0xAD; - ASSERT_NUM_EQUALS(evaluate_condition(cond, &memory, memrefs), 1); + ASSERT_NUM_EQUALS(evaluate_condition(cond, &memory, &memrefs), 1); /* value changes to 0xAB3411, delta and prior values are now 0xAB3412, 0xAB3411 < 0xAB3412 */ ram[1] = 0x11; - ASSERT_NUM_EQUALS(evaluate_condition(cond, &memory, memrefs), 0); + ASSERT_NUM_EQUALS(evaluate_condition(cond, &memory, &memrefs), 0); /* ram[4] should not affect the 24-bit value, 0xAB3411 < 0xAB3412 */ ram[4] = 0xAE; - ASSERT_NUM_EQUALS(evaluate_condition(cond, &memory, memrefs), 0); + ASSERT_NUM_EQUALS(evaluate_condition(cond, &memory, &memrefs), 0); /* ram[4] should not affect the 24-bit value, 0xAB3411 < 0xAB3412 */ ram[4] = 0xAF; - ASSERT_NUM_EQUALS(evaluate_condition(cond, &memory, memrefs), 0); + ASSERT_NUM_EQUALS(evaluate_condition(cond, &memory, &memrefs), 0); } void test_condition(void) { diff --git a/test/rcheevos/test_condset.c b/test/rcheevos/test_condset.c index f9f56455..5bfaf426 100644 --- a/test/rcheevos/test_condset.c +++ b/test/rcheevos/test_condset.c @@ -3,20 +3,13 @@ #include "../test_framework.h" #include "mock_memory.h" -typedef struct rc_condset_memrefs_t -{ - rc_memref_t* memrefs; - rc_value_t* variables; -} rc_condset_memrefs_t; - -static void _assert_parse_condset(rc_condset_t** condset, rc_condset_memrefs_t* memrefs, void* buffer, const char* memaddr) +static void _assert_parse_condset(rc_condset_t** condset, rc_memrefs_t* memrefs, void* buffer, const char* memaddr) { rc_parse_state_t parse; int size; rc_init_parse_state(&parse, buffer, 0, 0); - rc_init_parse_state_memrefs(&parse, &memrefs->memrefs); - rc_init_parse_state_variables(&parse, &memrefs->variables); + rc_init_parse_state_memrefs(&parse, memrefs); *condset = rc_parse_condset(&memaddr, &parse); size = parse.offset; @@ -27,12 +20,11 @@ static void _assert_parse_condset(rc_condset_t** condset, rc_condset_memrefs_t* } #define assert_parse_condset(condset, memrefs_out, buffer, memaddr) ASSERT_HELPER(_assert_parse_condset(condset, memrefs_out, buffer, memaddr), "assert_parse_condset") -static void _assert_evaluate_condset(rc_condset_t* condset, rc_condset_memrefs_t* memrefs, memory_t* memory, int expected_result) { +static void _assert_evaluate_condset(rc_condset_t* condset, rc_memrefs_t* memrefs, memory_t* memory, int expected_result) { int result; rc_eval_state_t eval_state; - rc_update_memref_values(memrefs->memrefs, peek, memory); - rc_update_variables(memrefs->variables, peek, memory, 0); + rc_update_memref_values(memrefs, peek, memory); memset(&eval_state, 0, sizeof(eval_state)); eval_state.peek = peek; @@ -74,7 +66,7 @@ static void test_hitcount_increment_when_true() { uint8_t ram[] = {0x00, 0x12, 0x34, 0xAB, 0x56}; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -91,7 +83,7 @@ static void test_hitcount_does_not_increment_when_false() { uint8_t ram[] = {0x00, 0x12, 0x34, 0xAB, 0x56}; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -108,7 +100,7 @@ static void test_hitcount_target() { uint8_t ram[] = {0x00, 0x12, 0x34, 0xAB, 0x56}; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -144,7 +136,7 @@ static void test_hitcount_two_conditions(const char* memaddr, int expected_resul uint8_t ram[] = {0x00, 0x12, 0x34, 0xAB, 0x56}; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -161,7 +153,7 @@ static void test_hitcount_three_conditions(const char* memaddr, int expected_res uint8_t ram[] = {0x00, 0x12, 0x34, 0xAB, 0x56}; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -178,7 +170,7 @@ static void test_pauseif() { uint8_t ram[] = {0x00, 0x12, 0x34, 0xAB, 0x56}; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -211,7 +203,7 @@ static void test_pauseif_hitcount_one() { uint8_t ram[] = {0x00, 0x12, 0x34, 0xAB, 0x56}; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -234,7 +226,7 @@ static void test_pauseif_hitcount_two() { uint8_t ram[] = {0x00, 0x12, 0x34, 0xAB, 0x56}; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -263,7 +255,7 @@ static void test_pauseif_hitcount_with_reset() { uint8_t ram[] = {0x00, 0x12, 0x34, 0xAB, 0x56}; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -297,7 +289,7 @@ static void test_pauseif_resetnextif() uint8_t ram[] = { 0x00, 0x12, 0x34, 0xAB, 0x56 }; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -354,7 +346,7 @@ static void test_pauseif_does_not_increment_hits() { uint8_t ram[] = {0x00, 0x12, 0x34, 0xAB, 0x56}; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -401,7 +393,7 @@ static void test_pauseif_delta_updated() { uint8_t ram[] = {0x00, 0x00, 0x34, 0xAB, 0x56}; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -439,7 +431,7 @@ static void test_pauseif_indirect_delta_updated() { uint8_t ram[] = {0x00, 0x00, 0x34, 0x3C, 0x56}; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -477,7 +469,7 @@ static void test_pauseif_short_circuit() { uint8_t ram[] = {0x00, 0x00, 0x00, 0x00, 0x00}; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -547,7 +539,7 @@ static void test_resetif() { uint8_t ram[] = {0x00, 0x12, 0x34, 0xAB, 0x56}; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -591,7 +583,7 @@ static void test_resetif_cond_with_hittarget() { uint8_t ram[] = {0x00, 0x12, 0x34, 0xAB, 0x56}; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -641,7 +633,7 @@ static void test_resetif_hitcount() { uint8_t ram[] = {0x00, 0x12, 0x34, 0xAB, 0x56}; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -680,7 +672,7 @@ static void test_resetif_hitcount_one() { uint8_t ram[] = {0x00, 0x12, 0x34, 0xAB, 0x56}; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -713,7 +705,7 @@ static void test_resetif_hitcount_addhits() { uint8_t ram[] = {0x00, 0x12, 0x34, 0xAB, 0x56}; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -738,7 +730,7 @@ static void test_pauseif_resetif_hitcounts() { uint8_t ram[] = {0x00, 0x12, 0x34, 0xAB, 0x56}; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -779,7 +771,7 @@ static void test_resetnextif() { uint8_t ram[] = {0x00, 0x12, 0x34, 0xAB, 0x56}; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -829,7 +821,7 @@ static void test_resetnextif_non_hitcount_condition() { uint8_t ram[] = {0x00, 0x12, 0x34, 0xAB, 0x56}; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -880,7 +872,7 @@ static void test_resetnextif_addhits() { uint8_t ram[] = {0x00, 0x12, 0x34, 0xAB, 0x56}; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -920,7 +912,7 @@ static void test_resetnextif_addhits_chain() { uint8_t ram[] = {0x00, 0x12, 0x34, 0xAB, 0x56}; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -978,7 +970,7 @@ static void test_resetnextif_addhits_chain_total() { uint8_t ram[] = {0x00, 0x12, 0x34, 0xAB, 0x56}; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -1022,7 +1014,7 @@ static void test_resetnextif_using_andnext() { uint8_t ram[] = {0x00, 0x12, 0x34, 0xAB, 0x56}; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -1071,7 +1063,7 @@ static void test_resetnextif_andnext() { uint8_t ram[] = {0x00, 0x12, 0x34, 0xAB, 0x56}; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -1120,7 +1112,7 @@ static void test_resetnextif_andnext_hitchain() { uint8_t ram[] = {0x00, 0x12, 0x34, 0xAB, 0x56}; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -1177,7 +1169,7 @@ static void test_resetnextif_andnext_chain() uint8_t ram[] = { 0x00, 0x00, 0x00, 0x01, 0x00 }; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -1226,7 +1218,7 @@ static void test_resetnextif_addaddress_andnext_chain() uint8_t ram[] = { 0x00, 0x00, 0x00, 0x01, 0x00 }; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -1307,7 +1299,7 @@ static void test_resetnextif_addaddress() { uint8_t ram[] = {0x00, 0x00, 0x02, 0x03, 0x04}; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -1383,7 +1375,7 @@ static void test_resetnextif_chain() { uint8_t ram[] = {0x00, 0x12, 0x34, 0xAB, 0x56}; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -1440,7 +1432,7 @@ static void test_resetnextif_chain_andnext() { uint8_t ram[] = {0x00, 0x00, 0x01}; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -1495,7 +1487,7 @@ static void test_resetnextif_chain_with_hits() { uint8_t ram[] = {0x00, 0x12, 0x34, 0xAB, 0x56}; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -1583,7 +1575,7 @@ static void test_resetnextif_pause_lock() { uint8_t ram[] = {0x00, 0x12, 0x34, 0xAB, 0x56}; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -1646,7 +1638,7 @@ static void test_addsource() { uint8_t ram[] = {0x00, 0x12, 0x34, 0xAB, 0x56}; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -1683,7 +1675,7 @@ static void test_addsource_overflow() { uint8_t ram[] = {0x00, 0x12, 0x34, 0xAB, 0x56}; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -1705,7 +1697,7 @@ static void test_subsource() { uint8_t ram[] = {0x00, 0x12, 0x34, 0xAB, 0x56}; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -1749,7 +1741,7 @@ static void test_subsource_legacy_garbage() { uint8_t ram[] = { 0x00, 0x12, 0x34, 0xAB, 0x56 }; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -1793,7 +1785,7 @@ static void test_subsource_overflow() { uint8_t ram[] = {0x00, 0x12, 0x34, 0xAB, 0x56}; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -1815,7 +1807,7 @@ static void test_addsource_subsource() { uint8_t ram[] = {0x00, 0x12, 0x34, 0xAB, 0x56}; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -1864,7 +1856,7 @@ static void test_addsource_multiply() { uint8_t ram[] = {0x00, 0x06, 0x34, 0xAB, 0x56}; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -1901,7 +1893,7 @@ static void test_subsource_multiply() { uint8_t ram[] = {0x00, 0x06, 0x34, 0xAB, 0x56}; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -1938,7 +1930,7 @@ static void test_addsource_multiply_fraction() { uint8_t ram[] = {0x00, 0x08, 0x34, 0xAB, 0x56}; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -1975,7 +1967,7 @@ static void test_addsource_multiply_address() { uint8_t ram[] = {0x00, 0x06, 0x04, 0xAB, 0x56}; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -2012,7 +2004,7 @@ static void test_addsource_divide() { uint8_t ram[] = {0x00, 0x06, 0x34, 0xAB, 0x56}; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -2049,7 +2041,7 @@ static void test_addsource_compare_percentage() { uint8_t ram[] = {0x00, 0x06, 0x34, 0xAB, 0x56}; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -2071,7 +2063,7 @@ static void test_subsource_divide() { uint8_t ram[] = {0x00, 0x06, 0x34, 0xAB, 0x56}; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -2108,7 +2100,7 @@ static void test_addsource_divide_address() { uint8_t ram[] = {0x00, 0x06, 0x10, 0xAB, 0x56}; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -2145,7 +2137,7 @@ static void test_addsource_divide_self() { uint8_t ram[] = {0x00, 0x06, 0x10, 0xAB, 0x56}; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -2182,7 +2174,7 @@ static void test_addsource_mask() { uint8_t ram[] = {0x00, 0x06, 0x34, 0xAB, 0x56}; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -2219,7 +2211,7 @@ static void test_addsource_xor() { uint8_t ram[] = {0x00, 0x06, 0x34, 0xAB, 0x56}; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -2256,7 +2248,7 @@ static void test_addsource_float_first() { uint8_t ram[] = {0x00, 0x06, 0x34, 0xAB, 0x00, 0x00, 0xC0, 0x3F}; /* fF0004 = 1.5 */ memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -2287,7 +2279,7 @@ static void test_addsource_float_second() { uint8_t ram[] = {0x00, 0x06, 0x34, 0xAB, 0x00, 0x00, 0xC0, 0x3F}; /* fF0004 = 1.5 */ memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -2318,7 +2310,7 @@ static void test_subsource_mask() { uint8_t ram[] = {0x00, 0x6C, 0x34, 0xAB, 0x56}; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -2355,7 +2347,7 @@ static void test_subsource_overflow_comparison_equal() { uint8_t ram[] = {0x00, 0x6C, 0x34, 0xAB, 0x56}; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -2403,7 +2395,7 @@ static void test_subsource_overflow_comparison_greater() { uint8_t ram[] = {0x00, 0x6C, 0x34, 0xAB, 0x56}; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -2452,7 +2444,7 @@ static void test_subsource_overflow_comparison_greater_or_equal() { uint8_t ram[] = {0x00, 0x6C, 0x34, 0xAB, 0x56}; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -2501,7 +2493,7 @@ static void test_subsource_overflow_comparison_lesser() { uint8_t ram[] = {0x00, 0x6C, 0x34, 0xAB, 0x56}; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -2550,7 +2542,7 @@ static void test_subsource_overflow_comparison_lesser_or_equal() { uint8_t ram[] = {0x00, 0x6C, 0x34, 0xAB, 0x56}; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -2599,7 +2591,7 @@ static void test_subsource_float() { uint8_t ram[] = {0x06, 0x00, 0x00, 0x00, 0x92, 0x44, 0x9A, 0x42}; /* fF0004 = 77.133926 */ memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -2620,7 +2612,7 @@ static void test_addsource_bits_change() { uint8_t ram[] = { 0x00, 0x12, 0x34, 0xAB, 0x56 }; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -2669,7 +2661,7 @@ static void test_addhits() { uint8_t ram[] = {0x00, 0x12, 0x34, 0xAB, 0x56}; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -2717,7 +2709,7 @@ static void test_addhits_multiple() { uint8_t ram[] = {0x00, 0x12, 0x34, 0xAB, 0x56}; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -2749,7 +2741,7 @@ static void test_addhits_no_target() { uint8_t ram[] = {0x00, 0x12, 0x34, 0xAB, 0x56}; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -2781,7 +2773,7 @@ static void test_addhits_with_addsource() { uint8_t ram[] = {0x00, 0x12, 0x34, 0xAB, 0x56}; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -2810,7 +2802,7 @@ static void test_subhits() { uint8_t ram[] = {0x00, 0x12, 0x34, 0xAB, 0x56}; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -2856,7 +2848,7 @@ static void test_subhits_below_zero() { uint8_t ram[] = {0x00, 0x12, 0x34, 0xAB, 0x56}; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -2915,7 +2907,7 @@ static void test_andnext() { uint8_t ram[] = {0x00, 0x12, 0x34, 0xAB, 0x56}; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -2997,7 +2989,7 @@ static void test_andnext_boundaries() { uint8_t ram[] = {0x00, 0x12, 0x34, 0xAB, 0x56}; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -3046,7 +3038,7 @@ static void test_andnext_resetif() { uint8_t ram[] = {0x00, 0x12, 0x34, 0xAB, 0x56}; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -3123,7 +3115,7 @@ static void test_andnext_pauseif() { uint8_t ram[] = {0x00, 0x12, 0x34, 0xAB, 0x56}; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -3200,7 +3192,7 @@ static void test_andnext_addsource() { uint8_t ram[] = {0x00, 0x12, 0x34, 0xAB, 0x56}; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -3241,7 +3233,7 @@ static void test_andnext_addhits() { uint8_t ram[] = {0x00, 0x00, 0x34, 0xAB, 0x56}; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -3287,7 +3279,7 @@ static void test_andnext_between_addhits() { uint8_t ram[] = {0x00, 0x12, 0x34, 0xAB, 0x56}; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -3358,7 +3350,7 @@ static void test_andnext_with_hits_chain() { uint8_t ram[] = {0x00, 0x12, 0x34, 0xAB, 0x56}; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -3441,7 +3433,7 @@ static void test_andnext_changes_to() { uint8_t ram[] = {0x00, 0x12, 0x34, 0xAB, 0x56}; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -3472,7 +3464,7 @@ static void test_ornext() { uint8_t ram[] = {0x00, 0x12, 0x34, 0xAB, 0x56}; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -3542,7 +3534,7 @@ static void test_andnext_ornext_interaction() { uint8_t ram[] = {0, 0, 0, 0, 0}; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -3567,7 +3559,7 @@ static void test_addaddress_direct_pointer() { uint8_t ram[] = {0x01, 0x12, 0x34, 0xAB, 0x56}; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -3604,7 +3596,7 @@ static void test_addaddress_direct_pointer_delta() { uint8_t ram[] = { 0x01, 0x12, 0x34, 0xAB, 0x56 }; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -3669,7 +3661,7 @@ static void test_addaddress_direct_pointer_prior() { uint8_t ram[] = { 0x01, 0x12, 0x34, 0xAB, 0x56 }; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -3738,7 +3730,7 @@ static void test_addaddress_direct_pointer_change() { uint8_t ram[] = { 0x01, 0x12, 0x34, 0xAB, 0x56 }; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -3806,7 +3798,7 @@ static void test_addaddress_indirect_pointer() { uint8_t ram[] = {0x01, 0x12, 0x34, 0xAB, 0x56}; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -3847,7 +3839,7 @@ static void test_addaddress_indirect_pointer_negative() { uint8_t ram[] = {0x02, 0x12, 0x34, 0xAB, 0x56}; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -3888,7 +3880,7 @@ static void test_addaddress_indirect_pointer_out_of_range() { uint8_t ram[] = {0x01, 0x12, 0x34, 0xAB, 0x56, 0x16}; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -3915,7 +3907,7 @@ static void test_addaddress_indirect_pointer_multiple() { uint8_t ram[] = {0x01, 0x02, 0x03, 0x34, 0xAB, 0x56}; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -3960,7 +3952,7 @@ static void test_addaddress_indirect_pointer_with_delta() uint8_t ram[] = { 0x01, 0x02, 0x03, 0x34, 0xAB, 0x56 }; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -4010,7 +4002,7 @@ static void test_addaddress_indirect_pointer_from_memory() { uint8_t ram[] = { 0x01, 0x01, 0x34, 0xAB, 0x56 }; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -4047,7 +4039,7 @@ static void test_addaddress_indirect_constant() { uint8_t ram[] = { 0x01, 0x12, 0x34, 0xAB, 0x56 }; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -4076,7 +4068,7 @@ static void test_addaddress_pointer_data_size_differs_from_pointer_size() { uint8_t ram[] = {0x01, 0x12, 0x34, 0xAB, 0x56}; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -4110,7 +4102,7 @@ static void test_addaddress_double_indirection() { uint8_t ram[] = {0x01, 0x02, 0x34, 0xAB, 0x56}; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -4148,7 +4140,7 @@ static void test_addaddress_double_indirection_with_delta() { uint8_t ram[] = { 0, 2, 4 }; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -4176,7 +4168,7 @@ static void test_addaddress_double_indirection_with_delta_incorrect() { uint8_t ram[] = { 0, 2, 4 }; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -4209,7 +4201,7 @@ static void test_addaddress_adjust_both_sides() { uint8_t ram[] = {0x02, 0x11, 0x34, 0xAB, 0x56}; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -4243,7 +4235,7 @@ static void test_addaddress_adjust_both_sides_different_bases() { uint8_t ram[] = {0x02, 0x11, 0x34, 0xAB, 0x56}; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -4270,7 +4262,7 @@ static void test_addaddress_scaled() { uint8_t ram[] = {0x01, 0x12, 0x34, 0xAB, 0x56}; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -4305,7 +4297,7 @@ static void test_addaddress_scaled_negative() { uint8_t ram[] = {0x01, 0x12, 0x34, 0xAB, 0x01}; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -4341,7 +4333,7 @@ static void test_addaddress_shared_size() uint8_t ram[] = { 0x01, 0x12, 0x34, 0xAB, 0x56 }; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; @@ -4371,7 +4363,7 @@ static void test_prior_sequence() { uint8_t ram[] = {0x00}; memory_t memory; rc_condset_t* condset; - rc_condset_memrefs_t memrefs; + rc_memrefs_t memrefs; char buffer[2048]; memory.ram = ram; diff --git a/test/rcheevos/test_memref.c b/test/rcheevos/test_memref.c index ba9ef5a5..4d4d3eec 100644 --- a/test/rcheevos/test_memref.c +++ b/test/rcheevos/test_memref.c @@ -258,19 +258,12 @@ static void test_transforms(void) } static int get_memref_count(rc_parse_state_t* parse) { - int count = 0; - rc_memref_t *memref = *parse->first_memref; - while (memref) { - ++count; - memref = memref->next; - } - - return count; + return rc_memrefs_count_memrefs(parse->memrefs) + rc_memrefs_count_modified_memrefs(parse->memrefs); } static void test_allocate_shared_address() { rc_parse_state_t parse; - rc_memref_t* memrefs; + rc_memrefs_t memrefs; rc_init_parse_state(&parse, NULL, 0, 0); rc_init_parse_state_memrefs(&parse, &memrefs); @@ -306,7 +299,7 @@ static void test_allocate_shared_address() { static void test_allocate_shared_address2() { rc_parse_state_t parse; - rc_memref_t* memrefs; + rc_memrefs_t memrefs; rc_memref_t* memref1; rc_memref_t* memref2; rc_memref_t* memref3; @@ -324,8 +317,7 @@ static void test_allocate_shared_address2() { ASSERT_NUM_EQUALS(memref1->value.value, 0); ASSERT_NUM_EQUALS(memref1->value.changed, 0); ASSERT_NUM_EQUALS(memref1->value.prior, 0); - ASSERT_PTR_EQUALS(memref1->next, 0); - + memref2 = rc_alloc_memref(&parse, 1, RC_MEMSIZE_16_BITS); /* differing size will not match */ memref3 = rc_alloc_memref(&parse, 1, RC_MEMSIZE_LOW); /* differing size will not match */ memref4 = rc_alloc_memref(&parse, 1, RC_MEMSIZE_BIT_2); /* differing size will not match */ @@ -351,7 +343,7 @@ static void test_allocate_shared_address2() { static void test_allocate_shared_indirect_address() { rc_parse_state_t parse; - rc_memref_t* memrefs; + rc_memrefs_t memrefs; rc_memref_t* parent_memref1, *parent_memref2; rc_operand_t parent1, parent2, delta1, intermediate2; rc_modified_memref_t* child1, *child2, *child3, *child4; @@ -420,7 +412,7 @@ static void test_allocate_shared_indirect_address() { static void test_sizing_mode_grow_buffer() { int i; rc_parse_state_t parse; - rc_memref_t* memrefs; + rc_memrefs_t memrefs; rc_init_parse_state(&parse, NULL, 0, 0); rc_init_parse_state_memrefs(&parse, &memrefs); @@ -451,7 +443,7 @@ static void test_sizing_mode_grow_buffer() { static void test_update_memref_values() { rc_parse_state_t parse; - rc_memref_t* memrefs; + rc_memrefs_t memrefs; rc_memref_t* memref1; rc_memref_t* memref2; @@ -466,7 +458,7 @@ static void test_update_memref_values() { memref1 = rc_alloc_memref(&parse, 1, RC_MEMSIZE_8_BITS); memref2 = rc_alloc_memref(&parse, 2, RC_MEMSIZE_8_BITS); - rc_update_memref_values(memrefs, peek, &memory); + rc_update_memref_values(&memrefs, peek, &memory); ASSERT_NUM_EQUALS(memref1->value.value, 0x12); ASSERT_NUM_EQUALS(memref1->value.changed, 1); @@ -476,7 +468,7 @@ static void test_update_memref_values() { ASSERT_NUM_EQUALS(memref2->value.prior, 0); ram[1] = 3; - rc_update_memref_values(memrefs, peek, &memory); + rc_update_memref_values(&memrefs, peek, &memory); ASSERT_NUM_EQUALS(memref1->value.value, 3); ASSERT_NUM_EQUALS(memref1->value.changed, 1); @@ -486,7 +478,7 @@ static void test_update_memref_values() { ASSERT_NUM_EQUALS(memref2->value.prior, 0); ram[1] = 5; - rc_update_memref_values(memrefs, peek, &memory); + rc_update_memref_values(&memrefs, peek, &memory); ASSERT_NUM_EQUALS(memref1->value.value, 5); ASSERT_NUM_EQUALS(memref1->value.changed, 1); @@ -496,7 +488,7 @@ static void test_update_memref_values() { ASSERT_NUM_EQUALS(memref2->value.prior, 0); ram[2] = 7; - rc_update_memref_values(memrefs, peek, &memory); + rc_update_memref_values(&memrefs, peek, &memory); ASSERT_NUM_EQUALS(memref1->value.value, 5); ASSERT_NUM_EQUALS(memref1->value.changed, 0); diff --git a/test/rcheevos/test_operand.c b/test/rcheevos/test_operand.c index 60bd1d9e..f46a2135 100644 --- a/test/rcheevos/test_operand.c +++ b/test/rcheevos/test_operand.c @@ -5,7 +5,7 @@ static void _assert_parse_operand(rc_operand_t* self, char* buffer, const char** memaddr) { rc_parse_state_t parse; - rc_memref_t* memrefs; + rc_memrefs_t memrefs; int ret; rc_init_parse_state(&parse, buffer, 0, 0); @@ -63,7 +63,7 @@ static void test_parse_error_operand(const char* memaddr, int valid_chars, int e rc_parse_state_t parse; int ret; const char* begin = memaddr; - rc_memref_t* memrefs; + rc_memrefs_t memrefs; rc_init_parse_state(&parse, 0, 0, 0); rc_init_parse_state_memrefs(&parse, &memrefs); @@ -74,7 +74,7 @@ static void test_parse_error_operand(const char* memaddr, int valid_chars, int e ASSERT_NUM_EQUALS(memaddr - begin, valid_chars); } -static uint32_t evaluate_operand(rc_operand_t* op, memory_t* memory, rc_memref_t* memrefs) +static uint32_t evaluate_operand(rc_operand_t* op, memory_t* memory, rc_memrefs_t* memrefs) { rc_eval_state_t eval_state; rc_typed_value_t value; @@ -91,7 +91,7 @@ static uint32_t evaluate_operand(rc_operand_t* op, memory_t* memory, rc_memref_t static void test_evaluate_operand(const char* memaddr, memory_t* memory, uint32_t expected_value) { rc_operand_t self; rc_parse_state_t parse; - rc_memref_t* memrefs; + rc_memrefs_t memrefs; char buffer[512]; uint32_t value; @@ -100,11 +100,11 @@ static void test_evaluate_operand(const char* memaddr, memory_t* memory, uint32_ rc_parse_operand(&self, &memaddr, &parse); rc_destroy_parse_state(&parse); - value = evaluate_operand(&self, memory, memrefs); + value = evaluate_operand(&self, memory, &memrefs); ASSERT_NUM_EQUALS(value, expected_value); } -static float evaluate_operand_float(rc_operand_t* op, memory_t* memory, rc_memref_t* memrefs) { +static float evaluate_operand_float(rc_operand_t* op, memory_t* memory, rc_memrefs_t* memrefs) { rc_eval_state_t eval_state; rc_typed_value_t value; @@ -120,7 +120,7 @@ static float evaluate_operand_float(rc_operand_t* op, memory_t* memory, rc_memre static void test_evaluate_operand_float(const char* memaddr, memory_t* memory, double expected_value) { rc_operand_t self; rc_parse_state_t parse; - rc_memref_t* memrefs; + rc_memrefs_t memrefs; char buffer[512]; float value; @@ -129,7 +129,7 @@ static void test_evaluate_operand_float(const char* memaddr, memory_t* memory, d rc_parse_operand(&self, &memaddr, &parse); rc_destroy_parse_state(&parse); - value = evaluate_operand_float(&self, memory, memrefs); + value = evaluate_operand_float(&self, memory, &memrefs); ASSERT_FLOAT_EQUALS(value, expected_value); } static void test_parse_memory_references() { @@ -522,7 +522,7 @@ static void test_evaluate_delta_memory_reference() { const char* memaddr; rc_parse_state_t parse; char buffer[256]; - rc_memref_t* memrefs; + rc_memrefs_t memrefs; memory.ram = ram; memory.size = sizeof(ram); @@ -533,24 +533,24 @@ static void test_evaluate_delta_memory_reference() { rc_parse_operand(&op, &memaddr, &parse); rc_destroy_parse_state(&parse); - ASSERT_UNUM_EQUALS(evaluate_operand(&op, &memory, memrefs), 0x00); /* first call gets uninitialized value */ - ASSERT_UNUM_EQUALS(evaluate_operand(&op, &memory, memrefs), 0x12); /* second gets current value */ + ASSERT_UNUM_EQUALS(evaluate_operand(&op, &memory, &memrefs), 0x00); /* first call gets uninitialized value */ + ASSERT_UNUM_EQUALS(evaluate_operand(&op, &memory, &memrefs), 0x12); /* second gets current value */ /* RC_OPERAND_DELTA is always one frame behind */ ram[1] = 0x13; - ASSERT_UNUM_EQUALS(evaluate_operand(&op, &memory, memrefs), 0x12U); + ASSERT_UNUM_EQUALS(evaluate_operand(&op, &memory, &memrefs), 0x12U); ram[1] = 0x14; - ASSERT_UNUM_EQUALS(evaluate_operand(&op, &memory, memrefs), 0x13U); + ASSERT_UNUM_EQUALS(evaluate_operand(&op, &memory, &memrefs), 0x13U); ram[1] = 0x15; - ASSERT_UNUM_EQUALS(evaluate_operand(&op, &memory, memrefs), 0x14U); + ASSERT_UNUM_EQUALS(evaluate_operand(&op, &memory, &memrefs), 0x14U); ram[1] = 0x16; - ASSERT_UNUM_EQUALS(evaluate_operand(&op, &memory, memrefs), 0x15U); + ASSERT_UNUM_EQUALS(evaluate_operand(&op, &memory, &memrefs), 0x15U); - ASSERT_UNUM_EQUALS(evaluate_operand(&op, &memory, memrefs), 0x16U); - ASSERT_UNUM_EQUALS(evaluate_operand(&op, &memory, memrefs), 0x16U); + ASSERT_UNUM_EQUALS(evaluate_operand(&op, &memory, &memrefs), 0x16U); + ASSERT_UNUM_EQUALS(evaluate_operand(&op, &memory, &memrefs), 0x16U); } void test_evaluate_prior_memory_reference() { @@ -560,7 +560,7 @@ void test_evaluate_prior_memory_reference() { const char* memaddr; rc_parse_state_t parse; char buffer[256]; - rc_memref_t* memrefs; + rc_memrefs_t memrefs; memory.ram = ram; memory.size = sizeof(ram); @@ -572,25 +572,25 @@ void test_evaluate_prior_memory_reference() { rc_destroy_parse_state(&parse); /* RC_OPERAND_PRIOR only updates when the memory value changes */ - ASSERT_UNUM_EQUALS(evaluate_operand(&op, &memory, memrefs), 0x00); /* first call gets uninitialized value */ - ASSERT_UNUM_EQUALS(evaluate_operand(&op, &memory, memrefs), 0x00); /* value only changes when memory changes */ + ASSERT_UNUM_EQUALS(evaluate_operand(&op, &memory, &memrefs), 0x00); /* first call gets uninitialized value */ + ASSERT_UNUM_EQUALS(evaluate_operand(&op, &memory, &memrefs), 0x00); /* value only changes when memory changes */ ram[1] = 0x13; - ASSERT_UNUM_EQUALS(evaluate_operand(&op, &memory, memrefs), 0x12U); - ASSERT_UNUM_EQUALS(evaluate_operand(&op, &memory, memrefs), 0x12U); - ASSERT_UNUM_EQUALS(evaluate_operand(&op, &memory, memrefs), 0x12U); - ASSERT_UNUM_EQUALS(evaluate_operand(&op, &memory, memrefs), 0x12U); + ASSERT_UNUM_EQUALS(evaluate_operand(&op, &memory, &memrefs), 0x12U); + ASSERT_UNUM_EQUALS(evaluate_operand(&op, &memory, &memrefs), 0x12U); + ASSERT_UNUM_EQUALS(evaluate_operand(&op, &memory, &memrefs), 0x12U); + ASSERT_UNUM_EQUALS(evaluate_operand(&op, &memory, &memrefs), 0x12U); ram[1] = 0x14; - ASSERT_UNUM_EQUALS(evaluate_operand(&op, &memory, memrefs), 0x13U); + ASSERT_UNUM_EQUALS(evaluate_operand(&op, &memory, &memrefs), 0x13U); ram[1] = 0x15; - ASSERT_UNUM_EQUALS(evaluate_operand(&op, &memory, memrefs), 0x14U); + ASSERT_UNUM_EQUALS(evaluate_operand(&op, &memory, &memrefs), 0x14U); ram[1] = 0x16; - ASSERT_UNUM_EQUALS(evaluate_operand(&op, &memory, memrefs), 0x15U); - ASSERT_UNUM_EQUALS(evaluate_operand(&op, &memory, memrefs), 0x15U); - ASSERT_UNUM_EQUALS(evaluate_operand(&op, &memory, memrefs), 0x15U); + ASSERT_UNUM_EQUALS(evaluate_operand(&op, &memory, &memrefs), 0x15U); + ASSERT_UNUM_EQUALS(evaluate_operand(&op, &memory, &memrefs), 0x15U); + ASSERT_UNUM_EQUALS(evaluate_operand(&op, &memory, &memrefs), 0x15U); } static void test_evaluate_memory_references_float() { @@ -633,7 +633,7 @@ static void test_evaluate_delta_memory_reference_float() { const char* memaddr; rc_parse_state_t parse; char buffer[256]; - rc_memref_t* memrefs; + rc_memrefs_t memrefs; memory.ram = ram; memory.size = sizeof(ram); @@ -644,24 +644,24 @@ static void test_evaluate_delta_memory_reference_float() { rc_parse_operand(&op, &memaddr, &parse); rc_destroy_parse_state(&parse); - ASSERT_NUM_EQUALS(evaluate_operand_float(&op, &memory, memrefs), 0.0); /* first call gets uninitialized value */ - ASSERT_NUM_EQUALS(evaluate_operand_float(&op, &memory, memrefs), 1.0); /* second gets current value */ + ASSERT_NUM_EQUALS(evaluate_operand_float(&op, &memory, &memrefs), 0.0); /* first call gets uninitialized value */ + ASSERT_NUM_EQUALS(evaluate_operand_float(&op, &memory, &memrefs), 1.0); /* second gets current value */ /* RC_OPERAND_DELTA is always one frame behind */ ram[3] = 0x40; - ASSERT_NUM_EQUALS(evaluate_operand_float(&op, &memory, memrefs), 1.0); + ASSERT_NUM_EQUALS(evaluate_operand_float(&op, &memory, &memrefs), 1.0); ram[3] = 0x41; - ASSERT_NUM_EQUALS(evaluate_operand_float(&op, &memory, memrefs), 4.0); + ASSERT_NUM_EQUALS(evaluate_operand_float(&op, &memory, &memrefs), 4.0); ram[3] = 0x42; - ASSERT_NUM_EQUALS(evaluate_operand_float(&op, &memory, memrefs), 16.0); + ASSERT_NUM_EQUALS(evaluate_operand_float(&op, &memory, &memrefs), 16.0); ram[3] = 0x43; - ASSERT_NUM_EQUALS(evaluate_operand_float(&op, &memory, memrefs), 64.0); + ASSERT_NUM_EQUALS(evaluate_operand_float(&op, &memory, &memrefs), 64.0); - ASSERT_NUM_EQUALS(evaluate_operand_float(&op, &memory, memrefs), 256.0); - ASSERT_NUM_EQUALS(evaluate_operand_float(&op, &memory, memrefs), 256.0); + ASSERT_NUM_EQUALS(evaluate_operand_float(&op, &memory, &memrefs), 256.0); + ASSERT_NUM_EQUALS(evaluate_operand_float(&op, &memory, &memrefs), 256.0); } void test_operand(void) { diff --git a/test/rcheevos/test_richpresence.c b/test/rcheevos/test_richpresence.c index 82d05648..691a607c 100644 --- a/test/rcheevos/test_richpresence.c +++ b/test/rcheevos/test_richpresence.c @@ -5,13 +5,14 @@ #include "../src/rc_compat.h" -static void _assert_parse_richpresence(rc_richpresence_t** richpresence, void* buffer, const char* script) { +static void _assert_parse_richpresence(rc_richpresence_t** richpresence, void* buffer, size_t buffer_size, const char* script) { int size; unsigned* overflow; *richpresence = NULL; size = rc_richpresence_size(script); ASSERT_NUM_GREATER(size, 0); + ASSERT_NUM_LESS_EQUALS(size + 4, buffer_size); overflow = (unsigned*)(((char*)buffer) + size); *overflow = 0xCDCDCDCD; @@ -23,7 +24,7 @@ static void _assert_parse_richpresence(rc_richpresence_t** richpresence, void* b ASSERT_FAIL("write past end of buffer"); } } -#define assert_parse_richpresence(richpresence_out, buffer, script) ASSERT_HELPER(_assert_parse_richpresence(richpresence_out, buffer, script), "assert_parse_richpresence") +#define assert_parse_richpresence(richpresence_out, buffer, script) ASSERT_HELPER(_assert_parse_richpresence(richpresence_out, buffer, sizeof(buffer), script), "assert_parse_richpresence") static void _assert_richpresence_output(rc_richpresence_t* richpresence, memory_t* memory, const char* expected_display_string) { char output[256]; @@ -81,31 +82,31 @@ static void test_buffer_boundary() { memory.size = sizeof(ram); /* static strings */ - assert_parse_richpresence(&richpresence, &buffer[32], "Display:\nABCDEFGH"); + assert_parse_richpresence(&richpresence, buffer, "Display:\nABCDEFGH"); TEST_PARAMS5(assert_buffer_boundary, richpresence, &memory, 7, 8, "ABCDEF"); /* only 6 chars written */ TEST_PARAMS5(assert_buffer_boundary, richpresence, &memory, 8, 8, "ABCDEFG"); /* only 7 chars written */ TEST_PARAMS5(assert_buffer_boundary, richpresence, &memory, 9, 8, "ABCDEFGH"); /* all 8 chars written */ /* number formatting */ - assert_parse_richpresence(&richpresence, &buffer[32], "Format:V\nFormatType=VALUE\n\nDisplay:\n@V(0xX0000)"); + assert_parse_richpresence(&richpresence, buffer, "Format:V\nFormatType=VALUE\n\nDisplay:\n@V(0xX0000)"); TEST_PARAMS5(assert_buffer_boundary, richpresence, &memory, 7, 8, "167772"); /* only 6 chars written */ TEST_PARAMS5(assert_buffer_boundary, richpresence, &memory, 8, 8, "1677721"); /* only 7 chars written */ TEST_PARAMS5(assert_buffer_boundary, richpresence, &memory, 9, 8, "16777216"); /* all 8 chars written */ /* lookup */ - assert_parse_richpresence(&richpresence, &buffer[32], "Lookup:L\n1=ABCDEFGH\n\nDisplay:\n@L(0xH0003)"); + assert_parse_richpresence(&richpresence, buffer, "Lookup:L\n1=ABCDEFGH\n\nDisplay:\n@L(0xH0003)"); TEST_PARAMS5(assert_buffer_boundary, richpresence, &memory, 7, 8, "ABCDEF"); /* only 6 chars written */ TEST_PARAMS5(assert_buffer_boundary, richpresence, &memory, 8, 8, "ABCDEFG"); /* only 7 chars written */ TEST_PARAMS5(assert_buffer_boundary, richpresence, &memory, 9, 8, "ABCDEFGH"); /* all 8 chars written */ /* unknown macro - "[Unknown macro]L(0xH0003)" = 25 chars */ - assert_parse_richpresence(&richpresence, &buffer[32], "Display:\n@L(0xH0003)"); + assert_parse_richpresence(&richpresence, buffer, "Display:\n@L(0xH0003)"); TEST_PARAMS5(assert_buffer_boundary, richpresence, &memory, 7, 25, "[Unkno"); /* only 6 chars written */ TEST_PARAMS5(assert_buffer_boundary, richpresence, &memory, 25, 25, "[Unknown macro]L(0xH0003"); /* only 24 chars written */ TEST_PARAMS5(assert_buffer_boundary, richpresence, &memory, 26, 25, "[Unknown macro]L(0xH0003)"); /* all 25 chars written */ /* multipart */ - assert_parse_richpresence(&richpresence, &buffer[32], "Lookup:L\n0=\n1=A\n4=ABCD\n8=ABCDEFGH\n\nFormat:V\nFormatType=VALUE\n\nDisplay:\n@L(0xH0000)--@L(0xH0001)--@V(0xH0002)"); + assert_parse_richpresence(&richpresence, buffer, "Lookup:L\n0=\n1=A\n4=ABCD\n8=ABCDEFGH\n\nFormat:V\nFormatType=VALUE\n\nDisplay:\n@L(0xH0000)--@L(0xH0001)--@V(0xH0002)"); TEST_PARAMS5(assert_buffer_boundary, richpresence, &memory, 8, 5, "----0"); /* initial value fits */ ram[1] = 4; TEST_PARAMS5(assert_buffer_boundary, richpresence, &memory, 8, 9, "--ABCD-"); /* only 7 chars written */ @@ -1156,7 +1157,7 @@ static void test_builtin_macro_override() { uint8_t ram[] = { 0x39, 0x30 }; memory_t memory; rc_richpresence_t* richpresence; - char buffer[256]; + char buffer[512]; memory.ram = ram; memory.size = sizeof(ram); diff --git a/test/rcheevos/test_runtime.c b/test/rcheevos/test_runtime.c index 6c9fcd49..a01324db 100644 --- a/test/rcheevos/test_runtime.c +++ b/test/rcheevos/test_runtime.c @@ -53,7 +53,7 @@ static void assert_do_frame(rc_runtime_t* runtime, memory_t* memory) rc_runtime_do_frame(runtime, event_handler, peek, memory, NULL); } -static void assert_richpresence_display_string(rc_runtime_t* runtime, memory_t* memory, const char* expected) +static void _assert_richpresence_display_string(rc_runtime_t* runtime, memory_t* memory, const char* expected) { char buffer[512]; const int expected_len = (int)strlen(expected); @@ -61,6 +61,7 @@ static void assert_richpresence_display_string(rc_runtime_t* runtime, memory_t* ASSERT_STR_EQUALS(buffer, expected); ASSERT_NUM_EQUALS(result, expected_len); } +#define assert_richpresence_display_string(runtime, memory, expected) ASSERT_HELPER(_assert_richpresence_display_string(runtime, memory, expected), "assert_richpresence_display_string") static void test_two_achievements_activate_and_trigger(void) { @@ -145,11 +146,10 @@ static void test_deactivate_achievements(void) ASSERT_NUM_EQUALS(runtime.triggers[1].trigger->state, RC_TRIGGER_STATE_WAITING); ASSERT_NUM_EQUALS(event_count, 0); - /* deactivate the first. it owns shared memrefs, so can't be deallocated */ + /* deactivate the first. */ rc_runtime_deactivate_achievement(&runtime, 1); - ASSERT_NUM_EQUALS(runtime.trigger_count, 2); - ASSERT_PTR_NULL(runtime.triggers[0].trigger); - ASSERT_NUM_EQUALS(runtime.triggers[1].trigger->state, RC_TRIGGER_STATE_WAITING); + ASSERT_NUM_EQUALS(runtime.trigger_count, 1); + ASSERT_NUM_EQUALS(runtime.triggers[0].trigger->state, RC_TRIGGER_STATE_WAITING); /* both achievements are false, deactivated one should not activate */ ram[1] = ram[2] = 9; @@ -163,24 +163,23 @@ static void test_deactivate_achievements(void) ASSERT_NUM_EQUALS(event_count, 1); assert_event(RC_RUNTIME_EVENT_ACHIEVEMENT_TRIGGERED, 2, 0); - /* reactivate achievement. definition didn't change, should reactivate in-place */ + /* reactivate achievement. */ assert_activate_achievement(&runtime, 1, "0xH0001=10"); ASSERT_NUM_EQUALS(runtime.trigger_count, 2); - ASSERT_PTR_NOT_NULL(runtime.triggers[0].trigger); - ASSERT_NUM_EQUALS(runtime.triggers[0].trigger->state, RC_TRIGGER_STATE_WAITING); - ASSERT_NUM_EQUALS(runtime.triggers[1].trigger->state, RC_TRIGGER_STATE_TRIGGERED); + ASSERT_NUM_EQUALS(runtime.triggers[0].trigger->state, RC_TRIGGER_STATE_TRIGGERED); + ASSERT_NUM_EQUALS(runtime.triggers[1].trigger->state, RC_TRIGGER_STATE_WAITING); /* reactivated achievement is waiting and should not trigger */ assert_do_frame(&runtime, &memory); - ASSERT_NUM_EQUALS(runtime.triggers[0].trigger->state, RC_TRIGGER_STATE_WAITING); - ASSERT_NUM_EQUALS(runtime.triggers[1].trigger->state, RC_TRIGGER_STATE_TRIGGERED); + ASSERT_NUM_EQUALS(runtime.triggers[0].trigger->state, RC_TRIGGER_STATE_TRIGGERED); + ASSERT_NUM_EQUALS(runtime.triggers[1].trigger->state, RC_TRIGGER_STATE_WAITING); ASSERT_NUM_EQUALS(event_count, 0); /* both achievements are false. first should activate, second should be ignored */ ram[1] = ram[2] = 9; assert_do_frame(&runtime, &memory); - ASSERT_NUM_EQUALS(runtime.triggers[0].trigger->state, RC_TRIGGER_STATE_ACTIVE); - ASSERT_NUM_EQUALS(runtime.triggers[1].trigger->state, RC_TRIGGER_STATE_TRIGGERED); + ASSERT_NUM_EQUALS(runtime.triggers[0].trigger->state, RC_TRIGGER_STATE_TRIGGERED); + ASSERT_NUM_EQUALS(runtime.triggers[1].trigger->state, RC_TRIGGER_STATE_ACTIVE); ASSERT_NUM_EQUALS(event_count, 1); assert_event(RC_RUNTIME_EVENT_ACHIEVEMENT_ACTIVATED, 1, 0); @@ -499,11 +498,10 @@ static void test_shared_memref(void) ASSERT_NUM_EQUALS(event_count, 1); assert_event(RC_RUNTIME_EVENT_ACHIEVEMENT_ACTIVATED, 2, 0); - /* deactivate first achievement. memrefs used by second - cannot be free'd */ + /* deactivate first achievement. */ rc_runtime_deactivate_achievement(&runtime, 1); - ASSERT_NUM_EQUALS(runtime.trigger_count, 2); - ASSERT_PTR_NULL(runtime.triggers[0].trigger); - ASSERT_NUM_EQUALS(runtime.triggers[1].trigger->state, RC_TRIGGER_STATE_ACTIVE); + ASSERT_NUM_EQUALS(runtime.trigger_count, 1); + ASSERT_NUM_EQUALS(runtime.triggers[0].trigger->state, RC_TRIGGER_STATE_ACTIVE); /* second achievement is true. should trigger using memrefs from first */ ram[1] = 12; @@ -530,9 +528,8 @@ static void test_replace_active_trigger(void) /* both are true, but first should have been overwritten by second */ assert_do_frame(&runtime, &memory); - ASSERT_NUM_EQUALS(runtime.trigger_count, 2); - ASSERT_PTR_NULL(runtime.triggers[0].trigger); - ASSERT_NUM_EQUALS(runtime.triggers[1].trigger->state, RC_TRIGGER_STATE_WAITING); + ASSERT_NUM_EQUALS(runtime.trigger_count, 1); + ASSERT_NUM_EQUALS(runtime.triggers[0].trigger->state, RC_TRIGGER_STATE_WAITING); ASSERT_NUM_EQUALS(event_count, 0); /* both are false. only second should be getting processed, expect single event */ @@ -552,11 +549,10 @@ static void test_replace_active_trigger(void) ASSERT_NUM_EQUALS(event_count, 1); assert_event(RC_RUNTIME_EVENT_ACHIEVEMENT_TRIGGERED, 1, 0); - /* switch back to original definition. since the memrefs kept the buffer alive, it should be recycled */ + /* switch back to original definition. */ assert_activate_achievement(&runtime, 1, "0xH0001=10"); - ASSERT_NUM_EQUALS(runtime.trigger_count, 2); + ASSERT_NUM_EQUALS(runtime.trigger_count, 1); ASSERT_NUM_EQUALS(runtime.triggers[0].trigger->state, RC_TRIGGER_STATE_WAITING); - ASSERT_PTR_NULL(runtime.triggers[1].trigger); rc_runtime_destroy(&runtime); } @@ -603,10 +599,8 @@ static void test_trigger_deactivation(void) assert_event(RC_RUNTIME_EVENT_ACHIEVEMENT_TRIGGERED, 2, 0); assert_event(RC_RUNTIME_EVENT_ACHIEVEMENT_TRIGGERED, 3, 0); - /* triggers 2 and 3 should have been removed from the runtime since they don't have memrefs, - * and trigger 1 should be nulled out. */ - ASSERT_NUM_EQUALS(runtime.trigger_count, 1); - ASSERT_PTR_NULL(runtime.triggers[0].trigger); + /* triggers are no longer active and should have been removed from the runtime */ + ASSERT_NUM_EQUALS(runtime.trigger_count, 0); rc_runtime_destroy(&runtime); } @@ -1347,10 +1341,6 @@ static void test_richpresence_reload(void) "Format:Points\nFormatType=VALUE\n\nDisplay:\n@Points(0x 0001) Bananas"); assert_richpresence_display_string(&runtime, &memory, "2570 Bananas"); - /* memrefs should be reused from first script */ - ASSERT_NUM_EQUALS(runtime.richpresence->owns_memrefs, 0); - ASSERT_PTR_NOT_NULL(runtime.richpresence->previous); - /* first frame after reloading should update display string */ assert_do_frame(&runtime, &memory); assert_richpresence_display_string(&runtime, &memory, "2580 Bananas"); @@ -1386,10 +1376,6 @@ static void test_richpresence_reload_addaddress(void) "Format:Points\nFormatType=VALUE\n\nDisplay:\n@Points(I:0xH0000_M:0x 0001) Bananas"); assert_richpresence_display_string(&runtime, &memory, "2570 Bananas"); - /* the AddAddress expression will be owned by the previous script. */ - ASSERT_NUM_EQUALS(runtime.richpresence->owns_memrefs, 0); - ASSERT_PTR_NOT_NULL(runtime.richpresence->previous); - /* first frame after reloading should update display string */ assert_do_frame(&runtime, &memory); assert_richpresence_display_string(&runtime, &memory, "2580 Bananas"); @@ -1419,6 +1405,23 @@ static void test_richpresence_static(void) rc_runtime_destroy(&runtime); } +static void test_richpresence_addsource_chain(void) +{ + rc_runtime_t runtime; + rc_runtime_init(&runtime); + + /* large number of AddSources will exceed the runtime buffer of 32 memrefs and 16 modified memrefs */ + assert_activate_richpresence(&runtime, + "Display:\n" + "@Number(0xH0000_0xH0001_0xH0002_0xH0003_0xH0004_0xH0005_0xH0006_0xH0007_" + "0xH0010_0xH0011_0xH0012_0xH0013_0xH0014_0xH0015_0xH0016_0xH0017_" + "0xH0020_0xH0021_0xH0022_0xH0023_0xH0024_0xH0025_0xH0026_0xH0027_" + "0xH0030_0xH0031_0xH0032_0xH0033_0xH0034_0xH0035_0xH0036_0xH0037_" + "0xH0040_0xH0041_0xH0042_0xH0043)\n"); + + rc_runtime_destroy(&runtime); +} + typedef struct { memory_t memory; rc_runtime_t* runtime; @@ -1650,6 +1653,7 @@ void test_runtime(void) { TEST(test_richpresence_reload); TEST(test_richpresence_reload_addaddress); TEST(test_richpresence_static); + TEST(test_richpresence_addsource_chain); /* invalidate address */ TEST(test_invalidate_address); diff --git a/test/rcheevos/test_runtime_progress.c b/test/rcheevos/test_runtime_progress.c index 800faaf7..8303aa29 100644 --- a/test/rcheevos/test_runtime_progress.c +++ b/test/rcheevos/test_runtime_progress.c @@ -75,26 +75,25 @@ static void _assert_deserialize(rc_runtime_t* runtime, uint8_t* buffer) static void _assert_sized_memref(rc_runtime_t* runtime, uint32_t address, uint8_t size, uint32_t value, uint32_t prev, uint32_t prior) { - rc_memref_t* memref = runtime->memrefs; - while (memref) - { - if (memref->address == address && memref->value.size == size) - { - ASSERT_NUM_EQUALS(memref->value.value, value); - ASSERT_NUM_EQUALS(memref->value.prior, prior); - - if (value == prior) - { - ASSERT_NUM_EQUALS(memref->value.changed, 0); - } - else - { - ASSERT_NUM_EQUALS(memref->value.changed, (prev == prior) ? 1 : 0); + rc_memref_list_t* memref_list = &runtime->memrefs->memrefs; + for (; memref_list; memref_list = memref_list->next) { + const rc_memref_t* memref = memref_list->items; + const rc_memref_t* memref_end = memref + memref_list->count; + for (; memref < memref_end; ++memref) { + if (memref->address == address && memref->value.size == size) { + ASSERT_NUM_EQUALS(memref->value.value, value); + ASSERT_NUM_EQUALS(memref->value.prior, prior); + + if (value == prior) { + ASSERT_NUM_EQUALS(memref->value.changed, 0); + } + else { + ASSERT_NUM_EQUALS(memref->value.changed, (prev == prior) ? 1 : 0); + } + + return; } - return; } - - memref = memref->next; } ASSERT_FAIL("could not find memref for address %u", address); @@ -245,46 +244,42 @@ static void update_md5(uint8_t* buffer) static void reset_runtime(rc_runtime_t* runtime) { + rc_memref_list_t* memref_list; rc_memref_t* memref; rc_trigger_t* trigger; rc_condition_t* cond; rc_condset_t* condset; uint32_t i; - memref = runtime->memrefs; - while (memref) - { - memref->value.value = 0xFF; - memref->value.changed = 0; - memref->value.prior = 0xFF; - - memref = memref->next; + for (memref_list = &runtime->memrefs->memrefs; memref_list; memref_list = memref_list->next) { + const rc_memref_t* memref_end; + memref = memref_list->items; + memref_end = memref + memref_list->count; + for (; memref < memref_end; ++memref) { + memref->value.value = 0xFF; + memref->value.changed = 0; + memref->value.prior = 0xFF; + } } - for (i = 0; i < runtime->trigger_count; ++i) - { + for (i = 0; i < runtime->trigger_count; ++i) { trigger = runtime->triggers[i].trigger; - if (trigger) - { + if (trigger) { trigger->measured_value = 0xFF; trigger->measured_target = 0xFF; - if (trigger->requirement) - { + if (trigger->requirement) { cond = trigger->requirement->conditions; - while (cond) - { + while (cond) { cond->current_hits = 0xFF; cond = cond->next; } } condset = trigger->alternative; - while (condset) - { + while (condset) { cond = condset->conditions; - while (cond) - { + while (cond) { cond->current_hits = 0xFF; cond = cond->next; } @@ -307,7 +302,8 @@ static void test_empty() reset_runtime(&runtime); assert_deserialize(&runtime, buffer); - ASSERT_PTR_NULL(runtime.memrefs); + ASSERT_NUM_EQUALS(runtime.memrefs->memrefs.count, 0); + ASSERT_NUM_EQUALS(runtime.memrefs->modified_memrefs.count, 0); ASSERT_NUM_EQUALS(runtime.trigger_count, 0); ASSERT_NUM_EQUALS(runtime.lboard_count, 0); @@ -1293,11 +1289,10 @@ static void test_multiple_achievements_deactivated_memrefs() assert_hitcount(&runtime, 2, 0, 0, 2); assert_hitcount(&runtime, 3, 0, 0, 1); - /* deactivate an achievement with memrefs - trigger should be nulled */ + /* deactivate an achievement with memrefs */ ASSERT_NUM_EQUALS(runtime.trigger_count, 3); - ASSERT_TRUE(runtime.triggers[0].owns_memrefs); rc_runtime_deactivate_achievement(&runtime, 1); - ASSERT_NUM_EQUALS(runtime.trigger_count, 3); + ASSERT_NUM_EQUALS(runtime.trigger_count, 2); assert_serialize(&runtime, buffer, sizeof(buffer)); @@ -1348,7 +1343,6 @@ static void test_multiple_achievements_deactivated_no_memrefs() /* deactivate an achievement without memrefs - trigger should be removed */ ASSERT_NUM_EQUALS(runtime.trigger_count, 3); - ASSERT_FALSE(runtime.triggers[1].owns_memrefs); rc_runtime_deactivate_achievement(&runtime, 2); ASSERT_NUM_EQUALS(runtime.trigger_count, 2); diff --git a/test/rcheevos/test_trigger.c b/test/rcheevos/test_trigger.c index 286a5581..77b7f90c 100644 --- a/test/rcheevos/test_trigger.c +++ b/test/rcheevos/test_trigger.c @@ -10,7 +10,7 @@ static void _assert_parse_trigger(rc_trigger_t** trigger, void* buffer, size_t b size = rc_trigger_size(memaddr); ASSERT_NUM_GREATER(size, 0); - ASSERT_NUM_LESS_EQUALS(size, buffer_size); + ASSERT_NUM_LESS_EQUALS(size + 4, buffer_size); overflow = (unsigned*)(((char*)buffer) + size); *overflow = 0xCDCDCDCD; @@ -530,7 +530,7 @@ static void test_measured_addhits() { uint8_t ram[] = {0x00, 0x12, 0x34, 0xAB, 0x56}; memory_t memory; rc_trigger_t* trigger; - char buffer[256]; + char buffer[512]; memory.ram = ram; memory.size = sizeof(ram); @@ -1049,7 +1049,7 @@ static void test_measured_if() { uint8_t ram[] = {0x00, 0x12, 0x34, 0xAB, 0x56}; memory_t memory; rc_trigger_t* trigger; - char buffer[256]; + char buffer[512]; memory.ram = ram; memory.size = sizeof(ram); @@ -1089,7 +1089,7 @@ static void test_measured_if_comparison() { uint8_t ram[] = {0x00, 0x12, 0x34, 0xAB, 0x56}; memory_t memory; rc_trigger_t* trigger; - char buffer[256]; + char buffer[512]; memory.ram = ram; memory.size = sizeof(ram); @@ -1697,7 +1697,7 @@ static void test_evaluate_trigger_primed() { uint8_t ram[] = {0x00, 0x01, 0x00, 0x01, 0x00}; memory_t memory; rc_trigger_t* trigger; - char buffer[512]; + char buffer[640]; memory.ram = ram; memory.size = sizeof(ram); @@ -1823,7 +1823,7 @@ static void test_evaluate_trigger_chained_resetnextif() { uint8_t ram[] = {0x00, 0x00, 0x00, 0x00, 0x00}; memory_t memory; rc_trigger_t* trigger; - char buffer[512]; + char buffer[640]; memory.ram = ram; memory.size = sizeof(ram); @@ -1880,13 +1880,16 @@ static void test_evaluate_trigger_chained_resetnextif() { static void test_prev_prior_share_memref() { rc_trigger_t* trigger; + rc_memrefs_t* memrefs; char buffer[512]; assert_parse_trigger(&trigger, buffer, "0xH0001=d0xH0001_0xH0001!=p0xH0001"); - ASSERT_NUM_EQUALS(trigger->memrefs->address, 1U); - ASSERT_NUM_EQUALS(trigger->memrefs->value.size, RC_MEMSIZE_8_BITS); - ASSERT_PTR_NULL(trigger->memrefs->next); + memrefs = rc_trigger_get_memrefs(trigger); + ASSERT_PTR_NOT_NULL(memrefs); + ASSERT_NUM_EQUALS(memrefs->memrefs.count, 1); + ASSERT_NUM_EQUALS(memrefs->memrefs.items[0].address, 1U); + ASSERT_NUM_EQUALS(memrefs->memrefs.items[0].value.size, RC_MEMSIZE_8_BITS); ASSERT_NUM_EQUALS(trigger_get_cond(trigger, 0, 0)->operand1.type, RC_OPERAND_ADDRESS); ASSERT_NUM_EQUALS(trigger_get_cond(trigger, 0, 0)->operand2.type, RC_OPERAND_DELTA); @@ -1896,13 +1899,16 @@ static void test_prev_prior_share_memref() { static void test_bit_lookups_share_memref() { rc_trigger_t* trigger; + rc_memrefs_t* memrefs; char buffer[512]; assert_parse_trigger(&trigger, buffer, "0xM0001=1_0xN0x0001=0_0xO0x0001=1"); - ASSERT_NUM_EQUALS(trigger->memrefs->address, 1U); - ASSERT_NUM_EQUALS(trigger->memrefs->value.size, RC_MEMSIZE_8_BITS); - ASSERT_PTR_NULL(trigger->memrefs->next); + memrefs = rc_trigger_get_memrefs(trigger); + ASSERT_PTR_NOT_NULL(memrefs); + ASSERT_NUM_EQUALS(memrefs->memrefs.count, 1); + ASSERT_NUM_EQUALS(memrefs->memrefs.items[0].address, 1U); + ASSERT_NUM_EQUALS(memrefs->memrefs.items[0].value.size, RC_MEMSIZE_8_BITS); ASSERT_NUM_EQUALS(trigger_get_cond(trigger, 0, 0)->operand1.size, RC_MEMSIZE_BIT_0); ASSERT_NUM_EQUALS(trigger_get_cond(trigger, 0, 1)->operand1.size, RC_MEMSIZE_BIT_1); @@ -1911,13 +1917,16 @@ static void test_bit_lookups_share_memref() { static void test_bitcount_shares_memref() { rc_trigger_t* trigger; + rc_memrefs_t* memrefs; char buffer[512]; assert_parse_trigger(&trigger, buffer, "0xH0001>5_0xK0001!=3"); - ASSERT_NUM_EQUALS(trigger->memrefs->address, 1U); - ASSERT_NUM_EQUALS(trigger->memrefs->value.size, RC_MEMSIZE_8_BITS); - ASSERT_PTR_NULL(trigger->memrefs->next); + memrefs = rc_trigger_get_memrefs(trigger); + ASSERT_PTR_NOT_NULL(memrefs); + ASSERT_NUM_EQUALS(memrefs->memrefs.count, 1); + ASSERT_NUM_EQUALS(memrefs->memrefs.items[0].address, 1U); + ASSERT_NUM_EQUALS(memrefs->memrefs.items[0].value.size, RC_MEMSIZE_8_BITS); ASSERT_NUM_EQUALS(trigger_get_cond(trigger, 0, 0)->operand1.type, RC_OPERAND_ADDRESS); ASSERT_NUM_EQUALS(trigger_get_cond(trigger, 0, 0)->operand1.size, RC_MEMSIZE_8_BITS); @@ -1927,18 +1936,21 @@ static void test_bitcount_shares_memref() { static void test_large_memref_not_shared() { rc_trigger_t* trigger; + rc_memrefs_t* memrefs; char buffer[512]; assert_parse_trigger(&trigger, buffer, "0xH1234=1_0xX1234>d0xX1234"); + memrefs = rc_trigger_get_memrefs(trigger); + ASSERT_PTR_NOT_NULL(memrefs); + /* this could be shared, but isn't currently */ - ASSERT_NUM_EQUALS(trigger->memrefs->address, 0x1234); - ASSERT_NUM_EQUALS(trigger->memrefs->value.size, RC_MEMSIZE_8_BITS); - ASSERT_PTR_NOT_NULL(trigger->memrefs->next); + ASSERT_NUM_EQUALS(memrefs->memrefs.count, 2); + ASSERT_NUM_EQUALS(memrefs->memrefs.items[0].address, 0x1234U); + ASSERT_NUM_EQUALS(memrefs->memrefs.items[0].value.size, RC_MEMSIZE_8_BITS); - ASSERT_NUM_EQUALS(trigger->memrefs->next->address, 0x1234); - ASSERT_NUM_EQUALS(trigger->memrefs->next->value.size, RC_MEMSIZE_32_BITS); - ASSERT_PTR_NULL(trigger->memrefs->next->next); + ASSERT_NUM_EQUALS(memrefs->memrefs.items[1].address, 0x1234U); + ASSERT_NUM_EQUALS(memrefs->memrefs.items[1].value.size, RC_MEMSIZE_32_BITS); } static void test_remember_recall() { diff --git a/test/test.c b/test/test.c index 3142c9eb..13fc857a 100644 --- a/test/test.c +++ b/test/test.c @@ -129,7 +129,6 @@ int main(void) { #ifdef RC_CLIENT_SUPPORTS_RAINTEGRATION test_client_raintegration(); #endif - #ifdef RC_CLIENT_SUPPORTS_HASH /* no direct compile option for hash support, so leverage RC_CLIENT_SUPPORTS_HASH */ test_rc_libretro(); /* libretro extensions require hash support */ diff --git a/validator/validator.c b/validator/validator.c index 9e1b8bd6..b670fc97 100644 --- a/validator/validator.c +++ b/validator/validator.c @@ -392,7 +392,7 @@ static int validate_richpresence(const char* script, char result[], const size_t } if (success) - success = rc_validate_memrefs_for_console(compiled->memrefs, result, result_size, console_id); + success = rc_validate_memrefs_for_console(rc_richpresence_get_memrefs(compiled), result, result_size, console_id); if (success) success = validate_macros(compiled, script, result, result_size); if (success)