Skip to content

Commit

Permalink
split processing into pause/reset/hittarget/measured/other passes (#380)
Browse files Browse the repository at this point in the history
  • Loading branch information
Jamiras authored Nov 2, 2024
1 parent 61fd958 commit fc93954
Show file tree
Hide file tree
Showing 13 changed files with 610 additions and 298 deletions.
31 changes: 23 additions & 8 deletions include/rc_runtime_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ typedef struct rc_value_t rc_value_t;
* num_bytes is greater than 1, the value is read in little-endian from
* memory.
*/
typedef uint32_t(RC_CCONV *rc_peek_t)(uint32_t address, uint32_t num_bytes, void* ud);
typedef uint32_t(RC_CCONV* rc_peek_t)(uint32_t address, uint32_t num_bytes, void* ud);

/*****************************************************************************\
| Memory References |
Expand Down Expand Up @@ -210,9 +210,6 @@ struct rc_condition_t {
/* The comparison operator to use. (RC_OPERATOR_*) */
uint8_t oper; /* operator is a reserved word in C++. */

/* Set if the condition needs to processed as part of the "check if paused" pass. (bool) */
uint8_t pause;

/* Whether or not the condition evaluated true on the last check. (bool) */
uint8_t is_true;

Expand All @@ -233,9 +230,27 @@ struct rc_condset_t {
/* The first condition in this condition set. Then follow ->next chain. */
rc_condition_t* conditions;

/* True if any condition in the set is a pause condition. */
uint8_t has_pause;
/* The number of pause conditions in this condition set. */
/* The first pause condition is at "this + RC_ALIGN(sizeof(this)). */
uint16_t num_pause_conditions;

/* The number of reset conditions in this condition set. */
uint16_t num_reset_conditions;

/* The number of hittarget conditions in this condition set. */
uint16_t num_hittarget_conditions;

/* The number of non-hittarget measured conditions in this condition set. */
uint16_t num_measured_conditions;

/* The number of other conditions in this condition set. */
uint16_t num_other_conditions;

/* The number of indirect conditions in this condition set. */
uint16_t num_indirect_conditions;

/* True if any condition in the set is a pause condition. */
uint8_t has_pause; /* DEPRECATED - just check num_pause_conditions != 0 */
/* True if the set is currently paused. */
uint8_t is_paused;
};
Expand Down Expand Up @@ -300,7 +315,7 @@ struct rc_value_t {
/* The current value of the variable. */
rc_memref_value_t value;

/* The list of conditions to evaluate. */
/* The list of possible values (traverse next chain, pick max). */
rc_condset_t* conditions;

/* The memory references required by the variable. */
Expand Down Expand Up @@ -409,7 +424,7 @@ struct rc_richpresence_display_part_t {
rc_richpresence_display_part_t* next;
const char* text;
rc_richpresence_lookup_t* lookup;
rc_memref_value_t *value;
rc_memref_value_t* value;
uint8_t display_type;
};

Expand Down
4 changes: 2 additions & 2 deletions src/rcheevos/alloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,11 @@ void* rc_alloc(void* pointer, int32_t* offset, uint32_t size, uint32_t alignment

if (pointer != 0) {
/* valid buffer, grab the next chunk */
ptr = (void*)((char*)pointer + *offset);
ptr = (void*)((uint8_t*)pointer + *offset);
}
else if (scratch != 0 && scratch_object_pointer_offset < sizeof(scratch->objs)) {
/* only allocate one instance of each object type (indentified by scratch_object_pointer_offset) */
void** scratch_object_pointer = (void**)((char*)&scratch->objs + scratch_object_pointer_offset);
void** scratch_object_pointer = (void**)((uint8_t*)&scratch->objs + scratch_object_pointer_offset);
ptr = *scratch_object_pointer;
if (!ptr) {
int32_t used;
Expand Down
99 changes: 45 additions & 54 deletions src/rcheevos/condition.c
Original file line number Diff line number Diff line change
Expand Up @@ -184,16 +184,19 @@ void rc_condition_convert_to_operand(const rc_condition_t* condition, rc_operand
}

rc_condition_t* rc_parse_condition(const char** memaddr, rc_parse_state_t* parse) {
rc_condition_t* self;
rc_condition_t * self = RC_ALLOC(rc_condition_t, parse);
rc_parse_condition_internal(self, memaddr, parse);
return (parse->offset < 0) ? NULL : self;
}

void rc_parse_condition_internal(rc_condition_t* self, const char** memaddr, rc_parse_state_t* parse) {
const char* aux;
int result;
int can_modify = 0;

aux = *memaddr;
self = RC_ALLOC(rc_condition_t, parse);
self->current_hits = 0;
self->is_true = 0;
self->pause = 0;
self->optimized_comparator = RC_PROCESSING_COMPARE_DEFAULT;

if (*aux != 0 && aux[1] == ':') {
Expand All @@ -216,8 +219,11 @@ rc_condition_t* rc_parse_condition(const char** memaddr, rc_parse_state_t* parse
parse->measured_as_percent = 1;
self->type = RC_CONDITION_MEASURED;
break;

/* e f h j l s u v w x y */
default: parse->offset = RC_INVALID_CONDITION_TYPE; return 0;
default:
parse->offset = RC_INVALID_CONDITION_TYPE;
return;
}

aux += 2;
Expand All @@ -229,69 +235,55 @@ rc_condition_t* rc_parse_condition(const char** memaddr, rc_parse_state_t* parse
result = rc_parse_operand(&self->operand1, &aux, parse);
if (result < 0) {
parse->offset = result;
return 0;
return;
}

result = rc_parse_operator(&aux);
if (result < 0) {
parse->offset = result;
return 0;
return;
}

self->oper = (char)result;
switch (self->oper) {
case RC_OPERATOR_NONE:
/* non-modifying statements must have a second operand */
if (!can_modify) {
/* measured does not require a second operand when used in a value */
if (self->type != RC_CONDITION_MEASURED) {
parse->offset = RC_INVALID_OPERATOR;
return 0;
}
self->oper = (uint8_t)result;

if (self->oper == RC_OPERATOR_NONE) {
/* non-modifying statements must have a second operand */
if (!can_modify) {
/* measured does not require a second operand when used in a value */
if (self->type != RC_CONDITION_MEASURED) {
parse->offset = RC_INVALID_OPERATOR;
return;
}
}

/* provide dummy operand of '1' and no required hits */
rc_operand_set_const(&self->operand2, 1);
self->required_hits = 0;
*memaddr = aux;
return self;

case RC_OPERATOR_MULT:
case RC_OPERATOR_DIV:
case RC_OPERATOR_AND:
case RC_OPERATOR_XOR:
case RC_OPERATOR_MOD:
case RC_OPERATOR_ADD:
case RC_OPERATOR_SUB:
/* modifying operators are only valid on modifying statements */
if (can_modify)
break;
/* fallthrough */
/* provide dummy operand of '1' and no required hits */
rc_operand_set_const(&self->operand2, 1);
self->required_hits = 0;
*memaddr = aux;
return;
}

default:
/* comparison operators are not valid on modifying statements */
if (can_modify) {
switch (self->type) {
case RC_CONDITION_ADD_SOURCE:
case RC_CONDITION_SUB_SOURCE:
case RC_CONDITION_ADD_ADDRESS:
case RC_CONDITION_REMEMBER:
/* prevent parse errors on legacy achievements where a condition was present before changing the type */
self->oper = RC_OPERATOR_NONE;
break;
if (can_modify && !rc_operator_is_modifying(self->oper)) {
/* comparison operators are not valid on modifying statements */
switch (self->type) {
case RC_CONDITION_ADD_SOURCE:
case RC_CONDITION_SUB_SOURCE:
case RC_CONDITION_ADD_ADDRESS:
case RC_CONDITION_REMEMBER:
/* prevent parse errors on legacy achievements where a condition was present before changing the type */
self->oper = RC_OPERATOR_NONE;
break;

default:
parse->offset = RC_INVALID_OPERATOR;
return 0;
}
}
break;
default:
parse->offset = RC_INVALID_OPERATOR;
return;
}
}

result = rc_parse_operand(&self->operand2, &aux, parse);
if (result < 0) {
parse->offset = result;
return 0;
return;
}

if (self->oper == RC_OPERATOR_NONE) {
Expand All @@ -305,7 +297,7 @@ rc_condition_t* rc_parse_condition(const char** memaddr, rc_parse_state_t* parse

if (end == aux || *end != ')') {
parse->offset = RC_INVALID_REQUIRED_HITS;
return 0;
return;
}

/* if operator is none, explicitly clear out the required hits */
Expand All @@ -322,7 +314,7 @@ rc_condition_t* rc_parse_condition(const char** memaddr, rc_parse_state_t* parse

if (end == aux || *end != '.') {
parse->offset = RC_INVALID_REQUIRED_HITS;
return 0;
return;
}

/* if operator is none, explicitly clear out the required hits */
Expand All @@ -341,7 +333,6 @@ rc_condition_t* rc_parse_condition(const char** memaddr, rc_parse_state_t* parse
self->optimized_comparator = rc_condition_determine_comparator(self);

*memaddr = aux;
return self;
}

void rc_condition_update_parse_state(rc_condition_t* condition, rc_parse_state_t* parse) {
Expand Down
Loading

0 comments on commit fc93954

Please sign in to comment.