summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu
diff options
context:
space:
mode:
author Miodrag Milanovic <mmicko@gmail.com>2010-06-15 09:16:05 +0000
committer Miodrag Milanovic <mmicko@gmail.com>2010-06-15 09:16:05 +0000
commit791a3515b9b1e2b9761d695357e5ff1e621d0224 (patch)
tree5c356f6ef1cd67248f5093c4079745b4bad14635 /src/emu
parent2a5ee186143b35358af24085537426616c4508c6 (diff)
devlegacy.c,clifront.c,info.c [Miodrag Milanovic]
- Created legacy image device - Moved opresolv implementation from MESS - listmedia is option is available in MAME too - listxml output now contains image devices
Diffstat (limited to 'src/emu')
-rw-r--r--src/emu/clifront.c70
-rw-r--r--src/emu/devlegcy.c197
-rw-r--r--src/emu/devlegcy.h156
-rw-r--r--src/emu/diimage.c89
-rw-r--r--src/emu/diimage.h91
-rw-r--r--src/emu/emu.h2
-rw-r--r--src/emu/emu.mak2
-rw-r--r--src/emu/info.c59
-rw-r--r--src/emu/opresolv.c585
-rw-r--r--src/emu/opresolv.h160
10 files changed, 1406 insertions, 5 deletions
diff --git a/src/emu/clifront.c b/src/emu/clifront.c
index f05616006bf..380211d7eb8 100644
--- a/src/emu/clifront.c
+++ b/src/emu/clifront.c
@@ -55,6 +55,7 @@ static void display_help(void);
static int info_verifyroms(core_options *options, const char *gamename);
static int info_verifysamples(core_options *options, const char *gamename);
static int info_romident(core_options *options, const char *gamename);
+static int info_listmedia(core_options *opts, const char *gamename);
/* utilities */
static void romident(core_options *options, const char *filename, romident_status *status);
@@ -95,8 +96,8 @@ static const options_entry cli_options[] =
{ "verifysamples", "0", OPTION_COMMAND, "report samplesets that have problems" },
{ "romident", "0", OPTION_COMMAND, "compare files with known MAME roms" },
{ "listdevices;ld", "0", OPTION_COMMAND, "list available devices" },
-#ifdef MESS
{ "listmedia;lm", "0", OPTION_COMMAND, "list available media for the system" },
+#ifdef MESS
{ "listsoftware", "0", OPTION_COMMAND, "list known software for the system" },
#endif
@@ -273,8 +274,8 @@ static int execute_commands(core_options *options, const char *exename, const ga
{ CLIOPTION_LISTSAMPLES, cli_info_listsamples },
{ CLIOPTION_VERIFYROMS, info_verifyroms },
{ CLIOPTION_VERIFYSAMPLES, info_verifysamples },
-#ifdef MESS
{ CLIOPTION_LISTMEDIA, info_listmedia },
+#ifdef MESS
{ CLIOPTION_LISTSOFTWARE, info_listsoftware },
#endif
{ CLIOPTION_ROMIDENT, info_romident }
@@ -777,6 +778,71 @@ static int info_verifyroms(core_options *options, const char *gamename)
/*-------------------------------------------------
+ info_listmedia - output the list of image
+ devices referenced by a given game or set of
+ games
+-------------------------------------------------*/
+
+static int info_listmedia(core_options *options, const char *gamename)
+{
+ int count = 0, devcount;
+ int drvindex;
+ machine_config *config;
+ const device_config_image_interface *dev;
+ const char *src;
+ const char *driver_name;
+ const char *name;
+ const char *shortname;
+ char paren_shortname[16];
+
+ printf(" SYSTEM DEVICE NAME (brief) IMAGE FILE EXTENSIONS SUPPORTED \n");
+ printf("---------- -------------------- ------------------------------------\n");
+
+ /* iterate over drivers */
+ for (drvindex = 0; drivers[drvindex] != NULL; drvindex++)
+ if (mame_strwildcmp(gamename, drivers[drvindex]->name) == 0)
+ {
+ /* allocate the machine config */
+ config = machine_config_alloc(drivers[drvindex]->machine_config);
+
+ driver_name = drivers[drvindex]->name;
+
+ devcount = 0;
+
+ for (bool gotone = config->devicelist.first(dev); gotone; gotone = dev->next(dev))
+ {
+ src = downcast<const legacy_image_device_config_base *>(dev)->file_extensions();
+ name = downcast<const legacy_image_device_config_base *>(dev)->instance_name();
+ shortname = downcast<const legacy_image_device_config_base *>(dev)->brief_instance_name();
+
+ sprintf(paren_shortname, "(%s)", shortname);
+
+ printf("%-13s%-12s%-8s ", driver_name, name, paren_shortname);
+ driver_name = " ";
+
+ while (src && *src)
+ {
+ printf(".%-5s", src);
+ src += strlen(src) + 1;
+ devcount++;
+ }
+ printf("\n");
+ }
+ if (!devcount)
+ printf("%-13s(none)\n",driver_name);
+
+ count++;
+ machine_config_free(config);
+ }
+
+ if (!count)
+ printf("There are no Computers or Consoles named %s\n", gamename);
+
+ return (count > 0) ? MAMERR_NONE : MAMERR_NO_SUCH_GAME;
+}
+
+
+/*-------------------------------------------------
info_verifysamples - verify the sample sets of
one or more games
-------------------------------------------------*/
diff --git a/src/emu/devlegcy.c b/src/emu/devlegcy.c
index 7bb660e5af9..19a8579cc25 100644
--- a/src/emu/devlegcy.c
+++ b/src/emu/devlegcy.c
@@ -344,3 +344,200 @@ void legacy_nvram_device_base::nvram_write(mame_file &file)
device_nvram_func nvram_func = reinterpret_cast<device_nvram_func>(m_config.get_legacy_config_fct(DEVINFO_FCT_NVRAM));
(*nvram_func)(this, &file, TRUE);
}
+
+//**************************************************************************
+// LEGACY IMAGE DEVICE CONFIGURATION
+//**************************************************************************
+
+typedef struct _image_device_type_info image_device_type_info;
+struct _image_device_type_info
+{
+ iodevice_t type;
+ const char *name;
+ const char *shortname;
+};
+
+static const image_device_type_info device_info_array[] =
+{
+ { IO_CARTSLOT, "cartridge", "cart" }, /* 0 */
+ { IO_FLOPPY, "floppydisk", "flop" }, /* 1 */
+ { IO_HARDDISK, "harddisk", "hard" }, /* 2 */
+ { IO_CYLINDER, "cylinder", "cyln" }, /* 3 */
+ { IO_CASSETTE, "cassette", "cass" }, /* 4 */
+ { IO_PUNCHCARD, "punchcard", "pcrd" }, /* 5 */
+ { IO_PUNCHTAPE, "punchtape", "ptap" }, /* 6 */
+ { IO_PRINTER, "printer", "prin" }, /* 7 */
+ { IO_SERIAL, "serial", "serl" }, /* 8 */
+ { IO_PARALLEL, "parallel", "parl" }, /* 9 */
+ { IO_SNAPSHOT, "snapshot", "dump" }, /* 10 */
+ { IO_QUICKLOAD, "quickload", "quik" }, /* 11 */
+ { IO_MEMCARD, "memcard", "memc" }, /* 12 */
+ { IO_CDROM, "cdrom", "cdrm" }, /* 13 */
+ { IO_MAGTAPE, "magtape", "magt" }, /* 14 */
+};
+
+static const image_device_type_info *find_device_type(iodevice_t type)
+{
+ int i;
+ for (i = 0; i < ARRAY_LENGTH(device_info_array); i++)
+ {
+ if (device_info_array[i].type == type)
+ return &device_info_array[i];
+ }
+ return NULL;
+}
+
+static const char *device_typename(iodevice_t type)
+{
+ const image_device_type_info *info = find_device_type(type);
+ return (info != NULL) ? info->name : NULL;
+}
+
+
+
+static const char *device_brieftypename(iodevice_t type)
+{
+ const image_device_type_info *info = find_device_type(type);
+ return (info != NULL) ? info->shortname : NULL;
+}
+
+//-------------------------------------------------
+// legacy_image_device_config_base - constructor
+//-------------------------------------------------
+
+legacy_image_device_config_base::legacy_image_device_config_base(const machine_config &mconfig, device_type type, const char *tag, const device_config *owner, UINT32 clock, device_get_config_func get_config)
+ : legacy_device_config_base(mconfig, type, tag, owner, clock, get_config),
+ device_config_image_interface(mconfig, *this)
+{
+ memset(&m_config, 0, sizeof(m_config));
+ m_mconfig = &mconfig;
+}
+
+//-------------------------------------------------
+// device_config_complete - update configuration
+// based on completed device setup
+//-------------------------------------------------
+
+void legacy_image_device_config_base::device_config_complete()
+{
+ char buffer[64];
+ const device_config_image_interface *that_device;
+ int count = 0;
+ int index = -1;
+ image_device_format **formatptr;
+ image_device_format *format;
+ formatptr = &m_config.m_formatlist;
+ int cnt = 0;
+
+ m_config.m_type = static_cast<iodevice_t>(get_legacy_config_int(DEVINFO_INT_IMAGE_TYPE));
+ m_config.m_readable = get_legacy_config_int(DEVINFO_INT_IMAGE_READABLE)!=0;
+ m_config.m_writeable = get_legacy_config_int(DEVINFO_INT_IMAGE_WRITEABLE)!=0;
+ m_config.m_creatable = get_legacy_config_int(DEVINFO_INT_IMAGE_CREATABLE)!=0;
+ m_config.m_must_be_loaded = get_legacy_config_int(DEVINFO_INT_IMAGE_MUST_BE_LOADED)!=0;
+ m_config.m_reset_on_load = get_legacy_config_int(DEVINFO_INT_IMAGE_RESET_ON_LOAD)!=0;
+ m_config.m_has_partial_hash = get_legacy_config_int(DEVINFO_FCT_IMAGE_PARTIAL_HASH)!=0;
+
+ m_config.m_interface_name = core_strdup(get_legacy_config_string(DEVINFO_STR_IMAGE_INTERFACE));
+ char *s = global_alloc_array_clear(char,strlen(get_legacy_config_string(DEVINFO_STR_IMAGE_FILE_EXTENSIONS))+2);
+ strcpy(s,get_legacy_config_string(DEVINFO_STR_IMAGE_FILE_EXTENSIONS));
+ m_config.m_file_extensions = s;
+ /* convert the comma delimited list to a NUL delimited list */
+ while((s = strchr(s, ',')) != NULL)
+ *(s++) = '\0';
+
+ m_config.load = reinterpret_cast<device_image_load_func>(get_legacy_config_fct(DEVINFO_FCT_IMAGE_LOAD));
+ m_config.create = reinterpret_cast<device_image_create_func>(get_legacy_config_fct(DEVINFO_FCT_IMAGE_CREATE));
+ m_config.unload = reinterpret_cast<device_image_unload_func>(get_legacy_config_fct(DEVINFO_FCT_IMAGE_UNLOAD));
+ m_config.display = reinterpret_cast<device_image_display_func>(get_legacy_config_fct(DEVINFO_FCT_IMAGE_DISPLAY));
+ m_config.partialhash = reinterpret_cast<device_image_partialhash_func>(get_legacy_config_fct(DEVINFO_FCT_IMAGE_PARTIAL_HASH));
+ m_config.get_devices = reinterpret_cast<device_image_get_devices_func>(get_legacy_config_fct(DEVINFO_FCT_IMAGE_GET_DEVICES));
+
+ m_config.m_create_option_guide = reinterpret_cast<const option_guide *>(get_legacy_config_ptr(DEVINFO_PTR_IMAGE_CREATE_OPTGUIDE));
+
+ int format_count = get_legacy_config_int(DEVINFO_INT_IMAGE_CREATE_OPTCOUNT);
+
+ for (int i = 0; i < format_count; i++)
+ {
+ // only add if creatable
+ if (get_legacy_config_string(DEVINFO_PTR_IMAGE_CREATE_OPTSPEC + i)) {
+ // allocate a new format
+ format = global_alloc_clear(image_device_format);
+
+ // populate it
+ format->index = cnt;
+ format->name = core_strdup(get_legacy_config_string(DEVINFO_STR_IMAGE_CREATE_OPTNAME + i));
+ format->description = core_strdup(get_legacy_config_string(DEVINFO_STR_IMAGE_CREATE_OPTDESC + i));
+ format->extensions = core_strdup(get_legacy_config_string(DEVINFO_STR_IMAGE_CREATE_OPTEXTS + i));
+ format->optspec = core_strdup(get_legacy_config_string(DEVINFO_PTR_IMAGE_CREATE_OPTSPEC + i));
+
+ // and append it to the list
+ *formatptr = format;
+ formatptr = &format->next;
+ cnt++;
+ }
+ }
+
+ for (bool gotone = m_mconfig->devicelist.first(that_device); gotone; gotone = that_device->next(that_device))
+ {
+ if (this == that_device)
+ index = count;
+ if (downcast<const legacy_image_device_config_base *>(that_device)->image_type_direct() == m_config.m_type)
+ count++;
+ }
+ if (count > 1) {
+ snprintf(buffer, 64, "%s%d", device_typename(m_config.m_type), index + 1);
+ m_config.m_instance_name = core_strdup(buffer);
+ snprintf(buffer, 64, "%s%d", device_brieftypename(m_config.m_type), index + 1);
+ m_config.m_brief_instance_name = core_strdup(buffer);
+ }
+ else
+ {
+ m_config.m_instance_name = core_strdup(device_typename(m_config.m_type));
+ m_config.m_brief_instance_name = core_strdup(device_brieftypename(m_config.m_type));
+ }
+ // Override in case of hardcoded values
+ if (strlen(get_legacy_config_string(DEVINFO_STR_IMAGE_INSTANCE_NAME))>0) {
+ m_config.m_instance_name = core_strdup(get_legacy_config_string(DEVINFO_STR_IMAGE_INSTANCE_NAME));
+ }
+ if (strlen(get_legacy_config_string(DEVINFO_STR_IMAGE_BRIEF_INSTANCE_NAME))>0) {
+ m_config.m_brief_instance_name = core_strdup(get_legacy_config_string(DEVINFO_STR_IMAGE_BRIEF_INSTANCE_NAME));
+ }
+}
+
+const char *legacy_image_device_config_base::image_type_name() const
+{
+ return device_typename(m_config.m_type);
+}
+//-------------------------------------------------
+// ~legacy_device_config_base - destructor
+//-------------------------------------------------
+
+legacy_image_device_config_base::~legacy_image_device_config_base()
+{
+ global_free(m_config.m_file_extensions);
+ image_device_format **formatptr = &m_config.m_formatlist;
+
+
+ /* free all entries */
+ while (*formatptr != NULL)
+ {
+ image_device_format *entry = *formatptr;
+ *formatptr = entry->next;
+ global_free(entry);
+ }
+}
+
+
+//**************************************************************************
+// LIVE LEGACY IMAGE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// legacy_image_device_base - constructor
+//-------------------------------------------------
+
+legacy_image_device_base::legacy_image_device_base(running_machine &machine, const device_config &config)
+ : legacy_device_base(machine, config),
+ device_image_interface(machine, config, *this)
+{
+}
diff --git a/src/emu/devlegcy.h b/src/emu/devlegcy.h
index 5a320f840d3..d393d89478f 100644
--- a/src/emu/devlegcy.h
+++ b/src/emu/devlegcy.h
@@ -48,6 +48,8 @@
// CONSTANTS
//**************************************************************************
+#define DEVINFO_IMAGE_CREATE_OPTMAX 32
+
// state constants passed to the device_get_config_func
enum
{
@@ -130,9 +132,68 @@ enum
DEVINFO_STR_CLASS_SPECIFIC = 0x34000, // R/W: device-specific values start here
DEVINFO_STR_DEVICE_SPECIFIC = 0x38000, // R/W: device-specific values start here
- DEVINFO_STR_LAST = 0x3ffff
+ DEVINFO_STR_LAST = 0x3ffff,
+
+ /* --- image device related --- */
+ /* --- the following bits of info are returned as integers --- */
+ DEVINFO_INT_IMAGE_FIRST = DEVINFO_INT_FIRST + 0x7000,
+ DEVINFO_INT_IMAGE_TYPE,
+ DEVINFO_INT_IMAGE_READABLE,
+ DEVINFO_INT_IMAGE_WRITEABLE,
+ DEVINFO_INT_IMAGE_CREATABLE,
+ DEVINFO_INT_IMAGE_MUST_BE_LOADED,
+ DEVINFO_INT_IMAGE_RESET_ON_LOAD,
+ DEVINFO_INT_IMAGE_CREATE_OPTCOUNT,
+ DEVINFO_INT_IMAGE_LAST = DEVINFO_INT_IMAGE_FIRST + 0x0fff,
+
+ /* --- the following bits of info are returned as pointers --- */
+ DEVINFO_PTR_IMAGE_FIRST = DEVINFO_PTR_FIRST + 0x7000,
+ DEVINFO_PTR_IMAGE_CREATE_OPTGUIDE,
+ DEVINFO_PTR_IMAGE_CREATE_OPTSPEC,
+
+ /* --- the following bits of info are returned as pointers to functions --- */
+ DEVINFO_FCT_IMAGE_FIRST = DEVINFO_FCT_FIRST + 0x7000,
+ DEVINFO_FCT_IMAGE_LOAD, /* R/O: device_image_load_func */
+ DEVINFO_FCT_IMAGE_CREATE, /* R/O: device_image_create_func */
+ DEVINFO_FCT_IMAGE_UNLOAD, /* R/O: device_image_unload_func */
+ DEVINFO_FCT_IMAGE_DISPLAY, /* R/O: device_image_display_func */
+ DEVINFO_FCT_IMAGE_PARTIAL_HASH, /* R/O: device_image_partialhash_func */
+ DEVINFO_FCT_IMAGE_GET_DEVICES, /* R/O: device_image_get_devices_func */
+ DEVINFO_FCT_IMAGE_LAST = DEVINFO_FCT_FIRST + 0x0fff,
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ DEVINFO_STR_IMAGE_FIRST = DEVINFO_STR_FIRST + 0x7000,
+ DEVINFO_STR_IMAGE_FILE_EXTENSIONS,
+ DEVINFO_STR_IMAGE_INSTANCE_NAME,
+ DEVINFO_STR_IMAGE_BRIEF_INSTANCE_NAME,
+ DEVINFO_STR_IMAGE_CREATE_OPTNAME,
+ DEVINFO_STR_IMAGE_CREATE_OPTDESC = DEVINFO_STR_IMAGE_CREATE_OPTNAME + DEVINFO_IMAGE_CREATE_OPTMAX,
+ DEVINFO_STR_IMAGE_CREATE_OPTEXTS = DEVINFO_STR_IMAGE_CREATE_OPTDESC + DEVINFO_IMAGE_CREATE_OPTMAX,
+ DEVINFO_STR_IMAGE_INTERFACE,
+ DEVINFO_STR_IMAGE_LAST = DEVINFO_STR_IMAGE_FIRST + 0x0fff
};
+typedef enum
+{
+ /* List of all supported devices. Refer to the device by these names only */
+ IO_UNKNOWN,
+ IO_CARTSLOT, /* 1 - Cartridge Port, as found on most console and on some computers */
+ IO_FLOPPY, /* 2 - Floppy Disk unit */
+ IO_HARDDISK, /* 3 - Hard Disk unit */
+ IO_CYLINDER, /* 4 - Magnetically-Coated Cylinder */
+ IO_CASSETTE, /* 5 - Cassette Recorder (common on early home computers) */
+ IO_PUNCHCARD, /* 6 - Card Puncher/Reader */
+ IO_PUNCHTAPE, /* 7 - Tape Puncher/Reader (reels instead of punchcards) */
+ IO_PRINTER, /* 8 - Printer device */
+ IO_SERIAL, /* 9 - Generic Serial Port */
+ IO_PARALLEL, /* 10 - Generic Parallel Port */
+ IO_SNAPSHOT, /* 11 - Complete 'snapshot' of the state of the computer */
+ IO_QUICKLOAD, /* 12 - Allow to load program/data into memory, without matching any actual device */
+ IO_MEMCARD, /* 13 - Memory card */
+ IO_CDROM, /* 14 - optical CD-ROM disc */
+ IO_MAGTAPE, /* 15 - Magentic tape */
+ IO_COUNT /* 16 - Total Number of IO_devices for searching */
+} iodevice_t;
//**************************************************************************
@@ -191,11 +252,13 @@ device_t *configclass::alloc_device(running_machine &machine) const \
#define DECLARE_LEGACY_SOUND_DEVICE(name, basename) _DECLARE_LEGACY_DEVICE(SOUND_##name, basename, basename##_sound_device_config, basename##_sound_device, legacy_sound_device_config_base, legacy_sound_device_base)
#define DECLARE_LEGACY_MEMORY_DEVICE(name, basename) _DECLARE_LEGACY_DEVICE(name, basename, basename##_device_config, basename##_device, legacy_memory_device_config_base, legacy_memory_device_base)
#define DECLARE_LEGACY_NVRAM_DEVICE(name, basename) _DECLARE_LEGACY_DEVICE(name, basename, basename##_device_config, basename##_device, legacy_nvram_device_config_base, legacy_nvram_device_base)
+#define DECLARE_LEGACY_IMAGE_DEVICE(name, basename) _DECLARE_LEGACY_DEVICE(name, basename, basename##_device_config, basename##_device, legacy_image_device_config_base, legacy_image_device_base)
#define DEFINE_LEGACY_DEVICE(name, basename) _DEFINE_LEGACY_DEVICE(name, basename, basename##_device_config, basename##_device, legacy_device_config_base, legacy_device_base)
#define DEFINE_LEGACY_SOUND_DEVICE(name, basename) _DEFINE_LEGACY_DEVICE(SOUND_##name, basename, basename##_sound_device_config, basename##_sound_device, legacy_sound_device_config_base, legacy_sound_device_base)
#define DEFINE_LEGACY_MEMORY_DEVICE(name, basename) _DEFINE_LEGACY_DEVICE(name, basename, basename##_device_config, basename##_device, legacy_memory_device_config_base, legacy_memory_device_base)
#define DEFINE_LEGACY_NVRAM_DEVICE(name, basename) _DEFINE_LEGACY_DEVICE(name, basename, basename##_device_config, basename##_device, legacy_nvram_device_config_base, legacy_nvram_device_base)
+#define DEFINE_LEGACY_IMAGE_DEVICE(name, basename) _DEFINE_LEGACY_DEVICE(name, basename, basename##_device_config, basename##_device, legacy_image_device_config_base, legacy_image_device_base)
// macros to wrap legacy device functions
@@ -346,6 +409,13 @@ typedef INT32 (*device_execute_func)(device_t *device, INT32 clocks);
typedef void (*device_reset_func)(device_t *device);
typedef void (*device_nvram_func)(device_t *device, mame_file *file, int read_or_write);
+// device image interface function types
+typedef int (*device_image_load_func)(running_device *image);
+typedef int (*device_image_create_func)(running_device *image, int format_type, option_resolution *format_options);
+typedef void (*device_image_unload_func)(running_device *image);
+typedef void (*device_image_display_func)(running_device *image);
+typedef void (*device_image_partialhash_func)(char *, const unsigned char *, unsigned long, unsigned int);
+typedef void (*device_image_get_devices_func)(running_device *device);
// the actual deviceinfo union
union deviceinfo
@@ -530,5 +600,89 @@ protected:
virtual void nvram_write(mame_file &file);
};
+// ======================> legacy_image_device_config
+typedef struct _image_device_format image_device_format;
+struct _image_device_format
+{
+ image_device_format *next;
+ int index;
+ const char *name;
+ const char *description;
+ const char *extensions;
+ const char *optspec;
+};
+
+struct image_config
+{
+ iodevice_t m_type;
+ bool m_readable;
+ bool m_writeable;
+ bool m_creatable;
+ bool m_must_be_loaded;
+ bool m_reset_on_load;
+ bool m_has_partial_hash;
+ const char *m_file_extensions;
+ const char *m_instance_name;
+ const char *m_brief_instance_name;
+ const char *m_interface_name;
+
+ device_image_load_func load;
+ device_image_create_func create;
+ device_image_unload_func unload;
+ device_image_display_func display;
+ device_image_partialhash_func partialhash;
+ device_image_get_devices_func get_devices;
+
+ /* creation info */
+ const option_guide *m_create_option_guide;
+ image_device_format *m_formatlist;
+};
+// legacy_image_device_config is a device_config with a image interface
+class legacy_image_device_config_base : public legacy_device_config_base,
+ public device_config_image_interface
+{
+public:
+ virtual iodevice_t image_type() const { return m_config.m_type; }
+ virtual const char *image_type_name() const;
+ virtual iodevice_t image_type_direct() const { return static_cast<iodevice_t>(get_legacy_config_int(DEVINFO_INT_IMAGE_TYPE)); }
+ virtual bool is_readable() const { return m_config.m_readable; }
+ virtual bool is_writeable() const { return m_config.m_writeable; }
+ virtual bool is_creatable() const { return m_config.m_creatable; }
+ virtual bool must_be_loaded() const { return m_config.m_must_be_loaded; }
+ virtual bool is_reset_on_load() const { return m_config.m_reset_on_load; }
+ virtual bool has_partiah_hash() const { return m_config.m_has_partial_hash; }
+ virtual const char *image_interface() const { return m_config.m_interface_name; }
+ virtual const char *file_extensions() const { return m_config.m_file_extensions; }
+ virtual const char *file_extensions_list() const { return core_strdup(get_legacy_config_string(DEVINFO_STR_IMAGE_FILE_EXTENSIONS)); }
+ virtual const char *instance_name() const { return m_config.m_instance_name; }
+ virtual const char *brief_instance_name() const { return m_config.m_brief_instance_name; }
+protected:
+ // construction/destruction
+ legacy_image_device_config_base(const machine_config &mconfig, device_type type, const char *tag, const device_config *owner, UINT32 clock, device_get_config_func get_config);
+ virtual ~legacy_image_device_config_base();
+
+ // device_config overrides
+ virtual void device_config_complete();
+
+ image_config m_config;
+ const machine_config *m_mconfig;
+};
+
+
+// ======================> legacy_image_device
+
+// legacy_image_device is a legacy_device_base with a image interface
+class legacy_image_device_base : public legacy_device_base,
+ public device_image_interface
+{
+protected:
+ // construction/destruction
+ legacy_image_device_base(running_machine &machine, const device_config &config);
+
+ // device_image_interface overrides
+};
+
+
+
#endif /* __DEVLEGCY_H__ */
diff --git a/src/emu/diimage.c b/src/emu/diimage.c
new file mode 100644
index 00000000000..9a6cf74ebdc
--- /dev/null
+++ b/src/emu/diimage.c
@@ -0,0 +1,89 @@
+/***************************************************************************
+
+ diimage.c
+
+ Device image interfaces.
+
+****************************************************************************
+
+ Copyright Miodrag Milanovic
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name 'MAME' nor the names of its contributors may be
+ used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+***************************************************************************/
+
+#include "emu.h"
+
+
+
+//**************************************************************************
+// DEVICE CONFIG IMAGE INTERFACE
+//**************************************************************************
+
+//-------------------------------------------------
+// device_config_nvram_interface - constructor
+//-------------------------------------------------
+
+device_config_image_interface::device_config_image_interface(const machine_config &mconfig, device_config &devconfig)
+ : device_config_interface(mconfig, devconfig)
+{
+}
+
+
+//-------------------------------------------------
+// ~device_config_image_interface - destructor
+//-------------------------------------------------
+
+device_config_image_interface::~device_config_image_interface()
+{
+}
+
+
+
+//**************************************************************************
+// DEVICE image INTERFACE
+//**************************************************************************
+
+//-------------------------------------------------
+// device_image_interface - constructor
+//-------------------------------------------------
+
+device_image_interface::device_image_interface(running_machine &machine, const device_config &config, device_t &device)
+ : device_interface(machine, config, device),
+ m_image_config(dynamic_cast<const device_config_image_interface &>(config))
+{
+}
+
+
+//-------------------------------------------------
+// ~device_image_interface - destructor
+//-------------------------------------------------
+
+device_image_interface::~device_image_interface()
+{
+}
diff --git a/src/emu/diimage.h b/src/emu/diimage.h
new file mode 100644
index 00000000000..5ad80884070
--- /dev/null
+++ b/src/emu/diimage.h
@@ -0,0 +1,91 @@
+/***************************************************************************
+
+ diimage.h
+
+ Device image interfaces.
+
+****************************************************************************
+
+ Copyright Miodrag Milanovic
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name 'MAME' nor the names of its contributors may be
+ used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __EMU_H__
+#error Dont include this file directly; include emu.h instead.
+#endif
+
+#ifndef __DIIMAGE_H__
+#define __DIIMAGE_H__
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+
+// ======================> device_config_image_interface
+
+// class representing interface-specific configuration image
+class device_config_image_interface : public device_config_interface
+{
+public:
+ // construction/destruction
+ device_config_image_interface(const machine_config &mconfig, device_config &device);
+ virtual ~device_config_image_interface();
+};
+
+
+
+// ======================> device_image_interface
+
+// class representing interface-specific live image
+class device_image_interface : public device_interface
+{
+public:
+ // construction/destruction
+ device_image_interface(running_machine &machine, const device_config &config, device_t &device);
+ virtual ~device_image_interface();
+
+ // configuration access
+ const device_config_image_interface &image_config() const { return m_image_config; }
+
+ // public accessors... for now
+
+protected:
+ // derived class overrides
+
+ // configuration
+ const device_config_image_interface &m_image_config; // reference to our device_config_execute_interface
+};
+
+
+#endif /* __DIIMAGE_H__ */
diff --git a/src/emu/emu.h b/src/emu/emu.h
index 3086a64b4c6..281e23235d8 100644
--- a/src/emu/emu.h
+++ b/src/emu/emu.h
@@ -72,6 +72,8 @@
#include "distate.h"
#include "dimemory.h"
#include "diexec.h"
+#include "opresolv.h"
+#include "diimage.h"
#include "disound.h"
#include "dinvram.h"
#include "didisasm.h"
diff --git a/src/emu/emu.mak b/src/emu/emu.mak
index 7d62845c3d3..1e83756a748 100644
--- a/src/emu/emu.mak
+++ b/src/emu/emu.mak
@@ -50,6 +50,7 @@ EMUOBJS = \
$(EMUOBJ)/devintrf.o \
$(EMUOBJ)/didisasm.o \
$(EMUOBJ)/diexec.o \
+ $(EMUOBJ)/diimage.o \
$(EMUOBJ)/dimemory.o \
$(EMUOBJ)/dinvram.o \
$(EMUOBJ)/disound.o \
@@ -70,6 +71,7 @@ EMUOBJS = \
$(EMUOBJ)/mconfig.o \
$(EMUOBJ)/memory.o \
$(EMUOBJ)/output.o \
+ $(EMUOBJ)/opresolv.o \
$(EMUOBJ)/render.o \
$(EMUOBJ)/rendfont.o \
$(EMUOBJ)/rendlay.o \
diff --git a/src/emu/info.c b/src/emu/info.c
index 583eb757329..85d6d3b64d0 100644
--- a/src/emu/info.c
+++ b/src/emu/info.c
@@ -868,6 +868,60 @@ static void print_game_categories(FILE *out, const game_driver *game, const iopo
}
/*-------------------------------------------------
+ print_game_images - prints out all info on
+ image devices
+-------------------------------------------------*/
+
+static void print_game_images(FILE *out, const game_driver *game, const machine_config *config)
+{
+ const device_config_image_interface *dev;
+ const char *name;
+ const char *shortname;
+ const char *ext;
+
+ for (bool gotone = config->devicelist.first(dev); gotone; gotone = dev->next(dev))
+ {
+ const legacy_image_device_config_base *info = downcast<const legacy_image_device_config_base *>(dev);
+
+ /* print out device type */
+ fprintf(out, "\t\t<device type=\"%s\"", xml_normalize_string(info->image_type_name()));
+
+ /* does this device have a tag? */
+ if (info->tag())
+ fprintf(out, " tag=\"%s\"", xml_normalize_string(info->tag()));
+
+ /* is this device mandatory? */
+ if (info->must_be_loaded())
+ fprintf(out, " mandatory=\"1\"");
+
+ if (info->image_interface()[0] )
+ fprintf(out, " interface=\"%s\"", xml_normalize_string(info->image_interface()));
+
+ /* close the XML tag */
+ fprintf(out, ">\n");
+
+ name = info->instance_name();
+ shortname = info->brief_instance_name();
+
+ fprintf(out, "\t\t\t<instance");
+ fprintf(out, " name=\"%s\"", xml_normalize_string(name));
+ fprintf(out, " briefname=\"%s\"", xml_normalize_string(shortname));
+ fprintf(out, "/>\n");
+
+ ext = info->file_extensions();
+ while (*ext)
+ {
+ fprintf(out, "\t\t\t<extension");
+ fprintf(out, " name=\"%s\"", xml_normalize_string(ext));
+ fprintf(out, "/>\n");
+ ext += strlen(ext) + 1;
+ }
+
+ fprintf(out, "\t\t</device>\n");
+ }
+}
+
+/*-------------------------------------------------
print_game_info - print the XML information
for one particular game driver
-------------------------------------------------*/
@@ -941,6 +995,7 @@ static void print_game_info(FILE *out, const game_driver *game)
print_game_categories(out, game, portlist);
print_game_adjusters(out, game, portlist);
print_game_driver(out, game, config);
+ print_game_images( out, game, config );
#ifdef MESS
print_mess_game_xml(out, game, config);
#endif /* MESS */
@@ -971,7 +1026,7 @@ void print_mame_xml(FILE *out, const game_driver *const games[], const char *gam
#ifdef MESS
"\t<!ELEMENT " XML_TOP " (description, year?, manufacturer, biosset*, rom*, disk*, sample*, chip*, display*, sound?, input?, dipswitch*, configuration*, category*, adjuster*, driver?, device*, ramoption*, softwarelist*)>\n"
#else
- "\t<!ELEMENT " XML_TOP " (description, year?, manufacturer, biosset*, rom*, disk*, sample*, chip*, display*, sound?, input?, dipswitch*, configuration*, category*, adjuster*, driver?)>\n"
+ "\t<!ELEMENT " XML_TOP " (description, year?, manufacturer, biosset*, rom*, disk*, sample*, chip*, display*, sound?, input?, dipswitch*, configuration*, category*, adjuster*, driver?, device*)>\n"
#endif
"\t\t<!ATTLIST " XML_TOP " name CDATA #REQUIRED>\n"
"\t\t<!ATTLIST " XML_TOP " sourcefile CDATA #IMPLIED>\n"
@@ -1078,7 +1133,6 @@ void print_mame_xml(FILE *out, const game_driver *const games[], const char *gam
"\t\t\t<!ATTLIST driver protection (good|imperfect|preliminary) #IMPLIED>\n"
"\t\t\t<!ATTLIST driver savestate (supported|unsupported) #REQUIRED>\n"
"\t\t\t<!ATTLIST driver palettesize CDATA #REQUIRED>\n"
-#ifdef MESS
"\t\t<!ELEMENT device (instance*, extension*)>\n"
"\t\t\t<!ATTLIST device type CDATA #REQUIRED>\n"
"\t\t\t<!ATTLIST device tag CDATA #IMPLIED>\n"
@@ -1089,6 +1143,7 @@ void print_mame_xml(FILE *out, const game_driver *const games[], const char *gam
"\t\t\t\t<!ATTLIST instance briefname CDATA #REQUIRED>\n"
"\t\t\t<!ELEMENT extension EMPTY>\n"
"\t\t\t\t<!ATTLIST extension name CDATA #REQUIRED>\n"
+#ifdef MESS
"\t\t<!ELEMENT ramoption (#PCDATA)>\n"
"\t\t\t<!ATTLIST ramoption default CDATA #IMPLIED>\n"
"\t\t<!ELEMENT softwarelist EMPTY>\n"
diff --git a/src/emu/opresolv.c b/src/emu/opresolv.c
new file mode 100644
index 00000000000..aa63396804e
--- /dev/null
+++ b/src/emu/opresolv.c
@@ -0,0 +1,585 @@
+/****************************************************************************
+
+ opresolv.h
+
+ Extensible ranged option resolution handling
+
+****************************************************************************/
+
+#include <assert.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "pool.h"
+#include "opresolv.h"
+#include "emu.h"
+
+enum resolution_entry_state
+{
+ RESOLUTION_ENTRY_STATE_UNSPECIFIED,
+ RESOLUTION_ENTRY_STATE_SPECIFIED
+};
+
+struct option_resolution_entry
+{
+ const option_guide *guide_entry;
+ enum resolution_entry_state state;
+ union
+ {
+ int int_value;
+ const char *str_value;
+ } u;
+};
+
+struct _option_resolution
+{
+ object_pool *pool;
+ const char *specification;
+ size_t option_count;
+ struct option_resolution_entry *entries;
+};
+
+
+
+/* syntax errors are generally indicative of some sort of internal error */
+static void syntaxerror(const char *str)
+{
+#ifdef MAME_DEBUG
+ logerror("Option resolution syntax error! str='%s'\n", str);
+#endif
+}
+
+
+
+static optreserr_t resolve_single_param(const char *specification, int *param_value,
+ struct OptionRange *range, size_t range_count)
+{
+ int FLAG_IN_RANGE = 0x01;
+ int FLAG_IN_DEFAULT = 0x02;
+ int FLAG_DEFAULT_SPECIFIED = 0x04;
+ int FLAG_HALF_RANGE = 0x08;
+
+ int last_value = 0;
+ int value = 0;
+ int flags = 0;
+ const char *s = specification;
+
+ while(*s && !isalpha(*s))
+ {
+ if (*s == '-')
+ {
+ /* range specifier */
+ if (flags & (FLAG_IN_RANGE|FLAG_IN_DEFAULT))
+ {
+ syntaxerror(NULL);
+ return OPTIONRESOLUTION_ERROR_SYNTAX;
+ }
+ flags |= FLAG_IN_RANGE;
+ s++;
+
+ if (range)
+ {
+ range->max = -1;
+ if ((flags & FLAG_HALF_RANGE) == 0)
+ {
+ range->min = -1;
+ flags |= FLAG_HALF_RANGE;
+ }
+ }
+ }
+ else if (*s == '[')
+ {
+ /* begin default value */
+ if (flags & (FLAG_IN_DEFAULT|FLAG_DEFAULT_SPECIFIED))
+ {
+ syntaxerror(NULL);
+ return OPTIONRESOLUTION_ERROR_SYNTAX;
+ }
+ flags |= FLAG_IN_DEFAULT;
+ s++;
+ }
+ else if (*s == ']')
+ {
+ /* end default value */
+ if ((flags & FLAG_IN_DEFAULT) == 0)
+ {
+ syntaxerror(NULL);
+ return OPTIONRESOLUTION_ERROR_SYNTAX;
+ }
+ flags &= ~FLAG_IN_DEFAULT;
+ flags |= FLAG_DEFAULT_SPECIFIED;
+ s++;
+
+ if (param_value && *param_value == -1)
+ *param_value = value;
+ }
+ else if (*s == '/')
+ {
+ /* value separator */
+ if (flags & (FLAG_IN_DEFAULT|FLAG_IN_RANGE))
+ {
+ syntaxerror(NULL);
+ return OPTIONRESOLUTION_ERROR_SYNTAX;
+ }
+ s++;
+
+ /* if we are spitting out ranges, complete the range */
+ if (range && (flags & FLAG_HALF_RANGE))
+ {
+ range++;
+ flags &= ~FLAG_HALF_RANGE;
+ if (--range_count == 0)
+ range = NULL;
+ }
+ }
+ else if (*s == ';')
+ {
+ /* basic separator */
+ s++;
+ }
+ else if (isdigit(*s))
+ {
+ /* numeric value */
+ last_value = value;
+ value = 0;
+ do
+ {
+ value *= 10;
+ value += *s - '0';
+ s++;
+ }
+ while(isdigit(*s));
+
+ if (range)
+ {
+ if ((flags & FLAG_HALF_RANGE) == 0)
+ {
+ range->min = value;
+ flags |= FLAG_HALF_RANGE;
+ }
+ range->max = value;
+ }
+
+ /* if we have a value; check to see if it is out of range */
+ if (param_value && (*param_value != -1) && (*param_value != value))
+ {
+ if ((last_value < *param_value) && (*param_value < value))
+ {
+ if ((flags & FLAG_IN_RANGE) == 0)
+ return OPTIONRESOLUTION_ERROR_PARAMOUTOFRANGE;
+ }
+ }
+ flags &= ~FLAG_IN_RANGE;
+ }
+ else
+ {
+ syntaxerror(NULL);
+ return OPTIONRESOLUTION_ERROR_SYNTAX;
+ }
+ }
+
+ /* we can't have zero length guidelines strings */
+ if (s == specification)
+ {
+ syntaxerror(NULL);
+ return OPTIONRESOLUTION_ERROR_SYNTAX;
+ }
+
+ return OPTIONRESOLUTION_ERROR_SUCCESS;
+}
+
+
+
+static const char *lookup_in_specification(const char *specification, const option_guide *option)
+{
+ const char *s;
+ s = strchr(specification, option->parameter);
+ return s ? s + 1 : NULL;
+}
+
+
+
+option_resolution *option_resolution_create(const option_guide *guide, const char *specification)
+{
+ option_resolution *resolution = NULL;
+ const option_guide *guide_entry;
+ int option_count;
+ int opt = -1;
+ object_pool *pool;
+
+ assert(guide);
+
+ /* first count the number of options specified in the guide */
+ option_count = option_resolution_countoptions(guide, specification);
+
+ /* create a memory pool for this structure */
+ pool = pool_alloc_lib(NULL);
+ if (!pool)
+ goto outofmemory;
+
+ /* allocate the main structure */
+ resolution = (option_resolution *)pool_malloc_lib(pool, sizeof(option_resolution));
+ if (!resolution)
+ goto outofmemory;
+ memset(resolution, 0, sizeof(*resolution));
+ resolution->pool = pool;
+
+ /* set up the entries list */
+ resolution->option_count = option_count;
+ resolution->specification = specification;
+ resolution->entries = (option_resolution_entry *)pool_malloc_lib(resolution->pool, sizeof(struct option_resolution_entry) * option_count);
+ if (!resolution->entries)
+ goto outofmemory;
+ memset(resolution->entries, 0, sizeof(struct option_resolution_entry) * option_count);
+
+ /* initialize each of the entries */
+ opt = 0;
+ guide_entry = guide;
+ while(guide_entry->option_type != OPTIONTYPE_END)
+ {
+ switch(guide_entry->option_type) {
+ case OPTIONTYPE_INT:
+ case OPTIONTYPE_ENUM_BEGIN:
+ case OPTIONTYPE_STRING:
+ if (lookup_in_specification(specification, guide_entry))
+ resolution->entries[opt++].guide_entry = guide_entry;
+ break;
+ case OPTIONTYPE_ENUM_VALUE:
+ break;
+ default:
+ goto unexpected;
+ }
+ guide_entry++;
+ }
+ assert(opt == option_count);
+ return resolution;
+
+unexpected:
+ assert(FALSE);
+outofmemory:
+ if (resolution)
+ option_resolution_close(resolution);
+ return NULL;
+}
+
+
+
+optreserr_t option_resolution_add_param(option_resolution *resolution, const char *param, const char *value)
+{
+ int i;
+ int must_resolve;
+ optreserr_t err;
+ const char *option_specification;
+ struct option_resolution_entry *entry = NULL;
+
+ for (i = 0; i < resolution->option_count; i++)
+ {
+ if (!strcmp(param, resolution->entries[i].guide_entry->identifier))
+ {
+ entry = &resolution->entries[i];
+ break;
+ }
+ }
+ if (!entry)
+ return OPTIONRESOLUTION_ERROR_PARAMNOTFOUND;
+
+ if (entry->state != RESOLUTION_ENTRY_STATE_UNSPECIFIED)
+ return OPTIONRESOLUTION_ERROR_PARAMALREADYSPECIFIED;
+
+ switch(entry->guide_entry->option_type) {
+ case OPTIONTYPE_INT:
+ entry->u.int_value = atoi(value);
+ entry->state = RESOLUTION_ENTRY_STATE_SPECIFIED;
+ must_resolve = TRUE;
+ break;
+
+ case OPTIONTYPE_STRING:
+ entry->u.str_value = pool_strdup_lib(resolution->pool, value);
+ if (!entry->u.str_value)
+ {
+ err = OPTIONRESOLUTION_ERROR_OUTOFMEMORY;
+ goto done;
+ }
+ entry->state = RESOLUTION_ENTRY_STATE_SPECIFIED;
+ must_resolve = FALSE;
+ break;
+
+ case OPTIONTYPE_ENUM_BEGIN:
+ for (i = 1; entry->guide_entry[i].option_type == OPTIONTYPE_ENUM_VALUE; i++)
+ {
+ if (!mame_stricmp(value, entry->guide_entry[i].identifier))
+ {
+ entry->u.int_value = entry->guide_entry[i].parameter;
+ entry->state = RESOLUTION_ENTRY_STATE_SPECIFIED;
+ break;
+ }
+ }
+ if (entry->state != RESOLUTION_ENTRY_STATE_SPECIFIED)
+ {
+ err = OPTIONRESOLUTION_ERROR_BADPARAM;
+ goto done;
+ }
+ must_resolve = TRUE;
+ break;
+
+ default:
+ err = OPTIONRESOLTUION_ERROR_INTERNAL;
+ assert(0);
+ goto done;
+ }
+
+ /* do a resolution step if necessary */
+ if (must_resolve)
+ {
+ option_specification = lookup_in_specification(resolution->specification, entry->guide_entry);
+ err = resolve_single_param(option_specification, &entry->u.int_value, NULL, 0);
+ if (err)
+ goto done;
+
+ /* did we not get a real value? */
+ if (entry->u.int_value < 0)
+ {
+ err = OPTIONRESOLUTION_ERROR_PARAMNOTSPECIFIED;
+ goto done;
+ }
+ }
+
+ err = OPTIONRESOLUTION_ERROR_SUCCESS;
+
+done:
+ return err;
+}
+
+
+
+void option_resolution_close(option_resolution *resolution)
+{
+ pool_free_lib(resolution->pool);
+}
+
+
+
+optreserr_t option_resolution_finish(option_resolution *resolution)
+{
+ int i;
+ optreserr_t err;
+ struct option_resolution_entry *entry;
+ const char *option_specification;
+
+ for (i = 0; i < resolution->option_count; i++)
+ {
+ entry = &resolution->entries[i];
+
+ if (entry->state == RESOLUTION_ENTRY_STATE_UNSPECIFIED)
+ {
+ switch(entry->guide_entry->option_type) {
+ case OPTIONTYPE_INT:
+ case OPTIONTYPE_ENUM_BEGIN:
+ option_specification = lookup_in_specification(resolution->specification, entry->guide_entry);
+ assert(option_specification);
+ entry->u.int_value = -1;
+ err = resolve_single_param(option_specification, &entry->u.int_value, NULL, 0);
+ if (err)
+ return err;
+ break;
+
+ case OPTIONTYPE_STRING:
+ entry->u.str_value = "";
+ break;
+
+ default:
+ assert(FALSE);
+ return OPTIONRESOLTUION_ERROR_INTERNAL;
+ }
+ entry->state = RESOLUTION_ENTRY_STATE_SPECIFIED;
+ }
+ }
+ return OPTIONRESOLUTION_ERROR_SUCCESS;
+}
+
+
+
+static const struct option_resolution_entry *option_resolution_lookup_entry(option_resolution *resolution, int option_char)
+{
+ size_t i;
+ const struct option_resolution_entry *entry;
+
+ for (i = 0; i < resolution->option_count; i++)
+ {
+ entry = &resolution->entries[i];
+
+ switch(entry->guide_entry->option_type) {
+ case OPTIONTYPE_INT:
+ case OPTIONTYPE_STRING:
+ case OPTIONTYPE_ENUM_BEGIN:
+ if (entry->guide_entry->parameter == option_char)
+ return entry;
+ break;
+
+ default:
+ assert(FALSE);
+ return NULL;
+ }
+ }
+ return NULL;
+}
+
+
+
+int option_resolution_lookup_int(option_resolution *resolution, int option_char)
+{
+ const struct option_resolution_entry *entry;
+ entry = option_resolution_lookup_entry(resolution, option_char);
+ return entry ? entry->u.int_value : -1;
+}
+
+
+
+const char *option_resolution_lookup_string(option_resolution *resolution, int option_char)
+{
+ const struct option_resolution_entry *entry;
+ entry = option_resolution_lookup_entry(resolution, option_char);
+ return entry ? entry->u.str_value : NULL;
+}
+
+
+
+const char *option_resolution_specification(option_resolution *resolution)
+{
+ return resolution->specification;
+}
+
+
+
+const option_guide *option_resolution_find_option(option_resolution *resolution, int option_char)
+{
+ const struct option_resolution_entry *entry;
+ entry = option_resolution_lookup_entry(resolution, option_char);
+ return entry ? entry->guide_entry : NULL;
+}
+
+
+
+const option_guide *option_resolution_index_option(option_resolution *resolution, int indx)
+{
+ if ((indx < 0) || (indx >= resolution->option_count))
+ return NULL;
+ return resolution->entries[indx].guide_entry;
+}
+
+
+
+int option_resolution_countoptions(const option_guide *guide, const char *specification)
+{
+ int option_count = 0;
+
+ while(guide->option_type != OPTIONTYPE_END)
+ {
+ switch(guide->option_type) {
+ case OPTIONTYPE_INT:
+ case OPTIONTYPE_STRING:
+ case OPTIONTYPE_ENUM_BEGIN:
+ if (lookup_in_specification(specification, guide))
+ option_count++;
+ break;
+ case OPTIONTYPE_ENUM_VALUE:
+ break;
+ default:
+ assert(FALSE);
+ return 0;
+ }
+ guide++;
+ }
+ return option_count;
+}
+
+
+
+optreserr_t option_resolution_listranges(const char *specification, int option_char,
+ struct OptionRange *range, size_t range_count)
+{
+ assert(range_count > 0);
+
+ /* clear out range */
+ memset(range, -1, sizeof(*range) * range_count);
+ range_count--;
+
+ specification = strchr(specification, option_char);
+ if (!specification)
+ {
+ syntaxerror(NULL);
+ return OPTIONRESOLUTION_ERROR_SYNTAX;
+ }
+
+ return resolve_single_param(specification + 1, NULL, range, range_count);
+}
+
+
+
+optreserr_t option_resolution_getdefault(const char *specification, int option_char, int *val)
+{
+ assert(val);
+
+ /* clear out default */
+ *val = -1;
+
+ specification = strchr(specification, option_char);
+ if (!specification)
+ {
+ syntaxerror(NULL);
+ return OPTIONRESOLUTION_ERROR_SYNTAX;
+ }
+
+ return resolve_single_param(specification + 1, val, NULL, 0);
+}
+
+
+
+optreserr_t option_resolution_isvalidvalue(const char *specification, int option_char, int val)
+{
+ optreserr_t err;
+ struct OptionRange ranges[256];
+ int i;
+
+ err = option_resolution_listranges(specification, option_char, ranges, ARRAY_LENGTH(ranges));
+ if (err)
+ return err;
+
+ for (i = 0; (ranges[i].min >= 0) && (ranges[i].max >= 0); i++)
+ {
+ if ((ranges[i].min <= val) && (ranges[i].max >= val))
+ return OPTIONRESOLUTION_ERROR_SUCCESS;
+ }
+ return OPTIONRESOLUTION_ERROR_PARAMOUTOFRANGE;
+}
+
+
+
+int option_resolution_contains(const char *specification, int option_char)
+{
+ return strchr(specification, option_char) != NULL;
+}
+
+
+
+const char *option_resolution_error_string(optreserr_t err)
+{
+ static const char *const errors[] =
+ {
+ "The operation completed successfully", /* OPTIONRESOLUTION_ERROR_SUCCESS */
+ "Out of memory", /* OPTIONRESOLUTION_ERROR_OUTOFMEMORY */
+ "Parameter out of range", /* OPTIONRESOLUTION_ERROR_PARAMOUTOFRANGE */
+ "Parameter not specified", /* OPTIONRESOLUTION_ERROR_PARAMNOTSPECIFIED */
+ "Unknown parameter", /* OPTIONRESOLUTION_ERROR_PARAMNOTFOUND */
+ "Paramter specified multiple times", /* OPTIONRESOLUTION_ERROR_PARAMALREADYSPECIFIED */
+ "Invalid parameter", /* OPTIONRESOLUTION_ERROR_BADPARAM */
+ "Syntax error", /* OPTIONRESOLUTION_ERROR_SYNTAX */
+ "Internal error" /* OPTIONRESOLTUION_ERROR_INTERNAL */
+ };
+
+ if ((err < 0) || (err >= ARRAY_LENGTH(errors)))
+ return NULL;
+ return errors[err];
+}
+
diff --git a/src/emu/opresolv.h b/src/emu/opresolv.h
new file mode 100644
index 00000000000..7048e8b1538
--- /dev/null
+++ b/src/emu/opresolv.h
@@ -0,0 +1,160 @@
+/****************************************************************************
+
+ opresolv.h
+
+ Extensible ranged option resolution handling
+
+ An extensible mechanism for handling options is a major need in MESS and
+ Imgtool. Unfortunately, since we are using straight C for everything, it
+ can be hard and awkward to create non-arcane mechanisms for representing
+ these options.
+
+ In this system, we have the following concepts:
+ 1. An "option specification"; a string that represents what options are
+ available, their defaults, and their allowed ranges. Here is an
+ example:
+
+ Examples:
+ "H[1]-2;T[35]/40/80;S[18]"
+ Allow 1-2 heads; 35, 40 or 80 tracks, and 18 sectors,
+ defaulting to 1 heads and 35 tracks.
+
+ "N'Simon''s desk'"
+ Simon's desk (strings are not subject to range checking)
+
+ 2. An "option guide"; a struct that provides information about what the
+ various members of the option specification mean (i.e. - H=heads)
+
+ 3. An "option resolution"; an object that represents a set of interpreted
+ options. At this stage, the option bid has been processed and it is
+ guaranteed that all options reside in their expected ranges.
+
+ An option_resolution object is created based on an option guide and an
+ option specification. It is then possible to specify individual parameters
+ to the option_resolution object. Argument checks occur at this time. When
+ one is all done, you can then query the object for any given value.
+
+****************************************************************************/
+
+#ifndef __OPRESOLV_H__
+#define __OPRESOLV_H__
+
+#include <stdlib.h>
+
+
+/***************************************************************************
+
+ Type definitions
+
+***************************************************************************/
+
+enum option_type
+{
+ OPTIONTYPE_END,
+ OPTIONTYPE_INT,
+ OPTIONTYPE_STRING,
+ OPTIONTYPE_ENUM_BEGIN,
+ OPTIONTYPE_ENUM_VALUE
+};
+
+typedef struct _option_guide option_guide;
+struct _option_guide
+{
+ enum option_type option_type;
+ int parameter;
+ const char *identifier;
+ const char *display_name;
+};
+
+#define OPTION_GUIDE_START(option_guide_) \
+ const option_guide option_guide_[] = \
+ { \
+
+#define OPTION_GUIDE_END \
+ { OPTIONTYPE_END } \
+ }; \
+
+#define OPTION_GUIDE_EXTERN(option_guide_) \
+ extern const option_guide option_guide_[] \
+
+#define OPTION_INT(option_char, identifier, display_name) \
+ { OPTIONTYPE_INT, (option_char), (identifier), (display_name) }, \
+
+#define OPTION_STRING(option_char, identifier, display_name) \
+ { OPTIONTYPE_STRING, (option_char), (identifier), (display_name) }, \
+
+#define OPTION_ENUM_START(option_char, identifier, display_name) \
+ { OPTIONTYPE_ENUM_BEGIN, (option_char), (identifier), (display_name) }, \
+
+#define OPTION_ENUM(value, identifier, display_name) \
+ { OPTIONTYPE_ENUM_VALUE, (value), (identifier), (display_name) }, \
+
+#define OPTION_ENUM_END
+
+
+typedef enum
+{
+ OPTIONRESOLUTION_ERROR_SUCCESS,
+ OPTIONRESOLUTION_ERROR_OUTOFMEMORY,
+ OPTIONRESOLUTION_ERROR_PARAMOUTOFRANGE,
+ OPTIONRESOLUTION_ERROR_PARAMNOTSPECIFIED,
+ OPTIONRESOLUTION_ERROR_PARAMNOTFOUND,
+ OPTIONRESOLUTION_ERROR_PARAMALREADYSPECIFIED,
+ OPTIONRESOLUTION_ERROR_BADPARAM,
+ OPTIONRESOLUTION_ERROR_SYNTAX,
+ OPTIONRESOLTUION_ERROR_INTERNAL
+} optreserr_t;
+
+
+
+struct OptionResolutionError
+{
+ const option_guide *option;
+ optreserr_t error;
+};
+
+
+
+typedef struct _option_resolution option_resolution;
+
+struct OptionRange
+{
+ int min, max;
+};
+
+
+
+/***************************************************************************
+
+ Prototypes
+
+***************************************************************************/
+
+/* processing options with option_resolution objects */
+option_resolution *option_resolution_create(const option_guide *guide, const char *specification);
+optreserr_t option_resolution_add_param(option_resolution *resolution, const char *param, const char *value);
+optreserr_t option_resolution_finish(option_resolution *resolution);
+void option_resolution_close(option_resolution *resolution);
+int option_resolution_lookup_int(option_resolution *resolution, int option_char);
+const char *option_resolution_lookup_string(option_resolution *resolution, int option_char);
+
+/* option resolution accessors */
+const char *option_resolution_specification(option_resolution *resolution);
+const option_guide *option_resolution_find_option(option_resolution *resolution, int option_char);
+const option_guide *option_resolution_index_option(option_resolution *resolution, int indx);
+
+/* processing option guides */
+int option_resolution_countoptions(const option_guide *guide, const char *specification);
+
+/* processing option specifications */
+optreserr_t option_resolution_listranges(const char *specification, int option_char,
+ struct OptionRange *range, size_t range_count);
+optreserr_t option_resolution_getdefault(const char *specification, int option_char, int *val);
+optreserr_t option_resolution_isvalidvalue(const char *specification, int option_char, int val);
+int option_resolution_contains(const char *specification, int option_char);
+
+/* misc */
+const char *option_resolution_error_string(optreserr_t err);
+
+#endif /* __OPRESOLV_H__ */
+