mirror of
https://github.com/CTCaer/RetroArch.git
synced 2025-01-12 05:40:36 +00:00
Merge pull request #3912 from leiradel/master
Fixes to cheevos issues; added warning about the console IDs enumerat…
This commit is contained in:
commit
752d3a1804
500
cheevos.c
500
cheevos.c
@ -44,16 +44,19 @@
|
|||||||
#include "verbosity.h"
|
#include "verbosity.h"
|
||||||
|
|
||||||
/* Define this macro to prevent cheevos from being deactivated. */
|
/* Define this macro to prevent cheevos from being deactivated. */
|
||||||
#define CHEEVOS_DONT_DEACTIVATE
|
#undef CHEEVOS_DONT_DEACTIVATE
|
||||||
|
|
||||||
/* Define this macro to log URLs (will log the user token). */
|
/* Define this macro to log URLs (will log the user token). */
|
||||||
#define CHEEVOS_LOG_URLS
|
#undef CHEEVOS_LOG_URLS
|
||||||
|
|
||||||
/* Define this macro to dump all cheevos' addresses. */
|
/* Define this macro to dump all cheevos' addresses. */
|
||||||
#undef CHEEVOS_DUMP_ADDRS
|
#undef CHEEVOS_DUMP_ADDRS
|
||||||
|
|
||||||
/* Define this macro to remove HTTP timeouts. */
|
/* Define this macro to remove HTTP timeouts. */
|
||||||
#define CHEEVOS_NO_TIMEOUT
|
#undef CHEEVOS_NO_TIMEOUT
|
||||||
|
|
||||||
|
/* Define this macro to get extra-verbose log for cheevos. */
|
||||||
|
#undef CHEEVOS_VERBOSE
|
||||||
|
|
||||||
#define JSON_KEY_GAMEID 0xb4960eecU
|
#define JSON_KEY_GAMEID 0xb4960eecU
|
||||||
#define JSON_KEY_ACHIEVEMENTS 0x69749ae1U
|
#define JSON_KEY_ACHIEVEMENTS 0x69749ae1U
|
||||||
@ -72,17 +75,19 @@
|
|||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
|
/* Don't change those, the values match the console IDs
|
||||||
|
* at retroachievements.org. */
|
||||||
CHEEVOS_CONSOLE_MEGA_DRIVE = 1,
|
CHEEVOS_CONSOLE_MEGA_DRIVE = 1,
|
||||||
CHEEVOS_CONSOLE_NINTENDO_64,
|
CHEEVOS_CONSOLE_NINTENDO_64 = 2,
|
||||||
CHEEVOS_CONSOLE_SUPER_NINTENDO,
|
CHEEVOS_CONSOLE_SUPER_NINTENDO = 3,
|
||||||
CHEEVOS_CONSOLE_GAMEBOY,
|
CHEEVOS_CONSOLE_GAMEBOY = 4,
|
||||||
CHEEVOS_CONSOLE_GAMEBOY_ADVANCE,
|
CHEEVOS_CONSOLE_GAMEBOY_ADVANCE = 5,
|
||||||
CHEEVOS_CONSOLE_GAMEBOY_COLOR,
|
CHEEVOS_CONSOLE_GAMEBOY_COLOR = 6,
|
||||||
CHEEVOS_CONSOLE_NINTENDO,
|
CHEEVOS_CONSOLE_NINTENDO = 7,
|
||||||
CHEEVOS_CONSOLE_PC_ENGINE,
|
CHEEVOS_CONSOLE_PC_ENGINE = 8,
|
||||||
CHEEVOS_CONSOLE_SEGA_CD,
|
CHEEVOS_CONSOLE_SEGA_CD = 9,
|
||||||
CHEEVOS_CONSOLE_SEGA_32X,
|
CHEEVOS_CONSOLE_SEGA_32X = 10,
|
||||||
CHEEVOS_CONSOLE_MASTER_SYSTEM
|
CHEEVOS_CONSOLE_MASTER_SYSTEM = 11
|
||||||
};
|
};
|
||||||
|
|
||||||
enum
|
enum
|
||||||
@ -187,6 +192,7 @@ typedef struct
|
|||||||
unsigned points;
|
unsigned points;
|
||||||
unsigned dirty;
|
unsigned dirty;
|
||||||
int active;
|
int active;
|
||||||
|
int last;
|
||||||
int modified;
|
int modified;
|
||||||
|
|
||||||
cheevos_condset_t *condsets;
|
cheevos_condset_t *condsets;
|
||||||
@ -276,6 +282,267 @@ static int cheats_were_enabled = 0;
|
|||||||
Supporting functions.
|
Supporting functions.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#ifdef CHEEVOS_VERBOSE
|
||||||
|
static void cheevos_add_char(char** aux, size_t* left, char k)
|
||||||
|
{
|
||||||
|
if (*left >= 1)
|
||||||
|
{
|
||||||
|
**aux = k;
|
||||||
|
(*aux)++;
|
||||||
|
(*left)--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cheevos_add_string(char** aux, size_t* left, const char* s)
|
||||||
|
{
|
||||||
|
size_t len = strlen(s);
|
||||||
|
|
||||||
|
if (*left >= len)
|
||||||
|
{
|
||||||
|
strcpy(*aux, s);
|
||||||
|
*aux += len;
|
||||||
|
*left -= len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cheevos_add_hex(char** aux, size_t* left, unsigned v)
|
||||||
|
{
|
||||||
|
char buffer[32];
|
||||||
|
|
||||||
|
snprintf(buffer, sizeof(buffer), "%06x", v);
|
||||||
|
buffer[sizeof(buffer) - 1] = 0;
|
||||||
|
|
||||||
|
cheevos_add_string(aux, left, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cheevos_add_uint(char** aux, size_t* left, unsigned v)
|
||||||
|
{
|
||||||
|
char buffer[32];
|
||||||
|
|
||||||
|
snprintf(buffer, sizeof(buffer), "%u", v);
|
||||||
|
buffer[sizeof(buffer) - 1] = 0;
|
||||||
|
|
||||||
|
cheevos_add_string(aux, left, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cheevos_log_var(const cheevos_var_t* var)
|
||||||
|
{
|
||||||
|
RARCH_LOG("CHEEVOS size: %s\n",
|
||||||
|
var->size == CHEEVOS_VAR_SIZE_BIT_0 ? "bit 0" :
|
||||||
|
var->size == CHEEVOS_VAR_SIZE_BIT_1 ? "bit 1" :
|
||||||
|
var->size == CHEEVOS_VAR_SIZE_BIT_2 ? "bit 2" :
|
||||||
|
var->size == CHEEVOS_VAR_SIZE_BIT_3 ? "bit 3" :
|
||||||
|
var->size == CHEEVOS_VAR_SIZE_BIT_4 ? "bit 4" :
|
||||||
|
var->size == CHEEVOS_VAR_SIZE_BIT_5 ? "bit 5" :
|
||||||
|
var->size == CHEEVOS_VAR_SIZE_BIT_6 ? "bit 6" :
|
||||||
|
var->size == CHEEVOS_VAR_SIZE_BIT_7 ? "bit 7" :
|
||||||
|
var->size == CHEEVOS_VAR_SIZE_NIBBLE_LOWER ? "low nibble" :
|
||||||
|
var->size == CHEEVOS_VAR_SIZE_NIBBLE_UPPER ? "high nibble" :
|
||||||
|
var->size == CHEEVOS_VAR_SIZE_EIGHT_BITS ? "byte" :
|
||||||
|
var->size == CHEEVOS_VAR_SIZE_SIXTEEN_BITS ? "word" :
|
||||||
|
var->size == CHEEVOS_VAR_SIZE_THIRTYTWO_BITS ? "dword" :
|
||||||
|
"?"
|
||||||
|
);
|
||||||
|
RARCH_LOG("CHEEVOS type: %s\n",
|
||||||
|
var->type == CHEEVOS_VAR_TYPE_ADDRESS ? "address" :
|
||||||
|
var->type == CHEEVOS_VAR_TYPE_VALUE_COMP ? "value" :
|
||||||
|
var->type == CHEEVOS_VAR_TYPE_DELTA_MEM ? "delta" :
|
||||||
|
var->type == CHEEVOS_VAR_TYPE_DYNAMIC_VAR ? "dynamic" :
|
||||||
|
"?"
|
||||||
|
);
|
||||||
|
RARCH_LOG("CHEEVOS value: %u\n", var->value);
|
||||||
|
}
|
||||||
|
|
||||||
|
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" :
|
||||||
|
"?"
|
||||||
|
);
|
||||||
|
RARCH_LOG("CHEEVOS req_hits: %u\n", cond->req_hits);
|
||||||
|
RARCH_LOG("CHEEVOS source:\n");
|
||||||
|
cheevos_log_var(&cond->source);
|
||||||
|
RARCH_LOG("CHEEVOS op: %s\n",
|
||||||
|
cond->op == CHEEVOS_COND_OP_EQUALS ? "==" :
|
||||||
|
cond->op == CHEEVOS_COND_OP_LESS_THAN ? "<" :
|
||||||
|
cond->op == CHEEVOS_COND_OP_LESS_THAN_OR_EQUAL ? "<=" :
|
||||||
|
cond->op == CHEEVOS_COND_OP_GREATER_THAN ? ">" :
|
||||||
|
cond->op == CHEEVOS_COND_OP_GREATER_THAN_OR_EQUAL ? ">=" :
|
||||||
|
cond->op == CHEEVOS_COND_OP_NOT_EQUAL_TO ? "!=" :
|
||||||
|
"?"
|
||||||
|
);
|
||||||
|
RARCH_LOG("CHEEVOS target:\n");
|
||||||
|
cheevos_log_var(&cond->target);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cheevos_log_cheevo(const cheevo_t* cheevo,
|
||||||
|
const cheevos_field_t* memaddr_ud)
|
||||||
|
{
|
||||||
|
char memaddr[256];
|
||||||
|
size_t length;
|
||||||
|
|
||||||
|
length = memaddr_ud->length + 1;
|
||||||
|
|
||||||
|
if (length >= sizeof(memaddr))
|
||||||
|
length = sizeof(memaddr);
|
||||||
|
|
||||||
|
strncpy(memaddr, memaddr_ud->string, length - 1);
|
||||||
|
memaddr[length - 1] = 0;
|
||||||
|
|
||||||
|
RARCH_LOG("CHEEVOS cheevo %p\n", cheevo);
|
||||||
|
RARCH_LOG("CHEEVOS id: %u\n", cheevo->id);
|
||||||
|
RARCH_LOG("CHEEVOS title: %s\n", cheevo->title);
|
||||||
|
RARCH_LOG("CHEEVOS desc: %s\n", cheevo->description);
|
||||||
|
RARCH_LOG("CHEEVOS author: %s\n", cheevo->author);
|
||||||
|
RARCH_LOG("CHEEVOS badge: %s\n", cheevo->badge);
|
||||||
|
RARCH_LOG("CHEEVOS points: %u\n", cheevo->points);
|
||||||
|
RARCH_LOG("CHEEVOS sets: %u\n", cheevo->count);
|
||||||
|
RARCH_LOG("CHEEVOS memaddr: %s\n", memaddr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cheevos_add_var_size(char** aux, size_t* left,
|
||||||
|
const cheevos_var_t* var)
|
||||||
|
{
|
||||||
|
switch( var->size )
|
||||||
|
{
|
||||||
|
case CHEEVOS_VAR_SIZE_BIT_0:
|
||||||
|
cheevos_add_char(aux, left, 'M');
|
||||||
|
break;
|
||||||
|
case CHEEVOS_VAR_SIZE_BIT_1:
|
||||||
|
cheevos_add_char(aux, left, 'N');
|
||||||
|
break;
|
||||||
|
case CHEEVOS_VAR_SIZE_BIT_2:
|
||||||
|
cheevos_add_char(aux, left, 'O');
|
||||||
|
break;
|
||||||
|
case CHEEVOS_VAR_SIZE_BIT_3:
|
||||||
|
cheevos_add_char(aux, left, 'P');
|
||||||
|
break;
|
||||||
|
case CHEEVOS_VAR_SIZE_BIT_4:
|
||||||
|
cheevos_add_char(aux, left, 'Q');
|
||||||
|
break;
|
||||||
|
case CHEEVOS_VAR_SIZE_BIT_5:
|
||||||
|
cheevos_add_char(aux, left, 'R');
|
||||||
|
break;
|
||||||
|
case CHEEVOS_VAR_SIZE_BIT_6:
|
||||||
|
cheevos_add_char(aux, left, 'S');
|
||||||
|
break;
|
||||||
|
case CHEEVOS_VAR_SIZE_BIT_7:
|
||||||
|
cheevos_add_char(aux, left, 'T');
|
||||||
|
break;
|
||||||
|
case CHEEVOS_VAR_SIZE_NIBBLE_LOWER:
|
||||||
|
cheevos_add_char(aux, left, 'L');
|
||||||
|
break;
|
||||||
|
case CHEEVOS_VAR_SIZE_NIBBLE_UPPER:
|
||||||
|
cheevos_add_char(aux, left, 'U');
|
||||||
|
break;
|
||||||
|
case CHEEVOS_VAR_SIZE_EIGHT_BITS:
|
||||||
|
cheevos_add_char(aux, left, 'H');
|
||||||
|
break;
|
||||||
|
case CHEEVOS_VAR_SIZE_THIRTYTWO_BITS:
|
||||||
|
cheevos_add_char(aux, left, 'X');
|
||||||
|
break;
|
||||||
|
case CHEEVOS_VAR_SIZE_SIXTEEN_BITS:
|
||||||
|
default:
|
||||||
|
cheevos_add_char(aux, left, ' ');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cheevos_post_log_cheevo(const cheevo_t* cheevo)
|
||||||
|
{
|
||||||
|
char memaddr[256];
|
||||||
|
char *aux = memaddr;
|
||||||
|
size_t left = sizeof(memaddr);
|
||||||
|
const cheevos_condset_t* condset;
|
||||||
|
const cheevos_cond_t* cond;
|
||||||
|
size_t i, j;
|
||||||
|
|
||||||
|
for (i = 0, condset = cheevo->condsets; i < cheevo->count; i++, condset++)
|
||||||
|
{
|
||||||
|
if (i != 0)
|
||||||
|
cheevos_add_char(&aux, &left, 'S');
|
||||||
|
|
||||||
|
for (j = 0, cond = condset->conds; j < condset->count; j++, cond++)
|
||||||
|
{
|
||||||
|
if (j != 0)
|
||||||
|
cheevos_add_char(&aux, &left, '_');
|
||||||
|
|
||||||
|
if (cond->type == CHEEVOS_COND_TYPE_RESET_IF)
|
||||||
|
cheevos_add_string(&aux, &left, "R:");
|
||||||
|
else if (cond->type == CHEEVOS_COND_TYPE_PAUSE_IF)
|
||||||
|
cheevos_add_string(&aux, &left, "P:");
|
||||||
|
|
||||||
|
if ( cond->source.type == CHEEVOS_VAR_TYPE_ADDRESS
|
||||||
|
|| cond->source.type == CHEEVOS_VAR_TYPE_DELTA_MEM)
|
||||||
|
{
|
||||||
|
if (cond->source.type == CHEEVOS_VAR_TYPE_DELTA_MEM)
|
||||||
|
cheevos_add_char(&aux, &left, 'd');
|
||||||
|
|
||||||
|
cheevos_add_string(&aux, &left, "0x");
|
||||||
|
cheevos_add_var_size(&aux, &left, &cond->source);
|
||||||
|
cheevos_add_hex(&aux, &left, cond->source.value);
|
||||||
|
}
|
||||||
|
else if (cond->source.type == CHEEVOS_VAR_TYPE_VALUE_COMP)
|
||||||
|
{
|
||||||
|
cheevos_add_uint(&aux, &left, cond->source.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (cond->op)
|
||||||
|
{
|
||||||
|
case CHEEVOS_COND_OP_EQUALS:
|
||||||
|
cheevos_add_char(&aux, &left, '=');
|
||||||
|
break;
|
||||||
|
case CHEEVOS_COND_OP_GREATER_THAN:
|
||||||
|
cheevos_add_char(&aux, &left, '>');
|
||||||
|
break;
|
||||||
|
case CHEEVOS_COND_OP_GREATER_THAN_OR_EQUAL:
|
||||||
|
cheevos_add_string(&aux, &left, ">=");
|
||||||
|
break;
|
||||||
|
case CHEEVOS_COND_OP_LESS_THAN:
|
||||||
|
cheevos_add_char(&aux, &left, '<');
|
||||||
|
break;
|
||||||
|
case CHEEVOS_COND_OP_LESS_THAN_OR_EQUAL:
|
||||||
|
cheevos_add_string(&aux, &left, "<=");
|
||||||
|
break;
|
||||||
|
case CHEEVOS_COND_OP_NOT_EQUAL_TO:
|
||||||
|
cheevos_add_string(&aux, &left, "!=");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( cond->target.type == CHEEVOS_VAR_TYPE_ADDRESS
|
||||||
|
|| cond->target.type == CHEEVOS_VAR_TYPE_DELTA_MEM)
|
||||||
|
{
|
||||||
|
if (cond->target.type == CHEEVOS_VAR_TYPE_DELTA_MEM)
|
||||||
|
cheevos_add_char(&aux, &left, 'd');
|
||||||
|
|
||||||
|
cheevos_add_string(&aux, &left, "0x");
|
||||||
|
cheevos_add_var_size(&aux, &left, &cond->target);
|
||||||
|
cheevos_add_hex(&aux, &left, cond->target.value);
|
||||||
|
}
|
||||||
|
else if (cond->target.type == CHEEVOS_VAR_TYPE_VALUE_COMP)
|
||||||
|
{
|
||||||
|
cheevos_add_uint(&aux, &left, cond->target.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cond->req_hits > 0)
|
||||||
|
{
|
||||||
|
cheevos_add_char(&aux, &left, '.');
|
||||||
|
cheevos_add_uint(&aux, &left, cond->req_hits);
|
||||||
|
cheevos_add_char(&aux, &left, '.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cheevos_add_char(&aux, &left, 0);
|
||||||
|
memaddr[sizeof(memaddr) - 1] = 0;
|
||||||
|
|
||||||
|
RARCH_LOG("CHEEVOS memaddr (computed): %s\n", memaddr);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static uint32_t cheevos_djb2(const char* str, size_t length)
|
static uint32_t cheevos_djb2(const char* str, size_t length)
|
||||||
{
|
{
|
||||||
const unsigned char *aux = (const unsigned char*)str;
|
const unsigned char *aux = (const unsigned char*)str;
|
||||||
@ -748,26 +1015,25 @@ static unsigned cheevos_count_cond_sets(const char *memaddr)
|
|||||||
cheevos_cond_t cond;
|
cheevos_cond_t cond;
|
||||||
unsigned count = 0;
|
unsigned count = 0;
|
||||||
|
|
||||||
do
|
for (;;)
|
||||||
{
|
{
|
||||||
do
|
|
||||||
{
|
|
||||||
/* Skip any characters up until the start of the achievement condition */
|
|
||||||
while ( *memaddr == ' '
|
|
||||||
|| *memaddr == '_'
|
|
||||||
|| *memaddr == '|'
|
|
||||||
|| *memaddr == 'S')
|
|
||||||
memaddr++;
|
|
||||||
|
|
||||||
cheevos_parse_cond(&cond, &memaddr);
|
|
||||||
}
|
|
||||||
while ( *memaddr == '_'
|
|
||||||
|| *memaddr == 'R'
|
|
||||||
|| *memaddr == 'P'); /* AND, ResetIf, PauseIf */
|
|
||||||
|
|
||||||
count++;
|
count++;
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
cheevos_parse_cond(&cond, &memaddr);
|
||||||
|
|
||||||
|
if (*memaddr != '_')
|
||||||
|
break;
|
||||||
|
|
||||||
|
memaddr++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*memaddr != 'S')
|
||||||
|
break;
|
||||||
|
|
||||||
|
memaddr++;
|
||||||
}
|
}
|
||||||
while (*memaddr == 'S'); /* Repeat for all subconditions if they exist */
|
|
||||||
|
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
@ -778,47 +1044,68 @@ static unsigned cheevos_count_conds_in_set(const char *memaddr, unsigned set)
|
|||||||
unsigned index = 0;
|
unsigned index = 0;
|
||||||
unsigned count = 0;
|
unsigned count = 0;
|
||||||
|
|
||||||
do
|
for (;;)
|
||||||
{
|
{
|
||||||
do
|
for (;;)
|
||||||
{
|
{
|
||||||
/* Skip any characters up until the start of the achievement condition */
|
|
||||||
while ( *memaddr == ' '
|
|
||||||
|| *memaddr == '_'
|
|
||||||
|| *memaddr == '|'
|
|
||||||
|| *memaddr == 'S')
|
|
||||||
memaddr++;
|
|
||||||
|
|
||||||
cheevos_parse_cond(&cond, &memaddr);
|
cheevos_parse_cond(&cond, &memaddr);
|
||||||
|
|
||||||
if (index == set)
|
if (index == set)
|
||||||
count++;
|
count++;
|
||||||
|
|
||||||
|
if (*memaddr != '_')
|
||||||
|
break;
|
||||||
|
|
||||||
|
memaddr++;
|
||||||
}
|
}
|
||||||
while (*memaddr == '_' || *memaddr == 'R' || *memaddr == 'P'); /* AND, ResetIf, PauseIf */
|
|
||||||
|
index++;
|
||||||
|
|
||||||
|
if (*memaddr != 'S')
|
||||||
|
break;
|
||||||
|
|
||||||
|
memaddr++;
|
||||||
}
|
}
|
||||||
while (*memaddr == 'S'); /* Repeat for all subconditions if they exist */
|
|
||||||
|
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cheevos_parse_memaddr(cheevos_cond_t *cond, const char *memaddr)
|
static void cheevos_parse_memaddr(cheevos_cond_t *cond, const char *memaddr, unsigned set)
|
||||||
{
|
{
|
||||||
do
|
cheevos_cond_t dummy;
|
||||||
{
|
unsigned index = 0;
|
||||||
do
|
|
||||||
{
|
|
||||||
/* Skip any characters up until the start of the achievement condition */
|
|
||||||
while ( *memaddr == ' '
|
|
||||||
|| *memaddr == '_'
|
|
||||||
|| *memaddr == '|'
|
|
||||||
|| *memaddr == 'S')
|
|
||||||
memaddr++;
|
|
||||||
|
|
||||||
cheevos_parse_cond(cond++, &memaddr);
|
for (;;)
|
||||||
|
{
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
if (index == set)
|
||||||
|
{
|
||||||
|
cheevos_parse_cond(cond, &memaddr);
|
||||||
|
#ifdef CHEEVOS_VERBOSE
|
||||||
|
cheevos_log_cond(cond);
|
||||||
|
#endif
|
||||||
|
cond++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
cheevos_parse_cond(&dummy, &memaddr);
|
||||||
|
|
||||||
|
if (*memaddr != '_')
|
||||||
|
break;
|
||||||
|
|
||||||
|
memaddr++;
|
||||||
}
|
}
|
||||||
while (*memaddr == '_' || *memaddr == 'R' || *memaddr == 'P'); /* AND, ResetIf, PauseIf */
|
|
||||||
|
index++;
|
||||||
|
|
||||||
|
if (*memaddr != 'S')
|
||||||
|
break;
|
||||||
|
|
||||||
|
memaddr++;
|
||||||
}
|
}
|
||||||
while (*memaddr == 'S'); /* Repeat for all subconditions if they exist */
|
|
||||||
|
if (*memaddr != '"')
|
||||||
|
RARCH_LOG("CHEEVOS error parsing memaddr\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
@ -840,7 +1127,7 @@ static INLINE const char *cheevos_dupstr(const cheevos_field_t *field)
|
|||||||
|
|
||||||
static int cheevos_new_cheevo(cheevos_readud_t *ud)
|
static int cheevos_new_cheevo(cheevos_readud_t *ud)
|
||||||
{
|
{
|
||||||
cheevo_t *cheevo = NULL;
|
cheevo_t *cheevo = NULL;
|
||||||
|
|
||||||
if (strtol(ud->flags.string, NULL, 10) == 3)
|
if (strtol(ud->flags.string, NULL, 10) == 3)
|
||||||
cheevo = cheevos_locals.core.cheevos + ud->core_count++;
|
cheevo = cheevos_locals.core.cheevos + ud->core_count++;
|
||||||
@ -855,6 +1142,7 @@ static int cheevos_new_cheevo(cheevos_readud_t *ud)
|
|||||||
cheevo->points = strtol(ud->points.string, NULL, 10);
|
cheevo->points = strtol(ud->points.string, NULL, 10);
|
||||||
cheevo->dirty = 0;
|
cheevo->dirty = 0;
|
||||||
cheevo->active = 1;
|
cheevo->active = 1;
|
||||||
|
cheevo->last = 1;
|
||||||
cheevo->modified = 0;
|
cheevo->modified = 0;
|
||||||
|
|
||||||
if (!cheevo->title || !cheevo->description || !cheevo->author || !cheevo->badge)
|
if (!cheevo->title || !cheevo->description || !cheevo->author || !cheevo->badge)
|
||||||
@ -862,13 +1150,18 @@ static int cheevos_new_cheevo(cheevos_readud_t *ud)
|
|||||||
|
|
||||||
cheevo->count = cheevos_count_cond_sets(ud->memaddr.string);
|
cheevo->count = cheevos_count_cond_sets(ud->memaddr.string);
|
||||||
|
|
||||||
|
#ifdef CHEEVOS_VERBOSE
|
||||||
|
cheevos_log_cheevo(cheevo, &ud->memaddr);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (cheevo->count)
|
if (cheevo->count)
|
||||||
{
|
{
|
||||||
unsigned set = 0;
|
unsigned set = 0;
|
||||||
const cheevos_condset_t *end = NULL;
|
//const cheevos_condset_t *end = NULL;
|
||||||
cheevos_condset_t *condset = NULL;
|
cheevos_condset_t *condset = NULL;
|
||||||
cheevos_condset_t *conds = (cheevos_condset_t*)
|
cheevos_condset_t *conds = (cheevos_condset_t*)
|
||||||
calloc(cheevo->count, sizeof(cheevos_condset_t));
|
calloc(cheevo->count, sizeof(cheevos_condset_t));
|
||||||
|
const cheevos_condset_t* end;
|
||||||
|
|
||||||
if (!conds)
|
if (!conds)
|
||||||
return -1;
|
return -1;
|
||||||
@ -876,12 +1169,17 @@ static int cheevos_new_cheevo(cheevos_readud_t *ud)
|
|||||||
cheevo->condsets = conds;
|
cheevo->condsets = conds;
|
||||||
end = cheevo->condsets + cheevo->count;
|
end = cheevo->condsets + cheevo->count;
|
||||||
|
|
||||||
for (condset = cheevo->condsets; condset < end; condset++)
|
for (condset = cheevo->condsets; condset < end; condset++, set++)
|
||||||
{
|
{
|
||||||
condset->count =
|
condset->count =
|
||||||
cheevos_count_conds_in_set(ud->memaddr.string, set++);
|
cheevos_count_conds_in_set(ud->memaddr.string, set);
|
||||||
condset->conds = NULL;
|
condset->conds = NULL;
|
||||||
|
|
||||||
|
#ifdef CHEEVOS_VERBOSE
|
||||||
|
RARCH_LOG("CHEEVOS set %p (index=%u)\n", condset, set);
|
||||||
|
RARCH_LOG("CHEEVOS conds: %u\n", condset->count);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (condset->count)
|
if (condset->count)
|
||||||
{
|
{
|
||||||
cheevos_cond_t *conds = (cheevos_cond_t*)
|
cheevos_cond_t *conds = (cheevos_cond_t*)
|
||||||
@ -892,11 +1190,15 @@ static int cheevos_new_cheevo(cheevos_readud_t *ud)
|
|||||||
|
|
||||||
condset->conds = conds;
|
condset->conds = conds;
|
||||||
condset->expression = cheevos_dupstr(&ud->memaddr);
|
condset->expression = cheevos_dupstr(&ud->memaddr);
|
||||||
cheevos_parse_memaddr(condset->conds, ud->memaddr.string);
|
cheevos_parse_memaddr(condset->conds, ud->memaddr.string, set);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CHEEVOS_VERBOSE
|
||||||
|
cheevos_post_log_cheevo(cheevo);
|
||||||
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
@ -1193,7 +1495,7 @@ static int cheevos_test_condition(cheevos_cond_t *cond)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cheevos_test_cond_set(const cheevos_condset_t *condset,
|
static int cheevos_test_cond_set(const cheevos_condset_t *condset,
|
||||||
@ -1209,28 +1511,27 @@ static int cheevos_test_cond_set(const cheevos_condset_t *condset,
|
|||||||
|
|
||||||
for (cond = condset->conds; cond < end; cond++)
|
for (cond = condset->conds; cond < end; cond++)
|
||||||
{
|
{
|
||||||
if (cond->type == CHEEVOS_COND_TYPE_PAUSE_IF)
|
if (cond->type != CHEEVOS_COND_TYPE_PAUSE_IF)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Reset by default, set to 1 if hit! */
|
||||||
|
cond->curr_hits = 0;
|
||||||
|
|
||||||
|
if (cheevos_test_condition(cond))
|
||||||
{
|
{
|
||||||
/* Reset by default, set to 1 if hit! */
|
cond->curr_hits = 1;
|
||||||
cond->curr_hits = 0;
|
*dirty_conds = 1;
|
||||||
|
|
||||||
if (cheevos_test_condition(cond))
|
/* Early out: this achievement is paused,
|
||||||
{
|
* do not process any further! */
|
||||||
cond->curr_hits = 1;
|
return 0;
|
||||||
*dirty_conds = 1;
|
|
||||||
|
|
||||||
/* Early out: this achievement is paused,
|
|
||||||
* do not process any further! */
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read all standard conditions, and process as normal: */
|
/* Read all standard conditions, and process as normal: */
|
||||||
for (cond = condset->conds; cond < end; cond++)
|
for (cond = condset->conds; cond < end; cond++)
|
||||||
{
|
{
|
||||||
if ( cond->type == CHEEVOS_COND_TYPE_PAUSE_IF
|
if (cond->type != CHEEVOS_COND_TYPE_STANDARD)
|
||||||
|| cond->type == CHEEVOS_COND_TYPE_RESET_IF)
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (cond->req_hits != 0 && cond->curr_hits >= cond->req_hits)
|
if (cond->req_hits != 0 && cond->curr_hits >= cond->req_hits)
|
||||||
@ -1260,16 +1561,16 @@ static int cheevos_test_cond_set(const cheevos_condset_t *condset,
|
|||||||
/* Now, ONLY read reset conditions! */
|
/* Now, ONLY read reset conditions! */
|
||||||
for (cond = condset->conds; cond < end; cond++)
|
for (cond = condset->conds; cond < end; cond++)
|
||||||
{
|
{
|
||||||
if (cond->type == CHEEVOS_COND_TYPE_RESET_IF)
|
if (cond->type != CHEEVOS_COND_TYPE_RESET_IF)
|
||||||
{
|
continue;
|
||||||
cond_valid = cheevos_test_condition(cond);
|
|
||||||
|
|
||||||
if (cond_valid)
|
cond_valid = cheevos_test_condition(cond);
|
||||||
{
|
|
||||||
*reset_conds = 1; /* Resets all hits found so far */
|
if (cond_valid)
|
||||||
set_valid = 0; /* Cannot be valid if we've hit a reset condition. */
|
{
|
||||||
break; /* No point processing any further reset conditions. */
|
*reset_conds = 1; /* Resets all hits found so far */
|
||||||
}
|
set_valid = 0; /* Cannot be valid if we've hit a reset condition. */
|
||||||
|
break; /* No point processing any further reset conditions. */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1323,8 +1624,7 @@ static int cheevos_test_cheevo(cheevo_t *cheevo)
|
|||||||
|
|
||||||
while (condset < end)
|
while (condset < end)
|
||||||
{
|
{
|
||||||
int res = cheevos_test_cond_set(condset, &dirty_conds, &reset_conds, 0);
|
ret_val_sub_cond |= cheevos_test_cond_set(condset, &dirty_conds, &reset_conds, 0);
|
||||||
ret_val_sub_cond |= res;
|
|
||||||
condset++;
|
condset++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1484,25 +1784,33 @@ static void cheevos_test_cheevo_set(const cheevoset_t *set)
|
|||||||
{
|
{
|
||||||
cheevo_t *cheevo = NULL;
|
cheevo_t *cheevo = NULL;
|
||||||
const cheevo_t *end = set->cheevos + set->count;
|
const cheevo_t *end = set->cheevos + set->count;
|
||||||
|
int valid;
|
||||||
|
|
||||||
for (cheevo = set->cheevos; cheevo < end; cheevo++)
|
for (cheevo = set->cheevos; cheevo < end; cheevo++)
|
||||||
{
|
{
|
||||||
if (cheevo->active && cheevos_test_cheevo(cheevo))
|
if (cheevo->active)
|
||||||
{
|
{
|
||||||
char url[256];
|
valid = cheevos_test_cheevo(cheevo);
|
||||||
|
|
||||||
url[0] = '\0';
|
if (valid && !cheevo->last)
|
||||||
|
{
|
||||||
|
char url[256];
|
||||||
|
|
||||||
cheevo->active = 0;
|
url[0] = '\0';
|
||||||
|
|
||||||
RARCH_LOG("CHEEVOS awarding cheevo %u: %s (%s).\n",
|
cheevo->active = 0;
|
||||||
cheevo->id, cheevo->title, cheevo->description);
|
|
||||||
|
|
||||||
runloop_msg_queue_push(cheevo->title, 0, 3 * 60, false);
|
RARCH_LOG("CHEEVOS awarding cheevo %u: %s (%s).\n",
|
||||||
runloop_msg_queue_push(cheevo->description, 0, 5 * 60, false);
|
cheevo->id, cheevo->title, cheevo->description);
|
||||||
|
|
||||||
cheevos_make_unlock_url(cheevo, url, sizeof(url));
|
runloop_msg_queue_push(cheevo->title, 0, 3 * 60, false);
|
||||||
task_push_http_transfer(url, true, NULL, cheevos_unlocked, cheevo);
|
runloop_msg_queue_push(cheevo->description, 0, 5 * 60, false);
|
||||||
|
|
||||||
|
cheevos_make_unlock_url(cheevo, url, sizeof(url));
|
||||||
|
task_push_http_transfer(url, true, NULL, cheevos_unlocked, cheevo);
|
||||||
|
}
|
||||||
|
|
||||||
|
cheevo->last = valid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user