API cleanups and miscellaneous fixes.

emu/ioport.cpp: Allow controller files to override input sequences for
inputs that don't use defaults, and to override the toggle setting for
digital inputs.

emu/config.cpp: Expose configuration level (mostly matters for
controller files), improved verbose diagnostic messages, and moved a few
things out of the global and preprocessor namespaces.

docs: Added documentation for some controller configuration file
features.  The device mapping feature documentation will be merged in at
some point.

util/unicode.cpp, emu/input.cpp: API cleanups.
This commit is contained in:
Vas Crabb 2021-07-15 04:09:18 +10:00 committed by Vas Crabb
parent 66554d3b84
commit 3715746131
36 changed files with 875 additions and 570 deletions

View File

@ -0,0 +1,229 @@
.. _ctrlrcfg:
Controller Configuration Files
==============================
.. contents:: :local:
.. _ctrlrcfg-intro:
Introduction
------------
Controller configuration files can be used to modify MAMEs default input
settings. Controller configuration files may be supplied with an input device
to provide more suitable defaults, or used as profiles that can be selected for
different situations. MAME includes a few sample controller configuration files
in the **ctrlr** folder, designed to provide useful defaults for certain
arcade-style controllers.
Controller configuration files are an XML application, using the ``.cfg``
filename extension. MAME searches for controller configuration files in the
directories specified using the ``ctrlrpath`` option. A controller
configuration file is selected by setting the ``ctrlr`` option to its filename,
excluding the ``.cfg`` extension (e.g. set the ``ctrlr`` option to
``scorpionxg`` to use **scorpionxg.cfg**). It is an error if the specified
controller configuration file does not exist, or if it contains no sections
applicable to the emulated system.
Controller configuration files use implementation-dependent input tokens. The
values available and their precise meanings depend on the exact version of MAME
used, the input devices connected, the selected input provider modules
(``keyboardprovider``, ``mouseprovider``, ``lightgunprovider`` and
``joystickprovider`` options), and possibly other settings.
.. _ctrlrcfg-structure:
Basic structure
---------------
Controller configuration files follow a similar format to the system
configuration files that MAME uses to save things like input settings and
bookkeeping data. This example shows the overall structure of a controller
configuration file:
.. code-block:: XML
<?xml version="1.0"?>
<mameconfig version="10">
<system name="default">
<input>
<!-- settings affecting all emulated systems go here -->
</input>
</system>
<system name="neogeo">
<input>
<!-- settings affecting neogeo and clones go here -->
</input>
</system>
<system name="intellec4.cpp">
<input>
<!-- settings affecting all systems defined in intellec4.cpp go here -->
</input>
</system>
</mameconfig>
The root of a controller configuration file must be a ``mameconfig`` element,
with a ``version`` attribute specifying the configuration format version
(currently ``10`` MAME will not load a file using a different version). The
``mameconfig`` element contains one or more ``system`` elements, each of which
has a ``name`` attribute specifying the system(s) it applies to. Each
``system`` element contains an ``input`` element which holds the actual
``remap`` and ``port`` configuration elements, which will be described later.
When launching an emulated system, MAME will apply configuration from ``system``
elements where the value of the ``name`` attribute meets one of the following
criteria:
* If the ``name`` attribute has the value ``default``, it will always be applied
(including for the system/software selection menus).
* If the value of the ``name`` attribute matches the systems short name, the
short name of its parent system, or the short name of its BIOS system (if
applicable).
* If the value of the ``name`` attribute matches the name of the source file
where the system is defined.
For example, for the game “DaeJeon! SanJeon SuJeon (AJTUE 990412 V1.000)”,
``system`` elements will be applied if their ``name`` attribute has the value
``default`` (applies to all systems), ``sanjeon`` (short name of the system
itself), ``sasissu`` (short name of the parent system), ``stvbios`` (short
name of the BIOS system), or ``stv.cpp`` (source file where the system is
defined).
As another example, a ``system`` element whose ``name`` attribute has the value
``zac2650.cpp`` will be applied for the systems “The Invaders”, “Super Invader
Attack (bootleg of The Invaders)”, and “Dodgem”.
Applicable ``system`` elements are applied in the order they appear in the
controller configuration file. Settings from elements that appear later in the
file may modify or override settings from elements that appear earlier. Within
a ``system`` element, ``remap`` elements are applied before ``port`` elements.
.. _ctrlrcfg-substitute:
Substituting default controls
-----------------------------
You can use a ``remap`` element to substitute one host input for another in
MAMEs default input configuration. For example, this substitutes keys on the
numeric keypad for the cursor direction keys:
.. code-block:: XML
<input>
<remap origcode="KEYCODE_UP" newcode="KEYCODE_8PAD" />
<remap origcode="KEYCODE_DOWN" newcode="KEYCODE_2PAD" />
<remap origcode="KEYCODE_LEFT" newcode="KEYCODE_4PAD" />
<remap origcode="KEYCODE_RIGHT" newcode="KEYCODE_6PAD" />
</input>
The ``origcode`` attribute specifies the token for the host input to be
substituted, and the ``newcode`` attribute specifies the token for the
replacement host input. In this case, assignments using the cursor up, down,
left and right arrows will be replaced with the numeric 8, 2, 4 and 6 keys on
the numeric keypad, respectively.
Note that substitutions specified using ``remap`` elements only apply to inputs
that use MAMEs default assignment for the control type. That is, they only
apply to default assignments for control types set in the “Inputs (general)”
menu. They *do not* apply to default input assignments set in driver/device I/O
port definitions (using the ``PORT_CODE`` macro).
MAME applies ``remap`` elements found inside any applicable ``system`` element.
.. _ctrlrcfg-typeoverride:
Overriding defaults by control type
-----------------------------------
Use ``port`` elements with ``type`` attributes but without ``tag`` attributes to
override the default host input assignments for a controls:
.. code-block:: XML
<input>
<port type="UI_CONFIGURE">
<newseq type="standard">KEYCODE_TAB OR KEYCODE_1 KEYCODE_5</newseq>
</port>
<port type="UI_CANCEL">
<newseq type="standard">KEYCODE_ESC OR KEYCODE_2 KEYCODE_6</newseq>
</port>
<port type="P1_BUTTON1">
<newseq type="standard">KEYCODE_C OR JOYCODE_1_BUTTON1</newseq>
</port>
<port type="P1_BUTTON2">
<newseq type="standard">KEYCODE_LSHIFT OR JOYCODE_1_BUTTON2</newseq>
</port>
<port type="P1_BUTTON3">
<newseq type="standard">KEYCODE_Z OR JOYCODE_1_BUTTON3</newseq>
</port>
<port type="P1_BUTTON4">
<newseq type="standard">KEYCODE_X OR JOYCODE_1_BUTTON4</newseq>
</port>
</input>
This sets the following default input assignments:
Config Menu (User Interface)
Tab key, or 1 and 2 keys pressed simultaneously
UI Cancel (User Interface)
Escape key, or 2 and 6 keys pressed simultaneously
P1 Button 1 (Player 1 Controls)
C key, or joystick 1 button 1
P1 Button 2 (Player 1 Controls)
Left Shift key, or joystick 1 button 2
P1 Button 3 (Player 1 Controls)
Z key, or joystick 1 button 3
P1 Button 4 (Player 1 Controls)
X key, or joystick 1 button 4
Note that this will only apply for inputs that use MAMEs default assignment for
the control type. That is, ``port`` elements without ``tag`` attributes only
override default assignments for control types set in the “Inputs (general)”
menu. They *do not* override default input assignments set in driver/device I/O
port definitions (using the ``PORT_CODE`` macro).
MAME applies ``port`` elements without ``tag`` attributes found inside any
applicable ``system`` element.
.. _ctrlrcfg-ctrloverride:
Overriding defaults for specific controls
-----------------------------------------
Use ``port`` elements with ``tag``, ``type``, ``mask`` and ``defvalue``
attributes to override defaults for specific controls. These ``port`` elements
should only occur inside ``system`` elements that apply to particular systems or
source files (i.e. they should not occur inside ``system`` elements where the
``name`` attribute has the value ``default``). The default host input
assignments can be overridden, as well as the toggle setting for digital
controls.
The ``tag``, ``type``, ``mask`` and ``defvalue`` are used to identify the
affected input. You can find out the values to use for a particular input by
changing its assigned host input, exiting MAME, and checking the values in the
system configuration file. Note that these values are not guaranteed to be
stable, and may change between MAME versions.
Heres an example that overrides defaults for 280-ZZZAP:
.. code-block:: XML
<system name="280zzzap">
<input>
<port tag=":IN0" type="P1_BUTTON2" mask="16" defvalue="0" toggle="no" />
<port tag=":IN1" type="P1_PADDLE" mask="255" defvalue="127">
<newseq type="increment">KEYCODE_K</newseq>
<newseq type="decrement">KEYCODE_J</newseq>
</port>
</input>
</system>
This sets the host inputs to steer left and right to the K and J keys,
respectively, and disables the toggle setting for the gear shift input.

View File

@ -2,13 +2,14 @@ Advanced configuration
----------------------
.. toctree::
:titlesonly:
:titlesonly:
multiconfig
paths
shiftertoggle
bgfx
hlsl
glsl
devicemap
linux-lightguns
multiconfig
paths
shiftertoggle
bgfx
hlsl
glsl
ctrlr_config
devicemap
linux-lightguns

View File

@ -32,7 +32,6 @@ patterns to avoid having your shell try to expand them against filenames (e.g.
.. _mame-commandline-paths:
File Names and Directory Paths
------------------------------
@ -1087,7 +1086,7 @@ Core Search Path Options
.. _mame-commandline-artpath:
**-artpath** *<path>* *<path>*
**-artpath** *<path>*
Specifies one or more paths within which to find external layout and artwork
files. Multiple paths can be specified by separating them with semicolons.
@ -1104,8 +1103,9 @@ Core Search Path Options
**-ctrlrpath** *<path>*
Specifies one or more paths within which to find default input configuration
Specifies one or more paths within which to find controller configuration
files. Multiple paths can be specified by separating them with semicolons.
Used in conjunction with the ``-ctrlr`` option.
The default is ``ctrlr`` (that is, a directory ``ctrlr`` in the current
working directory).
@ -2942,11 +2942,13 @@ Core Input Options
**-ctrlr** *<controller>*
Enables support for special controllers. Configuration files are loaded from
the ctrlrpath. They are in the same format as the .cfg files that are
saved, but only control configuration data is read from the file.
Specifies a controller configuration file, typically used to set more
suitable default input assignments for special controllers. Directories
specified using the ``ctrlrpath`` option are searched. Controller
configuration files use a similar format to ``.cfg`` used to save system
settings. See :ref:`ctrlrcfg` for more details.
The default is ``NULL`` (no controller file).
The default is ``NULL`` (no controller configuration file).
Example:
.. code-block:: bash

View File

@ -223,7 +223,10 @@ void laserdisc_device::device_start()
init_audio();
// register callbacks
machine().configuration().config_register("laserdisc", config_load_delegate(&laserdisc_device::config_load, this), config_save_delegate(&laserdisc_device::config_save, this));
machine().configuration().config_register(
"laserdisc",
configuration_manager::load_delegate(&laserdisc_device::config_load, this),
configuration_manager::save_delegate(&laserdisc_device::config_save, this));
}
@ -1040,20 +1043,16 @@ void laserdisc_device::process_track_data()
// configuration file
//-------------------------------------------------
void laserdisc_device::config_load(config_type cfg_type, util::xml::data_node const *parentnode)
void laserdisc_device::config_load(config_type cfg_type, config_level cfg_level, util::xml::data_node const *parentnode)
{
// we only care about game files
if (cfg_type != config_type::GAME)
return;
// might not have any data
if (parentnode == nullptr)
// we only care system-specific configuration
if ((cfg_type != config_type::SYSTEM) || !parentnode)
return;
// iterate over overlay nodes
for (util::xml::data_node const *ldnode = parentnode->get_child("device"); ldnode != nullptr; ldnode = ldnode->get_next_sibling("device"))
{
const char *devtag = ldnode->get_attribute_string("tag", "");
char const *const devtag = ldnode->get_attribute_string("tag", "");
if (strcmp(devtag, tag()) == 0)
{
// handle the overlay node
@ -1078,13 +1077,13 @@ void laserdisc_device::config_load(config_type cfg_type, util::xml::data_node co
void laserdisc_device::config_save(config_type cfg_type, util::xml::data_node *parentnode)
{
// we only care about game files
if (cfg_type != config_type::GAME)
// we only save system-specific configuration
if (cfg_type != config_type::SYSTEM)
return;
// create a node
util::xml::data_node *const ldnode = parentnode->add_child("device", nullptr);
if (ldnode != nullptr)
if (ldnode)
{
// output the basics
ldnode->set_attribute("tag", tag());

View File

@ -260,7 +260,7 @@ private:
void read_track_data();
static void *read_async_static(void *param, int threadid);
void process_track_data();
void config_load(config_type cfg_type, util::xml::data_node const *parentnode);
void config_load(config_type cfg_type, config_level cfg_level, util::xml::data_node const *parentnode);
void config_save(config_type cfg_type, util::xml::data_node *parentnode);
// configuration

View File

@ -39,7 +39,9 @@ bookkeeping_manager::bookkeeping_manager(running_machine &machine)
machine.save().save_item(NAME(m_dispensed_tickets));
// register for configuration
machine.configuration().config_register("counters", config_load_delegate(&bookkeeping_manager::config_load, this), config_save_delegate(&bookkeeping_manager::config_save, this));
machine.configuration().config_register("counters",
configuration_manager::load_delegate(&bookkeeping_manager::config_load, this),
configuration_manager::save_delegate(&bookkeeping_manager::config_save, this));
}
@ -80,36 +82,30 @@ void bookkeeping_manager::increment_dispensed_tickets(int delta)
and tickets
-------------------------------------------------*/
void bookkeeping_manager::config_load(config_type cfg_type, util::xml::data_node const *parentnode)
void bookkeeping_manager::config_load(config_type cfg_type, config_level cfg_level, util::xml::data_node const *parentnode)
{
util::xml::data_node const *coinnode, *ticketnode;
/* on init, reset the counters */
// on init, reset the counters
if (cfg_type == config_type::INIT)
{
memset(m_coin_count, 0, sizeof(m_coin_count));
m_dispensed_tickets = 0;
}
/* only care about game-specific data */
if (cfg_type != config_type::GAME)
// only care about system-specific data
if ((cfg_type != config_type::SYSTEM) || !parentnode)
return;
/* might not have any data */
if (parentnode == nullptr)
return;
/* iterate over coins nodes */
for (coinnode = parentnode->get_child("coins"); coinnode; coinnode = coinnode->get_next_sibling("coins"))
// iterate over coins nodes
for (util::xml::data_node const *coinnode = parentnode->get_child("coins"); coinnode; coinnode = coinnode->get_next_sibling("coins"))
{
int index = coinnode->get_attribute_int("index", -1);
if (index >= 0 && index < COIN_COUNTERS)
m_coin_count[index] = coinnode->get_attribute_int("number", 0);
}
/* get the single tickets node */
ticketnode = parentnode->get_child("tickets");
if (ticketnode != nullptr)
// get the single tickets node
util::xml::data_node const *const ticketnode = parentnode->get_child("tickets");
if (ticketnode)
m_dispensed_tickets = ticketnode->get_attribute_int("number", 0);
}
@ -121,19 +117,17 @@ void bookkeeping_manager::config_load(config_type cfg_type, util::xml::data_node
void bookkeeping_manager::config_save(config_type cfg_type, util::xml::data_node *parentnode)
{
int i;
/* only care about game-specific data */
if (cfg_type != config_type::GAME)
// only save system-specific data
if (cfg_type != config_type::SYSTEM)
return;
/* iterate over coin counters */
for (i = 0; i < COIN_COUNTERS; i++)
// iterate over coin counters
for (int i = 0; i < COIN_COUNTERS; i++)
{
if (m_coin_count[i] != 0)
{
util::xml::data_node *coinnode = parentnode->add_child("coins", nullptr);
if (coinnode != nullptr)
util::xml::data_node *const coinnode = parentnode->add_child("coins", nullptr);
if (coinnode)
{
coinnode->set_attribute_int("index", i);
coinnode->set_attribute_int("number", m_coin_count[i]);
@ -141,11 +135,11 @@ void bookkeeping_manager::config_save(config_type cfg_type, util::xml::data_node
}
}
/* output tickets */
// output tickets
if (m_dispensed_tickets != 0)
{
util::xml::data_node *tickets = parentnode->add_child("tickets", nullptr);
if (tickets != nullptr)
util::xml::data_node *const tickets = parentnode->add_child("tickets", nullptr);
if (tickets)
tickets->set_attribute_int("number", m_dispensed_tickets);
}
}

View File

@ -57,7 +57,7 @@ public:
// getters
running_machine &machine() const { return m_machine; }
private:
void config_load(config_type cfg_type, util::xml::data_node const *parentnode);
void config_load(config_type cfg_type, config_level cfg_level, util::xml::data_node const *parentnode);
void config_save(config_type cfg_type, util::xml::data_node *parentnode);
// internal state

View File

@ -39,14 +39,14 @@ configuration_manager::configuration_manager(running_machine &machine)
*
*************************************/
void configuration_manager::config_register(const char* nodename, config_load_delegate load, config_save_delegate save)
void configuration_manager::config_register(const char *nodename, load_delegate load, save_delegate save)
{
config_element element;
element.name = nodename;
element.load = std::move(load);
element.save = std::move(save);
m_typelist.push_back(element);
m_typelist.emplace_back(std::move(element));
}
@ -57,72 +57,69 @@ void configuration_manager::config_register(const char* nodename, config_load_de
*
*************************************/
int configuration_manager::load_settings()
bool configuration_manager::load_settings()
{
const char *controller = machine().options().ctrlr();
int loaded = 0;
/* loop over all registrants and call their init function */
// loop over all registrants and call their init function
for (const auto &type : m_typelist)
type.load(config_type::INIT, nullptr);
type.load(config_type::INIT, config_level::DEFAULT, nullptr);
/* now load the controller file */
if (controller[0] != 0)
// now load the controller file
const char *controller = machine().options().ctrlr();
if (controller && *controller)
{
/* open the config file */
// open the config file
emu_file file(machine().options().ctrlr_path(), OPEN_FLAG_READ);
osd_printf_verbose("Attempting to parse: %s.cfg\n",controller);
osd_printf_verbose("Attempting to parse: %s.cfg\n", controller);
osd_file::error filerr = file.open(std::string(controller) + ".cfg");
if (filerr != osd_file::error::NONE)
throw emu_fatalerror("Could not load controller file %s.cfg", controller);
throw emu_fatalerror("Could not open controller file %s.cfg", controller);
/* load the XML */
// load the XML
if (!load_xml(file, config_type::CONTROLLER))
throw emu_fatalerror("Could not load controller file %s.cfg", controller);
}
/* next load the defaults file */
// next load the defaults file
emu_file file(machine().options().cfg_directory(), OPEN_FLAG_READ);
osd_file::error filerr = file.open("default.cfg");
osd_printf_verbose("Attempting to parse: default.cfg\n");
if (filerr == osd_file::error::NONE)
load_xml(file, config_type::DEFAULT);
/* finally, load the game-specific file */
// finally, load the game-specific file
filerr = file.open(machine().basename() + ".cfg");
osd_printf_verbose("Attempting to parse: %s.cfg\n",machine().basename());
if (filerr == osd_file::error::NONE)
loaded = load_xml(file, config_type::GAME);
const bool loaded = (osd_file::error::NONE == filerr) && load_xml(file, config_type::SYSTEM);
/* loop over all registrants and call their final function */
// loop over all registrants and call their final function
for (const auto &type : m_typelist)
type.load(config_type::FINAL, nullptr);
type.load(config_type::FINAL, config_level::DEFAULT, nullptr);
/* if we didn't find a saved config, return 0 so the main core knows that it */
/* is the first time the game is run and it should display the disclaimer. */
// if we didn't find a saved config, return false so the main core knows that it
// is the first time the game is run and it should display the disclaimer.
return loaded;
}
void configuration_manager::save_settings()
{
/* loop over all registrants and call their init function */
// loop over all registrants and call their init function
for (const auto &type : m_typelist)
type.save(config_type::INIT, nullptr);
/* save the defaults file */
// save the defaults file
emu_file file(machine().options().cfg_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
osd_file::error filerr = file.open("default.cfg");
if (filerr == osd_file::error::NONE)
save_xml(file, config_type::DEFAULT);
/* finally, save the game-specific file */
// finally, save the system-specific file
filerr = file.open(machine().basename() + ".cfg");
if (filerr == osd_file::error::NONE)
save_xml(file, config_type::GAME);
save_xml(file, config_type::SYSTEM);
/* loop over all registrants and call their final function */
// loop over all registrants and call their final function
for (const auto &type : m_typelist)
type.save(config_type::FINAL, nullptr);
}
@ -135,24 +132,33 @@ void configuration_manager::save_settings()
*
*************************************/
int configuration_manager::load_xml(emu_file &file, config_type which_type)
bool configuration_manager::load_xml(emu_file &file, config_type which_type)
{
/* read the file */
// read the file
util::xml::file::ptr const root(util::xml::file::read(file, nullptr));
if (!root)
return 0;
{
osd_printf_verbose("Error parsing XML configuration file %s\n", file.filename());
return false;
}
/* find the config node */
// find the config node
util::xml::data_node const *const confignode = root->get_child("mameconfig");
if (!confignode)
return 0;
{
osd_printf_verbose("Could not find root mameconfig element in configuration file %s\n", file.filename());
return false;
}
/* validate the config data version */
// validate the config data version
int const version = confignode->get_attribute_int("version", 0);
if (version != CONFIG_VERSION)
return 0;
{
osd_printf_verbose("Configuration file %s has unsupported version %d\n", file.filename(), version);
return false;
}
/* strip off all the path crap from the source filename */
// strip off all the path crap from the source filename
const char *srcfile = strrchr(machine().system().type.source(), '/');
if (!srcfile)
srcfile = strrchr(machine().system().type.source(), '\\');
@ -163,38 +169,67 @@ int configuration_manager::load_xml(emu_file &file, config_type which_type)
else
srcfile++;
/* loop over all system nodes in the file */
// loop over all system nodes in the file
int count = 0;
for (util::xml::data_node const *systemnode = confignode->get_child("system"); systemnode; systemnode = systemnode->get_next_sibling("system"))
{
/* look up the name of the system here; skip if none */
// look up the name of the system here; skip if none
const char *name = systemnode->get_attribute_string("name", "");
/* based on the file type, determine whether we have a match */
// based on the file type, determine whether we have a match
config_level level = config_level::DEFAULT;
switch (which_type)
{
case config_type::GAME:
/* only match on the specific game name */
if (strcmp(name, machine().system().name) != 0)
case config_type::SYSTEM:
// only match on the specific system name
if (strcmp(name, machine().system().name))
{
osd_printf_verbose("Ignoring configuration for system %s in system configuration file %s\n", name, file.filename());
continue;
}
level = config_level::SYSTEM;
break;
case config_type::DEFAULT:
/* only match on default */
if (strcmp(name, "default") != 0)
// only match on default
if (strcmp(name, "default"))
{
osd_printf_verbose("Ignoring configuration for system %s in default configuration file %s\n", name, file.filename());
continue;
}
level = config_level::DEFAULT;
break;
case config_type::CONTROLLER:
{
// match on: default, system name, source file name, parent name, grandparent name
int clone_of;
/* match on: default, game name, source file name, parent name, grandparent name */
if (strcmp(name, "default") != 0 &&
strcmp(name, machine().system().name) != 0 &&
strcmp(name, srcfile) != 0 &&
((clone_of = driver_list::clone(machine().system())) == -1 || strcmp(name, driver_list::driver(clone_of).name) != 0) &&
(clone_of == -1 || ((clone_of = driver_list::clone(clone_of)) == -1) || strcmp(name, driver_list::driver(clone_of).name) != 0))
if (!strcmp(name, "default"))
{
osd_printf_verbose("Applying default configuration from controller configuration file %s\n", file.filename());
level = config_level::DEFAULT;
}
else if (!strcmp(name, machine().system().name))
{
osd_printf_verbose("Applying configuration for system %s from controller configuration file %s\n", name, file.filename());
level = config_level::SYSTEM;
}
else if (!strcmp(name, srcfile))
{
osd_printf_verbose("Applying configuration for source file %s from controller configuration file %s\n", name, file.filename());
level = config_level::SOURCE;
}
else if (
((clone_of = driver_list::clone(machine().system())) != -1 && !strcmp(name, driver_list::driver(clone_of).name)) ||
(clone_of != -1 && ((clone_of = driver_list::clone(clone_of)) != -1) && !strcmp(name, driver_list::driver(clone_of).name)))
{
osd_printf_verbose("Applying configuration for parent/BIOS %s from controller configuration file %s\n", name, file.filename());
level = (driver_list::driver(clone_of).flags & MACHINE_IS_BIOS_ROOT) ? config_level::BIOS : config_level::PARENT;
}
else
{
continue;
}
break;
}
@ -202,21 +237,18 @@ int configuration_manager::load_xml(emu_file &file, config_type which_type)
break;
}
/* log that we are processing this entry */
// log that we are processing this entry
if (DEBUG_CONFIG)
osd_printf_debug("Entry: %s -- processing\n", name);
/* loop over all registrants and call their load function */
// loop over all registrants and call their load function
for (const auto &type : m_typelist)
type.load(which_type, systemnode->get_child(type.name.c_str()));
type.load(which_type, level, systemnode->get_child(type.name.c_str()));
count++;
}
/* error if this isn't a valid game match */
if (count == 0)
return 0;
return 1;
// error if this isn't a valid match
return count != 0;
}
@ -227,43 +259,41 @@ int configuration_manager::load_xml(emu_file &file, config_type which_type)
*
*************************************/
int configuration_manager::save_xml(emu_file &file, config_type which_type)
bool configuration_manager::save_xml(emu_file &file, config_type which_type)
{
// if we cant't create a root node, bail
util::xml::file::ptr root(util::xml::file::create());
/* if we don't have a root, bail */
if (!root)
return 0;
return false;
/* create a config node */
// create a config node
util::xml::data_node *const confignode = root->add_child("mameconfig", nullptr);
if (!confignode)
return 0;
return false;
confignode->set_attribute_int("version", CONFIG_VERSION);
/* create a system node */
// create a system node
util::xml::data_node *const systemnode = confignode->add_child("system", nullptr);
if (!systemnode)
return 0;
return false;
systemnode->set_attribute("name", (which_type == config_type::DEFAULT) ? "default" : machine().system().name);
/* create the input node and write it out */
/* loop over all registrants and call their save function */
// loop over all registrants and call their save function
for (const auto &type : m_typelist)
{
util::xml::data_node *const curnode = systemnode->add_child(type.name.c_str(), nullptr);
if (!curnode)
return 0;
return false;
type.save(which_type, curnode);
/* if nothing was added, just nuke the node */
// if nothing was added, just nuke the node
if (!curnode->get_value() && !curnode->get_first_child() && !curnode->count_attributes())
curnode->delete_node();
}
/* flush the file */
// flush the file
root->write(file);
/* free and get out of here */
return 1;
// free and get out of here
return true;
}

View File

@ -15,60 +15,58 @@
#include "xmlfile.h"
/*************************************
*
* Constants
*
*************************************/
#define CONFIG_VERSION 10
enum class config_type
enum class config_type : int
{
INIT = 0, // opportunity to initialize things first
INIT, // opportunity to initialize things first
CONTROLLER, // loading from controller file
DEFAULT, // loading from default.cfg
GAME, // loading from game.cfg
SYSTEM, // loading from system.cfg
FINAL // opportunity to finish initialization
};
/*************************************
*
* Type definitions
*
*************************************/
enum class config_level : int
{
DEFAULT,
SOURCE,
BIOS,
PARENT,
SYSTEM
};
typedef delegate<void (config_type, util::xml::data_node const *)> config_load_delegate;
typedef delegate<void (config_type, util::xml::data_node *)> config_save_delegate;
// ======================> configuration_manager
class configuration_manager
{
struct config_element
{
std::string name; // node name
config_load_delegate load; // load callback
config_save_delegate save; // save callback
};
public:
typedef delegate<void (config_type, config_level, util::xml::data_node const *)> load_delegate;
typedef delegate<void (config_type, util::xml::data_node *)> save_delegate;
static inline constexpr int CONFIG_VERSION = 10;
// construction/destruction
configuration_manager(running_machine &machine);
void config_register(const char* nodename, config_load_delegate load, config_save_delegate save);
int load_settings();
void config_register(const char *nodename, load_delegate load, save_delegate save);
bool load_settings();
void save_settings();
// getters
running_machine &machine() const { return m_machine; }
private:
int load_xml(emu_file &file, config_type which_type);
int save_xml(emu_file &file, config_type which_type);
struct config_element
{
std::string name; // node name
load_delegate load; // load callback
save_delegate save; // save callback
};
bool load_xml(emu_file &file, config_type which_type);
bool save_xml(emu_file &file, config_type which_type);
// internal state
running_machine & m_machine; // reference to our machine
std::vector<config_element> m_typelist;
};
#endif /* MAME_EMU_CONFIG_H */
#endif // MAME_EMU_CONFIG_H

View File

@ -248,8 +248,8 @@ void render_crosshair::update_position()
{
// read all the lightgun values
bool gotx = false, goty = false;
for (auto &port : m_machine.ioport().ports())
for (ioport_field &field : port.second->fields())
for (auto const &port : m_machine.ioport().ports())
for (ioport_field const &field : port.second->fields())
if (field.player() == m_player && field.crosshair_axis() != CROSSHAIR_AXIS_NONE && field.enabled())
{
// handle X axis
@ -357,7 +357,7 @@ crosshair_manager::crosshair_manager(running_machine &machine)
/* determine who needs crosshairs */
for (auto &port : machine.ioport().ports())
for (ioport_field &field : port.second->fields())
for (ioport_field const &field : port.second->fields())
if (field.crosshair_axis() != CROSSHAIR_AXIS_NONE)
{
int player = field.player();
@ -374,7 +374,11 @@ crosshair_manager::crosshair_manager(running_machine &machine)
/* register callbacks for when we load/save configurations */
if (m_usage)
machine.configuration().config_register("crosshairs", config_load_delegate(&crosshair_manager::config_load, this), config_save_delegate(&crosshair_manager::config_save, this));
{
machine.configuration().config_register("crosshairs",
configuration_manager::load_delegate(&crosshair_manager::config_load, this),
configuration_manager::save_delegate(&crosshair_manager::config_save, this));
}
/* register the animation callback */
screen_device *first_screen = screen_device_enumerator(machine.root_device()).first();
@ -445,19 +449,15 @@ void crosshair_manager::render(screen_device &screen)
configuration file
-------------------------------------------------*/
void crosshair_manager::config_load(config_type cfg_type, util::xml::data_node const *parentnode)
void crosshair_manager::config_load(config_type cfg_type, config_level cfg_level, util::xml::data_node const *parentnode)
{
/* Note: crosshair_load() is only registered if croshairs are used */
// Note: crosshair_load() is only registered if croshairs are used
/* we only care about game files */
if (cfg_type != config_type::GAME)
// we only care about system-specific configuration
if ((cfg_type != config_type::SYSTEM) || !parentnode)
return;
/* might not have any data */
if (parentnode == nullptr)
return;
/* loop and get player crosshair info */
// loop and get player crosshair info
for (util::xml::data_node const *crosshairnode = parentnode->get_child("crosshair"); crosshairnode; crosshairnode = crosshairnode->get_next_sibling("crosshair"))
{
int const player = crosshairnode->get_attribute_int("player", -1);
@ -474,8 +474,7 @@ void crosshair_manager::config_load(config_type cfg_type, util::xml::data_node c
if (mode >= CROSSHAIR_VISIBILITY_OFF && mode <= CROSSHAIR_VISIBILITY_AUTO)
{
crosshair.set_mode(u8(mode));
/* set visibility as specified by mode */
/* auto mode starts with visibility off */
// set visibility as specified by mode - auto mode starts with visibility off
crosshair.set_visible(mode == CROSSHAIR_VISIBILITY_ON);
}
@ -485,7 +484,7 @@ void crosshair_manager::config_load(config_type cfg_type, util::xml::data_node c
}
}
/* get, check, and store auto visibility time */
// get, check, and store auto visibility time
util::xml::data_node const *crosshairnode = parentnode->get_child("autotime");
if (crosshairnode)
{
@ -503,10 +502,10 @@ void crosshair_manager::config_load(config_type cfg_type, util::xml::data_node c
void crosshair_manager::config_save(config_type cfg_type, util::xml::data_node *parentnode)
{
/* Note: crosshair_save() is only registered if crosshairs are used */
// Note: crosshair_save() is only registered if crosshairs are used
/* we only care about game files */
if (cfg_type != config_type::GAME)
// we only create system-specific configuration
if (cfg_type != config_type::SYSTEM)
return;
for (int player = 0; player < MAX_PLAYERS; player++)
@ -515,7 +514,7 @@ void crosshair_manager::config_save(config_type cfg_type, util::xml::data_node *
if (crosshair.is_used())
{
/* create a node */
// create a node
util::xml::data_node *const crosshairnode = parentnode->add_child("crosshair", nullptr);
if (crosshairnode != nullptr)
@ -537,20 +536,19 @@ void crosshair_manager::config_save(config_type cfg_type, util::xml::data_node *
changed = true;
}
/* if nothing changed, kill the node */
// if nothing changed, kill the node
if (!changed)
crosshairnode->delete_node();
}
}
}
/* always store autotime so that it stays at the user value if it is needed */
// always store autotime so that it stays at the user value if it is needed
if (m_auto_time != CROSSHAIR_VISIBILITY_AUTOTIME_DEFAULT)
{
/* create a node */
// create a node
util::xml::data_node *const crosshairnode = parentnode->add_child("autotime", nullptr);
if (crosshairnode != nullptr)
if (crosshairnode)
crosshairnode->set_attribute_int("val", m_auto_time);
}

View File

@ -118,7 +118,7 @@ private:
void exit();
void animate(screen_device &device, bool vblank_state);
void config_load(config_type cfg_type, util::xml::data_node const *parentnode);
void config_load(config_type cfg_type, config_level cfg_lvl, util::xml::data_node const *parentnode);
void config_save(config_type cfg_type, util::xml::data_node *parentnode);
// internal state

View File

@ -69,7 +69,8 @@ class address_map_entry;
class bookkeeping_manager;
// declared in config.h
enum class config_type;
enum class config_type : int;
enum class config_level : int;
class configuration_manager;
// declared in crsshair.h

View File

@ -86,7 +86,10 @@ image_manager::image_manager(running_machine &machine)
}
}
machine.configuration().config_register("image_directories", config_load_delegate(&image_manager::config_load, this), config_save_delegate(&image_manager::config_save, this));
machine.configuration().config_register(
"image_directories",
configuration_manager::load_delegate(&image_manager::config_load, this),
configuration_manager::save_delegate(&image_manager::config_save, this));
}
//-------------------------------------------------
@ -105,9 +108,9 @@ void image_manager::unload_all()
}
}
void image_manager::config_load(config_type cfg_type, util::xml::data_node const *parentnode)
void image_manager::config_load(config_type cfg_type, config_level cfg_level, util::xml::data_node const *parentnode)
{
if ((cfg_type == config_type::GAME) && (parentnode != nullptr))
if ((cfg_type == config_type::SYSTEM) && parentnode)
{
for (util::xml::data_node const *node = parentnode->get_child("device"); node; node = node->get_next_sibling("device"))
{
@ -136,8 +139,8 @@ void image_manager::config_load(config_type cfg_type, util::xml::data_node const
void image_manager::config_save(config_type cfg_type, util::xml::data_node *parentnode)
{
/* only care about game-specific data */
if (cfg_type == config_type::GAME)
// only save system-specific data
if (cfg_type == config_type::SYSTEM)
{
for (device_image_interface &image : image_interface_enumerator(machine().root_device()))
{

View File

@ -30,7 +30,7 @@ public:
std::string setup_working_directory();
private:
void config_load(config_type cfg_type, util::xml::data_node const *parentnode);
void config_load(config_type cfg_type, config_level cfg_level, util::xml::data_node const *parentnode);
void config_save(config_type cfg_type, util::xml::data_node *parentnode);
void options_extract();

View File

@ -1313,15 +1313,12 @@ void input_manager::seq_from_tokens(input_seq &seq, std::string_view string)
// controller based on device map table
//-------------------------------------------------
bool input_manager::map_device_to_controller(const devicemap_table_type *devicemap_table)
bool input_manager::map_device_to_controller(const devicemap_table_type &devicemap_table)
{
if (nullptr == devicemap_table)
return true;
for (devicemap_table_type::const_iterator it = devicemap_table->begin(); it != devicemap_table->end(); it++)
for (const auto &it : devicemap_table)
{
std::string_view deviceid = it->first;
std::string_view controllername = it->second;
std::string_view deviceid = it.first;
std::string_view controllername = it.second;
// tokenize the controller name into device class and index (i.e. controller name should be of the form "GUNCODE_1")
std::string token[2];
@ -1360,7 +1357,7 @@ bool input_manager::map_device_to_controller(const devicemap_table_type *devicem
for (int devnum = 0; devnum <= input_devclass->maxindex(); devnum++)
{
input_device *device = input_devclass->device(devnum);
if (device != nullptr && device->match_device_id(deviceid))
if (device && device->match_device_id(deviceid))
{
// remap devindex
input_devclass->remap_device_index(device->devindex(), devindex);

View File

@ -526,7 +526,7 @@ public:
void seq_from_tokens(input_seq &seq, std::string_view _token);
// misc
bool map_device_to_controller(const devicemap_table_type *devicemap_table = nullptr);
bool map_device_to_controller(const devicemap_table_type &devicemap_table);
private:
// internal helpers

View File

@ -422,8 +422,7 @@ void input_type_entry::restore_default_seq() noexcept
//-------------------------------------------------
digital_joystick::digital_joystick(int player, int number)
: m_next(nullptr),
m_player(player),
: m_player(player),
m_number(number),
m_current(0),
m_current4way(0),
@ -529,7 +528,7 @@ bool ioport_condition::eval() const
return true;
// otherwise, read the referenced port and switch off the condition type
ioport_value condvalue = m_port->read();
ioport_value const condvalue = m_port->read();
switch (m_condition)
{
case ALWAYS: return true;
@ -565,8 +564,7 @@ void ioport_condition::initialize(device_t &device)
//-------------------------------------------------
ioport_setting::ioport_setting(ioport_field &field, ioport_value _value, const char *_name)
: m_next(nullptr),
m_field(field),
: m_field(field),
m_value(_value),
m_name(_name)
{
@ -583,8 +581,7 @@ ioport_setting::ioport_setting(ioport_field &field, ioport_value _value, const c
//-------------------------------------------------
ioport_diplocation::ioport_diplocation(const char *name, u8 swnum, bool invert)
: m_next(nullptr),
m_name(name),
: m_name(name),
m_number(swnum),
m_invert(invert)
{
@ -926,7 +923,7 @@ void ioport_field::set_user_settings(const user_settings &settings) noexcept
if (!m_settinglist.empty() || m_type == IPT_ADJUSTER)
m_live->value = settings.value;
if (m_live->analog != nullptr)
if (m_live->analog)
{
// if there's analog data, extract the analog settings
m_live->analog->m_sensitivity = settings.sensitivity;
@ -953,7 +950,7 @@ const char *ioport_field::setting_name() const
assert(!m_settinglist.empty());
// scan the list of settings looking for a match on the current value
for (ioport_setting &setting : m_settinglist)
for (ioport_setting const &setting : m_settinglist)
if (setting.enabled())
if (setting.value() == m_live->value)
return setting.name();
@ -973,7 +970,7 @@ bool ioport_field::has_previous_setting() const
assert(!m_settinglist.empty());
// scan the list of settings looking for a match on the current value
for (ioport_setting &setting : m_settinglist)
for (ioport_setting const &setting : m_settinglist)
if (setting.enabled())
return (setting.value() != m_live->value);
@ -992,30 +989,32 @@ void ioport_field::select_previous_setting()
assert(!m_settinglist.empty());
// scan the list of settings looking for a match on the current value
ioport_setting *prevsetting = nullptr;
auto prevsetting = m_settinglist.end();
bool found_match = false;
for (ioport_setting &setting : m_settinglist)
if (setting.enabled())
for (auto setting = m_settinglist.begin(); m_settinglist.end() != setting; ++setting)
{
if (setting->enabled())
{
if (setting.value() == m_live->value)
if (setting->value() == m_live->value)
{
found_match = true;
if (prevsetting != nullptr)
if (m_settinglist.end() != prevsetting)
break;
}
prevsetting = &setting;
prevsetting = setting;
}
}
// if we didn't find a matching value, select the first
if (!found_match)
{
for (prevsetting = m_settinglist.first(); prevsetting != nullptr; prevsetting = prevsetting->next())
if (prevsetting->enabled())
break;
prevsetting = m_settinglist.begin();
while ((m_settinglist.end() != prevsetting) && !prevsetting->enabled())
++prevsetting;
}
// update the value to the previous one
if (prevsetting != nullptr)
if (m_settinglist.end() != prevsetting)
m_live->value = prevsetting->value();
}
@ -1032,7 +1031,8 @@ bool ioport_field::has_next_setting() const
// scan the list of settings looking for a match on the current value
bool found = false;
for (ioport_setting &setting : m_settinglist)
for (ioport_setting const &setting : m_settinglist)
{
if (setting.enabled())
{
if (found)
@ -1040,7 +1040,7 @@ bool ioport_field::has_next_setting() const
if (setting.value() == m_live->value)
found = true;
}
}
return false;
}
@ -1056,27 +1056,29 @@ void ioport_field::select_next_setting()
assert(!m_settinglist.empty());
// scan the list of settings looking for a match on the current value
ioport_setting *nextsetting = nullptr;
ioport_setting *setting;
for (setting = m_settinglist.first(); setting != nullptr; setting = setting->next())
if (setting->enabled())
if (setting->value() == m_live->value)
break;
auto setting = m_settinglist.begin();
while ((m_settinglist.end() != setting) && (!setting->enabled() || (setting->value() != m_live->value)))
++setting;
// if we found one, scan forward for the next valid one
if (setting != nullptr)
for (nextsetting = setting->next(); nextsetting != nullptr; nextsetting = nextsetting->next())
if (nextsetting->enabled())
break;
auto nextsetting = setting;
if (m_settinglist.end() != nextsetting)
{
++nextsetting;
while ((m_settinglist.end() != nextsetting) && !nextsetting->enabled())
++nextsetting;
}
// if we hit the end, search from the beginning
if (nextsetting == nullptr)
for (nextsetting = m_settinglist.first(); nextsetting != nullptr; nextsetting = nextsetting->next())
if (nextsetting->enabled())
break;
if (m_settinglist.end() == nextsetting)
{
nextsetting = m_settinglist.begin();
while ((m_settinglist.end() != nextsetting) && !nextsetting->enabled())
++nextsetting;
}
// update the value to the previous one
if (nextsetting != nullptr)
if (m_settinglist.end() != nextsetting)
m_live->value = nextsetting->value();
}
@ -1142,7 +1144,7 @@ void ioport_field::frame_update(ioport_value &result)
// toggle controls: flip the toggle state or advance to the next setting
if (m_live->toggle)
{
if (m_settinglist.count() == 0)
if (m_settinglist.empty())
m_live->value ^= m_mask;
else
select_next_setting();
@ -1199,7 +1201,7 @@ void ioport_field::frame_update(ioport_value &result)
// position
//-------------------------------------------------
float ioport_field::crosshair_read()
float ioport_field::crosshair_read() const
{
float value = m_live->analog->crosshair_read();
@ -1227,10 +1229,10 @@ float ioport_field::crosshair_read()
void ioport_field::expand_diplocation(const char *location, std::string &errorbuf)
{
// if nothing present, bail
if (location == nullptr)
if (!location)
return;
m_diploclist.reset();
m_diploclist.clear();
// parse the string
std::string name; // Don't move this variable inside the loop, lastname's lifetime depends on it being outside
@ -1245,23 +1247,21 @@ void ioport_field::expand_diplocation(const char *location, std::string &errorbu
comma = curentry + strlen(curentry);
// extract it to tempbuf
std::string tempstr;
tempstr.assign(curentry, comma - curentry);
std::string tempstr(curentry, comma - curentry);
// first extract the switch name if present
const char *number = tempstr.c_str();
const char *colon = strchr(tempstr.c_str(), ':');
// allocate and copy the name if it is present
if (colon != nullptr)
{
// allocate and copy the name if it is present
lastname = name.assign(number, colon - number).c_str();
number = colon + 1;
}
// otherwise, just copy the last name
else
{
// otherwise, just copy the last name
if (lastname == nullptr)
{
errorbuf.append(string_format("Switch location '%s' missing switch name!\n", location));
@ -1284,7 +1284,7 @@ void ioport_field::expand_diplocation(const char *location, std::string &errorbu
errorbuf.append(string_format("Switch location '%s' has invalid format!\n", location));
// allocate a new entry
m_diploclist.append(*new ioport_diplocation(name.c_str(), swnum, invert));
m_diploclist.emplace_back(name.c_str(), swnum, invert);
entries++;
// advance to the next item
@ -1492,7 +1492,7 @@ void ioport_port::frame_update()
m_live->digital = 0;
// now loop back and modify based on the inputs
for (ioport_field &field : fields())
for (ioport_field &field : m_fieldlist)
field.frame_update(m_live->digital);
}
@ -1620,15 +1620,15 @@ ioport_port_live::ioport_port_live(ioport_port &port)
// allocate analog state if it's analog
analog_field *analog = nullptr;
if (field.is_analog())
analog = &analoglist.append(*new analog_field(field));
analog = &analoglist.emplace_back(field);
// allocate a dynamic field for reading
if (field.has_dynamic_read())
readlist.append(*new dynamic_field(field));
readlist.emplace_back(field);
// allocate a dynamic field for writing
if (field.has_dynamic_write())
writelist.append(*new dynamic_field(field));
writelist.emplace_back(field);
// let the field initialize its live state
field.init_live_state(analog);
@ -1726,7 +1726,7 @@ time_t ioport_manager::initialize()
const char *joystick_map_default = machine().options().joystick_map();
if (joystick_map_default[0] == 0 || strcmp(joystick_map_default, "auto") == 0)
for (auto &port : m_portlist)
for (ioport_field &field : port.second->fields())
for (ioport_field const &field : port.second->fields())
if (field.live().joystick != nullptr && field.rotated())
{
input_class_joystick &devclass = downcast<input_class_joystick &>(machine().input().device_class(DEVICE_CLASS_JOYSTICK));
@ -1735,7 +1735,10 @@ time_t ioport_manager::initialize()
}
// register callbacks for when we load configurations
machine().configuration().config_register("input", config_load_delegate(&ioport_manager::load_config, this), config_save_delegate(&ioport_manager::save_config, this));
machine().configuration().config_register(
"input",
configuration_manager::load_delegate(&ioport_manager::load_config, this),
configuration_manager::save_delegate(&ioport_manager::save_config, this));
// open playback and record files if specified
time_t basetime = playback_init();
@ -1800,7 +1803,7 @@ void ioport_manager::init_autoselect_devices(int type1, int type2, int type3, co
// only scan the list if we haven't already enabled this class of control
if (!autoenable_class->enabled())
for (auto &port : m_portlist)
for (ioport_field &field : port.second->fields())
for (ioport_field const &field : port.second->fields())
// if this port type is in use, apply the autoselect criteria
if ((type1 != 0 && field.type() == type1) || (type2 != 0 && field.type() == type2) || (type3 != 0 && field.type() == type3))
@ -1921,7 +1924,7 @@ bool ioport_manager::type_pressed(ioport_type type, int player)
bool ioport_manager::type_class_present(ioport_type_class inputclass) const noexcept
{
for (auto &port : m_portlist)
for (ioport_field &field : port.second->fields())
for (ioport_field const &field : port.second->fields())
if (field.type_class() == inputclass)
return true;
return false;
@ -1937,7 +1940,7 @@ int ioport_manager::count_players() const noexcept
{
int max_player = 0;
for (auto &port : m_portlist)
for (ioport_field &field : port.second->fields())
for (ioport_field const &field : port.second->fields())
if (field.type_class() == INPUT_CLASS_CONTROLLER && max_player <= field.player() + 1)
max_player = field.player() + 1;
@ -1958,7 +1961,7 @@ digital_joystick &ioport_manager::digjoystick(int player, int number)
return joystick;
// create a new one
return m_joystick_list.append(*new digital_joystick(player, number));
return m_joystick_list.emplace_back(player, number);
}
@ -2045,7 +2048,7 @@ s32 ioport_manager::frame_interpolate(s32 oldval, s32 newval)
// data from the XML nodes
//-------------------------------------------------
void ioport_manager::load_config(config_type cfg_type, util::xml::data_node const *parentnode)
void ioport_manager::load_config(config_type cfg_type, config_level cfg_level, util::xml::data_node const *parentnode)
{
// in the completion phase, we finish the initialization with the final ports
if (cfg_type == config_type::FINAL)
@ -2062,24 +2065,20 @@ void ioport_manager::load_config(config_type cfg_type, util::xml::data_node cons
if (cfg_type == config_type::CONTROLLER)
{
// iterate over all the remap nodes
load_remap_table(parentnode);
load_remap_table(*parentnode);
std::unique_ptr<devicemap_table_type> devicemap_table = std::make_unique<devicemap_table_type>();
devicemap_table_type devicemap_table;
for (util::xml::data_node const *mapdevice_node = parentnode->get_child("mapdevice"); mapdevice_node != nullptr; mapdevice_node = mapdevice_node->get_next_sibling("mapdevice"))
{
const char *devicename = mapdevice_node->get_attribute_string("device", nullptr);
const char *controllername = mapdevice_node->get_attribute_string("controller", nullptr);
if (devicename != nullptr && controllername != nullptr)
{
devicemap_table->insert(std::make_pair(std::string(devicename), std::string(controllername)));
}
char const *const devicename = mapdevice_node->get_attribute_string("device", nullptr);
char const *const controllername = mapdevice_node->get_attribute_string("controller", nullptr);
if (devicename && controllername)
devicemap_table.emplace(devicename, controllername);
}
// map device to controller if we have a device map
if (!devicemap_table->empty())
{
machine().input().map_device_to_controller(devicemap_table.get());
}
if (!devicemap_table.empty())
machine().input().map_device_to_controller(devicemap_table);
}
// iterate over all the port nodes
@ -2099,20 +2098,22 @@ void ioport_manager::load_config(config_type cfg_type, util::xml::data_node cons
{
// with a valid type, parse out the new sequence
input_seq_type seqtype = token_to_seq_type(seqnode->get_attribute_string("type", ""));
if (seqtype != -1 && seqnode->get_value() != nullptr)
if ((seqtype != -1) && seqnode->get_value())
{
if (strcmp(seqnode->get_value(), "NONE") == 0)
if (!strcmp(seqnode->get_value(), "NONE"))
newseq[seqtype].reset();
else
machine().input().seq_from_tokens(newseq[seqtype], seqnode->get_value());
}
}
// if we're loading default ports, apply to the defaults
if (cfg_type != config_type::GAME)
load_default_config(portnode, type, player, newseq);
// load into the appropriate place for the config type/level
if (config_type::SYSTEM == cfg_type)
load_system_config(*portnode, type, player, newseq);
else if ((config_type::CONTROLLER == cfg_type) && (config_level::DEFAULT != cfg_level))
load_controller_config(*portnode, type, player, newseq);
else
load_game_config(portnode, type, player, newseq);
load_default_config(type, player, newseq);
}
// after applying the controller config, push that back into the backup, since that is
@ -2123,7 +2124,7 @@ void ioport_manager::load_config(config_type cfg_type, util::xml::data_node cons
entry.defseq(seqtype) = entry.seq(seqtype);
// load keyboard enable/disable state
if (cfg_type == config_type::GAME)
if (cfg_type == config_type::SYSTEM)
{
std::vector<bool> kbd_enable_set;
bool keyboard_enabled = false, missing_enabled = false;
@ -2191,11 +2192,11 @@ void ioport_manager::load_config(config_type cfg_type, util::xml::data_node cons
// global remapping table
//-------------------------------------------------
void ioport_manager::load_remap_table(util::xml::data_node const *parentnode)
void ioport_manager::load_remap_table(util::xml::data_node const &parentnode)
{
// count items first so we can allocate
int count = 0;
for (util::xml::data_node const *remapnode = parentnode->get_child("remap"); remapnode != nullptr; remapnode = remapnode->get_next_sibling("remap"))
for (util::xml::data_node const *remapnode = parentnode.get_child("remap"); remapnode != nullptr; remapnode = remapnode->get_next_sibling("remap"))
count++;
// if we have some, deal with them
@ -2207,7 +2208,7 @@ void ioport_manager::load_remap_table(util::xml::data_node const *parentnode)
// build up the remap table
count = 0;
for (util::xml::data_node const *remapnode = parentnode->get_child("remap"); remapnode != nullptr; remapnode = remapnode->get_next_sibling("remap"))
for (util::xml::data_node const *remapnode = parentnode.get_child("remap"); remapnode != nullptr; remapnode = remapnode->get_next_sibling("remap"))
{
input_code origcode = machine().input().code_from_token(remapnode->get_attribute_string("origcode", ""));
input_code newcode = machine().input().code_from_token(remapnode->get_attribute_string("newcode", ""));
@ -2228,14 +2229,15 @@ void ioport_manager::load_remap_table(util::xml::data_node const *parentnode)
//-------------------------------------------------
// load_default_config - apply configuration
// data to the default mappings
// load_default_config - apply input settings
// to defaults for all systems
//-------------------------------------------------
bool ioport_manager::load_default_config(util::xml::data_node const *portnode, int type, int player, const input_seq *newseq)
bool ioport_manager::load_default_config(int type, int player, const input_seq (&newseq)[SEQ_TYPE_TOTAL])
{
// find a matching port in the list
for (input_type_entry &entry : m_typelist)
{
if (entry.type() == type && entry.player() == player)
{
for (input_seq_type seqtype = SEQ_TYPE_STANDARD; seqtype < SEQ_TYPE_TOTAL; ++seqtype)
@ -2243,115 +2245,196 @@ bool ioport_manager::load_default_config(util::xml::data_node const *portnode, i
entry.set_seq(seqtype, newseq[seqtype]);
return true;
}
}
return false;
}
//-------------------------------------------------
// load_game_config - apply configuration
// data to the current set of input ports
// load_controller_config - apply controler
// profile settings to defaults
//-------------------------------------------------
void ioport_manager::load_game_config(util::xml::data_node const *portnode, int type, int player, const input_seq *newseq)
bool ioport_manager::load_controller_config(util::xml::data_node const &portnode, int type, int player, const input_seq (&newseq)[SEQ_TYPE_TOTAL])
{
// read the mask and defvalue attributes
ioport_value mask = portnode->get_attribute_int("mask", 0);
ioport_value defvalue = portnode->get_attribute_int("defvalue", 0);
// without a tag, apply to the defaults for all systems
char const *const tag = portnode.get_attribute_string("tag", nullptr);
if (!tag)
return load_default_config(type, player, newseq);
auto const apply =
[portnode, type, player, newseq, mask, defvalue] (ioport_port &port) -> bool
// ensure the port actually exists
auto const port(m_portlist.find(tag));
if (m_portlist.end() == port)
return false;
ioport_value const mask = portnode.get_attribute_int("mask", 0);
if (!mask)
return false;
// find the matching field
ioport_value const defvalue = portnode.get_attribute_int("defvalue", 0);
for (ioport_field &field : port->second->fields())
{
// find the matching mask and default value
if (field.type() == type && field.player() == player &&
field.mask() == mask && (field.defvalue() & mask) == (defvalue & mask))
{
for (ioport_field &field : port.fields())
// if a sequence was specified, override the developer-specified default for the field
for (input_seq_type seqtype = SEQ_TYPE_STANDARD; seqtype < SEQ_TYPE_TOTAL; ++seqtype)
{
// find the matching mask and default value
if (field.type() == type && field.player() == player &&
field.mask() == mask && (field.defvalue() & mask) == (defvalue & mask))
if (newseq[seqtype][0] != INPUT_CODE_INVALID)
field.set_defseq(seqtype, newseq[seqtype]);
}
// fetch configurable attributes
if (!field.live().analog)
{
// for non-analog fields
// can't practically set value here
// fetch yes/no for toggle setting
char const *const togstring = portnode.get_attribute_string("toggle", nullptr);
if (togstring && !strcmp(togstring, "yes"))
{
// if a sequence was specified, copy it in
for (input_seq_type seqtype = SEQ_TYPE_STANDARD; seqtype < SEQ_TYPE_TOTAL; ++seqtype)
if (newseq[seqtype][0] != INPUT_CODE_INVALID)
field.live().seq[seqtype] = newseq[seqtype];
// fetch configurable attributes
if (!field.live().analog)
{
// for non-analog fields
// fetch the value
field.live().value = portnode->get_attribute_int("value", field.defvalue());
// fetch yes/no for toggle setting
char const *const togstring = portnode->get_attribute_string("toggle", nullptr);
if (togstring)
field.live().toggle = !strcmp(togstring, "yes");
}
else
{
// for analog fields
// get base attributes
field.live().analog->m_delta = portnode->get_attribute_int("keydelta", field.delta());
field.live().analog->m_centerdelta = portnode->get_attribute_int("centerdelta", field.centerdelta());
field.live().analog->m_sensitivity = portnode->get_attribute_int("sensitivity", field.sensitivity());
// fetch yes/no for reverse setting
const char *revstring = portnode->get_attribute_string("reverse", nullptr);
if (revstring)
field.live().analog->m_reverse = !strcmp(revstring, "yes");
}
return true;
field.live().toggle = true;
field.m_flags |= ioport_field::FIELD_FLAG_TOGGLE;
}
else if (togstring && !strcmp(togstring, "no"))
{
field.live().toggle = false;
field.m_flags &= ~ioport_field::FIELD_FLAG_TOGGLE;
}
}
return false;
};
else
{
// for analog fields
#if 0 // changing this stuff causes issues because of the way it's tied up with the analog_field object
// get base attributes
field.live().analog->m_delta = field.m_delta = portnode.get_attribute_int("keydelta", field.delta());
field.live().analog->m_centerdelta = field.m_centerdelta = portnode.get_attribute_int("centerdelta", field.centerdelta());
field.live().analog->m_sensitivity = field.m_sensitivity = portnode.get_attribute_int("sensitivity", field.sensitivity());
// fetch yes/no for reverse setting
char const *const revstring = portnode.get_attribute_string("reverse", nullptr);
if (revstring && !strcmp(revstring, "yes"))
{
field.live().analog->m_reverse = true;
field.m_flags |= ioport_field::ANALOG_FLAG_REVERSE;
}
else if (revstring && !strcmp(revstring, "no"))
{
field.live().analog->m_reverse = false;
field.m_flags &= ~ioport_field::ANALOG_FLAG_REVERSE;
}
#endif
}
// successfully applied
return true;
}
}
// no matching field
return false;
}
//-------------------------------------------------
// load_system_config - apply saved input
// configuration for the current system
//-------------------------------------------------
void ioport_manager::load_system_config(util::xml::data_node const &portnode, int type, int player, const input_seq (&newseq)[SEQ_TYPE_TOTAL])
{
// system-specific configuration should always apply by port/field
char const *const tag = portnode.get_attribute_string("tag", nullptr);
ioport_value const mask = portnode.get_attribute_int("mask", 0);
ioport_value const defvalue = portnode.get_attribute_int("defvalue", 0);
if (!tag || !mask)
return;
// find the port we want
char const *const tag = portnode->get_attribute_string("tag", nullptr);
if (tag)
auto const port(m_portlist.find(tag));
if (m_portlist.end() != port)
{
auto const port(m_portlist.find(tag));
if (m_portlist.end() != port)
for (ioport_field &field : port->second->fields())
{
apply(*port->second);
}
else
{
// see if this belongs to a slot card that isn't inserted
std::string_view parent_tag(tag);
auto pos(parent_tag.rfind(':'));
if (pos && (std::string_view::npos != pos))
// find the matching mask and default value
if (field.type() == type && field.player() == player &&
field.mask() == mask && (field.defvalue() & mask) == (defvalue & mask))
{
parent_tag = parent_tag.substr(0, pos);
if (!machine().root_device().subdevice(parent_tag))
// if a sequence was specified, copy it in
for (input_seq_type seqtype = SEQ_TYPE_STANDARD; seqtype < SEQ_TYPE_TOTAL; ++seqtype)
{
for (pos = parent_tag.rfind(':'); pos && (std::string_view::npos != pos); pos = parent_tag.rfind(':'))
{
std::string_view const child_tag(parent_tag.substr(pos + 1));
parent_tag = parent_tag.substr(0, pos);
device_t const *const parent_device(machine().root_device().subdevice(parent_tag));
if (parent_device)
{
device_slot_interface const *slot;
if (parent_device->interface(slot) && (slot->option_list().find(std::string(child_tag)) != slot->option_list().end()))
{
if (!m_deselected_card_config)
m_deselected_card_config = util::xml::file::create().release();
portnode->copy_into(*m_deselected_card_config);
}
break;
}
}
if (newseq[seqtype][0] != INPUT_CODE_INVALID)
field.live().seq[seqtype] = newseq[seqtype];
}
// fetch configurable attributes
if (!field.live().analog)
{
// for non-analog fields
// fetch the value
field.live().value = portnode.get_attribute_int("value", field.defvalue());
// fetch yes/no for toggle setting
char const *const togstring = portnode.get_attribute_string("toggle", nullptr);
if (togstring && !strcmp(togstring, "yes"))
field.live().toggle = true;
else if (togstring && !strcmp(togstring, "no"))
field.live().toggle = false;
}
else
{
// for analog fields
// get base attributes
field.live().analog->m_delta = portnode.get_attribute_int("keydelta", field.delta());
field.live().analog->m_centerdelta = portnode.get_attribute_int("centerdelta", field.centerdelta());
field.live().analog->m_sensitivity = portnode.get_attribute_int("sensitivity", field.sensitivity());
// fetch yes/no for reverse setting
char const *const revstring = portnode.get_attribute_string("reverse", nullptr);
if (revstring && !strcmp(revstring, "yes"))
field.live().analog->m_reverse = true;
else if (revstring && !strcmp(revstring, "no"))
field.live().analog->m_reverse = false;
}
break;
}
}
}
else
{
// if no tag, search them all
for (auto &port : m_portlist)
if (apply(*port.second))
break;
// see if this belongs to a slot card that isn't inserted
std::string_view parent_tag(tag);
auto pos(parent_tag.rfind(':'));
if (pos && (std::string_view::npos != pos))
{
parent_tag = parent_tag.substr(0, pos);
if (!machine().root_device().subdevice(parent_tag))
{
for (pos = parent_tag.rfind(':'); pos && (std::string_view::npos != pos); pos = parent_tag.rfind(':'))
{
std::string_view const child_tag(parent_tag.substr(pos + 1));
parent_tag = parent_tag.substr(0, pos);
device_t const *const parent_device(machine().root_device().subdevice(parent_tag));
if (parent_device)
{
device_slot_interface const *slot;
if (parent_device->interface(slot) && (slot->option_list().find(std::string(child_tag)) != slot->option_list().end()))
{
if (!m_deselected_card_config)
m_deselected_card_config = util::xml::file::create().release();
portnode.copy_into(*m_deselected_card_config);
}
break;
}
}
}
}
}
}
@ -2369,13 +2452,13 @@ void ioport_manager::load_game_config(util::xml::data_node const *portnode, int
void ioport_manager::save_config(config_type cfg_type, util::xml::data_node *parentnode)
{
// if no parentnode, ignore
if (parentnode == nullptr)
if (!parentnode)
return;
// default ports save differently
if (cfg_type == config_type::DEFAULT)
save_default_inputs(*parentnode);
else
else if (cfg_type == config_type::SYSTEM)
save_game_inputs(*parentnode);
}
@ -2481,7 +2564,7 @@ void ioport_manager::save_game_inputs(util::xml::data_node &parentnode)
// iterate over ports
for (auto &port : m_portlist)
for (ioport_field &field : port.second->fields())
for (ioport_field const &field : port.second->fields())
if (save_this_input_field_type(field.type()))
{
// determine if we changed
@ -2489,16 +2572,15 @@ void ioport_manager::save_game_inputs(util::xml::data_node &parentnode)
for (input_seq_type seqtype = SEQ_TYPE_STANDARD; seqtype < SEQ_TYPE_TOTAL; ++seqtype)
changed |= (field.seq(seqtype) != field.defseq(seqtype));
// non-analog changes
if (!field.is_analog())
{
// non-analog changes
changed |= ((field.live().value & field.mask()) != (field.defvalue() & field.mask()));
changed |= (field.live().toggle != field.toggle());
}
// analog changes
else
{
// analog changes
changed |= (field.live().analog->m_delta != field.delta());
changed |= (field.live().analog->m_centerdelta != field.centerdelta());
changed |= (field.live().analog->m_sensitivity != field.sensitivity());
@ -2510,7 +2592,7 @@ void ioport_manager::save_game_inputs(util::xml::data_node &parentnode)
{
// add a new port node
util::xml::data_node *const portnode = parentnode.add_child("port", nullptr);
if (portnode != nullptr)
if (portnode)
{
// add the identifying information and attributes
portnode->set_attribute("tag", port.second->tag());
@ -2523,18 +2605,17 @@ void ioport_manager::save_game_inputs(util::xml::data_node &parentnode)
if (field.seq(seqtype) != field.defseq(seqtype))
save_sequence(*portnode, seqtype, field.type(), field.seq(seqtype));
// write out non-analog changes
if (!field.is_analog())
{
// write out non-analog changes
if ((field.live().value & field.mask()) != (field.defvalue() & field.mask()))
portnode->set_attribute_int("value", field.live().value & field.mask());
if (field.live().toggle != field.toggle())
portnode->set_attribute("toggle", field.live().toggle ? "yes" : "no");
}
// write out analog changes
else
{
// write out analog changes
if (field.live().analog->m_delta != field.delta())
portnode->set_attribute_int("keydelta", field.live().analog->m_delta);
if (field.live().analog->m_centerdelta != field.centerdelta())
@ -3190,12 +3271,11 @@ ioport_configurer& ioport_configurer::field_add_code(input_seq_type which, input
ioport_configurer& ioport_configurer::setting_alloc(ioport_value value, const char *name)
{
// make sure we have a field
if (m_curfield == nullptr)
if (!m_curfield)
throw emu_fatalerror("alloc_setting called with no active field (value=%X name=%s)\n", value, name);
m_cursetting = new ioport_setting(*m_curfield, value & m_curfield->mask(), string_from_token(name));
// append a new setting
m_curfield->m_settinglist.append(*m_cursetting);
m_cursetting = &m_curfield->m_settinglist.emplace_back(*m_curfield, value & m_curfield->mask(), string_from_token(name));
return *this;
}
@ -3207,7 +3287,7 @@ ioport_configurer& ioport_configurer::setting_alloc(ioport_value value, const ch
ioport_configurer& ioport_configurer::set_condition(ioport_condition::condition_t condition, const char *tag, ioport_value mask, ioport_value value)
{
ioport_condition &target = (m_cursetting != nullptr) ? m_cursetting->condition() : m_curfield->condition();
ioport_condition &target = m_cursetting ? m_cursetting->condition() : m_curfield->condition();
target.set(condition, tag, mask, value);
return *this;
}
@ -3245,8 +3325,7 @@ ioport_configurer& ioport_configurer::onoff_alloc(const char *name, ioport_value
//-------------------------------------------------
dynamic_field::dynamic_field(ioport_field &field)
: m_next(nullptr),
m_field(field),
: m_field(field),
m_shift(0),
m_oldval(field.defvalue())
{
@ -3265,15 +3344,15 @@ dynamic_field::dynamic_field(ioport_field &field)
void dynamic_field::read(ioport_value &result)
{
// skip if not enabled
if (!m_field.enabled())
return;
if (m_field.enabled())
{
// call the callback to read a new value
ioport_value newval = m_field.m_read();
m_oldval = newval;
// call the callback to read a new value
ioport_value newval = m_field.m_read();
m_oldval = newval;
// merge in the bits (don't invert yet, as all digitals are inverted together)
result = (result & ~m_field.mask()) | ((newval << m_shift) & m_field.mask());
// merge in the bits (don't invert yet, as all digitals are inverted together)
result = (result & ~m_field.mask()) | ((newval << m_shift) & m_field.mask());
}
}
@ -3285,15 +3364,15 @@ void dynamic_field::read(ioport_value &result)
void dynamic_field::write(ioport_value newval)
{
// skip if not enabled
if (!m_field.enabled())
return;
// if the bits have changed, call the handler
newval = (newval & m_field.mask()) >> m_shift;
if (m_oldval != newval)
if (m_field.enabled())
{
m_field.m_write(m_field, m_field.m_write_param, m_oldval, newval);
m_oldval = newval;
// if the bits have changed, call the handler
newval = (newval & m_field.mask()) >> m_shift;
if (m_oldval != newval)
{
m_field.m_write(m_field, m_field.m_write_param, m_oldval, newval);
m_oldval = newval;
}
}
}
@ -3303,8 +3382,7 @@ void dynamic_field::write(ioport_value newval)
//-------------------------------------------------
analog_field::analog_field(ioport_field &field)
: m_next(nullptr),
m_field(field),
: m_field(field),
m_shift(0),
m_adjdefvalue(field.defvalue() & field.mask()),
m_adjmin(field.minval() & field.mask()),

View File

@ -20,8 +20,9 @@
#include <array>
#include <cstdint>
#include <cstring>
#include <vector>
#include <ctime>
#include <list>
#include <vector>
//**************************************************************************
@ -32,19 +33,19 @@
typedef u32 ioport_value;
// active high/low values for input ports
const ioport_value IP_ACTIVE_HIGH = 0x00000000;
const ioport_value IP_ACTIVE_LOW = 0xffffffff;
constexpr ioport_value IP_ACTIVE_HIGH = 0x00000000;
constexpr ioport_value IP_ACTIVE_LOW = 0xffffffff;
// maximum number of players supported
const int MAX_PLAYERS = 10;
constexpr int MAX_PLAYERS = 10;
// unicode constants
const char32_t UCHAR_PRIVATE = 0x100000;
const char32_t UCHAR_SHIFT_1 = UCHAR_PRIVATE + 0;
const char32_t UCHAR_SHIFT_2 = UCHAR_PRIVATE + 1;
const char32_t UCHAR_SHIFT_BEGIN = UCHAR_SHIFT_1;
const char32_t UCHAR_SHIFT_END = UCHAR_SHIFT_2;
const char32_t UCHAR_MAMEKEY_BEGIN = UCHAR_PRIVATE + 2;
constexpr char32_t UCHAR_PRIVATE = 0x100000;
constexpr char32_t UCHAR_SHIFT_1 = UCHAR_PRIVATE + 0;
constexpr char32_t UCHAR_SHIFT_2 = UCHAR_PRIVATE + 1;
constexpr char32_t UCHAR_SHIFT_BEGIN = UCHAR_SHIFT_1;
constexpr char32_t UCHAR_SHIFT_END = UCHAR_SHIFT_2;
constexpr char32_t UCHAR_MAMEKEY_BEGIN = UCHAR_PRIVATE + 2;
// sequence types for input_port_seq() call
@ -825,7 +826,6 @@ private:
class digital_joystick
{
DISABLE_COPYING(digital_joystick);
friend class simple_list<digital_joystick>;
public:
// directions
@ -848,7 +848,6 @@ public:
digital_joystick(int player, int number);
// getters
digital_joystick *next() const noexcept { return m_next; }
int player() const noexcept { return m_player; }
int number() const noexcept { return m_number; }
u8 current() const noexcept { return m_current; }
@ -862,7 +861,6 @@ public:
private:
// internal state
digital_joystick * m_next; // next joystick in the list
int m_player; // player number represented
int m_number; // joystick number represented
std::forward_list<std::reference_wrapper<ioport_field> > m_field[JOYDIR_COUNT]; // potential input fields for each direction
@ -933,15 +931,11 @@ private:
// a single setting for a configuration or DIP switch
class ioport_setting
{
DISABLE_COPYING(ioport_setting);
friend class simple_list<ioport_setting>;
public:
// construction/destruction
ioport_setting(ioport_field &field, ioport_value value, const char *name);
// getters
ioport_setting *next() const { return m_next; }
ioport_field &field() const { return m_field; }
device_t &device() const;
running_machine &machine() const;
@ -951,15 +945,14 @@ public:
const char *name() const { return m_name; }
// helpers
bool enabled() { return m_condition.eval(); }
bool enabled() const { return m_condition.eval(); }
private:
// internal state
ioport_setting * m_next; // pointer to next setting in sequence
ioport_field & m_field; // pointer back to the field that owns us
ioport_value m_value; // value of the bits in this setting
const char * m_name; // user-friendly name to display
ioport_condition m_condition; // condition under which this setting is valid
ioport_field & m_field; // pointer back to the field that owns us
ioport_value m_value; // value of the bits in this setting
const char * m_name; // user-friendly name to display
ioport_condition m_condition; // condition under which this setting is valid
};
@ -968,24 +961,19 @@ private:
// a mapping from a bit to a physical DIP switch description
class ioport_diplocation
{
DISABLE_COPYING(ioport_diplocation);
friend class simple_list<ioport_diplocation>;
public:
// construction/destruction
ioport_diplocation(const char *name, u8 swnum, bool invert);
// getters
ioport_diplocation *next() const { return m_next; }
const char *name() const { return m_name.c_str(); }
u8 number() const { return m_number; }
bool inverted() const { return m_invert; }
private:
ioport_diplocation * m_next; // pointer to the next bit
std::string m_name; // name of the physical DIP switch
u8 m_number; // physical switch number
bool m_invert; // is this an active-high DIP?
std::string m_name; // name of the physical DIP switch
u8 m_number; // physical switch number
bool m_invert; // is this an active-high DIP?
};
@ -996,18 +984,19 @@ class ioport_field
{
DISABLE_COPYING(ioport_field);
friend class simple_list<ioport_field>;
friend class ioport_manager;
friend class ioport_configurer;
friend class dynamic_field;
// flags for ioport_fields
static const int FIELD_FLAG_OPTIONAL = 0x0001; // set if this field is not required but recognized by hw
static const int FIELD_FLAG_COCKTAIL = 0x0002; // set if this field is relevant only for cocktail cabinets
static const int FIELD_FLAG_TOGGLE = 0x0004; // set if this field should behave as a toggle
static const int FIELD_FLAG_ROTATED = 0x0008; // set if this field represents a rotated control
static const int ANALOG_FLAG_REVERSE = 0x0010; // analog only: reverse the sense of the axis
static const int ANALOG_FLAG_RESET = 0x0020; // analog only: always preload in->default for relative axes, returning only deltas
static const int ANALOG_FLAG_WRAPS = 0x0040; // analog only: positional count wraps around
static const int ANALOG_FLAG_INVERT = 0x0080; // analog only: bitwise invert bits
static inline constexpr u32 FIELD_FLAG_OPTIONAL = 0x0001; // set if this field is not required but recognized by hw
static inline constexpr u32 FIELD_FLAG_COCKTAIL = 0x0002; // set if this field is relevant only for cocktail cabinets
static inline constexpr u32 FIELD_FLAG_TOGGLE = 0x0004; // set if this field should behave as a toggle
static inline constexpr u32 FIELD_FLAG_ROTATED = 0x0008; // set if this field represents a rotated control
static inline constexpr u32 ANALOG_FLAG_REVERSE = 0x0010; // analog only: reverse the sense of the axis
static inline constexpr u32 ANALOG_FLAG_RESET = 0x0020; // analog only: always preload in->default for relative axes, returning only deltas
static inline constexpr u32 ANALOG_FLAG_WRAPS = 0x0040; // analog only: positional count wraps around
static inline constexpr u32 ANALOG_FLAG_INVERT = 0x0080; // analog only: bitwise invert bits
public:
// construction/destruction
@ -1021,8 +1010,8 @@ public:
ioport_manager &manager() const;
running_machine &machine() const;
int modcount() const { return m_modcount; }
const simple_list<ioport_setting> &settings() const { return m_settinglist; }
const simple_list<ioport_diplocation> &diplocations() const { return m_diploclist; }
const std::vector<ioport_setting> &settings() const { return m_settinglist; }
const std::vector<ioport_diplocation> &diplocations() const { return m_diploclist; }
ioport_value mask() const { return m_mask; }
ioport_value defvalue() const { return m_defvalue; }
@ -1087,7 +1076,7 @@ public:
void select_previous_setting();
bool has_next_setting() const;
void select_next_setting();
float crosshair_read();
float crosshair_read() const;
void init_live_state(analog_field *analog);
void frame_update(ioport_value &result);
void reduce_mask(ioport_value bits_to_remove) { m_mask &= ~bits_to_remove; }
@ -1112,10 +1101,10 @@ private:
// internal state
ioport_field * m_next; // pointer to next field in sequence
ioport_port & m_port; // reference to the port that owns us
std::unique_ptr<ioport_field_live> m_live; // live state of field (nullptr if not live)
std::unique_ptr<ioport_field_live> m_live; // live state of field (nullptr if not live)
int m_modcount; // modification count
simple_list<ioport_setting> m_settinglist; // list of input_setting_configs
simple_list<ioport_diplocation> m_diploclist; // list of locations for various bits
std::vector<ioport_setting> m_settinglist; // list of input_setting_configs
std::vector<ioport_diplocation> m_diploclist; // list of locations for various bits
// generally-applicable data
ioport_value m_mask; // mask of bits belonging to the field
@ -1246,7 +1235,6 @@ private:
// live analog field information
class analog_field
{
friend class simple_list<analog_field>;
friend class ioport_manager;
friend void ioport_field::set_user_settings(const ioport_field::user_settings &settings) noexcept;
@ -1255,7 +1243,6 @@ public:
analog_field(ioport_field &field);
// getters
analog_field *next() const noexcept { return m_next; }
ioport_manager &manager() const noexcept { return m_field.manager(); }
ioport_field &field() const noexcept { return m_field; }
s32 sensitivity() const noexcept { return m_sensitivity; }
@ -1279,7 +1266,6 @@ private:
s32 apply_inverse_sensitivity(s32 value) const;
// internal state
analog_field * m_next; // link to the next analog state for this port
ioport_field & m_field; // pointer to the input field referenced
// adjusted values (right-justified and tweaked)
@ -1329,14 +1315,11 @@ private:
// live device field information
class dynamic_field
{
friend class simple_list<dynamic_field>;
public:
// construction/destruction
dynamic_field(ioport_field &field);
// getters
dynamic_field *next() const { return m_next; }
ioport_field &field() const { return m_field; }
// read/write
@ -1345,7 +1328,6 @@ public:
private:
// internal state
dynamic_field * m_next; // linked list of info for this port
ioport_field & m_field; // reference to the input field
u8 m_shift; // shift to apply to the final result
ioport_value m_oldval; // last value
@ -1361,9 +1343,9 @@ struct ioport_port_live
ioport_port_live(ioport_port &port);
// public state
simple_list<analog_field> analoglist; // list of analog port info
simple_list<dynamic_field> readlist; // list of dynamic read fields
simple_list<dynamic_field> writelist; // list of dynamic write fields
std::list<analog_field> analoglist; // list of analog port info
std::vector<dynamic_field> readlist; // list of dynamic read fields
std::vector<dynamic_field> writelist; // list of dynamic write fields
ioport_value defvalue; // combined default value across the port
ioport_value digital; // current value from all digital inputs
ioport_value outputvalue; // current value for outputs
@ -1420,10 +1402,11 @@ private:
input_seq_type token_to_seq_type(const char *string);
static const char *const seqtypestrings[];
void load_config(config_type cfg_type, util::xml::data_node const *parentnode);
void load_remap_table(util::xml::data_node const *parentnode);
bool load_default_config(util::xml::data_node const *portnode, int type, int player, const input_seq *newseq);
void load_game_config(util::xml::data_node const *portnode, int type, int player, const input_seq *newseq);
void load_config(config_type cfg_type, config_level cfg_level, util::xml::data_node const *parentnode);
void load_remap_table(util::xml::data_node const &parentnode);
bool load_default_config(int type, int player, const input_seq (&newseq)[SEQ_TYPE_TOTAL]);
bool load_controller_config(util::xml::data_node const &portnode, int type, int player, const input_seq (&newseq)[SEQ_TYPE_TOTAL]);
void load_system_config(util::xml::data_node const &portnode, int type, int player, const input_seq (&newseq)[SEQ_TYPE_TOTAL]);
void save_config(config_type cfg_type, util::xml::data_node *parentnode);
void save_sequence(util::xml::data_node &parentnode, input_seq_type type, ioport_type porttype, const input_seq &seq);
@ -1457,7 +1440,7 @@ private:
input_type_entry * m_type_to_entry[IPT_COUNT][MAX_PLAYERS]; // map from type/player to type state
// specific special global input states
simple_list<digital_joystick> m_joystick_list; // list of digital joysticks
std::list<digital_joystick> m_joystick_list; // list of digital joysticks
// frame time tracking
attotime m_last_frame_time; // time of the last frame callback

View File

@ -26,7 +26,10 @@
network_manager::network_manager(running_machine &machine)
: m_machine(machine)
{
machine.configuration().config_register("network", config_load_delegate(&network_manager::config_load, this), config_save_delegate(&network_manager::config_save, this));
machine.configuration().config_register(
"network",
configuration_manager::load_delegate(&network_manager::config_load, this),
configuration_manager::save_delegate(&network_manager::config_save, this));
}
//-------------------------------------------------
@ -34,9 +37,9 @@ network_manager::network_manager(running_machine &machine)
// configuration file
//-------------------------------------------------
void network_manager::config_load(config_type cfg_type, util::xml::data_node const *parentnode)
void network_manager::config_load(config_type cfg_type, config_level cfg_level, util::xml::data_node const *parentnode)
{
if ((cfg_type == config_type::GAME) && (parentnode != nullptr))
if ((cfg_type == config_type::SYSTEM) && parentnode)
{
for (util::xml::data_node const *node = parentnode->get_child("device"); node; node = node->get_next_sibling("device"))
{
@ -71,13 +74,13 @@ void network_manager::config_load(config_type cfg_type, util::xml::data_node con
void network_manager::config_save(config_type cfg_type, util::xml::data_node *parentnode)
{
/* only care about game-specific data */
if (cfg_type == config_type::GAME)
// only save about system-specific data
if (cfg_type == config_type::SYSTEM)
{
for (device_network_interface &network : network_interface_enumerator(machine().root_device()))
{
util::xml::data_node *const node = parentnode->add_child("device", nullptr);
if (node != nullptr)
if (node)
{
node->set_attribute("tag", network.device().tag());
node->set_attribute_int("interface", network.get_interface());

View File

@ -23,7 +23,7 @@ public:
// getters
running_machine &machine() const { return m_machine; }
private:
void config_load(config_type cfg_type, util::xml::data_node const *parentnode);
void config_load(config_type cfg_type, config_level cfg_lvl, util::xml::data_node const *parentnode);
void config_save(config_type cfg_type, util::xml::data_node *parentnode);
// internal state

View File

@ -3057,7 +3057,10 @@ render_manager::render_manager(running_machine &machine)
, m_ui_container(new render_container(*this))
{
// register callbacks
machine.configuration().config_register("video", config_load_delegate(&render_manager::config_load, this), config_save_delegate(&render_manager::config_save, this));
machine.configuration().config_register(
"video",
configuration_manager::load_delegate(&render_manager::config_load, this),
configuration_manager::save_delegate(&render_manager::config_save, this));
// create one container per screen
for (screen_device &screen : screen_device_enumerator(machine.root_device()))
@ -3312,10 +3315,10 @@ void render_manager::container_free(render_container *container)
// configuration file
//-------------------------------------------------
void render_manager::config_load(config_type cfg_type, util::xml::data_node const *parentnode)
void render_manager::config_load(config_type cfg_type, config_level cfg_level, util::xml::data_node const *parentnode)
{
// we only care about game files with matching nodes
if ((cfg_type != config_type::GAME) || !parentnode)
// we only care about system-specific configuration with matching nodes
if ((cfg_type != config_type::SYSTEM) || !parentnode)
return;
// check the UI target
@ -3368,8 +3371,8 @@ void render_manager::config_load(config_type cfg_type, util::xml::data_node cons
void render_manager::config_save(config_type cfg_type, util::xml::data_node *parentnode)
{
// we only care about game files
if (cfg_type != config_type::GAME)
// we only save system-specific configuration
if (cfg_type != config_type::SYSTEM)
return;
// write out the interface target

View File

@ -701,7 +701,7 @@ private:
void container_free(render_container *container);
// config callbacks
void config_load(config_type cfg_type, util::xml::data_node const *parentnode);
void config_load(config_type cfg_type, config_level cfg_lvl, util::xml::data_node const *parentnode);
void config_save(config_type cfg_type, util::xml::data_node *parentnode);
// internal state

View File

@ -4659,7 +4659,7 @@ void layout_view::item::resolve_tags()
if (m_input_port)
{
// if there's a matching unconditional field, cache it
for (ioport_field &field : m_input_port->fields())
for (ioport_field const &field : m_input_port->fields())
{
if (field.mask() & m_input_mask)
{

View File

@ -1090,7 +1090,10 @@ sound_manager::sound_manager(running_machine &machine) :
#endif
// register callbacks
machine.configuration().config_register("mixer", config_load_delegate(&sound_manager::config_load, this), config_save_delegate(&sound_manager::config_save, this));
machine.configuration().config_register(
"mixer",
configuration_manager::load_delegate(&sound_manager::config_load, this),
configuration_manager::save_delegate(&sound_manager::config_save, this));
machine.add_notifier(MACHINE_NOTIFY_PAUSE, machine_notify_delegate(&sound_manager::pause, this));
machine.add_notifier(MACHINE_NOTIFY_RESUME, machine_notify_delegate(&sound_manager::resume, this));
machine.add_notifier(MACHINE_NOTIFY_RESET, machine_notify_delegate(&sound_manager::reset, this));
@ -1356,14 +1359,10 @@ void sound_manager::resume()
// configuration file
//-------------------------------------------------
void sound_manager::config_load(config_type cfg_type, util::xml::data_node const *parentnode)
void sound_manager::config_load(config_type cfg_type, config_level cfg_level, util::xml::data_node const *parentnode)
{
// we only care about game files
if (cfg_type != config_type::GAME)
return;
// might not have any data
if (parentnode == nullptr)
// we only care system-specific configuration
if ((cfg_type != config_type::SYSTEM) || !parentnode)
return;
// iterate over channel nodes
@ -1388,29 +1387,28 @@ void sound_manager::config_load(config_type cfg_type, util::xml::data_node const
void sound_manager::config_save(config_type cfg_type, util::xml::data_node *parentnode)
{
// we only care about game files
if (cfg_type != config_type::GAME)
// we only save system-specific configuration
if (cfg_type != config_type::SYSTEM)
return;
// iterate over mixer channels
if (parentnode != nullptr)
for (int mixernum = 0; ; mixernum++)
{
mixer_input info;
if (!indexed_mixer_input(mixernum, info))
break;
float newvol = info.stream->input(info.inputnum).user_gain();
for (int mixernum = 0; ; mixernum++)
{
mixer_input info;
if (!indexed_mixer_input(mixernum, info))
break;
if (newvol != 1.0f)
float const newvol = info.stream->input(info.inputnum).user_gain();
if (newvol != 1.0f)
{
util::xml::data_node *const channelnode = parentnode->add_child("channel", nullptr);
if (channelnode)
{
util::xml::data_node *const channelnode = parentnode->add_child("channel", nullptr);
if (channelnode != nullptr)
{
channelnode->set_attribute_int("index", mixernum);
channelnode->set_attribute_float("newvol", newvol);
}
channelnode->set_attribute_int("index", mixernum);
channelnode->set_attribute_float("newvol", newvol);
}
}
}
}

View File

@ -808,7 +808,7 @@ private:
void resume();
// handle configuration load/save
void config_load(config_type cfg_type, util::xml::data_node const *parentnode);
void config_load(config_type cfg_type, config_level cfg_lvl, util::xml::data_node const *parentnode);
void config_save(config_type cfg_type, util::xml::data_node *parentnode);
// helper to adjust scale factor toward a goal

View File

@ -1706,7 +1706,7 @@ void validity_checker::validate_roms(device_t &root)
// analog input field
//-------------------------------------------------
void validity_checker::validate_analog_input_field(ioport_field &field)
void validity_checker::validate_analog_input_field(const ioport_field &field)
{
// analog ports must have a valid sensitivity
if (field.sensitivity() == 0)
@ -1787,7 +1787,7 @@ void validity_checker::validate_analog_input_field(ioport_field &field)
// setting
//-------------------------------------------------
void validity_checker::validate_dip_settings(ioport_field &field)
void validity_checker::validate_dip_settings(const ioport_field &field)
{
const char *demo_sounds = ioport_string_from_index(INPUT_STRING_Demo_Sounds);
const char *flipscreen = ioport_string_from_index(INPUT_STRING_Flip_Screen);
@ -1795,30 +1795,31 @@ void validity_checker::validate_dip_settings(ioport_field &field)
bool coin_error = false;
// iterate through the settings
for (ioport_setting &setting : field.settings())
for (auto setting = field.settings().begin(); field.settings().end() != setting; ++setting)
{
// note any coinage strings
int strindex = get_defstr_index(setting.name());
int strindex = get_defstr_index(setting->name());
if (strindex >= __input_string_coinage_start && strindex <= __input_string_coinage_end)
coin_list[strindex - __input_string_coinage_start] = 1;
// make sure demo sounds default to on
if (field.name() == demo_sounds && strindex == INPUT_STRING_On && field.defvalue() != setting.value())
if (field.name() == demo_sounds && strindex == INPUT_STRING_On && field.defvalue() != setting->value())
osd_printf_error("Demo Sounds must default to On\n");
// check for bad demo sounds options
if (field.name() == demo_sounds && (strindex == INPUT_STRING_Yes || strindex == INPUT_STRING_No))
osd_printf_error("Demo Sounds option must be Off/On, not %s\n", setting.name());
osd_printf_error("Demo Sounds option must be Off/On, not %s\n", setting->name());
// check for bad flip screen options
if (field.name() == flipscreen && (strindex == INPUT_STRING_Yes || strindex == INPUT_STRING_No))
osd_printf_error("Flip Screen option must be Off/On, not %s\n", setting.name());
osd_printf_error("Flip Screen option must be Off/On, not %s\n", setting->name());
// if we have a neighbor, compare ourselves to him
if (setting.next() != nullptr)
auto const nextsetting = std::next(setting);
if (field.settings().end() != nextsetting)
{
// check for inverted off/on dispswitch order
int next_strindex = get_defstr_index(setting.next()->name(), true);
int next_strindex = get_defstr_index(nextsetting->name(), true);
if (strindex == INPUT_STRING_On && next_strindex == INPUT_STRING_Off)
osd_printf_error("%s option must have Off/On options in the order: Off, On\n", field.name());
@ -1832,9 +1833,9 @@ void validity_checker::validate_dip_settings(ioport_field &field)
// check for proper coin ordering
else if (strindex >= __input_string_coinage_start && strindex <= __input_string_coinage_end && next_strindex >= __input_string_coinage_start && next_strindex <= __input_string_coinage_end &&
strindex >= next_strindex && setting.condition() == setting.next()->condition())
strindex >= next_strindex && setting->condition() == nextsetting->condition())
{
osd_printf_error("%s option has unsorted coinage %s > %s\n", field.name(), setting.name(), setting.next()->name());
osd_printf_error("%s option has unsorted coinage %s > %s\n", field.name(), setting->name(), nextsetting->name());
coin_error = true;
}
}
@ -1856,7 +1857,7 @@ void validity_checker::validate_dip_settings(ioport_field &field)
// stored within an ioport field or setting
//-------------------------------------------------
void validity_checker::validate_condition(ioport_condition &condition, device_t &device)
void validity_checker::validate_condition(const ioport_condition &condition, device_t &device)
{
// resolve the tag, then find a matching port
if (m_ioport_set.find(device.subtag(condition.tag())) == m_ioport_set.end())
@ -1916,7 +1917,7 @@ void validity_checker::validate_inputs(device_t &root)
}
// iterate through the fields on this port
for (ioport_field &field : port.second->fields())
for (ioport_field const &field : port.second->fields())
{
// verify analog inputs
if (field.is_analog())
@ -1973,7 +1974,7 @@ void validity_checker::validate_inputs(device_t &root)
validate_condition(field.condition(), device);
// verify conditions on the settings
for (ioport_setting &setting : field.settings())
for (ioport_setting const &setting : field.settings())
if (!setting.condition().none())
validate_condition(setting.condition(), device);

View File

@ -74,9 +74,9 @@ private:
void validate_rgb();
void validate_driver(device_t &root);
void validate_roms(device_t &root);
void validate_analog_input_field(ioport_field &field);
void validate_dip_settings(ioport_field &field);
void validate_condition(ioport_condition &condition, device_t &device);
void validate_analog_input_field(const ioport_field &field);
void validate_dip_settings(const ioport_field &field);
void validate_condition(const ioport_condition &condition, device_t &device);
void validate_inputs(device_t &root);
void validate_devices(machine_config &config);
void validate_device_types();

View File

@ -548,7 +548,7 @@ void output_header(std::ostream &out, bool dtd)
"\" mameconfig=\"%d\">\n",
XML_ROOT,
normalize_string(emulator_info::get_build_version()),
CONFIG_VERSION);
configuration_manager::CONFIG_VERSION);
}
@ -1269,7 +1269,7 @@ void output_input(std::ostream &out, const ioport_list &portlist)
{
int ctrl_type = CTRL_DIGITAL_BUTTONS;
bool ctrl_analog = false;
for (ioport_field &field : port.second->fields())
for (ioport_field const &field : port.second->fields())
{
// track the highest player number
if (nplayer < field.player() + 1)

View File

@ -334,7 +334,7 @@ void lua_engine::initialize_input(sol::table &emu)
[this] (ioport_field &f)
{
sol::table result = sol().create_table();
for (ioport_setting &setting : f.settings())
for (ioport_setting const &setting : f.settings())
if (setting.enabled())
result[setting.value()] = setting.name();
return result;

View File

@ -221,7 +221,7 @@ void menu_device_config::populate(float &customtop, float &custombottom)
{
dips++;
bool def(false);
for (ioport_setting &setting : field.settings())
for (ioport_setting const &setting : field.settings())
{
if (setting.value() == field.defvalue())
{
@ -237,7 +237,7 @@ void menu_device_config::populate(float &customtop, float &custombottom)
{
confs++;
bool def(false);
for (ioport_setting &setting : field.settings())
for (ioport_setting const &setting : field.settings())
{
if (setting.value() == field.defvalue())
{

View File

@ -218,8 +218,8 @@ void mame_ui_manager::init()
machine().add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(&mame_ui_manager::exit, this));
machine().configuration().config_register(
"ui_warnings",
config_load_delegate(&mame_ui_manager::config_load, this),
config_save_delegate(&mame_ui_manager::config_save, this));
configuration_manager::load_delegate(&mame_ui_manager::config_load, this),
configuration_manager::save_delegate(&mame_ui_manager::config_save, this));
// create mouse bitmap
uint32_t *dst = &m_mouse_bitmap.pix(0);
@ -258,10 +258,10 @@ void mame_ui_manager::exit()
// config_load - load configuration data
//-------------------------------------------------
void mame_ui_manager::config_load(config_type cfg_type, util::xml::data_node const *parentnode)
void mame_ui_manager::config_load(config_type cfg_type, config_level cfg_level, util::xml::data_node const *parentnode)
{
// make sure it's relevant and there's data available
if (config_type::GAME == cfg_type)
if (config_type::SYSTEM == cfg_type)
{
m_unemulated_features.clear();
m_imperfect_features.clear();
@ -302,7 +302,7 @@ void mame_ui_manager::config_load(config_type cfg_type, util::xml::data_node con
void mame_ui_manager::config_save(config_type cfg_type, util::xml::data_node *parentnode)
{
// only save system-level configuration when times are valid
if ((config_type::GAME == cfg_type) && (std::time_t(-1) != m_last_launch_time) && (std::time_t(-1) != m_last_warning_time))
if ((config_type::SYSTEM == cfg_type) && (std::time_t(-1) != m_last_launch_time) && (std::time_t(-1) != m_last_warning_time))
{
parentnode->set_attribute_int("launched", static_cast<long long>(m_last_launch_time));
parentnode->set_attribute_int("warned", static_cast<long long>(m_last_warning_time));

View File

@ -257,7 +257,7 @@ private:
// private methods
void exit();
void config_load(config_type cfg_type, util::xml::data_node const *parentnode);
void config_load(config_type cfg_type, config_level cfg_level, util::xml::data_node const *parentnode);
void config_save(config_type cfg_type, util::xml::data_node *parentnode);
template <typename... Params> void slider_alloc(Params &&...args) { m_sliders.push_back(std::make_unique<slider_state>(std::forward<Params>(args)...)); }

View File

@ -281,18 +281,21 @@ int uchar_from_utf16f(char32_t *uchar, const char16_t *utf16char, size_t count)
// into a Unicode string
//-------------------------------------------------
std::u32string ustr_from_utf8(const std::string &utf8str)
std::u32string ustr_from_utf8(std::string_view utf8str)
{
std::u32string result;
char const *utf8char(utf8str.c_str());
size_t remaining(utf8str.length());
while (remaining)
if (!utf8str.empty())
{
char32_t ch;
int const consumed(uchar_from_utf8(&ch, utf8char, remaining));
result.append(1, (consumed > 0) ? ch : char32_t(0x00fffdU));
utf8char += (consumed > 0) ? consumed : 1;
remaining -= (consumed > 0) ? consumed : 1;
char const *utf8char(&utf8str[0]);
auto remaining(utf8str.length());
while (remaining)
{
char32_t ch;
int const consumed(uchar_from_utf8(&ch, utf8char, remaining));
result.append(1, (consumed > 0) ? ch : char32_t(0x00fffdU));
utf8char += (consumed > 0) ? consumed : 1;
remaining -= (consumed > 0) ? consumed : 1;
}
}
return result;
}
@ -480,17 +483,6 @@ std::string utf8_from_wstring(const std::wstring &string)
}
//-------------------------------------------------
// normalize_unicode - uses utf8proc to normalize
// unicode
//-------------------------------------------------
std::string normalize_unicode(const std::string &s, unicode_normalization_form normalization_form, bool fold_case)
{
return internal_normalize_unicode(s.c_str(), s.length(), normalization_form, fold_case, false);
}
//-------------------------------------------------
// normalize_unicode - uses utf8proc to normalize
// unicode

View File

@ -59,7 +59,7 @@ int uchar_from_utf8(char32_t *uchar, const char *utf8char, size_t count);
int uchar_from_utf8(char32_t *uchar, std::string_view utf8str);
int uchar_from_utf16(char32_t *uchar, const char16_t *utf16char, size_t count);
int uchar_from_utf16f(char32_t *uchar, const char16_t *utf16char, size_t count);
std::u32string ustr_from_utf8(const std::string &utf8str);
std::u32string ustr_from_utf8(std::string_view utf8str);
// converting 32-bit Unicode chars to strings
int utf8_from_uchar(char *utf8string, size_t count, char32_t uchar);
@ -72,7 +72,6 @@ std::wstring wstring_from_utf8(const std::string &utf8string);
std::string utf8_from_wstring(const std::wstring &string);
// unicode normalization
std::string normalize_unicode(const std::string &s, unicode_normalization_form normalization_form, bool fold_case = false);
std::string normalize_unicode(const char *s, unicode_normalization_form normalization_form, bool fold_case = false);
std::string normalize_unicode(std::string_view s, unicode_normalization_form normalization_form, bool fold_case = false);

View File

@ -71,7 +71,7 @@ public:
private:
void create_console();
void build_menus();
void config_load(config_type cfgtype, util::xml::data_node const *parentnode);
void config_load(config_type cfgtype, config_level cfglevel, util::xml::data_node const *parentnode);
void config_save(config_type cfgtype, util::xml::data_node *parentnode);
running_machine *m_machine;
@ -129,8 +129,8 @@ void debugger_osx::init_debugger(running_machine &machine)
m_machine = &machine;
machine.configuration().config_register(
"debugger",
config_load_delegate(&debugger_osx::config_load, this),
config_save_delegate(&debugger_osx::config_save, this));
configuration_manager::load_delegate(&debugger_osx::config_load, this),
configuration_manager::save_delegate(&debugger_osx::config_save, this));
}
@ -305,9 +305,9 @@ void debugger_osx::build_menus()
// restore state based on configuration XML
//============================================================
void debugger_osx::config_load(config_type cfgtype, util::xml::data_node const *parentnode)
void debugger_osx::config_load(config_type cfgtype, config_level cfglevel, util::xml::data_node const *parentnode)
{
if ((config_type::GAME == cfgtype) && parentnode)
if ((config_type::SYSTEM == cfgtype) && parentnode)
{
if (m_console)
{
@ -331,7 +331,7 @@ void debugger_osx::config_load(config_type cfgtype, util::xml::data_node const *
void debugger_osx::config_save(config_type cfgtype, util::xml::data_node *parentnode)
{
if ((config_type::GAME == cfgtype) && m_console)
if ((config_type::SYSTEM == cfgtype) && m_console)
{
NSAutoreleasePool *const pool = [[NSAutoreleasePool alloc] init];
NSDictionary *info = [NSDictionary dictionaryWithObjectsAndKeys:[NSValue valueWithPointer:m_machine],

View File

@ -79,21 +79,17 @@ MainWindow *mainQtWindow = nullptr;
std::vector<std::unique_ptr<WindowQtConfig> > xmlConfigurations;
void xml_configuration_load(running_machine &machine, config_type cfg_type, util::xml::data_node const *parentnode)
void xml_configuration_load(running_machine &machine, config_type cfg_type, config_level cfg_level, util::xml::data_node const *parentnode)
{
// We only care about game files
if (cfg_type != config_type::GAME)
return;
// Might not have any data
if (!parentnode)
// We only care about system configuration files
if ((cfg_type != config_type::SYSTEM) || !parentnode)
return;
xmlConfigurations.clear();
// Configuration load
util::xml::data_node const *wnode = nullptr;
for (wnode = parentnode->get_child("window"); wnode != nullptr; wnode = wnode->get_next_sibling("window"))
for (wnode = parentnode->get_child("window"); wnode; wnode = wnode->get_next_sibling("window"))
{
WindowQtConfig::WindowType type = (WindowQtConfig::WindowType)wnode->get_attribute_int("type", WindowQtConfig::WIN_TYPE_UNKNOWN);
switch (type)
@ -114,8 +110,8 @@ void xml_configuration_load(running_machine &machine, config_type cfg_type, util
void xml_configuration_save(running_machine &machine, config_type cfg_type, util::xml::data_node *parentnode)
{
// We only write to game configurations
if (cfg_type != config_type::GAME)
// We only save system configuration
if (cfg_type != config_type::SYSTEM)
return;
for (int i = 0; i < xmlConfigurations.size(); i++)
@ -269,8 +265,8 @@ void debug_qt::init_debugger(running_machine &machine)
m_machine = &machine;
// Setup the configuration XML saving and loading
machine.configuration().config_register("debugger",
config_load_delegate(&xml_configuration_load, &machine),
config_save_delegate(&xml_configuration_save, &machine));
configuration_manager::load_delegate(&xml_configuration_load, &machine),
configuration_manager::save_delegate(&xml_configuration_save, &machine));
}