mirror of
https://github.com/holub/mame
synced 2025-06-30 07:58:56 +03:00
Merge pull request #5438 from npwoods/lua_manadatory_file_manager_override_changes
Changed mechanisms for overriding the mandatory file manager
This commit is contained in:
commit
43fc80c5aa
@ -193,7 +193,6 @@ const options_entry emu_options::s_option_entries[] =
|
||||
{ OPTION_BIOS, nullptr, OPTION_STRING, "select the system BIOS to use" },
|
||||
{ OPTION_CHEAT ";c", "0", OPTION_BOOLEAN, "enable cheat subsystem" },
|
||||
{ OPTION_SKIP_GAMEINFO, "0", OPTION_BOOLEAN, "skip displaying the system information screen at startup" },
|
||||
{ OPTION_SKIP_MANDATORY_FILEMAN, "0", OPTION_BOOLEAN, "skip prompting the user for any mandatory images with the file manager at startup" },
|
||||
{ OPTION_UI_FONT, "default", OPTION_STRING, "specify a font to use" },
|
||||
{ OPTION_UI, "cabinet", OPTION_STRING, "type of UI (simple|cabinet)" },
|
||||
{ OPTION_RAMSIZE ";ram", nullptr, OPTION_STRING, "size of RAM (if supported by driver)" },
|
||||
|
@ -162,7 +162,6 @@
|
||||
#define OPTION_BIOS "bios"
|
||||
#define OPTION_CHEAT "cheat"
|
||||
#define OPTION_SKIP_GAMEINFO "skip_gameinfo"
|
||||
#define OPTION_SKIP_MANDATORY_FILEMAN "skip_mandatory_fileman"
|
||||
#define OPTION_UI_FONT "uifont"
|
||||
#define OPTION_UI "ui"
|
||||
#define OPTION_RAMSIZE "ramsize"
|
||||
@ -438,7 +437,6 @@ public:
|
||||
const char *bios() const { return value(OPTION_BIOS); }
|
||||
bool cheat() const { return bool_value(OPTION_CHEAT); }
|
||||
bool skip_gameinfo() const { return bool_value(OPTION_SKIP_GAMEINFO); }
|
||||
bool skip_mandatory_fileman() const { return bool_value(OPTION_SKIP_MANDATORY_FILEMAN); }
|
||||
const char *ui_font() const { return value(OPTION_UI_FONT); }
|
||||
ui_option ui() const { return m_ui; }
|
||||
const char *ram_size() const { return value(OPTION_RAMSIZE); }
|
||||
|
@ -650,17 +650,23 @@ bool lua_engine::menu_callback(const std::string &menu, int index, const std::st
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool lua_engine::execute_function(const char *id)
|
||||
int lua_engine::enumerate_functions(const char *id, std::function<bool(const sol::protected_function &func)> &&callback)
|
||||
{
|
||||
int count = 0;
|
||||
sol::object functable = sol().registry()[id];
|
||||
if(functable.is<sol::table>())
|
||||
if (functable.is<sol::table>())
|
||||
{
|
||||
for(auto &func : functable.as<sol::table>())
|
||||
for (auto &func : functable.as<sol::table>())
|
||||
{
|
||||
if(func.second.is<sol::protected_function>())
|
||||
if (func.second.is<sol::protected_function>())
|
||||
{
|
||||
bool cont = callback(func.second.as<sol::protected_function>());
|
||||
count++;
|
||||
if (!cont)
|
||||
break;
|
||||
|
||||
auto ret = invoke(func.second.as<sol::protected_function>());
|
||||
if(!ret.valid())
|
||||
if (!ret.valid())
|
||||
{
|
||||
sol::error err = ret;
|
||||
osd_printf_error("[LUA ERROR] in execute_function: %s\n", err.what());
|
||||
@ -669,7 +675,22 @@ bool lua_engine::execute_function(const char *id)
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return count;
|
||||
}
|
||||
|
||||
bool lua_engine::execute_function(const char *id)
|
||||
{
|
||||
int count = enumerate_functions(id, [this](const sol::protected_function &func)
|
||||
{
|
||||
auto ret = invoke(func);
|
||||
if(!ret.valid())
|
||||
{
|
||||
sol::error err = ret;
|
||||
osd_printf_error("[LUA ERROR] in execute_function: %s\n", err.what());
|
||||
}
|
||||
return true;
|
||||
});
|
||||
return count > 0;
|
||||
}
|
||||
|
||||
void lua_engine::register_function(sol::function func, const char *id)
|
||||
@ -721,6 +742,27 @@ void lua_engine::on_periodic()
|
||||
execute_function("LUA_ON_PERIODIC");
|
||||
}
|
||||
|
||||
bool lua_engine::on_missing_mandatory_image(const std::string &instance_name)
|
||||
{
|
||||
bool handled = false;
|
||||
enumerate_functions("LUA_ON_MANDATORY_FILE_MANAGER_OVERRIDE", [this, &instance_name, &handled](const sol::protected_function &func)
|
||||
{
|
||||
auto ret = invoke(func, instance_name);
|
||||
|
||||
if(!ret.valid())
|
||||
{
|
||||
sol::error err = ret;
|
||||
osd_printf_error("[LUA ERROR] in on_missing_mandatory_image: %s\n", err.what());
|
||||
}
|
||||
else if (ret.get<bool>())
|
||||
{
|
||||
handled = true;
|
||||
}
|
||||
return !handled;
|
||||
});
|
||||
return handled;
|
||||
}
|
||||
|
||||
void lua_engine::attach_notifiers()
|
||||
{
|
||||
machine().add_notifier(MACHINE_NOTIFY_RESET, machine_notify_delegate(&lua_engine::on_machine_prestart, this), true);
|
||||
@ -767,6 +809,7 @@ void lua_engine::initialize()
|
||||
* emu.register_periodic(callback) - register periodic callback while program is running
|
||||
* emu.register_callback(callback, name) - register callback to be used by MAME via lua_engine::call_plugin()
|
||||
* emu.register_menu(event_callback, populate_callback, name) - register callbacks for plugin menu
|
||||
* emu.register_mandatory_file_manager_override(callback) - register callback invoked to override mandatory file manager
|
||||
* emu.show_menu(menu_name) - show menu by name and pause the machine
|
||||
*
|
||||
* emu.print_verbose(str) - output to stderr at verbose level
|
||||
@ -806,6 +849,7 @@ void lua_engine::initialize()
|
||||
emu["register_frame"] = [this](sol::function func){ register_function(func, "LUA_ON_FRAME"); };
|
||||
emu["register_frame_done"] = [this](sol::function func){ register_function(func, "LUA_ON_FRAME_DONE"); };
|
||||
emu["register_periodic"] = [this](sol::function func){ register_function(func, "LUA_ON_PERIODIC"); };
|
||||
emu["register_mandatory_file_manager_override"] = [this](sol::function func) { register_function(func, "LUA_ON_MANDATORY_FILE_MANAGER_OVERRIDE"); };
|
||||
emu["register_menu"] = [this](sol::function cb, sol::function pop, const std::string &name) {
|
||||
std::string cbfield = "menu_cb_" + name;
|
||||
std::string popfield = "menu_pop_" + name;
|
||||
|
@ -50,6 +50,7 @@ public:
|
||||
void attach_notifiers();
|
||||
void on_frame_done();
|
||||
void on_periodic();
|
||||
bool on_missing_mandatory_image(const std::string &instance_name);
|
||||
|
||||
template<typename T, typename U>
|
||||
bool call_plugin(const std::string &name, const T in, U &out)
|
||||
@ -126,6 +127,7 @@ private:
|
||||
|
||||
void resume(void *ptr, int nparam);
|
||||
void register_function(sol::function func, const char *id);
|
||||
int enumerate_functions(const char *id, std::function<bool(const sol::protected_function &func)> &&callback);
|
||||
bool execute_function(const char *id);
|
||||
sol::object call_plugin(const std::string &name, sol::object in);
|
||||
|
||||
|
@ -341,6 +341,32 @@ void mame_machine_manager::load_cheatfiles(running_machine& machine)
|
||||
m_cheat = std::make_unique<cheat_manager>(machine);
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// missing_mandatory_images - search for devices
|
||||
// which need an image to be loaded
|
||||
//-------------------------------------------------
|
||||
|
||||
std::vector<std::reference_wrapper<const std::string>> mame_machine_manager::missing_mandatory_images()
|
||||
{
|
||||
std::vector<std::reference_wrapper<const std::string>> results;
|
||||
assert(m_machine);
|
||||
|
||||
// make sure that any required image has a mounted file
|
||||
for (device_image_interface &image : image_interface_iterator(m_machine->root_device()))
|
||||
{
|
||||
if (image.must_be_loaded())
|
||||
{
|
||||
if (m_machine->options().image_option(image.instance_name()).value().empty())
|
||||
{
|
||||
// this is a missing image; give LUA plugins a chance to handle it
|
||||
if (!lua()->on_missing_mandatory_image(image.instance_name()))
|
||||
results.push_back(std::reference_wrapper<const std::string>(image.instance_name()));
|
||||
}
|
||||
}
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
const char * emulator_info::get_bare_build_version() { return bare_build_version; }
|
||||
const char * emulator_info::get_build_version() { return build_version; }
|
||||
|
||||
|
@ -50,6 +50,8 @@ public:
|
||||
|
||||
virtual void ui_initialize(running_machine& machine) override;
|
||||
|
||||
std::vector<std::reference_wrapper<const std::string>> missing_mandatory_images();
|
||||
|
||||
/* execute as configured by the OPTION_SYSTEMNAME option on the specified options */
|
||||
int execute();
|
||||
void start_luaengine();
|
||||
|
@ -407,35 +407,6 @@ std::string machine_info::game_info_string() const
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// mandatory_images - search for devices which
|
||||
// need an image to be loaded
|
||||
//-------------------------------------------------
|
||||
|
||||
std::string machine_info::mandatory_images() const
|
||||
{
|
||||
std::ostringstream buf;
|
||||
bool is_first = true;
|
||||
|
||||
// make sure that any required image has a mounted file
|
||||
for (device_image_interface &image : image_interface_iterator(m_machine.root_device()))
|
||||
{
|
||||
if (image.must_be_loaded())
|
||||
{
|
||||
if (m_machine.options().image_option(image.instance_name()).value().empty())
|
||||
{
|
||||
if (is_first)
|
||||
is_first = false;
|
||||
else
|
||||
buf << ", ";
|
||||
buf << "\"" << image.instance_name() << "\"";
|
||||
}
|
||||
}
|
||||
}
|
||||
return buf.str();
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// get_screen_desc - returns the description for
|
||||
// a given screen
|
||||
|
@ -76,7 +76,6 @@ public:
|
||||
// text generators
|
||||
std::string warnings_string() const;
|
||||
std::string game_info_string() const;
|
||||
std::string mandatory_images() const;
|
||||
std::string get_screen_desc(screen_device &screen) const;
|
||||
|
||||
private:
|
||||
|
@ -273,6 +273,26 @@ void mame_ui_manager::set_handler(ui_callback_type callback_type, const std::fun
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// output_joined_collection
|
||||
//-------------------------------------------------
|
||||
|
||||
template<typename TColl, typename TEmitMemberFunc, typename TEmitDelimFunc>
|
||||
static void output_joined_collection(const TColl &collection, TEmitMemberFunc emit_member, TEmitDelimFunc emit_delim)
|
||||
{
|
||||
bool is_first = true;
|
||||
|
||||
for (const auto &member : collection)
|
||||
{
|
||||
if (is_first)
|
||||
is_first = false;
|
||||
else
|
||||
emit_delim();
|
||||
emit_member(member);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// display_startup_screens - display the
|
||||
// various startup screens
|
||||
@ -283,13 +303,13 @@ void mame_ui_manager::display_startup_screens(bool first_time)
|
||||
const int maxstate = 3;
|
||||
int str = machine().options().seconds_to_run();
|
||||
bool show_gameinfo = !machine().options().skip_gameinfo();
|
||||
bool show_warnings = true, show_mandatory_fileman = !machine().options().skip_mandatory_fileman();
|
||||
bool show_warnings = true;
|
||||
bool video_none = strcmp(downcast<osd_options &>(machine().options()).video(), "none") == 0;
|
||||
|
||||
// disable everything if we are using -str for 300 or fewer seconds, or if we're the empty driver,
|
||||
// or if we are debugging, or if there's no mame window to send inputs to
|
||||
if (!first_time || (str > 0 && str < 60*5) || &machine().system() == &GAME_NAME(___empty) || (machine().debug_flags & DEBUG_FLAG_ENABLED) != 0 || video_none)
|
||||
show_gameinfo = show_warnings = show_mandatory_fileman = false;
|
||||
show_gameinfo = show_warnings = false;
|
||||
|
||||
#if defined(EMSCRIPTEN)
|
||||
// also disable for the JavaScript port since the startup screens do not run asynchronously
|
||||
@ -326,12 +346,17 @@ void mame_ui_manager::display_startup_screens(bool first_time)
|
||||
break;
|
||||
|
||||
case 2:
|
||||
if (show_mandatory_fileman)
|
||||
messagebox_text = machine_info().mandatory_images();
|
||||
if (!messagebox_text.empty())
|
||||
std::vector<std::reference_wrapper<const std::string>> mandatory_images = mame_machine_manager::instance()->missing_mandatory_images();
|
||||
if (!mandatory_images.empty())
|
||||
{
|
||||
std::string warning = std::string(_("This driver requires images to be loaded in the following device(s): ")) + messagebox_text;
|
||||
ui::menu_file_manager::force_file_manager(*this, machine().render().ui_container(), warning.c_str());
|
||||
std::ostringstream warning;
|
||||
warning << _("This driver requires images to be loaded in the following device(s): ");
|
||||
|
||||
output_joined_collection(mandatory_images,
|
||||
[&warning](const std::reference_wrapper<const std::string> &img) { warning << "\"" << img.get() << "\""; },
|
||||
[&warning]() { warning << ","; });
|
||||
|
||||
ui::menu_file_manager::force_file_manager(*this, machine().render().ui_container(), warning.str().c_str());
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user