summaryrefslogtreecommitdiffstatshomepage
path: root/src/frontend
diff options
context:
space:
mode:
author Vas Crabb <vas@vastheman.com>2020-12-27 01:32:37 +1100
committer Vas Crabb <vas@vastheman.com>2020-12-27 01:32:37 +1100
commit9e36b6a6d951ea6f2d72cab874c3c8e72d001001 (patch)
treec41bfd0c1b499d790c4091eb266caf6955219fc1 /src/frontend
parent509c946736b5f02cac84d19f2cde4e966d637a2c (diff)
More Lua interface cleanup - it's simpler with cleaner underlyng APIs.
Made the sound manager mute controls readable, and got rid of system enable since it just controls system mute anyway. This was causing confusion: phantom2 was trying to use both independentlyt casuing the mute bit to be ignored. THe Lua interface changes are mostly changing methods to properties, some renames to make things clearer, and some additional properties for better control over snapshots.
Diffstat (limited to 'src/frontend')
-rw-r--r--src/frontend/mame/luaengine.cpp507
-rw-r--r--src/frontend/mame/luaengine_debug.cpp26
-rw-r--r--src/frontend/mame/luaengine_render.cpp6
-rw-r--r--src/frontend/mame/mame.cpp6
-rw-r--r--src/frontend/mame/pluginopts.cpp4
-rw-r--r--src/frontend/mame/pluginopts.h21
-rw-r--r--src/frontend/mame/ui/miscmenu.cpp2
-rw-r--r--src/frontend/mame/ui/ui.cpp2
8 files changed, 250 insertions, 324 deletions
diff --git a/src/frontend/mame/luaengine.cpp b/src/frontend/mame/luaengine.cpp
index 98f00a219d0..fe534302f9e 100644
--- a/src/frontend/mame/luaengine.cpp
+++ b/src/frontend/mame/luaengine.cpp
@@ -125,6 +125,18 @@ struct image_interface_formats
device_image_interface &image;
};
+
+struct plugin_options_plugins
+{
+ plugin_options_plugins(plugin_options &o) : options(o) { }
+ std::list<plugin_options::plugin> &items() { return options.plugins(); }
+
+ static plugin_options::plugin const &unwrap(std::list<plugin_options::plugin>::const_iterator const &it) { return *it; }
+ static int push_key(lua_State *L, std::list<plugin_options::plugin>::const_iterator const &it, std::size_t ix) { return sol::stack::push_reference(L, it->m_name); }
+
+ plugin_options &options;
+};
+
} // anonymous namespace
@@ -132,6 +144,7 @@ namespace sol
{
template <> struct is_container<image_interface_formats> : std::true_type { };
+template <> struct is_container<plugin_options_plugins> : std::true_type { };
sol::buffer *sol_lua_get(sol::types<buffer *>, lua_State *L, int index, sol::stack::record &tracking)
@@ -145,6 +158,7 @@ int sol_lua_push(sol::types<buffer *>, lua_State *L, buffer *value)
return 1;
}
+
template <typename T>
struct usertype_container<lua_engine::devenum<T> > : lua_engine::immutable_collection_helper<lua_engine::devenum<T>, T>
{
@@ -275,6 +289,34 @@ public:
}
};
+
+template <>
+struct usertype_container<plugin_options_plugins> : lua_engine::immutable_sequence_helper<plugin_options_plugins, std::list<plugin_options::plugin> >
+{
+private:
+ using plugin_list = std::list<plugin_options::plugin>;
+
+public:
+ static int get(lua_State *L)
+ {
+ plugin_options_plugins &self(get_self(L));
+ char const *const name(stack::unqualified_get<char const *>(L));
+ auto const found(std::find_if(
+ self.options.plugins().begin(),
+ self.options.plugins().end(),
+ [&name] (plugin_options::plugin const &p) { return p.m_name == name; }));
+ if (self.options.plugins().end() != found)
+ return stack::push_reference(L, *found);
+ else
+ return stack::push(L, lua_nil);
+ }
+
+ static int index_get(lua_State *L)
+ {
+ return get(L);
+ }
+};
+
} // namespace sol
@@ -421,7 +463,7 @@ sol::object lua_engine::call_plugin(const std::string &name, sol::object in)
else
return res.get<sol::object>();
}
- return sol::make_object(sol(), sol::lua_nil);
+ return sol::lua_nil;
}
void lua_engine::menu_populate(const std::string &menu, std::vector<std::tuple<std::string, std::string, std::string>> &menu_list)
@@ -734,15 +776,15 @@ void lua_engine::initialize()
emu["print_info"] = [] (const char *str) { osd_printf_info("%s\n", str); };
emu["print_debug"] = [] (const char *str) { osd_printf_debug("%s\n", str); };
emu["driver_find"] =
- [this] (const char *driver) -> sol::object
+ [] (sol::this_state s, const char *driver) -> sol::object
{
const int i = driver_list::find(driver);
if (i < 0)
- return sol::make_object(sol(), sol::lua_nil);
- return sol::make_object(sol(), driver_list::driver(i));
+ return sol::lua_nil;
+ return sol::make_object(s, driver_list::driver(i));
};
emu["wait"] = lua_CFunction(
- [](lua_State *L)
+ [] (lua_State *L)
{
lua_engine *engine = mame_machine_manager::instance()->lua();
luaL_argcheck(L, lua_isnumber(L, 1), 1, "waiting duration expected");
@@ -844,26 +886,26 @@ void lua_engine::initialize()
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 {
+ [this] (emu_file &file, s64 offset, int whence) -> sol::object {
if(file.seek(offset, whence))
- return sol::make_object(sol(), sol::lua_nil);
+ return sol::lua_nil;
else
return sol::make_object(sol(), file.tell());
},
[this](emu_file &file, const char* whence) -> sol::object {
int wval = s_seek_parser(whence);
if(wval < 0 || wval >= 3)
- return sol::make_object(sol(), sol::lua_nil);
+ return sol::lua_nil;
if(file.seek(0, wval))
- return sol::make_object(sol(), sol::lua_nil);
+ return sol::lua_nil;
return sol::make_object(sol(), file.tell());
},
[this](emu_file &file, const char* whence, s64 offset) -> sol::object {
int wval = s_seek_parser(whence);
if(wval < 0 || wval >= 3)
- return sol::make_object(sol(), sol::lua_nil);
+ return sol::lua_nil;
if(file.seek(offset, wval))
- return sol::make_object(sol(), sol::lua_nil);
+ return sol::lua_nil;
return sol::make_object(sol(), file.tell());
}));
file_type.set("size", &emu_file::size);
@@ -971,7 +1013,7 @@ void lua_engine::initialize()
item_type.set("count", sol::readonly(&save_item::count));
item_type.set("read", [this](save_item &item, int offset) -> sol::object {
if(!item.base || (offset >= item.count))
- return sol::make_object(sol(), sol::lua_nil);
+ return sol::lua_nil;
const void *const data = reinterpret_cast<const uint8_t *>(item.base) + (item.stride * (offset / item.valcount));
uint64_t ret = 0;
switch(item.size)
@@ -1157,7 +1199,7 @@ void lua_engine::initialize()
},
[this](core_options::entry &e) -> sol::object {
if (e.type() == core_options::option_type::INVALID)
- return sol::make_object(sol(), sol::lua_nil);
+ return sol::lua_nil;
switch(e.type())
{
case core_options::option_type::BOOLEAN:
@@ -1177,53 +1219,17 @@ void lua_engine::initialize()
core_options_entry_type.set("has_range", &core_options::entry::has_range);
-/* running_machine library
- *
- * manager:machine()
- *
- * machine:exit() - close program
- * machine:hard_reset() - hard reset emulation
- * machine:soft_reset() - soft reset emulation
- * machine:save(filename) - save state to filename
- * machine:load(filename) - load state from filename
- * machine:buffer_save() - return save state buffer as binary string
- * machine:buffer_load(str) - load state from binary string buffer. returns true on success, otherwise nil
- * machine:popmessage(str) - print str as popup
- * machine:popmessage() - clear displayed popup message
- * machine:logerror(str) - print str to log
- *
- * machine:system() - get game_driver for running driver
- * machine:video() - get video_manager
- * machine:sound() - get sound_manager
- * machine:render() - get render_manager
- * machine:ioport() - get ioport_manager
- * machine:parameters() - get parameter_manager
- * machine:memory() - get memory_manager
- * machine:options() - get machine emu_options
- * machine:outputs() - get output_manager
- * machine:input() - get input_manager
- * machine:uiinput() - get ui_input_manager
- * machine:debugger() - get debugger_manager
- *
- * machine.paused - get paused state
- * machine.samplerate - get audio sample rate
- * machine.exit_pending
- * machine.hard_reset_pending
- *
- * machine.devices[] - get device table (k=tag, v=device_t)
- * machine.screens[] - get screens table (k=tag, v=screen_device)
- * machine.images[] - get available image devices table (k=type, v=device_image_interface)
- */
-
auto machine_type = sol().registry().new_usertype<running_machine>("machine", sol::no_constructor);
machine_type["exit"] = &running_machine::schedule_exit;
machine_type["hard_reset"] = &running_machine::schedule_hard_reset;
machine_type["soft_reset"] = &running_machine::schedule_soft_reset;
- machine_type["save"] = &running_machine::schedule_save;
- machine_type["load"] = &running_machine::schedule_load;
+ machine_type["save"] = &running_machine::schedule_save; // TODO: some kind of completion notification?
+ machine_type["load"] = &running_machine::schedule_load; // TODO: some kind of completion notification?
machine_type["buffer_save"] =
[] (running_machine &m, sol::this_state s)
{
+ // FIXME: this needs to schedule saving to a buffer and return asynchronously somehow
+ // right now it's broken by anonymous timers, synchronize, etc.
lua_State *L = s;
luaL_Buffer buff;
int size = ram_state::get_size(m.save());
@@ -1240,37 +1246,47 @@ void lua_engine::initialize()
machine_type["buffer_load"] =
[] (running_machine &m, sol::this_state s, std::string str)
{
- lua_State *L = s;
+ // FIXME: this needs to schedule loading from the buffer and return asynchronously somehow
+ // right now it's broken by anonymous timers, synchronize, etc.
save_error error = m.save().read_buffer((u8 *)str.data(), str.size());
if (error == STATERR_NONE)
+ {
return true;
+ }
else
{
- luaL_error(L,"State load error.");
+ luaL_error(s,"State load error.");
return false;
}
};
- machine_type["popmessage"] = sol::overload(
- [](running_machine &m, const char *str) { m.popmessage("%s", str); },
- [](running_machine &m) { m.popmessage(); });
- machine_type["system"] = &running_machine::system;
- machine_type["video"] = &running_machine::video;
- machine_type["sound"] = &running_machine::sound;
- machine_type["render"] = &running_machine::render;
- machine_type["ioport"] = &running_machine::ioport;
- machine_type["parameters"] = &running_machine::parameters;
- machine_type["memory"] = &running_machine::memory;
- machine_type["options"] = &running_machine::options;
- machine_type["outputs"] = &running_machine::output;
- machine_type["input"] = &running_machine::input;
- machine_type["uiinput"] = &running_machine::ui_input;
- machine_type["debugger"] =
- [this] (running_machine &m) -> sol::object
+ machine_type["popmessage"] =
+ [] (running_machine &m, const char *str)
{
- if (!(m.debug_flags & DEBUG_FLAG_ENABLED))
- return sol::make_object(sol(), sol::lua_nil);
- return sol::make_object(sol(), &m.debugger());
+ if (str)
+ m.popmessage("%s", str);
+ else
+ m.popmessage();
};
+ machine_type["logerror"] = [] (running_machine &m, std::string const *str) { m.logerror("[luaengine] %s\n", str); };
+ machine_type["system"] = sol::property(&running_machine::system);
+ machine_type["video"] = sol::property(&running_machine::video);
+ machine_type["sound"] = sol::property(&running_machine::sound);
+ machine_type["render"] = sol::property(&running_machine::render);
+ machine_type["ioport"] = sol::property(&running_machine::ioport);
+ machine_type["parameters"] = sol::property(&running_machine::parameters);
+ machine_type["memory"] = sol::property(&running_machine::memory);
+ machine_type["options"] = sol::property(&running_machine::options);
+ machine_type["output"] = sol::property(&running_machine::output);
+ machine_type["input"] = sol::property(&running_machine::input);
+ machine_type["uiinput"] = sol::property(&running_machine::ui_input);
+ machine_type["debugger"] = sol::property(
+ [] (running_machine &m, sol::this_state s) -> sol::object
+ {
+ if (m.debug_flags & DEBUG_FLAG_ENABLED)
+ return sol::make_object(s, &m.debugger());
+ else
+ return sol::lua_nil;
+ });
machine_type["paused"] = sol::property(&running_machine::paused);
machine_type["samplerate"] = sol::property(&running_machine::sample_rate);
machine_type["exit_pending"] = sol::property(&running_machine::exit_pending);
@@ -1280,47 +1296,21 @@ void lua_engine::initialize()
machine_type["cassettes"] = sol::property([] (running_machine &m) { return devenum<cassette_device_enumerator>(m.root_device()); });
machine_type["images"] = sol::property([] (running_machine &m) { return devenum<image_interface_enumerator>(m.root_device()); });
machine_type["slots"] = sol::property([](running_machine &m) { return devenum<slot_interface_enumerator>(m.root_device()); });
- machine_type["logerror"] = [] (running_machine &m, const char *str) { m.logerror("[luaengine] %s\n", str); };
-
-/* game_driver library
- *
- * emu.driver_find(driver_name)
- *
- * driver.source_file - relative path to the source file
- * driver.parent
- * driver.name
- * driver.description
- * driver.year
- * driver.manufacturer
- * driver.compatible_with
- * driver.default_layout
- * driver.orientation - screen rotation degree (rot0/90/180/270)
- * driver.type - machine type (arcade/console/computer/other)
- * driver.not_working - not considered working
- * driver.supports_save - supports save states
- * driver.no_cocktail - screen flip support is missing
- * driver.is_bios_root - this driver entry is a BIOS root
- * driver.requires_artwork - requires external artwork for key game elements
- * driver.clickable_artwork - artwork is clickable and requires mouse cursor
- * driver.unofficial - unofficial hardware modification
- * driver.no_sound_hw - system has no sound output
- * driver.mechanical - contains mechanical parts (pinball, redemption games, ...)
- * driver.is_incomplete - official system with blatantly incomplete hardware/software
- */
auto game_driver_type = sol().registry().new_usertype<game_driver>("game_driver", sol::no_constructor);
- game_driver_type["source_file"] = sol::property([] (game_driver const &driver) { return &driver.type.source()[0]; });
- game_driver_type["parent"] = sol::readonly(&game_driver::parent);
game_driver_type["name"] = sol::property([] (game_driver const &driver) { return &driver.name[0]; });
game_driver_type["description"] = sol::property([] (game_driver const &driver) { return &driver.type.fullname()[0]; });
game_driver_type["year"] = sol::readonly(&game_driver::year);
game_driver_type["manufacturer"] = sol::readonly(&game_driver::manufacturer);
- game_driver_type["compatible_with"] = sol::readonly(&game_driver::compatible_with);
- game_driver_type["default_layout"] = sol::readonly(&game_driver::default_layout);
+ game_driver_type["parent"] = sol::readonly(&game_driver::parent);
+ game_driver_type["compatible_with"] = sol::property([] (game_driver const &driver) { return strcmp(driver.compatible_with, "0") ? driver.compatible_with : nullptr; });
+ game_driver_type["source_file"] = sol::property([] (game_driver const &driver) { return &driver.type.source()[0]; });
game_driver_type["orientation"] = sol::property(
[] (game_driver const &driver)
{
+ // FIXME: this works differently to the screen orientation function and the render target orientation property
+ // it should probably be made consistent with one of them
std::string rot;
switch (driver.flags & machine_flags::MASK_ORIENTATION)
{
@@ -1343,8 +1333,10 @@ void lua_engine::initialize()
return rot;
});
game_driver_type["type"] = sol::property(
- [](game_driver const &driver)
+ [] (game_driver const &driver)
{
+ // FIXME: this shouldn't be called type - there's potendial for confusion with the device type
+ // also, this should eventually go away in favour of richer flags
std::string type;
switch (driver.flags & machine_flags::MASK_TYPE)
{
@@ -1384,6 +1376,7 @@ void lua_engine::initialize()
device_type["ioport"] = &device_t::ioport;
device_type["subdevice"] = static_cast<device_t *(device_t::*)(char const *) const>(&device_t::subdevice);
device_type["siblingdevice"] = static_cast<device_t *(device_t::*)(char const *) const>(&device_t::siblingdevice);
+ device_type["parameter"] = &device_t::parameter;
device_type["tag"] = sol::property(&device_t::tag);
device_type["basetag"] = sol::property(&device_t::basetag);
device_type["name"] = sol::property(&device_t::name);
@@ -1392,11 +1385,11 @@ void lua_engine::initialize()
device_type["configured"] = sol::property(&device_t::configured);
device_type["started"] = sol::property(&device_t::started);
device_type["debug"] = sol::property(
- [this] (device_t &dev) -> sol::object
+ [] (device_t &dev, sol::this_state s) -> sol::object
{
- if (!(dev.machine().debug_flags & DEBUG_FLAG_ENABLED) || !dynamic_cast<cpu_device *>(&dev)) // debugger not enabled or not cpu
- return sol::make_object(sol(), sol::lua_nil);
- return sol::make_object(sol(), dev.debug());
+ if (!(dev.machine().debug_flags & DEBUG_FLAG_ENABLED) || !dynamic_cast<cpu_device *>(&dev)) // debugger not enabled or not CPU
+ return sol::lua_nil;
+ return sol::make_object(s, dev.debug());
});
device_type["spaces"] = sol::property(
[this] (device_t &dev)
@@ -1513,6 +1506,8 @@ void lua_engine::initialize()
screen_dev_type["snapshot"] =
[this] (screen_device &sdev, char const *filename) -> sol::object
{
+ // FIXME: this shouldn't be a member of the screen device
+ // the screen is only used as a hint when configured for native snapshots and may be ignored
std::string snapstr;
bool is_absolute_path = false;
if (filename)
@@ -1534,20 +1529,20 @@ void lua_engine::initialize()
// and save the snapshot
machine().video().save_snapshot(&sdev, file);
- return sol::make_object(sol(), sol::lua_nil);
+ return sol::lua_nil;
};
screen_dev_type["pixel"] = [] (screen_device &sdev, s32 x, s32 y) { return sdev.pixel(x, y); };
screen_dev_type["pixels"] =
[] (screen_device &sdev, sol::this_state s)
{
- lua_State *L = s;
+ // TODO: would be better if this could return a tuple of (buffer, width, height)
const rectangle &visarea = sdev.visible_area();
luaL_Buffer buff;
int size = visarea.height() * visarea.width() * 4;
- u32 *ptr = (u32 *)luaL_buffinitsize(L, &buff, size);
+ u32 *ptr = (u32 *)luaL_buffinitsize(s, &buff, size);
sdev.pixels(ptr);
luaL_pushresultsize(&buff, size);
- return sol::make_reference(L, sol::stack_reference(L, -1));
+ return sol::make_reference(s, sol::stack_reference(s, -1));
};
screen_dev_type["screen_type"] = sol::property(&screen_device::screen_type);
screen_dev_type["width"] = sol::property([] (screen_device &sdev) { return sdev.visible_area().width(); });
@@ -1664,147 +1659,103 @@ void lua_engine::initialize()
dislot_option_type["clock"] = sol::property(static_cast<u32 (device_slot_interface::slot_option::*)() const>(&device_slot_interface::slot_option::clock));
-/* parameters_manager library
- *
- * manager:machine():parameters()
- *
- * parameters:add(tag, val) - add tag = val parameter
- * parameters:lookup(tag) - get val for tag
- */
-
- auto parameters_type = sol().registry().new_usertype<parameters_manager>("parameters", "new", sol::no_constructor);
+ auto parameters_type = sol().registry().new_usertype<parameters_manager>("parameters", sol::no_constructor);
parameters_type["add"] = &parameters_manager::add;
parameters_type["lookup"] = &parameters_manager::lookup;
-/* video_manager library
- *
- * manager:machine():video()
- *
- * video:begin_recording([opt] filename, [opt] format) - start AVI recording to filename if given or default
- * video:end_recording() - stop AVI recording
- * video:is_recording() - get recording status
- * video:snapshot() - save shot of all screens
- * video:skip_this_frame() - is current frame going to be skipped
- * video:speed_factor() - get speed factor
- * video:speed_percent() - get percent from realtime
- * video:frame_update() - render a frame
- * video:size() - get width and height of snapshot bitmap in pixels
- * video:pixels() - get binary bitmap of all screens as string
- *
- * video.frameskip - current frameskip
- * video.throttled - throttle state
- * video.throttle_rate - throttle rate
- */
-
- auto video_type = sol().registry().new_usertype<video_manager>("video", "new", sol::no_constructor);
- video_type.set("begin_recording", sol::overload(
- [this](video_manager &vm, const char *filename, const char *format_string) {
- std::string fn = process_snapshot_filename(machine(), filename);
- movie_recording::format format = s_movie_recording_format_parser(format_string);
- vm.begin_recording(fn.c_str(), format);
- },
- [this](video_manager &vm, const char *filename) {
- std::string fn = process_snapshot_filename(machine(), filename);
- vm.begin_recording(fn.c_str(), movie_recording::format::AVI);
- },
- [](video_manager &vm) {
- vm.begin_recording(nullptr, movie_recording::format::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_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) {
+ auto video_type = sol().registry().new_usertype<video_manager>("video", sol::no_constructor);
+ video_type["frame_update"] = [] (video_manager &vm) { vm.frame_update(true); };
+ video_type["snapshot"] = &video_manager::save_active_screen_snapshots;
+ video_type["begin_recording"] =
+ [this] (video_manager &vm, const char *filename, const char *format_string)
+ {
+ // FIXME: the filename substitution shouldn't be done here
+ std::string fn;
+ movie_recording::format format = movie_recording::format::AVI;
+ if (filename)
+ fn = process_snapshot_filename(machine(), filename);
+ if (format_string)
+ format = s_movie_recording_format_parser(format_string);
+ vm.begin_recording(filename ? fn.c_str() : nullptr, format);
+ };
+ video_type["end_recording"] = &video_manager::end_recording;
+ video_type["snapshot_size"] =
+ [] (video_manager &vm)
+ {
s32 width, height;
vm.compute_snapshot_size(width, height);
- return std::tuple<s32, s32>(width, height);
- });
- video_type.set("pixels", [](video_manager &vm, sol::this_state s) {
- lua_State *L = s;
- luaL_Buffer buff;
+ return std::make_tuple(width, height);
+ };
+ video_type["snapshot_pixels"] =
+ [] (video_manager &vm, sol::this_state s)
+ {
+ // TODO: would be better if this could return a tuple of (buffer, width, height)
s32 width, height;
vm.compute_snapshot_size(width, height);
int size = width * height * 4;
- u32 *ptr = (u32 *)luaL_buffinitsize(L, &buff, size);
+ luaL_Buffer buff;
+ u32 *ptr = (u32 *)luaL_buffinitsize(s, &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));
-
-
-/* sound_manager library
- *
- * manager:machine():sound()
- *
- * sound:start_recording() - begin audio recording
- * sound:stop_recording() - end audio recording
- * sound:ui_mute(turn_off) - turns on/off UI sound
- * sound:system_mute() - turns on/off system sound
- * sound:samples() - get current audio buffer contents in binary form as string (updates 50 times per second)
- *
- * sound.attenuation - sound attenuation
- */
-
- auto sound_type = sol().registry().new_usertype<sound_manager>("sound", "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;
+ return sol::make_reference(s, sol::stack_reference(s, -1));
+ };
+ video_type["speed_factor"] = sol::property(&video_manager::speed_factor);
+ video_type["throttled"] = sol::property(&video_manager::throttled, &video_manager::set_throttled);
+ video_type["throttle_rate"] = sol::property(&video_manager::throttle_rate, &video_manager::set_throttle_rate);
+ video_type["frameskip"] = sol::property(&video_manager::frameskip, &video_manager::set_frameskip);
+ video_type["speed_percent"] = sol::property(&video_manager::speed_percent);
+ video_type["effective_frameskip"] = sol::property(&video_manager::effective_frameskip);
+ video_type["skip_this_frame"] = sol::property(&video_manager::skip_this_frame);
+ video_type["snap_native"] = sol::property(&video_manager::snap_native);
+ video_type["is_recording"] = sol::property(&video_manager::is_recording);
+ video_type["snapshot_target"] = sol::property(&video_manager::snapshot_target);
+
+
+ auto sound_type = sol().registry().new_usertype<sound_manager>("sound", sol::no_constructor);
+ sound_type["start_recording"] =
+ [] (sound_manager &sm, char const *filename)
+ {
+ return filename ? sm.start_recording(filename) : sm.start_recording();
+ };
+ sound_type["stop_recording"] = &sound_manager::stop_recording;
+ sound_type["get_samples"] =
+ [] (sound_manager &sm, sol::this_state 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);
+ s32 const count = sm.sample_count() * 2 * 2; // 2 channels, 2 bytes per sample
+ s16 *const ptr = (s16 *)luaL_buffinitsize(s, &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));
-
-
-/* mame_ui_manager library
- *
- * manager:ui()
- *
- * ui:is_menu_active() - ui menu state
- * ui:options() - ui core_options
- * ui:get_line_height() - current ui font height
- * ui:get_string_width(str, scale) - get str width with ui font at scale factor of current font size
- * ui:get_char_width(char) - get width of utf8 glyph char with ui font
- * ui:set_aggressive_input_focus(bool)
- *
- * ui.single_step
- * ui.show_fps - fps display enabled
- * ui.show_profiler - profiler display enabled
- */
-
- auto ui_type = sol().registry().new_usertype<mame_ui_manager>("ui", "new", sol::no_constructor);
- ui_type.set("is_menu_active", &mame_ui_manager::is_menu_active);
- ui_type.set("options", [](mame_ui_manager &m) { return static_cast<core_options *>(&m.options()); });
- ui_type.set("show_fps", sol::property(&mame_ui_manager::show_fps, &mame_ui_manager::set_show_fps));
- ui_type.set("show_profiler", sol::property(&mame_ui_manager::show_profiler, &mame_ui_manager::set_show_profiler));
- ui_type.set("single_step", sol::property(&mame_ui_manager::single_step, &mame_ui_manager::set_single_step));
- ui_type.set("get_line_height", &mame_ui_manager::get_line_height);
- ui_type.set("get_string_width", &mame_ui_manager::get_string_width);
+ return sol::make_reference(s, sol::stack_reference(s, -1));
+ };
+ sound_type["muted"] = sol::property(&sound_manager::muted);
+ sound_type["ui_mute"] = sol::property(
+ static_cast<bool (sound_manager::*)() const>(&sound_manager::ui_mute),
+ static_cast<void (sound_manager::*)(bool)>(&sound_manager::ui_mute));
+ sound_type["debugger_mute"] = sol::property(
+ static_cast<bool (sound_manager::*)() const>(&sound_manager::debugger_mute),
+ static_cast<void (sound_manager::*)(bool)>(&sound_manager::debugger_mute));
+ sound_type["system_mute"] = sol::property(
+ static_cast<bool (sound_manager::*)() const>(&sound_manager::system_mute),
+ static_cast<void (sound_manager::*)(bool)>(&sound_manager::system_mute));
+ sound_type["attenuation"] = sol::property(
+ &sound_manager::attenuation,
+ &sound_manager::set_attenuation);
+ sound_type["recording"] = sol::property(&sound_manager::is_recording);
+
+
+ auto ui_type = sol().registry().new_usertype<mame_ui_manager>("ui", sol::no_constructor);
// 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); });
+ ui_type["get_char_width"] = [] (mame_ui_manager &m, uint32_t utf8char) { return m.get_char_width(utf8char); };
+ ui_type["get_string_width"] = &mame_ui_manager::get_string_width;
+ ui_type["set_aggressive_input_focus"] = [](mame_ui_manager &m, bool aggressive_focus) { osd_set_aggressive_input_focus(aggressive_focus); };
+ ui_type["options"] = sol::property([] (mame_ui_manager &m) { return static_cast<core_options *>(&m.options()); });
+ ui_type["line_height"] = sol::property(&mame_ui_manager::get_line_height);
+ ui_type["menu_active"] = sol::property(&mame_ui_manager::is_menu_active);
+ ui_type["single_step"] = sol::property(&mame_ui_manager::single_step, &mame_ui_manager::set_single_step);
+ ui_type["show_fps"] = sol::property(&mame_ui_manager::show_fps, &mame_ui_manager::set_show_fps);
+ ui_type["show_profiler"] = sol::property(&mame_ui_manager::show_profiler, &mame_ui_manager::set_show_profiler);
/* device_state_entry library
@@ -1861,64 +1812,40 @@ void lua_engine::initialize()
rom_entry_type.set("flags", &rom_entry::get_flags);
-/* output_manager library
- *
- * manager:machine():outputs()
- *
- * outputs:set_value(name, val) - set output name to val
- * outputs:set_indexed_value(index, val) - set output index to val
- * outputs:get_value(name) - get output name value
- * outputs:get_indexed_value(index) - get output index value
- * outputs:name_to_id(name) - get index for name
- * outputs:id_to_name(index) - get name for index
- */
-
- auto output_type = sol().registry().new_usertype<output_manager>("output", "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) {
+ auto output_type = sol().registry().new_usertype<output_manager>("output", sol::no_constructor);
+ output_type["set_value"] = &output_manager::set_value;
+ output_type["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) {
+ };
+ output_type["get_value"] = &output_manager::get_value;
+ output_type["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);
-
+ };
+ output_type["name_to_id"] = &output_manager::name_to_id;
+ output_type["id_to_name"] = &output_manager::id_to_name;
-/* mame_machine_manager library
- *
- * manager
- * mame_manager - alias of manager
- *
- * manager:machine() - running machine
- * manager:options() - emu options
- * manager:plugins() - plugin options
- * manager:ui() - mame ui manager
- */
- sol().registry().new_usertype<mame_machine_manager>("manager", "new", sol::no_constructor,
- "machine", &machine_manager::machine,
- "options", &machine_manager::options,
- "plugins", [this](mame_machine_manager &m) {
- sol::table table = sol().create_table();
- for (auto &curentry : m.plugins().plugins())
- {
- sol::table plugin_table = sol().create_table();
- plugin_table["name"] = curentry.m_name;
- plugin_table["description"] = curentry.m_description;
- plugin_table["type"] = curentry.m_type;
- plugin_table["directory"] = curentry.m_directory;
- plugin_table["start"] = curentry.m_start;
- table[curentry.m_name] = plugin_table;
- }
- return table;
- },
- "ui", &mame_machine_manager::ui);
+ auto mame_manager_type = sol().registry().new_usertype<mame_machine_manager>("manager", sol::no_constructor);
+ mame_manager_type["machine"] = sol::property(&mame_machine_manager::machine);
+ mame_manager_type["ui"] = sol::property(&mame_machine_manager::ui);
+ mame_manager_type["options"] = sol::property(&mame_machine_manager::options);
+ mame_manager_type["plugins"] = sol::property([] (mame_machine_manager &m) { return plugin_options_plugins(m.plugins()); });
sol()["manager"] = std::ref(*mame_machine_manager::instance());
sol()["mame_manager"] = std::ref(*mame_machine_manager::instance());
+ auto plugin_type = sol().registry().new_usertype<plugin_options::plugin>("plugin", sol::no_constructor);
+ plugin_type["name"] = sol::readonly(&plugin_options::plugin::m_name);
+ plugin_type["description"] = sol::readonly(&plugin_options::plugin::m_description);
+ plugin_type["type"] = sol::readonly(&plugin_options::plugin::m_type);
+ plugin_type["directory"] = sol::readonly(&plugin_options::plugin::m_directory);
+ plugin_type["start"] = sol::readonly(&plugin_options::plugin::m_start);
+
+
// set up other user types
initialize_debug(emu);
initialize_input(emu);
diff --git a/src/frontend/mame/luaengine_debug.cpp b/src/frontend/mame/luaengine_debug.cpp
index 7297a7f82a3..e3817d95ced 100644
--- a/src/frontend/mame/luaengine_debug.cpp
+++ b/src/frontend/mame/luaengine_debug.cpp
@@ -29,24 +29,25 @@ struct wrap_textbuf
};
-sol::object do_breakpoint_enable(lua_State *L, device_debug &dev, sol::object &index, bool enable)
+template <bool Enable>
+sol::object do_breakpoint_enable(device_debug &dev, sol::this_state s, sol::object index)
{
if (index == sol::lua_nil)
{
- dev.breakpoint_enable_all(enable);
+ dev.breakpoint_enable_all(Enable);
dev.device().machine().debug_view().update_all(DVT_DISASSEMBLY);
dev.device().machine().debug_view().update_all(DVT_BREAK_POINTS);
return sol::lua_nil;
}
else if (index.is<int>())
{
- bool result(dev.breakpoint_enable(index.as<int>(), enable));
+ bool result(dev.breakpoint_enable(index.as<int>(), Enable));
if (result)
{
dev.device().machine().debug_view().update_all(DVT_DISASSEMBLY);
dev.device().machine().debug_view().update_all(DVT_BREAK_POINTS);
}
- return sol::make_object(L, result);
+ return sol::make_object(s, result);
}
else
{
@@ -56,20 +57,21 @@ sol::object do_breakpoint_enable(lua_State *L, device_debug &dev, sol::object &i
}
-sol::object do_watchpoint_enable(lua_State *L, device_debug &dev, sol::object &index, bool enable)
+template <bool Enable>
+sol::object do_watchpoint_enable(device_debug &dev, sol::this_state s, sol::object index)
{
if (index == sol::lua_nil)
{
- dev.watchpoint_enable_all(enable);
+ dev.watchpoint_enable_all(Enable);
dev.device().machine().debug_view().update_all(DVT_WATCH_POINTS);
return sol::lua_nil;
}
else if (index.is<int>())
{
- bool result(dev.watchpoint_enable(index.as<int>(), enable));
+ bool result(dev.watchpoint_enable(index.as<int>(), Enable));
if (result)
dev.device().machine().debug_view().update_all(DVT_WATCH_POINTS);
- return sol::make_object(L, result);
+ return sol::make_object(s, result);
}
else
{
@@ -162,8 +164,8 @@ void lua_engine::initialize_debug(sol::table &emu)
dev.device().machine().debug_view().update_all(DVT_DISASSEMBLY);
dev.device().machine().debug_view().update_all(DVT_BREAK_POINTS);
});
- device_debug_type["bpenable"] = [this] (device_debug &dev, sol::object index) { return do_breakpoint_enable(sol(), dev, index, true); };
- device_debug_type["bpdisable"] = [this] (device_debug &dev, sol::object index) { return do_breakpoint_enable(sol(), dev, index, false); };
+ device_debug_type["bpenable"] = &do_breakpoint_enable<true>;
+ device_debug_type["bpdisable"] = &do_breakpoint_enable<false>;
device_debug_type["bplist"] =
[this] (device_debug &dev)
{
@@ -193,8 +195,8 @@ void lua_engine::initialize_debug(sol::table &emu)
dev.watchpoint_clear_all();
dev.device().machine().debug_view().update_all(DVT_WATCH_POINTS);
});
- device_debug_type["wpenable"] = [this] (device_debug &dev, sol::object index) { return do_watchpoint_enable(sol(), dev, index, true); };
- device_debug_type["wpdisable"] = [this] (device_debug &dev, sol::object index) { return do_watchpoint_enable(sol(), dev, index, false); };
+ device_debug_type["wpenable"] = &do_watchpoint_enable<true>;
+ device_debug_type["wpdisable"] = &do_watchpoint_enable<false>;
device_debug_type["wplist"] =
[this] (device_debug &dev, addr_space &sp)
{
diff --git a/src/frontend/mame/luaengine_render.cpp b/src/frontend/mame/luaengine_render.cpp
index b910a717561..8a84fcc4e82 100644
--- a/src/frontend/mame/luaengine_render.cpp
+++ b/src/frontend/mame/luaengine_render.cpp
@@ -348,12 +348,12 @@ void lua_engine::initialize_render(sol::table &emu)
}
};
layout_view_item_type["id"] = sol::property(
- [this] (layout_view::item &i) -> sol::object
+ [] (layout_view::item &i, sol::this_state s) -> sol::object
{
if (i.id().empty())
- return sol::make_object(sol(), sol::lua_nil);
+ return sol::lua_nil;
else
- return sol::make_object(sol(), i.id());
+ return sol::make_object(s, i.id());
});
layout_view_item_type["bounds_animated"] = sol::property(&layout_view::item::bounds_animated);
layout_view_item_type["color_animated"] = sol::property(&layout_view::item::color_animated);
diff --git a/src/frontend/mame/mame.cpp b/src/frontend/mame/mame.cpp
index a461a08b7e6..f48cbd46563 100644
--- a/src/frontend/mame/mame.cpp
+++ b/src/frontend/mame/mame.cpp
@@ -166,7 +166,7 @@ void mame_machine_manager::start_luaengine()
// process includes
for (const std::string &incl : split(options().plugin(), ','))
{
- plugin *p = m_plugins->find(incl);
+ plugin_options::plugin *p = m_plugins->find(incl);
if (!p)
fatalerror("Fatal error: Could not load plugin: %s\n", incl);
p->m_start = true;
@@ -175,7 +175,7 @@ void mame_machine_manager::start_luaengine()
// process excludes
for (const std::string &excl : split(options().no_plugin(), ','))
{
- plugin *p = m_plugins->find(excl);
+ plugin_options::plugin *p = m_plugins->find(excl);
if (!p)
fatalerror("Fatal error: Unknown plugin: %s\n", excl);
p->m_start = false;
@@ -185,7 +185,7 @@ void mame_machine_manager::start_luaengine()
// we have a special way to open the console plugin
if (options().console())
{
- plugin *p = m_plugins->find(OPTION_CONSOLE);
+ plugin_options::plugin *p = m_plugins->find(OPTION_CONSOLE);
if (!p)
fatalerror("Fatal error: Console plugin not found.\n");
diff --git a/src/frontend/mame/pluginopts.cpp b/src/frontend/mame/pluginopts.cpp
index 3828be3c8cd..2dda2062064 100644
--- a/src/frontend/mame/pluginopts.cpp
+++ b/src/frontend/mame/pluginopts.cpp
@@ -107,7 +107,7 @@ bool plugin_options::load_plugin(const std::string &path)
// find
//-------------------------------------------------
-plugin *plugin_options::find(const std::string &name)
+plugin_options::plugin *plugin_options::find(const std::string &name)
{
auto iter = std::find_if(
m_plugins.begin(),
@@ -139,7 +139,7 @@ static core_options create_core_options(const plugin_options &plugin_opts)
opts.add_entries(s_option_entries);
// create an entry for each option
- for (const plugin &p : plugin_opts.plugins())
+ for (const plugin_options::plugin &p : plugin_opts.plugins())
{
opts.add_entry(
{ p.m_name },
diff --git a/src/frontend/mame/pluginopts.h b/src/frontend/mame/pluginopts.h
index 3565f5d9e78..41c688b2ab6 100644
--- a/src/frontend/mame/pluginopts.h
+++ b/src/frontend/mame/pluginopts.h
@@ -17,23 +17,20 @@
#include <string>
-// ======================> plugin
-
-struct plugin
-{
- std::string m_name;
- std::string m_description;
- std::string m_type;
- std::string m_directory;
- bool m_start;
-};
-
-
// ======================> plugin_options
class plugin_options
{
public:
+ struct plugin
+ {
+ std::string m_name;
+ std::string m_description;
+ std::string m_type;
+ std::string m_directory;
+ bool m_start;
+ };
+
plugin_options();
// accessors
diff --git a/src/frontend/mame/ui/miscmenu.cpp b/src/frontend/mame/ui/miscmenu.cpp
index dc5cc2ba9a3..b9b55264ca4 100644
--- a/src/frontend/mame/ui/miscmenu.cpp
+++ b/src/frontend/mame/ui/miscmenu.cpp
@@ -886,7 +886,7 @@ void menu_plugins_configure::handle()
{
if (menu_event->iptkey == IPT_UI_LEFT || menu_event->iptkey == IPT_UI_RIGHT || menu_event->iptkey == IPT_UI_SELECT)
{
- plugin *p = plugins.find((const char*)menu_event->itemref);
+ plugin_options::plugin *p = plugins.find((const char*)menu_event->itemref);
if (p)
{
p->m_start = !p->m_start;
diff --git a/src/frontend/mame/ui/ui.cpp b/src/frontend/mame/ui/ui.cpp
index 1273c5e92df..7ba294c446c 100644
--- a/src/frontend/mame/ui/ui.cpp
+++ b/src/frontend/mame/ui/ui.cpp
@@ -1381,7 +1381,7 @@ uint32_t mame_ui_manager::handler_ingame(render_container &container)
// toggle throttle?
if (machine().ui_input().pressed(IPT_UI_THROTTLE))
- machine().video().toggle_throttle();
+ machine().video().set_throttled(!machine().video().throttled());
// check for fast forward
if (machine().ioport().type_pressed(IPT_UI_FAST_FORWARD))