Update to rcheevos v10.2.0

Leaderboard rurl hacks are now replaced by proper calls
This commit is contained in:
Silent
2022-01-07 16:21:37 +01:00
parent 46737acecd
commit 9c91af6dfa
23 changed files with 656 additions and 257 deletions

View File

@ -324,7 +324,7 @@ static void* cdreader_open_cue_track(const char* path, uint32_t track)
}
/* calculate the true offset and update the counters for the next INDEX marker */
offset += sector_offset * previous_sector_size;
offset += (int64_t)sector_offset * previous_sector_size;
previous_sector_size = sector_size;
previous_index_sector_offset += sector_offset;
@ -334,7 +334,7 @@ static void* cdreader_open_cue_track(const char* path, uint32_t track)
{
char message[128];
char* scan = mode;
while (*scan && !isspace(*scan))
while (*scan && !isspace((unsigned char)*scan))
++scan;
*scan = '\0';
@ -589,43 +589,43 @@ static void* cdreader_open_gdi_track(const char* path, uint32_t track)
++ptr;
/* line format: [trackid] [lba] [type] [sectorsize] [file] [?] */
while (isspace(*ptr))
while (isspace((unsigned char)*ptr))
++ptr;
current_track = (uint32_t)atoi(ptr);
if (track && current_track != track)
continue;
while (isdigit(*ptr))
while (isdigit((unsigned char)*ptr))
++ptr;
++ptr;
while (isspace(*ptr))
while (isspace((unsigned char)*ptr))
++ptr;
lba = atoi(ptr);
while (isdigit(*ptr))
while (isdigit((unsigned char)*ptr))
++ptr;
++ptr;
while (isspace(*ptr))
while (isspace((unsigned char)*ptr))
++ptr;
track_type = atoi(ptr);
while (isdigit(*ptr))
while (isdigit((unsigned char)*ptr))
++ptr;
++ptr;
while (isspace(*ptr))
while (isspace((unsigned char)*ptr))
++ptr;
ptr2 = sector_size;
while (isdigit(*ptr))
while (isdigit((unsigned char)*ptr))
*ptr2++ = *ptr++;
*ptr2 = '\0';
++ptr;
while (isspace(*ptr))
while (isspace((unsigned char)*ptr))
++ptr;
ptr2 = file;

View File

@ -58,7 +58,6 @@ static void filereader_seek(void* file_handle, int64_t offset, int 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
}
@ -119,7 +118,11 @@ void* rc_file_open(const char* path)
void* handle;
if (!filereader)
{
rc_hash_init_custom_filereader(NULL);
if (!filereader)
return NULL;
}
handle = filereader->open(path);
if (handle && verbose_message_callback)
@ -361,7 +364,7 @@ static int rc_hash_finalize(md5_state_t* md5, char hash[33])
return 1;
}
static int rc_hash_buffer(char hash[33], uint8_t* buffer, size_t buffer_size)
static int rc_hash_buffer(char hash[33], const uint8_t* buffer, size_t buffer_size)
{
md5_state_t md5;
md5_init(&md5);
@ -411,9 +414,9 @@ static int rc_hash_cd_file(md5_state_t* md5, void* track_handle, uint32_t sector
{
md5_append(md5, buffer, (int)num_read);
size -= (unsigned)num_read;
if (size == 0)
if (size <= (unsigned)num_read)
break;
size -= (unsigned)num_read;
++sector;
if (size >= sizeof(buffer))
@ -495,7 +498,7 @@ static int rc_hash_3do(char hash[33], const char* path)
block_location *= block_size;
/* the file size is at offset 0x10 (assume 0x10 is always 0) */
size = buffer[offset + 0x11] * 65536 + buffer[offset + 0x12] * 256 + buffer[offset + 0x13];
size = (size_t)buffer[offset + 0x11] * 65536 + buffer[offset + 0x12] * 256 + buffer[offset + 0x13];
if (verbose_message_callback)
{
@ -558,7 +561,7 @@ 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)
static int rc_hash_7800(char hash[33], const uint8_t* buffer, size_t buffer_size)
{
/* if the file contains a header, ignore it */
if (memcmp(&buffer[1], "ATARI7800", 9) == 0)
@ -645,7 +648,7 @@ static int rc_hash_arcade(char hash[33], const char* path)
return rc_hash_buffer(hash, (uint8_t*)filename, filename_length);
}
static int rc_hash_lynx(char hash[33], uint8_t* buffer, size_t buffer_size)
static int rc_hash_lynx(char hash[33], const uint8_t* buffer, size_t buffer_size)
{
/* if the file contains a header, ignore it */
if (buffer[0] == 'L' && buffer[1] == 'Y' && buffer[2] == 'N' && buffer[3] == 'X' && buffer[4] == 0)
@ -659,7 +662,7 @@ static int rc_hash_lynx(char hash[33], uint8_t* buffer, size_t buffer_size)
return rc_hash_buffer(hash, buffer, buffer_size);
}
static int rc_hash_nes(char hash[33], uint8_t* buffer, size_t buffer_size)
static int rc_hash_nes(char hash[33], const uint8_t* buffer, size_t buffer_size)
{
/* if the file contains a header, ignore it */
if (buffer[0] == 'N' && buffer[1] == 'E' && buffer[2] == 'S' && buffer[3] == 0x1A)
@ -680,6 +683,212 @@ static int rc_hash_nes(char hash[33], uint8_t* buffer, size_t buffer_size)
return rc_hash_buffer(hash, buffer, buffer_size);
}
static void rc_hash_v64_to_z64(uint8_t* buffer, const uint8_t* stop)
{
uint32_t* ptr = (uint32_t*)buffer;
const uint32_t* stop32 = (const uint32_t*)stop;
while (ptr < stop32)
{
uint32_t temp = *ptr;
temp = (temp & 0xFF00FF00) >> 8 |
(temp & 0x00FF00FF) << 8;
*ptr++ = temp;
}
}
static void rc_hash_n64_to_z64(uint8_t* buffer, const uint8_t* stop)
{
uint32_t* ptr = (uint32_t*)buffer;
const uint32_t* stop32 = (const uint32_t*)stop;
while (ptr < stop32)
{
uint32_t temp = *ptr;
temp = (temp & 0xFF000000) >> 24 |
(temp & 0x00FF0000) >> 8 |
(temp & 0x0000FF00) << 8 |
(temp & 0x000000FF) << 24;
*ptr++ = temp;
}
}
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)
{
uint8_t* buffer;
uint8_t* stop;
const size_t buffer_size = 65536;
md5_state_t md5;
size_t remaining;
void* file_handle;
int is_v64 = 0;
int is_n64 = 0;
file_handle = rc_file_open(path);
if (!file_handle)
return rc_hash_error("Could not open file");
buffer = (uint8_t*)malloc(buffer_size);
if (!buffer)
{
rc_file_close(file_handle);
return rc_hash_error("Could not allocate temporary buffer");
}
stop = buffer + buffer_size;
/* read first byte so we can detect endianness */
rc_file_seek(file_handle, 0, SEEK_SET);
rc_file_read(file_handle, buffer, 1);
if (buffer[0] == 0x80) /* z64 format (big endian [native]) */
{
}
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_n64 = 1;
}
else
{
free(buffer);
rc_file_close(file_handle);
rc_hash_verbose("Not a Nintendo 64 ROM");
return 0;
}
/* calculate total file size */
rc_file_seek(file_handle, 0, SEEK_END);
remaining = (size_t)rc_file_tell(file_handle);
if (remaining > MAX_BUFFER_SIZE)
remaining = MAX_BUFFER_SIZE;
if (verbose_message_callback)
{
char message[64];
snprintf(message, sizeof(message), "Hashing %u bytes", (unsigned)remaining);
verbose_message_callback(message);
}
/* begin hashing */
md5_init(&md5);
rc_file_seek(file_handle, 0, SEEK_SET);
while (remaining >= buffer_size)
{
rc_file_read(file_handle, buffer, (int)buffer_size);
if (is_v64)
rc_hash_v64_to_z64(buffer, stop);
else if (is_n64)
rc_hash_n64_to_z64(buffer, stop);
md5_append(&md5, buffer, (int)buffer_size);
remaining -= buffer_size;
}
if (remaining > 0)
{
rc_file_read(file_handle, buffer, (int)remaining);
stop = buffer + remaining;
if (is_v64)
rc_hash_v64_to_z64(buffer, stop);
else if (is_n64)
rc_hash_n64_to_z64(buffer, stop);
md5_append(&md5, buffer, (int)remaining);
}
/* cleanup */
rc_file_close(file_handle);
free(buffer);
return rc_hash_finalize(&md5, hash);
}
static int rc_hash_nintendo_ds(char hash[33], const char* path)
{
uint8_t header[512];
@ -791,7 +1000,7 @@ static int rc_hash_nintendo_ds(char hash[33], const char* path)
return rc_hash_finalize(&md5, hash);
}
static int rc_hash_pce(char hash[33], uint8_t* buffer, size_t buffer_size)
static int rc_hash_pce(char hash[33], const uint8_t* buffer, size_t buffer_size)
{
/* if the file contains a header, ignore it (expect ROM data to be multiple of 128KB) */
uint32_t calc_size = ((uint32_t)buffer_size / 0x20000) * 0x20000;
@ -1034,7 +1243,7 @@ static int rc_hash_dreamcast(char hash[33], const char* path)
/* 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)
while (!isspace((unsigned char)buffer[96 + i]) && i < 16)
++i;
/* sometimes boot file isn't present on meta information.
@ -1096,18 +1305,19 @@ static int rc_hash_find_playstation_executable(void* track_handle, const char* b
size = (unsigned)rc_cd_read_sector(track_handle, sector, buffer, sizeof(buffer) - 1);
buffer[size] = '\0';
sector = 0;
for (ptr = (char*)buffer; *ptr; ++ptr)
{
if (strncmp(ptr, boot_key, boot_key_len) == 0)
{
ptr += boot_key_len;
while (isspace(*ptr))
while (isspace((unsigned char)*ptr))
++ptr;
if (*ptr == '=')
{
++ptr;
while (isspace(*ptr))
while (isspace((unsigned char)*ptr))
++ptr;
if (strncmp(ptr, cdrom_prefix, cdrom_prefix_len) == 0)
@ -1116,7 +1326,7 @@ static int rc_hash_find_playstation_executable(void* track_handle, const char* b
++ptr;
start = ptr;
while (!isspace(*ptr) && *ptr != ';')
while (!isspace((unsigned char)*ptr) && *ptr != ';')
++ptr;
size = (unsigned)(ptr - start);
@ -1152,7 +1362,6 @@ static int rc_hash_psx(char hash[33], const char* path)
void* track_handle;
uint32_t sector;
unsigned size;
size_t num_read;
int result = 0;
md5_state_t md5;
@ -1172,7 +1381,7 @@ static int rc_hash_psx(char hash[33], const char* path)
{
rc_hash_error("Could not locate primary executable");
}
else if ((num_read = rc_cd_read_sector(track_handle, sector, buffer, sizeof(buffer))) < sizeof(buffer))
else if (rc_cd_read_sector(track_handle, sector, buffer, sizeof(buffer)) < sizeof(buffer))
{
rc_hash_error("Could not read primary executable");
}
@ -1217,7 +1426,6 @@ static int rc_hash_ps2(char hash[33], const char* path)
void* track_handle;
uint32_t sector;
unsigned size;
size_t num_read;
int result = 0;
md5_state_t md5;
@ -1230,7 +1438,7 @@ static int rc_hash_ps2(char hash[33], const char* path)
{
rc_hash_error("Could not locate primary executable");
}
else if ((num_read = rc_cd_read_sector(track_handle, sector, buffer, sizeof(buffer))) < sizeof(buffer))
else if (rc_cd_read_sector(track_handle, sector, buffer, sizeof(buffer)) < sizeof(buffer))
{
rc_hash_error("Could not read primary executable");
}
@ -1261,6 +1469,40 @@ static int rc_hash_ps2(char hash[33], const char* path)
return result;
}
static int rc_hash_psp(char hash[33], const char* path)
{
void* track_handle;
uint32_t sector;
unsigned size;
md5_state_t md5;
track_handle = rc_cd_open_track(path, 1);
if (!track_handle)
return rc_hash_error("Could not open track");
/* http://www.romhacking.net/forum/index.php?topic=30899.0
* PSP_GAME/PARAM.SFO contains key/value pairs identifying the game for the system (i.e. serial number,
* name, version). PSP_GAME/SYSDIR/EBOOT.BIN is the encrypted primary executable.
*/
sector = rc_cd_find_file_sector(track_handle, "PSP_GAME\\PARAM.SFO", &size);
if (!sector)
return rc_hash_error("Not a PSP game disc");
md5_init(&md5);
if (!rc_hash_cd_file(&md5, track_handle, sector, NULL, size, "PSP_GAME\\PARAM.SFO"))
return 0;
sector = rc_cd_find_file_sector(track_handle, "PSP_GAME\\SYSDIR\\EBOOT.BIN", &size);
if (!sector)
return rc_hash_error("Could not find primary executable");
if (!rc_hash_cd_file(&md5, track_handle, sector, NULL, size, "PSP_GAME\\SYSDIR\\EBOOT.BIN"))
return 0;
rc_cd_close_track(track_handle);
return rc_hash_finalize(&md5, hash);
}
static int rc_hash_sega_cd(char hash[33], const char* path)
{
uint8_t buffer[512];
@ -1290,7 +1532,7 @@ static int rc_hash_sega_cd(char hash[33], const char* path)
return rc_hash_buffer(hash, buffer, sizeof(buffer));
}
static int rc_hash_snes(char hash[33], uint8_t* buffer, size_t buffer_size)
static int rc_hash_snes(char hash[33], const uint8_t* buffer, size_t buffer_size)
{
/* if the file contains a header, ignore it */
uint32_t calc_size = ((uint32_t)buffer_size / 0x2000) * 0x2000;
@ -1305,7 +1547,7 @@ static int rc_hash_snes(char hash[33], uint8_t* buffer, size_t buffer_size)
return rc_hash_buffer(hash, buffer, buffer_size);
}
int rc_hash_generate_from_buffer(char hash[33], int console_id, uint8_t* buffer, size_t buffer_size)
int rc_hash_generate_from_buffer(char hash[33], int console_id, const uint8_t* buffer, size_t buffer_size)
{
switch (console_id)
{
@ -1330,7 +1572,6 @@ int rc_hash_generate_from_buffer(char hash[33], int console_id, uint8_t* buffer,
case RC_CONSOLE_MEGA_DRIVE:
case RC_CONSOLE_MSX:
case RC_CONSOLE_NEOGEO_POCKET:
case RC_CONSOLE_NINTENDO_64:
case RC_CONSOLE_ORIC:
case RC_CONSOLE_PC8800:
case RC_CONSOLE_POKEMON_MINI:
@ -1352,6 +1593,9 @@ int rc_hash_generate_from_buffer(char hash[33], int console_id, uint8_t* buffer,
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);
@ -1360,7 +1604,7 @@ int rc_hash_generate_from_buffer(char hash[33], int console_id, uint8_t* buffer,
}
}
static int rc_hash_whole_file(char hash[33], int console_id, const char* path)
static int rc_hash_whole_file(char hash[33], const char* path)
{
md5_state_t md5;
uint8_t* buffer;
@ -1525,7 +1769,7 @@ static const char* rc_hash_get_first_item_from_playlist(const char* path)
next = ptr;
/* remove trailing whitespace - especially '\r' */
while (ptr > start && isspace(ptr[-1]))
while (ptr > start && isspace((unsigned char)ptr[-1]))
--ptr;
/* if we found a non-empty line, break out of the loop to process it */
@ -1611,7 +1855,6 @@ int rc_hash_generate_from_file(char hash[33], int console_id, const char* path)
case RC_CONSOLE_MASTER_SYSTEM:
case RC_CONSOLE_MEGA_DRIVE:
case RC_CONSOLE_NEOGEO_POCKET:
case RC_CONSOLE_NINTENDO_64:
case RC_CONSOLE_ORIC:
case RC_CONSOLE_POKEMON_MINI:
case RC_CONSOLE_SEGA_32X:
@ -1622,7 +1865,7 @@ int rc_hash_generate_from_file(char hash[33], int console_id, const char* path)
case RC_CONSOLE_VIRTUAL_BOY:
case RC_CONSOLE_WONDERSWAN:
/* generic whole-file hash - don't buffer */
return rc_hash_whole_file(hash, console_id, path);
return rc_hash_whole_file(hash, path);
case RC_CONSOLE_MSX:
case RC_CONSOLE_PC8800:
@ -1630,7 +1873,7 @@ int rc_hash_generate_from_file(char hash[33], int console_id, const char* path)
if (rc_path_compare_extension(path, "m3u"))
return rc_hash_generate_from_playlist(hash, console_id, path);
return rc_hash_whole_file(hash, console_id, path);
return rc_hash_whole_file(hash, path);
case RC_CONSOLE_ATARI_7800:
case RC_CONSOLE_ATARI_LYNX:
@ -1648,6 +1891,9 @@ int rc_hash_generate_from_file(char hash[33], int console_id, const char* path)
case RC_CONSOLE_ARCADE:
return rc_hash_arcade(hash, path);
case RC_CONSOLE_NINTENDO_64:
return rc_hash_n64_file(hash, path);
case RC_CONSOLE_NINTENDO_DS:
return rc_hash_nintendo_ds(hash, path);
@ -1678,6 +1924,9 @@ int rc_hash_generate_from_file(char hash[33], int console_id, const char* path)
return rc_hash_ps2(hash, path);
case RC_CONSOLE_PSP:
return rc_hash_psp(hash, path);
case RC_CONSOLE_DREAMCAST:
if (rc_path_compare_extension(path, "m3u"))
return rc_hash_generate_from_playlist(hash, console_id, path);
@ -1693,7 +1942,7 @@ int rc_hash_generate_from_file(char hash[33], int console_id, const char* path)
}
}
static void rc_hash_iterator_append_console(struct rc_hash_iterator* iterator, int console_id)
static void rc_hash_iterator_append_console(struct rc_hash_iterator* iterator, uint8_t console_id)
{
int i = 0;
while (iterator->consoles[i] != 0)
@ -1919,8 +2168,9 @@ void rc_hash_initialize_iterator(struct rc_hash_iterator* iterator, const char*
if (rc_path_compare_extension(ext, "iso"))
{
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 */
iterator->consoles[1] = RC_CONSOLE_PSP;
iterator->consoles[2] = RC_CONSOLE_3DO;
iterator->consoles[3] = RC_CONSOLE_SEGA_CD; /* ASSERT: handles both Sega CD and Saturn */
need_path = 1;
}
break;
@ -2064,6 +2314,10 @@ void rc_hash_initialize_iterator(struct rc_hash_iterator* iterator, const char*
{
iterator->consoles[0] = RC_CONSOLE_VIRTUAL_BOY;
}
else if (rc_path_compare_extension(ext, "v64"))
{
iterator->consoles[0] = RC_CONSOLE_NINTENDO_64;
}
break;
case 'w':
@ -2084,6 +2338,10 @@ void rc_hash_initialize_iterator(struct rc_hash_iterator* iterator, const char*
iterator->consoles[0] = RC_CONSOLE_ARCADE;
need_path = 1;
}
else if (rc_path_compare_extension(ext, "z64"))
{
iterator->consoles[0] = RC_CONSOLE_NINTENDO_64;
}
break;
}