mirror of
https://github.com/libretro/RetroArch
synced 2025-01-29 18:32:44 +00:00
Avoid allocating memory to compute the hash for NES ROMs when the core needs fullpath (fixed).
This commit is contained in:
parent
58b3ef3ba4
commit
3d2cdbde98
172
cheevos.c
172
cheevos.c
@ -1811,34 +1811,52 @@ static INLINE unsigned cheevos_next_power_of_2(unsigned n)
|
||||
|
||||
static size_t cheevos_eval_md5(
|
||||
const struct retro_game_info *info,
|
||||
size_t offset,
|
||||
size_t max_size,
|
||||
MD5_CTX *ctx)
|
||||
{
|
||||
MD5_Init(ctx);
|
||||
|
||||
if (info->data)
|
||||
{
|
||||
MD5_Update(ctx, info->data, info->size);
|
||||
return info->size;
|
||||
if (max_size == 0)
|
||||
max_size = info->size;
|
||||
|
||||
if (info->size - offset < max_size)
|
||||
max_size = info->size - offset;
|
||||
|
||||
MD5_Update(ctx, (void*)(uint8_t*)info->data + offset, max_size);
|
||||
return max_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
RFILE *file = filestream_open(info->path, RFILE_MODE_READ, 0);
|
||||
filestream_seek(file, offset, SEEK_SET);
|
||||
size_t size = 0;
|
||||
|
||||
if (!file)
|
||||
return 0;
|
||||
|
||||
if (max_size == 0)
|
||||
max_size = (size_t)-1;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
uint8_t buffer[4096];
|
||||
size_t to_read = sizeof(buffer);
|
||||
|
||||
if (to_read > max_size)
|
||||
to_read = max_size;
|
||||
|
||||
ssize_t num_read = filestream_read(file,
|
||||
(void*)buffer, sizeof(buffer));
|
||||
(void*)buffer, to_read);
|
||||
|
||||
if (num_read <= 0)
|
||||
break;
|
||||
|
||||
MD5_Update(ctx, (void*)buffer, num_read);
|
||||
size += num_read;
|
||||
max_size -= num_read;
|
||||
}
|
||||
|
||||
filestream_close(file);
|
||||
@ -1846,22 +1864,21 @@ static size_t cheevos_eval_md5(
|
||||
}
|
||||
}
|
||||
|
||||
static void cheevos_fill_md5(size_t size, size_t total, MD5_CTX *ctx)
|
||||
static void cheevos_fill_md5(size_t size, char fill, MD5_CTX *ctx)
|
||||
{
|
||||
char buffer[4096];
|
||||
ssize_t fill = total - size;
|
||||
|
||||
buffer[0] = '\0';
|
||||
memset((void*)buffer, fill, sizeof(buffer));
|
||||
|
||||
while (fill > 0)
|
||||
while (size > 0)
|
||||
{
|
||||
ssize_t len = sizeof(buffer);
|
||||
|
||||
if (len > fill)
|
||||
len = fill;
|
||||
if (len > size)
|
||||
len = size;
|
||||
|
||||
MD5_Update(ctx, (void*)buffer, len);
|
||||
fill -= len;
|
||||
size -= len;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1872,7 +1889,7 @@ static unsigned cheevos_find_game_id_generic(
|
||||
MD5_CTX ctx;
|
||||
retro_time_t to;
|
||||
uint8_t hash[16];
|
||||
size_t size = cheevos_eval_md5(info, &ctx);
|
||||
size_t size = cheevos_eval_md5(info, 0, 0, &ctx);
|
||||
|
||||
hash[0] = '\0';
|
||||
|
||||
@ -1890,23 +1907,19 @@ static unsigned cheevos_find_game_id_snes(
|
||||
retro_time_t timeout)
|
||||
{
|
||||
MD5_CTX ctx;
|
||||
retro_time_t to;
|
||||
uint8_t hash[16];
|
||||
size_t size = cheevos_eval_md5(info, &ctx);
|
||||
size_t count = cheevos_eval_md5(info, 0, 0, &ctx);
|
||||
|
||||
hash[0] = '\0';
|
||||
|
||||
if (!size)
|
||||
if (count == 0)
|
||||
{
|
||||
MD5_Final(hash, &ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
cheevos_fill_md5(size, CHEEVOS_EIGHT_MB, &ctx);
|
||||
cheevos_fill_md5(CHEEVOS_EIGHT_MB - count, 0, &ctx);
|
||||
MD5_Final(hash, &ctx);
|
||||
|
||||
to = timeout;
|
||||
return cheevos_get_game_id(hash, &to);
|
||||
return cheevos_get_game_id(hash, &timeout);
|
||||
}
|
||||
|
||||
static unsigned cheevos_find_game_id_genesis(
|
||||
@ -1914,31 +1927,30 @@ static unsigned cheevos_find_game_id_genesis(
|
||||
{
|
||||
MD5_CTX ctx;
|
||||
uint8_t hash[16];
|
||||
retro_time_t to;
|
||||
size_t size = cheevos_eval_md5(info, &ctx);
|
||||
size_t count = cheevos_eval_md5(info, 0, 0, &ctx);
|
||||
|
||||
if (!size)
|
||||
if (count == 0)
|
||||
{
|
||||
MD5_Final(hash, &ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
cheevos_fill_md5(size, CHEEVOS_SIX_MB, &ctx);
|
||||
cheevos_fill_md5(CHEEVOS_SIX_MB - count, 0, &ctx);
|
||||
MD5_Final(hash, &ctx);
|
||||
|
||||
to = timeout;
|
||||
return cheevos_get_game_id(hash, &to);
|
||||
return cheevos_get_game_id(hash, &timeout);
|
||||
}
|
||||
|
||||
static unsigned cheevos_find_game_id_nes(
|
||||
const struct retro_game_info *info,
|
||||
retro_time_t timeout)
|
||||
{
|
||||
static int not_power2[] =
|
||||
{
|
||||
53, 198, 228
|
||||
};
|
||||
|
||||
/* Note about the references to the FCEU emulator below. There is no
|
||||
* core-specific code in this function, it's rather Retro Achievements
|
||||
* specific code that must be followed to the letter so we compute
|
||||
* the correct ROM hash. Retro Achievements does indeed use some
|
||||
* FCEU related method to compute the hash, since its NES emulator
|
||||
* is based on it. */
|
||||
struct
|
||||
{
|
||||
uint8_t id[4]; /* NES^Z */
|
||||
@ -1949,16 +1961,15 @@ static unsigned cheevos_find_game_id_nes(
|
||||
uint8_t reserve[8];
|
||||
} header;
|
||||
|
||||
size_t rom_size;
|
||||
size_t rom_size, offset, count;
|
||||
MD5_CTX ctx;
|
||||
uint8_t hash[16];
|
||||
retro_time_t to;
|
||||
|
||||
unsigned bytes;
|
||||
size_t bytes;
|
||||
RFILE *file;
|
||||
ssize_t num_read;
|
||||
int i, mapper_no;
|
||||
bool round = true;
|
||||
uint8_t *data;
|
||||
int mapper_no;
|
||||
bool round;
|
||||
|
||||
if (info->data)
|
||||
{
|
||||
@ -1969,8 +1980,7 @@ static unsigned cheevos_find_game_id_nes(
|
||||
}
|
||||
else
|
||||
{
|
||||
ssize_t num_read;
|
||||
RFILE *file = filestream_open(info->path, RFILE_MODE_READ, 0);
|
||||
file = filestream_open(info->path, RFILE_MODE_READ, 0);
|
||||
|
||||
if (!file)
|
||||
return 0;
|
||||
@ -1993,83 +2003,27 @@ static unsigned cheevos_find_game_id_nes(
|
||||
else
|
||||
rom_size = 256;
|
||||
|
||||
data = (uint8_t *) malloc(rom_size << 14);
|
||||
|
||||
if (!data)
|
||||
return 0;
|
||||
|
||||
/* from FCEU core - need it for a correctly md5 sum */
|
||||
memset(data, 0xFF, rom_size << 14);
|
||||
|
||||
/* from FCEU core - compute size using the cart mapper */
|
||||
mapper_no = (header.rom_type >> 4);
|
||||
mapper_no |= (header.rom_type2 & 0xF0);
|
||||
|
||||
for (i = 0; i != ARRAY_SIZE(not_power2); ++i)
|
||||
{
|
||||
/* for games not to the power of 2, so we just read enough
|
||||
* PRG rom from it, but we have to keep ROM_size to the power of 2
|
||||
* since PRGCartMapping wants ROM_size to be to the power of 2
|
||||
* so instead if not to power of 2, we just use head.ROM_size when
|
||||
* we use FCEU_read. */
|
||||
if (not_power2[i] == mapper_no)
|
||||
{
|
||||
round = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
mapper_no = (header.rom_type >> 4) | (header.rom_type2 & 0xF0);
|
||||
|
||||
/* for games not to the power of 2, so we just read enough
|
||||
* PRG rom from it, but we have to keep ROM_size to the power of 2
|
||||
* since PRGCartMapping wants ROM_size to be to the power of 2
|
||||
* so instead if not to power of 2, we just use head.ROM_size when
|
||||
* we use FCEU_read. */
|
||||
round = mapper_no != 53 && mapper_no != 198 && mapper_no != 228;
|
||||
bytes = (round) ? rom_size : header.rom_size;
|
||||
|
||||
/* from FCEU core - check if Trainer included in ROM data */
|
||||
offset = sizeof(header) + (header.rom_type & 4 ? sizeof(header) : 0);
|
||||
|
||||
MD5_Init(&ctx);
|
||||
|
||||
if (info->data)
|
||||
{
|
||||
size_t offset = sizeof(header);
|
||||
size_t count;
|
||||
|
||||
/* from FCEU core - check if Trainer included in ROM data */
|
||||
if (header.rom_type & 4)
|
||||
offset += sizeof(header);
|
||||
|
||||
count = info->size - offset;
|
||||
|
||||
if (count > 0x4000 * bytes)
|
||||
count = 0x4000 * bytes;
|
||||
|
||||
memcpy(data, (void*)(uint8_t*)info->data + offset, count);
|
||||
}
|
||||
else
|
||||
{
|
||||
RFILE *file = filestream_open(info->path, RFILE_MODE_READ, 0);
|
||||
|
||||
if (!file)
|
||||
{
|
||||
free(data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
filestream_seek(file, sizeof(header), SEEK_SET);
|
||||
|
||||
/* from FCEU core - check if Trainer included in ROM data */
|
||||
if (header.rom_type & 4)
|
||||
filestream_seek(file, sizeof(header), SEEK_CUR);
|
||||
|
||||
num_read = filestream_read(file, (void*)data, 0x4000 * bytes );
|
||||
filestream_close(file);
|
||||
|
||||
if (num_read <= 0)
|
||||
{
|
||||
free(data);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
MD5_Update(&ctx, (void*) data, rom_size << 14);
|
||||
count = cheevos_eval_md5(info, offset, 0x4000 * bytes, &ctx);
|
||||
count = 0x4000 * bytes - count;
|
||||
cheevos_fill_md5(count, 0xff, &ctx);
|
||||
MD5_Final(hash, &ctx);
|
||||
free(data);
|
||||
|
||||
to = timeout;
|
||||
return cheevos_get_game_id(hash, &to);
|
||||
return cheevos_get_game_id(hash, &timeout);
|
||||
}
|
||||
|
||||
bool cheevos_load(const void *data)
|
||||
|
Loading…
x
Reference in New Issue
Block a user