// license:BSD-3-Clause
// copyright-holders:Miodrag Milanovic
/***************************************************************************
luaengine.c
Controls execution of the core MAME system.
***************************************************************************/
#include "emu.h"
#include "emuopts.h"
#include "osdepend.h"
#include "lua/lua.hpp"
lua_engine* lua_engine::luaThis = NULL;
//**************************************************************************
// LUA ENGINE
//**************************************************************************
//-------------------------------------------------
// emu_gamename - returns game full name
//-------------------------------------------------
int lua_engine::emu_gamename(lua_State *L)
{
lua_pushstring(L, luaThis->machine().system().description);
return 1;
}
//-------------------------------------------------
// emu_keypost - post keys to natural keyboard
//-------------------------------------------------
int lua_engine::emu_keypost(lua_State *L)
{
const char *keys = luaL_checkstring(L,1);
luaThis->machine().ioport().natkeyboard().post_utf8(keys);
return 1;
}
static const struct luaL_Reg emu_funcs [] =
{
{ "gamename", lua_engine::emu_gamename },
{ "keypost", lua_engine::emu_keypost },
{ NULL, NULL } /* sentinel */
};
//-------------------------------------------------
// luaopen_emu - connect emu section lib
//-------------------------------------------------
int luaopen_emu ( lua_State * L )
{
luaL_newlib(L, emu_funcs);
return 1;
}
//-------------------------------------------------
// hook - lua hook to make slice execution of
// script possible
//-------------------------------------------------
void hook(lua_State* l, lua_Debug* ar)
{
lua_yield(l, 0);
}
//-------------------------------------------------
// lua_engine - constructor
//-------------------------------------------------
lua_engine::lua_engine(running_machine &machine)
: m_machine(machine)
{
luaThis = this;
m_lua_state = NULL;
}
//-------------------------------------------------
// ~lua_engine - destructor
//-------------------------------------------------
lua_engine::~lua_engine()
{
close();
}
//-------------------------------------------------
// initialize - initialize lua hookup to emu engine
//-------------------------------------------------
void lua_engine::initialize()
{
machine().add_notifier(MACHINE_NOTIFY_FRAME, machine_notify_delegate(FUNC(lua_engine::lua_execute), this));
}
//-------------------------------------------------
// close - close and cleanup of lua engine
//-------------------------------------------------
void lua_engine::close()
{
if (m_lua_state) {
// close the Lua state
lua_close(m_lua_state);
osd_printf_verbose("[LUA] End executing script\n");
m_lua_state = NULL;
}
}
//-------------------------------------------------
// report_errors - report lua error in execution
//-------------------------------------------------
void lua_engine::report_errors(int status)
{
if ( status!=0 ) {
osd_printf_error("[LUA ERROR] %s\n",lua_tostring(m_lua_state, -1));
lua_pop(m_lua_state, 1); // remove error message
close(); // close in case of error
}
}
//-------------------------------------------------
// createvm - setup lua VM and load script
//-------------------------------------------------
void lua_engine::createvm()
{
close();
// create new Lua state
m_lua_state = luaL_newstate();
luaL_openlibs(m_lua_state);
luaL_requiref(m_lua_state, "emu", luaopen_emu, 1);
lua_sethook(m_lua_state, hook, LUA_MASKLINE, 0);
}
//-------------------------------------------------
// execute - load and execute script
//-------------------------------------------------
void lua_engine::execute(const char *filename)
{
createvm();
int s = luaL_loadfile(m_lua_state, filename);
report_errors(s);
osd_printf_verbose("[LUA] Start executing script\n");
}
//-------------------------------------------------
// execute_string - execute script from string
//-------------------------------------------------
void lua_engine::execute_string(const char *value)
{
createvm();
int s = luaL_loadstring(m_lua_state, value);
report_errors(s);
osd_printf_verbose("[LUA] Start executing script\n");
}
//-------------------------------------------------
// lua_execute - execute slice of lua script
// this callback is hooked to frame notification
//-------------------------------------------------
void lua_engine::lua_execute()
{
if (m_lua_state==NULL) return;
int s = lua_resume(m_lua_state, m_lua_state, 0);
if (s != LUA_YIELD) {
report_errors(s);
close();
}
}