diff options
author | 2017-07-27 09:56:53 +1000 | |
---|---|---|
committer | 2017-07-27 09:56:53 +1000 | |
commit | 22d80b35290491e041122708b0482826ba3a89c9 (patch) | |
tree | f9b39d9aa70ab6573c2f5559b6ef06be27512e51 | |
parent | 6cf16fde31232e3081a7ec2d2db9bcece9f8b95d (diff) |
Move unemulated/imperfect flags from machines into devices.
Right now, flags for unemulated/imperfect features apply at system
level. This falls over quickly with systems that have slot devices.
For example you can plug in a broken sound card or keyboard on a PC or
Amiga driver and get no warnings. There's also no way to propagate
these flags from a device to all systems using it.
This changeset addresses these issues. It's now possible to report
unemulated/imperfect features on a device level with static
unemulated_feeatures() and imperfect_features() member functions. So
far the only thing using this is the votrax device.
To support front-ends, this is exposed in -listxml output as a new
"feature" element that can appear in system/device descriptions. It has
a "type" attribute indicating which feature it is, potentially a
"status" attribute if the device itself declares that the feature is
unemulated/imperfect, and potentially an "overall" attribute if the
device inherits a more severe indication from a subdevice. The embedded
DTD describes possible values.
Example: device/machine declares imperfect sound:
<feature type="sound" status="imperfect"/>
Example: device/machine declares unemulated keyboard:
<feature type="keyboard" status="unemulated"/>
Example: device declares imperfect controls but inherits unemulated
controls from a subdevice:
<feature type="controls" status="imperfect" overall="unemulated"/>
Example: device doesn't declare imperfect LAN but inherits it from a
subdevice:
<feature type="lan" overall="imperfect"/>
It's still possible to add these flags to machines in the GAME/COMP/CONS
macro. If the state class declares them with static member functions,
the two sources will be combined.
If you subclass a device, you inherit its flags if you don't redefine
the relevant static member functions (no override qualifier is necessary
since they're static).
The UI has been updated to display appropriate warnings for the overall
machine configuration, including selected slot devices, at launch time.
The menus don't display overall status, only status for the machine
itself. We can make it scan subdevices if we decide that's desirable,
it just needs caching to enure we don't take a huge performance hit.
-rw-r--r-- | src/devices/sound/votrax.h | 2 | ||||
-rw-r--r-- | src/emu/device.h | 74 | ||||
-rw-r--r-- | src/emu/emucore.h | 16 | ||||
-rw-r--r-- | src/emu/gamedrv.h | 162 | ||||
-rw-r--r-- | src/emu/render.cpp | 4 | ||||
-rw-r--r-- | src/emu/save.cpp | 2 | ||||
-rw-r--r-- | src/emu/validity.cpp | 37 | ||||
-rw-r--r-- | src/frontend/mame/clifront.cpp | 6 | ||||
-rw-r--r-- | src/frontend/mame/info.cpp | 157 | ||||
-rw-r--r-- | src/frontend/mame/info.h | 5 | ||||
-rw-r--r-- | src/frontend/mame/luaengine.cpp | 2 | ||||
-rw-r--r-- | src/frontend/mame/mameopts.cpp | 17 | ||||
-rw-r--r-- | src/frontend/mame/ui/auditmenu.cpp | 4 | ||||
-rw-r--r-- | src/frontend/mame/ui/info.cpp | 275 | ||||
-rw-r--r-- | src/frontend/mame/ui/info.h | 16 | ||||
-rw-r--r-- | src/frontend/mame/ui/inifile.cpp | 4 | ||||
-rw-r--r-- | src/frontend/mame/ui/miscmenu.cpp | 2 | ||||
-rw-r--r-- | src/frontend/mame/ui/selgame.cpp | 63 | ||||
-rw-r--r-- | src/frontend/mame/ui/selmenu.cpp | 32 | ||||
-rw-r--r-- | src/frontend/mame/ui/simpleselgame.cpp | 35 | ||||
-rw-r--r-- | src/frontend/mame/ui/ui.cpp | 65 | ||||
-rw-r--r-- | src/frontend/mame/ui/ui.h | 2 | ||||
-rw-r--r-- | src/frontend/mame/ui/viewgfx.cpp | 2 | ||||
-rw-r--r-- | src/mame/drivers/rm380z.cpp | 4 |
24 files changed, 625 insertions, 363 deletions
diff --git a/src/devices/sound/votrax.h b/src/devices/sound/votrax.h index 0ec75317227..2779b42d5fe 100644 --- a/src/devices/sound/votrax.h +++ b/src/devices/sound/votrax.h @@ -20,6 +20,8 @@ class votrax_sc01_device : public device_t, public device_sound_interface { public: + static constexpr feature_type imperfect_features() { return feature::SOUND; } + // construction/destruction votrax_sc01_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); diff --git a/src/emu/device.h b/src/emu/device.h index 0f56adbe36d..de321265908 100644 --- a/src/emu/device.h +++ b/src/emu/device.h @@ -73,6 +73,32 @@ namespace emu { namespace detail { class device_type_impl; +struct device_feature +{ + enum type : u32 + { + PROTECTION = u32(1) << 0, + PALETTE = u32(1) << 1, + GRAPHICS = u32(1) << 2, + SOUND = u32(1) << 3, + CONTROLS = u32(1) << 4, + KEYBOARD = u32(1) << 5, + MOUSE = u32(1) << 6, + MICROPHONE = u32(1) << 7, + CAMERA = u32(1) << 8, + DISK = u32(1) << 9, + PRINTER = u32(1) << 10, + LAN = u32(1) << 11, + WAN = u32(1) << 12, + + NONE = u32(0), + ALL = (u32(1) << 13) - 1U + }; +}; + +DECLARE_ENUM_BITWISE_OPERATORS(device_feature::type); + + class device_registrar { private: @@ -126,11 +152,15 @@ private: }; -template <class DeviceClass, char const *ShortName, char const *FullName, char const *Source> struct device_tag_struct { typedef DeviceClass type; }; -template <class DriverClass, char const *ShortName, char const *FullName, char const *Source> struct driver_tag_struct { typedef DriverClass type; }; +template <class DeviceClass, char const *ShortName, char const *FullName, char const *Source> +struct device_tag_struct { typedef DeviceClass type; }; +template <class DriverClass, char const *ShortName, char const *FullName, char const *Source, device_feature::type Unemulated, device_feature::type Imperfect> +struct driver_tag_struct { typedef DriverClass type; }; -template <class DeviceClass, char const *ShortName, char const *FullName, char const *Source> auto device_tag_func() { return device_tag_struct<DeviceClass, ShortName, FullName, Source>{ }; }; -template <class DriverClass, char const *ShortName, char const *FullName, char const *Source> auto driver_tag_func() { return driver_tag_struct<DriverClass, ShortName, FullName, Source>{ }; }; +template <class DeviceClass, char const *ShortName, char const *FullName, char const *Source> +auto device_tag_func() { return device_tag_struct<DeviceClass, ShortName, FullName, Source>{ }; }; +template <class DriverClass, char const *ShortName, char const *FullName, char const *Source, device_feature::type Unemulated, device_feature::type Imperfect> +auto driver_tag_func() { return driver_tag_struct<DriverClass, ShortName, FullName, Source, Unemulated, Imperfect>{ }; }; class device_type_impl { @@ -164,6 +194,8 @@ private: char const *const m_shortname; char const *const m_fullname; char const *const m_source; + device_feature::type const m_unemulated_features; + device_feature::type const m_imperfect_features; device_type_impl *m_next; @@ -174,6 +206,8 @@ public: , m_shortname(nullptr) , m_fullname(nullptr) , m_source(nullptr) + , m_unemulated_features(device_feature::NONE) + , m_imperfect_features(device_feature::NONE) , m_next(nullptr) { } @@ -185,17 +219,21 @@ public: , m_shortname(ShortName) , m_fullname(FullName) , m_source(Source) + , m_unemulated_features(DeviceClass::unemulated_features()) + , m_imperfect_features(DeviceClass::imperfect_features()) , m_next(device_registrar::register_device(*this)) { } - template <class DriverClass, char const *ShortName, char const *FullName, char const *Source> - device_type_impl(driver_tag_struct<DriverClass, ShortName, FullName, Source> (*)()) + template <class DriverClass, char const *ShortName, char const *FullName, char const *Source, device_feature::type Unemulated, device_feature::type Imperfect> + device_type_impl(driver_tag_struct<DriverClass, ShortName, FullName, Source, Unemulated, Imperfect> (*)()) : m_creator(&create_driver<DriverClass>) , m_type(typeid(DriverClass)) , m_shortname(ShortName) , m_fullname(FullName) , m_source(Source) + , m_unemulated_features(DriverClass::unemulated_features() | Unemulated) + , m_imperfect_features((DriverClass::imperfect_features() & ~Unemulated) | Imperfect) , m_next(nullptr) { } @@ -204,6 +242,8 @@ public: char const *shortname() const { return m_shortname; } char const *fullname() const { return m_fullname; } char const *source() const { return m_source; } + device_feature::type unemulated_features() const { return m_unemulated_features; } + device_feature::type imperfect_features() const { return m_imperfect_features; } std::unique_ptr<device_t> operator()(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) const { @@ -226,11 +266,21 @@ typedef emu::detail::device_type_impl const &device_type; typedef std::add_pointer_t<device_type> device_type_ptr; extern emu::detail::device_registrar const registered_device_types; -template <typename DeviceClass, char const *ShortName, char const *FullName, char const *Source> +template < + typename DeviceClass, + char const *ShortName, + char const *FullName, + char const *Source> constexpr auto device_creator = &emu::detail::device_tag_func<DeviceClass, ShortName, FullName, Source>; -template <typename DriverClass, char const *ShortName, char const *FullName, char const *Source> -constexpr auto driver_device_creator = &emu::detail::driver_tag_func<DriverClass, ShortName, FullName, Source>; +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<DriverClass, ShortName, FullName, Source, Unemulated, Imperfect>; #define DECLARE_DEVICE_TYPE(Type, Class) \ extern device_type const Type; \ @@ -376,6 +426,12 @@ protected: u32 clock); public: + // device flags + using feature = emu::detail::device_feature; + using feature_type = emu::detail::device_feature::type; + static constexpr feature_type unemulated_features() { return feature::NONE; } + static constexpr feature_type imperfect_features() { return feature::NONE; } + virtual ~device_t(); // getters diff --git a/src/emu/emucore.h b/src/emu/emucore.h index 51fca10e42b..46a5427a4ec 100644 --- a/src/emu/emucore.h +++ b/src/emu/emucore.h @@ -168,14 +168,14 @@ const endianness_t ENDIANNESS_NATIVE = ENDIANNESS_BIG; // orientation of bitmaps -#define ORIENTATION_FLIP_X 0x0001 /* mirror everything in the X direction */ -#define ORIENTATION_FLIP_Y 0x0002 /* mirror everything in the Y direction */ -#define ORIENTATION_SWAP_XY 0x0004 /* mirror along the top-left/bottom-right diagonal */ - -#define ROT0 0 -#define ROT90 (ORIENTATION_SWAP_XY | ORIENTATION_FLIP_X) /* rotate clockwise 90 degrees */ -#define ROT180 (ORIENTATION_FLIP_X | ORIENTATION_FLIP_Y) /* rotate 180 degrees */ -#define ROT270 (ORIENTATION_SWAP_XY | ORIENTATION_FLIP_Y) /* rotate counter-clockwise 90 degrees */ +constexpr int ORIENTATION_FLIP_X = 0x0001; // mirror everything in the X direction +constexpr int ORIENTATION_FLIP_Y = 0x0002; // mirror everything in the Y direction +constexpr int ORIENTATION_SWAP_XY = 0x0004; // mirror along the top-left/bottom-right diagonal + +constexpr int ROT0 = 0; +constexpr int ROT90 = ORIENTATION_SWAP_XY | ORIENTATION_FLIP_X; // rotate clockwise 90 degrees +constexpr int ROT180 = ORIENTATION_FLIP_X | ORIENTATION_FLIP_Y; // rotate 180 degrees +constexpr int ROT270 = ORIENTATION_SWAP_XY | ORIENTATION_FLIP_Y; // rotate counter-clockwise 90 degrees diff --git a/src/emu/gamedrv.h b/src/emu/gamedrv.h index b501960859a..f0168aa8b23 100644 --- a/src/emu/gamedrv.h +++ b/src/emu/gamedrv.h @@ -23,42 +23,78 @@ // maxima constexpr int MAX_DRIVER_NAME_CHARS = 16; -// flags for game drivers -constexpr u32 ORIENTATION_MASK = 0x00000007; -constexpr u32 MACHINE_NOT_WORKING = 0x00000008; -constexpr u32 MACHINE_UNEMULATED_PROTECTION = 0x00000010; // game's protection not fully emulated -constexpr u32 MACHINE_WRONG_COLORS = 0x00000020; // colors are totally wrong -constexpr u32 MACHINE_IMPERFECT_COLORS = 0x00000040; // colors are not 100% accurate, but close -constexpr u32 MACHINE_IMPERFECT_GRAPHICS = 0x00000080; // graphics are wrong/incomplete -constexpr u32 MACHINE_NO_COCKTAIL = 0x00000100; // screen flip support is missing -constexpr u32 MACHINE_NO_SOUND = 0x00000200; // sound is missing -constexpr u32 MACHINE_IMPERFECT_SOUND = 0x00000400; // sound is known to be wrong -constexpr u32 MACHINE_SUPPORTS_SAVE = 0x00000800; // game supports save states -constexpr u32 MACHINE_IS_BIOS_ROOT = 0x00001000; // this driver entry is a BIOS root -constexpr u32 MACHINE_NO_STANDALONE = 0x00002000; // this driver cannot stand alone -constexpr u32 MACHINE_REQUIRES_ARTWORK = 0x00004000; // the driver requires external artwork for key elements of the game -constexpr u32 MACHINE_UNOFFICIAL = 0x00008000; // unofficial hardware change -constexpr u32 MACHINE_NO_SOUND_HW = 0x00010000; // sound hardware not available -constexpr u32 MACHINE_MECHANICAL = 0x00020000; // contains mechanical parts (pinball, redemption games,...) -constexpr u32 MACHINE_TYPE_ARCADE = 0x00040000; // arcade machine (coin operated machines) -constexpr u32 MACHINE_TYPE_CONSOLE = 0x00080000; // console system -constexpr u32 MACHINE_TYPE_COMPUTER = 0x00100000; // any kind of computer including home computers, minis, calcs,... -constexpr u32 MACHINE_TYPE_OTHER = 0x00200000; // any other emulated system that doesn't fit above (ex. clock, satellite receiver,...) -constexpr u32 MACHINE_IMPERFECT_KEYBOARD = 0x00400000; // keyboard is known to be wrong -constexpr u32 MACHINE_CLICKABLE_ARTWORK = 0x00800000; // marking that artwork is clickable and require mouse cursor -constexpr u32 MACHINE_IS_INCOMPLETE = 0x01000000; // any official game/system with blatantly incomplete HW or SW should be marked with this -constexpr u32 MACHINE_NODEVICE_MICROPHONE = 0x02000000; // any game/system that has unemulated recording voice device peripheral -constexpr u32 MACHINE_NODEVICE_CAMERA = 0x04000000; // any game/system that has unemulated capturing image device peripheral -constexpr u32 MACHINE_NODEVICE_PRINTER = 0x08000000; // any game/system that has unemulated grabbing of screen content device -constexpr u32 MACHINE_NODEVICE_LAN = 0x10000000; // any game/system that has unemulated multi-linking capability -constexpr u32 MACHINE_NODEVICE_WAN = 0x20000000; // any game/system that has unemulated networking capability +struct machine_flags +{ + enum type : u32 + { + MASK_ORIENTATION = 0x00000007, + MASK_TYPE = 0x00000038, + + FLIP_X = 0x00000001, + FLIP_Y = 0x00000002, + SWAP_XY = 0x00000004, + ROT0 = 0x00000000, + ROT90 = FLIP_X | SWAP_XY, + ROT180 = FLIP_X | FLIP_Y, + ROT270 = FLIP_Y | SWAP_XY, + + TYPE_ARCADE = 0x00000008, // coin-operated machine for public use + TYPE_CONSOLE = 0x00000010, // console system + TYPE_COMPUTER = 0x00000018, // any kind of computer including home computers, minis, calculators, ... + TYPE_OTHER = 0x00000038, // any other emulated system (e.g. clock, satellite receiver, ...) + + NOT_WORKING = 0x00000040, + SUPPORTS_SAVE = 0x00000080, // system supports save states + NO_COCKTAIL = 0x00000100, // screen flip support is missing + IS_BIOS_ROOT = 0x00000200, // this driver entry is a BIOS root + NO_STANDALONE = 0x00000400, // this driver cannot stand alone + REQUIRES_ARTWORK = 0x00000800, // requires external artwork for key game elements + CLICKABLE_ARTWORK = 0x00001000, // artwork is clickable and requires mouse cursor + UNOFFICIAL = 0x00002000, // unofficial hardware change + NO_SOUND_HW = 0x00004000, // system has no sound output + MECHANICAL = 0x00008000, // contains mechanical parts (pinball, redemption games, ...) + IS_INCOMPLETE = 0x00010000 // official system with blatantly incomplete hardware/software + }; +}; + +DECLARE_ENUM_BITWISE_OPERATORS(machine_flags::type); + + +// flags for machine drivers +constexpr u64 MACHINE_TYPE_ARCADE = machine_flags::TYPE_ARCADE; +constexpr u64 MACHINE_TYPE_CONSOLE = machine_flags::TYPE_CONSOLE; +constexpr u64 MACHINE_TYPE_COMPUTER = machine_flags::TYPE_COMPUTER; +constexpr u64 MACHINE_TYPE_OTHER = machine_flags::TYPE_OTHER; +constexpr u64 MACHINE_NOT_WORKING = machine_flags::NOT_WORKING; +constexpr u64 MACHINE_SUPPORTS_SAVE = machine_flags::SUPPORTS_SAVE; +constexpr u64 MACHINE_NO_COCKTAIL = machine_flags::NO_COCKTAIL; +constexpr u64 MACHINE_IS_BIOS_ROOT = machine_flags::IS_BIOS_ROOT; +constexpr u64 MACHINE_NO_STANDALONE = machine_flags::NO_STANDALONE; +constexpr u64 MACHINE_REQUIRES_ARTWORK = machine_flags::REQUIRES_ARTWORK; +constexpr u64 MACHINE_CLICKABLE_ARTWORK = machine_flags::CLICKABLE_ARTWORK; +constexpr u64 MACHINE_UNOFFICIAL = machine_flags::UNOFFICIAL; +constexpr u64 MACHINE_NO_SOUND_HW = machine_flags::NO_SOUND_HW; +constexpr u64 MACHINE_MECHANICAL = machine_flags::MECHANICAL; +constexpr u64 MACHINE_IS_INCOMPLETE = machine_flags::IS_INCOMPLETE; + +// flags taht map to device feature flags +constexpr u64 MACHINE_UNEMULATED_PROTECTION = 0x00000001'00000000; // game's protection not fully emulated +constexpr u64 MACHINE_WRONG_COLORS = 0x00000002'00000000; // colors are totally wrong +constexpr u64 MACHINE_IMPERFECT_COLORS = 0x00000004'00000000; // colors are not 100% accurate, but close +constexpr u64 MACHINE_IMPERFECT_GRAPHICS = 0x00000008'00000000; // graphics are wrong/incomplete +constexpr u64 MACHINE_NO_SOUND = 0x00000010'00000000; // sound is missing +constexpr u64 MACHINE_IMPERFECT_SOUND = 0x00000020'00000000; // sound is known to be wrong +constexpr u64 MACHINE_IMPERFECT_KEYBOARD = 0x00000040'00000000; // keyboard is known to be wrong +constexpr u64 MACHINE_NODEVICE_MICROPHONE = 0x00000080'00000000; // any game/system that has unemulated recording voice device peripheral +constexpr u64 MACHINE_NODEVICE_CAMERA = 0x00000100'00000000; // any game/system that has unemulated capturing image device peripheral +constexpr u64 MACHINE_NODEVICE_PRINTER = 0x00000200'00000000; // any game/system that has unemulated grabbing of screen content device +constexpr u64 MACHINE_NODEVICE_LAN = 0x00000400'00000000; // any game/system that has unemulated multi-linking capability +constexpr u64 MACHINE_NODEVICE_WAN = 0x00000800'00000000; // any game/system that has unemulated networking capability // useful combinations of flags -constexpr u32 MACHINE_IS_SKELETON = MACHINE_NO_SOUND | MACHINE_NOT_WORKING; // mask for skelly games -constexpr u32 MACHINE_IS_SKELETON_MECHANICAL = MACHINE_IS_SKELETON | MACHINE_MECHANICAL | MACHINE_REQUIRES_ARTWORK; // mask for skelly mechanical games -constexpr u32 MACHINE_FATAL_FLAGS = MACHINE_NOT_WORKING | MACHINE_UNEMULATED_PROTECTION | MACHINE_MECHANICAL; // red disclaimer -constexpr u32 MACHINE_WARNING_FLAGS = MACHINE_WRONG_COLORS | MACHINE_IMPERFECT_COLORS | MACHINE_REQUIRES_ARTWORK | MACHINE_IMPERFECT_GRAPHICS | MACHINE_IMPERFECT_SOUND | MACHINE_IMPERFECT_KEYBOARD | MACHINE_NO_SOUND | MACHINE_NO_COCKTAIL | MACHINE_NODEVICE_MICROPHONE | MACHINE_NODEVICE_CAMERA | MACHINE_NODEVICE_PRINTER | MACHINE_NODEVICE_LAN | MACHINE_NODEVICE_WAN; // yellow disclaimer -constexpr u32 MACHINE_BTANB_FLAGS = MACHINE_IS_INCOMPLETE | MACHINE_NO_SOUND_HW; // default disclaimer +constexpr u64 MACHINE_IS_SKELETON = MACHINE_NO_SOUND | MACHINE_NOT_WORKING; // mask for skelly games +constexpr u64 MACHINE_IS_SKELETON_MECHANICAL = MACHINE_IS_SKELETON | MACHINE_MECHANICAL | MACHINE_REQUIRES_ARTWORK; // mask for skelly mechanical games + //************************************************************************** // TYPE DEFINITIONS @@ -89,7 +125,32 @@ public: void (DriverClass::*const m_method)(); }; - template <class DriverClass> static constexpr auto make_driver_init(void (DriverClass::*method)()) { return driver_init_helper_impl<DriverClass>(method); } + template <class DriverClass> static constexpr auto make_driver_init(void (DriverClass::*method)()) + { + return driver_init_helper_impl<DriverClass>(method); + } + + static constexpr device_t::feature_type unemulated_features(u64 flags) + { + return + ((flags & MACHINE_WRONG_COLORS) ? device_t::feature::PALETTE : device_t::feature::NONE) | + ((flags & MACHINE_NO_SOUND) ? device_t::feature::SOUND : device_t::feature::NONE) | + ((flags & MACHINE_NODEVICE_MICROPHONE) ? device_t::feature::MICROPHONE : device_t::feature::NONE) | + ((flags & MACHINE_NODEVICE_CAMERA) ? device_t::feature::CAMERA : device_t::feature::NONE) | + ((flags & MACHINE_NODEVICE_PRINTER) ? device_t::feature::PRINTER : device_t::feature::NONE) | + ((flags & MACHINE_NODEVICE_LAN) ? device_t::feature::LAN : device_t::feature::NONE) | + ((flags & MACHINE_NODEVICE_WAN) ? device_t::feature::WAN : device_t::feature::NONE); + } + + static constexpr device_t::feature_type imperfect_features(u64 flags) + { + return + ((flags & MACHINE_UNEMULATED_PROTECTION) ? device_t::feature::PROTECTION : device_t::feature::NONE) | + ((flags & MACHINE_IMPERFECT_COLORS) ? device_t::feature::PALETTE : device_t::feature::NONE) | + ((flags & MACHINE_IMPERFECT_GRAPHICS) ? device_t::feature::GRAPHICS : device_t::feature::NONE) | + ((flags & MACHINE_IMPERFECT_SOUND) ? device_t::feature::SOUND : device_t::feature::NONE) | + ((flags & MACHINE_IMPERFECT_KEYBOARD) ? device_t::feature::KEYBOARD : device_t::feature::NONE); + } device_type type; // static type info for driver class const char * parent; // if this is a clone, the name of the parent @@ -101,7 +162,7 @@ public: const tiny_rom_entry * rom; // pointer to list of ROMs for the game const char * compatible_with; const internal_layout * default_layout; // default internally defined layout - u32 flags; // orientation and other flags; see defines above + machine_flags::type flags; // orientation and other flags; see defines above char name[MAX_DRIVER_NAME_CHARS + 1]; // short name of the game }; @@ -127,14 +188,21 @@ 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) driver_device_creator<CLASS, (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)> // standard GAME() macro #define GAME(YEAR,NAME,PARENT,MACHINE,INPUT,CLASS,INIT,MONITOR,COMPANY,FULLNAME,FLAGS) \ GAME_DRIVER_TRAITS(NAME,FULLNAME) \ extern game_driver const GAME_NAME(NAME) \ { \ - GAME_DRIVER_TYPE(NAME, CLASS), \ + GAME_DRIVER_TYPE(NAME, CLASS, FLAGS), \ #PARENT, \ #YEAR, \ COMPANY, \ @@ -144,7 +212,7 @@ extern game_driver const GAME_NAME(NAME) \ ROM_NAME(NAME), \ nullptr, \ nullptr, \ - (MONITOR) | (FLAGS) | MACHINE_TYPE_ARCADE, \ + machine_flags::type(u32((MONITOR) | (FLAGS) | MACHINE_TYPE_ARCADE)),\ #NAME \ }; @@ -153,7 +221,7 @@ extern game_driver const GAME_NAME(NAME) \ GAME_DRIVER_TRAITS(NAME,FULLNAME) \ extern game_driver const GAME_NAME(NAME) \ { \ - GAME_DRIVER_TYPE(NAME, CLASS), \ + GAME_DRIVER_TYPE(NAME, CLASS, FLAGS), \ #PARENT, \ #YEAR, \ COMPANY, \ @@ -163,7 +231,7 @@ extern game_driver const GAME_NAME(NAME) \ ROM_NAME(NAME), \ nullptr, \ &LAYOUT, \ - (MONITOR) | (FLAGS) | MACHINE_TYPE_ARCADE, \ + machine_flags::type(u32((MONITOR) | (FLAGS) | MACHINE_TYPE_ARCADE)),\ #NAME \ }; @@ -173,7 +241,7 @@ extern game_driver const GAME_NAME(NAME) \ GAME_DRIVER_TRAITS(NAME,FULLNAME) \ extern game_driver const GAME_NAME(NAME) \ { \ - GAME_DRIVER_TYPE(NAME, CLASS), \ + GAME_DRIVER_TYPE(NAME, CLASS, FLAGS), \ #PARENT, \ #YEAR, \ COMPANY, \ @@ -183,7 +251,7 @@ extern game_driver const GAME_NAME(NAME) \ ROM_NAME(NAME), \ #COMPAT, \ nullptr, \ - ROT0 | (FLAGS) | MACHINE_TYPE_CONSOLE, \ + machine_flags::type(u32(ROT0 | (FLAGS) | MACHINE_TYPE_CONSOLE)), \ #NAME \ }; @@ -192,7 +260,7 @@ extern game_driver const GAME_NAME(NAME) \ GAME_DRIVER_TRAITS(NAME,FULLNAME) \ extern game_driver const GAME_NAME(NAME) \ { \ - GAME_DRIVER_TYPE(NAME, CLASS), \ + GAME_DRIVER_TYPE(NAME, CLASS, FLAGS), \ #PARENT, \ #YEAR, \ COMPANY, \ @@ -202,7 +270,7 @@ extern game_driver const GAME_NAME(NAME) \ ROM_NAME(NAME), \ #COMPAT, \ nullptr, \ - ROT0 | (FLAGS) | MACHINE_TYPE_COMPUTER, \ + machine_flags::type(u32(ROT0 | (FLAGS) | MACHINE_TYPE_COMPUTER)), \ #NAME \ }; @@ -211,7 +279,7 @@ extern game_driver const GAME_NAME(NAME) \ GAME_DRIVER_TRAITS(NAME,FULLNAME) \ extern game_driver const GAME_NAME(NAME) \ { \ - GAME_DRIVER_TYPE(NAME, CLASS), \ + GAME_DRIVER_TYPE(NAME, CLASS, FLAGS), \ #PARENT, \ #YEAR, \ COMPANY, \ @@ -221,7 +289,7 @@ extern game_driver const GAME_NAME(NAME) \ ROM_NAME(NAME), \ #COMPAT, \ nullptr, \ - ROT0 | (FLAGS) | MACHINE_TYPE_OTHER, \ + machine_flags::type(u32(ROT0 | (FLAGS) | MACHINE_TYPE_OTHER)), \ #NAME \ }; diff --git a/src/emu/render.cpp b/src/emu/render.cpp index 29fd2e42a63..4531b2adc32 100644 --- a/src/emu/render.cpp +++ b/src/emu/render.cpp @@ -575,7 +575,7 @@ render_container::render_container(render_manager &manager, screen_device *scree if (m_screen != nullptr) { // set the initial orientation and brightness/contrast/gamma - m_user.m_orientation = manager.machine().system().flags & ORIENTATION_MASK; + m_user.m_orientation = manager.machine().system().flags & machine_flags::MASK_ORIENTATION; m_user.m_brightness = manager.machine().options().brightness(); m_user.m_contrast = manager.machine().options().contrast(); m_user.m_gamma = manager.machine().options().gamma(); @@ -948,7 +948,7 @@ render_target::render_target(render_manager &manager, const internal_layout *lay // determine the base orientation based on options if (!manager.machine().options().rotate()) - m_base_orientation = orientation_reverse(manager.machine().system().flags & ORIENTATION_MASK); + m_base_orientation = orientation_reverse(manager.machine().system().flags & machine_flags::MASK_ORIENTATION); // rotate left/right if (manager.machine().options().ror() || (manager.machine().options().auto_ror() && (manager.machine().system().flags & ORIENTATION_SWAP_XY))) diff --git a/src/emu/save.cpp b/src/emu/save.cpp index c85f0d1b9ef..dea222227ee 100644 --- a/src/emu/save.cpp +++ b/src/emu/save.cpp @@ -155,7 +155,7 @@ void save_manager::save_memory(device_t *device, const char *module, const char if (!m_reg_allowed) { machine().logerror("Attempt to register save state entry after state registration is closed!\nModule %s tag %s name %s\n", module, tag, name); - if (machine().system().flags & MACHINE_SUPPORTS_SAVE) + if (machine().system().flags & machine_flags::SUPPORTS_SAVE) fatalerror("Attempt to register save state entry after state registration is closed!\nModule %s tag %s name %s\n", module, tag, name); m_illegal_regs++; return; diff --git a/src/emu/validity.cpp b/src/emu/validity.cpp index 6322ac69738..fee199034fc 100644 --- a/src/emu/validity.cpp +++ b/src/emu/validity.cpp @@ -1362,7 +1362,7 @@ void validity_checker::validate_driver() // determine if we are a clone bool is_clone = (strcmp(m_current_driver->parent, "0") != 0); int clone_of = m_drivlist.clone(*m_current_driver); - if (clone_of != -1 && (m_drivlist.driver(clone_of).flags & MACHINE_IS_BIOS_ROOT)) + if (clone_of != -1 && (m_drivlist.driver(clone_of).flags & machine_flags::IS_BIOS_ROOT)) is_clone = false; // if we have at least 100 drivers, validate the clone @@ -1422,17 +1422,24 @@ void validity_checker::validate_driver() } // make sure sound-less drivers are flagged - sound_interface_iterator iter(m_current_config->root_device()); - if ((m_current_driver->flags & MACHINE_IS_BIOS_ROOT) == 0 && !iter.first() && (m_current_driver->flags & (MACHINE_NO_SOUND | MACHINE_NO_SOUND_HW)) == 0) - osd_printf_error("Driver is missing MACHINE_NO_SOUND flag\n"); + device_t::feature_type const unemulated(m_current_driver->type.unemulated_features()); + device_t::feature_type const imperfect(m_current_driver->type.imperfect_features()); + if (!(m_current_driver->flags & (machine_flags::IS_BIOS_ROOT | machine_flags::NO_SOUND_HW)) && !(unemulated & device_t::feature::SOUND)) + { + sound_interface_iterator iter(m_current_config->root_device()); + if (!iter.first()) + osd_printf_error("Driver is missing MACHINE_NO_SOUND or MACHINE_NO_SOUND_HW flag\n"); + } // catch invalid flag combinations - if ((m_current_driver->flags & MACHINE_WRONG_COLORS) && (m_current_driver->flags & MACHINE_IMPERFECT_COLORS)) - osd_printf_error("Driver cannot have colours that are both completely wrong and imperfect\n"); - if ((m_current_driver->flags & MACHINE_NO_SOUND_HW) && (m_current_driver->flags & (MACHINE_NO_SOUND | MACHINE_IMPERFECT_SOUND))) - osd_printf_error("Machine without sound hardware cannot have unemulated sound\n"); - if ((m_current_driver->flags & MACHINE_NO_SOUND) && (m_current_driver->flags & MACHINE_IMPERFECT_SOUND)) - osd_printf_error("Driver cannot have sound emulation that's both imperfect and not present\n"); + if (unemulated & ~device_t::feature::ALL) + osd_printf_error("Driver has invalid unemulated feature flags (0x%08lX)\n", static_cast<unsigned long>(unemulated & ~device_t::feature::ALL)); + if (imperfect & ~device_t::feature::ALL) + osd_printf_error("Driver has invalid imperfect feature flags (0x%08lX)\n", static_cast<unsigned long>(imperfect & ~device_t::feature::ALL)); + if (unemulated & imperfect) + osd_printf_error("Driver cannot have features that are both unemulated and imperfect (0x%08lX)\n", static_cast<unsigned long>(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"); } @@ -1978,6 +1985,16 @@ void validity_checker::validate_device_types() if (dev->type().type() != type.type()) osd_printf_error("Device %s reports type '%s' (created with '%s')\n", description.c_str(), dev->type().type().name(), type.type().name()); + // catch invalid flag combinations + device_t::feature_type const unemulated(dev->type().unemulated_features()); + device_t::feature_type const imperfect(dev->type().imperfect_features()); + if (unemulated & ~device_t::feature::ALL) + osd_printf_error("Device has invalid unemulated feature flags (0x%08lX)\n", static_cast<unsigned long>(unemulated & ~device_t::feature::ALL)); + if (imperfect & ~device_t::feature::ALL) + osd_printf_error("Device has invalid imperfect feature flags (0x%08lX)\n", static_cast<unsigned long>(imperfect & ~device_t::feature::ALL)); + if (unemulated & imperfect) + osd_printf_error("Device cannot have features that are both unemulated and imperfect (0x%08lX)\n", static_cast<unsigned long>(unemulated & imperfect)); + config.device_remove(&config.root_device(), "_tmp"); } diff --git a/src/frontend/mame/clifront.cpp b/src/frontend/mame/clifront.cpp index 24dee0b9e2a..872d0e7df29 100644 --- a/src/frontend/mame/clifront.cpp +++ b/src/frontend/mame/clifront.cpp @@ -360,7 +360,7 @@ void cli_frontend::listfull(const std::vector<std::string> &args) // iterate through drivers and output the info while (drivlist.next()) - if ((drivlist.driver().flags & MACHINE_NO_STANDALONE) == 0) + if ((drivlist.driver().flags & machine_flags::NO_STANDALONE) == 0) osd_printf_info("%-18s\"%s\"\n", drivlist.driver().name, drivlist.driver().type.fullname()); } @@ -403,7 +403,7 @@ void cli_frontend::listclones(const std::vector<std::string> &args) { // if we have a non-bios clone and it matches, keep it int clone_of = drivlist.clone(); - if (clone_of != -1 && (drivlist.driver(clone_of).flags & MACHINE_IS_BIOS_ROOT) == 0) + if ((clone_of >= 0) && !(drivlist.driver(clone_of).flags & machine_flags::IS_BIOS_ROOT)) if (drivlist.matches(gamename, drivlist.driver(clone_of).name)) drivlist.include(); } @@ -427,7 +427,7 @@ void cli_frontend::listclones(const std::vector<std::string> &args) while (drivlist.next()) { int clone_of = drivlist.clone(); - if (clone_of != -1 && (drivlist.driver(clone_of).flags & MACHINE_IS_BIOS_ROOT) == 0) + if ((clone_of >= 0) && !(drivlist.driver(clone_of).flags & machine_flags::IS_BIOS_ROOT)) osd_printf_info("%-16s %s\n", drivlist.driver().name, drivlist.driver(clone_of).name); } } diff --git a/src/frontend/mame/info.cpp b/src/frontend/mame/info.cpp index 05037fda65d..9d2963c68c9 100644 --- a/src/frontend/mame/info.cpp +++ b/src/frontend/mame/info.cpp @@ -42,7 +42,7 @@ const char info_xml_creator::s_dtd_string[] = "\t<!ATTLIST __XML_ROOT__ build CDATA #IMPLIED>\n" "\t<!ATTLIST __XML_ROOT__ debug (yes|no) \"no\">\n" "\t<!ATTLIST __XML_ROOT__ mameconfig CDATA #REQUIRED>\n" -"\t<!ELEMENT __XML_TOP__ (description, year?, manufacturer?, biosset*, rom*, disk*, device_ref*, sample*, chip*, display*, sound?, input?, dipswitch*, configuration*, port*, adjuster*, driver?, device*, slot*, softwarelist*, ramoption*)>\n" +"\t<!ELEMENT __XML_TOP__ (description, year?, manufacturer?, biosset*, rom*, disk*, device_ref*, sample*, chip*, display*, sound?, input?, dipswitch*, configuration*, port*, adjuster*, driver?, feature*, device*, slot*, softwarelist*, ramoption*)>\n" "\t\t<!ATTLIST __XML_TOP__ name CDATA #REQUIRED>\n" "\t\t<!ATTLIST __XML_TOP__ sourcefile CDATA #IMPLIED>\n" "\t\t<!ATTLIST __XML_TOP__ isbios (yes|no) \"no\">\n" @@ -155,6 +155,10 @@ const char info_xml_creator::s_dtd_string[] = "\t\t\t<!ATTLIST driver cocktail (good|imperfect|preliminary) #IMPLIED>\n" "\t\t\t<!ATTLIST driver protection (good|imperfect|preliminary) #IMPLIED>\n" "\t\t\t<!ATTLIST driver savestate (supported|unsupported) #REQUIRED>\n" +"\t\t<!ELEMENT feature EMPTY>\n" +"\t\t\t<!ATTLIST feature type (protection|palette|graphics|sound|controls|keyboard|mouse|microphone|camera|disk|printer|lan|wan) #REQUIRED>\n" +"\t\t\t<!ATTLIST feature status (unemulated|imperfect) #IMPLIED>\n" +"\t\t\t<!ATTLIST feature overall (unemulated|imperfect) #IMPLIED>\n" "\t\t<!ELEMENT device (instance*, extension*)>\n" "\t\t\t<!ATTLIST device type CDATA #REQUIRED>\n" "\t\t\t<!ATTLIST device tag CDATA #IMPLIED>\n" @@ -370,22 +374,22 @@ void info_xml_creator::output_footer() void info_xml_creator::output_one(driver_enumerator &drivlist, device_type_set *devtypes) { - // no action if not a game const game_driver &driver = drivlist.driver(); - if (driver.flags & MACHINE_NO_STANDALONE) - return; - std::shared_ptr<machine_config> const config(drivlist.config()); device_iterator iter(config->root_device()); - // allocate input ports + // allocate input ports and build overall emulation status ioport_list portlist; std::string errors; + device_t::feature_type overall_unemulated(driver.type.unemulated_features()); + device_t::feature_type overall_imperfect(driver.type.imperfect_features()); for (device_t &device : iter) { portlist.append(device, errors); + overall_unemulated |= device.type().unemulated_features(); + overall_imperfect |= device.type().imperfect_features(); - if (devtypes && device.owner() && device.shortname() && *device.shortname()) + if (devtypes && device.owner()) devtypes->insert(&device.type()); } @@ -429,16 +433,16 @@ void info_xml_creator::output_one(driver_enumerator &drivlist, device_type_set * fprintf(m_output, " sourcefile=\"%s\"", util::xml::normalize_string(start)); // append bios and runnable flags - if (driver.flags & MACHINE_IS_BIOS_ROOT) + if (driver.flags & machine_flags::IS_BIOS_ROOT) fprintf(m_output, " isbios=\"yes\""); - if (driver.flags & MACHINE_NO_STANDALONE) + if (driver.flags & machine_flags::NO_STANDALONE) fprintf(m_output, " runnable=\"no\""); - if (driver.flags & MACHINE_MECHANICAL) + if (driver.flags & machine_flags::MECHANICAL) fprintf(m_output, " ismechanical=\"yes\""); // display clone information int clone_of = drivlist.find(driver.parent); - if (clone_of != -1 && !(drivlist.driver(clone_of).flags & MACHINE_IS_BIOS_ROOT)) + if (clone_of != -1 && !(drivlist.driver(clone_of).flags & machine_flags::IS_BIOS_ROOT)) fprintf(m_output, " cloneof=\"%s\"", util::xml::normalize_string(drivlist.driver(clone_of).name)); if (clone_of != -1) fprintf(m_output, " romof=\"%s\"", util::xml::normalize_string(drivlist.driver(clone_of).name)); @@ -472,7 +476,8 @@ void info_xml_creator::output_one(driver_enumerator &drivlist, device_type_set * output_switches(portlist, "", IPT_CONFIG, "configuration", "confsetting"); output_ports(portlist); output_adjusters(portlist); - output_driver(driver); + output_driver(driver, overall_unemulated, overall_imperfect); + output_features(driver.type, overall_unemulated, overall_imperfect); output_images(config->root_device(), ""); output_slots(*config, config->root_device(), "", devtypes); output_software_list(config->root_device()); @@ -495,11 +500,19 @@ void info_xml_creator::output_one_device(machine_config &config, device_t &devic sound_interface_iterator snditer(device); if (snditer.first() != nullptr) has_speaker = true; - // generate input list + + // generate input list and build overall emulation status ioport_list portlist; std::string errors; + device_t::feature_type overall_unemulated(device.type().unemulated_features()); + device_t::feature_type overall_imperfect(device.type().imperfect_features()); for (device_t &dev : device_iterator(device)) + { portlist.append(dev, errors); + overall_unemulated |= dev.type().unemulated_features(); + overall_imperfect |= dev.type().imperfect_features(); + } + // check if the device adds player inputs (other than dsw and configs) to the system for (auto &port : portlist) for (ioport_field &field : port.second->fields()) @@ -535,6 +548,7 @@ void info_xml_creator::output_one_device(machine_config &config, device_t &devic output_switches(portlist, devtag, IPT_DIPSWITCH, "dipswitch", "dipvalue"); output_switches(portlist, devtag, IPT_CONFIG, "configuration", "confsetting"); output_adjusters(portlist); + output_features(device.type(), overall_unemulated, overall_imperfect); output_images(device, devtag); output_slots(config, device, devtag, nullptr); fprintf(m_output, "\t</%s>\n", XML_TOP); @@ -829,7 +843,7 @@ void info_xml_creator::output_chips(device_t &device, const char *root_tag) // displays //------------------------------------------------- -void info_xml_creator::output_display(device_t &device, u32 const *flags, const char *root_tag) +void info_xml_creator::output_display(device_t &device, machine_flags::type const *flags, const char *root_tag) { // iterate over screens for (const screen_device &screendev : screen_device_iterator(device)) @@ -853,7 +867,7 @@ void info_xml_creator::output_display(device_t &device, u32 const *flags, const // output the orientation as a string if (flags) { - switch (*flags & ORIENTATION_MASK) + switch (*flags & machine_flags::MASK_ORIENTATION) { case ORIENTATION_FLIP_X: fprintf(m_output, " rotate=\"0\" flipx=\"yes\""); @@ -1504,57 +1518,57 @@ void info_xml_creator::output_adjusters(const ioport_list &portlist) // output_driver - print driver status //------------------------------------------------- -void info_xml_creator::output_driver(game_driver const &driver) +void info_xml_creator::output_driver(game_driver const &driver, device_t::feature_type unemulated, device_t::feature_type imperfect) { fprintf(m_output, "\t\t<driver"); - /* The status entry is an hint for frontend authors */ - /* to select working and not working games without */ - /* the need to know all the other status entries. */ - /* Games marked as status=good are perfectly emulated, games */ - /* marked as status=imperfect are emulated with only */ - /* some minor issues, games marked as status=preliminary */ - /* don't work or have major emulation problems. */ + /* + The status entry is an hint for frontend authors to select working + and not working games without the need to know all the other status + entries. Games marked as status=good are perfectly emulated, games + marked as status=imperfect are emulated with only some minor issues, + games marked as status=preliminary don't work or have major + emulation problems. + */ + + auto const print_feature = + [this, unemulated, imperfect] (device_t::feature_type feature, char const *name, bool show_good) + { + if (unemulated & feature) + fprintf(m_output, " %s=\"preliminary\"", name); + else if (imperfect & feature) + fprintf(m_output, " %s=\"imperfect\"", name); + else if (show_good) + fprintf(m_output, " %s=\"good\"", name); + }; u32 const flags = driver.flags; - if (flags & (MACHINE_NOT_WORKING | MACHINE_UNEMULATED_PROTECTION | MACHINE_NO_SOUND | MACHINE_WRONG_COLORS | MACHINE_MECHANICAL)) + bool const machine_preliminary(flags & (machine_flags::NOT_WORKING | machine_flags::MECHANICAL)); + bool const unemulated_preliminary(unemulated & (device_t::feature::PALETTE | device_t::feature::GRAPHICS | device_t::feature::SOUND | device_t::feature::KEYBOARD)); + bool const imperfect_preliminary((unemulated | imperfect) & device_t::feature::PROTECTION); + + if (machine_preliminary || unemulated_preliminary || imperfect_preliminary) fprintf(m_output, " status=\"preliminary\""); - else if (flags & (MACHINE_IMPERFECT_COLORS | MACHINE_IMPERFECT_SOUND | MACHINE_IMPERFECT_GRAPHICS)) + else if (imperfect) fprintf(m_output, " status=\"imperfect\""); else fprintf(m_output, " status=\"good\""); - if (flags & MACHINE_NOT_WORKING) + if (flags & machine_flags::NOT_WORKING) fprintf(m_output, " emulation=\"preliminary\""); else fprintf(m_output, " emulation=\"good\""); - if (flags & MACHINE_WRONG_COLORS) - fprintf(m_output, " color=\"preliminary\""); - else if (flags & MACHINE_IMPERFECT_COLORS) - fprintf(m_output, " color=\"imperfect\""); - else - fprintf(m_output, " color=\"good\""); - - if (flags & MACHINE_NO_SOUND) - fprintf(m_output, " sound=\"preliminary\""); - else if (flags & MACHINE_IMPERFECT_SOUND) - fprintf(m_output, " sound=\"imperfect\""); - else - fprintf(m_output, " sound=\"good\""); + print_feature(device_t::feature::PALETTE, "color", true); + print_feature(device_t::feature::SOUND, "sound", true); + print_feature(device_t::feature::GRAPHICS, "graphic", true); - if (flags & MACHINE_IMPERFECT_GRAPHICS) - fprintf(m_output, " graphic=\"imperfect\""); - else - fprintf(m_output, " graphic=\"good\""); - - if (flags & MACHINE_NO_COCKTAIL) + if (flags & machine_flags::NO_COCKTAIL) fprintf(m_output, " cocktail=\"preliminary\""); - if (flags & MACHINE_UNEMULATED_PROTECTION) - fprintf(m_output, " protection=\"preliminary\""); + print_feature(device_t::feature::PROTECTION, "protection", false); - if (flags & MACHINE_SUPPORTS_SAVE) + if (flags & machine_flags::SUPPORTS_SAVE) fprintf(m_output, " savestate=\"supported\""); else fprintf(m_output, " savestate=\"unsupported\""); @@ -1564,6 +1578,53 @@ void info_xml_creator::output_driver(game_driver const &driver) //------------------------------------------------- +// output_features - print emulation features of +// +//------------------------------------------------- + +void info_xml_creator::output_features(device_type type, device_t::feature_type unemulated, device_t::feature_type imperfect) +{ + static constexpr std::pair<device_t::feature_type, char const *> features[] = { + { device_t::feature::PROTECTION, "protection" }, + { device_t::feature::PALETTE, "palette" }, + { device_t::feature::GRAPHICS, "graphics" }, + { device_t::feature::SOUND, "sound" }, + { device_t::feature::CONTROLS, "controls" }, + { device_t::feature::KEYBOARD, "keyboard" }, + { device_t::feature::MOUSE, "mouse" }, + { device_t::feature::MICROPHONE, "microphone" }, + { device_t::feature::CAMERA, "camera" }, + { device_t::feature::DISK, "disk" }, + { device_t::feature::PRINTER, "printer" }, + { device_t::feature::LAN, "lan" }, + { device_t::feature::WAN, "wan" } }; + + device_t::feature_type const flags(type.unemulated_features() | type.imperfect_features() | unemulated | imperfect); + for (auto const &feature : features) + { + if (flags & feature.first) + { + fprintf(m_output, "\t\t<feature type=\"%s\"", feature.second); + if (type.unemulated_features() & feature.first) + { + fprintf(m_output, " status=\"unemulated\""); + } + else + { + if (type.imperfect_features() & feature.first) + fprintf(m_output, " status=\"imperfect\""); + if (unemulated & feature.first) + fprintf(m_output, " overall=\"unemulated\""); + else if ((~type.imperfect_features() & imperfect) & feature.first) + fprintf(m_output, " overall=\"imperfect\""); + } + fprintf(m_output, "/>\n"); + } + } +} + + +//------------------------------------------------- // output_images - prints m_output all info on // image devices //------------------------------------------------- diff --git a/src/frontend/mame/info.h b/src/frontend/mame/info.h index 8ebf1bc4a3b..635084a3a3b 100644 --- a/src/frontend/mame/info.h +++ b/src/frontend/mame/info.h @@ -52,13 +52,14 @@ private: void output_device_roms(device_t &root); void output_sample(device_t &device); void output_chips(device_t &device, const char *root_tag); - void output_display(device_t &device, u32 const *flags, const char *root_tag); + void output_display(device_t &device, machine_flags::type const *flags, const char *root_tag); void output_sound(device_t &device); void output_input(const ioport_list &portlist); void output_switches(const ioport_list &portlist, const char *root_tag, int type, const char *outertag, const char *innertag); void output_ports(const ioport_list &portlist); void output_adjusters(const ioport_list &portlist); - void output_driver(game_driver const &driver); + void output_driver(game_driver const &driver, device_t::feature_type unemulated, device_t::feature_type imperfect); + void output_features(device_type type, device_t::feature_type unemulated, device_t::feature_type imperfect); void output_images(device_t &device, const char *root_tag); void output_slots(machine_config &config, device_t &device, const char *root_tag, device_type_set *devtypes); void output_software_list(device_t &root); diff --git a/src/frontend/mame/luaengine.cpp b/src/frontend/mame/luaengine.cpp index a68aaa1699b..b2ea5e017d2 100644 --- a/src/frontend/mame/luaengine.cpp +++ b/src/frontend/mame/luaengine.cpp @@ -1763,7 +1763,7 @@ void lua_engine::initialize() "height", [](screen_device &sdev) { return sdev.visible_area().height(); }, "width", [](screen_device &sdev) { return sdev.visible_area().width(); }, "orientation", [](screen_device &sdev) { - uint32_t flags = sdev.machine().system().flags & ORIENTATION_MASK; + uint32_t flags = sdev.machine().system().flags & machine_flags::MASK_ORIENTATION; int rotation_angle = 0; switch (flags) { diff --git a/src/frontend/mame/mameopts.cpp b/src/frontend/mame/mameopts.cpp index 029c5c601a6..d6c1e1044cf 100644 --- a/src/frontend/mame/mameopts.cpp +++ b/src/frontend/mame/mameopts.cpp @@ -49,14 +49,23 @@ void mame_options::parse_standard_inis(emu_options &options, std::ostream &error else parse_one_ini(options, "horizont", OPTION_PRIORITY_ORIENTATION_INI, &error_stream); - if (cursystem->flags & MACHINE_TYPE_ARCADE) + switch (cursystem->flags & machine_flags::MASK_TYPE) + { + case machine_flags::TYPE_ARCADE: parse_one_ini(options, "arcade", OPTION_PRIORITY_SYSTYPE_INI, &error_stream); - else if (cursystem->flags & MACHINE_TYPE_CONSOLE) + break; + case machine_flags::TYPE_CONSOLE: parse_one_ini(options ,"console", OPTION_PRIORITY_SYSTYPE_INI, &error_stream); - else if (cursystem->flags & MACHINE_TYPE_COMPUTER) + break; + case machine_flags::TYPE_COMPUTER: parse_one_ini(options, "computer", OPTION_PRIORITY_SYSTYPE_INI, &error_stream); - else if (cursystem->flags & MACHINE_TYPE_OTHER) + break; + case machine_flags::TYPE_OTHER: parse_one_ini(options, "othersys", OPTION_PRIORITY_SYSTYPE_INI, &error_stream); + break; + default: + break; + } machine_config config(*cursystem, options); for (const screen_device &device : screen_device_iterator(config.root_device())) diff --git a/src/frontend/mame/ui/auditmenu.cpp b/src/frontend/mame/ui/auditmenu.cpp index ed9e0094bfa..23c0eee30ba 100644 --- a/src/frontend/mame/ui/auditmenu.cpp +++ b/src/frontend/mame/ui/auditmenu.cpp @@ -45,14 +45,14 @@ bool sorted_game_list(const game_driver *x, const game_driver *y) if (clonex) { cx = driver_list::find(x->parent); - if (cx == -1 || (driver_list::driver(cx).flags & MACHINE_IS_BIOS_ROOT) != 0) + if ((0 > cx) || (driver_list::driver(cx).flags & machine_flags::IS_BIOS_ROOT)) clonex = false; } if (cloney) { cy = driver_list::find(y->parent); - if (cy == -1 || (driver_list::driver(cy).flags & MACHINE_IS_BIOS_ROOT) != 0) + if ((0 > cy) || (driver_list::driver(cy).flags & machine_flags::IS_BIOS_ROOT)) cloney = false; } diff --git a/src/frontend/mame/ui/info.cpp b/src/frontend/mame/ui/info.cpp index e4abb6ce94d..1c792f1eaa3 100644 --- a/src/frontend/mame/ui/info.cpp +++ b/src/frontend/mame/ui/info.cpp @@ -18,40 +18,78 @@ #include "emuopts.h" namespace ui { + +namespace { + +constexpr machine_flags::type MACHINE_ERRORS = machine_flags::NOT_WORKING | 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 std::pair<device_t::feature_type, char const *> FEATURE_NAMES[] = { + { device_t::feature::PROTECTION, __("protection") }, + { device_t::feature::PALETTE, __("color palette") }, + { device_t::feature::GRAPHICS, __("graphics") }, + { device_t::feature::SOUND, __("sound") }, + { device_t::feature::CONTROLS, __("controls") }, + { device_t::feature::KEYBOARD, __("keyboard") }, + { device_t::feature::MOUSE, __("mouse") }, + { device_t::feature::MICROPHONE, __("microphone") }, + { device_t::feature::CAMERA, __("camera") }, + { device_t::feature::DISK, __("disk") }, + { device_t::feature::PRINTER, __("printer") }, + { device_t::feature::LAN, __("LAN") }, + { device_t::feature::WAN, __("WAN") } }; + +} // anonymous namespace + + //------------------------------------------------- // machine_info - constructor //------------------------------------------------- machine_info::machine_info(running_machine &machine) : m_machine(machine) + , m_flags(m_machine.system().flags) + , m_unemulated_features(m_machine.system().type.unemulated_features()) + , m_imperfect_features(m_machine.system().type.imperfect_features()) + , m_has_configs(false) + , m_has_analog(false) + , m_has_dips(false) + , m_has_bioses(false) + , m_has_keyboard(false) + , m_has_test_switch(false) { - // calculate "has..." values - m_has_configs = false; - m_has_analog = false; - m_has_dips = false; - m_has_bioses = false; - m_has_keyboard = false; - m_has_test_switch = 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; + switch (field.type()) + { + case IPT_DIPSWITCH: m_has_dips = true; break; + case IPT_CONFIG: m_has_configs = true; break; + case IPT_KEYBOARD: m_has_keyboard = true; break; + case IPT_SERVICE: m_has_test_switch = true; break; + default: break; + } if (field.is_analog()) m_has_analog = true; - if (field.type() == IPT_KEYBOARD) - m_has_keyboard = true; - if (field.type() == IPT_SERVICE) - m_has_test_switch = true; } + } + // build overall emulation status and look for BIOS options for (device_t &device : device_iterator(machine.root_device())) + { + if (dynamic_cast<device_sound_interface *>(&device)) + m_flags &= ~machine_flags::NO_SOUND_HW; + + m_unemulated_features |= device.type().unemulated_features(); + m_imperfect_features |= device.type().imperfect_features(); + for (const rom_entry &rom : device.rom_region_vector()) if (ROMENTRY_ISSYSTEM_BIOS(&rom)) { m_has_bioses = true; break; } + } + m_imperfect_features &= ~m_unemulated_features; } @@ -64,132 +102,112 @@ machine_info::machine_info(running_machine &machine) // text to the given buffer //------------------------------------------------- -std::string machine_info::warnings_string() +std::string machine_info::warnings_string() const { - constexpr uint32_t warning_flags = ( MACHINE_FATAL_FLAGS | MACHINE_WARNING_FLAGS | MACHINE_BTANB_FLAGS ); - - // 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) { + if (!m_machine.rom_load().software_load_warnings_message().empty()) 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) + if ((m_machine.rom_load().knownbad() > 0) || (m_flags & (MACHINE_WARNINGS | MACHINE_BTANB)) || m_unemulated_features || m_imperfect_features) { + if (!buf.str().empty()) + buf << '\n'; 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"); + // 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"); - // 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 ) + // add line for unemulated features + if (m_unemulated_features) + { + buf << _("Completely unemulated features: "); + bool first = false; + for (auto const &feature : FEATURE_NAMES) { - buf << _("This machine was never completed. It may exhibit strange behavior or missing elements that are not bugs in the emulation.\n"); + if (m_unemulated_features & feature.first) + { + util::stream_format(buf, first ? _("%s") : _(", %s"), _(feature.second)); + first = false; + } } + buf << '\n'; + } - if (m_machine.system().flags & MACHINE_NODEVICE_MICROPHONE ) - buf << _("This machine has unemulated microphone device.\n"); - - if (m_machine.system().flags & MACHINE_NODEVICE_CAMERA ) - buf << _("This machine has unemulated camera device.\n"); - - if (m_machine.system().flags & MACHINE_NODEVICE_PRINTER ) - buf << _("This machine has unemulated printer device.\n"); - - if (m_machine.system().flags & MACHINE_NODEVICE_LAN ) - buf << _("This machine has unemulated linking capabilities.\n"); - - if (m_machine.system().flags & MACHINE_NODEVICE_WAN ) - buf << _("This machine has unemulated networking capabilities.\n"); - - if (m_machine.system().flags & MACHINE_NO_SOUND_HW ) + // add line for imperfect features + if (m_imperfect_features) + { + buf << _("Imperfectly emulated features: "); + bool first = false; + for (auto const &feature : FEATURE_NAMES) { - buf << _("This machine has no sound hardware, MAME will produce no sounds, this is expected behaviour.\n"); + if (m_imperfect_features & feature.first) + { + util::stream_format(buf, first ? _("%s") : _(", %s"), _(feature.second)); + first = false; + } } + buf << '\n'; + } - - // if there's a NOT WORKING, UNEMULATED PROTECTION or GAME MECHANICAL warning, make it stronger - if (m_machine.system().flags & (MACHINE_FATAL_FLAGS)) + // add one line per machine warning flag + if (m_flags & machine_flags::NO_COCKTAIL) + buf << _("Screen flipping in cocktail mode is not supported.\n"); + if (m_flags & machine_flags::REQUIRES_ARTWORK) // check if external artwork is present before displaying this warning? + buf << _("This machine requires external artwork files.\n"); + if (m_flags & machine_flags::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_flags & machine_flags::NO_SOUND_HW ) + buf << _("This machine has no sound hardware, MAME will produce no sounds, this is expected behaviour.\n"); + + // these are more severe warnings + if (m_flags & machine_flags::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_flags & machine_flags::MECHANICAL) + buf << _("\nElements of this machine cannot be emulated as they requires physical interaction or consist of mechanical devices. It is not possible to fully experience this machine.\n"); + + if ((m_flags & MACHINE_ERRORS) || ((m_machine.system().type.unemulated_features() | m_machine.system().type.imperfect_features()) & device_t::feature::PROTECTION)) + { + // 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()) { - // 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"); + 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)) + { + // this one works, add a header and display the name of the clone + if (!foundworking) + util::stream_format(buf, _("\n\nThere are working clones of this machine: %s"), driver.name); + else + util::stream_format(buf, _(", %s"), driver.name); + foundworking = true; + } } - - // 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"; } + if (foundworking) + buf << '\n'; } // add the 'press OK' string - buf << _("\n\nPress any key to continue"); + if (!buf.str().empty()) + buf << _("\n\nPress any key to continue"); + return buf.str(); } @@ -198,7 +216,7 @@ std::string machine_info::warnings_string() // game_info_string - return the game info text //------------------------------------------------- -std::string machine_info::game_info_string() +std::string machine_info::game_info_string() const { std::ostringstream buf; @@ -316,7 +334,7 @@ std::string machine_info::game_info_string() // need an image to be loaded //------------------------------------------------- -std::string machine_info::mandatory_images() +std::string machine_info::mandatory_images() const { std::ostringstream buf; bool is_first = true; @@ -345,7 +363,7 @@ std::string machine_info::mandatory_images() // a given screen //------------------------------------------------- -std::string machine_info::get_screen_desc(screen_device &screen) +std::string machine_info::get_screen_desc(screen_device &screen) const { if (screen_device_iterator(m_machine.root_device()).count() > 1) return string_format(_("Screen '%1$s'"), screen.tag()); @@ -354,6 +372,23 @@ std::string machine_info::get_screen_desc(screen_device &screen) } +//------------------------------------------------- +// warnings_color - returns suitable colour for +// warning message based on severity +//------------------------------------------------- + +rgb_t machine_info::warnings_color() const +{ + if ((m_flags & MACHINE_ERRORS) || ((m_unemulated_features | m_imperfect_features) & device_t::feature::PROTECTION)) + return UI_RED_COLOR; + else if ((m_flags & MACHINE_WARNINGS) || m_unemulated_features || m_imperfect_features) + return UI_YELLOW_COLOR; + else + return UI_BACKGROUND_COLOR; +} + + + /*------------------------------------------------- menu_game_info - handle the game information menu diff --git a/src/frontend/mame/ui/info.h b/src/frontend/mame/ui/info.h index b718c2acf64..491f7898841 100644 --- a/src/frontend/mame/ui/info.h +++ b/src/frontend/mame/ui/info.h @@ -32,15 +32,23 @@ public: bool has_test_switch() const { return m_has_test_switch; } // text generators - std::string warnings_string(); - std::string game_info_string(); - std::string mandatory_images(); - std::string get_screen_desc(screen_device &screen); + std::string warnings_string() const; + std::string game_info_string() const; + std::string mandatory_images() const; + std::string get_screen_desc(screen_device &screen) const; + + // message colour + rgb_t warnings_color() const; private: // reference to machine running_machine & m_machine; + // overall feature status + machine_flags::type m_flags; + device_t::feature_type m_unemulated_features; + device_t::feature_type m_imperfect_features; + // has... bool m_has_configs; bool m_has_analog; diff --git a/src/frontend/mame/ui/inifile.cpp b/src/frontend/mame/ui/inifile.cpp index 2da9adb59d2..e56dd317242 100644 --- a/src/frontend/mame/ui/inifile.cpp +++ b/src/frontend/mame/ui/inifile.cpp @@ -179,7 +179,7 @@ void favorite_manager::add_favorite_game(ui_software_info &swinfo) void favorite_manager::add_favorite_game() { - if ((machine().system().flags & MACHINE_TYPE_ARCADE) != 0) + if ((machine().system().flags & machine_flags::MASK_TYPE) == machine_flags::TYPE_ARCADE) { add_favorite_game(&machine().system()); return; @@ -270,7 +270,7 @@ void favorite_manager::remove_favorite_game() bool favorite_manager::isgame_favorite() { - if ((machine().system().flags & MACHINE_TYPE_ARCADE) != 0) + if ((machine().system().flags & machine_flags::MASK_TYPE) == machine_flags::TYPE_ARCADE) return isgame_favorite(&machine().system()); auto image_loaded = false; diff --git a/src/frontend/mame/ui/miscmenu.cpp b/src/frontend/mame/ui/miscmenu.cpp index e48b042b53d..09bfd0d2388 100644 --- a/src/frontend/mame/ui/miscmenu.cpp +++ b/src/frontend/mame/ui/miscmenu.cpp @@ -635,7 +635,7 @@ void menu_export::handle() // iterate through drivers and output the info while (drvlist.next()) - if ((drvlist.driver().flags & MACHINE_NO_STANDALONE) == 0) + if (!(drvlist.driver().flags & machine_flags::NO_STANDALONE)) util::stream_format(buffer, "%-18s\"%s\"\n", drvlist.driver().name, drvlist.driver().type.fullname()); file.puts(buffer.str().c_str()); file.close(); diff --git a/src/frontend/mame/ui/selgame.cpp b/src/frontend/mame/ui/selgame.cpp index fce7ad41d9f..06a1ec8ec59 100644 --- a/src/frontend/mame/ui/selgame.cpp +++ b/src/frontend/mame/ui/selgame.cpp @@ -540,7 +540,7 @@ void menu_select_game::populate(float &customtop, float &custombottom) if (cloneof) { int cx = driver_list::find(elem->parent); - if (cx != -1 && ((driver_list::driver(cx).flags & MACHINE_IS_BIOS_ROOT) != 0)) + if (cx != -1 && ((driver_list::driver(cx).flags & machine_flags::IS_BIOS_ROOT) != 0)) cloneof = false; } @@ -568,7 +568,7 @@ void menu_select_game::populate(float &customtop, float &custombottom) if (cloneof) { int cx = driver_list::find(favmap.second.driver->parent); - if (cx != -1 && ((driver_list::driver(cx).flags & MACHINE_IS_BIOS_ROOT) != 0)) + if (cx != -1 && ((driver_list::driver(cx).flags & machine_flags::IS_BIOS_ROOT) != 0)) cloneof = false; } @@ -802,7 +802,7 @@ void menu_select_game::inkey_select(const event *menu_event) // if everything looks good, schedule the new driver if (summary == media_auditor::CORRECT || summary == media_auditor::BEST_AVAILABLE || summary == media_auditor::NONE_NEEDED) { - if ((driver->flags & MACHINE_TYPE_ARCADE) == 0) + if ((machine().system().flags & machine_flags::MASK_TYPE) != machine_flags::TYPE_ARCADE) { for (software_list_device &swlistdev : software_list_device_iterator(enumerator.config()->root_device())) if (!swlistdev.get_info().empty()) @@ -861,7 +861,7 @@ void menu_select_game::inkey_select_favorite(const event *menu_event) if (summary == media_auditor::CORRECT || summary == media_auditor::BEST_AVAILABLE || summary == media_auditor::NONE_NEEDED) { - if ((ui_swinfo->driver->flags & MACHINE_TYPE_ARCADE) == 0) + if ((machine().system().flags & machine_flags::MASK_TYPE) != machine_flags::TYPE_ARCADE) { for (software_list_device &swlistdev : software_list_device_iterator(enumerator.config()->root_device())) if (!swlistdev.get_info().empty()) @@ -950,7 +950,7 @@ void menu_select_game::build_list(const char *filter_text, int filter, bool bios for (auto & s_driver : s_drivers) { - if (!bioscheck && filter != FILTER_BIOS && (s_driver->flags & MACHINE_IS_BIOS_ROOT) != 0) + if (!bioscheck && filter != FILTER_BIOS && (s_driver->flags & machine_flags::IS_BIOS_ROOT) != 0) continue; switch (filter) @@ -962,17 +962,17 @@ void menu_select_game::build_list(const char *filter_text, int filter, bool bios break; case FILTER_WORKING: - if (!(s_driver->flags & MACHINE_NOT_WORKING)) + if (!(s_driver->flags & machine_flags::NOT_WORKING)) m_displaylist.push_back(s_driver); break; case FILTER_NOT_MECHANICAL: - if (!(s_driver->flags & MACHINE_MECHANICAL)) + if (!(s_driver->flags & machine_flags::MECHANICAL)) m_displaylist.push_back(s_driver); break; case FILTER_BIOS: - if (s_driver->flags & MACHINE_IS_BIOS_ROOT) + if (s_driver->flags & machine_flags::IS_BIOS_ROOT) m_displaylist.push_back(s_driver); break; @@ -983,7 +983,7 @@ void menu_select_game::build_list(const char *filter_text, int filter, bool bios if (cloneof) { auto cx = driver_list::find(s_driver->parent); - if (cx != -1 && ((driver_list::driver(cx).flags & MACHINE_IS_BIOS_ROOT) != 0)) + if (cx != -1 && ((driver_list::driver(cx).flags & machine_flags::IS_BIOS_ROOT) != 0)) cloneof = false; } @@ -994,22 +994,22 @@ void menu_select_game::build_list(const char *filter_text, int filter, bool bios } break; case FILTER_NOT_WORKING: - if (s_driver->flags & MACHINE_NOT_WORKING) + if (s_driver->flags & machine_flags::NOT_WORKING) m_displaylist.push_back(s_driver); break; case FILTER_MECHANICAL: - if (s_driver->flags & MACHINE_MECHANICAL) + if (s_driver->flags & machine_flags::MECHANICAL) m_displaylist.push_back(s_driver); break; case FILTER_SAVE: - if (s_driver->flags & MACHINE_SUPPORTS_SAVE) + if (s_driver->flags & machine_flags::SUPPORTS_SAVE) m_displaylist.push_back(s_driver); break; case FILTER_NOSAVE: - if (!(s_driver->flags & MACHINE_SUPPORTS_SAVE)) + if (!(s_driver->flags & machine_flags::SUPPORTS_SAVE)) m_displaylist.push_back(s_driver); break; @@ -1172,7 +1172,7 @@ void menu_select_game::populate_search() if (cloneof) { int cx = driver_list::find(m_searchlist[curitem]->parent); - if (cx != -1 && ((driver_list::driver(cx).flags & MACHINE_IS_BIOS_ROOT) != 0)) + if (cx != -1 && ((driver_list::driver(cx).flags & machine_flags::IS_BIOS_ROOT) != 0)) cloneof = false; } item_append(m_searchlist[curitem]->type.fullname(), "", (!cloneof) ? flags_ui : (FLAG_INVERT | flags_ui), @@ -1198,36 +1198,39 @@ void menu_select_game::general_info(const game_driver *driver, std::string &buff else str << _("Driver is Parent:\n"); - if (driver->flags & MACHINE_NOT_WORKING) + if (driver->flags & machine_flags::NOT_WORKING) str << _("Overall: NOT WORKING\n"); - else if (driver->flags & MACHINE_UNEMULATED_PROTECTION) + else if ((driver->type.unemulated_features() | driver->type.imperfect_features()) & device_t::feature::PROTECTION) str << _("Overall: Unemulated Protection\n"); else str << _("Overall: Working\n"); - if (driver->flags & MACHINE_IMPERFECT_COLORS) - str << _("Graphics: Imperfect Colors\n"); - else if (driver->flags & MACHINE_WRONG_COLORS) + if (driver->type.unemulated_features() & device_t::feature::GRAPHICS) + str << _("Graphics: Unimplemented\n"); + else if (driver->type.unemulated_features() & device_t::feature::PALETTE) str << ("Graphics: Wrong Colors\n"); - else if (driver->flags & MACHINE_IMPERFECT_GRAPHICS) + else if (driver->type.imperfect_features() & device_t::feature::PALETTE) + str << _("Graphics: Imperfect Colors\n"); + else if (driver->type.imperfect_features() & device_t::feature::GRAPHICS) str << _("Graphics: Imperfect\n"); else str << _("Graphics: OK\n"); - if (driver->flags & MACHINE_NO_SOUND) + if (driver->flags & machine_flags::NO_SOUND_HW) + str << _("Sound: None\n"); + else if (driver->type.unemulated_features() & device_t::feature::SOUND) str << _("Sound: Unimplemented\n"); - else if (driver->flags & MACHINE_IMPERFECT_SOUND) + else if (driver->type.imperfect_features() & device_t::feature::SOUND) str << _("Sound: Imperfect\n"); else str << _("Sound: OK\n"); - util::stream_format(str, _("Driver is Skeleton: %1$s\n"), ((driver->flags & MACHINE_IS_SKELETON) ? _("Yes") : _("No"))); - util::stream_format(str, _("Game is Mechanical: %1$s\n"), ((driver->flags & MACHINE_MECHANICAL) ? _("Yes") : _("No"))); - util::stream_format(str, _("Requires Artwork: %1$s\n"), ((driver->flags & MACHINE_REQUIRES_ARTWORK) ? _("Yes") : _("No"))); - util::stream_format(str, _("Requires Clickable Artwork: %1$s\n"), ((driver->flags & MACHINE_CLICKABLE_ARTWORK) ? _("Yes") : _("No"))); - util::stream_format(str, _("Support Cocktail: %1$s\n"), ((driver->flags & MACHINE_NO_COCKTAIL) ? _("Yes") : _("No"))); - util::stream_format(str, _("Driver is Bios: %1$s\n"), ((driver->flags & MACHINE_IS_BIOS_ROOT) ? _("Yes") : _("No"))); - util::stream_format(str, _("Support Save: %1$s\n"), ((driver->flags & MACHINE_SUPPORTS_SAVE) ? _("Yes") : _("No"))); + util::stream_format(str, _("Game is Mechanical: %1$s\n"), ((driver->flags & machine_flags::MECHANICAL) ? _("Yes") : _("No"))); + util::stream_format(str, _("Requires Artwork: %1$s\n"), ((driver->flags & machine_flags::REQUIRES_ARTWORK) ? _("Yes") : _("No"))); + util::stream_format(str, _("Requires Clickable Artwork: %1$s\n"), ((driver->flags & machine_flags::CLICKABLE_ARTWORK) ? _("Yes") : _("No"))); + util::stream_format(str, _("Support Cocktail: %1$s\n"), ((driver->flags & machine_flags::NO_COCKTAIL) ? _("Yes") : _("No"))); + util::stream_format(str, _("Driver is Bios: %1$s\n"), ((driver->flags & machine_flags::IS_BIOS_ROOT) ? _("Yes") : _("No"))); + util::stream_format(str, _("Support Save: %1$s\n"), ((driver->flags & machine_flags::SUPPORTS_SAVE) ? _("Yes") : _("No"))); util::stream_format(str, _("Screen Orientation: %1$s\n"), ((driver->flags & ORIENTATION_SWAP_XY) ? _("Vertical") : _("Horizontal"))); bool found = false; auto entries = rom_build_entries(driver->rom); @@ -1330,7 +1333,7 @@ void menu_select_game::init_sorted_list() const game_driver *driver = &driver_list::driver(x); if (driver == &GAME_NAME(___empty)) continue; - if (driver->flags & MACHINE_IS_BIOS_ROOT) + if (driver->flags & machine_flags::IS_BIOS_ROOT) m_isabios++; m_sortedlist.push_back(driver); diff --git a/src/frontend/mame/ui/selmenu.cpp b/src/frontend/mame/ui/selmenu.cpp index 62ae749a4ea..09e001a972c 100644 --- a/src/frontend/mame/ui/selmenu.cpp +++ b/src/frontend/mame/ui/selmenu.cpp @@ -645,34 +645,36 @@ void menu_select_launch::custom_render(void *selectedref, float top, float botto tempbuf[2] = _("Driver is parent"); // next line is overall driver status - if (driver->flags & MACHINE_NOT_WORKING) + if (driver->flags & machine_flags::NOT_WORKING) tempbuf[3] = _("Overall: NOT WORKING"); - else if (driver->flags & MACHINE_UNEMULATED_PROTECTION) + else if ((driver->type.unemulated_features() | driver->type.imperfect_features()) & device_t::feature::PROTECTION) tempbuf[3] = _("Overall: Unemulated Protection"); else tempbuf[3] = _("Overall: Working"); // next line is graphics, sound status - if (driver->flags & (MACHINE_IMPERFECT_GRAPHICS | MACHINE_WRONG_COLORS | MACHINE_IMPERFECT_COLORS)) + if (driver->type.unemulated_features() & device_t::feature::GRAPHICS) + tempbuf[4] = _("Graphics: Unimplemented, "); + else if ((driver->type.unemulated_features() | driver->type.imperfect_features()) & (device_t::feature::GRAPHICS | device_t::feature::PALETTE)) tempbuf[4] = _("Graphics: Imperfect, "); else tempbuf[4] = _("Graphics: OK, "); - if (driver->flags & MACHINE_NO_SOUND) + if (driver->flags & machine_flags::NO_SOUND_HW) + tempbuf[4].append(_("Sound: None")); + else if (driver->type.unemulated_features() & device_t::feature::SOUND) tempbuf[4].append(_("Sound: Unimplemented")); - else if (driver->flags & MACHINE_IMPERFECT_SOUND) + else if (driver->type.imperfect_features() & device_t::feature::SOUND) tempbuf[4].append(_("Sound: Imperfect")); else tempbuf[4].append(_("Sound: OK")); - color = UI_GREEN_COLOR; - - if ((driver->flags & (MACHINE_IMPERFECT_GRAPHICS | MACHINE_WRONG_COLORS | MACHINE_IMPERFECT_COLORS - | MACHINE_NO_SOUND | MACHINE_IMPERFECT_SOUND)) != 0) - color = UI_YELLOW_COLOR; - - if ((driver->flags & (MACHINE_NOT_WORKING | MACHINE_UNEMULATED_PROTECTION)) != 0) + if ((driver->flags & machine_flags::NOT_WORKING) || ((driver->type.unemulated_features() | driver->type.imperfect_features()) & device_t::feature::PROTECTION)) color = UI_RED_COLOR; + else if (driver->type.unemulated_features() || driver->type.imperfect_features()) + color = UI_YELLOW_COLOR; + else + color = UI_GREEN_COLOR; } else { @@ -1020,7 +1022,7 @@ float menu_select_launch::draw_icon(int linenum, void *selectedref, float x0, fl if (cloneof) { auto cx = driver_list::find(driver->parent); - if (cx != -1 && ((driver_list::driver(cx).flags & MACHINE_IS_BIOS_ROOT) != 0)) + if ((cx >= 0) && (driver_list::driver(cx).flags & machine_flags::IS_BIOS_ROOT)) cloneof = false; } @@ -2021,7 +2023,7 @@ void menu_select_launch::arts_render(float origx1, float origy1, float origx2, f m_cache->set_snapx_software(nullptr); if (ui_globals::default_image) - ui_globals::curimage_view = ((driver->flags & MACHINE_TYPE_ARCADE) == 0) ? CABINETS_VIEW : SNAPSHOT_VIEW; + ui_globals::curimage_view = ((driver->flags & machine_flags::MASK_TYPE) != machine_flags::TYPE_ARCADE) ? CABINETS_VIEW : SNAPSHOT_VIEW; std::string const searchstr = arts_render_common(origx1, origy1, origx2, origy2); @@ -2061,7 +2063,7 @@ void menu_select_launch::arts_render(float origx1, float origy1, float origx2, f if (cloneof) { int cx = driver_list::find(driver->parent); - if (cx != -1 && ((driver_list::driver(cx).flags & MACHINE_IS_BIOS_ROOT) != 0)) + if ((cx >= 0) && (driver_list::driver(cx).flags & machine_flags::IS_BIOS_ROOT)) cloneof = false; } diff --git a/src/frontend/mame/ui/simpleselgame.cpp b/src/frontend/mame/ui/simpleselgame.cpp index 956594c52f7..62d9c58ac91 100644 --- a/src/frontend/mame/ui/simpleselgame.cpp +++ b/src/frontend/mame/ui/simpleselgame.cpp @@ -220,7 +220,7 @@ void simple_menu_select_game::populate(float &customtop, float &custombottom) int curitem; for (curitem = matchcount = 0; m_driverlist[curitem] != nullptr && matchcount < VISIBLE_GAMES_IN_LIST; curitem++) - if (!(m_driverlist[curitem]->flags & MACHINE_NO_STANDALONE)) + if (!(m_driverlist[curitem]->flags & machine_flags::NO_STANDALONE)) matchcount++; // if nothing there, add a single multiline item and return @@ -326,22 +326,26 @@ void simple_menu_select_game::custom_render(void *selectedref, float top, float tempbuf[2] = string_format(_("Driver: %1$-.100s"), core_filename_extract_base(driver->type.source())); // next line is overall driver status - if (driver->flags & MACHINE_NOT_WORKING) - tempbuf[3].assign(_("Overall: NOT WORKING")); - else if (driver->flags & MACHINE_UNEMULATED_PROTECTION) - tempbuf[3].assign(_("Overall: Unemulated Protection")); + if (driver->flags & machine_flags::NOT_WORKING) + tempbuf[3] = _("Overall: NOT WORKING"); + else if ((driver->type.unemulated_features() | driver->type.imperfect_features()) & device_t::feature::PROTECTION) + tempbuf[3] = _("Overall: Unemulated Protection"); else - tempbuf[3].assign(_("Overall: Working")); + tempbuf[3] = _("Overall: Working"); // next line is graphics, sound status - if (driver->flags & (MACHINE_IMPERFECT_GRAPHICS | MACHINE_WRONG_COLORS | MACHINE_IMPERFECT_COLORS)) + if (driver->type.unemulated_features() & device_t::feature::GRAPHICS) + gfxstat = _("Unimplemented"); + else if ((driver->type.unemulated_features() | driver->type.imperfect_features()) & (device_t::feature::GRAPHICS | device_t::feature::PALETTE)) gfxstat = _("Imperfect"); else gfxstat = _("OK"); - if (driver->flags & MACHINE_NO_SOUND) + if (driver->flags & machine_flags::NO_SOUND_HW) + soundstat = _("None"); + else if (driver->type.unemulated_features() & device_t::feature::SOUND) soundstat = _("Unimplemented"); - else if (driver->flags & MACHINE_IMPERFECT_SOUND) + else if (driver->type.imperfect_features() & device_t::feature::SOUND) soundstat = _("Imperfect"); else soundstat = _("OK"); @@ -390,13 +394,14 @@ void simple_menu_select_game::custom_render(void *selectedref, float top, float y2 = origy2 + bottom; // draw a box - color = UI_BACKGROUND_COLOR; - if (driver != nullptr) - color = UI_GREEN_COLOR; - if (driver != nullptr && (driver->flags & (MACHINE_IMPERFECT_GRAPHICS | MACHINE_WRONG_COLORS | MACHINE_IMPERFECT_COLORS | MACHINE_NO_SOUND | MACHINE_IMPERFECT_SOUND)) != 0) - color = UI_YELLOW_COLOR; - if (driver != nullptr && (driver->flags & (MACHINE_NOT_WORKING | MACHINE_UNEMULATED_PROTECTION)) != 0) + if (!driver) + color = UI_BACKGROUND_COLOR; + else if ((driver->flags & machine_flags::NOT_WORKING) || ((driver->type.unemulated_features() | driver->type.imperfect_features()) & device_t::feature::PROTECTION)) color = UI_RED_COLOR; + else if (driver->type.unemulated_features() || driver->type.imperfect_features()) + color = UI_YELLOW_COLOR; + else + color = UI_GREEN_COLOR; ui().draw_outlined_box(container(), x1, y1, x2, y2, color); // take off the borders diff --git a/src/frontend/mame/ui/ui.cpp b/src/frontend/mame/ui/ui.cpp index b98922ab193..28708a1d041 100644 --- a/src/frontend/mame/ui/ui.cpp +++ b/src/frontend/mame/ui/ui.cpp @@ -202,7 +202,7 @@ void mame_ui_manager::init() using namespace std::placeholders; set_handler(ui_callback_type::GENERAL, std::bind(&mame_ui_manager::handler_messagebox, this, _1)); m_non_char_keys_down = std::make_unique<uint8_t[]>((ARRAY_LENGTH(non_char_keys) + 7) / 8); - m_mouse_show = machine().system().flags & MACHINE_CLICKABLE_ARTWORK ? true : false; + m_mouse_show = machine().system().flags & machine_flags::CLICKABLE_ARTWORK ? true : false; // request a callback upon exiting machine().add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(&mame_ui_manager::exit, this)); @@ -289,22 +289,21 @@ void mame_ui_manager::display_startup_screens(bool first_time) int str = machine().options().seconds_to_run(); bool show_gameinfo = !machine().options().skip_gameinfo(); bool show_warnings = true, show_mandatory_fileman = true; - int state; // disable everything if we are using -str for 300 or fewer seconds, or if we're the empty driver, // or if we are debugging if (!first_time || (str > 0 && str < 60*5) || &machine().system() == &GAME_NAME(___empty) || (machine().debug_flags & DEBUG_FLAG_ENABLED) != 0) show_gameinfo = show_warnings = show_mandatory_fileman = false; - #if defined(EMSCRIPTEN) +#if defined(EMSCRIPTEN) // also disable for the JavaScript port since the startup screens do not run asynchronously show_gameinfo = show_warnings = false; - #endif +#endif // loop over states using namespace std::placeholders; set_handler(ui_callback_type::GENERAL, std::bind(&mame_ui_manager::handler_ingame, this, _1)); - for (state = 0; state < maxstate && !machine().scheduled_event_pending() && !ui::menu::stack_has_special_main_menu(machine()); state++) + for (int state = 0; state < maxstate && !machine().scheduled_event_pending() && !ui::menu::stack_has_special_main_menu(machine()); state++) { // default to standard colors messagebox_backcolor = UI_BACKGROUND_COLOR; @@ -313,36 +312,32 @@ void mame_ui_manager::display_startup_screens(bool first_time) // pick the next state switch (state) { - case 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)); - // TODO: don't think BTANB should be marked yellow? Also move this snippet to specific getter - if (machine().system().flags & (MACHINE_WARNING_FLAGS|MACHINE_BTANB_FLAGS)) - messagebox_backcolor = UI_YELLOW_COLOR; - if (machine().system().flags & (MACHINE_FATAL_FLAGS)) - messagebox_backcolor = UI_RED_COLOR; - } - break; - - case 1: - 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) - messagebox_text = machine_info().mandatory_images(); - if (!messagebox_text.empty()) - { - std::string warning = std::string(_("This driver requires images to be loaded in the following device(s): ")) + messagebox_text; - ui::menu_file_manager::force_file_manager(*this, machine().render().ui_container(), warning.c_str()); - } - break; + case 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)); + messagebox_backcolor = machine_info().warnings_color(); + } + break; + + case 1: + 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) + messagebox_text = machine_info().mandatory_images(); + if (!messagebox_text.empty()) + { + std::string warning = std::string(_("This driver requires images to be loaded in the following device(s): ")) + messagebox_text; + ui::menu_file_manager::force_file_manager(*this, machine().render().ui_container(), warning.c_str()); + } + break; } // clear the input memory diff --git a/src/frontend/mame/ui/ui.h b/src/frontend/mame/ui/ui.h index ce83bb692cc..02695a56bf3 100644 --- a/src/frontend/mame/ui/ui.h +++ b/src/frontend/mame/ui/ui.h @@ -161,7 +161,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; } + ui::machine_info &machine_info() const { assert(m_machine_info); return *m_machine_info; } // setters void set_single_step(bool single_step) { m_single_step = single_step; } diff --git a/src/frontend/mame/ui/viewgfx.cpp b/src/frontend/mame/ui/viewgfx.cpp index b6e5c53665b..d1734b172af 100644 --- a/src/frontend/mame/ui/viewgfx.cpp +++ b/src/frontend/mame/ui/viewgfx.cpp @@ -140,7 +140,7 @@ static void tilemap_handler(mame_ui_manager &mui, render_container &container, u void ui_gfx_init(running_machine &machine) { ui_gfx_state *state = &ui_gfx; - uint8_t rotate = machine.system().flags & ORIENTATION_MASK; + uint8_t rotate = machine.system().flags & machine_flags::MASK_ORIENTATION; // make sure we clean up after ourselves machine.add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(&ui_gfx_exit, &machine)); diff --git a/src/mame/drivers/rm380z.cpp b/src/mame/drivers/rm380z.cpp index 2f1b05730ac..3263d9f6c86 100644 --- a/src/mame/drivers/rm380z.cpp +++ b/src/mame/drivers/rm380z.cpp @@ -347,8 +347,8 @@ ROM_END /* Driver */ // YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS COMP(1978, rm380z, 0, 0, rm380z, rm380z, rm380z_state, rm380z, "Research Machines", "RM-380Z, COS 4.0B", MACHINE_NO_SOUND_HW) -COMP(1978, rm380z34d, rm380z, 0, rm380z, rm380z, rm380z_state, rm380z34d, "Research Machines", "RM-380Z, COS 3.4D", MACHINE_BTANB_FLAGS) -COMP(1978, rm380z34e, rm380z, 0, rm380z, rm380z, rm380z_state, rm380z34e, "Research Machines", "RM-380Z, COS 3.4E", MACHINE_BTANB_FLAGS) +COMP(1978, rm380z34d, rm380z, 0, rm380z, rm380z, rm380z_state, rm380z34d, "Research Machines", "RM-380Z, COS 3.4D", MACHINE_NO_SOUND_HW) +COMP(1978, rm380z34e, rm380z, 0, rm380z, rm380z, rm380z_state, rm380z34e, "Research Machines", "RM-380Z, COS 3.4E", MACHINE_NO_SOUND_HW) COMP(1981, rm480z, rm380z, 0, rm480z, rm380z, rm380z_state, rm380z34e, "Research Machines", "LINK RM-480Z (set 1)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND) COMP(1981, rm480za, rm380z, 0, rm480z, rm380z, rm380z_state, rm380z34e, "Research Machines", "LINK RM-480Z (set 2)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND) |