summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--plugins/autofire/autofire_menu.lua4
-rw-r--r--plugins/cheatfind/init.lua10
-rw-r--r--plugins/inputmacro/inputmacro_menu.lua24
-rw-r--r--plugins/timer/init.lua2
-rw-r--r--src/frontend/mame/luaengine.cpp275
-rw-r--r--src/frontend/mame/luaengine.h33
-rw-r--r--src/frontend/mame/luaengine.ipp60
-rw-r--r--src/frontend/mame/luaengine_debug.cpp20
-rw-r--r--src/frontend/mame/luaengine_mem.cpp232
-rw-r--r--src/frontend/mame/mame.cpp72
-rw-r--r--src/frontend/mame/mame.h25
11 files changed, 416 insertions, 341 deletions
diff --git a/plugins/autofire/autofire_menu.lua b/plugins/autofire/autofire_menu.lua
index 5c87e27a63d..e2287ce2276 100644
--- a/plugins/autofire/autofire_menu.lua
+++ b/plugins/autofire/autofire_menu.lua
@@ -157,8 +157,8 @@ local function populate_configure_menu(menu)
configure_selection_save = #menu
end
table.insert(menu, {_p('plugin-autofire', 'Hotkey'), key_name, hotkey_poller and 'lr' or ''})
- table.insert(menu, {_p('plugin-autofire', 'On frames'), current_button.on_frames, current_button.on_frames > 1 and 'lr' or 'r'})
- table.insert(menu, {_p('plugin-autofire', 'Off frames'), current_button.off_frames, current_button.off_frames > 1 and 'lr' or 'r'})
+ table.insert(menu, {_p('plugin-autofire', 'On frames'), tostring(current_button.on_frames), current_button.on_frames > 1 and 'lr' or 'r'})
+ table.insert(menu, {_p('plugin-autofire', 'Off frames'), tostring(current_button.off_frames), current_button.off_frames > 1 and 'lr' or 'r'})
configure_menu_active = true
end
diff --git a/plugins/cheatfind/init.lua b/plugins/cheatfind/init.lua
index d565b31437f..96617e12fb6 100644
--- a/plugins/cheatfind/init.lua
+++ b/plugins/cheatfind/init.lua
@@ -351,7 +351,7 @@ function cheatfind.startplugin()
for num, func in ipairs(menu) do
local item, f = func()
if item then
- menu_list[#menu_list + 1] = item
+ table.insert(menu_list, item)
menu_func[#menu_list] = f
end
end
@@ -715,9 +715,9 @@ function cheatfind.startplugin()
end
local m
if optable[opsel] == "ltv" or optable[opsel] == "gtv" or optable[opsel] == "eqv" or optable[opsel] == "nev" then
- m = { _("Value"), value, "" }
+ m = { _("Value"), tostring(value), "" }
else
- m = { _("Difference"), value, "" }
+ m = { _("Difference"), tostring(value), "" }
end
local max = 100 -- max value?
menu_lim(value, 0, max, m)
@@ -792,7 +792,7 @@ function cheatfind.startplugin()
end
menu[#menu + 1] = function() return { "---", "", "off" }, nil end
menu[#menu + 1] = function()
- local m = { _("Match block"), matchsel, "" }
+ local m = { _("Match block"), tostring(matchsel), "" }
menu_lim(matchsel, 0, #matches[#matches], m)
if matchsel == 0 then
m[2] = _("All")
@@ -1017,7 +1017,7 @@ function cheatfind.startplugin()
end
if matches[#matches].count > 100 then
menu[#menu + 1] = function()
- local m = { _("Page"), matchpg, "on" }
+ local m = { _("Page"), tostring(matchpg), "on" }
local max
if matchsel == 0 then
max = math.ceil(matches[#matches].count / 100) - 1
diff --git a/plugins/inputmacro/inputmacro_menu.lua b/plugins/inputmacro/inputmacro_menu.lua
index 33223e9f20f..0c22de4a8f6 100644
--- a/plugins/inputmacro/inputmacro_menu.lua
+++ b/plugins/inputmacro/inputmacro_menu.lua
@@ -347,7 +347,7 @@ local function add_edit_items(items)
local input = manager.machine.input
local arrows
- items[#items + 1] = { _p('plugin-inputmacro', 'Name'), edit_name_buffer and (edit_name_buffer .. '_') or edit_current_macro.name, '' }
+ table.insert(items, { _p('plugin-inputmacro', 'Name'), edit_name_buffer and (edit_name_buffer .. '_') or edit_current_macro.name, '' })
edit_items[#items] = { action = 'name' }
if not (edit_start_selection or edit_start_step or edit_menu_active) then
edit_start_selection = #items
@@ -356,11 +356,11 @@ local function add_edit_items(items)
local binding = edit_current_macro.binding
local activation = binding and input:seq_name(binding) or _p('plugin-inputmacro', '[not set]')
- items[#items + 1] = { _p('plugin-inputmacro', 'Activation sequence'), activation, edit_switch_poller and 'lr' or '' }
+ table.insert(items, { _p('plugin-inputmacro', 'Activation sequence'), activation, edit_switch_poller and 'lr' or '' })
edit_items[#items] = { action = 'binding' }
local releaseaction = edit_current_macro.earlycancel and _p('plugin-inputmacro', 'Stop immediately') or _p('plugin-inputmacro', 'Complete macro')
- items[#items + 1] = { _p('plugin-inputmacro', 'On release'), releaseaction, edit_current_macro.earlycancel and 'r' or 'l' }
+ table.insert(items, { _p('plugin-inputmacro', 'On release'), releaseaction, edit_current_macro.earlycancel and 'r' or 'l' })
edit_items[#items] = { action = 'releaseaction' }
local holdaction
@@ -376,18 +376,18 @@ local function add_edit_items(items)
else
holdaction = string.format(_p('plugin-inputmacro', 'Prolong step %d'), #edit_current_macro.steps)
end
- items[#items + 1] = { _p('plugin-inputmacro', 'When held'), holdaction, arrows }
+ table.insert(items, { _p('plugin-inputmacro', 'When held'), holdaction, arrows })
edit_items[#items] = { action = 'holdaction' }
for i, step in ipairs(edit_current_macro.steps) do
- items[#items + 1] = { string.format(_p('plugin-inputmacro', 'Step %d'), i), '', 'heading' }
- items[#items + 1] = { _p('plugin-inputmacro', 'Delay (frames)'), step.delay, (step.delay > 0) and 'lr' or 'r' }
+ table.insert(items, { string.format(_p('plugin-inputmacro', 'Step %d'), i), '', 'heading' })
+ table.insert(items, { _p('plugin-inputmacro', 'Delay (frames)'), tostring(step.delay), (step.delay > 0) and 'lr' or 'r' })
edit_items[#items] = { action = 'delay', step = i }
if edit_start_step == i then
edit_start_selection = #items
end
- items[#items + 1] = { _p('plugin-inputmacro', 'Duration (frames)'), step.duration, (step.duration > 1) and 'lr' or 'r' }
+ table.insert(items, { _p('plugin-inputmacro', 'Duration (frames)'), tostring(step.duration), (step.duration > 1) and 'lr' or 'r' })
edit_items[#items] = { action = 'duration', step = i }
for j, input in ipairs(step.inputs) do
@@ -399,17 +399,17 @@ local function add_edit_items(items)
else
inputname = _p('plugin-inputmacro', '[not set]')
end
- items[#items + 1] = { string.format(_p('plugin-inputmacro', 'Input %d'), j), inputname, '' }
+ table.insert(items, { string.format(_p('plugin-inputmacro', 'Input %d'), j), inputname, '' })
edit_items[#items] = { action = 'input', step = i, input = j }
end
if step.inputs[#step.inputs].field then
- items[#items + 1] = { _p('plugin-inputmacro', 'Add input'), '', '' }
+ table.insert(items, { _p('plugin-inputmacro', 'Add input'), '', '' })
edit_items[#items] = { action = 'addinput', step = i }
end
if #edit_current_macro.steps > 1 then
- items[#items + 1] = { _p('plugin-inputmacro', 'Delete step'), '', '' }
+ table.insert(items, { _p('plugin-inputmacro', 'Delete step'), '', '' })
edit_items[#items] = { action = 'deletestep', step = i }
end
end
@@ -417,7 +417,7 @@ local function add_edit_items(items)
local laststep = edit_current_macro.steps[#edit_current_macro.steps]
if laststep.inputs[#laststep.inputs].field then
- items[#items + 1] = { '---', '', '' }
+ table.insert(items, { '---', '', '' })
arrows = 'lr'
if edit_insert_position > #edit_current_macro.steps then
@@ -425,7 +425,7 @@ local function add_edit_items(items)
elseif edit_insert_position < 2 then
arrows = 'r'
end
- items[#items + 1] = { _p('plugin-inputmacro', 'Add step at position'), edit_insert_position, arrows }
+ table.insert(items, { _p('plugin-inputmacro', 'Add step at position'), tostring(edit_insert_position), arrows })
edit_items[#items] = { action = 'addstep', step = i }
end
end
diff --git a/plugins/timer/init.lua b/plugins/timer/init.lua
index e7d7155b4c1..35dbb6431ac 100644
--- a/plugins/timer/init.lua
+++ b/plugins/timer/init.lua
@@ -38,7 +38,7 @@ function timer.startplugin()
{ '---', '', '' },
{ _p("plugin-timer", "Current time"), sectohms(time), "off" },
{ _p("plugin-timer", "Total time"), sectohms(total), "off" },
- { _p("plugin-timer", "Play Count"), play_count, "off" } },
+ { _p("plugin-timer", "Play Count"), tostring(play_count), "off" } },
highlight,
"idle"
end
diff --git a/src/frontend/mame/luaengine.cpp b/src/frontend/mame/luaengine.cpp
index 6981ebfe41b..db35b227faa 100644
--- a/src/frontend/mame/luaengine.cpp
+++ b/src/frontend/mame/luaengine.cpp
@@ -352,16 +352,18 @@ sol::object lua_engine::call_plugin(const std::string &name, sol::object in)
{
std::string field = "cb_" + name;
sol::object obj = sol().registry()[field];
- if(obj.is<sol::protected_function>())
+ if (obj.is<sol::protected_function>())
{
auto res = invoke(obj.as<sol::protected_function>(), in);
- if(!res.valid())
+ if (!res.valid())
{
sol::error err = res;
osd_printf_error("[LUA ERROR] in call_plugin: %s\n", err.what());
}
else
+ {
return res.get<sol::object>();
+ }
}
return sol::lua_nil;
}
@@ -380,7 +382,7 @@ std::optional<long> lua_engine::menu_populate(const std::string &menu, std::vect
}
else
{
- std::tuple<sol::table, std::optional<long>, std::string> table = res;
+ std::tuple<sol::table, std::optional<long>, std::optional<std::string> > table = res;
for (auto &entry : std::get<0>(table))
{
if (entry.second.is<sol::table>())
@@ -389,7 +391,10 @@ std::optional<long> lua_engine::menu_populate(const std::string &menu, std::vect
menu_list.emplace_back(enttable.get<std::string, std::string, std::string>(1, 2, 3));
}
}
- flags = std::get<2>(table);
+ if (std::get<2>(table))
+ flags = *std::get<2>(table);
+ else
+ flags.clear();
return std::get<1>(table);
}
}
@@ -400,7 +405,7 @@ std::optional<long> lua_engine::menu_populate(const std::string &menu, std::vect
std::pair<bool, std::optional<long> > lua_engine::menu_callback(const std::string &menu, int index, const std::string &event)
{
std::string field = "menu_cb_" + menu;
- std::pair<bool, std::optional<long> > ret(false, std::nullopt);
+ std::pair<std::optional<bool>, std::optional<long> > ret(false, std::nullopt);
sol::object obj = sol().registry()[field];
if (obj.is<sol::protected_function>())
{
@@ -415,7 +420,7 @@ std::pair<bool, std::optional<long> > lua_engine::menu_callback(const std::strin
ret = res;
}
}
- return ret;
+ return std::make_pair(std::get<0>(ret) && *std::get<0>(ret), std::get<1>(ret));
}
void lua_engine::set_machine(running_machine *machine)
@@ -423,9 +428,10 @@ void lua_engine::set_machine(running_machine *machine)
m_machine = machine;
}
-int lua_engine::enumerate_functions(const char *id, std::function<bool(const sol::protected_function &func)> &&callback)
+template <typename T>
+size_t lua_engine::enumerate_functions(const char *id, T &&callback)
{
- int count = 0;
+ size_t count = 0;
sol::object functable = sol().registry()[id];
if (functable.is<sol::table>())
{
@@ -439,23 +445,24 @@ int lua_engine::enumerate_functions(const char *id, std::function<bool(const sol
break;
}
}
- return true;
}
return count;
}
bool lua_engine::execute_function(const char *id)
{
- int count = enumerate_functions(id, [this](const sol::protected_function &func)
- {
- auto ret = invoke(func);
- if(!ret.valid())
- {
- sol::error err = ret;
- osd_printf_error("[LUA ERROR] in execute_function: %s\n", err.what());
- }
- return true;
- });
+ size_t count = enumerate_functions(
+ id,
+ [] (const sol::protected_function &func)
+ {
+ auto ret = invoke(func);
+ if (!ret.valid())
+ {
+ sol::error err = ret;
+ osd_printf_error("[LUA ERROR] in execute_function: %s\n", err.what());
+ }
+ return true;
+ });
return count > 0;
}
@@ -521,21 +528,23 @@ void lua_engine::on_periodic()
bool lua_engine::on_missing_mandatory_image(const std::string &instance_name)
{
bool handled = false;
- enumerate_functions("LUA_ON_MANDATORY_FILE_MANAGER_OVERRIDE", [this, &instance_name, &handled](const sol::protected_function &func)
- {
- auto ret = invoke(func, instance_name);
+ enumerate_functions(
+ "LUA_ON_MANDATORY_FILE_MANAGER_OVERRIDE",
+ [&instance_name, &handled] (const sol::protected_function &func)
+ {
+ auto ret = invoke(func, instance_name);
- if(!ret.valid())
- {
- sol::error err = ret;
- osd_printf_error("[LUA ERROR] in on_missing_mandatory_image: %s\n", err.what());
- }
- else if (ret.get<bool>())
- {
- handled = true;
- }
- return !handled;
- });
+ if (!ret.valid())
+ {
+ sol::error err = ret;
+ osd_printf_error("[LUA ERROR] in on_missing_mandatory_image: %s\n", err.what());
+ }
+ else if (ret.get<bool>())
+ {
+ handled = true;
+ }
+ return !handled;
+ });
return handled;
}
@@ -829,7 +838,7 @@ void lua_engine::initialize()
auto space = buf.prepare(len);
space.add(file.read(space.get(), len));
buf.push();
- return sol::stack::pop<sol::object>(s);
+ return sol::make_reference(s, sol::stack_reference(s, -1));
});
file_type.set("write", [](emu_file &file, const std::string &data) { return file.write(data.data(), data.size()); });
file_type.set("puts", &emu_file::puts);
@@ -974,12 +983,14 @@ void lua_engine::initialize()
}));
item_type.set("size", sol::readonly(&save_item::size));
item_type.set("count", sol::readonly(&save_item::count));
- item_type.set("read", [this](save_item &item, int offset) -> sol::object {
- if(!item.base || (offset >= item.count))
+ item_type.set("read",
+ [this] (save_item &item, int offset) -> sol::object
+ {
+ if (!item.base || (offset >= item.count))
return sol::lua_nil;
const void *const data = reinterpret_cast<const uint8_t *>(item.base) + (item.stride * (offset / item.valcount));
uint64_t ret = 0;
- switch(item.size)
+ switch (item.size)
{
case 1:
default:
@@ -997,33 +1008,38 @@ void lua_engine::initialize()
}
return sol::make_object(sol(), ret);
});
- item_type.set("read_block", [](save_item &item, sol::this_state s, int offset, size_t len) {
- buffer_helper buf(s);
- auto space = buf.prepare(len);
- if(!item.base || ((offset + len) > (item.size * item.count)))
+ item_type.set("read_block",
+ [] (save_item &item, sol::this_state s, uint32_t offset, size_t len) -> sol::object
+ {
+ if (!item.base)
{
- space.add(0);
+ luaL_error(s, "Invalid save item");
+ return sol::lua_nil;
}
- else
+
+ if ((offset + len) > (item.size * item.count))
{
- const uint32_t blocksize = item.size * item.valcount;
- size_t remaining = len;
- uint8_t *dest = reinterpret_cast<uint8_t *>(space.get());
- while(remaining)
- {
- const uint32_t blockno = offset / blocksize;
- const uint32_t available = blocksize - (offset % blocksize);
- const uint32_t chunk = (available < remaining) ? available : remaining;
- const void *const source = reinterpret_cast<const uint8_t *>(item.base) + (blockno * item.stride) + (offset % blocksize);
- std::memcpy(dest, source, chunk);
- offset += chunk;
- remaining -= chunk;
- dest += chunk;
- }
- space.add(len);
+ luaL_error(s, "Range extends beyond end of save item");
+ return sol::lua_nil;
}
- buf.push();
- return sol::stack::pop<sol::object>(s);
+
+ luaL_Buffer buff;
+ uint8_t *dest = reinterpret_cast<uint8_t *>(luaL_buffinitsize(s, &buff, len));
+ const uint32_t blocksize = item.size * item.valcount;
+ size_t remaining = len;
+ while (remaining)
+ {
+ const uint32_t blockno = offset / blocksize;
+ const uint32_t available = blocksize - (offset % blocksize);
+ const uint32_t chunk = (available < remaining) ? available : remaining;
+ const void *const source = reinterpret_cast<const uint8_t *>(item.base) + (blockno * item.stride) + (offset % blocksize);
+ std::memcpy(dest, source, chunk);
+ offset += chunk;
+ remaining -= chunk;
+ dest += chunk;
+ }
+ luaL_pushresultsize(&buff, len);
+ return sol::make_reference(s, sol::stack_reference(s, -1));
});
item_type.set("write", [](save_item &item, int offset, uint64_t value) {
if(!item.base || (offset >= item.count))
@@ -1187,54 +1203,54 @@ void lua_engine::initialize()
auto machine_type = sol().registry().new_usertype<running_machine>("machine", sol::no_constructor);
- machine_type["exit"] = &running_machine::schedule_exit;
- machine_type["hard_reset"] = &running_machine::schedule_hard_reset;
- machine_type["soft_reset"] = &running_machine::schedule_soft_reset;
- machine_type["save"] = &running_machine::schedule_save; // TODO: some kind of completion notification?
- machine_type["load"] = &running_machine::schedule_load; // TODO: some kind of completion notification?
- machine_type["buffer_save"] =
- [] (running_machine &m, sol::this_state s)
- {
- // FIXME: this needs to schedule saving to a buffer and return asynchronously somehow
- // right now it's broken by anonymous timers, synchronize, etc.
- lua_State *L = s;
- luaL_Buffer buff;
- int size = ram_state::get_size(m.save());
- u8 *ptr = (u8 *)luaL_buffinitsize(L, &buff, size);
- save_error error = m.save().write_buffer(ptr, size);
- if (error == STATERR_NONE)
+ machine_type.set_function("exit", &running_machine::schedule_exit);
+ machine_type.set_function("hard_reset", &running_machine::schedule_hard_reset);
+ machine_type.set_function("soft_reset", &running_machine::schedule_soft_reset);
+ machine_type.set_function("save", &running_machine::schedule_save); // TODO: some kind of completion notification?
+ machine_type.set_function("load", &running_machine::schedule_load); // TODO: some kind of completion notification?
+ machine_type.set_function("buffer_save",
+ [] (running_machine &m, sol::this_state s)
{
- luaL_pushresultsize(&buff, size);
- return sol::make_reference(L, sol::stack_reference(L, -1));
- }
- luaL_error(L, "State save error.");
- return sol::make_reference(L, nullptr);
- };
- machine_type["buffer_load"] =
- [] (running_machine &m, sol::this_state s, std::string str)
- {
- // FIXME: this needs to schedule loading from the buffer and return asynchronously somehow
- // right now it's broken by anonymous timers, synchronize, etc.
- save_error error = m.save().read_buffer((u8 *)str.data(), str.size());
- if (error == STATERR_NONE)
+ // FIXME: this needs to schedule saving to a buffer and return asynchronously somehow
+ // right now it's broken by anonymous timers, synchronize, etc.
+ lua_State *L = s;
+ luaL_Buffer buff;
+ int size = ram_state::get_size(m.save());
+ u8 *ptr = (u8 *)luaL_buffinitsize(L, &buff, size);
+ save_error error = m.save().write_buffer(ptr, size);
+ if (error == STATERR_NONE)
+ {
+ luaL_pushresultsize(&buff, size);
+ return sol::make_reference(L, sol::stack_reference(L, -1));
+ }
+ luaL_error(L, "State save error.");
+ return sol::make_reference(L, nullptr);
+ });
+ machine_type.set_function("buffer_load",
+ [] (running_machine &m, sol::this_state s, std::string str)
{
- return true;
- }
- else
+ // FIXME: this needs to schedule loading from the buffer and return asynchronously somehow
+ // right now it's broken by anonymous timers, synchronize, etc.
+ save_error error = m.save().read_buffer((u8 *)str.data(), str.size());
+ if (error == STATERR_NONE)
+ {
+ return true;
+ }
+ else
+ {
+ luaL_error(s,"State load error.");
+ return false;
+ }
+ });
+ machine_type.set_function("popmessage",
+ [] (running_machine &m, std::optional<const char *> str)
{
- luaL_error(s,"State load error.");
- return false;
- }
- };
- machine_type["popmessage"] =
- [] (running_machine &m, const char *str)
- {
- if (str)
- m.popmessage("%s", str);
- else
- m.popmessage();
- };
- machine_type["logerror"] = [] (running_machine &m, std::string const *str) { m.logerror("[luaengine] %s\n", str); };
+ if (str)
+ m.popmessage("%s", *str);
+ else
+ m.popmessage();
+ });
+ machine_type.set_function("logerror", [] (running_machine &m, char const *str) { m.logerror("[luaengine] %s\n", str); });
machine_type["time"] = sol::property(&running_machine::time);
machine_type["system"] = sol::property(&running_machine::system);
machine_type["parameters"] = sol::property(&running_machine::parameters);
@@ -1337,15 +1353,16 @@ void lua_engine::initialize()
auto device_type = sol().registry().new_usertype<device_t>("device", sol::no_constructor);
- device_type["subtag"] = &device_t::subtag;
- device_type["siblingtag"] = &device_t::siblingtag;
- device_type["memregion"] = &device_t::memregion;
- device_type["memshare"] = &device_t::memshare;
- device_type["membank"] = &device_t::membank;
- device_type["ioport"] = &device_t::ioport;
- device_type["subdevice"] = static_cast<device_t *(device_t::*)(std::string_view) const>(&device_t::subdevice);
- device_type["siblingdevice"] = static_cast<device_t *(device_t::*)(std::string_view) const>(&device_t::siblingdevice);
- device_type["parameter"] = &device_t::parameter;
+ device_type.set_function(sol::meta_function::to_string, [] (device_t &d) { return util::string_format("%s(%s)", d.shortname(), d.tag()); });
+ device_type.set_function("subtag", &device_t::subtag);
+ device_type.set_function("siblingtag", &device_t::siblingtag);
+ device_type.set_function("memregion", &device_t::memregion);
+ device_type.set_function("memshare", &device_t::memshare);
+ device_type.set_function("membank", &device_t::membank);
+ device_type.set_function("ioport", &device_t::ioport);
+ device_type.set_function("subdevice", static_cast<device_t *(device_t::*)(std::string_view) const>(&device_t::subdevice));
+ device_type.set_function("siblingdevice", static_cast<device_t *(device_t::*)(std::string_view) const>(&device_t::siblingdevice));
+ device_type.set_function("parameter", &device_t::parameter);
device_type["tag"] = sol::property(&device_t::tag);
device_type["basetag"] = sol::property(&device_t::basetag);
device_type["name"] = sol::property(&device_t::name);
@@ -1914,35 +1931,29 @@ void lua_engine::resume(int nparam)
luaL_unref(m_lua_state, LUA_REGISTRYINDEX, nparam);
}
-void lua_engine::run(sol::load_result res)
+//-------------------------------------------------
+// load_script - load script from file path
+//-------------------------------------------------
+
+sol::load_result lua_engine::load_script(std::string const &filename)
{
- if(res.valid())
- {
- auto ret = invoke(res.get<sol::protected_function>());
- if(!ret.valid())
- {
- sol::error err = ret;
- osd_printf_error("[LUA ERROR] in run: %s\n", err.what());
- }
- }
- else
- osd_printf_error("[LUA ERROR] %d loading Lua script\n", (int)res.status());
+ return sol().load_file(filename);
}
//-------------------------------------------------
-// execute - load and execute script
+// load_string - load script from string
//-------------------------------------------------
-void lua_engine::load_script(const char *filename)
+sol::load_result lua_engine::load_string(std::string const &value)
{
- run(sol().load_file(filename));
+ return sol().load(value);
}
//-------------------------------------------------
-// execute_string - execute script from string
+// make_environment - make a sandbox
//-------------------------------------------------
-void lua_engine::load_string(const char *value)
+sol::environment lua_engine::make_environment()
{
- run(sol().load(value));
+ return sol::environment(sol(), sol::create, sol().globals());
}
diff --git a/src/frontend/mame/luaengine.h b/src/frontend/mame/luaengine.h
index 6c5f572885d..27761eb85b5 100644
--- a/src/frontend/mame/luaengine.h
+++ b/src/frontend/mame/luaengine.h
@@ -34,7 +34,6 @@ class lua_engine
{
public:
// helper structures
- class buffer_helper;
template <typename T> struct devenum;
template <typename T> struct simple_list_wrapper;
template <typename T> struct tag_object_ptr_map;
@@ -48,8 +47,9 @@ public:
~lua_engine();
void initialize();
- void load_script(const char *filename);
- void load_string(const char *value);
+ sol::load_result load_script(std::string const &filename);
+ sol::load_result load_string(std::string const &value);
+ sol::environment make_environment();
bool frame_hook();
@@ -122,9 +122,27 @@ public:
sol::state_view &sol() const { return *m_sol_state; }
+ template <typename Func, typename... Params>
+ static std::decay_t<std::invoke_result_t<Func, Params...> > invoke(Func &&func, Params&&... args)
+ {
+ g_profiler.start(PROFILER_LUA);
+ try
+ {
+ auto result = func(std::forward<Params>(args)...);
+ g_profiler.stop();
+ return result;
+ }
+ catch (...)
+ {
+ g_profiler.stop();
+ throw;
+ }
+ }
+
private:
- template<typename T, size_t SIZE> class enum_parser;
+ template <typename T, size_t Size> class enum_parser;
+ class buffer_helper;
struct addr_space;
class tap_helper;
class addr_space_change_notif;
@@ -170,17 +188,12 @@ private:
void resume(int nparam);
void register_function(sol::function func, const char *id);
- int enumerate_functions(const char *id, std::function<bool(const sol::protected_function &func)> &&callback);
+ template <typename T> size_t enumerate_functions(const char *id, T &&callback);
bool execute_function(const char *id);
sol::object call_plugin(const std::string &name, sol::object in);
void close();
- void run(sol::load_result res);
-
- template <typename TFunc, typename... TArgs>
- sol::protected_function_result invoke(TFunc &&func, TArgs&&... args);
-
void initialize_debug(sol::table &emu);
void initialize_input(sol::table &emu);
void initialize_memory(sol::table &emu);
diff --git a/src/frontend/mame/luaengine.ipp b/src/frontend/mame/luaengine.ipp
index 0dd6d3d8d90..08d55a48e37 100644
--- a/src/frontend/mame/luaengine.ipp
+++ b/src/frontend/mame/luaengine.ipp
@@ -21,6 +21,24 @@
+template <typename T>
+struct lua_engine::simple_list_wrapper
+{
+ simple_list_wrapper(simple_list<T> const &l) : list(l) { }
+
+ simple_list<T> const &list;
+};
+
+
+template <typename T>
+struct lua_engine::tag_object_ptr_map
+{
+ tag_object_ptr_map(T const &m) : map(m) { }
+
+ T const &map;
+};
+
+
class lua_engine::buffer_helper
{
private:
@@ -110,24 +128,6 @@ public:
};
-template <typename T>
-struct lua_engine::simple_list_wrapper
-{
- simple_list_wrapper(simple_list<T> const &l) : list(l) { }
-
- simple_list<T> const &list;
-};
-
-
-template <typename T>
-struct lua_engine::tag_object_ptr_map
-{
- tag_object_ptr_map(T const &m) : map(m) { }
-
- T const &map;
-};
-
-
namespace sol {
// don't convert core_options to a table directly
@@ -491,13 +491,13 @@ struct lua_engine::addr_space
};
-template <typename T, size_t SIZE>
+template <typename T, size_t Size>
class lua_engine::enum_parser
{
public:
constexpr enum_parser(std::initializer_list<std::pair<std::string_view, T> > values)
{
- if (values.size() != SIZE)
+ if (values.size() != Size)
throw false && "size template argument incorrectly specified";
std::copy(values.begin(), values.end(), m_map.begin());
}
@@ -514,7 +514,7 @@ public:
}
private:
- std::array<std::pair<std::string_view, T>, SIZE> m_map;
+ std::array<std::pair<std::string_view, T>, Size> m_map;
};
@@ -527,7 +527,7 @@ template <typename R, typename T, typename D>
auto lua_engine::make_simple_callback_setter(void (T::*setter)(delegate<R ()> &&), D &&dflt, const char *name, const char *desc)
{
return
- [this, setter, dflt, name, desc] (T &self, sol::object cb)
+ [setter, dflt, name, desc] (T &self, sol::object cb)
{
if (cb == sol::lua_nil)
{
@@ -536,7 +536,7 @@ auto lua_engine::make_simple_callback_setter(void (T::*setter)(delegate<R ()> &&
else if (cb.is<sol::protected_function>())
{
(self.*setter)(delegate<R ()>(
- [this, dflt, desc, cbfunc = cb.as<sol::protected_function>()] () -> R
+ [dflt, desc, cbfunc = cb.as<sol::protected_function>()] () -> R
{
if constexpr (std::is_same_v<R, void>)
{
@@ -566,18 +566,4 @@ auto lua_engine::make_simple_callback_setter(void (T::*setter)(delegate<R ()> &&
};
}
-
-//-------------------------------------------------
-// invoke - invokes a function, wrapping profiler
-//-------------------------------------------------
-
-template <typename TFunc, typename... TArgs>
-inline sol::protected_function_result lua_engine::invoke(TFunc &&func, TArgs &&... args)
-{
- g_profiler.start(PROFILER_LUA);
- sol::protected_function_result result = func(std::forward<TArgs>(args)...);
- g_profiler.stop();
- return result;
-}
-
#endif // MAME_FRONTEND_MAME_LUAENGINE_IPP
diff --git a/src/frontend/mame/luaengine_debug.cpp b/src/frontend/mame/luaengine_debug.cpp
index 94748d5a897..e2c6713ff44 100644
--- a/src/frontend/mame/luaengine_debug.cpp
+++ b/src/frontend/mame/luaengine_debug.cpp
@@ -181,14 +181,14 @@ void lua_engine::initialize_debug(sol::table &emu)
{ "m", EXPSPACE_REGION }
};
- auto const do_add_symbol = [this] (symbol_table_wrapper &st, char const *name, sol::protected_function getter, std::optional<sol::protected_function> setter, std::optional<char const *> format) -> symbol_entry &
+ auto const do_add_symbol = [] (symbol_table_wrapper &st, char const *name, sol::protected_function getter, std::optional<sol::protected_function> setter, std::optional<char const *> format) -> symbol_entry &
{
symbol_table::setter_func setfun;
if (setter)
- setfun = [this, cbfunc = std::move(*setter)] (u64 value) { invoke(cbfunc, value); };
+ setfun = [cbfunc = std::move(*setter)] (u64 value) { invoke(cbfunc, value); };
return st.table().add(
name,
- [this, cbfunc = std::move(getter)] () -> u64
+ [cbfunc = std::move(getter)] () -> u64
{
auto result = invoke(cbfunc).get<sol::optional<u64> >();
if (result)
@@ -217,12 +217,12 @@ void lua_engine::initialize_debug(sol::table &emu)
[] (device_t &device)
{ return std::make_shared<symbol_table_wrapper>(device.machine(), nullptr, &device); }));
symbol_table_type.set_function("set_memory_modified_func",
- [this] (symbol_table_wrapper &st, sol::object cb)
+ [] (symbol_table_wrapper &st, sol::object cb)
{
if (cb == sol::lua_nil)
st.table().set_memory_modified_func(nullptr);
else if (cb.is<sol::protected_function>())
- st.table().set_memory_modified_func([this, cbfunc = cb.as<sol::protected_function>()] () { invoke(cbfunc); });
+ st.table().set_memory_modified_func([cbfunc = cb.as<sol::protected_function>()] () { invoke(cbfunc); });
else
osd_printf_error("[LUA ERROR] must call set_memory_modified_func with function or nil\n");
});
@@ -246,19 +246,19 @@ void lua_engine::initialize_debug(sol::table &emu)
{
return do_add_symbol(st, name, getter, std::nullopt, nullptr);
},
- [this] (symbol_table_wrapper &st, char const *name, int minparams, int maxparams, sol::protected_function execute) -> symbol_entry &
+ [] (symbol_table_wrapper &st, sol::this_state s, char const *name, int minparams, int maxparams, sol::protected_function execute) -> symbol_entry &
{
return st.table().add(
name,
minparams,
maxparams,
- [this, cbref = sol::reference(execute)] (int numparams, u64 const *paramlist) -> u64
+ [L = s.L, cbref = sol::reference(execute)] (int numparams, u64 const *paramlist) -> u64
{
- sol::stack_reference traceback(m_lua_state, -sol::stack::push(m_lua_state, sol::default_traceback_error_handler));
+ sol::stack_reference traceback(L, -sol::stack::push(L, sol::default_traceback_error_handler));
cbref.push();
- sol::stack_aligned_stack_handler_function func(m_lua_state, -1, traceback);
+ sol::stack_aligned_stack_handler_function func(L, -1, traceback);
for (int i = 0; numparams > i; ++i)
- lua_pushinteger(m_lua_state, paramlist[i]);
+ lua_pushinteger(L, paramlist[i]);
auto result = func(sol::stack_count(numparams)).get<sol::optional<u64> >();
traceback.pop();
return result ? *result : 0;
diff --git a/src/frontend/mame/luaengine_mem.cpp b/src/frontend/mame/luaengine_mem.cpp
index f22d23b0961..1bbf7c24431 100644
--- a/src/frontend/mame/luaengine_mem.cpp
+++ b/src/frontend/mame/luaengine_mem.cpp
@@ -195,7 +195,6 @@ public:
tap_helper(tap_helper &&) = delete;
tap_helper(
- lua_engine &engine,
address_space &space,
read_or_write mode,
offs_t start,
@@ -203,7 +202,6 @@ public:
std::string &&name,
sol::protected_function &&callback)
: m_callback(std::move(callback))
- , m_engine(engine)
, m_space(space)
, m_handler()
, m_name(std::move(name))
@@ -270,7 +268,7 @@ private:
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> >();
+ auto result = invoke(m_callback, offset, data, mem_mask).template get<sol::optional<T> >();
if (result)
data = *result;
},
@@ -283,7 +281,7 @@ private:
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> >();
+ auto result = invoke(m_callback, offset, data, mem_mask).template get<sol::optional<T> >();
if (result)
data = *result;
},
@@ -303,7 +301,6 @@ private:
};
sol::protected_function m_callback;
- lua_engine &m_engine;
address_space &m_space;
memory_passthrough_handler m_handler;
std::string m_name;
@@ -531,118 +528,125 @@ void lua_engine::initialize_memory(sol::table &emu)
{
auto addr_space_type = sol().registry().new_usertype<addr_space>("addr_space", sol::no_constructor);
- addr_space_type["read_i8"] = &addr_space::mem_read<s8>;
- addr_space_type["read_u8"] = &addr_space::mem_read<u8>;
- addr_space_type["read_i16"] = &addr_space::mem_read<s16>;
- addr_space_type["read_u16"] = &addr_space::mem_read<u16>;
- addr_space_type["read_i32"] = &addr_space::mem_read<s32>;
- addr_space_type["read_u32"] = &addr_space::mem_read<u32>;
- addr_space_type["read_i64"] = &addr_space::mem_read<s64>;
- addr_space_type["read_u64"] = &addr_space::mem_read<u64>;
- addr_space_type["write_i8"] = &addr_space::mem_write<s8>;
- addr_space_type["write_u8"] = &addr_space::mem_write<u8>;
- addr_space_type["write_i16"] = &addr_space::mem_write<s16>;
- addr_space_type["write_u16"] = &addr_space::mem_write<u16>;
- addr_space_type["write_i32"] = &addr_space::mem_write<s32>;
- addr_space_type["write_u32"] = &addr_space::mem_write<u32>;
- addr_space_type["write_i64"] = &addr_space::mem_write<s64>;
- addr_space_type["write_u64"] = &addr_space::mem_write<u64>;
- addr_space_type["readv_i8"] = &addr_space::log_mem_read<s8>;
- addr_space_type["readv_u8"] = &addr_space::log_mem_read<u8>;
- addr_space_type["readv_i16"] = &addr_space::log_mem_read<s16>;
- addr_space_type["readv_u16"] = &addr_space::log_mem_read<u16>;
- addr_space_type["readv_i32"] = &addr_space::log_mem_read<s32>;
- addr_space_type["readv_u32"] = &addr_space::log_mem_read<u32>;
- addr_space_type["readv_i64"] = &addr_space::log_mem_read<s64>;
- addr_space_type["readv_u64"] = &addr_space::log_mem_read<u64>;
- addr_space_type["writev_i8"] = &addr_space::log_mem_write<s8>;
- addr_space_type["writev_u8"] = &addr_space::log_mem_write<u8>;
- addr_space_type["writev_i16"] = &addr_space::log_mem_write<s16>;
- addr_space_type["writev_u16"] = &addr_space::log_mem_write<u16>;
- addr_space_type["writev_i32"] = &addr_space::log_mem_write<s32>;
- addr_space_type["writev_u32"] = &addr_space::log_mem_write<u32>;
- addr_space_type["writev_i64"] = &addr_space::log_mem_write<s64>;
- addr_space_type["writev_u64"] = &addr_space::log_mem_write<u64>;
- addr_space_type["read_direct_i8"] = &addr_space::direct_mem_read<s8>;
- addr_space_type["read_direct_u8"] = &addr_space::direct_mem_read<u8>;
- addr_space_type["read_direct_i16"] = &addr_space::direct_mem_read<s16>;
- addr_space_type["read_direct_u16"] = &addr_space::direct_mem_read<u16>;
- addr_space_type["read_direct_i32"] = &addr_space::direct_mem_read<s32>;
- addr_space_type["read_direct_u32"] = &addr_space::direct_mem_read<u32>;
- addr_space_type["read_direct_i64"] = &addr_space::direct_mem_read<s64>;
- addr_space_type["read_direct_u64"] = &addr_space::direct_mem_read<u64>;
- addr_space_type["write_direct_i8"] = &addr_space::direct_mem_write<s8>;
- addr_space_type["write_direct_u8"] = &addr_space::direct_mem_write<u8>;
- addr_space_type["write_direct_i16"] = &addr_space::direct_mem_write<s16>;
- addr_space_type["write_direct_u16"] = &addr_space::direct_mem_write<u16>;
- addr_space_type["write_direct_i32"] = &addr_space::direct_mem_write<s32>;
- addr_space_type["write_direct_u32"] = &addr_space::direct_mem_write<u32>;
- 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_type.set_function(sol::meta_function::to_string,
+ [] (addr_space const &sp)
+ {
+ device_t &d(sp.dev.device());
+ return util::string_format("%s(%s):%s", d.shortname(), d.tag(), sp.space.name());
+ });
+ addr_space_type.set_function("read_i8", &addr_space::mem_read<s8>);
+ addr_space_type.set_function("read_u8", &addr_space::mem_read<u8>);
+ addr_space_type.set_function("read_i16", &addr_space::mem_read<s16>);
+ addr_space_type.set_function("read_u16", &addr_space::mem_read<u16>);
+ addr_space_type.set_function("read_i32", &addr_space::mem_read<s32>);
+ addr_space_type.set_function("read_u32", &addr_space::mem_read<u32>);
+ addr_space_type.set_function("read_i64", &addr_space::mem_read<s64>);
+ addr_space_type.set_function("read_u64", &addr_space::mem_read<u64>);
+ addr_space_type.set_function("write_i8", &addr_space::mem_write<s8>);
+ addr_space_type.set_function("write_u8", &addr_space::mem_write<u8>);
+ addr_space_type.set_function("write_i16", &addr_space::mem_write<s16>);
+ addr_space_type.set_function("write_u16", &addr_space::mem_write<u16>);
+ addr_space_type.set_function("write_i32", &addr_space::mem_write<s32>);
+ addr_space_type.set_function("write_u32", &addr_space::mem_write<u32>);
+ addr_space_type.set_function("write_i64", &addr_space::mem_write<s64>);
+ addr_space_type.set_function("write_u64", &addr_space::mem_write<u64>);
+ addr_space_type.set_function("readv_i8", &addr_space::log_mem_read<s8>);
+ addr_space_type.set_function("readv_u8", &addr_space::log_mem_read<u8>);
+ addr_space_type.set_function("readv_i16", &addr_space::log_mem_read<s16>);
+ addr_space_type.set_function("readv_u16", &addr_space::log_mem_read<u16>);
+ addr_space_type.set_function("readv_i32", &addr_space::log_mem_read<s32>);
+ addr_space_type.set_function("readv_u32", &addr_space::log_mem_read<u32>);
+ addr_space_type.set_function("readv_i64", &addr_space::log_mem_read<s64>);
+ addr_space_type.set_function("readv_u64", &addr_space::log_mem_read<u64>);
+ addr_space_type.set_function("writev_i8", &addr_space::log_mem_write<s8>);
+ addr_space_type.set_function("writev_u8", &addr_space::log_mem_write<u8>);
+ addr_space_type.set_function("writev_i16", &addr_space::log_mem_write<s16>);
+ addr_space_type.set_function("writev_u16", &addr_space::log_mem_write<u16>);
+ addr_space_type.set_function("writev_i32", &addr_space::log_mem_write<s32>);
+ addr_space_type.set_function("writev_u32", &addr_space::log_mem_write<u32>);
+ addr_space_type.set_function("writev_i64", &addr_space::log_mem_write<s64>);
+ addr_space_type.set_function("writev_u64", &addr_space::log_mem_write<u64>);
+ addr_space_type.set_function("read_direct_i8", &addr_space::direct_mem_read<s8>);
+ addr_space_type.set_function("read_direct_u8", &addr_space::direct_mem_read<u8>);
+ addr_space_type.set_function("read_direct_i16", &addr_space::direct_mem_read<s16>);
+ addr_space_type.set_function("read_direct_u16", &addr_space::direct_mem_read<u16>);
+ addr_space_type.set_function("read_direct_i32", &addr_space::direct_mem_read<s32>);
+ addr_space_type.set_function("read_direct_u32", &addr_space::direct_mem_read<u32>);
+ addr_space_type.set_function("read_direct_i64", &addr_space::direct_mem_read<s64>);
+ addr_space_type.set_function("read_direct_u64", &addr_space::direct_mem_read<u64>);
+ addr_space_type.set_function("write_direct_i8", &addr_space::direct_mem_write<s8>);
+ addr_space_type.set_function("write_direct_u8", &addr_space::direct_mem_write<u8>);
+ addr_space_type.set_function("write_direct_i16", &addr_space::direct_mem_write<s16>);
+ addr_space_type.set_function("write_direct_u16", &addr_space::direct_mem_write<u16>);
+ addr_space_type.set_function("write_direct_i32", &addr_space::direct_mem_write<s32>);
+ addr_space_type.set_function("write_direct_u32", &addr_space::direct_mem_write<u32>);
+ addr_space_type.set_function("write_direct_i64", &addr_space::direct_mem_write<s64>);
+ addr_space_type.set_function("write_direct_u64", &addr_space::direct_mem_write<u64>);
+ addr_space_type.set_function("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)
+ if ((step < 1) || (step > last - first))
{
- luaL_error(L, "Invalid step");
+ luaL_error(s, "Invalid step");
return sol::lua_nil;
}
}
- if (first > space_size || last > space_size || last < first)
+
+ offs_t space_size = sp.space.addrmask();
+ if ((first > space_size) || (last > space_size) || (last < first))
{
- luaL_error(L, "Invalid offset");
+ luaL_error(s, "Invalid offset");
return sol::lua_nil;
}
+
+ luaL_Buffer buff;
int byte_count = width / 8 * (last - first + 1) / step;
switch (width)
{
case 8:
{
- u8 *dest = (u8 *)luaL_buffinitsize(L, &buff, byte_count);
+ u8 *dest = (u8 *)luaL_buffinitsize(s, &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);
+ u16 *dest = (u16 *)luaL_buffinitsize(s, &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);
+ u32 *dest = (u32 *)luaL_buffinitsize(s, &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);
+ u64 *dest = (u64 *)luaL_buffinitsize(s, &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");
+ luaL_error(s, "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)
+ return sol::make_reference(s, sol::stack_reference(s, -1));
+ });
+ addr_space_type.set_function("add_change_notifier",
+ [] (addr_space &sp, sol::protected_function &&cb)
{
return sp.space.add_change_notifier(
- [this, callback = std::move(cb)] (read_or_write mode)
+ [callback = std::move(cb)] (read_or_write mode)
{
char const *modestr = "";
switch (mode)
@@ -653,17 +657,17 @@ void lua_engine::initialize_memory(sol::table &emu)
}
invoke(callback, modestr);
});
- };
- addr_space_type["install_read_tap"] =
- [this] (addr_space &sp, offs_t start, offs_t end, std::string &&name, sol::protected_function &&cb)
+ });
+ addr_space_type.set_function("install_read_tap",
+ [] (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>(sp.space, read_or_write::READ, start, end, std::move(name), std::move(cb));
+ });
+ addr_space_type.set_function("install_write_tap",
+ [] (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));
- };
+ return std::make_unique<tap_helper>(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(); });
@@ -674,8 +678,8 @@ void lua_engine::initialize_memory(sol::table &emu)
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.set_function("reinstall", &tap_helper::reinstall);
+ tap_type.set_function("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);
@@ -722,22 +726,22 @@ void lua_engine::initialize_memory(sol::table &emu)
auto region_type = sol().registry().new_usertype<memory_region>("region", sol::no_constructor);
- region_type["read_i8"] = &region_read<s8>;
- region_type["read_u8"] = &region_read<u8>;
- region_type["read_i16"] = &region_read<s16>;
- region_type["read_u16"] = &region_read<u16>;
- region_type["read_i32"] = &region_read<s32>;
- region_type["read_u32"] = &region_read<u32>;
- region_type["read_i64"] = &region_read<s64>;
- region_type["read_u64"] = &region_read<u64>;
- region_type["write_i8"] = &region_write<s8>;
- region_type["write_u8"] = &region_write<u8>;
- region_type["write_i16"] = &region_write<s16>;
- region_type["write_u16"] = &region_write<u16>;
- region_type["write_i32"] = &region_write<s32>;
- region_type["write_u32"] = &region_write<u32>;
- region_type["write_i64"] = &region_write<s64>;
- region_type["write_u64"] = &region_write<u64>;
+ region_type.set_function("read_i8", &region_read<s8>);
+ region_type.set_function("read_u8", &region_read<u8>);
+ region_type.set_function("read_i16", &region_read<s16>);
+ region_type.set_function("read_u16", &region_read<u16>);
+ region_type.set_function("read_i32", &region_read<s32>);
+ region_type.set_function("read_u32", &region_read<u32>);
+ region_type.set_function("read_i64", &region_read<s64>);
+ region_type.set_function("read_u64", &region_read<u64>);
+ region_type.set_function("write_i8", &region_write<s8>);
+ region_type.set_function("write_u8", &region_write<u8>);
+ region_type.set_function("write_i16", &region_write<s16>);
+ region_type.set_function("write_u16", &region_write<u16>);
+ region_type.set_function("write_i32", &region_write<s32>);
+ region_type.set_function("write_u32", &region_write<u32>);
+ region_type.set_function("write_i64", &region_write<s64>);
+ region_type.set_function("write_u64", &region_write<u64>);
region_type["tag"] = sol::property(&memory_region::name);
region_type["size"] = sol::property(&memory_region::bytes);
region_type["length"] = sol::property([] (memory_region &r) { return r.bytes() / r.bytewidth(); });
@@ -747,22 +751,22 @@ void lua_engine::initialize_memory(sol::table &emu)
auto share_type = sol().registry().new_usertype<memory_share>("share", sol::no_constructor);
- share_type["read_i8"] = &share_read<s8>;
- share_type["read_u8"] = &share_read<u8>;
- share_type["read_i16"] = &share_read<s16>;
- share_type["read_u16"] = &share_read<u16>;
- share_type["read_i32"] = &share_read<s32>;
- share_type["read_u32"] = &share_read<u32>;
- share_type["read_i64"] = &share_read<s64>;
- share_type["read_u64"] = &share_read<u64>;
- share_type["write_i8"] = &share_write<s8>;
- share_type["write_u8"] = &share_write<u8>;
- share_type["write_i16"] = &share_write<s16>;
- share_type["write_u16"] = &share_write<u16>;
- share_type["write_i32"] = &share_write<s32>;
- share_type["write_u32"] = &share_write<u32>;
- share_type["write_i64"] = &share_write<s64>;
- share_type["write_u64"] = &share_write<u64>;
+ share_type.set_function("read_i8", &share_read<s8>);
+ share_type.set_function("read_u8", &share_read<u8>);
+ share_type.set_function("read_i16", &share_read<s16>);
+ share_type.set_function("read_u16", &share_read<u16>);
+ share_type.set_function("read_i32", &share_read<s32>);
+ share_type.set_function("read_u32", &share_read<u32>);
+ share_type.set_function("read_i64", &share_read<s64>);
+ share_type.set_function("read_u64", &share_read<u64>);
+ share_type.set_function("write_i8", &share_write<s8>);
+ share_type.set_function("write_u8", &share_write<u8>);
+ share_type.set_function("write_i16", &share_write<s16>);
+ share_type.set_function("write_u16", &share_write<u16>);
+ share_type.set_function("write_i32", &share_write<s32>);
+ share_type.set_function("write_u32", &share_write<u32>);
+ share_type.set_function("write_i64", &share_write<s64>);
+ share_type.set_function("write_u64", &share_write<u64>);
share_type["tag"] = sol::property(&memory_share::name);
share_type["size"] = sol::property(&memory_share::bytes);
share_type["length"] = sol::property([] (memory_share &s) { return s.bytes() / s.bytewidth(); });
diff --git a/src/frontend/mame/mame.cpp b/src/frontend/mame/mame.cpp
index 486f3a8db66..75e487f8753 100644
--- a/src/frontend/mame/mame.cpp
+++ b/src/frontend/mame/mame.cpp
@@ -203,8 +203,29 @@ void mame_machine_manager::start_luaengine()
if (!filerr)
{
std::string exppath;
- osd_subst_env(exppath, std::string(file.fullpath()));
- m_lua->load_script(exppath.c_str());
+ osd_subst_env(exppath, file.fullpath());
+ auto &l(*lua());
+ auto load_result = l.load_script(exppath);
+ if (!load_result.valid())
+ {
+ sol::error err = load_result;
+ sol::load_status status = load_result.status();
+ fatalerror("Error plugin bootstrap script %s: %s error\n%s\n",
+ exppath,
+ sol::to_string(status),
+ err.what());
+ }
+ sol::protected_function func = load_result;
+ sol::protected_function_result call_result = l.invoke(func);
+ if (!call_result.valid())
+ {
+ sol::error err = call_result;
+ sol::call_status status = call_result.status();
+ fatalerror("Error running plugin bootstrap script %s: %s error\n%s\n",
+ options().autoboot_script(),
+ sol::to_string(status),
+ err.what());
+ }
}
}
}
@@ -295,21 +316,35 @@ int mame_machine_manager::execute()
TIMER_CALLBACK_MEMBER(mame_machine_manager::autoboot_callback)
{
- if (strlen(options().autoboot_script())!=0) {
- mame_machine_manager::instance()->lua()->load_script(options().autoboot_script());
+ if (*options().autoboot_script())
+ {
+ assert(m_autoboot_script);
+ sol::protected_function func = *m_autoboot_script;
+ sol::protected_function_result result = lua()->invoke(func);
+ if (!result.valid())
+ {
+ sol::error err = result;
+ sol::call_status status = result.status();
+ fatalerror("Error running autoboot script %s: %s error\n%s\n",
+ options().autoboot_script(),
+ sol::to_string(status),
+ err.what());
+ }
}
- else if (strlen(options().autoboot_command())!=0) {
- std::string cmd = std::string(options().autoboot_command());
+ else if (*options().autoboot_command())
+ {
+ std::string cmd(options().autoboot_command());
strreplace(cmd, "'", "\\'");
std::string val = std::string("emu.keypost('").append(cmd).append("')");
- mame_machine_manager::instance()->lua()->load_string(val.c_str());
+ auto &l(*lua());
+ l.invoke(l.load_string(val));
}
}
void mame_machine_manager::reset()
{
// setup autoboot if needed
- m_autoboot_timer->adjust(attotime(options().autoboot_delay(),0),0);
+ m_autoboot_timer->adjust(attotime(options().autoboot_delay(), 0), 0);
}
ui_manager* mame_machine_manager::create_ui(running_machine& machine)
@@ -337,7 +372,7 @@ void mame_machine_manager::before_load_settings(running_machine& machine)
m_lua->on_machine_before_load_settings();
}
-void mame_machine_manager::create_custom(running_machine& machine)
+void mame_machine_manager::create_custom(running_machine &machine)
{
// start the inifile manager
m_inifile = std::make_unique<inifile_manager>(m_ui->options());
@@ -347,6 +382,25 @@ void mame_machine_manager::create_custom(running_machine& machine)
// start favorite manager
m_favorite = std::make_unique<favorite_manager>(m_ui->options());
+
+ // attempt to load the autoboot script if configured
+ m_autoboot_script.reset();
+ if (*options().autoboot_script())
+ {
+ auto result = lua()->load_script(options().autoboot_script());
+ if (!result.valid())
+ {
+ sol::error err = result;
+ sol::load_status status = result.status();
+ fatalerror("Error loading autoboot script %s: %s error\n%s\n",
+ options().autoboot_script(),
+ sol::to_string(status),
+ err.what());
+ }
+ m_autoboot_script.reset(new sol::load_result(std::move(result)));
+ sol::protected_function func = *m_autoboot_script;
+ sol::set_environment(lua()->make_environment(), func);
+ }
}
void mame_machine_manager::load_cheatfiles(running_machine& machine)
diff --git a/src/frontend/mame/mame.h b/src/frontend/mame/mame.h
index 5fb5a2f4a81..a850cf51083 100644
--- a/src/frontend/mame/mame.h
+++ b/src/frontend/mame/mame.h
@@ -12,6 +12,12 @@
#pragma once
+namespace sol {
+
+struct load_result;
+
+} // namespace sol
+
class plugin_options;
class osd_interface;
@@ -71,19 +77,20 @@ private:
mame_machine_manager &operator=(mame_machine_manager const &) = delete;
mame_machine_manager &operator=(mame_machine_manager &&) = delete;
- std::unique_ptr<plugin_options> m_plugins; // pointer to plugin options
- std::unique_ptr<lua_engine> m_lua;
+ std::unique_ptr<plugin_options> m_plugins; // pointer to plugin options
+ std::unique_ptr<lua_engine> m_lua;
- const game_driver * m_new_driver_pending; // pointer to the next pending driver
+ const game_driver * m_new_driver_pending; // pointer to the next pending driver
bool m_firstrun;
- static mame_machine_manager *s_manager;
- emu_timer *m_autoboot_timer; // autoboot timer
- std::unique_ptr<mame_ui_manager> m_ui; // internal data from ui.cpp
- std::unique_ptr<cheat_manager> m_cheat; // internal data from cheat.cpp
- std::unique_ptr<inifile_manager> m_inifile; // internal data from inifile.c for INIs
- std::unique_ptr<favorite_manager> m_favorite; // internal data from inifile.c for favorites
+ emu_timer * m_autoboot_timer; // auto-boot timer
+ std::unique_ptr<sol::load_result> m_autoboot_script; // auto-boot script
+ std::unique_ptr<mame_ui_manager> m_ui; // internal data from ui.cpp
+ std::unique_ptr<cheat_manager> m_cheat; // internal data from cheat.cpp
+ std::unique_ptr<inifile_manager> m_inifile; // internal data from inifile.c for INIs
+ std::unique_ptr<favorite_manager> m_favorite; // internal data from inifile.c for favorites
+ static mame_machine_manager *s_manager;
};
//**************************************************************************