diff options
| author | 2015-11-08 12:56:12 +0100 | |
|---|---|---|
| committer | 2015-11-08 12:56:12 +0100 | |
| commit | 7c19aac60e12d6f5ea301bdb34d7826a01e0b06f (patch) | |
| tree | f310d86aa2c6bfc19d115307dedde4eb0cd52dad /src/emu/luaengine.c | |
| parent | a57b46ae933badd7441ce1644711dbb851e2b504 (diff) | |
Rename *.c -> *.cpp in our source (nw)
Diffstat (limited to 'src/emu/luaengine.c')
| -rw-r--r-- | src/emu/luaengine.c | 1141 |
1 files changed, 0 insertions, 1141 deletions
diff --git a/src/emu/luaengine.c b/src/emu/luaengine.c deleted file mode 100644 index 989cb78f72b..00000000000 --- a/src/emu/luaengine.c +++ /dev/null @@ -1,1141 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Miodrag Milanovic,Luca Bruno -/*************************************************************************** - - luaengine.c - - Controls execution of the core MAME system. - -***************************************************************************/ - -#include <limits> -#include "lua.hpp" -#include "luabridge/Source/LuaBridge/LuaBridge.h" -#include <signal.h> -#include "emu.h" -#include "emuopts.h" -#include "osdepend.h" -#include "drivenum.h" -#include "ui/ui.h" -#include "luaengine.h" - -//************************************************************************** -// LUA ENGINE -//************************************************************************** - -#if !defined(LUA_PROMPT) -#define LUA_PROMPT "> " -#define LUA_PROMPT2 ">> " -#endif - -#if !defined(LUA_MAXINPUT) -#define LUA_MAXINPUT 512 -#endif - -#define lua_readline(b,p) \ - (fputs(p, stdout), fflush(stdout), /* show prompt */ \ - fgets(b, LUA_MAXINPUT, stdin) != NULL) /* get line */ - -static lua_State *globalL = NULL; - -#define luai_writestring(s,l) fwrite((s), sizeof(char), (l), stdout) -#define luai_writeline() (luai_writestring("\n", 1), fflush(stdout)) - -const char *const lua_engine::tname_ioport = "lua.ioport"; -lua_engine* lua_engine::luaThis = NULL; - -extern "C" { - int luaopen_lsqlite3(lua_State *L); -} - -static void lstop(lua_State *L, lua_Debug *ar) -{ - (void)ar; /* unused arg. */ - lua_sethook(L, NULL, 0, 0); - luaL_error(L, "interrupted!"); -} - - -static void laction(int i) -{ - signal(i, SIG_DFL); /* if another SIGINT happens before lstop, - terminate process (default action) */ - lua_sethook(globalL, lstop, LUA_MASKCALL | LUA_MASKRET | LUA_MASKCOUNT, 1); -} - -int lua_engine::report(int status) { - if (status != LUA_OK && !lua_isnil(m_lua_state, -1)) - { - const char *msg = lua_tostring(m_lua_state, -1); - if (msg == NULL) msg = "(error object is not a string)"; - lua_writestringerror("%s\n", msg); - lua_pop(m_lua_state, 1); - /* force a complete garbage collection in case of errors */ - lua_gc(m_lua_state, LUA_GCCOLLECT, 0); - } - return status; -} - - -static int traceback (lua_State *L) -{ - const char *msg = lua_tostring(L, 1); - if (msg) - luaL_traceback(L, L, msg, 1); - else if (!lua_isnoneornil(L, 1)) - { /* is there an error object? */ - if (!luaL_callmeta(L, 1, "__tostring")) /* try its 'tostring' metamethod */ - lua_pushliteral(L, "(no error message)"); - } - return 1; -} - - -int lua_engine::docall(int narg, int nres) -{ - int status; - int base = lua_gettop(m_lua_state) - narg; /* function index */ - lua_pushcfunction(m_lua_state, traceback); /* push traceback function */ - lua_insert(m_lua_state, base); /* put it under chunk and args */ - globalL = m_lua_state; /* to be available to 'laction' */ - signal(SIGINT, laction); - status = lua_pcall(m_lua_state, narg, nres, base); - signal(SIGINT, SIG_DFL); - lua_remove(m_lua_state, base); /* remove traceback function */ - return status; -} - -/* mark in error messages for incomplete statements */ -#define EOFMARK "<eof>" -#define marklen (sizeof(EOFMARK)/sizeof(char) - 1) - -int lua_engine::incomplete(int status) -{ - if (status == LUA_ERRSYNTAX) - { - size_t lmsg; - const char *msg = lua_tolstring(m_lua_state, -1, &lmsg); - if (lmsg >= marklen && strcmp(msg + lmsg - marklen, EOFMARK) == 0) - { - lua_pop(m_lua_state, 1); - return 1; - } - } - return 0; /* else... */ -} - -lua_engine::hook::hook() -{ - L = NULL; - cb = -1; -} - -#if (defined(__sun__) && defined(__svr4__)) || defined(__ANDROID__) || defined(__OpenBSD__) -#undef _L -#endif - -void lua_engine::hook::set(lua_State *_L, int idx) -{ - if (L) - luaL_unref(L, LUA_REGISTRYINDEX, cb); - - if (lua_isnil(_L, idx)) { - L = NULL; - cb = -1; - - } else { - L = _L; - lua_pushvalue(_L, idx); - cb = luaL_ref(_L, LUA_REGISTRYINDEX); - } -} - -lua_State *lua_engine::hook::precall() -{ - lua_State *T = lua_newthread(L); - lua_rawgeti(T, LUA_REGISTRYINDEX, cb); - return T; -} - -void lua_engine::hook::call(lua_engine *engine, lua_State *T, int nparam) -{ - engine->resume(T, nparam, L); -} - -void lua_engine::resume(lua_State *L, int nparam, lua_State *root) -{ - int s = lua_resume(L, NULL, nparam); - switch(s) { - case LUA_OK: - if(!root) { - std::map<lua_State *, std::pair<lua_State *, int> >::iterator i = thread_registry.find(L); - if(i != thread_registry.end()) { - luaL_unref(i->second.first, LUA_REGISTRYINDEX, i->second.second); - thread_registry.erase(i); - } - } else - lua_pop(root, 1); - break; - - case LUA_YIELD: - if(root) { - int id = luaL_ref(root, LUA_REGISTRYINDEX); - thread_registry[L] = std::pair<lua_State *, int>(root, id); - } - break; - - default: - osd_printf_error("[LUA ERROR] %s\n", lua_tostring(L, -1)); - lua_pop(L, 1); - break; - } -} - -void lua_engine::resume(void *_L, INT32 param) -{ - resume(static_cast<lua_State *>(_L)); -} - -int lua_engine::l_ioport_write(lua_State *L) -{ - ioport_field *field = static_cast<ioport_field *>(getparam(L, 1, tname_ioport)); - luaL_argcheck(L, lua_isnumber(L, 2), 2, "value expected"); - field->set_value(lua_tointeger(L, 2)); - return 0; -} - -//------------------------------------------------- -// emu_app_name - return application name -//------------------------------------------------- - -int lua_engine::l_emu_app_name(lua_State *L) -{ - lua_pushstring(L, emulator_info::get_appname_lower()); - return 1; -} - -//------------------------------------------------- -// emu_app_version - return application version -//------------------------------------------------- - -int lua_engine::l_emu_app_version(lua_State *L) -{ - lua_pushstring(L, bare_build_version); - return 1; -} - - -//------------------------------------------------- -// emu_gamename - returns game full name -//------------------------------------------------- - -int lua_engine::l_emu_gamename(lua_State *L) -{ - lua_pushstring(L, luaThis->machine().system().description); - return 1; -} - -//------------------------------------------------- -// emu_romname - returns rom base name -//------------------------------------------------- - -int lua_engine::l_emu_romname(lua_State *L) -{ - lua_pushstring(L, luaThis->machine().basename()); - return 1; -} - -//------------------------------------------------- -// emu_pause/emu_unpause - pause/unpause game -//------------------------------------------------- - -int lua_engine::l_emu_pause(lua_State *L) -{ - luaThis->machine().pause(); - return 0; -} - -int lua_engine::l_emu_unpause(lua_State *L) -{ - luaThis->machine().resume(); - return 0; -} - -//------------------------------------------------- -// emu_keypost - post keys to natural keyboard -//------------------------------------------------- - -int lua_engine::l_emu_keypost(lua_State *L) -{ - const char *keys = luaL_checkstring(L,1); - luaThis->machine().ioport().natkeyboard().post_utf8(keys); - return 1; -} - -int lua_engine::l_emu_time(lua_State *L) -{ - lua_pushnumber(L, luaThis->machine().time().as_double()); - return 1; -} - -void lua_engine::emu_after_done(void *_h, INT32 param) -{ - hook *h = static_cast<hook *>(_h); - h->call(this, h->precall(), 0); - delete h; -} - -int lua_engine::emu_after(lua_State *L) -{ - luaL_argcheck(L, lua_isnumber(L, 1), 1, "waiting duration expected"); - struct hook *h = new hook; - h->set(L, 2); - machine().scheduler().timer_set(attotime::from_double(lua_tonumber(L, 1)), timer_expired_delegate(FUNC(lua_engine::emu_after_done), this), 0, h); - return 0; -} - -int lua_engine::l_emu_after(lua_State *L) -{ - return luaThis->emu_after(L); -} - -int lua_engine::emu_wait(lua_State *L) -{ - luaL_argcheck(L, lua_isnumber(L, 1), 1, "waiting duration expected"); - machine().scheduler().timer_set(attotime::from_double(lua_tonumber(L, 1)), timer_expired_delegate(FUNC(lua_engine::resume), this), 0, L); - return lua_yieldk(L, 0, 0, 0); -} - -int lua_engine::l_emu_wait(lua_State *L) -{ - return luaThis->emu_wait(L); -} - -void lua_engine::output_notifier(const char *outname, INT32 value) -{ - if (hook_output_cb.active()) { - lua_State *L = hook_output_cb.precall(); - lua_pushstring(L, outname); - lua_pushnumber(L, value); - hook_output_cb.call(this, L, 2); - } -} - -void lua_engine::s_output_notifier(const char *outname, INT32 value, void *param) -{ - static_cast<lua_engine *>(param)->output_notifier(outname, value); -} - -void lua_engine::emu_hook_output(lua_State *L) -{ - luaL_argcheck(L, lua_isfunction(L, 1), 1, "callback function expected"); - hook_output_cb.set(L, 1); - - if (!output_notifier_set) { - output_set_notifier(NULL, s_output_notifier, this); - output_notifier_set = true; - } -} - -int lua_engine::l_emu_hook_output(lua_State *L) -{ - luaThis->emu_hook_output(L); - return 0; -} - -int lua_engine::l_emu_set_hook(lua_State *L) -{ - luaThis->emu_set_hook(L); - return 0; -} - -void lua_engine::emu_set_hook(lua_State *L) -{ - luaL_argcheck(L, lua_isfunction(L, 1) || lua_isnil(L, 1), 1, "callback function expected"); - luaL_argcheck(L, lua_isstring(L, 2), 2, "message (string) expected"); - const char *hookname = luaL_checkstring(L,2); - - if (strcmp(hookname, "output") == 0) { - hook_output_cb.set(L, 1); - if (!output_notifier_set) { - output_set_notifier(NULL, s_output_notifier, this); - output_notifier_set = true; - } - } else if (strcmp(hookname, "frame") == 0) { - hook_frame_cb.set(L, 1); - } else { - lua_writestringerror("%s", "Unknown hook name, aborting.\n"); - } -} - -//------------------------------------------------- -// machine_get_screens - return table of available screens userdata -// -> manager:machine().screens[":screen"] -//------------------------------------------------- - -luabridge::LuaRef lua_engine::l_machine_get_screens(const running_machine *r) -{ - lua_State *L = luaThis->m_lua_state; - luabridge::LuaRef screens_table = luabridge::LuaRef::newTable(L); - - for (device_t *dev = r->first_screen(); dev != NULL; dev = dev->next()) { - screen_device *sc = dynamic_cast<screen_device *>(dev); - if (sc && sc->configured() && sc->started() && sc->type()) { - screens_table[sc->tag()] = sc; - } - } - - return screens_table; -} - -//------------------------------------------------- -// machine_get_devices - return table of available devices userdata -// -> manager:machine().devices[":maincpu"] -//------------------------------------------------- - -luabridge::LuaRef lua_engine::l_machine_get_devices(const running_machine *r) -{ - running_machine *m = const_cast<running_machine *>(r); - lua_State *L = luaThis->m_lua_state; - luabridge::LuaRef devs_table = luabridge::LuaRef::newTable(L); - - device_t *root = &(m->root_device()); - devs_table = devtree_dfs(root, devs_table); - - return devs_table; -} - -// private helper for get_devices - DFS visit all devices in a running machine -luabridge::LuaRef lua_engine::devtree_dfs(device_t *root, luabridge::LuaRef devs_table) -{ - if (root) { - for (device_t *dev = root->first_subdevice(); dev != NULL; dev = dev->next()) { - if (dev && dev->configured() && dev->started()) { - devs_table[dev->tag()] = dev; - devtree_dfs(dev, devs_table); - } - } - } - return devs_table; -} - -//------------------------------------------------- -// device_get_memspaces - return table of available address spaces userdata -// -> manager:machine().devices[":maincpu"].spaces["program"] -//------------------------------------------------- - -luabridge::LuaRef lua_engine::l_dev_get_memspaces(const device_t *d) -{ - device_t *dev = const_cast<device_t *>(d); - lua_State *L = luaThis->m_lua_state; - luabridge::LuaRef sp_table = luabridge::LuaRef::newTable(L); - - for (address_spacenum sp = AS_0; sp < ADDRESS_SPACES; sp++) { - if (dev->memory().has_space(sp)) { - sp_table[dev->memory().space(sp).name()] = &(dev->memory().space(sp)); - } - } - - return sp_table; -} - -//------------------------------------------------- -// device_get_state - return table of available state userdata -// -> manager:machine().devices[":maincpu"].state -//------------------------------------------------- - -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 != NULL; s = s->next()) { - // XXX: refrain from exporting non-visible entries? - if (s) { - st_table[s->symbol()] = const_cast<device_state_entry *>(s); - } - } - - return st_table; -} - -//------------------------------------------------- -// state_get_value - return value of a device state entry -// -> manager:machine().devices[":maincpu"].state["PC"].value -//------------------------------------------------- - -UINT64 lua_engine::l_state_get_value(const device_state_entry *d) -{ - device_state_interface *state = d->parent_state(); - if(state) { - luaThis->machine().save().dispatch_presave(); - return state->state_int(d->index()); - } else { - return 0; - } -} - -//------------------------------------------------- -// state_set_value - set value of a device state entry -// -> manager:machine().devices[":maincpu"].state["D0"].value = 0x0c00 -//------------------------------------------------- - -void lua_engine::l_state_set_value(device_state_entry *d, UINT64 val) -{ - device_state_interface *state = d->parent_state(); - if(state) { - state->set_state_int(d->index(), val); - luaThis->machine().save().dispatch_presave(); - } -} - -//------------------------------------------------- -// mem_read - templated memory readers for <sign>,<size> -// -> manager:machine().devices[":maincpu"].spaces["program"]:read_i8(0xC000) -//------------------------------------------------- - -template <typename T> -int lua_engine::lua_addr_space::l_mem_read(lua_State *L) -{ - address_space &sp = luabridge::Stack<address_space &>::get(L, 1); - luaL_argcheck(L, lua_isnumber(L, 2), 2, "address (integer) expected"); - offs_t address = lua_tounsigned(L, 2); - T mem_content = 0; - switch(sizeof(mem_content) * 8) { - case 8: - mem_content = sp.read_byte(address); - break; - case 16: - if ((address & 1) == 0) { - mem_content = sp.read_word(address); - } else { - mem_content = sp.read_word_unaligned(address); - } - break; - case 32: - if ((address & 3) == 0) { - mem_content = sp.read_dword(address); - } else { - mem_content = sp.read_dword_unaligned(address); - } - break; - case 64: - if ((address & 7) == 0) { - mem_content = sp.read_qword(address); - } else { - mem_content = sp.read_qword_unaligned(address); - } - break; - default: - break; - } - - if (std::numeric_limits<T>::is_signed) { - lua_pushinteger(L, mem_content); - } else { - lua_pushunsigned(L, mem_content); - } - - return 1; - -} - -//------------------------------------------------- -// mem_write - templated memory writer for <sign>,<size> -// -> manager:machine().devices[":maincpu"].spaces["program"]:write_u16(0xC000, 0xF00D) -//------------------------------------------------- - -template <typename T> -int lua_engine::lua_addr_space::l_mem_write(lua_State *L) -{ - address_space &sp = luabridge::Stack<address_space &>::get(L, 1); - luaL_argcheck(L, lua_isnumber(L, 2), 2, "address (integer) expected"); - luaL_argcheck(L, lua_isnumber(L, 3), 3, "value (integer) expected"); - offs_t address = lua_tounsigned(L, 2); - T val = lua_tounsigned(L, 3); - - switch(sizeof(val) * 8) { - case 8: - sp.write_byte(address, val); - break; - case 16: - if ((address & 1) == 0) { - sp.write_word(address, val); - } else { - sp.read_word_unaligned(address, val); - } - break; - case 32: - if ((address & 3) == 0) { - sp.write_dword(address, val); - } else { - sp.write_dword_unaligned(address, val); - } - break; - case 64: - if ((address & 7) == 0) { - sp.write_qword(address, val); - } else { - sp.write_qword_unaligned(address, val); - } - break; - default: - break; - } - - return 0; -} - -//------------------------------------------------- -// screen_height - return screen visible height -// -> manager:machine().screens[":screen"]:height() -//------------------------------------------------- - -int lua_engine::lua_screen::l_height(lua_State *L) -{ - screen_device *sc = luabridge::Stack<screen_device *>::get(L, 1); - if(!sc) { - return 0; - } - - lua_pushunsigned(L, sc->visible_area().height()); - return 1; -} - -//------------------------------------------------- -// screen_width - return screen visible width -// -> manager:machine().screens[":screen"]:width() -//------------------------------------------------- - -int lua_engine::lua_screen::l_width(lua_State *L) -{ - screen_device *sc = luabridge::Stack<screen_device *>::get(L, 1); - if(!sc) { - return 0; - } - - lua_pushunsigned(L, sc->visible_area().width()); - return 1; -} - -//------------------------------------------------- -// draw_box - draw a box on a screen container -// -> manager:machine().screens[":screen"]:draw_box(x1, y1, x2, y2, bgcolor, linecolor) -//------------------------------------------------- - -int lua_engine::lua_screen::l_draw_box(lua_State *L) -{ - screen_device *sc = luabridge::Stack<screen_device *>::get(L, 1); - if(!sc) { - return 0; - } - - // ensure that we got 6 numerical parameters - luaL_argcheck(L, lua_isnumber(L, 2), 2, "x1 (integer) expected"); - luaL_argcheck(L, lua_isnumber(L, 3), 3, "y1 (integer) expected"); - luaL_argcheck(L, lua_isnumber(L, 4), 4, "x2 (integer) expected"); - luaL_argcheck(L, lua_isnumber(L, 5), 5, "y2 (integer) expected"); - luaL_argcheck(L, lua_isnumber(L, 6), 6, "background color (integer) expected"); - luaL_argcheck(L, lua_isnumber(L, 7), 7, "outline color (integer) expected"); - - // retrieve all parameters - int sc_width = sc->visible_area().width(); - int sc_height = sc->visible_area().height(); - float x1, y1, x2, y2; - x1 = MIN(MAX(0, (float) lua_tonumber(L, 2)), sc_width-1) / static_cast<float>(sc_width); - y1 = MIN(MAX(0, (float) lua_tonumber(L, 3)), sc_height-1) / static_cast<float>(sc_height); - x2 = MIN(MAX(0, (float) lua_tonumber(L, 4)), sc_width-1) / static_cast<float>(sc_width); - y2 = MIN(MAX(0, (float) lua_tonumber(L, 5)), sc_height-1) / static_cast<float>(sc_height); - UINT32 bgcolor = lua_tounsigned(L, 6); - UINT32 fgcolor = lua_tounsigned(L, 7); - - // draw the box - render_container &rc = sc->container(); - ui_manager &ui = sc->machine().ui(); - ui.draw_outlined_box(&rc, x1, y1, x2, y2, fgcolor, bgcolor); - - return 0; -} - -//------------------------------------------------- -// draw_line - draw a line on a screen container -// -> manager:machine().screens[":screen"]:draw_line(x1, y1, x2, y2, linecolor) -//------------------------------------------------- - -int lua_engine::lua_screen::l_draw_line(lua_State *L) -{ - screen_device *sc = luabridge::Stack<screen_device *>::get(L, 1); - if(!sc) { - return 0; - } - - // ensure that we got 5 numerical parameters - luaL_argcheck(L, lua_isnumber(L, 2), 2, "x1 (integer) expected"); - luaL_argcheck(L, lua_isnumber(L, 3), 3, "y1 (integer) expected"); - luaL_argcheck(L, lua_isnumber(L, 4), 4, "x2 (integer) expected"); - luaL_argcheck(L, lua_isnumber(L, 5), 5, "y2 (integer) expected"); - luaL_argcheck(L, lua_isnumber(L, 6), 6, "color (integer) expected"); - - // retrieve all parameters - int sc_width = sc->visible_area().width(); - int sc_height = sc->visible_area().height(); - float x1, y1, x2, y2; - x1 = MIN(MAX(0, (float) lua_tonumber(L, 2)), sc_width-1) / static_cast<float>(sc_width); - y1 = MIN(MAX(0, (float) lua_tonumber(L, 3)), sc_height-1) / static_cast<float>(sc_height); - x2 = MIN(MAX(0, (float) lua_tonumber(L, 4)), sc_width-1) / static_cast<float>(sc_width); - y2 = MIN(MAX(0, (float) lua_tonumber(L, 5)), sc_height-1) / static_cast<float>(sc_height); - UINT32 color = lua_tounsigned(L, 6); - - // draw the line - sc->container().add_line(x1, y1, x2, y2, UI_LINE_WIDTH, rgb_t(color), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA)); - return 0; -} - -//------------------------------------------------- -// draw_text - draw text on a screen container -// -> manager:machine().screens[":screen"]:draw_text(x, y, message) -//------------------------------------------------- - -int lua_engine::lua_screen::l_draw_text(lua_State *L) -{ - screen_device *sc = luabridge::Stack<screen_device *>::get(L, 1); - if(!sc) { - return 0; - } - - // ensure that we got proper parameters - luaL_argcheck(L, lua_isnumber(L, 2), 2, "x (integer) expected"); - luaL_argcheck(L, lua_isnumber(L, 3), 3, "y (integer) expected"); - luaL_argcheck(L, lua_isstring(L, 4), 4, "message (string) expected"); - luaL_argcheck(L, lua_isinteger(L, 5) || lua_isnone(L, 5), 5, "optional argument: text color, integer expected (default: 0xffffffff)"); - - // retrieve all parameters - int sc_width = sc->visible_area().width(); - int sc_height = sc->visible_area().height(); - float x = MIN(MAX(0, (float) lua_tonumber(L, 2)), sc_width-1) / static_cast<float>(sc_width); - float y = MIN(MAX(0, (float) lua_tonumber(L, 3)), sc_height-1) / static_cast<float>(sc_height); - const char *msg = luaL_checkstring(L,4); - rgb_t textcolor = UI_TEXT_COLOR; - if (!lua_isnone(L, 5)) { - textcolor = rgb_t(lua_tounsigned(L, 5)); - } - - // draw the text - render_container &rc = sc->container(); - ui_manager &ui = sc->machine().ui(); - ui.draw_text_full(&rc, msg, x, y , (1.0f - x), - JUSTIFY_LEFT, WRAP_WORD, DRAW_NORMAL, textcolor, - UI_TEXT_BG_COLOR, NULL, NULL); - - return 0; -} - -void *lua_engine::checkparam(lua_State *L, int idx, const char *tname) -{ - const char *name; - - if(!lua_getmetatable(L, idx)) - return 0; - - lua_rawget(L, LUA_REGISTRYINDEX); - name = lua_tostring(L, -1); - if(!name || strcmp(name, tname)) { - lua_pop(L, 1); - return 0; - } - lua_pop(L, 1); - - return *static_cast<void **>(lua_touserdata(L, idx)); -} - -void *lua_engine::getparam(lua_State *L, int idx, const char *tname) -{ - void *p = checkparam(L, idx, tname); - char msg[256]; - sprintf(msg, "%s expected", tname); - luaL_argcheck(L, p, idx, msg); - return p; -} - -void lua_engine::push(lua_State *L, void *p, const char *tname) -{ - void **pp = static_cast<void **>(lua_newuserdata(L, sizeof(void *))); - *pp = p; - luaL_getmetatable(L, tname); - lua_setmetatable(L, -2); -} - -int lua_engine::l_emu_exit(lua_State *L) -{ - luaThis->machine().schedule_exit(); - return 1; -} - -int lua_engine::l_emu_start(lua_State *L) -{ - const char *system_name = luaL_checkstring(L,1); - - int index = driver_list::find(system_name); - if (index != -1) { - machine_manager::instance()->schedule_new_driver(driver_list::driver(index)); - luaThis->machine().schedule_hard_reset(); - } - return 1; -} - -int lua_engine::luaopen_ioport(lua_State *L) -{ - static const struct luaL_Reg ioport_funcs [] = { - { "write", l_ioport_write }, - { NULL, NULL } /* sentinel */ - }; - - luaL_newmetatable(L, tname_ioport); - lua_pushvalue(L, -1); - lua_pushstring(L, tname_ioport); - lua_rawset(L, LUA_REGISTRYINDEX); - lua_pushstring(L, "__index"); - lua_pushvalue(L, -2); - lua_settable(L, -3); - luaL_setfuncs(L, ioport_funcs, 0); - return 1; -} - -struct msg { - std::string text; - int ready; - std::string response; - int status; - int done; -} msg; - -osd_lock *lock; - -void lua_engine::serve_lua() -{ - osd_sleep(osd_ticks_per_second() / 1000 * 50); - printf("%s v%s - %s\n%s\n%s\n\n", emulator_info::get_applongname(),build_version,emulator_info::get_fulllongname(),emulator_info::get_copyright_info(),LUA_COPYRIGHT); - fflush(stdout); - char buff[LUA_MAXINPUT]; - std::string oldbuff; - - const char *b = LUA_PROMPT; - - do { - // Wait for input - fputs(b, stdout); fflush(stdout); /* show prompt */ - fgets(buff, LUA_MAXINPUT, stdin); - - // Create message - osd_lock_acquire(lock); - if (msg.ready == 0) { - msg.text = oldbuff; - if (oldbuff.length()!=0) msg.text.append("\n"); - msg.text.append(buff); - msg.ready = 1; - msg.done = 0; - } - osd_lock_release(lock); - - // Wait for response - int done = 0; - do { - osd_sleep(osd_ticks_per_second() / 1000); - osd_lock_acquire(lock); - done = msg.done; - osd_lock_release(lock); - } while (done==0); - - // Do action on client side - osd_lock_acquire(lock); - if (msg.status == -1){ - b = LUA_PROMPT2; - oldbuff = msg.response; - } - else { - b = LUA_PROMPT; - oldbuff = ""; - } - msg.done = 0; - osd_lock_release(lock); - - } while (1); -} - -/* -static void *serve_lua(void *param) -{ - lua_engine *engine = (lua_engine *)param; - engine->serve_lua(); - return NULL; -} -*/ - -//------------------------------------------------- -// lua_engine - constructor -//------------------------------------------------- - -lua_engine::lua_engine() -{ - m_machine = NULL; - luaThis = this; - m_lua_state = luaL_newstate(); /* create state */ - output_notifier_set = false; - - luaL_checkversion(m_lua_state); - lua_gc(m_lua_state, LUA_GCSTOP, 0); /* stop collector during initialization */ - luaL_openlibs(m_lua_state); /* open libraries */ - - luaopen_lsqlite3(m_lua_state); - - luaopen_ioport(m_lua_state); - - lua_gc(m_lua_state, LUA_GCRESTART, 0); - msg.ready = 0; - msg.status = 0; - msg.done = 0; - lock = osd_lock_alloc(); -} - -//------------------------------------------------- -// ~lua_engine - destructor -//------------------------------------------------- - -lua_engine::~lua_engine() -{ - close(); -} - - -void lua_engine::update_machine() -{ - lua_newtable(m_lua_state); - if (m_machine!=NULL) - { - // 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()); - } - field = field->next(); - } - port = port->next(); - } - } - lua_setglobal(m_lua_state, "ioport"); -} - -//------------------------------------------------- -// initialize - initialize lua hookup to emu engine -//------------------------------------------------- - -void lua_engine::initialize() -{ - luabridge::getGlobalNamespace (m_lua_state) - .beginNamespace ("emu") - .addCFunction ("app_name", l_emu_app_name ) - .addCFunction ("app_version", l_emu_app_version ) - .addCFunction ("gamename", l_emu_gamename ) - .addCFunction ("romname", l_emu_romname ) - .addCFunction ("keypost", l_emu_keypost ) - .addCFunction ("hook_output", l_emu_hook_output ) - .addCFunction ("sethook", l_emu_set_hook ) - .addCFunction ("time", l_emu_time ) - .addCFunction ("wait", l_emu_wait ) - .addCFunction ("after", l_emu_after ) - .addCFunction ("exit", l_emu_exit ) - .addCFunction ("start", l_emu_start ) - .addCFunction ("pause", l_emu_pause ) - .addCFunction ("unpause", l_emu_unpause ) - .beginClass <machine_manager> ("manager") - .addFunction ("machine", &machine_manager::machine) - .addFunction ("options", &machine_manager::options) - .endClass () - .beginClass <running_machine> ("machine") - .addFunction ("exit", &running_machine::schedule_exit) - .addFunction ("hard_reset", &running_machine::schedule_hard_reset) - .addFunction ("soft_reset", &running_machine::schedule_soft_reset) - .addFunction ("save", &running_machine::schedule_save) - .addFunction ("load", &running_machine::schedule_load) - .addFunction ("system", &running_machine::system) - .addProperty <luabridge::LuaRef, void> ("devices", &lua_engine::l_machine_get_devices) - .addProperty <luabridge::LuaRef, void> ("screens", &lua_engine::l_machine_get_screens) - .endClass () - .beginClass <game_driver> ("game_driver") - .addData ("name", &game_driver::name) - .addData ("description", &game_driver::description) - .addData ("year", &game_driver::year) - .addData ("manufacturer", &game_driver::manufacturer) - .endClass () - .beginClass <device_t> ("device") - .addFunction ("name", &device_t::name) - .addFunction ("shortname", &device_t::shortname) - .addFunction ("tag", &device_t::tag) - .addProperty <luabridge::LuaRef, void> ("spaces", &lua_engine::l_dev_get_memspaces) - .addProperty <luabridge::LuaRef, void> ("state", &lua_engine::l_dev_get_states) - .endClass() - .beginClass <lua_addr_space> ("lua_addr_space") - .addCFunction ("read_i8", &lua_addr_space::l_mem_read<INT8>) - .addCFunction ("read_u8", &lua_addr_space::l_mem_read<UINT8>) - .addCFunction ("read_i16", &lua_addr_space::l_mem_read<INT16>) - .addCFunction ("read_u16", &lua_addr_space::l_mem_read<UINT16>) - .addCFunction ("read_i32", &lua_addr_space::l_mem_read<INT32>) - .addCFunction ("read_u32", &lua_addr_space::l_mem_read<UINT32>) - .addCFunction ("read_i64", &lua_addr_space::l_mem_read<INT64>) - .addCFunction ("read_u64", &lua_addr_space::l_mem_read<UINT64>) - .addCFunction ("write_i8", &lua_addr_space::l_mem_write<INT8>) - .addCFunction ("write_u8", &lua_addr_space::l_mem_write<UINT8>) - .addCFunction ("write_i16", &lua_addr_space::l_mem_write<INT16>) - .addCFunction ("write_u16", &lua_addr_space::l_mem_write<UINT16>) - .addCFunction ("write_i32", &lua_addr_space::l_mem_write<INT32>) - .addCFunction ("write_u32", &lua_addr_space::l_mem_write<UINT32>) - .addCFunction ("write_i64", &lua_addr_space::l_mem_write<INT64>) - .addCFunction ("write_u64", &lua_addr_space::l_mem_write<UINT64>) - .endClass() - .deriveClass <address_space, lua_addr_space> ("addr_space") - .addFunction("name", &address_space::name) - .endClass() - .beginClass <lua_screen> ("lua_screen_dev") - .addCFunction ("draw_box", &lua_screen::l_draw_box) - .addCFunction ("draw_line", &lua_screen::l_draw_line) - .addCFunction ("draw_text", &lua_screen::l_draw_text) - .addCFunction ("height", &lua_screen::l_height) - .addCFunction ("width", &lua_screen::l_width) - .endClass() - .deriveClass <screen_device, lua_screen> ("screen_dev") - .addFunction ("frame_number", &screen_device::frame_number) - .addFunction ("name", &screen_device::name) - .addFunction ("shortname", &screen_device::shortname) - .addFunction ("tag", &screen_device::tag) - .endClass() - .beginClass <device_state_entry> ("dev_space") - .addFunction ("name", &device_state_entry::symbol) - .addProperty <UINT64, UINT64> ("value", &lua_engine::l_state_get_value, &lua_engine::l_state_set_value) - .addFunction ("is_visible", &device_state_entry::visible) - .addFunction ("is_divider", &device_state_entry::divider) - .endClass() - .endNamespace(); - - luabridge::push (m_lua_state, machine_manager::instance()); - lua_setglobal(m_lua_state, "manager"); -} - -void lua_engine::start_console() -{ -} - -//------------------------------------------------- -// frame_hook - called at each frame refresh, used to draw a HUD -//------------------------------------------------- -bool lua_engine::frame_hook() -{ - bool is_cb_hooked = false; - if (m_machine != NULL) { - // invoke registered callback (if any) - is_cb_hooked = hook_frame_cb.active(); - if (is_cb_hooked) { - lua_State *L = hook_frame_cb.precall(); - hook_frame_cb.call(this, L, 0); - } - } - return is_cb_hooked; -} - -void lua_engine::periodic_check() -{ - osd_lock_acquire(lock); - if (msg.ready == 1) { - lua_settop(m_lua_state, 0); - int status = luaL_loadbuffer(m_lua_state, msg.text.c_str(), strlen(msg.text.c_str()), "=stdin"); - if (incomplete(status)==0) /* cannot try to add lines? */ - { - if (status == LUA_OK) status = docall(0, LUA_MULTRET); - report(status); - if (status == LUA_OK && lua_gettop(m_lua_state) > 0) /* any result to print? */ - { - luaL_checkstack(m_lua_state, LUA_MINSTACK, "too many results to print"); - lua_getglobal(m_lua_state, "print"); - lua_insert(m_lua_state, 1); - if (lua_pcall(m_lua_state, lua_gettop(m_lua_state) - 1, 0, 0) != LUA_OK) - lua_writestringerror("%s\n", lua_pushfstring(m_lua_state, - "error calling " LUA_QL("print") " (%s)", - lua_tostring(m_lua_state, -1))); - } - } - else - { - status = -1; - } - msg.status = status; - msg.response = msg.text; - msg.text = ""; - msg.ready = 0; - msg.done = 1; - } - osd_lock_release(lock); -} - -//------------------------------------------------- -// close - close and cleanup of lua engine -//------------------------------------------------- - -void lua_engine::close() -{ - lua_settop(m_lua_state, 0); /* clear stack */ - lua_close(m_lua_state); -} - -//------------------------------------------------- -// execute - load and execute script -//------------------------------------------------- - -void lua_engine::load_script(const char *filename) -{ - int s = luaL_loadfile(m_lua_state, filename); - report(s); - update_machine(); - start(); -} - -//------------------------------------------------- -// execute_string - execute script from string -//------------------------------------------------- - -void lua_engine::load_string(const char *value) -{ - int s = luaL_loadstring(m_lua_state, value); - report(s); - update_machine(); - start(); -} - -//------------------------------------------------- -// start - execute the loaded script -//------------------------------------------------- - -void lua_engine::start() -{ - resume(m_lua_state); -} - - -//************************************************************************** -// LuaBridge Stack specializations -//************************************************************************** - -namespace luabridge { - template <> - struct Stack <UINT64> { - static inline void push (lua_State* L, UINT64 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)); - } - }; -} |
