Support N64 cheevos

This commit is contained in:
Andre Leiradella 2017-07-07 23:12:38 +01:00
parent 26711ec0d5
commit 5e2e586f6e

View File

@ -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;
}