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)