summaryrefslogtreecommitdiffstatshomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/emu/debug/points.cpp84
-rw-r--r--src/frontend/mame/luaengine.h2
-rw-r--r--src/frontend/mame/luaengine_mem.cpp342
3 files changed, 337 insertions, 91 deletions
diff --git a/src/emu/debug/points.cpp b/src/emu/debug/points.cpp
index c44bc3f7563..d4c1ebb3045 100644
--- a/src/emu/debug/points.cpp
+++ b/src/emu/debug/points.cpp
@@ -22,18 +22,19 @@
// debug_breakpoint - constructor
//-------------------------------------------------
-debug_breakpoint::debug_breakpoint(device_debug* debugInterface,
- symbol_table &symbols,
- int index,
- offs_t address,
- const char *condition,
- const char *action)
- : m_debugInterface(debugInterface),
- m_index(index),
- m_enabled(true),
- m_address(address),
- m_condition(symbols, (condition != nullptr) ? condition : "1"),
- m_action((action != nullptr) ? action : "")
+debug_breakpoint::debug_breakpoint(
+ device_debug *debugInterface,
+ symbol_table &symbols,
+ int index,
+ offs_t address,
+ const char *condition,
+ const char *action) :
+ m_debugInterface(debugInterface),
+ m_index(index),
+ m_enabled(true),
+ m_address(address),
+ m_condition(symbols, condition ? condition : "1"),
+ m_action(action ? action : "")
{
}
@@ -59,7 +60,7 @@ bool debug_breakpoint::hit(offs_t pc)
{
return (m_condition.execute() != 0);
}
- catch (expression_error &)
+ catch (expression_error const &)
{
return false;
}
@@ -78,27 +79,28 @@ bool debug_breakpoint::hit(offs_t pc)
// debug_watchpoint - constructor
//-------------------------------------------------
-debug_watchpoint::debug_watchpoint(device_debug* debugInterface,
- symbol_table &symbols,
- int index,
- address_space &space,
- read_or_write type,
- offs_t address,
- offs_t length,
- const char *condition,
- const char *action)
- : m_debugInterface(debugInterface),
- m_phr(nullptr),
- m_phw(nullptr),
- m_space(space),
- m_index(index),
- m_enabled(true),
- m_type(type),
- m_address(address & space.addrmask()),
- m_length(length),
- m_condition(symbols, (condition != nullptr) ? condition : "1"),
- m_action((action != nullptr) ? action : ""),
- m_installing(false)
+debug_watchpoint::debug_watchpoint(
+ device_debug* debugInterface,
+ symbol_table &symbols,
+ int index,
+ address_space &space,
+ read_or_write type,
+ offs_t address,
+ offs_t length,
+ const char *condition,
+ const char *action) :
+ m_debugInterface(debugInterface),
+ m_phr(nullptr),
+ m_phw(nullptr),
+ m_space(space),
+ m_index(index),
+ m_enabled(true),
+ m_type(type),
+ m_address(address & space.addrmask()),
+ m_length(length),
+ m_condition(symbols, condition ? condition : "1"),
+ m_action(action ? action : ""),
+ m_installing(false)
{
std::fill(std::begin(m_start_address), std::end(m_start_address), 0);
std::fill(std::begin(m_end_address), std::end(m_end_address), 0);
@@ -170,12 +172,14 @@ debug_watchpoint::debug_watchpoint(device_debug* debugInterface,
}
install(read_or_write::READWRITE);
- m_notifier = m_space.add_change_notifier([this](read_or_write mode) {
- if (m_enabled)
- {
- install(mode);
- }
- });
+ m_notifier = m_space.add_change_notifier(
+ [this] (read_or_write mode)
+ {
+ if (m_enabled)
+ {
+ install(mode);
+ }
+ });
}
debug_watchpoint::~debug_watchpoint()
diff --git a/src/frontend/mame/luaengine.h b/src/frontend/mame/luaengine.h
index bb16aea6a43..1aaa83bbf0b 100644
--- a/src/frontend/mame/luaengine.h
+++ b/src/frontend/mame/luaengine.h
@@ -121,6 +121,8 @@ private:
template<typename T, size_t SIZE> class enum_parser;
struct addr_space;
+ class tap_helper;
+ class addr_space_change_notif;
struct save_item {
void *base;
diff --git a/src/frontend/mame/luaengine_mem.cpp b/src/frontend/mame/luaengine_mem.cpp
index f95ebdb37c2..26518931e9e 100644
--- a/src/frontend/mame/luaengine_mem.cpp
+++ b/src/frontend/mame/luaengine_mem.cpp
@@ -184,6 +184,220 @@ int sol_lua_push(sol::types<endianness_t>, lua_State *L, endianness_t &&value)
//-------------------------------------------------
+// tap_helper - class for managing address space
+// taps
+//-------------------------------------------------
+
+class lua_engine::tap_helper
+{
+public:
+ tap_helper(tap_helper const &) = delete;
+ tap_helper(tap_helper &&) = delete;
+
+ tap_helper(
+ lua_engine &engine,
+ address_space &space,
+ read_or_write mode,
+ offs_t start,
+ offs_t end,
+ std::string &&name,
+ sol::protected_function &&callback)
+ : m_callback(std::move(callback))
+ , m_engine(engine)
+ , m_space(space)
+ , m_handler(nullptr)
+ , m_name(std::move(name))
+ , m_start(start)
+ , m_end(end)
+ , m_mode(mode)
+ , m_installing(false)
+ , m_installed(false)
+ {
+ reinstall();
+ }
+
+ ~tap_helper()
+ {
+ if (m_handler && m_installed)
+ m_handler->remove();
+ }
+
+ offs_t start() const noexcept { return m_start; }
+ offs_t end() const noexcept { return m_end; }
+ std::string const &name() const noexcept { return m_name; }
+
+ void reinstall()
+ {
+ switch (m_space.data_width())
+ {
+ case 8: do_install<u8>(); break;
+ case 16: do_install<u16>(); break;
+ case 32: do_install<u32>(); break;
+ case 64: do_install<u64>(); break;
+ }
+ }
+
+ void remove()
+ {
+ if (m_handler)
+ {
+ m_handler->remove();
+ m_installed = false;
+ }
+ }
+
+private:
+ template <typename T>
+ void do_install()
+ {
+ if (m_installing)
+ return;
+ m_installing = true;
+ if (m_handler)
+ m_handler->remove();
+
+ switch (m_mode)
+ {
+ case read_or_write::READ:
+ m_handler = m_space.install_read_tap(
+ m_start,
+ m_end,
+ m_name,
+ [this] (offs_t offset, T &data, T mem_mask)
+ {
+ auto result = m_engine.invoke(m_callback, offset, data, mem_mask).template get<sol::optional<T> >();
+ if (result)
+ data = *result;
+ },
+ m_handler);
+ break;
+ case read_or_write::WRITE:
+ m_handler = m_space.install_write_tap(
+ m_start,
+ m_end,
+ m_name,
+ [this] (offs_t offset, T &data, T mem_mask)
+ {
+ auto result = m_engine.invoke(m_callback, offset, data, mem_mask).template get<sol::optional<T> >();
+ if (result)
+ data = *result;
+ },
+ m_handler);
+ break;
+ case read_or_write::READWRITE:
+ // won't ever get here, but compilers complain about unhandled enum value
+ break;
+ }
+
+ m_installed = true;
+ m_installing = false;
+ };
+
+ sol::protected_function m_callback;
+ lua_engine &m_engine;
+ address_space &m_space;
+ memory_passthrough_handler *m_handler;
+ std::string m_name;
+ offs_t const m_start;
+ offs_t const m_end;
+ read_or_write const m_mode;
+ bool m_installing;
+ bool m_installed;
+};
+
+
+//-------------------------------------------------
+// addr_space_change_notif - helper for hanging
+// on to an address space change notification
+// subscription
+//-------------------------------------------------
+
+class lua_engine::addr_space_change_notif
+{
+public:
+ addr_space_change_notif(addr_space_change_notif const &) = delete;
+
+ addr_space_change_notif(addr_space_change_notif &&that)
+ : m_callback(std::move(that.m_callback))
+ , m_engine(that.m_engine)
+ , m_space(that.m_space)
+ , m_id(-1)
+ {
+ that.remove();
+ install();
+ }
+
+ addr_space_change_notif &operator=(addr_space_change_notif &&that)
+ {
+ if (&that != this)
+ {
+ remove();
+ m_callback = std::move(that.m_callback);
+ m_engine = that.m_engine;
+ m_space = that.m_space;
+ that.remove();
+ install();
+ }
+ return *this;
+ }
+
+ addr_space_change_notif(lua_engine &engine, address_space &space, sol::protected_function &&callback)
+ : m_callback(std::move(callback))
+ , m_engine(&engine)
+ , m_space(&space)
+ , m_id(-1)
+ {
+ install();
+ }
+
+ ~addr_space_change_notif()
+ {
+ if (m_space)
+ m_space->remove_change_notifier(m_id);
+ }
+
+ void remove()
+ {
+ if (m_space)
+ {
+ m_space->remove_change_notifier(m_id);
+ m_space = nullptr;
+ m_id = -1;
+ }
+ }
+
+private:
+ void install()
+ {
+ if (m_space)
+ {
+ m_id = m_space->add_change_notifier(
+ [this] (read_or_write mode)
+ {
+ char const *modestr = "";
+ switch (mode)
+ {
+ case read_or_write::READ: modestr = "r"; break;
+ case read_or_write::WRITE: modestr = "w"; break;
+ case read_or_write::READWRITE: modestr = "rw"; break;
+ }
+ m_engine->invoke(m_callback, modestr);
+ });
+ }
+ else
+ {
+ m_id = -1;
+ }
+ }
+
+ sol::protected_function m_callback;
+ lua_engine *m_engine;
+ address_space *m_space;
+ int m_id;
+};
+
+
+//-------------------------------------------------
// mem_read - templated memory readers for <sign>,<size>
// -> manager:machine().devices[":maincpu"].spaces["program"]:read_i8(0xC000)
//-------------------------------------------------
@@ -449,64 +663,79 @@ void lua_engine::initialize_memory(sol::table &emu)
addr_space_type["write_direct_i64"] = &addr_space::direct_mem_write<s64>;
addr_space_type["write_direct_u64"] = &addr_space::direct_mem_write<u64>;
addr_space_type["read_range"] =
- [] (addr_space &sp, sol::this_state s, u64 first, u64 last, int width, sol::object opt_step) -> sol::object
- {
- lua_State *L = s;
- luaL_Buffer buff;
- offs_t space_size = sp.space.addrmask();
- u64 step = 1;
- if (opt_step.is<u64>())
- {
- step = opt_step.as<u64>();
- if (step < 1 || step > last - first)
- {
- luaL_error(L, "Invalid step");
- return sol::lua_nil;
- }
- }
- if (first > space_size || last > space_size || last < first)
+ [] (addr_space &sp, sol::this_state s, u64 first, u64 last, int width, sol::object opt_step) -> sol::object
{
- luaL_error(L, "Invalid offset");
- return sol::lua_nil;
- }
- int byte_count = width / 8 * (last - first + 1) / step;
- switch (width)
- {
- case 8:
+ lua_State *L = s;
+ luaL_Buffer buff;
+ offs_t space_size = sp.space.addrmask();
+ u64 step = 1;
+ if (opt_step.is<u64>())
{
- u8 *dest = (u8 *)luaL_buffinitsize(L, &buff, byte_count);
- for ( ; first <= last; first += step)
- *dest++ = sp.mem_read<u8>(first);
- break;
+ step = opt_step.as<u64>();
+ if (step < 1 || step > last - first)
+ {
+ luaL_error(L, "Invalid step");
+ return sol::lua_nil;
+ }
}
- case 16:
+ if (first > space_size || last > space_size || last < first)
{
- u16 *dest = (u16 *)luaL_buffinitsize(L, &buff, byte_count);
- for ( ; first <= last; first += step)
- *dest++ = sp.mem_read<u16>(first);
- break;
- }
- case 32:
- {
- u32 *dest = (u32 *)luaL_buffinitsize(L, &buff, byte_count);
- for(; first <= last; first += step)
- *dest++ = sp.mem_read<u32>(first);
- break;
+ luaL_error(L, "Invalid offset");
+ return sol::lua_nil;
}
- case 64:
+ int byte_count = width / 8 * (last - first + 1) / step;
+ switch (width)
{
- u64 *dest = (u64 *)luaL_buffinitsize(L, &buff, byte_count);
- for(; first <= last; first += step)
- *dest++ = sp.mem_read<u64>(first);
- break;
+ case 8:
+ {
+ u8 *dest = (u8 *)luaL_buffinitsize(L, &buff, byte_count);
+ for ( ; first <= last; first += step)
+ *dest++ = sp.mem_read<u8>(first);
+ break;
+ }
+ case 16:
+ {
+ u16 *dest = (u16 *)luaL_buffinitsize(L, &buff, byte_count);
+ for ( ; first <= last; first += step)
+ *dest++ = sp.mem_read<u16>(first);
+ break;
+ }
+ case 32:
+ {
+ u32 *dest = (u32 *)luaL_buffinitsize(L, &buff, byte_count);
+ for( ; first <= last; first += step)
+ *dest++ = sp.mem_read<u32>(first);
+ break;
+ }
+ case 64:
+ {
+ u64 *dest = (u64 *)luaL_buffinitsize(L, &buff, byte_count);
+ for( ; first <= last; first += step)
+ *dest++ = sp.mem_read<u64>(first);
+ break;
+ }
+ default:
+ luaL_error(L, "Invalid width. Must be 8/16/32/64");
+ return sol::lua_nil;
}
- default:
- luaL_error(L, "Invalid width. Must be 8/16/32/64");
- return sol::lua_nil;
- }
- luaL_pushresultsize(&buff, byte_count);
- return sol::make_reference(L, sol::stack_reference(L, -1));
- };
+ luaL_pushresultsize(&buff, byte_count);
+ return sol::make_reference(L, sol::stack_reference(L, -1));
+ };
+ addr_space_type["add_change_notifier"] =
+ [this] (addr_space &sp, sol::protected_function &&cb)
+ {
+ return addr_space_change_notif(*this, sp.space, std::move(cb));
+ };
+ addr_space_type["install_read_tap"] =
+ [this] (addr_space &sp, offs_t start, offs_t end, std::string &&name, sol::protected_function &&cb)
+ {
+ return std::make_unique<tap_helper>(*this, sp.space, read_or_write::READ, start, end, std::move(name), std::move(cb));
+ };
+ addr_space_type["install_write_tap"] =
+ [this] (addr_space &sp, offs_t start, offs_t end, std::string &&name, sol::protected_function &&cb)
+ {
+ return std::make_unique<tap_helper>(*this, sp.space, read_or_write::WRITE, start, end, std::move(name), std::move(cb));
+ };
addr_space_type["name"] = sol::property([] (addr_space &sp) { return sp.space.name(); });
addr_space_type["shift"] = sol::property([] (addr_space &sp) { return sp.space.addr_shift(); });
addr_space_type["index"] = sol::property([] (addr_space &sp) { return sp.space.spacenum(); });
@@ -516,6 +745,17 @@ void lua_engine::initialize_memory(sol::table &emu)
addr_space_type["map"] = sol::property([] (addr_space &sp) { return sp.space.map(); });
+ auto change_notif_type = sol().registry().new_usertype<addr_space_change_notif>("addr_space_change", sol::no_constructor);
+ change_notif_type["remove"] = &addr_space_change_notif::remove;
+
+ auto tap_type = sol().registry().new_usertype<tap_helper>("mempassthrough", sol::no_constructor);
+ tap_type["reinstall"] = &tap_helper::reinstall;
+ tap_type["remove"] = &tap_helper::remove;
+ tap_type["addrstart"] = sol::property(&tap_helper::start);
+ tap_type["addrend"] = sol::property(&tap_helper::end);
+ tap_type["name"] = sol::property(&tap_helper::name);
+
+
auto addrmap_type = sol().registry().new_usertype<address_map>("addrmap", sol::no_constructor);
addrmap_type["spacenum"] = sol::readonly(&address_map::m_spacenum);
addrmap_type["device"] = sol::readonly(&address_map::m_device);