mirror of
https://github.com/holub/mame
synced 2025-04-28 11:11:48 +03:00
Cleanup of image device base classes and prepare for rewrite (no whatsnew)
This commit is contained in:
parent
6312851a55
commit
2749c957bc
@ -39,9 +39,7 @@
|
|||||||
|
|
||||||
|
|
||||||
#include "emu.h"
|
#include "emu.h"
|
||||||
#include "emuopts.h"
|
|
||||||
#include "devlegcy.h"
|
#include "devlegcy.h"
|
||||||
#include "zippath.h"
|
|
||||||
|
|
||||||
|
|
||||||
//**************************************************************************
|
//**************************************************************************
|
||||||
@ -54,20 +52,6 @@
|
|||||||
|
|
||||||
legacy_image_device_base::~legacy_image_device_base()
|
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_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),
|
: legacy_device_base(mconfig, type, tag, owner, clock, get_config),
|
||||||
device_image_interface(mconfig, *this),
|
device_image_interface(mconfig, *this)
|
||||||
m_create_option_guide(NULL),
|
|
||||||
m_formatlist(NULL),
|
|
||||||
m_is_loading(FALSE)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -103,20 +84,6 @@ void legacy_image_device_base::device_config_complete()
|
|||||||
formatptr = &m_formatlist;
|
formatptr = &m_formatlist;
|
||||||
int cnt = 0;
|
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);
|
int format_count = get_legacy_int(DEVINFO_INT_IMAGE_CREATE_OPTCOUNT);
|
||||||
|
|
||||||
for (int i = 0; i < format_count; i++)
|
for (int i = 0; i < format_count; i++)
|
||||||
@ -144,482 +111,29 @@ void legacy_image_device_base::device_config_complete()
|
|||||||
{
|
{
|
||||||
if (this == image)
|
if (this == image)
|
||||||
index = count;
|
index = count;
|
||||||
if (image->image_type_direct() == m_type)
|
if (image->image_type() == image_type())
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
if (count > 1) {
|
if (count > 1) {
|
||||||
m_instance_name.printf("%s%d", device_typename(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(m_type), index + 1);
|
m_brief_instance_name.printf("%s%d", device_brieftypename(image_type()), index + 1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_instance_name = device_typename(m_type);
|
m_instance_name = device_typename(image_type());
|
||||||
m_brief_instance_name = device_brieftypename(m_type);
|
m_brief_instance_name = device_brieftypename(image_type());
|
||||||
}
|
}
|
||||||
// Override in case of hardcoded values
|
// Override in case of hardcoded values
|
||||||
if (strlen(get_legacy_string(DEVINFO_STR_IMAGE_INSTANCE_NAME))>0) {
|
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) {
|
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);
|
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 legacy_image_device_base::call_load()
|
||||||
{
|
|
||||||
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()
|
|
||||||
{
|
{
|
||||||
device_image_load_func func = reinterpret_cast<device_image_load_func>(get_legacy_fct(DEVINFO_FCT_IMAGE_LOAD));
|
device_image_load_func func = reinterpret_cast<device_image_load_func>(get_legacy_fct(DEVINFO_FCT_IMAGE_LOAD));
|
||||||
if (func) {
|
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));
|
device_image_create_func func = reinterpret_cast<device_image_create_func>(get_legacy_fct(DEVINFO_FCT_IMAGE_CREATE));
|
||||||
if (func) {
|
if (func) {
|
||||||
@ -667,17 +181,17 @@ void legacy_image_device_base::call_display_info()
|
|||||||
if (func) (*func)(*this);
|
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()
|
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));
|
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);
|
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()
|
void *legacy_image_device_base::get_device_specific_call()
|
||||||
{
|
{
|
||||||
return (void*) get_legacy_fct(DEVINFO_FCT_DEVICE_SPECIFIC);
|
return (void*) get_legacy_fct(DEVINFO_FCT_DEVICE_SPECIFIC);
|
||||||
|
@ -513,70 +513,33 @@ class legacy_image_device_base : public legacy_device_base,
|
|||||||
public device_image_interface
|
public device_image_interface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual iodevice_t image_type() const { return m_type; }
|
virtual bool call_load();
|
||||||
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_softlist_load(char *swlist, char *swname, rom_entry *start_entry);
|
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_unload();
|
||||||
virtual void call_display();
|
virtual void call_display();
|
||||||
virtual void call_display_info();
|
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 call_get_devices();
|
||||||
virtual void *get_device_specific_call();
|
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:
|
protected:
|
||||||
// device overrides
|
// device overrides
|
||||||
virtual void device_config_complete();
|
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
|
// 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(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();
|
~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;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -81,7 +81,9 @@ device_image_interface::device_image_interface(const machine_config &mconfig, de
|
|||||||
m_software_info_ptr(NULL),
|
m_software_info_ptr(NULL),
|
||||||
m_software_part_ptr(NULL),
|
m_software_part_ptr(NULL),
|
||||||
m_readonly(false),
|
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()
|
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);
|
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();
|
||||||
|
}
|
||||||
|
@ -158,51 +158,36 @@ public:
|
|||||||
device_image_interface(const machine_config &mconfig, device_t &device);
|
device_image_interface(const machine_config &mconfig, device_t &device);
|
||||||
virtual ~device_image_interface();
|
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_typename(iodevice_t type);
|
||||||
static const char *device_brieftypename(iodevice_t type);
|
static const char *device_brieftypename(iodevice_t type);
|
||||||
static iodevice_t device_typeid(const char *name);
|
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 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 call_load() = 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_softlist_load(char *swlist, char *swname, rom_entry *start_entry) = 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_unload() = 0;
|
||||||
virtual void call_display() = 0;
|
virtual void call_display() = 0;
|
||||||
virtual void call_display_info() = 0;
|
virtual void call_display_info() = 0;
|
||||||
virtual void call_get_devices() = 0;
|
virtual void call_get_devices() = 0;
|
||||||
virtual void *get_device_specific_call() = 0;
|
virtual void *get_device_specific_call() = 0;
|
||||||
|
virtual device_image_partialhash_func get_partial_hash() const = 0;
|
||||||
virtual const image_device_format *device_get_indexed_creatable_format(int index);
|
virtual iodevice_t image_type() const = 0;
|
||||||
virtual const image_device_format *device_get_named_creatable_format(const char *format_name);
|
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 option_guide *device_get_creation_option_guide() { return create_option_guide(); }
|
||||||
const image_device_format *device_get_creatable_formats() { return formatlist(); }
|
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();
|
const char *error();
|
||||||
void seterror(image_error_t err, const char *message);
|
void seterror(image_error_t err, const char *message);
|
||||||
void message(const char *format, ...);
|
void message(const char *format, ...);
|
||||||
@ -236,8 +221,8 @@ public:
|
|||||||
const software_info *software_entry() { return m_software_info_ptr; }
|
const software_info *software_entry() { return m_software_info_ptr; }
|
||||||
const software_part *part_entry() { return m_software_part_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; }
|
void set_working_directory(const char *working_directory) { m_working_directory = working_directory; }
|
||||||
virtual const char * working_directory();
|
const char * working_directory();
|
||||||
|
|
||||||
UINT8 *get_software_region(const char *tag);
|
UINT8 *get_software_region(const char *tag);
|
||||||
UINT32 get_software_region_length(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_load(void *buffer, int length, int fill);
|
||||||
void battery_save(const void *buffer, int length);
|
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:
|
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);
|
image_error_t set_image_filename(const char *filename);
|
||||||
|
|
||||||
void clear_error();
|
void clear_error();
|
||||||
@ -304,6 +310,14 @@ protected:
|
|||||||
option_resolution *m_create_args;
|
option_resolution *m_create_args;
|
||||||
|
|
||||||
hash_collection m_hash;
|
hash_collection m_hash;
|
||||||
|
|
||||||
|
astring m_brief_instance_name;
|
||||||
|
astring m_instance_name;
|
||||||
|
|
||||||
|
/* creation info */
|
||||||
|
image_device_format *m_formatlist;
|
||||||
|
|
||||||
|
bool m_is_loading;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user