diff --git a/src/emu/image.cpp b/src/emu/image.cpp index a08acad47cf..5fbc5844b9d 100644 --- a/src/emu/image.cpp +++ b/src/emu/image.cpp @@ -208,23 +208,6 @@ void image_manager::options_extract() } -/*------------------------------------------------- - image_mandatory_scan - search for devices which - need an image to be loaded - -------------------------------------------------*/ - -std::string &image_manager::mandatory_scan(std::string &mandatory) -{ - mandatory.clear(); - // make sure that any required image has a mounted file - for (device_image_interface &image : image_interface_iterator(machine().root_device())) - { - if (image.filename() == nullptr && image.must_be_loaded()) - mandatory.append("\"").append(image.instance_name()).append("\", "); - } - return mandatory; -} - /*------------------------------------------------- postdevice_init - initialize devices for a specific running_machine diff --git a/src/emu/image.h b/src/emu/image.h index 32b8035d14d..4a9e55e4c80 100644 --- a/src/emu/image.h +++ b/src/emu/image.h @@ -23,7 +23,6 @@ public: void unload_all(); void postdevice_init(); - std::string &mandatory_scan(std::string &mandatory); // getters running_machine &machine() const { return m_machine; } diff --git a/src/emu/ioport.cpp b/src/emu/ioport.cpp index 4bec462ceed..44e758b5752 100644 --- a/src/emu/ioport.cpp +++ b/src/emu/ioport.cpp @@ -2450,10 +2450,6 @@ ioport_manager::ioport_manager(running_machine &machine) m_timecode_file(machine.options().input_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS), m_timecode_count(0), m_timecode_last_time(attotime::zero), - m_has_configs(false), - m_has_analog(false), - m_has_dips(false), - m_has_bioses(false), m_autofire_toggle(false), m_autofire_delay(3) // 1 seems too fast for a bunch of games { @@ -2534,29 +2530,6 @@ time_t ioport_manager::initialize() // register callbacks for when we load configurations machine().configuration().config_register("input", config_saveload_delegate(FUNC(ioport_manager::load_config), this), config_saveload_delegate(FUNC(ioport_manager::save_config), this)); - // calculate "has..." values - { - m_has_configs = false; - m_has_analog = false; - m_has_dips = false; - m_has_bioses = false; - - // scan the input port array to see what options we need to enable - for (auto &port : m_portlist) - for (ioport_field &field : port.second->fields()) - { - if (field.type() == IPT_DIPSWITCH) - m_has_dips = true; - if (field.type() == IPT_CONFIG) - m_has_configs = true; - if (field.is_analog()) - m_has_analog = true; - } - for (device_t &device : device_iterator(machine().root_device())) - for (const rom_entry &rom : device.rom_region_vector()) - if (ROMENTRY_ISSYSTEM_BIOS(&rom)) { m_has_bioses= true; break; } - } - // open playback and record files if specified time_t basetime = playback_init(); record_init(); diff --git a/src/emu/ioport.h b/src/emu/ioport.h index 71368f37507..419b603b239 100644 --- a/src/emu/ioport.h +++ b/src/emu/ioport.h @@ -1474,12 +1474,6 @@ public: bool safe_to_read() const { return m_safe_to_read; } natural_keyboard &natkeyboard() { return m_natkeyboard; } - // has... getters - bool has_configs() const { return m_has_configs; } - bool has_analog() const { return m_has_analog; } - bool has_dips() const { return m_has_dips; } - bool has_bioses() const { return m_has_bioses; } - // type helpers const simple_list &types() const { return m_typelist; } bool type_pressed(ioport_type type, int player = 0); @@ -1570,12 +1564,6 @@ private: int m_timecode_count; attotime m_timecode_last_time; - // has... - bool m_has_configs; - bool m_has_analog; - bool m_has_dips; - bool m_has_bioses; - // autofire bool m_autofire_toggle; // autofire toggle int m_autofire_delay; // autofire delay diff --git a/src/frontend/mame/luaengine.cpp b/src/frontend/mame/luaengine.cpp index 83a077cec86..0ccda19620e 100644 --- a/src/frontend/mame/luaengine.cpp +++ b/src/frontend/mame/luaengine.cpp @@ -2395,10 +2395,6 @@ void lua_engine::initialize() .addFunction ("select_next_state", &cheat_entry::select_next_state) .endClass() .beginClass ("ioport") - .addFunction ("has_configs", &ioport_manager::has_configs) - .addFunction ("has_analog", &ioport_manager::has_analog) - .addFunction ("has_dips", &ioport_manager::has_dips) - .addFunction ("has_bioses", &ioport_manager::has_bioses) .addFunction ("has_keyboard", &ioport_manager::has_keyboard) .addFunction ("count_players", &ioport_manager::count_players) .addProperty ("ports", &lua_engine::l_ioport_get_ports) diff --git a/src/frontend/mame/ui/info.cpp b/src/frontend/mame/ui/info.cpp index 9461f566d71..1048ac426ce 100644 --- a/src/frontend/mame/ui/info.cpp +++ b/src/frontend/mame/ui/info.cpp @@ -13,9 +13,328 @@ #include "ui/info.h" #include "ui/ui.h" +#include "drivenum.h" #include "softlist.h" namespace ui { + + +//------------------------------------------------- +// machine_info - constructor +//------------------------------------------------- + +machine_info::machine_info(running_machine &machine) + : m_machine(machine) +{ + // calculate "has..." values + m_has_configs = false; + m_has_analog = false; + m_has_dips = false; + m_has_bioses = false; + + // scan the input port array to see what options we need to enable + for (auto &port : machine.ioport().ports()) + for (ioport_field &field : port.second->fields()) + { + if (field.type() == IPT_DIPSWITCH) + m_has_dips = true; + if (field.type() == IPT_CONFIG) + m_has_configs = true; + if (field.is_analog()) + m_has_analog = true; + } + + for (device_t &device : device_iterator(machine.root_device())) + for (const rom_entry &rom : device.rom_region_vector()) + if (ROMENTRY_ISSYSTEM_BIOS(&rom)) { m_has_bioses = true; break; } +} + + +/*************************************************************************** + TEXT GENERATORS +***************************************************************************/ + +//------------------------------------------------- +// warnings_string - print the warning flags +// text to the given buffer +//------------------------------------------------- + +std::string machine_info::warnings_string() +{ + constexpr UINT32 warning_flags = ( MACHINE_NOT_WORKING | + MACHINE_UNEMULATED_PROTECTION | + MACHINE_MECHANICAL | + MACHINE_WRONG_COLORS | + MACHINE_IMPERFECT_COLORS | + MACHINE_REQUIRES_ARTWORK | + MACHINE_NO_SOUND | + MACHINE_IMPERFECT_SOUND | + MACHINE_IMPERFECT_GRAPHICS | + MACHINE_IMPERFECT_KEYBOARD | + MACHINE_NO_COCKTAIL | + MACHINE_IS_INCOMPLETE | + MACHINE_NO_SOUND_HW ); + + // if no warnings, nothing to return + if (m_machine.rom_load().warnings() == 0 && m_machine.rom_load().knownbad() == 0 && !(m_machine.system().flags & warning_flags) && m_machine.rom_load().software_load_warnings_message().length() == 0) + return std::string(); + + std::ostringstream buf; + + // add a warning if any ROMs were loaded with warnings + if (m_machine.rom_load().warnings() > 0) + { + buf << _("One or more ROMs/CHDs for this machine are incorrect. The machine may not run correctly.\n"); + if (m_machine.system().flags & warning_flags) + buf << "\n"; + } + + if (m_machine.rom_load().software_load_warnings_message().length()>0) { + buf << m_machine.rom_load().software_load_warnings_message(); + if (m_machine.system().flags & warning_flags) + buf << "\n"; + } + // if we have at least one warning flag, print the general header + if ((m_machine.system().flags & warning_flags) || m_machine.rom_load().knownbad() > 0) + { + buf << _("There are known problems with this machine\n\n"); + + // add a warning if any ROMs are flagged BAD_DUMP/NO_DUMP + if (m_machine.rom_load().knownbad() > 0) { + buf << _("One or more ROMs/CHDs for this machine have not been correctly dumped.\n"); + } + // add one line per warning flag + if (m_machine.system().flags & MACHINE_IMPERFECT_KEYBOARD) + buf << _("The keyboard emulation may not be 100% accurate.\n"); + if (m_machine.system().flags & MACHINE_IMPERFECT_COLORS) + buf << _("The colors aren't 100% accurate.\n"); + if (m_machine.system().flags & MACHINE_WRONG_COLORS) + buf << _("The colors are completely wrong.\n"); + if (m_machine.system().flags & MACHINE_IMPERFECT_GRAPHICS) + buf << _("The video emulation isn't 100% accurate.\n"); + if (m_machine.system().flags & MACHINE_IMPERFECT_SOUND) + buf << _("The sound emulation isn't 100% accurate.\n"); + if (m_machine.system().flags & MACHINE_NO_SOUND) { + buf << _("The machine lacks sound.\n"); + } + if (m_machine.system().flags & MACHINE_NO_COCKTAIL) + buf << _("Screen flipping in cocktail mode is not supported.\n"); + + // check if external artwork is present before displaying this warning? + if (m_machine.system().flags & MACHINE_REQUIRES_ARTWORK) { + buf << _("The machine requires external artwork files\n"); + } + + if (m_machine.system().flags & MACHINE_IS_INCOMPLETE ) + { + buf << _("This machine was never completed. It may exhibit strange behavior or missing elements that are not bugs in the emulation.\n"); + } + + if (m_machine.system().flags & MACHINE_NO_SOUND_HW ) + { + buf << _("This machine has no sound hardware, MAME will produce no sounds, this is expected behaviour.\n"); + } + + // if there's a NOT WORKING, UNEMULATED PROTECTION or GAME MECHANICAL warning, make it stronger + if (m_machine.system().flags & (MACHINE_NOT_WORKING | MACHINE_UNEMULATED_PROTECTION | MACHINE_MECHANICAL)) + { + // add the strings for these warnings + if (m_machine.system().flags & MACHINE_UNEMULATED_PROTECTION) { + buf << _("The machine has protection which isn't fully emulated.\n"); + } + if (m_machine.system().flags & MACHINE_NOT_WORKING) { + buf << _("\nTHIS MACHINE DOESN'T WORK. The emulation for this machine is not yet complete. " + "There is nothing you can do to fix this problem except wait for the developers to improve the emulation.\n"); + } + if (m_machine.system().flags & MACHINE_MECHANICAL) { + buf << _("\nCertain elements of this machine cannot be emulated as it requires actual physical interaction or consists of mechanical devices. " + "It is not possible to fully play this machine.\n"); + } + + // find the parent of this driver + driver_enumerator drivlist(m_machine.options()); + int maindrv = drivlist.find(m_machine.system()); + int clone_of = drivlist.non_bios_clone(maindrv); + if (clone_of != -1) + maindrv = clone_of; + + // scan the driver list for any working clones and add them + bool foundworking = false; + while (drivlist.next()) + if (drivlist.current() == maindrv || drivlist.clone() == maindrv) + if ((drivlist.driver().flags & (MACHINE_NOT_WORKING | MACHINE_UNEMULATED_PROTECTION | MACHINE_MECHANICAL)) == 0) + { + // this one works, add a header and display the name of the clone + if (!foundworking) { + buf << _("\n\nThere are working clones of this machine: "); + } + else + buf << ", "; + buf << drivlist.driver().name; + foundworking = true; + } + + if (foundworking) + buf << "\n"; + } + } + + // add the 'press OK' string + buf << _("\n\nPress any key to continue"); + return buf.str(); +} + + +//------------------------------------------------- +// game_info_string - return the game info text +//------------------------------------------------- + +std::string machine_info::game_info_string() +{ + std::ostringstream buf; + + // print description, manufacturer, and CPU: + util::stream_format(buf, _("%1$s\n%2$s %3$s\nDriver: %4$s\n\nCPU:\n"), + m_machine.system().description, + m_machine.system().year, + m_machine.system().manufacturer, + core_filename_extract_base(m_machine.system().source_file)); + + // loop over all CPUs + execute_interface_iterator execiter(m_machine.root_device()); + std::unordered_set exectags; + for (device_execute_interface &exec : execiter) + { + if (!exectags.insert(exec.device().tag()).second) + continue; + // get cpu specific clock that takes internal multiplier/dividers into account + int clock = exec.device().clock(); + + // count how many identical CPUs we have + int count = 1; + const char *name = exec.device().name(); + for (device_execute_interface &scan : execiter) + { + if (exec.device().type() == scan.device().type() && strcmp(name, scan.device().name()) == 0 && exec.device().clock() == scan.device().clock()) + if (exectags.insert(scan.device().tag()).second) + count++; + } + + // if more than one, prepend a #x in front of the CPU name + // display clock in kHz or MHz + util::stream_format(buf, + (count > 1) ? "%1$d" UTF8_MULTIPLY "%2$s %3$d.%4$0*5$d%6$s\n" : "%2$s %3$d.%4$0*5$d%6$s\n", + count, + name, + (clock >= 1000000) ? (clock / 1000000) : (clock / 1000), + (clock >= 1000000) ? (clock % 1000000) : (clock % 1000), + (clock >= 1000000) ? 6 : 3, + (clock >= 1000000) ? _("MHz") : _("kHz")); + } + + // loop over all sound chips + sound_interface_iterator snditer(m_machine.root_device()); + std::unordered_set soundtags; + bool found_sound = false; + for (device_sound_interface &sound : snditer) + { + if (!soundtags.insert(sound.device().tag()).second) + continue; + + // append the Sound: string + if (!found_sound) + buf << _("\nSound:\n"); + found_sound = true; + + // count how many identical sound chips we have + int count = 1; + for (device_sound_interface &scan : snditer) + { + if (sound.device().type() == scan.device().type() && sound.device().clock() == scan.device().clock()) + if (soundtags.insert(scan.device().tag()).second) + count++; + } + + // if more than one, prepend a #x in front of the CPU name + // display clock in kHz or MHz + int clock = sound.device().clock(); + util::stream_format(buf, + (count > 1) + ? ((clock != 0) ? "%1$d" UTF8_MULTIPLY "%2$s %3$d.%4$0*5$d%6$s\n" : "%1$d" UTF8_MULTIPLY "%2$s\n") + : ((clock != 0) ? "%2$s %3$d.%4$0*5$d%6$s\n" : "%2$s\n"), + count, + sound.device().name(), + (clock >= 1000000) ? (clock / 1000000) : (clock / 1000), + (clock >= 1000000) ? (clock % 1000000) : (clock % 1000), + (clock >= 1000000) ? 6 : 3, + (clock >= 1000000) ? _("MHz") : _("kHz")); + } + + // display screen information + buf << _("\nVideo:\n"); + screen_device_iterator scriter(m_machine.root_device()); + int scrcount = scriter.count(); + if (scrcount == 0) + buf << _("None\n"); + else + { + for (screen_device &screen : scriter) + { + std::string detail; + if (screen.screen_type() == SCREEN_TYPE_VECTOR) + detail = _("Vector"); + else + { + const rectangle &visarea = screen.visible_area(); + detail = string_format("%d " UTF8_MULTIPLY " %d (%s) %f" UTF8_NBSP "Hz", + visarea.width(), visarea.height(), + (m_machine.system().flags & ORIENTATION_SWAP_XY) ? "V" : "H", + ATTOSECONDS_TO_HZ(screen.frame_period().attoseconds())); + } + + util::stream_format(buf, + (scrcount > 1) ? _("%1$s: %2$s\n") : _("%2$s\n"), + get_screen_desc(screen), detail); + } + } + + return buf.str(); +} + + +//------------------------------------------------- +// mandatory_images - search for devices which +// need an image to be loaded +//------------------------------------------------- + +std::string machine_info::mandatory_images() +{ + std::ostringstream buf; + + // make sure that any required image has a mounted file + for (device_image_interface &image : image_interface_iterator(m_machine.root_device())) + { + if (image.filename() == nullptr && image.must_be_loaded()) + buf << "\"" << image.instance_name() << "\", "; + } + return buf.str(); +} + + +//------------------------------------------------- +// get_screen_desc - returns the description for +// a given screen +//------------------------------------------------- + +std::string machine_info::get_screen_desc(screen_device &screen) +{ + if (screen_device_iterator(m_machine.root_device()).count() > 1) + return string_format(_("Screen '%1$s'"), screen.tag()); + else + return _("Screen"); +} + + /*------------------------------------------------- menu_game_info - handle the game information menu @@ -31,8 +350,8 @@ menu_game_info::~menu_game_info() void menu_game_info::populate() { - std::string tempstring; - item_append(ui().game_info_astring(tempstring), "", FLAG_MULTILINE, nullptr); + std::string tempstring = ui().machine_info().game_info_string(); + item_append(std::move(tempstring), "", FLAG_MULTILINE, nullptr); } void menu_game_info::handle() diff --git a/src/frontend/mame/ui/info.h b/src/frontend/mame/ui/info.h index 2fbd9de3683..8a1d339dc73 100644 --- a/src/frontend/mame/ui/info.h +++ b/src/frontend/mame/ui/info.h @@ -16,6 +16,36 @@ #include "ui/menu.h" namespace ui { + +class machine_info +{ +public: + // construction + machine_info(running_machine &machine); + + // has... getters + bool has_configs() const { return m_has_configs; } + bool has_analog() const { return m_has_analog; } + bool has_dips() const { return m_has_dips; } + bool has_bioses() const { return m_has_bioses; } + + // text generators + std::string warnings_string(); + std::string game_info_string(); + std::string mandatory_images(); + std::string get_screen_desc(screen_device &screen); + +private: + // reference to machine + running_machine & m_machine; + + // has... + bool m_has_configs; + bool m_has_analog; + bool m_has_dips; + bool m_has_bioses; +}; + class menu_game_info : public menu { public: diff --git a/src/frontend/mame/ui/mainmenu.cpp b/src/frontend/mame/ui/mainmenu.cpp index 3bf5e5cb7b6..92d7db18d4c 100644 --- a/src/frontend/mame/ui/mainmenu.cpp +++ b/src/frontend/mame/ui/mainmenu.cpp @@ -56,11 +56,11 @@ void menu_main::populate() item_append(_("Input (this Machine)"), "", 0, (void *)INPUT_SPECIFIC); /* add optional input-related menus */ - if (machine().ioport().has_analog()) + if (ui().machine_info().has_analog()) item_append(_("Analog Controls"), "", 0, (void *)ANALOG); - if (machine().ioport().has_dips()) + if (ui().machine_info().has_dips()) item_append(_("Dip Switches"), "", 0, (void *)SETTINGS_DIP_SWITCHES); - if (machine().ioport().has_configs()) + if (ui().machine_info().has_configs()) { item_append(_("Machine Configuration"), "", 0, (void *)SETTINGS_DRIVER_CONFIG); } @@ -92,7 +92,7 @@ void menu_main::populate() if (pty_interface_iterator(machine().root_device()).first() != nullptr) item_append(_("Pseudo terminals"), "", 0, (void *)PTY_INFO); - if (machine().ioport().has_bioses()) + if (ui().machine_info().has_bioses()) item_append(_("Bios Selection"), "", 0, (void *)BIOS_SELECTION); /* add slot info menu */ diff --git a/src/frontend/mame/ui/ui.cpp b/src/frontend/mame/ui/ui.cpp index 7394f03be2f..5c7f4a54a39 100644 --- a/src/frontend/mame/ui/ui.cpp +++ b/src/frontend/mame/ui/ui.cpp @@ -21,13 +21,13 @@ #include "rendfont.h" #include "uiinput.h" #include "ui/ui.h" +#include "ui/info.h" #include "ui/menu.h" #include "ui/mainmenu.h" #include "ui/filemngr.h" #include "ui/sliders.h" #include "ui/viewgfx.h" #include "imagedev/cassette.h" -#include "image.h" /*************************************************************************** @@ -186,6 +186,10 @@ mame_ui_manager::mame_ui_manager(running_machine &machine) { } +mame_ui_manager::~mame_ui_manager() +{ +} + void mame_ui_manager::init() { load_ui_options(); @@ -240,6 +244,8 @@ void mame_ui_manager::exit() void mame_ui_manager::initialize(running_machine &machine) { + m_machine_info = std::make_unique(machine); + // initialize the on-screen display system slider_list = slider_init(machine); if (slider_list.size() > 0) @@ -295,12 +301,15 @@ void mame_ui_manager::display_startup_screens(bool first_time) { // default to standard colors messagebox_backcolor = UI_BACKGROUND_COLOR; + messagebox_text.clear(); // pick the next state switch (state) { case 0: - if (show_warnings && warnings_string(messagebox_text).length() > 0) + if (show_warnings) + messagebox_text = machine_info().warnings_string(); + if (!messagebox_text.empty()) { set_handler(ui_callback_type::MODAL, std::bind(&mame_ui_manager::handler_messagebox_anykey, this, _1)); if (machine().system().flags & (MACHINE_WRONG_COLORS | MACHINE_IMPERFECT_COLORS | MACHINE_REQUIRES_ARTWORK | MACHINE_IMPERFECT_GRAPHICS | MACHINE_IMPERFECT_SOUND | MACHINE_IMPERFECT_KEYBOARD | MACHINE_NO_SOUND)) @@ -311,12 +320,16 @@ void mame_ui_manager::display_startup_screens(bool first_time) break; case 1: - if (show_gameinfo && game_info_astring(messagebox_text).length() > 0) + if (show_gameinfo) + messagebox_text = machine_info().game_info_string(); + if (!messagebox_text.empty()) set_handler(ui_callback_type::MODAL, std::bind(&mame_ui_manager::handler_messagebox_anykey, this, _1)); break; case 2: - if (show_mandatory_fileman && machine().image().mandatory_scan(messagebox_text).length() > 0) + if (show_mandatory_fileman) + messagebox_text = machine_info().mandatory_images(); + if (!messagebox_text.empty()) { std::string warning; warning.assign(_("This driver requires images to be loaded in the following device(s): ")).append(messagebox_text.substr(0, messagebox_text.length() - 2)); @@ -745,259 +758,6 @@ bool mame_ui_manager::is_menu_active(void) } -/*************************************************************************** - TEXT GENERATORS -***************************************************************************/ - -//------------------------------------------------- -// warnings_string - print the warning flags -// text to the given buffer -//------------------------------------------------- - -std::string &mame_ui_manager::warnings_string(std::string &str) -{ -#define WARNING_FLAGS ( MACHINE_NOT_WORKING | \ - MACHINE_UNEMULATED_PROTECTION | \ - MACHINE_MECHANICAL | \ - MACHINE_WRONG_COLORS | \ - MACHINE_IMPERFECT_COLORS | \ - MACHINE_REQUIRES_ARTWORK | \ - MACHINE_NO_SOUND | \ - MACHINE_IMPERFECT_SOUND | \ - MACHINE_IMPERFECT_GRAPHICS | \ - MACHINE_IMPERFECT_KEYBOARD | \ - MACHINE_NO_COCKTAIL| \ - MACHINE_IS_INCOMPLETE| \ - MACHINE_NO_SOUND_HW ) - - str.clear(); - - // if no warnings, nothing to return - if (machine().rom_load().warnings() == 0 && machine().rom_load().knownbad() == 0 && !(machine().system().flags & WARNING_FLAGS) && machine().rom_load().software_load_warnings_message().length() == 0) - return str; - - // add a warning if any ROMs were loaded with warnings - if (machine().rom_load().warnings() > 0) - { - str.append(_("One or more ROMs/CHDs for this machine are incorrect. The machine may not run correctly.\n")); - if (machine().system().flags & WARNING_FLAGS) - str.append("\n"); - } - - if (machine().rom_load().software_load_warnings_message().length()>0) { - str.append(machine().rom_load().software_load_warnings_message()); - if (machine().system().flags & WARNING_FLAGS) - str.append("\n"); - } - // if we have at least one warning flag, print the general header - if ((machine().system().flags & WARNING_FLAGS) || machine().rom_load().knownbad() > 0) - { - str.append(_("There are known problems with this machine\n\n")); - - // add a warning if any ROMs are flagged BAD_DUMP/NO_DUMP - if (machine().rom_load().knownbad() > 0) { - str.append(_("One or more ROMs/CHDs for this machine have not been correctly dumped.\n")); - } - // add one line per warning flag - if (machine().system().flags & MACHINE_IMPERFECT_KEYBOARD) - str.append(_("The keyboard emulation may not be 100% accurate.\n")); - if (machine().system().flags & MACHINE_IMPERFECT_COLORS) - str.append(_("The colors aren't 100% accurate.\n")); - if (machine().system().flags & MACHINE_WRONG_COLORS) - str.append(_("The colors are completely wrong.\n")); - if (machine().system().flags & MACHINE_IMPERFECT_GRAPHICS) - str.append(_("The video emulation isn't 100% accurate.\n")); - if (machine().system().flags & MACHINE_IMPERFECT_SOUND) - str.append(_("The sound emulation isn't 100% accurate.\n")); - if (machine().system().flags & MACHINE_NO_SOUND) { - str.append(_("The machine lacks sound.\n")); - } - if (machine().system().flags & MACHINE_NO_COCKTAIL) - str.append(_("Screen flipping in cocktail mode is not supported.\n")); - - // check if external artwork is present before displaying this warning? - if (machine().system().flags & MACHINE_REQUIRES_ARTWORK) { - str.append(_("The machine requires external artwork files\n")); - } - - if (machine().system().flags & MACHINE_IS_INCOMPLETE ) - { - str.append(_("This machine was never completed. It may exhibit strange behavior or missing elements that are not bugs in the emulation.\n")); - } - - if (machine().system().flags & MACHINE_NO_SOUND_HW ) - { - str.append(_("This machine has no sound hardware, MAME will produce no sounds, this is expected behaviour.\n")); - } - - // if there's a NOT WORKING, UNEMULATED PROTECTION or GAME MECHANICAL warning, make it stronger - if (machine().system().flags & (MACHINE_NOT_WORKING | MACHINE_UNEMULATED_PROTECTION | MACHINE_MECHANICAL)) - { - // add the strings for these warnings - if (machine().system().flags & MACHINE_UNEMULATED_PROTECTION) { - str.append(_("The machine has protection which isn't fully emulated.\n")); - } - if (machine().system().flags & MACHINE_NOT_WORKING) { - str.append(_("\nTHIS MACHINE DOESN'T WORK. The emulation for this machine is not yet complete. " - "There is nothing you can do to fix this problem except wait for the developers to improve the emulation.\n")); - } - if (machine().system().flags & MACHINE_MECHANICAL) { - str.append(_("\nCertain elements of this machine cannot be emulated as it requires actual physical interaction or consists of mechanical devices. " - "It is not possible to fully play this machine.\n")); - } - - // find the parent of this driver - driver_enumerator drivlist(machine().options()); - int maindrv = drivlist.find(machine().system()); - int clone_of = drivlist.non_bios_clone(maindrv); - if (clone_of != -1) - maindrv = clone_of; - - // scan the driver list for any working clones and add them - bool foundworking = false; - while (drivlist.next()) - if (drivlist.current() == maindrv || drivlist.clone() == maindrv) - if ((drivlist.driver().flags & (MACHINE_NOT_WORKING | MACHINE_UNEMULATED_PROTECTION | MACHINE_MECHANICAL)) == 0) - { - // this one works, add a header and display the name of the clone - if (!foundworking) { - str.append(_("\n\nThere are working clones of this machine: ")); - } - else - str.append(", "); - str.append(drivlist.driver().name); - foundworking = true; - } - - if (foundworking) - str.append("\n"); - } - } - - // add the 'press OK' string - str.append(_("\n\nPress any key to continue")); - return str; -} - - -//------------------------------------------------- -// game_info_std::string - populate an allocated -// string with the game info text -//------------------------------------------------- - -std::string &mame_ui_manager::game_info_astring(std::string &str) -{ - std::ostringstream buf; - - // print description, manufacturer, and CPU: - util::stream_format(buf, _("%1$s\n%2$s %3$s\nDriver: %4$s\n\nCPU:\n"), - machine().system().description, - machine().system().year, - machine().system().manufacturer, - core_filename_extract_base(machine().system().source_file)); - - // loop over all CPUs - execute_interface_iterator execiter(machine().root_device()); - std::unordered_set exectags; - for (device_execute_interface &exec : execiter) - { - if (!exectags.insert(exec.device().tag()).second) - continue; - // get cpu specific clock that takes internal multiplier/dividers into account - int clock = exec.device().clock(); - - // count how many identical CPUs we have - int count = 1; - const char *name = exec.device().name(); - for (device_execute_interface &scan : execiter) - { - if (exec.device().type() == scan.device().type() && strcmp(name, scan.device().name()) == 0 && exec.device().clock() == scan.device().clock()) - if (exectags.insert(scan.device().tag()).second) - count++; - } - - // if more than one, prepend a #x in front of the CPU name - // display clock in kHz or MHz - util::stream_format(buf, - (count > 1) ? "%1$d" UTF8_MULTIPLY "%2$s %3$d.%4$0*5$d%6$s\n" : "%2$s %3$d.%4$0*5$d%6$s\n", - count, - name, - (clock >= 1000000) ? (clock / 1000000) : (clock / 1000), - (clock >= 1000000) ? (clock % 1000000) : (clock % 1000), - (clock >= 1000000) ? 6 : 3, - (clock >= 1000000) ? _("MHz") : _("kHz")); - } - - // loop over all sound chips - sound_interface_iterator snditer(machine().root_device()); - std::unordered_set soundtags; - bool found_sound = false; - for (device_sound_interface &sound : snditer) - { - if (!soundtags.insert(sound.device().tag()).second) - continue; - - // append the Sound: string - if (!found_sound) - buf << _("\nSound:\n"); - found_sound = true; - - // count how many identical sound chips we have - int count = 1; - for (device_sound_interface &scan : snditer) - { - if (sound.device().type() == scan.device().type() && sound.device().clock() == scan.device().clock()) - if (soundtags.insert(scan.device().tag()).second) - count++; - } - - // if more than one, prepend a #x in front of the CPU name - // display clock in kHz or MHz - int clock = sound.device().clock(); - util::stream_format(buf, - (count > 1) - ? ((clock != 0) ? "%1$d" UTF8_MULTIPLY "%2$s %3$d.%4$0*5$d%6$s\n" : "%1$d" UTF8_MULTIPLY "%2$s\n") - : ((clock != 0) ? "%2$s %3$d.%4$0*5$d%6$s\n" : "%2$s\n"), - count, - sound.device().name(), - (clock >= 1000000) ? (clock / 1000000) : (clock / 1000), - (clock >= 1000000) ? (clock % 1000000) : (clock % 1000), - (clock >= 1000000) ? 6 : 3, - (clock >= 1000000) ? _("MHz") : _("kHz")); - } - - // display screen information - buf << _("\nVideo:\n"); - screen_device_iterator scriter(machine().root_device()); - int scrcount = scriter.count(); - if (scrcount == 0) - buf << _("None\n"); - else - { - for (screen_device &screen : scriter) - { - std::string detail; - if (screen.screen_type() == SCREEN_TYPE_VECTOR) - detail = _("Vector"); - else - { - const rectangle &visarea = screen.visible_area(); - detail = string_format("%d " UTF8_MULTIPLY " %d (%s) %f" UTF8_NBSP "Hz", - visarea.width(), visarea.height(), - (machine().system().flags & ORIENTATION_SWAP_XY) ? "V" : "H", - ATTOSECONDS_TO_HZ(screen.frame_period().attoseconds())); - } - - util::stream_format(buf, - (scrcount > 1) ? _("%1$s: %2$s\n") : _("%2$s\n"), - slider_get_screen_desc(screen), detail); - } - } - - return str = buf.str(); -} - - /*************************************************************************** UI HANDLERS @@ -1043,7 +803,7 @@ UINT32 mame_ui_manager::handler_messagebox_anykey(render_container &container) } -//-------------------------------------------------3 +//------------------------------------------------- // process_natural_keyboard - processes any // natural keyboard input //------------------------------------------------- @@ -1758,7 +1518,7 @@ std::vector mame_ui_manager::slider_init(running_machine &machine int defxoffset = floor(screen.xoffset() * 1000.0f + 0.5f); int defyoffset = floor(screen.yoffset() * 1000.0f + 0.5f); void *param = (void *)&screen; - std::string screen_desc = slider_get_screen_desc(screen); + std::string screen_desc = machine_info().get_screen_desc(screen); // add refresh rate tweaker if (machine.options().cheat()) @@ -2317,19 +2077,6 @@ INT32 mame_ui_manager::slider_beam_intensity_weight(running_machine &machine, vo } -//------------------------------------------------- -// slider_get_screen_desc - returns the -// description for a given screen -//------------------------------------------------- - -std::string mame_ui_manager::slider_get_screen_desc(screen_device &screen) -{ - if (screen_device_iterator(screen.machine().root_device()).count() > 1) - return string_format(_("Screen '%1$s'"), screen.tag()); - else - return _("Screen"); -} - //------------------------------------------------- // slider_crossscale - crosshair scale slider // callback diff --git a/src/frontend/mame/ui/ui.h b/src/frontend/mame/ui/ui.h index 0c45dd08405..3baa5db61c2 100644 --- a/src/frontend/mame/ui/ui.h +++ b/src/frontend/mame/ui/ui.h @@ -26,7 +26,7 @@ namespace ui { class menu_item; - +class machine_info; } // namespace ui /*************************************************************************** @@ -152,6 +152,7 @@ public: // construction/destruction mame_ui_manager(running_machine &machine); + ~mame_ui_manager(); void init(); @@ -159,6 +160,7 @@ public: running_machine &machine() const { return m_machine; } bool single_step() const { return m_single_step; } ui_options &options() { return m_ui_options; } + ui::machine_info &machine_info() const { assert(m_machine_info != nullptr); return *m_machine_info; } // setters void set_single_step(bool single_step) { m_single_step = single_step; } @@ -213,9 +215,6 @@ public: void start_save_state(); void start_load_state(); - // print the game info string into a buffer - std::string &game_info_astring(std::string &str); - // slider controls std::vector& get_slider_list(void); @@ -249,6 +248,8 @@ private: bool m_load_save_hold; ui_options m_ui_options; + std::unique_ptr m_machine_info; + // static variables static std::string messagebox_text; static std::string messagebox_poptext; @@ -257,9 +258,6 @@ private: static std::vector slider_list; static slider_state *slider_current; - // text generators - std::string &warnings_string(std::string &buffer); - // UI handlers UINT32 handler_messagebox(render_container &container); UINT32 handler_messagebox_anykey(render_container &container);