diff options
Diffstat (limited to 'src/emu/luaengine.cpp')
-rw-r--r-- | src/emu/luaengine.cpp | 277 |
1 files changed, 217 insertions, 60 deletions
diff --git a/src/emu/luaengine.cpp b/src/emu/luaengine.cpp index ecf1b418de5..262bf5c925e 100644 --- a/src/emu/luaengine.cpp +++ b/src/emu/luaengine.cpp @@ -10,18 +10,16 @@ #include <limits> #include <thread> -#include "lua.hpp" +#include <lua.hpp> #include "luabridge/Source/LuaBridge/LuaBridge.h" #include <signal.h> #include "emu.h" #include "cheat.h" #include "drivenum.h" +#include "emuopts.h" #include "ui/ui.h" #include "luaengine.h" #include <mutex> -#if !defined(NO_LIBUV) -#include "libuv/include/uv.h" -#endif //************************************************************************** // LUA ENGINE @@ -52,10 +50,6 @@ extern "C" { int luaopen_lsqlite3(lua_State *L); int luaopen_zlib(lua_State *L); int luaopen_lfs(lua_State *L); -#if !defined(NO_LIBUV) - int luaopen_luv(lua_State *L); - uv_loop_t* luv_loop(lua_State* L); -#endif } static void lstop(lua_State *L, lua_Debug *ar) @@ -252,6 +246,16 @@ int lua_engine::l_emu_romname(lua_State *L) } //------------------------------------------------- +// emu_softname - returns softlist name +//------------------------------------------------- + +int lua_engine::l_emu_softname(lua_State *L) +{ + lua_pushstring(L, luaThis->machine().options().software_name()); + return 1; +} + +//------------------------------------------------- // emu_pause/emu_unpause - pause/unpause game //------------------------------------------------- @@ -389,9 +393,9 @@ luabridge::LuaRef lua_engine::l_options_get_entries(const T *o) luabridge::LuaRef entries_table = luabridge::LuaRef::newTable(L); int unadorned_index = 0; - for (typename T::entry *curentry = options->first(); curentry != nullptr; curentry = curentry->next()) + for (typename T::entry &curentry : *options) { - const char *name = curentry->name(); + const char *name = curentry.name(); bool is_unadorned = false; // check if it's unadorned if (name && strlen(name) && !strcmp(name, options->unadorned(unadorned_index))) @@ -399,8 +403,8 @@ luabridge::LuaRef lua_engine::l_options_get_entries(const T *o) unadorned_index++; is_unadorned = true; } - if (!curentry->is_header() && !curentry->is_command() && !curentry->is_internal() && !is_unadorned) - entries_table[name] = curentry; + if (!curentry.is_header() && !curentry.is_command() && !curentry.is_internal() && !is_unadorned) + entries_table[name] = &curentry; } return entries_table; @@ -455,8 +459,8 @@ luabridge::LuaRef lua_engine::l_cheat_get_entries(const cheat_manager *c) luabridge::LuaRef entry_table = luabridge::LuaRef::newTable(L); int cheatnum = 0; - for (cheat_entry *entry = cm->first(); entry != nullptr; entry = entry->next()) { - entry_table[cheatnum++] = entry; + for (cheat_entry &entry : cm->entries()) { + entry_table[cheatnum++] = &entry; } return entry_table; @@ -493,10 +497,9 @@ luabridge::LuaRef lua_engine::l_ioport_get_ports(const ioport_manager *m) ioport_manager *im = const_cast<ioport_manager *>(m); lua_State *L = luaThis->m_lua_state; luabridge::LuaRef port_table = luabridge::LuaRef::newTable(L); - ioport_port *port; - for (port = im->first_port(); port != nullptr; port = port->next()) { - port_table[port->tag()] = port; + for (ioport_port &port : im->ports()) { + port_table[port.tag()] = &port; } return port_table; @@ -512,10 +515,9 @@ luabridge::LuaRef lua_engine::l_ioports_port_get_fields(const ioport_port *i) ioport_port *p = const_cast<ioport_port *>(i); lua_State *L = luaThis->m_lua_state; luabridge::LuaRef f_table = luabridge::LuaRef::newTable(L); - ioport_field *field; - for (field = p->first_field(); field != nullptr; field = field->next()) { - f_table[field->name()] = field; + for (ioport_field &field : p->fields()) { + f_table[field.name()] = &field; } return f_table; @@ -532,9 +534,9 @@ luabridge::LuaRef lua_engine::l_render_get_targets(const render_manager *r) luabridge::LuaRef target_table = luabridge::LuaRef::newTable(L); int tc = 0; - for (render_target *curr_rt = r->first_target(); curr_rt != nullptr; curr_rt = curr_rt->next()) + for (render_target &curr_rt : r->targets()) { - target_table[tc++] = curr_rt; + target_table[tc++] = &curr_rt; } return target_table; @@ -544,10 +546,10 @@ luabridge::LuaRef lua_engine::l_render_get_targets(const render_manager *r) luabridge::LuaRef lua_engine::devtree_dfs(device_t *root, luabridge::LuaRef devs_table) { if (root) { - for (device_t *dev = root->first_subdevice(); dev != nullptr; dev = dev->next()) { - if (dev && dev->configured() && dev->started()) { - devs_table[dev->tag()] = dev; - devtree_dfs(dev, devs_table); + for (device_t &dev : root->subdevices()) { + if (dev.configured() && dev.started()) { + devs_table[dev.tag()] = &dev; + devtree_dfs(&dev, devs_table); } } } @@ -584,11 +586,10 @@ luabridge::LuaRef lua_engine::l_dev_get_states(const device_t *d) device_t *dev = const_cast<device_t *>(d); lua_State *L = luaThis->m_lua_state; luabridge::LuaRef st_table = luabridge::LuaRef::newTable(L); - for (const device_state_entry *s = dev->state().state_first(); s != nullptr; s = s->next()) { + for (device_state_entry &s : dev->state().state_entries()) + { // XXX: refrain from exporting non-visible entries? - if (s) { - st_table[s->symbol()] = const_cast<device_state_entry *>(s); - } + st_table[s.symbol()] = &s; } return st_table; @@ -845,6 +846,54 @@ int lua_engine::lua_screen::l_width(lua_State *L) return 1; } + +//------------------------------------------------- +// screen_orientation - return screen orientation +// -> manager:machine().screens[":screen"]:orientation() +// -> rotation_angle (0, 90, 180, 270) +// -> flipx (true, false) +// -> flipy (true, false) +//------------------------------------------------- + +int lua_engine::lua_screen::l_orientation(lua_State *L) +{ + UINT32 flags = (luaThis->machine().system().flags & ORIENTATION_MASK); + + int rotation_angle = 0; + switch (flags) + { + case ORIENTATION_FLIP_X: + rotation_angle = 0; + break; + case ORIENTATION_SWAP_XY: + case ORIENTATION_SWAP_XY|ORIENTATION_FLIP_X: + rotation_angle = 90; + break; + case ORIENTATION_FLIP_Y: + case ORIENTATION_FLIP_X|ORIENTATION_FLIP_Y: + rotation_angle = 180; + break; + case ORIENTATION_SWAP_XY|ORIENTATION_FLIP_Y: + case ORIENTATION_SWAP_XY|ORIENTATION_FLIP_X|ORIENTATION_FLIP_Y: + rotation_angle = 270; + break; + } + + lua_createtable(L, 2, 2); + lua_pushliteral(L, "rotation_angle"); + lua_pushinteger(L, rotation_angle); + + lua_settable(L, -3); + lua_pushliteral(L, "flipx"); + lua_pushboolean(L, (flags & ORIENTATION_FLIP_X)); + + lua_settable(L, -3); + lua_pushliteral(L, "flipy"); + lua_pushboolean(L, (flags & ORIENTATION_FLIP_Y)); + lua_settable(L, -3); + return 1; +} + //------------------------------------------------- // screen_refresh - return screen refresh rate // -> manager:machine().screens[":screen"]:refresh() @@ -877,7 +926,7 @@ int lua_engine::lua_screen::l_snapshot(lua_State *L) luaL_argcheck(L, lua_isstring(L, 2) || lua_isnone(L, 2), 2, "optional argument: filename, string expected"); emu_file file(sc->machine().options().snapshot_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS); - file_error filerr; + osd_file::error filerr; if (!lua_isnone(L, 2)) { const char *filename = lua_tostring(L, 2); @@ -891,9 +940,9 @@ int lua_engine::lua_screen::l_snapshot(lua_State *L) filerr = sc->machine().video().open_next(file, "png"); } - if (filerr != FILERR_NONE) + if (filerr != osd_file::error::NONE) { - luaL_error(L, "file_error=%d", filerr); + luaL_error(L, "osd_file::error=%d", filerr); return 0; } @@ -920,6 +969,7 @@ int lua_engine::lua_screen::l_type(lua_State *L) case SCREEN_TYPE_RASTER: lua_pushliteral(L, "raster"); break; case SCREEN_TYPE_VECTOR: lua_pushliteral(L, "vector"); break; case SCREEN_TYPE_LCD: lua_pushliteral(L, "lcd"); break; + case SCREEN_TYPE_SVG: lua_pushliteral(L, "svg"); break; default: lua_pushliteral(L, "unknown"); break; } @@ -1199,12 +1249,6 @@ lua_engine::lua_engine() lua_getfield(m_lua_state, -1, "preload"); lua_remove(m_lua_state, -2); // Remove package -#if !defined(NO_LIBUV) - // Store uv module definition at preload.uv - lua_pushcfunction(m_lua_state, luaopen_luv); - lua_setfield(m_lua_state, -2, "luv"); -#endif - lua_pushcfunction(m_lua_state, luaopen_zlib); lua_setfield(m_lua_state, -2, "zlib"); @@ -1231,6 +1275,82 @@ lua_engine::~lua_engine() close(); } +std::vector<lua_engine::menu_item> &lua_engine::menu_populate(std::string &menu) +{ + std::vector<menu_item> &menu_list = *global_alloc(std::vector<menu_item>); + std::string field = "menu_pop_" + menu; + lua_settop(m_lua_state, 0); + lua_getfield(m_lua_state, LUA_REGISTRYINDEX, field.c_str()); + + if(!lua_isfunction(m_lua_state, -1)) + { + lua_pop(m_lua_state, 1); + return menu_list; + } + lua_pcall(m_lua_state, 0, 1, 0); + if(!lua_istable(m_lua_state, -1)) + { + lua_pop(m_lua_state, 1); + return menu_list; + } + + lua_pushnil(m_lua_state); + while(lua_next(m_lua_state, -2)) + { + if(lua_istable(m_lua_state, -1)) + { + menu_item item; + lua_rawgeti(m_lua_state, -1, 1); + item.text = lua_tostring(m_lua_state, -1); + lua_pop(m_lua_state, 1); + lua_rawgeti(m_lua_state, -1, 2); + item.subtext = lua_tostring(m_lua_state, -1); + lua_pop(m_lua_state, 1); + lua_rawgeti(m_lua_state, -1, 3); + item.flags = lua_tointeger(m_lua_state, -1); + lua_pop(m_lua_state, 1); + menu_list.push_back(item); + } + lua_pop(m_lua_state, 1); + } + lua_pop(m_lua_state, 1); + return menu_list; +} + +bool lua_engine::menu_callback(std::string &menu, int index, std::string event) +{ + std::string field = "menu_cb_" + menu; + bool ret = false; + lua_settop(m_lua_state, 0); + lua_getfield(m_lua_state, LUA_REGISTRYINDEX, field.c_str()); + + if(lua_isfunction(m_lua_state, -1)) + { + lua_pushinteger(m_lua_state, index); + lua_pushstring(m_lua_state, event.c_str()); + lua_pcall(m_lua_state, 2, 1, 0); + ret = lua_toboolean(m_lua_state, -1); + lua_pop(m_lua_state, 1); + } + return ret; +} + +int lua_engine::l_emu_register_menu(lua_State *L) +{ + luaL_argcheck(L, lua_isfunction(L, 1), 1, "callback function expected"); + luaL_argcheck(L, lua_isfunction(L, 2), 2, "callback function expected"); + luaL_argcheck(L, lua_isstring(L, 3), 3, "message (string) expected"); + std::string name = luaL_checkstring(L, 3); + std::string cbfield = "menu_cb_" + name; + std::string popfield = "menu_pop_" + name; + luaThis->m_menu.push_back(std::string(name)); + lua_pushvalue(L, 1); + lua_setfield(L, LUA_REGISTRYINDEX, cbfield.c_str()); + lua_pushvalue(L, 2); + lua_setfield(L, LUA_REGISTRYINDEX, popfield.c_str()); + return 1; +} + void lua_engine::execute_function(const char *id) { lua_settop(m_lua_state, 0); @@ -1243,7 +1363,12 @@ void lua_engine::execute_function(const char *id) { if (lua_isfunction(m_lua_state, -1)) { - lua_pcall(m_lua_state, 0, 0, 0); + if(int error = lua_pcall(m_lua_state, 0, 0, 0)) + { + if(error == 2) + printf("%s\n", lua_tostring(m_lua_state, -1)); + lua_pop(m_lua_state, 1); + } } else { @@ -1274,6 +1399,11 @@ int lua_engine::register_function(lua_State *L, const char *id) return 1; } +int lua_engine::l_emu_register_prestart(lua_State *L) +{ + return register_function(L, "LUA_ON_PRESTART"); +} + int lua_engine::l_emu_register_start(lua_State *L) { return register_function(L, "LUA_ON_START"); @@ -1299,6 +1429,11 @@ int lua_engine::l_emu_register_frame(lua_State *L) return register_function(L, "LUA_ON_FRAME"); } +void lua_engine::on_machine_prestart() +{ + execute_function("LUA_ON_PRESTART"); +} + void lua_engine::on_machine_start() { execute_function("LUA_ON_START"); @@ -1330,17 +1465,16 @@ void lua_engine::update_machine() if (m_machine!=nullptr) { // Create the ioport array - ioport_port *port = machine().ioport().first_port(); - while(port) { - ioport_field *field = port->first_field(); - while(field) { - if(field->name()) { - push(m_lua_state, field, tname_ioport); - lua_setfield(m_lua_state, -2, field->name()); + for (ioport_port &port : machine().ioport().ports()) + { + for (ioport_field &field : port.fields()) + { + if (field.name()) + { + push(m_lua_state, &field, tname_ioport); + lua_setfield(m_lua_state, -2, field.name()); } - field = field->next(); } - port = port->next(); } } lua_setglobal(m_lua_state, "ioport"); @@ -1348,6 +1482,7 @@ void lua_engine::update_machine() void lua_engine::attach_notifiers() { + machine().add_notifier(MACHINE_NOTIFY_RESET, machine_notify_delegate(FUNC(lua_engine::on_machine_prestart), this), true); machine().add_notifier(MACHINE_NOTIFY_RESET, machine_notify_delegate(FUNC(lua_engine::on_machine_start), this)); machine().add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(FUNC(lua_engine::on_machine_stop), this)); machine().add_notifier(MACHINE_NOTIFY_PAUSE, machine_notify_delegate(FUNC(lua_engine::on_machine_pause), this)); @@ -1355,6 +1490,22 @@ void lua_engine::attach_notifiers() machine().add_notifier(MACHINE_NOTIFY_FRAME, machine_notify_delegate(FUNC(lua_engine::on_machine_frame), this)); } +int lua_engine::lua_machine::l_popmessage(lua_State *L) +{ + running_machine *m = luabridge::Stack<running_machine *>::get(L, 1); + luaL_argcheck(L, lua_isstring(L, 2), 2, "message (string) expected"); + m->popmessage("%s", luaL_checkstring(L, 2)); + return 0; +} + +int lua_engine::lua_machine::l_logerror(lua_State *L) +{ + running_machine *m = luabridge::Stack<running_machine *>::get(L, 1); + luaL_argcheck(L, lua_isstring(L, 2), 2, "message (string) expected"); + m->logerror("[luaengine] %s\n", luaL_checkstring(L, 2)); + return 0; +} + //------------------------------------------------- // initialize - initialize lua hookup to emu engine //------------------------------------------------- @@ -1367,6 +1518,7 @@ void lua_engine::initialize() .addCFunction ("app_version", l_emu_app_version ) .addCFunction ("gamename", l_emu_gamename ) .addCFunction ("romname", l_emu_romname ) + .addCFunction ("softname", l_emu_softname ) .addCFunction ("keypost", l_emu_keypost ) .addCFunction ("hook_output", l_emu_hook_output ) .addCFunction ("sethook", l_emu_set_hook ) @@ -1377,16 +1529,23 @@ void lua_engine::initialize() .addCFunction ("start", l_emu_start ) .addCFunction ("pause", l_emu_pause ) .addCFunction ("unpause", l_emu_unpause ) + .addCFunction ("register_prestart", l_emu_register_prestart ) .addCFunction ("register_start", l_emu_register_start ) .addCFunction ("register_stop", l_emu_register_stop ) .addCFunction ("register_pause", l_emu_register_pause ) .addCFunction ("register_resume",l_emu_register_resume ) .addCFunction ("register_frame", l_emu_register_frame ) - .beginClass <machine_manager> ("manager") + .addCFunction ("register_menu", l_emu_register_menu ) + .beginClass <machine_manager> ("manager") .addFunction ("machine", &machine_manager::machine) .addFunction ("options", &machine_manager::options) + .addFunction ("plugins", &machine_manager::plugins) + .endClass () + .beginClass <lua_machine> ("lua_machine") + .addCFunction ("popmessage", &lua_machine::l_popmessage) + .addCFunction ("logerror", &lua_machine::l_logerror) .endClass () - .beginClass <running_machine> ("machine") + .deriveClass <running_machine, lua_machine> ("machine") .addFunction ("exit", &running_machine::schedule_exit) .addFunction ("hard_reset", &running_machine::schedule_hard_reset) .addFunction ("soft_reset", &running_machine::schedule_soft_reset) @@ -1509,6 +1668,8 @@ void lua_engine::initialize() .endClass() .deriveClass <ui_options, core_options> ("ui_options") .endClass() + .deriveClass <plugin_options, core_options> ("plugin_options") + .endClass() .beginClass <parameters_manager> ("parameters") .addFunction ("add", ¶meters_manager::add) .addFunction ("lookup", ¶meters_manager::lookup) @@ -1592,6 +1753,7 @@ void lua_engine::initialize() .addCFunction ("draw_text", &lua_screen::l_draw_text) .addCFunction ("height", &lua_screen::l_height) .addCFunction ("width", &lua_screen::l_width) + .addCFunction ("orientation", &lua_screen::l_orientation) .addCFunction ("refresh", &lua_screen::l_refresh) .addCFunction ("snapshot", &lua_screen::l_snapshot) .addCFunction ("type", &lua_screen::l_type) @@ -1670,11 +1832,6 @@ void lua_engine::periodic_check() msg.ready = 0; msg.done = 1; } -#if !defined(NO_LIBUV) - auto loop = luv_loop(m_lua_state); - if (loop!=nullptr) - uv_run(loop, UV_RUN_NOWAIT); -#endif } //------------------------------------------------- @@ -1727,13 +1884,13 @@ void lua_engine::start() namespace luabridge { template <> - struct Stack <UINT64> { - static inline void push (lua_State* L, UINT64 value) { + struct Stack <unsigned long long> { + static inline void push (lua_State* L, unsigned long long value) { lua_pushunsigned(L, static_cast <lua_Unsigned> (value)); } - static inline UINT64 get (lua_State* L, int index) { - return static_cast <UINT64> (luaL_checkunsigned (L, index)); + static inline unsigned long long get (lua_State* L, int index) { + return static_cast <unsigned long long> (luaL_checkunsigned (L, index)); } }; } |