mirror of
https://github.com/libretro/RetroArch
synced 2025-02-07 12:39:54 +00:00
use PSX.EXE if SYSTEM.CNF cannot be found
This commit is contained in:
parent
0d284c42bc
commit
3b0cbc1e41
@ -1215,18 +1215,139 @@ enum
|
||||
RCHEEVOS_PCE_CD_MD5 = -17
|
||||
};
|
||||
|
||||
static int rcheevos_hash_psx(rcheevos_coro_t* coro)
|
||||
{
|
||||
char exe_name_buffer[64];
|
||||
size_t exe_name_size;
|
||||
char* exe_name = NULL;
|
||||
uint8_t* ptr = NULL;
|
||||
const char* end = NULL;
|
||||
char* scan = NULL;
|
||||
char buffer[2048];
|
||||
int success = 0;
|
||||
size_t to_read = 0;
|
||||
|
||||
/* find the data track - it should be the first one */
|
||||
coro->track = cdfs_open_data_track(coro->path);
|
||||
if (!coro->track)
|
||||
{
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "could not open CD\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* open the SYSTEM.CNF file and find the BOOT= record */
|
||||
if (cdfs_open_file(&coro->cdfp, coro->track, "SYSTEM.CNF"))
|
||||
{
|
||||
cdfs_read_file(&coro->cdfp, buffer, sizeof(buffer));
|
||||
|
||||
for (scan = buffer; scan < &buffer[sizeof(buffer)] && *scan; ++scan)
|
||||
{
|
||||
if (strncmp(scan, "BOOT", 4) == 0)
|
||||
{
|
||||
exe_name = scan + 4;
|
||||
while (isspace(*exe_name))
|
||||
++exe_name;
|
||||
|
||||
if (*exe_name == '=')
|
||||
{
|
||||
++exe_name;
|
||||
while (isspace(*exe_name))
|
||||
++exe_name;
|
||||
|
||||
if (strncmp(exe_name, "cdrom:", 6) == 0)
|
||||
exe_name += 6;
|
||||
if (*exe_name == '\\')
|
||||
++exe_name;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
while (*scan && *scan != '\n')
|
||||
++scan;
|
||||
}
|
||||
|
||||
cdfs_close_file(&coro->cdfp);
|
||||
|
||||
if (exe_name)
|
||||
{
|
||||
scan = exe_name;
|
||||
while (!isspace(*scan) && *scan != ';')
|
||||
++scan;
|
||||
*scan = '\0';
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* no SYSTEM.CNF, check for a PSX.EXE */
|
||||
exe_name = "PSX.EXE";
|
||||
}
|
||||
|
||||
if (!exe_name || !cdfs_open_file(&coro->cdfp, coro->track, exe_name))
|
||||
{
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "could not locate primary executable\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
/* store the exe name, we're about to overwrite buffer */
|
||||
strncpy(exe_name_buffer, exe_name, sizeof(exe_name_buffer));
|
||||
exe_name_buffer[sizeof(exe_name_buffer) - 1] = '\0';
|
||||
exe_name_size = strlen(exe_name_buffer);
|
||||
|
||||
/* read the first sector of the executable */
|
||||
cdfs_read_file(&coro->cdfp, buffer, sizeof(buffer));
|
||||
|
||||
/* the PSX-E header specifies the executable size as a 4-byte value 28 bytes into the header, which doesn't
|
||||
* include the header itself. We want to include the header in the hash, so append another 2048 to that value.
|
||||
* ASSERT: this results in the same value as coro->cdfp->size */
|
||||
coro->count = 2048 + (((uint8_t)buffer[28 + 3] << 24) | ((uint8_t)buffer[28 + 2] << 16) |
|
||||
((uint8_t)buffer[28 + 1] << 8) | (uint8_t)buffer[28]);
|
||||
|
||||
if (coro->count <= CHEEVOS_MB(16)) /* sanity check */
|
||||
{
|
||||
/* 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 executable name in the hash */
|
||||
coro->count += exe_name_size;
|
||||
|
||||
free(coro->data);
|
||||
coro->data = (uint8_t*)malloc(coro->count);
|
||||
memcpy(coro->data, exe_name_buffer, exe_name_size);
|
||||
coro->len = exe_name_size;
|
||||
|
||||
memcpy((uint8_t*)coro->data + coro->len, buffer, sizeof(buffer));
|
||||
coro->len += sizeof(buffer);
|
||||
|
||||
while (coro->len < coro->count)
|
||||
{
|
||||
to_read = coro->count - coro->len;
|
||||
if (to_read > 2048)
|
||||
to_read = 2048;
|
||||
|
||||
cdfs_read_file(&coro->cdfp, (uint8_t*)coro->data + coro->len, to_read);
|
||||
|
||||
coro->len += to_read;
|
||||
};
|
||||
|
||||
success = 1;
|
||||
}
|
||||
|
||||
cdfs_close_file(&coro->cdfp);
|
||||
}
|
||||
|
||||
cdfs_close_track(coro->track);
|
||||
coro->track = NULL;
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
static int rcheevos_iterate(rcheevos_coro_t* coro)
|
||||
{
|
||||
const int snes_header_len = 0x200;
|
||||
const int lynx_header_len = 0x40;
|
||||
ssize_t num_read = 0;
|
||||
size_t to_read = 4096;
|
||||
uint8_t *ptr = NULL;
|
||||
const char *end = NULL;
|
||||
size_t exe_name_size = 0;
|
||||
char exe_name_buffer[64];
|
||||
char* exe_name = NULL;
|
||||
char* scan = NULL;
|
||||
uint8_t* ptr = NULL;
|
||||
const char* end = NULL;
|
||||
char buffer[2048];
|
||||
|
||||
static const uint32_t snes_exts[] =
|
||||
@ -1766,120 +1887,13 @@ found:
|
||||
*************************************************************************/
|
||||
CORO_SUB(RCHEEVOS_PSX_MD5)
|
||||
{
|
||||
MD5_Init(&coro->md5);
|
||||
|
||||
/* find the data track - it should be the first one */
|
||||
coro->track = cdfs_open_data_track(coro->path);
|
||||
if (coro->track)
|
||||
if (rcheevos_hash_psx(coro))
|
||||
{
|
||||
/* open the SYSTEM.CNF file and find the BOOT= record */
|
||||
if (cdfs_open_file(&coro->cdfp, coro->track, "SYSTEM.CNF"))
|
||||
{
|
||||
cdfs_read_file(&coro->cdfp, buffer, sizeof(buffer));
|
||||
MD5_Init(&coro->md5);
|
||||
CORO_GOSUB(RCHEEVOS_EVAL_MD5);
|
||||
MD5_Final(coro->hash, &coro->md5);
|
||||
|
||||
for (scan = buffer; scan < &buffer[sizeof(buffer)] && *scan; ++scan)
|
||||
{
|
||||
if (strncmp(scan, "BOOT", 4) == 0)
|
||||
{
|
||||
exe_name = scan + 4;
|
||||
while (isspace(*exe_name))
|
||||
++exe_name;
|
||||
if (*exe_name == '=')
|
||||
{
|
||||
++exe_name;
|
||||
while (isspace(*exe_name))
|
||||
++exe_name;
|
||||
|
||||
if (strncmp(exe_name, "cdrom:", 6) == 0)
|
||||
exe_name += 6;
|
||||
if (*exe_name == '\\')
|
||||
++exe_name;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
while (*scan && *scan != '\n')
|
||||
++scan;
|
||||
}
|
||||
|
||||
cdfs_close_file(&coro->cdfp);
|
||||
|
||||
if (exe_name)
|
||||
{
|
||||
scan = exe_name;
|
||||
while (*scan != '\n' && *scan != '\r' && *scan != ';' && *scan != ' ')
|
||||
++scan;
|
||||
*scan = '\0';
|
||||
|
||||
exe_name_size = scan - exe_name;
|
||||
if (exe_name_size < sizeof(exe_name_buffer))
|
||||
strcpy(exe_name_buffer, exe_name);
|
||||
|
||||
/* open the file pointed to by the BOOT= record */
|
||||
if (exe_name_buffer[0] && cdfs_open_file(&coro->cdfp, coro->track, exe_name_buffer))
|
||||
{
|
||||
cdfs_read_file(&coro->cdfp, buffer, sizeof(buffer));
|
||||
|
||||
/* the PSX-E header specifies the executable size as a 4-byte value 28 bytes into the header, which doesn't
|
||||
* include the header itself. We want to include the header in the hash, so append another 2048 to that value.
|
||||
* ASSERT: this results in the same value as coro->cdfp->size */
|
||||
coro->count = 2048 + (((uint8_t)buffer[28 + 3] << 24) | ((uint8_t)buffer[28 + 2] << 16) |
|
||||
((uint8_t)buffer[28 + 1] << 8) | (uint8_t)buffer[28]);
|
||||
|
||||
if (coro->count > CHEEVOS_MB(16)) /* sanity check */
|
||||
{
|
||||
cdfs_close_file(&coro->cdfp);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* there's 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 executable name in the hash */
|
||||
coro->count += exe_name_size;
|
||||
|
||||
free(coro->data);
|
||||
coro->data = (uint8_t*)malloc(coro->count);
|
||||
memcpy(coro->data, exe_name_buffer, exe_name_size);
|
||||
coro->len = exe_name_size;
|
||||
|
||||
memcpy((uint8_t*)coro->data + coro->len, buffer, sizeof(buffer));
|
||||
coro->len += sizeof(buffer);
|
||||
|
||||
while (coro->len < coro->count)
|
||||
{
|
||||
CORO_YIELD();
|
||||
|
||||
to_read = coro->count - coro->len;
|
||||
if (to_read > 2048)
|
||||
to_read = 2048;
|
||||
|
||||
cdfs_read_file(&coro->cdfp, (uint8_t*)coro->data + coro->len, to_read);
|
||||
|
||||
coro->len += to_read;
|
||||
};
|
||||
|
||||
CORO_GOSUB(RCHEEVOS_EVAL_MD5);
|
||||
MD5_Final(coro->hash, &coro->md5);
|
||||
|
||||
cdfs_close_file(&coro->cdfp);
|
||||
|
||||
cdfs_close_track(coro->track);
|
||||
coro->track = NULL;
|
||||
|
||||
CORO_GOTO(RCHEEVOS_GET_GAMEID);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "could not locate primary executable\n", coro->gameid);
|
||||
|
||||
cdfs_close_track(coro->track);
|
||||
coro->track = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "could not open CD\n", coro->gameid);
|
||||
CORO_GOTO(RCHEEVOS_GET_GAMEID);
|
||||
}
|
||||
|
||||
coro->gameid = 0;
|
||||
|
Loading…
x
Reference in New Issue
Block a user