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:
Twinaphex 2016-11-14 03:57:13 +01:00 committed by GitHub
commit 8ec45750d4
3 changed files with 296 additions and 214 deletions

417
cheevos.c
View File

@ -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
View File

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

View File

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