summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author feos <vadosnaprimer@users.noreply.github.com>2022-02-27 18:12:25 +0300
committer GitHub <noreply@github.com>2022-02-28 02:12:25 +1100
commit300206e308c2c5f9ad8898fb62f1873be682df5a (patch)
treecb780133d4b724eb390bf84fa9c14a7b7ee4dc1a
parent029f4232fe9779cbe7d2f9cf2d3e991108da75dc (diff)
Lua engine: Make setting analog I/O port field values user-friendly. (#9322)
Exposed minimum/maximum values for analog fields. together with defvalue, they can be used to check range of values and neutral position. Previously you had to send a normalised value between -65535 and 65535 which would be scaled depending on machine specifics. You could read the scaled value from the port, but you couldn't send scaled values in. This allows scripts to set scaled values as seen by the machine.
-rw-r--r--docs/source/techspecs/luareference.rst13
-rw-r--r--src/emu/ioport.cpp60
-rw-r--r--src/emu/ioport.h8
-rw-r--r--src/frontend/mame/luaengine_input.cpp11
4 files changed, 71 insertions, 21 deletions
diff --git a/docs/source/techspecs/luareference.rst b/docs/source/techspecs/luareference.rst
index 68704b95951..bc896c34ebc 100644
--- a/docs/source/techspecs/luareference.rst
+++ b/docs/source/techspecs/luareference.rst
@@ -1962,7 +1962,7 @@ Wraps MAME’s ``ioport_field`` class, representing a field within an I/O port.
Instantiation
^^^^^^^^^^^^^
-manager.machine.ioport.ports[tag]:field[mask]
+manager.machine.ioport.ports[tag]:field(mask)
Gets a field for the given port by bit mask.
manager.machine.ioport.ports[tag].fields[name]
Gets a field for the given port by display name.
@@ -1974,6 +1974,9 @@ field:set_value(value)
Set the value of the I/O port field. For digital fields, the value is
compared to zero to determine whether the field should be active; for
analog fields, the value must be right-aligned and in the correct range.
+field:clear_value()
+ Clear programmatically overridden value and restore the field’s regular
+ behaviour.
field:set_input_seq(seqtype, seq)
Set the :ref:`input sequence <luareference-input-iptseq>` for the
specified sequence type. This is used to configure per-machine input
@@ -2018,9 +2021,13 @@ field.player (read-only)
field.mask (read-only)
Bits in the I/O port corresponding to this field.
field.defvalue (read-only)
- The field’s default value
+ The field’s default value.
+field.minvalue (read-only)
+ The minimum allowed value for analog fields, or nil for digital fields.
+field.maxvalue (read-only)
+ The maximum allowed value for analog fields, or nil for digital fields.
field.sensitivity (read-only)
- The sensitivity or gain for analog fields
+ The sensitivity or gain for analog fields.
field.way (read-only)
The number of directions allowed by the restrictor plate/gate for a digital
joystick, or zero (0) for other inputs.
diff --git a/src/emu/ioport.cpp b/src/emu/ioport.cpp
index f96b2a8d323..5999a75abe5 100644
--- a/src/emu/ioport.cpp
+++ b/src/emu/ioport.cpp
@@ -824,6 +824,20 @@ ioport_field::ioport_field(ioport_port &port, ioport_type type, ioport_value def
}
}
+
+//-------------------------------------------------
+// ~ioport_field - destructor
+//-------------------------------------------------
+
+ioport_field::~ioport_field()
+{
+}
+
+
+//-------------------------------------------------
+// set_value - programmatically set field value
+//-------------------------------------------------
+
void ioport_field::set_value(ioport_value value)
{
if (is_analog())
@@ -834,11 +848,15 @@ void ioport_field::set_value(ioport_value value)
//-------------------------------------------------
-// ~ioport_field - destructor
+// clear_value - clear programmatic override
//-------------------------------------------------
-ioport_field::~ioport_field()
+void ioport_field::clear_value()
{
+ if (is_analog())
+ live().analog->clear_value();
+ else
+ m_digital_value = false;
}
@@ -3442,6 +3460,7 @@ analog_field::analog_field(ioport_field &field)
m_adjdefvalue(field.defvalue() & field.mask()),
m_adjmin(field.minval() & field.mask()),
m_adjmax(field.maxval() & field.mask()),
+ m_adjoverride(field.defvalue() & field.mask()),
m_sensitivity(field.sensitivity()),
m_reverse(field.analog_reverse()),
m_delta(field.delta()),
@@ -3449,7 +3468,6 @@ analog_field::analog_field(ioport_field &field)
m_accum(0),
m_previous(0),
m_previousanalog(0),
- m_prog_analog_value(0),
m_minimum(INPUT_ABSOLUTE_MIN),
m_maximum(INPUT_ABSOLUTE_MAX),
m_center(0),
@@ -3465,7 +3483,7 @@ analog_field::analog_field(ioport_field &field)
m_single_scale(false),
m_interpolate(false),
m_lastdigital(false),
- m_was_written(false)
+ m_use_adjoverride(false)
{
// compute the shift amount and number of bits
for (ioport_value mask = field.mask(); !(mask & 1); mask >>= 1)
@@ -3705,16 +3723,28 @@ s32 analog_field::apply_settings(s32 value) const
//-------------------------------------------------
-// set_value - take a new value to be used
-// at next frame update
+// set_value - override the value that will be
+// read from the field
//-------------------------------------------------
void analog_field::set_value(s32 value)
{
- m_was_written = true;
- m_prog_analog_value = value;
+ m_use_adjoverride = true;
+ m_adjoverride = std::clamp(value, m_adjmin, m_adjmax);
+}
+
+
+//-------------------------------------------------
+// clear_value - clear programmatic override
+//-------------------------------------------------
+
+void analog_field::clear_value()
+{
+ m_use_adjoverride = false;
+ m_adjoverride = m_adjdefvalue;
}
+
//-------------------------------------------------
// frame_update - update the internals of a
// single analog field periodically
@@ -3733,13 +3763,6 @@ void analog_field::frame_update(running_machine &machine)
input_item_class itemclass;
s32 rawvalue = machine.input().seq_axis_value(m_field.seq(SEQ_TYPE_STANDARD), itemclass);
- // use programmatically set value if available
- if (m_was_written)
- {
- m_was_written = false;
- rawvalue = m_prog_analog_value;
- }
-
// if we got an absolute input, it overrides everything else
if (itemclass == ITEM_CLASS_ABSOLUTE)
{
@@ -3885,6 +3908,13 @@ void analog_field::read(ioport_value &result)
if (!m_field.enabled())
return;
+ // if set programmatically, only use the override value
+ if (m_use_adjoverride)
+ {
+ result = m_adjoverride;
+ return;
+ }
+
// start with the raw value
s32 value = m_accum;
diff --git a/src/emu/ioport.h b/src/emu/ioport.h
index 2d9bd855918..76f61debcac 100644
--- a/src/emu/ioport.h
+++ b/src/emu/ioport.h
@@ -916,6 +916,7 @@ public:
u8 player() const { return m_player; }
bool digital_value() const { return m_digital_value; }
void set_value(ioport_value value);
+ void clear_value();
bool optional() const { return ((m_flags & FIELD_FLAG_OPTIONAL) != 0); }
bool cocktail() const { return ((m_flags & FIELD_FLAG_COCKTAIL) != 0); }
@@ -1152,8 +1153,9 @@ public:
float crosshair_read();
void frame_update(running_machine &machine);
- // setters
+ // programmatic override (for script bindings)
void set_value(s32 value);
+ void clear_value();
private:
// helpers
@@ -1170,6 +1172,7 @@ private:
s32 m_adjdefvalue; // adjusted default value from the config
s32 m_adjmin; // adjusted minimum value from the config
s32 m_adjmax; // adjusted maximum value from the config
+ s32 m_adjoverride; // programmatically set adjusted value
// live values of configurable parameters
s32 m_sensitivity; // current live sensitivity (100=normal)
@@ -1181,7 +1184,6 @@ private:
s32 m_accum; // accumulated value (including relative adjustments)
s32 m_previous; // previous adjusted value
s32 m_previousanalog; // previous analog value
- s32 m_prog_analog_value; // programmatically set analog value
// parameters for modifying live values
s32 m_minimum; // minimum adjusted value
@@ -1203,7 +1205,7 @@ private:
bool m_single_scale; // scale joystick differently if default is between min/max
bool m_interpolate; // should we do linear interpolation for mid-frame reads?
bool m_lastdigital; // was the last modification caused by a digital form?
- bool m_was_written; // was the last modification caused programmatically?
+ bool m_use_adjoverride; // override what will be read from the field
};
diff --git a/src/frontend/mame/luaengine_input.cpp b/src/frontend/mame/luaengine_input.cpp
index 1812bdc17b3..4f13b7e2484 100644
--- a/src/frontend/mame/luaengine_input.cpp
+++ b/src/frontend/mame/luaengine_input.cpp
@@ -257,6 +257,7 @@ void lua_engine::initialize_input(sol::table &emu)
auto ioport_field_type = sol().registry().new_usertype<ioport_field>("ioport_field", sol::no_constructor);
ioport_field_type["set_value"] = &ioport_field::set_value;
+ ioport_field_type["clear_value"] = &ioport_field::clear_value;
ioport_field_type["set_input_seq"] =
[] (ioport_field &f, std::string const &seq_type_string, const input_seq &seq)
{
@@ -312,6 +313,16 @@ void lua_engine::initialize_input(sol::table &emu)
ioport_field_type["player"] = sol::property(&ioport_field::player, &ioport_field::set_player);
ioport_field_type["mask"] = sol::property(&ioport_field::mask);
ioport_field_type["defvalue"] = sol::property(&ioport_field::defvalue);
+ ioport_field_type["minvalue"] = sol::property(
+ [] (ioport_field &f)
+ {
+ return f.is_analog() ? std::make_optional(f.minval()) : std::nullopt;
+ });
+ ioport_field_type["maxvalue"] = sol::property(
+ [] (ioport_field &f)
+ {
+ return f.is_analog() ? std::make_optional(f.maxval()) : std::nullopt;
+ });
ioport_field_type["sensitivity"] = sol::property(&ioport_field::sensitivity);
ioport_field_type["way"] = sol::property(&ioport_field::way);
ioport_field_type["type_class"] = sol::property(