mirror of
https://github.com/holub/mame
synced 2025-07-04 17:38:08 +03:00
Merge pull request #1642 from cracyc/luaconsole
Make console a Lua plugin
This commit is contained in:
commit
846dfa8ffd
9
3rdparty/lua-linenoise/linenoise.c
vendored
9
3rdparty/lua-linenoise/linenoise.c
vendored
@ -101,6 +101,14 @@ static int l_historyadd(lua_State *L)
|
|||||||
return handle_ln_ok(L);
|
return handle_ln_ok(L);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int l_preloadbuffer(lua_State *L)
|
||||||
|
{
|
||||||
|
const char *line = luaL_checkstring(L, 1);
|
||||||
|
linenoisePreloadBuffer(line);
|
||||||
|
|
||||||
|
return handle_ln_ok(L);
|
||||||
|
}
|
||||||
|
|
||||||
static int l_historysetmaxlen(lua_State *L)
|
static int l_historysetmaxlen(lua_State *L)
|
||||||
{
|
{
|
||||||
int len = luaL_checkinteger(L, 1);
|
int len = luaL_checkinteger(L, 1);
|
||||||
@ -168,6 +176,7 @@ luaL_Reg linenoise_funcs[] = {
|
|||||||
{ "clearscreen", l_clearscreen },
|
{ "clearscreen", l_clearscreen },
|
||||||
{ "setcompletion", l_setcompletion},
|
{ "setcompletion", l_setcompletion},
|
||||||
{ "addcompletion", l_addcompletion },
|
{ "addcompletion", l_addcompletion },
|
||||||
|
{ "preload", l_preloadbuffer },
|
||||||
|
|
||||||
/* Aliases for more consistent function names */
|
/* Aliases for more consistent function names */
|
||||||
{ "addhistory", l_historyadd },
|
{ "addhistory", l_historyadd },
|
||||||
|
104
plugins/console/init.lua
Normal file
104
plugins/console/init.lua
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
-- license:BSD-3-Clause
|
||||||
|
-- copyright-holders:Carl
|
||||||
|
local exports = {}
|
||||||
|
exports.name = "console"
|
||||||
|
exports.version = "0.0.1"
|
||||||
|
exports.description = "Console plugin"
|
||||||
|
exports.license = "The BSD 3-Clause License"
|
||||||
|
exports.author = { name = "Carl" }
|
||||||
|
|
||||||
|
local console = exports
|
||||||
|
|
||||||
|
function console.startplugin()
|
||||||
|
local conth = emu.thread()
|
||||||
|
local started = false
|
||||||
|
local ln = require("linenoise")
|
||||||
|
local preload = false
|
||||||
|
print(" _/ _/ _/_/ _/ _/ _/_/_/_/");
|
||||||
|
print(" _/_/ _/_/ _/ _/ _/_/ _/_/ _/ ");
|
||||||
|
print(" _/ _/ _/ _/_/_/_/ _/ _/ _/ _/_/_/ ");
|
||||||
|
print(" _/ _/ _/ _/ _/ _/ _/ ");
|
||||||
|
print("_/ _/ _/ _/ _/ _/ _/_/_/_/ \n");
|
||||||
|
print(emu.app_name() .. " " .. emu.app_version(), "\nCopyright (C) Nicola Salmoria and the MAME team\n");
|
||||||
|
print(_VERSION, "\nCopyright (C) Lua.org, PUC-Rio\n");
|
||||||
|
-- linenoise isn't thread safe but that means history can handled here
|
||||||
|
-- that also means that bad things will happen if anything outside lua tries to use it
|
||||||
|
-- especially the completion callback
|
||||||
|
ln.historysetmaxlen(10)
|
||||||
|
local scr = "local ln = require('linenoise')\n"
|
||||||
|
scr = scr .. "ln.setcompletion(function(c, str) status = str\n"
|
||||||
|
scr = scr .. " yield()\n" -- coroutines can't yield in the middle of a callback so this is a real thread
|
||||||
|
scr = scr .. " status:gsub('[^,]*', function(s) if s ~= '' then ln.addcompletion(c, s) end end)\n"
|
||||||
|
scr = scr .. "end)\n"
|
||||||
|
scr = scr .. "return ln.linenoise('\x1b[1;36m[MAME]\x1b[0m> ')"
|
||||||
|
|
||||||
|
local function get_completions(str)
|
||||||
|
local function is_pair_iterable(t)
|
||||||
|
local mt = getmetatable(t)
|
||||||
|
return type(t) == 'table' or (mt and mt.__pairs)
|
||||||
|
end
|
||||||
|
local comps = ","
|
||||||
|
local table = str:match("([(]?[%w.:()]-)[:.]?[%w_]*$")
|
||||||
|
local rest, last = str:match("(.-[:.]?)([%w_]*)$")
|
||||||
|
local err
|
||||||
|
if table == "" then
|
||||||
|
table = "_G"
|
||||||
|
end
|
||||||
|
err, tablef = pcall(load("return " .. table))
|
||||||
|
if (not err) or (not tablef) then
|
||||||
|
return comps
|
||||||
|
end
|
||||||
|
if is_pair_iterable(tablef) then
|
||||||
|
for k, v in pairs(tablef) do
|
||||||
|
if k:match("^" .. last) then
|
||||||
|
comps = comps .. "," .. rest .. k
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local tablef = getmetatable(tablef)
|
||||||
|
if is_pair_iterable(tablef) then
|
||||||
|
for k, v in pairs(tablef) do
|
||||||
|
if k:match("^" .. last) then
|
||||||
|
comps = comps .. "," .. rest .. k
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return comps
|
||||||
|
end
|
||||||
|
|
||||||
|
emu.register_periodic(function()
|
||||||
|
if conth.yield then
|
||||||
|
conth:continue(get_completions(conth.result))
|
||||||
|
return
|
||||||
|
elseif conth.busy then
|
||||||
|
return
|
||||||
|
elseif started then
|
||||||
|
local cmd = conth.result
|
||||||
|
local func, err = load(cmd)
|
||||||
|
if not func then
|
||||||
|
if err:match("<eof>") then
|
||||||
|
print("incomplete command")
|
||||||
|
ln.preload(cmd)
|
||||||
|
preload = true
|
||||||
|
else
|
||||||
|
print("error: ", err)
|
||||||
|
preload = false
|
||||||
|
end
|
||||||
|
else
|
||||||
|
preload = false
|
||||||
|
local status
|
||||||
|
status, err = pcall(func)
|
||||||
|
if not status then
|
||||||
|
print("error: ", err)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if not preload then
|
||||||
|
ln.historyadd(cmd)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
conth:start(scr)
|
||||||
|
started = true
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
return exports
|
10
plugins/console/plugin.json
Normal file
10
plugins/console/plugin.json
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"plugin": {
|
||||||
|
"name": "console",
|
||||||
|
"description": "Console plugin",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"author": "Carl",
|
||||||
|
"type": "plugin",
|
||||||
|
"start": "false"
|
||||||
|
}
|
||||||
|
}
|
@ -66,8 +66,6 @@ files {
|
|||||||
MAME_DIR .. "src/frontend/mame/cheat.h",
|
MAME_DIR .. "src/frontend/mame/cheat.h",
|
||||||
MAME_DIR .. "src/frontend/mame/clifront.cpp",
|
MAME_DIR .. "src/frontend/mame/clifront.cpp",
|
||||||
MAME_DIR .. "src/frontend/mame/clifront.h",
|
MAME_DIR .. "src/frontend/mame/clifront.h",
|
||||||
MAME_DIR .. "src/frontend/mame/console.cpp",
|
|
||||||
MAME_DIR .. "src/frontend/mame/console.h",
|
|
||||||
MAME_DIR .. "src/frontend/mame/info.cpp",
|
MAME_DIR .. "src/frontend/mame/info.cpp",
|
||||||
MAME_DIR .. "src/frontend/mame/info.h",
|
MAME_DIR .. "src/frontend/mame/info.h",
|
||||||
MAME_DIR .. "src/frontend/mame/language.cpp",
|
MAME_DIR .. "src/frontend/mame/language.cpp",
|
||||||
|
@ -29,7 +29,6 @@
|
|||||||
#include "ui/moptions.h"
|
#include "ui/moptions.h"
|
||||||
#include "language.h"
|
#include "language.h"
|
||||||
#include "pluginopts.h"
|
#include "pluginopts.h"
|
||||||
#include "console.h"
|
|
||||||
|
|
||||||
#include <new>
|
#include <new>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
@ -312,13 +311,7 @@ int cli_frontend::execute(int argc, char **argv)
|
|||||||
|
|
||||||
manager->start_luaengine();
|
manager->start_luaengine();
|
||||||
|
|
||||||
if (m_options.console()) {
|
|
||||||
//manager->lua()->start_console();
|
|
||||||
console_frontend console(m_options, m_osd);
|
|
||||||
console.start_console();
|
|
||||||
} else {
|
|
||||||
start_execution(manager, argc, argv, option_errors);
|
start_execution(manager, argc, argv, option_errors);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// handle exceptions of various types
|
// handle exceptions of various types
|
||||||
catch (emu_fatalerror &fatal)
|
catch (emu_fatalerror &fatal)
|
||||||
|
@ -1,138 +0,0 @@
|
|||||||
// license:BSD-3-Clause
|
|
||||||
// copyright-holders:Miodrag Milanovic
|
|
||||||
/***************************************************************************
|
|
||||||
|
|
||||||
console.c
|
|
||||||
|
|
||||||
Console interface frontend for MAME.
|
|
||||||
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
#include "emu.h"
|
|
||||||
#include "luaengine.h"
|
|
||||||
#include "console.h"
|
|
||||||
#include "linenoise-ng/include/linenoise.h"
|
|
||||||
#include "mame.h"
|
|
||||||
|
|
||||||
#include <atomic>
|
|
||||||
#include <thread>
|
|
||||||
|
|
||||||
static console_frontend *gConsole = nullptr;
|
|
||||||
//-------------------------------------------------
|
|
||||||
// console_frontend - constructor
|
|
||||||
//-------------------------------------------------
|
|
||||||
|
|
||||||
console_frontend::console_frontend(emu_options &options, osd_interface &osd)
|
|
||||||
: //m_options(options),
|
|
||||||
//m_osd(osd),
|
|
||||||
m_run(true),
|
|
||||||
m_wait(false),
|
|
||||||
m_prompt("\x1b[1;36m[MAME]\x1b[0m> ")
|
|
||||||
{
|
|
||||||
mame_machine_manager::instance()->lua()->sol()["quit"] = [this]() { cmd_quit(); };
|
|
||||||
m_commands.push_back("quit()");
|
|
||||||
mame_machine_manager::instance()->lua()->sol()["exit"] = [this]() { cmd_quit(); };
|
|
||||||
m_commands.push_back("exit()");
|
|
||||||
gConsole = this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------
|
|
||||||
// ~console_frontend - destructor
|
|
||||||
//-------------------------------------------------
|
|
||||||
|
|
||||||
console_frontend::~console_frontend()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void console_frontend::completion(char const* prefix, linenoiseCompletions* lc)
|
|
||||||
{
|
|
||||||
for (auto cmd : m_commands)
|
|
||||||
{
|
|
||||||
if (strncmp(prefix, cmd.c_str(), strlen(prefix)) == 0)
|
|
||||||
{
|
|
||||||
linenoiseAddCompletion(lc, cmd.c_str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void console_frontend::cmd_quit()
|
|
||||||
{
|
|
||||||
printf("Exiting application\n");
|
|
||||||
m_run.store(false);
|
|
||||||
m_wait.store(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
void console_frontend::read_console(std::string &cmdLine)
|
|
||||||
{
|
|
||||||
while (m_run.load())
|
|
||||||
{
|
|
||||||
while (m_wait.load())
|
|
||||||
{
|
|
||||||
using namespace std::chrono_literals;
|
|
||||||
std::this_thread::sleep_for(100ms);
|
|
||||||
}
|
|
||||||
if (!m_run.load()) break;
|
|
||||||
char* result = linenoise(m_prompt.c_str());
|
|
||||||
if (result == NULL)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else if (*result == '\0') {
|
|
||||||
free(result);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
cmdLine = std::string(result);
|
|
||||||
linenoiseHistoryAdd(result);
|
|
||||||
//m_prompt = "\x1b[1;36m[MAME]\x1b[0m \x1b[1;32m[test]\x1b[0m> ";
|
|
||||||
|
|
||||||
free(result);
|
|
||||||
m_wait.store(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void completionHook(char const* prefix, linenoiseCompletions* lc)
|
|
||||||
{
|
|
||||||
gConsole->completion(prefix, lc);
|
|
||||||
}
|
|
||||||
|
|
||||||
void console_frontend::start_console()
|
|
||||||
{
|
|
||||||
linenoiseInstallWindowChangeHandler();
|
|
||||||
std::string cmdLine = "";
|
|
||||||
const char* file = "./history";
|
|
||||||
|
|
||||||
linenoiseHistoryLoad(file);
|
|
||||||
linenoiseSetCompletionCallback(completionHook);
|
|
||||||
|
|
||||||
// Display app info
|
|
||||||
printf(" _/ _/ _/_/ _/ _/ _/_/_/_/\n");
|
|
||||||
printf(" _/_/ _/_/ _/ _/ _/_/ _/_/ _/ \n");
|
|
||||||
printf(" _/ _/ _/ _/_/_/_/ _/ _/ _/ _/_/_/ \n");
|
|
||||||
printf(" _/ _/ _/ _/ _/ _/ _/ \n");
|
|
||||||
printf("_/ _/ _/ _/ _/ _/ _/_/_/_/ \n");
|
|
||||||
printf("\n");
|
|
||||||
printf("%s v%s\n%s\n\n", emulator_info::get_appname(), build_version, emulator_info::get_copyright_info());
|
|
||||||
|
|
||||||
|
|
||||||
std::thread cinThread(&console_frontend::read_console, this, std::ref(cmdLine));
|
|
||||||
|
|
||||||
while (m_run.load())
|
|
||||||
{
|
|
||||||
if (m_wait.load())
|
|
||||||
{
|
|
||||||
mame_machine_manager::instance()->lua()->load_string(cmdLine.c_str());
|
|
||||||
cmdLine.clear();
|
|
||||||
m_wait.store(false);
|
|
||||||
} else {
|
|
||||||
using namespace std::chrono_literals;
|
|
||||||
std::this_thread::sleep_for(100ms);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m_run.store(false);
|
|
||||||
cinThread.join();
|
|
||||||
|
|
||||||
linenoiseHistorySave(file);
|
|
||||||
linenoiseHistoryFree();
|
|
||||||
}
|
|
@ -1,41 +0,0 @@
|
|||||||
// license:BSD-3-Clause
|
|
||||||
// copyright-holders:Miodrag Milanovic
|
|
||||||
/***************************************************************************
|
|
||||||
|
|
||||||
console.c
|
|
||||||
|
|
||||||
Console interface frontend for MAME.
|
|
||||||
|
|
||||||
***************************************************************************/
|
|
||||||
#ifndef MAME_FRONTEND_CONSOLE_H
|
|
||||||
#define MAME_FRONTEND_CONSOLE_H
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "emu.h"
|
|
||||||
|
|
||||||
struct linenoiseCompletions;
|
|
||||||
|
|
||||||
class console_frontend
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
// construction/destruction
|
|
||||||
console_frontend(emu_options &options, osd_interface &osd);
|
|
||||||
~console_frontend();
|
|
||||||
|
|
||||||
void start_console();
|
|
||||||
void completion(char const* prefix, linenoiseCompletions* lc);
|
|
||||||
|
|
||||||
private:
|
|
||||||
void read_console(std::string &cmdLine);
|
|
||||||
|
|
||||||
void cmd_quit();
|
|
||||||
// internal state
|
|
||||||
std::atomic<bool> m_run;
|
|
||||||
std::atomic<bool> m_wait;
|
|
||||||
std::string m_prompt;
|
|
||||||
|
|
||||||
std::vector<std::string> m_commands;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* MAME_FRONTEND_CONSOLE_H */
|
|
@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
|
#include <thread>
|
||||||
#include <lua.hpp>
|
#include <lua.hpp>
|
||||||
#include "emu.h"
|
#include "emu.h"
|
||||||
#include "mame.h"
|
#include "mame.h"
|
||||||
@ -668,6 +669,11 @@ void lua_engine::on_frame_done()
|
|||||||
execute_function("LUA_ON_FRAME_DONE");
|
execute_function("LUA_ON_FRAME_DONE");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void lua_engine::on_periodic()
|
||||||
|
{
|
||||||
|
execute_function("LUA_ON_PERIODIC");
|
||||||
|
}
|
||||||
|
|
||||||
void lua_engine::attach_notifiers()
|
void lua_engine::attach_notifiers()
|
||||||
{
|
{
|
||||||
machine().add_notifier(MACHINE_NOTIFY_RESET, machine_notify_delegate(&lua_engine::on_machine_prestart, this), true);
|
machine().add_notifier(MACHINE_NOTIFY_RESET, machine_notify_delegate(&lua_engine::on_machine_prestart, this), true);
|
||||||
@ -702,6 +708,7 @@ void lua_engine::initialize()
|
|||||||
* emu.register_resume(callback) - callback at resume
|
* emu.register_resume(callback) - callback at resume
|
||||||
* emu.register_frame(callback) - callback at end of frame
|
* emu.register_frame(callback) - callback at end of frame
|
||||||
* emu.register_frame_done(callback) - callback after frame is drawn to screen (for overlays)
|
* emu.register_frame_done(callback) - callback after frame is drawn to screen (for overlays)
|
||||||
|
* emu.register_periodic(callback) - periodic callback while program is running
|
||||||
* emu.register_menu(event_callback, populate_callback, name) - callbacks for plugin menu
|
* emu.register_menu(event_callback, populate_callback, name) - callbacks for plugin menu
|
||||||
* emu.print_verbose(str) -- output to stderr at verbose level
|
* emu.print_verbose(str) -- output to stderr at verbose level
|
||||||
* emu.print_error(str) -- output to stderr at error level
|
* emu.print_error(str) -- output to stderr at error level
|
||||||
@ -735,6 +742,7 @@ void lua_engine::initialize()
|
|||||||
emu["register_resume"] = [this](sol::function func){ register_function(func, "LUA_ON_RESUME"); };
|
emu["register_resume"] = [this](sol::function func){ register_function(func, "LUA_ON_RESUME"); };
|
||||||
emu["register_frame"] = [this](sol::function func){ register_function(func, "LUA_ON_FRAME"); };
|
emu["register_frame"] = [this](sol::function func){ register_function(func, "LUA_ON_FRAME"); };
|
||||||
emu["register_frame_done"] = [this](sol::function func){ register_function(func, "LUA_ON_FRAME_DONE"); };
|
emu["register_frame_done"] = [this](sol::function func){ register_function(func, "LUA_ON_FRAME_DONE"); };
|
||||||
|
emu["register_periodic"] = [this](sol::function func){ register_function(func, "LUA_ON_PERIODIC"); };
|
||||||
emu["register_menu"] = [this](sol::function cb, sol::function pop, const std::string &name) {
|
emu["register_menu"] = [this](sol::function cb, sol::function pop, const std::string &name) {
|
||||||
std::string cbfield = "menu_cb_" + name;
|
std::string cbfield = "menu_cb_" + name;
|
||||||
std::string popfield = "menu_pop_" + name;
|
std::string popfield = "menu_pop_" + name;
|
||||||
@ -767,6 +775,7 @@ void lua_engine::initialize()
|
|||||||
}
|
}
|
||||||
return item;
|
return item;
|
||||||
};
|
};
|
||||||
|
emu["thread"] = []() { context *ctx = new context; ctx->busy = false; ctx->yield = false; return ctx; };
|
||||||
|
|
||||||
emu.new_usertype<emu_file>("file", sol::call_constructor, sol::constructors<sol::types<const char *, uint32_t>>(),
|
emu.new_usertype<emu_file>("file", sol::call_constructor, sol::constructors<sol::types<const char *, uint32_t>>(),
|
||||||
"read", [](emu_file &file, sol::buffer *buff) { buff->set_len(file.read(buff->get_ptr(), buff->get_len())); return buff; },
|
"read", [](emu_file &file, sol::buffer *buff) { buff->set_len(file.read(buff->get_ptr(), buff->get_len())); return buff; },
|
||||||
@ -777,6 +786,64 @@ void lua_engine::initialize()
|
|||||||
"filename", &emu_file::filename,
|
"filename", &emu_file::filename,
|
||||||
"fullpath", &emu_file::fullpath);
|
"fullpath", &emu_file::fullpath);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* thread.start(scr) - run scr (string not function) in a seperate thread in a new empty (other then modules) lua context
|
||||||
|
* thread.continue(val) - resume thread and pass val to it
|
||||||
|
* thread.result() - get thread result as string
|
||||||
|
* thread.busy - check if thread is running
|
||||||
|
* thread.yield - check if thread is yielded
|
||||||
|
*/
|
||||||
|
|
||||||
|
sol().new_usertype<context>("thread",
|
||||||
|
sol::meta_function::garbage_collect, sol::destructor([](context *ctx) { delete ctx; }),
|
||||||
|
"start", [this](context &ctx, const char *scr) {
|
||||||
|
std::string script(scr);
|
||||||
|
if(ctx.busy)
|
||||||
|
return false;
|
||||||
|
std::thread th([&ctx, script]() {
|
||||||
|
sol::state thstate;
|
||||||
|
thstate.open_libraries();
|
||||||
|
thstate["package"]["preload"]["zlib"] = &luaopen_zlib;
|
||||||
|
thstate["package"]["preload"]["lfs"] = &luaopen_lfs;
|
||||||
|
thstate["package"]["preload"]["linenoise"] = &luaopen_linenoise;
|
||||||
|
sol::load_result res = thstate.load(script);
|
||||||
|
if(res.valid())
|
||||||
|
{
|
||||||
|
sol::protected_function func = res.get<sol::protected_function>();
|
||||||
|
thstate["yield"] = [&ctx, &thstate]() {
|
||||||
|
std::mutex m;
|
||||||
|
std::unique_lock<std::mutex> lock(m);
|
||||||
|
ctx.result = thstate["status"];
|
||||||
|
ctx.yield = true;
|
||||||
|
ctx.sync.wait(lock);
|
||||||
|
ctx.yield = false;
|
||||||
|
thstate["status"] = ctx.result;
|
||||||
|
};
|
||||||
|
auto ret = func();
|
||||||
|
if(ret.valid())
|
||||||
|
ctx.result = ret.get<const char *>();
|
||||||
|
}
|
||||||
|
ctx.busy = false;
|
||||||
|
});
|
||||||
|
ctx.busy = true;
|
||||||
|
ctx.yield = false;
|
||||||
|
th.detach();
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
"continue", [this](context &ctx, const char *val) {
|
||||||
|
if(!ctx.yield)
|
||||||
|
return;
|
||||||
|
ctx.result = val;
|
||||||
|
ctx.sync.notify_all();
|
||||||
|
},
|
||||||
|
"result", sol::property([this](context &ctx) -> std::string {
|
||||||
|
if(ctx.busy && !ctx.yield)
|
||||||
|
return "";
|
||||||
|
return ctx.result;
|
||||||
|
}),
|
||||||
|
"busy", sol::readonly(&context::busy),
|
||||||
|
"yield", sol::readonly(&context::yield));
|
||||||
|
|
||||||
sol().new_usertype<save_item>("item",
|
sol().new_usertype<save_item>("item",
|
||||||
sol::meta_function::garbage_collect, sol::destructor([](save_item *item) { delete item; }),
|
sol::meta_function::garbage_collect, sol::destructor([](save_item *item) { delete item; }),
|
||||||
"size", sol::readonly(&save_item::size),
|
"size", sol::readonly(&save_item::size),
|
||||||
|
@ -18,12 +18,11 @@
|
|||||||
#define __LUA_ENGINE_H__
|
#define __LUA_ENGINE_H__
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <condition_variable>
|
||||||
#define SOL_SAFE_USERTYPE
|
#define SOL_SAFE_USERTYPE
|
||||||
//#define SOL_CHECK_ARGUMENTS
|
//#define SOL_CHECK_ARGUMENTS
|
||||||
#include "sol2/sol.hpp"
|
#include "sol2/sol.hpp"
|
||||||
|
|
||||||
class cheat_manager;
|
|
||||||
|
|
||||||
struct lua_State;
|
struct lua_State;
|
||||||
|
|
||||||
class lua_engine
|
class lua_engine
|
||||||
@ -46,6 +45,7 @@ public:
|
|||||||
std::vector<std::string> &get_menu() { return m_menu; }
|
std::vector<std::string> &get_menu() { return m_menu; }
|
||||||
void attach_notifiers();
|
void attach_notifiers();
|
||||||
void on_frame_done();
|
void on_frame_done();
|
||||||
|
void on_periodic();
|
||||||
|
|
||||||
template<typename T, typename U>
|
template<typename T, typename U>
|
||||||
bool call_plugin(const std::string &name, const T in, U &out)
|
bool call_plugin(const std::string &name, const T in, U &out)
|
||||||
@ -153,6 +153,14 @@ private:
|
|||||||
void close();
|
void close();
|
||||||
|
|
||||||
void run(sol::load_result res);
|
void run(sol::load_result res);
|
||||||
|
|
||||||
|
struct context
|
||||||
|
{
|
||||||
|
std::string result;
|
||||||
|
std::condition_variable sync;
|
||||||
|
bool busy;
|
||||||
|
bool yield;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* __LUA_ENGINE_H__ */
|
#endif /* __LUA_ENGINE_H__ */
|
||||||
|
@ -326,6 +326,7 @@ void emulator_info::draw_user_interface(running_machine& machine)
|
|||||||
|
|
||||||
void emulator_info::periodic_check()
|
void emulator_info::periodic_check()
|
||||||
{
|
{
|
||||||
|
return mame_machine_manager::instance()->lua()->on_periodic();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool emulator_info::frame_hook()
|
bool emulator_info::frame_hook()
|
||||||
|
Loading…
Reference in New Issue
Block a user