summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/luaengine.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/emu/luaengine.cpp')
-rw-r--r--src/emu/luaengine.cpp277
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", &parameters_manager::add)
.addFunction ("lookup", &parameters_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));
}
};
}