summaryrefslogtreecommitdiffstatshomepage
path: root/src/frontend
diff options
context:
space:
mode:
author npwoods <npwoods@mess.org>2020-12-04 07:10:12 -0500
committer GitHub <noreply@github.com>2020-12-04 23:10:12 +1100
commit4526eaf0f3bce6f9f85f9e9487e4d5cef3d5ab67 (patch)
tree736b4066c389d5f660a8db2e0556fbcf075867a1 /src/frontend
parenta5ae1c2148de63ea0d5e7dc217672308ce5fcc6b (diff)
luaengine.cpp: Exposed device_slot_interface, emu_options, and slot options. (#7458)
Diffstat (limited to 'src/frontend')
-rw-r--r--src/frontend/mame/luaengine.cpp75
-rw-r--r--src/frontend/mame/luaengine.h3
-rw-r--r--src/frontend/mame/luaengine.ipp110
-rw-r--r--src/frontend/mame/luaengine_mem.cpp120
4 files changed, 187 insertions, 121 deletions
diff --git a/src/frontend/mame/luaengine.cpp b/src/frontend/mame/luaengine.cpp
index 7f627d0c4dd..d0fdcedab88 100644
--- a/src/frontend/mame/luaengine.cpp
+++ b/src/frontend/mame/luaengine.cpp
@@ -978,6 +978,41 @@ void lua_engine::initialize()
return table;
}));
+/* emu_options library
+ *
+ * manager:options()
+ * manager:machine():options()
+ *
+ * options:slot_option() - retrieves a specific slot option
+ */
+
+ auto emu_options_type = sol().registry().new_usertype<emu_options>("emu_options", sol::no_constructor, sol::base_classes, sol::bases<core_options>());
+ emu_options_type.set("slot_option", [](emu_options &opts, const std::string &name) { return opts.find_slot_option(name); });
+
+
+/* slot_option library
+ *
+ * manager:options():slot_option("name")
+ * manager:machine():options():slot_option("name")
+ *
+ * slot_option.value - the actual value of the option, after being interpreted
+ * slot_option.specified_value - the value of the option, as specified from outside
+ * slot_option.bios - the bios, if any, associated with the slot
+ * slot_option.default_card_software - the software list item that is associated with this option, by default
+ * slot_option:specify() - specifies the value of the slot, potentially causing a recalculation
+ */
+
+ auto slot_option_type = sol().registry().new_usertype<slot_option>("slot_option", sol::no_constructor);
+ slot_option_type["value"] = sol::property(&slot_option::value);
+ slot_option_type["specified_value"] = sol::property(&slot_option::specified_value);
+ slot_option_type["bios"] = sol::property(&slot_option::bios);
+ slot_option_type["default_card_software"] = sol::property(&slot_option::default_card_software);
+ slot_option_type.set("specify", [](slot_option &opt, std::string &&text, const char *bios) {
+ opt.specify(std::move(text));
+ if (bios)
+ opt.set_bios(bios);
+ });
+
/* core_options::entry library
*
@@ -1061,7 +1096,7 @@ void lua_engine::initialize()
* machine:ioport() - get ioport_manager
* machine:parameters() - get parameter_manager
* machine:memory() - get memory_manager
- * machine:options() - get machine core_options
+ * machine:options() - get machine emu_options
* machine:outputs() - get output_manager
* machine:input() - get input_manager
* machine:uiinput() - get ui_input_manager
@@ -1119,7 +1154,7 @@ void lua_engine::initialize()
machine_type["ioport"] = &running_machine::ioport;
machine_type["parameters"] = &running_machine::parameters;
machine_type["memory"] = &running_machine::memory;
- machine_type["options"] = [] (running_machine &m) { return static_cast<core_options *>(&m.options()); };
+ machine_type["options"] = &running_machine::options;
machine_type["outputs"] = &running_machine::output;
machine_type["input"] = &running_machine::input;
machine_type["uiinput"] = &running_machine::ui_input;
@@ -1138,6 +1173,7 @@ void lua_engine::initialize()
machine_type["screens"] = sol::property([] (running_machine &m) { return devenum<screen_device_enumerator>(m.root_device()); });
machine_type["cassettes"] = sol::property([] (running_machine &m) { return devenum<cassette_device_enumerator>(m.root_device()); });
machine_type["images"] = sol::property([] (running_machine &m) { return devenum<image_interface_enumerator>(m.root_device()); });
+ machine_type["slots"] = sol::property([](running_machine &m) { return devenum<slot_interface_enumerator>(m.root_device()); });
machine_type["popmessage"] = sol::overload(
[](running_machine &m, const char *str) { m.popmessage("%s", str); },
[](running_machine &m) { m.popmessage(); });
@@ -1778,6 +1814,37 @@ void lua_engine::initialize()
image_type.set("is_reset_on_load", sol::property(&device_image_interface::is_reset_on_load));
image_type.set("must_be_loaded", sol::property(&device_image_interface::must_be_loaded));
+/* device_slot_interface library
+ *
+ * manager:machine().slots[slot_name]
+ *
+ * slot.fixed - whether this slot is fixed, and hence not selectable by the user
+ * slot.has_selectable_options - does this slot have any selectable options at all?
+ * slot.default_option - returns the default option if one exists
+ * slot.options[] - get options table (k=name, v=device_slot_interface::slot_option)
+ */
+
+ auto slot_type = sol().registry().new_usertype<device_slot_interface>("slot", "new", sol::no_constructor);
+ slot_type["fixed"] = sol::property(&device_slot_interface::fixed);
+ slot_type["has_selectable_options"] = sol::property(&device_slot_interface::has_selectable_options);
+ slot_type["default_option"] = sol::property(&device_slot_interface::default_option);
+ slot_type["options"] = sol::property([](const device_slot_interface &slot) { return standard_tag_object_ptr_map<device_slot_interface::slot_option>(slot.option_list()); });
+
+
+/* device_slot_interface::slot_option library
+ *
+ * manager:machine().slots[slot_name].options[option_name]
+ *
+ * slot_option.selectable - is this item selectable by the user?
+ * slot_option.default_bios - the default bios for this option
+ * slot_option.clock - the clock speed associated with this option
+ */
+
+ auto dislot_option_type = sol().registry().new_usertype<device_slot_interface::slot_option>("dislot_option", "new", sol::no_constructor);
+ dislot_option_type["selectable"] = sol::property(&device_slot_interface::slot_option::selectable);
+ dislot_option_type["default_bios"] = sol::property(static_cast<const char *(device_slot_interface::slot_option::*)() const>(&device_slot_interface::slot_option::default_bios));
+ dislot_option_type["clock"] = sol::property(static_cast<u32 (device_slot_interface::slot_option:: *)() const>(&device_slot_interface::slot_option::clock));
+
/* cassette_image_device
*
@@ -1823,14 +1890,14 @@ void lua_engine::initialize()
* mame_manager - alias of manager
*
* manager:machine() - running machine
- * manager:options() - core options
+ * manager:options() - emu options
* manager:plugins() - plugin options
* manager:ui() - mame ui manager
*/
sol().registry().new_usertype<mame_machine_manager>("manager", "new", sol::no_constructor,
"machine", &machine_manager::machine,
- "options", [](mame_machine_manager &m) { return static_cast<core_options *>(&m.options()); },
+ "options", &machine_manager::options,
"plugins", [this](mame_machine_manager &m) {
sol::table table = sol().create_table();
for (auto &curentry : m.plugins().plugins())
diff --git a/src/frontend/mame/luaengine.h b/src/frontend/mame/luaengine.h
index e479ba60646..e4a7ac2bdf6 100644
--- a/src/frontend/mame/luaengine.h
+++ b/src/frontend/mame/luaengine.h
@@ -37,6 +37,9 @@ public:
template <typename T> struct devenum;
template <typename T, typename C, typename I = typename C::iterator> struct immutable_container_helper;
+ template <typename T> struct tag_object_ptr_map;
+ template <typename T> using standard_tag_object_ptr_map = tag_object_ptr_map<std::unordered_map<std::string, std::unique_ptr<T> > >;
+
// construction/destruction
lua_engine();
~lua_engine();
diff --git a/src/frontend/mame/luaengine.ipp b/src/frontend/mame/luaengine.ipp
index 142a1ec269e..16065ae5216 100644
--- a/src/frontend/mame/luaengine.ipp
+++ b/src/frontend/mame/luaengine.ipp
@@ -17,6 +17,16 @@
#include <lua.hpp>
+
+template <typename T>
+struct lua_engine::tag_object_ptr_map
+{
+ tag_object_ptr_map(T const &m) : map(m) { }
+
+ T const &map;
+};
+
+
namespace sol {
class buffer
@@ -69,6 +79,106 @@ int sol_lua_push(sol::types<buffer *>, lua_State *L, buffer *value);
template <typename T> struct is_container<lua_engine::devenum<T> > : std::true_type { };
template <typename T> struct usertype_container<lua_engine::devenum<T> >;
+
+// tag_object_ptr_map is_container
+template <typename T> struct is_container<lua_engine::tag_object_ptr_map<T> > : std::true_type { };
+
+// tag_object_ptr_map usertype_container
+template <typename T>
+struct usertype_container<lua_engine::tag_object_ptr_map<T> > : lua_engine::immutable_container_helper<lua_engine::tag_object_ptr_map<T>, T const, typename T::const_iterator>
+{
+private:
+ template <bool Indexed>
+ static int next_pairs(lua_State *L)
+ {
+ typename usertype_container::indexed_iterator &i(stack::unqualified_get<user<typename usertype_container::indexed_iterator> >(L, 1));
+ if (i.src.end() == i.it)
+ return stack::push(L, lua_nil);
+ int result;
+ if constexpr (Indexed)
+ result = stack::push(L, i.ix + 1);
+ else
+ result = stack::push(L, i.it->first);
+ result += stack::push_reference(L, *i.it->second);
+ ++i;
+ return result;
+ }
+
+ template <bool Indexed>
+ static int start_pairs(lua_State *L)
+ {
+ lua_engine::tag_object_ptr_map<T> &self(usertype_container::get_self(L));
+ stack::push(L, next_pairs<Indexed>);
+ stack::push<user<typename usertype_container::indexed_iterator> >(L, self.map, self.map.begin());
+ stack::push(L, lua_nil);
+ return 3;
+ }
+
+public:
+ static int at(lua_State *L)
+ {
+ lua_engine::tag_object_ptr_map<T> &self(usertype_container::get_self(L));
+ std::ptrdiff_t const index(stack::unqualified_get<std::ptrdiff_t>(L, 2));
+ if ((0 >= index) || (self.map.size() < index))
+ return stack::push(L, lua_nil);
+ auto const found(std::next(self.map.begin(), index - 1));
+ if (!found->second)
+ return stack::push(L, lua_nil);
+ else
+ return stack::push_reference(L, *found->second);
+ }
+
+ static int get(lua_State *L)
+ {
+ lua_engine::tag_object_ptr_map<T> &self(usertype_container::get_self(L));
+ char const *const tag(stack::unqualified_get<char const *>(L));
+ auto const found(self.map.find(tag));
+ if ((self.map.end() == found) || !found->second)
+ return stack::push(L, lua_nil);
+ else
+ return stack::push_reference(L, *found->second);
+ }
+
+ static int index_get(lua_State *L)
+ {
+ return get(L);
+ }
+
+ static int index_of(lua_State *L)
+ {
+ lua_engine::tag_object_ptr_map<T> &self(usertype_container::get_self(L));
+ auto &obj(stack::unqualified_get<decltype(*self.map.begin()->second)>(L, 2));
+ auto it(self.map.begin());
+ std::ptrdiff_t ix(0);
+ while ((self.map.end() != it) && (it->second.get() != &obj))
+ {
+ ++it;
+ ++ix;
+ }
+ if (self.map.end() == it)
+ return stack::push(L, lua_nil);
+ else
+ return stack::push(L, ix + 1);
+ }
+
+ static int size(lua_State *L)
+ {
+ lua_engine::tag_object_ptr_map<T> &self(usertype_container::get_self(L));
+ return stack::push(L, self.map.size());
+ }
+
+ static int empty(lua_State *L)
+ {
+ lua_engine::tag_object_ptr_map<T> &self(usertype_container::get_self(L));
+ return stack::push(L, self.map.empty());
+ }
+
+ static int next(lua_State *L) { return stack::push(L, next_pairs<false>); }
+ static int pairs(lua_State *L) { return start_pairs<false>(L); }
+ static int ipairs(lua_State *L) { return start_pairs<true>(L); }
+};
+
+
} // namespace sol
diff --git a/src/frontend/mame/luaengine_mem.cpp b/src/frontend/mame/luaengine_mem.cpp
index 59ffe9582dd..65db6becf6a 100644
--- a/src/frontend/mame/luaengine_mem.cpp
+++ b/src/frontend/mame/luaengine_mem.cpp
@@ -14,17 +14,6 @@
namespace {
-template <typename T>
-struct memory_object_map
-{
- memory_object_map(T const &m) : map(m) { }
-
- T const &map;
-};
-
-template <typename T>
-using standard_memory_object_map = memory_object_map<std::unordered_map<std::string, std::unique_ptr<T> > >;
-
template <typename T>
std::string get_endianness_name(T const &obj)
@@ -151,109 +140,6 @@ void share_write(memory_share &share, offs_t address, T val)
-namespace sol {
-
-template <typename T> struct is_container<memory_object_map<T> > : std::true_type { };
-
-
-template <typename T>
-struct usertype_container<memory_object_map<T> > : lua_engine::immutable_container_helper<memory_object_map<T>, T const, typename T::const_iterator>
-{
-private:
- template <bool Indexed>
- static int next_pairs(lua_State *L)
- {
- typename usertype_container::indexed_iterator &i(stack::unqualified_get<user<typename usertype_container::indexed_iterator> >(L, 1));
- if (i.src.end() == i.it)
- return stack::push(L, lua_nil);
- int result;
- if constexpr (Indexed)
- result = stack::push(L, i.ix + 1);
- else
- result = stack::push(L, i.it->first);
- result += stack::push_reference(L, *i.it->second);
- ++i;
- return result;
- }
-
- template <bool Indexed>
- static int start_pairs(lua_State *L)
- {
- memory_object_map<T> &self(usertype_container::get_self(L));
- stack::push(L, next_pairs<Indexed>);
- stack::push<user<typename usertype_container::indexed_iterator> >(L, self.map, self.map.begin());
- stack::push(L, lua_nil);
- return 3;
- }
-
-public:
- static int at(lua_State *L)
- {
- memory_object_map<T> &self(usertype_container::get_self(L));
- std::ptrdiff_t const index(stack::unqualified_get<std::ptrdiff_t>(L, 2));
- if ((0 >= index) || (self.map.size() < index))
- return stack::push(L, lua_nil);
- auto const found(std::next(self.map.begin(), index - 1));
- if (!found->second)
- return stack::push(L, lua_nil);
- else
- return stack::push_reference(L, *found->second);
- }
-
- static int get(lua_State *L)
- {
- memory_object_map<T> &self(usertype_container::get_self(L));
- char const *const tag(stack::unqualified_get<char const *>(L));
- auto const found(self.map.find(tag));
- if ((self.map.end() == found) || !found->second)
- return stack::push(L, lua_nil);
- else
- return stack::push_reference(L, *found->second);
- }
-
- static int index_get(lua_State *L)
- {
- return get(L);
- }
-
- static int index_of(lua_State *L)
- {
- memory_object_map<T> &self(usertype_container::get_self(L));
- auto &obj(stack::unqualified_get<decltype(*self.map.begin()->second)>(L, 2));
- auto it(self.map.begin());
- std::ptrdiff_t ix(0);
- while ((self.map.end() != it) && (it->second.get() != &obj))
- {
- ++it;
- ++ix;
- }
- if (self.map.end() == it)
- return stack::push(L, lua_nil);
- else
- return stack::push(L, ix + 1);
- }
-
- static int size(lua_State *L)
- {
- memory_object_map<T> &self(usertype_container::get_self(L));
- return stack::push(L, self.map.size());
- }
-
- static int empty(lua_State *L)
- {
- memory_object_map<T> &self(usertype_container::get_self(L));
- return stack::push(L, self.map.empty());
- }
-
- static int next(lua_State *L) { return stack::push(L, next_pairs<false>); }
- static int pairs(lua_State *L) { return start_pairs<false>(L); }
- static int ipairs(lua_State *L) { return start_pairs<true>(L); }
-};
-
-} // namespace sol
-
-
-
//-------------------------------------------------
// mem_read - templated memory readers for <sign>,<size>
// -> manager:machine().devices[":maincpu"].spaces["program"]:read_i8(0xC000)
@@ -652,9 +538,9 @@ void lua_engine::initialize_memory()
*/
auto memory_type = sol().registry().new_usertype<memory_manager>("memory", sol::no_constructor);
- memory_type["banks"] = sol::property([] (memory_manager &mm) { return standard_memory_object_map<memory_bank>(mm.banks()); });
- memory_type["regions"] = sol::property([] (memory_manager &mm) { return standard_memory_object_map<memory_region>(mm.regions()); });
- memory_type["shares"] = sol::property([] (memory_manager &mm) { return standard_memory_object_map<memory_share>(mm.shares()); });
+ memory_type["banks"] = sol::property([] (memory_manager &mm) { return standard_tag_object_ptr_map<memory_bank>(mm.banks()); });
+ memory_type["regions"] = sol::property([] (memory_manager &mm) { return standard_tag_object_ptr_map<memory_region>(mm.regions()); });
+ memory_type["shares"] = sol::property([] (memory_manager &mm) { return standard_tag_object_ptr_map<memory_share>(mm.shares()); });
/* memory_bank library