diff --git a/cheevos/cheevos.c b/cheevos/cheevos.c index d0e92a14cf..bcdccf6bd2 100644 --- a/cheevos/cheevos.c +++ b/cheevos/cheevos.c @@ -170,6 +170,9 @@ enum CHEEVOS_COND_TYPE_STANDARD = 0, CHEEVOS_COND_TYPE_PAUSE_IF, CHEEVOS_COND_TYPE_RESET_IF, + CHEEVOS_COND_TYPE_ADD_SOURCE, + CHEEVOS_COND_TYPE_SUB_SOURCE, + CHEEVOS_COND_TYPE_ADD_HITS, CHEEVOS_COND_TYPE_LAST }; /* cheevos_cond_t.type */ @@ -321,6 +324,8 @@ typedef struct { int console_id; bool core_supports; + int add_buffer; + int add_hits; cheevoset_t core; cheevoset_t unofficial; @@ -336,6 +341,8 @@ static cheevos_locals_t cheevos_locals = { /* console_id */ 0, /* core_supports */ true, + /* add_buffer */ 0, + /* add_hits */ 0, /* core */ {NULL, 0}, /* unofficial */ {NULL, 0}, /* leaderboards */ NULL, @@ -502,9 +509,12 @@ static void cheevos_log_cond(const cheevos_cond_t* cond) { RARCH_LOG("CHEEVOS condition %p\n", cond); RARCH_LOG("CHEEVOS type: %s\n", - cond->type == CHEEVOS_COND_TYPE_STANDARD ? "standard" : - cond->type == CHEEVOS_COND_TYPE_PAUSE_IF ? "pause" : - cond->type == CHEEVOS_COND_TYPE_RESET_IF ? "reset" : + cond->type == CHEEVOS_COND_TYPE_STANDARD ? "standard" : + cond->type == CHEEVOS_COND_TYPE_PAUSE_IF ? "pause" : + cond->type == CHEEVOS_COND_TYPE_RESET_IF ? "reset" : + cond->type == CHEEVOS_COND_TYPE_ADD_SOURCE ? "add source" : + cond->type == CHEEVOS_COND_TYPE_SUB_SOURCE ? "sub source" : + cond->type == CHEEVOS_COND_TYPE_ADD_HITS ? "add hits" : "?" ); RARCH_LOG("CHEEVOS req_hits: %u\n", cond->req_hits); @@ -628,6 +638,12 @@ static void cheevos_build_memaddr(const cheevos_condition_t* condition, cheevos_add_string(&aux, &left, "R:"); else if (cond->type == CHEEVOS_COND_TYPE_PAUSE_IF) cheevos_add_string(&aux, &left, "P:"); + else if (cond->type == CHEEVOS_COND_TYPE_ADD_SOURCE) + cheevos_add_string(&aux, &left, "A:"); + else if (cond->type == CHEEVOS_COND_TYPE_SUB_SOURCE) + cheevos_add_string(&aux, &left, "B:"); + else if (cond->type == CHEEVOS_COND_TYPE_ADD_HITS) + cheevos_add_string(&aux, &left, "C:"); cheevos_add_var(&cond->source, &aux, &left); @@ -1169,19 +1185,36 @@ static void cheevos_parse_var(cheevos_var_t *var, const char **memaddr) static void cheevos_parse_cond(cheevos_cond_t *cond, const char **memaddr) { const char* str = *memaddr; + cond->type = CHEEVOS_COND_TYPE_STANDARD; - if (*str == 'R' && str[1] == ':') + if (str[1] == ':') { - cond->type = CHEEVOS_COND_TYPE_RESET_IF; - str += 2; + int skip = 2; + + switch (*str) + { + case 'R': + cond->type = CHEEVOS_COND_TYPE_RESET_IF; + break; + case 'P': + cond->type = CHEEVOS_COND_TYPE_PAUSE_IF; + break; + case 'A': + cond->type = CHEEVOS_COND_TYPE_ADD_SOURCE; + break; + case 'B': + cond->type = CHEEVOS_COND_TYPE_SUB_SOURCE; + break; + case 'C': + cond->type = CHEEVOS_COND_TYPE_ADD_HITS; + break; + default: + skip = 0; + break; + } + + str += skip; } - else if (*str == 'P' && str[1] == ':') - { - cond->type = CHEEVOS_COND_TYPE_PAUSE_IF; - str += 2; - } - else - cond->type = CHEEVOS_COND_TYPE_STANDARD; cheevos_parse_var(&cond->source, &str); cond->op = cheevos_parse_operator(&str); @@ -1836,7 +1869,7 @@ static unsigned cheevos_get_var_value(cheevos_var_t *var) static int cheevos_test_condition(cheevos_cond_t *cond) { - unsigned sval = cheevos_get_var_value(&cond->source); + unsigned sval = cheevos_get_var_value(&cond->source) + cheevos_locals.add_buffer; unsigned tval = cheevos_get_var_value(&cond->target); switch (cond->op) @@ -1868,6 +1901,9 @@ static int cheevos_test_cond_set(const cheevos_condset_t *condset, const cheevos_cond_t *end = condset->conds + condset->count; cheevos_cond_t *cond = NULL; + cheevos_locals.add_buffer = 0; + cheevos_locals.add_hits = 0; + /* Now, read all Pause conditions, and if any are true, * do not process further (retain old state). */ @@ -1895,6 +1931,32 @@ static int cheevos_test_cond_set(const cheevos_condset_t *condset, { if (cond->type != CHEEVOS_COND_TYPE_STANDARD) continue; + + if (cond->type == CHEEVOS_COND_TYPE_ADD_SOURCE) + { + cheevos_locals.add_buffer += cheevos_get_var_value(&cond->source); + set_valid = 1; + continue; + } + + if (cond->type == CHEEVOS_COND_TYPE_SUB_SOURCE) + { + cheevos_locals.add_buffer -= cheevos_get_var_value(&cond->source); + set_valid = 1; + continue; + } + + if (cond->type == CHEEVOS_COND_TYPE_ADD_HITS) + { + if (cheevos_test_condition(cond)) + { + cond->curr_hits++; + *dirty_conds = 1; + } + + cheevos_locals.add_hits += cond->curr_hits; + continue; + } if (cond->req_hits != 0 && cond->curr_hits >= cond->req_hits) continue; @@ -1909,13 +1971,16 @@ static int cheevos_test_cond_set(const cheevos_condset_t *condset, /* Process this logic, if this condition is true: */ if (cond->req_hits == 0) ; /* Not a hit-based requirement: ignore any additional logic! */ - else if (cond->curr_hits < cond->req_hits) + else if ((cond->curr_hits + cheevos_locals.add_hits) < cond->req_hits) cond_valid = 0; /* Not entirely valid yet! */ if (match_any) break; } + cheevos_locals.add_buffer = 0; + cheevos_locals.add_hits = 0; + /* Sequential or non-sequential? */ set_valid &= cond_valid; }