Cleanup of image device base classes and prepare for rewrite (no whatsnew)

This commit is contained in:
Miodrag Milanovic 2011-06-10 14:54:08 +00:00
parent 6312851a55
commit 2749c957bc
4 changed files with 540 additions and 585 deletions

View File

@ -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<device_image_partialhash_func>(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<iodevice_t>(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<const option_guide *>(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<device_image_load_func>(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<device_image_create_func>(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<device_image_partialhash_func>(get_legacy_fct(DEVINFO_FCT_IMAGE_PARTIAL_HASH));
}
void legacy_image_device_base::call_get_devices()
{
device_image_get_devices_func func = reinterpret_cast<device_image_get_devices_func>(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<device_image_partialhash_func>(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);

View File

@ -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<iodevice_t>(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<iodevice_t>(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<const option_guide *>(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;
};

View File

@ -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();
}

View File

@ -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;
};