|
|
|
@ -148,10 +148,10 @@ void device_image_interface::device_compute_hash(hash_collection &hashes, const
|
|
|
|
|
hashes.compute(reinterpret_cast<const UINT8 *>(data), length, types);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*-------------------------------------------------
|
|
|
|
|
set_image_filename - specifies the filename of
|
|
|
|
|
an image
|
|
|
|
|
-------------------------------------------------*/
|
|
|
|
|
//-------------------------------------------------
|
|
|
|
|
// set_image_filename - specifies the filename of
|
|
|
|
|
// an image
|
|
|
|
|
//-------------------------------------------------
|
|
|
|
|
|
|
|
|
|
image_error_t device_image_interface::set_image_filename(const char *filename)
|
|
|
|
|
{
|
|
|
|
@ -189,28 +189,29 @@ image_error_t device_image_interface::set_image_filename(const char *filename)
|
|
|
|
|
CREATION FORMATS
|
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
|
|
/*-------------------------------------------------
|
|
|
|
|
device_get_named_creatable_format -
|
|
|
|
|
accesses a specific image format available for
|
|
|
|
|
image creation by name
|
|
|
|
|
-------------------------------------------------*/
|
|
|
|
|
//-------------------------------------------------
|
|
|
|
|
// device_get_named_creatable_format -
|
|
|
|
|
// accesses a specific image format available for
|
|
|
|
|
// image creation by name
|
|
|
|
|
//-------------------------------------------------
|
|
|
|
|
|
|
|
|
|
const image_device_format *device_image_interface::device_get_named_creatable_format(const char *format_name)
|
|
|
|
|
{
|
|
|
|
|
for (auto &format : m_formatlist)
|
|
|
|
|
if (strcmp(format->name(), format_name) == 0)
|
|
|
|
|
if (strcmp(format->name().c_str(), format_name) == 0)
|
|
|
|
|
return format.get();
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
|
ERROR HANDLING
|
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
|
|
/*-------------------------------------------------
|
|
|
|
|
image_clear_error - clear out any specified
|
|
|
|
|
error
|
|
|
|
|
-------------------------------------------------*/
|
|
|
|
|
//-------------------------------------------------
|
|
|
|
|
// image_clear_error - clear out any specified
|
|
|
|
|
// error
|
|
|
|
|
//-------------------------------------------------
|
|
|
|
|
|
|
|
|
|
void device_image_interface::clear_error()
|
|
|
|
|
{
|
|
|
|
@ -223,10 +224,11 @@ void device_image_interface::clear_error()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*-------------------------------------------------
|
|
|
|
|
error - returns the error text for an image
|
|
|
|
|
error
|
|
|
|
|
-------------------------------------------------*/
|
|
|
|
|
//-------------------------------------------------
|
|
|
|
|
// error - returns the error text for an image
|
|
|
|
|
// error
|
|
|
|
|
//-------------------------------------------------
|
|
|
|
|
|
|
|
|
|
static const char *const messages[] =
|
|
|
|
|
{
|
|
|
|
|
"",
|
|
|
|
@ -246,9 +248,9 @@ const char *device_image_interface::error()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*-------------------------------------------------
|
|
|
|
|
seterror - specifies an error on an image
|
|
|
|
|
-------------------------------------------------*/
|
|
|
|
|
//-------------------------------------------------
|
|
|
|
|
// seterror - specifies an error on an image
|
|
|
|
|
//-------------------------------------------------
|
|
|
|
|
|
|
|
|
|
void device_image_interface::seterror(image_error_t err, const char *message)
|
|
|
|
|
{
|
|
|
|
@ -262,10 +264,10 @@ void device_image_interface::seterror(image_error_t err, const char *message)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*-------------------------------------------------
|
|
|
|
|
message - used to display a message while
|
|
|
|
|
loading
|
|
|
|
|
-------------------------------------------------*/
|
|
|
|
|
//-------------------------------------------------
|
|
|
|
|
// message - used to display a message while
|
|
|
|
|
// loading
|
|
|
|
|
//-------------------------------------------------
|
|
|
|
|
|
|
|
|
|
void device_image_interface::message(const char *format, ...)
|
|
|
|
|
{
|
|
|
|
@ -288,11 +290,12 @@ void device_image_interface::message(const char *format, ...)
|
|
|
|
|
WORKING DIRECTORIES
|
|
|
|
|
***************************************************************************/
|
|
|
|
|
|
|
|
|
|
/*-------------------------------------------------
|
|
|
|
|
try_change_working_directory - tries to change
|
|
|
|
|
the working directory, but only if the directory
|
|
|
|
|
actually exists
|
|
|
|
|
-------------------------------------------------*/
|
|
|
|
|
//-------------------------------------------------
|
|
|
|
|
// try_change_working_directory - tries to change
|
|
|
|
|
// the working directory, but only if the directory
|
|
|
|
|
// actually exists
|
|
|
|
|
//-------------------------------------------------
|
|
|
|
|
|
|
|
|
|
bool device_image_interface::try_change_working_directory(const char *subdir)
|
|
|
|
|
{
|
|
|
|
|
const osd::directory::entry *entry;
|
|
|
|
@ -314,26 +317,28 @@ bool device_image_interface::try_change_working_directory(const char *subdir)
|
|
|
|
|
directory.reset();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* did we successfully identify the directory? */
|
|
|
|
|
// did we successfully identify the directory?
|
|
|
|
|
if (success)
|
|
|
|
|
m_working_directory = util::zippath_combine(m_working_directory.c_str(), subdir);
|
|
|
|
|
|
|
|
|
|
return success;
|
|
|
|
|
}
|
|
|
|
|
/*-------------------------------------------------
|
|
|
|
|
setup_working_directory - sets up the working
|
|
|
|
|
directory according to a few defaults
|
|
|
|
|
-------------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//-------------------------------------------------
|
|
|
|
|
// setup_working_directory - sets up the working
|
|
|
|
|
// directory according to a few defaults
|
|
|
|
|
//-------------------------------------------------
|
|
|
|
|
|
|
|
|
|
void device_image_interface::setup_working_directory()
|
|
|
|
|
{
|
|
|
|
|
/* first set up the working directory to be the starting directory */
|
|
|
|
|
// first set up the working directory to be the starting directory
|
|
|
|
|
osd_get_full_path(m_working_directory, ".");
|
|
|
|
|
|
|
|
|
|
/* now try browsing down to "software" */
|
|
|
|
|
// now try browsing down to "software"
|
|
|
|
|
if (try_change_working_directory("software"))
|
|
|
|
|
{
|
|
|
|
|
/* now down to a directory for this computer */
|
|
|
|
|
// now down to a directory for this computer
|
|
|
|
|
int gamedrv = driver_list::find(device().machine().system());
|
|
|
|
|
while(gamedrv != -1 && !try_change_working_directory(driver_list::driver(gamedrv).name))
|
|
|
|
|
{
|
|
|
|
@ -342,6 +347,7 @@ void device_image_interface::setup_working_directory()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//-------------------------------------------------
|
|
|
|
|
// working_directory - returns the working
|
|
|
|
|
// directory to use for this image; this is
|
|
|
|
@ -350,7 +356,7 @@ void device_image_interface::setup_working_directory()
|
|
|
|
|
|
|
|
|
|
const char * device_image_interface::working_directory()
|
|
|
|
|
{
|
|
|
|
|
/* check to see if we've never initialized the working directory */
|
|
|
|
|
// check to see if we've never initialized the working directory
|
|
|
|
|
if (m_working_directory.empty())
|
|
|
|
|
setup_working_directory();
|
|
|
|
|
|
|
|
|
@ -358,9 +364,9 @@ const char * device_image_interface::working_directory()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*-------------------------------------------------
|
|
|
|
|
get_software_region
|
|
|
|
|
-------------------------------------------------*/
|
|
|
|
|
//-------------------------------------------------
|
|
|
|
|
// get_software_region
|
|
|
|
|
//-------------------------------------------------
|
|
|
|
|
|
|
|
|
|
UINT8 *device_image_interface::get_software_region(const char *tag)
|
|
|
|
|
{
|
|
|
|
@ -375,9 +381,9 @@ UINT8 *device_image_interface::get_software_region(const char *tag)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*-------------------------------------------------
|
|
|
|
|
image_get_software_region_length
|
|
|
|
|
-------------------------------------------------*/
|
|
|
|
|
//-------------------------------------------------
|
|
|
|
|
// image_get_software_region_length
|
|
|
|
|
//-------------------------------------------------
|
|
|
|
|
|
|
|
|
|
UINT32 device_image_interface::get_software_region_length(const char *tag)
|
|
|
|
|
{
|
|
|
|
@ -390,9 +396,9 @@ UINT32 device_image_interface::get_software_region_length(const char *tag)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*-------------------------------------------------
|
|
|
|
|
image_get_feature
|
|
|
|
|
-------------------------------------------------*/
|
|
|
|
|
//-------------------------------------------------
|
|
|
|
|
// image_get_feature
|
|
|
|
|
//-------------------------------------------------
|
|
|
|
|
|
|
|
|
|
const char *device_image_interface::get_feature(const char *feature_name)
|
|
|
|
|
{
|
|
|
|
@ -418,12 +424,13 @@ bool device_image_interface::load_software_region(const char *tag, optional_shar
|
|
|
|
|
return size > 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
|
Hash info loading
|
|
|
|
|
|
|
|
|
|
If the hash is not checked and the relevant info not loaded, force that info
|
|
|
|
|
to be loaded
|
|
|
|
|
****************************************************************************/
|
|
|
|
|
// ****************************************************************************
|
|
|
|
|
// Hash info loading
|
|
|
|
|
//
|
|
|
|
|
// If the hash is not checked and the relevant info not loaded, force that info
|
|
|
|
|
// to be loaded
|
|
|
|
|
// ****************************************************************************
|
|
|
|
|
|
|
|
|
|
void device_image_interface::run_hash(void (*partialhash)(hash_collection &, const unsigned char *, unsigned long, const char *),
|
|
|
|
|
hash_collection &hashes, const char *types)
|
|
|
|
@ -437,7 +444,7 @@ void device_image_interface::run_hash(void (*partialhash)(hash_collection &, con
|
|
|
|
|
buf.resize(size);
|
|
|
|
|
memset(&buf[0], 0, size);
|
|
|
|
|
|
|
|
|
|
/* read the file */
|
|
|
|
|
// read the file
|
|
|
|
|
fseek(0, SEEK_SET);
|
|
|
|
|
fread(&buf[0], size);
|
|
|
|
|
|
|
|
|
@ -446,7 +453,7 @@ void device_image_interface::run_hash(void (*partialhash)(hash_collection &, con
|
|
|
|
|
else
|
|
|
|
|
hashes.compute(&buf[0], size, types);
|
|
|
|
|
|
|
|
|
|
/* cleanup */
|
|
|
|
|
// cleanup
|
|
|
|
|
fseek(0, SEEK_SET);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -456,20 +463,20 @@ void device_image_interface::image_checkhash()
|
|
|
|
|
{
|
|
|
|
|
device_image_partialhash_func partialhash;
|
|
|
|
|
|
|
|
|
|
/* only calculate CRC if it hasn't been calculated, and the open_mode is read only */
|
|
|
|
|
// only calculate CRC if it hasn't been calculated, and the open_mode is read only
|
|
|
|
|
UINT32 crcval;
|
|
|
|
|
if (!m_hash.crc(crcval) && m_readonly && !m_created)
|
|
|
|
|
{
|
|
|
|
|
/* do not cause a linear read of 600 megs please */
|
|
|
|
|
/* TODO: use SHA1 in the CHD header as the hash */
|
|
|
|
|
// do not cause a linear read of 600 megs please
|
|
|
|
|
// TODO: use SHA1 in the CHD header as the hash
|
|
|
|
|
if (image_type() == IO_CDROM)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
/* Skip calculating the hash when we have an image mounted through a software list */
|
|
|
|
|
// Skip calculating the hash when we have an image mounted through a software list
|
|
|
|
|
if ( m_software_info_ptr )
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
/* retrieve the partial hash func */
|
|
|
|
|
// retrieve the partial hash func
|
|
|
|
|
partialhash = get_partial_hash();
|
|
|
|
|
|
|
|
|
|
run_hash(partialhash, m_hash, hash_collection::HASH_TYPES_ALL);
|
|
|
|
@ -487,20 +494,21 @@ UINT32 device_image_interface::crc()
|
|
|
|
|
return crc;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
|
Battery functions
|
|
|
|
|
|
|
|
|
|
These functions provide transparent access to battery-backed RAM on an
|
|
|
|
|
image; typically for cartridges.
|
|
|
|
|
****************************************************************************/
|
|
|
|
|
// ****************************************************************************
|
|
|
|
|
// Battery functions
|
|
|
|
|
//
|
|
|
|
|
// These functions provide transparent access to battery-backed RAM on an
|
|
|
|
|
// image; typically for cartridges.
|
|
|
|
|
// ****************************************************************************
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*-------------------------------------------------
|
|
|
|
|
battery_load - retrieves the battery
|
|
|
|
|
backed RAM for an image. The file name is
|
|
|
|
|
created from the machine driver name and the
|
|
|
|
|
image name.
|
|
|
|
|
-------------------------------------------------*/
|
|
|
|
|
//-------------------------------------------------
|
|
|
|
|
// battery_load - retrieves the battery
|
|
|
|
|
// backed RAM for an image. The file name is
|
|
|
|
|
// created from the machine driver name and the
|
|
|
|
|
// image name.
|
|
|
|
|
//-------------------------------------------------
|
|
|
|
|
|
|
|
|
|
void device_image_interface::battery_load(void *buffer, int length, int fill)
|
|
|
|
|
{
|
|
|
|
|
assert_always(buffer && (length > 0), "Must specify sensical buffer/length");
|
|
|
|
@ -515,7 +523,7 @@ void device_image_interface::battery_load(void *buffer, int length, int fill)
|
|
|
|
|
if (filerr == osd_file::error::NONE)
|
|
|
|
|
bytes_read = file.read(buffer, length);
|
|
|
|
|
|
|
|
|
|
/* fill remaining bytes (if necessary) */
|
|
|
|
|
// fill remaining bytes (if necessary)
|
|
|
|
|
memset(((char *)buffer) + bytes_read, fill, length - bytes_read);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -527,35 +535,38 @@ void device_image_interface::battery_load(void *buffer, int length, void *def_bu
|
|
|
|
|
int bytes_read = 0;
|
|
|
|
|
std::string fname = std::string(device().machine().system().name).append(PATH_SEPARATOR).append(m_basename_noext.c_str()).append(".nv");
|
|
|
|
|
|
|
|
|
|
/* try to open the battery file and read it in, if possible */
|
|
|
|
|
// try to open the battery file and read it in, if possible
|
|
|
|
|
emu_file file(device().machine().options().nvram_directory(), OPEN_FLAG_READ);
|
|
|
|
|
filerr = file.open(fname.c_str());
|
|
|
|
|
if (filerr == osd_file::error::NONE)
|
|
|
|
|
bytes_read = file.read(buffer, length);
|
|
|
|
|
|
|
|
|
|
/* if no file was present, copy the default battery */
|
|
|
|
|
// if no file was present, copy the default battery
|
|
|
|
|
if (bytes_read == 0 && def_buffer)
|
|
|
|
|
memcpy((char *)buffer, (char *)def_buffer, length);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*-------------------------------------------------
|
|
|
|
|
battery_save - stores the battery
|
|
|
|
|
backed RAM for an image. The file name is
|
|
|
|
|
created from the machine driver name and the
|
|
|
|
|
image name.
|
|
|
|
|
-------------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
//-------------------------------------------------
|
|
|
|
|
// battery_save - stores the battery
|
|
|
|
|
// backed RAM for an image. The file name is
|
|
|
|
|
// created from the machine driver name and the
|
|
|
|
|
// image name.
|
|
|
|
|
//-------------------------------------------------
|
|
|
|
|
|
|
|
|
|
void device_image_interface::battery_save(const void *buffer, int length)
|
|
|
|
|
{
|
|
|
|
|
assert_always(buffer && (length > 0), "Must specify sensical buffer/length");
|
|
|
|
|
std::string fname = std::string(device().machine().system().name).append(PATH_SEPARATOR).append(m_basename_noext.c_str()).append(".nv");
|
|
|
|
|
|
|
|
|
|
/* try to open the battery file and write it out, if possible */
|
|
|
|
|
// try to open the battery file and write it out, if possible
|
|
|
|
|
emu_file file(device().machine().options().nvram_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
|
|
|
|
|
osd_file::error filerr = file.open(fname.c_str());
|
|
|
|
|
if (filerr == osd_file::error::NONE)
|
|
|
|
|
file.write(buffer, length);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//-------------------------------------------------
|
|
|
|
|
// uses_file_extension - update configuration
|
|
|
|
|
// based on completed device setup
|
|
|
|
@ -583,38 +594,40 @@ bool device_image_interface::uses_file_extension(const char *file_extension) con
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
|
IMAGE LOADING
|
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
|
|
/*-------------------------------------------------
|
|
|
|
|
is_loaded - quick check to determine whether an
|
|
|
|
|
image is loaded
|
|
|
|
|
-------------------------------------------------*/
|
|
|
|
|
// ***************************************************************************
|
|
|
|
|
// IMAGE LOADING
|
|
|
|
|
// ***************************************************************************
|
|
|
|
|
|
|
|
|
|
//-------------------------------------------------
|
|
|
|
|
// is_loaded - quick check to determine whether an
|
|
|
|
|
// image is loaded
|
|
|
|
|
//-------------------------------------------------
|
|
|
|
|
|
|
|
|
|
bool device_image_interface::is_loaded()
|
|
|
|
|
{
|
|
|
|
|
return (m_file != nullptr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*-------------------------------------------------
|
|
|
|
|
load_image_by_path - loads an image with a
|
|
|
|
|
specific path
|
|
|
|
|
-------------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
//-------------------------------------------------
|
|
|
|
|
// 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)
|
|
|
|
|
{
|
|
|
|
|
image_error_t err;
|
|
|
|
|
std::string revised_path;
|
|
|
|
|
|
|
|
|
|
/* attempt to read the file */
|
|
|
|
|
// attempt to read the file
|
|
|
|
|
auto const filerr = util::zippath_fopen(path, open_flags, m_file, revised_path);
|
|
|
|
|
|
|
|
|
|
/* did the open succeed? */
|
|
|
|
|
// did the open succeed?
|
|
|
|
|
switch(filerr)
|
|
|
|
|
{
|
|
|
|
|
case osd_file::error::NONE:
|
|
|
|
|
/* success! */
|
|
|
|
|
// success!
|
|
|
|
|
m_readonly = (open_flags & OPEN_FLAG_WRITE) ? 0 : 1;
|
|
|
|
|
m_created = (open_flags & OPEN_FLAG_CREATE) ? 1 : 0;
|
|
|
|
|
err = IMAGE_ERROR_SUCCESS;
|
|
|
|
@ -622,17 +635,17 @@ image_error_t device_image_interface::load_image_by_path(UINT32 open_flags, cons
|
|
|
|
|
|
|
|
|
|
case osd_file::error::NOT_FOUND:
|
|
|
|
|
case osd_file::error::ACCESS_DENIED:
|
|
|
|
|
/* file not found (or otherwise cannot open); continue */
|
|
|
|
|
// file not found (or otherwise cannot open); continue
|
|
|
|
|
err = IMAGE_ERROR_FILENOTFOUND;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case osd_file::error::OUT_OF_MEMORY:
|
|
|
|
|
/* out of memory */
|
|
|
|
|
// out of memory
|
|
|
|
|
err = IMAGE_ERROR_OUTOFMEMORY;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case osd_file::error::ALREADY_OPEN:
|
|
|
|
|
/* this shouldn't happen */
|
|
|
|
|
// this shouldn't happen
|
|
|
|
|
err = IMAGE_ERROR_ALREADYOPEN;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
@ -640,12 +653,12 @@ image_error_t device_image_interface::load_image_by_path(UINT32 open_flags, cons
|
|
|
|
|
case osd_file::error::TOO_MANY_FILES:
|
|
|
|
|
case osd_file::error::INVALID_DATA:
|
|
|
|
|
default:
|
|
|
|
|
/* other errors */
|
|
|
|
|
// other errors
|
|
|
|
|
err = IMAGE_ERROR_INTERNAL;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* if successful, set the file name */
|
|
|
|
|
// if successful, set the file name
|
|
|
|
|
if (filerr == osd_file::error::NONE)
|
|
|
|
|
set_image_filename(revised_path.c_str());
|
|
|
|
|
|
|
|
|
@ -659,14 +672,14 @@ int device_image_interface::reopen_for_write(const char *path)
|
|
|
|
|
image_error_t err;
|
|
|
|
|
std::string revised_path;
|
|
|
|
|
|
|
|
|
|
/* attempt to open the file for writing*/
|
|
|
|
|
// attempt to open the file for writing
|
|
|
|
|
auto const filerr = util::zippath_fopen(path, OPEN_FLAG_READ|OPEN_FLAG_WRITE|OPEN_FLAG_CREATE, m_file, revised_path);
|
|
|
|
|
|
|
|
|
|
/* did the open succeed? */
|
|
|
|
|
// did the open succeed?
|
|
|
|
|
switch(filerr)
|
|
|
|
|
{
|
|
|
|
|
case osd_file::error::NONE:
|
|
|
|
|
/* success! */
|
|
|
|
|
// success!
|
|
|
|
|
m_readonly = 0;
|
|
|
|
|
m_created = 1;
|
|
|
|
|
err = IMAGE_ERROR_SUCCESS;
|
|
|
|
@ -674,17 +687,17 @@ int device_image_interface::reopen_for_write(const char *path)
|
|
|
|
|
|
|
|
|
|
case osd_file::error::NOT_FOUND:
|
|
|
|
|
case osd_file::error::ACCESS_DENIED:
|
|
|
|
|
/* file not found (or otherwise cannot open); continue */
|
|
|
|
|
// file not found (or otherwise cannot open); continue
|
|
|
|
|
err = IMAGE_ERROR_FILENOTFOUND;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case osd_file::error::OUT_OF_MEMORY:
|
|
|
|
|
/* out of memory */
|
|
|
|
|
// out of memory
|
|
|
|
|
err = IMAGE_ERROR_OUTOFMEMORY;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case osd_file::error::ALREADY_OPEN:
|
|
|
|
|
/* this shouldn't happen */
|
|
|
|
|
// this shouldn't happen
|
|
|
|
|
err = IMAGE_ERROR_ALREADYOPEN;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
@ -692,28 +705,29 @@ int device_image_interface::reopen_for_write(const char *path)
|
|
|
|
|
case osd_file::error::TOO_MANY_FILES:
|
|
|
|
|
case osd_file::error::INVALID_DATA:
|
|
|
|
|
default:
|
|
|
|
|
/* other errors */
|
|
|
|
|
// other errors
|
|
|
|
|
err = IMAGE_ERROR_INTERNAL;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* if successful, set the file name */
|
|
|
|
|
// if successful, set the file name
|
|
|
|
|
if (filerr == osd_file::error::NONE)
|
|
|
|
|
set_image_filename(revised_path.c_str());
|
|
|
|
|
|
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*-------------------------------------------------
|
|
|
|
|
determine_open_plan - determines which open
|
|
|
|
|
flags to use, and in what order
|
|
|
|
|
-------------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
//-------------------------------------------------
|
|
|
|
|
// 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 */
|
|
|
|
|
// 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())
|
|
|
|
@ -725,11 +739,12 @@ void device_image_interface::determine_open_plan(int is_create, UINT32 *open_pla
|
|
|
|
|
open_plan[i] = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*-------------------------------------------------
|
|
|
|
|
dump_wrong_and_correct_checksums - dump an
|
|
|
|
|
error message containing the wrong and the
|
|
|
|
|
correct checksums for a given software item
|
|
|
|
|
-------------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
//-------------------------------------------------
|
|
|
|
|
// dump_wrong_and_correct_checksums - dump an
|
|
|
|
|
// error message containing the wrong and the
|
|
|
|
|
// correct checksums for a given software item
|
|
|
|
|
//-------------------------------------------------
|
|
|
|
|
|
|
|
|
|
static void dump_wrong_and_correct_checksums(const hash_collection &hashes, const hash_collection &acthashes)
|
|
|
|
|
{
|
|
|
|
@ -737,17 +752,18 @@ static void dump_wrong_and_correct_checksums(const hash_collection &hashes, cons
|
|
|
|
|
osd_printf_error(" FOUND: %s\n", acthashes.macro_string().c_str());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*-------------------------------------------------
|
|
|
|
|
verify_length_and_hash - verify the length
|
|
|
|
|
and hash signatures of a file
|
|
|
|
|
-------------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
//-------------------------------------------------
|
|
|
|
|
// verify_length_and_hash - verify the length
|
|
|
|
|
// and hash signatures of a file
|
|
|
|
|
//-------------------------------------------------
|
|
|
|
|
|
|
|
|
|
static int verify_length_and_hash(emu_file *file, const char *name, UINT32 explength, const hash_collection &hashes)
|
|
|
|
|
{
|
|
|
|
|
int retVal = 0;
|
|
|
|
|
if (file==nullptr) return 0;
|
|
|
|
|
|
|
|
|
|
/* verify length */
|
|
|
|
|
// verify length
|
|
|
|
|
UINT32 actlength = file->size();
|
|
|
|
|
if (explength != actlength)
|
|
|
|
|
{
|
|
|
|
@ -755,21 +771,21 @@ static int verify_length_and_hash(emu_file *file, const char *name, UINT32 exple
|
|
|
|
|
retVal++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* If there is no good dump known, write it */
|
|
|
|
|
// If there is no good dump known, write it
|
|
|
|
|
hash_collection &acthashes = file->hashes(hashes.hash_types().c_str());
|
|
|
|
|
if (hashes.flag(hash_collection::FLAG_NO_DUMP))
|
|
|
|
|
{
|
|
|
|
|
osd_printf_error("%s NO GOOD DUMP KNOWN\n", name);
|
|
|
|
|
}
|
|
|
|
|
/* verify checksums */
|
|
|
|
|
// verify checksums
|
|
|
|
|
else if (hashes != acthashes)
|
|
|
|
|
{
|
|
|
|
|
/* otherwise, it's just bad */
|
|
|
|
|
// otherwise, it's just bad
|
|
|
|
|
osd_printf_error("%s WRONG CHECKSUMS:\n", name);
|
|
|
|
|
dump_wrong_and_correct_checksums(hashes, acthashes);
|
|
|
|
|
retVal++;
|
|
|
|
|
}
|
|
|
|
|
/* If it matches, but it is actually a bad dump, write it */
|
|
|
|
|
// If it matches, but it is actually a bad dump, write it
|
|
|
|
|
else if (hashes.flag(hash_collection::FLAG_BAD_DUMP))
|
|
|
|
|
{
|
|
|
|
|
osd_printf_error("%s NEEDS REDUMP\n",name);
|
|
|
|
@ -777,9 +793,10 @@ static int verify_length_and_hash(emu_file *file, const char *name, UINT32 exple
|
|
|
|
|
return retVal;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*-------------------------------------------------
|
|
|
|
|
load_software - software image loading
|
|
|
|
|
-------------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
//-------------------------------------------------
|
|
|
|
|
// load_software - software image loading
|
|
|
|
|
//-------------------------------------------------
|
|
|
|
|
|
|
|
|
|
bool device_image_interface::load_software(software_list_device &swlist, const char *swname, const rom_entry *start)
|
|
|
|
|
{
|
|
|
|
@ -789,11 +806,11 @@ bool device_image_interface::load_software(software_list_device &swlist, const c
|
|
|
|
|
int warningcount = 0;
|
|
|
|
|
for (region = start; region != nullptr; region = rom_next_region(region))
|
|
|
|
|
{
|
|
|
|
|
/* loop until we hit the end of this region */
|
|
|
|
|
// loop until we hit the end of this region
|
|
|
|
|
const rom_entry *romp = region + 1;
|
|
|
|
|
while (!ROMENTRY_ISREGIONEND(romp))
|
|
|
|
|
{
|
|
|
|
|
/* handle files */
|
|
|
|
|
// handle files
|
|
|
|
|
if (ROMENTRY_ISFILE(romp))
|
|
|
|
|
{
|
|
|
|
|
osd_file::error filerr = osd_file::error::NOT_FOUND;
|
|
|
|
@ -882,9 +899,10 @@ bool device_image_interface::load_software(software_list_device &swlist, const c
|
|
|
|
|
return retVal;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*-------------------------------------------------
|
|
|
|
|
load_internal - core image loading
|
|
|
|
|
-------------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
//-------------------------------------------------
|
|
|
|
|
// load_internal - core image loading
|
|
|
|
|
//-------------------------------------------------
|
|
|
|
|
|
|
|
|
|
bool device_image_interface::load_internal(const char *path, bool is_create, int create_format, option_resolution *create_args, bool just_load)
|
|
|
|
|
{
|
|
|
|
@ -897,16 +915,16 @@ bool device_image_interface::load_internal(const char *path, bool is_create, int
|
|
|
|
|
std::string pathstr(path);
|
|
|
|
|
bool filename_has_period = (pathstr.find_last_of('.') != -1) ? TRUE : FALSE;
|
|
|
|
|
|
|
|
|
|
/* first unload the image */
|
|
|
|
|
// first unload the image
|
|
|
|
|
unload();
|
|
|
|
|
|
|
|
|
|
/* clear any possible error messages */
|
|
|
|
|
// clear any possible error messages
|
|
|
|
|
clear_error();
|
|
|
|
|
|
|
|
|
|
/* we are now loading */
|
|
|
|
|
// we are now loading
|
|
|
|
|
m_is_loading = TRUE;
|
|
|
|
|
|
|
|
|
|
/* record the filename */
|
|
|
|
|
// record the filename
|
|
|
|
|
m_err = set_image_filename(path);
|
|
|
|
|
|
|
|
|
|
if (m_err)
|
|
|
|
@ -914,7 +932,7 @@ bool device_image_interface::load_internal(const char *path, bool is_create, int
|
|
|
|
|
|
|
|
|
|
if (core_opens_image_file())
|
|
|
|
|
{
|
|
|
|
|
/* Check if there's a software list defined for this device and use that if we're not creating an image */
|
|
|
|
|
// 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 && !just_load)
|
|
|
|
|
{
|
|
|
|
|
softload = load_software_part(path, m_software_part_ptr);
|
|
|
|
@ -941,20 +959,20 @@ bool device_image_interface::load_internal(const char *path, bool is_create, int
|
|
|
|
|
|
|
|
|
|
if (is_create || filename_has_period)
|
|
|
|
|
{
|
|
|
|
|
/* determine open plan */
|
|
|
|
|
// determine open plan
|
|
|
|
|
determine_open_plan(is_create, open_plan);
|
|
|
|
|
|
|
|
|
|
/* attempt to open the file in various ways */
|
|
|
|
|
// attempt to open the file in various ways
|
|
|
|
|
for (i = 0; !m_file && open_plan[i]; i++)
|
|
|
|
|
{
|
|
|
|
|
/* open the file */
|
|
|
|
|
// 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 */
|
|
|
|
|
// Copy some image information when we have been loaded through a software list
|
|
|
|
|
if ( m_software_info_ptr )
|
|
|
|
|
{
|
|
|
|
|
// sanitize
|
|
|
|
@ -968,7 +986,7 @@ bool device_image_interface::load_internal(const char *path, bool is_create, int
|
|
|
|
|
//m_playable = m_software_info_ptr->supported();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* did we fail to find the file? */
|
|
|
|
|
// did we fail to find the file?
|
|
|
|
|
if (!is_loaded() && !softload)
|
|
|
|
|
{
|
|
|
|
|
m_err = IMAGE_ERROR_FILENOTFOUND;
|
|
|
|
@ -976,7 +994,7 @@ bool device_image_interface::load_internal(const char *path, bool is_create, int
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* call device load or create */
|
|
|
|
|
// call device load or create
|
|
|
|
|
m_create_format = create_format;
|
|
|
|
|
m_create_args = create_args;
|
|
|
|
|
|
|
|
|
@ -985,7 +1003,7 @@ bool device_image_interface::load_internal(const char *path, bool is_create, int
|
|
|
|
|
if (m_err)
|
|
|
|
|
goto done;
|
|
|
|
|
}
|
|
|
|
|
/* success! */
|
|
|
|
|
// success!
|
|
|
|
|
|
|
|
|
|
done:
|
|
|
|
|
if (just_load) {
|
|
|
|
@ -1022,18 +1040,19 @@ done:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*-------------------------------------------------
|
|
|
|
|
load - load an image into MESS
|
|
|
|
|
-------------------------------------------------*/
|
|
|
|
|
//-------------------------------------------------
|
|
|
|
|
// load - load an image into MAME
|
|
|
|
|
//-------------------------------------------------
|
|
|
|
|
|
|
|
|
|
bool device_image_interface::load(const char *path)
|
|
|
|
|
{
|
|
|
|
|
return load_internal(path, FALSE, 0, nullptr, FALSE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*-------------------------------------------------
|
|
|
|
|
open_image_file - opening plain image file
|
|
|
|
|
-------------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
//-------------------------------------------------
|
|
|
|
|
// open_image_file - opening plain image file
|
|
|
|
|
//-------------------------------------------------
|
|
|
|
|
|
|
|
|
|
bool device_image_interface::open_image_file(emu_options &options)
|
|
|
|
|
{
|
|
|
|
@ -1049,10 +1068,11 @@ bool device_image_interface::open_image_file(emu_options &options)
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*-------------------------------------------------
|
|
|
|
|
image_finish_load - special call - only use
|
|
|
|
|
from core
|
|
|
|
|
-------------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
//-------------------------------------------------
|
|
|
|
|
// image_finish_load - special call - only use
|
|
|
|
|
// from core
|
|
|
|
|
//-------------------------------------------------
|
|
|
|
|
|
|
|
|
|
bool device_image_interface::finish_load()
|
|
|
|
|
{
|
|
|
|
@ -1073,7 +1093,7 @@ bool device_image_interface::finish_load()
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/* using device load */
|
|
|
|
|
// using device load
|
|
|
|
|
err = call_load();
|
|
|
|
|
if (err)
|
|
|
|
|
{
|
|
|
|
@ -1089,9 +1109,10 @@ bool device_image_interface::finish_load()
|
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*-------------------------------------------------
|
|
|
|
|
create - create a image
|
|
|
|
|
-------------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
//-------------------------------------------------
|
|
|
|
|
// create - create a image
|
|
|
|
|
//-------------------------------------------------
|
|
|
|
|
|
|
|
|
|
bool device_image_interface::create(const char *path, const image_device_format *create_format, option_resolution *create_args)
|
|
|
|
|
{
|
|
|
|
@ -1109,10 +1130,10 @@ bool device_image_interface::create(const char *path, const image_device_format
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*-------------------------------------------------
|
|
|
|
|
clear - clear all internal data pertaining
|
|
|
|
|
to an image
|
|
|
|
|
-------------------------------------------------*/
|
|
|
|
|
//-------------------------------------------------
|
|
|
|
|
// clear - clear all internal data pertaining
|
|
|
|
|
// to an image
|
|
|
|
|
//-------------------------------------------------
|
|
|
|
|
|
|
|
|
|
void device_image_interface::clear()
|
|
|
|
|
{
|
|
|
|
@ -1136,9 +1157,10 @@ void device_image_interface::clear()
|
|
|
|
|
m_software_list_name.clear();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*-------------------------------------------------
|
|
|
|
|
unload - main call to unload an image
|
|
|
|
|
-------------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
//-------------------------------------------------
|
|
|
|
|
// unload - main call to unload an image
|
|
|
|
|
//-------------------------------------------------
|
|
|
|
|
|
|
|
|
|
void device_image_interface::unload()
|
|
|
|
|
{
|
|
|
|
@ -1150,9 +1172,10 @@ void device_image_interface::unload()
|
|
|
|
|
clear_error();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*-------------------------------------------------
|
|
|
|
|
update_names - update brief and instance names
|
|
|
|
|
-------------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
//-------------------------------------------------
|
|
|
|
|
// update_names - update brief and instance names
|
|
|
|
|
//-------------------------------------------------
|
|
|
|
|
|
|
|
|
|
void device_image_interface::update_names(const device_type device_type, const char *inst, const char *brief)
|
|
|
|
|
{
|
|
|
|
@ -1357,7 +1380,7 @@ std::string device_image_interface::software_get_default_slot(const char *defaul
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ----------------------------------------------------------------------- */
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
static int image_fseek_thunk(void *file, INT64 offset, int whence)
|
|
|
|
|
{
|
|
|
|
@ -1383,7 +1406,7 @@ static UINT64 image_fsize_thunk(void *file)
|
|
|
|
|
return image->length();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ----------------------------------------------------------------------- */
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
struct io_procs image_ioprocs =
|
|
|
|
|
{
|
|
|
|
|