From 826dba59230eb70043f3ab1a304b9cb4b8ad8fbb Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Thu, 17 Jun 2010 20:06:54 +0000 Subject: [PATCH] - removed MESS dependency from config.c - moved image legacy device implementation to devimage.c - created image.c implementation with initialization of devices/configuration for image devices, used those calls from mame.c - some minor cleanup of legacy device and initial implementation of some calls (no whatsnew for now, this is just for log,will put more info on final commit) --- .gitattributes | 3 + src/emu/config.c | 4 - src/emu/devimage.c | 478 +++++++++++++++++++++++++++++++++++++++++++++ src/emu/devlegcy.c | 215 +------------------- src/emu/devlegcy.h | 66 ++++--- src/emu/diimage.c | 56 +++++- src/emu/diimage.h | 74 ++++++- src/emu/emu.h | 4 +- src/emu/emu.mak | 2 + src/emu/emuopts.c | 4 +- src/emu/emuopts.h | 2 +- src/emu/image.c | 168 ++++++++++++++++ src/emu/image.h | 23 +++ src/emu/mame.c | 16 +- src/emu/mame.h | 3 - 15 files changed, 847 insertions(+), 271 deletions(-) create mode 100644 src/emu/devimage.c create mode 100644 src/emu/image.c create mode 100644 src/emu/image.h diff --git a/.gitattributes b/.gitattributes index 9f5b4dbca5c..d1dab293fc0 100644 --- a/.gitattributes +++ b/.gitattributes @@ -561,6 +561,7 @@ src/emu/devcb.h svneol=native#text/plain src/emu/devconv.h svneol=native#text/plain src/emu/devcpu.c svneol=native#text/plain src/emu/devcpu.h svneol=native#text/plain +src/emu/devimage.c svneol=native#text/plain src/emu/devintrf.c svneol=native#text/plain src/emu/devintrf.h svneol=native#text/plain src/emu/devlegcy.c svneol=native#text/plain @@ -606,6 +607,8 @@ src/emu/hash.c svneol=native#text/plain src/emu/hash.h svneol=native#text/plain src/emu/hashfile.c svneol=native#text/plain src/emu/hashfile.h svneol=native#text/plain +src/emu/image.c svneol=native#text/plain +src/emu/image.h svneol=native#text/plain src/emu/info.c svneol=native#text/plain src/emu/info.h svneol=native#text/plain src/emu/inptport.c svneol=native#text/plain diff --git a/src/emu/config.c b/src/emu/config.c index 4ab9c1339a9..e2995c283d9 100644 --- a/src/emu/config.c +++ b/src/emu/config.c @@ -64,10 +64,6 @@ static int config_save_xml(running_machine *machine, mame_file *file, int type); void config_init(running_machine *machine) { typelist = NULL; - -#ifdef MESS - mess_config_init(machine); -#endif } diff --git a/src/emu/devimage.c b/src/emu/devimage.c new file mode 100644 index 00000000000..bbafeab224f --- /dev/null +++ b/src/emu/devimage.c @@ -0,0 +1,478 @@ +/*************************************************************************** + + devimage.c + + Legacy image device helpers. + +**************************************************************************** + + Copyright Miodrag Milanovic + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + * Neither the name 'MAME' nor the names of its contributors may be + used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + +***************************************************************************/ + + +#include "emu.h" +#include "devlegcy.h" +#include "hashfile.h" +#include "zippath.h" + + +//************************************************************************** +// LEGACY IMAGE DEVICE CONFIGURATION +//************************************************************************** + +//------------------------------------------------- +// legacy_image_device_config_base - constructor +//------------------------------------------------- + +legacy_image_device_config_base::legacy_image_device_config_base(const machine_config &mconfig, device_type type, const char *tag, const device_config *owner, UINT32 clock, device_get_config_func get_config) + : legacy_device_config_base(mconfig, type, tag, owner, clock, get_config), + device_config_image_interface(mconfig, *this), + m_create_option_guide(NULL), + m_formatlist(NULL) +{ +} + +//------------------------------------------------- +// device_config_complete - update configuration +// based on completed device setup +//------------------------------------------------- + +void legacy_image_device_config_base::device_config_complete() +{ + const device_config_image_interface *image = NULL; + int count = 0; + int index = -1; + image_device_format **formatptr; + image_device_format *format; + formatptr = &m_formatlist; + int cnt = 0; + + m_type = static_cast(get_legacy_config_int(DEVINFO_INT_IMAGE_TYPE)); + m_readable = get_legacy_config_int(DEVINFO_INT_IMAGE_READABLE)!=0; + m_writeable = get_legacy_config_int(DEVINFO_INT_IMAGE_WRITEABLE)!=0; + m_creatable = get_legacy_config_int(DEVINFO_INT_IMAGE_CREATABLE)!=0; + m_must_be_loaded = get_legacy_config_int(DEVINFO_INT_IMAGE_MUST_BE_LOADED)!=0; + m_reset_on_load = get_legacy_config_int(DEVINFO_INT_IMAGE_RESET_ON_LOAD)!=0; + m_has_partial_hash = get_legacy_config_int(DEVINFO_FCT_IMAGE_PARTIAL_HASH)!=0; + + m_interface_name = get_legacy_config_string(DEVINFO_STR_IMAGE_INTERFACE); + + m_file_extensions = get_legacy_config_string(DEVINFO_STR_IMAGE_FILE_EXTENSIONS); + + load = reinterpret_cast(get_legacy_config_fct(DEVINFO_FCT_IMAGE_LOAD)); + create = reinterpret_cast(get_legacy_config_fct(DEVINFO_FCT_IMAGE_CREATE)); + unload = reinterpret_cast(get_legacy_config_fct(DEVINFO_FCT_IMAGE_UNLOAD)); + display = reinterpret_cast(get_legacy_config_fct(DEVINFO_FCT_IMAGE_DISPLAY)); + partialhash = reinterpret_cast(get_legacy_config_fct(DEVINFO_FCT_IMAGE_PARTIAL_HASH)); + get_devices = reinterpret_cast(get_legacy_config_fct(DEVINFO_FCT_IMAGE_GET_DEVICES)); + + m_create_option_guide = reinterpret_cast(get_legacy_config_ptr(DEVINFO_PTR_IMAGE_CREATE_OPTGUIDE)); + + int format_count = get_legacy_config_int(DEVINFO_INT_IMAGE_CREATE_OPTCOUNT); + + for (int i = 0; i < format_count; i++) + { + // only add if creatable + if (get_legacy_config_string(DEVINFO_PTR_IMAGE_CREATE_OPTSPEC + i)) { + // allocate a new format + format = global_alloc_clear(image_device_format); + + // populate it + format->m_index = cnt; + format->m_name = get_legacy_config_string(DEVINFO_STR_IMAGE_CREATE_OPTNAME + i); + format->m_description = get_legacy_config_string(DEVINFO_STR_IMAGE_CREATE_OPTDESC + i); + format->m_extensions = get_legacy_config_string(DEVINFO_STR_IMAGE_CREATE_OPTEXTS + i); + format->m_optspec = get_legacy_config_string(DEVINFO_PTR_IMAGE_CREATE_OPTSPEC + i); + + // and append it to the list + *formatptr = format; + formatptr = &format->m_next; + cnt++; + } + } + + for (bool gotone = device_config_interface::m_machine_config.devicelist.first(image); gotone; gotone = image->next(image)) + { + if (this == image) + index = count; + if (image->image_type_direct() == m_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); + } + else + { + m_instance_name = device_typename(m_type); + m_brief_instance_name = device_brieftypename(m_type); + } + // Override in case of hardcoded values + if (strlen(get_legacy_config_string(DEVINFO_STR_IMAGE_INSTANCE_NAME))>0) { + m_instance_name = get_legacy_config_string(DEVINFO_STR_IMAGE_INSTANCE_NAME); + } + if (strlen(get_legacy_config_string(DEVINFO_STR_IMAGE_BRIEF_INSTANCE_NAME))>0) { + m_brief_instance_name = get_legacy_config_string(DEVINFO_STR_IMAGE_BRIEF_INSTANCE_NAME); + } +} + +//------------------------------------------------- +// uses_file_extension - update configuration +// based on completed device setup +//------------------------------------------------- + +bool legacy_image_device_config_base::uses_file_extension(const char *file_extension) const +{ + bool result = FALSE; + + if (file_extension[0] == '.') + file_extension++; + + /* find the extensions */ + char *ext = strtok((char*)m_file_extensions.cstr(),","); + while (ext != NULL) + { + if (!mame_stricmp(ext, file_extension)) + { + result = TRUE; + break; + } + ext = strtok (NULL, ","); + } + return result; +} + +//------------------------------------------------- +// ~legacy_device_config_base - destructor +//------------------------------------------------- + +legacy_image_device_config_base::~legacy_image_device_config_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); + } +} + + +//************************************************************************** +// LIVE LEGACY IMAGE DEVICE +//************************************************************************** + +//------------------------------------------------- +// legacy_image_device_base - constructor +//------------------------------------------------- + +legacy_image_device_base::legacy_image_device_base(running_machine &machine, const device_config &config) + : legacy_device_base(machine, config), + device_image_interface(machine, config, *this), + m_file(NULL) +{ +} + + +/**************************************************************************** + IMAGE LOADING +****************************************************************************/ + +/*------------------------------------------------- + set_image_filename - specifies the filename of + an image +-------------------------------------------------*/ + +image_error_t legacy_image_device_base::set_image_filename(const char *filename) +{ + m_name = filename; + zippath_parent(&m_working_directory, filename); + return IMAGE_ERROR_SUCCESS; +} + + +/*------------------------------------------------- + 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_writeable = (open_flags & OPEN_FLAG_WRITE) ? 1 : 0; + 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 && m_image_config.is_readable() && m_image_config.is_writeable()) + open_plan[i++] = OPEN_FLAG_READ | OPEN_FLAG_WRITE; + if (!is_create && !m_image_config.is_readable() && m_image_config.is_writeable()) + open_plan[i++] = OPEN_FLAG_WRITE; + if (!is_create && m_image_config.is_readable()) + open_plan[i++] = OPEN_FLAG_READ; + if (m_image_config.is_writeable() && m_image_config.is_creatable()) + open_plan[i++] = OPEN_FLAG_READ | OPEN_FLAG_WRITE | OPEN_FLAG_CREATE; + open_plan[i] = 0; +} + +/*------------------------------------------------- + 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) +{ + image_error_t err; + UINT32 open_plan[4]; + int i; + + /* first unload the image */ + unload(); + + /* clear any possible error messages */ + + /* we are now loading */ + + /* record the filename */ + err = set_image_filename(path); + if (err) + goto done; + + /* Check if there's a software list defined for this device and use that if we're not creating an image */ + /* 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 */ + err = load_image_by_path(open_plan[i], path); + if (err && (err != IMAGE_ERROR_FILENOTFOUND)) + goto done; + } + /* success! */ + +done: + if (err) { + clear(); + } + else { + /* do we need to reset the CPU? only schedule it if load/create is successful */ + if ((attotime_compare(timer_get_time(device().machine), attotime_zero) > 0) && m_image_config.is_reset_on_load()) + mame_schedule_hard_reset(device().machine); + } + return err ? FALSE : TRUE; +} + + + +/*------------------------------------------------- + load - load an image into MESS +-------------------------------------------------*/ + +bool legacy_image_device_base::load(const char *path) +{ + return load_internal(path, FALSE, 0, NULL); +} + +/*------------------------------------------------- + clear - clear all internal data pertaining + to an image +-------------------------------------------------*/ + +void legacy_image_device_base::clear() +{ + if (m_file) + { + core_fclose(m_file); + m_file = NULL; + } + + m_name.reset(); + m_writeable = FALSE; + m_created = FALSE; +} + + +/*------------------------------------------------- + unload_internal - internal call to unload + images +-------------------------------------------------*/ + +void legacy_image_device_base::unload_internal() +{ + clear(); +} + + + +/*------------------------------------------------- + unload - main call to unload an image +-------------------------------------------------*/ + +void legacy_image_device_base::unload() +{ + unload_internal(); +} + + +/*************************************************************************** + WORKING DIRECTORIES +***************************************************************************/ + +/*------------------------------------------------- + try_change_working_directory - tries to change + the working directory, but only if the directory + actually exists +-------------------------------------------------*/ +bool legacy_image_device_base::try_change_working_directory(const char *subdir) +{ + osd_directory *directory; + const osd_directory_entry *entry; + bool success = FALSE; + bool done = FALSE; + + directory = osd_opendir(m_working_directory.cstr()); + if (directory != NULL) + { + while(!done && (entry = osd_readdir(directory)) != NULL) + { + if (!mame_stricmp(subdir, entry->name)) + { + done = TRUE; + success = entry->type == ENTTYPE_DIR; + } + } + + osd_closedir(directory); + } + + /* did we successfully identify the directory? */ + if (success) + zippath_combine(&m_working_directory, m_working_directory, subdir); + + return success; +} +/*------------------------------------------------- + setup_working_directory - sets up the working + directory according to a few defaults +-------------------------------------------------*/ + +void legacy_image_device_base::setup_working_directory() +{ + const game_driver *gamedrv; + char *dst = NULL; + + osd_get_full_path(&dst,"."); + /* first set up the working directory to be the starting directory */ + m_working_directory = dst; + + /* now try browsing down to "software" */ + if (try_change_working_directory("software")) + { + /* now down to a directory for this computer */ + gamedrv = device().machine->gamedrv; + while(gamedrv && !try_change_working_directory(gamedrv->name)) + { + gamedrv = driver_get_compatible(gamedrv); + } + } + osd_free(dst); +} + +//------------------------------------------------- +// working_directory - returns the working +// directory to use for this image; this is +// valid even if not mounted +//------------------------------------------------- + +const char * legacy_image_device_base::working_directory() +{ + /* check to see if we've never initialized the working directory */ + if (m_working_directory.len() == 0) + setup_working_directory(); + + return m_working_directory; +} diff --git a/src/emu/devlegcy.c b/src/emu/devlegcy.c index b8433ab4d57..676c94f2024 100644 --- a/src/emu/devlegcy.c +++ b/src/emu/devlegcy.c @@ -343,217 +343,4 @@ void legacy_nvram_device_base::nvram_write(mame_file &file) { device_nvram_func nvram_func = reinterpret_cast(m_config.get_legacy_config_fct(DEVINFO_FCT_NVRAM)); (*nvram_func)(this, &file, TRUE); -} - -//************************************************************************** -// LEGACY IMAGE DEVICE CONFIGURATION -//************************************************************************** -const image_device_type_info legacy_image_device_config_base::m_device_info_array[] = - { - { IO_CARTSLOT, "cartridge", "cart" }, /* 0 */ - { IO_FLOPPY, "floppydisk", "flop" }, /* 1 */ - { IO_HARDDISK, "harddisk", "hard" }, /* 2 */ - { IO_CYLINDER, "cylinder", "cyln" }, /* 3 */ - { IO_CASSETTE, "cassette", "cass" }, /* 4 */ - { IO_PUNCHCARD, "punchcard", "pcrd" }, /* 5 */ - { IO_PUNCHTAPE, "punchtape", "ptap" }, /* 6 */ - { IO_PRINTER, "printer", "prin" }, /* 7 */ - { IO_SERIAL, "serial", "serl" }, /* 8 */ - { IO_PARALLEL, "parallel", "parl" }, /* 9 */ - { IO_SNAPSHOT, "snapshot", "dump" }, /* 10 */ - { IO_QUICKLOAD, "quickload", "quik" }, /* 11 */ - { IO_MEMCARD, "memcard", "memc" }, /* 12 */ - { IO_CDROM, "cdrom", "cdrm" }, /* 13 */ - { IO_MAGTAPE, "magtape", "magt" }, /* 14 */ - }; - -//------------------------------------------------- -// legacy_image_device_config_base - constructor -//------------------------------------------------- - -legacy_image_device_config_base::legacy_image_device_config_base(const machine_config &mconfig, device_type type, const char *tag, const device_config *owner, UINT32 clock, device_get_config_func get_config) - : legacy_device_config_base(mconfig, type, tag, owner, clock, get_config), - device_config_image_interface(mconfig, *this), - m_create_option_guide(NULL), - m_formatlist(NULL) -{ -} - -//------------------------------------------------- -// device_config_complete - update configuration -// based on completed device setup -//------------------------------------------------- - -void legacy_image_device_config_base::device_config_complete() -{ - const device_config_image_interface *image = NULL; - int count = 0; - int index = -1; - image_device_format **formatptr; - image_device_format *format; - formatptr = &m_formatlist; - int cnt = 0; - - m_type = static_cast(get_legacy_config_int(DEVINFO_INT_IMAGE_TYPE)); - m_readable = get_legacy_config_int(DEVINFO_INT_IMAGE_READABLE)!=0; - m_writeable = get_legacy_config_int(DEVINFO_INT_IMAGE_WRITEABLE)!=0; - m_creatable = get_legacy_config_int(DEVINFO_INT_IMAGE_CREATABLE)!=0; - m_must_be_loaded = get_legacy_config_int(DEVINFO_INT_IMAGE_MUST_BE_LOADED)!=0; - m_reset_on_load = get_legacy_config_int(DEVINFO_INT_IMAGE_RESET_ON_LOAD)!=0; - m_has_partial_hash = get_legacy_config_int(DEVINFO_FCT_IMAGE_PARTIAL_HASH)!=0; - - m_interface_name = get_legacy_config_string(DEVINFO_STR_IMAGE_INTERFACE); - - m_file_extensions = get_legacy_config_string(DEVINFO_STR_IMAGE_FILE_EXTENSIONS); - - load = reinterpret_cast(get_legacy_config_fct(DEVINFO_FCT_IMAGE_LOAD)); - create = reinterpret_cast(get_legacy_config_fct(DEVINFO_FCT_IMAGE_CREATE)); - unload = reinterpret_cast(get_legacy_config_fct(DEVINFO_FCT_IMAGE_UNLOAD)); - display = reinterpret_cast(get_legacy_config_fct(DEVINFO_FCT_IMAGE_DISPLAY)); - partialhash = reinterpret_cast(get_legacy_config_fct(DEVINFO_FCT_IMAGE_PARTIAL_HASH)); - get_devices = reinterpret_cast(get_legacy_config_fct(DEVINFO_FCT_IMAGE_GET_DEVICES)); - - m_create_option_guide = reinterpret_cast(get_legacy_config_ptr(DEVINFO_PTR_IMAGE_CREATE_OPTGUIDE)); - - int format_count = get_legacy_config_int(DEVINFO_INT_IMAGE_CREATE_OPTCOUNT); - - for (int i = 0; i < format_count; i++) - { - // only add if creatable - if (get_legacy_config_string(DEVINFO_PTR_IMAGE_CREATE_OPTSPEC + i)) { - // allocate a new format - format = global_alloc_clear(image_device_format); - - // populate it - format->m_index = cnt; - format->m_name = get_legacy_config_string(DEVINFO_STR_IMAGE_CREATE_OPTNAME + i); - format->m_description = get_legacy_config_string(DEVINFO_STR_IMAGE_CREATE_OPTDESC + i); - format->m_extensions = get_legacy_config_string(DEVINFO_STR_IMAGE_CREATE_OPTEXTS + i); - format->m_optspec = get_legacy_config_string(DEVINFO_PTR_IMAGE_CREATE_OPTSPEC + i); - - // and append it to the list - *formatptr = format; - formatptr = &format->m_next; - cnt++; - } - } - - for (bool gotone = device_config_interface::m_machine_config.devicelist.first(image); gotone; gotone = image->next(image)) - { - if (this == image) - index = count; - if (image->image_type_direct() == m_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); - } - else - { - m_instance_name = device_typename(m_type); - m_brief_instance_name = device_brieftypename(m_type); - } - // Override in case of hardcoded values - if (strlen(get_legacy_config_string(DEVINFO_STR_IMAGE_INSTANCE_NAME))>0) { - m_instance_name = get_legacy_config_string(DEVINFO_STR_IMAGE_INSTANCE_NAME); - } - if (strlen(get_legacy_config_string(DEVINFO_STR_IMAGE_BRIEF_INSTANCE_NAME))>0) { - m_brief_instance_name = get_legacy_config_string(DEVINFO_STR_IMAGE_BRIEF_INSTANCE_NAME); - } -} - -//------------------------------------------------- -// find_device_type - search trough list of -// device types to extact data -//------------------------------------------------- - -const image_device_type_info *legacy_image_device_config_base::find_device_type(iodevice_t type) -{ - int i; - for (i = 0; i < ARRAY_LENGTH(legacy_image_device_config_base::m_device_info_array); i++) - { - if (m_device_info_array[i].m_type == type) - return &m_device_info_array[i]; - } - return NULL; -} - -//------------------------------------------------- -// device_typename - retrieves device type name -//------------------------------------------------- - -const char *legacy_image_device_config_base::device_typename(iodevice_t type) -{ - const image_device_type_info *info = find_device_type(type); - return (info != NULL) ? info->m_name : NULL; -} - -//------------------------------------------------- -// device_brieftypename - retrieves device -// brief type name -//------------------------------------------------- - -const char *legacy_image_device_config_base::device_brieftypename(iodevice_t type) -{ - const image_device_type_info *info = find_device_type(type); - return (info != NULL) ? info->m_shortname : NULL; -} - -//------------------------------------------------- -// uses_file_extension - update configuration -// based on completed device setup -//------------------------------------------------- - -bool legacy_image_device_config_base::uses_file_extension(const char *file_extension) const -{ - bool result = FALSE; - - if (file_extension[0] == '.') - file_extension++; - - /* find the extensions */ - char *ext = strtok((char*)m_file_extensions.cstr(),","); - while (ext != NULL) - { - if (!mame_stricmp(ext, file_extension)) - { - result = TRUE; - break; - } - ext = strtok (NULL, ","); - } - return result; -} - -//------------------------------------------------- -// ~legacy_device_config_base - destructor -//------------------------------------------------- - -legacy_image_device_config_base::~legacy_image_device_config_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); - } -} - - -//************************************************************************** -// LIVE LEGACY IMAGE DEVICE -//************************************************************************** - -//------------------------------------------------- -// legacy_image_device_base - constructor -//------------------------------------------------- - -legacy_image_device_base::legacy_image_device_base(running_machine &machine, const device_config &config) - : legacy_device_base(machine, config), - device_image_interface(machine, config, *this) -{ -} +} \ No newline at end of file diff --git a/src/emu/devlegcy.h b/src/emu/devlegcy.h index 84efeb00675..73329a2bf45 100644 --- a/src/emu/devlegcy.h +++ b/src/emu/devlegcy.h @@ -386,14 +386,6 @@ typedef INT32 (*device_execute_func)(device_t *device, INT32 clocks); typedef void (*device_reset_func)(device_t *device); typedef void (*device_nvram_func)(device_t *device, mame_file *file, int read_or_write); -// device image interface function types -typedef int (*device_image_load_func)(device_t *image); -typedef int (*device_image_create_func)(device_t *image, int format_type, option_resolution *format_options); -typedef void (*device_image_unload_func)(device_t *image); -typedef void (*device_image_display_func)(device_t *image); -typedef void (*device_image_partialhash_func)(char *, const unsigned char *, unsigned long, unsigned int); -typedef void (*device_image_get_devices_func)(device_t *device); - // the actual deviceinfo union union deviceinfo { @@ -578,28 +570,14 @@ protected: }; // ======================> legacy_image_device_config -struct image_device_format -{ - image_device_format *m_next; - int m_index; - astring m_name; - astring m_description; - astring m_extensions; - astring m_optspec; -}; - -struct image_device_type_info -{ - iodevice_t m_type; - astring m_name; - astring m_shortname; -}; // legacy_image_device_config is a device_config with a image interface class legacy_image_device_config_base : public legacy_device_config_base, public device_config_image_interface { + friend class legacy_image_device_base; public: + virtual const char *name() const { return get_legacy_config_string(DEVINFO_STR_NAME); } 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_config_int(DEVINFO_INT_IMAGE_TYPE)); } @@ -614,8 +592,7 @@ public: 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; - static const char *device_typename(iodevice_t type); - static const char *device_brieftypename(iodevice_t type); + protected: // construction/destruction legacy_image_device_config_base(const machine_config &mconfig, device_type type, const char *tag, const device_config *owner, UINT32 clock, device_get_config_func get_config); @@ -624,10 +601,6 @@ protected: // device_config overrides virtual void device_config_complete(); - static const image_device_type_info *find_device_type(iodevice_t type); - - static const image_device_type_info m_device_info_array[]; - iodevice_t m_type; bool m_readable; bool m_writeable; @@ -659,11 +632,42 @@ protected: class legacy_image_device_base : public legacy_device_base, public device_image_interface { + friend class legacy_image_device_config_base; +public: + virtual void set_working_directory(const char *working_directory) { m_working_directory = working_directory; } + virtual const char * working_directory(); + virtual bool load(const char *path); + virtual void unload(); protected: // construction/destruction legacy_image_device_base(running_machine &machine, const device_config &config); - // device_image_interface overrides + + /* working directory; persists across mounts */ + astring m_working_directory; + + /* variables that are only non-zero when an image is mounted */ + core_file *m_file; + astring m_name; + + /* error related info */ + image_error_t err; + astring err_message; + + + void setup_working_directory(); + bool try_change_working_directory(const char *subdir); + + 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 set_image_filename(const char *filename); + image_error_t load_image_by_path(UINT32 open_flags, const char *path); + void clear(); + void unload_internal(); + + /* flags */ + bool m_writeable; + bool m_created; }; diff --git a/src/emu/diimage.c b/src/emu/diimage.c index 9a6cf74ebdc..de807427fbe 100644 --- a/src/emu/diimage.c +++ b/src/emu/diimage.c @@ -44,9 +44,27 @@ //************************************************************************** // DEVICE CONFIG IMAGE INTERFACE //************************************************************************** +const image_device_type_info device_config_image_interface::m_device_info_array[] = + { + { IO_CARTSLOT, "cartridge", "cart" }, /* 0 */ + { IO_FLOPPY, "floppydisk", "flop" }, /* 1 */ + { IO_HARDDISK, "harddisk", "hard" }, /* 2 */ + { IO_CYLINDER, "cylinder", "cyln" }, /* 3 */ + { IO_CASSETTE, "cassette", "cass" }, /* 4 */ + { IO_PUNCHCARD, "punchcard", "pcrd" }, /* 5 */ + { IO_PUNCHTAPE, "punchtape", "ptap" }, /* 6 */ + { IO_PRINTER, "printer", "prin" }, /* 7 */ + { IO_SERIAL, "serial", "serl" }, /* 8 */ + { IO_PARALLEL, "parallel", "parl" }, /* 9 */ + { IO_SNAPSHOT, "snapshot", "dump" }, /* 10 */ + { IO_QUICKLOAD, "quickload", "quik" }, /* 11 */ + { IO_MEMCARD, "memcard", "memc" }, /* 12 */ + { IO_CDROM, "cdrom", "cdrm" }, /* 13 */ + { IO_MAGTAPE, "magtape", "magt" }, /* 14 */ + }; //------------------------------------------------- -// device_config_nvram_interface - constructor +// device_config_image_interface - constructor //------------------------------------------------- device_config_image_interface::device_config_image_interface(const machine_config &mconfig, device_config &devconfig) @@ -64,6 +82,42 @@ device_config_image_interface::~device_config_image_interface() } +//------------------------------------------------- +// find_device_type - search trough list of +// device types to extact data +//------------------------------------------------- + +const image_device_type_info *device_config_image_interface::find_device_type(iodevice_t type) +{ + int i; + for (i = 0; i < ARRAY_LENGTH(device_config_image_interface::m_device_info_array); i++) + { + if (m_device_info_array[i].m_type == type) + return &m_device_info_array[i]; + } + return NULL; +} + +//------------------------------------------------- +// device_typename - retrieves device type name +//------------------------------------------------- + +const char *device_config_image_interface::device_typename(iodevice_t type) +{ + const image_device_type_info *info = find_device_type(type); + return (info != NULL) ? info->m_name : NULL; +} + +//------------------------------------------------- +// device_brieftypename - retrieves device +// brief type name +//------------------------------------------------- + +const char *device_config_image_interface::device_brieftypename(iodevice_t type) +{ + const image_device_type_info *info = find_device_type(type); + return (info != NULL) ? info->m_shortname : NULL; +} //************************************************************************** // DEVICE image INTERFACE diff --git a/src/emu/diimage.h b/src/emu/diimage.h index 8473a3554ea..586a99796cf 100644 --- a/src/emu/diimage.h +++ b/src/emu/diimage.h @@ -73,18 +73,77 @@ enum iodevice_t IO_COUNT /* 16 - Total Number of IO_devices for searching */ }; +enum image_error_t +{ + IMAGE_ERROR_SUCCESS, + IMAGE_ERROR_INTERNAL, + IMAGE_ERROR_UNSUPPORTED, + IMAGE_ERROR_OUTOFMEMORY, + IMAGE_ERROR_FILENOTFOUND, + IMAGE_ERROR_INVALIDIMAGE, + IMAGE_ERROR_ALREADYOPEN, + IMAGE_ERROR_UNSPECIFIED +}; + +struct image_device_type_info +{ + iodevice_t m_type; + const char *m_name; + const char *m_shortname; +}; + +struct image_device_format +{ + image_device_format *m_next; + int m_index; + astring m_name; + astring m_description; + astring m_extensions; + astring m_optspec; +}; + +// device image interface function types +typedef int (*device_image_load_func)(device_t *image); +typedef int (*device_image_create_func)(device_t *image, int format_type, option_resolution *format_options); +typedef void (*device_image_unload_func)(device_t *image); +typedef void (*device_image_display_func)(device_t *image); +typedef void (*device_image_partialhash_func)(char *, const unsigned char *, unsigned long, unsigned int); +typedef void (*device_image_get_devices_func)(device_t *device); + + +//************************************************************************** +// MACROS +//************************************************************************** + +#define DEVICE_IMAGE_LOAD_NAME(name) device_load_##name +#define DEVICE_IMAGE_LOAD(name) int DEVICE_IMAGE_LOAD_NAME(name)(device_t *image) + +#define DEVICE_IMAGE_CREATE_NAME(name) device_create_##name +#define DEVICE_IMAGE_CREATE(name) int DEVICE_IMAGE_CREATE_NAME(name)(device_t *image, int create_format, option_resolution *create_args) + +#define DEVICE_IMAGE_UNLOAD_NAME(name) device_unload_##name +#define DEVICE_IMAGE_UNLOAD(name) void DEVICE_IMAGE_UNLOAD_NAME(name)(device_t *image) + +#define DEVICE_IMAGE_DISPLAY_NAME(name) device_image_display_func##name +#define DEVICE_IMAGE_DISPLAY(name) void DEVICE_IMAGE_DISPLAY_NAME(name)(device_t *image) + +#define DEVICE_IMAGE_GET_DEVICES_NAME(name) device_image_get_devices_##name +#define DEVICE_IMAGE_GET_DEVICES(name) void DEVICE_IMAGE_GET_DEVICES_NAME(name)(device_t *device) + // ======================> device_config_image_interface // class representing interface-specific configuration image class device_config_image_interface : public device_config_interface { + friend class device_image_interface; public: // construction/destruction device_config_image_interface(const machine_config &mconfig, device_config &device); virtual ~device_config_image_interface(); // public accessors... for now + virtual const char *name() const = 0; virtual iodevice_t image_type() const = 0; virtual const char *image_type_name() const = 0; virtual iodevice_t image_type_direct() const = 0; @@ -99,6 +158,12 @@ public: 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; + + static const char *device_typename(iodevice_t type); + static const char *device_brieftypename(iodevice_t type); +protected: + static const image_device_type_info *find_device_type(iodevice_t type); + static const image_device_type_info m_device_info_array[]; }; @@ -108,19 +173,24 @@ public: // class representing interface-specific live image class device_image_interface : public device_interface { + friend class device_config_image_interface; public: // construction/destruction device_image_interface(running_machine &machine, const device_config &config, device_t &device); virtual ~device_image_interface(); + virtual void set_working_directory(const char *working_directory) = 0; + virtual const char * working_directory() = 0; + virtual bool load(const char *path) = 0; + virtual void unload() = 0; + // configuration access const device_config_image_interface &image_config() const { return m_image_config; } - protected: // derived class overrides // configuration - const device_config_image_interface &m_image_config; // reference to our device_config_execute_interface + const device_config_image_interface &m_image_config; // reference to our device_config_execute_interface }; diff --git a/src/emu/emu.h b/src/emu/emu.h index 281e23235d8..c5625d6d60c 100644 --- a/src/emu/emu.h +++ b/src/emu/emu.h @@ -98,10 +98,12 @@ #include "romload.h" #include "state.h" +// image-related +#include "image.h" + // the running machine #ifdef MESS #include "mess.h" -#include "image.h" #include "messdrv.h" #endif /* MESS */ #include "mame.h" diff --git a/src/emu/emu.mak b/src/emu/emu.mak index 55e0923f6be..e96bf33ea71 100644 --- a/src/emu/emu.mak +++ b/src/emu/emu.mak @@ -46,6 +46,7 @@ EMUOBJS = \ $(EMUOBJ)/debugger.o \ $(EMUOBJ)/devcb.o \ $(EMUOBJ)/devcpu.o \ + $(EMUOBJ)/devimage.o \ $(EMUOBJ)/devlegcy.o \ $(EMUOBJ)/devintrf.o \ $(EMUOBJ)/didisasm.o \ @@ -64,6 +65,7 @@ EMUOBJS = \ $(EMUOBJ)/fileio.o \ $(EMUOBJ)/hash.o \ $(EMUOBJ)/hashfile.o \ + $(EMUOBJ)/image.o \ $(EMUOBJ)/info.o \ $(EMUOBJ)/input.o \ $(EMUOBJ)/inputseq.o \ diff --git a/src/emu/emuopts.c b/src/emu/emuopts.c index 94a7c81e3e7..629f89caa9f 100644 --- a/src/emu/emuopts.c +++ b/src/emu/emuopts.c @@ -207,14 +207,14 @@ static void mame_puts_error(const char *s) option -------------------------------------------------*/ -const char *image_get_device_option(device_t *image) +const char *image_get_device_option(device_image_interface *image) { const char *result = NULL; if (options_get_bool(mame_options(), OPTION_ADDED_DEVICE_OPTIONS)) { /* access the option */ - result = options_get_string(mame_options(), downcast(&image->baseconfig())->instance_name()); + result = options_get_string(mame_options(), image->image_config().instance_name()); } return result; } diff --git a/src/emu/emuopts.h b/src/emu/emuopts.h index b2cb0373447..c28e32fcc02 100644 --- a/src/emu/emuopts.h +++ b/src/emu/emuopts.h @@ -182,6 +182,6 @@ core_options *mame_options_init(const options_entry *entries); /* add the device options for a specified device */ void image_add_device_options(core_options *opts, const game_driver *driver); /* accesses a device option, by device and index */ -const char *image_get_device_option(device_t *image); +const char *image_get_device_option(device_image_interface *image); #endif /* __EMUOPTS_H__ */ diff --git a/src/emu/image.c b/src/emu/image.c new file mode 100644 index 00000000000..3405a47a7cb --- /dev/null +++ b/src/emu/image.c @@ -0,0 +1,168 @@ +/*************************************************************************** + + image.c + + Core image functions and definitions. + + Copyright Nicola Salmoria and the MAME Team. + Visit http://mamedev.org for licensing and usage restrictions. + +***************************************************************************/ + +#include "emu.h" +#include "emuopts.h" +#include "image.h" +#include "config.h" +#include "xmlfile.h" + + +/*************************************************************************** + INITIALIZATION HELPERS +***************************************************************************/ +//============================================================ +// filename_basename +//============================================================ + +static const char *filename_basename(const char *filename) +{ + const char *c; + + // NULL begets NULL + if (!filename) + return NULL; + + // start at the end and return when we hit a slash or colon + for (c = filename + strlen(filename) - 1; c >= filename; c--) + if (*c == '\\' || *c == '/' || *c == ':') + return c + 1; + + // otherwise, return the whole thing + return filename; +} + +/*------------------------------------------------- + image_dirs_load - loads image device directory + configuration items +-------------------------------------------------*/ + +static void image_dirs_load(running_machine *machine, int config_type, xml_data_node *parentnode) +{ + xml_data_node *node; + const char *dev_instance; + const char *working_directory; + device_image_interface *image = NULL; + + if ((config_type == CONFIG_TYPE_GAME) && (parentnode != NULL)) + { + for (node = xml_get_sibling(parentnode->child, "device"); node; node = xml_get_sibling(node->next, "device")) + { + dev_instance = xml_get_attribute_string(node, "instance", NULL); + + if ((dev_instance != NULL) && (dev_instance[0] != '\0')) + { + for (bool gotone = machine->devicelist.first(image); gotone; gotone = image->next(image)) + { + if (!strcmp(dev_instance, image->image_config().instance_name())) { + working_directory = xml_get_attribute_string(node, "directory", NULL); + if (working_directory != NULL) + image->set_working_directory(working_directory); + } + } + } + } + } +} + + + +/*------------------------------------------------- + image_dirs_save - saves out image device + directories to the configuration file +-------------------------------------------------*/ + +static void image_dirs_save(running_machine *machine, int config_type, xml_data_node *parentnode) +{ + xml_data_node *node; + const char *dev_instance; + device_image_interface *image = NULL; + + /* only care about game-specific data */ + if (config_type == CONFIG_TYPE_GAME) + { + for (bool gotone = machine->devicelist.first(image); gotone; gotone = image->next(image)) + { + dev_instance = image->image_config().instance_name(); + + node = xml_add_child(parentnode, "device", NULL); + if (node != NULL) + { + xml_set_attribute(node, "instance", dev_instance); + xml_set_attribute(node, "directory", image->working_directory()); + } + } + } +} + + +/*------------------------------------------------- + image_device_init - initialize devices for a specific + running_machine +-------------------------------------------------*/ + +void image_device_init(running_machine *machine) +{ + const char *image_name; + device_image_interface *image = NULL; + + /* make sure that any required devices have been allocated */ + for (bool gotone = machine->devicelist.first(image); gotone; gotone = image->next(image)) + { + /* is an image specified for this image */ + image_name = image_get_device_option(image); + + if ((image_name != NULL) && (image_name[0] != '\0')) + { + bool result = FALSE; + + /* try to load this image */ + result = image->load(image_name); + + /* did the image load fail? */ + if (!result) + { + /* retrieve image error message */ + const char *image_err = "error";// image_error(image); + char *image_basename = auto_strdup(machine, filename_basename(image_name)); + + /* unload all images */ + //image_unload_all(machine); + + fatalerror_exitcode(machine, MAMERR_DEVICE, "Device %s load (%s) failed: %s", + image->image_config().name(), + image_basename, + image_err); + } + } + else + { + /* no image... must this device be loaded? */ + if (image->image_config().must_be_loaded()) + { + fatalerror_exitcode(machine, MAMERR_DEVICE, "Driver requires that device \"%s\" must have an image to load", image->image_config().instance_name()); + } + } + } +} +/*************************************************************************** + INITIALIZATION +***************************************************************************/ + +/*------------------------------------------------- + image_init - start up the image system +-------------------------------------------------*/ + +void image_init(running_machine *machine) +{ + image_device_init(machine); + config_register(machine, "image_directories", image_dirs_load, image_dirs_save); +} diff --git a/src/emu/image.h b/src/emu/image.h new file mode 100644 index 00000000000..76072838a21 --- /dev/null +++ b/src/emu/image.h @@ -0,0 +1,23 @@ +/*************************************************************************** + + image.h + + Core image interface functions and definitions. + + Copyright Nicola Salmoria and the MAME Team. + Visit http://mamedev.org for licensing and usage restrictions. + +***************************************************************************/ + +#pragma once + +#ifndef __EMU_H__ +#error Dont include this file directly; include emu.h instead. +#endif + +#ifndef __IMAGE_H__ +#define __IMAGE_H__ + +void image_init(running_machine *machine); + +#endif /* __IMAGE_H__ */ diff --git a/src/emu/mame.c b/src/emu/mame.c index 188d29ad765..98c8318e87b 100644 --- a/src/emu/mame.c +++ b/src/emu/mame.c @@ -52,6 +52,7 @@ - calls the driver's MACHINE_START, SOUND_START, and VIDEO_START callbacks - calls saveload_init() [mame.c] to set up for save/load - calls cheat_init() [cheat.c] to initialize the cheat system + - calls image_init() [image.c] to initialize the image system - calls config_load_settings() [config.c] to load the configuration file - calls nvram_load [machine/generic.c] to load NVRAM @@ -77,6 +78,7 @@ #include "osdepend.h" #include "config.h" #include "debugger.h" +#include "image.h" #include "profiler.h" #include "render.h" #include "cheat.h" @@ -1267,9 +1269,6 @@ running_machine::running_machine(const game_driver *driver) generic_machine_data(NULL), generic_video_data(NULL), generic_audio_data(NULL), -#ifdef MESS - images_data(NULL), -#endif /* MESS */ driver_data(NULL) { try @@ -1418,10 +1417,8 @@ static void init_machine(running_machine *machine) /* initialize natural keyboard support */ inputx_init(machine); -#ifdef MESS - /* first MESS initialization */ - mess_predevice_init(machine); -#endif /* MESS */ + /* initialize image devices */ + image_init(machine); /* start up the devices */ machine->devicelist.start_all(); @@ -1433,11 +1430,6 @@ static void init_machine(running_machine *machine) if (machine->gamedrv->driver_init != NULL) (*machine->gamedrv->driver_init)(machine); -#ifdef MESS - /* second MESS initialization */ - mess_postdevice_init(machine); -#endif /* MESS */ - /* start the video and audio hardware */ video_init(machine); tilemap_init(machine); diff --git a/src/emu/mame.h b/src/emu/mame.h index b7f8c873978..7b2af0cc792 100644 --- a/src/emu/mame.h +++ b/src/emu/mame.h @@ -291,9 +291,6 @@ public: generic_machine_private *generic_machine_data; /* internal data from machine/generic.c */ generic_video_private * generic_video_data; /* internal data from video/generic.c */ generic_audio_private * generic_audio_data; /* internal data from audio/generic.c */ -#ifdef MESS - images_private * images_data; /* internal data from image.c */ -#endif /* MESS */ /* driver-specific information */ void * driver_data; /* drivers can hang data off of here instead of using globals */