summaryrefslogtreecommitdiffstatshomepage
path: root/src/frontend/mame
diff options
context:
space:
mode:
author Vas Crabb <vas@vastheman.com>2020-12-05 21:04:22 +1100
committer Vas Crabb <vas@vastheman.com>2020-12-05 21:04:22 +1100
commitcac83ba5b1fec32513704e5cb1919efc35d15e0e (patch)
treee12482d7bc59320c5a0225bb17444735eab250e3 /src/frontend/mame
parente4ed0ebf242daeca43d85fa3281978d9e6d1b4c6 (diff)
Expose enough of the layout system to Lua to allow position and colour to be animated.
Diffstat (limited to 'src/frontend/mame')
-rw-r--r--src/frontend/mame/luaengine.cpp19
-rw-r--r--src/frontend/mame/luaengine.h53
-rw-r--r--src/frontend/mame/luaengine.ipp47
-rw-r--r--src/frontend/mame/luaengine_debug.cpp2
-rw-r--r--src/frontend/mame/luaengine_input.cpp2
-rw-r--r--src/frontend/mame/luaengine_mem.cpp2
-rw-r--r--src/frontend/mame/luaengine_render.cpp124
7 files changed, 134 insertions, 115 deletions
diff --git a/src/frontend/mame/luaengine.cpp b/src/frontend/mame/luaengine.cpp
index 6ff6dc0709c..e4da280e221 100644
--- a/src/frontend/mame/luaengine.cpp
+++ b/src/frontend/mame/luaengine.cpp
@@ -985,7 +985,7 @@ void lua_engine::initialize()
* manager:options()
* manager:machine():options()
*
- * options:slot_option() - retrieves a specific slot option
+ * options:slot_option(tag) - 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>());
@@ -1286,6 +1286,7 @@ void lua_engine::initialize()
* device:memregion(tag) - get memory region
* device:memshare(tag) - get memory share
* device:membank(tag) - get memory bank
+ * device:ioport(tag) - get I/O port
* device:subdevice(tag) - get subdevice
* device:siblingdevice(tag) - get sibling device
* device:debug() - debug interface, CPUs only
@@ -1309,6 +1310,7 @@ void lua_engine::initialize()
device_type["memregion"] = &device_t::memregion;
device_type["memshare"] = &device_t::memshare;
device_type["membank"] = &device_t::membank;
+ device_type["ioport"] = &device_t::ioport;
device_type["subdevice"] = static_cast<device_t *(device_t::*)(char const *) const>(&device_t::subdevice);
device_type["siblingdevice"] = static_cast<device_t *(device_t::*)(char const *) const>(&device_t::siblingdevice);
device_type["debug"] =
@@ -1873,7 +1875,7 @@ void lua_engine::initialize()
auto cass_type = sol().registry().new_usertype<cassette_image_device>(
"cassette",
sol::no_constructor,
- sol::base_classes, sol::bases<device_t>());
+ sol::base_classes, sol::bases<device_t, device_image_interface>());
cass_type["stop"] = [] (cassette_image_device &c) { c.change_state(CASSETTE_STOPPED, CASSETTE_MASK_UISTATE); };
cass_type["play"] = [] (cassette_image_device &c) { c.change_state(CASSETTE_PLAY, CASSETTE_MASK_UISTATE); };
cass_type["record"] = [] (cassette_image_device &c) { c.change_state(CASSETTE_RECORD, CASSETTE_MASK_UISTATE); };
@@ -1886,11 +1888,10 @@ void lua_engine::initialize()
cass_type["motor_state"] = sol::property(&cassette_image_device::motor_on, &cassette_image_device::set_motor);
cass_type["speaker_state"] = sol::property(&cassette_image_device::speaker_on, &cassette_image_device::set_speaker);
cass_type["position"] = sol::property(&cassette_image_device::get_position);
- cass_type["length"] = sol::property([] (cassette_image_device &c) { if (c.exists()) return c.get_length(); return 0.0; });
- cass_type["image"] = sol::property([] (cassette_image_device &c) { return dynamic_cast<device_image_interface *>(&c); });
+ cass_type["length"] = sol::property([] (cassette_image_device &c) { return c.exists() ? c.get_length() : 0.0; });
-/* mame_machine_manager library
+/* mame_machine_manager library
*
* manager
* mame_manager - alias of manager
@@ -1924,10 +1925,10 @@ void lua_engine::initialize()
// set up other user types
- initialize_debug();
- initialize_input();
- initialize_memory();
- initialize_render();
+ initialize_debug(emu);
+ initialize_input(emu);
+ initialize_memory(emu);
+ initialize_render(emu);
}
//-------------------------------------------------
diff --git a/src/frontend/mame/luaengine.h b/src/frontend/mame/luaengine.h
index e4a7ac2bdf6..14d47fbf89c 100644
--- a/src/frontend/mame/luaengine.h
+++ b/src/frontend/mame/luaengine.h
@@ -122,6 +122,26 @@ public:
private:
template<typename T, size_t SIZE> class enum_parser;
+ struct addr_space;
+
+ struct save_item {
+ void *base;
+ unsigned int size;
+ unsigned int count;
+ unsigned int valcount;
+ unsigned int blockcount;
+ unsigned int stride;
+ };
+
+ struct context
+ {
+ context() { busy = false; yield = false; }
+ std::string result;
+ std::condition_variable sync;
+ bool busy;
+ bool yield;
+ };
+
// internal state
lua_State *m_lua_state;
std::unique_ptr<sol::state_view> m_sol_state;
@@ -130,6 +150,9 @@ private:
std::vector<std::string> m_menu;
+ template <typename R, typename T, typename D>
+ auto make_simple_callback_setter(void (T::*setter)(delegate<R ()> &&), D &&dflt, const char *name, const char *desc);
+
running_machine &machine() const { return *m_machine; }
void on_machine_prestart();
@@ -145,37 +168,17 @@ private:
bool execute_function(const char *id);
sol::object call_plugin(const std::string &name, sol::object in);
- struct addr_space;
-
- struct save_item {
- void *base;
- unsigned int size;
- unsigned int count;
- unsigned int valcount;
- unsigned int blockcount;
- unsigned int stride;
- };
-
void close();
void run(sol::load_result res);
- struct context
- {
- context() { busy = false; yield = false; }
- std::string result;
- std::condition_variable sync;
- bool busy;
- bool yield;
- };
-
- template<typename TFunc, typename... TArgs>
+ template <typename TFunc, typename... TArgs>
sol::protected_function_result invoke(TFunc &&func, TArgs&&... args);
- void initialize_debug();
- void initialize_input();
- void initialize_memory();
- void initialize_render();
+ void initialize_debug(sol::table &emu);
+ void initialize_input(sol::table &emu);
+ void initialize_memory(sol::table &emu);
+ void initialize_render(sol::table &emu);
};
#endif // MAME_FRONTEND_MAME_LUAENGINE_H
diff --git a/src/frontend/mame/luaengine.ipp b/src/frontend/mame/luaengine.ipp
index 16065ae5216..0024c0afb78 100644
--- a/src/frontend/mame/luaengine.ipp
+++ b/src/frontend/mame/luaengine.ipp
@@ -310,6 +310,53 @@ private:
//-------------------------------------------------
+// make_simple_callback_setter - make a callback
+// setter for simple cases
+//-------------------------------------------------
+
+template <typename R, typename T, typename D>
+auto lua_engine::make_simple_callback_setter(void (T::*setter)(delegate<R ()> &&), D &&dflt, const char *name, const char *desc)
+{
+ return
+ [this, setter, dflt, name, desc] (T &self, sol::object cb)
+ {
+ if (cb == sol::lua_nil)
+ {
+ (self.*setter)(delegate<R ()>());
+ }
+ else if (cb.is<sol::protected_function>())
+ {
+ (self.*setter)(delegate<R ()>(
+ [this, dflt, name, desc, cbfunc = cb.as<sol::protected_function>()] () -> R
+ {
+ if constexpr (std::is_same_v<R, void>)
+ {
+ invoke(cbfunc);
+ }
+ else
+ {
+ auto result(invoke(cbfunc).get<sol::optional<R> >());
+ if (result)
+ {
+ return *result;
+ }
+ else
+ {
+ osd_printf_error("[LUA ERROR] invalid return from %s callback\n", desc);
+ return dflt();
+ }
+ }
+ }));
+ }
+ else
+ {
+ osd_printf_error("[LUA ERROR] must call %s with function or nil\n", name);
+ }
+ };
+}
+
+
+//-------------------------------------------------
// invoke - invokes a function, wrapping profiler
//-------------------------------------------------
diff --git a/src/frontend/mame/luaengine_debug.cpp b/src/frontend/mame/luaengine_debug.cpp
index 4cbff8d799f..aec17ada89b 100644
--- a/src/frontend/mame/luaengine_debug.cpp
+++ b/src/frontend/mame/luaengine_debug.cpp
@@ -81,7 +81,7 @@ sol::object do_watchpoint_enable(lua_State *L, device_debug &dev, sol::object &i
} // anonymous namespace
-void lua_engine::initialize_debug()
+void lua_engine::initialize_debug(sol::table &emu)
{
static const enum_parser<read_or_write, 4> s_read_or_write_parser =
diff --git a/src/frontend/mame/luaengine_input.cpp b/src/frontend/mame/luaengine_input.cpp
index f954038b70f..e135678a840 100644
--- a/src/frontend/mame/luaengine_input.cpp
+++ b/src/frontend/mame/luaengine_input.cpp
@@ -21,7 +21,7 @@
// initialize_input - register input user types
//-------------------------------------------------
-void lua_engine::initialize_input()
+void lua_engine::initialize_input(sol::table &emu)
{
static const enum_parser<input_seq_type, 3> s_seq_type_parser =
diff --git a/src/frontend/mame/luaengine_mem.cpp b/src/frontend/mame/luaengine_mem.cpp
index 65db6becf6a..dc9abcbbb21 100644
--- a/src/frontend/mame/luaengine_mem.cpp
+++ b/src/frontend/mame/luaengine_mem.cpp
@@ -353,7 +353,7 @@ void lua_engine::addr_space::direct_mem_write(offs_t address, T val)
// initialize_memory - register memory user types
//-------------------------------------------------
-void lua_engine::initialize_memory()
+void lua_engine::initialize_memory(sol::table &emu)
{
/* addr_space library
diff --git a/src/frontend/mame/luaengine_render.cpp b/src/frontend/mame/luaengine_render.cpp
index 68113f0650b..5df401c9b17 100644
--- a/src/frontend/mame/luaengine_render.cpp
+++ b/src/frontend/mame/luaengine_render.cpp
@@ -316,7 +316,7 @@ public:
// initialize_render - register render user types
//-------------------------------------------------
-void lua_engine::initialize_render()
+void lua_engine::initialize_render(sol::table &emu)
{
/* render_bounds library
@@ -333,12 +333,14 @@ void lua_engine::initialize_render()
* bounds.height - get/set height
* bounds.aspect - read-only aspect ratio width:height
*/
- auto bounds_type = sol().registry().new_usertype<render_bounds>("bounds", sol::call_constructor, sol::initializers(
+ auto bounds_type = emu.new_usertype<render_bounds>(
+ "render_bounds",
+ sol::call_constructor, sol::initializers(
[] (render_bounds &b) { new (&b) render_bounds{ 0.0F, 0.0F, 1.0F, 1.0F }; },
[] (render_bounds &b, float x0, float y0, float x1, float y1) { new (&b) render_bounds{ x0, y0, x1, y1 }; }));
bounds_type["includes"] = &render_bounds::includes;
- bounds_type["set_xy"] = &render_bounds::includes;
- bounds_type["set_wh"] = &render_bounds::includes;
+ bounds_type["set_xy"] = &render_bounds::set_xy;
+ bounds_type["set_wh"] = &render_bounds::set_wh;
bounds_type["x0"] = &render_bounds::x0;
bounds_type["y0"] = &render_bounds::y0;
bounds_type["x1"] = &render_bounds::x1;
@@ -357,7 +359,9 @@ void lua_engine::initialize_render()
* color.g - green channel
* color.b - blue channel
*/
- auto color_type = sol().registry().new_usertype<render_color>("color", sol::call_constructor, sol::initializers(
+ auto color_type = emu.new_usertype<render_color>(
+ "render_color",
+ sol::call_constructor, sol::initializers(
[] (render_color &c) { new (&c) render_color{ 1.0F, 1.0F, 1.0F, 1.0F }; },
[] (render_color &c, float a, float r, float g, float b) { new (&c) render_color{ a, r, g, b }; }));
color_type["set"] = &render_color::set;
@@ -372,6 +376,9 @@ void lua_engine::initialize_render()
* manager:machine():render().targets[target_index]:current_view()
*
* view:has_screen(screen) - returns whether a given screen is present in the view (including hidden screens)
+ * view:set_prepare_items_callback(cb) - set additional tasks before adding items to render target
+ * view:set_preload_callback(cb) - set additional tasks after preloading visible items
+ * view:set_recomputed_callback(cb) - set additional tasks after recomputing for resize or visibility change
*
* view.items - get the items in the view (including hidden items)
* view.name - display name for the view
@@ -384,6 +391,24 @@ void lua_engine::initialize_render()
auto layout_view_type = sol().registry().new_usertype<layout_view>("layout_view", sol::no_constructor);
layout_view_type["has_screen"] = &layout_view::has_screen;
+ layout_view_type["set_prepare_items_callback"] =
+ make_simple_callback_setter<void>(
+ &layout_view::set_prepare_items_callback,
+ nullptr,
+ "set_prepare_items_callback",
+ nullptr);
+ layout_view_type["set_preload_callback"] =
+ make_simple_callback_setter<void>(
+ &layout_view::set_preload_callback,
+ nullptr,
+ "set_preload_callback",
+ nullptr);
+ layout_view_type["set_recomputed_callback"] =
+ make_simple_callback_setter<void>(
+ &layout_view::set_recomputed_callback,
+ nullptr,
+ "set_recomputed_callback",
+ nullptr);
layout_view_type["items"] = sol::property([] (layout_view &v) { return layout_view_items(v); });
layout_view_type["name"] = sol::property(&layout_view::name);
layout_view_type["unqualified_name"] = sol::property(&layout_view::unqualified_name);
@@ -415,63 +440,17 @@ void lua_engine::initialize_render()
auto layout_view_item_type = sol().registry().new_usertype<layout_view::item>("layout_item", sol::no_constructor);
layout_view_item_type["set_state"] = &layout_view::item::set_state;
layout_view_item_type["set_element_state_callback"] =
- [this] (layout_view::item &i, sol::object cb)
- {
- if (cb == sol::lua_nil)
- {
- i.set_element_state_callback(layout_view::item::state_delegate());
- }
- else if (cb.is<sol::protected_function>())
- {
- i.set_element_state_callback(layout_view::item::state_delegate(
- [this, cbfunc = cb.as<sol::protected_function>()] () -> int
- {
- auto result(invoke(cbfunc).get<sol::optional<int> >());
- if (result)
- {
- return *result;
- }
- else
- {
- osd_printf_error("[LUA ERROR] invalid return from element state callback\n");
- return 0;
- }
- }));
- }
- else
- {
- osd_printf_error("[LUA ERROR] must call set_element_state_callback with function or nil\n");
- }
- };
+ make_simple_callback_setter<int>(
+ &layout_view::item::set_element_state_callback,
+ [] () { return 0; },
+ "set_element_state_callback",
+ "element state");
layout_view_item_type["set_animation_state_callback"] =
- [this] (layout_view::item &i, sol::object cb)
- {
- if (cb == sol::lua_nil)
- {
- i.set_animation_state_callback(layout_view::item::state_delegate());
- }
- else if (cb.is<sol::protected_function>())
- {
- i.set_animation_state_callback(layout_view::item::state_delegate(
- [this, cbfunc = cb.as<sol::protected_function>()] () -> int
- {
- auto result(invoke(cbfunc).get<sol::optional<int> >());
- if (result)
- {
- return *result;
- }
- else
- {
- osd_printf_error("[LUA ERROR] invalid return from animation state callback\n");
- return 0;
- }
- }));
- }
- else
- {
- osd_printf_error("[LUA ERROR] must call set_animation_state_callback with function or nil\n");
- }
- };
+ make_simple_callback_setter<int>(
+ &layout_view::item::set_animation_state_callback,
+ [] () { return 0; },
+ "set_animation_state_callback",
+ "animation state");
layout_view_item_type["set_bounds_callback"] =
[this] (layout_view::item &i, sol::object cb)
{
@@ -550,7 +529,7 @@ void lua_engine::initialize_render()
/* layout_file library
*
- * file.set_resolve_tags_callback - set additional tasks after resolving tags
+ * file:set_resolve_tags_callback(cb) - set additional tasks after resolving tags
*
* file.device - get device that caused the file to be loaded
* file.views[] - get view table (k=name, v=layout_view)
@@ -558,22 +537,11 @@ void lua_engine::initialize_render()
auto layout_file_type = sol().registry().new_usertype<layout_file>("layout_file", sol::no_constructor);
layout_file_type["set_resolve_tags_callback"] =
- [this] (layout_file &f, sol::object cb)
- {
- if (cb == sol::lua_nil)
- {
- f.set_resolve_tags_callback(layout_file::resolve_tags_delegate());
- }
- else if (cb.is<sol::protected_function>())
- {
- f.set_resolve_tags_callback(layout_file::resolve_tags_delegate(
- [this, cbfunc = cb.as<sol::protected_function>()] () { invoke(cbfunc); }));
- }
- else
- {
- osd_printf_error("[LUA ERROR] must call set_resolve_tags_callback with function or nil\n");
- }
- };
+ make_simple_callback_setter<void>(
+ &layout_file::set_resolve_tags_callback,
+ nullptr,
+ "set_resolve_tags_callback",
+ nullptr);
layout_file_type["device"] = sol::property(&layout_file::device);
layout_file_type["views"] = sol::property([] (layout_file &f) { return layout_file_views(f); });