From 2749c957bc7160fa6fd3180fbefbea57e6287f2b Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Fri, 10 Jun 2011 14:54:08 +0000 Subject: [PATCH] Cleanup of image device base classes and prepare for rewrite (no whatsnew) --- src/emu/devimage.c | 514 ++------------------------------------------- src/emu/devlegcy.h | 65 ++---- src/emu/diimage.c | 466 +++++++++++++++++++++++++++++++++++++++- src/emu/diimage.h | 80 ++++--- 4 files changed, 540 insertions(+), 585 deletions(-) diff --git a/src/emu/devimage.c b/src/emu/devimage.c index 22004cf6d6b..67e2ccba8cf 100644 --- a/src/emu/devimage.c +++ b/src/emu/devimage.c @@ -39,9 +39,7 @@ #include "emu.h" -#include "emuopts.h" #include "devlegcy.h" -#include "zippath.h" //************************************************************************** @@ -54,20 +52,6 @@ legacy_image_device_base::~legacy_image_device_base() { - image_device_format **formatptr = &m_formatlist; - - /* free all entries */ - while (*formatptr != NULL) - { - image_device_format *entry = *formatptr; - *formatptr = entry->m_next; - global_free(entry); - } -} - -device_image_partialhash_func legacy_image_device_base::get_partial_hash() const -{ - return reinterpret_cast(get_legacy_fct(DEVINFO_FCT_IMAGE_PARTIAL_HASH)); } //************************************************************************** @@ -80,10 +64,7 @@ device_image_partialhash_func legacy_image_device_base::get_partial_hash() const legacy_image_device_base::legacy_image_device_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, UINT32 clock, device_get_config_func get_config) : legacy_device_base(mconfig, type, tag, owner, clock, get_config), - device_image_interface(mconfig, *this), - m_create_option_guide(NULL), - m_formatlist(NULL), - m_is_loading(FALSE) + device_image_interface(mconfig, *this) { } @@ -103,20 +84,6 @@ void legacy_image_device_base::device_config_complete() formatptr = &m_formatlist; int cnt = 0; - m_type = static_cast(get_legacy_int(DEVINFO_INT_IMAGE_TYPE)); - m_readable = get_legacy_int(DEVINFO_INT_IMAGE_READABLE)!=0; - m_writeable = get_legacy_int(DEVINFO_INT_IMAGE_WRITEABLE)!=0; - m_creatable = get_legacy_int(DEVINFO_INT_IMAGE_CREATABLE)!=0; - m_must_be_loaded = get_legacy_int(DEVINFO_INT_IMAGE_MUST_BE_LOADED)!=0; - m_reset_on_load = get_legacy_int(DEVINFO_INT_IMAGE_RESET_ON_LOAD)!=0; - m_has_partial_hash = get_legacy_int(DEVINFO_FCT_IMAGE_PARTIAL_HASH)!=0; - - m_interface_name = get_legacy_string(DEVINFO_STR_IMAGE_INTERFACE); - - m_file_extensions = get_legacy_string(DEVINFO_STR_IMAGE_FILE_EXTENSIONS); - - m_create_option_guide = reinterpret_cast(get_legacy_ptr(DEVINFO_PTR_IMAGE_CREATE_OPTGUIDE)); - int format_count = get_legacy_int(DEVINFO_INT_IMAGE_CREATE_OPTCOUNT); for (int i = 0; i < format_count; i++) @@ -144,482 +111,29 @@ void legacy_image_device_base::device_config_complete() { if (this == image) index = count; - if (image->image_type_direct() == m_type) + if (image->image_type() == image_type()) count++; } if (count > 1) { - m_instance_name.printf("%s%d", device_typename(m_type), index + 1); - m_brief_instance_name.printf("%s%d", device_brieftypename(m_type), index + 1); + m_instance_name.printf("%s%d", device_typename(image_type()), index + 1); + m_brief_instance_name.printf("%s%d", device_brieftypename(image_type()), index + 1); } else { - m_instance_name = device_typename(m_type); - m_brief_instance_name = device_brieftypename(m_type); + m_instance_name = device_typename(image_type()); + m_brief_instance_name = device_brieftypename(image_type()); } // Override in case of hardcoded values if (strlen(get_legacy_string(DEVINFO_STR_IMAGE_INSTANCE_NAME))>0) { - m_instance_name = get_legacy_string(DEVINFO_STR_IMAGE_INSTANCE_NAME); + m_instance_name = get_legacy_string(DEVINFO_STR_IMAGE_INSTANCE_NAME); } if (strlen(get_legacy_string(DEVINFO_STR_IMAGE_BRIEF_INSTANCE_NAME))>0) { m_brief_instance_name = get_legacy_string(DEVINFO_STR_IMAGE_BRIEF_INSTANCE_NAME); } } -//------------------------------------------------- -// uses_file_extension - update configuration -// based on completed device setup -//------------------------------------------------- -bool legacy_image_device_base::uses_file_extension(const char *file_extension) const -{ - bool result = FALSE; - - if (file_extension[0] == '.') - file_extension++; - - /* find the extensions */ - astring extensions(m_file_extensions); - char *ext = strtok((char*)extensions.cstr(),","); - while (ext != NULL) - { - if (!mame_stricmp(ext, file_extension)) - { - result = TRUE; - break; - } - ext = strtok (NULL, ","); - } - return result; -} - -/**************************************************************************** - IMAGE LOADING -****************************************************************************/ - -/*------------------------------------------------- - is_loaded - quick check to determine whether an - image is loaded --------------------------------------------------*/ - -bool legacy_image_device_base::is_loaded() -{ - return (m_file != NULL); -} - -/*------------------------------------------------- - load_image_by_path - loads an image with a - specific path --------------------------------------------------*/ - -image_error_t legacy_image_device_base::load_image_by_path(UINT32 open_flags, const char *path) -{ - file_error filerr = FILERR_NOT_FOUND; - image_error_t err = IMAGE_ERROR_FILENOTFOUND; - astring revised_path; - - /* attempt to read the file */ - filerr = zippath_fopen(path, open_flags, &m_file, &revised_path); - - /* did the open succeed? */ - switch(filerr) - { - case FILERR_NONE: - /* success! */ - m_readonly = (open_flags & OPEN_FLAG_WRITE) ? 0 : 1; - m_created = (open_flags & OPEN_FLAG_CREATE) ? 1 : 0; - err = IMAGE_ERROR_SUCCESS; - break; - - case FILERR_NOT_FOUND: - case FILERR_ACCESS_DENIED: - /* file not found (or otherwise cannot open); continue */ - err = IMAGE_ERROR_FILENOTFOUND; - break; - - case FILERR_OUT_OF_MEMORY: - /* out of memory */ - err = IMAGE_ERROR_OUTOFMEMORY; - break; - - case FILERR_ALREADY_OPEN: - /* this shouldn't happen */ - err = IMAGE_ERROR_ALREADYOPEN; - break; - - case FILERR_FAILURE: - case FILERR_TOO_MANY_FILES: - case FILERR_INVALID_DATA: - default: - /* other errors */ - err = IMAGE_ERROR_INTERNAL; - break; - } - - /* if successful, set the file name */ - if (filerr == FILERR_NONE) - set_image_filename(revised_path); - - return err; -} - -/*------------------------------------------------- - determine_open_plan - determines which open - flags to use, and in what order --------------------------------------------------*/ - -void legacy_image_device_base::determine_open_plan(int is_create, UINT32 *open_plan) -{ - int i = 0; - - /* emit flags */ - if (!is_create && is_readable() && is_writeable()) - open_plan[i++] = OPEN_FLAG_READ | OPEN_FLAG_WRITE; - if (!is_create && !is_readable() && is_writeable()) - open_plan[i++] = OPEN_FLAG_WRITE; - if (!is_create && is_readable()) - open_plan[i++] = OPEN_FLAG_READ; - if (is_writeable() && is_creatable()) - open_plan[i++] = OPEN_FLAG_READ | OPEN_FLAG_WRITE | OPEN_FLAG_CREATE; - open_plan[i] = 0; -} - -/*------------------------------------------------- - load_software - software image loading --------------------------------------------------*/ -bool legacy_image_device_base::load_software(char *swlist, char *swname, rom_entry *start) -{ - astring locationtag, breakstr("%"); - const rom_entry *region; - astring regiontag; - bool retVal = FALSE; - for (region = start; region != NULL; region = rom_next_region(region)) - { - /* loop until we hit the end of this region */ - const rom_entry *romp = region + 1; - while (!ROMENTRY_ISREGIONEND(romp)) - { - /* handle files */ - if (ROMENTRY_ISFILE(romp)) - { - file_error filerr = FILERR_NOT_FOUND; - - UINT32 crc = 0; - bool has_crc = hash_collection(ROM_GETHASHDATA(romp)).crc(crc); - - // attempt reading up the chain through the parents and create a locationtag astring in the format - // " swlist % clonename % parentname " - // below, we have the code to split the elements and to create paths to load from - - software_list *software_list_ptr = software_list_open(machine().options(), swlist, FALSE, NULL); - if (software_list_ptr) - { - for (software_info *swinfo = software_list_find(software_list_ptr, swname, NULL); swinfo != NULL; ) - { - if (swinfo != NULL) - { - astring tmp(swinfo->shortname); - locationtag.cat(tmp); - locationtag.cat(breakstr); - //printf("%s\n", locationtag.cstr()); - } - const char *parentname = software_get_clone(machine().options(), swlist, swinfo->shortname); - if (parentname != NULL) - swinfo = software_list_find(software_list_ptr, parentname, NULL); - else - swinfo = NULL; - } - // strip the final '%' - locationtag.del(locationtag.len() - 1, 1); - software_list_close(software_list_ptr); - } - - if (software_get_support(machine().options(), swlist, swname) == SOFTWARE_SUPPORTED_PARTIAL) - mame_printf_error("WARNING: support for software %s (in list %s) is only partial\n", swname, swlist); - - if (software_get_support(machine().options(), swlist, swname) == SOFTWARE_SUPPORTED_NO) - mame_printf_error("WARNING: support for software %s (in list %s) is only preliminary\n", swname, swlist); - - // check if locationtag actually contains two locations separated by '%' - // (i.e. check if we are dealing with a clone in softwarelist) - astring tag2, tag3, tag4(locationtag), tag5; - int separator = tag4.chr(0, '%'); - if (separator != -1) - { - // we are loading a clone through softlists, split the setname from the parentname - tag5.cpysubstr(tag4, separator + 1, tag4.len() - separator + 1); - tag4.del(separator, tag4.len() - separator); - } - - // prepare locations where we have to load from: list/parentname & list/clonename - astring tag1(swlist); - tag1.cat(PATH_SEPARATOR); - tag2.cpy(tag1.cat(tag4)); - tag1.cpy(swlist); - tag1.cat(PATH_SEPARATOR); - tag3.cpy(tag1.cat(tag5)); - - if (tag5.chr(0, '%') != -1) - fatalerror("We do not support clones of clones!\n"); - - // try to load from the available location(s): - // - if we are not using lists, we have regiontag only; - // - if we are using lists, we have: list/clonename, list/parentname, clonename, parentname - // try to load from list/setname - if ((m_mame_file == NULL) && (tag2.cstr() != NULL)) - filerr = common_process_file(machine().options(), tag2.cstr(), has_crc, crc, romp, &m_mame_file); - // try to load from list/parentname - if ((m_mame_file == NULL) && (tag3.cstr() != NULL)) - filerr = common_process_file(machine().options(), tag3.cstr(), has_crc, crc, romp, &m_mame_file); - // try to load from setname - if ((m_mame_file == NULL) && (tag4.cstr() != NULL)) - filerr = common_process_file(machine().options(), tag4.cstr(), has_crc, crc, romp, &m_mame_file); - // try to load from parentname - if ((m_mame_file == NULL) && (tag5.cstr() != NULL)) - filerr = common_process_file(machine().options(), tag5.cstr(), has_crc, crc, romp, &m_mame_file); - - if (filerr == FILERR_NONE) - { - m_file = *m_mame_file; - retVal = TRUE; - } - - break; // load first item for start - } - romp++; /* something else; skip */ - } - } - return retVal; -} - -/*------------------------------------------------- - load_internal - core image loading --------------------------------------------------*/ - -bool legacy_image_device_base::load_internal(const char *path, bool is_create, int create_format, option_resolution *create_args) -{ - UINT32 open_plan[4]; - int i; - bool softload = FALSE; - m_from_swlist = FALSE; - - // if the path contains no period, we are using softlists, so we won't create an image - astring pathstr(path); - bool filename_has_period = (pathstr.rchr(0, '.') != -1) ? TRUE : FALSE; - - /* first unload the image */ - unload(); - - /* clear any possible error messages */ - clear_error(); - - /* we are now loading */ - m_is_loading = TRUE; - - /* record the filename */ - m_err = set_image_filename(path); - - if (m_err) - goto done; - - /* Check if there's a software list defined for this device and use that if we're not creating an image */ - if (!filename_has_period) - { - softload = load_software_part( this, path, &m_software_info_ptr, &m_software_part_ptr, &m_full_software_name ); - // if we had launched from softlist with a specified part, e.g. "shortname:part" - // we would have recorded the wrong name, so record it again based on software_info - if (m_software_info_ptr && m_software_info_ptr->shortname) - m_err = set_image_filename(m_software_info_ptr->shortname); - - m_from_swlist = TRUE; - } - - if (is_create || filename_has_period) - { - /* determine open plan */ - determine_open_plan(is_create, open_plan); - - /* attempt to open the file in various ways */ - for (i = 0; !m_file && open_plan[i]; i++) - { - /* open the file */ - m_err = load_image_by_path(open_plan[i], path); - if (m_err && (m_err != IMAGE_ERROR_FILENOTFOUND)) - goto done; - } - } - - /* Copy some image information when we have been loaded through a software list */ - if ( m_software_info_ptr ) - { - m_longname = m_software_info_ptr->longname; - m_manufacturer = m_software_info_ptr->publisher; - m_year = m_software_info_ptr->year; - //m_playable = m_software_info_ptr->supported; - } - - /* did we fail to find the file? */ - if (!is_loaded() && !softload) - { - m_err = IMAGE_ERROR_FILENOTFOUND; - goto done; - } - - /* call device load or create */ - m_create_format = create_format; - m_create_args = create_args; - - if (m_init_phase==FALSE) { - m_err = (image_error_t)finish_load(); - if (m_err) - goto done; - } - /* success! */ - -done: - if (m_err!=0) { - if (!m_init_phase) - { - if (machine().phase() == MACHINE_PHASE_RUNNING) - popmessage("Error: Unable to %s image '%s': %s\n", is_create ? "create" : "load", path, error()); - else - mame_printf_error("Error: Unable to %s image '%s': %s", is_create ? "create" : "load", path, error()); - } - clear(); - } - else { - /* do we need to reset the CPU? only schedule it if load/create is successful */ - if (device().machine().time() > attotime::zero && is_reset_on_load()) - device().machine().schedule_hard_reset(); - else - { - if (!m_init_phase) - { - if (machine().phase() == MACHINE_PHASE_RUNNING) - popmessage("Image '%s' was successfully %s.", path, is_create ? "created" : "loaded"); - else - mame_printf_info("Image '%s' was successfully %s.\n", path, is_create ? "created" : "loaded"); - } - } - } - return m_err ? IMAGE_INIT_FAIL : IMAGE_INIT_PASS; -} - - - -/*------------------------------------------------- - load - load an image into MESS --------------------------------------------------*/ - -bool legacy_image_device_base::load(const char *path) -{ - return load_internal(path, FALSE, 0, NULL); -} - - -/*------------------------------------------------- - image_finish_load - special call - only use - from core --------------------------------------------------*/ - -bool legacy_image_device_base::finish_load() -{ - bool err = IMAGE_INIT_PASS; - - if (m_is_loading) - { - image_checkhash(); - - if (m_from_swlist) - call_display_info(); - - if (has_been_created() && get_legacy_fct(DEVINFO_FCT_IMAGE_CREATE) != NULL) - { - err = call_create(m_create_format, m_create_args); - if (err) - { - if (!m_err) - m_err = IMAGE_ERROR_UNSPECIFIED; - } - } - else - { - /* using device load */ - err = call_load(); - if (err) - { - if (!m_err) - m_err = IMAGE_ERROR_UNSPECIFIED; - } - } - } - m_is_loading = FALSE; - m_create_format = 0; - m_create_args = NULL; - m_init_phase = FALSE; - return err; -} - -/*------------------------------------------------- - create - create a image --------------------------------------------------*/ - -bool legacy_image_device_base::create(const char *path, const image_device_format *create_format, option_resolution *create_args) -{ - int format_index = (create_format != NULL) ? create_format->m_index : 0; - return load_internal(path, TRUE, format_index, create_args); -} - - -/*------------------------------------------------- - clear - clear all internal data pertaining - to an image --------------------------------------------------*/ - -void legacy_image_device_base::clear() -{ - if (m_mame_file) - { - global_free(m_mame_file); - m_mame_file = NULL; - m_file = NULL; - } else { - if (m_file) - { - core_fclose(m_file); - m_file = NULL; - } - } - - m_image_name.reset(); - m_readonly = false; - m_created = false; - - m_longname.reset(); - m_manufacturer.reset(); - m_year.reset(); - m_basename.reset(); - m_basename_noext.reset(); - m_filetype.reset(); - - m_full_software_name = NULL; - m_software_info_ptr = NULL; - m_software_part_ptr = NULL; -} - -/*------------------------------------------------- - unload - main call to unload an image --------------------------------------------------*/ - -void legacy_image_device_base::unload() -{ - if (is_loaded()) { - call_unload(); - } - clear(); - clear_error(); -} - -int legacy_image_device_base::call_load() +bool legacy_image_device_base::call_load() { device_image_load_func func = reinterpret_cast(get_legacy_fct(DEVINFO_FCT_IMAGE_LOAD)); if (func) { @@ -639,7 +153,7 @@ bool legacy_image_device_base::call_softlist_load(char *swlist, char *swname, ro } } -int legacy_image_device_base::call_create(int format_type, option_resolution *format_options) +bool legacy_image_device_base::call_create(int format_type, option_resolution *format_options) { device_image_create_func func = reinterpret_cast(get_legacy_fct(DEVINFO_FCT_IMAGE_CREATE)); if (func) { @@ -667,17 +181,17 @@ void legacy_image_device_base::call_display_info() if (func) (*func)(*this); } -device_image_partialhash_func legacy_image_device_base::get_partial_hash() -{ - return reinterpret_cast(get_legacy_fct(DEVINFO_FCT_IMAGE_PARTIAL_HASH)); -} - void legacy_image_device_base::call_get_devices() { device_image_get_devices_func func = reinterpret_cast(get_legacy_fct(DEVINFO_FCT_IMAGE_GET_DEVICES)); if (func) (*func)(*this); } +device_image_partialhash_func legacy_image_device_base::get_partial_hash() const +{ + return reinterpret_cast(get_legacy_fct(DEVINFO_FCT_IMAGE_PARTIAL_HASH)); +} + void *legacy_image_device_base::get_device_specific_call() { return (void*) get_legacy_fct(DEVINFO_FCT_DEVICE_SPECIFIC); diff --git a/src/emu/devlegcy.h b/src/emu/devlegcy.h index 38e99db407d..bb58b0cf92f 100644 --- a/src/emu/devlegcy.h +++ b/src/emu/devlegcy.h @@ -513,70 +513,33 @@ class legacy_image_device_base : public legacy_device_base, public device_image_interface { public: - virtual iodevice_t image_type() const { return m_type; } - virtual const char *image_type_name() const { return device_typename(m_type); } - virtual iodevice_t image_type_direct() const { return static_cast(get_legacy_int(DEVINFO_INT_IMAGE_TYPE)); } - virtual bool is_readable() const { return m_readable; } - virtual bool is_writeable() const { return m_writeable; } - virtual bool is_creatable() const { return m_creatable; } - virtual bool must_be_loaded() const { return m_must_be_loaded; } - virtual bool is_reset_on_load() const { return m_reset_on_load; } - virtual bool has_partial_hash() const { return m_has_partial_hash; } - virtual const char *image_interface() const { return m_interface_name; } - virtual const char *file_extensions() const { return m_file_extensions; } - virtual const char *instance_name() const { return m_instance_name; } - virtual const char *brief_instance_name() const { return m_brief_instance_name; } - virtual bool uses_file_extension(const char *file_extension) const; - virtual const option_guide *create_option_guide() const { return m_create_option_guide; } - virtual image_device_format *formatlist() const { return m_formatlist; } - virtual device_image_partialhash_func get_partial_hash() const; - - virtual bool load(const char *path); - virtual bool finish_load(); - virtual void unload(); - virtual bool create(const char *path, const image_device_format *create_format, option_resolution *create_args); - virtual bool load_software(char *swlist, char *swname, rom_entry *entry); - - virtual int call_load(); + virtual bool call_load(); virtual bool call_softlist_load(char *swlist, char *swname, rom_entry *start_entry); - virtual int call_create(int format_type, option_resolution *format_options); + virtual bool call_create(int format_type, option_resolution *format_options); virtual void call_unload(); virtual void call_display(); virtual void call_display_info(); - virtual device_image_partialhash_func get_partial_hash(); + virtual device_image_partialhash_func get_partial_hash() const; virtual void call_get_devices(); virtual void *get_device_specific_call(); + + virtual iodevice_t image_type() const { return static_cast(get_legacy_int(DEVINFO_INT_IMAGE_TYPE)); } + + virtual bool is_readable() const { return get_legacy_int(DEVINFO_INT_IMAGE_READABLE)!=0; } + virtual bool is_writeable() const { return get_legacy_int(DEVINFO_INT_IMAGE_WRITEABLE)!=0; } + virtual bool is_creatable() const { return get_legacy_int(DEVINFO_INT_IMAGE_CREATABLE)!=0; } + virtual bool must_be_loaded() const { return get_legacy_int(DEVINFO_INT_IMAGE_MUST_BE_LOADED)!=0; } + virtual bool is_reset_on_load() const { return get_legacy_int(DEVINFO_INT_IMAGE_RESET_ON_LOAD)!=0; } + virtual const char *image_interface() const { return get_legacy_string(DEVINFO_STR_IMAGE_INTERFACE); } + virtual const char *file_extensions() const { return get_legacy_string(DEVINFO_STR_IMAGE_FILE_EXTENSIONS); } + virtual const option_guide *create_option_guide() const { return reinterpret_cast(get_legacy_ptr(DEVINFO_PTR_IMAGE_CREATE_OPTGUIDE)); } protected: // device overrides virtual void device_config_complete(); - iodevice_t m_type; - bool m_readable; - bool m_writeable; - bool m_creatable; - bool m_must_be_loaded; - bool m_reset_on_load; - bool m_has_partial_hash; - astring m_file_extensions; - astring m_instance_name; - astring m_brief_instance_name; - astring m_interface_name; - - /* creation info */ - const option_guide *m_create_option_guide; - image_device_format *m_formatlist; - // construction/destruction legacy_image_device_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, UINT32 clock, device_get_config_func get_config); ~legacy_image_device_base(); - // device_image_interface overrides - bool load_internal(const char *path, bool is_create, int create_format, option_resolution *create_args); - void determine_open_plan(int is_create, UINT32 *open_plan); - image_error_t load_image_by_path(UINT32 open_flags, const char *path); - void clear(); - bool is_loaded(); - - bool m_is_loading; }; diff --git a/src/emu/diimage.c b/src/emu/diimage.c index 280f75c2f74..ad85df70ff1 100644 --- a/src/emu/diimage.c +++ b/src/emu/diimage.c @@ -81,7 +81,9 @@ device_image_interface::device_image_interface(const machine_config &mconfig, de m_software_info_ptr(NULL), m_software_part_ptr(NULL), m_readonly(false), - m_created(false) + m_created(false), + m_formatlist(NULL), + m_is_loading(FALSE) { } @@ -92,6 +94,15 @@ device_image_interface::device_image_interface(const machine_config &mconfig, de device_image_interface::~device_image_interface() { + image_device_format **formatptr = &m_formatlist; + + /* free all entries */ + while (*formatptr != NULL) + { + image_device_format *entry = *formatptr; + *formatptr = entry->m_next; + global_free(entry); + } } //------------------------------------------------- @@ -541,3 +552,456 @@ void device_image_interface::battery_save(const void *buffer, int length) astring_free(fname); } +//------------------------------------------------- +// uses_file_extension - update configuration +// based on completed device setup +//------------------------------------------------- + +bool device_image_interface::uses_file_extension(const char *file_extension) const +{ + bool result = FALSE; + + if (file_extension[0] == '.') + file_extension++; + + /* find the extensions */ + astring extensions(file_extensions()); + char *ext = strtok((char*)extensions.cstr(),","); + while (ext != NULL) + { + if (!mame_stricmp(ext, file_extension)) + { + result = TRUE; + break; + } + ext = strtok (NULL, ","); + } + return result; +} + +/**************************************************************************** + IMAGE LOADING +****************************************************************************/ + +/*------------------------------------------------- + is_loaded - quick check to determine whether an + image is loaded +-------------------------------------------------*/ + +bool device_image_interface::is_loaded() +{ + return (m_file != NULL); +} + +/*------------------------------------------------- + load_image_by_path - loads an image with a + specific path +-------------------------------------------------*/ + +image_error_t device_image_interface::load_image_by_path(UINT32 open_flags, const char *path) +{ + file_error filerr = FILERR_NOT_FOUND; + image_error_t err = IMAGE_ERROR_FILENOTFOUND; + astring revised_path; + + /* attempt to read the file */ + filerr = zippath_fopen(path, open_flags, &m_file, &revised_path); + + /* did the open succeed? */ + switch(filerr) + { + case FILERR_NONE: + /* success! */ + m_readonly = (open_flags & OPEN_FLAG_WRITE) ? 0 : 1; + m_created = (open_flags & OPEN_FLAG_CREATE) ? 1 : 0; + err = IMAGE_ERROR_SUCCESS; + break; + + case FILERR_NOT_FOUND: + case FILERR_ACCESS_DENIED: + /* file not found (or otherwise cannot open); continue */ + err = IMAGE_ERROR_FILENOTFOUND; + break; + + case FILERR_OUT_OF_MEMORY: + /* out of memory */ + err = IMAGE_ERROR_OUTOFMEMORY; + break; + + case FILERR_ALREADY_OPEN: + /* this shouldn't happen */ + err = IMAGE_ERROR_ALREADYOPEN; + break; + + case FILERR_FAILURE: + case FILERR_TOO_MANY_FILES: + case FILERR_INVALID_DATA: + default: + /* other errors */ + err = IMAGE_ERROR_INTERNAL; + break; + } + + /* if successful, set the file name */ + if (filerr == FILERR_NONE) + set_image_filename(revised_path); + + return err; +} + +/*------------------------------------------------- + determine_open_plan - determines which open + flags to use, and in what order +-------------------------------------------------*/ + +void device_image_interface::determine_open_plan(int is_create, UINT32 *open_plan) +{ + int i = 0; + + /* emit flags */ + if (!is_create && is_readable() && is_writeable()) + open_plan[i++] = OPEN_FLAG_READ | OPEN_FLAG_WRITE; + if (!is_create && !is_readable() && is_writeable()) + open_plan[i++] = OPEN_FLAG_WRITE; + if (!is_create && is_readable()) + open_plan[i++] = OPEN_FLAG_READ; + if (is_writeable() && is_creatable()) + open_plan[i++] = OPEN_FLAG_READ | OPEN_FLAG_WRITE | OPEN_FLAG_CREATE; + open_plan[i] = 0; +} + +/*------------------------------------------------- + load_software - software image loading +-------------------------------------------------*/ +bool device_image_interface::load_software(char *swlist, char *swname, rom_entry *start) +{ + astring locationtag, breakstr("%"); + const rom_entry *region; + astring regiontag; + bool retVal = FALSE; + for (region = start; region != NULL; region = rom_next_region(region)) + { + /* loop until we hit the end of this region */ + const rom_entry *romp = region + 1; + while (!ROMENTRY_ISREGIONEND(romp)) + { + /* handle files */ + if (ROMENTRY_ISFILE(romp)) + { + file_error filerr = FILERR_NOT_FOUND; + + UINT32 crc = 0; + bool has_crc = hash_collection(ROM_GETHASHDATA(romp)).crc(crc); + + // attempt reading up the chain through the parents and create a locationtag astring in the format + // " swlist % clonename % parentname " + // below, we have the code to split the elements and to create paths to load from + + software_list *software_list_ptr = software_list_open(device().machine().options(), swlist, FALSE, NULL); + if (software_list_ptr) + { + for (software_info *swinfo = software_list_find(software_list_ptr, swname, NULL); swinfo != NULL; ) + { + if (swinfo != NULL) + { + astring tmp(swinfo->shortname); + locationtag.cat(tmp); + locationtag.cat(breakstr); + //printf("%s\n", locationtag.cstr()); + } + const char *parentname = software_get_clone(device().machine().options(), swlist, swinfo->shortname); + if (parentname != NULL) + swinfo = software_list_find(software_list_ptr, parentname, NULL); + else + swinfo = NULL; + } + // strip the final '%' + locationtag.del(locationtag.len() - 1, 1); + software_list_close(software_list_ptr); + } + + if (software_get_support(device().machine().options(), swlist, swname) == SOFTWARE_SUPPORTED_PARTIAL) + mame_printf_error("WARNING: support for software %s (in list %s) is only partial\n", swname, swlist); + + if (software_get_support(device().machine().options(), swlist, swname) == SOFTWARE_SUPPORTED_NO) + mame_printf_error("WARNING: support for software %s (in list %s) is only preliminary\n", swname, swlist); + + // check if locationtag actually contains two locations separated by '%' + // (i.e. check if we are dealing with a clone in softwarelist) + astring tag2, tag3, tag4(locationtag), tag5; + int separator = tag4.chr(0, '%'); + if (separator != -1) + { + // we are loading a clone through softlists, split the setname from the parentname + tag5.cpysubstr(tag4, separator + 1, tag4.len() - separator + 1); + tag4.del(separator, tag4.len() - separator); + } + + // prepare locations where we have to load from: list/parentname & list/clonename + astring tag1(swlist); + tag1.cat(PATH_SEPARATOR); + tag2.cpy(tag1.cat(tag4)); + tag1.cpy(swlist); + tag1.cat(PATH_SEPARATOR); + tag3.cpy(tag1.cat(tag5)); + + if (tag5.chr(0, '%') != -1) + fatalerror("We do not support clones of clones!\n"); + + // try to load from the available location(s): + // - if we are not using lists, we have regiontag only; + // - if we are using lists, we have: list/clonename, list/parentname, clonename, parentname + // try to load from list/setname + if ((m_mame_file == NULL) && (tag2.cstr() != NULL)) + filerr = common_process_file(device().machine().options(), tag2.cstr(), has_crc, crc, romp, &m_mame_file); + // try to load from list/parentname + if ((m_mame_file == NULL) && (tag3.cstr() != NULL)) + filerr = common_process_file(device().machine().options(), tag3.cstr(), has_crc, crc, romp, &m_mame_file); + // try to load from setname + if ((m_mame_file == NULL) && (tag4.cstr() != NULL)) + filerr = common_process_file(device().machine().options(), tag4.cstr(), has_crc, crc, romp, &m_mame_file); + // try to load from parentname + if ((m_mame_file == NULL) && (tag5.cstr() != NULL)) + filerr = common_process_file(device().machine().options(), tag5.cstr(), has_crc, crc, romp, &m_mame_file); + + if (filerr == FILERR_NONE) + { + m_file = *m_mame_file; + retVal = TRUE; + } + + break; // load first item for start + } + romp++; /* something else; skip */ + } + } + return retVal; +} + +/*------------------------------------------------- + load_internal - core image loading +-------------------------------------------------*/ + +bool device_image_interface::load_internal(const char *path, bool is_create, int create_format, option_resolution *create_args) +{ + UINT32 open_plan[4]; + int i; + bool softload = FALSE; + m_from_swlist = FALSE; + + // if the path contains no period, we are using softlists, so we won't create an image + astring pathstr(path); + bool filename_has_period = (pathstr.rchr(0, '.') != -1) ? TRUE : FALSE; + + /* first unload the image */ + unload(); + + /* clear any possible error messages */ + clear_error(); + + /* we are now loading */ + m_is_loading = TRUE; + + /* record the filename */ + m_err = set_image_filename(path); + + if (m_err) + goto done; + + /* Check if there's a software list defined for this device and use that if we're not creating an image */ + if (!filename_has_period) + { + softload = load_software_part( this, path, &m_software_info_ptr, &m_software_part_ptr, &m_full_software_name ); + // if we had launched from softlist with a specified part, e.g. "shortname:part" + // we would have recorded the wrong name, so record it again based on software_info + if (m_software_info_ptr && m_software_info_ptr->shortname) + m_err = set_image_filename(m_software_info_ptr->shortname); + + m_from_swlist = TRUE; + } + + if (is_create || filename_has_period) + { + /* determine open plan */ + determine_open_plan(is_create, open_plan); + + /* attempt to open the file in various ways */ + for (i = 0; !m_file && open_plan[i]; i++) + { + /* open the file */ + m_err = load_image_by_path(open_plan[i], path); + if (m_err && (m_err != IMAGE_ERROR_FILENOTFOUND)) + goto done; + } + } + + /* Copy some image information when we have been loaded through a software list */ + if ( m_software_info_ptr ) + { + m_longname = m_software_info_ptr->longname; + m_manufacturer = m_software_info_ptr->publisher; + m_year = m_software_info_ptr->year; + //m_playable = m_software_info_ptr->supported; + } + + /* did we fail to find the file? */ + if (!is_loaded() && !softload) + { + m_err = IMAGE_ERROR_FILENOTFOUND; + goto done; + } + + /* call device load or create */ + m_create_format = create_format; + m_create_args = create_args; + + if (m_init_phase==FALSE) { + m_err = (image_error_t)finish_load(); + if (m_err) + goto done; + } + /* success! */ + +done: + if (m_err!=0) { + if (!m_init_phase) + { + if (device().machine().phase() == MACHINE_PHASE_RUNNING) + popmessage("Error: Unable to %s image '%s': %s\n", is_create ? "create" : "load", path, error()); + else + mame_printf_error("Error: Unable to %s image '%s': %s", is_create ? "create" : "load", path, error()); + } + clear(); + } + else { + /* do we need to reset the CPU? only schedule it if load/create is successful */ + if (device().machine().time() > attotime::zero && is_reset_on_load()) + device().machine().schedule_hard_reset(); + else + { + if (!m_init_phase) + { + if (device().machine().phase() == MACHINE_PHASE_RUNNING) + popmessage("Image '%s' was successfully %s.", path, is_create ? "created" : "loaded"); + else + mame_printf_info("Image '%s' was successfully %s.\n", path, is_create ? "created" : "loaded"); + } + } + } + return m_err ? IMAGE_INIT_FAIL : IMAGE_INIT_PASS; +} + + + +/*------------------------------------------------- + load - load an image into MESS +-------------------------------------------------*/ + +bool device_image_interface::load(const char *path) +{ + return load_internal(path, FALSE, 0, NULL); +} + + +/*------------------------------------------------- + image_finish_load - special call - only use + from core +-------------------------------------------------*/ + +bool device_image_interface::finish_load() +{ + bool err = IMAGE_INIT_PASS; + + if (m_is_loading) + { + image_checkhash(); + + if (m_from_swlist) + call_display_info(); + + if (has_been_created() )// && get_legacy_fct(DEVINFO_FCT_IMAGE_CREATE) != NULL) + { + err = call_create(m_create_format, m_create_args); + if (err) + { + if (!m_err) + m_err = IMAGE_ERROR_UNSPECIFIED; + } + } + else + { + /* using device load */ + err = call_load(); + if (err) + { + if (!m_err) + m_err = IMAGE_ERROR_UNSPECIFIED; + } + } + } + m_is_loading = FALSE; + m_create_format = 0; + m_create_args = NULL; + m_init_phase = FALSE; + return err; +} + +/*------------------------------------------------- + create - create a image +-------------------------------------------------*/ + +bool device_image_interface::create(const char *path, const image_device_format *create_format, option_resolution *create_args) +{ + int format_index = (create_format != NULL) ? create_format->m_index : 0; + return load_internal(path, TRUE, format_index, create_args); +} + + +/*------------------------------------------------- + clear - clear all internal data pertaining + to an image +-------------------------------------------------*/ + +void device_image_interface::clear() +{ + if (m_mame_file) + { + global_free(m_mame_file); + m_mame_file = NULL; + m_file = NULL; + } else { + if (m_file) + { + core_fclose(m_file); + m_file = NULL; + } + } + + m_image_name.reset(); + m_readonly = false; + m_created = false; + + m_longname.reset(); + m_manufacturer.reset(); + m_year.reset(); + m_basename.reset(); + m_basename_noext.reset(); + m_filetype.reset(); + + m_full_software_name = NULL; + m_software_info_ptr = NULL; + m_software_part_ptr = NULL; +} + +/*------------------------------------------------- + unload - main call to unload an image +-------------------------------------------------*/ + +void device_image_interface::unload() +{ + if (is_loaded()) { + call_unload(); + } + clear(); + clear_error(); +} diff --git a/src/emu/diimage.h b/src/emu/diimage.h index 32936f34d82..bd82fc19f79 100644 --- a/src/emu/diimage.h +++ b/src/emu/diimage.h @@ -158,51 +158,36 @@ public: device_image_interface(const machine_config &mconfig, device_t &device); virtual ~device_image_interface(); - virtual iodevice_t image_type() const = 0; - virtual const char *image_type_name() const = 0; - virtual iodevice_t image_type_direct() const = 0; - virtual bool is_readable() const = 0; - virtual bool is_writeable() const = 0; - virtual bool is_creatable() const = 0; - virtual bool must_be_loaded() const = 0; - virtual bool is_reset_on_load() const = 0; - virtual bool has_partial_hash() const = 0; - virtual const char *image_interface() const = 0; - virtual const char *file_extensions() const = 0; - virtual const char *instance_name() const = 0; - virtual const char *brief_instance_name() const = 0; - virtual bool uses_file_extension(const char *file_extension) const = 0; - virtual const option_guide *create_option_guide() const = 0; - virtual image_device_format *formatlist() const = 0; - static const char *device_typename(iodevice_t type); static const char *device_brieftypename(iodevice_t type); static iodevice_t device_typeid(const char *name); - virtual device_image_partialhash_func get_partial_hash() const = 0; virtual void device_compute_hash(hash_collection &hashes, const void *data, size_t length, const char *types) const; - virtual bool load(const char *path) = 0; - virtual bool finish_load() = 0; - virtual void unload() = 0; - virtual bool load_software(char *swlist, char *swname, rom_entry *entry) = 0; - - virtual int call_load() = 0; + virtual bool call_load() = 0; virtual bool call_softlist_load(char *swlist, char *swname, rom_entry *start_entry) = 0; - virtual int call_create(int format_type, option_resolution *format_options) = 0; + virtual bool call_create(int format_type, option_resolution *format_options) = 0; virtual void call_unload() = 0; virtual void call_display() = 0; virtual void call_display_info() = 0; virtual void call_get_devices() = 0; virtual void *get_device_specific_call() = 0; - - virtual const image_device_format *device_get_indexed_creatable_format(int index); - virtual const image_device_format *device_get_named_creatable_format(const char *format_name); + virtual device_image_partialhash_func get_partial_hash() const = 0; + virtual iodevice_t image_type() const = 0; + virtual bool is_readable() const = 0; + virtual bool is_writeable() const = 0; + virtual bool is_creatable() const = 0; + virtual bool must_be_loaded() const = 0; + virtual bool is_reset_on_load() const = 0; + virtual const char *image_interface() const = 0; + virtual const char *file_extensions() const = 0; + virtual const option_guide *create_option_guide() const = 0; + + const image_device_format *device_get_indexed_creatable_format(int index); + const image_device_format *device_get_named_creatable_format(const char *format_name); const option_guide *device_get_creation_option_guide() { return create_option_guide(); } const image_device_format *device_get_creatable_formats() { return formatlist(); } - - virtual bool create(const char *path, const image_device_format *create_format, option_resolution *create_args) = 0; - + const char *error(); void seterror(image_error_t err, const char *message); void message(const char *format, ...); @@ -236,8 +221,8 @@ public: const software_info *software_entry() { return m_software_info_ptr; } const software_part *part_entry() { return m_software_part_ptr; } - virtual void set_working_directory(const char *working_directory) { m_working_directory = working_directory; } - virtual const char * working_directory(); + void set_working_directory(const char *working_directory) { m_working_directory = working_directory; } + const char * working_directory(); UINT8 *get_software_region(const char *tag); UINT32 get_software_region_length(const char *tag); @@ -248,7 +233,28 @@ public: void battery_load(void *buffer, int length, int fill); void battery_save(const void *buffer, int length); + + const char *image_type_name() const { return device_typename(image_type()); } + + + + const char *instance_name() const { return m_instance_name; } + const char *brief_instance_name() const { return m_brief_instance_name; } + bool uses_file_extension(const char *file_extension) const; + image_device_format *formatlist() const { return m_formatlist; } + + bool load(const char *path); + bool finish_load(); + void unload(); + bool create(const char *path, const image_device_format *create_format, option_resolution *create_args); + bool load_software(char *swlist, char *swname, rom_entry *entry); protected: + bool load_internal(const char *path, bool is_create, int create_format, option_resolution *create_args); + void determine_open_plan(int is_create, UINT32 *open_plan); + image_error_t load_image_by_path(UINT32 open_flags, const char *path); + void clear(); + bool is_loaded(); + image_error_t set_image_filename(const char *filename); void clear_error(); @@ -304,6 +310,14 @@ protected: option_resolution *m_create_args; hash_collection m_hash; + + astring m_brief_instance_name; + astring m_instance_name; + + /* creation info */ + image_device_format *m_formatlist; + + bool m_is_loading; };