summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author feos <feos-theos@yandex.ru>2019-10-19 11:37:01 +0300
committer feos <feos-theos@yandex.ru>2019-10-19 11:37:01 +0300
commitd51d2a71d58ea17238ad65612040f68fb407c3c1 (patch)
treeb5433dfe632e7ca6e79443a71d404ed95ad849d7
parentbfbe918626cd69d4cf4982415a9e5b546aaf194d (diff)
luaengine: reduce memory usage during compilation
Previous semantics were encouraged by sol2, and ThePhD admitted it was a bad idea for usertypes with lots of members. sol3 allows to assign members outside a constructor for regular usertypes, but mame can't move to sol3 because it requires C++17. Turns out sol2 also has a way to add members separately, and that is what I used. This helps immensely. This approach required a fix to warning C5046 copied from here https://github.com/ThePhD/sol2/commit/57990845726e17fba11a39cfcb1fc0127a7ea638 Tested current mame plugins, everything seems to work. PS: Due to come black magic, if I use simple_usertype::set() with "manager" as well, "machine" member dies (others are fine!), so I had to leave it intact.
-rw-r--r--3rdparty/sol2/sol/traits.hpp2
-rw-r--r--src/frontend/mame/luaengine.cpp2203
2 files changed, 1123 insertions, 1082 deletions
diff --git a/3rdparty/sol2/sol/traits.hpp b/3rdparty/sol2/sol/traits.hpp
index 1ed95a1656e..762bc84b947 100644
--- a/3rdparty/sol2/sol/traits.hpp
+++ b/3rdparty/sol2/sol/traits.hpp
@@ -252,7 +252,7 @@ namespace sol {
using yes = char;
using no = struct { char s[2]; };
- struct F { void operator()(); };
+ struct F { void operator()() {}; };
struct Derived : T, F {};
template<typename U, U> struct Check;
diff --git a/src/frontend/mame/luaengine.cpp b/src/frontend/mame/luaengine.cpp
index 4c5f9d0f42d..2be6737e124 100644
--- a/src/frontend/mame/luaengine.cpp
+++ b/src/frontend/mame/luaengine.cpp
@@ -889,7 +889,8 @@ void lua_engine::initialize()
* file:fullpath() -
*/
- emu.new_usertype<emu_file>("file", sol::call_constructor, sol::initializers([](emu_file &file, u32 flags) { new (&file) emu_file(flags); },
+ auto file_type = emu.create_simple_usertype<emu_file>(sol::call_constructor, sol::initializers(
+ [](emu_file &file, u32 flags) { new (&file) emu_file(flags); },
[](emu_file &file, const char *path, u32 flags) { new (&file) emu_file(path, flags); },
[](emu_file &file, const char *mode) {
int flags = 0;
@@ -928,55 +929,57 @@ void lua_engine::initialize()
}
}
new (&file) emu_file(path, flags);
- }),
- "read", [](emu_file &file, sol::buffer *buff) { buff->set_len(file.read(buff->get_ptr(), buff->get_len())); return buff; },
- "write", [](emu_file &file, const std::string &data) { return file.write(data.data(), data.size()); },
- "open", static_cast<osd_file::error (emu_file::*)(const std::string &)>(&emu_file::open),
- "open_next", &emu_file::open_next,
- "seek", sol::overload([](emu_file &file) { return file.tell(); },
- [this](emu_file &file, s64 offset, int whence) -> sol::object {
- if(file.seek(offset, whence))
- return sol::make_object(sol(), sol::nil);
- else
- return sol::make_object(sol(), file.tell());
- },
- [this](emu_file &file, const char* whence) -> sol::object {
- int wval = -1;
- const char *seekdirs[] = {"set", "cur", "end"};
- for(int i = 0; i < 3; i++)
+ }));
+ file_type.set("read", [](emu_file &file, sol::buffer *buff) { buff->set_len(file.read(buff->get_ptr(), buff->get_len())); return buff; });
+ file_type.set("write", [](emu_file &file, const std::string &data) { return file.write(data.data(), data.size()); });
+ file_type.set("open", static_cast<osd_file::error (emu_file::*)(const std::string &)>(&emu_file::open));
+ file_type.set("open_next", &emu_file::open_next);
+ file_type.set("seek", sol::overload(
+ [](emu_file &file) { return file.tell(); },
+ [this](emu_file &file, s64 offset, int whence) -> sol::object {
+ if(file.seek(offset, whence))
+ return sol::make_object(sol(), sol::nil);
+ else
+ return sol::make_object(sol(), file.tell());
+ },
+ [this](emu_file &file, const char* whence) -> sol::object {
+ int wval = -1;
+ const char *seekdirs[] = {"set", "cur", "end"};
+ for(int i = 0; i < 3; i++)
+ {
+ if(!strncmp(whence, seekdirs[i], 3))
{
- if(!strncmp(whence, seekdirs[i], 3))
- {
- wval = i;
- break;
- }
+ wval = i;
+ break;
}
- if(wval < 0 || wval >= 3)
- return sol::make_object(sol(), sol::nil);
- if(file.seek(0, wval))
- return sol::make_object(sol(), sol::nil);
- return sol::make_object(sol(), file.tell());
- },
- [this](emu_file &file, const char* whence, s64 offset) -> sol::object {
- int wval = -1;
- const char *seekdirs[] = {"set", "cur", "end"};
- for(int i = 0; i < 3; i++)
+ }
+ if(wval < 0 || wval >= 3)
+ return sol::make_object(sol(), sol::nil);
+ if(file.seek(0, wval))
+ return sol::make_object(sol(), sol::nil);
+ return sol::make_object(sol(), file.tell());
+ },
+ [this](emu_file &file, const char* whence, s64 offset) -> sol::object {
+ int wval = -1;
+ const char *seekdirs[] = {"set", "cur", "end"};
+ for(int i = 0; i < 3; i++)
+ {
+ if(!strncmp(whence, seekdirs[i], 3))
{
- if(!strncmp(whence, seekdirs[i], 3))
- {
- wval = i;
- break;
- }
+ wval = i;
+ break;
}
- if(wval < 0 || wval >= 3)
- return sol::make_object(sol(), sol::nil);
- if(file.seek(offset, wval))
- return sol::make_object(sol(), sol::nil);
- return sol::make_object(sol(), file.tell());
- }),
- "size", &emu_file::size,
- "filename", &emu_file::filename,
- "fullpath", &emu_file::fullpath);
+ }
+ if(wval < 0 || wval >= 3)
+ return sol::make_object(sol(), sol::nil);
+ if(file.seek(offset, wval))
+ return sol::make_object(sol(), sol::nil);
+ return sol::make_object(sol(), file.tell());
+ }));
+ file_type.set("size", &emu_file::size);
+ file_type.set("filename", &emu_file::filename);
+ file_type.set("fullpath", &emu_file::fullpath);
+ emu.set_usertype("file", file_type);
/* thread library
@@ -993,59 +996,60 @@ void lua_engine::initialize()
* thread.yield - check if thread is yielded
*/
- emu.new_usertype<context>("thread", sol::call_constructor, sol::constructors<sol::types<>>(),
- "start", [](context &ctx, const char *scr) {
- std::string script(scr);
- if(ctx.busy)
- return false;
- std::thread th([&ctx, script]() {
- sol::state thstate;
- thstate.open_libraries();
- thstate["package"]["preload"]["zlib"] = &luaopen_zlib;
- thstate["package"]["preload"]["lfs"] = &luaopen_lfs;
- thstate["package"]["preload"]["linenoise"] = &luaopen_linenoise;
- sol::load_result res = thstate.load(script);
- if(res.valid())
- {
- sol::protected_function func = res.get<sol::protected_function>();
- thstate["yield"] = [&ctx, &thstate]() {
- std::mutex m;
- std::unique_lock<std::mutex> lock(m);
- ctx.result = thstate["status"];
- ctx.yield = true;
- ctx.sync.wait(lock);
- ctx.yield = false;
- thstate["status"] = ctx.result;
- };
- auto ret = func();
- if (ret.valid()) {
- const char *tmp = ret.get<const char *>();
- if (tmp != nullptr)
- ctx.result = tmp;
- else
- exit(0);
- }
- }
- ctx.busy = false;
- });
- ctx.busy = true;
- ctx.yield = false;
- th.detach();
- return true;
- },
- "continue", [](context &ctx, const char *val) {
- if(!ctx.yield)
- return;
- ctx.result = val;
- ctx.sync.notify_all();
- },
- "result", sol::property([](context &ctx) -> std::string {
- if(ctx.busy && !ctx.yield)
- return "";
- return ctx.result;
- }),
- "busy", sol::readonly(&context::busy),
- "yield", sol::readonly(&context::yield));
+ auto thread_type = emu.create_simple_usertype<context>(sol::call_constructor, sol::constructors<sol::types<>>());
+ thread_type.set("start", [](context &ctx, const char *scr) {
+ std::string script(scr);
+ if(ctx.busy)
+ return false;
+ std::thread th([&ctx, script]() {
+ sol::state thstate;
+ thstate.open_libraries();
+ thstate["package"]["preload"]["zlib"] = &luaopen_zlib;
+ thstate["package"]["preload"]["lfs"] = &luaopen_lfs;
+ thstate["package"]["preload"]["linenoise"] = &luaopen_linenoise;
+ sol::load_result res = thstate.load(script);
+ if(res.valid())
+ {
+ sol::protected_function func = res.get<sol::protected_function>();
+ thstate["yield"] = [&ctx, &thstate]() {
+ std::mutex m;
+ std::unique_lock<std::mutex> lock(m);
+ ctx.result = thstate["status"];
+ ctx.yield = true;
+ ctx.sync.wait(lock);
+ ctx.yield = false;
+ thstate["status"] = ctx.result;
+ };
+ auto ret = func();
+ if (ret.valid()) {
+ const char *tmp = ret.get<const char *>();
+ if (tmp != nullptr)
+ ctx.result = tmp;
+ else
+ exit(0);
+ }
+ }
+ ctx.busy = false;
+ });
+ ctx.busy = true;
+ ctx.yield = false;
+ th.detach();
+ return true;
+ });
+ thread_type.set("continue", [](context &ctx, const char *val) {
+ if(!ctx.yield)
+ return;
+ ctx.result = val;
+ ctx.sync.notify_all();
+ });
+ thread_type.set("result", sol::property([](context &ctx) -> std::string {
+ if(ctx.busy && !ctx.yield)
+ return "";
+ return ctx.result;
+ }));
+ thread_type.set("busy", sol::readonly(&context::busy));
+ thread_type.set("yield", sol::readonly(&context::yield));
+ emu.set_usertype("thread", thread_type);
/* save_item library
@@ -1060,65 +1064,66 @@ void lua_engine::initialize()
* item:write(offset, value) - write entry value by index
*/
- emu.new_usertype<save_item>("item", sol::call_constructor, sol::initializers([this](save_item &item, int index) {
+ auto item_type = emu.create_simple_usertype<save_item>(sol::call_constructor, sol::initializers([this](save_item &item, int index) {
if(!machine().save().indexed_item(index, item.base, item.size, item.count))
{
item.base = nullptr;
item.size = 0;
item.count= 0;
}
- }),
- "size", sol::readonly(&save_item::size),
- "count", sol::readonly(&save_item::count),
- "read", [this](save_item &item, int offset) -> sol::object {
- uint64_t ret = 0;
- if(!item.base || (offset > item.count))
- return sol::make_object(sol(), sol::nil);
- switch(item.size)
- {
- case 1:
- default:
- ret = ((uint8_t *)item.base)[offset];
- break;
- case 2:
- ret = ((uint16_t *)item.base)[offset];
- break;
- case 4:
- ret = ((uint32_t *)item.base)[offset];
- break;
- case 8:
- ret = ((uint64_t *)item.base)[offset];
- break;
- }
- return sol::make_object(sol(), ret);
- },
- "read_block", [](save_item &item, int offset, sol::buffer *buff) {
- if(!item.base || ((offset + buff->get_len()) > (item.size * item.count)))
- buff->set_len(0);
- else
- memcpy(buff->get_ptr(), (uint8_t *)item.base + offset, buff->get_len());
- return buff;
- },
- "write", [](save_item &item, int offset, uint64_t value) {
- if(!item.base || (offset > item.count))
- return;
- switch(item.size)
- {
- case 1:
- default:
- ((uint8_t *)item.base)[offset] = (uint8_t)value;
- break;
- case 2:
- ((uint16_t *)item.base)[offset] = (uint16_t)value;
- break;
- case 4:
- ((uint32_t *)item.base)[offset] = (uint32_t)value;
- break;
- case 8:
- ((uint64_t *)item.base)[offset] = (uint64_t)value;
- break;
- }
- });
+ }));
+ 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 {
+ uint64_t ret = 0;
+ if(!item.base || (offset > item.count))
+ return sol::make_object(sol(), sol::nil);
+ switch(item.size)
+ {
+ case 1:
+ default:
+ ret = ((uint8_t *)item.base)[offset];
+ break;
+ case 2:
+ ret = ((uint16_t *)item.base)[offset];
+ break;
+ case 4:
+ ret = ((uint32_t *)item.base)[offset];
+ break;
+ case 8:
+ ret = ((uint64_t *)item.base)[offset];
+ break;
+ }
+ return sol::make_object(sol(), ret);
+ });
+ item_type.set("read_block", [](save_item &item, int offset, sol::buffer *buff) {
+ if(!item.base || ((offset + buff->get_len()) > (item.size * item.count)))
+ buff->set_len(0);
+ else
+ memcpy(buff->get_ptr(), (uint8_t *)item.base + offset, buff->get_len());
+ return buff;
+ });
+ item_type.set("write", [](save_item &item, int offset, uint64_t value) {
+ if(!item.base || (offset > item.count))
+ return;
+ switch(item.size)
+ {
+ case 1:
+ default:
+ ((uint8_t *)item.base)[offset] = (uint8_t)value;
+ break;
+ case 2:
+ ((uint16_t *)item.base)[offset] = (uint16_t)value;
+ break;
+ case 4:
+ ((uint32_t *)item.base)[offset] = (uint32_t)value;
+ break;
+ case 8:
+ ((uint64_t *)item.base)[offset] = (uint64_t)value;
+ break;
+ }
+ });
+ emu.set_usertype("item", item_type);
/* core_options library
@@ -1134,29 +1139,30 @@ void lua_engine::initialize()
* options.entries[] - get table of option entries (k=name, v=core_options::entry)
*/
- sol().registry().new_usertype<core_options>("core_options", "new", sol::no_constructor,
- "help", &core_options::output_help,
- "command", &core_options::command,
- "entries", sol::property([this](core_options &options) {
- sol::table table = sol().create_table();
- int unadorned_index = 0;
- for (auto &curentry : options.entries())
+ auto core_options_type = sol().registry().create_simple_usertype<core_options>("new", sol::no_constructor);
+ core_options_type.set("help", &core_options::output_help);
+ core_options_type.set("command", &core_options::command);
+ core_options_type.set("entries", sol::property([this](core_options &options) {
+ sol::table table = sol().create_table();
+ int unadorned_index = 0;
+ for (auto &curentry : options.entries())
+ {
+ const char *name = curentry->names().size() > 0
+ ? curentry->name().c_str()
+ : nullptr;
+ bool is_unadorned = false;
+ // check if it's unadorned
+ if (name && strlen(name) && !strcmp(name, options.unadorned(unadorned_index)))
{
- const char *name = curentry->names().size() > 0
- ? curentry->name().c_str()
- : nullptr;
- bool is_unadorned = false;
- // check if it's unadorned
- if (name && strlen(name) && !strcmp(name, options.unadorned(unadorned_index)))
- {
- unadorned_index++;
- is_unadorned = true;
- }
- if (curentry->type() != core_options::option_type::HEADER && curentry->type() != core_options::option_type::COMMAND && !is_unadorned)
- table[name] = &*curentry;
+ unadorned_index++;
+ is_unadorned = true;
}
- return table;
- }));
+ if (curentry->type() != core_options::option_type::HEADER && curentry->type() != core_options::option_type::COMMAND && !is_unadorned)
+ table[name] = &*curentry;
+ }
+ return table;
+ }));
+ sol().registry().set_usertype("core_options", core_options_type);
/* core_options::entry library
@@ -1172,51 +1178,53 @@ void lua_engine::initialize()
* entry:has_range() - are min and max valid for entry
*/
- sol().registry().new_usertype<core_options::entry>("core_options_entry", "new", sol::no_constructor,
- "value", sol::overload([this](core_options::entry &e, bool val) {
- if(e.type() != OPTION_BOOLEAN)
- luaL_error(m_lua_state, "Cannot set option to wrong type");
- else
- e.set_value(val ? "1" : "0", OPTION_PRIORITY_CMDLINE);
- },
- [this](core_options::entry &e, float val) {
- if(e.type() != OPTION_FLOAT)
- luaL_error(m_lua_state, "Cannot set option to wrong type");
- else
- e.set_value(string_format("%f", val).c_str(), OPTION_PRIORITY_CMDLINE);
- },
- [this](core_options::entry &e, int val) {
- if(e.type() != OPTION_INTEGER)
- luaL_error(m_lua_state, "Cannot set option to wrong type");
- else
- e.set_value(string_format("%d", val).c_str(), OPTION_PRIORITY_CMDLINE);
- },
- [this](core_options::entry &e, const char *val) {
- if(e.type() != OPTION_STRING)
- luaL_error(m_lua_state, "Cannot set option to wrong type");
- else
- e.set_value(val, OPTION_PRIORITY_CMDLINE);
- },
- [this](core_options::entry &e) -> sol::object {
- if (e.type() == core_options::option_type::INVALID)
- return sol::make_object(sol(), sol::nil);
- switch(e.type())
- {
- case core_options::option_type::BOOLEAN:
- return sol::make_object(sol(), atoi(e.value()) != 0);
- case core_options::option_type::INTEGER:
- return sol::make_object(sol(), atoi(e.value()));
- case core_options::option_type::FLOAT:
- return sol::make_object(sol(), atof(e.value()));
- default:
- return sol::make_object(sol(), e.value());
- }
- }),
- "description", &core_options::entry::description,
- "default_value", &core_options::entry::default_value,
- "minimum", &core_options::entry::minimum,
- "maximum", &core_options::entry::maximum,
- "has_range", &core_options::entry::has_range);
+ auto core_options_entry_type = sol().registry().create_simple_usertype<core_options::entry>("new", sol::no_constructor);
+ core_options_entry_type.set("value", sol::overload(
+ [this](core_options::entry &e, bool val) {
+ if(e.type() != OPTION_BOOLEAN)
+ luaL_error(m_lua_state, "Cannot set option to wrong type");
+ else
+ e.set_value(val ? "1" : "0", OPTION_PRIORITY_CMDLINE);
+ },
+ [this](core_options::entry &e, float val) {
+ if(e.type() != OPTION_FLOAT)
+ luaL_error(m_lua_state, "Cannot set option to wrong type");
+ else
+ e.set_value(string_format("%f", val).c_str(), OPTION_PRIORITY_CMDLINE);
+ },
+ [this](core_options::entry &e, int val) {
+ if(e.type() != OPTION_INTEGER)
+ luaL_error(m_lua_state, "Cannot set option to wrong type");
+ else
+ e.set_value(string_format("%d", val).c_str(), OPTION_PRIORITY_CMDLINE);
+ },
+ [this](core_options::entry &e, const char *val) {
+ if(e.type() != OPTION_STRING)
+ luaL_error(m_lua_state, "Cannot set option to wrong type");
+ else
+ e.set_value(val, OPTION_PRIORITY_CMDLINE);
+ },
+ [this](core_options::entry &e) -> sol::object {
+ if (e.type() == core_options::option_type::INVALID)
+ return sol::make_object(sol(), sol::nil);
+ switch(e.type())
+ {
+ case core_options::option_type::BOOLEAN:
+ return sol::make_object(sol(), atoi(e.value()) != 0);
+ case core_options::option_type::INTEGER:
+ return sol::make_object(sol(), atoi(e.value()));
+ case core_options::option_type::FLOAT:
+ return sol::make_object(sol(), atof(e.value()));
+ default:
+ return sol::make_object(sol(), e.value());
+ }
+ }));
+ core_options_entry_type.set("description", &core_options::entry::description);
+ core_options_entry_type.set("default_value", &core_options::entry::default_value);
+ core_options_entry_type.set("minimum", &core_options::entry::minimum);
+ core_options_entry_type.set("maximum", &core_options::entry::maximum);
+ core_options_entry_type.set("has_range", &core_options::entry::has_range);
+ sol().registry().set_usertype("core_options_entry", core_options_entry_type);
/* running_machine library
@@ -1254,69 +1262,71 @@ void lua_engine::initialize()
* machine.images[] - get available image devices table (k=type, v=device_image_interface)
*/
- sol().registry().new_usertype<running_machine> ("machine", "new", sol::no_constructor,
- "exit", &running_machine::schedule_exit,
- "hard_reset", &running_machine::schedule_hard_reset,
- "soft_reset", &running_machine::schedule_soft_reset,
- "save", &running_machine::schedule_save,
- "load", &running_machine::schedule_load,
- "system", &running_machine::system,
- "video", &running_machine::video,
- "sound", &running_machine::sound,
- "render", &running_machine::render,
- "ioport", &running_machine::ioport,
- "parameters", &running_machine::parameters,
- "memory", &running_machine::memory,
- "options", [](running_machine &m) { return static_cast<core_options *>(&m.options()); },
- "outputs", &running_machine::output,
- "input", &running_machine::input,
- "uiinput", &running_machine::ui_input,
- "debugger", [this](running_machine &m) -> sol::object {
- if(!(m.debug_flags & DEBUG_FLAG_ENABLED))
- return sol::make_object(sol(), sol::nil);
- return sol::make_object(sol(), &m.debugger());
- },
- "paused", sol::property(&running_machine::paused),
- "samplerate", sol::property(&running_machine::sample_rate),
- "exit_pending", sol::property(&running_machine::exit_pending),
- "hard_reset_pending", sol::property(&running_machine::hard_reset_pending),
- "devices", sol::property([this](running_machine &m) {
- std::function<void(device_t &, sol::table)> tree;
- sol::table table = sol().create_table();
- tree = [&tree](device_t &root, sol::table table) {
- for(device_t &dev : root.subdevices())
- {
- if(dev.configured() && dev.started())
- {
- table[dev.tag()] = &dev;
- tree(dev, table);
- }
- }
- };
- tree(m.root_device(), table);
- return table;
- }),
- "screens", sol::property([this](running_machine &r) {
- sol::table table = sol().create_table();
- for (screen_device &sc : screen_device_iterator(r.root_device()))
- {
- if (sc.configured() && sc.started() && sc.type())
- table[sc.tag()] = &sc;
- }
- return table;
- }),
- "images", sol::property([this](running_machine &r) {
- sol::table image_table = sol().create_table();
- for(device_image_interface &image : image_interface_iterator(r.root_device()))
+ auto machine_type = sol().registry().create_simple_usertype<running_machine>("new", sol::no_constructor);
+ machine_type.set("exit", &running_machine::schedule_exit);
+ machine_type.set("hard_reset", &running_machine::schedule_hard_reset);
+ machine_type.set("soft_reset", &running_machine::schedule_soft_reset);
+ machine_type.set("save", &running_machine::schedule_save);
+ machine_type.set("load", &running_machine::schedule_load);
+ machine_type.set("system", &running_machine::system);
+ machine_type.set("video", &running_machine::video);
+ machine_type.set("sound", &running_machine::sound);
+ machine_type.set("render", &running_machine::render);
+ machine_type.set("ioport", &running_machine::ioport);
+ machine_type.set("parameters", &running_machine::parameters);
+ machine_type.set("memory", &running_machine::memory);
+ machine_type.set("options", [](running_machine &m) { return static_cast<core_options *>(&m.options()); });
+ machine_type.set("outputs", &running_machine::output);
+ machine_type.set("input", &running_machine::input);
+ machine_type.set("uiinput", &running_machine::ui_input);
+ machine_type.set("debugger", [this](running_machine &m) -> sol::object {
+ if(!(m.debug_flags & DEBUG_FLAG_ENABLED))
+ return sol::make_object(sol(), sol::nil);
+ return sol::make_object(sol(), &m.debugger());
+ });
+ machine_type.set("paused", sol::property(&running_machine::paused));
+ machine_type.set("samplerate", sol::property(&running_machine::sample_rate));
+ machine_type.set("exit_pending", sol::property(&running_machine::exit_pending));
+ machine_type.set("hard_reset_pending", sol::property(&running_machine::hard_reset_pending));
+ machine_type.set("devices", sol::property([this](running_machine &m) {
+ std::function<void(device_t &, sol::table)> tree;
+ sol::table table = sol().create_table();
+ tree = [&tree](device_t &root, sol::table table) {
+ for(device_t &dev : root.subdevices())
+ {
+ if(dev.configured() && dev.started())
{
- image_table[image.brief_instance_name()] = &image;
- image_table[image.instance_name()] = &image;
+ table[dev.tag()] = &dev;
+ tree(dev, table);
}
- return image_table;
- }),
- "popmessage", sol::overload([](running_machine &m, const char *str) { m.popmessage("%s", str); },
- [](running_machine &m) { m.popmessage(); }),
- "logerror", [](running_machine &m, const char *str) { m.logerror("[luaengine] %s\n", str); } );
+ }
+ };
+ tree(m.root_device(), table);
+ return table;
+ }));
+ machine_type.set("screens", sol::property([this](running_machine &r) {
+ sol::table table = sol().create_table();
+ for (screen_device &sc : screen_device_iterator(r.root_device()))
+ {
+ if (sc.configured() && sc.started() && sc.type())
+ table[sc.tag()] = &sc;
+ }
+ return table;
+ }));
+ machine_type.set("images", sol::property([this](running_machine &r) {
+ sol::table image_table = sol().create_table();
+ for(device_image_interface &image : image_interface_iterator(r.root_device()))
+ {
+ image_table[image.brief_instance_name()] = &image;
+ image_table[image.instance_name()] = &image;
+ }
+ return image_table;
+ }));
+ machine_type.set("popmessage", sol::overload(
+ [](running_machine &m, const char *str) { m.popmessage("%s", str); },
+ [](running_machine &m) { m.popmessage(); }));
+ machine_type.set("logerror", [](running_machine &m, const char *str) { m.logerror("[luaengine] %s\n", str); } );
+ sol().registry().set_usertype("machine", machine_type);
/* game_driver library
@@ -1345,67 +1355,67 @@ void lua_engine::initialize()
* driver.is_incomplete - official system with blatantly incomplete hardware/software
*/
- sol().registry().new_usertype<game_driver>("game_driver", "new", sol::no_constructor,
- "source_file", sol::property([] (game_driver const &driver) { return &driver.type.source()[0]; }),
- "parent", sol::readonly(&game_driver::parent),
- "name", sol::property([] (game_driver const &driver) { return &driver.name[0]; }),
- "description", sol::property([] (game_driver const &driver) { return &driver.type.fullname()[0]; }),
- "year", sol::readonly(&game_driver::year),
- "manufacturer", sol::readonly(&game_driver::manufacturer),
- "compatible_with", sol::readonly(&game_driver::compatible_with),
- "default_layout", sol::readonly(&game_driver::default_layout),
- "orientation", sol::property([](game_driver const &driver) {
- std::string rot;
- switch (driver.flags & machine_flags::MASK_ORIENTATION)
- {
- case machine_flags::ROT0:
- rot = "rot0";
- break;
- case machine_flags::ROT90:
- rot = "rot90";
- break;
- case machine_flags::ROT180:
- rot = "rot180";
- break;
- case machine_flags::ROT270:
- rot = "rot270";
- break;
- default:
- rot = "undefined";
- break;
- }
- return rot;
- }),
- "type", sol::property([](game_driver const &driver) {
- std::string type;
- switch (driver.flags & machine_flags::MASK_TYPE)
- {
- case machine_flags::TYPE_ARCADE:
- type = "arcade";
- break;
- case machine_flags::TYPE_CONSOLE:
- type = "console";
- break;
- case machine_flags::TYPE_COMPUTER:
- type = "computer";
- break;
- default:
- type = "other";
- break;
- }
- return type;
- }),
- "not_working", sol::property([](game_driver const &driver) { return (driver.flags & machine_flags::NOT_WORKING) > 0; }),
- "supports_save", sol::property([](game_driver const &driver) { return (driver.flags & machine_flags::SUPPORTS_SAVE) > 0; }),
- "no_cocktail", sol::property([](game_driver const &driver) { return (driver.flags & machine_flags::NO_COCKTAIL) > 0; }),
- "is_bios_root", sol::property([](game_driver const &driver) { return (driver.flags & machine_flags::IS_BIOS_ROOT) > 0; }),
- "requires_artwork", sol::property([](game_driver const &driver) { return (driver.flags & machine_flags::REQUIRES_ARTWORK) > 0; }),
- "clickable_artwork", sol::property([](game_driver const &driver) { return (driver.flags & machine_flags::CLICKABLE_ARTWORK) > 0; }),
- "unofficial", sol::property([](game_driver const &driver) { return (driver.flags & machine_flags::UNOFFICIAL) > 0; }),
- "no_sound_hw", sol::property([](game_driver const &driver) { return (driver.flags & machine_flags::NO_SOUND_HW) > 0; }),
- "mechanical", sol::property([](game_driver const &driver) { return (driver.flags & machine_flags::MECHANICAL) > 0; }),
- "is_incomplete", sol::property([](game_driver const &driver) { return (driver.flags & machine_flags::IS_INCOMPLETE) > 0; }
- ));
+ auto game_driver_type = sol().registry().create_simple_usertype<game_driver>("new", sol::no_constructor);
+ game_driver_type.set("source_file", sol::property([] (game_driver const &driver) { return &driver.type.source()[0]; }));
+ game_driver_type.set("parent", sol::readonly(&game_driver::parent));
+ game_driver_type.set("name", sol::property([] (game_driver const &driver) { return &driver.name[0]; }));
+ game_driver_type.set("description", sol::property([] (game_driver const &driver) { return &driver.type.fullname()[0]; }));
+ game_driver_type.set("year", sol::readonly(&game_driver::year));
+ game_driver_type.set("manufacturer", sol::readonly(&game_driver::manufacturer));
+ game_driver_type.set("compatible_with", sol::readonly(&game_driver::compatible_with));
+ game_driver_type.set("default_layout", sol::readonly(&game_driver::default_layout));
+ game_driver_type.set("orientation", sol::property([](game_driver const &driver) {
+ std::string rot;
+ switch (driver.flags & machine_flags::MASK_ORIENTATION)
+ {
+ case machine_flags::ROT0:
+ rot = "rot0";
+ break;
+ case machine_flags::ROT90:
+ rot = "rot90";
+ break;
+ case machine_flags::ROT180:
+ rot = "rot180";
+ break;
+ case machine_flags::ROT270:
+ rot = "rot270";
+ break;
+ default:
+ rot = "undefined";
+ break;
+ }
+ return rot;
+ }));
+ game_driver_type.set("type", sol::property([](game_driver const &driver) {
+ std::string type;
+ switch (driver.flags & machine_flags::MASK_TYPE)
+ {
+ case machine_flags::TYPE_ARCADE:
+ type = "arcade";
+ break;
+ case machine_flags::TYPE_CONSOLE:
+ type = "console";
+ break;
+ case machine_flags::TYPE_COMPUTER:
+ type = "computer";
+ break;
+ default:
+ type = "other";
+ break;
+ }
+ return type;
+ }));
+ game_driver_type.set("not_working", sol::property([](game_driver const &driver) { return (driver.flags & machine_flags::NOT_WORKING) > 0; }));
+ game_driver_type.set("supports_save", sol::property([](game_driver const &driver) { return (driver.flags & machine_flags::SUPPORTS_SAVE) > 0; }));
+ game_driver_type.set("no_cocktail", sol::property([](game_driver const &driver) { return (driver.flags & machine_flags::NO_COCKTAIL) > 0; }));
+ game_driver_type.set("is_bios_root", sol::property([](game_driver const &driver) { return (driver.flags & machine_flags::IS_BIOS_ROOT) > 0; }));
+ game_driver_type.set("requires_artwork", sol::property([](game_driver const &driver) { return (driver.flags & machine_flags::REQUIRES_ARTWORK) > 0; }));
+ game_driver_type.set("clickable_artwork", sol::property([](game_driver const &driver) { return (driver.flags & machine_flags::CLICKABLE_ARTWORK) > 0; }));
+ game_driver_type.set("unofficial", sol::property([](game_driver const &driver) { return (driver.flags & machine_flags::UNOFFICIAL) > 0; }));
+ game_driver_type.set("no_sound_hw", sol::property([](game_driver const &driver) { return (driver.flags & machine_flags::NO_SOUND_HW) > 0; }));
+ game_driver_type.set("mechanical", sol::property([](game_driver const &driver) { return (driver.flags & machine_flags::MECHANICAL) > 0; }));
+ game_driver_type.set("is_incomplete", sol::property([](game_driver const &driver) { return (driver.flags & machine_flags::IS_INCOMPLETE) > 0; } ));
+ sol().registry().set_usertype("game_driver", game_driver_type);
/* debugger_manager library (requires debugger to be active)
@@ -1422,21 +1432,24 @@ void lua_engine::initialize()
struct wrap_textbuf { wrap_textbuf(text_buffer *buf) { textbuf = buf; }; text_buffer *textbuf; };
- sol().registry().new_usertype<debugger_manager>("debugger", "new", sol::no_constructor,
- "command", [](debugger_manager &debug, const std::string &cmd) { debug.console().execute_command(cmd, false); },
- "consolelog", sol::property([](debugger_manager &debug) { return wrap_textbuf(debug.console().get_console_textbuf()); }),
- "errorlog", sol::property([](debugger_manager &debug) { return wrap_textbuf(debug.console().get_errorlog_textbuf()); }),
- "visible_cpu", sol::property([](debugger_manager &debug) { debug.cpu().get_visible_cpu(); },
- [](debugger_manager &debug, device_t &dev) { debug.cpu().set_visible_cpu(&dev); }),
- "execution_state", sol::property([](debugger_manager &debug) {
- return debug.cpu().is_stopped() ? "stop" : "run";
- },
- [](debugger_manager &debug, const std::string &state) {
- if(state == "stop")
- debug.cpu().set_execution_stopped();
- else
- debug.cpu().set_execution_running();
- }));
+ auto debugger_type = sol().registry().create_simple_usertype<debugger_manager>("new", sol::no_constructor);
+ debugger_type.set("command", [](debugger_manager &debug, const std::string &cmd) { debug.console().execute_command(cmd, false); });
+ debugger_type.set("consolelog", sol::property([](debugger_manager &debug) { return wrap_textbuf(debug.console().get_console_textbuf()); }));
+ debugger_type.set("errorlog", sol::property([](debugger_manager &debug) { return wrap_textbuf(debug.console().get_errorlog_textbuf()); }));
+ debugger_type.set("visible_cpu", sol::property(
+ [](debugger_manager &debug) { debug.cpu().get_visible_cpu(); },
+ [](debugger_manager &debug, device_t &dev) { debug.cpu().set_visible_cpu(&dev); }));
+ debugger_type.set("execution_state", sol::property(
+ [](debugger_manager &debug) {
+ return debug.cpu().is_stopped() ? "stop" : "run";
+ },
+ [](debugger_manager &debug, const std::string &state) {
+ if(state == "stop")
+ debug.cpu().set_execution_stopped();
+ else
+ debug.cpu().set_execution_running();
+ }));
+ sol().registry().set_usertype("debugger", debugger_type);
/* wrap_textbuf library (requires debugger to be active)
@@ -1448,11 +1461,12 @@ void lua_engine::initialize()
* #log - entry count
*/
- sol().registry().new_usertype<wrap_textbuf>("text_buffer", "new", sol::no_constructor,
- "__metatable", [](){},
- "__newindex", [](){},
- "__index", [](wrap_textbuf &buf, int index) { return text_buffer_get_seqnum_line(buf.textbuf, index - 1); },
- "__len", [](wrap_textbuf &buf) { return text_buffer_num_lines(buf.textbuf) + text_buffer_line_index_to_seqnum(buf.textbuf, 0) - 1; });
+ auto text_buffer_type = sol().registry().create_simple_usertype<wrap_textbuf>("new", sol::no_constructor);
+ text_buffer_type.set("__metatable", [](){});
+ text_buffer_type.set("__newindex", [](){});
+ text_buffer_type.set("__index", [](wrap_textbuf &buf, int index) { return text_buffer_get_seqnum_line(buf.textbuf, index - 1); });
+ text_buffer_type.set("__len", [](wrap_textbuf &buf) { return text_buffer_num_lines(buf.textbuf) + text_buffer_line_index_to_seqnum(buf.textbuf, 0) - 1; });
+ sol().registry().set_usertype("text_buffer", text_buffer_type);
/* device_debug library (requires debugger to be active)
@@ -1472,67 +1486,68 @@ void lua_engine::initialize()
* debug:wplist(space)[] - table of watchpoints (k=index, v=watchpoint)
*/
- sol().registry().new_usertype<device_debug>("device_debug", "new", sol::no_constructor,
- "step", [](device_debug &dev, sol::object num) {
- int steps = 1;
- if(num.is<int>())
- steps = num.as<int>();
- dev.single_step(steps);
- },
- "go", &device_debug::go,
- "bpset", [](device_debug &dev, offs_t addr, const char *cond, const char *act) { return dev.breakpoint_set(addr, cond, act); },
- "bpclr", &device_debug::breakpoint_clear,
- "bplist", [this](device_debug &dev) {
- sol::table table = sol().create_table();
- for(const device_debug::breakpoint &bpt : dev.breakpoint_list())
- {
- sol::table bp = sol().create_table();
- bp["enabled"] = bpt.enabled();
- bp["address"] = bpt.address();
- bp["condition"] = bpt.condition();
- bp["action"] = bpt.action();
- table[bpt.index()] = bp;
- }
- return table;
- },
- "wpset", [](device_debug &dev, addr_space &sp, const std::string &type, offs_t addr, offs_t len, const char *cond, const char *act) {
- read_or_write wptype = read_or_write::READ;
- if(type == "w")
- wptype = read_or_write::WRITE;
- else if((type == "rw") || (type == "wr"))
- wptype = read_or_write::READWRITE;
- return dev.watchpoint_set(sp.space, wptype, addr, len, cond, act);
- },
- "wpclr", &device_debug::watchpoint_clear,
- "wplist", [this](device_debug &dev, addr_space &sp) {
- sol::table table = sol().create_table();
- for(auto &wpp : dev.watchpoint_vector(sp.space.spacenum()))
- {
- sol::table wp = sol().create_table();
- wp["enabled"] = wpp->enabled();
- wp["address"] = wpp->address();
- wp["length"] = wpp->length();
- switch(wpp->type())
- {
- case read_or_write::READ:
- wp["type"] = "r";
- break;
- case read_or_write::WRITE:
- wp["type"] = "w";
- break;
- case read_or_write::READWRITE:
- wp["type"] = "rw";
- break;
- default: // huh?
- wp["type"] = "";
- break;
- }
- wp["condition"] = wpp->condition();
- wp["action"] = wpp->action();
- table[wpp->index()] = wp;
- }
- return table;
- });
+ auto device_debug_type = sol().registry().create_simple_usertype<device_debug>("new", sol::no_constructor);
+ device_debug_type.set("step", [](device_debug &dev, sol::object num) {
+ int steps = 1;
+ if(num.is<int>())
+ steps = num.as<int>();
+ dev.single_step(steps);
+ });
+ device_debug_type.set("go", &device_debug::go);
+ device_debug_type.set("bpset", [](device_debug &dev, offs_t addr, const char *cond, const char *act) { return dev.breakpoint_set(addr, cond, act); });
+ device_debug_type.set("bpclr", &device_debug::breakpoint_clear);
+ device_debug_type.set("bplist", [this](device_debug &dev) {
+ sol::table table = sol().create_table();
+ for(const device_debug::breakpoint &bpt : dev.breakpoint_list())
+ {
+ sol::table bp = sol().create_table();
+ bp["enabled"] = bpt.enabled();
+ bp["address"] = bpt.address();
+ bp["condition"] = bpt.condition();
+ bp["action"] = bpt.action();
+ table[bpt.index()] = bp;
+ }
+ return table;
+ });
+ device_debug_type.set("wpset", [](device_debug &dev, addr_space &sp, const std::string &type, offs_t addr, offs_t len, const char *cond, const char *act) {
+ read_or_write wptype = read_or_write::READ;
+ if(type == "w")
+ wptype = read_or_write::WRITE;
+ else if((type == "rw") || (type == "wr"))
+ wptype = read_or_write::READWRITE;
+ return dev.watchpoint_set(sp.space, wptype, addr, len, cond, act);
+ });
+ device_debug_type.set("wpclr", &device_debug::watchpoint_clear);
+ device_debug_type.set("wplist", [this](device_debug &dev, addr_space &sp) {
+ sol::table table = sol().create_table();
+ for(auto &wpp : dev.watchpoint_vector(sp.space.spacenum()))
+ {
+ sol::table wp = sol().create_table();
+ wp["enabled"] = wpp->enabled();
+ wp["address"] = wpp->address();
+ wp["length"] = wpp->length();
+ switch(wpp->type())
+ {
+ case read_or_write::READ:
+ wp["type"] = "r";
+ break;
+ case read_or_write::WRITE:
+ wp["type"] = "w";
+ break;
+ case read_or_write::READWRITE:
+ wp["type"] = "rw";
+ break;
+ default: // huh?
+ wp["type"] = "";
+ break;
+ }
+ wp["condition"] = wpp->condition();
+ wp["action"] = wpp->action();
+ table[wpp->index()] = wp;
+ }
+ return table;
+ });
+ sol().registry().set_usertype("device_debug", device_debug_type);
/* device_t library
@@ -1550,59 +1565,60 @@ void lua_engine::initialize()
* device.items[] - device save state items table (k=name, v=index)
*/
- sol().registry().new_usertype<device_t>("device", "new", sol::no_constructor,
- "name", &device_t::name,
- "shortname", &device_t::shortname,
- "tag", &device_t::tag,
- "owner", &device_t::owner,
- "debug", [this](device_t &dev) -> sol::object {
- if(!(dev.machine().debug_flags & DEBUG_FLAG_ENABLED) || !dynamic_cast<cpu_device *>(&dev)) // debugger not enabled or not cpu
- return sol::make_object(sol(), sol::nil);
- return sol::make_object(sol(), dev.debug());
- },
- "spaces", sol::property([this](device_t &dev) {
- device_memory_interface *memdev = dynamic_cast<device_memory_interface *>(&dev);
- sol::table sp_table = sol().create_table();
- if(!memdev)
- return sp_table;
- for(int sp = 0; sp < memdev->max_space_count(); ++sp)
- {
- if(memdev->has_space(sp))
- sp_table[memdev->space(sp).name()] = addr_space(memdev->space(sp), *memdev);
- }
- return sp_table;
- }),
- "state", sol::property([this](device_t &dev) {
- sol::table st_table = sol().create_table();
- if(!dynamic_cast<device_state_interface *>(&dev))
- return st_table;
- // XXX: refrain from exporting non-visible entries?
- for(auto &s : dev.state().state_entries())
- st_table[s->symbol()] = s.get();
- return st_table;
- }),
- "items", sol::property([this](device_t &dev) {
- sol::table table = sol().create_table();
- std::string tag = dev.tag();
- // 10000 is enough?
- for(int i = 0; i < 10000; i++)
- {
- std::string name;
- const char *item;
- unsigned int size, count;
- void *base;
- item = dev.machine().save().indexed_item(i, base, size, count);
- if(!item)
- break;
- name = &(strchr(item, '/')[1]);
- if(name.substr(0, name.find("/")) == tag)
- {
- name = name.substr(name.find("/") + 1, std::string::npos);
- table[name] = i;
- }
- }
- return table;
- }));
+ auto device_type = sol().registry().create_simple_usertype<device_t>("new", sol::no_constructor);
+ device_type.set("name", &device_t::name);
+ device_type.set("shortname", &device_t::shortname);
+ device_type.set("tag", &device_t::tag);
+ device_type.set("owner", &device_t::owner);
+ device_type.set("debug", [this](device_t &dev) -> sol::object {
+ if(!(dev.machine().debug_flags & DEBUG_FLAG_ENABLED) || !dynamic_cast<cpu_device *>(&dev)) // debugger not enabled or not cpu
+ return sol::make_object(sol(), sol::nil);
+ return sol::make_object(sol(), dev.debug());
+ });
+ device_type.set("spaces", sol::property([this](device_t &dev) {
+ device_memory_interface *memdev = dynamic_cast<device_memory_interface *>(&dev);
+ sol::table sp_table = sol().create_table();
+ if(!memdev)
+ return sp_table;
+ for(int sp = 0; sp < memdev->max_space_count(); ++sp)
+ {
+ if(memdev->has_space(sp))
+ sp_table[memdev->space(sp).name()] = addr_space(memdev->space(sp), *memdev);
+ }
+ return sp_table;
+ }));
+ device_type.set("state", sol::property([this](device_t &dev) {
+ sol::table st_table = sol().create_table();
+ if(!dynamic_cast<device_state_interface *>(&dev))
+ return st_table;
+ // XXX: refrain from exporting non-visible entries?
+ for(auto &s : dev.state().state_entries())
+ st_table[s->symbol()] = s.get();
+ return st_table;
+ }));
+ device_type.set("items", sol::property([this](device_t &dev) {
+ sol::table table = sol().create_table();
+ std::string tag = dev.tag();
+ // 10000 is enough?
+ for(int i = 0; i < 10000; i++)
+ {
+ std::string name;
+ const char *item;
+ unsigned int size, count;
+ void *base;
+ item = dev.machine().save().indexed_item(i, base, size, count);
+ if(!item)
+ break;
+ name = &(strchr(item, '/')[1]);
+ if(name.substr(0, name.find("/")) == tag)
+ {
+ name = name.substr(name.find("/") + 1, std::string::npos);
+ table[name] = i;
+ }
+ }
+ return table;
+ }));
+ sol().registry().set_usertype("device", device_type);
/* addr_space library
@@ -1626,58 +1642,58 @@ void lua_engine::initialize()
* space.map[] - table of address map entries (k=index, v=address_map_entry)
*/
- sol().registry().new_usertype<addr_space>("addr_space", sol::call_constructor, sol::constructors<sol::types<address_space &, device_memory_interface &>>(),
- "read_i8", &addr_space::mem_read<int8_t>,
- "read_u8", &addr_space::mem_read<uint8_t>,
- "read_i16", &addr_space::mem_read<int16_t>,
- "read_u16", &addr_space::mem_read<uint16_t>,
- "read_i32", &addr_space::mem_read<int32_t>,
- "read_u32", &addr_space::mem_read<uint32_t>,
- "read_i64", &addr_space::mem_read<int64_t>,
- "read_u64", &addr_space::mem_read<uint64_t>,
- "write_i8", &addr_space::mem_write<int8_t>,
- "write_u8", &addr_space::mem_write<uint8_t>,
- "write_i16", &addr_space::mem_write<int16_t>,
- "write_u16", &addr_space::mem_write<uint16_t>,
- "write_i32", &addr_space::mem_write<int32_t>,
- "write_u32", &addr_space::mem_write<uint32_t>,
- "write_i64", &addr_space::mem_write<int64_t>,
- "write_u64", &addr_space::mem_write<uint64_t>,
- "read_log_i8", &addr_space::log_mem_read<int8_t>,
- "read_log_u8", &addr_space::log_mem_read<uint8_t>,
- "read_log_i16", &addr_space::log_mem_read<int16_t>,
- "read_log_u16", &addr_space::log_mem_read<uint16_t>,
- "read_log_i32", &addr_space::log_mem_read<int32_t>,
- "read_log_u32", &addr_space::log_mem_read<uint32_t>,
- "read_log_i64", &addr_space::log_mem_read<int64_t>,
- "read_log_u64", &addr_space::log_mem_read<uint64_t>,
- "write_log_i8", &addr_space::log_mem_write<int8_t>,
- "write_log_u8", &addr_space::log_mem_write<uint8_t>,
- "write_log_i16", &addr_space::log_mem_write<int16_t>,
- "write_log_u16", &addr_space::log_mem_write<uint16_t>,
- "write_log_i32", &addr_space::log_mem_write<int32_t>,
- "write_log_u32", &addr_space::log_mem_write<uint32_t>,
- "write_log_i64", &addr_space::log_mem_write<int64_t>,
- "write_log_u64", &addr_space::log_mem_write<uint64_t>,
- "read_direct_i8", &addr_space::direct_mem_read<int8_t>,
- "read_direct_u8", &addr_space::direct_mem_read<uint8_t>,
- "read_direct_i16", &addr_space::direct_mem_read<int16_t>,
- "read_direct_u16", &addr_space::direct_mem_read<uint16_t>,
- "read_direct_i32", &addr_space::direct_mem_read<int32_t>,
- "read_direct_u32", &addr_space::direct_mem_read<uint32_t>,
- "read_direct_i64", &addr_space::direct_mem_read<int64_t>,
- "read_direct_u64", &addr_space::direct_mem_read<uint64_t>,
- "write_direct_i8", &addr_space::direct_mem_write<int8_t>,
- "write_direct_u8", &addr_space::direct_mem_write<uint8_t>,
- "write_direct_i16", &addr_space::direct_mem_write<int16_t>,
- "write_direct_u16", &addr_space::direct_mem_write<uint16_t>,
- "write_direct_i32", &addr_space::direct_mem_write<int32_t>,
- "write_direct_u32", &addr_space::direct_mem_write<uint32_t>,
- "write_direct_i64", &addr_space::direct_mem_write<int64_t>,
- "write_direct_u64", &addr_space::direct_mem_write<uint64_t>,
- "name", sol::property([](addr_space &sp) { return sp.space.name(); }),
- "shift", sol::property([](addr_space &sp) { return sp.space.addr_shift(); }),
- "index", sol::property([](addr_space &sp) { return sp.space.spacenum(); }),
+ auto addr_space_type = sol().registry().create_simple_usertype<addr_space>(sol::call_constructor, sol::constructors<sol::types<address_space &, device_memory_interface &>>());
+ addr_space_type.set("read_i8", &addr_space::mem_read<int8_t>);
+ addr_space_type.set("read_u8", &addr_space::mem_read<uint8_t>);
+ addr_space_type.set("read_i16", &addr_space::mem_read<int16_t>);
+ addr_space_type.set("read_u16", &addr_space::mem_read<uint16_t>);
+ addr_space_type.set("read_i32", &addr_space::mem_read<int32_t>);
+ addr_space_type.set("read_u32", &addr_space::mem_read<uint32_t>);
+ addr_space_type.set("read_i64", &addr_space::mem_read<int64_t>);
+ addr_space_type.set("read_u64", &addr_space::mem_read<uint64_t>);
+ addr_space_type.set("write_i8", &addr_space::mem_write<int8_t>);
+ addr_space_type.set("write_u8", &addr_space::mem_write<uint8_t>);
+ addr_space_type.set("write_i16", &addr_space::mem_write<int16_t>);
+ addr_space_type.set("write_u16", &addr_space::mem_write<uint16_t>);
+ addr_space_type.set("write_i32", &addr_space::mem_write<int32_t>);
+ addr_space_type.set("write_u32", &addr_space::mem_write<uint32_t>);
+ addr_space_type.set("write_i64", &addr_space::mem_write<int64_t>);
+ addr_space_type.set("write_u64", &addr_space::mem_write<uint64_t>);
+ addr_space_type.set("read_log_i8", &addr_space::log_mem_read<int8_t>);
+ addr_space_type.set("read_log_u8", &addr_space::log_mem_read<uint8_t>);
+ addr_space_type.set("read_log_i16", &addr_space::log_mem_read<int16_t>);
+ addr_space_type.set("read_log_u16", &addr_space::log_mem_read<uint16_t>);
+ addr_space_type.set("read_log_i32", &addr_space::log_mem_read<int32_t>);
+ addr_space_type.set("read_log_u32", &addr_space::log_mem_read<uint32_t>);
+ addr_space_type.set("read_log_i64", &addr_space::log_mem_read<int64_t>);
+ addr_space_type.set("read_log_u64", &addr_space::log_mem_read<uint64_t>);
+ addr_space_type.set("write_log_i8", &addr_space::log_mem_write<int8_t>);
+ addr_space_type.set("write_log_u8", &addr_space::log_mem_write<uint8_t>);
+ addr_space_type.set("write_log_i16", &addr_space::log_mem_write<int16_t>);
+ addr_space_type.set("write_log_u16", &addr_space::log_mem_write<uint16_t>);
+ addr_space_type.set("write_log_i32", &addr_space::log_mem_write<int32_t>);
+ addr_space_type.set("write_log_u32", &addr_space::log_mem_write<uint32_t>);
+ addr_space_type.set("write_log_i64", &addr_space::log_mem_write<int64_t>);
+ addr_space_type.set("write_log_u64", &addr_space::log_mem_write<uint64_t>);
+ addr_space_type.set("read_direct_i8", &addr_space::direct_mem_read<int8_t>);
+ addr_space_type.set("read_direct_u8", &addr_space::direct_mem_read<uint8_t>);
+ addr_space_type.set("read_direct_i16", &addr_space::direct_mem_read<int16_t>);
+ addr_space_type.set("read_direct_u16", &addr_space::direct_mem_read<uint16_t>);
+ addr_space_type.set("read_direct_i32", &addr_space::direct_mem_read<int32_t>);
+ addr_space_type.set("read_direct_u32", &addr_space::direct_mem_read<uint32_t>);
+ addr_space_type.set("read_direct_i64", &addr_space::direct_mem_read<int64_t>);
+ addr_space_type.set("read_direct_u64", &addr_space::direct_mem_read<uint64_t>);
+ addr_space_type.set("write_direct_i8", &addr_space::direct_mem_write<int8_t>);
+ addr_space_type.set("write_direct_u8", &addr_space::direct_mem_write<uint8_t>);
+ addr_space_type.set("write_direct_i16", &addr_space::direct_mem_write<int16_t>);
+ addr_space_type.set("write_direct_u16", &addr_space::direct_mem_write<uint16_t>);
+ addr_space_type.set("write_direct_i32", &addr_space::direct_mem_write<int32_t>);
+ addr_space_type.set("write_direct_u32", &addr_space::direct_mem_write<uint32_t>);
+ addr_space_type.set("write_direct_i64", &addr_space::direct_mem_write<int64_t>);
+ addr_space_type.set("write_direct_u64", &addr_space::direct_mem_write<uint64_t>);
+ addr_space_type.set("name", sol::property([](addr_space &sp) { return sp.space.name(); }));
+ addr_space_type.set("shift", sol::property([](addr_space &sp) { return sp.space.addr_shift(); }));
+ addr_space_type.set("index", sol::property([](addr_space &sp) { return sp.space.spacenum(); }));
/* address_map_entry library
*
@@ -1688,20 +1704,21 @@ void lua_engine::initialize()
* mapentry.readtype
* mapentry.writetype
*/
- "map", sol::property([this](addr_space &sp) {
- address_space &space = sp.space;
- sol::table map = sol().create_table();
- for (address_map_entry &entry : space.map()->m_entrylist)
- {
- sol::table mapentry = sol().create_table();
- mapentry["offset"] = entry.m_addrstart & space.addrmask();
- mapentry["endoff"] = entry.m_addrend & space.addrmask();
- mapentry["readtype"] = entry.m_read.m_type;
- mapentry["writetype"] = entry.m_write.m_type;
- map.add(mapentry);
- }
- return map;
- }));
+ addr_space_type.set("map", sol::property([this](addr_space &sp) {
+ address_space &space = sp.space;
+ sol::table map = sol().create_table();
+ for (address_map_entry &entry : space.map()->m_entrylist)
+ {
+ sol::table mapentry = sol().create_table();
+ mapentry["offset"] = entry.m_addrstart & space.addrmask();
+ mapentry["endoff"] = entry.m_addrend & space.addrmask();
+ mapentry["readtype"] = entry.m_read.m_type;
+ mapentry["writetype"] = entry.m_write.m_type;
+ map.add(mapentry);
+ }
+ return map;
+ }));
+ sol().registry().set_usertype("addr_space", addr_space_type);
/* ioport_manager library
@@ -1714,18 +1731,19 @@ void lua_engine::initialize()
* ioport.ports[] - ioports table (k=tag, v=ioport_port)
*/
- sol().registry().new_usertype<ioport_manager>("ioport", "new", sol::no_constructor,
- "count_players", &ioport_manager::count_players,
- "natkeyboard", &ioport_manager::natkeyboard,
- "type_group", [](ioport_manager &im, ioport_type type, int player) {
- return im.type_group(type, player);
- },
- "ports", sol::property([this](ioport_manager &im) {
- sol::table port_table = sol().create_table();
- for (auto &port : im.ports())
- port_table[port.second->tag()] = port.second.get();
- return port_table;
- }));
+ auto ioport_manager_type = sol().registry().create_simple_usertype<ioport_manager>("new", sol::no_constructor);
+ ioport_manager_type.set("count_players", &ioport_manager::count_players);
+ ioport_manager_type.set("natkeyboard", &ioport_manager::natkeyboard);
+ ioport_manager_type.set("type_group", [](ioport_manager &im, ioport_type type, int player) {
+ return im.type_group(type, player);
+ });
+ ioport_manager_type.set("ports", sol::property([this](ioport_manager &im) {
+ sol::table port_table = sol().create_table();
+ for (auto &port : im.ports())
+ port_table[port.second->tag()] = port.second.get();
+ return port_table;
+ }));
+ sol().registry().set_usertype("ioport", ioport_manager_type);
/* natural_keyboard library
@@ -1740,12 +1758,13 @@ void lua_engine::initialize()
* natkeyboard.in_use - is the natural keyboard in use?
*/
- sol().registry().new_usertype<natural_keyboard>("natkeyboard", "new", sol::no_constructor,
- "empty", sol::property(&natural_keyboard::empty),
- "in_use", sol::property(&natural_keyboard::in_use, &natural_keyboard::set_in_use),
- "paste", &natural_keyboard::paste,
- "post", [](natural_keyboard &nat, const std::string &text) { nat.post_utf8(text); },
- "post_coded", [](natural_keyboard &nat, const std::string &text) { nat.post_coded(text); });
+ auto natkeyboard_type = sol().registry().create_simple_usertype<natural_keyboard>("new", sol::no_constructor);
+ natkeyboard_type.set("empty", sol::property(&natural_keyboard::empty));
+ natkeyboard_type.set("in_use", sol::property(&natural_keyboard::in_use, &natural_keyboard::set_in_use));
+ natkeyboard_type.set("paste", &natural_keyboard::paste);
+ natkeyboard_type.set("post", [](natural_keyboard &nat, const std::string &text) { nat.post_utf8(text); });
+ natkeyboard_type.set("post_coded", [](natural_keyboard &nat, const std::string &text) { nat.post_coded(text); });
+ sol().registry().set_usertype("natkeyboard", natkeyboard_type);
/* ioport_port library
@@ -1762,33 +1781,34 @@ void lua_engine::initialize()
* port.fields[] - get ioport_field table (k=name, v=ioport_field)
*/
- sol().registry().new_usertype<ioport_port>("ioport_port", "new", sol::no_constructor,
- "tag", &ioport_port::tag,
- "active", &ioport_port::active,
- "live", &ioport_port::live,
- "read", &ioport_port::read,
- "write", &ioport_port::write,
- "field", &ioport_port::field,
- "fields", sol::property([this](ioport_port &p){
- sol::table f_table = sol().create_table();
- // parse twice for custom and default names, default has priority
- for(ioport_field &field : p.fields())
- {
- if (field.type_class() != INPUT_CLASS_INTERNAL)
- f_table[field.name()] = &field;
- }
- for(ioport_field &field : p.fields())
- {
- if (field.type_class() != INPUT_CLASS_INTERNAL)
- {
- if(field.specific_name())
- f_table[field.specific_name()] = &field;
- else
- f_table[field.manager().type_name(field.type(), field.player())] = &field;
- }
- }
- return f_table;
- }));
+ auto ioport_port_type = sol().registry().create_simple_usertype<ioport_port>("new", sol::no_constructor);
+ ioport_port_type.set("tag", &ioport_port::tag);
+ ioport_port_type.set("active", &ioport_port::active);
+ ioport_port_type.set("live", &ioport_port::live);
+ ioport_port_type.set("read", &ioport_port::read);
+ ioport_port_type.set("write", &ioport_port::write);
+ ioport_port_type.set("field", &ioport_port::field);
+ ioport_port_type.set("fields", sol::property([this](ioport_port &p){
+ sol::table f_table = sol().create_table();
+ // parse twice for custom and default names, default has priority
+ for(ioport_field &field : p.fields())
+ {
+ if (field.type_class() != INPUT_CLASS_INTERNAL)
+ f_table[field.name()] = &field;
+ }
+ for(ioport_field &field : p.fields())
+ {
+ if (field.type_class() != INPUT_CLASS_INTERNAL)
+ {
+ if(field.specific_name())
+ f_table[field.specific_name()] = &field;
+ else
+ f_table[field.manager().type_name(field.type(), field.player())] = &field;
+ }
+ }
+ return f_table;
+ }));
+ sol().registry().set_usertype("ioport_port", ioport_port_type);
/* ioport_field library
@@ -1831,84 +1851,86 @@ void lua_engine::initialize()
* field.user_value
*/
- sol().registry().new_usertype<ioport_field>("ioport_field", "new", sol::no_constructor,
- "set_value", &ioport_field::set_value,
- "set_input_seq", [](ioport_field &f, const std::string &seq_type_string, sol::user<input_seq> seq) {
- input_seq_type seq_type = parse_seq_type(seq_type_string);
- ioport_field::user_settings settings;
- f.get_user_settings(settings);
- settings.seq[seq_type] = seq;
- f.set_user_settings(settings);
- },
- "input_seq", [](ioport_field &f, const std::string &seq_type_string) {
- input_seq_type seq_type = parse_seq_type(seq_type_string);
- return sol::make_user(f.seq(seq_type));
- },
- "set_default_input_seq", [](ioport_field &f, const std::string &seq_type_string, sol::user<input_seq> seq) {
- input_seq_type seq_type = parse_seq_type(seq_type_string);
- f.set_defseq(seq_type, seq);
- },
- "default_input_seq", [](ioport_field &f, const std::string &seq_type_string) {
- input_seq_type seq_type = parse_seq_type(seq_type_string);
- return sol::make_user(f.defseq(seq_type));
- },
- "keyboard_codes", [this](ioport_field &f, int which)
+ auto ioport_field_type = sol().registry().create_simple_usertype<ioport_field>("new", sol::no_constructor);
+ ioport_field_type.set("set_value", &ioport_field::set_value);
+ ioport_field_type.set("set_input_seq", [](ioport_field &f, const std::string &seq_type_string, sol::user<input_seq> seq) {
+ input_seq_type seq_type = parse_seq_type(seq_type_string);
+ ioport_field::user_settings settings;
+ f.get_user_settings(settings);
+ settings.seq[seq_type] = seq;
+ f.set_user_settings(settings);
+ });
+ ioport_field_type.set("input_seq", [](ioport_field &f, const std::string &seq_type_string) {
+ input_seq_type seq_type = parse_seq_type(seq_type_string);
+ return sol::make_user(f.seq(seq_type));
+ });
+ ioport_field_type.set("set_default_input_seq", [](ioport_field &f, const std::string &seq_type_string, sol::user<input_seq> seq) {
+ input_seq_type seq_type = parse_seq_type(seq_type_string);
+ f.set_defseq(seq_type, seq);
+ });
+ ioport_field_type.set("default_input_seq", [](ioport_field &f, const std::string &seq_type_string) {
+ input_seq_type seq_type = parse_seq_type(seq_type_string);
+ return sol::make_user(f.defseq(seq_type));
+ });
+ ioport_field_type.set("keyboard_codes", [this](ioport_field &f, int which) {
+ sol::table result = sol().create_table();
+ int index = 1;
+ for (char32_t code : f.keyboard_codes(which))
+ result[index++] = code;
+ return result;
+ });
+ ioport_field_type.set("device", sol::property(&ioport_field::device));
+ ioport_field_type.set("port", sol::property(&ioport_field::port));
+ ioport_field_type.set("name", sol::property(&ioport_field::name));
+ ioport_field_type.set("default_name", sol::property([](ioport_field &f) {
+ return f.specific_name() ? f.specific_name() : f.manager().type_name(f.type(), f.player());
+ }));
+ ioport_field_type.set("player", sol::property(&ioport_field::player, &ioport_field::set_player));
+ ioport_field_type.set("mask", sol::property(&ioport_field::mask));
+ ioport_field_type.set("defvalue", sol::property(&ioport_field::defvalue));
+ ioport_field_type.set("sensitivity", sol::property(&ioport_field::sensitivity));
+ ioport_field_type.set("way", sol::property(&ioport_field::way));
+ ioport_field_type.set("type_class", sol::property([](ioport_field &f) {
+ switch (f.type_class())
{
- sol::table result = sol().create_table();
- int index = 1;
- for (char32_t code : f.keyboard_codes(which))
- result[index++] = code;
- return result;
- },
- "device", sol::property(&ioport_field::device),
- "port", sol::property(&ioport_field::port),
- "name", sol::property(&ioport_field::name),
- "default_name", sol::property([](ioport_field &f) {
- return f.specific_name() ? f.specific_name() : f.manager().type_name(f.type(), f.player());
- }),
- "player", sol::property(&ioport_field::player, &ioport_field::set_player),
- "mask", sol::property(&ioport_field::mask),
- "defvalue", sol::property(&ioport_field::defvalue),
- "sensitivity", sol::property(&ioport_field::sensitivity),
- "way", sol::property(&ioport_field::way),
- "type_class", sol::property([](ioport_field &f) {
- switch (f.type_class())
- {
- case INPUT_CLASS_KEYBOARD: return "keyboard";
- case INPUT_CLASS_CONTROLLER: return "controller";
- case INPUT_CLASS_CONFIG: return "config";
- case INPUT_CLASS_DIPSWITCH: return "dipswitch";
- case INPUT_CLASS_MISC: return "misc";
- default: break;
- }
- throw false;
- }),
- "is_analog", sol::property(&ioport_field::is_analog),
- "is_digital_joystick", sol::property(&ioport_field::is_digital_joystick),
- "enabled", sol::property(&ioport_field::enabled),
- "optional", sol::property(&ioport_field::optional),
- "cocktail", sol::property(&ioport_field::cocktail),
- "toggle", sol::property(&ioport_field::toggle),
- "rotated", sol::property(&ioport_field::rotated),
- "analog_reverse", sol::property(&ioport_field::analog_reverse),
- "analog_reset", sol::property(&ioport_field::analog_reset),
- "analog_wraps", sol::property(&ioport_field::analog_wraps),
- "analog_invert", sol::property(&ioport_field::analog_invert),
- "impulse", sol::property(&ioport_field::impulse),
- "type", sol::property(&ioport_field::type),
- "live", sol::property(&ioport_field::live),
- "crosshair_scale", sol::property(&ioport_field::crosshair_scale, &ioport_field::set_crosshair_scale),
- "crosshair_offset", sol::property(&ioport_field::crosshair_offset, &ioport_field::set_crosshair_offset),
- "user_value", sol::property([](ioport_field &f) {
- ioport_field::user_settings settings;
- f.get_user_settings(settings);
- return settings.value;
- }, [](ioport_field &f, ioport_value val) {
- ioport_field::user_settings settings;
- f.get_user_settings(settings);
- settings.value = val;
- f.set_user_settings(settings);
- }));
+ case INPUT_CLASS_KEYBOARD: return "keyboard";
+ case INPUT_CLASS_CONTROLLER: return "controller";
+ case INPUT_CLASS_CONFIG: return "config";
+ case INPUT_CLASS_DIPSWITCH: return "dipswitch";
+ case INPUT_CLASS_MISC: return "misc";
+ default: break;
+ }
+ throw false;
+ }));
+ ioport_field_type.set("is_analog", sol::property(&ioport_field::is_analog));
+ ioport_field_type.set("is_digital_joystick", sol::property(&ioport_field::is_digital_joystick));
+ ioport_field_type.set("enabled", sol::property(&ioport_field::enabled));
+ ioport_field_type.set("optional", sol::property(&ioport_field::optional));
+ ioport_field_type.set("cocktail", sol::property(&ioport_field::cocktail));
+ ioport_field_type.set("toggle", sol::property(&ioport_field::toggle));
+ ioport_field_type.set("rotated", sol::property(&ioport_field::rotated));
+ ioport_field_type.set("analog_reverse", sol::property(&ioport_field::analog_reverse));
+ ioport_field_type.set("analog_reset", sol::property(&ioport_field::analog_reset));
+ ioport_field_type.set("analog_wraps", sol::property(&ioport_field::analog_wraps));
+ ioport_field_type.set("analog_invert", sol::property(&ioport_field::analog_invert));
+ ioport_field_type.set("impulse", sol::property(&ioport_field::impulse));
+ ioport_field_type.set("type", sol::property(&ioport_field::type));
+ ioport_field_type.set("live", sol::property(&ioport_field::live));
+ ioport_field_type.set("crosshair_scale", sol::property(&ioport_field::crosshair_scale, &ioport_field::set_crosshair_scale));
+ ioport_field_type.set("crosshair_offset", sol::property(&ioport_field::crosshair_offset, &ioport_field::set_crosshair_offset));
+ ioport_field_type.set("user_value", sol::property(
+ [](ioport_field &f) {
+ ioport_field::user_settings settings;
+ f.get_user_settings(settings);
+ return settings.value;
+ },
+ [](ioport_field &f, ioport_value val) {
+ ioport_field::user_settings settings;
+ f.get_user_settings(settings);
+ settings.value = val;
+ f.set_user_settings(settings);
+ }));
+ sol().registry().set_usertype("ioport_field", ioport_field_type);
/* ioport_field_live library
@@ -1955,48 +1977,50 @@ void lua_engine::initialize()
* video.throttle_rate - throttle rate
*/
- sol().registry().new_usertype<video_manager>("video", "new", sol::no_constructor,
- "begin_recording", sol::overload([this](video_manager &vm, const char *filename) {
- std::string fn = filename;
- strreplace(fn, "/", PATH_SEPARATOR);
- strreplace(fn, "%g", machine().basename());
- vm.begin_recording(fn.c_str(), video_manager::MF_AVI);
- },
- [](video_manager &vm) { vm.begin_recording(nullptr, video_manager::MF_AVI); }),
- "end_recording", [this](video_manager &vm) {
- if(!vm.is_recording())
- {
- machine().logerror("[luaengine] No active recording to stop\n");
- return;
- }
- vm.end_recording(video_manager::MF_AVI);
- },
- "snapshot", &video_manager::save_active_screen_snapshots,
- "is_recording", &video_manager::is_recording,
- "skip_this_frame", &video_manager::skip_this_frame,
- "speed_factor", &video_manager::speed_factor,
- "speed_percent", &video_manager::speed_percent,
- "effective_frameskip", &video_manager::effective_frameskip,
- "frame_update", &video_manager::frame_update,
- "size", [](video_manager &vm) {
- s32 width, height;
- vm.compute_snapshot_size(width, height);
- return std::tuple<s32, s32>(width, height);
- },
- "pixels", [](video_manager &vm, sol::this_state s) {
- lua_State *L = s;
- luaL_Buffer buff;
- s32 width, height;
- vm.compute_snapshot_size(width, height);
- int size = width * height * 4;
- u32 *ptr = (u32 *)luaL_buffinitsize(L, &buff, size);
- vm.pixels(ptr);
- luaL_pushresultsize(&buff, size);
- return sol::make_reference(L, sol::stack_reference(L, -1));
- },
- "frameskip", sol::property(&video_manager::frameskip, &video_manager::set_frameskip),
- "throttled", sol::property(&video_manager::throttled, &video_manager::set_throttled),
- "throttle_rate", sol::property(&video_manager::throttle_rate, &video_manager::set_throttle_rate));
+ auto video_type = sol().registry().create_simple_usertype<video_manager>("new", sol::no_constructor);
+ video_type.set("begin_recording", sol::overload(
+ [this](video_manager &vm, const char *filename) {
+ std::string fn = filename;
+ strreplace(fn, "/", PATH_SEPARATOR);
+ strreplace(fn, "%g", machine().basename());
+ vm.begin_recording(fn.c_str(), video_manager::MF_AVI);
+ },
+ [](video_manager &vm) { vm.begin_recording(nullptr, video_manager::MF_AVI); }));
+ video_type.set("end_recording", [this](video_manager &vm) {
+ if(!vm.is_recording())
+ {
+ machine().logerror("[luaengine] No active recording to stop\n");
+ return;
+ }
+ vm.end_recording(video_manager::MF_AVI);
+ });
+ video_type.set("snapshot", &video_manager::save_active_screen_snapshots);
+ video_type.set("is_recording", &video_manager::is_recording);
+ video_type.set("skip_this_frame", &video_manager::skip_this_frame);
+ video_type.set("speed_factor", &video_manager::speed_factor);
+ video_type.set("speed_percent", &video_manager::speed_percent);
+ video_type.set("effective_frameskip", &video_manager::effective_frameskip);
+ video_type.set("frame_update", &video_manager::frame_update);
+ video_type.set("size", [](video_manager &vm) {
+ s32 width, height;
+ vm.compute_snapshot_size(width, height);
+ return std::tuple<s32, s32>(width, height);
+ });
+ video_type.set("pixels", [](video_manager &vm, sol::this_state s) {
+ lua_State *L = s;
+ luaL_Buffer buff;
+ s32 width, height;
+ vm.compute_snapshot_size(width, height);
+ int size = width * height * 4;
+ u32 *ptr = (u32 *)luaL_buffinitsize(L, &buff, size);
+ vm.pixels(ptr);
+ luaL_pushresultsize(&buff, size);
+ return sol::make_reference(L, sol::stack_reference(L, -1));
+ });
+ video_type.set("frameskip", sol::property(&video_manager::frameskip, &video_manager::set_frameskip));
+ video_type.set("throttled", sol::property(&video_manager::throttled, &video_manager::set_throttled));
+ video_type.set("throttle_rate", sol::property(&video_manager::throttle_rate, &video_manager::set_throttle_rate));
+ sol().registry().set_usertype("video", video_type);
/* sound_manager library
@@ -2012,22 +2036,23 @@ void lua_engine::initialize()
* sound.attenuation - sound attenuation
*/
- sol().registry().new_usertype<sound_manager>("sound", "new", sol::no_constructor,
- "start_recording", &sound_manager::start_recording,
- "stop_recording", &sound_manager::stop_recording,
- "ui_mute", &sound_manager::ui_mute,
- "debugger_mute", &sound_manager::debugger_mute,
- "system_mute", &sound_manager::system_mute,
- "samples", [](sound_manager &sm, sol::this_state s) {
- lua_State *L = s;
- luaL_Buffer buff;
- s32 count = sm.sample_count() * 2 * 2; // 2 channels, 2 bytes per sample
- s16 *ptr = (s16 *)luaL_buffinitsize(L, &buff, count);
- sm.samples(ptr);
- luaL_pushresultsize(&buff, count);
- return sol::make_reference(L, sol::stack_reference(L, -1));
- },
- "attenuation", sol::property(&sound_manager::attenuation, &sound_manager::set_attenuation));
+ auto sound_type = sol().registry().create_simple_usertype<sound_manager>("new", sol::no_constructor);
+ sound_type.set("start_recording", &sound_manager::start_recording);
+ sound_type.set("stop_recording", &sound_manager::stop_recording);
+ sound_type.set("ui_mute", &sound_manager::ui_mute);
+ sound_type.set("debugger_mute", &sound_manager::debugger_mute);
+ sound_type.set("system_mute", &sound_manager::system_mute);
+ sound_type.set("samples", [](sound_manager &sm, sol::this_state s) {
+ lua_State *L = s;
+ luaL_Buffer buff;
+ s32 count = sm.sample_count() * 2 * 2; // 2 channels, 2 bytes per sample
+ s16 *ptr = (s16 *)luaL_buffinitsize(L, &buff, count);
+ sm.samples(ptr);
+ luaL_pushresultsize(&buff, count);
+ return sol::make_reference(L, sol::stack_reference(L, -1));
+ });
+ sound_type.set("attenuation", sol::property(&sound_manager::attenuation, &sound_manager::set_attenuation));
+ sol().registry().set_usertype("sound", sound_type);
/* input_manager library
@@ -2050,46 +2075,46 @@ void lua_engine::initialize()
* input.device_classes - returns device classes
*/
- sol().registry().new_usertype<input_manager>("input", "new", sol::no_constructor,
- "code_from_token", [](input_manager &input, const char *token) { return sol::make_user(input.code_from_token(token)); },
- "code_pressed", [](input_manager &input, sol::user<input_code> code) { return input.code_pressed(code); },
- "code_to_token", [](input_manager &input, sol::user<input_code> code) { return input.code_to_token(code); },
- "code_name", [](input_manager &input, sol::user<input_code> code) { return input.code_name(code); },
- "seq_from_tokens", [](input_manager &input, const char *tokens) { input_seq seq; input.seq_from_tokens(seq, tokens); return sol::make_user(seq); },
- "seq_pressed", [](input_manager &input, sol::user<input_seq> seq) { return input.seq_pressed(seq); },
- "seq_to_tokens", [](input_manager &input, sol::user<input_seq> seq) { return input.seq_to_tokens(seq); },
- "seq_name", [](input_manager &input, sol::user<input_seq> seq) { return input.seq_name(seq); },
- "seq_clean", [](input_manager &input, sol::user<input_seq> seq) { input_seq cleaned_seq = input.seq_clean(seq); return sol::make_user(cleaned_seq); },
- "seq_poll_start", [](input_manager &input, const char *cls_string, sol::object seq) {
- input_item_class cls;
- if (!strcmp(cls_string, "switch"))
- cls = ITEM_CLASS_SWITCH;
- else if (!strcmp(cls_string, "absolute") || !strcmp(cls_string, "abs"))
- cls = ITEM_CLASS_ABSOLUTE;
- else if (!strcmp(cls_string, "relative") || !strcmp(cls_string, "rel"))
- cls = ITEM_CLASS_RELATIVE;
- else if (!strcmp(cls_string, "maximum") || !strcmp(cls_string, "max"))
- cls = ITEM_CLASS_MAXIMUM;
- else
- cls = ITEM_CLASS_INVALID;
+ auto input_type = sol().registry().create_simple_usertype<input_manager>("new", sol::no_constructor);
+ input_type.set("code_from_token", [](input_manager &input, const char *token) { return sol::make_user(input.code_from_token(token)); });
+ input_type.set("code_pressed", [](input_manager &input, sol::user<input_code> code) { return input.code_pressed(code); });
+ input_type.set("code_to_token", [](input_manager &input, sol::user<input_code> code) { return input.code_to_token(code); });
+ input_type.set("code_name", [](input_manager &input, sol::user<input_code> code) { return input.code_name(code); });
+ input_type.set("seq_from_tokens", [](input_manager &input, const char *tokens) { input_seq seq; input.seq_from_tokens(seq, tokens); return sol::make_user(seq); });
+ input_type.set("seq_pressed", [](input_manager &input, sol::user<input_seq> seq) { return input.seq_pressed(seq); });
+ input_type.set("seq_to_tokens", [](input_manager &input, sol::user<input_seq> seq) { return input.seq_to_tokens(seq); });
+ input_type.set("seq_name", [](input_manager &input, sol::user<input_seq> seq) { return input.seq_name(seq); });
+ input_type.set("seq_clean", [](input_manager &input, sol::user<input_seq> seq) { input_seq cleaned_seq = input.seq_clean(seq); return sol::make_user(cleaned_seq); });
+ input_type.set("seq_poll_start", [](input_manager &input, const char *cls_string, sol::object seq) {
+ input_item_class cls;
+ if (!strcmp(cls_string, "switch"))
+ cls = ITEM_CLASS_SWITCH;
+ else if (!strcmp(cls_string, "absolute") || !strcmp(cls_string, "abs"))
+ cls = ITEM_CLASS_ABSOLUTE;
+ else if (!strcmp(cls_string, "relative") || !strcmp(cls_string, "rel"))
+ cls = ITEM_CLASS_RELATIVE;
+ else if (!strcmp(cls_string, "maximum") || !strcmp(cls_string, "max"))
+ cls = ITEM_CLASS_MAXIMUM;
+ else
+ cls = ITEM_CLASS_INVALID;
- input_seq *start = nullptr;
- if(seq.is<sol::user<input_seq>>())
- start = &seq.as<sol::user<input_seq>>();
- input.seq_poll_start(cls, start);
- },
- "seq_poll", &input_manager::seq_poll,
- "seq_poll_final", [](input_manager &input) { return sol::make_user(input.seq_poll_final()); },
- "device_classes", sol::property([this](input_manager &input)
+ input_seq *start = nullptr;
+ if(seq.is<sol::user<input_seq>>())
+ start = &seq.as<sol::user<input_seq>>();
+ input.seq_poll_start(cls, start);
+ });
+ input_type.set("seq_poll", &input_manager::seq_poll);
+ input_type.set("seq_poll_final", [](input_manager &input) { return sol::make_user(input.seq_poll_final()); });
+ input_type.set("device_classes", sol::property([this](input_manager &input) {
+ sol::table result = sol().create_table();
+ for (input_device_class devclass_id = DEVICE_CLASS_FIRST_VALID; devclass_id <= DEVICE_CLASS_LAST_VALID; devclass_id++)
{
- sol::table result = sol().create_table();
- for (input_device_class devclass_id = DEVICE_CLASS_FIRST_VALID; devclass_id <= DEVICE_CLASS_LAST_VALID; devclass_id++)
- {
- input_class &devclass = input.device_class(devclass_id);
- result[devclass.name()] = &devclass;
- }
- return result;
- }));
+ input_class &devclass = input.device_class(devclass_id);
+ result[devclass.name()] = &devclass;
+ }
+ return result;
+ }));
+ sol().registry().set_usertype("input", input_type);
/* input_class library
@@ -2102,22 +2127,22 @@ void lua_engine::initialize()
* devclass.devices[]
*/
- sol().registry().new_usertype<input_class>("input_class", "new", sol::no_constructor,
- "name", sol::property(&input_class::name),
- "enabled", sol::property(&input_class::enabled, &input_class::enable),
- "multi", sol::property(&input_class::multi, &input_class::set_multi),
- "devices", sol::property([this](input_class &devclass)
+ auto input_class_type = sol().registry().create_simple_usertype<input_class>("new", sol::no_constructor);
+ input_class_type.set("name", sol::property(&input_class::name));
+ input_class_type.set("enabled", sol::property(&input_class::enabled, &input_class::enable));
+ input_class_type.set("multi", sol::property(&input_class::multi, &input_class::set_multi));
+ input_class_type.set("devices", sol::property([this](input_class &devclass) {
+ sol::table result = sol().create_table();
+ int index = 1;
+ for (int devindex = 0; devindex <= devclass.maxindex(); devindex++)
{
- sol::table result = sol().create_table();
- int index = 1;
- for (int devindex = 0; devindex <= devclass.maxindex(); devindex++)
- {
- input_device *dev = devclass.device(devindex);
- if (dev)
- result[index++] = dev;
- }
- return result;
- }));
+ input_device *dev = devclass.device(devindex);
+ if (dev)
+ result[index++] = dev;
+ }
+ return result;
+ }));
+ sol().registry().set_usertype("input_class", input_class_type);
/* input_device library
@@ -2129,12 +2154,11 @@ void lua_engine::initialize()
* device.items[]
*/
- sol().registry().new_usertype<input_device>("input_device", "new", sol::no_constructor,
- "name", sol::property(&input_device::name),
- "id", sol::property(&input_device::id),
- "devindex", sol::property(&input_device::devindex),
- "items", sol::property([this](input_device &dev)
- {
+ auto input_device_type = sol().registry().create_simple_usertype<input_device>("new", sol::no_constructor);
+ input_device_type.set("name", sol::property(&input_device::name));
+ input_device_type.set("id", sol::property(&input_device::id));
+ input_device_type.set("devindex", sol::property(&input_device::devindex));
+ input_device_type.set("items", sol::property([this](input_device &dev) {
sol::table result = sol().create_table();
for (input_item_id id = ITEM_ID_FIRST_VALID; id < dev.maxitem(); id++)
{
@@ -2144,6 +2168,7 @@ void lua_engine::initialize()
}
return result;
}));
+ sol().registry().set_usertype("input_device", input_device_type);
/* input_device_item library
@@ -2154,14 +2179,14 @@ void lua_engine::initialize()
* item:code()
*/
- sol().registry().new_usertype<input_device_item>("input_device_item", "new", sol::no_constructor,
- "name", sol::property(&input_device_item::name),
- "token", sol::property(&input_device_item::token),
- "code", [](input_device_item &item)
- {
+ auto input_device_item_type = sol().registry().create_simple_usertype<input_device_item>("new", sol::no_constructor);
+ input_device_item_type.set("name", sol::property(&input_device_item::name));
+ input_device_item_type.set("token", sol::property(&input_device_item::token));
+ input_device_item_type.set("code", [](input_device_item &item) {
input_code code(item.device().devclass(), item.device().devindex(), item.itemclass(), ITEM_MODIFIER_NONE, item.itemid());
return sol::make_user(code);
});
+ sol().registry().set_usertype("input_device_item", input_device_item_type);
/* ui_input_manager library
@@ -2173,15 +2198,16 @@ void lua_engine::initialize()
* uiinput.presses_enabled - enable/disable ui key presses
*/
- sol().registry().new_usertype<ui_input_manager>("uiinput", "new", sol::no_constructor,
- "find_mouse", [](ui_input_manager &ui) {
- int32_t x, y;
- bool button;
- render_target *rt = ui.find_mouse(&x, &y, &button);
- return std::tuple<int32_t, int32_t, bool, render_target *>(x, y, button, rt);
- },
- "pressed", &ui_input_manager::pressed,
- "presses_enabled", sol::property(&ui_input_manager::presses_enabled, &ui_input_manager::set_presses_enabled));
+ auto uiinput_type = sol().registry().create_simple_usertype<ui_input_manager>("new", sol::no_constructor);
+ uiinput_type.set("find_mouse", [](ui_input_manager &ui) {
+ int32_t x, y;
+ bool button;
+ render_target *rt = ui.find_mouse(&x, &y, &button);
+ return std::tuple<int32_t, int32_t, bool, render_target *>(x, y, button, rt);
+ });
+ uiinput_type.set("pressed", &ui_input_manager::pressed);
+ uiinput_type.set("presses_enabled", sol::property(&ui_input_manager::presses_enabled, &ui_input_manager::set_presses_enabled));
+ sol().registry().set_usertype("uiinput", uiinput_type);
/* render_target library
@@ -2205,23 +2231,24 @@ void lua_engine::initialize()
* target.zoom - enable zoom
*/
- sol().registry().new_usertype<render_target>("target", "new", sol::no_constructor,
- "view_bounds", [](render_target &rt) {
- const render_bounds b = rt.current_view()->bounds();
- return std::tuple<float, float, float, float>(b.x0, b.x1, b.y0, b.y1);
- },
- "width", &render_target::width,
- "height", &render_target::height,
- "pixel_aspect", &render_target::pixel_aspect,
- "hidden", &render_target::hidden,
- "is_ui_target", &render_target::is_ui_target,
- "index", &render_target::index,
- "view_name", &render_target::view_name,
- "max_update_rate", sol::property(&render_target::max_update_rate, &render_target::set_max_update_rate),
- "view", sol::property(&render_target::view, &render_target::set_view),
- "orientation", sol::property(&render_target::orientation, &render_target::set_orientation),
- "screen_overlay", sol::property(&render_target::screen_overlay_enabled, &render_target::set_screen_overlay_enabled),
- "zoom", sol::property(&render_target::zoom_to_screen, &render_target::set_zoom_to_screen));
+ auto target_type = sol().registry().create_simple_usertype<render_target>("new", sol::no_constructor);
+ target_type.set("view_bounds", [](render_target &rt) {
+ const render_bounds b = rt.current_view()->bounds();
+ return std::tuple<float, float, float, float>(b.x0, b.x1, b.y0, b.y1);
+ });
+ target_type.set("width", &render_target::width);
+ target_type.set("height", &render_target::height);
+ target_type.set("pixel_aspect", &render_target::pixel_aspect);
+ target_type.set("hidden", &render_target::hidden);
+ target_type.set("is_ui_target", &render_target::is_ui_target);
+ target_type.set("index", &render_target::index);
+ target_type.set("view_name", &render_target::view_name);
+ target_type.set("max_update_rate", sol::property(&render_target::max_update_rate, &render_target::set_max_update_rate));
+ target_type.set("view", sol::property(&render_target::view, &render_target::set_view));
+ target_type.set("orientation", sol::property(&render_target::orientation, &render_target::set_orientation));
+ target_type.set("screen_overlay", sol::property(&render_target::screen_overlay_enabled, &render_target::set_screen_overlay_enabled));
+ target_type.set("zoom", sol::property(&render_target::zoom_to_screen, &render_target::set_zoom_to_screen));
+ sol().registry().set_usertype("target", target_type);
/* render_container library
@@ -2236,13 +2263,14 @@ void lua_engine::initialize()
* container:is_empty()
*/
- sol().registry().new_usertype<render_container>("render_container", "new", sol::no_constructor,
- "orientation", &render_container::orientation,
- "xscale", &render_container::xscale,
- "yscale", &render_container::yscale,
- "xoffset", &render_container::xoffset,
- "yoffset", &render_container::yoffset,
- "is_empty", &render_container::is_empty);
+ auto render_container_type = sol().registry().create_simple_usertype<render_container>("new", sol::no_constructor);
+ render_container_type.set("orientation", &render_container::orientation);
+ render_container_type.set("xscale", &render_container::xscale);
+ render_container_type.set("yscale", &render_container::yscale);
+ render_container_type.set("xoffset", &render_container::xoffset);
+ render_container_type.set("yoffset", &render_container::yoffset);
+ render_container_type.set("is_empty", &render_container::is_empty);
+ sol().registry().set_usertype("render_container", render_container_type);
/* render_manager library
@@ -2256,17 +2284,18 @@ void lua_engine::initialize()
* render.targets[] - render_target table
*/
- sol().registry().new_usertype<render_manager>("render", "new", sol::no_constructor,
- "max_update_rate", &render_manager::max_update_rate,
- "ui_target", &render_manager::ui_target,
- "ui_container", &render_manager::ui_container,
- "targets", sol::property([this](render_manager &r) {
- sol::table target_table = sol().create_table();
- int tc = 0;
- for(render_target &curr_rt : r.targets())
- target_table[tc++] = &curr_rt;
- return target_table;
- }));
+ auto render_type = sol().registry().create_simple_usertype<render_manager>("new", sol::no_constructor);
+ render_type.set("max_update_rate", &render_manager::max_update_rate);
+ render_type.set("ui_target", &render_manager::ui_target);
+ render_type.set("ui_container", &render_manager::ui_container);
+ render_type.set("targets", sol::property([this](render_manager &r) {
+ sol::table target_table = sol().create_table();
+ int tc = 0;
+ for(render_target &curr_rt : r.targets())
+ target_table[tc++] = &curr_rt;
+ return target_table;
+ }));
+ sol().registry().set_usertype("render", render_type);
/* screen_device library
@@ -2295,144 +2324,142 @@ void lua_engine::initialize()
* screen:pixels() - get whole screen binary bitmap as string
*/
- sol().registry().new_usertype<screen_device>("screen_dev", "new", sol::no_constructor,
- "draw_box", [](screen_device &sdev, float x1, float y1, float x2, float y2, uint32_t bgcolor, uint32_t fgcolor) {
- int sc_width = sdev.visible_area().width();
- int sc_height = sdev.visible_area().height();
- x1 = std::min(std::max(0.0f, x1), float(sc_width-1)) / float(sc_width);
- y1 = std::min(std::max(0.0f, y1), float(sc_height-1)) / float(sc_height);
- x2 = std::min(std::max(0.0f, x2), float(sc_width-1)) / float(sc_width);
- y2 = std::min(std::max(0.0f, y2), float(sc_height-1)) / float(sc_height);
- mame_machine_manager::instance()->ui().draw_outlined_box(sdev.container(), x1, y1, x2, y2, fgcolor, bgcolor);
- },
- "draw_line", [](screen_device &sdev, float x1, float y1, float x2, float y2, uint32_t color) {
- int sc_width = sdev.visible_area().width();
- int sc_height = sdev.visible_area().height();
- x1 = std::min(std::max(0.0f, x1), float(sc_width-1)) / float(sc_width);
- y1 = std::min(std::max(0.0f, y1), float(sc_height-1)) / float(sc_height);
- x2 = std::min(std::max(0.0f, x2), float(sc_width-1)) / float(sc_width);
- y2 = std::min(std::max(0.0f, y2), float(sc_height-1)) / float(sc_height);
- sdev.container().add_line(x1, y1, x2, y2, UI_LINE_WIDTH, rgb_t(color), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
- },
- "draw_text", [this](screen_device &sdev, sol::object xobj, float y, const char *msg, sol::object color, sol::object bcolor) {
- int sc_width = sdev.visible_area().width();
- int sc_height = sdev.visible_area().height();
- auto justify = ui::text_layout::LEFT;
- float x = 0;
- if(xobj.is<float>())
- {
- x = std::min(std::max(0.0f, xobj.as<float>()), float(sc_width-1)) / float(sc_width);
- y = std::min(std::max(0.0f, y), float(sc_height-1)) / float(sc_height);
- }
- else if(xobj.is<const char *>())
- {
- std::string just_str = xobj.as<const char *>();
- if(just_str == "right")
- justify = ui::text_layout::RIGHT;
- else if(just_str == "center")
- justify = ui::text_layout::CENTER;
- }
- else
- {
- luaL_error(m_lua_state, "Error in param 1 to draw_text");
- return;
- }
- rgb_t textcolor = mame_machine_manager::instance()->ui().colors().text_color();
- rgb_t bgcolor = 0;
- if(color.is<uint32_t>())
- textcolor = rgb_t(color.as<uint32_t>());
- if(bcolor.is<uint32_t>())
- bgcolor = rgb_t(bcolor.as<uint32_t>());
- mame_machine_manager::instance()->ui().draw_text_full(sdev.container(), msg, x, y, (1.0f - x),
- justify, ui::text_layout::WORD, mame_ui_manager::OPAQUE_, textcolor, bgcolor);
- },
- "height", [](screen_device &sdev) { return sdev.visible_area().height(); },
- "width", [](screen_device &sdev) { return sdev.visible_area().width(); },
- "orientation", [](screen_device &sdev) {
- uint32_t flags = sdev.orientation();
- int rotation_angle = 0;
- switch (flags)
- {
- case ORIENTATION_FLIP_X:
- rotation_angle = 0;
- break;
- case ORIENTATION_SWAP_XY:
- case ORIENTATION_SWAP_XY|ORIENTATION_FLIP_X:
- rotation_angle = 90;
- break;
- case ORIENTATION_FLIP_Y:
- case ORIENTATION_FLIP_X|ORIENTATION_FLIP_Y:
- rotation_angle = 180;
- break;
- case ORIENTATION_SWAP_XY|ORIENTATION_FLIP_Y:
- case ORIENTATION_SWAP_XY|ORIENTATION_FLIP_X|ORIENTATION_FLIP_Y:
- rotation_angle = 270;
- break;
- }
- return std::tuple<int, bool, bool>(rotation_angle, flags & ORIENTATION_FLIP_X, flags & ORIENTATION_FLIP_Y);
- },
- "refresh", [](screen_device &sdev) { return ATTOSECONDS_TO_HZ(sdev.refresh_attoseconds()); },
- "refresh_attoseconds", [](screen_device &sdev) { return sdev.refresh_attoseconds(); },
- "snapshot", [this](screen_device &sdev, sol::object filename) -> sol::object {
- std::string snapstr;
- bool is_absolute_path = false;
- if (filename.is<const char *>())
- {
- // a filename was specified; if it isn't absolute postprocess it
- snapstr = filename.as<const char *>();
- is_absolute_path = osd_is_absolute_path(snapstr);
- if (!is_absolute_path)
- {
- strreplace(snapstr, "/", PATH_SEPARATOR);
- strreplace(snapstr, "%g", machine().basename());
- }
- }
+ auto screen_dev_type = sol().registry().create_simple_usertype<screen_device>("new", sol::no_constructor);
+ screen_dev_type.set("draw_box", [](screen_device &sdev, float x1, float y1, float x2, float y2, uint32_t bgcolor, uint32_t fgcolor) {
+ int sc_width = sdev.visible_area().width();
+ int sc_height = sdev.visible_area().height();
+ x1 = std::min(std::max(0.0f, x1), float(sc_width-1)) / float(sc_width);
+ y1 = std::min(std::max(0.0f, y1), float(sc_height-1)) / float(sc_height);
+ x2 = std::min(std::max(0.0f, x2), float(sc_width-1)) / float(sc_width);
+ y2 = std::min(std::max(0.0f, y2), float(sc_height-1)) / float(sc_height);
+ mame_machine_manager::instance()->ui().draw_outlined_box(sdev.container(), x1, y1, x2, y2, fgcolor, bgcolor);
+ });
+ screen_dev_type.set("draw_line", [](screen_device &sdev, float x1, float y1, float x2, float y2, uint32_t color) {
+ int sc_width = sdev.visible_area().width();
+ int sc_height = sdev.visible_area().height();
+ x1 = std::min(std::max(0.0f, x1), float(sc_width-1)) / float(sc_width);
+ y1 = std::min(std::max(0.0f, y1), float(sc_height-1)) / float(sc_height);
+ x2 = std::min(std::max(0.0f, x2), float(sc_width-1)) / float(sc_width);
+ y2 = std::min(std::max(0.0f, y2), float(sc_height-1)) / float(sc_height);
+ sdev.container().add_line(x1, y1, x2, y2, UI_LINE_WIDTH, rgb_t(color), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
+ });
+ screen_dev_type.set("draw_text", [this](screen_device &sdev, sol::object xobj, float y, const char *msg, sol::object color, sol::object bcolor) {
+ int sc_width = sdev.visible_area().width();
+ int sc_height = sdev.visible_area().height();
+ auto justify = ui::text_layout::LEFT;
+ float x = 0;
+ if(xobj.is<float>())
+ {
+ x = std::min(std::max(0.0f, xobj.as<float>()), float(sc_width-1)) / float(sc_width);
+ y = std::min(std::max(0.0f, y), float(sc_height-1)) / float(sc_height);
+ }
+ else if(xobj.is<const char *>())
+ {
+ std::string just_str = xobj.as<const char *>();
+ if(just_str == "right")
+ justify = ui::text_layout::RIGHT;
+ else if(just_str == "center")
+ justify = ui::text_layout::CENTER;
+ }
+ else
+ {
+ luaL_error(m_lua_state, "Error in param 1 to draw_text");
+ return;
+ }
+ rgb_t textcolor = mame_machine_manager::instance()->ui().colors().text_color();
+ rgb_t bgcolor = 0;
+ if(color.is<uint32_t>())
+ textcolor = rgb_t(color.as<uint32_t>());
+ if(bcolor.is<uint32_t>())
+ bgcolor = rgb_t(bcolor.as<uint32_t>());
+ mame_machine_manager::instance()->ui().draw_text_full(sdev.container(), msg, x, y, (1.0f - x),
+ justify, ui::text_layout::WORD, mame_ui_manager::OPAQUE_, textcolor, bgcolor);
+ });
+ screen_dev_type.set("height", [](screen_device &sdev) { return sdev.visible_area().height(); });
+ screen_dev_type.set("width", [](screen_device &sdev) { return sdev.visible_area().width(); });
+ screen_dev_type.set("orientation", [](screen_device &sdev) {
+ uint32_t flags = sdev.orientation();
+ int rotation_angle = 0;
+ switch (flags)
+ {
+ case ORIENTATION_FLIP_X:
+ rotation_angle = 0;
+ break;
+ case ORIENTATION_SWAP_XY:
+ case ORIENTATION_SWAP_XY|ORIENTATION_FLIP_X:
+ rotation_angle = 90;
+ break;
+ case ORIENTATION_FLIP_Y:
+ case ORIENTATION_FLIP_X|ORIENTATION_FLIP_Y:
+ rotation_angle = 180;
+ break;
+ case ORIENTATION_SWAP_XY|ORIENTATION_FLIP_Y:
+ case ORIENTATION_SWAP_XY|ORIENTATION_FLIP_X|ORIENTATION_FLIP_Y:
+ rotation_angle = 270;
+ break;
+ }
+ return std::tuple<int, bool, bool>(rotation_angle, flags & ORIENTATION_FLIP_X, flags & ORIENTATION_FLIP_Y);
+ });
+ screen_dev_type.set("refresh", [](screen_device &sdev) { return ATTOSECONDS_TO_HZ(sdev.refresh_attoseconds()); });
+ screen_dev_type.set("refresh_attoseconds", [](screen_device &sdev) { return sdev.refresh_attoseconds(); });
+ screen_dev_type.set("snapshot", [this](screen_device &sdev, sol::object filename) -> sol::object {
+ std::string snapstr;
+ bool is_absolute_path = false;
+ if (filename.is<const char *>())
+ {
+ // a filename was specified; if it isn't absolute postprocess it
+ snapstr = filename.as<const char *>();
+ is_absolute_path = osd_is_absolute_path(snapstr);
+ if (!is_absolute_path)
+ {
+ strreplace(snapstr, "/", PATH_SEPARATOR);
+ strreplace(snapstr, "%g", machine().basename());
+ }
+ }
- // open the file
- emu_file file(is_absolute_path ? "" : machine().options().snapshot_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
- osd_file::error filerr;
- if (!snapstr.empty())
- filerr = file.open(snapstr);
- else
- filerr = machine().video().open_next(file, "png");
- if (filerr != osd_file::error::NONE)
- return sol::make_object(sol(), filerr);
+ // open the file
+ emu_file file(is_absolute_path ? "" : machine().options().snapshot_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
+ osd_file::error filerr;
+ if (!snapstr.empty())
+ filerr = file.open(snapstr);
+ else
+ filerr = machine().video().open_next(file, "png");
+ if (filerr != osd_file::error::NONE)
+ return sol::make_object(sol(), filerr);
- // and save the snapshot
- machine().video().save_snapshot(&sdev, file);
- return sol::make_object(sol(), sol::nil);
- },
- "type", [](screen_device &sdev) {
- switch (sdev.screen_type())
- {
- case SCREEN_TYPE_RASTER: return "raster"; break;
- case SCREEN_TYPE_VECTOR: return "vector"; break;
- case SCREEN_TYPE_LCD: return "lcd"; break;
- case SCREEN_TYPE_SVG: return "svg"; break;
- default: break;
- }
- return "unknown";
- },
- "frame_number", &screen_device::frame_number,
- "name", &screen_device::name,
- "shortname", &screen_device::shortname,
- "tag", &screen_device::tag,
- "xscale", &screen_device::xscale,
- "yscale", &screen_device::yscale,
- "pixel", [](screen_device &sdev, float x, float y) {
- return sdev.pixel((s32)x, (s32)y);
- },
- "pixels", [](screen_device &sdev, sol::this_state s) {
- lua_State *L = s;
- const rectangle &visarea = sdev.visible_area();
- luaL_Buffer buff;
- int size = visarea.height() * visarea.width() * 4;
- u32 *ptr = (u32 *)luaL_buffinitsize(L, &buff, size);
- sdev.pixels(ptr);
- luaL_pushresultsize(&buff, size);
- return sol::make_reference(L, sol::stack_reference(L, -1));
- }
- );
+ // and save the snapshot
+ machine().video().save_snapshot(&sdev, file);
+ return sol::make_object(sol(), sol::nil);
+ });
+ screen_dev_type.set("type", [](screen_device &sdev) {
+ switch (sdev.screen_type())
+ {
+ case SCREEN_TYPE_RASTER: return "raster"; break;
+ case SCREEN_TYPE_VECTOR: return "vector"; break;
+ case SCREEN_TYPE_LCD: return "lcd"; break;
+ case SCREEN_TYPE_SVG: return "svg"; break;
+ default: break;
+ }
+ return "unknown";
+ });
+ screen_dev_type.set("frame_number", &screen_device::frame_number);
+ screen_dev_type.set("name", &screen_device::name);
+ screen_dev_type.set("shortname", &screen_device::shortname);
+ screen_dev_type.set("tag", &screen_device::tag);
+ screen_dev_type.set("xscale", &screen_device::xscale);
+ screen_dev_type.set("yscale", &screen_device::yscale);
+ screen_dev_type.set("pixel", [](screen_device &sdev, float x, float y) { return sdev.pixel((s32)x, (s32)y); });
+ screen_dev_type.set("pixels", [](screen_device &sdev, sol::this_state s) {
+ lua_State *L = s;
+ const rectangle &visarea = sdev.visible_area();
+ luaL_Buffer buff;
+ int size = visarea.height() * visarea.width() * 4;
+ u32 *ptr = (u32 *)luaL_buffinitsize(L, &buff, size);
+ sdev.pixels(ptr);
+ luaL_pushresultsize(&buff, size);
+ return sol::make_reference(L, sol::stack_reference(L, -1));
+ });
+ sol().registry().set_usertype("screen_dev", screen_dev_type);
/* mame_ui_manager library
@@ -2451,17 +2478,18 @@ void lua_engine::initialize()
* ui.show_profiler - profiler display enabled
*/
- sol().registry().new_usertype<mame_ui_manager>("ui", "new", sol::no_constructor,
- "is_menu_active", &mame_ui_manager::is_menu_active,
- "options", [](mame_ui_manager &m) { return static_cast<core_options *>(&m.options()); },
- "show_fps", sol::property(&mame_ui_manager::show_fps, &mame_ui_manager::set_show_fps),
- "show_profiler", sol::property(&mame_ui_manager::show_profiler, &mame_ui_manager::set_show_profiler),
- "single_step", sol::property(&mame_ui_manager::single_step, &mame_ui_manager::set_single_step),
- "get_line_height", &mame_ui_manager::get_line_height,
- "get_string_width", &mame_ui_manager::get_string_width,
- // sol converts char32_t to a string
- "get_char_width", [](mame_ui_manager &m, uint32_t utf8char) { return m.get_char_width(utf8char); },
- "set_aggressive_input_focus", [](mame_ui_manager &m, bool aggressive_focus) { osd_set_aggressive_input_focus(aggressive_focus); });
+ auto ui_type = sol().registry().create_simple_usertype<mame_ui_manager>("new", sol::no_constructor);
+ ui_type.set("is_menu_active", &mame_ui_manager::is_menu_active);
+ ui_type.set("options", [](mame_ui_manager &m) { return static_cast<core_options *>(&m.options()); });
+ ui_type.set("show_fps", sol::property(&mame_ui_manager::show_fps, &mame_ui_manager::set_show_fps));
+ ui_type.set("show_profiler", sol::property(&mame_ui_manager::show_profiler, &mame_ui_manager::set_show_profiler));
+ ui_type.set("single_step", sol::property(&mame_ui_manager::single_step, &mame_ui_manager::set_single_step));
+ ui_type.set("get_line_height", &mame_ui_manager::get_line_height);
+ ui_type.set("get_string_width", &mame_ui_manager::get_string_width);
+ // sol converts char32_t to a string
+ ui_type.set("get_char_width", [](mame_ui_manager &m, uint32_t utf8char) { return m.get_char_width(utf8char); });
+ ui_type.set("set_aggressive_input_focus", [](mame_ui_manager &m, bool aggressive_focus) { osd_set_aggressive_input_focus(aggressive_focus); });
+ sol().registry().set_usertype("ui", ui_type);
/* device_state_entry library
@@ -2475,27 +2503,29 @@ void lua_engine::initialize()
* state.value - get device state value
*/
- sol().registry().new_usertype<device_state_entry>("dev_space", "new", sol::no_constructor,
- "name", &device_state_entry::symbol,
- "value", sol::property([this](device_state_entry &entry) -> uint64_t {
- device_state_interface *state = entry.parent_state();
- if(state)
- {
- machine().save().dispatch_presave();
- return state->state_int(entry.index());
- }
- return 0;
- },
- [this](device_state_entry &entry, uint64_t val) {
- device_state_interface *state = entry.parent_state();
- if(state)
- {
- state->set_state_int(entry.index(), val);
- machine().save().dispatch_presave();
- }
- }),
- "is_visible", &device_state_entry::visible,
- "is_divider", &device_state_entry::divider);
+ auto dev_space_type = sol().registry().create_simple_usertype<device_state_entry>("new", sol::no_constructor);
+ dev_space_type.set("name", &device_state_entry::symbol);
+ dev_space_type.set("value", sol::property(
+ [this](device_state_entry &entry) -> uint64_t {
+ device_state_interface *state = entry.parent_state();
+ if(state)
+ {
+ machine().save().dispatch_presave();
+ return state->state_int(entry.index());
+ }
+ return 0;
+ },
+ [this](device_state_entry &entry, uint64_t val) {
+ device_state_interface *state = entry.parent_state();
+ if(state)
+ {
+ state->set_state_int(entry.index(), val);
+ machine().save().dispatch_presave();
+ }
+ }));
+ dev_space_type.set("is_visible", &device_state_entry::visible);
+ dev_space_type.set("is_divider", &device_state_entry::divider);
+ sol().registry().set_usertype("dev_space", dev_space_type);
/* memory_manager library
@@ -2507,25 +2537,26 @@ void lua_engine::initialize()
* memory.shares[] - table of memory shares
*/
- sol().registry().new_usertype<memory_manager>("memory", "new", sol::no_constructor,
- "banks", sol::property([this](memory_manager &mm) {
- sol::table table = sol().create_table();
- for (auto &bank : mm.banks())
- table[bank.second->tag()] = bank.second.get();
- return table;
- }),
- "regions", sol::property([this](memory_manager &mm) {
- sol::table table = sol().create_table();
- for (auto &region : mm.regions())
- table[region.second->name()] = region.second.get();
- return table;
- }),
- "shares", sol::property([this](memory_manager &mm) {
- sol::table table = sol().create_table();
- for (auto &share : mm.shares())
- table[share.first] = share.second.get();
- return table;
- }));
+ auto memory_type = sol().registry().create_simple_usertype<memory_manager>("new", sol::no_constructor);
+ memory_type.set("banks", sol::property([this](memory_manager &mm) {
+ sol::table table = sol().create_table();
+ for (auto &bank : mm.banks())
+ table[bank.second->tag()] = bank.second.get();
+ return table;
+ }));
+ memory_type.set("regions", sol::property([this](memory_manager &mm) {
+ sol::table table = sol().create_table();
+ for (auto &region : mm.regions())
+ table[region.second->name()] = region.second.get();
+ return table;
+ }));
+ memory_type.set("shares", sol::property([this](memory_manager &mm) {
+ sol::table table = sol().create_table();
+ for (auto &share : mm.shares())
+ table[share.first] = share.second.get();
+ return table;
+ }));
+ sol().registry().set_usertype("memory", memory_type);
/* memory_region library
@@ -2539,24 +2570,25 @@ void lua_engine::initialize()
* region.size
*/
- sol().registry().new_usertype<memory_region>("region", "new", sol::no_constructor,
- "read_i8", &region_read<int8_t>,
- "read_u8", &region_read<uint8_t>,
- "read_i16", &region_read<int16_t>,
- "read_u16", &region_read<uint16_t>,
- "read_i32", &region_read<int32_t>,
- "read_u32", &region_read<uint32_t>,
- "read_i64", &region_read<int64_t>,
- "read_u64", &region_read<uint64_t>,
- "write_i8", &region_write<int8_t>,
- "write_u8", &region_write<uint8_t>,
- "write_i16", &region_write<int16_t>,
- "write_u16", &region_write<uint16_t>,
- "write_i32", &region_write<int32_t>,
- "write_u32", &region_write<uint32_t>,
- "write_i64", &region_write<int64_t>,
- "write_u64", &region_write<uint64_t>,
- "size", sol::property(&memory_region::bytes));
+ auto region_type = sol().registry().create_simple_usertype<memory_region>("new", sol::no_constructor);
+ region_type.set("read_i8", &region_read<int8_t>);
+ region_type.set("read_u8", &region_read<uint8_t>);
+ region_type.set("read_i16", &region_read<int16_t>);
+ region_type.set("read_u16", &region_read<uint16_t>);
+ region_type.set("read_i32", &region_read<int32_t>);
+ region_type.set("read_u32", &region_read<uint32_t>);
+ region_type.set("read_i64", &region_read<int64_t>);
+ region_type.set("read_u64", &region_read<uint64_t>);
+ region_type.set("write_i8", &region_write<int8_t>);
+ region_type.set("write_u8", &region_write<uint8_t>);
+ region_type.set("write_i16", &region_write<int16_t>);
+ region_type.set("write_u16", &region_write<uint16_t>);
+ region_type.set("write_i32", &region_write<int32_t>);
+ region_type.set("write_u32", &region_write<uint32_t>);
+ region_type.set("write_i64", &region_write<int64_t>);
+ region_type.set("write_u64", &region_write<uint64_t>);
+ region_type.set("size", sol::property(&memory_region::bytes));
+ sol().registry().set_usertype("region", region_type);
/* memory_share library
@@ -2570,24 +2602,25 @@ void lua_engine::initialize()
* region.size
*/
- sol().registry().new_usertype<memory_share>("share", "new", sol::no_constructor,
- "read_i8", &share_read<int8_t>,
- "read_u8", &share_read<uint8_t>,
- "read_i16", &share_read<int16_t>,
- "read_u16", &share_read<uint16_t>,
- "read_i32", &share_read<int32_t>,
- "read_u32", &share_read<uint32_t>,
- "read_i64", &share_read<int64_t>,
- "read_u64", &share_read<uint64_t>,
- "write_i8", &share_write<int8_t>,
- "write_u8", &share_write<uint8_t>,
- "write_i16", &share_write<int16_t>,
- "write_u16", &share_write<uint16_t>,
- "write_i32", &share_write<int32_t>,
- "write_u32", &share_write<uint32_t>,
- "write_i64", &share_write<int64_t>,
- "write_u64", &share_write<uint64_t>,
- "size", sol::property(&memory_share::bytes));
+ auto share_type = sol().registry().create_simple_usertype<memory_share>("new", sol::no_constructor);
+ share_type.set("read_i8", &share_read<int8_t>);
+ share_type.set("read_u8", &share_read<uint8_t>);
+ share_type.set("read_i16", &share_read<int16_t>);
+ share_type.set("read_u16", &share_read<uint16_t>);
+ share_type.set("read_i32", &share_read<int32_t>);
+ share_type.set("read_u32", &share_read<uint32_t>);
+ share_type.set("read_i64", &share_read<int64_t>);
+ share_type.set("read_u64", &share_read<uint64_t>);
+ share_type.set("write_i8", &share_write<int8_t>);
+ share_type.set("write_u8", &share_write<uint8_t>);
+ share_type.set("write_i16", &share_write<int16_t>);
+ share_type.set("write_u16", &share_write<uint16_t>);
+ share_type.set("write_i32", &share_write<int32_t>);
+ share_type.set("write_u32", &share_write<uint32_t>);
+ share_type.set("write_i64", &share_write<int64_t>);
+ share_type.set("write_u64", &share_write<uint64_t>);
+ share_type.set("size", sol::property(&memory_share::bytes));
+ sol().registry().set_usertype("share", share_type);
/* output_manager library
@@ -2602,13 +2635,18 @@ void lua_engine::initialize()
* outputs:id_to_name(index) - get name for index
*/
- sol().registry().new_usertype<output_manager>("output", "new", sol::no_constructor,
- "set_value", &output_manager::set_value,
- "set_indexed_value", [](output_manager &o, char const *basename, int index, int value) { o.set_value(util::string_format("%s%d", basename, index).c_str(), value); },
- "get_value", &output_manager::get_value,
- "get_indexed_value", [](output_manager &o, char const *basename, int index) { return o.get_value(util::string_format("%s%d", basename, index).c_str()); },
- "name_to_id", &output_manager::name_to_id,
- "id_to_name", &output_manager::id_to_name);
+ auto output_type = sol().registry().create_simple_usertype<output_manager>("new", sol::no_constructor);
+ output_type.set("set_value", &output_manager::set_value);
+ output_type.set("set_indexed_value", [](output_manager &o, char const *basename, int index, int value) {
+ o.set_value(util::string_format("%s%d", basename, index).c_str(), value);
+ });
+ output_type.set("get_value", &output_manager::get_value);
+ output_type.set("get_indexed_value", [](output_manager &o, char const *basename, int index) {
+ return o.get_value(util::string_format("%s%d", basename, index).c_str());
+ });
+ output_type.set("name_to_id", &output_manager::name_to_id);
+ output_type.set("id_to_name", &output_manager::id_to_name);
+ sol().registry().set_usertype("output", output_type);
/* device_image_interface library
@@ -2639,29 +2677,32 @@ void lua_engine::initialize()
* image.must_be_loaded
*/
- sol().registry().new_usertype<device_image_interface>("image", "new", sol::no_constructor,
- "exists", &device_image_interface::exists,
- "filename", &device_image_interface::filename,
- "longname", &device_image_interface::longname,
- "manufacturer", &device_image_interface::manufacturer,
- "year", &device_image_interface::year,
- "software_list_name", &device_image_interface::software_list_name,
- "software_parent", sol::property([](device_image_interface &di) { const software_info *si = di.software_entry(); return si ? si->parentname() : ""; }),
- "image_type_name", &device_image_interface::image_type_name,
- "load", &device_image_interface::load,
- "unload", &device_image_interface::unload,
- "create", [](device_image_interface &di, const std::string &filename) { return di.create(filename); },
- "crc", &device_image_interface::crc,
- "display", [](device_image_interface &di) { return di.call_display(); },
- "device", sol::property(static_cast<const device_t &(device_image_interface::*)() const>(&device_image_interface::device)),
- "instance_name", sol::property(&device_image_interface::instance_name),
- "brief_instance_name", sol::property(&device_image_interface::brief_instance_name),
- "is_readable", sol::property(&device_image_interface::is_readable),
- "is_writeable", sol::property(&device_image_interface::is_writeable),
- "is_creatable", sol::property(&device_image_interface::is_creatable),
- "is_reset_on_load", sol::property(&device_image_interface::is_reset_on_load),
- "must_be_loaded", sol::property(&device_image_interface::must_be_loaded)
- );
+ auto image_type = sol().registry().create_simple_usertype<device_image_interface>("new", sol::no_constructor);
+ image_type.set("exists", &device_image_interface::exists);
+ image_type.set("filename", &device_image_interface::filename);
+ image_type.set("longname", &device_image_interface::longname);
+ image_type.set("manufacturer", &device_image_interface::manufacturer);
+ image_type.set("year", &device_image_interface::year);
+ image_type.set("software_list_name", &device_image_interface::software_list_name);
+ image_type.set("software_parent", sol::property([](device_image_interface &di) {
+ const software_info *si = di.software_entry();
+ return si ? si->parentname() : "";
+ }));
+ image_type.set("image_type_name", &device_image_interface::image_type_name);
+ image_type.set("load", &device_image_interface::load);
+ image_type.set("unload", &device_image_interface::unload);
+ image_type.set("create", [](device_image_interface &di, const std::string &filename) { return di.create(filename); });
+ image_type.set("crc", &device_image_interface::crc);
+ image_type.set("display", [](device_image_interface &di) { return di.call_display(); });
+ image_type.set("device", sol::property(static_cast<const device_t &(device_image_interface::*)() const>(&device_image_interface::device)));
+ image_type.set("instance_name", sol::property(&device_image_interface::instance_name));
+ image_type.set("brief_instance_name", sol::property(&device_image_interface::brief_instance_name));
+ image_type.set("is_readable", sol::property(&device_image_interface::is_readable));
+ image_type.set("is_writeable", sol::property(&device_image_interface::is_writeable));
+ image_type.set("is_creatable", sol::property(&device_image_interface::is_creatable));
+ image_type.set("is_reset_on_load", sol::property(&device_image_interface::is_reset_on_load));
+ image_type.set("must_be_loaded", sol::property(&device_image_interface::must_be_loaded));
+ sol().registry().set_usertype("image", image_type);
/* mame_machine_manager library