mirror of
https://github.com/holub/mame
synced 2025-05-13 09:28:13 +03:00
Added new function mame_fclose_and_open_next() which will close a file
and then keep searching the searchpath for the next valid file. Did some internal rearranging in fileio.c to make this work. Changed cheat search so that it loads *all* cheat files in all search paths. Note that it is easy to end up with duplicate entries this way. Some currently disabled code is present which filters out duplicates, but the logic for doing this is quite unclear with the presence of text-only cheats, which is why the code is disabled for now.
This commit is contained in:
parent
43b28f89a5
commit
a0dc0e0196
124
src/emu/cheat.c
124
src/emu/cheat.c
@ -93,6 +93,9 @@
|
|||||||
CONSTANTS
|
CONSTANTS
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
|
/* turn this on to enable removing duplicate cheats; not sure if we should */
|
||||||
|
#define REMOVE_DUPLICATE_CHEATS 0
|
||||||
|
|
||||||
#define CHEAT_VERSION 1
|
#define CHEAT_VERSION 1
|
||||||
|
|
||||||
#define DEFAULT_TEMP_VARIABLES 10
|
#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)
|
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 *cheatlist = NULL;
|
||||||
cheat_entry **cheattailptr;
|
cheat_entry **cheattailptr = &cheatlist;
|
||||||
xml_parse_options options;
|
mame_file *cheatfile = NULL;
|
||||||
xml_parse_error error;
|
|
||||||
mame_file *cheatfile;
|
|
||||||
file_error filerr;
|
file_error filerr;
|
||||||
astring *fname;
|
astring *fname;
|
||||||
int version;
|
|
||||||
|
|
||||||
/* open the file with the proper name */
|
/* open the file with the proper name */
|
||||||
fname = astring_assemble_2(astring_alloc(), filename, ".xml");
|
fname = astring_assemble_2(astring_alloc(), filename, ".xml");
|
||||||
filerr = mame_fopen(SEARCHPATH_CHEAT, astring_c(fname), OPEN_FLAG_READ, &cheatfile);
|
filerr = mame_fopen(SEARCHPATH_CHEAT, astring_c(fname), OPEN_FLAG_READ, &cheatfile);
|
||||||
astring_free(fname);
|
|
||||||
|
|
||||||
/* if that failed, return nothing */
|
/* loop over all instrances of the files found in our search paths */
|
||||||
if (filerr != FILERR_NONE)
|
while (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)
|
|
||||||
{
|
{
|
||||||
mame_printf_error("%s.xml(%d): error parsing XML (%s)\n", filename, error.error_line, error.error_message);
|
xml_data_node *mamecheatnode, *cheatnode;
|
||||||
return NULL;
|
xml_parse_options options;
|
||||||
}
|
xml_parse_error error;
|
||||||
|
cheat_entry *scannode;
|
||||||
|
int version;
|
||||||
|
|
||||||
/* find the layout node */
|
mame_printf_verbose("Loading cheats file from %s\n", mame_file_full_name(cheatfile));
|
||||||
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 */
|
/* read the XML file into internal data structures */
|
||||||
version = xml_get_attribute_int(mamecheatnode, "version", 0);
|
memset(&options, 0, sizeof(options));
|
||||||
if (version != CHEAT_VERSION)
|
options.error = &error;
|
||||||
{
|
rootnode = xml_file_read(mame_core_file(cheatfile), &options);
|
||||||
mame_printf_error("%s.xml(%d): Invalid cheat XML file: unsupported version", filename, mamecheatnode->line);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* parse all the elements */
|
/* if unable to parse the file, just bail */
|
||||||
cheatlist = NULL;
|
if (rootnode == NULL)
|
||||||
cheattailptr = &cheatlist;
|
{
|
||||||
for (cheatnode = xml_get_sibling(mamecheatnode->child, "cheat"); cheatnode != NULL; cheatnode = xml_get_sibling(cheatnode->next, "cheat"))
|
mame_printf_error("%s.xml(%d): error parsing XML (%s)\n", filename, error.error_line, error.error_message);
|
||||||
{
|
|
||||||
/* load this entry */
|
|
||||||
cheat_entry *curcheat = cheat_entry_load(machine, filename, cheatnode);
|
|
||||||
if (curcheat == NULL)
|
|
||||||
goto error;
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
/* add to the end of the list */
|
/* find the layout node */
|
||||||
*cheattailptr = curcheat;
|
mamecheatnode = xml_get_sibling(rootnode->child, "mamecheat");
|
||||||
cheattailptr = &curcheat->next;
|
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 */
|
/* release memory and return the cheat list */
|
||||||
xml_file_free(rootnode);
|
astring_free(fname);
|
||||||
return cheatlist;
|
return cheatlist;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
cheat_list_free(cheatlist);
|
cheat_list_free(cheatlist);
|
||||||
xml_file_free(rootnode);
|
xml_file_free(rootnode);
|
||||||
|
if (cheatfile != NULL)
|
||||||
|
mame_fclose(cheatfile);
|
||||||
|
astring_free(fname);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,6 +38,15 @@
|
|||||||
TYPE DEFINITIONS
|
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 */
|
/* typedef struct _mame_file mame_file -- declared in fileio.h */
|
||||||
struct _mame_file
|
struct _mame_file
|
||||||
{
|
{
|
||||||
@ -46,6 +55,7 @@ struct _mame_file
|
|||||||
#endif
|
#endif
|
||||||
astring * filename; /* full filename */
|
astring * filename; /* full filename */
|
||||||
core_file * file; /* core file pointer */
|
core_file * file; /* core file pointer */
|
||||||
|
path_iterator iterator; /* iterator for paths */
|
||||||
UINT32 openflags; /* flags we used for the open */
|
UINT32 openflags; /* flags we used for the open */
|
||||||
char hash[HASH_BUF_SIZE]; /* hash data for the file */
|
char hash[HASH_BUF_SIZE]; /* hash data for the file */
|
||||||
zip_file * zipfile; /* ZIP file pointer */
|
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 */
|
/* typedef struct _mame_path mame_path -- declared in fileio.h */
|
||||||
struct _mame_path
|
struct _mame_path
|
||||||
{
|
{
|
||||||
@ -82,7 +83,7 @@ struct _mame_path
|
|||||||
static void fileio_exit(running_machine *machine);
|
static void fileio_exit(running_machine *machine);
|
||||||
|
|
||||||
/* file open/close */
|
/* 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);
|
static file_error fopen_attempt_zipped(astring *fullname, UINT32 crc, UINT32 openflags, mame_file *file);
|
||||||
|
|
||||||
/* path iteration */
|
/* 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)
|
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)
|
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);
|
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)
|
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)
|
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
|
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;
|
file_error filerr = FILERR_NOT_FOUND;
|
||||||
path_iterator iterator;
|
|
||||||
|
|
||||||
/* can either have a hash or open for write, but not both */
|
/* can either have a hash or open for write, but not both */
|
||||||
if ((openflags & OPEN_FLAG_HAS_CRC) && (openflags & OPEN_FLAG_WRITE))
|
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;
|
(*file)->debug_cookie = DEBUG_COOKIE;
|
||||||
#endif
|
#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 */
|
/* loop over paths */
|
||||||
(*file)->filename = astring_alloc();
|
(*file)->filename = astring_alloc();
|
||||||
while (path_iterator_get_next(&iterator, (*file)->filename))
|
while (path_iterator_get_next(iterator, (*file)->filename))
|
||||||
{
|
{
|
||||||
/* compute the full pathname */
|
/* compute the full pathname */
|
||||||
if (astring_len((*file)->filename) > 0)
|
if (astring_len((*file)->filename) > 0)
|
||||||
@ -263,8 +264,12 @@ static file_error fopen_internal(core_options *opts, const char *searchpath, con
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* if we succeeded, save the iterator */
|
||||||
|
if (filerr == FILERR_NONE)
|
||||||
|
(*file)->iterator = *iterator;
|
||||||
|
|
||||||
/* handle errors and return */
|
/* handle errors and return */
|
||||||
if (filerr != FILERR_NONE)
|
else
|
||||||
{
|
{
|
||||||
mame_fclose(*file);
|
mame_fclose(*file);
|
||||||
*file = NULL;
|
*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
|
mame_fcompress - enable/disable streaming file
|
||||||
compression via zlib; level is 0 to disable
|
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 */
|
/* reset the structure */
|
||||||
memset(iterator, 0, sizeof(*iterator));
|
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;
|
iterator->cur = iterator->base;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,6 +99,9 @@ file_error mame_fopen_ram(const void *data, UINT32 length, UINT32 openflags, mam
|
|||||||
/* close an open file */
|
/* close an open file */
|
||||||
void mame_fclose(mame_file *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 */
|
/* 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);
|
file_error mame_fcompress(mame_file *file, int compress);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user