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:
parent
66554d3b84
commit
3715746131
229
docs/source/advanced/ctrlr_config.rst
Normal file
229
docs/source/advanced/ctrlr_config.rst
Normal file
@ -0,0 +1,229 @@
|
||||
.. _ctrlrcfg:
|
||||
|
||||
Controller Configuration Files
|
||||
==============================
|
||||
|
||||
.. contents:: :local:
|
||||
|
||||
|
||||
.. _ctrlrcfg-intro:
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
Controller configuration files can be used to modify MAME’s 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 system’s 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
|
||||
MAME’s 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 MAME’s 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 MAME’s 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.
|
||||
|
||||
Here’s 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.
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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());
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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()))
|
||||
{
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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()),
|
||||
|
103
src/emu/ioport.h
103
src/emu/ioport.h
@ -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
|
||||
|
@ -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());
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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())
|
||||
{
|
||||
|
@ -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));
|
||||
|
@ -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)...)); }
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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],
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user