mirror of
https://github.com/holub/mame
synced 2025-04-21 07:52:35 +03:00
luaengine.cpp: Exposed device_slot_interface, emu_options, and slot options. (#7458)
This commit is contained in:
parent
a5ae1c2148
commit
4526eaf0f3
@ -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())
|
||||
|
@ -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();
|
||||
|
@ -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 ↦
|
||||
};
|
||||
|
||||
|
||||
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
|
||||
|
||||
|
||||
|
@ -14,17 +14,6 @@
|
||||
|
||||
namespace {
|
||||
|
||||
template <typename T>
|
||||
struct memory_object_map
|
||||
{
|
||||
memory_object_map(T const &m) : map(m) { }
|
||||
|
||||
T const ↦
|
||||
};
|
||||
|
||||
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
|
||||
|
Loading…
Reference in New Issue
Block a user