Overhaul to how MAME handles options, take two (#2341)

This commit is contained in:
npwoods 2017-06-24 22:48:56 -04:00 committed by Vas Crabb
parent 1b28df0b39
commit b193e05cd7
34 changed files with 2203 additions and 1692 deletions

View File

@ -1217,7 +1217,7 @@ void device_image_interface::reset_and_load(const std::string &path)
device().machine().schedule_hard_reset(); device().machine().schedule_hard_reset();
// and record the new load // and record the new load
device().machine().options().image_options()[instance_name()] = path; device().machine().options().image_option(instance_name()).specify(path);
} }
@ -1301,9 +1301,10 @@ void device_image_interface::update_names()
if (brief_name == nullptr) if (brief_name == nullptr)
brief_name = device_brieftypename(image_type()); brief_name = device_brieftypename(image_type());
m_canonical_instance_name = string_format("%s%d", inst_name, index + 1);
if (count > 1) if (count > 1)
{ {
m_instance_name = string_format("%s%d", inst_name, index + 1); m_instance_name = m_canonical_instance_name;
m_brief_instance_name = string_format("%s%d", brief_name, index + 1); m_brief_instance_name = string_format("%s%d", brief_name, index + 1);
} }
else else
@ -1454,11 +1455,11 @@ std::string device_image_interface::software_get_default_slot(const char *defaul
{ {
std::string result; std::string result;
auto iter = device().mconfig().options().image_options().find(instance_name()); const std::string &image_name(device().mconfig().options().image_option(instance_name()).value());
if (iter != device().mconfig().options().image_options().end() && !iter->second.empty()) if (!image_name.empty())
{ {
result.assign(default_card_slot); result.assign(default_card_slot);
const software_part *swpart = find_software_item(iter->second, true); const software_part *swpart = find_software_item(image_name, true);
if (swpart != nullptr) if (swpart != nullptr)
{ {
const char *slot = swpart->feature("slot"); const char *slot = swpart->feature("slot");

View File

@ -213,6 +213,7 @@ public:
const std::string &instance_name() const { return m_instance_name; } const std::string &instance_name() const { return m_instance_name; }
const std::string &brief_instance_name() const { return m_brief_instance_name; } const std::string &brief_instance_name() const { return m_brief_instance_name; }
const std::string &cannonical_instance_name() const { return m_canonical_instance_name; }
bool uses_file_extension(const char *file_extension) const; bool uses_file_extension(const char *file_extension) const;
const formatlist_type &formatlist() const { return m_formatlist; } const formatlist_type &formatlist() const { return m_formatlist; }
@ -329,8 +330,9 @@ private:
util::hash_collection m_hash; util::hash_collection m_hash;
std::string m_brief_instance_name; std::string m_instance_name; // e.g. - "cartridge", "floppydisk2"
std::string m_instance_name; std::string m_brief_instance_name; // e.g. - "cart", "flop2"
std::string m_canonical_instance_name; // e.g. - "cartridge1", "floppydisk2" - only used internally in emuopts.cpp
// in the case of arcade cabinet with fixed carts inserted, // in the case of arcade cabinet with fixed carts inserted,
// we want to disable command line cart loading... // we want to disable command line cart loading...

File diff suppressed because it is too large Load Diff

View File

@ -195,56 +195,78 @@
// TYPE DEFINITIONS // TYPE DEFINITIONS
//************************************************************************** //**************************************************************************
class game_driver;
class device_slot_interface;
class emu_options;
class slot_option class slot_option
{ {
public: public:
slot_option(const char *default_value = nullptr); slot_option(emu_options &host, const char *default_value);
slot_option(const slot_option &that) = default; slot_option(const slot_option &that) = delete;
slot_option(slot_option &&that) = default; slot_option(slot_option &&that) = default;
const slot_option &operator=(const slot_option &that)
{
m_specified = that.m_specified;
m_specified_value = that.m_specified_value;
m_specified_bios = that.m_specified_bios;
m_default_card_software = that.m_default_card_software;
m_default_value = that.m_default_value;
return *this;
}
const slot_option &operator=(slot_option &&that)
{
m_specified = that.m_specified;
m_specified_value = std::move(that.m_specified_value);
m_specified_bios = std::move(that.m_specified_bios);
m_default_card_software = std::move(that.m_default_card_software);
m_default_value = std::move(that.m_default_value);
return *this;
}
// accessors // accessors
const std::string &value() const; const std::string &value() const;
std::string specified_value() const; std::string specified_value() const;
const std::string &bios() const { return m_specified_bios; } const std::string &bios() const { return m_specified_bios; }
const std::string &default_card_software() const { return m_default_card_software; } const std::string &default_card_software() const { return m_default_card_software; }
bool specified() const { return m_specified; } bool specified() const { return m_specified; }
core_options::entry::shared_ptr option_entry() const { return m_entry.lock(); }
// seters // seters
void specify(std::string &&text); void specify(const std::string &text, bool peg_priority = true);
void specify(std::string &&text, bool peg_priority = true);
void set_bios(std::string &&text); void set_bios(std::string &&text);
void set_default_card_software(std::string &&s) { m_default_card_software = std::move(s); } void set_default_card_software(std::string &&s);
// instantiates an option entry (don't call outside of emuopts.cpp)
core_options::entry::shared_ptr setup_option_entry(const char *name);
private: private:
void possibly_changed(const std::string &old_value);
emu_options & m_host;
bool m_specified; bool m_specified;
std::string m_specified_value; std::string m_specified_value;
std::string m_specified_bios; std::string m_specified_bios;
std::string m_default_card_software; std::string m_default_card_software;
std::string m_default_value; std::string m_default_value;
core_options::entry::weak_ptr m_entry;
};
class image_option
{
public:
image_option(emu_options &host, const std::string &canonical_instance_name);
image_option(const image_option &that) = delete;
image_option(image_option &&that) = default;
// accessors
const std::string &canonical_instance_name() const { return m_canonical_instance_name; }
const std::string &value() const { return m_value; }
core_options::entry::shared_ptr option_entry() const { return m_entry.lock(); }
// mutators
void specify(const std::string &value, bool peg_priority = true);
void specify(std::string &&value, bool peg_priority = true);
// instantiates an option entry (don't call outside of emuopts.cpp)
core_options::entry::shared_ptr setup_option_entry(std::vector<std::string> &&names);
private:
emu_options & m_host;
std::string m_canonical_instance_name;
std::string m_value;
core_options::entry::weak_ptr m_entry;
}; };
class emu_options : public core_options class emu_options : public core_options
{ {
friend class slot_option;
friend class image_option;
public: public:
enum ui_option enum ui_option
{ {
@ -252,12 +274,27 @@ public:
UI_SIMPLE UI_SIMPLE
}; };
enum class option_support
{
FULL, // full option support
GENERAL_AND_SYSTEM, // support for general options and system (no softlist)
GENERAL_ONLY // only support for general options
};
// construction/destruction // construction/destruction
emu_options(); emu_options(option_support support = option_support::FULL);
~emu_options();
// mutation
void set_system_name(const std::string &new_system_name);
void set_system_name(std::string &&new_system_name);
void set_software(std::string &&new_software);
// core options // core options
const char *system_name() const { return value(OPTION_SYSTEMNAME); } const game_driver *system() const { return m_system; }
const char *software_name() const { return value(OPTION_SOFTWARENAME); } const char *system_name() const;
const std::string &attempted_system_name() const { return m_attempted_system_name; }
const std::string &software_name() const { return m_software_name; }
// core configuration options // core configuration options
bool read_config() const { return bool_value(OPTION_READCONFIG); } bool read_config() const { return bool_value(OPTION_READCONFIG); }
@ -427,29 +464,50 @@ public:
const char *language() const { return value(OPTION_LANGUAGE); } const char *language() const { return value(OPTION_LANGUAGE); }
// Web server specific optopns // Web server specific options
bool http() const { return bool_value(OPTION_HTTP); } bool http() const { return bool_value(OPTION_HTTP); }
short http_port() const { return int_value(OPTION_HTTP_PORT); } short http_port() const { return int_value(OPTION_HTTP_PORT); }
const char *http_root() const { return value(OPTION_HTTP_ROOT); } const char *http_root() const { return value(OPTION_HTTP_ROOT); }
// slots and devices - the values for these are stored outside of the core_options // slots and devices - the values for these are stored outside of the core_options
// structure // structure
std::map<std::string, slot_option> &slot_options() { return m_slot_options; } const ::slot_option &slot_option(const std::string &device_name) const;
const std::map<std::string, slot_option> &slot_options() const { return m_slot_options; } ::slot_option &slot_option(const std::string &device_name);
std::map<std::string, std::string> &image_options() { return m_image_options; } const ::slot_option *find_slot_option(const std::string &device_name) const;
const std::map<std::string, std::string> &image_options() const { return m_image_options; } ::slot_option *find_slot_option(const std::string &device_name);
bool has_slot_option(const std::string &device_name) const { return find_slot_option(device_name) ? true : false; }
const ::image_option &image_option(const std::string &device_name) const;
::image_option &image_option(const std::string &device_name);
protected: protected:
virtual void value_changed(const std::string &name, const std::string &value) override; virtual void command_argument_processed() override;
virtual override_get_value_result override_get_value(const char *name, std::string &value) const override;
virtual bool override_set_value(const char *name, const std::string &value) override;
private: private:
struct software_options
{
std::unordered_map<std::string, std::string> slot;
std::unordered_map<std::string, std::string> image;
};
// slot/image/softlist calculus
software_options evaluate_initial_softlist_options(const std::string &software_identifier);
void update_slot_and_image_options();
bool add_and_remove_slot_options();
bool add_and_remove_image_options();
void reevaluate_default_card_software();
std::string get_default_card_software(device_slot_interface &slot);
// static list of options entries
static const options_entry s_option_entries[]; static const options_entry s_option_entries[];
// the basics
option_support m_support;
const game_driver * m_system;
// slots and devices // slots and devices
std::map<std::string, slot_option> m_slot_options; std::unordered_map<std::string, ::slot_option> m_slot_options;
std::map<std::string, std::string> m_image_options; std::unordered_map<std::string, ::image_option> m_image_options_cannonical;
std::unordered_map<std::string, ::image_option *> m_image_options;
// cached options, for scenarios where parsing core_options is too slow // cached options, for scenarios where parsing core_options is too slow
int m_coin_impulse; int m_coin_impulse;
@ -457,6 +515,12 @@ private:
bool m_sleep; bool m_sleep;
bool m_refresh_speed; bool m_refresh_speed;
ui_option m_ui; ui_option m_ui;
// special option; the system name we tried to specify
std::string m_attempted_system_name;
// special option; the software set name that we did specify
std::string m_software_name;
}; };
#endif // MAME_EMU_EMUOPTS_H #endif // MAME_EMU_EMUOPTS_H

View File

@ -38,37 +38,12 @@ image_manager::image_manager(running_machine &machine)
continue; continue;
// find the image option in image_options() // find the image option in image_options()
auto iter = machine.options().image_options().find(image.instance_name()); const std::string &startup_image(machine.options().image_option(image.instance_name()).value());
// GROSS HACK - if we began our journey with a single device configuration (e.g. - a single
// cartridge system) but later added a device of that type, image.instance_name() will become
// something different. We're going to try to accomodate that specific scenario here
//
// Specific example: 'mame snes -cart1 sufami -cart2 poipoi' - the instance_name() starts out
// as "cartridge" but at the end becomes "cartridge1"
if (iter == machine.options().image_options().end()
&& (image.instance_name().rbegin() != image.instance_name().rend())
&& (*image.instance_name().rbegin() == '1'))
{
std::string alternate_instance_name = image.instance_name().substr(0, image.instance_name().size() - 1);
iter = machine.options().image_options().find(alternate_instance_name);
// If we found something, we need to write it back (so later checks work). We also need to redo
// the find; the act of erasing the old value breaks the iterator
if (iter != machine.options().image_options().end())
{
std::string temp = std::move(iter->second);
machine.options().image_options()[image.instance_name()] = std::move(temp);
machine.options().image_options().erase(alternate_instance_name);
iter = machine.options().image_options().find(image.instance_name());
}
}
// is an image specified for this image? // is an image specified for this image?
if (iter != machine.options().image_options().end() && !iter->second.empty()) if (!startup_image.empty())
{ {
// we do have a startup image specified - load it // we do have a startup image specified - load it
const std::string &startup_image(iter->second);
image_init_result result = image_init_result::FAIL; image_init_result result = image_init_result::FAIL;
// try as a softlist // try as a softlist
@ -93,7 +68,7 @@ image_manager::image_manager(running_machine &machine)
image.unload(); image.unload();
// make sure it is removed from the ini file too // make sure it is removed from the ini file too
machine.options().image_options()[image.instance_name()] = ""; machine.options().image_option(image.instance_name()).specify("");
if (machine.options().write_config()) if (machine.options().write_config())
write_config(machine.options(), nullptr, &machine.system()); write_config(machine.options(), nullptr, &machine.system());
@ -208,9 +183,15 @@ void image_manager::options_extract()
{ {
for (device_image_interface &image : image_interface_iterator(machine().root_device())) for (device_image_interface &image : image_interface_iterator(machine().root_device()))
{ {
// only perform this activity for devices where is_reset_on_load() is false; for devices // There are two scenarios where we want to extract the option:
// where this is true, manipulation of this value is done in reset_and_load() //
if (!image.is_reset_on_load()) // 1. When for the device, is_reset_on_load() is false (mounting devices for which is reset_and_load()
// is true forces a reset, hence the name)
//
// 2. When is_reset_on_load(), and this results in a device being unmounted (unmounting is_reset_and_load()
// doesn't force an unmount)
if (!image.is_reset_on_load()
|| (!image.exists() && !machine().options().image_option(image.instance_name()).value().empty()))
{ {
// we have to assemble the image option differently for software lists and for normal images // we have to assemble the image option differently for software lists and for normal images
std::string image_opt; std::string image_opt;
@ -223,7 +204,7 @@ void image_manager::options_extract()
} }
// and set the option // and set the option
machine().options().image_options()[image.instance_name()] = std::move(image_opt); machine().options().image_option(image.instance_name()).specify(std::move(image_opt));
} }
} }

View File

@ -39,21 +39,20 @@ machine_config::machine_config(const game_driver &gamedrv, emu_options &options)
const char *slot_option_name = owner.tag() + 1; const char *slot_option_name = owner.tag() + 1;
// figure out which device goes into this slot // figure out which device goes into this slot
bool has_option = options.slot_options().count(slot_option_name); bool has_option = options.has_slot_option(slot_option_name);
const char *selval; const char *selval;
bool is_default; bool is_default;
if (!has_option) if (!has_option)
{ {
// Theoretically we should never get here; in the long run the expectation is that // The only time we should be getting here is when emuopts.cpp is invoking
// options.slot_options() should be fully qualified and all options should be // us to evaluate slot/image options, and the internal state of emuopts.cpp has
// present. However, we're getting late in the MAME 0.185 development cycle and // not caught up yet
// I don't want to rip this out (yet)
selval = slot.default_option(); selval = slot.default_option();
is_default = true; is_default = true;
} }
else else
{ {
const slot_option &opt = options.slot_options()[slot_option_name]; const slot_option &opt = options.slot_option(slot_option_name);
selval = opt.value().c_str(); selval = opt.value().c_str();
is_default = !opt.specified(); is_default = !opt.specified();
} }

View File

@ -365,9 +365,7 @@ void natural_keyboard::set_in_use(bool usage)
{ {
// update active usage // update active usage
m_in_use = usage; m_in_use = usage;
std::string error; machine().options().set_value(OPTION_NATURAL_KEYBOARD, usage, OPTION_PRIORITY_CMDLINE);
machine().options().set_value(OPTION_NATURAL_KEYBOARD, usage, OPTION_PRIORITY_CMDLINE, error);
assert(error.empty());
// lock out (or unlock) all keyboard inputs // lock out (or unlock) all keyboard inputs
for (auto &port : machine().ioport().ports()) for (auto &port : machine().ioport().ports())

View File

@ -1091,10 +1091,9 @@ int open_disk_image(emu_options &options, const game_driver *gamedrv, const rom_
// will only find CHDs for the default configuration. I believe that this in practice will // will only find CHDs for the default configuration. I believe that this in practice will
// be acceptable. // be acceptable.
emu_options driver_specific_options; emu_options driver_specific_options;
std::string error_string; driver_specific_options.set_system_name(current_driver.name);
driver_specific_options.set_value(OPTION_SYSTEMNAME, options.system_name(), OPTION_PRIORITY_DEFAULT, error_string); driver_specific_options.set_value(OPTION_MEDIAPATH, options.media_path(), OPTION_PRIORITY_DEFAULT);
driver_specific_options.set_value(OPTION_MEDIAPATH, options.media_path(), OPTION_PRIORITY_DEFAULT, error_string); driver_specific_options.set_value(OPTION_DIFF_DIRECTORY, options.diff_directory(), OPTION_PRIORITY_DEFAULT);
driver_specific_options.set_value(OPTION_DIFF_DIRECTORY, options.diff_directory(), OPTION_PRIORITY_DEFAULT, error_string);
// Now that we have an emu_options structure properly set up, we can create a machine_config // Now that we have an emu_options structure properly set up, we can create a machine_config
machine_config config(current_driver, driver_specific_options); machine_config config(current_driver, driver_specific_options);
@ -1496,12 +1495,13 @@ rom_load_manager::rom_load_manager(running_machine &machine)
specbios.assign(machine.options().bios()); specbios.assign(machine.options().bios());
else else
{ {
const char *slot_option_name = device.owner()->tag() + 1; const device_slot_interface *slot = dynamic_cast<const device_slot_interface *>(&device);
const slot_option *opt = machine.options().slot_options().count(slot_option_name) const slot_option *slot_opt = slot
? &machine.options().slot_options()[slot_option_name] ? &machine.options().slot_option(slot->slot_name())
: nullptr; : nullptr;
specbios = opt && !opt->bios().empty()
? opt->bios().c_str() specbios = slot_opt && !slot_opt->bios().empty()
? slot_opt->bios().c_str()
: device.default_bios_tag(); : device.default_bios_tag();
} }
determine_bios_rom(device, specbios.c_str()); determine_bios_rom(device, specbios.c_str());

View File

@ -190,26 +190,30 @@ cli_frontend::cli_frontend(emu_options &options, osd_interface &osd)
cli_frontend::~cli_frontend() cli_frontend::~cli_frontend()
{ {
// nuke any device options since they will leak memory
mame_options::remove_device_options(m_options);
} }
void cli_frontend::start_execution(mame_machine_manager *manager, std::vector<std::string> &args) void cli_frontend::start_execution(mame_machine_manager *manager, const std::vector<std::string> &args)
{ {
std::string option_errors; std::ostringstream option_errors;
// because softlist evaluation relies on hashpath being populated, we are going to go through
// a special step to force it to be evaluated
mame_options::populate_hashpath_from_args_and_inis(m_options, args);
// parse the command line, adding any system-specific options // parse the command line, adding any system-specific options
if (!mame_options::parse_command_line(m_options, args, option_errors)) try
{
m_options.parse_command_line(args, OPTION_PRIORITY_CMDLINE);
}
catch (options_exception &ex)
{ {
// if we failed, check for no command and a system name first; in that case error on the name // if we failed, check for no command and a system name first; in that case error on the name
if (m_options.command().empty() && mame_options::system(m_options) == nullptr && *(m_options.system_name()) != 0) if (m_options.command().empty() && mame_options::system(m_options) == nullptr && !m_options.attempted_system_name().empty())
throw emu_fatalerror(EMU_ERR_NO_SUCH_GAME, "Unknown system '%s'", m_options.system_name()); throw emu_fatalerror(EMU_ERR_NO_SUCH_GAME, "Unknown system '%s'", m_options.attempted_system_name().c_str());
// otherwise, error on the options // otherwise, error on the options
throw emu_fatalerror(EMU_ERR_INVALID_CONFIG, "%s", strtrimspace(option_errors).c_str()); throw emu_fatalerror(EMU_ERR_INVALID_CONFIG, "%s", ex.message().c_str());
} }
if (!option_errors.empty())
osd_printf_error("Error in command line:\n%s\n", strtrimspace(option_errors).c_str());
// determine the base name of the EXE // determine the base name of the EXE
std::string exename = core_filename_extract_base(args[0], true); std::string exename = core_filename_extract_base(args[0], true);
@ -232,8 +236,11 @@ void cli_frontend::start_execution(mame_machine_manager *manager, std::vector<st
manager->start_luaengine(); manager->start_luaengine();
if (!option_errors.empty()) if (option_errors.tellp() > 0)
osd_printf_error("Error in command line:\n%s\n", strtrimspace(option_errors).c_str()); {
std::string option_errors_string = option_errors.str();
osd_printf_error("Error in command line:\n%s\n", strtrimspace(option_errors_string).c_str());
}
// if we can't find it, give an appropriate error // if we can't find it, give an appropriate error
const game_driver *system = mame_options::system(m_options); const game_driver *system = mame_options::system(m_options);
@ -269,16 +276,19 @@ int cli_frontend::execute(std::vector<std::string> &args)
// if a game was specified, wasn't a wildcard, and our error indicates this was the // if a game was specified, wasn't a wildcard, and our error indicates this was the
// reason for failure, offer some suggestions // reason for failure, offer some suggestions
if (m_result == EMU_ERR_NO_SUCH_GAME && *(m_options.system_name()) != 0 && !core_iswildstr(m_options.system_name()) && mame_options::system(m_options) == nullptr) if (m_result == EMU_ERR_NO_SUCH_GAME
&& !m_options.attempted_system_name().empty()
&& !core_iswildstr(m_options.attempted_system_name().c_str())
&& mame_options::system(m_options) == nullptr)
{ {
// get the top 16 approximate matches // get the top 16 approximate matches
driver_enumerator drivlist(m_options); driver_enumerator drivlist(m_options);
int matches[16]; int matches[16];
drivlist.find_approximate_matches(m_options.system_name(), ARRAY_LENGTH(matches), matches); drivlist.find_approximate_matches(m_options.attempted_system_name().c_str(), ARRAY_LENGTH(matches), matches);
// print them out // print them out
osd_printf_error("\n\"%s\" approximately matches the following\n" osd_printf_error("\n\"%s\" approximately matches the following\n"
"supported machines (best match first):\n\n", m_options.system_name()); "supported machines (best match first):\n\n", m_options.attempted_system_name().c_str());
for (auto & matche : matches) for (auto & matche : matches)
if (matche != -1) if (matche != -1)
osd_printf_error("%-18s%s\n", drivlist.driver(matche).name, drivlist.driver(matche).type.fullname()); osd_printf_error("%-18s%s\n", drivlist.driver(matche).name, drivlist.driver(matche).type.fullname());
@ -1441,8 +1451,7 @@ void cli_frontend::romident(const std::vector<std::string> &args)
// create our own copy of options for the purposes of ROM identification // create our own copy of options for the purposes of ROM identification
// so we are not "polluted" with driver-specific slot/image options // so we are not "polluted" with driver-specific slot/image options
emu_options options; emu_options options;
std::string error_string; options.set_value(OPTION_MEDIAPATH, m_options.media_path(), OPTION_PRIORITY_DEFAULT);
options.set_value(OPTION_MEDIAPATH, m_options.media_path(), OPTION_PRIORITY_DEFAULT, error_string);
media_identifier ident(options); media_identifier ident(options);
@ -1470,24 +1479,24 @@ const cli_frontend::info_command_struct *cli_frontend::find_command(const std::s
{ {
static const info_command_struct s_info_commands[] = static const info_command_struct s_info_commands[] =
{ {
{ CLICOMMAND_LISTXML, 0, -1, false, &cli_frontend::listxml, "[pattern] ..." }, { CLICOMMAND_LISTXML, 0, -1, &cli_frontend::listxml, "[pattern] ..." },
{ CLICOMMAND_LISTFULL, 0, 1, false, &cli_frontend::listfull, "[system name]" }, { CLICOMMAND_LISTFULL, 0, 1, &cli_frontend::listfull, "[system name]" },
{ CLICOMMAND_LISTSOURCE, 0, 1, false, &cli_frontend::listsource, "[system name]" }, { CLICOMMAND_LISTSOURCE, 0, 1, &cli_frontend::listsource, "[system name]" },
{ CLICOMMAND_LISTCLONES, 0, 1, false, &cli_frontend::listclones, "[system name]" }, { CLICOMMAND_LISTCLONES, 0, 1, &cli_frontend::listclones, "[system name]" },
{ CLICOMMAND_LISTBROTHERS, 0, 1, false, &cli_frontend::listbrothers, "[system name]" }, { CLICOMMAND_LISTBROTHERS, 0, 1, &cli_frontend::listbrothers, "[system name]" },
{ CLICOMMAND_LISTCRC, 0, 1, false, &cli_frontend::listcrc, "[system name]" }, { CLICOMMAND_LISTCRC, 0, 1, &cli_frontend::listcrc, "[system name]" },
{ CLICOMMAND_LISTDEVICES, 0, 1, true, &cli_frontend::listdevices, "[system name]" }, { CLICOMMAND_LISTDEVICES, 0, 1, &cli_frontend::listdevices, "[system name]" },
{ CLICOMMAND_LISTSLOTS, 0, 1, true, &cli_frontend::listslots, "[system name]" }, { CLICOMMAND_LISTSLOTS, 0, 1, &cli_frontend::listslots, "[system name]" },
{ CLICOMMAND_LISTROMS, 0, -1, false, &cli_frontend::listroms, "[pattern] ..." }, { CLICOMMAND_LISTROMS, 0, -1, &cli_frontend::listroms, "[pattern] ..." },
{ CLICOMMAND_LISTSAMPLES, 0, 1, false, &cli_frontend::listsamples, "[system name]" }, { CLICOMMAND_LISTSAMPLES, 0, 1, &cli_frontend::listsamples, "[system name]" },
{ CLICOMMAND_VERIFYROMS, 0, -1, false, &cli_frontend::verifyroms, "[pattern] ..." }, { CLICOMMAND_VERIFYROMS, 0, -1, &cli_frontend::verifyroms, "[pattern] ..." },
{ CLICOMMAND_VERIFYSAMPLES, 0, 1, false, &cli_frontend::verifysamples, "[system name|*]" }, { CLICOMMAND_VERIFYSAMPLES, 0, 1, &cli_frontend::verifysamples, "[system name|*]" },
{ CLICOMMAND_LISTMEDIA, 0, 1, true, &cli_frontend::listmedia, "[system name]" }, { CLICOMMAND_LISTMEDIA, 0, 1, &cli_frontend::listmedia, "[system name]" },
{ CLICOMMAND_LISTSOFTWARE, 0, 1, false, &cli_frontend::listsoftware, "[system name]" }, { CLICOMMAND_LISTSOFTWARE, 0, 1, &cli_frontend::listsoftware, "[system name]" },
{ CLICOMMAND_VERIFYSOFTWARE, 0, 1, false, &cli_frontend::verifysoftware, "[system name|*]" }, { CLICOMMAND_VERIFYSOFTWARE, 0, 1, &cli_frontend::verifysoftware, "[system name|*]" },
{ CLICOMMAND_ROMIDENT, 1, 1, false, &cli_frontend::romident, "(file or directory path)" }, { CLICOMMAND_ROMIDENT, 1, 1, &cli_frontend::romident, "(file or directory path)" },
{ CLICOMMAND_GETSOFTLIST, 0, 1, false, &cli_frontend::getsoftlist, "[system name|*]" }, { CLICOMMAND_GETSOFTLIST, 0, 1, &cli_frontend::getsoftlist, "[system name|*]" },
{ CLICOMMAND_VERIFYSOFTLIST, 0, 1, false, &cli_frontend::verifysoftlist, "[system name|*]" } { CLICOMMAND_VERIFYSOFTLIST, 0, 1, &cli_frontend::verifysoftlist, "[system name|*]" }
}; };
for (const auto &info_command : s_info_commands) for (const auto &info_command : s_info_commands)
@ -1499,17 +1508,6 @@ const cli_frontend::info_command_struct *cli_frontend::find_command(const std::s
} }
//-------------------------------------------------
// parse_slot_options_for_auxverb
//-------------------------------------------------
bool cli_frontend::parse_slot_options_for_auxverb(const std::string &auxverb)
{
const info_command_struct *command = find_command(auxverb);
return command && command->specify_system;
}
//------------------------------------------------- //-------------------------------------------------
// execute_commands - execute various frontend // execute_commands - execute various frontend
// commands // commands
@ -1545,10 +1543,10 @@ void cli_frontend::execute_commands(const char *exename)
} }
// other commands need the INIs parsed // other commands need the INIs parsed
std::string option_errors; std::ostringstream option_errors;
mame_options::parse_standard_inis(m_options,option_errors); mame_options::parse_standard_inis(m_options,option_errors);
if (!option_errors.empty()) if (option_errors.tellp() > 0)
osd_printf_error("%s\n", option_errors.c_str()); osd_printf_error("%s\n", option_errors.str().c_str());
// createconfig? // createconfig?
if (m_options.command() == CLICOMMAND_CREATECONFIG) if (m_options.command() == CLICOMMAND_CREATECONFIG)

View File

@ -34,16 +34,12 @@ public:
// execute based on the incoming argc/argv // execute based on the incoming argc/argv
int execute(std::vector<std::string> &args); int execute(std::vector<std::string> &args);
// should we parse slot options for the auxillary verb in question?
static bool parse_slot_options_for_auxverb(const std::string &auxverb);
private: private:
struct info_command_struct struct info_command_struct
{ {
const char *option; const char *option;
int min_args; int min_args;
int max_args; int max_args;
bool specify_system;
void (cli_frontend::*function)(const std::vector<std::string> &args); void (cli_frontend::*function)(const std::vector<std::string> &args);
const char *usage; const char *usage;
}; };
@ -72,7 +68,7 @@ private:
void execute_commands(const char *exename); void execute_commands(const char *exename);
void display_help(const char *exename); void display_help(const char *exename);
void output_single_softlist(FILE *out, software_list_device &swlist); void output_single_softlist(FILE *out, software_list_device &swlist);
void start_execution(mame_machine_manager *manager, std::vector<std::string> &args); void start_execution(mame_machine_manager *manager, const std::vector<std::string> &args);
static const info_command_struct *find_command(const std::string &s); static const info_command_struct *find_command(const std::string &s);
// internal state // internal state

View File

@ -191,9 +191,7 @@ const char info_xml_creator::s_dtd_string[] =
info_xml_creator::info_xml_creator(emu_options const &options) info_xml_creator::info_xml_creator(emu_options const &options)
: m_output(nullptr) : m_output(nullptr)
, m_lookup_options(options)
{ {
mame_options::remove_device_options(m_lookup_options);
} }

View File

@ -1016,9 +1016,11 @@ void lua_engine::initialize()
"entries", sol::property([this](core_options &options) { "entries", sol::property([this](core_options &options) {
sol::table table = sol().create_table(); sol::table table = sol().create_table();
int unadorned_index = 0; int unadorned_index = 0;
for(core_options::entry &curentry : options) for (auto &curentry : options.entries())
{ {
const char *name = curentry.name(); const char *name = curentry->names().size() > 0
? curentry->name().c_str()
: nullptr;
bool is_unadorned = false; bool is_unadorned = false;
// check if it's unadorned // check if it's unadorned
if (name && strlen(name) && !strcmp(name, options.unadorned(unadorned_index))) if (name && strlen(name) && !strcmp(name, options.unadorned(unadorned_index)))
@ -1026,8 +1028,8 @@ void lua_engine::initialize()
unadorned_index++; unadorned_index++;
is_unadorned = true; is_unadorned = true;
} }
if (!curentry.is_header() && !curentry.is_command() && !curentry.is_internal() && !is_unadorned) if (curentry->type() != core_options::option_type::HEADER && curentry->type() != core_options::option_type::COMMAND && !is_unadorned)
table[name] = &curentry; table[name] = &*curentry;
} }
return table; return table;
})); }));
@ -1068,18 +1070,19 @@ void lua_engine::initialize()
e.set_value(val, OPTION_PRIORITY_CMDLINE); e.set_value(val, OPTION_PRIORITY_CMDLINE);
}, },
[this](core_options::entry &e) -> sol::object { [this](core_options::entry &e) -> sol::object {
if(!e.type()) if (e.type() == core_options::option_type::INVALID)
return sol::make_object(sol(), sol::nil); return sol::make_object(sol(), sol::nil);
switch(e.type()) switch(e.type())
{ {
case OPTION_BOOLEAN: case core_options::option_type::BOOLEAN:
return sol::make_object(sol(), atoi(e.value()) != 0); return sol::make_object(sol(), atoi(e.value()) != 0);
case OPTION_INTEGER: case core_options::option_type::INTEGER:
return sol::make_object(sol(), atoi(e.value())); return sol::make_object(sol(), atoi(e.value()));
case OPTION_FLOAT: case core_options::option_type::FLOAT:
return sol::make_object(sol(), atof(e.value())); return sol::make_object(sol(), atof(e.value()));
} default:
return sol::make_object(sol(), e.value()); return sol::make_object(sol(), e.value());
}
}), }),
"description", &core_options::entry::description, "description", &core_options::entry::description,
"default_value", &core_options::entry::default_value, "default_value", &core_options::entry::default_value,

View File

@ -124,36 +124,38 @@ void mame_machine_manager::start_luaengine()
std::vector<std::string> exclude = split(options().no_plugin(),','); std::vector<std::string> exclude = split(options().no_plugin(),',');
{ {
// parse the file // parse the file
std::string error;
// attempt to open the output file // attempt to open the output file
emu_file file(options().ini_path(), OPEN_FLAG_READ); emu_file file(options().ini_path(), OPEN_FLAG_READ);
if (file.open("plugin.ini") == osd_file::error::NONE) if (file.open("plugin.ini") == osd_file::error::NONE)
{ {
bool result = m_plugins->parse_ini_file((util::core_file&)file, OPTION_PRIORITY_MAME_INI, OPTION_PRIORITY_MAME_INI < OPTION_PRIORITY_DRIVER_INI, error); try
if (!result) {
m_plugins->parse_ini_file((util::core_file&)file, OPTION_PRIORITY_MAME_INI, OPTION_PRIORITY_MAME_INI < OPTION_PRIORITY_DRIVER_INI, false);
}
catch (options_exception &)
{
osd_printf_error("**Error loading plugin.ini**\n"); osd_printf_error("**Error loading plugin.ini**\n");
} }
} }
for (auto &curentry : *m_plugins) }
for (auto &curentry : m_plugins->entries())
{ {
if (!curentry.is_header()) if (curentry->type() != core_options::option_type::HEADER)
{ {
if (std::find(include.begin(), include.end(), curentry.name()) != include.end()) if (std::find(include.begin(), include.end(), curentry->name()) != include.end())
{ {
std::string error_string; m_plugins->set_value(curentry->name(), "1", OPTION_PRIORITY_CMDLINE);
m_plugins->set_value(curentry.name(), "1", OPTION_PRIORITY_CMDLINE, error_string);
} }
if (std::find(exclude.begin(), exclude.end(), curentry.name()) != exclude.end()) if (std::find(exclude.begin(), exclude.end(), curentry->name()) != exclude.end())
{ {
std::string error_string; m_plugins->set_value(curentry->name(), "0", OPTION_PRIORITY_CMDLINE);
m_plugins->set_value(curentry.name(), "0", OPTION_PRIORITY_CMDLINE, error_string);
} }
} }
} }
} }
if (options().console()) { if (options().console())
std::string error_string; {
m_plugins->set_value("console", "1", OPTION_PRIORITY_CMDLINE, error_string); m_plugins->set_value("console", "1", OPTION_PRIORITY_CMDLINE);
} }
m_lua->initialize(); m_lua->initialize();
@ -202,8 +204,7 @@ int mame_machine_manager::execute()
// parse any INI files as the first thing // parse any INI files as the first thing
if (m_options.read_config()) if (m_options.read_config())
{ {
m_options.revert(OPTION_PRIORITY_INI); std::ostringstream errors;
std::string errors;
mame_options::parse_standard_inis(m_options, errors); mame_options::parse_standard_inis(m_options, errors);
} }
@ -216,11 +217,6 @@ int mame_machine_manager::execute()
valid.check_shared_source(*system); valid.check_shared_source(*system);
} }
// reevaluate slot options until nothing changes
while (mame_options::reevaluate_slot_options(m_options))
{
}
// create the machine configuration // create the machine configuration
machine_config config(*system, m_options); machine_config config(*system, m_options);
@ -237,12 +233,13 @@ int mame_machine_manager::execute()
if (m_new_driver_pending) if (m_new_driver_pending)
{ {
// set up new system name and adjust device options accordingly // set up new system name and adjust device options accordingly
mame_options::set_system_name(m_options,m_new_driver_pending->name); m_options.set_system_name(m_new_driver_pending->name);
m_firstrun = true; m_firstrun = true;
} }
else else
{ {
if (machine.exit_pending()) mame_options::set_system_name(m_options,""); if (machine.exit_pending())
m_options.set_system_name("");
} }
if (machine.exit_pending() && (!started_empty || is_empty)) if (machine.exit_pending() && (!started_empty || is_empty))

View File

@ -22,511 +22,21 @@
#include <stack> #include <stack>
int mame_options::m_slot_options = 0;
int mame_options::m_device_options = 0;
//-------------------------------------------------
// add_slot_options - add all of the slot
// options for the configured system
//-------------------------------------------------
bool mame_options::add_slot_options(emu_options &options, value_specifier_func value_specifier)
{
// look up the system configured by name; if no match, do nothing
const game_driver *cursystem = system(options);
if (cursystem == nullptr)
return false;
// create the configuration
machine_config config(*cursystem, options);
// iterate through all slot devices
int starting_count = options.options_count();
for (const device_slot_interface &slot : slot_interface_iterator(config.root_device()))
{
// skip fixed slots
if (slot.fixed())
continue;
// retrieve info about the device instance
const char *name = slot.device().tag() + 1;
if (!options.exists(name))
{
// first device? add the header as to be pretty
if (m_slot_options++ == 0)
options.add_entry(nullptr, "SLOT DEVICES", OPTION_HEADER | OPTION_FLAG_DEVICE);
// add the option
options.add_entry(name, nullptr, OPTION_STRING | OPTION_FLAG_DEVICE, slot.default_option(), true);
options.slot_options()[name] = slot_option(slot.default_option());
// allow opportunity to specify this value
if (value_specifier)
{
std::string specified_value = value_specifier(name);
if (specified_value != value_specifier_invalid_value())
options.slot_options()[name].specify(std::move(specified_value));
}
}
}
return (options.options_count() != starting_count);
}
//-------------------------------------------------
// update_slot_options - update slot values
// depending of image mounted
//-------------------------------------------------
void mame_options::update_slot_options(emu_options &options, const software_part *swpart)
{
// look up the system configured by name; if no match, do nothing
const game_driver *cursystem = system(options);
if (cursystem == nullptr)
return;
machine_config config(*cursystem, options);
// iterate through all slot devices
for (device_slot_interface &slot : slot_interface_iterator(config.root_device()))
{
// retrieve info about the device instance
const char *name = slot.device().tag() + 1;
if (options.exists(name) && !slot.option_list().empty())
{
std::string defvalue = get_default_card_software(slot, options);
if (defvalue.empty())
{
// keep any non-default setting
if (options.priority(name) > OPTION_PRIORITY_DEFAULT)
continue;
// reinstate the actual default value as configured
if (slot.default_option() != nullptr)
defvalue.assign(slot.default_option());
}
// set the value and hide the option if not selectable
options.set_default_value(name, defvalue.c_str());
const device_slot_option *option = slot.option(defvalue.c_str());
options.set_flag(name, ~OPTION_FLAG_INTERNAL, (option != nullptr && !option->selectable()) ? OPTION_FLAG_INTERNAL : 0);
}
}
add_device_options(options);
}
//-------------------------------------------------
// get_default_card_software
//-------------------------------------------------
std::string mame_options::get_default_card_software(device_slot_interface &slot, const emu_options &options)
{
std::string image_path;
std::function<bool(util::core_file &, std::string&)> get_hashfile_extrainfo;
// figure out if an image option has been specified, and if so, get the image path out of the options
device_image_interface *image = dynamic_cast<device_image_interface *>(&slot);
if (image)
{
auto iter = options.image_options().find(image->instance_name());
if (iter != options.image_options().end())
image_path = iter->second;
get_hashfile_extrainfo = [image, &options](util::core_file &file, std::string &extrainfo)
{
util::hash_collection hashes = image->calculate_hash_on_file(file);
return hashfile_extrainfo(
options.hash_path(),
image->device().mconfig().gamedrv(),
hashes,
extrainfo);
};
}
// create the hook
get_default_card_software_hook hook(image_path, std::move(get_hashfile_extrainfo));
// and invoke the slot's implementation of get_default_card_software()
return slot.get_default_card_software(hook);
}
//-------------------------------------------------
// add_device_options - add all of the device
// options for the configured system
//-------------------------------------------------
void mame_options::add_device_options(emu_options &options, value_specifier_func value_specifier)
{
// look up the system configured by name; if no match, do nothing
const game_driver *cursystem = system(options);
if (cursystem == nullptr)
return;
machine_config config(*cursystem, options);
// iterate through all image devices
for (device_image_interface &image : image_interface_iterator(config.root_device()))
{
if (!image.user_loadable())
continue;
// add the option
if (!options.exists(image.instance_name().c_str()))
{
// first device? add the header as to be pretty
if (m_device_options++ == 0)
options.add_entry(nullptr, "IMAGE DEVICES", OPTION_HEADER | OPTION_FLAG_DEVICE);
// add the option
std::string option_name = get_full_option_name(image);
options.add_entry(option_name.c_str(), nullptr, OPTION_STRING | OPTION_FLAG_DEVICE, nullptr, true);
options.image_options()[image.instance_name()] = "";
// allow opportunity to specify this value
if (value_specifier)
{
std::string value = value_specifier(image.instance_name());
if (value != value_specifier_invalid_value())
options.image_options()[image.instance_name()] = std::move(value);
}
}
}
}
//-------------------------------------------------
// remove_device_options - remove device options
//-------------------------------------------------
std::string mame_options::get_full_option_name(const device_image_interface &image)
{
std::ostringstream option_name;
util::stream_format(option_name, "%s;%s", image.instance_name(), image.brief_instance_name());
if (strcmp(image.device_typename(image.image_type()), image.instance_name().c_str()) == 0)
util::stream_format(option_name, ";%s1;%s1", image.instance_name(), image.brief_instance_name());
return option_name.str();
}
//-------------------------------------------------
// remove_device_options - remove device options
//-------------------------------------------------
void mame_options::remove_device_options(emu_options &options)
{
// iterate through options and remove interesting ones
core_options::entry *nextentry;
for (auto *curentry = options.first(); curentry != nullptr; curentry = nextentry)
{
// pre-fetch the next entry in case we delete this one
nextentry = curentry->next();
// if this is a device option, nuke it
if ((curentry->flags() & OPTION_FLAG_DEVICE) != 0)
options.remove_entry(*curentry);
}
// take also care of ramsize options
options.set_default_value(OPTION_RAMSIZE, "");
// reset counters
m_slot_options = 0;
m_device_options = 0;
}
//-------------------------------------------------
// parse_slot_devices - parse the command line
// and update slot and image devices
//-------------------------------------------------
void mame_options::parse_slot_devices(emu_options &options, value_specifier_func value_specifier)
{
bool still_adding = true;
while (still_adding)
{
// keep adding slot options until we stop seeing new stuff
still_adding = false;
while (add_slot_options(options, value_specifier))
still_adding = true;
// add device options
add_device_options(options, value_specifier);
if (reevaluate_slot_options(options))
still_adding = true;
}
}
//-------------------------------------------------
// reevaluate_slot_options - based on recent changes
// in what images are mounted, give drivers a chance
// to specify new default slot options
//-------------------------------------------------
bool mame_options::reevaluate_slot_options(emu_options &options)
{
bool result = false;
// look up the system configured by name; if no match, do nothing
const game_driver *cursystem = system(options);
if (cursystem == nullptr)
return result;
machine_config config(*cursystem, options);
// iterate through all slot devices
for (device_slot_interface &slot : slot_interface_iterator(config.root_device()))
{
// retrieve info about the device instance
const char *name = slot.device().tag() + 1;
if (options.exists(name) && !slot.option_list().empty())
{
// device_slot_interface::get_default_card_software() is essentially a hook
// that lets devices provide a feedback loop to force a specified software
// list entry to be loaded
//
// In the repeated cycle of adding slots and slot devices, this gives a chance
// for devices to "plug in" default software list items. Of course, the fact
// that this is all shuffling options is brittle and roundabout, but such is
// the nature of software lists.
//
// In reality, having some sort of hook into the pipeline of slot/device evaluation
// makes sense, but the fact that it is joined at the hip to device_image_interface
// and device_slot_interface is unfortunate
std::string default_card_software = get_default_card_software(slot, options);
if (!default_card_software.empty())
{
// we have default card software - is this resulting in the slot option being mutated?
if (options.slot_options()[name].default_card_software() != default_card_software)
{
options.slot_options()[name].set_default_card_software(std::move(default_card_software));
result = true;
}
}
}
}
return result;
}
//-------------------------------------------------
// parse_command_line - parse the command line
// and update the devices
//-------------------------------------------------
bool mame_options::parse_command_line(emu_options &options, std::vector<std::string> &args, std::string &error_string)
{
// parse the command line
if (!options.parse_command_line(args, OPTION_PRIORITY_CMDLINE, error_string))
return false;
// in order to evaluate softlist options, we need to fish any hashpath variable out of INI files; this is
// because hashpath in particular can affect softlist evaluation
if (options.software_name()[0] != '\0' && options.read_config())
populate_hashpath_from_ini_files(options);
// identify any options as a result of softlists
auto softlist_opts = evaluate_initial_softlist_options(options);
// assemble a "value specifier" that will be used to specify options set up as a consequence
// of slot and device setup
auto value_specifier = [&options, &softlist_opts, &args, &error_string](const std::string &arg)
{
// first find within the command line
std::string arg_value;
bool success = options.pluck_from_command_line(args, arg, arg_value);
// next try to find within softlist-specified options
if (!success)
{
auto iter = softlist_opts.find(arg);
if (iter != softlist_opts.end())
{
arg_value = iter->second;
success = true;
}
}
// did we find something?
return success
? arg_value
: value_specifier_invalid_value();
};
// some auxillary verbs expect that slot options are specified; and to do this we need to figure
// out if this is necessary for this particular auxillary verb, and if so, set the system name
if (!options.command().empty()
&& cli_frontend::parse_slot_options_for_auxverb(options.command())
&& !options.command_arguments().empty()
&& !core_iswildstr(options.command_arguments()[0].c_str()))
{
std::string error_string;
options.set_value(OPTION_SYSTEMNAME, options.command_arguments()[0].c_str(), OPTION_PRIORITY_CMDLINE, error_string);
const game_driver *system = mame_options::system(options);
if (!system)
throw emu_fatalerror(EMU_ERR_NO_SUCH_GAME, "Unknown system '%s'", options.system_name());
}
// parse the slot devices
parse_slot_devices(options, value_specifier);
// at this point, we should have handled all arguments; the only argument that shouldn't have
// been handled is the file name
if (args.size() > 1)
{
error_string.append(string_format("Error: unknown option: %s\n", args[1]));
return false;
}
return true;
}
//-------------------------------------------------
// evaluate_initial_softlist_options
//-------------------------------------------------
std::map<std::string, std::string> mame_options::evaluate_initial_softlist_options(emu_options &options)
{
std::map<std::string, std::string> results;
// load software specified at the command line (if any of course)
std::string software_identifier = options.software_name();
if (!software_identifier.empty())
{
// we have software; first identify the proper game_driver
const game_driver *system = mame_options::system(options);
if (system == nullptr && *(options.system_name()) != 0)
throw emu_fatalerror(EMU_ERR_NO_SUCH_GAME, "Unknown system '%s'", options.system_name());
// and set up a configuration
machine_config config(*system, options);
software_list_device_iterator iter(config.root_device());
if (iter.count() == 0)
throw emu_fatalerror(EMU_ERR_FATALERROR, "Error: unknown option: %s\n", options.software_name());
// and finally set up the stack
std::stack<std::string> software_identifier_stack;
software_identifier_stack.push(software_identifier);
// we need to keep evaluating softlist identifiers until the stack is empty
while (!software_identifier_stack.empty())
{
// pop the identifier
software_identifier = std::move(software_identifier_stack.top());
software_identifier_stack.pop();
// and parse it
std::string list_name, software_name;
auto colon_pos = software_identifier.find_first_of(':');
if (colon_pos != std::string::npos)
{
list_name = software_identifier.substr(0, colon_pos);
software_name = software_identifier.substr(colon_pos + 1);
}
else
{
software_name = software_identifier;
}
// loop through all softlist devices, and try to find one capable of handling the requested software
bool found = false;
bool compatible = false;
for (software_list_device &swlistdev : iter)
{
if (list_name.empty() || (list_name == swlistdev.list_name()))
{
const software_info *swinfo = swlistdev.find(software_name);
if (swinfo != nullptr)
{
// loop through all parts
for (const software_part &swpart : swinfo->parts())
{
// only load compatible software this way
if (swlistdev.is_compatible(swpart) == SOFTWARE_IS_COMPATIBLE)
{
// we need to find a mountable image slot, but we need to ensure it is a slot
// for which we have not already distributed a part to
device_image_interface *image = software_list_device::find_mountable_image(
config,
swpart,
[&results](const device_image_interface &candidate) { return results.count(candidate.instance_name()) == 0; });
// did we find a slot to put this part into?
if (image != nullptr)
{
// we've resolved this software
results[image->instance_name()] = string_format("%s:%s:%s", swlistdev.list_name(), software_name, swpart.name());
// does this software part have a requirement on another part?
const char *requirement = swpart.feature("requirement");
if (requirement)
software_identifier_stack.push(requirement);
}
compatible = true;
}
found = true;
}
// identify other shared features specified as '<<slot name>>_default'
//
// example from SMS:
//
// <software name = "alexbmx">
// ...
// <sharedfeat name = "ctrl1_default" value = "paddle" />
// </software>
for (const feature_list_item &fi : swinfo->shared_info())
{
const std::string default_suffix = "_default";
if (fi.name().size() > default_suffix.size()
&& fi.name().compare(fi.name().size() - default_suffix.size(), default_suffix.size(), default_suffix) == 0)
{
std::string slot_name = fi.name().substr(0, fi.name().size() - default_suffix.size());
results[slot_name] = fi.value();
}
}
}
}
if (compatible)
break;
}
if (!compatible)
{
software_list_device::display_matches(config, nullptr, software_name);
if (!found)
throw emu_fatalerror(EMU_ERR_FATALERROR, nullptr);
else
throw emu_fatalerror(EMU_ERR_FATALERROR, "Software '%s' is incompatible with system '%s'\n", software_name.c_str(), options.system_name());
}
}
}
return results;
}
//------------------------------------------------- //-------------------------------------------------
// parse_standard_inis - parse the standard set // parse_standard_inis - parse the standard set
// of INI files // of INI files
//------------------------------------------------- //-------------------------------------------------
void mame_options::parse_standard_inis(emu_options &options, std::string &error_string, const game_driver *driver) void mame_options::parse_standard_inis(emu_options &options, std::ostream &error_stream, const game_driver *driver)
{ {
// start with an empty string
error_string.clear();
// parse the INI file defined by the platform (e.g., "mame.ini") // parse the INI file defined by the platform (e.g., "mame.ini")
// we do this twice so that the first file can change the INI path // we do this twice so that the first file can change the INI path
parse_one_ini(options, emulator_info::get_configname(), OPTION_PRIORITY_MAME_INI); parse_one_ini(options, emulator_info::get_configname(), OPTION_PRIORITY_MAME_INI);
parse_one_ini(options,emulator_info::get_configname(), OPTION_PRIORITY_MAME_INI, &error_string); parse_one_ini(options, emulator_info::get_configname(), OPTION_PRIORITY_MAME_INI, &error_stream);
// debug mode: parse "debug.ini" as well // debug mode: parse "debug.ini" as well
if (options.debug()) if (options.debug())
parse_one_ini(options,"debug", OPTION_PRIORITY_DEBUG_INI, &error_string); parse_one_ini(options, "debug", OPTION_PRIORITY_DEBUG_INI, &error_stream);
// if we have a valid system driver, parse system-specific INI files // if we have a valid system driver, parse system-specific INI files
const game_driver *cursystem = (driver == nullptr) ? system(options) : driver; const game_driver *cursystem = (driver == nullptr) ? system(options) : driver;
@ -535,18 +45,18 @@ void mame_options::parse_standard_inis(emu_options &options, std::string &error_
// parse "vertical.ini" or "horizont.ini" // parse "vertical.ini" or "horizont.ini"
if (cursystem->flags & ORIENTATION_SWAP_XY) if (cursystem->flags & ORIENTATION_SWAP_XY)
parse_one_ini(options,"vertical", OPTION_PRIORITY_ORIENTATION_INI, &error_string); parse_one_ini(options, "vertical", OPTION_PRIORITY_ORIENTATION_INI, &error_stream);
else else
parse_one_ini(options,"horizont", OPTION_PRIORITY_ORIENTATION_INI, &error_string); parse_one_ini(options, "horizont", OPTION_PRIORITY_ORIENTATION_INI, &error_stream);
if (cursystem->flags & MACHINE_TYPE_ARCADE) if (cursystem->flags & MACHINE_TYPE_ARCADE)
parse_one_ini(options,"arcade", OPTION_PRIORITY_SYSTYPE_INI, &error_string); parse_one_ini(options, "arcade", OPTION_PRIORITY_SYSTYPE_INI, &error_stream);
else if (cursystem->flags & MACHINE_TYPE_CONSOLE) else if (cursystem->flags & MACHINE_TYPE_CONSOLE)
parse_one_ini(options,"console", OPTION_PRIORITY_SYSTYPE_INI, &error_string); parse_one_ini(options ,"console", OPTION_PRIORITY_SYSTYPE_INI, &error_stream);
else if (cursystem->flags & MACHINE_TYPE_COMPUTER) else if (cursystem->flags & MACHINE_TYPE_COMPUTER)
parse_one_ini(options,"computer", OPTION_PRIORITY_SYSTYPE_INI, &error_string); parse_one_ini(options, "computer", OPTION_PRIORITY_SYSTYPE_INI, &error_stream);
else if (cursystem->flags & MACHINE_TYPE_OTHER) else if (cursystem->flags & MACHINE_TYPE_OTHER)
parse_one_ini(options,"othersys", OPTION_PRIORITY_SYSTYPE_INI, &error_string); parse_one_ini(options, "othersys", OPTION_PRIORITY_SYSTYPE_INI, &error_stream);
machine_config config(*cursystem, options); machine_config config(*cursystem, options);
for (const screen_device &device : screen_device_iterator(config.root_device())) for (const screen_device &device : screen_device_iterator(config.root_device()))
@ -554,35 +64,35 @@ void mame_options::parse_standard_inis(emu_options &options, std::string &error_
// parse "raster.ini" for raster games // parse "raster.ini" for raster games
if (device.screen_type() == SCREEN_TYPE_RASTER) if (device.screen_type() == SCREEN_TYPE_RASTER)
{ {
parse_one_ini(options,"raster", OPTION_PRIORITY_SCREEN_INI, &error_string); parse_one_ini(options, "raster", OPTION_PRIORITY_SCREEN_INI, &error_stream);
break; break;
} }
// parse "vector.ini" for vector games // parse "vector.ini" for vector games
if (device.screen_type() == SCREEN_TYPE_VECTOR) if (device.screen_type() == SCREEN_TYPE_VECTOR)
{ {
parse_one_ini(options,"vector", OPTION_PRIORITY_SCREEN_INI, &error_string); parse_one_ini(options, "vector", OPTION_PRIORITY_SCREEN_INI, &error_stream);
break; break;
} }
// parse "lcd.ini" for lcd games // parse "lcd.ini" for lcd games
if (device.screen_type() == SCREEN_TYPE_LCD) if (device.screen_type() == SCREEN_TYPE_LCD)
{ {
parse_one_ini(options,"lcd", OPTION_PRIORITY_SCREEN_INI, &error_string); parse_one_ini(options, "lcd", OPTION_PRIORITY_SCREEN_INI, &error_stream);
break; break;
} }
} }
// next parse "source/<sourcefile>.ini" // next parse "source/<sourcefile>.ini"
std::string sourcename = core_filename_extract_base(cursystem->type.source(), true).insert(0, "source" PATH_SEPARATOR); std::string sourcename = core_filename_extract_base(cursystem->type.source(), true).insert(0, "source" PATH_SEPARATOR);
parse_one_ini(options,sourcename.c_str(), OPTION_PRIORITY_SOURCE_INI, &error_string); parse_one_ini(options, sourcename.c_str(), OPTION_PRIORITY_SOURCE_INI, &error_stream);
// then parse the grandparent, parent, and system-specific INIs // then parse the grandparent, parent, and system-specific INIs
int parent = driver_list::clone(*cursystem); int parent = driver_list::clone(*cursystem);
int gparent = (parent != -1) ? driver_list::clone(parent) : -1; int gparent = (parent != -1) ? driver_list::clone(parent) : -1;
if (gparent != -1) if (gparent != -1)
parse_one_ini(options,driver_list::driver(gparent).name, OPTION_PRIORITY_GPARENT_INI, &error_string); parse_one_ini(options, driver_list::driver(gparent).name, OPTION_PRIORITY_GPARENT_INI, &error_stream);
if (parent != -1) if (parent != -1)
parse_one_ini(options,driver_list::driver(parent).name, OPTION_PRIORITY_PARENT_INI, &error_string); parse_one_ini(options, driver_list::driver(parent).name, OPTION_PRIORITY_PARENT_INI, &error_stream);
parse_one_ini(options,cursystem->name, OPTION_PRIORITY_DRIVER_INI, &error_string); parse_one_ini(options, cursystem->name, OPTION_PRIORITY_DRIVER_INI, &error_stream);
} }
@ -598,137 +108,90 @@ const game_driver *mame_options::system(const emu_options &options)
} }
//-------------------------------------------------
// set_system_name - set a new system name
//-------------------------------------------------
void mame_options::set_system_name(emu_options &options, const char *name)
{
// remember the original system name
std::string old_system_name(options.system_name());
bool new_system = old_system_name.compare(name) != 0;
// if the system name changed, fix up the device options
if (new_system)
{
// first set the new name
std::string error;
options.set_value(OPTION_SYSTEMNAME, name, OPTION_PRIORITY_CMDLINE, error);
assert(error.empty());
// remove any existing device options
remove_device_options(options);
}
else
{
// revert device options set for the old software
options.revert(OPTION_PRIORITY_SUBCMD, OPTION_PRIORITY_SUBCMD);
}
// get the new system
const game_driver *cursystem = system(options);
if (cursystem == nullptr)
return;
if (*options.software_name() != 0)
{
std::string sw_load(options.software_name());
std::string sw_list, sw_name, sw_part, sw_instance, error_string;
int left = sw_load.find_first_of(':');
int middle = sw_load.find_first_of(':', left + 1);
int right = sw_load.find_last_of(':');
sw_list = sw_load.substr(0, left);
sw_name = sw_load.substr(left + 1, middle - left - 1);
sw_part = sw_load.substr(middle + 1, right - middle - 1);
sw_instance = sw_load.substr(right + 1);
sw_load.assign(sw_load.substr(0, right));
// look up the software part
machine_config config(*cursystem, options);
software_list_device *swlist = software_list_device::find_by_name(config, sw_list.c_str());
const software_info *swinfo = swlist != nullptr ? swlist->find(sw_name.c_str()) : nullptr;
const software_part *swpart = swinfo != nullptr ? swinfo->find_part(sw_part.c_str()) : nullptr;
if (swpart == nullptr)
osd_printf_warning("Could not find %s in software list\n", options.software_name());
// then add the options
if (new_system)
{
while (add_slot_options(options)) {}
add_device_options(options);
}
options.set_value(OPTION_SOFTWARENAME, sw_name.c_str(), OPTION_PRIORITY_CMDLINE, error_string);
if (options.exists(sw_instance.c_str()))
options.set_value(sw_instance.c_str(), sw_load.c_str(), OPTION_PRIORITY_SUBCMD, error_string);
int num;
do {
num = options.options_count();
update_slot_options(options,swpart);
} while (num != options.options_count());
}
else if (new_system)
{
// add the options afresh
while (add_slot_options(options)) {}
add_device_options(options);
int num;
do {
num = options.options_count();
update_slot_options(options);
} while (num != options.options_count());
}
}
//------------------------------------------------- //-------------------------------------------------
// parse_one_ini - parse a single INI file // parse_one_ini - parse a single INI file
//------------------------------------------------- //-------------------------------------------------
bool mame_options::parse_one_ini(emu_options &options, const char *basename, int priority, std::string *error_string) void mame_options::parse_one_ini(emu_options &options, const char *basename, int priority, std::ostream *error_stream)
{ {
// don't parse if it has been disabled // don't parse if it has been disabled
if (!options.read_config()) if (!options.read_config())
return false; return;
// open the file; if we fail, that's ok // open the file; if we fail, that's ok
emu_file file(options.ini_path(), OPEN_FLAG_READ); emu_file file(options.ini_path(), OPEN_FLAG_READ);
osd_printf_verbose("Attempting load of %s.ini\n", basename); osd_printf_verbose("Attempting load of %s.ini\n", basename);
osd_file::error filerr = file.open(basename, ".ini"); osd_file::error filerr = file.open(basename, ".ini");
if (filerr != osd_file::error::NONE) if (filerr != osd_file::error::NONE)
return false; return;
// parse the file // parse the file
osd_printf_verbose("Parsing %s.ini\n", basename); osd_printf_verbose("Parsing %s.ini\n", basename);
std::string error; try
bool result = options.parse_ini_file((util::core_file&)file, priority, priority < OPTION_PRIORITY_DRIVER_INI, error); {
options.parse_ini_file((util::core_file&)file, priority, priority < OPTION_PRIORITY_DRIVER_INI, false);
}
catch (options_exception &ex)
{
if (error_stream)
util::stream_format(*error_stream, "While parsing %s:\n%s\n", ex.message(), file.fullpath(), ex.message());
return;
}
// append errors if requested
if (!error.empty() && error_string)
error_string->append(string_format("While parsing %s:\n%s\n", file.fullpath(), error));
return result;
} }
//------------------------------------------------- //-------------------------------------------------
// populate_hashpath_from_ini_files // populate_hashpath_from_args_and_inis
//------------------------------------------------- //-------------------------------------------------
void mame_options::populate_hashpath_from_ini_files(emu_options &options) void mame_options::populate_hashpath_from_args_and_inis(emu_options &options, const std::vector<std::string> &args)
{ {
// create temporary emu_options for the purposes of evaluating the INI files // The existence of this function comes from the fact that for softlist options to be properly
emu_options temp_options; // evaluated, we need to have the hashpath variable set. The problem is that the hashpath may
std::string temp_error_string; // be set anywhere on the command line, but also in any of the myriad INI files that we parse, some
temp_options.set_value(OPTION_SYSTEMNAME, options.system_name(), OPTION_PRIORITY_MAXIMUM, temp_error_string); // of which may be system specific (e.g. - nes.ini) or otherwise influenced by the system (e.g. - vector.ini)
temp_options.set_value(OPTION_INIPATH, options.ini_path(), OPTION_PRIORITY_MAXIMUM, temp_error_string); //
// I think that it is terrible that we have to do a completely independent pass on the command line and every
// argument simply because any one of these things might be setting - hashpath.Unless we invest the effort in
// building some sort of "late binding" apparatus for options(e.g. - delay evaluation of softlist options until
// we've scoured all INIs for hashpath) that can completely straddle the command line and the INI worlds, doing
// this is the best that we can do IMO.
// read the INIs into temp_options // parse the command line
parse_standard_inis(temp_options, temp_error_string); emu_options temp_options(emu_options::option_support::GENERAL_AND_SYSTEM);
try
{
temp_options.parse_command_line(args, OPTION_PRIORITY_CMDLINE, true);
}
catch (options_exception &)
{
// Something is very long; we have bigger problems than -hashpath possibly
// being in never-never land. Punt and let the main code fail
return;
}
// if we have an auxillary verb, hashpath is irrelevant
if (!temp_options.command().empty())
return;
// read INI files
if (temp_options.read_config())
{
std::ostringstream error_stream;
parse_standard_inis(temp_options, error_stream);
}
// and fish out hashpath // and fish out hashpath
const auto entry = temp_options.get_entry(OPTION_HASHPATH); const auto entry = temp_options.get_entry(OPTION_HASHPATH);
if (entry) if (entry)
options.set_value(OPTION_HASHPATH, entry->value(), entry->priority(), temp_error_string); {
try
{
options.set_value(OPTION_HASHPATH, entry->value(), entry->priority());
}
catch (options_exception &)
{
}
}
} }

View File

@ -50,45 +50,15 @@ class software_part;
class mame_options class mame_options
{ {
static const uint32_t OPTION_FLAG_DEVICE = 0x80000000;
public: public:
typedef std::function<std::string (const std::string &)> value_specifier_func;
// parsing wrappers // parsing wrappers
static bool parse_command_line(emu_options &options, std::vector<std::string> &args, std::string &error_string); static void parse_standard_inis(emu_options &options, std::ostream &error_stream, const game_driver *driver = nullptr);
static void parse_standard_inis(emu_options &options, std::string &error_string, const game_driver *driver = nullptr);
// FIXME: Couriersud: This should be in image_device_exit
static void remove_device_options(emu_options &options);
static const game_driver *system(const emu_options &options); static const game_driver *system(const emu_options &options);
static void set_system_name(emu_options &options, const char *name); static void populate_hashpath_from_args_and_inis(emu_options &options, const std::vector<std::string> &args);
static bool add_slot_options(emu_options &options, value_specifier_func value_specifier = nullptr);
static bool reevaluate_slot_options(emu_options &options);
private: private:
// device-specific option handling
static void add_device_options(emu_options &options, value_specifier_func value_specifier = nullptr);
static void update_slot_options(emu_options &options, const software_part *swpart = nullptr);
static void parse_slot_devices(emu_options &options, value_specifier_func value_specifier);
static std::string get_full_option_name(const device_image_interface &image);
static std::string get_default_card_software(device_slot_interface &slot, const emu_options &options);
// INI parsing helper // INI parsing helper
static bool parse_one_ini(emu_options &options, const char *basename, int priority, std::string *error_string = nullptr); static void parse_one_ini(emu_options &options, const char *basename, int priority, std::ostream *error_stream = nullptr);
// softlist handling
static std::map<std::string, std::string> evaluate_initial_softlist_options(emu_options &options);
// special function to fish hashpath out of INI files - needed for softlist processing
static void populate_hashpath_from_ini_files(emu_options &options);
// represents an "invalid" value (an empty string is valid so we can't use that; what I
// really want to return is std::optional<std::string> but C++17 isn't here yet)
static std::string value_specifier_invalid_value() { return std::string("\x01\x02\x03"); }
static int m_slot_options;
static int m_device_options;
}; };
#endif // MAME_FRONTEND_MAMEOPTS_H #endif // MAME_FRONTEND_MAMEOPTS_H

View File

@ -75,7 +75,7 @@ void plugin_options::parse_json(std::string path)
if (type=="plugin") if (type=="plugin")
{ {
add_entry(core_strdup(plugin_name.c_str()),core_strdup(description.c_str()), OPTION_BOOLEAN, start ? "1" : "0"); add_entry({ std::move(plugin_name) }, core_strdup(description.c_str()), option_type::BOOLEAN, start ? "1" : "0");
} }
} }

View File

@ -64,12 +64,10 @@ menu_custom_ui::menu_custom_ui(mame_ui_manager &mui, render_container &container
menu_custom_ui::~menu_custom_ui() menu_custom_ui::~menu_custom_ui()
{ {
std::string error_string; ui().options().set_value(OPTION_HIDE_PANELS, ui_globals::panels_status, OPTION_PRIORITY_CMDLINE);
ui().options().set_value(OPTION_HIDE_PANELS, ui_globals::panels_status, OPTION_PRIORITY_CMDLINE, error_string);
if (!m_lang.empty()) if (!m_lang.empty())
{ {
machine().options().set_value(OPTION_LANGUAGE, m_lang[m_currlang].c_str(), OPTION_PRIORITY_CMDLINE, error_string); machine().options().set_value(OPTION_LANGUAGE, m_lang[m_currlang].c_str(), OPTION_PRIORITY_CMDLINE);
machine().options().mark_changed(OPTION_LANGUAGE);
load_translation(machine().options()); load_translation(machine().options());
} }
ui_globals::reset = true; ui_globals::reset = true;
@ -215,22 +213,10 @@ menu_font_ui::menu_font_ui(mame_ui_manager &mui, render_container &container) :
m_info_size = moptions.infos_size(); m_info_size = moptions.infos_size();
m_font_size = moptions.font_rows(); m_font_size = moptions.font_rows();
m_info_max = atof(moptions.get_entry(OPTION_INFOS_SIZE)->maximum());
for (ui_options::entry &f_entry : moptions) m_info_min = atof(moptions.get_entry(OPTION_INFOS_SIZE)->minimum());
{ m_font_max = atof(moptions.get_entry(OPTION_FONT_ROWS)->maximum());
const char *entry_name = f_entry.name(); m_font_max = atof(moptions.get_entry(OPTION_FONT_ROWS)->minimum());
if (entry_name && strlen(entry_name) && !strcmp(OPTION_INFOS_SIZE, f_entry.name()))
{
m_info_max = atof(f_entry.maximum());
m_info_min = atof(f_entry.minimum());
}
else if (entry_name && strlen(entry_name) && !strcmp(OPTION_FONT_ROWS, f_entry.name()))
{
m_font_max = atof(f_entry.maximum());
m_font_min = atof(f_entry.minimum());
}
}
} }
//------------------------------------------------- //-------------------------------------------------
@ -264,11 +250,9 @@ menu_font_ui::~menu_font_ui()
name.insert(0, "[B]"); name.insert(0, "[B]");
} }
#endif #endif
machine().options().set_value(OPTION_UI_FONT, name.c_str(), OPTION_PRIORITY_CMDLINE, error_string); machine().options().set_value(OPTION_UI_FONT, name, OPTION_PRIORITY_CMDLINE);
machine().options().mark_changed(OPTION_UI_FONT); moptions.set_value(OPTION_INFOS_SIZE, m_info_size, OPTION_PRIORITY_CMDLINE);
moptions.set_value(OPTION_FONT_ROWS, m_font_size, OPTION_PRIORITY_CMDLINE);
moptions.set_value(OPTION_INFOS_SIZE, m_info_size, OPTION_PRIORITY_CMDLINE, error_string);
moptions.set_value(OPTION_FONT_ROWS, m_font_size, OPTION_PRIORITY_CMDLINE, error_string);
} }
//------------------------------------------------- //-------------------------------------------------
@ -463,11 +447,11 @@ menu_colors_ui::menu_colors_ui(mame_ui_manager &mui, render_container &container
menu_colors_ui::~menu_colors_ui() menu_colors_ui::~menu_colors_ui()
{ {
std::string error_string, dec_color; std::string dec_color;
for (int index = 1; index < MUI_RESTORE; index++) for (int index = 1; index < MUI_RESTORE; index++)
{ {
dec_color = string_format("%x", (uint32_t)m_color_table[index].color); dec_color = string_format("%x", (uint32_t)m_color_table[index].color);
ui().options().set_value(m_color_table[index].option, dec_color.c_str(), OPTION_PRIORITY_CMDLINE, error_string); ui().options().set_value(m_color_table[index].option, dec_color.c_str(), OPTION_PRIORITY_CMDLINE);
} }
} }

View File

@ -352,11 +352,10 @@ void menu_add_change_folder::handle()
if (m_change) if (m_change)
{ {
if (ui().options().exists(s_folders[m_ref].option)) if (ui().options().exists(s_folders[m_ref].option))
ui().options().set_value(s_folders[m_ref].option, m_current_path.c_str(), OPTION_PRIORITY_CMDLINE, error_string); ui().options().set_value(s_folders[m_ref].option, m_current_path.c_str(), OPTION_PRIORITY_CMDLINE);
else if (strcmp(machine().options().value(s_folders[m_ref].option), m_current_path.c_str()) != 0) else if (strcmp(machine().options().value(s_folders[m_ref].option), m_current_path.c_str()) != 0)
{ {
machine().options().set_value(s_folders[m_ref].option, m_current_path.c_str(), OPTION_PRIORITY_CMDLINE, error_string); machine().options().set_value(s_folders[m_ref].option, m_current_path.c_str(), OPTION_PRIORITY_CMDLINE);
machine().options().mark_changed(s_folders[m_ref].option);
} }
} }
else else
@ -371,11 +370,10 @@ void menu_add_change_folder::handle()
} }
if (ui().options().exists(s_folders[m_ref].option)) if (ui().options().exists(s_folders[m_ref].option))
ui().options().set_value(s_folders[m_ref].option, tmppath.c_str(), OPTION_PRIORITY_CMDLINE, error_string); ui().options().set_value(s_folders[m_ref].option, tmppath.c_str(), OPTION_PRIORITY_CMDLINE);
else if (strcmp(machine().options().value(s_folders[m_ref].option), tmppath.c_str()) != 0) else if (strcmp(machine().options().value(s_folders[m_ref].option), tmppath.c_str()) != 0)
{ {
machine().options().set_value(s_folders[m_ref].option, tmppath.c_str(), OPTION_PRIORITY_CMDLINE, error_string); machine().options().set_value(s_folders[m_ref].option, tmppath.c_str(), OPTION_PRIORITY_CMDLINE);
machine().options().mark_changed(s_folders[m_ref].option);
} }
} }
@ -592,11 +590,10 @@ void menu_remove_folder::handle()
} }
if (ui().options().exists(s_folders[m_ref].option)) if (ui().options().exists(s_folders[m_ref].option))
ui().options().set_value(s_folders[m_ref].option, tmppath.c_str(), OPTION_PRIORITY_CMDLINE, error_string); ui().options().set_value(s_folders[m_ref].option, tmppath.c_str(), OPTION_PRIORITY_CMDLINE);
else if (strcmp(machine().options().value(s_folders[m_ref].option),tmppath.c_str())!=0) else if (strcmp(machine().options().value(s_folders[m_ref].option),tmppath.c_str())!=0)
{ {
machine().options().set_value(s_folders[m_ref].option, tmppath.c_str(), OPTION_PRIORITY_CMDLINE, error_string); machine().options().set_value(s_folders[m_ref].option, tmppath.c_str(), OPTION_PRIORITY_CMDLINE);
machine().options().mark_changed(s_folders[m_ref].option);
} }
reset_parent(reset_options::REMEMBER_REF); reset_parent(reset_options::REMEMBER_REF);

View File

@ -326,8 +326,7 @@ std::string machine_info::mandatory_images()
{ {
if (image.must_be_loaded()) if (image.must_be_loaded())
{ {
auto iter = m_machine.options().image_options().find(image.instance_name()); if (m_machine.options().image_option(image.instance_name()).value().empty())
if (iter == m_machine.options().image_options().end() || iter->second.empty())
{ {
if (is_first) if (is_first)
is_first = false; is_first = false;

View File

@ -127,12 +127,10 @@ void menu_bios_selection::handle()
if (val>cnt) val=1; if (val>cnt) val=1;
dev->set_system_bios(val); dev->set_system_bios(val);
if (strcmp(dev->tag(),":")==0) { if (strcmp(dev->tag(),":")==0) {
std::string error; machine().options().set_value("bios", val-1, OPTION_PRIORITY_CMDLINE);
machine().options().set_value("bios", val-1, OPTION_PRIORITY_CMDLINE, error);
assert(error.empty());
} else { } else {
const char *slot_option_name = dev->owner()->tag() + 1; const char *slot_option_name = dev->owner()->tag() + 1;
machine().options().slot_options()[slot_option_name].set_bios(string_format("%d", val - 1)); machine().options().slot_option(slot_option_name).set_bios(string_format("%d", val - 1));
} }
reset(reset_options::REMEMBER_REF); reset(reset_options::REMEMBER_REF);
} }
@ -671,14 +669,13 @@ void menu_export::populate(float &customtop, float &custombottom)
menu_machine_configure::menu_machine_configure(mame_ui_manager &mui, render_container &container, const game_driver *prev, float _x0, float _y0) menu_machine_configure::menu_machine_configure(mame_ui_manager &mui, render_container &container, const game_driver *prev, float _x0, float _y0)
: menu(mui, container) : menu(mui, container)
, m_drv(prev) , m_drv(prev)
, m_opts(mui.machine().options())
, x0(_x0) , x0(_x0)
, y0(_y0) , y0(_y0)
, m_curbios(0) , m_curbios(0)
, m_fav_reset(false) , m_fav_reset(false)
{ {
// parse the INI file // parse the INI file
std::string error; std::ostringstream error;
mame_options::parse_standard_inis(m_opts, error, m_drv); mame_options::parse_standard_inis(m_opts, error, m_drv);
setup_bios(); setup_bios();
} }
@ -750,9 +747,7 @@ void menu_machine_configure::handle()
else if (menu_event->iptkey == IPT_UI_LEFT || menu_event->iptkey == IPT_UI_RIGHT) else if (menu_event->iptkey == IPT_UI_LEFT || menu_event->iptkey == IPT_UI_RIGHT)
{ {
(menu_event->iptkey == IPT_UI_LEFT) ? --m_curbios : ++m_curbios; (menu_event->iptkey == IPT_UI_LEFT) ? --m_curbios : ++m_curbios;
std::string error; m_opts.set_value(OPTION_BIOS, m_bios[m_curbios].second, OPTION_PRIORITY_CMDLINE);
m_opts.set_value(OPTION_BIOS, m_bios[m_curbios].second, OPTION_PRIORITY_CMDLINE, error);
m_opts.mark_changed(OPTION_BIOS);
reset(reset_options::REMEMBER_POSITION); reset(reset_options::REMEMBER_POSITION);
} }
} }
@ -914,8 +909,7 @@ void menu_plugins_configure::handle()
if (menu_event->iptkey == IPT_UI_LEFT || menu_event->iptkey == IPT_UI_RIGHT || menu_event->iptkey == IPT_UI_SELECT) if (menu_event->iptkey == IPT_UI_LEFT || menu_event->iptkey == IPT_UI_RIGHT || menu_event->iptkey == IPT_UI_SELECT)
{ {
int oldval = plugins.int_value((const char*)menu_event->itemref); int oldval = plugins.int_value((const char*)menu_event->itemref);
std::string error_string; plugins.set_value((const char*)menu_event->itemref, oldval == 1 ? 0 : 1, OPTION_PRIORITY_CMDLINE);
plugins.set_value((const char*)menu_event->itemref, oldval == 1 ? 0 : 1, OPTION_PRIORITY_CMDLINE, error_string);
changed = true; changed = true;
} }
} }
@ -931,13 +925,13 @@ void menu_plugins_configure::populate(float &customtop, float &custombottom)
{ {
plugin_options& plugins = mame_machine_manager::instance()->plugins(); plugin_options& plugins = mame_machine_manager::instance()->plugins();
for (auto &curentry : plugins) for (auto &curentry : plugins.entries())
{ {
if (!curentry.is_header()) if (curentry->type() != OPTION_HEADER)
{ {
auto enabled = std::string(curentry.value()) == "1"; auto enabled = !strcmp(curentry->value(), "1");
item_append(curentry.description(), enabled ? _("On") : _("Off"), item_append(curentry->description(), enabled ? _("On") : _("Off"),
enabled ? FLAG_RIGHT_ARROW : FLAG_LEFT_ARROW, (void *)(uintptr_t)curentry.name()); enabled ? FLAG_RIGHT_ARROW : FLAG_LEFT_ARROW, (void *)(uintptr_t)curentry->name().c_str());
} }
} }
item_append(menu_item_type::SEPARATOR); item_append(menu_item_type::SEPARATOR);

View File

@ -116,8 +116,7 @@ menu_select_game::menu_select_game(mame_ui_manager &mui, render_container &conta
if (!moptions.remember_last()) if (!moptions.remember_last())
reselect_last::reset(); reselect_last::reset();
mui.machine().options().set_value(OPTION_SNAPNAME, "%g/%i", OPTION_PRIORITY_CMDLINE, error_string); mui.machine().options().set_value(OPTION_SNAPNAME, "%g/%i", OPTION_PRIORITY_CMDLINE);
mui.machine().options().set_value(OPTION_SOFTWARENAME, "", OPTION_PRIORITY_CMDLINE, error_string);
ui_globals::curimage_view = FIRST_VIEW; ui_globals::curimage_view = FIRST_VIEW;
ui_globals::curdats_view = 0; ui_globals::curdats_view = 0;
@ -155,9 +154,9 @@ menu_select_game::~menu_select_game()
filter.append(",").append(c_year::ui[c_year::actual]); filter.append(",").append(c_year::ui[c_year::actual]);
ui_options &mopt = ui().options(); ui_options &mopt = ui().options();
mopt.set_value(OPTION_LAST_USED_FILTER, filter.c_str(), OPTION_PRIORITY_CMDLINE, error_string); mopt.set_value(OPTION_LAST_USED_FILTER, filter.c_str(), OPTION_PRIORITY_CMDLINE);
mopt.set_value(OPTION_LAST_USED_MACHINE, last_driver.c_str(), OPTION_PRIORITY_CMDLINE, error_string); mopt.set_value(OPTION_LAST_USED_MACHINE, last_driver.c_str(), OPTION_PRIORITY_CMDLINE);
mopt.set_value(OPTION_HIDE_PANELS, ui_globals::panels_status, OPTION_PRIORITY_CMDLINE, error_string); mopt.set_value(OPTION_HIDE_PANELS, ui_globals::panels_status, OPTION_PRIORITY_CMDLINE);
ui().save_ui_options(); ui().save_ui_options();
} }
@ -942,11 +941,10 @@ void menu_select_game::inkey_select_favorite(const event *menu_event)
return; return;
} }
std::string error_string;
std::string string_list = string_format("%s:%s:%s:%s", ui_swinfo->listname, ui_swinfo->shortname, ui_swinfo->part, ui_swinfo->instance); std::string string_list = string_format("%s:%s:%s:%s", ui_swinfo->listname, ui_swinfo->shortname, ui_swinfo->part, ui_swinfo->instance);
mopt.set_value(OPTION_SOFTWARENAME, string_list.c_str(), OPTION_PRIORITY_CMDLINE, error_string); mopt.set_value(OPTION_SOFTWARENAME, string_list.c_str(), OPTION_PRIORITY_CMDLINE);
std::string snap_list = std::string(ui_swinfo->listname).append(PATH_SEPARATOR).append(ui_swinfo->shortname); std::string snap_list = std::string(ui_swinfo->listname).append(PATH_SEPARATOR).append(ui_swinfo->shortname);
mopt.set_value(OPTION_SNAPNAME, snap_list.c_str(), OPTION_PRIORITY_CMDLINE, error_string); mopt.set_value(OPTION_SNAPNAME, snap_list.c_str(), OPTION_PRIORITY_CMDLINE);
reselect_last::driver = drv.driver().name; reselect_last::driver = drv.driver().name;
reselect_last::software = ui_swinfo->shortname; reselect_last::software = ui_swinfo->shortname;
reselect_last::swlist = ui_swinfo->listname; reselect_last::swlist = ui_swinfo->listname;

View File

@ -144,9 +144,6 @@ menu_select_software::menu_select_software(mame_ui_manager &mui, render_containe
ui_globals::switch_image = true; ui_globals::switch_image = true;
ui_globals::cur_sw_dats_view = 0; ui_globals::cur_sw_dats_view = 0;
ui_globals::cur_sw_dats_total = 1; ui_globals::cur_sw_dats_total = 1;
std::string error_string;
mui.machine().options().set_value(OPTION_SOFTWARENAME, "", OPTION_PRIORITY_CMDLINE, error_string);
} }
//------------------------------------------------- //-------------------------------------------------
@ -718,11 +715,10 @@ void menu_select_software::inkey_select(const event *menu_event)
return; return;
} }
std::string error_string; machine().options().set_system_name(m_driver->name);
std::string string_list = std::string(ui_swinfo->listname).append(":").append(ui_swinfo->shortname).append(":").append(ui_swinfo->part).append(":").append(ui_swinfo->instance); machine().options().set_value(OPTION_SOFTWARENAME, ui_swinfo->shortname, OPTION_PRIORITY_CMDLINE);
machine().options().set_value(OPTION_SOFTWARENAME, string_list.c_str(), OPTION_PRIORITY_CMDLINE, error_string);
std::string snap_list = std::string(ui_swinfo->listname).append(PATH_SEPARATOR).append(ui_swinfo->shortname); std::string snap_list = std::string(ui_swinfo->listname).append(PATH_SEPARATOR).append(ui_swinfo->shortname);
machine().options().set_value(OPTION_SNAPNAME, snap_list.c_str(), OPTION_PRIORITY_CMDLINE, error_string); machine().options().set_value(OPTION_SNAPNAME, snap_list.c_str(), OPTION_PRIORITY_CMDLINE);
reselect_last::driver = drivlist.driver().name; reselect_last::driver = drivlist.driver().name;
reselect_last::software = ui_swinfo->shortname; reselect_last::software = ui_swinfo->shortname;
reselect_last::swlist = ui_swinfo->listname; reselect_last::swlist = ui_swinfo->listname;
@ -1288,9 +1284,8 @@ void software_parts::handle()
{ {
if ((void*)&elem == menu_event->itemref) if ((void*)&elem == menu_event->itemref)
{ {
std::string error_string;
std::string string_list = std::string(m_uiinfo->listname).append(":").append(m_uiinfo->shortname).append(":").append(elem.first).append(":").append(m_uiinfo->instance); std::string string_list = std::string(m_uiinfo->listname).append(":").append(m_uiinfo->shortname).append(":").append(elem.first).append(":").append(m_uiinfo->instance);
machine().options().set_value(OPTION_SOFTWARENAME, string_list.c_str(), OPTION_PRIORITY_CMDLINE, error_string); machine().options().set_value(OPTION_SOFTWARENAME, string_list.c_str(), OPTION_PRIORITY_CMDLINE);
reselect_last::driver = m_uiinfo->driver->name; reselect_last::driver = m_uiinfo->driver->name;
reselect_last::software = m_uiinfo->shortname; reselect_last::software = m_uiinfo->shortname;
@ -1298,7 +1293,7 @@ void software_parts::handle()
reselect_last::set(true); reselect_last::set(true);
std::string snap_list = std::string(m_uiinfo->listname).append("/").append(m_uiinfo->shortname); std::string snap_list = std::string(m_uiinfo->listname).append("/").append(m_uiinfo->shortname);
machine().options().set_value(OPTION_SNAPNAME, snap_list.c_str(), OPTION_PRIORITY_CMDLINE, error_string); machine().options().set_value(OPTION_SNAPNAME, snap_list.c_str(), OPTION_PRIORITY_CMDLINE);
mame_machine_manager::instance()->schedule_new_driver(*m_uiinfo->driver); mame_machine_manager::instance()->schedule_new_driver(*m_uiinfo->driver);
machine().schedule_hard_reset(); machine().schedule_hard_reset();
@ -1400,8 +1395,7 @@ void bios_selection::handle()
reselect_last::set(true); reselect_last::set(true);
} }
std::string error; moptions.set_value(OPTION_BIOS, elem.second, OPTION_PRIORITY_CMDLINE);
moptions.set_value(OPTION_BIOS, elem.second, OPTION_PRIORITY_CMDLINE, error);
mame_machine_manager::instance()->schedule_new_driver(*s_driver); mame_machine_manager::instance()->schedule_new_driver(*s_driver);
machine().schedule_hard_reset(); machine().schedule_hard_reset();
stack_reset(); stack_reset();
@ -1409,8 +1403,7 @@ void bios_selection::handle()
else else
{ {
ui_software_info *ui_swinfo = (ui_software_info *)m_driver; ui_software_info *ui_swinfo = (ui_software_info *)m_driver;
std::string error; machine().options().set_value(OPTION_BIOS, elem.second, OPTION_PRIORITY_CMDLINE);
machine().options().set_value(OPTION_BIOS, elem.second, OPTION_PRIORITY_CMDLINE, error);
driver_enumerator drivlist(machine().options(), *ui_swinfo->driver); driver_enumerator drivlist(machine().options(), *ui_swinfo->driver);
drivlist.next(); drivlist.next();
software_list_device *swlist = software_list_device::find_by_name(*drivlist.config(), ui_swinfo->listname.c_str()); software_list_device *swlist = software_list_device::find_by_name(*drivlist.config(), ui_swinfo->listname.c_str());
@ -1431,11 +1424,10 @@ void bios_selection::handle()
menu::stack_push<software_parts>(ui(), container(), parts, ui_swinfo); menu::stack_push<software_parts>(ui(), container(), parts, ui_swinfo);
return; return;
} }
std::string error_string;
std::string string_list = std::string(ui_swinfo->listname).append(":").append(ui_swinfo->shortname).append(":").append(ui_swinfo->part).append(":").append(ui_swinfo->instance); std::string string_list = std::string(ui_swinfo->listname).append(":").append(ui_swinfo->shortname).append(":").append(ui_swinfo->part).append(":").append(ui_swinfo->instance);
moptions.set_value(OPTION_SOFTWARENAME, string_list.c_str(), OPTION_PRIORITY_CMDLINE, error_string); moptions.set_value(OPTION_SOFTWARENAME, string_list.c_str(), OPTION_PRIORITY_CMDLINE);
std::string snap_list = std::string(ui_swinfo->listname).append(PATH_SEPARATOR).append(ui_swinfo->shortname); std::string snap_list = std::string(ui_swinfo->listname).append(PATH_SEPARATOR).append(ui_swinfo->shortname);
moptions.set_value(OPTION_SNAPNAME, snap_list.c_str(), OPTION_PRIORITY_CMDLINE, error_string); moptions.set_value(OPTION_SNAPNAME, snap_list.c_str(), OPTION_PRIORITY_CMDLINE);
reselect_last::driver = drivlist.driver().name; reselect_last::driver = drivlist.driver().name;
reselect_last::software = ui_swinfo->shortname; reselect_last::software = ui_swinfo->shortname;
reselect_last::swlist = ui_swinfo->listname; reselect_last::swlist = ui_swinfo->listname;

View File

@ -100,10 +100,10 @@ device_slot_option *menu_slot_devices::get_current_option(device_slot_interface
{ {
std::string current; std::string current;
const char *slot_option_name = slot.slot_name(); if (!slot.fixed())
if (!slot.fixed() && machine().options().slot_options().count(slot_option_name) > 0)
{ {
current = machine().options().slot_options()[slot_option_name].value(); const char *slot_option_name = slot.slot_name();
current = machine().options().slot_option(slot_option_name).value();
} }
else else
{ {
@ -185,9 +185,82 @@ const char *menu_slot_devices::get_previous_slot(device_slot_interface &slot) co
void menu_slot_devices::set_slot_device(device_slot_interface &slot, const char *val) void menu_slot_devices::set_slot_device(device_slot_interface &slot, const char *val)
{ {
std::string error; // we might change slot options; in the spirit of user friendliness, we should record all current
machine().options().set_value(slot.slot_name(), val, OPTION_PRIORITY_CMDLINE, error); // options
assert(error.empty()); record_current_options();
// find the slot option
slot_option &opt(machine().options().slot_option(slot.slot_name()));
// specify it
opt.specify(val);
// erase this from our recorded options list - this is the slot we're trying to change!
m_slot_options.erase(slot.slot_name());
// refresh any options that we might have annotated earlier
while (try_refresh_current_options())
;
// changing the options may result in options changing; we need to reset
reset(reset_options::REMEMBER_POSITION);
}
//-------------------------------------------------
// record_current_options
//-------------------------------------------------
void menu_slot_devices::record_current_options()
{
for (device_slot_interface &slot : slot_interface_iterator(m_config->root_device()))
{
// we're doing this out of a desire to honor user-selectable options; therefore it only
// makes sense to record values for selectable options
if (slot.has_selectable_options())
{
// get the slot option
const slot_option &opt(machine().options().slot_option(slot.slot_name()));
// and record the value in our local cache
m_slot_options[slot.slot_name()] = opt.specified_value();
}
}
}
//-------------------------------------------------
// try_refresh_current_options
//-------------------------------------------------
bool menu_slot_devices::try_refresh_current_options()
{
// enumerate through all slot options that we've tracked
for (const auto &opt : m_slot_options)
{
// do we have a value different than what we're tracking?
slot_option *slotopt = machine().options().find_slot_option(opt.first);
if (slotopt && slotopt->specified_value() != opt.second)
{
// specify this option (but catch errors)
try
{
slotopt->specify(opt.second);
// the option was successfully specified; it isn't safe to continue
// checking slots as the act of specifying the slot may have drastically
// changed the options list
return true;
}
catch (options_exception &)
{
// this threw an exception - that is fine; we can just proceed
}
}
}
// we've went through all options without changing anything
return false;
} }
@ -197,8 +270,12 @@ void menu_slot_devices::set_slot_device(device_slot_interface &slot, const char
void menu_slot_devices::populate(float &customtop, float &custombottom) void menu_slot_devices::populate(float &customtop, float &custombottom)
{ {
// we need to keep our own copy of the machine_config because we
// can change this out from under the caller
m_config = std::make_unique<machine_config>(machine().system(), machine().options());
// cycle through all devices for this system // cycle through all devices for this system
for (device_slot_interface &slot : slot_interface_iterator(machine().root_device())) for (device_slot_interface &slot : slot_interface_iterator(m_config->root_device()))
{ {
// does this slot have any selectable options? // does this slot have any selectable options?
bool has_selectable_options = slot.has_selectable_options(); bool has_selectable_options = slot.has_selectable_options();
@ -238,7 +315,6 @@ void menu_slot_devices::handle()
{ {
if (menu_event->itemref == ITEMREF_RESET && menu_event->iptkey == IPT_UI_SELECT) if (menu_event->itemref == ITEMREF_RESET && menu_event->iptkey == IPT_UI_SELECT)
{ {
mame_options::add_slot_options(machine().options());
machine().schedule_hard_reset(); machine().schedule_hard_reset();
} }
else if (menu_event->iptkey == IPT_UI_LEFT || menu_event->iptkey == IPT_UI_RIGHT) else if (menu_event->iptkey == IPT_UI_LEFT || menu_event->iptkey == IPT_UI_RIGHT)
@ -246,7 +322,6 @@ void menu_slot_devices::handle()
device_slot_interface *slot = (device_slot_interface *)menu_event->itemref; device_slot_interface *slot = (device_slot_interface *)menu_event->itemref;
const char *val = (menu_event->iptkey == IPT_UI_LEFT) ? get_previous_slot(*slot) : get_next_slot(*slot); const char *val = (menu_event->iptkey == IPT_UI_LEFT) ? get_previous_slot(*slot) : get_next_slot(*slot);
set_slot_device(*slot, val); set_slot_device(*slot, val);
reset(reset_options::REMEMBER_REF);
} }
else if (menu_event->iptkey == IPT_UI_SELECT) else if (menu_event->iptkey == IPT_UI_SELECT)
{ {

View File

@ -15,6 +15,7 @@
#include "ui/menu.h" #include "ui/menu.h"
#include <unordered_map>
namespace ui { namespace ui {
class menu_slot_devices : public menu class menu_slot_devices : public menu
@ -32,6 +33,12 @@ private:
const char *get_next_slot(device_slot_interface &slot) const; const char *get_next_slot(device_slot_interface &slot) const;
const char *get_previous_slot(device_slot_interface &slot) const; const char *get_previous_slot(device_slot_interface &slot) const;
void set_slot_device(device_slot_interface &slot, const char *val); void set_slot_device(device_slot_interface &slot, const char *val);
void record_current_options();
bool try_refresh_current_options();
// variables
std::unique_ptr<machine_config> m_config;
std::unordered_map<std::string, std::string> m_slot_options;
}; };
} // namespace ui } // namespace ui

View File

@ -45,23 +45,19 @@ menu_sound_options::menu_sound_options(mame_ui_manager &mui, render_container &c
menu_sound_options::~menu_sound_options() menu_sound_options::~menu_sound_options()
{ {
std::string error_string;
emu_options &moptions = machine().options(); emu_options &moptions = machine().options();
if (strcmp(moptions.value(OSDOPTION_SOUND),m_sound ? OSDOPTVAL_AUTO : OSDOPTVAL_NONE)!=0) if (strcmp(moptions.value(OSDOPTION_SOUND),m_sound ? OSDOPTVAL_AUTO : OSDOPTVAL_NONE)!=0)
{ {
moptions.set_value(OSDOPTION_SOUND, m_sound ? OSDOPTVAL_AUTO : OSDOPTVAL_NONE, OPTION_PRIORITY_CMDLINE, error_string); moptions.set_value(OSDOPTION_SOUND, m_sound ? OSDOPTVAL_AUTO : OSDOPTVAL_NONE, OPTION_PRIORITY_CMDLINE);
machine().options().mark_changed(OSDOPTION_SOUND);
} }
if (moptions.int_value(OPTION_SAMPLERATE)!=m_sound_rate[m_cur_rates]) if (moptions.int_value(OPTION_SAMPLERATE)!=m_sound_rate[m_cur_rates])
{ {
moptions.set_value(OPTION_SAMPLERATE, m_sound_rate[m_cur_rates], OPTION_PRIORITY_CMDLINE, error_string); moptions.set_value(OPTION_SAMPLERATE, m_sound_rate[m_cur_rates], OPTION_PRIORITY_CMDLINE);
machine().options().mark_changed(OPTION_SAMPLERATE);
} }
if (moptions.bool_value(OPTION_SAMPLES)!=m_samples) if (moptions.bool_value(OPTION_SAMPLES)!=m_samples)
{ {
moptions.set_value(OPTION_SAMPLES, m_samples, OPTION_PRIORITY_CMDLINE, error_string); moptions.set_value(OPTION_SAMPLES, m_samples, OPTION_PRIORITY_CMDLINE);
machine().options().mark_changed(OPTION_SAMPLES);
} }
} }

View File

@ -240,8 +240,7 @@ void submenu::handle()
{ {
case OPTION_BOOLEAN: case OPTION_BOOLEAN:
changed = true; changed = true;
sm_option.options->set_value(sm_option.name, !strcmp(sm_option.entry->value(),"1") ? "0" : "1", OPTION_PRIORITY_CMDLINE, error_string); sm_option.options->set_value(sm_option.name, !strcmp(sm_option.entry->value(),"1") ? "0" : "1", OPTION_PRIORITY_CMDLINE);
sm_option.entry->mark_changed();
break; break;
case OPTION_INTEGER: case OPTION_INTEGER:
if (menu_event->iptkey == IPT_UI_LEFT || menu_event->iptkey == IPT_UI_RIGHT) if (menu_event->iptkey == IPT_UI_LEFT || menu_event->iptkey == IPT_UI_RIGHT)
@ -249,8 +248,7 @@ void submenu::handle()
changed = true; changed = true;
int i_cur = atoi(sm_option.entry->value()); int i_cur = atoi(sm_option.entry->value());
(menu_event->iptkey == IPT_UI_LEFT) ? i_cur-- : i_cur++; (menu_event->iptkey == IPT_UI_LEFT) ? i_cur-- : i_cur++;
sm_option.options->set_value(sm_option.name, i_cur, OPTION_PRIORITY_CMDLINE, error_string); sm_option.options->set_value(sm_option.name, i_cur, OPTION_PRIORITY_CMDLINE);
sm_option.entry->mark_changed();
} }
break; break;
case OPTION_FLOAT: case OPTION_FLOAT:
@ -260,17 +258,19 @@ void submenu::handle()
f_cur = atof(sm_option.entry->value()); f_cur = atof(sm_option.entry->value());
if (sm_option.entry->has_range()) if (sm_option.entry->has_range())
{ {
f_step = atof(sm_option.entry->minimum()); const char *minimum = sm_option.entry->minimum();
const char *maximum = sm_option.entry->maximum();
f_step = atof(minimum);
if (f_step <= 0.0f) { if (f_step <= 0.0f) {
int pmin = getprecisionchr(sm_option.entry->minimum()); int pmin = getprecisionchr(minimum);
int pmax = getprecisionchr(sm_option.entry->maximum()); int pmax = getprecisionchr(maximum);
tmptxt = '1' + std::string((pmin > pmax) ? pmin : pmax, '0'); tmptxt = '1' + std::string((pmin > pmax) ? pmin : pmax, '0');
f_step = 1 / atof(tmptxt.c_str()); f_step = 1 / atof(tmptxt.c_str());
} }
} }
else else
{ {
int precision = getprecisionchr(sm_option.entry->default_value()); int precision = getprecisionchr(sm_option.entry->default_value().c_str());
tmptxt = '1' + std::string(precision, '0'); tmptxt = '1' + std::string(precision, '0');
f_step = 1 / atof(tmptxt.c_str()); f_step = 1 / atof(tmptxt.c_str());
} }
@ -279,8 +279,7 @@ void submenu::handle()
else else
f_cur += f_step; f_cur += f_step;
tmptxt = string_format("%g", f_cur); tmptxt = string_format("%g", f_cur);
sm_option.options->set_value(sm_option.name, tmptxt.c_str(), OPTION_PRIORITY_CMDLINE, error_string); sm_option.options->set_value(sm_option.name, tmptxt.c_str(), OPTION_PRIORITY_CMDLINE);
sm_option.entry->mark_changed();
} }
break; break;
case OPTION_STRING: case OPTION_STRING:
@ -293,10 +292,11 @@ void submenu::handle()
v_cur = sm_option.value[--cur_value]; v_cur = sm_option.value[--cur_value];
else else
v_cur = sm_option.value[++cur_value]; v_cur = sm_option.value[++cur_value];
sm_option.options->set_value(sm_option.name, v_cur.c_str(), OPTION_PRIORITY_CMDLINE, error_string); sm_option.options->set_value(sm_option.name, v_cur.c_str(), OPTION_PRIORITY_CMDLINE);
sm_option.entry->mark_changed();
} }
break; break;
default:
break;
} }
break; break;
default: default:
@ -391,7 +391,7 @@ void submenu::populate(float &customtop, float &custombottom)
break; break;
case OPTION_STRING: case OPTION_STRING:
{ {
std::string const v_cur(sm_option->entry->value()); std::string v_cur(sm_option->entry->value());
int const cur_value = std::distance(sm_option->value.begin(), std::find(sm_option->value.begin(), sm_option->value.end(), v_cur)); int const cur_value = std::distance(sm_option->value.begin(), std::find(sm_option->value.begin(), sm_option->value.end(), v_cur));
arrow_flags = get_arrow_flags(0, int(unsigned(sm_option->value.size() - 1)), cur_value); arrow_flags = get_arrow_flags(0, int(unsigned(sm_option->value.size() - 1)), cur_value);
item_append(_(sm_option->description), item_append(_(sm_option->description),

View File

@ -48,7 +48,7 @@ public:
option_type type; option_type type;
const char *description; const char *description;
const char *name; const char *name;
core_options::entry *entry; core_options::entry::shared_ptr entry;
core_options *options; core_options *options;
std::vector<std::string> value; std::vector<std::string> value;
}; };

View File

@ -2117,16 +2117,20 @@ void mame_ui_manager::popup_time_string(int seconds, std::string message)
void mame_ui_manager::load_ui_options() void mame_ui_manager::load_ui_options()
{ {
// parse the file // parse the file
std::string error;
// attempt to open the output file // attempt to open the output file
emu_file file(machine().options().ini_path(), OPEN_FLAG_READ); emu_file file(machine().options().ini_path(), OPEN_FLAG_READ);
if (file.open("ui.ini") == osd_file::error::NONE) if (file.open("ui.ini") == osd_file::error::NONE)
{ {
bool result = options().parse_ini_file((util::core_file&)file, OPTION_PRIORITY_MAME_INI, OPTION_PRIORITY_MAME_INI < OPTION_PRIORITY_DRIVER_INI, error); try
if (!result) {
options().parse_ini_file((util::core_file&)file, OPTION_PRIORITY_MAME_INI, OPTION_PRIORITY_MAME_INI < OPTION_PRIORITY_DRIVER_INI, true);
}
catch (options_exception &)
{
osd_printf_error("**Error loading ui.ini**\n"); osd_printf_error("**Error loading ui.ini**\n");
} }
} }
}
//------------------------------------------------- //-------------------------------------------------
// save ui options // save ui options
@ -2155,28 +2159,37 @@ void mame_ui_manager::save_main_option()
{ {
// parse the file // parse the file
std::string error; std::string error;
emu_options options(machine().options()); // This way we make sure that all OSD parts are in emu_options options(emu_options::option_support::GENERAL_ONLY); // This way we make sure that all OSD parts are in
std::string error_string;
options.copy_from(machine().options());
// attempt to open the main ini file // attempt to open the main ini file
{ {
emu_file file(machine().options().ini_path(), OPEN_FLAG_READ); emu_file file(machine().options().ini_path(), OPEN_FLAG_READ);
if (file.open(emulator_info::get_configname(), ".ini") == osd_file::error::NONE) if (file.open(emulator_info::get_configname(), ".ini") == osd_file::error::NONE)
{ {
bool result = options.parse_ini_file((util::core_file&)file, OPTION_PRIORITY_MAME_INI, OPTION_PRIORITY_MAME_INI < OPTION_PRIORITY_DRIVER_INI, error); try
if (!result) {
options.parse_ini_file((util::core_file&)file, OPTION_PRIORITY_MAME_INI, OPTION_PRIORITY_MAME_INI < OPTION_PRIORITY_DRIVER_INI, true);
}
catch(options_error_exception &)
{ {
osd_printf_error("**Error loading %s.ini**\n", emulator_info::get_configname()); osd_printf_error("**Error loading %s.ini**\n", emulator_info::get_configname());
return; return;
} }
catch (options_exception &)
{
// ignore other exceptions related to options
}
} }
} }
for (emu_options::entry &f_entry : machine().options()) for (const auto &f_entry : machine().options().entries())
{ {
if (f_entry.is_changed()) const char *value = f_entry->value();
if (value && strcmp(value, options.value(f_entry->name().c_str())))
{ {
options.set_value(f_entry.name(), f_entry.value(), OPTION_PRIORITY_CMDLINE, error_string); options.set_value(f_entry->name(), *f_entry->value(), OPTION_PRIORITY_CMDLINE);
} }
} }

File diff suppressed because it is too large Load Diff

View File

@ -13,26 +13,13 @@
#include "corefile.h" #include "corefile.h"
#include <unordered_map> #include <unordered_map>
#include <sstream>
//************************************************************************** //**************************************************************************
// CONSTANTS // CONSTANTS
//************************************************************************** //**************************************************************************
// option types
const uint32_t OPTION_TYPE_MASK = 0x0007; // up to 8 different types
enum
{
OPTION_INVALID, // invalid
OPTION_HEADER, // a header item
OPTION_COMMAND, // a command
OPTION_BOOLEAN, // boolean option
OPTION_INTEGER, // integer option
OPTION_FLOAT, // floating-point option
OPTION_STRING // string option
};
// option priorities // option priorities
const int OPTION_PRIORITY_DEFAULT = 0; // defaults are at 0 priority const int OPTION_PRIORITY_DEFAULT = 0; // defaults are at 0 priority
const int OPTION_PRIORITY_LOW = 50; // low priority const int OPTION_PRIORITY_LOW = 50; // low priority
@ -40,20 +27,55 @@ const int OPTION_PRIORITY_NORMAL = 100; // normal priority
const int OPTION_PRIORITY_HIGH = 150; // high priority const int OPTION_PRIORITY_HIGH = 150; // high priority
const int OPTION_PRIORITY_MAXIMUM = 255; // maximum priority const int OPTION_PRIORITY_MAXIMUM = 255; // maximum priority
const uint32_t OPTION_FLAG_INTERNAL = 0x40000000;
//************************************************************************** //**************************************************************************
// TYPE DEFINITIONS // TYPE DEFINITIONS
//************************************************************************** //**************************************************************************
// static structure describing a single option with its description and default value struct options_entry;
struct options_entry
// exception thrown by core_options when an illegal request is made
class options_exception : public std::exception
{ {
const char * name; // name on the command line public:
const char * defvalue; // default value of this argument const std::string &message() const { return m_message; }
uint32_t flags; // flags to describe the option virtual const char *what() const noexcept override { return message().c_str(); }
const char * description; // description for -showusage
protected:
options_exception(std::string &&message);
private:
std::string m_message;
};
class options_warning_exception : public options_exception
{
public:
template <typename... Params> options_warning_exception(const char *fmt, Params &&...args)
: options_warning_exception(util::string_format(fmt, std::forward<Params>(args)...))
{
}
options_warning_exception(std::string &&message);
options_warning_exception(const options_warning_exception &) = default;
options_warning_exception(options_warning_exception &&) = default;
options_warning_exception& operator=(const options_warning_exception &) = default;
options_warning_exception& operator=(options_warning_exception &&) = default;
};
class options_error_exception : public options_exception
{
public:
template <typename... Params> options_error_exception(const char *fmt, Params &&...args)
: options_error_exception(util::string_format(fmt, std::forward<Params>(args)...))
{
}
options_error_exception(std::string &&message);
options_error_exception(const options_error_exception &) = default;
options_error_exception(options_error_exception &&) = default;
options_error_exception& operator=(const options_error_exception &) = default;
options_error_exception& operator=(options_error_exception &&) = default;
}; };
@ -63,95 +85,97 @@ class core_options
static const int MAX_UNADORNED_OPTIONS = 16; static const int MAX_UNADORNED_OPTIONS = 16;
public: public:
enum class option_type
{
INVALID, // invalid
HEADER, // a header item
COMMAND, // a command
BOOLEAN, // boolean option
INTEGER, // integer option
FLOAT, // floating-point option
STRING // string option
};
// information about a single entry in the options // information about a single entry in the options
class entry class entry
{ {
friend class core_options;
friend class simple_list<entry>;
// construction/destruction
entry(const char *name, const char *description, uint32_t flags = 0, const char *defvalue = nullptr);
public: public:
// getters typedef std::shared_ptr<entry> shared_ptr;
entry *next() const { return m_next; } typedef std::weak_ptr<entry> weak_ptr;
const char *name(int index = 0) const { return (index < ARRAY_LENGTH(m_name) && !m_name[index].empty()) ? m_name[index].c_str() : nullptr; }
const char *description() const { return m_description; }
const char *value() const { return m_data.c_str(); }
const char *default_value() const { return m_defdata.c_str(); }
const char *minimum() const { return m_minimum.c_str(); }
const char *maximum() const { return m_maximum.c_str(); }
int type() const { return (m_flags & OPTION_TYPE_MASK); }
uint32_t flags() const { return m_flags; }
bool is_header() const { return type() == OPTION_HEADER; }
bool is_command() const { return type() == OPTION_COMMAND; }
bool is_internal() const { return m_flags & OPTION_FLAG_INTERNAL; }
bool has_range() const { return (!m_minimum.empty() && !m_maximum.empty()); }
int priority() const { return m_priority; }
bool is_changed() const { return m_changed; }
// setters // constructor/destructor
void set_value(const char *newvalue, int priority); entry(std::vector<std::string> &&names, option_type type = option_type::STRING, const char *description = nullptr);
void set_default_value(const char *defvalue); entry(std::string &&name, option_type type = option_type::STRING, const char *description = nullptr);
void set_description(const char *description); entry(const entry &) = delete;
void set_flag(uint32_t mask, uint32_t flag); entry(entry &&) = delete;
void mark_changed() { m_changed = true; } entry& operator=(const entry &) = delete;
void revert(int priority_hi, int priority_lo); entry& operator=(entry &&) = delete;
virtual ~entry();
// accessors
const std::vector<std::string> &names() const { return m_names; }
const std::string &name() const { return m_names[0]; }
virtual const char *value() const;
int priority() const { return m_priority; }
void set_priority(int priority) { m_priority = priority; }
option_type type() const { return m_type; }
const char *description() const { return m_description; }
virtual const std::string &default_value() const;
virtual const char *minimum() const;
virtual const char *maximum() const;
bool has_range() const;
// mutators
void set_value(std::string &&newvalue, int priority, bool always_override = false);
virtual void set_default_value(std::string &&newvalue);
void set_description(const char *description) { m_description = description; }
void set_value_changed_handler(std::function<void(const char *)> &&handler) { m_value_changed_handler = std::move(handler); }
protected:
virtual void internal_set_value(std::string &&newvalue) = 0;
private: private:
// internal state void validate(const std::string &value);
entry * m_next; // link to the next data
uint32_t m_flags; // flags from the entry std::vector<std::string> m_names;
bool m_error_reported; // have we reported an error on this option yet? int m_priority;
int m_priority; // priority of the data set core_options::option_type m_type;
const char * m_description; // description for this item const char * m_description;
std::string m_name[4]; // up to 4 names for the item std::function<void(const char *)> m_value_changed_handler;
std::string m_data; // data for this item
std::string m_defdata; // default data for this item
std::string m_minimum; // minimum value
std::string m_maximum; // maximum value
bool m_changed; // changed flag
}; };
// construction/destruction // construction/destruction
core_options(); core_options();
core_options(const options_entry *entrylist); core_options(const core_options &) = delete;
core_options(const options_entry *entrylist1, const options_entry *entrylist2); core_options(core_options &&) = delete;
core_options(const options_entry *entrylist1, const options_entry *entrylist2, const options_entry *entrylist3); core_options& operator=(const core_options &) = delete;
core_options(const core_options &src); core_options& operator=(core_options &&) = delete;
virtual ~core_options(); virtual ~core_options();
// operators
core_options &operator=(const core_options &rhs);
bool operator==(const core_options &rhs);
bool operator!=(const core_options &rhs);
// getters // getters
entry *first() const { return m_entrylist.first(); }
const std::string &command() const { return m_command; } const std::string &command() const { return m_command; }
const std::vector<std::string> &command_arguments() const { assert(!m_command.empty()); return m_command_arguments; } const std::vector<std::string> &command_arguments() const { assert(!m_command.empty()); return m_command_arguments; }
entry *get_entry(const char *name) const; const entry::shared_ptr get_entry(const std::string &name) const;
entry::shared_ptr get_entry(const std::string &name);
// range iterators const std::vector<entry::shared_ptr> &entries() const { return m_entries; }
using auto_iterator = simple_list<entry>::auto_iterator; bool exists(const std::string &name) const { return get_entry(name) != nullptr; }
auto_iterator begin() const { return m_entrylist.begin(); } bool header_exists(const char *description) const;
auto_iterator end() const { return m_entrylist.end(); }
// configuration // configuration
void add_entry(const char *name, const char *description, uint32_t flags = 0, const char *defvalue = nullptr, bool override_existing = false); void add_entry(entry::shared_ptr &&entry, const char *after_header = nullptr);
void add_entry(const options_entry &data, bool override_existing = false) { add_entry(data.name, data.description, data.flags, data.defvalue, override_existing); } void add_entry(const options_entry &entry, bool override_existing = false);
void add_entry(std::vector<std::string> &&names, const char *description, option_type type, std::string &&default_value = "", std::string &&minimum = "", std::string &&maximum = "");
void add_header(const char *description);
void add_entries(const options_entry *entrylist, bool override_existing = false); void add_entries(const options_entry *entrylist, bool override_existing = false);
void set_default_value(const char *name, const char *defvalue); void set_default_value(const char *name, const char *defvalue);
void set_description(const char *name, const char *description); void set_description(const char *name, const char *description);
void remove_entry(entry &delentry); void remove_entry(entry &delentry);
void set_value_changed_handler(const std::string &name, std::function<void(const char *)> &&handler);
// parsing/input // parsing/input
bool parse_command_line(std::vector<std::string> &args, int priority, std::string &error_string); void parse_command_line(const std::vector<std::string> &args, int priority, bool ignore_unknown_options = false);
bool parse_ini_file(util::core_file &inifile, int priority, bool ignore_unknown_options, std::string &error_string); void parse_ini_file(util::core_file &inifile, int priority, bool ignore_unknown_options, bool always_override);
bool pluck_from_command_line(std::vector<std::string> &args, const std::string &name, std::string &result); void copy_from(const core_options &that);
// reverting
void revert(int priority_hi = OPTION_PRIORITY_MAXIMUM, int priority_lo = OPTION_PRIORITY_DEFAULT);
// output // output
std::string output_ini(const core_options *diff = nullptr) const; std::string output_ini(const core_options *diff = nullptr) const;
@ -160,52 +184,92 @@ public:
// reading // reading
const char *value(const char *option) const; const char *value(const char *option) const;
const char *description(const char *option) const; const char *description(const char *option) const;
int priority(const char *option) const; bool bool_value(const char *option) const { return int_value(option) != 0; }
bool bool_value(const char *name) const { return (atoi(value(name)) != 0); } int int_value(const char *option) const { return atoi(value(option)); }
int int_value(const char *name) const { return atoi(value(name)); } float float_value(const char *option) const { return atof(value(option)); }
float float_value(const char *name) const { return atof(value(name)); }
bool exists(const char *name) const;
// setting // setting
bool set_value(const char *name, const char *value, int priority, std::string &error_string); void set_value(const std::string &name, const std::string &value, int priority);
bool set_value(const char *name, int value, int priority, std::string &error_string); void set_value(const std::string &name, std::string &&value, int priority);
bool set_value(const char *name, float value, int priority, std::string &error_string); void set_value(const std::string &name, int value, int priority);
void set_flag(const char *name, uint32_t mask, uint32_t flags); void set_value(const std::string &name, float value, int priority);
void mark_changed(const char *name);
// misc // misc
static const char *unadorned(int x = 0) { return s_option_unadorned[std::min(x, MAX_UNADORNED_OPTIONS - 1)]; } static const char *unadorned(int x = 0) { return s_option_unadorned[std::min(x, MAX_UNADORNED_OPTIONS - 1)]; }
int options_count() const { return m_entrylist.count(); }
protected: protected:
// This is a hook to allow option value retrieval to be overridden for various reasons; this is a crude virtual void command_argument_processed() { }
// extensibility mechanism that should really be replaced by something better
enum class override_get_value_result
{
NONE,
OVERRIDE,
SKIP
};
virtual void value_changed(const std::string &name, const std::string &value) {}
virtual override_get_value_result override_get_value(const char *name, std::string &value) const { return override_get_value_result::NONE; }
virtual bool override_set_value(const char *name, const std::string &value) { return false; }
private: private:
class simple_entry : public entry
{
public:
// construction/destruction
simple_entry(std::vector<std::string> &&names, const char *description, core_options::option_type type, std::string &&defdata, std::string &&minimum, std::string &&maximum);
simple_entry(const simple_entry &) = delete;
simple_entry(simple_entry &&) = delete;
simple_entry& operator=(const simple_entry &) = delete;
simple_entry& operator=(simple_entry &&) = delete;
~simple_entry();
// getters
virtual const char *value() const override;
virtual const char *minimum() const override;
virtual const char *maximum() const override;
virtual const std::string &default_value() const override;
virtual void set_default_value(std::string &&newvalue) override;
protected:
virtual void internal_set_value(std::string &&newvalue) override;
private:
// internal state
std::string m_data; // data for this item
std::string m_defdata; // default data for this item
std::string m_minimum; // minimum value
std::string m_maximum; // maximum value
};
// used internally in core_options
enum class condition_type
{
NONE,
WARN,
ERR
};
// internal helpers // internal helpers
void reset(); void add_to_entry_map(std::string &&name, entry::shared_ptr &entry);
void append_entry(entry &newentry); void do_set_value(entry &curentry, std::string &&data, int priority, std::ostream &error_stream, condition_type &condition);
void copyfrom(const core_options &src); void throw_options_exception_if_appropriate(condition_type condition, std::ostringstream &error_stream);
bool validate_and_set_data(entry &curentry, std::string &&newdata, int priority, std::string &error_string);
// internal state // internal state
simple_list<entry> m_entrylist; // head of list of entries std::vector<entry::shared_ptr> m_entries; // cannonical list of entries
std::unordered_map<std::string,entry *> m_entrymap; // map for fast lookup std::unordered_map<std::string, entry::weak_ptr> m_entrymap; // map for fast lookup
std::string m_command; // command found std::string m_command; // command found
std::vector<std::string> m_command_arguments; // command arguments std::vector<std::string> m_command_arguments; // command arguments
static const char *const s_option_unadorned[]; // array of unadorned option "names" static const char *const s_option_unadorned[]; // array of unadorned option "names"
}; };
// static structure describing a single option with its description and default value
struct options_entry
{
const char * name; // name on the command line
const char * defvalue; // default value of this argument
core_options::option_type type; // type of option
const char * description; // description for -showusage
};
// legacy option types
const core_options::option_type OPTION_INVALID = core_options::option_type::INVALID;
const core_options::option_type OPTION_HEADER = core_options::option_type::HEADER;
const core_options::option_type OPTION_COMMAND = core_options::option_type::COMMAND;
const core_options::option_type OPTION_BOOLEAN = core_options::option_type::BOOLEAN;
const core_options::option_type OPTION_INTEGER = core_options::option_type::INTEGER;
const core_options::option_type OPTION_FLOAT = core_options::option_type::FLOAT;
const core_options::option_type OPTION_STRING = core_options::option_type::STRING;
#endif // MAME_LIB_UTIL_OPTIONS_H #endif // MAME_LIB_UTIL_OPTIONS_H

View File

@ -270,7 +270,7 @@ private:
// FIXME: should be elsewhere // FIXME: should be elsewhere
osd_module *select_module_options(const core_options &opts, const std::string &opt_name) osd_module *select_module_options(const core_options &opts, const std::string &opt_name)
{ {
std::string opt_val = opts.value(opt_name.c_str()); std::string opt_val = opts.exists(opt_name) ? opts.value(opt_name.c_str()) : "";
if (opt_val.compare("auto")==0) if (opt_val.compare("auto")==0)
opt_val = ""; opt_val = "";
else if (!m_mod_man.type_has_name(opt_name.c_str(), opt_val.c_str())) else if (!m_mod_man.type_has_name(opt_name.c_str(), opt_val.c_str()))

View File

@ -85,7 +85,6 @@ renderer_bgfx::renderer_bgfx(std::shared_ptr<osd_window> w)
, m_avi_writer(nullptr) , m_avi_writer(nullptr)
, m_avi_target(nullptr) , m_avi_target(nullptr)
{ {
m_options = downcast<osd_options &>(assert_window()->machine().options());
} }
//============================================================ //============================================================

View File

@ -408,14 +408,12 @@ void sdl_osd_interface::init(running_machine &machine)
// determine if we are benchmarking, and adjust options appropriately // determine if we are benchmarking, and adjust options appropriately
int bench = options().bench(); int bench = options().bench();
std::string error_string;
if (bench > 0) if (bench > 0)
{ {
options().set_value(OPTION_THROTTLE, false, OPTION_PRIORITY_MAXIMUM, error_string); options().set_value(OPTION_THROTTLE, false, OPTION_PRIORITY_MAXIMUM);
options().set_value(OSDOPTION_SOUND, "none", OPTION_PRIORITY_MAXIMUM, error_string); options().set_value(OSDOPTION_SOUND, "none", OPTION_PRIORITY_MAXIMUM);
options().set_value(OSDOPTION_VIDEO, "none", OPTION_PRIORITY_MAXIMUM, error_string); options().set_value(OSDOPTION_VIDEO, "none", OPTION_PRIORITY_MAXIMUM);
options().set_value(OPTION_SECONDS_TO_RUN, bench, OPTION_PRIORITY_MAXIMUM, error_string); options().set_value(OPTION_SECONDS_TO_RUN, bench, OPTION_PRIORITY_MAXIMUM);
assert(error_string.c_str()[0] == 0);
} }
// Some driver options - must be before audio init! // Some driver options - must be before audio init!

View File

@ -515,23 +515,20 @@ void windows_osd_interface::init(running_machine &machine)
// determine if we are benchmarking, and adjust options appropriately // determine if we are benchmarking, and adjust options appropriately
int bench = options.bench(); int bench = options.bench();
std::string error_string;
if (bench > 0) if (bench > 0)
{ {
options.set_value(OPTION_THROTTLE, false, OPTION_PRIORITY_MAXIMUM, error_string); options.set_value(OPTION_THROTTLE, false, OPTION_PRIORITY_MAXIMUM);
options.set_value(OSDOPTION_SOUND, "none", OPTION_PRIORITY_MAXIMUM, error_string); options.set_value(OSDOPTION_SOUND, "none", OPTION_PRIORITY_MAXIMUM);
options.set_value(OSDOPTION_VIDEO, "none", OPTION_PRIORITY_MAXIMUM, error_string); options.set_value(OSDOPTION_VIDEO, "none", OPTION_PRIORITY_MAXIMUM);
options.set_value(OPTION_SECONDS_TO_RUN, bench, OPTION_PRIORITY_MAXIMUM, error_string); options.set_value(OPTION_SECONDS_TO_RUN, bench, OPTION_PRIORITY_MAXIMUM);
assert(error_string.empty());
} }
// determine if we are profiling, and adjust options appropriately // determine if we are profiling, and adjust options appropriately
int profile = options.profile(); int profile = options.profile();
if (profile > 0) if (profile > 0)
{ {
options.set_value(OPTION_THROTTLE, false, OPTION_PRIORITY_MAXIMUM, error_string); options.set_value(OPTION_THROTTLE, false, OPTION_PRIORITY_MAXIMUM);
options.set_value(OSDOPTION_NUMPROCESSORS, 1, OPTION_PRIORITY_MAXIMUM, error_string); options.set_value(OSDOPTION_NUMPROCESSORS, 1, OPTION_PRIORITY_MAXIMUM);
assert(error_string.empty());
} }
// thread priority // thread priority