mirror of
https://github.com/libretro/RetroArch
synced 2025-01-30 12:32:52 +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(
|
static size_t cheevos_eval_md5(
|
||||||
const struct retro_game_info *info,
|
const struct retro_game_info *info,
|
||||||
|
size_t offset,
|
||||||
|
size_t max_size,
|
||||||
MD5_CTX *ctx)
|
MD5_CTX *ctx)
|
||||||
{
|
{
|
||||||
MD5_Init(ctx);
|
MD5_Init(ctx);
|
||||||
|
|
||||||
if (info->data)
|
if (info->data)
|
||||||
{
|
{
|
||||||
MD5_Update(ctx, info->data, info->size);
|
if (max_size == 0)
|
||||||
return info->size;
|
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
|
else
|
||||||
{
|
{
|
||||||
RFILE *file = filestream_open(info->path, RFILE_MODE_READ, 0);
|
RFILE *file = filestream_open(info->path, RFILE_MODE_READ, 0);
|
||||||
|
filestream_seek(file, offset, SEEK_SET);
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
|
|
||||||
if (!file)
|
if (!file)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
if (max_size == 0)
|
||||||
|
max_size = (size_t)-1;
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
uint8_t buffer[4096];
|
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,
|
ssize_t num_read = filestream_read(file,
|
||||||
(void*)buffer, sizeof(buffer));
|
(void*)buffer, to_read);
|
||||||
|
|
||||||
if (num_read <= 0)
|
if (num_read <= 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
MD5_Update(ctx, (void*)buffer, num_read);
|
MD5_Update(ctx, (void*)buffer, num_read);
|
||||||
size += num_read;
|
size += num_read;
|
||||||
|
max_size -= num_read;
|
||||||
}
|
}
|
||||||
|
|
||||||
filestream_close(file);
|
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];
|
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);
|
ssize_t len = sizeof(buffer);
|
||||||
|
|
||||||
if (len > fill)
|
if (len > size)
|
||||||
len = fill;
|
len = size;
|
||||||
|
|
||||||
MD5_Update(ctx, (void*)buffer, len);
|
MD5_Update(ctx, (void*)buffer, len);
|
||||||
fill -= len;
|
size -= len;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1872,7 +1889,7 @@ static unsigned cheevos_find_game_id_generic(
|
|||||||
MD5_CTX ctx;
|
MD5_CTX ctx;
|
||||||
retro_time_t to;
|
retro_time_t to;
|
||||||
uint8_t hash[16];
|
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';
|
hash[0] = '\0';
|
||||||
|
|
||||||
@ -1890,23 +1907,19 @@ static unsigned cheevos_find_game_id_snes(
|
|||||||
retro_time_t timeout)
|
retro_time_t timeout)
|
||||||
{
|
{
|
||||||
MD5_CTX ctx;
|
MD5_CTX ctx;
|
||||||
retro_time_t to;
|
|
||||||
uint8_t hash[16];
|
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 (count == 0)
|
||||||
|
|
||||||
if (!size)
|
|
||||||
{
|
{
|
||||||
MD5_Final(hash, &ctx);
|
MD5_Final(hash, &ctx);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
cheevos_fill_md5(size, CHEEVOS_EIGHT_MB, &ctx);
|
cheevos_fill_md5(CHEEVOS_EIGHT_MB - count, 0, &ctx);
|
||||||
MD5_Final(hash, &ctx);
|
MD5_Final(hash, &ctx);
|
||||||
|
|
||||||
to = timeout;
|
return cheevos_get_game_id(hash, &timeout);
|
||||||
return cheevos_get_game_id(hash, &to);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned cheevos_find_game_id_genesis(
|
static unsigned cheevos_find_game_id_genesis(
|
||||||
@ -1914,31 +1927,30 @@ static unsigned cheevos_find_game_id_genesis(
|
|||||||
{
|
{
|
||||||
MD5_CTX ctx;
|
MD5_CTX ctx;
|
||||||
uint8_t hash[16];
|
uint8_t hash[16];
|
||||||
retro_time_t to;
|
size_t count = cheevos_eval_md5(info, 0, 0, &ctx);
|
||||||
size_t size = cheevos_eval_md5(info, &ctx);
|
|
||||||
|
|
||||||
if (!size)
|
if (count == 0)
|
||||||
{
|
{
|
||||||
MD5_Final(hash, &ctx);
|
MD5_Final(hash, &ctx);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
cheevos_fill_md5(size, CHEEVOS_SIX_MB, &ctx);
|
cheevos_fill_md5(CHEEVOS_SIX_MB - count, 0, &ctx);
|
||||||
MD5_Final(hash, &ctx);
|
MD5_Final(hash, &ctx);
|
||||||
|
|
||||||
to = timeout;
|
return cheevos_get_game_id(hash, &timeout);
|
||||||
return cheevos_get_game_id(hash, &to);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned cheevos_find_game_id_nes(
|
static unsigned cheevos_find_game_id_nes(
|
||||||
const struct retro_game_info *info,
|
const struct retro_game_info *info,
|
||||||
retro_time_t timeout)
|
retro_time_t timeout)
|
||||||
{
|
{
|
||||||
static int not_power2[] =
|
/* Note about the references to the FCEU emulator below. There is no
|
||||||
{
|
* core-specific code in this function, it's rather Retro Achievements
|
||||||
53, 198, 228
|
* 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
|
struct
|
||||||
{
|
{
|
||||||
uint8_t id[4]; /* NES^Z */
|
uint8_t id[4]; /* NES^Z */
|
||||||
@ -1949,16 +1961,15 @@ static unsigned cheevos_find_game_id_nes(
|
|||||||
uint8_t reserve[8];
|
uint8_t reserve[8];
|
||||||
} header;
|
} header;
|
||||||
|
|
||||||
size_t rom_size;
|
size_t rom_size, offset, count;
|
||||||
MD5_CTX ctx;
|
MD5_CTX ctx;
|
||||||
uint8_t hash[16];
|
uint8_t hash[16];
|
||||||
retro_time_t to;
|
|
||||||
|
|
||||||
unsigned bytes;
|
size_t bytes;
|
||||||
|
RFILE *file;
|
||||||
ssize_t num_read;
|
ssize_t num_read;
|
||||||
int i, mapper_no;
|
int mapper_no;
|
||||||
bool round = true;
|
bool round;
|
||||||
uint8_t *data;
|
|
||||||
|
|
||||||
if (info->data)
|
if (info->data)
|
||||||
{
|
{
|
||||||
@ -1969,8 +1980,7 @@ static unsigned cheevos_find_game_id_nes(
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ssize_t num_read;
|
file = filestream_open(info->path, RFILE_MODE_READ, 0);
|
||||||
RFILE *file = filestream_open(info->path, RFILE_MODE_READ, 0);
|
|
||||||
|
|
||||||
if (!file)
|
if (!file)
|
||||||
return 0;
|
return 0;
|
||||||
@ -1993,83 +2003,27 @@ static unsigned cheevos_find_game_id_nes(
|
|||||||
else
|
else
|
||||||
rom_size = 256;
|
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 */
|
/* from FCEU core - compute size using the cart mapper */
|
||||||
mapper_no = (header.rom_type >> 4);
|
mapper_no = (header.rom_type >> 4) | (header.rom_type2 & 0xF0);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/* 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;
|
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);
|
MD5_Init(&ctx);
|
||||||
|
count = cheevos_eval_md5(info, offset, 0x4000 * bytes, &ctx);
|
||||||
if (info->data)
|
count = 0x4000 * bytes - count;
|
||||||
{
|
cheevos_fill_md5(count, 0xff, &ctx);
|
||||||
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);
|
|
||||||
MD5_Final(hash, &ctx);
|
MD5_Final(hash, &ctx);
|
||||||
free(data);
|
|
||||||
|
|
||||||
to = timeout;
|
return cheevos_get_game_id(hash, &timeout);
|
||||||
return cheevos_get_game_id(hash, &to);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cheevos_load(const void *data)
|
bool cheevos_load(const void *data)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user