mirror of
https://github.com/libretro/RetroArch
synced 2025-02-20 15:40:44 +00:00
Backport leiradel PR - 'support need_fullpath; changed how md5 hashes
are tested'
This commit is contained in:
parent
869ebb3733
commit
fa9ef5b021
160
cheevos.c
160
cheevos.c
@ -18,6 +18,7 @@
|
||||
|
||||
#include <formats/jsonsax.h>
|
||||
#include <rhash.h>
|
||||
#include <retro_file.h>
|
||||
#include <retro_log.h>
|
||||
#include <rthreads/async_job.h>
|
||||
|
||||
@ -31,7 +32,7 @@
|
||||
|
||||
enum
|
||||
{
|
||||
CHEEVOS_VAR_SIZE_BIT_0,
|
||||
CHEEVOS_VAR_SIZE_BIT_0 = 0,
|
||||
CHEEVOS_VAR_SIZE_BIT_1,
|
||||
CHEEVOS_VAR_SIZE_BIT_2,
|
||||
CHEEVOS_VAR_SIZE_BIT_3,
|
||||
@ -51,7 +52,7 @@ enum
|
||||
|
||||
enum
|
||||
{
|
||||
CHEEVOS_VAR_TYPE_ADDRESS, /* compare to the value of a live address in RAM */
|
||||
CHEEVOS_VAR_TYPE_ADDRESS = 0, /* compare to the value of a live address in RAM */
|
||||
CHEEVOS_VAR_TYPE_VALUE_COMP, /* a number. assume 32 bit */
|
||||
CHEEVOS_VAR_TYPE_DELTA_MEM, /* the value last known at this address. */
|
||||
CHEEVOS_VAR_TYPE_DYNAMIC_VAR, /* a custom user-set variable */
|
||||
@ -61,7 +62,7 @@ enum
|
||||
|
||||
enum
|
||||
{
|
||||
CHEEVOS_COND_OP_EQUALS,
|
||||
CHEEVOS_COND_OP_EQUALS = 0,
|
||||
CHEEVOS_COND_OP_LESS_THAN,
|
||||
CHEEVOS_COND_OP_LESS_THAN_OR_EQUAL,
|
||||
CHEEVOS_COND_OP_GREATER_THAN,
|
||||
@ -73,7 +74,7 @@ enum
|
||||
|
||||
enum
|
||||
{
|
||||
CHEEVOS_COND_TYPE_STANDARD,
|
||||
CHEEVOS_COND_TYPE_STANDARD = 0,
|
||||
CHEEVOS_COND_TYPE_PAUSE_IF,
|
||||
CHEEVOS_COND_TYPE_RESET_IF,
|
||||
|
||||
@ -1502,51 +1503,126 @@ static int cheevos_deactivate_unlocks(unsigned game_id, retro_time_t *timeout)
|
||||
|
||||
#define CHEEVOS_EIGHT_MB (8 * 1024 * 1024)
|
||||
|
||||
int cheevos_load(const void *data, size_t size)
|
||||
static size_t cheevos_eval_md5(const struct retro_game_info *info, MD5_CTX *ctx)
|
||||
{
|
||||
const char *json;
|
||||
MD5_CTX ctx, saved_ctx;
|
||||
retro_time_t timeout;
|
||||
char buffer[4096];
|
||||
size_t len;
|
||||
unsigned char hash[16];
|
||||
unsigned game_id;
|
||||
MD5_Init(ctx);
|
||||
|
||||
if (info->data)
|
||||
{
|
||||
MD5_Update(ctx, info->data, info->size);
|
||||
return info->size;
|
||||
}
|
||||
else
|
||||
{
|
||||
RFILE *file = retro_fopen(info->path, RFILE_MODE_READ, 0);
|
||||
size_t size = 0;
|
||||
|
||||
if (!file)
|
||||
return 0;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
uint8_t buffer[4096];
|
||||
ssize_t num_read = retro_fread(file, (void*)buffer, sizeof(buffer));
|
||||
|
||||
if (num_read <= 0)
|
||||
break;
|
||||
|
||||
MD5_Update(ctx, (void*)buffer, num_read);
|
||||
size += num_read;
|
||||
}
|
||||
|
||||
retro_fclose(file);
|
||||
return size;
|
||||
}
|
||||
}
|
||||
|
||||
static void cheevos_fill_md5(size_t size, size_t total, MD5_CTX *ctx)
|
||||
{
|
||||
ssize_t fill = total - size;
|
||||
char buffer[4096];
|
||||
|
||||
memset((void*)buffer, 0, sizeof(buffer));
|
||||
|
||||
do
|
||||
{
|
||||
ssize_t len = sizeof(buffer);
|
||||
|
||||
if (len > fill)
|
||||
len = fill;
|
||||
|
||||
MD5_Update(ctx, (void*)buffer, len);
|
||||
fill -= len;
|
||||
}
|
||||
while (fill > 0);
|
||||
}
|
||||
|
||||
typedef unsigned (*cheevos_id_finder_t)(const struct retro_game_info *, retro_time_t);
|
||||
|
||||
static unsigned cheevos_find_game_id_generic(const struct retro_game_info *info, retro_time_t timeout)
|
||||
{
|
||||
MD5_CTX ctx;
|
||||
uint8_t hash[16];
|
||||
retro_time_t to;
|
||||
size_t size;
|
||||
|
||||
size = cheevos_eval_md5(info, &ctx);
|
||||
MD5_Final(hash, &ctx);
|
||||
|
||||
if (!size)
|
||||
return 0;
|
||||
|
||||
to = timeout;
|
||||
return cheevos_get_game_id(hash, &to);
|
||||
}
|
||||
|
||||
static unsigned cheevos_find_game_id_snes(const struct retro_game_info *info, retro_time_t timeout)
|
||||
{
|
||||
MD5_CTX ctx;
|
||||
uint8_t hash[16];
|
||||
retro_time_t to;
|
||||
size_t size;
|
||||
|
||||
size = cheevos_eval_md5(info, &ctx);
|
||||
|
||||
if (!size)
|
||||
{
|
||||
MD5_Final(hash, &ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
cheevos_fill_md5(size, CHEEVOS_EIGHT_MB, &ctx);
|
||||
MD5_Final(hash, &ctx);
|
||||
|
||||
to = timeout;
|
||||
return cheevos_get_game_id(hash, &to);
|
||||
}
|
||||
|
||||
int cheevos_load(const struct retro_game_info *info)
|
||||
{
|
||||
static const cheevos_id_finder_t finders[] =
|
||||
{
|
||||
cheevos_find_game_id_generic,
|
||||
cheevos_find_game_id_snes
|
||||
};
|
||||
|
||||
retro_time_t timeout = 5000000;
|
||||
unsigned game_id = 0;
|
||||
int i;
|
||||
const char *json;
|
||||
|
||||
/* Just return OK if cheevos are disabled. */
|
||||
if (!config_get_ptr()->cheevos.enable)
|
||||
return 0;
|
||||
|
||||
MD5_Init(&ctx);
|
||||
MD5_Update(&ctx, data, size);
|
||||
saved_ctx = ctx;
|
||||
MD5_Final(hash, &ctx);
|
||||
|
||||
timeout = 15000000;
|
||||
game_id = cheevos_get_game_id(hash, &timeout);
|
||||
|
||||
if (!game_id && size < CHEEVOS_EIGHT_MB)
|
||||
|
||||
for (i = 0; i < sizeof(finders) / sizeof(finders[0]); i++)
|
||||
{
|
||||
/* Maybe the content is a SNES game, continue MD5 with zeroes up to 8 MB. */
|
||||
size = CHEEVOS_EIGHT_MB - size;
|
||||
memset((void*)buffer, 0, sizeof(buffer));
|
||||
|
||||
do
|
||||
{
|
||||
len = sizeof(buffer);
|
||||
|
||||
if (len > size)
|
||||
len = size;
|
||||
|
||||
MD5_Update(&saved_ctx, (void*)buffer, len);
|
||||
size -= len;
|
||||
}
|
||||
while (size);
|
||||
|
||||
MD5_Final(hash, &saved_ctx);
|
||||
|
||||
game_id = cheevos_get_game_id(hash, &timeout);
|
||||
game_id = finders[i](info, 5000000);
|
||||
|
||||
if (game_id)
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if (game_id)
|
||||
{
|
||||
cheevos_playing_activity(game_id, &timeout);
|
||||
|
@ -19,6 +19,8 @@
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "libretro.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int cheats_are_enabled;
|
||||
@ -27,7 +29,7 @@ typedef struct
|
||||
|
||||
extern cheevos_globals_t cheevos_globals;
|
||||
|
||||
int cheevos_load(const void *data, size_t size);
|
||||
int cheevos_load(const struct retro_game_info *info);
|
||||
|
||||
void cheevos_test(void);
|
||||
|
||||
|
@ -518,11 +518,8 @@ static bool load_content(const struct retro_subsystem_info *special,
|
||||
#ifdef HAVE_CHEEVOS
|
||||
/* Load the achievements into memory if the game has content. */
|
||||
|
||||
if (*content->elems[0].data)
|
||||
{
|
||||
cheevos_globals.cheats_were_enabled = cheevos_globals.cheats_are_enabled;
|
||||
cheevos_load(info->data, info->size);
|
||||
}
|
||||
cheevos_globals.cheats_were_enabled = cheevos_globals.cheats_are_enabled;
|
||||
cheevos_load(*content->elems[0].data ? info : NULL);
|
||||
#endif
|
||||
|
||||
ret = core.retro_load_game(*content->elems[0].data ? info : NULL);
|
||||
|
Loading…
x
Reference in New Issue
Block a user