image_manager modernized and move some things around (nw)

This commit is contained in:
Miodrag Milanovic 2016-01-11 14:59:24 +01:00
parent e0358a4ce4
commit f0dc809ab8
13 changed files with 294 additions and 298 deletions

View File

@ -16,7 +16,6 @@
#include "sc499.h"
#include "formats/ioprocs.h"
#include "image.h"
#define VERBOSE 0

View File

@ -134,6 +134,52 @@
#define GKRACKER_ROM_TAG "gkracker_rom"
#define GKRACKER_NVRAM_TAG "gkracker_nvram"
/*-------------------------------------------------
image_battery_load_by_name - retrieves the battery
backed RAM for an image. A filename may be supplied
to the function.
The function comes in two flavors, depending on
what should happen when no battery is available:
we could fill the memory with a given value, or
pass a default battery (for a pre-initialized
battery from factory)
-------------------------------------------------*/
static void image_battery_load_by_name(emu_options &options, const char *filename, void *buffer, int length, int fill)
{
file_error filerr;
int bytes_read = 0;
assert_always(buffer && (length > 0), "Must specify sensical buffer/length");
/* try to open the battery file and read it in, if possible */
emu_file file(options.nvram_directory(), OPEN_FLAG_READ);
filerr = file.open(filename);
if (filerr == FILERR_NONE)
bytes_read = file.read(buffer, length);
/* fill remaining bytes (if necessary) */
memset(((char *) buffer) + bytes_read, fill, length - bytes_read);
}
/*-------------------------------------------------
image_battery_save_by_name - stores the battery
backed RAM for an image. A filename may be supplied
to the function.
-------------------------------------------------*/
static void image_battery_save_by_name(emu_options &options, const char *filename, const void *buffer, int length)
{
assert_always(buffer && (length > 0), "Must specify sensical buffer/length");
/* try to open the battery file and write it out, if possible */
emu_file file(options.nvram_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
file_error filerr = file.open(filename);
if (filerr == FILERR_NONE)
file.write(buffer, length);
}
gromport_device::gromport_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: bus8z_device(mconfig, GROMPORT, "Cartridge port", tag, owner, clock, "gromport", __FILE__),
device_slot_interface(mconfig, *this),

View File

@ -12,7 +12,6 @@
#include "formats/imageutl.h"
#include "cassette.h"
#include "ui/ui.h"
#include "image.h"
#define ANIMATION_FPS 1

View File

@ -16,7 +16,6 @@
#include "emu.h"
#include "formats/imageutl.h"
#include "flopdrv.h"
#include "image.h"
#define VERBOSE 0
#define LOG(x) do { if (VERBOSE) logerror x; } while (0)

View File

@ -12,7 +12,6 @@
#include "zippath.h"
#include "floppy.h"
#include "formats/imageutl.h"
#include "image.h"
/*
Debugging flags. Set to 0 or 1.

View File

@ -17,6 +17,7 @@
#include "ui/imgcntrl.h"
#include "softlist.h"
#include "image.h"
#include "formats/ioprocs.h"
//**************************************************************************
// DEVICE CONFIG IMAGE INTERFACE
@ -508,14 +509,39 @@ UINT32 device_image_interface::crc()
-------------------------------------------------*/
void device_image_interface::battery_load(void *buffer, int length, int fill)
{
assert_always(buffer && (length > 0), "Must specify sensical buffer/length");
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");
image_battery_load_by_name(device().machine().options(), fname.c_str(), buffer, length, fill);
/* 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 == FILERR_NONE)
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)
{
assert_always(buffer && (length > 0), "Must specify sensical buffer/length");
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");
image_battery_load_by_name(device().machine().options(), fname.c_str(), buffer, length, def_buffer);
/* 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 == FILERR_NONE)
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);
}
/*-------------------------------------------------
@ -526,9 +552,14 @@ void device_image_interface::battery_load(void *buffer, int length, void *def_bu
-------------------------------------------------*/
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");
image_battery_save_by_name(device().machine().options(), fname.c_str(), buffer, length);
/* 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);
file_error filerr = file.open(fname.c_str());
if (filerr == FILERR_NONE)
file.write(buffer, length);
}
//-------------------------------------------------
@ -1350,3 +1381,41 @@ ui_menu *device_image_interface::get_selection_menu(running_machine &machine, re
{
return auto_alloc_clear(machine, <ui_menu_control_device_image>(machine, container, this));
}
/* ----------------------------------------------------------------------- */
static int image_fseek_thunk(void *file, INT64 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 UINT64 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
};

View File

@ -21,6 +21,8 @@
// TYPE DEFINITIONS
//**************************************************************************
extern struct io_procs image_ioprocs;
class software_list;
enum iodevice_t

View File

@ -211,7 +211,7 @@ void driver_device::device_start()
(*m_system->driver_init)(machine());
// finish image devices init process
image_postdevice_init(machine());
machine().image().postdevice_init();
// start the various pieces
driver_start();

View File

@ -15,192 +15,17 @@
#include "image.h"
#include "config.h"
#include "xmlfile.h"
#include "formats/ioprocs.h"
/* ----------------------------------------------------------------------- */
//**************************************************************************
// IMAGE MANAGER
//**************************************************************************
static int image_fseek_thunk(void *file, INT64 offset, int whence)
{
device_image_interface *image = (device_image_interface *) file;
return image->fseek(offset, whence);
}
//-------------------------------------------------
// image_manager - constructor
//-------------------------------------------------
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 UINT64 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
};
/***************************************************************************
INITIALIZATION HELPERS
***************************************************************************/
/*-------------------------------------------------
image_dirs_load - loads image device directory
configuration items
-------------------------------------------------*/
static void image_dirs_load(running_machine &machine, config_type cfg_type, xml_data_node *parentnode)
{
xml_data_node *node;
const char *dev_instance;
const char *working_directory;
if ((cfg_type == config_type::CONFIG_TYPE_GAME) && (parentnode != nullptr))
{
for (node = xml_get_sibling(parentnode->child, "device"); node; node = xml_get_sibling(node->next, "device"))
{
dev_instance = xml_get_attribute_string(node, "instance", nullptr);
if ((dev_instance != nullptr) && (dev_instance[0] != '\0'))
{
image_interface_iterator iter(machine.root_device());
for (device_image_interface *image = iter.first(); image != nullptr; image = iter.next())
{
if (!strcmp(dev_instance, image->instance_name())) {
working_directory = xml_get_attribute_string(node, "directory", nullptr);
if (working_directory != nullptr)
image->set_working_directory(working_directory);
}
}
}
}
}
}
/*-------------------------------------------------
image_dirs_save - saves out image device
directories to the configuration file
-------------------------------------------------*/
static void image_dirs_save(running_machine &machine, config_type cfg_type, xml_data_node *parentnode)
{
xml_data_node *node;
const char *dev_instance;
/* only care about game-specific data */
if (cfg_type == config_type::CONFIG_TYPE_GAME)
{
image_interface_iterator iter(machine.root_device());
for (device_image_interface *image = iter.first(); image != nullptr; image = iter.next())
{
dev_instance = image->instance_name();
node = xml_add_child(parentnode, "device", nullptr);
if (node != nullptr)
{
xml_set_attribute(node, "instance", dev_instance);
xml_set_attribute(node, "directory", image->working_directory());
}
}
}
}
/*-------------------------------------------------
write_config - emit current option statuses as
INI files
-------------------------------------------------*/
static int write_config(emu_options &options, const char *filename, const game_driver *gamedrv)
{
char buffer[128];
int retval = 1;
if (gamedrv != nullptr)
{
sprintf(buffer, "%s.ini", gamedrv->name);
filename = buffer;
}
emu_file file(options.ini_path(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE);
file_error filerr = file.open(filename);
if (filerr == FILERR_NONE)
{
std::string inistring = options.output_ini();
file.puts(inistring.c_str());
retval = 0;
}
return retval;
}
/*-------------------------------------------------
image_options_extract - extract device options
out of core into the options
-------------------------------------------------*/
static void image_options_extract(running_machine &machine)
{
/* only extract the device options if we've added them
no need to assert in case they are missing */
{
int index = 0;
image_interface_iterator iter(machine.root_device());
for (device_image_interface *image = iter.first(); image != nullptr; image = iter.next())
{
const char *filename = image->filename();
/* and set the option */
std::string error;
machine.options().set_value(image->instance_name(), filename ? filename : "", OPTION_PRIORITY_CMDLINE, error);
index++;
}
}
/* write the config, if appropriate */
if (machine.options().write_config())
write_config(machine.options(), nullptr, &machine.system());
}
/*-------------------------------------------------
image_unload_all - unload all images and
extract options
-------------------------------------------------*/
void image_unload_all(running_machine &machine)
{
// extract the options
image_options_extract(machine);
image_interface_iterator iter(machine.root_device());
for (device_image_interface *image = iter.first(); image != nullptr; image = iter.next())
{
// unload this image
image->unload();
}
}
/*-------------------------------------------------
image_device_init - initialize devices for a specific
running_machine
-------------------------------------------------*/
void image_device_init(running_machine &machine)
image_manager::image_manager(running_machine &machine)
: m_machine(machine)
{
const char *image_name;
@ -226,9 +51,6 @@ void image_device_init(running_machine &machine)
std::string image_err = std::string(image->error());
std::string image_basename(image_name);
/* unload all images */
image_unload_all(machine);
fatalerror_exitcode(machine, MAMERR_DEVICE, "Device %s load (%s) failed: %s",
image->device().name(),
image_basename.c_str(),
@ -236,18 +58,150 @@ void image_device_init(running_machine &machine)
}
}
}
machine.configuration().config_register("image_directories", config_saveload_delegate(FUNC(image_manager::config_load), this), config_saveload_delegate(FUNC(image_manager::config_save), this));
}
//-------------------------------------------------
// image_manager - destructor
//-------------------------------------------------
image_manager::~image_manager()
{
// extract the options
options_extract();
image_interface_iterator iter(machine().root_device());
for (device_image_interface *image = iter.first(); image != nullptr; image = iter.next())
{
// unload this image
image->unload();
}
}
void image_manager::config_load(config_type cfg_type, xml_data_node *parentnode)
{
xml_data_node *node;
const char *dev_instance;
const char *working_directory;
if ((cfg_type == config_type::CONFIG_TYPE_GAME) && (parentnode != nullptr))
{
for (node = xml_get_sibling(parentnode->child, "device"); node; node = xml_get_sibling(node->next, "device"))
{
dev_instance = xml_get_attribute_string(node, "instance", nullptr);
if ((dev_instance != nullptr) && (dev_instance[0] != '\0'))
{
image_interface_iterator iter(machine().root_device());
for (device_image_interface *image = iter.first(); image != nullptr; image = iter.next())
{
if (!strcmp(dev_instance, image->instance_name())) {
working_directory = xml_get_attribute_string(node, "directory", nullptr);
if (working_directory != nullptr)
image->set_working_directory(working_directory);
}
}
}
}
}
}
/*-------------------------------------------------
config_save - saves out image device
directories to the configuration file
-------------------------------------------------*/
void image_manager::config_save(config_type cfg_type, xml_data_node *parentnode)
{
xml_data_node *node;
const char *dev_instance;
/* only care about game-specific data */
if (cfg_type == config_type::CONFIG_TYPE_GAME)
{
image_interface_iterator iter(machine().root_device());
for (device_image_interface *image = iter.first(); image != nullptr; image = iter.next())
{
dev_instance = image->instance_name();
node = xml_add_child(parentnode, "device", nullptr);
if (node != nullptr)
{
xml_set_attribute(node, "instance", dev_instance);
xml_set_attribute(node, "directory", image->working_directory());
}
}
}
}
/*-------------------------------------------------
write_config - emit current option statuses as
INI files
-------------------------------------------------*/
int image_manager::write_config(emu_options &options, const char *filename, const game_driver *gamedrv)
{
char buffer[128];
int retval = 1;
if (gamedrv != nullptr)
{
sprintf(buffer, "%s.ini", gamedrv->name);
filename = buffer;
}
emu_file file(options.ini_path(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE);
file_error filerr = file.open(filename);
if (filerr == FILERR_NONE)
{
std::string inistring = options.output_ini();
file.puts(inistring.c_str());
retval = 0;
}
return retval;
}
/*-------------------------------------------------
options_extract - extract device options
out of core into the options
-------------------------------------------------*/
void image_manager::options_extract()
{
/* only extract the device options if we've added them
no need to assert in case they are missing */
{
int index = 0;
image_interface_iterator iter(machine().root_device());
for (device_image_interface *image = iter.first(); image != nullptr; image = iter.next())
{
const char *filename = image->filename();
/* and set the option */
std::string error;
machine().options().set_value(image->instance_name(), filename ? filename : "", OPTION_PRIORITY_CMDLINE, error);
index++;
}
}
/* write the config, if appropriate */
if (machine().options().write_config())
write_config(machine().options(), nullptr, &machine().system());
}
/*-------------------------------------------------
image_mandatory_scan - search for devices which
need an image to be loaded
-------------------------------------------------*/
std::string &image_mandatory_scan(running_machine &machine, std::string &mandatory)
std::string &image_manager::mandatory_scan(std::string &mandatory)
{
mandatory.clear();
// make sure that any required image has a mounted file
image_interface_iterator iter(machine.root_device());
image_interface_iterator iter(machine().root_device());
for (device_image_interface *image = iter.first(); image != nullptr; image = iter.next())
{
if (image->filename() == nullptr && image->must_be_loaded())
@ -257,14 +211,14 @@ std::string &image_mandatory_scan(running_machine &machine, std::string &mandato
}
/*-------------------------------------------------
image_postdevice_init - initialize devices for a specific
postdevice_init - initialize devices for a specific
running_machine
-------------------------------------------------*/
void image_postdevice_init(running_machine &machine)
void image_manager::postdevice_init()
{
/* make sure that any required devices have been allocated */
image_interface_iterator iter(machine.root_device());
image_interface_iterator iter(machine().root_device());
for (device_image_interface *image = iter.first(); image != nullptr; image = iter.next())
{
int result = image->finish_load();
@ -274,99 +228,10 @@ void image_postdevice_init(running_machine &machine)
/* retrieve image error message */
std::string image_err = std::string(image->error());
/* unload all images */
image_unload_all(machine);
fatalerror_exitcode(machine, MAMERR_DEVICE, "Device %s load failed: %s",
fatalerror_exitcode(machine(), MAMERR_DEVICE, "Device %s load failed: %s",
image->device().name(),
image_err.c_str());
}
}
/* add a callback for when we shut down */
machine.add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(FUNC(image_unload_all), &machine));
}
/***************************************************************************
INITIALIZATION
***************************************************************************/
/*-------------------------------------------------
image_init - start up the image system
-------------------------------------------------*/
void image_init(running_machine &machine)
{
image_device_init(machine);
machine.configuration().config_register("image_directories", config_saveload_delegate(FUNC(image_dirs_load), &machine), config_saveload_delegate(FUNC(image_dirs_save), &machine));
}
/****************************************************************************
Battery functions
These functions provide transparent access to battery-backed RAM on an
image; typically for cartridges.
****************************************************************************/
/*-------------------------------------------------
image_battery_load_by_name - retrieves the battery
backed RAM for an image. A filename may be supplied
to the function.
The function comes in two flavors, depending on
what should happen when no battery is available:
we could fill the memory with a given value, or
pass a default battery (for a pre-initialized
battery from factory)
-------------------------------------------------*/
void image_battery_load_by_name(emu_options &options, const char *filename, void *buffer, int length, int fill)
{
file_error filerr;
int bytes_read = 0;
assert_always(buffer && (length > 0), "Must specify sensical buffer/length");
/* try to open the battery file and read it in, if possible */
emu_file file(options.nvram_directory(), OPEN_FLAG_READ);
filerr = file.open(filename);
if (filerr == FILERR_NONE)
bytes_read = file.read(buffer, length);
/* fill remaining bytes (if necessary) */
memset(((char *) buffer) + bytes_read, fill, length - bytes_read);
}
void image_battery_load_by_name(emu_options &options, const char *filename, void *buffer, int length, void *def_buffer)
{
file_error filerr;
int bytes_read = 0;
assert_always(buffer && (length > 0), "Must specify sensical buffer/length");
/* try to open the battery file and read it in, if possible */
emu_file file(options.nvram_directory(), OPEN_FLAG_READ);
filerr = file.open(filename);
if (filerr == FILERR_NONE)
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);
}
/*-------------------------------------------------
image_battery_save_by_name - stores the battery
backed RAM for an image. A filename may be supplied
to the function.
-------------------------------------------------*/
void image_battery_save_by_name(emu_options &options, const char *filename, const void *buffer, int length)
{
assert_always(buffer && (length > 0), "Must specify sensical buffer/length");
/* try to open the battery file and write it out, if possible */
emu_file file(options.nvram_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
file_error filerr = file.open(filename);
if (filerr == FILERR_NONE)
file.write(buffer, length);
}

View File

@ -13,14 +13,29 @@
#ifndef __IMAGE_H__
#define __IMAGE_H__
void image_init(running_machine &machine);
void image_postdevice_init(running_machine &machine);
std::string &image_mandatory_scan(running_machine &machine, std::string &mandatory);
// ======================> image_manager
extern struct io_procs image_ioprocs;
class image_manager
{
public:
// construction/destruction
image_manager(running_machine &machine);
~image_manager();
void image_battery_load_by_name(emu_options &options, const char *filename, void *buffer, int length, int fill);
void image_battery_load_by_name(emu_options &options, const char *filename, void *buffer, int length, void *def_buffer);
void image_battery_save_by_name(emu_options &options, const char *filename, const void *buffer, int length);
void postdevice_init();
std::string &mandatory_scan(std::string &mandatory);
// getters
running_machine &machine() const { return m_machine; }
private:
void config_load(config_type cfg_type, xml_data_node *parentnode);
void config_save(config_type cfg_type, xml_data_node *parentnode);
void options_extract();
int write_config(emu_options &options, const char *filename, const game_driver *gamedrv);
// internal state
running_machine & m_machine; // reference to our machine
};
#endif /* __IMAGE_H__ */

View File

@ -264,7 +264,7 @@ void running_machine::start()
save().save_item(NAME(m_rand_seed));
// initialize image devices
image_init(*this);
m_image = std::make_unique<image_manager>(*this);
m_tilemap = std::make_unique<tilemap_manager>(*this);
m_crosshair = make_unique_clear<crosshair_manager>(*this);
m_network = std::make_unique<network_manager>(*this);

View File

@ -91,6 +91,7 @@ class configuration_manager;
class output_manager;
class ui_input_manager;
class crosshair_manager;
class image_manager;
class osd_interface;
enum class config_type;
@ -175,6 +176,7 @@ public:
ui_manager &ui() const { assert(m_ui != nullptr); return *m_ui; }
ui_input_manager &ui_input() const { assert(m_ui_input != nullptr); return *m_ui_input; }
crosshair_manager &crosshair() const { assert(m_crosshair != nullptr); return *m_crosshair; }
image_manager &image() const { assert(m_image != nullptr); return *m_image; }
tilemap_manager &tilemap() const { assert(m_tilemap != nullptr); return *m_tilemap; }
debug_view_manager &debug_view() const { assert(m_debug_view != nullptr); return *m_debug_view; }
driver_device *driver_data() const { return &downcast<driver_device &>(root_device()); }
@ -293,6 +295,7 @@ private:
std::unique_ptr<configuration_manager> m_configuration; // internal data from config.c
std::unique_ptr<output_manager> m_output; // internal data from output.c
std::unique_ptr<crosshair_manager> m_crosshair; // internal data from crsshair.c
std::unique_ptr<image_manager> m_image; // internal data from image.c
// system state
machine_phase m_current_phase; // current execution phase

View File

@ -358,7 +358,7 @@ void ui_manager::display_startup_screens(bool first_time, bool show_disclaimer)
break;
case 3:
if (show_mandatory_fileman && image_mandatory_scan(machine(), messagebox_text).length() > 0)
if (show_mandatory_fileman && machine().image().mandatory_scan(messagebox_text).length() > 0)
{
std::string warning;
warning.assign("This driver requires images to be loaded in the following device(s): ").append(messagebox_text.substr(0, messagebox_text.length() - 2));