Cleanups to ram_device (#2324)

Specifically:
  1.  Changed ram_device to expose specific options, removing the burden for clients to parse RAM strings
  2.  Moved validation of command line arguments out of device_validity_check(); that method is only intended for checking the device itself
  3.  Miscellaneous polishing
This commit is contained in:
npwoods 2017-05-24 09:58:33 -04:00 committed by Vas Crabb
parent f3d04843e3
commit a20c2428d6
3 changed files with 120 additions and 126 deletions

View File

@ -8,13 +8,14 @@
**************************************************************************/
#include <stdio.h>
#include <ctype.h>
#include "emu.h"
#include "ram.h"
#include "emuopts.h"
#include <stdio.h>
#include <ctype.h>
#include <algorithm>
/*****************************************************************************
LIVE DEVICE
@ -30,41 +31,62 @@ DEFINE_DEVICE_TYPE(RAM, ram_device, "ram", "RAM")
ram_device::ram_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, RAM, tag, owner, clock)
, m_size(0)
, m_default_size(0)
, m_default_value(0xCD)
, m_extra_options_string(nullptr)
{
m_size = 0;
m_default_size = nullptr;
m_extra_options = nullptr;
m_default_value = 0xCD;
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void ram_device::device_start()
{
/* the device named 'ram' can get ram options from command line */
// the device named 'ram' can get ram options from command line
m_size = 0;
if (strcmp(tag(), ":" RAM_TAG) == 0)
{
const char *ramsize_string = machine().options().ram_size();
if ((ramsize_string != nullptr) && (ramsize_string[0] != '\0'))
if (ramsize_string && *ramsize_string)
{
m_size = parse_string(ramsize_string);
if (!is_valid_size(m_size))
{
std::ostringstream output;
util::stream_format(output, "Cannot recognize the RAM option %s", ramsize_string);
util::stream_format(output, " (valid options are %s", m_default_size);
if (m_extra_options_string)
util::stream_format(output, ",%s).\n", m_extra_options_string);
else
util::stream_format(output, ").\n");
osd_printf_error("%s", output.str().c_str());
osd_printf_warning("Setting value to default %s\n", m_default_size);
m_size = 0;
}
}
}
/* if we didn't get a size yet, use the default */
// if we didn't get a size yet, use the default
if (m_size == 0)
m_size = default_size();
/* allocate space for the ram */
// allocate space for the ram
m_pointer.resize(m_size);
memset(&m_pointer[0], m_default_value, m_size);
/* register for state saving */
// register for state saving
save_item(NAME(m_size));
save_item(NAME(m_pointer));
}
//-------------------------------------------------
// device_validity_check - device-specific validity
// checks
@ -72,101 +94,33 @@ void ram_device::device_start()
void ram_device::device_validity_check(validity_checker &valid) const
{
const char *ramsize_string = nullptr;
int is_valid = false;
uint32_t specified_ram;
const char *gamename_option;
/* verify default ram value */
// verify default ram value
if (default_size() == 0)
osd_printf_error("Invalid default RAM option: %s\n", m_default_size);
/* command line options are only parsed for the device named RAM_TAG */
if (tag() != nullptr && strcmp(tag(), ":" RAM_TAG) == 0)
{
/* verify command line ram option */
ramsize_string = mconfig().options().ram_size();
gamename_option = mconfig().options().system_name();
// calculate any extra options
std::vector<uint32_t> extra_options;
std::string bad_option;
if (m_extra_options_string)
extra_options = calculate_extra_options(m_extra_options_string, &bad_option);
if ((ramsize_string != nullptr) && (ramsize_string[0] != '\0'))
{
specified_ram = parse_string(ramsize_string);
if (specified_ram == 0)
osd_printf_error("Cannot recognize the RAM option %s\n", ramsize_string);
if (gamename_option != nullptr && *gamename_option != 0 && strcmp(gamename_option, mconfig().gamedrv().name) == 0)
{
/* compare command line option to default value */
if (default_size() == specified_ram)
is_valid = true;
/* verify extra ram options */
if (m_extra_options != nullptr)
{
int j;
int size = strlen(m_extra_options);
char * const s = core_strdup(m_extra_options);
char * const e = s + size;
char *p = s;
for (j=0;j<size;j++) {
if (p[j]==',') p[j]=0;
}
/* try to parse each option */
while(p <= e)
{
uint32_t option_ram_size = parse_string(p);
if (option_ram_size == 0)
osd_printf_error("Invalid RAM option: %s\n", p);
if (option_ram_size == specified_ram)
is_valid = true;
p += strlen(p);
if (p == e)
break;
p += 1;
}
free(s);
}
} else {
/* if not for this driver then return ok */
is_valid = true;
}
}
else
{
/* not specifying the ramsize on the command line is valid as well */
is_valid = true;
}
}
else
is_valid = true;
if (!is_valid)
{
std::ostringstream output;
util::stream_format(output, "Cannot recognize the RAM option %s", ramsize_string);
util::stream_format(output, " (valid options are %s", m_default_size);
if (m_extra_options != nullptr)
util::stream_format(output, ",%s).\n", m_extra_options);
else
util::stream_format(output, ").\n");
osd_printf_error("%s", output.str().c_str());
osd_printf_warning("Setting value to default %s\n",m_default_size);
std::string error;
mconfig().options().set_value(OPTION_RAMSIZE, m_default_size, OPTION_PRIORITY_CMDLINE, error);
assert(error.empty());
}
// report any errors
if (!bad_option.empty())
osd_printf_error("Invalid RAM option: %s\n", bad_option.c_str());
}
//-------------------------------------------------
// is_valid_size
//-------------------------------------------------
bool ram_device::is_valid_size(uint32_t size) const
{
return size == default_size()
|| std::find(extra_options().begin(), extra_options().end(), size) != extra_options().end();
}
//-------------------------------------------------
// parse_string - convert a ram string to an
// integer value
@ -204,6 +158,7 @@ uint32_t ram_device::parse_string(const char *s)
return ram;
}
//-------------------------------------------------
// default_size
//-------------------------------------------------
@ -212,3 +167,45 @@ uint32_t ram_device::default_size(void) const
{
return parse_string(m_default_size);
}
//-------------------------------------------------
// extra_options
//-------------------------------------------------
const std::vector<uint32_t> &ram_device::extra_options(void) const
{
if (m_extra_options_string && m_extra_options.empty())
m_extra_options = calculate_extra_options(m_extra_options_string, nullptr);
return m_extra_options;
}
//-------------------------------------------------
// calculate_extra_options
//-------------------------------------------------
std::vector<uint32_t> ram_device::calculate_extra_options(const char *extra_options_string, std::string *bad_option)
{
std::vector<uint32_t> result;
std::string options(extra_options_string);
bool done = false;
for (std::string::size_type start = 0, end = options.find_first_of(','); !done; start = end + 1, end = options.find_first_of(',', start))
{
// parse the option
const std::string ram_option_string = options.substr(start, (end == -1) ? -1 : end - start);
const uint32_t ram_option = parse_string(ram_option_string.c_str());
if (ram_option == 0)
{
if (bad_option)
*bad_option = std::move(ram_option_string);
return result;
}
// and add it to the results
result.push_back(ram_option);
done = end == std::string::npos;
}
return result;
}

View File

@ -56,12 +56,11 @@ public:
ram_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// accessors
uint32_t size(void) const { return m_size; }
uint32_t mask(void) const { return m_size - 1; }
uint8_t *pointer(void) { return &m_pointer[0]; }
static uint32_t parse_string(const char *s);
uint32_t default_size(void) const;
const char *extra_options(void) const { return m_extra_options; }
uint32_t size() const { return m_size; }
uint32_t mask() const { return m_size - 1; }
uint8_t *pointer() { return &m_pointer[0]; }
uint32_t default_size() const;
const std::vector<uint32_t> &extra_options() const;
// read/write
uint8_t read(offs_t offset) { return m_pointer[offset % m_size]; }
@ -69,22 +68,27 @@ public:
// inline configuration helpers
static void static_set_default_size(device_t &device, const char *default_size) { downcast<ram_device &>(device).m_default_size = default_size; }
static void static_set_extra_options(device_t &device, const char *extra_options) { downcast<ram_device &>(device).m_extra_options = extra_options; }
static void static_set_extra_options(device_t &device, const char *extra_options) { downcast<ram_device &>(device).m_extra_options_string = extra_options && extra_options[0] ? extra_options : nullptr; downcast<ram_device &>(device).m_extra_options.clear(); }
static void static_set_default_value(device_t &device, uint8_t default_value) { downcast<ram_device &>(device).m_default_value = default_value; }
protected:
virtual void device_start(void) override;
virtual void device_start() override;
virtual void device_validity_check(validity_checker &valid) const override;
private:
static std::vector<uint32_t> calculate_extra_options(const char *extra_options_string, std::string *bad_option);
static uint32_t parse_string(const char *s);
bool is_valid_size(uint32_t size) const;
// device state
uint32_t m_size;
std::vector<uint8_t> m_pointer;
uint32_t m_size;
std::vector<uint8_t> m_pointer;
// device config
const char *m_default_size;
const char *m_extra_options;
uint8_t m_default_value;
const char * m_default_size;
uint8_t m_default_value;
mutable std::vector<uint32_t> m_extra_options;
const char * m_extra_options_string;
};

View File

@ -1686,19 +1686,12 @@ void info_xml_creator::output_ramoptions(device_t &root)
{
for (const ram_device &ram : ram_device_iterator(root))
{
fprintf(m_output, "\t\t<ramoption default=\"1\">%u</ramoption>\n", ram.default_size());
if (ram.extra_options() != nullptr)
for (uint32_t option : ram.extra_options())
{
std::string options(ram.extra_options());
for (int start = 0, end = options.find_first_of(',');; start = end + 1, end = options.find_first_of(',', start))
{
std::string option;
option.assign(options.substr(start, (end == -1) ? -1 : end - start));
fprintf(m_output, "\t\t<ramoption>%u</ramoption>\n", ram_device::parse_string(option.c_str()));
if (end == -1)
break;
}
if (option == ram.default_size())
fprintf(m_output, "\t\t<ramoption default=\"1\">%u</ramoption>\n", option);
else
fprintf(m_output, "\t\t<ramoption>%u</ramoption>\n", option);
}
}
}