Upgrade rcheevos to v10.1.0

This commit is contained in:
Silent
2021-06-21 19:00:14 +02:00
committed by Connor McLaughlin
parent 9d26a85967
commit d567f1e870
29 changed files with 1636 additions and 1399 deletions

View File

@ -8,8 +8,8 @@
/* internal helper functions in hash.c */
extern void* rc_file_open(const char* path);
extern void rc_file_seek(void* file_handle, size_t offset, int origin);
extern size_t rc_file_tell(void* file_handle);
extern void rc_file_seek(void* file_handle, int64_t offset, int origin);
extern int64_t rc_file_tell(void* file_handle);
extern size_t rc_file_read(void* file_handle, void* buffer, int requested_bytes);
extern void rc_file_close(void* file_handle);
extern int rc_hash_error(const char* message);
@ -22,8 +22,8 @@ struct cdrom_t
void* file_handle;
int sector_size;
int sector_header_size;
int first_sector_offset;
int first_sector;
int64_t first_sector_offset;
};
static void cdreader_determine_sector_size(struct cdrom_t* cdrom)
@ -38,13 +38,14 @@ static void cdreader_determine_sector_size(struct cdrom_t* cdrom)
};
unsigned char header[32];
const int toc_sector = 16;
const int64_t toc_sector = 16;
cdrom->sector_size = 0;
cdrom->sector_header_size = 0;
rc_file_seek(cdrom->file_handle, toc_sector * 2352 + cdrom->first_sector_offset, SEEK_SET);
rc_file_read(cdrom->file_handle, header, sizeof(header));
if (rc_file_read(cdrom->file_handle, header, sizeof(header)) < sizeof(header))
return;
if (memcmp(header, sync_pattern, 12) == 0)
{
@ -219,9 +220,9 @@ static char* cdreader_get_bin_path(const char* cue_path, const char* bin_name)
return bin_filename;
}
static size_t cdreader_get_bin_size(const char* cue_path, const char* bin_name)
static int64_t cdreader_get_bin_size(const char* cue_path, const char* bin_name)
{
size_t size = 0;
int64_t size = 0;
char* bin_filename = cdreader_get_bin_path(cue_path, bin_name);
if (bin_filename)
{
@ -242,7 +243,7 @@ static size_t cdreader_get_bin_size(const char* cue_path, const char* bin_name)
static void* cdreader_open_cue_track(const char* path, uint32_t track)
{
void* file_handle;
size_t file_offset = 0;
int64_t file_offset = 0;
char buffer[1024], mode[16];
char* bin_filename;
char file[256];
@ -253,14 +254,14 @@ static void* cdreader_open_cue_track(const char* path, uint32_t track)
int previous_sector_size = 0;
int previous_index_sector_offset = 0;
int previous_track_is_data = 0;
int previous_track_sector_offset = 0;
int64_t previous_track_sector_offset = 0;
char previous_track_mode[16];
int largest_track = 0;
int largest_track_sector_count = 0;
int largest_track_offset = 0;
int64_t largest_track_offset = 0;
char largest_track_mode[16];
char largest_track_file[256];
int offset = 0;
int64_t offset = 0;
int done = 0;
size_t num_read = 0;
struct cdrom_t* cdrom = NULL;
@ -290,7 +291,8 @@ static void* cdreader_open_cue_track(const char* path, uint32_t track)
if (strncasecmp(ptr, "INDEX ", 6) == 0)
{
int m = 0, s = 0, f = 0;
int index, sector_offset;
int index;
int sector_offset;
ptr += 6;
index = atoi(ptr);
@ -336,7 +338,9 @@ static void* cdreader_open_cue_track(const char* path, uint32_t track)
++scan;
*scan = '\0';
snprintf(message, sizeof(message), "Found %s track %d (sector size %d, track starts at %d)", mode, current_track, sector_size, offset);
/* it's undesirable to truncate offset to 32-bits, but %lld isn't defined in c89. */
snprintf(message, sizeof(message), "Found %s track %d (sector size %d, track starts at %d)",
mode, current_track, sector_size, (int)offset);
verbose_message_callback(message);
}
@ -501,7 +505,8 @@ static void* cdreader_open_cue_track(const char* path, uint32_t track)
if (verbose_message_callback)
{
if (cdrom->first_sector_offset)
snprintf((char*)buffer, sizeof(buffer), "Opened track %d (sector size %d, track starts at %d)", track, cdrom->sector_size, cdrom->first_sector_offset);
snprintf((char*)buffer, sizeof(buffer), "Opened track %d (sector size %d, track starts at %d)",
track, cdrom->sector_size, (int)cdrom->first_sector_offset);
else
snprintf((char*)buffer, sizeof(buffer), "Opened track %d (sector size %d)", track, cdrom->sector_size);
@ -531,7 +536,7 @@ static void* cdreader_open_gdi_track(const char* path, uint32_t track)
char mode[16] = "MODE1/";
char sector_size[16];
char file[256];
size_t track_size;
int64_t track_size;
int track_type;
char* bin_path = "";
uint32_t current_track = 0;
@ -539,14 +544,14 @@ static void* cdreader_open_gdi_track(const char* path, uint32_t track)
int lba = 0;
uint32_t largest_track = 0;
size_t largest_track_size = 0;
int64_t largest_track_size = 0;
char largest_track_file[256];
char largest_track_sector_size[16];
int largest_track_lba = 0;
int found = 0;
size_t num_read = 0;
size_t file_offset = 0;
int64_t file_offset = 0;
struct cdrom_t* cdrom = NULL;
file_handle = rc_file_open(path);
@ -584,6 +589,9 @@ static void* cdreader_open_gdi_track(const char* path, uint32_t track)
++ptr;
/* line format: [trackid] [lba] [type] [sectorsize] [file] [?] */
while (isspace(*ptr))
++ptr;
current_track = (uint32_t)atoi(ptr);
if (track && current_track != track)
continue;
@ -592,22 +600,34 @@ static void* cdreader_open_gdi_track(const char* path, uint32_t track)
++ptr;
++ptr;
while (isspace(*ptr))
++ptr;
lba = atoi(ptr);
while (isdigit(*ptr))
++ptr;
++ptr;
while (isspace(*ptr))
++ptr;
track_type = atoi(ptr);
while (isdigit(*ptr))
++ptr;
++ptr;
while (isspace(*ptr))
++ptr;
ptr2 = sector_size;
while (isdigit(*ptr))
*ptr2++ = *ptr++;
*ptr2 = '\0';
++ptr;
while (isspace(*ptr))
++ptr;
ptr2 = file;
if (*ptr == '\"')
{
@ -698,6 +718,8 @@ static void* cdreader_open_gdi_track(const char* path, uint32_t track)
cdrom = NULL;
}
free(bin_path);
return cdrom;
}
@ -717,7 +739,7 @@ static void* cdreader_open_track(const char* path, uint32_t track)
static size_t cdreader_read_sector(void* track_handle, uint32_t sector, void* buffer, size_t requested_bytes)
{
size_t sector_start;
int64_t sector_start;
size_t num_read, total_read = 0;
uint8_t* buffer_ptr = (uint8_t*)buffer;
@ -725,7 +747,7 @@ static size_t cdreader_read_sector(void* track_handle, uint32_t sector, void* bu
if (!cdrom)
return 0;
sector_start = sector * cdrom->sector_size + cdrom->sector_header_size + cdrom->first_sector_offset;
sector_start = (int64_t)sector * cdrom->sector_size + cdrom->sector_header_size + cdrom->first_sector_offset;
while (requested_bytes > 2048)
{

View File

@ -4,6 +4,7 @@
#include "md5.h"
#include <stdio.h>
#include <ctype.h>
/* arbitrary limit to prevent allocating and hashing large files */
@ -50,14 +51,27 @@ static void* filereader_open(const char* path)
return fopen(path, "rb");
}
static void filereader_seek(void* file_handle, size_t offset, int origin)
static void filereader_seek(void* file_handle, int64_t offset, int origin)
{
fseek((FILE*)file_handle, (long)offset, origin);
#if defined(_WIN32)
_fseeki64((FILE*)file_handle, offset, origin);
#elif defined(_LARGEFILE64_SOURCE)
fseeko64((FILE*)file_handle, offset, origin);
#else
#pragma message("Using generic fseek may fail for large files")
fseek((FILE*)file_handle, offset, origin);
#endif
}
static size_t filereader_tell(void* file_handle)
static int64_t filereader_tell(void* file_handle)
{
#if defined(_WIN32)
return _ftelli64((FILE*)file_handle);
#elif defined(_LARGEFILE64_SOURCE)
return ftello64((FILE*)file_handle);
#else
return ftell((FILE*)file_handle);
#endif
}
static size_t filereader_read(void* file_handle, void* buffer, size_t requested_bytes)
@ -118,13 +132,13 @@ void* rc_file_open(const char* path)
return handle;
}
void rc_file_seek(void* file_handle, size_t offset, int origin)
void rc_file_seek(void* file_handle, int64_t offset, int origin)
{
if (filereader)
filereader->seek(file_handle, offset, origin);
}
size_t rc_file_tell(void* file_handle)
int64_t rc_file_tell(void* file_handle)
{
return (filereader) ? filereader->tell(file_handle) : 0;
}
@ -367,6 +381,50 @@ static int rc_hash_buffer(char hash[33], uint8_t* buffer, size_t buffer_size)
return rc_hash_finalize(&md5, hash);
}
static int rc_hash_cd_file(md5_state_t* md5, void* track_handle, uint32_t sector, const char* name, unsigned size, const char* description)
{
uint8_t buffer[2048];
size_t num_read;
if ((num_read = rc_cd_read_sector(track_handle, sector, buffer, sizeof(buffer))) < sizeof(buffer))
{
char message[128];
snprintf(message, sizeof(message), "Could not read %s", description);
return rc_hash_error(message);
}
if (size > MAX_BUFFER_SIZE)
size = MAX_BUFFER_SIZE;
if (verbose_message_callback)
{
char message[128];
if (name)
snprintf(message, sizeof(message), "Hashing %s title (%u bytes) and contents (%u bytes) ", name, (unsigned)strlen(name), size);
else
snprintf(message, sizeof(message), "Hashing %s contents (%u bytes)", description, size);
verbose_message_callback(message);
}
do
{
md5_append(md5, buffer, (int)num_read);
size -= (unsigned)num_read;
if (size == 0)
break;
++sector;
if (size >= sizeof(buffer))
num_read = rc_cd_read_sector(track_handle, sector, buffer, sizeof(buffer));
else
num_read = rc_cd_read_sector(track_handle, sector, buffer, size);
} while (num_read > 0);
return 1;
}
static int rc_hash_3do(char hash[33], const char* path)
{
uint8_t buffer[2048];
@ -500,6 +558,20 @@ static int rc_hash_3do(char hash[33], const char* path)
return rc_hash_finalize(&md5, hash);
}
static int rc_hash_7800(char hash[33], uint8_t* buffer, size_t buffer_size)
{
/* if the file contains a header, ignore it */
if (memcmp(&buffer[1], "ATARI7800", 9) == 0)
{
rc_hash_verbose("Ignoring 7800 header");
buffer += 128;
buffer_size -= 128;
}
return rc_hash_buffer(hash, buffer, buffer_size);
}
static int rc_hash_arcade(char hash[33], const char* path)
{
/* arcade hash is just the hash of the filename (no extension) - the cores are pretty stringent about having the right ROM data */
@ -614,7 +686,7 @@ static int rc_hash_nintendo_ds(char hash[33], const char* path)
uint8_t* hash_buffer;
unsigned int hash_size, arm9_size, arm9_addr, arm7_size, arm7_addr, icon_addr;
size_t num_read;
int offset = 0;
int64_t offset = 0;
md5_state_t md5;
void* file_handle;
@ -745,7 +817,10 @@ static int rc_hash_pce_track(char hash[33], void* track_handle)
* the string "PC Engine CD-ROM SYSTEM" should exist at 32 bytes into the sector
* http://shu.sheldows.com/shu/download/pcedocs/pce_cdrom.html
*/
rc_cd_read_sector(track_handle, 1, buffer, 128);
if (rc_cd_read_sector(track_handle, 1, buffer, 128) < 128)
{
return rc_hash_error("Not a PC Engine CD");
}
/* normal PC Engine CD will have a header block in sector 1 */
if (memcmp("PC Engine CD-ROM SYSTEM", &buffer[32], 23) == 0)
@ -914,13 +989,13 @@ static int rc_hash_pcfx_cd(char hash[33], const char* path)
static int rc_hash_dreamcast(char hash[33], const char* path)
{
uint8_t buffer[2048];
uint8_t buffer[256];
void* track_handle;
void* last_track_handle;
char exe_file[32] = "";
unsigned size;
size_t num_read = 0;
uint32_t sector;
uint32_t track_sector;
int result = 0;
md5_state_t md5;
int i = 0;
@ -940,6 +1015,7 @@ static int rc_hash_dreamcast(char hash[33], const char* path)
return rc_hash_error("Not a Dreamcast CD");
}
/* start the hash with the game meta information */
md5_init(&md5);
md5_append(&md5, (md5_byte_t*)buffer, 256);
@ -955,6 +1031,7 @@ static int rc_hash_dreamcast(char hash[33], const char* path)
verbose_message_callback(message);
}
/* the boot filename is 96 bytes into the meta information (https://mc.pp.se/dc/ip0000.bin.html) */
/* remove whitespace from bootfile */
i = 0;
while (!isspace(buffer[96 + i]) && i < 16)
@ -980,50 +1057,98 @@ static int rc_hash_dreamcast(char hash[33], const char* path)
/* last track contains the boot executable */
last_track_handle = rc_cd_open_track(path, RC_HASH_CDTRACK_LAST);
track_sector = rc_cd_absolute_sector_to_track_sector(last_track_handle, sector);
sector = rc_cd_absolute_sector_to_track_sector(last_track_handle, sector);
if ((num_read = rc_cd_read_sector(last_track_handle, sector, buffer, sizeof(buffer))) < sizeof(buffer))
rc_hash_error("Could not read boot executable");
if (size > MAX_BUFFER_SIZE)
size = MAX_BUFFER_SIZE;
if (verbose_message_callback)
if ((int32_t)track_sector < 0)
{
char message[128];
snprintf(message, sizeof(message), "Hashing %s contents (%u bytes)", exe_file, size);
verbose_message_callback(message);
/* boot executable is not in the last track; try the primary data track.
* There's only a handful of games that do this: Q*bert was the first identified. */
rc_cd_close_track(last_track_handle);
rc_hash_verbose("Boot executable not found in last track, trying primary track");
last_track_handle = rc_cd_open_track(path, 3);
track_sector = rc_cd_absolute_sector_to_track_sector(last_track_handle, sector);
}
do
{
md5_append(&md5, buffer, (int)num_read);
size -= (unsigned)num_read;
if (size == 0)
break;
++sector;
if (size >= sizeof(buffer))
num_read = rc_cd_read_sector(last_track_handle, sector, buffer, sizeof(buffer));
else
num_read = rc_cd_read_sector(last_track_handle, sector, buffer, size);
} while (num_read > 0);
result = rc_hash_cd_file(&md5, last_track_handle, track_sector, NULL, size, "boot executable");
rc_cd_close_track(last_track_handle);
result = rc_hash_finalize(&md5, hash);
rc_hash_finalize(&md5, hash);
return result;
}
static int rc_hash_find_playstation_executable(void* track_handle, const char* boot_key, const char* cdrom_prefix,
char exe_name[], unsigned exe_name_size, unsigned* exe_size)
{
uint8_t buffer[2048];
unsigned size;
char* ptr;
char* start;
const size_t boot_key_len = strlen(boot_key);
const size_t cdrom_prefix_len = strlen(cdrom_prefix);
int sector;
sector = rc_cd_find_file_sector(track_handle, "SYSTEM.CNF", NULL);
if (!sector)
return 0;
size = (unsigned)rc_cd_read_sector(track_handle, sector, buffer, sizeof(buffer) - 1);
buffer[size] = '\0';
for (ptr = (char*)buffer; *ptr; ++ptr)
{
if (strncmp(ptr, boot_key, boot_key_len) == 0)
{
ptr += boot_key_len;
while (isspace(*ptr))
++ptr;
if (*ptr == '=')
{
++ptr;
while (isspace(*ptr))
++ptr;
if (strncmp(ptr, cdrom_prefix, cdrom_prefix_len) == 0)
ptr += cdrom_prefix_len;
if (*ptr == '\\')
++ptr;
start = ptr;
while (!isspace(*ptr) && *ptr != ';')
++ptr;
size = (unsigned)(ptr - start);
if (size >= exe_name_size)
size = exe_name_size - 1;
memcpy(exe_name, start, size);
exe_name[size] = '\0';
if (verbose_message_callback)
{
snprintf((char*)buffer, sizeof(buffer), "Looking for boot executable: %s", exe_name);
verbose_message_callback((const char*)buffer);
}
sector = rc_cd_find_file_sector(track_handle, exe_name, exe_size);
break;
}
}
/* advance to end of line */
while (*ptr && *ptr != '\n')
++ptr;
}
return sector;
}
static int rc_hash_psx(char hash[33], const char* path)
{
uint8_t buffer[2048];
uint8_t buffer[32];
char exe_name[64] = "";
char* ptr;
char* start;
void* track_handle;
uint32_t sector;
unsigned size;
@ -1035,63 +1160,12 @@ static int rc_hash_psx(char hash[33], const char* path)
if (!track_handle)
return rc_hash_error("Could not open track");
sector = rc_cd_find_file_sector(track_handle, "SYSTEM.CNF", NULL);
sector = rc_hash_find_playstation_executable(track_handle, "BOOT", "cdrom:", exe_name, sizeof(exe_name), &size);
if (!sector)
{
sector = rc_cd_find_file_sector(track_handle, "PSX.EXE", &size);
if (sector)
strcpy(exe_name, "PSX.EXE");
}
else
{
size = (unsigned)rc_cd_read_sector(track_handle, sector, buffer, sizeof(buffer) - 1);
buffer[size] = '\0';
for (ptr = (char*)buffer; *ptr; ++ptr)
{
if (strncmp(ptr, "BOOT", 4) == 0)
{
ptr += 4;
while (isspace(*ptr))
++ptr;
if (*ptr == '=')
{
++ptr;
while (isspace(*ptr))
++ptr;
if (strncmp(ptr, "cdrom:", 6) == 0)
ptr += 6;
if (*ptr == '\\')
++ptr;
start = ptr;
while (!isspace(*ptr) && *ptr != ';')
++ptr;
size = (unsigned)(ptr - start);
if (size >= sizeof(exe_name))
size = sizeof(exe_name) - 1;
memcpy(exe_name, start, size);
exe_name[size] = '\0';
if (verbose_message_callback)
{
snprintf((char*)buffer, sizeof(buffer), "Looking for boot executable: %s", exe_name);
verbose_message_callback((const char*)buffer);
}
sector = rc_cd_find_file_sector(track_handle, exe_name, &size);
break;
}
}
/* advance to end of line */
while (*ptr && *ptr != '\n')
++ptr;
}
memcpy(exe_name, "PSX.EXE", 8);
}
if (!sector)
@ -1121,38 +1195,65 @@ static int rc_hash_psx(char hash[33], const char* path)
size = (((uint8_t)buffer[31] << 24) | ((uint8_t)buffer[30] << 16) | ((uint8_t)buffer[29] << 8) | (uint8_t)buffer[28]) + 2048;
}
if (size > MAX_BUFFER_SIZE)
size = MAX_BUFFER_SIZE;
if (verbose_message_callback)
{
char message[128];
snprintf(message, sizeof(message), "Hashing %s title (%u bytes) and contents (%u bytes) ", exe_name, (unsigned)strlen(exe_name), size);
verbose_message_callback(message);
}
/* there's also a few games that are use a singular engine and only differ via their data files. luckily, they have
* unique serial numbers, and use the serial number as the boot file in the standard way. include the boot file in the hash
/* there's a few games that use a singular engine and only differ via their data files. luckily, they have unique
* serial numbers, and use the serial number as the boot file in the standard way. include the boot file name in the hash.
*/
md5_init(&md5);
md5_append(&md5, (md5_byte_t*)exe_name, (int)strlen(exe_name));
do
result = rc_hash_cd_file(&md5, track_handle, sector, exe_name, size, "primary executable");
rc_hash_finalize(&md5, hash);
}
rc_cd_close_track(track_handle);
return result;
}
static int rc_hash_ps2(char hash[33], const char* path)
{
uint8_t buffer[4];
char exe_name[64] = "";
void* track_handle;
uint32_t sector;
unsigned size;
size_t num_read;
int result = 0;
md5_state_t md5;
track_handle = rc_cd_open_track(path, 1);
if (!track_handle)
return rc_hash_error("Could not open track");
sector = rc_hash_find_playstation_executable(track_handle, "BOOT2", "cdrom0:", exe_name, sizeof(exe_name), &size);
if (!sector)
{
rc_hash_error("Could not locate primary executable");
}
else if ((num_read = rc_cd_read_sector(track_handle, sector, buffer, sizeof(buffer))) < sizeof(buffer))
{
rc_hash_error("Could not read primary executable");
}
else
{
if (memcmp(buffer, "\x7f\x45\x4c\x46", 4) != 0)
{
md5_append(&md5, buffer, (int)num_read);
if (verbose_message_callback)
{
char message[128];
snprintf(message, sizeof(message), "%s did not contain ELF marker", exe_name);
verbose_message_callback(message);
}
}
size -= (unsigned)num_read;
if (size == 0)
break;
/* there's a few games that use a singular engine and only differ via their data files. luckily, they have unique
* serial numbers, and use the serial number as the boot file in the standard way. include the boot file name in the hash.
*/
md5_init(&md5);
md5_append(&md5, (md5_byte_t*)exe_name, (int)strlen(exe_name));
++sector;
if (size >= sizeof(buffer))
num_read = rc_cd_read_sector(track_handle, sector, buffer, sizeof(buffer));
else
num_read = rc_cd_read_sector(track_handle, sector, buffer, size);
} while (num_read > 0);
result = rc_hash_finalize(&md5, hash);
result = rc_hash_cd_file(&md5, track_handle, sector, exe_name, size, "primary executable");
rc_hash_finalize(&md5, hash);
}
rc_cd_close_track(track_handle);
@ -1217,7 +1318,6 @@ int rc_hash_generate_from_buffer(char hash[33], int console_id, uint8_t* buffer,
case RC_CONSOLE_APPLE_II:
case RC_CONSOLE_ATARI_2600:
case RC_CONSOLE_ATARI_7800:
case RC_CONSOLE_ATARI_JAGUAR:
case RC_CONSOLE_COLECOVISION:
case RC_CONSOLE_GAMEBOY:
@ -1236,11 +1336,16 @@ int rc_hash_generate_from_buffer(char hash[33], int console_id, uint8_t* buffer,
case RC_CONSOLE_POKEMON_MINI:
case RC_CONSOLE_SEGA_32X:
case RC_CONSOLE_SG1000:
case RC_CONSOLE_SUPERVISION:
case RC_CONSOLE_TIC80:
case RC_CONSOLE_VECTREX:
case RC_CONSOLE_VIRTUAL_BOY:
case RC_CONSOLE_WONDERSWAN:
return rc_hash_buffer(hash, buffer, buffer_size);
case RC_CONSOLE_ATARI_7800:
return rc_hash_7800(hash, buffer, buffer_size);
case RC_CONSOLE_ATARI_LYNX:
return rc_hash_lynx(hash, buffer, buffer_size);
@ -1259,9 +1364,10 @@ static int rc_hash_whole_file(char hash[33], int console_id, const char* path)
{
md5_state_t md5;
uint8_t* buffer;
size_t size;
int64_t size;
const size_t buffer_size = 65536;
void* file_handle;
size_t remaining;
int result = 0;
file_handle = rc_file_open(path);
@ -1282,7 +1388,9 @@ static int rc_hash_whole_file(char hash[33], int console_id, const char* path)
}
if (size > MAX_BUFFER_SIZE)
size = MAX_BUFFER_SIZE;
remaining = MAX_BUFFER_SIZE;
else
remaining = (size_t)size;
md5_init(&md5);
@ -1290,17 +1398,17 @@ static int rc_hash_whole_file(char hash[33], int console_id, const char* path)
if (buffer)
{
rc_file_seek(file_handle, 0, SEEK_SET);
while (size >= buffer_size)
while (remaining >= buffer_size)
{
rc_file_read(file_handle, buffer, (int)buffer_size);
md5_append(&md5, buffer, (int)buffer_size);
size -= buffer_size;
remaining -= buffer_size;
}
if (size > 0)
if (remaining > 0)
{
rc_file_read(file_handle, buffer, (int)size);
md5_append(&md5, buffer, (int)size);
rc_file_read(file_handle, buffer, (int)remaining);
md5_append(&md5, buffer, (int)remaining);
}
free(buffer);
@ -1314,7 +1422,7 @@ static int rc_hash_whole_file(char hash[33], int console_id, const char* path)
static int rc_hash_buffered_file(char hash[33], int console_id, const char* path)
{
uint8_t* buffer;
size_t size;
int64_t size;
int result = 0;
void* file_handle;
@ -1338,13 +1446,13 @@ static int rc_hash_buffered_file(char hash[33], int console_id, const char* path
if (size > MAX_BUFFER_SIZE)
size = MAX_BUFFER_SIZE;
buffer = (uint8_t*)malloc(size);
buffer = (uint8_t*)malloc((size_t)size);
if (buffer)
{
rc_file_seek(file_handle, 0, SEEK_SET);
rc_file_read(file_handle, buffer, (int)size);
result = rc_hash_generate_from_buffer(hash, console_id, buffer, size);
result = rc_hash_generate_from_buffer(hash, console_id, buffer, (size_t)size);
free(buffer);
}
@ -1492,7 +1600,6 @@ int rc_hash_generate_from_file(char hash[33], int console_id, const char* path)
case RC_CONSOLE_APPLE_II:
case RC_CONSOLE_ATARI_2600:
case RC_CONSOLE_ATARI_7800:
case RC_CONSOLE_ATARI_JAGUAR:
case RC_CONSOLE_COLECOVISION:
case RC_CONSOLE_GAMEBOY:
@ -1509,6 +1616,8 @@ int rc_hash_generate_from_file(char hash[33], int console_id, const char* path)
case RC_CONSOLE_POKEMON_MINI:
case RC_CONSOLE_SEGA_32X:
case RC_CONSOLE_SG1000:
case RC_CONSOLE_SUPERVISION:
case RC_CONSOLE_TIC80:
case RC_CONSOLE_VECTREX:
case RC_CONSOLE_VIRTUAL_BOY:
case RC_CONSOLE_WONDERSWAN:
@ -1523,6 +1632,7 @@ int rc_hash_generate_from_file(char hash[33], int console_id, const char* path)
return rc_hash_whole_file(hash, console_id, path);
case RC_CONSOLE_ATARI_7800:
case RC_CONSOLE_ATARI_LYNX:
case RC_CONSOLE_NINTENDO:
case RC_CONSOLE_SUPER_NINTENDO:
@ -1562,6 +1672,12 @@ int rc_hash_generate_from_file(char hash[33], int console_id, const char* path)
return rc_hash_psx(hash, path);
case RC_CONSOLE_PLAYSTATION_2:
if (rc_path_compare_extension(path, "m3u"))
return rc_hash_generate_from_playlist(hash, console_id, path);
return rc_hash_ps2(hash, path);
case RC_CONSOLE_DREAMCAST:
if (rc_path_compare_extension(path, "m3u"))
return rc_hash_generate_from_playlist(hash, console_id, path);
@ -1601,7 +1717,7 @@ static void rc_hash_initialize_dsk_iterator(struct rc_hash_iterator* iterator, c
if (file)
{
rc_file_seek(file, 0, SEEK_END);
size = rc_file_tell(file);
size = (size_t)rc_file_tell(file);
rc_file_close(file);
}
}
@ -1655,6 +1771,13 @@ void rc_hash_initialize_iterator(struct rc_hash_iterator* iterator, const char*
const char* ext = rc_path_get_extension(path);
switch (tolower(*ext))
{
case '2':
if (rc_path_compare_extension(ext, "2d"))
{
iterator->consoles[0] = RC_CONSOLE_SHARPX1;
}
break;
case '7':
if (rc_path_compare_extension(ext, "7z"))
{
@ -1680,7 +1803,7 @@ void rc_hash_initialize_iterator(struct rc_hash_iterator* iterator, const char*
void* file = rc_file_open(path);
if (file)
{
size_t size;
int64_t size;
rc_file_seek(file, 0, SEEK_END);
size = rc_file_tell(file);
@ -1690,17 +1813,18 @@ void rc_hash_initialize_iterator(struct rc_hash_iterator* iterator, const char*
{
iterator->consoles[0] = RC_CONSOLE_3DO; /* 4DO supports directly opening the bin file */
iterator->consoles[1] = RC_CONSOLE_PLAYSTATION; /* PCSX ReARMed supports directly opening the bin file*/
iterator->consoles[2] = RC_CONSOLE_SEGA_CD; /* Genesis Plus GX supports directly opening the bin file*/
iterator->consoles[2] = RC_CONSOLE_PLAYSTATION_2; /* PCSX2 supports directly opening the bin file*/
iterator->consoles[3] = RC_CONSOLE_SEGA_CD; /* Genesis Plus GX supports directly opening the bin file*/
/* fallback to megadrive which just does a full hash */
iterator->consoles[3] = RC_CONSOLE_MEGA_DRIVE;
iterator->consoles[4] = RC_CONSOLE_MEGA_DRIVE;
break;
}
}
}
/* bin is associated with MegaDrive, Sega32X and Atari 2600. Since they all use the same
* hashing algorithm, only specify one of them */
/* bin is associated with MegaDrive, Sega32X, Atari 2600, and Watara Supervision.
* Since they all use the same hashing algorithm, only specify one of them */
iterator->consoles[0] = RC_CONSOLE_MEGA_DRIVE;
}
else if (rc_path_compare_extension(ext, "bs"))
@ -1713,20 +1837,22 @@ void rc_hash_initialize_iterator(struct rc_hash_iterator* iterator, const char*
if (rc_path_compare_extension(ext, "cue"))
{
iterator->consoles[0] = RC_CONSOLE_PLAYSTATION;
iterator->consoles[1] = RC_CONSOLE_PC_ENGINE;
iterator->consoles[2] = RC_CONSOLE_3DO;
iterator->consoles[3] = RC_CONSOLE_PCFX;
iterator->consoles[4] = RC_CONSOLE_SEGA_CD; /* ASSERT: handles both Sega CD and Saturn */
iterator->consoles[1] = RC_CONSOLE_PLAYSTATION_2;
iterator->consoles[2] = RC_CONSOLE_PC_ENGINE;
iterator->consoles[3] = RC_CONSOLE_3DO;
iterator->consoles[4] = RC_CONSOLE_PCFX;
iterator->consoles[5] = RC_CONSOLE_SEGA_CD; /* ASSERT: handles both Sega CD and Saturn */
need_path = 1;
}
else if (rc_path_compare_extension(ext, "chd"))
{
iterator->consoles[0] = RC_CONSOLE_PLAYSTATION;
iterator->consoles[1] = RC_CONSOLE_DREAMCAST;
iterator->consoles[2] = RC_CONSOLE_PC_ENGINE;
iterator->consoles[3] = RC_CONSOLE_3DO;
iterator->consoles[4] = RC_CONSOLE_PCFX;
iterator->consoles[5] = RC_CONSOLE_SEGA_CD; /* ASSERT: handles both Sega CD and Saturn */
iterator->consoles[1] = RC_CONSOLE_PLAYSTATION_2;
iterator->consoles[2] = RC_CONSOLE_DREAMCAST;
iterator->consoles[3] = RC_CONSOLE_PC_ENGINE;
iterator->consoles[4] = RC_CONSOLE_3DO;
iterator->consoles[5] = RC_CONSOLE_PCFX;
iterator->consoles[6] = RC_CONSOLE_SEGA_CD; /* ASSERT: handles both Sega CD and Saturn */
need_path = 1;
}
else if (rc_path_compare_extension(ext, "col"))
@ -1747,6 +1873,7 @@ void rc_hash_initialize_iterator(struct rc_hash_iterator* iterator, const char*
else if (rc_path_compare_extension(ext, "d88"))
{
iterator->consoles[0] = RC_CONSOLE_PC8800;
iterator->consoles[1] = RC_CONSOLE_SHARPX1;
}
break;
@ -1759,6 +1886,10 @@ void rc_hash_initialize_iterator(struct rc_hash_iterator* iterator, const char*
{
iterator->consoles[0] = RC_CONSOLE_NINTENDO;
}
else if (rc_path_compare_extension(ext, "fd"))
{
iterator->consoles[0] = RC_CONSOLE_THOMSONTO8; /* disk */
}
break;
case 'g':
@ -1787,8 +1918,9 @@ void rc_hash_initialize_iterator(struct rc_hash_iterator* iterator, const char*
case 'i':
if (rc_path_compare_extension(ext, "iso"))
{
iterator->consoles[0] = RC_CONSOLE_3DO;
iterator->consoles[1] = RC_CONSOLE_SEGA_CD; /* ASSERT: handles both Sega CD and Saturn */
iterator->consoles[0] = RC_CONSOLE_PLAYSTATION_2;
iterator->consoles[1] = RC_CONSOLE_3DO;
iterator->consoles[2] = RC_CONSOLE_SEGA_CD; /* ASSERT: handles both Sega CD and Saturn */
need_path = 1;
}
break;
@ -1800,6 +1932,13 @@ void rc_hash_initialize_iterator(struct rc_hash_iterator* iterator, const char*
}
break;
case 'k':
if (rc_path_compare_extension(ext, "k7"))
{
iterator->consoles[0] = RC_CONSOLE_THOMSONTO8; /* tape */
}
break;
case 'l':
if (rc_path_compare_extension(ext, "lnx"))
{
@ -1835,6 +1974,14 @@ void rc_hash_initialize_iterator(struct rc_hash_iterator* iterator, const char*
{
iterator->consoles[0] = RC_CONSOLE_MSX;
}
else if (rc_path_compare_extension(ext, "m5"))
{
iterator->consoles[0] = RC_CONSOLE_THOMSONTO8; /* cartridge */
}
else if (rc_path_compare_extension(ext, "m7"))
{
iterator->consoles[0] = RC_CONSOLE_THOMSONTO8; /* cartridge */
}
break;
case 'n':
@ -1868,6 +2015,7 @@ void rc_hash_initialize_iterator(struct rc_hash_iterator* iterator, const char*
if (rc_path_compare_extension(ext, "rom"))
{
iterator->consoles[0] = RC_CONSOLE_MSX;
iterator->consoles[1] = RC_CONSOLE_THOMSONTO8; /* cartridge */
}
if (rc_path_compare_extension(ext, "ri"))
{
@ -1890,6 +2038,14 @@ void rc_hash_initialize_iterator(struct rc_hash_iterator* iterator, const char*
{
iterator->consoles[0] = RC_CONSOLE_PC_ENGINE;
}
else if (rc_path_compare_extension(ext, "sv"))
{
iterator->consoles[0] = RC_CONSOLE_SUPERVISION;
}
else if (rc_path_compare_extension(ext, "sap"))
{
iterator->consoles[0] = RC_CONSOLE_THOMSONTO8; /* disk */
}
break;
case 't':
@ -1897,6 +2053,10 @@ void rc_hash_initialize_iterator(struct rc_hash_iterator* iterator, const char*
{
iterator->consoles[0] = RC_CONSOLE_ORIC;
}
else if (rc_path_compare_extension(ext, "tic"))
{
iterator->consoles[0] = RC_CONSOLE_TIC80;
}
break;
case 'v':