summaryrefslogtreecommitdiffstats
path: root/src/frontend/mame/luaengine.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/frontend/mame/luaengine.cpp')
-rw-r--r--src/frontend/mame/luaengine.cpp275
1 files changed, 143 insertions, 132 deletions
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());
}