diff options
Diffstat (limited to 'src/emu/diimage.cpp')
-rw-r--r-- | src/emu/diimage.cpp | 1118 |
1 files changed, 455 insertions, 663 deletions
diff --git a/src/emu/diimage.cpp b/src/emu/diimage.cpp index 953e89dc42c..59d1523a6b1 100644 --- a/src/emu/diimage.cpp +++ b/src/emu/diimage.cpp @@ -2,7 +2,7 @@ // copyright-holders:Miodrag Milanovic /*************************************************************************** - diimage.c + diimage.cpp Device image interfaces. @@ -11,44 +11,20 @@ #include "emu.h" #include "emuopts.h" -#include "drivenum.h" +#include "fileio.h" #include "romload.h" -#include "ui/uimain.h" -#include "zippath.h" #include "softlist.h" #include "softlist_dev.h" -#include "formats/ioprocs.h" - -#include <regex> +#include "corestr.h" +#include "opresolv.h" +#include "path.h" +#include "zippath.h" -//************************************************************************** -// DEVICE CONFIG IMAGE INTERFACE -//************************************************************************** -const image_device_type_info device_image_interface::m_device_info_array[] = - { - { IO_UNKNOWN, "unknown", "unkn" }, /* 0 */ - { IO_CARTSLOT, "cartridge", "cart" }, /* 1 */ - { IO_FLOPPY, "floppydisk", "flop" }, /* 2 */ - { IO_HARDDISK, "harddisk", "hard" }, /* 3 */ - { IO_CYLINDER, "cylinder", "cyln" }, /* 4 */ - { IO_CASSETTE, "cassette", "cass" }, /* 5 */ - { IO_PUNCHCARD, "punchcard", "pcrd" }, /* 6 */ - { IO_PUNCHTAPE, "punchtape", "ptap" }, /* 7 */ - { IO_PRINTER, "printout", "prin" }, /* 8 */ - { IO_SERIAL, "serial", "serl" }, /* 9 */ - { IO_PARALLEL, "parallel", "parl" }, /* 10 */ - { IO_SNAPSHOT, "snapshot", "dump" }, /* 11 */ - { IO_QUICKLOAD, "quickload", "quik" }, /* 12 */ - { IO_MEMCARD, "memcard", "memc" }, /* 13 */ - { IO_CDROM, "cdrom", "cdrm" }, /* 14 */ - { IO_MAGTAPE, "magtape", "magt" }, /* 15 */ - { IO_ROM, "romimage", "rom" }, /* 16 */ - { IO_MIDIIN, "midiin", "min" }, /* 17 */ - { IO_MIDIOUT, "midiout", "mout" }, /* 18 */ - { IO_PICTURE, "picture", "pic" }, /* 19 */ - { IO_VIDEO, "vidfile", "vid" } /* 20 */ - }; +#include <algorithm> +#include <cstring> +#include <regex> +#include <sstream> //************************************************************************** @@ -89,16 +65,18 @@ image_device_format::~image_device_format() device_image_interface::device_image_interface(const machine_config &mconfig, device_t &device) : device_interface(device, "image") - , m_err() , m_file() , m_mame_file() + , m_default_region(-1) + , m_current_region(-1) , m_software_part_ptr(nullptr) - , m_supported(0) + , m_sequence_counter(0) , m_readonly(false) , m_created(false) , m_create_format(0) , m_create_args(nullptr) , m_user_loadable(true) + , m_must_be_loaded(false) , m_is_loading(false) , m_is_reset_and_loading(false) { @@ -113,6 +91,17 @@ device_image_interface::~device_image_interface() { } +//------------------------------------------------- +// add_region - register a region that may +// have a chd image +//------------------------------------------------- +void device_image_interface::add_region(std::string name, bool is_default) +{ + if (is_default) + m_default_region = m_possible_preset_regions.size(); + m_possible_preset_regions.push_back(name); +} + //------------------------------------------------- // interface_config_complete - perform any @@ -126,75 +115,150 @@ void device_image_interface::interface_config_complete() update_names(); } - //------------------------------------------------- -// find_device_type - search trough list of -// device types to extract data +// check_preset_images - lookup the CHDs from the +// region(s), if any //------------------------------------------------- -const image_device_type_info *device_image_interface::find_device_type(iodevice_t type) +void device_image_interface::check_preset_images() { - int i; - for (i = 0; i < ARRAY_LENGTH(device_image_interface::m_device_info_array); i++) + if (!m_possible_preset_regions.empty()) + { + for(const auto &r : m_possible_preset_regions) + m_preset_images.push_back(device().machine().rom_load().get_disk_handle(":" + r)); + if (m_default_region != -1 && m_preset_images[m_default_region]) + m_current_region = m_default_region; + else + { + for (m_current_region = 0; m_current_region != int(m_preset_images.size()) && !m_preset_images[m_current_region]; m_current_region++); + if (m_current_region == int(m_preset_images.size())) + fatalerror("%s: No configured region has an image\n", device().tag()); + } + set_image_tag(); + set_user_loadable(false); + } + else { - if (m_device_info_array[i].m_type == type) - return &m_device_info_array[i]; + std::string tag = device().owner()->tag(); + auto *const chd = device().machine().rom_load().get_disk_handle(tag); + if (chd) + { + m_possible_preset_regions.emplace_back(std::move(tag)); + m_preset_images.push_back(chd); + m_current_region = 0; + set_image_tag(); + set_user_loadable(false); + } } - return nullptr; } //------------------------------------------------- -// device_typename - retrieves device type name +// has_preset_images - does the device have an +// image to retrieve through current_image_* //------------------------------------------------- -const char *device_image_interface::device_typename(iodevice_t type) +bool device_image_interface::has_preset_images() const { - const image_device_type_info *info = find_device_type(type); - return (info != nullptr) ? info->m_name : "unknown"; + return !m_possible_preset_regions.empty(); } //------------------------------------------------- -// device_brieftypename - retrieves device -// brief type name +// has_preset_images - does the device have +// multiple preset images with user selection //------------------------------------------------- -const char *device_image_interface::device_brieftypename(iodevice_t type) +bool device_image_interface::has_preset_images_selection() const { - const image_device_type_info *info = find_device_type(type); - return (info != nullptr) ? info->m_shortname : "unk"; + int icount = 0; + for (const auto *f : m_preset_images) + if (f) + icount ++; + return icount > 1; } + //------------------------------------------------- -// device_typeid - retrieves device type id +// preset_images_list -- generate the list of +// available image names //------------------------------------------------- -iodevice_t device_image_interface::device_typeid(const char *name) +std::vector<std::string> device_image_interface::preset_images_list() const { - int i; - for (i = 0; i < ARRAY_LENGTH(device_image_interface::m_device_info_array); i++) - { - if (!core_stricmp(name, m_device_info_array[i].m_name) || !core_stricmp(name, m_device_info_array[i].m_shortname)) - return m_device_info_array[i].m_type; - } - return (iodevice_t)-1; + std::vector<std::string> result; + for (unsigned int i = 0; i != m_preset_images.size(); i++) + if (m_preset_images[i]) + result.push_back(m_possible_preset_regions[i]); + return result; +} + +//------------------------------------------------- +// current_preset_image_id -- current image id, +// recomputed to ignore non-present images. +// returns -1 if not in preset mode +//------------------------------------------------- + +int device_image_interface::current_preset_image_id() const +{ + if (m_current_region == -1) + return -1; + int id = 0; + for (int i = 0; i != m_current_region; i++) + if (m_preset_images[i]) + id++; + return id; +} + +//------------------------------------------------- +// current_preset_image_chd -- return the chd of +// the current active image, nullptr if non +//------------------------------------------------- + +chd_file *device_image_interface::current_preset_image_chd() const +{ + if (m_current_region == -1) + return nullptr; + return m_preset_images[m_current_region]; +} + +//------------------------------------------------- +// switch_preset_image -- change of preset image +//------------------------------------------------- + +void device_image_interface::switch_preset_image(int id) +{ + for (unsigned int i = 0; i != m_preset_images.size(); i++) + if (m_preset_images[i]) + { + if(!id) + { + call_unload(); + m_current_region = i; + call_load(); + break; + } + id--; + } + + return; } + //------------------------------------------------- // set_image_filename - specifies the filename of // an image //------------------------------------------------- -void device_image_interface::set_image_filename(const std::string &filename) +void device_image_interface::set_image_filename(std::string_view filename) { m_image_name = filename; - util::zippath_parent(m_working_directory, filename); + m_working_directory = util::zippath_parent(m_image_name); m_basename.assign(m_image_name); // find the last "path separator" auto iter = std::find_if( - m_image_name.rbegin(), - m_image_name.rend(), - [](char c) { return (c == '\\') || (c == '/') || (c == ':'); }); + m_image_name.rbegin(), + m_image_name.rend(), + [] (char c) { return (c == '\\') || (c == '/') || (c == ':'); }); if (iter != m_image_name.rend()) m_basename.assign(iter.base(), m_image_name.end()); @@ -207,222 +271,119 @@ void device_image_interface::set_image_filename(const std::string &filename) m_filetype = core_filename_extract_extension(m_basename, true); } - -/**************************************************************************** - CREATION FORMATS -****************************************************************************/ - //------------------------------------------------- -// 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 std::string &format_name) -{ - for (auto &format : m_formatlist) - if (format->name() == format_name) - return format.get(); - return nullptr; -} - - -//------------------------------------------------- -// add_format +// set_image_tag - specifies the filename of +// an image as the device tag //------------------------------------------------- -void device_image_interface::add_format(std::unique_ptr<image_device_format> &&format) +void device_image_interface::set_image_tag() { - m_formatlist.push_back(std::move(format)); + m_image_name = device().owner()->tag(); + m_working_directory = ""; + m_basename = ""; + m_basename_noext = ""; + m_filetype = ""; } //------------------------------------------------- -// add_format +// is_filetype - check if the filetype matches //------------------------------------------------- -void device_image_interface::add_format(std::string &&name, std::string &&description, std::string &&extensions, std::string &&optspec) +bool device_image_interface::is_filetype(std::string_view candidate_filetype) const { - auto format = std::make_unique<image_device_format>(std::move(name), std::move(description), std::move(extensions), std::move(optspec)); - add_format(std::move(format)); + return util::streqlower(m_filetype, candidate_filetype); } -/**************************************************************************** - ERROR HANDLING -****************************************************************************/ - //------------------------------------------------- -// image_clear_error - clear out any specified -// error +// add_media_change_notifier - subscribe for +// media change notifications //------------------------------------------------- -void device_image_interface::clear_error() +util::notifier_subscription device_image_interface::add_media_change_notifier(delegate<void (media_change_event)> &&n) { - m_err = IMAGE_ERROR_SUCCESS; - if (!m_err_message.empty()) - { - m_err_message.clear(); - } + return m_media_change_notifier.subscribe(std::move(n)); } +//*************************************************************************** +// CREATION FORMATS +//*************************************************************************** //------------------------------------------------- -// error - returns the error text for an image -// error +// device_get_named_creatable_format - +// accesses a specific image format available for +// image creation by name //------------------------------------------------- -static const char *const messages[] = +const image_device_format *device_image_interface::device_get_named_creatable_format(std::string_view format_name) const noexcept { - "", - "Internal error", - "Unsupported operation", - "Out of memory", - "File not found", - "Invalid image", - "File already open", - "Unspecified error" -}; - -const char *device_image_interface::error() -{ - return (!m_err_message.empty()) ? m_err_message.c_str() : messages[m_err]; + for (const auto &format : m_formatlist) + if (std::string_view(format->name()) == format_name) + return format.get(); + return nullptr; } - //------------------------------------------------- -// seterror - specifies an error on an image +// add_format //------------------------------------------------- -void device_image_interface::seterror(image_error_t err, const char *message) +void device_image_interface::add_format(std::unique_ptr<image_device_format> &&format) { - clear_error(); - m_err = err; - if (message != nullptr) - { - m_err_message = message; - } + m_formatlist.push_back(std::move(format)); } - //------------------------------------------------- -// message - used to display a message while -// loading +// add_format //------------------------------------------------- -void device_image_interface::message(const char *format, ...) +void device_image_interface::add_format(std::string &&name, std::string &&description, std::string &&extensions, std::string &&optspec) { - va_list args; - char buffer[256]; - - /* format the message */ - va_start(args, format); - vsnprintf(buffer, ARRAY_LENGTH(buffer), format, args); - va_end(args); - - /* display the popup for a standard amount of time */ - device().machine().ui().popup_time(5, "%s: %s", - basename(), - buffer); + auto format = std::make_unique<image_device_format>(std::move(name), std::move(description), std::move(extensions), std::move(optspec)); + add_format(std::move(format)); } -/*************************************************************************** - WORKING DIRECTORIES -***************************************************************************/ - -//------------------------------------------------- -// 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 std::string &subdir) -{ - const osd::directory::entry *entry; - bool success = false; - bool done = false; - - auto directory = osd::directory::open(m_working_directory); - if (directory) - { - while (!done && (entry = directory->read()) != nullptr) - { - if (!core_stricmp(subdir.c_str(), entry->name)) - { - done = true; - success = entry->type == osd::directory::entry::entry_type::DIR; - } - } - - directory.reset(); - } - - // did we successfully identify the directory? - if (success) - m_working_directory = util::zippath_combine(m_working_directory, subdir); - - return success; -} - +//*************************************************************************** +// ERROR HANDLING +//*************************************************************************** //------------------------------------------------- -// setup_working_directory - sets up the working -// directory according to a few defaults +// error - returns the error text for an image +// error //------------------------------------------------- -void device_image_interface::setup_working_directory() +std::error_category const &image_category() noexcept { - bool success = false; - // get user-specified directory and make sure it exists - m_working_directory = device().mconfig().options().sw_path(); - // if multipath, get first - size_t i = m_working_directory.find_first_of(";"); - if (i != std::string::npos) - m_working_directory.resize(i); - // validate directory - if (!m_working_directory.empty()) - if (osd::directory::open(m_working_directory)) - success = true; - - // if not exist, use previous method - if (!success) + class image_category_impl : public std::error_category { - // first set up the working directory to be the starting directory - osd_get_full_path(m_working_directory, "."); - // now try browsing down to "software" - if (try_change_working_directory("software")) - success = true; - } + public: + virtual char const *name() const noexcept override { return "image"; } - if (success) - { - // 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)) + virtual std::string message(int condition) const override { - gamedrv = driver_list::compatible_with(gamedrv); + using namespace std::literals; + static std::string_view const s_messages[] = { + "No error"sv, + "Internal error"sv, + "Unsupported operation"sv, + "Invalid image"sv, + "Invalid image length"sv, + "File already open"sv, + "Unrecognized software item"sv, + "Invalid software item"sv, + "Unspecified error"sv }; + if ((0 <= condition) && (std::size(s_messages) > condition)) + return std::string(s_messages[condition]); + else + return "Unknown error"s; } - } -} - - -//------------------------------------------------- -// working_directory - returns the working -// directory to use for this image; this is -// valid even if not mounted -//------------------------------------------------- - -const std::string &device_image_interface::working_directory() -{ - // check to see if we've never initialized the working directory - if (m_working_directory.empty()) - setup_working_directory(); - - return m_working_directory; + }; + static image_category_impl const s_image_category_instance; + return s_image_category_instance; } @@ -431,7 +392,7 @@ const std::string &device_image_interface::working_directory() // software_info structure from the softlist //------------------------------------------------- -const software_info *device_image_interface::software_entry() const +const software_info *device_image_interface::software_entry() const noexcept { return !m_software_part_ptr ? nullptr : &m_software_part_ptr->info(); } @@ -441,14 +402,13 @@ const software_info *device_image_interface::software_entry() const // get_software_region //------------------------------------------------- -u8 *device_image_interface::get_software_region(const char *tag) +u8 *device_image_interface::get_software_region(std::string_view tag) { if (!loaded_through_softlist()) return nullptr; - std::string full_tag = util::string_format("%s:%s", device().tag(), tag); - memory_region *region = device().machine().root_device().memregion(full_tag.c_str()); - return region != nullptr ? region->base() : nullptr; + memory_region *const region = device().memregion(tag); + return region ? region->base() : nullptr; } @@ -456,11 +416,13 @@ u8 *device_image_interface::get_software_region(const char *tag) // image_get_software_region_length //------------------------------------------------- -u32 device_image_interface::get_software_region_length(const char *tag) +u32 device_image_interface::get_software_region_length(std::string_view tag) { - std::string full_tag = util::string_format("%s:%s", device().tag(), tag); - memory_region *region = device().machine().root_device().memregion(full_tag.c_str()); - return region != nullptr ? region->bytes() : 0; + if (!loaded_through_softlist()) + return 0; + + memory_region *const region = device().memregion(tag); + return region ? region->bytes() : 0; } @@ -468,7 +430,7 @@ u32 device_image_interface::get_software_region_length(const char *tag) // image_get_feature //------------------------------------------------- -const char *device_image_interface::get_feature(const char *feature_name) const +const char *device_image_interface::get_feature(std::string_view feature_name) const { return !m_software_part_ptr ? nullptr : m_software_part_ptr->feature(feature_name); } @@ -478,18 +440,18 @@ const char *device_image_interface::get_feature(const char *feature_name) const // load_software_region - //------------------------------------------------- -bool device_image_interface::load_software_region(const char *tag, optional_shared_ptr<u8> &ptr) +std::error_condition device_image_interface::load_software_region(std::string_view tag, std::unique_ptr<u8[]> &ptr) { size_t size = get_software_region_length(tag); if (size) { - ptr.allocate(size); - - memcpy(ptr, get_software_region(tag), size); + ptr = std::make_unique<u8[]>(size); + memcpy(ptr.get(), get_software_region(tag), size); + return std::error_condition(); } - - return size > 0; + else + return image_error::UNSUPPORTED; } @@ -500,45 +462,30 @@ bool device_image_interface::load_software_region(const char *tag, optional_shar // to be loaded // **************************************************************************** -bool device_image_interface::run_hash(util::core_file &file, u32 skip_bytes, util::hash_collection &hashes, const char *types) +std::error_condition device_image_interface::run_hash(util::random_read &file, u32 skip_bytes, util::hash_collection &hashes, const char *types) { // reset the hash; we want to override existing data hashes.reset(); // figure out the size, and "cap" the skip bytes - u64 size = file.size(); - skip_bytes = (u32) std::min((u64) skip_bytes, size); - - // seek to the beginning - file.seek(skip_bytes, SEEK_SET); - u64 position = skip_bytes; - - // keep on reading hashes - hashes.begin(types); - while (position < size) - { - uint8_t buffer[8192]; - - // read bytes - const u32 count = (u32) std::min(size - position, (u64) sizeof(buffer)); - const u32 actual_count = file.read(buffer, count); - if (actual_count == 0) - return false; - position += actual_count; - - // and compute the hashes - hashes.buffer(buffer, actual_count); - } - hashes.end(); - - // cleanup - file.seek(0, SEEK_SET); - return true; + u64 size; + std::error_condition filerr = file.length(size); + if (filerr) + return filerr; + skip_bytes = u32(std::min<u64>(skip_bytes, size)); + + // and compute the hashes + size_t actual_count; + filerr = hashes.compute(file, skip_bytes, size - skip_bytes, actual_count, types); + if (filerr) + return filerr; + + return std::error_condition(); } -bool device_image_interface::image_checkhash() +std::error_condition device_image_interface::image_checkhash() { // only calculate CRC if it hasn't been calculated, and the open_mode is read only u32 crcval; @@ -546,26 +493,25 @@ bool device_image_interface::image_checkhash() { // 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 true; + if (image_is_chd_type()) + return std::error_condition(); // Skip calculating the hash when we have an image mounted through a software list if (loaded_through_softlist()) - return true; + return std::error_condition(); // run the hash - if (!run_hash(*m_file, unhashed_header_length(), m_hash, util::hash_collection::HASH_TYPES_ALL)) - return false; + return run_hash(*m_file, unhashed_header_length(), m_hash, util::hash_collection::HASH_TYPES_ALL); } - return true; + return std::error_condition(); } -util::hash_collection device_image_interface::calculate_hash_on_file(util::core_file &file) const +util::hash_collection device_image_interface::calculate_hash_on_file(util::random_read &file) const { // calculate the hash util::hash_collection hash; - if (!run_hash(file, unhashed_header_length(), hash, util::hash_collection::HASH_TYPES_ALL)) + if (run_hash(file, unhashed_header_length(), hash, util::hash_collection::HASH_TYPES_ALL)) hash.reset(); return hash; } @@ -576,39 +522,13 @@ u32 device_image_interface::crc() u32 crc = 0; image_checkhash(); - m_hash.crc(crc); + if (!m_hash.crc(crc)) + crc = 0; return crc; } -//------------------------------------------------- -// support_command_line_image_creation - do we -// want to support image creation from the front -// end command line? -//------------------------------------------------- - -bool device_image_interface::support_command_line_image_creation() const -{ - bool result; - switch (image_type()) - { - case IO_PRINTER: - case IO_SERIAL: - case IO_PARALLEL: - // going by the assumption that these device image types should support this - // behavior; ideally we'd get rid of IO_* and just push this to the specific - // devices - result = true; - break; - default: - result = false; - break; - } - return result; -} - - // **************************************************************************** // Battery functions // @@ -629,38 +549,36 @@ void device_image_interface::battery_load(void *buffer, int length, int fill) if (!buffer || (length <= 0)) throw emu_fatalerror("device_image_interface::battery_load: Must specify sensical buffer/length"); - osd_file::error filerr; - int bytes_read = 0; - std::string fname = std::string(device().machine().system().name).append(PATH_SEPARATOR).append(m_basename_noext.c_str()).append(".nv"); + std::string const fname = std::string(device().machine().system().name).append(PATH_SEPARATOR).append(m_basename_noext).append(".nv"); /* 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); - if (filerr == osd_file::error::NONE) + std::error_condition const filerr = file.open(fname); + int bytes_read = 0; + if (!filerr) bytes_read = file.read(buffer, length); // fill remaining bytes (if necessary) memset(((char *)buffer) + bytes_read, fill, length - bytes_read); } -void device_image_interface::battery_load(void *buffer, int length, void *def_buffer) +void device_image_interface::battery_load(void *buffer, int length, const void *def_buffer) { if (!buffer || (length <= 0)) throw emu_fatalerror("device_image_interface::battery_load: Must specify sensical buffer/length"); - osd_file::error filerr; - int bytes_read = 0; - std::string fname = std::string(device().machine().system().name).append(PATH_SEPARATOR).append(m_basename_noext.c_str()).append(".nv"); + std::string const fname = std::string(device().machine().system().name).append(PATH_SEPARATOR).append(m_basename_noext).append(".nv"); // 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); - if (filerr == osd_file::error::NONE) + std::error_condition const filerr = file.open(fname); + int bytes_read = 0; + if (!filerr) bytes_read = file.read(buffer, length); - // if no file was present, copy the default battery - if (bytes_read == 0 && def_buffer) - memcpy((char *)buffer, (char *)def_buffer, length); + // if no file was present, copy the default contents + if (!bytes_read && def_buffer) + std::memcpy(buffer, def_buffer, length); } @@ -679,111 +597,45 @@ void device_image_interface::battery_save(const void *buffer, int length) if (!device().machine().options().nvram_save()) return; - std::string fname = std::string(device().machine().system().name).append(PATH_SEPARATOR).append(m_basename_noext.c_str()).append(".nv"); + std::string fname = std::string(device().machine().system().name).append(PATH_SEPARATOR).append(m_basename_noext).append(".nv"); // 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); - if (filerr == osd_file::error::NONE) + std::error_condition const filerr = file.open(fname); + if (!filerr) file.write(buffer, length); } -//------------------------------------------------- -// 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 */ - std::string extensions(file_extensions()); - char *ext = strtok((char*)extensions.c_str(),","); - while (ext != nullptr) - { - if (!core_stricmp(ext, file_extension)) - { - result = true; - break; - } - ext = strtok (nullptr, ","); - } - return result; -} - - // *************************************************************************** // IMAGE LOADING // *************************************************************************** //------------------------------------------------- -// is_loaded - quick check to determine whether an -// image is loaded -//------------------------------------------------- - -bool device_image_interface::is_loaded() -{ - return (m_file != nullptr); -} - -//------------------------------------------------- -// image_error_from_file_error - converts an image -// error to a file error -//------------------------------------------------- - -image_error_t device_image_interface::image_error_from_file_error(osd_file::error filerr) -{ - switch (filerr) - { - case osd_file::error::NONE: - return IMAGE_ERROR_SUCCESS; - - case osd_file::error::NOT_FOUND: - case osd_file::error::ACCESS_DENIED: - // file not found (or otherwise cannot open) - return IMAGE_ERROR_FILENOTFOUND; - - case osd_file::error::OUT_OF_MEMORY: - // out of memory - return IMAGE_ERROR_OUTOFMEMORY; - - case osd_file::error::ALREADY_OPEN: - // this shouldn't happen - return IMAGE_ERROR_ALREADYOPEN; - - case osd_file::error::FAILURE: - case osd_file::error::TOO_MANY_FILES: - case osd_file::error::INVALID_DATA: - default: - // other errors - return IMAGE_ERROR_INTERNAL; - } -} - - -//------------------------------------------------- // load_image_by_path - loads an image with a // specific path //------------------------------------------------- -image_error_t device_image_interface::load_image_by_path(u32 open_flags, const std::string &path) +std::error_condition device_image_interface::load_image_by_path(u32 open_flags, std::string_view path) { std::string revised_path; // attempt to read the file - auto const filerr = util::zippath_fopen(path, open_flags, m_file, revised_path); - if (filerr != osd_file::error::NONE) - return image_error_from_file_error(filerr); + auto filerr = util::zippath_fopen(path, open_flags, m_file, revised_path); + if (filerr) + { + osd_printf_verbose("%s: error opening image file %s with flags=%08X (%s:%d %s)\n", device().tag(), path, open_flags, filerr.category().name(), filerr.value(), filerr.message()); + return filerr; + } + else + { + osd_printf_verbose("%s: opened image file %s with flags=%08X\n", device().tag(), path, open_flags); + } m_readonly = (open_flags & OPEN_FLAG_WRITE) ? 0 : 1; m_created = (open_flags & OPEN_FLAG_CREATE) ? 1 : 0; set_image_filename(revised_path); - return IMAGE_ERROR_SUCCESS; + return std::error_condition(); } @@ -791,7 +643,7 @@ image_error_t device_image_interface::load_image_by_path(u32 open_flags, const s // reopen_for_write //------------------------------------------------- -int device_image_interface::reopen_for_write(const std::string &path) +std::error_condition device_image_interface::reopen_for_write(std::string_view path) { m_file.reset(); @@ -799,15 +651,15 @@ int device_image_interface::reopen_for_write(const std::string &path) // 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); - if (filerr != osd_file::error::NONE) - return image_error_from_file_error(filerr); + if (filerr) + return filerr; // success! m_readonly = 0; m_created = 1; set_image_filename(revised_path); - return IMAGE_ERROR_SUCCESS; + return std::error_condition(); } @@ -820,71 +672,64 @@ std::vector<u32> device_image_interface::determine_open_plan(bool is_create) { std::vector<u32> open_plan; - // emit flags into a vector - if (!is_create && is_readable() && is_writeable()) - open_plan.push_back(OPEN_FLAG_READ | OPEN_FLAG_WRITE); - if (!is_create && !is_readable() && is_writeable()) - open_plan.push_back(OPEN_FLAG_WRITE); - if (!is_create && is_readable()) - open_plan.push_back(OPEN_FLAG_READ); - if (is_create && is_writeable() && is_creatable()) - open_plan.push_back(OPEN_FLAG_READ | OPEN_FLAG_WRITE | OPEN_FLAG_CREATE); + if (!is_create) + { + if (is_writeable()) + open_plan.push_back(is_readable() ? (OPEN_FLAG_READ | OPEN_FLAG_WRITE) : OPEN_FLAG_WRITE); + if (is_readable()) + open_plan.push_back(OPEN_FLAG_READ); + } + else if (is_writeable() && is_creatable()) + { + if (is_readable()) + open_plan.push_back(OPEN_FLAG_READ | OPEN_FLAG_WRITE | OPEN_FLAG_CREATE); + else + open_plan.push_back(OPEN_FLAG_WRITE | OPEN_FLAG_CREATE); + } return open_plan; } //------------------------------------------------- -// 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 util::hash_collection &hashes, const util::hash_collection &acthashes) -{ - osd_printf_error(" EXPECTED: %s\n", hashes.macro_string().c_str()); - osd_printf_error(" FOUND: %s\n", acthashes.macro_string().c_str()); -} - - -//------------------------------------------------- // 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, u32 explength, const util::hash_collection &hashes) +static int verify_length_and_hash(emu_file *file, std::string_view name, u32 explength, const util::hash_collection &hashes) { - int retVal = 0; - if (file==nullptr) return 0; + int retval = 0; + if (!file) + return 0; // verify length u32 actlength = file->size(); if (explength != actlength) { osd_printf_error("%s WRONG LENGTH (expected: %d found: %d)\n", name, explength, actlength); - retVal++; + retval++; } - // If there is no good dump known, write it - util::hash_collection &acthashes = file->hashes(hashes.hash_types().c_str()); + util::hash_collection &acthashes = file->hashes(hashes.hash_types()); if (hashes.flag(util::hash_collection::FLAG_NO_DUMP)) { + // If there is no good dump known, write it osd_printf_error("%s NO GOOD DUMP KNOWN\n", name); } - // verify checksums else if (hashes != acthashes) { // otherwise, it's just bad osd_printf_error("%s WRONG CHECKSUMS:\n", name); - dump_wrong_and_correct_checksums(hashes, acthashes); - retVal++; + osd_printf_error(" EXPECTED: %s\n", hashes.macro_string()); + osd_printf_error(" FOUND: %s\n", acthashes.macro_string()); + retval++; } - // If it matches, but it is actually a bad dump, write it else if (hashes.flag(util::hash_collection::FLAG_BAD_DUMP)) { + // If it matches, but it is actually a bad dump, write it osd_printf_error("%s NEEDS REDUMP\n",name); } - return retVal; + return retval; } @@ -892,104 +737,85 @@ static int verify_length_and_hash(emu_file *file, const char *name, u32 explengt // load_software - software image loading //------------------------------------------------- -bool device_image_interface::load_software(software_list_device &swlist, const char *swname, const rom_entry *start) +std::error_condition device_image_interface::load_software(software_list_device &swlist, std::string_view swname, const rom_entry *start) { - std::string locationtag, breakstr("%"); - const rom_entry *region; - bool retVal = false; + std::error_condition retval; int warningcount = 0; - for (region = start; region != nullptr; region = rom_next_region(region)) + for (const rom_entry *region = start; region; region = rom_next_region(region)) { // loop until we hit the end of this region - const rom_entry *romp = region + 1; - while (!ROMENTRY_ISREGIONEND(romp)) + for (const rom_entry *romp = region + 1; !ROMENTRY_ISREGIONEND(romp); romp++) { // handle files if (ROMENTRY_ISFILE(romp)) { - osd_file::error filerr = osd_file::error::NOT_FOUND; + const software_info *const swinfo = swlist.find(std::string(swname)); + if (!swinfo) + return image_error::NOSOFTWARE; - u32 crc = 0; - bool has_crc = util::hash_collection(ROM_GETHASHDATA(romp)).crc(crc); + if (swinfo->supported() == software_support::PARTIALLY_SUPPORTED) + osd_printf_error("WARNING: support for software %s (in list %s) is only partial\n", swname, swlist.list_name()); + else if (swinfo->supported() == software_support::UNSUPPORTED) + osd_printf_error("WARNING: support for software %s (in list %s) is only preliminary\n", swname, swlist.list_name()); - const software_info *swinfo = swlist.find(swname); - if (swinfo == nullptr) - return false; - - u32 supported = swinfo->supported(); - if (supported == SOFTWARE_SUPPORTED_PARTIAL) - osd_printf_error("WARNING: support for software %s (in list %s) is only partial\n", swname, swlist.list_name().c_str()); - if (supported == SOFTWARE_SUPPORTED_NO) - osd_printf_error("WARNING: support for software %s (in list %s) is only preliminary\n", swname, swlist.list_name().c_str()); - - // attempt reading up the chain through the parents and create a locationtag std::string in the format - // " swlist % clonename % parentname " - // below, we have the code to split the elements and to create paths to load from + u32 crc = 0; + const bool has_crc = util::hash_collection(romp->hashdata()).crc(crc); + std::vector<const software_info *> parents; + std::vector<std::string> searchpath = rom_load_manager::get_software_searchpath(swlist, *swinfo); - while (swinfo != nullptr) + // for historical reasons, add the search path for the software list device's owner + const device_t *const listowner = swlist.owner(); + if (listowner) { - locationtag.append(swinfo->shortname()).append(breakstr); - swinfo = !swinfo->parentname().empty() ? swlist.find(swinfo->parentname().c_str()) : nullptr; + std::vector<std::string> devsearch = listowner->searchpath(); + for (std::string &path : devsearch) + searchpath.emplace_back(std::move(path)); } - // strip the final '%' - locationtag.erase(locationtag.length() - 1, 1); - - // check if locationtag actually contains two locations separated by '%' - // (i.e. check if we are dealing with a clone in softwarelist) - std::string tag2, tag3, tag4(locationtag), tag5; - int separator = tag4.find_first_of('%'); - if (separator != -1) + // try to load the file + m_mame_file.reset(new emu_file(device().machine().options().media_path(), searchpath, OPEN_FLAG_READ)); + m_mame_file->set_restrict_to_mediapath(1); + std::error_condition filerr; + if (has_crc) + filerr = m_mame_file->open(romp->name(), crc); + else + filerr = m_mame_file->open(romp->name()); + if (filerr) { - // we are loading a clone through softlists, split the setname from the parentname - tag5.assign(tag4.substr(separator + 1, tag4.length() - separator + 1)); - tag4.erase(separator, tag4.length() - separator); + m_mame_file.reset(); + std::ostringstream msg; + util::stream_format(msg, + "%s: error opening image file %s: %s (%s:%d)", + device().tag(), romp->name(), + filerr.message(), + filerr.category().name(), + filerr.value()); + if (!searchpath.empty()) + { + msg << " (tried in"; + for (auto const &path : searchpath) + msg << ' ' << path; + msg << ')'; + } + osd_printf_error("%s\n", std::move(msg).str()); } - // prepare locations where we have to load from: list/parentname & list/clonename - std::string tag1(swlist.list_name()); - tag1.append(PATH_SEPARATOR); - tag2.assign(tag1.append(tag4)); - tag1.assign(swlist.list_name()); - tag1.append(PATH_SEPARATOR); - tag3.assign(tag1.append(tag5)); - - if (tag5.find_first_of('%') != -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 == nullptr) && (tag2.c_str() != nullptr)) - m_mame_file = common_process_file(device().machine().options(), tag2.c_str(), has_crc, crc, romp, filerr); - // try to load from list/parentname - if ((m_mame_file == nullptr) && (tag3.c_str() != nullptr)) - m_mame_file = common_process_file(device().machine().options(), tag3.c_str(), has_crc, crc, romp, filerr); - // try to load from setname - if ((m_mame_file == nullptr) && (tag4.c_str() != nullptr)) - m_mame_file = common_process_file(device().machine().options(), tag4.c_str(), has_crc, crc, romp, filerr); - // try to load from parentname - if ((m_mame_file == nullptr) && (tag5.c_str() != nullptr)) - m_mame_file = common_process_file(device().machine().options(), tag5.c_str(), has_crc, crc, romp, filerr); - - warningcount += verify_length_and_hash(m_mame_file.get(),ROM_GETNAME(romp),ROM_GETLENGTH(romp), util::hash_collection(ROM_GETHASHDATA(romp))); - - if (filerr == osd_file::error::NONE) + warningcount += verify_length_and_hash(m_mame_file.get(), romp->name(), romp->get_length(), util::hash_collection(romp->hashdata())); + + if (!filerr) filerr = util::core_file::open_proxy(*m_mame_file, m_file); - if (filerr == osd_file::error::NONE) - retVal = true; + if (filerr) + retval = filerr; break; // load first item for start } - romp++; /* something else; skip */ } } + if (warningcount > 0) - { osd_printf_error("WARNING: the software item might not run correctly.\n"); - } - return retVal; + + return retval; } @@ -997,16 +823,16 @@ bool device_image_interface::load_software(software_list_device &swlist, const c // load_internal - core image loading //------------------------------------------------- -image_init_result device_image_interface::load_internal(const std::string &path, bool is_create, int create_format, util::option_resolution *create_args) +std::pair<std::error_condition, std::string> device_image_interface::load_internal(std::string_view path, bool is_create, int create_format, util::option_resolution *create_args) { + std::pair<std::error_condition, std::string> err; + // first unload the image unload(); - // clear any possible error messages - clear_error(); - // we are now loading m_is_loading = true; + m_sequence_counter++; // record the filename set_image_filename(path); @@ -1014,48 +840,47 @@ image_init_result device_image_interface::load_internal(const std::string &path, if (core_opens_image_file()) { // determine open plan - std::vector<u32> open_plan = determine_open_plan(is_create); + std::vector<u32> const open_plan = determine_open_plan(is_create); // attempt to open the file in various ways for (auto iter = open_plan.cbegin(); !m_file && iter != open_plan.cend(); iter++) { // open the file - m_err = load_image_by_path(*iter, path); - if (m_err && (m_err != IMAGE_ERROR_FILENOTFOUND)) - goto done; + err.first = load_image_by_path(*iter, path); + if (err.first && (err.first != std::errc::no_such_file_or_directory) && (err.first != std::errc::permission_denied)) + break; } // did we fail to find the file? - if (!is_loaded()) - { - m_err = IMAGE_ERROR_FILENOTFOUND; - goto done; - } + if (!err.first && !m_file) + err.first = std::errc::no_such_file_or_directory; } - // call device load or create - m_create_format = create_format; - m_create_args = create_args; + if (!err.first) + { + // call device load or create + m_create_format = create_format; + m_create_args = create_args; - if (init_phase()==false) { - m_err = (finish_load() == image_init_result::PASS) ? IMAGE_ERROR_SUCCESS : IMAGE_ERROR_INTERNAL; - if (m_err) - goto done; + if (!init_phase()) + err = finish_load(); } - // success! -done: - if (m_err!=0) { - if (!init_phase()) - { - if (device().machine().phase() == machine_phase::RUNNING) - device().popmessage("Error: Unable to %s image '%s': %s", is_create ? "create" : "load", path, error()); - else - osd_printf_error("Error: Unable to %s image '%s': %s\n", is_create ? "create" : "load", path.c_str(), error()); - } + if (err.first) + { + osd_printf_error( + !err.second.empty() + ? (is_create ? "Unable to create image '%1$s': %2$s (%3$s:%4$d %5$s)\n" : "Unable to load image '%1$s': %2$s (%3$s:%4$d %5$s)\n") + : (is_create ? "Unable to create image '%1$s': %5$s (%3$s:%4$d)\n" : "Unable to load image '%1$s': %5$s (%3$s:%4$d)\n"), + path, + err.second, + err.first.category().name(), + err.first.value(), + err.first.message()); clear(); } - return m_err ? image_init_result::FAIL : image_init_result::PASS; + + return err; } @@ -1063,13 +888,13 @@ done: // load - load an image into MAME //------------------------------------------------- -image_init_result device_image_interface::load(const std::string &path) +std::pair<std::error_condition, std::string> device_image_interface::load(std::string_view path) { // is this a reset on load item? if (is_reset_on_load() && !init_phase()) { reset_and_load(path); - return image_init_result::PASS; + return std::make_pair(std::error_condition(), std::string()); } return load_internal(path, false, 0, nullptr); @@ -1080,26 +905,26 @@ image_init_result device_image_interface::load(const std::string &path) // load_software - loads a softlist item by name //------------------------------------------------- -image_init_result device_image_interface::load_software(const std::string &software_identifier) +std::pair<std::error_condition, std::string> device_image_interface::load_software(std::string_view software_identifier) { // Is this a software part that forces a reset and we're at runtime? If so, get this loaded through reset_and_load if (is_reset_on_load() && !init_phase()) { reset_and_load(software_identifier); - return image_init_result::PASS; + return std::make_pair(std::error_condition(), std::string()); } // Prepare to load unload(); - clear_error(); m_is_loading = true; // Check if there's a software list defined for this device and use that if we're not creating an image - bool softload = load_software_part(software_identifier); - if (!softload) + std::pair<std::error_condition, std::string> err; + err.first = load_software_part(software_identifier); + if (err.first) { m_is_loading = false; - return image_init_result::FAIL; + return err; } // set up softlist stuff @@ -1109,9 +934,10 @@ image_init_result device_image_interface::load_software(const std::string &softw m_image_name = m_full_software_name; m_basename = m_full_software_name; m_basename_noext = m_full_software_name; - m_filetype = use_software_list_file_extension_for_filetype() && m_mame_file != nullptr - ? core_filename_extract_extension(m_mame_file->filename(), true) - : ""; + if (use_software_list_file_extension_for_filetype() && m_mame_file) + m_filetype = core_filename_extract_extension(m_mame_file->filename(), true); + else + m_filetype.clear(); // Copy some image information when we have been loaded through a software list software_info &swinfo = m_software_part_ptr->info(); @@ -1120,22 +946,32 @@ image_init_result device_image_interface::load_software(const std::string &softw if (swinfo.longname().empty() || swinfo.publisher().empty() || swinfo.year().empty()) fatalerror("Each entry in an XML list must have all of the following fields: description, publisher, year!\n"); - // store - m_longname = swinfo.longname(); - m_manufacturer = swinfo.publisher(); - m_year = swinfo.year(); - // set file type - std::string filename = (m_mame_file != nullptr) && (m_mame_file->filename() != nullptr) + std::string filename = (m_mame_file && m_mame_file->filename()) ? m_mame_file->filename() : ""; m_filetype = core_filename_extract_extension(filename, true); // call finish_load if necessary - if (init_phase() == false && (finish_load() != image_init_result::PASS)) - return image_init_result::FAIL; + if (!init_phase()) + { + err = finish_load(); + if (err.first) + { + osd_printf_error( + !err.second.empty() + ? "Unable to load software item '%1$s': %2$s (%3$s:%4$d %5$s)\n" + : "Unable to load software item '%1$s': %5$s (%3$s:%4$d)\n", + software_identifier, + err.second, + err.first.category().name(), + err.first.value(), + err.first.message()); + clear(); + } + } - return image_init_result::PASS; + return err; } @@ -1144,53 +980,38 @@ image_init_result device_image_interface::load_software(const std::string &softw // from core //------------------------------------------------- -image_init_result device_image_interface::finish_load() +std::pair<std::error_condition, std::string> device_image_interface::finish_load() { - image_init_result err = image_init_result::PASS; + std::pair<std::error_condition, std::string> err; if (m_is_loading) { - if (!image_checkhash()) - { - m_err = IMAGE_ERROR_INVALIDIMAGE; - err = image_init_result::FAIL; - } + err.first = image_checkhash(); - if (err == image_init_result::PASS) + if (!err.first) { if (m_created) - { err = call_create(m_create_format, m_create_args); - if (err != image_init_result::PASS) - { - if (!m_err) - m_err = IMAGE_ERROR_UNSPECIFIED; - } - } else - { - // using device load - err = call_load(); - if (err != image_init_result::PASS) - { - if (!m_err) - m_err = IMAGE_ERROR_UNSPECIFIED; - } - } + err = call_load(); // using device load } } + m_is_loading = false; m_create_format = 0; m_create_args = nullptr; + if (!err.first) + m_media_change_notifier(media_change_event::LOADED); + return err; } //------------------------------------------------- -// create - create a image +// create - create an image //------------------------------------------------- -image_init_result device_image_interface::create(const std::string &path) +std::pair<std::error_condition, std::string> device_image_interface::create(std::string_view path) { return create(path, nullptr, nullptr); } @@ -1200,13 +1021,14 @@ image_init_result device_image_interface::create(const std::string &path) // create - create a image //------------------------------------------------- -image_init_result device_image_interface::create(const std::string &path, const image_device_format *create_format, util::option_resolution *create_args) +std::pair<std::error_condition, std::string> device_image_interface::create(std::string_view path, const image_device_format *create_format, util::option_resolution *create_args) { int format_index = 0; int cnt = 0; for (auto &format : m_formatlist) { - if (create_format == format.get()) { + if (create_format == format.get()) + { format_index = cnt; break; } @@ -1222,7 +1044,7 @@ image_init_result device_image_interface::create(const std::string &path, const // the emulation and record this image to be loaded //------------------------------------------------- -void device_image_interface::reset_and_load(const std::string &path) +void device_image_interface::reset_and_load(std::string_view path) { // first make sure the reset is scheduled device().machine().schedule_hard_reset(); @@ -1240,7 +1062,7 @@ void device_image_interface::reset_and_load(const std::string &path) // to an image //------------------------------------------------- -void device_image_interface::clear() +void device_image_interface::clear() noexcept { m_mame_file.reset(); m_file.reset(); @@ -1251,9 +1073,6 @@ void device_image_interface::clear() m_create_format = 0; m_create_args = nullptr; - m_longname.clear(); - m_manufacturer.clear(); - m_year.clear(); m_basename.clear(); m_basename_noext.clear(); m_filetype.clear(); @@ -1261,6 +1080,10 @@ void device_image_interface::clear() m_full_software_name.clear(); m_software_part_ptr = nullptr; m_software_list_name.clear(); + + m_hash.reset(); + + m_sequence_counter++; } @@ -1272,10 +1095,15 @@ void device_image_interface::unload() { if (is_loaded() || loaded_through_softlist()) { + m_sequence_counter++; call_unload(); + clear(); + m_media_change_notifier(media_change_event::UNLOADED); + } + else + { + clear(); // just to make sure everything is reset } - clear(); - clear_error(); } @@ -1297,33 +1125,33 @@ const util::option_guide &device_image_interface::create_option_guide() const void device_image_interface::update_names() { - const char *inst_name = custom_instance_name(); - const char *brief_name = custom_brief_instance_name(); - if (inst_name == nullptr) - inst_name = device_typename(image_type()); - if (brief_name == nullptr) - brief_name = device_brieftypename(image_type()); + const char *inst_name = image_type_name(); + const char *brief_name = image_brief_type_name(); + assert(inst_name != nullptr); + assert(brief_name != nullptr); // count instances of the general image type, or device type if custom int count = 0; int index = -1; - for (const device_image_interface &image : image_interface_iterator(device().mconfig().root_device())) + for (const device_image_interface &image : image_interface_enumerator(device().mconfig().root_device())) { if (this == &image) index = count; - const char *other_name = image.custom_instance_name(); - if (!other_name) - other_name = device_typename(image.image_type()); + const char *other_name = image.image_type_name(); + const char *other_brief_name = image.image_brief_type_name(); + assert(other_name != nullptr); + assert(other_brief_name != nullptr); - if (other_name == inst_name || !strcmp(other_name, inst_name)) + if (other_name == inst_name || !strcmp(other_name, inst_name) || + other_brief_name == brief_name || !strcmp(other_brief_name, brief_name)) count++; } - m_canonical_instance_name = string_format("%s%d", inst_name, index + 1); + m_canonical_instance_name = util::string_format("%s%d", inst_name, index + 1); if (count > 1) { m_instance_name = m_canonical_instance_name; - m_brief_instance_name = string_format("%s%d", brief_name, index + 1); + m_brief_instance_name = util::string_format("%s%d", brief_name, index + 1); } else { @@ -1336,7 +1164,7 @@ void device_image_interface::update_names() // find_software_item //------------------------------------------------- -const software_part *device_image_interface::find_software_item(const std::string &identifier, bool restrict_to_interface, software_list_device **dev) const +const software_part *device_image_interface::find_software_item(std::string_view identifier, bool restrict_to_interface, software_list_device **dev) const { // split full software name into software list name and short software name std::string list_name, software_name, part_name; @@ -1349,7 +1177,7 @@ const software_part *device_image_interface::find_software_item(const std::strin : nullptr; // find the software list if explicitly specified - for (software_list_device &swlistdev : software_list_device_iterator(device().mconfig().root_device())) + for (software_list_device &swlistdev : software_list_device_enumerator(device().mconfig().root_device())) { if (list_name.empty() || (list_name == swlistdev.list_name())) { @@ -1416,7 +1244,7 @@ const software_list_loader &device_image_interface::get_software_list_loader() c // sw_info and sw_part are also set. //------------------------------------------------- -bool device_image_interface::load_software_part(const std::string &identifier) +std::error_condition device_image_interface::load_software_part(std::string_view identifier) { // if no match has been found, we suggest similar shortnames software_list_device *swlist; @@ -1424,14 +1252,14 @@ bool device_image_interface::load_software_part(const std::string &identifier) if (m_software_part_ptr == nullptr) { software_list_device::display_matches(device().machine().config(), image_interface(), identifier); - return false; + return image_error::NOSOFTWARE; } // Load the software part - const char *swname = m_software_part_ptr->info().shortname().c_str(); + const std::string &swname = m_software_part_ptr->info().shortname(); const rom_entry *start_entry = m_software_part_ptr->romdata().data(); const software_list_loader &loader = get_software_list_loader(); - bool result = loader.load_software(*this, *swlist, swname, start_entry); + std::error_condition result = loader.load_software(*this, *swlist, swname, start_entry); // check compatibility switch (swlist->is_compatible(*m_software_part_ptr)) @@ -1441,10 +1269,12 @@ bool device_image_interface::load_software_part(const std::string &identifier) case SOFTWARE_IS_INCOMPATIBLE: swlist->popmessage("WARNING! the set %s might not work on this system due to incompatible filter(s) '%s'\n", m_software_part_ptr->info().shortname(), swlist->filter()); + osd_printf_warning("WARNING: the set %s might not work on this system due to incompatible filter(s) '%s'\n", m_software_part_ptr->info().shortname(), swlist->filter()); break; case SOFTWARE_NOT_COMPATIBLE: swlist->popmessage("WARNING! the set %s might not work on this system due to missing filter(s) '%s'\n", m_software_part_ptr->info().shortname(), swlist->filter()); + osd_printf_warning("WARNING! the set %s might not work on this system due to missing filter(s) '%s'\n", m_software_part_ptr->info().shortname(), swlist->filter()); break; } @@ -1469,7 +1299,7 @@ bool device_image_interface::load_software_part(const std::string &identifier) // software_get_default_slot //------------------------------------------------- -std::string device_image_interface::software_get_default_slot(const char *default_card_slot) const +std::string device_image_interface::software_get_default_slot(std::string_view default_card_slot) const { std::string result; @@ -1501,41 +1331,3 @@ bool device_image_interface::init_phase() const return !device().has_running_machine() || device().machine().phase() == machine_phase::INIT; } - - -//---------------------------------------------------------------------------- - -static int image_fseek_thunk(void *file, s64 offset, int whence) -{ - device_image_interface *image = (device_image_interface *) file; - return image->fseek(offset, whence); -} - -static size_t image_fread_thunk(void *file, void *buffer, size_t length) -{ - device_image_interface *image = (device_image_interface *) file; - return image->fread(buffer, length); -} - -static size_t image_fwrite_thunk(void *file, const void *buffer, size_t length) -{ - device_image_interface *image = (device_image_interface *) file; - return image->fwrite(buffer, length); -} - -static u64 image_fsize_thunk(void *file) -{ - device_image_interface *image = (device_image_interface *) file; - return image->length(); -} - -//---------------------------------------------------------------------------- - -struct io_procs image_ioprocs = -{ - nullptr, - image_fseek_thunk, - image_fread_thunk, - image_fwrite_thunk, - image_fsize_thunk -}; |