diff --git a/src/devices/bus/plg1x0/plg1x0.cpp b/src/devices/bus/plg1x0/plg1x0.cpp index 1bbded3ff18..1f0fec2fd51 100644 --- a/src/devices/bus/plg1x0/plg1x0.cpp +++ b/src/devices/bus/plg1x0/plg1x0.cpp @@ -19,7 +19,6 @@ plg1x0_connector::plg1x0_connector(const machine_config &mconfig, const char *ta void plg1x0_connector::device_start() { - save_item(NAME(m_dummy_save)); } void plg1x0_connector::midi_rx(int state) diff --git a/src/devices/bus/plg1x0/plg1x0.h b/src/devices/bus/plg1x0/plg1x0.h index dd7186a58b0..b3af4bb075b 100644 --- a/src/devices/bus/plg1x0/plg1x0.h +++ b/src/devices/bus/plg1x0/plg1x0.h @@ -53,7 +53,6 @@ public: void do_midi_tx(int state) { m_midi_tx(state); } protected: - bool m_dummy_save = false; // needed for save-state support devcb_write_line m_midi_tx; virtual void device_start() override ATTR_COLD; diff --git a/src/devices/bus/rs232/keyboard.cpp b/src/devices/bus/rs232/keyboard.cpp index 50ea6a1a95f..f29057588cc 100644 --- a/src/devices/bus/rs232/keyboard.cpp +++ b/src/devices/bus/rs232/keyboard.cpp @@ -4,6 +4,7 @@ #include "keyboard.h" namespace { + INPUT_PORTS_START(serial_keyboard) PORT_INCLUDE(generic_keyboard) @@ -12,6 +13,7 @@ INPUT_PORTS_START(serial_keyboard) PORT_RS232_PARITY("RS232_PARITY", RS232_PARITY_NONE, "Parity", serial_keyboard_device, update_serial) PORT_RS232_STOPBITS("RS232_STOPBITS", RS232_STOPBITS_1, "Stop Bits", serial_keyboard_device, update_serial) INPUT_PORTS_END + } // anonymous namespace serial_keyboard_device::serial_keyboard_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) diff --git a/src/devices/bus/svi3x8/expander/expander.cpp b/src/devices/bus/svi3x8/expander/expander.cpp index e75be84a7ba..6c305e47082 100644 --- a/src/devices/bus/svi3x8/expander/expander.cpp +++ b/src/devices/bus/svi3x8/expander/expander.cpp @@ -58,9 +58,6 @@ void svi_expander_device::device_start() { // get inserted module m_module = get_card_device(); - - // register for save states - save_item(NAME(m_dummy_save)); } //------------------------------------------------- diff --git a/src/devices/bus/svi3x8/expander/expander.h b/src/devices/bus/svi3x8/expander/expander.h index 997f10afc1e..3a8182ad12c 100644 --- a/src/devices/bus/svi3x8/expander/expander.h +++ b/src/devices/bus/svi3x8/expander/expander.h @@ -112,8 +112,6 @@ private: devcb_read8 m_excsr_handler; devcb_write8 m_excsw_handler; - - bool m_dummy_save = false; // needed for save-state support }; diff --git a/src/devices/bus/waveblaster/waveblaster.cpp b/src/devices/bus/waveblaster/waveblaster.cpp index a1a12323879..d947a265e63 100644 --- a/src/devices/bus/waveblaster/waveblaster.cpp +++ b/src/devices/bus/waveblaster/waveblaster.cpp @@ -22,7 +22,6 @@ waveblaster_connector::waveblaster_connector(const machine_config &mconfig, cons void waveblaster_connector::device_start() { - save_item(NAME(m_dummy_save)); } void waveblaster_connector::midi_rx(int state) diff --git a/src/devices/bus/waveblaster/waveblaster.h b/src/devices/bus/waveblaster/waveblaster.h index 47d6558f966..bfc58e7b98a 100644 --- a/src/devices/bus/waveblaster/waveblaster.h +++ b/src/devices/bus/waveblaster/waveblaster.h @@ -31,7 +31,6 @@ public: void do_midi_tx(int state) { m_midi_tx(state); } protected: - bool m_dummy_save = false; // needed for save-state support devcb_write_line m_midi_tx; virtual void device_start() override ATTR_COLD; diff --git a/src/devices/machine/mc6852.h b/src/devices/machine/mc6852.h index c7862be4d1e..c7d0a3a6cbf 100644 --- a/src/devices/machine/mc6852.h +++ b/src/devices/machine/mc6852.h @@ -41,6 +41,8 @@ class mc6852_device : public device_t, public device_serial_interface { public: + static constexpr flags_type emulation_flags() { return flags::SAVE_UNSUPPORTED; } + // construction/destruction mc6852_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); diff --git a/src/devices/sound/mixer.cpp b/src/devices/sound/mixer.cpp index e92dc8fbfe1..3b8435182c4 100644 --- a/src/devices/sound/mixer.cpp +++ b/src/devices/sound/mixer.cpp @@ -27,6 +27,4 @@ mixer_device::mixer_device(const machine_config &mconfig, const char *tag, devic void mixer_device::device_start() { - // register for save states - save_item(NAME(m_dummy_save)); } diff --git a/src/devices/sound/mixer.h b/src/devices/sound/mixer.h index f467ec6d636..c54a006e364 100644 --- a/src/devices/sound/mixer.h +++ b/src/devices/sound/mixer.h @@ -20,11 +20,8 @@ public: mixer_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0); protected: - // device-level overrides + // device_t implementation virtual void device_start() override ATTR_COLD; - -private: - bool m_dummy_save = false; // needed for save-state support }; #endif // MAME_SOUND_MIXER_H diff --git a/src/emu/device.cpp b/src/emu/device.cpp index 1a66094bde9..272df837cd4 100644 --- a/src/emu/device.cpp +++ b/src/emu/device.cpp @@ -544,11 +544,10 @@ void device_t::start() // complain if nothing was registered by the device state_registrations = machine().save().registration_count() - state_registrations; device_execute_interface *exec; - device_sound_interface *sound; - if (state_registrations == 0 && (interface(exec) || interface(sound)) && type() != SPEAKER && type() != MICROPHONE) + if ((state_registrations == 0) && interface(exec)) { logerror("Device did not register any state to save!\n"); - if ((machine().system().flags & MACHINE_SUPPORTS_SAVE) != 0) + if (!(type().emulation_flags() & flags::SAVE_UNSUPPORTED)) fatalerror("Device '%s' did not register any state to save!\n", tag()); } diff --git a/src/emu/device.h b/src/emu/device.h index 87736144292..4c2e1d8a180 100644 --- a/src/emu/device.h +++ b/src/emu/device.h @@ -63,6 +63,18 @@ template using is_device_interface = std::bool_constant && !is_device_implementation::value>; +struct device_flags +{ + enum type : u16 + { + NOT_WORKING = u16(1) << 0, + SAVE_UNSUPPORTED = u16(1) << 1, + + NONE = u16(0), + ALL = (u16(1) << 2) - 1U + }; +}; + struct device_feature { enum type : u32 @@ -107,6 +119,7 @@ struct device_feature }; }; +DECLARE_ENUM_BITWISE_OPERATORS(device_flags::type); DECLARE_ENUM_BITWISE_OPERATORS(device_feature::type); @@ -165,14 +178,9 @@ private: template struct device_tag_struct { typedef DeviceClass type; }; -template +template struct driver_tag_struct { typedef DriverClass type; }; -template -auto device_tag_func() { return device_tag_struct{ }; }; -template -auto driver_tag_func() { return driver_tag_struct{ }; }; - class device_type_impl_base { private: @@ -205,6 +213,7 @@ private: char const *const m_shortname; char const *const m_fullname; char const *const m_source; + device_flags::type const m_emulation_flags; device_feature::type const m_unemulated_features; device_feature::type const m_imperfect_features; device_type_impl_base const *const m_parent_rom; @@ -220,6 +229,7 @@ public: , m_shortname(nullptr) , m_fullname(nullptr) , m_source(nullptr) + , m_emulation_flags(device_flags::NONE) , m_unemulated_features(device_feature::NONE) , m_imperfect_features(device_feature::NONE) , m_parent_rom(nullptr) @@ -228,12 +238,13 @@ public: } template - device_type_impl_base(device_tag_struct (*)()) + device_type_impl_base(device_tag_struct) : m_creator(&create_device) , m_type(typeid(DeviceClass)) , m_shortname(ShortName) , m_fullname(FullName) , m_source(Source) + , m_emulation_flags(DeviceClass::emulation_flags()) , m_unemulated_features(DeviceClass::unemulated_features()) , m_imperfect_features(DeviceClass::imperfect_features()) , m_parent_rom(DeviceClass::parent_rom_device_type()) @@ -241,13 +252,14 @@ public: { } - template - device_type_impl_base(driver_tag_struct (*)()) + template + device_type_impl_base(driver_tag_struct) : m_creator(&create_driver) , m_type(typeid(DriverClass)) , m_shortname(ShortName) , m_fullname(FullName) , m_source(Source) + , m_emulation_flags(DriverClass::emulation_flags() | Flags) , m_unemulated_features(DriverClass::unemulated_features() | Unemulated) , m_imperfect_features((DriverClass::imperfect_features() & ~Unemulated) | Imperfect) , m_parent_rom(DriverClass::parent_rom_device_type()) @@ -259,6 +271,7 @@ public: char const *shortname() const { return m_shortname; } char const *fullname() const { return m_fullname; } char const *source() const { return m_source; } + device_flags::type emulation_flags() const { return m_emulation_flags; } device_feature::type unemulated_features() const { return m_unemulated_features; } device_feature::type imperfect_features() const { return m_imperfect_features; } device_type_impl_base const *parent_rom_device_type() const { return m_parent_rom; } @@ -306,22 +319,6 @@ typedef emu::detail::device_type_impl_base const &device_type; typedef std::add_pointer_t device_type_ptr; extern emu::detail::device_registrar const registered_device_types; -template < - typename DeviceClass, - char const *ShortName, - char const *FullName, - char const *Source> -constexpr auto device_creator = &emu::detail::device_tag_func; - -template < - typename DriverClass, - char const *ShortName, - char const *FullName, - char const *Source, - emu::detail::device_feature::type Unemulated, - emu::detail::device_feature::type Imperfect> -constexpr auto driver_device_creator = &emu::detail::driver_tag_func; - /// \addtogroup machinedef /// \{ @@ -404,7 +401,7 @@ constexpr auto driver_device_creator = &emu::detail::driver_tag_func const Type = device_creator; \ + emu::detail::device_type_impl const Type = emu::detail::device_tag_struct{ }; \ template class device_finder; \ template class device_finder; @@ -440,7 +437,7 @@ constexpr auto driver_device_creator = &emu::detail::driver_tag_func const Type = device_creator; + emu::detail::device_type_impl const Type = emu::detail::device_tag_struct{ }; /// \} @@ -565,9 +562,22 @@ protected: public: // device flags + using flags = emu::detail::device_flags; + using flags_type = emu::detail::device_flags::type; using feature = emu::detail::device_feature; using feature_type = emu::detail::device_feature::type; + /// \brief Report emulation status flags + /// + /// Implement this member in a derived class to declare flags + /// pertaining to the overall emulation status of the device. Some + /// flags propagate to all other devices and systems that use the + /// device. + /// \return Bitwise or of the flag constants pertaining to the + /// device emulation. + /// \sa unemulated_features imperfect_features + static constexpr flags_type emulation_flags() { return flags::NONE; } + /// \brief Report unemulated features /// /// Implement this member in a derived class to declare features @@ -577,7 +587,7 @@ public: /// displayed on starting a system. /// \return Bitwise or of the feature constants for unemulated /// features of the device. - /// \sa imperfect_features + /// \sa emulation_flags imperfect_features static constexpr feature_type unemulated_features() { return feature::NONE; } /// \brief Report imperfectly emulated features @@ -594,7 +604,7 @@ public: /// in a red warning being displayed when starting a system. /// \return Bitwise or of the feature constants for imperfectly /// emulated features of the device. - /// \sa unemulated_features + /// \sa emulation_flags unemulated_features static constexpr feature_type imperfect_features() { return feature::NONE; } /// \brief Get parent device type for ROM search diff --git a/src/emu/gamedrv.h b/src/emu/gamedrv.h index 9f454923f17..b3a1087a66a 100644 --- a/src/emu/gamedrv.h +++ b/src/emu/gamedrv.h @@ -40,15 +40,13 @@ struct machine_flags ROT180 = FLIP_X | FLIP_Y, ROT270 = FLIP_Y | SWAP_XY, - NOT_WORKING = 0x0000'0040, - SUPPORTS_SAVE = 0x0000'0080, // system supports save states - NO_COCKTAIL = 0x0000'0100, // screen flip support is missing - IS_BIOS_ROOT = 0x0000'0200, // this driver entry is a BIOS root - REQUIRES_ARTWORK = 0x0000'0400, // requires external artwork for key game elements - UNOFFICIAL = 0x0000'0800, // unofficial hardware modification - NO_SOUND_HW = 0x0000'1000, // system has no sound output - MECHANICAL = 0x0000'2000, // contains mechanical parts (pinball, redemption games, ...) - IS_INCOMPLETE = 0x0000'4000 // official system with blatantly incomplete hardware/software + NO_COCKTAIL = 0x0000'0040, // screen flip support is missing + IS_BIOS_ROOT = 0x0000'0080, // this driver entry is a BIOS root + REQUIRES_ARTWORK = 0x0000'0100, // requires external artwork for key game elements + UNOFFICIAL = 0x0000'0200, // unofficial hardware modification + NO_SOUND_HW = 0x0000'0400, // system has no sound output + MECHANICAL = 0x0000'0800, // contains mechanical parts (pinball, redemption games, ...) + IS_INCOMPLETE = 0x0000'1000 // official system with blatantly incomplete hardware/software }; }; @@ -65,8 +63,6 @@ DECLARE_ENUM_BITWISE_OPERATORS(machine_flags::type); /// \{ // flags for machine drivers -constexpr u64 MACHINE_NOT_WORKING = machine_flags::NOT_WORKING; ///< Imperfect emulation prevents using the system as intended -constexpr u64 MACHINE_SUPPORTS_SAVE = machine_flags::SUPPORTS_SAVE; ///< All devices in the system supports save states (enables auto save feature, and won't show a warning on using save states) constexpr u64 MACHINE_NO_COCKTAIL = machine_flags::NO_COCKTAIL; ///< The system supports screen flipping for use in a cocktail cabinet, but this feature is not properly emulated constexpr u64 MACHINE_IS_BIOS_ROOT = machine_flags::IS_BIOS_ROOT; ///< The system represents an empty system board of some kind - clones are treated as separate systems rather than variants constexpr u64 MACHINE_REQUIRES_ARTWORK = machine_flags::REQUIRES_ARTWORK; ///< The system requires external artwork for key functionality @@ -75,18 +71,20 @@ constexpr u64 MACHINE_NO_SOUND_HW = machine_flags::NO_SOUND_HW; constexpr u64 MACHINE_MECHANICAL = machine_flags::MECHANICAL; ///< The system depends on mechanical features for key functionality constexpr u64 MACHINE_IS_INCOMPLETE = machine_flags::IS_INCOMPLETE; ///< The system represents an incomplete prototype -// flags that map to device feature flags -constexpr u64 MACHINE_UNEMULATED_PROTECTION = 0x00000001'00000000; ///< Some form of protection is imperfectly emulated (e.g. copy protection or anti-tampering) -constexpr u64 MACHINE_WRONG_COLORS = 0x00000002'00000000; ///< Colours are completely wrong -constexpr u64 MACHINE_IMPERFECT_COLORS = 0x00000004'00000000; ///< Colours are close but not completely accurate -constexpr u64 MACHINE_IMPERFECT_GRAPHICS = 0x00000008'00000000; ///< Graphics are emulated incorrectly for the system -constexpr u64 MACHINE_NO_SOUND = 0x00000010'00000000; ///< The system has sound output, but it is not emulated -constexpr u64 MACHINE_IMPERFECT_SOUND = 0x00000020'00000000; ///< Sound is known to be imperfectly emulated for the system -constexpr u64 MACHINE_IMPERFECT_CONTROLS = 0x00000040'00000000; ///< Controls or inputs are emulated imperfectly for the system -constexpr u64 MACHINE_NODEVICE_MICROPHONE = 0x00000080'00000000; ///< The system has unemulated audio capture functionality -constexpr u64 MACHINE_NODEVICE_PRINTER = 0x00000100'00000000; ///< The system has unemulated printer functionality -constexpr u64 MACHINE_NODEVICE_LAN = 0x00000200'00000000; ///< The system has unemulated local area networking -constexpr u64 MACHINE_IMPERFECT_TIMING = 0x00000400'00000000; ///< Timing is known to be imperfectly emulated for the system +// flags that map to device emulation and feature flags +constexpr u64 MACHINE_NOT_WORKING = 0x00000001'00000000; ///< Imperfect emulation prevents using the system as intended +constexpr u64 MACHINE_SUPPORTS_SAVE = 0x00000002'00000000; ///< All devices in the system supports save states (enables auto save feature, and won't show a warning on using save states) +constexpr u64 MACHINE_UNEMULATED_PROTECTION = 0x00000004'00000000; ///< Some form of protection is imperfectly emulated (e.g. copy protection or anti-tampering) +constexpr u64 MACHINE_WRONG_COLORS = 0x00000008'00000000; ///< Colours are completely wrong +constexpr u64 MACHINE_IMPERFECT_COLORS = 0x00000010'00000000; ///< Colours are close but not completely accurate +constexpr u64 MACHINE_IMPERFECT_GRAPHICS = 0x00000020'00000000; ///< Graphics are emulated incorrectly for the system +constexpr u64 MACHINE_NO_SOUND = 0x00000040'00000000; ///< The system has sound output, but it is not emulated +constexpr u64 MACHINE_IMPERFECT_SOUND = 0x00000080'00000000; ///< Sound is known to be imperfectly emulated for the system +constexpr u64 MACHINE_IMPERFECT_CONTROLS = 0x00000100'00000000; ///< Controls or inputs are emulated imperfectly for the system +constexpr u64 MACHINE_NODEVICE_MICROPHONE = 0x00000200'00000000; ///< The system has unemulated audio capture functionality +constexpr u64 MACHINE_NODEVICE_PRINTER = 0x00000400'00000000; ///< The system has unemulated printer functionality +constexpr u64 MACHINE_NODEVICE_LAN = 0x00000800'00000000; ///< The system has unemulated local area networking +constexpr u64 MACHINE_IMPERFECT_TIMING = 0x00001000'00000000; ///< Timing is known to be imperfectly emulated for the system /// \} /// \} @@ -107,6 +105,20 @@ public: typedef void (*machine_creator_wrapper)(machine_config &, device_t &); typedef void (*driver_init_wrapper)(device_t &); + /// \brief Get emulation flags + /// + /// Converts system flags corresponding to device emulation flags to + /// a device flags type bit field. + /// \param [in] flags A system flags bit field. + /// \return A device flags type bit field corresponding to emulation + /// flags declared in the \p flags argument. + static constexpr device_t::flags_type emulation_flags(u64 flags) + { + return + ((flags & MACHINE_NOT_WORKING) ? device_t::flags::NOT_WORKING : device_t::flags::NONE) | + ((flags & MACHINE_SUPPORTS_SAVE) ? device_t::flags::NONE : device_t::flags::SAVE_UNSUPPORTED); + } + /// \brief Get unemulated system features /// /// Converts system flags corresponding to unemulated device @@ -169,18 +181,19 @@ public: // static game traits #define GAME_DRIVER_TRAITS(NAME, FULLNAME) \ -namespace { \ - struct GAME_TRAITS_NAME(NAME) { static constexpr char const shortname[] = #NAME, fullname[] = FULLNAME, source[] = __FILE__; }; \ - constexpr char const GAME_TRAITS_NAME(NAME)::shortname[], GAME_TRAITS_NAME(NAME)::fullname[], GAME_TRAITS_NAME(NAME)::source[]; \ -} + namespace { \ + struct GAME_TRAITS_NAME(NAME) { static constexpr char const shortname[] = #NAME, fullname[] = FULLNAME, source[] = __FILE__; }; \ + constexpr char const GAME_TRAITS_NAME(NAME)::shortname[], GAME_TRAITS_NAME(NAME)::fullname[], GAME_TRAITS_NAME(NAME)::source[]; \ + } #define GAME_DRIVER_TYPE(NAME, CLASS, FLAGS) \ -driver_device_creator< \ - CLASS, \ - (GAME_TRAITS_NAME(NAME)::shortname), \ - (GAME_TRAITS_NAME(NAME)::fullname), \ - (GAME_TRAITS_NAME(NAME)::source), \ - game_driver::unemulated_features(FLAGS), \ - game_driver::imperfect_features(FLAGS)> + emu::detail::driver_tag_struct< \ + CLASS, \ + (GAME_TRAITS_NAME(NAME)::shortname), \ + (GAME_TRAITS_NAME(NAME)::fullname), \ + (GAME_TRAITS_NAME(NAME)::source), \ + game_driver::emulation_flags(FLAGS), \ + game_driver::unemulated_features(FLAGS), \ + game_driver::imperfect_features(FLAGS)>{ } /// \addtogroup machinedef diff --git a/src/emu/machine.cpp b/src/emu/machine.cpp index 859e6b4506f..a77140dba16 100644 --- a/src/emu/machine.cpp +++ b/src/emu/machine.cpp @@ -234,14 +234,28 @@ void running_machine::start() if (filename[0] != 0 && !m_video->is_recording()) m_video->begin_recording(filename, movie_recording::format::AVI); - // if we're coming in with a savegame request, process it now const char *savegame = options().state(); if (savegame[0] != 0) + { + // if we're coming in with a savegame request, process it now schedule_load(savegame); - - // if we're in autosave mode, schedule a load - else if (options().autosave() && (m_system.flags & MACHINE_SUPPORTS_SAVE) != 0) - schedule_load("auto"); + } + else if (options().autosave()) + { + // if we're in autosave mode, schedule a load + // m_save.supported() won't be set until save state registrations are finalised + bool supported = true; + for (device_t &device : device_enumerator(root_device())) + { + if (device.type().emulation_flags() & device_t::flags::SAVE_UNSUPPORTED) + { + supported = false; + break; + } + } + if (supported) + schedule_load("auto"); + } manager().update_machine(); } @@ -286,15 +300,13 @@ int running_machine::run(bool quiet) // then finish setting up our local machine start(); + // disallow save state registrations starting here + m_save.allow_registration(false); + // load the configuration settings manager().before_load_settings(*this); m_configuration->load_settings(); - // disallow save state registrations starting here. - // Don't do it earlier, config load can create network - // devices with timers. - m_save.allow_registration(false); - // load the NVRAM nvram_load(); @@ -413,7 +425,7 @@ void running_machine::schedule_exit() m_scheduler.eat_all_cycles(); // if we're autosaving on exit, schedule a save as well - if (options().autosave() && (m_system.flags & MACHINE_SUPPORTS_SAVE) && this->time() > attotime::zero) + if (options().autosave() && m_save.supported() && (this->time() > attotime::zero)) schedule_save("auto"); } @@ -910,7 +922,7 @@ void running_machine::handle_saveload() case STATERR_NONE: { const char *const opnamed = (m_saveload_schedule == saveload_schedule::LOAD) ? "Loaded" : "Saved"; - if (!(m_system.flags & MACHINE_SUPPORTS_SAVE)) + if (!m_save.supported()) popmessage("%s state %s %s.\nWarning: Save states are not officially supported for this system.", opnamed, preposname, m_saveload_pending_file); else popmessage("%s state %s %s.", opnamed, preposname, m_saveload_pending_file); diff --git a/src/emu/save.cpp b/src/emu/save.cpp index 6b3d4bbdeb6..35599c2e679 100644 --- a/src/emu/save.cpp +++ b/src/emu/save.cpp @@ -67,6 +67,7 @@ enum save_manager::save_manager(running_machine &machine) : m_machine(machine) , m_reg_allowed(true) + , m_supported(false) { m_rewind = std::make_unique(*this); } @@ -100,6 +101,16 @@ void save_manager::allow_registration(bool allowed) if (dupes_found) fatalerror("%d duplicate save state entries found.\n", dupes_found); + m_supported = true; + for (device_t &device : device_enumerator(machine().root_device())) + { + if (device.type().emulation_flags() & device_t::flags::SAVE_UNSUPPORTED) + { + m_supported = false; + break; + } + } + dump_registry(); // everything is registered by now, evaluate the savestate size @@ -934,7 +945,7 @@ void rewinder::report_error(save_error error, rewind_operation operation) // success case STATERR_NONE: { - const u64 supported = m_save.machine().system().flags & MACHINE_SUPPORTS_SAVE; + const u64 supported = m_save.supported(); const char *const warning = supported || !m_first_time_warning ? "" : "Rewind warning: Save states are not officially supported for this machine.\n"; const char *const opnamed = (operation == rewind_operation::LOAD) ? "loaded" : "captured"; diff --git a/src/emu/save.h b/src/emu/save.h index e473f408317..066f20f3330 100644 --- a/src/emu/save.h +++ b/src/emu/save.h @@ -159,6 +159,7 @@ public: rewinder *rewind() { return m_rewind.get(); } int registration_count() const { return m_entry_list.size(); } bool registration_allowed() const { return m_reg_allowed; } + bool supported() const { return m_supported; } // registration control void allow_registration(bool allowed = true); @@ -333,6 +334,7 @@ private: running_machine & m_machine; // reference to our machine std::unique_ptr m_rewind; // rewinder bool m_reg_allowed; // are registrations allowed? + bool m_supported; // are saved states supported? std::vector> m_entry_list; // list of registered entries std::vector> m_ramstate_list; // list of ram states diff --git a/src/emu/validity.cpp b/src/emu/validity.cpp index f7200416e89..92b141f269e 100644 --- a/src/emu/validity.cpp +++ b/src/emu/validity.cpp @@ -2144,6 +2144,49 @@ void validity_checker::validate_driver(device_t &root) osd_printf_error("Driver cannot have features that are both unemulated and imperfect (0x%08X)\n", util::underlying_value(unemulated & imperfect)); if ((m_current_driver->flags & machine_flags::NO_SOUND_HW) && ((unemulated | imperfect) & device_t::feature::SOUND)) osd_printf_error("Machine without sound hardware cannot have unemulated/imperfect sound\n"); + + // catch systems marked as supporting save states that contain devices that don't support save states + if (!(m_current_driver->type.emulation_flags() & device_t::flags::SAVE_UNSUPPORTED)) + { + std::set > nosave; + device_enumerator iter(root); + std::string_view cardtag; + for (auto &device : iter) + { + // ignore any children of a slot card + if (!cardtag.empty()) + { + std::string_view tag(device.tag()); + if ((tag.length() > cardtag.length()) && (tag.substr(0, cardtag.length()) == cardtag) && tag[cardtag.length()] == ':') + continue; + else + cardtag = std::string_view(); + } + + // check to see if this is a slot card + device_t *const parent(device.owner()); + if (parent) + { + device_slot_interface *slot; + parent->interface(slot); + if (slot && (slot->get_card_device() == &device)) + { + cardtag = device.tag(); + continue; + } + } + + if (device.type().emulation_flags() & device_t::flags::SAVE_UNSUPPORTED) + nosave.emplace(&device.type()); + } + if (!nosave.empty()) + { + std::ostringstream buf; + for (auto const &devtype : nosave) + util::stream_format(buf, "%s(%s) %s\n", core_filename_extract_base(devtype->source()), devtype->shortname(), devtype->fullname()); + osd_printf_error("Machine is marked as supporting save states but uses devices that lack save state support:\n%s", std::move(buf).str()); + } + } } diff --git a/src/frontend/mame/infoxml.cpp b/src/frontend/mame/infoxml.cpp index 1318fa12fda..46978109432 100644 --- a/src/frontend/mame/infoxml.cpp +++ b/src/frontend/mame/infoxml.cpp @@ -143,7 +143,7 @@ void output_input(std::ostream &out, const ioport_list &portlist); void output_switches(std::ostream &out, const ioport_list &portlist, const char *root_tag, int type, const char *outertag, const char *loctag, const char *innertag); void output_ports(std::ostream &out, const ioport_list &portlist); void output_adjusters(std::ostream &out, const ioport_list &portlist); -void output_driver(std::ostream &out, game_driver const &driver, device_t::feature_type unemulated, device_t::feature_type imperfect); +void output_driver(std::ostream &out, game_driver const &driver, device_t::flags_type flags, device_t::feature_type unemulated, device_t::feature_type imperfect); void output_features(std::ostream &out, device_type type, device_t::feature_type unemulated, device_t::feature_type imperfect); void output_images(std::ostream &out, device_t &device, const char *root_tag); void output_slots(std::ostream &out, machine_config &config, device_t &device, const char *root_tag, device_type_set *devtypes); @@ -699,6 +699,7 @@ void output_one(std::ostream &out, driver_enumerator &drivlist, const game_drive // allocate input ports and build overall emulation status ioport_list portlist; + device_t::flags_type overall_flags(driver.type.emulation_flags()); device_t::feature_type overall_unemulated(driver.type.unemulated_features()); device_t::feature_type overall_imperfect(driver.type.imperfect_features()); { @@ -706,6 +707,7 @@ void output_one(std::ostream &out, driver_enumerator &drivlist, const game_drive for (device_t &device : iter) { portlist.append(device, errors); + overall_flags |= device.type().emulation_flags() & ~device_t::flags::NOT_WORKING; overall_unemulated |= device.type().unemulated_features(); overall_imperfect |= device.type().imperfect_features(); @@ -791,7 +793,7 @@ void output_one(std::ostream &out, driver_enumerator &drivlist, const game_drive output_switches(out, portlist, "", IPT_CONFIG, "configuration", "conflocation", "confsetting"); output_ports(out, portlist); output_adjusters(out, portlist); - output_driver(out, driver, overall_unemulated, overall_imperfect); + output_driver(out, driver, overall_flags, overall_unemulated, overall_imperfect); output_features(out, driver.type, overall_unemulated, overall_imperfect); output_images(out, config.root_device(), ""); output_slots(out, config, config.root_device(), "", devtypes); @@ -1998,7 +2000,12 @@ void output_adjusters(std::ostream &out, const ioport_list &portlist) // output_driver - print driver status //------------------------------------------------- -void output_driver(std::ostream &out, game_driver const &driver, device_t::feature_type unemulated, device_t::feature_type imperfect) +void output_driver( + std::ostream &out, + game_driver const &driver, + device_t::flags_type flags, + device_t::feature_type unemulated, + device_t::feature_type imperfect) { out << "\t\t\n"; diff --git a/src/frontend/mame/luaengine.cpp b/src/frontend/mame/luaengine.cpp index 54693cd4536..ece3c0ceccb 100644 --- a/src/frontend/mame/luaengine.cpp +++ b/src/frontend/mame/luaengine.cpp @@ -1527,8 +1527,8 @@ void lua_engine::initialize() } return rot; }); - game_driver_type["not_working"] = sol::property([] (game_driver const &driver) { return (driver.flags & machine_flags::NOT_WORKING) != 0; }); - game_driver_type["supports_save"] = sol::property([] (game_driver const &driver) { return (driver.flags & machine_flags::SUPPORTS_SAVE) != 0; }); + game_driver_type["not_working"] = sol::property([] (game_driver const &driver) { return (driver.type.emulation_flags() & device_t::flags::NOT_WORKING) != 0; }); + game_driver_type["supports_save"] = sol::property([] (game_driver const &driver) { return (driver.type.emulation_flags() & device_t::flags::SAVE_UNSUPPORTED) == 0; }); game_driver_type["no_cocktail"] = sol::property([] (game_driver const &driver) { return (driver.flags & machine_flags::NO_COCKTAIL) != 0; }); game_driver_type["is_bios_root"] = sol::property([] (game_driver const &driver) { return (driver.flags & machine_flags::IS_BIOS_ROOT) != 0; }); game_driver_type["requires_artwork"] = sol::property([] (game_driver const &driver) { return (driver.flags & machine_flags::REQUIRES_ARTWORK) != 0; }); diff --git a/src/frontend/mame/ui/info.cpp b/src/frontend/mame/ui/info.cpp index 7176779ea02..8c08af9a4c6 100644 --- a/src/frontend/mame/ui/info.cpp +++ b/src/frontend/mame/ui/info.cpp @@ -36,9 +36,10 @@ namespace ui { namespace { -constexpr machine_flags::type MACHINE_ERRORS = machine_flags::NOT_WORKING | machine_flags::MECHANICAL; +constexpr machine_flags::type MACHINE_ERRORS = machine_flags::MECHANICAL; constexpr machine_flags::type MACHINE_WARNINGS = machine_flags::NO_COCKTAIL | machine_flags::REQUIRES_ARTWORK; constexpr machine_flags::type MACHINE_BTANB = machine_flags::NO_SOUND_HW | machine_flags::IS_INCOMPLETE; +constexpr device_t::flags_type DEVICE_ERRORS = device_t::flags::NOT_WORKING; constexpr std::pair FEATURE_NAMES[] = { { device_t::feature::PROTECTION, N_p("emulation-feature", "protection") }, @@ -63,7 +64,14 @@ constexpr std::pair FEATURE_NAMES[] = { { device_t::feature::LAN, N_p("emulation-feature", "LAN") }, { device_t::feature::WAN, N_p("emulation-feature", "WAN") } }; -void get_general_warnings(std::ostream &buf, running_machine &machine, machine_flags::type flags, device_t::feature_type unemulated, device_t::feature_type imperfect) +void get_general_warnings( + std::ostream &buf, + running_machine &machine, + machine_flags::type machflags, + device_t::flags_type devflags, + device_t::feature_type unemulated, + device_t::feature_type imperfect, + bool has_nonworking_devices) { // add a warning if any ROMs were loaded with warnings bool bad_roms(false); @@ -79,7 +87,7 @@ void get_general_warnings(std::ostream &buf, running_machine &machine, machine_f } // if we have at least one warning flag, print the general header - if ((machine.rom_load().knownbad() > 0) || (flags & (MACHINE_ERRORS | MACHINE_WARNINGS | MACHINE_BTANB)) || unemulated || imperfect) + if ((machine.rom_load().knownbad() > 0) || (machflags & (MACHINE_ERRORS | MACHINE_WARNINGS | MACHINE_BTANB)) || (devflags & DEVICE_ERRORS) || unemulated || imperfect || has_nonworking_devices) { if (bad_roms) buf << '\n'; @@ -91,8 +99,12 @@ void get_general_warnings(std::ostream &buf, running_machine &machine, machine_f buf << _("One or more ROMs/disk images for this system have not been correctly dumped.\n"); } -void get_device_warnings(std::ostream &buf, device_t::feature_type unemulated, device_t::feature_type imperfect) +void get_device_warnings(std::ostream &buf, device_t::flags_type flags, device_t::feature_type unemulated, device_t::feature_type imperfect) { + // add line for not working + if (flags & device_t::flags::NOT_WORKING) + buf << _("THIS DEVICE DOES NOT WORK.\n"); + // add line for unemulated features if (unemulated) { @@ -126,48 +138,74 @@ void get_device_warnings(std::ostream &buf, device_t::feature_type unemulated, d } } -void get_system_warnings(std::ostream &buf, running_machine &machine, machine_flags::type flags, device_t::feature_type unemulated, device_t::feature_type imperfect) +void get_system_warnings( + std::ostream &buf, + running_machine &machine, + machine_flags::type machflags, + device_t::flags_type devflags, + device_t::feature_type unemulated, + device_t::feature_type imperfect, + bool has_nonworking_devices) { std::streampos start_position = buf.tellp(); // start with the unemulated/imperfect features - get_device_warnings(buf, unemulated, imperfect); + get_device_warnings(buf, device_t::flags::NONE, unemulated, imperfect); // add one line per machine warning flag - if (flags & ::machine_flags::NO_COCKTAIL) + if (machflags & ::machine_flags::NO_COCKTAIL) buf << _("Screen flipping in cocktail mode is not supported.\n"); - if (flags & ::machine_flags::REQUIRES_ARTWORK) + if (machflags & ::machine_flags::REQUIRES_ARTWORK) buf << _("This system requires external artwork files.\n"); // add the 'BTANB' warnings - if (flags & ::machine_flags::IS_INCOMPLETE) + if (machflags & ::machine_flags::IS_INCOMPLETE) { if (buf.tellp() > start_position) buf << '\n'; buf << _("This system was never completed. It may exhibit strange behavior or missing elements that are not bugs in the emulation.\n"); } - if (flags & ::machine_flags::NO_SOUND_HW) + if (machflags & ::machine_flags::NO_SOUND_HW) { if (buf.tellp() > start_position) buf << '\n'; buf << _("This system has no sound hardware, MAME will produce no sounds, this is expected behavior.\n"); } + // list devices that don't work + if (has_nonworking_devices) + { + if (buf.tellp() > start_position) + buf << '\n'; + buf << _("The following devices do not work: "); + bool first = true; + std::set > seen; + for (device_t &device : device_enumerator(machine.root_device())) + { + if ((device.type().emulation_flags() & device_t::flags::NOT_WORKING) && seen.insert(&device.type()).second) + { + util::stream_format(buf, first ? _("%s") : _(", %s"), device.type().fullname()); + first = false; + } + } + buf << '\n'; + } + // these are more severe warnings - if (flags & ::machine_flags::MECHANICAL) + if (machflags & ::machine_flags::MECHANICAL) { if (buf.tellp() > start_position) buf << '\n'; buf << _("Elements of this system cannot be emulated accurately as they require physical interaction or consist of mechanical devices. It is not possible to fully experience this system.\n"); } - if (flags & ::machine_flags::NOT_WORKING) + if (devflags & device_t::flags::NOT_WORKING) { if (buf.tellp() > start_position) buf << '\n'; buf << _("THIS SYSTEM DOESN'T WORK. The emulation for this system 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 ((flags & MACHINE_ERRORS) || ((machine.system().type.unemulated_features() | machine.system().type.imperfect_features()) & device_t::feature::PROTECTION)) + if ((machflags & MACHINE_ERRORS) || (devflags & DEVICE_ERRORS) || ((machine.system().type.unemulated_features() | machine.system().type.imperfect_features()) & device_t::feature::PROTECTION)) { // find the parent of this driver driver_enumerator drivlist(machine.options()); @@ -183,7 +221,7 @@ void get_system_warnings(std::ostream &buf, running_machine &machine, machine_fl if (drivlist.current() == maindrv || drivlist.clone() == maindrv) { game_driver const &driver(drivlist.driver()); - if (!(driver.flags & MACHINE_ERRORS) && !((driver.type.unemulated_features() | driver.type.imperfect_features()) & device_t::feature::PROTECTION)) + if (!(driver.flags & MACHINE_ERRORS) && !(driver.type.emulation_flags() & DEVICE_ERRORS) && !((driver.type.unemulated_features() | driver.type.imperfect_features()) & device_t::feature::PROTECTION)) { // this one works, add a header and display the name of the clone if (!foundworking) @@ -220,8 +258,10 @@ machine_static_info::machine_static_info(const ui_options &options, machine_conf machine_static_info::machine_static_info(const ui_options &options, machine_config const &config, ioport_list const *ports) : m_options(options) , m_flags(config.gamedrv().flags) + , m_emulation_flags(config.gamedrv().type.emulation_flags()) , m_unemulated_features(config.gamedrv().type.unemulated_features()) , m_imperfect_features(config.gamedrv().type.imperfect_features()) + , m_has_nonworking_devices(false) , m_has_bioses(false) , m_has_dips(false) , m_has_configs(false) @@ -238,8 +278,10 @@ machine_static_info::machine_static_info(const ui_options &options, machine_conf m_flags &= ~::machine_flags::NO_SOUND_HW; // build overall emulation status + m_emulation_flags |= device.type().emulation_flags() & ~device_t::flags::NOT_WORKING; m_unemulated_features |= device.type().unemulated_features(); m_imperfect_features |= device.type().imperfect_features(); + m_has_nonworking_devices = m_has_nonworking_devices || (device.type().emulation_flags() & device_t::flags::NOT_WORKING); // look for BIOS options device_t const *const parent(device.owner()); @@ -297,9 +339,14 @@ machine_static_info::machine_static_info(const ui_options &options, machine_conf // issues that warrant a yellow/red message //------------------------------------------------- -bool machine_static_info::has_warnings() const +bool machine_static_info::has_warnings() const noexcept { - return (machine_flags() & (MACHINE_ERRORS | MACHINE_WARNINGS)) || unemulated_features() || imperfect_features(); + return + (machine_flags() & (MACHINE_ERRORS | MACHINE_WARNINGS)) || + (emulation_flags() & DEVICE_ERRORS) || + unemulated_features() || + imperfect_features() || + has_nonworking_devices(); } @@ -308,10 +355,11 @@ bool machine_static_info::has_warnings() const // system has issues that warrant a red message //------------------------------------------------- -bool machine_static_info::has_severe_warnings() const +bool machine_static_info::has_severe_warnings() const noexcept { return (machine_flags() & MACHINE_ERRORS) || + (emulation_flags() & DEVICE_ERRORS) || (unemulated_features() & (device_t::feature::PROTECTION | device_t::feature::GRAPHICS | device_t::feature::SOUND)) || (imperfect_features() & device_t::feature::PROTECTION); } @@ -322,7 +370,7 @@ bool machine_static_info::has_severe_warnings() const // driver status box //------------------------------------------------- -rgb_t machine_static_info::status_color() const +rgb_t machine_static_info::status_color() const noexcept { if (has_severe_warnings()) return UI_RED_COLOR; @@ -338,7 +386,7 @@ rgb_t machine_static_info::status_color() const // warning message based on severity //------------------------------------------------- -rgb_t machine_static_info::warnings_color() const +rgb_t machine_static_info::warnings_color() const noexcept { if (has_severe_warnings()) return UI_RED_COLOR; @@ -373,8 +421,8 @@ machine_info::machine_info(running_machine &machine) std::string machine_info::warnings_string() const { std::ostringstream buf; - get_general_warnings(buf, m_machine, machine_flags(), unemulated_features(), imperfect_features()); - get_system_warnings(buf, m_machine, machine_flags(), unemulated_features(), imperfect_features()); + get_general_warnings(buf, m_machine, machine_flags(), emulation_flags(), unemulated_features(), imperfect_features(), has_nonworking_devices()); + get_system_warnings(buf, m_machine, machine_flags(), emulation_flags(), unemulated_features(), imperfect_features(), has_nonworking_devices()); return buf.str(); } @@ -600,26 +648,26 @@ void menu_warn_info::populate_text(std::optional &layout, float &wi machine_info const &info(ui().machine_info()); device_t &root(machine().root_device()); - get_general_warnings(buf, machine(), info.machine_flags(), info.unemulated_features(), info.imperfect_features()); - if ((info.machine_flags() & (MACHINE_ERRORS | MACHINE_WARNINGS | MACHINE_BTANB)) || root.type().unemulated_features() || root.type().imperfect_features()) + get_general_warnings(buf, machine(), info.machine_flags(), info.emulation_flags(), info.unemulated_features(), info.imperfect_features(), info.has_nonworking_devices()); + if ((info.machine_flags() & (MACHINE_ERRORS | MACHINE_WARNINGS | MACHINE_BTANB)) || (root.type().emulation_flags() & DEVICE_ERRORS) || root.type().unemulated_features() || root.type().imperfect_features()) { seen.insert(&root.type()); if (!first) buf << '\n'; first = false; util::stream_format(buf, _("%1$s:\n"), root.name()); - get_system_warnings(buf, machine(), info.machine_flags(), root.type().unemulated_features(), root.type().imperfect_features()); + get_system_warnings(buf, machine(), info.machine_flags(), root.type().emulation_flags(), root.type().unemulated_features(), root.type().imperfect_features(), false); } for (device_t const &device : device_enumerator(root)) { - if ((device.type().unemulated_features() || device.type().imperfect_features()) && seen.insert(&device.type()).second) + if (((device.type().emulation_flags() & DEVICE_ERRORS) || device.type().unemulated_features() || device.type().imperfect_features()) && seen.insert(&device.type()).second) { if (!first) buf << '\n'; first = false; util::stream_format(buf, _("%1$s:\n"), device.name()); - get_device_warnings(buf, device.type().unemulated_features(), device.type().imperfect_features()); + get_device_warnings(buf, device.type().emulation_flags(), device.type().unemulated_features(), device.type().imperfect_features()); } } diff --git a/src/frontend/mame/ui/info.h b/src/frontend/mame/ui/info.h index c1b5d318a69..49e67dea5ae 100644 --- a/src/frontend/mame/ui/info.h +++ b/src/frontend/mame/ui/info.h @@ -30,25 +30,27 @@ public: machine_static_info(const ui_options &options, machine_config const &config); // overall emulation status - ::machine_flags::type machine_flags() const { return m_flags; } - device_t::feature_type unemulated_features() const { return m_unemulated_features; } - device_t::feature_type imperfect_features() const { return m_imperfect_features; } + ::machine_flags::type machine_flags() const noexcept { return m_flags; } + device_t::flags_type emulation_flags() const noexcept { return m_emulation_flags; } + device_t::feature_type unemulated_features() const noexcept { return m_unemulated_features; } + device_t::feature_type imperfect_features() const noexcept { return m_imperfect_features; } // has... getters - bool has_bioses() const { return m_has_bioses; } + bool has_nonworking_devices() const noexcept { return m_has_nonworking_devices; } + bool has_bioses() const noexcept { return m_has_bioses; } // has input types getters - bool has_dips() const { return m_has_dips; } - bool has_configs() const { return m_has_configs; } - bool has_keyboard() const { return m_has_keyboard; } - bool has_test_switch() const { return m_has_test_switch; } - bool has_analog() const { return m_has_analog; } + bool has_dips() const noexcept { return m_has_dips; } + bool has_configs() const noexcept { return m_has_configs; } + bool has_keyboard() const noexcept { return m_has_keyboard; } + bool has_test_switch() const noexcept { return m_has_test_switch; } + bool has_analog() const noexcept { return m_has_analog; } // warning severity indications - bool has_warnings() const; - bool has_severe_warnings() const; - rgb_t status_color() const; - rgb_t warnings_color() const; + bool has_warnings() const noexcept; + bool has_severe_warnings() const noexcept; + rgb_t status_color() const noexcept; + rgb_t warnings_color() const noexcept; protected: machine_static_info(const ui_options &options, machine_config const &config, ioport_list const &ports); @@ -60,10 +62,12 @@ private: // overall feature status ::machine_flags::type m_flags; + device_t::flags_type m_emulation_flags; device_t::feature_type m_unemulated_features; device_t::feature_type m_imperfect_features; // has... + bool m_has_nonworking_devices; bool m_has_bioses; // has input types diff --git a/src/frontend/mame/ui/mainmenu.cpp b/src/frontend/mame/ui/mainmenu.cpp index c7b23b8d19f..84c6b3d1500 100644 --- a/src/frontend/mame/ui/mainmenu.cpp +++ b/src/frontend/mame/ui/mainmenu.cpp @@ -126,7 +126,7 @@ void menu_main::populate() item_append(_("menu-main", "System Information"), 0, (void *)GAME_INFO); - if (ui().found_machine_warnings()) + if (ui().machine_info().has_warnings()) item_append(_("menu-main", "Warning Information"), 0, (void *)WARN_INFO); for (device_image_interface &image : image_interface_enumerator(machine().root_device())) diff --git a/src/frontend/mame/ui/selmenu.cpp b/src/frontend/mame/ui/selmenu.cpp index c32f04d27e6..a9d4c9e9bed 100644 --- a/src/frontend/mame/ui/selmenu.cpp +++ b/src/frontend/mame/ui/selmenu.cpp @@ -222,6 +222,7 @@ template void menu_select_launch::draw_left_panel(u32 flags, so menu_select_launch::system_flags::system_flags(machine_static_info const &info) : m_machine_flags(info.machine_flags()) + , m_emulation_flags(info.emulation_flags()) , m_unemulated_features(info.unemulated_features()) , m_imperfect_features(info.imperfect_features()) , m_has_keyboard(info.has_keyboard()) @@ -873,7 +874,7 @@ void menu_select_launch::custom_render(uint32_t flags, void *selectedref, float // next line is overall driver status system_flags const &flags(get_system_flags(driver)); - if (flags.machine_flags() & machine_flags::NOT_WORKING) + if (flags.emulation_flags() & device_t::flags::NOT_WORKING) tempbuf[2] = _("Status: NOT WORKING"); else if ((flags.unemulated_features() | flags.imperfect_features()) & device_t::feature::PROTECTION) tempbuf[2] = _("Status: Unemulated Protection"); @@ -4150,7 +4151,7 @@ void menu_select_launch::general_info(ui_system_info const *system, game_driver if (flags.has_keyboard()) str << _("Keyboard Inputs\tYes\n"); - if (flags.machine_flags() & machine_flags::NOT_WORKING) + if (flags.emulation_flags() & device_t::flags::NOT_WORKING) str << _("Overall\tNOT WORKING\n"); else if ((flags.unemulated_features() | flags.imperfect_features()) & device_t::feature::PROTECTION) str << _("Overall\tUnemulated Protection\n"); @@ -4262,13 +4263,13 @@ void menu_select_launch::general_info(ui_system_info const *system, game_driver else if (flags.imperfect_features() & device_t::feature::TIMING) str << _("Timing\tImperfect\n"); - str << ((flags.machine_flags() & machine_flags::MECHANICAL) ? _("Mechanical System\tYes\n") : _("Mechanical System\tNo\n")); - str << ((flags.machine_flags() & machine_flags::REQUIRES_ARTWORK) ? _("Requires Artwork\tYes\n") : _("Requires Artwork\tNo\n")); + str << ((flags.machine_flags() & machine_flags::MECHANICAL) ? _("Mechanical System\tYes\n") : _("Mechanical System\tNo\n")); + str << ((flags.machine_flags() & machine_flags::REQUIRES_ARTWORK) ? _("Requires Artwork\tYes\n") : _("Requires Artwork\tNo\n")); if (flags.machine_flags() & machine_flags::NO_COCKTAIL) str << _("Support Cocktail\tNo\n"); - str << ((flags.machine_flags() & machine_flags::IS_BIOS_ROOT) ? _("System is BIOS\tYes\n") : _("System is BIOS\tNo\n")); - str << ((flags.machine_flags() & machine_flags::SUPPORTS_SAVE) ? _("Support Save\tYes\n") : _("Support Save\tNo\n")); - str << ((flags.machine_flags() & ORIENTATION_SWAP_XY) ? _("Screen Orientation\tVertical\n") : _("Screen Orientation\tHorizontal\n")); + str << ((flags.machine_flags() & machine_flags::IS_BIOS_ROOT) ? _("System is BIOS\tYes\n") : _("System is BIOS\tNo\n")); + str << ((flags.emulation_flags() & device_t::flags::SAVE_UNSUPPORTED) ? _("Support Save\tNo\n") : _("Support Save\tYes\n")); + str << ((flags.machine_flags() & ORIENTATION_SWAP_XY) ? _("Screen Orientation\tVertical\n") : _("Screen Orientation\tHorizontal\n")); bool found = false; for (romload::region const ®ion : romload::entries(driver.rom).get_regions()) { diff --git a/src/frontend/mame/ui/selmenu.h b/src/frontend/mame/ui/selmenu.h index 3d1409ab68e..f95dd8fb163 100644 --- a/src/frontend/mame/ui/selmenu.h +++ b/src/frontend/mame/ui/selmenu.h @@ -88,6 +88,7 @@ protected: system_flags &operator=(system_flags &&) = default; ::machine_flags::type machine_flags() const { return m_machine_flags; } + device_t::flags_type emulation_flags() const { return m_emulation_flags; } device_t::feature_type unemulated_features() const { return m_unemulated_features; } device_t::feature_type imperfect_features() const { return m_imperfect_features; } bool has_keyboard() const { return m_has_keyboard; } @@ -96,6 +97,7 @@ protected: private: ::machine_flags::type m_machine_flags; + device_t::flags_type m_emulation_flags; device_t::feature_type m_unemulated_features; device_t::feature_type m_imperfect_features; bool m_has_keyboard; diff --git a/src/frontend/mame/ui/simpleselgame.cpp b/src/frontend/mame/ui/simpleselgame.cpp index eef346feff7..1034a368f1b 100644 --- a/src/frontend/mame/ui/simpleselgame.cpp +++ b/src/frontend/mame/ui/simpleselgame.cpp @@ -43,7 +43,8 @@ simple_menu_select_game::simple_menu_select_game(mame_ui_manager &mui, render_co , m_driverlist(driver_list::total() + 1) , m_drivlist() , m_cached_driver(nullptr) - , m_cached_flags(machine_flags::NOT_WORKING) + , m_cached_machine_flags(machine_flags::ROT0) + , m_cached_emulation_flags(device_t::flags::NOT_WORKING) , m_cached_unemulated(device_t::feature::NONE), m_cached_imperfect(device_t::feature::NONE) , m_cached_color(ui().colors().background_color()) { @@ -353,14 +354,15 @@ void simple_menu_select_game::custom_render(uint32_t flags, void *selectedref, f emu_options clean_options; machine_static_info const info(ui().options(), machine_config(*driver, clean_options)); m_cached_driver = driver; - m_cached_flags = info.machine_flags(); + m_cached_machine_flags = info.machine_flags(); + m_cached_emulation_flags = info.emulation_flags(); m_cached_unemulated = info.unemulated_features(); m_cached_imperfect = info.imperfect_features(); m_cached_color = info.status_color(); } // next line is overall driver status - if (m_cached_flags & machine_flags::NOT_WORKING) + if (m_cached_emulation_flags & device_t::flags::NOT_WORKING) tempbuf[3] = _("Status: NOT WORKING"); else if ((m_cached_unemulated | m_cached_imperfect) & device_t::feature::PROTECTION) tempbuf[3] = _("Status: Unemulated Protection"); @@ -375,7 +377,7 @@ void simple_menu_select_game::custom_render(uint32_t flags, void *selectedref, f else tempbuf[4] = _("Graphics: OK, "); - if (m_cached_flags & machine_flags::NO_SOUND_HW) + if (m_cached_machine_flags & machine_flags::NO_SOUND_HW) tempbuf[4].append(_("Sound: None")); else if (m_cached_unemulated & device_t::feature::SOUND) tempbuf[4].append(_("Sound: Unimplemented")); diff --git a/src/frontend/mame/ui/simpleselgame.h b/src/frontend/mame/ui/simpleselgame.h index 5b278450d7f..14e3b34d74b 100644 --- a/src/frontend/mame/ui/simpleselgame.h +++ b/src/frontend/mame/ui/simpleselgame.h @@ -59,7 +59,8 @@ private: // cached driver flags const game_driver * m_cached_driver; - machine_flags::type m_cached_flags; + machine_flags::type m_cached_machine_flags; + device_t::flags_type m_cached_emulation_flags; device_t::feature_type m_cached_unemulated; device_t::feature_type m_cached_imperfect; rgb_t m_cached_color; diff --git a/src/frontend/mame/ui/ui.cpp b/src/frontend/mame/ui/ui.cpp index 71006aa8a97..a3977a310c0 100644 --- a/src/frontend/mame/ui/ui.cpp +++ b/src/frontend/mame/ui/ui.cpp @@ -270,7 +270,6 @@ mame_ui_manager::mame_ui_manager(running_machine &machine) , m_mouse_arrow_texture(nullptr) , m_pointers_changed(false) , m_target_font_height(0) - , m_has_warnings(false) , m_unthrottle_mute(false) , m_image_display_enabled(true) , m_machine_info() @@ -697,12 +696,10 @@ void mame_ui_manager::display_startup_screens(bool first_time) break; case 1: - warning_text = machine_info().warnings_string(); - m_has_warnings = !warning_text.empty(); if (show_warnings) { - bool need_warning = m_has_warnings; - if (machine_info().has_severe_warnings() || !m_has_warnings) + bool need_warning = machine_info().has_warnings(); + if (machine_info().has_severe_warnings() || !machine_info().has_warnings()) { // critical warnings - no need to persist stuff m_unemulated_features.clear(); @@ -717,6 +714,8 @@ void mame_ui_manager::display_startup_screens(bool first_time) for (device_t &device : device_enumerator(machine().root_device())) { device_t::feature_type unemulated = device.type().unemulated_features(); + if ((&device != &machine().root_device()) && (device.type().emulation_flags() & device_t::flags::NOT_WORKING)) + unemulated_features.emplace(device.type().shortname(), "functionality"); for (std::underlying_type_t feature = 1U; unemulated; feature <<= 1) { if (unemulated & feature) @@ -764,6 +763,7 @@ void mame_ui_manager::display_startup_screens(bool first_time) } if (need_warning) { + warning_text = machine_info().warnings_string(); warning_text.append(_("\n\nPress any key to continue")); set_handler(ui_callback_type::MODAL, handler_callback_func(handler_messagebox_anykey)); warning_color = machine_info().warnings_color(); @@ -815,7 +815,7 @@ void mame_ui_manager::display_startup_screens(bool first_time) } // update last launch time if this was a run that was eligible for emulation warnings - if (m_has_warnings && show_warnings && !machine().scheduled_event_pending()) + if (machine_info().has_warnings() && show_warnings && !machine().scheduled_event_pending()) m_last_launch_time = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()); // if we're the empty driver, force the menus on diff --git a/src/frontend/mame/ui/ui.h b/src/frontend/mame/ui/ui.h index 667f4b30aeb..ed5fa97156d 100644 --- a/src/frontend/mame/ui/ui.h +++ b/src/frontend/mame/ui/ui.h @@ -204,7 +204,6 @@ public: void show_menu(); virtual bool is_menu_active() override; bool can_paste(); - bool found_machine_warnings() const { return m_has_warnings; } void image_handler_ingame(); void request_quit(); void set_pointer_activity_timeout(int target, std::chrono::steady_clock::duration timeout) noexcept; @@ -314,7 +313,6 @@ private: ui_options m_ui_options; ui_colors m_ui_colors; float m_target_font_height; - bool m_has_warnings; bool m_unthrottle_mute; bool m_image_display_enabled; diff --git a/src/frontend/mame/ui/utils.cpp b/src/frontend/mame/ui/utils.cpp index b0107589e04..8acd4a70b5e 100644 --- a/src/frontend/mame/ui/utils.cpp +++ b/src/frontend/mame/ui/utils.cpp @@ -680,7 +680,7 @@ class working_machine_filter_impl : public simple_filter_impl_baseflags & machine_flags::NOT_WORKING); } + virtual bool apply(ui_system_info const &system) const override { return !(system.driver->type.emulation_flags() & device_t::flags::NOT_WORKING); } }; @@ -743,7 +743,7 @@ class save_machine_filter_impl : public simple_filter_impl_baseflags & machine_flags::SUPPORTS_SAVE; } + virtual bool apply(ui_system_info const &system) const override { return !(system.driver->type.emulation_flags() & device_t::flags::SAVE_UNSUPPORTED); } }; diff --git a/src/mame/igs/igs_m027.cpp b/src/mame/igs/igs_m027.cpp index 23e4ccac364..0a18925cca3 100644 --- a/src/mame/igs/igs_m027.cpp +++ b/src/mame/igs/igs_m027.cpp @@ -155,6 +155,7 @@ public: void mgzz(machine_config &config) ATTR_COLD; void oceanpar(machine_config &config) ATTR_COLD; void tripslot(machine_config &config) ATTR_COLD; + void ccly(machine_config &config) ATTR_COLD; void extradrw(machine_config &config) ATTR_COLD; void chessc2(machine_config &config) ATTR_COLD; @@ -1446,6 +1447,108 @@ INPUT_PORTS_START( tripslot ) PORT_DIPUNKNOWN_DIPLOC( 0x80, 0x80, "SW3:8" ) INPUT_PORTS_END +INPUT_PORTS_START( ccly ) + // preliminary - game seems to lack an input test + // To access sound test, hold Service Mode and reset, then press Service Mode and Book-Keeping simultaneously + + PORT_START("PORTB") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNKNOWN ) + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_SLOT_STOP1 ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x01) + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_GAMBLE_BOOK ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x01) + PORT_SERVICE_NO_TOGGLE( 0x08, IP_ACTIVE_LOW ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x01) + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_GAMBLE_BET ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x00) + PORT_SERVICE_NO_TOGGLE( 0x04, IP_ACTIVE_LOW ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x00) + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_GAMBLE_BOOK ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x00) + PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_COIN1 ) + PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_GAMBLE_KEYOUT ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x01) + PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_GAMBLE_PAYOUT ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x00) + PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNKNOWN ) + PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_GAMBLE_LOW ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x01) PORT_NAME("Small / Half Gamble / Show Odds") + PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_GAMBLE_HIGH ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x00) PORT_NAME("Big") + + PORT_START("PORTC") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_GAMBLE_KEYIN ) + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNKNOWN ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x01) + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_GAMBLE_BET ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x01) PORT_NAME("Bet / Double Up") + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_GAMBLE_HIGH ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x01) PORT_NAME("Big") + PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_START1 ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x01) PORT_NAME("Start / Take Score") + PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_CUSTOM ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x01) PORT_READ_LINE_DEVICE_MEMBER("hopper", FUNC(hopper_device::line_r)) + PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_GAMBLE_PAYOUT ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x01) + PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x01) + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_GAMBLE_KEYOUT ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x00) + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_START1 ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x00) PORT_NAME("Start / Take Score") + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNKNOWN ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x00) + PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_CUSTOM ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x00) PORT_READ_LINE_DEVICE_MEMBER("hopper", FUNC(hopper_device::line_r)) + PORT_BIT( 0x60, IP_ACTIVE_LOW, IPT_GAMBLE_PAYOUT ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x00) + PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_COIN2 ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x00) + + PORT_START("PLAYER") + PORT_BIT( 0x00001, IP_ACTIVE_LOW, IPT_UNKNOWN ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x01) + PORT_BIT( 0x00002, IP_ACTIVE_LOW, IPT_SLOT_STOP3 ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x01) + PORT_BIT( 0x00004, IP_ACTIVE_LOW, IPT_SLOT_STOP2 ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x01) + PORT_BIT( 0x00038, IP_ACTIVE_LOW, IPT_UNKNOWN ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x01) + PORT_BIT( 0x00001, IP_ACTIVE_LOW, IPT_SLOT_STOP2 ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x00) + PORT_BIT( 0x00002, IP_ACTIVE_LOW, IPT_SLOT_STOP1 ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x00) + PORT_BIT( 0x00004, IP_ACTIVE_LOW, IPT_SLOT_STOP3 ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x00) + PORT_BIT( 0x00008, IP_ACTIVE_LOW, IPT_GAMBLE_LOW ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x00) PORT_NAME("Small / Half Gamble / Show Odds") + PORT_BIT( 0x00010, IP_ACTIVE_LOW, IPT_GAMBLE_TAKE ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x00) + PORT_BIT( 0x00020, IP_ACTIVE_LOW, IPT_GAMBLE_D_UP ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x00) + PORT_BIT( 0x000c0, IP_ACTIVE_LOW, IPT_UNKNOWN ) + PORT_BIT( 0x00100, IP_ACTIVE_HIGH, IPT_UNKNOWN ) // must be low or most inputs are ignored + PORT_BIT( 0xffe00, IP_ACTIVE_LOW, IPT_UNKNOWN ) + + PORT_START("CLEARMEM") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_MEMORY_RESET ) PORT_TOGGLE + + PORT_START("PPIB") + PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OUTPUT ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x01) PORT_WRITE_LINE_MEMBER(FUNC(igs_m027_state::counter_w<4>)) // key-out + PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_OUTPUT ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x01) PORT_WRITE_LINE_MEMBER(FUNC(igs_m027_state::counter_w<0>)) // coin + PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_OUTPUT ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x01) PORT_WRITE_LINE_DEVICE_MEMBER("hopper", FUNC(hopper_device::motor_w)) + PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_OUTPUT ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x01) PORT_WRITE_LINE_MEMBER(FUNC(igs_m027_state::counter_w<3>)) // payout + PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_OUTPUT ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x01) PORT_WRITE_LINE_MEMBER(FUNC(igs_m027_state::counter_w<2>)) // key-in + + PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OUTPUT ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x00) PORT_WRITE_LINE_MEMBER(FUNC(igs_m027_state::counter_w<0>)) // coin 1 + PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_OUTPUT ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x00) PORT_WRITE_LINE_MEMBER(FUNC(igs_m027_state::counter_w<2>)) // key-in + PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_OUTPUT ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x00) PORT_WRITE_LINE_MEMBER(FUNC(igs_m027_state::counter_w<1>)) // coin 2 + PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_OUTPUT ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x00) PORT_WRITE_LINE_MEMBER(FUNC(igs_m027_state::counter_w<3>)) // payout + PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_OUTPUT ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x00) PORT_WRITE_LINE_MEMBER(FUNC(igs_m027_state::counter_w<4>)) // key-out + PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_OUTPUT ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x00) PORT_WRITE_LINE_DEVICE_MEMBER("hopper", FUNC(hopper_device::motor_w)) + + PORT_START("DSW1") + PORT_DIPUNKNOWN_DIPLOC( 0x01, 0x01, "SW1:1" ) + PORT_DIPUNKNOWN_DIPLOC( 0x02, 0x02, "SW1:2" ) + PORT_DIPUNKNOWN_DIPLOC( 0x04, 0x04, "SW1:3" ) + PORT_DIPUNKNOWN_DIPLOC( 0x08, 0x08, "SW1:4" ) + PORT_DIPUNKNOWN_DIPLOC( 0x10, 0x10, "SW1:5" ) + PORT_DIPUNKNOWN_DIPLOC( 0x20, 0x20, "SW1:6" ) + PORT_DIPUNKNOWN_DIPLOC( 0x40, 0x40, "SW1:7" ) + PORT_DIPUNKNOWN_DIPLOC( 0x80, 0x80, "SW1:8" ) + + PORT_START("DSW2") + PORT_DIPNAME( 0x01, 0x01, "Operation Mode" ) PORT_DIPLOCATION("SW2:1") // 操作模式 + PORT_DIPSETTING( 0x01, "Amusement" ) // 娱乐配线 + PORT_DIPSETTING( 0x00, "Fruit Machine" ) // 水果配线 + PORT_DIPNAME( 0x02, 0x02, DEF_STR(Demo_Sounds) ) PORT_DIPLOCATION("SW2:2") // 示范音乐 + PORT_DIPSETTING( 0x00, DEF_STR(Off) ) // 无 + PORT_DIPSETTING( 0x02, DEF_STR(On) ) // 有 + PORT_DIPUNKNOWN_DIPLOC( 0x04, 0x04, "SW2:3" ) + PORT_DIPUNKNOWN_DIPLOC( 0x08, 0x08, "SW2:4" ) + PORT_DIPUNKNOWN_DIPLOC( 0x10, 0x10, "SW2:5" ) + PORT_DIPUNKNOWN_DIPLOC( 0x20, 0x20, "SW2:6" ) + PORT_DIPUNKNOWN_DIPLOC( 0x40, 0x40, "SW2:7" ) + PORT_DIPUNKNOWN_DIPLOC( 0x80, 0x80, "SW2:8" ) + + PORT_START("DSW3") + PORT_DIPUNKNOWN_DIPLOC( 0x01, 0x01, "SW3:1" ) + PORT_DIPUNKNOWN_DIPLOC( 0x02, 0x02, "SW3:2" ) + PORT_DIPUNKNOWN_DIPLOC( 0x04, 0x04, "SW3:3" ) + PORT_DIPUNKNOWN_DIPLOC( 0x08, 0x08, "SW3:4" ) + PORT_DIPUNKNOWN_DIPLOC( 0x10, 0x10, "SW3:5" ) + PORT_DIPUNKNOWN_DIPLOC( 0x20, 0x20, "SW3:6" ) + PORT_DIPUNKNOWN_DIPLOC( 0x40, 0x40, "SW3:7" ) + PORT_DIPUNKNOWN_DIPLOC( 0x80, 0x80, "SW3:8" ) +INPUT_PORTS_END + INPUT_PORTS_START( chessc2 ) // preliminary - game seems to lack an input test and settings are locked out with password @@ -1639,28 +1742,28 @@ template void igs_m027_state::lamps_w(u8 data) { // active high outputs - // +------+-------------------------------+-------------------------------+---------------+ - // | lamp | jking02 | tripslot | oceanpar | - // | +---------------+---------------+---------------+---------------+ | - // | | 36+10 | 28-Pin | 36+10 | 28-Pin | | - // +------+---------------+---------------+---------------+---------------+---------------+ - // | 1 | stop 4/start | | start | | start | - // | 2 | stop 3/small | | stop 3/small | | stop 2/small | - // | 3 | bet | | stop 5/bet | | bet | - // | 4 | stop 1/take | | stop 4/take | | stop 3/take | - // | 5 | stop 2/double | | stop 2/double | | stop 1/double | - // | 6 | stop all/big | | stop 1/big | | stop all/big | - // | 7 | | | | | | - // | 8 | | | | | | - // | 9 | | bet | | stop 5/bet | | - // | 10 | | start | | start | | - // | 11 | | | | | | - // | 12 | | stop 1/take | | stop 1/big | | - // | 13 | | stop 2/big | | stop 2/double | | - // | 14 | | stop 4/double | | stop 4/take | | - // | 15 | | stop 3/small | | stop 3/small | | - // | 16 | | | | | | - // +------+---------------+---------------+---------------+---------------+---------------+ + // +------+-------------------------------+-------------------------------+---------------+--------+ + // | lamp | jking02 | tripslot | oceanpar | ccly | + // | +---------------+---------------+---------------+---------------+ +--------+ + // | | 36+10 | 28-Pin | 36+10 | 28-Pin | | Fruit | + // +------+---------------+---------------+---------------+---------------+---------------+--------| + // | 1 | stop 4/start | | start | | start | start | + // | 2 | stop 3/small | | stop 3/small | | stop 2/small | small | + // | 3 | bet | | stop 5/bet | | bet | bet | + // | 4 | stop 1/take | | stop 4/take | | stop 3/take | take | + // | 5 | stop 2/double | | stop 2/double | | stop 1/double | double | + // | 6 | stop all/big | | stop 1/big | | stop all/big | big | + // | 7 | | | | | | | + // | 8 | | | | | | | + // | 9 | | bet | | stop 5/bet | | | + // | 10 | | start | | start | | | + // | 11 | | | | | | | + // | 12 | | stop 1/take | | stop 1/big | | | + // | 13 | | stop 2/big | | stop 2/double | | | + // | 14 | | stop 4/double | | stop 4/take | | | + // | 15 | | stop 3/small | | stop 3/small | | | + // | 16 | | | | | | | + // +------+---------------+---------------+---------------+---------------+---------------+--------+ for (unsigned i = 0; 8 > i; ++i) m_out_lamps[Start + i] = BIT(data, i); } @@ -1771,7 +1874,7 @@ void igs_m027_state::counter_w(int state) template void igs_m027_state::m027_noppi(machine_config &config) { - IGS027A(config, m_maincpu, 22'000'000); // Jungle King 2002 has a 22Mhz Xtal, what about the others? + IGS027A(config, m_maincpu, 22'000'000); // Jungle King 2002 has a 22MHz Xtal, what about the others? m_maincpu->set_addrmap(AS_PROGRAM, &igs_m027_state::m027_noppi_map); m_maincpu->out_port().set(FUNC(igs_m027_state::io_select_w<1>)); @@ -2026,6 +2129,18 @@ void igs_m027_state::tripslot(machine_config &config) HOPPER(config, m_hopper, attotime::from_msec(50)); } +void igs_m027_state::ccly(machine_config &config) +{ + m027_1ppi(config); + + m_maincpu->in_port().set_ioport("PLAYER"); + + m_ppi[0]->out_pb_callback().set_ioport("PPIB"); + m_ppi[0]->out_pc_callback().set(FUNC(igs_m027_state::lamps_w<0>)); + + HOPPER(config, m_hopper, attotime::from_msec(50)); +} + void igs_m027_state::extradrw(machine_config &config) { m027_2ppis(config); @@ -2313,7 +2428,7 @@ U17 is a ATF16V8B-15P labeled ( FG-1 ) (read protected) U10 is a IGS 003c Dip 40 pin ( Maybe 8255 ? ) U24 is a IGS031 QFP with 208 pin U32 is a IGS027a QFP with 120 pin ( Encrypted ARM, internal code, stamped P9 A/K II ) -Crystal Frequency = 22.000 Mhz +Crystal Frequency = 22.000 MHz Sound Processor ( U6295 ) */ @@ -3711,7 +3826,7 @@ GAME( 2005, cjddzlf, 0, cjddz, cjddz, igs_m027_stat GAME( 2005, cjtljp, 0, xypdk, lhzb4, igs_m027_state, init_cjtljp, ROT0, "IGS", "Chaoji Tuolaji Jiaqiang Ban (V206CN)", 0 ) // 2005 date in internal ROM GAME( 2005, xypdk, 0, xypdk, lhzb4, igs_m027_state, init_xypdk, ROT0, "IGS", "Xingyun Pao De Kuai (V106CN)", 0 ) GAMEL( 2007, tripslot, 0, tripslot, tripslot, igs_m027_state, init_tripslot, ROT0, "IGS", "Triple Slot (V200VE)", 0, layout_tripslot ) // 2007 date in internal ROM at least, could be later, default settings password is all 'start 1' -GAME( 2005, ccly, crzybugs, m027_1ppi, base, igs_m027_state, init_ccly, ROT0, "IGS", "Chong Chong Leyuan (V100CN)", MACHINE_NOT_WORKING ) +GAME( 2005, ccly, crzybugs, ccly, ccly, igs_m027_state, init_ccly, ROT0, "IGS", "Chong Chong Leyuan (V100CN)", MACHINE_NOT_WORKING ) // this has a 2nd 8255 GAME( 2001, extradrw, 0, extradrw, base, igs_m027_state, init_extradrw, ROT0, "IGS", "Extra Draw (V100VE)", MACHINE_NOT_WORKING ) // these have an IGS025 protection device instead of the 8255 diff --git a/src/mame/miltonbradley/milton6805.cpp b/src/mame/miltonbradley/milton6805.cpp index 4d590550329..6fb89baba0d 100644 --- a/src/mame/miltonbradley/milton6805.cpp +++ b/src/mame/miltonbradley/milton6805.cpp @@ -91,7 +91,6 @@ protected: private: sound_stream *m_stream = nullptr; output_finder<> m_led_out; - bool m_dummy_save = false; // needed for save-state support }; DEFINE_DEVICE_TYPE(MILTON_LED_FILTER, milton_filter_device, "milton_led_filter", "Milton LED Filter") @@ -107,7 +106,6 @@ void milton_filter_device::device_start() { m_stream = stream_alloc(1, 1, machine().sample_rate()); m_led_out.resolve(); - save_item(NAME(m_dummy_save)); } void milton_filter_device::sound_stream_update(sound_stream &stream) diff --git a/src/mame/shared/gottlieb_a.cpp b/src/mame/shared/gottlieb_a.cpp index c54d4c0f3b3..d16e8ec6aa7 100644 --- a/src/mame/shared/gottlieb_a.cpp +++ b/src/mame/shared/gottlieb_a.cpp @@ -150,8 +150,6 @@ void gottlieb_sound_p2_device::device_add_mconfig(machine_config &config) void gottlieb_sound_p2_device::device_start() { - // register for save states - save_item(NAME(m_dummy_save)); } @@ -369,8 +367,6 @@ void gottlieb_sound_r1_device::device_add_mconfig(machine_config &config) void gottlieb_sound_r1_device::device_start() { - // register for save states - save_item(NAME(m_dummy_save)); } diff --git a/src/mame/shared/gottlieb_a.h b/src/mame/shared/gottlieb_a.h index 7ec6bc6de12..67a5ae37d6f 100644 --- a/src/mame/shared/gottlieb_a.h +++ b/src/mame/shared/gottlieb_a.h @@ -69,9 +69,6 @@ protected: // devices required_device m_cpu; required_device m_r6530; - -private: - bool m_dummy_save = false; // needed for save-state support }; @@ -127,9 +124,6 @@ protected: // devices required_device m_dac; required_device m_riot; - -private: - bool m_dummy_save = false; // needed for save-state support }; diff --git a/src/mame/shared/williamssound.cpp b/src/mame/shared/williamssound.cpp index dd7df345a6b..670b4c228c3 100644 --- a/src/mame/shared/williamssound.cpp +++ b/src/mame/shared/williamssound.cpp @@ -914,8 +914,6 @@ void williams_s4_sound_device::device_add_mconfig(machine_config &config) //------------------------------------------------- void williams_s4_sound_device::device_start() { - // register for save states - save_item(NAME(m_dummy_save)); } //------------------------------------------------- @@ -1031,8 +1029,6 @@ void williams_s6_sound_device::device_add_mconfig(machine_config &config) //------------------------------------------------- void williams_s6_sound_device::device_start() { - // register for save states - save_item(NAME(m_dummy_save)); } //------------------------------------------------- @@ -1142,8 +1138,6 @@ void williams_s9_sound_device::device_add_mconfig(machine_config &config) //------------------------------------------------- void williams_s9_sound_device::device_start() { - // register for save states - save_item(NAME(m_dummy_save)); } //------------------------------------------------- @@ -1260,9 +1254,6 @@ void williams_s11_sound_device::device_start() u8 *ROM = memregion("audiocpu")->base(); membank("bank0")->configure_entries(0, 2, &ROM[0x0000], 0x4000); membank("bank1")->configure_entries(0, 2, &ROM[0x8000], 0x4000); - - // register for save states - save_item(NAME(m_dummy_save)); } //------------------------------------------------- diff --git a/src/mame/shared/williamssound.h b/src/mame/shared/williamssound.h index 67b92f760ab..7ef47925ef0 100644 --- a/src/mame/shared/williamssound.h +++ b/src/mame/shared/williamssound.h @@ -223,7 +223,6 @@ private: void williams_s4_map(address_map &map) ATTR_COLD; required_device m_cpu; required_device m_pia; - bool m_dummy_save = false; // needed for save-state support }; @@ -254,7 +253,6 @@ private: required_device m_cpu; required_device m_pia; required_device m_hc; - bool m_dummy_save = false; // needed for save-state support }; @@ -285,7 +283,6 @@ private: required_device m_cpu; required_device m_pia; required_device m_hc; - bool m_dummy_save = false; // needed for save-state support }; @@ -317,7 +314,6 @@ private: required_device m_cpu; required_device m_pia; required_device m_hc; - bool m_dummy_save = false; // needed for save-state support }; #endif // MAME_SHARED_WILLIAMSSOUND_H diff --git a/src/osd/interface/audio.h b/src/osd/interface/audio.h index 9e084cf53ab..f40744cfff6 100644 --- a/src/osd/interface/audio.h +++ b/src/osd/interface/audio.h @@ -6,10 +6,11 @@ #pragma once -#include #include +#include +#include #include -#include + namespace osd { @@ -25,7 +26,7 @@ struct audio_info { uint32_t m_id; audio_rate_range m_rate; std::vector m_port_names; - std::vector> m_port_positions; + std::vector > m_port_positions; uint32_t m_sinks; uint32_t m_sources; @@ -45,8 +46,9 @@ struct audio_info { std::vector m_streams; }; -static inline float db_to_linear(float db) { return db <= -96 ? 0.0 : pow(10, db/20); } -static inline float linear_to_db(float linear) { return linear <= 1/65536.0 ? -96 : 20*log10(linear); } -} +inline float db_to_linear(float db) { return (db <= -96.0F) ? 0.0F : std::pow(10.0F, db / 20.0F); } +inline float linear_to_db(float linear) { return (linear <= (1.0F / 65536.0F)) ? -96.0F : (20.0F * std::log10(linear)); } -#endif +} // namespace osd + +#endif // MAME_OSD_INTERFACE_AUDIO_H