mirror of
https://github.com/libretro/RetroArch
synced 2025-01-29 18:32:44 +00:00
added RETRO_ENVIRONMENT_SET_SUPPORT_ACHIEVEMENTS; cheevos now work with mmaps
This commit is contained in:
parent
3d7be61363
commit
031686f27a
225
cheevos.c
225
cheevos.c
@ -24,6 +24,7 @@
|
||||
#include "cheevos.h"
|
||||
#include "dynamic.h"
|
||||
#include "libretro.h"
|
||||
#include "system.h"
|
||||
#include "network/net_http_special.h"
|
||||
#include "configuration.h"
|
||||
#include "performance_counters.h"
|
||||
@ -44,6 +45,9 @@
|
||||
/* Define this macro to log URLs (will log the user token). */
|
||||
#undef CHEEVOS_LOG_URLS
|
||||
|
||||
/* Define this macro to dump all cheevos' addresses. */
|
||||
#undef CHEEVOS_DUMP_ADDRS
|
||||
|
||||
#define JSON_KEY_GAMEID 0xb4960eecU
|
||||
#define JSON_KEY_ACHIEVEMENTS 0x69749ae1U
|
||||
#define JSON_KEY_ID 0x005973f2U
|
||||
@ -62,6 +66,7 @@
|
||||
enum
|
||||
{
|
||||
CHEEVOS_CONSOLE_GAMEBOY = 4,
|
||||
CHEEVOS_CONSOLE_GAMEBOY_ADVANCED = 5,
|
||||
CHEEVOS_CONSOLE_GAMEBOY_COLOR = 6,
|
||||
};
|
||||
|
||||
@ -142,7 +147,7 @@ typedef struct
|
||||
{
|
||||
unsigned size;
|
||||
unsigned type;
|
||||
unsigned bank_id;
|
||||
int bank_id;
|
||||
unsigned value;
|
||||
unsigned previous;
|
||||
} cheevos_var_t;
|
||||
@ -218,7 +223,7 @@ typedef struct
|
||||
typedef struct
|
||||
{
|
||||
int in_cheevos;
|
||||
int console_id;
|
||||
int is_console_id;
|
||||
unsigned core_count;
|
||||
unsigned unofficial_count;
|
||||
|
||||
@ -236,19 +241,23 @@ typedef struct
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int loaded;
|
||||
int console_id;
|
||||
int loaded;
|
||||
int console_id;
|
||||
bool core_supports;
|
||||
|
||||
cheevoset_t core;
|
||||
cheevoset_t unofficial;
|
||||
|
||||
char token[32];
|
||||
|
||||
retro_ctx_memory_info_t meminfo[4];
|
||||
} cheevos_locals_t;
|
||||
|
||||
static cheevos_locals_t cheevos_locals =
|
||||
{
|
||||
0,
|
||||
0,
|
||||
true,
|
||||
{NULL, 0},
|
||||
{NULL, 0},
|
||||
{0},
|
||||
@ -620,6 +629,69 @@ static void cheevos_parse_var(cheevos_var_t *var, const char **memaddr)
|
||||
|
||||
var->value = strtol(str, &end, base);
|
||||
*memaddr = end;
|
||||
|
||||
if ( var->type == CHEEVOS_VAR_TYPE_ADDRESS
|
||||
|| var->type == CHEEVOS_VAR_TYPE_DELTA_MEM)
|
||||
{
|
||||
rarch_system_info_t *system;
|
||||
runloop_ctl(RUNLOOP_CTL_SYSTEM_INFO_GET, &system);
|
||||
|
||||
var->bank_id = -1;
|
||||
|
||||
if (system->mmaps.num_descriptors != 0)
|
||||
{
|
||||
const struct retro_memory_descriptor *desc;
|
||||
const struct retro_memory_descriptor *end;
|
||||
|
||||
#if 0
|
||||
if (cheevos_locals.console_id == CHEEVOS_CONSOLE_GAMEBOY_ADVANCED)
|
||||
{
|
||||
/* Patch the address to correctly map it to the mmaps */
|
||||
if (var->value < 0x8000)
|
||||
{
|
||||
/* Internal RAM */
|
||||
var->value += 0x3000000;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Work RAM */
|
||||
var->value += 0x2000000 - 0x8000;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
desc = system->mmaps.descriptors;
|
||||
end = desc + system->mmaps.num_descriptors;
|
||||
|
||||
for (; desc < end; desc++)
|
||||
{
|
||||
if (var->value >= desc->start && var->value < (desc->start + desc->len))
|
||||
{
|
||||
var->bank_id = desc - system->mmaps.descriptors;
|
||||
var->value = var->value - desc->start + desc->offset;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < sizeof(cheevos_locals.meminfo) / sizeof(cheevos_locals.meminfo[0]); i++)
|
||||
{
|
||||
if (var->value < cheevos_locals.meminfo[i].size)
|
||||
{
|
||||
var->bank_id = i;
|
||||
break;
|
||||
}
|
||||
|
||||
var->value -= cheevos_locals.meminfo[i].size;
|
||||
}
|
||||
}
|
||||
#ifdef CHEEVOS_DUMP_ADDRS
|
||||
RARCH_LOG("CHEEVOS var %03d:%08X\n", var->bank_id + 1, var->value);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
static void cheevos_parse_cond(cheevos_cond_t *cond, const char **memaddr)
|
||||
@ -818,7 +890,7 @@ static int cheevos_read__json_key( void *userdata,
|
||||
if (hash == JSON_KEY_ACHIEVEMENTS)
|
||||
ud->in_cheevos = 1;
|
||||
else if (hash == JSON_KEY_CONSOLE_ID)
|
||||
ud->console_id = 0;
|
||||
ud->is_console_id = 1;
|
||||
else if (ud->in_cheevos)
|
||||
{
|
||||
switch ( hash )
|
||||
@ -883,8 +955,11 @@ static int cheevos_read__json_number(void *userdata,
|
||||
ud->field->string = number;
|
||||
ud->field->length = length;
|
||||
}
|
||||
else if (ud->console_id == 0)
|
||||
ud->console_id = strtol(number, NULL, 10);
|
||||
else if (ud->is_console_id)
|
||||
{
|
||||
cheevos_locals.console_id = strtol(number, NULL, 10);
|
||||
ud->is_console_id = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -963,7 +1038,7 @@ static int cheevos_parse(const char *json)
|
||||
|
||||
/* Load the achievements. */
|
||||
ud.in_cheevos = 0;
|
||||
ud.console_id = -1;
|
||||
ud.is_console_id = 0;
|
||||
ud.field = NULL;
|
||||
ud.core_count = 0;
|
||||
ud.unofficial_count = 0;
|
||||
@ -974,7 +1049,6 @@ static int cheevos_parse(const char *json)
|
||||
return -1;
|
||||
}
|
||||
|
||||
cheevos_locals.console_id = ud.console_id;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -982,63 +1056,23 @@ static int cheevos_parse(const char *json)
|
||||
Test all the achievements (call once per frame).
|
||||
*****************************************************************************/
|
||||
|
||||
static const uint8_t *cheevos_get_memory(unsigned offset)
|
||||
static const uint8_t *cheevos_get_memory(const cheevos_var_t *var)
|
||||
{
|
||||
retro_ctx_memory_info_t mem_info;
|
||||
uint8_t *memory = NULL;
|
||||
if (var->bank_id >= 0)
|
||||
{
|
||||
rarch_system_info_t *system;
|
||||
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;
|
||||
}
|
||||
else
|
||||
{
|
||||
return (uint8_t *)cheevos_locals.meminfo[var->bank_id].data + var->value;
|
||||
}
|
||||
}
|
||||
|
||||
mem_info.id = RETRO_MEMORY_SYSTEM_RAM;
|
||||
|
||||
core_get_memory(&mem_info);
|
||||
|
||||
if (offset < mem_info.size)
|
||||
{
|
||||
memory = (uint8_t*)mem_info.data;
|
||||
return memory + offset;
|
||||
}
|
||||
|
||||
offset -= mem_info.size;
|
||||
|
||||
mem_info.data = NULL;
|
||||
mem_info.size = 0;
|
||||
mem_info.id = RETRO_MEMORY_SAVE_RAM;
|
||||
|
||||
core_get_memory(&mem_info);
|
||||
|
||||
if (offset < mem_info.size)
|
||||
{
|
||||
memory = (uint8_t*)mem_info.data;
|
||||
return memory + offset;
|
||||
}
|
||||
|
||||
offset -= mem_info.size;
|
||||
|
||||
mem_info.data = NULL;
|
||||
mem_info.size = 0;
|
||||
mem_info.id = RETRO_MEMORY_VIDEO_RAM;
|
||||
|
||||
core_get_memory(&mem_info);
|
||||
|
||||
if (offset < mem_info.size)
|
||||
{
|
||||
memory = (uint8_t*)mem_info.data;
|
||||
return memory + offset;
|
||||
}
|
||||
|
||||
offset -= mem_info.size;
|
||||
|
||||
mem_info.data = NULL;
|
||||
mem_info.size = 0;
|
||||
mem_info.id = RETRO_MEMORY_RTC;
|
||||
|
||||
core_get_memory(&mem_info);
|
||||
|
||||
if (offset < mem_info.size)
|
||||
{
|
||||
memory = (uint8_t*)mem_info.data;
|
||||
return memory + offset;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -1055,7 +1089,7 @@ static unsigned cheevos_get_var_value(cheevos_var_t *var)
|
||||
|| var->type == CHEEVOS_VAR_TYPE_DELTA_MEM)
|
||||
{
|
||||
/* TODO Check with Scott if the bank id is needed */
|
||||
memory = cheevos_get_memory(var->value);
|
||||
memory = cheevos_get_memory(var);
|
||||
|
||||
if (memory)
|
||||
{
|
||||
@ -1396,7 +1430,7 @@ static void cheevos_unlocker(void *payload)
|
||||
request[sizeof(request) - 1] = 0;
|
||||
|
||||
#ifdef CHEEVOS_LOG_URLS
|
||||
RARCH_LOG("CHEEVOS url to award a cheevo: %s\n", request);
|
||||
RARCH_LOG("CHEEVOS url to award the cheevo: %s\n", request);
|
||||
#endif
|
||||
|
||||
if (!cheevos_http_get(&result, NULL, request, NULL))
|
||||
@ -1970,8 +2004,6 @@ static unsigned cheevos_find_game_id_nes(
|
||||
|
||||
bool cheevos_load(const void *data)
|
||||
{
|
||||
retro_ctx_memory_info_t mem_info;
|
||||
|
||||
static const uint32_t genesis_exts[] =
|
||||
{
|
||||
0x0b888feeU, /* mdx */
|
||||
@ -2008,7 +2040,6 @@ bool cheevos_load(const void *data)
|
||||
{cheevos_find_game_id_generic, "Generic (plain content)", NULL},
|
||||
};
|
||||
|
||||
size_t memory;
|
||||
struct retro_system_info sysinfo;
|
||||
unsigned i;
|
||||
const char *json = NULL;
|
||||
@ -2019,52 +2050,21 @@ bool cheevos_load(const void *data)
|
||||
|
||||
cheevos_locals.loaded = 0;
|
||||
|
||||
/* Just return OK if cheevos are disabled. */
|
||||
if (!settings->cheevos.enable)
|
||||
/* Just return OK if cheevos are disabled, the core doesn't support cheevos, or info is NULL. */
|
||||
if (!settings->cheevos.enable || !cheevos_locals.core_supports || !info)
|
||||
return true;
|
||||
|
||||
/* Also return OK if there's no content. */
|
||||
if (!info)
|
||||
return true;
|
||||
cheevos_locals.meminfo[0].id = RETRO_MEMORY_SYSTEM_RAM;
|
||||
core_get_memory(&cheevos_locals.meminfo[0]);
|
||||
|
||||
mem_info.data = NULL;
|
||||
mem_info.size = 0;
|
||||
mem_info.id = RETRO_MEMORY_SYSTEM_RAM;
|
||||
cheevos_locals.meminfo[1].id = RETRO_MEMORY_SAVE_RAM;
|
||||
core_get_memory(&cheevos_locals.meminfo[1]);
|
||||
|
||||
core_get_memory(&mem_info);
|
||||
|
||||
memory = mem_info.size;
|
||||
cheevos_locals.meminfo[2].id = RETRO_MEMORY_VIDEO_RAM;
|
||||
core_get_memory(&cheevos_locals.meminfo[2]);
|
||||
|
||||
mem_info.data = NULL;
|
||||
mem_info.size = 0;
|
||||
mem_info.id = RETRO_MEMORY_VIDEO_RAM;
|
||||
|
||||
core_get_memory(&mem_info);
|
||||
|
||||
memory += mem_info.size;
|
||||
|
||||
mem_info.data = NULL;
|
||||
mem_info.size = 0;
|
||||
mem_info.id = RETRO_MEMORY_RTC;
|
||||
|
||||
core_get_memory(&mem_info);
|
||||
|
||||
memory += mem_info.size;
|
||||
|
||||
mem_info.data = NULL;
|
||||
mem_info.size = 0;
|
||||
mem_info.id = RETRO_MEMORY_SAVE_RAM;
|
||||
|
||||
core_get_memory(&mem_info);
|
||||
|
||||
memory += mem_info.size;
|
||||
|
||||
if (!memory)
|
||||
{
|
||||
runloop_msg_queue_push("This core doesn't support achievements", 0, 5 * 60, false);
|
||||
RARCH_ERR("This core doesn't support achievements\n");
|
||||
return false;
|
||||
}
|
||||
cheevos_locals.meminfo[3].id = RETRO_MEMORY_RTC;
|
||||
core_get_memory(&cheevos_locals.meminfo[3]);
|
||||
|
||||
/* The the supported extensions as a hint to what method we should use. */
|
||||
|
||||
@ -2306,3 +2306,8 @@ bool cheevos_set_cheats(void)
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void cheevos_set_support_cheevos(bool state)
|
||||
{
|
||||
cheevos_locals.core_supports = state;
|
||||
}
|
||||
|
@ -42,4 +42,6 @@ bool cheevos_test(void);
|
||||
|
||||
bool cheevos_set_cheats(void);
|
||||
|
||||
void cheevos_set_support_cheevos(bool state);
|
||||
|
||||
#endif /* __RARCH_CHEEVOS_H */
|
||||
|
@ -45,6 +45,7 @@
|
||||
#include "cores/internal_cores.h"
|
||||
#include "frontend/frontend_driver.h"
|
||||
#include "content.h"
|
||||
#include "cheevos.h"
|
||||
#include "retroarch.h"
|
||||
#include "configuration.h"
|
||||
#include "general.h"
|
||||
@ -1428,6 +1429,14 @@ bool rarch_environment_cb(unsigned cmd, void *data)
|
||||
case RETRO_ENVIRONMENT_GET_HW_RENDER_INTERFACE:
|
||||
return video_driver_get_hw_render_interface(
|
||||
(const struct retro_hw_render_interface**)data);
|
||||
|
||||
case RETRO_ENVIRONMENT_SET_SUPPORT_ACHIEVEMENTS:
|
||||
{
|
||||
bool state = *(const bool*)data;
|
||||
RARCH_LOG("Environ SET_SUPPORT_ACHIEVEMENTS: %s.\n", state ? "yes" : "no");
|
||||
cheevos_set_support_cheevos(state);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Private extensions for internal use, not part of libretro API. */
|
||||
/* None yet. */
|
||||
|
@ -946,6 +946,15 @@ struct retro_hw_render_interface
|
||||
* the contents of the HW_RENDER_INTERFACE are invalidated.
|
||||
*/
|
||||
|
||||
#define RETRO_ENVIRONMENT_SET_SUPPORT_ACHIEVEMENTS (42 | RETRO_ENVIRONMENT_EXPERIMENTAL)
|
||||
/* const bool * --
|
||||
* If true, the libretro implementation supports achievements
|
||||
* either via memory descriptors set with RETRO_ENVIRONMENT_SET_MEMORY_MAPS
|
||||
* or via retro_get_memory_data/retro_get_memory_size.
|
||||
*
|
||||
* This must be called before the first call to retro_run.
|
||||
*/
|
||||
|
||||
#define RETRO_MEMDESC_CONST (1 << 0) /* The frontend will never change this memory area once retro_load_game has returned. */
|
||||
#define RETRO_MEMDESC_BIGENDIAN (1 << 1) /* The memory area contains big endian data. Default is little endian. */
|
||||
#define RETRO_MEMDESC_ALIGN_2 (1 << 16) /* All memory access in this area is aligned to their own size, or 2, whichever is smaller. */
|
||||
|
Loading…
x
Reference in New Issue
Block a user