From 4526eaf0f3bce6f9f85f9e9487e4d5cef3d5ab67 Mon Sep 17 00:00:00 2001 From: npwoods Date: Fri, 4 Dec 2020 07:10:12 -0500 Subject: luaengine.cpp: Exposed device_slot_interface, emu_options, and slot options. (#7458) --- src/frontend/mame/luaengine.cpp | 75 ++++++++++++++++++++-- src/frontend/mame/luaengine.h | 3 + src/frontend/mame/luaengine.ipp | 110 +++++++++++++++++++++++++++++++++ src/frontend/mame/luaengine_mem.cpp | 120 +----------------------------------- 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", sol::no_constructor, sol::base_classes, sol::bases()); + 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", 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(&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(m.root_device()); }); machine_type["cassettes"] = sol::property([] (running_machine &m) { return devenum(m.root_device()); }); machine_type["images"] = sol::property([] (running_machine &m) { return devenum(m.root_device()); }); + machine_type["slots"] = sol::property([](running_machine &m) { return devenum(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("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(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("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(&device_slot_interface::slot_option::default_bios)); + dislot_option_type["clock"] = sol::property(static_cast(&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("manager", "new", sol::no_constructor, "machine", &machine_manager::machine, - "options", [](mame_machine_manager &m) { return static_cast(&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 struct devenum; template struct immutable_container_helper; + template struct tag_object_ptr_map; + template using standard_tag_object_ptr_map = tag_object_ptr_map > >; + // 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 + +template +struct lua_engine::tag_object_ptr_map +{ + tag_object_ptr_map(T const &m) : map(m) { } + + T const ↦ +}; + + namespace sol { class buffer @@ -69,6 +79,106 @@ int sol_lua_push(sol::types, lua_State *L, buffer *value); template struct is_container > : std::true_type { }; template struct usertype_container >; + +// tag_object_ptr_map is_container +template struct is_container > : std::true_type { }; + +// tag_object_ptr_map usertype_container +template +struct usertype_container > : lua_engine::immutable_container_helper, T const, typename T::const_iterator> +{ +private: + template + static int next_pairs(lua_State *L) + { + typename usertype_container::indexed_iterator &i(stack::unqualified_get >(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 + static int start_pairs(lua_State *L) + { + lua_engine::tag_object_ptr_map &self(usertype_container::get_self(L)); + stack::push(L, next_pairs); + stack::push >(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 &self(usertype_container::get_self(L)); + std::ptrdiff_t const index(stack::unqualified_get(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 &self(usertype_container::get_self(L)); + char const *const tag(stack::unqualified_get(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 &self(usertype_container::get_self(L)); + auto &obj(stack::unqualified_getsecond)>(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 &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 &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); } + static int pairs(lua_State *L) { return start_pairs(L); } + static int ipairs(lua_State *L) { return start_pairs(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 -struct memory_object_map -{ - memory_object_map(T const &m) : map(m) { } - - T const ↦ -}; - -template -using standard_memory_object_map = memory_object_map > >; - template 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 struct is_container > : std::true_type { }; - - -template -struct usertype_container > : lua_engine::immutable_container_helper, T const, typename T::const_iterator> -{ -private: - template - static int next_pairs(lua_State *L) - { - typename usertype_container::indexed_iterator &i(stack::unqualified_get >(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 - static int start_pairs(lua_State *L) - { - memory_object_map &self(usertype_container::get_self(L)); - stack::push(L, next_pairs); - stack::push >(L, self.map, self.map.begin()); - stack::push(L, lua_nil); - return 3; - } - -public: - static int at(lua_State *L) - { - memory_object_map &self(usertype_container::get_self(L)); - std::ptrdiff_t const index(stack::unqualified_get(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 &self(usertype_container::get_self(L)); - char const *const tag(stack::unqualified_get(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 &self(usertype_container::get_self(L)); - auto &obj(stack::unqualified_getsecond)>(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 &self(usertype_container::get_self(L)); - return stack::push(L, self.map.size()); - } - - static int empty(lua_State *L) - { - memory_object_map &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); } - static int pairs(lua_State *L) { return start_pairs(L); } - static int ipairs(lua_State *L) { return start_pairs(L); } -}; - -} // namespace sol - - - //------------------------------------------------- // mem_read - templated memory readers for , // -> 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", sol::no_constructor); - memory_type["banks"] = sol::property([] (memory_manager &mm) { return standard_memory_object_map(mm.banks()); }); - memory_type["regions"] = sol::property([] (memory_manager &mm) { return standard_memory_object_map(mm.regions()); }); - memory_type["shares"] = sol::property([] (memory_manager &mm) { return standard_memory_object_map(mm.shares()); }); + memory_type["banks"] = sol::property([] (memory_manager &mm) { return standard_tag_object_ptr_map(mm.banks()); }); + memory_type["regions"] = sol::property([] (memory_manager &mm) { return standard_tag_object_ptr_map(mm.regions()); }); + memory_type["shares"] = sol::property([] (memory_manager &mm) { return standard_tag_object_ptr_map(mm.shares()); }); /* memory_bank library -- cgit v1.2.3