mirror of
https://github.com/holub/mame
synced 2025-04-22 16:31:49 +03:00
frontend: Exposed memory pass-through handlers (address space taps) to Lua.
This commit is contained in:
parent
53bfaabe4c
commit
e1a6a41234
@ -1363,6 +1363,42 @@ space:read_range(start, end, width, [step])
|
||||
Reads a range of addresses as a binary string. The end address must be
|
||||
greater than or equal to the start address. The width must be 8, 16, 30 or
|
||||
64. If the step is provided, it must be a positive number of elements.
|
||||
space:add_change_notifier(callback)
|
||||
Adds a
|
||||
:ref:`handler change subscription <luareference-mem-spacechangenotif>` to
|
||||
the address space. The callback function is passed a single string as an
|
||||
argument, either ``r`` if read handlers have potentially changed, ``w`` if
|
||||
write handlers have potentially changed, or ``rw`` if both read and write
|
||||
handlers have potentially changed.
|
||||
|
||||
Note that handler change subscriptions must be explicitly removed before the
|
||||
emulation session ends.
|
||||
space:install_read_tap(start, end, name, callback)
|
||||
Installs a :ref:`pass-through handler <luareference-mem-tap>` that will
|
||||
receive notifications on reads from the specified range of addresses in the
|
||||
address space. The start and end addresses are inclusive. The name must be
|
||||
a string, and the callback must be a function.
|
||||
|
||||
The callback is passed three arguments for the access offset, the data read,
|
||||
and the memory access mask. To modify the data being read, return the
|
||||
modified value from the callback function as an integer. If the callback
|
||||
does not return an integer, the data will not be modified.
|
||||
|
||||
Note that pass-through handlers must be explicitly removed before the
|
||||
emulation session ends.
|
||||
space:install_write_tap(start, end, name, callback)
|
||||
Installs a :ref:`pass-through handler <luareference-mem-tap>` that will
|
||||
receive notifications on write to the specified range of addresses in the
|
||||
address space. The start and end addresses are inclusive. The name must be
|
||||
a string, and the callback must be a function.
|
||||
|
||||
The callback is passed three arguments for the access offset, the data
|
||||
written, and the memory access mask. To modify the data being written,
|
||||
return the modified value from the callback function as an integer. If the
|
||||
callback does not return an integer, the data will not be modified.
|
||||
|
||||
Note that pass-through handlers must be explicitly removed before the
|
||||
emulation session ends.
|
||||
|
||||
Properties
|
||||
^^^^^^^^^^
|
||||
@ -1387,6 +1423,76 @@ space.map (read-only)
|
||||
The configured :ref:`address map <luareference-mem-map>` for the space or
|
||||
``nil``.
|
||||
|
||||
.. _luareference-mem-spacechangenotif:
|
||||
|
||||
Address space change notifier
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Tracks a subscription to :ref:`address space <luareference-mem-space>` handler
|
||||
changes. Note that you must remove subscriptions before the emulation session
|
||||
ends.
|
||||
|
||||
Instantiation
|
||||
^^^^^^^^^^^^^
|
||||
|
||||
manager.machine.devices[tag].spaces[name]:add_change_notifier(callback)
|
||||
Adds a handler change subscriptions to an
|
||||
:ref:`address space <luareference-mem-space>`.
|
||||
|
||||
Methods
|
||||
^^^^^^^
|
||||
|
||||
notifier:remove()
|
||||
Removes the notification subscription. The associated callback will not be
|
||||
called on future handler changes for the address space.
|
||||
|
||||
.. _luareference-mem-tap:
|
||||
|
||||
Pass-through handler
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Tracks a pass-through handler installed in an
|
||||
:ref:`address space <luareference-mem-space>`. A memory pass-through handler
|
||||
receives notifications on accesses to a specified range of addresses, and can
|
||||
modify the data that is read or written if desired. Note that you must remove
|
||||
pass-through handlers before the emulation session ends.
|
||||
|
||||
Instantiation
|
||||
^^^^^^^^^^^^^
|
||||
|
||||
manager.machine.devices[tag].spaces[name]:install_read_tap(start, end, name, callback)
|
||||
Installs a pass-through handler that will receive notifications on reads
|
||||
from the specified range of addresses in an
|
||||
:ref:`address space <luareference-mem-space>`.
|
||||
manager.machine.devices[tag].spaces[name]:install_write_tap(start, end, name, callback)
|
||||
Installs a pass-through handler that will receive notifications on writes to
|
||||
the specified range of addresses in an
|
||||
:ref:`address space <luareference-mem-space>`.
|
||||
|
||||
Methods
|
||||
^^^^^^^
|
||||
|
||||
passthrough:reinstall()
|
||||
Reinstalls the pass-through handler in the address space. May be necessary
|
||||
if the handler is removed due to other changes to handlers in the address
|
||||
space.
|
||||
passthrough:remove()
|
||||
Removes the pass-through handler from the address space. The associated
|
||||
callback will not be called in response to future memory accesses.
|
||||
|
||||
Properties
|
||||
^^^^^^^^^^
|
||||
|
||||
passthrough.addrstart (read-only)
|
||||
The inclusive start address of the address range monitored by the
|
||||
pass-through handler (i.e. the lowest address that the handler will be
|
||||
notified for).
|
||||
passthrough.addrend (read-only)
|
||||
The inclusive end address of the address range monitored by the pass-through
|
||||
handler (i.e. the highest address that the handler will be notified for).
|
||||
passthrough.name (read-only)
|
||||
The display name for the pass-through handler.
|
||||
|
||||
.. _luareference-mem-map:
|
||||
|
||||
Address map
|
||||
@ -3140,8 +3246,8 @@ Wraps MAME’s ``parsed_expression`` class, which represents a tokenised debugge
|
||||
expression. Note that parsed expressions can be created and used even when the
|
||||
debugger is not enabled.
|
||||
|
||||
Intantiation
|
||||
^^^^^^^^^^^^
|
||||
Instantiation
|
||||
^^^^^^^^^^^^^
|
||||
|
||||
emu.parsed_expression(symbols)
|
||||
Creates an empty expression that will use the supplied
|
||||
|
@ -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()
|
||||
|
@ -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;
|
||||
|
@ -183,6 +183,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>())
|
||||
[] (addr_space &sp, sol::this_state s, u64 first, u64 last, int width, sol::object opt_step) -> sol::object
|
||||
{
|
||||
step = opt_step.as<u64>();
|
||||
if (step < 1 || step > last - first)
|
||||
lua_State *L = s;
|
||||
luaL_Buffer buff;
|
||||
offs_t space_size = sp.space.addrmask();
|
||||
u64 step = 1;
|
||||
if (opt_step.is<u64>())
|
||||
{
|
||||
luaL_error(L, "Invalid step");
|
||||
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)
|
||||
{
|
||||
luaL_error(L, "Invalid offset");
|
||||
return sol::lua_nil;
|
||||
}
|
||||
}
|
||||
if (first > space_size || last > space_size || last < first)
|
||||
int byte_count = width / 8 * (last - first + 1) / step;
|
||||
switch (width)
|
||||
{
|
||||
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;
|
||||
}
|
||||
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)
|
||||
{
|
||||
luaL_error(L, "Invalid offset");
|
||||
return sol::lua_nil;
|
||||
}
|
||||
int byte_count = width / 8 * (last - first + 1) / step;
|
||||
switch (width)
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
luaL_pushresultsize(&buff, byte_count);
|
||||
return sol::make_reference(L, sol::stack_reference(L, -1));
|
||||
};
|
||||
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);
|
||||
|
Loading…
Reference in New Issue
Block a user