Update cheevos - style nits

This commit is contained in:
twinaphex 2015-10-15 16:04:26 +02:00
parent bbcd49b6df
commit 0a3db8f7bb
2 changed files with 908 additions and 969 deletions

322
cheevos.c
View File

@ -76,7 +76,6 @@ enum
CHEEVOS_COND_TYPE_STANDARD, CHEEVOS_COND_TYPE_STANDARD,
CHEEVOS_COND_TYPE_PAUSE_IF, CHEEVOS_COND_TYPE_PAUSE_IF,
CHEEVOS_COND_TYPE_RESET_IF, CHEEVOS_COND_TYPE_RESET_IF,
CHEEVOS_COND_TYPE_LAST CHEEVOS_COND_TYPE_LAST
}; /* cheevos_cond_t.type */ }; /* cheevos_cond_t.type */
@ -102,8 +101,7 @@ typedef struct
unsigned bank_id; unsigned bank_id;
unsigned value; unsigned value;
unsigned previous; unsigned previous;
} } cheevos_var_t;
cheevos_var_t;
typedef struct typedef struct
{ {
@ -114,25 +112,23 @@ typedef struct
cheevos_var_t source; cheevos_var_t source;
unsigned op; unsigned op;
cheevos_var_t target; cheevos_var_t target;
} } cheevos_cond_t;
cheevos_cond_t;
typedef struct typedef struct
{ {
cheevos_cond_t* conds; cheevos_cond_t *conds;
unsigned count; unsigned count;
const char* expression; const char *expression;
} } cheevos_condset_t;
cheevos_condset_t;
typedef struct typedef struct
{ {
unsigned id; unsigned id;
const char* title; const char *title;
const char* description; const char *description;
const char* author; const char *author;
const char* badge; const char *badge;
unsigned points; unsigned points;
unsigned dirty; unsigned dirty;
int active; int active;
@ -140,15 +136,13 @@ typedef struct
cheevos_condset_t* condsets; cheevos_condset_t* condsets;
unsigned count; unsigned count;
} } cheevo_t;
cheevo_t;
typedef struct typedef struct
{ {
cheevo_t* cheevos; cheevo_t* cheevos;
unsigned count; unsigned count;
} } cheevoset_t;
cheevoset_t;
cheevos_config_t cheevos_config = cheevos_config_t cheevos_config =
{ {
@ -166,8 +160,8 @@ static cheevoset_t core_cheevos = { NULL, 0 };
static cheevoset_t unofficial_cheevos = { NULL, 0 }; static cheevoset_t unofficial_cheevos = { NULL, 0 };
/***************************************************************************** /*****************************************************************************
Supporting functions. Supporting functions.
*****************************************************************************/ *****************************************************************************/
static uint32_t cheevos_djb2( const char* str, size_t length ) static uint32_t cheevos_djb2( const char* str, size_t length )
{ {
@ -176,16 +170,14 @@ static uint32_t cheevos_djb2( const char* str, size_t length )
uint32_t hash = 5381; uint32_t hash = 5381;
while ( aux < end ) while ( aux < end )
{
hash = ( hash << 5 ) + hash + *aux++; hash = ( hash << 5 ) + hash + *aux++;
}
return hash; return hash;
} }
/***************************************************************************** /*****************************************************************************
Count number of achievements in a JSON file. Count number of achievements in a JSON file.
*****************************************************************************/ *****************************************************************************/
typedef struct typedef struct
{ {
@ -193,8 +185,7 @@ typedef struct
uint32_t field_hash; uint32_t field_hash;
unsigned core_count; unsigned core_count;
unsigned unofficial_count; unsigned unofficial_count;
} } cheevos_countud_t;
cheevos_countud_t;
static int count__json_end_array( void* userdata ) static int count__json_end_array( void* userdata )
{ {
@ -209,9 +200,7 @@ static int count__json_key( void* userdata, const char* name, size_t length )
ud->field_hash = cheevos_djb2( name, length ); ud->field_hash = cheevos_djb2( name, length );
if ( ud->field_hash == 0x69749ae1U /* Achievements */ ) if ( ud->field_hash == 0x69749ae1U /* Achievements */ )
{
ud->in_cheevos = 1; ud->in_cheevos = 1;
}
return 0; return 0;
} }
@ -225,20 +214,18 @@ static int count__json_number( void* userdata, const char* number, size_t length
long flags = strtol( number, NULL, 10 ); long flags = strtol( number, NULL, 10 );
if ( flags == 3 ) /* core achievements */ if ( flags == 3 ) /* core achievements */
{
ud->core_count++; ud->core_count++;
}
else if ( flags == 5 ) /* unofficial achievements */ else if ( flags == 5 ) /* unofficial achievements */
{
ud->unofficial_count++; ud->unofficial_count++;
} }
}
return 0; return 0;
} }
static int count_cheevos( const char* json, unsigned* core_count, unsigned* unofficial_count ) static int count_cheevos( const char* json, unsigned* core_count, unsigned* unofficial_count )
{ {
int res;
cheevos_countud_t ud;
static const jsonsax_handlers_t handlers = static const jsonsax_handlers_t handlers =
{ {
NULL, NULL,
@ -255,8 +242,6 @@ static int count_cheevos( const char* json, unsigned* core_count, unsigned* unof
NULL NULL
}; };
int res;
cheevos_countud_t ud;
ud.in_cheevos = 0; ud.in_cheevos = 0;
ud.core_count = 0; ud.core_count = 0;
ud.unofficial_count = 0; ud.unofficial_count = 0;
@ -270,8 +255,8 @@ static int count_cheevos( const char* json, unsigned* core_count, unsigned* unof
} }
/***************************************************************************** /*****************************************************************************
Parse the MemAddr field. Parse the MemAddr field.
*****************************************************************************/ *****************************************************************************/
static unsigned prefix_to_comp_size( char prefix ) static unsigned prefix_to_comp_size( char prefix )
{ {
@ -279,21 +264,36 @@ static unsigned prefix_to_comp_size( char prefix )
switch( toupper( prefix ) ) switch( toupper( prefix ) )
{ {
case 'M': return CHEEVOS_VAR_SIZE_BIT_0; case 'M':
case 'N': return CHEEVOS_VAR_SIZE_BIT_1; return CHEEVOS_VAR_SIZE_BIT_0;
case 'O': return CHEEVOS_VAR_SIZE_BIT_2; case 'N':
case 'P': return CHEEVOS_VAR_SIZE_BIT_3; return CHEEVOS_VAR_SIZE_BIT_1;
case 'Q': return CHEEVOS_VAR_SIZE_BIT_4; case 'O':
case 'R': return CHEEVOS_VAR_SIZE_BIT_5; return CHEEVOS_VAR_SIZE_BIT_2;
case 'S': return CHEEVOS_VAR_SIZE_BIT_6; case 'P':
case 'T': return CHEEVOS_VAR_SIZE_BIT_7; return CHEEVOS_VAR_SIZE_BIT_3;
case 'L': return CHEEVOS_VAR_SIZE_NIBBLE_LOWER; case 'Q':
case 'U': return CHEEVOS_VAR_SIZE_NIBBLE_UPPER; return CHEEVOS_VAR_SIZE_BIT_4;
case 'H': return CHEEVOS_VAR_SIZE_EIGHT_BITS; case 'R':
case 'X': return CHEEVOS_VAR_SIZE_THIRTYTWO_BITS; return CHEEVOS_VAR_SIZE_BIT_5;
case 'S':
return CHEEVOS_VAR_SIZE_BIT_6;
case 'T':
return CHEEVOS_VAR_SIZE_BIT_7;
case 'L':
return CHEEVOS_VAR_SIZE_NIBBLE_LOWER;
case 'U':
return CHEEVOS_VAR_SIZE_NIBBLE_UPPER;
case 'H':
return CHEEVOS_VAR_SIZE_EIGHT_BITS;
case 'X':
return CHEEVOS_VAR_SIZE_THIRTYTWO_BITS;
default: default:
case ' ': return CHEEVOS_VAR_SIZE_SIXTEEN_BITS; case ' ':
break;
} }
return CHEEVOS_VAR_SIZE_SIXTEEN_BITS;
} }
static unsigned read_hits( const char** memaddr ) static unsigned read_hits( const char** memaddr )
@ -352,11 +352,8 @@ static unsigned parse_operator( const char** memaddr )
op = CHEEVOS_COND_OP_GREATER_THAN; op = CHEEVOS_COND_OP_GREATER_THAN;
str++; str++;
} }
else else /* TODO log the exception */
{
/* TODO log the exception */
op = CHEEVOS_COND_OP_EQUALS; op = CHEEVOS_COND_OP_EQUALS;
}
*memaddr = str; *memaddr = str;
return op; return op;
@ -364,8 +361,8 @@ static unsigned parse_operator( const char** memaddr )
static void parse_var( cheevos_var_t* var, const char** memaddr ) static void parse_var( cheevos_var_t* var, const char** memaddr )
{ {
const char* str = *memaddr;
char* end; char* end;
const char* str = *memaddr;
unsigned base = 16; unsigned base = 16;
if ( toupper( *str ) == 'D' && str[ 1 ] == '0' && toupper( str[ 2 ] ) == 'X' ) if ( toupper( *str ) == 'D' && str[ 1 ] == '0' && toupper( str[ 2 ] ) == 'X' )
@ -385,24 +382,18 @@ static void parse_var( cheevos_var_t* var, const char** memaddr )
var->type = CHEEVOS_VAR_TYPE_VALUE_COMP; var->type = CHEEVOS_VAR_TYPE_VALUE_COMP;
if ( toupper( *str ) == 'H' ) if ( toupper( *str ) == 'H' )
{
str++; str++;
}
else else
{
base = 10; base = 10;
} }
}
if ( var->type != CHEEVOS_VAR_TYPE_VALUE_COMP ) if ( var->type != CHEEVOS_VAR_TYPE_VALUE_COMP )
{ {
var->size = prefix_to_comp_size( *str ); var->size = prefix_to_comp_size( *str );
if ( var->size != CHEEVOS_VAR_SIZE_SIXTEEN_BITS ) if ( var->size != CHEEVOS_VAR_SIZE_SIXTEEN_BITS )
{
str++; str++;
} }
}
var->value = strtol( str, &end, base ); var->value = strtol( str, &end, base );
*memaddr = end; *memaddr = end;
@ -423,9 +414,7 @@ static void parse_cond( cheevos_cond_t* cond, const char** memaddr )
str += 2; str += 2;
} }
else else
{
cond->type = CHEEVOS_COND_TYPE_STANDARD; cond->type = CHEEVOS_COND_TYPE_STANDARD;
}
parse_var( &cond->source, &str ); parse_var( &cond->source, &str );
cond->op = parse_operator( &str ); cond->op = parse_operator( &str );
@ -438,54 +427,44 @@ static void parse_cond( cheevos_cond_t* cond, const char** memaddr )
static unsigned count_cond_sets( const char* memaddr ) static unsigned count_cond_sets( const char* memaddr )
{ {
unsigned count = 0;
cheevos_cond_t cond; cheevos_cond_t cond;
unsigned count = 0;
do do
{ {
do do
{ {
while( *memaddr == ' ' || *memaddr == '_' || *memaddr == '|' || *memaddr == 'S' ) while( *memaddr == ' ' || *memaddr == '_' || *memaddr == '|' || *memaddr == 'S' )
{
memaddr++; /* Skip any chars up til the start of the achievement condition */ memaddr++; /* Skip any chars up til the start of the achievement condition */
}
parse_cond( &cond, &memaddr ); parse_cond( &cond, &memaddr );
} }while( *memaddr == '_' || *memaddr == 'R' || *memaddr == 'P' ); /* AND, ResetIf, PauseIf */
while( *memaddr == '_' || *memaddr == 'R' || *memaddr == 'P' ); /* AND, ResetIf, PauseIf */
count++; count++;
} }while( *memaddr == 'S' ); /* Repeat for all subconditions if they exist */
while( *memaddr == 'S' ); /* Repeat for all subconditions if they exist */
return count; return count;
} }
static unsigned count_conds_in_set( const char* memaddr, unsigned set ) static unsigned count_conds_in_set( const char* memaddr, unsigned set )
{ {
cheevos_cond_t cond;
unsigned index = 0; unsigned index = 0;
unsigned count = 0; unsigned count = 0;
cheevos_cond_t cond;
do do
{ {
do do
{ {
while ( *memaddr == ' ' || *memaddr == '_' || *memaddr == '|' || *memaddr == 'S' ) while ( *memaddr == ' ' || *memaddr == '_' || *memaddr == '|' || *memaddr == 'S' )
{
memaddr++; /* Skip any chars up til the start of the achievement condition */ memaddr++; /* Skip any chars up til the start of the achievement condition */
}
parse_cond( &cond, &memaddr ); parse_cond( &cond, &memaddr );
if ( index == set ) if ( index == set )
{
count++; count++;
} }while ( *memaddr == '_' || *memaddr == 'R' || *memaddr == 'P' ); /* AND, ResetIf, PauseIf */
} }while( *memaddr == 'S' ); /* Repeat for all subconditions if they exist */
while ( *memaddr == '_' || *memaddr == 'R' || *memaddr == 'P' ); /* AND, ResetIf, PauseIf */
}
while( *memaddr == 'S' ); /* Repeat for all subconditions if they exist */
return count; return count;
} }
@ -497,27 +476,22 @@ static void parse_memaddr( cheevos_cond_t* cond, const char* memaddr )
do do
{ {
while( *memaddr == ' ' || *memaddr == '_' || *memaddr == '|' || *memaddr == 'S' ) while( *memaddr == ' ' || *memaddr == '_' || *memaddr == '|' || *memaddr == 'S' )
{
memaddr++; /* Skip any chars up til the start of the achievement condition */ memaddr++; /* Skip any chars up til the start of the achievement condition */
}
parse_cond( cond++, &memaddr ); parse_cond( cond++, &memaddr );
} }while( *memaddr == '_' || *memaddr == 'R' || *memaddr == 'P' ); /* AND, ResetIf, PauseIf */
while( *memaddr == '_' || *memaddr == 'R' || *memaddr == 'P' ); /* AND, ResetIf, PauseIf */ }while( *memaddr == 'S' ); /* Repeat for all subconditions if they exist */
}
while( *memaddr == 'S' ); /* Repeat for all subconditions if they exist */
} }
/***************************************************************************** /*****************************************************************************
Load achievements from a JSON string. Load achievements from a JSON string.
*****************************************************************************/ *****************************************************************************/
typedef struct typedef struct
{ {
const char* string; const char* string;
size_t length; size_t length;
} } cheevos_field_t;
cheevos_field_t;
typedef struct typedef struct
{ {
@ -528,8 +502,7 @@ typedef struct
cheevos_field_t* field; cheevos_field_t* field;
cheevos_field_t id, memaddr, title, desc, points, author; cheevos_field_t id, memaddr, title, desc, points, author;
cheevos_field_t modified, created, badge, flags; cheevos_field_t modified, created, badge, flags;
} } cheevos_readud_t;
cheevos_readud_t;
static inline const char* dupstr( const cheevos_field_t* field ) static inline const char* dupstr( const cheevos_field_t* field )
{ {
@ -553,13 +526,9 @@ static int new_cheevo( cheevos_readud_t* ud )
int flags = strtol( ud->flags.string, NULL, 10 ); int flags = strtol( ud->flags.string, NULL, 10 );
if ( flags == 3 ) if ( flags == 3 )
{
cheevo = core_cheevos.cheevos + ud->core_count++; cheevo = core_cheevos.cheevos + ud->core_count++;
}
else else
{
cheevo = unofficial_cheevos.cheevos + ud->unofficial_count++; cheevo = unofficial_cheevos.cheevos + ud->unofficial_count++;
}
cheevo->id = strtol( ud->id.string, NULL, 10 ); cheevo->id = strtol( ud->id.string, NULL, 10 );
cheevo->title = dupstr( &ud->title ); cheevo->title = dupstr( &ud->title );
@ -587,9 +556,7 @@ static int new_cheevo( cheevos_readud_t* ud )
cheevo->condsets = (cheevos_condset_t*)malloc( cheevo->count * sizeof( cheevos_condset_t ) ); cheevo->condsets = (cheevos_condset_t*)malloc( cheevo->count * sizeof( cheevos_condset_t ) );
if ( !cheevo->condsets ) if ( !cheevo->condsets )
{
return -1; return -1;
}
memset( (void*)cheevo->condsets, 0, cheevo->count * sizeof( cheevos_condset_t ) ); memset( (void*)cheevo->condsets, 0, cheevo->count * sizeof( cheevos_condset_t ) );
end = cheevo->condsets + cheevo->count; end = cheevo->condsets + cheevo->count;
@ -598,24 +565,19 @@ static int new_cheevo( cheevos_readud_t* ud )
for ( condset = cheevo->condsets; condset < end; condset++ ) for ( condset = cheevo->condsets; condset < end; condset++ )
{ {
condset->count = count_conds_in_set( ud->memaddr.string, set++ ); condset->count = count_conds_in_set( ud->memaddr.string, set++ );
condset->conds = NULL;
if ( condset->count ) if ( condset->count )
{ {
condset->conds = (cheevos_cond_t*)malloc( condset->count * sizeof( cheevos_cond_t ) ); condset->conds = (cheevos_cond_t*)malloc( condset->count * sizeof( cheevos_cond_t ) );
if ( !condset->conds ) if ( !condset->conds )
{
return -1; return -1;
}
memset( (void*)condset->conds, 0, condset->count * sizeof( cheevos_cond_t ) ); memset( (void*)condset->conds, 0, condset->count * sizeof( cheevos_cond_t ) );
condset->expression = dupstr( &ud->memaddr ); condset->expression = dupstr( &ud->memaddr );
parse_memaddr( condset->conds, ud->memaddr.string ); parse_memaddr( condset->conds, ud->memaddr.string );
} }
else
{
condset->conds = NULL;
}
} }
} }
@ -630,23 +592,41 @@ static int read__json_key( void* userdata, const char* name, size_t length )
ud->field = NULL; ud->field = NULL;
if ( hash == 0x69749ae1U /* Achievements */ ) if ( hash == 0x69749ae1U /* Achievements */ )
{
ud->in_cheevos = 1; ud->in_cheevos = 1;
}
else if ( ud->in_cheevos ) else if ( ud->in_cheevos )
{ {
switch ( hash ) switch ( hash )
{ {
case 0x005973f2U: /* ID */ ud->field = &ud->id; break; case 0x005973f2U: /* ID */
case 0x1e76b53fU: /* MemAddr */ ud->field = &ud->memaddr; break; ud->field = &ud->id;
case 0x0e2a9a07U: /* Title */ ud->field = &ud->title; break; break;
case 0xe61a1f69U: /* Description */ ud->field = &ud->desc; break; case 0x1e76b53fU: /* MemAddr */
case 0xca8fce22U: /* Points */ ud->field = &ud->points; break; ud->field = &ud->memaddr;
case 0xa804edb8U: /* Author */ ud->field = &ud->author; break; break;
case 0xdcea4fe6U: /* Modified */ ud->field = &ud->modified; break; case 0x0e2a9a07U: /* Title */
case 0x3a84721dU: /* Created */ ud->field = &ud->created; break; ud->field = &ud->title;
case 0x887685d9U: /* BadgeName */ ud->field = &ud->badge; break; break;
case 0x0d2e96b2U: /* Flags */ ud->field = &ud->flags; break; case 0xe61a1f69U: /* Description */
ud->field = &ud->desc;
break;
case 0xca8fce22U: /* Points */
ud->field = &ud->points;
break;
case 0xa804edb8U: /* Author */
ud->field = &ud->author;
break;
case 0xdcea4fe6U: /* Modified */
ud->field = &ud->modified;
break;
case 0x3a84721dU: /* Created */
ud->field = &ud->created;
break;
case 0x887685d9U: /* BadgeName */
ud->field = &ud->badge;
break;
case 0x0d2e96b2U: /* Flags */
ud->field = &ud->flags;
break;
} }
} }
@ -684,9 +664,7 @@ static int read__json_end_object( void* userdata )
cheevos_readud_t* ud = (cheevos_readud_t*)userdata; cheevos_readud_t* ud = (cheevos_readud_t*)userdata;
if ( ud->in_cheevos ) if ( ud->in_cheevos )
{
return new_cheevo( ud ); return new_cheevo( ud );
}
return 0; return 0;
} }
@ -721,9 +699,7 @@ int cheevos_load( const char* json )
unsigned core_count, unofficial_count; unsigned core_count, unofficial_count;
if ( count_cheevos( json, &core_count, &unofficial_count ) != JSONSAX_OK ) if ( count_cheevos( json, &core_count, &unofficial_count ) != JSONSAX_OK )
{
return -1; return -1;
}
/* Allocate the achievements. */ /* Allocate the achievements. */
@ -754,28 +730,24 @@ int cheevos_load( const char* json )
ud.unofficial_count = 0; ud.unofficial_count = 0;
if ( jsonsax_parse( json, &handlers, (void*)&ud ) == JSONSAX_OK ) if ( jsonsax_parse( json, &handlers, (void*)&ud ) == JSONSAX_OK )
{
return 0; return 0;
}
cheevos_unload(); cheevos_unload();
return -1; return -1;
} }
/***************************************************************************** /*****************************************************************************
Test all the achievements (call once per frame). Test all the achievements (call once per frame).
*****************************************************************************/ *****************************************************************************/
static unsigned get_var_value( cheevos_var_t* var ) static unsigned get_var_value( cheevos_var_t* var )
{ {
uint8_t* memory;
unsigned previous = var->previous; unsigned previous = var->previous;
unsigned live_val = 0; unsigned live_val = 0;
uint8_t* memory;
if ( var->type == CHEEVOS_VAR_TYPE_VALUE_COMP ) if ( var->type == CHEEVOS_VAR_TYPE_VALUE_COMP )
{
return var->value; return var->value;
}
if ( var->type == CHEEVOS_VAR_TYPE_ADDRESS || var->type == CHEEVOS_VAR_TYPE_DELTA_MEM ) if ( var->type == CHEEVOS_VAR_TYPE_ADDRESS || var->type == CHEEVOS_VAR_TYPE_DELTA_MEM )
{ {
@ -785,25 +757,14 @@ static unsigned get_var_value( cheevos_var_t* var )
live_val = memory[ var->value ]; live_val = memory[ var->value ];
if ( var->size >= CHEEVOS_VAR_SIZE_BIT_0 && var->size <= CHEEVOS_VAR_SIZE_BIT_7 ) if ( var->size >= CHEEVOS_VAR_SIZE_BIT_0 && var->size <= CHEEVOS_VAR_SIZE_BIT_7 )
{
live_val = ( live_val & ( 1 << ( var->size - CHEEVOS_VAR_SIZE_BIT_0 ) ) ) != 0; live_val = ( live_val & ( 1 << ( var->size - CHEEVOS_VAR_SIZE_BIT_0 ) ) ) != 0;
}
else if ( var->size == CHEEVOS_VAR_SIZE_NIBBLE_LOWER ) else if ( var->size == CHEEVOS_VAR_SIZE_NIBBLE_LOWER )
{
live_val &= 0x0f; live_val &= 0x0f;
}
else if ( var->size == CHEEVOS_VAR_SIZE_NIBBLE_UPPER ) else if ( var->size == CHEEVOS_VAR_SIZE_NIBBLE_UPPER )
{
live_val = ( live_val >> 4 ) & 0x0f; live_val = ( live_val >> 4 ) & 0x0f;
} else if ( var->size == CHEEVOS_VAR_SIZE_EIGHT_BITS ) { }
else if ( var->size == CHEEVOS_VAR_SIZE_EIGHT_BITS )
{
/* nothing */
}
else if ( var->size == CHEEVOS_VAR_SIZE_SIXTEEN_BITS ) else if ( var->size == CHEEVOS_VAR_SIZE_SIXTEEN_BITS )
{
live_val |= memory[ var->value + 1 ] << 8; live_val |= memory[ var->value + 1 ] << 8;
}
else if ( var->size == CHEEVOS_VAR_SIZE_THIRTYTWO_BITS ) else if ( var->size == CHEEVOS_VAR_SIZE_THIRTYTWO_BITS )
{ {
live_val |= memory[ var->value + 1 ] << 8; live_val |= memory[ var->value + 1 ] << 8;
@ -850,17 +811,19 @@ static int test_condition( cheevos_cond_t* cond )
return sval != tval; return sval != tval;
default: default:
return 1; break;
} }
return 1;
} }
static int test_cond_set( const cheevos_condset_t* condset, int* dirty_conds, int* reset_conds, int match_any ) static int test_cond_set( const cheevos_condset_t* condset, int* dirty_conds, int* reset_conds, int match_any )
{ {
cheevos_cond_t* cond;
int cond_valid = 0; int cond_valid = 0;
int set_valid = 1; int set_valid = 1;
int pause_active = 0; int pause_active = 0;
const cheevos_cond_t* end = condset->conds + condset->count; const cheevos_cond_t* end = condset->conds + condset->count;
cheevos_cond_t* cond;
/* Now, read all Pause conditions, and if any are true, do not process further (retain old state) */ /* Now, read all Pause conditions, and if any are true, do not process further (retain old state) */
for ( cond = condset->conds; cond < end; cond++ ) for ( cond = condset->conds; cond < end; cond++ )
@ -885,14 +848,10 @@ static int test_cond_set( const cheevos_condset_t* condset, int* dirty_conds, in
for ( cond = condset->conds; cond < end; cond++ ) for ( cond = condset->conds; cond < end; cond++ )
{ {
if ( cond->type == CHEEVOS_COND_TYPE_PAUSE_IF || cond->type == CHEEVOS_COND_TYPE_RESET_IF ) if ( cond->type == CHEEVOS_COND_TYPE_PAUSE_IF || 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 )
{
continue; continue;
}
cond_valid = test_condition( cond ); cond_valid = test_condition( cond );
@ -913,10 +872,8 @@ static int test_cond_set( const cheevos_condset_t* condset, int* dirty_conds, in
} }
if ( match_any ) if ( match_any )
{
break; break;
} }
}
/* Sequential or non-sequential? */ /* Sequential or non-sequential? */
set_valid &= cond_valid; set_valid &= cond_valid;
@ -943,9 +900,9 @@ static int test_cond_set( const cheevos_condset_t* condset, int* dirty_conds, in
static int reset_cond_set( cheevos_condset_t* condset, int deltas ) static int reset_cond_set( cheevos_condset_t* condset, int deltas )
{ {
cheevos_cond_t* cond;
int dirty = 0; int dirty = 0;
const cheevos_cond_t* end = condset->conds + condset->count; const cheevos_cond_t* end = condset->conds + condset->count;
cheevos_cond_t* cond;
if ( deltas ) if ( deltas )
{ {
@ -972,10 +929,10 @@ static int reset_cond_set( cheevos_condset_t* condset, int deltas )
static int test_cheevo( cheevo_t* cheevo ) static int test_cheevo( cheevo_t* cheevo )
{ {
int dirty;
int dirty_conds = 0; int dirty_conds = 0;
int reset_conds = 0; int reset_conds = 0;
int ret_val = 0; int ret_val = 0;
int dirty;
int ret_val_sub_cond = cheevo->count == 1; int ret_val_sub_cond = cheevo->count == 1;
cheevos_condset_t* condset = cheevo->condsets; cheevos_condset_t* condset = cheevo->condsets;
const cheevos_condset_t* end = condset + cheevo->count; const cheevos_condset_t* end = condset + cheevo->count;
@ -996,32 +953,26 @@ static int test_cheevo( cheevo_t* cheevo )
} }
if ( dirty_conds ) if ( dirty_conds )
{
cheevo->dirty |= CHEEVOS_DIRTY_CONDITIONS; cheevo->dirty |= CHEEVOS_DIRTY_CONDITIONS;
}
if ( reset_conds ) if ( reset_conds )
{ {
dirty = 0; dirty = 0;
for ( condset = cheevo->condsets; condset < end; condset++ ) for ( condset = cheevo->condsets; condset < end; condset++ )
{
dirty |= reset_cond_set( condset, 0 ); dirty |= reset_cond_set( condset, 0 );
}
if ( dirty ) if ( dirty )
{
cheevo->dirty |= CHEEVOS_DIRTY_CONDITIONS; cheevo->dirty |= CHEEVOS_DIRTY_CONDITIONS;
} }
}
return ret_val && ret_val_sub_cond; return ret_val && ret_val_sub_cond;
} }
static void test_cheevo_set( const cheevoset_t* set ) static void test_cheevo_set( const cheevoset_t* set )
{ {
const cheevo_t* end = set->cheevos + set->count;
cheevo_t* cheevo; cheevo_t* cheevo;
const cheevo_t* end = set->cheevos + set->count;
for ( cheevo = set->cheevos; cheevo < end; cheevo++ ) for ( cheevo = set->cheevos; cheevo < end; cheevo++ )
{ {
@ -1038,22 +989,20 @@ static void test_cheevo_set( const cheevoset_t* set )
} }
} }
void cheevos_test( void ) void cheevos_test(void)
{ {
if ( cheevos_config.enable ) if ( cheevos_config.enable )
{ {
test_cheevo_set( &core_cheevos ); test_cheevo_set( &core_cheevos );
if ( cheevos_config.test_unofficial ) if ( cheevos_config.test_unofficial )
{
test_cheevo_set( &unofficial_cheevos ); test_cheevo_set( &unofficial_cheevos );
} }
}
} }
/***************************************************************************** /*****************************************************************************
Free the loaded achievements. Free the loaded achievements.
*****************************************************************************/ *****************************************************************************/
static void free_condset( const cheevos_condset_t* set ) static void free_condset( const cheevos_condset_t* set )
{ {
@ -1076,45 +1025,36 @@ static void free_cheevo_set( const cheevoset_t* set )
const cheevo_t* end = cheevo + set->count; const cheevo_t* end = cheevo + set->count;
while ( cheevo < end ) while ( cheevo < end )
{
free_cheevo( cheevo++ ); free_cheevo( cheevo++ );
}
free( (void*)set->cheevos ); free( (void*)set->cheevos );
} }
void cheevos_unload( void ) void cheevos_unload(void)
{ {
free_cheevo_set( &core_cheevos ); free_cheevo_set( &core_cheevos );
free_cheevo_set( &unofficial_cheevos ); free_cheevo_set( &unofficial_cheevos );
} }
/***************************************************************************** /*****************************************************************************
Load achievements from retroachievements.org. Load achievements from retroachievements.org.
*****************************************************************************/ *****************************************************************************/
static const char* cheevos_http_get( const char* url, size_t* size ) static const char* cheevos_http_get( const char* url, size_t* size )
{ {
#ifdef HAVE_NETWORKING #ifdef HAVE_NETWORKING
struct http_connection_t* conn;
struct http_t* http; struct http_t* http;
uint8_t* data; uint8_t* data;
size_t length; size_t length;
char* result; char *result;
struct http_connection_t *conn = net_http_connection_new( url );
RARCH_LOG( "CHEEVOS http get %s\n", url ); RARCH_LOG( "CHEEVOS http get %s\n", url );
conn = net_http_connection_new( url );
if ( !conn ) if ( !conn )
{
return NULL; return NULL;
}
while ( !net_http_connection_iterate( conn ) ) while ( !net_http_connection_iterate( conn ) ) { }
{
/* nothing */
}
if ( !net_http_connection_done( conn ) ) if ( !net_http_connection_done( conn ) )
{ {
@ -1126,16 +1066,12 @@ error1:
http = net_http_new( conn ); http = net_http_new( conn );
if ( !http ) if ( !http )
{
goto error1; goto error1;
}
while ( !net_http_update( http, NULL, NULL ) ) while ( !net_http_update( http, NULL, NULL ) ) { }
{
/* nothing */
}
data = net_http_data( http, &length, false ); data = net_http_data( http, &length, false );
result = NULL;
if ( data ) if ( data )
{ {
@ -1143,10 +1079,6 @@ error1:
memcpy( (void*)result, (void*)data, length ); memcpy( (void*)result, (void*)data, length );
result[ length ] = 0; result[ length ] = 0;
} }
else
{
result = NULL;
}
net_http_delete( http ); net_http_delete( http );
net_http_connection_free( conn ); net_http_connection_free( conn );
@ -1154,9 +1086,7 @@ error1:
RARCH_LOG( "CHEEVOS http result is %s\n", result ); RARCH_LOG( "CHEEVOS http result is %s\n", result );
if ( size ) if ( size )
{
*size = length; *size = length;
}
return (char*)result; return (char*)result;
@ -1166,9 +1096,7 @@ error1:
RARCH_ERROR( "CHEEVOS Network unavailable\n" ); RARCH_ERROR( "CHEEVOS Network unavailable\n" );
if ( size ) if ( size )
{
*size = 0; *size = 0;
}
return NULL; return NULL;
@ -1269,12 +1197,12 @@ static int cheevos_get_value( const char* json, unsigned key_hash, char* value,
return -1; return -1;
} }
static int cheevos_login( void ) static int cheevos_login(void)
{ {
int res = 0;
char request[ 256 ]; char request[ 256 ];
const char* json; const char* json;
cheevo_getvalueud_t ud; cheevo_getvalueud_t ud;
int res = 0;
if ( cheevos_config.token[ 0 ] == 0 ) if ( cheevos_config.token[ 0 ] == 0 )
{ {
@ -1291,9 +1219,7 @@ static int cheevos_login( void )
json = cheevos_http_get( request, NULL ); json = cheevos_http_get( request, NULL );
if ( !json ) if ( !json )
{
return -1; return -1;
}
res = cheevos_get_value( json, 0x0e2dbd26U /* Token */, cheevos_config.token, sizeof( cheevos_config.token ) ); res = cheevos_get_value( json, 0x0e2dbd26U /* Token */, cheevos_config.token, sizeof( cheevos_config.token ) );
} }
@ -1319,9 +1245,7 @@ int cheevos_get_by_game_id( const char** json, unsigned game_id )
*json = cheevos_http_get( request, NULL ); *json = cheevos_http_get( request, NULL );
if ( !*json ) if ( !*json )
{
return -1; return -1;
}
return 0; return 0;
} }
@ -1349,9 +1273,7 @@ static unsigned cheevos_get_game_id( unsigned char* hash )
json = cheevos_http_get( request, NULL ); json = cheevos_http_get( request, NULL );
if ( !json ) if ( !json )
{
return -1; return -1;
}
res = cheevos_get_value( json, 0xb4960eecU /* GameID */, game_id, sizeof( game_id ) ); res = cheevos_get_value( json, 0xb4960eecU /* GameID */, game_id, sizeof( game_id ) );
free( (void*)json ); free( (void*)json );
@ -1364,10 +1286,10 @@ static unsigned cheevos_get_game_id( unsigned char* hash )
int cheevos_get_by_content( const char** json, const void* data, size_t size ) int cheevos_get_by_content( const char** json, const void* data, size_t size )
{ {
MD5_CTX ctx, saved_ctx; MD5_CTX ctx, saved_ctx;
char buffer[ 4096 ];
size_t len; size_t len;
unsigned char hash[ 16 ]; unsigned char hash[ 16 ];
char request[ 256 ]; char request[ 256 ];
char buffer[ 4096 ];
unsigned game_id; unsigned game_id;
int res; int res;
@ -1389,9 +1311,7 @@ int cheevos_get_by_content( const char** json, const void* data, size_t size )
len = sizeof( buffer ); len = sizeof( buffer );
if ( len > size ) if ( len > size )
{
len = size; len = size;
}
MD5_Update( &saved_ctx, (void*)buffer, len ); MD5_Update( &saved_ctx, (void*)buffer, len );
size -= len; size -= len;
@ -1402,10 +1322,8 @@ int cheevos_get_by_content( const char** json, const void* data, size_t size )
game_id = cheevos_get_game_id( hash ); game_id = cheevos_get_game_id( hash );
if ( !game_id ) if ( !game_id )
{
return -1; return -1;
} }
}
RARCH_LOG( "CHEEVOS game id is %u\n", game_id ); RARCH_LOG( "CHEEVOS game id is %u\n", game_id );
return cheevos_get_by_game_id( json, game_id ); return cheevos_get_by_game_id( json, game_id );
@ -1418,11 +1336,11 @@ int cheevos_load( const char* json )
return -1; return -1;
} }
void cheevos_test( void ) void cheevos_test(void)
{ {
} }
void cheevos_unload( void ) void cheevos_unload(void)
{ {
} }

View File

@ -0,0 +1,21 @@
TARGET := http_test
SOURCES := $(wildcard *.c) \
../compat/compat.c
OBJS := $(SOURCES:.c=.o)
CFLAGS += -Wall -pedantic -std=gnu99 -O0 -g -I../include
all: $(TARGET)
%.o: %.c
$(CC) -c -o $@ $< $(CFLAGS)
$(TARGET): $(OBJS)
$(CC) -o $@ $^ $(LDFLAGS)
clean:
rm -f $(TARGET) $(OBJS)
.PHONY: clean