diff --git a/src/emu/cheat.c b/src/emu/cheat.c index db1e73bb06e..3affd417534 100644 --- a/src/emu/cheat.c +++ b/src/emu/cheat.c @@ -93,6 +93,9 @@ CONSTANTS ***************************************************************************/ +/* turn this on to enable removing duplicate cheats; not sure if we should */ +#define REMOVE_DUPLICATE_CHEATS 0 + #define CHEAT_VERSION 1 #define DEFAULT_TEMP_VARIABLES 10 @@ -959,76 +962,99 @@ static void cheat_execute_script(cheat_private *cheatinfo, cheat_entry *cheat, s static cheat_entry *cheat_list_load(running_machine *machine, const char *filename) { - xml_data_node *rootnode, *mamecheatnode, *cheatnode; + xml_data_node *rootnode = NULL; cheat_entry *cheatlist = NULL; - cheat_entry **cheattailptr; - xml_parse_options options; - xml_parse_error error; - mame_file *cheatfile; + cheat_entry **cheattailptr = &cheatlist; + mame_file *cheatfile = NULL; file_error filerr; astring *fname; - int version; /* open the file with the proper name */ fname = astring_assemble_2(astring_alloc(), filename, ".xml"); filerr = mame_fopen(SEARCHPATH_CHEAT, astring_c(fname), OPEN_FLAG_READ, &cheatfile); - astring_free(fname); - - /* if that failed, return nothing */ - if (filerr != FILERR_NONE) - return NULL; - - /* read the XML file into internal data structures */ - memset(&options, 0, sizeof(options)); - options.error = &error; - rootnode = xml_file_read(mame_core_file(cheatfile), &options); - mame_fclose(cheatfile); - - /* if unable to parse the file, just bail */ - if (rootnode == NULL) + + /* loop over all instrances of the files found in our search paths */ + while (filerr == FILERR_NONE) { - mame_printf_error("%s.xml(%d): error parsing XML (%s)\n", filename, error.error_line, error.error_message); - return NULL; - } + xml_data_node *mamecheatnode, *cheatnode; + xml_parse_options options; + xml_parse_error error; + cheat_entry *scannode; + int version; - /* find the layout node */ - mamecheatnode = xml_get_sibling(rootnode->child, "mamecheat"); - if (mamecheatnode == NULL) - { - mame_printf_error("%s.xml: missing mamecheatnode node", filename); - goto error; - } + mame_printf_verbose("Loading cheats file from %s\n", mame_file_full_name(cheatfile)); + + /* read the XML file into internal data structures */ + memset(&options, 0, sizeof(options)); + options.error = &error; + rootnode = xml_file_read(mame_core_file(cheatfile), &options); - /* validate the config data version */ - version = xml_get_attribute_int(mamecheatnode, "version", 0); - if (version != CHEAT_VERSION) - { - mame_printf_error("%s.xml(%d): Invalid cheat XML file: unsupported version", filename, mamecheatnode->line); - goto error; - } - - /* parse all the elements */ - cheatlist = NULL; - cheattailptr = &cheatlist; - for (cheatnode = xml_get_sibling(mamecheatnode->child, "cheat"); cheatnode != NULL; cheatnode = xml_get_sibling(cheatnode->next, "cheat")) - { - /* load this entry */ - cheat_entry *curcheat = cheat_entry_load(machine, filename, cheatnode); - if (curcheat == NULL) + /* if unable to parse the file, just bail */ + if (rootnode == NULL) + { + mame_printf_error("%s.xml(%d): error parsing XML (%s)\n", filename, error.error_line, error.error_message); goto error; + } - /* add to the end of the list */ - *cheattailptr = curcheat; - cheattailptr = &curcheat->next; + /* find the layout node */ + mamecheatnode = xml_get_sibling(rootnode->child, "mamecheat"); + if (mamecheatnode == NULL) + { + mame_printf_error("%s.xml: missing mamecheatnode node", filename); + goto error; + } + + /* validate the config data version */ + version = xml_get_attribute_int(mamecheatnode, "version", 0); + if (version != CHEAT_VERSION) + { + mame_printf_error("%s.xml(%d): Invalid cheat XML file: unsupported version", filename, mamecheatnode->line); + goto error; + } + + /* parse all the elements */ + for (cheatnode = xml_get_sibling(mamecheatnode->child, "cheat"); cheatnode != NULL; cheatnode = xml_get_sibling(cheatnode->next, "cheat")) + { + /* load this entry */ + cheat_entry *curcheat = cheat_entry_load(machine, filename, cheatnode); + if (curcheat == NULL) + goto error; + + /* make sure we're not a duplicate */ + scannode = NULL; + if (REMOVE_DUPLICATE_CHEATS) + for (scannode = cheatlist; scannode != NULL; scannode = scannode->next) + if (astring_cmp(scannode->description, curcheat->description) == 0) + { + mame_printf_verbose("Ignoring duplicate cheat '%s' from file %s\n", astring_c(curcheat->description), mame_file_full_name(cheatfile)); + break; + } + + /* add to the end of the list */ + if (scannode == NULL) + { + *cheattailptr = curcheat; + cheattailptr = &curcheat->next; + } + } + + /* free the file and loop for the next one */ + xml_file_free(rootnode); + + /* open the next file in sequence */ + filerr = mame_fclose_and_open_next(&cheatfile, astring_c(fname), OPEN_FLAG_READ); } - /* free the file and exit */ - xml_file_free(rootnode); + /* release memory and return the cheat list */ + astring_free(fname); return cheatlist; error: cheat_list_free(cheatlist); xml_file_free(rootnode); + if (cheatfile != NULL) + mame_fclose(cheatfile); + astring_free(fname); return NULL; } diff --git a/src/emu/fileio.c b/src/emu/fileio.c index 85bc2938e86..9540d62a1fc 100644 --- a/src/emu/fileio.c +++ b/src/emu/fileio.c @@ -38,6 +38,15 @@ TYPE DEFINITIONS ***************************************************************************/ +typedef struct _path_iterator path_iterator; +struct _path_iterator +{ + const char * base; + const char * cur; + int index; +}; + + /* typedef struct _mame_file mame_file -- declared in fileio.h */ struct _mame_file { @@ -46,6 +55,7 @@ struct _mame_file #endif astring * filename; /* full filename */ core_file * file; /* core file pointer */ + path_iterator iterator; /* iterator for paths */ UINT32 openflags; /* flags we used for the open */ char hash[HASH_BUF_SIZE]; /* hash data for the file */ zip_file * zipfile; /* ZIP file pointer */ @@ -54,15 +64,6 @@ struct _mame_file }; -typedef struct _path_iterator path_iterator; -struct _path_iterator -{ - const char * base; - const char * cur; - int index; -}; - - /* typedef struct _mame_path mame_path -- declared in fileio.h */ struct _mame_path { @@ -82,7 +83,7 @@ struct _mame_path static void fileio_exit(running_machine *machine); /* file open/close */ -static file_error fopen_internal(core_options *opts, const char *searchpath, const char *filename, UINT32 crc, UINT32 flags, mame_file **file); +static file_error fopen_internal(core_options *opts, path_iterator *iterator, const char *filename, UINT32 crc, UINT32 flags, mame_file **file); static file_error fopen_attempt_zipped(astring *fullname, UINT32 crc, UINT32 openflags, mame_file *file); /* path iteration */ @@ -134,7 +135,9 @@ static void fileio_exit(running_machine *machine) file_error mame_fopen(const char *searchpath, const char *filename, UINT32 openflags, mame_file **file) { - return fopen_internal(mame_options(), searchpath, filename, 0, openflags, file); + path_iterator iterator; + path_iterator_init(&iterator, mame_options(), searchpath); + return fopen_internal(mame_options(), &iterator, filename, 0, openflags, file); } @@ -145,6 +148,8 @@ file_error mame_fopen(const char *searchpath, const char *filename, UINT32 openf file_error mame_fopen_crc(const char *searchpath, const char *filename, UINT32 crc, UINT32 openflags, mame_file **file) { + path_iterator iterator; + path_iterator_init(&iterator, mame_options(), searchpath); return mame_fopen_crc_options(mame_options(), searchpath, filename, crc, openflags, file); } @@ -156,7 +161,9 @@ file_error mame_fopen_crc(const char *searchpath, const char *filename, UINT32 c file_error mame_fopen_options(core_options *opts, const char *searchpath, const char *filename, UINT32 openflags, mame_file **file) { - return fopen_internal(opts, searchpath, filename, 0, openflags, file); + path_iterator iterator; + path_iterator_init(&iterator, opts, searchpath); + return fopen_internal(opts, &iterator, filename, 0, openflags, file); } @@ -167,7 +174,9 @@ file_error mame_fopen_options(core_options *opts, const char *searchpath, const file_error mame_fopen_crc_options(core_options *opts, const char *searchpath, const char *filename, UINT32 crc, UINT32 openflags, mame_file **file) { - return fopen_internal(opts, searchpath, filename, crc, openflags | OPEN_FLAG_HAS_CRC, file); + path_iterator iterator; + path_iterator_init(&iterator, opts, searchpath); + return fopen_internal(opts, &iterator, filename, crc, openflags | OPEN_FLAG_HAS_CRC, file); } @@ -212,10 +221,9 @@ error: fopen_internal - open a file -------------------------------------------------*/ -static file_error fopen_internal(core_options *opts, const char *searchpath, const char *filename, UINT32 crc, UINT32 openflags, mame_file **file) +static file_error fopen_internal(core_options *opts, path_iterator *iterator, const char *filename, UINT32 crc, UINT32 openflags, mame_file **file) { file_error filerr = FILERR_NOT_FOUND; - path_iterator iterator; /* can either have a hash or open for write, but not both */ if ((openflags & OPEN_FLAG_HAS_CRC) && (openflags & OPEN_FLAG_WRITE)) @@ -233,16 +241,9 @@ static file_error fopen_internal(core_options *opts, const char *searchpath, con (*file)->debug_cookie = DEBUG_COOKIE; #endif - /* if the path is absolute, null out the search path */ - if (searchpath != NULL && osd_is_absolute_path(searchpath)) - searchpath = NULL; - - /* determine the maximum length of a composed filename, plus some extra space for .zip extensions */ - path_iterator_init(&iterator, opts, searchpath); - /* loop over paths */ (*file)->filename = astring_alloc(); - while (path_iterator_get_next(&iterator, (*file)->filename)) + while (path_iterator_get_next(iterator, (*file)->filename)) { /* compute the full pathname */ if (astring_len((*file)->filename) > 0) @@ -262,9 +263,13 @@ static file_error fopen_internal(core_options *opts, const char *searchpath, con break; } } + + /* if we succeeded, save the iterator */ + if (filerr == FILERR_NONE) + (*file)->iterator = *iterator; /* handle errors and return */ - if (filerr != FILERR_NONE) + else { mame_fclose(*file); *file = NULL; @@ -388,6 +393,21 @@ void mame_fclose(mame_file *file) } +/*------------------------------------------------- + mame_fclose_and_open_next - close an open + file, and open the next entry in the original + searchpath +-------------------------------------------------*/ + +file_error mame_fclose_and_open_next(mame_file **file, const char *filename, UINT32 openflags) +{ + path_iterator iterator = (*file)->iterator; + mame_fclose(*file); + *file = NULL; + return fopen_internal(mame_options(), &iterator, filename, 0, openflags, file); +} + + /*------------------------------------------------- mame_fcompress - enable/disable streaming file compression via zlib; level is 0 to disable @@ -803,7 +823,7 @@ static void path_iterator_init(path_iterator *iterator, core_options *opts, cons { /* reset the structure */ memset(iterator, 0, sizeof(*iterator)); - iterator->base = (searchpath != NULL) ? options_get_string(opts, searchpath) : ""; + iterator->base = (searchpath != NULL && !osd_is_absolute_path(searchpath)) ? options_get_string(opts, searchpath) : ""; iterator->cur = iterator->base; } diff --git a/src/emu/fileio.h b/src/emu/fileio.h index f89e61fa697..a4a7ced06ed 100644 --- a/src/emu/fileio.h +++ b/src/emu/fileio.h @@ -99,6 +99,9 @@ file_error mame_fopen_ram(const void *data, UINT32 length, UINT32 openflags, mam /* close an open file */ void mame_fclose(mame_file *file); +/* close an open file, and open the next entry in the original searchpath*/ +file_error mame_fclose_and_open_next(mame_file **file, const char *filename, UINT32 openflags); + /* enable/disable streaming file compression via zlib; level is 0 to disable compression, or up to 9 for max compression */ file_error mame_fcompress(mame_file *file, int compress);