diff options
-rw-r--r-- | plugins/autofire/autofire_menu.lua | 4 | ||||
-rw-r--r-- | plugins/cheatfind/init.lua | 10 | ||||
-rw-r--r-- | plugins/inputmacro/inputmacro_menu.lua | 24 | ||||
-rw-r--r-- | plugins/timer/init.lua | 2 | ||||
-rw-r--r-- | src/frontend/mame/luaengine.cpp | 275 | ||||
-rw-r--r-- | src/frontend/mame/luaengine.h | 33 | ||||
-rw-r--r-- | src/frontend/mame/luaengine.ipp | 60 | ||||
-rw-r--r-- | src/frontend/mame/luaengine_debug.cpp | 20 | ||||
-rw-r--r-- | src/frontend/mame/luaengine_mem.cpp | 232 | ||||
-rw-r--r-- | src/frontend/mame/mame.cpp | 72 | ||||
-rw-r--r-- | src/frontend/mame/mame.h | 25 |
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 ↦ +}; + + 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 ↦ -}; - - 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"] = ®ion_read<s8>; - region_type["read_u8"] = ®ion_read<u8>; - region_type["read_i16"] = ®ion_read<s16>; - region_type["read_u16"] = ®ion_read<u16>; - region_type["read_i32"] = ®ion_read<s32>; - region_type["read_u32"] = ®ion_read<u32>; - region_type["read_i64"] = ®ion_read<s64>; - region_type["read_u64"] = ®ion_read<u64>; - region_type["write_i8"] = ®ion_write<s8>; - region_type["write_u8"] = ®ion_write<u8>; - region_type["write_i16"] = ®ion_write<s16>; - region_type["write_u16"] = ®ion_write<u16>; - region_type["write_i32"] = ®ion_write<s32>; - region_type["write_u32"] = ®ion_write<u32>; - region_type["write_i64"] = ®ion_write<s64>; - region_type["write_u64"] = ®ion_write<u64>; + region_type.set_function("read_i8", ®ion_read<s8>); + region_type.set_function("read_u8", ®ion_read<u8>); + region_type.set_function("read_i16", ®ion_read<s16>); + region_type.set_function("read_u16", ®ion_read<u16>); + region_type.set_function("read_i32", ®ion_read<s32>); + region_type.set_function("read_u32", ®ion_read<u32>); + region_type.set_function("read_i64", ®ion_read<s64>); + region_type.set_function("read_u64", ®ion_read<u64>); + region_type.set_function("write_i8", ®ion_write<s8>); + region_type.set_function("write_u8", ®ion_write<u8>); + region_type.set_function("write_i16", ®ion_write<s16>); + region_type.set_function("write_u16", ®ion_write<u16>); + region_type.set_function("write_i32", ®ion_write<s32>); + region_type.set_function("write_u32", ®ion_write<u32>); + region_type.set_function("write_i64", ®ion_write<s64>); + region_type.set_function("write_u64", ®ion_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; }; //************************************************************************** |