From 0a46c8b8d786b8ef59beeb2cff4f38115c9b96db Mon Sep 17 00:00:00 2001 From: Luca Bruno Date: Tue, 23 Dec 2014 23:46:17 +0100 Subject: [PATCH] luaengine: add access to devices and address spaces This commit maps some more classes (device_t and address_space) to retrieve devices and address spaces out of current running machine. Proxy methods are provided to enumerate/access devices and address spaces, and to read memory content. Signed-off-by: Luca Bruno --- src/emu/luaengine.c | 120 ++++++++++++++++++++++++++++++++++++++++++++ src/emu/luaengine.h | 17 +++++++ 2 files changed, 137 insertions(+) diff --git a/src/emu/luaengine.c b/src/emu/luaengine.c index 128b6716194..843c873233e 100644 --- a/src/emu/luaengine.c +++ b/src/emu/luaengine.c @@ -8,6 +8,7 @@ ***************************************************************************/ +#include #include "lua/lua.hpp" #include "lua/lib/lualibs.h" #include "lua/bridge/LuaBridge.h" @@ -335,6 +336,107 @@ int lua_engine::l_emu_hook_output(lua_State *L) return 0; } +//------------------------------------------------- +// 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(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(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; +} + +//------------------------------------------------- +// mem_read - templated memory readers for , +// -> manager:machine().devices[":maincpu"].spaces["program"]:read_i8(0xC000) +//------------------------------------------------- + +template +int lua_engine::lua_addr_space::l_mem_read(lua_State *L) +{ + address_space &sp = luabridge::Stack::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::is_signed) { + lua_pushinteger(L, mem_content); + } else { + lua_pushunsigned(L, mem_content); + } + + return 1; + +} void *lua_engine::checkparam(lua_State *L, int idx, const char *tname) { @@ -564,6 +666,7 @@ void lua_engine::initialize() .addFunction ("hard_reset", &running_machine::schedule_hard_reset) .addFunction ("soft_reset", &running_machine::schedule_soft_reset) .addFunction ("system", &running_machine::system) + .addProperty ("devices", &lua_engine::l_machine_get_devices) .endClass () .beginClass ("game_driver") .addData ("name", &game_driver::name) @@ -571,6 +674,23 @@ void lua_engine::initialize() .addData ("year", &game_driver::year) .addData ("manufacturer", &game_driver::manufacturer) .endClass () + .beginClass ("device") + .addFunction("name", &device_t::tag) + .addProperty ("spaces", &lua_engine::l_dev_get_memspaces) + .endClass() + .beginClass ("lua_addr_space") + .addCFunction ("read_i8", &lua_addr_space::l_mem_read) + .addCFunction ("read_u8", &lua_addr_space::l_mem_read) + .addCFunction ("read_i16", &lua_addr_space::l_mem_read) + .addCFunction ("read_u16", &lua_addr_space::l_mem_read) + .addCFunction ("read_i32", &lua_addr_space::l_mem_read) + .addCFunction ("read_u32", &lua_addr_space::l_mem_read) + .addCFunction ("read_i64", &lua_addr_space::l_mem_read) + .addCFunction ("read_u64", &lua_addr_space::l_mem_read) + .endClass() + .deriveClass ("addr_space") + .addFunction("name", &address_space::name) + .endClass() .endNamespace (); luabridge::push (m_lua_state, machine_manager::instance()); diff --git a/src/emu/luaengine.h b/src/emu/luaengine.h index 62399dbd281..ae1221415ff 100644 --- a/src/emu/luaengine.h +++ b/src/emu/luaengine.h @@ -19,6 +19,15 @@ #include +// None is typedef'd already in SDL/X11 libs +#ifdef None +#undef None +#endif + +#include "lua/lua.hpp" +#include "lua/lib/lualibs.h" +#include "lua/bridge/LuaBridge.h" + struct lua_State; class lua_engine @@ -89,6 +98,14 @@ private: static int l_emu_pause(lua_State *L); static int l_emu_unpause(lua_State *L); + // "emu.machine" namespace + static luabridge::LuaRef l_machine_get_devices(const running_machine *r); + static luabridge::LuaRef l_dev_get_memspaces(const device_t *d); + static luabridge::LuaRef devtree_dfs(device_t *root, luabridge::LuaRef dev_table); + struct lua_addr_space { + template int l_mem_read(lua_State *L); + }; + void resume(void *L, INT32 param); void report_errors(int status); void start();