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 <lucab@debian.org>
This commit is contained in:
Luca Bruno 2014-12-23 23:46:17 +01:00
parent 4a22c103dd
commit 0a46c8b8d7
2 changed files with 137 additions and 0 deletions

View File

@ -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());

View File

@ -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();