.fixed potential memory issue when loading CD game after a large ROM file

.added support for upper-case ROM file extensions
.modified load_archive behavior so that it does not overwrite original filename with uncompressed name anymore
.replaced use of strcmp by memcmp
This commit is contained in:
EkeEke 2012-07-15 17:39:47 +02:00
parent 2b8656c27f
commit 47040dbba6
10 changed files with 75 additions and 94 deletions

View File

@ -348,7 +348,7 @@ void gen_tmss_w(unsigned int offset, unsigned int data)
WRITE_WORD(tmss, offset, data); WRITE_WORD(tmss, offset, data);
/* VDP requires "SEGA" value to be written in TMSS register */ /* VDP requires "SEGA" value to be written in TMSS register */
if (strncmp((char *)tmss, "SEGA", 4) == 0) if (memcmp((char *)tmss, "SEGA", 4) == 0)
{ {
for (i=0xc0; i<0xe0; i+=8) for (i=0xc0; i<0xe0; i+=8)
{ {

View File

@ -61,7 +61,7 @@ static int config_load(void)
char version[16]; char version[16];
fseek(fp, 0, SEEK_SET); fseek(fp, 0, SEEK_SET);
fread(version, 16, 1, fp); fread(version, 16, 1, fp);
if (strncmp(version,CONFIG_VERSION,16)) if (memcmp(version,CONFIG_VERSION,16))
{ {
fclose(fp); fclose(fp);
return 0; return 0;

View File

@ -83,37 +83,7 @@ static inline u16 FLIP16 (u16 b)
return c; return c;
} }
void get_zipfilename(char *filename) int load_archive(char *filename, unsigned char *buffer, int maxsize, char *extension)
{
char in[CHUNKSIZE];
/* Open file */
FILE *fd = fopen(filename, "rb");
if (!fd) return;
/* Read first 2 bytes */
fread(in, 2, 1, fd);
/* Detect Zip file */
if (memcmp(in, "PK", 2) == 0)
{
/* Read remaining header data */
fread(in + 2, sizeof(PKZIPHEADER) - 2, 1, fd);
/* Zip header pointer */
PKZIPHEADER *pkzip = (PKZIPHEADER *) in;
/* Return compressed file name */
int len = FLIP16(pkzip->filenameLength);
if (len >= MAXPATHLEN) len = MAXPATHLEN - 1;
fread(filename, len, 1, fd);
filename[len] = 0;
}
fclose(fd);
}
int load_archive(char *filename, unsigned char *buffer, int maxsize)
{ {
int size = 0; int size = 0;
char in[CHUNKSIZE]; char in[CHUNKSIZE];
@ -132,7 +102,7 @@ int load_archive(char *filename, unsigned char *buffer, int maxsize)
/* Mega CD BIOS are required files */ /* Mega CD BIOS are required files */
if (!strcmp(filename,CD_BIOS_US) || !strcmp(filename,CD_BIOS_EU) || !strcmp(filename,CD_BIOS_JP)) if (!strcmp(filename,CD_BIOS_US) || !strcmp(filename,CD_BIOS_EU) || !strcmp(filename,CD_BIOS_JP))
{ {
sprintf(msg,"Unable to open CD BIOS"); sprintf(msg,"Unable to open %s", filename + 14);
} }
if (!fd) if (!fd)
@ -187,19 +157,23 @@ int load_archive(char *filename, unsigned char *buffer, int maxsize)
return 0; return 0;
} }
/* Compressed filename offset */
int offset = sizeof (PKZIPHEADER) + FLIP16(pkzip->filenameLength);
if (extension)
{
memcpy(extension, &in[offset - 3], 3);
extension[3] = 0;
}
/* Initial Zip buffer offset */ /* Initial Zip buffer offset */
int offset = sizeof (PKZIPHEADER) + FLIP16(pkzip->filenameLength) + FLIP16(pkzip->extraDataLength); offset += FLIP16(pkzip->extraDataLength);
zs.next_in = (Bytef *)&in[offset]; zs.next_in = (Bytef *)&in[offset];
/* Initial Zip remaining chunk size */ /* Initial Zip remaining chunk size */
zs.avail_in = CHUNKSIZE - offset; zs.avail_in = CHUNKSIZE - offset;
/* Overwrite input filename with compressed filename */
offset = FLIP16(pkzip->filenameLength);
if (offset >= MAXPATHLEN) offset = MAXPATHLEN - 1;
strncpy(filename, &in[sizeof(PKZIPHEADER)], offset);
filename[offset] = 0;
/* Start unzipping file */ /* Start unzipping file */
do do
{ {
@ -255,6 +229,13 @@ int load_archive(char *filename, unsigned char *buffer, int maxsize)
sprintf((char *)msg,"Loading %d bytes ...", size); sprintf((char *)msg,"Loading %d bytes ...", size);
GUI_MsgBoxOpen("Information", (char *)msg, 1); GUI_MsgBoxOpen("Information", (char *)msg, 1);
/* filename extension */
if (extension)
{
memcpy(extension, &filename[strlen(filename) - 3], 3);
extension[3] = 0;
}
/* Read into buffer */ /* Read into buffer */
int left = size; int left = size;
while (left > CHUNKSIZE) while (left > CHUNKSIZE)

View File

@ -42,6 +42,6 @@
#define _FILEIO_H_ #define _FILEIO_H_
/* Function prototypes */ /* Function prototypes */
int load_archive(char *filename, unsigned char *buffer, int maxsize); int load_archive(char *filename, unsigned char *buffer, int maxsize, char *extension);
#endif /* _FILEIO_H_ */ #endif /* _FILEIO_H_ */

View File

@ -118,7 +118,7 @@ static void init_machine(void)
fclose(fp); fclose(fp);
/* check BOOT ROM */ /* check BOOT ROM */
if (!strncmp((char *)(boot_rom + 0x120),"GENESIS OS", 10)) if (!memcmp((char *)(boot_rom + 0x120),"GENESIS OS", 10))
{ {
/* mark Genesis BIOS as loaded */ /* mark Genesis BIOS as loaded */
system_bios = SYSTEM_MD; system_bios = SYSTEM_MD;

View File

@ -403,13 +403,13 @@ int load_bios(void)
switch (region_code) switch (region_code)
{ {
case REGION_USA: case REGION_USA:
size = load_archive(CD_BIOS_US, scd.bootrom, sizeof(scd.bootrom)); size = load_archive(CD_BIOS_US, scd.bootrom, sizeof(scd.bootrom), 0);
break; break;
case REGION_EUROPE: case REGION_EUROPE:
size = load_archive(CD_BIOS_EU, scd.bootrom, sizeof(scd.bootrom)); size = load_archive(CD_BIOS_EU, scd.bootrom, sizeof(scd.bootrom), 0);
break; break;
default: default:
size = load_archive(CD_BIOS_JP, scd.bootrom, sizeof(scd.bootrom)); size = load_archive(CD_BIOS_JP, scd.bootrom, sizeof(scd.bootrom), 0);
break; break;
} }
@ -458,7 +458,7 @@ int load_bios(void)
if (cart.romsize <= 0x400000) if (cart.romsize <= 0x400000)
{ {
/* load Game Gear "BIOS" file */ /* load Game Gear "BIOS" file */
size = load_archive(GG_BIOS, cart.rom + 0x400000, 0x100000); size = load_archive(GG_BIOS, cart.rom + 0x400000, 0x100000, 0);
if (size > 0) if (size > 0)
{ {
@ -489,13 +489,13 @@ int load_bios(void)
switch (region_code) switch (region_code)
{ {
case REGION_USA: case REGION_USA:
size = load_archive(MS_BIOS_US, cart.rom + 0x400000, 0x100000); size = load_archive(MS_BIOS_US, cart.rom + 0x400000, 0x100000, 0);
break; break;
case REGION_EUROPE: case REGION_EUROPE:
size = load_archive(MS_BIOS_EU, cart.rom + 0x400000, 0x100000); size = load_archive(MS_BIOS_EU, cart.rom + 0x400000, 0x100000, 0);
break; break;
default: default:
size = load_archive(MS_BIOS_JP, cart.rom + 0x400000, 0x100000); size = load_archive(MS_BIOS_JP, cart.rom + 0x400000, 0x100000, 0);
break; break;
} }
@ -548,9 +548,13 @@ int load_rom(char *filename)
{ {
cdd_unload(); cdd_unload();
} }
else
{
cdd.loaded = 0;
}
/* .cue file support */ /* .cue file support */
if (!strncmp(".cue", &filename[strlen(filename) - 4], 4)) if (!memcmp(".cue", &filename[strlen(filename) - 4], 4))
{ {
/* open associated .bin file */ /* open associated .bin file */
strncpy(&filename[strlen(filename) - 4], ".bin", 4); strncpy(&filename[strlen(filename) - 4], ".bin", 4);
@ -565,7 +569,7 @@ int load_rom(char *filename)
} }
/* auto-detect CD image file */ /* auto-detect CD image file */
if (!strncmp("SEGADISCSYSTEM", buf + 0x10, 14)) if (!memcmp("SEGADISCSYSTEM", buf + 0x10, 14))
{ {
/* file header pointer (BIN format) */ /* file header pointer (BIN format) */
header = buf + 0x10; header = buf + 0x10;
@ -573,7 +577,7 @@ int load_rom(char *filename)
/* enable CD hardware */ /* enable CD hardware */
system_hw = SYSTEM_MCD; system_hw = SYSTEM_MCD;
} }
else if (!strncmp("SEGADISCSYSTEM", buf, 14)) else if (!memcmp("SEGADISCSYSTEM", buf, 14))
{ {
/* file header pointer (ISO format) */ /* file header pointer (ISO format) */
header = buf; header = buf;
@ -583,25 +587,29 @@ int load_rom(char *filename)
} }
else else
{ {
/* load file into ROM buffer (input filename is overwritten by uncompressed filename) */ /* load file into ROM buffer */
int size = load_archive(filename, cart.rom, sizeof(cart.rom)); char extension[4];
int size = load_archive(filename, cart.rom, sizeof(cart.rom), extension);
if (!size) return(0); if (!size) return(0);
/* mark CD BIOS as unloaded */ /* mark CD BIOS as unloaded */
system_bios &= ~0x10; system_bios &= ~0x10;
/* convert lower case to upper case */
*(uint32 *)(extension) &= 0xdfdfdfdf;
/* Auto-detect system hardware from ROM file extension */ /* Auto-detect system hardware from ROM file extension */
if (!strncmp(".sms", &filename[strlen(filename) - 4], 4)) if (!memcmp("SMS", &extension[0], 3))
{ {
/* Master System II hardware */ /* Master System II hardware */
system_hw = SYSTEM_SMS2; system_hw = SYSTEM_SMS2;
} }
else if (!strncmp(".gg", &filename[strlen(filename) - 3], 3)) else if (!memcmp("GG", &extension[1], 2))
{ {
/* Game Gear hardware (GG mode) */ /* Game Gear hardware (GG mode) */
system_hw = SYSTEM_GG; system_hw = SYSTEM_GG;
} }
else if (!strncmp(".sg", &filename[strlen(filename) - 3], 3)) else if (!memcmp("SG", &extension[1], 2))
{ {
/* SG-1000 hardware */ /* SG-1000 hardware */
system_hw = SYSTEM_SG; system_hw = SYSTEM_SG;
@ -612,7 +620,7 @@ int load_rom(char *filename)
system_hw = SYSTEM_MD; system_hw = SYSTEM_MD;
/* Decode .MDX format */ /* Decode .MDX format */
if (!strncmp(".mdx", &filename[strlen(filename) - 4], 4)) if (!memcmp("MDX", &extension[0], 3))
{ {
for (i = 4; i < size - 1; i++) for (i = 4; i < size - 1; i++)
{ {
@ -623,7 +631,7 @@ int load_rom(char *filename)
} }
/* auto-detect 512 byte extra header */ /* auto-detect 512 byte extra header */
if (strncmp((char *)(cart.rom + 0x100),"SEGA", 4) && ((size / 512) & 1)) if (memcmp((char *)(cart.rom + 0x100), "SEGA", 4) && ((size / 512) & 1))
{ {
/* remove header */ /* remove header */
size -= 512; size -= 512;
@ -817,12 +825,12 @@ void get_region(char *romheader)
int country = 0; int country = 0;
/* from Gens */ /* from Gens */
if (!strncmp(rominfo.country, "eur", 3)) country |= 8; if (!memcmp(rominfo.country, "eur", 3)) country |= 8;
else if (!strncmp(rominfo.country, "EUR", 3)) country |= 8; else if (!memcmp(rominfo.country, "EUR", 3)) country |= 8;
else if (!strncmp(rominfo.country, "jap", 3)) country |= 1; else if (!memcmp(rominfo.country, "jap", 3)) country |= 1;
else if (!strncmp(rominfo.country, "JAP", 3)) country |= 1; else if (!memcmp(rominfo.country, "JAP", 3)) country |= 1;
else if (!strncmp(rominfo.country, "usa", 3)) country |= 4; else if (!memcmp(rominfo.country, "usa", 3)) country |= 4;
else if (!strncmp(rominfo.country, "USA", 3)) country |= 4; else if (!memcmp(rominfo.country, "USA", 3)) country |= 4;
else else
{ {
int i; int i;

View File

@ -46,7 +46,7 @@ int state_load(unsigned char *state)
char version[17]; char version[17];
load_param(version,16); load_param(version,16);
version[16] = 0; version[16] = 0;
if (strncmp(version,STATE_VERSION,11)) if (memcmp(version,STATE_VERSION,11))
{ {
return -1; return -1;
} }

View File

@ -45,9 +45,8 @@
#include <zlib.h> #include <zlib.h>
static int check_zip(char *filename); static int check_zip(char *filename);
static int gzsize(gzFile *gd);
int load_archive(char *filename, unsigned char *buffer, int maxsize) int load_archive(char *filename, unsigned char *buffer, int maxsize, char *extension)
{ {
int size = 0; int size = 0;
@ -55,6 +54,7 @@ int load_archive(char *filename, unsigned char *buffer, int maxsize)
{ {
unz_file_info info; unz_file_info info;
int ret = 0; int ret = 0;
char fname[256];
/* Attempt to open the archive */ /* Attempt to open the archive */
unzFile *fd = unzOpen(filename); unzFile *fd = unzOpen(filename);
@ -69,13 +69,20 @@ int load_archive(char *filename, unsigned char *buffer, int maxsize)
} }
/* Get file informations and update filename */ /* Get file informations and update filename */
ret = unzGetCurrentFileInfo(fd, &info, filename, 128, NULL, 0, NULL, 0); ret = unzGetCurrentFileInfo(fd, &info, fname, 256, NULL, 0, NULL, 0);
if(ret != UNZ_OK) if(ret != UNZ_OK)
{ {
unzClose(fd); unzClose(fd);
return 0; return 0;
} }
/* Compressed filename extension */
if (extension)
{
strncpy(extension, &fname[strlen(fname) - 3], 3);
extension[3] = 0;
}
/* Open the file for reading */ /* Open the file for reading */
ret = unzOpenCurrentFile(fd); ret = unzOpenCurrentFile(fd);
if(ret != UNZ_OK) if(ret != UNZ_OK)
@ -121,6 +128,13 @@ int load_archive(char *filename, unsigned char *buffer, int maxsize)
/* Read file data */ /* Read file data */
size = gzread(gd, buffer, maxsize); size = gzread(gd, buffer, maxsize);
/* filename extension */
if (extension)
{
strncpy(extension, &filename[strlen(filename) - 3], 3);
extension[3] = 0;
}
/* Close file */ /* Close file */
gzclose(gd); gzclose(gd);
} }
@ -143,25 +157,3 @@ static int check_zip(char *filename)
if(memcmp(buf, "PK", 2) == 0) return (1); if(memcmp(buf, "PK", 2) == 0) return (1);
return (0); return (0);
} }
/*
Returns the size of a GZ compressed file.
*/
static int gzsize(gzFile *gd)
{
#define CHUNKSIZE (0x10000)
int size = 0, length = 0;
unsigned char buffer[CHUNKSIZE];
gzrewind(gd);
do
{
size = gzread(gd, buffer, CHUNKSIZE);
if(size <= 0) break;
length += size;
}
while (!gzeof(gd));
gzrewind(gd);
return (length);
#undef CHUNKSIZE
}

View File

@ -43,6 +43,6 @@
#define _FILEIO_H_ #define _FILEIO_H_
/* Function prototypes */ /* Function prototypes */
extern int load_archive(char *filename, unsigned char *buffer, int maxsize); extern int load_archive(char *filename, unsigned char *buffer, int maxsize, char *extension);
#endif /* _FILEIO_H_ */ #endif /* _FILEIO_H_ */

View File

@ -701,7 +701,7 @@ int main (int argc, char **argv)
fclose(fp); fclose(fp);
/* check BOOT ROM */ /* check BOOT ROM */
if (!strncmp((char *)(boot_rom + 0x120),"GENESIS OS", 10)) if (!memcmp((char *)(boot_rom + 0x120),"GENESIS OS", 10))
{ {
/* mark Genesis BIOS as loaded */ /* mark Genesis BIOS as loaded */
system_bios = SYSTEM_MD; system_bios = SYSTEM_MD;