1 // license:BSD-3-Clause
2 // copyright-holders:Aaron Giles
3 /***************************************************************************
4 
5     gamedrv.h
6 
7     Definitions for game drivers.
8 
9 ***************************************************************************/
10 
11 #ifndef MAME_EMU_GAMEDRV_H
12 #define MAME_EMU_GAMEDRV_H
13 
14 #pragma once
15 
16 #include <type_traits>
17 
18 
19 //**************************************************************************
20 //  CONSTANTS
21 //**************************************************************************
22 
23 // maxima
24 constexpr int MAX_DRIVER_NAME_CHARS = 16;
25 
26 struct machine_flags
27 {
28 	enum type : u32
29 	{
30 		MASK_ORIENTATION    = 0x00000007,
31 		MASK_TYPE           = 0x00000038,
32 
33 		FLIP_X              = 0x00000001,
34 		FLIP_Y              = 0x00000002,
35 		SWAP_XY             = 0x00000004,
36 		ROT0                = 0x00000000,
37 		ROT90               = FLIP_X | SWAP_XY,
38 		ROT180              = FLIP_X | FLIP_Y,
39 		ROT270              = FLIP_Y | SWAP_XY,
40 
41 		TYPE_ARCADE         = 0x00000008,   // coin-operated machine for public use
42 		TYPE_CONSOLE        = 0x00000010,   // console system
43 		TYPE_COMPUTER       = 0x00000018,   // any kind of computer including home computers, minis, calculators, ...
44 		TYPE_OTHER          = 0x00000038,   // any other emulated system (e.g. clock, satellite receiver, ...)
45 
46 		NOT_WORKING         = 0x00000040,
47 		SUPPORTS_SAVE       = 0x00000080,   // system supports save states
48 		NO_COCKTAIL         = 0x00000100,   // screen flip support is missing
49 		IS_BIOS_ROOT        = 0x00000200,   // this driver entry is a BIOS root
50 		REQUIRES_ARTWORK    = 0x00000400,   // requires external artwork for key game elements
51 		CLICKABLE_ARTWORK   = 0x00000800,   // artwork is clickable and requires mouse cursor
52 		UNOFFICIAL          = 0x00001000,   // unofficial hardware modification
53 		NO_SOUND_HW         = 0x00002000,   // system has no sound output
54 		MECHANICAL          = 0x00004000,   // contains mechanical parts (pinball, redemption games, ...)
55 		IS_INCOMPLETE       = 0x00008000    // official system with blatantly incomplete hardware/software
56 	};
57 };
58 
59 DECLARE_ENUM_BITWISE_OPERATORS(machine_flags::type);
60 
61 
62 // flags for machine drivers
63 constexpr u64 MACHINE_TYPE_ARCADE               = machine_flags::TYPE_ARCADE;
64 constexpr u64 MACHINE_TYPE_CONSOLE              = machine_flags::TYPE_CONSOLE;
65 constexpr u64 MACHINE_TYPE_COMPUTER             = machine_flags::TYPE_COMPUTER;
66 constexpr u64 MACHINE_TYPE_OTHER                = machine_flags::TYPE_OTHER;
67 constexpr u64 MACHINE_NOT_WORKING               = machine_flags::NOT_WORKING;
68 constexpr u64 MACHINE_SUPPORTS_SAVE             = machine_flags::SUPPORTS_SAVE;
69 constexpr u64 MACHINE_NO_COCKTAIL               = machine_flags::NO_COCKTAIL;
70 constexpr u64 MACHINE_IS_BIOS_ROOT              = machine_flags::IS_BIOS_ROOT;
71 constexpr u64 MACHINE_REQUIRES_ARTWORK          = machine_flags::REQUIRES_ARTWORK;
72 constexpr u64 MACHINE_CLICKABLE_ARTWORK         = machine_flags::CLICKABLE_ARTWORK;
73 constexpr u64 MACHINE_UNOFFICIAL                = machine_flags::UNOFFICIAL;
74 constexpr u64 MACHINE_NO_SOUND_HW               = machine_flags::NO_SOUND_HW;
75 constexpr u64 MACHINE_MECHANICAL                = machine_flags::MECHANICAL;
76 constexpr u64 MACHINE_IS_INCOMPLETE             = machine_flags::IS_INCOMPLETE;
77 
78 // flags that map to device feature flags
79 constexpr u64 MACHINE_UNEMULATED_PROTECTION     = 0x00000001'00000000;   // game's protection not fully emulated
80 constexpr u64 MACHINE_WRONG_COLORS              = 0x00000002'00000000;   // colors are totally wrong
81 constexpr u64 MACHINE_IMPERFECT_COLORS          = 0x00000004'00000000;   // colors are not 100% accurate, but close
82 constexpr u64 MACHINE_IMPERFECT_GRAPHICS        = 0x00000008'00000000;   // graphics are wrong/incomplete
83 constexpr u64 MACHINE_NO_SOUND                  = 0x00000010'00000000;   // sound is missing
84 constexpr u64 MACHINE_IMPERFECT_SOUND           = 0x00000020'00000000;   // sound is known to be wrong
85 constexpr u64 MACHINE_IMPERFECT_CONTROLS        = 0x00000040'00000000;   // controls are known to be imperfectly emulated
86 constexpr u64 MACHINE_NODEVICE_MICROPHONE       = 0x00000080'00000000;   // any game/system that has unemulated audio capture device
87 constexpr u64 MACHINE_NODEVICE_PRINTER          = 0x00000100'00000000;   // any game/system that has unemulated hardcopy output device
88 constexpr u64 MACHINE_NODEVICE_LAN              = 0x00000200'00000000;   // any game/system that has unemulated local networking
89 constexpr u64 MACHINE_IMPERFECT_TIMING          = 0x00000400'00000000;   // timing is known to be imperfectly emulated
90 
91 // useful combinations of flags
92 constexpr u64 MACHINE_IS_SKELETON               = MACHINE_NO_SOUND | MACHINE_NOT_WORKING; // flag combination for skeleton drivers
93 constexpr u64 MACHINE_IS_SKELETON_MECHANICAL    = MACHINE_IS_SKELETON | MACHINE_MECHANICAL | MACHINE_REQUIRES_ARTWORK; // flag combination for skeleton mechanical machines
94 
95 
96 //**************************************************************************
97 //  TYPE DEFINITIONS
98 //**************************************************************************
99 
100 // static POD structure describing each game driver entry
101 class game_driver
102 {
103 public:
104 	typedef void (*machine_creator_wrapper)(machine_config &, device_t &);
105 	typedef void (*driver_init_wrapper)(device_t &);
106 
unemulated_features(u64 flags)107 	static constexpr device_t::feature_type unemulated_features(u64 flags)
108 	{
109 		return
110 				((flags & MACHINE_WRONG_COLORS)             ? device_t::feature::PALETTE    : device_t::feature::NONE) |
111 				((flags & MACHINE_NO_SOUND)                 ? device_t::feature::SOUND      : device_t::feature::NONE) |
112 				((flags & MACHINE_NODEVICE_MICROPHONE)      ? device_t::feature::MICROPHONE : device_t::feature::NONE) |
113 				((flags & MACHINE_NODEVICE_PRINTER)         ? device_t::feature::PRINTER    : device_t::feature::NONE) |
114 				((flags & MACHINE_NODEVICE_LAN)             ? device_t::feature::LAN        : device_t::feature::NONE);
115 	}
116 
imperfect_features(u64 flags)117 	static constexpr device_t::feature_type imperfect_features(u64 flags)
118 	{
119 		return
120 				((flags & MACHINE_UNEMULATED_PROTECTION)    ? device_t::feature::PROTECTION : device_t::feature::NONE) |
121 				((flags & MACHINE_IMPERFECT_COLORS)         ? device_t::feature::PALETTE    : device_t::feature::NONE) |
122 				((flags & MACHINE_IMPERFECT_GRAPHICS)       ? device_t::feature::GRAPHICS   : device_t::feature::NONE) |
123 				((flags & MACHINE_IMPERFECT_SOUND)          ? device_t::feature::SOUND      : device_t::feature::NONE) |
124 				((flags & MACHINE_IMPERFECT_CONTROLS)       ? device_t::feature::CONTROLS   : device_t::feature::NONE) |
125 				((flags & MACHINE_IMPERFECT_TIMING)         ? device_t::feature::TIMING     : device_t::feature::NONE);
126 	}
127 
128 	device_type                 type;               // static type info for driver class
129 	const char *                parent;             // if this is a clone, the name of the parent
130 	const char *                year;               // year the game was released
131 	const char *                manufacturer;       // manufacturer of the game
132 	machine_creator_wrapper     machine_creator;    // machine driver tokens
133 	ioport_constructor          ipt;                // pointer to constructor for input ports
134 	driver_init_wrapper         driver_init;        // DRIVER_INIT callback
135 	const tiny_rom_entry *      rom;                // pointer to list of ROMs for the game
136 	const char *                compatible_with;
137 	const internal_layout *     default_layout;     // default internally defined layout
138 	machine_flags::type         flags;              // orientation and other flags; see defines above
139 	char                        name[MAX_DRIVER_NAME_CHARS + 1]; // short name of the game
140 };
141 
142 
143 //**************************************************************************
144 //  MACROS
145 //**************************************************************************
146 
147 // wrappers for declaring and defining game drivers
148 #define GAME_NAME(name)         driver_##name
149 #define GAME_TRAITS_NAME(name)  driver_##name##traits
150 #define GAME_EXTERN(name)       extern game_driver const GAME_NAME(name)
151 
152 // static game traits
153 #define GAME_DRIVER_TRAITS(NAME, FULLNAME) \
154 namespace { \
155 	struct GAME_TRAITS_NAME(NAME) { static constexpr char const shortname[] = #NAME, fullname[] = FULLNAME, source[] = __FILE__; }; \
156 	constexpr char const GAME_TRAITS_NAME(NAME)::shortname[], GAME_TRAITS_NAME(NAME)::fullname[], GAME_TRAITS_NAME(NAME)::source[]; \
157 }
158 #define GAME_DRIVER_TYPE(NAME, CLASS, FLAGS) \
159 driver_device_creator< \
160 		CLASS, \
161 		(GAME_TRAITS_NAME(NAME)::shortname), \
162 		(GAME_TRAITS_NAME(NAME)::fullname), \
163 		(GAME_TRAITS_NAME(NAME)::source), \
164 		game_driver::unemulated_features(FLAGS), \
165 		game_driver::imperfect_features(FLAGS)>
166 
167 // standard GAME() macro
168 #define GAME(YEAR,NAME,PARENT,MACHINE,INPUT,CLASS,INIT,MONITOR,COMPANY,FULLNAME,FLAGS) \
169 GAME_DRIVER_TRAITS(NAME,FULLNAME)                                       \
170 extern game_driver const GAME_NAME(NAME)                                \
171 {                                                                       \
172 	GAME_DRIVER_TYPE(NAME, CLASS, FLAGS),                               \
173 	#PARENT,                                                            \
174 	#YEAR,                                                              \
175 	COMPANY,                                                            \
176 	[] (machine_config &config, device_t &owner) { downcast<CLASS &>(owner).MACHINE(config); }, \
177 	INPUT_PORTS_NAME(INPUT),                                            \
178 	[] (device_t &owner) { downcast<CLASS &>(owner).INIT(); },          \
179 	ROM_NAME(NAME),                                                     \
180 	nullptr,                                                            \
181 	nullptr,                                                            \
182 	machine_flags::type(u32((MONITOR) | (FLAGS) | MACHINE_TYPE_ARCADE)),\
183 	#NAME                                                               \
184 };
185 
186 // standard macro with additional layout
187 #define GAMEL(YEAR,NAME,PARENT,MACHINE,INPUT,CLASS,INIT,MONITOR,COMPANY,FULLNAME,FLAGS,LAYOUT) \
188 GAME_DRIVER_TRAITS(NAME,FULLNAME)                                       \
189 extern game_driver const GAME_NAME(NAME)                                \
190 {                                                                       \
191 	GAME_DRIVER_TYPE(NAME, CLASS, FLAGS),                               \
192 	#PARENT,                                                            \
193 	#YEAR,                                                              \
194 	COMPANY,                                                            \
195 	[] (machine_config &config, device_t &owner) { downcast<CLASS &>(owner).MACHINE(config); }, \
196 	INPUT_PORTS_NAME(INPUT),                                            \
197 	[] (device_t &owner) { downcast<CLASS &>(owner).INIT(); },          \
198 	ROM_NAME(NAME),                                                     \
199 	nullptr,                                                            \
200 	&LAYOUT,                                                            \
201 	machine_flags::type(u32((MONITOR) | (FLAGS) | MACHINE_TYPE_ARCADE)),\
202 	#NAME                                                               \
203 };
204 
205 
206 // standard console definition macro
207 #define CONS(YEAR,NAME,PARENT,COMPAT,MACHINE,INPUT,CLASS,INIT,COMPANY,FULLNAME,FLAGS) \
208 GAME_DRIVER_TRAITS(NAME,FULLNAME)                                       \
209 extern game_driver const GAME_NAME(NAME)                                \
210 {                                                                       \
211 	GAME_DRIVER_TYPE(NAME, CLASS, FLAGS),                               \
212 	#PARENT,                                                            \
213 	#YEAR,                                                              \
214 	COMPANY,                                                            \
215 	[] (machine_config &config, device_t &owner) { downcast<CLASS &>(owner).MACHINE(config); }, \
216 	INPUT_PORTS_NAME(INPUT),                                            \
217 	[] (device_t &owner) { downcast<CLASS &>(owner).INIT(); },          \
218 	ROM_NAME(NAME),                                                     \
219 	#COMPAT,                                                            \
220 	nullptr,                                                            \
221 	machine_flags::type(u32(ROT0 | (FLAGS) | MACHINE_TYPE_CONSOLE)),    \
222 	#NAME                                                               \
223 };
224 
225 // standard computer definition macro
226 #define COMP(YEAR,NAME,PARENT,COMPAT,MACHINE,INPUT,CLASS,INIT,COMPANY,FULLNAME,FLAGS) \
227 GAME_DRIVER_TRAITS(NAME,FULLNAME)                                       \
228 extern game_driver const GAME_NAME(NAME)                                \
229 {                                                                       \
230 	GAME_DRIVER_TYPE(NAME, CLASS, FLAGS),                               \
231 	#PARENT,                                                            \
232 	#YEAR,                                                              \
233 	COMPANY,                                                            \
234 	[] (machine_config &config, device_t &owner) { downcast<CLASS &>(owner).MACHINE(config); }, \
235 	INPUT_PORTS_NAME(INPUT),                                            \
236 	[] (device_t &owner) { downcast<CLASS &>(owner).INIT(); },          \
237 	ROM_NAME(NAME),                                                     \
238 	#COMPAT,                                                            \
239 	nullptr,                                                            \
240 	machine_flags::type(u32(ROT0 | (FLAGS) | MACHINE_TYPE_COMPUTER)),   \
241 	#NAME                                                               \
242 };
243 
244 // standard system definition macro
245 #define SYST(YEAR,NAME,PARENT,COMPAT,MACHINE,INPUT,CLASS,INIT,COMPANY,FULLNAME,FLAGS) \
246 GAME_DRIVER_TRAITS(NAME,FULLNAME)                                       \
247 extern game_driver const GAME_NAME(NAME)                                \
248 {                                                                       \
249 	GAME_DRIVER_TYPE(NAME, CLASS, FLAGS),                               \
250 	#PARENT,                                                            \
251 	#YEAR,                                                              \
252 	COMPANY,                                                            \
253 	[] (machine_config &config, device_t &owner) { downcast<CLASS &>(owner).MACHINE(config); }, \
254 	INPUT_PORTS_NAME(INPUT),                                            \
255 	[] (device_t &owner) { downcast<CLASS &>(owner).INIT(); },          \
256 	ROM_NAME(NAME),                                                     \
257 	#COMPAT,                                                            \
258 	nullptr,                                                            \
259 	machine_flags::type(u32(ROT0 | (FLAGS) | MACHINE_TYPE_OTHER)),      \
260 	#NAME                                                               \
261 };
262 
263 
264 #endif // MAME_EMU_GAMEDRV_H
265