diff options
author | 2014-12-24 11:53:36 +0100 | |
---|---|---|
committer | 2014-12-24 11:53:36 +0100 | |
commit | f19ef3e2078365924bb4f2942539af34929792a1 (patch) | |
tree | abe0abe2ac7aca59620c7d215a61b015e6e81a8e | |
parent | 00180d3f6747488899e99b341a6f162c99bc2854 (diff) | |
parent | 0a46c8b8d786b8ef59beeb2cff4f38115c9b96db (diff) |
Merge pull request #89 from lucab/lucab/mame-lua/mem-v2
luaengine: add memory-reading capabilities [Luca Bruno]
-rw-r--r-- | src/emu/luaengine.c | 120 | ||||
-rw-r--r-- | src/emu/luaengine.h | 17 |
2 files changed, 137 insertions, 0 deletions
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 <limits> #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<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; +} + +//------------------------------------------------- +// 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; + +} 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 <luabridge::LuaRef, void> ("devices", &lua_engine::l_machine_get_devices) .endClass () .beginClass <game_driver> ("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_t> ("device") + .addFunction("name", &device_t::tag) + .addProperty <luabridge::LuaRef, void> ("spaces", &lua_engine::l_dev_get_memspaces) + .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>) + .endClass() + .deriveClass <address_space, lua_addr_space> ("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 <map> +// 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<typename T> int l_mem_read(lua_State *L); + }; + void resume(void *L, INT32 param); void report_errors(int status); void start(); |