diff options
Diffstat (limited to 'src/emu/config.c')
-rw-r--r-- | src/emu/config.c | 363 |
1 files changed, 363 insertions, 0 deletions
diff --git a/src/emu/config.c b/src/emu/config.c new file mode 100644 index 00000000000..7c014fef188 --- /dev/null +++ b/src/emu/config.c @@ -0,0 +1,363 @@ +/*************************************************************************** + + config.c + + Configuration file I/O. + + Copyright (c) 1996-2007, Nicola Salmoria and the MAME Team. + Visit http://mamedev.org for licensing and usage restrictions. + +***************************************************************************/ + +#include "driver.h" +#include "config.h" +#include "xmlfile.h" + + +#define DEBUG_CONFIG 0 + + + +/*************************************************************************** + CONSTANTS +***************************************************************************/ + +#define CONFIG_VERSION 10 + + + +/*************************************************************************** + TYPE DEFINITIONS +***************************************************************************/ + +typedef struct _config_type config_type; +struct _config_type +{ + struct _config_type * next; /* next in line */ + const char * name; /* node name */ + config_callback load; /* load callback */ + config_callback save; /* save callback */ +}; + + + +/*************************************************************************** + GLOBAL VARIABLES +***************************************************************************/ + +static config_type *typelist; + + + +/*************************************************************************** + FUNCTION PROTOTYPES +***************************************************************************/ + +static int config_load_xml(mame_file *file, int type); +static int config_save_xml(mame_file *file, int type); + + + +/*************************************************************************** + CORE IMPLEMENTATION +***************************************************************************/ + +/************************************* + * + * Reset the configuration callbacks + * + *************************************/ + +void config_init(running_machine *machine) +{ + typelist = NULL; + +#ifdef MESS + mess_config_init(machine); +#endif +} + + + +/************************************* + * + * Register to be involved in config + * save/load + * + *************************************/ + +void config_register(const char *nodename, config_callback load, config_callback save) +{ + config_type *newtype; + config_type **ptype; + + /* allocate a new type */ + newtype = auto_malloc(sizeof(*newtype)); + newtype->next = NULL; + newtype->name = nodename; + newtype->load = load; + newtype->save = save; + + /* add us to the end */ + for (ptype = &typelist; *ptype; ptype = &(*ptype)->next) ; + *ptype = newtype; +} + + + +/************************************* + * + * Settings save/load frontend + * + *************************************/ + +int config_load_settings(void) +{ + const char *controller = options_get_string(mame_options(), OPTION_CTRLR); + file_error filerr; + config_type *type; + mame_file *file; + int loaded = 0; + astring *fname; + + /* loop over all registrants and call their init function */ + for (type = typelist; type; type = type->next) + (*type->load)(CONFIG_TYPE_INIT, NULL); + + /* now load the controller file */ + if (controller[0] != 0) + { + /* open the config file */ + fname = astring_assemble_2(astring_alloc(), controller, ".cfg"); + filerr = mame_fopen(SEARCHPATH_CTRLR, astring_c(fname), OPEN_FLAG_READ, &file); + astring_free(fname); + + if (filerr != FILERR_NONE) + fatalerror("Could not load controller file %s.cfg", controller); + + /* load the XML */ + if (!config_load_xml(file, CONFIG_TYPE_CONTROLLER)) + fatalerror("Could not load controller file %s.cfg", controller); + mame_fclose(file); + } + + /* next load the defaults file */ + filerr = mame_fopen(SEARCHPATH_CONFIG, "default.cfg", OPEN_FLAG_READ, &file); + if (filerr == FILERR_NONE) + { + config_load_xml(file, CONFIG_TYPE_DEFAULT); + mame_fclose(file); + } + + /* finally, load the game-specific file */ + fname = astring_assemble_2(astring_alloc(), Machine->basename, ".cfg"); + filerr = mame_fopen(SEARCHPATH_CONFIG, astring_c(fname), OPEN_FLAG_READ, &file); + astring_free(fname); + + if (filerr == FILERR_NONE) + { + loaded = config_load_xml(file, CONFIG_TYPE_GAME); + mame_fclose(file); + } + + /* loop over all registrants and call their final function */ + for (type = typelist; type; type = type->next) + (*type->load)(CONFIG_TYPE_FINAL, NULL); + + /* if we didn't find a saved config, return 0 so the main core knows that it */ + /* is the first time the game is run and it should diplay the disclaimer. */ + return loaded; +} + + +void config_save_settings(void) +{ + file_error filerr; + config_type *type; + mame_file *file; + astring *fname; + + /* loop over all registrants and call their init function */ + for (type = typelist; type; type = type->next) + (*type->save)(CONFIG_TYPE_INIT, NULL); + + /* save the defaults file */ + filerr = mame_fopen(SEARCHPATH_CONFIG, "default.cfg", OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS, &file); + if (filerr == FILERR_NONE) + { + config_save_xml(file, CONFIG_TYPE_DEFAULT); + mame_fclose(file); + } + + /* finally, save the game-specific file */ + fname = astring_assemble_2(astring_alloc(), Machine->basename, ".cfg"); + filerr = mame_fopen(SEARCHPATH_CONFIG, astring_c(fname), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS, &file); + astring_free(fname); + + if (filerr == FILERR_NONE) + { + config_save_xml(file, CONFIG_TYPE_GAME); + mame_fclose(file); + } + + /* loop over all registrants and call their final function */ + for (type = typelist; type; type = type->next) + (*type->save)(CONFIG_TYPE_FINAL, NULL); +} + + + +/************************************* + * + * XML file load + * + *************************************/ + +static int config_load_xml(mame_file *file, int which_type) +{ + xml_data_node *root, *confignode, *systemnode; + config_type *type; + const char *srcfile; + int version, count; + + /* read the file */ + root = xml_file_read(mame_core_file(file), NULL); + if (!root) + goto error; + + /* find the config node */ + confignode = xml_get_sibling(root->child, "mameconfig"); + if (!confignode) + goto error; + + /* validate the config data version */ + version = xml_get_attribute_int(confignode, "version", 0); + if (version != CONFIG_VERSION) + goto error; + + /* strip off all the path crap from the source filename */ + srcfile = strrchr(Machine->gamedrv->source_file, '/'); + if (!srcfile) + srcfile = strrchr(Machine->gamedrv->source_file, '\\'); + if (!srcfile) + srcfile = strrchr(Machine->gamedrv->source_file, ':'); + if (!srcfile) + srcfile = Machine->gamedrv->source_file; + else + srcfile++; + + /* loop over all system nodes in the file */ + count = 0; + for (systemnode = xml_get_sibling(confignode->child, "system"); systemnode; systemnode = xml_get_sibling(systemnode->next, "system")) + { + /* look up the name of the system here; skip if none */ + const char *name = xml_get_attribute_string(systemnode, "name", ""); + + /* based on the file type, determine whether we have a match */ + switch (which_type) + { + case CONFIG_TYPE_GAME: + /* only match on the specific game name */ + if (strcmp(name, Machine->gamedrv->name) != 0) + continue; + break; + + case CONFIG_TYPE_DEFAULT: + /* only match on default */ + if (strcmp(name, "default") != 0) + continue; + break; + + case CONFIG_TYPE_CONTROLLER: + { + const game_driver *clone_of; + /* match on: default, game name, source file name, parent name, grandparent name */ + if (strcmp(name, "default") != 0 && + strcmp(name, Machine->gamedrv->name) != 0 && + strcmp(name, srcfile) != 0 && + ((clone_of = driver_get_clone(Machine->gamedrv)) == NULL || strcmp(name, clone_of->name) != 0) && + (clone_of == NULL || ((clone_of = driver_get_clone(clone_of)) == NULL) || strcmp(name, clone_of->name) != 0)) + continue; + break; + } + } + + /* log that we are processing this entry */ + if (DEBUG_CONFIG) + mame_printf_debug("Entry: %s -- processing\n", name); + + /* loop over all registrants and call their load function */ + for (type = typelist; type; type = type->next) + (*type->load)(which_type, xml_get_sibling(systemnode->child, type->name)); + count++; + } + + /* error if this isn't a valid game match */ + if (count == 0) + goto error; + + /* free the parser */ + xml_file_free(root); + return 1; + +error: + if (root) + xml_file_free(root); + return 0; +} + + + +/************************************* + * + * XML file save + * + *************************************/ + +static int config_save_xml(mame_file *file, int which_type) +{ + xml_data_node *root = xml_file_create(); + xml_data_node *confignode, *systemnode; + config_type *type; + + /* if we don't have a root, bail */ + if (!root) + return 0; + + /* create a config node */ + confignode = xml_add_child(root, "mameconfig", NULL); + if (!confignode) + goto error; + xml_set_attribute_int(confignode, "version", CONFIG_VERSION); + + /* create a system node */ + systemnode = xml_add_child(confignode, "system", NULL); + if (!systemnode) + goto error; + xml_set_attribute(systemnode, "name", (which_type == CONFIG_TYPE_DEFAULT) ? "default" : Machine->gamedrv->name); + + /* create the input node and write it out */ + /* loop over all registrants and call their save function */ + for (type = typelist; type; type = type->next) + { + xml_data_node *curnode = xml_add_child(systemnode, type->name, NULL); + if (!curnode) + goto error; + (*type->save)(which_type, curnode); + + /* if nothing was added, just nuke the node */ + if (!curnode->value && !curnode->child) + xml_delete_node(curnode); + } + + /* flush the file */ + xml_file_write(root, mame_core_file(file)); + + /* free and get out of here */ + xml_file_free(root); + return 1; + +error: + xml_file_free(root); + return 0; +} |