support for hashing buffered NDS ROMs (#13365)

This commit is contained in:
Jamiras 2021-12-16 21:42:29 -07:00 committed by GitHub
parent 45f2f74d45
commit cd50a51f3e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -711,86 +711,7 @@ static void rc_hash_n64_to_z64(uint8_t* buffer, const uint8_t* stop)
}
}
static int rc_hash_n64(char hash[33], const uint8_t* buffer, size_t buffer_size)
{
uint8_t* swapbuffer;
uint8_t* stop;
const size_t swapbuffer_size = 65536;
md5_state_t md5;
size_t remaining;
int is_v64;
if (buffer[0] == 0x80) /* z64 format (big endian [native]) */
{
return rc_hash_buffer(hash, buffer, buffer_size);
}
else if (buffer[0] == 0x37) /* v64 format (byteswapped) */
{
rc_hash_verbose("converting v64 to z64");
is_v64 = 1;
}
else if (buffer[0] == 0x40) /* n64 format (little endian) */
{
rc_hash_verbose("converting n64 to z64");
is_v64 = 0;
}
else
{
rc_hash_verbose("Not a Nintendo 64 ROM");
return 0;
}
swapbuffer = (uint8_t*)malloc(swapbuffer_size);
if (!swapbuffer)
return rc_hash_error("Could not allocate temporary buffer");
stop = swapbuffer + swapbuffer_size;
md5_init(&md5);
if (buffer_size > MAX_BUFFER_SIZE)
remaining = MAX_BUFFER_SIZE;
else
remaining = (size_t)buffer_size;
if (verbose_message_callback)
{
char message[64];
snprintf(message, sizeof(message), "Hashing %u bytes", (unsigned)remaining);
verbose_message_callback(message);
}
while (remaining >= swapbuffer_size)
{
memcpy(swapbuffer, buffer, swapbuffer_size);
if (is_v64)
rc_hash_v64_to_z64(swapbuffer, stop);
else
rc_hash_n64_to_z64(swapbuffer, stop);
md5_append(&md5, swapbuffer, (int)swapbuffer_size);
buffer += swapbuffer_size;
remaining -= swapbuffer_size;
}
if (remaining > 0)
{
memcpy(swapbuffer, buffer, remaining);
stop = swapbuffer + remaining;
if (is_v64)
rc_hash_v64_to_z64(swapbuffer, stop);
else
rc_hash_n64_to_z64(swapbuffer, stop);
md5_append(&md5, swapbuffer, (int)remaining);
}
free(swapbuffer);
return rc_hash_finalize(&md5, hash);
}
static int rc_hash_n64_file(char hash[33], const char* path)
static int rc_hash_n64(char hash[33], const char* path)
{
uint8_t* buffer;
uint8_t* stop;
@ -1547,6 +1468,83 @@ static int rc_hash_snes(char hash[33], const uint8_t* buffer, size_t buffer_size
return rc_hash_buffer(hash, buffer, buffer_size);
}
struct rc_buffered_file
{
const uint8_t* read_ptr;
const uint8_t* data;
size_t data_size;
};
static struct rc_buffered_file rc_buffered_file;
static void* rc_file_open_buffered_file(const char* path)
{
struct rc_buffered_file* handle = (struct rc_buffered_file*)malloc(sizeof(struct rc_buffered_file));
memcpy(handle, &rc_buffered_file, sizeof(rc_buffered_file));
return handle;
}
void rc_file_seek_buffered_file(void* file_handle, int64_t offset, int origin)
{
struct rc_buffered_file* buffered_file = (struct rc_buffered_file*)file_handle;
switch (origin)
{
case SEEK_SET: buffered_file->read_ptr = buffered_file->data + offset; break;
case SEEK_CUR: buffered_file->read_ptr += offset; break;
case SEEK_END: buffered_file->read_ptr = buffered_file->data + buffered_file->data_size - offset; break;
}
if (buffered_file->read_ptr < buffered_file->data)
buffered_file->read_ptr = buffered_file->data;
else if (buffered_file->read_ptr > buffered_file->data + buffered_file->data_size)
buffered_file->read_ptr = buffered_file->data + buffered_file->data_size;
}
int64_t rc_file_tell_buffered_file(void* file_handle)
{
struct rc_buffered_file* buffered_file = (struct rc_buffered_file*)file_handle;
return (buffered_file->read_ptr - buffered_file->data);
}
size_t rc_file_read_buffered_file(void* file_handle, void* buffer, size_t requested_bytes)
{
struct rc_buffered_file* buffered_file = (struct rc_buffered_file*)file_handle;
const int64_t remaining = buffered_file->data_size - (buffered_file->read_ptr - buffered_file->data);
if ((int)requested_bytes > remaining)
requested_bytes = (int)remaining;
memcpy(buffer, buffered_file->read_ptr, requested_bytes);
buffered_file->read_ptr += requested_bytes;
return requested_bytes;
}
void rc_file_close_buffered_file(void* file_handle)
{
free(file_handle);
}
static int rc_hash_file_from_buffer(char hash[33], int console_id, const uint8_t* buffer, size_t buffer_size)
{
struct rc_hash_filereader filereader_funcs_old;
int result;
memcpy(&filereader_funcs_old, &filereader_funcs, sizeof(filereader_funcs));
filereader_funcs.open = rc_file_open_buffered_file;
filereader_funcs.close = rc_file_close_buffered_file;
filereader_funcs.read = rc_file_read_buffered_file;
filereader_funcs.seek = rc_file_seek_buffered_file;
filereader_funcs.tell = rc_file_tell_buffered_file;
rc_buffered_file.data = rc_buffered_file.read_ptr = buffer;
rc_buffered_file.data_size = buffer_size;
result = rc_hash_generate_from_file(hash, console_id, "[buffered file]");
memcpy(&filereader_funcs, &filereader_funcs_old, sizeof(filereader_funcs));
return result;
}
int rc_hash_generate_from_buffer(char hash[33], int console_id, const uint8_t* buffer, size_t buffer_size)
{
switch (console_id)
@ -1593,14 +1591,15 @@ int rc_hash_generate_from_buffer(char hash[33], int console_id, const uint8_t* b
case RC_CONSOLE_NINTENDO:
return rc_hash_nes(hash, buffer, buffer_size);
case RC_CONSOLE_NINTENDO_64:
return rc_hash_n64(hash, buffer, buffer_size);
case RC_CONSOLE_PC_ENGINE: /* NOTE: does not support PCEngine CD */
return rc_hash_pce(hash, buffer, buffer_size);
case RC_CONSOLE_SUPER_NINTENDO:
return rc_hash_snes(hash, buffer, buffer_size);
case RC_CONSOLE_NINTENDO_64:
case RC_CONSOLE_NINTENDO_DS:
return rc_hash_file_from_buffer(hash, console_id, buffer, buffer_size);
}
}
@ -1892,7 +1891,7 @@ int rc_hash_generate_from_file(char hash[33], int console_id, const char* path)
return rc_hash_arcade(hash, path);
case RC_CONSOLE_NINTENDO_64:
return rc_hash_n64_file(hash, path);
return rc_hash_n64(hash, path);
case RC_CONSOLE_NINTENDO_DS:
return rc_hash_nintendo_ds(hash, path);