diff --git a/3rdparty/sol2/sol/traits.hpp b/3rdparty/sol2/sol/traits.hpp index 1ed95a1656e4b..762bc84b9472e 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 struct Check; diff --git a/src/frontend/mame/luaengine.cpp b/src/frontend/mame/luaengine.cpp index 4c5f9d0f42db3..2be6737e12473 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("file", sol::call_constructor, sol::initializers([](emu_file &file, u32 flags) { new (&file) emu_file(flags); }, + auto file_type = emu.create_simple_usertype(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(&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(&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("thread", sol::call_constructor, sol::constructors>(), - "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(); - thstate["yield"] = [&ctx, &thstate]() { - std::mutex m; - std::unique_lock 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(); - 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(sol::call_constructor, sol::constructors>()); + 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(); + thstate["yield"] = [&ctx, &thstate]() { + std::mutex m; + std::unique_lock 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(); + 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("item", sol::call_constructor, sol::initializers([this](save_item &item, int index) { + auto item_type = emu.create_simple_usertype(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", "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("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", "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("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 ("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(&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 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()] = ≻ - } - 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("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(&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 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_table[image.instance_name()] = ℑ + 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()] = ≻ + } + 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_table[image.instance_name()] = ℑ + } + 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", "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("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", "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("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("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("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", "new", sol::no_constructor, - "step", [](device_debug &dev, sol::object num) { - int steps = 1; - if(num.is()) - steps = num.as(); - 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("new", sol::no_constructor); + device_debug_type.set("step", [](device_debug &dev, sol::object num) { + int steps = 1; + if(num.is()) + steps = num.as(); + 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", "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(&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(&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(&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("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(&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(&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(&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", sol::call_constructor, sol::constructors>(), - "read_i8", &addr_space::mem_read, - "read_u8", &addr_space::mem_read, - "read_i16", &addr_space::mem_read, - "read_u16", &addr_space::mem_read, - "read_i32", &addr_space::mem_read, - "read_u32", &addr_space::mem_read, - "read_i64", &addr_space::mem_read, - "read_u64", &addr_space::mem_read, - "write_i8", &addr_space::mem_write, - "write_u8", &addr_space::mem_write, - "write_i16", &addr_space::mem_write, - "write_u16", &addr_space::mem_write, - "write_i32", &addr_space::mem_write, - "write_u32", &addr_space::mem_write, - "write_i64", &addr_space::mem_write, - "write_u64", &addr_space::mem_write, - "read_log_i8", &addr_space::log_mem_read, - "read_log_u8", &addr_space::log_mem_read, - "read_log_i16", &addr_space::log_mem_read, - "read_log_u16", &addr_space::log_mem_read, - "read_log_i32", &addr_space::log_mem_read, - "read_log_u32", &addr_space::log_mem_read, - "read_log_i64", &addr_space::log_mem_read, - "read_log_u64", &addr_space::log_mem_read, - "write_log_i8", &addr_space::log_mem_write, - "write_log_u8", &addr_space::log_mem_write, - "write_log_i16", &addr_space::log_mem_write, - "write_log_u16", &addr_space::log_mem_write, - "write_log_i32", &addr_space::log_mem_write, - "write_log_u32", &addr_space::log_mem_write, - "write_log_i64", &addr_space::log_mem_write, - "write_log_u64", &addr_space::log_mem_write, - "read_direct_i8", &addr_space::direct_mem_read, - "read_direct_u8", &addr_space::direct_mem_read, - "read_direct_i16", &addr_space::direct_mem_read, - "read_direct_u16", &addr_space::direct_mem_read, - "read_direct_i32", &addr_space::direct_mem_read, - "read_direct_u32", &addr_space::direct_mem_read, - "read_direct_i64", &addr_space::direct_mem_read, - "read_direct_u64", &addr_space::direct_mem_read, - "write_direct_i8", &addr_space::direct_mem_write, - "write_direct_u8", &addr_space::direct_mem_write, - "write_direct_i16", &addr_space::direct_mem_write, - "write_direct_u16", &addr_space::direct_mem_write, - "write_direct_i32", &addr_space::direct_mem_write, - "write_direct_u32", &addr_space::direct_mem_write, - "write_direct_i64", &addr_space::direct_mem_write, - "write_direct_u64", &addr_space::direct_mem_write, - "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(sol::call_constructor, sol::constructors>()); + addr_space_type.set("read_i8", &addr_space::mem_read); + addr_space_type.set("read_u8", &addr_space::mem_read); + addr_space_type.set("read_i16", &addr_space::mem_read); + addr_space_type.set("read_u16", &addr_space::mem_read); + addr_space_type.set("read_i32", &addr_space::mem_read); + addr_space_type.set("read_u32", &addr_space::mem_read); + addr_space_type.set("read_i64", &addr_space::mem_read); + addr_space_type.set("read_u64", &addr_space::mem_read); + addr_space_type.set("write_i8", &addr_space::mem_write); + addr_space_type.set("write_u8", &addr_space::mem_write); + addr_space_type.set("write_i16", &addr_space::mem_write); + addr_space_type.set("write_u16", &addr_space::mem_write); + addr_space_type.set("write_i32", &addr_space::mem_write); + addr_space_type.set("write_u32", &addr_space::mem_write); + addr_space_type.set("write_i64", &addr_space::mem_write); + addr_space_type.set("write_u64", &addr_space::mem_write); + addr_space_type.set("read_log_i8", &addr_space::log_mem_read); + addr_space_type.set("read_log_u8", &addr_space::log_mem_read); + addr_space_type.set("read_log_i16", &addr_space::log_mem_read); + addr_space_type.set("read_log_u16", &addr_space::log_mem_read); + addr_space_type.set("read_log_i32", &addr_space::log_mem_read); + addr_space_type.set("read_log_u32", &addr_space::log_mem_read); + addr_space_type.set("read_log_i64", &addr_space::log_mem_read); + addr_space_type.set("read_log_u64", &addr_space::log_mem_read); + addr_space_type.set("write_log_i8", &addr_space::log_mem_write); + addr_space_type.set("write_log_u8", &addr_space::log_mem_write); + addr_space_type.set("write_log_i16", &addr_space::log_mem_write); + addr_space_type.set("write_log_u16", &addr_space::log_mem_write); + addr_space_type.set("write_log_i32", &addr_space::log_mem_write); + addr_space_type.set("write_log_u32", &addr_space::log_mem_write); + addr_space_type.set("write_log_i64", &addr_space::log_mem_write); + addr_space_type.set("write_log_u64", &addr_space::log_mem_write); + addr_space_type.set("read_direct_i8", &addr_space::direct_mem_read); + addr_space_type.set("read_direct_u8", &addr_space::direct_mem_read); + addr_space_type.set("read_direct_i16", &addr_space::direct_mem_read); + addr_space_type.set("read_direct_u16", &addr_space::direct_mem_read); + addr_space_type.set("read_direct_i32", &addr_space::direct_mem_read); + addr_space_type.set("read_direct_u32", &addr_space::direct_mem_read); + addr_space_type.set("read_direct_i64", &addr_space::direct_mem_read); + addr_space_type.set("read_direct_u64", &addr_space::direct_mem_read); + addr_space_type.set("write_direct_i8", &addr_space::direct_mem_write); + addr_space_type.set("write_direct_u8", &addr_space::direct_mem_write); + addr_space_type.set("write_direct_i16", &addr_space::direct_mem_write); + addr_space_type.set("write_direct_u16", &addr_space::direct_mem_write); + addr_space_type.set("write_direct_i32", &addr_space::direct_mem_write); + addr_space_type.set("write_direct_u32", &addr_space::direct_mem_write); + addr_space_type.set("write_direct_i64", &addr_space::direct_mem_write); + addr_space_type.set("write_direct_u64", &addr_space::direct_mem_write); + 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", "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("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("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("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", "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("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", "new", sol::no_constructor, - "set_value", &ioport_field::set_value, - "set_input_seq", [](ioport_field &f, const std::string &seq_type_string, sol::user 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 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("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 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 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", "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(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("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(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", "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("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", "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 code) { return input.code_pressed(code); }, - "code_to_token", [](input_manager &input, sol::user code) { return input.code_to_token(code); }, - "code_name", [](input_manager &input, sol::user 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 seq) { return input.seq_pressed(seq); }, - "seq_to_tokens", [](input_manager &input, sol::user seq) { return input.seq_to_tokens(seq); }, - "seq_name", [](input_manager &input, sol::user seq) { return input.seq_name(seq); }, - "seq_clean", [](input_manager &input, sol::user 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("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 code) { return input.code_pressed(code); }); + input_type.set("code_to_token", [](input_manager &input, sol::user code) { return input.code_to_token(code); }); + input_type.set("code_name", [](input_manager &input, sol::user 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 seq) { return input.seq_pressed(seq); }); + input_type.set("seq_to_tokens", [](input_manager &input, sol::user seq) { return input.seq_to_tokens(seq); }); + input_type.set("seq_name", [](input_manager &input, sol::user seq) { return input.seq_name(seq); }); + input_type.set("seq_clean", [](input_manager &input, sol::user 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>()) - start = &seq.as>(); - 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>()) + start = &seq.as>(); + 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", "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("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", "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("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", "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("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("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(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("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(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("target", "new", sol::no_constructor, - "view_bounds", [](render_target &rt) { - const render_bounds b = rt.current_view()->bounds(); - return std::tuple(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("new", sol::no_constructor); + target_type.set("view_bounds", [](render_target &rt) { + const render_bounds b = rt.current_view()->bounds(); + return std::tuple(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", "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("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", "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("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_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()) - { - x = std::min(std::max(0.0f, xobj.as()), 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()) - { - std::string just_str = xobj.as(); - 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()) - textcolor = rgb_t(color.as()); - if(bcolor.is()) - bgcolor = rgb_t(bcolor.as()); - 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(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()) - { - // a filename was specified; if it isn't absolute postprocess it - snapstr = filename.as(); - 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("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()) + { + x = std::min(std::max(0.0f, xobj.as()), 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()) + { + std::string just_str = xobj.as(); + 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()) + textcolor = rgb_t(color.as()); + if(bcolor.is()) + bgcolor = rgb_t(bcolor.as()); + 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(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()) + { + // a filename was specified; if it isn't absolute postprocess it + snapstr = filename.as(); + 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("ui", "new", sol::no_constructor, - "is_menu_active", &mame_ui_manager::is_menu_active, - "options", [](mame_ui_manager &m) { return static_cast(&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("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(&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("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("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", "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 ®ion : 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("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 ®ion : 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("region", "new", sol::no_constructor, - "read_i8", ®ion_read, - "read_u8", ®ion_read, - "read_i16", ®ion_read, - "read_u16", ®ion_read, - "read_i32", ®ion_read, - "read_u32", ®ion_read, - "read_i64", ®ion_read, - "read_u64", ®ion_read, - "write_i8", ®ion_write, - "write_u8", ®ion_write, - "write_i16", ®ion_write, - "write_u16", ®ion_write, - "write_i32", ®ion_write, - "write_u32", ®ion_write, - "write_i64", ®ion_write, - "write_u64", ®ion_write, - "size", sol::property(&memory_region::bytes)); + auto region_type = sol().registry().create_simple_usertype("new", sol::no_constructor); + region_type.set("read_i8", ®ion_read); + region_type.set("read_u8", ®ion_read); + region_type.set("read_i16", ®ion_read); + region_type.set("read_u16", ®ion_read); + region_type.set("read_i32", ®ion_read); + region_type.set("read_u32", ®ion_read); + region_type.set("read_i64", ®ion_read); + region_type.set("read_u64", ®ion_read); + region_type.set("write_i8", ®ion_write); + region_type.set("write_u8", ®ion_write); + region_type.set("write_i16", ®ion_write); + region_type.set("write_u16", ®ion_write); + region_type.set("write_i32", ®ion_write); + region_type.set("write_u32", ®ion_write); + region_type.set("write_i64", ®ion_write); + region_type.set("write_u64", ®ion_write); + 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("share", "new", sol::no_constructor, - "read_i8", &share_read, - "read_u8", &share_read, - "read_i16", &share_read, - "read_u16", &share_read, - "read_i32", &share_read, - "read_u32", &share_read, - "read_i64", &share_read, - "read_u64", &share_read, - "write_i8", &share_write, - "write_u8", &share_write, - "write_i16", &share_write, - "write_u16", &share_write, - "write_i32", &share_write, - "write_u32", &share_write, - "write_i64", &share_write, - "write_u64", &share_write, - "size", sol::property(&memory_share::bytes)); + auto share_type = sol().registry().create_simple_usertype("new", sol::no_constructor); + share_type.set("read_i8", &share_read); + share_type.set("read_u8", &share_read); + share_type.set("read_i16", &share_read); + share_type.set("read_u16", &share_read); + share_type.set("read_i32", &share_read); + share_type.set("read_u32", &share_read); + share_type.set("read_i64", &share_read); + share_type.set("read_u64", &share_read); + share_type.set("write_i8", &share_write); + share_type.set("write_u8", &share_write); + share_type.set("write_i16", &share_write); + share_type.set("write_u16", &share_write); + share_type.set("write_i32", &share_write); + share_type.set("write_u32", &share_write); + share_type.set("write_i64", &share_write); + share_type.set("write_u64", &share_write); + 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", "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("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("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(&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("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(&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