mirror of
https://github.com/libretro/RetroArch
synced 2025-02-01 00:32:46 +00:00
Merge pull request #3992 from leiradel/master
Fixed math to translate a physical address to the memory descriptor index + offset
This commit is contained in:
commit
8ec45750d4
417
cheevos.c
417
cheevos.c
@ -58,20 +58,27 @@
|
||||
/* Define this macro to get extra-verbose log for cheevos. */
|
||||
#undef CHEEVOS_VERBOSE
|
||||
|
||||
#define JSON_KEY_GAMEID 0xb4960eecU
|
||||
#define JSON_KEY_ACHIEVEMENTS 0x69749ae1U
|
||||
#define JSON_KEY_ID 0x005973f2U
|
||||
#define JSON_KEY_MEMADDR 0x1e76b53fU
|
||||
#define JSON_KEY_TITLE 0x0e2a9a07U
|
||||
#define JSON_KEY_DESCRIPTION 0xe61a1f69U
|
||||
#define JSON_KEY_POINTS 0xca8fce22U
|
||||
#define JSON_KEY_AUTHOR 0xa804edb8U
|
||||
#define JSON_KEY_MODIFIED 0xdcea4fe6U
|
||||
#define JSON_KEY_CREATED 0x3a84721dU
|
||||
#define JSON_KEY_BADGENAME 0x887685d9U
|
||||
#define JSON_KEY_CONSOLE_ID 0x071656e5U
|
||||
#define JSON_KEY_TOKEN 0x0e2dbd26U
|
||||
#define JSON_KEY_FLAGS 0x0d2e96b2U
|
||||
/* Define this macro to load a JSON file from disk instead of downloading
|
||||
* from retroachievements.org. */
|
||||
#undef CHEEVOS_JSON_OVERRIDE
|
||||
|
||||
enum
|
||||
{
|
||||
CHEEVOS_JSON_KEY_GAMEID = 0xb4960eecU,
|
||||
CHEEVOS_JSON_KEY_ACHIEVEMENTS = 0x69749ae1U,
|
||||
CHEEVOS_JSON_KEY_ID = 0x005973f2U,
|
||||
CHEEVOS_JSON_KEY_MEMADDR = 0x1e76b53fU,
|
||||
CHEEVOS_JSON_KEY_TITLE = 0x0e2a9a07U,
|
||||
CHEEVOS_JSON_KEY_DESCRIPTION = 0xe61a1f69U,
|
||||
CHEEVOS_JSON_KEY_POINTS = 0xca8fce22U,
|
||||
CHEEVOS_JSON_KEY_AUTHOR = 0xa804edb8U,
|
||||
CHEEVOS_JSON_KEY_MODIFIED = 0xdcea4fe6U,
|
||||
CHEEVOS_JSON_KEY_CREATED = 0x3a84721dU,
|
||||
CHEEVOS_JSON_KEY_BADGENAME = 0x887685d9U,
|
||||
CHEEVOS_JSON_KEY_CONSOLE_ID = 0x071656e5U,
|
||||
CHEEVOS_JSON_KEY_TOKEN = 0x0e2dbd26U,
|
||||
CHEEVOS_JSON_KEY_FLAGS = 0x0d2e96b2U
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
@ -184,10 +191,14 @@ typedef struct
|
||||
{
|
||||
cheevos_cond_t *conds;
|
||||
unsigned count;
|
||||
|
||||
const char* expression;
|
||||
} cheevos_condset_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
cheevos_condset_t *condsets;
|
||||
unsigned count;
|
||||
} cheevos_condition_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned id;
|
||||
@ -201,8 +212,7 @@ typedef struct
|
||||
int last;
|
||||
int modified;
|
||||
|
||||
cheevos_condset_t *condsets;
|
||||
unsigned count;
|
||||
cheevos_condition_t condition;
|
||||
} cheevo_t;
|
||||
|
||||
typedef struct
|
||||
@ -406,7 +416,7 @@ static void cheevos_log_cheevo(const cheevo_t* cheevo,
|
||||
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 sets: TBD\n");
|
||||
RARCH_LOG("CHEEVOS memaddr: %s\n", memaddr);
|
||||
}
|
||||
|
||||
@ -458,16 +468,36 @@ static void cheevos_add_var_size(char** aux, size_t* left,
|
||||
}
|
||||
}
|
||||
|
||||
static void cheevos_post_log_cheevo(const cheevo_t* cheevo)
|
||||
static void cheevos_add_var(const cheevos_var_t* var, char** memaddr,
|
||||
size_t *left)
|
||||
{
|
||||
if ( var->type == CHEEVOS_VAR_TYPE_ADDRESS
|
||||
|| var->type == CHEEVOS_VAR_TYPE_DELTA_MEM)
|
||||
{
|
||||
if (var->type == CHEEVOS_VAR_TYPE_DELTA_MEM)
|
||||
cheevos_add_char(memaddr, left, 'd');
|
||||
|
||||
cheevos_add_string(memaddr, left, "0x");
|
||||
cheevos_add_var_size(memaddr, left, var);
|
||||
cheevos_add_hex(memaddr, left, var->value);
|
||||
}
|
||||
else if (var->type == CHEEVOS_VAR_TYPE_VALUE_COMP)
|
||||
{
|
||||
cheevos_add_uint(memaddr, left, var->value);
|
||||
}
|
||||
}
|
||||
|
||||
static void cheevos_build_memaddr(const cheevos_condition_t* condition,
|
||||
char* memaddr, size_t left)
|
||||
{
|
||||
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++)
|
||||
left--; /* reserve one char for the null terminator */
|
||||
|
||||
for (i = 0, condset = condition->condsets; i < condition->count; i++, condset++)
|
||||
{
|
||||
if (i != 0)
|
||||
cheevos_add_char(&aux, &left, 'S');
|
||||
@ -482,20 +512,7 @@ static void cheevos_post_log_cheevo(const cheevo_t* cheevo)
|
||||
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);
|
||||
}
|
||||
cheevos_add_var(&cond->source, &aux, &left);
|
||||
|
||||
switch (cond->op)
|
||||
{
|
||||
@ -519,20 +536,7 @@ static void cheevos_post_log_cheevo(const cheevo_t* cheevo)
|
||||
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);
|
||||
}
|
||||
cheevos_add_var(&cond->target, &aux, &left);
|
||||
|
||||
if (cond->req_hits > 0)
|
||||
{
|
||||
@ -543,9 +547,13 @@ static void cheevos_post_log_cheevo(const cheevo_t* cheevo)
|
||||
}
|
||||
}
|
||||
|
||||
cheevos_add_char(&aux, &left, 0);
|
||||
memaddr[sizeof(memaddr) - 1] = 0;
|
||||
*aux = 0;
|
||||
}
|
||||
|
||||
static void cheevos_post_log_cheevo(const cheevo_t* cheevo)
|
||||
{
|
||||
char memaddr[256];
|
||||
cheevos_build_memaddr(&cheevo->condition, memaddr, sizeof(memaddr));
|
||||
RARCH_LOG("CHEEVOS memaddr (computed): %s\n", memaddr);
|
||||
}
|
||||
#endif
|
||||
@ -706,7 +714,7 @@ static int cheevos_count__json_key(void *userdata,
|
||||
cheevos_countud_t* ud = (cheevos_countud_t*)userdata;
|
||||
ud->field_hash = cheevos_djb2(name, length);
|
||||
|
||||
if (ud->field_hash == JSON_KEY_ACHIEVEMENTS)
|
||||
if (ud->field_hash == CHEEVOS_JSON_KEY_ACHIEVEMENTS)
|
||||
ud->in_cheevos = 1;
|
||||
|
||||
return 0;
|
||||
@ -717,21 +725,14 @@ static int cheevos_count__json_number(void *userdata,
|
||||
{
|
||||
cheevos_countud_t* ud = (cheevos_countud_t*)userdata;
|
||||
|
||||
if (ud->in_cheevos && ud->field_hash == JSON_KEY_FLAGS)
|
||||
if (ud->in_cheevos && ud->field_hash == CHEEVOS_JSON_KEY_FLAGS)
|
||||
{
|
||||
long flags = strtol(number, NULL, 10);
|
||||
|
||||
switch (flags)
|
||||
{
|
||||
case 3: /* Core achievements */
|
||||
ud->core_count++;
|
||||
break;
|
||||
case 5: /* Unofficial achievements */
|
||||
ud->unofficial_count++;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (flags == 3)
|
||||
ud->core_count++; /* Core achievements */
|
||||
else if (flags == 5)
|
||||
ud->unofficial_count++; /* Unofficial achievements */
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -878,6 +879,29 @@ static unsigned cheevos_parse_operator(const char **memaddr)
|
||||
return op;
|
||||
}
|
||||
|
||||
static size_t cheevos_reduce(size_t addr, size_t mask)
|
||||
{
|
||||
while (mask)
|
||||
{
|
||||
size_t tmp = (mask - 1) & ~mask;
|
||||
addr = (addr & tmp) | ((addr >> 1) & ~tmp);
|
||||
mask = (mask & (mask - 1)) >> 1;
|
||||
}
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
static size_t cheevos_highest_bit(size_t n)
|
||||
{
|
||||
n |= n >> 1;
|
||||
n |= n >> 2;
|
||||
n |= n >> 4;
|
||||
n |= n >> 8;
|
||||
n |= n >> 16;
|
||||
|
||||
return n ^ (n >> 1);
|
||||
}
|
||||
|
||||
void cheevos_parse_guest_addr(cheevos_var_t *var, unsigned value)
|
||||
{
|
||||
rarch_system_info_t *system;
|
||||
@ -892,8 +916,8 @@ void cheevos_parse_guest_addr(cheevos_var_t *var, unsigned value)
|
||||
|
||||
if (system->mmaps.num_descriptors != 0)
|
||||
{
|
||||
const struct retro_memory_descriptor *desc = NULL;
|
||||
const struct retro_memory_descriptor *end = NULL;
|
||||
const rarch_memory_descriptor_t *desc = NULL;
|
||||
const rarch_memory_descriptor_t *end = NULL;
|
||||
|
||||
switch (cheevos_locals.console_id)
|
||||
{
|
||||
@ -917,10 +941,17 @@ void cheevos_parse_guest_addr(cheevos_var_t *var, unsigned value)
|
||||
|
||||
for (; desc < end; desc++)
|
||||
{
|
||||
if ((var->value & desc->select) == desc->start)
|
||||
if (((desc->core.start ^ var->value) & desc->core.select) == 0)
|
||||
{
|
||||
var->bank_id = desc - system->mmaps.descriptors;
|
||||
var->value = var->value - desc->start + desc->offset;
|
||||
var->value = cheevos_reduce(
|
||||
(var->value - desc->core.start) & desc->disconnect_mask,
|
||||
desc->core.disconnect);
|
||||
|
||||
if (var->value >= desc->core.len)
|
||||
var->value -= cheevos_highest_bit(var->value);
|
||||
|
||||
var->value += desc->core.offset;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1118,9 +1149,52 @@ static void cheevos_parse_memaddr(cheevos_cond_t *cond, const char *memaddr, uns
|
||||
|
||||
memaddr++;
|
||||
}
|
||||
}
|
||||
|
||||
if (*memaddr != '"')
|
||||
RARCH_LOG("CHEEVOS error parsing memaddr\n");
|
||||
static int cheevos_parse_condition(cheevos_condition_t *condition, const char* memaddr)
|
||||
{
|
||||
condition->count = cheevos_count_cond_sets(memaddr);
|
||||
|
||||
if (condition->count)
|
||||
{
|
||||
unsigned set = 0;
|
||||
cheevos_condset_t *condset = NULL;
|
||||
cheevos_condset_t *conds = (cheevos_condset_t*)
|
||||
calloc(condition->count, sizeof(cheevos_condset_t));
|
||||
const cheevos_condset_t* end;
|
||||
|
||||
if (!conds)
|
||||
return -1;
|
||||
|
||||
condition->condsets = conds;
|
||||
end = condition->condsets + condition->count;
|
||||
|
||||
for (condset = condition->condsets; condset < end; condset++, set++)
|
||||
{
|
||||
condset->count =
|
||||
cheevos_count_conds_in_set(memaddr, set);
|
||||
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)
|
||||
{
|
||||
cheevos_cond_t *conds = (cheevos_cond_t*)
|
||||
calloc(condset->count, sizeof(cheevos_cond_t));
|
||||
|
||||
if (!conds)
|
||||
return -1;
|
||||
|
||||
condset->conds = conds;
|
||||
cheevos_parse_memaddr(condset->conds, memaddr, set);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
@ -1163,51 +1237,12 @@ static int cheevos_new_cheevo(cheevos_readud_t *ud)
|
||||
if (!cheevo->title || !cheevo->description || !cheevo->author || !cheevo->badge)
|
||||
goto error;
|
||||
|
||||
cheevo->count = cheevos_count_cond_sets(ud->memaddr.string);
|
||||
|
||||
#ifdef CHEEVOS_VERBOSE
|
||||
cheevos_log_cheevo(cheevo, &ud->memaddr);
|
||||
#endif
|
||||
|
||||
if (cheevo->count)
|
||||
{
|
||||
unsigned set = 0;
|
||||
cheevos_condset_t *condset = NULL;
|
||||
cheevos_condset_t *conds = (cheevos_condset_t*)
|
||||
calloc(cheevo->count, sizeof(cheevos_condset_t));
|
||||
const cheevos_condset_t* end;
|
||||
|
||||
if (!conds)
|
||||
return -1;
|
||||
|
||||
cheevo->condsets = conds;
|
||||
end = cheevo->condsets + cheevo->count;
|
||||
|
||||
for (condset = cheevo->condsets; condset < end; condset++, set++)
|
||||
{
|
||||
condset->count =
|
||||
cheevos_count_conds_in_set(ud->memaddr.string, set);
|
||||
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)
|
||||
{
|
||||
cheevos_cond_t *conds = (cheevos_cond_t*)
|
||||
calloc(condset->count, sizeof(cheevos_cond_t));
|
||||
|
||||
if (!conds)
|
||||
return -1;
|
||||
|
||||
condset->conds = conds;
|
||||
condset->expression = cheevos_dupstr(&ud->memaddr);
|
||||
cheevos_parse_memaddr(condset->conds, ud->memaddr.string, set);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (cheevos_parse_condition(&cheevo->condition, ud->memaddr.string))
|
||||
goto error;
|
||||
|
||||
#ifdef CHEEVOS_VERBOSE
|
||||
cheevos_post_log_cheevo(cheevo);
|
||||
@ -1233,49 +1268,49 @@ static int cheevos_read__json_key( void *userdata,
|
||||
|
||||
switch (hash)
|
||||
{
|
||||
case JSON_KEY_ACHIEVEMENTS:
|
||||
ud->in_cheevos = 1;
|
||||
case CHEEVOS_JSON_KEY_ACHIEVEMENTS:
|
||||
ud->in_cheevos = 1;
|
||||
break;
|
||||
case JSON_KEY_CONSOLE_ID:
|
||||
case CHEEVOS_JSON_KEY_CONSOLE_ID:
|
||||
ud->is_console_id = 1;
|
||||
break;
|
||||
case JSON_KEY_ID:
|
||||
case CHEEVOS_JSON_KEY_ID:
|
||||
if (ud->in_cheevos)
|
||||
ud->field = &ud->id;
|
||||
break;
|
||||
case JSON_KEY_MEMADDR:
|
||||
case CHEEVOS_JSON_KEY_MEMADDR:
|
||||
if (ud->in_cheevos)
|
||||
ud->field = &ud->memaddr;
|
||||
break;
|
||||
case JSON_KEY_TITLE:
|
||||
case CHEEVOS_JSON_KEY_TITLE:
|
||||
if (ud->in_cheevos)
|
||||
ud->field = &ud->title;
|
||||
break;
|
||||
case JSON_KEY_DESCRIPTION:
|
||||
case CHEEVOS_JSON_KEY_DESCRIPTION:
|
||||
if (ud->in_cheevos)
|
||||
ud->field = &ud->desc;
|
||||
break;
|
||||
case JSON_KEY_POINTS:
|
||||
case CHEEVOS_JSON_KEY_POINTS:
|
||||
if (ud->in_cheevos)
|
||||
ud->field = &ud->points;
|
||||
break;
|
||||
case JSON_KEY_AUTHOR:
|
||||
case CHEEVOS_JSON_KEY_AUTHOR:
|
||||
if (ud->in_cheevos)
|
||||
ud->field = &ud->author;
|
||||
break;
|
||||
case JSON_KEY_MODIFIED:
|
||||
case CHEEVOS_JSON_KEY_MODIFIED:
|
||||
if (ud->in_cheevos)
|
||||
ud->field = &ud->modified;
|
||||
break;
|
||||
case JSON_KEY_CREATED:
|
||||
case CHEEVOS_JSON_KEY_CREATED:
|
||||
if (ud->in_cheevos)
|
||||
ud->field = &ud->created;
|
||||
break;
|
||||
case JSON_KEY_BADGENAME:
|
||||
case CHEEVOS_JSON_KEY_BADGENAME:
|
||||
if (ud->in_cheevos)
|
||||
ud->field = &ud->badge;
|
||||
break;
|
||||
case JSON_KEY_FLAGS:
|
||||
case CHEEVOS_JSON_KEY_FLAGS:
|
||||
if (ud->in_cheevos)
|
||||
ud->field = &ud->flags;
|
||||
break;
|
||||
@ -1355,25 +1390,28 @@ static int cheevos_parse(const char *json)
|
||||
};
|
||||
|
||||
unsigned core_count, unofficial_count;
|
||||
int res;
|
||||
cheevos_readud_t ud;
|
||||
settings_t *settings = config_get_ptr();
|
||||
settings_t *settings = config_get_ptr();
|
||||
|
||||
/* Just return OK if cheevos are disabled. */
|
||||
if (!settings->cheevos.enable)
|
||||
return 0;
|
||||
|
||||
/* Count the number of achievements in the JSON file. */
|
||||
if (cheevos_count_cheevos(json, &core_count, &unofficial_count) != JSONSAX_OK)
|
||||
res = cheevos_count_cheevos(json, &core_count, &unofficial_count);
|
||||
|
||||
if (res != JSONSAX_OK)
|
||||
return -1;
|
||||
|
||||
/* Allocate the achievements. */
|
||||
|
||||
cheevos_locals.core.cheevos = (cheevo_t*)
|
||||
malloc(core_count * sizeof(cheevo_t));
|
||||
calloc(core_count, sizeof(cheevo_t));
|
||||
cheevos_locals.core.count = core_count;
|
||||
|
||||
cheevos_locals.unofficial.cheevos = (cheevo_t*)
|
||||
malloc(unofficial_count * sizeof(cheevo_t));
|
||||
calloc(unofficial_count, sizeof(cheevo_t));
|
||||
cheevos_locals.unofficial.count = unofficial_count;
|
||||
|
||||
if (!cheevos_locals.core.cheevos || !cheevos_locals.unofficial.cheevos)
|
||||
@ -1385,11 +1423,6 @@ static int cheevos_parse(const char *json)
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset((void*)cheevos_locals.core.cheevos,
|
||||
0, core_count * sizeof(cheevo_t));
|
||||
memset((void*)cheevos_locals.unofficial.cheevos,
|
||||
0, unofficial_count * sizeof(cheevo_t));
|
||||
|
||||
/* Load the achievements. */
|
||||
ud.in_cheevos = 0;
|
||||
ud.is_console_id = 0;
|
||||
@ -1420,7 +1453,7 @@ uint8_t *cheevos_get_memory(const cheevos_var_t *var)
|
||||
runloop_ctl(RUNLOOP_CTL_SYSTEM_INFO_GET, &system);
|
||||
|
||||
if (system->mmaps.num_descriptors != 0)
|
||||
return (uint8_t *)system->mmaps.descriptors[var->bank_id].ptr + var->value;
|
||||
return (uint8_t *)system->mmaps.descriptors[var->bank_id].core.ptr + var->value;
|
||||
|
||||
return (uint8_t *)cheevos_locals.meminfo[var->bank_id].data + var->value;
|
||||
}
|
||||
@ -1444,31 +1477,48 @@ static unsigned cheevos_get_var_value(cheevos_var_t *var)
|
||||
{
|
||||
live_val = memory[0];
|
||||
|
||||
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;
|
||||
else
|
||||
switch (var->size)
|
||||
{
|
||||
switch (var->size)
|
||||
{
|
||||
case CHEEVOS_VAR_SIZE_NIBBLE_LOWER:
|
||||
live_val &= 0x0f;
|
||||
break;
|
||||
case CHEEVOS_VAR_SIZE_NIBBLE_UPPER:
|
||||
live_val = (live_val >> 4) & 0x0f;
|
||||
break;
|
||||
case CHEEVOS_VAR_SIZE_EIGHT_BITS:
|
||||
break;
|
||||
case CHEEVOS_VAR_SIZE_SIXTEEN_BITS:
|
||||
live_val |= memory[1] << 8;
|
||||
break;
|
||||
case CHEEVOS_VAR_SIZE_THIRTYTWO_BITS:
|
||||
live_val |= memory[1] << 8;
|
||||
live_val |= memory[2] << 16;
|
||||
live_val |= memory[3] << 24;
|
||||
break;
|
||||
}
|
||||
case CHEEVOS_VAR_SIZE_BIT_0:
|
||||
live_val &= 1;
|
||||
break;
|
||||
case CHEEVOS_VAR_SIZE_BIT_1:
|
||||
live_val = (live_val >> 1) & 1;
|
||||
break;
|
||||
case CHEEVOS_VAR_SIZE_BIT_2:
|
||||
live_val = (live_val >> 2) & 1;
|
||||
break;
|
||||
case CHEEVOS_VAR_SIZE_BIT_3:
|
||||
live_val = (live_val >> 3) & 1;
|
||||
break;
|
||||
case CHEEVOS_VAR_SIZE_BIT_4:
|
||||
live_val = (live_val >> 4) & 1;
|
||||
break;
|
||||
case CHEEVOS_VAR_SIZE_BIT_5:
|
||||
live_val = (live_val >> 5) & 1;
|
||||
break;
|
||||
case CHEEVOS_VAR_SIZE_BIT_6:
|
||||
live_val = (live_val >> 6) & 1;
|
||||
break;
|
||||
case CHEEVOS_VAR_SIZE_BIT_7:
|
||||
live_val = (live_val >> 7) & 1;
|
||||
break;
|
||||
case CHEEVOS_VAR_SIZE_NIBBLE_LOWER:
|
||||
live_val &= 0x0f;
|
||||
break;
|
||||
case CHEEVOS_VAR_SIZE_NIBBLE_UPPER:
|
||||
live_val = (live_val >> 4) & 0x0f;
|
||||
break;
|
||||
case CHEEVOS_VAR_SIZE_EIGHT_BITS:
|
||||
break;
|
||||
case CHEEVOS_VAR_SIZE_SIXTEEN_BITS:
|
||||
live_val |= memory[1] << 8;
|
||||
break;
|
||||
case CHEEVOS_VAR_SIZE_THIRTYTWO_BITS:
|
||||
live_val |= memory[1] << 8;
|
||||
live_val |= memory[2] << 16;
|
||||
live_val |= memory[3] << 24;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1626,9 +1676,9 @@ static int cheevos_test_cheevo(cheevo_t *cheevo)
|
||||
int dirty_conds = 0;
|
||||
int reset_conds = 0;
|
||||
int ret_val = 0;
|
||||
int ret_val_sub_cond = cheevo->count == 1;
|
||||
cheevos_condset_t *condset = cheevo->condsets;
|
||||
const cheevos_condset_t *end = condset + cheevo->count;
|
||||
int ret_val_sub_cond = cheevo->condition.count == 1;
|
||||
cheevos_condset_t *condset = cheevo->condition.condsets;
|
||||
const cheevos_condset_t *end = condset + cheevo->condition.count;
|
||||
|
||||
if (condset < end)
|
||||
{
|
||||
@ -1649,7 +1699,7 @@ static int cheevos_test_cheevo(cheevo_t *cheevo)
|
||||
{
|
||||
dirty = 0;
|
||||
|
||||
for (condset = cheevo->condsets; condset < end; condset++)
|
||||
for (condset = cheevo->condition.condsets; condset < end; condset++)
|
||||
dirty |= cheevos_reset_cond_set(condset, 0);
|
||||
|
||||
if (dirty)
|
||||
@ -1733,12 +1783,12 @@ static int cheevos_login(retro_time_t *timeout)
|
||||
request[sizeof(request) - 1] = 0;
|
||||
|
||||
#ifdef CHEEVOS_LOG_URLS
|
||||
RARCH_LOG("CHEEVOS url to login: %s.\n", request);
|
||||
RARCH_LOG("CHEEVOS url to login: %s\n", request);
|
||||
#endif
|
||||
|
||||
if (!cheevos_http_get(&json, NULL, request, timeout))
|
||||
{
|
||||
res = cheevos_get_value(json, JSON_KEY_TOKEN,
|
||||
res = cheevos_get_value(json, CHEEVOS_JSON_KEY_TOKEN,
|
||||
cheevos_locals.token, sizeof(cheevos_locals.token));
|
||||
|
||||
free((void*)json);
|
||||
@ -1770,7 +1820,7 @@ static void cheevos_make_unlock_url(const cheevo_t *cheevo, char* url, size_t ur
|
||||
url[url_size - 1] = 0;
|
||||
|
||||
#ifdef CHEEVOS_LOG_URLS
|
||||
RARCH_LOG("CHEEVOS url to award the cheevo: %s.\n", url);
|
||||
RARCH_LOG("CHEEVOS url to award the cheevo: %s\n", url);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -1852,7 +1902,7 @@ static void cheevos_free_cheevo(const cheevo_t *cheevo)
|
||||
free((void*)cheevo->description);
|
||||
free((void*)cheevo->author);
|
||||
free((void*)cheevo->badge);
|
||||
cheevos_free_condset(cheevo->condsets);
|
||||
cheevos_free_condset(cheevo->condition.condsets);
|
||||
}
|
||||
|
||||
static void cheevos_free_cheevo_set(const cheevoset_t *set)
|
||||
@ -1894,7 +1944,7 @@ static int cheevos_get_by_game_id(const char **json,
|
||||
request[sizeof(request) - 1] = 0;
|
||||
|
||||
#ifdef CHEEVOS_LOG_URLS
|
||||
RARCH_LOG("CHEEVOS url to get the list of cheevos: %s.\n", request);
|
||||
RARCH_LOG("CHEEVOS url to get the list of cheevos: %s\n", request);
|
||||
#endif
|
||||
|
||||
if (!cheevos_http_get(json, NULL, request, timeout))
|
||||
@ -1939,12 +1989,12 @@ static unsigned cheevos_get_game_id(unsigned char *hash, retro_time_t *timeout)
|
||||
request[sizeof(request) - 1] = 0;
|
||||
|
||||
#ifdef CHEEVOS_LOG_URLS
|
||||
RARCH_LOG("CHEEVOS url to get the game's id: %s.\n", request);
|
||||
RARCH_LOG("CHEEVOS url to get the game's id: %s\n", request);
|
||||
#endif
|
||||
|
||||
if (!cheevos_http_get(&json, NULL, request, timeout))
|
||||
{
|
||||
res = cheevos_get_value(json, JSON_KEY_GAMEID,
|
||||
res = cheevos_get_value(json, CHEEVOS_JSON_KEY_GAMEID,
|
||||
game_id, sizeof(game_id));
|
||||
|
||||
free((void*)json);
|
||||
@ -1973,7 +2023,7 @@ static void cheevos_make_playing_url(unsigned game_id, char* url, size_t url_siz
|
||||
url[url_size - 1] = 0;
|
||||
|
||||
#ifdef CHEEVOS_LOG_URLS
|
||||
RARCH_LOG("CHEEVOS url to post the 'playing' activity: %s.\n", url);
|
||||
RARCH_LOG("CHEEVOS url to post the 'playing' activity: %s\n", url);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -2100,7 +2150,7 @@ static int cheevos_deactivate_unlocks(unsigned game_id, retro_time_t *timeout)
|
||||
request[sizeof(request) - 1] = 0;
|
||||
|
||||
#ifdef CHEEVOS_LOG_URLS
|
||||
RARCH_LOG("CHEEVOS url to get the list of unlocked cheevos in softcore: %s.\n", request);
|
||||
RARCH_LOG("CHEEVOS url to get the list of unlocked cheevos in softcore: %s\n", request);
|
||||
#endif
|
||||
|
||||
if (!cheevos_http_get(&json, NULL, request, timeout))
|
||||
@ -2129,7 +2179,7 @@ static int cheevos_deactivate_unlocks(unsigned game_id, retro_time_t *timeout)
|
||||
request[sizeof(request) - 1] = 0;
|
||||
|
||||
#ifdef CHEEVOS_LOG_URLS
|
||||
RARCH_LOG("CHEEVOS url to get the list of unlocked cheevos in hardcore: %s.\n", request);
|
||||
RARCH_LOG("CHEEVOS url to get the list of unlocked cheevos in hardcore: %s\n", request);
|
||||
#endif
|
||||
|
||||
if (!cheevos_http_get(&json, NULL, request, timeout))
|
||||
@ -2525,7 +2575,24 @@ bool cheevos_load(const void *data)
|
||||
return false;
|
||||
|
||||
found:
|
||||
#ifdef CHEEVOS_JSON_OVERRIDE
|
||||
{
|
||||
FILE* file;
|
||||
size_t size;
|
||||
|
||||
file = fopen(CHEEVOS_JSON_OVERRIDE, "rb");
|
||||
fseek(file, 0, SEEK_END);
|
||||
size = ftell(file);
|
||||
fseek(file, 0, SEEK_SET);
|
||||
|
||||
json = (const char*)malloc(size);
|
||||
fread((void*)json, 1, size, file);
|
||||
|
||||
fclose(file);
|
||||
}
|
||||
#else
|
||||
if (!cheevos_get_by_game_id(&json, game_id, &timeout))
|
||||
#endif
|
||||
{
|
||||
if (!cheevos_parse(json))
|
||||
{
|
||||
@ -2748,6 +2815,8 @@ bool cheevos_test(void)
|
||||
|
||||
if (settings->cheevos.test_unofficial)
|
||||
cheevos_test_cheevo_set(&cheevos_locals.unofficial);
|
||||
|
||||
//cheevos_test_leaderboards();
|
||||
}
|
||||
|
||||
return true;
|
||||
|
14
core.h
14
core.h
@ -43,6 +43,18 @@ enum
|
||||
POLL_TYPE_LATE
|
||||
};
|
||||
|
||||
typedef struct rarch_memory_descriptor
|
||||
{
|
||||
struct retro_memory_descriptor core;
|
||||
size_t disconnect_mask;
|
||||
} rarch_memory_descriptor_t;
|
||||
|
||||
typedef struct rarch_memory_map
|
||||
{
|
||||
rarch_memory_descriptor_t *descriptors;
|
||||
unsigned num_descriptors;
|
||||
} rarch_memory_map_t;
|
||||
|
||||
typedef struct rarch_system_info
|
||||
{
|
||||
struct retro_system_info info;
|
||||
@ -68,7 +80,7 @@ typedef struct rarch_system_info
|
||||
unsigned size;
|
||||
} ports;
|
||||
|
||||
struct retro_memory_map mmaps;
|
||||
rarch_memory_map_t mmaps;
|
||||
} rarch_system_info_t;
|
||||
|
||||
typedef struct retro_ctx_input_state_info
|
||||
|
79
dynamic.c
79
dynamic.c
@ -778,52 +778,51 @@ static size_t mmap_highest_bit(size_t n)
|
||||
return n ^ (n >> 1);
|
||||
}
|
||||
|
||||
static bool mmap_preprocess_descriptors(struct retro_memory_descriptor *first, unsigned count)
|
||||
static bool mmap_preprocess_descriptors(rarch_memory_descriptor_t *first, unsigned count)
|
||||
{
|
||||
size_t disconnect_mask;
|
||||
size_t top_addr = 1;
|
||||
struct retro_memory_descriptor *desc = NULL;
|
||||
const struct retro_memory_descriptor *end = first + count;
|
||||
size_t top_addr = 1;
|
||||
rarch_memory_descriptor_t *desc = NULL;
|
||||
const rarch_memory_descriptor_t *end = first + count;
|
||||
|
||||
for (desc = first; desc < end; desc++)
|
||||
{
|
||||
if (desc->select != 0)
|
||||
top_addr |= desc->select;
|
||||
if (desc->core.select != 0)
|
||||
top_addr |= desc->core.select;
|
||||
else
|
||||
top_addr |= desc->start + desc->len - 1;
|
||||
top_addr |= desc->core.start + desc->core.len - 1;
|
||||
}
|
||||
|
||||
top_addr = mmap_add_bits_down(top_addr);
|
||||
|
||||
for (desc = first; desc < end; desc++)
|
||||
{
|
||||
if (desc->select == 0)
|
||||
if (desc->core.select == 0)
|
||||
{
|
||||
if (desc->len == 0)
|
||||
if (desc->core.len == 0)
|
||||
return false;
|
||||
|
||||
if ((desc->len & (desc->len - 1)) != 0)
|
||||
if ((desc->core.len & (desc->core.len - 1)) != 0)
|
||||
return false;
|
||||
|
||||
desc->select = top_addr & ~mmap_inflate(mmap_add_bits_down(desc->len - 1), desc->disconnect);
|
||||
desc->core.select = top_addr & ~mmap_inflate(mmap_add_bits_down(desc->core.len - 1), desc->core.disconnect);
|
||||
}
|
||||
|
||||
if (desc->len == 0)
|
||||
desc->len = mmap_add_bits_down(mmap_reduce(top_addr & ~desc->select, desc->disconnect)) + 1;
|
||||
if (desc->core.len == 0)
|
||||
desc->core.len = mmap_add_bits_down(mmap_reduce(top_addr & ~desc->core.select, desc->core.disconnect)) + 1;
|
||||
|
||||
if (desc->start & ~desc->select)
|
||||
if (desc->core.start & ~desc->core.select)
|
||||
return false;
|
||||
|
||||
while (mmap_reduce(top_addr & ~desc->select, desc->disconnect) >> 1 > desc->len - 1)
|
||||
desc->disconnect |= mmap_highest_bit(top_addr & ~desc->select & ~desc->disconnect);
|
||||
while (mmap_reduce(top_addr & ~desc->core.select, desc->core.disconnect) >> 1 > desc->core.len - 1)
|
||||
desc->core.disconnect |= mmap_highest_bit(top_addr & ~desc->core.select & ~desc->core.disconnect);
|
||||
|
||||
disconnect_mask = mmap_add_bits_down(desc->len - 1);
|
||||
desc->disconnect &= disconnect_mask;
|
||||
desc->disconnect_mask = mmap_add_bits_down(desc->core.len - 1);
|
||||
desc->core.disconnect &= desc->disconnect_mask;
|
||||
|
||||
while ((~disconnect_mask) >> 1 & desc->disconnect)
|
||||
while ((~desc->disconnect_mask) >> 1 & desc->core.disconnect)
|
||||
{
|
||||
disconnect_mask >>= 1;
|
||||
desc->disconnect &= disconnect_mask;
|
||||
desc->disconnect_mask >>= 1;
|
||||
desc->core.disconnect &= desc->disconnect_mask;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1486,22 +1485,24 @@ bool rarch_environment_cb(unsigned cmd, void *data)
|
||||
unsigned i;
|
||||
const struct retro_memory_map *mmaps =
|
||||
(const struct retro_memory_map*)data;
|
||||
struct retro_memory_descriptor *descriptors = NULL;
|
||||
rarch_memory_descriptor_t *descriptors = NULL;
|
||||
|
||||
RARCH_LOG("Environ SET_MEMORY_MAPS.\n");
|
||||
free((void*)system->mmaps.descriptors);
|
||||
system->mmaps.num_descriptors = 0;
|
||||
descriptors = (struct retro_memory_descriptor*)
|
||||
descriptors = (rarch_memory_descriptor_t*)
|
||||
calloc(mmaps->num_descriptors,
|
||||
sizeof(*system->mmaps.descriptors));
|
||||
sizeof(*descriptors));
|
||||
|
||||
if (!descriptors)
|
||||
return false;
|
||||
|
||||
system->mmaps.descriptors = descriptors;
|
||||
memcpy((void*)system->mmaps.descriptors, mmaps->descriptors,
|
||||
mmaps->num_descriptors * sizeof(*system->mmaps.descriptors));
|
||||
system->mmaps.num_descriptors = mmaps->num_descriptors;
|
||||
|
||||
for (i = 0; i < mmaps->num_descriptors; i++)
|
||||
system->mmaps.descriptors[i].core = mmaps->descriptors[i];
|
||||
|
||||
mmap_preprocess_descriptors(descriptors, mmaps->num_descriptors);
|
||||
|
||||
if (sizeof(void *) == 8)
|
||||
@ -1511,38 +1512,38 @@ bool rarch_environment_cb(unsigned cmd, void *data)
|
||||
|
||||
for (i = 0; i < system->mmaps.num_descriptors; i++)
|
||||
{
|
||||
const struct retro_memory_descriptor *desc =
|
||||
const rarch_memory_descriptor_t *desc =
|
||||
&system->mmaps.descriptors[i];
|
||||
char flags[7];
|
||||
|
||||
flags[0] = 'M';
|
||||
if ((desc->flags & RETRO_MEMDESC_MINSIZE_8) == RETRO_MEMDESC_MINSIZE_8)
|
||||
if ((desc->core.flags & RETRO_MEMDESC_MINSIZE_8) == RETRO_MEMDESC_MINSIZE_8)
|
||||
flags[1] = '8';
|
||||
else if ((desc->flags & RETRO_MEMDESC_MINSIZE_4) == RETRO_MEMDESC_MINSIZE_4)
|
||||
else if ((desc->core.flags & RETRO_MEMDESC_MINSIZE_4) == RETRO_MEMDESC_MINSIZE_4)
|
||||
flags[1] = '4';
|
||||
else if ((desc->flags & RETRO_MEMDESC_MINSIZE_2) == RETRO_MEMDESC_MINSIZE_2)
|
||||
else if ((desc->core.flags & RETRO_MEMDESC_MINSIZE_2) == RETRO_MEMDESC_MINSIZE_2)
|
||||
flags[1] = '2';
|
||||
else
|
||||
flags[1] = '1';
|
||||
|
||||
flags[2] = 'A';
|
||||
if ((desc->flags & RETRO_MEMDESC_ALIGN_8) == RETRO_MEMDESC_ALIGN_8)
|
||||
if ((desc->core.flags & RETRO_MEMDESC_ALIGN_8) == RETRO_MEMDESC_ALIGN_8)
|
||||
flags[3] = '8';
|
||||
else if ((desc->flags & RETRO_MEMDESC_ALIGN_4) == RETRO_MEMDESC_ALIGN_4)
|
||||
else if ((desc->core.flags & RETRO_MEMDESC_ALIGN_4) == RETRO_MEMDESC_ALIGN_4)
|
||||
flags[3] = '4';
|
||||
else if ((desc->flags & RETRO_MEMDESC_ALIGN_2) == RETRO_MEMDESC_ALIGN_2)
|
||||
else if ((desc->core.flags & RETRO_MEMDESC_ALIGN_2) == RETRO_MEMDESC_ALIGN_2)
|
||||
flags[3] = '2';
|
||||
else
|
||||
flags[3] = '1';
|
||||
|
||||
flags[4] = (desc->flags & RETRO_MEMDESC_BIGENDIAN) ? 'B' : 'b';
|
||||
flags[5] = (desc->flags & RETRO_MEMDESC_CONST) ? 'C' : 'c';
|
||||
flags[4] = (desc->core.flags & RETRO_MEMDESC_BIGENDIAN) ? 'B' : 'b';
|
||||
flags[5] = (desc->core.flags & RETRO_MEMDESC_CONST) ? 'C' : 'c';
|
||||
flags[6] = 0;
|
||||
|
||||
RARCH_LOG(" %03u %s %p %08X %08X %08X %08X %08X %s\n",
|
||||
i + 1, flags, desc->ptr, desc->offset, desc->start,
|
||||
desc->select, desc->disconnect, desc->len,
|
||||
desc->addrspace ? desc->addrspace : "");
|
||||
i + 1, flags, desc->core.ptr, desc->core.offset, desc->core.start,
|
||||
desc->core.select, desc->core.disconnect, desc->core.len,
|
||||
desc->core.addrspace ? desc->core.addrspace : "");
|
||||
}
|
||||
}
|
||||
else
|
||||
|
Loading…
x
Reference in New Issue
Block a user