summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/gamedrv.h
blob: 9f454923f17eca1b5cd968903f6dcd753c03e149 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
// license:BSD-3-Clause
// copyright-holders:Aaron Giles
/***************************************************************************

    gamedrv.h

    Definitions for game drivers.

***************************************************************************/

#ifndef MAME_EMU_GAMEDRV_H
#define MAME_EMU_GAMEDRV_H

#pragma once

#include <type_traits>


/// \defgroup machinedef Machine definition macros


//**************************************************************************
//  CONSTANTS
//**************************************************************************

// maxima
constexpr int MAX_DRIVER_NAME_CHARS = 16;

struct machine_flags
{
	enum type : u32
	{
		MASK_ORIENTATION    = 0x0000'0007,

		FLIP_X              = 0x0000'0001,
		FLIP_Y              = 0x0000'0002,
		SWAP_XY             = 0x0000'0004,
		ROT0                = 0x0000'0000,
		ROT90               = FLIP_X | SWAP_XY,
		ROT180              = FLIP_X | FLIP_Y,
		ROT270              = FLIP_Y | SWAP_XY,

		NOT_WORKING         = 0x0000'0040,
		SUPPORTS_SAVE       = 0x0000'0080,  // system supports save states
		NO_COCKTAIL         = 0x0000'0100,  // screen flip support is missing
		IS_BIOS_ROOT        = 0x0000'0200,  // this driver entry is a BIOS root
		REQUIRES_ARTWORK    = 0x0000'0400,  // requires external artwork for key game elements
		UNOFFICIAL          = 0x0000'0800,  // unofficial hardware modification
		NO_SOUND_HW         = 0x0000'1000,  // system has no sound output
		MECHANICAL          = 0x0000'2000,  // contains mechanical parts (pinball, redemption games, ...)
		IS_INCOMPLETE       = 0x0000'4000   // official system with blatantly incomplete hardware/software
	};
};

DECLARE_ENUM_BITWISE_OPERATORS(machine_flags::type);


/// \addtogroup machinedef
/// \{
/// \name System emulation status constants
///
/// Constants representing system emulation status flags.  May be
/// combined for use as FLAGS arguments to the #GAME, #GAMEL, #CONS,
/// #COMP and #SYST macros.
/// \{

// flags for machine drivers
constexpr u64 MACHINE_NOT_WORKING               = machine_flags::NOT_WORKING;               ///< Imperfect emulation prevents using the system as intended
constexpr u64 MACHINE_SUPPORTS_SAVE             = machine_flags::SUPPORTS_SAVE;             ///< All devices in the system supports save states (enables auto save feature, and won't show a warning on using save states)
constexpr u64 MACHINE_NO_COCKTAIL               = machine_flags::NO_COCKTAIL;               ///< The system supports screen flipping for use in a cocktail cabinet, but this feature is not properly emulated
constexpr u64 MACHINE_IS_BIOS_ROOT              = machine_flags::IS_BIOS_ROOT;              ///< The system represents an empty system board of some kind - clones are treated as separate systems rather than variants
constexpr u64 MACHINE_REQUIRES_ARTWORK          = machine_flags::REQUIRES_ARTWORK;          ///< The system requires external artwork for key functionality
constexpr u64 MACHINE_UNOFFICIAL                = machine_flags::UNOFFICIAL;                ///< The system represents an after-market or end-user modification to a system
constexpr u64 MACHINE_NO_SOUND_HW               = machine_flags::NO_SOUND_HW;               ///< The system has no sound output capability
constexpr u64 MACHINE_MECHANICAL                = machine_flags::MECHANICAL;                ///< The system depends on mechanical features for key functionality
constexpr u64 MACHINE_IS_INCOMPLETE             = machine_flags::IS_INCOMPLETE;             ///< The system represents an incomplete prototype

// flags that map to device feature flags
constexpr u64 MACHINE_UNEMULATED_PROTECTION     = 0x00000001'00000000;                      ///< Some form of protection is imperfectly emulated (e.g. copy protection or anti-tampering)
constexpr u64 MACHINE_WRONG_COLORS              = 0x00000002'00000000;                      ///< Colours are completely wrong
constexpr u64 MACHINE_IMPERFECT_COLORS          = 0x00000004'00000000;                      ///< Colours are close but not completely accurate
constexpr u64 MACHINE_IMPERFECT_GRAPHICS        = 0x00000008'00000000;                      ///< Graphics are emulated incorrectly for the system
constexpr u64 MACHINE_NO_SOUND                  = 0x00000010'00000000;                      ///< The system has sound output, but it is not emulated
constexpr u64 MACHINE_IMPERFECT_SOUND           = 0x00000020'00000000;                      ///< Sound is known to be imperfectly emulated for the system
constexpr u64 MACHINE_IMPERFECT_CONTROLS        = 0x00000040'00000000;                      ///< Controls or inputs are emulated imperfectly for the system
constexpr u64 MACHINE_NODEVICE_MICROPHONE       = 0x00000080'00000000;                      ///< The system has unemulated audio capture functionality
constexpr u64 MACHINE_NODEVICE_PRINTER          = 0x00000100'00000000;                      ///< The system has unemulated printer functionality
constexpr u64 MACHINE_NODEVICE_LAN              = 0x00000200'00000000;                      ///< The system has unemulated local area networking
constexpr u64 MACHINE_IMPERFECT_TIMING          = 0x00000400'00000000;                      ///< Timing is known to be imperfectly emulated for the system

/// \}
/// \}


//**************************************************************************
//  TYPE DEFINITIONS
//**************************************************************************

/// \brief Static system description
///
/// A plain data structure providing static information about a system.
/// Used to allow multiple systems to be implemented using a single
/// system device class (an implementation of #driver_device).
class game_driver
{
public:
	typedef void (*machine_creator_wrapper)(machine_config &, device_t &);
	typedef void (*driver_init_wrapper)(device_t &);

	/// \brief Get unemulated system features
	///
	/// Converts system flags corresponding to unemulated device
	/// features to a device feature type bit field.
	/// \param [in] flags A system flags bit field.
	/// \return A device feature type bit field corresponding to
	///   unemulated features declared in the \p flags argument.
	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_PRINTER)         ? device_t::feature::PRINTER    : device_t::feature::NONE) |
				((flags & MACHINE_NODEVICE_LAN)             ? device_t::feature::LAN        : device_t::feature::NONE);
	}

	/// \brief Get imperfectly emulated system features
	///
	/// Converts system flags corresponding to imperfectly emulated
	/// device features to a device feature type bit field.
	/// \param [in] flags A system flags bit field.
	/// \return A device feature type bit field corresponding to
	///   imperfectly emulated features declared in the \p flags
	///   argument.
	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_CONTROLS)       ? device_t::feature::CONTROLS   : device_t::feature::NONE) |
				((flags & MACHINE_IMPERFECT_TIMING)         ? device_t::feature::TIMING     : device_t::feature::NONE);
	}

	device_type                 type;               // static type info for driver class
	const char *                parent;             // name of the parent or BIOS system if applicable
	const char *                year;               // year the game was released
	const char *                manufacturer;       // manufacturer of the game
	machine_creator_wrapper     machine_creator;    // machine driver tokens
	ioport_constructor          ipt;                // pointer to constructor for input ports
	driver_init_wrapper         driver_init;        // DRIVER_INIT callback
	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
	machine_flags::type         flags;              // orientation and other flags; see defines above
	char                        name[MAX_DRIVER_NAME_CHARS + 1]; // short name of the system
};


//**************************************************************************
//  MACROS
//**************************************************************************

// wrappers for declaring and defining game drivers
#define GAME_NAME(name)         driver_##name
#define GAME_TRAITS_NAME(name)  driver_##name##traits
#define GAME_EXTERN(name)       extern game_driver const GAME_NAME(name)

// static game traits
#define GAME_DRIVER_TRAITS(NAME, FULLNAME) \
namespace { \
	struct GAME_TRAITS_NAME(NAME) { static constexpr char const shortname[] = #NAME, fullname[] = FULLNAME, source[] = __FILE__; }; \
	constexpr char const GAME_TRAITS_NAME(NAME)::shortname[], GAME_TRAITS_NAME(NAME)::fullname[], GAME_TRAITS_NAME(NAME)::source[]; \
}
#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)>


/// \addtogroup machinedef
/// \{

/// \brief Define a system
///
/// Must be used in the global namespace.
///
/// Creates an appropriately named and populated #game_driver structure
/// describing the system.
/// \param YEAR The year that the system was first made available.  Must
///   be a token containing only the digits zero to nine, question mark
///   and plus sign.
/// \param NAME The short name of the system, used for identification,
///   and in filesystem paths for assets and data.  Must be a token no
///   longer than sixteen characters, containing only ASCII lowercase
///   letters, digits and underscores.  Must be globally unique across
///   systems and devices.
/// \param PARENT Short name of the parent or BIOS system if applicable,
///   or a single digit zero otherwise.
/// \param MACHINE Function used to buid machine configuration for the
///   system.  Must be a public member function of the system device
///   class (\p CLASS argument), returning void and taking a reference
///   to a #machine_config object as a parameter.
/// \param INPUT Input port definitions for the root device of the
///   system, usually defined using #INPUT_PORTS_START and associated
///   macros.
/// \param CLASS Class to instantiate as the root device of the system.
///   Must be an implementation of #driver_device.
/// \param INIT Initialisation function called after all child devices
///   have started, but before the driver start functions are called.
///   Often used for tasks like decrypting ROMs.  Must be a public
///   member function of the system device class (\p CLASS argument),
///   returning void and accepting no parameters.  The function
///   #driver_device::empty_init is supplied for systems that don't need
///   to perform additional tasks.
/// \param MONITOR Screen orientation flags applied to all screens in
///   the system, after the individual screens' orientation flags are
///   applied.  Usually one #ROT0, #ROT90, #ROT180 or #ROT270.
/// \param COMPANY Name of the developer or distributor of the system.
///   Must be a string.
/// \param FULLNAME Display name for the system.  Must be a string, and
///   must be globally unique across systems and devices.
/// \param FLAGS Bitwise combination of emulation status flags for the
///   system, in addition to flags supplied by the system device class
///   (see #device_t::unemulated_features and
///   #device_t::imperfect_features).  It is advisable to supply
///   unemulated and imperfectly emulated feature flags that apply to
///   all systems implemented using the class in the class itself to
///   avoid repetition.
/// \sa GAMEL SYST
#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, FLAGS),                               \
	#PARENT,                                                            \
	#YEAR,                                                              \
	COMPANY,                                                            \
	[] (machine_config &config, device_t &owner) { downcast<CLASS &>(owner).MACHINE(config); }, \
	INPUT_PORTS_NAME(INPUT),                                            \
	[] (device_t &owner) { downcast<CLASS &>(owner).INIT(); },          \
	ROM_NAME(NAME),                                                     \
	nullptr,                                                            \
	nullptr,                                                            \
	machine_flags::type(u32((MONITOR) | (FLAGS))),                      \
	#NAME                                                               \
};


/// \brief Define a system with an additional internal layout
///
/// Equivalent to the #GAME macro, but with the additional ability to
/// supply a system-specific internal artwork layout.  Views from the
/// system-specific layout are available in addition to any views from
/// layouts specified in the machine configuration.  Must be used in the
/// global namespace.
///
/// Creates an appropriately named and populated #game_driver structure
/// describing the system.
/// \param YEAR The year that the system was first made available.  Must
///   be a token containing only the digits zero to nine, question mark
///   and plus sign.
/// \param NAME The short name of the system, used for identification,
///   and in filesystem paths for assets and data.  Must be a token no
///   longer than sixteen characters, containing only ASCII lowercase
///   letters, digits and underscores.  Must be globally unique across
///   systems and devices.
/// \param PARENT Short name of the parent or BIOS system if applicable,
///   or a single digit zero otherwise.
/// \param MACHINE Function used to buid machine configuration for the
///   system.  Must be a public member function of the system device
///   class (\p CLASS argument), returning void and taking a reference
///   to a #machine_config object as a parameter.
/// \param INPUT Input port definitions for the root device of the
///   system, usually defined using #INPUT_PORTS_START and associated
///   macros.
/// \param CLASS Class to instantiate as the root device of the system.
///   Must be an implementation of #driver_device.
/// \param INIT Initialisation function called after all child devices
///   have started, but before the driver start functions are called.
///   Often used for tasks like decrypting ROMs.  Must be a public
///   member function of the system device class (\p CLASS argument),
///   returning void and accepting no parameters.  The function
///   #driver_device::empty_init is supplied for systems that don't need
///   to perform additional tasks.
/// \param MONITOR Screen orientation flags applied to all screens in
///   the system, after the individual screens' orientation flags are
///   applied.  Usually one #ROT0, #ROT90, #ROT180 or #ROT270.
/// \param COMPANY Name of the developer or distributor of the system.
///   Must be a string.
/// \param FULLNAME Display name for the system.  Must be a string, and
///   must be globally unique across systems and devices.
/// \param FLAGS Bitwise combination of emulation status flags for the
///   system, in addition to flags supplied by the system device class
///   (see #device_t::unemulated_features and
///   #device_t::imperfect_features).  It is advisable to supply
///   unemulated and imperfectly emulated feature flags that apply to
///   all systems implemented using the class in the class itself to
///   avoid repetition.
/// \param LAYOUT An #internal_layout structure providing additional
///   internal artwork for the system.
/// \sa GAME SYST
#define GAMEL(YEAR, NAME, PARENT, MACHINE, INPUT, CLASS, INIT, MONITOR, COMPANY, FULLNAME, FLAGS, LAYOUT) \
GAME_DRIVER_TRAITS(NAME, FULLNAME)                                      \
extern game_driver const GAME_NAME(NAME)                                \
{                                                                       \
	GAME_DRIVER_TYPE(NAME, CLASS, FLAGS),                               \
	#PARENT,                                                            \
	#YEAR,                                                              \
	COMPANY,                                                            \
	[] (machine_config &config, device_t &owner) { downcast<CLASS &>(owner).MACHINE(config); }, \
	INPUT_PORTS_NAME(INPUT),                                            \
	[] (device_t &owner) { downcast<CLASS &>(owner).INIT(); },          \
	ROM_NAME(NAME),                                                     \
	nullptr,                                                            \
	&LAYOUT,                                                            \
	machine_flags::type(u32((MONITOR) | (FLAGS))),                      \
	#NAME                                                               \
};


/// \brief Define a system with software compatibility grouping
///
/// Equivalent to the #GAME macro, but allows software-compatible
/// systems to be grouped.
///
/// Creates an appropriately named and populated #game_driver structure
/// describing the system.
/// \param YEAR The year that the system was first made available.  Must
///   be a token containing only the digits zero to nine, question mark
///   and plus sign.
/// \param NAME The short name of the system, used for identification,
///   and in filesystem paths for assets and data.  Must be a token no
///   longer than sixteen characters, containing only ASCII lowercase
///   letters, digits and underscores.  Must be globally unique across
///   systems and devices.
/// \param PARENT Short name of the parent or BIOS system if applicable,
///   or a single digit zero otherwise.
/// \param COMPAT Short name of a system that this system is compatible
///   with if applicable, or a single digit zero otherwise.
/// \param MACHINE Function used to buid machine configuration for the
///   system.  Must be a public member function of the system device
///   class (\p CLASS argument), returning void and taking a reference
///   to a #machine_config object as a parameter.
/// \param INPUT Input port definitions for the root device of the
///   system, usually defined using #INPUT_PORTS_START and associated
///   macros.
/// \param CLASS Class to instantiate as the root device of the system.
///   Must be an implementation of #driver_device.
/// \param INIT Initialisation function called after all child devices
///   have started, but before the driver start functions are called.
///   Often used for tasks like decrypting ROMs.  Must be a public
///   member function of the system device class (\p CLASS argument),
///   returning void and accepting no parameters.  The function
///   #driver_device::empty_init is supplied for systems that don't need
///   to perform additional tasks.
/// \param COMPANY Name of the developer or distributor of the system.
///   Must be a string.
/// \param FULLNAME Display name for the system.  Must be a string, and
///   must be globally unique across systems and devices.
/// \param FLAGS Bitwise combination of emulation status flags for the
///   system, in addition to flags supplied by the system device class
///   (see #device_t::unemulated_features and
///   #device_t::imperfect_features).  It is advisable to supply
///   unemulated and imperfectly emulated feature flags that apply to
///   all systems implemented using the class in the class itself to
///   avoid repetition.  Screen orientation flags may be included here.
/// \sa GAME GAMEL
#define SYST(YEAR, NAME, PARENT, COMPAT, MACHINE, INPUT, CLASS, INIT, COMPANY, FULLNAME, FLAGS) \
		GAME_DRIVER_TRAITS(NAME, FULLNAME)                                      \
		extern game_driver const GAME_NAME(NAME)                                \
		{                                                                       \
			GAME_DRIVER_TYPE(NAME, CLASS, FLAGS),                               \
			#PARENT,                                                            \
			#YEAR,                                                              \
			COMPANY,                                                            \
			[] (machine_config &config, device_t &owner) { downcast<CLASS &>(owner).MACHINE(config); }, \
			INPUT_PORTS_NAME(INPUT),                                            \
			[] (device_t &owner) { downcast<CLASS &>(owner).INIT(); },          \
			ROM_NAME(NAME),                                                     \
			#COMPAT,                                                            \
			nullptr,                                                            \
			machine_flags::type(u32(ROT0 | (FLAGS))),                           \
			#NAME                                                               \
		};


#define CONS(YEAR, NAME, PARENT, COMPAT, MACHINE, INPUT, CLASS, INIT, COMPANY, FULLNAME, FLAGS) \
		SYST(YEAR, NAME, PARENT, COMPAT, MACHINE, INPUT, CLASS, INIT, COMPANY, FULLNAME, FLAGS)

#define COMP(YEAR, NAME, PARENT, COMPAT, MACHINE, INPUT, CLASS, INIT, COMPANY, FULLNAME, FLAGS) \
		SYST(YEAR, NAME, PARENT, COMPAT, MACHINE, INPUT, CLASS, INIT, COMPANY, FULLNAME, FLAGS)

/// \}

#endif // MAME_EMU_GAMEDRV_H