summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--plugins/dummy/init.lua11
-rw-r--r--scripts/src/emu.lua2
-rw-r--r--src/emu/luaengine.cpp86
-rw-r--r--src/emu/luaengine.h13
-rw-r--r--src/emu/ui/mainmenu.cpp8
-rw-r--r--src/emu/ui/mainmenu.h1
-rw-r--r--src/emu/ui/pluginopt.cpp100
-rw-r--r--src/emu/ui/pluginopt.h38
8 files changed, 257 insertions, 2 deletions
diff --git a/plugins/dummy/init.lua b/plugins/dummy/init.lua
index 3ef8fe3fc0b..8058bcad452 100644
--- a/plugins/dummy/init.lua
+++ b/plugins/dummy/init.lua
@@ -17,6 +17,17 @@ function dummy.startplugin()
emu.register_stop(function()
print("Exiting " .. emu.gamename())
end)
+
+ local function menu_populate()
+ return {{ "This is a", "test", 32 }, { "Also a", "test", 0 }} -- 32 is MENU_FLAG_DISABLE
+ end
+
+ local function menu_callback(index, event)
+ print("index: " .. index .. " event: " .. event)
+ return false
+ end
+
+ emu.register_menu(menu_callback, menu_populate, "Dummy")
end
return exports
diff --git a/scripts/src/emu.lua b/scripts/src/emu.lua
index e2fe63f5e10..ca3103422a5 100644
--- a/scripts/src/emu.lua
+++ b/scripts/src/emu.lua
@@ -216,6 +216,8 @@ files {
MAME_DIR .. "src/emu/ui/barcode.h",
MAME_DIR .. "src/emu/ui/cheatopt.cpp",
MAME_DIR .. "src/emu/ui/cheatopt.h",
+ MAME_DIR .. "src/emu/ui/pluginopt.cpp",
+ MAME_DIR .. "src/emu/ui/pluginopt.h",
MAME_DIR .. "src/emu/ui/devopt.cpp",
MAME_DIR .. "src/emu/ui/devopt.h",
MAME_DIR .. "src/emu/ui/filemngr.cpp",
diff --git a/src/emu/luaengine.cpp b/src/emu/luaengine.cpp
index 8de543669d2..ce170910c5c 100644
--- a/src/emu/luaengine.cpp
+++ b/src/emu/luaengine.cpp
@@ -1274,6 +1274,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);
@@ -1286,7 +1362,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
{
@@ -1453,7 +1534,8 @@ void lua_engine::initialize()
.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)
diff --git a/src/emu/luaengine.h b/src/emu/luaengine.h
index b98b9597b56..1ed1c82df36 100644
--- a/src/emu/luaengine.h
+++ b/src/emu/luaengine.h
@@ -49,9 +49,19 @@ public:
bool frame_hook();
void execute_function(const char *id);
+ struct menu_item {
+ std::string text;
+ std::string subtext;
+ int flags;
+ };
+ std::vector<menu_item> &menu_populate(std::string &menu);
+ bool menu_callback(std::string &menu, int index, std::string event);
+
void resume(lua_State *L, int nparam = 0, lua_State *root = nullptr);
void set_machine(running_machine *machine) { m_machine = machine; update_machine(); }
+ std::vector<std::string> &get_menu() { return m_menu; }
void attach_notifiers();
+
private:
struct hook {
lua_State *L;
@@ -70,6 +80,8 @@ private:
lua_State *m_lua_state;
running_machine * m_machine;
+ std::vector<std::string> m_menu;
+
hook hook_output_cb;
bool output_notifier_set;
@@ -121,6 +133,7 @@ private:
static int l_emu_register_pause(lua_State *L);
static int l_emu_register_resume(lua_State *L);
static int l_emu_register_frame(lua_State *L);
+ static int l_emu_register_menu(lua_State *L);
static int register_function(lua_State *L, const char *id);
// "emu.machine" namespace
diff --git a/src/emu/ui/mainmenu.cpp b/src/emu/ui/mainmenu.cpp
index 7fe16d771b0..33156e21ec2 100644
--- a/src/emu/ui/mainmenu.cpp
+++ b/src/emu/ui/mainmenu.cpp
@@ -33,6 +33,7 @@
#include "ui/datfile.h"
#include "ui/inifile.h"
#include "ui/datmenu.h"
+#include "ui/pluginopt.h"
/***************************************************************************
@@ -131,6 +132,9 @@ void ui_menu_main::populate()
if (machine().options().cheat())
item_append(_("Cheat"), nullptr, 0, (void *)CHEAT);
+ if (machine().options().plugins())
+ item_append(_("Plugin Options"), nullptr, 0, (void *)PLUGINS);
+
// add dats menu
if (machine().ui().options().enabled_dats() && machine().datfile().has_data())
item_append(_("External DAT View"), nullptr, 0, (void *)EXTERNAL_DATS);
@@ -241,6 +245,10 @@ void ui_menu_main::handle()
ui_menu::stack_push(global_alloc_clear<ui_menu_cheat>(machine(), container));
break;
+ case PLUGINS:
+ ui_menu::stack_push(global_alloc_clear<ui_menu_plugin>(machine(), container));
+ break;
+
case SELECT_GAME:
if (strcmp(machine().options().ui(),"simple")==0) {
ui_menu::stack_push(global_alloc_clear<ui_simple_menu_select_game>(machine(), container, nullptr));
diff --git a/src/emu/ui/mainmenu.h b/src/emu/ui/mainmenu.h
index 0684e230ad8..cb12e6e1d1a 100644
--- a/src/emu/ui/mainmenu.h
+++ b/src/emu/ui/mainmenu.h
@@ -42,6 +42,7 @@ private:
VIDEO_OPTIONS,
CROSSHAIR,
CHEAT,
+ PLUGINS,
SELECT_GAME,
BIOS_SELECTION,
BARCODE_READ,
diff --git a/src/emu/ui/pluginopt.cpp b/src/emu/ui/pluginopt.cpp
new file mode 100644
index 00000000000..625d60600f1
--- /dev/null
+++ b/src/emu/ui/pluginopt.cpp
@@ -0,0 +1,100 @@
+// license:BSD-3-Clause
+// copyright-holders:Nicola Salmoria, Aaron Giles, Nathan Woods
+/*********************************************************************
+
+ ui/pluginopt.cpp
+
+ Internal menu for the plugin interface.
+
+*********************************************************************/
+
+#include "emu.h"
+#include "luaengine.h"
+
+#include "ui/pluginopt.h"
+
+void ui_menu_plugin::handle()
+{
+ const ui_menu_event *menu_event = process(0);
+
+ if (menu_event != nullptr && menu_event->itemref != nullptr)
+ {
+ if (menu_event->iptkey == IPT_UI_SELECT)
+ ui_menu::stack_push(global_alloc_clear<ui_menu_plugin_opt>(machine(), container, (char *)menu_event->itemref));
+ }
+}
+
+ui_menu_plugin::ui_menu_plugin(running_machine &machine, render_container *container) :
+ ui_menu(machine, container),
+ m_plugins(machine.manager().lua()->get_menu())
+{
+}
+
+void ui_menu_plugin::populate()
+{
+ for (auto &curplugin : m_plugins)
+ item_append(curplugin.c_str(), 0, 0, (void *)curplugin.c_str());
+ item_append(MENU_SEPARATOR_ITEM, nullptr, 0, nullptr);
+}
+
+ui_menu_plugin::~ui_menu_plugin()
+{
+}
+
+ui_menu_plugin_opt::ui_menu_plugin_opt(running_machine &machine, render_container *container, char *menu) :
+ ui_menu(machine, container),
+ m_menu(menu)
+{
+}
+
+void ui_menu_plugin_opt::handle()
+{
+ const ui_menu_event *menu_event = process(0);
+
+ if (menu_event != nullptr && (FPTR)menu_event->itemref)
+ {
+ std::string key;
+ switch(menu_event->iptkey)
+ {
+ case IPT_UI_UP:
+ key = "up";
+ break;
+ case IPT_UI_DOWN:
+ key = "down";
+ break;
+ case IPT_UI_LEFT:
+ key = "left";
+ break;
+ case IPT_UI_RIGHT:
+ key = "right";
+ break;
+ case IPT_UI_SELECT:
+ key = "select";
+ break;
+ case IPT_UI_DISPLAY_COMMENT:
+ key = "comment";
+ break;
+ case IPT_UI_CLEAR:
+ key = "clear";
+ break;
+ default:
+ return;
+ }
+ if(machine().manager().lua()->menu_callback(m_menu, (FPTR)menu_event->itemref, key))
+ reset(UI_MENU_RESET_REMEMBER_REF);
+ }
+}
+
+void ui_menu_plugin_opt::populate()
+{
+ std::vector<lua_engine::menu_item> &menu_list = machine().manager().lua()->menu_populate(m_menu);
+ FPTR i = 1;
+ for(auto &item : menu_list)
+ item_append(item.text.c_str(), item.subtext.c_str(), item.flags, (void *)i++);
+ item_append(MENU_SEPARATOR_ITEM, nullptr, 0, nullptr);
+ global_free(&menu_list);
+}
+
+ui_menu_plugin_opt::~ui_menu_plugin_opt()
+{
+}
diff --git a/src/emu/ui/pluginopt.h b/src/emu/ui/pluginopt.h
new file mode 100644
index 00000000000..9d529e93749
--- /dev/null
+++ b/src/emu/ui/pluginopt.h
@@ -0,0 +1,38 @@
+// license:BSD-3-Clause
+// copyright-holders:Nicola Salmoria, Aaron Giles, Nathan Woods, Carl
+/***************************************************************************
+
+ ui/pluginopt.h
+
+ Internal menu for the plugin interface.
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __UI_PLUGINOPT_H__
+#define __UI_PLUGINOPT_H__
+
+#include "ui/ui.h"
+#include "ui/menu.h"
+
+class ui_menu_plugin : public ui_menu {
+public:
+ ui_menu_plugin(running_machine &machine, render_container *container);
+ virtual ~ui_menu_plugin();
+ virtual void populate() override;
+ virtual void handle() override;
+private:
+ std::vector<std::string> &m_plugins;
+};
+
+class ui_menu_plugin_opt : public ui_menu {
+public:
+ ui_menu_plugin_opt(running_machine &machine, render_container *container, char *menu);
+ virtual ~ui_menu_plugin_opt();
+ virtual void populate() override;
+ virtual void handle() override;
+private:
+ std::string m_menu;
+};
+#endif /* __UI_PLUGINOPT_H__ */